1
2/*
3 * Copyright 2006 The Android Open Source Project
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8
9
10#include "SkImageDecoder.h"
11#include "SkStream.h"
12#include "SkColorPriv.h"
13#include "SkTypes.h"
14
15class SkICOImageDecoder : public SkImageDecoder {
16public:
17    SkICOImageDecoder();
18
19    virtual Format getFormat() const {
20        return kICO_Format;
21    }
22
23protected:
24    virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode);
25};
26
27SkImageDecoder* SkCreateICOImageDecoder();
28SkImageDecoder* SkCreateICOImageDecoder() {
29    return new SkICOImageDecoder;
30}
31
32/////////////////////////////////////////////////////////////////////////////////////////
33
34//read bytes starting from the begin-th index in the buffer
35//read in Intel order, and return an integer
36
37#define readByte(buffer,begin) buffer[begin]
38#define read2Bytes(buffer,begin) buffer[begin]+(buffer[begin+1]<<8)
39#define read4Bytes(buffer,begin) buffer[begin]+(buffer[begin+1]<<8)+(buffer[begin+2]<<16)+(buffer[begin+3]<<24)
40
41/////////////////////////////////////////////////////////////////////////////////////////
42
43SkICOImageDecoder::SkICOImageDecoder()
44{
45}
46
47//helpers - my function pointer will call one of these, depending on the bitCount, each time through the inner loop
48static void editPixelBit1(const int pixelNo, const unsigned char* buf,
49            const int xorOffset, int& x, int y, const int w,
50            SkBitmap* bm, int alphaByte, int m, int shift, SkPMColor* colors);
51static void editPixelBit4(const int pixelNo, const unsigned char* buf,
52            const int xorOffset, int& x, int y, const int w,
53            SkBitmap* bm, int alphaByte, int m, int shift, SkPMColor* colors);
54static void editPixelBit8(const int pixelNo, const unsigned char* buf,
55            const int xorOffset, int& x, int y, const int w,
56            SkBitmap* bm, int alphaByte, int m, int shift, SkPMColor* colors);
57static void editPixelBit24(const int pixelNo, const unsigned char* buf,
58            const int xorOffset, int& x, int y, const int w,
59            SkBitmap* bm, int alphaByte, int m, int shift, SkPMColor* colors);
60static void editPixelBit32(const int pixelNo, const unsigned char* buf,
61            const int xorOffset, int& x, int y, const int w,
62            SkBitmap* bm, int alphaByte, int m, int shift, SkPMColor* colors);
63
64
65static int calculateRowBytesFor8888(int w, int bitCount)
66{
67    //  Default rowBytes is w << 2 for kARGB_8888
68    //  In the case of a 4 bit image with an odd width, we need to add some
69    //  so we can go off the end of the drawn bitmap.
70    //  Add 4 to ensure that it is still a multiple of 4.
71    if (4 == bitCount && (w & 0x1)) {
72        return (w + 1) << 2;
73    }
74    //  Otherwise return 0, which will allow it to be calculated automatically.
75    return 0;
76}
77
78bool SkICOImageDecoder::onDecode(SkStream* stream, SkBitmap* bm, Mode mode)
79{
80    size_t length = stream->read(NULL, 0);
81    SkAutoMalloc autoMal(length);
82    unsigned char* buf = (unsigned char*)autoMal.get();
83    if (stream->read((void*)buf, length) != length) {
84        return false;
85    }
86
87    //these should always be the same - should i use for error checking? - what about files that have some
88    //incorrect values, but still decode properly?
89    int reserved = read2Bytes(buf, 0);    // 0
90    int type = read2Bytes(buf, 2);        // 1
91    if (reserved != 0 || type != 1)
92        return false;
93    int count = read2Bytes(buf, 4);
94
95    //need to at least have enough space to hold the initial table of info
96    if (length < (size_t)(6 + count*16))
97        return false;
98
99    int choice;
100    Chooser* chooser = this->getChooser();
101    //FIXME:if no chooser, consider providing the largest color image
102    //what are the odds that the largest image would be monochrome?
103    if (NULL == chooser) {
104        choice = 0;
105    } else {
106        chooser->begin(count);
107        for (int i = 0; i < count; i++)
108        {
109            //need to find out the config, width, and height from the stream
110            int width = readByte(buf, 6 + i*16);
111            int height = readByte(buf, 7 + i*16);
112            int offset = read4Bytes(buf, 18 + i*16);
113            int bitCount = read2Bytes(buf, offset+14);
114            SkBitmap::Config c;
115            //currently only provide ARGB_8888_, but maybe we want kIndex8_Config for 1 and 4, and possibly 8?
116            //or maybe we'll determine this based on the provided config
117            switch (bitCount)
118            {
119                case 1:
120                case 4:
121                    // In reality, at least for the moment, these will be decoded into kARGB_8888 bitmaps.
122                    // However, this will be used to distinguish between the lower quality 1bpp and 4 bpp
123                    // images and the higher quality images.
124                    c = SkBitmap::kIndex8_Config;
125                    break;
126                case 8:
127                case 24:
128                case 32:
129                    c = SkBitmap::kARGB_8888_Config;
130                    break;
131                default:
132                    SkDEBUGF(("Image with %ibpp not supported\n", bitCount));
133                    continue;
134            }
135            chooser->inspect(i, c, width, height);
136        }
137        choice = chooser->choose();
138    }
139
140    //you never know what the chooser is going to supply
141    if (choice >= count || choice < 0)
142        return false;
143
144    //skip ahead to the correct header
145    //commented out lines are not used, but if i switch to other read method, need to know how many to skip
146    //otherwise, they could be used for error checking
147    int w = readByte(buf, 6 + choice*16);
148    int h = readByte(buf, 7 + choice*16);
149    int colorCount = readByte(buf, 8 + choice*16);
150    //int reservedToo = readByte(buf, 9 + choice*16);   //0
151    //int planes = read2Bytes(buf, 10 + choice*16);       //1 - but often 0
152    //int fakeBitCount = read2Bytes(buf, 12 + choice*16); //should be real - usually 0
153    int size = read4Bytes(buf, 14 + choice*16);           //matters?
154    int offset = read4Bytes(buf, 18 + choice*16);
155    if ((size_t)(offset + size) > length)
156        return false;
157    //int infoSize = read4Bytes(buf, offset);             //40
158    //int width = read4Bytes(buf, offset+4);              //should == w
159    //int height = read4Bytes(buf, offset+8);             //should == 2*h
160    //int planesToo = read2Bytes(buf, offset+12);         //should == 1 (does it?)
161    int bitCount = read2Bytes(buf, offset+14);
162
163    void (*placePixel)(const int pixelNo, const unsigned char* buf,
164        const int xorOffset, int& x, int y, const int w,
165        SkBitmap* bm, int alphaByte, int m, int shift, SkPMColor* colors) = NULL;
166    switch (bitCount)
167    {
168        case 1:
169            placePixel = &editPixelBit1;
170            colorCount = 2;
171            break;
172        case 4:
173            placePixel = &editPixelBit4;
174            colorCount = 16;
175            break;
176        case 8:
177            placePixel = &editPixelBit8;
178            colorCount = 256;
179            break;
180        case 24:
181            placePixel = &editPixelBit24;
182            colorCount = 0;
183            break;
184        case 32:
185            placePixel = &editPixelBit32;
186            colorCount = 0;
187            break;
188        default:
189            SkDEBUGF(("Decoding %ibpp is unimplemented\n", bitCount));
190            return false;
191    }
192
193    //these should all be zero, but perhaps are not - need to check
194    //int compression = read4Bytes(buf, offset+16);       //0
195    //int imageSize = read4Bytes(buf, offset+20);         //0 - sometimes has a value
196    //int xPixels = read4Bytes(buf, offset+24);           //0
197    //int yPixels = read4Bytes(buf, offset+28);           //0
198    //int colorsUsed = read4Bytes(buf, offset+32)         //0 - might have an actual value though
199    //int colorsImportant = read4Bytes(buf, offset+36);   //0
200
201    int begin = offset + 40;
202    //this array represents the colortable
203    //if i allow other types of bitmaps, it may actually be used as a part of the bitmap
204    SkPMColor* colors = NULL;
205    int blue, green, red;
206    if (colorCount)
207    {
208        colors = new SkPMColor[colorCount];
209        for (int j = 0; j < colorCount; j++)
210        {
211            //should this be a function - maybe a #define?
212            blue = readByte(buf, begin + 4*j);
213            green = readByte(buf, begin + 4*j + 1);
214            red = readByte(buf, begin + 4*j + 2);
215            colors[j] = SkPackARGB32(0xFF, red & 0xFF, green & 0xFF, blue & 0xFF);
216        }
217    }
218    int bitWidth = w*bitCount;
219    int test = bitWidth & 0x1F;
220    int mask = -(((test >> 4) | (test >> 3) | (test >> 2) | (test >> 1) | test) & 0x1);    //either 0xFFFFFFFF or 0
221    int lineBitWidth = (bitWidth & 0xFFFFFFE0) + (0x20 & mask);
222    int lineWidth = lineBitWidth/bitCount;
223
224    int xorOffset = begin + colorCount*4;   //beginning of the color bitmap
225                                            //other read method means we will just be here already
226    int andOffset = xorOffset + ((lineWidth*h*bitCount) >> 3);
227
228    /*int */test = w & 0x1F;   //the low 5 bits - we are rounding up to the next 32 (2^5)
229    /*int */mask = -(((test >> 4) | (test >> 3) | (test >> 2) | (test >> 1) | test) & 0x1);    //either 0xFFFFFFFF or 0
230    int andLineWidth = (w & 0xFFFFFFE0) + (0x20 & mask);
231    //if we allow different Configs, everything is the same til here
232    //change the config, and use different address getter, and place index vs color, and add the color table
233    //FIXME: what is the tradeoff in size?
234    //if the andbitmap (mask) is all zeroes, then we can easily do an index bitmap
235    //however, with small images with large colortables, maybe it's better to still do argb_8888
236
237    if (SkImageDecoder::kDecodeBounds_Mode == mode) {
238        bm->setConfig(SkBitmap::kARGB_8888_Config, w, h, calculateRowBytesFor8888(w, bitCount));
239        delete[] colors;
240        return true;
241    }
242#ifdef SK_BUILD_FOR_ANDROID
243    // No Bitmap reuse supported for this format
244    if (!bm->isNull()) {
245        return false;
246    }
247#endif
248    bm->setConfig(SkBitmap::kARGB_8888_Config, w, h, calculateRowBytesFor8888(w, bitCount));
249
250    if (!this->allocPixelRef(bm, NULL))
251    {
252        delete[] colors;
253        return false;
254    }
255
256    SkAutoLockPixels alp(*bm);
257
258    for (int y = 0; y < h; y++)
259    {
260        for (int x = 0; x < w; x++)
261        {
262            //U32* address = bm->getAddr32(x, y);
263
264            //check the alpha bit first, but pass it along to the function to figure out how to deal with it
265            int andPixelNo = andLineWidth*(h-y-1)+x;
266            //only need to get a new alphaByte when x %8 == 0
267            //but that introduces an if and a mod - probably much slower
268            //that's ok, it's just a read of an array, not a stream
269            int alphaByte = readByte(buf, andOffset + (andPixelNo >> 3));
270            int shift = 7 - (andPixelNo & 0x7);
271            int m = 1 << shift;
272
273            int pixelNo = lineWidth*(h-y-1)+x;
274            placePixel(pixelNo, buf, xorOffset, x, y, w, bm, alphaByte, m, shift, colors);
275
276        }
277    }
278
279    delete [] colors;
280    //ensure we haven't read off the end?
281    //of course this doesn't help us if the andOffset was a lie...
282    //return andOffset + (andLineWidth >> 3) <= length;
283    return true;
284}   //onDecode
285
286//function to place the pixel, determined by the bitCount
287static void editPixelBit1(const int pixelNo, const unsigned char* buf,
288            const int xorOffset, int& x, int y, const int w,
289            SkBitmap* bm, int alphaByte, int m, int shift, SkPMColor* colors)
290{
291    // note that this should be the same as/similar to the AND bitmap
292    SkPMColor* address = bm->getAddr32(x,y);
293    int byte = readByte(buf, xorOffset + (pixelNo >> 3));
294    int colorBit;
295    int alphaBit;
296    // Read all of the bits in this byte.
297    int i = x + 8;
298    // Pin to the width so we do not write outside the bounds of
299    // our color table.
300    i = i > w ? w : i;
301    // While loop to check all 8 bits individually.
302    while (x < i)
303    {
304
305        colorBit = (byte & m) >> shift;
306        alphaBit = (alphaByte & m) >> shift;
307        *address = (alphaBit-1)&(colors[colorBit]);
308        x++;
309        // setup for the next pixel
310        address = address + 1;
311        m = m >> 1;
312        shift -= 1;
313    }
314    x--;
315}
316static void editPixelBit4(const int pixelNo, const unsigned char* buf,
317            const int xorOffset, int& x, int y, const int w,
318            SkBitmap* bm, int alphaByte, int m, int shift, SkPMColor* colors)
319{
320    SkPMColor* address = bm->getAddr32(x, y);
321    int byte = readByte(buf, xorOffset + (pixelNo >> 1));
322    int pixel = (byte >> 4) & 0xF;
323    int alphaBit = (alphaByte & m) >> shift;
324    *address = (alphaBit-1)&(colors[pixel]);
325    x++;
326    //if w is odd, x may be the same as w, which means we are writing to an unused portion of the bitmap
327    //but that's okay, since i've added an extra rowByte for just this purpose
328    address = address + 1;
329    pixel = byte & 0xF;
330    m = m >> 1;
331    alphaBit = (alphaByte & m) >> (shift-1);
332    //speed up trick here
333    *address = (alphaBit-1)&(colors[pixel]);
334}
335
336static void editPixelBit8(const int pixelNo, const unsigned char* buf,
337            const int xorOffset, int& x, int y, const int w,
338            SkBitmap* bm, int alphaByte, int m, int shift, SkPMColor* colors)
339{
340    SkPMColor* address = bm->getAddr32(x, y);
341    int pixel = readByte(buf, xorOffset + pixelNo);
342    int alphaBit = (alphaByte & m) >> shift;
343    *address = (alphaBit-1)&(colors[pixel]);
344}
345
346static void editPixelBit24(const int pixelNo, const unsigned char* buf,
347            const int xorOffset, int& x, int y, const int w,
348            SkBitmap* bm, int alphaByte, int m, int shift, SkPMColor* colors)
349{
350    SkPMColor* address = bm->getAddr32(x, y);
351    int blue = readByte(buf, xorOffset + 3*pixelNo);
352    int green = readByte(buf, xorOffset + 3*pixelNo + 1);
353    int red = readByte(buf, xorOffset + 3*pixelNo + 2);
354    int alphaBit = (alphaByte & m) >> shift;
355    //alphaBit == 1 => alpha = 0
356    int alpha = (alphaBit-1) & 0xFF;
357    *address = SkPreMultiplyARGB(alpha, red, green, blue);
358}
359
360static void editPixelBit32(const int pixelNo, const unsigned char* buf,
361            const int xorOffset, int& x, int y, const int w,
362            SkBitmap* bm, int alphaByte, int m, int shift, SkPMColor* colors)
363{
364    SkPMColor* address = bm->getAddr32(x, y);
365    int blue = readByte(buf, xorOffset + 4*pixelNo);
366    int green = readByte(buf, xorOffset + 4*pixelNo + 1);
367    int red = readByte(buf, xorOffset + 4*pixelNo + 2);
368    int alphaBit = (alphaByte & m) >> shift;
369#if 1 // don't trust the alphaBit for 32bit images <mrr>
370    alphaBit = 0;
371#endif
372    int alpha = readByte(buf, xorOffset + 4*pixelNo + 3) & ((alphaBit-1)&0xFF);
373    *address = SkPreMultiplyARGB(alpha, red, green, blue);
374}
375
376/////////////////////////////////////////////////////////////////////////////////////////
377
378#include "SkTRegistry.h"
379
380static SkImageDecoder* Factory(SkStream* stream) {
381    // Check to see if the first four bytes are 0,0,1,0
382    // FIXME: Is that required and sufficient?
383    SkAutoMalloc autoMal(4);
384    unsigned char* buf = (unsigned char*)autoMal.get();
385    stream->read((void*)buf, 4);
386    int reserved = read2Bytes(buf, 0);
387    int type = read2Bytes(buf, 2);
388    if (reserved != 0 || type != 1) {
389        // This stream does not represent an ICO image.
390        return NULL;
391    }
392    return SkNEW(SkICOImageDecoder);
393}
394
395static SkTRegistry<SkImageDecoder*, SkStream*> gReg(Factory);
396
397