3
* Copyright (C) 2002 Matthew Allum
5
* This library is free software; you can redistribute it and/or
6
* modify it under the terms of the GNU Lesser General Public
7
* License as published by the Free Software Foundation; either
8
* version 2 of the License, or (at your option) any later version.
10
* This library is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
* Lesser General Public License for more details.
15
* You should have received a copy of the GNU Lesser General Public
16
* License along with this library; if not, write to the
17
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18
* Boston, MA 02111-1307, USA.
26
#define BYTE_ORD_24_RGB 0
27
#define BYTE_ORD_24_RBG 1
28
#define BYTE_ORD_24_BRG 2
29
#define BYTE_ORD_24_BGR 3
30
#define BYTE_ORD_24_GRB 4
31
#define BYTE_ORD_24_GBR 5
32
#define BYTE_ORD_32_ARGB 6
34
#define alpha_composite(composite, fg, alpha, bg) { \
38
else if ((alpha) == 255) \
41
temp = ((ush)(fg)*(ush)(alpha) + \
42
(ush)(bg)*(ush)(255 - (ush)(alpha)) + (ush)128); \
43
(composite) = (ush)((temp + (temp >> 8)) >> 8); } \
46
#ifdef WORDS_BIGENDIAN
47
#define SHORT_FROM_2BYTES(p) ( *(p+1) | (*(p) << 8) )
48
#define 2BYTES_FROM_SHORT(p,s) \
49
*((p)+1) = (unsigned char) s; \
50
*(p) = (unsigned char) ((s >> 8) & 0xff);
52
#define SHORT_FROM_2BYTES(p) ( *(p) | (*((p)+1) << 8) )
53
#define BYTES_FROM_SHORT(p,s) \
54
*(p) = (unsigned char) s; \
55
*((p)+1) = (unsigned char) ((s >> 8) & 0xff);
58
#define internal_16bpp_pixel_to_rgb(p,r,g,b) \
60
unsigned short s = SHORT_FROM_2BYTES(p); \
61
(r) = (( s & 0xf800) >> 8); \
62
(g) = (( s & 0x07e0) >> 3); \
63
(b) = (( s & 0x001f) << 3); \
67
#define internal_rgb_to_16bpp_pixel(r,g,b,p) \
69
unsigned short s = ( (((b) >> 3) & 0x001f) | \
70
(((g) << 3) & 0x07e0) | \
71
(((r) << 8) & 0xf800) ); \
72
BYTES_FROM_SHORT(p,s) \
75
#define internal_16bpp_pixel_next(p) \
78
#define IN_REGION(x,y,w,h) ( (x) > -1 && (x) < (w) && (y) > -1 && (y) <(h) )
80
typedef unsigned short ush;
84
_load_png_file( const char *file,
85
int *width, int *height, int *has_alpha );
90
_load_jpg_file( const char *file,
91
int *width, int *height, int *has_alpha );
94
static int _mbpb_trapped_error_code = 0;
95
static int (*_mbpb_old_error_handler) (Display *d, XErrorEvent *e);
98
_mbpb_error_handler(Display *display,
101
_mbpb_trapped_error_code = error->error_code;
106
_mbpb_trap_errors(void)
108
_mbpb_trapped_error_code = 0;
109
_mbpb_old_error_handler = XSetErrorHandler(_mbpb_error_handler);
113
_mbpb_untrap_errors(void)
115
XSetErrorHandler(_mbpb_old_error_handler);
116
return _mbpb_trapped_error_code;
120
_paletteAlloc(MBPixbuf *pb);
124
struct my_error_mgr {
125
struct jpeg_error_mgr pub; /* "public" fields */
127
jmp_buf setjmp_buffer; /* for return to caller */
130
typedef struct my_error_mgr * my_error_ptr;
133
_jpeg_error_exit (j_common_ptr cinfo)
135
my_error_ptr myerr = (my_error_ptr) cinfo->err;
136
(*cinfo->err->output_message) (cinfo);
137
longjmp(myerr->setjmp_buffer, 1);
140
static unsigned char*
141
_load_jpg_file( const char *file,
142
int *width, int *height, int *has_alpha )
144
struct jpeg_decompress_struct cinfo;
145
struct my_error_mgr jerr;
146
FILE * infile; /* source file */
147
JSAMPLE *buffer; /* Output row buffer */
148
int row_stride; /* physical row width in output buffer */
150
unsigned char *data = NULL;
152
if ((infile = fopen(file, "rb")) == NULL) {
153
if (mb_want_warnings())
154
fprintf(stderr, "mbpixbuf: can't open %s\n", file);
158
cinfo.err = jpeg_std_error(&jerr.pub);
159
jerr.pub.error_exit = _jpeg_error_exit;
161
if (setjmp(jerr.setjmp_buffer)) {
162
jpeg_destroy_decompress(&cinfo);
167
jpeg_create_decompress(&cinfo);
168
jpeg_stdio_src(&cinfo, infile);
169
jpeg_read_header(&cinfo, TRUE);
171
cinfo.do_fancy_upsampling = FALSE;
172
cinfo.do_block_smoothing = FALSE;
173
cinfo.out_color_space = JCS_RGB;
176
jpeg_start_decompress(&cinfo);
178
if( cinfo.output_components != 3 )
180
if (mb_want_warnings())
181
fprintf( stderr, "mbpixbuf: jpegs with %d channles not supported\n",
182
cinfo.output_components );
183
jpeg_finish_decompress(&cinfo);
184
jpeg_destroy_decompress(&cinfo);
189
*width = cinfo.output_width;
190
*height = cinfo.output_height;
192
data = malloc(*width * *height * 3 );
193
row_stride = cinfo.output_width * cinfo.output_components;
194
buffer = malloc( sizeof(JSAMPLE)*row_stride );
196
while (cinfo.output_scanline < cinfo.output_height) {
197
jpeg_read_scanlines(&cinfo, &buffer, 1);
198
memcpy( &data[ ( cinfo.output_scanline - 1 ) * row_stride ],
199
buffer, row_stride );
202
jpeg_finish_decompress(&cinfo);
203
jpeg_destroy_decompress(&cinfo);
206
if (buffer) free(buffer);
215
static unsigned char*
216
_load_png_file( const char *file,
217
int *width, int *height, int *has_alpha ) {
220
unsigned char header[8];
221
int bit_depth, color_type;
223
png_uint_32 png_width, png_height, i, rowbytes;
226
png_bytep *row_pointers;
228
if ((fd = fopen( file, "rb" )) == NULL) return NULL;
230
fread( header, 1, 8, fd );
231
if ( ! png_check_sig( header, 8 ) )
237
png_ptr = png_create_read_struct( PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
243
info_ptr = png_create_info_struct(png_ptr);
245
png_destroy_read_struct( &png_ptr, (png_infopp)NULL, (png_infopp)NULL);
250
#if PNG_LIBPNG_VER_MAJOR == 1 && PNG_LIBPNG_VER_MINOR >= 4
251
if ( setjmp( png_jmpbuf ( png_ptr ) ) ) {
253
if ( setjmp( png_ptr->jmpbuf ) ) {
255
png_destroy_read_struct( &png_ptr, &info_ptr, NULL);
260
png_init_io( png_ptr, fd );
261
png_set_sig_bytes( png_ptr, 8);
262
png_read_info( png_ptr, info_ptr);
263
png_get_IHDR( png_ptr, info_ptr, &png_width, &png_height, &bit_depth,
264
&color_type, NULL, NULL, NULL);
265
*width = (int) png_width;
266
*height = (int) png_height;
268
if (( color_type == PNG_COLOR_TYPE_PALETTE )||
269
( png_get_valid( png_ptr, info_ptr, PNG_INFO_tRNS )))
270
png_set_expand(png_ptr);
272
if (( color_type == PNG_COLOR_TYPE_GRAY )||
273
( color_type == PNG_COLOR_TYPE_GRAY_ALPHA ))
274
png_set_gray_to_rgb(png_ptr);
276
if ( color_type == PNG_COLOR_TYPE_RGB_ALPHA
277
|| color_type == PNG_COLOR_TYPE_GRAY_ALPHA
284
if ( bit_depth == 16 )
285
png_set_strip_16(png_ptr);
288
png_set_packing(png_ptr);
290
/* not needed as data will be RGB not RGBA and have_alpha will reflect this
291
png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);
294
png_read_update_info( png_ptr, info_ptr);
296
/* allocate space for data and row pointers */
297
rowbytes = png_get_rowbytes( png_ptr, info_ptr);
298
data = (unsigned char *) malloc( (rowbytes*(*height + 1)));
299
row_pointers = (png_bytep *) malloc( (*height)*sizeof(png_bytep));
301
if (( data == NULL )||( row_pointers == NULL )) {
302
png_destroy_read_struct( &png_ptr, &info_ptr, NULL);
308
for ( i = 0; i < *height; i++ )
309
row_pointers[i] = data + i*rowbytes;
311
png_read_image( png_ptr, row_pointers );
312
png_read_end( png_ptr, NULL);
315
png_destroy_read_struct( &png_ptr, &info_ptr, NULL);
323
static unsigned char*
324
_load_xpm_file( MBPixbuf *pb, const char *filename, int *w, int *h, int *has_alpha)
325
{ /* This hell is adapted from imlib ;-) */
330
unsigned char str[6];
331
unsigned char transp;
335
unsigned char *data = NULL, *ptr = NULL, *end = NULL;
337
int pc, c = ' ', i = 0, j = 0, k = 0, ncolors = 0, cpp = 0,
338
comment = 0, transp = 0, quote = 0, context = 0, len, done = 0;
340
char *line, s[257], tok[128], col[256];
345
short lookup[128 - 32][128 - 32];
347
if (!filename) return NULL;
349
if ((file = fopen( filename, "rb" )) == NULL) return NULL;
361
if ((pc == '/') && (c == '*'))
363
else if ((pc == '*') && (c == '/') && (comment))
368
if ((!quote) && (c == '"'))
373
else if ((quote) && (c == '"'))
380
sscanf(line, "%i %i %i %i", w, h, &ncolors, &cpp);
381
if (ncolors > 32766 || cpp > 5 || *w > 32767 || *h > 32767)
383
if (mb_want_warnings())
384
fprintf(stderr, "xpm file invalid");
391
cmap = malloc(sizeof(struct _cmap) * ncolors);
400
data = malloc(*w ** h * 4);
410
end = ptr + (*w ** h * 4);
414
else if (context == 1)
420
int hascolor, iscolor;
428
strncpy((char*)cmap[j].str, line, cpp);
429
cmap[j].str[cpp] = 0;
432
for (k = cpp; k < len; k++)
437
sscanf(&line[k], "%256s", s);
442
if ((!strcmp(s, "m")) || (!strcmp(s, "s")) ||
443
(!strcmp(s, "g4")) || (!strcmp(s, "g")) ||
444
(!strcmp(s, "c")) || (k >= len))
450
if (strlen(col) + strlen(s) < sizeof(col))
455
if (!strcasecmp(col, "none"))
462
if ((((cmap[j].r < 0) ||
463
(!strcmp(tok, "c"))) &&
467
DefaultColormap(pb->dpy,
471
cmap[j].r = xcol.red >> 8;
472
cmap[j].g = xcol.green >> 8;
473
cmap[j].b = xcol.blue >> 8;
474
if ((cmap[j].r == 255) &&
499
for (i = 0; i < ncolors; i++)
500
lookup[(int)cmap[i].str[0] - 32][0] = i;
502
for (i = 0; i < ncolors; i++)
503
lookup[(int)cmap[i].str[0] - 32][(int)cmap[i].str[1] - 32] = i;
514
((i < 65536) && (ptr < end) && (line[i]));
519
cmap[lookup[(int)col[0] - 32][0]].transp)
521
*ptr++ = 0; *ptr++ = 0; *ptr++ = 0; *ptr++ = 0;
525
int idx = lookup[(int)col[0] - 32][0];
526
*ptr++ = (unsigned char)cmap[idx].r;
527
*ptr++ = (unsigned char)cmap[idx].g;
528
*ptr++ = (unsigned char)cmap[idx].b;
529
if (transp) *ptr++ = 255;
536
((i < 65536) && (ptr < end) && (line[i]));
539
for (j = 0; j < cpp; j++, i++)
545
for (j = 0; j < ncolors; j++)
547
if (!strcmp(col, (char*)cmap[j].str))
549
if (transp && cmap[j].transp)
558
*ptr++ = (unsigned char)cmap[j].r;
559
*ptr++ = (unsigned char)cmap[j].g;
560
*ptr++ = (unsigned char)cmap[j].b;
561
if (transp) *ptr++ = 255;
572
/* Scan in line from XPM file */
573
if ((!comment) && (quote) && (c != '"'))
584
line = realloc(line, lsz);
593
if ((ptr) && ((ptr - data) >= *w ** h * 4))
610
_paletteAlloc(MBPixbuf *pb)
614
unsigned long used[256];
615
int num_used, is_used;
617
int num_of_cols = 1 << pb->depth;
618
int colors_per_channel = num_of_cols / 3;
620
if (pb->palette) free(pb->palette);
622
pb->palette = malloc(sizeof(MBPixbufColor) * num_of_cols);
627
switch(pb->vis->class)
632
for (r = 0, i = 0; r < colors_per_channel; r++)
633
for (g = 0; g < colors_per_channel; g++)
634
for (b = 0; b < colors_per_channel; b++, i++)
636
xcl.red = (r * 0xffff) / (colors_per_channel - 1);
637
xcl.green = (g * 0xffff) / (colors_per_channel - 1);
638
xcl.blue = (b * 0xffff) / (colors_per_channel - 1);
639
xcl.flags = DoRed | DoGreen | DoBlue;
643
for (i = 0; i < num_of_cols; i++)
644
{ /* RRRGGGBB - TODO check for 4 bit col */
645
int ii = (i * 256)/num_of_cols;
646
xcl.red = (unsigned short)( ( ii & 0xe0 ) << 8 );
647
xcl.green = (unsigned short)(( ii & 0x1c ) << 11 );
648
xcl.blue = (unsigned short)( ( ii & 0x03 ) << 14 );
649
xcl.flags = DoRed | DoGreen | DoBlue;
651
if (!XAllocColor(pb->dpy, pb->root_cmap, &xcl))
653
if (mb_want_warnings())
654
printf("alloc color failed\n");
657
for (j = 0; j < num_used; j++)
659
if (xcl.pixel == used[j])
667
pb->palette[colnum].r = xcl.red >> 8;
668
pb->palette[colnum].g = xcl.green >> 8;
669
pb->palette[colnum].b = xcl.blue >> 8;
670
pb->palette[colnum].pixel = xcl.pixel;
671
used[num_used++] = xcl.pixel;
680
for(i = 0; i < num_of_cols; i++)
682
xcl.red = (i * 0xffff) / (colors_per_channel - 1);
683
xcl.green = (i * 0xffff) / (colors_per_channel - 1);
684
xcl.blue = (i * 0xffff) / (colors_per_channel - 1);
685
xcl.flags = DoRed | DoGreen | DoBlue;
687
if (!XAllocColor(pb->dpy, pb->root_cmap, &xcl))
689
if (mb_want_warnings())
690
fprintf(stderr, "libmb: alloc color failed\n");
693
for (j = 0; j < num_used; j++)
695
if (xcl.pixel == used[j])
703
pb->palette[colnum].r = xcl.red >> 8;
704
pb->palette[colnum].g = xcl.green >> 8;
705
pb->palette[colnum].b = xcl.blue >> 8;
706
pb->palette[colnum].pixel = xcl.pixel;
707
used[num_used++] = xcl.pixel;
719
mb_pixbuf_get_pixel(MBPixbuf *pb, int r, int g, int b, int a)
726
return ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | ((b & 0xf8) >> 3);
728
return ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | ((b & 0xf8) >> 3);
731
switch (pb->byte_order)
733
case BYTE_ORD_24_RGB:
734
return ((r & 0xff) << 16) | ((g & 0xff) << 8) | (b & 0xff);
735
case BYTE_ORD_24_RBG:
736
return ((r & 0xff) << 16) | ((b & 0xff) << 8) | (g & 0xff);
737
case BYTE_ORD_24_BRG:
738
return ((b & 0xff) << 16) | ((r & 0xff) << 8) | (g & 0xff);
739
case BYTE_ORD_24_BGR:
740
return ((b & 0xff) << 16) | ((g & 0xff) << 8) | (r & 0xff);
741
case BYTE_ORD_24_GRB:
742
return ((g & 0xff) << 16) | ((r & 0xff) << 8) | (b & 0xff);
743
case BYTE_ORD_24_GBR:
744
return ((g & 0xff) << 16) | ((b & 0xff) << 8) | (r & 0xff);
745
case BYTE_ORD_32_ARGB:
746
return (a << 24) | (r << 16) | (g << 8) | b;
757
switch(pb->vis->class)
765
unsigned long col = 0;
766
int mindif = 0x7fffffff;
768
for (i = 0; i < pb->num_of_cols; i++)
770
dr = r - pb->palette[i].r;
773
dg = g - pb->palette[i].g;
776
db = b - pb->palette[i].b;
786
return pb->palette[col].pixel;
790
return (((r * 77) + (g * 151) + (b * 28)) >> (16 - pb->depth));
792
if ((r+g+b) == 765 ) return 0; /* HACK */
793
return (1 << pb->depth) - ((( ((r * 54) + (g * 183) + (b * 19)) / 256) * 0xffff )/ (1 << pb->depth)); /* TODO should be oxffffffff ?? */
802
mb_pixbuf_lookup_x_pixel(MBPixbuf *pb, int r, int g, int b, int a)
804
return mb_pixbuf_get_pixel(pb, r, g, b, a);
809
mb_pixbuf_new(Display *dpy, int scr)
811
return mb_pixbuf_new_extended(dpy,
813
DefaultVisual(dpy, scr),
814
DefaultDepth(dpy, scr));
819
mb_pixbuf_destroy(MBPixbuf *pb)
821
/* XXX Probably needs to free more here */
822
XFreeGC(pb->dpy, pb->gc);
827
mb_pixbuf_new_extended(Display *dpy,
833
unsigned long rmsk, gmsk, bmsk;
834
MBPixbuf *pb = malloc(sizeof(MBPixbuf));
839
pb->root = RootWindow(dpy, scr);
845
rmsk = pb->vis->red_mask;
846
gmsk = pb->vis->green_mask;
847
bmsk = pb->vis->blue_mask;
849
if (depth == 32 && pb->vis->class == TrueColor)
850
pb->byte_order = BYTE_ORD_32_ARGB;
851
else if ((rmsk > gmsk) && (gmsk > bmsk))
852
pb->byte_order = BYTE_ORD_24_RGB;
853
else if ((rmsk > bmsk) && (bmsk > gmsk))
854
pb->byte_order = BYTE_ORD_24_RBG;
855
else if ((bmsk > rmsk) && (rmsk > gmsk))
856
pb->byte_order = BYTE_ORD_24_BRG;
857
else if ((bmsk > gmsk) && (gmsk > rmsk))
858
pb->byte_order = BYTE_ORD_24_BGR;
859
else if ((gmsk > rmsk) && (rmsk > bmsk))
860
pb->byte_order = BYTE_ORD_24_GRB;
861
else if ((gmsk > bmsk) && (bmsk > rmsk))
862
pb->byte_order = BYTE_ORD_24_GBR;
866
pb->internal_bytespp = 3;
868
if ((pb->depth < 24 && !getenv("MBPIXBUF_FORCE_32BPP_INTERNAL"))
869
|| getenv("MBPIXBUF_FORCE_16BPP_INTERNAL"))
870
pb->internal_bytespp = 2;
872
if ((pb->depth <= 8))
874
XWindowAttributes xwa;
875
if (XGetWindowAttributes(dpy, pb->root, &xwa))
878
pb->root_cmap = xwa.colormap;
880
pb->root_cmap = DefaultColormap(dpy, scr);
884
pb->root_cmap = DefaultColormap(dpy, scr);
885
pb->num_of_cols = _paletteAlloc(pb);
888
/* TODO: No exposes ? */
889
gcv.foreground = BlackPixel(dpy, scr);
890
gcv.background = WhitePixel(dpy, scr);
892
pb->gc = XCreateGC( dpy, pb->root, GCForeground | GCBackground, &gcv);
894
if (!XShmQueryExtension(pb->dpy) || getenv("MBPIXBUF_NO_SHM"))
896
fprintf(stderr, "mbpixbuf: no shared memory extension\n");
897
pb->have_shm = False;
899
else /* Really check we have shm */
900
{ /* Urg, not nicer way todo this ? */
901
XShmSegmentInfo shminfo;
905
shminfo.shmid=shmget(IPC_PRIVATE, 1, IPC_CREAT|0777);
906
shminfo.shmaddr=shmat(shminfo.shmid,0,0);
907
shminfo.readOnly=True;
911
XShmAttach(pb->dpy, &shminfo);
912
XSync(pb->dpy, False);
914
if (_mbpb_untrap_errors())
916
fprintf(stderr, "mbpixbuf: unable to use XShm. DISPLAY remote?\n");
917
pb->have_shm = False;
919
else XShmDetach(pb->dpy, &shminfo);
921
shmdt(shminfo.shmaddr);
922
shmctl(shminfo.shmid, IPC_RMID, 0);
928
mb_pixbuf_img_new(MBPixbuf *pb, int w, int h)
932
img = malloc(sizeof(MBPixbufImage));
936
img->rgba = malloc(sizeof(unsigned char)*((w*h*(pb->internal_bytespp+1))));
937
memset(img->rgba, 0, sizeof(unsigned char)*((w*h*(pb->internal_bytespp+1))));
941
img->internal_bytespp = pb->internal_bytespp;
947
mb_pixbuf_img_rgba_new(MBPixbuf *pb, int w, int h)
949
return mb_pixbuf_img_new(pb, w, h);
954
mb_pixbuf_img_rgb_new(MBPixbuf *pixbuf, int width, int height)
959
img = malloc(sizeof(MBPixbufImage));
961
img->height = height;
964
= malloc(sizeof(unsigned char)*((width*height*pixbuf->internal_bytespp)));
966
sizeof(unsigned char)*((width*height*pixbuf->internal_bytespp)));
970
img->internal_bytespp = pixbuf->internal_bytespp;
979
mb_pixbuf_img_new_from_int_data(MBPixbuf *pixbuf,
987
img = mb_pixbuf_img_rgba_new(pixbuf, width, height);
989
if (pixbuf->internal_bytespp == 3)
991
unsigned char *p = img->rgba;
993
for (y=0; y<height; y++)
994
for (x=0; x<width; x++)
996
*p++ = (data[i] >> 16) & 0xff;
997
*p++ = (data[i] >> 8) & 0xff;
998
*p++ = data[i] & 0xff;
999
*p++ = data[i] >> 24;
1005
unsigned char *p = img->rgba, r,g,b,a;
1007
for (y=0; y<height; y++)
1008
for (x=0; x<width; x++)
1010
r = ((data[i] >> 16) & 0xff);
1011
g = ((data[i] >> 8) & 0xff);
1012
b = (data[i] & 0xff);
1013
a = (data[i] >> 24);
1015
internal_rgb_to_16bpp_pixel(r,g,b,p);
1016
internal_16bpp_pixel_next(p);
1027
mb_pixbuf_img_new_from_data(MBPixbuf *pixbuf,
1028
const unsigned char *data,
1036
img = mb_pixbuf_img_rgba_new(pixbuf, width, height);
1038
img = mb_pixbuf_img_rgb_new(pixbuf, width, height);
1040
if (pixbuf->internal_bytespp == 3)
1042
memcpy(img->rgba, data, width*height*(3+has_alpha));
1046
/* Data is expected as 24/32 RGBA. but internally were
1047
* 16/24 so we need to scale the data down.
1050
unsigned char r,g,b, *p16 = img->rgba;
1051
const unsigned char *p24 = data;
1053
for (x=0; x<img->width; x++)
1054
for (y=0; y<img->height; y++)
1056
r = *p24++; g = *p24++; b = *p24++;
1057
internal_rgb_to_16bpp_pixel(r,g,b,p16);
1058
internal_16bpp_pixel_next(p16);
1069
mb_pixbuf_img_new_from_drawable (MBPixbuf *pb,
1077
return mb_pixbuf_img_new_from_x_drawable(pb, drw, msk, sx, sy, sw, sh, 0);
1081
mb_pixbuf_img_new_from_x_drawable (MBPixbuf *pb,
1090
int i,x,y,br,bg,bb,mg,mb,mr,lr,lg,lb;
1091
unsigned long xpixel;
1095
XImage *ximg, *xmskimg = NULL;
1096
int num_of_cols = 1 << pb->depth;
1100
unsigned int rw, rh, rb, rdepth;
1102
XShmSegmentInfo shminfo;
1104
/* XXX should probably tray an X error here. */
1105
XGetGeometry(pb->dpy, (Window)drw, &chld, &rx, &rx,
1106
(unsigned int *)&rw, (unsigned int *)&rh,
1107
(unsigned int *)&rb, (unsigned int *)&rdepth);
1109
if (rdepth != pb->depth) return NULL;
1111
if ( (sx + sw) > rw || (sy + sh) > rh )
1113
/* area wanted is bigger than pixmap - should probably trim it down */
1117
XGrabServer(pb->dpy);
1119
if (1) /* (!pb->have_shm) BROKE */
1121
ximg = XGetImage(pb->dpy, drw, sx, sy, sw, sh, -1, ZPixmap);
1125
ximg = XShmCreateImage(pb->dpy, pb->vis, pb->depth,
1126
ZPixmap, NULL, &shminfo,
1128
XSync(pb->dpy, False);
1130
shminfo.shmid=shmget(IPC_PRIVATE,
1131
ximg->bytes_per_line*ximg->height,
1133
shminfo.shmaddr=img->ximg->data=shmat(shminfo.shmid,0,0);
1134
shminfo.readOnly=True;
1136
XShmAttach(pb->dpy, &shminfo);
1138
XSync(pb->dpy, False);
1140
if (!XShmGetImage(pb->dpy, drw, ximg, sx, sy, -1))
1145
XSync(pb->dpy, False);
1150
xmskimg = XGetImage(pb->dpy, msk, sx, sy, sw, sh, -1, ZPixmap);
1152
XUngrabServer(pb->dpy);
1155
if (ximg == NULL) return NULL;
1157
if (msk || want_alpha)
1158
img = mb_pixbuf_img_rgba_new(pb, sw, sh);
1160
img = mb_pixbuf_img_rgb_new(pb, sw, sh);
1166
switch (pb->depth) {
1171
mr = mg = mb = 0xf8;
1188
mr = mg = mb = 0xff;
1194
if (pb->internal_bytespp == 2)
1196
for (y = 0; y < sh; y++)
1197
for (x = 0; x < sw; x++)
1199
xpixel = XGetPixel(ximg, x, y);
1200
internal_rgb_to_16bpp_pixel((((xpixel >> br) << lr) & mr),
1201
(((xpixel >> bg) << lg) & mg),
1202
(((xpixel >> bb) << lb) & mb), p);
1204
internal_16bpp_pixel_next(p);
1208
if (xmskimg && XGetPixel(xmskimg, x, y))
1214
else if (want_alpha) p++;
1219
for (y = 0; y < sh; y++)
1220
for (x = 0; x < sw; x++)
1222
xpixel = XGetPixel(ximg, x, y);
1223
*p++ = (((xpixel >> br) << lr) & mr); /* r */
1224
*p++ = (((xpixel >> bg) << lg) & mg); /* g */
1225
*p++ = (((xpixel >> bb) << lb) & mb); /* b */
1228
if (xmskimg && XGetPixel(xmskimg, x, y))
1234
else if (want_alpha) p++;
1241
MBPixbufColor mbcols[256];
1243
for (i = 0; i < num_of_cols; i++) {
1245
cols[i].flags = DoRed | DoGreen | DoBlue;
1247
XQueryColors(pb->dpy, pb->root_cmap, cols, num_of_cols);
1248
for (i = 0; i < num_of_cols; i++) {
1249
mbcols[i].r = cols[i].red >> 8;
1250
mbcols[i].g = cols[i].green >> 8;
1251
mbcols[i].b = cols[i].blue >> 8;
1252
mbcols[i].pixel = cols[i].pixel;
1254
for (x = 0; x < sw; x++)
1255
for (y = 0; y < sh; y++)
1257
xpixel = XGetPixel(ximg, x, y);
1258
*p++ = mbcols[xpixel & 0xff].r;
1259
*p++ = mbcols[xpixel & 0xff].g;
1260
*p++ = mbcols[xpixel & 0xff].b;
1263
if (xmskimg && XGetPixel(xmskimg, x, y))
1269
else if (want_alpha) p++;
1273
if (0) /* (pb->have_shm) BROKE */
1275
XShmDetach(pb->dpy, &shminfo);
1276
XDestroyImage (ximg);
1277
shmdt(shminfo.shmaddr);
1278
shmctl(shminfo.shmid, IPC_RMID, 0);
1280
else XDestroyImage (ximg);
1288
mb_pixbuf_img_clone(MBPixbuf *pb, MBPixbufImage *img)
1290
MBPixbufImage *img_new;
1293
img_new = mb_pixbuf_img_rgba_new(pb, img->width, img->height);
1295
img_new = mb_pixbuf_img_rgb_new(pb, img->width, img->height);
1297
memcpy(img_new->rgba, img->rgba,
1298
sizeof(unsigned char)*((img->width * img->height * (pb->internal_bytespp + img->has_alpha))));
1303
mb_pixbuf_img_free(MBPixbuf *pb, MBPixbufImage *img)
1305
if (img->rgba) free(img->rgba);
1310
_mb_convert_24bpp_to_16bpp(MBPixbuf *pb, MBPixbufImage **img)
1312
MBPixbufImage *img16, *img24 = *img;
1314
unsigned char r,g,b, *p16 = NULL, *p24 = NULL;
1316
if (img24->has_alpha)
1317
img16 = mb_pixbuf_img_rgba_new(pb, img24->width, img24->height);
1319
img16 = mb_pixbuf_img_rgb_new(pb, img24->width, img24->height);
1321
p16 = img16->rgba; p24 = img24->rgba;
1323
for (x=0; x<img24->width; x++)
1324
for (y=0; y<img24->height; y++)
1330
internal_rgb_to_16bpp_pixel(r,g,b,p16);
1331
internal_16bpp_pixel_next(p16);
1333
if (img24->has_alpha)
1337
mb_pixbuf_img_free(pb, img24);
1343
mb_pixbuf_img_new_from_file(MBPixbuf *pb, const char *filename)
1347
img = malloc(sizeof(MBPixbufImage));
1350
if (!strcasecmp(&filename[strlen(filename)-4], ".png"))
1351
img->rgba = _load_png_file( filename, &img->width,
1352
&img->height, &img->has_alpha );
1356
if (!strcasecmp(&filename[strlen(filename)-4], ".jpg")
1357
|| !strcasecmp(&filename[strlen(filename)-5], ".jpeg"))
1358
img->rgba = _load_jpg_file( filename, &img->width,
1359
&img->height, &img->has_alpha );
1362
if (!strcasecmp(&filename[strlen(filename)-4], ".xpm"))
1363
img->rgba = _load_xpm_file( pb, filename, &img->width,
1364
&img->height, &img->has_alpha );
1365
else img->rgba = NULL;
1367
if (img->rgba == NULL)
1374
if (pb->internal_bytespp == 2)
1376
/* Need to convert the data down, always comes as 24 rgb :/ */
1377
_mb_convert_24bpp_to_16bpp(pb, &img);
1386
mb_pixbuf_img_fill(MBPixbuf *pb,
1393
unsigned char *p = img->rgba;
1396
if (pb->internal_bytespp == 2)
1398
for(y=0; y<img->height; y++)
1399
for(x=0; x<img->width; x++)
1401
internal_rgb_to_16bpp_pixel(r,g,b,p);
1402
internal_16bpp_pixel_next(p);
1409
for(y=0; y<img->height; y++)
1410
for(x=0; x<img->width; x++)
1415
if (img->has_alpha) *p++ = a;
1421
mb_pixbuf_img_composite(MBPixbuf *pb, MBPixbufImage *dest,
1422
MBPixbufImage *src, int dx, int dy)
1424
/* XXX depreictaed, should really now use copy_composite */
1425
int x, y, r, g, b, a;
1426
unsigned char *sp, *dp;
1429
if (src->has_alpha == False)
1430
return mb_pixbuf_img_copy(pb, dest, src, 0, 0,
1431
src->width, src->height, dx, dy);
1435
dbc = (pb->internal_bytespp + dest->has_alpha);
1437
dp += ((dest->width*dbc)*dy) + (dx*dbc);
1439
if (pb->internal_bytespp == 2)
1441
for(y=0; y<src->height; y++)
1443
for(x=0; x<src->width; x++)
1445
unsigned char dr,dg,db;
1447
/* TODO, This needs optimising */
1449
internal_16bpp_pixel_to_rgb(sp,r,g,b);
1450
internal_16bpp_pixel_next(sp);
1453
internal_16bpp_pixel_to_rgb(dp,dr,dg,db);
1454
alpha_composite(dr, r, a, dr);
1455
alpha_composite(dg, g, a, dg);
1456
alpha_composite(db, b, a, db);
1457
internal_rgb_to_16bpp_pixel(dr,dg,db,dp)
1458
internal_16bpp_pixel_next(dp);
1460
dp += dest->has_alpha;
1462
dp += (dest->width-src->width)*dbc;
1469
for(y=0; y<src->height; y++)
1471
for(x=0; x<src->width; x++)
1478
alpha_composite(*dp, r, a, *dp);
1480
alpha_composite(*dp, g, a, *dp);
1482
alpha_composite(*dp, b, a, *dp);
1484
dp += dest->has_alpha;
1486
dp += (dest->width-src->width)*dbc;
1492
mb_pixbuf_img_copy_composite_with_alpha (MBPixbuf *pb,
1493
MBPixbufImage *dest,
1500
int x, y, r, g, b, a;
1501
unsigned char *sp, *dp;
1504
if (!src->has_alpha)
1505
return mb_pixbuf_img_copy(pb, dest, src, sx, sy, sw, sh, dx, dy);
1510
dbc = (pb->internal_bytespp + dest->has_alpha);
1512
dp += ((dest->width*dbc)*dy) + (dx*dbc);
1513
sp += ((src->width*(pb->internal_bytespp+1))*sy) + (sx*(pb->internal_bytespp+1));
1515
if (pb->internal_bytespp == 2)
1519
for(x=0; x < sw; x++)
1521
unsigned char dr,dg,db;
1523
/* TODO, This needs optimising */
1525
internal_16bpp_pixel_to_rgb(sp,r,g,b);
1526
internal_16bpp_pixel_next(sp);
1533
if (a > 255) a = 255;
1536
internal_16bpp_pixel_to_rgb(dp,dr,dg,db);
1537
alpha_composite(dr, r, a, dr);
1538
alpha_composite(dg, g, a, dg);
1539
alpha_composite(db, b, a, db);
1540
internal_rgb_to_16bpp_pixel(dr,dg,db,dp);
1541
internal_16bpp_pixel_next(dp);
1543
if (dest->has_alpha)
1546
dp += (dest->width-sw)*dbc;
1547
sp += (src->width-sw)*3;
1554
for(x=0; x < sw; x++)
1565
if (a > 255) a = 255;
1568
alpha_composite(*dp, r, a, *dp);
1570
alpha_composite(*dp, g, a, *dp);
1572
alpha_composite(*dp, b, a, *dp);
1574
if (dest->has_alpha) *dp++ = a;
1576
dp += (dest->width-sw)*dbc;
1577
sp += (src->width-sw)*4;
1584
mb_pixbuf_img_copy_composite(MBPixbuf *pb, MBPixbufImage *dest,
1585
MBPixbufImage *src, int sx, int sy,
1586
int sw, int sh, int dx, int dy)
1588
mb_pixbuf_img_copy_composite_with_alpha(pb, dest,src, sx, sy, sw, sh, dx, dy, 0);
1593
mb_pixbuf_img_copy(MBPixbuf *pb, MBPixbufImage *dest,
1594
MBPixbufImage *src, int sx, int sy, int sw, int sh,
1598
unsigned char *sp, *dp;
1602
dbc = (pb->internal_bytespp + dest->has_alpha);
1603
sbc = (pb->internal_bytespp + src->has_alpha);
1605
dp += ((dest->width*dbc)*dy) + (dx*dbc);
1606
sp += ((src->width*sbc)*sy) + (sx*sbc);
1610
for(x=0; x < sw; x++)
1614
if (pb->internal_bytespp > 2)
1616
/* XXX below to optimise */
1617
if (dest->has_alpha && src->has_alpha)
1621
if (dest->has_alpha) *dp++ = 0xff;
1622
// dp += dest->has_alpha;
1623
sp += src->has_alpha;
1626
dp += (dest->width-sw)*dbc;
1627
sp += (src->width-sw)*sbc;
1632
mb_pixbuf_img_scale_down(MBPixbuf *pb, MBPixbufImage *img,
1633
int new_width, int new_height)
1635
MBPixbufImage *img_scaled;
1636
unsigned char *dest, *src, *srcy;
1637
int *xsample, *ysample;
1638
int bytes_per_line, i, x, y, r, g, b, a, nb_samples, xrange, yrange, rx, ry;
1640
if ( new_width > img->width || new_height > img->height)
1645
img_scaled = mb_pixbuf_img_rgba_new(pb, new_width, new_height);
1646
bytes_per_line = (img->width * (pb->internal_bytespp+1));
1650
img_scaled = mb_pixbuf_img_rgb_new(pb, new_width, new_height);
1651
bytes_per_line = (img->width * pb->internal_bytespp);
1654
xsample = malloc( (new_width+1) * sizeof(int));
1655
ysample = malloc( (new_height+1) * sizeof(int));
1657
for ( i = 0; i <= new_width; i++ )
1658
xsample[i] = i*img->width/new_width;
1659
for ( i = 0; i <= new_height; i++ )
1660
ysample[i] = i*img->height/new_height * img->width;
1662
dest = img_scaled->rgba;
1664
/* scan output image */
1665
for ( y = 0; y < new_height; y++ )
1667
yrange = ( ysample[y+1] - ysample[y] )/img->width;
1668
for ( x = 0; x < new_width; x++)
1670
xrange = xsample[x+1] - xsample[x];
1671
srcy = img->rgba + (( ysample[y] + xsample[x] )
1672
* ( (img->has_alpha) ? (pb->internal_bytespp+1) : pb->internal_bytespp ) );
1674
/* average R,G,B,A values on sub-rectangle of source image */
1675
nb_samples = xrange * yrange;
1676
if ( nb_samples > 1 )
1682
for ( ry = 0; ry < yrange; ry++ )
1685
for ( rx = 0; rx < xrange; rx++ )
1687
/* average R,G,B,A values */
1688
if (pb->internal_bytespp == 2)
1690
unsigned char rr,gg,bb;
1691
internal_16bpp_pixel_to_rgb(src,rr,gg,bb);
1692
r += rr; g += gg; b += bb;
1693
internal_16bpp_pixel_next(src);
1701
if (img->has_alpha) a += *src++;
1703
srcy += bytes_per_line;
1706
if (pb->internal_bytespp == 2)
1708
unsigned char rr,gg,bb;
1709
rr = (r/nb_samples);
1710
gg = (g/nb_samples);
1711
bb = (b/nb_samples);
1713
internal_rgb_to_16bpp_pixel(rr, gg, bb, dest);
1714
internal_16bpp_pixel_next(dest);
1718
*dest++ = r/nb_samples;
1719
*dest++ = g/nb_samples;
1720
*dest++ = b/nb_samples;
1722
if (img_scaled->has_alpha) *dest++ = a/nb_samples;
1727
for (i=0; i<(pb->internal_bytespp + img_scaled->has_alpha); i++)
1741
mb_pixbuf_img_scale_up(MBPixbuf *pb, MBPixbufImage *img,
1742
int new_width, int new_height)
1744
MBPixbufImage *img_scaled;
1745
unsigned char *dest, *src;
1746
int x, y, xx, yy, bytes_per_line;
1748
if ( new_width < img->width || new_height < img->height)
1753
img_scaled = mb_pixbuf_img_rgba_new(pb, new_width, new_height);
1754
bytes_per_line = (img->width * (pb->internal_bytespp+1));
1758
img_scaled = mb_pixbuf_img_rgb_new(pb, new_width, new_height);
1759
bytes_per_line = (img->width * pb->internal_bytespp);
1763
dest = img_scaled->rgba;
1765
for (y = 0; y < new_height; y++)
1767
yy = (y * img->height) / new_height;
1768
for (x = 0; x < new_width; x++)
1770
xx = (x * img->width) / new_width;
1771
src = img->rgba + ((yy * bytes_per_line))
1772
+ ( (img->has_alpha) ? (xx * (pb->internal_bytespp+1)) : (xx * pb->internal_bytespp) );
1775
if (pb->internal_bytespp > 2)
1787
mb_pixbuf_img_scale(MBPixbuf *pb, MBPixbufImage *img,
1788
int new_width, int new_height)
1790
if (new_width >= img->width && new_height >= img->height)
1791
return mb_pixbuf_img_scale_up(pb, img, new_width, new_height);
1793
if (new_width <= img->width && new_height <= img->height)
1794
return mb_pixbuf_img_scale_down(pb, img, new_width, new_height);
1796
/* TODO: all scale functions should check for a dimention change
1797
being zero and act accordingly - ie faster.
1799
if (new_width >= img->width && new_height <= img->height)
1801
MBPixbufImage *tmp=NULL, *tmp2 = NULL;
1802
tmp = mb_pixbuf_img_scale_up(pb, img, new_width, img->height);
1804
tmp2 = mb_pixbuf_img_scale_down(pb, tmp, new_width, new_height);
1805
mb_pixbuf_img_free(pb, tmp);
1809
if (new_width <= img->width && new_height >= img->height)
1811
MBPixbufImage *tmp, *tmp2;
1812
tmp = mb_pixbuf_img_scale_down(pb, img, new_width, img->height);
1814
tmp2 = mb_pixbuf_img_scale_up(pb, tmp, new_width, new_height);
1815
mb_pixbuf_img_free(pb, tmp);
1823
mb_pixbuf_img_render_to_drawable(MBPixbuf *pb,
1829
mb_pixbuf_img_render_to_drawable_with_gc(pb, img, drw, drw_x, drw_y, pb->gc);
1834
mb_pixbuf_img_render_to_drawable_with_gc(MBPixbuf *pb,
1843
unsigned long pixel;
1847
XShmSegmentInfo shminfo;
1848
Bool shm_success = False;
1852
img->ximg = XShmCreateImage(pb->dpy, pb->vis, pb->depth,
1853
ZPixmap, NULL, &shminfo,
1854
img->width, img->height );
1856
shminfo.shmid=shmget(IPC_PRIVATE,
1857
img->ximg->bytes_per_line*img->ximg->height,
1859
shminfo.shmaddr = img->ximg->data = shmat(shminfo.shmid,0,0);
1861
if (img->ximg->data == (char *)-1)
1863
fprintf(stderr, "mbpixbuf: SHM can't attach SHM Segment for Shared XImage, falling back to XImages\n");
1864
XDestroyImage(img->ximg);
1865
shmctl(shminfo.shmid, IPC_RMID, 0);
1869
shminfo.readOnly=True;
1870
XShmAttach(pb->dpy, &shminfo);
1877
bitmap_pad = ( pb->depth > 16 )? 32 : (( pb->depth > 8 )? 16 : 8 );
1879
img->ximg = XCreateImage( pb->dpy, pb->vis, pb->depth,
1881
img->width, img->height, bitmap_pad, 0);
1883
img->ximg->data = malloc( img->ximg->bytes_per_line*img->height );
1888
if (pb->internal_bytespp == 2)
1890
for(y=0; y<img->height; y++)
1891
for(x=0; x<img->width; x++)
1893
/* Below is potentially dangerous.
1895
pixel = ( *p | (*(p+1) << 8));
1897
p += ((img->has_alpha) ? 3 : 2);
1899
XPutPixel(img->ximg, x, y, pixel);
1904
for(y=0; y<img->height; y++)
1906
for(x=0; x<img->width; x++)
1911
a = ((img->has_alpha) ? *p++ : 0xff);
1913
pixel = mb_pixbuf_get_pixel(pb, r, g, b, a);
1914
XPutPixel(img->ximg, x, y, pixel);
1921
XPutImage( pb->dpy, drw, gc, img->ximg, 0, 0,
1922
drw_x, drw_y, img->width, img->height);
1923
XDestroyImage (img->ximg);
1927
XShmPutImage(pb->dpy, drw, gc, img->ximg, 0, 0,
1928
drw_x, drw_y, img->width, img->height, False);
1930
XSync(pb->dpy, False);
1931
XShmDetach(pb->dpy, &shminfo);
1932
XDestroyImage (img->ximg);
1933
shmdt(shminfo.shmaddr);
1934
shmctl(shminfo.shmid, IPC_RMID, 0);
1937
img->ximg = NULL; /* Safety On */
1941
mb_pixbuf_img_render_to_mask(MBPixbuf *pb,
1950
XShmSegmentInfo shminfo;
1951
Bool shm_success = False;
1953
if (!img->has_alpha) return;
1955
gc1 = XCreateGC( pb->dpy, mask, 0, 0 );
1956
XSetForeground(pb->dpy, gc1, WhitePixel( pb->dpy, pb->scr ));
1960
img->ximg = XShmCreateImage(pb->dpy, pb->vis, 1,
1961
XYPixmap, NULL, &shminfo,
1962
img->width, img->height );
1964
shminfo.shmid=shmget(IPC_PRIVATE,
1965
img->ximg->bytes_per_line*img->ximg->height,
1967
shminfo.shmaddr=img->ximg->data=shmat(shminfo.shmid,0,0);
1969
if (img->ximg->data == (char *)-1)
1971
if (mb_want_warnings())
1972
fprintf(stderr, "mbpixbuf: SHM can't attach SHM Segment for Shared XImage, falling back to XImages\n");
1973
XDestroyImage(img->ximg);
1974
shmctl(shminfo.shmid, IPC_RMID, 0);
1978
shminfo.readOnly=True;
1979
XShmAttach(pb->dpy, &shminfo);
1986
img->ximg = XCreateImage( pb->dpy, pb->vis, 1, XYPixmap,
1987
0, 0, img->width, img->height, 8, 0);
1989
img->ximg->data = malloc( img->ximg->bytes_per_line*img->height );
1994
for(y=0; y<img->height; y++)
1995
for(x=0; x<img->width; x++)
1997
p += pb->internal_bytespp;
1998
XPutPixel(img->ximg, x, y, (*p < 127) ? 0 : 1);
2004
XPutImage( pb->dpy, mask, gc1, img->ximg, 0, 0,
2005
drw_x, drw_y, img->width, img->height);
2006
XDestroyImage (img->ximg);
2010
XShmPutImage(pb->dpy, mask, gc1, img->ximg, 0, 0,
2011
drw_x, drw_y, img->width, img->height, False);
2012
XSync(pb->dpy, False);
2013
XShmDetach(pb->dpy, &shminfo);
2014
XDestroyImage (img->ximg);
2015
shmdt(shminfo.shmaddr);
2016
shmctl(shminfo.shmid, IPC_RMID, 0);
2019
XFreeGC( pb->dpy, gc1 );
2020
img->ximg = NULL; /* Safety On */
2024
mb_pixbuf_img_data (MBPixbuf *pixbuf,
2025
MBPixbufImage *image)
2031
mb_pixbuf_img_get_pixel (MBPixbuf *pixbuf,
2043
idx = pixbuf->internal_bytespp + img->has_alpha;
2045
if (pixbuf->internal_bytespp == 2)
2047
int offset = ( (y * img->width * idx) + ( x * idx ) );
2048
internal_16bpp_pixel_to_rgb(img->rgba+offset, *r, *g, *b);
2051
*a = *(img->rgba+offset+2);
2057
*r = img->rgba[(((y)*img->width*idx)+((x)*idx))];
2058
*g = img->rgba[(((y)*img->width*idx)+((x)*idx))+1];
2059
*b = img->rgba[(((y)*img->width*idx)+((x)*idx))+2];
2062
*a = img->rgba[(((y)*img->width*idx)+((x)*idx))+3];
2070
mb_pixbuf_img_plot_pixel (MBPixbuf *pb,
2079
if (x >= img->width || y >= img->height) return;
2081
idx = pb->internal_bytespp + img->has_alpha;
2083
if (pb->internal_bytespp == 2)
2085
int offset = (((y)*img->width*idx)+((x)*idx));
2086
internal_rgb_to_16bpp_pixel(r,g,b, (img->rgba+offset));
2090
img->rgba[(((y)*img->width*idx)+((x)*idx))] = r;
2091
img->rgba[(((y)*img->width*idx)+((x)*idx))+1] = g;
2092
img->rgba[(((y)*img->width*idx)+((x)*idx))+2] = b;
2097
mb_pixbuf_img_plot_pixel_with_alpha (MBPixbuf *pb,
2106
int idx = (((y)*img->width*(pb->internal_bytespp+1))+((x)*(pb->internal_bytespp+1)));
2108
if (!img->has_alpha)
2110
mb_pixbuf_img_plot_pixel (pb, img, x, y, r, g, b );
2114
if (x >= img->width || y >= img->height) return;
2116
if (pb->internal_bytespp == 2)
2118
unsigned char rr,gg, bb;
2119
internal_16bpp_pixel_to_rgb((img->rgba+idx), rr,gg,bb);
2121
alpha_composite(rr, (r), (a), rr);
2122
alpha_composite(gg, (g), (a), gg);
2123
alpha_composite(bb, (b), (a), bb);
2125
internal_rgb_to_16bpp_pixel(rr,gg,bb, (img->rgba+idx));
2129
alpha_composite(img->rgba[idx], (r), (a), img->rgba[idx]);
2130
alpha_composite(img->rgba[idx+1], (g), (a), img->rgba[idx+1]);
2131
alpha_composite(img->rgba[idx+2], (b), (a), img->rgba[idx+2]);
2136
mb_pixbuf_img_transform (MBPixbuf *pb,
2138
MBPixbufTransform transform)
2140
MBPixbufImage *img_trans;
2141
int new_width = 0, new_height = 0, new_x = 0, new_y = 0, idx;
2142
int bytes_per_line, x, y;
2143
int byte_offset = 0, new_byte_offset = 0;
2147
case MBPIXBUF_TRANS_ROTATE_90:
2148
case MBPIXBUF_TRANS_ROTATE_270:
2149
new_width = mb_pixbuf_img_get_height(img);
2150
new_height = mb_pixbuf_img_get_width(img);
2152
case MBPIXBUF_TRANS_ROTATE_180:
2153
case MBPIXBUF_TRANS_FLIP_VERT:
2154
case MBPIXBUF_TRANS_FLIP_HORIZ:
2155
new_width = mb_pixbuf_img_get_width(img);
2156
new_height = mb_pixbuf_img_get_height(img);
2163
img_trans = mb_pixbuf_img_rgba_new(pb, new_width, new_height);
2164
bytes_per_line = (img->width * (pb->internal_bytespp+1));
2165
idx = pb->internal_bytespp +1 ;
2169
img_trans = mb_pixbuf_img_rgb_new(pb, new_width, new_height);
2170
bytes_per_line = (img->width * pb->internal_bytespp);
2171
idx = pb->internal_bytespp;
2174
for( y = 0; y < img->height; y++ )
2176
for( x = 0; x < img->width; x++ )
2180
/* XXX This could all be heavily optimised */
2183
case MBPIXBUF_TRANS_ROTATE_180:
2184
new_x = new_width - 1 - x;
2185
new_y = new_height - 1 - y;
2187
case MBPIXBUF_TRANS_ROTATE_270:
2189
new_y = img->width - x - 1;
2191
case MBPIXBUF_TRANS_ROTATE_90:
2192
new_x = img->height - y - 1;
2195
case MBPIXBUF_TRANS_FLIP_VERT:
2196
new_x = x; new_y = img->height - y - 1;
2198
case MBPIXBUF_TRANS_FLIP_HORIZ:
2199
new_y = y; new_x = img->width - x - 1;
2203
byte_offset = (y * bytes_per_line) + ( x * idx );
2204
new_byte_offset = (new_y * (new_width) * idx) + ( new_x * idx );
2206
img_trans->rgba[new_byte_offset] = img->rgba[byte_offset];
2207
img_trans->rgba[new_byte_offset+1] = img->rgba[byte_offset+1];
2209
if (pb->internal_bytespp > 2)
2210
img_trans->rgba[new_byte_offset+2] = img->rgba[byte_offset+2];
2213
img_trans->rgba[new_byte_offset+pb->internal_bytespp] = img->rgba[byte_offset+pb->internal_bytespp];