home *** CD-ROM | disk | FTP | other *** search
/ BCI NET / BCI NET Dec 94.iso / archives / programming / source / fbm12s.lha / fltiff.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-07-18  |  13.1 KB  |  496 lines

  1. /*****************************************************************
  2.  * fltiff.c: FBM Release 1.2 24-Mar-93 Michael Mauldin
  3.  *
  4.  * Copyright (C) 1993 by Michael Mauldin.  Permission is granted
  5.  * to use this file in whole or in part for any purpose, educational,
  6.  * recreational or commercial, provided that this copyright notice
  7.  * is retained unchanged.  This software is available to all free of
  8.  * charge by anonymous FTP and in the UUNET archives.
  9.  *
  10.  * fltiff.c: 
  11.  *
  12.  * CONTENTS
  13.  *    read_tiff (image, fname)
  14.  *    write_tiff (image, wfile, graybits)
  15.  *
  16.  * EDITLOG
  17.  *    LastEditDate = Mon Jun 25 00:18:04 1990 - Michael Mauldin
  18.  *    LastFileName = /usr2/mlm/src/misc/fbm/fltiff.c
  19.  *
  20.  * HISTORY
  21.  * 24-Mar-93  Michael Mauldin (mlm@cs.cmu.edu) Carnegie Mellon
  22.  *    Created from flsun.c and tiff2fbm.c, fbm2tiff.c
  23.  *****************************************************************/
  24.  
  25. # include <stdio.h>
  26. # include <math.h>
  27. # include <ctype.h>
  28. # include <stdio.h>
  29. # include <ctype.h>
  30. # ifdef BYTE
  31. # undef BYTE
  32. # endif
  33. # include <sys/types.h>
  34. # include <tiff.h>
  35. # include <tiffio.h>
  36. # include <tiffioP.h>
  37. # include "fbm.h"
  38.  
  39. # define RED 0
  40. # define GRN 1
  41. # define BLU 2
  42.  
  43.  
  44. # ifdef __STDC__
  45. #   define FIELD(tif,f)    TIFFFieldSet(tif, FIELD_ ## f)
  46. # else
  47.     /* The following macro is taken from tiff_print.c */
  48. #   define FIELD(tif,f)    TIFFFieldSet(tif, FIELD_/**/f)
  49. # endif
  50.  
  51. #ifndef howmany
  52. # define    howmany(x, y)    (((x)+((y)-1))/(y))
  53. #endif
  54. #define SCALE(x)        (((x)*((1L<<16)-1))/256)
  55.  
  56. /****************************************************************
  57.  * fbmid:
  58.  ****************************************************************/
  59.  
  60. #ifndef lint
  61. static char *fbmid =
  62. "$FBM fltiff.c <1.2> 24-Mar-93  (C) 1993 by Michael Mauldin, source \
  63. code available free from MLM@CS.CMU.EDU and from UUNET archives$";
  64. #endif
  65.  
  66. /****************************************************************
  67.  * write_tiff (image, fname, graybit)
  68.  ****************************************************************/
  69.  
  70. write_tiff (image, fname, graybit)
  71. FBM *image;
  72. char *fname;
  73. int graybit;
  74. { int width, height, rowlen, planes, plnlen, k;
  75.   int failed = 0;
  76.  
  77.   u_short    config = PLANARCONFIG_CONTIG;
  78.   u_short    compression = COMPRESSION_NONE;
  79.   u_short    rowsperstrip = 0;
  80.  
  81.   u_char *bmp, *obm, *scanbuf;
  82.   int row, linebytes;
  83.   TIFF *out;
  84.  
  85.  
  86.   /* Check for bad argument to reduced resolution argument */
  87.   switch (graybit)
  88.   { case 1: case 2: case 4:
  89.         /* These are standard values */
  90.         break;
  91.  
  92.     case 0: case 8:
  93.         /* These mean no reduced resolution */
  94.         graybit = 0; break;
  95.  
  96.     default:    fprintf (stderr,
  97.                  "Error: graybit value must be 0, 1, 2, or 4\n");
  98.         return (0);
  99.   }
  100.  
  101.   width = image->hdr.cols;
  102.   height = image->hdr.rows;
  103.   rowlen = image->hdr.rowlen;
  104.   planes = image->hdr.planes;
  105.   plnlen = image->hdr.plnlen;
  106.  
  107.   /*-Start of Tiff writing code-------------------------------------*/
  108.   if (!(out = TIFFOpen (fname, "w")))
  109.   { return (0); }
  110.  
  111.   TIFFSetField(out, TIFFTAG_IMAGEWIDTH, width);
  112.   TIFFSetField(out, TIFFTAG_IMAGELENGTH, height);
  113.   TIFFSetField(out, TIFFTAG_SAMPLESPERPIXEL, graybit ? 1:image->hdr.planes);
  114.   TIFFSetField(out, TIFFTAG_BITSPERSAMPLE, graybit ? graybit:image->hdr.bits);
  115.   TIFFSetField(out, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
  116.   TIFFSetField(out, TIFFTAG_PLANARCONFIG, config);
  117.  
  118.   if (image->hdr.clrlen > 0 && !graybit)
  119.   { register u_short *red;
  120.     register int i, j;
  121.     int mapsize, cbytes, nclrs;
  122.  
  123.     mapsize = 1<<image->hdr.bits;
  124.     if (image->hdr.clrlen > mapsize*3)
  125.     { fprintf(stderr,
  126.           "stdin: Huh, %d colormap entries, should be %d?\n",
  127.           image->hdr.clrlen, mapsize*3);
  128.       exit(-7);
  129.     }
  130.     
  131.     cbytes = mapsize * 3 * sizeof (u_short);
  132.     nclrs = image->hdr.clrlen/3;
  133.  
  134.     if ((red = (u_short *) malloc(cbytes)) == NULL)
  135.     { perror ("colormap"); exit (-8); }
  136.  
  137.     /* XXX -- set pointers up before we step through arrays */ 
  138.     TIFFSetField(out, TIFFTAG_COLORMAP,
  139.          red, red + mapsize, red + 2*mapsize);
  140.     bmp = image->cm;
  141.  
  142.     for (j = 0; j < 3; j++)
  143.     { for (i=0; i < nclrs; i++)    *red++ = SCALE(*bmp++);
  144.       for (; i<mapsize; i++)    *red++ = 0;
  145.     }
  146.  
  147.     TIFFSetField(out, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_PALETTE);
  148.   }
  149.   else
  150.   { /* XXX this is bogus... */
  151.     TIFFSetField(out, TIFFTAG_PHOTOMETRIC,
  152.          (image->hdr.planes == 3) && !graybit ? 
  153.          PHOTOMETRIC_RGB : PHOTOMETRIC_MINISBLACK);
  154.   }
  155.  
  156.   TIFFSetField(out, TIFFTAG_COMPRESSION, compression);
  157.  
  158.   linebytes = (((image->hdr.bits * width+15) >> 3) &~ 1) * planes;
  159.  
  160.   if (TIFFScanlineSize(out) < linebytes)
  161.       scanbuf = (u_char *)malloc(linebytes);
  162.   else
  163.       scanbuf = (u_char *)malloc(TIFFScanlineSize(out));
  164.  
  165.   if (scanbuf == NULL)
  166.   { perror ("mallocing scanbuf"); exit (1); }
  167.  
  168.   if (rowsperstrip != (u_short)-1)
  169.       rowsperstrip = (8*1024)/linebytes;
  170.   TIFFSetField(out, TIFFTAG_ROWSPERSTRIP,
  171.       rowsperstrip == 0 ? 1 : rowsperstrip);
  172.  
  173.   /* Handle bitmaps first */
  174.   if (image->hdr.bits == 1 && image->hdr.physbits == 8)
  175.   { int byte = 0, i;
  176.     u_char *obm;
  177.     
  178.     for (row = 0; row < height; row++)
  179.     { byte = 0;
  180.       bmp = &image->bm[row*rowlen];
  181.       obm = scanbuf;
  182.  
  183.       /* Write out each group of 8 bytes as one byte */
  184.       for (i=0; i<width; i++)
  185.       { byte = (byte << 1) | (*bmp++ ? 1 : 0);
  186.     if ((i&7) == 7)
  187.     { *obm++ = byte; byte=0; }
  188.       }
  189.  
  190.       /* Handle stragglers if width not multiple of 8 */
  191.       if (i&7)
  192.       { byte <<= (8 - (i&7));
  193.     *obm = byte;
  194.       }
  195.  
  196.       if (TIFFWriteScanline(out, scanbuf, row, 0) < 0)
  197.       { failed++; break; }
  198.     }
  199.   }
  200.  
  201.   /* Handle reduced level grayscale */
  202.   else if (graybit && image->hdr.bits == 8)
  203.   { int byte, mask, spb, shift, i; /* spb: Samples per byte mask */
  204.     u_char *obm;
  205.  
  206.     switch (graybit)
  207.     { case 1:    mask = 0x80; spb = 7; shift = 7; break;
  208.       case 2:    mask = 0xc0; spb = 3; shift = 6; break;
  209.       case 4:    mask = 0xf0; spb = 1; shift = 4; break;
  210.     }
  211.  
  212.     for (row = 0; row < height; row++)
  213.     { byte = 0;
  214.       bmp = &image->bm[row*rowlen];
  215.       obm = scanbuf;
  216.  
  217.       /* Write out each group of 8 bytes as one byte */
  218.       for (i=0; i<width; )
  219.       { byte = (byte << graybit) | ((*bmp++ & mask) >> shift);
  220.  
  221.     if ((++i & spb) == 0)
  222.     { *obm++ = byte; byte=0; }
  223.       }
  224.  
  225.       /* Handle stragglers if width not multiple of 8 */
  226.       if (i&spb)
  227.       { while (i++ & spb)
  228.     { byte <<= graybit; }
  229.     *obm = byte;
  230.       }
  231.  
  232.       if (TIFFWriteScanline(out, scanbuf, row, 0) < 0)
  233.       { failed++; break; }
  234.     }
  235.   }
  236.   
  237.   /* Catch cases we cant handle */
  238.   else if (image->hdr.physbits != 8)
  239.   { fprintf (stderr, "Error: cannot handle %d physical bits per pixel\n",
  240.          image->hdr.physbits);
  241.     (void) TIFFClose(out);
  242.     return (0);
  243.   }
  244.  
  245.   /* Handle 8bit grayscale or 24bit rgb */
  246.   else
  247.   { fprintf (stderr, "Writing %d bit output, height %d, width %d, ",
  248.           planes * image->hdr.physbits, height, width);
  249.     fprintf (stderr, "planes %d, linebytes %d. plnlen %d, rowlen %d\n",
  250.           planes, linebytes, plnlen, rowlen);
  251.  
  252.     for (row = 0; row < height; row++)
  253.     { for (k=0; k<planes; k++)
  254.       { register int i, j, oi;
  255.  
  256.     for (i=0; i<width; i++)
  257.     { oi = i*planes + k;
  258.       if (oi >= linebytes)
  259.       { fprintf (stderr, "Overran scanbuf...\n");
  260.         abort();
  261.       }
  262.       scanbuf[oi] = image->bm[k*plnlen + row*rowlen + i];
  263.     }
  264.       }
  265.  
  266.       if (TIFFWriteScanline(out, scanbuf, row, 0) < 0)
  267.       { failed++; break; }
  268.     }
  269.   }
  270.  
  271.   (void) TIFFClose(out);
  272.   
  273.   if (failed)
  274.   { fprintf (stderr, "Could not write tiff file\n"); return (0); }
  275.  
  276.  
  277.   return (1);
  278. }
  279.  
  280. /****************************************************************
  281. * read_tiff (image, rfile)
  282. ****************************************************************/
  283.  
  284. read_tiff (image, fname)
  285. FBM *image;
  286. char *fname;
  287. {
  288.   int userdir = 1, fw, fh, rowlen, plnlen, clrlen=0, colors=0;
  289.   double aspect = 0.0;
  290.   char *title = NULL, *credits = NULL;
  291.  
  292.   TIFF *tif;
  293.   TIFFDirectory *td;
  294.   u_char *scanbuf, *tail;
  295.   register u_char *pp, *obm, *tmp;
  296.   int bitspersample, scanline, samplesperbyte;
  297.   register unsigned int mask;
  298.   register int shift, nib;
  299.   register int poff, k, planes;
  300.   int i, j, w, h, dirnum = 0;
  301.  
  302.   /* Clear the memory pointers so alloc_fbm won't be confused */
  303.   image->cm  = image->bm  = (unsigned char *) NULL;
  304.  
  305.   /* Now read in the TIFF format image */
  306.  
  307.   if ((tif = TIFFOpen(fname, "r")) == NULL)
  308.   { return (0); }
  309.  
  310.   do
  311.   { ++dirnum;
  312.  
  313.     if (userdir != dirnum) continue;
  314.  
  315.     td = &tif->tif_dir;
  316.     bitspersample = td->td_bitspersample;
  317.     planes = td->td_samplesperpixel;
  318.  
  319.     if (td->td_planarconfig == PLANARCONFIG_CONTIG)
  320.     { bitspersample *= planes; }
  321.  
  322.     scanline = howmany (bitspersample * td->td_imagewidth, 8);
  323.     scanbuf = (u_char *) malloc (scanline);
  324.     if (scanbuf == NULL)
  325.     { printf ("No space for scanline buffer\n");
  326.       continue;
  327.     }
  328.  
  329.     w = td->td_imagewidth;
  330.     h = td->td_imagelength;
  331.  
  332.     switch (bitspersample)
  333.     { case 1:    samplesperbyte = 8; break;
  334.       case 2:    samplesperbyte = 4; break;
  335.       case 4:    samplesperbyte = 2; break;
  336.       case 8:    samplesperbyte = 1; break;
  337.       case 24:    samplesperbyte = 1; break;
  338.       default:    fprintf (stderr, "I can't handle %d bits per sample\n",
  339.             bitspersample);
  340.         if (tif) TIFFClose (tif);
  341.         return (0);
  342.     }
  343.  
  344.     /* Now build FBM image header */
  345.     
  346.     if (bitspersample == 1)
  347.     { rowlen = 16 * ((w+15)/16); }
  348.     else
  349.     { rowlen = 2 * ((w+1)/2); }
  350.  
  351.     plnlen = rowlen * h;
  352.  
  353.     /* Build header */
  354.     image->hdr.title[0] = image->hdr.credits[0] = '\0';
  355.     
  356.     image->hdr.rows = h;
  357.     image->hdr.cols = w;
  358.     image->hdr.planes = planes;
  359.     image->hdr.bits = bitspersample / planes;
  360.     image->hdr.physbits = 8;
  361.     image->hdr.rowlen = rowlen;
  362.     image->hdr.plnlen = plnlen;
  363.     colors = FIELD (tif,COLORMAP) ? (1 << td->td_bitspersample) : 0;
  364.     image->hdr.clrlen = colors * 3;
  365.  
  366.  
  367.     /* Determine aspect from X and Y resolution */
  368.     if (FIELD (tif,RESOLUTION) && td->td_yresolution != 0)
  369.     { image->hdr.aspect = td->td_xresolution / td->td_yresolution; }
  370.     else
  371.     { image->hdr.aspect = 1.0; }
  372.  
  373.     /* Extract Title and Credit information */
  374.     if (FIELD (tif,DOCUMENTNAME))
  375.     { strcpy (image->hdr.title, td->td_documentname); }
  376.     else if (FIELD (tif,IMAGEDESCRIPTION))
  377.     { strcpy (image->hdr.title, td->td_imagedescription); }
  378.     else
  379.     { strcpy (image->hdr.title, fname); }
  380.     
  381.     if (FIELD (tif,ARTIST))
  382.     { strcpy (image->hdr.credits, td->td_artist); }
  383.     else if (FIELD (tif,SOFTWARE))
  384.     { strcpy (image->hdr.credits, td->td_software); }
  385.     else if (FIELD (tif,MAKE))
  386.     { strcpy (image->hdr.credits, td->td_make);
  387.       if (FIELD (tif,MODEL))
  388.       { strcat (image->hdr.credits, ", ");
  389.         strcat (image->hdr.credits, td->td_model);
  390.       }
  391.     }
  392.  
  393.     fprintf (stderr, "Reading \"%s\" [%dx%d], %d bits, directory %d\n",
  394.          image->hdr.title, w, h, bitspersample, userdir);
  395.  
  396.     alloc_fbm (image);
  397.  
  398.     /* Read colormap: Note TIFF colors are 16 bit, FBM colors 8 bit */
  399.     if (FIELD (tif,COLORMAP))
  400.     { for (i=0; i<colors; i++)
  401.       { image->cm[i]            = td->td_colormap[0][i] >> 8;
  402.         image->cm[i + colors]        = td->td_colormap[1][i] >> 8;
  403.         image->cm[i + colors + colors]    = td->td_colormap[2][i] >> 8;
  404.       }
  405.     }
  406.  
  407.     /* Check for multiplane images */
  408.     if (td->td_planarconfig == PLANARCONFIG_SEPARATE &&
  409.         planes > 1)
  410.     { fprintf (stderr, "Multiplane images (%d) not yet implemented\n",
  411.            planes);
  412.       if (tif) TIFFClose (tif);
  413.       return (0);
  414.     }
  415.  
  416.     else
  417.     {
  418.       /*
  419.        * Read single plane images (for RGB color, values are stored in 
  420.        * successive bytes)
  421.        */
  422.   
  423.       /* Precompute mask and shift parameters */
  424.       switch (samplesperbyte)
  425.       { case 8:    mask = 0x01; shift = 1; break;
  426.     case 4:    mask = 0x03; shift = 2; break;
  427.     case 2:    mask = 0x0f; shift = 4; break;
  428.     case 1:    mask = 0xff; shift = 8; break;
  429.       }
  430.   
  431.       fprintf (stderr,
  432.       "Samples per byte %d, mask %02x, shift %d, planes %d, scanline %d\n", 
  433.         samplesperbyte, mask, shift, planes, scanline);
  434.  
  435.       /* Each loop does one scan line */
  436.       for (j=0; j<h; j++)
  437.       { if (TIFFReadScanline (tif, scanbuf, j, 0) < 0)
  438.     { fprintf (stderr, "Error: only read %d lines\n", j); break; }
  439.     
  440.     /* If 0 is WHITE, then flip all bits in the scanline */
  441.     if (td->td_photometric == PHOTOMETRIC_MINISWHITE)
  442.     { for (pp = scanbuf, i=scanline; --i >= 0; pp++)
  443.       { *pp = ~ *pp; }
  444.     }
  445.     
  446.     pp = scanbuf;
  447.     obm = &image->bm[j * rowlen];
  448.     tmp = obm;
  449.     tail = obm + w;
  450.         nib = 8 - shift;
  451.     
  452.     if (samplesperbyte > 1)
  453.     { nib = 8 - shift;
  454.       for (; obm < tail; obm++)
  455.       { for (k=0, poff=0; k<planes; k++, poff += plnlen)
  456.         { obm[poff] = (*pp >> nib) & mask;
  457. # ifdef DEBUG
  458.           if (j< 10 && (obm-tmp)< 18)
  459.           { fprintf (stderr, "<%2d,%2d>  obm[%d] = %d, nib %d, mask %d, pp %08x\n",
  460.             (obm-tmp), j, poff, obm[poff], nib, mask, pp);
  461.           }
  462. # endif
  463.           if ((nib -= shift) < 0) { pp++; nib = 8 - shift; }
  464.         }
  465.       }
  466.     }
  467.     
  468.     else
  469.     { for (; obm < tail; obm++)
  470.       { for (k=0, poff=0; k<planes; k++, poff += plnlen)
  471.         { obm[poff] = *pp++; }
  472.       }
  473.     }
  474.       }
  475.     }
  476.   } while (TIFFReadDirectory (tif));
  477.  
  478.  
  479.   /* ---- Close files and check to make sure we read an image ---- */
  480.   if (tif) TIFFClose (tif);
  481.  
  482.   /* Check whether an image was read */
  483.   if (userdir > dirnum)
  484.   { if (dirnum > 0)
  485.     { fprintf (stderr, "File %s has only %d directories, %d out of range\n",
  486.         fname, dirnum, userdir);
  487.     }
  488.     else
  489.     { fprintf (stderr, "File %s has no directories\n", fname); }
  490.     
  491.     return (0);
  492.   }
  493.  
  494.   return (1);
  495. }
  496.