summaryrefslogtreecommitdiff
path: root/gdk/gdkpixbuf-drawable.c
diff options
context:
space:
mode:
authorMichael Zucchi <zucchi@zedzone.mmc.com.au>1999-11-20 05:39:54 +0000
committerMichael Zucci <zucchi@src.gnome.org>1999-11-20 05:39:54 +0000
commit7b4d53a529246c379c99a9a0e5d8742217447457 (patch)
treeef22479af93717ece803c3bf4af57028a3cafe89 /gdk/gdkpixbuf-drawable.c
parent8e06c4d7f4338ab0061609b62488ce8ecbc05c07 (diff)
downloadgdk-pixbuf-7b4d53a529246c379c99a9a0e5d8742217447457.tar.gz
Rework/reorder of the code. Each case has been separated into another
1999-11-20 Michael Zucchi <zucchi@zedzone.mmc.com.au> * src/gdk-pixbuf-drawable.c (gdk_pixbuf_from_drawable_core): Rework/reorder of the code. Each case has been separated into another function; its big but it should be quick. gdk_pixbuf_rgba_from_drawable() will now return a pixbuf with opaque alpha information. Not all depths/formats have been tested, but 8, 15/16 and 24 (alinged 32) should work ok.
Diffstat (limited to 'gdk/gdkpixbuf-drawable.c')
-rw-r--r--gdk/gdkpixbuf-drawable.c1161
1 files changed, 785 insertions, 376 deletions
diff --git a/gdk/gdkpixbuf-drawable.c b/gdk/gdkpixbuf-drawable.c
index 0dd668406..b2af116ae 100644
--- a/gdk/gdkpixbuf-drawable.c
+++ b/gdk/gdkpixbuf-drawable.c
@@ -4,6 +4,9 @@
* Authors:
* Cody Russell <bratsche@dfw.net>
* Michael Zucchi <zucchi@zedzone.mmc.com.au>
+ *
+ * This is licensed software, see the file COPYING for
+ * details.
*/
#include <config.h>
@@ -20,331 +23,540 @@
#endif
#define d(x)
-unsigned long mask_table[] = {
- 0x00000000, 0x00000001, 0x00000003, 0x00000007,
- 0x0000000f, 0x0000001f, 0x0000003f, 0x0000007f,
- 0x000000ff, 0x000001ff, 0x000003ff, 0x000007ff,
- 0x00000fff, 0x00001fff, 0x00003fff, 0x00007fff,
- 0x0000ffff, 0x0001ffff, 0x0003ffff, 0x0007ffff,
- 0x000fffff, 0x001fffff, 0x003fffff, 0x007fffff,
- 0x00ffffff, 0x01ffffff, 0x03ffffff, 0x07ffffff,
- 0x0fffffff, 0x1fffffff, 0x3fffffff, 0x7fffffff,
- 0xffffffff
+static unsigned long mask_table[] = {
+ 0x00000000, 0x00000001, 0x00000003, 0x00000007,
+ 0x0000000f, 0x0000001f, 0x0000003f, 0x0000007f,
+ 0x000000ff, 0x000001ff, 0x000003ff, 0x000007ff,
+ 0x00000fff, 0x00001fff, 0x00003fff, 0x00007fff,
+ 0x0000ffff, 0x0001ffff, 0x0003ffff, 0x0007ffff,
+ 0x000fffff, 0x001fffff, 0x003fffff, 0x007fffff,
+ 0x00ffffff, 0x01ffffff, 0x03ffffff, 0x07ffffff,
+ 0x0fffffff, 0x1fffffff, 0x3fffffff, 0x7fffffff,
+ 0xffffffff
};
-static GdkPixbuf *
-gdk_pixbuf_from_drawable_core (GdkPixmap * window, gint x, gint y, gint width,
- gint height, gint with_alpha)
+/*
+ convert 1 bits-pixel data
+ no alpha
+*/
+static void rgb1(GdkImage *image, art_u8 *pixels, int rowstride)
{
- GdkImage *image;
- ArtPixBuf *art_pixbuf;
- GdkColormap *colormap;
- art_u8 *buff;
- art_u8 *pixels;
- gulong pixel;
- gint rowstride;
- art_u8 r, g, b;
- gint xx, yy;
- gint fatness;
- gint screen_width, screen_height;
- gint window_width, window_height, window_x, window_y;
- int bpl;
-
- g_return_val_if_fail (window != NULL, NULL);
-
- /* always returns image in ZPixmap format ... */
- image = gdk_image_get (window, x, y, width, height);
-
- fatness = with_alpha ? 4 : 3;
- rowstride = width * fatness;
-
- buff = art_alloc (rowstride * height);
- pixels = buff;
+ int xx, yy;
+ int width, height;
+ int bpl;
+ unsigned char *s;
+ register unsigned char data;
+ unsigned char *o;
+ unsigned char *srow = image->mem, *orow = pixels;
+ GdkColormap *colormap;
-#if 0
- printf ("bpp = %d\n", image->bpp);
- printf ("depth = %d\n", image->depth);
- printf ("byte order = %d\n", image->byte_order);
- printf ("bytes/line = %d\n", image->bpl);
-#endif
+ d (printf ("1 bits/pixel\n"));
+
+ /* convert upto 8 pixels/time */
+ /* its probably not worth trying to make this run very fast, who uses
+ 1 bit displays anymore? */
+ width = image->width;
+ height = image->height;
+ bpl = image->bpl;
+
+ colormap = gdk_rgb_get_cmap ();
- bpl = image->bpl;
+ for (yy = 0; yy < height; yy++) {
+ s = srow;
+ o = orow;
+
+ for (xx = 0; xx < width; xx ++) {
+ data = srow[xx>>3] >> (7 - (xx & 7)) & 1;
+ *o++ = colormap->colors[data].red;
+ *o++ = colormap->colors[data].green;
+ *o++ = colormap->colors[data].blue;
+ }
+ srow += bpl;
+ orow += rowstride;
+ }
+}
- switch (image->bpp)
- {
- case 1:
- {
+/*
+ convert 1 bits/pixel data
+ with alpha
+*/
+static void rgb1a(GdkImage *image, art_u8 *pixels, int rowstride)
+{
+ int xx, yy;
+ int width, height;
+ int bpl;
unsigned char *s;
- register unsigned char bits;
register unsigned char data;
unsigned char *o;
unsigned char *srow = image->mem, *orow = pixels;
- int i, base;
+ unsigned long remap[2];
+ GdkColormap *colormap;
d (printf ("1 bits/pixel\n"));
/* convert upto 8 pixels/time */
+ /* its probably not worth trying to make this run very fast, who uses
+ 1 bit displays anymore? */
+ width = image->width;
+ height = image->height;
+ bpl = image->bpl;
+
colormap = gdk_rgb_get_cmap ();
- for (yy = 0; yy < height; yy++)
- {
- s = srow;
- o = orow;
-
- for (xx = 0; xx < width; xx += 8)
- {
- bits = *s++;
-
- if (xx + 8 >= width)
- base = 7 - (xx + 8 - width);
- else
- base = 0;
-
- for (i = 7; i >= base; i--)
- {
- data = (bits & (0x80 >> i)) & 1;
- *o++ = colormap->colors[data].red;
- *o++ = colormap->colors[data].green;
- *o++ = colormap->colors[data].blue;
- }
- }
-
- srow += bpl;
- orow += rowstride;
- }
- break;
- }
-
- case 8:
- {
- unsigned char *s;
+
+ for (xx=0;xx<2;xx++) {
+#ifdef LITTLE
+ remap[xx] = 0xff000000
+ | colormap->colors[xx].blue<<16
+ | colormap->colors[xx].green<<8
+ | colormap->colors[xx].red;
+#else
+ remap[xx] = 0xff
+ | colormap->colors[xx].red<<24
+ | colormap->colors[xx].green<<16
+ | colormap->colors[xx].red<<8;
+#endif
+ }
+
+ for (yy = 0; yy < height; yy++) {
+ s = srow;
+ o = orow;
+
+ for (xx = 0; xx < width; xx ++) {
+ data = srow[xx>>3] >> (7 - (xx & 7)) & 1;
+ *o++ = remap[data];
+ }
+ srow += bpl;
+ orow += rowstride;
+ }
+}
+
+/*
+ convert 8 bits/pixel data
+ no alpha
+*/
+static void rgb8(GdkImage *image, art_u8 *pixels, int rowstride)
+{
+ int xx, yy;
+ int width, height;
+ int bpl;
unsigned long mask;
register unsigned long data;
- unsigned char *o;
unsigned char *srow = image->mem, *orow = pixels;
+ register unsigned char *s;
+ register unsigned char *o;
+ GdkColormap *colormap;
+
+ width = image->width;
+ height = image->height;
+ bpl = image->bpl;
+
+ d(printf("8 bit, no alpha output\n"));
+
+ colormap = gdk_rgb_get_cmap ();
+ mask = mask_table[image->depth];
- d (printf ("8 bits/pixel\n"));
+ for (yy = 0;yy < height; yy++) {
+ s = srow;
+ o = orow;
+ for (xx = 0; xx < width; xx++) {
+ data = *s++ & mask;
+ *o++ = colormap->colors[data].red;
+ *o++ = colormap->colors[data].green;
+ *o++ = colormap->colors[data].blue;
+ }
+ srow += bpl;
+ orow += rowstride;
+ }
+}
+
+/*
+ convert 8 bits/pixel data
+ with alpha
+*/
+static void rgb8a(GdkImage *image, art_u8 *pixels, int rowstride)
+{
+ int xx, yy;
+ int width, height;
+ int bpl;
+ unsigned long mask;
+ register unsigned long data;
+ GdkColormap *colormap;
+ unsigned long remap[256];
+ register unsigned char *s; /* read 2 pixels at once */
+ register unsigned long *o;
+ unsigned char *srow = image->mem, *orow = pixels;
+
+ width = image->width;
+ height = image->height;
+ bpl = image->bpl;
+ d(printf("8 bit, with alpha output\n"));
+
colormap = gdk_rgb_get_cmap ();
mask = mask_table[image->depth];
+
+ for (xx=0;xx<colormap->size;xx++) {
+#ifdef LITTLE
+ remap[xx] = 0xff000000
+ | colormap->colors[xx].blue<<16
+ | colormap->colors[xx].green<<8
+ | colormap->colors[xx].red;
+#else
+ remap[xx] = 0xff
+ | colormap->colors[xx].red<<24
+ | colormap->colors[xx].green<<16
+ | colormap->colors[xx].red<<8;
+#endif
+ }
+
+ for (yy = 0;yy < height; yy++) {
+ s = srow;
+ o = (unsigned long *)orow;
+ for (xx = 0; xx < width; xx ++) {
+ data = *s++ & mask;
+ *o++ = remap[data];
+ }
+ srow += bpl;
+ orow += rowstride;
+ }
+}
- for (yy = 0; yy < height; yy++)
- {
- s = srow;
- o = orow;
- for (xx = 0; xx < width; xx++)
- {
- data = *s++ & mask;
- *o++ = colormap->colors[data].red;
- *o++ = colormap->colors[data].green;
- *o++ = colormap->colors[data].blue;
- }
- srow += bpl;
- orow += rowstride;
- }
- break;
- }
-
- /*#define SIMPLE_16 this is really quite slow ! */
- case 16:
- {
-#ifdef SIMPLE_16
- unsigned short *s;
+/*
+ convert 16 bits/pixel data
+ no alpha
+ data in lsb format
+*/
+static void rgb565lsb(GdkImage *image, art_u8 *pixels, int rowstride)
+{
+ int xx, yy;
+ int width, height;
+ int bpl;
+
+#ifdef LITTLE
+ register unsigned long *s; /* read 2 pixels at once */
#else
- unsigned long *s; /* read 2 pixels at once */
+ register unsigned char *s; /* read 2 pixels at once */
#endif
- register unsigned long data;
- unsigned short *o;
+ register unsigned short *o;
unsigned char *srow = image->mem, *orow = pixels;
-
- printf ("16 bits/pixel\n");
-
- for (yy = 0; yy < height; yy++)
- {
- s = srow;
- o = orow;
-
- if (image->byte_order == GDK_LSB_FIRST)
- {
-#ifdef SIMPLE_16
- for (xx = 0; xx < width; xx++)
- {
- data = *s++;
- *o++ = (data >> 8) & 0xf8;
- *o++ = (data >> 3) & 0xfc;
- *o++ = (data << 3) & 0xf8;
- }
+
+ width = image->width;
+ height = image->height;
+ bpl = image->bpl;
+
+ for (yy = 0;yy < height; yy++) {
+#ifdef LITTLE
+ s = (unsigned long *)srow;
#else
- switch (image->depth)
- {
- case 15:
- /* starts at 1, so we dont over-flow the conversion */
- for (xx = 0; xx < width; xx += 2)
- {
- /* read/convert 2 pixels at a time */
-
- /* little endian, lsb data */
+ s = (unsigned char *)srow;
+#endif
+ o = (unsigned short *)orow;
+ for (xx = 1; xx < width; xx += 2) {
+ register unsigned long data;
#ifdef LITTLE
- /*7c 3e 1f */
data = *s++;
- *o++ = (data & 0x7c00) >> 7 | (data & 0x3e0) << 6;
- *o++ = (data & 0x1f) << 3 | (data & 0x7c000000) >> 15;
- *o++ =
- ((data & 0x3e00000) >> 18) | (data & 0x1f0000) >> 5;
+ *o++ = (data & 0xf800) >> 8 | (data & 0x7e0) << 5;
+ *o++ = (data & 0x1f) << 3 | (data & 0xf8000000) >> 16;
+ *o++ = ((data & 0x7e00000) >> 19) | (data & 0x1f0000) >> 5;
#else
- /* big endian, lsb data */
/* swap endianness first */
- data = (unsigned long) ((unsigned char *) s)[3] << 24
- | (unsigned long) ((unsigned char *) s)[2] << 16
- | (unsigned long) ((unsigned char *) s)[1] << 8
- | (unsigned long) ((unsigned char *) s)[0];
- s++;
- *o++ = (data & 0x7c00) << 1 | (data & 0x3e0) >> 2;
- *o++ =
- (data & 0x1f) << 11 | (data & 0x7c000000) >> 23;
- *o++ =
- ((data & 0x3e00000) >> 10) | (data & 0x1f0000) >>
- 13;
-#endif
- }
- /* check for last remaining pixel */
- if (width & 1)
- {
+ data = s[0] | s[1]<<8 | s[2]<<16 | s[3]<<24;
+ s+=4;
+ *o++ = (data & 0xf800) | (data & 0x7e0) >> 3;
+ *o++ = (data & 0x1f) << 11 | (data & 0xf8000000) >> 24;
+ *o++ = ((data & 0x7e00000) >> 11) | (data & 0x1f0000) >> 13;
+#endif
+ }
+ /* check for last remaining pixel */
+ if (width & 1) {
register unsigned short data;
#ifdef LITTLE
data = *((short *) s);
#else
data = *((short *) s);
data = ((data >> 8) & 0xff) | ((data & 0xff) << 8);
- data &= mask;
#endif
- ((char *) o)[0] = (data & 0x7c0) >> 7;
- ((char *) o)[1] = (data & 0x3e0) >> 2;
- ((char *) o)[2] = (data & 0x1f) << 3;
- }
- break;
- case 16:
- for (xx = 0; xx < width; xx += 2)
- {
- /* read/convert 2 pixels at a time */
-
- /* little endian, lsb data */
+ ((char *) o)[0] = (data >> 8) & 0xf8;
+ ((char *) o)[1] = (data >> 3) & 0xfc;
+ ((char *) o)[2] = (data << 3) & 0xf8;
+ }
+ srow += bpl;
+ orow += rowstride;
+ }
+}
+
+/*
+ convert 16 bits/pixel data
+ no alpha
+ data in msb format
+*/
+static void rgb565msb(GdkImage *image, art_u8 *pixels, int rowstride)
+{
+ int xx, yy;
+ int width, height;
+ int bpl;
+
#ifdef LITTLE
- data = *s++;
+ register unsigned char *s; /* need to swap data order */
+#else
+ register unsigned long *s; /* read 2 pixels at once */
+#endif
+ register unsigned short *o;
+ unsigned char *srow = image->mem, *orow = pixels;
+
+ width = image->width;
+ height = image->height;
+ bpl = image->bpl;
+
+ for (yy = 0;yy < height; yy++) {
+#ifdef LITTLE
+ s = srow;
+#else
+ s = (unsigned long *)srow;
+#endif
+ o = (unsigned short *)orow;
+ for (xx = 1; xx < width; xx += 2) {
+ register unsigned long data;
+#ifdef LITTLE
+ /* swap endianness first */
+ data = s[0] | s[1]<<8 | s[2]<<16 | s[3]<<24;
+ s+=4;
*o++ = (data & 0xf800) >> 8 | (data & 0x7e0) << 5;
*o++ = (data & 0x1f) << 3 | (data & 0xf8000000) >> 16;
- *o++ =
- ((data & 0x7e00000) >> 19) | (data & 0x1f0000) >> 5;
+ *o++ = ((data & 0x7e00000) >> 19) | (data & 0x1f0000) >> 5;
#else
- /* big endian, lsb data */
- /* swap endianness first */
- data = (unsigned long) ((unsigned char *) s)[3] << 24
- | (unsigned long) ((unsigned char *) s)[2] << 16
- | (unsigned long) ((unsigned char *) s)[1] << 8
- | (unsigned long) ((unsigned char *) s)[0];
- s++;
+ data = *s++;
*o++ = (data & 0xf800) | (data & 0x7e0) >> 3;
- *o++ =
- (data & 0x1f) << 11 | (data & 0xf8000000) >> 24;
- *o++ =
- ((data & 0x7e00000) >> 11) | (data & 0x1f0000) >>
- 13;
-#endif
- }
- /* check for last remaining pixel */
- if (width & 1)
- {
+ *o++ = (data & 0x1f) << 11 | (data & 0xf8000000) >> 24;
+ *o++ = ((data & 0x7e00000) >> 11) | (data & 0x1f0000) >> 13;
+#endif
+ }
+ /* check for last remaining pixel */
+ if (width & 1) {
register unsigned short data;
#ifdef LITTLE
data = *((short *) s);
+ data = ((data >> 8) & 0xff) | ((data & 0xff) << 8);
#else
data = *((short *) s);
- data = ((data >> 8) & 0xff) | ((data & 0xff) << 8);
#endif
((char *) o)[0] = (data >> 8) & 0xf8;
((char *) o)[1] = (data >> 3) & 0xfc;
((char *) o)[2] = (data << 3) & 0xf8;
- }
- break;
- }
-#endif /* SIMPLE_16 */
- }
- else
- {
- switch (image->depth)
- {
- case 15:
- for (xx = 0; xx < width; xx += 2)
- {
- /* read/convert 2 pixels at a time */
+ }
+ srow += bpl;
+ orow += rowstride;
+ }
+}
+
+/*
+ convert 16 bits/pixel data
+ with alpha
+ data in lsb format
+*/
+static void rgb565alsb(GdkImage *image, art_u8 *pixels, int rowstride)
+{
+ int xx, yy;
+ int width, height;
+ int bpl;
+
+#ifdef LITTLE
+ register unsigned short *s; /* read 1 pixels at once */
+#else
+ register unsigned char *s;
+#endif
+ register unsigned long *o;
+
+ unsigned char *srow = image->mem, *orow = pixels;
+
+ width = image->width;
+ height = image->height;
+ bpl = image->bpl;
+
+ for (yy = 0;yy < height; yy++) {
#ifdef LITTLE
- /* little endian, msb data */
+ s = (unsigned short *)srow;
+#else
+ s = (unsigned char *)srow;
+#endif
+ o = (unsigned long *)orow;
+ for (xx = 0; xx < width; xx ++) {
+ register unsigned long data;
+ /* rrrrrggg gggbbbbb -> rrrrr000 gggggg00 bbbbb000 aaaaaaaa */
+ /* little endian: aaaaaaaa bbbbb000 gggggg00 rrrrr000 */
+#ifdef LITTLE
+ data = *s++;
+ *o++ = (data & 0xf800) >>8 | (data & 0x7e0) << 5
+ | (data & 0x1f) << 19 | 0xff000000;
+#else
/* swap endianness first */
- data = (unsigned long) ((unsigned char *) s)[0] << 24
- | (unsigned long) ((unsigned char *) s)[1] << 16
- | (unsigned long) ((unsigned char *) s)[2] << 8
- | (unsigned long) ((unsigned char *) s)[3];
- s++;
- /*7c 3e 1f */
+ data = s[0] | s[1]<<8;
+ s+=2;
+ *o++ = (data & 0xf800) << 16 | (data & 0x7e0) << 13
+ | (data & 0x1f) << 11 | 0xff;
+#endif
+ }
+ srow += bpl;
+ orow += rowstride;
+ }
+}
+
+/*
+ convert 16 bits/pixel data
+ with alpha
+ data in msb format
+*/
+static void rgb565amsb(GdkImage *image, art_u8 *pixels, int rowstride)
+{
+ int xx, yy;
+ int width, height;
+ int bpl;
+
+#ifdef LITTLE
+ register unsigned char *s;
+#else
+ register unsigned short *s; /* read 1 pixels at once */
+#endif
+ register unsigned long *o;
+
+ unsigned char *srow = image->mem, *orow = pixels;
+
+ width = image->width;
+ height = image->height;
+ bpl = image->bpl;
+
+ for (yy = 0;yy < height; yy++) {
+ s = srow;
+ o = (unsigned long *)orow;
+ for (xx = 0; xx < width; xx ++) {
+ register unsigned long data;
+ /* rrrrrggg gggbbbbb -> rrrrr000 gggggg00 bbbbb000 aaaaaaaa */
+ /* little endian: aaaaaaaa bbbbb000 gggggg00 rrrrr000 */
+#ifdef LITTLE
+ /* swap endianness first */
+ data = s[0] | s[1]<<8;
+ s+=2;
+ *o++ = (data & 0xf800) >>8 | (data & 0x7e0) << 5
+ | (data & 0x1f) << 19 | 0xff000000;
+#else
+ data = *s++;
+ *o++ = (data & 0xf800) << 16 | (data & 0x7e0) << 13
+ | (data & 0x1f) << 11 | 0xff;
+#endif
+ }
+ srow += bpl;
+ orow += rowstride;
+ }
+}
+
+/*
+ convert 15 bits/pixel data
+ no alpha
+ data in lsb format
+*/
+static void rgb555lsb(GdkImage *image, art_u8 *pixels, int rowstride)
+{
+ int xx, yy;
+ int width, height;
+ int bpl;
+
+#ifdef LITTLE
+ register unsigned long *s; /* read 2 pixels at once */
+#else
+ register unsigned char *s; /* read 2 pixels at once */
+#endif
+ register unsigned short *o;
+ unsigned char *srow = image->mem, *orow = pixels;
+
+ width = image->width;
+ height = image->height;
+ bpl = image->bpl;
+
+ for (yy = 0;yy < height; yy++) {
+#ifdef LITTLE
+ s = (unsigned long *)srow;
+#else
+ s = srow;
+#endif
+ o = (unsigned short *)orow;
+ for (xx = 1; xx < width; xx += 2) {
+ register unsigned long data;
+#ifdef LITTLE
+ data = *s++;
*o++ = (data & 0x7c00) >> 7 | (data & 0x3e0) << 6;
*o++ = (data & 0x1f) << 3 | (data & 0x7c000000) >> 15;
- *o++ =
- ((data & 0x3e00000) >> 18) | (data & 0x1f0000) >> 5;
+ *o++ = ((data & 0x3e00000) >> 18) | (data & 0x1f0000) >> 5;
#else
- /* big endian, lsb data */
- data = *s++;
+ /* swap endianness first */
+ data = s[0] | s[1]<<8 | s[2]<<16 | s[3]<<24;
+ s+=4;
*o++ = (data & 0x7c00) << 1 | (data & 0x3e0) >> 2;
- *o++ =
- (data & 0x1f) << 11 | (data & 0x7c000000) >> 23;
- *o++ =
- ((data & 0x3e00000) >> 10) | (data & 0x1f0000) >>
- 13;
-#endif
- }
- /* check for last remaining pixel */
- if (width & 1)
- {
+ *o++ = (data & 0x1f) << 11 | (data & 0x7c000000) >> 23;
+ *o++ = ((data & 0x3e00000) >> 10) | (data & 0x1f0000) >> 13;
+#endif
+ }
+ /* check for last remaining pixel */
+ if (width & 1) {
register unsigned short data;
#ifdef LITTLE
data = *((short *) s);
- data = ((data >> 8) & 0xff) | ((data & 0xff) << 8);
#else
data = *((short *) s);
+ data = ((data >> 8) & 0xff) | ((data & 0xff) << 8);
#endif
- ((char *) o)[0] = (data >> 8) & 0xf8;
- ((char *) o)[1] = (data >> 3) & 0xfc;
- ((char *) o)[2] = (data << 3) & 0xf8;
- }
- break;
- case 16:
- for (xx = 0; xx < width; xx += 2)
- {
- /* read/convert 2 pixels at a time */
+ ((char *) o)[0] = (data & 0x7c0) >> 7;
+ ((char *) o)[1] = (data & 0x3e0) >> 2;
+ ((char *) o)[2] = (data & 0x1f) << 3;
+ }
+ srow += bpl;
+ orow += rowstride;
+ }
+}
+
+/*
+ convert 15 bits/pixel data
+ no alpha
+ data in msb format
+*/
+static void rgb555msb(GdkImage *image, art_u8 *pixels, int rowstride)
+{
+ int xx, yy;
+ int width, height;
+ int bpl;
+
+#ifdef LITTLE
+ register unsigned char *s; /* read 2 pixels at once */
+#else
+ register unsigned long *s; /* read 2 pixels at once */
+#endif
+ register unsigned short *o;
+ unsigned char *srow = image->mem, *orow = pixels;
+
+ width = image->width;
+ height = image->height;
+ bpl = image->bpl;
+
+ for (yy = 0;yy < height; yy++) {
+ s = srow;
+ o = (unsigned short *)orow;
+ for (xx = 1; xx < width; xx += 2) {
+ register unsigned long data;
#ifdef LITTLE
- /* little endian, msb data */
/* swap endianness first */
- data = (unsigned long) ((unsigned char *) s)[0] << 24
- | (unsigned long) ((unsigned char *) s)[1] << 16
- | (unsigned long) ((unsigned char *) s)[2] << 8
- | (unsigned long) ((unsigned char *) s)[3];
- s++;
- *o++ = (data & 0xf800) >> 8 | (data & 0x7e0) << 5;
- *o++ = (data & 0x1f) << 3 | (data & 0xf8000000) >> 16;
- *o++ =
- ((data & 0x7e00000) >> 19) | (data & 0x1f0000) >> 5;
+ data = s[0] | s[1]<<8 | s[2]<<16 | s[3]<<24;
+ s+=4;
+ *o++ = (data & 0x7c00) >> 7 | (data & 0x3e0) << 6;
+ *o++ = (data & 0x1f) << 3 | (data & 0x7c000000) >> 15;
+ *o++ = ((data & 0x3e00000) >> 18) | (data & 0x1f0000) >> 5;
#else
- /* big endian, lsb data */
data = *s++;
- *o++ = (data & 0xf800) | (data & 0x7e0) >> 3;
- *o++ =
- (data & 0x1f) << 11 | (data & 0xf8000000) >> 24;
- *o++ =
- ((data & 0x7e00000) >> 11) | (data & 0x1f0000) >>
- 13;
-#endif
- }
- /* check for last remaining pixel */
- if (width & 1)
- {
+ *o++ = (data & 0x7c00) << 1 | (data & 0x3e0) >> 2;
+ *o++ = (data & 0x1f) << 11 | (data & 0x7c000000) >> 23;
+ *o++ = ((data & 0x3e00000) >> 10) | (data & 0x1f0000) >> 13;
+#endif
+ }
+ /* check for last remaining pixel */
+ if (width & 1) {
register unsigned short data;
#ifdef LITTLE
data = *((short *) s);
@@ -352,145 +564,336 @@ gdk_pixbuf_from_drawable_core (GdkPixmap * window, gint x, gint y, gint width,
#else
data = *((short *) s);
#endif
- ((char *) o)[0] = (data >> 8) & 0xf8;
- ((char *) o)[1] = (data >> 3) & 0xfc;
- ((char *) o)[2] = (data << 3) & 0xf8;
- }
- break;
- }
- }
- srow += bpl;
- orow += rowstride;
- }
- break;
- }
- /*#define HAIRY_32 this is slowest implementation */
-#define SIMPLE_32 /* this is fastest implementation */
- case 32:
- {
-#ifdef SIMPLE_32
- unsigned char *s; /* read 1 pixels at once */
+ ((char *) o)[0] = (data & 0x7c0) >> 7;
+ ((char *) o)[1] = (data & 0x3e0) >> 2;
+ ((char *) o)[2] = (data & 0x1f) << 3;
+ }
+ srow += bpl;
+ orow += rowstride;
+ }
+}
+
+/*
+ convert 15 bits/pixel data
+ with alpha
+ data in lsb format
+*/
+static void rgb555alsb(GdkImage *image, art_u8 *pixels, int rowstride)
+{
+ int xx, yy;
+ int width, height;
+ int bpl;
+
+#ifdef LITTLE
+ register unsigned short *s; /* read 1 pixels at once */
+#else
+ register unsigned char *s;
+#endif
+ register unsigned long *o;
+
+ unsigned char *srow = image->mem, *orow = pixels;
+
+ width = image->width;
+ height = image->height;
+ bpl = image->bpl;
+
+ for (yy = 0;yy < height; yy++) {
+#ifdef LITTLE
+ s = (unsigned short *)srow;
#else
- unsigned long *s; /* read 1 pixels at once */
+ s = srow;
#endif
-#ifdef HAIRY_32
- register unsigned long data2;
- unsigned short *o;
+ o = (unsigned long *)orow;
+ for (xx = 0; xx < width; xx++) {
+ register unsigned long data;
+ /* rrrrrggg gggbbbbb -> rrrrr000 gggggg00 bbbbb000 aaaaaaaa */
+ /* little endian: aaaaaaaa bbbbb000 gggggg00 rrrrr000 */
+#ifdef LITTLE
+ data = *s++;
+ *o++ = (data & 0x7c00) >>7 | (data & 0x3e0) << 6
+ | (data & 0x1f) << 19 | 0xff000000;
#else
- unsigned char *o;
+ /* swap endianness first */
+ data = s[0] | s[1]<<8;
+ s+=2;
+ *o++ = (data & 0x7c00) << 17 | (data & 0x3e0) << 14
+ | (data & 0x1f) << 11 | 0xff;
#endif
- register unsigned long data;
+ }
+ srow += bpl;
+ orow += rowstride;
+ }
+}
+
+/*
+ convert 15 bits/pixel data
+ with alpha
+ data in msb format
+*/
+static void rgb555amsb(GdkImage *image, art_u8 *pixels, int rowstride)
+{
+ int xx, yy;
+ int width, height;
+ int bpl;
+
+#ifdef LITTLE
+ register unsigned short *s; /* read 1 pixels at once */
+#else
+ register unsigned char *s;
+#endif
+ register unsigned long *o;
+
+ unsigned char *srow = image->mem, *orow = pixels;
+
+ width = image->width;
+ height = image->height;
+ bpl = image->bpl;
+
+ for (yy = 0;yy < height; yy++) {
+#ifdef LITTLE
+ s = (unsigned short *)srow;
+#else
+ s = srow;
+#endif
+ o = (unsigned long *)orow;
+ for (xx = 0; xx < width; xx++) {
+ register unsigned long data;
+ /* rrrrrggg gggbbbbb -> rrrrr000 gggggg00 bbbbb000 aaaaaaaa */
+ /* little endian: aaaaaaaa bbbbb000 gggggg00 rrrrr000 */
+#ifdef LITTLE
+ /* swap endianness first */
+ data = s[0] | s[1]<<8;
+ s+=2;
+ *o++ = (data & 0x7c00) >>7 | (data & 0x3e0) << 6
+ | (data & 0x1f) << 19 | 0xff000000;
+#else
+ data = *s++;
+ *o++ = (data & 0x7c00) << 17 | (data & 0x3e0) << 14
+ | (data & 0x1f) << 11 | 0xff;
+#endif
+ }
+ srow += bpl;
+ orow += rowstride;
+ }
+}
+
+
+static void rgb888alsb(GdkImage *image, art_u8 *pixels, int rowstride)
+{
+ int xx, yy;
+ int width, height;
+ int bpl;
+
+ unsigned char *s; /* for byte order swapping */
+ unsigned char *o;
unsigned char *srow = image->mem, *orow = pixels;
- printf ("32 bits/pixel\n");
+ width = image->width;
+ height = image->height;
+ bpl = image->bpl;
+
+ d(printf ("32 bits/pixel with alpha\n"));
+
+ /* lsb data */
+ for (yy = 0; yy < height; yy++) {
+ s = srow;
+ o = orow;
+ for (xx = 0; xx < width; xx++) {
+ *o++ = s[2];
+ *o++ = s[1];
+ *o++ = s[0];
+ *o++ = 0xff;
+ s += 4;
+ }
+ srow += bpl;
+ orow += rowstride;
+ }
+}
+
+static void rgb888lsb(GdkImage *image, art_u8 *pixels, int rowstride)
+{
+ int xx, yy;
+ int width, height;
+ int bpl;
+
+ unsigned char *srow = image->mem, *orow = pixels;
+ unsigned char *o, *s;
+
+ width = image->width;
+ height = image->height;
+ bpl = image->bpl;
+
+ d(printf("32 bit, lsb, no alpha\n"));
+
+ for (yy = 0; yy < height; yy++) {
+ s = srow;
+ o = orow;
+ for (xx = 0; xx < width; xx++) {
+ *o++ = s[2];
+ *o++ = s[1];
+ *o++ = s[0];
+ s += 4;
+ }
+ srow += bpl;
+ orow += rowstride;
+ }
+}
- for (yy = 0; yy < height; yy++)
- {
- s = srow;
- o = orow;
+static void rgb888amsb(GdkImage *image, art_u8 *pixels, int rowstride)
+{
+ int xx, yy;
+ int width, height;
+ int bpl;
- if (image->byte_order == GDK_LSB_FIRST)
- {
-#ifdef HAIRY_32
- for (xx = 0; xx < width; xx += 2)
- {
+ unsigned char *srow = image->mem, *orow = pixels;
+#ifdef LITTLE
+ unsigned long *o;
+ unsigned long *s;
#else
- for (xx = 0; xx < width; xx++)
- {
+ unsigned char *s; /* for byte order swapping */
+ unsigned char *o;
#endif
- /* read/convert 2 pixels at a time */
- /* little endian, lsb data */
-#ifdef SIMPLE_32
- *o++ = s[2];
- *o++ = s[1];
- *o++ = s[0];
- s += 4;
-#else
+ d(printf("32 bit, msb, with alpha\n"));
+
+ width = image->width;
+ height = image->height;
+ bpl = image->bpl;
+ /* msb data */
+ for (yy = 0; yy < height; yy++) {
#ifdef LITTLE
-#ifdef HAIRY_32
- data = *s++;
- data2 = *s++;
+ s = (unsigned long *)srow;
+ o = (unsigned long *)orow;
#else
- data = *s++;
+ s = srow;
+ o = orow;
#endif
-#else
- /* big endian, lsb data */
- /* swap endianness first */
- data = (unsigned long) ((unsigned char *) s)[3] << 24
- | (unsigned long) ((unsigned char *) s)[2] << 16
- | (unsigned long) ((unsigned char *) s)[1] << 8
- | (unsigned long) ((unsigned char *) s)[0];
- s++;
-#endif
-#ifdef HAIRY_32
- *o++ = (data & 0xff0000) >> 16 | (data & 0xff00);
- *o++ = (data & 0xff) | (data2 & 0xff0000) >> 8;
- *o++ = ((data2 & 0xff00) >> 8) | (data2 & 0xff) << 8;
-#else
- /* FIXME: endianness conversion can be done here .. doh! */
- *o++ = data & 0xff0000 >> 16;
- *o++ = data & 0x00ff00 >> 8;
- *o++ = data & 0x0000ff;
-#endif
-
-#endif /* SIMPLE_32 */
- }
- }
- else
- {
- for (xx = 0; xx < width; xx++)
- {
- /* read/convert 2 pixels at a time */
+ for (xx = 0; xx < width; xx++) {
#ifdef LITTLE
- /* little endian, msb data */
- /* swap endianness first */
-#if 1 /* which is faster?? */
- data = (unsigned long) ((unsigned char *) s)[0] << 24
- | (unsigned long) ((unsigned char *) s)[1] << 16
- | (unsigned long) ((unsigned char *) s)[2] << 8
- | (unsigned long) ((unsigned char *) s)[3];
- s++;
-#else /* this is probably slower */
- data = *s++;
- data = ((data >> 16) & 0xffff) | ((data & 0xffff) << 16);
- data =
- ((data & 0xff00ff00) >> 8) | ((data & 0xff00ff) << 8);
-#endif
+ *o++ = s[1];
+ *o++ = s[2];
+ *o++ = s[3];
+ *o++ = 0xff;
+ s += 4;
#else
- /* big endian, lsb data */
- data = *s++;
-#endif
- /* FIXME: endianness conversion can be done here .. doh! */
- *o++ = data & 0xff0000 >> 16;
- *o++ = data & 0x00ff00 >> 8;
- *o++ = data & 0x0000ff;
- }
- }
- srow += bpl;
- orow += rowstride;
- }
- break;
- }
- default:
- g_warning ("gdk_pixbuf_from_drawable: Unsupported image format\n");
- }
-
- gdk_image_destroy (image);
-
- art_pixbuf =
- with_alpha ? art_pixbuf_new_rgba (buff, width, height,
- rowstride) : art_pixbuf_new_rgb (buff,
- width,
- height,
- rowstride);
-
- return gdk_pixbuf_new_from_art_pixbuf (art_pixbuf);
+ *o++ = (*s <<8 ) | 0xff; /* untested */
+ s++;
+#endif
+ }
+ srow += bpl;
+ orow += rowstride;
+ }
}
-/* Public functions */
+static void rgb888msb(GdkImage *image, art_u8 *pixels, int rowstride)
+{
+ int xx, yy;
+ int width, height;
+ int bpl;
+
+ unsigned char *srow = image->mem, *orow = pixels;
+ unsigned char *s;
+ unsigned char *o;
+
+ d(printf("32 bit, msb, no alpha\n"));
+
+ width = image->width;
+ height = image->height;
+ bpl = image->bpl;
+
+ for (yy = 0; yy < height; yy++) {
+ s = srow;
+ o = orow;
+ for (xx = 0; xx < width; xx++) {
+ *o++ = s[1];
+ *o++ = s[2];
+ *o++ = s[3];
+ s += 4;
+ }
+ srow += bpl;
+ orow += rowstride;
+ }
+}
+
+typedef void (*cfunc) (GdkImage *image, art_u8 *pixels, int rowstride);
+
+static cfunc convert_map[] = {
+ rgb1,rgb1,rgb1a,rgb1a,
+ rgb8,rgb8,rgb8a,rgb8a,
+ rgb555lsb,rgb555msb,rgb555alsb,rgb555amsb,
+ rgb565lsb,rgb565msb,rgb565alsb,rgb565amsb,
+ rgb888lsb,rgb888msb,rgb888alsb,rgb888amsb
+};
+
+/*
+ perform actual conversion
+*/
+static void rgbconvert(GdkImage *image, art_u8 *pixels, int rowstride, int alpha)
+{
+ int index = (image->byte_order == GDK_MSB_FIRST)
+ | (alpha!=0) << 1;
+ int bank=0;
+
+ switch (image->depth) {
+ case 1: bank = 0; break;
+ case 8: bank = 1; break;
+ case 15: bank = 2; break;
+ case 16: bank = 3; break;
+ case 24:
+ case 32: bank = 4; break;
+ }
+ index |= bank<<2;
+ convert_map[index](image, pixels, rowstride);
+}
+
+static GdkPixbuf *
+gdk_pixbuf_from_drawable_core (GdkPixmap * window, gint x, gint y, gint width,
+ gint height, gint with_alpha)
+{
+ GdkImage *image;
+ ArtPixBuf *art_pixbuf;
+ art_u8 *buff;
+ art_u8 *pixels;
+ gint rowstride;
+ gint fatness;
+ gint screen_width, screen_height;
+ gint window_width, window_height, window_x, window_y;
+ int bpl;
+
+ g_return_val_if_fail (window != NULL, NULL);
+
+ /* always returns image in ZPixmap format ... */
+ image = gdk_image_get (window, x, y, width, height);
+
+ fatness = with_alpha ? 4 : 3;
+ rowstride = width * fatness;
+
+ buff = art_alloc (rowstride * height);
+ pixels = buff;
+#if 0
+ printf ("bpp = %d\n", image->bpp);
+ printf ("depth = %d\n", image->depth);
+ printf ("byte order = %d\n", image->byte_order);
+ printf ("bytes/line = %d\n", image->bpl);
+#endif
+
+ bpl = image->bpl;
+
+ rgbconvert(image, pixels, rowstride, with_alpha);
+ gdk_image_destroy (image);
+
+ if (with_alpha)
+ art_pixbuf = art_pixbuf_new_rgba (buff, width, height, rowstride);
+ else
+ art_pixbuf = art_pixbuf_new_rgb (buff, width, height, rowstride);
+
+ return gdk_pixbuf_new_from_art_pixbuf (art_pixbuf);
+}
+
+/* Public functions */
+
GdkPixbuf *
gdk_pixbuf_rgb_from_drawable (GdkWindow * window, gint x, gint y, gint width,
gint height)
@@ -504,3 +907,9 @@ gdk_pixbuf_rgba_from_drawable (GdkWindow * window, gint x, gint y, gint width,
{
return gdk_pixbuf_from_drawable_core (window, x, y, width, height, 1);
}
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */