From: Jeff Smith whydoubt@gmail.com
--- dlls/gdiplus/image.c | 53 +++++++++++++++++++++++++++++++++++++- dlls/gdiplus/tests/image.c | 33 +++++++++++++++++++++++- 2 files changed, 84 insertions(+), 2 deletions(-)
diff --git a/dlls/gdiplus/image.c b/dlls/gdiplus/image.c index 599f576ca4d..4837b4b1a3f 100644 --- a/dlls/gdiplus/image.c +++ b/dlls/gdiplus/image.c @@ -3577,6 +3577,49 @@ static HRESULT png_read_chromaticity(IWICMetadataReader *reader, GpBitmap *bitma return S_OK; }
+static HRESULT png_read_time(IWICMetadataReader *reader, GpBitmap *bitmap) +{ + HRESULT hr; + UINT item_size, i; + PropertyItem* item; + PROPVARIANT value; + USHORT datetime[6]; + + for (i = 0; i < 6; i++) + { + hr = IWICMetadataReader_GetValueByIndex(reader, i, NULL, NULL, &value); + if (FAILED(hr)) + return hr; + if (i == 0 && value.vt == VT_UI2) + datetime[0] = value.uiVal; + else if (i > 0 && value.vt == VT_UI1) + datetime[i] = value.bVal; + else + { + PropVariantClear(&value); + return E_FAIL; + } + PropVariantClear(&value); + } + + item_size = 20; + item = heap_alloc_zero(sizeof(*item) + item_size); + if (!item) + return E_OUTOFMEMORY; + + item->id = PropertyTagDateTime; + item->type = PropertyTagTypeASCII; + item->length = item_size; + item->value = item + 1; + snprintf(item->value, item_size, "%04u:%02u:%02u %02u:%02u:%02u", + datetime[0], datetime[1], datetime[2], datetime[3], datetime[4], datetime[5]); + + add_property(bitmap, item); + heap_free(item); + + return S_OK; +} + static HRESULT png_add_unit_properties(IWICBitmapFrameDecode *frame, GpBitmap *bitmap) { HRESULT hr; @@ -3632,7 +3675,7 @@ static void png_metadata_reader(GpBitmap *bitmap, IWICBitmapDecoder *decoder, UI IWICBitmapFrameDecode *frame; IWICMetadataBlockReader *block_reader; UINT block_count, i; - BOOL seen_gamma=FALSE, seen_whitepoint=FALSE, seen_chrm=FALSE; + BOOL seen_gamma=FALSE, seen_whitepoint=FALSE, seen_chrm=FALSE, seen_time=FALSE; BOOL *seen_text = NULL;
hr = IWICBitmapDecoder_GetFrame(decoder, active_frame, &frame); @@ -3693,6 +3736,14 @@ static void png_metadata_reader(GpBitmap *bitmap, IWICBitmapDecoder *decoder, UI seen_chrm = SUCCEEDED(hr); } } + else if (IsEqualGUID(&GUID_MetadataFormatChunktIME, &format)) + { + if (!seen_time) + { + hr = png_read_time(reader, bitmap); + seen_time = SUCCEEDED(hr); + } + }
IWICMetadataReader_Release(reader); } diff --git a/dlls/gdiplus/tests/image.c b/dlls/gdiplus/tests/image.c index 5eb35ec85ad..b240e58ba43 100644 --- a/dlls/gdiplus/tests/image.c +++ b/dlls/gdiplus/tests/image.c @@ -3877,7 +3877,7 @@ static void test_image_properties(void)
status = GdipGetPropertyCount(image, &prop_count); ok(status == Ok, "GdipGetPropertyCount error %d\n", status); - todo_wine_if(td[i].image_data == pngimage || td[i].image_data == jpgimage) + todo_wine_if(td[i].image_data == jpgimage) ok(td[i].prop_count == prop_count || (td[i].prop_count2 != ~0 && td[i].prop_count2 == prop_count), "expected property count %u or %u, got %u\n", td[i].prop_count, td[i].prop_count2, prop_count); @@ -5802,6 +5802,14 @@ static const BYTE png_phys[] = { 0x00,0x00,0x00,0x00,'I','E','N','D',0xae,0x42,0x60,0x82 };
+static const BYTE png_time[] = { + 0x89,'P','N','G',0x0d,0x0a,0x1a,0x0a, + 0x00,0x00,0x00,0x0d,'I','H','D','R',0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x08,0x02,0x00,0x00,0x00,0x90,0x77,0x53,0xde, + 0x00,0x00,0x00,0x07,'t','I','M','E',0x07,0xb2,0x01,0x01,0x00,0x00,0x00,0xff,0xff,0xff,0xff, + 0x00,0x00,0x00,0x0c,'I','D','A','T',0x08,0xd7,0x63,0xf8,0xff,0xff,0x3f,0x00,0x05,0xfe,0x02,0xfe,0xdc,0xcc,0x59,0xe7, + 0x00,0x00,0x00,0x00,'I','E','N','D',0xae,0x42,0x60,0x82 +}; + static void test_png_unit_properties(void) { GpImage *image; @@ -5880,6 +5888,28 @@ static void test_png_unit_properties(void) } }
+static void test_png_datetime_property(void) +{ + struct property_test_data td[] = + { + { PropertyTagTypeASCII, PropertyTagDateTime, 20, { "1970:01:01 00:00:00" } }, + { PropertyTagTypeByte, PropertyTagPixelUnit, 1, { 1 } }, + { PropertyTagTypeLong, PropertyTagPixelPerUnitX, 4, { 0,0,0,0 } }, + { PropertyTagTypeLong, PropertyTagPixelPerUnitY, 4, { 0,0,0,0 } }, + }; + + GpImage *image = load_image(png_time, sizeof(png_time), TRUE, FALSE); + ok(image != NULL, "Failed to load PNG image data\n"); + if (!image) + return; + + winetest_push_context("%s", __FUNCTION__); + check_properties_get_all(image, td, ARRAY_SIZE(td), td, 1, ~0); + winetest_pop_context(); + + GdipDisposeImage(image); +} + static void test_GdipLoadImageFromStream(void) { IStream *stream; @@ -6125,6 +6155,7 @@ START_TEST(image) test_png_color_formats(); test_png_save_palette(); test_png_unit_properties(); + test_png_datetime_property(); test_supported_encoders(); test_CloneBitmapArea(); test_ARGB_conversion();