ReactOS  0.4.15-dev-1200-gc3b3fcd
tiffformat.c
Go to the documentation of this file.
1 /*
2  * Copyright 2010 Vincent Povirk for CodeWeavers
3  * Copyright 2016 Dmitry Timoshkov
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18  */
19 
20 #include "config.h"
21 #include "wine/port.h"
22 
23 #include <stdarg.h>
24 #ifdef HAVE_UNISTD_H
25 #include <unistd.h>
26 #endif
27 #ifdef HAVE_TIFFIO_H
28 #include <tiffio.h>
29 #endif
30 
31 #define COBJMACROS
32 
33 #include "windef.h"
34 #include "winbase.h"
35 #include "objbase.h"
36 
37 #include "wincodecs_private.h"
38 
39 #include "wine/debug.h"
40 #include "wine/library.h"
41 
43 
44 #ifdef SONAME_LIBTIFF
45 
46 /* Workaround for broken libtiff 4.x headers on some 64-bit hosts which
47  * define TIFF_UINT64_T/toff_t as 32-bit for 32-bit builds, while they
48  * are supposed to be always 64-bit.
49  * TIFF_UINT64_T doesn't exist in libtiff 3.x, it was introduced in 4.x.
50  */
51 #ifdef TIFF_UINT64_T
52 # undef toff_t
53 # define toff_t UINT64
54 #endif
55 
56 static CRITICAL_SECTION init_tiff_cs;
57 static CRITICAL_SECTION_DEBUG init_tiff_cs_debug =
58 {
59  0, 0, &init_tiff_cs,
60  { &init_tiff_cs_debug.ProcessLocksList,
61  &init_tiff_cs_debug.ProcessLocksList },
62  0, 0, { (DWORD_PTR)(__FILE__ ": init_tiff_cs") }
63 };
64 static CRITICAL_SECTION init_tiff_cs = { &init_tiff_cs_debug, -1, 0, 0, 0, 0 };
65 
66 static const WCHAR wszTiffCompressionMethod[] = {'T','i','f','f','C','o','m','p','r','e','s','s','i','o','n','M','e','t','h','o','d',0};
67 static const WCHAR wszCompressionQuality[] = {'C','o','m','p','r','e','s','s','i','o','n','Q','u','a','l','i','t','y',0};
68 
69 static void *libtiff_handle;
70 #define MAKE_FUNCPTR(f) static typeof(f) * p##f
84 #undef MAKE_FUNCPTR
85 
86 static void *load_libtiff(void)
87 {
88  void *result;
89 
90  EnterCriticalSection(&init_tiff_cs);
91 
92  if (!libtiff_handle &&
93  (libtiff_handle = wine_dlopen(SONAME_LIBTIFF, RTLD_NOW, NULL, 0)) != NULL)
94  {
95  void * (*pTIFFSetWarningHandler)(void *);
96  void * (*pTIFFSetWarningHandlerExt)(void *);
97 
98 #define LOAD_FUNCPTR(f) \
99  if((p##f = wine_dlsym(libtiff_handle, #f, NULL, 0)) == NULL) { \
100  ERR("failed to load symbol %s\n", #f); \
101  libtiff_handle = NULL; \
102  LeaveCriticalSection(&init_tiff_cs); \
103  return NULL; \
104  }
118 #undef LOAD_FUNCPTR
119 
120  if ((pTIFFSetWarningHandler = wine_dlsym(libtiff_handle, "TIFFSetWarningHandler", NULL, 0)))
121  pTIFFSetWarningHandler(NULL);
122  if ((pTIFFSetWarningHandlerExt = wine_dlsym(libtiff_handle, "TIFFSetWarningHandlerExt", NULL, 0)))
123  pTIFFSetWarningHandlerExt(NULL);
124  }
125 
126  result = libtiff_handle;
127 
128  LeaveCriticalSection(&init_tiff_cs);
129  return result;
130 }
131 
132 static tsize_t tiff_stream_read(thandle_t client_data, tdata_t data, tsize_t size)
133 {
134  IStream *stream = (IStream*)client_data;
135  ULONG bytes_read;
136  HRESULT hr;
137 
138  hr = IStream_Read(stream, data, size, &bytes_read);
139  if (FAILED(hr)) bytes_read = 0;
140  return bytes_read;
141 }
142 
143 static tsize_t tiff_stream_write(thandle_t client_data, tdata_t data, tsize_t size)
144 {
145  IStream *stream = (IStream*)client_data;
146  ULONG bytes_written;
147  HRESULT hr;
148 
149  hr = IStream_Write(stream, data, size, &bytes_written);
150  if (FAILED(hr)) bytes_written = 0;
151  return bytes_written;
152 }
153 
154 static toff_t tiff_stream_seek(thandle_t client_data, toff_t offset, int whence)
155 {
156  IStream *stream = (IStream*)client_data;
157  LARGE_INTEGER move;
158  DWORD origin;
159  ULARGE_INTEGER new_position;
160  HRESULT hr;
161 
162  move.QuadPart = offset;
163  switch (whence)
164  {
165  case SEEK_SET:
166  origin = STREAM_SEEK_SET;
167  break;
168  case SEEK_CUR:
169  origin = STREAM_SEEK_CUR;
170  break;
171  case SEEK_END:
172  origin = STREAM_SEEK_END;
173  break;
174  default:
175  ERR("unknown whence value %i\n", whence);
176  return -1;
177  }
178 
179  hr = IStream_Seek(stream, move, origin, &new_position);
180  if (SUCCEEDED(hr)) return new_position.QuadPart;
181  else return -1;
182 }
183 
184 static int tiff_stream_close(thandle_t client_data)
185 {
186  /* Caller is responsible for releasing the stream object. */
187  return 0;
188 }
189 
190 static toff_t tiff_stream_size(thandle_t client_data)
191 {
192  IStream *stream = (IStream*)client_data;
193  STATSTG statstg;
194  HRESULT hr;
195 
196  hr = IStream_Stat(stream, &statstg, STATFLAG_NONAME);
197 
198  if (SUCCEEDED(hr)) return statstg.cbSize.QuadPart;
199  else return -1;
200 }
201 
202 static int tiff_stream_map(thandle_t client_data, tdata_t *addr, toff_t *size)
203 {
204  /* Cannot mmap streams */
205  return 0;
206 }
207 
208 static void tiff_stream_unmap(thandle_t client_data, tdata_t addr, toff_t size)
209 {
210  /* No need to ever do this, since we can't map things. */
211 }
212 
213 static TIFF* tiff_open_stream(IStream *stream, const char *mode)
214 {
216 
217  zero.QuadPart = 0;
218  IStream_Seek(stream, zero, STREAM_SEEK_SET, NULL);
219 
220  return pTIFFClientOpen("<IStream object>", mode, stream, tiff_stream_read,
221  tiff_stream_write, (void *)tiff_stream_seek, tiff_stream_close,
222  (void *)tiff_stream_size, (void *)tiff_stream_map, (void *)tiff_stream_unmap);
223 }
224 
225 typedef struct {
226  IWICBitmapDecoder IWICBitmapDecoder_iface;
227  LONG ref;
228  IStream *stream;
229  CRITICAL_SECTION lock; /* Must be held when tiff is used or initialized is set */
230  TIFF *tiff;
232 } TiffDecoder;
233 
234 typedef struct {
235  const WICPixelFormatGUID *format;
236  int bps;
237  int samples;
238  int bpp, source_bpp;
239  int planar;
240  int indexed;
241  int reverse_bgr;
242  int invert_grayscale;
243  UINT width, height;
244  UINT tile_width, tile_height;
245  UINT tile_stride;
246  UINT tile_size;
247  int tiled;
248  UINT tiles_across;
249  UINT resolution_unit;
250  float xres, yres;
251 } tiff_decode_info;
252 
253 typedef struct {
254  IWICBitmapFrameDecode IWICBitmapFrameDecode_iface;
255  IWICMetadataBlockReader IWICMetadataBlockReader_iface;
256  LONG ref;
257  TiffDecoder *parent;
258  UINT index;
259  tiff_decode_info decode_info;
260  INT cached_tile_x, cached_tile_y;
261  BYTE *cached_tile;
262 } TiffFrameDecode;
263 
264 static const IWICBitmapFrameDecodeVtbl TiffFrameDecode_Vtbl;
265 static const IWICMetadataBlockReaderVtbl TiffFrameDecode_BlockVtbl;
266 
267 static inline TiffDecoder *impl_from_IWICBitmapDecoder(IWICBitmapDecoder *iface)
268 {
269  return CONTAINING_RECORD(iface, TiffDecoder, IWICBitmapDecoder_iface);
270 }
271 
272 static inline TiffFrameDecode *impl_from_IWICBitmapFrameDecode(IWICBitmapFrameDecode *iface)
273 {
274  return CONTAINING_RECORD(iface, TiffFrameDecode, IWICBitmapFrameDecode_iface);
275 }
276 
277 static inline TiffFrameDecode *impl_from_IWICMetadataBlockReader(IWICMetadataBlockReader *iface)
278 {
279  return CONTAINING_RECORD(iface, TiffFrameDecode, IWICMetadataBlockReader_iface);
280 }
281 
282 static HRESULT tiff_get_decode_info(TIFF *tiff, tiff_decode_info *decode_info)
283 {
284  uint16 photometric, bps, samples, planar;
285  uint16 extra_sample_count, extra_sample, *extra_samples;
286  int ret;
287 
288  decode_info->indexed = 0;
289  decode_info->reverse_bgr = 0;
290  decode_info->invert_grayscale = 0;
291  decode_info->tiled = 0;
292  decode_info->source_bpp = 0;
293 
294  ret = pTIFFGetField(tiff, TIFFTAG_PHOTOMETRIC, &photometric);
295  if (!ret)
296  {
297  WARN("missing PhotometricInterpretation tag\n");
298  return E_FAIL;
299  }
300 
301  ret = pTIFFGetField(tiff, TIFFTAG_BITSPERSAMPLE, &bps);
302  if (!ret) bps = 1;
303  decode_info->bps = bps;
304 
305  ret = pTIFFGetField(tiff, TIFFTAG_SAMPLESPERPIXEL, &samples);
306  if (!ret) samples = 1;
307  decode_info->samples = samples;
308 
309  if (samples == 1)
310  planar = 1;
311  else
312  {
313  ret = pTIFFGetField(tiff, TIFFTAG_PLANARCONFIG, &planar);
314  if (!ret) planar = 1;
315  if (planar != 1)
316  {
317  FIXME("unhandled planar configuration %u\n", planar);
318  return E_FAIL;
319  }
320  }
321  decode_info->planar = planar;
322 
323  TRACE("planar %u, photometric %u, samples %u, bps %u\n", planar, photometric, samples, bps);
324 
325  switch(photometric)
326  {
327  case 0: /* WhiteIsZero */
328  decode_info->invert_grayscale = 1;
329  /* fall through */
330  case 1: /* BlackIsZero */
331  if (samples == 2)
332  {
333  ret = pTIFFGetField(tiff, TIFFTAG_EXTRASAMPLES, &extra_sample_count, &extra_samples);
334  if (!ret)
335  {
336  extra_sample_count = 1;
337  extra_sample = 0;
338  extra_samples = &extra_sample;
339  }
340  }
341  else if (samples != 1)
342  {
343  FIXME("unhandled %dbpp sample count %u\n", bps, samples);
344  return E_FAIL;
345  }
346 
347  decode_info->bpp = bps * samples;
348  decode_info->source_bpp = decode_info->bpp;
349  switch (bps)
350  {
351  case 1:
352  if (samples != 1)
353  {
354  FIXME("unhandled 1bpp sample count %u\n", samples);
355  return E_FAIL;
356  }
357  decode_info->format = &GUID_WICPixelFormatBlackWhite;
358  break;
359  case 4:
360  if (samples != 1)
361  {
362  FIXME("unhandled 4bpp grayscale sample count %u\n", samples);
363  return E_FAIL;
364  }
365  decode_info->format = &GUID_WICPixelFormat4bppGray;
366  break;
367  case 8:
368  if (samples == 1)
369  decode_info->format = &GUID_WICPixelFormat8bppGray;
370  else
371  {
372  decode_info->bpp = 32;
373 
374  switch(extra_samples[0])
375  {
376  case 1: /* Associated (pre-multiplied) alpha data */
377  decode_info->format = &GUID_WICPixelFormat32bppPBGRA;
378  break;
379  case 0: /* Unspecified data */
380  case 2: /* Unassociated alpha data */
381  decode_info->format = &GUID_WICPixelFormat32bppBGRA;
382  break;
383  default:
384  FIXME("unhandled extra sample type %u\n", extra_samples[0]);
385  return E_FAIL;
386  }
387  }
388  break;
389  case 16:
390  if (samples != 1)
391  {
392  FIXME("unhandled 16bpp grayscale sample count %u\n", samples);
394  }
395  decode_info->format = &GUID_WICPixelFormat16bppGray;
396  break;
397  case 32:
398  if (samples != 1)
399  {
400  FIXME("unhandled 32bpp grayscale sample count %u\n", samples);
402  }
403  decode_info->format = &GUID_WICPixelFormat32bppGrayFloat;
404  break;
405  default:
406  WARN("unhandled greyscale bit count %u\n", bps);
408  }
409  break;
410  case 2: /* RGB */
411  if (samples == 4)
412  {
413  ret = pTIFFGetField(tiff, TIFFTAG_EXTRASAMPLES, &extra_sample_count, &extra_samples);
414  if (!ret)
415  {
416  extra_sample_count = 1;
417  extra_sample = 0;
418  extra_samples = &extra_sample;
419  }
420  }
421  else if (samples != 3)
422  {
423  FIXME("unhandled RGB sample count %u\n", samples);
424  return E_FAIL;
425  }
426 
427  decode_info->bpp = max(bps, 8) * samples;
428  decode_info->source_bpp = bps * samples;
429  switch(bps)
430  {
431  case 1:
432  case 4:
433  case 8:
434  decode_info->reverse_bgr = 1;
435  if (samples == 3)
436  decode_info->format = &GUID_WICPixelFormat24bppBGR;
437  else
438  switch(extra_samples[0])
439  {
440  case 1: /* Associated (pre-multiplied) alpha data */
441  decode_info->format = &GUID_WICPixelFormat32bppPBGRA;
442  break;
443  case 0: /* Unspecified data */
444  case 2: /* Unassociated alpha data */
445  decode_info->format = &GUID_WICPixelFormat32bppBGRA;
446  break;
447  default:
448  FIXME("unhandled extra sample type %i\n", extra_samples[0]);
449  return E_FAIL;
450  }
451  break;
452  case 16:
453  if (samples == 3)
454  decode_info->format = &GUID_WICPixelFormat48bppRGB;
455  else
456  switch(extra_samples[0])
457  {
458  case 1: /* Associated (pre-multiplied) alpha data */
459  decode_info->format = &GUID_WICPixelFormat64bppPRGBA;
460  break;
461  case 0: /* Unspecified data */
462  case 2: /* Unassociated alpha data */
463  decode_info->format = &GUID_WICPixelFormat64bppRGBA;
464  break;
465  default:
466  FIXME("unhandled extra sample type %i\n", extra_samples[0]);
467  return E_FAIL;
468  }
469  break;
470  case 32:
471  if (samples != 4)
472  {
473  FIXME("unhandled 32bpp RGB sample count %u\n", samples);
475  }
476  decode_info->format = &GUID_WICPixelFormat128bppRGBAFloat;
477  break;
478  default:
479  WARN("unhandled RGB bit count %u\n", bps);
481  }
482  break;
483  case 3: /* RGB Palette */
484  if (samples != 1)
485  {
486  FIXME("unhandled indexed sample count %u\n", samples);
487  return E_FAIL;
488  }
489 
490  decode_info->indexed = 1;
491  decode_info->bpp = bps;
492  switch (bps)
493  {
494  case 1:
495  decode_info->format = &GUID_WICPixelFormat1bppIndexed;
496  break;
497  case 2:
498  decode_info->format = &GUID_WICPixelFormat2bppIndexed;
499  break;
500  case 4:
501  decode_info->format = &GUID_WICPixelFormat4bppIndexed;
502  break;
503  case 8:
504  decode_info->format = &GUID_WICPixelFormat8bppIndexed;
505  break;
506  default:
507  FIXME("unhandled indexed bit count %u\n", bps);
508  return E_NOTIMPL;
509  }
510  break;
511 
512  case 5: /* Separated */
513  if (samples != 4)
514  {
515  FIXME("unhandled Separated sample count %u\n", samples);
516  return E_FAIL;
517  }
518 
519  decode_info->bpp = bps * samples;
520  switch(bps)
521  {
522  case 8:
523  decode_info->format = &GUID_WICPixelFormat32bppCMYK;
524  break;
525  case 16:
526  decode_info->format = &GUID_WICPixelFormat64bppCMYK;
527  break;
528 
529  default:
530  WARN("unhandled Separated bit count %u\n", bps);
532  }
533  break;
534 
535  case 4: /* Transparency mask */
536  case 6: /* YCbCr */
537  case 8: /* CIELab */
538  default:
539  FIXME("unhandled PhotometricInterpretation %u\n", photometric);
540  return E_FAIL;
541  }
542 
543  ret = pTIFFGetField(tiff, TIFFTAG_IMAGEWIDTH, &decode_info->width);
544  if (!ret)
545  {
546  WARN("missing image width\n");
547  return E_FAIL;
548  }
549 
550  ret = pTIFFGetField(tiff, TIFFTAG_IMAGELENGTH, &decode_info->height);
551  if (!ret)
552  {
553  WARN("missing image length\n");
554  return E_FAIL;
555  }
556 
557  if ((ret = pTIFFGetField(tiff, TIFFTAG_TILEWIDTH, &decode_info->tile_width)))
558  {
559  decode_info->tiled = 1;
560 
561  ret = pTIFFGetField(tiff, TIFFTAG_TILELENGTH, &decode_info->tile_height);
562  if (!ret)
563  {
564  WARN("missing tile height\n");
565  return E_FAIL;
566  }
567 
568  decode_info->tile_stride = ((decode_info->bpp * decode_info->tile_width + 7)/8);
569  decode_info->tile_size = decode_info->tile_height * decode_info->tile_stride;
570  decode_info->tiles_across = (decode_info->width + decode_info->tile_width - 1) / decode_info->tile_width;
571  }
572  else if ((ret = pTIFFGetField(tiff, TIFFTAG_ROWSPERSTRIP, &decode_info->tile_height)))
573  {
574  if (decode_info->tile_height > decode_info->height)
575  decode_info->tile_height = decode_info->height;
576  decode_info->tile_width = decode_info->width;
577  decode_info->tile_stride = ((decode_info->bpp * decode_info->tile_width + 7)/8);
578  decode_info->tile_size = decode_info->tile_height * decode_info->tile_stride;
579  }
580  else
581  {
582  /* Some broken TIFF files have a single strip and lack the RowsPerStrip tag */
583  decode_info->tile_height = decode_info->height;
584  decode_info->tile_width = decode_info->width;
585  decode_info->tile_stride = ((decode_info->bpp * decode_info->tile_width + 7)/8);
586  decode_info->tile_size = decode_info->tile_height * decode_info->tile_stride;
587  }
588 
589  decode_info->resolution_unit = 0;
590  pTIFFGetField(tiff, TIFFTAG_RESOLUTIONUNIT, &decode_info->resolution_unit);
591 
592  ret = pTIFFGetField(tiff, TIFFTAG_XRESOLUTION, &decode_info->xres);
593  if (!ret)
594  {
595  WARN("missing X resolution\n");
596  }
597  /* Emulate the behavior of current libtiff versions (libtiff commit a39f6131)
598  * yielding 0 instead of INFINITY for IFD_RATIONAL fields with denominator 0. */
599  if (!isfinite(decode_info->xres))
600  {
601  decode_info->xres = 0.0;
602  }
603 
604  ret = pTIFFGetField(tiff, TIFFTAG_YRESOLUTION, &decode_info->yres);
605  if (!ret)
606  {
607  WARN("missing Y resolution\n");
608  }
609  if (!isfinite(decode_info->yres))
610  {
611  decode_info->yres = 0.0;
612  }
613 
614  return S_OK;
615 }
616 
617 static HRESULT WINAPI TiffDecoder_QueryInterface(IWICBitmapDecoder *iface, REFIID iid,
618  void **ppv)
619 {
620  TiffDecoder *This = impl_from_IWICBitmapDecoder(iface);
621  TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
622 
623  if (!ppv) return E_INVALIDARG;
624 
625  if (IsEqualIID(&IID_IUnknown, iid) ||
626  IsEqualIID(&IID_IWICBitmapDecoder, iid))
627  {
628  *ppv = &This->IWICBitmapDecoder_iface;
629  }
630  else
631  {
632  *ppv = NULL;
633  return E_NOINTERFACE;
634  }
635 
636  IUnknown_AddRef((IUnknown*)*ppv);
637  return S_OK;
638 }
639 
640 static ULONG WINAPI TiffDecoder_AddRef(IWICBitmapDecoder *iface)
641 {
642  TiffDecoder *This = impl_from_IWICBitmapDecoder(iface);
644 
645  TRACE("(%p) refcount=%u\n", iface, ref);
646 
647  return ref;
648 }
649 
650 static ULONG WINAPI TiffDecoder_Release(IWICBitmapDecoder *iface)
651 {
652  TiffDecoder *This = impl_from_IWICBitmapDecoder(iface);
654 
655  TRACE("(%p) refcount=%u\n", iface, ref);
656 
657  if (ref == 0)
658  {
659  if (This->tiff) pTIFFClose(This->tiff);
660  if (This->stream) IStream_Release(This->stream);
661  This->lock.DebugInfo->Spare[0] = 0;
662  DeleteCriticalSection(&This->lock);
664  }
665 
666  return ref;
667 }
668 
669 static HRESULT WINAPI TiffDecoder_QueryCapability(IWICBitmapDecoder *iface, IStream *stream,
670  DWORD *capability)
671 {
672  HRESULT hr;
673 
674  TRACE("(%p,%p,%p)\n", iface, stream, capability);
675 
676  if (!stream || !capability) return E_INVALIDARG;
677 
678  hr = IWICBitmapDecoder_Initialize(iface, stream, WICDecodeMetadataCacheOnDemand);
679  if (hr != S_OK) return hr;
680 
684  return S_OK;
685 }
686 
687 static HRESULT WINAPI TiffDecoder_Initialize(IWICBitmapDecoder *iface, IStream *pIStream,
688  WICDecodeOptions cacheOptions)
689 {
690  TiffDecoder *This = impl_from_IWICBitmapDecoder(iface);
691  TIFF *tiff;
692  tiff_decode_info decode_info;
693  HRESULT hr=S_OK;
694 
695  TRACE("(%p,%p,%x)\n", iface, pIStream, cacheOptions);
696 
697  EnterCriticalSection(&This->lock);
698 
699  if (This->initialized)
700  {
702  goto exit;
703  }
704 
705  tiff = tiff_open_stream(pIStream, "r");
706  if (!tiff)
707  {
708  hr = E_FAIL;
709  goto exit;
710  }
711 
712  /* make sure that TIFF format is supported */
713  hr = tiff_get_decode_info(tiff, &decode_info);
714  if (hr != S_OK)
715  {
716  pTIFFClose(tiff);
717  goto exit;
718  }
719 
720  This->tiff = tiff;
721  This->stream = pIStream;
722  IStream_AddRef(pIStream);
723  This->initialized = TRUE;
724 
725 exit:
726  LeaveCriticalSection(&This->lock);
727  return hr;
728 }
729 
730 static HRESULT WINAPI TiffDecoder_GetContainerFormat(IWICBitmapDecoder *iface,
731  GUID *pguidContainerFormat)
732 {
733  if (!pguidContainerFormat) return E_INVALIDARG;
734 
735  memcpy(pguidContainerFormat, &GUID_ContainerFormatTiff, sizeof(GUID));
736  return S_OK;
737 }
738 
739 static HRESULT WINAPI TiffDecoder_GetDecoderInfo(IWICBitmapDecoder *iface,
740  IWICBitmapDecoderInfo **ppIDecoderInfo)
741 {
742  TRACE("(%p,%p)\n", iface, ppIDecoderInfo);
743 
744  return get_decoder_info(&CLSID_WICTiffDecoder, ppIDecoderInfo);
745 }
746 
747 static HRESULT WINAPI TiffDecoder_CopyPalette(IWICBitmapDecoder *iface,
749 {
750  TRACE("(%p,%p)\n", iface, palette);
752 }
753 
754 static HRESULT WINAPI TiffDecoder_GetMetadataQueryReader(IWICBitmapDecoder *iface,
755  IWICMetadataQueryReader **ppIMetadataQueryReader)
756 {
757  TRACE("(%p,%p)\n", iface, ppIMetadataQueryReader);
758 
759  if (!ppIMetadataQueryReader) return E_INVALIDARG;
760 
761  *ppIMetadataQueryReader = NULL;
763 }
764 
765 static HRESULT WINAPI TiffDecoder_GetPreview(IWICBitmapDecoder *iface,
766  IWICBitmapSource **ppIBitmapSource)
767 {
768  TRACE("(%p,%p)\n", iface, ppIBitmapSource);
769 
770  if (!ppIBitmapSource) return E_INVALIDARG;
771 
772  *ppIBitmapSource = NULL;
774 }
775 
776 static HRESULT WINAPI TiffDecoder_GetColorContexts(IWICBitmapDecoder *iface,
777  UINT cCount, IWICColorContext **ppIColorContexts, UINT *pcActualCount)
778 {
779  FIXME("(%p,%u,%p,%p)\n", iface, cCount, ppIColorContexts, pcActualCount);
781 }
782 
783 static HRESULT WINAPI TiffDecoder_GetThumbnail(IWICBitmapDecoder *iface,
784  IWICBitmapSource **ppIThumbnail)
785 {
786  TRACE("(%p,%p)\n", iface, ppIThumbnail);
787 
788  if (!ppIThumbnail) return E_INVALIDARG;
789 
790  *ppIThumbnail = NULL;
792 }
793 
794 static HRESULT WINAPI TiffDecoder_GetFrameCount(IWICBitmapDecoder *iface,
795  UINT *pCount)
796 {
797  TiffDecoder *This = impl_from_IWICBitmapDecoder(iface);
798 
799  if (!pCount) return E_INVALIDARG;
800 
801  EnterCriticalSection(&This->lock);
802  *pCount = This->tiff ? pTIFFNumberOfDirectories(This->tiff) : 0;
803  LeaveCriticalSection(&This->lock);
804 
805  TRACE("(%p) <-- %i\n", iface, *pCount);
806 
807  return S_OK;
808 }
809 
810 static HRESULT WINAPI TiffDecoder_GetFrame(IWICBitmapDecoder *iface,
811  UINT index, IWICBitmapFrameDecode **ppIBitmapFrame)
812 {
813  TiffDecoder *This = impl_from_IWICBitmapDecoder(iface);
814  TiffFrameDecode *result;
815  int res;
816  tiff_decode_info decode_info;
817  HRESULT hr;
818 
819  TRACE("(%p,%u,%p)\n", iface, index, ppIBitmapFrame);
820 
821  if (!This->tiff)
823 
824  EnterCriticalSection(&This->lock);
825  res = pTIFFSetDirectory(This->tiff, index);
826  if (!res) hr = E_INVALIDARG;
827  else hr = tiff_get_decode_info(This->tiff, &decode_info);
828  LeaveCriticalSection(&This->lock);
829 
830  if (SUCCEEDED(hr))
831  {
832  result = HeapAlloc(GetProcessHeap(), 0, sizeof(TiffFrameDecode));
833 
834  if (result)
835  {
836  result->IWICBitmapFrameDecode_iface.lpVtbl = &TiffFrameDecode_Vtbl;
837  result->IWICMetadataBlockReader_iface.lpVtbl = &TiffFrameDecode_BlockVtbl;
838  result->ref = 1;
839  result->parent = This;
840  IWICBitmapDecoder_AddRef(iface);
841  result->index = index;
842  result->decode_info = decode_info;
843  result->cached_tile_x = -1;
844  result->cached_tile = HeapAlloc(GetProcessHeap(), 0, decode_info.tile_size);
845 
846  if (result->cached_tile)
847  *ppIBitmapFrame = &result->IWICBitmapFrameDecode_iface;
848  else
849  {
850  hr = E_OUTOFMEMORY;
851  IWICBitmapFrameDecode_Release(&result->IWICBitmapFrameDecode_iface);
852  }
853  }
854  else hr = E_OUTOFMEMORY;
855  }
856 
857  if (FAILED(hr)) *ppIBitmapFrame = NULL;
858 
859  return hr;
860 }
861 
862 static const IWICBitmapDecoderVtbl TiffDecoder_Vtbl = {
863  TiffDecoder_QueryInterface,
864  TiffDecoder_AddRef,
865  TiffDecoder_Release,
866  TiffDecoder_QueryCapability,
867  TiffDecoder_Initialize,
868  TiffDecoder_GetContainerFormat,
869  TiffDecoder_GetDecoderInfo,
870  TiffDecoder_CopyPalette,
871  TiffDecoder_GetMetadataQueryReader,
872  TiffDecoder_GetPreview,
873  TiffDecoder_GetColorContexts,
874  TiffDecoder_GetThumbnail,
875  TiffDecoder_GetFrameCount,
876  TiffDecoder_GetFrame
877 };
878 
879 static HRESULT WINAPI TiffFrameDecode_QueryInterface(IWICBitmapFrameDecode *iface, REFIID iid,
880  void **ppv)
881 {
882  TiffFrameDecode *This = impl_from_IWICBitmapFrameDecode(iface);
883  TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
884 
885  if (!ppv) return E_INVALIDARG;
886 
887  if (IsEqualIID(&IID_IUnknown, iid) ||
888  IsEqualIID(&IID_IWICBitmapSource, iid) ||
889  IsEqualIID(&IID_IWICBitmapFrameDecode, iid))
890  {
891  *ppv = &This->IWICBitmapFrameDecode_iface;
892  }
893  else if (IsEqualIID(&IID_IWICMetadataBlockReader, iid))
894  {
895  *ppv = &This->IWICMetadataBlockReader_iface;
896  }
897  else
898  {
899  *ppv = NULL;
900  return E_NOINTERFACE;
901  }
902 
903  IUnknown_AddRef((IUnknown*)*ppv);
904  return S_OK;
905 }
906 
907 static ULONG WINAPI TiffFrameDecode_AddRef(IWICBitmapFrameDecode *iface)
908 {
909  TiffFrameDecode *This = impl_from_IWICBitmapFrameDecode(iface);
911 
912  TRACE("(%p) refcount=%u\n", iface, ref);
913 
914  return ref;
915 }
916 
917 static ULONG WINAPI TiffFrameDecode_Release(IWICBitmapFrameDecode *iface)
918 {
919  TiffFrameDecode *This = impl_from_IWICBitmapFrameDecode(iface);
921 
922  TRACE("(%p) refcount=%u\n", iface, ref);
923 
924  if (ref == 0)
925  {
926  IWICBitmapDecoder_Release(&This->parent->IWICBitmapDecoder_iface);
927  HeapFree(GetProcessHeap(), 0, This->cached_tile);
929  }
930 
931  return ref;
932 }
933 
934 static HRESULT WINAPI TiffFrameDecode_GetSize(IWICBitmapFrameDecode *iface,
935  UINT *puiWidth, UINT *puiHeight)
936 {
937  TiffFrameDecode *This = impl_from_IWICBitmapFrameDecode(iface);
938 
939  *puiWidth = This->decode_info.width;
940  *puiHeight = This->decode_info.height;
941 
942  TRACE("(%p) <-- %ux%u\n", iface, *puiWidth, *puiHeight);
943 
944  return S_OK;
945 }
946 
947 static HRESULT WINAPI TiffFrameDecode_GetPixelFormat(IWICBitmapFrameDecode *iface,
948  WICPixelFormatGUID *pPixelFormat)
949 {
950  TiffFrameDecode *This = impl_from_IWICBitmapFrameDecode(iface);
951 
952  memcpy(pPixelFormat, This->decode_info.format, sizeof(GUID));
953 
954  TRACE("(%p) <-- %s\n", This, debugstr_guid(This->decode_info.format));
955 
956  return S_OK;
957 }
958 
959 static HRESULT WINAPI TiffFrameDecode_GetResolution(IWICBitmapFrameDecode *iface,
960  double *pDpiX, double *pDpiY)
961 {
962  TiffFrameDecode *This = impl_from_IWICBitmapFrameDecode(iface);
963 
964  if (This->decode_info.xres == 0 || This->decode_info.yres == 0)
965  {
966  *pDpiX = *pDpiY = 96.0;
967  }
968  else
969  {
970  switch (This->decode_info.resolution_unit)
971  {
972  default:
973  FIXME("unknown resolution unit %i\n", This->decode_info.resolution_unit);
974  /* fall through */
975  case 0: /* Not set */
976  case 1: /* Relative measurements */
977  case 2: /* Inch */
978  *pDpiX = This->decode_info.xres;
979  *pDpiY = This->decode_info.yres;
980  break;
981  case 3: /* Centimeter */
982  *pDpiX = This->decode_info.xres * 2.54;
983  *pDpiY = This->decode_info.yres * 2.54;
984  break;
985  }
986  }
987 
988  TRACE("(%p) <-- %f,%f unit=%i\n", iface, *pDpiX, *pDpiY, This->decode_info.resolution_unit);
989 
990  return S_OK;
991 }
992 
993 static HRESULT WINAPI TiffFrameDecode_CopyPalette(IWICBitmapFrameDecode *iface,
994  IWICPalette *pIPalette)
995 {
996  TiffFrameDecode *This = impl_from_IWICBitmapFrameDecode(iface);
997  uint16 *red, *green, *blue;
998  WICColor colors[256];
999  int color_count, ret, i;
1000 
1001  TRACE("(%p,%p)\n", iface, pIPalette);
1002 
1003  color_count = 1<<This->decode_info.bps;
1004 
1005  EnterCriticalSection(&This->parent->lock);
1006  ret = pTIFFGetField(This->parent->tiff, TIFFTAG_COLORMAP, &red, &green, &blue);
1007  LeaveCriticalSection(&This->parent->lock);
1008 
1009  if (!ret)
1010  {
1011  WARN("Couldn't read color map\n");
1013  }
1014 
1015  for (i=0; i<color_count; i++)
1016  {
1017  colors[i] = 0xff000000 |
1018  ((red[i]<<8) & 0xff0000) |
1019  (green[i] & 0xff00) |
1020  ((blue[i]>>8) & 0xff);
1021  }
1022 
1023  return IWICPalette_InitializeCustom(pIPalette, colors, color_count);
1024 }
1025 
1026 static HRESULT TiffFrameDecode_ReadTile(TiffFrameDecode *This, UINT tile_x, UINT tile_y)
1027 {
1028  tsize_t ret;
1029  int swap_bytes;
1030 
1031  swap_bytes = pTIFFIsByteSwapped(This->parent->tiff);
1032 
1033  ret = pTIFFSetDirectory(This->parent->tiff, This->index);
1034  if (ret == -1)
1035  return E_FAIL;
1036 
1037  if (This->decode_info.tiled)
1038  ret = pTIFFReadEncodedTile(This->parent->tiff, tile_x + tile_y * This->decode_info.tiles_across, This->cached_tile, This->decode_info.tile_size);
1039  else
1040  ret = pTIFFReadEncodedStrip(This->parent->tiff, tile_y, This->cached_tile, This->decode_info.tile_size);
1041 
1042  if (ret == -1)
1043  return E_FAIL;
1044 
1045  /* 3bpp RGB */
1046  if (This->decode_info.source_bpp == 3 && This->decode_info.samples == 3 && This->decode_info.bpp == 24)
1047  {
1048  BYTE *srcdata, *src, *dst;
1049  DWORD x, y, count, width_bytes = (This->decode_info.tile_width * 3 + 7) / 8;
1050 
1051  count = width_bytes * This->decode_info.tile_height;
1052 
1053  srcdata = HeapAlloc(GetProcessHeap(), 0, count);
1054  if (!srcdata) return E_OUTOFMEMORY;
1055  memcpy(srcdata, This->cached_tile, count);
1056 
1057  for (y = 0; y < This->decode_info.tile_height; y++)
1058  {
1059  src = srcdata + y * width_bytes;
1060  dst = This->cached_tile + y * This->decode_info.tile_width * 3;
1061 
1062  for (x = 0; x < This->decode_info.tile_width; x += 8)
1063  {
1064  dst[2] = (src[0] & 0x80) ? 0xff : 0; /* R */
1065  dst[1] = (src[0] & 0x40) ? 0xff : 0; /* G */
1066  dst[0] = (src[0] & 0x20) ? 0xff : 0; /* B */
1067  if (x + 1 < This->decode_info.tile_width)
1068  {
1069  dst[5] = (src[0] & 0x10) ? 0xff : 0; /* R */
1070  dst[4] = (src[0] & 0x08) ? 0xff : 0; /* G */
1071  dst[3] = (src[0] & 0x04) ? 0xff : 0; /* B */
1072  }
1073  if (x + 2 < This->decode_info.tile_width)
1074  {
1075  dst[8] = (src[0] & 0x02) ? 0xff : 0; /* R */
1076  dst[7] = (src[0] & 0x01) ? 0xff : 0; /* G */
1077  dst[6] = (src[1] & 0x80) ? 0xff : 0; /* B */
1078  }
1079  if (x + 3 < This->decode_info.tile_width)
1080  {
1081  dst[11] = (src[1] & 0x40) ? 0xff : 0; /* R */
1082  dst[10] = (src[1] & 0x20) ? 0xff : 0; /* G */
1083  dst[9] = (src[1] & 0x10) ? 0xff : 0; /* B */
1084  }
1085  if (x + 4 < This->decode_info.tile_width)
1086  {
1087  dst[14] = (src[1] & 0x08) ? 0xff : 0; /* R */
1088  dst[13] = (src[1] & 0x04) ? 0xff : 0; /* G */
1089  dst[12] = (src[1] & 0x02) ? 0xff : 0; /* B */
1090  }
1091  if (x + 5 < This->decode_info.tile_width)
1092  {
1093  dst[17] = (src[1] & 0x01) ? 0xff : 0; /* R */
1094  dst[16] = (src[2] & 0x80) ? 0xff : 0; /* G */
1095  dst[15] = (src[2] & 0x40) ? 0xff : 0; /* B */
1096  }
1097  if (x + 6 < This->decode_info.tile_width)
1098  {
1099  dst[20] = (src[2] & 0x20) ? 0xff : 0; /* R */
1100  dst[19] = (src[2] & 0x10) ? 0xff : 0; /* G */
1101  dst[18] = (src[2] & 0x08) ? 0xff : 0; /* B */
1102  }
1103  if (x + 7 < This->decode_info.tile_width)
1104  {
1105  dst[23] = (src[2] & 0x04) ? 0xff : 0; /* R */
1106  dst[22] = (src[2] & 0x02) ? 0xff : 0; /* G */
1107  dst[21] = (src[2] & 0x01) ? 0xff : 0; /* B */
1108  }
1109  src += 3;
1110  dst += 24;
1111  }
1112  }
1113 
1114  HeapFree(GetProcessHeap(), 0, srcdata);
1115  }
1116  /* 12bpp RGB */
1117  else if (This->decode_info.source_bpp == 12 && This->decode_info.samples == 3 && This->decode_info.bpp == 24)
1118  {
1119  BYTE *srcdata, *src, *dst;
1120  DWORD x, y, count, width_bytes = (This->decode_info.tile_width * 12 + 7) / 8;
1121 
1122  count = width_bytes * This->decode_info.tile_height;
1123 
1124  srcdata = HeapAlloc(GetProcessHeap(), 0, count);
1125  if (!srcdata) return E_OUTOFMEMORY;
1126  memcpy(srcdata, This->cached_tile, count);
1127 
1128  for (y = 0; y < This->decode_info.tile_height; y++)
1129  {
1130  src = srcdata + y * width_bytes;
1131  dst = This->cached_tile + y * This->decode_info.tile_width * 3;
1132 
1133  for (x = 0; x < This->decode_info.tile_width; x += 2)
1134  {
1135  dst[0] = ((src[1] & 0xf0) >> 4) * 17; /* B */
1136  dst[1] = (src[0] & 0x0f) * 17; /* G */
1137  dst[2] = ((src[0] & 0xf0) >> 4) * 17; /* R */
1138  if (x + 1 < This->decode_info.tile_width)
1139  {
1140  dst[5] = (src[1] & 0x0f) * 17; /* B */
1141  dst[4] = ((src[2] & 0xf0) >> 4) * 17; /* G */
1142  dst[3] = (src[2] & 0x0f) * 17; /* R */
1143  }
1144  src += 3;
1145  dst += 6;
1146  }
1147  }
1148 
1149  HeapFree(GetProcessHeap(), 0, srcdata);
1150  }
1151  /* 4bps RGBA */
1152  else if (This->decode_info.source_bpp == 4 && This->decode_info.samples == 4 && This->decode_info.bpp == 32)
1153  {
1154  BYTE *srcdata, *src, *dst;
1155  DWORD x, y, count, width_bytes = (This->decode_info.tile_width * 3 + 7) / 8;
1156 
1157  count = width_bytes * This->decode_info.tile_height;
1158 
1159  srcdata = HeapAlloc(GetProcessHeap(), 0, count);
1160  if (!srcdata) return E_OUTOFMEMORY;
1161  memcpy(srcdata, This->cached_tile, count);
1162 
1163  for (y = 0; y < This->decode_info.tile_height; y++)
1164  {
1165  src = srcdata + y * width_bytes;
1166  dst = This->cached_tile + y * This->decode_info.tile_width * 4;
1167 
1168  /* 1 source byte expands to 2 BGRA samples */
1169 
1170  for (x = 0; x < This->decode_info.tile_width; x += 2)
1171  {
1172  dst[0] = (src[0] & 0x20) ? 0xff : 0; /* B */
1173  dst[1] = (src[0] & 0x40) ? 0xff : 0; /* G */
1174  dst[2] = (src[0] & 0x80) ? 0xff : 0; /* R */
1175  dst[3] = (src[0] & 0x10) ? 0xff : 0; /* A */
1176  if (x + 1 < This->decode_info.tile_width)
1177  {
1178  dst[4] = (src[0] & 0x02) ? 0xff : 0; /* B */
1179  dst[5] = (src[0] & 0x04) ? 0xff : 0; /* G */
1180  dst[6] = (src[0] & 0x08) ? 0xff : 0; /* R */
1181  dst[7] = (src[0] & 0x01) ? 0xff : 0; /* A */
1182  }
1183  src++;
1184  dst += 8;
1185  }
1186  }
1187 
1188  HeapFree(GetProcessHeap(), 0, srcdata);
1189  }
1190  /* 16bpp RGBA */
1191  else if (This->decode_info.source_bpp == 16 && This->decode_info.samples == 4 && This->decode_info.bpp == 32)
1192  {
1193  BYTE *src, *dst;
1194  DWORD count = This->decode_info.tile_width * This->decode_info.tile_height;
1195 
1196  src = This->cached_tile + count * 2;
1197  dst = This->cached_tile + This->decode_info.tile_size;
1198 
1199  while (count--)
1200  {
1201  BYTE b[2];
1202 
1203  src -= 2;
1204  dst -= 4;
1205 
1206  b[0] = src[0];
1207  b[1] = src[1];
1208 
1209  dst[0] = ((b[1] & 0xf0) >> 4) * 17; /* B */
1210  dst[1] = (b[0] & 0x0f) * 17; /* G */
1211  dst[2] = ((b[0] & 0xf0) >> 4) * 17; /* R */
1212  dst[3] = (b[1] & 0x0f) * 17; /* A */
1213  }
1214  }
1215  /* 8bpp grayscale with extra alpha */
1216  else if (This->decode_info.source_bpp == 16 && This->decode_info.samples == 2 && This->decode_info.bpp == 32)
1217  {
1218  BYTE *src;
1219  DWORD *dst, count = This->decode_info.tile_width * This->decode_info.tile_height;
1220 
1221  src = This->cached_tile + This->decode_info.tile_width * This->decode_info.tile_height * 2 - 2;
1222  dst = (DWORD *)(This->cached_tile + This->decode_info.tile_size - 4);
1223 
1224  while (count--)
1225  {
1226  *dst-- = src[0] | (src[0] << 8) | (src[0] << 16) | (src[1] << 24);
1227  src -= 2;
1228  }
1229  }
1230 
1231  if (This->decode_info.reverse_bgr)
1232  {
1233  if (This->decode_info.bps == 8)
1234  {
1235  UINT sample_count = This->decode_info.samples;
1236 
1237  reverse_bgr8(sample_count, This->cached_tile, This->decode_info.tile_width,
1238  This->decode_info.tile_height, This->decode_info.tile_width * sample_count);
1239  }
1240  }
1241 
1242  if (swap_bytes && This->decode_info.bps > 8)
1243  {
1244  UINT row, i, samples_per_row;
1245  BYTE *sample, temp;
1246 
1247  samples_per_row = This->decode_info.tile_width * This->decode_info.samples;
1248 
1249  switch(This->decode_info.bps)
1250  {
1251  case 16:
1252  for (row=0; row<This->decode_info.tile_height; row++)
1253  {
1254  sample = This->cached_tile + row * This->decode_info.tile_stride;
1255  for (i=0; i<samples_per_row; i++)
1256  {
1257  temp = sample[1];
1258  sample[1] = sample[0];
1259  sample[0] = temp;
1260  sample += 2;
1261  }
1262  }
1263  break;
1264  default:
1265  ERR("unhandled bps for byte swap %u\n", This->decode_info.bps);
1266  return E_FAIL;
1267  }
1268  }
1269 
1270  if (This->decode_info.invert_grayscale)
1271  {
1272  BYTE *byte, *end;
1273 
1274  if (This->decode_info.samples != 1)
1275  {
1276  ERR("cannot invert grayscale image with %u samples\n", This->decode_info.samples);
1277  return E_FAIL;
1278  }
1279 
1280  end = This->cached_tile+This->decode_info.tile_size;
1281 
1282  for (byte = This->cached_tile; byte != end; byte++)
1283  *byte = ~(*byte);
1284  }
1285 
1286  This->cached_tile_x = tile_x;
1287  This->cached_tile_y = tile_y;
1288 
1289  return S_OK;
1290 }
1291 
1292 static HRESULT WINAPI TiffFrameDecode_CopyPixels(IWICBitmapFrameDecode *iface,
1293  const WICRect *prc, UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer)
1294 {
1295  TiffFrameDecode *This = impl_from_IWICBitmapFrameDecode(iface);
1296  UINT min_tile_x, max_tile_x, min_tile_y, max_tile_y;
1297  UINT tile_x, tile_y;
1298  WICRect rc;
1299  HRESULT hr=S_OK;
1300  BYTE *dst_tilepos;
1301  UINT bytesperrow;
1302  WICRect rect;
1303 
1304  TRACE("(%p,%s,%u,%u,%p)\n", iface, debug_wic_rect(prc), cbStride, cbBufferSize, pbBuffer);
1305 
1306  if (!prc)
1307  {
1308  rect.X = 0;
1309  rect.Y = 0;
1310  rect.Width = This->decode_info.width;
1311  rect.Height = This->decode_info.height;
1312  prc = &rect;
1313  }
1314  else
1315  {
1316  if (prc->X < 0 || prc->Y < 0 || prc->X+prc->Width > This->decode_info.width ||
1317  prc->Y+prc->Height > This->decode_info.height)
1318  return E_INVALIDARG;
1319  }
1320 
1321  bytesperrow = ((This->decode_info.bpp * prc->Width)+7)/8;
1322 
1323  if (cbStride < bytesperrow)
1324  return E_INVALIDARG;
1325 
1326  if ((cbStride * (prc->Height-1)) + bytesperrow > cbBufferSize)
1327  return E_INVALIDARG;
1328 
1329  min_tile_x = prc->X / This->decode_info.tile_width;
1330  min_tile_y = prc->Y / This->decode_info.tile_height;
1331  max_tile_x = (prc->X+prc->Width-1) / This->decode_info.tile_width;
1332  max_tile_y = (prc->Y+prc->Height-1) / This->decode_info.tile_height;
1333 
1334  EnterCriticalSection(&This->parent->lock);
1335 
1336  for (tile_x=min_tile_x; tile_x <= max_tile_x; tile_x++)
1337  {
1338  for (tile_y=min_tile_y; tile_y <= max_tile_y; tile_y++)
1339  {
1340  if (tile_x != This->cached_tile_x || tile_y != This->cached_tile_y)
1341  {
1342  hr = TiffFrameDecode_ReadTile(This, tile_x, tile_y);
1343  }
1344 
1345  if (SUCCEEDED(hr))
1346  {
1347  if (prc->X < tile_x * This->decode_info.tile_width)
1348  rc.X = 0;
1349  else
1350  rc.X = prc->X - tile_x * This->decode_info.tile_width;
1351 
1352  if (prc->Y < tile_y * This->decode_info.tile_height)
1353  rc.Y = 0;
1354  else
1355  rc.Y = prc->Y - tile_y * This->decode_info.tile_height;
1356 
1357  if (prc->X+prc->Width > (tile_x+1) * This->decode_info.tile_width)
1358  rc.Width = This->decode_info.tile_width - rc.X;
1359  else if (prc->X < tile_x * This->decode_info.tile_width)
1360  rc.Width = prc->Width + prc->X - tile_x * This->decode_info.tile_width;
1361  else
1362  rc.Width = prc->Width;
1363 
1364  if (prc->Y+prc->Height > (tile_y+1) * This->decode_info.tile_height)
1365  rc.Height = This->decode_info.tile_height - rc.Y;
1366  else if (prc->Y < tile_y * This->decode_info.tile_height)
1367  rc.Height = prc->Height + prc->Y - tile_y * This->decode_info.tile_height;
1368  else
1369  rc.Height = prc->Height;
1370 
1371  dst_tilepos = pbBuffer + (cbStride * ((rc.Y + tile_y * This->decode_info.tile_height) - prc->Y)) +
1372  ((This->decode_info.bpp * ((rc.X + tile_x * This->decode_info.tile_width) - prc->X) + 7) / 8);
1373 
1374  hr = copy_pixels(This->decode_info.bpp, This->cached_tile,
1375  This->decode_info.tile_width, This->decode_info.tile_height, This->decode_info.tile_stride,
1376  &rc, cbStride, cbBufferSize, dst_tilepos);
1377  }
1378 
1379  if (FAILED(hr))
1380  {
1381  LeaveCriticalSection(&This->parent->lock);
1382  TRACE("<-- 0x%x\n", hr);
1383  return hr;
1384  }
1385  }
1386  }
1387 
1388  LeaveCriticalSection(&This->parent->lock);
1389 
1390  return S_OK;
1391 }
1392 
1393 static HRESULT WINAPI TiffFrameDecode_GetMetadataQueryReader(IWICBitmapFrameDecode *iface,
1394  IWICMetadataQueryReader **ppIMetadataQueryReader)
1395 {
1396  TiffFrameDecode *This = impl_from_IWICBitmapFrameDecode(iface);
1397 
1398  TRACE("(%p,%p)\n", iface, ppIMetadataQueryReader);
1399 
1400  if (!ppIMetadataQueryReader)
1401  return E_INVALIDARG;
1402 
1403  return MetadataQueryReader_CreateInstance(&This->IWICMetadataBlockReader_iface, NULL, ppIMetadataQueryReader);
1404 }
1405 
1406 static HRESULT WINAPI TiffFrameDecode_GetColorContexts(IWICBitmapFrameDecode *iface,
1407  UINT cCount, IWICColorContext **ppIColorContexts, UINT *pcActualCount)
1408 {
1409  TiffFrameDecode *This = impl_from_IWICBitmapFrameDecode(iface);
1410  const BYTE *profile;
1411  UINT len;
1412  HRESULT hr;
1413 
1414  TRACE("(%p,%u,%p,%p)\n", iface, cCount, ppIColorContexts, pcActualCount);
1415 
1416  EnterCriticalSection(&This->parent->lock);
1417 
1418  if (pTIFFGetField(This->parent->tiff, TIFFTAG_ICCPROFILE, &len, &profile))
1419  {
1420  if (cCount && ppIColorContexts)
1421  {
1422  hr = IWICColorContext_InitializeFromMemory(*ppIColorContexts, profile, len);
1423  if (FAILED(hr))
1424  {
1425  LeaveCriticalSection(&This->parent->lock);
1426  return hr;
1427  }
1428  }
1429  *pcActualCount = 1;
1430  }
1431  else
1432  *pcActualCount = 0;
1433 
1434  LeaveCriticalSection(&This->parent->lock);
1435 
1436  return S_OK;
1437 }
1438 
1439 static HRESULT WINAPI TiffFrameDecode_GetThumbnail(IWICBitmapFrameDecode *iface,
1440  IWICBitmapSource **ppIThumbnail)
1441 {
1442  TRACE("(%p,%p)\n", iface, ppIThumbnail);
1443 
1444  if (!ppIThumbnail) return E_INVALIDARG;
1445 
1446  *ppIThumbnail = NULL;
1448 }
1449 
1450 static const IWICBitmapFrameDecodeVtbl TiffFrameDecode_Vtbl = {
1451  TiffFrameDecode_QueryInterface,
1452  TiffFrameDecode_AddRef,
1453  TiffFrameDecode_Release,
1454  TiffFrameDecode_GetSize,
1455  TiffFrameDecode_GetPixelFormat,
1456  TiffFrameDecode_GetResolution,
1457  TiffFrameDecode_CopyPalette,
1458  TiffFrameDecode_CopyPixels,
1459  TiffFrameDecode_GetMetadataQueryReader,
1460  TiffFrameDecode_GetColorContexts,
1461  TiffFrameDecode_GetThumbnail
1462 };
1463 
1464 static HRESULT WINAPI TiffFrameDecode_Block_QueryInterface(IWICMetadataBlockReader *iface,
1465  REFIID iid, void **ppv)
1466 {
1467  TiffFrameDecode *This = impl_from_IWICMetadataBlockReader(iface);
1468  return IWICBitmapFrameDecode_QueryInterface(&This->IWICBitmapFrameDecode_iface, iid, ppv);
1469 }
1470 
1471 static ULONG WINAPI TiffFrameDecode_Block_AddRef(IWICMetadataBlockReader *iface)
1472 {
1473  TiffFrameDecode *This = impl_from_IWICMetadataBlockReader(iface);
1474  return IWICBitmapFrameDecode_AddRef(&This->IWICBitmapFrameDecode_iface);
1475 }
1476 
1477 static ULONG WINAPI TiffFrameDecode_Block_Release(IWICMetadataBlockReader *iface)
1478 {
1479  TiffFrameDecode *This = impl_from_IWICMetadataBlockReader(iface);
1480  return IWICBitmapFrameDecode_Release(&This->IWICBitmapFrameDecode_iface);
1481 }
1482 
1483 static HRESULT WINAPI TiffFrameDecode_Block_GetContainerFormat(IWICMetadataBlockReader *iface,
1484  GUID *guid)
1485 {
1486  TRACE("(%p,%p)\n", iface, guid);
1487 
1488  if (!guid) return E_INVALIDARG;
1489 
1490  *guid = GUID_ContainerFormatTiff;
1491  return S_OK;
1492 }
1493 
1494 static HRESULT WINAPI TiffFrameDecode_Block_GetCount(IWICMetadataBlockReader *iface,
1495  UINT *count)
1496 {
1497  TRACE("%p,%p\n", iface, count);
1498 
1499  if (!count) return E_INVALIDARG;
1500 
1501  *count = 1;
1502  return S_OK;
1503 }
1504 
1505 static HRESULT create_metadata_reader(TiffFrameDecode *This, IWICMetadataReader **reader)
1506 {
1507  HRESULT hr;
1508  LARGE_INTEGER dir_offset;
1509  IWICMetadataReader *metadata_reader;
1510  IWICPersistStream *persist;
1511 
1512  /* FIXME: Use IWICComponentFactory_CreateMetadataReader once it's implemented */
1513 
1514  hr = IfdMetadataReader_CreateInstance(&IID_IWICMetadataReader, (void **)&metadata_reader);
1515  if (FAILED(hr)) return hr;
1516 
1517  hr = IWICMetadataReader_QueryInterface(metadata_reader, &IID_IWICPersistStream, (void **)&persist);
1518  if (FAILED(hr))
1519  {
1520  IWICMetadataReader_Release(metadata_reader);
1521  return hr;
1522  }
1523 
1524  EnterCriticalSection(&This->parent->lock);
1525 
1526  dir_offset.QuadPart = pTIFFCurrentDirOffset(This->parent->tiff);
1527  hr = IStream_Seek(This->parent->stream, dir_offset, STREAM_SEEK_SET, NULL);
1528  if (SUCCEEDED(hr))
1529  {
1530  BOOL byte_swapped = pTIFFIsByteSwapped(This->parent->tiff);
1531 #ifdef WORDS_BIGENDIAN
1533 #else
1535 #endif
1536  persist_options |= WICPersistOptionNoCacheStream;
1537  hr = IWICPersistStream_LoadEx(persist, This->parent->stream, NULL, persist_options);
1538  if (FAILED(hr))
1539  ERR("IWICPersistStream_LoadEx error %#x\n", hr);
1540  }
1541 
1542  LeaveCriticalSection(&This->parent->lock);
1543 
1544  IWICPersistStream_Release(persist);
1545 
1546  if (FAILED(hr))
1547  {
1548  IWICMetadataReader_Release(metadata_reader);
1549  return hr;
1550  }
1551 
1552  *reader = metadata_reader;
1553  return S_OK;
1554 }
1555 
1556 static HRESULT WINAPI TiffFrameDecode_Block_GetReaderByIndex(IWICMetadataBlockReader *iface,
1558 {
1559  TiffFrameDecode *This = impl_from_IWICMetadataBlockReader(iface);
1560 
1561  TRACE("(%p,%u,%p)\n", iface, index, reader);
1562 
1563  if (!reader || index != 0) return E_INVALIDARG;
1564 
1566 }
1567 
1568 static HRESULT WINAPI TiffFrameDecode_Block_GetEnumerator(IWICMetadataBlockReader *iface,
1569  IEnumUnknown **enum_metadata)
1570 {
1571  FIXME("(%p,%p): stub\n", iface, enum_metadata);
1572  return E_NOTIMPL;
1573 }
1574 
1575 static const IWICMetadataBlockReaderVtbl TiffFrameDecode_BlockVtbl =
1576 {
1577  TiffFrameDecode_Block_QueryInterface,
1578  TiffFrameDecode_Block_AddRef,
1579  TiffFrameDecode_Block_Release,
1580  TiffFrameDecode_Block_GetContainerFormat,
1581  TiffFrameDecode_Block_GetCount,
1582  TiffFrameDecode_Block_GetReaderByIndex,
1583  TiffFrameDecode_Block_GetEnumerator
1584 };
1585 
1587 {
1588  HRESULT ret;
1589  TiffDecoder *This;
1590 
1591  TRACE("(%s,%p)\n", debugstr_guid(iid), ppv);
1592 
1593  *ppv = NULL;
1594 
1595  if (!load_libtiff())
1596  {
1597  ERR("Failed reading TIFF because unable to load %s\n",SONAME_LIBTIFF);
1598  return E_FAIL;
1599  }
1600 
1601  This = HeapAlloc(GetProcessHeap(), 0, sizeof(TiffDecoder));
1602  if (!This) return E_OUTOFMEMORY;
1603 
1604  This->IWICBitmapDecoder_iface.lpVtbl = &TiffDecoder_Vtbl;
1605  This->ref = 1;
1606  This->stream = NULL;
1608  This->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": TiffDecoder.lock");
1609  This->tiff = NULL;
1610  This->initialized = FALSE;
1611 
1612  ret = IWICBitmapDecoder_QueryInterface(&This->IWICBitmapDecoder_iface, iid, ppv);
1613  IWICBitmapDecoder_Release(&This->IWICBitmapDecoder_iface);
1614 
1615  return ret;
1616 }
1617 
1618 struct tiff_encode_format {
1619  const WICPixelFormatGUID *guid;
1620  int photometric;
1621  int bps;
1622  int samples;
1623  int bpp;
1624  int extra_sample;
1625  int extra_sample_type;
1626  int reverse_bgr;
1627 };
1628 
1629 static const struct tiff_encode_format formats[] = {
1630  {&GUID_WICPixelFormat24bppBGR, 2, 8, 3, 24, 0, 0, 1},
1631  {&GUID_WICPixelFormat24bppRGB, 2, 8, 3, 24, 0, 0, 0},
1632  {&GUID_WICPixelFormatBlackWhite, 1, 1, 1, 1, 0, 0, 0},
1633  {&GUID_WICPixelFormat4bppGray, 1, 4, 1, 4, 0, 0, 0},
1634  {&GUID_WICPixelFormat8bppGray, 1, 8, 1, 8, 0, 0, 0},
1635  {&GUID_WICPixelFormat32bppBGRA, 2, 8, 4, 32, 1, 2, 1},
1636  {&GUID_WICPixelFormat32bppPBGRA, 2, 8, 4, 32, 1, 1, 1},
1637  {&GUID_WICPixelFormat48bppRGB, 2, 16, 3, 48, 0, 0, 0},
1638  {&GUID_WICPixelFormat64bppRGBA, 2, 16, 4, 64, 1, 2, 0},
1639  {&GUID_WICPixelFormat64bppPRGBA, 2, 16, 4, 64, 1, 1, 0},
1640  {&GUID_WICPixelFormat1bppIndexed, 3, 1, 1, 1, 0, 0, 0},
1641  {&GUID_WICPixelFormat4bppIndexed, 3, 4, 1, 4, 0, 0, 0},
1642  {&GUID_WICPixelFormat8bppIndexed, 3, 8, 1, 8, 0, 0, 0},
1643  {0}
1644 };
1645 
1646 typedef struct TiffEncoder {
1647  IWICBitmapEncoder IWICBitmapEncoder_iface;
1648  LONG ref;
1649  IStream *stream;
1650  CRITICAL_SECTION lock; /* Must be held when tiff is used or fields below are set */
1651  TIFF *tiff;
1652  BOOL initialized;
1653  BOOL committed;
1654  ULONG num_frames;
1655  ULONG num_frames_committed;
1656 } TiffEncoder;
1657 
1658 static inline TiffEncoder *impl_from_IWICBitmapEncoder(IWICBitmapEncoder *iface)
1659 {
1660  return CONTAINING_RECORD(iface, TiffEncoder, IWICBitmapEncoder_iface);
1661 }
1662 
1663 typedef struct TiffFrameEncode {
1664  IWICBitmapFrameEncode IWICBitmapFrameEncode_iface;
1665  LONG ref;
1666  TiffEncoder *parent;
1667  /* fields below are protected by parent->lock */
1668  BOOL initialized;
1669  BOOL info_written;
1670  BOOL committed;
1671  const struct tiff_encode_format *format;
1672  UINT width, height;
1673  double xres, yres;
1674  UINT lines_written;
1675  WICColor palette[256];
1676  UINT colors;
1677 } TiffFrameEncode;
1678 
1679 static inline TiffFrameEncode *impl_from_IWICBitmapFrameEncode(IWICBitmapFrameEncode *iface)
1680 {
1681  return CONTAINING_RECORD(iface, TiffFrameEncode, IWICBitmapFrameEncode_iface);
1682 }
1683 
1684 static HRESULT WINAPI TiffFrameEncode_QueryInterface(IWICBitmapFrameEncode *iface, REFIID iid,
1685  void **ppv)
1686 {
1687  TiffFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface);
1688  TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
1689 
1690  if (!ppv) return E_INVALIDARG;
1691 
1692  if (IsEqualIID(&IID_IUnknown, iid) ||
1693  IsEqualIID(&IID_IWICBitmapFrameEncode, iid))
1694  {
1695  *ppv = &This->IWICBitmapFrameEncode_iface;
1696  }
1697  else
1698  {
1699  *ppv = NULL;
1700  return E_NOINTERFACE;
1701  }
1702 
1703  IUnknown_AddRef((IUnknown*)*ppv);
1704  return S_OK;
1705 }
1706 
1707 static ULONG WINAPI TiffFrameEncode_AddRef(IWICBitmapFrameEncode *iface)
1708 {
1709  TiffFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface);
1711 
1712  TRACE("(%p) refcount=%u\n", iface, ref);
1713 
1714  return ref;
1715 }
1716 
1717 static ULONG WINAPI TiffFrameEncode_Release(IWICBitmapFrameEncode *iface)
1718 {
1719  TiffFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface);
1721 
1722  TRACE("(%p) refcount=%u\n", iface, ref);
1723 
1724  if (ref == 0)
1725  {
1726  IWICBitmapEncoder_Release(&This->parent->IWICBitmapEncoder_iface);
1727  HeapFree(GetProcessHeap(), 0, This);
1728  }
1729 
1730  return ref;
1731 }
1732 
1733 static HRESULT WINAPI TiffFrameEncode_Initialize(IWICBitmapFrameEncode *iface,
1734  IPropertyBag2 *pIEncoderOptions)
1735 {
1736  TiffFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface);
1737  TRACE("(%p,%p)\n", iface, pIEncoderOptions);
1738 
1739  EnterCriticalSection(&This->parent->lock);
1740 
1741  if (This->initialized)
1742  {
1743  LeaveCriticalSection(&This->parent->lock);
1744  return WINCODEC_ERR_WRONGSTATE;
1745  }
1746 
1747  This->initialized = TRUE;
1748 
1749  LeaveCriticalSection(&This->parent->lock);
1750 
1751  return S_OK;
1752 }
1753 
1754 static HRESULT WINAPI TiffFrameEncode_SetSize(IWICBitmapFrameEncode *iface,
1755  UINT uiWidth, UINT uiHeight)
1756 {
1757  TiffFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface);
1758  TRACE("(%p,%u,%u)\n", iface, uiWidth, uiHeight);
1759 
1760  EnterCriticalSection(&This->parent->lock);
1761 
1762  if (!This->initialized || This->info_written)
1763  {
1764  LeaveCriticalSection(&This->parent->lock);
1765  return WINCODEC_ERR_WRONGSTATE;
1766  }
1767 
1768  This->width = uiWidth;
1769  This->height = uiHeight;
1770 
1771  LeaveCriticalSection(&This->parent->lock);
1772 
1773  return S_OK;
1774 }
1775 
1776 static HRESULT WINAPI TiffFrameEncode_SetResolution(IWICBitmapFrameEncode *iface,
1777  double dpiX, double dpiY)
1778 {
1779  TiffFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface);
1780  TRACE("(%p,%0.2f,%0.2f)\n", iface, dpiX, dpiY);
1781 
1782  EnterCriticalSection(&This->parent->lock);
1783 
1784  if (!This->initialized || This->info_written)
1785  {
1786  LeaveCriticalSection(&This->parent->lock);
1787  return WINCODEC_ERR_WRONGSTATE;
1788  }
1789 
1790  This->xres = dpiX;
1791  This->yres = dpiY;
1792 
1793  LeaveCriticalSection(&This->parent->lock);
1794 
1795  return S_OK;
1796 }
1797 
1798 static HRESULT WINAPI TiffFrameEncode_SetPixelFormat(IWICBitmapFrameEncode *iface,
1799  WICPixelFormatGUID *pPixelFormat)
1800 {
1801  TiffFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface);
1802  int i;
1803 
1804  TRACE("(%p,%s)\n", iface, debugstr_guid(pPixelFormat));
1805 
1806  EnterCriticalSection(&This->parent->lock);
1807 
1808  if (!This->initialized || This->info_written)
1809  {
1810  LeaveCriticalSection(&This->parent->lock);
1811  return WINCODEC_ERR_WRONGSTATE;
1812  }
1813 
1814  if (IsEqualGUID(pPixelFormat, &GUID_WICPixelFormat2bppIndexed))
1815  *pPixelFormat = GUID_WICPixelFormat4bppIndexed;
1816 
1817  for (i=0; formats[i].guid; i++)
1818  {
1819  if (IsEqualGUID(formats[i].guid, pPixelFormat))
1820  break;
1821  }
1822 
1823  if (!formats[i].guid) i = 0;
1824 
1825  This->format = &formats[i];
1826  memcpy(pPixelFormat, This->format->guid, sizeof(GUID));
1827 
1828  LeaveCriticalSection(&This->parent->lock);
1829 
1830  return S_OK;
1831 }
1832 
1833 static HRESULT WINAPI TiffFrameEncode_SetColorContexts(IWICBitmapFrameEncode *iface,
1834  UINT cCount, IWICColorContext **ppIColorContext)
1835 {
1836  FIXME("(%p,%u,%p): stub\n", iface, cCount, ppIColorContext);
1837  return E_NOTIMPL;
1838 }
1839 
1840 static HRESULT WINAPI TiffFrameEncode_SetPalette(IWICBitmapFrameEncode *iface,
1842 {
1843  TiffFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface);
1844  HRESULT hr;
1845 
1846  TRACE("(%p,%p)\n", iface, palette);
1847 
1848  if (!palette) return E_INVALIDARG;
1849 
1850  EnterCriticalSection(&This->parent->lock);
1851 
1852  if (This->initialized)
1853  hr = IWICPalette_GetColors(palette, 256, This->palette, &This->colors);
1854  else
1856 
1857  LeaveCriticalSection(&This->parent->lock);
1858  return hr;
1859 }
1860 
1861 static HRESULT WINAPI TiffFrameEncode_SetThumbnail(IWICBitmapFrameEncode *iface,
1862  IWICBitmapSource *pIThumbnail)
1863 {
1864  FIXME("(%p,%p): stub\n", iface, pIThumbnail);
1866 }
1867 
1868 static HRESULT WINAPI TiffFrameEncode_WritePixels(IWICBitmapFrameEncode *iface,
1869  UINT lineCount, UINT cbStride, UINT cbBufferSize, BYTE *pbPixels)
1870 {
1871  TiffFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface);
1872  BYTE *row_data, *swapped_data = NULL;
1873  UINT i, j, line_size;
1874 
1875  TRACE("(%p,%u,%u,%u,%p)\n", iface, lineCount, cbStride, cbBufferSize, pbPixels);
1876 
1877  EnterCriticalSection(&This->parent->lock);
1878 
1879  if (!This->initialized || !This->width || !This->height || !This->format)
1880  {
1881  LeaveCriticalSection(&This->parent->lock);
1882  return WINCODEC_ERR_WRONGSTATE;
1883  }
1884 
1885  if (lineCount == 0 || lineCount + This->lines_written > This->height)
1886  {
1887  LeaveCriticalSection(&This->parent->lock);
1888  return E_INVALIDARG;
1889  }
1890 
1891  line_size = ((This->width * This->format->bpp)+7)/8;
1892 
1893  if (This->format->reverse_bgr)
1894  {
1895  swapped_data = HeapAlloc(GetProcessHeap(), 0, line_size);
1896  if (!swapped_data)
1897  {
1898  LeaveCriticalSection(&This->parent->lock);
1899  return E_OUTOFMEMORY;
1900  }
1901  }
1902 
1903  if (!This->info_written)
1904  {
1905  pTIFFSetField(This->parent->tiff, TIFFTAG_PHOTOMETRIC, (uint16)This->format->photometric);
1906  pTIFFSetField(This->parent->tiff, TIFFTAG_PLANARCONFIG, (uint16)1);
1907  pTIFFSetField(This->parent->tiff, TIFFTAG_BITSPERSAMPLE, (uint16)This->format->bps);
1908  pTIFFSetField(This->parent->tiff, TIFFTAG_SAMPLESPERPIXEL, (uint16)This->format->samples);
1909 
1910  if (This->format->extra_sample)
1911  {
1912  uint16 extra_samples;
1913  extra_samples = This->format->extra_sample_type;
1914 
1915  pTIFFSetField(This->parent->tiff, TIFFTAG_EXTRASAMPLES, (uint16)1, &extra_samples);
1916  }
1917 
1918  pTIFFSetField(This->parent->tiff, TIFFTAG_IMAGEWIDTH, (uint32)This->width);
1919  pTIFFSetField(This->parent->tiff, TIFFTAG_IMAGELENGTH, (uint32)This->height);
1920 
1921  if (This->xres != 0.0 && This->yres != 0.0)
1922  {
1923  pTIFFSetField(This->parent->tiff, TIFFTAG_RESOLUTIONUNIT, (uint16)2); /* Inch */
1924  pTIFFSetField(This->parent->tiff, TIFFTAG_XRESOLUTION, (float)This->xres);
1925  pTIFFSetField(This->parent->tiff, TIFFTAG_YRESOLUTION, (float)This->yres);
1926  }
1927 
1928  if (This->format->bpp <= 8 && This->colors && !IsEqualGUID(This->format->guid, &GUID_WICPixelFormatBlackWhite))
1929  {
1930  uint16 red[256], green[256], blue[256];
1931  UINT i;
1932 
1933  for (i = 0; i < This->colors; i++)
1934  {
1935  red[i] = (This->palette[i] >> 8) & 0xff00;
1936  green[i] = This->palette[i] & 0xff00;
1937  blue[i] = (This->palette[i] << 8) & 0xff00;
1938  }
1939 
1940  pTIFFSetField(This->parent->tiff, TIFFTAG_COLORMAP, red, green, blue);
1941  }
1942 
1943  This->info_written = TRUE;
1944  }
1945 
1946  for (i=0; i<lineCount; i++)
1947  {
1948  row_data = pbPixels + i * cbStride;
1949 
1950  if (This->format->reverse_bgr && This->format->bps == 8)
1951  {
1952  memcpy(swapped_data, row_data, line_size);
1953  for (j=0; j<line_size; j += This->format->samples)
1954  {
1955  BYTE temp;
1956  temp = swapped_data[j];
1957  swapped_data[j] = swapped_data[j+2];
1958  swapped_data[j+2] = temp;
1959  }
1960  row_data = swapped_data;
1961  }
1962 
1963  pTIFFWriteScanline(This->parent->tiff, (tdata_t)row_data, i+This->lines_written, 0);
1964  }
1965 
1966  This->lines_written += lineCount;
1967 
1968  LeaveCriticalSection(&This->parent->lock);
1969 
1970  HeapFree(GetProcessHeap(), 0, swapped_data);
1971 
1972  return S_OK;
1973 }
1974 
1975 static HRESULT WINAPI TiffFrameEncode_WriteSource(IWICBitmapFrameEncode *iface,
1976  IWICBitmapSource *pIBitmapSource, WICRect *prc)
1977 {
1978  TiffFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface);
1979  HRESULT hr;
1980 
1981  TRACE("(%p,%p,%s)\n", iface, pIBitmapSource, debug_wic_rect(prc));
1982 
1983  if (!This->initialized)
1984  return WINCODEC_ERR_WRONGSTATE;
1985 
1986  hr = configure_write_source(iface, pIBitmapSource, prc,
1987  This->format ? This->format->guid : NULL, This->width, This->height,
1988  This->xres, This->yres);
1989 
1990  if (SUCCEEDED(hr))
1991  {
1992  hr = write_source(iface, pIBitmapSource, prc,
1993  This->format->guid, This->format->bpp, This->width, This->height);
1994  }
1995 
1996  return hr;
1997 }
1998 
1999 static HRESULT WINAPI TiffFrameEncode_Commit(IWICBitmapFrameEncode *iface)
2000 {
2001  TiffFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface);
2002 
2003  TRACE("(%p)\n", iface);
2004 
2005  EnterCriticalSection(&This->parent->lock);
2006 
2007  if (!This->info_written || This->lines_written != This->height || This->committed)
2008  {
2009  LeaveCriticalSection(&This->parent->lock);
2010  return WINCODEC_ERR_WRONGSTATE;
2011  }
2012 
2013  /* libtiff will commit the data when creating a new frame or closing the file */
2014 
2015  This->committed = TRUE;
2016  This->parent->num_frames_committed++;
2017 
2018  LeaveCriticalSection(&This->parent->lock);
2019 
2020  return S_OK;
2021 }
2022 
2023 static HRESULT WINAPI TiffFrameEncode_GetMetadataQueryWriter(IWICBitmapFrameEncode *iface,
2024  IWICMetadataQueryWriter **ppIMetadataQueryWriter)
2025 {
2026  FIXME("(%p, %p): stub\n", iface, ppIMetadataQueryWriter);
2027  return E_NOTIMPL;
2028 }
2029 
2030 static const IWICBitmapFrameEncodeVtbl TiffFrameEncode_Vtbl = {
2031  TiffFrameEncode_QueryInterface,
2032  TiffFrameEncode_AddRef,
2033  TiffFrameEncode_Release,
2034  TiffFrameEncode_Initialize,
2035  TiffFrameEncode_SetSize,
2036  TiffFrameEncode_SetResolution,
2037  TiffFrameEncode_SetPixelFormat,
2038  TiffFrameEncode_SetColorContexts,
2039  TiffFrameEncode_SetPalette,
2040  TiffFrameEncode_SetThumbnail,
2041  TiffFrameEncode_WritePixels,
2042  TiffFrameEncode_WriteSource,
2043  TiffFrameEncode_Commit,
2044  TiffFrameEncode_GetMetadataQueryWriter
2045 };
2046 
2047 static HRESULT WINAPI TiffEncoder_QueryInterface(IWICBitmapEncoder *iface, REFIID iid,
2048  void **ppv)
2049 {
2050  TiffEncoder *This = impl_from_IWICBitmapEncoder(iface);
2051  TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
2052 
2053  if (!ppv) return E_INVALIDARG;
2054 
2055  if (IsEqualIID(&IID_IUnknown, iid) ||
2056  IsEqualIID(&IID_IWICBitmapEncoder, iid))
2057  {
2058  *ppv = &This->IWICBitmapEncoder_iface;
2059  }
2060  else
2061  {
2062  *ppv = NULL;
2063  return E_NOINTERFACE;
2064  }
2065 
2066  IUnknown_AddRef((IUnknown*)*ppv);
2067  return S_OK;
2068 }
2069 
2070 static ULONG WINAPI TiffEncoder_AddRef(IWICBitmapEncoder *iface)
2071 {
2072  TiffEncoder *This = impl_from_IWICBitmapEncoder(iface);
2074 
2075  TRACE("(%p) refcount=%u\n", iface, ref);
2076 
2077  return ref;
2078 }
2079 
2080 static ULONG WINAPI TiffEncoder_Release(IWICBitmapEncoder *iface)
2081 {
2082  TiffEncoder *This = impl_from_IWICBitmapEncoder(iface);
2084 
2085  TRACE("(%p) refcount=%u\n", iface, ref);
2086 
2087  if (ref == 0)
2088  {
2089  if (This->tiff) pTIFFClose(This->tiff);
2090  if (This->stream) IStream_Release(This->stream);
2091  This->lock.DebugInfo->Spare[0] = 0;
2092  DeleteCriticalSection(&This->lock);
2093  HeapFree(GetProcessHeap(), 0, This);
2094  }
2095 
2096  return ref;
2097 }
2098 
2099 static HRESULT WINAPI TiffEncoder_Initialize(IWICBitmapEncoder *iface,
2100  IStream *pIStream, WICBitmapEncoderCacheOption cacheOption)
2101 {
2102  TiffEncoder *This = impl_from_IWICBitmapEncoder(iface);
2103  TIFF *tiff;
2104  HRESULT hr=S_OK;
2105 
2106  TRACE("(%p,%p,%u)\n", iface, pIStream, cacheOption);
2107 
2108  EnterCriticalSection(&This->lock);
2109 
2110  if (This->initialized || This->committed)
2111  {
2113  goto exit;
2114  }
2115 
2116  tiff = tiff_open_stream(pIStream, "w");
2117 
2118  if (!tiff)
2119  {
2120  hr = E_FAIL;
2121  goto exit;
2122  }
2123 
2124  This->tiff = tiff;
2125  This->stream = pIStream;
2126  IStream_AddRef(pIStream);
2127  This->initialized = TRUE;
2128 
2129 exit:
2130  LeaveCriticalSection(&This->lock);
2131  return hr;
2132 }
2133 
2134 static HRESULT WINAPI TiffEncoder_GetContainerFormat(IWICBitmapEncoder *iface,
2135  GUID *pguidContainerFormat)
2136 {
2137  TRACE("(%p,%p)\n", iface, pguidContainerFormat);
2138 
2139  if (!pguidContainerFormat)
2140  return E_INVALIDARG;
2141 
2142  memcpy(pguidContainerFormat, &GUID_ContainerFormatTiff, sizeof(GUID));
2143  return S_OK;
2144 }
2145 
2146 static HRESULT WINAPI TiffEncoder_GetEncoderInfo(IWICBitmapEncoder *iface, IWICBitmapEncoderInfo **info)
2147 {
2148  IWICComponentInfo *comp_info;
2149  HRESULT hr;
2150 
2151  TRACE("%p,%p\n", iface, info);
2152 
2153  if (!info) return E_INVALIDARG;
2154 
2155  hr = CreateComponentInfo(&CLSID_WICTiffEncoder, &comp_info);
2156  if (hr == S_OK)
2157  {
2158  hr = IWICComponentInfo_QueryInterface(comp_info, &IID_IWICBitmapEncoderInfo, (void **)info);
2159  IWICComponentInfo_Release(comp_info);
2160  }
2161  return hr;
2162 }
2163 
2164 static HRESULT WINAPI TiffEncoder_SetColorContexts(IWICBitmapEncoder *iface,
2165  UINT cCount, IWICColorContext **ppIColorContext)
2166 {
2167  FIXME("(%p,%u,%p): stub\n", iface, cCount, ppIColorContext);
2168  return E_NOTIMPL;
2169 }
2170 
2171 static HRESULT WINAPI TiffEncoder_SetPalette(IWICBitmapEncoder *iface, IWICPalette *palette)
2172 {
2173  TiffEncoder *This = impl_from_IWICBitmapEncoder(iface);
2174  HRESULT hr;
2175 
2176  TRACE("(%p,%p)\n", iface, palette);
2177 
2178  EnterCriticalSection(&This->lock);
2179 
2181 
2182  LeaveCriticalSection(&This->lock);
2183 
2184  return hr;
2185 }
2186 
2187 static HRESULT WINAPI TiffEncoder_SetThumbnail(IWICBitmapEncoder *iface, IWICBitmapSource *pIThumbnail)
2188 {
2189  TRACE("(%p,%p)\n", iface, pIThumbnail);
2191 }
2192 
2193 static HRESULT WINAPI TiffEncoder_SetPreview(IWICBitmapEncoder *iface, IWICBitmapSource *pIPreview)
2194 {
2195  TRACE("(%p,%p)\n", iface, pIPreview);
2197 }
2198 
2199 static HRESULT WINAPI TiffEncoder_CreateNewFrame(IWICBitmapEncoder *iface,
2200  IWICBitmapFrameEncode **ppIFrameEncode, IPropertyBag2 **ppIEncoderOptions)
2201 {
2202  TiffEncoder *This = impl_from_IWICBitmapEncoder(iface);
2203  TiffFrameEncode *result;
2204  static const PROPBAG2 opts[2] =
2205  {
2206  { PROPBAG2_TYPE_DATA, VT_UI1, 0, 0, (LPOLESTR)wszTiffCompressionMethod },
2207  { PROPBAG2_TYPE_DATA, VT_R4, 0, 0, (LPOLESTR)wszCompressionQuality },
2208  };
2209  HRESULT hr=S_OK;
2210 
2211  TRACE("(%p,%p,%p)\n", iface, ppIFrameEncode, ppIEncoderOptions);
2212 
2213  EnterCriticalSection(&This->lock);
2214 
2215  if (!This->initialized || This->committed)
2216  {
2218  }
2219  else if (This->num_frames != This->num_frames_committed)
2220  {
2221  FIXME("New frame created before previous frame was committed\n");
2222  hr = E_FAIL;
2223  }
2224 
2225  if (ppIEncoderOptions && SUCCEEDED(hr))
2226  {
2227  hr = CreatePropertyBag2(opts, ARRAY_SIZE(opts), ppIEncoderOptions);
2228  if (SUCCEEDED(hr))
2229  {
2230  VARIANT v;
2231  VariantInit(&v);
2232  V_VT(&v) = VT_UI1;
2234  hr = IPropertyBag2_Write(*ppIEncoderOptions, 1, (PROPBAG2 *)opts, &v);
2235  VariantClear(&v);
2236  if (FAILED(hr))
2237  {
2238  IPropertyBag2_Release(*ppIEncoderOptions);
2239  *ppIEncoderOptions = NULL;
2240  }
2241  }
2242  }
2243 
2244  if (SUCCEEDED(hr))
2245  {
2246  result = HeapAlloc(GetProcessHeap(), 0, sizeof(*result));
2247 
2248  if (result)
2249  {
2250  result->IWICBitmapFrameEncode_iface.lpVtbl = &TiffFrameEncode_Vtbl;
2251  result->ref = 1;
2252  result->parent = This;
2253  result->initialized = FALSE;
2254  result->info_written = FALSE;
2255  result->committed = FALSE;
2256  result->format = NULL;
2257  result->width = 0;
2258  result->height = 0;
2259  result->xres = 0.0;
2260  result->yres = 0.0;
2261  result->lines_written = 0;
2262  result->colors = 0;
2263 
2264  IWICBitmapEncoder_AddRef(iface);
2265  *ppIFrameEncode = &result->IWICBitmapFrameEncode_iface;
2266 
2267  if (This->num_frames != 0)
2268  pTIFFWriteDirectory(This->tiff);
2269 
2270  This->num_frames++;
2271  }
2272  else
2273  hr = E_OUTOFMEMORY;
2274 
2275  if (FAILED(hr))
2276  {
2277  IPropertyBag2_Release(*ppIEncoderOptions);
2278  *ppIEncoderOptions = NULL;
2279  }
2280  }
2281 
2282  LeaveCriticalSection(&This->lock);
2283 
2284  return hr;
2285 }
2286 
2287 static HRESULT WINAPI TiffEncoder_Commit(IWICBitmapEncoder *iface)
2288 {
2289  TiffEncoder *This = impl_from_IWICBitmapEncoder(iface);
2290 
2291  TRACE("(%p)\n", iface);
2292 
2293  EnterCriticalSection(&This->lock);
2294 
2295  if (!This->initialized || This->committed)
2296  {
2297  LeaveCriticalSection(&This->lock);
2298  return WINCODEC_ERR_WRONGSTATE;
2299  }
2300 
2301  pTIFFClose(This->tiff);
2302  IStream_Release(This->stream);
2303  This->stream = NULL;
2304  This->tiff = NULL;
2305 
2306  This->committed = TRUE;
2307 
2308  LeaveCriticalSection(&This->lock);
2309 
2310  return S_OK;
2311 }
2312 
2313 static HRESULT WINAPI TiffEncoder_GetMetadataQueryWriter(IWICBitmapEncoder *iface,
2314  IWICMetadataQueryWriter **ppIMetadataQueryWriter)
2315 {
2316  FIXME("(%p,%p): stub\n", iface, ppIMetadataQueryWriter);
2317  return E_NOTIMPL;
2318 }
2319 
2320 static const IWICBitmapEncoderVtbl TiffEncoder_Vtbl = {
2321  TiffEncoder_QueryInterface,
2322  TiffEncoder_AddRef,
2323  TiffEncoder_Release,
2324  TiffEncoder_Initialize,
2325  TiffEncoder_GetContainerFormat,
2326  TiffEncoder_GetEncoderInfo,
2327  TiffEncoder_SetColorContexts,
2328  TiffEncoder_SetPalette,
2329  TiffEncoder_SetThumbnail,
2330  TiffEncoder_SetPreview,
2331  TiffEncoder_CreateNewFrame,
2332  TiffEncoder_Commit,
2333  TiffEncoder_GetMetadataQueryWriter
2334 };
2335 
2337 {
2338  TiffEncoder *This;
2339  HRESULT ret;
2340 
2341  TRACE("(%s,%p)\n", debugstr_guid(iid), ppv);
2342 
2343  *ppv = NULL;
2344 
2345  if (!load_libtiff())
2346  {
2347  ERR("Failed writing TIFF because unable to load %s\n",SONAME_LIBTIFF);
2348  return E_FAIL;
2349  }
2350 
2351  This = HeapAlloc(GetProcessHeap(), 0, sizeof(TiffEncoder));
2352  if (!This) return E_OUTOFMEMORY;
2353 
2354  This->IWICBitmapEncoder_iface.lpVtbl = &TiffEncoder_Vtbl;
2355  This->ref = 1;
2356  This->stream = NULL;
2358  This->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": TiffEncoder.lock");
2359  This->tiff = NULL;
2360  This->initialized = FALSE;
2361  This->num_frames = 0;
2362  This->num_frames_committed = 0;
2363  This->committed = FALSE;
2364 
2365  ret = IWICBitmapEncoder_QueryInterface(&This->IWICBitmapEncoder_iface, iid, ppv);
2366  IWICBitmapEncoder_Release(&This->IWICBitmapEncoder_iface);
2367 
2368  return ret;
2369 }
2370 
2371 #else /* !SONAME_LIBTIFF */
2372 
2374 {
2375  ERR("Trying to load TIFF picture, but Wine was compiled without TIFF support.\n");
2376  return E_FAIL;
2377 }
2378 
2380 {
2381  ERR("Trying to save TIFF picture, but Wine was compiled without TIFF support.\n");
2382  return E_FAIL;
2383 }
2384 
2385 #endif
GLsizei samples
Definition: glext.h:7006
#define SEEK_CUR
Definition: util.h:63
GLint GLint GLsizei width
Definition: gl.h:1546
#define max(a, b)
Definition: svc.c:63
#define REFIID
Definition: guiddef.h:118
uint64 TIFFCurrentDirOffset(TIFF *tif)
Definition: tif_dir.c:1666
#define E_NOINTERFACE
Definition: winerror.h:2364
int TIFFReadDirectory(TIFF *tif)
Definition: tif_dirread.c:3574
#define TIFFTAG_BITSPERSAMPLE
Definition: tiff.h:156
rwlock_t lock
Definition: tcpcore.h:1163
#define TIFFTAG_ROWSPERSTRIP
Definition: tiff.h:233
#define DWORD_PTR
Definition: treelist.c:76
HRESULT hr
Definition: shlfolder.c:183
#define TIFFTAG_ICCPROFILE
Definition: tiff.h:440
#define TIFFTAG_COLORMAP
Definition: tiff.h:284
HRESULT TiffDecoder_CreateInstance(REFIID iid, void **ppv)
Definition: tiffformat.c:2373
tmsize_t TIFFReadEncodedTile(TIFF *tif, uint32 tile, void *buf, tmsize_t size)
Definition: tif_read.c:978
#define TRUE
Definition: types.h:120
#define TIFFTAG_EXTRASAMPLES
Definition: tiff.h:304
GLuint GLuint GLsizei count
Definition: gl.h:1545
unsigned int uint32
Definition: types.h:32
#define TIFFTAG_IMAGEWIDTH
Definition: tiff.h:154
#define TIFFTAG_YRESOLUTION
Definition: tiff.h:238
#define WARN(fmt,...)
Definition: debug.h:112
static const struct pixel_format_desc formats[]
Definition: util.c:57
GLintptr offset
Definition: glext.h:5920
uint64 toff_t
Definition: tiffio.h:66
REFIID LPVOID * ppv
Definition: atlbase.h:39
voidpf uLong int origin
Definition: ioapi.h:142
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
void * wine_dlsym(void *handle, const char *symbol, char *error, size_t errorsize)
Definition: loader.c:48
#define WINCODEC_ERR_NOTINITIALIZED
Definition: winerror.h:3277
GLuint GLuint end
Definition: gl.h:1545
void WINAPI VariantInit(VARIANTARG *pVarg)
Definition: variant.c:568
void WINAPI EnterCriticalSection(LPCRITICAL_SECTION)
WICBitmapEncoderCacheOption
Definition: wincodec.idl:69
static LPOLESTR
Definition: stg_prop.c:27
#define E_FAIL
Definition: ddrawi.h:102
#define TIFFTAG_PLANARCONFIG
Definition: tiff.h:239
int32_t INT
Definition: typedefs.h:58
int TIFFWriteScanline(TIFF *tif, void *buf, uint32 row, uint16 sample)
Definition: tif_write.c:47
Definition: send.c:48
& rect
Definition: startmenu.cpp:1413
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: gl.h:1546
Definition: tiffiop.h:115
int TIFFSetDirectory(TIFF *tif, uint16 dirn)
Definition: tif_dir.c:1617
void TIFFClose(TIFF *tif)
Definition: tif_close.c:122
int TIFFGetField(TIFF *tif, uint32 tag,...)
Definition: tif_dir.c:1232
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
const GUID * guid
#define E_OUTOFMEMORY
Definition: ddrawi.h:100
static const WCHAR wszCompressionQuality[]
Definition: converter.c:641
ULONGLONG QuadPart
Definition: ms-dtyp.idl:185
#define FALSE
Definition: types.h:117
#define TIFFTAG_TILEWIDTH
Definition: tiff.h:286
unsigned int BOOL
Definition: ntddk_ex.h:94
HRESULT write_source(IWICBitmapFrameEncode *iface, IWICBitmapSource *source, const WICRect *prc, const WICPixelFormatGUID *format, UINT bpp, INT width, INT height)
Definition: main.c:155
long LONG
Definition: pedump.c:60
static BmpFrameEncode * impl_from_IWICBitmapFrameEncode(IWICBitmapFrameEncode *iface)
Definition: bmpencode.c:84
GLenum GLint ref
Definition: glext.h:6028
#define FIXME(fmt,...)
Definition: debug.h:111
TIFF * TIFFClientOpen(const char *name, const char *mode, thandle_t clientdata, TIFFReadWriteProc readproc, TIFFReadWriteProc writeproc, TIFFSeekProc seekproc, TIFFCloseProc closeproc, TIFFSizeProc sizeproc, TIFFMapFileProc mapproc, TIFFUnmapFileProc unmapproc)
Definition: tif_open.c:71
#define TIFFTAG_TILELENGTH
Definition: tiff.h:287
#define E_INVALIDARG
Definition: ddrawi.h:101
int TIFFWriteDirectory(TIFF *tif)
Definition: tif_dirwrite.c:180
#define WINCODEC_ERR_PALETTEUNAVAILABLE
Definition: winerror.h:3284
VOID WINAPI InitializeCriticalSection(OUT LPCRITICAL_SECTION lpCriticalSection)
Definition: synch.c:751
smooth NULL
Definition: ftsmooth.c:416
void * wine_dlopen(const char *filename, int flag, char *error, size_t errorsize)
Definition: loader.c:53
static const WCHAR tiff[]
#define TIFFTAG_IMAGELENGTH
Definition: tiff.h:155
WINE_DEFAULT_DEBUG_CHANNEL(wincodecs)
#define TIFFTAG_SAMPLESPERPIXEL
Definition: tiff.h:232
GLuint index
Definition: glext.h:6031
INT Height
Definition: wincodec.idl:239
#define debugstr_guid
Definition: kernel32.h:35
GLclampf GLclampf blue
Definition: gl.h:1740
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
uint16 TIFFNumberOfDirectories(TIFF *tif)
Definition: tif_dir.c:1586
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
HRESULT CreateComponentInfo(REFCLSID clsid, IWICComponentInfo **ppIInfo)
Definition: info.c:2075
#define SEEK_SET
Definition: jmemansi.c:26
int byte_swapped
Definition: utils.c:251
#define LOAD_FUNCPTR(f)
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
#define TRACE(s)
Definition: solgame.cpp:4
GLsizeiptr size
Definition: glext.h:5919
#define GetProcessHeap()
Definition: compat.h:595
PVOID WINAPI HeapAlloc(HANDLE, DWORD, SIZE_T)
r parent
Definition: btrfs.c:2944
__wchar_t WCHAR
Definition: xmlstorage.h:180
static BmpEncoder * impl_from_IWICBitmapEncoder(IWICBitmapEncoder *iface)
Definition: bmpencode.c:433
void WINAPI DeleteCriticalSection(PCRITICAL_SECTION)
LONG HRESULT
Definition: typedefs.h:79
const GUID IID_IUnknown
#define V_UI1(A)
Definition: oleauto.h:266
static BOOL initialized
Definition: syslog.c:39
#define WINAPI
Definition: msvc.h:6
static BmpDecoder * impl_from_IWICBitmapDecoder(IWICBitmapDecoder *iface)
Definition: bmpdecode.c:83
GLclampf green
Definition: gl.h:1740
unsigned long DWORD
Definition: ntddk_ex.h:95
#define RTLD_NOW
Definition: port.h:100
#define red
Definition: linetest.c:67
static HRESULT create_metadata_reader(const void *data, int data_size, class_constructor constructor, IWICMetadataReader **reader)
Definition: gifformat.c:551
#define TIFFTAG_PHOTOMETRIC
Definition: tiff.h:195
#define WINCODEC_ERR_CODECNOTHUMBNAIL
Definition: winerror.h:3283
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
int ret
static double zero
Definition: j0_y0.c:96
#define WINCODEC_ERR_FRAMEMISSING
Definition: winerror.h:3293
HRESULT WINAPI DECLSPEC_HOTPATCH VariantClear(VARIANTARG *pVarg)
Definition: variant.c:648
GLenum const GLvoid * addr
Definition: glext.h:9621
Definition: compat.h:2158
#define index(s, c)
Definition: various.h:29
static UINT width_bytes(UINT width, UINT bpp)
Definition: tiffformat.c:888
#define InterlockedDecrement
Definition: armddk.h:52
Definition: parse.h:22
GLuint GLuint stream
Definition: glext.h:7522
#define SONAME_LIBTIFF
Definition: config.h:1266
static const char * debug_wic_rect(const WICRect *rect)
#define V_VT(A)
Definition: oleauto.h:211
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
GLenum GLsizei len
Definition: glext.h:6722
GLenum src
Definition: glext.h:6340
#define WINCODEC_ERR_UNSUPPORTEDOPERATION
Definition: winerror.h:3300
int isfinite(double x)
LIST_ENTRY ProcessLocksList
Definition: winbase.h:861
GLenum mode
Definition: glext.h:6217
tmsize_t tsize_t
Definition: tiffio.h:75
unsigned char BYTE
Definition: xxhash.c:193
static HPALETTE palette
Definition: clipboard.c:1345
GLint GLint GLsizei GLsizei height
Definition: gl.h:1546
void copy_pixels(const BYTE *src, UINT src_row_pitch, UINT src_slice_pitch, BYTE *dst, UINT dst_row_pitch, UINT dst_slice_pitch, const struct volume *size, const struct pixel_format_desc *format) DECLSPEC_HIDDEN
Definition: surface.c:1660
#define ERR(fmt,...)
Definition: debug.h:110
WICDecodeOptions
Definition: wincodec.idl:27
#define WINCODEC_ERR_WRONGSTATE
Definition: winerror.h:3273
#define S_OK
Definition: intsafe.h:51
tmsize_t TIFFReadEncodedStrip(TIFF *tif, uint32 strip, void *buf, tmsize_t size)
Definition: tif_read.c:527
static GpStatus get_decoder_info(IStream *stream, const struct image_codec **result)
Definition: image.c:4237
#define InterlockedIncrement
Definition: armddk.h:53
HRESULT configure_write_source(IWICBitmapFrameEncode *iface, IWICBitmapSource *source, const WICRect *prc, const WICPixelFormatGUID *format, INT width, INT height, double xres, double yres)
Definition: main.c:123
const GLdouble * v
Definition: gl.h:2040
int TIFFIsByteSwapped(TIFF *tif)
Definition: tif_open.c:639
static BmpDecoder * impl_from_IWICBitmapFrameDecode(IWICBitmapFrameDecode *iface)
Definition: bmpdecode.c:88
#define TIFFTAG_RESOLUTIONUNIT
Definition: tiff.h:262
#define byte(x, n)
Definition: tomcrypt.h:118
static calc_node_t temp
Definition: rpn_ieee.c:38
#define TIFFTAG_XRESOLUTION
Definition: tiff.h:237
HRESULT CreatePropertyBag2(const PROPBAG2 *options, UINT count, IPropertyBag2 **ppPropertyBag2)
Definition: propertybag.c:281
#define ARRAY_SIZE(a)
Definition: main.h:24
unsigned short uint16
Definition: types.h:30
#define WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT
Definition: winerror.h:3299
#define E_NOTIMPL
Definition: ddrawi.h:99
HRESULT TiffEncoder_CreateInstance(REFIID iid, void **ppv)
Definition: tiffformat.c:2379
GLenum GLenum dst
Definition: glext.h:6340
static GifDecoder * impl_from_IWICMetadataBlockReader(IWICMetadataBlockReader *iface)
Definition: gifformat.c:607
#define MAKE_FUNCPTR(f)
unsigned int UINT
Definition: ndis.h:50
BOOL WINAPI IsEqualGUID(REFGUID rguid1, REFGUID rguid2)
Definition: compobj.c:4112
GLint GLint GLint GLint GLint GLint y
Definition: gl.h:1548
Definition: reader.h:83
static const WCHAR wszTiffCompressionMethod[]
Definition: converter.c:640
INT Width
Definition: wincodec.idl:238
static void swap_bytes(void *buf, size_t samplesize, size_t samplecount)
GLuint res
Definition: glext.h:9613
unsigned int ULONG
Definition: retypes.h:1
#define SEEK_END
Definition: cabinet.c:27
void reverse_bgr8(UINT bytesperpixel, LPBYTE bits, UINT width, UINT height, INT stride)
Definition: main.c:212
#define profile
Definition: kernel32.h:12
DWORD bpp
Definition: surface.c:182
void WINAPI LeaveCriticalSection(LPCRITICAL_SECTION)
HRESULT IfdMetadataReader_CreateInstance(REFIID iid, void **ppv)
void exit(int exitcode)
Definition: _exit.c:33
HRESULT MetadataQueryReader_CreateInstance(IWICMetadataBlockReader *mbr, const WCHAR *root, IWICMetadataQueryReader **out)
_Out_ LPRECT prc
Definition: ntgdi.h:1658
GLuint64EXT * result
Definition: glext.h:11304
UINT32 WICColor
Definition: wincodec.idl:250
int TIFFSetField(TIFF *tif, uint32 tag,...)
Definition: tif_dir.c:807
#define HeapFree(x, y, z)
Definition: compat.h:594
#define IsEqualIID(riid1, riid2)
Definition: guiddef.h:95
#define SUCCEEDED(hr)
Definition: intsafe.h:49
LONGLONG QuadPart
Definition: typedefs.h:114
struct png_info_def *typedef unsigned char **typedef struct png_info_def *typedef struct png_info_def *typedef struct png_info_def *typedef unsigned char ** row
Definition: typeof.h:78