bitblt_g4.c

Mon, 10 Mar 2003 13:08:25 +0000

author
eric
date
Mon, 10 Mar 2003 13:08:25 +0000
changeset 94
7664a3f112ba
parent 91
e63762afae80
child 95
851a04fa5324
permissions
-rw-r--r--

Working on G4 encoding.

     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.10 2003/03/10 05:08:25 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"
    35 #include "pdf_util.h"
    38 #include "g4_tables.h"
    41 #define BIT_BUF_SIZE 4096
    43 struct bit_buffer
    44 {
    45   FILE *f;
    46   uint32_t byte_idx;  /* index to next byte position in data buffer */
    47   uint32_t bit_idx;   /* index to next bit position in data buffer,
    48 			 0 = MSB, 7 = LSB */
    49   uint8_t data [BIT_BUF_SIZE];
    50 };
    53 static void flush_bits (struct bit_buffer *buf)
    54 {
    55   size_t s;
    56   if (buf->bit_idx)
    57     {
    58       /* zero remaining bits in last byte */
    59       buf->data [buf->byte_idx] &= ~ ((1 << (8 - buf->bit_idx)) - 1);
    60       buf->byte_idx++;
    61       buf->bit_idx = 0;
    62     }
    63   s = fwrite (& buf->data [0], 1, buf->byte_idx, buf->f);
    64   /* $$$ should check result */
    65   buf->byte_idx = 0;
    66 }
    69 static void advance_byte (struct bit_buffer *buf)
    70 {
    71   buf->byte_idx++;
    72   buf->bit_idx = 0;
    73   if (buf->byte_idx == BIT_BUF_SIZE)
    74     flush_bits (buf);
    75 }
    78 static void write_bits (struct bit_buffer *buf,
    79 			uint32_t count,
    80 			uint32_t bits)
    81 {
    82   uint32_t b2;  /* how many bits will fit in byte in data buffer */
    83   uint32_t c2;  /* how many bits to transfer on this iteration */
    84   uint32_t d2;  /* bits to transfer on this iteration */
    86   while (count)
    87     {
    88       b2 = 8 - buf->bit_idx;
    89       if (b2 >= count)
    90 	c2 = count;
    91       else
    92 	c2 = b2;
    93       d2 = bits >> (count - c2);
    94       buf->data [buf->byte_idx] |= (d2 << (b2 + c2));
    95       buf->bit_idx += c2;
    96       if (buf->bit_idx > 7)
    97 	advance_byte (buf);
    98       count -= c2;
    99     }
   100 }
   103 static void g4_encode_horizontal_run (struct bit_buffer *buf,
   104 				      bool black,
   105 				      uint32_t run_length)
   106 {
   107   uint32_t i;
   109   while (run_length >= 2560)
   110     {
   111       write_bits (buf, 12, 0x01f);
   112       run_length -= 2560;
   113     }
   115   if (run_length >= 1792)
   116     {
   117       i = (run_length - 1792) >> 6;
   118       write_bits (buf,
   119 		  g4_long_makeup_code [i].count,
   120 		  g4_long_makeup_code [i].bits);
   121       run_length -= (1792 + (i << 6));
   122     }
   123   else if (run_length >= 64)
   124     {
   125       i = (run_length >> 6) - 1;
   126       write_bits (buf,
   127 		  g4_makeup_code [black] [i].count,
   128 		  g4_makeup_code [black] [i].bits);
   129       run_length -= (i + 1) << 6;
   130     }
   132   write_bits (buf,
   133 	      g4_h_code [black] [run_length].count,
   134 	      g4_h_code [black] [run_length].bits);
   135 }
   138 static inline int g4_get_pixel (uint8_t *buf, uint32_t x)
   139 {
   140   return ((buf [x >> 3] >> (x & 7)) & 1);
   141 }
   144 static uint32_t g4_find_pixel (uint8_t *buf,
   145 			       uint32_t pos,
   146 			       uint32_t width,
   147 			       bool color)
   148 {
   149   while (pos < width)
   150     {
   151       if (g4_get_pixel (buf, pos) == color)
   152 	return (pos);
   153       pos++;
   154     }
   155   return (width);
   156 }
   159 static void g4_encode_row (struct bit_buffer *buf,
   160 			   uint32_t width,
   161 			   uint8_t *ref,
   162 			   uint8_t *row)
   163 {
   164   uint32_t a0, a1, a2;
   165   uint32_t b1, b2;
   166   bool a0_c;
   168   a0 = 0;
   169   a0_c = 0;
   171   a1 = g4_find_pixel (row, 0, width, 1);
   172   b1 = g4_find_pixel (ref, 0, width, 1);
   174   while (a0 < width)
   175     {
   176       b2 = g4_find_pixel (ref, b1 + 1, width, g4_get_pixel (ref, b1));
   178       if (b2 < a1)
   179 	{
   180 	  /* pass mode - 0001 */
   181 	  write_bits (buf, 4, 0x1);
   182 	  a0 = b2;
   183 	}
   184       else if (abs (a1 - b1) <= 3)
   185 	{
   186 	  /* vertical mode */
   187 	  write_bits (buf,
   188 		      g4_vert_code [3 + a1 - b1].count,
   189 		      g4_vert_code [3 + a1 - b1].bits);
   190 	  a0 = a1;
   191 	}
   192       else
   193 	{
   194 	  /* horizontal mode - 001 */
   195 	  a2 = g4_find_pixel (row, a1, width, a0_c);
   196 	  write_bits (buf, 3, 0x1);
   197 	  g4_encode_horizontal_run (buf,   a0_c, a1 - a0);
   198 	  g4_encode_horizontal_run (buf, ! a0_c, a2 - a1);
   199 	  a0 = a2;
   200 	}
   202       if (a0 >= width)
   203 	break;;
   205       a0_c = g4_get_pixel (row, a0);
   207       a1 = g4_find_pixel (row, a0 + 1, width, ! a0_c);
   208       b1 = g4_find_pixel (ref, a0 + 1, width, a0_c);
   209       b1 = g4_find_pixel (ref, b1 + 1, width, ! a0_c);
   210     }
   211 }
   214 void bitblt_write_g4 (Bitmap *bitmap, FILE *f)
   215 {
   216   uint32_t width = (bitmap->rect.max.x - bitmap->rect.min.x) + 1;
   217   uint32_t row;
   218   struct bit_buffer bb;
   220   word_type *temp_buffer;
   222   word_type *cur_line;
   223   word_type *ref_line;  /* reference (previous) row */
   225   temp_buffer = pdf_calloc ((width + BITS_PER_WORD - 1) / BITS_PER_WORD,
   226 			    sizeof (word_type));
   228   cur_line = bitmap->bits;
   229   ref_line = temp_buffer;
   231   memset (& bb, 0, sizeof (bb));
   233   bb.f = f;
   235   for (row = bitmap->rect.min.y;
   236        row < bitmap->rect.max.y;
   237        row++)
   238     {
   239       g4_encode_row (& bb,
   240 		     width,
   241 		     (uint8_t *) ref_line,
   242 		     (uint8_t *) cur_line);
   243       ref_line = cur_line;
   244       cur_line += bitmap->row_words;
   245     }
   248   /* write EOFB code */
   249   write_bits (& bb, 24, 0x001001);
   251   flush_bits (& bb);
   253   free (temp_buffer);
   254 }