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

📄 tif_getimage.c

📁 一款最完整的工业组态软源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/* $Id: tif_getimage.c,v 1.5 2004/10/16 15:34:33 drolon 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 pickTileContigCase(TIFFRGBAImage*);
static	int pickTileSeparateCase(TIFFRGBAImage*);

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.
 */
int
TIFFRGBAImageOK(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:
	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;
    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;
    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);
}

void
TIFFRGBAImageEnd(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->redcmap ) {
		_TIFFfree( img->redcmap );
		_TIFFfree( img->greencmap );
		_TIFFfree( 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->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 > 0)
    {
	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)) {
	    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(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 ) {
	    TIFFError(TIFFFileName(tif), "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:
	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 (planarconfig == PLANARCONFIG_CONTIG)
	    /* can rely on libjpeg to convert to RGB */
	    /* XXX should restore current state on exit */
	    switch (compress) {
		case COMPRESSION_OJPEG:
		case COMPRESSION_JPEG:
		    TIFFSetField(tif, TIFFTAG_JPEGCOLORMODE, JPEGCOLORMODE_RGB);
		    img->photometric = PHOTOMETRIC_RGB;
                    break;

                default:
                    /* do nothing */;
                    break;
	    }
	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;
    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;
	return pickTileContigCase(img);
    } else {
	img->get = TIFFIsTiled(tif) ? gtTileSeparate : gtStripSeparate;
	return pickTileSeparateCase(img);
    }
}

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 rastertaking in account
 * specified orientation.
 */
int
TIFFReadRGBAImageOriented(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 {
	TIFFError(TIFFFileName(tif), emsg);
	ok = 0;
    }
    return (ok);
}

/*
 * Read the specified image into an ABGR-format raster. Use bottom left
 * origin for raster by default.
 */
int
TIFFReadRGBAImage(TIFF* tif,
		  uint32 rwidth, uint32 rheight, uint32* raster, int stop)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -