Ejemplo n.º 1
0
int
main(int argc, char* argv[])
{
	TIFF *in, *out;
	int c;
	extern int optind;
	extern char *optarg;

	while ((c = getopt(argc, argv, "c:r:t:bn8")) != -1)
		switch (c) {
			case 'b':
				process_by_block = 1;
				break;

			case 'c':
				if (streq(optarg, "none"))
					compression = COMPRESSION_NONE;
				else if (streq(optarg, "packbits"))
					compression = COMPRESSION_PACKBITS;
				else if (streq(optarg, "lzw"))
					compression = COMPRESSION_LZW;
				else if (streq(optarg, "jpeg"))
					compression = COMPRESSION_JPEG;
				else if (streq(optarg, "zip"))
					compression = COMPRESSION_DEFLATE;
				else
					usage(-1);
				break;

			case 'r':
				rowsperstrip = atoi(optarg);
				break;

			case 't':
				rowsperstrip = atoi(optarg);
				break;

			case 'n':
				no_alpha = 1;
				break;

			case '8':
				bigtiff_output = 1;
				break;

			case '?':
				usage(0);
				/*NOTREACHED*/
		}

	if (argc - optind < 2)
		usage(-1);

	out = TIFFOpen(argv[argc-1], bigtiff_output?"w8":"w");
	if (out == NULL)
		return (-2);

	for (; optind < argc-1; optind++) {
		in = TIFFOpen(argv[optind], "r");
		if (in != NULL) {
			do {
				if (!tiffcvt(in, out) ||
				    !TIFFWriteDirectory(out)) {
					(void) TIFFClose(out);
					(void) TIFFClose(in);
					return (1);
				}
			} while (TIFFReadDirectory(in));
			(void) TIFFClose(in);
		}
	}
	(void) TIFFClose(out);
	return (0);
}
Ejemplo n.º 2
0
TIFF*
TIFFClientOpen(
	const char* name, const char* mode,
	thandle_t clientdata,
	TIFFReadWriteProc readproc,
	TIFFReadWriteProc writeproc,
	TIFFSeekProc seekproc,
	TIFFCloseProc closeproc,
	TIFFSizeProc sizeproc,
	TIFFMapFileProc mapproc,
	TIFFUnmapFileProc unmapproc
)
{
	static const char module[] = "TIFFClientOpen";
	TIFF *tif;
	int m, bigendian;

	m = _TIFFgetMode(mode, module);
	if (m == -1)
		goto bad2;
	tif = (TIFF *)_TIFFmalloc(sizeof (TIFF) + strlen(name) + 1);
	if (tif == NULL) {
		TIFFError(module, "%s: Out of memory (TIFF structure)", name);
		goto bad2;
	}
	_TIFFmemset(tif, 0, sizeof (*tif));
	tif->tif_name = (char *)tif + sizeof (TIFF);
	strcpy(tif->tif_name, name);
	tif->tif_mode = m &~ (O_CREAT|O_TRUNC);
	tif->tif_curdir = (tdir_t) -1;		/* non-existent directory */
	tif->tif_curoff = 0;
	tif->tif_curstrip = (tstrip_t) -1;	/* invalid strip */
	tif->tif_row = (uint32)-1;		/* read/write pre-increment */
	tif->tif_clientdata = clientdata;
	tif->tif_readproc = readproc;
	tif->tif_writeproc = writeproc;
	tif->tif_seekproc = seekproc;
	tif->tif_closeproc = closeproc;
	tif->tif_sizeproc = sizeproc;
	tif->tif_mapproc = mapproc;
	tif->tif_unmapproc = unmapproc;

	{ union { int32 i; char c[4]; } u; u.i = 1; bigendian = u.c[0] == 0; }
#ifdef ENDIANHACK_SUPPORT
	/*
	 * Numerous vendors, typically on the PC, do not correctly
	 * support TIFF; they only support the Intel little-endian
	 * byte order.  If this hack is enabled, then applications
	 * can open a file with a specific byte-order by specifying
	 * either "wl" (for litt-endian byte order) or "wb" for
	 * (big-endian byte order).  This support is not configured
	 * by default because it supports the violation of the TIFF
	 * spec that says that readers *MUST* support both byte orders.
	 *
	 * It is strongly recommended that you not use this feature
	 * except to deal with busted apps that write invalid TIFF.
	 * And even in those cases you should bang on the vendors to
	 * fix their software.
	 */
	if ((m&O_CREAT) &&
	    ((bigendian && mode[1] == 'l') || (!bigendian && mode[1] == 'b')))
		tif->tif_flags |= TIFF_SWAB;
#endif
	/*
	 * Read in TIFF header.
	 */
	if (!ReadOK(tif, &tif->tif_header, sizeof (TIFFHeader))) {
		if (tif->tif_mode == O_RDONLY) {
			TIFFError(name, "Cannot read TIFF header");
			goto bad;
		}
		/*
		 * Setup header and write.
		 */
		tif->tif_header.tiff_magic = tif->tif_flags & TIFF_SWAB
		    ? (bigendian ? TIFF_LITTLEENDIAN : TIFF_BIGENDIAN)
		    : (bigendian ? TIFF_BIGENDIAN : TIFF_LITTLEENDIAN);
		tif->tif_header.tiff_version = TIFF_VERSION;
		tif->tif_header.tiff_diroff = 0;	/* filled in later */
		if (!WriteOK(tif, &tif->tif_header, sizeof (TIFFHeader))) {
			TIFFError(name, "Error writing TIFF header");
			goto bad;
		}
		/*
		 * Setup the byte order handling.
		 */
		TIFFInitOrder(tif, tif->tif_header.tiff_magic, bigendian);
		/*
		 * Setup default directory.
		 */
		if (!TIFFDefaultDirectory(tif))
			goto bad;
		tif->tif_diroff = 0;
		return (tif);
	}
	/*
	 * Setup the byte order handling.
	 */
	if (tif->tif_header.tiff_magic != TIFF_BIGENDIAN &&
	    tif->tif_header.tiff_magic != TIFF_LITTLEENDIAN) {
		TIFFError(name,  "Not a TIFF file, bad magic number %d (0x%x)",
		    tif->tif_header.tiff_magic,
		    tif->tif_header.tiff_magic);
		goto bad;
	}
	TIFFInitOrder(tif, tif->tif_header.tiff_magic, bigendian);
	/*
	 * Swap header if required.
	 */
	if (tif->tif_flags & TIFF_SWAB) {
		TIFFSwabShort(&tif->tif_header.tiff_version);
		TIFFSwabLong(&tif->tif_header.tiff_diroff);
	}
	/*
	 * Now check version (if needed, it's been byte-swapped).
	 * Note that this isn't actually a version number, it's a
	 * magic number that doesn't change (stupid).
	 */
	if (tif->tif_header.tiff_version != TIFF_VERSION) {
		TIFFError(name,
		    "Not a TIFF file, bad version number %d (0x%x)",
		    tif->tif_header.tiff_version,
		    tif->tif_header.tiff_version); 
		goto bad;
	}
	tif->tif_flags |= TIFF_MYBUFFER;
	tif->tif_rawcp = tif->tif_rawdata = 0;
	tif->tif_rawdatasize = 0;
	/*
	 * Setup initial directory.
	 */
	switch (mode[0]) {
	case 'r':
		tif->tif_nextdiroff = tif->tif_header.tiff_diroff;
		if (TIFFMapFileContents(tif, (tdata_t*) &tif->tif_base, &tif->tif_size))
			tif->tif_flags |= TIFF_MAPPED;
		if (TIFFReadDirectory(tif)) {
			tif->tif_rawcc = -1;
			tif->tif_flags |= TIFF_BUFFERSETUP;
			return (tif);
		}
		break;
	case 'a':
		/*
		 * New directories are automatically append
		 * to the end of the directory chain when they
		 * are written out (see TIFFWriteDirectory).
		 */
		if (!TIFFDefaultDirectory(tif))
			goto bad;
		return (tif);
	}
bad:
	tif->tif_mode = O_RDONLY;	/* XXX avoid flush */
	TIFFClose(tif);
	return ((TIFF*)0);
bad2:
	(void) (*closeproc)(clientdata);
	return ((TIFF*)0);
}
Ejemplo n.º 3
0
// Internal function used to load the Tiff.
ILboolean iLoadTiffInternal()
{
	TIFF		*tif;
	uint16	w, h, d, photometric, planarconfig;
	uint16	samplesperpixel, bitspersample, *sampleinfo, extrasamples;
	ILubyte		*pImageData;
	ILuint		i, ProfileLen, DirCount = 0;
	ILvoid		*Buffer;
	ILimage		*Image;
	ILushort	si;
//TIFFRGBAImage img;
//char emsg[1024];


	if (iCurImage == NULL) {
		ilSetError(IL_ILLEGAL_OPERATION);
		return IL_FALSE;
	}

	TIFFSetWarningHandler(NULL);
	TIFFSetErrorHandler(NULL);

	//for debugging only
	//TIFFSetWarningHandler(warningHandler);
	//TIFFSetErrorHandler(errorHandler);

		tif = iTIFFOpen("r");
		if (tif == NULL) {
		ilSetError(IL_COULD_NOT_OPEN_FILE);
		return IL_FALSE;
	}

	do {
		DirCount++;
	} while (TIFFReadDirectory(tif));

/*
	if (!ilTexImage(1, 1, 1, 1, IL_RGBA, IL_UNSIGNED_BYTE, NULL)) {
		TIFFClose(tif);
		return IL_FALSE;
	}
	Image = iCurImage;
	for (i = 1; i < DirCount; i++) {
		Image->Next = ilNewImage(1, 1, 1, 1, 1);
		if (Image->Next == NULL) {
			TIFFClose(tif);
			return IL_FALSE;
		}
		Image = Image->Next;
	}
	iCurImage->NumNext = DirCount - 1;
*/
	Image = NULL;
	for (i = 0; i < DirCount; i++) {
		TIFFSetDirectory(tif, (tdir_t)i);
		TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &w);
		TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &h);
		TIFFGetFieldDefaulted(tif, TIFFTAG_IMAGEDEPTH, &d);
		TIFFGetFieldDefaulted(tif, TIFFTAG_SAMPLESPERPIXEL, &samplesperpixel);
		TIFFGetFieldDefaulted(tif, TIFFTAG_SAMPLESPERPIXEL, &bitspersample);
		TIFFGetFieldDefaulted(tif, TIFFTAG_EXTRASAMPLES, &extrasamples, &sampleinfo);

		//added 2003-08-31
		//1 bpp tiffs are not neccessarily greyscale, they can
		//have a palette (photometric == 3)...get this information
		TIFFGetFieldDefaulted(tif, TIFFTAG_PHOTOMETRIC, &photometric);
		TIFFGetFieldDefaulted(tif, TIFFTAG_PLANARCONFIG, &planarconfig);

		if (samplesperpixel - extrasamples == 1) { //luminance or palette
			ILubyte* strip;
			tsize_t stripsize;
			ILuint y;
			uint32 rowsperstrip;

			if(!Image) {
				if(!ilTexImage(w, h, 1, 1, IL_LUMINANCE, IL_UNSIGNED_BYTE, NULL)) {
					TIFFClose(tif);
					return IL_FALSE;
				}
				iCurImage->NumNext = 0;
				Image = iCurImage;
			}
			else {
				Image->Next = ilNewImage(w, h, 1, 1, 1);
				if(Image->Next == NULL) {
					TIFFClose(tif);
					return IL_FALSE;
				}
				Image = Image->Next;
				iCurImage->NumNext++;
			}

			TIFFGetField(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip);
			stripsize = TIFFStripSize(tif);

			strip = ialloc(stripsize);

			for(y = 0; y < h; y += rowsperstrip) {
				//if(y + rowsperstrip > h)
				//	stripsize = (stripsize*(h - y))/rowsperstrip;
				if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, y, 0), strip, stripsize) == -1) {
					ilSetError(IL_LIB_TIFF_ERROR);
					ifree(strip);
					TIFFClose(tif);
					return IL_FALSE;
				}
			}

			ifree(strip);
		}
		else {//rgb or rgba

			if(!Image) {
				if(!ilTexImage(w, h, 1, 4, IL_RGBA, IL_UNSIGNED_BYTE, NULL)) {
					TIFFClose(tif);
					return IL_FALSE;
				}
				iCurImage->NumNext = 0;
				Image = iCurImage;
			}
			else {
				Image->Next = ilNewImage(w, h, 1, 4, 1);
				if(Image->Next == NULL) {
					TIFFClose(tif);
					return IL_FALSE;
				}
				Image = Image->Next;
				iCurImage->NumNext++;
			}

			if (samplesperpixel == 4) {
				TIFFGetFieldDefaulted(tif, TIFFTAG_EXTRASAMPLES, &extrasamples, &sampleinfo);
				if (!sampleinfo || sampleinfo[0] == EXTRASAMPLE_UNSPECIFIED) {
					si = EXTRASAMPLE_ASSOCALPHA;
					TIFFSetField(tif, TIFFTAG_EXTRASAMPLES, 1, &si);
				}
			}
/*
			if (!ilResizeImage(Image, Image->Width, Image->Height, 1, 4, 1)) {
				TIFFClose(tif);
				return IL_FALSE;
			}*/
			Image->Format = IL_RGBA;
			Image->Type = IL_UNSIGNED_BYTE;

			// Siigron: added u_long cast to shut up compiler warning
			//2003-08-31: changed flag from 1 (exit on error) to 0 (keep decoding)
			//this lets me view text.tif, but can give crashes with unsupported
			//tiffs...
			//2003-09-04: keep flag 1 for official version for now
			if (!TIFFReadRGBAImage(tif, Image->Width, Image->Height, (uint32*)Image->Data, 1)) {
				TIFFClose(tif);
				ilSetError(IL_LIB_TIFF_ERROR);
				return IL_FALSE;
			}
		} //else rgb or rgba

		if (TIFFGetField(tif, TIFFTAG_ICCPROFILE, &ProfileLen, &Buffer)) {
			if (Image->Profile && Image->ProfileSize)
				ifree(Image->Profile);
			Image->Profile = (ILubyte*)ialloc(ProfileLen);
			if (Image->Profile == NULL) {
				TIFFClose(tif);
				return IL_FALSE;
			}

			memcpy(Image->Profile, Buffer, ProfileLen);
			Image->ProfileSize = ProfileLen;

			//removed on 2003-08-24 as explained in bug 579574 on sourceforge
			//_TIFFfree(Buffer);
		}

		Image->Origin = IL_ORIGIN_LOWER_LEFT;  // eiu...dunno if this is right
