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
31 #include "wincodecs_private.h"
33 #include "wine/debug.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(wincodecs
);
38 IWICPalette IWICPalette_iface
;
42 WICBitmapPaletteType type
;
43 CRITICAL_SECTION lock
; /* must be held when count, colors, or type is accessed */
46 static inline PaletteImpl
*impl_from_IWICPalette(IWICPalette
*iface
)
48 return CONTAINING_RECORD(iface
, PaletteImpl
, IWICPalette_iface
);
51 static HRESULT WINAPI
PaletteImpl_QueryInterface(IWICPalette
*iface
, REFIID iid
,
54 PaletteImpl
*This
= impl_from_IWICPalette(iface
);
55 TRACE("(%p,%s,%p)\n", iface
, debugstr_guid(iid
), ppv
);
57 if (!ppv
) return E_INVALIDARG
;
59 if (IsEqualIID(&IID_IUnknown
, iid
) || IsEqualIID(&IID_IWICPalette
, iid
))
61 *ppv
= &This
->IWICPalette_iface
;
69 IUnknown_AddRef((IUnknown
*)*ppv
);
73 static ULONG WINAPI
PaletteImpl_AddRef(IWICPalette
*iface
)
75 PaletteImpl
*This
= impl_from_IWICPalette(iface
);
76 ULONG ref
= InterlockedIncrement(&This
->ref
);
78 TRACE("(%p) refcount=%u\n", iface
, ref
);
83 static ULONG WINAPI
PaletteImpl_Release(IWICPalette
*iface
)
85 PaletteImpl
*This
= impl_from_IWICPalette(iface
);
86 ULONG ref
= InterlockedDecrement(&This
->ref
);
88 TRACE("(%p) refcount=%u\n", iface
, ref
);
92 This
->lock
.DebugInfo
->Spare
[0] = 0;
93 DeleteCriticalSection(&This
->lock
);
94 HeapFree(GetProcessHeap(), 0, This
->colors
);
95 HeapFree(GetProcessHeap(), 0, This
);
101 static WICColor
*generate_gray16_palette(UINT
*count
)
107 entries
= HeapAlloc(GetProcessHeap(), 0, 16 * sizeof(WICColor
));
108 if (!entries
) return NULL
;
110 for (i
= 0; i
< 16; i
++)
112 entries
[i
] = 0xff000000;
113 entries
[i
] |= (i
<<20) | (i
<<16) | (i
<<12) | (i
<<8) | (i
<<4) | i
;
118 static WICColor
*generate_gray256_palette(UINT
*count
)
124 entries
= HeapAlloc(GetProcessHeap(), 0, 256 * sizeof(WICColor
));
125 if (!entries
) return NULL
;
127 for (i
= 0; i
< 256; i
++)
129 entries
[i
] = 0xff000000;
130 entries
[i
] |= (i
<<16) | (i
<<8) | i
;
135 static WICColor
*generate_halftone8_palette(UINT
*count
, BOOL add_transparent
)
140 *count
= add_transparent
? 17 : 16;
141 entries
= HeapAlloc(GetProcessHeap(), 0, *count
* sizeof(WICColor
));
142 if (!entries
) return NULL
;
144 for (i
= 0; i
< 8; i
++)
146 entries
[i
] = 0xff000000;
147 if (i
& 1) entries
[i
] |= 0xff;
148 if (i
& 2) entries
[i
] |= 0xff00;
149 if (i
& 4) entries
[i
] |= 0xff0000;
152 for (i
= 8; i
< 16; i
++)
154 static const DWORD halftone
[8] = { 0xc0c0c0, 0x808080, 0x800000, 0x008000,
155 0x000080, 0x808000, 0x800080, 0x008080 };
156 entries
[i
] = 0xff000000;
157 entries
[i
] |= halftone
[i
-8];
166 static WICColor
*generate_halftone27_palette(UINT
*count
, BOOL add_transparent
)
171 *count
= add_transparent
? 29 : 28;
172 entries
= HeapAlloc(GetProcessHeap(), 0, *count
* sizeof(WICColor
));
173 if (!entries
) return NULL
;
175 for (i
= 0; i
< 27; i
++)
177 static const BYTE halftone_values
[4] = { 0x00,0x80,0xff };
178 entries
[i
] = 0xff000000;
179 entries
[i
] |= halftone_values
[i
%3];
180 entries
[i
] |= halftone_values
[(i
/3)%3] << 8;
181 entries
[i
] |= halftone_values
[(i
/9)%3] << 16;
184 entries
[i
++] = 0xffc0c0c0;
191 static WICColor
*generate_halftone64_palette(UINT
*count
, BOOL add_transparent
)
196 *count
= add_transparent
? 73 : 72;
197 entries
= HeapAlloc(GetProcessHeap(), 0, *count
* sizeof(WICColor
));
198 if (!entries
) return NULL
;
200 for (i
= 0; i
< 64; i
++)
202 static const BYTE halftone_values
[4] = { 0x00,0x55,0xaa,0xff };
203 entries
[i
] = 0xff000000;
204 entries
[i
] |= halftone_values
[i
%4];
205 entries
[i
] |= halftone_values
[(i
/4)%4] << 8;
206 entries
[i
] |= halftone_values
[(i
/16)%4] << 16;
209 for (i
= 64; i
< 72; i
++)
211 static const DWORD halftone
[8] = { 0xc0c0c0, 0x808080, 0x800000, 0x008000,
212 0x000080, 0x808000, 0x800080, 0x008080 };
213 entries
[i
] = 0xff000000;
214 entries
[i
] |= halftone
[i
-64];
223 static WICColor
*generate_halftone125_palette(UINT
*count
, BOOL add_transparent
)
228 *count
= add_transparent
? 127 : 126;
229 entries
= HeapAlloc(GetProcessHeap(), 0, *count
* sizeof(WICColor
));
230 if (!entries
) return NULL
;
232 for (i
= 0; i
< 125; i
++)
234 static const BYTE halftone_values
[5] = { 0x00,0x40,0x80,0xbf,0xff };
235 entries
[i
] = 0xff000000;
236 entries
[i
] |= halftone_values
[i
%5];
237 entries
[i
] |= halftone_values
[(i
/5)%5] << 8;
238 entries
[i
] |= halftone_values
[(i
/25)%5] << 16;
241 entries
[i
++] = 0xffc0c0c0;
248 static WICColor
*generate_halftone216_palette(UINT
*count
, BOOL add_transparent
)
253 *count
= add_transparent
? 225 : 224;
254 entries
= HeapAlloc(GetProcessHeap(), 0, *count
* sizeof(WICColor
));
255 if (!entries
) return NULL
;
257 for (i
= 0; i
< 216; i
++)
259 static const BYTE halftone_values
[6] = { 0x00,0x33,0x66,0x99,0xcc,0xff };
260 entries
[i
] = 0xff000000;
261 entries
[i
] |= halftone_values
[i
%6];
262 entries
[i
] |= halftone_values
[(i
/6)%6] << 8;
263 entries
[i
] |= halftone_values
[(i
/36)%6] << 16;
266 for (i
= 216; i
< 224; i
++)
268 static const DWORD halftone
[8] = { 0xc0c0c0, 0x808080, 0x800000, 0x008000,
269 0x000080, 0x808000, 0x800080, 0x008080 };
270 entries
[i
] = 0xff000000;
271 entries
[i
] |= halftone
[i
-216];
280 static WICColor
*generate_halftone252_palette(UINT
*count
, BOOL add_transparent
)
285 *count
= add_transparent
? 253 : 252;
286 entries
= HeapAlloc(GetProcessHeap(), 0, *count
* sizeof(WICColor
));
287 if (!entries
) return NULL
;
289 for (i
= 0; i
< 252; i
++)
291 static const BYTE halftone_values_rb
[6] = { 0x00,0x33,0x66,0x99,0xcc,0xff };
292 static const BYTE halftone_values_g
[7] = { 0x00,0x2b,0x55,0x80,0xaa,0xd5,0xff };
293 entries
[i
] = 0xff000000;
294 entries
[i
] |= halftone_values_rb
[i
%6];
295 entries
[i
] |= halftone_values_g
[(i
/6)%7] << 8;
296 entries
[i
] |= halftone_values_rb
[(i
/42)%6] << 16;
305 static WICColor
*generate_halftone256_palette(UINT
*count
, BOOL add_transparent
)
311 entries
= HeapAlloc(GetProcessHeap(), 0, 256 * sizeof(WICColor
));
312 if (!entries
) return NULL
;
314 for (i
= 0; i
< 256; i
++)
316 static const BYTE halftone_values_b
[4] = { 0x00,0x55,0xaa,0xff };
317 static const BYTE halftone_values_gr
[8] = { 0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff };
318 entries
[i
] = 0xff000000;
319 entries
[i
] |= halftone_values_b
[i
%4];
320 entries
[i
] |= halftone_values_gr
[(i
/4)%8] << 8;
321 entries
[i
] |= halftone_values_gr
[(i
/32)%8] << 16;
330 static HRESULT WINAPI
PaletteImpl_InitializePredefined(IWICPalette
*iface
,
331 WICBitmapPaletteType type
, BOOL add_transparent
)
333 PaletteImpl
*This
= impl_from_IWICPalette(iface
);
337 TRACE("(%p,%u,%d)\n", iface
, type
, add_transparent
);
341 case WICBitmapPaletteTypeFixedBW
:
343 colors
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(WICColor
));
344 if (!colors
) return E_OUTOFMEMORY
;
345 colors
[0] = 0xff000000;
346 colors
[1] = 0xffffffff;
349 case WICBitmapPaletteTypeFixedGray4
:
351 colors
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(WICColor
));
352 if (!colors
) return E_OUTOFMEMORY
;
353 colors
[0] = 0xff000000;
354 colors
[1] = 0xff555555;
355 colors
[2] = 0xffaaaaaa;
356 colors
[3] = 0xffffffff;
359 case WICBitmapPaletteTypeFixedGray16
:
360 colors
= generate_gray16_palette(&count
);
361 if (!colors
) return E_OUTOFMEMORY
;
364 case WICBitmapPaletteTypeFixedGray256
:
365 colors
= generate_gray256_palette(&count
);
366 if (!colors
) return E_OUTOFMEMORY
;
369 case WICBitmapPaletteTypeFixedHalftone8
:
370 colors
= generate_halftone8_palette(&count
, add_transparent
);
371 if (!colors
) return E_OUTOFMEMORY
;
374 case WICBitmapPaletteTypeFixedHalftone27
:
375 colors
= generate_halftone27_palette(&count
, add_transparent
);
376 if (!colors
) return E_OUTOFMEMORY
;
379 case WICBitmapPaletteTypeFixedHalftone64
:
380 colors
= generate_halftone64_palette(&count
, add_transparent
);
381 if (!colors
) return E_OUTOFMEMORY
;
384 case WICBitmapPaletteTypeFixedHalftone125
:
385 colors
= generate_halftone125_palette(&count
, add_transparent
);
386 if (!colors
) return E_OUTOFMEMORY
;
389 case WICBitmapPaletteTypeFixedHalftone216
:
390 colors
= generate_halftone216_palette(&count
, add_transparent
);
391 if (!colors
) return E_OUTOFMEMORY
;
394 case WICBitmapPaletteTypeFixedHalftone252
:
395 colors
= generate_halftone252_palette(&count
, add_transparent
);
396 if (!colors
) return E_OUTOFMEMORY
;
399 case WICBitmapPaletteTypeFixedHalftone256
:
400 colors
= generate_halftone256_palette(&count
, add_transparent
);
401 if (!colors
) return E_OUTOFMEMORY
;
405 WARN("invalid palette type %u\n", type
);
409 EnterCriticalSection(&This
->lock
);
410 HeapFree(GetProcessHeap(), 0, This
->colors
);
411 This
->colors
= colors
;
414 LeaveCriticalSection(&This
->lock
);
419 static HRESULT WINAPI
PaletteImpl_InitializeCustom(IWICPalette
*iface
,
420 WICColor
*pColors
, UINT colorCount
)
422 PaletteImpl
*This
= impl_from_IWICPalette(iface
);
423 WICColor
*new_colors
;
425 TRACE("(%p,%p,%u)\n", iface
, pColors
, colorCount
);
433 if (!pColors
) return E_INVALIDARG
;
434 new_colors
= HeapAlloc(GetProcessHeap(), 0, sizeof(WICColor
) * colorCount
);
435 if (!new_colors
) return E_OUTOFMEMORY
;
436 memcpy(new_colors
, pColors
, sizeof(WICColor
) * colorCount
);
439 EnterCriticalSection(&This
->lock
);
440 HeapFree(GetProcessHeap(), 0, This
->colors
);
441 This
->colors
= new_colors
;
442 This
->count
= colorCount
;
443 This
->type
= WICBitmapPaletteTypeCustom
;
444 LeaveCriticalSection(&This
->lock
);
449 static HRESULT WINAPI
PaletteImpl_InitializeFromBitmap(IWICPalette
*iface
,
450 IWICBitmapSource
*pISurface
, UINT colorCount
, BOOL fAddTransparentColor
)
452 FIXME("(%p,%p,%u,%i): stub\n", iface
, pISurface
, colorCount
, fAddTransparentColor
);
456 static HRESULT WINAPI
PaletteImpl_InitializeFromPalette(IWICPalette
*iface
,
459 PaletteImpl
*This
= impl_from_IWICPalette(iface
);
461 WICColor
*colors
= NULL
;
462 WICBitmapPaletteType type
;
465 TRACE("(%p,%p)\n", iface
, source
);
467 if (!source
) return E_INVALIDARG
;
469 hr
= IWICPalette_GetType(source
, &type
);
470 if (hr
!= S_OK
) return hr
;
471 hr
= IWICPalette_GetColorCount(source
, &count
);
472 if (hr
!= S_OK
) return hr
;
475 colors
= HeapAlloc(GetProcessHeap(), 0, sizeof(WICColor
) * count
);
476 if (!colors
) return E_OUTOFMEMORY
;
477 hr
= IWICPalette_GetColors(source
, count
, colors
, &count
);
480 HeapFree(GetProcessHeap(), 0, colors
);
485 EnterCriticalSection(&This
->lock
);
486 HeapFree(GetProcessHeap(), 0, This
->colors
);
487 This
->colors
= colors
;
490 LeaveCriticalSection(&This
->lock
);
495 static HRESULT WINAPI
PaletteImpl_GetType(IWICPalette
*iface
,
496 WICBitmapPaletteType
*pePaletteType
)
498 PaletteImpl
*This
= impl_from_IWICPalette(iface
);
500 TRACE("(%p,%p)\n", iface
, pePaletteType
);
502 if (!pePaletteType
) return E_INVALIDARG
;
504 EnterCriticalSection(&This
->lock
);
505 *pePaletteType
= This
->type
;
506 LeaveCriticalSection(&This
->lock
);
511 static HRESULT WINAPI
PaletteImpl_GetColorCount(IWICPalette
*iface
, UINT
*pcCount
)
513 PaletteImpl
*This
= impl_from_IWICPalette(iface
);
515 TRACE("(%p,%p)\n", iface
, pcCount
);
517 if (!pcCount
) return E_INVALIDARG
;
519 EnterCriticalSection(&This
->lock
);
520 *pcCount
= This
->count
;
521 LeaveCriticalSection(&This
->lock
);
526 static HRESULT WINAPI
PaletteImpl_GetColors(IWICPalette
*iface
, UINT colorCount
,
527 WICColor
*pColors
, UINT
*pcActualColors
)
529 PaletteImpl
*This
= impl_from_IWICPalette(iface
);
531 TRACE("(%p,%i,%p,%p)\n", iface
, colorCount
, pColors
, pcActualColors
);
533 if (!pColors
|| !pcActualColors
) return E_INVALIDARG
;
535 EnterCriticalSection(&This
->lock
);
537 if (This
->count
< colorCount
) colorCount
= This
->count
;
539 memcpy(pColors
, This
->colors
, sizeof(WICColor
) * colorCount
);
541 *pcActualColors
= colorCount
;
543 LeaveCriticalSection(&This
->lock
);
548 static HRESULT WINAPI
PaletteImpl_IsBlackWhite(IWICPalette
*iface
, BOOL
*pfIsBlackWhite
)
550 PaletteImpl
*This
= impl_from_IWICPalette(iface
);
552 TRACE("(%p,%p)\n", iface
, pfIsBlackWhite
);
554 if (!pfIsBlackWhite
) return E_INVALIDARG
;
556 EnterCriticalSection(&This
->lock
);
557 if (This
->type
== WICBitmapPaletteTypeFixedBW
)
558 *pfIsBlackWhite
= TRUE
;
560 *pfIsBlackWhite
= FALSE
;
561 LeaveCriticalSection(&This
->lock
);
566 static HRESULT WINAPI
PaletteImpl_IsGrayscale(IWICPalette
*iface
, BOOL
*pfIsGrayscale
)
568 PaletteImpl
*This
= impl_from_IWICPalette(iface
);
570 TRACE("(%p,%p)\n", iface
, pfIsGrayscale
);
572 if (!pfIsGrayscale
) return E_INVALIDARG
;
574 EnterCriticalSection(&This
->lock
);
577 case WICBitmapPaletteTypeFixedBW
:
578 case WICBitmapPaletteTypeFixedGray4
:
579 case WICBitmapPaletteTypeFixedGray16
:
580 case WICBitmapPaletteTypeFixedGray256
:
581 *pfIsGrayscale
= TRUE
;
584 *pfIsGrayscale
= FALSE
;
586 LeaveCriticalSection(&This
->lock
);
591 static HRESULT WINAPI
PaletteImpl_HasAlpha(IWICPalette
*iface
, BOOL
*pfHasAlpha
)
593 PaletteImpl
*This
= impl_from_IWICPalette(iface
);
596 TRACE("(%p,%p)\n", iface
, pfHasAlpha
);
598 if (!pfHasAlpha
) return E_INVALIDARG
;
602 EnterCriticalSection(&This
->lock
);
603 for (i
=0; i
<This
->count
; i
++)
604 if ((This
->colors
[i
]&0xff000000) != 0xff000000)
609 LeaveCriticalSection(&This
->lock
);
614 static const IWICPaletteVtbl PaletteImpl_Vtbl
= {
615 PaletteImpl_QueryInterface
,
618 PaletteImpl_InitializePredefined
,
619 PaletteImpl_InitializeCustom
,
620 PaletteImpl_InitializeFromBitmap
,
621 PaletteImpl_InitializeFromPalette
,
623 PaletteImpl_GetColorCount
,
624 PaletteImpl_GetColors
,
625 PaletteImpl_IsBlackWhite
,
626 PaletteImpl_IsGrayscale
,
630 HRESULT
PaletteImpl_Create(IWICPalette
**palette
)
634 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(PaletteImpl
));
635 if (!This
) return E_OUTOFMEMORY
;
637 This
->IWICPalette_iface
.lpVtbl
= &PaletteImpl_Vtbl
;
641 This
->type
= WICBitmapPaletteTypeCustom
;
642 InitializeCriticalSection(&This
->lock
);
643 This
->lock
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": PaletteImpl.lock");
645 *palette
= &This
->IWICPalette_iface
;