bitblt_g4.c

Tue, 11 Mar 2003 11:14:39 +0000

author
eric
date
Tue, 11 Mar 2003 11:14:39 +0000
changeset 95
851a04fa5324
parent 94
7664a3f112ba
child 110
cb75ec9430b4
permissions
-rw-r--r--

many bug fixes including bit ordering of output, search positions and polarities. added G4_DEBUG conditional.

eric@62 1 /*
eric@62 2 * t2p: Create a PDF file from the contents of one or more TIFF
eric@62 3 * bilevel image files. The images in the resulting PDF file
eric@62 4 * will be compressed using ITU-T T.6 (G4) fax encoding.
eric@62 5 *
eric@91 6 * G4 compression
eric@95 7 * $Id: bitblt_g4.c,v 1.11 2003/03/11 03:14:39 eric Exp $
eric@78 8 * Copyright 2003 Eric Smith <eric@brouhaha.com>
eric@62 9 *
eric@62 10 * This program is free software; you can redistribute it and/or modify
eric@62 11 * it under the terms of the GNU General Public License version 2 as
eric@62 12 * published by the Free Software Foundation. Note that permission is
eric@62 13 * not granted to redistribute this program under the terms of any
eric@62 14 * other version of the General Public License.
eric@62 15 *
eric@62 16 * This program is distributed in the hope that it will be useful,
eric@62 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
eric@62 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
eric@62 19 * GNU General Public License for more details.
eric@62 20 *
eric@62 21 * You should have received a copy of the GNU General Public License
eric@62 22 * along with this program; if not, write to the Free Software
eric@62 23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
eric@62 24 */
eric@62 25
eric@62 26
eric@95 27 #define G4_DEBUG 0
eric@95 28
eric@95 29
eric@62 30 #include <stdbool.h>
eric@62 31 #include <stdint.h>
eric@59 32 #include <stdio.h>
eric@67 33 #include <stdlib.h>
eric@59 34 #include <string.h>
eric@59 35
eric@59 36
eric@62 37 #include "bitblt.h"
eric@94 38 #include "pdf_util.h"
eric@59 39
eric@59 40
eric@91 41 #include "g4_tables.h"
eric@67 42
eric@67 43
eric@95 44 #define BIT_BUF_SIZE 1 /* 4096 */
eric@91 45
eric@91 46 struct bit_buffer
eric@59 47 {
eric@91 48 FILE *f;
eric@91 49 uint32_t byte_idx; /* index to next byte position in data buffer */
eric@95 50 uint32_t bit_idx; /* one greater than the next bit position in data buffer,
eric@95 51 8 = MSB, 1 = LSB */
eric@91 52 uint8_t data [BIT_BUF_SIZE];
eric@59 53 };
eric@59 54
eric@59 55
eric@95 56 static void init_bit_buffer (struct bit_buffer *buf)
eric@95 57 {
eric@95 58 buf->byte_idx = 0;
eric@95 59 buf->bit_idx = 8;
eric@95 60 memset (& buf->data [0], 0, BIT_BUF_SIZE);
eric@95 61 }
eric@95 62
eric@95 63
eric@91 64 static void flush_bits (struct bit_buffer *buf)
eric@59 65 {
eric@91 66 size_t s;
eric@95 67 if (buf->bit_idx != 8)
eric@59 68 {
eric@91 69 buf->byte_idx++;
eric@95 70 buf->bit_idx = 8;
eric@59 71 }
eric@95 72 #if (G4_DEBUG >= 3)
eric@95 73 {
eric@95 74 int i;
eric@95 75 fprintf (stderr, "::: ");
eric@95 76 for (i = 0; i < buf->byte_idx; i++)
eric@95 77 fprintf (stderr, "%02x ", buf->data [i]);
eric@95 78 fprintf (stderr, "\n");
eric@95 79 }
eric@95 80 #endif
eric@91 81 s = fwrite (& buf->data [0], 1, buf->byte_idx, buf->f);
eric@91 82 /* $$$ should check result */
eric@95 83 init_bit_buffer (buf);
eric@91 84 }
eric@59 85
eric@59 86
eric@91 87 static void advance_byte (struct bit_buffer *buf)
eric@91 88 {
eric@91 89 buf->byte_idx++;
eric@95 90 buf->bit_idx = 8;
eric@91 91 if (buf->byte_idx == BIT_BUF_SIZE)
eric@91 92 flush_bits (buf);
eric@59 93 }
eric@59 94
eric@59 95
eric@91 96 static void write_bits (struct bit_buffer *buf,
eric@91 97 uint32_t count,
eric@91 98 uint32_t bits)
eric@59 99 {
eric@95 100 #if (G4_DEBUG >= 2)
eric@95 101 {
eric@95 102 int i;
eric@95 103 fprintf (stderr, "%d %04x: ", count, bits);
eric@95 104 for (i = count - 1; i >= 0; i--)
eric@95 105 fprintf (stderr, "%d", (bits >> i) & 1);
eric@95 106 fprintf (stderr, "\n");
eric@95 107 }
eric@95 108 #endif
eric@59 109
eric@95 110 while (count > buf->bit_idx)
eric@91 111 {
eric@95 112 buf->data [buf->byte_idx] |= bits >> (count - buf->bit_idx);
eric@95 113 count -= buf->bit_idx;
eric@95 114 advance_byte (buf);
eric@91 115 }
eric@95 116
eric@95 117 bits &= ((1 << count) - 1);
eric@95 118 buf->data [buf->byte_idx] |= bits << (buf->bit_idx - count);
eric@95 119 buf->bit_idx -= count;
eric@95 120 if (buf->bit_idx == 0)
eric@95 121 advance_byte (buf);
eric@59 122 }
eric@59 123
eric@59 124
eric@91 125 static void g4_encode_horizontal_run (struct bit_buffer *buf,
eric@91 126 bool black,
eric@91 127 uint32_t run_length)
eric@73 128 {
eric@73 129 uint32_t i;
eric@73 130
eric@73 131 while (run_length >= 2560)
eric@73 132 {
eric@91 133 write_bits (buf, 12, 0x01f);
eric@73 134 run_length -= 2560;
eric@73 135 }
eric@73 136
eric@73 137 if (run_length >= 1792)
eric@73 138 {
eric@73 139 i = (run_length - 1792) >> 6;
eric@91 140 write_bits (buf,
eric@91 141 g4_long_makeup_code [i].count,
eric@91 142 g4_long_makeup_code [i].bits);
eric@73 143 run_length -= (1792 + (i << 6));
eric@73 144 }
eric@73 145 else if (run_length >= 64)
eric@73 146 {
eric@73 147 i = (run_length >> 6) - 1;
eric@91 148 write_bits (buf,
eric@91 149 g4_makeup_code [black] [i].count,
eric@91 150 g4_makeup_code [black] [i].bits);
eric@73 151 run_length -= (i + 1) << 6;
eric@73 152 }
eric@73 153
eric@91 154 write_bits (buf,
eric@91 155 g4_h_code [black] [run_length].count,
eric@91 156 g4_h_code [black] [run_length].bits);
eric@73 157 }
eric@73 158
eric@73 159
eric@94 160 static inline int g4_get_pixel (uint8_t *buf, uint32_t x)
eric@73 161 {
eric@94 162 return ((buf [x >> 3] >> (x & 7)) & 1);
eric@94 163 }
eric@94 164
eric@94 165
eric@94 166 static uint32_t g4_find_pixel (uint8_t *buf,
eric@94 167 uint32_t pos,
eric@94 168 uint32_t width,
eric@94 169 bool color)
eric@94 170 {
eric@94 171 while (pos < width)
eric@94 172 {
eric@94 173 if (g4_get_pixel (buf, pos) == color)
eric@94 174 return (pos);
eric@94 175 pos++;
eric@94 176 }
eric@94 177 return (width);
eric@73 178 }
eric@73 179
eric@73 180
eric@91 181 static void g4_encode_row (struct bit_buffer *buf,
eric@91 182 uint32_t width,
eric@91 183 uint8_t *ref,
eric@91 184 uint8_t *row)
eric@73 185 {
eric@94 186 uint32_t a0, a1, a2;
eric@94 187 uint32_t b1, b2;
eric@94 188 bool a0_c;
eric@73 189
eric@94 190 a0 = 0;
eric@94 191 a0_c = 0;
eric@94 192
eric@94 193 a1 = g4_find_pixel (row, 0, width, 1);
eric@95 194
eric@94 195 b1 = g4_find_pixel (ref, 0, width, 1);
eric@95 196
eric@95 197 #if G4_DEBUG
eric@95 198 fprintf (stderr, "start of row\n");
eric@95 199 if ((a1 != width) || (b1 != width))
eric@95 200 {
eric@95 201 fprintf (stderr, "a1 = %u, b1 = %u\n", a1, b1);
eric@95 202 }
eric@95 203 #endif
eric@73 204
eric@73 205 while (a0 < width)
eric@73 206 {
eric@95 207 b2 = g4_find_pixel (ref, b1 + 1, width, ! g4_get_pixel (ref, b1));
eric@73 208
eric@73 209 if (b2 < a1)
eric@73 210 {
eric@73 211 /* pass mode - 0001 */
eric@91 212 write_bits (buf, 4, 0x1);
eric@73 213 a0 = b2;
eric@95 214 #if G4_DEBUG
eric@95 215 fprintf (stderr, "pass\n");
eric@95 216 #endif
eric@73 217 }
eric@73 218 else if (abs (a1 - b1) <= 3)
eric@73 219 {
eric@73 220 /* vertical mode */
eric@91 221 write_bits (buf,
eric@91 222 g4_vert_code [3 + a1 - b1].count,
eric@91 223 g4_vert_code [3 + a1 - b1].bits);
eric@73 224 a0 = a1;
eric@95 225 #if G4_DEBUG
eric@95 226 fprintf (stderr, "vertical %d\n", a1 - b1);
eric@95 227 #endif
eric@73 228 }
eric@73 229 else
eric@73 230 {
eric@73 231 /* horizontal mode - 001 */
eric@95 232 a2 = g4_find_pixel (row, a1 + 1, width, a0_c);
eric@91 233 write_bits (buf, 3, 0x1);
eric@94 234 g4_encode_horizontal_run (buf, a0_c, a1 - a0);
eric@94 235 g4_encode_horizontal_run (buf, ! a0_c, a2 - a1);
eric@95 236 #if G4_DEBUG
eric@95 237 fprintf (stderr, "horizontal %d %s, %d %s\n",
eric@95 238 a1 - a0, a0_c ? "black" : "white",
eric@95 239 a2 - a1, a0_c ? "white" : "black");
eric@95 240 #endif
eric@73 241 a0 = a2;
eric@73 242 }
eric@94 243
eric@94 244 if (a0 >= width)
eric@94 245 break;;
eric@94 246
eric@94 247 a0_c = g4_get_pixel (row, a0);
eric@94 248
eric@94 249 a1 = g4_find_pixel (row, a0 + 1, width, ! a0_c);
eric@95 250 b1 = g4_find_pixel (ref, a0 + 1, width, ! g4_get_pixel (ref, a0));
eric@95 251 if (g4_get_pixel (ref, b1) == a0_c)
eric@95 252 b1 = g4_find_pixel (ref, b1 + 1, width, ! a0_c);
eric@95 253 #if G4_DEBUG
eric@95 254 fprintf (stderr, "a1 = %u, b1 = %u\n", a1, b1);
eric@95 255 #endif
eric@73 256 }
eric@73 257 }
eric@73 258
eric@73 259
eric@91 260 void bitblt_write_g4 (Bitmap *bitmap, FILE *f)
eric@59 261 {
eric@95 262 uint32_t width = bitmap->rect.max.x - bitmap->rect.min.x;
eric@67 263 uint32_t row;
eric@91 264 struct bit_buffer bb;
eric@67 265
eric@94 266 word_type *temp_buffer;
eric@94 267
eric@94 268 word_type *cur_line;
eric@94 269 word_type *ref_line; /* reference (previous) row */
eric@94 270
eric@95 271 #if G4_DEBUG
eric@95 272 fprintf (stderr, "width %u\n", width);
eric@95 273 #endif
eric@95 274
eric@94 275 temp_buffer = pdf_calloc ((width + BITS_PER_WORD - 1) / BITS_PER_WORD,
eric@94 276 sizeof (word_type));
eric@94 277
eric@94 278 cur_line = bitmap->bits;
eric@94 279 ref_line = temp_buffer;
eric@91 280
eric@95 281 init_bit_buffer (& bb);
eric@59 282
eric@91 283 bb.f = f;
eric@91 284
eric@91 285 for (row = bitmap->rect.min.y;
eric@91 286 row < bitmap->rect.max.y;
eric@67 287 row++)
eric@59 288 {
eric@91 289 g4_encode_row (& bb,
eric@94 290 width,
eric@91 291 (uint8_t *) ref_line,
eric@94 292 (uint8_t *) cur_line);
eric@94 293 ref_line = cur_line;
eric@94 294 cur_line += bitmap->row_words;
eric@59 295 }
eric@67 296
eric@67 297
eric@73 298 /* write EOFB code */
eric@91 299 write_bits (& bb, 24, 0x001001);
eric@67 300
eric@91 301 flush_bits (& bb);
eric@94 302
eric@94 303 free (temp_buffer);
eric@59 304 }
eric@59 305
eric@59 306