ReactOS 0.4.15-dev-7924-g5949c20
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
56static CRITICAL_SECTION init_tiff_cs;
57static 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};
64static CRITICAL_SECTION init_tiff_cs = { &init_tiff_cs_debug, -1, 0, 0, 0, 0 };
65
66static 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};
67static const WCHAR wszCompressionQuality[] = {'C','o','m','p','r','e','s','s','i','o','n','Q','u','a','l','i','t','y',0};
68
69static void *libtiff_handle;
70#define MAKE_FUNCPTR(f) static typeof(f) * p##f
84#undef MAKE_FUNCPTR
85
86static 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
132static 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
143static 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
154static 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;
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
184static int tiff_stream_close(thandle_t client_data)
185{
186 /* Caller is responsible for releasing the stream object. */
187 return 0;
188}
189
190static 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
202static int tiff_stream_map(thandle_t client_data, tdata_t *addr, toff_t *size)
203{
204 /* Cannot mmap streams */
205 return 0;
206}
207
208static 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
213static 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
225typedef struct {
226 IWICBitmapDecoder IWICBitmapDecoder_iface;
227 LONG ref;
229 CRITICAL_SECTION lock; /* Must be held when tiff is used or initialized is set */
230 TIFF *tiff;
232} TiffDecoder;
233
234typedef struct {
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;
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
253typedef 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
264static const IWICBitmapFrameDecodeVtbl TiffFrameDecode_Vtbl;
265static const IWICMetadataBlockReaderVtbl TiffFrameDecode_BlockVtbl;
266
267static inline TiffDecoder *impl_from_IWICBitmapDecoder(IWICBitmapDecoder *iface)
268{
269 return CONTAINING_RECORD(iface, TiffDecoder, IWICBitmapDecoder_iface);
270}
271
272static inline TiffFrameDecode *impl_from_IWICBitmapFrameDecode(IWICBitmapFrameDecode *iface)
273{
274 return CONTAINING_RECORD(iface, TiffFrameDecode, IWICBitmapFrameDecode_iface);
275}
276
277static inline TiffFrameDecode *impl_from_IWICMetadataBlockReader(IWICMetadataBlockReader *iface)
278{
279 return CONTAINING_RECORD(iface, TiffFrameDecode, IWICMetadataBlockReader_iface);
280}
281
282static 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
617static 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
640static 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
650static 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;
664 }
665
666 return ref;
667}
668
669static 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
687static 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;
694
695 TRACE("(%p,%p,%x)\n", iface, pIStream, cacheOptions);
696
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
725exit:
727 return hr;
728}
729
730static 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
739static 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
747static HRESULT WINAPI TiffDecoder_CopyPalette(IWICBitmapDecoder *iface,
749{
750 TRACE("(%p,%p)\n", iface, palette);
752}
753
754static 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
765static 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
776static 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
783static 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
794static 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
802 *pCount = This->tiff ? pTIFFNumberOfDirectories(This->tiff) : 0;
804
805 TRACE("(%p) <-- %i\n", iface, *pCount);
806
807 return S_OK;
808}
809
810static 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
825 res = pTIFFSetDirectory(This->tiff, index);
826 if (!res) hr = E_INVALIDARG;
827 else hr = tiff_get_decode_info(This->tiff, &decode_info);
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 {
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
862static 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
879static 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
907static 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
917static 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
934static 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
947static 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
959static 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
993static 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
1026static 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
1292static 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
1393static 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
1406static 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
1439static 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
1450static 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
1464static 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
1471static ULONG WINAPI TiffFrameDecode_Block_AddRef(IWICMetadataBlockReader *iface)
1472{
1473 TiffFrameDecode *This = impl_from_IWICMetadataBlockReader(iface);
1474 return IWICBitmapFrameDecode_AddRef(&This->IWICBitmapFrameDecode_iface);
1475}
1476
1477static ULONG WINAPI TiffFrameDecode_Block_Release(IWICMetadataBlockReader *iface)
1478{
1479 TiffFrameDecode *This = impl_from_IWICMetadataBlockReader(iface);
1480 return IWICBitmapFrameDecode_Release(&This->IWICBitmapFrameDecode_iface);
1481}
1482
1483static 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
1494static 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
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
1556static 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
1568static 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
1575static 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
1618struct 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
1629static 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
1646typedef 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;
1653 BOOL committed;
1654 ULONG num_frames;
1655 ULONG num_frames_committed;
1656} TiffEncoder;
1657
1658static inline TiffEncoder *impl_from_IWICBitmapEncoder(IWICBitmapEncoder *iface)
1659{
1660 return CONTAINING_RECORD(iface, TiffEncoder, IWICBitmapEncoder_iface);
1661}
1662
1663typedef struct TiffFrameEncode {
1664 IWICBitmapFrameEncode IWICBitmapFrameEncode_iface;
1665 LONG ref;
1666 TiffEncoder *parent;
1667 /* fields below are protected by parent->lock */
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
1679static inline TiffFrameEncode *impl_from_IWICBitmapFrameEncode(IWICBitmapFrameEncode *iface)
1680{
1681 return CONTAINING_RECORD(iface, TiffFrameEncode, IWICBitmapFrameEncode_iface);
1682}
1683
1684static 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
1707static 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
1717static 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);
1728 }
1729
1730 return ref;
1731}
1732
1733static 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);
1745 }
1746
1747 This->initialized = TRUE;
1748
1749 LeaveCriticalSection(&This->parent->lock);
1750
1751 return S_OK;
1752}
1753
1754static 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);
1766 }
1767
1768 This->width = uiWidth;
1769 This->height = uiHeight;
1770
1771 LeaveCriticalSection(&This->parent->lock);
1772
1773 return S_OK;
1774}
1775
1776static 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);
1788 }
1789
1790 This->xres = dpiX;
1791 This->yres = dpiY;
1792
1793 LeaveCriticalSection(&This->parent->lock);
1794
1795 return S_OK;
1796}
1797
1798static 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);
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
1833static 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
1840static 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
1861static HRESULT WINAPI TiffFrameEncode_SetThumbnail(IWICBitmapFrameEncode *iface,
1862 IWICBitmapSource *pIThumbnail)
1863{
1864 FIXME("(%p,%p): stub\n", iface, pIThumbnail);
1866}
1867
1868static 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);
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
1975static 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)
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
1999static 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);
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
2023static HRESULT WINAPI TiffFrameEncode_GetMetadataQueryWriter(IWICBitmapFrameEncode *iface,
2024 IWICMetadataQueryWriter **ppIMetadataQueryWriter)
2025{
2026 FIXME("(%p, %p): stub\n", iface, ppIMetadataQueryWriter);
2027 return E_NOTIMPL;
2028}
2029
2030static 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
2047static 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
2070static 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
2080static 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;
2094 }
2095
2096 return ref;
2097}
2098
2099static 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
2129exit:
2130 LeaveCriticalSection(&This->lock);
2131 return hr;
2132}
2133
2134static 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
2146static 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
2164static 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
2171static 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
2187static HRESULT WINAPI TiffEncoder_SetThumbnail(IWICBitmapEncoder *iface, IWICBitmapSource *pIThumbnail)
2188{
2189 TRACE("(%p,%p)\n", iface, pIThumbnail);
2191}
2192
2193static HRESULT WINAPI TiffEncoder_SetPreview(IWICBitmapEncoder *iface, IWICBitmapSource *pIPreview)
2194{
2195 TRACE("(%p,%p)\n", iface, pIPreview);
2197}
2198
2199static 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
2287static 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);
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
2313static HRESULT WINAPI TiffEncoder_GetMetadataQueryWriter(IWICBitmapEncoder *iface,
2314 IWICMetadataQueryWriter **ppIMetadataQueryWriter)
2315{
2316 FIXME("(%p,%p): stub\n", iface, ppIMetadataQueryWriter);
2317 return E_NOTIMPL;
2318}
2319
2320static 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
#define InterlockedIncrement
Definition: armddk.h:53
#define InterlockedDecrement
Definition: armddk.h:52
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
unsigned short uint16
Definition: types.h:30
unsigned int uint32
Definition: types.h:32
#define index(s, c)
Definition: various.h:29
#define ARRAY_SIZE(A)
Definition: main.h:33
const GUID IID_IUnknown
static BmpDecoder * impl_from_IWICBitmapFrameDecode(IWICBitmapFrameDecode *iface)
Definition: bmpdecode.c:88
static BmpDecoder * impl_from_IWICBitmapDecoder(IWICBitmapDecoder *iface)
Definition: bmpdecode.c:83
static BmpFrameEncode * impl_from_IWICBitmapFrameEncode(IWICBitmapFrameEncode *iface)
Definition: bmpencode.c:84
static BmpEncoder * impl_from_IWICBitmapEncoder(IWICBitmapEncoder *iface)
Definition: bmpencode.c:433
#define FIXME(fmt,...)
Definition: debug.h:111
#define WARN(fmt,...)
Definition: debug.h:112
#define ERR(fmt,...)
Definition: debug.h:110
#define SEEK_END
Definition: cabinet.c:29
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:1700
#define E_OUTOFMEMORY
Definition: ddrawi.h:100
#define E_INVALIDARG
Definition: ddrawi.h:101
#define E_NOTIMPL
Definition: ddrawi.h:99
#define E_FAIL
Definition: ddrawi.h:102
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
DWORD bpp
Definition: surface.c:185
static const struct pixel_format_desc formats[]
Definition: util.c:59
#define GetProcessHeap()
Definition: compat.h:736
#define HeapAlloc
Definition: compat.h:733
#define HeapFree(x, y, z)
Definition: compat.h:735
@ VT_R4
Definition: compat.h:2299
@ VT_UI1
Definition: compat.h:2311
static GpStatus get_decoder_info(IStream *stream, const struct image_codec **result)
Definition: image.c:4285
#define byte(x, n)
Definition: tomcrypt.h:118
static GifDecoder * impl_from_IWICMetadataBlockReader(IWICMetadataBlockReader *iface)
Definition: gifformat.c:607
static HRESULT create_metadata_reader(const void *data, int data_size, class_constructor constructor, IWICMetadataReader **reader)
Definition: gifformat.c:551
HRESULT CreateComponentInfo(REFCLSID clsid, IWICComponentInfo **ppIInfo)
Definition: info.c:2075
HRESULT write_source(IWICBitmapFrameEncode *iface, IWICBitmapSource *source, const WICRect *prc, const WICPixelFormatGUID *format, UINT bpp, INT width, INT height)
Definition: main.c:155
void reverse_bgr8(UINT bytesperpixel, LPBYTE bits, UINT width, UINT height, INT stride)
Definition: main.c:212
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
HRESULT CreatePropertyBag2(const PROPBAG2 *options, UINT count, IPropertyBag2 **ppPropertyBag2)
Definition: propertybag.c:281
HRESULT TiffEncoder_CreateInstance(REFIID iid, void **ppv)
Definition: tiffformat.c:2379
HRESULT TiffDecoder_CreateInstance(REFIID iid, void **ppv)
Definition: tiffformat.c:2373
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
r parent
Definition: btrfs.c:3010
#define LOAD_FUNCPTR(f)
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
GLclampf green
Definition: gl.h:1740
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
const GLdouble * v
Definition: gl.h:2040
GLint GLint GLint GLint GLint GLint y
Definition: gl.h:1548
GLuint GLuint end
Definition: gl.h:1545
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: gl.h:1546
GLint GLint GLsizei GLsizei height
Definition: gl.h:1546
GLclampf GLclampf blue
Definition: gl.h:1740
GLint GLint GLsizei width
Definition: gl.h:1546
GLsizeiptr size
Definition: glext.h:5919
GLsizei samples
Definition: glext.h:7006
GLuint res
Definition: glext.h:9613
GLenum src
Definition: glext.h:6340
GLuint index
Definition: glext.h:6031
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
GLenum mode
Definition: glext.h:6217
GLenum GLenum dst
Definition: glext.h:6340
GLenum const GLvoid * addr
Definition: glext.h:9621
GLenum GLsizei len
Definition: glext.h:6722
GLuint64EXT * result
Definition: glext.h:11304
GLintptr offset
Definition: glext.h:5920
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
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
REFIID LPVOID * ppv
Definition: atlbase.h:39
#define S_OK
Definition: intsafe.h:52
#define SUCCEEDED(hr)
Definition: intsafe.h:50
#define FAILED(hr)
Definition: intsafe.h:51
voidpf uLong int origin
Definition: ioapi.h:144
#define SEEK_SET
Definition: jmemansi.c:26
#define debugstr_guid
Definition: kernel32.h:35
#define profile
Definition: kernel32.h:12
void * wine_dlopen(const char *filename, int flag, char *error, size_t errorsize)
Definition: loader.c:53
void * wine_dlsym(void *handle, const char *symbol, char *error, size_t errorsize)
Definition: loader.c:48
#define red
Definition: linetest.c:67
HRESULT IfdMetadataReader_CreateInstance(REFIID iid, void **ppv)
HRESULT MetadataQueryReader_CreateInstance(IWICMetadataBlockReader *mbr, const WCHAR *root, IWICMetadataQueryReader **out)
const GUID * guid
#define isfinite(x)
Definition: mingw_math.h:91
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define SEEK_CUR
Definition: util.h:63
static LPOLESTR
Definition: stg_prop.c:27
static HPALETTE palette
Definition: clipboard.c:1345
static const WCHAR wszCompressionQuality[]
Definition: converter.c:641
static const WCHAR wszTiffCompressionMethod[]
Definition: converter.c:640
static UINT width_bytes(UINT width, UINT bpp)
Definition: tiffformat.c:888
#define RTLD_NOW
Definition: port.h:100
unsigned int UINT
Definition: ndis.h:50
_Out_ LPRECT prc
Definition: ntgdi.h:1658
#define V_UI1(A)
Definition: oleauto.h:266
#define V_VT(A)
Definition: oleauto.h:211
long LONG
Definition: pedump.c:60
#define IsEqualGUID(rguid1, rguid2)
Definition: guiddef.h:147
#define IsEqualIID(riid1, riid2)
Definition: guiddef.h:95
#define REFIID
Definition: guiddef.h:118
static calc_node_t temp
Definition: rpn_ieee.c:38
#define MAKE_FUNCPTR(f)
#define SONAME_LIBTIFF
Definition: config.h:1266
#define exit(n)
Definition: config.h:202
int byte_swapped
Definition: utils.c:251
int zero
Definition: sehframes.cpp:29
HRESULT hr
Definition: shlfolder.c:183
#define TRACE(s)
Definition: solgame.cpp:4
& rect
Definition: startmenu.cpp:1413
INT Height
Definition: wincodec.idl:301
INT Width
Definition: wincodec.idl:300
LIST_ENTRY ProcessLocksList
Definition: winbase.h:883
ULONGLONG QuadPart
Definition: ms-dtyp.idl:185
Definition: reader.h:84
Definition: send.c:48
Definition: parse.h:23
Definition: tiffiop.h:115
#define max(a, b)
Definition: svc.c:63
static void swap_bytes(void *buf, size_t samplesize, size_t samplecount)
VOID WINAPI InitializeCriticalSection(OUT LPCRITICAL_SECTION lpCriticalSection)
Definition: synch.c:751
static BOOL initialized
Definition: syslog.c:39
rwlock_t lock
Definition: tcpcore.h:0
void TIFFClose(TIFF *tif)
Definition: tif_close.c:122
uint64 TIFFCurrentDirOffset(TIFF *tif)
Definition: tif_dir.c:1666
int TIFFSetField(TIFF *tif, uint32 tag,...)
Definition: tif_dir.c:807
int TIFFGetField(TIFF *tif, uint32 tag,...)
Definition: tif_dir.c:1232
int TIFFSetDirectory(TIFF *tif, uint16 dirn)
Definition: tif_dir.c:1617
uint16 TIFFNumberOfDirectories(TIFF *tif)
Definition: tif_dir.c:1586
int TIFFReadDirectory(TIFF *tif)
Definition: tif_dirread.c:3574
int TIFFWriteDirectory(TIFF *tif)
Definition: tif_dirwrite.c:180
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
int TIFFIsByteSwapped(TIFF *tif)
Definition: tif_open.c:639
tmsize_t TIFFReadEncodedStrip(TIFF *tif, uint32 strip, void *buf, tmsize_t size)
Definition: tif_read.c:527
tmsize_t TIFFReadEncodedTile(TIFF *tif, uint32 tile, void *buf, tmsize_t size)
Definition: tif_read.c:978
int TIFFWriteScanline(TIFF *tif, void *buf, uint32 row, uint16 sample)
Definition: tif_write.c:47
#define TIFFTAG_BITSPERSAMPLE
Definition: tiff.h:156
#define TIFFTAG_RESOLUTIONUNIT
Definition: tiff.h:261
#define TIFFTAG_SAMPLESPERPIXEL
Definition: tiff.h:231
#define TIFFTAG_COLORMAP
Definition: tiff.h:283
#define TIFFTAG_PHOTOMETRIC
Definition: tiff.h:194
#define TIFFTAG_TILELENGTH
Definition: tiff.h:286
#define TIFFTAG_EXTRASAMPLES
Definition: tiff.h:303
#define TIFFTAG_IMAGEWIDTH
Definition: tiff.h:154
#define TIFFTAG_XRESOLUTION
Definition: tiff.h:236
#define TIFFTAG_ICCPROFILE
Definition: tiff.h:431
#define TIFFTAG_YRESOLUTION
Definition: tiff.h:237
#define TIFFTAG_ROWSPERSTRIP
Definition: tiff.h:232
#define TIFFTAG_TILEWIDTH
Definition: tiff.h:285
#define TIFFTAG_IMAGELENGTH
Definition: tiff.h:155
#define TIFFTAG_PLANARCONFIG
Definition: tiff.h:238
uint64 toff_t
Definition: tiffio.h:66
tmsize_t tsize_t
Definition: tiffio.h:75
#define DWORD_PTR
Definition: treelist.c:76
int32_t INT
Definition: typedefs.h:58
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t ULONG
Definition: typedefs.h:59
LONGLONG QuadPart
Definition: typedefs.h:114
HRESULT WINAPI DECLSPEC_HOTPATCH VariantClear(VARIANTARG *pVarg)
Definition: variant.c:648
void WINAPI VariantInit(VARIANTARG *pVarg)
Definition: variant.c:568
int ret
void WINAPI LeaveCriticalSection(LPCRITICAL_SECTION)
void WINAPI EnterCriticalSection(LPCRITICAL_SECTION)
void WINAPI DeleteCriticalSection(PCRITICAL_SECTION)
WICBitmapEncoderCacheOption
Definition: wincodec.idl:69
@ WICTiffCompressionDontCare
Definition: wincodec.idl:168
WICDecodeOptions
Definition: wincodec.idl:27
@ WICDecodeMetadataCacheOnDemand
Definition: wincodec.idl:28
UINT32 WICColor
Definition: wincodec.idl:312
@ WICBitmapDecoderCapabilityCanDecodeSomeImages
Definition: wincodec.idl:50
@ WICBitmapDecoderCapabilityCanEnumerateMetadata
Definition: wincodec.idl:51
@ WICBitmapDecoderCapabilityCanDecodeAllImages
Definition: wincodec.idl:49
static const char * debug_wic_rect(const WICRect *rect)
@ WICPersistOptionBigEndian
Definition: wincodecsdk.idl:25
@ WICPersistOptionLittleEndian
Definition: wincodecsdk.idl:24
@ WICPersistOptionNoCacheStream
Definition: wincodecsdk.idl:27
#define WINAPI
Definition: msvc.h:6
#define WINCODEC_ERR_WRONGSTATE
Definition: winerror.h:3281
#define WINCODEC_ERR_UNSUPPORTEDOPERATION
Definition: winerror.h:3308
#define WINCODEC_ERR_NOTINITIALIZED
Definition: winerror.h:3285
#define E_NOINTERFACE
Definition: winerror.h:2364
#define WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT
Definition: winerror.h:3307
#define WINCODEC_ERR_PALETTEUNAVAILABLE
Definition: winerror.h:3292
#define WINCODEC_ERR_CODECNOTHUMBNAIL
Definition: winerror.h:3291
#define WINCODEC_ERR_FRAMEMISSING
Definition: winerror.h:3301
__wchar_t WCHAR
Definition: xmlstorage.h:180
unsigned char BYTE
Definition: xxhash.c:193