⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tif_getimage.c

📁 支持各种栅格图像和矢量图像读取的库
💻 C
📖 第 1 页 / 共 5 页
字号:
/* $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 + -