[PATCH 2/2] gdiplus: Fix resample offset for nearest neighbor interpolation.

Jan Havran havran.jan at email.cz
Sun Mar 24 09:48:36 CDT 2019


While PixelOffsetModeHighSpeed starts resampling from top left corner,
the PixelOffsetModeHighQuality uses half of step as an offset.

Signed-off-by: Jan Havran <havran.jan at email.cz>
---
 dlls/gdiplus/graphics.c | 21 ++++++++++++++-------
 1 file changed, 14 insertions(+), 7 deletions(-)

diff --git a/dlls/gdiplus/graphics.c b/dlls/gdiplus/graphics.c
index 82f0cc79f5..ec4cb6c69b 100644
--- a/dlls/gdiplus/graphics.c
+++ b/dlls/gdiplus/graphics.c
@@ -959,7 +959,7 @@ static ARGB sample_bitmap_pixel(GDIPCONST GpRect *src_rect, LPBYTE bits, UINT wi
 
 static ARGB resample_bitmap_pixel(GDIPCONST GpRect *src_rect, LPBYTE bits, UINT width,
     UINT height, GpPointF *point, GDIPCONST GpImageAttributes *attributes,
-    InterpolationMode interpolation, PixelOffsetMode offset_mode)
+    InterpolationMode interpolation, PixelOffsetMode offset_mode, REAL x_dx_half, REAL y_dy_half)
 {
     static int fixme;
 
@@ -1005,22 +1005,24 @@ static ARGB resample_bitmap_pixel(GDIPCONST GpRect *src_rect, LPBYTE bits, UINT
     }
     case InterpolationModeNearestNeighbor:
     {
-        FLOAT pixel_offset;
+        FLOAT pixel_offset_x, pixel_offset_y;
         switch (offset_mode)
         {
         default:
         case PixelOffsetModeNone:
         case PixelOffsetModeHighSpeed:
-            pixel_offset = 0.5;
+            pixel_offset_x = 0.5;
+            pixel_offset_y = 0.5;
             break;
 
         case PixelOffsetModeHalf:
         case PixelOffsetModeHighQuality:
-            pixel_offset = 0.0;
+            pixel_offset_x = x_dx_half;
+            pixel_offset_y = y_dy_half;
             break;
         }
         return sample_bitmap_pixel(src_rect, bits, width, height,
-            floorf(point->X + pixel_offset), floorf(point->Y + pixel_offset), attributes);
+            floorf(point->X + pixel_offset_x), floorf(point->Y + pixel_offset_y), attributes);
     }
 
     }
@@ -1311,6 +1313,8 @@ static GpStatus brush_fill_pixels(GpGraphics *graphics, GpBrush *brush,
             REAL x_dy = draw_points[1].Y - draw_points[0].Y;
             REAL y_dx = draw_points[2].X - draw_points[0].X;
             REAL y_dy = draw_points[2].Y - draw_points[0].Y;
+            REAL x_dx_half = x_dx / 2.0;
+            REAL y_dy_half = y_dx / 2.0;
 
             for (y=0; y<fill_area->Height; y++)
             {
@@ -1323,7 +1327,7 @@ static GpStatus brush_fill_pixels(GpGraphics *graphics, GpBrush *brush,
                     argb_pixels[x + y*cdwStride] = resample_bitmap_pixel(
                         &src_area, fill->bitmap_bits, bitmap->width, bitmap->height,
                         &point, fill->imageattributes, graphics->interpolation,
-                        graphics->pixeloffset);
+                        graphics->pixeloffset, x_dx_half, y_dy_half);
                 }
             }
         }
@@ -3083,6 +3087,7 @@ GpStatus WINGDIPAPI GdipDrawImagePointsRect(GpGraphics *graphics, GpImage *image
             PixelOffsetMode offset_mode = graphics->pixeloffset;
             GpPointF dst_to_src_points[3] = {{0.0, 0.0}, {1.0, 0.0}, {0.0, 1.0}};
             REAL x_dx, x_dy, y_dx, y_dy;
+            REAL x_dx_half, y_dy_half;
             static const GpImageAttributes defaultImageAttributes = {WrapModeClamp, 0, FALSE};
 
             if (!imageAttributes)
@@ -3187,6 +3192,8 @@ GpStatus WINGDIPAPI GdipDrawImagePointsRect(GpGraphics *graphics, GpImage *image
                 x_dy = dst_to_src_points[1].Y - dst_to_src_points[0].Y;
                 y_dx = dst_to_src_points[2].X - dst_to_src_points[0].X;
                 y_dy = dst_to_src_points[2].Y - dst_to_src_points[0].Y;
+                x_dx_half = x_dx / 2.0;
+                y_dy_half = y_dy / 2.0;
 
                 for (x=dst_area.left; x<dst_area.right; x++)
                 {
@@ -3202,7 +3209,7 @@ GpStatus WINGDIPAPI GdipDrawImagePointsRect(GpGraphics *graphics, GpImage *image
 
                         if (src_pointf.X >= srcx && src_pointf.X < srcx + srcwidth && src_pointf.Y >= srcy && src_pointf.Y < srcy+srcheight)
                             *dst_color = resample_bitmap_pixel(&src_area, src_data, bitmap->width, bitmap->height, &src_pointf,
-                                                               imageAttributes, interpolation, offset_mode);
+                                                               imageAttributes, interpolation, offset_mode, x_dx_half, y_dy_half);
                         else
                             *dst_color = 0;
                     }
-- 
2.21.0




More information about the wine-devel mailing list