summaryrefslogtreecommitdiff
path: root/gdk
diff options
context:
space:
mode:
authorMichael Zucchi <zucchi@zedzone.mmc.com.au>1999-12-09 01:50:18 +0000
committerMichael Zucci <zucchi@src.gnome.org>1999-12-09 01:50:18 +0000
commit757fc193c498f7f8e27b99e561ceecaf5427f48f (patch)
tree1bf48ecf1e3e6442011a41b73b3e4e425ff59324 /gdk
parent6b23587aefd002b06047f2b31489bfd268fd8cbe (diff)
downloadgtk+-757fc193c498f7f8e27b99e561ceecaf5427f48f.tar.gz
Should now handle all formats, slow routine used where optimised
ones can't be. 1999-12-09 Michael Zucchi <zucchi@zedzone.mmc.com.au> * gdk-pixbuf/gdk-pixbuf-drawable.c (convert_real_slow): New function - should convert ANY visual/data format properly, but it aint fast. Used as a fallback when an optimised routine wont match. (rgbconvert): Do very specific tests on the data format to verify properly if the optimised version will do, otherwise use the fallback function for all other data formats.
Diffstat (limited to 'gdk')
-rw-r--r--gdk/gdkpixbuf-drawable.c136
1 files changed, 115 insertions, 21 deletions
diff --git a/gdk/gdkpixbuf-drawable.c b/gdk/gdkpixbuf-drawable.c
index ad519f045d..35d829bff6 100644
--- a/gdk/gdkpixbuf-drawable.c
+++ b/gdk/gdkpixbuf-drawable.c
@@ -836,6 +836,69 @@ rgb888msb (GdkImage *image, art_u8 *pixels, int rowstride, GdkColormap *colormap
}
}
+/*
+ This should work correctly with any display/any endianness, but will probably
+ run quite slow
+*/
+static void
+convert_real_slow (GdkImage *image, art_u8 *pixels, int rowstride, GdkColormap *cmap, int alpha)
+{
+ int xx, yy;
+ int width, height;
+ int bpl;
+ unsigned char *srow = image->mem, *orow = pixels;
+ unsigned char *s;
+ unsigned char *o;
+ guint32 pixel;
+ GdkVisual *v;
+
+ width = image->width;
+ height = image->height;
+ bpl = image->bpl;
+ v = gdk_colormap_get_visual(cmap);
+
+ d(printf("rgb mask/shift/prec = %x:%x:%x %d:%d:%d %d:%d:%d\n",
+ v->red_mask, v->green_mask, v->blue_mask,
+ v->red_shift, v->green_shift, v->blue_shift,
+ v->red_prec, v->green_prec, v->blue_prec));
+
+ for (yy = 0; yy < height; yy++) {
+ s = srow;
+ o = orow;
+ for (xx = 0; xx < width; xx++) {
+ pixel = gdk_image_get_pixel(image, xx, yy);
+ switch (v->type) {
+ /* I assume this is right for static & greyscale's too? */
+ case GDK_VISUAL_STATIC_GRAY:
+ case GDK_VISUAL_GRAYSCALE:
+ case GDK_VISUAL_STATIC_COLOR:
+ case GDK_VISUAL_PSEUDO_COLOR:
+ *o++ = cmap->colors[pixel].red;
+ *o++ = cmap->colors[pixel].green;
+ *o++ = cmap->colors[pixel].blue;
+ break;
+ case GDK_VISUAL_TRUE_COLOR:
+ /* this is odd because it must sometimes shift left (otherwise
+ i'd just shift >> *_shift - 8 + *_prec), so this logic
+ should work for all bit sizes/shifts/etc */
+ *o++ = ((pixel & v->red_mask) << (32 - v->red_shift - v->red_prec)) >> 24;
+ *o++ = ((pixel & v->green_mask) << (32 - v->green_shift - v->green_prec)) >> 24;
+ *o++ = ((pixel & v->blue_mask) << (32 - v->blue_shift - v->blue_prec)) >> 24;
+ break;
+ case GDK_VISUAL_DIRECT_COLOR:
+ *o++ = cmap->colors[((pixel & v->red_mask) << (32 - v->red_shift - v->red_prec)) >> 24].red;
+ *o++ = cmap->colors[((pixel & v->green_mask) << (32 - v->green_shift - v->green_prec)) >> 24].green;
+ *o++ = cmap->colors[((pixel & v->blue_mask) << (32 - v->blue_shift - v->blue_prec)) >> 24].blue;
+ break;
+ }
+ if (alpha)
+ *o++ = 0xff;
+ }
+ srow += bpl;
+ orow += rowstride;
+ }
+}
+
typedef void (* cfunc) (GdkImage *image, art_u8 *pixels, int rowstride, GdkColormap *cmap);
static cfunc convert_map[] = {
@@ -848,38 +911,69 @@ static cfunc convert_map[] = {
/*
perform actual conversion
+
+ If we can, try and use the optimised code versions, but as a default
+ fallback, and always for direct colour, use the generic/slow but complete
+ conversion function.
*/
static void
rgbconvert (GdkImage *image, art_u8 *pixels, int rowstride, int alpha, GdkColormap *cmap)
{
int index = (image->byte_order == GDK_MSB_FIRST) | (alpha != 0) << 1;
- int bank=0;
-
- switch (image->depth) {
- case 1:
- bank = 0;
+ int bank=5; /* default fallback converter */
+ GdkVisual *v = gdk_colormap_get_visual(cmap);
+
+ d(printf("masks = %x:%x:%x\n", v->red_mask, v->green_mask, v->blue_mask));
+ d(printf("image depth = %d, bpp = %d\n", image->depth, image->bpp));
+
+ switch (v->type) {
+ /* I assume this is right for static & greyscale's too? */
+ case GDK_VISUAL_STATIC_GRAY:
+ case GDK_VISUAL_GRAYSCALE:
+ case GDK_VISUAL_STATIC_COLOR:
+ case GDK_VISUAL_PSEUDO_COLOR:
+ switch (image->bpp) {
+ case 1:
+ bank = 0;
+ break;
+ case 8:
+ bank = 1;
+ break;
+ }
break;
-
- case 8:
- bank = 1;
+ case GDK_VISUAL_TRUE_COLOR:
+ switch (image->depth) {
+ case 15:
+ if (v->red_mask == 0x7c00 && v->green_mask == 0x3e0 && v->blue_mask == 0x1f
+ && image->bpp == 16)
+ bank = 2;
+ break;
+ case 16:
+ if (v->red_mask == 0xf800 && v->green_mask == 0x7e0 && v->blue_mask == 0x1f
+ && image->bpp == 16)
+ bank = 3;
+ break;
+ case 24:
+ case 32:
+ if (v->red_mask == 0xff0000 && v->green_mask == 0xff00 && v->blue_mask == 0xff
+ && image->bpp == 32)
+ bank = 4;
+ break;
+ }
break;
-
- case 15:
- bank = 2;
+ case GDK_VISUAL_DIRECT_COLOR:
+ /* always use the slow version */
break;
+ }
- case 16:
- bank = 3;
- break;
+ d(printf("converting using conversion function in bank %d\n", bank));
- case 24:
- case 32:
- bank = 4;
- break;
+ if (bank==5) {
+ convert_real_slow(image, pixels, rowstride, cmap, alpha);
+ } else {
+ index |= bank << 2;
+ (* convert_map[index]) (image, pixels, rowstride, cmap);
}
-
- index |= bank << 2;
- (* convert_map[index]) (image, pixels, rowstride, cmap);
}