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

传真(Fax)编程

开发平台:

C/C++

  1. /* $Id: MemoryDecoder.c++,v 1.6 2007/11/04 01:45:30 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.  * Phase C data correction and page chopping support.
  28.  */
  29. #include "MemoryDecoder.h"
  30. #include "G3Encoder.h"
  31. #include "StackBuffer.h"
  32. #include "config.h"
  33. MemoryDecoder::MemoryDecoder(u_char* data, u_long n)
  34. {
  35.     bp = data;
  36.     cc = n;
  37.     endOfData = NULL;
  38.     nblanks = 0;
  39.     runs = NULL;
  40.     rowBuf = NULL;
  41.     rows = 0;
  42. }
  43. MemoryDecoder::MemoryDecoder(u_char* data, u_int wid, u_long n,
  44.                              u_int order, bool twoDim, bool mmr)
  45. {
  46.     bp         = data;
  47.     width      = wid;
  48.     byteWidth  = howmany(width, 8);
  49.     cc         = n;
  50.     rows       = 0;
  51.     
  52.     fillorder  = order;
  53.     is2D       = twoDim;
  54.     isG4       = mmr;
  55.     runs      = new tiff_runlen_t[2*width];      // run arrays for cur+ref rows
  56.     rowBuf    = new u_char[byteWidth];
  57.     setupDecoder(fillorder, is2D, isG4);
  58.     setRuns(runs, runs+width, width);
  59. }
  60. MemoryDecoder::~MemoryDecoder()
  61. {
  62.     if (rowBuf)
  63. delete rowBuf;
  64.     if (runs)
  65. delete runs;
  66. }
  67. int
  68. MemoryDecoder::decodeNextByte()
  69. {
  70.     if (cc == 0)
  71.         raiseRTC();                     // XXX don't need to recognize EOF
  72.     cc--;
  73.     return (*bp++);
  74. }
  75. void
  76. MemoryDecoder::invalidCode(const char* type, int x)
  77. {
  78.     printf("Invalid %s code word, x %dn", type, x);
  79. }        
  80. void
  81. MemoryDecoder::badPixelCount(const char* type, int got, int expected)  
  82. {
  83.     if (!seenRTC())
  84. printf("Bad %s pixel count, got %d, expected %dn",
  85.     type, got, expected);
  86. }
  87. void
  88. MemoryDecoder::badDecodingState(const char* type, int x)
  89. {
  90.     printf("Panic, bad %s decoding state, x %dn", type, x);
  91. }
  92. static bool
  93. isBlank(tiff_runlen_t* runs, u_int rowpixels)
  94. {
  95.     u_int x = 0;
  96.     for (;;) {
  97. if ((x += *runs++) >= rowpixels)
  98.     break;
  99. if (runs[0] != 0)
  100.     return (false);
  101. if ((x += *runs++) >= rowpixels)
  102.     break;
  103.     }
  104.     return (true);
  105. }
  106. void
  107. MemoryDecoder::scanPageForBlanks(u_int fillorder, const Class2Params& params)
  108. {
  109.     setupDecoder(fillorder,  params.is2D(), (params.df == DF_2DMMR));
  110.     u_int rowpixels = params.pageWidth(); // NB: assume rowpixels <= 4864
  111.     tiff_runlen_t runs[2*4864]; // run arrays for cur+ref rows
  112.     setRuns(runs, runs+4864, rowpixels);
  113.     if (!RTCraised()) {
  114. /*
  115.  * Skip a 1" margin at the top of the page before
  116.  * scanning for trailing white space.  We do this
  117.  * to ensure that there is always enough space on
  118.  * the page to image a tag line and to satisfy a
  119.  * fax machine that is incapable of imaging to the
  120.  * full extent of the page.
  121.  */
  122. u_int topMargin = 1*98; // 1" at 98 lpi
  123. switch (params.vr) {
  124.     case VR_FINE:
  125.     case VR_200X200:
  126. topMargin *= 2; // 196 lpi =>'s twice as many
  127. break;
  128.     case VR_300X300:
  129. topMargin *= 3;
  130. break;
  131.     case VR_R8:
  132.     case VR_R16:
  133.     case VR_200X400:
  134. topMargin *= 4;
  135. break;
  136. }
  137. do {
  138.     (void) decodeRow(NULL, rowpixels);
  139. } while (--topMargin);
  140. /*
  141.  * Scan the remainder of the page data and calculate
  142.  * the number of blank lines at the bottom.
  143.  */
  144. for (;;) {
  145.     (void) decodeRow(NULL, rowpixels);
  146.     if (isBlank(lastRuns(), rowpixels)) {
  147. endOfData = bp; // include one blank row
  148. nblanks = 0;
  149. do {
  150.     nblanks++;
  151.     (void) decodeRow(NULL, rowpixels);
  152. } while (isBlank(lastRuns(), rowpixels));
  153.     }
  154. }
  155.     }
  156. }
  157. #ifdef roundup
  158. #undef roundup
  159. #endif
  160. #define roundup(a,b)    ((((a)+((b)-1))/(b))*(b))
  161. /*
  162.  * TIFF Class F specs say:
  163.  *
  164.  * "As illustrated in FIGURE 1/T.4 in Recommendation T.4 (the Red
  165.  * Book, page 20), facsimile documents begin with an EOL (which in
  166.  * Class F is byte-aligned)..."
  167.  *
  168.  * This is wrong! "Byte-aligned" first EOL means extra zero bits
  169.  * which are not allowed by T.4. Reencode first row to fix this
  170.  * "byte-alignment".
  171.  */
  172. void MemoryDecoder::fixFirstEOL()
  173. {
  174.     fxStackBuffer result;
  175.     G3Encoder enc(result);
  176.     enc.setupEncoder(fillorder, is2D, isG4);
  177.     
  178.     memset(rowBuf, 0, byteWidth*sizeof(u_char)); // clear row to white
  179.     if(!RTCraised()) {
  180.         u_char* start = current();
  181.         (void)decodeRow(rowBuf, width);
  182.         /*
  183.          * syncronize to the next EOL and calculate pointer to it
  184.          * (see detailed explanation of look_ahead in encodeTagLine())
  185.          */
  186.         (void)isNextRow1D();
  187.         u_int look_ahead = roundup(getPendingBits(),8) / 8;
  188.         u_int decoded = current() - look_ahead - start;
  189.         enc.encode(rowBuf, width, 1);
  190. enc.encoderCleanup();
  191.         u_int encoded = result.getLength();
  192.             
  193.         while( encoded < decoded ){
  194.             result.put((char) 0);
  195.             encoded++;
  196.         }
  197.         if( encoded == decoded ){
  198.             memcpy(start, (const char*)result, encoded);
  199.         }
  200.     }
  201. }
  202. /*
  203.  * TIFF Class F specs say:
  204.  *
  205.  * "Aside from EOL's, TIFF Class F files contain only image data. This
  206.  * means that the Return To Control sequence (RTC) is specifically
  207.  * prohibited..."
  208.  *
  209.  * Nethertheless Ghostscript and possibly other TIFF Class F writers
  210.  * append RTC or single EOL to the last encoded line. Remove them.
  211.  */
  212. u_char* MemoryDecoder::cutExtraRTC()
  213. {
  214.     /*
  215.      * We expect RTC near the end of data and thus
  216.      * do not check all image to save processing time.
  217.      * It's safe because we will resync on the first 
  218.      * encountered EOL.
  219.      *
  220.      * NB: We expect G3Decoder::data==0 and
  221.      * G3Decoder::bit==0 (no data in the accumulator).
  222.      * As we cannot explicitly clear the accumulator
  223.      * (bit and data are private), cutExtraRTC()
  224.      * should be called immediately after
  225.      * MemoryDecoder() constructing.
  226.      */
  227.     const u_long CheckArea = 20;
  228.     if( cc > CheckArea ){
  229.         bp += (cc-CheckArea);
  230.         cc = CheckArea;
  231.     }
  232.         
  233.     endOfData = NULL;
  234.     rows = 0;
  235.     if(!RTCraised()) {
  236.         /*
  237.          * syncronize to the next EOL and calculate pointer to it
  238.          * (see detailed explanation of look_ahead in encodeTagLine())
  239.          */
  240.         (void)isNextRow1D();
  241.         u_int look_ahead = roundup(getPendingBits(),8) / 8;
  242.         endOfData = current() - look_ahead;
  243.         for (;;) {
  244.             if( decodeRow(NULL, width) ){
  245.                 /*
  246.                  * endOfData is now after last good row. Thus we correctly handle
  247.                  * RTC, single EOL in the end, or no RTC/EOL at all
  248.                  */
  249.                 endOfData = current();
  250.             }
  251.             if( seenRTC() )
  252.                 break;
  253.     rows++;
  254.         }
  255.     }
  256.     return endOfData;
  257. }
  258. u_char* MemoryDecoder::cutExtraEOFB()
  259. {
  260.     /*
  261.      * MMR requires us to decode the entire image...
  262.      */
  263.     endOfData = NULL;
  264.     rows = 0;
  265.     if(!RTCraised()) {
  266. endOfData = current();
  267.         for (;;) {
  268.             if( decodeRow(NULL, width) ){
  269.                 endOfData = current();
  270.             }
  271.             if( seenRTC() )
  272.                 break;
  273.     rows++;
  274.         }
  275.     }
  276.     /*
  277.      * The loop above will leave the endOfData pointer somewhere inside of EOFB.
  278.      * Make sure that endOfData points to the last byte containing real image data.
  279.      * So trim any whole bytes containing EOFB data.
  280.      */
  281.     if (seenRTC()) {
  282. bool trimmed;
  283. u_int searcharea;
  284. u_short i;
  285. do {
  286.     while (*(endOfData - 1) == 0x00) endOfData--;
  287.     searcharea =  (*(endOfData - 1) << 16) | (*(endOfData - 2) << 8) | *(endOfData - 3);
  288.     trimmed = false;
  289.     for (i = 0; i < 13; i++) {
  290. if (((searcharea >> i) & 0xFFF) == 0x800) {
  291.     endOfData--;
  292.     trimmed = true;
  293.     break;
  294. }
  295.     }
  296. } while (trimmed);
  297.     }
  298.     return endOfData;
  299. }
  300. u_char* MemoryDecoder::encodeTagLine(u_long* raster, u_int th, u_int slop)
  301. {
  302.     /*
  303.      * Decode (and discard) the top part of the page where
  304.      * the tag line is to be imaged.  Note that we assume
  305.      * the strip of raw data has enough scanlines in it
  306.      * to satisfy our needs (caller is responsible).
  307.      *
  308.      * ... and then...
  309.      *
  310.      * Encode the result according to the parameters of
  311.      * the outgoing page.  Note that the encoded data is
  312.      * written in the bit order of the page data since
  313.      * it must be merged back with it below.
  314.      */
  315.     fxStackBuffer result;
  316.     G3Encoder enc(result);
  317.     enc.setupEncoder(fillorder, is2D, isG4);
  318.     decode(NULL, width, th); // discard decoded data
  319.     if (!isG4) {
  320. /*
  321.  * If the source is 2D-encoded and the decoding done
  322.  * above leaves us at a row that is 2D-encoded, then
  323.  * our re-encoding below will generate a decoding
  324.  * error if we don't fix things up.  Thus we discard
  325.  * up to the next 1D-encoded scanline.  (We could
  326.  * instead decode the rows and re-encoded them below
  327.  * but to do that would require decoding above instead
  328.  * of skipping so that the reference line for the
  329.  * 2D-encoded rows is available.)
  330.  */
  331. u_int n;
  332. for (n = 0; n < 4 && !isNextRow1D(); n++)
  333.     decodeRow(NULL, width);
  334. th += n; // compensate for discarded rows
  335. /*
  336.  * Things get tricky trying to identify the last byte in
  337.  * the decoded data that we want to replace.  The decoder
  338.  * must potentially look ahead to see the zeros that
  339.  * makeup the EOL that marks the end of the data we want
  340.  * to skip over.  Consequently current() must be
  341.  * adjusted by the look ahead, a factor of the number of
  342.  * bits pending in the G3 decoder's bit accumulator.
  343.  */
  344. u_int look_ahead = roundup(getPendingBits(),8) / 8;
  345. u_int decoded = current() - look_ahead - bp;
  346. enc.encode(raster, width, th);
  347. enc.encoderCleanup();
  348. delete raster;
  349. /*
  350.  * To properly join the newly encoded data and the previous
  351.  * data we need to insert two bytes of zero-fill prior to
  352.  * the start of the old data to ensure 11 bits of zero exist
  353.  * prior to the EOL code in the first line of data that
  354.  * follows what we skipped over above.  Note that this
  355.  * assumes the G3 decoder always stops decoding prior to
  356.  * an EOL code and that we've adjusted the byte count to the
  357.  * start of the old data so that the leading bitstring is
  358.  * some number of zeros followed by a 1.
  359.  */
  360. result.put((char) 0);
  361. result.put((char) 0);
  362. /*
  363.  * Copy the encoded raster with the tag line back to
  364.  * the front of the buffer that was passed in.  The
  365.  * caller has preallocated a hunk of space for us to
  366.  * do this and we also reuse space occupied by the
  367.  * original encoded raster image.  If insufficient space
  368.  * exists for the newly encoded tag line, then we jam
  369.  * as much as will fit w/o concern for EOL markers;
  370.  * this will cause at most one bad row to be received
  371.  * at the receiver (got a better idea?).
  372.  */
  373. u_int encoded = result.getLength();
  374. if (encoded > slop + decoded)
  375.     encoded = slop + decoded;
  376. u_char* dst = bp + (int)(decoded-encoded);
  377. memcpy(dst, (const unsigned char*) result, encoded);
  378. return (dst);
  379.     } else {
  380. u_char* refrow = new u_char[byteWidth*sizeof(u_char)]; // reference row
  381. memset(refrow, 0, byteWidth*sizeof(u_char)); // clear to white
  382. enc.encode(raster, width, th, (unsigned char*) refrow);
  383. /*
  384.  * refrow does not need to be altered now to match the 
  385.  * last line of raster because the raster contains MARGIN_BOT
  386.  * blank lines.
  387.  */
  388. delete raster;
  389. if (!RTCraised()) {
  390.     for (;;) {
  391. (void) decodeRow(rowBuf, width);
  392. if(seenRTC())
  393.     break;
  394. enc.encode(rowBuf, width, 1, (unsigned char*) refrow);
  395. memcpy(refrow, rowBuf, byteWidth*sizeof(u_char));
  396.     }
  397. }
  398. enc.encoderCleanup();
  399. cc = result.getLength();
  400. u_char* dst = new u_char[cc];
  401. memcpy(dst, (const unsigned char*) result, cc);
  402. return (dst);
  403.     }
  404. }
  405. #ifdef HAVE_JBIG
  406. extern "C" {
  407. #include "jbig.h"
  408. }
  409. fxStackBuffer resultBuffer;
  410. void bufferJBIGData(unsigned char *start, size_t len, void *file)
  411. {
  412.     resultBuffer.put((const char*) start, len);
  413. }
  414. #endif /* HAVE_JBIG */
  415. u_char* MemoryDecoder::convertDataFormat(const Class2Params& params)
  416. {
  417.     /*
  418.      * Convert data to the format specified in params.  The decoder has already
  419.      * been set up, and we don't need to worry about decoder operation here.  
  420.      * These params are for the encoder to use.
  421.      */
  422.     rows = 0;
  423.     if (params.df <= DF_2DMMR) {
  424. fxStackBuffer result;
  425. G3Encoder enc(result);
  426. enc.setupEncoder(fillorder, params.is2D(), (params.df == DF_2DMMR));
  427. u_char* refrow = new u_char[byteWidth*sizeof(u_char)]; // reference row
  428. memset(refrow, 0, byteWidth*sizeof(u_char)); // clear to white
  429. /*
  430.  * For MR we encode a 1-D or 2-D line according to T.4 4.2.1.
  431.  * We understand that "standard" resolution means VR_NORMAL.
  432.  */
  433. u_short k = 0;
  434. if (!RTCraised()) {
  435.     for (;;) {
  436. (void) decodeRow(rowBuf, width);
  437. if(seenRTC())
  438.     break;
  439. rows++;
  440. // encode the line specific to the desired format
  441. if (params.df == DF_2DMMR) {
  442.     enc.encode(rowBuf, width, 1, (unsigned char*) refrow);
  443. } else if (params.df == DF_2DMR) {
  444.     if (k) {
  445. enc.encode(rowBuf, width, 1, (unsigned char*) refrow); // 2-D
  446.     } else {
  447. enc.encode(rowBuf, width, 1); // 1-D
  448. k = (params.vr == VR_NORMAL || params.vr == VR_200X100) ? 2 : 4;
  449.     }
  450.     k--;
  451. } else { // DF_1DMH
  452.     enc.encode(rowBuf, width, 1);
  453. }
  454. memcpy(refrow, rowBuf, byteWidth*sizeof(u_char));
  455.     }
  456. }
  457. enc.encoderCleanup();
  458. cc = result.getLength();
  459. u_char* dst = new u_char[cc];
  460. memcpy(dst, (const unsigned char*) result, cc);
  461. return (dst);
  462.     } else if (params.df == DF_JBIG) {
  463. #ifdef HAVE_JBIG
  464. char* decodedrow = new char[byteWidth];
  465. fxStackBuffer raster;
  466. resultBuffer = raster; // initialize resultBuffer
  467. if (!RTCraised()) {
  468.     for (;;) {
  469. (void) decodeRow(decodedrow, width);
  470. if(seenRTC())
  471.     break;
  472. raster.put(decodedrow, byteWidth*sizeof(u_char));
  473. rows++;
  474.     }
  475. }
  476. delete decodedrow;
  477. // bitmap raster is prepared, pass through JBIG encoding...
  478. cc = raster.getLength();
  479. u_char* rasterdst = new u_char[cc];
  480. memcpy(rasterdst, (const unsigned char*) raster, cc);
  481. unsigned char *pmap[1];
  482. pmap[0] = rasterdst;
  483. struct jbg_enc_state jbigstate;
  484. jbg_enc_init(&jbigstate, width, rows, 1, pmap, bufferJBIGData, NULL);
  485. /*
  486.  * T.85 requires "single-progressive sequential coding" and thus:
  487.  *
  488.  * Dl = 0, D = 0, P = 1 are required
  489.  * L0 = 128 is suggested (and appears to be standard among senders)
  490.  * Mx = 0 to 127 (and 0 appears to be standard)
  491.  * My = 0, HITOLO = 0, SEQ = 0, ILEAVE = 0, SMID = 0
  492.  * TPDON = 0, DPON = 0, DPPRIV = 0, DPLAST = 0
  493.  *
  494.  * As these settings vary from the library's defaults, we carefully
  495.  * specify all of them.
  496.  */
  497. jbg_enc_options(&jbigstate, 0, 0, 128, 0, 0);
  498. jbg_enc_out(&jbigstate);
  499. jbg_enc_free(&jbigstate);
  500. delete rasterdst;
  501. // image is now encoded into JBIG
  502. //resultBuffer[19] |= 0x20; // set VLENGTH = 1, if someday we want to transmit NEWLEN
  503. cc = resultBuffer.getLength();
  504. u_char* dst = new u_char[cc];
  505. memcpy(dst, (const unsigned char*) resultBuffer, cc);
  506. return (dst);
  507. #else
  508. printf("Attempt to convert Phase C data to JBIG without JBIG support.  This should not happen.n");
  509. return (NULL);
  510. #endif /* HAVE_JBIG */
  511.     } else {
  512. printf("Attempt to convert Phase C data to an unsupported format.  This should not happen.n");
  513. return (NULL);
  514.     }
  515. }