Chameleon

Chameleon Svn Source Tree

Root/branches/cparm/i386/modules/Libeg/egicns.c

  • Property svn:executable set to *
1/*
2 * libeg/load_icns.c
3 * Loading function for .icns Apple icon images
4 *
5 * Copyright (c) 2006 Christoph Pfisterer
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are
10 * met:
11 *
12 * * Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 *
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
18 * distribution.
19 *
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.
23 *
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.
35 */
36
37#include "libegint.h"
38
39//
40// Decompress .icns RLE data
41//
42
43VOID egDecompressIcnsRLE(IN OUT UINT8 **CompData, IN OUT UINTN *CompLen, IN UINT8 *PixelData, IN UINTN PixelCount)
44{
45 UINT8 *cp;
46 UINT8 *cp_end;
47 UINT8 *pp;
48 UINTN pp_left;
49 UINTN len, i;
50 UINT8 value;
51
52 // setup variables
53 cp = *CompData;
54 cp_end = cp + *CompLen;
55 pp = PixelData;
56 pp_left = PixelCount;
57
58 // decode
59 while (cp + 1 < cp_end && pp_left > 0) {
60 len = *cp++;
61 if (len & 0x80) { // compressed data: repeat next byte
62 len -= 125;
63 if (len > pp_left)
64 break;
65 value = *cp++;
66 for (i = 0; i < len; i++) {
67 *pp = value;
68 pp += 4;
69 }
70 } else { // uncompressed data: copy bytes
71 len++;
72 if (len > pp_left || cp + len > cp_end)
73 break;
74 for (i = 0; i < len; i++) {
75 *pp = *cp++;
76 pp += 4;
77 }
78 }
79 pp_left -= len;
80 }
81
82 if (pp_left > 0) {
83 printf(" egDecompressIcnsRLE: still need %d bytes of pixel data\n", pp_left);
84 }
85
86 // record what's left of the compressed data stream
87 *CompData = cp;
88 *CompLen = (UINTN)(cp_end - cp);
89}
90
91//
92// Load Apple .icns icons
93//
94
95EG_IMAGE * egDecodeICNS(IN UINT8 *FileData, IN UINTN FileDataLength, IN UINTN IconSize, IN BOOLEAN WantAlpha)
96{
97 EG_IMAGE *NewImage;
98 UINT8 *Ptr, *BufferEnd, *DataPtr, *MaskPtr;
99 UINT32 BlockLen, DataLen, MaskLen;
100 UINTN FetchPixelSize, PixelCount, i;
101 UINT8 *CompData;
102 UINTN CompLen;
103 UINT8 *SrcPtr;
104 EG_PIXEL *DestPtr;
105
106 if (FileDataLength < 8 || FileData == NULL ||
107 FileData[0] != 'i' || FileData[1] != 'c' || FileData[2] != 'n' || FileData[3] != 's') {
108 // not an icns file...
109 return NULL;
110 }
111
112 FetchPixelSize = IconSize;
113 for (;;) {
114 DataPtr = NULL;
115 DataLen = 0;
116 MaskPtr = NULL;
117 MaskLen = 0;
118
119 Ptr = FileData + 8;
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
125 break;
126
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) {
131 DataPtr = Ptr + 12;
132 DataLen = BlockLen - 12;
133 }
134 } else if (Ptr[0] == 't' && Ptr[1] == '8' && Ptr[2] == 'm' && Ptr[3] == 'k') {
135 MaskPtr = Ptr + 8;
136 MaskLen = BlockLen - 8;
137 }
138
139 } else if (FetchPixelSize == 48) {
140 if (Ptr[0] == 'i' && Ptr[1] == 'h' && Ptr[2] == '3' && Ptr[3] == '2') {
141 DataPtr = Ptr + 8;
142 DataLen = BlockLen - 8;
143 } else if (Ptr[0] == 'h' && Ptr[1] == '8' && Ptr[2] == 'm' && Ptr[3] == 'k') {
144 MaskPtr = Ptr + 8;
145 MaskLen = BlockLen - 8;
146 }
147
148 } else if (FetchPixelSize == 32) {
149 if (Ptr[0] == 'i' && Ptr[1] == 'l' && Ptr[2] == '3' && Ptr[3] == '2') {
150 DataPtr = Ptr + 8;
151 DataLen = BlockLen - 8;
152 } else if (Ptr[0] == 'l' && Ptr[1] == '8' && Ptr[2] == 'm' && Ptr[3] == 'k') {
153 MaskPtr = Ptr + 8;
154 MaskLen = BlockLen - 8;
155 }
156
157 } else if (FetchPixelSize == 16) {
158 if (Ptr[0] == 'i' && Ptr[1] == 's' && Ptr[2] == '3' && Ptr[3] == '2') {
159 DataPtr = Ptr + 8;
160 DataLen = BlockLen - 8;
161 } else if (Ptr[0] == 's' && Ptr[1] == '8' && Ptr[2] == 'm' && Ptr[3] == 'k') {
162 MaskPtr = Ptr + 8;
163 MaskLen = BlockLen - 8;
164 }
165
166 }
167
168 Ptr += BlockLen;
169 }
170
171 /* FUTURE: try to load a different size and scale it later
172 if (DataPtr == NULL && FetchPixelSize == 32) {
173 FetchPixelSize = 128;
174 continue;
175 }
176 */
177 break;
178 }
179
180 if (DataPtr == NULL)
181 return NULL; // no image found
182
183 // allocate image structure and buffer
184 NewImage = egCreateImage(FetchPixelSize, FetchPixelSize, WantAlpha);
185 if (NewImage == NULL)
186 return NULL;
187 PixelCount = FetchPixelSize * FetchPixelSize;
188
189 if (DataLen < PixelCount * 3) {
190
191 // pixel data is compressed, RGB planar
192 CompData = DataPtr;
193 CompLen = DataLen;
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
198 if (CompLen > 0) {
199 printf(" egLoadICNSIcon: %d bytes of compressed data left\n", CompLen);
200 }
201
202 } else {
203
204 // pixel data is uncompressed, RGB interleaved
205 SrcPtr = DataPtr;
206 DestPtr = NewImage->PixelData;
207 for (i = 0; i < PixelCount; i++, DestPtr++) {
208 DestPtr->r = *SrcPtr++;
209 DestPtr->g = *SrcPtr++;
210 DestPtr->b = *SrcPtr++;
211 }
212
213 }
214
215 // add/set alpha plane
216 if (MaskPtr != NULL && MaskLen >= PixelCount && WantAlpha)
217 egInsertPlane(MaskPtr, PLPTR(NewImage, a), PixelCount);
218 else
219 egSetPlane(PLPTR(NewImage, a), WantAlpha ? 255 : 0, PixelCount);
220
221 // FUTURE: scale to originally requested size if we had to load another size
222
223 return NewImage;
224}
225
226/* EOF */
227

Archive Download this file

Revision: 2182