Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'bundles/org.eclipse.equinox.executable/library/motif/NgImageData.c')
-rw-r--r--bundles/org.eclipse.equinox.executable/library/motif/NgImageData.c490
1 files changed, 490 insertions, 0 deletions
diff --git a/bundles/org.eclipse.equinox.executable/library/motif/NgImageData.c b/bundles/org.eclipse.equinox.executable/library/motif/NgImageData.c
new file mode 100644
index 000000000..d19f1dc22
--- /dev/null
+++ b/bundles/org.eclipse.equinox.executable/library/motif/NgImageData.c
@@ -0,0 +1,490 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+#include "NgImageData.h"
+
+static UBYTE4 RoundRow (UBYTE4 width)
+{
+ UBYTE4 result = (width + RowRounding - 1)
+ & ~(RowRounding - 1) ;
+ return result ;
+}
+
+void NgBitmapImageInit (ng_bitmap_image_t *image)
+{
+ NgBitmapImageClearData (image);
+}
+
+void NgBitmapImageFree (ng_bitmap_image_t *image)
+{
+ NgFree (image->color_map);
+ NgFree (image->image_data);
+ NgFree (image->alpha_data);
+}
+
+void NgBitmapImageClearData (ng_bitmap_image_t *image)
+{
+ image->bit_count = 0;
+ image->image_width = 0;
+ image->image_height = 0;
+ image->color_count = 0;
+ image->color_map = NULL;
+ image->image_data = NULL;
+ image->alpha_data = NULL;
+ image->transparent_pixel = -1;
+}
+
+void NgBitmapImageSetSize(ng_bitmap_image_t *image,
+ UBYTE4 color_count,
+ UBYTE4 bits,
+ UBYTE4 width,
+ UBYTE4 height)
+{
+ NgFree (image->color_map);
+ NgFree (image->image_data);
+ NgBitmapImageClearData (image);
+
+ switch (bits)
+ {
+ case 1:
+ case 2:
+ case 4:
+ case 8:
+ {
+ UBYTE4 bitsize;
+ UBYTE4 bytecount;
+
+ image->bit_count = bits;
+ image->color_count = color_count;
+ image->image_width = width;
+ image->image_height = height;
+
+ image->color_map = (ng_color_map_entry_t *) NgMalloc (sizeof(ng_color_map_entry_t) * image->color_count);
+ NgMemSet (image->color_map, 0, sizeof (ng_color_map_entry_t) * image->color_count);
+ bitsize = image->bit_count * image->image_width;
+ image->row_width = RoundRow ((bitsize + 7)/8);
+ bytecount = image->row_width * image->image_height;
+ image->image_data = (UBYTE1 *) NgMalloc (bytecount);
+ NgMemSet (image->image_data, 0, (BYTE4)bytecount);
+ }
+ break ;
+ case 16:
+ {
+ image->bit_count = bits;
+ image->color_count = color_count;
+ image->image_width = width;
+ image->image_height = height;
+ image->row_width = RoundRow (2 * image->image_width);
+ image->image_data = (UBYTE1 *) NgMalloc (image->row_width * image->image_height);
+ NgMemSet (image->image_data, 0, image->row_width * image->image_height);
+ }
+ break;
+ case 24:
+ {
+ image->bit_count = bits;
+ image->color_count = color_count;
+ image->image_width = width;
+ image->image_height = height;
+ image->row_width = RoundRow (3 * image->image_width);
+ image->image_data = (UBYTE1 *) NgMalloc (image->row_width * image->image_height);
+ NgMemSet (image->image_data, 0, image->row_width * image->image_height);
+ }
+ break;
+ case 32:
+ {
+ image->bit_count = bits;
+ image->color_count = color_count;
+ image->image_width = width;
+ image->image_height = height;
+ image->row_width = RoundRow (4 * image->image_width);
+ image->image_data = (UBYTE1 *) NgMalloc (image->row_width * image->image_height);
+ NgMemSet (image->image_data, 0, image->row_width * image->image_height);
+ }
+ break ;
+ default:
+ NgError (ERR_INVALID_BIT_COUNT, NULL);
+ }
+}
+
+ng_color_map_entry_t *NgBitmapImageColorMap (ng_bitmap_image_t *image, UBYTE4 index)
+{
+ if (index >= image->color_count)
+ {
+ NgError (ERR_SUBSCRIPT_OUT_OF_RANGE, "Error NgBitmapImageColorMap failed");
+ return NULL;
+ }
+
+ return &image->color_map [index] ;
+}
+
+/* blit constants */
+#define TYPE_INDEX_1_MSB 1
+#define TYPE_INDEX_1_LSB 2
+#define TYPE_INDEX_2 3
+#define TYPE_INDEX_4 4
+#define TYPE_INDEX_8 5
+#define TYPE_GENERIC_24 6
+#define TYPE_GENERIC_8 7
+#define TYPE_GENERIC_16_MSB 8
+#define TYPE_GENERIC_16_LSB 9
+#define TYPE_GENERIC_32_MSB 10
+#define TYPE_GENERIC_32_LSB 11
+
+/**
+ * Computes the required channel shift from a mask.
+ */
+UBYTE4 getChannelShift(UBYTE4 mask)
+{
+ UBYTE4 i;
+ if (mask == 0) return 0;
+ for (i = 0; ((mask & 1) == 0) && (i < 32); ++i)
+ {
+ mask >>= 1;
+ }
+ return i;
+}
+
+/**
+ * Computes the required channel width (depth) from a mask.
+ */
+UBYTE4 getChannelWidth(UBYTE4 mask, UBYTE4 shift)
+{
+ UBYTE4 i;
+ if (mask == 0) return 0;
+ mask >>= shift;
+ for (i = shift; ((mask & 1) != 0) && (i < 32); ++i)
+ {
+ mask >>= 1;
+ }
+ return i - shift;
+}
+
+/**
+ * Blits a direct palette image into a direct palette image.
+ *
+ * srcData the source byte array containing image data
+ * srcStride the source number of bytes per line
+ * srcWidth the width of the source blit region
+ * srcHeight the height of the source blit region
+ * destData the destination byte array containing image data
+ * destDepth the destination depth: one of 8, 16, 24, 32
+ * destStride the destination number of bytes per line
+ * destOrder the destination byte ordering: 0 for LSB, 1 otherwise
+ * ignored if destDepth is not 16 or 32
+ * destRedMask the destination red channel mask
+ * destGreenMask the destination green channel mask
+ * destBlueMask the destination blue channel mask
+ *
+ * It is assumed that.
+ * srcDepth: 24 - BGR ordering (BMP format)
+ * no alpha
+ * srcX: 0
+ * srcY: 0
+ * destX: 0
+ * destY: 0
+ * destWidth: same as srcWidth
+ * destHeight: same as srcHeight
+ */
+void NgBitmapImageBlitDirectToDirect(
+ UBYTE1 *srcData, BYTE4 srcStride,
+ BYTE4 srcWidth, BYTE4 srcHeight,
+ UBYTE1 *destData, BYTE4 destDepth, BYTE4 destStride, BYTE4 destOrder,
+ UBYTE4 destRedMask, UBYTE4 destGreenMask, UBYTE4 destBlueMask)
+{
+ BYTE4 srcX = 0, srcY = 0, destX = 0, destY = 0, destWidth = srcWidth, destHeight = srcHeight;
+
+ BYTE4 sbpp, stype, spr, dbpp, dtype, dpr, dprxi, dpryi, dp, sp, dy, dx;
+ BYTE4 destRedShift, destRedWidth;
+ BYTE4 destRedPreShift, destGreenShift, destGreenWidth, destGreenPreShift;
+ BYTE4 destBlueShift, destBlueWidth, destBluePreShift;
+ UBYTE1 r, g, b;
+ UBYTE4 data;
+
+ /*** Prepare source-related data ***/
+ sbpp = 3;
+ stype = TYPE_GENERIC_24;
+
+ spr = srcY * srcStride + srcX * sbpp;
+
+ /*** Prepare destination-related data ***/
+ switch (destDepth)
+ {
+ case 8:
+ dbpp = 1;
+ dtype = TYPE_GENERIC_8;
+ break;
+ case 16:
+ dbpp = 2;
+ dtype = (destOrder != 0) ? TYPE_GENERIC_16_MSB : TYPE_GENERIC_16_LSB;
+ break;
+ case 24:
+ dbpp = 3;
+ dtype = TYPE_GENERIC_24;
+ break;
+ case 32:
+ dbpp = 4;
+ dtype = (destOrder != 0) ? TYPE_GENERIC_32_MSB : TYPE_GENERIC_32_LSB;
+ break;
+ default:
+ return;
+ }
+
+ dpr = destY * destStride + destX * dbpp;
+ dprxi = dbpp;
+ dpryi = destStride;
+
+ /*** Blit ***/
+ dp = dpr;
+ sp = spr;
+
+ /*** Comprehensive blit (apply transformations) ***/
+ destRedShift = getChannelShift(destRedMask);
+ destRedWidth = getChannelWidth(destRedMask, destRedShift);
+ destRedPreShift = 8 - destRedWidth;
+ destGreenShift = getChannelShift(destGreenMask);
+ destGreenWidth = getChannelWidth(destGreenMask, destGreenShift);
+ destGreenPreShift = 8 - destGreenWidth;
+ destBlueShift = getChannelShift(destBlueMask);
+ destBlueWidth = getChannelWidth(destBlueMask, destBlueShift);
+ destBluePreShift = 8 - destBlueWidth;
+
+ r = 0; g = 0; b = 0;
+ for (dy = destHeight; dy > 0; --dy, sp = spr += srcStride, dp = dpr += dpryi)
+ {
+ for (dx = destWidth; dx > 0; --dx, dp += dprxi)
+ {
+ /*** READ NEXT PIXEL ASSUMING BGR ordering (BMP format) ***/
+ b = srcData[sp];
+ g = srcData[sp + 1];
+ r = srcData[sp + 2];
+ sp += 3;
+ /*** WRITE NEXT PIXEL ***/
+ data =
+ (r >> destRedPreShift << destRedShift) |
+ (g >> destGreenPreShift << destGreenShift) |
+ (b >> destBluePreShift << destBlueShift);
+ switch (dtype)
+ {
+ case TYPE_GENERIC_8:
+ {
+ destData[dp] = (UBYTE1) data;
+ } break;
+ case TYPE_GENERIC_16_MSB:
+ {
+ destData[dp] = (UBYTE1) (data >> 8);
+ destData[dp + 1] = (UBYTE1) (data & 0xff);
+ } break;
+ case TYPE_GENERIC_16_LSB:
+ {
+ destData[dp] = (UBYTE1) (data & 0xff);
+ destData[dp + 1] = (UBYTE1) (data >> 8);
+ } break;
+ case TYPE_GENERIC_24:
+ {
+ destData[dp] = (UBYTE1) (data >> 16);
+ destData[dp + 1] = (UBYTE1) (data >> 8);
+ destData[dp + 2] = (UBYTE1) (data & 0xff);
+ } break;
+ case TYPE_GENERIC_32_MSB:
+ {
+ destData[dp] = (UBYTE1) (data >> 24);
+ destData[dp + 1] = (UBYTE1) (data >> 16);
+ destData[dp + 2] = (UBYTE1) (data >> 8);
+ destData[dp + 3] = (UBYTE1) (data & 0xff);
+ } break;
+ case TYPE_GENERIC_32_LSB:
+ {
+ destData[dp] = (UBYTE1) (data & 0xff);
+ destData[dp + 1] = (UBYTE1) (data >> 8);
+ destData[dp + 2] = (UBYTE1) (data >> 16);
+ destData[dp + 3] = (UBYTE1) (data >> 24);
+ } break;
+ }
+ }
+ }
+}
+
+/**
+ * Create a simple hash table used when converting direct colors to values in a palette
+ * Each bucket stores the RGB codes and the corresponding palette index.
+ * The key is made from the RGB values.
+ * It is used as a cache. New entries colliding with older ones simply
+ * replace them.
+ */
+ng_palette_bucket_t *NgRGBIndexCreate ()
+{
+ ng_palette_bucket_t *table = (ng_palette_bucket_t *)NgMalloc (RGBIndexTableSize * sizeof (ng_palette_bucket_t));
+ NgMemSet (table, 0, RGBIndexTableSize * sizeof (ng_palette_bucket_t));
+ return table;
+}
+
+void NgRGBIndexFree (ng_palette_bucket_t *table)
+{
+ NgFree (table);
+}
+
+void NgRGBIndexSet (ng_palette_bucket_t *table, UBYTE1 r, UBYTE1 g, UBYTE1 b, UBYTE1 index)
+{
+ int i = (r * g * b) % RGBIndexTableSize;
+ table[i].blue = b;
+ table[i].green = g;
+ table[i].red = r;
+ table[i].index = index;
+ table[i].isSet = 1;
+}
+
+int NgRGBIndexGet (ng_palette_bucket_t *table, UBYTE1 r, UBYTE1 g, UBYTE1 b)
+{
+ int i = (r * g * b) % RGBIndexTableSize;
+ if (table[i].isSet && table[i].blue == b && table[i].green == g && table[i].red == r)
+ return table[i].index;
+ return -1;
+}
+
+/**
+ * Blits a direct palette image into an index palette image.
+ *
+ * srcData the source byte array containing image data
+ * srcStride the source number of bytes per line
+ * srcX the top-left x-coord of the source blit region
+ * srcY the top-left y-coord of the source blit region
+ * srcWidth the width of the source blit region
+ * srcHeight the height of the source blit region
+ * destData the destination byte array containing image data
+ * destDepth the destination depth: one of 1, 2, 4, 8
+ * destStride the destination number of bytes per line
+ * destOrder the destination byte ordering: 0 if LSB, 1 otherwise;
+ * ignored if destDepth is not 1
+ * destX the top-left x-coord of the destination blit region
+ * destY the top-left y-coord of the destination blit region
+ * destWidth the width of the destination blit region
+ * destHeight the height of the destination blit region
+ * destColors the destination palette red green blue component intensities
+ * destNumColors the number of colors in destColors
+ *
+ * It is assumed that.
+ * srcDepth: 24 - BGR ordering (BMP format)
+ * no alpha
+ * srcX: 0
+ * srcY: 0
+ * destX: 0
+ * destY: 0
+ * destWidth: same as srcWidth
+ * destHeight: same as srcHeight
+ */
+
+void NgBitmapImageBlitDirectToPalette(
+ UBYTE1 *srcData, BYTE4 srcStride,
+ BYTE4 srcWidth, BYTE4 srcHeight,
+ UBYTE1 *destData, BYTE4 destDepth, BYTE4 destStride, BYTE4 destOrder,
+ UBYTE1 *destColors, int destNumColors)
+{
+ BYTE4 srcX = 0, srcY = 0, destX = 0, destY = 0, destWidth = srcWidth, destHeight = srcHeight;
+ BYTE4 sbpp, spr, dtype, dpr, dp, sp, destPaletteSize, dy, dx, j, dr, dg, db, distance, minDistance;
+
+ UBYTE1 r = 0, g = 0, b = 0, index = 0;
+ int storedIndex;
+ ng_palette_bucket_t *RGBIndexTable;
+
+ /*** Prepare source-related data ***/
+ sbpp = 3;
+ spr = srcY * srcStride + srcX * sbpp;
+
+ /*** Prepare destination-related data ***/
+ switch (destDepth)
+ {
+ case 8:
+ dtype = TYPE_INDEX_8;
+ break;
+ case 4:
+ destStride <<= 1;
+ dtype = TYPE_INDEX_4;
+ break;
+ case 2:
+ destStride <<= 2;
+ dtype = TYPE_INDEX_2;
+ break;
+ case 1:
+ destStride <<= 3;
+ dtype = (destOrder != 0) ? TYPE_INDEX_1_MSB : TYPE_INDEX_1_LSB;
+ break;
+ default:
+ return;
+ }
+ dpr = destY * destStride + destX;
+
+ dp = dpr;
+ sp = spr;
+ destPaletteSize = destNumColors;
+
+ RGBIndexTable = NgRGBIndexCreate ();
+ for (dy = destHeight; dy > 0; --dy, sp = spr += srcStride, dp = dpr += destStride)
+ {
+ for (dx = destWidth; dx > 0; --dx, dp += 1)
+ {
+ /*** READ NEXT PIXEL ASSUMING BGR ordering (BMP format) ***/
+ b = srcData[sp];
+ g = srcData[sp+1];
+ r = srcData[sp+2];
+ sp += 3;
+
+ /*** MAP COLOR TO THE PALETTE ***/
+ storedIndex = NgRGBIndexGet (RGBIndexTable, r, g, b);
+ if (storedIndex >= 0)
+ {
+ index = (UBYTE1) storedIndex;
+ } else
+ {
+ for (j = 0, minDistance = 0x7fffffff; j < destPaletteSize; ++j)
+ {
+ dr = (destColors[j*3] & 0xff) - r;
+ dg = (destColors[j*3+1] & 0xff) - g;
+ db = (destColors[j*3+2] & 0xff) - b;
+ distance = dr * dr + dg * dg + db * db;
+ if (distance < minDistance)
+ {
+ index = (UBYTE1)j;
+ if (distance == 0) break;
+ minDistance = distance;
+ }
+ }
+ NgRGBIndexSet (RGBIndexTable, r, g, b, index);
+ }
+
+ /*** WRITE NEXT PIXEL ***/
+ switch (dtype) {
+ case TYPE_INDEX_8:
+ destData[dp] = (UBYTE1) index;
+ break;
+ case TYPE_INDEX_4:
+ if ((dp & 1) != 0) destData[dp >> 1] = ((destData[dp >> 1] & 0xf0) | index);
+ else destData[dp >> 1] = ((destData[dp >> 1] & 0x0f) | (index << 4));
+ break;
+ case TYPE_INDEX_2:
+ {
+ int shift = 6 - (dp & 3) * 2;
+ destData[dp >> 2] = ((destData[dp >> 2] & ~(0x03 << shift)) | (index << shift));
+ } break;
+ case TYPE_INDEX_1_MSB:
+ {
+ int shift = 7 - (dp & 7);
+ destData[dp >> 3] = ((destData[dp >> 3] & ~(0x01 << shift)) | (index << shift));
+ } break;
+ case TYPE_INDEX_1_LSB:
+ {
+ int shift = dp & 7;
+ destData[dp >> 3] = ((destData[dp >> 3] & ~(0x01 << shift)) | (index << shift));
+ } break;
+ }
+ }
+ }
+ NgRGBIndexFree (RGBIndexTable);
+}

Back to the top