Vincent Povirk : gdiplus: Implement color transforms.

Alexandre Julliard julliard at winehq.org
Mon Mar 28 14:21:59 CDT 2011


Module: wine
Branch: master
Commit: 805f0321ebffe0db2d39f414c0f19c21958bb3f6
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=805f0321ebffe0db2d39f414c0f19c21958bb3f6

Author: Vincent Povirk <vincent at codeweavers.com>
Date:   Thu Mar 24 16:50:05 2011 -0500

gdiplus: Implement color transforms.

---

 dlls/gdiplus/graphics.c    |   65 +++++++++++++++++++++++++++++++++++++++++--
 dlls/gdiplus/tests/image.c |   30 +++++++++++++++++---
 2 files changed, 88 insertions(+), 7 deletions(-)

diff --git a/dlls/gdiplus/graphics.c b/dlls/gdiplus/graphics.c
index 7d2dbcd..840825a 100644
--- a/dlls/gdiplus/graphics.c
+++ b/dlls/gdiplus/graphics.c
@@ -331,6 +331,45 @@ static ARGB blend_line_gradient(GpLineGradient* brush, REAL position)
     }
 }
 
+static ARGB transform_color(ARGB color, const ColorMatrix *matrix)
+{
+    REAL val[5], res[4];
+    int i, j;
+    unsigned char a, r, g, b;
+
+    val[0] = ((color >> 16) & 0xff) / 255.0; /* red */
+    val[1] = ((color >> 8) & 0xff) / 255.0; /* green */
+    val[2] = (color & 0xff) / 255.0; /* blue */
+    val[3] = ((color >> 24) & 0xff) / 255.0; /* alpha */
+    val[4] = 1.0; /* translation */
+
+    for (i=0; i<4; i++)
+    {
+        res[i] = 0.0;
+
+        for (j=0; j<5; j++)
+            res[i] += matrix->m[j][i] * val[j];
+    }
+
+    a = min(max(floorf(res[3]*255.0), 0.0), 255.0);
+    r = min(max(floorf(res[0]*255.0), 0.0), 255.0);
+    g = min(max(floorf(res[1]*255.0), 0.0), 255.0);
+    b = min(max(floorf(res[2]*255.0), 0.0), 255.0);
+
+    return (a << 24) | (r << 16) | (g << 8) | b;
+}
+
+static int color_is_gray(ARGB color)
+{
+    unsigned char r, g, b;
+
+    r = (color >> 16) & 0xff;
+    g = (color >> 8) & 0xff;
+    b = color & 0xff;
+
+    return (r == g) && (g == b);
+}
+
 static void apply_image_attributes(const GpImageAttributes *attributes, LPBYTE data,
     UINT width, UINT height, INT stride, ColorAdjustType type)
 {
@@ -400,9 +439,29 @@ static void apply_image_attributes(const GpImageAttributes *attributes, LPBYTE d
     if (attributes->colormatrices[type].enabled ||
         attributes->colormatrices[ColorAdjustTypeDefault].enabled)
     {
-        static int fixme;
-        if (!fixme++)
-            FIXME("Color transforms not implemented\n");
+        const struct color_matrix *colormatrices;
+
+        if (attributes->colormatrices[type].enabled)
+            colormatrices = &attributes->colormatrices[type];
+        else
+            colormatrices = &attributes->colormatrices[ColorAdjustTypeDefault];
+
+        for (x=0; x<width; x++)
+            for (y=0; y<height; y++)
+            {
+                ARGB *src_color;
+                src_color = (ARGB*)(data + stride * y + sizeof(ARGB) * x);
+
+                if (colormatrices->flags == ColorMatrixFlagsDefault ||
+                    !color_is_gray(*src_color))
+                {
+                    *src_color = transform_color(*src_color, &colormatrices->colormatrix);
+                }
+                else if (colormatrices->flags == ColorMatrixFlagsAltGray)
+                {
+                    *src_color = transform_color(*src_color, &colormatrices->graymatrix);
+                }
+            }
     }
 
     if (attributes->gamma_enabled[type] ||
diff --git a/dlls/gdiplus/tests/image.c b/dlls/gdiplus/tests/image.c
index 71a99ea..cbae047 100644
--- a/dlls/gdiplus/tests/image.c
+++ b/dlls/gdiplus/tests/image.c
@@ -1923,6 +1923,12 @@ static void test_colormatrix(void)
         {0.0,0.0,1.0,0.0,0.0},
         {0.0,0.0,0.0,1.0,0.0},
         {0.0,0.0,0.0,0.0,1.0}}};
+    const ColorMatrix asymmetric = {{
+        {0.0,1.0,0.0,0.0,0.0},
+        {0.0,0.0,1.0,0.0,0.0},
+        {0.0,0.0,0.0,1.0,0.0},
+        {1.0,0.0,0.0,0.0,0.0},
+        {0.0,0.0,0.0,0.0,1.0}}};
     GpBitmap *bitmap1, *bitmap2;
     GpGraphics *graphics;
     ARGB color;
@@ -1983,13 +1989,13 @@ static void test_colormatrix(void)
         TRUE, &colormatrix, NULL, ColorMatrixFlagsDefault);
     expect(Ok, stat);
 
-    stat = GdipCreateBitmapFromScan0(1, 1, 0, PixelFormat32bppRGB, NULL, &bitmap1);
+    stat = GdipCreateBitmapFromScan0(1, 1, 0, PixelFormat32bppARGB, NULL, &bitmap1);
     expect(Ok, stat);
 
-    stat = GdipCreateBitmapFromScan0(1, 1, 0, PixelFormat32bppRGB, NULL, &bitmap2);
+    stat = GdipCreateBitmapFromScan0(1, 1, 0, PixelFormat32bppARGB, NULL, &bitmap2);
     expect(Ok, stat);
 
-    stat = GdipBitmapSetPixel(bitmap1, 0, 0, 0xff40ffff);
+    stat = GdipBitmapSetPixel(bitmap1, 0, 0, 0xff40ccee);
     expect(Ok, stat);
 
     stat = GdipGetImageGraphicsContext((GpImage*)bitmap2, &graphics);
@@ -2001,7 +2007,23 @@ static void test_colormatrix(void)
 
     stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color);
     expect(Ok, stat);
-    todo_wine expect(0xff80ffff, color);
+    expect(0xff80ccee, color);
+
+    colormatrix = asymmetric;
+    stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
+        TRUE, &colormatrix, NULL, ColorMatrixFlagsDefault);
+    expect(Ok, stat);
+
+    stat = GdipBitmapSetPixel(bitmap2, 0, 0, 0);
+    expect(Ok, stat);
+
+    stat = GdipDrawImageRectRectI(graphics, (GpImage*)bitmap1, 0,0,1,1, 0,0,1,1,
+        UnitPixel, imageattr, NULL, NULL);
+    expect(Ok, stat);
+
+    stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color);
+    expect(Ok, stat);
+    ok(color_match(0xeeff40cc, color, 3), "expected 0xeeff40cc, got 0x%08x\n", color);
 
     GdipDeleteGraphics(graphics);
     GdipDisposeImage((GpImage*)bitmap1);




More information about the wine-cvs mailing list