2 * Copyright 2009 Vincent Povirk for CodeWeavers
3 * Copyright 2012 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 "wincodecs_private.h"
23 IWICPalette IWICPalette_iface
;
27 WICBitmapPaletteType type
;
28 CRITICAL_SECTION lock
; /* must be held when count, colors, or type is accessed */
31 static inline PaletteImpl
*impl_from_IWICPalette(IWICPalette
*iface
)
33 return CONTAINING_RECORD(iface
, PaletteImpl
, IWICPalette_iface
);
36 static HRESULT WINAPI
PaletteImpl_QueryInterface(IWICPalette
*iface
, REFIID iid
,
39 PaletteImpl
*This
= impl_from_IWICPalette(iface
);
40 TRACE("(%p,%s,%p)\n", iface
, debugstr_guid(iid
), ppv
);
42 if (!ppv
) return E_INVALIDARG
;
44 if (IsEqualIID(&IID_IUnknown
, iid
) || IsEqualIID(&IID_IWICPalette
, iid
))
46 *ppv
= &This
->IWICPalette_iface
;
54 IUnknown_AddRef((IUnknown
*)*ppv
);
58 static ULONG WINAPI
PaletteImpl_AddRef(IWICPalette
*iface
)
60 PaletteImpl
*This
= impl_from_IWICPalette(iface
);
61 ULONG ref
= InterlockedIncrement(&This
->ref
);
63 TRACE("(%p) refcount=%u\n", iface
, ref
);
68 static ULONG WINAPI
PaletteImpl_Release(IWICPalette
*iface
)
70 PaletteImpl
*This
= impl_from_IWICPalette(iface
);
71 ULONG ref
= InterlockedDecrement(&This
->ref
);
73 TRACE("(%p) refcount=%u\n", iface
, ref
);
77 This
->lock
.DebugInfo
->Spare
[0] = 0;
78 DeleteCriticalSection(&This
->lock
);
79 HeapFree(GetProcessHeap(), 0, This
->colors
);
80 HeapFree(GetProcessHeap(), 0, This
);
86 static WICColor
*generate_gray16_palette(UINT
*count
)
92 entries
= HeapAlloc(GetProcessHeap(), 0, 16 * sizeof(WICColor
));
93 if (!entries
) return NULL
;
95 for (i
= 0; i
< 16; i
++)
97 entries
[i
] = 0xff000000;
98 entries
[i
] |= (i
<<20) | (i
<<16) | (i
<<12) | (i
<<8) | (i
<<4) | i
;
103 static WICColor
*generate_gray256_palette(UINT
*count
)
109 entries
= HeapAlloc(GetProcessHeap(), 0, 256 * sizeof(WICColor
));
110 if (!entries
) return NULL
;
112 for (i
= 0; i
< 256; i
++)
114 entries
[i
] = 0xff000000;
115 entries
[i
] |= (i
<<16) | (i
<<8) | i
;
120 static WICColor
*generate_halftone8_palette(UINT
*count
, BOOL add_transparent
)
125 *count
= add_transparent
? 17 : 16;
126 entries
= HeapAlloc(GetProcessHeap(), 0, *count
* sizeof(WICColor
));
127 if (!entries
) return NULL
;
129 for (i
= 0; i
< 8; i
++)
131 entries
[i
] = 0xff000000;
132 if (i
& 1) entries
[i
] |= 0xff;
133 if (i
& 2) entries
[i
] |= 0xff00;
134 if (i
& 4) entries
[i
] |= 0xff0000;
137 for (i
= 8; i
< 16; i
++)
139 static const DWORD halftone
[8] = { 0xc0c0c0, 0x808080, 0x800000, 0x008000,
140 0x000080, 0x808000, 0x800080, 0x008080 };
141 entries
[i
] = 0xff000000;
142 entries
[i
] |= halftone
[i
-8];
151 static WICColor
*generate_halftone27_palette(UINT
*count
, BOOL add_transparent
)
156 *count
= add_transparent
? 29 : 28;
157 entries
= HeapAlloc(GetProcessHeap(), 0, *count
* sizeof(WICColor
));
158 if (!entries
) return NULL
;
160 for (i
= 0; i
< 27; i
++)
162 static const BYTE halftone_values
[4] = { 0x00,0x80,0xff };
163 entries
[i
] = 0xff000000;
164 entries
[i
] |= halftone_values
[i
%3];
165 entries
[i
] |= halftone_values
[(i
/3)%3] << 8;
166 entries
[i
] |= halftone_values
[(i
/9)%3] << 16;
169 entries
[i
++] = 0xffc0c0c0;
176 static WICColor
*generate_halftone64_palette(UINT
*count
, BOOL add_transparent
)
181 *count
= add_transparent
? 73 : 72;
182 entries
= HeapAlloc(GetProcessHeap(), 0, *count
* sizeof(WICColor
));
183 if (!entries
) return NULL
;
185 for (i
= 0; i
< 64; i
++)
187 static const BYTE halftone_values
[4] = { 0x00,0x55,0xaa,0xff };
188 entries
[i
] = 0xff000000;
189 entries
[i
] |= halftone_values
[i
%4];
190 entries
[i
] |= halftone_values
[(i
/4)%4] << 8;
191 entries
[i
] |= halftone_values
[(i
/16)%4] << 16;
194 for (i
= 64; i
< 72; i
++)
196 static const DWORD halftone
[8] = { 0xc0c0c0, 0x808080, 0x800000, 0x008000,
197 0x000080, 0x808000, 0x800080, 0x008080 };
198 entries
[i
] = 0xff000000;
199 entries
[i
] |= halftone
[i
-64];
208 static WICColor
*generate_halftone125_palette(UINT
*count
, BOOL add_transparent
)
213 *count
= add_transparent
? 127 : 126;
214 entries
= HeapAlloc(GetProcessHeap(), 0, *count
* sizeof(WICColor
));
215 if (!entries
) return NULL
;
217 for (i
= 0; i
< 125; i
++)
219 static const BYTE halftone_values
[5] = { 0x00,0x40,0x80,0xbf,0xff };
220 entries
[i
] = 0xff000000;
221 entries
[i
] |= halftone_values
[i
%5];
222 entries
[i
] |= halftone_values
[(i
/5)%5] << 8;
223 entries
[i
] |= halftone_values
[(i
/25)%5] << 16;
226 entries
[i
++] = 0xffc0c0c0;
233 static WICColor
*generate_halftone216_palette(UINT
*count
, BOOL add_transparent
)
238 *count
= add_transparent
? 225 : 224;
239 entries
= HeapAlloc(GetProcessHeap(), 0, *count
* sizeof(WICColor
));
240 if (!entries
) return NULL
;
242 for (i
= 0; i
< 216; i
++)
244 static const BYTE halftone_values
[6] = { 0x00,0x33,0x66,0x99,0xcc,0xff };
245 entries
[i
] = 0xff000000;
246 entries
[i
] |= halftone_values
[i
%6];
247 entries
[i
] |= halftone_values
[(i
/6)%6] << 8;
248 entries
[i
] |= halftone_values
[(i
/36)%6] << 16;
251 for (i
= 216; i
< 224; i
++)
253 static const DWORD halftone
[8] = { 0xc0c0c0, 0x808080, 0x800000, 0x008000,
254 0x000080, 0x808000, 0x800080, 0x008080 };
255 entries
[i
] = 0xff000000;
256 entries
[i
] |= halftone
[i
-216];
265 static WICColor
*generate_halftone252_palette(UINT
*count
, BOOL add_transparent
)
270 *count
= add_transparent
? 253 : 252;
271 entries
= HeapAlloc(GetProcessHeap(), 0, *count
* sizeof(WICColor
));
272 if (!entries
) return NULL
;
274 for (i
= 0; i
< 252; i
++)
276 static const BYTE halftone_values_rb
[6] = { 0x00,0x33,0x66,0x99,0xcc,0xff };
277 static const BYTE halftone_values_g
[7] = { 0x00,0x2b,0x55,0x80,0xaa,0xd5,0xff };
278 entries
[i
] = 0xff000000;
279 entries
[i
] |= halftone_values_rb
[i
%6];
280 entries
[i
] |= halftone_values_g
[(i
/6)%7] << 8;
281 entries
[i
] |= halftone_values_rb
[(i
/42)%6] << 16;
290 static WICColor
*generate_halftone256_palette(UINT
*count
, BOOL add_transparent
)
296 entries
= HeapAlloc(GetProcessHeap(), 0, 256 * sizeof(WICColor
));
297 if (!entries
) return NULL
;
299 for (i
= 0; i
< 256; i
++)
301 static const BYTE halftone_values_b
[4] = { 0x00,0x55,0xaa,0xff };
302 static const BYTE halftone_values_gr
[8] = { 0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff };
303 entries
[i
] = 0xff000000;
304 entries
[i
] |= halftone_values_b
[i
%4];
305 entries
[i
] |= halftone_values_gr
[(i
/4)%8] << 8;
306 entries
[i
] |= halftone_values_gr
[(i
/32)%8] << 16;
315 static HRESULT WINAPI
PaletteImpl_InitializePredefined(IWICPalette
*iface
,
316 WICBitmapPaletteType type
, BOOL add_transparent
)
318 PaletteImpl
*This
= impl_from_IWICPalette(iface
);
322 TRACE("(%p,%u,%d)\n", iface
, type
, add_transparent
);
326 case WICBitmapPaletteTypeFixedBW
:
328 colors
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(WICColor
));
329 if (!colors
) return E_OUTOFMEMORY
;
330 colors
[0] = 0xff000000;
331 colors
[1] = 0xffffffff;
334 case WICBitmapPaletteTypeFixedGray4
:
336 colors
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(WICColor
));
337 if (!colors
) return E_OUTOFMEMORY
;
338 colors
[0] = 0xff000000;
339 colors
[1] = 0xff555555;
340 colors
[2] = 0xffaaaaaa;
341 colors
[3] = 0xffffffff;
344 case WICBitmapPaletteTypeFixedGray16
:
345 colors
= generate_gray16_palette(&count
);
346 if (!colors
) return E_OUTOFMEMORY
;
349 case WICBitmapPaletteTypeFixedGray256
:
350 colors
= generate_gray256_palette(&count
);
351 if (!colors
) return E_OUTOFMEMORY
;
354 case WICBitmapPaletteTypeFixedHalftone8
:
355 colors
= generate_halftone8_palette(&count
, add_transparent
);
356 if (!colors
) return E_OUTOFMEMORY
;
359 case WICBitmapPaletteTypeFixedHalftone27
:
360 colors
= generate_halftone27_palette(&count
, add_transparent
);
361 if (!colors
) return E_OUTOFMEMORY
;
364 case WICBitmapPaletteTypeFixedHalftone64
:
365 colors
= generate_halftone64_palette(&count
, add_transparent
);
366 if (!colors
) return E_OUTOFMEMORY
;
369 case WICBitmapPaletteTypeFixedHalftone125
:
370 colors
= generate_halftone125_palette(&count
, add_transparent
);
371 if (!colors
) return E_OUTOFMEMORY
;
374 case WICBitmapPaletteTypeFixedHalftone216
:
375 colors
= generate_halftone216_palette(&count
, add_transparent
);
376 if (!colors
) return E_OUTOFMEMORY
;
379 case WICBitmapPaletteTypeFixedHalftone252
:
380 colors
= generate_halftone252_palette(&count
, add_transparent
);
381 if (!colors
) return E_OUTOFMEMORY
;
384 case WICBitmapPaletteTypeFixedHalftone256
:
385 colors
= generate_halftone256_palette(&count
, add_transparent
);
386 if (!colors
) return E_OUTOFMEMORY
;
390 WARN("invalid palette type %u\n", type
);
394 EnterCriticalSection(&This
->lock
);
395 HeapFree(GetProcessHeap(), 0, This
->colors
);
396 This
->colors
= colors
;
399 LeaveCriticalSection(&This
->lock
);
404 static HRESULT WINAPI
PaletteImpl_InitializeCustom(IWICPalette
*iface
,
405 WICColor
*pColors
, UINT colorCount
)
407 PaletteImpl
*This
= impl_from_IWICPalette(iface
);
408 WICColor
*new_colors
;
410 TRACE("(%p,%p,%u)\n", iface
, pColors
, colorCount
);
418 if (!pColors
) return E_INVALIDARG
;
419 new_colors
= HeapAlloc(GetProcessHeap(), 0, sizeof(WICColor
) * colorCount
);
420 if (!new_colors
) return E_OUTOFMEMORY
;
421 memcpy(new_colors
, pColors
, sizeof(WICColor
) * colorCount
);
424 EnterCriticalSection(&This
->lock
);
425 HeapFree(GetProcessHeap(), 0, This
->colors
);
426 This
->colors
= new_colors
;
427 This
->count
= colorCount
;
428 This
->type
= WICBitmapPaletteTypeCustom
;
429 LeaveCriticalSection(&This
->lock
);
434 static HRESULT WINAPI
PaletteImpl_InitializeFromBitmap(IWICPalette
*iface
,
435 IWICBitmapSource
*pISurface
, UINT colorCount
, BOOL fAddTransparentColor
)
437 FIXME("(%p,%p,%u,%i): stub\n", iface
, pISurface
, colorCount
, fAddTransparentColor
);
441 static HRESULT WINAPI
PaletteImpl_InitializeFromPalette(IWICPalette
*iface
,
444 PaletteImpl
*This
= impl_from_IWICPalette(iface
);
446 WICColor
*colors
= NULL
;
447 WICBitmapPaletteType type
;
450 TRACE("(%p,%p)\n", iface
, source
);
452 if (!source
) return E_INVALIDARG
;
454 hr
= IWICPalette_GetType(source
, &type
);
455 if (hr
!= S_OK
) return hr
;
456 hr
= IWICPalette_GetColorCount(source
, &count
);
457 if (hr
!= S_OK
) return hr
;
460 colors
= HeapAlloc(GetProcessHeap(), 0, sizeof(WICColor
) * count
);
461 if (!colors
) return E_OUTOFMEMORY
;
462 hr
= IWICPalette_GetColors(source
, count
, colors
, &count
);
465 HeapFree(GetProcessHeap(), 0, colors
);
470 EnterCriticalSection(&This
->lock
);
471 HeapFree(GetProcessHeap(), 0, This
->colors
);
472 This
->colors
= colors
;
475 LeaveCriticalSection(&This
->lock
);
480 static HRESULT WINAPI
PaletteImpl_GetType(IWICPalette
*iface
,
481 WICBitmapPaletteType
*pePaletteType
)
483 PaletteImpl
*This
= impl_from_IWICPalette(iface
);
485 TRACE("(%p,%p)\n", iface
, pePaletteType
);
487 if (!pePaletteType
) return E_INVALIDARG
;
489 EnterCriticalSection(&This
->lock
);
490 *pePaletteType
= This
->type
;
491 LeaveCriticalSection(&This
->lock
);
496 static HRESULT WINAPI
PaletteImpl_GetColorCount(IWICPalette
*iface
, UINT
*pcCount
)
498 PaletteImpl
*This
= impl_from_IWICPalette(iface
);
500 TRACE("(%p,%p)\n", iface
, pcCount
);
502 if (!pcCount
) return E_INVALIDARG
;
504 EnterCriticalSection(&This
->lock
);
505 *pcCount
= This
->count
;
506 LeaveCriticalSection(&This
->lock
);
511 static HRESULT WINAPI
PaletteImpl_GetColors(IWICPalette
*iface
, UINT colorCount
,
512 WICColor
*pColors
, UINT
*pcActualColors
)
514 PaletteImpl
*This
= impl_from_IWICPalette(iface
);
516 TRACE("(%p,%i,%p,%p)\n", iface
, colorCount
, pColors
, pcActualColors
);
518 if (!pColors
|| !pcActualColors
) return E_INVALIDARG
;
520 EnterCriticalSection(&This
->lock
);
522 if (This
->count
< colorCount
) colorCount
= This
->count
;
524 memcpy(pColors
, This
->colors
, sizeof(WICColor
) * colorCount
);
526 *pcActualColors
= colorCount
;
528 LeaveCriticalSection(&This
->lock
);
533 static HRESULT WINAPI
PaletteImpl_IsBlackWhite(IWICPalette
*iface
, BOOL
*pfIsBlackWhite
)
535 PaletteImpl
*This
= impl_from_IWICPalette(iface
);
537 TRACE("(%p,%p)\n", iface
, pfIsBlackWhite
);
539 if (!pfIsBlackWhite
) return E_INVALIDARG
;
541 EnterCriticalSection(&This
->lock
);
542 if (This
->type
== WICBitmapPaletteTypeFixedBW
)
543 *pfIsBlackWhite
= TRUE
;
545 *pfIsBlackWhite
= FALSE
;
546 LeaveCriticalSection(&This
->lock
);
551 static HRESULT WINAPI
PaletteImpl_IsGrayscale(IWICPalette
*iface
, BOOL
*pfIsGrayscale
)
553 PaletteImpl
*This
= impl_from_IWICPalette(iface
);
555 TRACE("(%p,%p)\n", iface
, pfIsGrayscale
);
557 if (!pfIsGrayscale
) return E_INVALIDARG
;
559 EnterCriticalSection(&This
->lock
);
562 case WICBitmapPaletteTypeFixedBW
:
563 case WICBitmapPaletteTypeFixedGray4
:
564 case WICBitmapPaletteTypeFixedGray16
:
565 case WICBitmapPaletteTypeFixedGray256
:
566 *pfIsGrayscale
= TRUE
;
569 *pfIsGrayscale
= FALSE
;
571 LeaveCriticalSection(&This
->lock
);
576 static HRESULT WINAPI
PaletteImpl_HasAlpha(IWICPalette
*iface
, BOOL
*pfHasAlpha
)
578 PaletteImpl
*This
= impl_from_IWICPalette(iface
);
581 TRACE("(%p,%p)\n", iface
, pfHasAlpha
);
583 if (!pfHasAlpha
) return E_INVALIDARG
;
587 EnterCriticalSection(&This
->lock
);
588 for (i
=0; i
<This
->count
; i
++)
589 if ((This
->colors
[i
]&0xff000000) != 0xff000000)
594 LeaveCriticalSection(&This
->lock
);
599 static const IWICPaletteVtbl PaletteImpl_Vtbl
= {
600 PaletteImpl_QueryInterface
,
603 PaletteImpl_InitializePredefined
,
604 PaletteImpl_InitializeCustom
,
605 PaletteImpl_InitializeFromBitmap
,
606 PaletteImpl_InitializeFromPalette
,
608 PaletteImpl_GetColorCount
,
609 PaletteImpl_GetColors
,
610 PaletteImpl_IsBlackWhite
,
611 PaletteImpl_IsGrayscale
,
615 HRESULT
PaletteImpl_Create(IWICPalette
**palette
)
619 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(PaletteImpl
));
620 if (!This
) return E_OUTOFMEMORY
;
622 This
->IWICPalette_iface
.lpVtbl
= &PaletteImpl_Vtbl
;
626 This
->type
= WICBitmapPaletteTypeCustom
;
627 InitializeCriticalSection(&This
->lock
);
628 This
->lock
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": PaletteImpl.lock");
630 *palette
= &This
->IWICPalette_iface
;