jscript: Ensure that the whole script is parsed.
[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 ReadByte(IStream *stream, BYTE *buffer, ULONG buffer_size,
403     ULONG *cursor, ULONG *bytesread, BYTE *result)
404 {
405     HRESULT hr=S_OK;
406
407     if (*bytesread == 0 || *cursor == *bytesread)
408     {
409         hr = IStream_Read(stream, buffer, buffer_size, bytesread);
410         *cursor = 0;
411     }
412
413     if (SUCCEEDED(hr))
414     {
415         if (*cursor < *bytesread)
416             *result = buffer[(*cursor)++];
417         else
418             hr = E_FAIL;
419     }
420
421     return hr;
422 }
423
424 static HRESULT BmpFrameDecode_ReadRLE8(BmpDecoder* This)
425 {
426     UINT bytesperrow;
427     UINT width, height;
428     BYTE rledata[4096];
429     UINT datasize, palettesize;
430     DWORD palette[256];
431     UINT x, y;
432     DWORD *bgrdata;
433     HRESULT hr;
434     LARGE_INTEGER offbits;
435     ULONG cursor=0, bytesread=0;
436
437     width = This->bih.bV5Width;
438     height = abs(This->bih.bV5Height);
439     bytesperrow = width * 4;
440     datasize = bytesperrow * height;
441     if (This->bih.bV5ClrUsed && This->bih.bV5ClrUsed < 256)
442         palettesize = 4 * This->bih.bV5ClrUsed;
443     else
444         palettesize = 4 * 256;
445
446     This->imagedata = HeapAlloc(GetProcessHeap(), 0, datasize);
447     if (!This->imagedata)
448     {
449         hr = E_OUTOFMEMORY;
450         goto fail;
451     }
452
453     /* read palette */
454     offbits.QuadPart = This->palette_offset;
455     hr = IStream_Seek(This->stream, offbits, STREAM_SEEK_SET, NULL);
456     if (FAILED(hr)) goto fail;
457
458     hr = IStream_Read(This->stream, palette, palettesize, &bytesread);
459     if (FAILED(hr) || bytesread != palettesize) goto fail;
460
461     /* read RLE data */
462     offbits.QuadPart = This->image_offset;
463     hr = IStream_Seek(This->stream, offbits, STREAM_SEEK_SET, NULL);
464     if (FAILED(hr)) goto fail;
465
466     /* decode RLE */
467     bgrdata = (DWORD*)This->imagedata;
468     x = 0;
469     y = 0;
470     cursor = 0;
471     bytesread = 0;
472     while (y < height)
473     {
474         BYTE length;
475         hr = ReadByte(This->stream, rledata, 4096, &cursor, &bytesread, &length);
476
477         if (FAILED(hr))
478             goto fail;
479         else if (length == 0)
480         {
481             /* escape code */
482             BYTE escape;
483             hr = ReadByte(This->stream, rledata, 4096, &cursor, &bytesread, &escape);
484             if (FAILED(hr))
485                 goto fail;
486             switch(escape)
487             {
488             case 0: /* end of line */
489                 x = 0;
490                 y++;
491                 break;
492             case 1: /* end of bitmap */
493                 goto end;
494             case 2: /* delta */
495             {
496                 BYTE dx, dy;
497                 hr = ReadByte(This->stream, rledata, 4096, &cursor, &bytesread, &dx);
498                 if (SUCCEEDED(hr))
499                     hr = ReadByte(This->stream, rledata, 4096, &cursor, &bytesread, &dy);
500                 if (FAILED(hr))
501                     goto fail;
502                 x += dx;
503                 y += dy;
504                 break;
505             }
506             default: /* absolute mode */
507                 length = escape;
508                 while (length-- && x < width)
509                 {
510                     BYTE index;
511                     hr = ReadByte(This->stream, rledata, 4096, &cursor, &bytesread, &index);
512                     if (FAILED(hr))
513                         goto fail;
514                     bgrdata[y*width + x++] = palette[index];
515                 }
516                 if (escape & 1)
517                     hr = ReadByte(This->stream, rledata, 4096, &cursor, &bytesread, &length); /* skip pad byte */
518                 if (FAILED(hr))
519                     goto fail;
520             }
521         }
522         else
523         {
524             BYTE index;
525             DWORD color;
526             hr = ReadByte(This->stream, rledata, 4096, &cursor, &bytesread, &index);
527             if (FAILED(hr))
528                 goto fail;
529             color = palette[index];
530             while (length-- && x < width)
531                 bgrdata[y*width + x++] = color;
532         }
533     }
534
535 end:
536     This->imagedatastart = This->imagedata + (height-1) * bytesperrow;
537     This->stride = -bytesperrow;
538
539     return S_OK;
540
541 fail:
542     HeapFree(GetProcessHeap(), 0, This->imagedata);
543     This->imagedata = NULL;
544     if (SUCCEEDED(hr)) hr = E_FAIL;
545     return hr;
546 }
547
548 static HRESULT BmpFrameDecode_ReadRLE4(BmpDecoder* This)
549 {
550     UINT bytesperrow;
551     UINT width, height;
552     BYTE rledata[4096];
553     UINT datasize, palettesize;
554     DWORD palette[16];
555     UINT x, y;
556     DWORD *bgrdata;
557     HRESULT hr;
558     LARGE_INTEGER offbits;
559     ULONG cursor=0, bytesread=0;
560
561     width = This->bih.bV5Width;
562     height = abs(This->bih.bV5Height);
563     bytesperrow = width * 4;
564     datasize = bytesperrow * height;
565     if (This->bih.bV5ClrUsed && This->bih.bV5ClrUsed < 16)
566         palettesize = 4 * This->bih.bV5ClrUsed;
567     else
568         palettesize = 4 * 16;
569
570     This->imagedata = HeapAlloc(GetProcessHeap(), 0, datasize);
571     if (!This->imagedata)
572     {
573         hr = E_OUTOFMEMORY;
574         goto fail;
575     }
576
577     /* read palette */
578     offbits.QuadPart = This->palette_offset;
579     hr = IStream_Seek(This->stream, offbits, STREAM_SEEK_SET, NULL);
580     if (FAILED(hr)) goto fail;
581
582     hr = IStream_Read(This->stream, palette, palettesize, &bytesread);
583     if (FAILED(hr) || bytesread != palettesize) goto fail;
584
585     /* read RLE data */
586     offbits.QuadPart = This->image_offset;
587     hr = IStream_Seek(This->stream, offbits, STREAM_SEEK_SET, NULL);
588     if (FAILED(hr)) goto fail;
589
590     /* decode RLE */
591     bgrdata = (DWORD*)This->imagedata;
592     x = 0;
593     y = 0;
594     cursor = 0;
595     bytesread = 0;
596     while (y < height)
597     {
598         BYTE length;
599         hr = ReadByte(This->stream, rledata, 4096, &cursor, &bytesread, &length);
600
601         if (FAILED(hr))
602             goto fail;
603         else if (length == 0)
604         {
605             /* escape code */
606             BYTE escape;
607             hr = ReadByte(This->stream, rledata, 4096, &cursor, &bytesread, &escape);
608             if (FAILED(hr))
609                 goto fail;
610             switch(escape)
611             {
612             case 0: /* end of line */
613                 x = 0;
614                 y++;
615                 break;
616             case 1: /* end of bitmap */
617                 goto end;
618             case 2: /* delta */
619             {
620                 BYTE dx, dy;
621                 hr = ReadByte(This->stream, rledata, 4096, &cursor, &bytesread, &dx);
622                 if (SUCCEEDED(hr))
623                     hr = ReadByte(This->stream, rledata, 4096, &cursor, &bytesread, &dy);
624                 if (FAILED(hr))
625                     goto fail;
626                 x += dx;
627                 y += dy;
628                 break;
629             }
630             default: /* absolute mode */
631             {
632                 BYTE realsize=0;
633                 length = escape;
634                 while (length-- && x < width)
635                 {
636                     BYTE colors;
637                     hr = ReadByte(This->stream, rledata, 4096, &cursor, &bytesread, &colors);
638                     realsize++;
639                     if (FAILED(hr))
640                         goto fail;
641                     bgrdata[y*width + x++] = palette[colors>>4];
642                     if (length-- && x < width)
643                         bgrdata[y*width + x++] = palette[colors&0xf];
644                     else
645                         break;
646                 }
647                 if (realsize & 1)
648                     hr = ReadByte(This->stream, rledata, 4096, &cursor, &bytesread, &length); /* skip pad byte */
649                 if (FAILED(hr))
650                     goto fail;
651             }
652             }
653         }
654         else
655         {
656             BYTE colors;
657             DWORD color1;
658             DWORD color2;
659             hr = ReadByte(This->stream, rledata, 4096, &cursor, &bytesread, &colors);
660             if (FAILED(hr))
661                 goto fail;
662             color1 = palette[colors>>4];
663             color2 = palette[colors&0xf];
664             while (length-- && x < width)
665             {
666                 bgrdata[y*width + x++] = color1;
667                 if (length-- && x < width)
668                     bgrdata[y*width + x++] = color2;
669                 else
670                     break;
671             }
672         }
673     }
674
675 end:
676     This->imagedatastart = This->imagedata + (height-1) * bytesperrow;
677     This->stride = -bytesperrow;
678
679     return S_OK;
680
681 fail:
682     HeapFree(GetProcessHeap(), 0, This->imagedata);
683     This->imagedata = NULL;
684     if (SUCCEEDED(hr)) hr = E_FAIL;
685     return hr;
686 }
687
688 static HRESULT BmpFrameDecode_ReadUnsupported(BmpDecoder* This)
689 {
690     return E_FAIL;
691 }
692
693 struct bitfields_format {
694     WORD bitcount; /* 0 for end of list */
695     DWORD redmask;
696     DWORD greenmask;
697     DWORD bluemask;
698     DWORD alphamask;
699     const WICPixelFormatGUID *pixelformat;
700     ReadDataFunc read_data_func;
701 };
702
703 static const struct bitfields_format bitfields_formats[] = {
704     {16,0x7c00,0x3e0,0x1f,0,&GUID_WICPixelFormat16bppBGR555,BmpFrameDecode_ReadUncompressed},
705     {16,0xf800,0x7e0,0x1f,0,&GUID_WICPixelFormat16bppBGR565,BmpFrameDecode_ReadUncompressed},
706     {32,0xff0000,0xff00,0xff,0,&GUID_WICPixelFormat32bppBGR,BmpFrameDecode_ReadUncompressed},
707     {32,0xff0000,0xff00,0xff,0xff000000,&GUID_WICPixelFormat32bppBGRA,BmpFrameDecode_ReadUncompressed},
708     {0}
709 };
710
711 static const IWICBitmapFrameDecodeVtbl BmpDecoder_FrameVtbl = {
712     BmpFrameDecode_QueryInterface,
713     BmpFrameDecode_AddRef,
714     BmpFrameDecode_Release,
715     BmpFrameDecode_GetSize,
716     BmpFrameDecode_GetPixelFormat,
717     BmpFrameDecode_GetResolution,
718     BmpFrameDecode_CopyPalette,
719     BmpFrameDecode_CopyPixels,
720     BmpFrameDecode_GetMetadataQueryReader,
721     BmpFrameDecode_GetColorContexts,
722     BmpFrameDecode_GetThumbnail
723 };
724
725 static HRESULT BmpDecoder_ReadHeaders(BmpDecoder* This, IStream *stream)
726 {
727     HRESULT hr;
728     ULONG bytestoread, bytesread;
729     LARGE_INTEGER seek;
730
731     if (This->initialized) return WINCODEC_ERR_WRONGSTATE;
732
733     seek.QuadPart = 0;
734     hr = IStream_Seek(stream, seek, STREAM_SEEK_SET, NULL);
735     if (FAILED(hr)) return hr;
736
737     if (!This->packed)
738     {
739         BITMAPFILEHEADER bfh;
740         hr = IStream_Read(stream, &bfh, sizeof(BITMAPFILEHEADER), &bytesread);
741         if (FAILED(hr)) return hr;
742         if (bytesread != sizeof(BITMAPFILEHEADER) ||
743             bfh.bfType != 0x4d42 /* "BM" */) return E_FAIL;
744         This->image_offset = bfh.bfOffBits;
745     }
746
747     hr = IStream_Read(stream, &This->bih.bV5Size, sizeof(DWORD), &bytesread);
748     if (FAILED(hr)) return hr;
749     if (bytesread != sizeof(DWORD) ||
750         (This->bih.bV5Size != sizeof(BITMAPCOREHEADER) &&
751          This->bih.bV5Size != sizeof(BITMAPCOREHEADER2) &&
752          This->bih.bV5Size != sizeof(BITMAPINFOHEADER) &&
753          This->bih.bV5Size != sizeof(BITMAPV4HEADER) &&
754          This->bih.bV5Size != sizeof(BITMAPV5HEADER))) return E_FAIL;
755
756     bytestoread = This->bih.bV5Size-sizeof(DWORD);
757     hr = IStream_Read(stream, &This->bih.bV5Width, bytestoread, &bytesread);
758     if (FAILED(hr)) return hr;
759     if (bytestoread != bytesread) return E_FAIL;
760
761     if (This->packed)
762         This->palette_offset = This->bih.bV5Size;
763     else
764         This->palette_offset = sizeof(BITMAPFILEHEADER) + This->bih.bV5Size;
765
766     if (This->icoframe)
767     {
768         if (This->bih.bV5Size == sizeof(BITMAPCOREHEADER))
769         {
770             BITMAPCOREHEADER *bch = (BITMAPCOREHEADER*)&This->bih;
771             bch->bcHeight /= 2;
772         }
773         else
774         {
775             This->bih.bV5Height /= 2;
776         }
777     }
778
779     /* if this is a BITMAPINFOHEADER with BI_BITFIELDS compression, we need to
780         read the extra fields */
781     if (This->bih.bV5Size == sizeof(BITMAPINFOHEADER) &&
782         This->bih.bV5Compression == BI_BITFIELDS)
783     {
784         hr = IStream_Read(stream, &This->bih.bV5RedMask, 12, &bytesread);
785         if (FAILED(hr)) return hr;
786         if (bytesread != 12) return E_FAIL;
787         This->bih.bV5AlphaMask = 0;
788         This->palette_offset += 12;
789     }
790
791     /* decide what kind of bitmap this is and how/if we can read it */
792     if (This->bih.bV5Size == sizeof(BITMAPCOREHEADER))
793     {
794         BITMAPCOREHEADER *bch = (BITMAPCOREHEADER*)&This->bih;
795         TRACE("BITMAPCOREHEADER with depth=%i\n", bch->bcBitCount);
796         This->bitsperpixel = bch->bcBitCount;
797         This->read_data_func = BmpFrameDecode_ReadUncompressed;
798         switch(bch->bcBitCount)
799         {
800         case 1:
801             This->pixelformat = &GUID_WICPixelFormat1bppIndexed;
802             break;
803         case 2:
804             This->pixelformat = &GUID_WICPixelFormat2bppIndexed;
805             break;
806         case 4:
807             This->pixelformat = &GUID_WICPixelFormat4bppIndexed;
808             break;
809         case 8:
810             This->pixelformat = &GUID_WICPixelFormat8bppIndexed;
811             break;
812         case 24:
813             This->pixelformat = &GUID_WICPixelFormat24bppBGR;
814             break;
815         default:
816             This->pixelformat = &GUID_WICPixelFormatUndefined;
817             WARN("unsupported bit depth %i for BITMAPCOREHEADER\n", bch->bcBitCount);
818             break;
819         }
820     }
821     else /* struct is compatible with BITMAPINFOHEADER */
822     {
823         TRACE("bitmap header=%i compression=%i depth=%i\n", This->bih.bV5Size, This->bih.bV5Compression, This->bih.bV5BitCount);
824         switch(This->bih.bV5Compression)
825         {
826         case BI_RGB:
827             This->bitsperpixel = This->bih.bV5BitCount;
828             This->read_data_func = BmpFrameDecode_ReadUncompressed;
829             switch(This->bih.bV5BitCount)
830             {
831             case 1:
832                 This->pixelformat = &GUID_WICPixelFormat1bppIndexed;
833                 break;
834             case 2:
835                 This->pixelformat = &GUID_WICPixelFormat2bppIndexed;
836                 break;
837             case 4:
838                 This->pixelformat = &GUID_WICPixelFormat4bppIndexed;
839                 break;
840             case 8:
841                 This->pixelformat = &GUID_WICPixelFormat8bppIndexed;
842                 break;
843             case 16:
844                 This->pixelformat = &GUID_WICPixelFormat16bppBGR555;
845                 break;
846             case 24:
847                 This->pixelformat = &GUID_WICPixelFormat24bppBGR;
848                 break;
849             case 32:
850                 This->pixelformat = &GUID_WICPixelFormat32bppBGR;
851                 break;
852             default:
853                 This->pixelformat = &GUID_WICPixelFormatUndefined;
854                 FIXME("unsupported bit depth %i for uncompressed RGB\n", This->bih.bV5BitCount);
855             }
856             break;
857         case BI_RLE8:
858             This->bitsperpixel = 32;
859             This->read_data_func = BmpFrameDecode_ReadRLE8;
860             This->pixelformat = &GUID_WICPixelFormat32bppBGR;
861             break;
862         case BI_RLE4:
863             This->bitsperpixel = 32;
864             This->read_data_func = BmpFrameDecode_ReadRLE4;
865             This->pixelformat = &GUID_WICPixelFormat32bppBGR;
866             break;
867         case BI_BITFIELDS:
868         {
869             const struct bitfields_format *format;
870             if (This->bih.bV5Size == sizeof(BITMAPCOREHEADER2))
871             {
872                 /* BCH2 doesn't support bitfields; this is Huffman 1D compression */
873                 This->bitsperpixel = 0;
874                 This->read_data_func = BmpFrameDecode_ReadUnsupported;
875                 This->pixelformat = &GUID_WICPixelFormatUndefined;
876                 FIXME("Huffman 1D compression is unsupported\n");
877                 break;
878             }
879             This->bitsperpixel = This->bih.bV5BitCount;
880             for (format = bitfields_formats; format->bitcount; format++)
881             {
882                 if ((format->bitcount == This->bih.bV5BitCount) &&
883                     (format->redmask == This->bih.bV5RedMask) &&
884                     (format->greenmask == This->bih.bV5GreenMask) &&
885                     (format->bluemask == This->bih.bV5BlueMask) &&
886                     (format->alphamask == This->bih.bV5AlphaMask))
887                 {
888                     This->read_data_func = format->read_data_func;
889                     This->pixelformat = format->pixelformat;
890                     break;
891                 }
892             }
893             if (!format->bitcount)
894             {
895                 This->read_data_func = BmpFrameDecode_ReadUncompressed;
896                 This->pixelformat = &GUID_WICPixelFormatUndefined;
897                 FIXME("unsupported bitfields type depth=%i red=%x green=%x blue=%x alpha=%x\n",
898                     This->bih.bV5BitCount, This->bih.bV5RedMask, This->bih.bV5GreenMask, This->bih.bV5BlueMask, This->bih.bV5AlphaMask);
899             }
900             break;
901         }
902         default:
903             This->bitsperpixel = 0;
904             This->read_data_func = BmpFrameDecode_ReadUnsupported;
905             This->pixelformat = &GUID_WICPixelFormatUndefined;
906             FIXME("unsupported bitmap type header=%i compression=%i depth=%i\n", This->bih.bV5Size, This->bih.bV5Compression, This->bih.bV5BitCount);
907             break;
908         }
909     }
910
911     if (This->packed)
912     {
913         /* In a packed DIB, the image follows the palette. */
914         ULONG palette_count, palette_size;
915         if (This->bih.bV5ClrUsed)
916             palette_count = This->bih.bV5ClrUsed;
917         else if (This->bih.bV5BitCount <= 8)
918             palette_count = 1 << This->bih.bV5BitCount;
919         else
920             palette_count = 0;
921         if (This->bih.bV5Size == sizeof(BITMAPCOREHEADER))
922             palette_size = sizeof(RGBTRIPLE) * palette_count;
923         else
924             palette_size = sizeof(RGBQUAD) * palette_count;
925         This->image_offset = This->palette_offset + palette_size;
926     }
927
928     This->initialized = TRUE;
929
930     return S_OK;
931 }
932
933 static HRESULT WINAPI BmpDecoder_QueryInterface(IWICBitmapDecoder *iface, REFIID iid,
934     void **ppv)
935 {
936     BmpDecoder *This = (BmpDecoder*)iface;
937     TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
938
939     if (!ppv) return E_INVALIDARG;
940
941     if (IsEqualIID(&IID_IUnknown, iid) || IsEqualIID(&IID_IWICBitmapDecoder, iid))
942     {
943         *ppv = This;
944     }
945     else
946     {
947         *ppv = NULL;
948         return E_NOINTERFACE;
949     }
950
951     IUnknown_AddRef((IUnknown*)*ppv);
952     return S_OK;
953 }
954
955 static ULONG WINAPI BmpDecoder_AddRef(IWICBitmapDecoder *iface)
956 {
957     BmpDecoder *This = (BmpDecoder*)iface;
958     ULONG ref = InterlockedIncrement(&This->ref);
959
960     TRACE("(%p) refcount=%u\n", iface, ref);
961
962     return ref;
963 }
964
965 static ULONG WINAPI BmpDecoder_Release(IWICBitmapDecoder *iface)
966 {
967     BmpDecoder *This = (BmpDecoder*)iface;
968     ULONG ref = InterlockedDecrement(&This->ref);
969
970     TRACE("(%p) refcount=%u\n", iface, ref);
971
972     if (ref == 0)
973     {
974         if (This->stream) IStream_Release(This->stream);
975         HeapFree(GetProcessHeap(), 0, This->imagedata);
976         This->lock.DebugInfo->Spare[0] = 0;
977         DeleteCriticalSection(&This->lock);
978         HeapFree(GetProcessHeap(), 0, This);
979     }
980
981     return ref;
982 }
983
984 static HRESULT WINAPI BmpDecoder_QueryCapability(IWICBitmapDecoder *iface, IStream *pIStream,
985     DWORD *pdwCapability)
986 {
987     HRESULT hr;
988     BmpDecoder *This = (BmpDecoder*)iface;
989
990     EnterCriticalSection(&This->lock);
991     hr = BmpDecoder_ReadHeaders(This, pIStream);
992     LeaveCriticalSection(&This->lock);
993     if (FAILED(hr)) return hr;
994
995     if (This->read_data_func == BmpFrameDecode_ReadUnsupported)
996         *pdwCapability = 0;
997     else
998         *pdwCapability = WICBitmapDecoderCapabilityCanDecodeAllImages;
999
1000     return S_OK;
1001 }
1002
1003 static HRESULT WINAPI BmpDecoder_Initialize(IWICBitmapDecoder *iface, IStream *pIStream,
1004     WICDecodeOptions cacheOptions)
1005 {
1006     HRESULT hr;
1007     BmpDecoder *This = (BmpDecoder*)iface;
1008
1009     EnterCriticalSection(&This->lock);
1010     hr = BmpDecoder_ReadHeaders(This, pIStream);
1011
1012     if (SUCCEEDED(hr))
1013     {
1014         This->stream = pIStream;
1015         IStream_AddRef(pIStream);
1016     }
1017     LeaveCriticalSection(&This->lock);
1018
1019     return hr;
1020 }
1021
1022 static HRESULT WINAPI BmpDecoder_GetContainerFormat(IWICBitmapDecoder *iface,
1023     GUID *pguidContainerFormat)
1024 {
1025     memcpy(pguidContainerFormat, &GUID_ContainerFormatBmp, sizeof(GUID));
1026     return S_OK;
1027 }
1028
1029 static HRESULT WINAPI BmpDecoder_GetDecoderInfo(IWICBitmapDecoder *iface,
1030     IWICBitmapDecoderInfo **ppIDecoderInfo)
1031 {
1032     HRESULT hr;
1033     IWICComponentInfo *compinfo;
1034
1035     TRACE("(%p,%p)\n", iface, ppIDecoderInfo);
1036
1037     hr = CreateComponentInfo(&CLSID_WICBmpDecoder, &compinfo);
1038     if (FAILED(hr)) return hr;
1039
1040     hr = IWICComponentInfo_QueryInterface(compinfo, &IID_IWICBitmapDecoderInfo,
1041         (void**)ppIDecoderInfo);
1042
1043     IWICComponentInfo_Release(compinfo);
1044
1045     return hr;
1046 }
1047
1048 static HRESULT WINAPI BmpDecoder_CopyPalette(IWICBitmapDecoder *iface,
1049     IWICPalette *pIPalette)
1050 {
1051     TRACE("(%p,%p)\n", iface, pIPalette);
1052
1053     return WINCODEC_ERR_PALETTEUNAVAILABLE;
1054 }
1055
1056 static HRESULT WINAPI BmpDecoder_GetMetadataQueryReader(IWICBitmapDecoder *iface,
1057     IWICMetadataQueryReader **ppIMetadataQueryReader)
1058 {
1059     TRACE("(%p,%p)\n", iface, ppIMetadataQueryReader);
1060     return WINCODEC_ERR_UNSUPPORTEDOPERATION;
1061 }
1062
1063 static HRESULT WINAPI BmpDecoder_GetPreview(IWICBitmapDecoder *iface,
1064     IWICBitmapSource **ppIBitmapSource)
1065 {
1066     TRACE("(%p,%p)\n", iface, ppIBitmapSource);
1067     return WINCODEC_ERR_UNSUPPORTEDOPERATION;
1068 }
1069
1070 static HRESULT WINAPI BmpDecoder_GetColorContexts(IWICBitmapDecoder *iface,
1071     UINT cCount, IWICColorContext **ppIColorContexts, UINT *pcActualCount)
1072 {
1073     TRACE("(%p,%u,%p,%p)\n", iface, cCount, ppIColorContexts, pcActualCount);
1074     return WINCODEC_ERR_UNSUPPORTEDOPERATION;
1075 }
1076
1077 static HRESULT WINAPI BmpDecoder_GetThumbnail(IWICBitmapDecoder *iface,
1078     IWICBitmapSource **ppIThumbnail)
1079 {
1080     TRACE("(%p,%p)\n", iface, ppIThumbnail);
1081     return WINCODEC_ERR_CODECNOTHUMBNAIL;
1082 }
1083
1084 static HRESULT WINAPI BmpDecoder_GetFrameCount(IWICBitmapDecoder *iface,
1085     UINT *pCount)
1086 {
1087     *pCount = 1;
1088     return S_OK;
1089 }
1090
1091 static HRESULT WINAPI BmpDecoder_GetFrame(IWICBitmapDecoder *iface,
1092     UINT index, IWICBitmapFrameDecode **ppIBitmapFrame)
1093 {
1094     BmpDecoder *This = (BmpDecoder*)iface;
1095
1096     if (index != 0) return E_INVALIDARG;
1097
1098     if (!This->stream) return WINCODEC_ERR_WRONGSTATE;
1099
1100     *ppIBitmapFrame = (IWICBitmapFrameDecode*)&This->lpFrameVtbl;
1101     IWICBitmapDecoder_AddRef(iface);
1102
1103     return S_OK;
1104 }
1105
1106 static const IWICBitmapDecoderVtbl BmpDecoder_Vtbl = {
1107     BmpDecoder_QueryInterface,
1108     BmpDecoder_AddRef,
1109     BmpDecoder_Release,
1110     BmpDecoder_QueryCapability,
1111     BmpDecoder_Initialize,
1112     BmpDecoder_GetContainerFormat,
1113     BmpDecoder_GetDecoderInfo,
1114     BmpDecoder_CopyPalette,
1115     BmpDecoder_GetMetadataQueryReader,
1116     BmpDecoder_GetPreview,
1117     BmpDecoder_GetColorContexts,
1118     BmpDecoder_GetThumbnail,
1119     BmpDecoder_GetFrameCount,
1120     BmpDecoder_GetFrame
1121 };
1122
1123 static HRESULT BmpDecoder_Construct(int packed, int icoframe, IUnknown *pUnkOuter, REFIID iid, void** ppv)
1124 {
1125     BmpDecoder *This;
1126     HRESULT ret;
1127
1128     TRACE("(%p,%s,%p)\n", pUnkOuter, debugstr_guid(iid), ppv);
1129
1130     *ppv = NULL;
1131
1132     if (pUnkOuter) return CLASS_E_NOAGGREGATION;
1133
1134     This = HeapAlloc(GetProcessHeap(), 0, sizeof(BmpDecoder));
1135     if (!This) return E_OUTOFMEMORY;
1136
1137     This->lpVtbl = &BmpDecoder_Vtbl;
1138     This->lpFrameVtbl = &BmpDecoder_FrameVtbl;
1139     This->ref = 1;
1140     This->initialized = FALSE;
1141     This->stream = NULL;
1142     This->imagedata = NULL;
1143     InitializeCriticalSection(&This->lock);
1144     This->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": BmpDecoder.lock");
1145     This->packed = packed;
1146     This->icoframe = icoframe;
1147
1148     ret = IUnknown_QueryInterface((IUnknown*)This, iid, ppv);
1149     IUnknown_Release((IUnknown*)This);
1150
1151     return ret;
1152 }
1153
1154 HRESULT BmpDecoder_CreateInstance(IUnknown *pUnkOuter, REFIID iid, void** ppv)
1155 {
1156     return BmpDecoder_Construct(FALSE, FALSE, pUnkOuter, iid, ppv);
1157 }
1158
1159 HRESULT DibDecoder_CreateInstance(IUnknown *pUnkOuter, REFIID iid, void** ppv)
1160 {
1161     return BmpDecoder_Construct(TRUE, FALSE, pUnkOuter, iid, ppv);
1162 }
1163
1164 HRESULT IcoDibDecoder_CreateInstance(IUnknown *pUnkOuter, REFIID iid, void** ppv)
1165 {
1166     return BmpDecoder_Construct(TRUE, TRUE, pUnkOuter, iid, ppv);
1167 }
1168
1169 /* Return the offset where the mask of an icon might be, or 0 for failure. */
1170 void BmpDecoder_FindIconMask(IWICBitmapDecoder *decoder, ULONG *mask_offset, int *topdown)
1171 {
1172     BmpDecoder *This = (BmpDecoder*)decoder;
1173
1174     assert(This->lpVtbl == &BmpDecoder_Vtbl);
1175     assert(This->stream != NULL);
1176
1177     if (This->read_data_func == BmpFrameDecode_ReadUncompressed)
1178     {
1179         /* RGB or BITFIELDS data */
1180         ULONG width, height, bytesperrow, datasize;
1181         IWICBitmapFrameDecode_GetSize((IWICBitmapFrameDecode*)&This->lpFrameVtbl, &width, &height);
1182         bytesperrow = (((width * This->bitsperpixel)+31)/32)*4;
1183         datasize = bytesperrow * height;
1184         *mask_offset = This->image_offset + datasize;
1185     }
1186     else
1187         *mask_offset = 0;
1188
1189     *topdown = This->stride > 0;
1190 }