gdiplus: Add an ability to cache bitmap properties and use distinct metadata loaders for different image formats.
This commit is contained in:
parent
f39c140a88
commit
915df87aa5
|
@ -311,6 +311,8 @@ struct GpBitmap{
|
||||||
BYTE *own_bits; /* image bits that need to be freed with this object */
|
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. */
|
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 */
|
IWICMetadataReader *metadata_reader; /* NULL if there is no metadata */
|
||||||
|
UINT prop_count;
|
||||||
|
PropertyItem *prop_item; /* cached image properties */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct GpCachedBitmap{
|
struct GpCachedBitmap{
|
||||||
|
|
|
@ -1911,6 +1911,8 @@ GpStatus WINGDIPAPI GdipCreateBitmapFromScan0(INT width, INT height, INT stride,
|
||||||
(*bitmap)->stride = stride;
|
(*bitmap)->stride = stride;
|
||||||
(*bitmap)->own_bits = own_bits;
|
(*bitmap)->own_bits = own_bits;
|
||||||
(*bitmap)->metadata_reader = NULL;
|
(*bitmap)->metadata_reader = NULL;
|
||||||
|
(*bitmap)->prop_count = 0;
|
||||||
|
(*bitmap)->prop_item = NULL;
|
||||||
|
|
||||||
/* set format-related flags */
|
/* set format-related flags */
|
||||||
if (format & (PixelFormatAlpha|PixelFormatPAlpha|PixelFormatIndexed))
|
if (format & (PixelFormatAlpha|PixelFormatPAlpha|PixelFormatIndexed))
|
||||||
|
@ -2123,6 +2125,9 @@ static void move_bitmap(GpBitmap *dst, GpBitmap *src, BOOL clobber_palette)
|
||||||
if (dst->metadata_reader)
|
if (dst->metadata_reader)
|
||||||
IWICMetadataReader_Release(dst->metadata_reader);
|
IWICMetadataReader_Release(dst->metadata_reader);
|
||||||
dst->metadata_reader = src->metadata_reader;
|
dst->metadata_reader = src->metadata_reader;
|
||||||
|
GdipFree(dst->prop_item);
|
||||||
|
dst->prop_item = src->prop_item;
|
||||||
|
dst->prop_count = src->prop_count;
|
||||||
if (dst->image.stream)
|
if (dst->image.stream)
|
||||||
IStream_Release(dst->image.stream);
|
IStream_Release(dst->image.stream);
|
||||||
dst->image.stream = src->image.stream;
|
dst->image.stream = src->image.stream;
|
||||||
|
@ -2147,6 +2152,7 @@ static GpStatus free_image_data(GpImage *image)
|
||||||
DeleteObject(((GpBitmap*)image)->hbitmap);
|
DeleteObject(((GpBitmap*)image)->hbitmap);
|
||||||
if (((GpBitmap*)image)->metadata_reader)
|
if (((GpBitmap*)image)->metadata_reader)
|
||||||
IWICMetadataReader_Release(((GpBitmap*)image)->metadata_reader);
|
IWICMetadataReader_Release(((GpBitmap*)image)->metadata_reader);
|
||||||
|
GdipFree(((GpBitmap*)image)->prop_item);
|
||||||
}
|
}
|
||||||
else if (image->type == ImageTypeMetafile)
|
else if (image->type == ImageTypeMetafile)
|
||||||
{
|
{
|
||||||
|
@ -2509,6 +2515,12 @@ GpStatus WINGDIPAPI GdipGetPropertyCount(GpImage *image, UINT *num)
|
||||||
|
|
||||||
if (image->type == ImageTypeBitmap)
|
if (image->type == ImageTypeBitmap)
|
||||||
{
|
{
|
||||||
|
if (((GpBitmap *)image)->prop_item)
|
||||||
|
{
|
||||||
|
*num = ((GpBitmap *)image)->prop_count;
|
||||||
|
return Ok;
|
||||||
|
}
|
||||||
|
|
||||||
if (((GpBitmap *)image)->metadata_reader)
|
if (((GpBitmap *)image)->metadata_reader)
|
||||||
IWICMetadataReader_GetCount(((GpBitmap *)image)->metadata_reader, num);
|
IWICMetadataReader_GetCount(((GpBitmap *)image)->metadata_reader, num);
|
||||||
}
|
}
|
||||||
|
@ -2533,6 +2545,18 @@ GpStatus WINGDIPAPI GdipGetPropertyIdList(GpImage *image, UINT num, PROPID *list
|
||||||
return NotImplemented;
|
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;
|
reader = ((GpBitmap *)image)->metadata_reader;
|
||||||
if (!reader)
|
if (!reader)
|
||||||
{
|
{
|
||||||
|
@ -2621,6 +2645,22 @@ GpStatus WINGDIPAPI GdipGetPropertyItemSize(GpImage *image, PROPID propid, UINT
|
||||||
return NotImplemented;
|
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;
|
reader = ((GpBitmap *)image)->metadata_reader;
|
||||||
if (!reader) return PropertyNotFound;
|
if (!reader) return PropertyNotFound;
|
||||||
|
|
||||||
|
@ -2753,6 +2793,27 @@ GpStatus WINGDIPAPI GdipGetPropertyItem(GpImage *image, PROPID propid, UINT size
|
||||||
return NotImplemented;
|
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, buffer->length);
|
||||||
|
return Ok;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return PropertyNotFound;
|
||||||
|
}
|
||||||
|
|
||||||
reader = ((GpBitmap *)image)->metadata_reader;
|
reader = ((GpBitmap *)image)->metadata_reader;
|
||||||
if (!reader) return PropertyNotFound;
|
if (!reader) return PropertyNotFound;
|
||||||
|
|
||||||
|
@ -2785,6 +2846,19 @@ GpStatus WINGDIPAPI GdipGetPropertySize(GpImage *image, UINT *size, UINT *count)
|
||||||
return NotImplemented;
|
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;
|
reader = ((GpBitmap *)image)->metadata_reader;
|
||||||
if (!reader) return PropertyNotFound;
|
if (!reader) return PropertyNotFound;
|
||||||
|
|
||||||
|
@ -2850,6 +2924,21 @@ GpStatus WINGDIPAPI GdipGetAllPropertyItems(GpImage *image, UINT size,
|
||||||
|
|
||||||
if (prop_count != count || prop_size != size) return InvalidParameter;
|
if (prop_count != count || prop_size != size) return InvalidParameter;
|
||||||
|
|
||||||
|
if (((GpBitmap *)image)->prop_item)
|
||||||
|
{
|
||||||
|
memcpy(buf, ((GpBitmap *)image)->prop_item, prop_size);
|
||||||
|
|
||||||
|
item_value = (char *)(buf + prop_count);
|
||||||
|
|
||||||
|
for (i = 0; i < prop_count; i++)
|
||||||
|
{
|
||||||
|
buf[i].value = item_value;
|
||||||
|
item_value += buf[i].length;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Ok;
|
||||||
|
}
|
||||||
|
|
||||||
reader = ((GpBitmap *)image)->metadata_reader;
|
reader = ((GpBitmap *)image)->metadata_reader;
|
||||||
if (!reader) return PropertyNotFound;
|
if (!reader) return PropertyNotFound;
|
||||||
|
|
||||||
|
@ -3011,7 +3100,14 @@ GpStatus WINGDIPAPI GdipLoadImageFromFileICM(GDIPCONST WCHAR* filename,GpImage *
|
||||||
return GdipLoadImageFromFile(filename, image);
|
return GdipLoadImageFromFile(filename, image);
|
||||||
}
|
}
|
||||||
|
|
||||||
static GpStatus decode_image_wic(IStream* stream, REFCLSID clsid, UINT active_frame, GpImage **image)
|
static void gif_metadata_reader(GpBitmap *bitmap, IWICBitmapDecoder *decoder, UINT frame)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef void (*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;
|
GpStatus status=Ok;
|
||||||
GpBitmap *bitmap;
|
GpBitmap *bitmap;
|
||||||
|
@ -3126,7 +3222,10 @@ static GpStatus decode_image_wic(IStream* stream, REFCLSID clsid, UINT active_fr
|
||||||
|
|
||||||
if (SUCCEEDED(hr)) {
|
if (SUCCEEDED(hr)) {
|
||||||
bitmap->metadata_reader = NULL;
|
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;
|
UINT block_count = 0;
|
||||||
if (IWICMetadataBlockReader_GetCount(block_reader, &block_count) == S_OK && block_count)
|
if (IWICMetadataBlockReader_GetCount(block_reader, &block_count) == S_OK && block_count)
|
||||||
|
@ -3172,7 +3271,7 @@ end:
|
||||||
|
|
||||||
static GpStatus decode_image_icon(IStream* stream, REFCLSID clsid, UINT active_frame, GpImage **image)
|
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)
|
static GpStatus decode_image_bmp(IStream* stream, REFCLSID clsid, UINT active_frame, GpImage **image)
|
||||||
|
@ -3180,7 +3279,7 @@ static GpStatus decode_image_bmp(IStream* stream, REFCLSID clsid, UINT active_fr
|
||||||
GpStatus status;
|
GpStatus status;
|
||||||
GpBitmap* bitmap;
|
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;
|
bitmap = (GpBitmap*)*image;
|
||||||
|
|
||||||
|
@ -3195,22 +3294,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)
|
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)
|
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)
|
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)
|
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)
|
static GpStatus decode_image_olepicture_metafile(IStream* stream, REFCLSID clsid, UINT active_frame, GpImage **image)
|
||||||
|
|
Loading…
Reference in New Issue