diff --git a/dlls/gdiplus/image.c b/dlls/gdiplus/image.c index 69f58659a2842301edbe1a3d0174112ade22aeca..a69046d0b9aac62abcbb652fd353e8fff4c20dea 100644 --- a/dlls/gdiplus/image.c +++ b/dlls/gdiplus/image.c @@ -296,6 +296,53 @@ GpStatus WINGDIPAPI GdipBitmapGetPixel(GpBitmap* bitmap, INT x, INT y, return Ok; } +static inline UINT get_palette_index(BYTE r, BYTE g, BYTE b, BYTE a, GpBitmap* bitmap) { + BYTE index = 0; + int best_distance = 0x7fff; + int distance; + int i; + /* This algorithm scans entire pallete, + computes difference from desired color (all color components have equal weight) + and returns the index of color with least difference. + + Note: Maybe it could be replaced with a better algorithm for better image quality + and performance, though better algorithm would probably need some pre-built lookup + tables and thus may actually be slower if this method is called only few times per + every image. + */ + for(i=0;i<bitmap->image.palette_size;i++) { + ARGB color=bitmap->image.palette_entries[i]; + distance=abs(b-(color & 0xff)) + abs(g-(color>>8 & 0xff)) + abs(r-(color>>16 & 0xff)) + abs(a-(color>>24 & 0xff)); + if (distance<best_distance) { + best_distance=distance; + index=i; + } + } + return index; +} + +static inline void setpixel_8bppIndexed(BYTE r, BYTE g, BYTE b, BYTE a, + BYTE *row, UINT x, GpBitmap* bitmap) +{ + BYTE index = get_palette_index(r,g,b,a,bitmap); + row[x]=index; +} + +static inline void setpixel_1bppIndexed(BYTE r, BYTE g, BYTE b, BYTE a, + BYTE *row, UINT x, GpBitmap* bitmap) +{ + row[x/8] = (row[x/8] & ~(1<<(7-x%8))) | (get_palette_index(r,g,b,a,bitmap)<<(7-x%8)); +} + +static inline void setpixel_4bppIndexed(BYTE r, BYTE g, BYTE b, BYTE a, + BYTE *row, UINT x, GpBitmap* bitmap) +{ + if (x & 1) + row[x/2] = (row[x/2] & 0xf0) | get_palette_index(r,g,b,a,bitmap); + else + row[x/2] = (row[x/2] & 0x0f) | get_palette_index(r,g,b,a,bitmap)<<4; +} + static inline void setpixel_16bppGrayScale(BYTE r, BYTE g, BYTE b, BYTE a, BYTE *row, UINT x) { @@ -434,6 +481,15 @@ GpStatus WINGDIPAPI GdipBitmapSetPixel(GpBitmap* bitmap, INT x, INT y, case PixelFormat64bppPARGB: setpixel_64bppPARGB(r,g,b,a,row,x); break; + case PixelFormat8bppIndexed: + setpixel_8bppIndexed(r,g,b,a,row,x,bitmap); + break; + case PixelFormat4bppIndexed: + setpixel_4bppIndexed(r,g,b,a,row,x,bitmap); + break; + case PixelFormat1bppIndexed: + setpixel_1bppIndexed(r,g,b,a,row,x,bitmap); + break; default: FIXME("not implemented for format 0x%x\n", bitmap->format); return NotImplemented; diff --git a/dlls/gdiplus/tests/image.c b/dlls/gdiplus/tests/image.c index b2b1a0f96b0fe951a56c66edd0494e754f7810fa..989e0bbe2370f57c6d7071351f96112b2066fbd1 100644 --- a/dlls/gdiplus/tests/image.c +++ b/dlls/gdiplus/tests/image.c @@ -1568,7 +1568,7 @@ static void test_palette(void) expect(0xff000000, color); stat = GdipBitmapSetPixel(bitmap, 0, 1, 0xffffffff); - todo_wine ok((stat == Ok) || + ok((stat == Ok) || broken(stat == InvalidParameter) /* pre-win7 */, "stat=%.8x\n", stat); if (stat == Ok) @@ -1601,7 +1601,7 @@ static void test_palette(void) expect(0xff000000, color); stat = GdipBitmapSetPixel(bitmap, 0, 1, 0xffff00ff); - todo_wine ok((stat == Ok) || + ok((stat == Ok) || broken(stat == InvalidParameter) /* pre-win7 */, "stat=%.8x\n", stat); if (stat == Ok) @@ -1634,7 +1634,7 @@ static void test_palette(void) expect(0xff000000, color); stat = GdipBitmapSetPixel(bitmap, 0, 1, 0xffcccccc); - todo_wine ok((stat == Ok) || + ok((stat == Ok) || broken(stat == InvalidParameter) /* pre-win7 */, "stat=%.8x\n", stat); if (stat == Ok)