[WINDOWSCODECS] Sync with Wine Staging 1.7.47. CORE-9924

svn path=/trunk/; revision=68543
This commit is contained in:
Amine Khaldi 2015-07-22 00:45:26 +00:00
parent b8cba24681
commit 9fdfcff1b4
15 changed files with 354 additions and 69 deletions

View file

@ -22,7 +22,7 @@ extern HRESULT WINAPI WIC_DllGetClassObject(REFCLSID, REFIID, LPVOID *) DECLSPEC
typedef struct {
REFCLSID classid;
HRESULT (*constructor)(REFIID,void**);
class_constructor constructor;
} classinfo;
static const classinfo wic_classes[] = {
@ -42,6 +42,7 @@ static const classinfo wic_classes[] = {
{&CLSID_WineTgaDecoder, TgaDecoder_CreateInstance},
{&CLSID_WICUnknownMetadataReader, UnknownMetadataReader_CreateInstance},
{&CLSID_WICIfdMetadataReader, IfdMetadataReader_CreateInstance},
{&CLSID_WICPngGamaMetadataReader, PngGamaReader_CreateInstance},
{&CLSID_WICPngTextMetadataReader, PngTextReader_CreateInstance},
{&CLSID_WICLSDMetadataReader, LSDReader_CreateInstance},
{&CLSID_WICIMDMetadataReader, IMDReader_CreateInstance},
@ -183,3 +184,14 @@ HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID iid, LPVOID *ppv)
TRACE("<-- %08X\n", ret);
return ret;
}
HRESULT create_instance(CLSID *clsid, const IID *iid, void **ppv)
{
int i;
for (i=0; wic_classes[i].classid; i++)
if (IsEqualCLSID(wic_classes[i].classid, clsid))
return wic_classes[i].constructor(iid, ppv);
return CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER, iid, ppv);
}

View file

