|
roentgen |
b75cab |
/* $Header: /cvs/maptools/cvsroot/libtiff/contrib/pds/tif_imageiter.c,v 1.4 2010-06-08 18:55:15 bfriesen Exp $ */
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
/*
|
|
roentgen |
b75cab |
* Copyright (c) 1991-1996 Sam Leffler
|
|
roentgen |
b75cab |
* Copyright (c) 1991-1996 Silicon Graphics, Inc.
|
|
roentgen |
b75cab |
*
|
|
roentgen |
b75cab |
* Permission to use, copy, modify, distribute, and sell this software and
|
|
roentgen |
b75cab |
* its documentation for any purpose is hereby granted without fee, provided
|
|
roentgen |
b75cab |
* that (i) the above copyright notices and this permission notice appear in
|
|
roentgen |
b75cab |
* all copies of the software and related documentation, and (ii) the names of
|
|
roentgen |
b75cab |
* Sam Leffler and Silicon Graphics may not be used in any advertising or
|
|
roentgen |
b75cab |
* publicity relating to the software without the specific, prior written
|
|
roentgen |
b75cab |
* permission of Sam Leffler and Silicon Graphics.
|
|
roentgen |
b75cab |
*
|
|
roentgen |
b75cab |
* THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
|
|
roentgen |
b75cab |
* EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
|
|
roentgen |
b75cab |
* WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
|
|
roentgen |
b75cab |
*
|
|
roentgen |
b75cab |
* IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
|
|
roentgen |
b75cab |
* ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
|
|
roentgen |
b75cab |
* OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
|
|
roentgen |
b75cab |
* WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
|
|
roentgen |
b75cab |
* LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
|
roentgen |
b75cab |
* OF THIS SOFTWARE.
|
|
roentgen |
b75cab |
*/
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
/*
|
|
roentgen |
b75cab |
* TIFF Library
|
|
roentgen |
b75cab |
*
|
|
roentgen |
b75cab |
* Written by Conrad J. Poelman, PL/WSAT, Kirtland AFB, NM on 26 Mar 96.
|
|
roentgen |
b75cab |
*
|
|
roentgen |
b75cab |
* This file contains code to allow a calling program to "iterate" over each
|
|
roentgen |
b75cab |
* pixels in an image as it is read from the file. The iterator takes care of
|
|
roentgen |
b75cab |
* reading strips versus (possibly clipped) tiles, decoding the information
|
|
roentgen |
b75cab |
* according to the decoding method, and so on, so that calling program can
|
|
roentgen |
b75cab |
* ignore those details. The calling program does, however, need to be
|
|
roentgen |
b75cab |
* conscious of the type of the pixel data that it is receiving.
|
|
roentgen |
b75cab |
*
|
|
roentgen |
b75cab |
* For reasons of efficiency, the callback function actually gets called for
|
|
roentgen |
b75cab |
* "blocks" of pixels rather than for individual pixels. The format of the
|
|
roentgen |
b75cab |
* callback arguments is given below.
|
|
roentgen |
b75cab |
*
|
|
roentgen |
b75cab |
* This code was taken from TIFFReadRGBAImage() in tif_getimage.c of the original
|
|
roentgen |
b75cab |
* TIFF distribution, and simplified and generalized to provide this general
|
|
roentgen |
b75cab |
* iteration capability. Those routines could certainly be re-implemented in terms
|
|
roentgen |
b75cab |
* of a TIFFImageIter if desired.
|
|
roentgen |
b75cab |
*
|
|
roentgen |
b75cab |
*/
|
|
roentgen |
b75cab |
#include "tiffiop.h"
|
|
roentgen |
b75cab |
#include "tif_imageiter.h"
|
|
roentgen |
b75cab |
#include <assert.h></assert.h>
|
|
roentgen |
b75cab |
#include <stdio.h></stdio.h>
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
static int gtTileContig(TIFFImageIter*, void *udata, uint32, uint32);
|
|
roentgen |
b75cab |
static int gtTileSeparate(TIFFImageIter*, void *udata, uint32, uint32);
|
|
roentgen |
b75cab |
static int gtStripContig(TIFFImageIter*, void *udata, uint32, uint32);
|
|
roentgen |
b75cab |
static int gtStripSeparate(TIFFImageIter*, void *udata, uint32, uint32);
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
static const char photoTag[] = "PhotometricInterpretation";
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
static int
|
|
roentgen |
b75cab |
isCCITTCompression(TIFF* tif)
|
|
roentgen |
b75cab |
{
|
|
roentgen |
b75cab |
uint16 compress;
|
|
roentgen |
b75cab |
TIFFGetField(tif, TIFFTAG_COMPRESSION, &compress);
|
|
roentgen |
b75cab |
return (compress == COMPRESSION_CCITTFAX3 ||
|
|
roentgen |
b75cab |
compress == COMPRESSION_CCITTFAX4 ||
|
|
roentgen |
b75cab |
compress == COMPRESSION_CCITTRLE ||
|
|
roentgen |
b75cab |
compress == COMPRESSION_CCITTRLEW);
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
int
|
|
roentgen |
b75cab |
TIFFImageIterBegin(TIFFImageIter* img, TIFF* tif, int stop, char emsg[1024])
|
|
roentgen |
b75cab |
{
|
|
roentgen |
b75cab |
uint16* sampleinfo;
|
|
roentgen |
b75cab |
uint16 extrasamples;
|
|
roentgen |
b75cab |
uint16 planarconfig;
|
|
roentgen |
b75cab |
int colorchannels;
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
img->tif = tif;
|
|
roentgen |
b75cab |
img->stoponerr = stop;
|
|
roentgen |
b75cab |
TIFFGetFieldDefaulted(tif, TIFFTAG_BITSPERSAMPLE, &img->bitspersample);
|
|
roentgen |
b75cab |
img->alpha = 0;
|
|
roentgen |
b75cab |
TIFFGetFieldDefaulted(tif, TIFFTAG_SAMPLESPERPIXEL, &img->samplesperpixel);
|
|
roentgen |
b75cab |
TIFFGetFieldDefaulted(tif, TIFFTAG_EXTRASAMPLES,
|
|
roentgen |
b75cab |
&extrasamples, &sampleinfo);
|
|
roentgen |
b75cab |
if (extrasamples == 1)
|
|
roentgen |
b75cab |
switch (sampleinfo[0]) {
|
|
roentgen |
b75cab |
case EXTRASAMPLE_ASSOCALPHA: /* data is pre-multiplied */
|
|
roentgen |
b75cab |
case EXTRASAMPLE_UNASSALPHA: /* data is not pre-multiplied */
|
|
roentgen |
b75cab |
img->alpha = sampleinfo[0];
|
|
roentgen |
b75cab |
break;
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
colorchannels = img->samplesperpixel - extrasamples;
|
|
roentgen |
b75cab |
TIFFGetFieldDefaulted(tif, TIFFTAG_PLANARCONFIG, &planarconfig);
|
|
roentgen |
b75cab |
if (!TIFFGetField(tif, TIFFTAG_PHOTOMETRIC, &img->photometric)) {
|
|
roentgen |
b75cab |
switch (colorchannels) {
|
|
roentgen |
b75cab |
case 1:
|
|
roentgen |
b75cab |
if (isCCITTCompression(tif))
|
|
roentgen |
b75cab |
img->photometric = PHOTOMETRIC_MINISWHITE;
|
|
roentgen |
b75cab |
else
|
|
roentgen |
b75cab |
img->photometric = PHOTOMETRIC_MINISBLACK;
|
|
roentgen |
b75cab |
break;
|
|
roentgen |
b75cab |
case 3:
|
|
roentgen |
b75cab |
img->photometric = PHOTOMETRIC_RGB;
|
|
roentgen |
b75cab |
break;
|
|
roentgen |
b75cab |
default:
|
|
roentgen |
b75cab |
sprintf(emsg, "Missing needed %s tag", photoTag);
|
|
roentgen |
b75cab |
return (0);
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
switch (img->photometric) {
|
|
roentgen |
b75cab |
case PHOTOMETRIC_PALETTE:
|
|
roentgen |
b75cab |
if (!TIFFGetField(tif, TIFFTAG_COLORMAP,
|
|
roentgen |
b75cab |
&img->redcmap, &img->greencmap, &img->bluecmap)) {
|
|
roentgen |
b75cab |
TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "Missing required \"Colormap\" tag");
|
|
roentgen |
b75cab |
return (0);
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
/* fall thru... */
|
|
roentgen |
b75cab |
case PHOTOMETRIC_MINISWHITE:
|
|
roentgen |
b75cab |
case PHOTOMETRIC_MINISBLACK:
|
|
roentgen |
b75cab |
/* This should work now so skip the check - BSR
|
|
roentgen |
b75cab |
if (planarconfig == PLANARCONFIG_CONTIG && img->samplesperpixel != 1) {
|
|
roentgen |
b75cab |
sprintf(emsg,
|
|
roentgen |
b75cab |
"Sorry, can not handle contiguous data with %s=%d, and %s=%d",
|
|
roentgen |
b75cab |
photoTag, img->photometric,
|
|
roentgen |
b75cab |
"Samples/pixel", img->samplesperpixel);
|
|
roentgen |
b75cab |
return (0);
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
*/
|
|
roentgen |
b75cab |
break;
|
|
roentgen |
b75cab |
case PHOTOMETRIC_YCBCR:
|
|
roentgen |
b75cab |
if (planarconfig != PLANARCONFIG_CONTIG) {
|
|
roentgen |
b75cab |
sprintf(emsg, "Sorry, can not handle YCbCr images with %s=%d",
|
|
roentgen |
b75cab |
"Planarconfiguration", planarconfig);
|
|
roentgen |
b75cab |
return (0);
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
/* It would probably be nice to have a reality check here. */
|
|
roentgen |
b75cab |
{ uint16 compress;
|
|
roentgen |
b75cab |
TIFFGetField(tif, TIFFTAG_COMPRESSION, &compress);
|
|
roentgen |
b75cab |
if (compress == COMPRESSION_JPEG && planarconfig == PLANARCONFIG_CONTIG) {
|
|
roentgen |
b75cab |
/* can rely on libjpeg to convert to RGB */
|
|
roentgen |
b75cab |
/* XXX should restore current state on exit */
|
|
roentgen |
b75cab |
TIFFSetField(tif, TIFFTAG_JPEGCOLORMODE, JPEGCOLORMODE_RGB);
|
|
roentgen |
b75cab |
img->photometric = PHOTOMETRIC_RGB;
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
break;
|
|
roentgen |
b75cab |
case PHOTOMETRIC_RGB:
|
|
roentgen |
b75cab |
if (colorchannels < 3) {
|
|
roentgen |
b75cab |
sprintf(emsg, "Sorry, can not handle RGB image with %s=%d",
|
|
roentgen |
b75cab |
"Color channels", colorchannels);
|
|
roentgen |
b75cab |
return (0);
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
break;
|
|
roentgen |
b75cab |
case PHOTOMETRIC_SEPARATED: {
|
|
roentgen |
b75cab |
uint16 inkset;
|
|
roentgen |
b75cab |
TIFFGetFieldDefaulted(tif, TIFFTAG_INKSET, &inkset);
|
|
roentgen |
b75cab |
if (inkset != INKSET_CMYK) {
|
|
roentgen |
b75cab |
sprintf(emsg, "Sorry, can not handle separated image with %s=%d",
|
|
roentgen |
b75cab |
"InkSet", inkset);
|
|
roentgen |
b75cab |
return (0);
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
if (img->samplesperpixel != 4) {
|
|
roentgen |
b75cab |
sprintf(emsg, "Sorry, can not handle separated image with %s=%d",
|
|
roentgen |
b75cab |
"Samples/pixel", img->samplesperpixel);
|
|
roentgen |
b75cab |
return (0);
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
break;
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
default:
|
|
roentgen |
b75cab |
sprintf(emsg, "Sorry, can not handle image with %s=%d",
|
|
roentgen |
b75cab |
photoTag, img->photometric);
|
|
roentgen |
b75cab |
return (0);
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &img->width);
|
|
roentgen |
b75cab |
TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &img->height);
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
TIFFGetFieldDefaulted(tif, TIFFTAG_ORIENTATION, &img->orientation);
|
|
roentgen |
b75cab |
switch (img->orientation) {
|
|
roentgen |
b75cab |
case ORIENTATION_BOTRIGHT:
|
|
roentgen |
b75cab |
case ORIENTATION_RIGHTBOT: /* XXX */
|
|
roentgen |
b75cab |
case ORIENTATION_LEFTBOT: /* XXX */
|
|
roentgen |
b75cab |
TIFFWarning(TIFFFileName(tif), "using bottom-left orientation");
|
|
roentgen |
b75cab |
img->orientation = ORIENTATION_BOTLEFT;
|
|
roentgen |
b75cab |
/* fall thru... */
|
|
roentgen |
b75cab |
case ORIENTATION_BOTLEFT:
|
|
roentgen |
b75cab |
break;
|
|
roentgen |
b75cab |
case ORIENTATION_TOPRIGHT:
|
|
roentgen |
b75cab |
case ORIENTATION_RIGHTTOP: /* XXX */
|
|
roentgen |
b75cab |
case ORIENTATION_LEFTTOP: /* XXX */
|
|
roentgen |
b75cab |
default:
|
|
roentgen |
b75cab |
TIFFWarning(TIFFFileName(tif), "using top-left orientation");
|
|
roentgen |
b75cab |
img->orientation = ORIENTATION_TOPLEFT;
|
|
roentgen |
b75cab |
/* fall thru... */
|
|
roentgen |
b75cab |
case ORIENTATION_TOPLEFT:
|
|
roentgen |
b75cab |
break;
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
img->isContig =
|
|
roentgen |
b75cab |
!(planarconfig == PLANARCONFIG_SEPARATE && colorchannels > 1);
|
|
roentgen |
b75cab |
if (img->isContig) {
|
|
roentgen |
b75cab |
img->get = TIFFIsTiled(tif) ? gtTileContig : gtStripContig;
|
|
roentgen |
b75cab |
} else {
|
|
roentgen |
b75cab |
img->get = TIFFIsTiled(tif) ? gtTileSeparate : gtStripSeparate;
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
return (1);
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
int
|
|
roentgen |
b75cab |
TIFFImageIterGet(TIFFImageIter* img, void *udata, uint32 w, uint32 h)
|
|
roentgen |
b75cab |
{
|
|
roentgen |
b75cab |
if (img->get == NULL) {
|
|
roentgen |
b75cab |
TIFFErrorExt(img->tif->tif_clientdata, TIFFFileName(img->tif), "No \"get\" routine setup");
|
|
roentgen |
b75cab |
return (0);
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
if (img->callback.any == NULL) {
|
|
roentgen |
b75cab |
TIFFErrorExt(img->tif->tif_clientdata, TIFFFileName(img->tif),
|
|
roentgen |
b75cab |
"No \"put\" routine setupl; probably can not handle image format");
|
|
roentgen |
b75cab |
return (0);
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
return (*img->get)(img, udata, w, h);
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
TIFFImageIterEnd(TIFFImageIter* img)
|
|
roentgen |
b75cab |
{
|
|
roentgen |
b75cab |
/* Nothing to free... ? */
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
/*
|
|
roentgen |
b75cab |
* Read the specified image into an ABGR-format raster.
|
|
roentgen |
b75cab |
*/
|
|
roentgen |
b75cab |
int
|
|
roentgen |
b75cab |
TIFFReadImageIter(TIFF* tif,
|
|
roentgen |
b75cab |
uint32 rwidth, uint32 rheight, uint8* raster, int stop)
|
|
roentgen |
b75cab |
{
|
|
roentgen |
b75cab |
char emsg[1024];
|
|
roentgen |
b75cab |
TIFFImageIter img;
|
|
roentgen |
b75cab |
int ok;
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
if (TIFFImageIterBegin(&img, tif, stop, emsg)) {
|
|
roentgen |
b75cab |
/* XXX verify rwidth and rheight against width and height */
|
|
roentgen |
b75cab |
ok = TIFFImageIterGet(&img, raster, rwidth, img.height);
|
|
roentgen |
b75cab |
TIFFImageIterEnd(&img);
|
|
roentgen |
b75cab |
} else {
|
|
roentgen |
b75cab |
TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), emsg);
|
|
roentgen |
b75cab |
ok = 0;
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
return (ok);
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
/*
|
|
roentgen |
b75cab |
* Get an tile-organized image that has
|
|
roentgen |
b75cab |
* PlanarConfiguration contiguous if SamplesPerPixel > 1
|
|
roentgen |
b75cab |
* or
|
|
roentgen |
b75cab |
* SamplesPerPixel == 1
|
|
roentgen |
b75cab |
*/
|
|
roentgen |
b75cab |
static int
|
|
roentgen |
b75cab |
gtTileContig(TIFFImageIter* img, void *udata, uint32 w, uint32 h)
|
|
roentgen |
b75cab |
{
|
|
roentgen |
b75cab |
TIFF* tif = img->tif;
|
|
roentgen |
b75cab |
ImageIterTileContigRoutine callback = img->callback.contig;
|
|
roentgen |
b75cab |
uint16 orientation;
|
|
roentgen |
b75cab |
uint32 col, row;
|
|
roentgen |
b75cab |
uint32 tw, th;
|
|
roentgen |
b75cab |
u_char* buf;
|
|
roentgen |
b75cab |
int32 fromskew;
|
|
roentgen |
b75cab |
uint32 nrow;
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
buf = (u_char*) _TIFFmalloc(TIFFTileSize(tif));
|
|
roentgen |
b75cab |
if (buf == 0) {
|
|
roentgen |
b75cab |
TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "No space for tile buffer");
|
|
roentgen |
b75cab |
return (0);
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
TIFFGetField(tif, TIFFTAG_TILEWIDTH, &tw);
|
|
roentgen |
b75cab |
TIFFGetField(tif, TIFFTAG_TILELENGTH, &th);
|
|
roentgen |
b75cab |
orientation = img->orientation;
|
|
roentgen |
b75cab |
for (row = 0; row < h; row += th) {
|
|
roentgen |
b75cab |
nrow = (row + th > h ? h - row : th);
|
|
roentgen |
b75cab |
for (col = 0; col < w; col += tw) {
|
|
roentgen |
b75cab |
if (TIFFReadTile(tif, buf, col, row, 0, 0) < 0 && img->stoponerr)
|
|
roentgen |
b75cab |
break;
|
|
roentgen |
b75cab |
if (col + tw > w) {
|
|
roentgen |
b75cab |
/*
|
|
roentgen |
b75cab |
* Tile is clipped horizontally. Calculate
|
|
roentgen |
b75cab |
* visible portion and skewing factors.
|
|
roentgen |
b75cab |
*/
|
|
roentgen |
b75cab |
uint32 npix = w - col;
|
|
roentgen |
b75cab |
fromskew = tw - npix;
|
|
roentgen |
b75cab |
(*callback)(img, udata, col, row, npix, nrow, fromskew, buf);
|
|
roentgen |
b75cab |
} else {
|
|
roentgen |
b75cab |
(*callback)(img, udata, col, row, tw, nrow, 0, buf);
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
_TIFFfree(buf);
|
|
roentgen |
b75cab |
return (1);
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
/*
|
|
roentgen |
b75cab |
* Get an tile-organized image that has
|
|
roentgen |
b75cab |
* SamplesPerPixel > 1
|
|
roentgen |
b75cab |
* PlanarConfiguration separated
|
|
roentgen |
b75cab |
* We assume that all such images are RGB.
|
|
roentgen |
b75cab |
*/
|
|
roentgen |
b75cab |
static int
|
|
roentgen |
b75cab |
gtTileSeparate(TIFFImageIter* img, void *udata, uint32 w, uint32 h)
|
|
roentgen |
b75cab |
{
|
|
roentgen |
b75cab |
TIFF* tif = img->tif;
|
|
roentgen |
b75cab |
ImageIterTileSeparateRoutine callback = img->callback.separate;
|
|
roentgen |
b75cab |
uint16 orientation;
|
|
roentgen |
b75cab |
uint32 col, row;
|
|
roentgen |
b75cab |
uint32 tw, th;
|
|
roentgen |
b75cab |
u_char* buf;
|
|
roentgen |
b75cab |
u_char* r;
|
|
roentgen |
b75cab |
u_char* g;
|
|
roentgen |
b75cab |
u_char* b;
|
|
roentgen |
b75cab |
u_char* a;
|
|
roentgen |
b75cab |
tsize_t tilesize;
|
|
roentgen |
b75cab |
int32 fromskew;
|
|
roentgen |
b75cab |
int alpha = img->alpha;
|
|
roentgen |
b75cab |
uint32 nrow;
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
tilesize = TIFFTileSize(tif);
|
|
roentgen |
b75cab |
buf = (u_char*) _TIFFmalloc(4*tilesize);
|
|
roentgen |
b75cab |
if (buf == 0) {
|
|
roentgen |
b75cab |
TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "No space for tile buffer");
|
|
roentgen |
b75cab |
return (0);
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
r = buf;
|
|
roentgen |
b75cab |
g = r + tilesize;
|
|
roentgen |
b75cab |
b = g + tilesize;
|
|
roentgen |
b75cab |
a = b + tilesize;
|
|
roentgen |
b75cab |
if (!alpha)
|
|
roentgen |
b75cab |
memset(a, 0xff, tilesize);
|
|
roentgen |
b75cab |
TIFFGetField(tif, TIFFTAG_TILEWIDTH, &tw);
|
|
roentgen |
b75cab |
TIFFGetField(tif, TIFFTAG_TILELENGTH, &th);
|
|
roentgen |
b75cab |
orientation = img->orientation;
|
|
roentgen |
b75cab |
for (row = 0; row < h; row += th) {
|
|
roentgen |
b75cab |
nrow = (row + th > h ? h - row : th);
|
|
roentgen |
b75cab |
for (col = 0; col < w; col += tw) {
|
|
roentgen |
b75cab |
if (TIFFReadTile(tif, r, col, row,0,0) < 0 && img->stoponerr)
|
|
roentgen |
b75cab |
break;
|
|
roentgen |
b75cab |
if (TIFFReadTile(tif, g, col, row,0,1) < 0 && img->stoponerr)
|
|
roentgen |
b75cab |
break;
|
|
roentgen |
b75cab |
if (TIFFReadTile(tif, b, col, row,0,2) < 0 && img->stoponerr)
|
|
roentgen |
b75cab |
break;
|
|
roentgen |
b75cab |
if (alpha && TIFFReadTile(tif,a,col,row,0,3) < 0 && img->stoponerr)
|
|
roentgen |
b75cab |
break;
|
|
roentgen |
b75cab |
if (col + tw > w) {
|
|
roentgen |
b75cab |
/*
|
|
roentgen |
b75cab |
* Tile is clipped horizontally. Calculate
|
|
roentgen |
b75cab |
* visible portion and skewing factors.
|
|
roentgen |
b75cab |
*/
|
|
roentgen |
b75cab |
uint32 npix = w - col;
|
|
roentgen |
b75cab |
fromskew = tw - npix;
|
|
roentgen |
b75cab |
(*callback)(img, udata, col, row, npix, nrow, fromskew, r, g, b, a);
|
|
roentgen |
b75cab |
} else {
|
|
roentgen |
b75cab |
(*callback)(img, udata, col, row, tw, nrow, 0, r, g, b, a);
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
_TIFFfree(buf);
|
|
roentgen |
b75cab |
return (1);
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
/*
|
|
roentgen |
b75cab |
* Get a strip-organized image that has
|
|
roentgen |
b75cab |
* PlanarConfiguration contiguous if SamplesPerPixel > 1
|
|
roentgen |
b75cab |
* or
|
|
roentgen |
b75cab |
* SamplesPerPixel == 1
|
|
roentgen |
b75cab |
*/
|
|
roentgen |
b75cab |
static int
|
|
roentgen |
b75cab |
gtStripContig(TIFFImageIter* img, void *udata, uint32 w, uint32 h)
|
|
roentgen |
b75cab |
{
|
|
roentgen |
b75cab |
TIFF* tif = img->tif;
|
|
roentgen |
b75cab |
ImageIterTileContigRoutine callback = img->callback.contig;
|
|
roentgen |
b75cab |
uint16 orientation;
|
|
roentgen |
b75cab |
uint32 row, nrow;
|
|
roentgen |
b75cab |
u_char* buf;
|
|
roentgen |
b75cab |
uint32 rowsperstrip;
|
|
roentgen |
b75cab |
uint32 imagewidth = img->width;
|
|
roentgen |
b75cab |
tsize_t scanline;
|
|
roentgen |
b75cab |
int32 fromskew;
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
buf = (u_char*) _TIFFmalloc(TIFFStripSize(tif));
|
|
roentgen |
b75cab |
if (buf == 0) {
|
|
roentgen |
b75cab |
TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "No space for strip buffer");
|
|
roentgen |
b75cab |
return (0);
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
orientation = img->orientation;
|
|
roentgen |
b75cab |
TIFFGetFieldDefaulted(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip);
|
|
roentgen |
b75cab |
scanline = TIFFScanlineSize(tif);
|
|
roentgen |
b75cab |
fromskew = (w < imagewidth ? imagewidth - w : 0);
|
|
roentgen |
b75cab |
for (row = 0; row < h; row += rowsperstrip) {
|
|
roentgen |
b75cab |
nrow = (row + rowsperstrip > h ? h - row : rowsperstrip);
|
|
roentgen |
b75cab |
if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, row, 0),
|
|
roentgen |
b75cab |
buf, nrow*scanline) < 0 && img->stoponerr)
|
|
roentgen |
b75cab |
break;
|
|
roentgen |
b75cab |
(*callback)(img, udata, 0, row, w, nrow, fromskew, buf);
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
_TIFFfree(buf);
|
|
roentgen |
b75cab |
return (1);
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
/*
|
|
roentgen |
b75cab |
* Get a strip-organized image with
|
|
roentgen |
b75cab |
* SamplesPerPixel > 1
|
|
roentgen |
b75cab |
* PlanarConfiguration separated
|
|
roentgen |
b75cab |
* We assume that all such images are RGB.
|
|
roentgen |
b75cab |
*/
|
|
roentgen |
b75cab |
static int
|
|
roentgen |
b75cab |
gtStripSeparate(TIFFImageIter* img, void *udata, uint32 w, uint32 h)
|
|
roentgen |
b75cab |
{
|
|
roentgen |
b75cab |
TIFF* tif = img->tif;
|
|
roentgen |
b75cab |
ImageIterTileSeparateRoutine callback = img->callback.separate;
|
|
roentgen |
b75cab |
uint16 orientation;
|
|
roentgen |
b75cab |
u_char *buf;
|
|
roentgen |
b75cab |
u_char *r, *g, *b, *a;
|
|
roentgen |
b75cab |
uint32 row, nrow;
|
|
roentgen |
b75cab |
tsize_t scanline;
|
|
roentgen |
b75cab |
uint32 rowsperstrip;
|
|
roentgen |
b75cab |
uint32 imagewidth = img->width;
|
|
roentgen |
b75cab |
tsize_t stripsize;
|
|
roentgen |
b75cab |
int32 fromskew;
|
|
roentgen |
b75cab |
int alpha = img->alpha;
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
stripsize = TIFFStripSize(tif);
|
|
roentgen |
b75cab |
r = buf = (u_char *)_TIFFmalloc(4*stripsize);
|
|
roentgen |
b75cab |
if (buf == 0) {
|
|
roentgen |
b75cab |
TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "No space for tile buffer");
|
|
roentgen |
b75cab |
return (0);
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
g = r + stripsize;
|
|
roentgen |
b75cab |
b = g + stripsize;
|
|
roentgen |
b75cab |
a = b + stripsize;
|
|
roentgen |
b75cab |
if (!alpha)
|
|
roentgen |
b75cab |
memset(a, 0xff, stripsize);
|
|
roentgen |
b75cab |
orientation = img->orientation;
|
|
roentgen |
b75cab |
TIFFGetFieldDefaulted(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip);
|
|
roentgen |
b75cab |
scanline = TIFFScanlineSize(tif);
|
|
roentgen |
b75cab |
fromskew = (w < imagewidth ? imagewidth - w : 0);
|
|
roentgen |
b75cab |
for (row = 0; row < h; row += rowsperstrip) {
|
|
roentgen |
b75cab |
nrow = (row + rowsperstrip > h ? h - row : rowsperstrip);
|
|
roentgen |
b75cab |
if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, row, 0),
|
|
roentgen |
b75cab |
r, nrow*scanline) < 0 && img->stoponerr)
|
|
roentgen |
b75cab |
break;
|
|
roentgen |
b75cab |
if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, row, 1),
|
|
roentgen |
b75cab |
g, nrow*scanline) < 0 && img->stoponerr)
|
|
roentgen |
b75cab |
break;
|
|
roentgen |
b75cab |
if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, row, 2),
|
|
roentgen |
b75cab |
b, nrow*scanline) < 0 && img->stoponerr)
|
|
roentgen |
b75cab |
break;
|
|
roentgen |
b75cab |
if (alpha &&
|
|
roentgen |
b75cab |
(TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, row, 3),
|
|
roentgen |
b75cab |
a, nrow*scanline) < 0 && img->stoponerr))
|
|
roentgen |
b75cab |
break;
|
|
roentgen |
b75cab |
(*callback)(img, udata, 0, row, w, nrow, fromskew, r, g, b, a);
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
_TIFFfree(buf);
|
|
roentgen |
b75cab |
return (1);
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
DECLAREContigCallbackFunc(TestContigCallback)
|
|
roentgen |
b75cab |
{
|
|
roentgen |
b75cab |
printf("Contig Callback called with x = %d, y = %d, w = %d, h = %d, fromskew = %d\n",
|
|
roentgen |
b75cab |
x, y, w, h, fromskew);
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
DECLARESepCallbackFunc(TestSepCallback)
|
|
roentgen |
b75cab |
{
|
|
roentgen |
b75cab |
printf("Sep Callback called with x = %d, y = %d, w = %d, h = %d, fromskew = %d\n",
|
|
roentgen |
b75cab |
x, y, w, h, fromskew);
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
#ifdef MAIN
|
|
roentgen |
b75cab |
main(int argc, char **argv)
|
|
roentgen |
b75cab |
{
|
|
roentgen |
b75cab |
char emsg[1024];
|
|
roentgen |
b75cab |
TIFFImageIter img;
|
|
roentgen |
b75cab |
int ok;
|
|
roentgen |
b75cab |
int stop = 1;
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
TIFF *tif;
|
|
roentgen |
b75cab |
unsigned long nx, ny;
|
|
roentgen |
b75cab |
unsigned short BitsPerSample, SamplesPerPixel;
|
|
roentgen |
b75cab |
int isColorMapped, isPliFile;
|
|
roentgen |
b75cab |
unsigned char *ColorMap;
|
|
roentgen |
b75cab |
unsigned char *data;
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
if (argc < 2) {
|
|
roentgen |
b75cab |
fprintf(stderr,"usage: %s tiff_file\n",argv[0]);
|
|
roentgen |
b75cab |
exit(1);
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
tif = (TIFF *)PLIGetImage(argv[1], (void *) &data, &ColorMap,
|
|
roentgen |
b75cab |
&nx, &ny, &BitsPerSample, &SamplesPerPixel,
|
|
roentgen |
b75cab |
&isColorMapped, &isPliFile);
|
|
roentgen |
b75cab |
if (tif != NULL) {
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
if (TIFFImageIterBegin(&img, tif, stop, emsg)) {
|
|
roentgen |
b75cab |
/* Here need to set data and callback function! */
|
|
roentgen |
b75cab |
if (img.isContig) {
|
|
roentgen |
b75cab |
img.callback = TestContigCallback;
|
|
roentgen |
b75cab |
} else {
|
|
roentgen |
b75cab |
img.callback = TestSepCallback;
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
ok = TIFFImageIterGet(&img, NULL, img.width, img.height);
|
|
roentgen |
b75cab |
TIFFImageIterEnd(&img);
|
|
roentgen |
b75cab |
} else {
|
|
roentgen |
b75cab |
TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), emsg);
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
#endif
|
|
roentgen |
b75cab |
/*
|
|
roentgen |
b75cab |
* Local Variables:
|
|
roentgen |
b75cab |
* mode: c
|
|
roentgen |
b75cab |
* c-basic-offset: 8
|
|
roentgen |
b75cab |
* fill-column: 78
|
|
roentgen |
b75cab |
* End:
|
|
roentgen |
b75cab |
*/
|