PageRenderTime 123ms CodeModel.GetById 18ms app.highlight 92ms RepoModel.GetById 1ms app.codeStats 1ms

/src/FreeImage/Source/LibTIFF/tif_getimage.c

https://bitbucket.org/cabalistic/ogredeps/
C | 2554 lines | 2069 code | 183 blank | 302 comment | 389 complexity | 01a416068600961142938173e5984966 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1/* $Id: tif_getimage.c,v 1.39 2011/04/10 17:14:09 drolon 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*);
  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	int32 incr = 2*toskew+w;
1850	(void) y;
1851	fromskew = (fromskew / 2) * 6;
1852	cp2 = cp+w+toskew;
1853	while (h>=2) {
1854		x = w;
1855		while (x>=2) {
1856			uint32 Cb = pp[4];
1857			uint32 Cr = pp[5];
1858			YCbCrtoRGB(cp[0], pp[0]);
1859			YCbCrtoRGB(cp[1], pp[1]);
1860			YCbCrtoRGB(cp2[0], pp[2]);
1861			YCbCrtoRGB(cp2[1], pp[3]);
1862			cp += 2;
1863			cp2 += 2;
1864			pp += 6;
1865			x -= 2;
1866		}
1867		if (x==1) {
1868			uint32 Cb = pp[4];
1869			uint32 Cr = pp[5];
1870			YCbCrtoRGB(cp[0], pp[0]);
1871			YCbCrtoRGB(cp2[0], pp[2]);
1872			cp ++ ;
1873			cp2 ++ ;
1874			pp += 6;
1875		}
1876		cp += incr;
1877		cp2 += incr;
1878		pp += fromskew;
1879		h-=2;
1880	}
1881	if (h==1) {
1882		x = w;
1883		while (x>=2) {
1884			uint32 Cb = pp[4];
1885			uint32 Cr = pp[5];
1886			YCbCrtoRGB(cp[0], pp[0]);
1887			YCbCrtoRGB(cp[1], pp[1]);
1888			cp += 2;
1889			cp2 += 2;
1890			pp += 6;
1891			x -= 2;
1892		}
1893		if (x==1) {
1894			uint32 Cb = pp[4];
1895			uint32 Cr = pp[5];
1896			YCbCrtoRGB(cp[0], pp[0]);
1897		}
1898	}
1899}
1900
1901/*
1902 * 8-bit packed YCbCr samples w/ 2,1 subsampling => RGB
1903 */
1904DECLAREContigPutFunc(putcontig8bi

Large files files are truncated, but you can click here to view the full file