1 /* Copyright (C) 1991, 1995, 1997, 1998, 1999 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: gsbitops.h,v 1.7 2002/09/21 00:26:04 dan Exp $ */ 18 /* Interface for bitmap operations */ 19 20 #ifndef gsbitops_INCLUDED 21 # define gsbitops_INCLUDED 22 23 /* ---------------- Pixel processing macros ---------------- */ 24 25 /* 26 * These macros support code that processes data pixel-by-pixel (or, to be 27 * more accurate, packed arrays of values -- they may be complete pixels 28 * or individual components of pixels). 29 * 30 * Supported #s of bits per value (bpv) are 1, 2, 4, or n * 8, where n <= 8. 31 * The suffix 8, 12, 16, 32, or 64 on a macro name indicates the maximum 32 * value of bpv that the macro is prepared to handle. 33 * 34 * The setup macros number bits within a byte in big-endian order, i.e., 35 * 0x80 is bit 0, 0x01 is bit 7. However, sbit/dbit may use a different 36 * representation for better performance. ****** NYI ****** 37 */ 38 39 #define sample_end_\ 40 default: return_error(gs_error_rangecheck);\ 41 } END 42 43 /* Declare variables for loading. */ 44 #define sample_load_declare(sptr, sbit)\ 45 const byte *sptr;\ 46 int sbit 47 #define sample_load_declare_setup(sptr, sbit, ptr, bitno, sbpv)\ 48 const byte *sptr = (ptr);\ 49 int sample_load_setup(sbit, bitno, sbpv) 50 51 /* Set up to load starting at a given bit number. */ 52 #define sample_load_setup(sbit, bitno, sbpv)\ 53 sbit = (bitno) 54 55 /* macro to eliminate compiler warning message */ 56 #define sample_bound_shift(value, shift)\ 57 ((shift) >= 8 * sizeof(value) ? (shift) & (8 * sizeof(value) - 1) : (shift)) 58 59 /* Load a value from memory, without incrementing. */ 60 #define sample_load8_(value, sptr, sbit, sbpv)\ 61 BEGIN\ 62 switch ( (sbpv) >> 2 ) {\ 63 case 0: value = (*(sptr) >> (8 - (sbit) - (sbpv))) & ((sbpv) | 1); break;\ 64 case 1: value = (*(sptr) >> (4 - (sbit))) & 0xf; break;\ 65 case 2: value = *(sptr); break; 66 #define sample_load8(value, sptr, sbit, sbpv)\ 67 sample_load8_(value, sptr, sbit, sbpv)\ 68 sample_end_ 69 #define sample_load_next8(value, sptr, sbit, sbpv)\ 70 sample_load8(value, sptr, sbit, sbpv);\ 71 sample_next(sptr, sbit, sbpv) 72 #define sample_load12_(value, sptr, sbit, sbpv)\ 73 sample_load8_(value, sptr, sbit, sbpv)\ 74 case 3:\ 75 value = ((sbit) ? ((*(sptr) & 0xf) << 8) | (sptr)[1] :\ 76 (*(sptr) << 4) | ((sptr)[1] >> 4));\ 77 break; 78 #define sample_load12(value, sptr, sbit, sbpv)\ 79 sample_load12_(value, sptr, sbit, sbpv)\ 80 sample_end_ 81 #define sample_load_next12(value, sptr, sbit, sbpv)\ 82 sample_load12(value, sptr, sbit, sbpv);\ 83 sample_next(sptr, sbit, sbpv) 84 #define sample_load16_(value, sptr, sbit, sbpv)\ 85 sample_load12_(value, sptr, sbit, sbpv)\ 86 case 4: value = (*(sptr) << 8) | (sptr)[1]; break; 87 #define sample_load16(value, sptr, sbit, sbpv)\ 88 sample_load16_(value, sptr, sbit, sbpv)\ 89 sample_end_ 90 #define sample_load_next16(value, sptr, sbit, sbpv)\ 91 sample_load16(value, sptr, sbit, sbpv);\ 92 sample_next(sptr, sbit, sbpv) 93 #define sample_load32_(value, sptr, sbit, sbpv)\ 94 sample_load16_(value, sptr, sbit, sbpv)\ 95 case 6: value = (*(sptr) << 16) | ((sptr)[1] << 8) | (sptr)[2]; break;\ 96 case 8:\ 97 value = (*(sptr) << 24) | ((sptr)[1] << 16) | ((sptr)[2] << 8) | sptr[3];\ 98 break; 99 #define sample_load32(value, sptr, sbit, sbpv)\ 100 sample_load32_(value, sptr, sbit, sbpv);\ 101 sample_end_ 102 #define sample_load_next32(value, sptr, sbit, sbpv)\ 103 sample_load32(value, sptr, sbit, sbpv);\ 104 sample_next(sptr, sbit, sbpv) 105 #define sample_load64_(value, sptr, sbit, sbpv)\ 106 sample_load32_(value, sptr, sbit, sbpv);\ 107 case 10:\ 108 value = ((gx_color_index)((sptr)[0]) << sample_bound_shift((value), 32)) |\ 109 ((gx_color_index)((sptr)[1]) << 24) |\ 110 ((gx_color_index)((sptr)[2]) << 16) |\ 111 ((gx_color_index)((sptr)[3]) << 8) |\ 112 (gx_color_index)((sptr)[4]);\ 113 break;\ 114 case 12:\ 115 value = ((gx_color_index)((sptr)[0]) << sample_bound_shift((value), 40)) |\ 116 ((gx_color_index)((sptr)[1]) << sample_bound_shift((value), 32)) |\ 117 ((gx_color_index)((sptr)[2]) << 24) |\ 118 ((gx_color_index)((sptr)[3]) << 16) |\ 119 ((gx_color_index)((sptr)[4]) << 8) |\ 120 (gx_color_index)((sptr)[5]);\ 121 break;\ 122 case 14:\ 123 value = ((gx_color_index)((sptr)[0]) << sample_bound_shift((value), 48)) |\ 124 ((gx_color_index)((sptr)[1]) << sample_bound_shift((value), 40)) |\ 125 ((gx_color_index)((sptr)[2]) << sample_bound_shift((value), 32)) |\ 126 ((gx_color_index)((sptr)[3]) << 24) |\ 127 ((gx_color_index)((sptr)[4]) << 16) |\ 128 ((gx_color_index)((sptr)[5]) << 8) |\ 129 (gx_color_index)((sptr)[6]);\ 130 break;\ 131 case 16:\ 132 value = ((gx_color_index)((sptr)[0]) << sample_bound_shift((value), 56)) |\ 133 ((gx_color_index)((sptr)[1]) << sample_bound_shift((value), 48)) |\ 134 ((gx_color_index)((sptr)[2]) << sample_bound_shift((value), 40)) |\ 135 ((gx_color_index)((sptr)[3]) << sample_bound_shift((value), 32)) |\ 136 ((gx_color_index)((sptr)[4]) << 24) |\ 137 ((gx_color_index)((sptr)[5]) << 16) |\ 138 ((gx_color_index)((sptr)[6]) << 8) |\ 139 (gx_color_index)((sptr)[7]);\ 140 break; 141 #define sample_load64(value, sptr, sbit, sbpv)\ 142 sample_load64_(value, sptr, sbit, sbpv);\ 143 sample_end_ 144 #define sample_load_next64(value, sptr, sbit, sbpv)\ 145 sample_load64(value, sptr, sbit, sbpv);\ 146 sample_next(sptr, sbit, sbpv) 147 #define sample_load_any(value, sptr, sbit, sbpv)\ 148 if (sizeof(value) > 4)\ 149 sample_load64(value, sptr, sbit, sbpv);\ 150 else\ 151 sample_load32(value, sptr, sbit, sbpv) 152 #define sample_load_next_any(value, sptr, sbit, sbpv)\ 153 sample_load_any(value, sptr, sbit, sbpv);\ 154 sample_next(sptr, sbit, sbpv) 155 156 /* Declare variables for storing. */ 157 #define sample_store_declare(dptr, dbit, dbbyte)\ 158 byte *dptr;\ 159 int dbit;\ 160 byte dbbyte /* maybe should be uint? */ 161 #define sample_store_declare_setup(dptr, dbit, dbbyte, ptr, bitno, dbpv)\ 162 byte *dptr = (ptr);\ 163 int sample_store_setup(dbit, bitno, dbpv);\ 164 byte /* maybe should be uint? */\ 165 sample_store_preload(dbbyte, dptr, dbit, dbpv) 166 167 /* Set up to store starting at a given bit number. */ 168 #define sample_store_setup(dbit, bitno, dbpv)\ 169 dbit = (bitno) 170 171 /* Prepare for storing by preloading any partial byte. */ 172 #define sample_store_preload(dbbyte, dptr, dbit, dbpv)\ 173 dbbyte = ((dbit) ? (byte)(*(dptr) & (0xff00 >> (dbit))) : 0) 174 175 /* Store a value and increment the pointer. */ 176 #define sample_store_next8_(value, dptr, dbit, dbpv, dbbyte)\ 177 BEGIN\ 178 switch ( (dbpv) >> 2 ) {\ 179 case 0:\ 180 if ( (dbit += (dbpv)) == 8 )\ 181 *(dptr)++ = dbbyte | (byte)(value), dbbyte = 0, dbit = 0;\ 182 else dbbyte |= (byte)((value) << (8 - dbit));\ 183 break;\ 184 case 1:\ 185 if ( dbit ^= 4 ) dbbyte = (byte)((value) << 4);\ 186 else *(dptr)++ = dbbyte | ((byte)(value));\ 187 break;\ 188 /* case 2 is deliberately omitted */ 189 #define sample_store_next8(value, dptr, dbit, dbpv, dbbyte)\ 190 sample_store_next8_(value, dptr, dbit, dbpv, dbbyte)\ 191 case 2: *(dptr)++ = (byte)(value); break;\ 192 sample_end_ 193 #define sample_store_next_12_(value, dptr, dbit, dbbyte)\ 194 if ( dbit ^= 4 ) *(dptr)++ = (byte)((value) >> 4), dbbyte = (byte)((value) << 4);\ 195 else\ 196 *(dptr) = dbbyte | (byte)((value) >> 8), (dptr)[1] = (byte)(value), dptr += 2; 197 #define sample_store_next_12(value, dptr, dbit, dbbyte)\ 198 BEGIN sample_store_next_12_(value, dptr, dbit, dbbyte) END 199 #define sample_store_next12_(value, dptr, dbit, dbpv, dbbyte)\ 200 sample_store_next8_(value, dptr, dbit, dbpv, dbbyte)\ 201 /* case 2 is deliberately omitted */\ 202 case 3: sample_store_next_12_(value, dptr, dbit, dbbyte) break; 203 #define sample_store_next12(value, dptr, dbit, dbpv, dbbyte)\ 204 sample_store_next12_(value, dptr, dbit, dbpv, dbbyte)\ 205 case 2: *(dptr)++ = (byte)(value); break;\ 206 sample_end_ 207 #define sample_store_next16(value, dptr, dbit, dbpv, dbbyte)\ 208 sample_store_next12_(value, dptr, dbit, dbpv, dbbyte)\ 209 case 4: *(dptr)++ = (byte)((value) >> 8);\ 210 case 2: *(dptr)++ = (byte)(value); break;\ 211 sample_end_ 212 #define sample_store_next32(value, dptr, dbit, dbpv, dbbyte)\ 213 sample_store_next12_(value, dptr, dbit, dbpv, dbbyte)\ 214 case 8: *(dptr)++ = (byte)((value) >> 24);\ 215 case 6: *(dptr)++ = (byte)((value) >> 16);\ 216 case 4: *(dptr)++ = (byte)((value) >> 8);\ 217 case 2: *(dptr)++ = (byte)(value); break;\ 218 sample_end_ 219 #define sample_store_next64(value, dptr, dbit, dbpv, dbbyte)\ 220 sample_store_next12_(value, dptr, dbit, dbpv, dbbyte)\ 221 case 16: *(dptr)++ = (byte)((value) >> sample_bound_shift((value), 56));\ 222 case 14: *(dptr)++ = (byte)((value) >> sample_bound_shift((value), 48));\ 223 case 12: *(dptr)++ = (byte)((value) >> sample_bound_shift((value), 40));\ 224 case 10: *(dptr)++ = (byte)((value) >> sample_bound_shift((value), 32));\ 225 case 8: *(dptr)++ = (byte)((value) >> 24);\ 226 case 6: *(dptr)++ = (byte)((value) >> 16);\ 227 case 4: *(dptr)++ = (byte)((value) >> 8);\ 228 case 2: *(dptr)++ = (byte)(value); break;\ 229 sample_end_ 230 #define sample_store_next_any(value, dptr, dbit, dbpv, dbbyte)\ 231 if (sizeof(value) > 4)\ 232 sample_store_next64(value, dptr, dbit, dbpv, dbbyte);\ 233 else\ 234 sample_store_next32(value, dptr, dbit, dbpv, dbbyte) 235 236 /* Skip over storing one sample. This may or may not store into the */ 237 /* skipped region. */ 238 #define sample_store_skip_next(dptr, dbit, dbpv, dbbyte)\ 239 if ( (dbpv) < 8 ) {\ 240 sample_store_flush(dptr, dbit, dbpv, dbbyte);\ 241 sample_next(dptr, dbit, dbpv);\ 242 } else dptr += ((dbpv) >> 3) 243 244 /* Finish storing by flushing any partial byte. */ 245 #define sample_store_flush(dptr, dbit, dbpv, dbbyte)\ 246 if ( (dbit) != 0 )\ 247 *(dptr) = dbbyte | (*(dptr) & (0xff >> (dbit))); 248 249 /* Increment a pointer to the next sample. */ 250 #define sample_next(ptr, bit, bpv)\ 251 BEGIN bit += (bpv); ptr += bit >> 3; bit &= 7; END 252 253 /* ---------------- Definitions ---------------- */ 254 255 /* 256 * Define the chunk size for monobit filling operations. 257 * This is always uint, regardless of byte order. 258 */ 259 #define mono_fill_chunk uint 260 #define mono_fill_chunk_bytes arch_sizeof_int 261 262 /* ---------------- Procedures ---------------- */ 263 264 /* Fill a rectangle of bits with an 8x1 pattern. */ 265 /* The pattern argument must consist of the pattern in every byte, */ 266 /* e.g., if the desired pattern is 0xaa, the pattern argument must */ 267 /* have the value 0xaaaa (if ints are short) or 0xaaaaaaaa. */ 268 #if mono_fill_chunk_bytes == 2 269 # define mono_fill_make_pattern(byt) (uint)((uint)(byt) * 0x0101) 270 #else 271 # define mono_fill_make_pattern(byt) (uint)((uint)(byt) * 0x01010101) 272 #endif 273 void bits_fill_rectangle(byte * dest, int dest_bit, uint raster, 274 mono_fill_chunk pattern, int width_bits, int height); 275 void bits_fill_rectangle_masked(byte * dest, int dest_bit, uint raster, 276 mono_fill_chunk pattern, mono_fill_chunk src_mask, 277 int width_bits, int height); 278 279 /* Replicate a bitmap horizontally in place. */ 280 void bits_replicate_horizontally(byte * data, uint width, uint height, 281 uint raster, uint replicated_width, uint replicated_raster); 282 283 /* Replicate a bitmap vertically in place. */ 284 void bits_replicate_vertically(byte * data, uint height, uint raster, 285 uint replicated_height); 286 287 /* Find the bounding box of a bitmap. */ 288 void bits_bounding_box(const byte * data, uint height, uint raster, 289 gs_int_rect * pbox); 290 291 /* Compress an oversampled image, possibly in place. */ 292 /* The width and height must be multiples of the respective scale factors. */ 293 /* The source must be an aligned bitmap, as usual. */ 294 void bits_compress_scaled(const byte * src, int srcx, uint width, 295 uint height, uint sraster, byte * dest, uint draster, 296 const gs_log2_scale_point * plog2_scale, int log2_out_bits); 297 298 /* Extract a plane from a pixmap. */ 299 typedef struct bits_plane_s { 300 union bpd_ { /* Bit planes must be aligned. */ 301 byte *write; 302 const byte *read; 303 } data; 304 int raster; 305 int depth; 306 int x; /* starting x */ 307 } bits_plane_t; 308 int bits_extract_plane(const bits_plane_t *dest /*write*/, 309 const bits_plane_t *source /*read*/, int shift, int width, int height); 310 311 /* Expand a plane into a pixmap. */ 312 int bits_expand_plane(const bits_plane_t *dest /*write*/, 313 const bits_plane_t *source /*read*/, int shift, int width, int height); 314 315 /* Fill a rectangle of bytes. */ 316 void bytes_fill_rectangle(byte * dest, uint raster, 317 byte value, int width_bytes, int height); 318 319 /* Copy a rectangle of bytes. */ 320 void bytes_copy_rectangle(byte * dest, uint dest_raster, 321 const byte * src, uint src_raster, int width_bytes, int height); 322 323 #endif /* gsbitops_INCLUDED */ 324