2 * Copyright 2009 Vincent Povirk for CodeWeavers
3 * Copyright 2016 Dmitry Timoshkov
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #define NONAMELESSUNION
29 #include "wincodecs_private.h"
31 #include "wine/debug.h"
33 static inline ULONG
read_ulong_be(BYTE
* data
)
35 return data
[0] << 24 | data
[1] << 16 | data
[2] << 8 | data
[3];
38 static HRESULT
LoadTextMetadata(IStream
*stream
, const GUID
*preferred_vendor
,
39 DWORD persist_options
, MetadataItem
**items
, DWORD
*item_count
)
45 ULONG name_len
, value_len
;
50 hr
= read_png_chunk(stream
, type
, &data
, &data_size
);
51 if (FAILED(hr
)) return hr
;
53 name_end_ptr
= memchr(data
, 0, data_size
);
55 name_len
= name_end_ptr
- data
;
57 if (!name_end_ptr
|| name_len
> 79)
59 HeapFree(GetProcessHeap(), 0, data
);
63 value_len
= data_size
- name_len
- 1;
65 result
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(MetadataItem
));
66 name
= HeapAlloc(GetProcessHeap(), 0, name_len
+ 1);
67 value
= HeapAlloc(GetProcessHeap(), 0, value_len
+ 1);
68 if (!result
|| !name
|| !value
)
70 HeapFree(GetProcessHeap(), 0, data
);
71 HeapFree(GetProcessHeap(), 0, result
);
72 HeapFree(GetProcessHeap(), 0, name
);
73 HeapFree(GetProcessHeap(), 0, value
);
77 PropVariantInit(&result
[0].schema
);
78 PropVariantInit(&result
[0].id
);
79 PropVariantInit(&result
[0].value
);
81 memcpy(name
, data
, name_len
+ 1);
82 memcpy(value
, name_end_ptr
+ 1, value_len
);
85 result
[0].id
.vt
= VT_LPSTR
;
86 result
[0].id
.pszVal
= name
;
87 result
[0].value
.vt
= VT_LPSTR
;
88 result
[0].value
.pszVal
= value
;
93 HeapFree(GetProcessHeap(), 0, data
);
98 static const MetadataHandlerVtbl TextReader_Vtbl
= {
100 &CLSID_WICPngTextMetadataReader
,
104 HRESULT
PngTextReader_CreateInstance(REFIID iid
, void** ppv
)
106 return MetadataReader_Create(&TextReader_Vtbl
, iid
, ppv
);
109 static HRESULT
LoadGamaMetadata(IStream
*stream
, const GUID
*preferred_vendor
,
110 DWORD persist_options
, MetadataItem
**items
, DWORD
*item_count
)
118 MetadataItem
*result
;
120 hr
= read_png_chunk(stream
, type
, &data
, &data_size
);
121 if (FAILED(hr
)) return hr
;
125 HeapFree(GetProcessHeap(), 0, data
);
129 gamma
= read_ulong_be(data
);
131 HeapFree(GetProcessHeap(), 0, data
);
133 result
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(MetadataItem
));
134 name
= HeapAlloc(GetProcessHeap(), 0, sizeof(L
"ImageGamma"));
135 if (!result
|| !name
)
137 HeapFree(GetProcessHeap(), 0, result
);
138 HeapFree(GetProcessHeap(), 0, name
);
139 return E_OUTOFMEMORY
;
142 PropVariantInit(&result
[0].schema
);
143 PropVariantInit(&result
[0].id
);
144 PropVariantInit(&result
[0].value
);
146 memcpy(name
, L
"ImageGamma", sizeof(L
"ImageGamma"));
148 result
[0].id
.vt
= VT_LPWSTR
;
149 result
[0].id
.pwszVal
= name
;
150 result
[0].value
.vt
= VT_UI4
;
151 result
[0].value
.ulVal
= gamma
;
159 static const MetadataHandlerVtbl GamaReader_Vtbl
= {
161 &CLSID_WICPngGamaMetadataReader
,
165 HRESULT
PngGamaReader_CreateInstance(REFIID iid
, void** ppv
)
167 return MetadataReader_Create(&GamaReader_Vtbl
, iid
, ppv
);
170 static HRESULT
LoadChrmMetadata(IStream
*stream
, const GUID
*preferred_vendor
,
171 DWORD persist_options
, MetadataItem
**items
, DWORD
*item_count
)
177 static const WCHAR names
[8][12] = {
187 LPWSTR dyn_names
[8] = {0};
188 MetadataItem
*result
;
191 hr
= read_png_chunk(stream
, type
, &data
, &data_size
);
192 if (FAILED(hr
)) return hr
;
196 HeapFree(GetProcessHeap(), 0, data
);
200 result
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(MetadataItem
)*8);
203 dyn_names
[i
] = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR
)*(lstrlenW(names
[i
])+1));
204 if (!dyn_names
[i
]) break;
206 if (!result
|| i
< 8)
208 HeapFree(GetProcessHeap(), 0, result
);
210 HeapFree(GetProcessHeap(), 0, dyn_names
[i
]);
211 HeapFree(GetProcessHeap(), 0, data
);
212 return E_OUTOFMEMORY
;
217 PropVariantInit(&result
[i
].schema
);
219 PropVariantInit(&result
[i
].id
);
220 result
[i
].id
.vt
= VT_LPWSTR
;
221 result
[i
].id
.pwszVal
= dyn_names
[i
];
222 lstrcpyW(dyn_names
[i
], names
[i
]);
224 PropVariantInit(&result
[i
].value
);
225 result
[i
].value
.vt
= VT_UI4
;
226 result
[i
].value
.ulVal
= read_ulong_be(&data
[i
*4]);
232 HeapFree(GetProcessHeap(), 0, data
);
237 static const MetadataHandlerVtbl ChrmReader_Vtbl
= {
239 &CLSID_WICPngChrmMetadataReader
,
243 HRESULT
PngChrmReader_CreateInstance(REFIID iid
, void** ppv
)
245 return MetadataReader_Create(&ChrmReader_Vtbl
, iid
, ppv
);
248 HRESULT
PngDecoder_CreateInstance(REFIID iid
, void** ppv
)
251 struct decoder
*decoder
;
252 struct decoder_info decoder_info
;
254 hr
= get_unix_decoder(&CLSID_WICPngDecoder
, &decoder_info
, &decoder
);
257 hr
= CommonDecoder_CreateInstance(decoder
, &decoder_info
, iid
, ppv
);
262 HRESULT
PngEncoder_CreateInstance(REFIID iid
, void** ppv
)
265 struct encoder
*encoder
;
266 struct encoder_info encoder_info
;
268 hr
= get_unix_encoder(&CLSID_WICPngEncoder
, &encoder_info
, &encoder
);
271 hr
= CommonEncoder_CreateInstance(encoder
, &encoder_info
, iid
, ppv
);