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 #include "wincodecs_private.h" 20 21 typedef struct ColorContext { 22 IWICColorContext IWICColorContext_iface; 23 LONG ref; 24 WICColorContextType type; 25 BYTE *profile; 26 UINT profile_len; 27 UINT exif_color_space; 28 } ColorContext; 29 30 static inline ColorContext *impl_from_IWICColorContext(IWICColorContext *iface) 31 { 32 return CONTAINING_RECORD(iface, ColorContext, IWICColorContext_iface); 33 } 34 35 static HRESULT WINAPI ColorContext_QueryInterface(IWICColorContext *iface, REFIID iid, 36 void **ppv) 37 { 38 ColorContext *This = impl_from_IWICColorContext(iface); 39 TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv); 40 41 if (!ppv) return E_INVALIDARG; 42 43 if (IsEqualIID(&IID_IUnknown, iid) || 44 IsEqualIID(&IID_IWICColorContext, iid)) 45 { 46 *ppv = &This->IWICColorContext_iface; 47 } 48 else 49 { 50 *ppv = NULL; 51 return E_NOINTERFACE; 52 } 53 54 IUnknown_AddRef((IUnknown*)*ppv); 55 return S_OK; 56 } 57 58 static ULONG WINAPI ColorContext_AddRef(IWICColorContext *iface) 59 { 60 ColorContext *This = impl_from_IWICColorContext(iface); 61 ULONG ref = InterlockedIncrement(&This->ref); 62 63 TRACE("(%p) refcount=%u\n", iface, ref); 64 65 return ref; 66 } 67 68 static ULONG WINAPI ColorContext_Release(IWICColorContext *iface) 69 { 70 ColorContext *This = impl_from_IWICColorContext(iface); 71 ULONG ref = InterlockedDecrement(&This->ref); 72 73 TRACE("(%p) refcount=%u\n", iface, ref); 74 75 if (ref == 0) 76 { 77 HeapFree(GetProcessHeap(), 0, This->profile); 78 HeapFree(GetProcessHeap(), 0, This); 79 } 80 81 return ref; 82 } 83 84 static HRESULT load_profile(const WCHAR *filename, BYTE **profile, UINT *len) 85 { 86 HANDLE handle; 87 DWORD count; 88 LARGE_INTEGER size; 89 BOOL ret; 90 91 *len = 0; 92 *profile = NULL; 93 handle = CreateFileW(filename, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL); 94 if (handle == INVALID_HANDLE_VALUE) return HRESULT_FROM_WIN32(GetLastError()); 95 96 if (!(GetFileSizeEx(handle, &size))) 97 { 98 CloseHandle(handle); 99 return HRESULT_FROM_WIN32(GetLastError()); 100 } 101 if (size.u.HighPart) 102 { 103 WARN("file too large\n"); 104 CloseHandle(handle); 105 return E_FAIL; 106 } 107 if (!(*profile = HeapAlloc(GetProcessHeap(), 0, size.u.LowPart))) 108 { 109 CloseHandle(handle); 110 return E_OUTOFMEMORY; 111 } 112 ret = ReadFile(handle, *profile, size.u.LowPart, &count, NULL); 113 CloseHandle(handle); 114 if (!ret) { 115 HeapFree (GetProcessHeap(),0,*profile); 116 *profile = NULL; 117 return HRESULT_FROM_WIN32(GetLastError()); 118 } 119 if (count != size.u.LowPart) { 120 HeapFree (GetProcessHeap(),0,*profile); 121 *profile = NULL; 122 return E_FAIL; 123 } 124 *len = count; 125 return S_OK; 126 } 127 128 static HRESULT WINAPI ColorContext_InitializeFromFilename(IWICColorContext *iface, 129 LPCWSTR wzFilename) 130 { 131 ColorContext *This = impl_from_IWICColorContext(iface); 132 BYTE *profile; 133 UINT len; 134 HRESULT hr; 135 TRACE("(%p,%s)\n", iface, debugstr_w(wzFilename)); 136 137 if (This->type != WICColorContextUninitialized && This->type != WICColorContextProfile) 138 return WINCODEC_ERR_WRONGSTATE; 139 140 if (!wzFilename) return E_INVALIDARG; 141 142 hr = load_profile(wzFilename, &profile, &len); 143 if (FAILED(hr)) return hr; 144 145 HeapFree(GetProcessHeap(), 0, This->profile); 146 This->profile = profile; 147 This->profile_len = len; 148 This->type = WICColorContextProfile; 149 150 return S_OK; 151 } 152 153 static HRESULT WINAPI ColorContext_InitializeFromMemory(IWICColorContext *iface, 154 const BYTE *pbBuffer, UINT cbBufferSize) 155 { 156 ColorContext *This = impl_from_IWICColorContext(iface); 157 BYTE *profile; 158 TRACE("(%p,%p,%u)\n", iface, pbBuffer, cbBufferSize); 159 160 if (This->type != WICColorContextUninitialized && This->type != WICColorContextProfile) 161 return WINCODEC_ERR_WRONGSTATE; 162 163 if (!(profile = HeapAlloc(GetProcessHeap(), 0, cbBufferSize))) return E_OUTOFMEMORY; 164 memcpy(profile, pbBuffer, cbBufferSize); 165 166 HeapFree(GetProcessHeap(), 0, This->profile); 167 This->profile = profile; 168 This->profile_len = cbBufferSize; 169 This->type = WICColorContextProfile; 170 171 return S_OK; 172 } 173 174 static HRESULT WINAPI ColorContext_InitializeFromExifColorSpace(IWICColorContext *iface, 175 UINT value) 176 { 177 ColorContext *This = impl_from_IWICColorContext(iface); 178 TRACE("(%p,%u)\n", iface, value); 179 180 if (This->type != WICColorContextUninitialized && This->type != WICColorContextExifColorSpace) 181 return WINCODEC_ERR_WRONGSTATE; 182 183 This->exif_color_space = value; 184 This->type = WICColorContextExifColorSpace; 185 186 return S_OK; 187 } 188 189 static HRESULT WINAPI ColorContext_GetType(IWICColorContext *iface, 190 WICColorContextType *pType) 191 { 192 ColorContext *This = impl_from_IWICColorContext(iface); 193 TRACE("(%p,%p)\n", iface, pType); 194 195 if (!pType) return E_INVALIDARG; 196 197 *pType = This->type; 198 return S_OK; 199 } 200 201 static HRESULT WINAPI ColorContext_GetProfileBytes(IWICColorContext *iface, 202 UINT cbBuffer, BYTE *pbBuffer, UINT *pcbActual) 203 { 204 ColorContext *This = impl_from_IWICColorContext(iface); 205 TRACE("(%p,%u,%p,%p)\n", iface, cbBuffer, pbBuffer, pcbActual); 206 207 if (This->type != WICColorContextProfile) 208 return WINCODEC_ERR_NOTINITIALIZED; 209 210 if (!pcbActual) return E_INVALIDARG; 211 212 if (cbBuffer >= This->profile_len && pbBuffer) 213 memcpy(pbBuffer, This->profile, This->profile_len); 214 215 *pcbActual = This->profile_len; 216 217 return S_OK; 218 } 219 220 static HRESULT WINAPI ColorContext_GetExifColorSpace(IWICColorContext *iface, 221 UINT *pValue) 222 { 223 ColorContext *This = impl_from_IWICColorContext(iface); 224 TRACE("(%p,%p)\n", iface, pValue); 225 226 if (!pValue) return E_INVALIDARG; 227 228 *pValue = This->exif_color_space; 229 return S_OK; 230 } 231 232 static const IWICColorContextVtbl ColorContext_Vtbl = { 233 ColorContext_QueryInterface, 234 ColorContext_AddRef, 235 ColorContext_Release, 236 ColorContext_InitializeFromFilename, 237 ColorContext_InitializeFromMemory, 238 ColorContext_InitializeFromExifColorSpace, 239 ColorContext_GetType, 240 ColorContext_GetProfileBytes, 241 ColorContext_GetExifColorSpace 242 }; 243 244 HRESULT ColorContext_Create(IWICColorContext **colorcontext) 245 { 246 ColorContext *This; 247 248 if (!colorcontext) return E_INVALIDARG; 249 250 This = HeapAlloc(GetProcessHeap(), 0, sizeof(ColorContext)); 251 if (!This) return E_OUTOFMEMORY; 252 253 This->IWICColorContext_iface.lpVtbl = &ColorContext_Vtbl; 254 This->ref = 1; 255 This->type = 0; 256 This->profile = NULL; 257 This->profile_len = 0; 258 This->exif_color_space = ~0u; 259 260 *colorcontext = &This->IWICColorContext_iface; 261 262 return S_OK; 263 } 264