?? tif_getimage.c
字號:
/* $Id: tif_getimage.c,v 1.61 2006/04/13 03:25:53 joris Exp $ *//* * 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. */#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 PickContigCase(TIFFRGBAImage*);static int PickSeparateCase(TIFFRGBAImage*);static int BuildMapUaToAa(TIFFRGBAImage* img);static int BuildMapBitdepth16To8(TIFFRGBAImage* img);static const char photoTag[] = "PhotometricInterpretation";/* * Helper constants used in Orientation tag handling */#define FLIP_VERTICALLY 0x01#define FLIP_HORIZONTALLY 0x02/* * Color conversion constants. We will define display types here. */TIFFDisplay display_sRGB = { { /* XYZ -> luminance matrix */ { 3.2410F, -1.5374F, -0.4986F }, { -0.9692F, 1.8760F, 0.0416F }, { 0.0556F, -0.2040F, 1.0570F } }, 100.0F, 100.0F, 100.0F, /* Light o/p for reference white */ 255, 255, 255, /* Pixel values for ref. white */ 1.0F, 1.0F, 1.0F, /* Residual light o/p for black pixel */ 2.4F, 2.4F, 2.4F, /* Gamma values for the three guns */};/* * 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. */intTIFFRGBAImageOK(TIFF* tif, char emsg[1024]){ TIFFDirectory* td = &tif->tif_dir; uint16 photometric; int colorchannels; if (!tif->tif_decodestatus) { sprintf(emsg, "Sorry, requested compression method is not configured"); return (0); } 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 && td->td_bitspersample < 8 ) { sprintf(emsg, "Sorry, can not handle contiguous data with %s=%d, " "and %s=%d and Bits/Sample=%d", photoTag, photometric, "Samples/pixel", td->td_samplesperpixel, td->td_bitspersample); return (0); } /* * We should likely validate that any extra samples are either * to be ignored, or are alpha, and if alpha we should try to use * them. But for now we won't bother with this. */ break; case PHOTOMETRIC_YCBCR: /* * TODO: if at all meaningful and useful, make more complete * support check here, or better still, refactor to let supporting * code decide whether there is support and what meaningfull * error to return */ 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 (td->td_samplesperpixel < 4) { sprintf(emsg, "Sorry, can not handle separated image with %s=%d", "Samples/pixel", td->td_samplesperpixel); return 0; } break; } 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; case PHOTOMETRIC_CIELAB: break; default: sprintf(emsg, "Sorry, can not handle image with %s=%d", photoTag, photometric); return (0); } return (1);}voidTIFFRGBAImageEnd(TIFFRGBAImage* img){ if (img->Map) _TIFFfree(img->Map), img->Map = NULL; if (img->BWmap) _TIFFfree(img->BWmap), img->BWmap = NULL; if (img->PALmap) _TIFFfree(img->PALmap), img->PALmap = NULL; if (img->ycbcr) _TIFFfree(img->ycbcr), img->ycbcr = NULL; if (img->cielab) _TIFFfree(img->cielab), img->cielab = NULL; if (img->UaToAa) _TIFFfree(img->UaToAa), img->UaToAa = NULL; if (img->Bitdepth16To8) _TIFFfree(img->Bitdepth16To8), img->Bitdepth16To8 = NULL; if( img->redcmap ) { _TIFFfree( img->redcmap ); _TIFFfree( img->greencmap ); _TIFFfree( img->bluecmap ); }}static intisCCITTCompression(TIFF* tif){ uint16 compress; TIFFGetField(tif, TIFFTAG_COMPRESSION, &compress); return (compress == COMPRESSION_CCITTFAX3 || compress == COMPRESSION_CCITTFAX4 || compress == COMPRESSION_CCITTRLE || compress == COMPRESSION_CCITTRLEW);}intTIFFRGBAImageBegin(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->req_orientation = ORIENTATION_BOTLEFT; /* It is the default */ 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 handle images 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_UNSPECIFIED: /* Workaround for some images without */ if (img->samplesperpixel > 3) /* correct info about alpha channel */ img->alpha = EXTRASAMPLE_ASSOCALPHA; break; case EXTRASAMPLE_ASSOCALPHA: /* data is pre-multiplied */ case EXTRASAMPLE_UNASSALPHA: /* data is not pre-multiplied */ img->alpha = sampleinfo[0]; break; } }#ifdef DEFAULT_EXTRASAMPLE_AS_ALPHA if( !TIFFGetField(tif, TIFFTAG_PHOTOMETRIC, &img->photometric)) img->photometric = PHOTOMETRIC_MINISWHITE; if( extrasamples == 0 && img->samplesperpixel == 4 && img->photometric == PHOTOMETRIC_RGB ) { img->alpha = EXTRASAMPLE_ASSOCALPHA; extrasamples = 1; }#endif 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)) { sprintf(emsg, "Missing required \"Colormap\" tag"); return (0); } /* copy the colormaps so we can modify them */ n_color = (1L << img->bitspersample); img->redcmap = (uint16 *) _TIFFmalloc(sizeof(uint16)*n_color); img->greencmap = (uint16 *) _TIFFmalloc(sizeof(uint16)*n_color); img->bluecmap = (uint16 *) _TIFFmalloc(sizeof(uint16)*n_color); if( !img->redcmap || !img->greencmap || !img->bluecmap ) { sprintf(emsg, "Out of memory for colormap copy"); return (0); } _TIFFmemcpy( img->redcmap, red_orig, n_color * 2 ); _TIFFmemcpy( img->greencmap, green_orig, n_color * 2 ); _TIFFmemcpy( img->bluecmap, blue_orig, n_color * 2 ); /* fall thru... */ case PHOTOMETRIC_MINISWHITE: case PHOTOMETRIC_MINISBLACK: if (planarconfig == PLANARCONFIG_CONTIG && img->samplesperpixel != 1 && img->bitspersample < 8 ) { sprintf(emsg, "Sorry, can not handle contiguous data with %s=%d, " "and %s=%d and Bits/Sample=%d", photoTag, img->photometric, "Samples/pixel", img->samplesperpixel, img->bitspersample); return (0); } break; case PHOTOMETRIC_YCBCR: /* It would probably be nice to have a reality check here. */ if (planarconfig == PLANARCONFIG_CONTIG) /* can rely on libjpeg to convert to RGB */ /* XXX should restore current state on exit */ switch (compress) { case COMPRESSION_JPEG: /* * TODO: when complete tests verify complete desubsampling * and YCbCr handling, remove use of TIFFTAG_JPEGCOLORMODE in * favor of tif_getimage.c native handling */ TIFFSetField(tif, TIFFTAG_JPEGCOLORMODE, JPEGCOLORMODE_RGB); img->photometric = PHOTOMETRIC_RGB; break; default: /* do nothing */; break; } /* * TODO: if at all meaningful and useful, make more complete * support check here, or better still, refactor to let supporting * code decide whether there is support and what meaningfull * error to return */ 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; case PHOTOMETRIC_CIELAB: 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; img->cielab = NULL; img->UaToAa = NULL; img->Bitdepth16To8 = 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) { if (!PickContigCase(img)) { sprintf(emsg, "Sorry, can not handle image"); return 0; } } else { if (!PickSeparateCase(img)) { sprintf(emsg, "Sorry, can not handle image"); return 0; } } return 1;}intTIFFRGBAImageGet(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h){ if (img->get == NULL) { TIFFErrorExt(img->tif->tif_clientdata, TIFFFileName(img->tif), "No \"get\" routine setup"); return (0); } if (img->put.any == NULL) { TIFFErrorExt(img->tif->tif_clientdata, 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 rastertaking in account * specified orientation. */intTIFFReadRGBAImageOriented(TIFF* tif, uint32 rwidth, uint32 rheight, uint32* raster, int orientation, int stop){ char emsg[1024] = ""; TIFFRGBAImage img; int ok; if (TIFFRGBAImageOK(tif, emsg) && TIFFRGBAImageBegin(&img, tif, stop, emsg)) { img.req_orientation = orientation; /* XXX verify rwidth and rheight against width and height */ ok = TIFFRGBAImageGet(&img, raster+(rheight-img.height)*rwidth, rwidth, img.height); TIFFRGBAImageEnd(&img); } else { TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), emsg); ok = 0; } return (ok);}/* * Read the specified image into an ABGR-format raster. Use bottom left * origin for raster by default. */intTIFFReadRGBAImage(TIFF* tif, uint32 rwidth, uint32 rheight, uint32* raster, int stop){ return TIFFReadRGBAImageOriented(tif, rwidth, rheight, raster, ORIENTATION_BOTLEFT, stop);}static int setorientation(TIFFRGBAImage* img){ switch (img->orientation) { case ORIENTATION_TOPLEFT: case ORIENTATION_LEFTTOP:
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -