[PATCH] GDI+: Implement GdipGetImageEncoders.

Nathan Beckmann nathan.beckmann at gmail.com
Wed Mar 5 13:21:37 CST 2008


Implement helper GdipGetImageEncodersSize.

Also included tests.
---
 dlls/gdiplus/gdiplus.spec  |    4 +-
 dlls/gdiplus/image.c       |   87 ++++++++++++++++++++++++++++++++++++++++++++
 dlls/gdiplus/tests/image.c |   53 +++++++++++++++++++++++++++
 include/gdiplusenums.h     |   13 +++++++
 include/gdiplusflat.h      |    2 +
 include/gdiplusimaging.h   |   35 ++++++++++++++++++
 6 files changed, 192 insertions(+), 2 deletions(-)

diff --git a/dlls/gdiplus/gdiplus.spec b/dlls/gdiplus/gdiplus.spec
index b4f314a..a477086 100644
--- a/dlls/gdiplus/gdiplus.spec
+++ b/dlls/gdiplus/gdiplus.spec
@@ -284,8 +284,8 @@
 @ stub GdipGetImageDecoders
 @ stub GdipGetImageDecodersSize
 @ stdcall GdipGetImageDimension(ptr ptr ptr)
-@ stub GdipGetImageEncoders
-@ stub GdipGetImageEncodersSize
+@ stdcall GdipGetImageEncoders(long long ptr)
+@ stdcall GdipGetImageEncodersSize(ptr ptr)
 @ stub GdipGetImageFlags
 @ stdcall GdipGetImageGraphicsContext(ptr ptr)
 @ stdcall GdipGetImageHeight(ptr ptr)
diff --git a/dlls/gdiplus/image.c b/dlls/gdiplus/image.c
index 5871209..330d90f 100644
--- a/dlls/gdiplus/image.c
+++ b/dlls/gdiplus/image.c
@@ -831,3 +831,90 @@ GpStatus WINGDIPAPI GdipSetImagePalette(GpImage *image,
 
     return NotImplemented;
 }
