Commit 436b3be6 authored by Vincent Povirk's avatar Vincent Povirk Committed by Alexandre Julliard

gdiplus: Create DIBs instead of IPictures in CreateBitmapFromScan0.

parent d87adf2a
...@@ -1838,37 +1838,78 @@ GpStatus WINGDIPAPI GdipDrawImagePointsRect(GpGraphics *graphics, GpImage *image ...@@ -1838,37 +1838,78 @@ GpStatus WINGDIPAPI GdipDrawImagePointsRect(GpGraphics *graphics, GpImage *image
if(!graphics || !image || !points || count != 3) if(!graphics || !image || !points || count != 3)
return InvalidParameter; 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)); memcpy(ptf, points, 3 * sizeof(GpPointF));
transform_and_round_points(graphics, pti, ptf, 3); transform_and_round_points(graphics, pti, ptf, 3);
/* IPicture renders bitmaps with the y-axis reversed if (image->picture)
* FIXME: flipping for unknown image type might not be correct. */ {
if(image->type != ImageTypeMetafile){ if(srcUnit == UnitInch)
INT temp; dx = dy = (REAL) INCH_HIMETRIC;
temp = pti[0].y; else if(srcUnit == UnitPixel){
pti[0].y = pti[2].y; dx = ((REAL) INCH_HIMETRIC) /
pti[2].y = temp; ((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, hdc = bitmap->hdc;
pti[0].x, pti[0].y, pti[1].x - pti[0].x, pti[2].y - pti[0].y, bm_is_selected = (hdc != 0);
srcx * dx, srcy * dy,
srcwidth * dx, srcheight * dy, if (!bm_is_selected)
NULL) != S_OK){ {
if(callback) hdc = CreateCompatibleDC(0);
callback(callbackData); old_hbm = SelectObject(hdc, bitmap->hbitmap);
return GenericError; }
/* 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; return Ok;
......
...@@ -312,10 +312,6 @@ GpStatus WINGDIPAPI GdipCloneBitmapAreaI(INT x, INT y, INT width, INT height, ...@@ -312,10 +312,6 @@ GpStatus WINGDIPAPI GdipCloneBitmapAreaI(INT x, INT y, INT width, INT height,
GpStatus WINGDIPAPI GdipCloneImage(GpImage *image, GpImage **cloneImage) GpStatus WINGDIPAPI GdipCloneImage(GpImage *image, GpImage **cloneImage)
{ {
IStream* stream;
HRESULT hr;
INT size;
LARGE_INTEGER move;
GpStatus stat = GenericError; GpStatus stat = GenericError;
TRACE("%p, %p\n", image, cloneImage); TRACE("%p, %p\n", image, cloneImage);
...@@ -323,29 +319,82 @@ GpStatus WINGDIPAPI GdipCloneImage(GpImage *image, GpImage **cloneImage) ...@@ -323,29 +319,82 @@ GpStatus WINGDIPAPI GdipCloneImage(GpImage *image, GpImage **cloneImage)
if (!image || !cloneImage) if (!image || !cloneImage)
return InvalidParameter; return InvalidParameter;
hr = CreateStreamOnHGlobal(0, TRUE, &stream); if (image->picture)
if (FAILED(hr))
return GenericError;
hr = IPicture_SaveAsFile(image->picture, stream, FALSE, &size);
if(FAILED(hr))
{ {
WARN("Failed to save image on stream\n"); IStream* stream;
goto out; 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 */ stat = GdipBitmapLockBits(bitmap, NULL, ImageLockModeRead, bitmap->format,
move.QuadPart = 0; &lockeddata_src);
hr = IStream_Seek(stream, move, STREAM_SEEK_SET, NULL); if (stat != Ok) return stat;
if (FAILED(hr))
goto out;
stat = GdipLoadImageFromStream(stream, cloneImage); stat = GdipCreateBitmapFromScan0(lockeddata_src.Width, lockeddata_src.Height,
if (stat != Ok) WARN("Failed to load image from stream\n"); 0, lockeddata_src.PixelFormat, NULL, (GpBitmap**)cloneImage);
if (stat == Ok)
{
stat = GdipBitmapLockBits((GpBitmap*)*cloneImage, NULL, ImageLockModeWrite,
lockeddata_src.PixelFormat, &lockeddata_dst);
out: if (stat == Ok)
IStream_Release(stream); {
return stat; /* copy the image data */
row_size = (lockeddata_src.Width * PIXELFORMATBPP(lockeddata_src.PixelFormat) +7)/8;
for (i=0; i<lockeddata_src.Height; i++)
memcpy((BYTE*)lockeddata_dst.Scan0+lockeddata_dst.Stride*i,
(BYTE*)lockeddata_src.Scan0+lockeddata_src.Stride*i,
row_size);
GdipBitmapUnlockBits((GpBitmap*)*cloneImage, &lockeddata_dst);
}
GdipBitmapUnlockBits(bitmap, &lockeddata_src);
}
if (stat != Ok)
{
GdipDisposeImage(*cloneImage);
*cloneImage = NULL;
}
return stat;
}
else
{
ERR("GpImage with no IPicture or bitmap?!\n");
return NotImplemented;
}
} }
GpStatus WINGDIPAPI GdipCreateBitmapFromFile(GDIPCONST WCHAR* filename, GpStatus WINGDIPAPI GdipCreateBitmapFromFile(GDIPCONST WCHAR* filename,
...@@ -599,11 +648,12 @@ GpStatus WINGDIPAPI GdipCreateBitmapFromHICON(HICON hicon, GpBitmap** bitmap) ...@@ -599,11 +648,12 @@ GpStatus WINGDIPAPI GdipCreateBitmapFromHICON(HICON hicon, GpBitmap** bitmap)
GpStatus WINGDIPAPI GdipCreateBitmapFromScan0(INT width, INT height, INT stride, GpStatus WINGDIPAPI GdipCreateBitmapFromScan0(INT width, INT height, INT stride,
PixelFormat format, BYTE* scan0, GpBitmap** bitmap) PixelFormat format, BYTE* scan0, GpBitmap** bitmap)
{ {
BITMAPFILEHEADER *bmfh; BITMAPINFOHEADER bmih;
BITMAPINFOHEADER *bmih; HBITMAP hbitmap;
BYTE *buff; INT row_size, dib_stride;
INT datalen, size; HDC hdc;
IStream *stream; BYTE *bits;
int i;
TRACE("%d %d %d %d %p %p\n", width, height, stride, format, scan0, bitmap); TRACE("%d %d %d %d %p %p\n", width, height, stride, format, scan0, bitmap);
...@@ -617,71 +667,45 @@ GpStatus WINGDIPAPI GdipCreateBitmapFromScan0(INT width, INT height, INT stride, ...@@ -617,71 +667,45 @@ GpStatus WINGDIPAPI GdipCreateBitmapFromScan0(INT width, INT height, INT stride,
if(scan0 && !stride) if(scan0 && !stride)
return InvalidParameter; return InvalidParameter;
*bitmap = GdipAlloc(sizeof(GpBitmap)); row_size = (width * PIXELFORMATBPP(format)+7) / 8;
if(!*bitmap) return OutOfMemory; dib_stride = (row_size + 3) & ~3;
if(stride == 0){ if(stride == 0)
stride = width * (PIXELFORMATBPP(format) / 8); stride = dib_stride;
stride = (stride + 3) & ~3;
}
datalen = abs(stride * height); bmih.biSize = sizeof(BITMAPINFOHEADER);
size = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + datalen; bmih.biWidth = width;
buff = GdipAlloc(size); bmih.biHeight = -height;
if(!buff){ bmih.biPlanes = 1;
GdipFree(*bitmap); /* FIXME: use the rest of the data from format */
return OutOfMemory; bmih.biBitCount = PIXELFORMATBPP(format);
} bmih.biCompression = BI_RGB;
bmih.biSizeImage = 0;
bmih.biXPelsPerMeter = 0;
bmih.biYPelsPerMeter = 0;
bmih.biClrUsed = 0;
bmih.biClrImportant = 0;
bmfh = (BITMAPFILEHEADER*) buff; hdc = CreateCompatibleDC(NULL);
bmih = (BITMAPINFOHEADER*) (bmfh + 1); if (!hdc) return GenericError;
bmfh->bfType = (((WORD)'M') << 8) + (WORD)'B'; hbitmap = CreateDIBSection(hdc, (BITMAPINFO*)&bmih, DIB_RGB_COLORS, (void**)&bits,
bmfh->bfSize = size; NULL, 0);
bmfh->bfOffBits = size - datalen;
bmih->biSize = sizeof(BITMAPINFOHEADER); DeleteDC(hdc);
bmih->biWidth = width;
/* FIXME: use the rest of the data from format */
bmih->biBitCount = PIXELFORMATBPP(format);
bmih->biCompression = BI_RGB;
bmih->biSizeImage = datalen;
if (scan0) if (!hbitmap) return GenericError;
{
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(CreateStreamOnHGlobal(buff, TRUE, &stream) != S_OK){ /* copy bits to the dib if necessary */
ERR("could not make stream\n"); if (scan0)
GdipFree(*bitmap); for (i=0; i<height; i++)
GdipFree(buff); memcpy(bits+i*dib_stride, scan0+i*stride, row_size);
*bitmap = NULL;
return GenericError;
}
if(OleLoadPicture(stream, 0, FALSE, &IID_IPicture, *bitmap = GdipAlloc(sizeof(GpBitmap));
(LPVOID*) &((*bitmap)->image.picture)) != S_OK){ if(!*bitmap)
TRACE("Could not load picture\n"); {
IStream_Release(stream); DeleteObject(hbitmap);
GdipFree(*bitmap); return OutOfMemory;
GdipFree(buff);
*bitmap = NULL;
return GenericError;
} }
(*bitmap)->image.type = ImageTypeBitmap; (*bitmap)->image.type = ImageTypeBitmap;
...@@ -689,8 +713,9 @@ GpStatus WINGDIPAPI GdipCreateBitmapFromScan0(INT width, INT height, INT stride, ...@@ -689,8 +713,9 @@ GpStatus WINGDIPAPI GdipCreateBitmapFromScan0(INT width, INT height, INT stride,
(*bitmap)->width = width; (*bitmap)->width = width;
(*bitmap)->height = height; (*bitmap)->height = height;
(*bitmap)->format = format; (*bitmap)->format = format;
IPicture_get_Handle((*bitmap)->image.picture, (OLE_HANDLE*)&(*bitmap)->hbitmap); (*bitmap)->image.picture = NULL;
IPicture_get_CurDC((*bitmap)->image.picture, &(*bitmap)->hdc); (*bitmap)->hbitmap = hbitmap;
(*bitmap)->hdc = NULL;
return Ok; return Ok;
} }
...@@ -793,7 +818,8 @@ GpStatus WINGDIPAPI GdipDisposeImage(GpImage *image) ...@@ -793,7 +818,8 @@ GpStatus WINGDIPAPI GdipDisposeImage(GpImage *image)
if(!image) if(!image)
return InvalidParameter; return InvalidParameter;
IPicture_Release(image->picture); if (image->picture)
IPicture_Release(image->picture);
if (image->type == ImageTypeBitmap) if (image->type == ImageTypeBitmap)
{ {
GdipFree(((GpBitmap*)image)->bitmapbits); GdipFree(((GpBitmap*)image)->bitmapbits);
...@@ -1543,8 +1569,6 @@ GpStatus WINGDIPAPI GdipSaveImageToStream(GpImage *image, IStream* stream, ...@@ -1543,8 +1569,6 @@ GpStatus WINGDIPAPI GdipSaveImageToStream(GpImage *image, IStream* stream,
GDIPCONST CLSID* clsid, GDIPCONST EncoderParameters* params) GDIPCONST CLSID* clsid, GDIPCONST EncoderParameters* params)
{ {
GpStatus stat; GpStatus stat;
HRESULT hr;
short type;
HBITMAP hbmp; HBITMAP hbmp;
HBITMAP old_hbmp; HBITMAP old_hbmp;
HDC hdc; HDC hdc;
...@@ -1566,11 +1590,7 @@ GpStatus WINGDIPAPI GdipSaveImageToStream(GpImage *image, IStream* stream, ...@@ -1566,11 +1590,7 @@ GpStatus WINGDIPAPI GdipSaveImageToStream(GpImage *image, IStream* stream,
if(!image || !stream) if(!image || !stream)
return InvalidParameter; return InvalidParameter;
if (!image->picture) if (image->type != ImageTypeBitmap)
return GenericError;
hr = IPicture_get_Type(image->picture, &type);
if (FAILED(hr) || type != PICTYPE_BITMAP)
return GenericError; return GenericError;
/* select correct encoder */ /* select correct encoder */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment