[PATCH 3/5] gdiplus: Implement GdipSaveImageToStream using encoders.

Nathan Beckmann nathan.beckmann at gmail.com
Mon Mar 10 10:16:55 CDT 2008


Add the correct framework for a fully-functional implementation of
image encoding (not a hack like before). Currently, only a stub for
BMP encoding is supported.

New tests added as well.
---
 dlls/gdiplus/image.c       |   87 ++++++++++++++++++++++++++++++++++++++++----
 dlls/gdiplus/tests/image.c |    8 +++--
 2 files changed, 84 insertions(+), 11 deletions(-)

diff --git a/dlls/gdiplus/image.c b/dlls/gdiplus/image.c
index db19cae..2699418 100644
--- a/dlls/gdiplus/image.c
+++ b/dlls/gdiplus/image.c
@@ -834,17 +834,93 @@ GpStatus WINGDIPAPI GdipSaveImageToFile(GpImage *image, GDIPCONST WCHAR* filenam
     return stat;
 }
 
+/*************************************************************************
+ * Encoding functions -
+ *   These functions encode an image in different image file formats.
+ */
+static GpStatus encode_image_BMP(LPVOID bitmap_bits, LPBITMAPINFO bitmap_info,
+                                 void **output, unsigned int *output_size)
+{
+    return NotImplemented;
+}
+
+typedef GpStatus encode_image_func(LPVOID bitmap_bits, LPBITMAPINFO bitmap_info,
+                                   void **output, unsigned int *output_size);
+
+typedef enum {
+    BMP,
+    NUM_ENCODERS_SUPPORTED
+} ImageFormat;
+
+static const ImageCodecInfo codecs[NUM_ENCODERS_SUPPORTED];
+static encode_image_func *const encode_image_funcs[NUM_ENCODERS_SUPPORTED] = {
+    encode_image_BMP,
+};
+
 GpStatus WINGDIPAPI GdipSaveImageToStream(GpImage *image, IStream* stream,
     GDIPCONST CLSID* clsid, GDIPCONST EncoderParameters* params)
 {
+    GpStatus stat;
+    HRESULT hr;
+    short type;
+    HBITMAP hbmp;
+    HDC hdc;
+    BITMAPINFO bmp_info;
+    LPVOID bmp_bits;
+    encode_image_func* encode_image;
+    LPVOID output;
+    unsigned int output_size;
+    unsigned int dummy;
+    int i;
+
+    output = NULL;
+    output_size = 0;
+
     if(!image || !stream)
         return InvalidParameter;
 
-    /* FIXME: CLSID, EncoderParameters not used */
+    if (!image->picture)
+        return GenericError;
+
+    hr = IPicture_get_Type(image->picture, &type);
+    if (FAILED(hr) || type != PICTYPE_BITMAP)
+        return GenericError;
 
-    IPicture_SaveAsFile(image->picture, stream, FALSE, NULL);
+    /* select correct encoder */
+    encode_image = NULL;
+    for (i = 0; i < NUM_ENCODERS_SUPPORTED; i++) {
+        if (IsEqualCLSID(clsid, &codecs[i].Clsid))
+            encode_image = encode_image_funcs[i];
+    }
+    if (encode_image == NULL)
+        return UnknownImageFormat;
 
-    return Ok;
+    /* extract underlying hbitmap representation from the IPicture */
+    hr = IPicture_get_Handle(image->picture, (OLE_HANDLE*)&hbmp);
+    if (FAILED(hr) || !hbmp)
+        return GenericError;
+
+    /* get bits from HBITMAP */
+    hdc = GetDC(0);
+    bmp_info.bmiHeader.biSize = sizeof(bmp_info.bmiHeader);
+    GetDIBits(hdc, hbmp, 0, 0, NULL, &bmp_info, DIB_RGB_COLORS);
+
+    bmp_bits = GdipAlloc(bmp_info.bmiHeader.biSizeImage);
+    if (!bmp_bits) {
+        ReleaseDC(0, hdc);
+        return OutOfMemory;
+    }
+    GetDIBits(hdc, hbmp, 0, bmp_info.bmiHeader.biHeight, bmp_bits, &bmp_info, DIB_RGB_COLORS);
+
+    stat = encode_image(bmp_bits, &bmp_info, &output, &output_size);
+    if (stat == Ok)
+        IStream_Write(stream, output, output_size, &dummy);
+
+    GdipFree(output);
+    GdipFree(bmp_bits);
+    ReleaseDC(0, hdc);
+
+    return stat;
 }
 
 GpStatus WINGDIPAPI GdipSetImagePalette(GpImage *image,
@@ -866,11 +942,6 @@ GpStatus WINGDIPAPI GdipSetImagePalette(GpImage *image,
  *   Structures that represent which formats we support for encoding.
  */
 
-typedef enum {
-    BMP,
-    NUM_ENCODERS_SUPPORTED
-} ImageFormat;
-
 /* ImageCodecInfo creation routines taken from libgdiplus */
 static const WCHAR bmp_codecname[] = {'B', 'u', 'i','l', 't', '-','i', 'n', ' ', 'B', 'M', 'P', 0}; /* Built-in BMP */
 static const WCHAR bmp_extension[] = {'*','.','B', 'M', 'P',';', '*','.', 'D','I', 'B',';', '*','.', 'R', 'L', 'E',0}; /* *.BMP;*.DIB;*.RLE */
diff --git a/dlls/gdiplus/tests/image.c b/dlls/gdiplus/tests/image.c
index 5293ac6..d51636b 100644
--- a/dlls/gdiplus/tests/image.c
+++ b/dlls/gdiplus/tests/image.c
@@ -158,9 +158,11 @@ static void test_SavingImages(void)
         
     stat = GdipGetImageEncoders(n, s, codecs);
     if (stat != Ok) goto cleanup;
-        
-    stat = GdipSaveImageToFile((GpImage*)bm, filename, &codecs[0].Clsid, 0);
-    expect(stat, Ok);
+
+    todo_wine {
+        stat = GdipSaveImageToFile((GpImage*)bm, filename, &codecs[0].Clsid, 0);
+        expect(stat, Ok);
+    }
 
  cleanup:
     if (codecs)
-- 
1.5.4.2




More information about the wine-patches mailing list