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