Coverage Report

Created: 2025-06-24 07:01

/src/ghostpdl/base/gsbitcom.c
Line
Count
Source (jump to first uncovered line)
1
/* Copyright (C) 2001-2023 Artifex Software, Inc.
2
   All Rights Reserved.
3
4
   This software is provided AS-IS with no warranty, either express or
5
   implied.
6
7
   This software is distributed under license and may not be copied,
8
   modified or distributed except as expressly authorized under the terms
9
   of the license contained in the file LICENSE in this distribution.
10
11
   Refer to licensing information at http://www.artifex.com or contact
12
   Artifex Software, Inc.,  39 Mesa Street, Suite 108A, San Francisco,
13
   CA 94129, USA, for further information.
14
*/
15
16
#include <assert.h>
17
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
0
{
103
0
    int log2_x = plog2_scale->x, log2_y = plog2_scale->y;
104
0
    int xscale = 1 << log2_x;
105
0
    int yscale = 1 << log2_y;
106
0
    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
0
    int input_byte_out_bits = out_bits << (3 - log2_x);
114
0
    byte input_byte_out_mask = (1 << input_byte_out_bits) - 1;
115
0
    const byte *table =
116
0
        compress_tables[log2_out_bits][log2_x + log2_y - 1];
117
0
    uint sskip = sraster << log2_y;
118
0
    uint dwidth = (width >> log2_x) << log2_out_bits;
119
0
    uint dskip = draster - ((dwidth + 7) >> 3);
120
0
    uint mask = (1 << xscale) - 1;
121
0
    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
0
    const byte *srow = src + (srcx >> 3);
127
0
    int in_shift_initial = 8 - xscale - (srcx & 7);
128
0
    int in_shift_check = (out_bits <= xscale ? 8 - xscale : -1);
129
0
    byte *d = dest;
130
0
    uint h;
131
132
    /* Assert some preconditions are satisfied: */
133
134
    /* log2_x and log2_y must each be 0, 1 or 2. */
135
0
    assert(log2_x >= 0 && log2_x < 3);
136
0
    assert(log2_y >= 0 && log2_y < 3);
137
138
    /* srcx and width must be multiple of xscale. */
139
0
    assert(srcx % xscale == 0);
140
0
    assert(width % xscale == 0);
141
142
    /* height must be multiple of yscale. */
143
0
    assert(height % yscale == 0);
144
145
    /* because xscale is 1, 2 or 4 and srcx is a multiple of xscale,
146
    in_shift_initial ends up being constrained as follows: */
147
0
    if (log2_x == 0) {
148
        /* in_shift_initial is {0,1,2,3,4,5,6,7]} */
149
0
        assert(in_shift_initial >= 0 && in_shift_initial < 8);
150
0
    }
151
0
    if (log2_x == 1) {
152
        /* in_shift_initial is {0,2,4,6}. */
153
0
        assert(in_shift_initial >= 0 && in_shift_initial < 7 && in_shift_initial % 2 == 0);
154
0
    }
155
0
    if (log2_x == 2) {
156
        /* in_shift_initial is {0,4} */
157
0
        assert(in_shift_initial == 0 || in_shift_initial == 4);
158
0
    }
159
160
0
    for (h = height; h; srow += sskip, h -= yscale) {
161
0
        const byte *s = srow;
162
163
#if ALPHA_LSB_FIRST
164
#  define out_shift_initial 0
165
#  define out_shift_update(out_shift, nbits) ((out_shift += (nbits)) >= 8)
166
#else
167
0
#  define out_shift_initial (8 - out_bits)
168
0
#  define out_shift_update(out_shift, nbits) ((out_shift -= (nbits)) < 0)
169
0
#endif
170
0
        int out_shift = out_shift_initial;
171
0
        byte out = 0;
172
0
        int in_shift = in_shift_initial;
173
0
        int dw = 8 - (srcx & 7);
174
0
        int w;
175
176
        /* Loop over source bytes. */
177
0
        for (w = width; w > 0; w -= dw, dw = 8) {
178
0
            int index;
179
0
            int in_shift_final = (w >= dw ? 0 : dw - w);
180
181
            /*
182
             * Check quickly for all-0s or all-1s, but only if each
183
             * input byte generates no more than one output byte,
184
             * we're at an input byte boundary, and we're processing
185
             * an entire input byte (i.e., this isn't a final
186
             * partial byte.)
187
             */
188
0
            if (in_shift == in_shift_check && in_shift_final == 0)
189
0
                switch (*s) {
190
0
                    case 0:
191
0
                        for (index = sraster; index != sskip; index += sraster)
192
0
                            if (s[index] != 0)
193
0
                                goto p;
194
0
                        if (out_shift_update(out_shift, input_byte_out_bits))
195
0
                            *d++ = out, out_shift &= 7, out = 0;
196
0
                        s++;
197
0
                        continue;
198
#if !ALPHA_LSB_FIRST    /* too messy to make it work */
199
0
                    case 0xff:
200
0
                        for (index = sraster; index != sskip; index += sraster)
201
0
                            if (s[index] != 0xff)
202
0
                                goto p;
203
0
                        {
204
0
                            int shift =
205
0
                                (out_shift -= input_byte_out_bits) + out_bits;
206
207
0
                            if (shift > 0)
208
0
                                out |= input_byte_out_mask << shift;
209
0
                            else {
210
0
                                out |= input_byte_out_mask >> -shift;
211
0
                                *d++ = out;
212
0
                                out_shift += 8;
213
0
                                out = input_byte_out_mask << (8 + shift);
214
0
                            }
215
0
                        }
216
0
                        s++;
217
0
                        continue;
218
0
#endif
219
0
                    default:
220
0
                        ;
221
0
                }
222
0
          p:      /* Loop over source pixels within a byte. */
223
0
            do {
224
0
                uint count;
225
226
0
                for (index = 0, count = 0; index != sskip;
227
0
                     index += sraster
228
0
                    ) {
229
                    /* Coverity 94484 incorrectly thinks in_shift can be negative. */
230
                    /* coverity[negative_shift] */
231
0
                    count += half_byte_1s[(s[index] >> in_shift) & mask];
232
0
                }
233
0
                if (count != 0 && table[count] == 0) { /* Look at adjacent cells to help prevent */
234
                    /* dropouts. */
235
0
                    uint orig_count = count;
236
0
                    uint shifted_mask = mask << in_shift;
237
0
                    byte in;
238
239
0
                    if_debug3('B', "[B]count(%d,%d)=%d\n",
240
0
                              (width - w) / xscale,
241
0
                              (height - h) / yscale, count);
242
0
                    if (yscale > 1) { /* Look at the next "lower" cell. */
243
0
                        if (h < height && (in = s[0] & shifted_mask) != 0) {
244
0
                            uint lower;
245
246
0
                            for (index = 0, lower = 0;
247
0
                                 -(index -= sraster) <= sskip &&
248
0
                                 (in &= s[index]) != 0;
249
0
                                )
250
0
                                lower += half_byte_1s[in >> in_shift];
251
0
                            if_debug1('B', "[B]  lower adds %d\n",
252
0
                                      lower);
253
0
                            if (lower <= orig_count)
254
0
                                count += lower;
255
0
                        }
256
                        /* Look at the next "higher" cell. */
257
0
                        if (h > yscale && (in = s[sskip - sraster] & shifted_mask) != 0) {
258
0
                            uint upper;
259
260
0
                            for (index = sskip, upper = 0;
261
0
                                 index < sskip << 1 &&
262
0
                                 (in &= s[index]) != 0;
263
0
                                 index += sraster
264
0
                                )
265
0
                                upper += half_byte_1s[in >> in_shift];
266
0
                            if_debug1('B', "[B]  upper adds %d\n",
267
0
                                      upper);
268
0
                            if (upper < orig_count)
269
0
                                count += upper;
270
0
                        }
271
0
                    }
272
0
                    if (xscale > 1) {
273
0
                        uint mask1 = (mask << 1) + 1;
274
275
                        /* Look at the next cell to the left. */
276
0
                        if (w < width) {
277
0
                            int lshift = in_shift + xscale - 1;
278
0
                            uint left;
279
280
0
                            for (index = 0, left = 0;
281
0
                                 index < sskip; index += sraster
282
0
                                ) {
283
0
                                uint bits =
284
0
                                ((s[index - 1] << 8) +
285
0
                                 s[index]) >> lshift;
286
287
0
                                left += bits5_trailing_1s[bits & mask1];
288
0
                            }
289
0
                            if_debug1('B', "[B]  left adds %d\n",
290
0
                                      left);
291
0
                            if (left < orig_count)
292
0
                                count += left;
293
0
                        }
294
                        /* Look at the next cell to the right. */
295
0
                        if (w > xscale) {
296
0
                            int rshift = in_shift - xscale + 8;
297
0
                            uint right;
298
299
0
                            for (index = 0, right = 0;
300
0
                                 index < sskip; index += sraster
301
0
                                ) {
302
0
                                uint bits =
303
0
                                ((s[index] << 8) +
304
0
                                 s[index + 1]) >> rshift;
305
306
0
                                right += bits5_leading_1s[(bits & mask1) << (4 - xscale)];
307
0
                            }
308
0
                            if_debug1('B', "[B]  right adds %d\n",
309
0
                                      right);
310
0
                            if (right <= orig_count)
311
0
                                count += right;
312
0
                        }
313
0
                    }
314
0
                    if (count > count_max)
315
0
                        count = count_max;
316
0
                }
317
0
                out += table[count] << out_shift;
318
0
                if (out_shift_update(out_shift, out_bits))
319
0
                    *d++ = out, out_shift &= 7, out = 0;
320
0
            }
321
0
            while ((in_shift -= xscale) >= in_shift_final);
322
0
            s++, in_shift += 8;
323
0
        }
324
0
        if (out_shift != out_shift_initial)
325
0
            *d++ = out;
326
0
        for (w = dskip; w != 0; w--)
327
0
            *d++ = 0;
328
0
#undef out_shift_initial
329
0
#undef out_shift_update
330
0
    }
331
0
}