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