+
+/*************************************************************************
+ * Encoders -
+ *   Implemented as dummy objects that let the user know which files are
+ *   supported. Actual encoding is done by OLE.
+ *
+ *   This code is based heavily on libgdiplus (Mono):
+ */
+
+typedef enum {
+    BMP,
+    ICO,
+} ImageFormat;
+
+#define NUM_ENCODERS_SUPPORTED 2
+
+/* 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 */
+static const WCHAR bmp_mimetype[] = {'i', 'm', 'a','g', 'e', '/', 'b', 'm', 'p', 0}; /* image/bmp */
+static const WCHAR bmp_format[] = {'B', 'M', 'P', 0}; /* BMP */
+static const BYTE bmp_sig_pattern[] = { 0x42, 0x4D };
+static const BYTE bmp_sig_mask[] = { 0xFF, 0xFF };
+
+static const WCHAR ico_codecname[] = {'B', 'u', 'i','l', 't', '-','i', 'n', ' ', 'I', 'C', 'O', 0}; /* Built-in ICO */
+static const WCHAR ico_extension[] = {'*','.','I', 'C', 'O', 0}; /* *.ICO */
+static const WCHAR ico_mimetype[] = {'i', 'm', 'a','g', 'e', '/', 'x', '-', 'i', 'c', 'o', 'n', 0}; /* image/x-icon */
+static const WCHAR ico_format[] = {'I', 'C', 'O', 0}; /* ICO */
+static const BYTE ico_sig_pattern[] = { 0x00, 0x00, 0x01, 0x00 };
+static const BYTE ico_sig_mask[] = { 0xFF, 0xFF, 0xFF, 0xFF };
+
+static const ImageCodecInfo codecs[NUM_ENCODERS_SUPPORTED] =
+    {
+        { /* BMP */
+            /* Clsid */              { 0x557cf400, 0x1a04, 0x11d3, { 0x9a, 0x73, 0x0, 0x0, 0xf8, 0x1e, 0xf3, 0x2e } },
+            /* FormatID */           { 0xb96b3cabU, 0x0728U, 0x11d3U, {0x9d, 0x7b, 0x00, 0x00, 0xf8, 0x1e, 0xf3, 0x2e} },
+            /* CodecName */          (const WCHAR*) bmp_codecname,
+            /* DllName */            NULL,
+            /* FormatDescription */  (const WCHAR*) bmp_format,
+            /* FilenameExtension */  (const WCHAR*) bmp_extension,
+            /* MimeType */           (const WCHAR*) bmp_mimetype,
+            /* Flags */              ImageCodecFlagsEncoder | ImageCodecFlagsDecoder | ImageCodecFlagsSupportBitmap | ImageCodecFlagsBuiltin,
+            /* Version */            1,
+            /* SigCount */           1,
+            /* SigSize */            2,
+            /* SigPattern */         (const BYTE*) bmp_sig_pattern,
+            /* SigMask */            (const BYTE*) bmp_sig_mask,
+        },
+        { /* ICO */
+            /* Clsid */              { 0x557cf407, 0x1a04, 0x11d3, { 0x9a, 0x73, 0x0, 0x0, 0xf8, 0x1e, 0xf3, 0x2e } },
+            /* FormatID */           { 0xb96b3cb5U, 0x0728U, 0x11d3U, {0x9d, 0x7b, 0x00, 0x00, 0xf8, 0x1e, 0xf3, 0x2e} },
+            /* CodecName */          (const WCHAR*) ico_codecname,
+            /* DllName */            NULL,
+            /* FormatDescription */  (const WCHAR*) ico_format,
+            /* FilenameExtension */  (const WCHAR*) ico_extension,
+            /* MimeType */           (const WCHAR*) ico_mimetype,
+            /* Flags */              ImageCodecFlagsDecoder | ImageCodecFlagsSupportBitmap | ImageCodecFlagsBuiltin,
+            /* Version */            1,
+            /* SigCount */           1,
+            /* SigSize */            4,
+            /* SigPattern */         (const BYTE*) ico_sig_pattern,
+            /* SigMask */            (const BYTE*) ico_sig_mask,
+        },
+    };
+
+GpStatus WINGDIPAPI GdipGetImageEncodersSize(UINT *numEncoders, UINT *size)
+{
+    if (!numEncoders || !size)
+        return InvalidParameter;
+
+    *numEncoders = NUM_ENCODERS_SUPPORTED;
+    *size = sizeof (codecs);
+
+    return Ok;
+}
+
+GpStatus WINGDIPAPI GdipGetImageEncoders(UINT numEncoders, UINT size, ImageCodecInfo *encoders)
+{
+    if (!encoders || 
+        (numEncoders != NUM_ENCODERS_SUPPORTED) || 
+        (size != sizeof (codecs)))
+        return InvalidParameter;
+
+    memcpy(encoders, codecs, sizeof (codecs));
+
+    return Ok;
+}
diff --git a/dlls/gdiplus/tests/image.c b/dlls/gdiplus/tests/image.c
index 5ff164d..5f75c15 100644
--- a/dlls/gdiplus/tests/image.c
+++ b/dlls/gdiplus/tests/image.c
@@ -122,6 +122,58 @@ static void test_LoadingImages(void)
     expect(InvalidParameter, stat);
 }
 
+static void test_encoders(void)
+{
+    GpStatus stat;
+    UINT n;
+    UINT s;
+    ImageCodecInfo *codecs;
+    int i;
+    int bmp_found;
+
+    static const WCHAR bmp_format[] = {'B', 'M', 'P', 0};
+
+    stat = GdipGetImageEncodersSize(NULL, NULL);
+    expect(stat, InvalidParameter);
+
+    stat = GdipGetImageEncodersSize(&n, &s);
+    expect(stat, Ok);
+
+    codecs = GdipAlloc(sizeof(ImageCodecInfo) * n);
+    if (!codecs)
+        return;
+    
+    stat = GdipGetImageEncoders(n, s, NULL);
+    expect(stat, InvalidParameter);
+
+    stat = GdipGetImageEncoders(0, s, codecs);
+    expect(stat, InvalidParameter);
+
+    stat = GdipGetImageEncoders(n, s-1, codecs);
+    expect(stat, InvalidParameter);
+
+    stat = GdipGetImageEncoders(n, s+1, codecs);
+    expect(stat, InvalidParameter);
+
+    stat = GdipGetImageEncoders(n, s, codecs);
+    expect(stat, Ok);
+
+    bmp_found = FALSE;
+    for (i = 0; i < n; i++)
+        {
+            if (CompareStringW(LOCALE_SYSTEM_DEFAULT, 0, 
+                               codecs[i].FormatDescription, -1, 
+                               bmp_format, -1) == CSTR_EQUAL) {
+                bmp_found = TRUE;
+                break;
+            }
+        }
+    if (!bmp_found)
+        ok(FALSE, "No BMP codec found.\n");
+
+    GdipFree(codecs);
+}
+
 START_TEST(image)
 {
     struct GdiplusStartupInput gdiplusStartupInput;
@@ -137,6 +189,7 @@ START_TEST(image)
     test_Scan0();
     test_GetImageDimension();
     test_LoadingImages();
+    test_encoders();
 
     GdiplusShutdown(gdiplusToken);
 }
