ReactOS  0.4.14-dev-342-gdc047f9
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 
293  ret = pTIFFGetField(tiff, TIFFTAG_PHOTOMETRIC, &photometric);
294  if (!ret)
295  {
296  WARN("missing PhotometricInterpretation tag\n");
297  return E_FAIL;
298  }
299 
300  ret = pTIFFGetField(tiff, TIFFTAG_BITSPERSAMPLE, &bps);
301  if (!ret) bps = 1;
302  decode_info->bps = bps;
303 
304  ret = pTIFFGetField(tiff, TIFFTAG_SAMPLESPERPIXEL, &samples);
305  if (!ret) samples = 1;
306  decode_info->samples = samples;
307 
308  if (samples == 1)
309  planar = 1;
310  else
311  {
312  ret = pTIFFGetField(tiff, TIFFTAG_PLANARCONFIG, &planar);
313  if (!ret) planar = 1;
314  if (planar != 1)
315  {
316  FIXME("unhandled planar configuration %u\n", planar);
317  return E_FAIL;
318  }
319  }
320  decode_info->planar = planar;
321 
322  TRACE("planar %u, photometric %u, samples %u, bps %u\n", planar, photometric, samples, bps);
323 
324  switch(photometric)
325  {
326  case 0: /* WhiteIsZero */
327  decode_info->invert_grayscale = 1;
328  /* fall through */
329  case 1: /* BlackIsZero */
330  if (samples == 2)
331  {
332  ret = pTIFFGetField(tiff, TIFFTAG_EXTRASAMPLES, &extra_sample_count, &extra_samples);
333  if (!ret)
334  {
335  extra_sample_count = 1;
336  extra_sample = 0;
337  extra_samples = &extra_sample;
338  }
339  }
340  else if (samples != 1)
341  {
342  FIXME("unhandled %dbpp sample count %u\n", bps, samples);
343  return E_FAIL;
344  }
345 
346  decode_info->bpp = bps * samples;
347  decode_info->source_bpp = decode_info->bpp;
348  switch (bps)
349  {
350  case 1:
351  if (samples != 1)
352  {
353  FIXME("unhandled 1bpp sample count %u\n", samples);
354  return E_FAIL;
355  }
356  decode_info->format = &GUID_WICPixelFormatBlackWhite;
357  break;
358  case 4:
359  if (samples != 1)
360  {
361  FIXME("unhandled 4bpp grayscale sample count %u\n", samples);
362  return E_FAIL;
363  }
364  decode_info->format = &GUID_WICPixelFormat4bppGray;
365  break;
366  case 8:
367  if (samples == 1)
368  decode_info->format = &GUID_WICPixelFormat8bppGray;
369  else
370  {
371  decode_info->bpp = 32;
372 
373  switch(extra_samples[0])
374  {
375  case 1: /* Associated (pre-multiplied) alpha data */
376  decode_info->format = &GUID_WICPixelFormat32bppPBGRA;
377  break;
378  case 0: /* Unspecified data */
379  case 2: /* Unassociated alpha data */
380  decode_info->format = &GUID_WICPixelFormat32bppBGRA;
381  break;
382  default:
383  FIXME("unhandled extra sample type %u\n", extra_samples[0]);
384  return E_FAIL;
385  }
386  }
387  break;
388  case 16:
389  if (samples != 1)
390  {
391  FIXME("unhandled 16bpp grayscale sample count %u\n", samples);
393  }
394  decode_info->format = &GUID_WICPixelFormat16bppGray;
395  break;
396  case 32:
397  if (samples != 1)
398  {
399  FIXME("unhandled 32bpp grayscale sample count %u\n", samples);
401  }
402  decode_info->format = &GUID_WICPixelFormat32bppGrayFloat;
403  break;
404  default:
405  WARN("unhandled greyscale bit count %u\n", bps);
407  }
408  break;
409  case 2: /* RGB */
410  if (samples == 4)
411  {
412  ret = pTIFFGetField(tiff, TIFFTAG_EXTRASAMPLES, &extra_sample_count, &extra_samples);
413  if (!ret)
414  {
415  extra_sample_count = 1;
416  extra_sample = 0;
417  extra_samples = &extra_sample;
418  }
419  }
420  else if (samples != 3)
421  {
422  FIXME("unhandled RGB sample count %u\n", samples);
423  return E_FAIL;
424  }
425 
426  decode_info->bpp = max(bps, 8) * samples;
427  decode_info->source_bpp = bps * samples;
428  switch(bps)
429  {
430  case 1:
431  case 4:
432  case 8:
433  decode_info->reverse_bgr = 1;
434  if (samples == 3)
435  decode_info->format = &GUID_WICPixelFormat24bppBGR;
436  else
437  switch(extra_samples[0])
438  {
439  case 1: /* Associated (pre-multiplied) alpha data */
440  decode_info->format = &GUID_WICPixelFormat32bppPBGRA;
441  break;
442  case 0: /* Unspecified data */
443  case 2: /* Unassociated alpha data */
444  decode_info->format = &GUID_WICPixelFormat32bppBGRA;
445  break;
446  default:
447  FIXME("unhandled extra sample type %i\n", extra_samples[0]);
448  return E_FAIL;
449  }
450  break;
451  case 16:
452  if (samples == 3)
453  decode_info->format = &GUID_WICPixelFormat48bppRGB;
454  else
455  switch(extra_samples[0])
456  {
457  case 1: /* Associated (pre-multiplied) alpha data */
458  decode_info->format = &GUID_WICPixelFormat64bppPRGBA;
459  break;
460  case 0: /* Unspecified data */
461  case 2: /* Unassociated alpha data */
462  decode_info->format = &GUID_WICPixelFormat64bppRGBA;
463  break;
464  default:
465  FIXME("unhandled extra sample type %i\n", extra_samples[0]);
466  return E_FAIL;
467  }
468  break;
469  case 32:
470  if (samples != 4)
471  {
472  FIXME("unhandled 32bpp RGB sample count %u\n", samples);
474  }
475  decode_info->format = &GUID_WICPixelFormat128bppRGBAFloat;
476  break;
477  default:
478  WARN("unhandled RGB bit count %u\n", bps);
480  }
481  break;
482  case 3: /* RGB Palette */
483  if (samples != 1)
484  {
485  FIXME("unhandled indexed sample count %u\n", samples);
486  return E_FAIL;
487  }
488 
489  decode_info->indexed = 1;
490  decode_info->bpp = bps;
491  switch (bps)
492  {
493  case 1:
494  decode_info->format = &GUID_WICPixelFormat1bppIndexed;
495  break;
496  case 2:
497  decode_info->format = &GUID_WICPixelFormat2bppIndexed;
498  break;
499  case 4:
500  decode_info->format = &GUID_WICPixelFormat4bppIndexed;
501  break;
502  case 8:
503  decode_info->format = &GUID_WICPixelFormat8bppIndexed;
504  break;
505  default:
506  FIXME("unhandled indexed bit count %u\n", bps);
507  return E_NOTIMPL;
508  }
509  break;
510 
511  case 5: /* Separated */
512  if (samples != 4)
513  {
514  FIXME("unhandled Separated sample count %u\n", samples);
515  return E_FAIL;
516  }
517 
518  decode_info->bpp = bps * samples;
519  switch(bps)
520  {
521  case 8:
522  decode_info->format = &GUID_WICPixelFormat32bppCMYK;
523  break;
524  case 16:
525  decode_info->format = &GUID_WICPixelFormat64bppCMYK;
526  break;
527 
528  default:
529  WARN("unhandled Separated bit count %u\n", bps);
531  }
532  break;
533 
534  case 4: /* Transparency mask */
535  case 6: /* YCbCr */
536  case 8: /* CIELab */
537  default:
538  FIXME("unhandled PhotometricInterpretation %u\n", photometric);
539  return E_FAIL;
540  }
541 
542  ret = pTIFFGetField(tiff, TIFFTAG_IMAGEWIDTH, &decode_info->width);
543  if (!ret)
544  {
545  WARN("missing image width\n");
546  return E_FAIL;
547  }
548 
549  ret = pTIFFGetField(tiff, TIFFTAG_IMAGELENGTH, &decode_info->height);
550  if (!ret)
551  {
552  WARN("missing image length\n");
553  return E_FAIL;
554  }
555 
556  if ((ret = pTIFFGetField(tiff, TIFFTAG_TILEWIDTH, &decode_info->tile_width)))
557  {
558  decode_info->tiled = 1;
559 
560  ret = pTIFFGetField(tiff, TIFFTAG_TILELENGTH, &decode_info->tile_height);
561  if (!ret)
562  {
563  WARN("missing tile height\n");
564  return E_FAIL;
565  }
566 
567  decode_info->tile_stride = ((decode_info->bpp * decode_info->tile_width + 7)/8);
568  decode_info->tile_size = decode_info->tile_height * decode_info->tile_stride;
569  decode_info->tiles_across = (decode_info->width + decode_info->tile_width - 1) / decode_info->tile_width;
570  }
571  else if ((ret = pTIFFGetField(tiff, TIFFTAG_ROWSPERSTRIP, &decode_info->tile_height)))
572  {
573  if (decode_info->tile_height > decode_info->height)
574  decode_info->tile_height = decode_info->height;
575  decode_info->tile_width = decode_info->width;
576  decode_info->tile_stride = ((decode_info->bpp * decode_info->tile_width + 7)/8);
577  decode_info->tile_size = decode_info->tile_height * decode_info->tile_stride;
578  }
579  else
580  {
581  /* Some broken TIFF files have a single strip and lack the RowsPerStrip tag */
582  decode_info->tile_height = decode_info->height;
583  decode_info->tile_width = decode_info->width;
584  decode_info->tile_stride = ((decode_info->bpp * decode_info->tile_width + 7)/8);
585  decode_info->tile_size = decode_info->tile_height * decode_info->tile_stride;
586  }
587 
588  decode_info->resolution_unit = 0;
589  pTIFFGetField(tiff, TIFFTAG_RESOLUTIONUNIT, &decode_info->resolution_unit);
590 
591  ret = pTIFFGetField(tiff, TIFFTAG_XRESOLUTION, &decode_info->xres);
592  if (!ret)
593  {
594  WARN("missing X resolution\n");
595  }
596  /* Emulate the behavior of current libtiff versions (libtiff commit a39f6131)
597  * yielding 0 instead of INFINITY for IFD_RATIONAL fields with denominator 0. */
598  if (!isfinite(decode_info->xres))
599  {
600  decode_info->xres = 0.0;
601  }
602 
603  ret = pTIFFGetField(tiff, TIFFTAG_YRESOLUTION, &decode_info->yres);
604  if (!ret)
605  {
606  WARN("missing Y resolution\n");
607  }
608  if (!isfinite(decode_info->yres))
609  {
610  decode_info->yres = 0.0;
611  }
612 
613  return S_OK;
614 }
615 
616 static HRESULT WINAPI TiffDecoder_QueryInterface(IWICBitmapDecoder *iface, REFIID iid,
617  void **ppv)
618 {
619  TiffDecoder *This = impl_from_IWICBitmapDecoder(iface);
620  TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
621 
622  if (!ppv) return E_INVALIDARG;
623 
624  if (IsEqualIID(&IID_IUnknown, iid) ||
625  IsEqualIID(&IID_IWICBitmapDecoder, iid))
626  {
627  *ppv = &This->IWICBitmapDecoder_iface;
628  }
629  else
630  {
631  *ppv = NULL;
632  return E_NOINTERFACE;
633  }
634 
635  IUnknown_AddRef((IUnknown*)*ppv);
636  return S_OK;
637 }
638 
639 static ULONG WINAPI TiffDecoder_AddRef(IWICBitmapDecoder *iface)
640 {
641  TiffDecoder *This = impl_from_IWICBitmapDecoder(iface);
643 
644  TRACE("(%p) refcount=%u\n", iface, ref);
645 
646  return ref;
647 }
648 
649 static ULONG WINAPI TiffDecoder_Release(IWICBitmapDecoder *iface)
650 {
651  TiffDecoder *This = impl_from_IWICBitmapDecoder(iface);
653 
654  TRACE("(%p) refcount=%u\n", iface, ref);
655 
656  if (ref == 0)
657  {
658  if (This->tiff) pTIFFClose(This->tiff);
659  if (This->stream) IStream_Release(This->stream);
660  This->lock.DebugInfo->Spare[0] = 0;
661  DeleteCriticalSection(&This->lock);
663  }
664 
665  return ref;
666 }
667 
668 static HRESULT WINAPI TiffDecoder_QueryCapability(IWICBitmapDecoder *iface, IStream *stream,
669  DWORD *capability)
670 {
671  HRESULT hr;
672 
673  TRACE("(%p,%p,%p)\n", iface, stream, capability);
674 
675  if (!stream || !capability) return E_INVALIDARG;
676 
677  hr = IWICBitmapDecoder_Initialize(iface, stream, WICDecodeMetadataCacheOnDemand);
678  if (hr != S_OK) return hr;
679 
683  return S_OK;
684 }
685 
686 static HRESULT WINAPI TiffDecoder_Initialize(IWICBitmapDecoder *iface, IStream *pIStream,
687  WICDecodeOptions cacheOptions)
688 {
689  TiffDecoder *This = impl_from_IWICBitmapDecoder(iface);
690  TIFF *tiff;
691  tiff_decode_info decode_info;
692  HRESULT hr=S_OK;
693 
694  TRACE("(%p,%p,%x)\n", iface, pIStream, cacheOptions);
695 
696  EnterCriticalSection(&This->lock);
697 
698  if (This->initialized)
699  {
701  goto exit;
702  }
703 
704  tiff = tiff_open_stream(pIStream, "r");
705  if (!tiff)
706  {
707  hr = E_FAIL;
708  goto exit;
709  }
710 
711  /* make sure that TIFF format is supported */
712  hr = tiff_get_decode_info(tiff, &decode_info);
713  if (hr != S_OK)
714  {
715  pTIFFClose(tiff);
716  goto exit;
717  }
718 
719  This->tiff = tiff;
720  This->stream = pIStream;
721  IStream_AddRef(pIStream);
722  This->initialized = TRUE;
723 
724 exit:
725  LeaveCriticalSection(&This->lock);
726  return hr;
727 }
728 
729 static HRESULT WINAPI TiffDecoder_GetContainerFormat(IWICBitmapDecoder *iface,
730  GUID *pguidContainerFormat)
731 {
732  if (!pguidContainerFormat) return E_INVALIDARG;
733 
734  memcpy(pguidContainerFormat, &GUID_ContainerFormatTiff, sizeof(GUID));
735  return S_OK;
736 }
737 
738 static HRESULT WINAPI TiffDecoder_GetDecoderInfo(IWICBitmapDecoder *iface,
739  IWICBitmapDecoderInfo **ppIDecoderInfo)
740 {
741  TRACE("(%p,%p)\n", iface, ppIDecoderInfo);
742 
743  return get_decoder_info(&CLSID_WICTiffDecoder, ppIDecoderInfo);
744 }
745 
746 static HRESULT WINAPI TiffDecoder_CopyPalette(IWICBitmapDecoder *iface,
748 {
749  TRACE("(%p,%p)\n", iface, palette);
751 }
752 
753 static HRESULT WINAPI TiffDecoder_GetMetadataQueryReader(IWICBitmapDecoder *iface,
754  IWICMetadataQueryReader **ppIMetadataQueryReader)
755 {
756  TRACE("(%p,%p)\n", iface, ppIMetadataQueryReader);
757 
758  if (!ppIMetadataQueryReader) return E_INVALIDARG;
759 
760  *ppIMetadataQueryReader = NULL;
762 }
763 
764 static HRESULT WINAPI TiffDecoder_GetPreview(IWICBitmapDecoder *iface,
765  IWICBitmapSource **ppIBitmapSource)
766 {
767  TRACE("(%p,%p)\n", iface, ppIBitmapSource);
768 
769  if (!ppIBitmapSource) return E_INVALIDARG;
770 
771  *ppIBitmapSource = NULL;
773 }
774 
775 static HRESULT WINAPI TiffDecoder_GetColorContexts(IWICBitmapDecoder *iface,
776  UINT cCount, IWICColorContext **ppIColorContexts, UINT *pcActualCount)
777 {
778  FIXME("(%p,%u,%p,%p)\n", iface, cCount, ppIColorContexts, pcActualCount);
780 }
781 
782 static HRESULT WINAPI TiffDecoder_GetThumbnail(IWICBitmapDecoder *iface,
783  IWICBitmapSource **ppIThumbnail)
784 {
785  TRACE("(%p,%p)\n", iface, ppIThumbnail);
786 
787  if (!ppIThumbnail) return E_INVALIDARG;
788 
789  *ppIThumbnail = NULL;
791 }
792 
793 static HRESULT WINAPI TiffDecoder_GetFrameCount(IWICBitmapDecoder *iface,
794  UINT *pCount)
795 {
796  TiffDecoder *This = impl_from_IWICBitmapDecoder(iface);
797 
798  if (!pCount) return E_INVALIDARG;
799 
800  EnterCriticalSection(&This->lock);
801  *pCount = This->tiff ? pTIFFNumberOfDirectories(This->tiff) : 0;
802  LeaveCriticalSection(&This->lock);
803 
804  TRACE("(%p) <-- %i\n", iface, *pCount);
805 
806  return S_OK;
807 }
808 
809 static HRESULT WINAPI TiffDecoder_GetFrame(IWICBitmapDecoder *iface,
810  UINT index, IWICBitmapFrameDecode **ppIBitmapFrame)
811 {
812  TiffDecoder *This = impl_from_IWICBitmapDecoder(iface);
813  TiffFrameDecode *result;
814  int res;
815  tiff_decode_info decode_info;
816  HRESULT hr;
817 
818  TRACE("(%p,%u,%p)\n", iface, index, ppIBitmapFrame);
819 
820  if (!This->tiff)
822 
823  EnterCriticalSection(&This->lock);
824  res = pTIFFSetDirectory(This->tiff, index);
825  if (!res) hr = E_INVALIDARG;
826  else hr = tiff_get_decode_info(This->tiff, &decode_info);
827  LeaveCriticalSection(&This->lock);
828 
829  if (SUCCEEDED(hr))
830  {
831  result = HeapAlloc(GetProcessHeap(), 0, sizeof(TiffFrameDecode));
832 
833  if (result)
834  {
835  result->IWICBitmapFrameDecode_iface.lpVtbl = &TiffFrameDecode_Vtbl;
836  result->IWICMetadataBlockReader_iface.lpVtbl = &TiffFrameDecode_BlockVtbl;
837  result->ref = 1;
838  result->parent = This;
839  IWICBitmapDecoder_AddRef(iface);
840  result->index = index;
841  result->decode_info = decode_info;
842  result->cached_tile_x = -1;
843  result->cached_tile = HeapAlloc(GetProcessHeap(), 0, decode_info.tile_size);
844 
845  if (result->cached_tile)
846  *ppIBitmapFrame = &result->IWICBitmapFrameDecode_iface;
847  else
848  {
849  hr = E_OUTOFMEMORY;
850  IWICBitmapFrameDecode_Release(&result->IWICBitmapFrameDecode_iface);
851  }
852  }
853  else hr = E_OUTOFMEMORY;
854  }
855 
856  if (FAILED(hr)) *ppIBitmapFrame = NULL;
857 
858  return hr;
859 }
860 
861 static const IWICBitmapDecoderVtbl TiffDecoder_Vtbl = {
862  TiffDecoder_QueryInterface,
863  TiffDecoder_AddRef,
864  TiffDecoder_Release,
865  TiffDecoder_QueryCapability,
866  TiffDecoder_Initialize,
867  TiffDecoder_GetContainerFormat,
868  TiffDecoder_GetDecoderInfo,
869  TiffDecoder_CopyPalette,
870  TiffDecoder_GetMetadataQueryReader,
871  TiffDecoder_GetPreview,
872  TiffDecoder_GetColorContexts,
873  TiffDecoder_GetThumbnail,
874  TiffDecoder_GetFrameCount,
875  TiffDecoder_GetFrame
876 };
877 
878 static HRESULT WINAPI TiffFrameDecode_QueryInterface(IWICBitmapFrameDecode *iface, REFIID iid,
879  void **ppv)
880 {
881  TiffFrameDecode *This = impl_from_IWICBitmapFrameDecode(iface);
882  TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
883 
884  if (!ppv) return E_INVALIDARG;
885 
886  if (IsEqualIID(&IID_IUnknown, iid) ||
887  IsEqualIID(&IID_IWICBitmapSource, iid) ||
888  IsEqualIID(&IID_IWICBitmapFrameDecode, iid))
889  {
890  *ppv = &This->IWICBitmapFrameDecode_iface;
891  }
892  else if (IsEqualIID(&IID_IWICMetadataBlockReader, iid))
893  {
894  *ppv = &This->IWICMetadataBlockReader_iface;
895  }
896  else
897  {
898  *ppv = NULL;
899  return E_NOINTERFACE;
900  }
901 
902  IUnknown_AddRef((IUnknown*)*ppv);
903  return S_OK;
904 }
905 
906 static ULONG WINAPI TiffFrameDecode_AddRef(IWICBitmapFrameDecode *iface)
907 {
908  TiffFrameDecode *This = impl_from_IWICBitmapFrameDecode(iface);
910 
911  TRACE("(%p) refcount=%u\n", iface, ref);
912 
913  return ref;
914 }
915 
916 static ULONG WINAPI TiffFrameDecode_Release(IWICBitmapFrameDecode *iface)
917 {
918  TiffFrameDecode *This = impl_from_IWICBitmapFrameDecode(iface);
920 
921  TRACE("(%p) refcount=%u\n", iface, ref);
922 
923  if (ref == 0)
924  {
925  IWICBitmapDecoder_Release(&This->parent->IWICBitmapDecoder_iface);
926  HeapFree(GetProcessHeap(), 0, This->cached_tile);
928  }
929 
930  return ref;
931 }
932 
933 static HRESULT WINAPI TiffFrameDecode_GetSize(IWICBitmapFrameDecode *iface,
934  UINT *puiWidth, UINT *puiHeight)
935 {
936  TiffFrameDecode *This = impl_from_IWICBitmapFrameDecode(iface);
937 
938  *puiWidth = This->decode_info.width;
939  *puiHeight = This->decode_info.height;
940 
941  TRACE("(%p) <-- %ux%u\n", iface, *puiWidth, *puiHeight);
942 
943  return S_OK;
944 }
945 
946 static HRESULT WINAPI TiffFrameDecode_GetPixelFormat(IWICBitmapFrameDecode *iface,
947  WICPixelFormatGUID *pPixelFormat)
948 {
949  TiffFrameDecode *This = impl_from_IWICBitmapFrameDecode(iface);
950 
951  memcpy(pPixelFormat, This->decode_info.format, sizeof(GUID));
952 
953  TRACE("(%p) <-- %s\n", This, debugstr_guid(This->decode_info.format));
954 
955  return S_OK;
956 }
957 
958 static HRESULT WINAPI TiffFrameDecode_GetResolution(IWICBitmapFrameDecode *iface,
959  double *pDpiX, double *pDpiY)
960 {
961  TiffFrameDecode *This = impl_from_IWICBitmapFrameDecode(iface);
962 
963  if (This->decode_info.xres == 0 || This->decode_info.yres == 0)
964  {
965  *pDpiX = *pDpiY = 96.0;
966  }
967  else
968  {
969  switch (This->decode_info.resolution_unit)
970  {
971  default:
972  FIXME("unknown resolution unit %i\n", This->decode_info.resolution_unit);
973  /* fall through */
974  case 0: /* Not set */
975  case 1: /* Relative measurements */
976  case 2: /* Inch */
977  *pDpiX = This->decode_info.xres;
978  *pDpiY = This->decode_info.yres;
979  break;
980  case 3: /* Centimeter */
981  *pDpiX = This->decode_info.xres * 2.54;
982  *pDpiY = This->decode_info.yres * 2.54;
983  break;
984  }
985  }
986 
987  TRACE("(%p) <-- %f,%f unit=%i\n", iface, *pDpiX, *pDpiY, This->decode_info.resolution_unit);
988 
989  return S_OK;
990 }
991 
992 static HRESULT WINAPI TiffFrameDecode_CopyPalette(IWICBitmapFrameDecode *iface,
993  IWICPalette *pIPalette)
994 {
995  TiffFrameDecode *This = impl_from_IWICBitmapFrameDecode(iface);
996  uint16 *red, *green, *blue;
997  WICColor colors[256];
998  int color_count, ret, i;
999 
1000  TRACE("(%p,%p)\n", iface, pIPalette);
1001 
1002  color_count = 1<<This->decode_info.bps;
1003 
1004  EnterCriticalSection(&This->parent->lock);
1005  ret = pTIFFGetField(This->parent->tiff, TIFFTAG_COLORMAP, &red, &green, &blue);
1006  LeaveCriticalSection(&This->parent->lock);
1007 
1008  if (!ret)
1009  {
1010  WARN("Couldn't read color map\n");
1012  }
1013 
1014  for (i=0; i<color_count; i++)
1015  {
1016  colors[i] = 0xff000000 |
1017  ((red[i]<<8) & 0xff0000) |
1018  (green[i] & 0xff00) |
1019  ((blue[i]>>8) & 0xff);
1020  }
1021 
1022  return IWICPalette_InitializeCustom(pIPalette, colors, color_count);
1023 }
1024 
1025 static HRESULT TiffFrameDecode_ReadTile(TiffFrameDecode *This, UINT tile_x, UINT tile_y)
1026 {
1027  tsize_t ret;
1028  int swap_bytes;
1029 
1030  swap_bytes = pTIFFIsByteSwapped(This->parent->tiff);
1031 
1032  ret = pTIFFSetDirectory(This->parent->tiff, This->index);
1033  if (ret == -1)
1034  return E_FAIL;
1035 
1036  if (This->decode_info.tiled)
1037  ret = pTIFFReadEncodedTile(This->parent->tiff, tile_x + tile_y * This->decode_info.tiles_across, This->cached_tile, This->decode_info.tile_size);
1038  else
1039  ret = pTIFFReadEncodedStrip(This->parent->tiff, tile_y, This->cached_tile, This->decode_info.tile_size);
1040 
1041  if (ret == -1)
1042  return E_FAIL;
1043 
1044  /* 3bpp RGB */
1045  if (This->decode_info.source_bpp == 3 && This->decode_info.samples == 3 && This->decode_info.bpp == 24)
1046  {
1047  BYTE *srcdata, *src, *dst;
1048  DWORD x, y, count, width_bytes = (This->decode_info.tile_width * 3 + 7) / 8;
1049 
1050  count = width_bytes * This->decode_info.tile_height;
1051 
1052  srcdata = HeapAlloc(GetProcessHeap(), 0, count);
1053  if (!srcdata) return E_OUTOFMEMORY;
1054  memcpy(srcdata, This->cached_tile, count);
1055 
1056  for (y = 0; y < This->decode_info.tile_height; y++)
1057  {
1058  src = srcdata + y * width_bytes;
1059  dst = This->cached_tile + y * This->decode_info.tile_width * 3;
1060 
1061  for (x = 0; x < This->decode_info.tile_width; x += 8)
1062  {
1063  dst[2] = (src[0] & 0x80) ? 0xff : 0; /* R */
1064  dst[1] = (src[0] & 0x40) ? 0xff : 0; /* G */
1065  dst[0] = (src[0] & 0x20) ? 0xff : 0; /* B */
1066  if (x + 1 < This->decode_info.tile_width)
1067  {
1068  dst[5] = (src[0] & 0x10) ? 0xff : 0; /* R */
1069  dst[4] = (src[0] & 0x08) ? 0xff : 0; /* G */
1070  dst[3] = (src[0] & 0x04) ? 0xff : 0; /* B */
1071  }
1072  if (x + 2 < This->decode_info.tile_width)
1073  {
1074  dst[8] = (src[0] & 0x02) ? 0xff : 0; /* R */
1075  dst[7] = (src[0] & 0x01) ? 0xff : 0; /* G */
1076  dst[6] = (src[1] & 0x80) ? 0xff : 0; /* B */
1077  }
1078  if (x + 3 < This->decode_info.tile_width)
1079  {
1080  dst[11] = (src[1] & 0x40) ? 0xff : 0; /* R */
1081  dst[10] = (src[1] & 0x20) ? 0xff : 0; /* G */
1082  dst[9] = (src[1] & 0x10) ? 0xff : 0; /* B */
1083  }
1084  if (x + 4 < This->decode_info.tile_width)
1085  {
1086  dst[14] = (src[1] & 0x08) ? 0xff : 0; /* R */
1087  dst[13] = (src[1] & 0x04) ? 0xff : 0; /* G */
1088  dst[12] = (src[1] & 0x02) ? 0xff : 0; /* B */
1089  }
1090  if (x + 5 < This->decode_info.tile_width)
1091  {
1092  dst[17] = (src[1] & 0x01) ? 0xff : 0; /* R */
1093  dst[16] = (src[2] & 0x80) ? 0xff : 0; /* G */
1094  dst[15] = (src[2] & 0x40) ? 0xff : 0; /* B */
1095  }
1096  if (x + 6 < This->decode_info.tile_width)
1097  {
1098  dst[20] = (src[2] & 0x20) ? 0xff : 0; /* R */
1099  dst[19] = (src[2] & 0x10) ? 0xff : 0; /* G */
1100  dst[18] = (src[2] & 0x08) ? 0xff : 0; /* B */
1101  }
1102  if (x + 7 < This->decode_info.tile_width)
1103  {
1104  dst[23] = (src[2] & 0x04) ? 0xff : 0; /* R */
1105  dst[22] = (src[2] & 0x02) ? 0xff : 0; /* G */
1106  dst[21] = (src[2] & 0x01) ? 0xff : 0; /* B */
1107  }
1108  src += 3;
1109  dst += 24;
1110  }
1111  }
1112 
1113  HeapFree(GetProcessHeap(), 0, srcdata);
1114  }
1115  /* 12bpp RGB */
1116  else if (This->decode_info.source_bpp == 12 && This->decode_info.samples == 3 && This->decode_info.bpp == 24)
1117  {
1118  BYTE *srcdata, *src, *dst;
1119  DWORD x, y, count, width_bytes = (This->decode_info.tile_width * 12 + 7) / 8;
1120 
1121  count = width_bytes * This->decode_info.tile_height;
1122 
1123  srcdata = HeapAlloc(GetProcessHeap(), 0, count);
1124  if (!srcdata) return E_OUTOFMEMORY;
1125  memcpy(srcdata, This->cached_tile, count);
1126 
1127  for (y = 0; y < This->decode_info.tile_height; y++)
1128  {
1129  src = srcdata + y * width_bytes;
1130  dst = This->cached_tile + y * This->decode_info.tile_width * 3;
1131 
1132  for (x = 0; x < This->decode_info.tile_width; x += 2)
1133  {
1134  dst[0] = ((src[1] & 0xf0) >> 4) * 17; /* B */
1135  dst[1] = (src[0] & 0x0f) * 17; /* G */
1136  dst[2] = ((src[0] & 0xf0) >> 4) * 17; /* R */
1137  if (x + 1 < This->decode_info.tile_width)
1138  {
1139  dst[5] = (src[1] & 0x0f) * 17; /* B */
1140  dst[4] = ((src[2] & 0xf0) >> 4) * 17; /* G */
1141  dst[3] = (src[2] & 0x0f) * 17; /* R */
1142  }
1143  src += 3;
1144  dst += 6;
1145  }
1146  }
1147 
1148  HeapFree(GetProcessHeap(), 0, srcdata);
1149  }
1150  /* 4bpp RGBA */
1151  else if (This->decode_info.source_bpp == 4 && This->decode_info.samples == 4 && This->decode_info.bpp == 32)
1152  {
1153  BYTE *src, *dst;
1154  DWORD count;
1155 
1156  /* 1 source byte expands to 2 BGRA samples */
1157  count = (This->decode_info.tile_width * This->decode_info.tile_height + 1) / 2;
1158 
1159  src = This->cached_tile + count - 1;
1160  dst = This->cached_tile + This->decode_info.tile_size;
1161 
1162  while (count--)
1163  {
1164  BYTE b = *src--;
1165 
1166  dst -= 8;
1167  dst[2] = (b & 0x80) ? 0xff : 0; /* R */
1168  dst[1] = (b & 0x40) ? 0xff : 0; /* G */
1169  dst[0] = (b & 0x20) ? 0xff : 0; /* B */
1170  dst[3] = (b & 0x10) ? 0xff : 0; /* A */
1171  dst[6] = (b & 0x08) ? 0xff : 0; /* R */
1172  dst[5] = (b & 0x04) ? 0xff : 0; /* G */
1173  dst[4] = (b & 0x02) ? 0xff : 0; /* B */
1174  dst[7] = (b & 0x01) ? 0xff : 0; /* A */
1175  }
1176  }
1177  /* 16bpp RGBA */
1178  else if (This->decode_info.source_bpp == 16 && This->decode_info.samples == 4 && This->decode_info.bpp == 32)
1179  {
1180  BYTE *src, *dst;
1181  DWORD count = This->decode_info.tile_width * This->decode_info.tile_height;
1182 
1183  src = This->cached_tile + count * 2;
1184  dst = This->cached_tile + This->decode_info.tile_size;
1185 
1186  while (count--)
1187  {
1188  BYTE b[2];
1189 
1190  src -= 2;
1191  dst -= 4;
1192 
1193  b[0] = src[0];
1194  b[1] = src[1];
1195 
1196  dst[0] = ((b[1] & 0xf0) >> 4) * 17; /* B */
1197  dst[1] = (b[0] & 0x0f) * 17; /* G */
1198  dst[2] = ((b[0] & 0xf0) >> 4) * 17; /* R */
1199  dst[3] = (b[1] & 0x0f) * 17; /* A */
1200  }
1201  }
1202  /* 8bpp grayscale with extra alpha */
1203  else if (This->decode_info.source_bpp == 16 && This->decode_info.samples == 2 && This->decode_info.bpp == 32)
1204  {
1205  BYTE *src;
1206  DWORD *dst, count = This->decode_info.tile_width * This->decode_info.tile_height;
1207 
1208  src = This->cached_tile + This->decode_info.tile_width * This->decode_info.tile_height * 2 - 2;
1209  dst = (DWORD *)(This->cached_tile + This->decode_info.tile_size - 4);
1210 
1211  while (count--)
1212  {
1213  *dst-- = src[0] | (src[0] << 8) | (src[0] << 16) | (src[1] << 24);
1214  src -= 2;
1215  }
1216  }
1217 
1218  if (This->decode_info.reverse_bgr)
1219  {
1220  if (This->decode_info.bps == 8)
1221  {
1222  UINT sample_count = This->decode_info.samples;
1223 
1224  reverse_bgr8(sample_count, This->cached_tile, This->decode_info.tile_width,
1225  This->decode_info.tile_height, This->decode_info.tile_width * sample_count);
1226  }
1227  }
1228 
1229  if (swap_bytes && This->decode_info.bps > 8)
1230  {
1231  UINT row, i, samples_per_row;
1232  BYTE *sample, temp;
1233 
1234  samples_per_row = This->decode_info.tile_width * This->decode_info.samples;
1235 
1236  switch(This->decode_info.bps)
1237  {
1238  case 16:
1239  for (row=0; row<This->decode_info.tile_height; row++)
1240  {
1241  sample = This->cached_tile + row * This->decode_info.tile_stride;
1242  for (i=0; i<samples_per_row; i++)
1243  {
1244  temp = sample[1];
1245  sample[1] = sample[0];
1246  sample[0] = temp;
1247  sample += 2;
1248  }
1249  }
1250  break;
1251  default:
1252  ERR("unhandled bps for byte swap %u\n", This->decode_info.bps);
1253  return E_FAIL;
1254  }
1255  }
1256 
1257  if (This->decode_info.invert_grayscale)
1258  {
1259  BYTE *byte, *end;
1260 
1261  if (This->decode_info.samples != 1)
1262  {
1263  ERR("cannot invert grayscale image with %u samples\n", This->decode_info.samples);
1264  return E_FAIL;
1265  }
1266 
1267  end = This->cached_tile+This->decode_info.tile_size;
1268 
1269  for (byte = This->cached_tile; byte != end; byte++)
1270  *byte = ~(*byte);
1271  }
1272 
1273  This->cached_tile_x = tile_x;
1274  This->cached_tile_y = tile_y;
1275 
1276  return S_OK;
1277 }
1278 
1279 static HRESULT WINAPI TiffFrameDecode_CopyPixels(IWICBitmapFrameDecode *iface,
1280  const WICRect *prc, UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer)
1281 {
1282  TiffFrameDecode *This = impl_from_IWICBitmapFrameDecode(iface);
1283  UINT min_tile_x, max_tile_x, min_tile_y, max_tile_y;
1284  UINT tile_x, tile_y;
1285  WICRect rc;
1286  HRESULT hr=S_OK;
1287  BYTE *dst_tilepos;
1288  UINT bytesperrow;
1289  WICRect rect;
1290 
1291  TRACE("(%p,%s,%u,%u,%p)\n", iface, debug_wic_rect(prc), cbStride, cbBufferSize, pbBuffer);
1292 
1293  if (!prc)
1294  {
1295  rect.X = 0;
1296  rect.Y = 0;
1297  rect.Width = This->decode_info.width;
1298  rect.Height = This->decode_info.height;
1299  prc = &rect;
1300  }
1301  else
1302  {
1303  if (prc->X < 0 || prc->Y < 0 || prc->X+prc->Width > This->decode_info.width ||
1304  prc->Y+prc->Height > This->decode_info.height)
1305  return E_INVALIDARG;
1306  }
1307 
1308  bytesperrow = ((This->decode_info.bpp * prc->Width)+7)/8;
1309 
1310  if (cbStride < bytesperrow)
1311  return E_INVALIDARG;
1312 
1313  if ((cbStride * (prc->Height-1)) + bytesperrow > cbBufferSize)
1314  return E_INVALIDARG;
1315 
1316  min_tile_x = prc->X / This->decode_info.tile_width;
1317  min_tile_y = prc->Y / This->decode_info.tile_height;
1318  max_tile_x = (prc->X+prc->Width-1) / This->decode_info.tile_width;
1319  max_tile_y = (prc->Y+prc->Height-1) / This->decode_info.tile_height;
1320 
1321  EnterCriticalSection(&This->parent->lock);
1322 
1323  for (tile_x=min_tile_x; tile_x <= max_tile_x; tile_x++)
1324  {
1325  for (tile_y=min_tile_y; tile_y <= max_tile_y; tile_y++)
1326  {
1327  if (tile_x != This->cached_tile_x || tile_y != This->cached_tile_y)
1328  {
1329  hr = TiffFrameDecode_ReadTile(This, tile_x, tile_y);
1330  }
1331 
1332  if (SUCCEEDED(hr))
1333  {
1334  if (prc->X < tile_x * This->decode_info.tile_width)
1335  rc.X = 0;
1336  else
1337  rc.X = prc->X - tile_x * This->decode_info.tile_width;
1338 
1339  if (prc->Y < tile_y * This->decode_info.tile_height)
1340  rc.Y = 0;
1341  else
1342  rc.Y = prc->Y - tile_y * This->decode_info.tile_height;
1343 
1344  if (prc->X+prc->Width > (tile_x+1) * This->decode_info.tile_width)
1345  rc.Width = This->decode_info.tile_width - rc.X;
1346  else if (prc->X < tile_x * This->decode_info.tile_width)
1347  rc.Width = prc->Width + prc->X - tile_x * This->decode_info.tile_width;
1348  else
1349  rc.Width = prc->Width;
1350 
1351  if (prc->Y+prc->Height > (tile_y+1) * This->decode_info.tile_height)
1352  rc.Height = This->decode_info.tile_height - rc.Y;
1353  else if (prc->Y < tile_y * This->decode_info.tile_height)
1354  rc.Height = prc->Height + prc->Y - tile_y * This->decode_info.tile_height;
1355  else
1356  rc.Height = prc->Height;
1357 
1358  dst_tilepos = pbBuffer + (cbStride * ((rc.Y + tile_y * This->decode_info.tile_height) - prc->Y)) +
1359  ((This->decode_info.bpp * ((rc.X + tile_x * This->decode_info.tile_width) - prc->X) + 7) / 8);
1360 
1361  hr = copy_pixels(This->decode_info.bpp, This->cached_tile,
1362  This->decode_info.tile_width, This->decode_info.tile_height, This->decode_info.tile_stride,
1363  &rc, cbStride, cbBufferSize, dst_tilepos);
1364  }
1365 
1366  if (FAILED(hr))
1367  {
1368  LeaveCriticalSection(&This->parent->lock);
1369  TRACE("<-- 0x%x\n", hr);
1370  return hr;
1371  }
1372  }
1373  }
1374 
1375  LeaveCriticalSection(&This->parent->lock);
1376 
1377  return S_OK;
1378 }
1379 
1380 static HRESULT WINAPI TiffFrameDecode_GetMetadataQueryReader(IWICBitmapFrameDecode *iface,
1381  IWICMetadataQueryReader **ppIMetadataQueryReader)
1382 {
1383  TiffFrameDecode *This = impl_from_IWICBitmapFrameDecode(iface);
1384 
1385  TRACE("(%p,%p)\n", iface, ppIMetadataQueryReader);
1386 
1387  if (!ppIMetadataQueryReader)
1388  return E_INVALIDARG;
1389 
1390  return MetadataQueryReader_CreateInstance(&This->IWICMetadataBlockReader_iface, NULL, ppIMetadataQueryReader);
1391 }
1392 
1393 static HRESULT WINAPI TiffFrameDecode_GetColorContexts(IWICBitmapFrameDecode *iface,
1394  UINT cCount, IWICColorContext **ppIColorContexts, UINT *pcActualCount)
1395 {
1396  TiffFrameDecode *This = impl_from_IWICBitmapFrameDecode(iface);
1397  const BYTE *profile;
1398  UINT len;
1399  HRESULT hr;
1400 
1401  TRACE("(%p,%u,%p,%p)\n", iface, cCount, ppIColorContexts, pcActualCount);
1402 
1403  EnterCriticalSection(&This->parent->lock);
1404 
1405  if (pTIFFGetField(This->parent->tiff, TIFFTAG_ICCPROFILE, &len, &profile))
1406  {
1407  if (cCount && ppIColorContexts)
1408  {
1409  hr = IWICColorContext_InitializeFromMemory(*ppIColorContexts, profile, len);
1410  if (FAILED(hr))
1411  {
1412  LeaveCriticalSection(&This->parent->lock);
1413  return hr;
1414  }
1415  }
1416  *pcActualCount = 1;
1417  }
1418  else
1419  *pcActualCount = 0;
1420 
1421  LeaveCriticalSection(&This->parent->lock);
1422 
1423  return S_OK;
1424 }
1425 
1426 static HRESULT WINAPI TiffFrameDecode_GetThumbnail(IWICBitmapFrameDecode *iface,
1427  IWICBitmapSource **ppIThumbnail)
1428 {
1429  TRACE("(%p,%p)\n", iface, ppIThumbnail);
1430 
1431  if (!ppIThumbnail) return E_INVALIDARG;
1432 
1433  *ppIThumbnail = NULL;
1435 }
1436 
1437 static const IWICBitmapFrameDecodeVtbl TiffFrameDecode_Vtbl = {
1438  TiffFrameDecode_QueryInterface,
1439  TiffFrameDecode_AddRef,
1440  TiffFrameDecode_Release,
1441  TiffFrameDecode_GetSize,
1442  TiffFrameDecode_GetPixelFormat,
1443  TiffFrameDecode_GetResolution,
1444  TiffFrameDecode_CopyPalette,
1445  TiffFrameDecode_CopyPixels,
1446  TiffFrameDecode_GetMetadataQueryReader,
1447  TiffFrameDecode_GetColorContexts,
1448  TiffFrameDecode_GetThumbnail
1449 };
1450 
1451 static HRESULT WINAPI TiffFrameDecode_Block_QueryInterface(IWICMetadataBlockReader *iface,
1452  REFIID iid, void **ppv)
1453 {
1454  TiffFrameDecode *This = impl_from_IWICMetadataBlockReader(iface);
1455  return IWICBitmapFrameDecode_QueryInterface(&This->IWICBitmapFrameDecode_iface, iid, ppv);
1456 }
1457 
1458 static ULONG WINAPI TiffFrameDecode_Block_AddRef(IWICMetadataBlockReader *iface)
1459 {
1460  TiffFrameDecode *This = impl_from_IWICMetadataBlockReader(iface);
1461  return IWICBitmapFrameDecode_AddRef(&This->IWICBitmapFrameDecode_iface);
1462 }
1463 
1464 static ULONG WINAPI TiffFrameDecode_Block_Release(IWICMetadataBlockReader *iface)
1465 {
1466  TiffFrameDecode *This = impl_from_IWICMetadataBlockReader(iface);
1467  return IWICBitmapFrameDecode_Release(&This->IWICBitmapFrameDecode_iface);
1468 }
1469 
1470 static HRESULT WINAPI TiffFrameDecode_Block_GetContainerFormat(IWICMetadataBlockReader *iface,
1471  GUID *guid)
1472 {
1473  TRACE("(%p,%p)\n", iface, guid);
1474 
1475  if (!guid) return E_INVALIDARG;
1476 
1477  *guid = GUID_ContainerFormatTiff;
1478  return S_OK;
1479 }
1480 
1481 static HRESULT WINAPI TiffFrameDecode_Block_GetCount(IWICMetadataBlockReader *iface,
1482  UINT *count)
1483 {
1484  TRACE("%p,%p\n", iface, count);
1485 
1486  if (!count) return E_INVALIDARG;
1487 
1488  *count = 1;
1489  return S_OK;
1490 }
1491 
1492 static HRESULT create_metadata_reader(TiffFrameDecode *This, IWICMetadataReader **reader)
1493 {
1494  HRESULT hr;
1495  LARGE_INTEGER dir_offset;
1496  IWICMetadataReader *metadata_reader;
1497  IWICPersistStream *persist;
1498 
1499  /* FIXME: Use IWICComponentFactory_CreateMetadataReader once it's implemented */
1500 
1501  hr = IfdMetadataReader_CreateInstance(&IID_IWICMetadataReader, (void **)&metadata_reader);
1502  if (FAILED(hr)) return hr;
1503 
1504  hr = IWICMetadataReader_QueryInterface(metadata_reader, &IID_IWICPersistStream, (void **)&persist);
1505  if (FAILED(hr))
1506  {
1507  IWICMetadataReader_Release(metadata_reader);
1508  return hr;
1509  }
1510 
1511  EnterCriticalSection(&This->parent->lock);
1512 
1513  dir_offset.QuadPart = pTIFFCurrentDirOffset(This->parent->tiff);
1514  hr = IStream_Seek(This->parent->stream, dir_offset, STREAM_SEEK_SET, NULL);
1515  if (SUCCEEDED(hr))
1516  {
1517  BOOL byte_swapped = pTIFFIsByteSwapped(This->parent->tiff);
1518 #ifdef WORDS_BIGENDIAN
1520 #else
1522 #endif
1523  persist_options |= WICPersistOptionNoCacheStream;
1524  hr = IWICPersistStream_LoadEx(persist, This->parent->stream, NULL, persist_options);
1525  if (FAILED(hr))
1526  ERR("IWICPersistStream_LoadEx error %#x\n", hr);
1527  }
1528 
1529  LeaveCriticalSection(&This->parent->lock);
1530 
1531  IWICPersistStream_Release(persist);
1532 
1533  if (FAILED(hr))
1534  {
1535  IWICMetadataReader_Release(metadata_reader);
1536  return hr;
1537  }
1538 
1539  *reader = metadata_reader;
1540  return S_OK;
1541 }
1542 
1543 static HRESULT WINAPI TiffFrameDecode_Block_GetReaderByIndex(IWICMetadataBlockReader *iface,
1545 {
1546  TiffFrameDecode *This = impl_from_IWICMetadataBlockReader(iface);
1547 
1548  TRACE("(%p,%u,%p)\n", iface, index, reader);
1549 
1550  if (!reader || index != 0) return E_INVALIDARG;
1551 
1553 }
1554 
1555 static HRESULT WINAPI TiffFrameDecode_Block_GetEnumerator(IWICMetadataBlockReader *iface,
1556  IEnumUnknown **enum_metadata)
1557 {
1558  FIXME("(%p,%p): stub\n", iface, enum_metadata);
1559  return E_NOTIMPL;
1560 }
1561 
1562 static const IWICMetadataBlockReaderVtbl TiffFrameDecode_BlockVtbl =
1563 {
1564  TiffFrameDecode_Block_QueryInterface,
1565  TiffFrameDecode_Block_AddRef,
1566  TiffFrameDecode_Block_Release,
1567  TiffFrameDecode_Block_GetContainerFormat,
1568  TiffFrameDecode_Block_GetCount,
1569  TiffFrameDecode_Block_GetReaderByIndex,
1570  TiffFrameDecode_Block_GetEnumerator
1571 };
1572 
1574 {
1575  HRESULT ret;
1576  TiffDecoder *This;
1577 
1578  TRACE("(%s,%p)\n", debugstr_guid(iid), ppv);
1579 
1580  *ppv = NULL;
1581 
1582  if (!load_libtiff())
1583  {
1584  ERR("Failed reading TIFF because unable to load %s\n",SONAME_LIBTIFF);
1585  return E_FAIL;
1586  }
1587 
1588  This = HeapAlloc(GetProcessHeap(), 0, sizeof(TiffDecoder));
1589  if (!This) return E_OUTOFMEMORY;
1590 
1591  This->IWICBitmapDecoder_iface.lpVtbl = &TiffDecoder_Vtbl;
1592  This->ref = 1;
1593  This->stream = NULL;
1595  This->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": TiffDecoder.lock");
1596  This->tiff = NULL;
1597  This->initialized = FALSE;
1598 
1599  ret = IWICBitmapDecoder_QueryInterface(&This->IWICBitmapDecoder_iface, iid, ppv);
1600  IWICBitmapDecoder_Release(&This->IWICBitmapDecoder_iface);
1601 
1602  return ret;
1603 }
1604 
1605 struct tiff_encode_format {
1606  const WICPixelFormatGUID *guid;
1607  int photometric;
1608  int bps;
1609  int samples;
1610  int bpp;
1611  int extra_sample;
1612  int extra_sample_type;
1613  int reverse_bgr;
1614 };
1615 
1616 static const struct tiff_encode_format formats[] = {
1617  {&GUID_WICPixelFormat24bppBGR, 2, 8, 3, 24, 0, 0, 1},
1618  {&GUID_WICPixelFormat24bppRGB, 2, 8, 3, 24, 0, 0, 0},
1619  {&GUID_WICPixelFormatBlackWhite, 1, 1, 1, 1, 0, 0, 0},
1620  {&GUID_WICPixelFormat4bppGray, 1, 4, 1, 4, 0, 0, 0},
1621  {&GUID_WICPixelFormat8bppGray, 1, 8, 1, 8, 0, 0, 0},
1622  {&GUID_WICPixelFormat32bppBGRA, 2, 8, 4, 32, 1, 2, 1},
1623  {&GUID_WICPixelFormat32bppPBGRA, 2, 8, 4, 32, 1, 1, 1},
1624  {&GUID_WICPixelFormat48bppRGB, 2, 16, 3, 48, 0, 0, 0},
1625  {&GUID_WICPixelFormat64bppRGBA, 2, 16, 4, 64, 1, 2, 0},
1626  {&GUID_WICPixelFormat64bppPRGBA, 2, 16, 4, 64, 1, 1, 0},
1627  {&GUID_WICPixelFormat1bppIndexed, 3, 1, 1, 1, 0, 0, 0},
1628  {&GUID_WICPixelFormat4bppIndexed, 3, 4, 1, 4, 0, 0, 0},
1629  {&GUID_WICPixelFormat8bppIndexed, 3, 8, 1, 8, 0, 0, 0},
1630  {0}
1631 };
1632 
1633 typedef struct TiffEncoder {
1634  IWICBitmapEncoder IWICBitmapEncoder_iface;
1635  LONG ref;
1636  IStream *stream;
1637  CRITICAL_SECTION lock; /* Must be held when tiff is used or fields below are set */
1638  TIFF *tiff;
1639  BOOL initialized;
1640  BOOL committed;
1641  ULONG num_frames;
1642  ULONG num_frames_committed;
1643 } TiffEncoder;
1644 
1645 static inline TiffEncoder *impl_from_IWICBitmapEncoder(IWICBitmapEncoder *iface)
1646 {
1647  return CONTAINING_RECORD(iface, TiffEncoder, IWICBitmapEncoder_iface);
1648 }
1649 
1650 typedef struct TiffFrameEncode {
1651  IWICBitmapFrameEncode IWICBitmapFrameEncode_iface;
1652  LONG ref;
1653  TiffEncoder *parent;
1654  /* fields below are protected by parent->lock */
1655  BOOL initialized;
1656  BOOL info_written;
1657  BOOL committed;
1658  const struct tiff_encode_format *format;
1659  UINT width, height;
1660  double xres, yres;
1661  UINT lines_written;
1662  WICColor palette[256];
1663  UINT colors;
1664 } TiffFrameEncode;
1665 
1666 static inline TiffFrameEncode *impl_from_IWICBitmapFrameEncode(IWICBitmapFrameEncode *iface)
1667 {
1668  return CONTAINING_RECORD(iface, TiffFrameEncode, IWICBitmapFrameEncode_iface);
1669 }
1670 
1671 static HRESULT WINAPI TiffFrameEncode_QueryInterface(IWICBitmapFrameEncode *iface, REFIID iid,
1672  void **ppv)
1673 {
1674  TiffFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface);
1675  TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
1676 
1677  if (!ppv) return E_INVALIDARG;
1678 
1679  if (IsEqualIID(&IID_IUnknown, iid) ||
1680  IsEqualIID(&IID_IWICBitmapFrameEncode, iid))
1681  {
1682  *ppv = &This->IWICBitmapFrameEncode_iface;
1683  }
1684  else
1685  {
1686  *ppv = NULL;
1687  return E_NOINTERFACE;
1688  }
1689 
1690  IUnknown_AddRef((IUnknown*)*ppv);
1691  return S_OK;
1692 }
1693 
1694 static ULONG WINAPI TiffFrameEncode_AddRef(IWICBitmapFrameEncode *iface)
1695 {
1696  TiffFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface);
1698 
1699  TRACE("(%p) refcount=%u\n", iface, ref);
1700 
1701  return ref;
1702 }
1703 
1704 static ULONG WINAPI TiffFrameEncode_Release(IWICBitmapFrameEncode *iface)
1705 {
1706  TiffFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface);
1708 
1709  TRACE("(%p) refcount=%u\n", iface, ref);
1710 
1711  if (ref == 0)
1712  {
1713  IWICBitmapEncoder_Release(&This->parent->IWICBitmapEncoder_iface);
1714  HeapFree(GetProcessHeap(), 0, This);
1715  }
1716 
1717  return ref;
1718 }
1719 
1720 static HRESULT WINAPI TiffFrameEncode_Initialize(IWICBitmapFrameEncode *iface,
1721  IPropertyBag2 *pIEncoderOptions)
1722 {
1723  TiffFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface);
1724  TRACE("(%p,%p)\n", iface, pIEncoderOptions);
1725 
1726  EnterCriticalSection(&This->parent->lock);
1727 
1728  if (This->initialized)
1729  {
1730  LeaveCriticalSection(&This->parent->lock);
1731  return WINCODEC_ERR_WRONGSTATE;
1732  }
1733 
1734  This->initialized = TRUE;
1735 
1736  LeaveCriticalSection(&This->parent->lock);
1737 
1738  return S_OK;
1739 }
1740 
1741 static HRESULT WINAPI TiffFrameEncode_SetSize(IWICBitmapFrameEncode *iface,
1742  UINT uiWidth, UINT uiHeight)
1743 {
1744  TiffFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface);
1745  TRACE("(%p,%u,%u)\n", iface, uiWidth, uiHeight);
1746 
1747  EnterCriticalSection(&This->parent->lock);
1748 
1749  if (!This->initialized || This->info_written)
1750  {
1751  LeaveCriticalSection(&This->parent->lock);
1752  return WINCODEC_ERR_WRONGSTATE;
1753  }
1754 
1755  This->width = uiWidth;
1756  This->height = uiHeight;
1757 
1758  LeaveCriticalSection(&This->parent->lock);
1759 
1760  return S_OK;
1761 }
1762 
1763 static HRESULT WINAPI TiffFrameEncode_SetResolution(IWICBitmapFrameEncode *iface,
1764  double dpiX, double dpiY)
1765 {
1766  TiffFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface);
1767  TRACE("(%p,%0.2f,%0.2f)\n", iface, dpiX, dpiY);
1768 
1769  EnterCriticalSection(&This->parent->lock);
1770 
1771  if (!This->initialized || This->info_written)
1772  {
1773  LeaveCriticalSection(&This->parent->lock);
1774  return WINCODEC_ERR_WRONGSTATE;
1775  }
1776 
1777  This->xres = dpiX;
1778  This->yres = dpiY;
1779 
1780  LeaveCriticalSection(&This->parent->lock);
1781 
1782  return S_OK;
1783 }
1784 
1785 static HRESULT WINAPI TiffFrameEncode_SetPixelFormat(IWICBitmapFrameEncode *iface,
1786  WICPixelFormatGUID *pPixelFormat)
1787 {
1788  TiffFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface);
1789  int i;
1790 
1791  TRACE("(%p,%s)\n", iface, debugstr_guid(pPixelFormat));
1792 
1793  EnterCriticalSection(&This->parent->lock);
1794 
1795  if (!This->initialized || This->info_written)
1796  {
1797  LeaveCriticalSection(&This->parent->lock);
1798  return WINCODEC_ERR_WRONGSTATE;
1799  }
1800 
1801  if (IsEqualGUID(pPixelFormat, &GUID_WICPixelFormat2bppIndexed))
1802  *pPixelFormat = GUID_WICPixelFormat4bppIndexed;
1803 
1804  for (i=0; formats[i].guid; i++)
1805  {
1806  if (IsEqualGUID(formats[i].guid, pPixelFormat))
1807  break;
1808  }
1809 
1810  if (!formats[i].guid) i = 0;
1811 
1812  This->format = &formats[i];
1813  memcpy(pPixelFormat, This->format->guid, sizeof(GUID));
1814 
1815  LeaveCriticalSection(&This->parent->lock);
1816 
1817  return S_OK;
1818 }
1819 
1820 static HRESULT WINAPI TiffFrameEncode_SetColorContexts(IWICBitmapFrameEncode *iface,
1821  UINT cCount, IWICColorContext **ppIColorContext)
1822 {
1823  FIXME("(%p,%u,%p): stub\n", iface, cCount, ppIColorContext);
1824  return E_NOTIMPL;
1825 }
1826 
1827 static HRESULT WINAPI TiffFrameEncode_SetPalette(IWICBitmapFrameEncode *iface,
1829 {
1830  TiffFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface);
1831  HRESULT hr;
1832 
1833  TRACE("(%p,%p)\n", iface, palette);
1834 
1835  if (!palette) return E_INVALIDARG;
1836 
1837  EnterCriticalSection(&This->parent->lock);
1838 
1839  if (This->initialized)
1840  hr = IWICPalette_GetColors(palette, 256, This->palette, &This->colors);
1841  else
1843 
1844  LeaveCriticalSection(&This->parent->lock);
1845  return hr;
1846 }
1847 
1848 static HRESULT WINAPI TiffFrameEncode_SetThumbnail(IWICBitmapFrameEncode *iface,
1849  IWICBitmapSource *pIThumbnail)
1850 {
1851  FIXME("(%p,%p): stub\n", iface, pIThumbnail);
1853 }
1854 
1855 static HRESULT WINAPI TiffFrameEncode_WritePixels(IWICBitmapFrameEncode *iface,
1856  UINT lineCount, UINT cbStride, UINT cbBufferSize, BYTE *pbPixels)
1857 {
1858  TiffFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface);
1859  BYTE *row_data, *swapped_data = NULL;
1860  UINT i, j, line_size;
1861 
1862  TRACE("(%p,%u,%u,%u,%p)\n", iface, lineCount, cbStride, cbBufferSize, pbPixels);
1863 
1864  EnterCriticalSection(&This->parent->lock);
1865 
1866  if (!This->initialized || !This->width || !This->height || !This->format)
1867  {
1868  LeaveCriticalSection(&This->parent->lock);
1869  return WINCODEC_ERR_WRONGSTATE;
1870  }
1871 
1872  if (lineCount == 0 || lineCount + This->lines_written > This->height)
1873  {
1874  LeaveCriticalSection(&This->parent->lock);
1875  return E_INVALIDARG;
1876  }
1877 
1878  line_size = ((This->width * This->format->bpp)+7)/8;
1879 
1880  if (This->format->reverse_bgr)
1881  {
1882  swapped_data = HeapAlloc(GetProcessHeap(), 0, line_size);
1883  if (!swapped_data)
1884  {
1885  LeaveCriticalSection(&This->parent->lock);
1886  return E_OUTOFMEMORY;
1887  }
1888  }
1889 
1890  if (!This->info_written)
1891  {
1892  pTIFFSetField(This->parent->tiff, TIFFTAG_PHOTOMETRIC, (uint16)This->format->photometric);
1893  pTIFFSetField(This->parent->tiff, TIFFTAG_PLANARCONFIG, (uint16)1);
1894  pTIFFSetField(This->parent->tiff, TIFFTAG_BITSPERSAMPLE, (uint16)This->format->bps);
1895  pTIFFSetField(This->parent->tiff, TIFFTAG_SAMPLESPERPIXEL, (uint16)This->format->samples);
1896 
1897  if (This->format->extra_sample)
1898  {
1899  uint16 extra_samples;
1900  extra_samples = This->format->extra_sample_type;
1901 
1902  pTIFFSetField(This->parent->tiff, TIFFTAG_EXTRASAMPLES, (uint16)1, &extra_samples);
1903  }
1904 
1905  pTIFFSetField(This->parent->tiff, TIFFTAG_IMAGEWIDTH, (uint32)This->width);
1906  pTIFFSetField(This->parent->tiff, TIFFTAG_IMAGELENGTH, (uint32)This->height);
1907 
1908  if (This->xres != 0.0 && This->yres != 0.0)
1909  {
1910  pTIFFSetField(This->parent->tiff, TIFFTAG_RESOLUTIONUNIT, (uint16)2); /* Inch */
1911  pTIFFSetField(This->parent->tiff, TIFFTAG_XRESOLUTION, (float)This->xres);
1912  pTIFFSetField(This->parent->tiff, TIFFTAG_YRESOLUTION, (float)This->yres);
1913  }
1914 
1915  if (This->format->bpp <= 8 && This->colors && !IsEqualGUID(This->format->guid, &GUID_WICPixelFormatBlackWhite))
1916  {
1917  uint16 red[256], green[256], blue[256];
1918  UINT i;
1919 
1920  for (i = 0; i < This->colors; i++)
1921  {
1922  red[i] = (This->palette[i] >> 8) & 0xff00;
1923  green[i] = This->palette[i] & 0xff00;
1924  blue[i] = (This->palette[i] << 8) & 0xff00;
1925  }
1926 
1927  pTIFFSetField(This->parent->tiff, TIFFTAG_COLORMAP, red, green, blue);
1928  }
1929 
1930  This->info_written = TRUE;
1931  }
1932 
1933  for (i=0; i<lineCount; i++)
1934  {
1935  row_data = pbPixels + i * cbStride;
1936 
1937  if (This->format->reverse_bgr && This->format->bps == 8)
1938  {
1939  memcpy(swapped_data, row_data, line_size);
1940  for (j=0; j<line_size; j += This->format->samples)
1941  {
1942  BYTE temp;
1943  temp = swapped_data[j];
1944  swapped_data[j] = swapped_data[j+2];
1945  swapped_data[j+2] = temp;
1946  }
1947  row_data = swapped_data;
1948  }
1949 
1950  pTIFFWriteScanline(This->parent->tiff, (tdata_t)row_data, i+This->lines_written, 0);
1951  }
1952 
1953  This->lines_written += lineCount;
1954 
1955  LeaveCriticalSection(&This->parent->lock);
1956 
1957  HeapFree(GetProcessHeap(), 0, swapped_data);
1958 
1959  return S_OK;
1960 }
1961 
1962 static HRESULT WINAPI TiffFrameEncode_WriteSource(IWICBitmapFrameEncode *iface,
1963  IWICBitmapSource *pIBitmapSource, WICRect *prc)
1964 {
1965  TiffFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface);
1966  HRESULT hr;
1967 
1968  TRACE("(%p,%p,%s)\n", iface, pIBitmapSource, debug_wic_rect(prc));
1969 
1970  if (!This->initialized)
1971  return WINCODEC_ERR_WRONGSTATE;
1972 
1973  hr = configure_write_source(iface, pIBitmapSource, prc,
1974  This->format ? This->format->guid : NULL, This->width, This->height,
1975  This->xres, This->yres);
1976 
1977  if (SUCCEEDED(hr))
1978  {
1979  hr = write_source(iface, pIBitmapSource, prc,
1980  This->format->guid, This->format->bpp, This->width, This->height);
1981  }
1982 
1983  return hr;
1984 }
1985 
1986 static HRESULT WINAPI TiffFrameEncode_Commit(IWICBitmapFrameEncode *iface)
1987 {
1988  TiffFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface);
1989 
1990  TRACE("(%p)\n", iface);
1991 
1992  EnterCriticalSection(&This->parent->lock);
1993 
1994  if (!This->info_written || This->lines_written != This->height || This->committed)
1995  {
1996  LeaveCriticalSection(&This->parent->lock);
1997  return WINCODEC_ERR_WRONGSTATE;
1998  }
1999 
2000  /* libtiff will commit the data when creating a new frame or closing the file */
2001 
2002  This->committed = TRUE;
2003  This->parent->num_frames_committed++;
2004 
2005  LeaveCriticalSection(&This->parent->lock);
2006 
2007  return S_OK;
2008 }
2009 
2010 static HRESULT WINAPI TiffFrameEncode_GetMetadataQueryWriter(IWICBitmapFrameEncode *iface,
2011  IWICMetadataQueryWriter **ppIMetadataQueryWriter)
2012 {
2013  FIXME("(%p, %p): stub\n", iface, ppIMetadataQueryWriter);
2014  return E_NOTIMPL;
2015 }
2016 
2017 static const IWICBitmapFrameEncodeVtbl TiffFrameEncode_Vtbl = {
2018  TiffFrameEncode_QueryInterface,
2019  TiffFrameEncode_AddRef,
2020  TiffFrameEncode_Release,
2021  TiffFrameEncode_Initialize,
2022  TiffFrameEncode_SetSize,
2023  TiffFrameEncode_SetResolution,
2024  TiffFrameEncode_SetPixelFormat,
2025  TiffFrameEncode_SetColorContexts,
2026  TiffFrameEncode_SetPalette,
2027  TiffFrameEncode_SetThumbnail,
2028  TiffFrameEncode_WritePixels,
2029  TiffFrameEncode_WriteSource,
2030  TiffFrameEncode_Commit,
2031  TiffFrameEncode_GetMetadataQueryWriter
2032 };
2033 
2034 static HRESULT WINAPI TiffEncoder_QueryInterface(IWICBitmapEncoder *iface, REFIID iid,
2035  void **ppv)
2036 {
2037  TiffEncoder *This = impl_from_IWICBitmapEncoder(iface);
2038  TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
2039 
2040  if (!ppv) return E_INVALIDARG;
2041 
2042  if (IsEqualIID(&IID_IUnknown, iid) ||
2043  IsEqualIID(&IID_IWICBitmapEncoder, iid))
2044  {
2045  *ppv = &This->IWICBitmapEncoder_iface;
2046  }
2047  else
2048  {
2049  *ppv = NULL;
2050  return E_NOINTERFACE;
2051  }
2052 
2053  IUnknown_AddRef((IUnknown*)*ppv);
2054  return S_OK;
2055 }
2056 
2057 static ULONG WINAPI TiffEncoder_AddRef(IWICBitmapEncoder *iface)
2058 {
2059  TiffEncoder *This = impl_from_IWICBitmapEncoder(iface);
2061 
2062  TRACE("(%p) refcount=%u\n", iface, ref);
2063 
2064  return ref;
2065 }
2066 
2067 static ULONG WINAPI TiffEncoder_Release(IWICBitmapEncoder *iface)
2068 {
2069  TiffEncoder *This = impl_from_IWICBitmapEncoder(iface);
2071 
2072  TRACE("(%p) refcount=%u\n", iface, ref);
2073 
2074  if (ref == 0)
2075  {
2076  if (This->tiff) pTIFFClose(This->tiff);
2077  if (This->stream) IStream_Release(This->stream);
2078  This->lock.DebugInfo->Spare[0] = 0;
2079  DeleteCriticalSection(&This->lock);
2080  HeapFree(GetProcessHeap(), 0, This);
2081  }
2082 
2083  return ref;
2084 }
2085 
2086 static HRESULT WINAPI TiffEncoder_Initialize(IWICBitmapEncoder *iface,
2087  IStream *pIStream, WICBitmapEncoderCacheOption cacheOption)
2088 {
2089  TiffEncoder *This = impl_from_IWICBitmapEncoder(iface);
2090  TIFF *tiff;
2091  HRESULT hr=S_OK;
2092 
2093  TRACE("(%p,%p,%u)\n", iface, pIStream, cacheOption);
2094 
2095  EnterCriticalSection(&This->lock);
2096 
2097  if (This->initialized || This->committed)
2098  {
2100  goto exit;
2101  }
2102 
2103  tiff = tiff_open_stream(pIStream, "w");
2104 
2105  if (!tiff)
2106  {
2107  hr = E_FAIL;
2108  goto exit;
2109  }
2110 
2111  This->tiff = tiff;
2112  This->stream = pIStream;
2113  IStream_AddRef(pIStream);
2114  This->initialized = TRUE;
2115 
2116 exit:
2117  LeaveCriticalSection(&This->lock);
2118  return hr;
2119 }
2120 
2121 static HRESULT WINAPI TiffEncoder_GetContainerFormat(IWICBitmapEncoder *iface,
2122  GUID *pguidContainerFormat)
2123 {
2124  TRACE("(%p,%p)\n", iface, pguidContainerFormat);
2125 
2126  if (!pguidContainerFormat)
2127  return E_INVALIDARG;
2128 
2129  memcpy(pguidContainerFormat, &GUID_ContainerFormatTiff, sizeof(GUID));
2130  return S_OK;
2131 }
2132 
2133 static HRESULT WINAPI TiffEncoder_GetEncoderInfo(IWICBitmapEncoder *iface, IWICBitmapEncoderInfo **info)
2134 {
2135  IWICComponentInfo *comp_info;
2136  HRESULT hr;
2137 
2138  TRACE("%p,%p\n", iface, info);
2139 
2140  if (!info) return E_INVALIDARG;
2141 
2142  hr = CreateComponentInfo(&CLSID_WICTiffEncoder, &comp_info);
2143  if (hr == S_OK)
2144  {
2145  hr = IWICComponentInfo_QueryInterface(comp_info, &IID_IWICBitmapEncoderInfo, (void **)info);
2146  IWICComponentInfo_Release(comp_info);
2147  }
2148  return hr;
2149 }
2150 
2151 static HRESULT WINAPI TiffEncoder_SetColorContexts(IWICBitmapEncoder *iface,
2152  UINT cCount, IWICColorContext **ppIColorContext)
2153 {
2154  FIXME("(%p,%u,%p): stub\n", iface, cCount, ppIColorContext);
2155  return E_NOTIMPL;
2156 }
2157 
2158 static HRESULT WINAPI TiffEncoder_SetPalette(IWICBitmapEncoder *iface, IWICPalette *palette)
2159 {
2160  TiffEncoder *This = impl_from_IWICBitmapEncoder(iface);
2161  HRESULT hr;
2162 
2163  TRACE("(%p,%p)\n", iface, palette);
2164 
2165  EnterCriticalSection(&This->lock);
2166 
2168 
2169  LeaveCriticalSection(&This->lock);
2170 
2171  return hr;
2172 }
2173 
2174 static HRESULT WINAPI TiffEncoder_SetThumbnail(IWICBitmapEncoder *iface, IWICBitmapSource *pIThumbnail)
2175 {
2176  TRACE("(%p,%p)\n", iface, pIThumbnail);
2178 }
2179 
2180 static HRESULT WINAPI TiffEncoder_SetPreview(IWICBitmapEncoder *iface, IWICBitmapSource *pIPreview)
2181 {
2182  TRACE("(%p,%p)\n", iface, pIPreview);
2184 }
2185 
2186 static HRESULT WINAPI TiffEncoder_CreateNewFrame(IWICBitmapEncoder *iface,
2187  IWICBitmapFrameEncode **ppIFrameEncode, IPropertyBag2 **ppIEncoderOptions)
2188 {
2189  TiffEncoder *This = impl_from_IWICBitmapEncoder(iface);
2190  TiffFrameEncode *result;
2191  static const PROPBAG2 opts[2] =
2192  {
2193  { PROPBAG2_TYPE_DATA, VT_UI1, 0, 0, (LPOLESTR)wszTiffCompressionMethod },
2194  { PROPBAG2_TYPE_DATA, VT_R4, 0, 0, (LPOLESTR)wszCompressionQuality },
2195  };
2196  HRESULT hr=S_OK;
2197 
2198  TRACE("(%p,%p,%p)\n", iface, ppIFrameEncode, ppIEncoderOptions);
2199 
2200  EnterCriticalSection(&This->lock);
2201 
2202  if (!This->initialized || This->committed)
2203  {
2205  }
2206  else if (This->num_frames != This->num_frames_committed)
2207  {
2208  FIXME("New frame created before previous frame was committed\n");
2209  hr = E_FAIL;
2210  }
2211 
2212  if (ppIEncoderOptions && SUCCEEDED(hr))
2213  {
2214  hr = CreatePropertyBag2(opts, ARRAY_SIZE(opts), ppIEncoderOptions);
2215  if (SUCCEEDED(hr))
2216  {
2217  VARIANT v;
2218  VariantInit(&v);
2219  V_VT(&v) = VT_UI1;
2221  hr = IPropertyBag2_Write(*ppIEncoderOptions, 1, (PROPBAG2 *)opts, &v);
2222  VariantClear(&v);
2223  if (FAILED(hr))
2224  {
2225  IPropertyBag2_Release(*ppIEncoderOptions);
2226  *ppIEncoderOptions = NULL;
2227  }
2228  }
2229  }
2230 
2231  if (SUCCEEDED(hr))
2232  {
2233  result = HeapAlloc(GetProcessHeap(), 0, sizeof(*result));
2234 
2235  if (result)
2236  {
2237  result->IWICBitmapFrameEncode_iface.lpVtbl = &TiffFrameEncode_Vtbl;
2238  result->ref = 1;
2239  result->parent = This;
2240  result->initialized = FALSE;
2241  result->info_written = FALSE;
2242  result->committed = FALSE;
2243  result->format = NULL;
2244  result->width = 0;
2245  result->height = 0;
2246  result->xres = 0.0;
2247  result->yres = 0.0;
2248  result->lines_written = 0;
2249  result->colors = 0;
2250 
2251  IWICBitmapEncoder_AddRef(iface);
2252  *ppIFrameEncode = &result->IWICBitmapFrameEncode_iface;
2253 
2254  if (This->num_frames != 0)
2255  pTIFFWriteDirectory(This->tiff);
2256 
2257  This->num_frames++;
2258  }
2259  else
2260  hr = E_OUTOFMEMORY;
2261 
2262  if (FAILED(hr))
2263  {
2264  IPropertyBag2_Release(*ppIEncoderOptions);
2265  *ppIEncoderOptions = NULL;
2266  }
2267  }
2268 
2269  LeaveCriticalSection(&This->lock);
2270 
2271  return hr;
2272 }
2273 
2274 static HRESULT WINAPI TiffEncoder_Commit(IWICBitmapEncoder *iface)
2275 {
2276  TiffEncoder *This = impl_from_IWICBitmapEncoder(iface);
2277 
2278  TRACE("(%p)\n", iface);
2279 
2280  EnterCriticalSection(&This->lock);
2281 
2282  if (!This->initialized || This->committed)
2283  {
2284  LeaveCriticalSection(&This->lock);
2285  return WINCODEC_ERR_WRONGSTATE;
2286  }
2287 
2288  pTIFFClose(This->tiff);
2289  IStream_Release(This->stream);
2290  This->stream = NULL;
2291  This->tiff = NULL;
2292 
2293  This->committed = TRUE;
2294 
2295  LeaveCriticalSection(&This->lock);
2296 
2297  return S_OK;
2298 }
2299 
2300 static HRESULT WINAPI TiffEncoder_GetMetadataQueryWriter(IWICBitmapEncoder *iface,
2301  IWICMetadataQueryWriter **ppIMetadataQueryWriter)
2302 {
2303  FIXME("(%p,%p): stub\n", iface, ppIMetadataQueryWriter);
2304  return E_NOTIMPL;
2305 }
2306 
2307 static const IWICBitmapEncoderVtbl TiffEncoder_Vtbl = {
2308  TiffEncoder_QueryInterface,
2309  TiffEncoder_AddRef,
2310  TiffEncoder_Release,
2311  TiffEncoder_Initialize,
2312  TiffEncoder_GetContainerFormat,
2313  TiffEncoder_GetEncoderInfo,
2314  TiffEncoder_SetColorContexts,
2315  TiffEncoder_SetPalette,
2316  TiffEncoder_SetThumbnail,
2317  TiffEncoder_SetPreview,
2318  TiffEncoder_CreateNewFrame,
2319  TiffEncoder_Commit,
2320  TiffEncoder_GetMetadataQueryWriter
2321 };
2322 
2324 {
2325  TiffEncoder *This;
2326  HRESULT ret;
2327 
2328  TRACE("(%s,%p)\n", debugstr_guid(iid), ppv);
2329 
2330  *ppv = NULL;
2331 
2332  if (!load_libtiff())
2333  {
2334  ERR("Failed writing TIFF because unable to load %s\n",SONAME_LIBTIFF);
2335  return E_FAIL;
2336  }
2337 
2338  This = HeapAlloc(GetProcessHeap(), 0, sizeof(TiffEncoder));
2339  if (!This) return E_OUTOFMEMORY;
2340 
2341  This->IWICBitmapEncoder_iface.lpVtbl = &TiffEncoder_Vtbl;
2342  This->ref = 1;
2343  This->stream = NULL;
2345  This->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": TiffEncoder.lock");
2346  This->tiff = NULL;
2347  This->initialized = FALSE;
2348  This->num_frames = 0;
2349  This->num_frames_committed = 0;
2350  This->committed = FALSE;
2351 
2352  ret = IWICBitmapEncoder_QueryInterface(&This->IWICBitmapEncoder_iface, iid, ppv);
2353  IWICBitmapEncoder_Release(&This->IWICBitmapEncoder_iface);
2354 
2355  return ret;
2356 }
2357 
2358 #else /* !SONAME_LIBTIFF */
2359 
2361 {
2362  ERR("Trying to load TIFF picture, but Wine was compiled without TIFF support.\n");
2363  return E_FAIL;
2364 }
2365 
2367 {
2368  ERR("Trying to save TIFF picture, but Wine was compiled without TIFF support.\n");
2369  return E_FAIL;
2370 }
2371 
2372 #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
#define TRUE
Definition: types.h:120
uint64 TIFFCurrentDirOffset(TIFF *tif)
Definition: tif_dir.c:1648
#define E_NOINTERFACE
Definition: winerror.h:2364
int TIFFReadDirectory(TIFF *tif)
Definition: tif_dirread.c:3542
#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:2360
tmsize_t TIFFReadEncodedTile(TIFF *tif, uint32 tile, void *buf, tmsize_t size)
Definition: tif_read.c:981
#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:111
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:571
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:56
int TIFFWriteScanline(TIFF *tif, void *buf, uint32 row, uint16 sample)
Definition: tif_write.c:48
Definition: send.c:47
& rect
Definition: startmenu.cpp:1413
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: gl.h:1546
Definition: tiffiop.h:102
int TIFFSetDirectory(TIFF *tif, uint16 dirn)
Definition: tif_dir.c:1599
void TIFFClose(TIFF *tif)
Definition: tif_close.c:122
int TIFFGetField(TIFF *tif, uint32 tag,...)
Definition: tif_dir.c:1215
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:629
ULONGLONG QuadPart
Definition: ms-dtyp.idl:185
#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:110
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:72
#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:1568
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:403
PVOID WINAPI HeapAlloc(HANDLE, DWORD, SIZE_T)
r parent
Definition: btrfs.c:2869
__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:77
const GUID IID_IUnknown
#define V_UI1(A)
Definition: oleauto.h:266
static BOOL initialized
Definition: syslog.c:39
#define WINAPI
Definition: msvc.h:8
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:651
GLenum const GLvoid * addr
Definition: glext.h:9621
Definition: compat.h:1948
#define index(s, c)
Definition: various.h:29
static UINT width_bytes(UINT width, UINT bpp)
Definition: tiffformat.c:846
#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
unsigned char BYTE
Definition: mem.h:68
GLenum src
Definition: glext.h:6340
#define WINCODEC_ERR_UNSUPPORTEDOPERATION
Definition: winerror.h:3300
int isfinite(double x)
LIST_ENTRY ProcessLocksList
Definition: winbase.h:855
GLenum mode
Definition: glext.h:6217
tmsize_t tsize_t
Definition: tiffio.h:75
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:1601
#define ERR(fmt,...)
Definition: debug.h:109
WICDecodeOptions
Definition: wincodec.idl:27
#define WINCODEC_ERR_WRONGSTATE
Definition: winerror.h:3273
#define S_OK
Definition: intsafe.h:59
tmsize_t TIFFReadEncodedStrip(TIFF *tif, uint32 strip, void *buf, tmsize_t size)
Definition: tif_read.c:512
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:622
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:2366
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:628
INT Width
Definition: wincodec.idl:238
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:181
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:790
#define HeapFree(x, y, z)
Definition: compat.h:402
#define IsEqualIID(riid1, riid2)
Definition: guiddef.h:95
#define SUCCEEDED(hr)
Definition: intsafe.h:57
LONGLONG QuadPart
Definition: typedefs.h:112
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