/*
		Image = Image->Next;
		if (Image == NULL)  // Should never happen except when we reach the end, but check anyway.
			break;*/
	} //for tiff directories

	//TODO: put switch into the loop??
	switch (samplesperpixel)
	{
		case 1:
			//added 2003-08-31 to keep palettized tiffs colored
			/*
			if(photometric != 3)
				ilConvertImage(IL_LUMINANCE, IL_UNSIGNED_BYTE);
			else //strip alpha as tiff supports no alpha palettes
				ilConvertImage(IL_RGB, IL_UNSIGNED_BYTE);*/
			break;

		case 3:
			//TODO: why the ifdef??
#ifdef __LITTLE_ENDIAN__
			ilConvertImage(IL_RGB, IL_UNSIGNED_BYTE);
#endif			
			break; 

		case 4:
			pImageData = iCurImage->Data;
//removed on 2003-08-26...why was this here? libtiff should and does
//take care of these things???
/*			
			//invert alpha
			#ifdef __LITTLE_ENDIAN__
			pImageData += 3;
#endif			
			for (i = iCurImage->Width * iCurImage->Height; i > 0; i--) {
				*pImageData ^= 255;
				pImageData += 4;
			}
*/
			break;
	}

	TIFFClose(tif);

	ilFixImage();

	return IL_TRUE;
}
Ejemplo n.º 4
0
// Internal function used to load the Tiff.
ILboolean iLoadTiffInternal()
{
	TIFF		*tif;
	uint16	w, h, d, photometric, planarconfig, orientation;
	uint16	samplesperpixel, bitspersample, *sampleinfo, extrasamples;
	uint32	linesize, tilewidth, tilelength;
	ILubyte		*pImageData;
	ILuint		i, ProfileLen, DirCount = 0;
	ILvoid		*Buffer;
	ILimage		*Image, *TempImage;
	ILushort	si;
//TIFFRGBAImage img;
//char emsg[1024];


	if (iCurImage == NULL) {
		ilSetError(IL_ILLEGAL_OPERATION);
		return IL_FALSE;
	}

	TIFFSetWarningHandler(NULL);
	TIFFSetErrorHandler(NULL);

	//for debugging only
	//TIFFSetWarningHandler(warningHandler);
	//TIFFSetErrorHandler(errorHandler);

	tif = iTIFFOpen("r");
	if (tif == NULL) {
		ilSetError(IL_COULD_NOT_OPEN_FILE);
		return IL_FALSE;
	}

	do {
		DirCount++;
	} while (TIFFReadDirectory(tif));

/*
	if (!ilTexImage(1, 1, 1, 1, IL_RGBA, IL_UNSIGNED_BYTE, NULL)) {
		TIFFClose(tif);
		return IL_FALSE;
	}
	Image = iCurImage;
	for (i = 1; i < DirCount; i++) {
		Image->Next = ilNewImage(1, 1, 1, 1, 1);
		if (Image->Next == NULL) {
			TIFFClose(tif);
			return IL_FALSE;
		}
		Image = Image->Next;
	}
	iCurImage->NumNext = DirCount - 1;
*/
	Image = NULL;
	for (i = 0; i < DirCount; i++) {
		TIFFSetDirectory(tif, (tdir_t)i);
		TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &w);
		TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &h);
		TIFFGetFieldDefaulted(tif, TIFFTAG_IMAGEDEPTH, &d); //TODO: d is ignored...
		TIFFGetFieldDefaulted(tif, TIFFTAG_SAMPLESPERPIXEL, &samplesperpixel);
		TIFFGetFieldDefaulted(tif, TIFFTAG_BITSPERSAMPLE, &bitspersample);
		TIFFGetFieldDefaulted(tif, TIFFTAG_EXTRASAMPLES, &extrasamples, &sampleinfo);
		TIFFGetFieldDefaulted(tif, TIFFTAG_ORIENTATION, &orientation);
		linesize = TIFFScanlineSize(tif);

		
		//added 2003-08-31
		//1 bpp tiffs are not neccessarily greyscale, they can
		//have a palette (photometric == 3)...get this information
		TIFFGetFieldDefaulted(tif, TIFFTAG_PHOTOMETRIC, &photometric);
		TIFFGetFieldDefaulted(tif, TIFFTAG_PLANARCONFIG, &planarconfig);