diff --git a/include/gdiplusenums.h b/include/gdiplusenums.h
index 7c97005..c579ebe 100644
--- a/include/gdiplusenums.h
+++ b/include/gdiplusenums.h
@@ -257,6 +257,18 @@ enum HotkeyPrefix
     HotkeyPrefixHide   = 2
 };
 
+enum ImageCodecFlags
+{
+    ImageCodecFlagsEncoder		= 1,
+    ImageCodecFlagsDecoder		= 2,
+    ImageCodecFlagsSupportBitmap	= 4,
+    ImageCodecFlagsSupportVector	= 8,
+    ImageCodecFlagsSeekableEncode	= 16,
+    ImageCodecFlagsBlockingDecode	= 32,
+    ImageCodecFlagsBuiltin		= 65536,
+    ImageCodecFlagsSystem	        = 131072,
+    ImageCodecFlagsUser		        = 262144
+};
 
 #ifndef __cplusplus
 
@@ -286,6 +298,7 @@ typedef enum StringTrimming StringTrimming;
 typedef enum StringFormatFlags StringFormatFlags;
 typedef enum HotkeyPrefix HotkeyPrefix;
 typedef enum PenAlignment GpPenAlignment;
+typedef enum ImageCodecFlags ImageCodecFlags;
 
 #endif /* end of c typedefs */
 
diff --git a/include/gdiplusflat.h b/include/gdiplusflat.h
index 1f635ba..b15a4ea 100644
--- a/include/gdiplusflat.h
+++ b/include/gdiplusflat.h
@@ -257,6 +257,8 @@ GpStatus WINGDIPAPI GdipCreateBitmapFromStreamICM(IStream*,GpBitmap**);
 GpStatus WINGDIPAPI GdipDisposeImage(GpImage*);
 GpStatus WINGDIPAPI GdipFindFirstImageItem(GpImage*,ImageItemData*);
 GpStatus WINGDIPAPI GdipFindNextImageItem(GpImage*,ImageItemData*);
+GpStatus WINGDIPAPI GdipGetImageEncodersSize(UINT *numEncoders, UINT *size);
+GpStatus WINGDIPAPI GdipGetImageEncoders(UINT numEncoders, UINT size, ImageCodecInfo *encoders);
 GpStatus WINGDIPAPI GdipGetImageItemData(GpImage*,ImageItemData*);
 GpStatus WINGDIPAPI GdipGetImageBounds(GpImage*,GpRectF*,GpUnit*);
 GpStatus WINGDIPAPI GdipGetImageGraphicsContext(GpImage*,GpGraphics**);
diff --git a/include/gdiplusimaging.h b/include/gdiplusimaging.h
index c78e1b1..a843da1 100644
--- a/include/gdiplusimaging.h
+++ b/include/gdiplusimaging.h
@@ -43,6 +43,24 @@ public:
     EncoderParameter Parameter[1];
 };
 
+class ImageCodecInfo 
+{
+public:
+    CLSID Clsid;
+    GUID  FormatID;
+    const WCHAR* CodecName;
+    const WCHAR* DllName;
+    const WCHAR* FormatDescription;
+    const WCHAR* FilenameExtension;
+    const WCHAR* MimeType;
+    DWORD Flags;
+    DWORD Version;
+    DWORD SigCount;
+    DWORD SigSize;
+    const BYTE* SigPattern;
+    const BYTE* SigMask;
+};
+
 class BitmapData
 {
 public:
@@ -84,6 +102,23 @@ typedef struct EncoderParameters
     EncoderParameter Parameter[1];
 } EncoderParameters;
 
+typedef struct ImageCodecInfo 
+{
+    CLSID Clsid;
+    GUID  FormatID;
+    const WCHAR* CodecName;
+    const WCHAR* DllName;
+    const WCHAR* FormatDescription;
+    const WCHAR* FilenameExtension;
+    const WCHAR* MimeType;
+    DWORD Flags;
+    DWORD Version;
+    DWORD SigCount;
+    DWORD SigSize;
+    const BYTE* SigPattern;
+    const BYTE* SigMask;
+} ImageCodecInfo;
+
 typedef struct BitmapData
 {
     UINT Width;
-- 
1.5.4.2




More information about the wine-patches mailing list