diff options
author | Michael Zucchi <zucchi@zedzone.mmc.com.au> | 1999-11-20 05:39:54 +0000 |
---|---|---|
committer | Michael Zucci <zucchi@src.gnome.org> | 1999-11-20 05:39:54 +0000 |
commit | 7b4d53a529246c379c99a9a0e5d8742217447457 (patch) | |
tree | ef22479af93717ece803c3bf4af57028a3cafe89 /gdk/gdkpixbuf-drawable.c | |
parent | 8e06c4d7f4338ab0061609b62488ce8ecbc05c07 (diff) | |
download | gtk+-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.c | 1161 |
1 files changed, 785 insertions, 376 deletions
diff --git a/gdk/gdkpixbuf-drawable.c b/gdk/gdkpixbuf-drawable.c index 0dd668406c..b2af116aef 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: + */ |