1 /* WMGlobe 1.3 - All the Earth on a WMaker Icon
2 * myconvert.c - an adaptation of wrlib for use in wmglobe
3 * initial source taken in WindowMaker-0.20.3/wrlib :
6 /* convert.c - convert RImage to Pixmap
7 * Raster graphics library
9 * Copyright (c) 1997 Alfredo K. Kojima
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Library General Public
13 * License as published by the Free Software Foundation; either
14 * version 2 of the License, or (at your option) any later version.
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Library General Public License for more details.
21 * You should have received a copy of the GNU Library General Public
22 * License along with this library; if not, write to the Free
23 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
28 typedef struct RConversionTable
{
29 unsigned short table
[256];
31 struct RConversionTable
*next
;
35 static RConversionTable
*conversionTable
= NULL
;
36 static RConversionTable
*pif
[3];
37 static short *re
, *ge
, *be
;
38 static short *nre
, *nge
, *nbe
;
39 static RXImage
*ximgok
;
43 pif
[0] = (RConversionTable
*) malloc(sizeof(RConversionTable
));
44 pif
[1] = (RConversionTable
*) malloc(sizeof(RConversionTable
));
45 pif
[2] = (RConversionTable
*) malloc(sizeof(RConversionTable
));
46 re
= (short *) malloc((DIAMETRE
+ 2) * sizeof(short));
47 ge
= (short *) malloc((DIAMETRE
+ 2) * sizeof(short));
48 be
= (short *) malloc((DIAMETRE
+ 2) * sizeof(short));
49 nre
= (short *) malloc((DIAMETRE
+ 2) * sizeof(short));
50 nge
= (short *) malloc((DIAMETRE
+ 2) * sizeof(short));
51 nbe
= (short *) malloc((DIAMETRE
+ 2) * sizeof(short));
58 static unsigned short *computeTable(unsigned short mask
, int hop
)
60 RConversionTable
*tmp
= conversionTable
;
65 for (i
= 0; i
< 256; i
++)
66 tmp
->table
[i
] = (i
* mask
+ 0x7f) / 0xff;
73 static RXImage
*image2TrueColor(RContext
* ctx
, RImage
* image
)
76 register int x
, y
, r
, g
, b
;
77 unsigned char *red
, *grn
, *blu
;
79 unsigned short rmask
, gmask
, bmask
;
80 unsigned short roffs
, goffs
, boffs
;
81 unsigned short *rtable
, *gtable
, *btable
;
86 RCreateXImage(ctx
, ctx
->depth
, image
->width
, image
->height
);
95 grn
= image
->data
+ 1;
96 blu
= image
->data
+ 2;
98 roffs
= ctx
->red_offset
;
99 goffs
= ctx
->green_offset
;
100 boffs
= ctx
->blue_offset
;
102 rmask
= ctx
->visual
->red_mask
>> roffs
;
103 gmask
= ctx
->visual
->green_mask
>> goffs
;
104 bmask
= ctx
->visual
->blue_mask
>> boffs
;
108 rtable
= computeTable(rmask
, 0);
109 gtable
= computeTable(gmask
, 1);
110 btable
= computeTable(bmask
, 2);
112 if (rtable
== NULL
|| gtable
== NULL
|| btable
== NULL
) {
113 RErrorCode
= RERR_NOMEMORY
;
114 RDestroyXImage(ctx
, ximg
);
117 if (ctx
->attribs
->render_mode
== RBestMatchRendering
) {
120 puts("true color match");
122 for (y
= 0, ofs
= 0; y
< image
->height
; y
++) {
123 for (x
= 0; x
< image
->width
; x
++, ofs
+= 3) {
125 r
= rtable
[red
[ofs
]];
126 g
= gtable
[grn
[ofs
]];
127 b
= btable
[blu
[ofs
]];
128 pixel
= (r
<< roffs
) | (g
<< goffs
) | (b
<< boffs
);
129 XPutPixel(ximg
->image
, x
, y
, pixel
);
134 short *rerr
, *gerr
, *berr
;
135 short *nrerr
, *ngerr
, *nberr
;
138 const int dr
= 0xff / rmask
;
139 const int dg
= 0xff / gmask
;
140 const int db
= 0xff / bmask
;
144 puts("true color dither");
153 if (!rerr
|| !gerr
|| !berr
|| !nrerr
|| !ngerr
|| !nberr
) {
154 RErrorCode
= RERR_NOMEMORY
;
155 RDestroyXImage(ctx
, ximg
);
158 for (x
= x1
= 0; x
< image
->width
; x
++, x1
+= 3) {
164 rerr
[x
] = gerr
[x
] = berr
[x
] = 0;
165 /* convert and dither the image to XImage */
166 for (y
= 0, ofs
= 0; y
< image
->height
; y
++) {
167 if (y
< image
->height
- 1) {
169 for (x
= 0, x1
= 3 * (ofs
+ image
->width
); x
<
170 image
->width
; x
++, x1
+= 3) {
182 for (x
= 0; x
< image
->width
; x
++) {
186 else if (rerr
[x
] < 0)
190 else if (gerr
[x
] < 0)
194 else if (berr
[x
] < 0)
201 pixel
= (r
<< roffs
) | (g
<< goffs
) | (b
<< boffs
);
202 XPutPixel(ximg
->image
, x
, y
, pixel
);
204 rer
= rerr
[x
] - r
* dr
;
205 ger
= gerr
[x
] - g
* dg
;
206 ber
= berr
[x
] - b
* db
;
208 /* distribute error */
221 nrerr
[x
+ 1] += rer
- 2 * r
;
222 ngerr
[x
+ 1] += ger
- 2 * g
;
223 nberr
[x
+ 1] += ber
- 2 * b
;
226 /* skip to next line */
244 static RXImage
*image2PseudoColor(RContext
* ctx
, RImage
* image
)
247 register int x
, y
, r
, g
, b
;
248 unsigned char *red
, *grn
, *blu
;
250 const int cpc
= ctx
->attribs
->colors_per_channel
;
251 const unsigned short rmask
= cpc
- 1; /* different sizes could be used */
252 const unsigned short gmask
= rmask
; /* for r,g,b */
253 const unsigned short bmask
= rmask
;
254 unsigned short *rtable
, *gtable
, *btable
;
255 const int cpccpc
= cpc
* cpc
;
258 /*register unsigned char maxrgb = 0xff; */
262 RCreateXImage(ctx
, ctx
->depth
, image
->width
, image
->height
);
271 grn
= image
->data
+ 1;
272 blu
= image
->data
+ 2;
274 data
= ximg
->image
->data
;
276 /* Tables are same at the moment because rmask==gmask==bmask. */
277 rtable
= computeTable(rmask
, 0);
278 gtable
= computeTable(gmask
, 1);
279 btable
= computeTable(bmask
, 2);
281 if (rtable
== NULL
|| gtable
== NULL
|| btable
== NULL
) {
282 RErrorCode
= RERR_NOMEMORY
;
283 RDestroyXImage(ctx
, ximg
);
286 if (ctx
->attribs
->render_mode
== RBestMatchRendering
) {
289 printf("pseudo color match with %d colors per channel\n", cpc
);
291 for (y
= 0, ofs
= 0; y
< image
->height
; y
++) {
292 for (x
= 0; x
< image
->width
; x
++, ofs
+= 3) {
294 r
= rtable
[red
[ofs
]];
295 g
= gtable
[grn
[ofs
]];
296 b
= btable
[blu
[ofs
]];
297 pixel
= r
* cpccpc
+ g
* cpc
+ b
;
298 /*data[ofs] = ctx->colors[pixel].pixel; */
299 XPutPixel(ximg
->image
, x
, y
, ctx
->colors
[pixel
].pixel
);
304 short *rerr
, *gerr
, *berr
;
305 short *nrerr
, *ngerr
, *nberr
;
308 const int dr
= 0xff / rmask
;
309 const int dg
= 0xff / gmask
;
310 const int db
= 0xff / bmask
;
314 printf("pseudo color dithering with %d colors per channel\n", cpc
);
322 if (!rerr
|| !gerr
|| !berr
|| !nrerr
|| !ngerr
|| !nberr
) {
323 RErrorCode
= RERR_NOMEMORY
;
324 RDestroyXImage(ctx
, ximg
);
327 for (x
= x1
= 0; x
< image
->width
; x
++, x1
+=3) {
332 rerr
[x
] = gerr
[x
] = berr
[x
] = 0;
333 /* convert and dither the image to XImage */
334 for (y
= 0, ofs
= 0; y
< image
->height
; y
++) {
335 if (y
< image
->height
- 1) {
337 for (x
= 0, x1
= 3*(ofs
+ image
->width
); x
<
338 image
->width
; x
++, x1
+= 3) {
349 for (x
= 0; x
< image
->width
; x
++, ofs
++) {
353 else if (rerr
[x
] < 0)
357 else if (gerr
[x
] < 0)
361 else if (berr
[x
] < 0)
368 pixel
= r
* cpccpc
+ g
* cpc
+ b
;
369 /*data[ofs] = ctx->colors[pixel].pixel; */
370 XPutPixel(ximg
->image
, x
, y
, ctx
->colors
[pixel
].pixel
);
373 rer
= rerr
[x
] - r
* dr
;
374 ger
= gerr
[x
] - g
* dg
;
375 ber
= berr
[x
] - b
* db
;
377 /* distribute error */
378 rerr
[x
+ 1] += (rer
* 7) / 16;
379 gerr
[x
+ 1] += (ger
* 7) / 16;
380 berr
[x
+ 1] += (ber
* 7) / 16;
382 nrerr
[x
] += (rer
* 5) / 16;
383 ngerr
[x
] += (ger
* 5) / 16;
384 nberr
[x
] += (ber
* 5) / 16;
387 nrerr
[x
- 1] += (rer
* 3) / 16;
388 ngerr
[x
- 1] += (ger
* 3) / 16;
389 nberr
[x
- 1] += (ber
* 3) / 16;
391 nrerr
[x
+ 1] += rer
/ 16;
392 ngerr
[x
+ 1] += ger
/ 16;
393 nberr
[x
+ 1] += ber
/ 16;
395 /* skip to next line */
409 ximg
->image
->data
= (char *) data
;
415 static RXImage
*image2GrayScale(RContext
* ctx
, RImage
* image
)
418 register int x
, y
, g
;
419 unsigned char *red
, *grn
, *blu
;
420 const int cpc
= ctx
->attribs
->colors_per_channel
;
421 unsigned short gmask
;
422 unsigned short *table
;
425 /*register unsigned char maxrgb = 0xff; */
429 RCreateXImage(ctx
, ctx
->depth
, image
->width
, image
->height
);
438 grn
= image
->data
+ 1;
439 blu
= image
->data
+ 2;
441 data
= ximg
->image
->data
;
443 if (ctx
->vclass
== StaticGray
)
444 gmask
= (1 << ctx
->depth
) - 1; /* use all grays */
446 gmask
= cpc
* cpc
* cpc
- 1;
448 table
= computeTable(gmask
, 0);
451 RErrorCode
= RERR_NOMEMORY
;
452 RDestroyXImage(ctx
, ximg
);
455 if (ctx
->attribs
->render_mode
== RBestMatchRendering
) {
458 printf("grayscale match with %d colors per channel\n", cpc
);
460 for (y
= 0, ofs
= 0; y
< image
->height
; y
++) {
461 for (x
= 0; x
< image
->width
; x
++, ofs
++) {
464 table
[(red
[ofs
] * 30 + grn
[ofs
] * 59 + blu
[ofs
] * 11) /
467 /*data[ofs] = ctx->colors[g].pixel; */
468 XPutPixel(ximg
->image
, x
, y
, ctx
->colors
[g
].pixel
);
477 const int dg
= 0xff / gmask
;
480 printf("grayscale dither with %d colors per channel\n", cpc
);
484 if (!gerr
|| !ngerr
) {
485 RErrorCode
= RERR_NOMEMORY
;
486 RDestroyXImage(ctx
, ximg
);
489 for (x
= 0; x
< image
->width
; x
++) {
490 gerr
[x
] = (red
[x
] * 30 + grn
[x
] * 59 + blu
[x
] * 11) / 100;
493 /* convert and dither the image to XImage */
494 for (y
= 0, ofs
= 0; y
< image
->height
; y
++) {
495 if (y
< image
->height
- 1) {
497 for (x
= 0, x1
= ofs
+ image
->width
; x
< image
->width
;
500 (red
[x1
] * 30 + grn
[x1
] * 59 + blu
[x1
] * 11) / 100;
505 (red
[x1
] * 30 + grn
[x1
] * 59 + blu
[x1
] * 11) / 100;
507 for (x
= 0; x
< image
->width
; x
++, ofs
++) {
511 else if (gerr
[x
] < 0)
516 /*data[ofs] = ctx->colors[g].pixel; */
517 XPutPixel(ximg
->image
, x
, y
, ctx
->colors
[g
].pixel
);
519 ger
= gerr
[x
] - g
* dg
;
521 /* distribute error */
528 ngerr
[x
+ 1] += ger
- 2 * g
;
530 /* skip to next line */
536 ximg
->image
->data
= (char *) data
;
543 int myRConvertImage(RContext
* context
, RImage
* image
, Pixmap
* pixmap
)
545 RXImage
*ximg
= NULL
;
548 assert(context
!= NULL
);
549 assert(image
!= NULL
);
550 assert(pixmap
!= NULL
);
552 /* clear error message */
553 if (context
->vclass
== TrueColor
)
554 ximg
= image2TrueColor(context
, image
);
555 else if (context
->vclass
== PseudoColor
556 || context
->vclass
== StaticColor
) ximg
=
557 image2PseudoColor(context
, image
);
558 else if (context
->vclass
== GrayScale
|| context
->vclass
== StaticGray
)
559 ximg
= image2GrayScale(context
, image
);
568 * *pixmap = XCreatePixmap(context->dpy, context->drawable, image->width,
569 * image->height, context->depth);
573 RPutXImage(context
, *pixmap
, context
->copy_gc
, ximg
, 0, 0, 0, 0,
574 image
->width
, image
->height
);
578 * RDestroyXImage(context, ximg);