1 #include <cstdlib>
2 #include <cstring>
3 #include <cmath>
4 #include <cassert>
5 #include <cstdio>
6 #include <climits>
7 #include "config.h"
8 #include "filter.h"
9 #include "misc-f.h"
10 #include "xerror.h"
11
12 #define nprecells \
13 (context->type & \
14 (LARGEITER | SMALLITER | TRUECOLOR | TRUECOLOR16 | TRUECOLOR24) \
15 ? 0 \
16 : (context)->ncells)
17 #define PREALLOCATED(palette) \
18 ((palette)->type & \
19 (LARGEITER | SMALLITER | TRUECOLOR | TRUECOLOR16 | TRUECOLOR24) \
20 ? 0 \
21 : (palette)->npreallocated)
22 /*emulate allocation routines using setpalette */
23 unsigned col_diff[3][512];
24 static struct palette *context;
25 static int maxentries;
26 static int needupdate;
genertruecolorinfo(struct truec * t,unsigned int r,unsigned int g,unsigned int b)27 static void genertruecolorinfo(struct truec *t, unsigned int r, unsigned int g,
28 unsigned int b)
29 {
30 int n;
31
32 for (n = 0; !((r >> n) & 1); n++)
33 ;
34 t->rshift = n;
35 for (; ((r >> n) & 1); n++)
36 ;
37 t->rprec = 8 - (n - t->rshift);
38 t->rmask = r;
39
40 for (n = 0; !((g >> n) & 1); n++)
41 ;
42 t->gshift = n;
43 for (; ((g >> n) & 1); n++)
44 ;
45 t->gprec = 8 - (n - t->gshift);
46 t->gmask = g;
47
48 for (n = 0; !((b >> n) & 1); n++)
49 ;
50 t->bshift = n;
51 for (; ((b >> n) & 1); n++)
52 ;
53 t->bprec = 8 - (n - t->bshift);
54 t->bmask = b;
55
56 t->allmask = r | g | b;
57 if ((r & b) || (r & g) || (b & g)) {
58 x_fatalerror("Internal error:Invalid color masks 1 %x %x %x!\n", r, g,
59 b);
60 }
61 if ((r < g && g < b) || (b < g && g < r)) {
62 t->mask1 = r | b;
63 t->mask2 = g;
64 } else if ((g < r && r < b) || (b < r && r < g)) {
65 t->mask1 = g | b;
66 t->mask2 = r;
67 } else if ((g < b && b < r) || (r < b && b < g)) {
68 t->mask1 = g | r;
69 t->mask2 = b;
70 }
71 t->byteexact = 0;
72 t->missingbyte = -1;
73 if (!(t->rshift % 8) && !(t->gshift % 8) && !(t->bshift % 8) && !t->rprec &&
74 !t->gprec && !t->bprec) {
75 t->byteexact = 1;
76 {
77 unsigned char ch[4];
78 *(unsigned int *)ch = t->allmask;
79 if (!ch[0])
80 t->missingbyte = 0;
81 if (!ch[1])
82 t->missingbyte = 1;
83 if (!ch[2])
84 t->missingbyte = 2;
85 if (!ch[3])
86 t->missingbyte = 3;
87 }
88 }
89 #ifdef DEBUG
90 printf("Image:\n");
91 printf("rshift:%i gshift:%i bshift:%i\n", t->rshift, t->gshift, t->bshift);
92 printf("rprec:%i gprec:%i bprec:%i\n", t->rprec, t->gprec, t->bprec);
93 printf("rmask:%x gmask:%x bmask:%x\n", t->rmask, t->gmask, t->bmask);
94 printf("mask1:%x mask2:%x allmask:%x\n", t->mask1, t->mask2, t->allmask);
95 printf("byteexact:%x missingbyte:%i\n", t->byteexact, t->missingbyte);
96 #endif
97 }
98
bestfit_init(void)99 void bestfit_init(void)
100 {
101 int i;
102
103 for (i = 1; i < 256; i++) {
104 int k = i * i;
105 col_diff[0][i] = col_diff[0][512 - i] = k * (59 * 59) / 256;
106 col_diff[1][i] = col_diff[1][512 - i] = k * (30 * 30) / 256;
107 col_diff[2][i] = col_diff[2][512 - i] = k * (11 * 11) / 256;
108 }
109 }
110
allocgenerictruecolor(struct palette * palette,int init,int r,int g,int b)111 static int allocgenerictruecolor(struct palette *palette, int init, int r,
112 int g, int b)
113 {
114 unsigned int n;
115 switch (palette->type) {
116 case LARGEITER:
117 case SMALLITER:
118 return 1;
119 case TRUECOLOR:
120 case TRUECOLOR16:
121 case TRUECOLOR24:
122 default:
123 n = ((r >> palette->info.truec.rprec)
124 << palette->info.truec.rshift) |
125 ((g >> palette->info.truec.gprec)
126 << palette->info.truec.gshift) |
127 ((b >> palette->info.truec.bprec)
128 << palette->info.truec.bshift) |
129 palette->info.truec.alpha;
130 break;
131 }
132 if (init)
133 palette->size = 0;
134 else if (palette->size >= palette->maxentries)
135 return -1;
136 palette->pixels[palette->size] = n;
137 palette->size++;
138 return palette->size;
139 }
140
allocgeneric(struct palette * palette,int init,int r,int g,int b)141 static int allocgeneric(struct palette *palette, int init, int r, int g, int b)
142 {
143 int start = palette->npreallocated + palette->start;
144 if (init)
145 palette->size = 0;
146 else if (palette->size >= palette->end - start)
147 return -1;
148 palette->pixels[palette->size] = palette->size + start;
149 palette->rgb[palette->size + start][0] = r;
150 palette->rgb[palette->size + start][1] = g;
151 palette->rgb[palette->size + start][2] = b;
152 palette->size++;
153 return (palette->size - 1);
154 }
155
fixedalloccolor(struct palette * palette,int init,int r,int g,int b)156 int fixedalloccolor(struct palette *palette, int init, int r, int g, int b)
157 {
158 int i, coldif, lowest, bestfit;
159 if (init)
160 palette->size = 0;
161 else if (palette->size >= palette->maxentries)
162 return -1;
163 lowest = INT_MAX;
164 bestfit = 1;
165 if (palette->type == FIXEDCOLOR || (palette->type & BITMAPS)) {
166 for (i = palette->start; i < palette->end; i++) {
167 coldif = col_diff[0][(g - palette->rgb[i][1]) & 0x1ff];
168 if (coldif < lowest) {
169 coldif += col_diff[1][(r - palette->rgb[i][0]) & 0x1ff];
170 if (coldif < lowest) {
171 coldif += col_diff[2][(b - palette->rgb[i][2]) & 0x1ff];
172 if (coldif < lowest) {
173 bestfit = i;
174 if (!coldif)
175 break;
176 lowest = coldif;
177 }
178 }
179 }
180 }
181 } else {
182 bestfit = (r * 30 + g * 59 + b * 11) * (palette->end - palette->start) /
183 256 / 100 +
184 palette->start;
185 }
186 palette->pixels[palette->size] = bestfit;
187 palette->size++;
188 return (palette->size - 1);
189 }
190
setcolorgeneric(struct palette *,int,int,rgb_t *)191 static void setcolorgeneric(struct palette * /*palette*/, int /*start*/,
192 int /*end*/, rgb_t * /*rgb*/)
193 {
194 }
195
allocfinishedgeneric(struct palette * palette)196 static void allocfinishedgeneric(struct palette *palette)
197 {
198 palette->setpalette(palette, palette->start,
199 palette->size + palette->start + palette->npreallocated,
200 palette->rgb + palette->start);
201 }
202
cycle_entries(struct palette * c,int direction)203 static void cycle_entries(struct palette *c, int direction)
204 {
205 int i;
206 int i1, i2, i3;
207 rgb_t *co;
208 if (direction > 0)
209 direction %= c->size - 1;
210 else
211 direction = -((-direction) % (c->size - 1));
212 if (!direction)
213 return;
214 co = (rgb_t *)malloc(c->end * sizeof(rgb_t));
215 memcpy(co, c->rgb, sizeof(*co) * c->end);
216 i3 = (c->size - 1 + direction) % (c->size - 1) + 1;
217 for (i = 1; i < c->size; i++) {
218 i1 = c->pixels[i];
219 i2 = c->pixels[i3];
220 c->rgb[i1][0] = co[i2][0];
221 c->rgb[i1][1] = co[i2][1];
222 c->rgb[i1][2] = co[i2][2];
223 i3++;
224 if (i3 >= c->size)
225 i3 = 1;
226 }
227 free(co);
228 }
229
cyclecolorsgeneric(struct palette * pal,int direction)230 static void cyclecolorsgeneric(struct palette *pal, int direction)
231 {
232 cycle_entries(pal, direction);
233 pal->setpalette(pal, pal->pixels[0], pal->size + pal->pixels[0],
234 pal->rgb + pal->pixels[0]);
235 }
236
237 #define TRUECOLORPALETTE 65536
createpalette(int start,int end,int type,int flags,int maxentries,int (* alloccolor)(struct palette * pal,int init,int r,int g,int b),void (* setcolor)(struct palette * pal,int start,int end,rgb_t * rgb),void (* allocfinished)(struct palette * pal),void (* cyclecolors)(struct palette * pal,int direction),union paletteinfo * info)238 struct palette *createpalette(
239 int start, int end, int type, int flags, int maxentries,
240 int (*alloccolor)(struct palette *pal, int init, int r, int g, int b),
241 void (*setcolor)(struct palette *pal, int start, int end, rgb_t *rgb),
242 void (*allocfinished)(struct palette *pal),
243 void (*cyclecolors)(struct palette *pal, int direction),
244 union paletteinfo *info)
245 {
246 static int versioncount;
247 struct palette *palette =
248 (struct palette *)calloc(1, sizeof(struct palette));
249
250 if (col_diff[0][1] == 0)
251 bestfit_init();
252 palette->ncells = 0;
253 palette->index = NULL;
254 palette->size = 0;
255 palette->rgb = NULL;
256 if (palette == NULL)
257 return NULL;
258
259 switch (type) {
260 case LBITMAP:
261 case MBITMAP:
262 case LIBITMAP:
263 case MIBITMAP:
264 end = 2;
265 start = 0;
266 maxentries = 256;
267 palette->rgb = (rgb_t *)calloc(end, sizeof(*palette->rgb));
268 if (palette->rgb == NULL) {
269 free(palette);
270 return NULL;
271 }
272 if (type & (LIBITMAP | MIBITMAP)) {
273 palette->rgb[0][0] = 255;
274 palette->rgb[0][1] = 255;
275 palette->rgb[0][2] = 255;
276 palette->rgb[1][0] = 0;
277 palette->rgb[1][1] = 0;
278 palette->rgb[1][2] = 0;
279 } else {
280 palette->rgb[0][0] = 0;
281 palette->rgb[0][1] = 0;
282 palette->rgb[0][2] = 0;
283 palette->rgb[1][0] = 255;
284 palette->rgb[1][1] = 255;
285 palette->rgb[1][2] = 255;
286 }
287 palette->maxentries = maxentries;
288 palette->alloccolor = fixedalloccolor;
289 palette->setpalette = NULL;
290 palette->allocfinished = NULL;
291 palette->cyclecolors = NULL;
292 break;
293 case FIXEDCOLOR:
294 if (!end)
295 end = 256;
296 if (!maxentries)
297 maxentries = 256;
298 palette->rgb = (rgb_t *)calloc(end, sizeof(*palette->rgb));
299 if (palette->rgb == NULL) {
300 free(palette);
301 return NULL;
302 }
303 palette->maxentries = maxentries;
304 palette->alloccolor = fixedalloccolor;
305 palette->setpalette = NULL;
306 palette->allocfinished = NULL;
307 palette->cyclecolors = NULL;
308 break;
309 case GRAYSCALE:
310 if (!end)
311 end = 256;
312 if (!maxentries)
313 maxentries = end - start;
314 palette->maxentries = 65536;
315 palette->alloccolor = fixedalloccolor;
316 palette->setpalette = NULL;
317 palette->allocfinished = NULL;
318 palette->cyclecolors = NULL;
319 palette->size = end - start;
320 break;
321 case C256:
322
323 if (!end)
324 end = 256;
325 if (!maxentries)
326 maxentries = end - start;
327 if (cyclecolors == NULL && setcolor != NULL)
328 cyclecolors = cyclecolorsgeneric;
329
330 if (alloccolor == NULL) {
331 alloccolor = allocgeneric, allocfinished = allocfinishedgeneric;
332 if (setcolor == NULL && type == C256) /*non hardware palette */
333 setcolor = setcolorgeneric,
334 cyclecolors = cyclecolorsgeneric;
335 }
336 palette->rgb = (rgb_t *)calloc(end, sizeof(*palette->rgb));
337
338 if (palette->rgb == NULL) {
339 free(palette);
340 return NULL;
341 }
342
343 palette->maxentries = maxentries;
344 palette->alloccolor = alloccolor;
345 palette->setpalette = setcolor;
346 palette->allocfinished = allocfinished;
347 palette->cyclecolors = cyclecolors;
348
349 break;
350 default:
351 end = TRUECOLORPALETTE;
352 start = 0;
353 if (type == SMALLITER)
354 end = 256;
355 start = 0;
356 palette->maxentries = end;
357 palette->alloccolor = allocgenerictruecolor;
358 palette->cyclecolors = NULL;
359 palette->setpalette = NULL;
360 palette->allocfinished = NULL;
361 }
362 {
363 int ee = palette->maxentries;
364 /*if(end>palette->maxentries) ee=end; */
365 if (ee < 256)
366 palette->pixels =
367 (unsigned int *)calloc(256, sizeof(*palette->pixels));
368 else
369 palette->pixels =
370 (unsigned int *)calloc(ee, sizeof(*palette->pixels));
371 }
372 if (palette->pixels == NULL) {
373 free(palette);
374 return NULL;
375 }
376 if (type & (LARGEITER | SMALLITER)) {
377 int i;
378 palette->size = end;
379 palette->flags |= DONOTCHANGE;
380 for (i = 0; i < end; i++)
381 palette->pixels[i] = i;
382 }
383 palette->start = start;
384 palette->end = end;
385 palette->type = type;
386 palette->flags |= flags;
387 palette->version = (versioncount += 65536);
388 if (type == FIXEDCOLOR) {
389 int i;
390 if (setcolor != NULL)
391 setcolor(palette, start, end, palette->rgb);
392 for (i = 0; i < end - start; i++)
393 palette->pixels[i] = i + start;
394 }
395 if (type == GRAYSCALE) {
396 int i;
397 for (i = palette->start; i < end - start; i++)
398 palette->pixels[i] = i + start;
399 }
400 if (info != NULL &&
401 (type == TRUECOLOR || type == TRUECOLOR24 || type == TRUECOLOR16)) {
402 genertruecolorinfo(&palette->info.truec, info->truec.rmask,
403 info->truec.gmask, info->truec.bmask);
404 } else {
405 if (type == TRUECOLOR)
406 genertruecolorinfo(&palette->info.truec, 255 << 16, 255 << 8, 255);
407 if (type == TRUECOLOR24)
408 genertruecolorinfo(&palette->info.truec, 255 << 16, 255 << 8, 255);
409 if (type == TRUECOLOR16)
410 genertruecolorinfo(&palette->info.truec, (255 >> 3) << 11,
411 (255 >> 2) << 5, (255 >> 3));
412 }
413 if (type == TRUECOLOR)
414 palette->info.truec.alpha = ~palette->info.truec.allmask;
415 else
416 palette->info.truec.alpha = 0;
417
418 return (palette);
419 }
420
destroypalette(struct palette * palette)421 void destroypalette(struct palette *palette)
422 {
423 free(palette->pixels);
424 if (palette->rgb != NULL)
425 free(palette->rgb);
426 if (palette->index != NULL)
427 free(palette->index);
428 free(palette);
429 }
430
431 #define MYMIN(x, y) ((x) < (y) ? (x) : (y))
clonepalette(struct palette * palette)432 struct palette *clonepalette(struct palette *palette)
433 {
434 struct palette *pal =
435 createpalette(palette->start, palette->end, palette->type,
436 palette->flags, palette->maxentries,
437 /*palette->alloccolor, palette->setpalette,
438 palette->allocfinished, palette->cyclecolors */
439 NULL, NULL, NULL, NULL, &palette->info);
440 memcpy(pal->pixels, palette->pixels,
441 sizeof(*pal->pixels) * MYMIN(palette->end, pal->end));
442 if (pal->rgb != NULL) {
443 memcpy(pal->rgb, palette->rgb,
444 sizeof(*pal->rgb) * MYMIN(palette->end, pal->end));
445 }
446 pal->size = palette->size;
447 return (pal);
448 }
449
preallocpalette(struct palette * pal)450 void preallocpalette(struct palette *pal)
451 {
452 int i;
453 int p;
454 if (pal->index != NULL)
455 free(pal->index), pal->index = NULL;
456 pal->npreallocated = 0;
457 if (!pal->ncells)
458 return;
459 pal->index = (unsigned int *)malloc(sizeof(int) * (pal->ncells + 1));
460 for (i = 0; i < pal->ncells; i++) {
461 if (!i)
462 p = pal->pixels[0];
463 else
464 p = pal->pixels[pal->size];
465 pal->alloccolor(pal, i == 0, pal->prergb[i][0], pal->prergb[i][1],
466 pal->prergb[i][2]);
467 if (pal->size) {
468 pal->index[i] = pal->pixels[pal->size - 1];
469 pal->pixels[pal->size - 1] = p;
470 }
471 }
472 pal->npreallocated = pal->size;
473 pal->size = 0;
474 needupdate = 0;
475 }
476
restorepalette(struct palette * dest,struct palette * src)477 void restorepalette(struct palette *dest, struct palette *src)
478 {
479 int i;
480 preallocpalette(dest);
481 for (i = 0; i < src->size; i++) {
482 int r = 0, g = 0, b = 0;
483 switch (src->type) {
484 case SMALLITER:
485 r = g = b = i;
486 break;
487 case LARGEITER:
488 r = g = b = i / 256;
489 break;
490 case GRAYSCALE:
491 r = g = b = src->pixels[i];
492 break;
493 case C256:
494 case FIXEDCOLOR:
495 case MBITMAP:
496 case LBITMAP:
497 case MIBITMAP:
498 case LIBITMAP:
499 r = src->rgb[src->pixels[i]][0];
500 g = src->rgb[src->pixels[i]][1];
501 b = src->rgb[src->pixels[i]][2];
502 break;
503 case TRUECOLOR:
504 case TRUECOLOR16:
505 case TRUECOLOR24:
506 r = (((src->pixels[i] & src->info.truec.rmask) >>
507 src->info.truec.rshift))
508 << src->info.truec.rprec;
509 g = (((src->pixels[i] & src->info.truec.gmask) >>
510 src->info.truec.gshift))
511 << src->info.truec.gprec;
512 b = (((src->pixels[i] & src->info.truec.bmask) >>
513 src->info.truec.bshift))
514 << src->info.truec.bprec;
515 break;
516 }
517 if (dest->size >= dest->maxentries - PREALLOCATED(dest))
518 break;
519 if (dest->alloccolor(dest, (i + dest->npreallocated) == 0, r, g, b) ==
520 -1)
521 break;
522 }
523 if (!(dest->flags & FINISHLATER)) {
524 if (dest->allocfinished != NULL)
525 dest->allocfinished(dest);
526 } else
527 dest->flags |= UNFINISHED;
528 dest->version++;
529 }
530
531 /*Generation code for various palettes */
532
533 #define DEFNSEGMENTS (255 / 8)
534 #define MAXNSEGMENTS (4096)
535 #define NSEGMENTS ((255 / segmentsize))
536 static int segmentsize;
537
538 static unsigned char colors[MAXNSEGMENTS][3];
539 static const unsigned char colors1[DEFNSEGMENTS][3] = {
540 /*{8, 14, 32}, */
541 {0, 0, 0}, {120, 119, 238}, {24, 7, 25}, {197, 66, 28},
542 {29, 18, 11}, {135, 46, 71}, {24, 27, 13}, {241, 230, 128},
543 {17, 31, 24}, {240, 162, 139}, {11, 4, 30}, {106, 87, 189},
544 {29, 21, 14}, {12, 140, 118}, {10, 6, 29}, {50, 144, 77},
545 {22, 0, 24}, {148, 188, 243}, {4, 32, 7}, {231, 146, 14},
546 {10, 13, 20}, {184, 147, 68}, {13, 28, 3}, {169, 248, 152},
547 {4, 0, 34}, {62, 83, 48}, {7, 21, 22}, {152, 97, 184},
548 {8, 3, 12}, {247, 92, 235}, {31, 32, 16}};
549
allocate(int r,int g,int b,int init)550 static int allocate(int r, int g, int b, int init)
551 {
552 unsigned int n;
553 if (init)
554 preallocpalette(context);
555 n = context->pixels[(init ? 0 : context->size) /*+ context->start */];
556 if (!init && context->size == maxentries)
557 return 0;
558 if ((context->alloccolor(context, init && !context->npreallocated, (int)r,
559 (int)g, (int)b)) == -1) {
560 return 0;
561 }
562 if (context->pixels[context->size - 1 /*+ context->start */] != n) {
563 needupdate = 1;
564 }
565 return (1);
566 }
567
mksmooth(int nsegments,int setsegments)568 static int mksmooth(int nsegments, int setsegments)
569 {
570 int i, y;
571 float r, g, b, rs, gs, bs;
572 int segmentsize1 = segmentsize;
573
574 for (i = 0; i < setsegments; i++) {
575 if (i == setsegments - 1 && !(context->flags & UNKNOWNENTRIES)) {
576 segmentsize1 = maxentries - context->size - 2;
577 }
578 r = colors[i % nsegments][0];
579 g = colors[i % nsegments][1];
580 b = colors[i % nsegments][2];
581 rs = ((int)colors[(i + 1) % setsegments % nsegments][0] - r) /
582 (unsigned int)segmentsize1;
583 gs = ((int)colors[(i + 1) % setsegments % nsegments][1] - g) /
584 (unsigned int)segmentsize1;
585 bs = ((int)colors[(i + 1) % setsegments % nsegments][2] - b) /
586 (unsigned int)segmentsize1;
587 for (y = 0; y < segmentsize1; y++) {
588 if (!allocate((int)r, (int)g, (int)b, i == 0 && y == 0)) {
589 if (!i)
590 context->size = 2;
591 context->size = i * segmentsize;
592 return 0;
593 }
594 r += rs;
595 g += gs;
596 b += bs;
597 }
598 }
599 if (context->flags & UNKNOWNENTRIES)
600 context->size = i * segmentsize;
601 return 1;
602 }
603
hsv_to_rgb(int h,int s,int v,unsigned char * red,unsigned char * green,unsigned char * blue)604 static inline void hsv_to_rgb(int h, int s, int v, unsigned char *red,
605 unsigned char *green, unsigned char *blue)
606 {
607 int hue;
608 int f, p, q, t;
609 h += 256;
610 h %= 256;
611
612 if (s == 0) {
613 *red = v;
614 *green = v;
615 *blue = v;
616 } else {
617 h %= 256;
618 if (h < 0)
619 h += 256;
620 hue = h * 6;
621
622 f = hue & 255;
623 p = v * (256 - s) / 256;
624 q = v * (256 - (s * f) / 256) >> 8;
625 t = v * (256 * 256 - (s * (256 - f))) >> 16;
626
627 switch ((int)(hue / 256)) {
628 case 0:
629 *red = v;
630 *green = t;
631 *blue = p;
632 break;
633 case 1:
634 *red = q;
635 *green = v;
636 *blue = p;
637 break;
638 case 2:
639 *red = p;
640 *green = v;
641 *blue = t;
642 break;
643 case 3:
644 *red = p;
645 *green = q;
646 *blue = v;
647 break;
648 case 4:
649 *red = t;
650 *green = p;
651 *blue = v;
652 break;
653 case 5:
654 *red = v;
655 *green = p;
656 *blue = q;
657 break;
658 }
659 }
660 }
661
randomize_segments3(int,int nsegments)662 static void randomize_segments3(int /*whitemode*/, int nsegments)
663 {
664 int i = 0;
665 int h, s, v;
666
667 for (i = 0; i < nsegments; i++) {
668 if (!(i % 3)) {
669 if (i % 6)
670 colors[i][0] = 255, colors[i][1] = 255, colors[i][2] = 255;
671 else
672 colors[i][0] = 0, colors[i][1] = 0, colors[i][2] = 0;
673 } else {
674 s = (int)XaoS_random() % 256;
675 h = (int)XaoS_random() % (128 - 32);
676 v = (int)XaoS_random() % 128;
677 if (((i) % 6 > 3) ^ ((i) % 3 == 1))
678 /*if(((i)%3==1)) */
679 h += 42 + 16;
680 else
681 h += 42 + 128 + 16, v += 128 + 64;
682 hsv_to_rgb(h, s, v, colors[i], colors[i] + 1, colors[i] + 2);
683 }
684 }
685 colors[i - 1][0] = colors[0][0];
686 colors[i - 1][1] = colors[0][1];
687 colors[i - 1][2] = colors[0][2];
688 }
689
randomize_segments2(int whitemode,int nsegments)690 static void randomize_segments2(int whitemode, int nsegments)
691 {
692 int i = 0;
693
694 for (i = 0; i < nsegments; i++) {
695 if (i % 3 == 2)
696 colors[i][0] = whitemode * 255,
697 colors[i][1] = whitemode * 255,
698 colors[i][2] = whitemode * 255;
699 else if (i % 3 == 0)
700 colors[i][0] = (!whitemode) * 255,
701 colors[i][1] = (!whitemode) * 255,
702 colors[i][2] = (!whitemode) * 255;
703 else
704 colors[i][0] = (int)XaoS_random() % 256,
705 colors[i][1] = (int)XaoS_random() % 256,
706 colors[i][2] = (int)XaoS_random() % 256;
707 }
708 colors[i - 1][0] = colors[0][0];
709 colors[i - 1][1] = colors[0][1];
710 colors[i - 1][2] = colors[0][2];
711 }
712
randomize_segments(int whitemode,int nsegments)713 static void randomize_segments(int whitemode, int nsegments)
714 {
715 int i = 0;
716 if (whitemode) {
717 colors[0][0] = 255, colors[0][1] = 255, colors[0][2] = 255;
718 for (i = 0; i < nsegments; i += 2) {
719 if (i != 0) {
720 colors[i][0] = (int)XaoS_random() % 256,
721 colors[i][1] = (int)XaoS_random() % 256,
722 colors[i][2] = (int)XaoS_random() % 256;
723 }
724 if (i + 1 < nsegments)
725 colors[i + 1][0] = (int)XaoS_random() % 35,
726 colors[i + 1][1] = (int)XaoS_random() % 35,
727 colors[i + 1][2] = (int)XaoS_random() % 35;
728 }
729 } else {
730 for (i = 0; i < nsegments; i += 2) {
731 colors[i][0] = (int)XaoS_random() % 35,
732 colors[i][1] = (int)XaoS_random() % 35,
733 colors[i][2] = (int)XaoS_random() % 35;
734 if (i + 1 < nsegments)
735 colors[i + 1][0] = (int)XaoS_random() % 256,
736 colors[i + 1][1] = (int)XaoS_random() % 256,
737 colors[i + 1][2] = (int)XaoS_random() % 256;
738 }
739 }
740 colors[i - 1][0] = colors[0][0];
741 colors[i - 1][1] = colors[0][1];
742 colors[i - 1][2] = colors[0][2];
743 }
744
745 #define MYLONG_MAX 0xffffff
746 #define rrandom(i) ((int)(((int)XaoS_random() / (double)MYLONG_MAX) * (i)))
747 /*Do not use modulo type random since it should bring very different results
748 *for slightly different sizes
749 */
750
mkpalette(struct palette * c,int seed,int algorithm)751 int mkpalette(struct palette *c, int seed, int algorithm)
752 {
753 int i, ncolors = c->size;
754 int whitemode;
755 int i1;
756
757 context = c;
758 needupdate = 0;
759
760 if (c->flags & DONOTCHANGE)
761 return 0;
762 XaoS_srandom(seed);
763 seed = (int)XaoS_random();
764 whitemode = (int)XaoS_random() % 2;
765
766 if ((c->flags & UNKNOWNENTRIES) || !c->size) {
767 maxentries = context->maxentries - nprecells;
768 segmentsize = (rrandom(maxentries / 2)) & (~3);
769 if (segmentsize < 1)
770 segmentsize = 1;
771 } else {
772 if (maxentries > 8) {
773 int qq = 255;
774
775 maxentries = context->maxentries - nprecells;
776 segmentsize = rrandom(qq / 3 + 4);
777 segmentsize += rrandom(qq / 3 + 4);
778 segmentsize += rrandom(qq / 3 + 4);
779 segmentsize += rrandom(
780 qq / 3 + 4); /*Make smaller segments with higher probability */
781
782 segmentsize = abs(segmentsize / 2 - qq / 3 + 3);
783 if (segmentsize < 8)
784 segmentsize = 8;
785 if (segmentsize > maxentries / 3)
786 segmentsize = maxentries / 3;
787 }
788 }
789
790 if (c->flags & UNKNOWNENTRIES)
791 i = rrandom(maxentries);
792 else
793 i = (maxentries + segmentsize - 5) / segmentsize;
794
795 if (i < 0)
796 i = 1;
797 if (i > MAXNSEGMENTS)
798 i1 = MAXNSEGMENTS;
799 else
800 i1 = i;
801
802 XaoS_srandom(seed);
803
804 switch (algorithm) {
805 case 2:
806 randomize_segments3(whitemode, i1);
807 break;
808 case 1:
809 randomize_segments2(whitemode, i1);
810 break;
811 case 0:
812 randomize_segments(whitemode, i1);
813 }
814 mksmooth(i1, i);
815
816 if (!(c->flags & FINISHLATER)) {
817 if (c->allocfinished != NULL)
818 c->allocfinished(c);
819 } else
820 c->flags |= UNFINISHED;
821 if (context->size != ncolors || needupdate) {
822 context->version++;
823 return 1;
824 }
825
826 return 0;
827 }
828
mkstereogrampalette(struct palette * c)829 int mkstereogrampalette(struct palette *c)
830 {
831 int i, ncolors = c->size;
832 context = c;
833 needupdate = 0;
834 for (i = 0; i < 16; i++)
835 allocate(i * 4, i * 4, i * 16, i == 0);
836 if (!(c->flags & FINISHLATER)) {
837 if (c->allocfinished != NULL)
838 c->allocfinished(c);
839 } else
840 c->flags |= UNFINISHED;
841 if (context->size != ncolors || needupdate) {
842 context->version++;
843 return 1;
844 }
845 return 0;
846 }
847
mkstarfieldpalette(struct palette * c)848 int mkstarfieldpalette(struct palette *c)
849 {
850 int i, ncolors = c->size;
851 context = c;
852 needupdate = 0;
853 for (i = 0; i < 16; i++)
854 if (i % 2)
855 allocate(i * 4, i * 4, i * 16, i == 0);
856 else
857 allocate(i * 16, i * 16, i * 16, i == 0);
858 if (!(c->flags & FINISHLATER)) {
859 if (c->allocfinished != NULL)
860 c->allocfinished(c);
861 } else
862 c->flags |= UNFINISHED;
863 if (context->size != ncolors || needupdate) {
864 context->version++;
865 return 1;
866 }
867 return 0;
868 }
869
mkblurpalette(struct palette * c)870 int mkblurpalette(struct palette *c)
871 {
872 int i, ncolors = c->size;
873 context = c;
874 needupdate = 0;
875 for (i = 0; i < 63; i++)
876 allocate(i * 2, i * 2, i * 4, i == 0);
877 allocate(i * 2, i * 2, i * 4 - 1, 0);
878 if (!(c->flags & FINISHLATER)) {
879 if (c->allocfinished != NULL)
880 c->allocfinished(c);
881 } else
882 c->flags |= UNFINISHED;
883 if (context->size != ncolors || needupdate) {
884 context->version++;
885 return 1;
886 }
887 return 0;
888 }
889
mkgraypalette(struct palette * c)890 int mkgraypalette(struct palette *c)
891 {
892 int i, ncolors = c->size;
893 context = c;
894 needupdate = 0;
895 for (i = 0; i < 64; i++)
896 allocate(i * 4, i * 4, i * 4, i == 0);
897 for (i = 0; i < 16; i++)
898 allocate(255, 255 - i * 16, 255 - i * 16, 0);
899 for (i = 0; i < 16; i++)
900 allocate(255 - i * 16, 0, 0, 0);
901 if (!(c->flags & FINISHLATER)) {
902 if (c->allocfinished != NULL)
903 c->allocfinished(c);
904 } else
905 c->flags |= UNFINISHED;
906 if (context->size != ncolors || needupdate) {
907 context->version++;
908 return 1;
909 }
910 return 0;
911 }
912
mkdefaultpalette(struct palette * c)913 int mkdefaultpalette(struct palette *c)
914 {
915 int i, ncolors = c->size;
916 context = c;
917 needupdate = 0;
918 segmentsize = 8;
919
920 if (c->flags & DONOTCHANGE)
921 return 0;
922 memcpy(colors, colors1, sizeof(colors1));
923 maxentries = context->maxentries - nprecells;
924 if (c->flags & UNKNOWNENTRIES)
925 i = 128 / 8;
926 else
927 i = (maxentries + 3) / 8;
928 if (i < 0)
929 i = 1;
930 mksmooth(255 / 8, i);
931 if (!(c->flags & FINISHLATER)) {
932 if (c->allocfinished != NULL)
933 c->allocfinished(c);
934 } else
935 c->flags |= UNFINISHED;
936 if (context->size != ncolors || needupdate) {
937 context->version++;
938 return 1;
939 }
940 return 0;
941 }
942
shiftpalette(struct palette * c,int shift)943 int shiftpalette(struct palette *c, int shift)
944 {
945 if (!c->size)
946 return 0;
947
948 while (shift < 0)
949 shift += c->size - 1;
950 shift = shift % (c->size - 1);
951
952 if (!shift)
953 return 0;
954
955 if (c->cyclecolors != NULL) {
956 if (c->flags & UNFINISHED) {
957 cycle_entries(c, shift);
958 } else {
959 c->cyclecolors(c, shift);
960 }
961 return 0;
962 }
963
964 if (c->type & (TRUECOLOR | TRUECOLOR24 | TRUECOLOR16)) {
965 int i;
966 int i3;
967 int *co;
968
969 if (shift > 0)
970 shift %= c->size - 1;
971 else
972 shift = -((-shift) % (c->size - 1));
973 if (!shift)
974 return 0;
975 co = (int *)malloc(c->size * sizeof(*co));
976 memcpy(co, c->pixels, sizeof(*co) * c->size);
977 i3 = (c->size - 1 + shift) % (c->size - 1) + 1;
978 for (i = 1; i < c->size; i++) {
979 c->pixels[i] = co[i3];
980 i3++;
981 if (i3 >= c->size)
982 i3 = 1;
983 }
984 c->version++;
985 free(co);
986 }
987 return 1;
988 }
989
allocrgb(struct palette *,int r1,int g1,int b1)990 static int allocrgb(struct palette */*c*/, int r1, int g1, int b1)
991 {
992 int r, g, b;
993 int f = 1;
994 for (g = 0; g < g1; g++)
995 for (b = 0; b < b1; b++) {
996 for (r = 0; r < r1; r++) {
997 if (!allocate(r * 255 / (r1 - 1), g * 255 / (g1 - 1),
998 b * 255 / (b1 - 1), f))
999 return 0;
1000 f = 0;
1001 }
1002 }
1003 return 1;
1004 }
1005
mkrgb(struct palette * c)1006 int mkrgb(struct palette *c)
1007 {
1008 int ncolors = c->size;
1009 int red = 8, green = 8, blue = 4;
1010
1011 context = c;
1012 needupdate = 0;
1013
1014 if (c->flags & UNKNOWNENTRIES) {
1015 while (blue > 0) {
1016 if (allocrgb(c, red, green, blue))
1017 break;
1018 red--;
1019 if (allocrgb(c, red, green, blue))
1020 break;
1021 green--;
1022 if (allocrgb(c, red, green, blue))
1023 break;
1024 red--;
1025 if (allocrgb(c, red, green, blue))
1026 break;
1027 green--;
1028 if (allocrgb(c, red, green, blue))
1029 break;
1030 blue--;
1031 }
1032 } else {
1033 number_t n =
1034 pow((c->maxentries - nprecells) / (0.5 * 0.2 * 0.3), 1.0 / 3);
1035 green = (int)(n * 0.5);
1036 blue = (int)(n * 0.2);
1037 red = (int)(n * 0.3);
1038 while ((blue + 1) * red * green < (c->maxentries - nprecells))
1039 blue++;
1040 while ((red + 1) * blue * green < (c->maxentries - nprecells))
1041 red++;
1042 while ((green + 1) * blue * red < (c->maxentries - nprecells))
1043 green++;
1044 allocrgb(c, red, green, blue);
1045 }
1046
1047 if (!(c->flags & FINISHLATER)) {
1048 if (c->allocfinished != NULL)
1049 c->allocfinished(c);
1050 } else
1051 c->flags |= UNFINISHED;
1052 if (context->size != ncolors || needupdate) {
1053 context->version++;
1054 }
1055
1056 return red * 256 * 256 + green * 256 + blue;
1057 }
1058
getPaletteColor(struct palette * src,int seed,int algorithm,int shift,int newColors[101][3])1059 void getPaletteColor(struct palette *src, int seed, int algorithm, int shift, int newColors[101][3]) {
1060 mkpalette(src, seed, algorithm);
1061 shiftpalette(src, shift);
1062 for (int i = 0; i < 101; i++) {
1063 int r = 0, g = 0, b = 0;
1064 switch (src->type) {
1065 case SMALLITER:
1066 r = g = b = i;
1067 break;
1068 case LARGEITER:
1069 r = g = b = i / 256;
1070 break;
1071 case GRAYSCALE:
1072 r = g = b = src->pixels[i];
1073 break;
1074 case C256:
1075 case FIXEDCOLOR:
1076 case MBITMAP:
1077 case LBITMAP:
1078 case MIBITMAP:
1079 case LIBITMAP:
1080 r = src->rgb[src->pixels[i]][0];
1081 g = src->rgb[src->pixels[i]][1];
1082 b = src->rgb[src->pixels[i]][2];
1083 break;
1084 case TRUECOLOR:
1085 case TRUECOLOR16:
1086 case TRUECOLOR24:
1087 r = (((src->pixels[i] & src->info.truec.rmask) >>
1088 src->info.truec.rshift))
1089 << src->info.truec.rprec;
1090 g = (((src->pixels[i] & src->info.truec.gmask) >>
1091 src->info.truec.gshift))
1092 << src->info.truec.gprec;
1093 b = (((src->pixels[i] & src->info.truec.bmask) >>
1094 src->info.truec.bshift))
1095 << src->info.truec.bprec;
1096 break;
1097 }
1098 newColors[i][0]=r;
1099 newColors[i][1]=g;
1100 newColors[i][2]=b;
1101 }
1102 }
1103
getDEFSEGMENTColor(unsigned char newColors[][3])1104 void getDEFSEGMENTColor(unsigned char newColors[][3]) {
1105 memcpy(newColors, colors, sizeof(colors1));
1106 }
1107
mkcustompalette(struct palette * c,unsigned char newColors[31][3])1108 int mkcustompalette(struct palette *c, unsigned char newColors[31][3])
1109 {
1110 int i, ncolors = c->size;
1111 context = c;
1112 needupdate = 0;
1113 segmentsize = 8;
1114
1115 if (c->flags & DONOTCHANGE)
1116 return 0;
1117 memcpy(colors, newColors, sizeof(colors1));
1118 maxentries = context->maxentries - nprecells;
1119 if (c->flags & UNKNOWNENTRIES)
1120 i = 128 / 8;
1121 else
1122 i = (maxentries + 3) / 8;
1123 if (i < 0)
1124 i = 1;
1125 mksmooth(255 / 8, i);
1126 if (!(c->flags & FINISHLATER)) {
1127 if (c->allocfinished != NULL)
1128 c->allocfinished(c);
1129 } else
1130 c->flags |= UNFINISHED;
1131 if (context->size != ncolors || needupdate) {
1132 context->version++;
1133 return 1;
1134 }
1135 return 0;
1136 }
1137