home *** CD-ROM | disk | FTP | other *** search
/ Photo CD Demo 1 / Demo.bin / fbm / src / fbm2tiff.c < prev    next >
C/C++ Source or Header  |  1990-06-24  |  8KB  |  279 lines

  1. /*****************************************************************
  2.  * fbm2tiff.c: FBM Release 1.0 25-Feb-90 Michael Mauldin
  3.  *
  4.  * Copyright (C) 1989,1990 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.  * fbm2tiff.c: 
  11.  *    Convert an FBM format image to TIFF format.  Uses Sam Leffler's
  12.  *    libtiff.a TIFF image library to write TIFF format.  See also,
  13.  *    tiff2fbm for the opposite conversion.
  14.  *
  15.  * USAGE
  16.  *    % fbm2tiff [ image ] > foo.tif
  17.  *
  18.  * EDITLOG
  19.  *    LastEditDate = Mon Jun 25 00:03:33 1990 - Michael Mauldin
  20.  *    LastFileName = /usr2/mlm/src/misc/fbm/fbm2tiff.c
  21.  *
  22.  * HISTORY
  23.  * 25-Jun-90  Michael Mauldin (mlm@cs.cmu.edu) Carnegie Mellon
  24.  *    Package for Release 1.0
  25.  *
  26.  * 13-Jun-90  Michael Mauldin (mlm) at Carnegie-Mellon University
  27.  *    Created.
  28.  *****************************************************************/
  29.  
  30. # include <stdio.h>
  31. # include <ctype.h>
  32. # ifdef BYTE
  33. # undef BYTE
  34. # endif
  35. # include <tiff.h>
  36. # include <tiffio.h>
  37. # include "fbm.h"
  38.  
  39. # ifdef __STDC__
  40. #   define FIELD(tif,f)    TIFFFieldSet(tif, FIELD_ ## f)
  41. # else
  42.     /* The following macro is taken from tiff_print.c */
  43. #   define FIELD(tif,f)    TIFFFieldSet(tif, FIELD_/**/f)
  44. # endif
  45.  
  46. #define    howmany(x, y)    (((x)+((y)-1))/(y))
  47. #define    streq(a,b)    (strcmp(a,b) == 0)
  48. #define SCALE(x)        (((x)*((1L<<16)-1))/256)
  49.  
  50. # define USAGE \
  51. "Usage: fbm2tiff [-N] [-<compression>] [-r<rowsperstrip>] foo.tif < foo.fbm\n\
  52.        -l=lzw, -p=packbits, -n=none"
  53.  
  54. /****************************************************************
  55.  * main
  56.  ****************************************************************/
  57.  
  58. #ifndef lint
  59. static char *fbmid =
  60. "$FBM fbm2tiff.c <1.0> 25-Jun-90  (C) 1989,1990 by Michael Mauldin, source \
  61. code available free from MLM@CS.CMU.EDU and from UUNET archives$";
  62. #endif
  63.  
  64. main (argc, argv)
  65. char *argv[];
  66. { FBM image;
  67.   int width, height, rowlen, planes, plnlen, k;
  68.   int graybit=0;
  69.   int failed = 0;
  70.  
  71.   u_short    config = PLANARCONFIG_CONTIG;
  72.   u_short    compression = COMPRESSION_NONE;
  73.   u_short    rowsperstrip = -1;
  74.  
  75.   u_char *bmp, *obm, *scanbuf;
  76.   int row, linebytes;
  77.   TIFF *out;
  78.  
  79.   /* Get the options */
  80.   while (--argc > 0 && (*++argv)[0] == '-')
  81.   { while (*++(*argv))
  82.     { switch (**argv)
  83.       { case 'n':    compression = COMPRESSION_NONE; break;
  84.     case 'p':    compression = COMPRESSION_PACKBITS; break;
  85.     case 'l':    compression = COMPRESSION_LZW; break;
  86.     case 'r':    rowsperstrip = atoi (*argv+1); SKIPARG; break;
  87.     case 'N':    graybit = 2; compression = COMPRESSION_NONE; break;
  88.     case 'g':    graybit = atoi (*argv+1); SKIPARG; break;
  89.     default:        fprintf (stderr, "%s\n", USAGE);
  90.                         exit (1);
  91.       }
  92.     }
  93.   }
  94.  
  95.   /* Check for bad argument to reduced resolution argument */
  96.   switch (graybit)
  97.   { case 1: case 2: case 4:
  98.         /* These are standard values */
  99.         break;
  100.  
  101.     case 0: case 8:
  102.         /* These mean no reduced resolution */
  103.         graybit = 0; break;
  104.  
  105.     default:    fprintf (stderr,
  106.                  "Error: graybit vvalue must be 0, 1, 2, or 4\n");
  107.         exit (1);
  108.   }
  109.  
  110.   image.cm  = image.bm  = (unsigned char *) NULL;
  111.  
  112.   /* Now read in an FBM image and write a TIFF format file */
  113.   if (!read_bitmap (&image, (char *) NULL))
  114.   { exit (1); }
  115.   else
  116.   { width = image.hdr.cols;
  117.     height = image.hdr.rows;
  118.     rowlen = image.hdr.rowlen;
  119.     planes = image.hdr.planes;
  120.     plnlen = image.hdr.plnlen;
  121.  
  122.     fprintf (stderr, "input [%dx%d], %d colors, %d bits, %d physbits\n",
  123.          width, height, image.hdr.clrlen/3, 
  124.          image.hdr.bits, image.hdr.physbits);
  125.  
  126.     /*-Start of Tiff writing code-------------------------------------*/
  127.     if (!(out = TIFFOpen(argv[0], "w")))
  128.     { exit(-4); }
  129.  
  130.     TIFFSetField(out, TIFFTAG_IMAGEWIDTH, width);
  131.     TIFFSetField(out, TIFFTAG_IMAGELENGTH, height);
  132.     TIFFSetField(out, TIFFTAG_SAMPLESPERPIXEL, graybit ? 1:image.hdr.planes);
  133.     TIFFSetField(out, TIFFTAG_BITSPERSAMPLE, graybit ? graybit:image.hdr.bits);
  134.     TIFFSetField(out, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
  135.     TIFFSetField(out, TIFFTAG_PLANARCONFIG, config);
  136.  
  137.     if (image.hdr.clrlen > 0 && !graybit)
  138.     { register u_short *red;
  139.       register int i, j;
  140.       int mapsize;
  141.  
  142.       mapsize = 1<<image.hdr.bits;
  143.       if (image.hdr.clrlen > mapsize*3)
  144.       { fprintf(stderr,
  145.                 "stdin: Huh, %d colormap entries, should be %d?\n",
  146.                 image.hdr.clrlen, mapsize*3);
  147.         exit(-7);
  148.       }
  149.  
  150.       if ((red = (u_short *)malloc(mapsize * 3 * sizeof (u_short))) == NULL)
  151.       { perror ("colormap"); exit (-8); }
  152.  
  153.       /* XXX -- set pointers up before we step through arrays */ 
  154.       TIFFSetField(out, TIFFTAG_COLORMAP,
  155.                    red, red + mapsize, red + 2*mapsize);
  156.       bmp = image.cm;
  157.       for (j = 0; j < 3; j++)
  158.       { for (i = image.hdr.clrlen; i-- > 0;)
  159.         { *red++ = SCALE(*bmp++); }
  160.         if ((i = image.hdr.clrlen/3) < mapsize)
  161.         { i = mapsize - i;
  162.           bzero(red, i*sizeof (u_short));
  163.           red += i;
  164.         }
  165.       }
  166.       TIFFSetField(out, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_PALETTE);
  167.     }
  168.     else
  169.     { /* XXX this is bogus... */
  170.       TIFFSetField(out, TIFFTAG_PHOTOMETRIC,
  171.            (image.hdr.planes == 3) && !graybit ? 
  172.            PHOTOMETRIC_RGB : PHOTOMETRIC_MINISBLACK);
  173.     }
  174.  
  175.     TIFFSetField(out, TIFFTAG_COMPRESSION, compression);
  176.  
  177.     linebytes = ((image.hdr.bits * width+15) >> 3) &~ 1;
  178.  
  179.     if (TIFFScanlineSize(out) > linebytes)
  180.         scanbuf = (u_char *)malloc(linebytes);
  181.     else
  182.         scanbuf = (u_char *)malloc(TIFFScanlineSize(out));
  183.  
  184.     if (rowsperstrip != (u_short)-1)
  185.         rowsperstrip = (8*1024)/linebytes;
  186.     TIFFSetField(out, TIFFTAG_ROWSPERSTRIP,
  187.         rowsperstrip == 0 ? 1 : rowsperstrip);
  188.  
  189.     /* Handle bitmaps first */
  190.     if (image.hdr.bits == 1 && image.hdr.physbits == 8)
  191.     { int byte = 0, i;
  192.       u_char *obm;
  193.       
  194.       for (row = 0; row < height; row++)
  195.       { byte = 0;
  196.         bmp = &image.bm[row*rowlen];
  197.     obm = scanbuf;
  198.  
  199.         /* Write out each group of 8 bytes as one byte */
  200.         for (i=0; i<width; i++)
  201.         { byte = (byte << 1) | (*bmp++ ? 1 : 0);
  202.           if ((i&7) == 7)
  203.       { *obm++ = byte; byte=0; }
  204.         }
  205.  
  206.         /* Handle stragglers if width not multiple of 8 */
  207.         if (i&7)
  208.         { byte <<= (8 - (i&7));
  209.           *obm = byte;
  210.         }
  211.  
  212.         if (TIFFWriteScanline(out, scanbuf, row, 0) < 0)
  213.         { failed++; break; }
  214.       }
  215.     }
  216.  
  217.     /* Handle reduced level grayscale */
  218.     else if (graybit && image.hdr.bits == 8)
  219.     { int byte, mask, spb, shift, i; /* spb: Samples per byte mask */
  220.       u_char *obm;
  221.  
  222.       switch (graybit)
  223.       { case 1:    mask = 0x80; spb = 7; shift = 7; break;
  224.     case 2:    mask = 0xc0; spb = 3; shift = 6; break;
  225.     case 4:    mask = 0xf0; spb = 1; shift = 4; break;
  226.       }
  227.  
  228.       for (row = 0; row < height; row++)
  229.       { byte = 0;
  230.         bmp = &image.bm[row*rowlen];
  231.     obm = scanbuf;
  232.  
  233.         /* Write out each group of 8 bytes as one byte */
  234.         for (i=0; i<width; )
  235.         { byte = (byte << graybit) | ((*bmp++ & mask) >> shift);
  236.  
  237.           if ((++i & spb) == 0)
  238.       { *obm++ = byte; byte=0; }
  239.         }
  240.  
  241.         /* Handle stragglers if width not multiple of 8 */
  242.         if (i&spb)
  243.         { while (i++ & spb)
  244.       { byte <<= graybit; }
  245.           *obm = byte;
  246.         }
  247.  
  248.         if (TIFFWriteScanline(out, scanbuf, row, 0) < 0)
  249.         { failed++; break; }
  250.       }
  251.     }
  252.     
  253.     /* Catch cases we cant handle */
  254.     else if (image.hdr.physbits != 8)
  255.     { fprintf (stderr, "Error: cannot handle %d physical bits per pixel\n",
  256.            image.hdr.physbits);
  257.       exit (1);
  258.     }
  259.  
  260.     /* Handle 8bit grayscale or 24bit rgb */
  261.     else
  262.     { for (row = 0; row < height; row++)
  263.       { for (k=0; k<planes; k++)
  264.         { bcopy (&image.bm[k*plnlen + row*rowlen], scanbuf + k*width, width); }
  265.  
  266.         if (TIFFWriteScanline(out, scanbuf, row, 0) < 0)
  267.         { failed++; break; }
  268.       }
  269.     }
  270.  
  271.     (void) TIFFClose(out);
  272.     
  273.     if (failed)
  274.     { exit (1); }
  275.   }
  276.  
  277.   exit (0);
  278. }
  279.