1 /* Copyright (C) 1991, 1995, 1997, 1998, 1999 artofcode LLC.  All rights reserved.
2 
3   This program is free software; you can redistribute it and/or modify it
4   under the terms of the GNU General Public License as published by the
5   Free Software Foundation; either version 2 of the License, or (at your
6   option) any later version.
7 
8   This program is distributed in the hope that it will be useful, but
9   WITHOUT ANY WARRANTY; without even the implied warranty of
10   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11   General Public License for more details.
12 
13   You should have received a copy of the GNU General Public License along
14   with this program; if not, write to the Free Software Foundation, Inc.,
15   59 Temple Place, Suite 330, Boston, MA, 02111-1307.
16 
17 */
18 
19 /*$Id: gsbitops.h,v 1.2.6.1.2.1 2003/01/17 00:49:02 giles Exp $ */
20 /* Interface for bitmap operations */
21 
22 #ifndef gsbitops_INCLUDED
23 #  define gsbitops_INCLUDED
24 
25 /* ---------------- Pixel processing macros ---------------- */
26 
27 /*
28  * These macros support code that processes data pixel-by-pixel (or, to be
29  * more accurate, packed arrays of values -- they may be complete pixels
30  * or individual components of pixels).
31  *
32  * Supported #s of bits per value (bpv) are 1, 2, 4, 8, 12, 16, 24, 32.
33  * The suffix 8, 12, 16, or 32 on a macro name indicates the maximum value
34  * of bpv that the macro is prepared to handle.
35  *
36  * The setup macros number bits within a byte in big-endian order, i.e.,
37  * 0x80 is bit 0, 0x01 is bit 7.  However, sbit/dbit may use a different
38  * representation for better performance.  ****** NYI ******
39  */
40 
41 #define sample_end_\
42   default: return_error(gs_error_rangecheck);\
43   } END
44 
45 /* Declare variables for loading. */
46 #define sample_load_declare(sptr, sbit)\
47   const byte *sptr;\
48   int sbit
49 #define sample_load_declare_setup(sptr, sbit, ptr, bitno, sbpv)\
50   const byte *sptr = (ptr);\
51   int sample_load_setup(sbit, bitno, sbpv)
52 
53 /* Set up to load starting at a given bit number. */
54 #define sample_load_setup(sbit, bitno, sbpv)\
55   sbit = (bitno)
56 
57 /* Load a value from memory, without incrementing. */
58 #define sample_load8_(value, sptr, sbit, sbpv)\
59   BEGIN\
60   switch ( (sbpv) >> 2 ) {\
61   case 0: value = (*(sptr) >> (8 - (sbit) - (sbpv))) & ((sbpv) | 1); break;\
62   case 1: value = (*(sptr) >> (4 - (sbit))) & 0xf; break;\
63   case 2: value = *(sptr); break;
64 #define sample_load8(value, sptr, sbit, sbpv)\
65   sample_load8_(value, sptr, sbit, sbpv)\
66   sample_end_
67 #define sample_load_next8(value, sptr, sbit, sbpv)\
68   sample_load8(value, sptr, sbit, sbpv);\
69   sample_next(sptr, sbit, sbpv)
70 #define sample_load12_(value, sptr, sbit, sbpv)\
71   sample_load8_(value, sptr, sbit, sbpv)\
72   case 3:\
73     value = ((sbit) ? ((*(sptr) & 0xf) << 8) | (sptr)[1] :\
74 	      (*(sptr) << 4) | ((sptr)[1] >> 4));\
75     break;
76 #define sample_load12(value, sptr, sbit, sbpv)\
77   sample_load12_(value, sptr, sbit, sbpv)\
78   sample_end_
79 #define sample_load_next12(value, sptr, sbit, sbpv)\
80   sample_load12(value, sptr, sbit, sbpv);\
81   sample_next(sptr, sbit, sbpv)
82 #define sample_load16_(value, sptr, sbit, sbpv)\
83   sample_load12_(value, sptr, sbit, sbpv)\
84   case 4: value = (*(sptr) << 8) | (sptr)[1]; break;
85 #define sample_load16(value, sptr, sbit, sbpv)\
86   sample_load16_(value, sptr, sbit, sbpv)\
87   sample_end_
88 #define sample_load_next16(value, sptr, sbit, sbpv)\
89   sample_load16(value, sptr, sbit, sbpv);\
90   sample_next(sptr, sbit, sbpv)
91 #define sample_load32(value, sptr, sbit, sbpv)\
92   sample_load16_(value, sptr, sbit, sbpv)\
93   case 6: value = (*(sptr) << 16) | ((sptr)[1] << 8) | (sptr)[2]; break;\
94   case 8:\
95     value = (*(sptr) << 24) | ((sptr)[1] << 16) | ((sptr)[2] << 8) | sptr[3];\
96     break;\
97   sample_end_
98 #define sample_load_next32(value, sptr, sbit, sbpv)\
99   sample_load32(value, sptr, sbit, sbpv);\
100   sample_next(sptr, sbit, sbpv)
101 
102 /* Declare variables for storing. */
103 #define sample_store_declare(dptr, dbit, dbbyte)\
104   byte *dptr;\
105   int dbit;\
106   byte dbbyte			/* maybe should be uint? */
107 #define sample_store_declare_setup(dptr, dbit, dbbyte, ptr, bitno, dbpv)\
108   byte *dptr = (ptr);\
109   int sample_store_setup(dbit, bitno, dbpv);\
110   byte /* maybe should be uint? */\
111     sample_store_preload(dbbyte, dptr, dbit, dbpv)
112 
113 /* Set up to store starting at a given bit number. */
114 #define sample_store_setup(dbit, bitno, dbpv)\
115   dbit = (bitno)
116 
117 /* Prepare for storing by preloading any partial byte. */
118 #define sample_store_preload(dbbyte, dptr, dbit, dbpv)\
119   dbbyte = ((dbit) ? (byte)(*(dptr) & (0xff00 >> (dbit))) : 0)
120 
121 /* Store a value and increment the pointer. */
122 #define sample_store_next8_(value, dptr, dbit, dbpv, dbbyte)\
123   BEGIN\
124   switch ( (dbpv) >> 2 ) {\
125   case 0:\
126     if ( (dbit += (dbpv)) == 8 )\
127        *(dptr)++ = dbbyte | (value), dbbyte = 0, dbit = 0;\
128     else dbbyte |= (value) << (8 - dbit);\
129     break;\
130   case 1:\
131     if ( dbit ^= 4 ) dbbyte = (byte)((value) << 4);\
132     else *(dptr)++ = dbbyte | (value);\
133     break;\
134   /* case 2 is deliberately omitted */
135 #define sample_store_next8(value, dptr, dbit, dbpv, dbbyte)\
136   sample_store_next8_(value, dptr, dbit, dbpv, dbbyte)\
137   case 2: *(dptr)++ = (byte)(value); break;\
138   sample_end_
139 #define sample_store_next_12_(value, dptr, dbit, dbbyte)\
140     if ( dbit ^= 4 ) *(dptr)++ = (value) >> 4, dbbyte = (byte)((value) << 4);\
141     else\
142       *(dptr) = dbbyte | ((value) >> 8), (dptr)[1] = (byte)(value), dptr += 2;
143 #define sample_store_next_12(value, dptr, dbit, dbbyte)\
144   BEGIN sample_store_next_12_(value, dptr, dbit, dbbyte) END
145 #define sample_store_next12_(value, dptr, dbit, dbpv, dbbyte)\
146   sample_store_next8_(value, dptr, dbit, dbpv, dbbyte)\
147   /* case 2 is deliberately omitted */\
148   case 3: sample_store_next_12_(value, dptr, dbit, dbbyte) break;
149 #define sample_store_next12(value, dptr, dbit, dbpv, dbbyte)\
150   sample_store_next12_(value, dptr, dbit, dbpv, dbbyte)\
151   case 2: *(dptr)++ = (byte)(value); break;\
152   sample_end_
153 #define sample_store_next16(value, dptr, dbit, dbpv, dbbyte)\
154   sample_store_next12_(value, dptr, dbit, dbpv, dbbyte)\
155   case 4: *(dptr)++ = (byte)((value) >> 8);\
156   case 2: *(dptr)++ = (byte)(value); break;\
157   sample_end_
158 #define sample_store_next32(value, dptr, dbit, dbpv, dbbyte)\
159   sample_store_next12_(value, dptr, dbit, dbpv, dbbyte)\
160   case 8: *(dptr)++ = (byte)((value) >> 24);\
161   case 6: *(dptr)++ = (byte)((value) >> 16);\
162   case 4: *(dptr)++ = (byte)((value) >> 8);\
163   case 2: *(dptr)++ = (byte)(value); break;\
164   sample_end_
165 
166 /* Skip over storing one sample.  This may or may not store into the */
167 /* skipped region. */
168 #define sample_store_skip_next(dptr, dbit, dbpv, dbbyte)\
169   if ( (dbpv) < 8 ) {\
170     sample_store_flush(dptr, dbit, dbpv, dbbyte);\
171     sample_next(dptr, dbit, dbpv);\
172   } else dptr += ((dbpv) >> 3)
173 
174 /* Finish storing by flushing any partial byte. */
175 #define sample_store_flush(dptr, dbit, dbpv, dbbyte)\
176   if ( (dbit) != 0 )\
177     *(dptr) = dbbyte | (*(dptr) & (0xff >> (dbit)));
178 
179 /* Increment a pointer to the next sample. */
180 #define sample_next(ptr, bit, bpv)\
181   BEGIN bit += (bpv); ptr += bit >> 3; bit &= 7; END
182 
183 /* ---------------- Definitions ---------------- */
184 
185 /*
186  * Define the chunk size for monobit filling operations.
187  * This is always uint, regardless of byte order.
188  */
189 #define mono_fill_chunk uint
190 #define mono_fill_chunk_bytes arch_sizeof_int
191 
192 /* ---------------- Procedures ---------------- */
193 
194 /* Fill a rectangle of bits with an 8x1 pattern. */
195 /* The pattern argument must consist of the pattern in every byte, */
196 /* e.g., if the desired pattern is 0xaa, the pattern argument must */
197 /* have the value 0xaaaa (if ints are short) or 0xaaaaaaaa. */
198 #if mono_fill_chunk_bytes == 2
199 #  define mono_fill_make_pattern(byt) (uint)((uint)(byt) * 0x0101)
200 #else
201 #  define mono_fill_make_pattern(byt) (uint)((uint)(byt) * 0x01010101)
202 #endif
203 void bits_fill_rectangle(P6(byte * dest, int dest_bit, uint raster,
204 		      mono_fill_chunk pattern, int width_bits, int height));
205 
206 /* Replicate a bitmap horizontally in place. */
207 void bits_replicate_horizontally(P6(byte * data, uint width, uint height,
208 	       uint raster, uint replicated_width, uint replicated_raster));
209 
210 /* Replicate a bitmap vertically in place. */
211 void bits_replicate_vertically(P4(byte * data, uint height, uint raster,
212     uint replicated_height));
213 
214 /* Find the bounding box of a bitmap. */
215 void bits_bounding_box(P4(const byte * data, uint height, uint raster,
216     gs_int_rect * pbox));
217 
218 /* Compress an oversampled image, possibly in place. */
219 /* The width and height must be multiples of the respective scale factors. */
220 /* The source must be an aligned bitmap, as usual. */
221 void bits_compress_scaled(P9(const byte * src, int srcx, uint width,
222     uint height, uint sraster, byte * dest, uint draster,
223     const gs_log2_scale_point * plog2_scale, int log2_out_bits));
224 
225 /* Extract a plane from a pixmap. */
226 typedef struct bits_plane_s {
227     union bpd_ {	/* Bit planes must be aligned. */
228 	byte *write;
229 	const byte *read;
230     } data;
231     int raster;
232     int depth;
233     int x;			/* starting x */
234 } bits_plane_t;
235 int bits_extract_plane(P5(const bits_plane_t *dest /*write*/,
236     const bits_plane_t *source /*read*/, int shift, int width, int height));
237 
238 /* Expand a plane into a pixmap. */
239 int bits_expand_plane(P5(const bits_plane_t *dest /*write*/,
240     const bits_plane_t *source /*read*/, int shift, int width, int height));
241 
242 /* Fill a rectangle of bytes. */
243 void bytes_fill_rectangle(P5(byte * dest, uint raster,
244 			     byte value, int width_bytes, int height));
245 
246 /* Copy a rectangle of bytes. */
247 void bytes_copy_rectangle(P6(byte * dest, uint dest_raster,
248 	   const byte * src, uint src_raster, int width_bytes, int height));
249 
250 #endif /* gsbitops_INCLUDED */
251