bitblt_g4.c

Mon, 10 Mar 2003 09:49:50 +0000

author
eric
date
Mon, 10 Mar 2003 09:49:50 +0000
changeset 91
e63762afae80
parent 78
74b6b230f85d
child 94
7664a3f112ba
permissions
-rw-r--r--

Moved g4 encoding functions from pdf library to bitblt library.

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