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
32 #include "wincodecs_private.h"
34 #include "wine/debug.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(wincodecs
);
39 IWICPalette IWICPalette_iface
;
43 WICBitmapPaletteType type
;
44 CRITICAL_SECTION lock
; /* must be held when count, colors, or type is accessed */
47 static inline PaletteImpl
*impl_from_IWICPalette(IWICPalette
*iface
)
49 return CONTAINING_RECORD(iface
, PaletteImpl
, IWICPalette_iface
);
52 static HRESULT WINAPI
PaletteImpl_QueryInterface(IWICPalette
*iface
, REFIID iid
,
55 PaletteImpl
*This
= impl_from_IWICPalette(iface
);
56 TRACE("(%p,%s,%p)\n", iface
, debugstr_guid(iid
), ppv
);
58 if (!ppv
) return E_INVALIDARG
;
60 if (IsEqualIID(&IID_IUnknown
, iid
) || IsEqualIID(&IID_IWICPalette
, iid
))
62 *ppv
= &This
->IWICPalette_iface
;
70 IUnknown_AddRef((IUnknown
*)*ppv
);
74 static ULONG WINAPI
PaletteImpl_AddRef(IWICPalette
*iface
)
76 PaletteImpl
*This
= impl_from_IWICPalette(iface
);
77 ULONG ref
= InterlockedIncrement(&This
->ref
);
79 TRACE("(%p) refcount=%u\n", iface
, ref
);
84 static ULONG WINAPI
PaletteImpl_Release(IWICPalette
*iface
)
86 PaletteImpl
*This
= impl_from_IWICPalette(iface
);
87 ULONG ref
= InterlockedDecrement(&This
->ref
);
89 TRACE("(%p) refcount=%u\n", iface
, ref
);
93 This
->lock
.DebugInfo
->Spare
[0] = 0;
94 DeleteCriticalSection(&This
->lock
);
95 HeapFree(GetProcessHeap(), 0, This
->colors
);
96 HeapFree(GetProcessHeap(), 0, This
);
102 static WICColor
*generate_gray16_palette(UINT
*count
)
108 entries
= HeapAlloc(GetProcessHeap(), 0, 16 * sizeof(WICColor
));
109 if (!entries
) return NULL
;
111 for (i
= 0; i
< 16; i
++)
113 entries
[i
] = 0xff000000;
114 entries
[i
] |= (i
<<20) | (i
<<16) | (i
<<12) | (i
<<8) | (i
<<4) | i
;
119 static WICColor
*generate_gray256_palette(UINT
*count
)
125 entries
= HeapAlloc(GetProcessHeap(), 0, 256 * sizeof(WICColor
));
126 if (!entries
) return NULL
;
128 for (i
= 0; i
< 256; i
++)
130 entries
[i
] = 0xff000000;
131 entries
[i
] |= (i
<<16) | (i
<<8) | i
;
136 static WICColor
*generate_halftone8_palette(UINT
*count
, BOOL add_transparent
)
141 *count
= add_transparent
? 17 : 16;
142 entries
= HeapAlloc(GetProcessHeap(), 0, *count
* sizeof(WICColor
));
143 if (!entries
) return NULL
;
145 for (i
= 0; i
< 8; i
++)
147 entries
[i
] = 0xff000000;
148 if (i
& 1) entries
[i
] |= 0xff;
149 if (i
& 2) entries
[i
] |= 0xff00;
150 if (i
& 4) entries
[i
] |= 0xff0000;
153 for (i
= 8; i
< 16; i
++)
155 static const DWORD halftone
[8] = { 0xc0c0c0, 0x808080, 0x800000, 0x008000,
156 0x000080, 0x808000, 0x800080, 0x008080 };
157 entries
[i
] = 0xff000000;
158 entries
[i
] |= halftone
[i
-8];
167 static WICColor
*generate_halftone27_palette(UINT
*count
, BOOL add_transparent
)
172 *count
= add_transparent
? 29 : 28;
173 entries
= HeapAlloc(GetProcessHeap(), 0, *count
* sizeof(WICColor
));
174 if (!entries
) return NULL
;
176 for (i
= 0; i
< 27; i
++)
178 static const BYTE halftone_values
[4] = { 0x00,0x80,0xff };
179 entries
[i
] = 0xff000000;
180 entries
[i
] |= halftone_values
[i
%3];
181 entries
[i
] |= halftone_values
[(i
/3)%3] << 8;
182 entries
[i
] |= halftone_values
[(i
/9)%3] << 16;
185 entries
[i
++] = 0xffc0c0c0;
192 static WICColor
*generate_halftone64_palette(UINT
*count
, BOOL add_transparent
)
197 *count
= add_transparent
? 73 : 72;
198 entries
= HeapAlloc(GetProcessHeap(), 0, *count
* sizeof(WICColor
));
199 if (!entries
) return NULL
;
201 for (i
= 0; i
< 64; i
++)
203 static const BYTE halftone_values
[4] = { 0x00,0x55,0xaa,0xff };
204 entries
[i
] = 0xff000000;
205 entries
[i
] |= halftone_values
[i
%4];
206 entries
[i
] |= halftone_values
[(i
/4)%4] << 8;
207 entries
[i
] |= halftone_values
[(i
/16)%4] << 16;
210 for (i
= 64; i
< 72; i
++)
212 static const DWORD halftone
[8] = { 0xc0c0c0, 0x808080, 0x800000, 0x008000,
213 0x000080, 0x808000, 0x800080, 0x008080 };
214 entries
[i
] = 0xff000000;
215 entries
[i
] |= halftone
[i
-64];
224 static WICColor
*generate_halftone125_palette(UINT
*count
, BOOL add_transparent
)
229 *count
= add_transparent
? 127 : 126;
230 entries
= HeapAlloc(GetProcessHeap(), 0, *count
* sizeof(WICColor
));
231 if (!entries
) return NULL
;
233 for (i
= 0; i
< 125; i
++)
235 static const BYTE halftone_values
[5] = { 0x00,0x40,0x80,0xbf,0xff };
236 entries
[i
] = 0xff000000;
237 entries
[i
] |= halftone_values
[i
%5];
238 entries
[i
] |= halftone_values
[(i
/5)%5] << 8;
239 entries
[i
] |= halftone_values
[(i
/25)%5] << 16;
242 entries
[i
++] = 0xffc0c0c0;
249 static WICColor
*generate_halftone216_palette(UINT
*count
, BOOL add_transparent
)
254 *count
= add_transparent
? 225 : 224;
255 entries
= HeapAlloc(GetProcessHeap(), 0, *count
* sizeof(WICColor
));
256 if (!entries
) return NULL
;
258 for (i
= 0; i
< 216; i
++)
260 static const BYTE halftone_values
[6] = { 0x00,0x33,0x66,0x99,0xcc,0xff };
261 entries
[i
] = 0xff000000;
262 entries
[i
] |= halftone_values
[i
%6];
263 entries
[i
] |= halftone_values
[(i
/6)%6] << 8;
264 entries
[i
] |= halftone_values
[(i
/36)%6] << 16;
267 for (i
= 216; i
< 224; i
++)
269 static const DWORD halftone
[8] = { 0xc0c0c0, 0x808080, 0x800000, 0x008000,
270 0x000080, 0x808000, 0x800080, 0x008080 };
271 entries
[i
] = 0xff000000;
272 entries
[i
] |= halftone
[i
-216];
281 static WICColor
*generate_halftone252_palette(UINT
*count
, BOOL add_transparent
)
286 *count
= add_transparent
? 253 : 252;
287 entries
= HeapAlloc(GetProcessHeap(), 0, *count
* sizeof(WICColor
));
288 if (!entries
) return NULL
;
290 for (i
= 0; i
< 252; i
++)
292 static const BYTE halftone_values_rb
[6] = { 0x00,0x33,0x66,0x99,0xcc,0xff };
293 static const BYTE halftone_values_g
[7] = { 0x00,0x2b,0x55,0x80,0xaa,0xd5,0xff };
294 entries
[i
] = 0xff000000;
295 entries
[i
] |= halftone_values_rb
[i
%6];
296 entries
[i
] |= halftone_values_g
[(i
/6)%7] << 8;
297 entries
[i
] |= halftone_values_rb
[(i
/42)%6] << 16;
306 static WICColor
*generate_halftone256_palette(UINT
*count
, BOOL add_transparent
)
312 entries
= HeapAlloc(GetProcessHeap(), 0, 256 * sizeof(WICColor
));
313 if (!entries
) return NULL
;
315 for (i
= 0; i
< 256; i
++)
317 static const BYTE halftone_values_b
[4] = { 0x00,0x55,0xaa,0xff };
318 static const BYTE halftone_values_gr
[8] = { 0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff };
319 entries
[i
] = 0xff000000;
320 entries
[i
] |= halftone_values_b
[i
%4];
321 entries
[i
] |= halftone_values_gr
[(i
/4)%8] << 8;
322 entries
[i
] |= halftone_values_gr
[(i
/32)%8] << 16;
331 static HRESULT WINAPI
PaletteImpl_InitializePredefined(IWICPalette
*iface
,
332 WICBitmapPaletteType type
, BOOL add_transparent
)
334 PaletteImpl
*This
= impl_from_IWICPalette(iface
);
338 TRACE("(%p,%u,%d)\n", iface
, type
, add_transparent
);
342 case WICBitmapPaletteTypeFixedBW
:
344 colors
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(WICColor
));
345 if (!colors
) return E_OUTOFMEMORY
;
346 colors
[0] = 0xff000000;
347 colors
[1] = 0xffffffff;
350 case WICBitmapPaletteTypeFixedGray4
:
352 colors
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(WICColor
));
353 if (!colors
) return E_OUTOFMEMORY
;
354 colors
[0] = 0xff000000;
355 colors
[1] = 0xff555555;
356 colors
[2] = 0xffaaaaaa;
357 colors
[3] = 0xffffffff;
360 case WICBitmapPaletteTypeFixedGray16
:
361 colors
= generate_gray16_palette(&count
);
362 if (!colors
) return E_OUTOFMEMORY
;
365 case WICBitmapPaletteTypeFixedGray256
:
366 colors
= generate_gray256_palette(&count
);
367 if (!colors
) return E_OUTOFMEMORY
;
370 case WICBitmapPaletteTypeFixedHalftone8
:
371 colors
= generate_halftone8_palette(&count
, add_transparent
);
372 if (!colors
) return E_OUTOFMEMORY
;
375 case WICBitmapPaletteTypeFixedHalftone27
:
376 colors
= generate_halftone27_palette(&count
, add_transparent
);
377 if (!colors
) return E_OUTOFMEMORY
;
380 case WICBitmapPaletteTypeFixedHalftone64
:
381 colors
= generate_halftone64_palette(&count
, add_transparent
);
382 if (!colors
) return E_OUTOFMEMORY
;
385 case WICBitmapPaletteTypeFixedHalftone125
:
386 colors
= generate_halftone125_palette(&count
, add_transparent
);
387 if (!colors
) return E_OUTOFMEMORY
;
390 case WICBitmapPaletteTypeFixedHalftone216
:
391 colors
= generate_halftone216_palette(&count
, add_transparent
);
392 if (!colors
) return E_OUTOFMEMORY
;
395 case WICBitmapPaletteTypeFixedHalftone252
:
396 colors
= generate_halftone252_palette(&count
, add_transparent
);
397 if (!colors
) return E_OUTOFMEMORY
;
400 case WICBitmapPaletteTypeFixedHalftone256
:
401 colors
= generate_halftone256_palette(&count
, add_transparent
);
402 if (!colors
) return E_OUTOFMEMORY
;
406 WARN("invalid palette type %u\n", type
);
410 EnterCriticalSection(&This
->lock
);
411 HeapFree(GetProcessHeap(), 0, This
->colors
);
412 This
->colors
= colors
;
415 LeaveCriticalSection(&This
->lock
);
420 static HRESULT WINAPI
PaletteImpl_InitializeCustom(IWICPalette
*iface
,
421 WICColor
*pColors
, UINT colorCount
)
423 PaletteImpl
*This
= impl_from_IWICPalette(iface
);
424 WICColor
*new_colors
;
426 TRACE("(%p,%p,%u)\n", iface
, pColors
, colorCount
);
434 if (!pColors
) return E_INVALIDARG
;
435 new_colors
= HeapAlloc(GetProcessHeap(), 0, sizeof(WICColor
) * colorCount
);
436 if (!new_colors
) return E_OUTOFMEMORY
;
437 memcpy(new_colors
, pColors
, sizeof(WICColor
) * colorCount
);
440 EnterCriticalSection(&This
->lock
);
441 HeapFree(GetProcessHeap(), 0, This
->colors
);
442 This
->colors
= new_colors
;
443 This
->count
= colorCount
;
444 This
->type
= WICBitmapPaletteTypeCustom
;
445 LeaveCriticalSection(&This
->lock
);
450 static HRESULT WINAPI
PaletteImpl_InitializeFromBitmap(IWICPalette
*iface
,
451 IWICBitmapSource
*pISurface
, UINT colorCount
, BOOL fAddTransparentColor
)
453 FIXME("(%p,%p,%u,%i): stub\n", iface
, pISurface
, colorCount
, fAddTransparentColor
);
457 static HRESULT WINAPI
PaletteImpl_InitializeFromPalette(IWICPalette
*iface
,
460 PaletteImpl
*This
= impl_from_IWICPalette(iface
);
462 WICColor
*colors
= NULL
;
463 WICBitmapPaletteType type
;
466 TRACE("(%p,%p)\n", iface
, source
);
468 if (!source
) return E_INVALIDARG
;
470 hr
= IWICPalette_GetType(source
, &type
);
471 if (hr
!= S_OK
) return hr
;
472 hr
= IWICPalette_GetColorCount(source
, &count
);
473 if (hr
!= S_OK
) return hr
;
476 colors
= HeapAlloc(GetProcessHeap(), 0, sizeof(WICColor
) * count
);
477 if (!colors
) return E_OUTOFMEMORY
;
478 hr
= IWICPalette_GetColors(source
, count
, colors
, &count
);
481 HeapFree(GetProcessHeap(), 0, colors
);
486 EnterCriticalSection(&This
->lock
);
487 HeapFree(GetProcessHeap(), 0, This
->colors
);
488 This
->colors
= colors
;
491 LeaveCriticalSection(&This
->lock
);
496 static HRESULT WINAPI
PaletteImpl_GetType(IWICPalette
*iface
,
497 WICBitmapPaletteType
*pePaletteType
)
499 PaletteImpl
*This
= impl_from_IWICPalette(iface
);
501 TRACE("(%p,%p)\n", iface
, pePaletteType
);
503 if (!pePaletteType
) return E_INVALIDARG
;
505 EnterCriticalSection(&This
->lock
);
506 *pePaletteType
= This
->type
;
507 LeaveCriticalSection(&This
->lock
);
512 static HRESULT WINAPI
PaletteImpl_GetColorCount(IWICPalette
*iface
, UINT
*pcCount
)
514 PaletteImpl
*This
= impl_from_IWICPalette(iface
);
516 TRACE("(%p,%p)\n", iface
, pcCount
);
518 if (!pcCount
) return E_INVALIDARG
;
520 EnterCriticalSection(&This
->lock
);
521 *pcCount
= This
->count
;
522 LeaveCriticalSection(&This
->lock
);
527 static HRESULT WINAPI
PaletteImpl_GetColors(IWICPalette
*iface
, UINT colorCount
,
528 WICColor
*pColors
, UINT
*pcActualColors
)
530 PaletteImpl
*This
= impl_from_IWICPalette(iface
);
532 TRACE("(%p,%i,%p,%p)\n", iface
, colorCount
, pColors
, pcActualColors
);
534 if (!pColors
|| !pcActualColors
) return E_INVALIDARG
;
536 EnterCriticalSection(&This
->lock
);
538 if (This
->count
< colorCount
) colorCount
= This
->count
;
540 memcpy(pColors
, This
->colors
, sizeof(WICColor
) * colorCount
);
542 *pcActualColors
= colorCount
;
544 LeaveCriticalSection(&This
->lock
);
549 static HRESULT WINAPI
PaletteImpl_IsBlackWhite(IWICPalette
*iface
, BOOL
*pfIsBlackWhite
)
551 PaletteImpl
*This
= impl_from_IWICPalette(iface
);
553 TRACE("(%p,%p)\n", iface
, pfIsBlackWhite
);
555 if (!pfIsBlackWhite
) return E_INVALIDARG
;
557 EnterCriticalSection(&This
->lock
);
558 if (This
->type
== WICBitmapPaletteTypeFixedBW
)
559 *pfIsBlackWhite
= TRUE
;
561 *pfIsBlackWhite
= FALSE
;
562 LeaveCriticalSection(&This
->lock
);
567 static HRESULT WINAPI
PaletteImpl_IsGrayscale(IWICPalette
*iface
, BOOL
*pfIsGrayscale
)
569 PaletteImpl
*This
= impl_from_IWICPalette(iface
);
571 TRACE("(%p,%p)\n", iface
, pfIsGrayscale
);
573 if (!pfIsGrayscale
) return E_INVALIDARG
;
575 EnterCriticalSection(&This
->lock
);
578 case WICBitmapPaletteTypeFixedBW
:
579 case WICBitmapPaletteTypeFixedGray4
:
580 case WICBitmapPaletteTypeFixedGray16
:
581 case WICBitmapPaletteTypeFixedGray256
:
582 *pfIsGrayscale
= TRUE
;
585 *pfIsGrayscale
= FALSE
;
587 LeaveCriticalSection(&This
->lock
);
592 static HRESULT WINAPI
PaletteImpl_HasAlpha(IWICPalette
*iface
, BOOL
*pfHasAlpha
)
594 PaletteImpl
*This
= impl_from_IWICPalette(iface
);
597 TRACE("(%p,%p)\n", iface
, pfHasAlpha
);
599 if (!pfHasAlpha
) return E_INVALIDARG
;
603 EnterCriticalSection(&This
->lock
);
604 for (i
=0; i
<This
->count
; i
++)
605 if ((This
->colors
[i
]&0xff000000) != 0xff000000)
610 LeaveCriticalSection(&This
->lock
);
615 static const IWICPaletteVtbl PaletteImpl_Vtbl
= {
616 PaletteImpl_QueryInterface
,
619 PaletteImpl_InitializePredefined
,
620 PaletteImpl_InitializeCustom
,
621 PaletteImpl_InitializeFromBitmap
,
622 PaletteImpl_InitializeFromPalette
,
624 PaletteImpl_GetColorCount
,
625 PaletteImpl_GetColors
,
626 PaletteImpl_IsBlackWhite
,
627 PaletteImpl_IsGrayscale
,
631 HRESULT
PaletteImpl_Create(IWICPalette
**palette
)
635 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(PaletteImpl
));
636 if (!This
) return E_OUTOFMEMORY
;
638 This
->IWICPalette_iface
.lpVtbl
= &PaletteImpl_Vtbl
;
642 This
->type
= WICBitmapPaletteTypeCustom
;
643 InitializeCriticalSection(&This
->lock
);
644 This
->lock
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": PaletteImpl.lock");
646 *palette
= &This
->IWICPalette_iface
;