Change to the linux kernel coding style
[wmaker-crm.git] / wrlib / convert.c
Commit [+]AuthorDateLineData
9d2e6ef9 scottc1998-09-29 22:36:29 +00001/* convert.c - convert RImage to Pixmap
6830b057 dan2004-10-12 21:28:27 +00002 *
4153e2fd dan2003-01-16 23:30:45 +00003 * Raster graphics library
9d2e6ef9 scottc1998-09-29 22:36:29 +00004 *
4153e2fd dan2003-01-16 23:30:45 +00005 * Copyright (c) 1997-2003 Alfredo K. Kojima
9d2e6ef9 scottc1998-09-29 22:36:29 +00006 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
6830b057 dan2004-10-12 21:28:27 +000011 *
9d2e6ef9 scottc1998-09-29 22:36:29 +000012 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
6830b057 dan2004-10-12 21:28:27 +000016 *
9d2e6ef9 scottc1998-09-29 22:36:29 +000017 * You should have received a copy of the GNU Library General Public
18 * License along with this library; if not, write to the Free
19 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
c720860e dan2001-02-26 00:43:44 +000021
22/* Problems:
23 * 1. Using Grayscale visual with Dithering crashes wmaker
24 * 2. Ghost dock/appicon is wrong in Pseudocolor, Staticgray, Grayscale
25 */
26
9d2e6ef9 scottc1998-09-29 22:36:29 +000027#include <config.h>
28
9d2e6ef9 scottc1998-09-29 22:36:29 +000029#include <X11/Xlib.h>
30#include <X11/Xutil.h>
31#include <stdlib.h>
32#include <stdio.h>
33#include <string.h>
34
35#include <assert.h>
36
a30475fc kojima2000-01-14 16:39:15 +000037#ifdef BENCH
38#include "bench.h"
39#endif
40
1941aaf3 dan2002-09-30 12:39:22 +000041#include "wraster.h"
9d2e6ef9 scottc1998-09-29 22:36:29 +000042
9af1c6c4 dan1998-10-21 14:43:47 +000043#ifdef XSHM
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +020044extern Pixmap R_CreateXImageMappedPixmap(RContext * context, RXImage * ximage);
9af1c6c4 dan1998-10-21 14:43:47 +000045
46#endif
9d2e6ef9 scottc1998-09-29 22:36:29 +000047
1941aaf3 dan2002-09-30 12:39:22 +000048#ifdef ASM_X86
49extern void x86_PseudoColor_32_to_8(unsigned char *image,
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +020050 unsigned char *ximage,
51 char *err, char *nerr,
52 short *ctable,
53 int dr, int dg, int db,
54 unsigned long *pixels,
55 int cpc, int width, int height, int bytesPerPixel, int line_offset);
56#endif /* ASM_X86 */
1941aaf3 dan2002-09-30 12:39:22 +000057
58#ifdef ASM_X86_MMX
59
60extern int x86_check_mmx();
61
62extern void x86_mmx_TrueColor_32_to_16(unsigned char *image,
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +020063 unsigned short *ximage,
64 short *err, short *nerr,
65 const unsigned short *rtable,
66 const unsigned short *gtable,
67 const unsigned short *btable,
68 int dr, int dg, int db,
69 unsigned int roffs,
70 unsigned int goffs,
71 unsigned int boffs, int width, int height, int line_offset);
72
73#endif /* ASM_X86_MMX */
1941aaf3 dan2002-09-30 12:39:22 +000074
75#define NFREE(n) if (n) free(n)
76
c720860e dan2001-02-26 00:43:44 +000077#define HAS_ALPHA(I) ((I)->format == RRGBAFormat)
78
9d2e6ef9 scottc1998-09-29 22:36:29 +000079typedef struct RConversionTable {
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +020080 unsigned short table[256];
81 unsigned short index;
33b8c225 kojima1999-11-16 00:13:21 +000082
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +020083 struct RConversionTable *next;
9d2e6ef9 scottc1998-09-29 22:36:29 +000084} RConversionTable;
85
33b8c225 kojima1999-11-16 00:13:21 +000086typedef struct RStdConversionTable {
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +020087 unsigned int table[256];
33b8c225 kojima1999-11-16 00:13:21 +000088
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +020089 unsigned short mult;
90 unsigned short max;
33b8c225 kojima1999-11-16 00:13:21 +000091
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +020092 struct RStdConversionTable *next;
33b8c225 kojima1999-11-16 00:13:21 +000093} RStdConversionTable;
94
9d2e6ef9 scottc1998-09-29 22:36:29 +000095static RConversionTable *conversionTable = NULL;
33b8c225 kojima1999-11-16 00:13:21 +000096static RStdConversionTable *stdConversionTable = NULL;
9d2e6ef9 scottc1998-09-29 22:36:29 +000097
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +020098static unsigned short *computeTable(unsigned short mask)
9d2e6ef9 scottc1998-09-29 22:36:29 +000099{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200100 RConversionTable *tmp = conversionTable;
101 int i;
9d2e6ef9 scottc1998-09-29 22:36:29 +0000102
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200103 while (tmp) {
104 if (tmp->index == mask)
105 break;
106 tmp = tmp->next;
107 }
9d2e6ef9 scottc1998-09-29 22:36:29 +0000108
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200109 if (tmp)
110 return tmp->table;
9d2e6ef9 scottc1998-09-29 22:36:29 +0000111
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200112 tmp = (RConversionTable *) malloc(sizeof(RConversionTable));
113 if (tmp == NULL)
114 return NULL;
9d2e6ef9 scottc1998-09-29 22:36:29 +0000115
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200116 for (i = 0; i < 256; i++)
117 tmp->table[i] = (i * mask + 0x7f) / 0xff;
9d2e6ef9 scottc1998-09-29 22:36:29 +0000118
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200119 tmp->index = mask;
120 tmp->next = conversionTable;
121 conversionTable = tmp;
122 return tmp->table;
9d2e6ef9 scottc1998-09-29 22:36:29 +0000123}
124
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200125static unsigned int *computeStdTable(unsigned int mult, unsigned int max)
33b8c225 kojima1999-11-16 00:13:21 +0000126{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200127 RStdConversionTable *tmp = stdConversionTable;
128 unsigned int i;
33b8c225 kojima1999-11-16 00:13:21 +0000129
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200130 while (tmp) {
131 if (tmp->mult == mult && tmp->max == max)
132 break;
133 tmp = tmp->next;
134 }
33b8c225 kojima1999-11-16 00:13:21 +0000135
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200136 if (tmp)
137 return tmp->table;
33b8c225 kojima1999-11-16 00:13:21 +0000138
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200139 tmp = (RStdConversionTable *) malloc(sizeof(RStdConversionTable));
140 if (tmp == NULL)
141 return NULL;
33b8c225 kojima1999-11-16 00:13:21 +0000142
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200143 for (i = 0; i < 256; i++) {
144 tmp->table[i] = (i * max) / 0xff * mult;
145 }
146 tmp->mult = mult;
147 tmp->max = max;
33b8c225 kojima1999-11-16 00:13:21 +0000148
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200149 tmp->next = stdConversionTable;
150 stdConversionTable = tmp;
33b8c225 kojima1999-11-16 00:13:21 +0000151
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200152 return tmp->table;
33b8c225 kojima1999-11-16 00:13:21 +0000153}
154
a30475fc kojima2000-01-14 16:39:15 +0000155/***************************************************************************/
33b8c225 kojima1999-11-16 00:13:21 +0000156
a30475fc kojima2000-01-14 16:39:15 +0000157static void
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200158convertTrueColor_generic(RXImage * ximg, RImage * image,
159 signed char *err, signed char *nerr,
160 const unsigned short *rtable,
161 const unsigned short *gtable,
162 const unsigned short *btable,
163 const int dr, const int dg, const int db,
164 const unsigned short roffs, const unsigned short goffs, const unsigned short boffs)
8f68cfd8 kojima1999-04-29 23:05:16 +0000165{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200166 signed char *terr;
167 int x, y, r, g, b;
168 int pixel;
169 int rer, ger, ber;
170 unsigned char *ptr = image->data;
171 int channels = (HAS_ALPHA(image) ? 4 : 3);
172
173 /* convert and dither the image to XImage */
174 for (y = 0; y < image->height; y++) {
175 nerr[0] = 0;
176 nerr[1] = 0;
177 nerr[2] = 0;
178 for (x = 0; x < image->width; x++, ptr += channels) {
179
180 /* reduce pixel */
181 pixel = *ptr + err[x];
182 if (pixel < 0)
183 pixel = 0;
184 else if (pixel > 0xff)
185 pixel = 0xff;
186 r = rtable[pixel];
187 /* calc error */
188 rer = pixel - r * dr;
189
190 /* reduce pixel */
191 pixel = *(ptr + 1) + err[x + 1];
192 if (pixel < 0)
193 pixel = 0;
194 else if (pixel > 0xff)
195 pixel = 0xff;
196 g = gtable[pixel];
197 /* calc error */
198 ger = pixel - g * dg;
199
200 /* reduce pixel */
201 pixel = *(ptr + 2) + err[x + 2];
202 if (pixel < 0)
203 pixel = 0;
204 else if (pixel > 0xff)
205 pixel = 0xff;
206 b = btable[pixel];
207 /* calc error */
208 ber = pixel - b * db;
209
210 pixel = (r << roffs) | (g << goffs) | (b << boffs);
211 XPutPixel(ximg->image, x, y, pixel);
212
213 /* distribute error */
214 r = (rer * 3) / 8;
215 g = (ger * 3) / 8;
216 b = (ber * 3) / 8;
217 /* x+1, y */
218 err[x + 3 * 1] += r;
219 err[x + 1 + 3 * 1] += g;
220 err[x + 2 + 3 * 1] += b;
221 /* x, y+1 */
222 nerr[x] += r;
223 nerr[x + 1] += g;
224 nerr[x + 2] += b;
225 /* x+1, y+1 */
226 nerr[x + 3 * 1] = rer - 2 * r;
227 nerr[x + 1 + 3 * 1] = ger - 2 * g;
228 nerr[x + 2 + 3 * 1] = ber - 2 * b;
229 }
230 /* skip to next line */
231 terr = err;
232 err = nerr;
233 nerr = terr;
234 }
235
236 /* redither the 1st line to distribute error better */
237 ptr = image->data;
238 y = 0;
239 nerr[0] = 0;
240 nerr[1] = 0;
241 nerr[2] = 0;
242 for (x = 0; x < image->width; x++, ptr += channels) {
243
244 /* reduce pixel */
245 pixel = *ptr + err[x];
246 if (pixel < 0)
247 pixel = 0;
248 else if (pixel > 0xff)
249 pixel = 0xff;
250 r = rtable[pixel];
251 /* calc error */
252 rer = pixel - r * dr;
253
254 /* reduce pixel */
255 pixel = *(ptr + 1) + err[x + 1];
256 if (pixel < 0)
257 pixel = 0;
258 else if (pixel > 0xff)
259 pixel = 0xff;
260 g = gtable[pixel];
261 /* calc error */
262 ger = pixel - g * dg;
263
264 /* reduce pixel */
265 pixel = *(ptr + 2) + err[x + 2];
266 if (pixel < 0)
267 pixel = 0;
268 else if (pixel > 0xff)
269 pixel = 0xff;
270 b = btable[pixel];
271 /* calc error */
272 ber = pixel - b * db;
273
274 pixel = (r << roffs) | (g << goffs) | (b << boffs);
275 XPutPixel(ximg->image, x, y, pixel);
276
277 /* distribute error */
278 r = (rer * 3) / 8;
279 g = (ger * 3) / 8;
280 b = (ber * 3) / 8;
281 /* x+1, y */
282 err[x + 3 * 1] += r;
283 err[x + 1 + 3 * 1] += g;
284 err[x + 2 + 3 * 1] += b;
285 /* x, y+1 */
286 nerr[x] += r;
287 nerr[x + 1] += g;
288 nerr[x + 2] += b;
289 /* x+1, y+1 */
290 nerr[x + 3 * 1] = rer - 2 * r;
291 nerr[x + 1 + 3 * 1] = ger - 2 * g;
292 nerr[x + 2 + 3 * 1] = ber - 2 * b;
293 }
8f68cfd8 kojima1999-04-29 23:05:16 +0000294}
295
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200296static RXImage *image2TrueColor(RContext * ctx, RImage * image)
9d2e6ef9 scottc1998-09-29 22:36:29 +0000297{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200298 RXImage *ximg;
299 unsigned short rmask, gmask, bmask;
300 unsigned short roffs, goffs, boffs;
301 unsigned short *rtable, *gtable, *btable;
302 int channels = (HAS_ALPHA(image) ? 4 : 3);
303
304 ximg = RCreateXImage(ctx, ctx->depth, image->width, image->height);
305 if (!ximg) {
306 return NULL;
307 }
308
309 roffs = ctx->red_offset;
310 goffs = ctx->green_offset;
311 boffs = ctx->blue_offset;
312
313 rmask = ctx->visual->red_mask >> roffs;
314 gmask = ctx->visual->green_mask >> goffs;
315 bmask = ctx->visual->blue_mask >> boffs;
316
317 rtable = computeTable(rmask);
318 gtable = computeTable(gmask);
319 btable = computeTable(bmask);
320
321 if (rtable == NULL || gtable == NULL || btable == NULL) {
322 RErrorCode = RERR_NOMEMORY;
323 RDestroyXImage(ctx, ximg);
324 return NULL;
325 }
5d5eaf33 dan2000-02-09 03:46:55 +0000326
327#ifdef BENCH
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200328 cycle_bench(1);
5d5eaf33 dan2000-02-09 03:46:55 +0000329#endif
330
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200331 if (ctx->attribs->render_mode == RBestMatchRendering) {
332 int ofs, r, g, b;
333 int x, y;
334 unsigned long pixel;
335 unsigned char *ptr = image->data;
6830b057 dan2004-10-12 21:28:27 +0000336
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200337 /* fake match */
9d2e6ef9 scottc1998-09-29 22:36:29 +0000338#ifdef DEBUG
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200339 puts("true color match");
9d2e6ef9 scottc1998-09-29 22:36:29 +0000340#endif
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200341 if (rmask == 0xff && gmask == 0xff && bmask == 0xff) {
342 for (y = 0; y < image->height; y++) {
343 for (x = 0; x < image->width; x++, ptr += channels) {
344 /* reduce pixel */
345 pixel = (*(ptr) << roffs) | (*(ptr + 1) << goffs) | (*(ptr + 2) << boffs);
346 XPutPixel(ximg->image, x, y, pixel);
347 }
348 }
349 } else {
350 for (y = 0, ofs = 0; y < image->height; y++) {
351 for (x = 0; x < image->width; x++, ofs += channels - 3) {
352 /* reduce pixel */
353 r = rtable[ptr[ofs++]];
354 g = gtable[ptr[ofs++]];
355 b = btable[ptr[ofs++]];
356 pixel = (r << roffs) | (g << goffs) | (b << boffs);
357 XPutPixel(ximg->image, x, y, pixel);
358 }
359 }
360 }
361 } else {
362 /* dither */
363 const int dr = 0xff / rmask;
364 const int dg = 0xff / gmask;
365 const int db = 0xff / bmask;
9d2e6ef9 scottc1998-09-29 22:36:29 +0000366
367#ifdef DEBUG
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200368 puts("true color dither");
1941aaf3 dan2002-09-30 12:39:22 +0000369#endif
370
371#ifdef ASM_X86_MMX
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200372 if (ctx->depth == 16 && HAS_ALPHA(image) && x86_check_mmx()) {
373 short *err;
374 short *nerr;
375
376 err = malloc(8 * (image->width + 3));
377 nerr = malloc(8 * (image->width + 3));
378 if (!err || !nerr) {
379 NFREE(err);
380 NFREE(nerr);
381 RErrorCode = RERR_NOMEMORY;
382 RDestroyXImage(ctx, ximg);
383 return NULL;
384 }
385 memset(err, 0, 8 * (image->width + 3));
386 memset(nerr, 0, 8 * (image->width + 3));
387
388 x86_mmx_TrueColor_32_to_16(image->data,
389 (unsigned short *)ximg->image->data,
390 err + 8, nerr + 8,
391 rtable, gtable, btable,
392 dr, dg, db,
393 roffs, goffs, boffs,
394 image->width, image->height,
395 ximg->image->bytes_per_line - 2 * image->width);
396
397 free(err);
398 free(nerr);
399 } else
400#endif /* ASM_X86_MMX */
401 {
402 signed char *err;
403 signed char *nerr;
404 int ch = (HAS_ALPHA(image) ? 4 : 3);
405
406 err = malloc(ch * (image->width + 2));
407 nerr = malloc(ch * (image->width + 2));
408 if (!err || !nerr) {
409 NFREE(err);
410 NFREE(nerr);
411 RErrorCode = RERR_NOMEMORY;
412 RDestroyXImage(ctx, ximg);
413 return NULL;
414 }
415
416 memset(err, 0, ch * (image->width + 2));
417 memset(nerr, 0, ch * (image->width + 2));
418
419 convertTrueColor_generic(ximg, image, err, nerr,
420 rtable, gtable, btable, dr, dg, db, roffs, goffs, boffs);
421 free(err);
422 free(nerr);
423 }
424
425 }
a30475fc kojima2000-01-14 16:39:15 +0000426
427#ifdef BENCH
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200428 cycle_bench(0);
a30475fc kojima2000-01-14 16:39:15 +0000429#endif
430
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200431 return ximg;
9d2e6ef9 scottc1998-09-29 22:36:29 +0000432}
433
a30475fc kojima2000-01-14 16:39:15 +0000434/***************************************************************************/
8f68cfd8 kojima1999-04-29 23:05:16 +0000435
0780ab82 kojima2000-01-19 17:47:35 +0000436static void
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200437convertPseudoColor_to_8(RXImage * ximg, RImage * image,
438 signed char *err, signed char *nerr,
439 const unsigned short *rtable,
440 const unsigned short *gtable,
441 const unsigned short *btable,
442 const int dr, const int dg, const int db, unsigned long *pixels, int cpc)
0780ab82 kojima2000-01-19 17:47:35 +0000443{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200444 signed char *terr;
445 int x, y, r, g, b;
446 int pixel;
447 int rer, ger, ber;
448 unsigned char *ptr = image->data;
449 unsigned char *optr = (unsigned char *)ximg->image->data;
450 int channels = (HAS_ALPHA(image) ? 4 : 3);
451 int cpcpc = cpc * cpc;
452
453 /* convert and dither the image to XImage */
454 for (y = 0; y < image->height; y++) {
455 nerr[0] = 0;
456 nerr[1] = 0;
457 nerr[2] = 0;
458 for (x = 0; x < image->width * 3; x += 3, ptr += channels) {
459
460 /* reduce pixel */
461 pixel = *ptr + err[x];
462 if (pixel < 0)
463 pixel = 0;
464 else if (pixel > 0xff)
465 pixel = 0xff;
466 r = rtable[pixel];
467 /* calc error */
468 rer = pixel - r * dr;
469
470 /* reduce pixel */
471 pixel = *(ptr + 1) + err[x + 1];
472 if (pixel < 0)
473 pixel = 0;
474 else if (pixel > 0xff)
475 pixel = 0xff;
476 g = gtable[pixel];
477 /* calc error */
478 ger = pixel - g * dg;
479
480 /* reduce pixel */
481 pixel = *(ptr + 2) + err[x + 2];
482 if (pixel < 0)
483 pixel = 0;
484 else if (pixel > 0xff)
485 pixel = 0xff;
486 b = btable[pixel];
487 /* calc error */
488 ber = pixel - b * db;
489
490 *optr++ = pixels[r * cpcpc + g * cpc + b];
491
492 /* distribute error */
493 r = (rer * 3) / 8;
494 g = (ger * 3) / 8;
495 b = (ber * 3) / 8;
496
497 /* x+1, y */
498 err[x + 3 * 1] += r;
499 err[x + 1 + 3 * 1] += g;
500 err[x + 2 + 3 * 1] += b;
501 /* x, y+1 */
502 nerr[x] += r;
503 nerr[x + 1] += g;
504 nerr[x + 2] += b;
505 /* x+1, y+1 */
506 nerr[x + 3 * 1] = rer - 2 * r;
507 nerr[x + 1 + 3 * 1] = ger - 2 * g;
508 nerr[x + 2 + 3 * 1] = ber - 2 * b;
509 }
510 /* skip to next line */
511 terr = err;
512 err = nerr;
513 nerr = terr;
514
515 optr += ximg->image->bytes_per_line - image->width;
516 }
0780ab82 kojima2000-01-19 17:47:35 +0000517}
518
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200519static RXImage *image2PseudoColor(RContext * ctx, RImage * image)
9d2e6ef9 scottc1998-09-29 22:36:29 +0000520{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200521 RXImage *ximg;
522 register int x, y, r, g, b;
523 unsigned char *ptr;
524 unsigned long pixel;
525 const int cpc = ctx->attribs->colors_per_channel;
526 const unsigned short rmask = cpc - 1; /* different sizes could be used */
527 const unsigned short gmask = rmask; /* for r,g,b */
528 const unsigned short bmask = rmask;
529 unsigned short *rtable, *gtable, *btable;
530 const int cpccpc = cpc * cpc;
531 int channels = (HAS_ALPHA(image) ? 4 : 3);
532
533 ximg = RCreateXImage(ctx, ctx->depth, image->width, image->height);
534 if (!ximg) {
535 return NULL;
536 }
537
538 ptr = image->data;
539
540 /* Tables are same at the moment because rmask==gmask==bmask. */
541 rtable = computeTable(rmask);
542 gtable = computeTable(gmask);
543 btable = computeTable(bmask);
544
545 if (rtable == NULL || gtable == NULL || btable == NULL) {
546 RErrorCode = RERR_NOMEMORY;
547 RDestroyXImage(ctx, ximg);
548 return NULL;
549 }
550
551 if (ctx->attribs->render_mode == RBestMatchRendering) {
552 /* fake match */
9d2e6ef9 scottc1998-09-29 22:36:29 +0000553#ifdef DEBUG
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200554 printf("pseudo color match with %d colors per channel\n", cpc);
9d2e6ef9 scottc1998-09-29 22:36:29 +0000555#endif
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200556 for (y = 0; y < image->height; y++) {
557 for (x = 0; x < image->width; x++, ptr += channels - 3) {
558 /* reduce pixel */
559 r = rtable[*ptr++];
560 g = gtable[*ptr++];
561 b = btable[*ptr++];
562 pixel = r * cpccpc + g * cpc + b;
563 /*data[ofs] = ctx->colors[pixel].pixel; */
564 XPutPixel(ximg->image, x, y, ctx->colors[pixel].pixel);
565 }
566 }
567 } else {
568 /* dither */
569 signed char *err;
570 signed char *nerr;
571 const int dr = 0xff / rmask;
572 const int dg = 0xff / gmask;
573 const int db = 0xff / bmask;
9d2e6ef9 scottc1998-09-29 22:36:29 +0000574
575#ifdef DEBUG
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200576 printf("pseudo color dithering with %d colors per channel\n", cpc);
9d2e6ef9 scottc1998-09-29 22:36:29 +0000577#endif
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200578 err = malloc(4 * (image->width + 3));
579 nerr = malloc(4 * (image->width + 3));
580 if (!err || !nerr) {
581 NFREE(err);
582 NFREE(nerr);
583 RErrorCode = RERR_NOMEMORY;
584 RDestroyXImage(ctx, ximg);
585 return NULL;
586 }
587 memset(err, 0, 4 * (image->width + 3));
588 memset(nerr, 0, 4 * (image->width + 3));
589
590 /*#ifdef ASM_X86 */
1941aaf3 dan2002-09-30 12:39:22 +0000591#if 0
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200592 x86_PseudoColor_32_to_8(image->data, ximg->image->data,
593 err + 4, nerr + 4,
594 rtable,
595 dr, dg, db, ctx->pixels, cpc,
596 image->width, image->height,
597 channels, ximg->image->bytes_per_line - image->width);
1941aaf3 dan2002-09-30 12:39:22 +0000598#else
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200599 convertPseudoColor_to_8(ximg, image, err + 4, nerr + 4,
600 rtable, gtable, btable, dr, dg, db, ctx->pixels, cpc);
1941aaf3 dan2002-09-30 12:39:22 +0000601#endif
9af1c6c4 dan1998-10-21 14:43:47 +0000602
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200603 free(err);
604 free(nerr);
605 }
6830b057 dan2004-10-12 21:28:27 +0000606
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200607 return ximg;
9d2e6ef9 scottc1998-09-29 22:36:29 +0000608}
609
33b8c225 kojima1999-11-16 00:13:21 +0000610/*
611 * For standard colormap
612 */
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200613static RXImage *image2StandardPseudoColor(RContext * ctx, RImage * image)
33b8c225 kojima1999-11-16 00:13:21 +0000614{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200615 RXImage *ximg;
616 register int x, y, r, g, b;
617 unsigned char *ptr;
618 unsigned long pixel;
619 unsigned char *data;
620 unsigned int *rtable, *gtable, *btable;
621 unsigned int base_pixel = ctx->std_rgb_map->base_pixel;
622 int channels = (HAS_ALPHA(image) ? 4 : 3);
623
624 ximg = RCreateXImage(ctx, ctx->depth, image->width, image->height);
625 if (!ximg) {
626 return NULL;
627 }
628
629 ptr = image->data;
630
631 data = (unsigned char *)ximg->image->data;
632
633 rtable = computeStdTable(ctx->std_rgb_map->red_mult, ctx->std_rgb_map->red_max);
634
635 gtable = computeStdTable(ctx->std_rgb_map->green_mult, ctx->std_rgb_map->green_max);
636
637 btable = computeStdTable(ctx->std_rgb_map->blue_mult, ctx->std_rgb_map->blue_max);
638
639 if (rtable == NULL || gtable == NULL || btable == NULL) {
640 RErrorCode = RERR_NOMEMORY;
641 RDestroyXImage(ctx, ximg);
642 return NULL;
643 }
644
645 if (ctx->attribs->render_mode == RBestMatchRendering) {
646 for (y = 0; y < image->height; y++) {
647 for (x = 0; x < image->width; x++, ptr += channels) {
648 /* reduce pixel */
649 pixel = (rtable[*ptr] + gtable[*(ptr + 1)]
650 + btable[*(ptr + 2)] + base_pixel) & 0xffffffff;
651
652 XPutPixel(ximg->image, x, y, pixel);
653 }
654 }
655 } else {
656 /* dither */
657 signed short *err, *nerr;
658 signed short *terr;
659 int rer, ger, ber;
660 int x1, ofs;
33b8c225 kojima1999-11-16 00:13:21 +0000661
662#ifdef DEBUG
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200663 printf("pseudo color dithering with %d colors per channel\n", ctx->attribs->colors_per_channel);
33b8c225 kojima1999-11-16 00:13:21 +0000664#endif
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200665 err = (short *)malloc(3 * (image->width + 2) * sizeof(short));
666 nerr = (short *)malloc(3 * (image->width + 2) * sizeof(short));
667 if (!err || !nerr) {
668 NFREE(err);
669 NFREE(nerr);
670 RErrorCode = RERR_NOMEMORY;
671 RDestroyXImage(ctx, ximg);
672 return NULL;
673 }
674 for (x = 0, x1 = 0; x < image->width * 3; x1 += channels - 3) {
675 err[x++] = ptr[x1++];
676 err[x++] = ptr[x1++];
677 err[x++] = ptr[x1++];
678 }
679 err[x] = err[x + 1] = err[x + 2] = 0;
680 /* convert and dither the image to XImage */
681 for (y = 0, ofs = 0; y < image->height; y++) {
682 if (y < image->height - 1) {
683 int x1;
684 for (x = 0, x1 = (y + 1) * image->width * channels;
685 x < image->width * 3; x1 += channels - 3) {
686 nerr[x++] = ptr[x1++];
687 nerr[x++] = ptr[x1++];
688 nerr[x++] = ptr[x1++];
689 }
690 /* last column */
691 x1 -= channels;
692 nerr[x++] = ptr[x1++];
693 nerr[x++] = ptr[x1++];
694 nerr[x++] = ptr[x1++];
695 }
696 for (x = 0; x < image->width * 3; x += 3, ofs++) {
697 /* reduce pixel */
698 if (err[x] > 0xff)
699 err[x] = 0xff;
700 else if (err[x] < 0)
701 err[x] = 0;
702 if (err[x + 1] > 0xff)
703 err[x + 1] = 0xff;
704 else if (err[x + 1] < 0)
705 err[x + 1] = 0;
706 if (err[x + 2] > 0xff)
707 err[x + 2] = 0xff;
708 else if (err[x + 2] < 0)
709 err[x + 2] = 0;
710
711 r = rtable[err[x]];
712 g = gtable[err[x + 1]];
713 b = btable[err[x + 2]];
714
715 pixel = r + g + b;
716
717 data[ofs] = base_pixel + pixel;
718
719 /* calc error */
720 rer = err[x] - (ctx->colors[pixel].red >> 8);
721 ger = err[x + 1] - (ctx->colors[pixel].green >> 8);
722 ber = err[x + 2] - (ctx->colors[pixel].blue >> 8);
723
724 /* distribute error */
725 err[x + 3 * 1] += (rer * 7) / 16;
726 err[x + 1 + 3 * 1] += (ger * 7) / 16;
727 err[x + 2 + 3 * 1] += (ber * 7) / 16;
728
729 nerr[x] += (rer * 5) / 16;
730 nerr[x + 1] += (ger * 5) / 16;
731 nerr[x + 2] += (ber * 5) / 16;
732
733 if (x > 0) {
734 nerr[x - 3 * 1] += (rer * 3) / 16;
735 nerr[x - 3 * 1 + 1] += (ger * 3) / 16;
736 nerr[x - 3 * 1 + 2] += (ber * 3) / 16;
737 }
738
739 nerr[x + 3 * 1] += rer / 16;
740 nerr[x + 1 + 3 * 1] += ger / 16;
741 nerr[x + 2 + 3 * 1] += ber / 16;
742 }
743 /* skip to next line */
744 terr = err;
745 err = nerr;
746 nerr = terr;
747
748 ofs += ximg->image->bytes_per_line - image->width;
749 }
750 free(err);
751 free(nerr);
752 }
753 ximg->image->data = (char *)data;
754
755 return ximg;
33b8c225 kojima1999-11-16 00:13:21 +0000756}
757
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200758static RXImage *image2GrayScale(RContext * ctx, RImage * image)
9d2e6ef9 scottc1998-09-29 22:36:29 +0000759{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200760 RXImage *ximg;
761 register int x, y, g;
762 unsigned char *ptr;
763 const int cpc = ctx->attribs->colors_per_channel;
764 unsigned short gmask;
765 unsigned short *table;
766 unsigned char *data;
767 int channels = (HAS_ALPHA(image) ? 4 : 3);
768
769 ximg = RCreateXImage(ctx, ctx->depth, image->width, image->height);
770 if (!ximg) {
771 return NULL;
772 }
773
774 ptr = image->data;
775
776 data = (unsigned char *)ximg->image->data;
777
778 if (ctx->vclass == StaticGray)
779 gmask = (1 << ctx->depth) - 1; /* use all grays */
780 else
781 gmask = cpc * cpc * cpc - 1;
782
783 table = computeTable(gmask);
784
785 if (table == NULL) {
786 RErrorCode = RERR_NOMEMORY;
787 RDestroyXImage(ctx, ximg);
788 return NULL;
789 }
790
791 if (ctx->attribs->render_mode == RBestMatchRendering) {
792 /* fake match */
9d2e6ef9 scottc1998-09-29 22:36:29 +0000793#ifdef DEBUG
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200794 printf("grayscale match with %d colors per channel\n", cpc);
9d2e6ef9 scottc1998-09-29 22:36:29 +0000795#endif
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200796 for (y = 0; y < image->height; y++) {
797 for (x = 0; x < image->width; x++) {
798 /* reduce pixel */
799 g = table[(*ptr * 30 + *(ptr + 1) * 59 + *(ptr + 2) * 11) / 100];
800 ptr += channels;
801 /*data[ofs] = ctx->colors[g].pixel; */
802 XPutPixel(ximg->image, x, y, ctx->colors[g].pixel);
803 }
804 }
805 } else {
806 /* dither */
807 short *gerr;
808 short *ngerr;
809 short *terr;
810 int ger;
811 const int dg = 0xff / gmask;
9d2e6ef9 scottc1998-09-29 22:36:29 +0000812
813#ifdef DEBUG
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200814 printf("grayscale dither with %d colors per channel\n", cpc);
9d2e6ef9 scottc1998-09-29 22:36:29 +0000815#endif
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200816 gerr = (short *)malloc((image->width + 2) * sizeof(short));
817 ngerr = (short *)malloc((image->width + 2) * sizeof(short));
818 if (!gerr || !ngerr) {
819 NFREE(gerr);
820 NFREE(ngerr);
821 RErrorCode = RERR_NOMEMORY;
822 RDestroyXImage(ctx, ximg);
823 return NULL;
824 }
825 for (x = 0, y = 0; x < image->width; x++, y += channels) {
826 gerr[x] = (ptr[y] * 30 + ptr[y + 1] * 59 + ptr[y + 2] * 11) / 100;
827 }
828 gerr[x] = 0;
829 /* convert and dither the image to XImage */
830 for (y = 0; y < image->height; y++) {
831 if (y < image->height - 1) {
832 int x1;
833 for (x = 0, x1 = (y + 1) * image->width * channels; x < image->width;
834 x++, x1 += channels) {
835 ngerr[x] = (ptr[x1] * 30 + ptr[x1 + 1] * 59 + ptr[x1 + 2] * 11) / 100;
836 }
837 /* last column */
838 x1 -= channels;
839 ngerr[x] = (ptr[x1] * 30 + ptr[x1 + 1] * 59 + ptr[x1 + 2] * 11) / 100;
840 }
841 for (x = 0; x < image->width; x++) {
842 /* reduce pixel */
843 if (gerr[x] > 0xff)
844 gerr[x] = 0xff;
845 else if (gerr[x] < 0)
846 gerr[x] = 0;
847
848 g = table[gerr[x]];
849
850 /*data[ofs] = ctx->colors[g].pixel; */
851 XPutPixel(ximg->image, x, y, ctx->colors[g].pixel);
852 /* calc error */
853 ger = gerr[x] - g * dg;
854
855 /* distribute error */
856 g = (ger * 3) / 8;
857 /* x+1, y */
858 gerr[x + 1] += g;
859 /* x, y+1 */
860 ngerr[x] += g;
861 /* x+1, y+1 */
862 ngerr[x + 1] += ger - 2 * g;
863 }
864 /* skip to next line */
865 terr = gerr;
866 gerr = ngerr;
867 ngerr = terr;
868 }
869 free(gerr);
870 free(ngerr);
871 }
872 ximg->image->data = (char *)data;
873
874 return ximg;
9d2e6ef9 scottc1998-09-29 22:36:29 +0000875}
876
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200877static RXImage *image2Bitmap(RContext * ctx, RImage * image, int threshold)
9d2e6ef9 scottc1998-09-29 22:36:29 +0000878{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200879 RXImage *ximg;
880 unsigned char *alpha;
881 int x, y;
882
883 ximg = RCreateXImage(ctx, 1, image->width, image->height);
884 if (!ximg) {
885 return NULL;
886 }
887 alpha = image->data + 3;
888
889 for (y = 0; y < image->height; y++) {
890 for (x = 0; x < image->width; x++) {
891 XPutPixel(ximg->image, x, y, (*alpha <= threshold ? 0 : 1));
892 alpha += 4;
893 }
894 }
895
896 return ximg;
9d2e6ef9 scottc1998-09-29 22:36:29 +0000897}
898
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200899int RConvertImage(RContext * context, RImage * image, Pixmap * pixmap)
9d2e6ef9 scottc1998-09-29 22:36:29 +0000900{
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200901 RXImage *ximg = NULL;
9af1c6c4 dan1998-10-21 14:43:47 +0000902#ifdef XSHM
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200903 Pixmap tmp;
9af1c6c4 dan1998-10-21 14:43:47 +0000904#endif
6830b057 dan2004-10-12 21:28:27 +0000905
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200906 assert(context != NULL);
907 assert(image != NULL);
908 assert(pixmap != NULL);
9d2e6ef9 scottc1998-09-29 22:36:29 +0000909
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200910 switch (context->vclass) {
911 case TrueColor:
1941aaf3 dan2002-09-30 12:39:22 +0000912#ifdef BENCH
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200913 cycle_bench(1);
1941aaf3 dan2002-09-30 12:39:22 +0000914#endif
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200915 ximg = image2TrueColor(context, image);
1941aaf3 dan2002-09-30 12:39:22 +0000916#ifdef BENCH
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200917 cycle_bench(0);
19b49b3f dan2001-05-10 21:31:13 +0000918#endif
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200919 break;
19b49b3f dan2001-05-10 21:31:13 +0000920
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200921 case PseudoColor:
922 case StaticColor:
0780ab82 kojima2000-01-19 17:47:35 +0000923#ifdef BENCH
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200924 cycle_bench(1);
0780ab82 kojima2000-01-19 17:47:35 +0000925#endif
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200926 if (context->attribs->standard_colormap_mode != RIgnoreStdColormap)
927 ximg = image2StandardPseudoColor(context, image);
928 else
929 ximg = image2PseudoColor(context, image);
0780ab82 kojima2000-01-19 17:47:35 +0000930#ifdef BENCH
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200931 cycle_bench(0);
0780ab82 kojima2000-01-19 17:47:35 +0000932#endif
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200933 break;
33b8c225 kojima1999-11-16 00:13:21 +0000934
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200935 case GrayScale:
936 case StaticGray:
937 ximg = image2GrayScale(context, image);
938 break;
939 }
19b49b3f dan2001-05-10 21:31:13 +0000940
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200941 if (!ximg) {
942 return False;
943 }
19b49b3f dan2001-05-10 21:31:13 +0000944
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200945 *pixmap = XCreatePixmap(context->dpy, context->drawable, image->width, image->height, context->depth);
1941aaf3 dan2002-09-30 12:39:22 +0000946
9af1c6c4 dan1998-10-21 14:43:47 +0000947#ifdef XSHM
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200948 if (context->flags.use_shared_pixmap && ximg->is_shared)
949 tmp = R_CreateXImageMappedPixmap(context, ximg);
950 else
951 tmp = None;
952 if (tmp) {
953 /*
954 * We have to copy the shm Pixmap into a normal Pixmap because
955 * otherwise, we would have to control when Pixmaps are freed so
956 * that we can detach their shm segments. This is a problem if the
957 * program crash, leaving stale shared memory segments in the
958 * system (lots of them). But with some work, we can optimize
959 * things and remove this XCopyArea. This will require
960 * explicitly freeing all pixmaps when exiting or restarting
961 * wmaker.
962 */
963 XCopyArea(context->dpy, tmp, *pixmap, context->copy_gc, 0, 0, image->width, image->height, 0, 0);
964 XFreePixmap(context->dpy, tmp);
965 } else {
966 RPutXImage(context, *pixmap, context->copy_gc, ximg, 0, 0, 0, 0, image->width, image->height);
967 }
968#else /* !XSHM */
969 RPutXImage(context, *pixmap, context->copy_gc, ximg, 0, 0, 0, 0, image->width, image->height);
970#endif /* !XSHM */
971
972 RDestroyXImage(context, ximg);
973
974 return True;
9d2e6ef9 scottc1998-09-29 22:36:29 +0000975}
976
a2b404b5 dan2002-10-08 08:26:06 +0000977/* make the gc permanent (create with context creation).
978 * GC creation is very expensive. altering its properties is not. -Dan
979 */
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200980int RConvertImageMask(RContext * context, RImage * image, Pixmap * pixmap, Pixmap * mask, int threshold)
9d2e6ef9 scottc1998-09-29 22:36:29 +0000981{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200982 GC gc;
983 XGCValues gcv;
984 RXImage *ximg = NULL;
985
986 assert(context != NULL);
987 assert(image != NULL);
988 assert(pixmap != NULL);
989 assert(mask != NULL);
990
991 if (!RConvertImage(context, image, pixmap))
992 return False;
993
994 if (image->format == RRGBFormat) {
995 *mask = None;
996 return True;
997 }
998
999 ximg = image2Bitmap(context, image, threshold);
1000
1001 if (!ximg) {
1002 return False;
1003 }
1004 *mask = XCreatePixmap(context->dpy, context->drawable, image->width, image->height, 1);
1005 gcv.foreground = context->black;
1006 gcv.background = context->white;
1007 gcv.graphics_exposures = False;
1008 gc = XCreateGC(context->dpy, *mask, GCForeground | GCBackground | GCGraphicsExposures, &gcv);
1009 RPutXImage(context, *mask, gc, ximg, 0, 0, 0, 0, image->width, image->height);
1010 RDestroyXImage(context, ximg);
1011 XFreeGC(context->dpy, gc);
1012
1013 return True;
9d2e6ef9 scottc1998-09-29 22:36:29 +00001014}
1015
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +02001016Bool RGetClosestXColor(RContext * context, RColor * color, XColor * retColor)
9d2e6ef9 scottc1998-09-29 22:36:29 +00001017{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +02001018 if (context->vclass == TrueColor) {
1019 unsigned short rmask, gmask, bmask;
1020 unsigned short roffs, goffs, boffs;
1021 unsigned short *rtable, *gtable, *btable;
1022
1023 roffs = context->red_offset;
1024 goffs = context->green_offset;
1025 boffs = context->blue_offset;
1026
1027 rmask = context->visual->red_mask >> roffs;
1028 gmask = context->visual->green_mask >> goffs;
1029 bmask = context->visual->blue_mask >> boffs;
1030
1031 rtable = computeTable(rmask);
1032 gtable = computeTable(gmask);
1033 btable = computeTable(bmask);
1034
1035 retColor->pixel = (rtable[color->red] << roffs) |
1036 (gtable[color->green] << goffs) | (btable[color->blue] << boffs);
1037
1038 retColor->red = color->red << 8;
1039 retColor->green = color->green << 8;
1040 retColor->blue = color->blue << 8;
1041 retColor->flags = DoRed | DoGreen | DoBlue;
1042
1043 } else if (context->vclass == PseudoColor || context->vclass == StaticColor) {
1044
1045 if (context->attribs->standard_colormap_mode != RIgnoreStdColormap) {
1046 unsigned int *rtable, *gtable, *btable;
1047
1048 rtable = computeStdTable(context->std_rgb_map->red_mult, context->std_rgb_map->red_max);
1049
1050 gtable = computeStdTable(context->std_rgb_map->green_mult,
1051 context->std_rgb_map->green_max);
1052
1053 btable = computeStdTable(context->std_rgb_map->blue_mult, context->std_rgb_map->blue_max);
1054
1055 if (rtable == NULL || gtable == NULL || btable == NULL) {
1056 RErrorCode = RERR_NOMEMORY;
1057 return False;
1058 }
1059
1060 retColor->pixel = (rtable[color->red]
1061 + gtable[color->green]
1062 + btable[color->blue]
1063 + context->std_rgb_map->base_pixel) & 0xffffffff;
1064 retColor->red = color->red << 8;
1065 retColor->green = color->green << 8;
1066 retColor->blue = color->blue << 8;
1067 retColor->flags = DoRed | DoGreen | DoBlue;
1068
1069 } else {
1070 const int cpc = context->attribs->colors_per_channel;
1071 const unsigned short rmask = cpc - 1; /* different sizes could be used */
1072 const unsigned short gmask = rmask; /* for r,g,b */
1073 const unsigned short bmask = rmask;
1074 unsigned short *rtable, *gtable, *btable;
1075 const int cpccpc = cpc * cpc;
1076 int index;
1077
1078 rtable = computeTable(rmask);
1079 gtable = computeTable(gmask);
1080 btable = computeTable(bmask);
1081
1082 if (rtable == NULL || gtable == NULL || btable == NULL) {
1083 RErrorCode = RERR_NOMEMORY;
1084 return False;
1085 }
1086 index = rtable[color->red] * cpccpc + gtable[color->green] * cpc + btable[color->blue];
1087 *retColor = context->colors[index];
1088 }
1089
1090 } else if (context->vclass == GrayScale || context->vclass == StaticGray) {
1091
1092 const int cpc = context->attribs->colors_per_channel;
1093 unsigned short gmask;
1094 unsigned short *table;
1095 int index;
1096
1097 if (context->vclass == StaticGray)
1098 gmask = (1 << context->depth) - 1; /* use all grays */
1099 else
1100 gmask = cpc * cpc * cpc - 1;
1101
1102 table = computeTable(gmask);
1103 if (!table)
1104 return False;
1105
1106 index = table[(color->red * 30 + color->green * 59 + color->blue * 11) / 100];
1107
1108 *retColor = context->colors[index];
1109 } else {
1110 RErrorCode = RERR_INTERNAL;
1111 return False;
1112 }
1113
1114 return True;
9d2e6ef9 scottc1998-09-29 22:36:29 +00001115}