494aad945b9e8d55d6a2d487b9bed69d02ac3318
[reactos.git] / reactos / dll / win32 / windowscodecs / colorcontext.c
1 /*
2 * Copyright 2012 Hans Leidekker for CodeWeavers
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17 */
18
19 #define WIN32_NO_STATUS
20 #define _INC_WINDOWS
21 #define COM_NO_WINDOWS_H
22
23 #include <config.h>
24
25 #include <stdarg.h>
26
27 #define COBJMACROS
28
29 #include <windef.h>
30 #include <winbase.h>
31 #include <objbase.h>
32 #include <wincodec.h>
33
34 //#include "wincodecs_private.h"
35
36 #include <wine/debug.h>
37
38 WINE_DEFAULT_DEBUG_CHANNEL(wincodecs);
39
40 typedef struct ColorContext {
41 IWICColorContext IWICColorContext_iface;
42 LONG ref;
43 WICColorContextType type;
44 BYTE *profile;
45 UINT profile_len;
46 UINT exif_color_space;
47 } ColorContext;
48
49 static inline ColorContext *impl_from_IWICColorContext(IWICColorContext *iface)
50 {
51 return CONTAINING_RECORD(iface, ColorContext, IWICColorContext_iface);
52 }
53
54 static HRESULT WINAPI ColorContext_QueryInterface(IWICColorContext *iface, REFIID iid,
55 void **ppv)
56 {
57 ColorContext *This = impl_from_IWICColorContext(iface);
58 TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
59
60 if (!ppv) return E_INVALIDARG;
61
62 if (IsEqualIID(&IID_IUnknown, iid) ||
63 IsEqualIID(&IID_IWICColorContext, iid))
64 {
65 *ppv = &This->IWICColorContext_iface;
66 }
67 else
68 {
69 *ppv = NULL;
70 return E_NOINTERFACE;
71 }
72
73 IUnknown_AddRef((IUnknown*)*ppv);
74 return S_OK;
75 }
76
77 static ULONG WINAPI ColorContext_AddRef(IWICColorContext *iface)
78 {
79 ColorContext *This = impl_from_IWICColorContext(iface);
80 ULONG ref = InterlockedIncrement(&This->ref);
81
82 TRACE("(%p) refcount=%u\n", iface, ref);
83
84 return ref;
85 }
86
87 static ULONG WINAPI ColorContext_Release(IWICColorContext *iface)
88 {
89 ColorContext *This = impl_from_IWICColorContext(iface);
90 ULONG ref = InterlockedDecrement(&This->ref);
91
92 TRACE("(%p) refcount=%u\n", iface, ref);
93
94 if (ref == 0)
95 {
96 HeapFree(GetProcessHeap(), 0, This->profile);
97 HeapFree(GetProcessHeap(), 0, This);
98 }
99
100 return ref;
101 }
102
103 static HRESULT load_profile(const WCHAR *filename, BYTE **profile, UINT *len)
104 {
105 HANDLE handle;
106 DWORD count;
107 LARGE_INTEGER size;
108 BOOL ret;
109
110 *len = 0;
111 *profile = NULL;
112 handle = CreateFileW(filename, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
113 if (handle == INVALID_HANDLE_VALUE) return HRESULT_FROM_WIN32(GetLastError());
114
115 if (!(GetFileSizeEx(handle, &size)))
116 {
117 CloseHandle(handle);
118 return HRESULT_FROM_WIN32(GetLastError());
119 }
120 if (size.u.HighPart)
121 {
122 WARN("file too large\n");
123 CloseHandle(handle);
124 return E_FAIL;
125 }
126 if (!(*profile = HeapAlloc(GetProcessHeap(), 0, size.u.LowPart)))
127 {
128 CloseHandle(handle);
129 return E_OUTOFMEMORY;
130 }
131 ret = ReadFile(handle, *profile, size.u.LowPart, &count, NULL);
132 CloseHandle(handle);
133 if (!ret) {
134 HeapFree (GetProcessHeap(),0,*profile);
135 *profile = NULL;
136 return HRESULT_FROM_WIN32(GetLastError());
137 }
138 if (count != size.u.LowPart) {
139 HeapFree (GetProcessHeap(),0,*profile);
140 *profile = NULL;
141 return E_FAIL;
142 }
143 *len = count;
144 return S_OK;
145 }
146
147 static HRESULT WINAPI ColorContext_InitializeFromFilename(IWICColorContext *iface,
148 LPCWSTR wzFilename)
149 {
150 ColorContext *This = impl_from_IWICColorContext(iface);
151 BYTE *profile;
152 UINT len;
153 HRESULT hr;
154 TRACE("(%p,%s)\n", iface, debugstr_w(wzFilename));
155
156 if (This->type != WICColorContextUninitialized && This->type != WICColorContextProfile)
157 return WINCODEC_ERR_WRONGSTATE;
158
159 if (!wzFilename) return E_INVALIDARG;
160
161 hr = load_profile(wzFilename, &profile, &len);
162 if (FAILED(hr)) return hr;
163
164 HeapFree(GetProcessHeap(), 0, This->profile);
165 This->profile = profile;
166 This->profile_len = len;
167 This->type = WICColorContextProfile;
168
169 return S_OK;
170 }
171
172 static HRESULT WINAPI ColorContext_InitializeFromMemory(IWICColorContext *iface,
173 const BYTE *pbBuffer, UINT cbBufferSize)
174 {
175 ColorContext *This = impl_from_IWICColorContext(iface);
176 BYTE *profile;
177 TRACE("(%p,%p,%u)\n", iface, pbBuffer, cbBufferSize);
178
179 if (This->type != WICColorContextUninitialized && This->type != WICColorContextProfile)
180 return WINCODEC_ERR_WRONGSTATE;
181
182 if (!(profile = HeapAlloc(GetProcessHeap(), 0, cbBufferSize))) return E_OUTOFMEMORY;
183 memcpy(profile, pbBuffer, cbBufferSize);
184
185 HeapFree(GetProcessHeap(), 0, This->profile);
186 This->profile = profile;
187 This->profile_len = cbBufferSize;
188 This->type = WICColorContextProfile;
189
190 return S_OK;
191 }
192
193 static HRESULT WINAPI ColorContext_InitializeFromExifColorSpace(IWICColorContext *iface,
194 UINT value)
195 {
196 ColorContext *This = impl_from_IWICColorContext(iface);
197 TRACE("(%p,%u)\n", iface, value);
198
199 if (This->type != WICColorContextUninitialized && This->type != WICColorContextExifColorSpace)
200 return WINCODEC_ERR_WRONGSTATE;
201
202 This->exif_color_space = value;
203 This->type = WICColorContextExifColorSpace;
204
205 return S_OK;
206 }
207
208 static HRESULT WINAPI ColorContext_GetType(IWICColorContext *iface,
209 WICColorContextType *pType)
210 {
211 ColorContext *This = impl_from_IWICColorContext(iface);
212 TRACE("(%p,%p)\n", iface, pType);
213
214 if (!pType) return E_INVALIDARG;
215
216 *pType = This->type;
217 return S_OK;
218 }
219
220 static HRESULT WINAPI ColorContext_GetProfileBytes(IWICColorContext *iface,
221 UINT cbBuffer, BYTE *pbBuffer, UINT *pcbActual)
222 {
223 ColorContext *This = impl_from_IWICColorContext(iface);
224 TRACE("(%p,%u,%p,%p)\n", iface, cbBuffer, pbBuffer, pcbActual);
225
226 if (This->type != WICColorContextProfile)
227 return WINCODEC_ERR_NOTINITIALIZED;
228
229 if (!pcbActual) return E_INVALIDARG;
230
231 if (cbBuffer >= This->profile_len && pbBuffer)
232 memcpy(pbBuffer, This->profile, This->profile_len);
233
234 *pcbActual = This->profile_len;
235
236 return S_OK;
237 }
238
239 static HRESULT WINAPI ColorContext_GetExifColorSpace(IWICColorContext *iface,
240 UINT *pValue)
241 {
242 ColorContext *This = impl_from_IWICColorContext(iface);
243 TRACE("(%p,%p)\n", iface, pValue);
244
245 if (!pValue) return E_INVALIDARG;
246
247 *pValue = This->exif_color_space;
248 return S_OK;
249 }
250
251 static const IWICColorContextVtbl ColorContext_Vtbl = {
252 ColorContext_QueryInterface,
253 ColorContext_AddRef,
254 ColorContext_Release,
255 ColorContext_InitializeFromFilename,
256 ColorContext_InitializeFromMemory,
257 ColorContext_InitializeFromExifColorSpace,
258 ColorContext_GetType,
259 ColorContext_GetProfileBytes,
260 ColorContext_GetExifColorSpace
261 };
262
263 HRESULT ColorContext_Create(IWICColorContext **colorcontext)
264 {
265 ColorContext *This;
266
267 if (!colorcontext) return E_INVALIDARG;
268
269 This = HeapAlloc(GetProcessHeap(), 0, sizeof(ColorContext));
270 if (!This) return E_OUTOFMEMORY;
271
272 This->IWICColorContext_iface.lpVtbl = &ColorContext_Vtbl;
273 This->ref = 1;
274 This->type = 0;
275 This->profile = NULL;
276 This->profile_len = 0;
277 This->exif_color_space = ~0u;
278
279 *colorcontext = &This->IWICColorContext_iface;
280
281 return S_OK;
282 }