home *** CD-ROM | disk | FTP | other *** search
- /*****************************************************************
- * fltiff.c: FBM Release 1.2 24-Mar-93 Michael Mauldin
- *
- * Copyright (C) 1993 by Michael Mauldin. Permission is granted
- * to use this file in whole or in part for any purpose, educational,
- * recreational or commercial, provided that this copyright notice
- * is retained unchanged. This software is available to all free of
- * charge by anonymous FTP and in the UUNET archives.
- *
- * fltiff.c:
- *
- * CONTENTS
- * read_tiff (image, fname)
- * write_tiff (image, wfile, graybits)
- *
- * EDITLOG
- * LastEditDate = Mon Jun 25 00:18:04 1990 - Michael Mauldin
- * LastFileName = /usr2/mlm/src/misc/fbm/fltiff.c
- *
- * HISTORY
- * 24-Mar-93 Michael Mauldin (mlm@cs.cmu.edu) Carnegie Mellon
- * Created from flsun.c and tiff2fbm.c, fbm2tiff.c
- *****************************************************************/
-
- # include <stdio.h>
- # include <math.h>
- # include <ctype.h>
- # include <stdio.h>
- # include <ctype.h>
- # ifdef BYTE
- # undef BYTE
- # endif
- # include <sys/types.h>
- # include <tiff.h>
- # include <tiffio.h>
- # include <tiffioP.h>
- # include "fbm.h"
-
- # define RED 0
- # define GRN 1
- # define BLU 2
-
-
- # ifdef __STDC__
- # define FIELD(tif,f) TIFFFieldSet(tif, FIELD_ ## f)
- # else
- /* The following macro is taken from tiff_print.c */
- # define FIELD(tif,f) TIFFFieldSet(tif, FIELD_/**/f)
- # endif
-
- #ifndef howmany
- # define howmany(x, y) (((x)+((y)-1))/(y))
- #endif
- #define SCALE(x) (((x)*((1L<<16)-1))/256)
-
- /****************************************************************
- * fbmid:
- ****************************************************************/
-
- #ifndef lint
- static char *fbmid =
- "$FBM fltiff.c <1.2> 24-Mar-93 (C) 1993 by Michael Mauldin, source \
- code available free from MLM@CS.CMU.EDU and from UUNET archives$";
- #endif
-
- /****************************************************************
- * write_tiff (image, fname, graybit)
- ****************************************************************/
-
- write_tiff (image, fname, graybit)
- FBM *image;
- char *fname;
- int graybit;
- { int width, height, rowlen, planes, plnlen, k;
- int failed = 0;
-
- u_short config = PLANARCONFIG_CONTIG;
- u_short compression = COMPRESSION_NONE;
- u_short rowsperstrip = 0;
-
- u_char *bmp, *obm, *scanbuf;
- int row, linebytes;
- TIFF *out;
-
-
- /* Check for bad argument to reduced resolution argument */
- switch (graybit)
- { case 1: case 2: case 4:
- /* These are standard values */
- break;
-
- case 0: case 8:
- /* These mean no reduced resolution */
- graybit = 0; break;
-
- default: fprintf (stderr,
- "Error: graybit value must be 0, 1, 2, or 4\n");
- return (0);
- }
-
- width = image->hdr.cols;
- height = image->hdr.rows;
- rowlen = image->hdr.rowlen;
- planes = image->hdr.planes;
- plnlen = image->hdr.plnlen;
-
- /*-Start of Tiff writing code-------------------------------------*/
- if (!(out = TIFFOpen (fname, "w")))
- { return (0); }
-
- TIFFSetField(out, TIFFTAG_IMAGEWIDTH, width);
- TIFFSetField(out, TIFFTAG_IMAGELENGTH, height);
- TIFFSetField(out, TIFFTAG_SAMPLESPERPIXEL, graybit ? 1:image->hdr.planes);
- TIFFSetField(out, TIFFTAG_BITSPERSAMPLE, graybit ? graybit:image->hdr.bits);
- TIFFSetField(out, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
- TIFFSetField(out, TIFFTAG_PLANARCONFIG, config);
-
- if (image->hdr.clrlen > 0 && !graybit)
- { register u_short *red;
- register int i, j;
- int mapsize, cbytes, nclrs;
-
- mapsize = 1<<image->hdr.bits;
- if (image->hdr.clrlen > mapsize*3)
- { fprintf(stderr,
- "stdin: Huh, %d colormap entries, should be %d?\n",
- image->hdr.clrlen, mapsize*3);
- exit(-7);
- }
-
- cbytes = mapsize * 3 * sizeof (u_short);
- nclrs = image->hdr.clrlen/3;
-
- if ((red = (u_short *) malloc(cbytes)) == NULL)
- { perror ("colormap"); exit (-8); }
-
- /* XXX -- set pointers up before we step through arrays */
- TIFFSetField(out, TIFFTAG_COLORMAP,
- red, red + mapsize, red + 2*mapsize);
- bmp = image->cm;
-
- for (j = 0; j < 3; j++)
- { for (i=0; i < nclrs; i++) *red++ = SCALE(*bmp++);
- for (; i<mapsize; i++) *red++ = 0;
- }
-
- TIFFSetField(out, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_PALETTE);
- }
- else
- { /* XXX this is bogus... */
- TIFFSetField(out, TIFFTAG_PHOTOMETRIC,
- (image->hdr.planes == 3) && !graybit ?
- PHOTOMETRIC_RGB : PHOTOMETRIC_MINISBLACK);
- }
-
- TIFFSetField(out, TIFFTAG_COMPRESSION, compression);
-
- linebytes = (((image->hdr.bits * width+15) >> 3) &~ 1) * planes;
-
- if (TIFFScanlineSize(out) < linebytes)
- scanbuf = (u_char *)malloc(linebytes);
- else
- scanbuf = (u_char *)malloc(TIFFScanlineSize(out));
-
- if (scanbuf == NULL)
- { perror ("mallocing scanbuf"); exit (1); }
-
- if (rowsperstrip != (u_short)-1)
- rowsperstrip = (8*1024)/linebytes;
- TIFFSetField(out, TIFFTAG_ROWSPERSTRIP,
- rowsperstrip == 0 ? 1 : rowsperstrip);
-
- /* Handle bitmaps first */
- if (image->hdr.bits == 1 && image->hdr.physbits == 8)
- { int byte = 0, i;
- u_char *obm;
-
- for (row = 0; row < height; row++)
- { byte = 0;
- bmp = &image->bm[row*rowlen];
- obm = scanbuf;
-
- /* Write out each group of 8 bytes as one byte */
- for (i=0; i<width; i++)
- { byte = (byte << 1) | (*bmp++ ? 1 : 0);
- if ((i&7) == 7)
- { *obm++ = byte; byte=0; }
- }
-
- /* Handle stragglers if width not multiple of 8 */
- if (i&7)
- { byte <<= (8 - (i&7));
- *obm = byte;
- }
-
- if (TIFFWriteScanline(out, scanbuf, row, 0) < 0)
- { failed++; break; }
- }
- }
-
- /* Handle reduced level grayscale */
- else if (graybit && image->hdr.bits == 8)
- { int byte, mask, spb, shift, i; /* spb: Samples per byte mask */
- u_char *obm;
-
- switch (graybit)
- { case 1: mask = 0x80; spb = 7; shift = 7; break;
- case 2: mask = 0xc0; spb = 3; shift = 6; break;
- case 4: mask = 0xf0; spb = 1; shift = 4; break;
- }
-
- for (row = 0; row < height; row++)
- { byte = 0;
- bmp = &image->bm[row*rowlen];
- obm = scanbuf;
-
- /* Write out each group of 8 bytes as one byte */
- for (i=0; i<width; )
- { byte = (byte << graybit) | ((*bmp++ & mask) >> shift);
-
- if ((++i & spb) == 0)
- { *obm++ = byte; byte=0; }
- }
-
- /* Handle stragglers if width not multiple of 8 */
- if (i&spb)
- { while (i++ & spb)
- { byte <<= graybit; }
- *obm = byte;
- }
-
- if (TIFFWriteScanline(out, scanbuf, row, 0) < 0)
- { failed++; break; }
- }
- }
-
- /* Catch cases we cant handle */
- else if (image->hdr.physbits != 8)
- { fprintf (stderr, "Error: cannot handle %d physical bits per pixel\n",
- image->hdr.physbits);
- (void) TIFFClose(out);
- return (0);
- }
-
- /* Handle 8bit grayscale or 24bit rgb */
- else
- { fprintf (stderr, "Writing %d bit output, height %d, width %d, ",
- planes * image->hdr.physbits, height, width);
- fprintf (stderr, "planes %d, linebytes %d. plnlen %d, rowlen %d\n",
- planes, linebytes, plnlen, rowlen);
-
- for (row = 0; row < height; row++)
- { for (k=0; k<planes; k++)
- { register int i, j, oi;
-
- for (i=0; i<width; i++)
- { oi = i*planes + k;
- if (oi >= linebytes)
- { fprintf (stderr, "Overran scanbuf...\n");
- abort();
- }
- scanbuf[oi] = image->bm[k*plnlen + row*rowlen + i];
- }
- }
-
- if (TIFFWriteScanline(out, scanbuf, row, 0) < 0)
- { failed++; break; }
- }
- }
-
- (void) TIFFClose(out);
-
- if (failed)
- { fprintf (stderr, "Could not write tiff file\n"); return (0); }
-
-
- return (1);
- }
-
- /****************************************************************
- * read_tiff (image, rfile)
- ****************************************************************/
-
- read_tiff (image, fname)
- FBM *image;
- char *fname;
- {
- int userdir = 1, fw, fh, rowlen, plnlen, clrlen=0, colors=0;
- double aspect = 0.0;
- char *title = NULL, *credits = NULL;
-
- TIFF *tif;
- TIFFDirectory *td;
- u_char *scanbuf, *tail;
- register u_char *pp, *obm, *tmp;
- int bitspersample, scanline, samplesperbyte;
- register unsigned int mask;
- register int shift, nib;
- register int poff, k, planes;
- int i, j, w, h, dirnum = 0;
-
- /* Clear the memory pointers so alloc_fbm won't be confused */
- image->cm = image->bm = (unsigned char *) NULL;
-
- /* Now read in the TIFF format image */
-
- if ((tif = TIFFOpen(fname, "r")) == NULL)
- { return (0); }
-
- do
- { ++dirnum;
-
- if (userdir != dirnum) continue;
-
- td = &tif->tif_dir;
- bitspersample = td->td_bitspersample;
- planes = td->td_samplesperpixel;
-
- if (td->td_planarconfig == PLANARCONFIG_CONTIG)
- { bitspersample *= planes; }
-
- scanline = howmany (bitspersample * td->td_imagewidth, 8);
- scanbuf = (u_char *) malloc (scanline);
- if (scanbuf == NULL)
- { printf ("No space for scanline buffer\n");
- continue;
- }
-
- w = td->td_imagewidth;
- h = td->td_imagelength;
-
- switch (bitspersample)
- { case 1: samplesperbyte = 8; break;
- case 2: samplesperbyte = 4; break;
- case 4: samplesperbyte = 2; break;
- case 8: samplesperbyte = 1; break;
- case 24: samplesperbyte = 1; break;
- default: fprintf (stderr, "I can't handle %d bits per sample\n",
- bitspersample);
- if (tif) TIFFClose (tif);
- return (0);
- }
-
- /* Now build FBM image header */
-
- if (bitspersample == 1)
- { rowlen = 16 * ((w+15)/16); }
- else
- { rowlen = 2 * ((w+1)/2); }
-
- plnlen = rowlen * h;
-
- /* Build header */
- image->hdr.title[0] = image->hdr.credits[0] = '\0';
-
- image->hdr.rows = h;
- image->hdr.cols = w;
- image->hdr.planes = planes;
- image->hdr.bits = bitspersample / planes;
- image->hdr.physbits = 8;
- image->hdr.rowlen = rowlen;
- image->hdr.plnlen = plnlen;
- colors = FIELD (tif,COLORMAP) ? (1 << td->td_bitspersample) : 0;
- image->hdr.clrlen = colors * 3;
-
-
- /* Determine aspect from X and Y resolution */
- if (FIELD (tif,RESOLUTION) && td->td_yresolution != 0)
- { image->hdr.aspect = td->td_xresolution / td->td_yresolution; }
- else
- { image->hdr.aspect = 1.0; }
-
- /* Extract Title and Credit information */
- if (FIELD (tif,DOCUMENTNAME))
- { strcpy (image->hdr.title, td->td_documentname); }
- else if (FIELD (tif,IMAGEDESCRIPTION))
- { strcpy (image->hdr.title, td->td_imagedescription); }
- else
- { strcpy (image->hdr.title, fname); }
-
- if (FIELD (tif,ARTIST))
- { strcpy (image->hdr.credits, td->td_artist); }
- else if (FIELD (tif,SOFTWARE))
- { strcpy (image->hdr.credits, td->td_software); }
- else if (FIELD (tif,MAKE))
- { strcpy (image->hdr.credits, td->td_make);
- if (FIELD (tif,MODEL))
- { strcat (image->hdr.credits, ", ");
- strcat (image->hdr.credits, td->td_model);
- }
- }
-
- fprintf (stderr, "Reading \"%s\" [%dx%d], %d bits, directory %d\n",
- image->hdr.title, w, h, bitspersample, userdir);
-
- alloc_fbm (image);
-
- /* Read colormap: Note TIFF colors are 16 bit, FBM colors 8 bit */
- if (FIELD (tif,COLORMAP))
- { for (i=0; i<colors; i++)
- { image->cm[i] = td->td_colormap[0][i] >> 8;
- image->cm[i + colors] = td->td_colormap[1][i] >> 8;
- image->cm[i + colors + colors] = td->td_colormap[2][i] >> 8;
- }
- }
-
- /* Check for multiplane images */
- if (td->td_planarconfig == PLANARCONFIG_SEPARATE &&
- planes > 1)
- { fprintf (stderr, "Multiplane images (%d) not yet implemented\n",
- planes);
- if (tif) TIFFClose (tif);
- return (0);
- }
-
- else
- {
- /*
- * Read single plane images (for RGB color, values are stored in
- * successive bytes)
- */
-
- /* Precompute mask and shift parameters */
- switch (samplesperbyte)
- { case 8: mask = 0x01; shift = 1; break;
- case 4: mask = 0x03; shift = 2; break;
- case 2: mask = 0x0f; shift = 4; break;
- case 1: mask = 0xff; shift = 8; break;
- }
-
- fprintf (stderr,
- "Samples per byte %d, mask %02x, shift %d, planes %d, scanline %d\n",
- samplesperbyte, mask, shift, planes, scanline);
-
- /* Each loop does one scan line */
- for (j=0; j<h; j++)
- { if (TIFFReadScanline (tif, scanbuf, j, 0) < 0)
- { fprintf (stderr, "Error: only read %d lines\n", j); break; }
-
- /* If 0 is WHITE, then flip all bits in the scanline */
- if (td->td_photometric == PHOTOMETRIC_MINISWHITE)
- { for (pp = scanbuf, i=scanline; --i >= 0; pp++)
- { *pp = ~ *pp; }
- }
-
- pp = scanbuf;
- obm = &image->bm[j * rowlen];
- tmp = obm;
- tail = obm + w;
- nib = 8 - shift;
-
- if (samplesperbyte > 1)
- { nib = 8 - shift;
- for (; obm < tail; obm++)
- { for (k=0, poff=0; k<planes; k++, poff += plnlen)
- { obm[poff] = (*pp >> nib) & mask;
- # ifdef DEBUG
- if (j< 10 && (obm-tmp)< 18)
- { fprintf (stderr, "<%2d,%2d> obm[%d] = %d, nib %d, mask %d, pp %08x\n",
- (obm-tmp), j, poff, obm[poff], nib, mask, pp);
- }
- # endif
- if ((nib -= shift) < 0) { pp++; nib = 8 - shift; }
- }
- }
- }
-
- else
- { for (; obm < tail; obm++)
- { for (k=0, poff=0; k<planes; k++, poff += plnlen)
- { obm[poff] = *pp++; }
- }
- }
- }
- }
- } while (TIFFReadDirectory (tif));
-
-
- /* ---- Close files and check to make sure we read an image ---- */
- if (tif) TIFFClose (tif);
-
- /* Check whether an image was read */
- if (userdir > dirnum)
- { if (dirnum > 0)
- { fprintf (stderr, "File %s has only %d directories, %d out of range\n",
- fname, dirnum, userdir);
- }
- else
- { fprintf (stderr, "File %s has no directories\n", fname); }
-
- return (0);
- }
-
- return (1);
- }
-