]>
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.
41 #ifdef __MAKEWITH_GNUEFI
60 INT16 Planes
; // Must be 1
61 INT16 BitPerPixel
; // 1, 4, 8, or 24
62 INT32 CompressionType
;
63 INT32 ImageSize
; // Compressed image size in bytes
64 INT32 XPixelsPerMeter
;
65 INT32 YPixelsPerMeter
;
67 INT32 ImportantColors
;
77 EG_IMAGE
* egDecodeBMP(IN UINT8
*FileData
, IN UINTN FileDataLength
, IN UINTN IconSize
, IN BOOLEAN WantAlpha
)
80 BMP_IMAGE_HEADER
*BmpHeader
;
81 BMP_COLOR_MAP
*BmpColorMap
;
85 UINTN PixelWidth
, PixelHeight
, ImageLineOffset
;
86 UINT8 ImageValue
= 0, AlphaValue
;
89 UINTN Index
, BitIndex
;
91 // read and check header
92 if (FileDataLength
< sizeof(BMP_IMAGE_HEADER
) || FileData
== NULL
)
94 BmpHeader
= (BMP_IMAGE_HEADER
*) FileData
;
95 if (BmpHeader
->CharB
!= 'B' || BmpHeader
->CharM
!= 'M')
97 if (BmpHeader
->CompressionType
!= 0)
99 if (BmpHeader
->BitPerPixel
!= 1 && BmpHeader
->BitPerPixel
!= 4 &&
100 BmpHeader
->BitPerPixel
!= 8 && BmpHeader
->BitPerPixel
!= 24)
102 if (BmpHeader
->PixelWidth
< 1 || BmpHeader
->PixelWidth
> 4096 ||
103 BmpHeader
->PixelHeight
< -4096 || BmpHeader
->PixelHeight
== 0 ||
104 BmpHeader
->PixelHeight
> 4096)
107 // calculate parameters
108 PixelWidth
= BmpHeader
->PixelWidth
;
109 UpsideDown
= BmpHeader
->PixelHeight
>= 0;
110 if (BmpHeader
->PixelHeight
< 0)
111 PixelHeight
= -BmpHeader
->PixelHeight
;
113 PixelHeight
= BmpHeader
->PixelHeight
;
114 ImageLineOffset
= PixelWidth
;
115 if (BmpHeader
->BitPerPixel
== 24)
116 ImageLineOffset
*= 3;
117 else if (BmpHeader
->BitPerPixel
== 1)
118 ImageLineOffset
= (ImageLineOffset
+ 7) >> 3;
119 else if (BmpHeader
->BitPerPixel
== 4)
120 ImageLineOffset
= (ImageLineOffset
+ 1) >> 1;
121 if ((ImageLineOffset
% 4) != 0)
122 ImageLineOffset
= ImageLineOffset
+ (4 - (ImageLineOffset
% 4));
124 if (BmpHeader
->ImageOffset
+ ImageLineOffset
* PixelHeight
> FileDataLength
)
127 // allocate image structure and buffer
128 NewImage
= egCreateImage(PixelWidth
, PixelHeight
, WantAlpha
);
129 if (NewImage
== NULL
)
131 AlphaValue
= WantAlpha
? 255 : 0;
134 BmpColorMap
= (BMP_COLOR_MAP
*)(FileData
+ sizeof(BMP_IMAGE_HEADER
));
135 ImagePtrBase
= FileData
+ BmpHeader
->ImageOffset
;
136 for (y
= 0; y
< PixelHeight
; y
++) {
137 ImagePtr
= ImagePtrBase
;
138 ImagePtrBase
+= ImageLineOffset
;
140 PixelPtr
= NewImage
->PixelData
+ (PixelHeight
- 1 - y
) * PixelWidth
;
142 PixelPtr
= NewImage
->PixelData
+ y
* PixelWidth
;
144 switch (BmpHeader
->BitPerPixel
) {
147 for (x
= 0; x
< PixelWidth
; x
++) {
150 ImageValue
= *ImagePtr
++;
152 Index
= (ImageValue
>> (7 - BitIndex
)) & 0x01;
153 PixelPtr
->b
= BmpColorMap
[Index
].Blue
;
154 PixelPtr
->g
= BmpColorMap
[Index
].Green
;
155 PixelPtr
->r
= BmpColorMap
[Index
].Red
;
156 PixelPtr
->a
= AlphaValue
;
162 for (x
= 0; x
<= PixelWidth
- 2; x
+= 2) {
163 ImageValue
= *ImagePtr
++;
165 Index
= ImageValue
>> 4;
166 PixelPtr
->b
= BmpColorMap
[Index
].Blue
;
167 PixelPtr
->g
= BmpColorMap
[Index
].Green
;
168 PixelPtr
->r
= BmpColorMap
[Index
].Red
;
169 PixelPtr
->a
= AlphaValue
;
172 Index
= ImageValue
& 0x0f;
173 PixelPtr
->b
= BmpColorMap
[Index
].Blue
;
174 PixelPtr
->g
= BmpColorMap
[Index
].Green
;
175 PixelPtr
->r
= BmpColorMap
[Index
].Red
;
176 PixelPtr
->a
= AlphaValue
;
179 if (x
< PixelWidth
) {
180 ImageValue
= *ImagePtr
++;
182 Index
= ImageValue
>> 4;
183 PixelPtr
->b
= BmpColorMap
[Index
].Blue
;
184 PixelPtr
->g
= BmpColorMap
[Index
].Green
;
185 PixelPtr
->r
= BmpColorMap
[Index
].Red
;
186 PixelPtr
->a
= AlphaValue
;
192 for (x
= 0; x
< PixelWidth
; x
++) {
194 PixelPtr
->b
= BmpColorMap
[Index
].Blue
;
195 PixelPtr
->g
= BmpColorMap
[Index
].Green
;
196 PixelPtr
->r
= BmpColorMap
[Index
].Red
;
197 PixelPtr
->a
= AlphaValue
;
203 for (x
= 0; x
< PixelWidth
; x
++) {
204 PixelPtr
->b
= *ImagePtr
++;
205 PixelPtr
->g
= *ImagePtr
++;
206 PixelPtr
->r
= *ImagePtr
++;
207 PixelPtr
->a
= AlphaValue
;
222 VOID
egEncodeBMP(IN EG_IMAGE
*Image
, OUT UINT8
**FileDataReturn
, OUT UINTN
*FileDataLengthReturn
)
224 BMP_IMAGE_HEADER
*BmpHeader
;
226 UINTN FileDataLength
;
229 UINTN ImageLineOffset
;
233 ImageLineOffset
= Image
->Width
* 3;
234 if ((ImageLineOffset
% 4) != 0)
235 ImageLineOffset
= ImageLineOffset
+ (4 - (ImageLineOffset
% 4));
237 // allocate buffer for file data
238 FileDataLength
= sizeof(BMP_IMAGE_HEADER
) + Image
->Height
* ImageLineOffset
;
239 FileData
= AllocateZeroPool(FileDataLength
);
240 if (FileData
== NULL
) {
241 Print(L
"Error allocate %d bytes\n", FileDataLength
);
242 *FileDataReturn
= NULL
;
243 *FileDataLengthReturn
= 0;
248 BmpHeader
= (BMP_IMAGE_HEADER
*)FileData
;
249 BmpHeader
->CharB
= 'B';
250 BmpHeader
->CharM
= 'M';
251 BmpHeader
->Size
= (INT32
)FileDataLength
;
252 BmpHeader
->ImageOffset
= sizeof(BMP_IMAGE_HEADER
);
253 BmpHeader
->HeaderSize
= 40;
254 BmpHeader
->PixelWidth
= (INT32
)Image
->Width
;
255 BmpHeader
->PixelHeight
= (INT32
)Image
->Height
;
256 BmpHeader
->Planes
= 1;
257 BmpHeader
->BitPerPixel
= 24;
258 BmpHeader
->CompressionType
= 0;
259 BmpHeader
->XPixelsPerMeter
= 0xb13;
260 BmpHeader
->YPixelsPerMeter
= 0xb13;
263 ImagePtrBase
= FileData
+ BmpHeader
->ImageOffset
;
264 for (y
= 0; y
< Image
->Height
; y
++) {
265 ImagePtr
= ImagePtrBase
;
266 ImagePtrBase
+= ImageLineOffset
;
267 PixelPtr
= Image
->PixelData
+ (Image
->Height
- 1 - y
) * Image
->Width
;
269 for (x
= 0; x
< Image
->Width
; x
++) {
270 *ImagePtr
++ = PixelPtr
->b
;
271 *ImagePtr
++ = PixelPtr
->g
;
272 *ImagePtr
++ = PixelPtr
->r
;
277 *FileDataReturn
= FileData
;
278 *FileDataLengthReturn
= FileDataLength
;