From fb714bd2daa93e1e5a0adf6ab34cb3180f3bbf66 Mon Sep 17 00:00:00 2001 From: Vincent Povirk Date: Thu, 24 Mar 2011 16:50:05 -0500 Subject: [PATCH] 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; xflags == 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); -- 1.7.1