windowscodecs: Add support for reading tiled TIFF images.
[wine] / dlls / windowscodecs / palette.c
1 /*
2  * Copyright 2009 Vincent Povirk 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 "config.h"
20
21 #include <stdarg.h>
22
23 #define COBJMACROS
24
25 #include "windef.h"
26 #include "winbase.h"
27 #include "winreg.h"
28 #include "objbase.h"
29 #include "wincodec.h"
30
31 #include "wincodecs_private.h"
32
33 #include "wine/debug.h"
34
35 WINE_DEFAULT_DEBUG_CHANNEL(wincodecs);
36
37 typedef struct {
38     IWICPalette IWICPalette_iface;
39     LONG ref;
40     UINT count;
41     WICColor *colors;
42     WICBitmapPaletteType type;
43     CRITICAL_SECTION lock; /* must be held when count, colors, or type is accessed */
44 } PaletteImpl;
45
46 static inline PaletteImpl *impl_from_IWICPalette(IWICPalette *iface)
47 {
48     return CONTAINING_RECORD(iface, PaletteImpl, IWICPalette_iface);
49 }
50
51 static HRESULT WINAPI PaletteImpl_QueryInterface(IWICPalette *iface, REFIID iid,
52     void **ppv)
53 {
54     PaletteImpl *This = impl_from_IWICPalette(iface);
55     TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
56
57     if (!ppv) return E_INVALIDARG;
58
59     if (IsEqualIID(&IID_IUnknown, iid) || IsEqualIID(&IID_IWICPalette, iid))
60     {
61         *ppv = This;
62     }
63     else
64     {
65         *ppv = NULL;
66         return E_NOINTERFACE;
67     }
68
69     IUnknown_AddRef((IUnknown*)*ppv);
70     return S_OK;
71 }
72
73 static ULONG WINAPI PaletteImpl_AddRef(IWICPalette *iface)
74 {
75     PaletteImpl *This = impl_from_IWICPalette(iface);
76     ULONG ref = InterlockedIncrement(&This->ref);
77
78     TRACE("(%p) refcount=%u\n", iface, ref);
79
80     return ref;
81 }
82
83 static ULONG WINAPI PaletteImpl_Release(IWICPalette *iface)
84 {
85     PaletteImpl *This = impl_from_IWICPalette(iface);
86     ULONG ref = InterlockedDecrement(&This->ref);
87
88     TRACE("(%p) refcount=%u\n", iface, ref);
89
90     if (ref == 0)
91     {
92         This->lock.DebugInfo->Spare[0] = 0;
93         DeleteCriticalSection(&This->lock);
94         HeapFree(GetProcessHeap(), 0, This->colors);
95         HeapFree(GetProcessHeap(), 0, This);
96     }
97
98     return ref;
99 }
100
101 static HRESULT WINAPI PaletteImpl_InitializePredefined(IWICPalette *iface,
102     WICBitmapPaletteType ePaletteType, BOOL fAddTransparentColor)
103 {
104     FIXME("(%p,%u,%i): stub\n", iface, ePaletteType, fAddTransparentColor);
105     return E_NOTIMPL;
106 }
107
108 static HRESULT WINAPI PaletteImpl_InitializeCustom(IWICPalette *iface,
109     WICColor *pColors, UINT colorCount)
110 {
111     PaletteImpl *This = impl_from_IWICPalette(iface);
112     WICColor *new_colors;
113
114     TRACE("(%p,%p,%u)\n", iface, pColors, colorCount);
115
116     if (colorCount == 0)
117     {
118         new_colors = NULL;
119     }
120     else
121     {
122         if (!pColors) return E_INVALIDARG;
123         new_colors = HeapAlloc(GetProcessHeap(), 0, sizeof(WICColor) * colorCount);
124         if (!new_colors) return E_OUTOFMEMORY;
125         memcpy(new_colors, pColors, sizeof(WICColor) * colorCount);
126     }
127
128     EnterCriticalSection(&This->lock);
129     HeapFree(GetProcessHeap(), 0, This->colors);
130     This->colors = new_colors;
131     This->count = colorCount;
132     This->type = WICBitmapPaletteTypeCustom;
133     LeaveCriticalSection(&This->lock);
134
135     return S_OK;
136 }
137
138 static HRESULT WINAPI PaletteImpl_InitializeFromBitmap(IWICPalette *iface,
139     IWICBitmapSource *pISurface, UINT colorCount, BOOL fAddTransparentColor)
140 {
141     FIXME("(%p,%p,%u,%i): stub\n", iface, pISurface, colorCount, fAddTransparentColor);
142     return E_NOTIMPL;
143 }
144
145 static HRESULT WINAPI PaletteImpl_InitializeFromPalette(IWICPalette *iface,
146     IWICPalette *pIPalette)
147 {
148     FIXME("(%p,%p): stub\n", iface, pIPalette);
149     return E_NOTIMPL;
150 }
151
152 static HRESULT WINAPI PaletteImpl_GetType(IWICPalette *iface,
153     WICBitmapPaletteType *pePaletteType)
154 {
155     PaletteImpl *This = impl_from_IWICPalette(iface);
156
157     TRACE("(%p,%p)\n", iface, pePaletteType);
158
159     if (!pePaletteType) return E_INVALIDARG;
160
161     EnterCriticalSection(&This->lock);
162     *pePaletteType = This->type;
163     LeaveCriticalSection(&This->lock);
164
165     return S_OK;
166 }
167
168 static HRESULT WINAPI PaletteImpl_GetColorCount(IWICPalette *iface, UINT *pcCount)
169 {
170     PaletteImpl *This = impl_from_IWICPalette(iface);
171
172     TRACE("(%p,%p)\n", iface, pcCount);
173
174     if (!pcCount) return E_INVALIDARG;
175
176     EnterCriticalSection(&This->lock);
177     *pcCount = This->count;
178     LeaveCriticalSection(&This->lock);
179
180     return S_OK;
181 }
182
183 static HRESULT WINAPI PaletteImpl_GetColors(IWICPalette *iface, UINT colorCount,
184     WICColor *pColors, UINT *pcActualColors)
185 {
186     PaletteImpl *This = impl_from_IWICPalette(iface);
187
188     TRACE("(%p,%i,%p,%p)\n", iface, colorCount, pColors, pcActualColors);
189
190     if (!pColors || !pcActualColors) return E_INVALIDARG;
191
192     EnterCriticalSection(&This->lock);
193
194     if (This->count < colorCount) colorCount = This->count;
195
196     memcpy(pColors, This->colors, sizeof(WICColor) * colorCount);
197
198     *pcActualColors = colorCount;
199
200     LeaveCriticalSection(&This->lock);
201
202     return S_OK;
203 }
204
205 static HRESULT WINAPI PaletteImpl_IsBlackWhite(IWICPalette *iface, BOOL *pfIsBlackWhite)
206 {
207     PaletteImpl *This = impl_from_IWICPalette(iface);
208
209     TRACE("(%p,%p)\n", iface, pfIsBlackWhite);
210
211     if (!pfIsBlackWhite) return E_INVALIDARG;
212
213     EnterCriticalSection(&This->lock);
214     if (This->type == WICBitmapPaletteTypeFixedBW)
215         *pfIsBlackWhite = TRUE;
216     else
217         *pfIsBlackWhite = FALSE;
218     LeaveCriticalSection(&This->lock);
219
220     return S_OK;
221 }
222
223 static HRESULT WINAPI PaletteImpl_IsGrayscale(IWICPalette *iface, BOOL *pfIsGrayscale)
224 {
225     PaletteImpl *This = impl_from_IWICPalette(iface);
226
227     TRACE("(%p,%p)\n", iface, pfIsGrayscale);
228
229     if (!pfIsGrayscale) return E_INVALIDARG;
230
231     EnterCriticalSection(&This->lock);
232     switch(This->type)
233     {
234         case WICBitmapPaletteTypeFixedBW:
235         case WICBitmapPaletteTypeFixedGray4:
236         case WICBitmapPaletteTypeFixedGray16:
237         case WICBitmapPaletteTypeFixedGray256:
238             *pfIsGrayscale = TRUE;
239             break;
240         default:
241             *pfIsGrayscale = FALSE;
242     }
243     LeaveCriticalSection(&This->lock);
244
245     return S_OK;
246 }
247
248 static HRESULT WINAPI PaletteImpl_HasAlpha(IWICPalette *iface, BOOL *pfHasAlpha)
249 {
250     PaletteImpl *This = impl_from_IWICPalette(iface);
251     int i;
252
253     TRACE("(%p,%p)\n", iface, pfHasAlpha);
254
255     if (!pfHasAlpha) return E_INVALIDARG;
256
257     *pfHasAlpha = FALSE;
258
259     EnterCriticalSection(&This->lock);
260     for (i=0; i<This->count; i++)
261         if ((This->colors[i]&0xff000000) != 0xff000000)
262         {
263             *pfHasAlpha = TRUE;
264             break;
265         }
266     LeaveCriticalSection(&This->lock);
267
268     return S_OK;
269 }
270
271 static const IWICPaletteVtbl PaletteImpl_Vtbl = {
272     PaletteImpl_QueryInterface,
273     PaletteImpl_AddRef,
274     PaletteImpl_Release,
275     PaletteImpl_InitializePredefined,
276     PaletteImpl_InitializeCustom,
277     PaletteImpl_InitializeFromBitmap,
278     PaletteImpl_InitializeFromPalette,
279     PaletteImpl_GetType,
280     PaletteImpl_GetColorCount,
281     PaletteImpl_GetColors,
282     PaletteImpl_IsBlackWhite,
283     PaletteImpl_IsGrayscale,
284     PaletteImpl_HasAlpha
285 };
286
287 HRESULT PaletteImpl_Create(IWICPalette **palette)
288 {
289     PaletteImpl *This;
290
291     This = HeapAlloc(GetProcessHeap(), 0, sizeof(PaletteImpl));
292     if (!This) return E_OUTOFMEMORY;
293
294     This->IWICPalette_iface.lpVtbl = &PaletteImpl_Vtbl;
295     This->ref = 1;
296     This->count = 0;
297     This->colors = NULL;
298     This->type = WICBitmapPaletteTypeCustom;
299     InitializeCriticalSection(&This->lock);
300     This->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": PaletteImpl.lock");
301
302     *palette = (IWICPalette*)This;
303
304     return S_OK;
305 }