]> Pileus Git - ~andy/gtk/blob - gdk/gdkpixbuf-drawable.c
#include <config.h>, and fix includes.
[~andy/gtk] / gdk / gdkpixbuf-drawable.c
1 /*
2  * Creates an GdkPixbuf from a Drawable
3  *
4  * Authors:
5  *   Cody Russell <bratsche@dfw.net>
6  *   Michael Zucchi  <zucchi@zedzone.mmc.com.au>
7  *
8  * This is licensed software, see the file COPYING for
9  * details.
10  */
11
12 #include <config.h>
13 #include <stdio.h>
14 #include <string.h>
15 #include <glib.h>
16 #include <gmodule.h>
17 #include "gdk-pixbuf.h"
18 #include "gdk-pixbuf-drawable.h"
19
20
21 #if (G_BYTE_ORDER == G_LITTLE_ENDIAN)
22 #define LITTLE
23 #endif
24 #define d(x)
25
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,
35         0xffffffff
36 };
37
38 /*
39   convert 1 bits-pixel data
40   no alpha
41 */
42 static void rgb1(GdkImage *image, art_u8 *pixels, int rowstride)
43 {
44         int xx, yy;
45         int width, height;
46         int bpl;
47         unsigned char *s;
48         register unsigned char data;
49         unsigned char *o;
50         unsigned char *srow = image->mem, *orow = pixels;
51         GdkColormap *colormap;  
52
53         d (printf ("1 bits/pixel\n"));
54
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? */
58         width = image->width;
59         height = image->height;
60         bpl = image->bpl;
61         
62         colormap = gdk_rgb_get_cmap ();
63
64         for (yy = 0; yy < height; yy++) {
65                 s = srow;
66                 o = orow;
67                 
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;
73                 }
74                 srow += bpl;
75                 orow += rowstride;
76         }
77 }
78
79 /*
80   convert 1 bits/pixel data
81   with alpha
82 */
83 static void rgb1a(GdkImage *image, art_u8 *pixels, int rowstride)
84 {
85         int xx, yy;
86         int width, height;
87         int bpl;
88         unsigned char *s;
89         register unsigned char data;
90         unsigned char *o;
91         unsigned char *srow = image->mem, *orow = pixels;
92         unsigned long remap[2];
93         GdkColormap *colormap;  
94
95         d (printf ("1 bits/pixel\n"));
96
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;
102         bpl = image->bpl;
103         
104         colormap = gdk_rgb_get_cmap ();
105
106         for (xx=0;xx<2;xx++) {
107 #ifdef LITTLE
108                 remap[xx] = 0xff000000
109                         | colormap->colors[xx].blue<<16
110                         | colormap->colors[xx].green<<8
111                         | colormap->colors[xx].red;
112 #else
113                 remap[xx] = 0xff
114                         | colormap->colors[xx].red<<24
115                         | colormap->colors[xx].green<<16
116                         | colormap->colors[xx].red<<8;
117 #endif
118         }
119
120         for (yy = 0; yy < height; yy++) {
121                 s = srow;
122                 o = orow;
123                 
124                 for (xx = 0; xx < width; xx ++) {
125                         data = srow[xx>>3] >> (7 - (xx & 7)) & 1;
126                         *o++ = remap[data];
127                 }
128                 srow += bpl;
129                 orow += rowstride;
130         }
131 }
132
133 /*
134   convert 8 bits/pixel data
135   no alpha
136 */
137 static void rgb8(GdkImage *image, art_u8 *pixels, int rowstride)
138 {
139         int xx, yy;
140         int width, height;
141         int bpl;
142         unsigned long mask;
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;  
148         
149         width = image->width;
150         height = image->height;
151         bpl = image->bpl;
152
153         d(printf("8 bit, no alpha output\n"));
154         
155         colormap = gdk_rgb_get_cmap ();
156         mask = mask_table[image->depth];
157
158         for (yy = 0;yy < height; yy++) {
159                 s = srow;
160                 o = orow;
161                 for (xx = 0; xx < width; xx++) {
162                         data = *s++ & mask;
163                         *o++ = colormap->colors[data].red;
164                         *o++ = colormap->colors[data].green;
165                         *o++ = colormap->colors[data].blue;
166                 }
167                 srow += bpl;
168                 orow += rowstride;
169         }
170 }
171
172 /*
173   convert 8 bits/pixel data
174   with alpha
175 */
176 static void rgb8a(GdkImage *image, art_u8 *pixels, int rowstride)
177 {
178         int xx, yy;
179         int width, height;
180         int bpl;
181         unsigned long mask;
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;
188         
189         width = image->width;
190         height = image->height;
191         bpl = image->bpl;
192
193         d(printf("8 bit, with alpha output\n"));
194         
195         colormap = gdk_rgb_get_cmap ();
196         mask = mask_table[image->depth];
197         
198         for (xx=0;xx<colormap->size;xx++) {
199 #ifdef LITTLE
200                 remap[xx] = 0xff000000
201                         | colormap->colors[xx].blue<<16
202                         | colormap->colors[xx].green<<8
203                         | colormap->colors[xx].red;
204 #else
205                 remap[xx] = 0xff
206                         | colormap->colors[xx].red<<24
207                         | colormap->colors[xx].green<<16
208                         | colormap->colors[xx].red<<8;
209 #endif
210         }
211         
212         for (yy = 0;yy < height; yy++) {
213                 s = srow;
214                 o = (unsigned long *)orow;
215                 for (xx = 0; xx < width; xx ++) {
216                         data = *s++ & mask;
217                         *o++ = remap[data];
218                 }
219                 srow += bpl;
220                 orow += rowstride;
221         }
222 }
223
224 /*
225   convert 16 bits/pixel data
226   no alpha
227   data in lsb format
228 */
229 static void rgb565lsb(GdkImage *image, art_u8 *pixels, int rowstride)
230 {
231         int xx, yy;
232         int width, height;
233         int bpl;
234         
235 #ifdef LITTLE
236         register unsigned long *s;      /* read 2 pixels at once */
237 #else
238         register unsigned char *s;      /* read 2 pixels at once */
239 #endif
240         register unsigned short *o;
241         unsigned char *srow = image->mem, *orow = pixels;
242         
243         width = image->width;
244         height = image->height;
245         bpl = image->bpl;
246         
247         for (yy = 0;yy < height; yy++) {
248 #ifdef LITTLE
249                 s = (unsigned long *)srow;
250 #else
251                 s = (unsigned char *)srow;
252 #endif
253                 o = (unsigned short *)orow;
254                 for (xx = 1; xx < width; xx += 2) {
255                         register unsigned long data;
256 #ifdef LITTLE
257                         data = *s++;
258                         *o++ = (data & 0xf800) >> 8 | (data & 0x7e0) << 5;
259                         *o++ = (data & 0x1f) << 3 | (data & 0xf8000000) >> 16;
260                         *o++ = ((data & 0x7e00000) >> 19) | (data & 0x1f0000) >> 5;
261 #else
262                         /* swap endianness first */
263                         data = s[0] | s[1]<<8 | s[2]<<16 | s[3]<<24;
264                         s+=4;
265                         *o++ = (data & 0xf800) | (data & 0x7e0) >> 3;
266                         *o++ = (data & 0x1f) << 11 | (data & 0xf8000000) >> 24;
267                         *o++ = ((data & 0x7e00000) >> 11) | (data & 0x1f0000) >> 13;
268 #endif
269                 }
270                 /* check for last remaining pixel */
271                 if (width & 1) {
272                         register unsigned short data;
273 #ifdef LITTLE
274                         data = *((short *) s);
275 #else
276                         data = *((short *) s);
277                         data = ((data >> 8) & 0xff) | ((data & 0xff) << 8);
278 #endif
279                         ((char *) o)[0] = (data >> 8) & 0xf8;
280                         ((char *) o)[1] = (data >> 3) & 0xfc;
281                         ((char *) o)[2] = (data << 3) & 0xf8;
282                 }
283                 srow += bpl;
284                 orow += rowstride;
285         }
286 }
287
288 /*
289   convert 16 bits/pixel data
290   no alpha
291   data in msb format
292 */
293 static void rgb565msb(GdkImage *image, art_u8 *pixels, int rowstride)
294 {
295         int xx, yy;
296         int width, height;
297         int bpl;
298         
299 #ifdef LITTLE
300         register unsigned char *s;      /* need to swap data order */
301 #else
302         register unsigned long *s;      /* read 2 pixels at once */
303 #endif
304         register unsigned short *o;
305         unsigned char *srow = image->mem, *orow = pixels;
306         
307         width = image->width;
308         height = image->height;
309         bpl = image->bpl;
310         
311         for (yy = 0;yy < height; yy++) {
312 #ifdef LITTLE
313                 s = srow;
314 #else
315                 s = (unsigned long *)srow;
316 #endif
317                 o = (unsigned short *)orow;
318                 for (xx = 1; xx < width; xx += 2) {
319                         register unsigned long data;
320 #ifdef LITTLE
321                         /* swap endianness first */
322                         data = s[0] | s[1]<<8 | s[2]<<16 | s[3]<<24;
323                         s+=4;
324                         *o++ = (data & 0xf800) >> 8 | (data & 0x7e0) << 5;
325                         *o++ = (data & 0x1f) << 3 | (data & 0xf8000000) >> 16;
326                         *o++ = ((data & 0x7e00000) >> 19) | (data & 0x1f0000) >> 5;
327 #else
328                         data = *s++;
329                         *o++ = (data & 0xf800) | (data & 0x7e0) >> 3;
330                         *o++ = (data & 0x1f) << 11 | (data & 0xf8000000) >> 24;
331                         *o++ = ((data & 0x7e00000) >> 11) | (data & 0x1f0000) >> 13;
332 #endif
333                 }
334                 /* check for last remaining pixel */
335                 if (width & 1) {
336                         register unsigned short data;
337 #ifdef LITTLE
338                         data = *((short *) s);
339                         data = ((data >> 8) & 0xff) | ((data & 0xff) << 8);
340 #else
341                         data = *((short *) s);
342 #endif
343                         ((char *) o)[0] = (data >> 8) & 0xf8;
344                         ((char *) o)[1] = (data >> 3) & 0xfc;
345                         ((char *) o)[2] = (data << 3) & 0xf8;
346                 }
347                 srow += bpl;
348                 orow += rowstride;
349         }
350 }
351
352 /*
353   convert 16 bits/pixel data
354   with alpha
355   data in lsb format
356 */
357 static void rgb565alsb(GdkImage *image, art_u8 *pixels, int rowstride)
358 {
359         int xx, yy;
360         int width, height;
361         int bpl;
362
363 #ifdef LITTLE
364         register unsigned short *s;     /* read 1 pixels at once */
365 #else
366         register unsigned char *s;
367 #endif
368         register unsigned long *o;
369         
370         unsigned char *srow = image->mem, *orow = pixels;
371         
372         width = image->width;
373         height = image->height;
374         bpl = image->bpl;
375         
376         for (yy = 0;yy < height; yy++) {
377 #ifdef LITTLE
378                 s = (unsigned short *)srow;
379 #else
380                 s = (unsigned char *)srow;
381 #endif
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 */
387 #ifdef LITTLE
388                         data = *s++;
389                         *o++ = (data & 0xf800) >>8 | (data & 0x7e0) << 5
390                                 | (data & 0x1f) << 19 | 0xff000000;
391 #else
392                         /* swap endianness first */
393                         data = s[0] | s[1]<<8;
394                         s+=2;
395                         *o++ = (data & 0xf800) << 16 | (data & 0x7e0) << 13
396                                 | (data & 0x1f) <<  11 | 0xff;
397 #endif
398                 }
399                 srow += bpl;
400                 orow += rowstride;
401         }
402 }
403
404 /*
405   convert 16 bits/pixel data
406   with alpha
407   data in msb format
408 */
409 static void rgb565amsb(GdkImage *image, art_u8 *pixels, int rowstride)
410 {
411         int xx, yy;
412         int width, height;
413         int bpl;
414
415 #ifdef LITTLE
416         register unsigned char *s;
417 #else
418         register unsigned short *s;     /* read 1 pixels at once */
419 #endif
420         register unsigned long *o;
421         
422         unsigned char *srow = image->mem, *orow = pixels;
423         
424         width = image->width;
425         height = image->height;
426         bpl = image->bpl;
427         
428         for (yy = 0;yy < height; yy++) {
429                 s = srow;
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 */
435 #ifdef LITTLE
436                         /* swap endianness first */
437                         data = s[0] | s[1]<<8;
438                         s+=2;
439                         *o++ = (data & 0xf800) >>8 | (data & 0x7e0) << 5
440                                 | (data & 0x1f) << 19 | 0xff000000;
441 #else
442                         data = *s++;
443                         *o++ = (data & 0xf800) << 16 | (data & 0x7e0) << 13
444                                 | (data & 0x1f) <<  11 | 0xff;
445 #endif
446                 }
447                 srow += bpl;
448                 orow += rowstride;
449         }
450 }
451
452 /*
453   convert 15 bits/pixel data
454   no alpha
455   data in lsb format
456 */
457 static void rgb555lsb(GdkImage *image, art_u8 *pixels, int rowstride)
458 {
459         int xx, yy;
460         int width, height;
461         int bpl;
462         
463 #ifdef LITTLE
464         register unsigned long *s;      /* read 2 pixels at once */
465 #else
466         register unsigned char *s;      /* read 2 pixels at once */
467 #endif
468         register unsigned short *o;
469         unsigned char *srow = image->mem, *orow = pixels;
470         
471         width = image->width;
472         height = image->height;
473         bpl = image->bpl;
474         
475         for (yy = 0;yy < height; yy++) {
476 #ifdef LITTLE
477                 s = (unsigned long *)srow;
478 #else
479                 s = srow;
480 #endif
481                 o = (unsigned short *)orow;
482                 for (xx = 1; xx < width; xx += 2) {
483                         register unsigned long data;
484 #ifdef LITTLE
485                         data = *s++;
486                         *o++ = (data & 0x7c00) >> 7 | (data & 0x3e0) << 6;
487                         *o++ = (data & 0x1f) << 3 | (data & 0x7c000000) >> 15;
488                         *o++ = ((data & 0x3e00000) >> 18) | (data & 0x1f0000) >> 5;
489 #else
490                         /* swap endianness first */
491                         data = s[0] | s[1]<<8 | s[2]<<16 | s[3]<<24;
492                         s+=4;
493                         *o++ = (data & 0x7c00) << 1 | (data & 0x3e0) >> 2;
494                         *o++ = (data & 0x1f) << 11 | (data & 0x7c000000) >> 23;
495                         *o++ = ((data & 0x3e00000) >> 10) | (data & 0x1f0000) >> 13;
496 #endif
497                 }
498                 /* check for last remaining pixel */
499                 if (width & 1) {
500                         register unsigned short data;
501 #ifdef LITTLE
502                         data = *((short *) s);
503 #else
504                         data = *((short *) s);
505                         data = ((data >> 8) & 0xff) | ((data & 0xff) << 8);
506 #endif
507                         ((char *) o)[0] = (data & 0x7c0) >> 7;
508                         ((char *) o)[1] = (data & 0x3e0) >> 2;
509                         ((char *) o)[2] = (data & 0x1f) << 3;
510                 }
511                 srow += bpl;
512                 orow += rowstride;
513         }
514 }
515
516 /*
517   convert 15 bits/pixel data
518   no alpha
519   data in msb format
520 */
521 static void rgb555msb(GdkImage *image, art_u8 *pixels, int rowstride)
522 {
523         int xx, yy;
524         int width, height;
525         int bpl;
526         
527 #ifdef LITTLE
528         register unsigned char *s;      /* read 2 pixels at once */
529 #else
530         register unsigned long *s;      /* read 2 pixels at once */
531 #endif
532         register unsigned short *o;
533         unsigned char *srow = image->mem, *orow = pixels;
534         
535         width = image->width;
536         height = image->height;
537         bpl = image->bpl;
538         
539         for (yy = 0;yy < height; yy++) {
540                 s = srow;
541                 o = (unsigned short *)orow;
542                 for (xx = 1; xx < width; xx += 2) {
543                         register unsigned long data;
544 #ifdef LITTLE
545                         /* swap endianness first */
546                         data = s[0] | s[1]<<8 | s[2]<<16 | s[3]<<24;
547                         s+=4;
548                         *o++ = (data & 0x7c00) >> 7 | (data & 0x3e0) << 6;
549                         *o++ = (data & 0x1f) << 3 | (data & 0x7c000000) >> 15;
550                         *o++ = ((data & 0x3e00000) >> 18) | (data & 0x1f0000) >> 5;
551 #else
552                         data = *s++;
553                         *o++ = (data & 0x7c00) << 1 | (data & 0x3e0) >> 2;
554                         *o++ = (data & 0x1f) << 11 | (data & 0x7c000000) >> 23;
555                         *o++ = ((data & 0x3e00000) >> 10) | (data & 0x1f0000) >> 13;
556 #endif
557                 }
558                 /* check for last remaining pixel */
559                 if (width & 1) {
560                         register unsigned short data;
561 #ifdef LITTLE
562                         data = *((short *) s);
563                         data = ((data >> 8) & 0xff) | ((data & 0xff) << 8);
564 #else
565                         data = *((short *) s);
566 #endif
567                         ((char *) o)[0] = (data & 0x7c0) >> 7;
568                         ((char *) o)[1] = (data & 0x3e0) >> 2;
569                         ((char *) o)[2] = (data & 0x1f) << 3;
570                 }
571                 srow += bpl;
572                 orow += rowstride;
573         }
574 }
575
576 /*
577   convert 15 bits/pixel data
578   with alpha
579   data in lsb format
580 */
581 static void rgb555alsb(GdkImage *image, art_u8 *pixels, int rowstride)
582 {
583         int xx, yy;
584         int width, height;
585         int bpl;
586
587 #ifdef LITTLE
588         register unsigned short *s;     /* read 1 pixels at once */
589 #else
590         register unsigned char *s;
591 #endif
592         register unsigned long *o;
593         
594         unsigned char *srow = image->mem, *orow = pixels;
595         
596         width = image->width;
597         height = image->height;
598         bpl = image->bpl;
599         
600         for (yy = 0;yy < height; yy++) {
601 #ifdef LITTLE
602                 s = (unsigned short *)srow;
603 #else
604                 s = srow;
605 #endif
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 */
611 #ifdef LITTLE
612                         data = *s++;
613                         *o++ = (data & 0x7c00) >>7 | (data & 0x3e0) << 6
614                                 | (data & 0x1f) << 19 | 0xff000000;
615 #else
616                         /* swap endianness first */
617                         data = s[0] | s[1]<<8;
618                         s+=2;
619                         *o++ = (data & 0x7c00) << 17 | (data & 0x3e0) << 14
620                                 | (data & 0x1f) <<  11 | 0xff;
621 #endif
622                 }
623                 srow += bpl;
624                 orow += rowstride;
625         }
626 }
627
628 /*
629   convert 15 bits/pixel data
630   with alpha
631   data in msb format
632 */
633 static void rgb555amsb(GdkImage *image, art_u8 *pixels, int rowstride)
634 {
635         int xx, yy;
636         int width, height;
637         int bpl;
638
639 #ifdef LITTLE
640         register unsigned short *s;     /* read 1 pixels at once */
641 #else
642         register unsigned char *s;
643 #endif
644         register unsigned long *o;
645         
646         unsigned char *srow = image->mem, *orow = pixels;
647         
648         width = image->width;
649         height = image->height;
650         bpl = image->bpl;
651         
652         for (yy = 0;yy < height; yy++) {
653 #ifdef LITTLE
654                 s = (unsigned short *)srow;
655 #else
656                 s = srow;
657 #endif
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 */
663 #ifdef LITTLE
664                         /* swap endianness first */
665                         data = s[0] | s[1]<<8;
666                         s+=2;
667                         *o++ = (data & 0x7c00) >>7 | (data & 0x3e0) << 6
668                                 | (data & 0x1f) << 19 | 0xff000000;
669 #else
670                         data = *s++;
671                         *o++ = (data & 0x7c00) << 17 | (data & 0x3e0) << 14
672                                 | (data & 0x1f) <<  11 | 0xff;
673 #endif
674                 }
675                 srow += bpl;
676                 orow += rowstride;
677         }
678 }
679
680
681 static void rgb888alsb(GdkImage *image, art_u8 *pixels, int rowstride)
682 {
683         int xx, yy;
684         int width, height;
685         int bpl;
686
687         unsigned char *s;       /* for byte order swapping */
688         unsigned char *o;
689         unsigned char *srow = image->mem, *orow = pixels;
690
691         width = image->width;
692         height = image->height;
693         bpl = image->bpl;
694         
695         d(printf ("32 bits/pixel with alpha\n"));
696         
697         /* lsb data */
698         for (yy = 0; yy < height; yy++) {
699                 s = srow;
700                 o = orow;
701                 for (xx = 0; xx < width; xx++) {
702                         *o++ = s[2];
703                         *o++ = s[1];
704                         *o++ = s[0];
705                         *o++ = 0xff;
706                         s += 4;
707                 }
708                 srow += bpl;
709                 orow += rowstride;
710         }
711 }
712
713 static void rgb888lsb(GdkImage *image, art_u8 *pixels, int rowstride)
714 {
715         int xx, yy;
716         int width, height;
717         int bpl;
718
719         unsigned char *srow = image->mem, *orow = pixels;
720         unsigned char *o, *s;
721
722         width = image->width;
723         height = image->height;
724         bpl = image->bpl;
725
726         d(printf("32 bit, lsb, no alpha\n"));
727
728         for (yy = 0; yy < height; yy++) {
729                 s = srow;
730                 o = orow;
731                 for (xx = 0; xx < width; xx++) {
732                         *o++ = s[2];
733                         *o++ = s[1];
734                         *o++ = s[0];
735                         s += 4;
736                 }
737                 srow += bpl;
738                 orow += rowstride;
739         }
740 }
741
742 static void rgb888amsb(GdkImage *image, art_u8 *pixels, int rowstride)
743 {
744         int xx, yy;
745         int width, height;
746         int bpl;
747
748         unsigned char *srow = image->mem, *orow = pixels;
749 #ifdef LITTLE
750         unsigned long *o;
751         unsigned long *s;
752 #else
753         unsigned char *s;       /* for byte order swapping */
754         unsigned char *o;
755 #endif
756
757         d(printf("32 bit, msb, with alpha\n"));
758
759         width = image->width;
760         height = image->height;
761         bpl = image->bpl;
762
763         /* msb data */
764         for (yy = 0; yy < height; yy++) {
765 #ifdef LITTLE
766                 s = (unsigned long *)srow;
767                 o = (unsigned long *)orow;
768 #else
769                 s = srow;
770                 o = orow;
771 #endif
772                 for (xx = 0; xx < width; xx++) {
773 #ifdef LITTLE
774                         *o++ = s[1];
775                         *o++ = s[2];
776                         *o++ = s[3];
777                         *o++ = 0xff;
778                         s += 4;
779 #else
780                         *o++ = (*s <<8 ) | 0xff; /* untested */
781                         s++;
782 #endif
783                 }
784                 srow += bpl;
785                 orow += rowstride;
786         }
787 }
788
789 static void rgb888msb(GdkImage *image, art_u8 *pixels, int rowstride)
790 {
791         int xx, yy;
792         int width, height;
793         int bpl;
794
795         unsigned char *srow = image->mem, *orow = pixels;
796         unsigned char *s;
797         unsigned char *o;
798
799         d(printf("32 bit, msb, no alpha\n"));
800
801         width = image->width;
802         height = image->height;
803         bpl = image->bpl;
804
805         for (yy = 0; yy < height; yy++) {
806                 s = srow;
807                 o = orow;
808                 for (xx = 0; xx < width; xx++) {
809                         *o++ = s[1];
810                         *o++ = s[2];
811                         *o++ = s[3];
812                         s += 4;
813                 }
814                 srow += bpl;
815                 orow += rowstride;
816         }
817 }
818
819 typedef void (*cfunc) (GdkImage *image, art_u8 *pixels, int rowstride);
820
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
827 };
828
829 /*
830   perform actual conversion
831 */
832 static void rgbconvert(GdkImage *image, art_u8 *pixels, int rowstride, int alpha)
833 {
834         int index = (image->byte_order == GDK_MSB_FIRST)
835                 | (alpha!=0) << 1;
836         int bank=0;
837
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;
843         case 24:
844         case 32: bank = 4; break;
845         }
846         index |= bank<<2;
847         convert_map[index](image, pixels, rowstride);
848 }
849
850 static GdkPixbuf *
851 gdk_pixbuf_from_drawable_core (GdkPixmap * window, gint x, gint y, gint width,
852                                gint height, gint with_alpha)
853 {
854         GdkImage *image;
855         ArtPixBuf *art_pixbuf;
856         art_u8 *buff;
857         art_u8 *pixels;
858         gint rowstride;
859         gint fatness;
860         gint screen_width, screen_height;
861         gint window_width, window_height, window_x, window_y;
862         int bpl;
863         
864         g_return_val_if_fail (window != NULL, NULL);
865         
866         /* always returns image in ZPixmap format ... */
867         image = gdk_image_get (window, x, y, width, height);
868         
869         fatness = with_alpha ? 4 : 3;
870         rowstride = width * fatness;
871         
872         buff = art_alloc (rowstride * height);
873         pixels = buff;
874
875 #if 0
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);
880 #endif
881         
882         bpl = image->bpl;
883         
884         rgbconvert(image, pixels, rowstride, with_alpha);
885         gdk_image_destroy (image);
886         
887         if (with_alpha)
888                 art_pixbuf = art_pixbuf_new_rgba (buff, width, height, rowstride);
889         else
890                 art_pixbuf = art_pixbuf_new_rgb (buff, width, height, rowstride);
891         
892         return gdk_pixbuf_new_from_art_pixbuf (art_pixbuf);
893 }
894
895 /* Public functions */
896  
897 GdkPixbuf *
898 gdk_pixbuf_rgb_from_drawable (GdkWindow * window, gint x, gint y, gint width,
899                               gint height)
900 {
901   return gdk_pixbuf_from_drawable_core (window, x, y, width, height, 0);
902 }
903
904 GdkPixbuf *
905 gdk_pixbuf_rgba_from_drawable (GdkWindow * window, gint x, gint y, gint width,
906                                gint height)
907 {
908   return gdk_pixbuf_from_drawable_core (window, x, y, width, height, 1);
909 }
910
911 /*
912  * Local variables:
913  * c-basic-offset: 8
914  * End:
915  */