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