1 /* ScummVM - Graphic Adventure Engine
2 *
3 * ScummVM is the legal property of its developers, whose names
4 * are too numerous to list here. Please refer to the COPYRIGHT
5 * file distributed with this source distribution.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program 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
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 *
21 */
22
23 #include "ags/lib/allegro/color.h"
24 #include "ags/lib/allegro/system.h"
25 #include "ags/lib/allegro/aintern.h"
26 #include "ags/shared/core/types.h"
27 #include "ags/shared/util/stream.h"
28 #include "ags/globals.h"
29 #include "common/textconsole.h"
30 #include "common/system.h"
31 #include "graphics/palette.h"
32
33 namespace AGS3 {
34
35 #define VGA_COLOR_TRANS(x) ((x) * 255 / 63)
36
readFromFile(AGS::Shared::Stream * file)37 void color::readFromFile(AGS::Shared::Stream *file) {
38 r = file->ReadByte();
39 g = file->ReadByte();
40 b = file->ReadByte();
41 filler = file->ReadByte();
42 }
43
writeToFile(AGS::Shared::Stream * file) const44 void color::writeToFile(AGS::Shared::Stream *file) const {
45 file->WriteByte(r);
46 file->WriteByte(g);
47 file->WriteByte(b);
48 file->WriteByte(filler);
49 }
50
convertPalette(const PALETTE src,byte dest[PALETTE_SIZE])51 static void convertPalette(const PALETTE src, byte dest[PALETTE_SIZE]) {
52 const color *cSrc = (const color *)src;
53 for (int i = 0; i < PALETTE_COUNT; ++i, cSrc++, dest += 3) {
54 dest[0] = VGA_COLOR_TRANS(cSrc->r);
55 dest[1] = VGA_COLOR_TRANS(cSrc->g);
56 dest[2] = VGA_COLOR_TRANS(cSrc->b);
57 }
58 }
59
applyPalette()60 static void applyPalette() {
61 if (g_system->getScreenFormat().bytesPerPixel == 1) {
62 byte pal[PALETTE_SIZE];
63 convertPalette(_G(current_palette), pal);
64 g_system->getPaletteManager()->setPalette(pal, 0, PALETTE_COUNT);
65 }
66 }
67
set_palette(const PALETTE p)68 void set_palette(const PALETTE p) {
69 for (int idx = 0; idx < PAL_SIZE; ++idx)
70 _G(current_palette)[idx] = p[idx];
71
72 applyPalette();
73 }
74
set_palette_range(const PALETTE p,int from,int to,int retracesync)75 void set_palette_range(const PALETTE p, int from, int to, int retracesync) {
76 for (int i = from; i <= to; ++i) {
77 _G(current_palette)[i] = p[i];
78 }
79
80 applyPalette();
81 }
82
makecol15(int r,int g,int b)83 int makecol15(int r, int g, int b) {
84 return (((r >> 3) << _G(_rgb_r_shift_15)) |
85 ((g >> 3) << _G(_rgb_g_shift_15)) |
86 ((b >> 3) << _G(_rgb_b_shift_15)));
87 }
88
makecol16(int r,int g,int b)89 int makecol16(int r, int g, int b) {
90 return (((r >> 3) << _G(_rgb_r_shift_16)) |
91 ((g >> 2) << _G(_rgb_g_shift_16)) |
92 ((b >> 3) << _G(_rgb_b_shift_16)));
93 }
94
makecol24(int r,int g,int b)95 int makecol24(int r, int g, int b) {
96 return ((r << _G(_rgb_r_shift_24)) |
97 (g << _G(_rgb_g_shift_24)) |
98 (b << _G(_rgb_b_shift_24)));
99 }
100
makecol32(int r,int g,int b)101 int makecol32(int r, int g, int b) {
102 return ((r << _G(_rgb_r_shift_32)) |
103 (g << _G(_rgb_g_shift_32)) |
104 (b << _G(_rgb_b_shift_32)));
105 }
106
makeacol32(int r,int g,int b,int a)107 int makeacol32(int r, int g, int b, int a) {
108 return ((r << _G(_rgb_r_shift_32)) |
109 (g << _G(_rgb_g_shift_32)) |
110 (b << _G(_rgb_b_shift_32)) |
111 (a << _G(_rgb_a_shift_32)));
112 }
113
getr8(int c)114 int getr8(int c) {
115 return (int)_G(current_palette)[c].r;
116 }
117
getg8(int c)118 int getg8(int c) {
119 return (int)_G(current_palette)[c].g;
120 }
121
getb8(int c)122 int getb8(int c) {
123 return (int)_G(current_palette)[c].b;
124 }
125
getr15(int c)126 int getr15(int c) {
127 return _rgb_scale_5[(c >> _G(_rgb_r_shift_15)) & 0x1F];
128 }
129
getg15(int c)130 int getg15(int c) {
131 return _rgb_scale_5[(c >> _G(_rgb_g_shift_15)) & 0x1F];
132 }
133
getb15(int c)134 int getb15(int c) {
135 return _rgb_scale_5[(c >> _G(_rgb_b_shift_15)) & 0x1F];
136 }
137
getr16(int c)138 int getr16(int c) {
139 return _rgb_scale_5[(c >> _G(_rgb_r_shift_16)) & 0x1F];
140 }
141
getg16(int c)142 int getg16(int c) {
143 return _rgb_scale_6[(c >> _G(_rgb_g_shift_16)) & 0x3F];
144 }
145
getb16(int c)146 int getb16(int c) {
147 return _rgb_scale_5[(c >> _G(_rgb_b_shift_16)) & 0x1F];
148 }
149
getr24(int c)150 int getr24(int c) {
151 return ((c >> _G(_rgb_r_shift_24)) & 0xFF);
152 }
153
getg24(int c)154 int getg24(int c) {
155 return ((c >> _G(_rgb_g_shift_24)) & 0xFF);
156 }
157
getb24(int c)158 int getb24(int c) {
159 return ((c >> _G(_rgb_b_shift_24)) & 0xFF);
160 }
161
getr32(int c)162 int getr32(int c) {
163 return ((c >> _G(_rgb_r_shift_32)) & 0xFF);
164 }
165
getg32(int c)166 int getg32(int c) {
167 return ((c >> _G(_rgb_g_shift_32)) & 0xFF);
168 }
169
getb32(int c)170 int getb32(int c) {
171 return ((c >> _G(_rgb_b_shift_32)) & 0xFF);
172 }
173
geta32(int c)174 int geta32(int c) {
175 return ((c >> _G(_rgb_a_shift_32)) & 0xFF);
176 }
177
makecol(byte r,byte g,byte b)178 int makecol(byte r, byte g, byte b) {
179 return (b) | (g << 8) | (r << 16);
180 }
181
makecol8(byte r,byte g,byte b)182 int makecol8(byte r, byte g, byte b) {
183 return (b) | (g << 8) | (r << 16);
184 }
185
get_color(int idx,RGB * p)186 void get_color(int idx, RGB *p) {
187 *p = _G(current_palette)[idx];
188 }
189
get_palette_range(PALETTE p,int from,int to)190 void get_palette_range(PALETTE p, int from, int to) {
191 Common::copy(&_G(current_palette)[from], &_G(current_palette)[to + 1], &p[from]);
192 }
193
get_palette(PALETTE p)194 void get_palette(PALETTE p) {
195 get_palette_range(p, 0, PAL_SIZE - 1);
196 }
197
fade_interpolate(AL_CONST PALETTE source,AL_CONST PALETTE dest,PALETTE output,int pos,int from,int to)198 void fade_interpolate(AL_CONST PALETTE source, AL_CONST PALETTE dest, PALETTE output, int pos, int from, int to) {
199 assert(pos >= 0 && pos <= 64);
200 assert(from >= 0 && from < PAL_SIZE);
201 assert(to >= 0 && to < PAL_SIZE);
202
203 for (int c = from; c <= to; c++) {
204 output[c].r = ((int)source[c].r * (63 - pos) + (int)dest[c].r * pos) / 64;
205 output[c].g = ((int)source[c].g * (63 - pos) + (int)dest[c].g * pos) / 64;
206 output[c].b = ((int)source[c].b * (63 - pos) + (int)dest[c].b * pos) / 64;
207 }
208 }
209
select_palette(AL_CONST PALETTE p)210 void select_palette(AL_CONST PALETTE p) {
211 int c;
212
213 for (c = 0; c < PAL_SIZE; c++) {
214 _G(prev_current_palette)[c] = _G(current_palette)[c];
215 _G(current_palette)[c] = p[c];
216 }
217
218 applyPalette();
219 }
220
unselect_palette(void)221 void unselect_palette(void) {
222 int c;
223
224 for (c = 0; c < PAL_SIZE; c++)
225 _G(current_palette)[c] = _G(prev_current_palette)[c];
226
227 applyPalette();
228 }
229
set_blender_mode(BlenderMode m,int r,int g,int b,int a)230 void set_blender_mode(BlenderMode m, int r, int g, int b, int a) {
231 _G(_blender_mode) = m;
232 _G(trans_blend_alpha) = a;
233 _G(trans_blend_red) = r;
234 _G(trans_blend_green) = g;
235 _G(trans_blend_blue) = b;
236 }
237
set_alpha_blender(void)238 void set_alpha_blender(void) {
239 set_blender_mode(kSourceAlphaBlender, 0, 0, 0, 0);
240 }
241
set_trans_blender(int r,int g,int b,int a)242 void set_trans_blender(int r, int g, int b, int a) {
243 set_blender_mode(kRgbToRgbBlender, r, g, b, a);
244 }
245
246 /* makecol_depth:
247 * Converts R, G, and B values (ranging 0-255) to whatever pixel format
248 * is required by the specified color depth.
249 */
makecol_depth(int color_depth,int r,int g,int b)250 int makecol_depth(int color_depth, int r, int g, int b) {
251 switch (color_depth) {
252
253 case 8:
254 return makecol8(r, g, b);
255
256 case 15:
257 return makecol15(r, g, b);
258
259 case 16:
260 return makecol16(r, g, b);
261
262 case 24:
263 return makecol24(r, g, b);
264
265 case 32:
266 return makecol32(r, g, b);
267 }
268
269 return 0;
270 }
271
272
273
274 /* makeacol_depth:
275 * Converts R, G, B, and A values (ranging 0-255) to whatever pixel format
276 * is required by the specified color depth.
277 */
makeacol_depth(int color_depth,int r,int g,int b,int a)278 int makeacol_depth(int color_depth, int r, int g, int b, int a) {
279 switch (color_depth) {
280
281 case 8:
282 return makecol8(r, g, b);
283
284 case 15:
285 return makecol15(r, g, b);
286
287 case 16:
288 return makecol16(r, g, b);
289
290 case 24:
291 return makecol24(r, g, b);
292
293 case 32:
294 return makeacol32(r, g, b, a);
295 }
296
297 return 0;
298 }
299
300 /* getr_depth:
301 * Extracts the red component (ranging 0-255) from a pixel in the format
302 * being used by the specified color depth.
303 */
getr_depth(int color_depth,int c)304 int getr_depth(int color_depth, int c) {
305 switch (color_depth) {
306
307 case 8:
308 return getr8(c);
309
310 case 15:
311 return getr15(c);
312
313 case 16:
314 return getr16(c);
315
316 case 24:
317 return getr24(c);
318
319 case 32:
320 return getr32(c);
321 }
322
323 return 0;
324 }
325
326
327
328 /* getg_depth:
329 * Extracts the green component (ranging 0-255) from a pixel in the format
330 * being used by the specified color depth.
331 */
getg_depth(int color_depth,int c)332 int getg_depth(int color_depth, int c) {
333 switch (color_depth) {
334
335 case 8:
336 return getg8(c);
337
338 case 15:
339 return getg15(c);
340
341 case 16:
342 return getg16(c);
343
344 case 24:
345 return getg24(c);
346
347 case 32:
348 return getg32(c);
349 }
350
351 return 0;
352 }
353
354
355
356 /* getb_depth:
357 * Extracts the blue component (ranging 0-255) from a pixel in the format
358 * being used by the specified color depth.
359 */
getb_depth(int color_depth,int c)360 int getb_depth(int color_depth, int c) {
361 switch (color_depth) {
362
363 case 8:
364 return getb8(c);
365
366 case 15:
367 return getb15(c);
368
369 case 16:
370 return getb16(c);
371
372 case 24:
373 return getb24(c);
374
375 case 32:
376 return getb32(c);
377 }
378
379 return 0;
380 }
381
382
383
384 /* geta_depth:
385 * Extracts the alpha component (ranging 0-255) from a pixel in the format
386 * being used by the specified color depth.
387 */
geta_depth(int color_depth,int c)388 int geta_depth(int color_depth, int c) {
389 if (color_depth == 32)
390 return geta32(c);
391
392 return 0;
393 }
394
395
396
397 /* getr:
398 * Extracts the red component (ranging 0-255) from a pixel in the format
399 * being used by the current video mode.
400 */
getr(int c)401 int getr(int c) {
402 return getr_depth(_G(_color_depth), c);
403 }
404
405
406
407 /* getg:
408 * Extracts the green component (ranging 0-255) from a pixel in the format
409 * being used by the current video mode.
410 */
getg(int c)411 int getg(int c) {
412 return getg_depth(_G(_color_depth), c);
413 }
414
415
416
417 /* getb:
418 * Extracts the blue component (ranging 0-255) from a pixel in the format
419 * being used by the current video mode.
420 */
getb(int c)421 int getb(int c) {
422 return getb_depth(_G(_color_depth), c);
423 }
424
425
426
427 /* geta:
428 * Extracts the alpha component (ranging 0-255) from a pixel in the format
429 * being used by the current video mode.
430 */
geta(int c)431 int geta(int c) {
432 return geta_depth(_G(_color_depth), c);
433 }
434
435
436
437 /* 1.5k lookup table for color matching */
438 static unsigned int col_diff[3 * 128];
439
440
441
442 /* bestfit_init:
443 * Color matching is done with weighted squares, which are much faster
444 * if we pregenerate a little lookup table...
445 */
bestfit_init(void)446 static void bestfit_init(void) {
447 int i;
448
449 for (i = 1; i < 64; i++) {
450 int k = i * i;
451 col_diff[0 + i] = col_diff[0 + 128 - i] = k * (59 * 59);
452 col_diff[128 + i] = col_diff[128 + 128 - i] = k * (30 * 30);
453 col_diff[256 + i] = col_diff[256 + 128 - i] = k * (11 * 11);
454 }
455 }
456
457
458
459 /* bestfit_color:
460 * Searches a palette for the color closest to the requested R, G, B value.
461 */
bestfit_color(AL_CONST PALETTE pal,int r,int g,int b)462 int bestfit_color(AL_CONST PALETTE pal, int r, int g, int b) {
463 int i, coldiff, lowest, bestfit;
464
465 assert(r >= 0 && r <= 63);
466 assert(g >= 0 && g <= 63);
467 assert(b >= 0 && b <= 63);
468
469 if (col_diff[1] == 0)
470 bestfit_init();
471
472 bestfit = 0;
473 lowest = INT_MAX;
474
475 /* only the transparent (pink) color can be mapped to index 0 */
476 if ((r == 63) && (g == 0) && (b == 63))
477 i = 0;
478 else
479 i = 1;
480
481 while (i < PAL_SIZE) {
482 AL_CONST RGB *rgb = &pal[i];
483 coldiff = (col_diff + 0)[(rgb->g - g) & 0x7F];
484 if (coldiff < lowest) {
485 coldiff += (col_diff + 128)[(rgb->r - r) & 0x7F];
486 if (coldiff < lowest) {
487 coldiff += (col_diff + 256)[(rgb->b - b) & 0x7F];
488 if (coldiff < lowest) {
489 bestfit = rgb - pal; /* faster than `bestfit = i;' */
490 if (coldiff == 0)
491 return bestfit;
492 lowest = coldiff;
493 }
494 }
495 }
496 i++;
497 }
498
499 return bestfit;
500 }
501
502
503
504 /* makecol8:
505 * Converts R, G, and B values (ranging 0-255) to an 8 bit paletted color.
506 * If the global _G(rgb_map) table is initialised, it uses that, otherwise
507 * it searches through the current palette to find the best match.
508 */
makecol8(int r,int g,int b)509 int makecol8(int r, int g, int b) {
510 if (_G(rgb_map))
511 return _G(rgb_map)->data[r >> 3][g >> 3][b >> 3];
512 else
513 return bestfit_color(_G(current_palette), r >> 2, g >> 2, b >> 2);
514 }
515
516
517
518 /* hsv_to_rgb:
519 * Converts from HSV colorspace to RGB values.
520 */
hsv_to_rgb(float h,float s,float v,int * r,int * g,int * b)521 void hsv_to_rgb(float h, float s, float v, int *r, int *g, int *b) {
522 float f, x, y, z;
523 int i;
524
525 assert(s >= 0 && s <= 1);
526 assert(v >= 0 && v <= 1);
527
528 v *= 255.0f;
529
530 if (s == 0.0f) { /* ok since we don't divide by s, and faster */
531 *r = *g = *b = v + 0.5f;
532 } else {
533 h = fmod(h, 360.0f) / 60.0f;
534 if (h < 0.0f)
535 h += 6.0f;
536
537 i = (int)h;
538 f = h - i;
539 x = v * s;
540 y = x * f;
541 v += 0.5f; /* round to the nearest integer below */
542 z = v - x;
543
544 switch (i) {
545
546 case 6:
547 case 0:
548 *r = v;
549 *g = z + y;
550 *b = z;
551 break;
552
553 case 1:
554 *r = v - y;
555 *g = v;
556 *b = z;
557 break;
558
559 case 2:
560 *r = z;
561 *g = v;
562 *b = z + y;
563 break;
564
565 case 3:
566 *r = z;
567 *g = v - y;
568 *b = v;
569 break;
570
571 case 4:
572 *r = z + y;
573 *g = z;
574 *b = v;
575 break;
576
577 case 5:
578 *r = v;
579 *g = z;
580 *b = v - y;
581 break;
582 }
583 }
584 }
585
586
587
588 /* rgb_to_hsv:
589 * Converts an RGB value into the HSV colorspace.
590 */
rgb_to_hsv(int r,int g,int b,float * h,float * s,float * v)591 void rgb_to_hsv(int r, int g, int b, float *h, float *s, float *v) {
592 int delta;
593
594 assert(r >= 0 && r <= 255);
595 assert(g >= 0 && g <= 255);
596 assert(b >= 0 && b <= 255);
597
598 if (r > g) {
599 if (b > r) {
600 /* b>r>g */
601 delta = b - g;
602 *h = 240.0f + ((r - g) * 60) / (float)delta;
603 *s = (float)delta / (float)b;
604 *v = (float)b * (1.0f / 255.0f);
605 } else {
606 /* r>g and r>b */
607 delta = r - MIN(g, b);
608 *h = ((g - b) * 60) / (float)delta;
609 if (*h < 0.0f)
610 *h += 360.0f;
611 *s = (float)delta / (float)r;
612 *v = (float)r * (1.0f / 255.0f);
613 }
614 } else {
615 if (b > g) {
616 /* b>g>=r */
617 delta = b - r;
618 *h = 240.0f + ((r - g) * 60) / (float)delta;
619 *s = (float)delta / (float)b;
620 *v = (float)b * (1.0f / 255.0f);
621 } else {
622 /* g>=b and g>=r */
623 delta = g - MIN(r, b);
624 if (delta == 0) {
625 *h = 0.0f;
626 if (g == 0)
627 *s = *v = 0.0f;
628 else {
629 *s = (float)delta / (float)g;
630 *v = (float)g * (1.0f / 255.0f);
631 }
632 } else {
633 *h = 120.0f + ((b - r) * 60) / (float)delta;
634 *s = (float)delta / (float)g;
635 *v = (float)g * (1.0f / 255.0f);
636 }
637 }
638 }
639 }
640
641
642
643 /* create_rgb_table:
644 * Fills an RGB_MAP lookup table with conversion data for the specified
645 * palette. This is the faster version by Jan Hubicka.
646 *
647 * Uses alg. similar to floodfill - it adds one seed per every color in
648 * palette to its best position. Then areas around seed are filled by
649 * same color because it is best approximation for them, and then areas
650 * about them etc...
651 *
652 * It does just about 80000 tests for distances and this is about 100
653 * times better than normal 256*32000 tests so the calculation time
654 * is now less than one second at all computers I tested.
655 */
create_rgb_table(RGB_MAP * table,AL_CONST PALETTE pal,void (* callback)(int pos))656 void create_rgb_table(RGB_MAP *table, AL_CONST PALETTE pal, void (*callback)(int pos)) {
657 #define UNUSED 65535
658 #define LAST 65532
659
660 /* macro add adds to single linked list */
661 #define add(i) (next[(i)] == UNUSED ? (next[(i)] = LAST, \
662 (first != LAST ? (next[last] = (i)) : (first = (i))), \
663 (last = (i))) : 0)
664
665 /* same but w/o checking for first element */
666 #define add1(i) (next[(i)] == UNUSED ? (next[(i)] = LAST, \
667 next[last] = (i), \
668 (last = (i))) : 0)
669
670 /* calculates distance between two colors */
671 #define dist(a1, a2, a3, b1, b2, b3) \
672 (col_diff[ ((a2) - (b2)) & 0x7F] + \
673 (col_diff + 128)[((a1) - (b1)) & 0x7F] + \
674 (col_diff + 256)[((a3) - (b3)) & 0x7F])
675
676 /* converts r,g,b to position in array and back */
677 #define pos(r, g, b) \
678 (((r) / 2) * 32 * 32 + ((g) / 2) * 32 + ((b) / 2))
679
680 #define depos(pal, r, g, b) \
681 ((b) = ((pal) & 31) * 2, \
682 (g) = (((pal) >> 5) & 31) * 2, \
683 (r) = (((pal) >> 10) & 31) * 2)
684
685 /* is current color better than pal1? */
686 #define better(r1, g1, b1, pal1) \
687 (((int)dist((r1), (g1), (b1), \
688 (pal1).r, (pal1).g, (pal1).b)) > (int)dist2)
689
690 /* checking of position */
691 #define dopos(rp, gp, bp, ts) \
692 if ((rp > -1 || r > 0) && (rp < 1 || r < 61) && \
693 (gp > -1 || g > 0) && (gp < 1 || g < 61) && \
694 (bp > -1 || b > 0) && (bp < 1 || b < 61)) { \
695 i = first + rp * 32 * 32 + gp * 32 + bp; \
696 if (!data[i]) { \
697 data[i] = val; \
698 add1(i); \
699 } \
700 else if ((ts) && (data[i] != val)) { \
701 dist2 = (rp ? (col_diff+128)[(r+2*rp-pal[val].r) & 0x7F] : r2) + \
702 (gp ? (col_diff )[(g+2*gp-pal[val].g) & 0x7F] : g2) + \
703 (bp ? (col_diff+256)[(b+2*bp-pal[val].b) & 0x7F] : b2); \
704 if (better((r+2*rp), (g+2*gp), (b+2*bp), pal[data[i]])) { \
705 data[i] = val; \
706 add1(i); \
707 } \
708 } \
709 }
710
711 int i, curr, r, g, b, val, dist2;
712 unsigned int r2, g2, b2;
713 unsigned short next[32 * 32 * 32];
714 unsigned char *data;
715 int first = LAST;
716 int last = LAST;
717 int count = 0;
718 int cbcount = 0;
719
720 #define AVERAGE_COUNT 18000
721
722 if (col_diff[1] == 0)
723 bestfit_init();
724
725 memset(next, 255, sizeof(next));
726 memset(table->data, 0, sizeof(char) * 32 * 32 * 32);
727
728 data = (unsigned char *)table->data;
729
730 /* add starting seeds for floodfill */
731 for (i = 1; i < PAL_SIZE; i++) {
732 curr = pos(pal[i].r, pal[i].g, pal[i].b);
733 if (next[curr] == UNUSED) {
734 data[curr] = i;
735 add(curr);
736 }
737 }
738
739 /* main floodfill: two versions of loop for faster growing in blue axis */
740 while (first != LAST) {
741 depos(first, r, g, b);
742
743 /* calculate distance of current color */
744 val = data[first];
745 r2 = (col_diff + 128)[((pal[val].r) - (r)) & 0x7F];
746 g2 = (col_diff)[((pal[val].g) - (g)) & 0x7F];
747 b2 = (col_diff + 256)[((pal[val].b) - (b)) & 0x7F];
748
749 /* try to grow to all directions */
750 dopos(0, 0, 1, 1);
751 dopos(0, 0, -1, 1);
752 dopos(1, 0, 0, 1);
753 dopos(-1, 0, 0, 1);
754 dopos(0, 1, 0, 1);
755 dopos(0, -1, 0, 1);
756
757 /* faster growing of blue direction */
758 if ((b > 0) && (data[first - 1] == val)) {
759 b -= 2;
760 first--;
761 b2 = (col_diff + 256)[((pal[val].b) - (b)) & 0x7F];
762
763 dopos(-1, 0, 0, 0);
764 dopos(1, 0, 0, 0);
765 dopos(0, -1, 0, 0);
766 dopos(0, 1, 0, 0);
767
768 first++;
769 }
770
771 /* get next from list */
772 i = first;
773 first = next[first];
774 next[i] = UNUSED;
775
776 /* second version of loop */
777 if (first != LAST) {
778 depos(first, r, g, b);
779
780 val = data[first];
781 r2 = (col_diff + 128)[((pal[val].r) - (r)) & 0x7F];
782 g2 = (col_diff)[((pal[val].g) - (g)) & 0x7F];
783 b2 = (col_diff + 256)[((pal[val].b) - (b)) & 0x7F];
784
785 dopos(0, 0, 1, 1);
786 dopos(0, 0, -1, 1);
787 dopos(1, 0, 0, 1);
788 dopos(-1, 0, 0, 1);
789 dopos(0, 1, 0, 1);
790 dopos(0, -1, 0, 1);
791
792 if ((b < 61) && (data[first + 1] == val)) {
793 b += 2;
794 first++;
795 b2 = (col_diff + 256)[((pal[val].b) - (b)) & 0x7f];
796
797 dopos(-1, 0, 0, 0);
798 dopos(1, 0, 0, 0);
799 dopos(0, -1, 0, 0);
800 dopos(0, 1, 0, 0);
801
802 first--;
803 }
804
805 i = first;
806 first = next[first];
807 next[i] = UNUSED;
808 }
809
810 count++;
811 if (count == (cbcount + 1) * AVERAGE_COUNT / 256) {
812 if (cbcount < 256) {
813 if (callback)
814 callback(cbcount);
815 cbcount++;
816 }
817 }
818 }
819
820 /* only the transparent (pink) color can be mapped to index 0 */
821 if ((pal[0].r == 63) && (pal[0].g == 0) && (pal[0].b == 63))
822 table->data[31][0][31] = 0;
823
824 if (callback)
825 while (cbcount < 256)
826 callback(cbcount++);
827 }
828
829
830
831 /* create_light_table:
832 * Constructs a lighting color table for the specified palette. At light
833 * intensity 255 the table will produce the palette colors directly, and
834 * at level 0 it will produce the specified R, G, B value for all colors
835 * (this is specified in 0-63 VGA format). If the callback function is
836 * not NULL, it will be called 256 times during the calculation, allowing
837 * you to display a progress indicator.
838 */
create_light_table(COLOR_MAP * table,AL_CONST PALETTE pal,int r,int g,int b,void (* callback)(int pos))839 void create_light_table(COLOR_MAP *table, AL_CONST PALETTE pal, int r, int g, int b, void (*callback)(int pos)) {
840 int r1, g1, b1, r2, g2, b2, x, y;
841 unsigned int t1, t2;
842
843 assert(table);
844 assert(r >= 0 && r <= 63);
845 assert(g >= 0 && g <= 63);
846 assert(b >= 0 && b <= 63);
847
848 if (_G(rgb_map)) {
849 for (x = 0; x < PAL_SIZE - 1; x++) {
850 t1 = x * 0x010101;
851 t2 = 0xFFFFFF - t1;
852
853 r1 = (1 << 24) + r * t2;
854 g1 = (1 << 24) + g * t2;
855 b1 = (1 << 24) + b * t2;
856
857 for (y = 0; y < PAL_SIZE; y++) {
858 r2 = (r1 + pal[y].r * t1) >> 25;
859 g2 = (g1 + pal[y].g * t1) >> 25;
860 b2 = (b1 + pal[y].b * t1) >> 25;
861
862 table->data[x][y] = _G(rgb_map)->data[r2][g2][b2];
863 }
864 }
865 if (callback)
866 (*callback)(x);
867 } else {
868 for (x = 0; x < PAL_SIZE - 1; x++) {
869 t1 = x * 0x010101;
870 t2 = 0xFFFFFF - t1;
871
872 r1 = (1 << 23) + r * t2;
873 g1 = (1 << 23) + g * t2;
874 b1 = (1 << 23) + b * t2;
875
876 for (y = 0; y < PAL_SIZE; y++) {
877 r2 = (r1 + pal[y].r * t1) >> 24;
878 g2 = (g1 + pal[y].g * t1) >> 24;
879 b2 = (b1 + pal[y].b * t1) >> 24;
880
881 table->data[x][y] = bestfit_color(pal, r2, g2, b2);
882 }
883 }
884
885 if (callback)
886 (*callback)(x);
887 }
888
889 for (y = 0; y < PAL_SIZE; y++)
890 table->data[255][y] = y;
891 }
892
893
894
895 /* create_trans_table:
896 * Constructs a translucency color table for the specified palette. The
897 * r, g, and b parameters specifiy the solidity of each color component,
898 * ranging from 0 (totally transparent) to 255 (totally solid). Source
899 * color #0 is a special case, and is set to leave the destination
900 * unchanged, so that masked sprites will draw correctly. If the callback
901 * function is not NULL, it will be called 256 times during the calculation,
902 * allowing you to display a progress indicator.
903 */
create_trans_table(COLOR_MAP * table,AL_CONST PALETTE pal,int r,int g,int b,void (* callback)(int pos))904 void create_trans_table(COLOR_MAP *table, AL_CONST PALETTE pal, int r, int g, int b, void (*callback)(int pos)) {
905 int tmp[768], *q;
906 int x, y, i, j, k;
907 unsigned char *p;
908 int tr, tg, tb;
909 int add;
910
911 assert(table);
912 assert(r >= 0 && r <= 255);
913 assert(g >= 0 && g <= 255);
914 assert(b >= 0 && b <= 255);
915
916 /* This is a bit ugly, but accounts for the solidity parameters
917 being in the range 0-255 rather than 0-256. Given that the
918 precision of r,g,b components is only 6 bits it shouldn't do any
919 harm. */
920 if (r > 128)
921 r++;
922 if (g > 128)
923 g++;
924 if (b > 128)
925 b++;
926
927 if (_G(rgb_map))
928 add = 255;
929 else
930 add = 127;
931
932 for (x = 0; x < 256; x++) {
933 tmp[x * 3] = pal[x].r * (256 - r) + add;
934 tmp[x * 3 + 1] = pal[x].g * (256 - g) + add;
935 tmp[x * 3 + 2] = pal[x].b * (256 - b) + add;
936 }
937
938 for (x = 1; x < PAL_SIZE; x++) {
939 i = pal[x].r * r;
940 j = pal[x].g * g;
941 k = pal[x].b * b;
942
943 p = table->data[x];
944 q = tmp;
945
946 if (_G(rgb_map)) {
947 for (y = 0; y < PAL_SIZE; y++) {
948 tr = (i + * (q++)) >> 9;
949 tg = (j + * (q++)) >> 9;
950 tb = (k + * (q++)) >> 9;
951 p[y] = _G(rgb_map)->data[tr][tg][tb];
952 }
953 } else {
954 for (y = 0; y < PAL_SIZE; y++) {
955 tr = (i + * (q++)) >> 8;
956 tg = (j + * (q++)) >> 8;
957 tb = (k + * (q++)) >> 8;
958 p[y] = bestfit_color(pal, tr, tg, tb);
959 }
960 }
961
962 if (callback)
963 (*callback)(x - 1);
964 }
965
966 for (y = 0; y < PAL_SIZE; y++) {
967 table->data[0][y] = y;
968 table->data[y][y] = y;
969 }
970
971 if (callback)
972 (*callback)(255);
973 }
974
975 } // namespace AGS3
976