Signed-off-by: Bernhard Kölbl besentv@gmail.com --- dlls/gdiplus/image.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+)
diff --git a/dlls/gdiplus/image.c b/dlls/gdiplus/image.c index ead76fc4b27..862f7fea111 100644 --- a/dlls/gdiplus/image.c +++ b/dlls/gdiplus/image.c @@ -726,6 +726,8 @@ GpStatus convert_pixels(INT width, INT height, { case PixelFormat1bppIndexed: convert_rgb_to_indexed(getpixel_16bppGrayScale, setpixel_1bppIndexed); + case PixelFormat4bppIndexed: + convert_rgb_to_indexed(getpixel_16bppGrayScale, setpixel_4bppIndexed); case PixelFormat8bppIndexed: convert_rgb_to_indexed(getpixel_16bppGrayScale, setpixel_8bppIndexed); case PixelFormat16bppRGB555: @@ -755,6 +757,8 @@ GpStatus convert_pixels(INT width, INT height, { case PixelFormat1bppIndexed: convert_rgb_to_indexed(getpixel_16bppRGB555, setpixel_1bppIndexed); + case PixelFormat4bppIndexed: + convert_rgb_to_indexed(getpixel_16bppRGB555, setpixel_4bppIndexed); case PixelFormat8bppIndexed: convert_rgb_to_indexed(getpixel_16bppRGB555, setpixel_8bppIndexed); case PixelFormat16bppGrayScale: @@ -784,6 +788,8 @@ GpStatus convert_pixels(INT width, INT height, { case PixelFormat1bppIndexed: convert_rgb_to_indexed(getpixel_16bppRGB565, setpixel_1bppIndexed); + case PixelFormat4bppIndexed: + convert_rgb_to_indexed(getpixel_16bppRGB565, setpixel_4bppIndexed); case PixelFormat8bppIndexed: convert_rgb_to_indexed(getpixel_16bppRGB565, setpixel_8bppIndexed); case PixelFormat16bppGrayScale: @@ -813,6 +819,8 @@ GpStatus convert_pixels(INT width, INT height, { case PixelFormat1bppIndexed: convert_rgb_to_indexed(getpixel_16bppARGB1555, setpixel_1bppIndexed); + case PixelFormat4bppIndexed: + convert_rgb_to_indexed(getpixel_16bppARGB1555, setpixel_4bppIndexed); case PixelFormat8bppIndexed: convert_rgb_to_indexed(getpixel_16bppARGB1555, setpixel_8bppIndexed); case PixelFormat16bppGrayScale: @@ -842,6 +850,8 @@ GpStatus convert_pixels(INT width, INT height, { case PixelFormat1bppIndexed: convert_rgb_to_indexed(getpixel_24bppRGB, setpixel_1bppIndexed); + case PixelFormat4bppIndexed: + convert_rgb_to_indexed(getpixel_24bppRGB, setpixel_4bppIndexed); case PixelFormat8bppIndexed: convert_rgb_to_indexed(getpixel_24bppRGB, setpixel_8bppIndexed); case PixelFormat16bppGrayScale: @@ -871,6 +881,8 @@ GpStatus convert_pixels(INT width, INT height, { case PixelFormat1bppIndexed: convert_rgb_to_indexed(getpixel_32bppRGB, setpixel_1bppIndexed); + case PixelFormat4bppIndexed: + convert_rgb_to_indexed(getpixel_32bppRGB, setpixel_4bppIndexed); case PixelFormat8bppIndexed: convert_rgb_to_indexed(getpixel_32bppRGB, setpixel_8bppIndexed); case PixelFormat16bppGrayScale: @@ -900,6 +912,8 @@ GpStatus convert_pixels(INT width, INT height, { case PixelFormat1bppIndexed: convert_rgb_to_indexed(getpixel_32bppARGB, setpixel_1bppIndexed); + case PixelFormat4bppIndexed: + convert_rgb_to_indexed(getpixel_32bppARGB, setpixel_4bppIndexed); case PixelFormat8bppIndexed: convert_rgb_to_indexed(getpixel_32bppARGB, setpixel_8bppIndexed); case PixelFormat16bppGrayScale: @@ -928,6 +942,8 @@ GpStatus convert_pixels(INT width, INT height, { case PixelFormat1bppIndexed: convert_rgb_to_indexed(getpixel_32bppPARGB, setpixel_1bppIndexed); + case PixelFormat4bppIndexed: + convert_rgb_to_indexed(getpixel_32bppPARGB, setpixel_4bppIndexed); case PixelFormat8bppIndexed: convert_rgb_to_indexed(getpixel_32bppPARGB, setpixel_8bppIndexed); case PixelFormat16bppGrayScale: @@ -957,6 +973,8 @@ GpStatus convert_pixels(INT width, INT height, { case PixelFormat1bppIndexed: convert_rgb_to_indexed(getpixel_48bppRGB, setpixel_1bppIndexed); + case PixelFormat4bppIndexed: + convert_rgb_to_indexed(getpixel_48bppRGB, setpixel_4bppIndexed); case PixelFormat8bppIndexed: convert_rgb_to_indexed(getpixel_48bppRGB, setpixel_8bppIndexed); case PixelFormat16bppGrayScale: @@ -986,6 +1004,8 @@ GpStatus convert_pixels(INT width, INT height, { case PixelFormat1bppIndexed: convert_rgb_to_indexed(getpixel_64bppARGB, setpixel_1bppIndexed); + case PixelFormat4bppIndexed: + convert_rgb_to_indexed(getpixel_64bppARGB, setpixel_4bppIndexed); case PixelFormat8bppIndexed: convert_rgb_to_indexed(getpixel_64bppARGB, setpixel_8bppIndexed); case PixelFormat16bppGrayScale: @@ -1015,6 +1035,8 @@ GpStatus convert_pixels(INT width, INT height, { case PixelFormat1bppIndexed: convert_rgb_to_indexed(getpixel_64bppPARGB, setpixel_1bppIndexed); + case PixelFormat4bppIndexed: + convert_rgb_to_indexed(getpixel_64bppPARGB, setpixel_4bppIndexed); case PixelFormat8bppIndexed: convert_rgb_to_indexed(getpixel_64bppPARGB, setpixel_8bppIndexed); case PixelFormat16bppGrayScale:
Make it possible to define a destination colour palette when using convert_pixels(), so converting a bitmap from a non indexed format to an indexed format does not produce an empty image. --- This happens if you e.g. clone an RGB bitmap area to indexed. Most times the cloned image is just a plain black or white image.
Signed-off-by: Bernhard Kölbl besentv@gmail.com --- dlls/gdiplus/gdiplus_private.h | 4 ++-- dlls/gdiplus/graphics.c | 2 +- dlls/gdiplus/image.c | 21 +++++++++++---------- 3 files changed, 14 insertions(+), 13 deletions(-)
diff --git a/dlls/gdiplus/gdiplus_private.h b/dlls/gdiplus/gdiplus_private.h index 22213e9f278..7ae8cc564c9 100644 --- a/dlls/gdiplus/gdiplus_private.h +++ b/dlls/gdiplus/gdiplus_private.h @@ -207,8 +207,8 @@ extern void convert_32bppARGB_to_32bppPARGB(UINT width, UINT height, BYTE *dst_bits, INT dst_stride, const BYTE *src_bits, INT src_stride) DECLSPEC_HIDDEN;
extern GpStatus convert_pixels(INT width, INT height, - INT dst_stride, BYTE *dst_bits, PixelFormat dst_format, - INT src_stride, const BYTE *src_bits, PixelFormat src_format, ColorPalette *palette) DECLSPEC_HIDDEN; + INT dst_stride, BYTE *dst_bits, PixelFormat dst_format, ColorPalette *dst_palette, + INT src_stride, const BYTE *src_bits, PixelFormat src_format, ColorPalette *src_palette) DECLSPEC_HIDDEN;
extern PixelFormat apply_image_attributes(const GpImageAttributes *attributes, LPBYTE data, UINT width, UINT height, INT stride, ColorAdjustType type, PixelFormat fmt) DECLSPEC_HIDDEN; diff --git a/dlls/gdiplus/graphics.c b/dlls/gdiplus/graphics.c index 4a428c49869..65cdf96510d 100644 --- a/dlls/gdiplus/graphics.c +++ b/dlls/gdiplus/graphics.c @@ -3350,7 +3350,7 @@ GpStatus WINGDIPAPI GdipDrawImagePointsRect(GpGraphics *graphics, GpImage *image dst_format = PixelFormat32bppRGB;
convert_pixels(bitmap->width, bitmap->height, - bitmap->width*4, temp_bits, dst_format, + bitmap->width*4, temp_bits, dst_format, bitmap->image.palette, bitmap->stride, bitmap->bits, bitmap->format, bitmap->image.palette); } diff --git a/dlls/gdiplus/image.c b/dlls/gdiplus/image.c index 862f7fea111..81df99e5455 100644 --- a/dlls/gdiplus/image.c +++ b/dlls/gdiplus/image.c @@ -590,9 +590,10 @@ GpStatus WINGDIPAPI GdipBitmapSetPixel(GpBitmap* bitmap, INT x, INT y, }
GpStatus convert_pixels(INT width, INT height, - INT dst_stride, BYTE *dst_bits, PixelFormat dst_format, + INT dst_stride, BYTE *dst_bits, PixelFormat dst_format, + ColorPalette *dst_palette, INT src_stride, const BYTE *src_bits, PixelFormat src_format, - ColorPalette *palette) + ColorPalette *src_palette) { INT x, y;
@@ -612,7 +613,7 @@ GpStatus convert_pixels(INT width, INT height, ARGB argb; \ BYTE *color = (BYTE *)&argb; \ getpixel_function(&index, src_bits+src_stride*y, x); \ - argb = (palette && index < palette->Count) ? palette->Entries[index] : 0; \ + argb = (src_palette && index < src_palette->Count) ? src_palette->Entries[index] : 0; \ setpixel_function(color[2], color[1], color[0], color[3], dst_bits+dst_stride*y, x); \ } \ return Ok; \ @@ -633,7 +634,7 @@ GpStatus convert_pixels(INT width, INT height, for (x=0; x<width; x++) { \ BYTE r, g, b, a; \ getpixel_function(&r, &g, &b, &a, src_bits+src_stride*y, x); \ - setpixel_function(r, g, b, a, dst_bits+dst_stride*y, x, palette); \ + setpixel_function(r, g, b, a, dst_bits+dst_stride*y, x, dst_palette); \ } \ return Ok; \ } while (0); @@ -1137,7 +1138,7 @@ GpStatus WINGDIPAPI GdipBitmapLockBits(GpBitmap* bitmap, GDIPCONST GpRect* rect, /* Make sure we can convert to the requested format. */ if (flags & ImageLockModeRead) { - stat = convert_pixels(0, 0, 0, NULL, format, 0, NULL, bitmap->format, NULL); + stat = convert_pixels(0, 0, 0, NULL, format, NULL, 0, NULL, bitmap->format, NULL); if (stat == NotImplemented) { FIXME("cannot read bitmap from %x to %x\n", bitmap->format, format); @@ -1150,7 +1151,7 @@ GpStatus WINGDIPAPI GdipBitmapLockBits(GpBitmap* bitmap, GDIPCONST GpRect* rect, * the original format. */ if (flags & ImageLockModeWrite) { - stat = convert_pixels(0, 0, 0, NULL, bitmap->format, 0, NULL, format, NULL); + stat = convert_pixels(0, 0, 0, NULL, bitmap->format, NULL, 0, NULL, format, NULL); if (stat == NotImplemented) { FIXME("cannot write bitmap from %x to %x\n", format, bitmap->format); @@ -1190,7 +1191,7 @@ GpStatus WINGDIPAPI GdipBitmapLockBits(GpBitmap* bitmap, GDIPCONST GpRect* rect, }
stat = convert_pixels(act_rect.Width, act_rect.Height, - lockeddata->Stride, lockeddata->Scan0, format, + lockeddata->Stride, lockeddata->Scan0, format, bitmap->image.palette, bitmap->stride, bitmap->bits + bitmap->stride * act_rect.Y + PIXELFORMATBPP(bitmap->format) * act_rect.X / 8, bitmap->format, bitmap->image.palette); @@ -1270,7 +1271,7 @@ GpStatus WINGDIPAPI GdipBitmapUnlockBits(GpBitmap* bitmap, stat = convert_pixels(lockeddata->Width, lockeddata->Height, bitmap->stride, bitmap->bits + bitmap->stride * bitmap->locky + PIXELFORMATBPP(bitmap->format) * bitmap->lockx / 8, - bitmap->format, + bitmap->format, NULL, lockeddata->Stride, lockeddata->Scan0, lockeddata->PixelFormat, NULL);
if (stat != Ok) @@ -1314,7 +1315,7 @@ GpStatus WINGDIPAPI GdipCloneBitmapArea(REAL x, REAL y, REAL width, REAL height, if (stat == Ok) { stat = convert_pixels(area.Width, area.Height, (*dstBitmap)->stride, (*dstBitmap)->bits, (*dstBitmap)->format, - srcBitmap->stride, + (*dstBitmap)->image.palette, srcBitmap->stride, srcBitmap->bits + srcBitmap->stride * area.Y + PIXELFORMATBPP(srcBitmap->format) * area.X / 8, srcBitmap->format, srcBitmap->image.palette);
@@ -1545,7 +1546,7 @@ GpStatus WINGDIPAPI GdipCreateHBITMAPFromBitmap(GpBitmap* bitmap, }
stat = convert_pixels(width, height, -width*4, - bits + (width * 4 * (height - 1)), PixelFormat32bppPARGB, + bits + (width * 4 * (height - 1)), PixelFormat32bppPARGB, bitmap->image.palette, bitmap->stride, bitmap->bits, bitmap->format, bitmap->image.palette); if (stat != Ok) {
For GdipUnlockBits, wouldn't we want to use the bitmap's palette for the destination?
Signed-off-by: Bernhard Kölbl besentv@gmail.com --- dlls/gdiplus/tests/image.c | 42 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+)
diff --git a/dlls/gdiplus/tests/image.c b/dlls/gdiplus/tests/image.c index 2175c1748e0..01fda84f44b 100644 --- a/dlls/gdiplus/tests/image.c +++ b/dlls/gdiplus/tests/image.c @@ -5102,9 +5102,17 @@ static void test_PARGB_conversion(void)
static void test_CloneBitmapArea(void) { + /* 3x3 pixeldata in format 32bpp RGB: red, green, blue, yellow, turquoise, pink, black, gray, white */ + static const unsigned char bmp_3x3_data[100] = { + 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0xff, 0x00, 0x00, + 0x00, 0xff, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0x80, 0x80, 0x80, 0x00, + 0x00, 0x00, 0x00, 0x00 + }; GpStatus status; GpBitmap *bitmap, *copy; BitmapData data, data2; + BYTE buf[sizeof(bmp_3x3_data)]; + INT x, y;
status = GdipCreateBitmapFromScan0(1, 1, 0, PixelFormat24bppRGB, NULL, &bitmap); expect(Ok, status); @@ -5123,6 +5131,40 @@ static void test_CloneBitmapArea(void)
GdipDisposeImage((GpImage *)copy); GdipDisposeImage((GpImage *)bitmap); + + memcpy(buf, bmp_3x3_data, sizeof(bmp_3x3_data)); + + status = GdipCreateBitmapFromScan0(3, 3, 4*3, PixelFormat32bppRGB, buf, &bitmap); + expect(Ok, status); + +#define check_clone_to_indexed(pixel_format) do { \ + status = GdipCloneBitmapAreaI(0, 0, 3, 3, pixel_format, bitmap, ©); \ + expect(Ok, status); \ + for (y=0; y<3; y++) \ + for (x=0; x<3; x++) \ + { \ + BOOL match; \ + ARGB color_orig; \ + ARGB color_copy; \ + \ + status = GdipBitmapGetPixel(bitmap, x, y, &color_orig); \ + expect(Ok, status); \ + status = GdipBitmapGetPixel(copy, x, y, &color_copy); \ + expect(Ok, status); \ + if(pixel_format == PixelFormat1bppIndexed) \ + color_orig = (color_orig >> 16 & 0xff) + (color_orig >> 8 & 0xff) + (color_orig & 0xff) \ + > 0x17d ? 0xffffffff : 0xff000000; \ + match = color_match(color_orig, color_copy, 0x00); \ + ok(match == TRUE, "Colors 0x%x and 0x%x do not match!\n", color_orig, color_copy); \ + } \ + GdipDisposeImage((GpImage *)copy); \ +}while(0) \ + + check_clone_to_indexed(PixelFormat1bppIndexed); + check_clone_to_indexed(PixelFormat4bppIndexed); + check_clone_to_indexed(PixelFormat8bppIndexed); + + GdipDisposeImage((GpImage *)bitmap); }
static void test_supported_encoders(void)