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