1
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2
/* GdkPixbuf library - convert X drawable information to RGB
4
* Copyright (C) 1999 Michael Zucchi
6
* Authors: Michael Zucchi <zucchi@zedzone.mmc.com.au>
7
* Cody Russell <bratsche@dfw.net>
8
* Federico Mena-Quintero <federico@gimp.org>
10
* This library is free software; you can redistribute it and/or
11
* modify it under the terms of the GNU Library General Public
12
* License as published by the Free Software Foundation; either
13
* version 2 of the License, or (at your option) any later version.
15
* This library is distributed in the hope that it will be useful,
16
* but WITHOUT ANY WARRANTY; without even the implied warranty of
17
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18
* Library General Public License for more details.
20
* You should have received a copy of the GNU Library General Public
21
* License along with this library; if not, write to the
22
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
23
* Boston, MA 02111-1307, USA.
26
/* Ported to Xlib by John Harper <john@dcs.warwick.ac.uk> */
32
#include "gdk-pixbuf-xlib-private.h"
34
#include <X11/Xutil.h>
36
#if (G_BYTE_ORDER == G_LITTLE_ENDIAN)
43
static const guint32 mask_table[] = {
44
0x00000000, 0x00000001, 0x00000003, 0x00000007,
45
0x0000000f, 0x0000001f, 0x0000003f, 0x0000007f,
46
0x000000ff, 0x000001ff, 0x000003ff, 0x000007ff,
47
0x00000fff, 0x00001fff, 0x00003fff, 0x00007fff,
48
0x0000ffff, 0x0001ffff, 0x0003ffff, 0x0007ffff,
49
0x000fffff, 0x001fffff, 0x003fffff, 0x007fffff,
50
0x00ffffff, 0x01ffffff, 0x03ffffff, 0x07ffffff,
51
0x0fffffff, 0x1fffffff, 0x3fffffff, 0x7fffffff,
58
typedef struct xlib_colormap_struct xlib_colormap;
59
struct xlib_colormap_struct {
66
static xlib_colormap *
67
xlib_get_colormap (Colormap id, Visual *visual)
70
xlib_colormap *xc = g_new (xlib_colormap, 1);
72
xc->size = visual->map_entries;
73
xc->colors = g_new (XColor, xc->size);
77
for (i = 0; i < xc->size; i++) {
78
xc->colors[i].pixel = i;
79
xc->colors[i].flags = DoRed | DoGreen | DoBlue;
82
XQueryColors (gdk_pixbuf_dpy, xc->colormap, xc->colors, xc->size);
88
xlib_colormap_free (xlib_colormap *xc)
94
/* from gdkvisual.c */
96
visual_decompose_mask (gulong mask,
103
while (!(mask & 0x1)) {
114
static gboolean x_error;
117
handle_x_error (Display *dpy, XErrorEvent *ev)
124
drawable_is_pixmap (Drawable d)
126
/* copied from Imlib */
129
XWindowAttributes wa;
132
errh = XSetErrorHandler (handle_x_error);
134
XGetWindowAttributes (gdk_pixbuf_dpy, d, &wa);
135
XSync (gdk_pixbuf_dpy, False);
137
XSetErrorHandler (errh);
145
convert 1 bits-pixel data
149
rgb1 (XImage *image, guchar *pixels, int rowstride, xlib_colormap *colormap)
154
register guint8 data;
156
guint8 *srow = (guint8 *)image->data, *orow = pixels;
158
d (printf ("1 bits/pixel\n"));
160
/* convert upto 8 pixels/time */
161
/* its probably not worth trying to make this run very fast, who uses
162
1 bit displays anymore? */
163
width = image->width;
164
height = image->height;
165
bpl = image->bytes_per_line;
167
for (yy = 0; yy < height; yy++) {
170
for (xx = 0; xx < width; xx ++) {
171
data = srow[xx >> 3] >> (7 - (xx & 7)) & 1;
172
*o++ = colormap->colors[data].red;
173
*o++ = colormap->colors[data].green;
174
*o++ = colormap->colors[data].blue;
182
convert 1 bits/pixel data
186
rgb1a (XImage *image, guchar *pixels, int rowstride, xlib_colormap *colormap)
191
register guint8 data;
193
guint8 *srow = (guint8 *)image->data, *orow = pixels;
196
d (printf ("1 bits/pixel\n"));
198
/* convert upto 8 pixels/time */
199
/* its probably not worth trying to make this run very fast, who uses
200
1 bit displays anymore? */
201
width = image->width;
202
height = image->height;
203
bpl = image->bytes_per_line;
205
for (xx = 0; xx < 2; xx++) {
207
remap[xx] = 0xff000000
208
| colormap->colors[xx].blue << 16
209
| colormap->colors[xx].green << 8
210
| colormap->colors[xx].red;
213
| colormap->colors[xx].red << 24
214
| colormap->colors[xx].green << 16
215
| colormap->colors[xx].blue << 8;
219
for (yy = 0; yy < height; yy++) {
222
for (xx = 0; xx < width; xx ++) {
223
data = srow[xx >> 3] >> (7 - (xx & 7)) & 1;
232
convert 8 bits/pixel data
236
rgb8 (XImage *image, guchar *pixels, int rowstride, xlib_colormap *colormap)
242
register guint32 data;
243
guint8 *srow = (guint8 *)image->data, *orow = pixels;
247
width = image->width;
248
height = image->height;
249
bpl = image->bytes_per_line;
251
d (printf ("8 bit, no alpha output\n"));
253
mask = mask_table[image->depth];
255
for (yy = 0; yy < height; yy++) {
258
for (xx = 0; xx < width; xx++) {
260
*o++ = colormap->colors[data].red;
261
*o++ = colormap->colors[data].green;
262
*o++ = colormap->colors[data].blue;
270
convert 8 bits/pixel data
274
rgb8a (XImage *image, guchar *pixels, int rowstride, xlib_colormap *colormap)
280
register guint32 data;
282
register guint8 *s; /* read 2 pixels at once */
284
guint8 *srow = (guint8 *)image->data, *orow = pixels;
286
width = image->width;
287
height = image->height;
288
bpl = image->bytes_per_line;
290
d (printf ("8 bit, with alpha output\n"));
292
mask = mask_table[image->depth];
294
for (xx = 0; xx < colormap->size; xx++) {
296
remap[xx] = 0xff000000
297
| colormap->colors[xx].blue << 16
298
| colormap->colors[xx].green << 8
299
| colormap->colors[xx].red;
302
| colormap->colors[xx].red << 24
303
| colormap->colors[xx].green << 16
304
| colormap->colors[xx].blue << 8;
308
for (yy = 0; yy < height; yy++) {
310
o = (guint32 *) orow;
311
for (xx = 0; xx < width; xx ++) {
321
convert 16 bits/pixel data
326
rgb565lsb (XImage *image, guchar *pixels, int rowstride, xlib_colormap *colormap)
333
register guint32 *s; /* read 2 pixels at once */
335
register guint8 *s; /* read 2 pixels at once */
338
guint8 *srow = (guint8 *)image->data, *orow = pixels;
340
width = image->width;
341
height = image->height;
342
bpl = image->bytes_per_line;
344
for (yy = 0; yy < height; yy++) {
346
s = (guint32 *) srow;
350
o = (guint16 *) orow;
351
for (xx = 1; xx < width; xx += 2) {
352
register guint32 data;
355
*o++ = (data & 0xf800) >> 8 | (data & 0xe000) >> 13
356
| (data & 0x7e0) << 5 | (data & 0x600) >> 1;
357
*o++ = (data & 0x1f) << 3 | (data & 0x1c) >> 2
358
| (data & 0xf8000000) >> 16 | (data & 0xe0000000) >> 21;
359
*o++ = (data & 0x7e00000) >> 19 | (data & 0x6000000) >> 25
360
| (data & 0x1f0000) >> 5 | (data & 0x1c0000) >> 10;
362
/* swap endianness first */
363
data = s[1] | s[0] << 8 | s[3] << 16 | s[2] << 24;
365
*o++ = (data & 0xf800) | (data & 0xe000) >> 5
366
| (data & 0x7e0) >> 3 | (data & 0x600) >> 9;
367
*o++ = (data & 0x1f) << 11 | (data & 0x1c) << 6
368
| (data & 0xf8000000) >> 24 | (data & 0xe0000000) >> 29;
369
*o++ = (data & 0x7e00000) >> 11 | (data & 0x6000000) >> 17
370
| (data & 0x1f0000) >> 13 | (data & 0x1c0000) >> 18;
373
/* check for last remaining pixel */
375
register guint16 data;
377
data = *((short *) s);
379
data = *((short *) s);
380
data = ((data >> 8) & 0xff) | ((data & 0xff) << 8);
382
((char *) o)[0] = ((data >> 8) & 0xf8) | ((data >> 13) & 0x7);
383
((char *) o)[1] = ((data >> 3) & 0xfc) | ((data >> 9) & 0x3);
384
((char *) o)[2] = ((data << 3) & 0xf8) | ((data >> 2) & 0x7);
392
convert 16 bits/pixel data
397
rgb565msb (XImage *image, guchar *pixels, int rowstride, xlib_colormap *colormap)
404
register guint8 *s; /* need to swap data order */
406
register guint32 *s; /* read 2 pixels at once */
409
guint8 *srow = (guint8 *)image->data, *orow = pixels;
411
width = image->width;
412
height = image->height;
413
bpl = image->bytes_per_line;
415
for (yy = 0; yy < height; yy++) {
419
s = (guint32 *) srow;
421
o = (guint16 *) orow;
422
for (xx = 1; xx < width; xx += 2) {
423
register guint32 data;
425
/* swap endianness first */
426
data = s[1] | s[0] << 8 | s[3] << 16 | s[2] << 24;
428
*o++ = (data & 0xf800) >> 8 | (data & 0xe000) >> 13
429
| (data & 0x7e0) << 5 | (data & 0x600) >> 1;
430
*o++ = (data & 0x1f) << 3 | (data & 0x1c) >> 2
431
| (data & 0xf8000000) >> 16 | (data & 0xe0000000) >> 21;
432
*o++ = (data & 0x7e00000) >> 19 | (data & 0x6000000) >> 25
433
| (data & 0x1f0000) >> 5 | (data & 0x1c0000) >> 10;
436
*o++ = (data & 0xf800) | (data & 0xe000) >> 5
437
| (data & 0x7e0) >> 3 | (data & 0x600) >> 9;
438
*o++ = (data & 0x1f) << 11 | (data & 0x1c) << 6
439
| (data & 0xf8000000) >> 24 | (data & 0xe0000000) >> 29;
440
*o++ = (data & 0x7e00000) >> 11 | (data & 0x6000000) >> 17
441
| (data & 0x1f0000) >> 13 | (data & 0x1c0000) >> 18;
444
/* check for last remaining pixel */
446
register guint16 data;
448
data = *((short *) s);
449
data = ((data >> 8) & 0xff) | ((data & 0xff) << 8);
451
data = *((short *) s);
453
((char *) o)[0] = ((data >> 8) & 0xf8) | ((data >> 13) & 0x7);
454
((char *) o)[1] = ((data >> 3) & 0xfc) | ((data >> 9) & 0x3);
455
((char *) o)[2] = ((data << 3) & 0xf8) | ((data >> 2) & 0x7);
463
convert 16 bits/pixel data
468
rgb565alsb (XImage *image, guchar *pixels, int rowstride, xlib_colormap *colormap)
475
register guint16 *s; /* read 1 pixels at once */
481
guint8 *srow = (guint8 *)image->data, *orow = pixels;
483
width = image->width;
484
height = image->height;
485
bpl = image->bytes_per_line;
487
for (yy = 0; yy < height; yy++) {
489
s = (guint16 *) srow;
493
o = (guint32 *) orow;
494
for (xx = 0; xx < width; xx ++) {
495
register guint32 data;
496
/* rrrrrggg gggbbbbb -> rrrrrRRR ggggggGG bbbbbBBB aaaaaaaa */
497
/* little endian: aaaaaaaa bbbbbBBB ggggggGG rrrrrRRR */
500
*o++ = (data & 0xf800) >> 8 | (data & 0xe000) >> 13
501
| (data & 0x7e0) << 5 | (data & 0x600) >> 1
502
| (data & 0x1f) << 19 | (data & 0x1c) << 14
505
/* swap endianness first */
506
data = s[0] | s[1] << 8;
508
*o++ = (data & 0xf800) << 16 | (data & 0xe000) << 11
509
| (data & 0x7e0) << 13 | (data & 0x600) << 7
510
| (data & 0x1f) << 11 | (data & 0x1c) << 6
520
convert 16 bits/pixel data
525
rgb565amsb (XImage *image, guchar *pixels, int rowstride, xlib_colormap *colormap)
534
register guint16 *s; /* read 1 pixels at once */
538
guint8 *srow = (guint8 *)image->data, *orow = pixels;
540
width = image->width;
541
height = image->height;
542
bpl = image->bytes_per_line;
544
for (yy = 0; yy < height; yy++) {
548
s = (guint16 *) srow;
550
o = (guint32 *) orow;
551
for (xx = 0; xx < width; xx ++) {
552
register guint32 data;
553
/* rrrrrggg gggbbbbb -> rrrrrRRR gggggg00 bbbbbBBB aaaaaaaa */
554
/* little endian: aaaaaaaa bbbbbBBB gggggg00 rrrrrRRR */
556
/* swap endianness first */
557
data = s[0] | s[1] << 8;
559
*o++ = (data & 0xf800) >> 8 | (data & 0xe000) >> 13
560
| (data & 0x7e0) << 5 | (data & 0x600) >> 1
561
| (data & 0x1f) << 19 | (data & 0x1c) << 14
565
*o++ = (data & 0xf800) << 16 | (data & 0xe000) << 11
566
| (data & 0x7e0) << 13 | (data & 0x600) << 7
567
| (data & 0x1f) << 11 | (data & 0x1c) << 6
577
convert 15 bits/pixel data
582
rgb555lsb (XImage *image, guchar *pixels, int rowstride, xlib_colormap *colormap)
589
register guint32 *s; /* read 2 pixels at once */
591
register guint8 *s; /* read 2 pixels at once */
594
guint8 *srow = (guint8 *)image->data, *orow = pixels;
596
width = image->width;
597
height = image->height;
598
bpl = image->bytes_per_line;
600
for (yy = 0; yy < height; yy++) {
602
s = (guint32 *) srow;
606
o = (guint16 *) orow;
607
for (xx = 1; xx < width; xx += 2) {
608
register guint32 data;
611
*o++ = (data & 0x7c00) >> 7 | (data & 0x7000) >> 12
612
| (data & 0x3e0) << 6 | (data & 0x380) << 1;
613
*o++ = (data & 0x1f) << 3 | (data & 0x1c) >> 2
614
| (data & 0x7c000000) >> 15 | (data & 0x70000000) >> 20;
615
*o++ = (data & 0x3e00000) >> 18 | (data & 0x3800000) >> 23
616
| (data & 0x1f0000) >> 5 | (data & 0x1c0000) >> 10;
618
/* swap endianness first */
619
data = s[1] | s[0] << 8 | s[3] << 16 | s[2] << 24;
621
*o++ = (data & 0x7c00) << 1 | (data & 0x7000) >> 4
622
| (data & 0x3e0) >> 2 | (data & 0x380) >> 7;
623
*o++ = (data & 0x1f) << 11 | (data & 0x1c) << 6
624
| (data & 0x7c000000) >> 23 | (data & 0x70000000) >> 28;
625
*o++ = (data & 0x3e00000) >> 10 | (data & 0x3800000) >> 15
626
| (data & 0x1f0000) >> 13 | (data & 0x1c0000) >> 18;
629
/* check for last remaining pixel */
631
register guint16 data;
633
data = *((short *) s);
635
data = *((short *) s);
636
data = ((data >> 8) & 0xff) | ((data & 0xff) << 8);
638
((char *) o)[0] = (data & 0x7c00) >> 7 | (data & 0x7000) >> 12;
639
((char *) o)[1] = (data & 0x3e0) >> 2 | (data & 0x380) >> 7;
640
((char *) o)[2] = (data & 0x1f) << 3 | (data & 0x1c) >> 2;
648
convert 15 bits/pixel data
653
rgb555msb (XImage *image, guchar *pixels, int rowstride, xlib_colormap *colormap)
660
register guint8 *s; /* read 2 pixels at once */
662
register guint32 *s; /* read 2 pixels at once */
665
guint8 *srow = (guint8 *)image->data, *orow = pixels;
667
width = image->width;
668
height = image->height;
669
bpl = image->bytes_per_line;
671
for (yy = 0; yy < height; yy++) {
675
s = (guint32 *) srow;
677
o = (guint16 *) orow;
678
for (xx = 1; xx < width; xx += 2) {
679
register guint32 data;
681
/* swap endianness first */
682
data = s[1] | s[0] << 8 | s[3] << 16 | s[2] << 24;
684
*o++ = (data & 0x7c00) >> 7 | (data & 0x7000) >> 12
685
| (data & 0x3e0) << 6 | (data & 0x380) << 1;
686
*o++ = (data & 0x1f) << 3 | (data & 0x1c) >> 2
687
| (data & 0x7c000000) >> 15 | (data & 0x70000000) >> 20;
688
*o++ = (data & 0x3e00000) >> 18 | (data & 0x3800000) >> 23
689
| (data & 0x1f0000) >> 5 | (data & 0x1c0000) >> 10;
692
*o++ = (data & 0x7c00) << 1 | (data & 0x7000) >> 4
693
| (data & 0x3e0) >> 2 | (data & 0x380) >> 7;
694
*o++ = (data & 0x1f) << 11 | (data & 0x1c) << 6
695
| (data & 0x7c000000) >> 23 | (data & 0x70000000) >> 28;
696
*o++ = (data & 0x3e00000) >> 10 | (data & 0x3800000) >> 15
697
| (data & 0x1f0000) >> 13 | (data & 0x1c0000) >> 18;
700
/* check for last remaining pixel */
702
register guint16 data;
704
data = *((short *) s);
705
data = ((data >> 8) & 0xff) | ((data & 0xff) << 8);
707
data = *((short *) s);
709
((char *) o)[0] = (data & 0x7c00) >> 7 | (data & 0x7000) >> 12;
710
((char *) o)[1] = (data & 0x3e0) >> 2 | (data & 0x380) >> 7;
711
((char *) o)[2] = (data & 0x1f) << 3 | (data & 0x1c) >> 2;
719
convert 15 bits/pixel data
724
rgb555alsb (XImage *image, guchar *pixels, int rowstride, xlib_colormap *colormap)
731
register guint16 *s; /* read 1 pixels at once */
737
guint8 *srow = (guint8 *)image->data, *orow = pixels;
739
width = image->width;
740
height = image->height;
741
bpl = image->bytes_per_line;
743
for (yy = 0; yy < height; yy++) {
745
s = (guint16 *) srow;
749
o = (guint32 *) orow;
750
for (xx = 0; xx < width; xx++) {
751
register guint32 data;
752
/* rrrrrggg gggbbbbb -> rrrrrRRR gggggGGG bbbbbBBB aaaaaaaa */
753
/* little endian: aaaaaaaa bbbbbBBB gggggGGG rrrrrRRR */
756
*o++ = (data & 0x7c00) >> 7 | (data & 0x7000) >> 12
757
| (data & 0x3e0) << 6 | (data & 0x380) << 1
758
| (data & 0x1f) << 19 | (data & 0x1c) << 14
761
/* swap endianness first */
762
data = s[0] | s[1] << 8;
764
*o++ = (data & 0x7c00) << 17 | (data & 0x7000) << 12
765
| (data & 0x3e0) << 14 | (data & 0x380) << 9
766
| (data & 0x1f) << 11 | (data & 0x1c) << 6
776
convert 15 bits/pixel data
781
rgb555amsb (XImage *image, guchar *pixels, int rowstride, xlib_colormap *colormap)
788
register guint16 *s; /* read 1 pixels at once */
794
guint8 *srow = (guint8 *)image->data, *orow = pixels;
796
width = image->width;
797
height = image->height;
798
bpl = image->bytes_per_line;
800
for (yy = 0; yy < height; yy++) {
802
s = (guint16 *) srow;
806
o = (guint32 *) orow;
807
for (xx = 0; xx < width; xx++) {
808
register guint32 data;
809
/* rrrrrggg gggbbbbb -> rrrrrRRR gggggGGG bbbbbBBB aaaaaaaa */
810
/* little endian: aaaaaaaa bbbbbBBB gggggGGG rrrrrRRR */
812
/* swap endianness first */
813
data = s[0] | s[1] << 8;
815
*o++ = (data & 0x7c00) >> 7 | (data & 0x7000) >> 12
816
| (data & 0x3e0) << 6 | (data & 0x380) << 1
817
| (data & 0x1f) << 19 | (data & 0x1c) << 14
821
*o++ = (data & 0x7c00) << 17 | (data & 0x7000) << 12
822
| (data & 0x3e0) << 14 | (data & 0x380) << 9
823
| (data & 0x1f) << 11 | (data & 0x1c) << 6
834
rgb888alsb (XImage *image, guchar *pixels, int rowstride, xlib_colormap *colormap)
840
guint8 *s; /* for byte order swapping */
842
guint8 *srow = (guint8 *)image->data, *orow = pixels;
844
width = image->width;
845
height = image->height;
846
bpl = image->bytes_per_line;
848
d (printf ("32 bits/pixel with alpha\n"));
851
for (yy = 0; yy < height; yy++) {
854
for (xx = 0; xx < width; xx++) {
867
rgb888lsb (XImage *image, guchar *pixels, int rowstride, xlib_colormap *colormap)
873
guint8 *srow = (guint8 *)image->data, *orow = pixels;
876
width = image->width;
877
height = image->height;
878
bpl = image->bytes_per_line;
880
d (printf ("32 bit, lsb, no alpha\n"));
882
for (yy = 0; yy < height; yy++) {
885
for (xx = 0; xx < width; xx++) {
897
rgb888amsb (XImage *image, guchar *pixels, int rowstride, xlib_colormap *colormap)
903
guint8 *srow = (guint8 *)image->data, *orow = pixels;
908
guint8 *s; /* for byte order swapping */
912
d (printf ("32 bit, msb, with alpha\n"));
914
width = image->width;
915
height = image->height;
916
bpl = image->bytes_per_line;
919
for (yy = 0; yy < height; yy++) {
921
s = (guint32 *) srow;
922
o = (guint32 *) orow;
927
for (xx = 0; xx < width; xx++) {
935
*o++ = (*s << 8) | 0xff; /* untested */
945
rgb888msb (XImage *image, guchar *pixels, int rowstride, xlib_colormap *colormap)
951
guint8 *srow = (guint8 *)image->data, *orow = pixels;
955
d (printf ("32 bit, msb, no alpha\n"));
957
width = image->width;
958
height = image->height;
959
bpl = image->bytes_per_line;
961
for (yy = 0; yy < height; yy++) {
964
for (xx = 0; xx < width; xx++) {
976
This should work correctly with any display/any endianness, but will probably
980
convert_real_slow (XImage *image, guchar *pixels, int rowstride, xlib_colormap *cmap, int alpha)
985
guint8 *srow = (guint8 *)image->data, *orow = pixels;
991
int red_shift, red_prec, green_shift, green_prec, blue_shift, blue_prec;
993
width = image->width;
994
height = image->height;
995
bpl = image->bytes_per_line;
998
visual_decompose_mask (v->red_mask, &red_shift, &red_prec);
999
visual_decompose_mask (v->green_mask, &green_shift, &green_prec);
1000
visual_decompose_mask (v->blue_mask, &blue_shift, &blue_prec);
1002
d(printf("rgb mask/shift/prec = %x:%x:%x %d:%d:%d %d:%d:%d\n",
1003
v->red_mask, v->green_mask, v->blue_mask,
1004
red_shift, green_shift, blue_shift,
1005
red_prec, green_prec, blue_prec));
1007
for (yy = 0; yy < height; yy++) {
1009
for (xx = 0; xx < width; xx++) {
1010
pixel = XGetPixel (image, xx, yy);
1012
/* I assume this is right for static & greyscale's too? */
1017
*o++ = cmap->colors[pixel].red;
1018
*o++ = cmap->colors[pixel].green;
1019
*o++ = cmap->colors[pixel].blue;
1022
/* This is odd because it must sometimes shift left (otherwise
1023
I'd just shift >> (*_shift - 8 + *_prec + <0-7>). This logic
1024
should work for all bit sizes/shifts/etc. */
1026
for (i = 24; i < 32; i += red_prec)
1027
component |= ((pixel & v->red_mask) << (32 - red_shift - red_prec)) >> i;
1030
for (i = 24; i < 32; i += green_prec)
1031
component |= ((pixel & v->green_mask) << (32 - green_shift - green_prec)) >> i;
1034
for (i = 24; i < 32; i += blue_prec)
1035
component |= ((pixel & v->blue_mask) << (32 - blue_shift - blue_prec)) >> i;
1039
*o++ = cmap->colors[((pixel & v->red_mask) << (32 - red_shift - red_prec)) >> 24].red;
1040
*o++ = cmap->colors[((pixel & v->green_mask) << (32 - green_shift - green_prec)) >> 24].green;
1041
*o++ = cmap->colors[((pixel & v->blue_mask) << (32 - blue_shift - blue_prec)) >> 24].blue;
1052
typedef void (* cfunc) (XImage *image, guchar *pixels, int rowstride, xlib_colormap *cmap);
1054
static const cfunc convert_map[] = {
1055
rgb1,rgb1,rgb1a,rgb1a,
1056
rgb8,rgb8,rgb8a,rgb8a,
1057
rgb555lsb,rgb555msb,rgb555alsb,rgb555amsb,
1058
rgb565lsb,rgb565msb,rgb565alsb,rgb565amsb,
1059
rgb888lsb,rgb888msb,rgb888alsb,rgb888amsb
1063
perform actual conversion
1065
If we can, try and use the optimised code versions, but as a default
1066
fallback, and always for direct colour, use the generic/slow but complete
1067
conversion function.
1070
rgbconvert (XImage *image, guchar *pixels, int rowstride, int alpha, xlib_colormap *cmap)
1072
int index = (image->byte_order == MSBFirst) | (alpha != 0) << 1;
1073
int bank=5; /* default fallback converter */
1074
Visual *v = cmap->visual;
1076
d(printf("masks = %x:%x:%x\n", v->red_mask, v->green_mask, v->blue_mask));
1077
d(printf("image depth = %d, bpp = %d\n", image->depth, image->bits_per_pixel));
1080
/* I assume this is right for static & greyscale's too? */
1085
switch (image->bits_per_pixel) {
1095
switch (image->depth) {
1097
if (v->red_mask == 0x7c00 && v->green_mask == 0x3e0 && v->blue_mask == 0x1f
1098
&& image->bits_per_pixel == 16)
1102
if (v->red_mask == 0xf800 && v->green_mask == 0x7e0 && v->blue_mask == 0x1f
1103
&& image->bits_per_pixel == 16)
1108
if (v->red_mask == 0xff0000 && v->green_mask == 0xff00 && v->blue_mask == 0xff
1109
&& image->bits_per_pixel == 32)
1115
/* always use the slow version */
1119
d(printf("converting using conversion function in bank %d\n", bank));
1122
convert_real_slow(image, pixels, rowstride, cmap, alpha);
1125
(* convert_map[index]) (image, pixels, rowstride, cmap);
1130
xlib_window_is_viewable (Window w)
1132
XWindowAttributes wa;
1135
Window parent, root, *children;
1138
XGetWindowAttributes (gdk_pixbuf_dpy, w, &wa);
1139
if (wa.map_state != IsViewable)
1142
if (!XQueryTree (gdk_pixbuf_dpy, w, &root,
1143
&parent, &children, &nchildren))
1149
if ((parent == root) || (w == root))
1159
xlib_window_get_origin (Window w, gint *x, gint *y)
1162
return XTranslateCoordinates (gdk_pixbuf_dpy, w,
1163
RootWindow (gdk_pixbuf_dpy,
1165
0, 0, x, y, &child);
1168
/* Exported functions */
1171
* gdk_pixbuf_xlib_get_from_drawable:
1172
* @dest: Destination pixbuf, or NULL if a new pixbuf should be created.
1173
* @src: Source drawable.
1174
* @cmap: A colormap if @src is a pixmap. If it is a window, this argument will
1176
* @visual: A visual if @src is a pixmap. If it is a window, this argument will
1178
* @src_x: Source X coordinate within drawable.
1179
* @src_y: Source Y coordinate within drawable.
1180
* @dest_x: Destination X coordinate in pixbuf, or 0 if @dest is NULL.
1181
* @dest_y: Destination Y coordinate in pixbuf, or 0 if @dest is NULL.
1182
* @width: Width in pixels of region to get.
1183
* @height: Height in pixels of region to get.
1185
* Transfers image data from a Gdk drawable and converts it to an RGB(A)
1186
* representation inside a GdkPixbuf.
1188
* If the drawable @src is a pixmap, then a suitable colormap must be specified,
1189
* since pixmaps are just blocks of pixel data without an associated colormap.
1190
* If the drawable is a window, the @cmap argument will be ignored and the
1191
* window's own colormap will be used instead.
1193
* If the specified destination pixbuf @dest is #NULL, then this function will
1194
* create an RGB pixbuf with 8 bits per channel and no alpha, with the same size
1195
* specified by the @width and @height arguments. In this case, the @dest_x and
1196
* @dest_y arguments must be specified as 0, otherwise the function will return
1197
* #NULL. If the specified destination pixbuf is not NULL and it contains alpha
1198
* information, then the filled pixels will be set to full opacity.
1200
* If the specified drawable is a pixmap, then the requested source rectangle
1201
* must be completely contained within the pixmap, otherwise the function will
1204
* If the specified drawable is a window, then it must be viewable, i.e. all of
1205
* its ancestors up to the root window must be mapped. Also, the specified
1206
* source rectangle must be completely contained within the window and within
1207
* the screen. If regions of the window are obscured by noninferior windows, the
1208
* contents of those regions are undefined. The contents of regions obscured by
1209
* inferior windows of a different depth than that of the source window will also
1212
* Return value: The same pixbuf as @dest if it was non-NULL, or a newly-created
1213
* pixbuf with a reference count of 1 if no destination pixbuf was specified; in
1214
* the latter case, NULL will be returned if not enough memory could be
1215
* allocated for the pixbuf to be created.
1218
gdk_pixbuf_xlib_get_from_drawable (GdkPixbuf *dest,
1220
Colormap cmap, Visual *visual,
1221
int src_x, int src_y,
1222
int dest_x, int dest_y,
1223
int width, int height)
1225
guint src_width, src_height;
1227
int rowstride, bpp, alpha;
1228
XWindowAttributes wa;
1229
xlib_colormap *x_cmap;
1232
/* General sanity checks */
1234
g_return_val_if_fail (src != 0, NULL);
1236
is_pixmap = drawable_is_pixmap (src);
1239
g_return_val_if_fail (cmap != 0, NULL);
1240
g_return_val_if_fail (visual != NULL, NULL);
1243
g_return_val_if_fail (xlib_window_is_viewable (src), NULL);
1246
g_return_val_if_fail (dest_x == 0 && dest_y == 0, NULL);
1248
g_return_val_if_fail (gdk_pixbuf_get_colorspace (dest) == GDK_COLORSPACE_RGB, NULL);
1249
g_return_val_if_fail (gdk_pixbuf_get_n_channels (dest) == 3
1250
|| gdk_pixbuf_get_n_channels (dest) == 4, NULL);
1251
g_return_val_if_fail (gdk_pixbuf_get_bits_per_sample (dest) == 8, NULL);
1254
/* Coordinate sanity checks */
1257
XGetWindowAttributes (gdk_pixbuf_dpy, src, &wa);
1258
src_width = wa.width;
1259
src_height = wa.height;
1263
guint bwidth, depth;
1264
XGetGeometry (gdk_pixbuf_dpy, src, &root, &tx, &ty,
1265
&src_width, &src_height, &bwidth, &depth);
1268
g_return_val_if_fail (src_x >= 0 && src_y >= 0, NULL);
1269
g_return_val_if_fail (src_x + width <= src_width
1270
&& src_y + height <= src_height, NULL);
1273
g_return_val_if_fail (dest_x >= 0 && dest_y >= 0, NULL);
1274
g_return_val_if_fail (dest_x + width <= gdk_pixbuf_get_width (dest), NULL);
1275
g_return_val_if_fail (dest_y + height <= gdk_pixbuf_get_height (dest), NULL);
1280
int src_xorigin, src_yorigin;
1281
int screen_width, screen_height;
1282
int screen_srcx, screen_srcy;
1284
ret = xlib_window_get_origin (src, &src_xorigin, &src_yorigin);
1285
g_return_val_if_fail (ret != FALSE, NULL);
1287
screen_width = DisplayWidth (gdk_pixbuf_dpy, gdk_pixbuf_screen);
1288
screen_height = DisplayHeight (gdk_pixbuf_dpy, gdk_pixbuf_screen);
1290
screen_srcx = src_xorigin + src_x;
1291
screen_srcy = src_yorigin + src_y;
1293
g_return_val_if_fail (screen_srcx >= 0 && screen_srcy >= 0, NULL);
1294
g_return_val_if_fail (screen_srcx + width <= screen_width, NULL);
1295
g_return_val_if_fail (screen_srcy + height <= screen_height, NULL);
1298
/* Get Image in ZPixmap format (packed bits). */
1299
image = XGetImage (gdk_pixbuf_dpy, src, src_x, src_y,
1300
width, height, AllPlanes, ZPixmap);
1301
g_return_val_if_fail (image != NULL, NULL);
1303
/* Create the pixbuf if needed */
1305
dest = gdk_pixbuf_new (GDK_COLORSPACE_RGB,
1306
FALSE, 8, width, height);
1308
XDestroyImage (image);
1313
/* Get the colormap if needed */
1320
x_cmap = xlib_get_colormap (cmap, visual);
1322
alpha = gdk_pixbuf_get_has_alpha (dest);
1323
rowstride = gdk_pixbuf_get_rowstride (dest);
1324
bpp = alpha ? 4 : 3;
1326
/* we offset into the image data based on the position we are retrieving from */
1327
rgbconvert (image, gdk_pixbuf_get_pixels (dest) +
1328
(dest_y * rowstride) + (dest_x * bpp),
1333
xlib_colormap_free (x_cmap);
1334
XDestroyImage (image);