2 |
- |
1 |
/* Copyright (C) 2000 Aladdin Enterprises. All rights reserved.
|
|
|
2 |
|
|
|
3 |
This software is provided AS-IS with no warranty, either express or
|
|
|
4 |
implied.
|
|
|
5 |
|
|
|
6 |
This software is distributed under license and may not be copied,
|
|
|
7 |
modified or distributed except as expressly authorized under the terms
|
|
|
8 |
of the license contained in the file LICENSE in this distribution.
|
|
|
9 |
|
|
|
10 |
For more information about licensing, please refer to
|
|
|
11 |
http://www.ghostscript.com/licensing/. For information on
|
|
|
12 |
commercial licensing, go to http://www.artifex.com/licensing/ or
|
|
|
13 |
contact Artifex Software, Inc., 101 Lucas Valley Road #110,
|
|
|
14 |
San Rafael, CA 94903, U.S.A., +1(415)492-9861.
|
|
|
15 |
*/
|
|
|
16 |
|
|
|
17 |
/* $Id: gsbitcom.c,v 1.3 2002/02/21 22:24:52 giles Exp $ */
|
|
|
18 |
/* Oversampled bitmap compression */
|
|
|
19 |
#include "std.h"
|
|
|
20 |
#include "gstypes.h"
|
|
|
21 |
#include "gdebug.h"
|
|
|
22 |
#include "gsbitops.h" /* for prototype */
|
|
|
23 |
|
|
|
24 |
/*
|
|
|
25 |
* Define a compile-time option to reverse nibble order in alpha maps.
|
|
|
26 |
* Note that this does not reverse bit order within nibbles.
|
|
|
27 |
* This option is here for a very specialized purpose and does not
|
|
|
28 |
* interact well with the rest of the code.
|
|
|
29 |
*/
|
|
|
30 |
#ifndef ALPHA_LSB_FIRST
|
|
|
31 |
# define ALPHA_LSB_FIRST 0
|
|
|
32 |
#endif
|
|
|
33 |
|
|
|
34 |
/* Count the number of 1-bits in a half-byte. */
|
|
|
35 |
static const byte half_byte_1s[16] = {
|
|
|
36 |
0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4
|
|
|
37 |
};
|
|
|
38 |
|
|
|
39 |
/* Count the number of trailing 1s in an up-to-5-bit value, -1. */
|
|
|
40 |
static const byte bits5_trailing_1s[32] = {
|
|
|
41 |
0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 3,
|
|
|
42 |
0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 4
|
|
|
43 |
};
|
|
|
44 |
|
|
|
45 |
/* Count the number of leading 1s in an up-to-5-bit value, -1. */
|
|
|
46 |
static const byte bits5_leading_1s[32] = {
|
|
|
47 |
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
48 |
0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 3, 4
|
|
|
49 |
};
|
|
|
50 |
|
|
|
51 |
/*
|
|
|
52 |
* Compress a value between 0 and 2^M to a value between 0 and 2^N-1.
|
|
|
53 |
* Possible values of M are 1, 2, 3, or 4; of N are 1, 2, and 4.
|
|
|
54 |
* The name of the table is compress_count_M_N.
|
|
|
55 |
* As noted below, we require that N <= M.
|
|
|
56 |
*/
|
|
|
57 |
static const byte compress_1_1[3] = {
|
|
|
58 |
0, 1, 1
|
|
|
59 |
};
|
|
|
60 |
static const byte compress_2_1[5] = {
|
|
|
61 |
0, 0, 1, 1, 1
|
|
|
62 |
};
|
|
|
63 |
static const byte compress_2_2[5] = {
|
|
|
64 |
0, 1, 2, 2, 3
|
|
|
65 |
};
|
|
|
66 |
static const byte compress_3_1[9] = {
|
|
|
67 |
0, 0, 0, 0, 1, 1, 1, 1, 1
|
|
|
68 |
};
|
|
|
69 |
static const byte compress_3_2[9] = {
|
|
|
70 |
0, 0, 1, 1, 2, 2, 2, 3, 3
|
|
|
71 |
};
|
|
|
72 |
static const byte compress_4_1[17] = {
|
|
|
73 |
0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
|
|
|
74 |
};
|
|
|
75 |
static const byte compress_4_2[17] = {
|
|
|
76 |
0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3
|
|
|
77 |
};
|
|
|
78 |
static const byte compress_4_4[17] = {
|
|
|
79 |
0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 10, 11, 12, 13, 14, 15
|
|
|
80 |
};
|
|
|
81 |
|
|
|
82 |
/* The table of tables is indexed by log2(N) and then by M-1. */
|
|
|
83 |
static const byte *const compress_tables[4][4] = {
|
|
|
84 |
{compress_1_1, compress_2_1, compress_3_1, compress_4_1},
|
|
|
85 |
{0, compress_2_2, compress_3_2, compress_4_2},
|
|
|
86 |
{0, 0, 0, compress_4_4}
|
|
|
87 |
};
|
|
|
88 |
|
|
|
89 |
/*
|
|
|
90 |
* Compress an XxY-oversampled bitmap to Nx1 by counting 1-bits. The X and
|
|
|
91 |
* Y oversampling factors are 1, 2, or 4, but may be different. N, the
|
|
|
92 |
* resulting number of (alpha) bits per pixel, may be 1, 2, or 4; we allow
|
|
|
93 |
* compression in place, in which case N must not exceed the X oversampling
|
|
|
94 |
* factor. Width and height are the source dimensions, and hence reflect
|
|
|
95 |
* the oversampling; both are multiples of the relevant scale factor. The
|
|
|
96 |
* same is true for srcx.
|
|
|
97 |
*/
|
|
|
98 |
void
|
|
|
99 |
bits_compress_scaled(const byte * src, int srcx, uint width, uint height,
|
|
|
100 |
uint sraster, byte * dest, uint draster,
|
|
|
101 |
const gs_log2_scale_point *plog2_scale, int log2_out_bits)
|
|
|
102 |
{
|
|
|
103 |
int log2_x = plog2_scale->x, log2_y = plog2_scale->y;
|
|
|
104 |
int xscale = 1 << log2_x;
|
|
|
105 |
int yscale = 1 << log2_y;
|
|
|
106 |
int out_bits = 1 << log2_out_bits;
|
|
|
107 |
/*
|
|
|
108 |
* The following two initializations are only needed (and the variables
|
|
|
109 |
* are only used) if out_bits <= xscale. We do them in all cases only
|
|
|
110 |
* to suppress bogus "possibly uninitialized variable" warnings from
|
|
|
111 |
* certain compilers.
|
|
|
112 |
*/
|
|
|
113 |
int input_byte_out_bits = out_bits << (3 - log2_x);
|
|
|
114 |
byte input_byte_out_mask = (1 << input_byte_out_bits) - 1;
|
|
|
115 |
const byte *table =
|
|
|
116 |
compress_tables[log2_out_bits][log2_x + log2_y - 1];
|
|
|
117 |
uint sskip = sraster << log2_y;
|
|
|
118 |
uint dwidth = (width >> log2_x) << log2_out_bits;
|
|
|
119 |
uint dskip = draster - ((dwidth + 7) >> 3);
|
|
|
120 |
uint mask = (1 << xscale) - 1;
|
|
|
121 |
uint count_max = 1 << (log2_x + log2_y);
|
|
|
122 |
/*
|
|
|
123 |
* For the moment, we don't attempt to take advantage of the fact
|
|
|
124 |
* that the input is aligned.
|
|
|
125 |
*/
|
|
|
126 |
const byte *srow = src + (srcx >> 3);
|
|
|
127 |
int in_shift_initial = 8 - xscale - (srcx & 7);
|
|
|
128 |
int in_shift_check = (out_bits <= xscale ? 8 - xscale : -1);
|
|
|
129 |
byte *d = dest;
|
|
|
130 |
uint h;
|
|
|
131 |
|
|
|
132 |
for (h = height; h; srow += sskip, h -= yscale) {
|
|
|
133 |
const byte *s = srow;
|
|
|
134 |
|
|
|
135 |
#if ALPHA_LSB_FIRST
|
|
|
136 |
# define out_shift_initial 0
|
|
|
137 |
# define out_shift_update(out_shift, nbits) ((out_shift += (nbits)) >= 8)
|
|
|
138 |
#else
|
|
|
139 |
# define out_shift_initial (8 - out_bits)
|
|
|
140 |
# define out_shift_update(out_shift, nbits) ((out_shift -= (nbits)) < 0)
|
|
|
141 |
#endif
|
|
|
142 |
int out_shift = out_shift_initial;
|
|
|
143 |
byte out = 0;
|
|
|
144 |
int in_shift = in_shift_initial;
|
|
|
145 |
int dw = 8 - (srcx & 7);
|
|
|
146 |
int w;
|
|
|
147 |
|
|
|
148 |
/* Loop over source bytes. */
|
|
|
149 |
for (w = width; w > 0; w -= dw, dw = 8) {
|
|
|
150 |
int index;
|
|
|
151 |
int in_shift_final = (w >= dw ? 0 : dw - w);
|
|
|
152 |
|
|
|
153 |
/*
|
|
|
154 |
* Check quickly for all-0s or all-1s, but only if each
|
|
|
155 |
* input byte generates no more than one output byte,
|
|
|
156 |
* we're at an input byte boundary, and we're processing
|
|
|
157 |
* an entire input byte (i.e., this isn't a final
|
|
|
158 |
* partial byte.)
|
|
|
159 |
*/
|
|
|
160 |
if (in_shift == in_shift_check && in_shift_final == 0)
|
|
|
161 |
switch (*s) {
|
|
|
162 |
case 0:
|
|
|
163 |
for (index = sraster; index != sskip; index += sraster)
|
|
|
164 |
if (s[index] != 0)
|
|
|
165 |
goto p;
|
|
|
166 |
if (out_shift_update(out_shift, input_byte_out_bits))
|
|
|
167 |
*d++ = out, out_shift &= 7, out = 0;
|
|
|
168 |
s++;
|
|
|
169 |
continue;
|
|
|
170 |
#if !ALPHA_LSB_FIRST /* too messy to make it work */
|
|
|
171 |
case 0xff:
|
|
|
172 |
for (index = sraster; index != sskip; index += sraster)
|
|
|
173 |
if (s[index] != 0xff)
|
|
|
174 |
goto p;
|
|
|
175 |
{
|
|
|
176 |
int shift =
|
|
|
177 |
(out_shift -= input_byte_out_bits) + out_bits;
|
|
|
178 |
|
|
|
179 |
if (shift > 0)
|
|
|
180 |
out |= input_byte_out_mask << shift;
|
|
|
181 |
else {
|
|
|
182 |
out |= input_byte_out_mask >> -shift;
|
|
|
183 |
*d++ = out;
|
|
|
184 |
out_shift += 8;
|
|
|
185 |
out = input_byte_out_mask << (8 + shift);
|
|
|
186 |
}
|
|
|
187 |
}
|
|
|
188 |
s++;
|
|
|
189 |
continue;
|
|
|
190 |
#endif
|
|
|
191 |
default:
|
|
|
192 |
;
|
|
|
193 |
}
|
|
|
194 |
p: /* Loop over source pixels within a byte. */
|
|
|
195 |
do {
|
|
|
196 |
uint count;
|
|
|
197 |
|
|
|
198 |
for (index = 0, count = 0; index != sskip;
|
|
|
199 |
index += sraster
|
|
|
200 |
)
|
|
|
201 |
count += half_byte_1s[(s[index] >> in_shift) & mask];
|
|
|
202 |
if (count != 0 && table[count] == 0) { /* Look at adjacent cells to help prevent */
|
|
|
203 |
/* dropouts. */
|
|
|
204 |
uint orig_count = count;
|
|
|
205 |
uint shifted_mask = mask << in_shift;
|
|
|
206 |
byte in;
|
|
|
207 |
|
|
|
208 |
if_debug3('B', "[B]count(%d,%d)=%d\n",
|
|
|
209 |
(width - w) / xscale,
|
|
|
210 |
(height - h) / yscale, count);
|
|
|
211 |
if (yscale > 1) { /* Look at the next "lower" cell. */
|
|
|
212 |
if (h < height && (in = s[0] & shifted_mask) != 0) {
|
|
|
213 |
uint lower;
|
|
|
214 |
|
|
|
215 |
for (index = 0, lower = 0;
|
|
|
216 |
-(index -= sraster) <= sskip &&
|
|
|
217 |
(in &= s[index]) != 0;
|
|
|
218 |
)
|
|
|
219 |
lower += half_byte_1s[in >> in_shift];
|
|
|
220 |
if_debug1('B', "[B] lower adds %d\n",
|
|
|
221 |
lower);
|
|
|
222 |
if (lower <= orig_count)
|
|
|
223 |
count += lower;
|
|
|
224 |
}
|
|
|
225 |
/* Look at the next "higher" cell. */
|
|
|
226 |
if (h > yscale && (in = s[sskip - sraster] & shifted_mask) != 0) {
|
|
|
227 |
uint upper;
|
|
|
228 |
|
|
|
229 |
for (index = sskip, upper = 0;
|
|
|
230 |
index < sskip << 1 &&
|
|
|
231 |
(in &= s[index]) != 0;
|
|
|
232 |
index += sraster
|
|
|
233 |
)
|
|
|
234 |
upper += half_byte_1s[in >> in_shift];
|
|
|
235 |
if_debug1('B', "[B] upper adds %d\n",
|
|
|
236 |
upper);
|
|
|
237 |
if (upper < orig_count)
|
|
|
238 |
count += upper;
|
|
|
239 |
}
|
|
|
240 |
}
|
|
|
241 |
if (xscale > 1) {
|
|
|
242 |
uint mask1 = (mask << 1) + 1;
|
|
|
243 |
|
|
|
244 |
/* Look at the next cell to the left. */
|
|
|
245 |
if (w < width) {
|
|
|
246 |
int lshift = in_shift + xscale - 1;
|
|
|
247 |
uint left;
|
|
|
248 |
|
|
|
249 |
for (index = 0, left = 0;
|
|
|
250 |
index < sskip; index += sraster
|
|
|
251 |
) {
|
|
|
252 |
uint bits =
|
|
|
253 |
((s[index - 1] << 8) +
|
|
|
254 |
s[index]) >> lshift;
|
|
|
255 |
|
|
|
256 |
left += bits5_trailing_1s[bits & mask1];
|
|
|
257 |
}
|
|
|
258 |
if_debug1('B', "[B] left adds %d\n",
|
|
|
259 |
left);
|
|
|
260 |
if (left < orig_count)
|
|
|
261 |
count += left;
|
|
|
262 |
}
|
|
|
263 |
/* Look at the next cell to the right. */
|
|
|
264 |
if (w > xscale) {
|
|
|
265 |
int rshift = in_shift - xscale + 8;
|
|
|
266 |
uint right;
|
|
|
267 |
|
|
|
268 |
for (index = 0, right = 0;
|
|
|
269 |
index < sskip; index += sraster
|
|
|
270 |
) {
|
|
|
271 |
uint bits =
|
|
|
272 |
((s[index] << 8) +
|
|
|
273 |
s[index + 1]) >> rshift;
|
|
|
274 |
|
|
|
275 |
right += bits5_leading_1s[(bits & mask1) << (4 - xscale)];
|
|
|
276 |
}
|
|
|
277 |
if_debug1('B', "[B] right adds %d\n",
|
|
|
278 |
right);
|
|
|
279 |
if (right <= orig_count)
|
|
|
280 |
count += right;
|
|
|
281 |
}
|
|
|
282 |
}
|
|
|
283 |
if (count > count_max)
|
|
|
284 |
count = count_max;
|
|
|
285 |
}
|
|
|
286 |
out += table[count] << out_shift;
|
|
|
287 |
if (out_shift_update(out_shift, out_bits))
|
|
|
288 |
*d++ = out, out_shift &= 7, out = 0;
|
|
|
289 |
}
|
|
|
290 |
while ((in_shift -= xscale) >= in_shift_final);
|
|
|
291 |
s++, in_shift += 8;
|
|
|
292 |
}
|
|
|
293 |
if (out_shift != out_shift_initial)
|
|
|
294 |
*d++ = out;
|
|
|
295 |
for (w = dskip; w != 0; w--)
|
|
|
296 |
*d++ = 0;
|
|
|
297 |
#undef out_shift_initial
|
|
|
298 |
#undef out_shift_update
|
|
|
299 |
}
|
|
|
300 |
}
|