1c2c66affSColin Finck /*
2c2c66affSColin Finck * Copyright 2009 Vincent Povirk for CodeWeavers
3c2c66affSColin Finck *
4c2c66affSColin Finck * This library is free software; you can redistribute it and/or
5c2c66affSColin Finck * modify it under the terms of the GNU Lesser General Public
6c2c66affSColin Finck * License as published by the Free Software Foundation; either
7c2c66affSColin Finck * version 2.1 of the License, or (at your option) any later version.
8c2c66affSColin Finck *
9c2c66affSColin Finck * This library is distributed in the hope that it will be useful,
10c2c66affSColin Finck * but WITHOUT ANY WARRANTY; without even the implied warranty of
11c2c66affSColin Finck * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12c2c66affSColin Finck * Lesser General Public License for more details.
13c2c66affSColin Finck *
14c2c66affSColin Finck * You should have received a copy of the GNU Lesser General Public
15c2c66affSColin Finck * License along with this library; if not, write to the Free Software
16c2c66affSColin Finck * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17c2c66affSColin Finck */
18c2c66affSColin Finck
19ae80686dSAmine Khaldi #include "config.h"
20c2c66affSColin Finck
21c2c66affSColin Finck #include <assert.h>
22ae80686dSAmine Khaldi #include <stdarg.h>
23ae80686dSAmine Khaldi
24ae80686dSAmine Khaldi #define COBJMACROS
25ae80686dSAmine Khaldi
26ae80686dSAmine Khaldi #include "windef.h"
27ae80686dSAmine Khaldi #include "winbase.h"
28ae80686dSAmine Khaldi #include "winreg.h"
29ae80686dSAmine Khaldi #include "wingdi.h"
30ae80686dSAmine Khaldi #include "objbase.h"
31ae80686dSAmine Khaldi
32ae80686dSAmine Khaldi #include "wincodecs_private.h"
33ae80686dSAmine Khaldi
34ae80686dSAmine Khaldi #include "wine/debug.h"
35ae80686dSAmine Khaldi
36ae80686dSAmine Khaldi WINE_DEFAULT_DEBUG_CHANNEL(wincodecs);
37c2c66affSColin Finck
38c2c66affSColin Finck typedef struct {
39c2c66affSColin Finck DWORD bc2Size;
40c2c66affSColin Finck DWORD bc2Width;
41c2c66affSColin Finck DWORD bc2Height;
42c2c66affSColin Finck WORD bc2Planes;
43c2c66affSColin Finck WORD bc2BitCount;
44c2c66affSColin Finck DWORD bc2Compression;
45c2c66affSColin Finck DWORD bc2SizeImage;
46c2c66affSColin Finck DWORD bc2XRes;
47c2c66affSColin Finck DWORD bc2YRes;
48c2c66affSColin Finck DWORD bc2ClrUsed;
49c2c66affSColin Finck DWORD bc2ClrImportant;
50c2c66affSColin Finck /* same as BITMAPINFOHEADER until this point */
51c2c66affSColin Finck WORD bc2ResUnit;
52c2c66affSColin Finck WORD bc2Reserved;
53c2c66affSColin Finck WORD bc2Orientation;
54c2c66affSColin Finck WORD bc2Halftoning;
55c2c66affSColin Finck DWORD bc2HalftoneSize1;
56c2c66affSColin Finck DWORD bc2HalftoneSize2;
57c2c66affSColin Finck DWORD bc2ColorSpace;
58c2c66affSColin Finck DWORD bc2AppData;
59c2c66affSColin Finck } BITMAPCOREHEADER2;
60c2c66affSColin Finck
61c2c66affSColin Finck typedef HRESULT (*ReadDataFunc)(BmpDecoder* This);
62c2c66affSColin Finck
63c2c66affSColin Finck struct BmpDecoder {
64c2c66affSColin Finck IWICBitmapDecoder IWICBitmapDecoder_iface;
65c2c66affSColin Finck IWICBitmapFrameDecode IWICBitmapFrameDecode_iface;
66c2c66affSColin Finck LONG ref;
67c2c66affSColin Finck BOOL initialized;
68c2c66affSColin Finck IStream *stream;
69c2c66affSColin Finck ULONG palette_offset;
70c2c66affSColin Finck ULONG image_offset;
71c2c66affSColin Finck BITMAPV5HEADER bih;
72c2c66affSColin Finck const WICPixelFormatGUID *pixelformat;
73c2c66affSColin Finck int bitsperpixel;
74c2c66affSColin Finck ReadDataFunc read_data_func;
75c2c66affSColin Finck INT stride;
76c2c66affSColin Finck BYTE *imagedata;
77c2c66affSColin Finck BYTE *imagedatastart;
78c2c66affSColin Finck CRITICAL_SECTION lock; /* must be held when initialized/imagedata is set or stream is accessed */
79c2c66affSColin Finck int packed; /* If TRUE, don't look for a file header and assume a packed DIB. */
80c2c66affSColin Finck int icoframe; /* If TRUE, this is a frame of a .ico file. */
81c2c66affSColin Finck };
82c2c66affSColin Finck
impl_from_IWICBitmapDecoder(IWICBitmapDecoder * iface)83c2c66affSColin Finck static inline BmpDecoder *impl_from_IWICBitmapDecoder(IWICBitmapDecoder *iface)
84c2c66affSColin Finck {
85c2c66affSColin Finck return CONTAINING_RECORD(iface, BmpDecoder, IWICBitmapDecoder_iface);
86c2c66affSColin Finck }
87c2c66affSColin Finck
impl_from_IWICBitmapFrameDecode(IWICBitmapFrameDecode * iface)88c2c66affSColin Finck static inline BmpDecoder *impl_from_IWICBitmapFrameDecode(IWICBitmapFrameDecode *iface)
89c2c66affSColin Finck {
90c2c66affSColin Finck return CONTAINING_RECORD(iface, BmpDecoder, IWICBitmapFrameDecode_iface);
91c2c66affSColin Finck }
92c2c66affSColin Finck
BmpFrameDecode_QueryInterface(IWICBitmapFrameDecode * iface,REFIID iid,void ** ppv)93c2c66affSColin Finck static HRESULT WINAPI BmpFrameDecode_QueryInterface(IWICBitmapFrameDecode *iface, REFIID iid,
94c2c66affSColin Finck void **ppv)
95c2c66affSColin Finck {
96c2c66affSColin Finck BmpDecoder *This = impl_from_IWICBitmapFrameDecode(iface);
97c2c66affSColin Finck
98c2c66affSColin Finck TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
99c2c66affSColin Finck
100c2c66affSColin Finck if (!ppv) return E_INVALIDARG;
101c2c66affSColin Finck
102c2c66affSColin Finck if (IsEqualIID(&IID_IUnknown, iid) ||
103c2c66affSColin Finck IsEqualIID(&IID_IWICBitmapSource, iid) ||
104c2c66affSColin Finck IsEqualIID(&IID_IWICBitmapFrameDecode, iid))
105c2c66affSColin Finck {
106c2c66affSColin Finck *ppv = &This->IWICBitmapFrameDecode_iface;
107c2c66affSColin Finck }
108c2c66affSColin Finck else
109c2c66affSColin Finck {
110c2c66affSColin Finck *ppv = NULL;
111c2c66affSColin Finck return E_NOINTERFACE;
112c2c66affSColin Finck }
113c2c66affSColin Finck
114c2c66affSColin Finck IUnknown_AddRef((IUnknown*)*ppv);
115c2c66affSColin Finck return S_OK;
116c2c66affSColin Finck }
117c2c66affSColin Finck
BmpFrameDecode_AddRef(IWICBitmapFrameDecode * iface)118c2c66affSColin Finck static ULONG WINAPI BmpFrameDecode_AddRef(IWICBitmapFrameDecode *iface)
119c2c66affSColin Finck {
120c2c66affSColin Finck BmpDecoder *This = impl_from_IWICBitmapFrameDecode(iface);
121c2c66affSColin Finck
122c2c66affSColin Finck return IWICBitmapDecoder_AddRef(&This->IWICBitmapDecoder_iface);
123c2c66affSColin Finck }
124c2c66affSColin Finck
BmpFrameDecode_Release(IWICBitmapFrameDecode * iface)125c2c66affSColin Finck static ULONG WINAPI BmpFrameDecode_Release(IWICBitmapFrameDecode *iface)
126c2c66affSColin Finck {
127c2c66affSColin Finck BmpDecoder *This = impl_from_IWICBitmapFrameDecode(iface);
128c2c66affSColin Finck
129c2c66affSColin Finck return IWICBitmapDecoder_Release(&This->IWICBitmapDecoder_iface);
130c2c66affSColin Finck }
131c2c66affSColin Finck
BmpFrameDecode_GetSize(IWICBitmapFrameDecode * iface,UINT * puiWidth,UINT * puiHeight)132c2c66affSColin Finck static HRESULT WINAPI BmpFrameDecode_GetSize(IWICBitmapFrameDecode *iface,
133c2c66affSColin Finck UINT *puiWidth, UINT *puiHeight)
134c2c66affSColin Finck {
135c2c66affSColin Finck BmpDecoder *This = impl_from_IWICBitmapFrameDecode(iface);
136c2c66affSColin Finck TRACE("(%p,%p,%p)\n", iface, puiWidth, puiHeight);
137c2c66affSColin Finck
138c2c66affSColin Finck if (This->bih.bV5Size == sizeof(BITMAPCOREHEADER))
139c2c66affSColin Finck {
140c2c66affSColin Finck BITMAPCOREHEADER *bch = (BITMAPCOREHEADER*)&This->bih;
141c2c66affSColin Finck *puiWidth = bch->bcWidth;
142c2c66affSColin Finck *puiHeight = bch->bcHeight;
143c2c66affSColin Finck }
144c2c66affSColin Finck else
145c2c66affSColin Finck {
146c2c66affSColin Finck *puiWidth = This->bih.bV5Width;
147c2c66affSColin Finck *puiHeight = abs(This->bih.bV5Height);
148c2c66affSColin Finck }
149c2c66affSColin Finck return S_OK;
150c2c66affSColin Finck }
151c2c66affSColin Finck
BmpFrameDecode_GetPixelFormat(IWICBitmapFrameDecode * iface,WICPixelFormatGUID * pPixelFormat)152c2c66affSColin Finck static HRESULT WINAPI BmpFrameDecode_GetPixelFormat(IWICBitmapFrameDecode *iface,
153c2c66affSColin Finck WICPixelFormatGUID *pPixelFormat)
154c2c66affSColin Finck {
155c2c66affSColin Finck BmpDecoder *This = impl_from_IWICBitmapFrameDecode(iface);
156c2c66affSColin Finck TRACE("(%p,%p)\n", iface, pPixelFormat);
157c2c66affSColin Finck
158c2c66affSColin Finck memcpy(pPixelFormat, This->pixelformat, sizeof(GUID));
159c2c66affSColin Finck
160c2c66affSColin Finck return S_OK;
161c2c66affSColin Finck }
162c2c66affSColin Finck
BmpHeader_GetResolution(BITMAPV5HEADER * bih,double * pDpiX,double * pDpiY)163c2c66affSColin Finck static HRESULT BmpHeader_GetResolution(BITMAPV5HEADER *bih, double *pDpiX, double *pDpiY)
164c2c66affSColin Finck {
165c2c66affSColin Finck LONG resx = 0, resy = 0;
166c2c66affSColin Finck
167c2c66affSColin Finck switch (bih->bV5Size)
168c2c66affSColin Finck {
169c2c66affSColin Finck default:
170c2c66affSColin Finck case sizeof(BITMAPCOREHEADER):
171c2c66affSColin Finck break;
172c2c66affSColin Finck
173c2c66affSColin Finck case sizeof(BITMAPCOREHEADER2):
174c2c66affSColin Finck case sizeof(BITMAPINFOHEADER):
175c2c66affSColin Finck case sizeof(BITMAPV4HEADER):
176c2c66affSColin Finck case sizeof(BITMAPV5HEADER):
177c2c66affSColin Finck resx = bih->bV5XPelsPerMeter;
178c2c66affSColin Finck resy = bih->bV5YPelsPerMeter;
179c2c66affSColin Finck break;
180c2c66affSColin Finck }
181c2c66affSColin Finck
182c2c66affSColin Finck if (!resx || !resy)
183c2c66affSColin Finck {
184c2c66affSColin Finck *pDpiX = 96.0;
185c2c66affSColin Finck *pDpiY = 96.0;
186c2c66affSColin Finck }
187c2c66affSColin Finck else
188c2c66affSColin Finck {
189c2c66affSColin Finck *pDpiX = resx * 0.0254;
190c2c66affSColin Finck *pDpiY = resy * 0.0254;
191c2c66affSColin Finck }
192c2c66affSColin Finck
193c2c66affSColin Finck return S_OK;
194c2c66affSColin Finck }
195c2c66affSColin Finck
BmpFrameDecode_GetResolution(IWICBitmapFrameDecode * iface,double * pDpiX,double * pDpiY)196c2c66affSColin Finck static HRESULT WINAPI BmpFrameDecode_GetResolution(IWICBitmapFrameDecode *iface,
197c2c66affSColin Finck double *pDpiX, double *pDpiY)
198c2c66affSColin Finck {
199c2c66affSColin Finck BmpDecoder *This = impl_from_IWICBitmapFrameDecode(iface);
200c2c66affSColin Finck TRACE("(%p,%p,%p)\n", iface, pDpiX, pDpiY);
201c2c66affSColin Finck
202c2c66affSColin Finck return BmpHeader_GetResolution(&This->bih, pDpiX, pDpiY);
203c2c66affSColin Finck }
204c2c66affSColin Finck
BmpFrameDecode_CopyPalette(IWICBitmapFrameDecode * iface,IWICPalette * pIPalette)205c2c66affSColin Finck static HRESULT WINAPI BmpFrameDecode_CopyPalette(IWICBitmapFrameDecode *iface,
206c2c66affSColin Finck IWICPalette *pIPalette)
207c2c66affSColin Finck {
208c2c66affSColin Finck HRESULT hr;
209c2c66affSColin Finck BmpDecoder *This = impl_from_IWICBitmapFrameDecode(iface);
210c2c66affSColin Finck int count;
211c2c66affSColin Finck WICColor *wiccolors=NULL;
212c2c66affSColin Finck RGBTRIPLE *bgrcolors=NULL;
213c2c66affSColin Finck
214c2c66affSColin Finck TRACE("(%p,%p)\n", iface, pIPalette);
215c2c66affSColin Finck
216c2c66affSColin Finck EnterCriticalSection(&This->lock);
217c2c66affSColin Finck
218c2c66affSColin Finck if (This->bih.bV5Size == sizeof(BITMAPCOREHEADER))
219c2c66affSColin Finck {
220c2c66affSColin Finck BITMAPCOREHEADER *bch = (BITMAPCOREHEADER*)&This->bih;
221c2c66affSColin Finck if (bch->bcBitCount <= 8)
222c2c66affSColin Finck {
223c2c66affSColin Finck /* 2**n colors in BGR format after the header */
224c2c66affSColin Finck ULONG tablesize, bytesread;
225c2c66affSColin Finck LARGE_INTEGER offset;
226c2c66affSColin Finck int i;
227c2c66affSColin Finck
228c2c66affSColin Finck count = 1 << bch->bcBitCount;
229c2c66affSColin Finck wiccolors = HeapAlloc(GetProcessHeap(), 0, sizeof(WICColor) * count);
230c2c66affSColin Finck tablesize = sizeof(RGBTRIPLE) * count;
231c2c66affSColin Finck bgrcolors = HeapAlloc(GetProcessHeap(), 0, tablesize);
232c2c66affSColin Finck if (!wiccolors || !bgrcolors)
233c2c66affSColin Finck {
234c2c66affSColin Finck hr = E_OUTOFMEMORY;
235c2c66affSColin Finck goto end;
236c2c66affSColin Finck }
237c2c66affSColin Finck
238c2c66affSColin Finck offset.QuadPart = This->palette_offset;
239c2c66affSColin Finck hr = IStream_Seek(This->stream, offset, STREAM_SEEK_SET, NULL);
240c2c66affSColin Finck if (FAILED(hr)) goto end;
241c2c66affSColin Finck
242c2c66affSColin Finck hr = IStream_Read(This->stream, bgrcolors, tablesize, &bytesread);
243c2c66affSColin Finck if (FAILED(hr)) goto end;
244c2c66affSColin Finck if (bytesread != tablesize) {
245c2c66affSColin Finck hr = E_FAIL;
246c2c66affSColin Finck goto end;
247c2c66affSColin Finck }
248c2c66affSColin Finck
249c2c66affSColin Finck for (i=0; i<count; i++)
250c2c66affSColin Finck {
251c2c66affSColin Finck wiccolors[i] = 0xff000000|
252c2c66affSColin Finck (bgrcolors[i].rgbtRed<<16)|
253c2c66affSColin Finck (bgrcolors[i].rgbtGreen<<8)|
254c2c66affSColin Finck bgrcolors[i].rgbtBlue;
255c2c66affSColin Finck }
256c2c66affSColin Finck }
257c2c66affSColin Finck else
258c2c66affSColin Finck {
259c2c66affSColin Finck hr = WINCODEC_ERR_PALETTEUNAVAILABLE;
260c2c66affSColin Finck goto end;
261c2c66affSColin Finck }
262c2c66affSColin Finck }
263c2c66affSColin Finck else
264c2c66affSColin Finck {
265c2c66affSColin Finck if (This->bih.bV5BitCount <= 8)
266c2c66affSColin Finck {
267c2c66affSColin Finck ULONG tablesize, bytesread;
268c2c66affSColin Finck LARGE_INTEGER offset;
269c2c66affSColin Finck int i;
270c2c66affSColin Finck
271c2c66affSColin Finck if (This->bih.bV5ClrUsed == 0)
272c2c66affSColin Finck count = 1 << This->bih.bV5BitCount;
273c2c66affSColin Finck else
274ae80686dSAmine Khaldi count = min(This->bih.bV5ClrUsed, 1 << This->bih.bV5BitCount);
275c2c66affSColin Finck
276c2c66affSColin Finck tablesize = sizeof(WICColor) * count;
277c2c66affSColin Finck wiccolors = HeapAlloc(GetProcessHeap(), 0, tablesize);
278c2c66affSColin Finck if (!wiccolors)
279c2c66affSColin Finck {
280c2c66affSColin Finck hr = E_OUTOFMEMORY;
281c2c66affSColin Finck goto end;
282c2c66affSColin Finck }
283c2c66affSColin Finck
284c2c66affSColin Finck offset.QuadPart = This->palette_offset;
285c2c66affSColin Finck hr = IStream_Seek(This->stream, offset, STREAM_SEEK_SET, NULL);
286c2c66affSColin Finck if (FAILED(hr)) goto end;
287c2c66affSColin Finck
288c2c66affSColin Finck hr = IStream_Read(This->stream, wiccolors, tablesize, &bytesread);
289c2c66affSColin Finck if (FAILED(hr)) goto end;
290c2c66affSColin Finck if (bytesread != tablesize) {
291c2c66affSColin Finck hr = E_FAIL;
292c2c66affSColin Finck goto end;
293c2c66affSColin Finck }
294c2c66affSColin Finck
295c2c66affSColin Finck /* convert from BGR to BGRA by setting alpha to 100% */
296c2c66affSColin Finck for (i=0; i<count; i++)
297c2c66affSColin Finck wiccolors[i] |= 0xff000000;
298c2c66affSColin Finck }
299c2c66affSColin Finck else
300c2c66affSColin Finck {
301c2c66affSColin Finck hr = WINCODEC_ERR_PALETTEUNAVAILABLE;
302c2c66affSColin Finck goto end;
303c2c66affSColin Finck }
304c2c66affSColin Finck }
305c2c66affSColin Finck
306c2c66affSColin Finck end:
307c2c66affSColin Finck
308c2c66affSColin Finck LeaveCriticalSection(&This->lock);
309c2c66affSColin Finck
310c2c66affSColin Finck if (SUCCEEDED(hr))
311c2c66affSColin Finck hr = IWICPalette_InitializeCustom(pIPalette, wiccolors, count);
312c2c66affSColin Finck
313c2c66affSColin Finck HeapFree(GetProcessHeap(), 0, wiccolors);
314c2c66affSColin Finck HeapFree(GetProcessHeap(), 0, bgrcolors);
315c2c66affSColin Finck return hr;
316c2c66affSColin Finck }
317c2c66affSColin Finck
BmpFrameDecode_CopyPixels(IWICBitmapFrameDecode * iface,const WICRect * prc,UINT cbStride,UINT cbBufferSize,BYTE * pbBuffer)318c2c66affSColin Finck static HRESULT WINAPI BmpFrameDecode_CopyPixels(IWICBitmapFrameDecode *iface,
319c2c66affSColin Finck const WICRect *prc, UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer)
320c2c66affSColin Finck {
321c2c66affSColin Finck BmpDecoder *This = impl_from_IWICBitmapFrameDecode(iface);
322c2c66affSColin Finck HRESULT hr=S_OK;
323c2c66affSColin Finck UINT width, height;
324e98ef499SAmine Khaldi TRACE("(%p,%s,%u,%u,%p)\n", iface, debug_wic_rect(prc), cbStride, cbBufferSize, pbBuffer);
325c2c66affSColin Finck
326c2c66affSColin Finck EnterCriticalSection(&This->lock);
327c2c66affSColin Finck if (!This->imagedata)
328c2c66affSColin Finck {
329c2c66affSColin Finck hr = This->read_data_func(This);
330c2c66affSColin Finck }
331c2c66affSColin Finck LeaveCriticalSection(&This->lock);
332c2c66affSColin Finck if (FAILED(hr)) return hr;
333c2c66affSColin Finck
334c2c66affSColin Finck hr = BmpFrameDecode_GetSize(iface, &width, &height);
335c2c66affSColin Finck if (FAILED(hr)) return hr;
336c2c66affSColin Finck
337c2c66affSColin Finck return copy_pixels(This->bitsperpixel, This->imagedatastart,
338c2c66affSColin Finck width, height, This->stride,
339c2c66affSColin Finck prc, cbStride, cbBufferSize, pbBuffer);
340c2c66affSColin Finck }
341c2c66affSColin Finck
BmpFrameDecode_GetMetadataQueryReader(IWICBitmapFrameDecode * iface,IWICMetadataQueryReader ** ppIMetadataQueryReader)342c2c66affSColin Finck static HRESULT WINAPI BmpFrameDecode_GetMetadataQueryReader(IWICBitmapFrameDecode *iface,
343c2c66affSColin Finck IWICMetadataQueryReader **ppIMetadataQueryReader)
344c2c66affSColin Finck {
345c2c66affSColin Finck TRACE("(%p,%p)\n", iface, ppIMetadataQueryReader);
346c2c66affSColin Finck return WINCODEC_ERR_UNSUPPORTEDOPERATION;
347c2c66affSColin Finck }
348c2c66affSColin Finck
BmpFrameDecode_GetColorContexts(IWICBitmapFrameDecode * iface,UINT cCount,IWICColorContext ** ppIColorContexts,UINT * pcActualCount)349c2c66affSColin Finck static HRESULT WINAPI BmpFrameDecode_GetColorContexts(IWICBitmapFrameDecode *iface,
350c2c66affSColin Finck UINT cCount, IWICColorContext **ppIColorContexts, UINT *pcActualCount)
351c2c66affSColin Finck {
352c2c66affSColin Finck TRACE("(%p,%u,%p,%p)\n", iface, cCount, ppIColorContexts, pcActualCount);
353c2c66affSColin Finck return WINCODEC_ERR_UNSUPPORTEDOPERATION;
354c2c66affSColin Finck }
355c2c66affSColin Finck
BmpFrameDecode_GetThumbnail(IWICBitmapFrameDecode * iface,IWICBitmapSource ** ppIThumbnail)356c2c66affSColin Finck static HRESULT WINAPI BmpFrameDecode_GetThumbnail(IWICBitmapFrameDecode *iface,
357c2c66affSColin Finck IWICBitmapSource **ppIThumbnail)
358c2c66affSColin Finck {
359c2c66affSColin Finck TRACE("(%p,%p)\n", iface, ppIThumbnail);
360c2c66affSColin Finck return WINCODEC_ERR_CODECNOTHUMBNAIL;
361c2c66affSColin Finck }
362c2c66affSColin Finck
BmpFrameDecode_ReadUncompressed(BmpDecoder * This)363c2c66affSColin Finck static HRESULT BmpFrameDecode_ReadUncompressed(BmpDecoder* This)
364c2c66affSColin Finck {
365c2c66affSColin Finck UINT bytesperrow;
366c2c66affSColin Finck UINT width, height;
367c2c66affSColin Finck UINT datasize;
368c2c66affSColin Finck int bottomup;
369c2c66affSColin Finck HRESULT hr;
370c2c66affSColin Finck LARGE_INTEGER offbits;
371c2c66affSColin Finck ULONG bytesread;
372c2c66affSColin Finck
373c2c66affSColin Finck if (This->bih.bV5Size == sizeof(BITMAPCOREHEADER))
374c2c66affSColin Finck {
375c2c66affSColin Finck BITMAPCOREHEADER *bch = (BITMAPCOREHEADER*)&This->bih;
376c2c66affSColin Finck width = bch->bcWidth;
377c2c66affSColin Finck height = bch->bcHeight;
378c2c66affSColin Finck bottomup = 1;
379c2c66affSColin Finck }
380c2c66affSColin Finck else
381c2c66affSColin Finck {
382c2c66affSColin Finck width = This->bih.bV5Width;
383c2c66affSColin Finck height = abs(This->bih.bV5Height);
384c2c66affSColin Finck bottomup = (This->bih.bV5Height > 0);
385c2c66affSColin Finck }
386c2c66affSColin Finck
387c2c66affSColin Finck /* row sizes in BMP files must be divisible by 4 bytes */
388c2c66affSColin Finck bytesperrow = (((width * This->bitsperpixel)+31)/32)*4;
389c2c66affSColin Finck datasize = bytesperrow * height;
390c2c66affSColin Finck
391c2c66affSColin Finck This->imagedata = HeapAlloc(GetProcessHeap(), 0, datasize);
392c2c66affSColin Finck if (!This->imagedata) return E_OUTOFMEMORY;
393c2c66affSColin Finck
394c2c66affSColin Finck offbits.QuadPart = This->image_offset;
395c2c66affSColin Finck hr = IStream_Seek(This->stream, offbits, STREAM_SEEK_SET, NULL);
396c2c66affSColin Finck if (FAILED(hr)) goto fail;
397c2c66affSColin Finck
398c2c66affSColin Finck hr = IStream_Read(This->stream, This->imagedata, datasize, &bytesread);
399c2c66affSColin Finck if (FAILED(hr) || bytesread != datasize) goto fail;
400c2c66affSColin Finck
401c2c66affSColin Finck if (bottomup)
402c2c66affSColin Finck {
403c2c66affSColin Finck This->imagedatastart = This->imagedata + (height-1) * bytesperrow;
404c2c66affSColin Finck This->stride = -bytesperrow;
405c2c66affSColin Finck }
406c2c66affSColin Finck else
407c2c66affSColin Finck {
408c2c66affSColin Finck This->imagedatastart = This->imagedata;
409c2c66affSColin Finck This->stride = bytesperrow;
410c2c66affSColin Finck }
411c2c66affSColin Finck return S_OK;
412c2c66affSColin Finck
413c2c66affSColin Finck fail:
414c2c66affSColin Finck HeapFree(GetProcessHeap(), 0, This->imagedata);
415c2c66affSColin Finck This->imagedata = NULL;
416c2c66affSColin Finck if (SUCCEEDED(hr)) hr = E_FAIL;
417c2c66affSColin Finck return hr;
418c2c66affSColin Finck }
419c2c66affSColin Finck
BmpFrameDecode_ReadRGB8(BmpDecoder * This)420c2c66affSColin Finck static HRESULT BmpFrameDecode_ReadRGB8(BmpDecoder* This)
421c2c66affSColin Finck {
422c2c66affSColin Finck HRESULT hr;
423c2c66affSColin Finck UINT width, height;
424c2c66affSColin Finck
425c2c66affSColin Finck hr = IWICBitmapFrameDecode_GetSize(&This->IWICBitmapFrameDecode_iface, &width, &height);
426c2c66affSColin Finck
427c2c66affSColin Finck if (SUCCEEDED(hr))
428c2c66affSColin Finck {
429c2c66affSColin Finck hr = BmpFrameDecode_ReadUncompressed(This);
430c2c66affSColin Finck }
431c2c66affSColin Finck
432c2c66affSColin Finck if (SUCCEEDED(hr))
433c2c66affSColin Finck {
434c2c66affSColin Finck reverse_bgr8(This->bitsperpixel/8, This->imagedatastart,
435c2c66affSColin Finck width, height, This->stride);
436c2c66affSColin Finck }
437c2c66affSColin Finck
438c2c66affSColin Finck return hr;
439c2c66affSColin Finck }
440c2c66affSColin Finck
ReadByte(IStream * stream,BYTE * buffer,ULONG buffer_size,ULONG * cursor,ULONG * bytesread,BYTE * result)441c2c66affSColin Finck static HRESULT ReadByte(IStream *stream, BYTE *buffer, ULONG buffer_size,
442c2c66affSColin Finck ULONG *cursor, ULONG *bytesread, BYTE *result)
443c2c66affSColin Finck {
444c2c66affSColin Finck HRESULT hr=S_OK;
445c2c66affSColin Finck
446c2c66affSColin Finck if (*bytesread == 0 || *cursor == *bytesread)
447c2c66affSColin Finck {
448c2c66affSColin Finck hr = IStream_Read(stream, buffer, buffer_size, bytesread);
449c2c66affSColin Finck *cursor = 0;
450c2c66affSColin Finck }
451c2c66affSColin Finck
452c2c66affSColin Finck if (SUCCEEDED(hr))
453c2c66affSColin Finck {
454c2c66affSColin Finck if (*cursor < *bytesread)
455c2c66affSColin Finck *result = buffer[(*cursor)++];
456c2c66affSColin Finck else
457c2c66affSColin Finck hr = E_FAIL;
458c2c66affSColin Finck }
459c2c66affSColin Finck
460c2c66affSColin Finck return hr;
461c2c66affSColin Finck }
462c2c66affSColin Finck
BmpFrameDecode_ReadRLE8(BmpDecoder * This)463c2c66affSColin Finck static HRESULT BmpFrameDecode_ReadRLE8(BmpDecoder* This)
464c2c66affSColin Finck {
465c2c66affSColin Finck UINT bytesperrow;
466c2c66affSColin Finck UINT width, height;
467c2c66affSColin Finck BYTE rledata[4096];
468c2c66affSColin Finck UINT datasize, palettesize;
469c2c66affSColin Finck DWORD palette[256];
470c2c66affSColin Finck UINT x, y;
471c2c66affSColin Finck DWORD *bgrdata;
472c2c66affSColin Finck HRESULT hr;
473c2c66affSColin Finck LARGE_INTEGER offbits;
474c2c66affSColin Finck ULONG cursor=0, bytesread=0;
475c2c66affSColin Finck
476c2c66affSColin Finck width = This->bih.bV5Width;
477c2c66affSColin Finck height = abs(This->bih.bV5Height);
478c2c66affSColin Finck bytesperrow = width * 4;
479c2c66affSColin Finck datasize = bytesperrow * height;
480c2c66affSColin Finck if (This->bih.bV5ClrUsed && This->bih.bV5ClrUsed < 256)
481c2c66affSColin Finck palettesize = 4 * This->bih.bV5ClrUsed;
482c2c66affSColin Finck else
483c2c66affSColin Finck palettesize = 4 * 256;
484c2c66affSColin Finck
485c2c66affSColin Finck This->imagedata = HeapAlloc(GetProcessHeap(), 0, datasize);
486c2c66affSColin Finck if (!This->imagedata)
487c2c66affSColin Finck {
488c2c66affSColin Finck hr = E_OUTOFMEMORY;
489c2c66affSColin Finck goto fail;
490c2c66affSColin Finck }
491c2c66affSColin Finck
492c2c66affSColin Finck /* read palette */
493c2c66affSColin Finck offbits.QuadPart = This->palette_offset;
494c2c66affSColin Finck hr = IStream_Seek(This->stream, offbits, STREAM_SEEK_SET, NULL);
495c2c66affSColin Finck if (FAILED(hr)) goto fail;
496c2c66affSColin Finck
497c2c66affSColin Finck hr = IStream_Read(This->stream, palette, palettesize, &bytesread);
498c2c66affSColin Finck if (FAILED(hr) || bytesread != palettesize) goto fail;
499c2c66affSColin Finck
500c2c66affSColin Finck /* read RLE data */
501c2c66affSColin Finck offbits.QuadPart = This->image_offset;
502c2c66affSColin Finck hr = IStream_Seek(This->stream, offbits, STREAM_SEEK_SET, NULL);
503c2c66affSColin Finck if (FAILED(hr)) goto fail;
504c2c66affSColin Finck
505c2c66affSColin Finck /* decode RLE */
506c2c66affSColin Finck bgrdata = (DWORD*)This->imagedata;
507c2c66affSColin Finck x = 0;
508c2c66affSColin Finck y = 0;
509c2c66affSColin Finck cursor = 0;
510c2c66affSColin Finck bytesread = 0;
511c2c66affSColin Finck while (y < height)
512c2c66affSColin Finck {
513c2c66affSColin Finck BYTE length;
514c2c66affSColin Finck hr = ReadByte(This->stream, rledata, 4096, &cursor, &bytesread, &length);
515c2c66affSColin Finck
516c2c66affSColin Finck if (FAILED(hr))
517c2c66affSColin Finck goto fail;
518c2c66affSColin Finck else if (length == 0)
519c2c66affSColin Finck {
520c2c66affSColin Finck /* escape code */
521c2c66affSColin Finck BYTE escape;
522c2c66affSColin Finck hr = ReadByte(This->stream, rledata, 4096, &cursor, &bytesread, &escape);
523c2c66affSColin Finck if (FAILED(hr))
524c2c66affSColin Finck goto fail;
525c2c66affSColin Finck switch(escape)
526c2c66affSColin Finck {
527c2c66affSColin Finck case 0: /* end of line */
528c2c66affSColin Finck x = 0;
529c2c66affSColin Finck y++;
530c2c66affSColin Finck break;
531c2c66affSColin Finck case 1: /* end of bitmap */
532c2c66affSColin Finck goto end;
533c2c66affSColin Finck case 2: /* delta */
534c2c66affSColin Finck {
535c2c66affSColin Finck BYTE dx, dy;
536c2c66affSColin Finck hr = ReadByte(This->stream, rledata, 4096, &cursor, &bytesread, &dx);
537c2c66affSColin Finck if (SUCCEEDED(hr))
538c2c66affSColin Finck hr = ReadByte(This->stream, rledata, 4096, &cursor, &bytesread, &dy);
539c2c66affSColin Finck if (FAILED(hr))
540c2c66affSColin Finck goto fail;
541c2c66affSColin Finck x += dx;
542c2c66affSColin Finck y += dy;
543c2c66affSColin Finck break;
544c2c66affSColin Finck }
545c2c66affSColin Finck default: /* absolute mode */
546c2c66affSColin Finck length = escape;
547c2c66affSColin Finck while (length-- && x < width)
548c2c66affSColin Finck {
549c2c66affSColin Finck BYTE index;
550c2c66affSColin Finck hr = ReadByte(This->stream, rledata, 4096, &cursor, &bytesread, &index);
551c2c66affSColin Finck if (FAILED(hr))
552c2c66affSColin Finck goto fail;
553c2c66affSColin Finck bgrdata[y*width + x++] = palette[index];
554c2c66affSColin Finck }
555c2c66affSColin Finck if (escape & 1)
556c2c66affSColin Finck hr = ReadByte(This->stream, rledata, 4096, &cursor, &bytesread, &length); /* skip pad byte */
557c2c66affSColin Finck if (FAILED(hr))
558c2c66affSColin Finck goto fail;
559c2c66affSColin Finck }
560c2c66affSColin Finck }
561c2c66affSColin Finck else
562c2c66affSColin Finck {
563c2c66affSColin Finck BYTE index;
564c2c66affSColin Finck DWORD color;
565c2c66affSColin Finck hr = ReadByte(This->stream, rledata, 4096, &cursor, &bytesread, &index);
566c2c66affSColin Finck if (FAILED(hr))
567c2c66affSColin Finck goto fail;
568c2c66affSColin Finck color = palette[index];
569c2c66affSColin Finck while (length-- && x < width)
570c2c66affSColin Finck bgrdata[y*width + x++] = color;
571c2c66affSColin Finck }
572c2c66affSColin Finck }
573c2c66affSColin Finck
574c2c66affSColin Finck end:
575c2c66affSColin Finck This->imagedatastart = This->imagedata + (height-1) * bytesperrow;
576c2c66affSColin Finck This->stride = -bytesperrow;
577c2c66affSColin Finck
578c2c66affSColin Finck return S_OK;
579c2c66affSColin Finck
580c2c66affSColin Finck fail:
581c2c66affSColin Finck HeapFree(GetProcessHeap(), 0, This->imagedata);
582c2c66affSColin Finck This->imagedata = NULL;
583c2c66affSColin Finck if (SUCCEEDED(hr)) hr = E_FAIL;
584c2c66affSColin Finck return hr;
585c2c66affSColin Finck }
586c2c66affSColin Finck
BmpFrameDecode_ReadRLE4(BmpDecoder * This)587c2c66affSColin Finck static HRESULT BmpFrameDecode_ReadRLE4(BmpDecoder* This)
588c2c66affSColin Finck {
589c2c66affSColin Finck UINT bytesperrow;
590c2c66affSColin Finck UINT width, height;
591c2c66affSColin Finck BYTE rledata[4096];
592c2c66affSColin Finck UINT datasize, palettesize;
593c2c66affSColin Finck DWORD palette[16];
594c2c66affSColin Finck UINT x, y;
595c2c66affSColin Finck DWORD *bgrdata;
596c2c66affSColin Finck HRESULT hr;
597c2c66affSColin Finck LARGE_INTEGER offbits;
598c2c66affSColin Finck ULONG cursor=0, bytesread=0;
599c2c66affSColin Finck
600c2c66affSColin Finck width = This->bih.bV5Width;
601c2c66affSColin Finck height = abs(This->bih.bV5Height);
602c2c66affSColin Finck bytesperrow = width * 4;
603c2c66affSColin Finck datasize = bytesperrow * height;
604c2c66affSColin Finck if (This->bih.bV5ClrUsed && This->bih.bV5ClrUsed < 16)
605c2c66affSColin Finck palettesize = 4 * This->bih.bV5ClrUsed;
606c2c66affSColin Finck else
607c2c66affSColin Finck palettesize = 4 * 16;
608c2c66affSColin Finck
609c2c66affSColin Finck This->imagedata = HeapAlloc(GetProcessHeap(), 0, datasize);
610c2c66affSColin Finck if (!This->imagedata)
611c2c66affSColin Finck {
612c2c66affSColin Finck hr = E_OUTOFMEMORY;
613c2c66affSColin Finck goto fail;
614c2c66affSColin Finck }
615c2c66affSColin Finck
616c2c66affSColin Finck /* read palette */
617c2c66affSColin Finck offbits.QuadPart = This->palette_offset;
618c2c66affSColin Finck hr = IStream_Seek(This->stream, offbits, STREAM_SEEK_SET, NULL);
619c2c66affSColin Finck if (FAILED(hr)) goto fail;
620c2c66affSColin Finck
621c2c66affSColin Finck hr = IStream_Read(This->stream, palette, palettesize, &bytesread);
622c2c66affSColin Finck if (FAILED(hr) || bytesread != palettesize) goto fail;
623c2c66affSColin Finck
624c2c66affSColin Finck /* read RLE data */
625c2c66affSColin Finck offbits.QuadPart = This->image_offset;
626c2c66affSColin Finck hr = IStream_Seek(This->stream, offbits, STREAM_SEEK_SET, NULL);
627c2c66affSColin Finck if (FAILED(hr)) goto fail;
628c2c66affSColin Finck
629c2c66affSColin Finck /* decode RLE */
630c2c66affSColin Finck bgrdata = (DWORD*)This->imagedata;
631c2c66affSColin Finck x = 0;
632c2c66affSColin Finck y = 0;
633c2c66affSColin Finck cursor = 0;
634c2c66affSColin Finck bytesread = 0;
635c2c66affSColin Finck while (y < height)
636c2c66affSColin Finck {
637c2c66affSColin Finck BYTE length;
638c2c66affSColin Finck hr = ReadByte(This->stream, rledata, 4096, &cursor, &bytesread, &length);
639c2c66affSColin Finck
640c2c66affSColin Finck if (FAILED(hr))
641c2c66affSColin Finck goto fail;
642c2c66affSColin Finck else if (length == 0)
643c2c66affSColin Finck {
644c2c66affSColin Finck /* escape code */
645c2c66affSColin Finck BYTE escape;
646c2c66affSColin Finck hr = ReadByte(This->stream, rledata, 4096, &cursor, &bytesread, &escape);
647c2c66affSColin Finck if (FAILED(hr))
648c2c66affSColin Finck goto fail;
649c2c66affSColin Finck switch(escape)
650c2c66affSColin Finck {
651c2c66affSColin Finck case 0: /* end of line */
652c2c66affSColin Finck x = 0;
653c2c66affSColin Finck y++;
654c2c66affSColin Finck break;
655c2c66affSColin Finck case 1: /* end of bitmap */
656c2c66affSColin Finck goto end;
657c2c66affSColin Finck case 2: /* delta */
658c2c66affSColin Finck {
659c2c66affSColin Finck BYTE dx, dy;
660c2c66affSColin Finck hr = ReadByte(This->stream, rledata, 4096, &cursor, &bytesread, &dx);
661c2c66affSColin Finck if (SUCCEEDED(hr))
662c2c66affSColin Finck hr = ReadByte(This->stream, rledata, 4096, &cursor, &bytesread, &dy);
663c2c66affSColin Finck if (FAILED(hr))
664c2c66affSColin Finck goto fail;
665c2c66affSColin Finck x += dx;
666c2c66affSColin Finck y += dy;
667c2c66affSColin Finck break;
668c2c66affSColin Finck }
669c2c66affSColin Finck default: /* absolute mode */
670c2c66affSColin Finck {
671c2c66affSColin Finck BYTE realsize=0;
672c2c66affSColin Finck length = escape;
673c2c66affSColin Finck while (length-- && x < width)
674c2c66affSColin Finck {
675c2c66affSColin Finck BYTE colors;
676c2c66affSColin Finck hr = ReadByte(This->stream, rledata, 4096, &cursor, &bytesread, &colors);
677c2c66affSColin Finck realsize++;
678c2c66affSColin Finck if (FAILED(hr))
679c2c66affSColin Finck goto fail;
680c2c66affSColin Finck bgrdata[y*width + x++] = palette[colors>>4];
681c2c66affSColin Finck if (length-- && x < width)
682c2c66affSColin Finck bgrdata[y*width + x++] = palette[colors&0xf];
683c2c66affSColin Finck else
684c2c66affSColin Finck break;
685c2c66affSColin Finck }
686c2c66affSColin Finck if (realsize & 1)
687c2c66affSColin Finck hr = ReadByte(This->stream, rledata, 4096, &cursor, &bytesread, &length); /* skip pad byte */
688c2c66affSColin Finck if (FAILED(hr))
689c2c66affSColin Finck goto fail;
690c2c66affSColin Finck }
691c2c66affSColin Finck }
692c2c66affSColin Finck }
693c2c66affSColin Finck else
694c2c66affSColin Finck {
695c2c66affSColin Finck BYTE colors;
696c2c66affSColin Finck DWORD color1;
697c2c66affSColin Finck DWORD color2;
698c2c66affSColin Finck hr = ReadByte(This->stream, rledata, 4096, &cursor, &bytesread, &colors);
699c2c66affSColin Finck if (FAILED(hr))
700c2c66affSColin Finck goto fail;
701c2c66affSColin Finck color1 = palette[colors>>4];
702c2c66affSColin Finck color2 = palette[colors&0xf];
703c2c66affSColin Finck while (length-- && x < width)
704c2c66affSColin Finck {
705c2c66affSColin Finck bgrdata[y*width + x++] = color1;
706c2c66affSColin Finck if (length-- && x < width)
707c2c66affSColin Finck bgrdata[y*width + x++] = color2;
708c2c66affSColin Finck else
709c2c66affSColin Finck break;
710c2c66affSColin Finck }
711c2c66affSColin Finck }
712c2c66affSColin Finck }
713c2c66affSColin Finck
714c2c66affSColin Finck end:
715c2c66affSColin Finck This->imagedatastart = This->imagedata + (height-1) * bytesperrow;
716c2c66affSColin Finck This->stride = -bytesperrow;
717c2c66affSColin Finck
718c2c66affSColin Finck return S_OK;
719c2c66affSColin Finck
720c2c66affSColin Finck fail:
721c2c66affSColin Finck HeapFree(GetProcessHeap(), 0, This->imagedata);
722c2c66affSColin Finck This->imagedata = NULL;
723c2c66affSColin Finck if (SUCCEEDED(hr)) hr = E_FAIL;
724c2c66affSColin Finck return hr;
725c2c66affSColin Finck }
726c2c66affSColin Finck
BmpFrameDecode_ReadUnsupported(BmpDecoder * This)727c2c66affSColin Finck static HRESULT BmpFrameDecode_ReadUnsupported(BmpDecoder* This)
728c2c66affSColin Finck {
729c2c66affSColin Finck return E_FAIL;
730c2c66affSColin Finck }
731c2c66affSColin Finck
732c2c66affSColin Finck struct bitfields_format {
733c2c66affSColin Finck WORD bitcount; /* 0 for end of list */
734c2c66affSColin Finck DWORD redmask;
735c2c66affSColin Finck DWORD greenmask;
736c2c66affSColin Finck DWORD bluemask;
737c2c66affSColin Finck DWORD alphamask;
738c2c66affSColin Finck const WICPixelFormatGUID *pixelformat;
739c2c66affSColin Finck ReadDataFunc read_data_func;
740c2c66affSColin Finck };
741c2c66affSColin Finck
742c2c66affSColin Finck static const struct bitfields_format bitfields_formats[] = {
743c2c66affSColin Finck {16,0x7c00,0x3e0,0x1f,0,&GUID_WICPixelFormat16bppBGR555,BmpFrameDecode_ReadUncompressed},
744c2c66affSColin Finck {16,0xf800,0x7e0,0x1f,0,&GUID_WICPixelFormat16bppBGR565,BmpFrameDecode_ReadUncompressed},
745c2c66affSColin Finck {32,0xff0000,0xff00,0xff,0,&GUID_WICPixelFormat32bppBGR,BmpFrameDecode_ReadUncompressed},
746c2c66affSColin Finck {32,0xff0000,0xff00,0xff,0xff000000,&GUID_WICPixelFormat32bppBGRA,BmpFrameDecode_ReadUncompressed},
747*cfaeaaa9SThomas Csovcsity {32,0xff000000,0xff0000,0xff00,0xff,&GUID_WICPixelFormat32bppRGBA,BmpFrameDecode_ReadUncompressed},
748c2c66affSColin Finck {32,0xff,0xff00,0xff0000,0,&GUID_WICPixelFormat32bppBGR,BmpFrameDecode_ReadRGB8},
749c2c66affSColin Finck {0}
750c2c66affSColin Finck };
751c2c66affSColin Finck
752c2c66affSColin Finck static const IWICBitmapFrameDecodeVtbl BmpDecoder_FrameVtbl = {
753c2c66affSColin Finck BmpFrameDecode_QueryInterface,
754c2c66affSColin Finck BmpFrameDecode_AddRef,
755c2c66affSColin Finck BmpFrameDecode_Release,
756c2c66affSColin Finck BmpFrameDecode_GetSize,
757c2c66affSColin Finck BmpFrameDecode_GetPixelFormat,
758c2c66affSColin Finck BmpFrameDecode_GetResolution,
759c2c66affSColin Finck BmpFrameDecode_CopyPalette,
760c2c66affSColin Finck BmpFrameDecode_CopyPixels,
761c2c66affSColin Finck BmpFrameDecode_GetMetadataQueryReader,
762c2c66affSColin Finck BmpFrameDecode_GetColorContexts,
763c2c66affSColin Finck BmpFrameDecode_GetThumbnail
764c2c66affSColin Finck };
765c2c66affSColin Finck
BmpDecoder_ReadHeaders(BmpDecoder * This,IStream * stream)766c2c66affSColin Finck static HRESULT BmpDecoder_ReadHeaders(BmpDecoder* This, IStream *stream)
767c2c66affSColin Finck {
768c2c66affSColin Finck HRESULT hr;
769c2c66affSColin Finck ULONG bytestoread, bytesread;
770c2c66affSColin Finck LARGE_INTEGER seek;
771c2c66affSColin Finck
772c2c66affSColin Finck if (This->initialized) return WINCODEC_ERR_WRONGSTATE;
773c2c66affSColin Finck
774c2c66affSColin Finck seek.QuadPart = 0;
775c2c66affSColin Finck hr = IStream_Seek(stream, seek, STREAM_SEEK_SET, NULL);
776c2c66affSColin Finck if (FAILED(hr)) return hr;
777c2c66affSColin Finck
778c2c66affSColin Finck if (!This->packed)
779c2c66affSColin Finck {
780c2c66affSColin Finck BITMAPFILEHEADER bfh;
781c2c66affSColin Finck hr = IStream_Read(stream, &bfh, sizeof(BITMAPFILEHEADER), &bytesread);
782c2c66affSColin Finck if (FAILED(hr)) return hr;
783c2c66affSColin Finck if (bytesread != sizeof(BITMAPFILEHEADER) ||
784c2c66affSColin Finck bfh.bfType != 0x4d42 /* "BM" */) return E_FAIL;
785c2c66affSColin Finck This->image_offset = bfh.bfOffBits;
786c2c66affSColin Finck }
787c2c66affSColin Finck
788c2c66affSColin Finck hr = IStream_Read(stream, &This->bih.bV5Size, sizeof(DWORD), &bytesread);
789c2c66affSColin Finck if (FAILED(hr)) return hr;
790c2c66affSColin Finck if (bytesread != sizeof(DWORD) ||
791c2c66affSColin Finck (This->bih.bV5Size != sizeof(BITMAPCOREHEADER) &&
792c2c66affSColin Finck This->bih.bV5Size != sizeof(BITMAPCOREHEADER2) &&
793c2c66affSColin Finck This->bih.bV5Size != sizeof(BITMAPINFOHEADER) &&
794c2c66affSColin Finck This->bih.bV5Size != sizeof(BITMAPV4HEADER) &&
795c2c66affSColin Finck This->bih.bV5Size != sizeof(BITMAPV5HEADER))) return E_FAIL;
796c2c66affSColin Finck
797c2c66affSColin Finck bytestoread = This->bih.bV5Size-sizeof(DWORD);
798c2c66affSColin Finck hr = IStream_Read(stream, &This->bih.bV5Width, bytestoread, &bytesread);
799c2c66affSColin Finck if (FAILED(hr)) return hr;
800c2c66affSColin Finck if (bytestoread != bytesread) return E_FAIL;
801c2c66affSColin Finck
802c2c66affSColin Finck if (This->packed)
803c2c66affSColin Finck This->palette_offset = This->bih.bV5Size;
804c2c66affSColin Finck else
805c2c66affSColin Finck This->palette_offset = sizeof(BITMAPFILEHEADER) + This->bih.bV5Size;
806c2c66affSColin Finck
807c2c66affSColin Finck if (This->icoframe)
808c2c66affSColin Finck {
809c2c66affSColin Finck if (This->bih.bV5Size == sizeof(BITMAPCOREHEADER))
810c2c66affSColin Finck {
811c2c66affSColin Finck BITMAPCOREHEADER *bch = (BITMAPCOREHEADER*)&This->bih;
812c2c66affSColin Finck bch->bcHeight /= 2;
813c2c66affSColin Finck }
814c2c66affSColin Finck else
815c2c66affSColin Finck {
816c2c66affSColin Finck This->bih.bV5Height /= 2;
817c2c66affSColin Finck }
818c2c66affSColin Finck }
819c2c66affSColin Finck
820c2c66affSColin Finck /* if this is a BITMAPINFOHEADER with BI_BITFIELDS compression, we need to
821c2c66affSColin Finck read the extra fields */
822c2c66affSColin Finck if (This->bih.bV5Size == sizeof(BITMAPINFOHEADER) &&
823c2c66affSColin Finck This->bih.bV5Compression == BI_BITFIELDS)
824c2c66affSColin Finck {
825c2c66affSColin Finck hr = IStream_Read(stream, &This->bih.bV5RedMask, 12, &bytesread);
826c2c66affSColin Finck if (FAILED(hr)) return hr;
827c2c66affSColin Finck if (bytesread != 12) return E_FAIL;
828c2c66affSColin Finck This->bih.bV5AlphaMask = 0;
829c2c66affSColin Finck This->palette_offset += 12;
830c2c66affSColin Finck }
831c2c66affSColin Finck
832c2c66affSColin Finck /* decide what kind of bitmap this is and how/if we can read it */
833c2c66affSColin Finck if (This->bih.bV5Size == sizeof(BITMAPCOREHEADER))
834c2c66affSColin Finck {
835c2c66affSColin Finck BITMAPCOREHEADER *bch = (BITMAPCOREHEADER*)&This->bih;
836c2c66affSColin Finck TRACE("BITMAPCOREHEADER with depth=%i\n", bch->bcBitCount);
837c2c66affSColin Finck This->bitsperpixel = bch->bcBitCount;
838c2c66affSColin Finck This->read_data_func = BmpFrameDecode_ReadUncompressed;
839c2c66affSColin Finck switch(bch->bcBitCount)
840c2c66affSColin Finck {
841c2c66affSColin Finck case 1:
842c2c66affSColin Finck This->pixelformat = &GUID_WICPixelFormat1bppIndexed;
843c2c66affSColin Finck break;
844c2c66affSColin Finck case 2:
845c2c66affSColin Finck This->pixelformat = &GUID_WICPixelFormat2bppIndexed;
846c2c66affSColin Finck break;
847c2c66affSColin Finck case 4:
848c2c66affSColin Finck This->pixelformat = &GUID_WICPixelFormat4bppIndexed;
849c2c66affSColin Finck break;
850c2c66affSColin Finck case 8:
851c2c66affSColin Finck This->pixelformat = &GUID_WICPixelFormat8bppIndexed;
852c2c66affSColin Finck break;
853c2c66affSColin Finck case 24:
854c2c66affSColin Finck This->pixelformat = &GUID_WICPixelFormat24bppBGR;
855c2c66affSColin Finck break;
856c2c66affSColin Finck default:
857c2c66affSColin Finck This->pixelformat = &GUID_WICPixelFormatUndefined;
858c2c66affSColin Finck WARN("unsupported bit depth %i for BITMAPCOREHEADER\n", bch->bcBitCount);
859c2c66affSColin Finck break;
860c2c66affSColin Finck }
861c2c66affSColin Finck }
862c2c66affSColin Finck else /* struct is compatible with BITMAPINFOHEADER */
863c2c66affSColin Finck {
864c2c66affSColin Finck TRACE("bitmap header=%i compression=%i depth=%i\n", This->bih.bV5Size, This->bih.bV5Compression, This->bih.bV5BitCount);
865c2c66affSColin Finck switch(This->bih.bV5Compression)
866c2c66affSColin Finck {
867c2c66affSColin Finck case BI_RGB:
868c2c66affSColin Finck This->bitsperpixel = This->bih.bV5BitCount;
869c2c66affSColin Finck This->read_data_func = BmpFrameDecode_ReadUncompressed;
870c2c66affSColin Finck switch(This->bih.bV5BitCount)
871c2c66affSColin Finck {
872c2c66affSColin Finck case 1:
873c2c66affSColin Finck This->pixelformat = &GUID_WICPixelFormat1bppIndexed;
874c2c66affSColin Finck break;
875c2c66affSColin Finck case 2:
876c2c66affSColin Finck This->pixelformat = &GUID_WICPixelFormat2bppIndexed;
877c2c66affSColin Finck break;
878c2c66affSColin Finck case 4:
879c2c66affSColin Finck This->pixelformat = &GUID_WICPixelFormat4bppIndexed;
880c2c66affSColin Finck break;
881c2c66affSColin Finck case 8:
882c2c66affSColin Finck This->pixelformat = &GUID_WICPixelFormat8bppIndexed;
883c2c66affSColin Finck break;
884c2c66affSColin Finck case 16:
885c2c66affSColin Finck This->pixelformat = &GUID_WICPixelFormat16bppBGR555;
886c2c66affSColin Finck break;
887c2c66affSColin Finck case 24:
888c2c66affSColin Finck This->pixelformat = &GUID_WICPixelFormat24bppBGR;
889c2c66affSColin Finck break;
890c2c66affSColin Finck case 32:
891c2c66affSColin Finck This->pixelformat = &GUID_WICPixelFormat32bppBGR;
892c2c66affSColin Finck break;
893c2c66affSColin Finck default:
894c2c66affSColin Finck This->pixelformat = &GUID_WICPixelFormatUndefined;
895c2c66affSColin Finck FIXME("unsupported bit depth %i for uncompressed RGB\n", This->bih.bV5BitCount);
896c2c66affSColin Finck }
897c2c66affSColin Finck break;
898c2c66affSColin Finck case BI_RLE8:
899c2c66affSColin Finck This->bitsperpixel = 32;
900c2c66affSColin Finck This->read_data_func = BmpFrameDecode_ReadRLE8;
901c2c66affSColin Finck This->pixelformat = &GUID_WICPixelFormat32bppBGR;
902c2c66affSColin Finck break;
903c2c66affSColin Finck case BI_RLE4:
904c2c66affSColin Finck This->bitsperpixel = 32;
905c2c66affSColin Finck This->read_data_func = BmpFrameDecode_ReadRLE4;
906c2c66affSColin Finck This->pixelformat = &GUID_WICPixelFormat32bppBGR;
907c2c66affSColin Finck break;
908c2c66affSColin Finck case BI_BITFIELDS:
909c2c66affSColin Finck {
910c2c66affSColin Finck const struct bitfields_format *format;
911c2c66affSColin Finck if (This->bih.bV5Size == sizeof(BITMAPCOREHEADER2))
912c2c66affSColin Finck {
913c2c66affSColin Finck /* BCH2 doesn't support bitfields; this is Huffman 1D compression */
914c2c66affSColin Finck This->bitsperpixel = 0;
915c2c66affSColin Finck This->read_data_func = BmpFrameDecode_ReadUnsupported;
916c2c66affSColin Finck This->pixelformat = &GUID_WICPixelFormatUndefined;
917c2c66affSColin Finck FIXME("Huffman 1D compression is unsupported\n");
918c2c66affSColin Finck break;
919c2c66affSColin Finck }
920c2c66affSColin Finck This->bitsperpixel = This->bih.bV5BitCount;
921c2c66affSColin Finck for (format = bitfields_formats; format->bitcount; format++)
922c2c66affSColin Finck {
923c2c66affSColin Finck if ((format->bitcount == This->bih.bV5BitCount) &&
924c2c66affSColin Finck (format->redmask == This->bih.bV5RedMask) &&
925c2c66affSColin Finck (format->greenmask == This->bih.bV5GreenMask) &&
926c2c66affSColin Finck (format->bluemask == This->bih.bV5BlueMask) &&
927c2c66affSColin Finck (format->alphamask == This->bih.bV5AlphaMask))
928c2c66affSColin Finck {
929c2c66affSColin Finck This->read_data_func = format->read_data_func;
930c2c66affSColin Finck This->pixelformat = format->pixelformat;
931c2c66affSColin Finck break;
932c2c66affSColin Finck }
933c2c66affSColin Finck }
934c2c66affSColin Finck if (!format->bitcount)
935c2c66affSColin Finck {
936c2c66affSColin Finck This->read_data_func = BmpFrameDecode_ReadUncompressed;
937c2c66affSColin Finck This->pixelformat = &GUID_WICPixelFormatUndefined;
938c2c66affSColin Finck FIXME("unsupported bitfields type depth=%i red=%x green=%x blue=%x alpha=%x\n",
939c2c66affSColin Finck This->bih.bV5BitCount, This->bih.bV5RedMask, This->bih.bV5GreenMask, This->bih.bV5BlueMask, This->bih.bV5AlphaMask);
940c2c66affSColin Finck }
941c2c66affSColin Finck break;
942c2c66affSColin Finck }
943c2c66affSColin Finck default:
944c2c66affSColin Finck This->bitsperpixel = 0;
945c2c66affSColin Finck This->read_data_func = BmpFrameDecode_ReadUnsupported;
946c2c66affSColin Finck This->pixelformat = &GUID_WICPixelFormatUndefined;
947c2c66affSColin Finck FIXME("unsupported bitmap type header=%i compression=%i depth=%i\n", This->bih.bV5Size, This->bih.bV5Compression, This->bih.bV5BitCount);
948c2c66affSColin Finck break;
949c2c66affSColin Finck }
950c2c66affSColin Finck }
951c2c66affSColin Finck
952c2c66affSColin Finck if (This->packed)
953c2c66affSColin Finck {
954c2c66affSColin Finck /* In a packed DIB, the image follows the palette. */
955c2c66affSColin Finck ULONG palette_count, palette_size;
956c2c66affSColin Finck if (This->bih.bV5ClrUsed)
957c2c66affSColin Finck palette_count = This->bih.bV5ClrUsed;
958c2c66affSColin Finck else if (This->bih.bV5BitCount <= 8)
959c2c66affSColin Finck palette_count = 1 << This->bih.bV5BitCount;
960c2c66affSColin Finck else
961c2c66affSColin Finck palette_count = 0;
962c2c66affSColin Finck if (This->bih.bV5Size == sizeof(BITMAPCOREHEADER))
963c2c66affSColin Finck palette_size = sizeof(RGBTRIPLE) * palette_count;
964c2c66affSColin Finck else
965c2c66affSColin Finck palette_size = sizeof(RGBQUAD) * palette_count;
966c2c66affSColin Finck This->image_offset = This->palette_offset + palette_size;
967c2c66affSColin Finck }
968c2c66affSColin Finck
969c2c66affSColin Finck This->initialized = TRUE;
970c2c66affSColin Finck
971c2c66affSColin Finck return S_OK;
972c2c66affSColin Finck }
973c2c66affSColin Finck
BmpDecoder_QueryInterface(IWICBitmapDecoder * iface,REFIID iid,void ** ppv)974c2c66affSColin Finck static HRESULT WINAPI BmpDecoder_QueryInterface(IWICBitmapDecoder *iface, REFIID iid,
975c2c66affSColin Finck void **ppv)
976c2c66affSColin Finck {
977c2c66affSColin Finck BmpDecoder *This = impl_from_IWICBitmapDecoder(iface);
978c2c66affSColin Finck TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
979c2c66affSColin Finck
980c2c66affSColin Finck if (!ppv) return E_INVALIDARG;
981c2c66affSColin Finck
982c2c66affSColin Finck if (IsEqualIID(&IID_IUnknown, iid) ||
983c2c66affSColin Finck IsEqualIID(&IID_IWICBitmapDecoder, iid))
984c2c66affSColin Finck {
985c2c66affSColin Finck *ppv = &This->IWICBitmapDecoder_iface;
986c2c66affSColin Finck }
987c2c66affSColin Finck else
988c2c66affSColin Finck {
989c2c66affSColin Finck *ppv = NULL;
990c2c66affSColin Finck return E_NOINTERFACE;
991c2c66affSColin Finck }
992c2c66affSColin Finck
993c2c66affSColin Finck IUnknown_AddRef((IUnknown*)*ppv);
994c2c66affSColin Finck return S_OK;
995c2c66affSColin Finck }
996c2c66affSColin Finck
BmpDecoder_AddRef(IWICBitmapDecoder * iface)997c2c66affSColin Finck static ULONG WINAPI BmpDecoder_AddRef(IWICBitmapDecoder *iface)
998c2c66affSColin Finck {
999c2c66affSColin Finck BmpDecoder *This = impl_from_IWICBitmapDecoder(iface);
1000c2c66affSColin Finck ULONG ref = InterlockedIncrement(&This->ref);
1001c2c66affSColin Finck
1002c2c66affSColin Finck TRACE("(%p) refcount=%u\n", iface, ref);
1003c2c66affSColin Finck
1004c2c66affSColin Finck return ref;
1005c2c66affSColin Finck }
1006c2c66affSColin Finck
BmpDecoder_Release(IWICBitmapDecoder * iface)1007c2c66affSColin Finck static ULONG WINAPI BmpDecoder_Release(IWICBitmapDecoder *iface)
1008c2c66affSColin Finck {
1009c2c66affSColin Finck BmpDecoder *This = impl_from_IWICBitmapDecoder(iface);
1010c2c66affSColin Finck ULONG ref = InterlockedDecrement(&This->ref);
1011c2c66affSColin Finck
1012c2c66affSColin Finck TRACE("(%p) refcount=%u\n", iface, ref);
1013c2c66affSColin Finck
1014c2c66affSColin Finck if (ref == 0)
1015c2c66affSColin Finck {
1016c2c66affSColin Finck if (This->stream) IStream_Release(This->stream);
1017c2c66affSColin Finck HeapFree(GetProcessHeap(), 0, This->imagedata);
1018c2c66affSColin Finck This->lock.DebugInfo->Spare[0] = 0;
1019c2c66affSColin Finck DeleteCriticalSection(&This->lock);
1020c2c66affSColin Finck HeapFree(GetProcessHeap(), 0, This);
1021c2c66affSColin Finck }
1022c2c66affSColin Finck
1023c2c66affSColin Finck return ref;
1024c2c66affSColin Finck }
1025c2c66affSColin Finck
BmpDecoder_QueryCapability(IWICBitmapDecoder * iface,IStream * stream,DWORD * capability)1026c2c66affSColin Finck static HRESULT WINAPI BmpDecoder_QueryCapability(IWICBitmapDecoder *iface, IStream *stream,
1027c2c66affSColin Finck DWORD *capability)
1028c2c66affSColin Finck {
1029c2c66affSColin Finck HRESULT hr;
1030c2c66affSColin Finck BmpDecoder *This = impl_from_IWICBitmapDecoder(iface);
1031c2c66affSColin Finck
1032c2c66affSColin Finck TRACE("(%p,%p,%p)\n", iface, stream, capability);
1033c2c66affSColin Finck
1034c2c66affSColin Finck if (!stream || !capability) return E_INVALIDARG;
1035c2c66affSColin Finck
1036c2c66affSColin Finck hr = IWICBitmapDecoder_Initialize(iface, stream, WICDecodeMetadataCacheOnDemand);
1037c2c66affSColin Finck if (hr != S_OK) return hr;
1038c2c66affSColin Finck
1039c2c66affSColin Finck *capability = This->read_data_func == BmpFrameDecode_ReadUnsupported ? 0 : WICBitmapDecoderCapabilityCanDecodeAllImages;
1040c2c66affSColin Finck return S_OK;
1041c2c66affSColin Finck }
1042c2c66affSColin Finck
BmpDecoder_Initialize(IWICBitmapDecoder * iface,IStream * pIStream,WICDecodeOptions cacheOptions)1043c2c66affSColin Finck static HRESULT WINAPI BmpDecoder_Initialize(IWICBitmapDecoder *iface, IStream *pIStream,
1044c2c66affSColin Finck WICDecodeOptions cacheOptions)
1045c2c66affSColin Finck {
1046c2c66affSColin Finck HRESULT hr;
1047c2c66affSColin Finck BmpDecoder *This = impl_from_IWICBitmapDecoder(iface);
1048c2c66affSColin Finck
1049c2c66affSColin Finck EnterCriticalSection(&This->lock);
1050c2c66affSColin Finck hr = BmpDecoder_ReadHeaders(This, pIStream);
1051c2c66affSColin Finck
1052c2c66affSColin Finck if (SUCCEEDED(hr))
1053c2c66affSColin Finck {
1054c2c66affSColin Finck This->stream = pIStream;
1055c2c66affSColin Finck IStream_AddRef(pIStream);
1056c2c66affSColin Finck }
1057c2c66affSColin Finck LeaveCriticalSection(&This->lock);
1058c2c66affSColin Finck
1059c2c66affSColin Finck return hr;
1060c2c66affSColin Finck }
1061c2c66affSColin Finck
BmpDecoder_GetContainerFormat(IWICBitmapDecoder * iface,GUID * pguidContainerFormat)1062c2c66affSColin Finck static HRESULT WINAPI BmpDecoder_GetContainerFormat(IWICBitmapDecoder *iface,
1063c2c66affSColin Finck GUID *pguidContainerFormat)
1064c2c66affSColin Finck {
1065c2c66affSColin Finck memcpy(pguidContainerFormat, &GUID_ContainerFormatBmp, sizeof(GUID));
1066c2c66affSColin Finck return S_OK;
1067c2c66affSColin Finck }
1068c2c66affSColin Finck
BmpDecoder_GetDecoderInfo(IWICBitmapDecoder * iface,IWICBitmapDecoderInfo ** ppIDecoderInfo)1069c2c66affSColin Finck static HRESULT WINAPI BmpDecoder_GetDecoderInfo(IWICBitmapDecoder *iface,
1070c2c66affSColin Finck IWICBitmapDecoderInfo **ppIDecoderInfo)
1071c2c66affSColin Finck {
1072c2c66affSColin Finck TRACE("(%p,%p)\n", iface, ppIDecoderInfo);
1073c2c66affSColin Finck
1074324214f9SAmine Khaldi return get_decoder_info(&CLSID_WICBmpDecoder, ppIDecoderInfo);
1075c2c66affSColin Finck }
1076c2c66affSColin Finck
BmpDecoder_CopyPalette(IWICBitmapDecoder * iface,IWICPalette * pIPalette)1077c2c66affSColin Finck static HRESULT WINAPI BmpDecoder_CopyPalette(IWICBitmapDecoder *iface,
1078c2c66affSColin Finck IWICPalette *pIPalette)
1079c2c66affSColin Finck {
1080c2c66affSColin Finck TRACE("(%p,%p)\n", iface, pIPalette);
1081c2c66affSColin Finck
1082c2c66affSColin Finck return WINCODEC_ERR_PALETTEUNAVAILABLE;
1083c2c66affSColin Finck }
1084c2c66affSColin Finck
BmpDecoder_GetMetadataQueryReader(IWICBitmapDecoder * iface,IWICMetadataQueryReader ** ppIMetadataQueryReader)1085c2c66affSColin Finck static HRESULT WINAPI BmpDecoder_GetMetadataQueryReader(IWICBitmapDecoder *iface,
1086c2c66affSColin Finck IWICMetadataQueryReader **ppIMetadataQueryReader)
1087c2c66affSColin Finck {
1088c2c66affSColin Finck TRACE("(%p,%p)\n", iface, ppIMetadataQueryReader);
1089c2c66affSColin Finck return WINCODEC_ERR_UNSUPPORTEDOPERATION;
1090c2c66affSColin Finck }
1091c2c66affSColin Finck
BmpDecoder_GetPreview(IWICBitmapDecoder * iface,IWICBitmapSource ** ppIBitmapSource)1092c2c66affSColin Finck static HRESULT WINAPI BmpDecoder_GetPreview(IWICBitmapDecoder *iface,
1093c2c66affSColin Finck IWICBitmapSource **ppIBitmapSource)
1094c2c66affSColin Finck {
1095c2c66affSColin Finck TRACE("(%p,%p)\n", iface, ppIBitmapSource);
1096c2c66affSColin Finck return WINCODEC_ERR_UNSUPPORTEDOPERATION;
1097c2c66affSColin Finck }
1098c2c66affSColin Finck
BmpDecoder_GetColorContexts(IWICBitmapDecoder * iface,UINT cCount,IWICColorContext ** ppIColorContexts,UINT * pcActualCount)1099c2c66affSColin Finck static HRESULT WINAPI BmpDecoder_GetColorContexts(IWICBitmapDecoder *iface,
1100c2c66affSColin Finck UINT cCount, IWICColorContext **ppIColorContexts, UINT *pcActualCount)
1101c2c66affSColin Finck {
1102c2c66affSColin Finck TRACE("(%p,%u,%p,%p)\n", iface, cCount, ppIColorContexts, pcActualCount);
1103c2c66affSColin Finck return WINCODEC_ERR_UNSUPPORTEDOPERATION;
1104c2c66affSColin Finck }
1105c2c66affSColin Finck
BmpDecoder_GetThumbnail(IWICBitmapDecoder * iface,IWICBitmapSource ** ppIThumbnail)1106c2c66affSColin Finck static HRESULT WINAPI BmpDecoder_GetThumbnail(IWICBitmapDecoder *iface,
1107c2c66affSColin Finck IWICBitmapSource **ppIThumbnail)
1108c2c66affSColin Finck {
1109c2c66affSColin Finck TRACE("(%p,%p)\n", iface, ppIThumbnail);
1110c2c66affSColin Finck return WINCODEC_ERR_CODECNOTHUMBNAIL;
1111c2c66affSColin Finck }
1112c2c66affSColin Finck
BmpDecoder_GetFrameCount(IWICBitmapDecoder * iface,UINT * pCount)1113c2c66affSColin Finck static HRESULT WINAPI BmpDecoder_GetFrameCount(IWICBitmapDecoder *iface,
1114c2c66affSColin Finck UINT *pCount)
1115c2c66affSColin Finck {
1116c2c66affSColin Finck if (!pCount) return E_INVALIDARG;
1117c2c66affSColin Finck
1118c2c66affSColin Finck *pCount = 1;
1119c2c66affSColin Finck return S_OK;
1120c2c66affSColin Finck }
1121c2c66affSColin Finck
BmpDecoder_GetFrame(IWICBitmapDecoder * iface,UINT index,IWICBitmapFrameDecode ** ppIBitmapFrame)1122c2c66affSColin Finck static HRESULT WINAPI BmpDecoder_GetFrame(IWICBitmapDecoder *iface,
1123c2c66affSColin Finck UINT index, IWICBitmapFrameDecode **ppIBitmapFrame)
1124c2c66affSColin Finck {
1125c2c66affSColin Finck BmpDecoder *This = impl_from_IWICBitmapDecoder(iface);
1126c2c66affSColin Finck
1127c2c66affSColin Finck if (index != 0) return E_INVALIDARG;
1128c2c66affSColin Finck
1129c2c66affSColin Finck if (!This->stream) return WINCODEC_ERR_FRAMEMISSING;
1130c2c66affSColin Finck
1131c2c66affSColin Finck *ppIBitmapFrame = &This->IWICBitmapFrameDecode_iface;
1132c2c66affSColin Finck IWICBitmapDecoder_AddRef(iface);
1133c2c66affSColin Finck
1134c2c66affSColin Finck return S_OK;
1135c2c66affSColin Finck }
1136c2c66affSColin Finck
1137c2c66affSColin Finck static const IWICBitmapDecoderVtbl BmpDecoder_Vtbl = {
1138c2c66affSColin Finck BmpDecoder_QueryInterface,
1139c2c66affSColin Finck BmpDecoder_AddRef,
1140c2c66affSColin Finck BmpDecoder_Release,
1141c2c66affSColin Finck BmpDecoder_QueryCapability,
1142c2c66affSColin Finck BmpDecoder_Initialize,
1143c2c66affSColin Finck BmpDecoder_GetContainerFormat,
1144c2c66affSColin Finck BmpDecoder_GetDecoderInfo,
1145c2c66affSColin Finck BmpDecoder_CopyPalette,
1146c2c66affSColin Finck BmpDecoder_GetMetadataQueryReader,
1147c2c66affSColin Finck BmpDecoder_GetPreview,
1148c2c66affSColin Finck BmpDecoder_GetColorContexts,
1149c2c66affSColin Finck BmpDecoder_GetThumbnail,
1150c2c66affSColin Finck BmpDecoder_GetFrameCount,
1151c2c66affSColin Finck BmpDecoder_GetFrame
1152c2c66affSColin Finck };
1153c2c66affSColin Finck
BmpDecoder_Create(int packed,int icoframe,BmpDecoder ** ppDecoder)1154c2c66affSColin Finck static HRESULT BmpDecoder_Create(int packed, int icoframe, BmpDecoder **ppDecoder)
1155c2c66affSColin Finck {
1156c2c66affSColin Finck BmpDecoder *This;
1157c2c66affSColin Finck
1158c2c66affSColin Finck This = HeapAlloc(GetProcessHeap(), 0, sizeof(BmpDecoder));
1159c2c66affSColin Finck if (!This) return E_OUTOFMEMORY;
1160c2c66affSColin Finck
1161c2c66affSColin Finck This->IWICBitmapDecoder_iface.lpVtbl = &BmpDecoder_Vtbl;
1162c2c66affSColin Finck This->IWICBitmapFrameDecode_iface.lpVtbl = &BmpDecoder_FrameVtbl;
1163c2c66affSColin Finck This->ref = 1;
1164c2c66affSColin Finck This->initialized = FALSE;
1165c2c66affSColin Finck This->stream = NULL;
1166c2c66affSColin Finck This->imagedata = NULL;
1167c2c66affSColin Finck InitializeCriticalSection(&This->lock);
1168c2c66affSColin Finck This->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": BmpDecoder.lock");
1169c2c66affSColin Finck This->packed = packed;
1170c2c66affSColin Finck This->icoframe = icoframe;
1171c2c66affSColin Finck
1172c2c66affSColin Finck *ppDecoder = This;
1173c2c66affSColin Finck
1174c2c66affSColin Finck return S_OK;
1175c2c66affSColin Finck }
1176c2c66affSColin Finck
BmpDecoder_Construct(int packed,int icoframe,REFIID iid,void ** ppv)1177c2c66affSColin Finck static HRESULT BmpDecoder_Construct(int packed, int icoframe, REFIID iid, void** ppv)
1178c2c66affSColin Finck {
1179c2c66affSColin Finck BmpDecoder *This;
1180c2c66affSColin Finck HRESULT ret;
1181c2c66affSColin Finck
1182c2c66affSColin Finck TRACE("(%s,%p)\n", debugstr_guid(iid), ppv);
1183c2c66affSColin Finck
1184c2c66affSColin Finck *ppv = NULL;
1185c2c66affSColin Finck
1186c2c66affSColin Finck ret = BmpDecoder_Create(packed, icoframe, &This);
1187c2c66affSColin Finck if (FAILED(ret)) return ret;
1188c2c66affSColin Finck
1189c2c66affSColin Finck ret = IWICBitmapDecoder_QueryInterface(&This->IWICBitmapDecoder_iface, iid, ppv);
1190c2c66affSColin Finck IWICBitmapDecoder_Release(&This->IWICBitmapDecoder_iface);
1191c2c66affSColin Finck
1192c2c66affSColin Finck return ret;
1193c2c66affSColin Finck }
1194c2c66affSColin Finck
BmpDecoder_CreateInstance(REFIID iid,void ** ppv)1195c2c66affSColin Finck HRESULT BmpDecoder_CreateInstance(REFIID iid, void** ppv)
1196c2c66affSColin Finck {
1197c2c66affSColin Finck return BmpDecoder_Construct(FALSE, FALSE, iid, ppv);
1198c2c66affSColin Finck }
1199c2c66affSColin Finck
DibDecoder_CreateInstance(REFIID iid,void ** ppv)1200c2c66affSColin Finck HRESULT DibDecoder_CreateInstance(REFIID iid, void** ppv)
1201c2c66affSColin Finck {
1202c2c66affSColin Finck return BmpDecoder_Construct(TRUE, FALSE, iid, ppv);
1203c2c66affSColin Finck }
1204c2c66affSColin Finck
IcoDibDecoder_CreateInstance(BmpDecoder ** ppDecoder)1205c2c66affSColin Finck HRESULT IcoDibDecoder_CreateInstance(BmpDecoder **ppDecoder)
1206c2c66affSColin Finck {
1207c2c66affSColin Finck return BmpDecoder_Create(TRUE, TRUE, ppDecoder);
1208c2c66affSColin Finck }
1209c2c66affSColin Finck
BmpDecoder_GetWICDecoder(BmpDecoder * This,IWICBitmapDecoder ** ppDecoder)1210c2c66affSColin Finck void BmpDecoder_GetWICDecoder(BmpDecoder *This, IWICBitmapDecoder **ppDecoder)
1211c2c66affSColin Finck {
1212c2c66affSColin Finck *ppDecoder = &This->IWICBitmapDecoder_iface;
1213c2c66affSColin Finck }
1214c2c66affSColin Finck
1215c2c66affSColin Finck /* Return the offset where the mask of an icon might be, or 0 for failure. */
BmpDecoder_FindIconMask(BmpDecoder * This,ULONG * mask_offset,int * topdown)1216c2c66affSColin Finck void BmpDecoder_FindIconMask(BmpDecoder *This, ULONG *mask_offset, int *topdown)
1217c2c66affSColin Finck {
1218c2c66affSColin Finck assert(This->stream != NULL);
1219c2c66affSColin Finck
1220c2c66affSColin Finck if (This->read_data_func == BmpFrameDecode_ReadUncompressed)
1221c2c66affSColin Finck {
1222c2c66affSColin Finck /* RGB or BITFIELDS data */
1223c2c66affSColin Finck ULONG width, height, bytesperrow, datasize;
1224c2c66affSColin Finck IWICBitmapFrameDecode_GetSize(&This->IWICBitmapFrameDecode_iface, &width, &height);
1225c2c66affSColin Finck bytesperrow = (((width * This->bitsperpixel)+31)/32)*4;
1226c2c66affSColin Finck datasize = bytesperrow * height;
1227c2c66affSColin Finck *mask_offset = This->image_offset + datasize;
1228c2c66affSColin Finck }
1229c2c66affSColin Finck else
1230c2c66affSColin Finck *mask_offset = 0;
1231c2c66affSColin Finck
1232c2c66affSColin Finck *topdown = This->stride > 0;
1233c2c66affSColin Finck }
1234