1 /*---------------------------------------------------------------------*
2 
3 Project:  bitmap reader
4 File:     bmp.c
5 
6 Copyright 1998, 1999 Nintendo.  All rights reserved.
7 
8 These coded instructions, statements and computer programs contain
9 proprietary information of Nintendo of America Inc. and/or Nintendo
10 Company Ltd., and are protected by Federal copyright law.  They may
11 not be disclosed to third parties or copied or duplicated in any form,
12 in whole or in part, without the prior written consent of Nintendo.
13 
14 Change History:
15 
16  $Log: bmp.c,v $
17  Revision 1.3  2007/05/23 08:37:47  urata
18  Fixed biSizeImage of bmp header information.
19 
20  Revision 1.2  2006/02/20 04:13:13  mitu
21  changed include path from dolphin/ to revolution/.
22 
23  Revision 1.1  2005/12/16 08:34:26  urata
24  Initial checkin.
25 
26 
27     1     1/15/00 3:04a Hashida
28     Initial revision
29 
30  $NoKeywords: $
31 
32 -----------------------------------------------------------------------*/
33 
34 
35 #include <revolution.h>
36 #include <assert.h>
37 #include "bmp.h"
38 
39 
40 #define CLAMP(x,l,h) ((x > h) ? h : ((x < l) ? l : x))
41 #define TENT(a, b, c) (0.25 * (a) + 0.5 * (b) + 0.25 * (c))
42 
43 // for endianness
44 #define REV16(x)      ((u16)( ( (x) >> 8 ) + ( ((x) & 0xff) << 8 ) ))
45 #define REV32(x)        ((u32)( ( ((x) & 0xff000000) >> 24)         \
46                               + ( ((x) & 0x00ff0000) >> 8 )         \
47                               + ( ((x) & 0x0000ff00) << 8 )         \
48                               + ( ((x) & 0x000000ff) << 24 ) ))
49 
50 // decode a tga file into a 'DecodedFile' structure
51 
openBmp(bmpInfo_s * bi,u8 * header)52 BOOL openBmp(bmpInfo_s* bi, u8* header)
53 {
54     u8*     bInfoHeader;
55 
56     assert( header != NULL );
57 
58     // fill bmpInfo
59     assert(*header == 'B');
60     assert(*(header + 1) == 'M');
61 
62     bi->biSizeImage = REV32(*(u32*)(header + 0x02));
63     bi->bfOffBits   = REV32(*(u32*)(header + 0x0a));
64 
65     bInfoHeader = header + 0x0e;
66 
67     bi->width       = REV32(*(u32*)(bInfoHeader + 0x04));
68     bi->height      = REV32(*(u32*)(bInfoHeader + 0x08));
69     bi->biBitCount  = REV16(*(u16*)(bInfoHeader + 0x0e));
70     bi->biCompression = REV32(*(u32*)(bInfoHeader + 0x10));
71 
72     bi->paletteOff  = 0x0e + REV32(*(u32*)(bInfoHeader));
73 
74     if (bi->biBitCount == 24)
75     {
76         // there should be no rgbquad
77         assert(bi->bfOffBits == bi->paletteOff);
78     }
79     else
80     {
81         assert(bi->bfOffBits ==
82                bi->paletteOff + 2^bi->biBitCount * sizeof(rgbQuad_s));
83     }
84 
85     return TRUE;
86 }
87 
88 #ifdef XFB_SF
bmpToYCbCr(bmpInfo_s * bi,u8 * rawData,u8 * dest1,u8 * dest2)89 BOOL bmpToYCbCr(bmpInfo_s* bi, u8* rawData, u8* dest1, u8* dest2)
90 #else
91 BOOL bmpToYCbCr(bmpInfo_s* bi, u8* rawData, u8* dest)
92 #endif
93 {
94     u8          r, g, b;
95     u32         row, col;
96     double      Y;
97     double      Cb_pp, Cb_p, Cb;
98     double      Cr_pp, Cr_p, Cr;
99 #ifdef XFB_SF
100     u8*         dest;
101 #endif
102     rgbQuad_s*  palette;
103     u32         paletteNum;
104     u32         bytesPerLine;
105     u8*         imageData;
106     u8*         imageDataStart;
107     u8*         destStart;
108 
109     palette = (rgbQuad_s*)(rawData + bi->paletteOff);
110     imageData = rawData + bi->bfOffBits;
111 
112     bytesPerLine = (bi->width * bi->biBitCount + 7) / 8;
113     bytesPerLine = ((bytesPerLine + 3) / 4) * 4;
114 
115     // we start from the last line because BMP stores its image upside down
116     imageData += bytesPerLine * (bi->height - 1);
117 
118     for(row = 0; row < bi->height; row++)
119     {
120 #ifdef XFB_SF
121         dest = ((row & 0x1) == 0)? dest1:dest2;
122 #endif
123         destStart = dest;
124         imageDataStart = imageData;
125 
126         for(col = 0; col < bi->width; col++)
127         {
128             switch(bi->biBitCount)
129             {
130               case 1:           // monochrome
131                 paletteNum = (u32)( ((*imageData) >> (7 - col % 8)) & 1 );
132                 r = palette[paletteNum].red;
133                 g = palette[paletteNum].green;
134                 b = palette[paletteNum].blue;
135                 break;
136 
137               case 4:           // 16 colors
138                 paletteNum = (u32)(((*imageData) >> (4 - (col % 2)*4)) & 0x0f);
139                 r = palette[paletteNum].red;
140                 g = palette[paletteNum].green;
141                 b = palette[paletteNum].blue;
142                 break;
143 
144               case 8:           // 256 colors
145                 paletteNum = (u32)*imageData;
146                 r = palette[paletteNum].red;
147                 g = palette[paletteNum].green;
148                 b = palette[paletteNum].blue;
149                 break;
150 
151               case 24:          // true color
152                 // be careful about the order
153                 b = *imageData;
154                 g = *(imageData + 1);
155                 r = *(imageData + 2);
156                 break;
157 
158               default:
159                 OSReport("biBitCount %d is not supported\n", bi->biBitCount);
160                 OSHalt("");
161                 break;
162             } // end switch(bi->biBitCount)
163 
164             Y  =  0.257 * r + 0.504 * g + 0.098 * b +  16.0 + 0.5;
165             Cb = -0.148 * r - 0.291 * g + 0.439 * b + 128.0 + 0.5;
166             Cr =  0.439 * r - 0.368 * g - 0.071 * b + 128.0 + 0.5;
167 
168             Y  = CLAMP(Y , 16, 235);
169             Cb = CLAMP(Cb, 16, 240);
170             Cr = CLAMP(Cr, 16, 240);
171 
172             *dest = (u8)Y;
173             if (col & 1)
174             {
175                 // col is odd
176                 *(dest - 1) = (u8)TENT(Cb_pp, Cb_p, Cb);
177                 *(dest + 1) = (u8)TENT(Cr_pp, Cr_p, Cr);
178             }
179 
180             // in case of col == 0, Cb_p doesn't have a valid value
181             // use Cb instead
182             Cb_pp = (col == 0)? Cb : Cb_p;
183             Cb_p  = Cb;
184             Cr_pp = (col == 0)? Cr : Cr_p;
185             Cr_p  = Cr;
186 
187             if (bi->biBitCount == 1)
188             {
189                 if (col % 8 == 7)
190                     imageData++;
191             }
192             else if (bi->biBitCount == 4)
193             {
194                 if (col % 2 == 1)
195                     imageData++;
196             }
197             else
198                 imageData += bi->biBitCount / 8;
199 
200             dest += 2;      // 2 bytes per pixel for 422YCbCr
201 
202         } // end 'col' for loop
203 
204         // if width is odd, add one pixel because 422YCbCr doesn't
205         // allow odd number for width
206         if (col % 2 == 1)
207         {
208             *dest = (u8)Y;
209             // col is odd (Cb = Cb_p, Cr = Cr_p)
210             *(dest - 1) = (u8)TENT(Cb_pp, Cb_p, Cb);
211             *(dest + 1) = (u8)TENT(Cr_pp, Cr_p, Cr);
212             dest += 2;
213 
214             col++;
215         }
216 
217         for( ; col < (bi->width + 15) / 16 * 16; col += 2)
218         {
219             // fill rest by black so that the next line is
220             // aligned by 32bytes
221             *dest++ = 16;
222             *dest++ = 128;
223             *dest++ = 16;
224             *dest++ = 128;
225         }
226 
227         dest = destStart + (bi->width + 15) / 16 * 16 * 2;
228         imageData = imageDataStart - bytesPerLine;
229 
230 #ifdef XFB_SF
231         if ( (row & 0x1) == 0 )
232             dest1 = dest;
233         else
234             dest2 = dest;
235 #endif
236     } // end 'row' for loop
237 
238     // if height is odd, add a black line on the bottom
239     if (row % 2 == 1)
240     {
241         for(col = 0; col < (bi->width + 15) / 16 * 16; col += 2)
242         {
243             *dest++ = 16;
244             *dest++ = 128;
245             *dest++ = 16;
246             *dest++ = 128;
247         }
248     }
249 
250     return TRUE;
251 }
252 
253