From 31bedb3b895e615f980e9e6e019753205d1cbebe Mon Sep 17 00:00:00 2001 From: Vincent Povirk Date: Fri, 28 Aug 2009 16:21:27 -0500 Subject: [PATCH] gdiplus: create DIBs instead of IPictures in CreateBitmapFromScan0 --- dlls/gdiplus/graphics.c | 93 +++++++++++++++------ dlls/gdiplus/image.c | 208 ++++++++++++++++++++++++++--------------------- 2 files changed, 181 insertions(+), 120 deletions(-) diff --git a/dlls/gdiplus/graphics.c b/dlls/gdiplus/graphics.c index 5263910..a455d45 100644 --- a/dlls/gdiplus/graphics.c +++ b/dlls/gdiplus/graphics.c @@ -1838,37 +1838,78 @@ GpStatus WINGDIPAPI GdipDrawImagePointsRect(GpGraphics *graphics, GpImage *image if(!graphics || !image || !points || count != 3) return InvalidParameter; - if(srcUnit == UnitInch) - dx = dy = (REAL) INCH_HIMETRIC; - else if(srcUnit == UnitPixel){ - dx = ((REAL) INCH_HIMETRIC) / - ((REAL) GetDeviceCaps(graphics->hdc, LOGPIXELSX)); - dy = ((REAL) INCH_HIMETRIC) / - ((REAL) GetDeviceCaps(graphics->hdc, LOGPIXELSY)); - } - else - return NotImplemented; - memcpy(ptf, points, 3 * sizeof(GpPointF)); transform_and_round_points(graphics, pti, ptf, 3); - /* IPicture renders bitmaps with the y-axis reversed - * FIXME: flipping for unknown image type might not be correct. */ - if(image->type != ImageTypeMetafile){ - INT temp; - temp = pti[0].y; - pti[0].y = pti[2].y; - pti[2].y = temp; + if (image->picture) + { + if(srcUnit == UnitInch) + dx = dy = (REAL) INCH_HIMETRIC; + else if(srcUnit == UnitPixel){ + dx = ((REAL) INCH_HIMETRIC) / + ((REAL) GetDeviceCaps(graphics->hdc, LOGPIXELSX)); + dy = ((REAL) INCH_HIMETRIC) / + ((REAL) GetDeviceCaps(graphics->hdc, LOGPIXELSY)); + } + else + return NotImplemented; + + /* IPicture renders bitmaps with the y-axis reversed + * FIXME: flipping for unknown image type might not be correct. */ + if(image->type != ImageTypeMetafile){ + INT temp; + temp = pti[0].y; + pti[0].y = pti[2].y; + pti[2].y = temp; + } + + if(IPicture_Render(image->picture, graphics->hdc, + pti[0].x, pti[0].y, pti[1].x - pti[0].x, pti[2].y - pti[0].y, + srcx * dx, srcy * dy, + srcwidth * dx, srcheight * dy, + NULL) != S_OK){ + if(callback) + callback(callbackData); + return GenericError; + } } + else if (image->type == ImageTypeBitmap && ((GpBitmap*)image)->hbitmap) + { + HDC hdc; + GpBitmap* bitmap = (GpBitmap*)image; + int bm_is_selected; + HBITMAP old_hbm=NULL; + + if (srcUnit == UnitInch) + dx = dy = 96.0; /* FIXME: use the image resolution */ + else if (srcUnit == UnitPixel) + dx = dy = 1.0; + else + return NotImplemented; - if(IPicture_Render(image->picture, graphics->hdc, - pti[0].x, pti[0].y, pti[1].x - pti[0].x, pti[2].y - pti[0].y, - srcx * dx, srcy * dy, - srcwidth * dx, srcheight * dy, - NULL) != S_OK){ - if(callback) - callback(callbackData); - return GenericError; + hdc = bitmap->hdc; + bm_is_selected = (hdc != 0); + + if (!bm_is_selected) + { + hdc = CreateCompatibleDC(0); + old_hbm = SelectObject(hdc, bitmap->hbitmap); + } + + /* FIXME: maybe alpha blend depending on the format */ + StretchBlt(graphics->hdc, pti[0].x, pti[0].y, pti[1].x-pti[0].x, pti[2].y-pti[0].y, + hdc, srcx*dx, srcy*dy, srcwidth*dx, srcheight*dy, SRCCOPY); + + if (!bm_is_selected) + { + SelectObject(hdc, old_hbm); + DeleteDC(hdc); + } + } + else + { + ERR("GpImage with no IPicture or HBITMAP?!\n"); + return NotImplemented; } return Ok; diff --git a/dlls/gdiplus/image.c b/dlls/gdiplus/image.c index 9d91755..cf56b90 100644 --- a/dlls/gdiplus/image.c +++ b/dlls/gdiplus/image.c @@ -312,10 +312,6 @@ GpStatus WINGDIPAPI GdipCloneBitmapAreaI(INT x, INT y, INT width, INT height, GpStatus WINGDIPAPI GdipCloneImage(GpImage *image, GpImage **cloneImage) { - IStream* stream; - HRESULT hr; - INT size; - LARGE_INTEGER move; GpStatus stat = GenericError; TRACE("%p, %p\n", image, cloneImage); @@ -323,29 +319,82 @@ GpStatus WINGDIPAPI GdipCloneImage(GpImage *image, GpImage **cloneImage) if (!image || !cloneImage) return InvalidParameter; - hr = CreateStreamOnHGlobal(0, TRUE, &stream); - if (FAILED(hr)) - return GenericError; - - hr = IPicture_SaveAsFile(image->picture, stream, FALSE, &size); - if(FAILED(hr)) + if (image->picture) { - WARN("Failed to save image on stream\n"); - goto out; + IStream* stream; + HRESULT hr; + INT size; + LARGE_INTEGER move; + + hr = CreateStreamOnHGlobal(0, TRUE, &stream); + if (FAILED(hr)) + return GenericError; + + hr = IPicture_SaveAsFile(image->picture, stream, FALSE, &size); + if(FAILED(hr)) + { + WARN("Failed to save image on stream\n"); + goto out; + } + + /* Set seek pointer back to the beginning of the picture */ + move.QuadPart = 0; + hr = IStream_Seek(stream, move, STREAM_SEEK_SET, NULL); + if (FAILED(hr)) + goto out; + + stat = GdipLoadImageFromStream(stream, cloneImage); + if (stat != Ok) WARN("Failed to load image from stream\n"); + + out: + IStream_Release(stream); + return stat; } + else if (image->type == ImageTypeBitmap) + { + GpBitmap *bitmap = (GpBitmap*)image; + BitmapData lockeddata_src, lockeddata_dst; + int i; + UINT row_size; - /* Set seek pointer back to the beginning of the picture */ - move.QuadPart = 0; - hr = IStream_Seek(stream, move, STREAM_SEEK_SET, NULL); - if (FAILED(hr)) - goto out; + stat = GdipBitmapLockBits(bitmap, NULL, ImageLockModeRead, bitmap->format, + &lockeddata_src); + if (stat != Ok) return stat; - stat = GdipLoadImageFromStream(stream, cloneImage); - if (stat != Ok) WARN("Failed to load image from stream\n"); + stat = GdipCreateBitmapFromScan0(lockeddata_src.Width, lockeddata_src.Height, + 0, lockeddata_src.PixelFormat, NULL, (GpBitmap**)cloneImage); + if (stat == Ok) + { + stat = GdipBitmapLockBits((GpBitmap*)*cloneImage, NULL, ImageLockModeWrite, + lockeddata_src.PixelFormat, &lockeddata_dst); -out: - IStream_Release(stream); - return stat; + if (stat == Ok) + { + /* copy the image data */ + row_size = (lockeddata_src.Width * PIXELFORMATBPP(lockeddata_src.PixelFormat) +7)/8; + for (i=0; ibfType = (((WORD)'M') << 8) + (WORD)'B'; - bmfh->bfSize = size; - bmfh->bfOffBits = size - datalen; + hbitmap = CreateDIBSection(hdc, (BITMAPINFO*)&bmih, DIB_RGB_COLORS, (void**)&bits, + NULL, 0); - bmih->biSize = sizeof(BITMAPINFOHEADER); - bmih->biWidth = width; - /* FIXME: use the rest of the data from format */ - bmih->biBitCount = PIXELFORMATBPP(format); - bmih->biCompression = BI_RGB; - bmih->biSizeImage = datalen; + DeleteDC(hdc); - if (scan0) - { - if (stride > 0) - { - bmih->biHeight = -height; - memcpy(bmih + 1, scan0, datalen); - } - else - { - bmih->biHeight = height; - memcpy(bmih + 1, scan0 + stride * (height - 1), datalen); - } - } - else - { - bmih->biHeight = height; - memset(bmih + 1, 0, datalen); - } + if (!hbitmap) return GenericError; - if(CreateStreamOnHGlobal(buff, TRUE, &stream) != S_OK){ - ERR("could not make stream\n"); - GdipFree(*bitmap); - GdipFree(buff); - *bitmap = NULL; - return GenericError; - } + /* copy bits to the dib if necessary */ + if (scan0) + for (i=0; iimage.picture)) != S_OK){ - TRACE("Could not load picture\n"); - IStream_Release(stream); - GdipFree(*bitmap); - GdipFree(buff); - *bitmap = NULL; - return GenericError; + *bitmap = GdipAlloc(sizeof(GpBitmap)); + if(!*bitmap) + { + DeleteObject(hbitmap); + return OutOfMemory; } (*bitmap)->image.type = ImageTypeBitmap; @@ -689,8 +713,9 @@ GpStatus WINGDIPAPI GdipCreateBitmapFromScan0(INT width, INT height, INT stride, (*bitmap)->width = width; (*bitmap)->height = height; (*bitmap)->format = format; - IPicture_get_Handle((*bitmap)->image.picture, (OLE_HANDLE*)&(*bitmap)->hbitmap); - IPicture_get_CurDC((*bitmap)->image.picture, &(*bitmap)->hdc); + (*bitmap)->image.picture = NULL; + (*bitmap)->hbitmap = hbitmap; + (*bitmap)->hdc = NULL; return Ok; } @@ -793,7 +818,8 @@ GpStatus WINGDIPAPI GdipDisposeImage(GpImage *image) if(!image) return InvalidParameter; - IPicture_Release(image->picture); + if (image->picture) + IPicture_Release(image->picture); if (image->type == ImageTypeBitmap) { GdipFree(((GpBitmap*)image)->bitmapbits); @@ -1543,8 +1569,6 @@ GpStatus WINGDIPAPI GdipSaveImageToStream(GpImage *image, IStream* stream, GDIPCONST CLSID* clsid, GDIPCONST EncoderParameters* params) { GpStatus stat; - HRESULT hr; - short type; HBITMAP hbmp; HBITMAP old_hbmp; HDC hdc; @@ -1566,11 +1590,7 @@ GpStatus WINGDIPAPI GdipSaveImageToStream(GpImage *image, IStream* stream, if(!image || !stream) return InvalidParameter; - if (!image->picture) - return GenericError; - - hr = IPicture_get_Type(image->picture, &type); - if (FAILED(hr) || type != PICTYPE_BITMAP) + if (image->type != ImageTypeBitmap) return GenericError; /* select correct encoder */ -- 1.5.4.3