#if 1
		//special-case code for frequent data cases that may be read more
		//efficiently than with the TIFFReadRGBAImage() interface.

		//added 2004-05-12
		//Get tile sizes and use TIFFReadRGBAImage() for tiled images for now
		tilewidth = w; tilelength = h;
		TIFFGetFieldDefaulted(tif, TIFFTAG_TILEWIDTH, &tilewidth);
		TIFFGetFieldDefaulted(tif, TIFFTAG_TILELENGTH, &tilelength);


		if (extrasamples == 0 && samplesperpixel == 1  //luminance or palette
			&& (bitspersample == 8 || bitspersample == 1)
			&& (photometric == PHOTOMETRIC_MINISWHITE
				|| photometric == PHOTOMETRIC_MINISBLACK
				|| photometric == PHOTOMETRIC_PALETTE)
			&& (orientation == ORIENTATION_TOPLEFT || orientation == ORIENTATION_BOTLEFT)
			&& tilewidth == w && tilelength == h
			) {
			ILubyte* strip;
			tsize_t stripsize;
			ILuint y;
			uint32 rowsperstrip, j, linesread;

			//TODO: 1 bit/pixel images should not be stored as 8 bits...
			//(-> add new format)
			if (!Image) {
				int type = IL_UNSIGNED_BYTE;
				if ( bitspersample == 16) type = IL_UNSIGNED_SHORT;
				if(!ilTexImage(w, h, 1, 1, IL_LUMINANCE, type, NULL)) {
					TIFFClose(tif);
					return IL_FALSE;
				}
				iCurImage->NumNext = 0;
				Image = iCurImage;
			}
			else {
				Image->Next = ilNewImage(w, h, 1, 1, 1);
				if(Image->Next == NULL) {
					TIFFClose(tif);
					return IL_FALSE;
				}
				Image = Image->Next;
				iCurImage->NumNext++;
			}

			if (photometric == PHOTOMETRIC_PALETTE) { //read palette
				uint16 *red, *green, *blue;
				ILboolean is16bitpalette = IL_FALSE;
				ILubyte *entry;
				uint32 count = 1 << bitspersample, j;

				TIFFGetField(tif, TIFFTAG_COLORMAP, &red, &green, &blue);

				Image->Format = IL_COLOUR_INDEX;
				Image->Pal.PalSize = (count)*3;
				Image->Pal.PalType = IL_PAL_RGB24;
				Image->Pal.Palette = ialloc(Image->Pal.PalSize);
				entry = Image->Pal.Palette;
				for (j = 0; j < count; ++j) {
					entry[0] = (ILubyte)(red[j] >> 8);
					entry[1] = (ILubyte)(green[j] >> 8);
					entry[2] = (ILubyte)(blue[j] >> 8);

					entry += 3;
				}
			}

			TIFFGetField(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip);
			stripsize = TIFFStripSize(tif);

			strip = ialloc(stripsize);

			if (bitspersample == 8) {
				ILubyte *dat = Image->Data;
				for (y = 0; y < h; y += rowsperstrip) {
					//the last strip may contain less data if the image
					//height is not evenly divisible by rowsperstrip
					if (y + rowsperstrip > h) {
						stripsize = linesize*(h - y);
						linesread = h - y;
					}
					else
						linesread = rowsperstrip;

					if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, y, 0), strip, stripsize) == -1) {
						ilSetError(IL_LIB_TIFF_ERROR);
						ifree(strip);
						TIFFClose(tif);
						return IL_FALSE;
					}

					if (photometric == PHOTOMETRIC_MINISWHITE) { //invert channel
						uint32 k, t2;
						for (j = 0; j < linesread; ++j) {
							t2 = j*linesize;
							for (k = 0; k < w; ++k)
								dat[k] = ~strip[t2 + k];
							dat += w;
						}
					}
					else
						for(j = 0; j < linesread; ++j)
							memcpy(&Image->Data[(y + j)*w], &strip[j*linesize], w);
				}
			}
			else if (bitspersample == 1) {
				//TODO: add a native format to devil, so we don't have to
				//unpack the values here
				ILubyte mask, curr, *dat = Image->Data;
				uint32 k, sx, t2;
				for (y = 0; y < h; y += rowsperstrip) {
					//the last strip may contain less data if the image
					//height is not evenly divisible by rowsperstrip
					if (y + rowsperstrip > h) {
						stripsize = linesize*(h - y);
						linesread = h - y;
					}
					else
						linesread = rowsperstrip;

					if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, y, 0), strip, stripsize) == -1) {
						ilSetError(IL_LIB_TIFF_ERROR);
						ifree(strip);
						TIFFClose(tif);
						return IL_FALSE;
					}

					for (j = 0; j < linesread; ++j) {
						k = 0;
						sx = 0;
						t2 = j*linesize;
						while (k < w) {
							curr = strip[t2 + sx];
							if (photometric == PHOTOMETRIC_MINISWHITE)
								curr = ~curr;
							for (mask = 0x80; mask != 0 && k < w; mask >>= 1){
								if((curr & mask) != 0)
									dat[k] = 255;
								else
									dat[k] = 0;
								++k;
							}
							++sx;
						}
						dat += w;
					}
				}
			}
