[3/3] gdiplus: Add an ability to cache bitmap properties and use distinct metadata loaders for different image formats.

Dmitry Timoshkov dmitry at baikal.ru
Thu Sep 20 03:47:48 CDT 2012


---
 dlls/gdiplus/gdiplus_private.h |   2 +
 dlls/gdiplus/image.c           | 106 +++++++++++++++++++++++++++++++++++++----
 2 files changed, 100 insertions(+), 8 deletions(-)

diff --git a/dlls/gdiplus/gdiplus_private.h b/dlls/gdiplus/gdiplus_private.h
index d44c969..53f978c 100644
--- a/dlls/gdiplus/gdiplus_private.h
+++ b/dlls/gdiplus/gdiplus_private.h
@@ -311,6 +311,8 @@ struct GpBitmap{
     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. */
     IWICMetadataReader *metadata_reader; /* NULL if there is no metadata */
+    UINT prop_count;
+    PropertyItem *prop_item; /* cached image properties */
 };
 
 struct GpCachedBitmap{
diff --git a/dlls/gdiplus/image.c b/dlls/gdiplus/image.c
index b657969..4068458 100644
--- a/dlls/gdiplus/image.c
+++ b/dlls/gdiplus/image.c
@@ -1911,6 +1911,8 @@ GpStatus WINGDIPAPI GdipCreateBitmapFromScan0(INT width, INT height, INT stride,
     (*bitmap)->stride = stride;
     (*bitmap)->own_bits = own_bits;
     (*bitmap)->metadata_reader = NULL;
+    (*bitmap)->prop_count = 0;
+    (*bitmap)->prop_item = NULL;
 
     /* set format-related flags */
     if (format & (PixelFormatAlpha|PixelFormatPAlpha|PixelFormatIndexed))
@@ -2123,6 +2125,8 @@ static void move_bitmap(GpBitmap *dst, GpBitmap *src, BOOL clobber_palette)
     if (dst->metadata_reader)
         IWICMetadataReader_Release(dst->metadata_reader);
     dst->metadata_reader = src->metadata_reader;
+    dst->prop_count = src->prop_count;
+    dst->prop_item = src->prop_item;
     if (dst->image.stream)
         IStream_Release(dst->image.stream);
     dst->image.stream = src->image.stream;
@@ -2147,6 +2151,7 @@ static GpStatus free_image_data(GpImage *image)
         DeleteObject(((GpBitmap*)image)->hbitmap);
         if (((GpBitmap*)image)->metadata_reader)
             IWICMetadataReader_Release(((GpBitmap*)image)->metadata_reader);
+        GdipFree(((GpBitmap*)image)->prop_item);
     }
     else if (image->type == ImageTypeMetafile)
     {
@@ -2509,6 +2514,12 @@ GpStatus WINGDIPAPI GdipGetPropertyCount(GpImage *image, UINT *num)
 
     if (image->type == ImageTypeBitmap)
     {
+        if (((GpBitmap *)image)->prop_item)
+        {
+            *num = ((GpBitmap *)image)->prop_count;
+            return Ok;
+        }
+
         if (((GpBitmap *)image)->metadata_reader)
             IWICMetadataReader_GetCount(((GpBitmap *)image)->metadata_reader, num);
     }
@@ -2533,6 +2544,18 @@ GpStatus WINGDIPAPI GdipGetPropertyIdList(GpImage *image, UINT num, PROPID *list
         return NotImplemented;
     }
 
+    if (((GpBitmap *)image)->prop_item)
+    {
+        if (num != ((GpBitmap *)image)->prop_count) return InvalidParameter;
+
+        for (i = 0; i < num; i++)
+        {
+            list[i] = ((GpBitmap *)image)->prop_item[i].id;
+        }
+
+        return Ok;
+    }
+
     reader = ((GpBitmap *)image)->metadata_reader;
     if (!reader)
     {
@@ -2621,6 +2644,22 @@ GpStatus WINGDIPAPI GdipGetPropertyItemSize(GpImage *image, PROPID propid, UINT
         return NotImplemented;
     }
 
+    if (((GpBitmap *)image)->prop_item)
+    {
+        UINT i;
+
+        for (i = 0; i < ((GpBitmap *)image)->prop_count; i++)
+        {
+            if (propid == ((GpBitmap *)image)->prop_item[i].id)
+            {
+                *size = sizeof(PropertyItem) + ((GpBitmap *)image)->prop_item[i].length;
+                return Ok;
+            }
+        }
+
+        return PropertyNotFound;
+    }
+
     reader = ((GpBitmap *)image)->metadata_reader;
     if (!reader) return PropertyNotFound;
 
@@ -2753,6 +2792,27 @@ GpStatus WINGDIPAPI GdipGetPropertyItem(GpImage *image, PROPID propid, UINT size
         return NotImplemented;
     }
 
+    if (((GpBitmap *)image)->prop_item)
+    {
+        UINT i;
+
+        for (i = 0; i < ((GpBitmap *)image)->prop_count; i++)
+        {
+            if (propid == ((GpBitmap *)image)->prop_item[i].id)
+            {
+                if (size != sizeof(PropertyItem) + ((GpBitmap *)image)->prop_item[i].length)
+                    return InvalidParameter;
+
+                *buffer = ((GpBitmap *)image)->prop_item[i];
+                buffer->value = buffer + 1;
+                memcpy(buffer->value, ((GpBitmap *)image)->prop_item[i].value, ((GpBitmap *)image)->prop_item[i].length);
+                return Ok;
+            }
+        }
+
+        return PropertyNotFound;
+    }
+
     reader = ((GpBitmap *)image)->metadata_reader;
     if (!reader) return PropertyNotFound;
 
@@ -2785,6 +2845,19 @@ GpStatus WINGDIPAPI GdipGetPropertySize(GpImage *image, UINT *size, UINT *count)
         return NotImplemented;
     }
 
+    if (((GpBitmap *)image)->prop_item)
+    {
+        *count = ((GpBitmap *)image)->prop_count;
+        *size = 0;
+
+        for (i = 0; i < ((GpBitmap *)image)->prop_count; i++)
+        {
+            *size += sizeof(PropertyItem) + ((GpBitmap *)image)->prop_item[i].length;
+        }
+
+        return Ok;
+    }
+
     reader = ((GpBitmap *)image)->metadata_reader;
     if (!reader) return PropertyNotFound;
 
@@ -2850,6 +2923,12 @@ GpStatus WINGDIPAPI GdipGetAllPropertyItems(GpImage *image, UINT size,
 
     if (prop_count != count || prop_size != size) return InvalidParameter;
 
+    if (((GpBitmap *)image)->prop_item)
+    {
+        memcpy(buf, ((GpBitmap *)image)->prop_item, prop_size);
+        return Ok;
+    }
+
     reader = ((GpBitmap *)image)->metadata_reader;
     if (!reader) return PropertyNotFound;
 
@@ -3011,7 +3090,15 @@ GpStatus WINGDIPAPI GdipLoadImageFromFileICM(GDIPCONST WCHAR* filename,GpImage *
     return GdipLoadImageFromFile(filename, image);
 }
 
-static GpStatus decode_image_wic(IStream* stream, REFCLSID clsid, UINT active_frame, GpImage **image)
+static GpStatus gif_metadata_reader(GpBitmap *bitmap, IWICBitmapDecoder *decoder, UINT frame)
+{
+    return Ok;
+}
+
+typedef GpStatus (*metadata_reader_func)(GpBitmap *bitmap, IWICBitmapDecoder *decoder, UINT frame);
+
+static GpStatus decode_image_wic(IStream *stream, GDIPCONST CLSID *clsid,
+    UINT active_frame, metadata_reader_func metadata_reader, GpImage **image)
 {
     GpStatus status=Ok;
     GpBitmap *bitmap;
@@ -3126,7 +3213,10 @@ static GpStatus decode_image_wic(IStream* stream, REFCLSID clsid, UINT active_fr
 
         if (SUCCEEDED(hr)) {
             bitmap->metadata_reader = NULL;
-            if (IWICBitmapFrameDecode_QueryInterface(frame, &IID_IWICMetadataBlockReader, (void **)&block_reader) == S_OK)
+
+            if (metadata_reader)
+                metadata_reader(bitmap, decoder, active_frame);
+            else if (IWICBitmapFrameDecode_QueryInterface(frame, &IID_IWICMetadataBlockReader, (void **)&block_reader) == S_OK)
             {
                 UINT block_count = 0;
                 if (IWICMetadataBlockReader_GetCount(block_reader, &block_count) == S_OK && block_count)
@@ -3172,7 +3262,7 @@ end:
 
 static GpStatus decode_image_icon(IStream* stream, REFCLSID clsid, UINT active_frame, GpImage **image)
 {
-    return decode_image_wic(stream, &CLSID_WICIcoDecoder, active_frame, image);
+    return decode_image_wic(stream, &CLSID_WICIcoDecoder, active_frame, NULL, image);
 }
 
 static GpStatus decode_image_bmp(IStream* stream, REFCLSID clsid, UINT active_frame, GpImage **image)
@@ -3180,7 +3270,7 @@ static GpStatus decode_image_bmp(IStream* stream, REFCLSID clsid, UINT active_fr
     GpStatus status;
     GpBitmap* bitmap;
 
-    status = decode_image_wic(stream, &CLSID_WICBmpDecoder, active_frame, image);
+    status = decode_image_wic(stream, &CLSID_WICBmpDecoder, active_frame, NULL, image);
 
     bitmap = (GpBitmap*)*image;
 
@@ -3195,22 +3285,22 @@ static GpStatus decode_image_bmp(IStream* stream, REFCLSID clsid, UINT active_fr
 
 static GpStatus decode_image_jpeg(IStream* stream, REFCLSID clsid, UINT active_frame, GpImage **image)
 {
-    return decode_image_wic(stream, &CLSID_WICJpegDecoder, active_frame, image);
+    return decode_image_wic(stream, &CLSID_WICJpegDecoder, active_frame, NULL, image);
 }
 
 static GpStatus decode_image_png(IStream* stream, REFCLSID clsid, UINT active_frame, GpImage **image)
 {
-    return decode_image_wic(stream, &CLSID_WICPngDecoder, active_frame, image);
+    return decode_image_wic(stream, &CLSID_WICPngDecoder, active_frame, NULL, image);
 }
 
 static GpStatus decode_image_gif(IStream* stream, REFCLSID clsid, UINT active_frame, GpImage **image)
 {
-    return decode_image_wic(stream, &CLSID_WICGifDecoder, active_frame, image);
+    return decode_image_wic(stream, &CLSID_WICGifDecoder, active_frame, gif_metadata_reader, image);
 }
 
 static GpStatus decode_image_tiff(IStream* stream, REFCLSID clsid, UINT active_frame, GpImage **image)
 {
-    return decode_image_wic(stream, &CLSID_WICTiffDecoder, active_frame, image);
+    return decode_image_wic(stream, &CLSID_WICTiffDecoder, active_frame, NULL, image);
 }
 
 static GpStatus decode_image_olepicture_metafile(IStream* stream, REFCLSID clsid, UINT active_frame, GpImage **image)
-- 
1.7.11.6




More information about the wine-patches mailing list