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

📄 loadtiff.c

📁 具有IDE功能的编辑器
💻 C
字号:
/* loadtiff.c - loads a tiff file into memory   Copyright (C) 1996-2000 Paul Sheer   This program is free software; you can redistribute it and/or modify   it under the terms of the GNU General Public License as published by   the Free Software Foundation; either version 2 of the License, or   (at your option) any later version.   This program is distributed in the hope that it will be useful,   but WITHOUT ANY WARRANTY; without even the implied warranty of   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the   GNU General Public License for more details.   You should have received a copy of the GNU General Public License   along with this program; if not, write to the Free Software   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA   02111-1307, USA. *//* this file is highly dependent on a long int being 4 bytes *//* NLS through this whole file ? */#include <config.h>#include <stdlib.h>#include <stdio.h>#include <X11/Xlib.h>#include <X11/Xutil.h>#include <math.h>#include "stringtools.h"#include "app_glob.c"#include "coolwidget.h"#include "mad.h"#define TPRINTF tiffprintf/*tiffprintf*//* #define ABORT_ON_ERROR */short highbytefirst = 0;short fgetshort(FILE *f){if(highbytefirst)    return (getc(f)<<8) + getc(f);else    return getc(f) + (getc(f) << 8);}long fgetlong (FILE * f){    if (highbytefirst)	return (getc (f) << 24) + (getc (f) << 16) + (getc (f) << 8) + getc (f);    else	return getc (f) + (getc (f) << 8) + (getc (f) << 16) + (getc (f) << 24);}/*Gets an array of unsigned char at offset 'offset' from the beginningof the file, of length 'length' bytes. It returns a pointer to the dataalthough the data is malloced from within the function, the functionchecks on each call to free previous mallocs, and does soif necessary. Therefore DO NOT FREE the pointer returned by this function.Also copy the results before the next call to fgetstring.*/unsigned char *fgetstring (FILE * f, long offset, long length){    static unsigned char *str = NULL;    if (str)	free (str);    if ((str = malloc (length + 1)) == NULL) {/* Not essential to translate */	printf(_("Could not allocate memory in fgetstring.\n"));	abort();    }    fseek (f, offset, SEEK_SET);    fread (str, length, 1, f);    str[length] = 0;    return str;}void tiffprintf(const char *str, ...){}struct IFDentry {    short tag;    short fieldtype;    long length;    long valueoffset;    short shortvalue;		/*this is duplicate of the lower numbered				   two bytes of valueoffset, for when valueoffset contains a 				   short value */};/*gets the value of an IFD entry. If the value is small enough   to fit in the valueoffset it gets it from there.   Handles correctly both arrays and single numbers */void getvalue (FILE * fp, struct IFDentry *entry, long *retval, long numtoget, int size){    int j;    if (size == 2 || (entry->fieldtype == 3 && size == 0)) {	TPRINTF (" (short) ");	if (numtoget <= 2) {	    retval[0] = entry->shortvalue;	    if (numtoget == 2)		if (highbytefirst)		    retval[1] = entry->valueoffset && 0xFFFF;		else		    retval[1] = entry->valueoffset >> 16;	} else {	    fseek (fp, entry->valueoffset, SEEK_SET);	    for (j = 0; j < numtoget; j++)		retval[j] = fgetshort (fp);	}    }    if (size == 4 || (entry->fieldtype == 4 && size == 0)) {	TPRINTF (" (long) ");	if (numtoget <= 1) {	    retval[0] = entry->valueoffset;	} else {	    fseek (fp, entry->valueoffset, SEEK_SET);	    for (j = 0; j < numtoget; j++)		retval[j] = fgetlong (fp);	}    }}void tifferror (const char *errmessage){  fprintf(stderr, errmessage); /* OR for the application:  */#ifdef ABORT_ON_ERRORabort();#endif/*    CError (errmessage);  *//********/}/*The return value must be free'd by the calling applicationsince the function malloc's it.loads an uncompressed class G tiff file. This is a greyscale file.Presently, this routine only supports, topdown orientation (Orientation = 1)1 sample per pixel of 8 bits. It uses the greyresponse curve and assumes themonitor to have a linear response.It will interprete PhotometricInterpretation of 0 or 1 (reverse or normal).It can handle multiple strips of any size and reads and displays most of theimportant fields (although it only actually interprets class G fields).rowstart and rowend are used to specify what part of the image to loadfor very large files. If they go past the end of a file. The callingapplication must check the size of the returned data by lookingat the height returned. To load the whole file,set rowstart = 0,rowend = 2^31 - 1.loadgreytiff returns contigous rows, 1 byte/pixel (0-255, black-white),exclusive of rowend. Hence rowend-rowstart rows/scanlines are returned.The first row/scanline is number zero, the last is numbered height - 1.*/unsigned char *loadgreytiff (const char *fname, long *width, long *height, long rowstart, long rowend, float gamma){    FILE *fp = NULL;    int i, j, c;    long IFDoffset;    struct IFDentry *theIFD = NULL;    short numberofIFDentries;    int numinterpreted;    long *greyresponsecurve = NULL;    long *stripbytecounts = NULL, *stripoffsets = NULL;    long numstrips;    float xresolution, yresolution;    long bitspersample[3] =    {8, 8, 8};    long index;    long maxgrey, mingrey;    unsigned char *pic8 = NULL;    unsigned char *pp = NULL;    int numgreylevels = 0;	/*number of entries in the grey response curve array *//*options: */    int photointerp = 1, spp = 1, comptype = 1, fillorder = 1, planarconfig = 1,     orient = 1;    long rps = 0x7FFFFFFF;    if ((fp = fopen (fname, "r")) == NULL) {/* NLS ? */	tifferror ("Cannot open tiff image file.\n");	goto freeall;    }    if ((c = fgetshort (fp)) != 'I' + 256 * 'I')	highbytefirst = 1;    TPRINTF ("00; %c%c\n", (unsigned char) c, (unsigned char) c);    if ((c = fgetshort (fp)) != 42) {	tifferror ("Not a recognised (meaning of life) tiff file.\n");	goto freeall;    }    TPRINTF ("02; %d\n", c);    IFDoffset = fgetlong (fp);    if (IFDoffset < 8) {	tifferror ("Not a recognised tiff file.\n");	goto freeall;    }    TPRINTF ("04; %ld\n", IFDoffset);    if (fseek (fp, IFDoffset, SEEK_SET)) {	tifferror ("Tiff IFD passed end of file.\n");	goto freeall;    }/*now read the Image File Directory (IFD) */    numberofIFDentries = fgetshort (fp);    TPRINTF ("\nNumber IFD entries = %d\n", numberofIFDentries);    if ((theIFD = malloc (numberofIFDentries * sizeof (struct IFDentry))) == NULL) {	tifferror ("Cannot allocate memory for tiff file.\n");	goto freeall;    }    for (i = 0; i < numberofIFDentries; i++) {/*TPRINTF's are for debug *//*      TPRINTF ("\n"); */	theIFD[i].tag = fgetshort (fp);/*      TPRINTF ("IFD %ld;%d\n", IFDoffset + 0 + 12 * i, theIFD[i].tag); */	theIFD[i].fieldtype = fgetshort (fp);/*      TPRINTF ("IFD %ld;%d\n", IFDoffset + 2 + 12 * i, theIFD[i].fieldtype); */	theIFD[i].length = fgetlong (fp);/*      TPRINTF ("IFD %ld;%ld\n", IFDoffset + 4 + 12 * i, theIFD[i].length); */	theIFD[i].valueoffset = fgetlong (fp);/*      TPRINTF ("IFD %ld;%ld\n", IFDoffset + 8 + 12 * i, theIFD[i].valueoffset); */	if (!highbytefirst)	    theIFD[i].shortvalue = (long) theIFD[i].valueoffset & 0xFFFF;	else	    theIFD[i].shortvalue = (long) theIFD[i].valueoffset >> 16;    }/*now loop through the IFD and check tags */    TPRINTF ("\n");    numinterpreted = numberofIFDentries;    for (i = 0; i < numberofIFDentries; i++) {	switch (theIFD[i].tag) {	case 254:	    TPRINTF ("NewSubfileType = %ld\n", theIFD[i].valueoffset);	    break;	case 256:	    getvalue (fp, theIFD + i, width, 1, 0);	    TPRINTF ("Image width = %ld\n", *width);	    break;	case 257:	    getvalue (fp, theIFD + i, height, 1, 0);	    TPRINTF ("Image length = %ld\n", *height);	    break;	case 258:	    getvalue (fp, theIFD + i, bitspersample, theIFD[i].length, 2);	    TPRINTF ("BitsPerSample\n");	    for (j = 0; j < theIFD[i].length; j++)		TPRINTF ("%ld ", bitspersample[j]);	    TPRINTF ("\n");	    break;	case 259:	    TPRINTF ("Compressing is type %d\n", theIFD[i].shortvalue);	    comptype = theIFD[i].shortvalue;	    break;	case 262:	    TPRINTF ("Photometric interpretation = %d\n", (int) theIFD[i].shortvalue);	    photointerp = theIFD[i].shortvalue;	    break;	case 266:	    TPRINTF ("Fillorder = %d\n", theIFD[i].shortvalue);	    fillorder = theIFD[i].shortvalue;	    break;	case 269:	    TPRINTF ("DocumentName: %s\n", fgetstring (fp, theIFD[i].valueoffset, theIFD[i].length));	    break;	case 270:	    TPRINTF ("ImageDescription: %s\n", fgetstring (fp, theIFD[i].valueoffset, theIFD[i].length));	    break;	case 271:	    TPRINTF ("Make: %s\n", fgetstring (fp, theIFD[i].valueoffset, theIFD[i].length));	    break;	case 272:	    TPRINTF ("Model: %s\n", fgetstring (fp, theIFD[i].valueoffset, theIFD[i].length));	    break;	case 273:	    numstrips = theIFD[i].length;	    if ((stripoffsets = malloc (numstrips * sizeof (long))) == NULL) {		tifferror ("Cannot allocate memory for tiff file.\n");		goto freeall;	    }	    getvalue (fp, theIFD + i, stripoffsets, numstrips, 0);	    TPRINTF ("StripOffsets: %ld\n", numstrips);	    for (j = 0; j < numstrips; j++)		TPRINTF ("%ld ", stripoffsets[j]);	    TPRINTF ("\n");	    break;	case 274:	    TPRINTF ("Orientation = %d\n", theIFD[i].shortvalue);	    orient = theIFD[i].shortvalue;	    break;	case 277:	    TPRINTF ("SamplesPerPixel = %d\n", theIFD[i].shortvalue);	    spp = theIFD[i].shortvalue;	    break;	case 278:	    getvalue (fp, theIFD + i, &rps, 1, 0);	    TPRINTF ("RowsPerStrip = %ld\n", rps);	    break;	case 279:	    numstrips = theIFD[i].length;	    if ((stripbytecounts = malloc (numstrips * sizeof (long))) == NULL) {		tifferror ("Cannot allocate memory for tiff file.\n");		goto freeall;	    }	    getvalue (fp, theIFD + i, stripbytecounts, numstrips, 0);	    TPRINTF ("StripByteCounts: %ld\n", numstrips);	    for (j = 0; j < numstrips; j++)		TPRINTF ("%ld ", stripbytecounts[j]);	    TPRINTF ("\n");	    break;	case 282:	    TPRINTF ("Xresolution at %ld\n", theIFD[i].valueoffset);	    fseek (fp, theIFD[i].valueoffset, SEEK_SET);	    xresolution = (float) fgetlong (fp) / fgetlong (fp);	    TPRINTF ("  %f\n", xresolution);	    break;	case 283:	    TPRINTF ("Yresolution at %ld\n", theIFD[i].valueoffset);	    fseek (fp, theIFD[i].valueoffset, SEEK_SET);	    yresolution = (float) fgetlong (fp) / fgetlong (fp);	    TPRINTF ("  %f\n", yresolution);	    break;	case 284:	    TPRINTF ("PlanarConfiguration = %d\n", theIFD[i].shortvalue);	    planarconfig = theIFD[i].shortvalue;	    break;	case 285:	    TPRINTF ("PageName: %s\n", fgetstring (fp, theIFD[i].valueoffset, theIFD[i].length));	    break;	case 290:	    TPRINTF ("GrayResponseUnit = %d\n", theIFD[i].shortvalue);	    break;	case 291:	    TPRINTF ("GrayResponseCurve at %ld, length %ld\n", theIFD[i].valueoffset, theIFD[i].length);	    numgreylevels = theIFD[i].length;	    if ((greyresponsecurve = malloc (numgreylevels * sizeof (long))) == NULL) {abort();		tifferror ("Cannot allocate memory for tiff file.\n");		goto freeall;	    }	    getvalue (fp, theIFD + i, greyresponsecurve, numgreylevels, 2);	    for (j = 0; j < numgreylevels; j++)		TPRINTF ("%ld ", greyresponsecurve[j]);	    TPRINTF ("\n");	    break;	case 296:	    TPRINTF ("ResolutionUnit = %d\n", theIFD[i].shortvalue);	    break;	case 301:	    TPRINTF ("Color response curve present at %ld, length %ld\n", theIFD[i].valueoffset, theIFD[i].length);	    break;	case 320:	    TPRINTF ("Colormap present at %ld\n", theIFD[i].valueoffset);	    break;	default:	    TPRINTF ("Tag %d unread.\n", theIFD[i].tag);	    numinterpreted--;	}    }    TPRINTF ("Number of fields interpreted = %d\n\n", numinterpreted);/*now that we've read most of what we might want to know, we can't   scratch all images that are too tedious to interpret. What we   are looking for is a class G greyscale with no compression */    if (spp != 1 || bitspersample[0] != 8 || comptype != 1 || fillorder != 1	|| orient != 1) {	tifferror ("This kind of tiff file is not supported.\n");	goto freeall;    }/*printf("rowstart = %ld, rowend = %ld.\n", rowstart, rowend);*//*check that rowstart and rowend are ok*/    if(rowstart > rowend) {	tifferror("Tiff called with rowstart > rowend.\n");	goto freeall;    }    if(rowstart > *height) rowstart = *height;     if(rowstart < 0) rowstart = 0;    if(rowend > *height) rowend = *height;/*printf("width = %ld\n", *width);printf("changeto rowstart = %ld, rowend = %ld.\n", rowstart, rowend);*/    if ((  pic8 = malloc ((rowend-rowstart) * *width + 1)  ) == NULL) {	tifferror ("Cannot allocate memory for tiff file.\n");	goto freeall;    }    index = 0;    if(gamma == 0) gamma = 1.5;    maxgrey = 0; mingrey = 1 << 30;    if(numgreylevels) {	for(i=0;i<numgreylevels;i++) {	    maxgrey = max(maxgrey, greyresponsecurve[i]);	    mingrey = min(mingrey, greyresponsecurve[i]);	}	for(i=0;i<numgreylevels;i++)	    greyresponsecurve[i] = (double) 255 * pow((double) 1 - (double) ((double) greyresponsecurve[i] - mingrey) / (maxgrey - mingrey), (double) 1 / gamma);    }    if(rowend > rowstart)        for(i=rowstart;i<rowend;i++) {		/*:loop through all rows*/	pp = fgetstring (fp, stripoffsets[i/rps] + (i%rps) * *width, *width);		/*:load the row*//*OR  pp = fdecodeLZW (fp, stripoffsets[i/rps] + (i%rps) * *width, *width); <-- for later*/	if(numgreylevels) {	    for(j=0;j<*width;j++)		pic8[index++] = greyresponsecurve[pp[j]];	} else {	    if(photointerp == 1)		for(j=0;j<*width;j++)		    pic8[index++] = pp[j];	    else		for(j=0;j<*width;j++)		    pic8[index++] = 255 - pp[j];	}    if(index > (rowend-rowstart) * *width) {printf("Index past end of array\n\n");abort();}    }  freeall:    if (greyresponsecurve)	free (greyresponsecurve);    if (stripbytecounts)	free (stripbytecounts);    if (stripoffsets)	free (stripoffsets);    if (theIFD)	free (theIFD);    if(fp) fclose(fp);    return pic8;}

⌨️ 快捷键说明

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