1 #   include	"bitmapConfig.h"
2 
3 #   include	"bmintern.h"
4 #   include	<stdlib.h>
5 #   include	<string.h>
6 #   include	<appDebugon.h>
7 
8 /************************************************************************/
9 /*									*/
10 /*  Expand a palette from one buffer to another one. Do it in such a	*/
11 /*  way ( reverse order ) that it works with from == to.		*/
12 /*									*/
13 /************************************************************************/
14 
15 #   define	setBytes(t,p,f)	\
16     { *(t--)= p[f].rgb8Blue; *(t--)= p[f].rgb8Green; *(t--)= p[f].rgb8Red; }
17 #   define	setAlpha(t,p,f)	\
18     { *(t--)= (f)?0xff:0x00; }
19 
bmExpandRGB8Palette(unsigned char * to,const unsigned char * from,int pixelsWide,int bitsPerPixel,const ColorPalette * cp,int hasAlpha)20 int bmExpandRGB8Palette(	unsigned char *		to,
21 				const unsigned char *	from,
22 				int			pixelsWide,
23 				int			bitsPerPixel,
24 				const ColorPalette *	cp,
25 				int			hasAlpha )
26     {
27     unsigned char	f1, f2;
28 
29     if  ( hasAlpha )
30 	{ to += 4* pixelsWide- 1;	}
31     else{ to += 3* pixelsWide- 1;	}
32 
33     from += ( bitsPerPixel* pixelsWide - 1 )/8;
34 
35     switch( bitsPerPixel )
36 	{
37 	case	16:
38 	    if  ( ! hasAlpha )
39 		{ LLDEB(bitsPerPixel,hasAlpha); return -1; }
40 
41 	    while( pixelsWide > 0 )
42 		{
43 		*(to--)= *(from--);
44 		f1= *(from--);
45 		setBytes(to,cp->cpColors,f1);
46 		pixelsWide--;
47 		}
48 	    break;
49 
50 	case	8:
51 	    if  ( hasAlpha )
52 		{
53 		while( pixelsWide > 0 )
54 		    {
55 		    f1= *(from--);
56 		    *(to--)= ( ( f1 & 0x0f ) << 4 ) | ( f1 & 0x0f );
57 		    f2= ( f1 >> 4 ) & 0x0f;	setBytes(to,cp->cpColors,f2);
58 		    pixelsWide--;
59 		    }
60 		}
61 	    else{
62 		while( pixelsWide > 0 )
63 		    {
64 		    f1= *(from--);
65 		    setBytes(to,cp->cpColors,f1);
66 		    pixelsWide--;
67 		    }
68 		}
69 	    break;
70 
71 	case	4:
72 	    if  ( hasAlpha )
73 		{ LDEB(hasAlpha); return -1;	}
74 	    while( pixelsWide > 0 )
75 		{
76 		f1= *(from--);
77 		f2=   f1        & 0x0f;	setBytes(to,cp->cpColors,f2);
78 		if  ( pixelsWide == 1 )
79 		    { break;	}
80 		f2= ( f1 >> 4 ) & 0x0f;	setBytes(to,cp->cpColors,f2);
81 		pixelsWide -= 2;
82 		}
83 	    break;
84 
85 	case	2:
86 	    if  ( hasAlpha )
87 		{
88 		while( pixelsWide > 0 )
89 		    {
90 		    f1= *(from--);
91 		    f2=   f1        & 0x01;	setAlpha(to,cp->cpColors,f2);
92 		    f2= ( f1 >> 1 ) & 0x01;	setBytes(to,cp->cpColors,f2);
93 		    f2= ( f1 >> 2 ) & 0x01;	setAlpha(to,cp->cpColors,f2);
94 		    f2= ( f1 >> 3 ) & 0x01;	setBytes(to,cp->cpColors,f2);
95 		    f2= ( f1 >> 4 ) & 0x01;	setAlpha(to,cp->cpColors,f2);
96 		    f2= ( f1 >> 5 ) & 0x01;	setBytes(to,cp->cpColors,f2);
97 		    f2= ( f1 >> 6 ) & 0x01;	setAlpha(to,cp->cpColors,f2);
98 		    f2= ( f1 >> 7 ) & 0x01;	setBytes(to,cp->cpColors,f2);
99 		    pixelsWide -= 4;
100 		    }
101 		}
102 	    else{
103 		while( pixelsWide > 0 )
104 		    {
105 		    f1= *(from--);
106 		    f2=   f1        & 0x03;	setBytes(to,cp->cpColors,f2);
107 		    f2= ( f1 >> 2 ) & 0x03;	setBytes(to,cp->cpColors,f2);
108 		    f2= ( f1 >> 4 ) & 0x03;	setBytes(to,cp->cpColors,f2);
109 		    f2= ( f1 >> 6 ) & 0x03;	setBytes(to,cp->cpColors,f2);
110 		    pixelsWide -= 4;
111 		    }
112 		}
113 	    break;
114 
115 	case	1:
116 	    while( pixelsWide > 0 )
117 		{
118 		f1= *(from--);
119 		f2=   f1        & 0x01;	setBytes(to,cp->cpColors,f2);
120 		f2= ( f1 >> 1 ) & 0x01;	setBytes(to,cp->cpColors,f2);
121 		f2= ( f1 >> 2 ) & 0x01;	setBytes(to,cp->cpColors,f2);
122 		f2= ( f1 >> 3 ) & 0x01;	setBytes(to,cp->cpColors,f2);
123 		f2= ( f1 >> 4 ) & 0x01;	setBytes(to,cp->cpColors,f2);
124 		f2= ( f1 >> 5 ) & 0x01;	setBytes(to,cp->cpColors,f2);
125 		f2= ( f1 >> 6 ) & 0x01;	setBytes(to,cp->cpColors,f2);
126 		f2= ( f1 >> 7 ) & 0x01;	setBytes(to,cp->cpColors,f2);
127 		pixelsWide -= 8;
128 		}
129 	    break;
130 
131 	default:
132 	    LDEB(bitsPerPixel); return -1;
133 	}
134 
135     return 0;
136     }
137 
bmExpandPaletteImage(RasterImage * riOut,const RasterImage * riIn,int ignoredInt)138 int bmExpandPaletteImage(	RasterImage *			riOut,
139 				const RasterImage *		riIn,
140 				int				ignoredInt )
141     {
142     const BitmapDescription *	bdIn= &(riIn->riDescription);
143     int				rval= 0;
144     int				row;
145     const unsigned char *	from;
146     unsigned char *		to;
147 
148     RasterImage			ri;
149 
150     bmInitRasterImage( &ri );
151 
152     switch( bdIn->bdColorEncoding )
153 	{
154 	case BMcoBLACKWHITE:
155 	case BMcoWHITEBLACK:
156 	case BMcoRGB:
157 	    LDEB(bdIn->bdColorEncoding);
158 	    rval= -1; goto ready;
159 
160 	case BMcoRGB8PALETTE:
161 	    break;
162 	}
163 
164     /************************************************************/
165     /*  Derive properties of output bitmap from input.		*/
166     /************************************************************/
167     if  ( bmCopyDescription( &(ri.riDescription), bdIn ) )
168 	{ LDEB(1); rval= -1; goto ready;	}
169 
170     ri.riDescription.bdColorEncoding= BMcoRGB;
171     ri.riDescription.bdBitsPerSample= 8;
172     /*  Done by copy..
173     ri.riDescription.bdHasAlpha= bdIn->bdHasAlpha;
174     */
175 
176     if  ( bmCalculateSizes( &(ri.riDescription) ) )
177 	{ LDEB(1); rval= -1; goto ready;	}
178 
179     /************************************************************/
180     /*  Allocate new buffer.					*/
181     /************************************************************/
182     if  ( bmAllocateBuffer( &ri ) )
183 	{
184 	LXDEB(ri.riDescription.bdBufferLength,ri.riBytes);
185 	rval= -1; goto ready;
186 	}
187 
188     from= riIn->riBytes; to= ri.riBytes;
189     for ( row= 0; row < bdIn->bdPixelsHigh; row++ )
190 	{
191 	if  ( bmExpandRGB8Palette( to, from,
192 				    bdIn->bdPixelsWide, bdIn->bdBitsPerPixel,
193 				    &(bdIn->bdPalette), bdIn->bdHasAlpha ) )
194 	    { LDEB(1); rval= -1; goto ready;	}
195 
196 	from += bdIn->bdBytesPerRow;
197 	to += ri.riDescription.bdBytesPerRow;
198 	}
199 
200     /* steal */
201     *riOut= ri; bmInitRasterImage( &ri );
202 
203   ready:
204 
205     bmCleanRasterImage( &ri );
206 
207     return rval;
208     }
209 
210 /************************************************************************/
211 /*									*/
212 /*  Make a palette for a grayscale raster image.			*/
213 /*									*/
214 /************************************************************************/
215 
bmMakeGrayPalette(const BitmapDescription * bd,int * pColorCount,int * pTransparentColor,RGB8Color * palette,int maxColors)216 int bmMakeGrayPalette(	const BitmapDescription *	bd,
217 			int *				pColorCount,
218 			int *				pTransparentColor,
219 			RGB8Color *			palette,
220 			int				maxColors )
221     {
222     int		i;
223     int		colorCount;
224     int		transparentColor= -1;
225 
226     switch( bd->bdColorEncoding )
227 	{
228 	case BMcoRGB8PALETTE:
229 	    LDEB(bd->bdColorEncoding); return -1;
230 
231 	case BMcoBLACKWHITE:
232 	    switch( bd->bdBitsPerSample )
233 		{
234 		case 1: case 2: case 4: case 8:
235 		    colorCount= 1 << bd->bdBitsPerSample;
236 
237 		    if  ( colorCount+ bd->bdHasAlpha > maxColors )
238 			{
239 			LLLDEB(colorCount,bd->bdHasAlpha,maxColors);
240 			return -1;
241 			}
242 
243 		    for ( i= 0; i < colorCount; i++ )
244 			{
245 			int n= colorCount- i- 1;
246 			int v= ( i* 255 )/ ( colorCount- 1 );
247 
248 			palette[n].rgb8Red= v;
249 			palette[n].rgb8Green= v;
250 			palette[n].rgb8Blue= v;
251 			palette[n].rgb8Alpha= 255;
252 			}
253 
254 		    break;
255 
256 		default:
257 		    LLDEB(bd->bdColorEncoding,bd->bdBitsPerSample);
258 		    return -1;
259 		}
260 	    break;
261 
262 	case BMcoWHITEBLACK:
263 	    switch( bd->bdBitsPerSample )
264 		{
265 		case 1: case 2: case 4: case 8:
266 		    colorCount= 1 << bd->bdBitsPerSample;
267 
268 		    if  ( colorCount+ bd->bdHasAlpha > maxColors )
269 			{
270 			LLLDEB(colorCount,bd->bdHasAlpha,maxColors);
271 			return -1;
272 			}
273 
274 		    for ( i= 0; i < colorCount; i++ )
275 			{
276 			int v= ( i* 255 )/ ( colorCount- 1 );
277 
278 			palette[i].rgb8Red= v;
279 			palette[i].rgb8Green= v;
280 			palette[i].rgb8Blue= v;
281 			palette[colorCount- i- 1].rgb8Alpha= 255;
282 			}
283 
284 		    break;
285 
286 		default:
287 		    LLDEB(bd->bdColorEncoding,bd->bdBitsPerSample);
288 		    return -1;
289 		}
290 	    break;
291 
292 	case BMcoRGB:
293 	default:
294 	    LDEB(bd->bdColorEncoding); return -1;
295 	}
296 
297     if  ( bd->bdHasAlpha )
298 	{
299 	if  ( colorCount >= maxColors )
300 	    { LLDEB(colorCount,maxColors); return -1;	}
301 
302 	palette[colorCount].rgb8Red= 255;
303 	palette[colorCount].rgb8Green= 255;
304 	palette[colorCount].rgb8Blue= 255;
305 	palette[colorCount].rgb8Alpha= 0;
306 
307 	transparentColor= colorCount++;
308 	}
309 
310     if  ( pColorCount )
311 	{ *pColorCount= colorCount;	}
312     if  ( pTransparentColor )
313 	{ *pTransparentColor= transparentColor;	}
314 
315     return 0;
316     }
317 
318 /************************************************************************/
319 /*									*/
320 /*  Inflate a scan line to 8 bits per pixel.				*/
321 /*									*/
322 /************************************************************************/
323 
bmInflateTo8bit(unsigned char * to,const unsigned char * from,const BitmapDescription * bd,const int transpColor,int removeAlpha)324 int bmInflateTo8bit(		unsigned char *			to,
325 				const unsigned char *		from,
326 				const BitmapDescription *	bd,
327 				const int			transpColor,
328 				int				removeAlpha )
329     {
330     int			col;
331     unsigned char	b;
332 
333     switch( bd->bdBitsPerPixel )
334 	{
335 	case 1:
336 	    if  ( bd->bdHasAlpha && removeAlpha )
337 		{ LLDEB(bd->bdBitsPerPixel,bd->bdHasAlpha); return -1;	}
338 	    else{
339 		for ( col= 0; col < bd->bdPixelsWide; col += 8 )
340 		    {
341 		    b= *(from++);
342 
343 		    *(to++)= ( b & 0x80 ) >> 7;
344 		    *(to++)= ( b & 0x40 ) >> 6;
345 		    *(to++)= ( b & 0x20 ) >> 5;
346 		    *(to++)= ( b & 0x10 ) >> 4;
347 		    *(to++)= ( b & 0x08 ) >> 3;
348 		    *(to++)= ( b & 0x04 ) >> 2;
349 		    *(to++)= ( b & 0x02 ) >> 1;
350 		    *(to++)= ( b & 0x01 )     ;
351 		    }
352 		}
353 
354 	    return 0;
355 
356 	case 2:
357 	    if  ( bd->bdHasAlpha && removeAlpha )
358 		{
359 		for ( col= 0; col < bd->bdPixelsWide; col += 4 )
360 		    {
361 		    b= *(from++);
362 
363 		    if  ( ( b & 0x40 ) )
364 			{ *(to++)= ( b & 0x80 ) >> 7;	}
365 		    else{ *(to++)= transpColor;	}
366 
367 		    if  ( ( b & 0x10 ) )
368 			{ *(to++)= ( b & 0x20 ) >> 5;	}
369 		    else{ *(to++)= transpColor;	}
370 
371 		    if  ( ( b & 0x04 ) )
372 			{ *(to++)= ( b & 0x08 ) >> 3;	}
373 		    else{ *(to++)= transpColor;	}
374 
375 		    if  ( ( b & 0x01 ) )
376 			{ *(to++)= ( b & 0x02 ) >> 1;	}
377 		    else{ *(to++)= transpColor;	}
378 		    }
379 		}
380 	    else{
381 		for ( col= 0; col < bd->bdPixelsWide; col += 4 )
382 		    {
383 		    b= *(from++);
384 
385 		    *(to++)= ( b & 0xc0 ) >> 6;
386 		    *(to++)= ( b & 0x30 ) >> 4;
387 		    *(to++)= ( b & 0x0c ) >> 2;
388 		    *(to++)= ( b & 0x03 )     ;
389 		    }
390 		}
391 
392 	    return 0;
393 
394 	case 4:
395 	    if  ( bd->bdHasAlpha && removeAlpha )
396 		{
397 		for ( col= 0; col < bd->bdPixelsWide; col += 2 )
398 		    {
399 		    b= *(from++);
400 
401 		    if  ( ( b & 0x30 ) )
402 			{ *(to++)= ( b & 0xc0 ) >> 6;	}
403 		    else{ *(to++)= transpColor;	}
404 
405 		    if  ( ( b & 0x03 ) )
406 			{ *(to++)= ( b & 0x0c ) >> 2;	}
407 		    else{ *(to++)= transpColor;	}
408 		    }
409 		}
410 	    else{
411 		for ( col= 0; col < bd->bdPixelsWide; col += 2 )
412 		    {
413 		    b= *(from++);
414 
415 		    *(to++)= ( b & 0xf0 ) >> 4;
416 		    *(to++)= ( b & 0x0f )     ;
417 		    }
418 		}
419 
420 	    return 0;
421 
422 	case 8:
423 	    if  ( bd->bdHasAlpha && removeAlpha )
424 		{
425 		b= *(from++);
426 
427 		for ( col= 0; col < bd->bdPixelsWide; col += 1 )
428 		    {
429 		    if  ( ( b & 0x0f ) )
430 			{ *(to++)= ( b & 0xf0 ) >> 4;	}
431 		    else{ *(to++)= transpColor;	}
432 		    }
433 		}
434 	    else{ memcpy( to, from, bd->bdBytesPerRow );	}
435 
436 	    return 0;
437 
438 	case 16:
439 	    if  ( ! removeAlpha )
440 		{ LDEB(removeAlpha); return -1;	}
441 
442 	    for ( col= 0; col < bd->bdPixelsWide; col += 1 )
443 		{
444 		b= *(from++);
445 
446 		if  ( *from == 0 )
447 		    { b= transpColor;	}
448 
449 		*(to++)= b; from++;
450 		}
451 
452 	    return 0;
453 
454 	default:
455 	    LDEB(bd->bdBitsPerPixel); return -1;
456 	}
457     }
458 
459 /************************************************************************/
460 /*									*/
461 /*  Inflate a scan line to 16 bits per pixel.				*/
462 /*									*/
463 /************************************************************************/
464 
bmInflateToInt(unsigned int * to,const unsigned char * from,const BitmapDescription * bd,const int transpColor,int removeAlpha)465 int bmInflateToInt(		unsigned int *			to,
466 				const unsigned char *		from,
467 				const BitmapDescription *	bd,
468 				const int			transpColor,
469 				int				removeAlpha )
470     {
471     int		col;
472     int		b;
473 
474     switch( bd->bdBitsPerPixel )
475 	{
476 	case 1:
477 	    if  ( bd->bdHasAlpha && removeAlpha )
478 		{ LLDEB(bd->bdBitsPerPixel,bd->bdHasAlpha); return -1;	}
479 	    else{
480 		for ( col= 0; col < bd->bdPixelsWide; col += 8 )
481 		    {
482 		    b= *(from++);
483 
484 		    *(to++)= ( b & 0x80 ) >> 7;
485 		    *(to++)= ( b & 0x40 ) >> 6;
486 		    *(to++)= ( b & 0x20 ) >> 5;
487 		    *(to++)= ( b & 0x10 ) >> 4;
488 		    *(to++)= ( b & 0x08 ) >> 3;
489 		    *(to++)= ( b & 0x04 ) >> 2;
490 		    *(to++)= ( b & 0x02 ) >> 1;
491 		    *(to++)= ( b & 0x01 )     ;
492 		    }
493 		}
494 
495 	    return 0;
496 
497 	case 2:
498 	    if  ( bd->bdHasAlpha && removeAlpha )
499 		{
500 		for ( col= 0; col < bd->bdPixelsWide; col += 4 )
501 		    {
502 		    b= *(from++);
503 
504 		    if  ( ( b & 0x40 ) )
505 			{ *(to++)= ( b & 0x80 ) >> 7;	}
506 		    else{ *(to++)= transpColor;	}
507 
508 		    if  ( ( b & 0x10 ) )
509 			{ *(to++)= ( b & 0x20 ) >> 5;	}
510 		    else{ *(to++)= transpColor;	}
511 
512 		    if  ( ( b & 0x04 ) )
513 			{ *(to++)= ( b & 0x08 ) >> 3;	}
514 		    else{ *(to++)= transpColor;	}
515 
516 		    if  ( ( b & 0x01 ) )
517 			{ *(to++)= ( b & 0x02 ) >> 1;	}
518 		    else{ *(to++)= transpColor;	}
519 		    }
520 		}
521 	    else{
522 		for ( col= 0; col < bd->bdPixelsWide; col += 4 )
523 		    {
524 		    b= *(from++);
525 
526 		    *(to++)= ( b & 0xc0 ) >> 6;
527 		    *(to++)= ( b & 0x30 ) >> 4;
528 		    *(to++)= ( b & 0x0c ) >> 2;
529 		    *(to++)= ( b & 0x03 )     ;
530 		    }
531 		}
532 
533 	    return 0;
534 
535 	case 4:
536 	    if  ( bd->bdHasAlpha && removeAlpha )
537 		{
538 		for ( col= 0; col < bd->bdPixelsWide; col += 2 )
539 		    {
540 		    b= *(from++);
541 
542 		    if  ( ( b & 0x30 ) )
543 			{ *(to++)= ( b & 0xc0 ) >> 6;	}
544 		    else{ *(to++)= transpColor;	}
545 
546 		    if  ( ( b & 0x03 ) )
547 			{ *(to++)= ( b & 0x0c ) >> 2;	}
548 		    else{ *(to++)= transpColor;	}
549 		    }
550 		}
551 	    else{
552 		for ( col= 0; col < bd->bdPixelsWide; col += 2 )
553 		    {
554 		    b= *(from++);
555 
556 		    *(to++)= ( b & 0xf0 ) >> 4;
557 		    *(to++)= ( b & 0x0f )     ;
558 		    }
559 		}
560 
561 	    return 0;
562 
563 	case 8:
564 	    if  ( bd->bdHasAlpha && removeAlpha )
565 		{
566 		b= *(from++);
567 
568 		for ( col= 0; col < bd->bdPixelsWide; col += 1 )
569 		    {
570 		    if  ( ( b & 0x0f ) )
571 			{ *(to++)= ( b & 0xf0 ) >> 4;	}
572 		    else{ *(to++)= transpColor;	}
573 		    }
574 		}
575 	    else{ memcpy( to, from, bd->bdBytesPerRow );	}
576 
577 	    return 0;
578 
579 	case 16:
580 	    if  ( ! removeAlpha )
581 		{ LDEB(removeAlpha); return -1;	}
582 
583 	    for ( col= 0; col < bd->bdPixelsWide; col += 1 )
584 		{
585 		b= *(from++);
586 
587 		if  ( *from == 0 )
588 		    { b= transpColor;	}
589 
590 		*(to++)= b; from++;
591 		}
592 
593 	    return 0;
594 
595 	default:
596 	    LDEB(bd->bdBitsPerPixel); return -1;
597 	}
598     }
599 
bmInflateTo8bitGray(unsigned char * to,const unsigned char * from,int bitsPerPixel,int pixelsWide)600 int bmInflateTo8bitGray(	unsigned char *			to,
601 				const unsigned char *		from,
602 				int				bitsPerPixel,
603 				int				pixelsWide )
604     {
605     int			col;
606     unsigned char	b;
607 
608     switch( bitsPerPixel )
609 	{
610 	case 1:
611 	    for ( col= 0; col < pixelsWide; col += 8 )
612 		{
613 		b= *(from++);
614 
615 		*(to++)= ( 255* ( ( b & 0x80 ) >> 7 ) );
616 		*(to++)= ( 255* ( ( b & 0x40 ) >> 6 ) );
617 		*(to++)= ( 255* ( ( b & 0x20 ) >> 5 ) );
618 		*(to++)= ( 255* ( ( b & 0x10 ) >> 4 ) );
619 		*(to++)= ( 255* ( ( b & 0x08 ) >> 3 ) );
620 		*(to++)= ( 255* ( ( b & 0x04 ) >> 2 ) );
621 		*(to++)= ( 255* ( ( b & 0x02 ) >> 1 ) );
622 		*(to++)= ( 255* ( ( b & 0x01 )      ) );
623 		}
624 	    return 0;
625 
626 	case 2:
627 	    for ( col= 0; col < pixelsWide; col += 4 )
628 		{
629 		b= *(from++);
630 
631 		*(to++)= ( 255* ( ( b & 0xc0 ) >> 6 ) )/ 3;
632 		*(to++)= ( 255* ( ( b & 0x30 ) >> 4 ) )/ 3;
633 		*(to++)= ( 255* ( ( b & 0x0c ) >> 2 ) )/ 3;
634 		*(to++)= ( 255* ( ( b & 0x03 )      ) )/ 3;
635 		}
636 	    return 0;
637 
638 	case 4:
639 	    for ( col= 0; col < pixelsWide; col += 2 )
640 		{
641 		b= *(from++);
642 
643 		*(to++)= ( 255* ( ( b & 0xf0 ) >> 4 ) )/ 15;
644 		*(to++)= ( 255* ( ( b & 0x0f )      ) )/ 15;
645 		}
646 	    return 0;
647 
648 	default:
649 	    LDEB(bitsPerPixel); return -1;
650 	}
651     }
652 
653 /************************************************************************/
654 /*									*/
655 /*  Find/Allocate a color in the palette of a palette image. Only do so	*/
656 /*  if there is space in the palette.					*/
657 /*									*/
658 /************************************************************************/
659 
bmPaletteColor(BitmapDescription * bd,int r,int g,int b,int a)660 int bmPaletteColor(	BitmapDescription *		bd,
661 			int				r,
662 			int				g,
663 			int				b,
664 			int				a )
665     {
666     return utilPaletteColorIndex( &(bd->bdPalette), 1<<bd->bdBitsPerPixel,
667 								r, g, b, a );
668     }
669