1
/* Copyright (C) 2001-2006 Artifex Software, Inc.
4
This software is provided AS-IS with no warranty, either express or
7
This software is distributed under license and may not be copied, modified
8
or distributed except as expressly authorized under the terms of that
9
license. Refer to licensing information at http://www.artifex.com/
10
or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134,
11
San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information.
14
/* $Id: gsbitops.h 8022 2007-06-05 22:23:38Z giles $ */
15
/* Interface for bitmap operations */
17
#ifndef gsbitops_INCLUDED
18
# define gsbitops_INCLUDED
20
/* ---------------- Pixel processing macros ---------------- */
23
* These macros support code that processes data pixel-by-pixel (or, to be
24
* more accurate, packed arrays of values -- they may be complete pixels
25
* or individual components of pixels).
27
* Supported #s of bits per value (bpv) are 1, 2, 4, or n * 8, where n <= 8.
28
* The suffix 8, 12, 16, 32, or 64 on a macro name indicates the maximum
29
* value of bpv that the macro is prepared to handle.
31
* The setup macros number bits within a byte in big-endian order, i.e.,
32
* 0x80 is bit 0, 0x01 is bit 7. However, sbit/dbit may use a different
33
* representation for better performance. ****** NYI ******
37
default: return_error(gs_error_rangecheck);\
40
/* Declare variables for loading. */
41
#define sample_load_declare(sptr, sbit)\
44
#define sample_load_declare_setup(sptr, sbit, ptr, bitno, sbpv)\
45
const byte *sptr = (ptr);\
46
int sample_load_setup(sbit, bitno, sbpv)
48
/* Set up to load starting at a given bit number. */
49
#define sample_load_setup(sbit, bitno, sbpv)\
52
/* macro to eliminate compiler warning message */
53
#define sample_bound_shift(value, shift)\
54
((shift) >= 8 * sizeof(value) ? (shift) & (8 * sizeof(value) - 1) : (shift))
56
/* Load a value from memory, without incrementing. */
57
#define sample_load8_(value, sptr, sbit, sbpv)\
59
switch ( (sbpv) >> 2 ) {\
60
case 0: value = (*(sptr) >> (8 - (sbit) - (sbpv))) & ((sbpv) | 1); break;\
61
case 1: value = (*(sptr) >> (4 - (sbit))) & 0xf; break;\
62
case 2: value = *(sptr); break;
63
#define sample_load8(value, sptr, sbit, sbpv)\
64
sample_load8_(value, sptr, sbit, sbpv)\
66
#define sample_load_next8(value, sptr, sbit, sbpv)\
67
sample_load8(value, sptr, sbit, sbpv);\
68
sample_next(sptr, sbit, sbpv)
69
#define sample_load12_(value, sptr, sbit, sbpv)\
70
sample_load8_(value, sptr, sbit, sbpv)\
72
value = ((sbit) ? ((*(sptr) & 0xf) << 8) | (sptr)[1] :\
73
(*(sptr) << 4) | ((sptr)[1] >> 4));\
75
#define sample_load12(value, sptr, sbit, sbpv)\
76
sample_load12_(value, sptr, sbit, sbpv)\
78
#define sample_load_next12(value, sptr, sbit, sbpv)\
79
sample_load12(value, sptr, sbit, sbpv);\
80
sample_next(sptr, sbit, sbpv)
81
#define sample_load16_(value, sptr, sbit, sbpv)\
82
sample_load12_(value, sptr, sbit, sbpv)\
83
case 4: value = (*(sptr) << 8) | (sptr)[1]; break;
84
#define sample_load16(value, sptr, sbit, sbpv)\
85
sample_load16_(value, sptr, sbit, sbpv)\
87
#define sample_load_next16(value, sptr, sbit, sbpv)\
88
sample_load16(value, sptr, sbit, sbpv);\
89
sample_next(sptr, sbit, sbpv)
90
#define sample_load32_(value, sptr, sbit, sbpv)\
91
sample_load16_(value, sptr, sbit, sbpv)\
92
case 6: value = (*(sptr) << 16) | ((sptr)[1] << 8) | (sptr)[2]; break;\
94
value = (*(sptr) << 24) | ((sptr)[1] << 16) | ((sptr)[2] << 8) | sptr[3];\
96
#define sample_load32(value, sptr, sbit, sbpv)\
97
sample_load32_(value, sptr, sbit, sbpv);\
99
#define sample_load_next32(value, sptr, sbit, sbpv)\
100
sample_load32(value, sptr, sbit, sbpv);\
101
sample_next(sptr, sbit, sbpv)
102
#define sample_load64_(value, sptr, sbit, sbpv)\
103
sample_load32_(value, sptr, sbit, sbpv);\
105
value = ((gx_color_index)((sptr)[0]) << sample_bound_shift((value), 32)) |\
106
((gx_color_index)((sptr)[1]) << 24) |\
107
((gx_color_index)((sptr)[2]) << 16) |\
108
((gx_color_index)((sptr)[3]) << 8) |\
109
(gx_color_index)((sptr)[4]);\
112
value = ((gx_color_index)((sptr)[0]) << sample_bound_shift((value), 40)) |\
113
((gx_color_index)((sptr)[1]) << sample_bound_shift((value), 32)) |\
114
((gx_color_index)((sptr)[2]) << 24) |\
115
((gx_color_index)((sptr)[3]) << 16) |\
116
((gx_color_index)((sptr)[4]) << 8) |\
117
(gx_color_index)((sptr)[5]);\
120
value = ((gx_color_index)((sptr)[0]) << sample_bound_shift((value), 48)) |\
121
((gx_color_index)((sptr)[1]) << sample_bound_shift((value), 40)) |\
122
((gx_color_index)((sptr)[2]) << sample_bound_shift((value), 32)) |\
123
((gx_color_index)((sptr)[3]) << 24) |\
124
((gx_color_index)((sptr)[4]) << 16) |\
125
((gx_color_index)((sptr)[5]) << 8) |\
126
(gx_color_index)((sptr)[6]);\
129
value = ((gx_color_index)((sptr)[0]) << sample_bound_shift((value), 56)) |\
130
((gx_color_index)((sptr)[1]) << sample_bound_shift((value), 48)) |\
131
((gx_color_index)((sptr)[2]) << sample_bound_shift((value), 40)) |\
132
((gx_color_index)((sptr)[3]) << sample_bound_shift((value), 32)) |\
133
((gx_color_index)((sptr)[4]) << 24) |\
134
((gx_color_index)((sptr)[5]) << 16) |\
135
((gx_color_index)((sptr)[6]) << 8) |\
136
(gx_color_index)((sptr)[7]);\
138
#define sample_load64(value, sptr, sbit, sbpv)\
139
sample_load64_(value, sptr, sbit, sbpv);\
141
#define sample_load_next64(value, sptr, sbit, sbpv)\
142
sample_load64(value, sptr, sbit, sbpv);\
143
sample_next(sptr, sbit, sbpv)
144
#define sample_load_any(value, sptr, sbit, sbpv)\
145
if (sizeof(value) > 4)\
146
sample_load64(value, sptr, sbit, sbpv);\
148
sample_load32(value, sptr, sbit, sbpv)
149
#define sample_load_next_any(value, sptr, sbit, sbpv)\
150
sample_load_any(value, sptr, sbit, sbpv);\
151
sample_next(sptr, sbit, sbpv)
153
/* Declare variables for storing. */
154
#define sample_store_declare(dptr, dbit, dbbyte)\
157
byte dbbyte /* maybe should be uint? */
158
#define sample_store_declare_setup(dptr, dbit, dbbyte, ptr, bitno, dbpv)\
160
int sample_store_setup(dbit, bitno, dbpv);\
161
byte /* maybe should be uint? */\
162
sample_store_preload(dbbyte, dptr, dbit, dbpv)
164
/* Set up to store starting at a given bit number. */
165
#define sample_store_setup(dbit, bitno, dbpv)\
168
/* Prepare for storing by preloading any partial byte. */
169
#define sample_store_preload(dbbyte, dptr, dbit, dbpv)\
170
dbbyte = ((dbit) ? (byte)(*(dptr) & (0xff00 >> (dbit))) : 0)
172
/* Store a value and increment the pointer. */
173
#define sample_store_next8_(value, dptr, dbit, dbpv, dbbyte)\
175
switch ( (dbpv) >> 2 ) {\
177
if ( (dbit += (dbpv)) == 8 )\
178
*(dptr)++ = dbbyte | (byte)(value), dbbyte = 0, dbit = 0;\
179
else dbbyte |= (byte)((value) << (8 - dbit));\
182
if ( dbit ^= 4 ) dbbyte = (byte)((value) << 4);\
183
else *(dptr)++ = dbbyte | ((byte)(value));\
185
/* case 2 is deliberately omitted */
186
#define sample_store_next8(value, dptr, dbit, dbpv, dbbyte)\
187
sample_store_next8_(value, dptr, dbit, dbpv, dbbyte)\
188
case 2: *(dptr)++ = (byte)(value); break;\
190
#define sample_store_next_12_(value, dptr, dbit, dbbyte)\
191
if ( dbit ^= 4 ) *(dptr)++ = (byte)((value) >> 4), dbbyte = (byte)((value) << 4);\
193
*(dptr) = dbbyte | (byte)((value) >> 8), (dptr)[1] = (byte)(value), dptr += 2;
194
#define sample_store_next_12(value, dptr, dbit, dbbyte)\
195
BEGIN sample_store_next_12_(value, dptr, dbit, dbbyte) END
196
#define sample_store_next12_(value, dptr, dbit, dbpv, dbbyte)\
197
sample_store_next8_(value, dptr, dbit, dbpv, dbbyte)\
198
/* case 2 is deliberately omitted */\
199
case 3: sample_store_next_12_(value, dptr, dbit, dbbyte) break;
200
#define sample_store_next12(value, dptr, dbit, dbpv, dbbyte)\
201
sample_store_next12_(value, dptr, dbit, dbpv, dbbyte)\
202
case 2: *(dptr)++ = (byte)(value); break;\
204
#define sample_store_next16(value, dptr, dbit, dbpv, dbbyte)\
205
sample_store_next12_(value, dptr, dbit, dbpv, dbbyte)\
206
case 4: *(dptr)++ = (byte)((value) >> 8);\
207
case 2: *(dptr)++ = (byte)(value); break;\
209
#define sample_store_next32(value, dptr, dbit, dbpv, dbbyte)\
210
sample_store_next12_(value, dptr, dbit, dbpv, dbbyte)\
211
case 8: *(dptr)++ = (byte)((value) >> 24);\
212
case 6: *(dptr)++ = (byte)((value) >> 16);\
213
case 4: *(dptr)++ = (byte)((value) >> 8);\
214
case 2: *(dptr)++ = (byte)(value); break;\
216
#define sample_store_next64(value, dptr, dbit, dbpv, dbbyte)\
217
sample_store_next12_(value, dptr, dbit, dbpv, dbbyte)\
218
case 16: *(dptr)++ = (byte)((value) >> sample_bound_shift((value), 56));\
219
case 14: *(dptr)++ = (byte)((value) >> sample_bound_shift((value), 48));\
220
case 12: *(dptr)++ = (byte)((value) >> sample_bound_shift((value), 40));\
221
case 10: *(dptr)++ = (byte)((value) >> sample_bound_shift((value), 32));\
222
case 8: *(dptr)++ = (byte)((value) >> 24);\
223
case 6: *(dptr)++ = (byte)((value) >> 16);\
224
case 4: *(dptr)++ = (byte)((value) >> 8);\
225
case 2: *(dptr)++ = (byte)(value); break;\
227
#define sample_store_next_any(value, dptr, dbit, dbpv, dbbyte)\
228
if (sizeof(value) > 4)\
229
sample_store_next64(value, dptr, dbit, dbpv, dbbyte);\
231
sample_store_next32(value, dptr, dbit, dbpv, dbbyte)
233
/* Skip over storing one sample. This may or may not store into the */
234
/* skipped region. */
235
#define sample_store_skip_next(dptr, dbit, dbpv, dbbyte)\
237
sample_store_flush(dptr, dbit, dbpv, dbbyte);\
238
sample_next(dptr, dbit, dbpv);\
239
} else dptr += ((dbpv) >> 3)
241
/* Finish storing by flushing any partial byte. */
242
#define sample_store_flush(dptr, dbit, dbpv, dbbyte)\
244
*(dptr) = dbbyte | (*(dptr) & (0xff >> (dbit)));
246
/* Increment a pointer to the next sample. */
247
#define sample_next(ptr, bit, bpv)\
248
BEGIN bit += (bpv); ptr += bit >> 3; bit &= 7; END
250
/* ---------------- Definitions ---------------- */
253
* Define the chunk size for monobit filling operations.
254
* This is always uint, regardless of byte order.
256
#define mono_fill_chunk uint
257
#define mono_fill_chunk_bytes arch_sizeof_int
259
/* ---------------- Procedures ---------------- */
261
/* Fill a rectangle of bits with an 8x1 pattern. */
262
/* The pattern argument must consist of the pattern in every byte, */
263
/* e.g., if the desired pattern is 0xaa, the pattern argument must */
264
/* have the value 0xaaaa (if ints are short) or 0xaaaaaaaa. */
265
#if mono_fill_chunk_bytes == 2
266
# define mono_fill_make_pattern(byt) (uint)((uint)(byt) * 0x0101)
268
# define mono_fill_make_pattern(byt) (uint)((uint)(byt) * 0x01010101)
270
void bits_fill_rectangle(byte * dest, int dest_bit, uint raster,
271
mono_fill_chunk pattern, int width_bits, int height);
272
void bits_fill_rectangle_masked(byte * dest, int dest_bit, uint raster,
273
mono_fill_chunk pattern, mono_fill_chunk src_mask,
274
int width_bits, int height);
276
/* Replicate a bitmap horizontally in place. */
277
void bits_replicate_horizontally(byte * data, uint width, uint height,
278
uint raster, uint replicated_width, uint replicated_raster);
280
/* Replicate a bitmap vertically in place. */
281
void bits_replicate_vertically(byte * data, uint height, uint raster,
282
uint replicated_height);
284
/* Find the bounding box of a bitmap. */
285
void bits_bounding_box(const byte * data, uint height, uint raster,
288
/* Compress an oversampled image, possibly in place. */
289
/* The width and height must be multiples of the respective scale factors. */
290
/* The source must be an aligned bitmap, as usual. */
291
void bits_compress_scaled(const byte * src, int srcx, uint width,
292
uint height, uint sraster, byte * dest, uint draster,
293
const gs_log2_scale_point * plog2_scale, int log2_out_bits);
295
/* Extract a plane from a pixmap. */
296
typedef struct bits_plane_s {
297
union bpd_ { /* Bit planes must be aligned. */
303
int x; /* starting x */
305
int bits_extract_plane(const bits_plane_t *dest /*write*/,
306
const bits_plane_t *source /*read*/, int shift, int width, int height);
308
/* Expand a plane into a pixmap. */
309
int bits_expand_plane(const bits_plane_t *dest /*write*/,
310
const bits_plane_t *source /*read*/, int shift, int width, int height);
312
/* Fill a rectangle of bytes. */
313
void bytes_fill_rectangle(byte * dest, uint raster,
314
byte value, int width_bytes, int height);
316
/* Copy a rectangle of bytes. */
317
void bytes_copy_rectangle(byte * dest, uint dest_raster,
318
const byte * src, uint src_raster, int width_bytes, int height);
320
#endif /* gsbitops_INCLUDED */