2 * Copyright 2009 Vincent Povirk for CodeWeavers
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.
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.
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
32 #include "wincodecs_private.h"
34 #include "wine/debug.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(wincodecs
);
49 DWORD bc2ClrImportant
;
50 /* same as BITMAPINFOHEADER until this point */
55 DWORD bc2HalftoneSize1
;
56 DWORD bc2HalftoneSize2
;
61 struct BmpFrameDecode
;
62 typedef HRESULT (*ReadDataFunc
)(struct BmpFrameDecode
* This
);
64 typedef struct BmpFrameDecode
{
65 const IWICBitmapFrameDecodeVtbl
*lpVtbl
;
70 const WICPixelFormatGUID
*pixelformat
;
72 ReadDataFunc read_data_func
;
78 static HRESULT WINAPI
BmpFrameDecode_QueryInterface(IWICBitmapFrameDecode
*iface
, REFIID iid
,
81 BmpFrameDecode
*This
= (BmpFrameDecode
*)iface
;
82 TRACE("(%p,%s,%p)\n", iface
, debugstr_guid(iid
), ppv
);
84 if (!ppv
) return E_INVALIDARG
;
86 if (IsEqualIID(&IID_IUnknown
, iid
) ||
87 IsEqualIID(&IID_IWICBitmapSource
, iid
) ||
88 IsEqualIID(&IID_IWICBitmapFrameDecode
, iid
))
98 IUnknown_AddRef((IUnknown
*)*ppv
);
102 static ULONG WINAPI
BmpFrameDecode_AddRef(IWICBitmapFrameDecode
*iface
)
104 BmpFrameDecode
*This
= (BmpFrameDecode
*)iface
;
105 ULONG ref
= InterlockedIncrement(&This
->ref
);
107 TRACE("(%p) refcount=%u\n", iface
, ref
);
112 static ULONG WINAPI
BmpFrameDecode_Release(IWICBitmapFrameDecode
*iface
)
114 BmpFrameDecode
*This
= (BmpFrameDecode
*)iface
;
115 ULONG ref
= InterlockedDecrement(&This
->ref
);
117 TRACE("(%p) refcount=%u\n", iface
, ref
);
121 IStream_Release(This
->stream
);
122 HeapFree(GetProcessHeap(), 0, This
->imagedata
);
123 HeapFree(GetProcessHeap(), 0, This
);
129 static HRESULT WINAPI
BmpFrameDecode_GetSize(IWICBitmapFrameDecode
*iface
,
130 UINT
*puiWidth
, UINT
*puiHeight
)
132 BmpFrameDecode
*This
= (BmpFrameDecode
*)iface
;
133 TRACE("(%p,%p,%p)\n", iface
, puiWidth
, puiHeight
);
135 if (This
->bih
.bV5Size
== sizeof(BITMAPCOREHEADER
))
137 BITMAPCOREHEADER
*bch
= (BITMAPCOREHEADER
*)&This
->bih
;
138 *puiWidth
= bch
->bcWidth
;
139 *puiHeight
= bch
->bcHeight
;
143 *puiWidth
= This
->bih
.bV5Width
;
144 *puiHeight
= abs(This
->bih
.bV5Height
);
149 static HRESULT WINAPI
BmpFrameDecode_GetPixelFormat(IWICBitmapFrameDecode
*iface
,
150 WICPixelFormatGUID
*pPixelFormat
)
152 BmpFrameDecode
*This
= (BmpFrameDecode
*)iface
;
153 TRACE("(%p,%p)\n", iface
, pPixelFormat
);
155 memcpy(pPixelFormat
, This
->pixelformat
, sizeof(GUID
));
160 static HRESULT
BmpHeader_GetResolution(BITMAPV5HEADER
*bih
, double *pDpiX
, double *pDpiY
)
162 switch (bih
->bV5Size
)
164 case sizeof(BITMAPCOREHEADER
):
168 case sizeof(BITMAPCOREHEADER2
):
169 case sizeof(BITMAPINFOHEADER
):
170 case sizeof(BITMAPV4HEADER
):
171 case sizeof(BITMAPV5HEADER
):
172 *pDpiX
= bih
->bV5XPelsPerMeter
* 0.0254;
173 *pDpiY
= bih
->bV5YPelsPerMeter
* 0.0254;
180 static HRESULT WINAPI
BmpFrameDecode_GetResolution(IWICBitmapFrameDecode
*iface
,
181 double *pDpiX
, double *pDpiY
)
183 BmpFrameDecode
*This
= (BmpFrameDecode
*)iface
;
184 TRACE("(%p,%p,%p)\n", iface
, pDpiX
, pDpiY
);
186 return BmpHeader_GetResolution(&This
->bih
, pDpiX
, pDpiY
);
189 static HRESULT WINAPI
BmpFrameDecode_CopyPalette(IWICBitmapFrameDecode
*iface
,
190 IWICPalette
*pIPalette
)
193 BmpFrameDecode
*This
= (BmpFrameDecode
*)iface
;
195 WICColor
*wiccolors
=NULL
;
196 RGBTRIPLE
*bgrcolors
=NULL
;
198 TRACE("(%p,%p)\n", iface
, pIPalette
);
200 if (This
->bih
.bV5Size
== sizeof(BITMAPCOREHEADER
))
202 BITMAPCOREHEADER
*bch
= (BITMAPCOREHEADER
*)&This
->bih
;
203 if (bch
->bcBitCount
<= 8)
205 /* 2**n colors in BGR format after the header */
206 ULONG tablesize
, bytesread
;
207 LARGE_INTEGER offset
;
210 count
= 1 << bch
->bcBitCount
;
211 wiccolors
= HeapAlloc(GetProcessHeap(), 0, sizeof(WICColor
) * count
);
212 tablesize
= sizeof(RGBTRIPLE
) * count
;
213 bgrcolors
= HeapAlloc(GetProcessHeap(), 0, tablesize
);
214 if (!wiccolors
|| !bgrcolors
)
220 offset
.QuadPart
= sizeof(BITMAPFILEHEADER
)+sizeof(BITMAPCOREHEADER
);
221 hr
= IStream_Seek(This
->stream
, offset
, STREAM_SEEK_SET
, NULL
);
222 if (FAILED(hr
)) goto end
;
224 hr
= IStream_Read(This
->stream
, bgrcolors
, tablesize
, &bytesread
);
225 if (FAILED(hr
)) goto end
;
226 if (bytesread
!= tablesize
) {
231 for (i
=0; i
<count
; i
++)
233 wiccolors
[i
] = 0xff000000|
234 (bgrcolors
[i
].rgbtRed
<<16)|
235 (bgrcolors
[i
].rgbtGreen
<<8)|
236 bgrcolors
[i
].rgbtBlue
;
241 return WINCODEC_ERR_PALETTEUNAVAILABLE
;
246 if (This
->bih
.bV5BitCount
<= 8)
248 ULONG tablesize
, bytesread
;
249 LARGE_INTEGER offset
;
252 if (This
->bih
.bV5ClrUsed
== 0)
253 count
= 1 << This
->bih
.bV5BitCount
;
255 count
= This
->bih
.bV5ClrUsed
;
257 tablesize
= sizeof(WICColor
) * count
;
258 wiccolors
= HeapAlloc(GetProcessHeap(), 0, tablesize
);
259 if (!wiccolors
) return E_OUTOFMEMORY
;
261 offset
.QuadPart
= sizeof(BITMAPFILEHEADER
) + This
->bih
.bV5Size
;
262 hr
= IStream_Seek(This
->stream
, offset
, STREAM_SEEK_SET
, NULL
);
263 if (FAILED(hr
)) goto end
;
265 hr
= IStream_Read(This
->stream
, wiccolors
, tablesize
, &bytesread
);
266 if (FAILED(hr
)) goto end
;
267 if (bytesread
!= tablesize
) {
272 /* convert from BGR to BGRA by setting alpha to 100% */
273 for (i
=0; i
<count
; i
++)
274 wiccolors
[i
] |= 0xff000000;
278 return WINCODEC_ERR_PALETTEUNAVAILABLE
;
282 hr
= IWICPalette_InitializeCustom(pIPalette
, wiccolors
, count
);
285 HeapFree(GetProcessHeap(), 0, wiccolors
);
286 HeapFree(GetProcessHeap(), 0, bgrcolors
);
290 static HRESULT WINAPI
BmpFrameDecode_CopyPixels(IWICBitmapFrameDecode
*iface
,
291 const WICRect
*prc
, UINT cbStride
, UINT cbBufferSize
, BYTE
*pbBuffer
)
293 BmpFrameDecode
*This
= (BmpFrameDecode
*)iface
;
296 TRACE("(%p,%p,%u,%u,%p)\n", iface
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
298 if (!This
->imagedata
)
300 hr
= This
->read_data_func(This
);
301 if (FAILED(hr
)) return hr
;
304 hr
= BmpFrameDecode_GetSize(iface
, &width
, &height
);
305 if (FAILED(hr
)) return hr
;
307 return copy_pixels(This
->bitsperpixel
, This
->imagedatastart
,
308 width
, height
, This
->stride
,
309 prc
, cbStride
, cbBufferSize
, pbBuffer
);
312 static HRESULT WINAPI
BmpFrameDecode_GetMetadataQueryReader(IWICBitmapFrameDecode
*iface
,
313 IWICMetadataQueryReader
**ppIMetadataQueryReader
)
315 TRACE("(%p,%p)\n", iface
, ppIMetadataQueryReader
);
316 return WINCODEC_ERR_UNSUPPORTEDOPERATION
;
319 static HRESULT WINAPI
BmpFrameDecode_GetColorContexts(IWICBitmapFrameDecode
*iface
,
320 UINT cCount
, IWICColorContext
**ppIColorContexts
, UINT
*pcActualCount
)
322 TRACE("(%p,%u,%p,%p)\n", iface
, cCount
, ppIColorContexts
, pcActualCount
);
323 return WINCODEC_ERR_UNSUPPORTEDOPERATION
;
326 static HRESULT WINAPI
BmpFrameDecode_GetThumbnail(IWICBitmapFrameDecode
*iface
,
327 IWICBitmapSource
**ppIThumbnail
)
329 TRACE("(%p,%p)\n", iface
, ppIThumbnail
);
330 return WINCODEC_ERR_CODECNOTHUMBNAIL
;
333 static HRESULT
BmpFrameDecode_ReadUncompressed(BmpFrameDecode
* This
)
340 LARGE_INTEGER offbits
;
343 if (This
->bih
.bV5Size
== sizeof(BITMAPCOREHEADER
))
345 BITMAPCOREHEADER
*bch
= (BITMAPCOREHEADER
*)&This
->bih
;
346 width
= bch
->bcWidth
;
347 height
= bch
->bcHeight
;
352 width
= This
->bih
.bV5Width
;
353 height
= abs(This
->bih
.bV5Height
);
354 bottomup
= (This
->bih
.bV5Height
> 0);
357 /* row sizes in BMP files must be divisible by 4 bytes */
358 bytesperrow
= (((width
* This
->bitsperpixel
)+31)/32)*4;
359 datasize
= bytesperrow
* height
;
361 This
->imagedata
= HeapAlloc(GetProcessHeap(), 0, datasize
);
362 if (!This
->imagedata
) return E_OUTOFMEMORY
;
364 offbits
.QuadPart
= This
->bfh
.bfOffBits
;
365 hr
= IStream_Seek(This
->stream
, offbits
, STREAM_SEEK_SET
, NULL
);
366 if (FAILED(hr
)) goto fail
;
368 hr
= IStream_Read(This
->stream
, This
->imagedata
, datasize
, &bytesread
);
369 if (FAILED(hr
) || bytesread
!= datasize
) goto fail
;
373 This
->imagedatastart
= This
->imagedata
+ (height
-1) * bytesperrow
;
374 This
->stride
= -bytesperrow
;
378 This
->imagedatastart
= This
->imagedata
;
379 This
->stride
= bytesperrow
;
384 HeapFree(GetProcessHeap(), 0, This
->imagedata
);
385 This
->imagedata
= NULL
;
386 if (SUCCEEDED(hr
)) hr
= E_FAIL
;
390 static HRESULT
BmpFrameDecode_ReadRLE8(BmpFrameDecode
* This
)
394 BYTE
*rledata
, *cursor
, *rledataend
;
395 UINT rlesize
, datasize
, palettesize
;
400 LARGE_INTEGER offbits
;
403 width
= This
->bih
.bV5Width
;
404 height
= abs(This
->bih
.bV5Height
);
405 bytesperrow
= width
* 4;
406 datasize
= bytesperrow
* height
;
407 rlesize
= This
->bih
.bV5SizeImage
;
408 if (This
->bih
.bV5ClrUsed
&& This
->bih
.bV5ClrUsed
< 256)
409 palettesize
= 4 * This
->bih
.bV5ClrUsed
;
411 palettesize
= 4 * 256;
413 rledata
= HeapAlloc(GetProcessHeap(), 0, rlesize
);
414 This
->imagedata
= HeapAlloc(GetProcessHeap(), 0, datasize
);
415 if (!This
->imagedata
|| !rledata
)
422 offbits
.QuadPart
= sizeof(BITMAPFILEHEADER
) + This
->bih
.bV5Size
;
423 hr
= IStream_Seek(This
->stream
, offbits
, STREAM_SEEK_SET
, NULL
);
424 if (FAILED(hr
)) goto fail
;
426 hr
= IStream_Read(This
->stream
, palette
, palettesize
, &bytesread
);
427 if (FAILED(hr
) || bytesread
!= palettesize
) goto fail
;
430 offbits
.QuadPart
= This
->bfh
.bfOffBits
;
431 hr
= IStream_Seek(This
->stream
, offbits
, STREAM_SEEK_SET
, NULL
);
432 if (FAILED(hr
)) goto fail
;
434 hr
= IStream_Read(This
->stream
, rledata
, rlesize
, &bytesread
);
435 if (FAILED(hr
) || bytesread
!= rlesize
) goto fail
;
438 bgrdata
= (DWORD
*)This
->imagedata
;
441 rledataend
= rledata
+ rlesize
;
443 while (cursor
< rledataend
&& y
< height
)
445 BYTE length
= *cursor
++;
449 BYTE escape
= *cursor
++;
452 case 0: /* end of line */
456 case 1: /* end of bitmap */
459 if (cursor
< rledataend
)
465 default: /* absolute mode */
467 while (cursor
< rledataend
&& length
-- && x
< width
)
468 bgrdata
[y
*width
+ x
++] = palette
[*cursor
++];
469 if (escape
& 1) cursor
++; /* skip pad byte */
474 DWORD color
= palette
[*cursor
++];
475 while (length
-- && x
< width
)
476 bgrdata
[y
*width
+ x
++] = color
;
481 HeapFree(GetProcessHeap(), 0, rledata
);
483 This
->imagedatastart
= This
->imagedata
+ (height
-1) * bytesperrow
;
484 This
->stride
= -bytesperrow
;
489 HeapFree(GetProcessHeap(), 0, rledata
);
490 HeapFree(GetProcessHeap(), 0, This
->imagedata
);
491 This
->imagedata
= NULL
;
492 if (SUCCEEDED(hr
)) hr
= E_FAIL
;
496 static HRESULT
BmpFrameDecode_ReadRLE4(BmpFrameDecode
* This
)
500 BYTE
*rledata
, *cursor
, *rledataend
;
501 UINT rlesize
, datasize
, palettesize
;
506 LARGE_INTEGER offbits
;
509 width
= This
->bih
.bV5Width
;
510 height
= abs(This
->bih
.bV5Height
);
511 bytesperrow
= width
* 4;
512 datasize
= bytesperrow
* height
;
513 rlesize
= This
->bih
.bV5SizeImage
;
514 if (This
->bih
.bV5ClrUsed
&& This
->bih
.bV5ClrUsed
< 16)
515 palettesize
= 4 * This
->bih
.bV5ClrUsed
;
517 palettesize
= 4 * 16;
519 rledata
= HeapAlloc(GetProcessHeap(), 0, rlesize
);
520 This
->imagedata
= HeapAlloc(GetProcessHeap(), 0, datasize
);
521 if (!This
->imagedata
|| !rledata
)
528 offbits
.QuadPart
= sizeof(BITMAPFILEHEADER
) + This
->bih
.bV5Size
;
529 hr
= IStream_Seek(This
->stream
, offbits
, STREAM_SEEK_SET
, NULL
);
530 if (FAILED(hr
)) goto fail
;
532 hr
= IStream_Read(This
->stream
, palette
, palettesize
, &bytesread
);
533 if (FAILED(hr
) || bytesread
!= palettesize
) goto fail
;
536 offbits
.QuadPart
= This
->bfh
.bfOffBits
;
537 hr
= IStream_Seek(This
->stream
, offbits
, STREAM_SEEK_SET
, NULL
);
538 if (FAILED(hr
)) goto fail
;
540 hr
= IStream_Read(This
->stream
, rledata
, rlesize
, &bytesread
);
541 if (FAILED(hr
) || bytesread
!= rlesize
) goto fail
;
544 bgrdata
= (DWORD
*)This
->imagedata
;
547 rledataend
= rledata
+ rlesize
;
549 while (cursor
< rledataend
&& y
< height
)
551 BYTE length
= *cursor
++;
555 BYTE escape
= *cursor
++;
558 case 0: /* end of line */
562 case 1: /* end of bitmap */
565 if (cursor
< rledataend
)
571 default: /* absolute mode */
573 while (cursor
< rledataend
&& length
-- && x
< width
)
575 BYTE colors
= *cursor
++;
576 bgrdata
[y
*width
+ x
++] = palette
[colors
>>4];
577 if (length
-- && x
< width
)
578 bgrdata
[y
*width
+ x
++] = palette
[colors
&0xf];
582 if ((cursor
- rledata
) & 1) cursor
++; /* skip pad byte */
587 BYTE colors
= *cursor
++;
588 DWORD color1
= palette
[colors
>>4];
589 DWORD color2
= palette
[colors
&0xf];
590 while (length
-- && x
< width
)
592 bgrdata
[y
*width
+ x
++] = color1
;
593 if (length
-- && x
< width
)
594 bgrdata
[y
*width
+ x
++] = color2
;
602 HeapFree(GetProcessHeap(), 0, rledata
);
604 This
->imagedatastart
= This
->imagedata
+ (height
-1) * bytesperrow
;
605 This
->stride
= -bytesperrow
;
610 HeapFree(GetProcessHeap(), 0, rledata
);
611 HeapFree(GetProcessHeap(), 0, This
->imagedata
);
612 This
->imagedata
= NULL
;
613 if (SUCCEEDED(hr
)) hr
= E_FAIL
;
617 static HRESULT
BmpFrameDecode_ReadUnsupported(BmpFrameDecode
* This
)
622 struct bitfields_format
{
623 WORD bitcount
; /* 0 for end of list */
628 const WICPixelFormatGUID
*pixelformat
;
629 ReadDataFunc read_data_func
;
632 static const struct bitfields_format bitfields_formats
[] = {
633 {16,0x7c00,0x3e0,0x1f,0,&GUID_WICPixelFormat16bppBGR555
,BmpFrameDecode_ReadUncompressed
},
634 {16,0xf800,0x7e0,0x1f,0,&GUID_WICPixelFormat16bppBGR565
,BmpFrameDecode_ReadUncompressed
},
635 {32,0xff0000,0xff00,0xff,0,&GUID_WICPixelFormat32bppBGR
,BmpFrameDecode_ReadUncompressed
},
636 {32,0xff0000,0xff00,0xff,0xff000000,&GUID_WICPixelFormat32bppBGRA
,BmpFrameDecode_ReadUncompressed
},
640 static const IWICBitmapFrameDecodeVtbl BmpFrameDecode_Vtbl
= {
641 BmpFrameDecode_QueryInterface
,
642 BmpFrameDecode_AddRef
,
643 BmpFrameDecode_Release
,
644 BmpFrameDecode_GetSize
,
645 BmpFrameDecode_GetPixelFormat
,
646 BmpFrameDecode_GetResolution
,
647 BmpFrameDecode_CopyPalette
,
648 BmpFrameDecode_CopyPixels
,
649 BmpFrameDecode_GetMetadataQueryReader
,
650 BmpFrameDecode_GetColorContexts
,
651 BmpFrameDecode_GetThumbnail
655 const IWICBitmapDecoderVtbl
*lpVtbl
;
659 BITMAPFILEHEADER bfh
;
661 BmpFrameDecode
*framedecode
;
662 const WICPixelFormatGUID
*pixelformat
;
664 ReadDataFunc read_data_func
;
667 static HRESULT
BmpDecoder_ReadHeaders(BmpDecoder
* This
, IStream
*stream
)
670 ULONG bytestoread
, bytesread
;
673 if (This
->initialized
) return WINCODEC_ERR_WRONGSTATE
;
676 hr
= IStream_Seek(stream
, seek
, STREAM_SEEK_SET
, NULL
);
677 if (FAILED(hr
)) return hr
;
679 hr
= IStream_Read(stream
, &This
->bfh
, sizeof(BITMAPFILEHEADER
), &bytesread
);
680 if (FAILED(hr
)) return hr
;
681 if (bytesread
!= sizeof(BITMAPFILEHEADER
) ||
682 This
->bfh
.bfType
!= 0x4d42 /* "BM" */) return E_FAIL
;
684 hr
= IStream_Read(stream
, &This
->bih
.bV5Size
, sizeof(DWORD
), &bytesread
);
685 if (FAILED(hr
)) return hr
;
686 if (bytesread
!= sizeof(DWORD
) ||
687 (This
->bih
.bV5Size
!= sizeof(BITMAPCOREHEADER
) &&
688 This
->bih
.bV5Size
!= sizeof(BITMAPCOREHEADER2
) &&
689 This
->bih
.bV5Size
!= sizeof(BITMAPINFOHEADER
) &&
690 This
->bih
.bV5Size
!= sizeof(BITMAPV4HEADER
) &&
691 This
->bih
.bV5Size
!= sizeof(BITMAPV5HEADER
))) return E_FAIL
;
693 bytestoread
= This
->bih
.bV5Size
-sizeof(DWORD
);
694 hr
= IStream_Read(stream
, &This
->bih
.bV5Width
, bytestoread
, &bytesread
);
695 if (FAILED(hr
)) return hr
;
696 if (bytestoread
!= bytesread
) return E_FAIL
;
698 /* if this is a BITMAPINFOHEADER with BI_BITFIELDS compression, we need to
699 read the extra fields */
700 if (This
->bih
.bV5Size
== sizeof(BITMAPINFOHEADER
) &&
701 This
->bih
.bV5Compression
== BI_BITFIELDS
)
703 hr
= IStream_Read(stream
, &This
->bih
.bV5RedMask
, 12, &bytesread
);
704 if (FAILED(hr
)) return hr
;
705 if (bytesread
!= 12) return E_FAIL
;
706 This
->bih
.bV5AlphaMask
= 0;
709 /* decide what kind of bitmap this is and how/if we can read it */
710 if (This
->bih
.bV5Size
== sizeof(BITMAPCOREHEADER
))
712 BITMAPCOREHEADER
*bch
= (BITMAPCOREHEADER
*)&This
->bih
;
713 TRACE("BITMAPCOREHEADER with depth=%i\n", bch
->bcBitCount
);
714 This
->bitsperpixel
= bch
->bcBitCount
;
715 This
->read_data_func
= BmpFrameDecode_ReadUncompressed
;
716 switch(bch
->bcBitCount
)
719 This
->pixelformat
= &GUID_WICPixelFormat1bppIndexed
;
722 This
->pixelformat
= &GUID_WICPixelFormat2bppIndexed
;
725 This
->pixelformat
= &GUID_WICPixelFormat4bppIndexed
;
728 This
->pixelformat
= &GUID_WICPixelFormat8bppIndexed
;
731 This
->pixelformat
= &GUID_WICPixelFormat24bppBGR
;
734 This
->pixelformat
= &GUID_WICPixelFormatUndefined
;
735 WARN("unsupported bit depth %i for BITMAPCOREHEADER\n", bch
->bcBitCount
);
739 else /* struct is compatible with BITMAPINFOHEADER */
741 TRACE("bitmap header=%i compression=%i depth=%i\n", This
->bih
.bV5Size
, This
->bih
.bV5Compression
, This
->bih
.bV5BitCount
);
742 switch(This
->bih
.bV5Compression
)
745 This
->bitsperpixel
= This
->bih
.bV5BitCount
;
746 This
->read_data_func
= BmpFrameDecode_ReadUncompressed
;
747 switch(This
->bih
.bV5BitCount
)
750 This
->pixelformat
= &GUID_WICPixelFormat1bppIndexed
;
753 This
->pixelformat
= &GUID_WICPixelFormat2bppIndexed
;
756 This
->pixelformat
= &GUID_WICPixelFormat4bppIndexed
;
759 This
->pixelformat
= &GUID_WICPixelFormat8bppIndexed
;
762 This
->pixelformat
= &GUID_WICPixelFormat16bppBGR555
;
765 This
->pixelformat
= &GUID_WICPixelFormat24bppBGR
;
768 This
->pixelformat
= &GUID_WICPixelFormat32bppBGR
;
771 This
->pixelformat
= &GUID_WICPixelFormatUndefined
;
772 FIXME("unsupported bit depth %i for uncompressed RGB\n", This
->bih
.bV5BitCount
);
776 This
->bitsperpixel
= 32;
777 This
->read_data_func
= BmpFrameDecode_ReadRLE8
;
778 This
->pixelformat
= &GUID_WICPixelFormat32bppBGR
;
781 This
->bitsperpixel
= 32;
782 This
->read_data_func
= BmpFrameDecode_ReadRLE4
;
783 This
->pixelformat
= &GUID_WICPixelFormat32bppBGR
;
787 const struct bitfields_format
*format
;
788 if (This
->bih
.bV5Size
== sizeof(BITMAPCOREHEADER2
))
790 /* BCH2 doesn't support bitfields; this is Huffman 1D compression */
791 This
->bitsperpixel
= 0;
792 This
->read_data_func
= BmpFrameDecode_ReadUnsupported
;
793 This
->pixelformat
= &GUID_WICPixelFormatUndefined
;
794 FIXME("Huffman 1D compression is unsupported\n");
797 This
->bitsperpixel
= This
->bih
.bV5BitCount
;
798 for (format
= bitfields_formats
; format
->bitcount
; format
++)
800 if ((format
->bitcount
== This
->bih
.bV5BitCount
) &&
801 (format
->redmask
== This
->bih
.bV5RedMask
) &&
802 (format
->greenmask
== This
->bih
.bV5GreenMask
) &&
803 (format
->bluemask
== This
->bih
.bV5BlueMask
) &&
804 (format
->alphamask
== This
->bih
.bV5AlphaMask
))
806 This
->read_data_func
= format
->read_data_func
;
807 This
->pixelformat
= format
->pixelformat
;
811 if (!format
->bitcount
)
813 This
->read_data_func
= BmpFrameDecode_ReadUncompressed
;
814 This
->pixelformat
= &GUID_WICPixelFormatUndefined
;
815 FIXME("unsupported bitfields type depth=%i red=%x green=%x blue=%x alpha=%x\n",
816 This
->bih
.bV5BitCount
, This
->bih
.bV5RedMask
, This
->bih
.bV5GreenMask
, This
->bih
.bV5BlueMask
, This
->bih
.bV5AlphaMask
);
821 This
->bitsperpixel
= 0;
822 This
->read_data_func
= BmpFrameDecode_ReadUnsupported
;
823 This
->pixelformat
= &GUID_WICPixelFormatUndefined
;
824 FIXME("unsupported bitmap type header=%i compression=%i depth=%i\n", This
->bih
.bV5Size
, This
->bih
.bV5Compression
, This
->bih
.bV5BitCount
);
829 This
->initialized
= TRUE
;
834 static HRESULT WINAPI
BmpDecoder_QueryInterface(IWICBitmapDecoder
*iface
, REFIID iid
,
837 BmpDecoder
*This
= (BmpDecoder
*)iface
;
838 TRACE("(%p,%s,%p)\n", iface
, debugstr_guid(iid
), ppv
);
840 if (!ppv
) return E_INVALIDARG
;
842 if (IsEqualIID(&IID_IUnknown
, iid
) || IsEqualIID(&IID_IWICBitmapDecoder
, iid
))
849 return E_NOINTERFACE
;
852 IUnknown_AddRef((IUnknown
*)*ppv
);
856 static ULONG WINAPI
BmpDecoder_AddRef(IWICBitmapDecoder
*iface
)
858 BmpDecoder
*This
= (BmpDecoder
*)iface
;
859 ULONG ref
= InterlockedIncrement(&This
->ref
);
861 TRACE("(%p) refcount=%u\n", iface
, ref
);
866 static ULONG WINAPI
BmpDecoder_Release(IWICBitmapDecoder
*iface
)
868 BmpDecoder
*This
= (BmpDecoder
*)iface
;
869 ULONG ref
= InterlockedDecrement(&This
->ref
);
871 TRACE("(%p) refcount=%u\n", iface
, ref
);
875 if (This
->stream
) IStream_Release(This
->stream
);
876 if (This
->framedecode
) IUnknown_Release((IUnknown
*)This
->framedecode
);
877 HeapFree(GetProcessHeap(), 0, This
);
883 static HRESULT WINAPI
BmpDecoder_QueryCapability(IWICBitmapDecoder
*iface
, IStream
*pIStream
,
884 DWORD
*pdwCapability
)
887 BmpDecoder
*This
= (BmpDecoder
*)iface
;
889 hr
= BmpDecoder_ReadHeaders(This
, pIStream
);
890 if (FAILED(hr
)) return hr
;
892 if (This
->read_data_func
== BmpFrameDecode_ReadUnsupported
)
895 *pdwCapability
= WICBitmapDecoderCapabilityCanDecodeAllImages
;
900 static HRESULT WINAPI
BmpDecoder_Initialize(IWICBitmapDecoder
*iface
, IStream
*pIStream
,
901 WICDecodeOptions cacheOptions
)
904 BmpDecoder
*This
= (BmpDecoder
*)iface
;
906 hr
= BmpDecoder_ReadHeaders(This
, pIStream
);
910 This
->stream
= pIStream
;
911 IStream_AddRef(pIStream
);
917 static HRESULT WINAPI
BmpDecoder_GetContainerFormat(IWICBitmapDecoder
*iface
,
918 GUID
*pguidContainerFormat
)
920 memcpy(pguidContainerFormat
, &GUID_ContainerFormatBmp
, sizeof(GUID
));
924 static HRESULT WINAPI
BmpDecoder_GetDecoderInfo(IWICBitmapDecoder
*iface
,
925 IWICBitmapDecoderInfo
**ppIDecoderInfo
)
928 IWICComponentInfo
*compinfo
;
930 TRACE("(%p,%p)\n", iface
, ppIDecoderInfo
);
932 hr
= CreateComponentInfo(&CLSID_WICBmpDecoder
, &compinfo
);
933 if (FAILED(hr
)) return hr
;
935 hr
= IWICComponentInfo_QueryInterface(compinfo
, &IID_IWICBitmapDecoderInfo
,
936 (void**)ppIDecoderInfo
);
938 IWICComponentInfo_Release(compinfo
);
943 static HRESULT WINAPI
BmpDecoder_CopyPalette(IWICBitmapDecoder
*iface
,
944 IWICPalette
*pIPalette
)
946 TRACE("(%p,%p)\n", iface
, pIPalette
);
948 return WINCODEC_ERR_PALETTEUNAVAILABLE
;
951 static HRESULT WINAPI
BmpDecoder_GetMetadataQueryReader(IWICBitmapDecoder
*iface
,
952 IWICMetadataQueryReader
**ppIMetadataQueryReader
)
954 TRACE("(%p,%p)\n", iface
, ppIMetadataQueryReader
);
955 return WINCODEC_ERR_UNSUPPORTEDOPERATION
;
958 static HRESULT WINAPI
BmpDecoder_GetPreview(IWICBitmapDecoder
*iface
,
959 IWICBitmapSource
**ppIBitmapSource
)
961 TRACE("(%p,%p)\n", iface
, ppIBitmapSource
);
962 return WINCODEC_ERR_UNSUPPORTEDOPERATION
;
965 static HRESULT WINAPI
BmpDecoder_GetColorContexts(IWICBitmapDecoder
*iface
,
966 UINT cCount
, IWICColorContext
**ppIColorContexts
, UINT
*pcActualCount
)
968 TRACE("(%p,%u,%p,%p)\n", iface
, cCount
, ppIColorContexts
, pcActualCount
);
969 return WINCODEC_ERR_UNSUPPORTEDOPERATION
;
972 static HRESULT WINAPI
BmpDecoder_GetThumbnail(IWICBitmapDecoder
*iface
,
973 IWICBitmapSource
**ppIThumbnail
)
975 TRACE("(%p,%p)\n", iface
, ppIThumbnail
);
976 return WINCODEC_ERR_CODECNOTHUMBNAIL
;
979 static HRESULT WINAPI
BmpDecoder_GetFrameCount(IWICBitmapDecoder
*iface
,
986 static HRESULT WINAPI
BmpDecoder_GetFrame(IWICBitmapDecoder
*iface
,
987 UINT index
, IWICBitmapFrameDecode
**ppIBitmapFrame
)
989 BmpDecoder
*This
= (BmpDecoder
*)iface
;
991 if (index
!= 0) return E_INVALIDARG
;
993 if (!This
->stream
) return WINCODEC_ERR_WRONGSTATE
;
995 if (!This
->framedecode
)
997 This
->framedecode
= HeapAlloc(GetProcessHeap(), 0, sizeof(BmpFrameDecode
));
998 if (!This
->framedecode
) return E_OUTOFMEMORY
;
1000 This
->framedecode
->lpVtbl
= &BmpFrameDecode_Vtbl
;
1001 This
->framedecode
->ref
= 1;
1002 This
->framedecode
->stream
= This
->stream
;
1003 IStream_AddRef(This
->stream
);
1004 This
->framedecode
->bfh
= This
->bfh
;
1005 This
->framedecode
->bih
= This
->bih
;
1006 This
->framedecode
->pixelformat
= This
->pixelformat
;
1007 This
->framedecode
->bitsperpixel
= This
->bitsperpixel
;
1008 This
->framedecode
->read_data_func
= This
->read_data_func
;
1009 This
->framedecode
->imagedata
= NULL
;
1012 *ppIBitmapFrame
= (IWICBitmapFrameDecode
*)This
->framedecode
;
1013 IWICBitmapFrameDecode_AddRef((IWICBitmapFrameDecode
*)This
->framedecode
);
1018 static const IWICBitmapDecoderVtbl BmpDecoder_Vtbl
= {
1019 BmpDecoder_QueryInterface
,
1022 BmpDecoder_QueryCapability
,
1023 BmpDecoder_Initialize
,
1024 BmpDecoder_GetContainerFormat
,
1025 BmpDecoder_GetDecoderInfo
,
1026 BmpDecoder_CopyPalette
,
1027 BmpDecoder_GetMetadataQueryReader
,
1028 BmpDecoder_GetPreview
,
1029 BmpDecoder_GetColorContexts
,
1030 BmpDecoder_GetThumbnail
,
1031 BmpDecoder_GetFrameCount
,
1035 HRESULT
BmpDecoder_CreateInstance(IUnknown
*pUnkOuter
, REFIID iid
, void** ppv
)
1040 TRACE("(%p,%s,%p)\n", pUnkOuter
, debugstr_guid(iid
), ppv
);
1044 if (pUnkOuter
) return CLASS_E_NOAGGREGATION
;
1046 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(BmpDecoder
));
1047 if (!This
) return E_OUTOFMEMORY
;
1049 This
->lpVtbl
= &BmpDecoder_Vtbl
;
1051 This
->initialized
= FALSE
;
1052 This
->stream
= NULL
;
1053 This
->framedecode
= NULL
;
1055 ret
= IUnknown_QueryInterface((IUnknown
*)This
, iid
, ppv
);
1056 IUnknown_Release((IUnknown
*)This
);