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