]>
code.delx.au - refind/blob - libeg/load_icns.c
3 * Loading function for .icns Apple icon 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.
40 // Decompress .icns RLE data
43 VOID
egDecompressIcnsRLE(IN OUT UINT8
**CompData
, IN OUT UINTN
*CompLen
, IN UINT8
*PixelData
, IN UINTN PixelCount
)
54 cp_end
= cp
+ *CompLen
;
59 while (cp
+ 1 < cp_end
&& pp_left
> 0) {
61 if (len
& 0x80) { // compressed data: repeat next byte
66 for (i
= 0; i
< len
; i
++) {
70 } else { // uncompressed data: copy bytes
72 if (len
> pp_left
|| cp
+ len
> cp_end
)
74 for (i
= 0; i
< len
; i
++) {
83 Print(L
" egDecompressIcnsRLE: still need %d bytes of pixel data\n", pp_left
);
86 // record what's left of the compressed data stream
88 *CompLen
= (UINTN
)(cp_end
- cp
);
92 // Load Apple .icns icons
95 EG_IMAGE
* egDecodeICNS(IN UINT8
*FileData
, IN UINTN FileDataLength
, IN UINTN IconSize
, IN BOOLEAN WantAlpha
)
98 UINT8
*Ptr
, *BufferEnd
, *DataPtr
, *MaskPtr
;
99 UINT32 BlockLen
, DataLen
, MaskLen
;
100 UINTN FetchPixelSize
, PixelCount
, i
;
106 if (FileDataLength
< 8 || FileData
== NULL
||
107 FileData
[0] != 'i' || FileData
[1] != 'c' || FileData
[2] != 'n' || FileData
[3] != 's') {
108 // not an icns file...
112 FetchPixelSize
= IconSize
;
120 BufferEnd
= FileData
+ FileDataLength
;
121 // iterate over tagged blocks in the file
122 while (Ptr
+ 8 <= BufferEnd
) {
123 BlockLen
= ((UINT32
)Ptr
[4] << 24) + ((UINT32
)Ptr
[5] << 16) + ((UINT32
)Ptr
[6] << 8) + (UINT32
)Ptr
[7];
124 if (Ptr
+ BlockLen
> BufferEnd
) // block continues beyond end of file
127 // extract the appropriate blocks for each pixel size
128 if (FetchPixelSize
== 128) {
129 if (Ptr
[0] == 'i' && Ptr
[1] == 't' && Ptr
[2] == '3' && Ptr
[3] == '2') {
130 if (Ptr
[8] == 0 && Ptr
[9] == 0 && Ptr
[10] == 0 && Ptr
[11] == 0) {
132 DataLen
= BlockLen
- 12;
134 } else if (Ptr
[0] == 't' && Ptr
[1] == '8' && Ptr
[2] == 'm' && Ptr
[3] == 'k') {
136 MaskLen
= BlockLen
- 8;
139 } else if (FetchPixelSize
== 48) {
140 if (Ptr
[0] == 'i' && Ptr
[1] == 'h' && Ptr
[2] == '3' && Ptr
[3] == '2') {
142 DataLen
= BlockLen
- 8;
143 } else if (Ptr
[0] == 'h' && Ptr
[1] == '8' && Ptr
[2] == 'm' && Ptr
[3] == 'k') {
145 MaskLen
= BlockLen
- 8;
148 } else if (FetchPixelSize
== 32) {
149 if (Ptr
[0] == 'i' && Ptr
[1] == 'l' && Ptr
[2] == '3' && Ptr
[3] == '2') {
151 DataLen
= BlockLen
- 8;
152 } else if (Ptr
[0] == 'l' && Ptr
[1] == '8' && Ptr
[2] == 'm' && Ptr
[3] == 'k') {
154 MaskLen
= BlockLen
- 8;
157 } else if (FetchPixelSize
== 16) {
158 if (Ptr
[0] == 'i' && Ptr
[1] == 's' && Ptr
[2] == '3' && Ptr
[3] == '2') {
160 DataLen
= BlockLen
- 8;
161 } else if (Ptr
[0] == 's' && Ptr
[1] == '8' && Ptr
[2] == 'm' && Ptr
[3] == 'k') {
163 MaskLen
= BlockLen
- 8;
171 /* FUTURE: try to load a different size and scale it later
172 if (DataPtr == NULL && FetchPixelSize == 32) {
173 FetchPixelSize = 128;
181 return NULL
; // no image found
183 // allocate image structure and buffer
184 NewImage
= egCreateImage(FetchPixelSize
, FetchPixelSize
, WantAlpha
);
185 if (NewImage
== NULL
)
187 PixelCount
= FetchPixelSize
* FetchPixelSize
;
189 if (DataLen
< PixelCount
* 3) {
191 // pixel data is compressed, RGB planar
194 egDecompressIcnsRLE(&CompData
, &CompLen
, PLPTR(NewImage
, r
), PixelCount
);
195 egDecompressIcnsRLE(&CompData
, &CompLen
, PLPTR(NewImage
, g
), PixelCount
);
196 egDecompressIcnsRLE(&CompData
, &CompLen
, PLPTR(NewImage
, b
), PixelCount
);
197 // possible assertion: CompLen == 0
199 Print(L
" egLoadICNSIcon: %d bytes of compressed data left\n", CompLen
);
204 // pixel data is uncompressed, RGB interleaved
206 DestPtr
= NewImage
->PixelData
;
207 for (i
= 0; i
< PixelCount
; i
++, DestPtr
++) {
208 DestPtr
->r
= *SrcPtr
++;
209 DestPtr
->g
= *SrcPtr
++;
210 DestPtr
->b
= *SrcPtr
++;
215 // add/set alpha plane
216 if (MaskPtr
!= NULL
&& MaskLen
>= PixelCount
&& WantAlpha
)
217 egInsertPlane(MaskPtr
, PLPTR(NewImage
, a
), PixelCount
);
219 egSetPlane(PLPTR(NewImage
, a
), WantAlpha
? 255 : 0, PixelCount
);
221 // FUTURE: scale to originally requested size if we had to load another size
224 } // EG_IMAGE * egDecodeICNS()