summaryrefslogtreecommitdiff
path: root/gs/base/gsbitops.h
diff options
context:
space:
mode:
Diffstat (limited to 'gs/base/gsbitops.h')
-rw-r--r--gs/base/gsbitops.h320
1 files changed, 320 insertions, 0 deletions
diff --git a/gs/base/gsbitops.h b/gs/base/gsbitops.h
new file mode 100644
index 000000000..a13a28d76
--- /dev/null
+++ b/gs/base/gsbitops.h
@@ -0,0 +1,320 @@
+/* Copyright (C) 2001-2006 Artifex Software, Inc.
+ All Rights Reserved.
+
+ This software is provided AS-IS with no warranty, either express or
+ implied.
+
+ This software is distributed under license and may not be copied, modified
+ or distributed except as expressly authorized under the terms of that
+ license. Refer to licensing information at http://www.artifex.com/
+ or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134,
+ San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information.
+*/
+
+/* $Id$ */
+/* Interface for bitmap operations */
+
+#ifndef gsbitops_INCLUDED
+# define gsbitops_INCLUDED
+
+/* ---------------- Pixel processing macros ---------------- */
+
+/*
+ * These macros support code that processes data pixel-by-pixel (or, to be
+ * more accurate, packed arrays of values -- they may be complete pixels
+ * or individual components of pixels).
+ *
+ * Supported #s of bits per value (bpv) are 1, 2, 4, or n * 8, where n <= 8.
+ * The suffix 8, 12, 16, 32, or 64 on a macro name indicates the maximum
+ * value of bpv that the macro is prepared to handle.
+ *
+ * The setup macros number bits within a byte in big-endian order, i.e.,
+ * 0x80 is bit 0, 0x01 is bit 7. However, sbit/dbit may use a different
+ * representation for better performance. ****** NYI ******
+ */
+
+#define sample_end_\
+ default: return_error(gs_error_rangecheck);\
+ } END
+
+/* Declare variables for loading. */
+#define sample_load_declare(sptr, sbit)\
+ const byte *sptr;\
+ int sbit
+#define sample_load_declare_setup(sptr, sbit, ptr, bitno, sbpv)\
+ const byte *sptr = (ptr);\
+ int sample_load_setup(sbit, bitno, sbpv)
+
+/* Set up to load starting at a given bit number. */
+#define sample_load_setup(sbit, bitno, sbpv)\
+ sbit = (bitno)
+
+/* macro to eliminate compiler warning message */
+#define sample_bound_shift(value, shift)\
+ ((shift) >= 8 * sizeof(value) ? (shift) & (8 * sizeof(value) - 1) : (shift))
+
+/* Load a value from memory, without incrementing. */
+#define sample_load8_(value, sptr, sbit, sbpv)\
+ BEGIN\
+ switch ( (sbpv) >> 2 ) {\
+ case 0: value = (*(sptr) >> (8 - (sbit) - (sbpv))) & ((sbpv) | 1); break;\
+ case 1: value = (*(sptr) >> (4 - (sbit))) & 0xf; break;\
+ case 2: value = *(sptr); break;
+#define sample_load8(value, sptr, sbit, sbpv)\
+ sample_load8_(value, sptr, sbit, sbpv)\
+ sample_end_
+#define sample_load_next8(value, sptr, sbit, sbpv)\
+ sample_load8(value, sptr, sbit, sbpv);\
+ sample_next(sptr, sbit, sbpv)
+#define sample_load12_(value, sptr, sbit, sbpv)\
+ sample_load8_(value, sptr, sbit, sbpv)\
+ case 3:\
+ value = ((sbit) ? ((*(sptr) & 0xf) << 8) | (sptr)[1] :\
+ (*(sptr) << 4) | ((sptr)[1] >> 4));\
+ break;
+#define sample_load12(value, sptr, sbit, sbpv)\
+ sample_load12_(value, sptr, sbit, sbpv)\
+ sample_end_
+#define sample_load_next12(value, sptr, sbit, sbpv)\
+ sample_load12(value, sptr, sbit, sbpv);\
+ sample_next(sptr, sbit, sbpv)
+#define sample_load16_(value, sptr, sbit, sbpv)\
+ sample_load12_(value, sptr, sbit, sbpv)\
+ case 4: value = (*(sptr) << 8) | (sptr)[1]; break;
+#define sample_load16(value, sptr, sbit, sbpv)\
+ sample_load16_(value, sptr, sbit, sbpv)\
+ sample_end_
+#define sample_load_next16(value, sptr, sbit, sbpv)\
+ sample_load16(value, sptr, sbit, sbpv);\
+ sample_next(sptr, sbit, sbpv)
+#define sample_load32_(value, sptr, sbit, sbpv)\
+ sample_load16_(value, sptr, sbit, sbpv)\
+ case 6: value = (*(sptr) << 16) | ((sptr)[1] << 8) | (sptr)[2]; break;\
+ case 8:\
+ value = (*(sptr) << 24) | ((sptr)[1] << 16) | ((sptr)[2] << 8) | sptr[3];\
+ break;
+#define sample_load32(value, sptr, sbit, sbpv)\
+ sample_load32_(value, sptr, sbit, sbpv);\
+ sample_end_
+#define sample_load_next32(value, sptr, sbit, sbpv)\
+ sample_load32(value, sptr, sbit, sbpv);\
+ sample_next(sptr, sbit, sbpv)
+#define sample_load64_(value, sptr, sbit, sbpv)\
+ sample_load32_(value, sptr, sbit, sbpv);\
+ case 10:\
+ value = ((gx_color_index)((sptr)[0]) << sample_bound_shift((value), 32)) |\
+ ((gx_color_index)((sptr)[1]) << 24) |\
+ ((gx_color_index)((sptr)[2]) << 16) |\
+ ((gx_color_index)((sptr)[3]) << 8) |\
+ (gx_color_index)((sptr)[4]);\
+ break;\
+ case 12:\
+ value = ((gx_color_index)((sptr)[0]) << sample_bound_shift((value), 40)) |\
+ ((gx_color_index)((sptr)[1]) << sample_bound_shift((value), 32)) |\
+ ((gx_color_index)((sptr)[2]) << 24) |\
+ ((gx_color_index)((sptr)[3]) << 16) |\
+ ((gx_color_index)((sptr)[4]) << 8) |\
+ (gx_color_index)((sptr)[5]);\
+ break;\
+ case 14:\
+ value = ((gx_color_index)((sptr)[0]) << sample_bound_shift((value), 48)) |\
+ ((gx_color_index)((sptr)[1]) << sample_bound_shift((value), 40)) |\
+ ((gx_color_index)((sptr)[2]) << sample_bound_shift((value), 32)) |\
+ ((gx_color_index)((sptr)[3]) << 24) |\
+ ((gx_color_index)((sptr)[4]) << 16) |\
+ ((gx_color_index)((sptr)[5]) << 8) |\
+ (gx_color_index)((sptr)[6]);\
+ break;\
+ case 16:\
+ value = ((gx_color_index)((sptr)[0]) << sample_bound_shift((value), 56)) |\
+ ((gx_color_index)((sptr)[1]) << sample_bound_shift((value), 48)) |\
+ ((gx_color_index)((sptr)[2]) << sample_bound_shift((value), 40)) |\
+ ((gx_color_index)((sptr)[3]) << sample_bound_shift((value), 32)) |\
+ ((gx_color_index)((sptr)[4]) << 24) |\
+ ((gx_color_index)((sptr)[5]) << 16) |\
+ ((gx_color_index)((sptr)[6]) << 8) |\
+ (gx_color_index)((sptr)[7]);\
+ break;
+#define sample_load64(value, sptr, sbit, sbpv)\
+ sample_load64_(value, sptr, sbit, sbpv);\
+ sample_end_
+#define sample_load_next64(value, sptr, sbit, sbpv)\
+ sample_load64(value, sptr, sbit, sbpv);\
+ sample_next(sptr, sbit, sbpv)
+#define sample_load_any(value, sptr, sbit, sbpv)\
+ if (sizeof(value) > 4)\
+ sample_load64(value, sptr, sbit, sbpv);\
+ else\
+ sample_load32(value, sptr, sbit, sbpv)
+#define sample_load_next_any(value, sptr, sbit, sbpv)\
+ sample_load_any(value, sptr, sbit, sbpv);\
+ sample_next(sptr, sbit, sbpv)
+
+/* Declare variables for storing. */
+#define sample_store_declare(dptr, dbit, dbbyte)\
+ byte *dptr;\
+ int dbit;\
+ byte dbbyte /* maybe should be uint? */
+#define sample_store_declare_setup(dptr, dbit, dbbyte, ptr, bitno, dbpv)\
+ byte *dptr = (ptr);\
+ int sample_store_setup(dbit, bitno, dbpv);\
+ byte /* maybe should be uint? */\
+ sample_store_preload(dbbyte, dptr, dbit, dbpv)
+
+/* Set up to store starting at a given bit number. */
+#define sample_store_setup(dbit, bitno, dbpv)\
+ dbit = (bitno)
+
+/* Prepare for storing by preloading any partial byte. */
+#define sample_store_preload(dbbyte, dptr, dbit, dbpv)\
+ dbbyte = ((dbit) ? (byte)(*(dptr) & (0xff00 >> (dbit))) : 0)
+
+/* Store a value and increment the pointer. */
+#define sample_store_next8_(value, dptr, dbit, dbpv, dbbyte)\
+ BEGIN\
+ switch ( (dbpv) >> 2 ) {\
+ case 0:\
+ if ( (dbit += (dbpv)) == 8 )\
+ *(dptr)++ = dbbyte | (byte)(value), dbbyte = 0, dbit = 0;\
+ else dbbyte |= (byte)((value) << (8 - dbit));\
+ break;\
+ case 1:\
+ if ( dbit ^= 4 ) dbbyte = (byte)((value) << 4);\
+ else *(dptr)++ = dbbyte | ((byte)(value));\
+ break;\
+ /* case 2 is deliberately omitted */
+#define sample_store_next8(value, dptr, dbit, dbpv, dbbyte)\
+ sample_store_next8_(value, dptr, dbit, dbpv, dbbyte)\
+ case 2: *(dptr)++ = (byte)(value); break;\
+ sample_end_
+#define sample_store_next_12_(value, dptr, dbit, dbbyte)\
+ if ( dbit ^= 4 ) *(dptr)++ = (byte)((value) >> 4), dbbyte = (byte)((value) << 4);\
+ else\
+ *(dptr) = dbbyte | (byte)((value) >> 8), (dptr)[1] = (byte)(value), dptr += 2;
+#define sample_store_next_12(value, dptr, dbit, dbbyte)\
+ BEGIN sample_store_next_12_(value, dptr, dbit, dbbyte) END
+#define sample_store_next12_(value, dptr, dbit, dbpv, dbbyte)\
+ sample_store_next8_(value, dptr, dbit, dbpv, dbbyte)\
+ /* case 2 is deliberately omitted */\
+ case 3: sample_store_next_12_(value, dptr, dbit, dbbyte) break;
+#define sample_store_next12(value, dptr, dbit, dbpv, dbbyte)\
+ sample_store_next12_(value, dptr, dbit, dbpv, dbbyte)\
+ case 2: *(dptr)++ = (byte)(value); break;\
+ sample_end_
+#define sample_store_next16(value, dptr, dbit, dbpv, dbbyte)\
+ sample_store_next12_(value, dptr, dbit, dbpv, dbbyte)\
+ case 4: *(dptr)++ = (byte)((value) >> 8);\
+ case 2: *(dptr)++ = (byte)(value); break;\
+ sample_end_
+#define sample_store_next32(value, dptr, dbit, dbpv, dbbyte)\
+ sample_store_next12_(value, dptr, dbit, dbpv, dbbyte)\
+ case 8: *(dptr)++ = (byte)((value) >> 24);\
+ case 6: *(dptr)++ = (byte)((value) >> 16);\
+ case 4: *(dptr)++ = (byte)((value) >> 8);\
+ case 2: *(dptr)++ = (byte)(value); break;\
+ sample_end_
+#define sample_store_next64(value, dptr, dbit, dbpv, dbbyte)\
+ sample_store_next12_(value, dptr, dbit, dbpv, dbbyte)\
+ case 16: *(dptr)++ = (byte)((value) >> sample_bound_shift((value), 56));\
+ case 14: *(dptr)++ = (byte)((value) >> sample_bound_shift((value), 48));\
+ case 12: *(dptr)++ = (byte)((value) >> sample_bound_shift((value), 40));\
+ case 10: *(dptr)++ = (byte)((value) >> sample_bound_shift((value), 32));\
+ case 8: *(dptr)++ = (byte)((value) >> 24);\
+ case 6: *(dptr)++ = (byte)((value) >> 16);\
+ case 4: *(dptr)++ = (byte)((value) >> 8);\
+ case 2: *(dptr)++ = (byte)(value); break;\
+ sample_end_
+#define sample_store_next_any(value, dptr, dbit, dbpv, dbbyte)\
+ if (sizeof(value) > 4)\
+ sample_store_next64(value, dptr, dbit, dbpv, dbbyte);\
+ else\
+ sample_store_next32(value, dptr, dbit, dbpv, dbbyte)
+
+/* Skip over storing one sample. This may or may not store into the */
+/* skipped region. */
+#define sample_store_skip_next(dptr, dbit, dbpv, dbbyte)\
+ if ( (dbpv) < 8 ) {\
+ sample_store_flush(dptr, dbit, dbpv, dbbyte);\
+ sample_next(dptr, dbit, dbpv);\
+ } else dptr += ((dbpv) >> 3)
+
+/* Finish storing by flushing any partial byte. */
+#define sample_store_flush(dptr, dbit, dbpv, dbbyte)\
+ if ( (dbit) != 0 )\
+ *(dptr) = dbbyte | (*(dptr) & (0xff >> (dbit)));
+
+/* Increment a pointer to the next sample. */
+#define sample_next(ptr, bit, bpv)\
+ BEGIN bit += (bpv); ptr += bit >> 3; bit &= 7; END
+
+/* ---------------- Definitions ---------------- */
+
+/*
+ * Define the chunk size for monobit filling operations.
+ * This is always uint, regardless of byte order.
+ */
+#define mono_fill_chunk uint
+#define mono_fill_chunk_bytes arch_sizeof_int
+
+/* ---------------- Procedures ---------------- */
+
+/* Fill a rectangle of bits with an 8x1 pattern. */
+/* The pattern argument must consist of the pattern in every byte, */
+/* e.g., if the desired pattern is 0xaa, the pattern argument must */
+/* have the value 0xaaaa (if ints are short) or 0xaaaaaaaa. */
+#if mono_fill_chunk_bytes == 2
+# define mono_fill_make_pattern(byt) (uint)((uint)(byt) * 0x0101)
+#else
+# define mono_fill_make_pattern(byt) (uint)((uint)(byt) * 0x01010101)
+#endif
+void bits_fill_rectangle(byte * dest, int dest_bit, uint raster,
+ mono_fill_chunk pattern, int width_bits, int height);
+void bits_fill_rectangle_masked(byte * dest, int dest_bit, uint raster,
+ mono_fill_chunk pattern, mono_fill_chunk src_mask,
+ int width_bits, int height);
+
+/* Replicate a bitmap horizontally in place. */
+void bits_replicate_horizontally(byte * data, uint width, uint height,
+ uint raster, uint replicated_width, uint replicated_raster);
+
+/* Replicate a bitmap vertically in place. */
+void bits_replicate_vertically(byte * data, uint height, uint raster,
+ uint replicated_height);
+
+/* Find the bounding box of a bitmap. */
+void bits_bounding_box(const byte * data, uint height, uint raster,
+ gs_int_rect * pbox);
+
+/* Compress an oversampled image, possibly in place. */
+/* The width and height must be multiples of the respective scale factors. */
+/* The source must be an aligned bitmap, as usual. */
+void bits_compress_scaled(const byte * src, int srcx, uint width,
+ uint height, uint sraster, byte * dest, uint draster,
+ const gs_log2_scale_point * plog2_scale, int log2_out_bits);
+
+/* Extract a plane from a pixmap. */
+typedef struct bits_plane_s {
+ union bpd_ { /* Bit planes must be aligned. */
+ byte *write;
+ const byte *read;
+ } data;
+ int raster;
+ int depth;
+ int x; /* starting x */
+} bits_plane_t;
+int bits_extract_plane(const bits_plane_t *dest /*write*/,
+ const bits_plane_t *source /*read*/, int shift, int width, int height);
+
+/* Expand a plane into a pixmap. */
+int bits_expand_plane(const bits_plane_t *dest /*write*/,
+ const bits_plane_t *source /*read*/, int shift, int width, int height);
+
+/* Fill a rectangle of bytes. */
+void bytes_fill_rectangle(byte * dest, uint raster,
+ byte value, int width_bytes, int height);
+
+/* Copy a rectangle of bytes. */
+void bytes_copy_rectangle(byte * dest, uint dest_raster,
+ const byte * src, uint src_raster, int width_bytes, int height);
+
+#endif /* gsbitops_INCLUDED */