home *** CD-ROM | disk | FTP | other *** search
/ Encyclopedia of Graphics File Formats Companion / GFF_CD.ISO / software / unix / libtiff / lbtif3_3.tar / tools / tiffdither.c < prev    next >
C/C++ Source or Header  |  1993-08-26  |  6KB  |  228 lines

  1. #ifndef lint
  2. static char rcsid[] = "$Header: /usr/people/sam/tiff/tools/RCS/tiffdither.c,v 1.13 93/08/26 15:12:04 sam Exp $";
  3. #endif
  4.  
  5. /*
  6.  * Copyright (c) 1988, 1989, 1990, 1991, 1992 Sam Leffler
  7.  * Copyright (c) 1991, 1992 Silicon Graphics, Inc.
  8.  *
  9.  * Permission to use, copy, modify, distribute, and sell this software and 
  10.  * its documentation for any purpose is hereby granted without fee, provided
  11.  * that (i) the above copyright notices and this permission notice appear in
  12.  * all copies of the software and related documentation, and (ii) the names of
  13.  * Sam Leffler and Silicon Graphics may not be used in any advertising or
  14.  * publicity relating to the software without the specific, prior written
  15.  * permission of Sam Leffler and Silicon Graphics.
  16.  * 
  17.  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
  18.  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
  19.  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
  20.  * 
  21.  * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
  22.  * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
  23.  * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  24.  * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
  25.  * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
  26.  * OF THIS SOFTWARE.
  27.  */
  28.  
  29. #include <stdio.h>
  30. #include <stdlib.h>
  31. #include <string.h>
  32.  
  33. #include "tiffio.h"
  34.  
  35. #define    CopyField(tag, v) \
  36.     if (TIFFGetField(in, tag, &v)) TIFFSetField(out, tag, v)
  37.  
  38. uint32    imagewidth;
  39. uint32    imagelength;
  40. int    threshold = 128;
  41.  
  42. static void
  43. usage(void)
  44. {
  45.     fprintf(stderr,
  46.         "usage: tiffdither [-f24op] [-t threshold] in.tif out.tif.\n");
  47.     exit(-1);
  48. }
  49.  
  50. /* 
  51.  * Floyd-Steinberg error propragation with threshold.
  52.  * This code is stolen from tiffmedian.
  53.  */
  54. static void
  55. fsdither(TIFF* in, TIFF* out)
  56. {
  57.     unsigned char *outline, *inputline, *inptr;
  58.     short *thisline, *nextline, *tmpptr;
  59.     register unsigned char    *outptr;
  60.     register short *thisptr, *nextptr;
  61.     register uint32 i, j;
  62.     uint32 imax, jmax;
  63.     int lastline, lastpixel;
  64.     int bit;
  65.     tsize_t outlinesize;
  66.  
  67.     imax = imagelength - 1;
  68.     jmax = imagewidth - 1;
  69.     inputline = (unsigned char *)malloc(TIFFScanlineSize(in));
  70.     thisline = (short *)malloc(imagewidth * sizeof (short));
  71.     nextline = (short *)malloc(imagewidth * sizeof (short));
  72.     outlinesize = TIFFScanlineSize(out);
  73.     outline = (unsigned char *) malloc(outlinesize);
  74.  
  75.     /*
  76.      * Get first line
  77.      */
  78.     if (TIFFReadScanline(in, inputline, 0, 0) <= 0)
  79.         return;
  80.     inptr = inputline;
  81.     nextptr = nextline;
  82.     for (j = 0; j < imagewidth; ++j)
  83.         *nextptr++ = *inptr++;
  84.     for (i = 1; i < imagelength; ++i) {
  85.         tmpptr = thisline;
  86.         thisline = nextline;
  87.         nextline = tmpptr;
  88.         lastline = (i == imax);
  89.         if (TIFFReadScanline(in, inputline, i, 0) <= 0)
  90.             break;
  91.         inptr = inputline;
  92.         nextptr = nextline;
  93.         for (j = 0; j < imagewidth; ++j)
  94.             *nextptr++ = *inptr++;
  95.         thisptr = thisline;
  96.         nextptr = nextline;
  97.         memset(outptr = outline, 0, outlinesize);
  98.         bit = 0x80;
  99.         for (j = 0; j < imagewidth; ++j) {
  100.             register int v;
  101.  
  102.             lastpixel = (j == jmax);
  103.             v = *thisptr++;
  104.             if (v < 0)
  105.                 v = 0;
  106.             else if (v > 255)
  107.                 v = 255;
  108.             if (v > threshold) {
  109.                 *outptr |= bit;
  110.                 v -= 255;
  111.             }
  112.             bit >>= 1;
  113.             if (bit == 0) {
  114.                 outptr++;
  115.                 bit = 0x80;
  116.             }
  117.             if (!lastpixel)
  118.                 thisptr[0] += v * 7 / 16;
  119.             if (!lastline) {
  120.                 if (j != 0)
  121.                     nextptr[-1] += v * 3 / 16;
  122.                 *nextptr++ += v * 5 / 16;
  123.                 if (!lastpixel)
  124.                     nextptr[0] += v / 16;
  125.             }
  126.         }
  127.         if (TIFFWriteScanline(out, outline, i-1, 0) < 0)
  128.             break;
  129.     }
  130.     free(inputline);
  131.     free(thisline);
  132.     free(nextline);
  133.     free(outline);
  134. }
  135.  
  136. void
  137. main(int argc, char* argv[])
  138. {
  139.     TIFF *in, *out;
  140.     uint16 samplesperpixel, bitspersample = 1, shortv, config;
  141.     float floatv;
  142.     char thing[1024];
  143.     uint32 rowsperstrip;
  144.     uint16 compression = COMPRESSION_LZW;
  145.     int onestrip = 0;
  146.     uint16 fillorder = FILLORDER_LSB2MSB;
  147.     uint32 group3options = GROUP3OPT_FILLBITS;
  148.     int c;
  149.     extern int optind;
  150.     extern char *optarg;
  151.  
  152.     while ((c = getopt(argc, argv, "t:f24ops")) != -1)
  153.         switch (c) {
  154.         case 't':
  155.             threshold = atoi(optarg);
  156.             if (threshold < 0)
  157.                 threshold = 0;
  158.             else if (threshold > 255)
  159.                 threshold = 255;
  160.             break;
  161.         case 'f':        /* CCITT Group 3 */
  162.             compression = COMPRESSION_CCITTFAX3;
  163.             onestrip = 1;
  164.             break;
  165.         case '4':        /* CCITT Group 4 */
  166.             compression = COMPRESSION_CCITTFAX4;
  167.             onestrip = 1;
  168.             break;
  169.         case 'o':        /* reverse bit ordering in output */
  170.             fillorder = FILLORDER_LSB2MSB;
  171.             break;
  172.         case '2':        /* 2d-encoding */
  173.             group3options |= GROUP3OPT_2DENCODING;
  174.             break;
  175.         case 'p':        /* zero pad scanlines before EOL */
  176.             group3options &= ~GROUP3OPT_FILLBITS;
  177.             break;
  178.         case '?':
  179.             usage();
  180.             /*NOTREACHED*/
  181.         }
  182.     if (argc - optind < 2)
  183.         usage();
  184.     in = TIFFOpen(argv[optind], "r");
  185.     if (in == NULL)
  186.         exit(-1);
  187.     TIFFGetField(in, TIFFTAG_SAMPLESPERPIXEL, &samplesperpixel);
  188.     if (samplesperpixel != 1) {
  189.         fprintf(stderr, "%s: Not a b&w image.\n", argv[0]);
  190.         exit(-1);
  191.     }
  192.     TIFFGetField(in, TIFFTAG_BITSPERSAMPLE, &bitspersample);
  193.     if (bitspersample != 8) {
  194.         fprintf(stderr,
  195.             " %s: Sorry, only handle 8-bit samples.\n", argv[0]);
  196.         exit(-1);
  197.     }
  198.     out = TIFFOpen(argv[optind+1], "w");
  199.     if (out == NULL)
  200.         exit(-1);
  201.     CopyField(TIFFTAG_IMAGEWIDTH, imagewidth);
  202.     TIFFGetField(in, TIFFTAG_IMAGELENGTH, &imagelength);
  203.     TIFFSetField(out, TIFFTAG_IMAGELENGTH, imagelength-1);
  204.     TIFFSetField(out, TIFFTAG_BITSPERSAMPLE, 1);
  205.     TIFFSetField(out, TIFFTAG_SAMPLESPERPIXEL, 1);
  206.     TIFFSetField(out, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
  207.     TIFFSetField(out, TIFFTAG_COMPRESSION, compression);
  208.     TIFFSetField(out, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK);
  209.     TIFFSetField(out, TIFFTAG_FILLORDER, fillorder);
  210.     sprintf(thing, "Dithered B&W version of %s", argv[optind]);
  211.     TIFFSetField(out, TIFFTAG_IMAGEDESCRIPTION, thing);
  212.     CopyField(TIFFTAG_ORIENTATION, shortv);
  213.     CopyField(TIFFTAG_XRESOLUTION, floatv);
  214.     CopyField(TIFFTAG_YRESOLUTION, floatv);
  215.     CopyField(TIFFTAG_RESOLUTIONUNIT, shortv);
  216.     if (onestrip)
  217.         rowsperstrip = imagelength-1;
  218.     else
  219.         rowsperstrip = (8*1024)/TIFFScanlineSize(out);
  220.     TIFFSetField(out, TIFFTAG_ROWSPERSTRIP,
  221.         rowsperstrip == 0 ? 1 : rowsperstrip);
  222.     if (compression == COMPRESSION_CCITTFAX3 && group3options)
  223.         TIFFSetField(out, TIFFTAG_GROUP3OPTIONS, group3options);
  224.     fsdither(in, out);
  225.     TIFFClose(in);
  226.     TIFFClose(out);
  227. }
  228.