bitblt_g4.c

Wed, 12 Mar 2003 10:59:09 +0000

author
eric
date
Wed, 12 Mar 2003 10:59:09 +0000
changeset 109
663da96ad2bc
parent 95
851a04fa5324
child 110
cb75ec9430b4
permissions
-rw-r--r--

changed word_type to word_t.

     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.11 2003/03/11 03:14:39 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 #define G4_DEBUG 0
    30 #include <stdbool.h>
    31 #include <stdint.h>
    32 #include <stdio.h>
    33 #include <stdlib.h>
    34 #include <string.h>
    37 #include "bitblt.h"
    38 #include "pdf_util.h"
    41 #include "g4_tables.h"
    44 #define BIT_BUF_SIZE 1 /* 4096 */
    46 struct bit_buffer
    47 {
    48   FILE *f;
    49   uint32_t byte_idx;  /* index to next byte position in data buffer */
    50   uint32_t bit_idx;   /* one greater than the next bit position in data buffer,
    51 			 8 = MSB, 1 = LSB */
    52   uint8_t data [BIT_BUF_SIZE];
    53 };
    56 static void init_bit_buffer (struct bit_buffer *buf)
    57 {
    58   buf->byte_idx = 0;
    59   buf->bit_idx = 8;
    60   memset (& buf->data [0], 0, BIT_BUF_SIZE);
    61 }
    64 static void flush_bits (struct bit_buffer *buf)
    65 {
    66   size_t s;
    67   if (buf->bit_idx != 8)
    68     {
    69       buf->byte_idx++;
    70       buf->bit_idx = 8;
    71     }
    72 #if (G4_DEBUG >= 3)
    73  {
    74    int i;
    75    fprintf (stderr, "::: ");
    76    for (i = 0; i < buf->byte_idx; i++)
    77      fprintf (stderr, "%02x ", buf->data [i]);
    78    fprintf (stderr, "\n");
    79  }
    80 #endif
    81   s = fwrite (& buf->data [0], 1, buf->byte_idx, buf->f);
    82   /* $$$ should check result */
    83   init_bit_buffer (buf);
    84 }
    87 static void advance_byte (struct bit_buffer *buf)
    88 {
    89   buf->byte_idx++;
    90   buf->bit_idx = 8;
    91   if (buf->byte_idx == BIT_BUF_SIZE)
    92     flush_bits (buf);
    93 }
    96 static void write_bits (struct bit_buffer *buf,
    97 			uint32_t count,
    98 			uint32_t bits)
    99 {
   100 #if (G4_DEBUG >= 2)
   101   {
   102     int i;
   103     fprintf (stderr, "%d %04x:  ", count, bits);
   104     for (i = count - 1; i >= 0; i--)
   105       fprintf (stderr, "%d", (bits >> i) & 1);
   106     fprintf (stderr, "\n");
   107   }
   108 #endif
   110   while (count > buf->bit_idx)
   111     {
   112       buf->data [buf->byte_idx] |= bits >> (count - buf->bit_idx);
   113       count -= buf->bit_idx;
   114       advance_byte (buf);
   115     }
   117   bits &= ((1 << count) - 1);
   118   buf->data [buf->byte_idx] |= bits << (buf->bit_idx - count);
   119   buf->bit_idx -= count;
   120   if (buf->bit_idx == 0)
   121     advance_byte (buf);
   122 }
   125 static void g4_encode_horizontal_run (struct bit_buffer *buf,
   126 				      bool black,
   127 				      uint32_t run_length)
   128 {
   129   uint32_t i;
   131   while (run_length >= 2560)
   132     {
   133       write_bits (buf, 12, 0x01f);
   134       run_length -= 2560;
   135     }
   137   if (run_length >= 1792)
   138     {
   139       i = (run_length - 1792) >> 6;
   140       write_bits (buf,
   141 		  g4_long_makeup_code [i].count,
   142 		  g4_long_makeup_code [i].bits);
   143       run_length -= (1792 + (i << 6));
   144     }
   145   else if (run_length >= 64)
   146     {
   147       i = (run_length >> 6) - 1;
   148       write_bits (buf,
   149 		  g4_makeup_code [black] [i].count,
   150 		  g4_makeup_code [black] [i].bits);
   151       run_length -= (i + 1) << 6;
   152     }
   154   write_bits (buf,
   155 	      g4_h_code [black] [run_length].count,
   156 	      g4_h_code [black] [run_length].bits);
   157 }
   160 static inline int g4_get_pixel (uint8_t *buf, uint32_t x)
   161 {
   162   return ((buf [x >> 3] >> (x & 7)) & 1);
   163 }
   166 static uint32_t g4_find_pixel (uint8_t *buf,
   167 			       uint32_t pos,
   168 			       uint32_t width,
   169 			       bool color)
   170 {
   171   while (pos < width)
   172     {
   173       if (g4_get_pixel (buf, pos) == color)
   174 	return (pos);
   175       pos++;
   176     }
   177   return (width);
   178 }
   181 static void g4_encode_row (struct bit_buffer *buf,
   182 			   uint32_t width,
   183 			   uint8_t *ref,
   184 			   uint8_t *row)
   185 {
   186   uint32_t a0, a1, a2;
   187   uint32_t b1, b2;
   188   bool a0_c;
   190   a0 = 0;
   191   a0_c = 0;
   193   a1 = g4_find_pixel (row, 0, width, 1);
   195   b1 = g4_find_pixel (ref, 0, width, 1);
   197 #if G4_DEBUG
   198   fprintf (stderr, "start of row\n");
   199   if ((a1 != width) || (b1 != width))
   200     {
   201       fprintf (stderr, "a1 = %u, b1 = %u\n", a1, b1);
   202     }
   203 #endif
   205   while (a0 < width)
   206     {
   207       b2 = g4_find_pixel (ref, b1 + 1, width, ! g4_get_pixel (ref, b1));
   209       if (b2 < a1)
   210 	{
   211 	  /* pass mode - 0001 */
   212 	  write_bits (buf, 4, 0x1);
   213 	  a0 = b2;
   214 #if G4_DEBUG
   215 	  fprintf (stderr, "pass\n");
   216 #endif
   217 	}
   218       else if (abs (a1 - b1) <= 3)
   219 	{
   220 	  /* vertical mode */
   221 	  write_bits (buf,
   222 		      g4_vert_code [3 + a1 - b1].count,
   223 		      g4_vert_code [3 + a1 - b1].bits);
   224 	  a0 = a1;
   225 #if G4_DEBUG
   226 	  fprintf (stderr, "vertical %d\n", a1 - b1);
   227 #endif
   228 	}
   229       else
   230 	{
   231 	  /* horizontal mode - 001 */
   232 	  a2 = g4_find_pixel (row, a1 + 1, width, a0_c);
   233 	  write_bits (buf, 3, 0x1);
   234 	  g4_encode_horizontal_run (buf,   a0_c, a1 - a0);
   235 	  g4_encode_horizontal_run (buf, ! a0_c, a2 - a1);
   236 #if G4_DEBUG
   237 	  fprintf (stderr, "horizontal %d %s, %d %s\n",
   238 		   a1 - a0, a0_c ? "black" : "white",
   239 		   a2 - a1, a0_c ? "white" : "black");
   240 #endif
   241 	  a0 = a2;
   242 	}
   244       if (a0 >= width)
   245 	break;;
   247       a0_c = g4_get_pixel (row, a0);
   249       a1 = g4_find_pixel (row, a0 + 1, width, ! a0_c);
   250       b1 = g4_find_pixel (ref, a0 + 1, width, ! g4_get_pixel (ref, a0));
   251       if (g4_get_pixel (ref, b1) == a0_c)
   252 	b1 = g4_find_pixel (ref, b1 + 1, width, ! a0_c);
   253 #if G4_DEBUG
   254       fprintf (stderr, "a1 = %u, b1 = %u\n", a1, b1);
   255 #endif
   256     }
   257 }
   260 void bitblt_write_g4 (Bitmap *bitmap, FILE *f)
   261 {
   262   uint32_t width = bitmap->rect.max.x - bitmap->rect.min.x;
   263   uint32_t row;
   264   struct bit_buffer bb;
   266   word_type *temp_buffer;
   268   word_type *cur_line;
   269   word_type *ref_line;  /* reference (previous) row */
   271 #if G4_DEBUG
   272   fprintf (stderr, "width %u\n", width);
   273 #endif
   275   temp_buffer = pdf_calloc ((width + BITS_PER_WORD - 1) / BITS_PER_WORD,
   276 			    sizeof (word_type));
   278   cur_line = bitmap->bits;
   279   ref_line = temp_buffer;
   281   init_bit_buffer (& bb);
   283   bb.f = f;
   285   for (row = bitmap->rect.min.y;
   286        row < bitmap->rect.max.y;
   287        row++)
   288     {
   289       g4_encode_row (& bb,
   290 		     width,
   291 		     (uint8_t *) ref_line,
   292 		     (uint8_t *) cur_line);
   293       ref_line = cur_line;
   294       cur_line += bitmap->row_words;
   295     }
   298   /* write EOFB code */
   299   write_bits (& bb, 24, 0x001001);
   301   flush_bits (& bb);
   303   free (temp_buffer);
   304 }