]>
code.delx.au - refind/blob - libeg/load_bmp.c
3 * Loading function for BMP images
5 * Copyright (c) 2006 Christoph Pfisterer
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are
12 * * Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
15 * * Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the
20 * * Neither the name of Christoph Pfisterer nor the names of the
21 * contributors may be used to endorse or promote products derived
22 * from this software without specific prior written permission.
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
27 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
28 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
29 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
30 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
31 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
32 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
34 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
59 UINT16 Planes
; // Must be 1
60 UINT16 BitPerPixel
; // 1, 4, 8, or 24
61 UINT32 CompressionType
;
62 UINT32 ImageSize
; // Compressed image size in bytes
63 UINT32 XPixelsPerMeter
;
64 UINT32 YPixelsPerMeter
;
65 UINT32 NumberOfColors
;
66 UINT32 ImportantColors
;
75 EG_IMAGE
* egDecodeBMP(IN UINT8
*FileData
, IN UINTN FileDataLength
, IN UINTN IconSize
, IN BOOLEAN WantAlpha
)
78 BMP_IMAGE_HEADER
*BmpHeader
;
79 BMP_COLOR_MAP
*BmpColorMap
;
83 UINTN ImageLineOffset
;
84 UINT8 ImageValue
= 0, AlphaValue
;
86 UINTN Index
, BitIndex
;
88 // read and check header
89 if (FileDataLength
< sizeof(BMP_IMAGE_HEADER
) || FileData
== NULL
)
91 BmpHeader
= (BMP_IMAGE_HEADER
*) FileData
;
92 if (BmpHeader
->CharB
!= 'B' || BmpHeader
->CharM
!= 'M')
94 if (BmpHeader
->CompressionType
!= 0)
96 if (BmpHeader
->BitPerPixel
!= 1 && BmpHeader
->BitPerPixel
!= 4 &&
97 BmpHeader
->BitPerPixel
!= 8 && BmpHeader
->BitPerPixel
!= 24)
100 // calculate parameters
101 ImageLineOffset
= BmpHeader
->PixelWidth
;
102 if (BmpHeader
->BitPerPixel
== 24)
103 ImageLineOffset
*= 3;
104 else if (BmpHeader
->BitPerPixel
== 1)
105 ImageLineOffset
= (ImageLineOffset
+ 7) >> 3;
106 else if (BmpHeader
->BitPerPixel
== 4)
107 ImageLineOffset
= (ImageLineOffset
+ 1) >> 1;
108 if ((ImageLineOffset
% 4) != 0)
109 ImageLineOffset
= ImageLineOffset
+ (4 - (ImageLineOffset
% 4));
111 if (BmpHeader
->ImageOffset
+ ImageLineOffset
* BmpHeader
->PixelHeight
> FileDataLength
)
114 // allocate image structure and buffer
115 NewImage
= egCreateImage(BmpHeader
->PixelWidth
, BmpHeader
->PixelHeight
, WantAlpha
);
116 if (NewImage
== NULL
)
118 AlphaValue
= WantAlpha
? 255 : 0;
121 BmpColorMap
= (BMP_COLOR_MAP
*)(FileData
+ sizeof(BMP_IMAGE_HEADER
));
122 ImagePtrBase
= FileData
+ BmpHeader
->ImageOffset
;
123 for (y
= 0; y
< BmpHeader
->PixelHeight
; y
++) {
124 ImagePtr
= ImagePtrBase
;
125 ImagePtrBase
+= ImageLineOffset
;
126 PixelPtr
= NewImage
->PixelData
+ (BmpHeader
->PixelHeight
- 1 - y
) * BmpHeader
->PixelWidth
;
128 switch (BmpHeader
->BitPerPixel
) {
131 for (x
= 0; x
< BmpHeader
->PixelWidth
; x
++) {
134 ImageValue
= *ImagePtr
++;
136 Index
= (ImageValue
>> (7 - BitIndex
)) & 0x01;
137 PixelPtr
->b
= BmpColorMap
[Index
].Blue
;
138 PixelPtr
->g
= BmpColorMap
[Index
].Green
;
139 PixelPtr
->r
= BmpColorMap
[Index
].Red
;
140 PixelPtr
->a
= AlphaValue
;
146 for (x
= 0; x
<= BmpHeader
->PixelWidth
- 2; x
+= 2) {
147 ImageValue
= *ImagePtr
++;
149 Index
= ImageValue
>> 4;
150 PixelPtr
->b
= BmpColorMap
[Index
].Blue
;
151 PixelPtr
->g
= BmpColorMap
[Index
].Green
;
152 PixelPtr
->r
= BmpColorMap
[Index
].Red
;
153 PixelPtr
->a
= AlphaValue
;
156 Index
= ImageValue
& 0x0f;
157 PixelPtr
->b
= BmpColorMap
[Index
].Blue
;
158 PixelPtr
->g
= BmpColorMap
[Index
].Green
;
159 PixelPtr
->r
= BmpColorMap
[Index
].Red
;
160 PixelPtr
->a
= AlphaValue
;
163 if (x
< BmpHeader
->PixelWidth
) {
164 ImageValue
= *ImagePtr
++;
166 Index
= ImageValue
>> 4;
167 PixelPtr
->b
= BmpColorMap
[Index
].Blue
;
168 PixelPtr
->g
= BmpColorMap
[Index
].Green
;
169 PixelPtr
->r
= BmpColorMap
[Index
].Red
;
170 PixelPtr
->a
= AlphaValue
;
176 for (x
= 0; x
< BmpHeader
->PixelWidth
; x
++) {
178 PixelPtr
->b
= BmpColorMap
[Index
].Blue
;
179 PixelPtr
->g
= BmpColorMap
[Index
].Green
;
180 PixelPtr
->r
= BmpColorMap
[Index
].Red
;
181 PixelPtr
->a
= AlphaValue
;
187 for (x
= 0; x
< BmpHeader
->PixelWidth
; x
++) {
188 PixelPtr
->b
= *ImagePtr
++;
189 PixelPtr
->g
= *ImagePtr
++;
190 PixelPtr
->r
= *ImagePtr
++;
191 PixelPtr
->a
= AlphaValue
;
206 VOID
egEncodeBMP(IN EG_IMAGE
*Image
, OUT UINT8
**FileDataReturn
, OUT UINTN
*FileDataLengthReturn
)
208 BMP_IMAGE_HEADER
*BmpHeader
;
210 UINTN FileDataLength
;
213 UINTN ImageLineOffset
;
217 ImageLineOffset
= Image
->Width
* 3;
218 if ((ImageLineOffset
% 4) != 0)
219 ImageLineOffset
= ImageLineOffset
+ (4 - (ImageLineOffset
% 4));
221 // allocate buffer for file data
222 FileDataLength
= sizeof(BMP_IMAGE_HEADER
) + Image
->Height
* ImageLineOffset
;
223 FileData
= AllocateZeroPool(FileDataLength
);
224 if (FileData
== NULL
) {
225 Print(L
"Error allocate %d bytes\n", FileDataLength
);
226 *FileDataReturn
= NULL
;
227 *FileDataLengthReturn
= 0;
232 BmpHeader
= (BMP_IMAGE_HEADER
*)FileData
;
233 BmpHeader
->CharB
= 'B';
234 BmpHeader
->CharM
= 'M';
235 BmpHeader
->Size
= FileDataLength
;
236 BmpHeader
->ImageOffset
= sizeof(BMP_IMAGE_HEADER
);
237 BmpHeader
->HeaderSize
= 40;
238 BmpHeader
->PixelWidth
= Image
->Width
;
239 BmpHeader
->PixelHeight
= Image
->Height
;
240 BmpHeader
->Planes
= 1;
241 BmpHeader
->BitPerPixel
= 24;
242 BmpHeader
->CompressionType
= 0;
243 BmpHeader
->XPixelsPerMeter
= 0xb13;
244 BmpHeader
->YPixelsPerMeter
= 0xb13;
247 ImagePtrBase
= FileData
+ BmpHeader
->ImageOffset
;
248 for (y
= 0; y
< Image
->Height
; y
++) {
249 ImagePtr
= ImagePtrBase
;
250 ImagePtrBase
+= ImageLineOffset
;
251 PixelPtr
= Image
->PixelData
+ (Image
->Height
- 1 - y
) * Image
->Width
;
253 for (x
= 0; x
< Image
->Width
; x
++) {
254 *ImagePtr
++ = PixelPtr
->b
;
255 *ImagePtr
++ = PixelPtr
->g
;
256 *ImagePtr
++ = PixelPtr
->r
;
261 *FileDataReturn
= FileData
;
262 *FileDataLengthReturn
= FileDataLength
;