home *** CD-ROM | disk | FTP | other *** search
- /*
- * Copyright (c) 1991-1997 Sam Leffler
- * Copyright (c) 1991-1997 Silicon Graphics, Inc.
- *
- * Permission to use, copy, modify, distribute, and sell this software and
- * its documentation for any purpose is hereby granted without fee, provided
- * that (i) the above copyright notices and this permission notice appear in
- * all copies of the software and related documentation, and (ii) the names of
- * Sam Leffler and Silicon Graphics may not be used in any advertising or
- * publicity relating to the software without the specific, prior written
- * permission of Sam Leffler and Silicon Graphics.
- *
- * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
- * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
- *
- * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
- * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
- * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
- * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
- * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
- * OF THIS SOFTWARE.
- */
-
- /*
- * TIFF Library
- *
- * Read and return a packed RGBA image.
- */
-
- /* $Id: tif_getimage.c,v 1.6 2001/03/21 17:16:25 rjs Exp $ */
-
- #include "tiffiop.h"
- #include <stdio.h>
-
- static int gtTileContig(TIFFRGBAImage*, uint32*, uint32, uint32);
- static int gtTileSeparate(TIFFRGBAImage*, uint32*, uint32, uint32);
- static int gtStripContig(TIFFRGBAImage*, uint32*, uint32, uint32);
- static int gtStripSeparate(TIFFRGBAImage*, uint32*, uint32, uint32);
- static int pickTileContigCase(TIFFRGBAImage*);
- static int pickTileSeparateCase(TIFFRGBAImage*);
-
- static const char photoTag[] = "PhotometricInterpretation";
-
- /*
- * Check the image to see if TIFFReadRGBAImage can deal with it.
- * 1/0 is returned according to whether or not the image can
- * be handled. If 0 is returned, emsg contains the reason
- * why it is being rejected.
- */
- int
- TIFFRGBAImageOK(TIFF* tif, char emsg[1024])
- {
- TIFFDirectory* td = &tif->tif_dir;
- uint16 photometric;
- int colorchannels;
-
- switch (td->td_bitspersample) {
- case 1: case 2: case 4:
- case 8: case 16:
- break;
- default:
- sprintf(emsg, "Sorry, can not handle images with %d-bit samples",
- td->td_bitspersample);
- return (0);
- }
- colorchannels = td->td_samplesperpixel - td->td_extrasamples;
- if (!TIFFGetField(tif, TIFFTAG_PHOTOMETRIC, &photometric)) {
- switch (colorchannels) {
- case 1:
- photometric = PHOTOMETRIC_MINISBLACK;
- break;
- case 3:
- photometric = PHOTOMETRIC_RGB;
- break;
- default:
- sprintf(emsg, "Missing needed %s tag", photoTag);
- return (0);
- }
- }
- switch (photometric) {
- case PHOTOMETRIC_MINISWHITE:
- case PHOTOMETRIC_MINISBLACK:
- case PHOTOMETRIC_PALETTE:
- if (td->td_planarconfig == PLANARCONFIG_CONTIG
- && td->td_samplesperpixel != 1) {
- sprintf(emsg,
- "Sorry, can not handle contiguous data with %s=%d, and %s=%d",
- photoTag, photometric,
- "Samples/pixel", td->td_samplesperpixel);
- return (0);
- }
- break;
- case PHOTOMETRIC_YCBCR:
- if (td->td_planarconfig != PLANARCONFIG_CONTIG) {
- sprintf(emsg, "Sorry, can not handle YCbCr images with %s=%d",
- "Planarconfiguration", td->td_planarconfig);
- return (0);
- }
- break;
- case PHOTOMETRIC_RGB:
- if (colorchannels < 3) {
- sprintf(emsg, "Sorry, can not handle RGB image with %s=%d",
- "Color channels", colorchannels);
- return (0);
- }
- break;
- #ifdef CMYK_SUPPORT
- case PHOTOMETRIC_SEPARATED:
- if (td->td_inkset != INKSET_CMYK) {
- sprintf(emsg, "Sorry, can not handle separated image with %s=%d",
- "InkSet", td->td_inkset);
- return (0);
- }
- if (td->td_samplesperpixel != 4) {
- sprintf(emsg, "Sorry, can not handle separated image with %s=%d",
- "Samples/pixel", td->td_samplesperpixel);
- return (0);
- }
- break;
- #endif
- case PHOTOMETRIC_LOGL:
- if (td->td_compression != COMPRESSION_SGILOG) {
- sprintf(emsg, "Sorry, LogL data must have %s=%d",
- "Compression", COMPRESSION_SGILOG);
- return (0);
- }
- break;
- case PHOTOMETRIC_LOGLUV:
- if (td->td_compression != COMPRESSION_SGILOG &&
- td->td_compression != COMPRESSION_SGILOG24) {
- sprintf(emsg, "Sorry, LogLuv data must have %s=%d or %d",
- "Compression", COMPRESSION_SGILOG, COMPRESSION_SGILOG24);
- return (0);
- }
- if (td->td_planarconfig != PLANARCONFIG_CONTIG) {
- sprintf(emsg, "Sorry, can not handle LogLuv images with %s=%d",
- "Planarconfiguration", td->td_planarconfig);
- return (0);
- }
- break;
- default:
- sprintf(emsg, "Sorry, can not handle image with %s=%d",
- photoTag, photometric);
- return (0);
- }
- return (1);
- }
-
- void
- TIFFRGBAImageEnd(TIFFRGBAImage* img)
- {
- TIFF* tif = img->tif;
-
- if (img->Map)
- _TIFFfree(tif, img->Map), img->Map = NULL;
- if (img->BWmap)
- _TIFFfree(tif, img->BWmap), img->BWmap = NULL;
- if (img->PALmap)
- _TIFFfree(tif, img->PALmap), img->PALmap = NULL;
- if (img->ycbcr)
- _TIFFfree(tif, img->ycbcr), img->ycbcr = NULL;
-
- if( img->redcmap ) {
- _TIFFfree(tif, img->redcmap );
- _TIFFfree(tif, img->greencmap );
- _TIFFfree(tif, img->bluecmap );
- }
- }
-
- static int
- isCCITTCompression(TIFF* tif)
- {
- uint16 compress;
- TIFFGetField(tif, TIFFTAG_COMPRESSION, &compress);
- return (compress == COMPRESSION_CCITTFAX3 ||
- compress == COMPRESSION_CCITTFAX4 ||
- compress == COMPRESSION_CCITTRLE ||
- compress == COMPRESSION_CCITTRLEW);
- }
-
- int
- TIFFRGBAImageBegin(TIFFRGBAImage* img, TIFF* tif, int stop, char emsg[1024])
- {
- uint16* sampleinfo;
- uint16 extrasamples;
- uint16 planarconfig;
- uint16 compress;
- int colorchannels;
- uint16 *red_orig, *green_orig, *blue_orig;
- int n_color;
-
- /* Initialize to normal values */
- img->row_offset = 0;
- img->col_offset = 0;
- img->redcmap = NULL;
- img->greencmap = NULL;
- img->bluecmap = NULL;
-
- img->tif = tif;
- img->stoponerr = stop;
- TIFFGetFieldDefaulted(tif, TIFFTAG_BITSPERSAMPLE, &img->bitspersample);
- switch (img->bitspersample) {
- case 1: case 2: case 4:
- case 8: case 16:
- break;
- default:
- sprintf(emsg, "Sorry, can not image with %d-bit samples",
- img->bitspersample);
- return (0);
- }
- img->alpha = 0;
- TIFFGetFieldDefaulted(tif, TIFFTAG_SAMPLESPERPIXEL, &img->samplesperpixel);
- TIFFGetFieldDefaulted(tif, TIFFTAG_EXTRASAMPLES,
- &extrasamples, &sampleinfo);
- if (extrasamples == 1)
- switch (sampleinfo[0]) {
- case EXTRASAMPLE_ASSOCALPHA: /* data is pre-multiplied */
- case EXTRASAMPLE_UNASSALPHA: /* data is not pre-multiplied */
- img->alpha = sampleinfo[0];
- break;
- }
- colorchannels = img->samplesperpixel - extrasamples;
- TIFFGetFieldDefaulted(tif, TIFFTAG_COMPRESSION, &compress);
- TIFFGetFieldDefaulted(tif, TIFFTAG_PLANARCONFIG, &planarconfig);
- if (!TIFFGetField(tif, TIFFTAG_PHOTOMETRIC, &img->photometric)) {
- switch (colorchannels) {
- case 1:
- if (isCCITTCompression(tif))
- img->photometric = PHOTOMETRIC_MINISWHITE;
- else
- img->photometric = PHOTOMETRIC_MINISBLACK;
- break;
- case 3:
- img->photometric = PHOTOMETRIC_RGB;
- break;
- default:
- sprintf(emsg, "Missing needed %s tag", photoTag);
- return (0);
- }
- }
- switch (img->photometric) {
- case PHOTOMETRIC_PALETTE:
- if (!TIFFGetField(tif, TIFFTAG_COLORMAP,
- &red_orig, &green_orig, &blue_orig)) {
- TIFFError(TIFFFileName(tif), "Missing required \"Colormap\" tag");
- return (0);
- }
-
- /* copy the colormaps so we can modify them */
- n_color = (1L << img->bitspersample);
- img->redcmap = (uint16 *) _TIFFmalloc(tif, sizeof(uint16)*n_color);
- img->greencmap = (uint16 *) _TIFFmalloc(tif, sizeof(uint16)*n_color);
- img->bluecmap = (uint16 *) _TIFFmalloc(tif, sizeof(uint16)*n_color);
- if( !img->redcmap || !img->greencmap || !img->bluecmap ) {
- TIFFError(TIFFFileName(tif), "Out of memory for colormap copy");
- return (0);
- }
-
- memcpy( img->redcmap, red_orig, n_color * 2 );
- memcpy( img->greencmap, green_orig, n_color * 2 );
- memcpy( img->bluecmap, blue_orig, n_color * 2 );
-
- /* fall thru... */
- case PHOTOMETRIC_MINISWHITE:
- case PHOTOMETRIC_MINISBLACK:
- if (planarconfig == PLANARCONFIG_CONTIG && img->samplesperpixel != 1) {
- sprintf(emsg,
- "Sorry, can not handle contiguous data with %s=%d, and %s=%d",
- photoTag, img->photometric,
- "Samples/pixel", img->samplesperpixel);
- return (0);
- }
- break;
- case PHOTOMETRIC_YCBCR:
- if (planarconfig != PLANARCONFIG_CONTIG) {
- sprintf(emsg, "Sorry, can not handle YCbCr images with %s=%d",
- "Planarconfiguration", planarconfig);
- return (0);
- }
- /* It would probably be nice to have a reality check here. */
- if (compress == COMPRESSION_JPEG
- && planarconfig == PLANARCONFIG_CONTIG) {
- /* can rely on libjpeg to convert to RGB */
- /* XXX should restore current state on exit */
- TIFFSetField(tif, TIFFTAG_JPEGCOLORMODE, JPEGCOLORMODE_RGB);
- img->photometric = PHOTOMETRIC_RGB;
- }
- break;
- case PHOTOMETRIC_RGB:
- if (colorchannels < 3) {
- sprintf(emsg, "Sorry, can not handle RGB image with %s=%d",
- "Color channels", colorchannels);
- return (0);
- }
- break;
- case PHOTOMETRIC_SEPARATED: {
- uint16 inkset;
- TIFFGetFieldDefaulted(tif, TIFFTAG_INKSET, &inkset);
- if (inkset != INKSET_CMYK) {
- sprintf(emsg, "Sorry, can not handle separated image with %s=%d",
- "InkSet", inkset);
- return (0);
- }
- if (img->samplesperpixel != 4) {
- sprintf(emsg, "Sorry, can not handle separated image with %s=%d",
- "Samples/pixel", img->samplesperpixel);
- return (0);
- }
- break;
- }
- case PHOTOMETRIC_LOGL:
- if (compress != COMPRESSION_SGILOG) {
- sprintf(emsg, "Sorry, LogL data must have %s=%d",
- "Compression", COMPRESSION_SGILOG);
- return (0);
- }
- TIFFSetField(tif, TIFFTAG_SGILOGDATAFMT, SGILOGDATAFMT_8BIT);
- img->photometric = PHOTOMETRIC_MINISBLACK; /* little white lie */
- img->bitspersample = 8;
- break;
- case PHOTOMETRIC_LOGLUV:
- if (compress != COMPRESSION_SGILOG
- && compress != COMPRESSION_SGILOG24) {
- sprintf(emsg, "Sorry, LogLuv data must have %s=%d or %d",
- "Compression", COMPRESSION_SGILOG, COMPRESSION_SGILOG24);
- return (0);
- }
- if (planarconfig != PLANARCONFIG_CONTIG) {
- sprintf(emsg, "Sorry, can not handle LogLuv images with %s=%d",
- "Planarconfiguration", planarconfig);
- return (0);
- }
- TIFFSetField(tif, TIFFTAG_SGILOGDATAFMT, SGILOGDATAFMT_8BIT);
- img->photometric = PHOTOMETRIC_RGB; /* little white lie */
- img->bitspersample = 8;
- break;
- default:
- sprintf(emsg, "Sorry, can not handle image with %s=%d",
- photoTag, img->photometric);
- return (0);
- }
- img->Map = NULL;
- img->BWmap = NULL;
- img->PALmap = NULL;
- img->ycbcr = NULL;
- TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &img->width);
- TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &img->height);
- TIFFGetFieldDefaulted(tif, TIFFTAG_ORIENTATION, &img->orientation);
- img->isContig =
- !(planarconfig == PLANARCONFIG_SEPARATE && colorchannels > 1);
- if (img->isContig) {
- img->get = TIFFIsTiled(tif) ? gtTileContig : gtStripContig;
- (void) pickTileContigCase(img);
- } else {
- img->get = TIFFIsTiled(tif) ? gtTileSeparate : gtStripSeparate;
- (void) pickTileSeparateCase(img);
- }
- return (1);
- }
-
- int
- TIFFRGBAImageGet(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h)
- {
- if (img->get == NULL) {
- TIFFError(TIFFFileName(img->tif), "No \"get\" routine setup");
- return (0);
- }
- if (img->put.any == NULL) {
- TIFFError(TIFFFileName(img->tif),
- "No \"put\" routine setupl; probably can not handle image format");
- return (0);
- }
- return (*img->get)(img, raster, w, h);
- }
-
- /*
- * Read the specified image into an ABGR-format raster.
- */
- int
- TIFFReadRGBAImage(TIFF* tif,
- uint32 rwidth, uint32 rheight, uint32* raster, int stop)
- {
- char emsg[1024];
- TIFFRGBAImage img;
- int ok;
-
- if (TIFFRGBAImageBegin(&img, tif, stop, emsg)) {
- /* XXX verify rwidth and rheight against width and height */
- ok = TIFFRGBAImageGet(&img, raster+(rheight-img.height)*rwidth,
- rwidth, img.height);
- TIFFRGBAImageEnd(&img);
- } else {
- TIFFError(TIFFFileName(tif), emsg);
- ok = 0;
- }
- return (ok);
- }
-
- static uint32
- setorientation(TIFFRGBAImage* img, uint32 h)
- {
- TIFF* tif = img->tif;
- uint32 y;
-
- switch (img->orientation) {
- case ORIENTATION_BOTRIGHT:
- case ORIENTATION_RIGHTBOT: /* XXX */
- case ORIENTATION_LEFTBOT: /* XXX */
- TIFFWarning(TIFFFileName(tif), "using bottom-left orientation");
- img->orientation = ORIENTATION_BOTLEFT;
- /* fall thru... */
- case ORIENTATION_BOTLEFT:
- y = 0;
- break;
- case ORIENTATION_TOPRIGHT:
- case ORIENTATION_RIGHTTOP: /* XXX */
- case ORIENTATION_LEFTTOP: /* XXX */
- default:
- TIFFWarning(TIFFFileName(tif), "using top-left orientation");
- img->orientation = ORIENTATION_TOPLEFT;
- /* fall thru... */
- case ORIENTATION_TOPLEFT:
- y = h-1;
- break;
- }
- return (y);
- }
-
- /*
- * Get an tile-organized image that has
- * PlanarConfiguration contiguous if SamplesPerPixel > 1
- * or
- * SamplesPerPixel == 1
- */
- static int
- gtTileContig(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h)
- {
- TIFF* tif = img->tif;
- tileContigRoutine put = img->put.contig;
- uint16 orientation;
- uint32 col, row, y;
- uint32 tw, th;
- u_char* buf;
- int32 fromskew, toskew;
- uint32 nrow;
-
- buf = (u_char*) _TIFFmalloc(tif, TIFFTileSize(tif));
- if (buf == 0) {
- TIFFError(TIFFFileName(tif), "No space for tile buffer");
- return (0);
- }
- TIFFGetField(tif, TIFFTAG_TILEWIDTH, &tw);
- TIFFGetField(tif, TIFFTAG_TILELENGTH, &th);
- y = setorientation(img, h);
- orientation = img->orientation;
- toskew = -(int32) (orientation == ORIENTATION_TOPLEFT ? tw+w : tw-w);
- for (row = 0; row < h; row += th) {
- nrow = (row + th > h ? h - row : th);
- for (col = 0; col < w; col += tw) {
- if (TIFFReadTile(tif, buf, col+img->col_offset,
- row+img->row_offset, 0, 0) < 0 && img->stoponerr)
- break;
- if (col + tw > w) {
- /*
- * Tile is clipped horizontally. Calculate
- * visible portion and skewing factors.
- */
- uint32 npix = w - col;
- fromskew = tw - npix;
- (*put)(img, raster+y*w+col, col, y,
- npix, nrow, fromskew, toskew + fromskew, buf);
- } else {
- (*put)(img, raster+y*w+col, col, y, tw, nrow, 0, toskew, buf);
- }
- }
- y += (orientation == ORIENTATION_TOPLEFT ?
- -(int32) nrow : (int32) nrow);
- }
- _TIFFfree(tif, buf);
- return (1);
- }
-
- /*
- * Get an tile-organized image that has
- * SamplesPerPixel > 1
- * PlanarConfiguration separated
- * We assume that all such images are RGB.
- */
- static int
- gtTileSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h)
- {
- TIFF* tif = img->tif;
- tileSeparateRoutine put = img->put.separate;
- uint16 orientation;
- uint32 col, row, y;
- uint32 tw, th;
- u_char* buf;
- u_char* r;
- u_char* g;
- u_char* b;
- u_char* a;
- tsize_t tilesize;
- int32 fromskew, toskew;
- int alpha = img->alpha;
- uint32 nrow;
-
- tilesize = TIFFTileSize(tif);
- buf = (u_char*) _TIFFmalloc(tif, 4*tilesize);
- if (buf == 0) {
- TIFFError(TIFFFileName(tif), "No space for tile buffer");
- return (0);
- }
- r = buf;
- g = r + tilesize;
- b = g + tilesize;
- a = b + tilesize;
- if (!alpha)
- memset(a, 0xff, tilesize);
- TIFFGetField(tif, TIFFTAG_TILEWIDTH, &tw);
- TIFFGetField(tif, TIFFTAG_TILELENGTH, &th);
- y = setorientation(img, h);
- orientation = img->orientation;
- toskew = -(int32) (orientation == ORIENTATION_TOPLEFT ? tw+w : tw-w);
- for (row = 0; row < h; row += th) {
- nrow = (row + th > h ? h - row : th);
- for (col = 0; col < w; col += tw) {
- if (TIFFReadTile(tif, r, col+img->col_offset,
- row+img->row_offset,0,0) < 0 && img->stoponerr)
- break;
- if (TIFFReadTile(tif, g, col+img->col_offset,
- row+img->row_offset,0,1) < 0 && img->stoponerr)
- break;
- if (TIFFReadTile(tif, b, col+img->col_offset,
- row+img->row_offset,0,2) < 0 && img->stoponerr)
- break;
- if (alpha && TIFFReadTile(tif,a,col+img->col_offset,
- row+img->row_offset,0,3) < 0 && img->stoponerr)
- break;
- if (col + tw > w) {
- /*
- * Tile is clipped horizontally. Calculate
- * visible portion and skewing factors.
- */
- uint32 npix = w - col;
- fromskew = tw - npix;
- (*put)(img, raster+y*w+col, col, y,
- npix, nrow, fromskew, toskew + fromskew, r, g, b, a);
- } else {
- (*put)(img, raster+y*w+col, col, y,
- tw, nrow, 0, toskew, r, g, b, a);
- }
- }
- y += (orientation == ORIENTATION_TOPLEFT ?
- -(int32) nrow : (int32) nrow);
- }
- _TIFFfree(tif, buf);
- return (1);
- }
-
- /*
- * Get a strip-organized image that has
- * PlanarConfiguration contiguous if SamplesPerPixel > 1
- * or
- * SamplesPerPixel == 1
- */
- static int
- gtStripContig(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h)
- {
- TIFF* tif = img->tif;
- tileContigRoutine put = img->put.contig;
- uint16 orientation;
- uint32 row, y, nrow;
- u_char* buf;
- uint32 rowsperstrip;
- uint32 imagewidth = img->width;
- tsize_t scanline;
- int32 fromskew, toskew;
-
- buf = (u_char*) _TIFFmalloc(tif, TIFFStripSize(tif));
- if (buf == 0) {
- TIFFError(TIFFFileName(tif), "No space for strip buffer");
- return (0);
- }
- y = setorientation(img, h);
- orientation = img->orientation;
- toskew = -(int32) (orientation == ORIENTATION_TOPLEFT ? w+w : w-w);
- TIFFGetFieldDefaulted(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip);
- scanline = TIFFScanlineSize(tif);
- fromskew = (w < imagewidth ? imagewidth - w : 0);
- for (row = 0; row < h; row += rowsperstrip) {
- nrow = (row + rowsperstrip > h ? h - row : rowsperstrip);
- if (TIFFReadEncodedStrip(tif,
- TIFFComputeStrip(tif,row+img->row_offset, 0),
- buf, nrow*scanline) < 0
- && img->stoponerr)
- break;
- (*put)(img, raster+y*w, 0, y, w, nrow, fromskew, toskew, buf);
- y += (orientation == ORIENTATION_TOPLEFT ?
- -(int32) nrow : (int32) nrow);
- }
- _TIFFfree(tif, buf);
- return (1);
- }
-
- /*
- * Get a strip-organized image with
- * SamplesPerPixel > 1
- * PlanarConfiguration separated
- * We assume that all such images are RGB.
- */
- static int
- gtStripSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h)
- {
- TIFF* tif = img->tif;
- tileSeparateRoutine put = img->put.separate;
- uint16 orientation;
- u_char *buf;
- u_char *r, *g, *b, *a;
- uint32 row, y, nrow;
- tsize_t scanline;
- uint32 rowsperstrip, offset_row;
- uint32 imagewidth = img->width;
- tsize_t stripsize;
- int32 fromskew, toskew;
- int alpha = img->alpha;
-
- stripsize = TIFFStripSize(tif);
- r = buf = (u_char *)_TIFFmalloc(tif, 4*stripsize);
- if (buf == 0) {
- TIFFError(TIFFFileName(tif), "No space for tile buffer");
- return (0);
- }
- g = r + stripsize;
- b = g + stripsize;
- a = b + stripsize;
- if (!alpha)
- memset(a, 0xff, stripsize);
- y = setorientation(img, h);
- orientation = img->orientation;
- toskew = -(int32) (orientation == ORIENTATION_TOPLEFT ? w+w : w-w);
- TIFFGetFieldDefaulted(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip);
- scanline = TIFFScanlineSize(tif);
- fromskew = (w < imagewidth ? imagewidth - w : 0);
- for (row = 0; row < h; row += rowsperstrip) {
- nrow = (row + rowsperstrip > h ? h - row : rowsperstrip);
- offset_row = row + img->row_offset;
- if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, offset_row, 0),
- r, nrow*scanline) < 0 && img->stoponerr)
- break;
- if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, offset_row, 1),
- g, nrow*scanline) < 0 && img->stoponerr)
- break;
- if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, offset_row, 2),
- b, nrow*scanline) < 0 && img->stoponerr)
- break;
- if (alpha &&
- (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, offset_row, 3),
- a, nrow*scanline) < 0 && img->stoponerr))
- break;
- (*put)(img, raster+y*w, 0, y, w, nrow, fromskew, toskew, r, g, b, a);
- y += (orientation == ORIENTATION_TOPLEFT ?
- -(int32) nrow : (int32) nrow);
- }
- _TIFFfree(tif, buf);
- return (1);
- }
-
- /*
- * The following routines move decoded data returned
- * from the TIFF library into rasters filled with packed
- * ABGR pixels (i.e. suitable for passing to lrecwrite.)
- *
- * The routines have been created according to the most
- * important cases and optimized. pickTileContigCase and
- * pickTileSeparateCase analyze the parameters and select
- * the appropriate "put" routine to use.
- */
- #define REPEAT8(op) REPEAT4(op); REPEAT4(op)
- #define REPEAT4(op) REPEAT2(op); REPEAT2(op)
- #define REPEAT2(op) op; op
- #define CASE8(x,op) \
- switch (x) { \
- case 7: op; case 6: op; case 5: op; \
- case 4: op; case 3: op; case 2: op; \
- case 1: op; \
- }
- #define CASE4(x,op) switch (x) { case 3: op; case 2: op; case 1: op; }
- #define NOP
-
- #define UNROLL8(w, op1, op2) { \
- uint32 _x; \
- for (_x = w; _x >= 8; _x -= 8) { \
- op1; \
- REPEAT8(op2); \
- } \
- if (_x > 0) { \
- op1; \
- CASE8(_x,op2); \
- } \
- }
- #define UNROLL4(w, op1, op2) { \
- uint32 _x; \
- for (_x = w; _x >= 4; _x -= 4) { \
- op1; \
- REPEAT4(op2); \
- } \
- if (_x > 0) { \
- op1; \
- CASE4(_x,op2); \
- } \
- }
- #define UNROLL2(w, op1, op2) { \
- uint32 _x; \
- for (_x = w; _x >= 2; _x -= 2) { \
- op1; \
- REPEAT2(op2); \
- } \
- if (_x) { \
- op1; \
- op2; \
- } \
- }
-
- #define SKEW(r,g,b,skew) { r += skew; g += skew; b += skew; }
- #define SKEW4(r,g,b,a,skew) { r += skew; g += skew; b += skew; a+= skew; }
-
- #define A1 ((uint32)(0xffL<<24))
- #define PACK(r,g,b) \
- ((uint32)(r)|((uint32)(g)<<8)|((uint32)(b)<<16)|A1)
- #define PACK4(r,g,b,a) \
- ((uint32)(r)|((uint32)(g)<<8)|((uint32)(b)<<16)|((uint32)(a)<<24))
- #define W2B(v) (((v)>>8)&0xff)
- #define PACKW(r,g,b) \
- ((uint32)W2B(r)|((uint32)W2B(g)<<8)|((uint32)W2B(b)<<16)|A1)
- #define PACKW4(r,g,b,a) \
- ((uint32)W2B(r)|((uint32)W2B(g)<<8)|((uint32)W2B(b)<<16)|((uint32)W2B(a)<<24))
-
- #define DECLAREContigPutFunc(name) \
- static void name(\
- TIFFRGBAImage* img, \
- uint32* cp, \
- uint32 x, uint32 y, \
- uint32 w, uint32 h, \
- int32 fromskew, int32 toskew, \
- u_char* pp \
- )
-
- /*
- * 8-bit palette => colormap/RGB
- */
- DECLAREContigPutFunc(put8bitcmaptile)
- {
- uint32** PALmap = img->PALmap;
-
- (void) x; (void) y;
- while (h-- > 0) {
- UNROLL8(w, NOP, *cp++ = PALmap[*pp++][0]);
- cp += toskew;
- pp += fromskew;
- }
- }
-
- /*
- * 4-bit palette => colormap/RGB
- */
- DECLAREContigPutFunc(put4bitcmaptile)
- {
- uint32** PALmap = img->PALmap;
-
- (void) x; (void) y;
- fromskew /= 2;
- while (h-- > 0) {
- uint32* bw;
- UNROLL2(w, bw = PALmap[*pp++], *cp++ = *bw++);
- cp += toskew;
- pp += fromskew;
- }
- }
-
- /*
- * 2-bit palette => colormap/RGB
- */
- DECLAREContigPutFunc(put2bitcmaptile)
- {
- uint32** PALmap = img->PALmap;
-
- (void) x; (void) y;
- fromskew /= 4;
- while (h-- > 0) {
- uint32* bw;
- UNROLL4(w, bw = PALmap[*pp++], *cp++ = *bw++);
- cp += toskew;
- pp += fromskew;
- }
- }
-
- /*
- * 1-bit palette => colormap/RGB
- */
- DECLAREContigPutFunc(put1bitcmaptile)
- {
- uint32** PALmap = img->PALmap;
-
- (void) x; (void) y;
- fromskew /= 8;
- while (h-- > 0) {
- uint32* bw;
- UNROLL8(w, bw = PALmap[*pp++], *cp++ = *bw++);
- cp += toskew;
- pp += fromskew;
- }
- }
-
- /*
- * 8-bit greyscale => colormap/RGB
- */
- DECLAREContigPutFunc(putgreytile)
- {
- uint32** BWmap = img->BWmap;
-
- (void) y;
- while (h-- > 0) {
- for (x = w; x-- > 0;)
- *cp++ = BWmap[*pp++][0];
- cp += toskew;
- pp += fromskew;
- }
- }
-
- /*
- * 1-bit bilevel => colormap/RGB
- */
- DECLAREContigPutFunc(put1bitbwtile)
- {
- uint32** BWmap = img->BWmap;
-
- (void) x; (void) y;
- fromskew /= 8;
- while (h-- > 0) {
- uint32* bw;
- UNROLL8(w, bw = BWmap[*pp++], *cp++ = *bw++);
- cp += toskew;
- pp += fromskew;
- }
- }
-
- /*
- * 2-bit greyscale => colormap/RGB
- */
- DECLAREContigPutFunc(put2bitbwtile)
- {
- uint32** BWmap = img->BWmap;
-
- (void) x; (void) y;
- fromskew /= 4;
- while (h-- > 0) {
- uint32* bw;
- UNROLL4(w, bw = BWmap[*pp++], *cp++ = *bw++);
- cp += toskew;
- pp += fromskew;
- }
- }
-
- /*
- * 4-bit greyscale => colormap/RGB
- */
- DECLAREContigPutFunc(put4bitbwtile)
- {
- uint32** BWmap = img->BWmap;
-
- (void) x; (void) y;
- fromskew /= 2;
- while (h-- > 0) {
- uint32* bw;
- UNROLL2(w, bw = BWmap[*pp++], *cp++ = *bw++);
- cp += toskew;
- pp += fromskew;
- }
- }
-
- /*
- * 8-bit packed samples, no Map => RGB
- */
- DECLAREContigPutFunc(putRGBcontig8bittile)
- {
- int samplesperpixel = img->samplesperpixel;
-
- (void) x; (void) y;
- fromskew *= samplesperpixel;
- while (h-- > 0) {
- UNROLL8(w, NOP,
- *cp++ = PACK(pp[0], pp[1], pp[2]);
- pp += samplesperpixel);
- cp += toskew;
- pp += fromskew;
- }
- }
-
- /*
- * 8-bit packed samples, w/ Map => RGB
- */
- DECLAREContigPutFunc(putRGBcontig8bitMaptile)
- {
- TIFFRGBValue* Map = img->Map;
- int samplesperpixel = img->samplesperpixel;
-
- (void) y;
- fromskew *= samplesperpixel;
- while (h-- > 0) {
- for (x = w; x-- > 0;) {
- *cp++ = PACK(Map[pp[0]], Map[pp[1]], Map[pp[2]]);
- pp += samplesperpixel;
- }
- pp += fromskew;
- cp += toskew;
- }
- }
-
- /*
- * 8-bit packed samples => RGBA w/ associated alpha
- * (known to have Map == NULL)
- */
- DECLAREContigPutFunc(putRGBAAcontig8bittile)
- {
- int samplesperpixel = img->samplesperpixel;
-
- (void) x; (void) y;
- fromskew *= samplesperpixel;
- while (h-- > 0) {
- UNROLL8(w, NOP,
- *cp++ = PACK4(pp[0], pp[1], pp[2], pp[3]);
- pp += samplesperpixel);
- cp += toskew;
- pp += fromskew;
- }
- }
-
- /*
- * 8-bit packed samples => RGBA w/ unassociated alpha
- * (known to have Map == NULL)
- */
- DECLAREContigPutFunc(putRGBUAcontig8bittile)
- {
- int samplesperpixel = img->samplesperpixel;
-
- (void) y;
- fromskew *= samplesperpixel;
- while (h-- > 0) {
- uint32 r, g, b, a;
- for (x = w; x-- > 0;) {
- a = pp[3];
- r = (pp[0] * a) / 255;
- g = (pp[1] * a) / 255;
- b = (pp[2] * a) / 255;
- *cp++ = PACK4(r,g,b,a);
- pp += samplesperpixel;
- }
- cp += toskew;
- pp += fromskew;
- }
- }
-
- /*
- * 16-bit packed samples => RGB
- */
- DECLAREContigPutFunc(putRGBcontig16bittile)
- {
- int samplesperpixel = img->samplesperpixel;
- uint16 *wp = (uint16 *)pp;
-
- (void) y;
- fromskew *= samplesperpixel;
- while (h-- > 0) {
- for (x = w; x-- > 0;) {
- *cp++ = PACKW(wp[0], wp[1], wp[2]);
- wp += samplesperpixel;
- }
- cp += toskew;
- wp += fromskew;
- }
- }
-
- /*
- * 16-bit packed samples => RGBA w/ associated alpha
- * (known to have Map == NULL)
- */
- DECLAREContigPutFunc(putRGBAAcontig16bittile)
- {
- int samplesperpixel = img->samplesperpixel;
- uint16 *wp = (uint16 *)pp;
-
- (void) y;
- fromskew *= samplesperpixel;
- while (h-- > 0) {
- for (x = w; x-- > 0;) {
- *cp++ = PACKW4(wp[0], wp[1], wp[2], wp[3]);
- wp += samplesperpixel;
- }
- cp += toskew;
- wp += fromskew;
- }
- }
-
- /*
- * 16-bit packed samples => RGBA w/ unassociated alpha
- * (known to have Map == NULL)
- */
- DECLAREContigPutFunc(putRGBUAcontig16bittile)
- {
- int samplesperpixel = img->samplesperpixel;
- uint16 *wp = (uint16 *)pp;
-
- (void) y;
- fromskew *= samplesperpixel;
- while (h-- > 0) {
- uint32 r,g,b,a;
- /*
- * We shift alpha down four bits just in case unsigned
- * arithmetic doesn't handle the full range.
- * We still have plenty of accuracy, since the output is 8 bits.
- * So we have (r * 0xffff) * (a * 0xfff)) = r*a * (0xffff*0xfff)
- * Since we want r*a * 0xff for eight bit output,
- * we divide by (0xffff * 0xfff) / 0xff == 0x10eff.
- */
- for (x = w; x-- > 0;) {
- a = wp[3] >> 4;
- r = (wp[0] * a) / 0x10eff;
- g = (wp[1] * a) / 0x10eff;
- b = (wp[2] * a) / 0x10eff;
- *cp++ = PACK4(r,g,b,a);
- wp += samplesperpixel;
- }
- cp += toskew;
- wp += fromskew;
- }
- }
-
- /*
- * 8-bit packed CMYK samples w/o Map => RGB
- *
- * NB: The conversion of CMYK->RGB is *very* crude.
- */
- DECLAREContigPutFunc(putRGBcontig8bitCMYKtile)
- {
- int samplesperpixel = img->samplesperpixel;
- uint16 r, g, b, k;
-
- (void) x; (void) y;
- fromskew *= samplesperpixel;
- while (h-- > 0) {
- UNROLL8(w, NOP,
- k = 255 - pp[3];
- r = (k*(255-pp[0]))/255;
- g = (k*(255-pp[1]))/255;
- b = (k*(255-pp[2]))/255;
- *cp++ = PACK(r, g, b);
- pp += samplesperpixel);
- cp += toskew;
- pp += fromskew;
- }
- }
-
- /*
- * 8-bit packed CMYK samples w/Map => RGB
- *
- * NB: The conversion of CMYK->RGB is *very* crude.
- */
- DECLAREContigPutFunc(putRGBcontig8bitCMYKMaptile)
- {
- int samplesperpixel = img->samplesperpixel;
- TIFFRGBValue* Map = img->Map;
- uint16 r, g, b, k;
-
- (void) y;
- fromskew *= samplesperpixel;
- while (h-- > 0) {
- for (x = w; x-- > 0;) {
- k = 255 - pp[3];
- r = (k*(255-pp[0]))/255;
- g = (k*(255-pp[1]))/255;
- b = (k*(255-pp[2]))/255;
- *cp++ = PACK(Map[r], Map[g], Map[b]);
- pp += samplesperpixel;
- }
- pp += fromskew;
- cp += toskew;
- }
- }
-
- #define DECLARESepPutFunc(name) \
- static void name(\
- TIFFRGBAImage* img,\
- uint32* cp,\
- uint32 x, uint32 y, \
- uint32 w, uint32 h,\
- int32 fromskew, int32 toskew,\
- u_char* r, u_char* g, u_char* b, u_char* a\
- )
-
- /*
- * 8-bit unpacked samples => RGB
- */
- DECLARESepPutFunc(putRGBseparate8bittile)
- {
- (void) img; (void) x; (void) y; (void) a;
- while (h-- > 0) {
- UNROLL8(w, NOP, *cp++ = PACK(*r++, *g++, *b++));
- SKEW(r, g, b, fromskew);
- cp += toskew;
- }
- }
-
- /*
- * 8-bit unpacked samples => RGB
- */
- DECLARESepPutFunc(putRGBseparate8bitMaptile)
- {
- TIFFRGBValue* Map = img->Map;
-
- (void) y; (void) a;
- while (h-- > 0) {
- for (x = w; x > 0; x--)
- *cp++ = PACK(Map[*r++], Map[*g++], Map[*b++]);
- SKEW(r, g, b, fromskew);
- cp += toskew;
- }
- }
-
- /*
- * 8-bit unpacked samples => RGBA w/ associated alpha
- */
- DECLARESepPutFunc(putRGBAAseparate8bittile)
- {
- (void) img; (void) x; (void) y;
- while (h-- > 0) {
- UNROLL8(w, NOP, *cp++ = PACK4(*r++, *g++, *b++, *a++));
- SKEW4(r, g, b, a, fromskew);
- cp += toskew;
- }
- }
-
- /*
- * 8-bit unpacked samples => RGBA w/ unassociated alpha
- */
- DECLARESepPutFunc(putRGBUAseparate8bittile)
- {
- (void) img; (void) y;
- while (h-- > 0) {
- uint32 rv, gv, bv, av;
- for (x = w; x-- > 0;) {
- av = *a++;
- rv = (*r++ * av) / 255;
- gv = (*g++ * av) / 255;
- bv = (*b++ * av) / 255;
- *cp++ = PACK4(rv,gv,bv,av);
- }
- SKEW4(r, g, b, a, fromskew);
- cp += toskew;
- }
- }
-
- /*
- * 16-bit unpacked samples => RGB
- */
- DECLARESepPutFunc(putRGBseparate16bittile)
- {
- uint16 *wr = (uint16*) r;
- uint16 *wg = (uint16*) g;
- uint16 *wb = (uint16*) b;
-
- (void) img; (void) y; (void) a;
- while (h-- > 0) {
- for (x = 0; x < w; x++)
- *cp++ = PACKW(*wr++, *wg++, *wb++);
- SKEW(wr, wg, wb, fromskew);
- cp += toskew;
- }
- }
-
- /*
- * 16-bit unpacked samples => RGBA w/ associated alpha
- */
- DECLARESepPutFunc(putRGBAAseparate16bittile)
- {
- uint16 *wr = (uint16*) r;
- uint16 *wg = (uint16*) g;
- uint16 *wb = (uint16*) b;
- uint16 *wa = (uint16*) a;
-
- (void) img; (void) y;
- while (h-- > 0) {
- for (x = 0; x < w; x++)
- *cp++ = PACKW4(*wr++, *wg++, *wb++, *wa++);
- SKEW4(wr, wg, wb, wa, fromskew);
- cp += toskew;
- }
- }
-
- /*
- * 16-bit unpacked samples => RGBA w/ unassociated alpha
- */
- DECLARESepPutFunc(putRGBUAseparate16bittile)
- {
- uint16 *wr = (uint16*) r;
- uint16 *wg = (uint16*) g;
- uint16 *wb = (uint16*) b;
- uint16 *wa = (uint16*) a;
-
- (void) img; (void) y;
- while (h-- > 0) {
- uint32 r,g,b,a;
- /*
- * We shift alpha down four bits just in case unsigned
- * arithmetic doesn't handle the full range.
- * We still have plenty of accuracy, since the output is 8 bits.
- * So we have (r * 0xffff) * (a * 0xfff)) = r*a * (0xffff*0xfff)
- * Since we want r*a * 0xff for eight bit output,
- * we divide by (0xffff * 0xfff) / 0xff == 0x10eff.
- */
- for (x = w; x-- > 0;) {
- a = *wa++ >> 4;
- r = (*wr++ * a) / 0x10eff;
- g = (*wg++ * a) / 0x10eff;
- b = (*wb++ * a) / 0x10eff;
- *cp++ = PACK4(r,g,b,a);
- }
- SKEW4(wr, wg, wb, wa, fromskew);
- cp += toskew;
- }
- }
-
- /*
- * YCbCr -> RGB conversion and packing routines. The colorspace
- * conversion algorithm comes from the IJG v5a code; see below
- * for more information on how it works.
- */
-
- #define YCbCrtoRGB(dst, yc) { \
- int Y = (yc); \
- dst = PACK( \
- clamptab[Y+Crrtab[Cr]], \
- clamptab[Y + (int)((Cbgtab[Cb]+Crgtab[Cr])>>16)], \
- clamptab[Y+Cbbtab[Cb]]); \
- }
- #define YCbCrSetup \
- TIFFYCbCrToRGB* ycbcr = img->ycbcr; \
- int* Crrtab = ycbcr->Cr_r_tab; \
- int* Cbbtab = ycbcr->Cb_b_tab; \
- int32* Crgtab = ycbcr->Cr_g_tab; \
- int32* Cbgtab = ycbcr->Cb_g_tab; \
- TIFFRGBValue* clamptab = ycbcr->clamptab
-
- /*
- * 8-bit packed YCbCr samples => RGB
- * This function is generic for different sampling sizes,
- * and can handle blocks sizes that aren't multiples of the
- * sampling size. However, it is substantially less optimized
- * than the specific sampling cases. It is used as a fallback
- * for difficult blocks.
- */
- #ifdef notdef
- static void putcontig8bitYCbCrGenericTile(
- TIFFRGBAImage* img,
- uint32* cp,
- uint32 x, uint32 y,
- uint32 w, uint32 h,
- int32 fromskew, int32 toskew,
- u_char* pp,
- int h_group,
- int v_group )
-
- {
- YCbCrSetup;
-
- uint32* cp1 = cp+w+toskew;
- uint32* cp2 = cp1+w+toskew;
- uint32* cp3 = cp2+w+toskew;
- int32 incr = 3*w+4*toskew;
- int Cb, Cr;
- int group_size = v_group * h_group + 2;
-
- (void) y;
- fromskew = (fromskew * group_size) / h_group;
-
- for( yy = 0; yy < h; yy++ )
- {
- u_char *pp_line;
- int y_line_group = yy / v_group;
- int y_remainder = yy - y_line_group * v_group;
-
- pp_line = pp + v_line_group *
-
-
- for( xx = 0; xx < w; xx++ )
- {
- Cb = pp
- }
- }
- for (; h >= 4; h -= 4) {
- x = w>>2;
- do {
- Cb = pp[16];
- Cr = pp[17];
-
- YCbCrtoRGB(cp [0], pp[ 0]);
- YCbCrtoRGB(cp [1], pp[ 1]);
- YCbCrtoRGB(cp [2], pp[ 2]);
- YCbCrtoRGB(cp [3], pp[ 3]);
- YCbCrtoRGB(cp1[0], pp[ 4]);
- YCbCrtoRGB(cp1[1], pp[ 5]);
- YCbCrtoRGB(cp1[2], pp[ 6]);
- YCbCrtoRGB(cp1[3], pp[ 7]);
- YCbCrtoRGB(cp2[0], pp[ 8]);
- YCbCrtoRGB(cp2[1], pp[ 9]);
- YCbCrtoRGB(cp2[2], pp[10]);
- YCbCrtoRGB(cp2[3], pp[11]);
- YCbCrtoRGB(cp3[0], pp[12]);
- YCbCrtoRGB(cp3[1], pp[13]);
- YCbCrtoRGB(cp3[2], pp[14]);
- YCbCrtoRGB(cp3[3], pp[15]);
-
- cp += 4, cp1 += 4, cp2 += 4, cp3 += 4;
- pp += 18;
- } while (--x);
- cp += incr, cp1 += incr, cp2 += incr, cp3 += incr;
- pp += fromskew;
- }
- }
- #endif
-
- /*
- * 8-bit packed YCbCr samples w/ 4,4 subsampling => RGB
- */
- DECLAREContigPutFunc(putcontig8bitYCbCr44tile)
- {
- YCbCrSetup;
- uint32* cp1 = cp+w+toskew;
- uint32* cp2 = cp1+w+toskew;
- uint32* cp3 = cp2+w+toskew;
- int32 incr = 3*w+4*toskew;
-
- (void) y;
- /* adjust fromskew */
- fromskew = (fromskew * 18) / 4;
- if ((h & 3) == 0 && (w & 3) == 0) {
- for (; h >= 4; h -= 4) {
- x = w>>2;
- do {
- int Cb = pp[16];
- int Cr = pp[17];
-
- YCbCrtoRGB(cp [0], pp[ 0]);
- YCbCrtoRGB(cp [1], pp[ 1]);
- YCbCrtoRGB(cp [2], pp[ 2]);
- YCbCrtoRGB(cp [3], pp[ 3]);
- YCbCrtoRGB(cp1[0], pp[ 4]);
- YCbCrtoRGB(cp1[1], pp[ 5]);
- YCbCrtoRGB(cp1[2], pp[ 6]);
- YCbCrtoRGB(cp1[3], pp[ 7]);
- YCbCrtoRGB(cp2[0], pp[ 8]);
- YCbCrtoRGB(cp2[1], pp[ 9]);
- YCbCrtoRGB(cp2[2], pp[10]);
- YCbCrtoRGB(cp2[3], pp[11]);
- YCbCrtoRGB(cp3[0], pp[12]);
- YCbCrtoRGB(cp3[1], pp[13]);
- YCbCrtoRGB(cp3[2], pp[14]);
- YCbCrtoRGB(cp3[3], pp[15]);
-
- cp += 4, cp1 += 4, cp2 += 4, cp3 += 4;
- pp += 18;
- } while (--x);
- cp += incr, cp1 += incr, cp2 += incr, cp3 += incr;
- pp += fromskew;
- }
- } else {
- while (h > 0) {
- for (x = w; x > 0;) {
- int Cb = pp[16];
- int Cr = pp[17];
- switch (x) {
- default:
- switch (h) {
- default: YCbCrtoRGB(cp3[3], pp[15]); /* FALLTHROUGH */
- case 3: YCbCrtoRGB(cp2[3], pp[11]); /* FALLTHROUGH */
- case 2: YCbCrtoRGB(cp1[3], pp[ 7]); /* FALLTHROUGH */
- case 1: YCbCrtoRGB(cp [3], pp[ 3]); /* FALLTHROUGH */
- } /* FALLTHROUGH */
- case 3:
- switch (h) {
- default: YCbCrtoRGB(cp3[2], pp[14]); /* FALLTHROUGH */
- case 3: YCbCrtoRGB(cp2[2], pp[10]); /* FALLTHROUGH */
- case 2: YCbCrtoRGB(cp1[2], pp[ 6]); /* FALLTHROUGH */
- case 1: YCbCrtoRGB(cp [2], pp[ 2]); /* FALLTHROUGH */
- } /* FALLTHROUGH */
- case 2:
- switch (h) {
- default: YCbCrtoRGB(cp3[1], pp[13]); /* FALLTHROUGH */
- case 3: YCbCrtoRGB(cp2[1], pp[ 9]); /* FALLTHROUGH */
- case 2: YCbCrtoRGB(cp1[1], pp[ 5]); /* FALLTHROUGH */
- case 1: YCbCrtoRGB(cp [1], pp[ 1]); /* FALLTHROUGH */
- } /* FALLTHROUGH */
- case 1:
- switch (h) {
- default: YCbCrtoRGB(cp3[0], pp[12]); /* FALLTHROUGH */
- case 3: YCbCrtoRGB(cp2[0], pp[ 8]); /* FALLTHROUGH */
- case 2: YCbCrtoRGB(cp1[0], pp[ 4]); /* FALLTHROUGH */
- case 1: YCbCrtoRGB(cp [0], pp[ 0]); /* FALLTHROUGH */
- } /* FALLTHROUGH */
- }
- if (x < 4) {
- cp += x; cp1 += x; cp2 += x; cp3 += x;
- x = 0;
- }
- else {
- cp += 4; cp1 += 4; cp2 += 4; cp3 += 4;
- x -= 4;
- }
- pp += 18;
- }
- if (h <= 4)
- break;
- h -= 4;
- cp += incr, cp1 += incr, cp2 += incr, cp3 += incr;
- pp += fromskew;
- }
- }
- }
-
- /*
- * 8-bit packed YCbCr samples w/ 4,2 subsampling => RGB
- */
- DECLAREContigPutFunc(putcontig8bitYCbCr42tile)
- {
- YCbCrSetup;
- uint32* cp1 = cp+w+toskew;
- int32 incr = 2*toskew+w;
-
- (void) y;
- fromskew = (fromskew * 10) / 4;
- if ((h & 3) == 0 && (w & 1) == 0) {
- for (; h >= 2; h -= 2) {
- x = w>>2;
- do {
- int Cb = pp[8];
- int Cr = pp[9];
-
- YCbCrtoRGB(cp [0], pp[0]);
- YCbCrtoRGB(cp [1], pp[1]);
- YCbCrtoRGB(cp [2], pp[2]);
- YCbCrtoRGB(cp [3], pp[3]);
- YCbCrtoRGB(cp1[0], pp[4]);
- YCbCrtoRGB(cp1[1], pp[5]);
- YCbCrtoRGB(cp1[2], pp[6]);
- YCbCrtoRGB(cp1[3], pp[7]);
-
- cp += 4, cp1 += 4;
- pp += 10;
- } while (--x);
- cp += incr, cp1 += incr;
- pp += fromskew;
- }
- } else {
- while (h > 0) {
- for (x = w; x > 0;) {
- int Cb = pp[8];
- int Cr = pp[9];
- switch (x) {
- default:
- switch (h) {
- default: YCbCrtoRGB(cp1[3], pp[ 7]); /* FALLTHROUGH */
- case 1: YCbCrtoRGB(cp [3], pp[ 3]); /* FALLTHROUGH */
- } /* FALLTHROUGH */
- case 3:
- switch (h) {
- default: YCbCrtoRGB(cp1[2], pp[ 6]); /* FALLTHROUGH */
- case 1: YCbCrtoRGB(cp [2], pp[ 2]); /* FALLTHROUGH */
- } /* FALLTHROUGH */
- case 2:
- switch (h) {
- default: YCbCrtoRGB(cp1[1], pp[ 5]); /* FALLTHROUGH */
- case 1: YCbCrtoRGB(cp [1], pp[ 1]); /* FALLTHROUGH */
- } /* FALLTHROUGH */
- case 1:
- switch (h) {
- default: YCbCrtoRGB(cp1[0], pp[ 4]); /* FALLTHROUGH */
- case 1: YCbCrtoRGB(cp [0], pp[ 0]); /* FALLTHROUGH */
- } /* FALLTHROUGH */
- }
- if (x < 4) {
- cp += x; cp1 += x;
- x = 0;
- }
- else {
- cp += 4; cp1 += 4;
- x -= 4;
- }
- pp += 10;
- }
- if (h <= 2)
- break;
- h -= 2;
- cp += incr, cp1 += incr;
- pp += fromskew;
- }
- }
- }
-
- /*
- * 8-bit packed YCbCr samples w/ 4,1 subsampling => RGB
- */
- DECLAREContigPutFunc(putcontig8bitYCbCr41tile)
- {
- YCbCrSetup;
-
- (void) y;
- /* XXX adjust fromskew */
- do {
- x = w>>2;
- do {
- int Cb = pp[4];
- int Cr = pp[5];
-
- YCbCrtoRGB(cp [0], pp[0]);
- YCbCrtoRGB(cp [1], pp[1]);
- YCbCrtoRGB(cp [2], pp[2]);
- YCbCrtoRGB(cp [3], pp[3]);
-
- cp += 4;
- pp += 6;
- } while (--x);
-
- if( (w&3) != 0 )
- {
- int Cb = pp[4];
- int Cr = pp[5];
-
- switch( (w&3) ) {
- case 3: YCbCrtoRGB(cp [2], pp[2]);
- case 2: YCbCrtoRGB(cp [1], pp[1]);
- case 1: YCbCrtoRGB(cp [0], pp[0]);
- case 0: break;
- }
-
- cp += (w&3);
- pp += 6;
- }
-
- cp += toskew;
- pp += fromskew;
- } while (--h);
-
- }
-
- /*
- * 8-bit packed YCbCr samples w/ 2,2 subsampling => RGB
- */
- DECLAREContigPutFunc(putcontig8bitYCbCr22tile)
- {
- YCbCrSetup;
- uint32* cp1 = cp+w+toskew;
- int32 incr = 2*toskew+w;
-
- (void) y;
- fromskew = (fromskew * 6) / 2;
- if ((h & 1) == 0 && (w & 1) == 0) {
- for (; h >= 2; h -= 2) {
- x = w>>1;
- do {
- int Cb = pp[4];
- int Cr = pp[5];
-
- YCbCrtoRGB(cp [0], pp[0]);
- YCbCrtoRGB(cp [1], pp[1]);
- YCbCrtoRGB(cp1[0], pp[2]);
- YCbCrtoRGB(cp1[1], pp[3]);
-
- cp += 2, cp1 += 2;
- pp += 6;
- } while (--x);
- cp += incr, cp1 += incr;
- pp += fromskew;
- }
- } else {
- while (h > 0) {
- for (x = w; x > 0;) {
- int Cb = pp[4];
- int Cr = pp[5];
- switch (x) {
- default:
- switch (h) {
- default: YCbCrtoRGB(cp1[1], pp[ 3]); /* FALLTHROUGH */
- case 1: YCbCrtoRGB(cp [1], pp[ 1]); /* FALLTHROUGH */
- } /* FALLTHROUGH */
- case 1:
- switch (h) {
- default: YCbCrtoRGB(cp1[0], pp[ 2]); /* FALLTHROUGH */
- case 1: YCbCrtoRGB(cp [0], pp[ 0]); /* FALLTHROUGH */
- } /* FALLTHROUGH */
- }
- if (x < 2) {
- cp += x; cp1 += x;
- x = 0;
- }
- else {
- cp += 2; cp1 += 2;
- x -= 2;
- }
- pp += 6;
- }
- if (h <= 2)
- break;
- h -= 2;
- cp += incr, cp1 += incr;
- pp += fromskew;
- }
- }
- }
-
- /*
- * 8-bit packed YCbCr samples w/ 2,1 subsampling => RGB
- */
- DECLAREContigPutFunc(putcontig8bitYCbCr21tile)
- {
- YCbCrSetup;
-
- (void) y;
- fromskew = (fromskew * 4) / 2;
- do {
- x = w>>1;
- do {
- int Cb = pp[2];
- int Cr = pp[3];
-
- YCbCrtoRGB(cp[0], pp[0]);
- YCbCrtoRGB(cp[1], pp[1]);
-
- cp += 2;
- pp += 4;
- } while (--x);
-
- if( (w&1) != 0 )
- {
- int Cb = pp[2];
- int Cr = pp[3];
-
- YCbCrtoRGB(cp [0], pp[0]);
-
- cp += 1;
- pp += 4;
- }
-
- cp += toskew;
- pp += fromskew;
- } while (--h);
- }
-
- /*
- * 8-bit packed YCbCr samples w/ no subsampling => RGB
- */
- DECLAREContigPutFunc(putcontig8bitYCbCr11tile)
- {
- YCbCrSetup;
-
- (void) y;
- fromskew *= 3;
- do {
- x = w; /* was x = w>>1; patched 2000/09/25 warmerda@home.com */
- do {
- int Cb = pp[1];
- int Cr = pp[2];
-
- YCbCrtoRGB(*cp++, pp[0]);
-
- pp += 3;
- } while (--x);
- cp += toskew;
- pp += fromskew;
- } while (--h);
- }
- #undef YCbCrSetup
- #undef YCbCrtoRGB
-
- #define LumaRed coeffs[0]
- #define LumaGreen coeffs[1]
- #define LumaBlue coeffs[2]
- #define SHIFT 16
- #define FIX(x) ((int32)((x) * (1L<<SHIFT) + 0.5))
- #define ONE_HALF ((int32)(1<<(SHIFT-1)))
-
- /*
- * Initialize the YCbCr->RGB conversion tables. The conversion
- * is done according to the 6.0 spec:
- *
- * R = Y + Cr*(2 - 2*LumaRed)
- * B = Y + Cb*(2 - 2*LumaBlue)
- * G = Y
- * - LumaBlue*Cb*(2-2*LumaBlue)/LumaGreen
- * - LumaRed*Cr*(2-2*LumaRed)/LumaGreen
- *
- * To avoid floating point arithmetic the fractional constants that
- * come out of the equations are represented as fixed point values
- * in the range 0...2^16. We also eliminate multiplications by
- * pre-calculating possible values indexed by Cb and Cr (this code
- * assumes conversion is being done for 8-bit samples).
- */
- static void
- TIFFYCbCrToRGBInit(TIFFYCbCrToRGB* ycbcr, TIFF* tif)
- {
- TIFFRGBValue* clamptab;
- float* coeffs;
- int i;
-
- clamptab = (TIFFRGBValue*)(
- (tidata_t) ycbcr+TIFFroundup(sizeof (TIFFYCbCrToRGB), sizeof (long)));
- _TIFFmemset(clamptab, 0, 256); /* v < 0 => 0 */
- ycbcr->clamptab = (clamptab += 256);
- for (i = 0; i < 256; i++)
- clamptab[i] = i;
- _TIFFmemset(clamptab+256, 255, 2*256); /* v > 255 => 255 */
- TIFFGetFieldDefaulted(tif, TIFFTAG_YCBCRCOEFFICIENTS, &coeffs);
- _TIFFmemcpy(ycbcr->coeffs, coeffs, 3*sizeof (float));
- { float f1 = 2-2*LumaRed; int32 D1 = FIX(f1);
- float f2 = LumaRed*f1/LumaGreen; int32 D2 = -FIX(f2);
- float f3 = 2-2*LumaBlue; int32 D3 = FIX(f3);
- float f4 = LumaBlue*f3/LumaGreen; int32 D4 = -FIX(f4);
- int x;
-
- ycbcr->Cr_r_tab = (int*) (clamptab + 3*256);
- ycbcr->Cb_b_tab = ycbcr->Cr_r_tab + 256;
- ycbcr->Cr_g_tab = (int32*) (ycbcr->Cb_b_tab + 256);
- ycbcr->Cb_g_tab = ycbcr->Cr_g_tab + 256;
- /*
- * i is the actual input pixel value in the range 0..255
- * Cb and Cr values are in the range -128..127 (actually
- * they are in a range defined by the ReferenceBlackWhite
- * tag) so there is some range shifting to do here when
- * constructing tables indexed by the raw pixel data.
- *
- * XXX handle ReferenceBlackWhite correctly to calculate
- * Cb/Cr values to use in constructing the tables.
- */
- for (i = 0, x = -128; i < 256; i++, x++) {
- ycbcr->Cr_r_tab[i] = (int)((D1*x + ONE_HALF)>>SHIFT);
- ycbcr->Cb_b_tab[i] = (int)((D3*x + ONE_HALF)>>SHIFT);
- ycbcr->Cr_g_tab[i] = D2*x;
- ycbcr->Cb_g_tab[i] = D4*x + ONE_HALF;
- }
- }
- }
- #undef SHIFT
- #undef ONE_HALF
- #undef FIX
- #undef LumaBlue
- #undef LumaGreen
- #undef LumaRed
-
- static tileContigRoutine
- initYCbCrConversion(TIFFRGBAImage* img)
- {
- uint16 hs, vs;
- TIFF* tif = img->tif;
-
- if (img->ycbcr == NULL) {
- img->ycbcr = (TIFFYCbCrToRGB*) _TIFFmalloc(tif,
- TIFFroundup(sizeof (TIFFYCbCrToRGB), sizeof (long))
- + 4*256*sizeof (TIFFRGBValue)
- + 2*256*sizeof (int)
- + 2*256*sizeof (int32)
- );
- if (img->ycbcr == NULL) {
- TIFFError(TIFFFileName(img->tif),
- "No space for YCbCr->RGB conversion state");
- return (NULL);
- }
- TIFFYCbCrToRGBInit(img->ycbcr, img->tif);
- } else {
- float* coeffs;
-
- TIFFGetFieldDefaulted(img->tif, TIFFTAG_YCBCRCOEFFICIENTS, &coeffs);
- if (_TIFFmemcmp(coeffs, img->ycbcr->coeffs, 3*sizeof (float)) != 0)
- TIFFYCbCrToRGBInit(img->ycbcr, img->tif);
- }
- /*
- * The 6.0 spec says that subsampling must be
- * one of 1, 2, or 4, and that vertical subsampling
- * must always be <= horizontal subsampling; so
- * there are only a few possibilities and we just
- * enumerate the cases.
- */
- TIFFGetFieldDefaulted(img->tif, TIFFTAG_YCBCRSUBSAMPLING, &hs, &vs);
- switch ((hs<<4)|vs) {
- case 0x44: return ((tileContigRoutine) putcontig8bitYCbCr44tile);
- case 0x42: return ((tileContigRoutine) putcontig8bitYCbCr42tile);
- case 0x41: return ((tileContigRoutine) putcontig8bitYCbCr41tile);
- case 0x22: return ((tileContigRoutine) putcontig8bitYCbCr22tile);
- case 0x21: return ((tileContigRoutine) putcontig8bitYCbCr21tile);
- case 0x11: return ((tileContigRoutine) putcontig8bitYCbCr11tile);
- }
- return (NULL);
- }
-
- /*
- * Greyscale images with less than 8 bits/sample are handled
- * with a table to avoid lots of shifts and masks. The table
- * is setup so that put*bwtile (below) can retrieve 8/bitspersample
- * pixel values simply by indexing into the table with one
- * number.
- */
- static int
- makebwmap(TIFFRGBAImage* img)
- {
- TIFFRGBValue* Map = img->Map;
- int bitspersample = img->bitspersample;
- int nsamples = 8 / bitspersample;
- int i;
- uint32* p;
- TIFF* tif = img->tif;
-
- img->BWmap = (uint32**) _TIFFmalloc(tif,
- 256*sizeof (uint32 *)+(256*nsamples*sizeof(uint32)));
- if (img->BWmap == NULL) {
- TIFFError(TIFFFileName(img->tif), "No space for B&W mapping table");
- return (0);
- }
- p = (uint32*)(img->BWmap + 256);
- for (i = 0; i < 256; i++) {
- TIFFRGBValue c;
- img->BWmap[i] = p;
- switch (bitspersample) {
- #define GREY(x) c = Map[x]; *p++ = PACK(c,c,c);
- case 1:
- GREY(i>>7);
- GREY((i>>6)&1);
- GREY((i>>5)&1);
- GREY((i>>4)&1);
- GREY((i>>3)&1);
- GREY((i>>2)&1);
- GREY((i>>1)&1);
- GREY(i&1);
- break;
- case 2:
- GREY(i>>6);
- GREY((i>>4)&3);
- GREY((i>>2)&3);
- GREY(i&3);
- break;
- case 4:
- GREY(i>>4);
- GREY(i&0xf);
- break;
- case 8:
- GREY(i);
- break;
- }
- #undef GREY
- }
- return (1);
- }
-
- /*
- * Construct a mapping table to convert from the range
- * of the data samples to [0,255] --for display. This
- * process also handles inverting B&W images when needed.
- */
- static int
- setupMap(TIFFRGBAImage* img)
- {
- int32 x, range;
- TIFF* tif = img->tif;
-
- range = (int32)((1L<<img->bitspersample)-1);
- img->Map = (TIFFRGBValue*)
- _TIFFmalloc(tif, (range+1) * sizeof (TIFFRGBValue));
- if (img->Map == NULL) {
- TIFFError(TIFFFileName(img->tif),
- "No space for photometric conversion table");
- return (0);
- }
- if (img->photometric == PHOTOMETRIC_MINISWHITE) {
- for (x = 0; x <= range; x++)
- img->Map[x] = (TIFFRGBValue) (((range - x) * 255) / range);
- } else {
- for (x = 0; x <= range; x++)
- img->Map[x] = (TIFFRGBValue) ((x * 255) / range);
- }
- if (img->bitspersample <= 8 &&
- (img->photometric == PHOTOMETRIC_MINISBLACK ||
- img->photometric == PHOTOMETRIC_MINISWHITE)) {
- /*
- * Use photometric mapping table to construct
- * unpacking tables for samples <= 8 bits.
- */
- if (!makebwmap(img))
- return (0);
- /* no longer need Map, free it */
- _TIFFfree(tif, img->Map), img->Map = NULL;
- }
- return (1);
- }
-
- static int
- checkcmap(TIFFRGBAImage* img)
- {
- uint16* r = img->redcmap;
- uint16* g = img->greencmap;
- uint16* b = img->bluecmap;
- long n = 1L<<img->bitspersample;
-
- while (n-- > 0)
- if (*r++ >= 256 || *g++ >= 256 || *b++ >= 256)
- return (16);
- return (8);
- }
-
- static void
- cvtcmap(TIFFRGBAImage* img)
- {
- uint16* r = img->redcmap;
- uint16* g = img->greencmap;
- uint16* b = img->bluecmap;
- long i;
-
- for (i = (1L<<img->bitspersample)-1; i >= 0; i--) {
- #define CVT(x) ((uint16)((x)>>8))
- r[i] = CVT(r[i]);
- g[i] = CVT(g[i]);
- b[i] = CVT(b[i]);
- #undef CVT
- }
- }
-
- /*
- * Palette images with <= 8 bits/sample are handled
- * with a table to avoid lots of shifts and masks. The table
- * is setup so that put*cmaptile (below) can retrieve 8/bitspersample
- * pixel values simply by indexing into the table with one
- * number.
- */
- static int
- makecmap(TIFFRGBAImage* img)
- {
- int bitspersample = img->bitspersample;
- int nsamples = 8 / bitspersample;
- uint16* r = img->redcmap;
- uint16* g = img->greencmap;
- uint16* b = img->bluecmap;
- uint32 *p;
- int i;
- TIFF* tif = img->tif;
-
- img->PALmap = (uint32**) _TIFFmalloc(tif,
- 256*sizeof (uint32 *)+(256*nsamples*sizeof(uint32)));
- if (img->PALmap == NULL) {
- TIFFError(TIFFFileName(img->tif), "No space for Palette mapping table");
- return (0);
- }
- p = (uint32*)(img->PALmap + 256);
- for (i = 0; i < 256; i++) {
- TIFFRGBValue c;
- img->PALmap[i] = p;
- #define CMAP(x) c = x; *p++ = PACK(r[c]&0xff, g[c]&0xff, b[c]&0xff);
- switch (bitspersample) {
- case 1:
- CMAP(i>>7);
- CMAP((i>>6)&1);
- CMAP((i>>5)&1);
- CMAP((i>>4)&1);
- CMAP((i>>3)&1);
- CMAP((i>>2)&1);
- CMAP((i>>1)&1);
- CMAP(i&1);
- break;
- case 2:
- CMAP(i>>6);
- CMAP((i>>4)&3);
- CMAP((i>>2)&3);
- CMAP(i&3);
- break;
- case 4:
- CMAP(i>>4);
- CMAP(i&0xf);
- break;
- case 8:
- CMAP(i);
- break;
- }
- #undef CMAP
- }
- return (1);
- }
-
- /*
- * Construct any mapping table used
- * by the associated put routine.
- */
- static int
- buildMap(TIFFRGBAImage* img)
- {
- switch (img->photometric) {
- case PHOTOMETRIC_RGB:
- case PHOTOMETRIC_YCBCR:
- case PHOTOMETRIC_SEPARATED:
- if (img->bitspersample == 8)
- break;
- /* fall thru... */
- case PHOTOMETRIC_MINISBLACK:
- case PHOTOMETRIC_MINISWHITE:
- if (!setupMap(img))
- return (0);
- break;
- case PHOTOMETRIC_PALETTE:
- /*
- * Convert 16-bit colormap to 8-bit (unless it looks
- * like an old-style 8-bit colormap).
- */
- if (checkcmap(img) == 16)
- cvtcmap(img);
- else
- TIFFWarning(TIFFFileName(img->tif), "Assuming 8-bit colormap");
- /*
- * Use mapping table and colormap to construct
- * unpacking tables for samples < 8 bits.
- */
- if (img->bitspersample <= 8 && !makecmap(img))
- return (0);
- break;
- }
- return (1);
- }
-
- /*
- * Select the appropriate conversion routine for packed data.
- */
- static int
- pickTileContigCase(TIFFRGBAImage* img)
- {
- tileContigRoutine put = 0;
-
- if (buildMap(img)) {
- switch (img->photometric) {
- case PHOTOMETRIC_RGB:
- switch (img->bitspersample) {
- case 8:
- if (!img->Map) {
- if (img->alpha == EXTRASAMPLE_ASSOCALPHA)
- put = putRGBAAcontig8bittile;
- else if (img->alpha == EXTRASAMPLE_UNASSALPHA)
- put = putRGBUAcontig8bittile;
- else
- put = putRGBcontig8bittile;
- } else
- put = putRGBcontig8bitMaptile;
- break;
- case 16:
- put = putRGBcontig16bittile;
- if (!img->Map) {
- if (img->alpha == EXTRASAMPLE_ASSOCALPHA)
- put = putRGBAAcontig16bittile;
- else if (img->alpha == EXTRASAMPLE_UNASSALPHA)
- put = putRGBUAcontig16bittile;
- }
- break;
- }
- break;
- case PHOTOMETRIC_SEPARATED:
- if (img->bitspersample == 8) {
- if (!img->Map)
- put = putRGBcontig8bitCMYKtile;
- else
- put = putRGBcontig8bitCMYKMaptile;
- }
- break;
- case PHOTOMETRIC_PALETTE:
- switch (img->bitspersample) {
- case 8: put = put8bitcmaptile; break;
- case 4: put = put4bitcmaptile; break;
- case 2: put = put2bitcmaptile; break;
- case 1: put = put1bitcmaptile; break;
- }
- break;
- case PHOTOMETRIC_MINISWHITE:
- case PHOTOMETRIC_MINISBLACK:
- switch (img->bitspersample) {
- case 8: put = putgreytile; break;
- case 4: put = put4bitbwtile; break;
- case 2: put = put2bitbwtile; break;
- case 1: put = put1bitbwtile; break;
- }
- break;
- case PHOTOMETRIC_YCBCR:
- if (img->bitspersample == 8)
- put = initYCbCrConversion(img);
- break;
- }
- }
- return ((img->put.contig = put) != 0);
- }
-
- /*
- * Select the appropriate conversion routine for unpacked data.
- *
- * NB: we assume that unpacked single channel data is directed
- * to the "packed routines.
- */
- static int
- pickTileSeparateCase(TIFFRGBAImage* img)
- {
- tileSeparateRoutine put = 0;
-
- if (buildMap(img)) {
- switch (img->photometric) {
- case PHOTOMETRIC_RGB:
- switch (img->bitspersample) {
- case 8:
- if (!img->Map) {
- if (img->alpha == EXTRASAMPLE_ASSOCALPHA)
- put = putRGBAAseparate8bittile;
- else if (img->alpha == EXTRASAMPLE_UNASSALPHA)
- put = putRGBUAseparate8bittile;
- else
- put = putRGBseparate8bittile;
- } else
- put = putRGBseparate8bitMaptile;
- break;
- case 16:
- put = putRGBseparate16bittile;
- if (!img->Map) {
- if (img->alpha == EXTRASAMPLE_ASSOCALPHA)
- put = putRGBAAseparate16bittile;
- else if (img->alpha == EXTRASAMPLE_UNASSALPHA)
- put = putRGBUAseparate16bittile;
- }
- break;
- }
- break;
- }
- }
- return ((img->put.separate = put) != 0);
- }
-
- /*
- * Read a whole strip off data from the file, and convert to RGBA form.
- * If this is the last strip, then it will only contain the portion of
- * the strip that is actually within the image space. The result is
- * organized in bottom to top form.
- */
-
-
- int
- TIFFReadRGBAStrip(TIFF* tif, uint32 row, uint32 * raster )
-
- {
- char emsg[1024];
- TIFFRGBAImage img;
- int ok;
- uint32 rowsperstrip, rows_to_read;
-
- if( TIFFIsTiled( tif ) )
- {
- TIFFError(TIFFFileName(tif),
- "Can't use TIFFReadRGBAStrip() with tiled file.");
- return (0);
- }
-
- TIFFGetFieldDefaulted(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip);
- if( (row % rowsperstrip) != 0 )
- {
- TIFFError(TIFFFileName(tif),
- "Row passed to TIFFReadRGBAStrip() must be first in a strip.");
- return (0);
- }
-
- if (TIFFRGBAImageBegin(&img, tif, 0, emsg)) {
-
- img.row_offset = row;
- img.col_offset = 0;
-
- if( row + rowsperstrip > img.height )
- rows_to_read = img.height - row;
- else
- rows_to_read = rowsperstrip;
-
- ok = TIFFRGBAImageGet(&img, raster, img.width, rows_to_read );
-
- TIFFRGBAImageEnd(&img);
- } else {
- TIFFError(TIFFFileName(tif), emsg);
- ok = 0;
- }
-
- return (ok);
- }
-
- /*
- * Read a whole tile off data from the file, and convert to RGBA form.
- * The returned RGBA data is organized from bottom to top of tile,
- * and may include zeroed areas if the tile extends off the image.
- */
-
- int
- TIFFReadRGBATile(TIFF* tif, uint32 col, uint32 row, uint32 * raster)
-
- {
- char emsg[1024];
- TIFFRGBAImage img;
- int ok;
- uint32 tile_xsize, tile_ysize;
- uint32 read_xsize, read_ysize;
- uint32 i_row;
-
- /*
- * Verify that our request is legal - on a tile file, and on a
- * tile boundary.
- */
-
- if( !TIFFIsTiled( tif ) )
- {
- TIFFError(TIFFFileName(tif),
- "Can't use TIFFReadRGBATile() with stripped file.");
- return (0);
- }
-
- TIFFGetFieldDefaulted(tif, TIFFTAG_TILEWIDTH, &tile_xsize);
- TIFFGetFieldDefaulted(tif, TIFFTAG_TILELENGTH, &tile_ysize);
- if( (col % tile_xsize) != 0 || (row % tile_ysize) != 0 )
- {
- TIFFError(TIFFFileName(tif),
- "Row/col passed to TIFFReadRGBATile() must be top"
- "left corner of a tile.");
- return (0);
- }
-
- /*
- * Setup the RGBA reader.
- */
-
- if ( !TIFFRGBAImageBegin(&img, tif, 0, emsg)) {
- TIFFError(TIFFFileName(tif), emsg);
- return( 0 );
- }
-
- /*
- * The TIFFRGBAImageGet() function doesn't allow us to get off the
- * edge of the image, even to fill an otherwise valid tile. So we
- * figure out how much we can read, and fix up the tile buffer to
- * a full tile configuration afterwards.
- */
-
- if( row + tile_ysize > img.height )
- read_ysize = img.height - row;
- else
- read_ysize = tile_ysize;
-
- if( col + tile_xsize > img.width )
- read_xsize = img.width - col;
- else
- read_xsize = tile_xsize;
-
- /*
- * Read the chunk of imagery.
- */
-
- img.row_offset = row;
- img.col_offset = col;
-
- ok = TIFFRGBAImageGet(&img, raster, read_xsize, read_ysize );
-
- TIFFRGBAImageEnd(&img);
-
- /*
- * If our read was incomplete we will need to fix up the tile by
- * shifting the data around as if a full tile of data is being returned.
- *
- * This is all the more complicated because the image is organized in
- * bottom to top format.
- */
-
- if( read_xsize == tile_xsize && read_ysize == tile_ysize )
- return( ok );
-
- for( i_row = 0; i_row < read_ysize; i_row++ )
- {
- _TIFFmemcpy( raster + (tile_ysize - i_row - 1) * tile_xsize,
- raster + (read_ysize - i_row - 1) * read_xsize,
- read_xsize * sizeof(uint32) );
- _TIFFmemset( raster + (tile_ysize - i_row - 1) * tile_xsize+read_xsize,
- 0, sizeof(uint32) * (tile_xsize - read_xsize) );
- }
-
- for( i_row = read_ysize; i_row < tile_ysize; i_row++ )
- {
- _TIFFmemset( raster + (tile_ysize - i_row - 1) * tile_xsize,
- 0, sizeof(uint32) * tile_xsize );
- }
-
- return (ok);
- }
-