1 /*
2 *
3 * tiffcodec.c : Contains function definitions for encoding decoding tiff images
4 *
5 *
6 * Copyright (C) Novell, Inc. 2003-2004.
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
9 * and associated documentation files (the "Software"), to deal in the Software without restriction,
10 * including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
12 * subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in all copies or substantial
15 * portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
18 * NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
21 * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 *
23 * Authors:
24 * Sanjay Gupta (gsanjay@novell.com)
25 * Vladimir Vukicevic (vladimir@pobox.com)
26 * Jordi Mas (jordi@ximian.com)
27 *
28 * Copyright (C) Novell, Inc. 2003-2004.
29 */
30
31 #include "config.h"
32 #include "codecs-private.h"
33 #include "tiffcodec.h"
34
35 GUID gdip_tif_image_format_guid = {0xb96b3cb1U, 0x0728U, 0x11d3U, {0x9d, 0x7b, 0x00, 0x00, 0xf8, 0x1e, 0xf3, 0x2e}};
36
37 #ifdef HAVE_LIBTIFF
38
39 /* Thankfully, libtiff sucks far less than libjpeg */
40 #include <tiffio.h>
41
42 #ifdef HAVE_BYTESWAP_H
43 #include <byteswap.h>
44 #endif
45
46 #ifndef TIFFTAG_EXIFIFD
47 #define TIFFTAG_EXIFIFD 34665
48 #endif
49
50
51 /* Codecinfo related data*/
52 static ImageCodecInfo tiff_codec;
53 static const WCHAR tiff_codecname[] = {'B', 'u', 'i','l', 't', '-','i', 'n', ' ', 'T', 'I', 'F', 'F', ' ', 'C', 'o', 'd', 'e', 'c', 0}; /* Built-in TIFF Codec */
54 static const WCHAR tiff_extension[] = {'*', '.', 'T', 'I', 'F',';', '*', '.', 'T', 'I', 'F','F', 0}; /* *.TIF;*.TIFF */
55 static const WCHAR tiff_mimetype[] = {'i', 'm', 'a','g', 'e', '/', 't', 'i', 'f', 'f', 0}; /* image/tiff */
56 static const WCHAR tiff_format[] = {'T', 'I', 'F', 'F', 0}; /* TIFF */
57 static const BYTE tiff_sig_pattern[] = { 0x49, 0x49, 0x4D, 0x4D };
58 static const BYTE tiff_sig_mask[] = { 0xFF, 0xFF, 0xFF, 0xFF };
59
60 /*Wrapper functions and client data strucutre for delegate functions from StreamHelper class of
61 System.Drawing Namespace*/
62 typedef struct {
63 GetBytesDelegate getBytesFunc;
64 PutBytesDelegate putBytesFunc;
65 SeekDelegate seekFunc;
66 CloseDelegate closeFunc;
67 SizeDelegate sizeFunc;
68 } gdip_tiff_clientData;
69
70 static tsize_t
gdip_tiff_fileread(thandle_t clientData,tdata_t buffer,tsize_t size)71 gdip_tiff_fileread (thandle_t clientData, tdata_t buffer, tsize_t size)
72 {
73 return (tsize_t)fread(buffer, 1, size, (FILE*)clientData);
74 }
75
76 static tsize_t
gdip_tiff_filewrite(thandle_t clientData,tdata_t buffer,tsize_t size)77 gdip_tiff_filewrite (thandle_t clientData, tdata_t buffer, tsize_t size)
78 {
79 return (tsize_t)fwrite (buffer, 1, size, (FILE*)clientData);
80 }
81
82 static toff_t
gdip_tiff_fileseek(thandle_t clientData,toff_t offSet,int whence)83 gdip_tiff_fileseek (thandle_t clientData, toff_t offSet, int whence)
84 {
85 int seek_ok = fseek ((FILE*)clientData, offSet, whence);
86 if (seek_ok == 0)
87 return offSet;
88
89 return -1;
90 }
91
92 static int
gdip_tiff_fileclose(thandle_t clientData)93 gdip_tiff_fileclose (thandle_t clientData)
94 {
95 /* This is a TIFF cleanup function; but we own the FILE* and close it in image.c so this is a null op */
96 return 0;
97 }
98
99 static toff_t
gdip_tiff_filesize(thandle_t clientData)100 gdip_tiff_filesize (thandle_t clientData)
101 {
102 long ret;
103 long cur_pos = ftell ((FILE*)clientData);
104 fseek ((FILE*)clientData, 0, SEEK_END);
105 ret = ftell ((FILE*)clientData);
106 fseek ((FILE*)clientData, cur_pos, SEEK_SET);
107 return (toff_t)ret;
108 }
109
110 static int
gdip_tiff_filedummy_map(thandle_t clientData,tdata_t * phase,toff_t * size)111 gdip_tiff_filedummy_map (thandle_t clientData, tdata_t *phase, toff_t* size)
112 {
113 return 0;
114 }
115
116 static void
gdip_tiff_filedummy_unmap(thandle_t clientData,tdata_t base,toff_t size)117 gdip_tiff_filedummy_unmap (thandle_t clientData, tdata_t base, toff_t size)
118 {
119 }
120
121 static tsize_t
gdip_tiff_read(thandle_t clientData,tdata_t buffer,tsize_t size)122 gdip_tiff_read (thandle_t clientData, tdata_t buffer, tsize_t size)
123 {
124 return (tsize_t)((gdip_tiff_clientData *) clientData)->getBytesFunc (buffer, size, 0);
125 }
126
127 static tsize_t
gdip_tiff_read_none(thandle_t clientData,tdata_t buffer,tsize_t size)128 gdip_tiff_read_none (thandle_t clientData, tdata_t buffer, tsize_t size)
129 {
130 return 0;
131 }
132
133 static tsize_t
gdip_tiff_write(thandle_t clientData,tdata_t buffer,tsize_t size)134 gdip_tiff_write (thandle_t clientData, tdata_t buffer, tsize_t size)
135 {
136 return (tsize_t)((gdip_tiff_clientData *) clientData)->putBytesFunc (buffer, size);
137 }
138
139 static toff_t
gdip_tiff_seek(thandle_t clientData,toff_t offSet,int whence)140 gdip_tiff_seek (thandle_t clientData, toff_t offSet, int whence)
141 {
142 return (toff_t)((gdip_tiff_clientData *) clientData)->seekFunc (offSet, whence);
143 }
144
145 static int
gdip_tiff_close(thandle_t clientData)146 gdip_tiff_close (thandle_t clientData)
147 {
148 /* We should not close the user provided streams */
149 /* ((gdip_tiff_clientData *) clientData)->closeFunc (); */
150 return 1;
151 }
152
153 static toff_t
gdip_tiff_size(thandle_t clientData)154 gdip_tiff_size (thandle_t clientData)
155 {
156 return (toff_t)((gdip_tiff_clientData *) clientData)->sizeFunc ();
157 }
158
159 static int
gdip_tiff_dummy_map(thandle_t clientData,tdata_t * phase,toff_t * size)160 gdip_tiff_dummy_map (thandle_t clientData, tdata_t *phase, toff_t* size)
161 {
162 return 0;
163 }
164
165 static void
gdip_tiff_dummy_unmap(thandle_t clientData,tdata_t base,toff_t size)166 gdip_tiff_dummy_unmap (thandle_t clientData, tdata_t base, toff_t size)
167 {
168 }
169
170 ImageCodecInfo *
gdip_getcodecinfo_tiff()171 gdip_getcodecinfo_tiff ()
172 {
173 tiff_codec.Clsid = (CLSID) { 0x557cf405, 0x1a04, 0x11d3, { 0x9a, 0x73, 0x0, 0x0, 0xf8, 0x1e, 0xf3, 0x2e } };
174 tiff_codec.FormatID = gdip_tif_image_format_guid;
175 tiff_codec.CodecName = (const WCHAR*) tiff_codecname;
176 tiff_codec.DllName = NULL;
177 tiff_codec.FormatDescription = (const WCHAR*) tiff_format;
178 tiff_codec.FilenameExtension = (const WCHAR*) tiff_extension;
179 tiff_codec.MimeType = (const WCHAR*) tiff_mimetype;
180 tiff_codec.Flags = ImageCodecFlagsEncoder | ImageCodecFlagsDecoder | ImageCodecFlagsSupportBitmap | ImageCodecFlagsBuiltin;
181 tiff_codec.Version = 1;
182 tiff_codec.SigCount = 2;
183 tiff_codec.SigSize = 2;
184 tiff_codec.SigPattern = tiff_sig_pattern;
185 tiff_codec.SigMask = tiff_sig_mask;
186
187 /* Mute the lib */
188 TIFFSetErrorHandler(NULL);
189 TIFFSetWarningHandler(NULL);
190
191 return &tiff_codec;
192 }
193
194 static GpStatus
gdip_load_tiff_properties(TIFF * tiff,ActiveBitmapData * bitmap_data)195 gdip_load_tiff_properties (TIFF *tiff, ActiveBitmapData *bitmap_data)
196 {
197 BYTE *text;
198 uint32 i;
199 uint16 s;
200 uint16 s2;
201 double d;
202 float f;
203 uint16 samples_per_pixel;
204 uint16 bits_per_sample;
205 uint16 planar_configuration;
206 uint32 image_length;
207 uint16 strips_per_image;
208 uint32 rows_per_strip;
209 uint32 tile_length;
210 uint32 tile_width;
211 uint16 compression = 0;
212
213 samples_per_pixel = 0;
214 bits_per_sample = 0;
215 planar_configuration = 0;
216 image_length = 0;
217 strips_per_image = 0;
218 rows_per_strip = 0;
219 tile_length = 0;
220 tile_width = 0;
221 i = 0;
222 s = 0;
223 s2 = 0;
224
225 if (TIFFGetField(tiff, TIFFTAG_ARTIST, &text)) {
226 gdip_bitmapdata_property_add_ASCII(bitmap_data, PropertyTagArtist, text);
227 }
228
229 if (TIFFGetField(tiff, TIFFTAG_BITSPERSAMPLE, &bits_per_sample)) {
230 gdip_bitmapdata_property_add_short(bitmap_data, PropertyTagBitsPerSample, bits_per_sample);
231 }
232
233 {
234 uint16 *rmap;
235 uint16 *gmap;
236 uint16 *bmap;
237
238 if (TIFFGetField(tiff, TIFFTAG_COLORMAP, &rmap, &gmap, &bmap)) {
239 BYTE *buffer;
240 uint16 *ptr;
241
242 if ((rmap != NULL) && (gmap != NULL) && (bmap != NULL)) {
243 buffer = GdipAlloc (3 * bits_per_sample * sizeof (uint16));
244 if (buffer != NULL) {
245 ptr = (uint16 *)buffer;
246
247 for (i = 0; i < bits_per_sample; i++) {
248 ptr[0] = rmap[i];
249 ptr[1] = gmap[i];
250 ptr[2] = bmap[i];
251 ptr += 3;
252 }
253 gdip_bitmapdata_property_add(bitmap_data, PropertyTagColorMap,
254 3 * bits_per_sample * sizeof(uint16), PropertyTagTypeShort, buffer);
255 GdipFree(buffer);
256 }
257 }
258 }
259 }
260
261 if (TIFFGetField(tiff, TIFFTAG_COMPRESSION, &s)) {
262 compression = s;
263 gdip_bitmapdata_property_add_short(bitmap_data, PropertyTagCompression, s);
264 }
265
266 if (TIFFGetField(tiff, TIFFTAG_COPYRIGHT, &text)) {
267 gdip_bitmapdata_property_add_ASCII(bitmap_data, PropertyTagCopyright, text);
268 }
269
270 if (TIFFGetField(tiff, TIFFTAG_DATETIME, &text)) {
271 gdip_bitmapdata_property_add_ASCII(bitmap_data, PropertyTagDateTime, text);
272 }
273
274 if (TIFFGetField(tiff, TIFFTAG_DOCUMENTNAME, &text)) {
275 gdip_bitmapdata_property_add_ASCII(bitmap_data, PropertyTagDocumentName, text);
276 }
277
278 if (TIFFGetField(tiff, TIFFTAG_DOTRANGE, &s, &s2)) {
279 gdip_bitmapdata_property_add_srational(bitmap_data, PropertyTagDotRange, s, s2);
280 }
281
282 {
283 uint16 count;
284 uint16 *samples;
285
286 if (TIFFGetField(tiff, TIFFTAG_EXTRASAMPLES, &count, &samples)) {
287 if ((count > 0) && (samples != NULL)) {
288 gdip_bitmapdata_property_add(bitmap_data, PropertyTagExtraSamples, count * sizeof(uint16),
289 PropertyTagTypeShort, samples);
290 }
291 }
292 }
293
294 if (TIFFGetField(tiff, TIFFTAG_FILLORDER, &s)) {
295 gdip_bitmapdata_property_add_short(bitmap_data, PropertyTagFillOrder, s);
296 }
297
298 if (TIFFGetField(tiff, TIFFTAG_GROUP3OPTIONS, &i, &i)) {
299 gdip_bitmapdata_property_add_long(bitmap_data, PropertyTagT4Option, i);
300 }
301
302 if (TIFFGetField(tiff, TIFFTAG_GROUP4OPTIONS, &i)) {
303 gdip_bitmapdata_property_add_long(bitmap_data, PropertyTagT6Option, i);
304 }
305
306 if (TIFFGetField(tiff, TIFFTAG_HALFTONEHINTS, &s, &s2)) {
307 gdip_bitmapdata_property_add_srational(bitmap_data, PropertyTagHalftoneHints, s, s2);
308 }
309
310 if (TIFFGetField(tiff, TIFFTAG_HOSTCOMPUTER, &text)) {
311 gdip_bitmapdata_property_add_ASCII(bitmap_data, PropertyTagHostComputer, text);
312 }
313
314 if (TIFFGetField(tiff, TIFFTAG_IMAGEDESCRIPTION, &text)) {
315 gdip_bitmapdata_property_add_ASCII(bitmap_data, PropertyTagImageDescription, text);
316 }
317
318 if (TIFFGetField(tiff, TIFFTAG_IMAGEWIDTH, &i)) {
319 gdip_bitmapdata_property_add_long(bitmap_data, PropertyTagImageWidth, i);
320 }
321
322 if (TIFFGetField(tiff, TIFFTAG_IMAGELENGTH, &image_length)) {
323 gdip_bitmapdata_property_add_long(bitmap_data, PropertyTagImageHeight, image_length);
324 }
325
326 if (TIFFGetField(tiff, TIFFTAG_INKNAMES, &text)) {
327 gdip_bitmapdata_property_add_ASCII(bitmap_data, PropertyTagInkNames, text);
328 }
329
330 if (TIFFGetField(tiff, TIFFTAG_INKSET, &s)) {
331 gdip_bitmapdata_property_add_short(bitmap_data, PropertyTagInkSet, s);
332 }
333
334
335 #ifdef NotImplemented
336 /* Don't know how this property should be stored, datatype is void */
337 {
338 uint32 count;
339 void *tables;
340
341 if (TIFFGetField(tiff, TIFFTAG_JPEGTABLES, &count, &tables)) {
342 gdip_bitmapdata_property_add(bitmap_data, PropertyTagJPEGTables, text);
343 }
344 }
345 #endif
346
347 if (TIFFGetField(tiff, TIFFTAG_JPEGQUALITY, &i)) {
348 gdip_bitmapdata_property_add_long(bitmap_data, PropertyTagJPEGQuality, i);
349 }
350
351 if (TIFFGetField(tiff, TIFFTAG_MAKE, &text)) {
352 gdip_bitmapdata_property_add_ASCII(bitmap_data, PropertyTagEquipMake, text);
353 }
354
355 if (TIFFGetField(tiff, TIFFTAG_MAXSAMPLEVALUE, &s)) {
356 gdip_bitmapdata_property_add_short(bitmap_data, PropertyTagMaxSampleValue, s);
357 }
358
359 if (TIFFGetField(tiff, TIFFTAG_MINSAMPLEVALUE, &s)) {
360 gdip_bitmapdata_property_add_short(bitmap_data, PropertyTagMinSampleValue, s);
361 }
362
363 if (TIFFGetField(tiff, TIFFTAG_MODEL, &text)) {
364 gdip_bitmapdata_property_add_ASCII(bitmap_data, PropertyTagEquipModel, text);
365 }
366
367 if (TIFFGetField(tiff, TIFFTAG_ORIENTATION, &s)) {
368 gdip_bitmapdata_property_add_short(bitmap_data, PropertyTagOrientation, s);
369 }
370
371 if (TIFFGetField(tiff, TIFFTAG_PAGENAME, &text)) {
372 gdip_bitmapdata_property_add_ASCII(bitmap_data, PropertyTagPageName, text);
373 }
374
375 if (TIFFGetField(tiff, TIFFTAG_PAGENUMBER, &s, &s2)) {
376 gdip_bitmapdata_property_add_short(bitmap_data, PropertyTagPageNumber, s);
377 }
378
379 if (TIFFGetField(tiff, TIFFTAG_PHOTOMETRIC, &s)) {
380 gdip_bitmapdata_property_add_short(bitmap_data, PropertyTagPhotometricInterp, s);
381 }
382
383 if (TIFFGetField(tiff, TIFFTAG_PLANARCONFIG, &planar_configuration)) {
384 gdip_bitmapdata_property_add_short(bitmap_data, PropertyTagPlanarConfig, planar_configuration);
385 }
386
387 if (compression == COMPRESSION_ADOBE_DEFLATE) {
388 if (TIFFGetField(tiff, TIFFTAG_PREDICTOR, &s)) {
389 gdip_bitmapdata_property_add_short(bitmap_data, PropertyTagPredictor, s);
390 }
391 }
392
393 {
394 float *chromacities = NULL; /* 6-entry array */
395
396 if (TIFFGetField(tiff, TIFFTAG_PRIMARYCHROMATICITIES, &chromacities) && (chromacities != NULL)) {
397 BYTE *buffer;
398 uint32 *ptr;
399
400 buffer = GdipAlloc(6 * (sizeof(uint32) + sizeof(uint32)));
401 if (buffer != NULL) {
402 ptr = (uint32 *)buffer;
403
404 for (i = 0; i < 6; i++) {
405 ptr[0] = (uint32)(chromacities[i] * 1000000);
406 ptr[1] = 1000000;
407 ptr += 2;
408 }
409 gdip_bitmapdata_property_add (bitmap_data, PropertyTagPrimaryChromaticities,
410 6 * (sizeof(uint32) + sizeof(uint32)), PropertyTagTypeRational, buffer);
411 GdipFree(buffer);
412 }
413 }
414 }
415
416 if (TIFFGetField(tiff, TIFFTAG_RESOLUTIONUNIT, &s)) {
417 gdip_bitmapdata_property_add_short(bitmap_data, PropertyTagResolutionUnit, s);
418 }
419
420 if (TIFFGetField(tiff, TIFFTAG_ROWSPERSTRIP, &rows_per_strip)) {
421 gdip_bitmapdata_property_add_long(bitmap_data, PropertyTagRowsPerStrip, rows_per_strip);
422 }
423
424 if (TIFFGetField(tiff, TIFFTAG_SAMPLEFORMAT, &s)) {
425 gdip_bitmapdata_property_add_short(bitmap_data, PropertyTagSampleFormat, s);
426 }
427
428 if (TIFFGetField(tiff, TIFFTAG_SAMPLESPERPIXEL, &samples_per_pixel)) {
429 gdip_bitmapdata_property_add_short(bitmap_data, PropertyTagSamplesPerPixel, samples_per_pixel);
430 }
431
432 if (samples_per_pixel > 0) {
433 float *ref_blackwhite; /* 2 * SamplesPerPixel array */
434
435 if (TIFFGetField(tiff, TIFFTAG_REFERENCEBLACKWHITE, &ref_blackwhite)) {
436 BYTE *buffer;
437 uint32 *ptr;
438
439 buffer = GdipAlloc(2 * samples_per_pixel * (sizeof(uint32) + sizeof(uint32)));
440 if (buffer != NULL) {
441 ptr = (uint32 *)buffer;
442
443 for (i = 0; i < 2 * samples_per_pixel; i++) {
444 ptr[0] = (uint32)(ref_blackwhite[i] * 1000000);
445 ptr[1] = 1000000;
446 ptr += 2;
447 }
448 gdip_bitmapdata_property_add (bitmap_data, PropertyTagREFBlackWhite,
449 6 * (sizeof(uint32) + sizeof(uint32)), PropertyTagTypeRational, buffer);
450 GdipFree(buffer);
451 }
452 }
453 }
454
455
456 if (TIFFGetField(tiff, TIFFTAG_SMAXSAMPLEVALUE, &d)) {
457 gdip_bitmapdata_property_add_rational(bitmap_data, PropertyTagSMaxSampleValue, d * 1000000, 1000000);
458 }
459
460 if (TIFFGetField(tiff, TIFFTAG_SMINSAMPLEVALUE, &d)) {
461 gdip_bitmapdata_property_add_rational(bitmap_data, PropertyTagSMinSampleValue, d * 1000000, 1000000);
462 }
463
464 if (TIFFGetField(tiff, TIFFTAG_SOFTWARE, &text)) {
465 gdip_bitmapdata_property_add_ASCII(bitmap_data, PropertyTagSoftwareUsed, text);
466 }
467
468 if ((rows_per_strip != 0) && (planar_configuration != 0)) {
469 uint32 *bytecounts;
470 uint32 *offsets;
471 int count;
472
473 strips_per_image = floor ((image_length + rows_per_strip - 1) / rows_per_strip);
474
475 if (planar_configuration == 1) {
476 count = strips_per_image;
477 } else {
478 count = samples_per_pixel * strips_per_image;
479 }
480
481 if (TIFFGetField(tiff, TIFFTAG_STRIPBYTECOUNTS, &bytecounts)) {
482 gdip_bitmapdata_property_add(bitmap_data, PropertyTagStripBytesCount,
483 count * sizeof(uint32), PropertyTagTypeLong, bytecounts);
484 }
485
486 if (TIFFGetField(tiff, TIFFTAG_STRIPOFFSETS, &offsets)) {
487 gdip_bitmapdata_property_add(bitmap_data, PropertyTagStripOffsets,
488 count * sizeof(uint32), PropertyTagTypeLong, offsets);
489 }
490 }
491
492 if (TIFFGetField(tiff, TIFFTAG_SUBFILETYPE, &i)) {
493 gdip_bitmapdata_property_add_long(bitmap_data, PropertyTagNewSubfileType, i);
494 }
495
496 if (TIFFGetField(tiff, TIFFTAG_TARGETPRINTER, &text)) {
497 gdip_bitmapdata_property_add_ASCII(bitmap_data, PropertyTagTargetPrinter, text);
498 }
499
500 if (TIFFGetField(tiff, TIFFTAG_THRESHHOLDING, &s)) {
501 gdip_bitmapdata_property_add_short(bitmap_data, PropertyTagThreshHolding, s);
502 }
503
504 if (TIFFGetField(tiff, TIFFTAG_TILEWIDTH, &tile_width)) {
505 gdip_bitmapdata_property_add_long(bitmap_data, PropertyTagTileWidth, tile_width);
506 }
507
508 if (TIFFGetField(tiff, TIFFTAG_TILELENGTH, &tile_length)) {
509 gdip_bitmapdata_property_add_long(bitmap_data, PropertyTagTileLength, tile_length);
510 }
511
512 if ((planar_configuration != 0) && (tile_width != 0) && (tile_length != 0)) {
513 uint32 *byte_counts;
514 uint32 *offsets;
515 uint32 tiles_across;
516 uint32 tiles_down;
517 int tiles_per_image;
518 int count;
519
520 tiles_across = (image_length + tile_width - 1) / tile_width;
521 tiles_down = (image_length + tile_length - 1) / tile_length;
522 tiles_per_image = tiles_across * tiles_down;
523
524 if (planar_configuration == 1) {
525 count = tiles_per_image;
526 } else {
527 count = samples_per_pixel * tiles_per_image;
528 }
529
530 if (TIFFGetField(tiff, TIFFTAG_TILEBYTECOUNTS, &byte_counts)) {
531 gdip_bitmapdata_property_add(bitmap_data, PropertyTagTileByteCounts, count * sizeof(uint32),
532 PropertyTagTypeLong, byte_counts);
533 }
534
535 if (TIFFGetField(tiff, TIFFTAG_TILEOFFSETS, &offsets)) {
536 gdip_bitmapdata_property_add(bitmap_data, PropertyTagTileOffset, count * sizeof(uint32),
537 PropertyTagTypeLong, offsets);
538 }
539 }
540
541 if (samples_per_pixel == 1) {
542 uint16 *sample;
543
544 if (TIFFGetField(tiff, TIFFTAG_TRANSFERFUNCTION, &sample)) {
545 gdip_bitmapdata_property_add (bitmap_data, PropertyTagTransferFuncition,
546 (1 << bits_per_sample) * (ULONG) sizeof(uint16), PropertyTagTypeShort, sample);
547 }
548 } else if (samples_per_pixel == 3) {
549 uint16 *r;
550 uint16 *g;
551 uint16 *b;
552
553 if (TIFFGetField(tiff, TIFFTAG_TRANSFERFUNCTION, &r, &g, &b)) {
554 BYTE *buffer;
555 uint16 *ptr;
556
557 buffer = GdipAlloc(3 * (1 << samples_per_pixel) * sizeof(uint16));
558 if (buffer != NULL) {
559 ptr = (uint16 *)buffer;
560
561 for (i = 0; i < 1 << bits_per_sample; i++) {
562 ptr[i] = r[i];
563 ptr[i + 1] = g[i];
564 ptr[i + 2] = b[i];
565 }
566 gdip_bitmapdata_property_add (bitmap_data, PropertyTagTransferFuncition,
567 3 * (1 << samples_per_pixel) * sizeof(uint16), PropertyTagTypeShort, buffer);
568 GdipFree(buffer);
569 }
570 }
571 }
572
573 {
574 float *whitepoints;
575
576 if (TIFFGetField(tiff, TIFFTAG_WHITEPOINT, &whitepoints)) {
577 BYTE *buffer;
578 uint32 *ptr;
579
580 buffer = GdipAlloc(2 * (sizeof(uint32) + sizeof(uint32)));
581 if (buffer != NULL) {
582 ptr = (uint32 *)buffer;
583
584 ptr[0] = whitepoints[0] * 1000000;
585 ptr[1] = 1000000;
586
587 ptr[2] = whitepoints[1] * 1000000;
588 ptr[3] = 1000000;
589
590 gdip_bitmapdata_property_add (bitmap_data, PropertyTagTransferFuncition,
591 2 * (sizeof(uint32) + sizeof(uint32)), PropertyTagTypeRational, buffer);
592 GdipFree(buffer);
593 }
594
595 gdip_bitmapdata_property_add_rational(bitmap_data, PropertyTagWhitePoint, whitepoints[0] * 1000000, 1000000);
596 }
597 }
598
599 if (TIFFGetField(tiff, TIFFTAG_XPOSITION, &f)) {
600 gdip_bitmapdata_property_add_rational(bitmap_data, PropertyTagXPosition, f * 1000000, 1000000);
601 }
602
603 if (TIFFGetField(tiff, TIFFTAG_XRESOLUTION, &f)) {
604 gdip_bitmapdata_property_add_rational(bitmap_data, PropertyTagXResolution, f, 1);
605 }
606
607 {
608 float *coefficients;
609
610 if (TIFFGetField(tiff, TIFFTAG_YCBCRCOEFFICIENTS, &coefficients)) {
611 BYTE buffer[sizeof(uint32) * 6];
612 uint32 *ptr;
613
614 ptr = (uint32 *)&buffer;
615 ptr[0] = (uint32)(coefficients[0] * 1000000);
616 ptr[1] = 1000000;
617 ptr[2] = (uint32)(coefficients[1] * 1000000);
618 ptr[3] = 1000000;
619 ptr[4] = (uint32)(coefficients[2] * 1000000);
620 ptr[5] = 1000000;
621
622 gdip_bitmapdata_property_add(bitmap_data, PropertyTagYCbCrCoefficients, sizeof(uint32) * 6,
623 PropertyTagTypeRational, buffer);
624 }
625 }
626
627 if (TIFFGetField(tiff, TIFFTAG_YCBCRPOSITIONING, &s)) {
628 gdip_bitmapdata_property_add_short(bitmap_data, PropertyTagYCbCrPositioning, s);
629 }
630
631 if (TIFFGetField(tiff, TIFFTAG_YCBCRSUBSAMPLING, &s, &s2)) {
632 gdip_bitmapdata_property_add_srational(bitmap_data, PropertyTagYCbCrSubsampling, s, s2);
633 }
634
635 if (TIFFGetField(tiff, TIFFTAG_YPOSITION, &f)) {
636 gdip_bitmapdata_property_add_rational(bitmap_data, PropertyTagYPosition, f * 1000000, 1000000);
637 }
638
639 if (TIFFGetField(tiff, TIFFTAG_YRESOLUTION, &f)) {
640 gdip_bitmapdata_property_add_rational(bitmap_data, PropertyTagYResolution, f, 1);
641 }
642
643 #ifdef NotImplemented
644 /* Not sure what type the data is */
645 {
646 uint32 count;
647 void *profile_data;
648
649 if (TIFFGetField(tiff, TIFFTAG_ICCPROFILE, &count, &profile_data)) {
650 gdip_bitmapdata_property_add(bitmap_data, PropertyTagICCProfile, count * sizeof(void *), , profile_data);
651 }
652 }
653 #endif
654
655 /* EXIF section */
656 if (TIFFGetField(tiff, TIFFTAG_EXIFIFD, &i)) {
657 gdip_bitmapdata_property_add_long(bitmap_data, PropertyTagExifIFD, i);
658 }
659
660 return Ok;
661 }
662
663 static GpStatus
gdip_save_tiff_properties(TIFF * tiff,ActiveBitmapData * bitmap_data,int samples_per_pixel,int bits_per_sample)664 gdip_save_tiff_properties (TIFF *tiff, ActiveBitmapData *bitmap_data, int samples_per_pixel, int bits_per_sample)
665 {
666 int index;
667 guint32 i;
668 guint32 l;
669 int j;
670 uint16 s;
671 uint16 s2;
672 double d;
673 float f;
674
675 i = 0;
676 s = 0;
677 s2 = 0;
678 d = 0;
679
680 if (gdip_bitmapdata_property_find_id(bitmap_data, PropertyTagArtist, &index) == Ok) {
681 TIFFSetField(tiff, TIFFTAG_ARTIST, bitmap_data->property[index].value);
682 }
683
684 if (gdip_bitmapdata_property_find_id(bitmap_data, PropertyTagCopyright, &index) == Ok) {
685 TIFFSetField(tiff, TIFFTAG_COPYRIGHT, bitmap_data->property[index].value);
686 }
687
688 if (gdip_bitmapdata_property_find_id(bitmap_data, PropertyTagDateTime, &index) == Ok) {
689 TIFFSetField(tiff, TIFFTAG_DATETIME, bitmap_data->property[index].value);
690 }
691
692 if (gdip_bitmapdata_property_find_id(bitmap_data, PropertyTagDocumentName, &index) == Ok) {
693 TIFFSetField(tiff, TIFFTAG_DOCUMENTNAME, bitmap_data->property[index].value);
694 }
695
696 if (gdip_bitmapdata_property_find_id(bitmap_data, PropertyTagDotRange, &index) == Ok) {
697 gdip_property_get_short(0, bitmap_data->property[index].value, &s);
698 gdip_property_get_short(2, bitmap_data->property[index].value, &s2);
699 TIFFSetField(tiff, TIFFTAG_DOTRANGE, s, s2);
700 }
701
702 if (gdip_bitmapdata_property_find_id(bitmap_data, PropertyTagExtraSamples, &index) == Ok) {
703 TIFFSetField(tiff, TIFFTAG_EXTRASAMPLES, bitmap_data->property[index].length, bitmap_data->property[index].value);
704 } else {
705 TIFFSetField (tiff, TIFFTAG_EXTRASAMPLES, 1, EXTRASAMPLE_UNSPECIFIED);
706 }
707
708 if (gdip_bitmapdata_property_find_id(bitmap_data, PropertyTagFillOrder, &index) == Ok) {
709 gdip_property_get_short(0, bitmap_data->property[index].value, &s);
710 TIFFSetField(tiff, TIFFTAG_FILLORDER, s);
711 }
712
713 if (gdip_bitmapdata_property_find_id(bitmap_data, PropertyTagT4Option, &index) == Ok) {
714 gdip_property_get_long(0, bitmap_data->property[index].value, &l);
715 TIFFSetField(tiff, TIFFTAG_GROUP3OPTIONS, l);
716 }
717
718 if (gdip_bitmapdata_property_find_id(bitmap_data, PropertyTagT6Option, &index) == Ok) {
719 gdip_property_get_long(0, bitmap_data->property[index].value, &l);
720 TIFFSetField(tiff, TIFFTAG_GROUP4OPTIONS, l);
721 }
722
723 if (gdip_bitmapdata_property_find_id(bitmap_data, PropertyTagHalftoneHints, &index) == Ok) {
724 gdip_property_get_short(0, bitmap_data->property[index].value, &s);
725 gdip_property_get_short(2, bitmap_data->property[index].value, &s2);
726 TIFFSetField(tiff, TIFFTAG_HALFTONEHINTS, s, s2);
727 }
728
729 if (gdip_bitmapdata_property_find_id(bitmap_data, PropertyTagHostComputer, &index) == Ok) {
730 TIFFSetField(tiff, TIFFTAG_HOSTCOMPUTER, bitmap_data->property[index].value);
731 }
732
733 if (gdip_bitmapdata_property_find_id(bitmap_data, PropertyTagImageDescription, &index) == Ok) {
734 TIFFSetField(tiff, TIFFTAG_IMAGEDESCRIPTION, bitmap_data->property[index].value);
735 }
736
737 if (gdip_bitmapdata_property_find_id(bitmap_data, PropertyTagInkNames, &index) == Ok) {
738 TIFFSetField(tiff, TIFFTAG_INKNAMES, bitmap_data->property[index].value);
739 }
740
741 if (gdip_bitmapdata_property_find_id(bitmap_data, PropertyTagInkSet, &index) == Ok) {
742 gdip_property_get_short(0, bitmap_data->property[index].value, &s);
743 TIFFSetField(tiff, TIFFTAG_INKSET, s);
744 }
745
746 if (gdip_bitmapdata_property_find_id(bitmap_data, PropertyTagJPEGQuality, &index) == Ok) {
747 gdip_property_get_long(0, bitmap_data->property[index].value, &l);
748 TIFFSetField(tiff, TIFFTAG_JPEGQUALITY, l);
749 }
750
751 if (gdip_bitmapdata_property_find_id(bitmap_data, PropertyTagEquipMake, &index) == Ok) {
752 TIFFSetField(tiff, TIFFTAG_MAKE, bitmap_data->property[index].value);
753 }
754
755 if (gdip_bitmapdata_property_find_id(bitmap_data, PropertyTagMaxSampleValue, &index) == Ok) {
756 gdip_property_get_short(0, bitmap_data->property[index].value, &s);
757 TIFFSetField(tiff, TIFFTAG_MAXSAMPLEVALUE, s);
758 }
759
760 if (gdip_bitmapdata_property_find_id(bitmap_data, PropertyTagMinSampleValue, &index) == Ok) {
761 gdip_property_get_short(0, bitmap_data->property[index].value, &s);
762 TIFFSetField(tiff, TIFFTAG_MINSAMPLEVALUE, s);
763 }
764
765 if (gdip_bitmapdata_property_find_id(bitmap_data, PropertyTagEquipModel, &index) == Ok) {
766 TIFFSetField(tiff, TIFFTAG_MODEL, bitmap_data->property[index].value);
767 }
768
769 if (gdip_bitmapdata_property_find_id(bitmap_data, PropertyTagOrientation, &index) == Ok) {
770 gdip_property_get_short(0, bitmap_data->property[index].value, &s);
771 TIFFSetField(tiff, TIFFTAG_ORIENTATION, s);
772 }
773
774 if (gdip_bitmapdata_property_find_id(bitmap_data, PropertyTagPageName, &index) == Ok) {
775 TIFFSetField(tiff, TIFFTAG_PAGENAME, bitmap_data->property[index].value);
776 }
777
778 if (gdip_bitmapdata_property_find_id(bitmap_data, PropertyTagPhotometricInterp, &index) == Ok) {
779 gdip_property_get_short(0, bitmap_data->property[index].value, &s);
780 TIFFSetField(tiff, TIFFTAG_PHOTOMETRIC, s);
781 }
782
783 if (gdip_bitmapdata_property_find_id(bitmap_data, PropertyTagPredictor, &index) == Ok) {
784 gdip_property_get_short(0, bitmap_data->property[index].value, &s);
785 TIFFSetField(tiff, TIFFTAG_PREDICTOR, s);
786 }
787
788 if (gdip_bitmapdata_property_find_id(bitmap_data, PropertyTagPrimaryChromaticities, &index) == Ok) {
789 float chromacities[6];
790 for (j = 0; j < 6; j++) {
791 gdip_property_get_long(j * 8, bitmap_data->property[index].value, &i);
792 chromacities[j] = (float)i / 1000000;
793 }
794
795 TIFFSetField(tiff, TIFFTAG_PRIMARYCHROMATICITIES, &chromacities);
796 }
797
798 if (gdip_bitmapdata_property_find_id(bitmap_data, PropertyTagResolutionUnit, &index) == Ok) {
799 gdip_property_get_short(0, bitmap_data->property[index].value, &s);
800 TIFFSetField(tiff, TIFFTAG_RESOLUTIONUNIT, s);
801 }
802
803 if (gdip_bitmapdata_property_find_id(bitmap_data, PropertyTagSampleFormat, &index) == Ok) {
804 gdip_property_get_short(0, bitmap_data->property[index].value, &s);
805 TIFFSetField(tiff, TIFFTAG_SAMPLEFORMAT, s);
806 }
807
808 if (gdip_bitmapdata_property_find_id(bitmap_data, PropertyTagREFBlackWhite, &index) == Ok) {
809 float *ref_blackwhite; /* 2 * SamplesPerPixel array */
810
811 ref_blackwhite = GdipAlloc(2 * samples_per_pixel * sizeof(float));
812 if (ref_blackwhite != NULL) {
813 for (j = 0; j < (2 * samples_per_pixel); j++) {
814 gdip_property_get_long(j * 8, bitmap_data->property[index].value, &i);
815 ref_blackwhite[j] = (float)i / 1000000;
816 }
817 TIFFSetField(tiff, TIFFTAG_REFERENCEBLACKWHITE, &ref_blackwhite);
818 GdipFree(ref_blackwhite);
819 }
820 }
821
822 if (gdip_bitmapdata_property_find_id(bitmap_data, PropertyTagSMaxSampleValue, &index) == Ok) {
823 gdip_property_get_long(0, bitmap_data->property[index].value, &i);
824 d = (double)i / 10000000;
825 TIFFSetField(tiff, TIFFTAG_SMAXSAMPLEVALUE, d);
826 }
827
828 if (gdip_bitmapdata_property_find_id(bitmap_data, PropertyTagSMinSampleValue, &index) == Ok) {
829 gdip_property_get_long(0, bitmap_data->property[index].value, &i);
830 d = (double)i / 10000000;
831 TIFFSetField(tiff, TIFFTAG_SMINSAMPLEVALUE, d);
832 }
833
834 if (gdip_bitmapdata_property_find_id(bitmap_data, PropertyTagSoftwareUsed, &index) == Ok) {
835 TIFFSetField(tiff, TIFFTAG_SOFTWARE, bitmap_data->property[index].value);
836 }
837
838 if (gdip_bitmapdata_property_find_id(bitmap_data, PropertyTagNewSubfileType, &index) == Ok) {
839 TIFFSetField(tiff, TIFFTAG_SUBFILETYPE, bitmap_data->property[index].value);
840 }
841
842 if (gdip_bitmapdata_property_find_id(bitmap_data, PropertyTagNewSubfileType, &index) == Ok) {
843 gdip_property_get_long(0, bitmap_data->property[index].value, &l);
844 TIFFSetField(tiff, TIFFTAG_SUBFILETYPE, l);
845 }
846
847 if (gdip_bitmapdata_property_find_id(bitmap_data, PropertyTagTargetPrinter, &index) == Ok) {
848 TIFFSetField(tiff, TIFFTAG_TARGETPRINTER, bitmap_data->property[index].value);
849 }
850
851 if (gdip_bitmapdata_property_find_id(bitmap_data, PropertyTagThreshHolding, &index) == Ok) {
852 gdip_property_get_short(0, bitmap_data->property[index].value, &s);
853 TIFFSetField(tiff, TIFFTAG_THRESHHOLDING, s);
854 }
855
856
857 if (samples_per_pixel == 1) {
858 if (gdip_bitmapdata_property_find_id(bitmap_data, PropertyTagTransferFuncition, &index) == Ok) {
859 TIFFSetField(tiff, TIFFTAG_TRANSFERFUNCTION, bitmap_data->property[index].value);
860 }
861 } else if (samples_per_pixel == 3) {
862 if (gdip_bitmapdata_property_find_id(bitmap_data, PropertyTagTransferFuncition, &index) == Ok) {
863 uint16 *rmap;
864 uint16 *gmap;
865 uint16 *bmap;
866
867 rmap = GdipAlloc ((1 << samples_per_pixel) * (ULONG) sizeof (uint16));
868 gmap = GdipAlloc ((1 << samples_per_pixel) * (ULONG) sizeof (uint16));
869 bmap = GdipAlloc ((1 << samples_per_pixel) * (ULONG) sizeof (uint16));
870
871 if ((rmap != NULL) && (gmap != NULL) && (bmap != NULL)) {
872 for (j = 0; j < 1 << bits_per_sample; j++) {
873 gdip_property_get_short((j * 3), bitmap_data->property[index].value, &rmap[j]);
874 gdip_property_get_short((j * 3) + 1, bitmap_data->property[index].value, &gmap[j]);
875 gdip_property_get_short((j * 3) + 2, bitmap_data->property[index].value, &bmap[j]);
876 }
877 TIFFSetField(tiff, TIFFTAG_TRANSFERFUNCTION, rmap, gmap, bmap);
878 }
879 if (rmap != NULL) {
880 GdipFree(rmap);
881 }
882
883 if (gmap != NULL) {
884 GdipFree(gmap);
885 }
886
887 if (bmap != NULL) {
888 GdipFree(bmap);
889 }
890 }
891 }
892
893 if (gdip_bitmapdata_property_find_id(bitmap_data, PropertyTagXPosition, &index) == Ok) {
894 gdip_property_get_long(0, bitmap_data->property[index].value, &i);
895 f = (float)i / 10000000;
896 TIFFSetField(tiff, TIFFTAG_XPOSITION, f);
897 }
898
899 if (gdip_bitmapdata_property_find_id(bitmap_data, PropertyTagXResolution, &index) == Ok) {
900 gdip_property_get_long(0, bitmap_data->property[index].value, &i);
901 f = (float)i;
902 TIFFSetField(tiff, TIFFTAG_XRESOLUTION, f);
903 }
904
905 if (gdip_bitmapdata_property_find_id(bitmap_data, PropertyTagYCbCrCoefficients, &index) == Ok) {
906 float coefficients[3];
907
908 gdip_property_get_long(0, bitmap_data->property[index].value, &i);
909 coefficients[0] = (float)i / 1000000;
910
911 gdip_property_get_long(8, bitmap_data->property[index].value, &i);
912 coefficients[1] = (float)i / 1000000;
913
914 gdip_property_get_long(16, bitmap_data->property[index].value, &i);
915 coefficients[2] = (float)i / 1000000;
916
917 TIFFSetField(tiff, TIFFTAG_YCBCRCOEFFICIENTS, coefficients);
918 }
919
920 if (TIFFGetField(tiff, TIFFTAG_YCBCRPOSITIONING, &s)) {
921 gdip_bitmapdata_property_add_short(bitmap_data, PropertyTagYCbCrPositioning, s);
922 }
923
924 if (TIFFGetField(tiff, TIFFTAG_YCBCRSUBSAMPLING, &s, &s2)) {
925 gdip_bitmapdata_property_add_srational(bitmap_data, PropertyTagYCbCrSubsampling, s, s2);
926 }
927
928 if (gdip_bitmapdata_property_find_id(bitmap_data, PropertyTagYPosition, &index) == Ok) {
929 gdip_property_get_long(0, bitmap_data->property[index].value, &i);
930 f = (float)i / 1000000;
931 TIFFSetField(tiff, TIFFTAG_YPOSITION, f);
932 }
933
934 if (gdip_bitmapdata_property_find_id(bitmap_data, PropertyTagYResolution, &index) == Ok) {
935 gdip_property_get_long(0, bitmap_data->property[index].value, &i);
936 f = (float)i;
937 TIFFSetField(tiff, TIFFTAG_YRESOLUTION, f);
938 }
939
940 if (gdip_bitmapdata_property_find_id(bitmap_data, PropertyTagExifIFD, &index) == Ok) {
941 gdip_property_get_long(0, bitmap_data->property[index].value, &i);
942 TIFFSetField(tiff, TIFFTAG_EXIFIFD, d);
943 }
944
945 return Ok;
946 }
947
948 /*TODO Handle TIFF Encoder Parameters*/
949 static GpStatus
gdip_save_tiff_image(TIFF * tiff,GpImage * image,GDIPCONST EncoderParameters * params)950 gdip_save_tiff_image (TIFF* tiff, GpImage *image, GDIPCONST EncoderParameters *params)
951 {
952 int frame;
953 int x;
954 int y;
955 int i;
956 int num_of_pages;
957 int page;
958 ActiveBitmapData *bitmap_data;
959 BYTE *pixbuf;
960 int samples_per_pixel;
961 int bits_per_sample;
962 unsigned long long int size;
963
964 if (tiff == NULL) {
965 return InvalidParameter;
966 }
967
968 /* Count all pages, we need to know ahead */
969 num_of_pages = 0;
970 for (frame = 0; frame < image->num_of_frames; frame++) {
971 num_of_pages += image->frames[frame].count;
972 for (i = 0; i < image->frames[frame].count; i++) {
973 if (gdip_is_an_indexed_pixelformat (image->frames[frame].bitmap[i].pixel_format)) {
974 return NotImplemented; /* FIXME? */
975 }
976 }
977 }
978
979 page = 0;
980 for (frame = 0; frame < image->num_of_frames; frame++) {
981 for (i = 0; i < image->frames[frame].count; i++) {
982 bitmap_data = &image->frames[frame].bitmap[i];
983
984 if (num_of_pages > 1) {
985 if ((frame > 0) && (i > 0)) {
986 TIFFCreateDirectory(tiff);
987 }
988
989 TIFFSetField (tiff, TIFFTAG_SUBFILETYPE, FILETYPE_PAGE);
990 TIFFSetField (tiff, TIFFTAG_PAGENUMBER, page, num_of_pages);
991 }
992
993 if (((bitmap_data->pixel_format & PixelFormatAlpha) != 0) || (bitmap_data->pixel_format == PixelFormat32bppRGB)) {
994 samples_per_pixel = 4;
995 bits_per_sample = 8;
996 } else {
997 samples_per_pixel = 3;
998 bits_per_sample = 8;
999 }
1000 gdip_save_tiff_properties(tiff, bitmap_data, samples_per_pixel, bits_per_sample);
1001
1002 TIFFSetField (tiff, TIFFTAG_SAMPLESPERPIXEL, samples_per_pixel);
1003 TIFFSetField (tiff, TIFFTAG_IMAGEWIDTH, bitmap_data->width);
1004 TIFFSetField (tiff, TIFFTAG_IMAGELENGTH, bitmap_data->height);
1005 TIFFSetField (tiff, TIFFTAG_BITSPERSAMPLE, bits_per_sample);
1006 TIFFSetField (tiff, TIFFTAG_COMPRESSION, COMPRESSION_NONE);
1007 TIFFSetField (tiff, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);
1008 TIFFSetField (tiff, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
1009 TIFFSetField (tiff, TIFFTAG_ROWSPERSTRIP, TIFFDefaultStripSize (tiff, bitmap_data->stride));
1010 TIFFSetField (tiff, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
1011
1012 size = (unsigned long long int)bitmap_data->width * samples_per_pixel;
1013 if (size > G_MAXINT32) {
1014 goto error;
1015 }
1016
1017 pixbuf = GdipAlloc (size);
1018 if (pixbuf == NULL) {
1019 goto error;
1020 }
1021 if (samples_per_pixel == 4) {
1022 for (y = 0; y < bitmap_data->height; y++) {
1023 for (x = 0; x < bitmap_data->width; x++) {
1024 #ifdef WORDS_BIGENDIAN
1025 pixbuf[x*4+0] = *((BYTE*)bitmap_data->scan0 + (bitmap_data->stride * y) + (x*4) + 1);
1026 pixbuf[x*4+1] = *((BYTE*)bitmap_data->scan0 + (bitmap_data->stride * y) + (x*4) + 2);
1027 pixbuf[x*4+2] = *((BYTE*)bitmap_data->scan0 + (bitmap_data->stride * y) + (x*4) + 3);
1028 pixbuf[x*4+3] = *((BYTE*)bitmap_data->scan0 + (bitmap_data->stride * y) + (x*4) + 0);
1029 #else
1030 pixbuf[x*4+0] = *((BYTE*)bitmap_data->scan0 + (bitmap_data->stride * y) + (x*4) + 2);
1031 pixbuf[x*4+1] = *((BYTE*)bitmap_data->scan0 + (bitmap_data->stride * y) + (x*4) + 1);
1032 pixbuf[x*4+2] = *((BYTE*)bitmap_data->scan0 + (bitmap_data->stride * y) + (x*4) + 0);
1033 pixbuf[x*4+3] = *((BYTE*)bitmap_data->scan0 + (bitmap_data->stride * y) + (x*4) + 3);
1034 #endif
1035 }
1036 TIFFWriteScanline (tiff, pixbuf, y, 0);
1037 }
1038 } else {
1039 for (y = 0; y < bitmap_data->height; y++) {
1040 for (x = 0; x < bitmap_data->width; x++) {
1041 #ifdef WORDS_BIGENDIAN
1042 pixbuf[x*3+0] = *((BYTE*)bitmap_data->scan0 + (bitmap_data->stride * y) + (x*4) + 1);
1043 pixbuf[x*3+1] = *((BYTE*)bitmap_data->scan0 + (bitmap_data->stride * y) + (x*4) + 2);
1044 pixbuf[x*3+2] = *((BYTE*)bitmap_data->scan0 + (bitmap_data->stride * y) + (x*4) + 3);
1045 #else
1046 pixbuf[x*3+0] = *((BYTE*)bitmap_data->scan0 + (bitmap_data->stride * y) + (x*4) + 2);
1047 pixbuf[x*3+1] = *((BYTE*)bitmap_data->scan0 + (bitmap_data->stride * y) + (x*4) + 1);
1048 pixbuf[x*3+2] = *((BYTE*)bitmap_data->scan0 + (bitmap_data->stride * y) + (x*4) + 0);
1049 #endif
1050 }
1051 TIFFWriteScanline (tiff, pixbuf, y, 0);
1052 }
1053 }
1054 GdipFree(pixbuf);
1055 TIFFWriteDirectory (tiff);
1056 page++;
1057 }
1058 }
1059 TIFFClose (tiff);
1060 return Ok;
1061
1062 error:
1063 TIFFClose (tiff);
1064 return OutOfMemory;
1065 }
1066
1067
1068 static GpStatus
gdip_load_tiff_image(TIFF * tiff,GpImage ** image)1069 gdip_load_tiff_image (TIFF *tiff, GpImage **image)
1070 {
1071 int i;
1072 char error_message[1024];
1073 int num_of_pages;
1074 GpImage *result;
1075 int page;
1076 TIFFRGBAImage tiff_image;
1077 FrameData *frame;
1078 ActiveBitmapData *bitmap_data;
1079 char *pixbuf;
1080 char *pixbuf_row;
1081 guint32 *pixbuf_ptr;
1082 guint16 samples_per_pixel;
1083 float dpi;
1084
1085 if (tiff == NULL) {
1086 *image = NULL;
1087 /* we cannot call TIFFClose(tiff); with a NULL value since it will crash - bnc #569940 */
1088 return OutOfMemory;
1089 }
1090
1091 result = NULL;
1092 pixbuf_row = NULL;
1093 pixbuf = NULL;
1094 memset (&tiff_image, 0, sizeof (TIFFRGBAImage));
1095
1096 num_of_pages = TIFFNumberOfDirectories(tiff);
1097
1098 /* Handle cases where there are too many directories or there is a infinite loop in the directory structure.
1099 * This relies on libtiff returning 65535 in the error case, which has been the case since v4.0.4 released in 2015. */
1100 if (num_of_pages >= 65535)
1101 goto error;
1102
1103 result = gdip_bitmap_new();
1104 if (!result)
1105 goto error;
1106
1107 result->type = ImageTypeBitmap;
1108 frame = gdip_frame_add(result, &gdip_image_frameDimension_page_guid);
1109 if (!frame)
1110 goto error;
1111
1112 for (page = 0; page < num_of_pages; page++) {
1113 unsigned long long int size;
1114
1115 bitmap_data = gdip_frame_add_bitmapdata(frame);
1116 if (bitmap_data == NULL) {
1117 goto error;
1118 }
1119
1120 if (!TIFFSetDirectory(tiff, page)) {
1121 goto error;
1122 }
1123
1124 gdip_load_tiff_properties(tiff, bitmap_data);
1125
1126 if (!TIFFRGBAImageBegin (&tiff_image, tiff, 0, error_message)) {
1127 goto error;
1128 }
1129
1130 if (TIFFGetField(tiff, TIFFTAG_SAMPLESPERPIXEL, &samples_per_pixel)) {
1131 if (samples_per_pixel != 4) {
1132 bitmap_data->pixel_format = PixelFormat24bppRGB;
1133 } else {
1134 bitmap_data->pixel_format = PixelFormat32bppARGB;
1135 bitmap_data->image_flags |= ImageFlagsHasAlpha;
1136 }
1137 }
1138
1139 if (TIFFGetField(tiff, TIFFTAG_XRESOLUTION, &dpi)) {
1140 bitmap_data->dpi_horz = dpi;
1141 } else {
1142 bitmap_data->dpi_horz = 0;
1143 }
1144
1145 if (TIFFGetField(tiff, TIFFTAG_YRESOLUTION, &dpi)) {
1146 bitmap_data->dpi_vert = dpi;
1147 } else {
1148 bitmap_data->dpi_vert = 0;
1149 }
1150
1151 if (bitmap_data->dpi_horz && bitmap_data->dpi_vert)
1152 bitmap_data->image_flags |= ImageFlagsHasRealDPI;
1153
1154 /* width and height are uint32, but TIFF uses 32 bits offsets (so it's real size limit is 4GB),
1155 * however libtiff uses signed int (int32 not uint32) as offsets so we limit ourselves to 2GB */
1156 size = tiff_image.width;
1157 /* stride is a (signed) _int_ and once multiplied by 4 it should hold a value that can be allocated by GdipAlloc
1158 * this effectively limits 'width' to 536870911 pixels */
1159 size *= sizeof (guint32);
1160 if (size > G_MAXINT32)
1161 goto error;
1162 bitmap_data->stride = size;
1163 bitmap_data->width = tiff_image.width;
1164 bitmap_data->height = tiff_image.height;
1165 bitmap_data->reserved = GBD_OWN_SCAN0;
1166 bitmap_data->image_flags |= ImageFlagsColorSpaceRGB | ImageFlagsHasRealPixelSize | ImageFlagsReadOnly;
1167
1168 /* ensure total 'size' does not overflow an integer and fits inside our 2GB limit */
1169 size *= tiff_image.height;
1170 if (size > G_MAXINT32)
1171 goto error;
1172 pixbuf = GdipAlloc (size);
1173 if (pixbuf == NULL) {
1174 goto error;
1175 }
1176
1177 /* Flip the image. TIFF has its origin at bottom left, and is in ARGB instead of ABGR */
1178 if (!TIFFRGBAImageGet(&tiff_image, (uint32 *)pixbuf, tiff_image.width, tiff_image.height)) {
1179 goto error;
1180 }
1181
1182 pixbuf_row = GdipAlloc(bitmap_data->stride);
1183 if (pixbuf_row == NULL) {
1184 goto error;
1185 }
1186
1187 /* First, flip rows */
1188 for (i = 0; i < tiff_image.height / 2; i++) {
1189 memcpy(pixbuf_row, pixbuf + (bitmap_data->stride * i), bitmap_data->stride);
1190 memcpy(pixbuf + (bitmap_data->stride * i), pixbuf + (bitmap_data->stride * (tiff_image.height - i - 1)), bitmap_data->stride);
1191 memcpy(pixbuf + (bitmap_data->stride * (tiff_image.height - i - 1)), pixbuf_row, bitmap_data->stride);
1192 }
1193
1194 /* Now flip from ARGB to ABGR processing one pixel (4 bytes) at the time */
1195 pixbuf_ptr = (guint32 *)pixbuf;
1196 for (i = 0; i < (size >> 2); i++) {
1197 *pixbuf_ptr = (*pixbuf_ptr & 0xff000000) |
1198 ((*pixbuf_ptr & 0x00ff0000) >> 16) |
1199 (*pixbuf_ptr & 0x0000ff00) |
1200 ((*pixbuf_ptr & 0x000000ff) << 16);
1201 pixbuf_ptr++;
1202 }
1203 GdipFree(pixbuf_row);
1204 bitmap_data->scan0 = (BYTE*) pixbuf;
1205 pixbuf_row = NULL;
1206 pixbuf = NULL;
1207
1208 TIFFRGBAImageEnd (&tiff_image);
1209 }
1210
1211 gdip_bitmap_setactive(result, &gdip_image_frameDimension_page_guid, 0);
1212
1213 TIFFClose(tiff);
1214
1215 *image = result;
1216 return Ok;
1217
1218 error:
1219 /* coverity[dead_error_line] */
1220 if (pixbuf_row != NULL) {
1221 GdipFree(pixbuf_row);
1222 }
1223
1224 if (pixbuf != NULL) {
1225 GdipFree(pixbuf);
1226 }
1227
1228 if (result != NULL) {
1229 gdip_bitmap_dispose(result);
1230 }
1231
1232 TIFFRGBAImageEnd (&tiff_image);
1233 TIFFClose(tiff);
1234
1235 return OutOfMemory;
1236 }
1237
1238 GpStatus
gdip_load_tiff_image_from_file(FILE * fp,GpImage ** image)1239 gdip_load_tiff_image_from_file (FILE *fp, GpImage **image)
1240 {
1241 TIFF *tif = NULL;
1242
1243 tif = TIFFClientOpen("<stream>", "r", (thandle_t) fp, gdip_tiff_fileread,
1244 gdip_tiff_filewrite, gdip_tiff_fileseek, gdip_tiff_fileclose,
1245 gdip_tiff_filesize, gdip_tiff_filedummy_map, gdip_tiff_filedummy_unmap);
1246 return gdip_load_tiff_image (tif, image);
1247 }
1248
1249 GpStatus
gdip_save_tiff_image_to_file(BYTE * filename,GpImage * image,GDIPCONST EncoderParameters * params)1250 gdip_save_tiff_image_to_file (BYTE *filename, GpImage *image, GDIPCONST EncoderParameters *params)
1251 {
1252 TIFF* tiff;
1253
1254 tiff = TIFFOpen((char *)filename, "w");
1255
1256 if (!tiff)
1257 return FileNotFound;
1258
1259 return gdip_save_tiff_image (tiff, image, params);
1260 }
1261
1262 GpStatus
gdip_load_tiff_image_from_stream_delegate(GetBytesDelegate getBytesFunc,PutBytesDelegate putBytesFunc,SeekDelegate seekFunc,CloseDelegate closeFunc,SizeDelegate sizeFunc,GpImage ** image)1263 gdip_load_tiff_image_from_stream_delegate (GetBytesDelegate getBytesFunc,
1264 PutBytesDelegate putBytesFunc,
1265 SeekDelegate seekFunc,
1266 CloseDelegate closeFunc,
1267 SizeDelegate sizeFunc,
1268 GpImage **image)
1269 {
1270 TIFF *tif = NULL;
1271 gdip_tiff_clientData clientData;
1272
1273 clientData.getBytesFunc = getBytesFunc;
1274 clientData.putBytesFunc = putBytesFunc;
1275 clientData.seekFunc = seekFunc;
1276 clientData.closeFunc = closeFunc;
1277 clientData.sizeFunc = sizeFunc;
1278
1279 tif = TIFFClientOpen("<stream>", "r", (thandle_t) &clientData, gdip_tiff_read,
1280 gdip_tiff_write, gdip_tiff_seek, gdip_tiff_close,
1281 gdip_tiff_size, gdip_tiff_dummy_map, gdip_tiff_dummy_unmap);
1282
1283 return gdip_load_tiff_image (tif, image);
1284 }
1285
1286 GpStatus
gdip_save_tiff_image_to_stream_delegate(GetBytesDelegate getBytesFunc,PutBytesDelegate putBytesFunc,SeekDelegate seekFunc,CloseDelegate closeFunc,SizeDelegate sizeFunc,GpImage * image,GDIPCONST EncoderParameters * params)1287 gdip_save_tiff_image_to_stream_delegate (GetBytesDelegate getBytesFunc,
1288 PutBytesDelegate putBytesFunc,
1289 SeekDelegate seekFunc,
1290 CloseDelegate closeFunc,
1291 SizeDelegate sizeFunc,
1292 GpImage *image,
1293 GDIPCONST EncoderParameters *params)
1294 {
1295 TIFF* tiff;
1296 gdip_tiff_clientData clientData;
1297
1298 clientData.getBytesFunc = getBytesFunc;
1299 clientData.putBytesFunc = putBytesFunc;
1300 clientData.seekFunc = seekFunc;
1301 clientData.closeFunc = closeFunc;
1302 clientData.sizeFunc = sizeFunc;
1303
1304 tiff = TIFFClientOpen("<stream>", "w", (thandle_t) &clientData, gdip_tiff_read_none,
1305 gdip_tiff_write, gdip_tiff_seek, gdip_tiff_close,
1306 gdip_tiff_size, gdip_tiff_dummy_map, gdip_tiff_dummy_unmap);
1307 if (!tiff)
1308 return InvalidParameter;
1309
1310 return gdip_save_tiff_image (tiff, image, params);
1311 }
1312
1313 #else
1314
1315 /* no libtiff */
1316
1317 #include "image.h"
1318
1319 ImageCodecInfo *
gdip_getcodecinfo_tiff()1320 gdip_getcodecinfo_tiff ()
1321 {
1322 return NULL;
1323 }
1324
1325 GpStatus
gdip_load_tiff_image_from_file(FILE * fp,GpImage ** image)1326 gdip_load_tiff_image_from_file (FILE *fp, GpImage **image)
1327 {
1328 *image = NULL;
1329 return UnknownImageFormat;
1330 }
1331
1332 GpStatus
gdip_load_tiff_image_from_stream_delegate(GetBytesDelegate getBytesFunc,PutBytesDelegate putBytesFunc,SeekDelegate seekFunc,CloseDelegate closeFunc,SizeDelegate sizeFunc,GpImage ** image)1333 gdip_load_tiff_image_from_stream_delegate (GetBytesDelegate getBytesFunc,
1334 PutBytesDelegate putBytesFunc,
1335 SeekDelegate seekFunc,
1336 CloseDelegate closeFunc,
1337 SizeDelegate sizeFunc,
1338 GpImage **image)
1339 {
1340 *image = NULL;
1341 return UnknownImageFormat;
1342 }
1343
1344 GpStatus
gdip_save_tiff_image_to_file(BYTE * filename,GpImage * image,GDIPCONST EncoderParameters * params)1345 gdip_save_tiff_image_to_file (BYTE *filename, GpImage *image, GDIPCONST EncoderParameters *params)
1346 {
1347 return UnknownImageFormat;
1348 }
1349
1350 GpStatus
gdip_save_tiff_image_to_stream_delegate(GetBytesDelegate getBytesFunc,PutBytesDelegate putBytesFunc,SeekDelegate seekFunc,CloseDelegate closeFunc,SizeDelegate sizeFunc,GpImage * image,GDIPCONST EncoderParameters * params)1351 gdip_save_tiff_image_to_stream_delegate (GetBytesDelegate getBytesFunc,
1352 PutBytesDelegate putBytesFunc,
1353 SeekDelegate seekFunc,
1354 CloseDelegate closeFunc,
1355 SizeDelegate sizeFunc,
1356 GpImage *image,
1357 GDIPCONST EncoderParameters *params)
1358 {
1359 return UnknownImageFormat;
1360 }
1361 #endif
1362
1363 GpStatus
gdip_fill_encoder_parameter_list_tiff(EncoderParameters * buffer,UINT size)1364 gdip_fill_encoder_parameter_list_tiff (EncoderParameters *buffer, UINT size)
1365 {
1366 TiffEncoderParameters *tiffBuffer = (TiffEncoderParameters *) buffer;
1367
1368 if (!buffer || size != sizeof (TiffEncoderParameters))
1369 return InvalidParameter;
1370
1371 tiffBuffer->count = 4;
1372
1373 tiffBuffer->compression.Guid = GdipEncoderCompression;
1374 tiffBuffer->compression.NumberOfValues = 5;
1375 tiffBuffer->compression.Type = EncoderParameterValueTypeLong;
1376 tiffBuffer->compressionData[0] = EncoderValueCompressionLZW;
1377 tiffBuffer->compressionData[1] = EncoderValueCompressionCCITT3;
1378 tiffBuffer->compressionData[2] = EncoderValueCompressionRle;
1379 tiffBuffer->compressionData[3] = EncoderValueCompressionCCITT4;
1380 tiffBuffer->compressionData[4] = EncoderValueCompressionNone;
1381 tiffBuffer->compression.Value = &tiffBuffer->compressionData;
1382
1383 tiffBuffer->colorDepth.Guid = GdipEncoderColorDepth;
1384 tiffBuffer->colorDepth.NumberOfValues = 5;
1385 tiffBuffer->colorDepth.Type = EncoderParameterValueTypeLong;
1386 tiffBuffer->colorDepthData[0] = 1;
1387 tiffBuffer->colorDepthData[1] = 4;
1388 tiffBuffer->colorDepthData[2] = 8;
1389 tiffBuffer->colorDepthData[3] = 24;
1390 tiffBuffer->colorDepthData[4] = 32;
1391 tiffBuffer->colorDepth.Value = &tiffBuffer->colorDepthData;
1392
1393 tiffBuffer->saveFlag.Guid = GdipEncoderSaveFlag;
1394 tiffBuffer->saveFlag.NumberOfValues = 1;
1395 tiffBuffer->saveFlag.Type = EncoderParameterValueTypeLong;
1396 tiffBuffer->saveFlagValue = EncoderValueMultiFrame;
1397 tiffBuffer->saveFlag.Value = &tiffBuffer->saveFlagValue;
1398
1399 tiffBuffer->saveAsCYMK.Guid = GdipEncoderSaveAsCMYK;
1400 tiffBuffer->saveAsCYMK.NumberOfValues = 1;
1401 tiffBuffer->saveAsCYMK.Type = EncoderParameterValueTypeLong;
1402 tiffBuffer->saveAsCYMKValue = 1;
1403 tiffBuffer->saveAsCYMK.Value = &tiffBuffer->saveAsCYMKValue;
1404
1405 return Ok;
1406 }
1407