Ejemplo n.º 5
0
TIFF*
TIFFClientOpen(
	const char* name, const char* mode,
	thandle_t clientdata,
	TIFFReadWriteProc readproc,
	TIFFReadWriteProc writeproc,
	TIFFSeekProc seekproc,
	TIFFCloseProc closeproc,
	TIFFSizeProc sizeproc,
	TIFFMapFileProc mapproc,
	TIFFUnmapFileProc unmapproc
)
{
	static const char module[] = "TIFFClientOpen";
	TIFF *tif;
	int m, bigendian;
	const char* cp;

	m = _TIFFgetMode(mode, module);
	if (m == -1)
		goto bad2;
	tif = (TIFF *)_TIFFmalloc(sizeof (TIFF) + strlen(name) + 1);
	if (tif == NULL) {
		TIFFError(module, "%s: Out of memory (TIFF structure)", name);
		goto bad2;
	}
	_TIFFmemset(tif, 0, sizeof (*tif));
	tif->tif_name = (char *)tif + sizeof (TIFF);
	strcpy(tif->tif_name, name);
	tif->tif_mode = m &~ (O_CREAT|O_TRUNC);
	tif->tif_curdir = (tdir_t) -1;		/* non-existent directory */
	tif->tif_curoff = 0;
	tif->tif_curstrip = (tstrip_t) -1;	/* invalid strip */
	tif->tif_row = (uint32) -1;		/* read/write pre-increment */
	tif->tif_clientdata = clientdata;
	tif->tif_readproc = readproc;
	tif->tif_writeproc = writeproc;
	tif->tif_seekproc = seekproc;
	tif->tif_closeproc = closeproc;
	tif->tif_sizeproc = sizeproc;
	tif->tif_mapproc = mapproc;
	tif->tif_unmapproc = unmapproc;
	_TIFFSetDefaultCompressionState(tif);	/* setup default state */
	/*
	 * Default is to return data MSB2LSB and enable the
	 * use of memory-mapped files and strip chopping when
	 * a file is opened read-only.
	 */
	tif->tif_flags = FILLORDER_MSB2LSB;
	if (m == O_RDONLY )
            tif->tif_flags |= TIFF_MAPPED;

#ifdef STRIPCHOP_DEFAULT
	if (m == O_RDONLY || m == O_RDWR)
		tif->tif_flags |= STRIPCHOP_DEFAULT;
#endif

	{ union { int32 i; char c[4]; } u; u.i = 1; bigendian = u.c[0] == 0; }
	/*
	 * Process library-specific flags in the open mode string.
	 * The following flags may be used to control intrinsic library
	 * behaviour that may or may not be desirable (usually for
	 * compatibility with some application that claims to support
	 * TIFF but only supports some braindead idea of what the
	 * vendor thinks TIFF is):
	 *
	 * 'l'		use little-endian byte order for creating a file
	 * 'b'		use big-endian byte order for creating a file
	 * 'L'		read/write information using LSB2MSB bit order
	 * 'B'		read/write information using MSB2LSB bit order
	 * 'H'		read/write information using host bit order
	 * 'M'		enable use of memory-mapped files when supported
	 * 'm'		disable use of memory-mapped files
	 * 'C'		enable strip chopping support when reading
	 * 'c'		disable strip chopping support
	 *
	 * The use of the 'l' and 'b' flags is strongly discouraged.
	 * These flags are provided solely because numerous vendors,
	 * typically on the PC, do not correctly support TIFF; they
	 * only support the Intel little-endian byte order.  This
	 * support is not configured by default because it supports
	 * the violation of the TIFF spec that says that readers *MUST*
	 * support both byte orders.  It is strongly recommended that
	 * you not use this feature except to deal with busted apps
	 * that write invalid TIFF.  And even in those cases you should
	 * bang on the vendors to fix their software.
	 *
	 * The 'L', 'B', and 'H' flags are intended for applications
	 * that can optimize operations on data by using a particular
	 * bit order.  By default the library returns data in MSB2LSB
	 * bit order for compatibiltiy with older versions of this
	 * library.  Returning data in the bit order of the native cpu
	 * makes the most sense but also requires applications to check
	 * the value of the FillOrder tag; something they probabyl do
	 * not do right now.
	 *
	 * The 'M' and 'm' flags are provided because some virtual memory
	 * systems exhibit poor behaviour when large images are mapped.
	 * These options permit clients to control the use of memory-mapped
	 * files on a per-file basis.
	 *
	 * The 'C' and 'c' flags are provided because the library support
	 * for chopping up large strips into multiple smaller strips is not
	 * application-transparent and as such can cause problems.  The 'c'
	 * option permits applications that only want to look at the tags,
	 * for example, to get the unadulterated TIFF tag information.
	 */
	for (cp = mode; *cp; cp++)
		switch (*cp) {
		case 'b':
			if ((m&O_CREAT) && !bigendian)
				tif->tif_flags |= TIFF_SWAB;
			break;
		case 'l':
			if ((m&O_CREAT) && bigendian)
				tif->tif_flags |= TIFF_SWAB;
			break;
		case 'B':
			tif->tif_flags = (tif->tif_flags &~ TIFF_FILLORDER) |
			    FILLORDER_MSB2LSB;
			break;
		case 'L':
			tif->tif_flags = (tif->tif_flags &~ TIFF_FILLORDER) |
			    FILLORDER_LSB2MSB;
			break;
		case 'H':
			tif->tif_flags = (tif->tif_flags &~ TIFF_FILLORDER) |
			    HOST_FILLORDER;
			break;
		case 'M':
			if (m == O_RDONLY)
				tif->tif_flags |= TIFF_MAPPED;
			break;
		case 'm':
			if (m == O_RDONLY)
				tif->tif_flags &= ~TIFF_MAPPED;
			break;
		case 'C':
			if (m == O_RDONLY)
				tif->tif_flags |= TIFF_STRIPCHOP;
			break;
		case 'c':
			if (m == O_RDONLY)
				tif->tif_flags &= ~TIFF_STRIPCHOP;
			break;
		}
	/*
	 * Read in TIFF header.
	 */
	if (!ReadOK(tif, &tif->tif_header, sizeof (TIFFHeader))) {
		if (tif->tif_mode == O_RDONLY) {
			TIFFError(name, "Cannot read TIFF header");
			goto bad;
		}
		/*
		 * Setup header and write.
		 */
		tif->tif_header.tiff_magic = tif->tif_flags & TIFF_SWAB
		    ? (bigendian ? TIFF_LITTLEENDIAN : TIFF_BIGENDIAN)
		    : (bigendian ? TIFF_BIGENDIAN : TIFF_LITTLEENDIAN);
		tif->tif_header.tiff_version = TIFF_VERSION;
		if (tif->tif_flags & TIFF_SWAB)
			TIFFSwabShort(&tif->tif_header.tiff_version);
		tif->tif_header.tiff_diroff = 0;	/* filled in later */

                /*
                 * This seek shouldn't be necessary, but I have had some
                 * crazy problems with a failed fseek() on Solaris leaving
                 * the current file pointer out of whack when an fwrite()
                 * is done. 
                 */
                TIFFSeekFile( tif, 0, SEEK_SET );

		if (!WriteOK(tif, &tif->tif_header, sizeof (TIFFHeader))) {
			TIFFError(name, "Error writing TIFF header");
			goto bad;
		}
		/*
		 * Setup the byte order handling.
		 */
		TIFFInitOrder(tif, tif->tif_header.tiff_magic, bigendian);
		/*
		 * Setup default directory.
		 */
		if (!TIFFDefaultDirectory(tif))
			goto bad;
		tif->tif_diroff = 0;
		return (tif);
	}
	/*
	 * Setup the byte order handling.
	 */
	if (tif->tif_header.tiff_magic != TIFF_BIGENDIAN &&
	    tif->tif_header.tiff_magic != TIFF_LITTLEENDIAN) {
		TIFFError(name,  "Not a TIFF file, bad magic number %d (0x%x)",
		    tif->tif_header.tiff_magic,
		    tif->tif_header.tiff_magic);
		goto bad;
	}
	TIFFInitOrder(tif, tif->tif_header.tiff_magic, bigendian);
	/*
	 * Swap header if required.
	 */
	if (tif->tif_flags & TIFF_SWAB) {
		TIFFSwabShort(&tif->tif_header.tiff_version);
		TIFFSwabLong(&tif->tif_header.tiff_diroff);
	}
	/*
	 * Now check version (if needed, it's been byte-swapped).
	 * Note that this isn't actually a version number, it's a
	 * magic number that doesn't change (stupid).
	 */
	if (tif->tif_header.tiff_version != TIFF_VERSION) {
		TIFFError(name,
		    "Not a TIFF file, bad version number %d (0x%x)",
		    tif->tif_header.tiff_version,
		    tif->tif_header.tiff_version); 
		goto bad;
	}
	tif->tif_flags |= TIFF_MYBUFFER;
	tif->tif_rawcp = tif->tif_rawdata = 0;
	tif->tif_rawdatasize = 0;
	/*
	 * Setup initial directory.
	 */
	switch (mode[0]) {
	case 'r':
		tif->tif_nextdiroff = tif->tif_header.tiff_diroff;
		/*
		 * Try to use a memory-mapped file if the client
		 * has not explicitly suppressed usage with the
		 * 'm' flag in the open mode (see above).
		 */
		if ((tif->tif_flags & TIFF_MAPPED) &&
	!TIFFMapFileContents(tif, (tdata_t*) &tif->tif_base, &tif->tif_size))
			tif->tif_flags &= ~TIFF_MAPPED;
		if (TIFFReadDirectory(tif)) {
                        if( m != O_RDONLY 
                          && tif->tif_dir.td_compression != COMPRESSION_NONE )
                        {
                            TIFFError( name, 
                                       "Can't open a compressed TIFF file"
                                       " with compression for update." );
                            goto bad;
                        }
			tif->tif_rawcc = -1;
			tif->tif_flags |= TIFF_BUFFERSETUP;
			return (tif);
		}
		break;
	case 'a':
		/*
		 * New directories are automatically append
		 * to the end of the directory chain when they
		 * are written out (see TIFFWriteDirectory).
		 */
		if (!TIFFDefaultDirectory(tif))
			goto bad;
		return (tif);
	}
bad:
	tif->tif_mode = O_RDONLY;	/* XXX avoid flush */
	TIFFClose(tif);
	return ((TIFF*)0);
bad2:
	(void) (*closeproc)(clientdata);
	return ((TIFF*)0);
}
Ejemplo n.º 6
0
int
main(int argc, char* argv[])
{
	TIFF *in, *out;
	int c;
	extern int optind;
	extern char *optarg;

	while ((c = getopt(argc, argv, "c:h:r:v:z")) != -1)
		switch (c) {
		case 'c':
			if (streq(optarg, "none"))
			    compression = COMPRESSION_NONE;
			else if (streq(optarg, "packbits"))
			    compression = COMPRESSION_PACKBITS;
			else if (streq(optarg, "lzw"))
			    compression = COMPRESSION_LZW;
			else if (streq(optarg, "jpeg"))
			    compression = COMPRESSION_JPEG;
			else if (streq(optarg, "zip"))
			    compression = COMPRESSION_ADOBE_DEFLATE;
			else
			    usage(-1);
			break;
		case 'h':
			horizSubSampling = atoi(optarg);
			break;
		case 'v':
			vertSubSampling = atoi(optarg);
			break;
		case 'r':
			rowsperstrip = atoi(optarg);
			break;
		case 'z':	/* CCIR Rec 601-1 w/ headroom/footroom */
			refBlackWhite[0] = 16.;
			refBlackWhite[1] = 235.;
			refBlackWhite[2] = 128.;
			refBlackWhite[3] = 240.;
			refBlackWhite[4] = 128.;
			refBlackWhite[5] = 240.;
			break;
		case '?':
			usage(0);
			/*NOTREACHED*/
		}
	if (argc - optind < 2)
		usage(-1);
	out = TIFFOpen(argv[argc-1], "w");
	if (out == NULL)
		return (-2);
	setupLumaTables();
	for (; optind < argc-1; optind++) {
		in = TIFFOpen(argv[optind], "r");
		if (in != NULL) {
			do {
				if (!tiffcvt(in, out) ||
				    !TIFFWriteDirectory(out)) {
					(void) TIFFClose(out);
					return (1);
				}
			} while (TIFFReadDirectory(in));
			(void) TIFFClose(in);
		}
	}
	(void) TIFFClose(out);
	return (0);
}
Ejemplo n.º 7
0
bool _openslide_try_aperio(openslide_t *osr, TIFF *tiff,
			   struct _openslide_hash *quickhash1,
			   GError **err) {
  int32_t level_count = 0;
  int32_t *levels = NULL;
  int32_t i = 0;

  if (!TIFFIsTiled(tiff)) {
    g_set_error(err, OPENSLIDE_ERROR, OPENSLIDE_ERROR_FORMAT_NOT_SUPPORTED,
                "TIFF is not tiled");
    goto FAIL;
  }

  char *tagval;
  int tiff_result;
  tiff_result = TIFFGetField(tiff, TIFFTAG_IMAGEDESCRIPTION, &tagval);
  if (!tiff_result ||
      (strncmp(APERIO_DESCRIPTION, tagval, strlen(APERIO_DESCRIPTION)) != 0)) {
    g_set_error(err, OPENSLIDE_ERROR, OPENSLIDE_ERROR_FORMAT_NOT_SUPPORTED,
                "Not an Aperio slide");
    goto FAIL;
  }

  /*
   * http://www.aperio.com/documents/api/Aperio_Digital_Slides_and_Third-party_data_interchange.pdf
   * page 14:
   *
   * The first image in an SVS file is always the baseline image (full
   * resolution). This image is always tiled, usually with a tile size
   * of 240 x 240 pixels. The second image is always a thumbnail,
   * typically with dimensions of about 1024 x 768 pixels. Unlike the
   * other slide images, the thumbnail image is always
   * stripped. Following the thumbnail there may be one or more
   * intermediate "pyramid" images. These are always compressed with
   * the same type of compression as the baseline image, and have a
   * tiled organization with the same tile size.
   *
   * Optionally at the end of an SVS file there may be a slide label
   * image, which is a low resolution picture taken of the slide’s
   * label, and/or a macro camera image, which is a low resolution
   * picture taken of the entire slide. The label and macro images are
   * always stripped.
   */

  // for aperio, the tiled directories are the ones we want
  do {
    if (TIFFIsTiled(tiff)) {
      level_count++;
    }
  } while (TIFFReadDirectory(tiff));
  levels = g_new(int32_t, level_count);

  TIFFSetDirectory(tiff, 0);
  i = 0;
  do {
    if (TIFFIsTiled(tiff)) {
      levels[i++] = TIFFCurrentDirectory(tiff);
      //g_debug("tiled directory: %d", TIFFCurrentDirectory(tiff));
    } else {
      // associated image
      const char *name = (i == 1) ? "thumbnail" : NULL;
      if (!add_associated_image(osr ? osr->associated_images : NULL,
                                name, tiff, err)) {
	g_prefix_error(err, "Can't read associated image: ");
	goto FAIL;
      }
      //g_debug("associated image: %d", TIFFCurrentDirectory(tiff));
    }

    // check depth
    uint32_t depth;
    tiff_result = TIFFGetField(tiff, TIFFTAG_IMAGEDEPTH, &depth);
    if (tiff_result && depth != 1) {
      // we can't handle depth != 1
      g_set_error(err, OPENSLIDE_ERROR, OPENSLIDE_ERROR_BAD_DATA,
                  "Cannot handle ImageDepth=%d", depth);
      goto FAIL;
    }

    // check compression
    uint16_t compression;
    if (!TIFFGetField(tiff, TIFFTAG_COMPRESSION, &compression)) {
      g_set_error(err, OPENSLIDE_ERROR, OPENSLIDE_ERROR_BAD_DATA,
                  "Can't read compression scheme");
      goto FAIL;
    }
    if ((compression != APERIO_COMPRESSION_JP2K_YCBCR) &&
        (compression != APERIO_COMPRESSION_JP2K_RGB) &&
        !TIFFIsCODECConfigured(compression)) {
      g_set_error(err, OPENSLIDE_ERROR, OPENSLIDE_ERROR_BAD_DATA,
                  "Unsupported TIFF compression: %u", compression);
      goto FAIL;
    }
  } while (TIFFReadDirectory(tiff));

  // read properties
  if (osr) {
    TIFFSetDirectory(tiff, 0);
    TIFFGetField(tiff, TIFFTAG_IMAGEDESCRIPTION, &tagval); // XXX? should be safe, we just did it
    char **props = g_strsplit(tagval, "|", -1);
    add_properties(osr->properties, props);
    g_strfreev(props);
  }

  // special jpeg 2000 aperio thing (with fallback)
  _openslide_add_tiff_ops(osr, tiff, 0, 0, NULL, level_count, levels,
			  aperio_tiff_tilereader,
			  quickhash1);
  return true;

 FAIL:
  g_free(levels);
  return false;
}
Ejemplo n.º 8
0
int fm_MITIFF_read(char *infile, unsigned char *image[], 
    fmio_mihead *ginfo) {
    
    char *where="MITIFF_read";
    TIFF *in;
    int i, status, size;
    short pmi;
    unsigned int fieldlen, currlen, nextlen, taglen;
    char *description, *o_description;
    char *currfield, *nextfield, *field, *pt;
    char *o_currfield, *o_nextfield, *o_field;
    char *fieldname[FMIO_FIELDS]={
	"Satellite:", 
	"Date and Time:", 
	"SatDir:", 
	"Channels:", 
	"In this file:", 
	"Xsize:", 
	"Ysize:", 
	"Map projection:", 
	"TrueLat:", 
	"GridRot:", 
	"Xunit:", 
	"Yunit:", 
	"NPX:", 
	"NPY:", 
	"Ax:", 
	"Ay:", 
	"Bx:", 
	"By:", 
	"Calibration"
    };

    /*
     * Open TIFF files and initialize IFD
     */
    
    in=TIFFOpen(infile, "rc");
    if (!in) {
	printf(" This is no TIFF file! \n");
	return(FM_IO_ERR);
    }

    /*
     * Test whether this is a color palette image or not. If so another
     * function should be used.
     */
    status = TIFFGetField(in, 262, &pmi);
    if (pmi == 3) {
	return(FM_IO_ERR);
    }

    description = (char *) malloc(1024*sizeof(char));
    if (!description) fmerrmsg(where,"Memory allocation failed");
    o_description = description;
    TIFFGetField(in, 270, &description);
    currfield = (char *) malloc(FMIO_TIFFHEAD*sizeof(char));
    if (!currfield) fmerrmsg(where,"Memory allocation failed"); 
    o_currfield = currfield;
    nextfield = (char *) malloc(FMIO_TIFFHEAD*sizeof(char));
    if (!nextfield) fmerrmsg(where,"Memory allocation failed"); 
    o_nextfield = nextfield;
    for (i=0; i<FMIO_FIELDS-1; i++) {
	pt = strstr(description, fieldname[i]);
	sprintf(currfield, "%s", pt);
	currlen = strlen(currfield);
	pt = strstr(description, fieldname[i+1]);
	sprintf(nextfield, "%s", pt);
	nextlen = strlen(nextfield);
	taglen = strlen(fieldname[i]);
	fieldlen = currlen-nextlen-taglen;
	field = (char *) calloc(fieldlen+1, sizeof(char));
	if (!field) fmerrmsg(where,"Memory allocation failed");
	o_field = field;
	currfield += taglen;
	strncpy(field, currfield, fieldlen);
	fillhead(field, fieldname[i], ginfo);
	free(o_field);
    }
    free(o_currfield);
    free(o_nextfield);
    free(o_description); 
    
    /*
     * Read image data into matrix.
     */
    TIFFGetField(in, 256, &ginfo->xsize);
    TIFFGetField(in, 257, &ginfo->ysize);
    size = ginfo->xsize*ginfo->ysize;
  
    /*
     * Memory allocated for image data in this function (*image) is freed 
     * in function main process.
     */
    if (ginfo->zsize > FMIO_MAXCHANNELS) {
	printf("\n\tNOT ENOUGH POINTERS AVAILABLE TO HOLD DATA!\n");
	return(FM_IO_ERR);
    }
    for (i=0; i<ginfo->zsize; i++) {
	image[i] = (unsigned char *) malloc((size+1)*sizeof(char));
	if (!image[i]) fmerrmsg(where,"Memory allocation failed");
	status = TIFFReadRawStrip(in, 0, image[i], size);
	if (status == -1) return(FM_IO_ERR);
	if (TIFFReadDirectory(in) == 0) break;
    }

    if (ginfo->zsize != (i+1)) {
	printf("\n\tERROR READING MULTIPLE SUBFILES!\n");
	return(FM_IO_ERR);
    }
    
    TIFFClose(in);
    return(FM_OK);
}
Ejemplo n.º 9
0
/*
 * PURPOSE:
 * To read DNMI/TIFF palette color files containing either classed satellite
 * imagery or radar imagery.
 *
 * RETURN VALUES:
 * 0 - Normal and correct ending
 * 2 - This is not a Palette-color image
 *
 * NOTE:
 * Requires access to libtiff.
 *
 * AUTHOR:
 * Øystein Godøy, DNMI/FOU, 21/07/1999
 * MODIFICATION:
 * Øystein Godøy, DNMI/FOU, 27/03/2001
 * Corrected some memory allocation and freeing problems connected to
 * strtok actually changing the string it operates on.
 */
