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.

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