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 :
4  */
5 
6 /* convert.c - convert RImage to Pixmap
7  *  Raster graphics library
8  *
9  *  Copyright (c) 1997 Alfredo K. Kojima
10  *
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.
15  *
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.
20  *
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.
24  */
25 
26 #include "wmglobe.h"
27 
28 typedef struct RConversionTable {
29     unsigned short table[256];
30     unsigned short index;
31     struct RConversionTable *next;
32 } RConversionTable;
33 
34 
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;
40 
initmyconvert()41 void initmyconvert()
42 {
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));
52     ximgok = NULL;
53     return;
54 }
55 
56 
57 
computeTable(unsigned short mask,int hop)58 static unsigned short *computeTable(unsigned short mask, int hop)
59 {
60     RConversionTable *tmp = conversionTable;
61     int i;
62 
63     tmp = pif[hop];
64 
65     for (i = 0; i < 256; i++)
66 	tmp->table[i] = (i * mask + 0x7f) / 0xff;
67 
68     tmp->index = mask;
69     return tmp->table;
70 }
71 
72 
image2TrueColor(RContext * ctx,RImage * image)73 static RXImage *image2TrueColor(RContext * ctx, RImage * image)
74 {
75     RXImage *ximg;
76     register int x, y, r, g, b;
77     unsigned char *red, *grn, *blu;
78     unsigned long pixel;
79     unsigned short rmask, gmask, bmask;
80     unsigned short roffs, goffs, boffs;
81     unsigned short *rtable, *gtable, *btable;
82     int ofs;
83 
84     if (ximgok == NULL)
85 	ximgok =
86 	    RCreateXImage(ctx, ctx->depth, image->width, image->height);
87 
88     ximg = ximgok;
89     if (!ximg) {
90 	puts("err ");
91 	return NULL;
92     }
93 
94     red = image->data;
95     grn = image->data + 1;
96     blu = image->data + 2;
97 
98     roffs = ctx->red_offset;
99     goffs = ctx->green_offset;
100     boffs = ctx->blue_offset;
101 
102     rmask = ctx->visual->red_mask >> roffs;
103     gmask = ctx->visual->green_mask >> goffs;
104     bmask = ctx->visual->blue_mask >> boffs;
105 
106 
107 
108     rtable = computeTable(rmask, 0);
109     gtable = computeTable(gmask, 1);
110     btable = computeTable(bmask, 2);
111 
112     if (rtable == NULL || gtable == NULL || btable == NULL) {
113 	RErrorCode = RERR_NOMEMORY;
114 	RDestroyXImage(ctx, ximg);
115 	return NULL;
116     }
117     if (ctx->attribs->render_mode == RBestMatchRendering) {
118 	/* fake match */
119 #ifdef DEBUG
120 	puts("true color match");
121 #endif
122 	for (y = 0, ofs = 0; y < image->height; y++) {
123 	    for (x = 0; x < image->width; x++, ofs += 3) {
124 		/* reduce pixel */
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);
130 	    }
131 	}
132     } else {
133 	/* dither */
134 	short *rerr, *gerr, *berr;
135 	short *nrerr, *ngerr, *nberr;
136 	short *terr;
137 	int rer, ger, ber;
138 	const int dr = 0xff / rmask;
139 	const int dg = 0xff / gmask;
140 	const int db = 0xff / bmask;
141         register int x1;
142 
143 #ifdef DEBUG
144 	puts("true color dither");
145 #endif
146 	rerr = re;
147 	gerr = ge;
148 	berr = be;
149 	nrerr = nre;
150 	ngerr = nge;
151 	nberr = nbe;
152 
153 	if (!rerr || !gerr || !berr || !nrerr || !ngerr || !nberr) {
154 	    RErrorCode = RERR_NOMEMORY;
155 	    RDestroyXImage(ctx, ximg);
156 	    return NULL;
157 	}
158 	for (x = x1 = 0; x < image->width; x++, x1 += 3) {
159 
160 	    rerr[x] = red[x1];
161 	    gerr[x] = grn[x1];
162 	    berr[x] = blu[x1];
163 	}
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) {
168 
169                 for (x = 0, x1 = 3 * (ofs + image->width); x <
170                      image->width; x++, x1 += 3) {
171 
172 		    nrerr[x] = red[x1];
173 		    ngerr[x] = grn[x1];
174 		    nberr[x] = blu[x1];
175 		}
176 		/* last column */
177 		x1-=3;
178 		nrerr[x] = red[x1];
179 		ngerr[x] = grn[x1];
180 		nberr[x] = blu[x1];
181 	    }
182 	    for (x = 0; x < image->width; x++) {
183 		/* reduce pixel */
184 		if (rerr[x] > 0xff)
185 		    rerr[x] = 0xff;
186 		else if (rerr[x] < 0)
187 		    rerr[x] = 0;
188 		if (gerr[x] > 0xff)
189 		    gerr[x] = 0xff;
190 		else if (gerr[x] < 0)
191 		    gerr[x] = 0;
192 		if (berr[x] > 0xff)
193 		    berr[x] = 0xff;
194 		else if (berr[x] < 0)
195 		    berr[x] = 0;
196 
197 		r = rtable[rerr[x]];
198 		g = gtable[gerr[x]];
199 		b = btable[berr[x]];
200 
201 		pixel = (r << roffs) | (g << goffs) | (b << boffs);
202 		XPutPixel(ximg->image, x, y, pixel);
203 		/* calc error */
204 		rer = rerr[x] - r * dr;
205 		ger = gerr[x] - g * dg;
206 		ber = berr[x] - b * db;
207 
208 		/* distribute error */
209 		r = (rer * 3) / 8;
210 		g = (ger * 3) / 8;
211 		b = (ber * 3) / 8;
212 		/* x+1, y */
213 		rerr[x + 1] += r;
214 		gerr[x + 1] += g;
215 		berr[x + 1] += b;
216 		/* x, y+1 */
217 		nrerr[x] += r;
218 		ngerr[x] += g;
219 		nberr[x] += b;
220 		/* x+1, y+1 */
221 		nrerr[x + 1] += rer - 2 * r;
222 		ngerr[x + 1] += ger - 2 * g;
223 		nberr[x + 1] += ber - 2 * b;
224 	    }
225 	    ofs += image->width;
226 	    /* skip to next line */
227 	    terr = rerr;
228 	    rerr = nrerr;
229 	    nrerr = terr;
230 
231 	    terr = gerr;
232 	    gerr = ngerr;
233 	    ngerr = terr;
234 
235 	    terr = berr;
236 	    berr = nberr;
237 	    nberr = terr;
238 	}
239     }
240     return ximg;
241 }
242 
243 
image2PseudoColor(RContext * ctx,RImage * image)244 static RXImage *image2PseudoColor(RContext * ctx, RImage * image)
245 {
246     RXImage *ximg;
247     register int x, y, r, g, b;
248     unsigned char *red, *grn, *blu;
249     unsigned long pixel;
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;
256     char *data;
257     int ofs;
258     /*register unsigned char maxrgb = 0xff; */
259 
260     if (ximgok == NULL)
261 	ximgok =
262 	    RCreateXImage(ctx, ctx->depth, image->width, image->height);
263 
264     ximg = ximgok;
265 
266     if (!ximg) {
267 	puts("err psc");
268 	return NULL;
269     }
270     red = image->data;
271     grn = image->data + 1;
272     blu = image->data + 2;
273 
274     data = ximg->image->data;
275 
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);
280 
281     if (rtable == NULL || gtable == NULL || btable == NULL) {
282 	RErrorCode = RERR_NOMEMORY;
283 	RDestroyXImage(ctx, ximg);
284 	return NULL;
285     }
286     if (ctx->attribs->render_mode == RBestMatchRendering) {
287 	/* fake match */
288 #ifdef DEBUG
289 	printf("pseudo color match with %d colors per channel\n", cpc);
290 #endif
291 	for (y = 0, ofs = 0; y < image->height; y++) {
292 	    for (x = 0; x < image->width; x++, ofs += 3) {
293 		/* reduce pixel */
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);
300 	    }
301 	}
302     } else {
303 	/* dither */
304 	short *rerr, *gerr, *berr;
305 	short *nrerr, *ngerr, *nberr;
306 	short *terr;
307 	int rer, ger, ber;
308 	const int dr = 0xff / rmask;
309 	const int dg = 0xff / gmask;
310 	const int db = 0xff / bmask;
311         register int x1;
312 
313 #ifdef DEBUG
314 	printf("pseudo color dithering with %d colors per channel\n", cpc);
315 #endif
316 	rerr = re;
317 	gerr = ge;
318 	berr = be;
319 	nrerr = nre;
320 	ngerr = nge;
321 	nberr = nbe;
322 	if (!rerr || !gerr || !berr || !nrerr || !ngerr || !nberr) {
323 	    RErrorCode = RERR_NOMEMORY;
324 	    RDestroyXImage(ctx, ximg);
325 	    return NULL;
326 	}
327 	for (x = x1 = 0; x < image->width; x++, x1+=3) {
328 	    rerr[x] = red[x1];
329 	    gerr[x] = grn[x1];
330 	    berr[x] = blu[x1];
331 	}
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) {
336 		int x1;
337 		for (x = 0, x1 = 3*(ofs + image->width); x <
338                      image->width; x++, x1 += 3) {
339 		    nrerr[x] = red[x1];
340 		    ngerr[x] = grn[x1];
341 		    nberr[x] = blu[x1];
342 		}
343 		/* last column */
344 		x1-=3;
345 		nrerr[x] = red[x1];
346 		ngerr[x] = grn[x1];
347 		nberr[x] = blu[x1];
348 	    }
349 	    for (x = 0; x < image->width; x++, ofs++) {
350 		/* reduce pixel */
351 		if (rerr[x] > 0xff)
352 		    rerr[x] = 0xff;
353 		else if (rerr[x] < 0)
354 		    rerr[x] = 0;
355 		if (gerr[x] > 0xff)
356 		    gerr[x] = 0xff;
357 		else if (gerr[x] < 0)
358 		    gerr[x] = 0;
359 		if (berr[x] > 0xff)
360 		    berr[x] = 0xff;
361 		else if (berr[x] < 0)
362 		    berr[x] = 0;
363 
364 		r = rtable[rerr[x]];
365 		g = gtable[gerr[x]];
366 		b = btable[berr[x]];
367 
368 		pixel = r * cpccpc + g * cpc + b;
369 		/*data[ofs] = ctx->colors[pixel].pixel; */
370 		XPutPixel(ximg->image, x, y, ctx->colors[pixel].pixel);
371 
372 		/* calc error */
373 		rer = rerr[x] - r * dr;
374 		ger = gerr[x] - g * dg;
375 		ber = berr[x] - b * db;
376 
377 		/* distribute error */
378 		rerr[x + 1] += (rer * 7) / 16;
379 		gerr[x + 1] += (ger * 7) / 16;
380 		berr[x + 1] += (ber * 7) / 16;
381 
382 		nrerr[x] += (rer * 5) / 16;
383 		ngerr[x] += (ger * 5) / 16;
384 		nberr[x] += (ber * 5) / 16;
385 
386 		if (x > 0) {
387 		    nrerr[x - 1] += (rer * 3) / 16;
388 		    ngerr[x - 1] += (ger * 3) / 16;
389 		    nberr[x - 1] += (ber * 3) / 16;
390 		}
391 		nrerr[x + 1] += rer / 16;
392 		ngerr[x + 1] += ger / 16;
393 		nberr[x + 1] += ber / 16;
394 	    }
395 	    /* skip to next line */
396 	    terr = rerr;
397 	    rerr = nrerr;
398 	    nrerr = terr;
399 
400 	    terr = gerr;
401 	    gerr = ngerr;
402 	    ngerr = terr;
403 
404 	    terr = berr;
405 	    berr = nberr;
406 	    nberr = terr;
407 	}
408     }
409     ximg->image->data = (char *) data;
410 
411     return ximg;
412 }
413 
414 
image2GrayScale(RContext * ctx,RImage * image)415 static RXImage *image2GrayScale(RContext * ctx, RImage * image)
416 {
417     RXImage *ximg;
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;
423     char *data;
424     int ofs;
425     /*register unsigned char maxrgb = 0xff; */
426 
427     if (ximgok == NULL)
428 	ximgok =
429 	    RCreateXImage(ctx, ctx->depth, image->width, image->height);
430 
431     ximg = ximgok;
432 
433     if (!ximg) {
434 	puts("error!");
435 	return NULL;
436     }
437     red = image->data;
438     grn = image->data + 1;
439     blu = image->data + 2;
440 
441     data = ximg->image->data;
442 
443     if (ctx->vclass == StaticGray)
444 	gmask = (1 << ctx->depth) - 1;	/* use all grays */
445     else
446 	gmask = cpc * cpc * cpc - 1;
447 
448     table = computeTable(gmask, 0);
449 
450     if (table == NULL) {
451 	RErrorCode = RERR_NOMEMORY;
452 	RDestroyXImage(ctx, ximg);
453 	return NULL;
454     }
455     if (ctx->attribs->render_mode == RBestMatchRendering) {
456 	/* fake match */
457 #ifdef DEBUG
458 	printf("grayscale match with %d colors per channel\n", cpc);
459 #endif
460 	for (y = 0, ofs = 0; y < image->height; y++) {
461 	    for (x = 0; x < image->width; x++, ofs++) {
462 		/* reduce pixel */
463 		g =
464 		    table[(red[ofs] * 30 + grn[ofs] * 59 + blu[ofs] * 11) /
465 			  100];
466 
467 		/*data[ofs] = ctx->colors[g].pixel; */
468 		XPutPixel(ximg->image, x, y, ctx->colors[g].pixel);
469 	    }
470 	}
471     } else {
472 	/* dither */
473 	short *gerr;
474 	short *ngerr;
475 	short *terr;
476 	int ger;
477 	const int dg = 0xff / gmask;
478 
479 #ifdef DEBUG
480 	printf("grayscale dither with %d colors per channel\n", cpc);
481 #endif
482 	gerr = ge;
483 	ngerr = nge;
484 	if (!gerr || !ngerr) {
485 	    RErrorCode = RERR_NOMEMORY;
486 	    RDestroyXImage(ctx, ximg);
487 	    return NULL;
488 	}
489 	for (x = 0; x < image->width; x++) {
490 	    gerr[x] = (red[x] * 30 + grn[x] * 59 + blu[x] * 11) / 100;
491 	}
492 	gerr[x] = 0;
493 	/* convert and dither the image to XImage */
494 	for (y = 0, ofs = 0; y < image->height; y++) {
495 	    if (y < image->height - 1) {
496 		int x1;
497 		for (x = 0, x1 = ofs + image->width; x < image->width;
498 		     x++, x1++) {
499 		    ngerr[x] =
500 			(red[x1] * 30 + grn[x1] * 59 + blu[x1] * 11) / 100;
501 		}
502 		/* last column */
503 		x1--;
504 		ngerr[x] =
505 		    (red[x1] * 30 + grn[x1] * 59 + blu[x1] * 11) / 100;
506 	    }
507 	    for (x = 0; x < image->width; x++, ofs++) {
508 		/* reduce pixel */
509 		if (gerr[x] > 0xff)
510 		    gerr[x] = 0xff;
511 		else if (gerr[x] < 0)
512 		    gerr[x] = 0;
513 
514 		g = table[gerr[x]];
515 
516 		/*data[ofs] = ctx->colors[g].pixel; */
517 		XPutPixel(ximg->image, x, y, ctx->colors[g].pixel);
518 		/* calc error */
519 		ger = gerr[x] - g * dg;
520 
521 		/* distribute error */
522 		g = (ger * 3) / 8;
523 		/* x+1, y */
524 		gerr[x + 1] += g;
525 		/* x, y+1 */
526 		ngerr[x] += g;
527 		/* x+1, y+1 */
528 		ngerr[x + 1] += ger - 2 * g;
529 	    }
530 	    /* skip to next line */
531 	    terr = gerr;
532 	    gerr = ngerr;
533 	    ngerr = terr;
534 	}
535     }
536     ximg->image->data = (char *) data;
537 
538     return ximg;
539 }
540 
541 
542 
myRConvertImage(RContext * context,RImage * image,Pixmap * pixmap)543 int myRConvertImage(RContext * context, RImage * image, Pixmap * pixmap)
544 {
545     RXImage *ximg = NULL;
546 
547 
548     assert(context != NULL);
549     assert(image != NULL);
550     assert(pixmap != NULL);
551 
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);
560 
561     if (!ximg) {
562 #ifdef C_ALLOCA
563 	alloca(0);
564 #endif
565 	return False;
566     }
567 /*
568  *     *pixmap = XCreatePixmap(context->dpy, context->drawable, image->width,
569  *                          image->height, context->depth);
570  */
571 
572 
573     RPutXImage(context, *pixmap, context->copy_gc, ximg, 0, 0, 0, 0,
574 	       image->width, image->height);
575 
576 
577 /*
578  *     RDestroyXImage(context, ximg);
579  */
580 
581 #ifdef C_ALLOCA
582 
583     alloca(0);
584 #endif
585     return True;
586 }
587