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