From 8081eea42c59a846c1225ed757d00275137bf376 Mon Sep 17 00:00:00 2001 From: Vincent Povirk Date: Thu, 24 Feb 2011 16:32:54 -0600 Subject: [PATCH 4/5] gdiplus: Copy only the area requested when (un)locking bitmaps. --- dlls/gdiplus/gdiplus_private.h | 1 + dlls/gdiplus/image.c | 37 +++++++++++++++++++++++++++++-------- dlls/gdiplus/tests/image.c | 4 ++++ 3 files changed, 34 insertions(+), 8 deletions(-) diff --git a/dlls/gdiplus/gdiplus_private.h b/dlls/gdiplus/gdiplus_private.h index bdfb204..42e28fa 100644 --- a/dlls/gdiplus/gdiplus_private.h +++ b/dlls/gdiplus/gdiplus_private.h @@ -280,6 +280,7 @@ struct GpBitmap{ BYTE *bits; /* actual image bits if this is a DIB */ INT stride; /* stride of bits if this is a DIB */ BYTE *own_bits; /* image bits that need to be freed with this object */ + INT lockx, locky; /* X and Y coordinates of the rect when a bitmap is locked for writing. */ }; struct GpCachedBitmap{ diff --git a/dlls/gdiplus/image.c b/dlls/gdiplus/image.c index 2139e97..070ea3d 100644 --- a/dlls/gdiplus/image.c +++ b/dlls/gdiplus/image.c @@ -990,8 +990,8 @@ GpStatus WINGDIPAPI GdipBitmapLockBits(GpBitmap* bitmap, GDIPCONST GpRect* rect, } } - abs_height = bitmap->height; - stride = (bitmap->width * bitspp + 7) / 8; + abs_height = act_rect.Height; + stride = (act_rect.Width * bitspp + 7) / 8; stride = (stride + 3) & ~3; buff = GdipAlloc(stride * abs_height); @@ -1000,9 +1000,19 @@ GpStatus WINGDIPAPI GdipBitmapLockBits(GpBitmap* bitmap, GDIPCONST GpRect* rect, if (flags & ImageLockModeRead) { - stat = convert_pixels(bitmap->width, bitmap->height, + static int fixme=0; + + if (!fixme && (PIXELFORMATBPP(bitmap->format) * act_rect.X) % 8 != 0) + { + FIXME("Cannot copy rows that don't start at a whole byte.\n"); + fixme = 1; + } + + stat = convert_pixels(act_rect.Width, act_rect.Height, stride, buff, format, - bitmap->stride, bitmap->bits, bitmap->format, bitmap->image.palette_entries); + bitmap->stride, + bitmap->bits + bitmap->stride * act_rect.Y + PIXELFORMATBPP(bitmap->format) * act_rect.X / 8, + bitmap->format, bitmap->image.palette_entries); if (stat != Ok) { @@ -1016,11 +1026,13 @@ GpStatus WINGDIPAPI GdipBitmapLockBits(GpBitmap* bitmap, GDIPCONST GpRect* rect, lockeddata->PixelFormat = format; lockeddata->Reserved = flags; lockeddata->Stride = stride; - lockeddata->Scan0 = buff + (bitspp / 8) * act_rect.X + stride * act_rect.Y; + lockeddata->Scan0 = buff; bitmap->lockmode = flags; bitmap->numlocks++; bitmap->bitmapbits = buff; + bitmap->lockx = act_rect.X; + bitmap->locky = act_rect.Y; return Ok; } @@ -1042,6 +1054,7 @@ GpStatus WINGDIPAPI GdipBitmapUnlockBits(GpBitmap* bitmap, BitmapData* lockeddata) { GpStatus stat; + static int fixme=0; TRACE("(%p,%p)\n", bitmap, lockeddata); @@ -1071,9 +1084,17 @@ GpStatus WINGDIPAPI GdipBitmapUnlockBits(GpBitmap* bitmap, return Ok; } - stat = convert_pixels(bitmap->width, bitmap->height, - bitmap->stride, bitmap->bits, bitmap->format, - lockeddata->Stride, bitmap->bitmapbits, lockeddata->PixelFormat, NULL); + if (!fixme && (PIXELFORMATBPP(bitmap->format) * bitmap->lockx) % 8 != 0) + { + FIXME("Cannot copy rows that don't start at a whole byte.\n"); + fixme = 1; + } + + stat = convert_pixels(lockeddata->Width, lockeddata->Height, + bitmap->stride, + bitmap->bits + bitmap->stride * bitmap->locky + PIXELFORMATBPP(bitmap->format) * bitmap->lockx / 8, + bitmap->format, + lockeddata->Stride, lockeddata->Scan0, lockeddata->PixelFormat, NULL); if (stat != Ok) { diff --git a/dlls/gdiplus/tests/image.c b/dlls/gdiplus/tests/image.c index 82d7588..005969b 100644 --- a/dlls/gdiplus/tests/image.c +++ b/dlls/gdiplus/tests/image.c @@ -687,6 +687,10 @@ static void test_LockBits(void) expect(Ok, stat); expect(0xff563412, color); + stat = GdipBitmapGetPixel(bm, 2, 8, &color); + expect(Ok, stat); + expect(0xffc30000, color); + stat = GdipDisposeImage((GpImage*)bm); expect(Ok, stat); stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB, NULL, &bm); -- 1.7.1