winepulse: Wrap unix call parameters in structs.
[wine.git] / dlls / windowscodecs / pngformat.c
blobe7c3e8d70469182fd02d1cd4a585800254c88eb3
1 /*
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
20 #include <stdarg.h>
22 #define NONAMELESSUNION
23 #define COBJMACROS
25 #include "windef.h"
26 #include "winbase.h"
27 #include "objbase.h"
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)
41 HRESULT hr;
42 BYTE type[4];
43 BYTE *data;
44 ULONG data_size;
45 ULONG name_len, value_len;
46 BYTE *name_end_ptr;
47 LPSTR name, value;
48 MetadataItem *result;
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);
60 return E_FAIL;
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);
74 return E_OUTOFMEMORY;
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);
83 value[value_len] = 0;
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;
90 *items = result;
91 *item_count = 1;
93 HeapFree(GetProcessHeap(), 0, data);
95 return S_OK;
98 static const MetadataHandlerVtbl TextReader_Vtbl = {
100 &CLSID_WICPngTextMetadataReader,
101 LoadTextMetadata
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)
112 HRESULT hr;
113 BYTE type[4];
114 BYTE *data;
115 ULONG data_size;
116 ULONG gamma;
117 LPWSTR name;
118 MetadataItem *result;
120 hr = read_png_chunk(stream, type, &data, &data_size);
121 if (FAILED(hr)) return hr;
123 if (data_size < 4)
125 HeapFree(GetProcessHeap(), 0, data);
126 return E_FAIL;
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;
153 *items = result;
154 *item_count = 1;
156 return S_OK;
159 static const MetadataHandlerVtbl GamaReader_Vtbl = {
161 &CLSID_WICPngGamaMetadataReader,
162 LoadGamaMetadata
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)
173 HRESULT hr;
174 BYTE type[4];
175 BYTE *data;
176 ULONG data_size;
177 static const WCHAR names[8][12] = {
178 L"WhitePointX",
179 L"WhitePointY",
180 L"RedX",
181 L"RedY",
182 L"GreenX",
183 L"GreenY",
184 L"BlueX",
185 L"BlueY",
187 LPWSTR dyn_names[8] = {0};
188 MetadataItem *result;
189 int i;
191 hr = read_png_chunk(stream, type, &data, &data_size);
192 if (FAILED(hr)) return hr;
194 if (data_size < 32)
196 HeapFree(GetProcessHeap(), 0, data);
197 return E_FAIL;
200 result = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(MetadataItem)*8);
201 for (i=0; i<8; i++)
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);
209 for (i=0; i<8; i++)
210 HeapFree(GetProcessHeap(), 0, dyn_names[i]);
211 HeapFree(GetProcessHeap(), 0, data);
212 return E_OUTOFMEMORY;
215 for (i=0; i<8; i++)
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]);
229 *items = result;
230 *item_count = 8;
232 HeapFree(GetProcessHeap(), 0, data);
234 return S_OK;
237 static const MetadataHandlerVtbl ChrmReader_Vtbl = {
239 &CLSID_WICPngChrmMetadataReader,
240 LoadChrmMetadata
243 HRESULT PngChrmReader_CreateInstance(REFIID iid, void** ppv)
245 return MetadataReader_Create(&ChrmReader_Vtbl, iid, ppv);
248 HRESULT PngDecoder_CreateInstance(REFIID iid, void** ppv)
250 HRESULT hr;
251 struct decoder *decoder;
252 struct decoder_info decoder_info;
254 hr = get_unix_decoder(&CLSID_WICPngDecoder, &decoder_info, &decoder);
256 if (SUCCEEDED(hr))
257 hr = CommonDecoder_CreateInstance(decoder, &decoder_info, iid, ppv);
259 return hr;
262 HRESULT PngEncoder_CreateInstance(REFIID iid, void** ppv)
264 HRESULT hr;
265 struct encoder *encoder;
266 struct encoder_info encoder_info;
268 hr = get_unix_encoder(&CLSID_WICPngEncoder, &encoder_info, &encoder);
270 if (SUCCEEDED(hr))
271 hr = CommonEncoder_CreateInstance(encoder, &encoder_info, iid, ppv);
273 return hr;