home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-387-Vol-3of3.iso / g / gs252src.zip / GS252 / SCFE.C < prev    next >
C/C++ Source or Header  |  1992-09-17  |  9KB  |  305 lines

  1. /* Copyright (C) 1992 Aladdin Enterprises.  All rights reserved.
  2.    Distributed by Free Software Foundation, Inc.
  3.  
  4. This file is part of Ghostscript.
  5.  
  6. Ghostscript is distributed in the hope that it will be useful, but
  7. WITHOUT ANY WARRANTY.  No author or distributor accepts responsibility
  8. to anyone for the consequences of using it or for whether it serves any
  9. particular purpose or works at all, unless he says so in writing.  Refer
  10. to the Ghostscript General Public License for full details.
  11.  
  12. Everyone is granted permission to copy, modify and redistribute
  13. Ghostscript, but only under the conditions described in the Ghostscript
  14. General Public License.  A copy of this license is supposed to have been
  15. given to you along with Ghostscript so you can know your rights and
  16. responsibilities.  It should be in a file named COPYING.  Among other
  17. things, the copyright notice and this notice must be preserved on all
  18. copies.  */
  19.  
  20. /* scfe.c */
  21. /* CCITTFax encoding filter */
  22. #include "stdio_.h"    /* includes std.h */
  23. #include "memory_.h"
  24. #include "gdebug.h"
  25. #include "scf.h"
  26. #include "stream.h"
  27.  
  28. /* Imported procedures */
  29. extern int s_filter_write_flush(P1(stream *));
  30.  
  31. /* ------ Macros and support routines ------ */
  32.  
  33. /* Put a code onto the target stream. */
  34. /* Relevant invariants: 0 <= bits_left <= bits_size; only the leftmost */
  35. /* (bits_size - bits_left) bits of bits contain valid data. */
  36.  
  37. #define bits_size (arch_sizeof_int == 2 ? 16 : 32)
  38.  
  39. #ifdef DEBUG
  40. #  define p_c(rp)\
  41.     (gs_debug['w'] ?\
  42.      (dprintf2("[w]0x%x,%d\n", (rp)->code, (rp)->code_length), 0) : 0)
  43. #else
  44. #  define p_c(rp) 0
  45. #endif
  46.  
  47. #define cf_put_code(s, rp)\
  48.   (p_c(rp),\
  49.    ((s->cfs.bits_left -= (rp)->code_length) >= 0 ?\
  50.     s->cfs.bits += (rp)->code << s->cfs.bits_left :\
  51.     cf_put_code_out(s, (rp)->code)))
  52.  
  53. private uint
  54. cf_put_code_out(register stream *s, uint code)
  55. {    int left = s->cfs.bits_left;
  56.     const uint cw = s->cfs.bits + (code >> -left);
  57.     stream *strm = s->strm;
  58. #if bits_size > 16
  59.     sputc(strm, cw >> 24);
  60.     sputc(strm, (byte)(cw >> 16));
  61. #endif
  62.     sputc(strm, (byte)(cw >> 8));
  63.     sputc(strm, (byte)cw);
  64.     return (s->cfs.bits = code << (s->cfs.bits_left = left + bits_size));
  65. }
  66.  
  67. /* Put a run onto the output stream. */
  68.  
  69. #define cf_put_run(s, lenv, tt, mut)\
  70. {    const cfe_run _ds *rp;\
  71.     if ( lenv >= 64 )\
  72.     {    rp = &mut[lenv >> 6];\
  73.         cf_put_code(s, rp);\
  74.         lenv &= 63;\
  75.     }\
  76.     rp = &tt[lenv];\
  77.     cf_put_code(s, rp);\
  78. }
  79.  
  80. #define cf_put_white_run(s, lenv)\
  81.   cf_put_run(s, lenv, cf_white_termination, cf_white_make_up)
  82.  
  83. #define cf_put_black_run(s, lenv)\
  84.   cf_put_run(s, lenv, cf_black_termination, cf_black_make_up)
  85.  
  86. /* ------ Stream procedures ------ */
  87.       
  88. /*
  89.  * For the 2-D encoding modes, we leave the previous complete scan line
  90.  * at the beginning of the buffer, and start the new data after it.
  91.  */
  92.  
  93. /* Initialize CCITTFaxEncode filter */
  94. void
  95. s_CFE_init(register stream *s, CCITTFax_state *pcfs)
  96. {    s->cfs = *pcfs;
  97.     if ( s->cfs.K != 0 )
  98.     {    /* Clear the initial reference line for 2-D encoding. */
  99.         s->cptr = s->cbuf + s->cfs.raster - 1;
  100.         memset(s->cbuf, (s->cfs.BlackIs1 ? 0xff : 0), s->cfs.raster);
  101.         s->cfs.k_left = -1;
  102.     }
  103.     s->cfs.k_left = max(s->cfs.K, 0);
  104.     s->cfs.bits = 0;
  105.     s->cfs.bits_left = bits_size;
  106. }
  107.  
  108. /* Flush the buffer */
  109. private int cf_encode_1d(P2(stream *, byte *));
  110. private int cf_encode_2d(P3(stream *, byte *, byte *));
  111. private int
  112. s_CFE_write_buf(register stream *s)
  113. {    int raster = s->cfs.raster;
  114.     byte *prev = s->cbuf;
  115.     byte *p = (s->cfs.K ? prev + raster : prev);
  116.     byte *limit = s->cptr;
  117.     byte end_mask = 1 << (-s->cfs.Columns & 7);
  118.     uint count;
  119.     /* Do complete scan lines. */
  120.     while ( (count = limit - p + 1) >= raster )
  121.     {    /* Ensure that the scan line ends with a polarity change. */
  122.         /* This may involve saving and restoring one byte beyond */
  123.         /* the scan line. */
  124.         byte *next = p + raster;
  125.         byte save_next = *next;
  126.         int code;
  127.         if ( end_mask == 1 )        /* set following byte */
  128.             *next = (next[-1] & 1) - 1;
  129.         else if ( next[-1] & end_mask )    /* clear lower bits */
  130.             next[-1] &= -end_mask;
  131.         else                /* set lower bits */
  132.             next[-1] |= end_mask - 1;
  133.         if ( s->cfs.EncodedByteAlign )
  134.             s->cfs.bits_left &= ~7;
  135.         if ( s->cfs.K > 0 )
  136.         {    /* Group 3, mixed encoding */
  137.             if ( --(s->cfs.k_left) )
  138.             {    /* Use 2-D encoding */
  139.                 if ( s->cfs.EndOfLine )
  140.                     cf_put_code(s, &cf2_run_eol_2d);
  141.                 code = cf_encode_2d(s, p, prev);
  142.             }
  143.             else
  144.             {    /* Use 1-D encoding */
  145.                 if ( s->cfs.EndOfLine )
  146.                     cf_put_code(s, &cf2_run_eol_1d);
  147.                 code = cf_encode_1d(s, p);
  148.                 s->cfs.k_left = s->cfs.K;
  149.             }
  150.         }
  151.         else
  152.         {    /* Uniform encoding */
  153.             if ( s->cfs.EndOfLine )
  154.                 cf_put_code(s, &cf_run_eol);
  155.             code = (s->cfs.K == 0 ? cf_encode_1d(s, p) :
  156.                 cf_encode_2d(s, p, prev));
  157.         }
  158.         *next = save_next;
  159.         if ( code )
  160.         {    s->end_status = code;
  161.             break;
  162.         }
  163.         prev = p;
  164.         p = next;
  165.     }
  166.     /* Move any remaining partial scan line (and, if 2-D encoding */
  167.     /* is a possibility, the last full scan line) to the beginning */
  168.     /* of the buffer. */
  169.     if ( s->cfs.K )
  170.         count += raster, p -= raster;
  171.     memcpy(s->cbuf, p, count);
  172.     s->cptr = s->cbuf - 1 + count;
  173.     return 0;
  174. }
  175.  
  176. /* Encode a 1-D scan line. */
  177. private int
  178. cf_encode_1d(stream *s, register byte *p)
  179. {    byte invert = (s->cfs.BlackIs1 ? 0 : 0xff);
  180.     register uint count;
  181.     uint end_count = s->cfs.Columns & 7;
  182.     register uint data = *p++ ^ invert;
  183.     for ( count = s->cfs.raster << 3; count != end_count; )
  184.     {    int white, black;
  185.         /* Parse a white run. */
  186.         white = count;
  187.         skip_white_pixels(data, p, count, invert, w0);
  188.         white -= count;
  189.         cf_put_white_run(s, white);
  190.         if ( count == end_count ) break;
  191.         /* Parse a black run. */
  192.         black = count;
  193.         skip_black_pixels(data, p, count, invert, b0, b1);
  194.         black -= count;
  195.         cf_put_black_run(s, black);
  196.     }
  197.     return 0;
  198. }
  199.  
  200. /* Encode a 2-D scan line. */
  201. private int
  202. cf_encode_2d(stream *s, byte *p, byte *prev_p)
  203. {    byte invert = (s->cfs.BlackIs1 ? 0 : 0xff);
  204.     byte invert_white = invert;
  205.     register uint count;
  206.     uint end_count = s->cfs.Columns & 7;
  207.     register uint data = *p++ ^ invert;
  208.     int dist = prev_p - p;
  209.     for ( count = s->cfs.raster << 3; count != end_count; )
  210.     {    /* If invert == invert_white, white and black have their */
  211.         /* correct meanings; if invert == ~invert_white, */
  212.         /* black and white are interchanged. */
  213.         uint a0, a1, b1;
  214.         uint prev_count = count;
  215.         byte prev_data;
  216.         int diff;
  217.         static const byte count_bit[8] =
  218.             { 0x80, 1, 2, 4, 8, 0x10, 0x20, 0x40 };
  219.         prev_p = p + dist;
  220.         prev_data = prev_p[-1] ^ invert;
  221.         /* Find the a1 and b1 transitions. */
  222.         a0 = count;
  223.         skip_white_pixels(data, p, count, invert, w00);
  224.         a1 = count;
  225.         if ( (prev_data & count_bit[prev_count & 7]) )
  226.         {    /* Look for changing white first. */
  227.             skip_black_pixels(prev_data, prev_p, prev_count, invert, b01, b11);
  228.         }
  229.         if ( prev_count != end_count )
  230.         {    skip_white_pixels(prev_data, prev_p, prev_count, invert, w01);
  231.         }
  232.         b1 = prev_count;
  233.         /* In all the comparisons below, remember that count */
  234.         /* runs downward, not upward, so the comparisons are */
  235.         /* reversed. */
  236.         if ( b1 >= a1 + 2 )
  237.         {    /* Could be a pass mode.  Find b2. */
  238.             if ( prev_count != end_count )
  239.             {    skip_black_pixels(prev_data, prev_p,
  240.                          prev_count, invert, b02, b12);
  241.             }
  242.             if ( prev_count > a1 )
  243.             {    /* Use pass mode. */
  244.                 cf_put_code(s, &cf2_run_pass);
  245.                 count = prev_count;
  246.                 p = prev_p - dist;
  247.                 data = p[-1] ^ invert;
  248.                 continue;
  249.             }
  250.         }
  251.         /* Check for vertical coding. */
  252.         diff = a1 - b1;        /* i.e., logical b1 - a1 */
  253.         if ( diff <= 3 && diff >= -3 )
  254.         {    /* Use vertical coding. */
  255.             cf_put_code(s, &cf2_run_vertical[diff + 3]);
  256.             invert = ~invert;    /* a1 polarity changes */
  257.             continue;
  258.         }
  259.         /* No luck, use horizontal coding. */
  260.         cf_put_code(s, &cf2_run_horizontal);
  261.         if ( count != end_count )
  262.         {    skip_black_pixels(data, p, count, invert, b03, b13);    /* find a2 */
  263.         }
  264.         a0 -= a1;
  265.         a1 -= count;
  266.         if ( invert == invert_white )
  267.         {    cf_put_white_run(s, a0);
  268.             cf_put_black_run(s, a1);
  269.         }
  270.         else
  271.         {    cf_put_black_run(s, a0);
  272.             cf_put_white_run(s, a1);
  273.         }
  274.     }
  275.     return 0;
  276. }
  277.  
  278. /* Close the stream */
  279. private int
  280. s_CFE_close(register stream *s)
  281. {    int code = s_CFE_write_buf(s);
  282.     if ( code == ERRC ) return code;
  283.     if ( s->cfs.EndOfBlock )
  284.     {    int i = (s->cfs.K < 0 ? 2 : 6);
  285.         const cfe_run _ds *rp =
  286.             (s->cfs.K > 0 ? &cf2_run_eol_1d : &cf_run_eol);
  287.         while ( --i >= 0 )
  288.             cf_put_code(s, rp);
  289.     }
  290.     /* Force out the last byte or bytes. */
  291.     while ( s->cfs.bits_left < bits_size )
  292.     {    stream *strm = s->strm;
  293.         sputc(strm, s->cfs.bits >> (bits_size - 8));
  294.         s->cfs.bits <<= 8;
  295.         s->cfs.bits_left += 8;
  296.     }
  297.     return s_std_close(s);
  298. }
  299.  
  300. /* Stream procedures */
  301. const stream_procs s_CFE_procs =
  302.    {    s_std_noavailable, NULL, s_filter_write_flush, s_CFE_close,
  303.     NULL, s_CFE_write_buf
  304.    };
  305.