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

传真(Fax)编程

开发平台:

C/C++

  1. /* $Id: tagtest.c++,v 1.6 2008/01/01 01:21:42 faxguy Exp $ */
  2. /*
  3.  * Copyright (c) 1994-1996 Sam Leffler
  4.  * Copyright (c) 1994-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.  * Program for testing tag line imaging support.
  28.  *
  29.  * Usage: tagtest [-f fontfile] [-m format] [-o output.tif] [-l locale] input.tif
  30.  */
  31. #include "Sys.h"
  32. #include "PCFFont.h"
  33. #include "StackBuffer.h"
  34. #include "FaxFont.h"
  35. #include "tiffio.h"
  36. #include "Class2Params.h"
  37. #if HAS_LOCALE
  38. extern "C" {
  39. #include <locale.h>
  40. }
  41. #endif
  42. #if HAS_LANGINFO
  43. extern "C" {
  44. #ifndef __USE_XOPEN
  45. #define __USE_XOPEN
  46. #endif
  47. #include <langinfo.h>
  48. }
  49. #endif
  50. u_int tagLineSlop;
  51. FaxFont* tagLineFont;
  52. u_int pageNumber = 1;
  53. u_int totalPages;
  54. fxStr tagLineFmt("From %%n|%c|Page %%p of %%t");
  55. fxStr tagLineLocale("");
  56. fxStr tagLineFontFile("fixed.pcf");
  57. fxStr jobid("9733");
  58. fxStr jobtag("sendq/q9733");
  59. fxStr localid("Sam's Bar&Grill");
  60. fxStr modemnumber("+15105268781");
  61. fxStr mailaddr("sam@flake.asd.sgi.com");
  62. fxStr external("+14159657824");
  63. fxStr sender("Sam Leffler");
  64. fxStr tagLine;
  65. u_int tagLineFields;
  66. static void
  67. insert(fxStr& tag, u_int l, const fxStr& s)
  68. {
  69.     tag.remove(l,2);
  70.     tag.insert(s, l);
  71. }
  72. /*
  73.  * Read in the PCF font to use for imaging the tag line and
  74.  * preformat as much of the tag line as possible.
  75.  */
  76. void
  77. setupTagLine()
  78. {
  79.     if (tagLineFont == NULL)
  80. tagLineFont = new PCFFont;
  81.     if (!tagLineFont->isReady() && tagLineFontFile != "")
  82. (void) tagLineFont->read(tagLineFontFile);
  83. #ifdef LC_CTYPE
  84.     setlocale(LC_CTYPE, tagLineLocale); // for <ctype.h> calls
  85. #endif
  86. #ifdef LC_TIME
  87.     setlocale(LC_TIME, tagLineLocale); // for strftime calls
  88. #endif
  89.     bool isutf8 = false;
  90. #if HAS_LANGINFO
  91.     isutf8 = (strcmp(nl_langinfo(CODESET), "UTF-8") == 0);
  92.     tagLine.setUTF8(isutf8);
  93. #endif
  94.     time_t t = Sys::now();
  95.     tm* tm = localtime(&t);
  96.     char line[1024];
  97.     strftime(line, sizeof (line), tagLineFmt, tm);
  98.     tagLine = line;
  99.     u_int l = 0;
  100.     while (l < tagLine.length()) {
  101. l = tagLine.next(l, '%');
  102. if (l >= tagLine.length()-1)
  103.     break;
  104. switch (tagLine[l+1]) {
  105. case 'd': insert(tagLine, l, external); break;
  106. case 'i': insert(tagLine, l, jobid); break;
  107. case 'j': insert(tagLine, l, jobtag); break;
  108. case 'l': insert(tagLine, l, localid); break;
  109. case 'm': insert(tagLine, l, mailaddr); break;
  110. case 'n': insert(tagLine, l, modemnumber); break;
  111. case 's': insert(tagLine, l, sender); break;
  112. /* for the purpose of tagtest %%T is the same of %%t */
  113. case 't':   
  114. case 'T': insert(tagLine, l, fxStr((int) totalPages, "%u")); break;
  115. default:  l += 2; break;
  116. }
  117.     }
  118.     /*
  119.      * Break the tag into fields.
  120.      */
  121.     tagLineFields = 0;
  122.     for (l = 0; l < tagLine.length(); l = tagLine.next(l+1, '|'))
  123. tagLineFields++;
  124. }
  125. #define MARGIN_TOP 2
  126. #define MARGIN_BOT 2
  127. #define MARGIN_LEFT 2
  128. #define MARGIN_RIGHT 2
  129. #define SLOP_LINES 3
  130. bool
  131. setupTagLineSlop(const Class2Params& params)
  132. {
  133.     if (tagLineFont->isReady()) {
  134. tagLineSlop = (tagLineFont->fontHeight()+MARGIN_TOP+MARGIN_BOT+SLOP_LINES) * 
  135.     howmany(params.pageWidth(),8);
  136. return (true);
  137.     } else
  138. return (false);
  139. }
  140. #include "MemoryDecoder.h"
  141. /*
  142.  * Image the tag line in place of the top few lines of the page
  143.  * data and return the encoded tag line at the front of the
  144.  * data buffer.  The buffer that holds the page data is assumed
  145.  * to have tagLineSlop extra space allocated in front of the
  146.  * page data.  The tag line format string is assumed to be
  147.  * preprocessed by setupTagLine above so that we only need to
  148.  * setup the current page number.
  149.  */
  150. u_char*
  151. imageTagLine(u_char* buf, u_int fillorder, const Class2Params& params, u_long& totdata)
  152. {
  153.     u_int l;
  154. #ifdef LC_CTYPE
  155.     setlocale(LC_CTYPE, tagLineLocale); // for <ctype.h> calls
  156. #endif
  157. #ifdef LC_TIME
  158.     setlocale(LC_TIME, tagLineLocale); // for strftime calls
  159. #endif
  160.     bool isutf8 = false;
  161. #if HAS_LANGINFO
  162.     isutf8 = (strcmp(nl_langinfo(CODESET), "UTF-8") == 0);
  163.     tagLine.setUTF8(isutf8);
  164. #endif
  165.     /*
  166.      * Fill in any per-page variables used in the tag line.
  167.      */
  168.     fxStr tag = tagLine;
  169.     l = 0;
  170.     while (l < tag.length()) {
  171. l = tag.next(l, '%');
  172. if (l >= tag.length()-1)
  173.     break;
  174. /* for the purpose of tagtest %%P is the same of %%p */
  175. if (tag[l+1] == 'p' || tag[l+1] == 'P')
  176.     insert(tag, l, fxStr((int) pageNumber, "%d"));
  177. else
  178.     l += 2;
  179.     }
  180.     /*
  181.      * Setup the raster in which the tag line is imaged.
  182.      *
  183.      * The font size information received from the font functions
  184.      * are suitable for VR_FINE.  Thus VR_FINE is used as the reference
  185.      * resolution, and all other resolutions must be scaled.
  186.      */
  187.     u_int w = params.pageWidth();
  188.     u_int h = (tagLineFont->fontHeight()*2)+MARGIN_TOP+MARGIN_BOT; // max height - double VR_FINE
  189.     u_int th = 0; // actual tagline height
  190.     switch(params.vr) {
  191. case VR_NORMAL:
  192. case VR_200X100:
  193.     th = (tagLineFont->fontHeight()/2)+MARGIN_TOP+MARGIN_BOT; // half VR_FINE
  194.     break;
  195. case VR_FINE:
  196. case VR_200X200:
  197.     th = tagLineFont->fontHeight()+MARGIN_TOP+MARGIN_BOT; // reference resolution
  198.     break;
  199. case VR_R8:
  200. case VR_R16:
  201. case VR_200X400:
  202. case VR_300X300:        // not proportionate but legible
  203.     th = (tagLineFont->fontHeight()*2)+MARGIN_TOP+MARGIN_BOT; // double VR_FINE
  204.     break;
  205.     }
  206.     /*
  207.      * imageText assumes that raster is word-aligned; we use
  208.      * longs here to optimize the scaling done below for the
  209.      * low res case.  This should satisfy the word-alignment.
  210.      */
  211.     u_int lpr = howmany(w,sizeof(u_long)*8); // longs/raster row
  212.     u_long* raster = new u_long[(h+SLOP_LINES)*lpr]; // decoded raster
  213.     memset(raster,0,(h+SLOP_LINES)*lpr*sizeof (u_long));// clear raster to white
  214.     /*
  215.      * Break the tag into fields and render each piece of
  216.      * text centered in its field.  Experiments indicate
  217.      * that rendering the text over white is better than,
  218.      * say, rendering it over the original page.
  219.      */
  220.     l = 0;
  221.     /*  
  222.      * imageText produces good dimensioned fonts at 1728 pixels/row. At VR_R16
  223.      * and VR_300X300, both being wider than 1728, text appears shrinked
  224.      * horizontally; while VR_300 is still ok, VR_R16 is too small. To help
  225.      * streching the text horizontally we force text imaging to still use
  226.      * 1728 instead of VR_R16's 3456 (3456 / 2 = 1728); text will be
  227.      * imaged the 1st (left) half of the line, it will be stretched after
  228.      * imaging takes place.
  229.      */
  230.     u_int fieldWidth = params.pageWidth() / (params.vr == VR_R16 ? 2 : 1) / tagLineFields;
  231.     for (u_int f = 0; f < tagLineFields; f++) {
  232. fxStr tagField = tag.token(l, '|');
  233. u_int fw, fh;
  234. tagLineFont->strWidth(tagField, fw, fh);
  235. u_int xoff = f*fieldWidth;
  236. if (fw < fieldWidth)
  237.     xoff += (fieldWidth-fw)/2;
  238. else
  239.     xoff += MARGIN_LEFT;
  240. (void) tagLineFont->imageText(tagField, isutf8, (u_short*) raster, w, h,
  241.     xoff, MARGIN_RIGHT, MARGIN_TOP, MARGIN_BOT);
  242.     }
  243.     /*
  244.      * Scale image data as needed (see notes above).
  245.      */
  246.     if (params.vr == VR_NORMAL || params.vr == VR_200X100) {
  247. /*
  248.  * These resolutions require vertical "shrinking" of the
  249.  * tagline image.  We make 1 line out of 2.
  250.  * (Note the ``or'' used to generate the final samples.)
  251.  *
  252.  * Details:  
  253.  * - image is in lines 1 through y
  254.  * - available lines are 1 through y/2
  255.  * - start at the top of the image
  256.  * - line 1 is ORed with line 2 to get new line 1
  257.  * - line 3 is ORed with line 4 to get new line 2
  258.  * - ...
  259.  * - line y is ORed with line y+1 to get new line (y+1)/2
  260.  */
  261. u_long* l1 = raster+MARGIN_TOP*lpr;
  262. u_long* l2 = l1+lpr;
  263. u_long* l3 = raster+MARGIN_TOP*lpr;
  264. for (u_int nr = th-(MARGIN_TOP+MARGIN_BOT); nr; nr--) {
  265.     for (u_int nl = lpr; nl; nl--)
  266. *l3++ = *l1++ | *l2++;
  267.     l1 += lpr;
  268.     l2 += lpr;
  269. }
  270. memset(l3, 0, MARGIN_BOT*lpr*sizeof (u_long));
  271.     }
  272.     if (params.vr == VR_R8 || params.vr == VR_R16 || params.vr == VR_200X400 || params.vr == VR_300X300) {
  273. /*
  274.  * These resolutions require vertical "stretching" of the
  275.  * tagline image.  We make 2 lines out of 1.
  276.  * Go bottom-to-top since the image resides in the top half and the
  277.  * bottom data can be overwritten since it is unset.
  278.  * 
  279.  * Details:
  280.  * - image is in lines 1 through y/2
  281.  * - available lines are 1 through y
  282.  * - we use 2 pointers, 1st starting at line y/2 the other at line y
  283.  * - line y/2   copied in line y   and y-1
  284.  * - line y/2-1 copied in line y-2 and y-2-1
  285.  * - ...
  286.  */
  287. // bottom of actual image
  288. u_long* l1 = raster - 1 + lpr * (MARGIN_TOP + (th-MARGIN_TOP-MARGIN_BOT)/2 + 2);
  289. // bottom of available image
  290. u_long* l2 = raster - 1 + lpr * (MARGIN_TOP + (th-MARGIN_TOP-MARGIN_BOT) + 1);
  291. /* stretch vertically (going backwards, R->L, B->T) */
  292. for (u_int nr = (th-(MARGIN_TOP+MARGIN_BOT))/2; nr; nr--) {
  293.     for (u_int nl = lpr; nl; nl--) { 
  294. *(l2 - lpr) = *l1; /* y/2 copied into y-1 */
  295. *l2 = *l1; /* y/2 copied into y */ 
  296. l2--; /* left 1 long */
  297. l1--; /* left 1 long */
  298.     }
  299.     /* after previous loop, l1 and l2 are up 1 line; l2 needs 1 more */
  300.     l2 -= lpr; /* 2nd ptr up 1 line */
  301. }
  302. if (params.vr == VR_R16) {
  303.     /*
  304.      * hr is twice the hr in which data is imaged.
  305.      * We need to strech the image horizontally:
  306.      * 1234567890ABCDEFGHIJ -> 11223344556677889900
  307.      * (ABCDEFGHIJ is whitespace)
  308.      */
  309.     /* Reset ptr to begin of image */
  310.     l1 = raster + MARGIN_TOP*lpr;               // begin of 1st line
  311.     l2 = raster + MARGIN_TOP*lpr + lpr - 1;     // end of 1st line
  312.     for (u_int nr = th-(MARGIN_TOP+MARGIN_BOT); nr; nr--) {
  313. /*
  314.  * 0      lpr/2      lpr
  315.  * |        |         |
  316.  * 1234567890__________
  317.  * 1234567890________00  x/2   copied into x   and x-1
  318.  * 1234567890______9900  x/2-1 copied into x-2 and x-3
  319.  * ...
  320.  * 11223344556677889900
  321.  */
  322. u_int bpl = sizeof(u_long) * 8; // bits per u_long
  323. for (u_int nl = lpr/2 - 1; nl ; nl--) {
  324.     // make 2 longs out of 1 (ABCD -> AABB CCDD)
  325.     int pos = 0;
  326.     for (u_int i = 0; i < (bpl/8); i++) {
  327. if (i == 0 || i == bpl/8/2) {
  328.     *l2 = (u_long) 0;
  329.     pos = bpl - 2;
  330. }
  331. // put pairs of bits from l1 into the right places within l2
  332. *l2 |= (u_long)((*(l1+nl) & (1<<(bpl-8*i-5))) >> (bpl-8*i-5) << pos);
  333. *l2 |= ((u_long)((*(l1+nl) & (1<<(bpl-8*i-5))) >> (bpl-8*i-5) << pos)) << 1;
  334. pos -= 2;
  335. *l2 |= (u_long)((*(l1+nl) & (1<<(bpl-8*i-6))) >> (bpl-8*i-6) << pos);
  336. *l2 |= ((u_long)((*(l1+nl) & (1<<(bpl-8*i-6))) >> (bpl-8*i-6) << pos)) << 1;
  337. pos -= 2;
  338. *l2 |= (u_long)((*(l1+nl) & (1<<(bpl-8*i-7))) >> (bpl-8*i-7) << pos);
  339. *l2 |= ((u_long)((*(l1+nl) & (1<<(bpl-8*i-7))) >> (bpl-8*i-7) << pos)) << 1;
  340. pos -= 2;
  341. *l2 |= (u_long)((*(l1+nl) & (1<<(bpl-8*i-8))) >> (bpl-8*i-8) << pos);
  342. *l2 |= ((u_long)((*(l1+nl) & (1<<(bpl-8*i-8))) >> (bpl-8*i-8) << pos)) << 1;
  343. pos -= 2;
  344. *l2 |= (u_long)((*(l1+nl) & (1<<(bpl-8*i-1))) >> (bpl-8*i-1) << pos);
  345. *l2 |= ((u_long)((*(l1+nl) & (1<<(bpl-8*i-1))) >> (bpl-8*i-1) << pos)) << 1;
  346. pos -= 2;
  347. *l2 |= (u_long)((*(l1+nl) & (1<<(bpl-8*i-2))) >> (bpl-8*i-2) << pos);
  348. *l2 |= ((u_long)((*(l1+nl) & (1<<(bpl-8*i-2))) >> (bpl-8*i-2) << pos)) << 1;
  349. pos -= 2;
  350. *l2 |= (u_long)((*(l1+nl) & (1<<(bpl-8*i-3))) >> (bpl-8*i-3) << pos);
  351. *l2 |= ((u_long)((*(l1+nl) & (1<<(bpl-8*i-3))) >> (bpl-8*i-3) << pos)) << 1;
  352. pos -= 2;
  353. *l2 |= (u_long)((*(l1+nl) & (1<<(bpl-8*i-4))) >> (bpl-8*i-4) << pos);
  354. *l2 |= ((u_long)((*(l1+nl) & (1<<(bpl-8*i-4))) >> (bpl-8*i-4) << pos)) << 1;
  355. pos -= 2;
  356. if (pos < 0) *l2--;
  357.     }
  358. }
  359. l1 += lpr;              // begin of next line
  360. l2 = l1 + lpr - 1;      // end of next line
  361.     }
  362. }
  363. memset(l2, 0, MARGIN_BOT*lpr*sizeof (u_long));
  364.     }
  365.     MemoryDecoder dec(buf, w, totdata, fillorder, params.is2D(), (params.df == DF_2DMMR));
  366.     u_char* encbuf = dec.encodeTagLine(raster, th, tagLineSlop);
  367.     totdata = dec.getCC();
  368.     return (encbuf);
  369. }
  370. void
  371. vlogError(const char* fmt, va_list ap)
  372. {
  373.     vfprintf(stderr, fmt, ap);
  374.     fputs(".n", stderr);
  375. }
  376. // NB: must duplicate this to avoid pulling faxApp&co.
  377. extern "C" void
  378. _fxassert(const char* msg, const char* file, int line)
  379. {
  380.     fprintf(stderr, "Assertion failed "%s", file "%s" line %d.n", 
  381. msg, file, line);
  382.     abort();
  383.     /*NOTREACHED*/
  384. }
  385. const char* appName;
  386. void
  387. usage()
  388. {
  389.     fprintf(stderr,
  390. "usage: %s [-m format] [-o t.tif] [-f font.pcf] [-l locale] input.tifn",
  391. appName);
  392.     exit(-1);
  393. }
  394. void
  395. fatal(const char* fmt ...)
  396. {
  397.     fprintf(stderr, "%s: ", appName);
  398.     va_list ap;
  399.     va_start(ap, fmt);
  400.     vfprintf(stderr, fmt, ap);
  401.     va_end(ap);
  402.     fputs(".n", stderr);
  403.     exit(-1);
  404. }
  405. int
  406. main(int argc, char* argv[])
  407. {
  408.     extern int optind;
  409.     extern char* optarg;
  410.     int c;
  411.     const char* output = "t.tif";
  412. #ifdef LC_CTYPE
  413.     setlocale(LC_CTYPE, ""); // for <ctype.h> calls
  414. #endif
  415. #ifdef LC_TIME
  416.     setlocale(LC_TIME, ""); // for strftime calls
  417. #endif
  418.     appName = argv[0];
  419.     while ((c = Sys::getopt(argc, argv, "f:l:m:o:")) != -1)
  420. switch (c) {
  421. case 'f':
  422.     tagLineFontFile = optarg;
  423.     break;
  424. case 'l':
  425.     tagLineLocale = optarg;
  426.     break;
  427. case 'm':
  428.     tagLineFmt = optarg;
  429.     break;
  430. case 'o':
  431.     output = optarg;
  432.     break;
  433. case '?':
  434.     usage();
  435.     /*NOTREACHED*/
  436. }
  437.     if (argc - optind != 1)
  438. usage();
  439.     TIFF* tif = TIFFOpen(argv[optind], "r");
  440.     if (!tif)
  441. fatal("%s: Cannot open, or not a TIFF file", argv[optind]);
  442.     uint16 comp;
  443.     TIFFGetField(tif, TIFFTAG_COMPRESSION, &comp);
  444.     if (comp != COMPRESSION_CCITTFAX3 && comp != COMPRESSION_CCITTFAX4)
  445. fatal("%s: Not a Group 3 or Group 4-encoded TIFF file", argv[optind]);
  446.     setupTagLine();
  447.     if (!tagLineFont->isReady())
  448. fatal("%s: Problem reading font", (const char*) tagLineFontFile);
  449.     TIFF* otif = TIFFOpen(output, "w");
  450.     if (!otif)
  451. fatal("%s: Cannot create output file", output);
  452.     for (totalPages = 1; TIFFReadDirectory(tif); totalPages++)
  453. ;
  454.     TIFFSetDirectory(tif, 0);
  455.     Class2Params params;
  456.     params.vr = VR_NORMAL;
  457.     params.wd = WD_A4;
  458.     params.ln = LN_INF;
  459.     params.df = DF_1DMH;
  460.     pageNumber = 1;
  461.     setupTagLine();
  462.     do {
  463. uint32 l, w;
  464. TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &l);
  465. TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &w);
  466. TIFFSetField(otif, TIFFTAG_SUBFILETYPE, FILETYPE_PAGE);
  467. TIFFSetField(otif, TIFFTAG_IMAGEWIDTH, w);
  468. /* 
  469.  * Values sampled using tiffinfo on tif generated by ps2fax
  470.  * VR_NORMAL     w=1728 l=1169
  471.  * VR_100X200    w=1728 l=?
  472.  * VR_FINE       w=1728 l=2292
  473.  * VR_200X200    w=1728 l=2339
  474.  * VR_R8         w=1728 l=4573
  475.  * VR_200X400    w=1728 l=4578
  476.  * VR_300X300    w=2592 l=3508
  477.  * VR_R16        w=3456 l=4573
  478.  *
  479.  * To simplify the setting of params.vr we use:
  480.  * VR_NORMAL in place of VR_100X200
  481.  * VR_FINE   in place of VR_200X200
  482.  * VR_R8     in place of VR_200X400
  483.  * for the purpose of imaging tagline this shouldn't make a difference 
  484.  *
  485.  */
  486. if (w <= 2000)
  487.     params.vr = (l < 1500 ? VR_NORMAL : l < 3000 ? VR_FINE : VR_R8);
  488. else if (w <= 3000)
  489.     params.vr = VR_300X300;
  490. else
  491.     params.vr = VR_R16;
  492. TIFFSetField(otif, TIFFTAG_XRESOLUTION, (float) params.horizontalRes());
  493. TIFFSetField(otif, TIFFTAG_YRESOLUTION, (float) params.verticalRes());
  494. TIFFSetField(otif, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH);
  495. TIFFSetField(otif, TIFFTAG_IMAGELENGTH, l);
  496. TIFFSetField(otif, TIFFTAG_BITSPERSAMPLE, 1);
  497. TIFFSetField(otif, TIFFTAG_SAMPLESPERPIXEL, 1);
  498. TIFFSetField(otif, TIFFTAG_FILLORDER, FILLORDER_LSB2MSB);
  499. TIFFSetField(otif, TIFFTAG_FILLORDER, FILLORDER_LSB2MSB);
  500. uint32 r;
  501. TIFFGetFieldDefaulted(tif, TIFFTAG_ROWSPERSTRIP, &r);
  502. TIFFSetField(otif, TIFFTAG_ROWSPERSTRIP, r);
  503. TIFFSetField(otif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
  504. TIFFSetField(otif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISWHITE);
  505. TIFFSetField(otif, TIFFTAG_COMPRESSION, comp);
  506. uint32 opts = 0;
  507. if (comp != COMPRESSION_CCITTFAX4) {
  508.     TIFFGetField(tif, TIFFTAG_GROUP3OPTIONS, &opts);
  509.     params.df = (opts & GROUP3OPT_2DENCODING) ? DF_2DMR : DF_1DMH;
  510.     TIFFSetField(otif, TIFFTAG_GROUP3OPTIONS, opts);
  511. } else {
  512.     TIFFGetField(tif, TIFFTAG_GROUP4OPTIONS, &opts);
  513.             params.df = DF_2DMMR;
  514.     TIFFSetField(tif, TIFFTAG_GROUP4OPTIONS, opts);
  515. }
  516. uint16 o;
  517. if (TIFFGetField(otif, TIFFTAG_ORIENTATION, &o))
  518.     TIFFSetField(tif, TIFFTAG_ORIENTATION, o);
  519. uint16 fillorder;
  520. TIFFGetFieldDefaulted(tif, TIFFTAG_FILLORDER, &fillorder);
  521. uint32* stripbytecount;
  522. (void) TIFFGetField(tif, TIFFTAG_STRIPBYTECOUNTS, &stripbytecount);
  523. bool firstStrip = setupTagLineSlop(params);
  524. u_int ts = tagLineSlop;
  525. for (u_int strip = 0; strip < TIFFNumberOfStrips(tif); strip++) {
  526.     u_long totbytes = (u_long) stripbytecount[strip];
  527.     if (totbytes > 0) {
  528. u_char* data = new u_char[totbytes+ts];
  529. if (TIFFReadRawStrip(tif, strip, data+ts, totbytes) >= 0) {
  530.     u_char* dp;
  531.     if (firstStrip) {
  532. uint32 rowsperstrip;
  533. TIFFGetFieldDefaulted(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip);  
  534. if (rowsperstrip == (uint32) -1)
  535.     TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &rowsperstrip);
  536. /*
  537.  * Generate tag line at the top of the page.
  538.  */
  539. u_long totdata = totbytes;
  540. dp = imageTagLine(data+ts, fillorder, params, totdata);
  541. totbytes = (params.df == DF_2DMMR) ? totdata : totbytes+ts - (dp-data);
  542. firstStrip = false;
  543.     } else
  544. dp = data;
  545.     if (fillorder != FILLORDER_LSB2MSB)
  546. TIFFReverseBits(dp, totbytes);
  547.     if (TIFFWriteRawStrip(otif, strip, dp, totbytes) == -1)
  548. fatal("%s: Write error at strip %u, writing %lu bytes", 
  549.     output, strip, (u_long) totbytes);
  550. }
  551. delete data;
  552.     }
  553. }
  554. pageNumber++;
  555.     } while (TIFFReadDirectory(tif) && TIFFWriteDirectory(otif));
  556.     TIFFClose(otif);
  557.     return (0);
  558. }