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