imgtofax.c
上传用户:weiyuanprp
上传日期:2020-05-20
资源大小:1169k
文件大小:10k
源码类别:

传真(Fax)编程

开发平台:

C/C++

  1. /* $Id: imgtofax.c,v 1.2 2006/06/22 04:11:37 faxguy Exp $ */
  2. /*
  3.  * Copyright (c) 1990-1996 Sam Leffler
  4.  * Copyright (c) 1991-1996 Silicon Graphics, Inc.
  5.  * HylaFAX is a trademark of Silicon Graphics
  6.  *
  7.  * Permission to use, copy, modify, distribute, and sell this software and 
  8.  * its documentation for any purpose is hereby granted without fee, provided
  9.  * that (i) the above copyright notices and this permission notice appear in
  10.  * all copies of the software and related documentation, and (ii) the names of
  11.  * Sam Leffler and Silicon Graphics may not be used in any advertising or
  12.  * publicity relating to the software without the specific, prior written
  13.  * permission of Sam Leffler and Silicon Graphics.
  14.  * 
  15.  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
  16.  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
  17.  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
  18.  * 
  19.  * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
  20.  * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
  21.  * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  22.  * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
  23.  * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
  24.  * OF THIS SOFTWARE.
  25.  */
  26. /*
  27.  * Prepare SGI image files for transmission as facsimile.
  28.  * Each image is scaled to fit a standard page, sharpened
  29.  * with a hipass filter, gamma warp'd, and then dithered
  30.  * to a bilevel image.
  31.  *
  32.  * Output is a single TIFF Class F file with each image as
  33.  * a separate page/directory.
  34.  *
  35.  * Derived from Paul Haeberli's imgtofax program.
  36.  */
  37. #include <stdio.h>
  38. #include <math.h>
  39. #include <image.h>
  40. #include "hipass.h"
  41. #include "izoom.h"
  42. #include "lut.h"
  43. #include "lum.h"
  44. #include "tiffio.h"
  45. #include <stdarg.h>
  46. #include "PageSize.h"
  47. #define GAMMAVAL        0.8
  48. #define DEF_MARGIN 14
  49. #define DEF_TOPMARGIN 0
  50. #define DEF_BOTMARGIN 0
  51. static short sbuf[4096];
  52. static IMAGE* iimage;
  53. static highpass *hp;
  54. static zoom* zm;
  55. static TIFF* tif;
  56. static lut* lookup;
  57. static int npages;
  58. static int pixelWidth;
  59. static int pixelHeight;
  60. static int leftMargin = DEF_MARGIN;
  61. static int rightMargin = DEF_MARGIN;
  62. static int topMargin = DEF_TOPMARGIN;
  63. static int bottomMargin = DEF_BOTMARGIN;
  64. static int pageWidth;
  65. static int pageHeight;
  66. static float pageres = 196.; /* default is medium res */
  67. static long g3opts = GROUP3OPT_FILLBITS;
  68. static void
  69. fatal(char* va_alist, ...)
  70. #define fmt va_alist
  71. {
  72.     va_list ap;
  73.     va_start(ap, fmt);
  74.     fprintf(stderr, "sgi2fax: ");
  75.     vfprintf(stderr, fmt, ap);
  76.     fprintf(stderr, ".n");
  77.     va_end(ap);
  78.     exit(-1);
  79. }
  80. #undef fmt
  81. static void
  82. getimgrow(buf,y)
  83. short *buf;
  84. int y;
  85. {
  86.     getbwrow(iimage,buf,iimage->ysize-1-y);
  87. }
  88. static void
  89. getzrow(buf,y)
  90. short *buf;
  91. int y;
  92. {
  93.     getzoomrow(zm,buf,y);
  94. }
  95. static void
  96. tofax(short* wp, int n)
  97. {
  98. #define MAXXSIZE 2432
  99.     unsigned char row[(MAXXSIZE+7) &~ 7], *rp = row;
  100.     int bit = 0x80;
  101.     memset(row, 0, sizeof (row));
  102.     while (n-- > 0) {
  103. if (*wp++ < 128)
  104.     *rp |= bit;
  105. if ((bit >>= 1) == 0) {
  106.     rp++;
  107.     bit = 0x80;
  108. }
  109.     }
  110.     (void) TIFFWriteScanline(tif, row,
  111. TIFFCurrentRow(tif) == (uint32) -1 ? 0 : TIFFCurrentRow(tif), 0);
  112. }
  113. static float transfunc(f)
  114. float f;
  115. {
  116.     return pow(f,GAMMAVAL);
  117. }
  118. /* 
  119.  *      dithering stuff follows
  120.  *
  121.  */
  122. #define MATSIZE88
  123. #define XSIZE   8
  124. #define YSIZE   8
  125. #ifdef notdef
  126. static short Xdithmat[YSIZE][XSIZE] = {         /* 8x8 floyd-steinberg */
  127.         0,      8,      36,     44,     2,      10,     38,     46,
  128.         16,     24,     52,     60,     18,     26,     54,     62,
  129.         32,     40,     4,      12,     34,     42,     6,      14,
  130.         48,     56,     20,     28,     50,     58,     22,     30,
  131.         3,      11,     39,     47,     1,      9,      37,     45,
  132.         19,     27,     55,     63,     17,     25,     53,     61,
  133.         35,     43,     7,      15,     33,     41,     5,      13,
  134.         51,     59,     23,     31,     49,     57,     21,     29,
  135. };
  136. #endif
  137. static short dithmat[YSIZE][XSIZE] = {          /* halftone dots */
  138.         3,      17,     55,     63,     61,     47,     9,      1,
  139.         15,     29,     39,     51,     49,     35,     25,     13,
  140.         40,     32,     26,     20,     22,     30,     36,     42,
  141.         56,     44,     10,     4,      6,      18,     52,     58,
  142.         60,     46,     8,      0,      2,      16,     54,     62,
  143.         48,     34,     24,     12,     14,     28,     38,     50,
  144.         23,     31,     37,     43,     41,     33,     27,     21,
  145.         7,      19,     53,     59,     57,     45,     11,     5,
  146. };
  147. #define TOTAL           (XSIZE*YSIZE)
  148. static ditherrow(buf,y,n)
  149. short *buf;
  150. int y, n;
  151. {
  152.     int r, val;
  153.     int rshades, rmaxbits;
  154.     short *rdith;
  155.     rdith = &dithmat[y%YSIZE][0];
  156.     rshades = TOTAL+1;
  157.     rmaxbits = ((rshades-1)/TOTAL);
  158.     while(n--) {
  159.         r = *buf;
  160.         val = (rshades*r)/255;
  161.         if(val>=TOTAL) 
  162.             *buf++ = 255;
  163.         else if(val>rdith[n%XSIZE])
  164.             *buf++ = 255;
  165.         else
  166.             *buf++ = 0;
  167.     }
  168. }
  169. static void
  170. blankSpace(int nrows)
  171. {
  172.     setrow(sbuf,255,pixelWidth);
  173.     while (nrows-- > 0)
  174.         tofax(sbuf,pixelWidth);
  175. }
  176. static void
  177. imgtofax(char* input, int pn)
  178. {
  179.     int ixsize, iysize;
  180.     int oxsize, oysize;
  181.     int ymargin;
  182.     int y;
  183.     TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, (long) pixelWidth);
  184.     TIFFSetField(tif, TIFFTAG_IMAGELENGTH, (long) pixelHeight);
  185.     TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, -1L);
  186.     TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 1);
  187.     TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 1);
  188.     TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
  189.     TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_CCITTFAX3);
  190.     TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISWHITE);
  191.     TIFFSetField(tif, TIFFTAG_FILLORDER, FILLORDER_LSB2MSB);
  192.     TIFFSetField(tif, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH);
  193.     TIFFSetField(tif, TIFFTAG_XRESOLUTION, 204.);
  194.     TIFFSetField(tif, TIFFTAG_YRESOLUTION, pageres);
  195.     TIFFSetField(tif, TIFFTAG_PAGENUMBER, pn, npages);
  196.     TIFFSetField(tif, TIFFTAG_CLEANFAXDATA, CLEANFAXDATA_CLEAN);
  197.     { char buf[1024];
  198.       snprintf(buf, sizeof(buf) - 1, "Ditherered B&W version of %s", input);
  199.       TIFFSetField(tif, TIFFTAG_IMAGEDESCRIPTION, buf);
  200.     }
  201.     TIFFSetField(tif, TIFFTAG_SOFTWARE, "sgi2fax");
  202.     TIFFSetField(tif, TIFFTAG_ORIENTATION, ORIENTATION_BOTLEFT);
  203.     TIFFSetField(tif, TIFFTAG_GROUP3OPTIONS, g3opts);
  204. /* calculate the zoom factor */
  205.     ixsize = iimage->xsize;
  206.     iysize = iimage->ysize;
  207.     oxsize = pageWidth;
  208.     oysize = (iysize*pageWidth)/ixsize; /* maintain aspect ratio */
  209.     if (pageres == 98.)
  210. oysize /= 2;
  211. /* set up the filters */
  212.     zm = newzoom(getimgrow, ixsize, iysize, oxsize, oysize, TRIANGLE, 1.0);
  213.     hp = newhp(getzrow, oxsize, oysize, 2.0);
  214.     ymargin = (pageHeight-oysize)/2;
  215.     if(ymargin<0)
  216.         ymargin = 0;
  217.     blankSpace(topMargin + ymargin);
  218.     for(y=0; y<oysize; y++) {
  219.         hpgetrow(hp, sbuf, y); 
  220.         applylut(lookup, sbuf, oxsize);
  221.         ditherrow(sbuf, y, oxsize);
  222.         tofax(sbuf, pixelWidth);
  223.     }
  224.     blankSpace(bottomMargin + ymargin);
  225.     freezoom(zm);
  226.     freehp(hp);
  227.     TIFFWriteDirectory(tif);
  228. }
  229. static void
  230. usage()
  231. {
  232.     fprintf(stderr, "usage: sgi2fax %s %s %s %s %s %s %s [-12] file ...n",
  233. "[-h height]",
  234. "[-w width]",
  235. "[-v vres]",
  236. "[-o output]",
  237. "[-r %red]",
  238. "[-g %green]",
  239. "[-b %blue]",
  240. ""
  241.     );
  242.     exit(-1);
  243. }
  244. #define CVT(x) (((x)*255)/100)
  245. main(argc, argv)
  246.     int argc;
  247.     char **argv;
  248. {
  249.     extern int optind;
  250.     extern char* optarg;
  251.     char* output = "sgi.fax";
  252.     int c;
  253.     float w, h;
  254.     struct pageSizeInfo* info;
  255.     info = getPageSize("default");
  256.     w = getPageWidth(info);
  257.     h = getPageHeight(info);
  258.     delPageSize(info);
  259.     while ((c = Sys::getopt(argc, argv, "o:r:g:b:h:s:v:w:12")) != -1)
  260. switch (c) {
  261. case '1':
  262.     g3opts &= ~GROUP3OPT_2DENCODING;
  263.     break;
  264. case '2':
  265.     g3opts |= GROUP3OPT_2DENCODING;
  266.     break;
  267. case 'r': /* %red illumination */
  268.     _RILUM = CVT(atoi(optarg));
  269.     break;
  270. case 'g': /* %green illumination */
  271.     _GILUM = CVT(atoi(optarg));
  272.     break;
  273. case 'b': /* %blue illumination */
  274.     _BILUM = CVT(atoi(optarg));
  275.     break;
  276. case 'o': /* output file */
  277.     output = optarg;
  278.     break;
  279. case 's': /* page size */
  280.     info = getPageSize(optarg);
  281.     if (!info) {
  282. fprintf(stderr, "%s: Unknown page size "%s".n",
  283.     argv[0], optarg);
  284. exit(-1);
  285.     }
  286.     w = getPageWidth(info);
  287.     h = getPageHeight(info);
  288.     delPageSize(info);
  289.     break;
  290. case 'v': /* vertical resolution (lines/inch) */
  291.     pageres = atof(optarg);
  292.     /* XXX force acceptable resolutions */
  293.     if (pageres < 120.)
  294. pageres = 98.;
  295.     else
  296. pageres = 196.;
  297.     break;
  298. case 'w': /* page width (mm) */
  299.     w = atof(optarg);
  300.     break;
  301. case 'h': /* page height (mm) */
  302.     h = atof(optarg);
  303.     break;
  304. case '?':
  305.     usage();
  306. }
  307.     if (argc - optind < 1)
  308. usage();
  309.     /* XXX force known sizes */
  310.     if (w > 280)
  311. pixelWidth = 2432;
  312.     else if (w > 230)
  313. pixelWidth = 2048;
  314.     else
  315. pixelWidth = 1728;
  316.     if (h > 350)
  317. pixelHeight = 2810;
  318.     else if (h > 280)
  319. pixelHeight = 2292;
  320.     else
  321. pixelHeight = 2166;
  322.     if (pageres == 98.) {
  323. pixelHeight /= 2;
  324. topMargin /= 2;
  325. bottomMargin /= 2;
  326.     }
  327.     pageWidth = pixelWidth - (leftMargin + rightMargin);
  328.     pageHeight = pixelHeight - (topMargin + bottomMargin);
  329. /* open the output file */
  330.     tif = TIFFOpen(output, "w");
  331.     if (!tif)
  332. fatal("%s: Can not create output file", output);
  333.     lookup = makelut(transfunc,256,256,0);
  334.     npages = argc - optind;
  335.     for (c = 0; optind < argc; c++, optind++) {
  336. iimage = iopen(argv[optind], "r");
  337. if (!iimage) {
  338.     fprintf(stderr, "sgi2fax: %s: Can not openn", argv[optind]);
  339.     continue;
  340. }
  341. imgtofax(argv[optind], c);
  342.     }
  343.     TIFFClose(tif);
  344.     freelut(lookup);
  345.     exit(0);
  346. }