Mon, 10 Mar 2003 09:58:34 +0000
*** 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 }