📄 tif_imageiter.c
字号:
/* $Header: /cvs/maptools/cvsroot/libtiff/contrib/pds/tif_imageiter.c,v 1.2 2004/05/19 17:14:45 dron Exp $ *//* * Copyright (c) 1991-1996 Sam Leffler * Copyright (c) 1991-1996 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 * * Written by Conrad J. Poelman, PL/WSAT, Kirtland AFB, NM on 26 Mar 96. * * This file contains code to allow a calling program to "iterate" over each * pixels in an image as it is read from the file. The iterator takes care of * reading strips versus (possibly clipped) tiles, decoding the information * according to the decoding method, and so on, so that calling program can * ignore those details. The calling program does, however, need to be * conscious of the type of the pixel data that it is receiving. * * For reasons of efficiency, the callback function actually gets called for * "blocks" of pixels rather than for individual pixels. The format of the * callback arguments is given below. * * This code was taken from TIFFReadRGBAImage() in tif_getimage.c of the original * TIFF distribution, and simplified and generalized to provide this general * iteration capability. Those routines could certainly be re-implemented in terms * of a TIFFImageIter if desired. * */#include "tiffiop.h"#include "tif_imageiter.h"#include <assert.h>#include <stdio.h>static int gtTileContig(TIFFImageIter*, void *udata, uint32, uint32);static int gtTileSeparate(TIFFImageIter*, void *udata, uint32, uint32);static int gtStripContig(TIFFImageIter*, void *udata, uint32, uint32);static int gtStripSeparate(TIFFImageIter*, void *udata, uint32, uint32);static const char photoTag[] = "PhotometricInterpretation";static intisCCITTCompression(TIFF* tif){ uint16 compress; TIFFGetField(tif, TIFFTAG_COMPRESSION, &compress); return (compress == COMPRESSION_CCITTFAX3 || compress == COMPRESSION_CCITTFAX4 || compress == COMPRESSION_CCITTRLE || compress == COMPRESSION_CCITTRLEW);}intTIFFImageIterBegin(TIFFImageIter* img, TIFF* tif, int stop, char emsg[1024]){ uint16* sampleinfo; uint16 extrasamples; uint16 planarconfig; int colorchannels; img->tif = tif; img->stoponerr = stop; TIFFGetFieldDefaulted(tif, TIFFTAG_BITSPERSAMPLE, &img->bitspersample); 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_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, &img->redcmap, &img->greencmap, &img->bluecmap)) { TIFFError(TIFFFileName(tif), "Missing required \"Colormap\" tag"); return (0); } /* fall thru... */ case PHOTOMETRIC_MINISWHITE: case PHOTOMETRIC_MINISBLACK:/* This should work now so skip the check - BSR 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. */ { uint16 compress; TIFFGetField(tif, TIFFTAG_COMPRESSION, &compress); 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; } default: sprintf(emsg, "Sorry, can not handle image with %s=%d", photoTag, img->photometric); return (0); } TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &img->width); TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &img->height); TIFFGetFieldDefaulted(tif, TIFFTAG_ORIENTATION, &img->orientation); 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: 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: break; } img->isContig = !(planarconfig == PLANARCONFIG_SEPARATE && colorchannels > 1); if (img->isContig) { img->get = TIFFIsTiled(tif) ? gtTileContig : gtStripContig; } else { img->get = TIFFIsTiled(tif) ? gtTileSeparate : gtStripSeparate; } return (1);}intTIFFImageIterGet(TIFFImageIter* img, void *udata, uint32 w, uint32 h){ if (img->get == NULL) { TIFFError(TIFFFileName(img->tif), "No \"get\" routine setup"); return (0); } if (img->callback.any == NULL) { TIFFError(TIFFFileName(img->tif), "No \"put\" routine setupl; probably can not handle image format"); return (0); } return (*img->get)(img, udata, w, h);}TIFFImageIterEnd(TIFFImageIter* img){ /* Nothing to free... ? */}/* * Read the specified image into an ABGR-format raster. */intTIFFReadImageIter(TIFF* tif, uint32 rwidth, uint32 rheight, uint8* raster, int stop){ char emsg[1024]; TIFFImageIter img; int ok; if (TIFFImageIterBegin(&img, tif, stop, emsg)) { /* XXX verify rwidth and rheight against width and height */ ok = TIFFImageIterGet(&img, raster, rwidth, img.height); TIFFImageIterEnd(&img); } else { TIFFError(TIFFFileName(tif), emsg); ok = 0; } return (ok);}/* * Get an tile-organized image that has * PlanarConfiguration contiguous if SamplesPerPixel > 1 * or * SamplesPerPixel == 1 */ static intgtTileContig(TIFFImageIter* img, void *udata, uint32 w, uint32 h)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -