~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Wine Cross Reference
wine/dlls/windowscodecs/tiffformat.c

Version: ~ [ wine-1.5.31 ] ~ [ wine-1.5.30 ] ~ [ wine-1.5.29 ] ~ [ wine-1.5.28 ] ~ [ wine-1.5.27 ] ~ [ wine-1.5.26 ] ~ [ wine-1.5.25 ] ~ [ wine-1.5.24 ] ~ [ wine-1.5.23 ] ~ [ wine-1.5.22 ] ~ [ wine-1.5.21 ] ~ [ wine-1.5.20 ] ~ [ wine-1.5.19 ] ~ [ wine-1.5.18 ] ~ [ wine-1.5.17 ] ~ [ wine-1.5.16 ] ~ [ wine-1.5.15 ] ~ [ wine-1.5.14 ] ~ [ wine-1.5.13 ] ~ [ wine-1.5.12 ] ~ [ wine-1.5.11 ] ~ [ wine-1.5.10 ] ~ [ wine-1.5.9 ] ~ [ wine-1.5.8 ] ~ [ wine-1.5.7 ] ~ [ wine-1.4.1 ] ~ [ wine-1.5.6 ] ~ [ wine-1.5.5 ] ~ [ wine-1.5.4 ] ~ [ wine-1.5.3 ] ~ [ wine-1.5.2 ] ~ [ wine-1.5.1 ] ~ [ wine-1.5.0 ] ~ [ wine-1.4 ] ~ [ wine-1.4-rc6 ] ~ [ wine-1.4-rc5 ] ~ [ wine-1.4-rc4 ] ~ [ wine-1.4-rc3 ] ~ [ wine-1.4-rc2 ] ~ [ wine-1.4-rc1 ] ~ [ wine-1.3.37 ] ~ [ wine-1.3.36 ] ~ [ wine-1.3.35 ] ~ [ wine-1.3.34 ] ~ [ wine-1.3.33 ] ~ [ wine-1.3.32 ] ~ [ wine-1.3.31 ] ~ [ wine-1.3.30 ] ~ [ wine-1.3.29 ] ~ [ wine-1.3.28 ] ~ [ wine-1.3.27 ] ~ [ wine-1.3.26 ] ~ [ wine-1.3.25 ] ~ [ wine-1.3.24 ] ~ [ wine-1.3.23 ] ~ [ wine-1.3.22 ] ~ [ wine-1.3.21 ] ~ [ wine-1.3.20 ] ~ [ wine-1.3.19 ] ~ [ wine-1.3.18 ] ~ [ wine-1.2.3 ] ~ [ wine-1.3.17 ] ~ [ wine-1.3.16 ] ~ [ wine-1.3.15 ] ~ [ wine-1.3.14 ] ~ [ wine-1.3.13 ] ~ [ wine-1.3.12 ] ~ [ wine-1.3.11 ] ~ [ wine-1.3.10 ] ~ [ wine-1.3.9 ] ~ [ wine-1.2.2 ] ~ [ wine-1.3.8 ] ~ [ wine-1.3.7 ] ~ [ wine-1.3.6 ] ~ [ wine-1.3.5 ] ~ [ wine-1.2.1 ] ~ [ wine-1.3.4 ] ~ [ wine-1.3.3 ] ~ [ wine-1.3.2 ] ~ [ wine-1.3.1 ] ~ [ wine-1.3.0 ] ~ [ wine-1.2 ] ~ [ wine-1.2-rc7 ] ~ [ wine-1.2-rc6 ] ~ [ wine-1.2-rc5 ] ~ [ wine-1.2-rc4 ] ~ [ wine-1.2-rc3 ] ~ [ wine-1.2-rc2 ] ~ [ wine-1.2-rc1 ] ~ [ wine-1.1.44 ] ~ [ wine-1.1.43 ] ~ [ wine-1.1.42 ] ~ [ wine-1.1.41 ] ~ [ wine-1.1.40 ] ~ [ wine-1.1.39 ] ~ [ wine-1.1.38 ] ~ [ wine-1.1.37 ] ~ [ wine-1.1.36 ] ~ [ wine-1.1.35 ] ~ [ wine-1.1.34 ] ~ [ wine-1.1.33 ] ~ [ wine-1.1.32 ] ~ [ wine-1.1.31 ] ~ [ wine-1.1.30 ] ~ [ wine-1.1.29 ] ~ [ wine-1.1.28 ] ~ [ wine-1.1.27 ] ~ [ wine-1.1.26 ] ~ [ wine-1.1.25 ] ~ [ wine-1.1.24 ] ~ [ wine-1.1.23 ] ~ [ wine-1.1.22 ] ~ [ wine-1.1.21 ] ~ [ wine-1.1.20 ] ~ [ wine-1.1.19 ] ~ [ wine-1.1.18 ] ~ [ wine-1.1.17 ] ~ [ wine-1.1.16 ] ~ [ wine-1.1.15 ] ~ [ wine-1.1.14 ] ~ [ wine-1.1.13 ] ~ [ wine-1.1.12 ] ~ [ wine-1.1.11 ] ~ [ wine-1.1.10 ] ~ [ wine-1.1.9 ] ~ [ wine-1.1.8 ] ~ [ wine-1.1.7 ] ~ [ wine-1.0.1 ] ~ [ wine-1.1.6 ] ~ [ wine-1.1.5 ] ~ [ wine-1.1.4 ] ~ [ wine-1.1.3 ] ~ [ wine-1.1.2 ] ~ [ wine-1.1.1 ] ~ [ wine-1.1.0 ] ~ [ wine-1.0 ] ~

  1 /*
  2  * Copyright 2010 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 #include <stdarg.h>
 23 #ifdef HAVE_UNISTD_H
 24 #include <unistd.h>
 25 #endif
 26 #ifdef HAVE_TIFFIO_H
 27 #include <tiffio.h>
 28 #endif
 29 
 30 #define COBJMACROS
 31 
 32 #include "windef.h"
 33 #include "winbase.h"
 34 #include "objbase.h"
 35 #include "wincodec.h"
 36 
 37 #include "wincodecs_private.h"
 38 
 39 #include "wine/debug.h"
 40 #include "wine/library.h"
 41 
 42 WINE_DEFAULT_DEBUG_CHANNEL(wincodecs);
 43 
 44 #ifdef SONAME_LIBTIFF
 45 
 46 static CRITICAL_SECTION init_tiff_cs;
 47 static CRITICAL_SECTION_DEBUG init_tiff_cs_debug =
 48 {
 49     0, 0, &init_tiff_cs,
 50     { &init_tiff_cs_debug.ProcessLocksList,
 51       &init_tiff_cs_debug.ProcessLocksList },
 52     0, 0, { (DWORD_PTR)(__FILE__ ": init_tiff_cs") }
 53 };
 54 static CRITICAL_SECTION init_tiff_cs = { &init_tiff_cs_debug, -1, 0, 0, 0, 0 };
 55 
 56 static void *libtiff_handle;
 57 #define MAKE_FUNCPTR(f) static typeof(f) * p##f
 58 MAKE_FUNCPTR(TIFFClientOpen);
 59 MAKE_FUNCPTR(TIFFClose);
 60 MAKE_FUNCPTR(TIFFCurrentDirectory);
 61 MAKE_FUNCPTR(TIFFGetField);
 62 MAKE_FUNCPTR(TIFFReadDirectory);
 63 MAKE_FUNCPTR(TIFFReadEncodedStrip);
 64 MAKE_FUNCPTR(TIFFSetDirectory);
 65 #undef MAKE_FUNCPTR
 66 
 67 static void *load_libtiff(void)
 68 {
 69     void *result;
 70 
 71     EnterCriticalSection(&init_tiff_cs);
 72 
 73     if (!libtiff_handle &&
 74         (libtiff_handle = wine_dlopen(SONAME_LIBTIFF, RTLD_NOW, NULL, 0)) != NULL)
 75     {
 76 
 77 #define LOAD_FUNCPTR(f) \
 78     if((p##f = wine_dlsym(libtiff_handle, #f, NULL, 0)) == NULL) { \
 79         ERR("failed to load symbol %s\n", #f); \
 80         libtiff_handle = NULL; \
 81         LeaveCriticalSection(&init_tiff_cs); \
 82         return NULL; \
 83     }
 84         LOAD_FUNCPTR(TIFFClientOpen);
 85         LOAD_FUNCPTR(TIFFClose);
 86         LOAD_FUNCPTR(TIFFCurrentDirectory);
 87         LOAD_FUNCPTR(TIFFGetField);
 88         LOAD_FUNCPTR(TIFFReadDirectory);
 89         LOAD_FUNCPTR(TIFFReadEncodedStrip);
 90         LOAD_FUNCPTR(TIFFSetDirectory);
 91 #undef LOAD_FUNCPTR
 92 
 93     }
 94 
 95     result = libtiff_handle;
 96 
 97     LeaveCriticalSection(&init_tiff_cs);
 98     return result;
 99 }
100 
101 static tsize_t tiff_stream_read(thandle_t client_data, tdata_t data, tsize_t size)
102 {
103     IStream *stream = (IStream*)client_data;
104     ULONG bytes_read;
105     HRESULT hr;
106 
107     hr = IStream_Read(stream, data, size, &bytes_read);
108     if (FAILED(hr)) bytes_read = 0;
109     return bytes_read;
110 }
111 
112 static tsize_t tiff_stream_write(thandle_t client_data, tdata_t data, tsize_t size)
113 {
114     IStream *stream = (IStream*)client_data;
115     ULONG bytes_written;
116     HRESULT hr;
117 
118     hr = IStream_Write(stream, data, size, &bytes_written);
119     if (FAILED(hr)) bytes_written = 0;
120     return bytes_written;
121 }
122 
123 static toff_t tiff_stream_seek(thandle_t client_data, toff_t offset, int whence)
124 {
125     IStream *stream = (IStream*)client_data;
126     LARGE_INTEGER move;
127     DWORD origin;
128     ULARGE_INTEGER new_position;
129     HRESULT hr;
130 
131     move.QuadPart = offset;
132     switch (whence)
133     {
134         case SEEK_SET:
135             origin = STREAM_SEEK_SET;
136             break;
137         case SEEK_CUR:
138             origin = STREAM_SEEK_CUR;
139             break;
140         case SEEK_END:
141             origin = STREAM_SEEK_END;
142             break;
143         default:
144             ERR("unknown whence value %i\n", whence);
145             return -1;
146     }
147 
148     hr = IStream_Seek(stream, move, origin, &new_position);
149     if (SUCCEEDED(hr)) return new_position.QuadPart;
150     else return -1;
151 }
152 
153 static int tiff_stream_close(thandle_t client_data)
154 {
155     /* Caller is responsible for releasing the stream object. */
156     return 0;
157 }
158 
159 static toff_t tiff_stream_size(thandle_t client_data)
160 {
161     IStream *stream = (IStream*)client_data;
162     STATSTG statstg;
163     HRESULT hr;
164 
165     hr = IStream_Stat(stream, &statstg, STATFLAG_NONAME);
166 
167     if (SUCCEEDED(hr)) return statstg.cbSize.QuadPart;
168     else return -1;
169 }
170 
171 static int tiff_stream_map(thandle_t client_data, tdata_t *addr, toff_t *size)
172 {
173     /* Cannot mmap streams */
174     return 0;
175 }
176 
177 static void tiff_stream_unmap(thandle_t client_data, tdata_t addr, toff_t size)
178 {
179     /* No need to ever do this, since we can't map things. */
180 }
181 
182 static TIFF* tiff_open_stream(IStream *stream, const char *mode)
183 {
184     return pTIFFClientOpen("<IStream object>", mode, stream, tiff_stream_read,
185         tiff_stream_write, tiff_stream_seek, tiff_stream_close,
186         tiff_stream_size, tiff_stream_map, tiff_stream_unmap);
187 }
188 
189 typedef struct {
190     const IWICBitmapDecoderVtbl *lpVtbl;
191     LONG ref;
192     IStream *stream;
193     CRITICAL_SECTION lock; /* Must be held when tiff is used or initiailzed is set */
194     TIFF *tiff;
195     BOOL initialized;
196 } TiffDecoder;
197 
198 typedef struct {
199     const WICPixelFormatGUID *format;
200     int bpp;
201     int indexed;
202     int reverse_bgr;
203     UINT width, height;
204     UINT tile_width, tile_height;
205     UINT tile_stride;
206     UINT tile_size;
207 } tiff_decode_info;
208 
209 typedef struct {
210     const IWICBitmapFrameDecodeVtbl *lpVtbl;
211     LONG ref;
212     TiffDecoder *parent;
213     UINT index;
214     tiff_decode_info decode_info;
215     INT cached_tile_x, cached_tile_y;
216     BYTE *cached_tile;
217 } TiffFrameDecode;
218 
219 static const IWICBitmapFrameDecodeVtbl TiffFrameDecode_Vtbl;
220 
221 static HRESULT tiff_get_decode_info(TIFF *tiff, tiff_decode_info *decode_info)
222 {
223     uint16 photometric, bps, samples, planar;
224     int ret;
225 
226     decode_info->indexed = 0;
227     decode_info->reverse_bgr = 0;
228 
229     ret = pTIFFGetField(tiff, TIFFTAG_PHOTOMETRIC, &photometric);
230     if (!ret)
231     {
232         WARN("missing PhotometricInterpretation tag\n");
233         return E_FAIL;
234     }
235 
236     ret = pTIFFGetField(tiff, TIFFTAG_BITSPERSAMPLE, &bps);
237     if (!ret) bps = 1;
238 
239     switch(photometric)
240     {
241     case 1: /* BlackIsZero */
242         decode_info->bpp = bps;
243         switch (bps)
244         {
245         case 1:
246             decode_info->format = &GUID_WICPixelFormatBlackWhite;
247             break;
248         case 4:
249             decode_info->format = &GUID_WICPixelFormat4bppGray;
250             break;
251         case 8:
252             decode_info->format = &GUID_WICPixelFormat8bppGray;
253             break;
254         default:
255             FIXME("unhandled greyscale bit count %u\n", bps);
256             return E_FAIL;
257         }
258         break;
259     case 2: /* RGB */
260         if (bps != 8)
261         {
262             FIXME("unhandled RGB bit count %u\n", bps);
263             return E_FAIL;
264         }
265         ret = pTIFFGetField(tiff, TIFFTAG_SAMPLESPERPIXEL, &samples);
266         if (samples != 3)
267         {
268             FIXME("unhandled RGB sample count %u\n", samples);
269             return E_FAIL;
270         }
271         ret = pTIFFGetField(tiff, TIFFTAG_PLANARCONFIG, &planar);
272         if (!ret) planar = 1;
273         if (planar != 1)
274         {
275             FIXME("unhandled planar configuration %u\n", planar);
276             return E_FAIL;
277         }
278         decode_info->bpp = bps * samples;
279         decode_info->reverse_bgr = 1;
280         decode_info->format = &GUID_WICPixelFormat24bppBGR;
281         break;
282     case 3: /* RGB Palette */
283         decode_info->indexed = 1;
284         decode_info->bpp = bps;
285         switch (bps)
286         {
287         case 4:
288             decode_info->format = &GUID_WICPixelFormat4bppIndexed;
289             break;
290         case 8:
291             decode_info->format = &GUID_WICPixelFormat8bppIndexed;
292             break;
293         default:
294             FIXME("unhandled indexed bit count %u\n", bps);
295             return E_FAIL;
296         }
297         break;
298     case 0: /* WhiteIsZero */
299     case 4: /* Transparency mask */
300     case 5: /* CMYK */
301     case 6: /* YCbCr */
302     case 8: /* CIELab */
303     default:
304         FIXME("unhandled PhotometricInterpretation %u\n", photometric);
305         return E_FAIL;
306     }
307 
308     ret = pTIFFGetField(tiff, TIFFTAG_IMAGEWIDTH, &decode_info->width);
309     if (!ret)
310     {
311         WARN("missing image width\n");
312         return E_FAIL;
313     }
314 
315     ret = pTIFFGetField(tiff, TIFFTAG_IMAGELENGTH, &decode_info->height);
316     if (!ret)
317     {
318         WARN("missing image length\n");
319         return E_FAIL;
320     }
321 
322     ret = pTIFFGetField(tiff, TIFFTAG_ROWSPERSTRIP, &decode_info->tile_height);
323     if (ret)
324     {
325         decode_info->tile_width = decode_info->width;
326         decode_info->tile_stride = ((decode_info->bpp * decode_info->tile_width + 7)/8);
327         decode_info->tile_size = decode_info->tile_height * decode_info->tile_stride;
328     }
329     else
330     {
331         /* Probably a tiled image */
332         FIXME("missing RowsPerStrip value\n");
333         return E_FAIL;
334     }
335 
336     return S_OK;
337 }
338 
339 static HRESULT WINAPI TiffDecoder_QueryInterface(IWICBitmapDecoder *iface, REFIID iid,
340     void **ppv)
341 {
342     TiffDecoder *This = (TiffDecoder*)iface;
343     TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
344 
345     if (!ppv) return E_INVALIDARG;
346 
347     if (IsEqualIID(&IID_IUnknown, iid) || IsEqualIID(&IID_IWICBitmapDecoder, iid))
348     {
349         *ppv = This;
350     }
351     else
352     {
353         *ppv = NULL;
354         return E_NOINTERFACE;
355     }
356 
357     IUnknown_AddRef((IUnknown*)*ppv);
358     return S_OK;
359 }
360 
361 static ULONG WINAPI TiffDecoder_AddRef(IWICBitmapDecoder *iface)
362 {
363     TiffDecoder *This = (TiffDecoder*)iface;
364     ULONG ref = InterlockedIncrement(&This->ref);
365 
366     TRACE("(%p) refcount=%u\n", iface, ref);
367 
368     return ref;
369 }
370 
371 static ULONG WINAPI TiffDecoder_Release(IWICBitmapDecoder *iface)
372 {
373     TiffDecoder *This = (TiffDecoder*)iface;
374     ULONG ref = InterlockedDecrement(&This->ref);
375 
376     TRACE("(%p) refcount=%u\n", iface, ref);
377 
378     if (ref == 0)
379     {
380         if (This->tiff) pTIFFClose(This->tiff);
381         if (This->stream) IStream_Release(This->stream);
382         This->lock.DebugInfo->Spare[0] = 0;
383         DeleteCriticalSection(&This->lock);
384         HeapFree(GetProcessHeap(), 0, This);
385     }
386 
387     return ref;
388 }
389 
390 static HRESULT WINAPI TiffDecoder_QueryCapability(IWICBitmapDecoder *iface, IStream *pIStream,
391     DWORD *pdwCapability)
392 {
393     FIXME("(%p,%p,%p): stub\n", iface, pIStream, pdwCapability);
394     return E_NOTIMPL;
395 }
396 
397 static HRESULT WINAPI TiffDecoder_Initialize(IWICBitmapDecoder *iface, IStream *pIStream,
398     WICDecodeOptions cacheOptions)
399 {
400     TiffDecoder *This = (TiffDecoder*)iface;
401     TIFF *tiff;
402     HRESULT hr=S_OK;
403 
404     TRACE("(%p,%p,%x): stub\n", iface, pIStream, cacheOptions);
405 
406     EnterCriticalSection(&This->lock);
407 
408     if (This->initialized)
409     {
410         hr = WINCODEC_ERR_WRONGSTATE;
411         goto exit;
412     }
413 
414     tiff = tiff_open_stream(pIStream, "r");
415 
416     if (!tiff)
417     {
418         hr = E_FAIL;
419         goto exit;
420     }
421 
422     This->tiff = tiff;
423     This->stream = pIStream;
424     IStream_AddRef(pIStream);
425     This->initialized = TRUE;
426 
427 exit:
428     LeaveCriticalSection(&This->lock);
429     return hr;
430 }
431 
432 static HRESULT WINAPI TiffDecoder_GetContainerFormat(IWICBitmapDecoder *iface,
433     GUID *pguidContainerFormat)
434 {
435     memcpy(pguidContainerFormat, &GUID_ContainerFormatTiff, sizeof(GUID));
436     return S_OK;
437 }
438 
439 static HRESULT WINAPI TiffDecoder_GetDecoderInfo(IWICBitmapDecoder *iface,
440     IWICBitmapDecoderInfo **ppIDecoderInfo)
441 {
442     FIXME("(%p,%p): stub\n", iface, ppIDecoderInfo);
443     return E_NOTIMPL;
444 }
445 
446 static HRESULT WINAPI TiffDecoder_CopyPalette(IWICBitmapDecoder *iface,
447     IWICPalette *pIPalette)
448 {
449     FIXME("(%p,%p): stub\n", iface, pIPalette);
450     return E_NOTIMPL;
451 }
452 
453 static HRESULT WINAPI TiffDecoder_GetMetadataQueryReader(IWICBitmapDecoder *iface,
454     IWICMetadataQueryReader **ppIMetadataQueryReader)
455 {
456     FIXME("(%p,%p): stub\n", iface, ppIMetadataQueryReader);
457     return E_NOTIMPL;
458 }
459 
460 static HRESULT WINAPI TiffDecoder_GetPreview(IWICBitmapDecoder *iface,
461     IWICBitmapSource **ppIBitmapSource)
462 {
463     FIXME("(%p,%p): stub\n", iface, ppIBitmapSource);
464     return E_NOTIMPL;
465 }
466 
467 static HRESULT WINAPI TiffDecoder_GetColorContexts(IWICBitmapDecoder *iface,
468     UINT cCount, IWICColorContext **ppIColorContexts, UINT *pcActualCount)
469 {
470     FIXME("(%p,%u,%p,%p)\n", iface, cCount, ppIColorContexts, pcActualCount);
471     return E_NOTIMPL;
472 }
473 
474 static HRESULT WINAPI TiffDecoder_GetThumbnail(IWICBitmapDecoder *iface,
475     IWICBitmapSource **ppIThumbnail)
476 {
477     TRACE("(%p,%p)\n", iface, ppIThumbnail);
478     return WINCODEC_ERR_CODECNOTHUMBNAIL;
479 }
480 
481 static HRESULT WINAPI TiffDecoder_GetFrameCount(IWICBitmapDecoder *iface,
482     UINT *pCount)
483 {
484     TiffDecoder *This = (TiffDecoder*)iface;
485 
486     if (!This->tiff)
487     {
488         WARN("(%p) <-- WINCODEC_ERR_WRONGSTATE\n", iface);
489         return WINCODEC_ERR_WRONGSTATE;
490     }
491 
492     EnterCriticalSection(&This->lock);
493     while (pTIFFReadDirectory(This->tiff)) { }
494     *pCount = pTIFFCurrentDirectory(This->tiff)+1;
495     LeaveCriticalSection(&This->lock);
496 
497     TRACE("(%p) <-- %i\n", iface, *pCount);
498 
499     return S_OK;
500 }
501 
502 static HRESULT WINAPI TiffDecoder_GetFrame(IWICBitmapDecoder *iface,
503     UINT index, IWICBitmapFrameDecode **ppIBitmapFrame)
504 {
505     TiffDecoder *This = (TiffDecoder*)iface;
506     TiffFrameDecode *result;
507     int res;
508     tiff_decode_info decode_info;
509     HRESULT hr;
510 
511     TRACE("(%p,%u,%p)\n", iface, index, ppIBitmapFrame);
512 
513     if (!This->tiff)
514         return WINCODEC_ERR_WRONGSTATE;
515 
516     EnterCriticalSection(&This->lock);
517     res = pTIFFSetDirectory(This->tiff, index);
518     if (!res) hr = E_INVALIDARG;
519     else hr = tiff_get_decode_info(This->tiff, &decode_info);
520     LeaveCriticalSection(&This->lock);
521 
522     if (SUCCEEDED(hr))
523     {
524         result = HeapAlloc(GetProcessHeap(), 0, sizeof(TiffFrameDecode));
525 
526         if (result)
527         {
528             result->lpVtbl = &TiffFrameDecode_Vtbl;
529             result->ref = 1;
530             result->parent = This;
531             result->index = index;
532             result->decode_info = decode_info;
533             result->cached_tile_x = -1;
534             result->cached_tile = HeapAlloc(GetProcessHeap(), 0, decode_info.tile_size);
535 
536             if (result->cached_tile)
537                 *ppIBitmapFrame = (IWICBitmapFrameDecode*)result;
538             else
539             {
540                 hr = E_OUTOFMEMORY;
541                 HeapFree(GetProcessHeap(), 0, result);
542             }
543         }
544         else hr = E_OUTOFMEMORY;
545     }
546 
547     if (FAILED(hr)) *ppIBitmapFrame = NULL;
548 
549     return hr;
550 }
551 
552 static const IWICBitmapDecoderVtbl TiffDecoder_Vtbl = {
553     TiffDecoder_QueryInterface,
554     TiffDecoder_AddRef,
555     TiffDecoder_Release,
556     TiffDecoder_QueryCapability,
557     TiffDecoder_Initialize,
558     TiffDecoder_GetContainerFormat,
559     TiffDecoder_GetDecoderInfo,
560     TiffDecoder_CopyPalette,
561     TiffDecoder_GetMetadataQueryReader,
562     TiffDecoder_GetPreview,
563     TiffDecoder_GetColorContexts,
564     TiffDecoder_GetThumbnail,
565     TiffDecoder_GetFrameCount,
566     TiffDecoder_GetFrame
567 };
568 
569 static HRESULT WINAPI TiffFrameDecode_QueryInterface(IWICBitmapFrameDecode *iface, REFIID iid,
570     void **ppv)
571 {
572     TiffFrameDecode *This = (TiffFrameDecode*)iface;
573     TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
574 
575     if (!ppv) return E_INVALIDARG;
576 
577     if (IsEqualIID(&IID_IUnknown, iid) ||
578         IsEqualIID(&IID_IWICBitmapSource, iid) ||
579         IsEqualIID(&IID_IWICBitmapFrameDecode, iid))
580     {
581         *ppv = This;
582     }
583     else
584     {
585         *ppv = NULL;
586         return E_NOINTERFACE;
587     }
588 
589     IUnknown_AddRef((IUnknown*)*ppv);
590     return S_OK;
591 }
592 
593 static ULONG WINAPI TiffFrameDecode_AddRef(IWICBitmapFrameDecode *iface)
594 {
595     TiffFrameDecode *This = (TiffFrameDecode*)iface;
596     ULONG ref = InterlockedIncrement(&This->ref);
597 
598     TRACE("(%p) refcount=%u\n", iface, ref);
599 
600     return ref;
601 }
602 
603 static ULONG WINAPI TiffFrameDecode_Release(IWICBitmapFrameDecode *iface)
604 {
605     TiffFrameDecode *This = (TiffFrameDecode*)iface;
606     ULONG ref = InterlockedDecrement(&This->ref);
607 
608     TRACE("(%p) refcount=%u\n", iface, ref);
609 
610     if (ref == 0)
611     {
612         HeapFree(GetProcessHeap(), 0, This->cached_tile);
613         HeapFree(GetProcessHeap(), 0, This);
614     }
615 
616     return ref;
617 }
618 
619 static HRESULT WINAPI TiffFrameDecode_GetSize(IWICBitmapFrameDecode *iface,
620     UINT *puiWidth, UINT *puiHeight)
621 {
622     TiffFrameDecode *This = (TiffFrameDecode*)iface;
623 
624     *puiWidth = This->decode_info.width;
625     *puiHeight = This->decode_info.height;
626 
627     TRACE("(%p) <-- %ux%u\n", iface, *puiWidth, *puiHeight);
628 
629     return S_OK;
630 }
631 
632 static HRESULT WINAPI TiffFrameDecode_GetPixelFormat(IWICBitmapFrameDecode *iface,
633     WICPixelFormatGUID *pPixelFormat)
634 {
635     TiffFrameDecode *This = (TiffFrameDecode*)iface;
636 
637     memcpy(pPixelFormat, This->decode_info.format, sizeof(GUID));
638 
639     TRACE("(%p) <-- %s\n", This, debugstr_guid(This->decode_info.format));
640 
641     return S_OK;
642 }
643 
644 static HRESULT WINAPI TiffFrameDecode_GetResolution(IWICBitmapFrameDecode *iface,
645     double *pDpiX, double *pDpiY)
646 {
647     FIXME("(%p,%p,%p)\n", iface, pDpiX, pDpiY);
648     return E_NOTIMPL;
649 }
650 
651 static HRESULT WINAPI TiffFrameDecode_CopyPalette(IWICBitmapFrameDecode *iface,
652     IWICPalette *pIPalette)
653 {
654     FIXME("(%p,%p)\n", iface, pIPalette);
655     return E_NOTIMPL;
656 }
657 
658 static HRESULT TiffFrameDecode_ReadTile(TiffFrameDecode *This, UINT tile_x, UINT tile_y)
659 {
660     HRESULT hr=S_OK;
661     tsize_t ret;
662 
663     ret = pTIFFSetDirectory(This->parent->tiff, This->index);
664 
665     if (ret == -1)
666         hr = E_FAIL;
667 
668     if (hr == S_OK)
669     {
670         ret = pTIFFReadEncodedStrip(This->parent->tiff, tile_y, This->cached_tile, This->decode_info.tile_size);
671 
672         if (ret == -1)
673             hr = E_FAIL;
674     }
675 
676     if (hr == S_OK && This->decode_info.reverse_bgr)
677     {
678         if (This->decode_info.format == &GUID_WICPixelFormat24bppBGR)
679         {
680             UINT i, total_pixels;
681             BYTE *pixel, temp;
682 
683             total_pixels = This->decode_info.tile_width * This->decode_info.tile_height;
684             pixel = This->cached_tile;
685             for (i=0; i<total_pixels; i++)
686             {
687                 temp = pixel[2];
688                 pixel[2] = pixel[0];
689                 pixel[0] = temp;
690                 pixel += 3;
691             }
692         }
693     }
694 
695     if (hr == S_OK)
696     {
697         This->cached_tile_x = tile_x;
698         This->cached_tile_y = tile_y;
699     }
700 
701     return hr;
702 }
703 
704 static HRESULT WINAPI TiffFrameDecode_CopyPixels(IWICBitmapFrameDecode *iface,
705     const WICRect *prc, UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer)
706 {
707     TiffFrameDecode *This = (TiffFrameDecode*)iface;
708     UINT min_tile_x, max_tile_x, min_tile_y, max_tile_y;
709     UINT tile_x, tile_y;
710     WICRect rc;
711     HRESULT hr=S_OK;
712     BYTE *dst_tilepos;
713     UINT bytesperrow;
714 
715     TRACE("(%p,%p,%u,%u,%p)\n", iface, prc, cbStride, cbBufferSize, pbBuffer);
716 
717     if (prc->X < 0 || prc->Y < 0 || prc->X+prc->Width > This->decode_info.width ||
718         prc->Y+prc->Height > This->decode_info.height)
719         return E_INVALIDARG;
720 
721     bytesperrow = ((This->decode_info.bpp * prc->Width)+7)/8;
722 
723     if (cbStride < bytesperrow)
724         return E_INVALIDARG;
725 
726     if ((cbStride * prc->Height) > cbBufferSize)
727         return E_INVALIDARG;
728 
729     min_tile_x = prc->X / This->decode_info.tile_width;
730     min_tile_y = prc->Y / This->decode_info.tile_height;
731     max_tile_x = (prc->X+prc->Width-1) / This->decode_info.tile_width;
732     max_tile_y = (prc->Y+prc->Height-1) / This->decode_info.tile_height;
733 
734     EnterCriticalSection(&This->parent->lock);
735 
736     for (tile_x=min_tile_x; tile_x <= max_tile_x; tile_x++)
737     {
738         for (tile_y=min_tile_y; tile_y <= max_tile_y; tile_y++)
739         {
740             if (tile_x != This->cached_tile_x || tile_y != This->cached_tile_y)
741             {
742                 hr = TiffFrameDecode_ReadTile(This, tile_x, tile_y);
743             }
744 
745             if (SUCCEEDED(hr))
746             {
747                 if (prc->X < tile_x * This->decode_info.tile_width)
748                     rc.X = 0;
749                 else
750                     rc.X = prc->X - tile_x * This->decode_info.tile_width;
751 
752                 if (prc->Y < tile_y * This->decode_info.tile_height)
753                     rc.Y = 0;
754                 else
755                     rc.Y = prc->Y - tile_y * This->decode_info.tile_height;
756 
757                 if (prc->X+prc->Width > (tile_x+1) * This->decode_info.tile_width)
758                     rc.Width = This->decode_info.tile_width - rc.X;
759                 else if (prc->X < tile_x * This->decode_info.tile_width)
760                     rc.Width = prc->Width + prc->X - tile_x * This->decode_info.tile_width;
761                 else
762                     rc.Width = prc->Width;
763 
764                 if (prc->Y+prc->Height > (tile_y+1) * This->decode_info.tile_height)
765                     rc.Height = This->decode_info.tile_height - rc.Y;
766                 else if (prc->Y < tile_y * This->decode_info.tile_height)
767                     rc.Height = prc->Height + prc->Y - tile_y * This->decode_info.tile_height;
768                 else
769                     rc.Height = prc->Height;
770 
771                 dst_tilepos = pbBuffer + (cbStride * ((rc.Y + tile_y * This->decode_info.tile_height) - prc->Y)) +
772                     ((This->decode_info.bpp * ((rc.X + tile_x * This->decode_info.tile_width) - prc->X) + 7) / 8);
773 
774                 hr = copy_pixels(This->decode_info.bpp, This->cached_tile,
775                     This->decode_info.tile_width, This->decode_info.tile_height, This->decode_info.tile_stride,
776                     &rc, cbStride, cbBufferSize, dst_tilepos);
777             }
778 
779             if (FAILED(hr))
780             {
781                 LeaveCriticalSection(&This->parent->lock);
782                 TRACE("<-- 0x%x\n", hr);
783                 return hr;
784             }
785         }
786     }
787 
788     LeaveCriticalSection(&This->parent->lock);
789 
790     return S_OK;
791 }
792 
793 static HRESULT WINAPI TiffFrameDecode_GetMetadataQueryReader(IWICBitmapFrameDecode *iface,
794     IWICMetadataQueryReader **ppIMetadataQueryReader)
795 {
796     FIXME("(%p,%p): stub\n", iface, ppIMetadataQueryReader);
797     return E_NOTIMPL;
798 }
799 
800 static HRESULT WINAPI TiffFrameDecode_GetColorContexts(IWICBitmapFrameDecode *iface,
801     UINT cCount, IWICColorContext **ppIColorContexts, UINT *pcActualCount)
802 {
803     FIXME("(%p,%u,%p,%p): stub\n", iface, cCount, ppIColorContexts, pcActualCount);
804     return E_NOTIMPL;
805 }
806 
807 static HRESULT WINAPI TiffFrameDecode_GetThumbnail(IWICBitmapFrameDecode *iface,
808     IWICBitmapSource **ppIThumbnail)
809 {
810     FIXME("(%p,%p): stub\n", iface, ppIThumbnail);
811     return E_NOTIMPL;
812 }
813 
814 static const IWICBitmapFrameDecodeVtbl TiffFrameDecode_Vtbl = {
815     TiffFrameDecode_QueryInterface,
816     TiffFrameDecode_AddRef,
817     TiffFrameDecode_Release,
818     TiffFrameDecode_GetSize,
819     TiffFrameDecode_GetPixelFormat,
820     TiffFrameDecode_GetResolution,
821     TiffFrameDecode_CopyPalette,
822     TiffFrameDecode_CopyPixels,
823     TiffFrameDecode_GetMetadataQueryReader,
824     TiffFrameDecode_GetColorContexts,
825     TiffFrameDecode_GetThumbnail
826 };
827 
828 HRESULT TiffDecoder_CreateInstance(IUnknown *pUnkOuter, REFIID iid, void** ppv)
829 {
830     HRESULT ret;
831     TiffDecoder *This;
832 
833     TRACE("(%p,%s,%p)\n", pUnkOuter, debugstr_guid(iid), ppv);
834 
835     *ppv = NULL;
836 
837     if (pUnkOuter) return CLASS_E_NOAGGREGATION;
838 
839     if (!load_libtiff())
840     {
841         ERR("Failed reading TIFF because unable to load %s\n",SONAME_LIBTIFF);
842         return E_FAIL;
843     }
844 
845     This = HeapAlloc(GetProcessHeap(), 0, sizeof(TiffDecoder));
846     if (!This) return E_OUTOFMEMORY;
847 
848     This->lpVtbl = &TiffDecoder_Vtbl;
849     This->ref = 1;
850     This->stream = NULL;
851     InitializeCriticalSection(&This->lock);
852     This->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": TiffDecoder.lock");
853     This->tiff = NULL;
854     This->initialized = FALSE;
855 
856     ret = IUnknown_QueryInterface((IUnknown*)This, iid, ppv);
857     IUnknown_Release((IUnknown*)This);
858 
859     return ret;
860 }
861 
862 #else /* !SONAME_LIBTIFF */
863 
864 HRESULT TiffDecoder_CreateInstance(IUnknown *pUnkOuter, REFIID iid, void** ppv)
865 {
866     ERR("Trying to load TIFF picture, but Wine was compiled without TIFF support.\n");
867     return E_FAIL;
868 }
869 
870 #endif
871 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.