BPicture: Fix archive constructor.
[haiku.git] / src / add-ons / translators / gif / SavePalette.cpp
blob329d02cb6f0fcdca668ec679b519a956dbd0ad90
1 ////////////////////////////////////////////////////////////////////////////////
2 //
3 // File: SavePalette.cpp
4 //
5 // Date: December 1999
6 //
7 // Author: Daniel Switkin
8 //
9 // Copyright 2003 (c) by Daniel Switkin. This file is made publically available
10 // under the BSD license, with the stipulations that this complete header must
11 // remain at the top of the file indefinitely, and credit must be given to the
12 // original author in any about box using this software.
14 ////////////////////////////////////////////////////////////////////////////////
16 // Additional authors: Stephan Aßmus, <superstippi@gmx.de>
17 // John Scipione, <jscipione@gmail.com>
20 #include "SavePalette.h"
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
26 #include <new>
28 #include <Bitmap.h>
31 using std::nothrow;
33 extern bool debug;
36 // "web safe palette"
37 const rgb_color wsp[256] = {
38 {0xff, 0xff, 0xff, 0xff}, {0xff, 0xff, 0xcc, 0xff},
39 {0xff, 0xff, 0x99, 0xff}, {0xff, 0xff, 0x66, 0xff},
40 {0xff, 0xff, 0x33, 0xff}, {0xff, 0xff, 0x00, 0xff},
41 {0xff, 0xcc, 0xff, 0xff}, {0xff, 0xcc, 0xcc, 0xff},
42 {0xff, 0xcc, 0x99, 0xff}, {0xff, 0xcc, 0x66, 0xff},
43 {0xff, 0xcc, 0x33, 0xff}, {0xff, 0xcc, 0x00, 0xff},
44 {0xff, 0x99, 0xff, 0xff}, {0xff, 0x99, 0xcc, 0xff},
45 {0xff, 0x99, 0x99, 0xff}, {0xff, 0x99, 0x66, 0xff},
46 {0xff, 0x99, 0x33, 0xff}, {0xff, 0x99, 0x00, 0xff},
47 {0xff, 0x66, 0xff, 0xff}, {0xff, 0x66, 0xcc, 0xff},
48 {0xff, 0x66, 0x99, 0xff}, {0xff, 0x66, 0x66, 0xff},
49 {0xff, 0x66, 0x33, 0xff}, {0xff, 0x66, 0x00, 0xff},
50 {0xff, 0x33, 0xff, 0xff}, {0xff, 0x33, 0xcc, 0xff},
51 {0xff, 0x33, 0x99, 0xff}, {0xff, 0x33, 0x66, 0xff},
52 {0xff, 0x33, 0x33, 0xff}, {0xff, 0x33, 0x00, 0xff},
53 {0xff, 0x00, 0xff, 0xff}, {0xff, 0x00, 0xcc, 0xff},
54 {0xff, 0x00, 0x99, 0xff}, {0xff, 0x00, 0x66, 0xff},
55 {0xff, 0x00, 0x33, 0xff}, {0xff, 0x00, 0x00, 0xff},
56 {0xcc, 0xff, 0xff, 0xff}, {0xcc, 0xff, 0xcc, 0xff},
57 {0xcc, 0xff, 0x99, 0xff}, {0xcc, 0xff, 0x66, 0xff},
58 {0xcc, 0xff, 0x33, 0xff}, {0xcc, 0xff, 0x00, 0xff},
59 {0xcc, 0xcc, 0xff, 0xff}, {0xcc, 0xcc, 0xcc, 0xff},
60 {0xcc, 0xcc, 0x99, 0xff}, {0xcc, 0xcc, 0x66, 0xff},
61 {0xcc, 0xcc, 0x33, 0xff}, {0xcc, 0xcc, 0x00, 0xff},
62 {0xcc, 0x99, 0xff, 0xff}, {0xcc, 0x99, 0xcc, 0xff},
63 {0xcc, 0x99, 0x99, 0xff}, {0xcc, 0x99, 0x66, 0xff},
64 {0xcc, 0x99, 0x33, 0xff}, {0xcc, 0x99, 0x00, 0xff},
65 {0xcc, 0x66, 0xff, 0xff}, {0xcc, 0x66, 0xcc, 0xff},
66 {0xcc, 0x66, 0x99, 0xff}, {0xcc, 0x66, 0x66, 0xff},
67 {0xcc, 0x66, 0x33, 0xff}, {0xcc, 0x66, 0x00, 0xff},
68 {0xcc, 0x33, 0xff, 0xff}, {0xcc, 0x33, 0xcc, 0xff},
69 {0xcc, 0x33, 0x99, 0xff}, {0xcc, 0x33, 0x66, 0xff},
70 {0xcc, 0x33, 0x33, 0xff}, {0xcc, 0x33, 0x00, 0xff},
71 {0xcc, 0x00, 0xff, 0xff}, {0xcc, 0x00, 0xcc, 0xff},
72 {0xcc, 0x00, 0x99, 0xff}, {0xcc, 0x00, 0x66, 0xff},
73 {0xcc, 0x00, 0x33, 0xff}, {0xcc, 0x00, 0x00, 0xff},
74 {0x99, 0xff, 0xff, 0xff}, {0x99, 0xff, 0xcc, 0xff},
75 {0x99, 0xff, 0x99, 0xff}, {0x99, 0xff, 0x66, 0xff},
76 {0x99, 0xff, 0x33, 0xff}, {0x99, 0xff, 0x00, 0xff},
77 {0x99, 0xcc, 0xff, 0xff}, {0x99, 0xcc, 0xcc, 0xff},
78 {0x99, 0xcc, 0x99, 0xff}, {0x99, 0xcc, 0x66, 0xff},
79 {0x99, 0xcc, 0x33, 0xff}, {0x99, 0xcc, 0x00, 0xff},
80 {0x99, 0x99, 0xff, 0xff}, {0x99, 0x99, 0xcc, 0xff},
81 {0x99, 0x99, 0x99, 0xff}, {0x99, 0x99, 0x66, 0xff},
82 {0x99, 0x99, 0x33, 0xff}, {0x99, 0x99, 0x00, 0xff},
83 {0x99, 0x66, 0xff, 0xff}, {0x99, 0x66, 0xcc, 0xff},
84 {0x99, 0x66, 0x99, 0xff}, {0x99, 0x66, 0x66, 0xff},
85 {0x99, 0x66, 0x33, 0xff}, {0x99, 0x66, 0x00, 0xff},
86 {0x99, 0x33, 0xff, 0xff}, {0x99, 0x33, 0xcc, 0xff},
87 {0x99, 0x33, 0x99, 0xff}, {0x99, 0x33, 0x66, 0xff},
88 {0x99, 0x33, 0x33, 0xff}, {0x99, 0x33, 0x00, 0xff},
89 {0x99, 0x00, 0xff, 0xff}, {0x99, 0x00, 0xcc, 0xff},
90 {0x99, 0x00, 0x99, 0xff}, {0x99, 0x00, 0x66, 0xff},
91 {0x99, 0x00, 0x33, 0xff}, {0x99, 0x00, 0x00, 0xff},
92 {0x66, 0xff, 0xff, 0xff}, {0x66, 0xff, 0xcc, 0xff},
93 {0x66, 0xff, 0x99, 0xff}, {0x66, 0xff, 0x66, 0xff},
94 {0x66, 0xff, 0x33, 0xff}, {0x66, 0xff, 0x00, 0xff},
95 {0x66, 0xcc, 0xff, 0xff}, {0x66, 0xcc, 0xcc, 0xff},
96 {0x66, 0xcc, 0x99, 0xff}, {0x66, 0xcc, 0x66, 0xff},
97 {0x66, 0xcc, 0x33, 0xff}, {0x66, 0xcc, 0x00, 0xff},
98 {0x66, 0x99, 0xff, 0xff}, {0x66, 0x99, 0xcc, 0xff},
99 {0x66, 0x99, 0x99, 0xff}, {0x66, 0x99, 0x66, 0xff},
100 {0x66, 0x99, 0x33, 0xff}, {0x66, 0x99, 0x00, 0xff},
101 {0x66, 0x66, 0xff, 0xff}, {0x66, 0x66, 0xcc, 0xff},
102 {0x66, 0x66, 0x99, 0xff}, {0x66, 0x66, 0x66, 0xff},
103 {0x66, 0x66, 0x33, 0xff}, {0x66, 0x66, 0x00, 0xff},
104 {0x66, 0x33, 0xff, 0xff}, {0x66, 0x33, 0xcc, 0xff},
105 {0x66, 0x33, 0x99, 0xff}, {0x66, 0x33, 0x66, 0xff},
106 {0x66, 0x33, 0x33, 0xff}, {0x66, 0x33, 0x00, 0xff},
107 {0x66, 0x00, 0xff, 0xff}, {0x66, 0x00, 0xcc, 0xff},
108 {0x66, 0x00, 0x99, 0xff}, {0x66, 0x00, 0x66, 0xff},
109 {0x66, 0x00, 0x33, 0xff}, {0x66, 0x00, 0x00, 0xff},
110 {0x33, 0xff, 0xff, 0xff}, {0x33, 0xff, 0xcc, 0xff},
111 {0x33, 0xff, 0x99, 0xff}, {0x33, 0xff, 0x66, 0xff},
112 {0x33, 0xff, 0x33, 0xff}, {0x33, 0xff, 0x00, 0xff},
113 {0x33, 0xcc, 0xff, 0xff}, {0x33, 0xcc, 0xcc, 0xff},
114 {0x33, 0xcc, 0x99, 0xff}, {0x33, 0xcc, 0x66, 0xff},
115 {0x33, 0xcc, 0x33, 0xff}, {0x33, 0xcc, 0x00, 0xff},
116 {0x33, 0x99, 0xff, 0xff}, {0x33, 0x99, 0xcc, 0xff},
117 {0x33, 0x99, 0x99, 0xff}, {0x33, 0x99, 0x66, 0xff},
118 {0x33, 0x99, 0x33, 0xff}, {0x33, 0x99, 0x00, 0xff},
119 {0x33, 0x66, 0xff, 0xff}, {0x33, 0x66, 0xcc, 0xff},
120 {0x33, 0x66, 0x99, 0xff}, {0x33, 0x66, 0x66, 0xff},
121 {0x33, 0x66, 0x33, 0xff}, {0x33, 0x66, 0x00, 0xff},
122 {0x33, 0x33, 0xff, 0xff}, {0x33, 0x33, 0xcc, 0xff},
123 {0x33, 0x33, 0x99, 0xff}, {0x33, 0x33, 0x66, 0xff},
124 {0x33, 0x33, 0x33, 0xff}, {0x33, 0x33, 0x00, 0xff},
125 {0x33, 0x00, 0xff, 0xff}, {0x33, 0x00, 0xcc, 0xff},
126 {0x33, 0x00, 0x99, 0xff}, {0x33, 0x00, 0x66, 0xff},
127 {0x33, 0x00, 0x33, 0xff}, {0x33, 0x00, 0x00, 0xff},
128 {0x00, 0xff, 0xff, 0xff}, {0x00, 0xff, 0xcc, 0xff},
129 {0x00, 0xff, 0x99, 0xff}, {0x00, 0xff, 0x66, 0xff},
130 {0x00, 0xff, 0x33, 0xff}, {0x00, 0xff, 0x00, 0xff},
131 {0x00, 0xcc, 0xff, 0xff}, {0x00, 0xcc, 0xcc, 0xff},
132 {0x00, 0xcc, 0x99, 0xff}, {0x00, 0xcc, 0x66, 0xff},
133 {0x00, 0xcc, 0x33, 0xff}, {0x00, 0xcc, 0x00, 0xff},
134 {0x00, 0x99, 0xff, 0xff}, {0x00, 0x99, 0xcc, 0xff},
135 {0x00, 0x99, 0x99, 0xff}, {0x00, 0x99, 0x66, 0xff},
136 {0x00, 0x99, 0x33, 0xff}, {0x00, 0x99, 0x00, 0xff},
137 {0x00, 0x66, 0xff, 0xff}, {0x00, 0x66, 0xcc, 0xff},
138 {0x00, 0x66, 0x99, 0xff}, {0x00, 0x66, 0x66, 0xff},
139 {0x00, 0x66, 0x33, 0xff}, {0x00, 0x66, 0x00, 0xff},
140 {0x00, 0x33, 0xff, 0xff}, {0x00, 0x33, 0xcc, 0xff},
141 {0x00, 0x33, 0x99, 0xff}, {0x00, 0x33, 0x66, 0xff},
142 {0x00, 0x33, 0x33, 0xff}, {0x00, 0x33, 0x00, 0xff},
143 {0x00, 0x00, 0xff, 0xff}, {0x00, 0x00, 0xcc, 0xff},
144 {0x00, 0x00, 0x99, 0xff}, {0x00, 0x00, 0x66, 0xff},
145 {0x00, 0x00, 0x33, 0xff}, {0x00, 0x00, 0x00, 0xff},
146 {0x00, 0x00, 0x00, 0xff}, {0x00, 0x00, 0x00, 0xff},
147 {0x00, 0x00, 0x00, 0xff}, {0x00, 0x00, 0x00, 0xff},
148 {0x00, 0x00, 0x00, 0xff}, {0x00, 0x00, 0x00, 0xff},
149 {0x00, 0x00, 0x00, 0xff}, {0x00, 0x00, 0x00, 0xff},
150 {0x00, 0x00, 0x00, 0xff}, {0x00, 0x00, 0x00, 0xff},
151 {0x00, 0x00, 0x00, 0xff}, {0x00, 0x00, 0x00, 0xff},
152 {0x00, 0x00, 0x00, 0xff}, {0x00, 0x00, 0x00, 0xff},
153 {0x00, 0x00, 0x00, 0xff}, {0x00, 0x00, 0x00, 0xff},
154 {0x00, 0x00, 0x00, 0xff}, {0x00, 0x00, 0x00, 0xff},
155 {0x00, 0x00, 0x00, 0xff}, {0x00, 0x00, 0x00, 0xff},
156 {0x00, 0x00, 0x00, 0xff}, {0x00, 0x00, 0x00, 0xff},
157 {0x00, 0x00, 0x00, 0xff}, {0x00, 0x00, 0x00, 0xff},
158 {0x00, 0x00, 0x00, 0xff}, {0x00, 0x00, 0x00, 0xff},
159 {0x00, 0x00, 0x00, 0xff}, {0x00, 0x00, 0x00, 0xff},
160 {0x00, 0x00, 0x00, 0xff}, {0x00, 0x00, 0x00, 0xff},
161 {0x00, 0x00, 0x00, 0xff}, {0x00, 0x00, 0x00, 0xff},
162 {0x00, 0x00, 0x00, 0xff}, {0x00, 0x00, 0x00, 0xff},
163 {0x00, 0x00, 0x00, 0xff}, {0x00, 0x00, 0x00, 0xff},
164 {0x00, 0x00, 0x00, 0xff}, {0x00, 0x00, 0x00, 0xff},
165 {0x00, 0x00, 0x00, 0xff}, {0x00, 0x00, 0x00, 0xff}
169 struct ColorItem : public HashItem {
170 ColorItem(unsigned int k, unsigned int c,
171 uint8 r, uint8 g, uint8 b)
173 count(c),
174 red(r),
175 green(g),
176 blue(b)
178 key = k;
181 unsigned int count;
182 uint8 red;
183 uint8 green;
184 uint8 blue;
188 SavePalette::SavePalette(int mode)
190 pal(new(nothrow) rgb_color[256]),
191 fSize(0),
192 fSizeInBits(8),
193 fMode(mode),
194 fTransparentMode(NO_TRANSPARENCY),
195 fTransparentIndex(-1),
196 fBackgroundIndex(0),
197 fFatalError(pal == NULL)
199 if (IsValid()) {
200 if (fMode == WEB_SAFE_PALETTE) {
201 memcpy(pal, wsp, sizeof(rgb_color) * 256);
202 fSize = 216;
203 } else if (fMode == BEOS_SYSTEM_PALETTE) {
204 color_map* map = (color_map*)system_colors();
205 memcpy(pal, map->color_list, sizeof(rgb_color) * 256);
206 fSize = 256;
207 } else if (fMode == GREYSCALE_PALETTE) {
208 for (int i = 0; i < 256; i++) {
209 pal[i].red = pal[i].green = pal[i].blue = i;
210 pal[i].alpha = 0xff;
212 fSize = 256;
218 static int
219 make_key(uint8 r, uint8 g, uint8 b, uint8 bits)
221 r = r >> (8 - bits);
222 g = g >> (8 - bits);
223 b = b >> (8 - bits);
225 return (r << (bits * 2)) | (g << bits) | b;
229 static bool
230 touch_color_item(SFHash& hash, unsigned int key, uint8 r, uint8 g, uint8 b)
232 ColorItem* ci = (ColorItem*)hash.GetItem(key);
233 if (ci == NULL) {
234 ci = new(nothrow) ColorItem(key, 1, r, g, b);
235 if (ci == NULL) {
236 if (debug)
237 printf("Out of memory in touch_color_item()\n");
238 return false;
240 hash.AddItem((HashItem*)ci);
241 } else {
242 ci->count++;
243 #if 0
244 // use brightest color
245 ci->red = max_c(ci->red, r);
246 ci->green = max_c(ci->green, g);
247 ci->blue = max_c(ci->blue, b);
248 #endif
250 return true;
254 SavePalette::SavePalette(BBitmap* bitmap, int32 maxSizeInBits)
256 pal(new(nothrow) rgb_color[256]),
257 fSize(0),
258 fSizeInBits(0),
259 fMode(OPTIMAL_PALETTE),
260 fTransparentMode(NO_TRANSPARENCY),
261 fTransparentIndex(-1),
262 fBackgroundIndex(0),
263 fFatalError(pal == NULL)
265 if (!IsValid())
266 return;
268 SFHash hash(1 << 16);
269 if (hash.fatalerror) {
270 if (debug)
271 printf("Out of memory in SavePalette(BBitmap*)\n");
272 fFatalError = true;
273 return;
276 // reject unsupported color spaces
277 // TODO: B_CMAP8 and B_GRAY8 should be really easy to support as well!!
278 color_space cs = bitmap->ColorSpace();
279 if (cs != B_RGB32 && cs != B_RGBA32 && cs != B_RGB32_BIG
280 && cs != B_RGBA32_BIG) {
281 if (debug) {
282 printf("Wrong color space given in SavePalette(BBitmap):\n");
283 printf("%d %d %d %d or 0x%x\n",
284 (cs & 0xff000000) >> 24, (cs & 0xff0000) >> 16,
285 (cs & 0xff00) >> 8, cs & 0xff, cs);
287 fFatalError = true;
288 return;
291 BRect rect = bitmap->Bounds();
292 uint32 height = rect.IntegerHeight() + 1;
293 uint32 width = rect.IntegerWidth() + 1;
294 uint8* bits = (uint8*)bitmap->Bits();
295 uint32 bpr = bitmap->BytesPerRow();
297 uint8 r;
298 uint8 g;
299 uint8 b;
300 uint8 useBits = 3 + maxSizeInBits / 2;
301 if (cs == B_RGB32 || cs == B_RGBA32) {
302 for (uint32 y = 0; y < height; y++) {
303 uint8* handle = bits;
304 for (uint32 x = 0; x < width; x++) {
305 b = handle[0];
306 g = handle[1];
307 r = handle[2];
308 handle += 4;
310 uint32 key = make_key(r, g, b, useBits);
311 if (!touch_color_item(hash, key, r, g, b)) {
312 if (debug)
313 printf("Out of memory in SavePalette(BBitmap*)\n");
315 fFatalError = true;
316 return;
319 bits += bpr;
321 } else if ((cs == B_RGB32_BIG || cs == B_RGBA32_BIG)) {
322 for (uint32 y = 0; y < height; y++) {
323 uint8* handle = bits;
324 for (uint32 x = 0; x < width; x++) {
325 b = handle[2];
326 g = handle[1];
327 r = handle[0];
328 handle += 4;
330 uint32 key = make_key(r, g, b, useBits);
331 if (!touch_color_item(hash, key, r, g, b)) {
332 if (debug)
333 printf("Out of memory in SavePalette(BBitmap*)\n");
334 fFatalError = true;
335 return;
338 bits += bpr;
342 int unique_colors = hash.CountItems();
343 while (((1 << fSizeInBits) < unique_colors)
344 && (fSizeInBits < maxSizeInBits)) {
345 fSizeInBits++;
347 fSize = 1 << fSizeInBits;
349 ColorItem** topcolors = (ColorItem**)malloc(fSize * sizeof(ColorItem*));
350 if (topcolors == NULL) {
351 if (debug) printf("Out of memory in SavePalette(BBitmap*)\n");
352 fFatalError = true;
353 return;
355 ColorItem* dummy = new ColorItem(0, 0, 0, 0, 0);
356 for (int i = 0; i < fSize; i++)
357 topcolors[i] = dummy;
359 for (int i = 0; i < unique_colors; i++) {
360 ColorItem* ci = (ColorItem*)hash.NextItem();
361 for (int j = 0; j < fSize; j++) {
362 if (ci->count > topcolors[j]->count) {
363 for (int k = fSize - 1; k > j; k--) {
364 topcolors[k] = topcolors[k - 1];
366 topcolors[j] = ci;
367 break;
372 for (int i = 0; i < fSize; i++) {
373 pal[i].red = topcolors[i]->red;
374 pal[i].green = topcolors[i]->green;
375 pal[i].blue = topcolors[i]->blue;
376 pal[i].alpha = 0xff;
379 delete dummy;
380 free(topcolors);
384 SavePalette::~SavePalette()
386 delete[] pal;
390 uint8
391 SavePalette::IndexForColor(uint8 red, uint8 green, uint8 blue, uint8 alpha)
393 // standard mapping services once a palette is loaded
394 if (fTransparentMode > NO_TRANSPARENCY && alpha < 128)
395 return fTransparentIndex;
397 uint8 index = 0;
399 if (fMode == GREYSCALE_PALETTE) {
400 index = (308 * red + 600 * green + 116 * blue) / 1024;
401 // avoid transparent index
402 if (fTransparentMode == AUTO_TRANSPARENCY && index == 1
403 && fTransparentIndex == 1) {
404 index = 0;
406 } else {
407 int closestDistance = 255 * 255 * 3;
409 if (fTransparentMode == AUTO_TRANSPARENCY) {
410 for (int i = 0; i < fTransparentIndex && closestDistance != 0;
411 i++) {
412 int rd = (int)red - (int)pal[i].red;
413 int gd = (int)green - (int)pal[i].green;
414 int bd = (int)blue - (int)pal[i].blue;
415 int distanceAtIndex = rd * rd + gd * gd + bd * bd;
416 if (distanceAtIndex < closestDistance) {
417 closestDistance = distanceAtIndex;
418 index = i;
421 for (int i = fTransparentIndex + 1;
422 i < fSize && closestDistance != 0; i++) {
423 int rd = (int)red - (int)pal[i].red;
424 int gd = (int)green - (int)pal[i].green;
425 int bd = (int)blue - (int)pal[i].blue;
426 int distanceAtIndex = rd * rd + gd * gd + bd * bd;
427 if (distanceAtIndex < closestDistance) {
428 closestDistance = distanceAtIndex;
429 index = i;
432 } else {
433 for (int i = 0; i < fSize && closestDistance != 0; i++) {
434 int rd = (int)red - (int)pal[i].red;
435 int gd = (int)green - (int)pal[i].green;
436 int bd = (int)blue - (int)pal[i].blue;
437 int distanceAtIndex = rd * rd + gd * gd + bd * bd;
438 if (distanceAtIndex < closestDistance) {
439 closestDistance = distanceAtIndex;
440 index = i;
446 return index;
450 void
451 SavePalette::PrepareForAutoTransparency()
453 fTransparentMode = AUTO_TRANSPARENCY;
454 // TODO: in the SavePalette::SavePalette(BBitmap*),
455 // we don't use more colors than necessary, however,
456 // here we take a slot away for transparency, even if
457 // we might still have used less colors than the user
458 // wanted as a maximum
459 // NOTE: the last index
460 switch (fMode) {
461 case WEB_SAFE_PALETTE:
462 fTransparentIndex = 216;
463 fSize = 217;
464 break;
465 case BEOS_SYSTEM_PALETTE:
466 fTransparentIndex = 0;
467 break;
468 case GREYSCALE_PALETTE:
469 fTransparentIndex = 1;
470 break;
471 case OPTIMAL_PALETTE:
472 fTransparentIndex = fSize - 1;
473 break;
478 void
479 SavePalette::SetTransparentColor(uint8 red, uint8 green, uint8 blue)
481 fTransparentMode = COLOR_KEY_TRANSPARENCY;
483 bool found = false;
484 // try direct hit first
485 for (int i = 0; i < fSize; i++) {
486 if (pal[i].red == red &&
487 pal[i].green == green &&
488 pal[i].blue == blue) {
490 fTransparentIndex = i;
491 found = true;
493 break;
496 if (!found) {
497 // find closest match
498 fTransparentIndex = IndexForColor(red, green, blue);
499 // NOTE: This is a tough decision:
500 // -> the exact color might be contained within the image
501 // but have slipped through the net and is now not in the
502 // palette, the user still wants those pixels to be
503 // transparent of course, so it is best to match up a
504 // color from the palette
505 // -> on the other hand, the setting might still be there
506 // from some previous image and the color might not
507 // even appear in the current image at all... but I guess
508 // handling it like below is the lesser evil.
509 // match up color at index to provided transparent color,
510 // to make sure it actually works
511 pal[fTransparentIndex].red = red;
512 pal[fTransparentIndex].green = green;
513 pal[fTransparentIndex].blue = blue;
514 found = true;
519 void
520 SavePalette::GetColors(uint8* buffer, int size) const
522 int maxIndex = max_c(size / 3, fSize) - 1;
523 for (int i = 0; i <= maxIndex; i++) {
524 *buffer++ = pal[i].red;
525 *buffer++ = pal[i].green;
526 *buffer++ = pal[i].blue;
528 int rest = (maxIndex + 1) * 3;
529 if (rest < size)
530 memset(buffer, 0, size - rest);