bitblt_g4.c

Mon, 10 Mar 2003 09:58:34 +0000

author
eric
date
Mon, 10 Mar 2003 09:58:34 +0000
changeset 93
98a8a2c763fd
parent 91
e63762afae80
child 94
7664a3f112ba
permissions
-rw-r--r--

*** empty log message ***

     1 /*
     2  * t2p: Create a PDF file from the contents of one or more TIFF
     3  *      bilevel image files.  The images in the resulting PDF file
     4  *      will be compressed using ITU-T T.6 (G4) fax encoding.
     5  *
     6  * G4 compression
     7  * $Id: bitblt_g4.c,v 1.9 2003/03/10 01:49:50 eric Exp $
     8  * Copyright 2003 Eric Smith <eric@brouhaha.com>
     9  *
    10  * This program is free software; you can redistribute it and/or modify
    11  * it under the terms of the GNU General Public License version 2 as
    12  * published by the Free Software Foundation.  Note that permission is
    13  * not granted to redistribute this program under the terms of any
    14  * other version of the General Public License.
    15  *
    16  * This program is distributed in the hope that it will be useful,
    17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    19  * GNU General Public License for more details.
    20  *
    21  * You should have received a copy of the GNU General Public License
    22  * along with this program; if not, write to the Free Software
    23  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
    24  */
    27 #include <stdbool.h>
    28 #include <stdint.h>
    29 #include <stdio.h>
    30 #include <stdlib.h>
    31 #include <string.h>
    34 #include "bitblt.h"
    37 #include "g4_tables.h"
    40 #define BIT_BUF_SIZE 4096
    42 struct bit_buffer
    43 {
    44   FILE *f;
    45   uint32_t byte_idx;  /* index to next byte position in data buffer */
    46   uint32_t bit_idx;   /* index to next bit position in data buffer,
    47 			 0 = MSB, 7 = LSB */
    48   uint8_t data [BIT_BUF_SIZE];
    49 };
    52 static void flush_bits (struct bit_buffer *buf)
    53 {
    54   size_t s;
    55   if (buf->bit_idx)
    56     {
    57       /* zero remaining bits in last byte */
    58       buf->data [buf->byte_idx] &= ~ ((1 << (8 - buf->bit_idx)) - 1);
    59       buf->byte_idx++;
    60       buf->bit_idx = 0;
    61     }
    62   s = fwrite (& buf->data [0], 1, buf->byte_idx, buf->f);
    63   /* $$$ should check result */
    64   buf->byte_idx = 0;
    65 }
    68 static void advance_byte (struct bit_buffer *buf)
    69 {
    70   buf->byte_idx++;
    71   buf->bit_idx = 0;
    72   if (buf->byte_idx == BIT_BUF_SIZE)
    73     flush_bits (buf);
    74 }
    77 static void write_bits (struct bit_buffer *buf,
    78 			uint32_t count,
    79 			uint32_t bits)
    80 {
    81   uint32_t b2;  /* how many bits will fit in byte in data buffer */
    82   uint32_t c2;  /* how many bits to transfer on this iteration */
    83   uint32_t d2;  /* bits to transfer on this iteration */
    85   while (count)
    86     {
    87       b2 = 8 - buf->bit_idx;
    88       if (b2 >= count)
    89 	c2 = count;
    90       else
    91 	c2 = b2;
    92       d2 = bits >> (count - c2);
    93       buf->data [buf->byte_idx] |= (d2 << (b2 + c2));
    94       buf->bit_idx += c2;
    95       if (buf->bit_idx > 7)
    96 	advance_byte (buf);
    97       count -= c2;
    98     }
    99 }
   102 static void g4_encode_horizontal_run (struct bit_buffer *buf,
   103 				      bool black,
   104 				      uint32_t run_length)
   105 {
   106   uint32_t i;
   108   while (run_length >= 2560)
   109     {
   110       write_bits (buf, 12, 0x01f);
   111       run_length -= 2560;
   112     }
   114   if (run_length >= 1792)
   115     {
   116       i = (run_length - 1792) >> 6;
   117       write_bits (buf,
   118 		  g4_long_makeup_code [i].count,
   119 		  g4_long_makeup_code [i].bits);
   120       run_length -= (1792 + (i << 6));
   121     }
   122   else if (run_length >= 64)
   123     {
   124       i = (run_length >> 6) - 1;
   125       write_bits (buf,
   126 		  g4_makeup_code [black] [i].count,
   127 		  g4_makeup_code [black] [i].bits);
   128       run_length -= (i + 1) << 6;
   129     }
   131   write_bits (buf,
   132 	      g4_h_code [black] [run_length].count,
   133 	      g4_h_code [black] [run_length].bits);
   134 }
   137 static uint32_t find_transition (uint8_t *data,
   138 				 uint32_t pos,
   139 				 uint32_t width)
   140 {
   141   if (! data)
   142     return (width);
   143   return (0);  /* $$$ */
   144 }
   147 static void g4_encode_row (struct bit_buffer *buf,
   148 			   uint32_t width,
   149 			   uint8_t *ref,
   150 			   uint8_t *row)
   151 {
   152   int a0, a1, a2;
   153   int b1, b2;
   155   a0 = -1;
   157   while (a0 < width)
   158     {
   159       /* find a1, a2 */
   160       a1 = find_transition (row, a0, width);
   161       a2 = find_transition (row, a1, width);
   163       /* find b1, b2 */
   164       b1 = find_transition (ref, a0, width);
   165       if (0) /* $$$ b1 color = a0 color */
   166 	b1 = find_transition (ref, b1, width);
   167       b2 = find_transition (ref, b2, width);
   169       if (b2 < a1)
   170 	{
   171 	  /* pass mode - 0001 */
   172 	  write_bits (buf, 4, 0x1);
   173 	  a0 = b2;
   174 	}
   175       else if (abs (a1 - b1) <= 3)
   176 	{
   177 	  /* vertical mode */
   178 	  write_bits (buf,
   179 		      g4_vert_code [3 + a1 - b1].count,
   180 		      g4_vert_code [3 + a1 - b1].bits);
   181 	  a0 = a1;
   182 	}
   183       else
   184 	{
   185 	  /* horizontal mode - 001 */
   186 	  write_bits (buf, 3, 0x1);
   187 	  g4_encode_horizontal_run (buf, 0 /* $$$ color (a0) */, a1 - a0);
   188 	  g4_encode_horizontal_run (buf, 1 /* $$$ color (a1) */, a2 - a1);
   189 	  a0 = a2;
   190 	}
   191     }
   192 }
   195 void bitblt_write_g4 (Bitmap *bitmap, FILE *f)
   196 {
   197   uint32_t row;
   198   struct bit_buffer bb;
   200   word_type *ref_line = NULL;  /* reference (previous) row */
   201   word_type *line = bitmap->bits;
   203   memset (& bb, 0, sizeof (bb));
   205   bb.f = f;
   207   for (row = bitmap->rect.min.y;
   208        row < bitmap->rect.max.y;
   209        row++)
   210     {
   211       g4_encode_row (& bb,
   212 		     (bitmap->rect.max.x - bitmap->rect.min.x) + 1,
   213 		     (uint8_t *) ref_line,
   214 		     (uint8_t *) line);
   215       ref_line = line;
   216       line += bitmap->row_words;
   217     }
   220   /* write EOFB code */
   221   write_bits (& bb, 24, 0x001001);
   223   flush_bits (& bb);
   224 }