/* * This software is copyrighted as noted below. It may be freely copied, * modified, and redistributed, provided that the copyright notice is * preserved on all copies. * * There is no warranty or other guarantee of fitness for this software, * it is provided solely "as is". Bug reports or fixes may be sent * to the author, who may or may not act on them as he desires. * * You may not include this software in a program or other software product * without supplying the source, or without informing the end-user that the * source is available for no extra charge. * * If you modify this software, you should include a notice giving the * name of the person performing the modification, the date of modification, * and the reason for such modification. */ /* * tiff.c - interface with Aldus-Microsoft TIFF format. * * Author: Raul Rivero * Mathematics Dept. * University of Oviedo * Date: Sat Jan 18 1992 * Copyright (c) 1992, Raul Rivero * */ /* * Raul Rivero - 04/14/94 * Added support for images with any # of colors. * */ #include #include /* * Look here !!! * ============= * * This code is valid only if we have defined the iTIFF * macro ( read the root Makefile for more information ). * */ #ifdef iTIFF #include #define GetField(a,b,c) if ( TIFFGetField(a,b,c) == 0 ) error( 21 ); extern int LUGverbose; read_tiff_file( name, image ) char *name; bitmap_hdr *image; { register int i, j; TIFF *handle; long xsize, ysize; ushort samplesperpixel; ushort bitspersample; ushort photometric; ushort planarconfig; ushort iscmyk = 0; ushort c, m, y, k; ushort *rTIFFcmap, *gTIFFcmap, *bTIFFcmap; byte *r, *g, *b; int totalsize; byte *ptr; byte *TIFFline; double val, inc; /* * Open the file. */ if ( name ) handle = TIFFOpen( name, "rb" ); else handle = TIFFFdOpen( 0, "stdin", "rb" ); if ( handle == NULL ) error( 1 ); /* * Get TIFF configuration. */ GetField( handle, TIFFTAG_IMAGEWIDTH, &xsize ); GetField( handle, TIFFTAG_IMAGELENGTH, &ysize ); GetField( handle, TIFFTAG_SAMPLESPERPIXEL, &samplesperpixel ); GetField( handle, TIFFTAG_BITSPERSAMPLE, &bitspersample ); GetField( handle, TIFFTAG_PHOTOMETRIC, &photometric ); GetField( handle, TIFFTAG_PLANARCONFIG, &planarconfig ); /* * ... ok. Fill our header. */ image->magic = LUGUSED; image->xsize = (int) xsize; image->ysize = (int) ysize; image->depth = ( samplesperpixel < 4 ? samplesperpixel : 3 ) * bitspersample; image->colors = 1 << image->depth; /* * New LIBTIFF library has changed the calling parameters * of the TIFFPrintDirectory functions, so ... what version * are you using ?. */ if ( LUGverbose ) #if TIFF_VERSION >= 42 TIFFPrintDirectory( handle, stderr, 0L ); #else TIFFPrintDirectory( handle, stderr, 1, 0, 0 ); #endif switch ( photometric ) { case PHOTOMETRIC_MINISBLACK : /* Get the increments while building the cmap table */ inc = 255. / (((double)image->colors)-1.); /* Allocate memory for our cmap and build it */ ptr = image->cmap = (byte *) Malloc( 3 * image->colors ); for ( i = 0, val = 0.; i < image->colors; i++, val += inc ) { *ptr++ = (byte) val; *ptr++ = *(ptr-1); *ptr++ = *(ptr-1); } break; case PHOTOMETRIC_MINISWHITE : /* Get the increments while building the cmap table */ inc = 255. / (((double)image->colors)-1.); /* Allocate memory for our cmap and build it */ ptr = image->cmap = (byte *) Malloc( 3 * image->colors ); for ( i = 0, val = 255.; i < image->colors; i++, val -=inc ) { *ptr++ = (byte) val; *ptr++ = *(ptr-1); *ptr++ = *(ptr-1); } break; case PHOTOMETRIC_PALETTE : /* Read the TIFF cmap */ if ( !TIFFGetField( handle, TIFFTAG_COLORMAP, &rTIFFcmap, &gTIFFcmap, &bTIFFcmap ) ) error( 9 ); /* Allocate memory for our cmap and get it */ ptr = image->cmap = (byte *) Malloc( 3 * image->colors ); for ( i = 0; i < image->colors; i++ ) { *ptr++ = ( rTIFFcmap[i] >> 8 ); *ptr++ = ( gTIFFcmap[i] >> 8 ); *ptr++ = ( bTIFFcmap[i] >> 8 ); } break; case PHOTOMETRIC_RGB : break; case PHOTOMETRIC_SEPARATED: if ( TIFFGetField( handle, TIFFTAG_INKSET, &iscmyk ) == 0 ) { if ( samplesperpixel == 4 ) { /* * Photoshop doesn't save the INKSET tag. So ... we hope * in a good CMYK's file if we have 4 samples per pixel. */ VPRINTF( stderr, "Warning, cannot get the INKSET tag (possible further errors)\n" ); iscmyk = 4; }else { VPRINTF( stderr, "A possible CMYK image without INKSET tag neither 4 samples per pixel\n" ); error( 99 ); } }else { if ( iscmyk != INKSET_CMYK ) { fprintf( stderr, "Separated Photometric image but not CMYK\n" ); error( 99 ); } } break; default: fprintf( stderr, "Not supported photometric configuration\n"); error( 99 ); } if ( image->depth > 8 ) { switch ( planarconfig ) { case PLANARCONFIG_CONTIG : break; case PLANARCONFIG_SEPARATE : fprintf( stderr, "Separate planar configuration is not supported, yet.\n"); error( 99 ); break; default: fprintf( stderr, "Unknown planar configuration\n"); error( 99 ); } } /* * Allocate memory for bitmap. */ totalsize = (int) (xsize * ysize); r = image->r = (byte *) Malloc( totalsize ); if ( image->depth > 8 ) { /* A real RGB image */ g = image->g = (byte *) Malloc( totalsize ); b = image->b = (byte *) Malloc( totalsize ); } /* * Get TIFF raster lines. */ TIFFline = (byte *) Malloc( TIFFScanlineSize(handle) ); /* * This ...if... could be done inside the loop but what we * wanna is efficacy :-), so ... */ if ( image->depth >= 8 ) { /* We have a 'beatiful' raw image */ for ( i = 0; i < ysize; i++ ) { TIFFReadScanline( handle, TIFFline, i, 0 ); if ( !iscmyk ) { /* Great!, a RGB image :) */ for ( j = 0, ptr = TIFFline; j < xsize; j++ ) { *r++ = *ptr++; if ( image->depth > 8 ) { *g++ = *ptr++; *b++ = *ptr++; if ( samplesperpixel == 4 ) { /* Skip alpha channel */ ptr++; } } } }else { /* Oooopss!, a CMYK image */ for ( j = 0, ptr = TIFFline; j < xsize; j++ ) { c = 255 - *ptr++; m = 255 - *ptr++; y = 255 - *ptr++; k = 255 - *ptr++; *r++ = ((int)k*c/255); *g++ = ((int)k*m/255); *b++ = ((int)k*y/255); } } } }else { /* Ooopss, we have packed bits */ int mask = ( 1 << bitspersample ) - 1; int offset; for ( i = 0; i < ysize; i++ ) { TIFFReadScanline( handle, TIFFline, i, 0 ); for ( j = 0, ptr = TIFFline, offset = 8 - bitspersample; j < xsize; j++, offset -= bitspersample) { *r++ = (*ptr >> offset ) & mask; if ( !offset ) { offset = 8; ptr++; } } } } /* * Free our raster line and close the TIFF file. */ free( TIFFline ); TIFFClose( handle ); } write_tiff_file( name, image ) char *name; bitmap_hdr *image; { register int i, j; TIFF *handle; byte *r, *g, *b; byte *buffer, *ptr; long rows_per_strip; int banks = (image->depth > 8 ? 3 : 1); long xsize, ysize; ushort *rTIFFcmap, *gTIFFcmap, *bTIFFcmap; if ( image->magic != LUGUSED ) error( 19 ); VPRINTF( stderr, "Writting TIFF file\n" ); /* * Open the TIFF file. */ if ( name ) handle = TIFFOpen( name, "wb" ); else handle = TIFFFdOpen( 1, "stdout", "wb" ); if ( handle == NULL) error( 1 ); /* * Configure the TIFF image. */ xsize = image->xsize; ysize = image->ysize; TIFFSetField( handle,TIFFTAG_IMAGEWIDTH, xsize ); TIFFSetField( handle,TIFFTAG_IMAGELENGTH, ysize ); TIFFSetField( handle, TIFFTAG_COMPRESSION, COMPRESSION_LZW); TIFFSetField( handle, TIFFTAG_PREDICTOR, 2); rows_per_strip = 16*1024 / (image->xsize); if ( rows_per_strip < 1 ) rows_per_strip = 1; TIFFSetField( handle, TIFFTAG_ROWSPERSTRIP, rows_per_strip); TIFFSetField( handle, TIFFTAG_XRESOLUTION, 72.0 ); TIFFSetField( handle, TIFFTAG_YRESOLUTION, 72.0 ); TIFFSetField( handle, TIFFTAG_RESOLUTIONUNIT, 1 ); TIFFSetField( handle, TIFFTAG_BITSPERSAMPLE, 8 ); TIFFSetField( handle, TIFFTAG_SAMPLESPERPIXEL, banks ); TIFFSetField( handle, TIFFTAG_PLANARCONFIG, 1 ); if ( banks > 1 ) { /* * A true color image. */ TIFFSetField( handle, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB ); }else { /* * If a mapped image, the we need build the cmap. */ TIFFSetField( handle, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_PALETTE ); rTIFFcmap = (ushort *) Malloc( sizeof(short) * 256 ); gTIFFcmap = (ushort *) Malloc( sizeof(short) * 256 ); bTIFFcmap = (ushort *) Malloc( sizeof(short) * 256 ); for ( i = 0, ptr = image->cmap; i < image->colors; i++ ) { rTIFFcmap[i] = ( *ptr++ << 8 ); gTIFFcmap[i] = ( *ptr++ << 8 ); bTIFFcmap[i] = ( *ptr++ << 8 ); } TIFFSetField( handle, TIFFTAG_COLORMAP, rTIFFcmap, gTIFFcmap, bTIFFcmap ); } /* * Set pointers. */ r = image->r; if ( image->depth > 8 ) { g = image->g; b = image->b; } buffer = (byte *) Malloc( banks * image->xsize ); /* * Dump each line. */ for ( i = 0; i < image->ysize; i++ ) { /* TIFF library needs a RGBRGB...RGB raster line so ... */ for ( j = 0, ptr = buffer; j < image->xsize; j++ ) { *ptr++ = *r++; if ( banks > 1 ) { *ptr++ = *g++; *ptr++ = *b++; } } TIFFWriteScanline( handle, buffer, i, 1); } /* * Close the TIFF file. */ TIFFClose( handle ); /* * Free memory. */ free( buffer ); if ( banks < 3 ) { free( rTIFFcmap ); free( gTIFFcmap ); free( bTIFFcmap ); } TIFFClose( handle ); } #endif /* iTIFF */