• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 1991-1997 Sam Leffler
3  * Copyright (c) 1991-1997 Silicon Graphics, Inc.
4  *
5  * Permission to use, copy, modify, distribute, and sell this software and
6  * its documentation for any purpose is hereby granted without fee, provided
7  * that (i) the above copyright notices and this permission notice appear in
8  * all copies of the software and related documentation, and (ii) the names of
9  * Sam Leffler and Silicon Graphics may not be used in any advertising or
10  * publicity relating to the software without the specific, prior written
11  * permission of Sam Leffler and Silicon Graphics.
12  *
13  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
14  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
15  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
16  *
17  * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
18  * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
19  * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
20  * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
21  * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
22  * OF THIS SOFTWARE.
23  */
24 
25 /*
26  * TIFF Library
27  *
28  * Read and return a packed RGBA image.
29  */
30 #include "tiffiop.h"
31 #include <stdio.h>
32 #include <limits.h>
33 
34 static int gtTileContig(TIFFRGBAImage*, uint32*, uint32, uint32);
35 static int gtTileSeparate(TIFFRGBAImage*, uint32*, uint32, uint32);
36 static int gtStripContig(TIFFRGBAImage*, uint32*, uint32, uint32);
37 static int gtStripSeparate(TIFFRGBAImage*, uint32*, uint32, uint32);
38 static int PickContigCase(TIFFRGBAImage*);
39 static int PickSeparateCase(TIFFRGBAImage*);
40 
41 static int BuildMapUaToAa(TIFFRGBAImage* img);
42 static int BuildMapBitdepth16To8(TIFFRGBAImage* img);
43 
44 static const char photoTag[] = "PhotometricInterpretation";
45 
46 /*
47  * Helper constants used in Orientation tag handling
48  */
49 #define FLIP_VERTICALLY 0x01
50 #define FLIP_HORIZONTALLY 0x02
51 
52 /*
53  * Color conversion constants. We will define display types here.
54  */
55 
56 static const TIFFDisplay display_sRGB = {
57 	{			/* XYZ -> luminance matrix */
58 		{  3.2410F, -1.5374F, -0.4986F },
59 		{  -0.9692F, 1.8760F, 0.0416F },
60 		{  0.0556F, -0.2040F, 1.0570F }
61 	},
62 	100.0F, 100.0F, 100.0F,	/* Light o/p for reference white */
63 	255, 255, 255,		/* Pixel values for ref. white */
64 	1.0F, 1.0F, 1.0F,	/* Residual light o/p for black pixel */
65 	2.4F, 2.4F, 2.4F,	/* Gamma values for the three guns */
66 };
67 
68 /*
69  * Check the image to see if TIFFReadRGBAImage can deal with it.
70  * 1/0 is returned according to whether or not the image can
71  * be handled.  If 0 is returned, emsg contains the reason
72  * why it is being rejected.
73  */
74 int
TIFFRGBAImageOK(TIFF * tif,char emsg[1024])75 TIFFRGBAImageOK(TIFF* tif, char emsg[1024])
76 {
77 	TIFFDirectory* td = &tif->tif_dir;
78 	uint16 photometric;
79 	int colorchannels;
80 
81 	if (!tif->tif_decodestatus) {
82 		sprintf(emsg, "Sorry, requested compression method is not configured");
83 		return (0);
84 	}
85 	switch (td->td_bitspersample) {
86 		case 1:
87 		case 2:
88 		case 4:
89 		case 8:
90 		case 16:
91 			break;
92 		default:
93 			sprintf(emsg, "Sorry, can not handle images with %d-bit samples",
94 			    td->td_bitspersample);
95 			return (0);
96 	}
97         if (td->td_sampleformat == SAMPLEFORMAT_IEEEFP) {
98                 sprintf(emsg, "Sorry, can not handle images with IEEE floating-point samples");
99                 return (0);
100         }
101 	colorchannels = td->td_samplesperpixel - td->td_extrasamples;
102 	if (!TIFFGetField(tif, TIFFTAG_PHOTOMETRIC, &photometric)) {
103 		switch (colorchannels) {
104 			case 1:
105 				photometric = PHOTOMETRIC_MINISBLACK;
106 				break;
107 			case 3:
108 				photometric = PHOTOMETRIC_RGB;
109 				break;
110 			default:
111 				sprintf(emsg, "Missing needed %s tag", photoTag);
112 				return (0);
113 		}
114 	}
115 	switch (photometric) {
116 		case PHOTOMETRIC_MINISWHITE:
117 		case PHOTOMETRIC_MINISBLACK:
118 		case PHOTOMETRIC_PALETTE:
119 			if (td->td_planarconfig == PLANARCONFIG_CONTIG
120 			    && td->td_samplesperpixel != 1
121 			    && td->td_bitspersample < 8 ) {
122 				sprintf(emsg,
123 				    "Sorry, can not handle contiguous data with %s=%d, "
124 				    "and %s=%d and Bits/Sample=%d",
125 				    photoTag, photometric,
126 				    "Samples/pixel", td->td_samplesperpixel,
127 				    td->td_bitspersample);
128 				return (0);
129 			}
130 			/*
131 			 * We should likely validate that any extra samples are either
132 			 * to be ignored, or are alpha, and if alpha we should try to use
133 			 * them.  But for now we won't bother with this.
134 			*/
135 			break;
136 		case PHOTOMETRIC_YCBCR:
137 			/*
138 			 * TODO: if at all meaningful and useful, make more complete
139 			 * support check here, or better still, refactor to let supporting
140 			 * code decide whether there is support and what meaningful
141 			 * error to return
142 			 */
143 			break;
144 		case PHOTOMETRIC_RGB:
145 			if (colorchannels < 3) {
146 				sprintf(emsg, "Sorry, can not handle RGB image with %s=%d",
147 				    "Color channels", colorchannels);
148 				return (0);
149 			}
150 			break;
151 		case PHOTOMETRIC_SEPARATED:
152 			{
153 				uint16 inkset;
154 				TIFFGetFieldDefaulted(tif, TIFFTAG_INKSET, &inkset);
155 				if (inkset != INKSET_CMYK) {
156 					sprintf(emsg,
157 					    "Sorry, can not handle separated image with %s=%d",
158 					    "InkSet", inkset);
159 					return 0;
160 				}
161 				if (td->td_samplesperpixel < 4) {
162 					sprintf(emsg,
163 					    "Sorry, can not handle separated image with %s=%d",
164 					    "Samples/pixel", td->td_samplesperpixel);
165 					return 0;
166 				}
167 				break;
168 			}
169 		case PHOTOMETRIC_LOGL:
170 			if (td->td_compression != COMPRESSION_SGILOG) {
171 				sprintf(emsg, "Sorry, LogL data must have %s=%d",
172 				    "Compression", COMPRESSION_SGILOG);
173 				return (0);
174 			}
175 			break;
176 		case PHOTOMETRIC_LOGLUV:
177 			if (td->td_compression != COMPRESSION_SGILOG &&
178 			    td->td_compression != COMPRESSION_SGILOG24) {
179 				sprintf(emsg, "Sorry, LogLuv data must have %s=%d or %d",
180 				    "Compression", COMPRESSION_SGILOG, COMPRESSION_SGILOG24);
181 				return (0);
182 			}
183 			if (td->td_planarconfig != PLANARCONFIG_CONTIG) {
184 				sprintf(emsg, "Sorry, can not handle LogLuv images with %s=%d",
185 				    "Planarconfiguration", td->td_planarconfig);
186 				return (0);
187 			}
188 			if ( td->td_samplesperpixel != 3 || colorchannels != 3 ) {
189                                 sprintf(emsg,
190                                         "Sorry, can not handle image with %s=%d, %s=%d",
191                                         "Samples/pixel", td->td_samplesperpixel,
192                                         "colorchannels", colorchannels);
193                                 return 0;
194                         }
195 			break;
196 		case PHOTOMETRIC_CIELAB:
197                         if ( td->td_samplesperpixel != 3 || colorchannels != 3 || td->td_bitspersample != 8 ) {
198                                 sprintf(emsg,
199                                         "Sorry, can not handle image with %s=%d, %s=%d and %s=%d",
200                                         "Samples/pixel", td->td_samplesperpixel,
201                                         "colorchannels", colorchannels,
202                                         "Bits/sample", td->td_bitspersample);
203                                 return 0;
204                         }
205 			break;
206                 default:
207 			sprintf(emsg, "Sorry, can not handle image with %s=%d",
208 			    photoTag, photometric);
209 			return (0);
210 	}
211 	return (1);
212 }
213 
214 void
TIFFRGBAImageEnd(TIFFRGBAImage * img)215 TIFFRGBAImageEnd(TIFFRGBAImage* img)
216 {
217 	if (img->Map) {
218 		_TIFFfree(img->Map);
219 		img->Map = NULL;
220 	}
221 	if (img->BWmap) {
222 		_TIFFfree(img->BWmap);
223 		img->BWmap = NULL;
224 	}
225 	if (img->PALmap) {
226 		_TIFFfree(img->PALmap);
227 		img->PALmap = NULL;
228 	}
229 	if (img->ycbcr) {
230 		_TIFFfree(img->ycbcr);
231 		img->ycbcr = NULL;
232 	}
233 	if (img->cielab) {
234 		_TIFFfree(img->cielab);
235 		img->cielab = NULL;
236 	}
237 	if (img->UaToAa) {
238 		_TIFFfree(img->UaToAa);
239 		img->UaToAa = NULL;
240 	}
241 	if (img->Bitdepth16To8) {
242 		_TIFFfree(img->Bitdepth16To8);
243 		img->Bitdepth16To8 = NULL;
244 	}
245 
246 	if( img->redcmap ) {
247 		_TIFFfree( img->redcmap );
248 		_TIFFfree( img->greencmap );
249 		_TIFFfree( img->bluecmap );
250                 img->redcmap = img->greencmap = img->bluecmap = NULL;
251 	}
252 }
253 
254 static int
isCCITTCompression(TIFF * tif)255 isCCITTCompression(TIFF* tif)
256 {
257     uint16 compress;
258     TIFFGetField(tif, TIFFTAG_COMPRESSION, &compress);
259     return (compress == COMPRESSION_CCITTFAX3 ||
260 	    compress == COMPRESSION_CCITTFAX4 ||
261 	    compress == COMPRESSION_CCITTRLE ||
262 	    compress == COMPRESSION_CCITTRLEW);
263 }
264 
265 int
TIFFRGBAImageBegin(TIFFRGBAImage * img,TIFF * tif,int stop,char emsg[1024])266 TIFFRGBAImageBegin(TIFFRGBAImage* img, TIFF* tif, int stop, char emsg[1024])
267 {
268 	uint16* sampleinfo;
269 	uint16 extrasamples;
270 	uint16 planarconfig;
271 	uint16 compress;
272 	int colorchannels;
273 	uint16 *red_orig, *green_orig, *blue_orig;
274 	int n_color;
275 
276 	if( !TIFFRGBAImageOK(tif, emsg) )
277 		return 0;
278 
279 	/* Initialize to normal values */
280 	img->row_offset = 0;
281 	img->col_offset = 0;
282 	img->redcmap = NULL;
283 	img->greencmap = NULL;
284 	img->bluecmap = NULL;
285 	img->Map = NULL;
286 	img->BWmap = NULL;
287 	img->PALmap = NULL;
288 	img->ycbcr = NULL;
289 	img->cielab = NULL;
290 	img->UaToAa = NULL;
291 	img->Bitdepth16To8 = NULL;
292 	img->req_orientation = ORIENTATION_BOTLEFT;     /* It is the default */
293 
294 	img->tif = tif;
295 	img->stoponerr = stop;
296 	TIFFGetFieldDefaulted(tif, TIFFTAG_BITSPERSAMPLE, &img->bitspersample);
297 	switch (img->bitspersample) {
298 		case 1:
299 		case 2:
300 		case 4:
301 		case 8:
302 		case 16:
303 			break;
304 		default:
305 			sprintf(emsg, "Sorry, can not handle images with %d-bit samples",
306 			    img->bitspersample);
307 			goto fail_return;
308 	}
309 	img->alpha = 0;
310 	TIFFGetFieldDefaulted(tif, TIFFTAG_SAMPLESPERPIXEL, &img->samplesperpixel);
311 	TIFFGetFieldDefaulted(tif, TIFFTAG_EXTRASAMPLES,
312 	    &extrasamples, &sampleinfo);
313 	if (extrasamples >= 1)
314 	{
315 		switch (sampleinfo[0]) {
316 			case EXTRASAMPLE_UNSPECIFIED:          /* Workaround for some images without */
317 				if (img->samplesperpixel > 3)  /* correct info about alpha channel */
318 					img->alpha = EXTRASAMPLE_ASSOCALPHA;
319 				break;
320 			case EXTRASAMPLE_ASSOCALPHA:           /* data is pre-multiplied */
321 			case EXTRASAMPLE_UNASSALPHA:           /* data is not pre-multiplied */
322 				img->alpha = sampleinfo[0];
323 				break;
324 		}
325 	}
326 
327 #ifdef DEFAULT_EXTRASAMPLE_AS_ALPHA
328 	if( !TIFFGetField(tif, TIFFTAG_PHOTOMETRIC, &img->photometric))
329 		img->photometric = PHOTOMETRIC_MINISWHITE;
330 
331 	if( extrasamples == 0
332 	    && img->samplesperpixel == 4
333 	    && img->photometric == PHOTOMETRIC_RGB )
334 	{
335 		img->alpha = EXTRASAMPLE_ASSOCALPHA;
336 		extrasamples = 1;
337 	}
338 #endif
339 
340 	colorchannels = img->samplesperpixel - extrasamples;
341 	TIFFGetFieldDefaulted(tif, TIFFTAG_COMPRESSION, &compress);
342 	TIFFGetFieldDefaulted(tif, TIFFTAG_PLANARCONFIG, &planarconfig);
343 	if (!TIFFGetField(tif, TIFFTAG_PHOTOMETRIC, &img->photometric)) {
344 		switch (colorchannels) {
345 			case 1:
346 				if (isCCITTCompression(tif))
347 					img->photometric = PHOTOMETRIC_MINISWHITE;
348 				else
349 					img->photometric = PHOTOMETRIC_MINISBLACK;
350 				break;
351 			case 3:
352 				img->photometric = PHOTOMETRIC_RGB;
353 				break;
354 			default:
355 				sprintf(emsg, "Missing needed %s tag", photoTag);
356                                 goto fail_return;
357 		}
358 	}
359 	switch (img->photometric) {
360 		case PHOTOMETRIC_PALETTE:
361 			if (!TIFFGetField(tif, TIFFTAG_COLORMAP,
362 			    &red_orig, &green_orig, &blue_orig)) {
363 				sprintf(emsg, "Missing required \"Colormap\" tag");
364                                 goto fail_return;
365 			}
366 
367 			/* copy the colormaps so we can modify them */
368 			n_color = (1U << img->bitspersample);
369 			img->redcmap = (uint16 *) _TIFFmalloc(sizeof(uint16)*n_color);
370 			img->greencmap = (uint16 *) _TIFFmalloc(sizeof(uint16)*n_color);
371 			img->bluecmap = (uint16 *) _TIFFmalloc(sizeof(uint16)*n_color);
372 			if( !img->redcmap || !img->greencmap || !img->bluecmap ) {
373 				sprintf(emsg, "Out of memory for colormap copy");
374                                 goto fail_return;
375 			}
376 
377 			_TIFFmemcpy( img->redcmap, red_orig, n_color * 2 );
378 			_TIFFmemcpy( img->greencmap, green_orig, n_color * 2 );
379 			_TIFFmemcpy( img->bluecmap, blue_orig, n_color * 2 );
380 
381 			/* fall through... */
382 		case PHOTOMETRIC_MINISWHITE:
383 		case PHOTOMETRIC_MINISBLACK:
384 			if (planarconfig == PLANARCONFIG_CONTIG
385 			    && img->samplesperpixel != 1
386 			    && img->bitspersample < 8 ) {
387 				sprintf(emsg,
388 				    "Sorry, can not handle contiguous data with %s=%d, "
389 				    "and %s=%d and Bits/Sample=%d",
390 				    photoTag, img->photometric,
391 				    "Samples/pixel", img->samplesperpixel,
392 				    img->bitspersample);
393                                 goto fail_return;
394 			}
395 			break;
396 		case PHOTOMETRIC_YCBCR:
397 			/* It would probably be nice to have a reality check here. */
398 			if (planarconfig == PLANARCONFIG_CONTIG)
399 				/* can rely on libjpeg to convert to RGB */
400 				/* XXX should restore current state on exit */
401 				switch (compress) {
402 					case COMPRESSION_JPEG:
403 						/*
404 						 * TODO: when complete tests verify complete desubsampling
405 						 * and YCbCr handling, remove use of TIFFTAG_JPEGCOLORMODE in
406 						 * favor of tif_getimage.c native handling
407 						 */
408 						TIFFSetField(tif, TIFFTAG_JPEGCOLORMODE, JPEGCOLORMODE_RGB);
409 						img->photometric = PHOTOMETRIC_RGB;
410 						break;
411 					default:
412 						/* do nothing */;
413 						break;
414 				}
415 			/*
416 			 * TODO: if at all meaningful and useful, make more complete
417 			 * support check here, or better still, refactor to let supporting
418 			 * code decide whether there is support and what meaningful
419 			 * error to return
420 			 */
421 			break;
422 		case PHOTOMETRIC_RGB:
423 			if (colorchannels < 3) {
424 				sprintf(emsg, "Sorry, can not handle RGB image with %s=%d",
425 				    "Color channels", colorchannels);
426                                 goto fail_return;
427 			}
428 			break;
429 		case PHOTOMETRIC_SEPARATED:
430 			{
431 				uint16 inkset;
432 				TIFFGetFieldDefaulted(tif, TIFFTAG_INKSET, &inkset);
433 				if (inkset != INKSET_CMYK) {
434 					sprintf(emsg, "Sorry, can not handle separated image with %s=%d",
435 					    "InkSet", inkset);
436                                         goto fail_return;
437 				}
438 				if (img->samplesperpixel < 4) {
439 					sprintf(emsg, "Sorry, can not handle separated image with %s=%d",
440 					    "Samples/pixel", img->samplesperpixel);
441                                         goto fail_return;
442 				}
443 			}
444 			break;
445 		case PHOTOMETRIC_LOGL:
446 			if (compress != COMPRESSION_SGILOG) {
447 				sprintf(emsg, "Sorry, LogL data must have %s=%d",
448 				    "Compression", COMPRESSION_SGILOG);
449                                 goto fail_return;
450 			}
451 			TIFFSetField(tif, TIFFTAG_SGILOGDATAFMT, SGILOGDATAFMT_8BIT);
452 			img->photometric = PHOTOMETRIC_MINISBLACK;	/* little white lie */
453 			img->bitspersample = 8;
454 			break;
455 		case PHOTOMETRIC_LOGLUV:
456 			if (compress != COMPRESSION_SGILOG && compress != COMPRESSION_SGILOG24) {
457 				sprintf(emsg, "Sorry, LogLuv data must have %s=%d or %d",
458 				    "Compression", COMPRESSION_SGILOG, COMPRESSION_SGILOG24);
459                                 goto fail_return;
460 			}
461 			if (planarconfig != PLANARCONFIG_CONTIG) {
462 				sprintf(emsg, "Sorry, can not handle LogLuv images with %s=%d",
463 				    "Planarconfiguration", planarconfig);
464 				return (0);
465 			}
466 			TIFFSetField(tif, TIFFTAG_SGILOGDATAFMT, SGILOGDATAFMT_8BIT);
467 			img->photometric = PHOTOMETRIC_RGB;		/* little white lie */
468 			img->bitspersample = 8;
469 			break;
470 		case PHOTOMETRIC_CIELAB:
471 			break;
472 		default:
473 			sprintf(emsg, "Sorry, can not handle image with %s=%d",
474 			    photoTag, img->photometric);
475                         goto fail_return;
476 	}
477 	TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &img->width);
478 	TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &img->height);
479 	TIFFGetFieldDefaulted(tif, TIFFTAG_ORIENTATION, &img->orientation);
480 	img->isContig =
481 	    !(planarconfig == PLANARCONFIG_SEPARATE && img->samplesperpixel > 1);
482 	if (img->isContig) {
483 		if (!PickContigCase(img)) {
484 			sprintf(emsg, "Sorry, can not handle image");
485 			goto fail_return;
486 		}
487 	} else {
488 		if (!PickSeparateCase(img)) {
489 			sprintf(emsg, "Sorry, can not handle image");
490 			goto fail_return;
491 		}
492 	}
493 	return 1;
494 
495   fail_return:
496         TIFFRGBAImageEnd( img );
497         return 0;
498 }
499 
500 int
TIFFRGBAImageGet(TIFFRGBAImage * img,uint32 * raster,uint32 w,uint32 h)501 TIFFRGBAImageGet(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h)
502 {
503     if (img->get == NULL) {
504 		TIFFErrorExt(img->tif->tif_clientdata, TIFFFileName(img->tif), "No \"get\" routine setup");
505 		return (0);
506 	}
507 	if (img->put.any == NULL) {
508 		TIFFErrorExt(img->tif->tif_clientdata, TIFFFileName(img->tif),
509 		"No \"put\" routine setupl; probably can not handle image format");
510 		return (0);
511     }
512     return (*img->get)(img, raster, w, h);
513 }
514 
515 /*
516  * Read the specified image into an ABGR-format rastertaking in account
517  * specified orientation.
518  */
519 int
TIFFReadRGBAImageOriented(TIFF * tif,uint32 rwidth,uint32 rheight,uint32 * raster,int orientation,int stop)520 TIFFReadRGBAImageOriented(TIFF* tif,
521 			  uint32 rwidth, uint32 rheight, uint32* raster,
522 			  int orientation, int stop)
523 {
524     char emsg[1024] = "";
525     TIFFRGBAImage img;
526     int ok;
527 
528 	if (TIFFRGBAImageOK(tif, emsg) && TIFFRGBAImageBegin(&img, tif, stop, emsg)) {
529 		img.req_orientation = (uint16)orientation;
530 		/* XXX verify rwidth and rheight against width and height */
531 		ok = TIFFRGBAImageGet(&img, raster+(rheight-img.height)*rwidth,
532 			rwidth, img.height);
533 		TIFFRGBAImageEnd(&img);
534 	} else {
535 		TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "%s", emsg);
536 		ok = 0;
537     }
538     return (ok);
539 }
540 
541 /*
542  * Read the specified image into an ABGR-format raster. Use bottom left
543  * origin for raster by default.
544  */
545 int
TIFFReadRGBAImage(TIFF * tif,uint32 rwidth,uint32 rheight,uint32 * raster,int stop)546 TIFFReadRGBAImage(TIFF* tif,
547 		  uint32 rwidth, uint32 rheight, uint32* raster, int stop)
548 {
549 	return TIFFReadRGBAImageOriented(tif, rwidth, rheight, raster,
550 					 ORIENTATION_BOTLEFT, stop);
551 }
552 
553 static int
setorientation(TIFFRGBAImage * img)554 setorientation(TIFFRGBAImage* img)
555 {
556 	switch (img->orientation) {
557 		case ORIENTATION_TOPLEFT:
558 		case ORIENTATION_LEFTTOP:
559 			if (img->req_orientation == ORIENTATION_TOPRIGHT ||
560 			    img->req_orientation == ORIENTATION_RIGHTTOP)
561 				return FLIP_HORIZONTALLY;
562 			else if (img->req_orientation == ORIENTATION_BOTRIGHT ||
563 			    img->req_orientation == ORIENTATION_RIGHTBOT)
564 				return FLIP_HORIZONTALLY | FLIP_VERTICALLY;
565 			else if (img->req_orientation == ORIENTATION_BOTLEFT ||
566 			    img->req_orientation == ORIENTATION_LEFTBOT)
567 				return FLIP_VERTICALLY;
568 			else
569 				return 0;
570 		case ORIENTATION_TOPRIGHT:
571 		case ORIENTATION_RIGHTTOP:
572 			if (img->req_orientation == ORIENTATION_TOPLEFT ||
573 			    img->req_orientation == ORIENTATION_LEFTTOP)
574 				return FLIP_HORIZONTALLY;
575 			else if (img->req_orientation == ORIENTATION_BOTRIGHT ||
576 			    img->req_orientation == ORIENTATION_RIGHTBOT)
577 				return FLIP_VERTICALLY;
578 			else if (img->req_orientation == ORIENTATION_BOTLEFT ||
579 			    img->req_orientation == ORIENTATION_LEFTBOT)
580 				return FLIP_HORIZONTALLY | FLIP_VERTICALLY;
581 			else
582 				return 0;
583 		case ORIENTATION_BOTRIGHT:
584 		case ORIENTATION_RIGHTBOT:
585 			if (img->req_orientation == ORIENTATION_TOPLEFT ||
586 			    img->req_orientation == ORIENTATION_LEFTTOP)
587 				return FLIP_HORIZONTALLY | FLIP_VERTICALLY;
588 			else if (img->req_orientation == ORIENTATION_TOPRIGHT ||
589 			    img->req_orientation == ORIENTATION_RIGHTTOP)
590 				return FLIP_VERTICALLY;
591 			else if (img->req_orientation == ORIENTATION_BOTLEFT ||
592 			    img->req_orientation == ORIENTATION_LEFTBOT)
593 				return FLIP_HORIZONTALLY;
594 			else
595 				return 0;
596 		case ORIENTATION_BOTLEFT:
597 		case ORIENTATION_LEFTBOT:
598 			if (img->req_orientation == ORIENTATION_TOPLEFT ||
599 			    img->req_orientation == ORIENTATION_LEFTTOP)
600 				return FLIP_VERTICALLY;
601 			else if (img->req_orientation == ORIENTATION_TOPRIGHT ||
602 			    img->req_orientation == ORIENTATION_RIGHTTOP)
603 				return FLIP_HORIZONTALLY | FLIP_VERTICALLY;
604 			else if (img->req_orientation == ORIENTATION_BOTRIGHT ||
605 			    img->req_orientation == ORIENTATION_RIGHTBOT)
606 				return FLIP_HORIZONTALLY;
607 			else
608 				return 0;
609 		default:	/* NOTREACHED */
610 			return 0;
611 	}
612 }
613 
614 /*
615  * Get an tile-organized image that has
616  *	PlanarConfiguration contiguous if SamplesPerPixel > 1
617  * or
618  *	SamplesPerPixel == 1
619  */
620 static int
gtTileContig(TIFFRGBAImage * img,uint32 * raster,uint32 w,uint32 h)621 gtTileContig(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h)
622 {
623     TIFF* tif = img->tif;
624     tileContigRoutine put = img->put.contig;
625     uint32 col, row, y, rowstoread;
626     tmsize_t pos;
627     uint32 tw, th;
628     unsigned char* buf = NULL;
629     int32 fromskew, toskew;
630     int64 safeskew;
631     uint32 nrow;
632     int ret = 1, flip;
633     uint32 this_tw, tocol;
634     int32 this_toskew, leftmost_toskew;
635     int32 leftmost_fromskew;
636     uint32 leftmost_tw;
637     tmsize_t bufsize;
638 
639     bufsize = TIFFTileSize(tif);
640     if (bufsize == 0) {
641         TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "%s", "No space for tile buffer");
642         return (0);
643     }
644 
645     TIFFGetField(tif, TIFFTAG_TILEWIDTH, &tw);
646     TIFFGetField(tif, TIFFTAG_TILELENGTH, &th);
647 
648     flip = setorientation(img);
649     if (flip & FLIP_VERTICALLY) {
650 	    y = h - 1;
651 	    safeskew = 0;
652 	    safeskew -= tw;
653 	    safeskew -= w;
654     }
655     else {
656 	    y = 0;
657 	    safeskew = 0;
658 	    safeskew -= tw;
659 	    safeskew +=w;
660     }
661 
662     if(safeskew > INT_MAX || safeskew < INT_MIN){
663        _TIFFfree(buf);
664        TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "%s", "Invalid skew");
665        return (0);
666     }
667     toskew = safeskew;
668 
669     /*
670      *	Leftmost tile is clipped on left side if col_offset > 0.
671      */
672     leftmost_fromskew = img->col_offset % tw;
673     leftmost_tw = tw - leftmost_fromskew;
674     safeskew = toskew;
675     safeskew += leftmost_fromskew;
676     if(safeskew > INT_MAX || safeskew < INT_MIN){
677        _TIFFfree(buf);
678        TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "%s", "Invalid skew");
679        return (0);
680     }
681     leftmost_toskew = safeskew;
682     for (row = 0; ret != 0 && row < h; row += nrow)
683     {
684         rowstoread = th - (row + img->row_offset) % th;
685     	nrow = (row + rowstoread > h ? h - row : rowstoread);
686 	fromskew = leftmost_fromskew;
687 	this_tw = leftmost_tw;
688 	this_toskew = leftmost_toskew;
689 	tocol = 0;
690 	col = img->col_offset;
691 	while (tocol < w)
692         {
693 	    if (_TIFFReadTileAndAllocBuffer(tif, (void**) &buf, bufsize, col,
694 			     row+img->row_offset, 0, 0)==(tmsize_t)(-1) &&
695                 (buf == NULL || img->stoponerr))
696             {
697                 ret = 0;
698                 break;
699             }
700             pos = ((row+img->row_offset) % th) * TIFFTileRowSize(tif) + \
701 		   ((tmsize_t) fromskew * img->samplesperpixel);
702 	    if (tocol + this_tw > w)
703 	    {
704 		/*
705 		 * Rightmost tile is clipped on right side.
706 		 */
707 		safeskew = tw;
708 		safeskew -= w;
709 		safeskew += tocol;
710 		if(safeskew > INT_MAX || safeskew < INT_MIN){
711 		        _TIFFfree(buf);
712 		        TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "%s", "Invalid skew");
713 		        return (0);
714 		}
715 		fromskew = safeskew;
716 		this_tw = tw - fromskew;
717 		safeskew = toskew;
718 		safeskew += fromskew;
719 		if(safeskew > INT_MAX || safeskew < INT_MIN){
720 		        _TIFFfree(buf);
721 		        TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "%s", "Invalid skew");
722 		        return (0);
723 		}
724 		this_toskew = safeskew;
725 	    }
726 	    (*put)(img, raster+y*w+tocol, tocol, y, this_tw, nrow, fromskew, this_toskew, buf + pos);
727 	    tocol += this_tw;
728 	    col += this_tw;
729 	    /*
730 	     * After the leftmost tile, tiles are no longer clipped on left side.
731 	     */
732 	    fromskew = 0;
733 	    this_tw = tw;
734 	    this_toskew = toskew;
735 	}
736 
737         y += ((flip & FLIP_VERTICALLY) ? -(int32) nrow : (int32) nrow);
738     }
739     _TIFFfree(buf);
740 
741     if (flip & FLIP_HORIZONTALLY) {
742 	    uint32 line;
743 
744 	    for (line = 0; line < h; line++) {
745 		    uint32 *left = raster + (line * w);
746 		    uint32 *right = left + w - 1;
747 
748 		    while ( left < right ) {
749 			    uint32 temp = *left;
750 			    *left = *right;
751 			    *right = temp;
752 			    left++;
753 				right--;
754 		    }
755 	    }
756     }
757 
758     return (ret);
759 }
760 
761 /*
762  * Get an tile-organized image that has
763  *	 SamplesPerPixel > 1
764  *	 PlanarConfiguration separated
765  * We assume that all such images are RGB.
766  */
767 static int
gtTileSeparate(TIFFRGBAImage * img,uint32 * raster,uint32 w,uint32 h)768 gtTileSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h)
769 {
770 	TIFF* tif = img->tif;
771 	tileSeparateRoutine put = img->put.separate;
772 	uint32 col, row, y, rowstoread;
773 	tmsize_t pos;
774 	uint32 tw, th;
775 	unsigned char* buf = NULL;
776 	unsigned char* p0 = NULL;
777 	unsigned char* p1 = NULL;
778 	unsigned char* p2 = NULL;
779 	unsigned char* pa = NULL;
780 	tmsize_t tilesize;
781 	tmsize_t bufsize;
782 	int32 fromskew, toskew;
783 	int alpha = img->alpha;
784 	uint32 nrow;
785 	int ret = 1, flip;
786         uint16 colorchannels;
787 	uint32 this_tw, tocol;
788 	int32 this_toskew, leftmost_toskew;
789 	int32 leftmost_fromskew;
790 	uint32 leftmost_tw;
791 
792 	tilesize = TIFFTileSize(tif);
793 	bufsize = _TIFFMultiplySSize(tif, alpha?4:3,tilesize, "gtTileSeparate");
794 	if (bufsize == 0) {
795 		return (0);
796 	}
797 
798 	TIFFGetField(tif, TIFFTAG_TILEWIDTH, &tw);
799 	TIFFGetField(tif, TIFFTAG_TILELENGTH, &th);
800 
801 	flip = setorientation(img);
802 	if (flip & FLIP_VERTICALLY) {
803 		y = h - 1;
804 		toskew = -(int32)(tw + w);
805 	}
806 	else {
807 		y = 0;
808 		toskew = -(int32)(tw - w);
809 	}
810 
811         switch( img->photometric )
812         {
813           case PHOTOMETRIC_MINISWHITE:
814           case PHOTOMETRIC_MINISBLACK:
815           case PHOTOMETRIC_PALETTE:
816             colorchannels = 1;
817             break;
818 
819           default:
820             colorchannels = 3;
821             break;
822         }
823 
824 	/*
825 	 *	Leftmost tile is clipped on left side if col_offset > 0.
826 	 */
827 	leftmost_fromskew = img->col_offset % tw;
828 	leftmost_tw = tw - leftmost_fromskew;
829 	leftmost_toskew = toskew + leftmost_fromskew;
830 	for (row = 0; ret != 0 && row < h; row += nrow)
831 	{
832 		rowstoread = th - (row + img->row_offset) % th;
833 		nrow = (row + rowstoread > h ? h - row : rowstoread);
834 		fromskew = leftmost_fromskew;
835 		this_tw = leftmost_tw;
836 		this_toskew = leftmost_toskew;
837 		tocol = 0;
838 		col = img->col_offset;
839 		while (tocol < w)
840 		{
841                         if( buf == NULL )
842                         {
843                             if (_TIFFReadTileAndAllocBuffer(
844                                     tif, (void**) &buf, bufsize, col,
845                                     row+img->row_offset,0,0)==(tmsize_t)(-1)
846                                 && (buf == NULL || img->stoponerr))
847                             {
848                                     ret = 0;
849                                     break;
850                             }
851                             p0 = buf;
852                             if( colorchannels == 1 )
853                             {
854                                 p2 = p1 = p0;
855                                 pa = (alpha?(p0+3*tilesize):NULL);
856                             }
857                             else
858                             {
859                                 p1 = p0 + tilesize;
860                                 p2 = p1 + tilesize;
861                                 pa = (alpha?(p2+tilesize):NULL);
862                             }
863                         }
864 			else if (TIFFReadTile(tif, p0, col,
865 			    row+img->row_offset,0,0)==(tmsize_t)(-1) && img->stoponerr)
866 			{
867 				ret = 0;
868 				break;
869 			}
870 			if (colorchannels > 1
871                             && TIFFReadTile(tif, p1, col,
872                                             row+img->row_offset,0,1) == (tmsize_t)(-1)
873                             && img->stoponerr)
874 			{
875 				ret = 0;
876 				break;
877 			}
878 			if (colorchannels > 1
879                             && TIFFReadTile(tif, p2, col,
880                                             row+img->row_offset,0,2) == (tmsize_t)(-1)
881                             && img->stoponerr)
882 			{
883 				ret = 0;
884 				break;
885 			}
886 			if (alpha
887                             && TIFFReadTile(tif,pa,col,
888                                             row+img->row_offset,0,colorchannels) == (tmsize_t)(-1)
889                             && img->stoponerr)
890                         {
891                             ret = 0;
892                             break;
893 			}
894 
895 			pos = ((row+img->row_offset) % th) * TIFFTileRowSize(tif) + \
896 			   ((tmsize_t) fromskew * img->samplesperpixel);
897 			if (tocol + this_tw > w)
898 			{
899 				/*
900 				 * Rightmost tile is clipped on right side.
901 				 */
902 				fromskew = tw - (w - tocol);
903 				this_tw = tw - fromskew;
904 				this_toskew = toskew + fromskew;
905 			}
906 			(*put)(img, raster+y*w+tocol, tocol, y, this_tw, nrow, fromskew, this_toskew, \
907 				p0 + pos, p1 + pos, p2 + pos, (alpha?(pa+pos):NULL));
908 			tocol += this_tw;
909 			col += this_tw;
910 			/*
911 			* After the leftmost tile, tiles are no longer clipped on left side.
912 			*/
913 			fromskew = 0;
914 			this_tw = tw;
915 			this_toskew = toskew;
916 		}
917 
918 		y += ((flip & FLIP_VERTICALLY) ?-(int32) nrow : (int32) nrow);
919 	}
920 
921 	if (flip & FLIP_HORIZONTALLY) {
922 		uint32 line;
923 
924 		for (line = 0; line < h; line++) {
925 			uint32 *left = raster + (line * w);
926 			uint32 *right = left + w - 1;
927 
928 			while ( left < right ) {
929 				uint32 temp = *left;
930 				*left = *right;
931 				*right = temp;
932 				left++;
933 				right--;
934 			}
935 		}
936 	}
937 
938 	_TIFFfree(buf);
939 	return (ret);
940 }
941 
942 /*
943  * Get a strip-organized image that has
944  *	PlanarConfiguration contiguous if SamplesPerPixel > 1
945  * or
946  *	SamplesPerPixel == 1
947  */
948 static int
gtStripContig(TIFFRGBAImage * img,uint32 * raster,uint32 w,uint32 h)949 gtStripContig(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h)
950 {
951 	TIFF* tif = img->tif;
952 	tileContigRoutine put = img->put.contig;
953 	uint32 row, y, nrow, nrowsub, rowstoread;
954 	tmsize_t pos;
955 	unsigned char* buf = NULL;
956 	uint32 rowsperstrip;
957 	uint16 subsamplinghor,subsamplingver;
958 	uint32 imagewidth = img->width;
959 	tmsize_t scanline;
960 	int32 fromskew, toskew;
961 	int ret = 1, flip;
962         tmsize_t maxstripsize;
963 
964 	if ((tmsize_t)img->row_offset > TIFF_SSIZE_T_MAX || (size_t)h > (size_t)TIFF_SSIZE_T_MAX)
965 		return (0);
966 
967 	TIFFGetFieldDefaulted(tif, TIFFTAG_YCBCRSUBSAMPLING, &subsamplinghor, &subsamplingver);
968 	if( subsamplingver == 0 ) {
969 		TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "Invalid vertical YCbCr subsampling");
970 		return (0);
971 	}
972 
973 	maxstripsize = TIFFStripSize(tif);
974 
975 	flip = setorientation(img);
976 	if (flip & FLIP_VERTICALLY) {
977 		y = h - 1;
978 		toskew = -(int32)(w + w);
979 	} else {
980 		y = 0;
981 		toskew = -(int32)(w - w);
982 	}
983 
984 	TIFFGetFieldDefaulted(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip);
985 
986 	scanline = TIFFScanlineSize(tif);
987 	fromskew = (w < imagewidth ? imagewidth - w : 0);
988 	for (row = 0; row < h; row += nrow)
989 	{
990 		uint32 temp;
991 		rowstoread = rowsperstrip - (row + img->row_offset) % rowsperstrip;
992 		nrow = (row + rowstoread > h ? h - row : rowstoread);
993 		nrowsub = nrow;
994 		if ((nrowsub%subsamplingver)!=0)
995 			nrowsub+=subsamplingver-nrowsub%subsamplingver;
996 		temp = (row + img->row_offset)%rowsperstrip + nrowsub;
997 		if( scanline > 0 && temp > (size_t)(TIFF_TMSIZE_T_MAX / scanline) )
998 		{
999 			TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "Integer overflow in gtStripContig");
1000 			return 0;
1001 		}
1002 		if (_TIFFReadEncodedStripAndAllocBuffer(tif,
1003 		    TIFFComputeStrip(tif,row+img->row_offset, 0),
1004 		    (void**)(&buf),
1005                     maxstripsize,
1006 		    temp * scanline)==(tmsize_t)(-1)
1007 		    && (buf == NULL || img->stoponerr))
1008 		{
1009 			ret = 0;
1010 			break;
1011 		}
1012 
1013 		pos = ((row + img->row_offset) % rowsperstrip) * scanline + \
1014 			((tmsize_t) img->col_offset * img->samplesperpixel);
1015 		(*put)(img, raster+y*w, 0, y, w, nrow, fromskew, toskew, buf + pos);
1016 		y += ((flip & FLIP_VERTICALLY) ? -(int32) nrow : (int32) nrow);
1017 	}
1018 
1019 	if (flip & FLIP_HORIZONTALLY) {
1020 		uint32 line;
1021 
1022 		for (line = 0; line < h; line++) {
1023 			uint32 *left = raster + (line * w);
1024 			uint32 *right = left + w - 1;
1025 
1026 			while ( left < right ) {
1027 				uint32 temp = *left;
1028 				*left = *right;
1029 				*right = temp;
1030 				left++;
1031 				right--;
1032 			}
1033 		}
1034 	}
1035 
1036 	_TIFFfree(buf);
1037 	return (ret);
1038 }
1039 
1040 /*
1041  * Get a strip-organized image with
1042  *	 SamplesPerPixel > 1
1043  *	 PlanarConfiguration separated
1044  * We assume that all such images are RGB.
1045  */
1046 static int
gtStripSeparate(TIFFRGBAImage * img,uint32 * raster,uint32 w,uint32 h)1047 gtStripSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h)
1048 {
1049 	TIFF* tif = img->tif;
1050 	tileSeparateRoutine put = img->put.separate;
1051 	unsigned char *buf = NULL;
1052 	unsigned char *p0 = NULL, *p1 = NULL, *p2 = NULL, *pa = NULL;
1053 	uint32 row, y, nrow, rowstoread;
1054 	tmsize_t pos;
1055 	tmsize_t scanline;
1056 	uint32 rowsperstrip, offset_row;
1057 	uint32 imagewidth = img->width;
1058 	tmsize_t stripsize;
1059 	tmsize_t bufsize;
1060 	int32 fromskew, toskew;
1061 	int alpha = img->alpha;
1062 	int ret = 1, flip;
1063         uint16 colorchannels;
1064 
1065 	stripsize = TIFFStripSize(tif);
1066 	bufsize = _TIFFMultiplySSize(tif,alpha?4:3,stripsize, "gtStripSeparate");
1067 	if (bufsize == 0) {
1068 		return (0);
1069 	}
1070 
1071 	flip = setorientation(img);
1072 	if (flip & FLIP_VERTICALLY) {
1073 		y = h - 1;
1074 		toskew = -(int32)(w + w);
1075 	}
1076 	else {
1077 		y = 0;
1078 		toskew = -(int32)(w - w);
1079 	}
1080 
1081         switch( img->photometric )
1082         {
1083           case PHOTOMETRIC_MINISWHITE:
1084           case PHOTOMETRIC_MINISBLACK:
1085           case PHOTOMETRIC_PALETTE:
1086             colorchannels = 1;
1087             break;
1088 
1089           default:
1090             colorchannels = 3;
1091             break;
1092         }
1093 
1094 	TIFFGetFieldDefaulted(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip);
1095 	scanline = TIFFScanlineSize(tif);
1096 	fromskew = (w < imagewidth ? imagewidth - w : 0);
1097 	for (row = 0; row < h; row += nrow)
1098 	{
1099                 uint32 temp;
1100 		rowstoread = rowsperstrip - (row + img->row_offset) % rowsperstrip;
1101 		nrow = (row + rowstoread > h ? h - row : rowstoread);
1102 		offset_row = row + img->row_offset;
1103                 temp = (row + img->row_offset)%rowsperstrip + nrow;
1104                 if( scanline > 0 && temp > (size_t)(TIFF_TMSIZE_T_MAX / scanline) )
1105                 {
1106                         TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "Integer overflow in gtStripSeparate");
1107                         return 0;
1108                 }
1109                 if( buf == NULL )
1110                 {
1111                     if (_TIFFReadEncodedStripAndAllocBuffer(
1112                             tif, TIFFComputeStrip(tif, offset_row, 0),
1113                             (void**) &buf, bufsize,
1114                             temp * scanline)==(tmsize_t)(-1)
1115                         && (buf == NULL || img->stoponerr))
1116                     {
1117                             ret = 0;
1118                             break;
1119                     }
1120                     p0 = buf;
1121                     if( colorchannels == 1 )
1122                     {
1123                         p2 = p1 = p0;
1124                         pa = (alpha?(p0+3*stripsize):NULL);
1125                     }
1126                     else
1127                     {
1128                         p1 = p0 + stripsize;
1129                         p2 = p1 + stripsize;
1130                         pa = (alpha?(p2+stripsize):NULL);
1131                     }
1132                 }
1133 		else if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, offset_row, 0),
1134 		    p0, temp * scanline)==(tmsize_t)(-1)
1135 		    && img->stoponerr)
1136 		{
1137 			ret = 0;
1138 			break;
1139 		}
1140 		if (colorchannels > 1
1141                     && TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, offset_row, 1),
1142                                             p1, temp * scanline) == (tmsize_t)(-1)
1143 		    && img->stoponerr)
1144 		{
1145 			ret = 0;
1146 			break;
1147 		}
1148 		if (colorchannels > 1
1149                     && TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, offset_row, 2),
1150                                             p2, temp * scanline) == (tmsize_t)(-1)
1151 		    && img->stoponerr)
1152 		{
1153 			ret = 0;
1154 			break;
1155 		}
1156 		if (alpha)
1157 		{
1158 			if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, offset_row, colorchannels),
1159 			    pa, temp * scanline)==(tmsize_t)(-1)
1160 			    && img->stoponerr)
1161 			{
1162 				ret = 0;
1163 				break;
1164 			}
1165 		}
1166 
1167 		pos = ((row + img->row_offset) % rowsperstrip) * scanline + \
1168 			((tmsize_t) img->col_offset * img->samplesperpixel);
1169 		(*put)(img, raster+y*w, 0, y, w, nrow, fromskew, toskew, p0 + pos, p1 + pos,
1170 		    p2 + pos, (alpha?(pa+pos):NULL));
1171 		y += ((flip & FLIP_VERTICALLY) ? -(int32) nrow : (int32) nrow);
1172 	}
1173 
1174 	if (flip & FLIP_HORIZONTALLY) {
1175 		uint32 line;
1176 
1177 		for (line = 0; line < h; line++) {
1178 			uint32 *left = raster + (line * w);
1179 			uint32 *right = left + w - 1;
1180 
1181 			while ( left < right ) {
1182 				uint32 temp = *left;
1183 				*left = *right;
1184 				*right = temp;
1185 				left++;
1186 				right--;
1187 			}
1188 		}
1189 	}
1190 
1191 	_TIFFfree(buf);
1192 	return (ret);
1193 }
1194 
1195 /*
1196  * The following routines move decoded data returned
1197  * from the TIFF library into rasters filled with packed
1198  * ABGR pixels (i.e. suitable for passing to lrecwrite.)
1199  *
1200  * The routines have been created according to the most
1201  * important cases and optimized.  PickContigCase and
1202  * PickSeparateCase analyze the parameters and select
1203  * the appropriate "get" and "put" routine to use.
1204  */
1205 #define	REPEAT8(op)	REPEAT4(op); REPEAT4(op)
1206 #define	REPEAT4(op)	REPEAT2(op); REPEAT2(op)
1207 #define	REPEAT2(op)	op; op
1208 #define	CASE8(x,op)			\
1209     switch (x) {			\
1210     case 7: op; /*-fallthrough*/ \
1211     case 6: op; /*-fallthrough*/ \
1212     case 5: op; /*-fallthrough*/ \
1213     case 4: op; /*-fallthrough*/ \
1214     case 3: op; /*-fallthrough*/ \
1215     case 2: op; /*-fallthrough*/ \
1216     case 1: op;				\
1217     }
1218 #define	CASE4(x,op)	switch (x) { case 3: op; /*-fallthrough*/ case 2: op; /*-fallthrough*/ case 1: op; }
1219 #define	NOP
1220 
1221 #define	UNROLL8(w, op1, op2) {		\
1222     uint32 _x;				\
1223     for (_x = w; _x >= 8; _x -= 8) {	\
1224 	op1;				\
1225 	REPEAT8(op2);			\
1226     }					\
1227     if (_x > 0) {			\
1228 	op1;				\
1229 	CASE8(_x,op2);			\
1230     }					\
1231 }
1232 #define	UNROLL4(w, op1, op2) {		\
1233     uint32 _x;				\
1234     for (_x = w; _x >= 4; _x -= 4) {	\
1235 	op1;				\
1236 	REPEAT4(op2);			\
1237     }					\
1238     if (_x > 0) {			\
1239 	op1;				\
1240 	CASE4(_x,op2);			\
1241     }					\
1242 }
1243 #define	UNROLL2(w, op1, op2) {		\
1244     uint32 _x;				\
1245     for (_x = w; _x >= 2; _x -= 2) {	\
1246 	op1;				\
1247 	REPEAT2(op2);			\
1248     }					\
1249     if (_x) {				\
1250 	op1;				\
1251 	op2;				\
1252     }					\
1253 }
1254 
1255 #define	SKEW(r,g,b,skew)	{ r += skew; g += skew; b += skew; }
1256 #define	SKEW4(r,g,b,a,skew)	{ r += skew; g += skew; b += skew; a+= skew; }
1257 
1258 #define A1 (((uint32)0xffL)<<24)
1259 #define	PACK(r,g,b)	\
1260 	((uint32)(r)|((uint32)(g)<<8)|((uint32)(b)<<16)|A1)
1261 #define	PACK4(r,g,b,a)	\
1262 	((uint32)(r)|((uint32)(g)<<8)|((uint32)(b)<<16)|((uint32)(a)<<24))
1263 #define W2B(v) (((v)>>8)&0xff)
1264 /* TODO: PACKW should have be made redundant in favor of Bitdepth16To8 LUT */
1265 #define	PACKW(r,g,b)	\
1266 	((uint32)W2B(r)|((uint32)W2B(g)<<8)|((uint32)W2B(b)<<16)|A1)
1267 #define	PACKW4(r,g,b,a)	\
1268 	((uint32)W2B(r)|((uint32)W2B(g)<<8)|((uint32)W2B(b)<<16)|((uint32)W2B(a)<<24))
1269 
1270 #define	DECLAREContigPutFunc(name) \
1271 static void name(\
1272     TIFFRGBAImage* img, \
1273     uint32* cp, \
1274     uint32 x, uint32 y, \
1275     uint32 w, uint32 h, \
1276     int32 fromskew, int32 toskew, \
1277     unsigned char* pp \
1278 )
1279 
1280 /*
1281  * 8-bit palette => colormap/RGB
1282  */
DECLAREContigPutFunc(put8bitcmaptile)1283 DECLAREContigPutFunc(put8bitcmaptile)
1284 {
1285     uint32** PALmap = img->PALmap;
1286     int samplesperpixel = img->samplesperpixel;
1287 
1288     (void) y;
1289     for( ; h > 0; --h) {
1290 	for (x = w; x > 0; --x)
1291         {
1292 	    *cp++ = PALmap[*pp][0];
1293             pp += samplesperpixel;
1294         }
1295 	cp += toskew;
1296 	pp += fromskew;
1297     }
1298 }
1299 
1300 /*
1301  * 4-bit palette => colormap/RGB
1302  */
DECLAREContigPutFunc(put4bitcmaptile)1303 DECLAREContigPutFunc(put4bitcmaptile)
1304 {
1305     uint32** PALmap = img->PALmap;
1306 
1307     (void) x; (void) y;
1308     fromskew /= 2;
1309     for( ; h > 0; --h) {
1310 	uint32* bw;
1311 	UNROLL2(w, bw = PALmap[*pp++], *cp++ = *bw++);
1312 	cp += toskew;
1313 	pp += fromskew;
1314     }
1315 }
1316 
1317 /*
1318  * 2-bit palette => colormap/RGB
1319  */
DECLAREContigPutFunc(put2bitcmaptile)1320 DECLAREContigPutFunc(put2bitcmaptile)
1321 {
1322     uint32** PALmap = img->PALmap;
1323 
1324     (void) x; (void) y;
1325     fromskew /= 4;
1326     for( ; h > 0; --h) {
1327 	uint32* bw;
1328 	UNROLL4(w, bw = PALmap[*pp++], *cp++ = *bw++);
1329 	cp += toskew;
1330 	pp += fromskew;
1331     }
1332 }
1333 
1334 /*
1335  * 1-bit palette => colormap/RGB
1336  */
DECLAREContigPutFunc(put1bitcmaptile)1337 DECLAREContigPutFunc(put1bitcmaptile)
1338 {
1339     uint32** PALmap = img->PALmap;
1340 
1341     (void) x; (void) y;
1342     fromskew /= 8;
1343     for( ; h > 0; --h) {
1344 	uint32* bw;
1345 	UNROLL8(w, bw = PALmap[*pp++], *cp++ = *bw++);
1346 	cp += toskew;
1347 	pp += fromskew;
1348     }
1349 }
1350 
1351 /*
1352  * 8-bit greyscale => colormap/RGB
1353  */
DECLAREContigPutFunc(putgreytile)1354 DECLAREContigPutFunc(putgreytile)
1355 {
1356     int samplesperpixel = img->samplesperpixel;
1357     uint32** BWmap = img->BWmap;
1358 
1359     (void) y;
1360     for( ; h > 0; --h) {
1361 	for (x = w; x > 0; --x)
1362         {
1363 	    *cp++ = BWmap[*pp][0];
1364             pp += samplesperpixel;
1365         }
1366 	cp += toskew;
1367 	pp += fromskew;
1368     }
1369 }
1370 
1371 /*
1372  * 8-bit greyscale with associated alpha => colormap/RGBA
1373  */
DECLAREContigPutFunc(putagreytile)1374 DECLAREContigPutFunc(putagreytile)
1375 {
1376     int samplesperpixel = img->samplesperpixel;
1377     uint32** BWmap = img->BWmap;
1378 
1379     (void) y;
1380     for( ; h > 0; --h) {
1381 	for (x = w; x > 0; --x)
1382         {
1383             *cp++ = BWmap[*pp][0] & ((uint32)*(pp+1) << 24 | ~A1);
1384             pp += samplesperpixel;
1385         }
1386 	cp += toskew;
1387 	pp += fromskew;
1388     }
1389 }
1390 
1391 /*
1392  * 16-bit greyscale => colormap/RGB
1393  */
DECLAREContigPutFunc(put16bitbwtile)1394 DECLAREContigPutFunc(put16bitbwtile)
1395 {
1396     int samplesperpixel = img->samplesperpixel;
1397     uint32** BWmap = img->BWmap;
1398 
1399     (void) y;
1400     for( ; h > 0; --h) {
1401         uint16 *wp = (uint16 *) pp;
1402 
1403 	for (x = w; x > 0; --x)
1404         {
1405             /* use high order byte of 16bit value */
1406 
1407 	    *cp++ = BWmap[*wp >> 8][0];
1408             pp += 2 * samplesperpixel;
1409             wp += samplesperpixel;
1410         }
1411 	cp += toskew;
1412 	pp += fromskew;
1413     }
1414 }
1415 
1416 /*
1417  * 1-bit bilevel => colormap/RGB
1418  */
DECLAREContigPutFunc(put1bitbwtile)1419 DECLAREContigPutFunc(put1bitbwtile)
1420 {
1421     uint32** BWmap = img->BWmap;
1422 
1423     (void) x; (void) y;
1424     fromskew /= 8;
1425     for( ; h > 0; --h) {
1426 	uint32* bw;
1427 	UNROLL8(w, bw = BWmap[*pp++], *cp++ = *bw++);
1428 	cp += toskew;
1429 	pp += fromskew;
1430     }
1431 }
1432 
1433 /*
1434  * 2-bit greyscale => colormap/RGB
1435  */
DECLAREContigPutFunc(put2bitbwtile)1436 DECLAREContigPutFunc(put2bitbwtile)
1437 {
1438     uint32** BWmap = img->BWmap;
1439 
1440     (void) x; (void) y;
1441     fromskew /= 4;
1442     for( ; h > 0; --h) {
1443 	uint32* bw;
1444 	UNROLL4(w, bw = BWmap[*pp++], *cp++ = *bw++);
1445 	cp += toskew;
1446 	pp += fromskew;
1447     }
1448 }
1449 
1450 /*
1451  * 4-bit greyscale => colormap/RGB
1452  */
DECLAREContigPutFunc(put4bitbwtile)1453 DECLAREContigPutFunc(put4bitbwtile)
1454 {
1455     uint32** BWmap = img->BWmap;
1456 
1457     (void) x; (void) y;
1458     fromskew /= 2;
1459     for( ; h > 0; --h) {
1460 	uint32* bw;
1461 	UNROLL2(w, bw = BWmap[*pp++], *cp++ = *bw++);
1462 	cp += toskew;
1463 	pp += fromskew;
1464     }
1465 }
1466 
1467 /*
1468  * 8-bit packed samples, no Map => RGB
1469  */
DECLAREContigPutFunc(putRGBcontig8bittile)1470 DECLAREContigPutFunc(putRGBcontig8bittile)
1471 {
1472     int samplesperpixel = img->samplesperpixel;
1473 
1474     (void) x; (void) y;
1475     fromskew *= samplesperpixel;
1476     for( ; h > 0; --h) {
1477 	UNROLL8(w, NOP,
1478 	    *cp++ = PACK(pp[0], pp[1], pp[2]);
1479 	    pp += samplesperpixel);
1480 	cp += toskew;
1481 	pp += fromskew;
1482     }
1483 }
1484 
1485 /*
1486  * 8-bit packed samples => RGBA w/ associated alpha
1487  * (known to have Map == NULL)
1488  */
DECLAREContigPutFunc(putRGBAAcontig8bittile)1489 DECLAREContigPutFunc(putRGBAAcontig8bittile)
1490 {
1491     int samplesperpixel = img->samplesperpixel;
1492 
1493     (void) x; (void) y;
1494     fromskew *= samplesperpixel;
1495     for( ; h > 0; --h) {
1496 	UNROLL8(w, NOP,
1497 	    *cp++ = PACK4(pp[0], pp[1], pp[2], pp[3]);
1498 	    pp += samplesperpixel);
1499 	cp += toskew;
1500 	pp += fromskew;
1501     }
1502 }
1503 
1504 /*
1505  * 8-bit packed samples => RGBA w/ unassociated alpha
1506  * (known to have Map == NULL)
1507  */
DECLAREContigPutFunc(putRGBUAcontig8bittile)1508 DECLAREContigPutFunc(putRGBUAcontig8bittile)
1509 {
1510 	int samplesperpixel = img->samplesperpixel;
1511 	(void) y;
1512 	fromskew *= samplesperpixel;
1513 	for( ; h > 0; --h) {
1514 		uint32 r, g, b, a;
1515 		uint8* m;
1516 		for (x = w; x > 0; --x) {
1517 			a = pp[3];
1518 			m = img->UaToAa+((size_t) a<<8);
1519 			r = m[pp[0]];
1520 			g = m[pp[1]];
1521 			b = m[pp[2]];
1522 			*cp++ = PACK4(r,g,b,a);
1523 			pp += samplesperpixel;
1524 		}
1525 		cp += toskew;
1526 		pp += fromskew;
1527 	}
1528 }
1529 
1530 /*
1531  * 16-bit packed samples => RGB
1532  */
DECLAREContigPutFunc(putRGBcontig16bittile)1533 DECLAREContigPutFunc(putRGBcontig16bittile)
1534 {
1535 	int samplesperpixel = img->samplesperpixel;
1536 	uint16 *wp = (uint16 *)pp;
1537 	(void) y;
1538 	fromskew *= samplesperpixel;
1539 	for( ; h > 0; --h) {
1540 		for (x = w; x > 0; --x) {
1541 			*cp++ = PACK(img->Bitdepth16To8[wp[0]],
1542 			    img->Bitdepth16To8[wp[1]],
1543 			    img->Bitdepth16To8[wp[2]]);
1544 			wp += samplesperpixel;
1545 		}
1546 		cp += toskew;
1547 		wp += fromskew;
1548 	}
1549 }
1550 
1551 /*
1552  * 16-bit packed samples => RGBA w/ associated alpha
1553  * (known to have Map == NULL)
1554  */
DECLAREContigPutFunc(putRGBAAcontig16bittile)1555 DECLAREContigPutFunc(putRGBAAcontig16bittile)
1556 {
1557 	int samplesperpixel = img->samplesperpixel;
1558 	uint16 *wp = (uint16 *)pp;
1559 	(void) y;
1560 	fromskew *= samplesperpixel;
1561 	for( ; h > 0; --h) {
1562 		for (x = w; x > 0; --x) {
1563 			*cp++ = PACK4(img->Bitdepth16To8[wp[0]],
1564 			    img->Bitdepth16To8[wp[1]],
1565 			    img->Bitdepth16To8[wp[2]],
1566 			    img->Bitdepth16To8[wp[3]]);
1567 			wp += samplesperpixel;
1568 		}
1569 		cp += toskew;
1570 		wp += fromskew;
1571 	}
1572 }
1573 
1574 /*
1575  * 16-bit packed samples => RGBA w/ unassociated alpha
1576  * (known to have Map == NULL)
1577  */
DECLAREContigPutFunc(putRGBUAcontig16bittile)1578 DECLAREContigPutFunc(putRGBUAcontig16bittile)
1579 {
1580 	int samplesperpixel = img->samplesperpixel;
1581 	uint16 *wp = (uint16 *)pp;
1582 	(void) y;
1583 	fromskew *= samplesperpixel;
1584 	for( ; h > 0; --h) {
1585 		uint32 r,g,b,a;
1586 		uint8* m;
1587 		for (x = w; x > 0; --x) {
1588 			a = img->Bitdepth16To8[wp[3]];
1589 			m = img->UaToAa+((size_t) a<<8);
1590 			r = m[img->Bitdepth16To8[wp[0]]];
1591 			g = m[img->Bitdepth16To8[wp[1]]];
1592 			b = m[img->Bitdepth16To8[wp[2]]];
1593 			*cp++ = PACK4(r,g,b,a);
1594 			wp += samplesperpixel;
1595 		}
1596 		cp += toskew;
1597 		wp += fromskew;
1598 	}
1599 }
1600 
1601 /*
1602  * 8-bit packed CMYK samples w/o Map => RGB
1603  *
1604  * NB: The conversion of CMYK->RGB is *very* crude.
1605  */
DECLAREContigPutFunc(putRGBcontig8bitCMYKtile)1606 DECLAREContigPutFunc(putRGBcontig8bitCMYKtile)
1607 {
1608     int samplesperpixel = img->samplesperpixel;
1609     uint16 r, g, b, k;
1610 
1611     (void) x; (void) y;
1612     fromskew *= samplesperpixel;
1613     for( ; h > 0; --h) {
1614 	UNROLL8(w, NOP,
1615 	    k = 255 - pp[3];
1616 	    r = (k*(255-pp[0]))/255;
1617 	    g = (k*(255-pp[1]))/255;
1618 	    b = (k*(255-pp[2]))/255;
1619 	    *cp++ = PACK(r, g, b);
1620 	    pp += samplesperpixel);
1621 	cp += toskew;
1622 	pp += fromskew;
1623     }
1624 }
1625 
1626 /*
1627  * 8-bit packed CMYK samples w/Map => RGB
1628  *
1629  * NB: The conversion of CMYK->RGB is *very* crude.
1630  */
DECLAREContigPutFunc(putRGBcontig8bitCMYKMaptile)1631 DECLAREContigPutFunc(putRGBcontig8bitCMYKMaptile)
1632 {
1633     int samplesperpixel = img->samplesperpixel;
1634     TIFFRGBValue* Map = img->Map;
1635     uint16 r, g, b, k;
1636 
1637     (void) y;
1638     fromskew *= samplesperpixel;
1639     for( ; h > 0; --h) {
1640 	for (x = w; x > 0; --x) {
1641 	    k = 255 - pp[3];
1642 	    r = (k*(255-pp[0]))/255;
1643 	    g = (k*(255-pp[1]))/255;
1644 	    b = (k*(255-pp[2]))/255;
1645 	    *cp++ = PACK(Map[r], Map[g], Map[b]);
1646 	    pp += samplesperpixel;
1647 	}
1648 	pp += fromskew;
1649 	cp += toskew;
1650     }
1651 }
1652 
1653 #define	DECLARESepPutFunc(name) \
1654 static void name(\
1655     TIFFRGBAImage* img,\
1656     uint32* cp,\
1657     uint32 x, uint32 y, \
1658     uint32 w, uint32 h,\
1659     int32 fromskew, int32 toskew,\
1660     unsigned char* r, unsigned char* g, unsigned char* b, unsigned char* a\
1661 )
1662 
1663 /*
1664  * 8-bit unpacked samples => RGB
1665  */
DECLARESepPutFunc(putRGBseparate8bittile)1666 DECLARESepPutFunc(putRGBseparate8bittile)
1667 {
1668     (void) img; (void) x; (void) y; (void) a;
1669     for( ; h > 0; --h) {
1670 	UNROLL8(w, NOP, *cp++ = PACK(*r++, *g++, *b++));
1671 	SKEW(r, g, b, fromskew);
1672 	cp += toskew;
1673     }
1674 }
1675 
1676 /*
1677  * 8-bit unpacked samples => RGBA w/ associated alpha
1678  */
DECLARESepPutFunc(putRGBAAseparate8bittile)1679 DECLARESepPutFunc(putRGBAAseparate8bittile)
1680 {
1681 	(void) img; (void) x; (void) y;
1682 	for( ; h > 0; --h) {
1683 		UNROLL8(w, NOP, *cp++ = PACK4(*r++, *g++, *b++, *a++));
1684 		SKEW4(r, g, b, a, fromskew);
1685 		cp += toskew;
1686 	}
1687 }
1688 
1689 /*
1690  * 8-bit unpacked CMYK samples => RGBA
1691  */
DECLARESepPutFunc(putCMYKseparate8bittile)1692 DECLARESepPutFunc(putCMYKseparate8bittile)
1693 {
1694 	(void) img; (void) y;
1695 	for( ; h > 0; --h) {
1696 		uint32 rv, gv, bv, kv;
1697 		for (x = w; x > 0; --x) {
1698 			kv = 255 - *a++;
1699 			rv = (kv*(255-*r++))/255;
1700 			gv = (kv*(255-*g++))/255;
1701 			bv = (kv*(255-*b++))/255;
1702 			*cp++ = PACK4(rv,gv,bv,255);
1703 		}
1704 		SKEW4(r, g, b, a, fromskew);
1705 		cp += toskew;
1706 	}
1707 }
1708 
1709 /*
1710  * 8-bit unpacked samples => RGBA w/ unassociated alpha
1711  */
DECLARESepPutFunc(putRGBUAseparate8bittile)1712 DECLARESepPutFunc(putRGBUAseparate8bittile)
1713 {
1714 	(void) img; (void) y;
1715 	for( ; h > 0; --h) {
1716 		uint32 rv, gv, bv, av;
1717 		uint8* m;
1718 		for (x = w; x > 0; --x) {
1719 			av = *a++;
1720 			m = img->UaToAa+((size_t) av<<8);
1721 			rv = m[*r++];
1722 			gv = m[*g++];
1723 			bv = m[*b++];
1724 			*cp++ = PACK4(rv,gv,bv,av);
1725 		}
1726 		SKEW4(r, g, b, a, fromskew);
1727 		cp += toskew;
1728 	}
1729 }
1730 
1731 /*
1732  * 16-bit unpacked samples => RGB
1733  */
DECLARESepPutFunc(putRGBseparate16bittile)1734 DECLARESepPutFunc(putRGBseparate16bittile)
1735 {
1736 	uint16 *wr = (uint16*) r;
1737 	uint16 *wg = (uint16*) g;
1738 	uint16 *wb = (uint16*) b;
1739 	(void) img; (void) y; (void) a;
1740 	for( ; h > 0; --h) {
1741 		for (x = 0; x < w; x++)
1742 			*cp++ = PACK(img->Bitdepth16To8[*wr++],
1743 			    img->Bitdepth16To8[*wg++],
1744 			    img->Bitdepth16To8[*wb++]);
1745 		SKEW(wr, wg, wb, fromskew);
1746 		cp += toskew;
1747 	}
1748 }
1749 
1750 /*
1751  * 16-bit unpacked samples => RGBA w/ associated alpha
1752  */
DECLARESepPutFunc(putRGBAAseparate16bittile)1753 DECLARESepPutFunc(putRGBAAseparate16bittile)
1754 {
1755 	uint16 *wr = (uint16*) r;
1756 	uint16 *wg = (uint16*) g;
1757 	uint16 *wb = (uint16*) b;
1758 	uint16 *wa = (uint16*) a;
1759 	(void) img; (void) y;
1760 	for( ; h > 0; --h) {
1761 		for (x = 0; x < w; x++)
1762 			*cp++ = PACK4(img->Bitdepth16To8[*wr++],
1763 			    img->Bitdepth16To8[*wg++],
1764 			    img->Bitdepth16To8[*wb++],
1765 			    img->Bitdepth16To8[*wa++]);
1766 		SKEW4(wr, wg, wb, wa, fromskew);
1767 		cp += toskew;
1768 	}
1769 }
1770 
1771 /*
1772  * 16-bit unpacked samples => RGBA w/ unassociated alpha
1773  */
DECLARESepPutFunc(putRGBUAseparate16bittile)1774 DECLARESepPutFunc(putRGBUAseparate16bittile)
1775 {
1776 	uint16 *wr = (uint16*) r;
1777 	uint16 *wg = (uint16*) g;
1778 	uint16 *wb = (uint16*) b;
1779 	uint16 *wa = (uint16*) a;
1780 	(void) img; (void) y;
1781 	for( ; h > 0; --h) {
1782 		uint32 r2,g2,b2,a2;
1783 		uint8* m;
1784 		for (x = w; x > 0; --x) {
1785 			a2 = img->Bitdepth16To8[*wa++];
1786 			m = img->UaToAa+((size_t) a2<<8);
1787 			r2 = m[img->Bitdepth16To8[*wr++]];
1788 			g2 = m[img->Bitdepth16To8[*wg++]];
1789 			b2 = m[img->Bitdepth16To8[*wb++]];
1790 			*cp++ = PACK4(r2,g2,b2,a2);
1791 		}
1792 		SKEW4(wr, wg, wb, wa, fromskew);
1793 		cp += toskew;
1794 	}
1795 }
1796 
1797 /*
1798  * 8-bit packed CIE L*a*b 1976 samples => RGB
1799  */
DECLAREContigPutFunc(putcontig8bitCIELab)1800 DECLAREContigPutFunc(putcontig8bitCIELab)
1801 {
1802 	float X, Y, Z;
1803 	uint32 r, g, b;
1804 	(void) y;
1805 	fromskew *= 3;
1806 	for( ; h > 0; --h) {
1807 		for (x = w; x > 0; --x) {
1808 			TIFFCIELabToXYZ(img->cielab,
1809 					(unsigned char)pp[0],
1810 					(signed char)pp[1],
1811 					(signed char)pp[2],
1812 					&X, &Y, &Z);
1813 			TIFFXYZToRGB(img->cielab, X, Y, Z, &r, &g, &b);
1814 			*cp++ = PACK(r, g, b);
1815 			pp += 3;
1816 		}
1817 		cp += toskew;
1818 		pp += fromskew;
1819 	}
1820 }
1821 
1822 /*
1823  * YCbCr -> RGB conversion and packing routines.
1824  */
1825 
1826 #define	YCbCrtoRGB(dst, Y) {						\
1827 	uint32 r, g, b;							\
1828 	TIFFYCbCrtoRGB(img->ycbcr, (Y), Cb, Cr, &r, &g, &b);		\
1829 	dst = PACK(r, g, b);						\
1830 }
1831 
1832 /*
1833  * 8-bit packed YCbCr samples => RGB
1834  * This function is generic for different sampling sizes,
1835  * and can handle blocks sizes that aren't multiples of the
1836  * sampling size.  However, it is substantially less optimized
1837  * than the specific sampling cases.  It is used as a fallback
1838  * for difficult blocks.
1839  */
1840 #ifdef notdef
putcontig8bitYCbCrGenericTile(TIFFRGBAImage * img,uint32 * cp,uint32 x,uint32 y,uint32 w,uint32 h,int32 fromskew,int32 toskew,unsigned char * pp,int h_group,int v_group)1841 static void putcontig8bitYCbCrGenericTile(
1842     TIFFRGBAImage* img,
1843     uint32* cp,
1844     uint32 x, uint32 y,
1845     uint32 w, uint32 h,
1846     int32 fromskew, int32 toskew,
1847     unsigned char* pp,
1848     int h_group,
1849     int v_group )
1850 
1851 {
1852     uint32* cp1 = cp+w+toskew;
1853     uint32* cp2 = cp1+w+toskew;
1854     uint32* cp3 = cp2+w+toskew;
1855     int32 incr = 3*w+4*toskew;
1856     int32   Cb, Cr;
1857     int     group_size = v_group * h_group + 2;
1858 
1859     (void) y;
1860     fromskew = (fromskew * group_size) / h_group;
1861 
1862     for( yy = 0; yy < h; yy++ )
1863     {
1864         unsigned char *pp_line;
1865         int     y_line_group = yy / v_group;
1866         int     y_remainder = yy - y_line_group * v_group;
1867 
1868         pp_line = pp + v_line_group *
1869 
1870 
1871         for( xx = 0; xx < w; xx++ )
1872         {
1873             Cb = pp
1874         }
1875     }
1876     for (; h >= 4; h -= 4) {
1877 	x = w>>2;
1878 	do {
1879 	    Cb = pp[16];
1880 	    Cr = pp[17];
1881 
1882 	    YCbCrtoRGB(cp [0], pp[ 0]);
1883 	    YCbCrtoRGB(cp [1], pp[ 1]);
1884 	    YCbCrtoRGB(cp [2], pp[ 2]);
1885 	    YCbCrtoRGB(cp [3], pp[ 3]);
1886 	    YCbCrtoRGB(cp1[0], pp[ 4]);
1887 	    YCbCrtoRGB(cp1[1], pp[ 5]);
1888 	    YCbCrtoRGB(cp1[2], pp[ 6]);
1889 	    YCbCrtoRGB(cp1[3], pp[ 7]);
1890 	    YCbCrtoRGB(cp2[0], pp[ 8]);
1891 	    YCbCrtoRGB(cp2[1], pp[ 9]);
1892 	    YCbCrtoRGB(cp2[2], pp[10]);
1893 	    YCbCrtoRGB(cp2[3], pp[11]);
1894 	    YCbCrtoRGB(cp3[0], pp[12]);
1895 	    YCbCrtoRGB(cp3[1], pp[13]);
1896 	    YCbCrtoRGB(cp3[2], pp[14]);
1897 	    YCbCrtoRGB(cp3[3], pp[15]);
1898 
1899 	    cp += 4, cp1 += 4, cp2 += 4, cp3 += 4;
1900 	    pp += 18;
1901 	} while (--x);
1902 	cp += incr, cp1 += incr, cp2 += incr, cp3 += incr;
1903 	pp += fromskew;
1904     }
1905 }
1906 #endif
1907 
1908 /*
1909  * 8-bit packed YCbCr samples w/ 4,4 subsampling => RGB
1910  */
DECLAREContigPutFunc(putcontig8bitYCbCr44tile)1911 DECLAREContigPutFunc(putcontig8bitYCbCr44tile)
1912 {
1913     uint32* cp1 = cp+w+toskew;
1914     uint32* cp2 = cp1+w+toskew;
1915     uint32* cp3 = cp2+w+toskew;
1916     int32 incr = 3*w+4*toskew;
1917 
1918     (void) y;
1919     /* adjust fromskew */
1920     fromskew = (fromskew / 4) * (4*2+2);
1921     if ((h & 3) == 0 && (w & 3) == 0) {
1922         for (; h >= 4; h -= 4) {
1923             x = w>>2;
1924             do {
1925                 int32 Cb = pp[16];
1926                 int32 Cr = pp[17];
1927 
1928                 YCbCrtoRGB(cp [0], pp[ 0]);
1929                 YCbCrtoRGB(cp [1], pp[ 1]);
1930                 YCbCrtoRGB(cp [2], pp[ 2]);
1931                 YCbCrtoRGB(cp [3], pp[ 3]);
1932                 YCbCrtoRGB(cp1[0], pp[ 4]);
1933                 YCbCrtoRGB(cp1[1], pp[ 5]);
1934                 YCbCrtoRGB(cp1[2], pp[ 6]);
1935                 YCbCrtoRGB(cp1[3], pp[ 7]);
1936                 YCbCrtoRGB(cp2[0], pp[ 8]);
1937                 YCbCrtoRGB(cp2[1], pp[ 9]);
1938                 YCbCrtoRGB(cp2[2], pp[10]);
1939                 YCbCrtoRGB(cp2[3], pp[11]);
1940                 YCbCrtoRGB(cp3[0], pp[12]);
1941                 YCbCrtoRGB(cp3[1], pp[13]);
1942                 YCbCrtoRGB(cp3[2], pp[14]);
1943                 YCbCrtoRGB(cp3[3], pp[15]);
1944 
1945                 cp += 4;
1946                 cp1 += 4;
1947                 cp2 += 4;
1948                 cp3 += 4;
1949                 pp += 18;
1950             } while (--x);
1951             cp += incr;
1952             cp1 += incr;
1953             cp2 += incr;
1954             cp3 += incr;
1955             pp += fromskew;
1956         }
1957     } else {
1958         while (h > 0) {
1959             for (x = w; x > 0;) {
1960                 int32 Cb = pp[16];
1961                 int32 Cr = pp[17];
1962                 switch (x) {
1963                 default:
1964                     switch (h) {
1965                     default: YCbCrtoRGB(cp3[3], pp[15]); /* FALLTHROUGH */
1966                     case 3:  YCbCrtoRGB(cp2[3], pp[11]); /* FALLTHROUGH */
1967                     case 2:  YCbCrtoRGB(cp1[3], pp[ 7]); /* FALLTHROUGH */
1968                     case 1:  YCbCrtoRGB(cp [3], pp[ 3]); /* FALLTHROUGH */
1969                     }                                    /* FALLTHROUGH */
1970                 case 3:
1971                     switch (h) {
1972                     default: YCbCrtoRGB(cp3[2], pp[14]); /* FALLTHROUGH */
1973                     case 3:  YCbCrtoRGB(cp2[2], pp[10]); /* FALLTHROUGH */
1974                     case 2:  YCbCrtoRGB(cp1[2], pp[ 6]); /* FALLTHROUGH */
1975                     case 1:  YCbCrtoRGB(cp [2], pp[ 2]); /* FALLTHROUGH */
1976                     }                                    /* FALLTHROUGH */
1977                 case 2:
1978                     switch (h) {
1979                     default: YCbCrtoRGB(cp3[1], pp[13]); /* FALLTHROUGH */
1980                     case 3:  YCbCrtoRGB(cp2[1], pp[ 9]); /* FALLTHROUGH */
1981                     case 2:  YCbCrtoRGB(cp1[1], pp[ 5]); /* FALLTHROUGH */
1982                     case 1:  YCbCrtoRGB(cp [1], pp[ 1]); /* FALLTHROUGH */
1983                     }                                    /* FALLTHROUGH */
1984                 case 1:
1985                     switch (h) {
1986                     default: YCbCrtoRGB(cp3[0], pp[12]); /* FALLTHROUGH */
1987                     case 3:  YCbCrtoRGB(cp2[0], pp[ 8]); /* FALLTHROUGH */
1988                     case 2:  YCbCrtoRGB(cp1[0], pp[ 4]); /* FALLTHROUGH */
1989                     case 1:  YCbCrtoRGB(cp [0], pp[ 0]); /* FALLTHROUGH */
1990                     }                                    /* FALLTHROUGH */
1991                 }
1992                 if (x < 4) {
1993                     cp += x; cp1 += x; cp2 += x; cp3 += x;
1994                     x = 0;
1995                 }
1996                 else {
1997                     cp += 4; cp1 += 4; cp2 += 4; cp3 += 4;
1998                     x -= 4;
1999                 }
2000                 pp += 18;
2001             }
2002             if (h <= 4)
2003                 break;
2004             h -= 4;
2005             cp += incr;
2006             cp1 += incr;
2007             cp2 += incr;
2008             cp3 += incr;
2009             pp += fromskew;
2010         }
2011     }
2012 }
2013 
2014 /*
2015  * 8-bit packed YCbCr samples w/ 4,2 subsampling => RGB
2016  */
DECLAREContigPutFunc(putcontig8bitYCbCr42tile)2017 DECLAREContigPutFunc(putcontig8bitYCbCr42tile)
2018 {
2019     uint32* cp1 = cp+w+toskew;
2020     int32 incr = 2*toskew+w;
2021 
2022     (void) y;
2023     fromskew = (fromskew / 4) * (4*2+2);
2024     if ((w & 3) == 0 && (h & 1) == 0) {
2025         for (; h >= 2; h -= 2) {
2026             x = w>>2;
2027             do {
2028                 int32 Cb = pp[8];
2029                 int32 Cr = pp[9];
2030 
2031                 YCbCrtoRGB(cp [0], pp[0]);
2032                 YCbCrtoRGB(cp [1], pp[1]);
2033                 YCbCrtoRGB(cp [2], pp[2]);
2034                 YCbCrtoRGB(cp [3], pp[3]);
2035                 YCbCrtoRGB(cp1[0], pp[4]);
2036                 YCbCrtoRGB(cp1[1], pp[5]);
2037                 YCbCrtoRGB(cp1[2], pp[6]);
2038                 YCbCrtoRGB(cp1[3], pp[7]);
2039 
2040                 cp += 4;
2041                 cp1 += 4;
2042                 pp += 10;
2043             } while (--x);
2044             cp += incr;
2045             cp1 += incr;
2046             pp += fromskew;
2047         }
2048     } else {
2049         while (h > 0) {
2050             for (x = w; x > 0;) {
2051                 int32 Cb = pp[8];
2052                 int32 Cr = pp[9];
2053                 switch (x) {
2054                 default:
2055                     switch (h) {
2056                     default: YCbCrtoRGB(cp1[3], pp[ 7]); /* FALLTHROUGH */
2057                     case 1:  YCbCrtoRGB(cp [3], pp[ 3]); /* FALLTHROUGH */
2058                     }                                    /* FALLTHROUGH */
2059                 case 3:
2060                     switch (h) {
2061                     default: YCbCrtoRGB(cp1[2], pp[ 6]); /* FALLTHROUGH */
2062                     case 1:  YCbCrtoRGB(cp [2], pp[ 2]); /* FALLTHROUGH */
2063                     }                                    /* FALLTHROUGH */
2064                 case 2:
2065                     switch (h) {
2066                     default: YCbCrtoRGB(cp1[1], pp[ 5]); /* FALLTHROUGH */
2067                     case 1:  YCbCrtoRGB(cp [1], pp[ 1]); /* FALLTHROUGH */
2068                     }                                    /* FALLTHROUGH */
2069                 case 1:
2070                     switch (h) {
2071                     default: YCbCrtoRGB(cp1[0], pp[ 4]); /* FALLTHROUGH */
2072                     case 1:  YCbCrtoRGB(cp [0], pp[ 0]); /* FALLTHROUGH */
2073                     }                                    /* FALLTHROUGH */
2074                 }
2075                 if (x < 4) {
2076                     cp += x; cp1 += x;
2077                     x = 0;
2078                 }
2079                 else {
2080                     cp += 4; cp1 += 4;
2081                     x -= 4;
2082                 }
2083                 pp += 10;
2084             }
2085             if (h <= 2)
2086                 break;
2087             h -= 2;
2088             cp += incr;
2089             cp1 += incr;
2090             pp += fromskew;
2091         }
2092     }
2093 }
2094 
2095 /*
2096  * 8-bit packed YCbCr samples w/ 4,1 subsampling => RGB
2097  */
DECLAREContigPutFunc(putcontig8bitYCbCr41tile)2098 DECLAREContigPutFunc(putcontig8bitYCbCr41tile)
2099 {
2100     (void) y;
2101     fromskew = (fromskew / 4) * (4*1+2);
2102     do {
2103 	x = w>>2;
2104 	while(x>0) {
2105 	    int32 Cb = pp[4];
2106 	    int32 Cr = pp[5];
2107 
2108 	    YCbCrtoRGB(cp [0], pp[0]);
2109 	    YCbCrtoRGB(cp [1], pp[1]);
2110 	    YCbCrtoRGB(cp [2], pp[2]);
2111 	    YCbCrtoRGB(cp [3], pp[3]);
2112 
2113 	    cp += 4;
2114 	    pp += 6;
2115 		x--;
2116 	}
2117 
2118         if( (w&3) != 0 )
2119         {
2120 	    int32 Cb = pp[4];
2121 	    int32 Cr = pp[5];
2122 
2123             switch( (w&3) ) {
2124               case 3: YCbCrtoRGB(cp [2], pp[2]); /*-fallthrough*/
2125               case 2: YCbCrtoRGB(cp [1], pp[1]); /*-fallthrough*/
2126               case 1: YCbCrtoRGB(cp [0], pp[0]); /*-fallthrough*/
2127               case 0: break;
2128             }
2129 
2130             cp += (w&3);
2131             pp += 6;
2132         }
2133 
2134 	cp += toskew;
2135 	pp += fromskew;
2136     } while (--h);
2137 
2138 }
2139 
2140 /*
2141  * 8-bit packed YCbCr samples w/ 2,2 subsampling => RGB
2142  */
DECLAREContigPutFunc(putcontig8bitYCbCr22tile)2143 DECLAREContigPutFunc(putcontig8bitYCbCr22tile)
2144 {
2145 	uint32* cp2;
2146 	int32 incr = 2*toskew+w;
2147 	(void) y;
2148 	fromskew = (fromskew / 2) * (2*2+2);
2149 	cp2 = cp+w+toskew;
2150 	while (h>=2) {
2151 		x = w;
2152 		while (x>=2) {
2153 			uint32 Cb = pp[4];
2154 			uint32 Cr = pp[5];
2155 			YCbCrtoRGB(cp[0], pp[0]);
2156 			YCbCrtoRGB(cp[1], pp[1]);
2157 			YCbCrtoRGB(cp2[0], pp[2]);
2158 			YCbCrtoRGB(cp2[1], pp[3]);
2159 			cp += 2;
2160 			cp2 += 2;
2161 			pp += 6;
2162 			x -= 2;
2163 		}
2164 		if (x==1) {
2165 			uint32 Cb = pp[4];
2166 			uint32 Cr = pp[5];
2167 			YCbCrtoRGB(cp[0], pp[0]);
2168 			YCbCrtoRGB(cp2[0], pp[2]);
2169 			cp ++ ;
2170 			cp2 ++ ;
2171 			pp += 6;
2172 		}
2173 		cp += incr;
2174 		cp2 += incr;
2175 		pp += fromskew;
2176 		h-=2;
2177 	}
2178 	if (h==1) {
2179 		x = w;
2180 		while (x>=2) {
2181 			uint32 Cb = pp[4];
2182 			uint32 Cr = pp[5];
2183 			YCbCrtoRGB(cp[0], pp[0]);
2184 			YCbCrtoRGB(cp[1], pp[1]);
2185 			cp += 2;
2186 			cp2 += 2;
2187 			pp += 6;
2188 			x -= 2;
2189 		}
2190 		if (x==1) {
2191 			uint32 Cb = pp[4];
2192 			uint32 Cr = pp[5];
2193 			YCbCrtoRGB(cp[0], pp[0]);
2194 		}
2195 	}
2196 }
2197 
2198 /*
2199  * 8-bit packed YCbCr samples w/ 2,1 subsampling => RGB
2200  */
DECLAREContigPutFunc(putcontig8bitYCbCr21tile)2201 DECLAREContigPutFunc(putcontig8bitYCbCr21tile)
2202 {
2203 	(void) y;
2204 	fromskew = (fromskew / 2) * (2*1+2);
2205 	do {
2206 		x = w>>1;
2207 		while(x>0) {
2208 			int32 Cb = pp[2];
2209 			int32 Cr = pp[3];
2210 
2211 			YCbCrtoRGB(cp[0], pp[0]);
2212 			YCbCrtoRGB(cp[1], pp[1]);
2213 
2214 			cp += 2;
2215 			pp += 4;
2216 			x --;
2217 		}
2218 
2219 		if( (w&1) != 0 )
2220 		{
2221 			int32 Cb = pp[2];
2222 			int32 Cr = pp[3];
2223 
2224 			YCbCrtoRGB(cp[0], pp[0]);
2225 
2226 			cp += 1;
2227 			pp += 4;
2228 		}
2229 
2230 		cp += toskew;
2231 		pp += fromskew;
2232 	} while (--h);
2233 }
2234 
2235 /*
2236  * 8-bit packed YCbCr samples w/ 1,2 subsampling => RGB
2237  */
DECLAREContigPutFunc(putcontig8bitYCbCr12tile)2238 DECLAREContigPutFunc(putcontig8bitYCbCr12tile)
2239 {
2240 	uint32* cp2;
2241 	int32 incr = 2*toskew+w;
2242 	(void) y;
2243 	fromskew = (fromskew / 1) * (1 * 2 + 2);
2244 	cp2 = cp+w+toskew;
2245 	while (h>=2) {
2246 		x = w;
2247 		do {
2248 			uint32 Cb = pp[2];
2249 			uint32 Cr = pp[3];
2250 			YCbCrtoRGB(cp[0], pp[0]);
2251 			YCbCrtoRGB(cp2[0], pp[1]);
2252 			cp ++;
2253 			cp2 ++;
2254 			pp += 4;
2255 		} while (--x);
2256 		cp += incr;
2257 		cp2 += incr;
2258 		pp += fromskew;
2259 		h-=2;
2260 	}
2261 	if (h==1) {
2262 		x = w;
2263 		do {
2264 			uint32 Cb = pp[2];
2265 			uint32 Cr = pp[3];
2266 			YCbCrtoRGB(cp[0], pp[0]);
2267 			cp ++;
2268 			pp += 4;
2269 		} while (--x);
2270 	}
2271 }
2272 
2273 /*
2274  * 8-bit packed YCbCr samples w/ no subsampling => RGB
2275  */
DECLAREContigPutFunc(putcontig8bitYCbCr11tile)2276 DECLAREContigPutFunc(putcontig8bitYCbCr11tile)
2277 {
2278 	(void) y;
2279 	fromskew = (fromskew / 1) * (1 * 1 + 2);
2280 	do {
2281 		x = w; /* was x = w>>1; patched 2000/09/25 warmerda@home.com */
2282 		do {
2283 			int32 Cb = pp[1];
2284 			int32 Cr = pp[2];
2285 
2286 			YCbCrtoRGB(*cp++, pp[0]);
2287 
2288 			pp += 3;
2289 		} while (--x);
2290 		cp += toskew;
2291 		pp += fromskew;
2292 	} while (--h);
2293 }
2294 
2295 /*
2296  * 8-bit packed YCbCr samples w/ no subsampling => RGB
2297  */
DECLARESepPutFunc(putseparate8bitYCbCr11tile)2298 DECLARESepPutFunc(putseparate8bitYCbCr11tile)
2299 {
2300 	(void) y;
2301 	(void) a;
2302 	/* TODO: naming of input vars is still off, change obfuscating declaration inside define, or resolve obfuscation */
2303 	for( ; h > 0; --h) {
2304 		x = w;
2305 		do {
2306 			uint32 dr, dg, db;
2307 			TIFFYCbCrtoRGB(img->ycbcr,*r++,*g++,*b++,&dr,&dg,&db);
2308 			*cp++ = PACK(dr,dg,db);
2309 		} while (--x);
2310 		SKEW(r, g, b, fromskew);
2311 		cp += toskew;
2312 	}
2313 }
2314 #undef YCbCrtoRGB
2315 
isInRefBlackWhiteRange(float f)2316 static int isInRefBlackWhiteRange(float f)
2317 {
2318     return f > (float)(-0x7FFFFFFF + 128) && f < (float)0x7FFFFFFF;
2319 }
2320 
2321 static int
initYCbCrConversion(TIFFRGBAImage * img)2322 initYCbCrConversion(TIFFRGBAImage* img)
2323 {
2324 	static const char module[] = "initYCbCrConversion";
2325 
2326 	float *luma, *refBlackWhite;
2327 
2328 	if (img->ycbcr == NULL) {
2329 		img->ycbcr = (TIFFYCbCrToRGB*) _TIFFmalloc(
2330 		    TIFFroundup_32(sizeof (TIFFYCbCrToRGB), sizeof (long))
2331 		    + 4*256*sizeof (TIFFRGBValue)
2332 		    + 2*256*sizeof (int)
2333 		    + 3*256*sizeof (int32)
2334 		    );
2335 		if (img->ycbcr == NULL) {
2336 			TIFFErrorExt(img->tif->tif_clientdata, module,
2337 			    "No space for YCbCr->RGB conversion state");
2338 			return (0);
2339 		}
2340 	}
2341 
2342 	TIFFGetFieldDefaulted(img->tif, TIFFTAG_YCBCRCOEFFICIENTS, &luma);
2343 	TIFFGetFieldDefaulted(img->tif, TIFFTAG_REFERENCEBLACKWHITE,
2344 	    &refBlackWhite);
2345 
2346         /* Do some validation to avoid later issues. Detect NaN for now */
2347         /* and also if lumaGreen is zero since we divide by it later */
2348         if( luma[0] != luma[0] ||
2349             luma[1] != luma[1] ||
2350             luma[1] == 0.0 ||
2351             luma[2] != luma[2] )
2352         {
2353             TIFFErrorExt(img->tif->tif_clientdata, module,
2354                 "Invalid values for YCbCrCoefficients tag");
2355             return (0);
2356         }
2357 
2358         if( !isInRefBlackWhiteRange(refBlackWhite[0]) ||
2359             !isInRefBlackWhiteRange(refBlackWhite[1]) ||
2360             !isInRefBlackWhiteRange(refBlackWhite[2]) ||
2361             !isInRefBlackWhiteRange(refBlackWhite[3]) ||
2362             !isInRefBlackWhiteRange(refBlackWhite[4]) ||
2363             !isInRefBlackWhiteRange(refBlackWhite[5]) )
2364         {
2365             TIFFErrorExt(img->tif->tif_clientdata, module,
2366                 "Invalid values for ReferenceBlackWhite tag");
2367             return (0);
2368         }
2369 
2370 	if (TIFFYCbCrToRGBInit(img->ycbcr, luma, refBlackWhite) < 0)
2371 		return(0);
2372 	return (1);
2373 }
2374 
2375 static tileContigRoutine
initCIELabConversion(TIFFRGBAImage * img)2376 initCIELabConversion(TIFFRGBAImage* img)
2377 {
2378 	static const char module[] = "initCIELabConversion";
2379 
2380 	float   *whitePoint;
2381 	float   refWhite[3];
2382 
2383 	TIFFGetFieldDefaulted(img->tif, TIFFTAG_WHITEPOINT, &whitePoint);
2384 	if (whitePoint[1] == 0.0f ) {
2385 		TIFFErrorExt(img->tif->tif_clientdata, module,
2386 		    "Invalid value for WhitePoint tag.");
2387 		return NULL;
2388         }
2389 
2390 	if (!img->cielab) {
2391 		img->cielab = (TIFFCIELabToRGB *)
2392 			_TIFFmalloc(sizeof(TIFFCIELabToRGB));
2393 		if (!img->cielab) {
2394 			TIFFErrorExt(img->tif->tif_clientdata, module,
2395 			    "No space for CIE L*a*b*->RGB conversion state.");
2396 			return NULL;
2397 		}
2398 	}
2399 
2400 	refWhite[1] = 100.0F;
2401 	refWhite[0] = whitePoint[0] / whitePoint[1] * refWhite[1];
2402 	refWhite[2] = (1.0F - whitePoint[0] - whitePoint[1])
2403 		      / whitePoint[1] * refWhite[1];
2404 	if (TIFFCIELabToRGBInit(img->cielab, &display_sRGB, refWhite) < 0) {
2405 		TIFFErrorExt(img->tif->tif_clientdata, module,
2406 		    "Failed to initialize CIE L*a*b*->RGB conversion state.");
2407 		_TIFFfree(img->cielab);
2408 		return NULL;
2409 	}
2410 
2411 	return putcontig8bitCIELab;
2412 }
2413 
2414 /*
2415  * Greyscale images with less than 8 bits/sample are handled
2416  * with a table to avoid lots of shifts and masks.  The table
2417  * is setup so that put*bwtile (below) can retrieve 8/bitspersample
2418  * pixel values simply by indexing into the table with one
2419  * number.
2420  */
2421 static int
makebwmap(TIFFRGBAImage * img)2422 makebwmap(TIFFRGBAImage* img)
2423 {
2424     TIFFRGBValue* Map = img->Map;
2425     int bitspersample = img->bitspersample;
2426     int nsamples = 8 / bitspersample;
2427     int i;
2428     uint32* p;
2429 
2430     if( nsamples == 0 )
2431         nsamples = 1;
2432 
2433     img->BWmap = (uint32**) _TIFFmalloc(
2434 	256*sizeof (uint32 *)+(256*nsamples*sizeof(uint32)));
2435     if (img->BWmap == NULL) {
2436 		TIFFErrorExt(img->tif->tif_clientdata, TIFFFileName(img->tif), "No space for B&W mapping table");
2437 		return (0);
2438     }
2439     p = (uint32*)(img->BWmap + 256);
2440     for (i = 0; i < 256; i++) {
2441 	TIFFRGBValue c;
2442 	img->BWmap[i] = p;
2443 	switch (bitspersample) {
2444 #define	GREY(x)	c = Map[x]; *p++ = PACK(c,c,c);
2445 	case 1:
2446 	    GREY(i>>7);
2447 	    GREY((i>>6)&1);
2448 	    GREY((i>>5)&1);
2449 	    GREY((i>>4)&1);
2450 	    GREY((i>>3)&1);
2451 	    GREY((i>>2)&1);
2452 	    GREY((i>>1)&1);
2453 	    GREY(i&1);
2454 	    break;
2455 	case 2:
2456 	    GREY(i>>6);
2457 	    GREY((i>>4)&3);
2458 	    GREY((i>>2)&3);
2459 	    GREY(i&3);
2460 	    break;
2461 	case 4:
2462 	    GREY(i>>4);
2463 	    GREY(i&0xf);
2464 	    break;
2465 	case 8:
2466         case 16:
2467 	    GREY(i);
2468 	    break;
2469 	}
2470 #undef	GREY
2471     }
2472     return (1);
2473 }
2474 
2475 /*
2476  * Construct a mapping table to convert from the range
2477  * of the data samples to [0,255] --for display.  This
2478  * process also handles inverting B&W images when needed.
2479  */
2480 static int
setupMap(TIFFRGBAImage * img)2481 setupMap(TIFFRGBAImage* img)
2482 {
2483     int32 x, range;
2484 
2485     range = (int32)((1L<<img->bitspersample)-1);
2486 
2487     /* treat 16 bit the same as eight bit */
2488     if( img->bitspersample == 16 )
2489         range = (int32) 255;
2490 
2491     img->Map = (TIFFRGBValue*) _TIFFmalloc((range+1) * sizeof (TIFFRGBValue));
2492     if (img->Map == NULL) {
2493 		TIFFErrorExt(img->tif->tif_clientdata, TIFFFileName(img->tif),
2494 			"No space for photometric conversion table");
2495 		return (0);
2496     }
2497     if (img->photometric == PHOTOMETRIC_MINISWHITE) {
2498 	for (x = 0; x <= range; x++)
2499 	    img->Map[x] = (TIFFRGBValue) (((range - x) * 255) / range);
2500     } else {
2501 	for (x = 0; x <= range; x++)
2502 	    img->Map[x] = (TIFFRGBValue) ((x * 255) / range);
2503     }
2504     if (img->bitspersample <= 16 &&
2505 	(img->photometric == PHOTOMETRIC_MINISBLACK ||
2506 	 img->photometric == PHOTOMETRIC_MINISWHITE)) {
2507 	/*
2508 	 * Use photometric mapping table to construct
2509 	 * unpacking tables for samples <= 8 bits.
2510 	 */
2511 	if (!makebwmap(img))
2512 	    return (0);
2513 	/* no longer need Map, free it */
2514 	_TIFFfree(img->Map);
2515 	img->Map = NULL;
2516     }
2517     return (1);
2518 }
2519 
2520 static int
checkcmap(TIFFRGBAImage * img)2521 checkcmap(TIFFRGBAImage* img)
2522 {
2523     uint16* r = img->redcmap;
2524     uint16* g = img->greencmap;
2525     uint16* b = img->bluecmap;
2526     long n = 1L<<img->bitspersample;
2527 
2528     while (n-- > 0)
2529 	if (*r++ >= 256 || *g++ >= 256 || *b++ >= 256)
2530 	    return (16);
2531     return (8);
2532 }
2533 
2534 static void
cvtcmap(TIFFRGBAImage * img)2535 cvtcmap(TIFFRGBAImage* img)
2536 {
2537     uint16* r = img->redcmap;
2538     uint16* g = img->greencmap;
2539     uint16* b = img->bluecmap;
2540     long i;
2541 
2542     for (i = (1L<<img->bitspersample)-1; i >= 0; i--) {
2543 #define	CVT(x)		((uint16)((x)>>8))
2544 	r[i] = CVT(r[i]);
2545 	g[i] = CVT(g[i]);
2546 	b[i] = CVT(b[i]);
2547 #undef	CVT
2548     }
2549 }
2550 
2551 /*
2552  * Palette images with <= 8 bits/sample are handled
2553  * with a table to avoid lots of shifts and masks.  The table
2554  * is setup so that put*cmaptile (below) can retrieve 8/bitspersample
2555  * pixel values simply by indexing into the table with one
2556  * number.
2557  */
2558 static int
makecmap(TIFFRGBAImage * img)2559 makecmap(TIFFRGBAImage* img)
2560 {
2561     int bitspersample = img->bitspersample;
2562     int nsamples = 8 / bitspersample;
2563     uint16* r = img->redcmap;
2564     uint16* g = img->greencmap;
2565     uint16* b = img->bluecmap;
2566     uint32 *p;
2567     int i;
2568 
2569     img->PALmap = (uint32**) _TIFFmalloc(
2570 	256*sizeof (uint32 *)+(256*nsamples*sizeof(uint32)));
2571     if (img->PALmap == NULL) {
2572 		TIFFErrorExt(img->tif->tif_clientdata, TIFFFileName(img->tif), "No space for Palette mapping table");
2573 		return (0);
2574 	}
2575     p = (uint32*)(img->PALmap + 256);
2576     for (i = 0; i < 256; i++) {
2577 	TIFFRGBValue c;
2578 	img->PALmap[i] = p;
2579 #define	CMAP(x)	c = (TIFFRGBValue) x; *p++ = PACK(r[c]&0xff, g[c]&0xff, b[c]&0xff);
2580 	switch (bitspersample) {
2581 	case 1:
2582 	    CMAP(i>>7);
2583 	    CMAP((i>>6)&1);
2584 	    CMAP((i>>5)&1);
2585 	    CMAP((i>>4)&1);
2586 	    CMAP((i>>3)&1);
2587 	    CMAP((i>>2)&1);
2588 	    CMAP((i>>1)&1);
2589 	    CMAP(i&1);
2590 	    break;
2591 	case 2:
2592 	    CMAP(i>>6);
2593 	    CMAP((i>>4)&3);
2594 	    CMAP((i>>2)&3);
2595 	    CMAP(i&3);
2596 	    break;
2597 	case 4:
2598 	    CMAP(i>>4);
2599 	    CMAP(i&0xf);
2600 	    break;
2601 	case 8:
2602 	    CMAP(i);
2603 	    break;
2604 	}
2605 #undef CMAP
2606     }
2607     return (1);
2608 }
2609 
2610 /*
2611  * Construct any mapping table used
2612  * by the associated put routine.
2613  */
2614 static int
buildMap(TIFFRGBAImage * img)2615 buildMap(TIFFRGBAImage* img)
2616 {
2617     switch (img->photometric) {
2618     case PHOTOMETRIC_RGB:
2619     case PHOTOMETRIC_YCBCR:
2620     case PHOTOMETRIC_SEPARATED:
2621 	if (img->bitspersample == 8)
2622 	    break;
2623 	/* fall through... */
2624     case PHOTOMETRIC_MINISBLACK:
2625     case PHOTOMETRIC_MINISWHITE:
2626 	if (!setupMap(img))
2627 	    return (0);
2628 	break;
2629     case PHOTOMETRIC_PALETTE:
2630 	/*
2631 	 * Convert 16-bit colormap to 8-bit (unless it looks
2632 	 * like an old-style 8-bit colormap).
2633 	 */
2634 	if (checkcmap(img) == 16)
2635 	    cvtcmap(img);
2636 	else
2637 	    TIFFWarningExt(img->tif->tif_clientdata, TIFFFileName(img->tif), "Assuming 8-bit colormap");
2638 	/*
2639 	 * Use mapping table and colormap to construct
2640 	 * unpacking tables for samples < 8 bits.
2641 	 */
2642 	if (img->bitspersample <= 8 && !makecmap(img))
2643 	    return (0);
2644 	break;
2645     }
2646     return (1);
2647 }
2648 
2649 /*
2650  * Select the appropriate conversion routine for packed data.
2651  */
2652 static int
PickContigCase(TIFFRGBAImage * img)2653 PickContigCase(TIFFRGBAImage* img)
2654 {
2655 	img->get = TIFFIsTiled(img->tif) ? gtTileContig : gtStripContig;
2656 	img->put.contig = NULL;
2657 	switch (img->photometric) {
2658 		case PHOTOMETRIC_RGB:
2659 			switch (img->bitspersample) {
2660 				case 8:
2661 					if (img->alpha == EXTRASAMPLE_ASSOCALPHA &&
2662 						img->samplesperpixel >= 4)
2663 						img->put.contig = putRGBAAcontig8bittile;
2664 					else if (img->alpha == EXTRASAMPLE_UNASSALPHA &&
2665 							 img->samplesperpixel >= 4)
2666 					{
2667 						if (BuildMapUaToAa(img))
2668 							img->put.contig = putRGBUAcontig8bittile;
2669 					}
2670 					else if( img->samplesperpixel >= 3 )
2671 						img->put.contig = putRGBcontig8bittile;
2672 					break;
2673 				case 16:
2674 					if (img->alpha == EXTRASAMPLE_ASSOCALPHA &&
2675 						img->samplesperpixel >=4 )
2676 					{
2677 						if (BuildMapBitdepth16To8(img))
2678 							img->put.contig = putRGBAAcontig16bittile;
2679 					}
2680 					else if (img->alpha == EXTRASAMPLE_UNASSALPHA &&
2681 							 img->samplesperpixel >=4 )
2682 					{
2683 						if (BuildMapBitdepth16To8(img) &&
2684 						    BuildMapUaToAa(img))
2685 							img->put.contig = putRGBUAcontig16bittile;
2686 					}
2687 					else if( img->samplesperpixel >=3 )
2688 					{
2689 						if (BuildMapBitdepth16To8(img))
2690 							img->put.contig = putRGBcontig16bittile;
2691 					}
2692 					break;
2693 			}
2694 			break;
2695 		case PHOTOMETRIC_SEPARATED:
2696 			if (img->samplesperpixel >=4 && buildMap(img)) {
2697 				if (img->bitspersample == 8) {
2698 					if (!img->Map)
2699 						img->put.contig = putRGBcontig8bitCMYKtile;
2700 					else
2701 						img->put.contig = putRGBcontig8bitCMYKMaptile;
2702 				}
2703 			}
2704 			break;
2705 		case PHOTOMETRIC_PALETTE:
2706 			if (buildMap(img)) {
2707 				switch (img->bitspersample) {
2708 					case 8:
2709 						img->put.contig = put8bitcmaptile;
2710 						break;
2711 					case 4:
2712 						img->put.contig = put4bitcmaptile;
2713 						break;
2714 					case 2:
2715 						img->put.contig = put2bitcmaptile;
2716 						break;
2717 					case 1:
2718 						img->put.contig = put1bitcmaptile;
2719 						break;
2720 				}
2721 			}
2722 			break;
2723 		case PHOTOMETRIC_MINISWHITE:
2724 		case PHOTOMETRIC_MINISBLACK:
2725 			if (buildMap(img)) {
2726 				switch (img->bitspersample) {
2727 					case 16:
2728 						img->put.contig = put16bitbwtile;
2729 						break;
2730 					case 8:
2731 						if (img->alpha && img->samplesperpixel == 2)
2732 							img->put.contig = putagreytile;
2733 						else
2734 							img->put.contig = putgreytile;
2735 						break;
2736 					case 4:
2737 						img->put.contig = put4bitbwtile;
2738 						break;
2739 					case 2:
2740 						img->put.contig = put2bitbwtile;
2741 						break;
2742 					case 1:
2743 						img->put.contig = put1bitbwtile;
2744 						break;
2745 				}
2746 			}
2747 			break;
2748 		case PHOTOMETRIC_YCBCR:
2749 			if ((img->bitspersample==8) && (img->samplesperpixel==3))
2750 			{
2751 				if (initYCbCrConversion(img)!=0)
2752 				{
2753 					/*
2754 					 * The 6.0 spec says that subsampling must be
2755 					 * one of 1, 2, or 4, and that vertical subsampling
2756 					 * must always be <= horizontal subsampling; so
2757 					 * there are only a few possibilities and we just
2758 					 * enumerate the cases.
2759 					 * Joris: added support for the [1,2] case, nonetheless, to accommodate
2760 					 * some OJPEG files
2761 					 */
2762 					uint16 SubsamplingHor;
2763 					uint16 SubsamplingVer;
2764 					TIFFGetFieldDefaulted(img->tif, TIFFTAG_YCBCRSUBSAMPLING, &SubsamplingHor, &SubsamplingVer);
2765 					switch ((SubsamplingHor<<4)|SubsamplingVer) {
2766 						case 0x44:
2767 							img->put.contig = putcontig8bitYCbCr44tile;
2768 							break;
2769 						case 0x42:
2770 							img->put.contig = putcontig8bitYCbCr42tile;
2771 							break;
2772 						case 0x41:
2773 							img->put.contig = putcontig8bitYCbCr41tile;
2774 							break;
2775 						case 0x22:
2776 							img->put.contig = putcontig8bitYCbCr22tile;
2777 							break;
2778 						case 0x21:
2779 							img->put.contig = putcontig8bitYCbCr21tile;
2780 							break;
2781 						case 0x12:
2782 							img->put.contig = putcontig8bitYCbCr12tile;
2783 							break;
2784 						case 0x11:
2785 							img->put.contig = putcontig8bitYCbCr11tile;
2786 							break;
2787 					}
2788 				}
2789 			}
2790 			break;
2791 		case PHOTOMETRIC_CIELAB:
2792 			if (img->samplesperpixel == 3 && buildMap(img)) {
2793 				if (img->bitspersample == 8)
2794 					img->put.contig = initCIELabConversion(img);
2795 				break;
2796 			}
2797 	}
2798 	return ((img->get!=NULL) && (img->put.contig!=NULL));
2799 }
2800 
2801 /*
2802  * Select the appropriate conversion routine for unpacked data.
2803  *
2804  * NB: we assume that unpacked single channel data is directed
2805  *	 to the "packed routines.
2806  */
2807 static int
PickSeparateCase(TIFFRGBAImage * img)2808 PickSeparateCase(TIFFRGBAImage* img)
2809 {
2810 	img->get = TIFFIsTiled(img->tif) ? gtTileSeparate : gtStripSeparate;
2811 	img->put.separate = NULL;
2812 	switch (img->photometric) {
2813 	case PHOTOMETRIC_MINISWHITE:
2814 	case PHOTOMETRIC_MINISBLACK:
2815 		/* greyscale images processed pretty much as RGB by gtTileSeparate */
2816 	case PHOTOMETRIC_RGB:
2817 		switch (img->bitspersample) {
2818 		case 8:
2819 			if (img->alpha == EXTRASAMPLE_ASSOCALPHA)
2820 				img->put.separate = putRGBAAseparate8bittile;
2821 			else if (img->alpha == EXTRASAMPLE_UNASSALPHA)
2822 			{
2823 				if (BuildMapUaToAa(img))
2824 					img->put.separate = putRGBUAseparate8bittile;
2825 			}
2826 			else
2827 				img->put.separate = putRGBseparate8bittile;
2828 			break;
2829 		case 16:
2830 			if (img->alpha == EXTRASAMPLE_ASSOCALPHA)
2831 			{
2832 				if (BuildMapBitdepth16To8(img))
2833 					img->put.separate = putRGBAAseparate16bittile;
2834 			}
2835 			else if (img->alpha == EXTRASAMPLE_UNASSALPHA)
2836 			{
2837 				if (BuildMapBitdepth16To8(img) &&
2838 				    BuildMapUaToAa(img))
2839 					img->put.separate = putRGBUAseparate16bittile;
2840 			}
2841 			else
2842 			{
2843 				if (BuildMapBitdepth16To8(img))
2844 					img->put.separate = putRGBseparate16bittile;
2845 			}
2846 			break;
2847 		}
2848 		break;
2849 	case PHOTOMETRIC_SEPARATED:
2850 		if (img->bitspersample == 8 && img->samplesperpixel == 4)
2851 		{
2852 			img->alpha = 1; // Not alpha, but seems like the only way to get 4th band
2853 			img->put.separate = putCMYKseparate8bittile;
2854 		}
2855 		break;
2856 	case PHOTOMETRIC_YCBCR:
2857 		if ((img->bitspersample==8) && (img->samplesperpixel==3))
2858 		{
2859 			if (initYCbCrConversion(img)!=0)
2860 			{
2861 				uint16 hs, vs;
2862 				TIFFGetFieldDefaulted(img->tif, TIFFTAG_YCBCRSUBSAMPLING, &hs, &vs);
2863 				switch ((hs<<4)|vs) {
2864 				case 0x11:
2865 					img->put.separate = putseparate8bitYCbCr11tile;
2866 					break;
2867 					/* TODO: add other cases here */
2868 				}
2869 			}
2870 		}
2871 		break;
2872 	}
2873 	return ((img->get!=NULL) && (img->put.separate!=NULL));
2874 }
2875 
2876 static int
BuildMapUaToAa(TIFFRGBAImage * img)2877 BuildMapUaToAa(TIFFRGBAImage* img)
2878 {
2879 	static const char module[]="BuildMapUaToAa";
2880 	uint8* m;
2881 	uint16 na,nv;
2882 	assert(img->UaToAa==NULL);
2883 	img->UaToAa=_TIFFmalloc(65536);
2884 	if (img->UaToAa==NULL)
2885 	{
2886 		TIFFErrorExt(img->tif->tif_clientdata,module,"Out of memory");
2887 		return(0);
2888 	}
2889 	m=img->UaToAa;
2890 	for (na=0; na<256; na++)
2891 	{
2892 		for (nv=0; nv<256; nv++)
2893 			*m++=(uint8)((nv*na+127)/255);
2894 	}
2895 	return(1);
2896 }
2897 
2898 static int
BuildMapBitdepth16To8(TIFFRGBAImage * img)2899 BuildMapBitdepth16To8(TIFFRGBAImage* img)
2900 {
2901 	static const char module[]="BuildMapBitdepth16To8";
2902 	uint8* m;
2903 	uint32 n;
2904 	assert(img->Bitdepth16To8==NULL);
2905 	img->Bitdepth16To8=_TIFFmalloc(65536);
2906 	if (img->Bitdepth16To8==NULL)
2907 	{
2908 		TIFFErrorExt(img->tif->tif_clientdata,module,"Out of memory");
2909 		return(0);
2910 	}
2911 	m=img->Bitdepth16To8;
2912 	for (n=0; n<65536; n++)
2913 		*m++=(uint8)((n+128)/257);
2914 	return(1);
2915 }
2916 
2917 
2918 /*
2919  * Read a whole strip off data from the file, and convert to RGBA form.
2920  * If this is the last strip, then it will only contain the portion of
2921  * the strip that is actually within the image space.  The result is
2922  * organized in bottom to top form.
2923  */
2924 
2925 
2926 int
TIFFReadRGBAStrip(TIFF * tif,uint32 row,uint32 * raster)2927 TIFFReadRGBAStrip(TIFF* tif, uint32 row, uint32 * raster )
2928 
2929 {
2930     return TIFFReadRGBAStripExt(tif, row, raster, 0 );
2931 }
2932 
2933 int
TIFFReadRGBAStripExt(TIFF * tif,uint32 row,uint32 * raster,int stop_on_error)2934 TIFFReadRGBAStripExt(TIFF* tif, uint32 row, uint32 * raster, int stop_on_error)
2935 
2936 {
2937     char 	emsg[1024] = "";
2938     TIFFRGBAImage img;
2939     int 	ok;
2940     uint32	rowsperstrip, rows_to_read;
2941 
2942     if( TIFFIsTiled( tif ) )
2943     {
2944 		TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif),
2945                   "Can't use TIFFReadRGBAStrip() with tiled file.");
2946 	return (0);
2947     }
2948 
2949     TIFFGetFieldDefaulted(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip);
2950     if( (row % rowsperstrip) != 0 )
2951     {
2952 		TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif),
2953 				"Row passed to TIFFReadRGBAStrip() must be first in a strip.");
2954 		return (0);
2955     }
2956 
2957     if (TIFFRGBAImageOK(tif, emsg) && TIFFRGBAImageBegin(&img, tif, stop_on_error, emsg)) {
2958 
2959         img.row_offset = row;
2960         img.col_offset = 0;
2961 
2962         if( row + rowsperstrip > img.height )
2963             rows_to_read = img.height - row;
2964         else
2965             rows_to_read = rowsperstrip;
2966 
2967 	ok = TIFFRGBAImageGet(&img, raster, img.width, rows_to_read );
2968 
2969 	TIFFRGBAImageEnd(&img);
2970     } else {
2971 		TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "%s", emsg);
2972 		ok = 0;
2973     }
2974 
2975     return (ok);
2976 }
2977 
2978 /*
2979  * Read a whole tile off data from the file, and convert to RGBA form.
2980  * The returned RGBA data is organized from bottom to top of tile,
2981  * and may include zeroed areas if the tile extends off the image.
2982  */
2983 
2984 int
TIFFReadRGBATile(TIFF * tif,uint32 col,uint32 row,uint32 * raster)2985 TIFFReadRGBATile(TIFF* tif, uint32 col, uint32 row, uint32 * raster)
2986 
2987 {
2988     return TIFFReadRGBATileExt(tif, col, row, raster, 0 );
2989 }
2990 
2991 
2992 int
TIFFReadRGBATileExt(TIFF * tif,uint32 col,uint32 row,uint32 * raster,int stop_on_error)2993 TIFFReadRGBATileExt(TIFF* tif, uint32 col, uint32 row, uint32 * raster, int stop_on_error )
2994 {
2995     char 	emsg[1024] = "";
2996     TIFFRGBAImage img;
2997     int 	ok;
2998     uint32	tile_xsize, tile_ysize;
2999     uint32	read_xsize, read_ysize;
3000     uint32	i_row;
3001 
3002     /*
3003      * Verify that our request is legal - on a tile file, and on a
3004      * tile boundary.
3005      */
3006 
3007     if( !TIFFIsTiled( tif ) )
3008     {
3009 		TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif),
3010 				  "Can't use TIFFReadRGBATile() with striped file.");
3011 		return (0);
3012     }
3013 
3014     TIFFGetFieldDefaulted(tif, TIFFTAG_TILEWIDTH, &tile_xsize);
3015     TIFFGetFieldDefaulted(tif, TIFFTAG_TILELENGTH, &tile_ysize);
3016     if( (col % tile_xsize) != 0 || (row % tile_ysize) != 0 )
3017     {
3018 		TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif),
3019                   "Row/col passed to TIFFReadRGBATile() must be top"
3020                   "left corner of a tile.");
3021 	return (0);
3022     }
3023 
3024     /*
3025      * Setup the RGBA reader.
3026      */
3027 
3028     if (!TIFFRGBAImageOK(tif, emsg)
3029 	|| !TIFFRGBAImageBegin(&img, tif, stop_on_error, emsg)) {
3030 	    TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "%s", emsg);
3031 	    return( 0 );
3032     }
3033 
3034     /*
3035      * The TIFFRGBAImageGet() function doesn't allow us to get off the
3036      * edge of the image, even to fill an otherwise valid tile.  So we
3037      * figure out how much we can read, and fix up the tile buffer to
3038      * a full tile configuration afterwards.
3039      */
3040 
3041     if( row + tile_ysize > img.height )
3042         read_ysize = img.height - row;
3043     else
3044         read_ysize = tile_ysize;
3045 
3046     if( col + tile_xsize > img.width )
3047         read_xsize = img.width - col;
3048     else
3049         read_xsize = tile_xsize;
3050 
3051     /*
3052      * Read the chunk of imagery.
3053      */
3054 
3055     img.row_offset = row;
3056     img.col_offset = col;
3057 
3058     ok = TIFFRGBAImageGet(&img, raster, read_xsize, read_ysize );
3059 
3060     TIFFRGBAImageEnd(&img);
3061 
3062     /*
3063      * If our read was incomplete we will need to fix up the tile by
3064      * shifting the data around as if a full tile of data is being returned.
3065      *
3066      * This is all the more complicated because the image is organized in
3067      * bottom to top format.
3068      */
3069 
3070     if( read_xsize == tile_xsize && read_ysize == tile_ysize )
3071         return( ok );
3072 
3073     for( i_row = 0; i_row < read_ysize; i_row++ ) {
3074         memmove( raster + (tile_ysize - i_row - 1) * tile_xsize,
3075                  raster + (read_ysize - i_row - 1) * read_xsize,
3076                  read_xsize * sizeof(uint32) );
3077         _TIFFmemset( raster + (tile_ysize - i_row - 1) * tile_xsize+read_xsize,
3078                      0, sizeof(uint32) * (tile_xsize - read_xsize) );
3079     }
3080 
3081     for( i_row = read_ysize; i_row < tile_ysize; i_row++ ) {
3082         _TIFFmemset( raster + (tile_ysize - i_row - 1) * tile_xsize,
3083                      0, sizeof(uint32) * tile_xsize );
3084     }
3085 
3086     return (ok);
3087 }
3088 
3089 /* vim: set ts=8 sts=8 sw=8 noet: */
3090 /*
3091  * Local Variables:
3092  * mode: c
3093  * c-basic-offset: 8
3094  * fill-column: 78
3095  * End:
3096  */
3097