int fm_MITIFF_read_imagepal(char *infile, unsigned char *image[], 
    fmio_mihead *ginfo, fmio_mihead_pal *palinfo) {
    
    char *where="MITIFF_read_imagepal";
    TIFF *in;
    int i, status, size;
    short pmi;
    unsigned int fieldlen, currlen, nextlen, taglen;
    uint16 *red, *green, *blue;
    char *description, *o_description;
    char *currfield, *nextfield, *field, *pt;
    char *o_currfield, *o_nextfield, *o_field;
    char *fieldname[FMIO_FIELDS]={
	"Satellite:", 
	"Date and Time:", 
	"SatDir:", 
	"Channels:", 
	"In this file:", 
	"Xsize:", 
	"Ysize:", 
	"Map projection:", 
	"TrueLat:", 
	"GridRot:", 
	"Xunit:", 
	"Yunit:", 
	"NPX:", 
	"NPY:", 
	"Ax:", 
	"Ay:", 
	"Bx:", 
	"By:", 
	"COLOR INFO:"
    };

    /*
     * Open TIFF files and initialize IFD
     */
    
    in=TIFFOpen(infile, "rc");
    if (!in) {
	printf(" This is no TIFF file! \n");
	return(FM_IO_ERR);
    }

    /*
     * Test whether this is a color palette image or not. If so another
     * function should be used.
     */
    status = TIFFGetField(in, 262, &pmi);
    if (pmi != 3) {
	return(FM_IO_ERR);
    }

    status = TIFFGetField(in, 320, &red, &green, &blue);
    if (status != 1) {
	return(FM_IO_ERR);
    }
    for (i=0; i<256; i++) {
	palinfo->cmap[0][i] = red[i];
	palinfo->cmap[1][i] = green[i];
	palinfo->cmap[2][i] = blue[i];
    }

    description = (char *) malloc(FMIO_TIFFHEAD*sizeof(char));
    if (!description) fmerrmsg(where,"Memory allocation failed"); 
    o_description = description;
    TIFFGetField(in, 270, &description);
    /*
     * Lead through the filed tags defined, except for the last one which will
     * create a segmentation fault if it is used. This is processed after the
     * loop.
     */
    currfield = (char *) malloc(FMIO_TIFFHEAD*sizeof(char));
    if (!currfield) fmerrmsg(where,"Memory allocation failed"); 
    o_currfield = currfield;
    nextfield = (char *) malloc(FMIO_TIFFHEAD*sizeof(char));
    if (!nextfield) fmerrmsg(where,"Memory allocation failed"); 
    o_nextfield = nextfield;
    for (i=0; i<FMIO_FIELDS-1; i++) {
	pt = strstr(description, fieldname[i]);
	sprintf(currfield, "%s", pt);
	currlen = strlen(currfield);
	pt = strstr(description, fieldname[i+1]);
	sprintf(nextfield, "%s", pt);
	nextlen = strlen(nextfield);
	taglen = strlen(fieldname[i]);
	fieldlen = currlen-nextlen-taglen;
	field = (char *) malloc((fieldlen+1)*sizeof(char));
	if (!field) fmerrmsg(where,"Memory allocation failed");
	o_field = field;
	currfield += taglen;
	strncpy(field, currfield, fieldlen);
	fillhead(field, fieldname[i], ginfo);
	free(o_field);
    }
    /*
     * The last part of the information header is treated as one single string
     * and is extracted as the remaining part and processed in a suitable way
     * later...
     */
    pt = strstr(description, fieldname[FMIO_FIELDS-1]);
    sprintf(currfield, "%s", pt);
    currlen = strlen(currfield);
    nextlen = strlen(description);
    taglen = strlen(fieldname[FMIO_FIELDS-1]);
    /*
    fieldlen = nextlen-currlen-taglen;
    field = (char *) malloc((fieldlen+1)*sizeof(char));
    */
    fieldlen = nextlen-currlen-taglen;
    field = (char *) malloc((currlen+1)*sizeof(char));
    if (!field) fmerrmsg(where,"Memory allocation failed");
    o_field = field;
    /*
     * Beware here, in order to help C keep track of which memory to free
     * later, currfield should be reduced by taglen imediately or better a new
     * work string should be used, but for now this solution is chosen...
     */
    currfield += taglen;
    /*
    strncpy(field, currfield, fieldlen);
    */
    strncpy(field, currfield, currlen);
    currfield -= taglen;
    /*
    printf(" %d-%d-%d-%d\n",currlen,nextlen,taglen,fieldlen);
    printf("%s\n\n%s\n",currfield, field);
    printf("%d - %d\n",strlen(currfield),strlen(field));
    */
    fillhead_imagepal(field, fieldname[FMIO_FIELDS-1], palinfo); 
    free(o_field);
    free(o_currfield);
    free(o_nextfield);
    free(o_description);
    /*
     * Read image data into matrix.
     */
    TIFFGetField(in, 256, &ginfo->xsize);
    TIFFGetField(in, 257, &ginfo->ysize);
    size = ginfo->xsize*ginfo->ysize;
  
    /*
     * Memory allocated for image data in this function (*image) is freed 
     * in function main process.
     */
    if (ginfo->zsize > FMIO_MAXCHANNELS) {
	printf("\n\tNOT ENOUGH POINTERS AVAILABLE TO HOLD DATA!\n");
	return(FM_IO_ERR);
    }
    for (i=0; i<ginfo->zsize; i++) {
	image[i] = (unsigned char *) malloc((size+1)*sizeof(char));
	if (!image[i]) fmerrmsg(where,"Memory allocation failed");
	status = TIFFReadRawStrip(in, 0, *image, size);
	if (status == -1) return(FM_IO_ERR);
	if (TIFFReadDirectory(in) == 0) break;
    }

    if (ginfo->zsize != (i+1)) {
	printf("\n\tERROR READING MULTIPLE SUBFILES!\n");
	return(FM_IO_ERR);
    }
    
    TIFFClose(in);
    return(FM_OK);
}
Ejemplo n.º 10
0
TIFF*
TIFFClientOpen(
	const char* name, const char* mode,
	thandle_t clientdata,
	TIFFReadWriteProc readproc,
	TIFFReadWriteProc writeproc,
	TIFFSeekProc seekproc,
	TIFFCloseProc closeproc,
	TIFFSizeProc sizeproc,
	TIFFMapFileProc mapproc,
	TIFFUnmapFileProc unmapproc
)
{
	static const char module[] = "TIFFClientOpen";
	TIFF *tif;
	int m;
	const char* cp;

	/* The following are configuration checks. They should be redundant, but should not
	 * compile to any actual code in an optimised release build anyway. If any of them
	 * fail, (makefile-based or other) configuration is not correct */
	assert(sizeof(uint8)==1);
	assert(sizeof(int8)==1);
	assert(sizeof(uint16)==2);
	assert(sizeof(int16)==2);
	assert(sizeof(uint32)==4);
	assert(sizeof(int32)==4);
	assert(sizeof(uint64)==8);
	assert(sizeof(int64)==8);
	assert(sizeof(tmsize_t)==sizeof(void*));
	{
		union{
			uint8 a8[2];
			uint16 a16;
		} n;
		n.a8[0]=1;
		n.a8[1]=0;
		#ifdef WORDS_BIGENDIAN
		assert(n.a16==256);
		#else
		assert(n.a16==1);
		#endif
	}

	m = _TIFFgetMode(mode, module);
	if (m == -1)
		goto bad2;
	tif = (TIFF *)_TIFFmalloc((tmsize_t)(sizeof (TIFF) + strlen(name) + 1));
	if (tif == NULL) {
		TIFFErrorExt(clientdata, module, "%s: Out of memory (TIFF structure)", name);
		goto bad2;
	}
	_TIFFmemset(tif, 0, sizeof (*tif));
	tif->tif_name = (char *)tif + sizeof (TIFF);
	strcpy(tif->tif_name, name);
	tif->tif_mode = m &~ (O_CREAT|O_TRUNC);
	tif->tif_curdir = (uint16) -1;		/* non-existent directory */
	tif->tif_curoff = 0;
	tif->tif_curstrip = (uint32) -1;	/* invalid strip */
	tif->tif_row = (uint32) -1;		/* read/write pre-increment */
	tif->tif_clientdata = clientdata;
	if (!readproc || !writeproc || !seekproc || !closeproc || !sizeproc) {
		TIFFErrorExt(clientdata, module,
		    "One of the client procedures is NULL pointer.");
		goto bad2;
	}
	tif->tif_readproc = readproc;
	tif->tif_writeproc = writeproc;
	tif->tif_seekproc = seekproc;
	tif->tif_closeproc = closeproc;
	tif->tif_sizeproc = sizeproc;
	if (mapproc)
		tif->tif_mapproc = mapproc;
	else
		tif->tif_mapproc = _tiffDummyMapProc;
	if (unmapproc)
		tif->tif_unmapproc = unmapproc;
	else
		tif->tif_unmapproc = _tiffDummyUnmapProc;
	_TIFFSetDefaultCompressionState(tif);    /* setup default state */
	/*
	 * Default is to return data MSB2LSB and enable the
	 * use of memory-mapped files and strip chopping when
	 * a file is opened read-only.
	 */
	tif->tif_flags = FILLORDER_MSB2LSB;
	if (m == O_RDONLY )
		tif->tif_flags |= TIFF_MAPPED;

	#ifdef STRIPCHOP_DEFAULT
	if (m == O_RDONLY || m == O_RDWR)
		tif->tif_flags |= STRIPCHOP_DEFAULT;
	#endif

	/*
	 * Process library-specific flags in the open mode string.
	 * The following flags may be used to control intrinsic library
	 * behaviour that may or may not be desirable (usually for
	 * compatibility with some application that claims to support
	 * TIFF but only supports some brain dead idea of what the
	 * vendor thinks TIFF is):
	 *
	 * 'l' use little-endian byte order for creating a file
	 * 'b' use big-endian byte order for creating a file
	 * 'L' read/write information using LSB2MSB bit order
	 * 'B' read/write information using MSB2LSB bit order
	 * 'H' read/write information using host bit order
	 * 'M' enable use of memory-mapped files when supported
	 * 'm' disable use of memory-mapped files
	 * 'C' enable strip chopping support when reading
	 * 'c' disable strip chopping support
	 * 'h' read TIFF header only, do not load the first IFD
	 * '4' ClassicTIFF for creating a file (default)
	 * '8' BigTIFF for creating a file
	 *
	 * The use of the 'l' and 'b' flags is strongly discouraged.
	 * These flags are provided solely because numerous vendors,
	 * typically on the PC, do not correctly support TIFF; they
	 * only support the Intel little-endian byte order.  This
	 * support is not configured by default because it supports
	 * the violation of the TIFF spec that says that readers *MUST*
	 * support both byte orders.  It is strongly recommended that
	 * you not use this feature except to deal with busted apps
	 * that write invalid TIFF.  And even in those cases you should
	 * bang on the vendors to fix their software.
	 *
	 * The 'L', 'B', and 'H' flags are intended for applications
	 * that can optimize operations on data by using a particular
	 * bit order.  By default the library returns data in MSB2LSB
	 * bit order for compatibility with older versions of this
	 * library.  Returning data in the bit order of the native CPU
	 * makes the most sense but also requires applications to check
	 * the value of the FillOrder tag; something they probably do
	 * not do right now.
	 *
	 * The 'M' and 'm' flags are provided because some virtual memory
	 * systems exhibit poor behaviour when large images are mapped.
	 * These options permit clients to control the use of memory-mapped
	 * files on a per-file basis.
	 *
	 * The 'C' and 'c' flags are provided because the library support
	 * for chopping up large strips into multiple smaller strips is not
	 * application-transparent and as such can cause problems.  The 'c'
	 * option permits applications that only want to look at the tags,
	 * for example, to get the unadulterated TIFF tag information.
	 */
	for (cp = mode; *cp; cp++)
		switch (*cp) {
			case 'b':
				#ifndef WORDS_BIGENDIAN
				if (m&O_CREAT)
					tif->tif_flags |= TIFF_SWAB;
				#endif
				break;
			case 'l':
				#ifdef WORDS_BIGENDIAN
				if ((m&O_CREAT))
					tif->tif_flags |= TIFF_SWAB;
				#endif
				break;
			case 'B':
				tif->tif_flags = (tif->tif_flags &~ TIFF_FILLORDER) |
				    FILLORDER_MSB2LSB;
				break;
			case 'L':
				tif->tif_flags = (tif->tif_flags &~ TIFF_FILLORDER) |
				    FILLORDER_LSB2MSB;
				break;
			case 'H':
				tif->tif_flags = (tif->tif_flags &~ TIFF_FILLORDER) |
				    HOST_FILLORDER;
				break;
			case 'M':
				if (m == O_RDONLY)
					tif->tif_flags |= TIFF_MAPPED;
				break;
			case 'm':
				if (m == O_RDONLY)
					tif->tif_flags &= ~TIFF_MAPPED;
				break;
			case 'C':
				if (m == O_RDONLY)
					tif->tif_flags |= TIFF_STRIPCHOP;
				break;
			case 'c':
				if (m == O_RDONLY)
					tif->tif_flags &= ~TIFF_STRIPCHOP;
				break;
			case 'h':
				tif->tif_flags |= TIFF_HEADERONLY;
				break;
			case '8':
				if (m&O_CREAT)
					tif->tif_flags |= TIFF_BIGTIFF;
				break;
		}
	/*
	 * Read in TIFF header.
	 */
	if ((m & O_TRUNC) ||
	    !ReadOK(tif, &tif->tif_header, sizeof (TIFFHeaderClassic))) {
		if (tif->tif_mode == O_RDONLY) {
			TIFFErrorExt(tif->tif_clientdata, name,
			    "Cannot read TIFF header");
			goto bad;
		}
		/*
		 * Setup header and write.
		 */
		#ifdef WORDS_BIGENDIAN
		tif->tif_header.common.tiff_magic = (tif->tif_flags & TIFF_SWAB)
		    ? TIFF_LITTLEENDIAN : TIFF_BIGENDIAN;
		#else
		tif->tif_header.common.tiff_magic = (tif->tif_flags & TIFF_SWAB)
		    ? TIFF_BIGENDIAN : TIFF_LITTLEENDIAN;
		#endif
		if (!(tif->tif_flags&TIFF_BIGTIFF))
		{
			tif->tif_header.common.tiff_version = TIFF_VERSION_CLASSIC;
			tif->tif_header.classic.tiff_diroff = 0;
			if (tif->tif_flags & TIFF_SWAB)
				TIFFSwabShort(&tif->tif_header.common.tiff_version);
			tif->tif_header_size = sizeof(TIFFHeaderClassic);
		}
		else
		{
			tif->tif_header.common.tiff_version = TIFF_VERSION_BIG;
			tif->tif_header.big.tiff_offsetsize = 8;
			tif->tif_header.big.tiff_unused = 0;
			tif->tif_header.big.tiff_diroff = 0;
			if (tif->tif_flags & TIFF_SWAB)
			{
				TIFFSwabShort(&tif->tif_header.common.tiff_version);
				TIFFSwabShort(&tif->tif_header.big.tiff_offsetsize);
			}
			tif->tif_header_size = sizeof (TIFFHeaderBig);
		}
		/*
		 * The doc for "fopen" for some STD_C_LIBs says that if you
		 * open a file for modify ("+"), then you must fseek (or
		 * fflush?) between any freads and fwrites.  This is not
		 * necessary on most systems, but has been shown to be needed
		 * on Solaris.
		 */
		TIFFSeekFile( tif, 0, SEEK_SET );
		if (!WriteOK(tif, &tif->tif_header, (tmsize_t)(tif->tif_header_size))) {
			TIFFErrorExt(tif->tif_clientdata, name,
			    "Error writing TIFF header");
			goto bad;
		}
		/*
		 * Setup the byte order handling.
		 */
		if (tif->tif_header.common.tiff_magic == TIFF_BIGENDIAN) {
			#ifndef WORDS_BIGENDIAN
			tif->tif_flags |= TIFF_SWAB;
			#endif
		} else {
			#ifdef WORDS_BIGENDIAN
			tif->tif_flags |= TIFF_SWAB;
			#endif
		}
		/*
		 * Setup default directory.
		 */
		if (!TIFFDefaultDirectory(tif))
			goto bad;
		tif->tif_diroff = 0;
		tif->tif_dirlist = NULL;
		tif->tif_dirlistsize = 0;
		tif->tif_dirnumber = 0;
		return (tif);
	}
	/*
	 * Setup the byte order handling.
	 */
	if (tif->tif_header.common.tiff_magic != TIFF_BIGENDIAN &&
	    tif->tif_header.common.tiff_magic != TIFF_LITTLEENDIAN
	    #if MDI_SUPPORT
	    &&
	    #if HOST_BIGENDIAN
	    tif->tif_header.common.tiff_magic != MDI_BIGENDIAN
	    #else
	    tif->tif_header.common.tiff_magic != MDI_LITTLEENDIAN
	    #endif
	    ) {
		TIFFErrorExt(tif->tif_clientdata, name,
		    "Not a TIFF or MDI file, bad magic number %d (0x%x)",
	    #else
	    ) {
		TIFFErrorExt(tif->tif_clientdata, name,
		    "Not a TIFF file, bad magic number %d (0x%x)",
	    #endif
		    tif->tif_header.common.tiff_magic,
		    tif->tif_header.common.tiff_magic);
		goto bad;
	}
	if (tif->tif_header.common.tiff_magic == TIFF_BIGENDIAN) {
		#ifndef WORDS_BIGENDIAN
		tif->tif_flags |= TIFF_SWAB;
		#endif
	} else {
		#ifdef WORDS_BIGENDIAN
		tif->tif_flags |= TIFF_SWAB;
		#endif
	}
	if (tif->tif_flags & TIFF_SWAB) 
		TIFFSwabShort(&tif->tif_header.common.tiff_version);
	if ((tif->tif_header.common.tiff_version != TIFF_VERSION_CLASSIC)&&
	    (tif->tif_header.common.tiff_version != TIFF_VERSION_BIG)) {
		TIFFErrorExt(tif->tif_clientdata, name,
		    "Not a TIFF file, bad version number %d (0x%x)",
		    tif->tif_header.common.tiff_version,
		    tif->tif_header.common.tiff_version);
		goto bad;
	}
	if (tif->tif_header.common.tiff_version == TIFF_VERSION_CLASSIC)
	{
		if (tif->tif_flags & TIFF_SWAB)
			TIFFSwabLong(&tif->tif_header.classic.tiff_diroff);
		tif->tif_header_size = sizeof(TIFFHeaderClassic);
	}
	else
	{
		if (!ReadOK(tif, ((uint8*)(&tif->tif_header) + sizeof(TIFFHeaderClassic)), (sizeof(TIFFHeaderBig)-sizeof(TIFFHeaderClassic))))
		{
			TIFFErrorExt(tif->tif_clientdata, name,
			    "Cannot read TIFF header");
			goto bad;
		}
		if (tif->tif_flags & TIFF_SWAB)
		{
			TIFFSwabShort(&tif->tif_header.big.tiff_offsetsize);
			TIFFSwabLong8(&tif->tif_header.big.tiff_diroff);
		}
		if (tif->tif_header.big.tiff_offsetsize != 8)
		{
			TIFFErrorExt(tif->tif_clientdata, name,
			    "Not a TIFF file, bad BigTIFF offsetsize %d (0x%x)",
			    tif->tif_header.big.tiff_offsetsize,
			    tif->tif_header.big.tiff_offsetsize);
			goto bad;
		}
		if (tif->tif_header.big.tiff_unused != 0)
		{
			TIFFErrorExt(tif->tif_clientdata, name,
			    "Not a TIFF file, bad BigTIFF unused %d (0x%x)",
			    tif->tif_header.big.tiff_unused,
			    tif->tif_header.big.tiff_unused);
			goto bad;
		}
		tif->tif_header_size = sizeof(TIFFHeaderBig);
		tif->tif_flags |= TIFF_BIGTIFF;
	}
	tif->tif_flags |= TIFF_MYBUFFER;
	tif->tif_rawcp = tif->tif_rawdata = 0;
	tif->tif_rawdatasize = 0;
        tif->tif_rawdataoff = 0;
        tif->tif_rawdataloaded = 0;

	switch (mode[0]) {
		case 'r':
			if (!(tif->tif_flags&TIFF_BIGTIFF))
				tif->tif_nextdiroff = tif->tif_header.classic.tiff_diroff;
			else
				tif->tif_nextdiroff = tif->tif_header.big.tiff_diroff;
			/*
			 * Try to use a memory-mapped file if the client
			 * has not explicitly suppressed usage with the
			 * 'm' flag in the open mode (see above).
			 */
			if (tif->tif_flags & TIFF_MAPPED)
			{
				toff_t n;
				if (TIFFMapFileContents(tif,(void**)(&tif->tif_base),&n))
				{
					tif->tif_size=(tmsize_t)n;
					assert((toff_t)tif->tif_size==n);
				}
				else
					tif->tif_flags &= ~TIFF_MAPPED;
			}
			/*
			 * Sometimes we do not want to read the first directory (for example,
			 * it may be broken) and want to proceed to other directories. I this
			 * case we use the TIFF_HEADERONLY flag to open file and return
			 * immediately after reading TIFF header.
			 */
			if (tif->tif_flags & TIFF_HEADERONLY)
				return (tif);

			/*
			 * Setup initial directory.
			 */
			if (TIFFReadDirectory(tif)) {
				tif->tif_rawcc = (tmsize_t)-1;
				tif->tif_flags |= TIFF_BUFFERSETUP;
				return (tif);
			}
			break;
		case 'a':
			/*
			 * New directories are automatically append
			 * to the end of the directory chain when they
			 * are written out (see TIFFWriteDirectory).
			 */
			if (!TIFFDefaultDirectory(tif))
				goto bad;
			return (tif);
	}
bad:
	tif->tif_mode = O_RDONLY;	/* XXX avoid flush */
        TIFFCleanup(tif);
bad2:
	return ((TIFF*)0);
}