3 Copyright 1999, Be Incorporated. All Rights Reserved.
4 This file may be used under the terms of the Be Sample Code License.
8 #include <GraphicsDefs.h>
9 #include <InterfaceDefs.h>
16 #include "colorspace.h"
19 #if !defined(_PR3_COMPATIBLE_)
20 #define B_CMY24 ((color_space)0xC001) /* C[7:0] M[7:0] Y[7:0] No gray removal done */
21 #define B_CMY32 ((color_space)0xC002) /* C[7:0] M[7:0] Y[7:0] X[7:0] No gray removal done */
22 #define B_CMYA32 ((color_space)0xE002) /* C[7:0] M[7:0] Y[7:0] A[7:0] No gray removal done */
23 #define B_CMYK32 ((color_space)0xC003) /* C[7:0] M[7:0] Y[7:0] K[7:0] */
27 expand_data( /* expands to BGRA in the output buffer from <whatever> in the input buffer */
28 color_space from_space
,
29 unsigned char * in_data
,
31 unsigned char * out_buf
)
33 ASSERT(in_data
!= out_buf
);
35 /* We don't do YUV and friends yet. */
36 /* It's important to replicate the most significant component bits to LSB when going 15->24 */
37 unsigned char * in_out
= out_buf
;
40 while (rowbytes
> 3) {
41 out_buf
[0] = in_data
[0];
42 out_buf
[1] = in_data
[1];
43 out_buf
[2] = in_data
[2];
51 memcpy(out_buf
, in_data
, rowbytes
);
54 while (rowbytes
> 2) {
55 out_buf
[0] = in_data
[0];
56 out_buf
[1] = in_data
[1];
57 out_buf
[2] = in_data
[2];
65 while (rowbytes
> 1) {
66 uint16 val
= in_data
[0]+(in_data
[1]<<8);
67 out_buf
[0] = ((val
&0x1f)<<3)|((val
&0x1f)>>2);
68 out_buf
[1] = ((val
&0x3e0)>>2)|((val
&0x3e0)>>7);
69 out_buf
[2] = ((val
&0x7c00)>>7)|((val
&0x7c00)>>12);
77 while (rowbytes
> 1) {
78 uint16 val
= in_data
[0]+(in_data
[1]<<8);
79 out_buf
[0] = ((val
&0x1f)<<3)|((val
&0x1f)>>2);
80 out_buf
[1] = ((val
&0x3e0)>>2)|((val
&0x3e0)>>7);
81 out_buf
[2] = ((val
&0x7c00)>>7)|((val
&0x7c00)>>12);
82 out_buf
[3] = (val
&0x8000) ? 255 : 0;
89 while (rowbytes
> 1) {
90 uint16 val
= in_data
[0]+(in_data
[1]<<8);
91 out_buf
[0] = ((val
&0x1f)<<3)|((val
&0x1f)>>2);
92 out_buf
[1] = ((val
&0x7e0)>>3)|((val
&0x7e0)>>9);
93 out_buf
[2] = ((val
&0xf800)>>8)|((val
&0xf800)>>13);
101 while (rowbytes
> 3) {
102 out_buf
[0] = in_data
[3];
103 out_buf
[1] = in_data
[2];
104 out_buf
[2] = in_data
[1];
112 while (rowbytes
> 3) {
113 out_buf
[0] = in_data
[3];
114 out_buf
[1] = in_data
[2];
115 out_buf
[2] = in_data
[1];
116 out_buf
[3] = in_data
[0];
123 while (rowbytes
> 2) {
124 out_buf
[0] = in_data
[2];
125 out_buf
[1] = in_data
[1];
126 out_buf
[2] = in_data
[0];
134 while (rowbytes
> 1) {
135 uint16 val
= in_data
[1]+(in_data
[0]<<8);
136 out_buf
[0] = ((val
&0x1f)<<3)|((val
&0x1f)>>2);
137 out_buf
[1] = ((val
&0x3e0)>>2)|((val
&0x3e0)>>7);
138 out_buf
[2] = ((val
&0x7c00)>>7)|((val
&0x7c00)>>12);
146 while (rowbytes
> 1) {
147 uint16 val
= in_data
[1]+(in_data
[0]<<8);
148 out_buf
[0] = ((val
&0x1f)<<3)|((val
&0x1f)>>2);
149 out_buf
[1] = ((val
&0x3e0)>>2)|((val
&0x3e0)>>7);
150 out_buf
[2] = ((val
&0x7c00)>>7)|((val
&0x7c00)>>12);
151 out_buf
[3] = (val
&0x8000) ? 255 : 0;
158 while (rowbytes
> 1) {
159 uint16 val
= in_data
[1]+(in_data
[0]<<8);
160 out_buf
[0] = ((val
&0x1f)<<3)|((val
&0x1f)>>2);
161 out_buf
[1] = ((val
&0x7e0)>>3)|((val
&0x7e0)>>9);
162 out_buf
[2] = ((val
&0xf800)>>8)|((val
&0xf800)>>13);
170 const color_map
* map
= system_colors();
171 while (rowbytes
> 0) {
172 rgb_color c
= map
->color_list
[in_data
[0]];
174 out_buf
[1] = c
.green
;
176 out_buf
[3] = c
.alpha
;
183 while (rowbytes
> 0) {
184 unsigned char ch
= *in_data
;
195 while (rowbytes
> 0) { /* expansion 1->32 is pretty good :-) */
196 unsigned char c1
= *in_data
;
197 for (int b
= 128; b
; b
= b
>>1) {
215 case B_CMY24
: /* We do the "clean" inversion which doesn't correct for printing ink deficiencies. */
216 while (rowbytes
> 2) {
217 out_buf
[0] = 255-in_data
[2];
218 out_buf
[1] = 255-in_data
[1];
219 out_buf
[2] = 255-in_data
[0];
227 while (rowbytes
> 3) {
228 out_buf
[0] = 255-in_data
[2];
229 out_buf
[1] = 255-in_data
[1];
230 out_buf
[2] = 255-in_data
[0];
238 while (rowbytes
> 3) {
239 out_buf
[0] = 255-in_data
[2];
240 out_buf
[1] = 255-in_data
[1];
241 out_buf
[2] = 255-in_data
[0];
242 out_buf
[3] = in_data
[3];
248 case B_CMYK32
: /* We assume uniform gray removal, and no under-color-removal. */
249 while (rowbytes
> 3) {
250 int comp
= 255-in_data
[2]-in_data
[3];
251 out_buf
[0] = comp
< 0 ? 0 : comp
;
252 comp
= 255-in_data
[1]-in_data
[3];
253 out_buf
[1] = comp
< 0 ? 0 : comp
;
254 comp
= 255-in_data
[0]-in_data
[3];
255 out_buf
[2] = comp
< 0 ? 0 : comp
;
265 return out_buf
- in_out
;
271 unsigned char * in_buf
,
273 color_space out_space
,
274 unsigned char * out_buf
)
276 ASSERT(in_buf
!= out_buf
);
278 unsigned char * in_out
= out_buf
;
279 /* We could increase perceived image quality of down conversions by implementing */
280 /* dithering. However, someone might want to operate on the images after */
281 /* conversion, in which case dithering would be un-good. Besides, good error */
282 /* diffusion requires more than one scan line to propagate errors to. */
285 memcpy(out_buf
, in_buf
, num_bytes
);
288 memcpy(out_buf
, in_buf
, num_bytes
);
291 while (num_bytes
> 3) {
292 out_buf
[0] = in_buf
[0];
293 out_buf
[1] = in_buf
[1];
294 out_buf
[2] = in_buf
[2];
301 while (num_bytes
> 3) {
302 uint16 val
= (in_buf
[0]>>3)|((in_buf
[1]<<3)&0x7e0)|((in_buf
[2]<<8)&0xf800);
311 while (num_bytes
> 3) {
312 uint16 val
= (in_buf
[0]>>3)|((in_buf
[1]<<2)&0x3e0)|((in_buf
[2]<<7)&0x7c00)|0x8000;
321 while (num_bytes
> 3) {
322 uint16 val
= (in_buf
[0]>>3)|((in_buf
[1]<<2)&0x3e0)|((in_buf
[2]<<7)&0x7c00);
323 if (in_buf
[3] > 127) {
334 const color_map
* map
= system_colors();
335 while (num_bytes
> 3) {
336 if (in_buf
[3] < 128) {
337 out_buf
[0] = B_TRANSPARENT_8_BIT
;
340 uint16 val
= (in_buf
[0]>>3)|((in_buf
[1]<<2)&0x3e0)|((in_buf
[2]<<7)&0x7c00);
341 out_buf
[0] = map
->index_map
[val
];
350 while (num_bytes
> 3) { /* There are better algorithms than Y = .25B+.50G+.25R */
351 /* but hardly faster -- and it's still better than (B+G+R)/3 ! */
352 out_buf
[0] = (in_buf
[0]+in_buf
[1]*2+in_buf
[2])>>2;
362 while (num_bytes
> 3) {
369 c
= ((in_buf
[0]+in_buf
[1]*2+in_buf
[2])&0x200)>>(2+cnt
);
380 /* big endian version, when the encoding is not endianess independant */
382 while (num_bytes
> 3) {
383 out_buf
[3] = in_buf
[0];
384 out_buf
[2] = in_buf
[1];
385 out_buf
[1] = in_buf
[2];
392 while (num_bytes
> 3) {
393 out_buf
[3] = in_buf
[0];
394 out_buf
[2] = in_buf
[1];
395 out_buf
[1] = in_buf
[2];
396 out_buf
[0] = in_buf
[3];
403 while (num_bytes
> 3) {
404 out_buf
[2] = in_buf
[0];
405 out_buf
[1] = in_buf
[1];
406 out_buf
[0] = in_buf
[2];
413 while (num_bytes
> 3) {
414 uint16 val
= (in_buf
[0]>>3)|((in_buf
[1]<<3)&0x7e0)|((in_buf
[2]<<8)&0xf800);
423 while (num_bytes
> 3) {
424 uint16 val
= (in_buf
[0]>>3)|((in_buf
[1]<<2)&0x3e0)|((in_buf
[2]<<7)&0x7c00)|0x8000;
433 while (num_bytes
> 3) {
434 uint16 val
= (in_buf
[0]>>3)|((in_buf
[1]<<2)&0x3e0)|((in_buf
[2]<<7)&0x7c00);
435 if (in_buf
[3] > 127) {
446 while (num_bytes
> 3) {
447 out_buf
[0] = 255-in_buf
[2];
448 out_buf
[1] = 255-in_buf
[1];
449 out_buf
[2] = 255-in_buf
[0];
456 while (num_bytes
> 3) {
457 out_buf
[0] = 255-in_buf
[2];
458 out_buf
[1] = 255-in_buf
[1];
459 out_buf
[2] = 255-in_buf
[0];
466 while (num_bytes
> 3) {
467 out_buf
[0] = 255-in_buf
[2];
468 out_buf
[1] = 255-in_buf
[1];
469 out_buf
[2] = 255-in_buf
[0];
470 out_buf
[3] = in_buf
[3];
477 while (num_bytes
> 3) { /* We do direct gray removal */
478 int c
= 255-in_buf
[2];
479 int m
= 255-in_buf
[1];
480 int y
= 255-in_buf
[0];
481 int k
= (c
>m
)?((y
>c
)?y
:c
):((y
>m
)?y
:m
);
494 return out_buf
-in_out
;
505 printf("%02x ", *(ptr
++));
514 color_space in_space
,
515 color_space out_space
,
516 unsigned char * in_data
,
518 unsigned char * out_data
)
520 ASSERT(in_data
!= out_data
);
522 /* Instead of coding each transformation separately, which would create */
523 /* a very large number of conversion functions, we write one function to */
524 /* convert to RGBA32, and another function to convert from RGBA32, and */
525 /* put them together to get a manageable program, at a slight expense in */
526 /* conversion speed. */
530 printf("convert_space(%x, %x, %x)\n", in_space
, out_space
, rowbytes
);
531 printf("raw data: ");
532 print_data(in_data
, rowbytes
);
534 /* If we convert from a format to itself, well... */
535 if (in_space
== out_space
) {
536 memcpy(out_data
, in_data
, rowbytes
);
539 /* When the input format is RGBA32, we don't need the first conversion. */
540 if (in_space
== B_RGBA32
) {
541 n
= collapse_data(in_data
, rowbytes
, out_space
, out_data
);
543 printf("collapsed data: ");
544 print_data(out_data
, n
);
548 /* When the output format is RGBA32, we don't need any second conversion. */
549 if (out_space
== B_RGB32
|| out_space
== B_RGBA32
) {
550 n
= expand_data(in_space
, in_data
, rowbytes
, out_data
);
552 printf("expanded data: ");
553 print_data(out_data
, n
);
557 /* Figure out byte expansion rate -- usually isn't more than 4 */
559 if (in_space
== B_GRAY1
) {
562 unsigned char * buf
= (unsigned char *)malloc(rowbytes
*mul
);
567 n
= expand_data(in_space
, in_data
, rowbytes
, buf
);
569 printf("expanded data: ");
570 print_data(out_data
, n
);
572 n
= collapse_data(buf
, n
, out_space
, out_data
);
574 printf("collapsed data: ");
575 print_data(out_data
, n
);
583 /* Figure out what the rowbytes is for a given width in a given color space. */
584 /* Rowbytes is bytes per pixel times width, rounded up to nearest multiple of 4. */
613 v
= (width
+7)/8; /* whole bytes only, please */