wined3d: The ARB loop unroller's iteration is unsigned.
[wine] / dlls / windowscodecs / jpegformat.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 #include "wine/port.h"
21
22 #ifdef HAVE_UNISTD_H
23 # include <unistd.h>
24 #endif
25 #include <stdarg.h>
26 #include <stdio.h>
27 #include <string.h>
28
29 #ifdef SONAME_LIBJPEG
30 /* This is a hack, so jpeglib.h does not redefine INT32 and the like*/
31 #define XMD_H
32 #define UINT8 JPEG_UINT8
33 #define UINT16 JPEG_UINT16
34 #define boolean jpeg_boolean
35 #undef HAVE_STDLIB_H
36 # include <jpeglib.h>
37 #undef HAVE_STDLIB_H
38 #define HAVE_STDLIB_H 1
39 #undef UINT8
40 #undef UINT16
41 #undef boolean
42 #endif
43
44 #define COBJMACROS
45
46 #include "windef.h"
47 #include "winbase.h"
48 #include "objbase.h"
49 #include "wincodec.h"
50
51 #include "wincodecs_private.h"
52
53 #include "wine/debug.h"
54 #include "wine/library.h"
55
56 WINE_DEFAULT_DEBUG_CHANNEL(wincodecs);
57
58 #ifdef SONAME_LIBJPEG
59
60 static void *libjpeg_handle;
61
62 #define MAKE_FUNCPTR(f) static typeof(f) * p##f
63 MAKE_FUNCPTR(jpeg_CreateDecompress);
64 MAKE_FUNCPTR(jpeg_destroy_decompress);
65 MAKE_FUNCPTR(jpeg_read_header);
66 MAKE_FUNCPTR(jpeg_read_scanlines);
67 MAKE_FUNCPTR(jpeg_resync_to_restart);
68 MAKE_FUNCPTR(jpeg_start_decompress);
69 MAKE_FUNCPTR(jpeg_std_error);
70 #undef MAKE_FUNCPTR
71
72 static void *load_libjpeg(void)
73 {
74     if((libjpeg_handle = wine_dlopen(SONAME_LIBJPEG, RTLD_NOW, NULL, 0)) != NULL) {
75
76 #define LOAD_FUNCPTR(f) \
77     if((p##f = wine_dlsym(libjpeg_handle, #f, NULL, 0)) == NULL) { \
78         libjpeg_handle = NULL; \
79         return NULL; \
80     }
81
82         LOAD_FUNCPTR(jpeg_CreateDecompress);
83         LOAD_FUNCPTR(jpeg_destroy_decompress);
84         LOAD_FUNCPTR(jpeg_read_header);
85         LOAD_FUNCPTR(jpeg_read_scanlines);
86         LOAD_FUNCPTR(jpeg_resync_to_restart);
87         LOAD_FUNCPTR(jpeg_start_decompress);
88         LOAD_FUNCPTR(jpeg_std_error);
89 #undef LOAD_FUNCPTR
90     }
91     return libjpeg_handle;
92 }
93
94 typedef struct {
95     const IWICBitmapDecoderVtbl *lpVtbl;
96     const IWICBitmapFrameDecodeVtbl *lpFrameVtbl;
97     LONG ref;
98     BOOL initialized;
99     BOOL cinfo_initialized;
100     IStream *stream;
101     struct jpeg_decompress_struct cinfo;
102     struct jpeg_error_mgr jerr;
103     struct jpeg_source_mgr source_mgr;
104     BYTE source_buffer[1024];
105     BYTE *image_data;
106     CRITICAL_SECTION lock;
107 } JpegDecoder;
108
109 static inline JpegDecoder *decoder_from_decompress(j_decompress_ptr decompress)
110 {
111     return CONTAINING_RECORD(decompress, JpegDecoder, cinfo);
112 }
113
114 static inline JpegDecoder *decoder_from_frame(IWICBitmapFrameDecode *iface)
115 {
116     return CONTAINING_RECORD(iface, JpegDecoder, lpFrameVtbl);
117 }
118
119 static HRESULT WINAPI JpegDecoder_QueryInterface(IWICBitmapDecoder *iface, REFIID iid,
120     void **ppv)
121 {
122     JpegDecoder *This = (JpegDecoder*)iface;
123     TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
124
125     if (!ppv) return E_INVALIDARG;
126
127     if (IsEqualIID(&IID_IUnknown, iid) || IsEqualIID(&IID_IWICBitmapDecoder, iid))
128     {
129         *ppv = This;
130     }
131     else
132     {
133         *ppv = NULL;
134         return E_NOINTERFACE;
135     }
136
137     IUnknown_AddRef((IUnknown*)*ppv);
138     return S_OK;
139 }
140
141 static ULONG WINAPI JpegDecoder_AddRef(IWICBitmapDecoder *iface)
142 {
143     JpegDecoder *This = (JpegDecoder*)iface;
144     ULONG ref = InterlockedIncrement(&This->ref);
145
146     TRACE("(%p) refcount=%u\n", iface, ref);
147
148     return ref;
149 }
150
151 static ULONG WINAPI JpegDecoder_Release(IWICBitmapDecoder *iface)
152 {
153     JpegDecoder *This = (JpegDecoder*)iface;
154     ULONG ref = InterlockedDecrement(&This->ref);
155
156     TRACE("(%p) refcount=%u\n", iface, ref);
157
158     if (ref == 0)
159     {
160         This->lock.DebugInfo->Spare[0] = 0;
161         DeleteCriticalSection(&This->lock);
162         if (This->cinfo_initialized) pjpeg_destroy_decompress(&This->cinfo);
163         if (This->stream) IStream_Release(This->stream);
164         HeapFree(GetProcessHeap(), 0, This->image_data);
165         HeapFree(GetProcessHeap(), 0, This);
166     }
167
168     return ref;
169 }
170
171 static HRESULT WINAPI JpegDecoder_QueryCapability(IWICBitmapDecoder *iface, IStream *pIStream,
172     DWORD *pdwCapability)
173 {
174     FIXME("(%p,%p,%p): stub\n", iface, pIStream, pdwCapability);
175     return E_NOTIMPL;
176 }
177
178 static void source_mgr_init_source(j_decompress_ptr cinfo)
179 {
180 }
181
182 static jpeg_boolean source_mgr_fill_input_buffer(j_decompress_ptr cinfo)
183 {
184     JpegDecoder *This = decoder_from_decompress(cinfo);
185     HRESULT hr;
186     ULONG bytesread;
187
188     hr = IStream_Read(This->stream, This->source_buffer, 1024, &bytesread);
189
190     if (hr != S_OK || bytesread == 0)
191     {
192         return FALSE;
193     }
194     else
195     {
196         This->source_mgr.next_input_byte = This->source_buffer;
197         This->source_mgr.bytes_in_buffer = bytesread;
198         return TRUE;
199     }
200 }
201
202 static void source_mgr_skip_input_data(j_decompress_ptr cinfo, long num_bytes)
203 {
204     JpegDecoder *This = decoder_from_decompress(cinfo);
205     LARGE_INTEGER seek;
206
207     if (num_bytes > This->source_mgr.bytes_in_buffer)
208     {
209         seek.QuadPart = num_bytes - This->source_mgr.bytes_in_buffer;
210         IStream_Seek(This->stream, seek, STREAM_SEEK_CUR, NULL);
211         This->source_mgr.bytes_in_buffer = 0;
212     }
213     else if (num_bytes > 0)
214     {
215         This->source_mgr.next_input_byte += num_bytes;
216         This->source_mgr.bytes_in_buffer -= num_bytes;
217     }
218 }
219
220 static void source_mgr_term_source(j_decompress_ptr cinfo)
221 {
222 }
223
224 static HRESULT WINAPI JpegDecoder_Initialize(IWICBitmapDecoder *iface, IStream *pIStream,
225     WICDecodeOptions cacheOptions)
226 {
227     JpegDecoder *This = (JpegDecoder*)iface;
228     int ret;
229     LARGE_INTEGER seek;
230     TRACE("(%p,%p,%u)\n", iface, pIStream, cacheOptions);
231
232     EnterCriticalSection(&This->lock);
233
234     if (This->cinfo_initialized)
235     {
236         LeaveCriticalSection(&This->lock);
237         return WINCODEC_ERR_WRONGSTATE;
238     }
239
240     This->cinfo.err = pjpeg_std_error(&This->jerr);
241
242     pjpeg_CreateDecompress(&This->cinfo, JPEG_LIB_VERSION, sizeof(struct jpeg_decompress_struct));
243
244     This->cinfo_initialized = TRUE;
245
246     This->stream = pIStream;
247     IStream_AddRef(pIStream);
248
249     seek.QuadPart = 0;
250     IStream_Seek(This->stream, seek, STREAM_SEEK_SET, NULL);
251
252     This->source_mgr.bytes_in_buffer = 0;
253     This->source_mgr.init_source = source_mgr_init_source;
254     This->source_mgr.fill_input_buffer = source_mgr_fill_input_buffer;
255     This->source_mgr.skip_input_data = source_mgr_skip_input_data;
256     This->source_mgr.resync_to_restart = pjpeg_resync_to_restart;
257     This->source_mgr.term_source = source_mgr_term_source;
258
259     This->cinfo.src = &This->source_mgr;
260
261     ret = pjpeg_read_header(&This->cinfo, TRUE);
262
263     if (ret != JPEG_HEADER_OK) {
264         WARN("Jpeg image in stream has bad format, read header returned %d.\n",ret);
265         LeaveCriticalSection(&This->lock);
266         return E_FAIL;
267     }
268
269     if (This->cinfo.jpeg_color_space == JCS_GRAYSCALE)
270         This->cinfo.out_color_space = JCS_GRAYSCALE;
271     else
272         This->cinfo.out_color_space = JCS_RGB;
273
274     if (!pjpeg_start_decompress(&This->cinfo))
275     {
276         ERR("jpeg_start_decompress failed\n");
277         LeaveCriticalSection(&This->lock);
278         return E_FAIL;
279     }
280
281     This->initialized = TRUE;
282
283     LeaveCriticalSection(&This->lock);
284
285     return S_OK;
286 }
287
288 static HRESULT WINAPI JpegDecoder_GetContainerFormat(IWICBitmapDecoder *iface,
289     GUID *pguidContainerFormat)
290 {
291     memcpy(pguidContainerFormat, &GUID_ContainerFormatJpeg, sizeof(GUID));
292     return S_OK;
293 }
294
295 static HRESULT WINAPI JpegDecoder_GetDecoderInfo(IWICBitmapDecoder *iface,
296     IWICBitmapDecoderInfo **ppIDecoderInfo)
297 {
298     FIXME("(%p,%p): stub\n", iface, ppIDecoderInfo);
299     return E_NOTIMPL;
300 }
301
302 static HRESULT WINAPI JpegDecoder_CopyPalette(IWICBitmapDecoder *iface,
303     IWICPalette *pIPalette)
304 {
305     TRACE("(%p,%p)\n", iface, pIPalette);
306
307     return WINCODEC_ERR_PALETTEUNAVAILABLE;
308 }
309
310 static HRESULT WINAPI JpegDecoder_GetMetadataQueryReader(IWICBitmapDecoder *iface,
311     IWICMetadataQueryReader **ppIMetadataQueryReader)
312 {
313     FIXME("(%p,%p): stub\n", iface, ppIMetadataQueryReader);
314     return E_NOTIMPL;
315 }
316
317 static HRESULT WINAPI JpegDecoder_GetPreview(IWICBitmapDecoder *iface,
318     IWICBitmapSource **ppIBitmapSource)
319 {
320     FIXME("(%p,%p): stub\n", iface, ppIBitmapSource);
321     return WINCODEC_ERR_UNSUPPORTEDOPERATION;
322 }
323
324 static HRESULT WINAPI JpegDecoder_GetColorContexts(IWICBitmapDecoder *iface,
325     UINT cCount, IWICColorContext **ppIColorContexts, UINT *pcActualCount)
326 {
327     FIXME("(%p,%u,%p,%p): stub\n", iface, cCount, ppIColorContexts, pcActualCount);
328     return WINCODEC_ERR_UNSUPPORTEDOPERATION;
329 }
330
331 static HRESULT WINAPI JpegDecoder_GetThumbnail(IWICBitmapDecoder *iface,
332     IWICBitmapSource **ppIThumbnail)
333 {
334     FIXME("(%p,%p): stub\n", iface, ppIThumbnail);
335     return WINCODEC_ERR_CODECNOTHUMBNAIL;
336 }
337
338 static HRESULT WINAPI JpegDecoder_GetFrameCount(IWICBitmapDecoder *iface,
339     UINT *pCount)
340 {
341     *pCount = 1;
342     return S_OK;
343 }
344
345 static HRESULT WINAPI JpegDecoder_GetFrame(IWICBitmapDecoder *iface,
346     UINT index, IWICBitmapFrameDecode **ppIBitmapFrame)
347 {
348     JpegDecoder *This = (JpegDecoder*)iface;
349     TRACE("(%p,%u,%p)\n", iface, index, ppIBitmapFrame);
350
351     if (!This->initialized) return WINCODEC_ERR_NOTINITIALIZED;
352
353     if (index != 0) return E_INVALIDARG;
354
355     IWICBitmapDecoder_AddRef(iface);
356     *ppIBitmapFrame = (IWICBitmapFrameDecode*)&This->lpFrameVtbl;
357
358     return S_OK;
359 }
360
361 static const IWICBitmapDecoderVtbl JpegDecoder_Vtbl = {
362     JpegDecoder_QueryInterface,
363     JpegDecoder_AddRef,
364     JpegDecoder_Release,
365     JpegDecoder_QueryCapability,
366     JpegDecoder_Initialize,
367     JpegDecoder_GetContainerFormat,
368     JpegDecoder_GetDecoderInfo,
369     JpegDecoder_CopyPalette,
370     JpegDecoder_GetMetadataQueryReader,
371     JpegDecoder_GetPreview,
372     JpegDecoder_GetColorContexts,
373     JpegDecoder_GetThumbnail,
374     JpegDecoder_GetFrameCount,
375     JpegDecoder_GetFrame
376 };
377
378 static HRESULT WINAPI JpegDecoder_Frame_QueryInterface(IWICBitmapFrameDecode *iface, REFIID iid,
379     void **ppv)
380 {
381     TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
382
383     if (!ppv) return E_INVALIDARG;
384
385     if (IsEqualIID(&IID_IUnknown, iid) ||
386         IsEqualIID(&IID_IWICBitmapSource, iid) ||
387         IsEqualIID(&IID_IWICBitmapFrameDecode, iid))
388     {
389         *ppv = iface;
390     }
391     else
392     {
393         *ppv = NULL;
394         return E_NOINTERFACE;
395     }
396
397     IUnknown_AddRef((IUnknown*)*ppv);
398     return S_OK;
399 }
400
401 static ULONG WINAPI JpegDecoder_Frame_AddRef(IWICBitmapFrameDecode *iface)
402 {
403     JpegDecoder *This = decoder_from_frame(iface);
404     return IUnknown_AddRef((IUnknown*)This);
405 }
406
407 static ULONG WINAPI JpegDecoder_Frame_Release(IWICBitmapFrameDecode *iface)
408 {
409     JpegDecoder *This = decoder_from_frame(iface);
410     return IUnknown_Release((IUnknown*)This);
411 }
412
413 static HRESULT WINAPI JpegDecoder_Frame_GetSize(IWICBitmapFrameDecode *iface,
414     UINT *puiWidth, UINT *puiHeight)
415 {
416     JpegDecoder *This = decoder_from_frame(iface);
417     *puiWidth = This->cinfo.output_width;
418     *puiHeight = This->cinfo.output_height;
419     TRACE("(%p)->(%u,%u)\n", iface, *puiWidth, *puiHeight);
420     return S_OK;
421 }
422
423 static HRESULT WINAPI JpegDecoder_Frame_GetPixelFormat(IWICBitmapFrameDecode *iface,
424     WICPixelFormatGUID *pPixelFormat)
425 {
426     JpegDecoder *This = decoder_from_frame(iface);
427     TRACE("(%p,%p)\n", iface, pPixelFormat);
428     if (This->cinfo.out_color_space == JCS_RGB)
429         memcpy(pPixelFormat, &GUID_WICPixelFormat24bppBGR, sizeof(GUID));
430     else /* This->cinfo.out_color_space == JCS_GRAYSCALE */
431         memcpy(pPixelFormat, &GUID_WICPixelFormat8bppGray, sizeof(GUID));
432     return S_OK;
433 }
434
435 static HRESULT WINAPI JpegDecoder_Frame_GetResolution(IWICBitmapFrameDecode *iface,
436     double *pDpiX, double *pDpiY)
437 {
438     FIXME("(%p,%p,%p): stub\n", iface, pDpiX, pDpiY);
439     return E_NOTIMPL;
440 }
441
442 static HRESULT WINAPI JpegDecoder_Frame_CopyPalette(IWICBitmapFrameDecode *iface,
443     IWICPalette *pIPalette)
444 {
445     FIXME("(%p,%p): stub\n", iface, pIPalette);
446     return E_NOTIMPL;
447 }
448
449 static HRESULT WINAPI JpegDecoder_Frame_CopyPixels(IWICBitmapFrameDecode *iface,
450     const WICRect *prc, UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer)
451 {
452     JpegDecoder *This = decoder_from_frame(iface);
453     UINT bpp;
454     UINT stride;
455     UINT data_size;
456     UINT max_row_needed;
457     TRACE("(%p,%p,%u,%u,%p)\n", iface, prc, cbStride, cbBufferSize, pbBuffer);
458
459     if (This->cinfo.out_color_space == JCS_GRAYSCALE) bpp = 8;
460     else bpp = 24;
461
462     stride = bpp * This->cinfo.output_width;
463     data_size = stride * This->cinfo.output_height;
464
465     max_row_needed = prc->Y + prc->Height;
466     if (max_row_needed > This->cinfo.output_height) return E_INVALIDARG;
467
468     EnterCriticalSection(&This->lock);
469
470     if (!This->image_data)
471     {
472         This->image_data = HeapAlloc(GetProcessHeap(), 0, data_size);
473         if (!This->image_data)
474         {
475             LeaveCriticalSection(&This->lock);
476             return E_OUTOFMEMORY;
477         }
478     }
479
480     while (max_row_needed > This->cinfo.output_scanline)
481     {
482         UINT first_scanline = This->cinfo.output_scanline;
483         UINT max_rows;
484         JSAMPROW out_rows[4];
485         UINT i, j;
486         JDIMENSION ret;
487
488         max_rows = min(This->cinfo.output_height-first_scanline, 4);
489         for (i=0; i<max_rows; i++)
490             out_rows[i] = This->image_data + stride * (first_scanline+i);
491
492         ret = pjpeg_read_scanlines(&This->cinfo, out_rows, max_rows);
493
494         if (ret == 0)
495         {
496             ERR("read_scanlines failed\n");
497             LeaveCriticalSection(&This->lock);
498             return E_FAIL;
499         }
500
501         if (bpp == 24)
502         {
503             /* libjpeg gives us RGB data and we want BGR, so byteswap the data */
504             for (i=first_scanline; i<This->cinfo.output_scanline; i++)
505             {
506                 BYTE *pixel = This->image_data + stride * i;
507                 for (j=0; j<This->cinfo.output_width; j++)
508                 {
509                     BYTE red=pixel[0];
510                     BYTE blue=pixel[2];
511                     pixel[0]=blue;
512                     pixel[2]=red;
513                     pixel+=3;
514                 }
515             }
516         }
517     }
518
519     LeaveCriticalSection(&This->lock);
520
521     return copy_pixels(bpp, This->image_data,
522         This->cinfo.output_width, This->cinfo.output_height, stride,
523         prc, cbStride, cbBufferSize, pbBuffer);
524 }
525
526 static HRESULT WINAPI JpegDecoder_Frame_GetMetadataQueryReader(IWICBitmapFrameDecode *iface,
527     IWICMetadataQueryReader **ppIMetadataQueryReader)
528 {
529     FIXME("(%p,%p): stub\n", iface, ppIMetadataQueryReader);
530     return WINCODEC_ERR_UNSUPPORTEDOPERATION;
531 }
532
533 static HRESULT WINAPI JpegDecoder_Frame_GetColorContexts(IWICBitmapFrameDecode *iface,
534     UINT cCount, IWICColorContext **ppIColorContexts, UINT *pcActualCount)
535 {
536     FIXME("(%p,%u,%p,%p): stub\n", iface, cCount, ppIColorContexts, pcActualCount);
537     return WINCODEC_ERR_UNSUPPORTEDOPERATION;
538 }
539
540 static HRESULT WINAPI JpegDecoder_Frame_GetThumbnail(IWICBitmapFrameDecode *iface,
541     IWICBitmapSource **ppIThumbnail)
542 {
543     FIXME("(%p,%p): stub\n", iface, ppIThumbnail);
544     return WINCODEC_ERR_CODECNOTHUMBNAIL;
545 }
546
547 static const IWICBitmapFrameDecodeVtbl JpegDecoder_Frame_Vtbl = {
548     JpegDecoder_Frame_QueryInterface,
549     JpegDecoder_Frame_AddRef,
550     JpegDecoder_Frame_Release,
551     JpegDecoder_Frame_GetSize,
552     JpegDecoder_Frame_GetPixelFormat,
553     JpegDecoder_Frame_GetResolution,
554     JpegDecoder_Frame_CopyPalette,
555     JpegDecoder_Frame_CopyPixels,
556     JpegDecoder_Frame_GetMetadataQueryReader,
557     JpegDecoder_Frame_GetColorContexts,
558     JpegDecoder_Frame_GetThumbnail
559 };
560
561 HRESULT JpegDecoder_CreateInstance(IUnknown *pUnkOuter, REFIID iid, void** ppv)
562 {
563     JpegDecoder *This;
564     HRESULT ret;
565
566     TRACE("(%p,%s,%p)\n", pUnkOuter, debugstr_guid(iid), ppv);
567
568     if (!libjpeg_handle && !load_libjpeg())
569     {
570         ERR("Failed reading JPEG because unable to find %s\n", SONAME_LIBJPEG);
571         return E_FAIL;
572     }
573
574     *ppv = NULL;
575
576     if (pUnkOuter) return CLASS_E_NOAGGREGATION;
577
578     This = HeapAlloc(GetProcessHeap(), 0, sizeof(JpegDecoder));
579     if (!This) return E_OUTOFMEMORY;
580
581     This->lpVtbl = &JpegDecoder_Vtbl;
582     This->lpFrameVtbl = &JpegDecoder_Frame_Vtbl;
583     This->ref = 1;
584     This->initialized = FALSE;
585     This->cinfo_initialized = FALSE;
586     This->stream = NULL;
587     This->image_data = NULL;
588     InitializeCriticalSection(&This->lock);
589     This->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": JpegDecoder.lock");
590
591     ret = IUnknown_QueryInterface((IUnknown*)This, iid, ppv);
592     IUnknown_Release((IUnknown*)This);
593
594     return ret;
595 }
596
597 #else /* !defined(SONAME_LIBJPEG) */
598
599 HRESULT JpegDecoder_CreateInstance(IUnknown *pUnkOuter, REFIID iid, void** ppv)
600 {
601     ERR("Trying to load JPEG picture, but JPEG support is not compiled in.\n");
602     return E_FAIL;
603 }
604
605 #endif