@ -60,7 +60,7 @@ static HRESULT load_LSD_metadata(IStream *stream, const GUID *vendor, DWORD opti
hr = IStream_Read(stream, &lsd_data, sizeof(lsd_data), &bytesread);
if (FAILED(hr) || bytesread != sizeof(lsd_data)) return S_OK;
result = HeapAlloc(GetProcessHeap(), 0, sizeof(MetadataItem) * 9);
result = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(MetadataItem) * 9);
if (!result) return E_OUTOFMEMORY;
for (i = 0; i < 9; i++)
@ -165,7 +165,7 @@ static HRESULT load_IMD_metadata(IStream *stream, const GUID *vendor, DWORD opti
hr = IStream_Read(stream, &imd_data, sizeof(imd_data), &bytesread);
if (FAILED(hr) || bytesread != sizeof(imd_data)) return S_OK;
result = HeapAlloc(GetProcessHeap(), 0, sizeof(MetadataItem) * 8);
result = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(MetadataItem) * 8);
if (!result) return E_OUTOFMEMORY;
for (i = 0; i < 8; i++)
@ -258,7 +258,7 @@ static HRESULT load_GCE_metadata(IStream *stream, const GUID *vendor, DWORD opti
hr = IStream_Read(stream, &gce_data, sizeof(gce_data), &bytesread);
if (FAILED(hr) || bytesread != sizeof(gce_data)) return S_OK;
result = HeapAlloc(GetProcessHeap(), 0, sizeof(MetadataItem) * 5);
result = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(MetadataItem) * 5);
if (!result) return E_OUTOFMEMORY;
for (i = 0; i < 5; i++)
@ -373,7 +373,7 @@ static HRESULT load_APE_metadata(IStream *stream, const GUID *vendor, DWORD opti
data_size += subblock_size + 1;
}
result = HeapAlloc(GetProcessHeap(), 0, sizeof(MetadataItem) * 2);
result = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(MetadataItem) * 2);
if (!result)
{
HeapFree(GetProcessHeap(), 0, data);
@ -478,7 +478,7 @@ static HRESULT load_GifComment_metadata(IStream *stream, const GUID *vendor, DWO
data[data_size] = 0;
result = HeapAlloc(GetProcessHeap(), 0, sizeof(MetadataItem));
result = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(MetadataItem));
if (!result)
{
HeapFree(GetProcessHeap(), 0, data);
@ -530,7 +530,8 @@ static IStream *create_stream(const void *data, int data_size)
}
static HRESULT create_metadata_reader(const void *data, int data_size,
const CLSID *clsid, IWICMetadataReader **reader)
class_constructor constructor,
IWICMetadataReader **reader)
{
HRESULT hr;
IWICMetadataReader *metadata_reader;
@ -539,8 +540,7 @@ static HRESULT create_metadata_reader(const void *data, int data_size,
/* FIXME: Use IWICComponentFactory_CreateMetadataReader once it's implemented */
hr = CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER,
&IID_IWICMetadataReader, (void **)&metadata_reader);
hr = constructor(&IID_IWICMetadataReader, (void**)&metadata_reader);
if (FAILED(hr)) return hr;
hr = IWICMetadataReader_QueryInterface(metadata_reader, &IID_IWICPersistStream, (void **)&persist);
@ -563,6 +563,7 @@ static HRESULT create_metadata_reader(const void *data, int data_size,
typedef struct {
IWICBitmapDecoder IWICBitmapDecoder_iface;
IWICMetadataBlockReader IWICMetadataBlockReader_iface;
IStream *stream;
BYTE LSD_data[13]; /* Logical Screen Descriptor */
LONG ref;
BOOL initialized;
@ -885,8 +886,7 @@ static HRESULT create_IMD_metadata_reader(GifFrameDecode *This, IWICMetadataRead
/* FIXME: Use IWICComponentFactory_CreateMetadataReader once it's implemented */
hr = CoCreateInstance(&CLSID_WICIMDMetadataReader, NULL, CLSCTX_INPROC_SERVER,
&IID_IWICMetadataReader, (void **)&metadata_reader);
hr = IMDReader_CreateInstance(&IID_IWICMetadataReader, (void **)&metadata_reader);
if (FAILED(hr)) return hr;
hr = IWICMetadataReader_QueryInterface(metadata_reader, &IID_IWICPersistStream, (void **)&persist);
@ -942,7 +942,7 @@ static HRESULT WINAPI GifFrameDecode_Block_GetReaderByIndex(IWICMetadataBlockRea
for (i = 0; i < This->frame->Extensions.ExtensionBlockCount; i++)
{
const CLSID *clsid;
class_constructor constructor;
const void *data;
int data_size;
@ -956,24 +956,24 @@ static HRESULT WINAPI GifFrameDecode_Block_GetReaderByIndex(IWICMetadataBlockRea
}
else if (This->frame->Extensions.ExtensionBlocks[i].Function == COMMENT_EXT_FUNC_CODE)
{
clsid = &CLSID_WICGifCommentMetadataReader;
constructor = GifCommentReader_CreateInstance;
data = This->frame->Extensions.ExtensionBlocks[i].Bytes;
data_size = This->frame->Extensions.ExtensionBlocks[i].ByteCount;
}
else
{
clsid = &CLSID_WICUnknownMetadataReader;
constructor = UnknownMetadataReader_CreateInstance;
data = This->frame->Extensions.ExtensionBlocks[i].Bytes;
data_size = This->frame->Extensions.ExtensionBlocks[i].ByteCount;
}
return create_metadata_reader(data, data_size, clsid, reader);
return create_metadata_reader(data, data_size, constructor, reader);
}
if (gce_index == -1) return E_INVALIDARG;
return create_metadata_reader(This->frame->Extensions.ExtensionBlocks[gce_index].Bytes + 3,
This->frame->Extensions.ExtensionBlocks[gce_index].ByteCount - 4,
&CLSID_WICGCEMetadataReader, reader);
GCEReader_CreateInstance, reader);
}
static HRESULT WINAPI GifFrameDecode_Block_GetEnumerator(IWICMetadataBlockReader *iface,
@ -1040,6 +1040,7 @@ static ULONG WINAPI GifDecoder_Release(IWICBitmapDecoder *iface)
if (ref == 0)
{
IStream_Release(This->stream);
This->lock.DebugInfo->Spare[0] = 0;
DeleteCriticalSection(&This->lock);
DGifCloseFile(This->gif);
@ -1127,6 +1128,9 @@ static HRESULT WINAPI GifDecoder_Initialize(IWICBitmapDecoder *iface, IStream *p
IStream_Seek(pIStream, seek, STREAM_SEEK_SET, NULL);
IStream_Read(pIStream, This->LSD_data, sizeof(This->LSD_data), NULL);
This->stream = pIStream;
IStream_AddRef(This->stream);
This->initialized = TRUE;
LeaveCriticalSection(&This->lock);
@ -1361,24 +1365,24 @@ static HRESULT WINAPI GifDecoder_Block_GetReaderByIndex(IWICMetadataBlockReader
if (index == 0)
return create_metadata_reader(This->LSD_data, sizeof(This->LSD_data),
&CLSID_WICLSDMetadataReader, reader);
LSDReader_CreateInstance, reader);
for (i = 0; i < This->gif->Extensions.ExtensionBlockCount; i++)
{
const CLSID *clsid;
class_constructor constructor;
if (index != i + 1) continue;
if (This->gif->Extensions.ExtensionBlocks[i].Function == APPLICATION_EXT_FUNC_CODE)
clsid = &CLSID_WICAPEMetadataReader;
constructor = APEReader_CreateInstance;
else if (This->gif->Extensions.ExtensionBlocks[i].Function == COMMENT_EXT_FUNC_CODE)
clsid = &CLSID_WICGifCommentMetadataReader;
constructor = GifCommentReader_CreateInstance;
else
clsid = &CLSID_WICUnknownMetadataReader;
constructor = UnknownMetadataReader_CreateInstance;
return create_metadata_reader(This->gif->Extensions.ExtensionBlocks[i].Bytes,
This->gif->Extensions.ExtensionBlocks[i].ByteCount,
clsid, reader);
constructor, reader);
}
return E_INVALIDARG;

View file

@ -162,7 +162,7 @@ static ULONG WINAPI IcnsFrameEncode_Release(IWICBitmapFrameEncode *iface)
if (This->icns_image != NULL)
HeapFree(GetProcessHeap(), 0, This->icns_image);
IUnknown_Release((IUnknown*)This->encoder);
IWICBitmapEncoder_Release(&This->encoder->IWICBitmapEncoder_iface);
HeapFree(GetProcessHeap(), 0, This);
}
@ -380,7 +380,7 @@ static HRESULT WINAPI IcnsFrameEncode_WriteSource(IWICBitmapFrameEncode *iface,
if (!This->initialized)
return WINCODEC_ERR_WRONGSTATE;
hr = configure_write_source(iface, pIBitmapSource, &prc,
hr = configure_write_source(iface, pIBitmapSource, prc,
&GUID_WICPixelFormat32bppBGRA, This->size, This->size,
1.0, 1.0);
@ -472,7 +472,7 @@ static HRESULT WINAPI IcnsEncoder_QueryInterface(IWICBitmapEncoder *iface, REFII
if (IsEqualIID(&IID_IUnknown, iid) ||
IsEqualIID(&IID_IWICBitmapEncoder, iid))
{
*ppv = This;
*ppv = &This->IWICBitmapEncoder_iface;
}
else
{
@ -622,7 +622,7 @@ static HRESULT WINAPI IcnsEncoder_CreateNewFrame(IWICBitmapEncoder *iface,
frameEncode->committed = FALSE;
*ppIFrameEncode = &frameEncode->IWICBitmapFrameEncode_iface;
This->outstanding_commits++;
IUnknown_AddRef((IUnknown*)This);
IWICBitmapEncoder_AddRef(&This->IWICBitmapEncoder_iface);
end:
LeaveCriticalSection(&This->lock);
@ -708,8 +708,8 @@ HRESULT IcnsEncoder_CreateInstance(REFIID iid, void** ppv)
InitializeCriticalSection(&This->lock);
This->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": IcnsEncoder.lock");
ret = IUnknown_QueryInterface((IUnknown*)This, iid, ppv);
IUnknown_Release((IUnknown*)This);
ret = IWICBitmapEncoder_QueryInterface(&This->IWICBitmapEncoder_iface, iid, ppv);
IWICBitmapEncoder_Release(&This->IWICBitmapEncoder_iface);
return ret;
}

View file

@ -694,7 +694,7 @@ static HRESULT WINAPI ComponentFactory_CreateBitmapFromHBITMAP(IWICComponentFact
return E_INVALIDARG;
}
hr = BitmapImpl_Create(bm.bmWidth, bm.bmHeight, bm.bmWidthBytes, 0, NULL, &format, option, bitmap);
hr = BitmapImpl_Create(bm.bmWidth, bm.bmHeight, bm.bmWidthBytes, 0, NULL, &format, WICBitmapCacheOnLoad, bitmap);
if (hr != S_OK) return hr;
hr = IWICBitmap_Lock(*bitmap, NULL, WICBitmapLockWrite, &lock);

View file

@ -213,7 +213,7 @@ static HRESULT WINAPI BitmapDecoderInfo_QueryInterface(IWICBitmapDecoderInfo *if
IsEqualIID(&IID_IWICBitmapCodecInfo, iid) ||
IsEqualIID(&IID_IWICBitmapDecoderInfo ,iid))
{
*ppv = This;
*ppv = &This->IWICBitmapDecoderInfo_iface;
}
else
{
@ -606,8 +606,7 @@ static HRESULT WINAPI BitmapDecoderInfo_CreateInstance(IWICBitmapDecoderInfo *if
TRACE("(%p,%p)\n", iface, ppIBitmapDecoder);
return CoCreateInstance(&This->clsid, NULL, CLSCTX_INPROC_SERVER,
&IID_IWICBitmapDecoder, (void**)ppIBitmapDecoder);
return create_instance(&This->clsid, &IID_IWICBitmapDecoder, (void**)ppIBitmapDecoder);
}
static const IWICBitmapDecoderInfoVtbl BitmapDecoderInfo_Vtbl = {
@ -655,7 +654,7 @@ static HRESULT BitmapDecoderInfo_Constructor(HKEY classkey, REFCLSID clsid, IWIC
This->classkey = classkey;
memcpy(&This->clsid, clsid, sizeof(CLSID));
*ppIInfo = (IWICComponentInfo*)This;
*ppIInfo = (IWICComponentInfo *)&This->IWICBitmapDecoderInfo_iface;
return S_OK;
}
@ -684,7 +683,7 @@ static HRESULT WINAPI BitmapEncoderInfo_QueryInterface(IWICBitmapEncoderInfo *if
IsEqualIID(&IID_IWICBitmapCodecInfo, iid) ||
IsEqualIID(&IID_IWICBitmapEncoderInfo ,iid))
{
*ppv = This;
*ppv = &This->IWICBitmapEncoderInfo_iface;
}
else
{
@ -900,8 +899,7 @@ static HRESULT WINAPI BitmapEncoderInfo_CreateInstance(IWICBitmapEncoderInfo *if
TRACE("(%p,%p)\n", iface, ppIBitmapEncoder);
return CoCreateInstance(&This->clsid, NULL, CLSCTX_INPROC_SERVER,
&IID_IWICBitmapEncoder, (void**)ppIBitmapEncoder);
return create_instance(&This->clsid, &IID_IWICBitmapEncoder, (void**)ppIBitmapEncoder);
}
static const IWICBitmapEncoderInfoVtbl BitmapEncoderInfo_Vtbl = {
@ -947,7 +945,7 @@ static HRESULT BitmapEncoderInfo_Constructor(HKEY classkey, REFCLSID clsid, IWIC
This->classkey = classkey;
memcpy(&This->clsid, clsid, sizeof(CLSID));
*ppIInfo = (IWICComponentInfo*)This;
*ppIInfo = (IWICComponentInfo *)&This->IWICBitmapEncoderInfo_iface;
return S_OK;
}
@ -975,7 +973,7 @@ static HRESULT WINAPI FormatConverterInfo_QueryInterface(IWICFormatConverterInfo
IsEqualIID(&IID_IWICComponentInfo, iid) ||
IsEqualIID(&IID_IWICFormatConverterInfo ,iid))
{
*ppv = This;
*ppv = &This->IWICFormatConverterInfo_iface;
}
else
{
@ -1108,8 +1106,8 @@ static HRESULT WINAPI FormatConverterInfo_CreateInstance(IWICFormatConverterInfo
TRACE("(%p,%p)\n", iface, ppIFormatConverter);
return CoCreateInstance(&This->clsid, NULL, CLSCTX_INPROC_SERVER,
&IID_IWICFormatConverter, (void**)ppIFormatConverter);
return create_instance(&This->clsid, &IID_IWICFormatConverter,
(void**)ppIFormatConverter);
}
static BOOL ConverterSupportsFormat(IWICFormatConverterInfo *iface, const WCHAR *formatguid)
@ -1164,7 +1162,7 @@ static HRESULT FormatConverterInfo_Constructor(HKEY classkey, REFCLSID clsid, IW
This->classkey = classkey;
memcpy(&This->clsid, clsid, sizeof(CLSID));
*ppIInfo = (IWICComponentInfo*)This;
*ppIInfo = (IWICComponentInfo *)&This->IWICFormatConverterInfo_iface;
return S_OK;
}
@ -1193,7 +1191,7 @@ static HRESULT WINAPI PixelFormatInfo_QueryInterface(IWICPixelFormatInfo2 *iface
IsEqualIID(&IID_IWICPixelFormatInfo, iid) ||
IsEqualIID(&IID_IWICPixelFormatInfo2 ,iid))
{
*ppv = This;
*ppv = &This->IWICPixelFormatInfo2_iface;
}
else
{
@ -1458,7 +1456,7 @@ static HRESULT PixelFormatInfo_Constructor(HKEY classkey, REFCLSID clsid, IWICCo
This->classkey = classkey;
memcpy(&This->clsid, clsid, sizeof(CLSID));
*ppIInfo = (IWICComponentInfo*)This;
*ppIInfo = (IWICComponentInfo *)&This->IWICPixelFormatInfo2_iface;
return S_OK;
}
@ -1489,7 +1487,7 @@ static HRESULT WINAPI MetadataReaderInfo_QueryInterface(IWICMetadataReaderInfo *
IsEqualIID(&IID_IWICMetadataHandlerInfo, riid) ||
IsEqualIID(&IID_IWICMetadataReaderInfo, riid))
{
*ppv = This;
*ppv = &This->IWICMetadataReaderInfo_iface;
}
else
{
@ -1854,8 +1852,7 @@ static HRESULT WINAPI MetadataReaderInfo_CreateInstance(IWICMetadataReaderInfo *
TRACE("(%p,%p)\n", iface, reader);
return CoCreateInstance(&This->clsid, NULL, CLSCTX_INPROC_SERVER,
&IID_IWICMetadataReader, (void **)reader);
return create_instance(&This->clsid, &IID_IWICMetadataReader, (void **)reader);
}
static const IWICMetadataReaderInfoVtbl MetadataReaderInfo_Vtbl = {
@ -1898,7 +1895,7 @@ static HRESULT MetadataReaderInfo_Constructor(HKEY classkey, REFCLSID clsid, IWI
This->classkey = classkey;
This->clsid = *clsid;
*info = (IWICComponentInfo *)This;
*info = (IWICComponentInfo *)&This->IWICMetadataReaderInfo_iface;
return S_OK;
}

View file

@ -680,7 +680,7 @@ static HRESULT LoadUnknownMetadata(IStream *input, const GUID *preferred_vendor,
return hr;
}
result = HeapAlloc(GetProcessHeap(), 0, sizeof(MetadataItem));
result = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(MetadataItem));
if (!result)
{
HeapFree(GetProcessHeap(), 0, data);
@ -1110,7 +1110,7 @@ static HRESULT LoadIfdMetadata(IStream *input, const GUID *preferred_vendor,
return WINCODEC_ERR_BADMETADATAHEADER;
}
result = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*result));
result = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, count * sizeof(*result));
if (!result)
{
HeapFree(GetProcessHeap(), 0, entry);

View file

@ -24,6 +24,11 @@
static const WCHAR wszPngInterlaceOption[] = {'I','n','t','e','r','l','a','c','e','O','p','t','i','o','n',0};
static inline ULONG read_ulong_be(BYTE* data)
{
return data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];
}
static HRESULT read_png_chunk(IStream *stream, BYTE *type, BYTE **data, ULONG *data_size)
{
BYTE header[8];
@ -38,7 +43,7 @@ static HRESULT read_png_chunk(IStream *stream, BYTE *type, BYTE **data, ULONG *d
return hr;
}
*data_size = header[0] << 24 | header[1] << 16 | header[2] << 8 | header[3];
*data_size = read_ulong_be(&header[0]);
memcpy(type, &header[4], 4);
@ -92,7 +97,7 @@ static HRESULT LoadTextMetadata(IStream *stream, const GUID *preferred_vendor,
value_len = data_size - name_len - 1;
result = HeapAlloc(GetProcessHeap(), 0, sizeof(MetadataItem));
result = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(MetadataItem));
name = HeapAlloc(GetProcessHeap(), 0, name_len + 1);
value = HeapAlloc(GetProcessHeap(), 0, value_len + 1);
if (!result || !name || !value)
@ -136,6 +141,68 @@ HRESULT PngTextReader_CreateInstance(REFIID iid, void** ppv)
return MetadataReader_Create(&TextReader_Vtbl, iid, ppv);
}
static HRESULT LoadGamaMetadata(IStream *stream, const GUID *preferred_vendor,
DWORD persist_options, MetadataItem **items, DWORD *item_count)
{
HRESULT hr;
BYTE type[4];
BYTE *data;
ULONG data_size;
ULONG gamma;
static const WCHAR ImageGamma[] = {'I','m','a','g','e','G','a','m','m','a',0};
LPWSTR name;
MetadataItem *result;
hr = read_png_chunk(stream, type, &data, &data_size);
if (FAILED(hr)) return hr;
if (data_size < 4)
{
HeapFree(GetProcessHeap(), 0, data);
return E_FAIL;
}
gamma = read_ulong_be(data);
HeapFree(GetProcessHeap(), 0, data);
result = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(MetadataItem));
name = HeapAlloc(GetProcessHeap(), 0, sizeof(ImageGamma));
if (!result || !name)
{
HeapFree(GetProcessHeap(), 0, result);
HeapFree(GetProcessHeap(), 0, name);
return E_OUTOFMEMORY;
}
PropVariantInit(&result[0].schema);
PropVariantInit(&result[0].id);
PropVariantInit(&result[0].value);
memcpy(name, ImageGamma, sizeof(ImageGamma));
result[0].id.vt = VT_LPWSTR;
result[0].id.u.pwszVal = name;
result[0].value.vt = VT_UI4;
result[0].value.u.ulVal = gamma;
*items = result;
*item_count = 1;
return S_OK;
}
static const MetadataHandlerVtbl GamaReader_Vtbl = {
0,
&CLSID_WICPngGamaMetadataReader,
LoadGamaMetadata
};
HRESULT PngGamaReader_CreateInstance(REFIID iid, void** ppv)
{
return MetadataReader_Create(&GamaReader_Vtbl, iid, ppv);
}
#ifdef SONAME_LIBPNG
static void *libpng_handle;
@ -272,11 +339,17 @@ static void user_warning_fn(png_structp png_ptr, png_const_charp warning_message
WARN("PNG warning: %s\n", debugstr_a(warning_message));
}
typedef struct {
ULARGE_INTEGER ofs, len;
IWICMetadataReader* reader;
} metadata_block_info;
typedef struct {
IWICBitmapDecoder IWICBitmapDecoder_iface;
IWICBitmapFrameDecode IWICBitmapFrameDecode_iface;
IWICMetadataBlockReader IWICMetadataBlockReader_iface;
LONG ref;
IStream *stream;
png_structp png_ptr;
png_infop info_ptr;
png_infop end_info;
@ -287,6 +360,8 @@ typedef struct {
const WICPixelFormatGUID *format;
BYTE *image_bits;
CRITICAL_SECTION lock; /* must be held when png structures are accessed or initialized is set */
ULONG metadata_count;
metadata_block_info* metadata_blocks;
} PngDecoder;
static inline PngDecoder *impl_from_IWICBitmapDecoder(IWICBitmapDecoder *iface)
@ -342,16 +417,25 @@ static ULONG WINAPI PngDecoder_Release(IWICBitmapDecoder *iface)
{
PngDecoder *This = impl_from_IWICBitmapDecoder(iface);
ULONG ref = InterlockedDecrement(&This->ref);
ULONG i;
TRACE("(%p) refcount=%u\n", iface, ref);
if (ref == 0)
{
if (This->stream)
IStream_Release(This->stream);
if (This->png_ptr)
ppng_destroy_read_struct(&This->png_ptr, &This->info_ptr, &This->end_info);
This->lock.DebugInfo->Spare[0] = 0;
DeleteCriticalSection(&This->lock);
HeapFree(GetProcessHeap(), 0, This->image_bits);
for (i=0; i<This->metadata_count; i++)
{
if (This->metadata_blocks[i].reader)
IWICMetadataReader_Release(This->metadata_blocks[i].reader);
}
HeapFree(GetProcessHeap(), 0, This->metadata_blocks);
HeapFree(GetProcessHeap(), 0, This);
}
@ -404,6 +488,10 @@ static HRESULT WINAPI PngDecoder_Initialize(IWICBitmapDecoder *iface, IStream *p
png_uint_32 transparency;
png_color_16p trans_values;
jmp_buf jmpbuf;
BYTE chunk_type[4];
ULONG chunk_size;
ULARGE_INTEGER chunk_start;
ULONG metadata_blocks_size = 0;
TRACE("(%p,%p,%x)\n", iface, pIStream, cacheOptions);
@ -586,10 +674,60 @@ static HRESULT WINAPI PngDecoder_Initialize(IWICBitmapDecoder *iface, IStream *p
ppng_read_end(This->png_ptr, This->end_info);
/* Find the metadata chunks in the file. */
seek.QuadPart = 8;
hr = IStream_Seek(pIStream, seek, STREAM_SEEK_SET, &chunk_start);
if (FAILED(hr)) goto end;
do
{
hr = read_png_chunk(pIStream, chunk_type, NULL, &chunk_size);
if (FAILED(hr)) goto end;
if (chunk_type[0] >= 'a' && chunk_type[0] <= 'z' &&
memcmp(chunk_type, "tRNS", 4) && memcmp(chunk_type, "pHYs", 4))
{
/* This chunk is considered metadata. */
if (This->metadata_count == metadata_blocks_size)
{
metadata_block_info* new_metadata_blocks;
ULONG new_metadata_blocks_size;
new_metadata_blocks_size = 4 + metadata_blocks_size * 2;
new_metadata_blocks = HeapAlloc(GetProcessHeap(), 0,
new_metadata_blocks_size * sizeof(*new_metadata_blocks));
if (!new_metadata_blocks)
{
hr = E_OUTOFMEMORY;
goto end;
}
memcpy(new_metadata_blocks, This->metadata_blocks,
This->metadata_count * sizeof(*new_metadata_blocks));
HeapFree(GetProcessHeap(), 0, This->metadata_blocks);
This->metadata_blocks = new_metadata_blocks;
metadata_blocks_size = new_metadata_blocks_size;
}
This->metadata_blocks[This->metadata_count].ofs = chunk_start;
This->metadata_blocks[This->metadata_count].len.QuadPart = chunk_size + 12;
This->metadata_blocks[This->metadata_count].reader = NULL;
This->metadata_count++;
}
seek.QuadPart = chunk_start.QuadPart + chunk_size + 12; /* skip data and CRC */
hr = IStream_Seek(pIStream, seek, STREAM_SEEK_SET, &chunk_start);
if (FAILED(hr)) goto end;
} while (memcmp(chunk_type, "IEND", 4));
This->stream = pIStream;
IStream_AddRef(This->stream);
This->initialized = TRUE;
end:
LeaveCriticalSection(&This->lock);
return hr;
@ -959,17 +1097,65 @@ static HRESULT WINAPI PngDecoder_Block_GetContainerFormat(IWICMetadataBlockReade
static HRESULT WINAPI PngDecoder_Block_GetCount(IWICMetadataBlockReader *iface,
UINT *pcCount)
{
static int once;
PngDecoder *This = impl_from_IWICMetadataBlockReader(iface);
TRACE("%p,%p\n", iface, pcCount);
if (!once++) FIXME("stub\n");
return E_NOTIMPL;
if (!pcCount) return E_INVALIDARG;
*pcCount = This->metadata_count;
return S_OK;
}
static HRESULT WINAPI PngDecoder_Block_GetReaderByIndex(IWICMetadataBlockReader *iface,
UINT nIndex, IWICMetadataReader **ppIMetadataReader)
{
FIXME("%p,%d,%p\n", iface, nIndex, ppIMetadataReader);
return E_NOTIMPL;
PngDecoder *This = impl_from_IWICMetadataBlockReader(iface);
HRESULT hr;
IWICComponentFactory* factory;
IWICStream* stream;
TRACE("%p,%d,%p\n", iface, nIndex, ppIMetadataReader);
if (nIndex >= This->metadata_count || !ppIMetadataReader)
return E_INVALIDARG;
if (!This->metadata_blocks[nIndex].reader)
{
hr = StreamImpl_Create(&stream);
if (SUCCEEDED(hr))
{
hr = IWICStream_InitializeFromIStreamRegion(stream, This->stream,
This->metadata_blocks[nIndex].ofs, This->metadata_blocks[nIndex].len);
if (SUCCEEDED(hr))
hr = ComponentFactory_CreateInstance(&IID_IWICComponentFactory, (void**)&factory);
if (SUCCEEDED(hr))
{
hr = IWICComponentFactory_CreateMetadataReaderFromContainer(factory,
&GUID_ContainerFormatPng, NULL, WICMetadataCreationAllowUnknown,
(IStream*)stream, &This->metadata_blocks[nIndex].reader);
IWICComponentFactory_Release(factory);
}
IWICStream_Release(stream);
}
if (FAILED(hr))
{
*ppIMetadataReader = NULL;
return hr;
}
}
*ppIMetadataReader = This->metadata_blocks[nIndex].reader;
IWICMetadataReader_AddRef(*ppIMetadataReader);
return S_OK;
}
static HRESULT WINAPI PngDecoder_Block_GetEnumerator(IWICMetadataBlockReader *iface,
@ -1014,10 +1200,13 @@ HRESULT PngDecoder_CreateInstance(REFIID iid, void** ppv)
This->png_ptr = NULL;
This->info_ptr = NULL;
This->end_info = NULL;
This->stream = NULL;
This->initialized = FALSE;
This->image_bits = NULL;
InitializeCriticalSection(&This->lock);
This->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": PngDecoder.lock");
This->metadata_count = 0;
This->metadata_blocks = NULL;
ret = IWICBitmapDecoder_QueryInterface(&This->IWICBitmapDecoder_iface, iid, ppv);
IWICBitmapDecoder_Release(&This->IWICBitmapDecoder_iface);

View file

@ -1483,6 +1483,21 @@ static const struct reader_containers pngtext_containers[] = {
{ NULL } /* list terminator */
};
static const BYTE gAMA[] = "gAMA";
static const struct metadata_pattern pnggama_metadata_pattern[] = {
{ 4, 4, gAMA, mask_all, 4 },
{ 0 }
};
static const struct reader_containers pnggama_containers[] = {
{
&GUID_ContainerFormatPng,
pnggama_metadata_pattern
},
{ NULL } /* list terminator */
};
static const struct metadata_pattern lsd_metadata_patterns[] = {
{ 0, 6, gif87a_magic, mask_all, 0 },
{ 0, 6, gif89a_magic, mask_all, 0 },
@ -1578,6 +1593,16 @@ static struct regsvr_metadatareader const metadatareader_list[] = {
1, 1, 0,
ifd_containers
},
{ &CLSID_WICPngGamaMetadataReader,
"The Wine Project",
"Chunk gAMA Reader",
"1.0.0.0",
"1.0.0.0",
&GUID_VendorMicrosoft,
&GUID_MetadataFormatChunkgAMA,
0, 0, 0,
pnggama_containers
},
{ &CLSID_WICPngTextMetadataReader,
"The Wine Project",
"Chunk tEXt Reader",

View file

@ -748,7 +748,7 @@ static HRESULT WINAPI IWICStreamImpl_QueryInterface(IWICStream *iface,
if (IsEqualIID(&IID_IUnknown, iid) || IsEqualIID(&IID_IStream, iid) ||
IsEqualIID(&IID_ISequentialStream, iid) || IsEqualIID(&IID_IWICStream, iid))
{
*ppv = This;
*ppv = &This->IWICStream_iface;
IUnknown_AddRef((IUnknown*)*ppv);
return S_OK;
}

View file

@ -219,7 +219,7 @@ typedef struct {
const WICPixelFormatGUID *format;
int bps;
int samples;
int bpp;
int bpp, source_bpp;
int planar;
int indexed;
int reverse_bgr;
@ -318,26 +318,54 @@ static HRESULT tiff_get_decode_info(TIFF *tiff, tiff_decode_info *decode_info)
extra_sample = 0;
extra_samples = &extra_sample;
}
else
FIXME("ignoring extra alpha %u/%u bps %u\n", extra_sample_count, extra_samples[0], bps);
}
else if (samples != 1)
{
FIXME("unhandled grayscale sample count %u\n", samples);
FIXME("unhandled %dbpp sample count %u\n", bps, samples);
return E_FAIL;
}
decode_info->bpp = bps;
decode_info->bpp = bps * samples;
decode_info->source_bpp = decode_info->bpp;
switch (bps)
{
case 1:
if (samples != 1)
{
FIXME("unhandled 1bpp sample count %u\n", samples);
return E_FAIL;
}
decode_info->format = &GUID_WICPixelFormatBlackWhite;
break;
case 4:
if (samples != 1)
{
FIXME("unhandled 4bpp grayscale sample count %u\n", samples);
return E_FAIL;
}
decode_info->format = &GUID_WICPixelFormat4bppGray;
break;
case 8:
decode_info->format = &GUID_WICPixelFormat8bppGray;
if (samples == 1)
decode_info->format = &GUID_WICPixelFormat8bppGray;
else
{
decode_info->bpp = 32;
switch(extra_samples[0])
{
case 1: /* Associated (pre-multiplied) alpha data */
decode_info->format = &GUID_WICPixelFormat32bppPBGRA;
break;
case 0: /* Unspecified data */
case 2: /* Unassociated alpha data */
decode_info->format = &GUID_WICPixelFormat32bppBGRA;
break;
default:
FIXME("unhandled extra sample type %u\n", extra_samples[0]);
return E_FAIL;
}
}
break;
default:
FIXME("unhandled greyscale bit count %u\n", bps);
@ -938,6 +966,22 @@ static HRESULT TiffFrameDecode_ReadTile(TiffFrameDecode *This, UINT tile_x, UINT
hr = E_FAIL;
}
/* 8bpp grayscale with extra alpha */
if (hr == S_OK && This->decode_info.source_bpp == 16 && This->decode_info.samples == 2 && This->decode_info.bpp == 32)
{
BYTE *src;
DWORD *dst, count = This->decode_info.tile_width * This->decode_info.tile_height;
src = This->cached_tile + This->decode_info.tile_width * This->decode_info.tile_height * 2 - 2;
dst = (DWORD *)(This->cached_tile + This->decode_info.tile_size - 4);
while (count--)
{
*dst-- = src[0] | (src[0] << 8) | (src[0] << 16) | (src[1] << 24);
src -= 2;
}
}
if (hr == S_OK && This->decode_info.reverse_bgr)
{
if (This->decode_info.bps == 8)
@ -1218,8 +1262,7 @@ static HRESULT create_metadata_reader(TiffFrameDecode *This, IWICMetadataReader
/* FIXME: Use IWICComponentFactory_CreateMetadataReader once it's implemented */
hr = CoCreateInstance(&CLSID_WICIfdMetadataReader, NULL, CLSCTX_INPROC_SERVER,
&IID_IWICMetadataReader, (void **)&metadata_reader);
hr = IfdMetadataReader_CreateInstance(&IID_IWICMetadataReader, (void **)&metadata_reader);
if (FAILED(hr)) return hr;
hr = IWICMetadataReader_QueryInterface(metadata_reader, &IID_IWICPersistStream, (void **)&persist);

View file

@ -491,7 +491,7 @@ DGifGetLine(GifFileType * GifFile,
* image until empty block (size 0) detected. We use GetCodeNext. */
do
if (DGifGetCodeNext(GifFile, &Dummy) == GIF_ERROR)
return GIF_ERROR;
break;
while (Dummy != NULL) ;
}
return GIF_OK;

View file

@ -94,6 +94,9 @@ DECLARE_INTERFACE_(IMILUnknown2,IUnknown)
};
#undef INTERFACE
HRESULT create_instance(CLSID *clsid, const IID *iid, void **ppv) DECLSPEC_HIDDEN;
typedef HRESULT(*class_constructor)(REFIID,void**);
extern HRESULT FormatConverter_CreateInstance(REFIID riid, void** ppv) DECLSPEC_HIDDEN;
extern HRESULT ComponentFactory_CreateInstance(REFIID riid, void** ppv) DECLSPEC_HIDDEN;
extern HRESULT BmpDecoder_CreateInstance(REFIID riid, void** ppv) DECLSPEC_HIDDEN;
@ -175,6 +178,7 @@ extern HRESULT MetadataReader_Create(const MetadataHandlerVtbl *vtable, REFIID i
extern HRESULT UnknownMetadataReader_CreateInstance(REFIID iid, void** ppv) DECLSPEC_HIDDEN;
extern HRESULT IfdMetadataReader_CreateInstance(REFIID iid, void **ppv) DECLSPEC_HIDDEN;
extern HRESULT PngGamaReader_CreateInstance(REFIID iid, void** ppv) DECLSPEC_HIDDEN;
extern HRESULT PngTextReader_CreateInstance(REFIID iid, void** ppv) DECLSPEC_HIDDEN;
extern HRESULT LSDReader_CreateInstance(REFIID iid, void **ppv) DECLSPEC_HIDDEN;
extern HRESULT IMDReader_CreateInstance(REFIID iid, void **ppv) DECLSPEC_HIDDEN;

View file

@ -139,6 +139,13 @@ coclass WICUnknownMetadataReader { interface IWICMetadataReader; }
]
coclass WICIfdMetadataReader { interface IWICIfdMetadataReader; }
[
helpstring("WIC Png gAMA Metadata Reader"),
threading(both),
uuid(3692ca39-e082-4350-9e1f-3704cb083cd5)
]
coclass WICPngGamaMetadataReader { interface IWICMetadataReader; }
[
helpstring("WIC Png tEXt Metadata Reader"),
threading(both),

View file

@ -203,6 +203,10 @@ HKCR
{
InprocServer32 = s '%MODULE%' { val ThreadingModel = s 'Both' }
}
'{3692CA39-E082-4350-9E1F-3704CB083CD5}' = s 'WIC Png gAMA Metadata Reader'
{
InprocServer32 = s '%MODULE%' { val ThreadingModel = s 'Both' }
}
'{4B59AFCC-B8C3-408A-B670-89E5FAB6FDA7}' = s 'WIC Png tEXt Metadata Reader'
{
InprocServer32 = s '%MODULE%' { val ThreadingModel = s 'Both' }
@ -228,4 +232,4 @@ HKCR
InprocServer32 = s '%MODULE%' { val ThreadingModel = s 'Both' }
}
}
}
}

View file

@ -202,7 +202,7 @@ reactos/dll/win32/vbscript # Synced to WineStaging-1.7.47
reactos/dll/win32/version # Synced to WineStaging-1.7.47
reactos/dll/win32/wbemdisp # Synced to WineStaging-1.7.47
reactos/dll/win32/wbemprox # Synced to WineStaging-1.7.47
reactos/dll/win32/windowscodecs # Synced to WineStaging-1.7.37
reactos/dll/win32/windowscodecs # Synced to WineStaging-1.7.47
reactos/dll/win32/windowscodecsext # Synced to WineStaging-1.7.37
reactos/dll/win32/winemp3.acm # Synced to WineStaging-1.7.47
reactos/dll/win32/wing32 # Out of sync