Wed, 12 Mar 2003 07:53:55 +0000
made callback functions static.
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 }