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

传真(Fax)编程

开发平台:

C/C++

  1. /* $Id: tiffcheck.c++,v 1.4 2008/01/02 20:38:34 faxguy Exp $ */
  2. /*
  3.  * Copyright (c) 1995-1996 Sam Leffler
  4.  * Copyright (c) 1995-1996 Silicon Graphics, Inc.
  5.  *
  6.  * Permission to use, copy, modify, distribute, and sell this software and 
  7.  * its documentation for any purpose is hereby granted without fee, provided
  8.  * that (i) the above copyright notices and this permission notice appear in
  9.  * all copies of the software and related documentation, and (ii) the names of
  10.  * Sam Leffler and Silicon Graphics may not be used in any advertising or
  11.  * publicity relating to the software without the specific, prior written
  12.  * permission of Sam Leffler and Silicon Graphics.
  13.  * 
  14.  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
  15.  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
  16.  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
  17.  * 
  18.  * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
  19.  * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
  20.  * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  21.  * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
  22.  * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
  23.  * OF THIS SOFTWARE.
  24.  */
  25. #include "Sys.h"
  26. #include "Str.h"
  27. #include "tiffio.h"
  28. static const char* appName;
  29. extern void fxFatal(const char* fmt, ...);
  30. static void
  31. usage(void)
  32. {
  33.     fxFatal("usage: %s"
  34. " [-r vertical-res]"
  35. " [-l page-length]"
  36. " [-w page-width]"
  37. " [-1] [-2] [-3]"
  38. " input.tif"
  39. , appName
  40. );
  41. }
  42. #define OK 0
  43. #define REJECT 0x1
  44. #define REFORMAT 0x2
  45. #define RESIZE 0x4
  46. #define REVRES 0x8
  47. #define REIMAGE 0x10
  48. static uint32 dataFormat = 0;
  49. static  bool useMMR = 0;
  50. static uint32 pageLength = 297;
  51. static uint32 pageWidth = 1728;
  52. static u_long vres = 98;
  53. static bool useUnlimitedLength = false;
  54. static int checkPageFormat(TIFF* tif, fxStr& emsg);
  55. int
  56. main(int argc, char* argv[])
  57. {
  58.     int c;
  59.     appName = argv[0];
  60.     while ((c = Sys::getopt(argc, argv, "r:l:w:U123")) != -1)
  61. switch (c) {
  62. case '1':
  63.     dataFormat &= ~GROUP3OPT_2DENCODING;
  64.     break;
  65. case '2':
  66.     dataFormat |= GROUP3OPT_2DENCODING;
  67.     break;
  68. case '3':
  69.     useMMR = 1;
  70.     break;
  71. case 'U':
  72.     useUnlimitedLength = true;
  73.     break;
  74. case 'l':
  75.     pageLength = (uint32) strtoul(optarg, NULL, 0);
  76.     break;
  77. case 'r':
  78.     vres = strtoul(optarg, NULL, 0);
  79.     break;
  80. case 'w':
  81.     pageWidth = (uint32) strtoul(optarg, NULL, 0);
  82.     break;
  83. case '?':
  84.     usage();
  85.     /*NOTREACHED*/
  86. }
  87.     if (argc - optind != 1)
  88. usage();
  89.     int status;
  90.     fxStr emsg;
  91.     TIFF* tif = TIFFOpen(argv[optind], "r");
  92.     /*
  93.      * Suppress libtiff warning messages from becoming fatal.
  94.      */
  95.     TIFFSetWarningHandler(NULL);
  96.     if (tif) {
  97. status = OK;
  98. do {
  99.     status |= checkPageFormat(tif, emsg);
  100. } while ((status & REJECT) == 0 && TIFFReadDirectory(tif));
  101. TIFFClose(tif);
  102.     } else {
  103. struct stat sb;
  104. if (Sys::stat(argv[optind], sb) < 0)
  105.     emsg = "Document file is unreadable or does not exist";
  106. else
  107.     emsg = "Document is not valid TIFF (unspecified format error)";
  108. status = REJECT;
  109.     }
  110.     if (status != OK) {
  111. const char* sep = "";
  112. if (status & REJECT)
  113.     printf("%sREJECT", sep), sep = "+";
  114. if (status & REFORMAT)
  115.     printf("%sREFORMAT", sep), sep = "+";
  116. if (status & RESIZE)
  117.     printf("%sRESIZE", sep), sep = "+";
  118. if (status & REVRES)
  119.     printf("%sREVRES", sep), sep = "+";
  120. if (status & REIMAGE)
  121.     printf("%sREIMAGE", sep), sep = "+";
  122. printf("n%s", (const char*) emsg);
  123.     } else
  124. printf("OKn");
  125.     return (0);
  126. }
  127. /*
  128.  * Check the format of a page against the capabilities
  129.  * of the modem (or the default capabilities if no modem
  130.  * is currently setup).
  131.  */
  132. static int
  133. checkPageFormat(TIFF* tif, fxStr& emsg)
  134. {
  135.     int status = OK;
  136.     uint16 bps;
  137.     TIFFGetFieldDefaulted(tif, TIFFTAG_BITSPERSAMPLE, &bps);
  138.     if (bps != 1) {
  139. emsg.append(fxStr::format(
  140.     "Document is not a bilevel image (bits/sample %u).n", bps));
  141. status |= REIMAGE;
  142.     }
  143.     uint16 spp;
  144.     TIFFGetFieldDefaulted(tif, TIFFTAG_SAMPLESPERPIXEL, &spp);
  145.     if (spp != 1) {
  146. emsg.append(fxStr::format(
  147.     "Document is a multi-sample image (samples/pixel %u).n", spp));
  148. status |= REIMAGE;
  149.     }
  150.     uint16 pmi;
  151.     TIFFGetFieldDefaulted(tif, TIFFTAG_PHOTOMETRIC, &pmi);
  152.     if (pmi != PHOTOMETRIC_MINISWHITE) {
  153. emsg.append(fxStr::format(
  154.     "Document is not black-on-white.n"));
  155. status |= REIMAGE;
  156.     }
  157.     uint16 compression = 0;
  158.     (void) TIFFGetField(tif, TIFFTAG_COMPRESSION, &compression);
  159.     if (useMMR) {
  160. if (compression != COMPRESSION_CCITTFAX4) {
  161.     emsg.append("Document requires reformatting, not in Group 4 format.n");
  162.     status |= REFORMAT;
  163. }
  164.     } else {
  165. if (compression != COMPRESSION_CCITTFAX3) {
  166.     emsg.append("Document requires reformatting, not in Group 3 format.n");
  167.     status |= REFORMAT;
  168. }
  169. uint32 g3opts = 0;
  170. (void) TIFFGetField(tif, TIFFTAG_GROUP3OPTIONS, &g3opts);
  171. if ((g3opts ^ dataFormat) & GROUP3OPT_2DENCODING) {
  172.     emsg.append("Document requires reformatting, not in 2DMR format.n");
  173.     status |= REFORMAT;
  174. }
  175.     }
  176.     /*
  177.      * FaxSend can handle multistrip MH and MR images (not MMR),
  178.      * but not if the strips are not in sequential order.
  179.      */
  180.     if (TIFFNumberOfStrips(tif) != 1) {
  181. emsg.append("Document should be reformatted as a single strip.n");
  182. status |= REFORMAT;
  183.     }
  184. #ifdef notdef
  185.     /*
  186.      * The server can handle images that have an MSB2LSB fill order.
  187.      */
  188.     uint16 fill;
  189.     (void) TIFFGetFieldDefaulted(tif, TIFFTAG_FILLORDER, &fill);
  190.     if (fill != FILLORDER_LSB2MSB) {
  191. emsg.append("Document should be reformatted with "
  192.     "LSB-to-MSB bit order.n");
  193. status |= REFORMAT;
  194.     }
  195. #endif
  196.     /*
  197.      * Try to deduce the vertical resolution of the image
  198.      * image.  This can be problematical for arbitrary TIFF
  199.      * images because vendors sometimes do not give the units.
  200.      * We, however, can depend on the info in images that
  201.      * we generate because we are careful to include valid info.
  202.      */
  203.     float yres, yresinch = .0F;
  204.     if (TIFFGetField(tif, TIFFTAG_YRESOLUTION, &yres)) {
  205. short resunit = RESUNIT_INCH; // TIFF spec default
  206. (void) TIFFGetField(tif, TIFFTAG_RESOLUTIONUNIT, &resunit);
  207. if (resunit == RESUNIT_INCH) {
  208.     yresinch = yres;
  209.     yres /= 25.4;
  210. } else
  211. if (resunit == RESUNIT_CENTIMETER) {
  212.     yresinch = yres * 25.4;
  213.     yres /= 10;
  214. } else
  215. if (resunit == RESUNIT_NONE) { // postscript units ?
  216.     yresinch = yres * 720.0;
  217.     yres /= 28.35;
  218. }
  219.     } else {
  220. /*
  221.  * No vertical resolution is specified, try
  222.  * to deduce one from the image length.
  223.  */
  224. uint32 l;
  225. TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &l);
  226. yres = (l < 1450 ? 98 : 196); // B4 at 98 lpi is ~1400 lines
  227.     }
  228.     // vres is in inches, compare inches to inches, allow 15 lpi variation
  229.     if ((u_long) yresinch > vres ? (u_long) yresinch - vres > 15 : vres - (u_long) yresinch > 15) {
  230. emsg.append(fxStr::format("Document requires reformatting to adjust"
  231.     " vertical resolution (convert to %lu, document is %lu).n",
  232.     vres, (u_long) yresinch));
  233. status |= REVRES;
  234.     }
  235.     /*
  236.      * Select page width according to the image width
  237.      * and vertical resolution.
  238.      */
  239.     uint32 w;
  240.     if (!TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &w)) {
  241. emsg = "Document is not valid TIFF (missing ImageWidth tag).n";
  242. return (REJECT);
  243.     }
  244.     if (w != pageWidth) {
  245. emsg.append(fxStr::format("Document requires resizing to adjust"
  246.     " page width (convert to %lu, document is %lu).n",
  247.     (u_long) pageWidth, (u_long) w));
  248. status |= RESIZE;
  249.     }
  250.     /*
  251.      * Select page length according to the image size and
  252.      * vertical resolution.  Note that if the resolution
  253.      * info is bogus, we may select the wrong page size.
  254.      * Note also that we're a bit lenient in places here
  255.      * to take into account sloppy coding practice (e.g.
  256.      * using 200 lpi for high-res facsimile.)
  257.      */
  258.     uint32 h = 0;
  259.     if (!TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &h)) {
  260. emsg = "Document is not valid TIFF (missing ImageLength tag).n";
  261. return (REJECT);
  262.     }
  263.     /*
  264.      * Ignore length check when unlimited length is used.
  265.      */
  266.     if (!useUnlimitedLength) {
  267. float len = h / (yres == 0 ? 1. : yres); // page length in mm
  268. if (pageLength != (uint32) -1 && len > pageLength) {
  269.     emsg.append(fxStr::format("Document requires resizing to adjust"
  270. " page length (convert to %lu, document is %lu).n",
  271. (u_long) pageLength, (u_long) len));
  272.     status |= RESIZE;
  273. }
  274.     }
  275.     return (status);
  276. }