Home | History | Annotate | Download | only in images
      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 
     15 class SkICOImageDecoder : public SkImageDecoder {
     16 public:
     17     SkICOImageDecoder();
     18 
     19     virtual Format getFormat() const {
     20         return kICO_Format;
     21     }
     22 
     23 protected:
     24     virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode);
     25 };
     26 
     27 SkImageDecoder* SkCreateICOImageDecoder();
     28 SkImageDecoder* 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 
     43 SkICOImageDecoder::SkICOImageDecoder()
     44 {
     45 }
     46 
     47 //helpers - my function pointer will call one of these, depending on the bitCount, each time through the inner loop
     48 static 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);
     51 static 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);
     54 static 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);
     57 static 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);
     60 static 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 
     65 static 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 
     78 bool 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
    287 static 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 }
    316 static 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 
    336 static 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 
    346 static 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 
    360 static 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 
    380 static 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 
    395 static SkTRegistry<SkImageDecoder*, SkStream*> gReg(Factory);
    396 
    397