2 * Creates an GdkPixbuf from a Drawable
5 * Cody Russell <bratsche@dfw.net>
6 * Michael Zucchi <zucchi@zedzone.mmc.com.au>
8 * This is licensed software, see the file COPYING for
17 #include "gdk-pixbuf.h"
18 #include "gdk-pixbuf-drawable.h"
21 #if (G_BYTE_ORDER == G_LITTLE_ENDIAN)
26 static unsigned long mask_table[] = {
27 0x00000000, 0x00000001, 0x00000003, 0x00000007,
28 0x0000000f, 0x0000001f, 0x0000003f, 0x0000007f,
29 0x000000ff, 0x000001ff, 0x000003ff, 0x000007ff,
30 0x00000fff, 0x00001fff, 0x00003fff, 0x00007fff,
31 0x0000ffff, 0x0001ffff, 0x0003ffff, 0x0007ffff,
32 0x000fffff, 0x001fffff, 0x003fffff, 0x007fffff,
33 0x00ffffff, 0x01ffffff, 0x03ffffff, 0x07ffffff,
34 0x0fffffff, 0x1fffffff, 0x3fffffff, 0x7fffffff,
39 convert 1 bits-pixel data
42 static void rgb1(GdkImage *image, art_u8 *pixels, int rowstride)
48 register unsigned char data;
50 unsigned char *srow = image->mem, *orow = pixels;
51 GdkColormap *colormap;
53 d (printf ("1 bits/pixel\n"));
55 /* convert upto 8 pixels/time */
56 /* its probably not worth trying to make this run very fast, who uses
57 1 bit displays anymore? */
59 height = image->height;
62 colormap = gdk_rgb_get_cmap ();
64 for (yy = 0; yy < height; yy++) {
68 for (xx = 0; xx < width; xx ++) {
69 data = srow[xx>>3] >> (7 - (xx & 7)) & 1;
70 *o++ = colormap->colors[data].red;
71 *o++ = colormap->colors[data].green;
72 *o++ = colormap->colors[data].blue;
80 convert 1 bits/pixel data
83 static void rgb1a(GdkImage *image, art_u8 *pixels, int rowstride)
89 register unsigned char data;
91 unsigned char *srow = image->mem, *orow = pixels;
92 unsigned long remap[2];
93 GdkColormap *colormap;
95 d (printf ("1 bits/pixel\n"));
97 /* convert upto 8 pixels/time */
98 /* its probably not worth trying to make this run very fast, who uses
99 1 bit displays anymore? */
100 width = image->width;
101 height = image->height;
104 colormap = gdk_rgb_get_cmap ();
106 for (xx=0;xx<2;xx++) {
108 remap[xx] = 0xff000000
109 | colormap->colors[xx].blue<<16
110 | colormap->colors[xx].green<<8
111 | colormap->colors[xx].red;
114 | colormap->colors[xx].red<<24
115 | colormap->colors[xx].green<<16
116 | colormap->colors[xx].red<<8;
120 for (yy = 0; yy < height; yy++) {
124 for (xx = 0; xx < width; xx ++) {
125 data = srow[xx>>3] >> (7 - (xx & 7)) & 1;
134 convert 8 bits/pixel data
137 static void rgb8(GdkImage *image, art_u8 *pixels, int rowstride)
143 register unsigned long data;
144 unsigned char *srow = image->mem, *orow = pixels;
145 register unsigned char *s;
146 register unsigned char *o;
147 GdkColormap *colormap;
149 width = image->width;
150 height = image->height;
153 d(printf("8 bit, no alpha output\n"));
155 colormap = gdk_rgb_get_cmap ();
156 mask = mask_table[image->depth];
158 for (yy = 0;yy < height; yy++) {
161 for (xx = 0; xx < width; xx++) {
163 *o++ = colormap->colors[data].red;
164 *o++ = colormap->colors[data].green;
165 *o++ = colormap->colors[data].blue;
173 convert 8 bits/pixel data
176 static void rgb8a(GdkImage *image, art_u8 *pixels, int rowstride)
182 register unsigned long data;
183 GdkColormap *colormap;
184 unsigned long remap[256];
185 register unsigned char *s; /* read 2 pixels at once */
186 register unsigned long *o;
187 unsigned char *srow = image->mem, *orow = pixels;
189 width = image->width;
190 height = image->height;
193 d(printf("8 bit, with alpha output\n"));
195 colormap = gdk_rgb_get_cmap ();
196 mask = mask_table[image->depth];
198 for (xx=0;xx<colormap->size;xx++) {
200 remap[xx] = 0xff000000
201 | colormap->colors[xx].blue<<16
202 | colormap->colors[xx].green<<8
203 | colormap->colors[xx].red;
206 | colormap->colors[xx].red<<24
207 | colormap->colors[xx].green<<16
208 | colormap->colors[xx].red<<8;
212 for (yy = 0;yy < height; yy++) {
214 o = (unsigned long *)orow;
215 for (xx = 0; xx < width; xx ++) {
225 convert 16 bits/pixel data
229 static void rgb565lsb(GdkImage *image, art_u8 *pixels, int rowstride)
236 register unsigned long *s; /* read 2 pixels at once */
238 register unsigned char *s; /* read 2 pixels at once */
240 register unsigned short *o;
241 unsigned char *srow = image->mem, *orow = pixels;
243 width = image->width;
244 height = image->height;
247 for (yy = 0;yy < height; yy++) {
249 s = (unsigned long *)srow;
251 s = (unsigned char *)srow;
253 o = (unsigned short *)orow;
254 for (xx = 1; xx < width; xx += 2) {
255 register unsigned long data;
258 *o++ = (data & 0xf800) >> 8 | (data & 0x7e0) << 5;
259 *o++ = (data & 0x1f) << 3 | (data & 0xf8000000) >> 16;
260 *o++ = ((data & 0x7e00000) >> 19) | (data & 0x1f0000) >> 5;
262 /* swap endianness first */
263 data = s[0] | s[1]<<8 | s[2]<<16 | s[3]<<24;
265 *o++ = (data & 0xf800) | (data & 0x7e0) >> 3;
266 *o++ = (data & 0x1f) << 11 | (data & 0xf8000000) >> 24;
267 *o++ = ((data & 0x7e00000) >> 11) | (data & 0x1f0000) >> 13;
270 /* check for last remaining pixel */
272 register unsigned short data;
274 data = *((short *) s);
276 data = *((short *) s);
277 data = ((data >> 8) & 0xff) | ((data & 0xff) << 8);
279 ((char *) o)[0] = (data >> 8) & 0xf8;
280 ((char *) o)[1] = (data >> 3) & 0xfc;
281 ((char *) o)[2] = (data << 3) & 0xf8;
289 convert 16 bits/pixel data
293 static void rgb565msb(GdkImage *image, art_u8 *pixels, int rowstride)
300 register unsigned char *s; /* need to swap data order */
302 register unsigned long *s; /* read 2 pixels at once */
304 register unsigned short *o;
305 unsigned char *srow = image->mem, *orow = pixels;
307 width = image->width;
308 height = image->height;
311 for (yy = 0;yy < height; yy++) {
315 s = (unsigned long *)srow;
317 o = (unsigned short *)orow;
318 for (xx = 1; xx < width; xx += 2) {
319 register unsigned long data;
321 /* swap endianness first */
322 data = s[0] | s[1]<<8 | s[2]<<16 | s[3]<<24;
324 *o++ = (data & 0xf800) >> 8 | (data & 0x7e0) << 5;
325 *o++ = (data & 0x1f) << 3 | (data & 0xf8000000) >> 16;
326 *o++ = ((data & 0x7e00000) >> 19) | (data & 0x1f0000) >> 5;
329 *o++ = (data & 0xf800) | (data & 0x7e0) >> 3;
330 *o++ = (data & 0x1f) << 11 | (data & 0xf8000000) >> 24;
331 *o++ = ((data & 0x7e00000) >> 11) | (data & 0x1f0000) >> 13;
334 /* check for last remaining pixel */
336 register unsigned short data;
338 data = *((short *) s);
339 data = ((data >> 8) & 0xff) | ((data & 0xff) << 8);
341 data = *((short *) s);
343 ((char *) o)[0] = (data >> 8) & 0xf8;
344 ((char *) o)[1] = (data >> 3) & 0xfc;
345 ((char *) o)[2] = (data << 3) & 0xf8;
353 convert 16 bits/pixel data
357 static void rgb565alsb(GdkImage *image, art_u8 *pixels, int rowstride)
364 register unsigned short *s; /* read 1 pixels at once */
366 register unsigned char *s;
368 register unsigned long *o;
370 unsigned char *srow = image->mem, *orow = pixels;
372 width = image->width;
373 height = image->height;
376 for (yy = 0;yy < height; yy++) {
378 s = (unsigned short *)srow;
380 s = (unsigned char *)srow;
382 o = (unsigned long *)orow;
383 for (xx = 0; xx < width; xx ++) {
384 register unsigned long data;
385 /* rrrrrggg gggbbbbb -> rrrrr000 gggggg00 bbbbb000 aaaaaaaa */
386 /* little endian: aaaaaaaa bbbbb000 gggggg00 rrrrr000 */
389 *o++ = (data & 0xf800) >>8 | (data & 0x7e0) << 5
390 | (data & 0x1f) << 19 | 0xff000000;
392 /* swap endianness first */
393 data = s[0] | s[1]<<8;
395 *o++ = (data & 0xf800) << 16 | (data & 0x7e0) << 13
396 | (data & 0x1f) << 11 | 0xff;
405 convert 16 bits/pixel data
409 static void rgb565amsb(GdkImage *image, art_u8 *pixels, int rowstride)
416 register unsigned char *s;
418 register unsigned short *s; /* read 1 pixels at once */
420 register unsigned long *o;
422 unsigned char *srow = image->mem, *orow = pixels;
424 width = image->width;
425 height = image->height;
428 for (yy = 0;yy < height; yy++) {
430 o = (unsigned long *)orow;
431 for (xx = 0; xx < width; xx ++) {
432 register unsigned long data;
433 /* rrrrrggg gggbbbbb -> rrrrr000 gggggg00 bbbbb000 aaaaaaaa */
434 /* little endian: aaaaaaaa bbbbb000 gggggg00 rrrrr000 */
436 /* swap endianness first */
437 data = s[0] | s[1]<<8;
439 *o++ = (data & 0xf800) >>8 | (data & 0x7e0) << 5
440 | (data & 0x1f) << 19 | 0xff000000;
443 *o++ = (data & 0xf800) << 16 | (data & 0x7e0) << 13
444 | (data & 0x1f) << 11 | 0xff;
453 convert 15 bits/pixel data
457 static void rgb555lsb(GdkImage *image, art_u8 *pixels, int rowstride)
464 register unsigned long *s; /* read 2 pixels at once */
466 register unsigned char *s; /* read 2 pixels at once */
468 register unsigned short *o;
469 unsigned char *srow = image->mem, *orow = pixels;
471 width = image->width;
472 height = image->height;
475 for (yy = 0;yy < height; yy++) {
477 s = (unsigned long *)srow;
481 o = (unsigned short *)orow;
482 for (xx = 1; xx < width; xx += 2) {
483 register unsigned long data;
486 *o++ = (data & 0x7c00) >> 7 | (data & 0x3e0) << 6;
487 *o++ = (data & 0x1f) << 3 | (data & 0x7c000000) >> 15;
488 *o++ = ((data & 0x3e00000) >> 18) | (data & 0x1f0000) >> 5;
490 /* swap endianness first */
491 data = s[0] | s[1]<<8 | s[2]<<16 | s[3]<<24;
493 *o++ = (data & 0x7c00) << 1 | (data & 0x3e0) >> 2;
494 *o++ = (data & 0x1f) << 11 | (data & 0x7c000000) >> 23;
495 *o++ = ((data & 0x3e00000) >> 10) | (data & 0x1f0000) >> 13;
498 /* check for last remaining pixel */
500 register unsigned short data;
502 data = *((short *) s);
504 data = *((short *) s);
505 data = ((data >> 8) & 0xff) | ((data & 0xff) << 8);
507 ((char *) o)[0] = (data & 0x7c0) >> 7;
508 ((char *) o)[1] = (data & 0x3e0) >> 2;
509 ((char *) o)[2] = (data & 0x1f) << 3;
517 convert 15 bits/pixel data
521 static void rgb555msb(GdkImage *image, art_u8 *pixels, int rowstride)
528 register unsigned char *s; /* read 2 pixels at once */
530 register unsigned long *s; /* read 2 pixels at once */
532 register unsigned short *o;
533 unsigned char *srow = image->mem, *orow = pixels;
535 width = image->width;
536 height = image->height;
539 for (yy = 0;yy < height; yy++) {
541 o = (unsigned short *)orow;
542 for (xx = 1; xx < width; xx += 2) {
543 register unsigned long data;
545 /* swap endianness first */
546 data = s[0] | s[1]<<8 | s[2]<<16 | s[3]<<24;
548 *o++ = (data & 0x7c00) >> 7 | (data & 0x3e0) << 6;
549 *o++ = (data & 0x1f) << 3 | (data & 0x7c000000) >> 15;
550 *o++ = ((data & 0x3e00000) >> 18) | (data & 0x1f0000) >> 5;
553 *o++ = (data & 0x7c00) << 1 | (data & 0x3e0) >> 2;
554 *o++ = (data & 0x1f) << 11 | (data & 0x7c000000) >> 23;
555 *o++ = ((data & 0x3e00000) >> 10) | (data & 0x1f0000) >> 13;
558 /* check for last remaining pixel */
560 register unsigned short data;
562 data = *((short *) s);
563 data = ((data >> 8) & 0xff) | ((data & 0xff) << 8);
565 data = *((short *) s);
567 ((char *) o)[0] = (data & 0x7c0) >> 7;
568 ((char *) o)[1] = (data & 0x3e0) >> 2;
569 ((char *) o)[2] = (data & 0x1f) << 3;
577 convert 15 bits/pixel data
581 static void rgb555alsb(GdkImage *image, art_u8 *pixels, int rowstride)
588 register unsigned short *s; /* read 1 pixels at once */
590 register unsigned char *s;
592 register unsigned long *o;
594 unsigned char *srow = image->mem, *orow = pixels;
596 width = image->width;
597 height = image->height;
600 for (yy = 0;yy < height; yy++) {
602 s = (unsigned short *)srow;
606 o = (unsigned long *)orow;
607 for (xx = 0; xx < width; xx++) {
608 register unsigned long data;
609 /* rrrrrggg gggbbbbb -> rrrrr000 gggggg00 bbbbb000 aaaaaaaa */
610 /* little endian: aaaaaaaa bbbbb000 gggggg00 rrrrr000 */
613 *o++ = (data & 0x7c00) >>7 | (data & 0x3e0) << 6
614 | (data & 0x1f) << 19 | 0xff000000;
616 /* swap endianness first */
617 data = s[0] | s[1]<<8;
619 *o++ = (data & 0x7c00) << 17 | (data & 0x3e0) << 14
620 | (data & 0x1f) << 11 | 0xff;
629 convert 15 bits/pixel data
633 static void rgb555amsb(GdkImage *image, art_u8 *pixels, int rowstride)
640 register unsigned short *s; /* read 1 pixels at once */
642 register unsigned char *s;
644 register unsigned long *o;
646 unsigned char *srow = image->mem, *orow = pixels;
648 width = image->width;
649 height = image->height;
652 for (yy = 0;yy < height; yy++) {
654 s = (unsigned short *)srow;
658 o = (unsigned long *)orow;
659 for (xx = 0; xx < width; xx++) {
660 register unsigned long data;
661 /* rrrrrggg gggbbbbb -> rrrrr000 gggggg00 bbbbb000 aaaaaaaa */
662 /* little endian: aaaaaaaa bbbbb000 gggggg00 rrrrr000 */
664 /* swap endianness first */
665 data = s[0] | s[1]<<8;
667 *o++ = (data & 0x7c00) >>7 | (data & 0x3e0) << 6
668 | (data & 0x1f) << 19 | 0xff000000;
671 *o++ = (data & 0x7c00) << 17 | (data & 0x3e0) << 14
672 | (data & 0x1f) << 11 | 0xff;
681 static void rgb888alsb(GdkImage *image, art_u8 *pixels, int rowstride)
687 unsigned char *s; /* for byte order swapping */
689 unsigned char *srow = image->mem, *orow = pixels;
691 width = image->width;
692 height = image->height;
695 d(printf ("32 bits/pixel with alpha\n"));
698 for (yy = 0; yy < height; yy++) {
701 for (xx = 0; xx < width; xx++) {
713 static void rgb888lsb(GdkImage *image, art_u8 *pixels, int rowstride)
719 unsigned char *srow = image->mem, *orow = pixels;
720 unsigned char *o, *s;
722 width = image->width;
723 height = image->height;
726 d(printf("32 bit, lsb, no alpha\n"));
728 for (yy = 0; yy < height; yy++) {
731 for (xx = 0; xx < width; xx++) {
742 static void rgb888amsb(GdkImage *image, art_u8 *pixels, int rowstride)
748 unsigned char *srow = image->mem, *orow = pixels;
753 unsigned char *s; /* for byte order swapping */
757 d(printf("32 bit, msb, with alpha\n"));
759 width = image->width;
760 height = image->height;
764 for (yy = 0; yy < height; yy++) {
766 s = (unsigned long *)srow;
767 o = (unsigned long *)orow;
772 for (xx = 0; xx < width; xx++) {
780 *o++ = (*s <<8 ) | 0xff; /* untested */
789 static void rgb888msb(GdkImage *image, art_u8 *pixels, int rowstride)
795 unsigned char *srow = image->mem, *orow = pixels;
799 d(printf("32 bit, msb, no alpha\n"));
801 width = image->width;
802 height = image->height;
805 for (yy = 0; yy < height; yy++) {
808 for (xx = 0; xx < width; xx++) {
819 typedef void (*cfunc) (GdkImage *image, art_u8 *pixels, int rowstride);
821 static cfunc convert_map[] = {
822 rgb1,rgb1,rgb1a,rgb1a,
823 rgb8,rgb8,rgb8a,rgb8a,
824 rgb555lsb,rgb555msb,rgb555alsb,rgb555amsb,
825 rgb565lsb,rgb565msb,rgb565alsb,rgb565amsb,
826 rgb888lsb,rgb888msb,rgb888alsb,rgb888amsb
830 perform actual conversion
832 static void rgbconvert(GdkImage *image, art_u8 *pixels, int rowstride, int alpha)
834 int index = (image->byte_order == GDK_MSB_FIRST)
838 switch (image->depth) {
839 case 1: bank = 0; break;
840 case 8: bank = 1; break;
841 case 15: bank = 2; break;
842 case 16: bank = 3; break;
844 case 32: bank = 4; break;
847 convert_map[index](image, pixels, rowstride);
851 gdk_pixbuf_from_drawable_core (GdkPixmap * window, gint x, gint y, gint width,
852 gint height, gint with_alpha)
855 ArtPixBuf *art_pixbuf;
860 gint screen_width, screen_height;
861 gint window_width, window_height, window_x, window_y;
864 g_return_val_if_fail (window != NULL, NULL);
866 /* always returns image in ZPixmap format ... */
867 image = gdk_image_get (window, x, y, width, height);
869 fatness = with_alpha ? 4 : 3;
870 rowstride = width * fatness;
872 buff = art_alloc (rowstride * height);
876 printf ("bpp = %d\n", image->bpp);
877 printf ("depth = %d\n", image->depth);
878 printf ("byte order = %d\n", image->byte_order);
879 printf ("bytes/line = %d\n", image->bpl);
884 rgbconvert(image, pixels, rowstride, with_alpha);
885 gdk_image_destroy (image);
888 art_pixbuf = art_pixbuf_new_rgba (buff, width, height, rowstride);
890 art_pixbuf = art_pixbuf_new_rgb (buff, width, height, rowstride);
892 return gdk_pixbuf_new_from_art_pixbuf (art_pixbuf);
895 /* Public functions */
898 gdk_pixbuf_rgb_from_drawable (GdkWindow * window, gint x, gint y, gint width,
901 return gdk_pixbuf_from_drawable_core (window, x, y, width, height, 0);
905 gdk_pixbuf_rgba_from_drawable (GdkWindow * window, gint x, gint y, gint width,
908 return gdk_pixbuf_from_drawable_core (window, x, y, width, height, 1);