Adding swizzles for bmp:
    We now support kN32 and kRGB_565 color types.
    Additionally, we support premul, unpremul, and opaque alpha types.
    Unpremul is currently untested as we cannot currently draw to unpremul.

BUG=skia:

Review URL: https://codereview.chromium.org/1013743003
diff --git a/src/codec/SkCodecPriv.h b/src/codec/SkCodecPriv.h
index a0e5c94..7c57a9f 100644
--- a/src/codec/SkCodecPriv.h
+++ b/src/codec/SkCodecPriv.h
@@ -65,15 +65,6 @@
 
 /*
  *
- * Checks if alpha types are premul and unpremul
- *
- */
-static inline bool premul_and_unpremul(SkAlphaType dst, SkAlphaType src) {
-    return kPremul_SkAlphaType == dst && kUnpremul_SkAlphaType == src;
-}
-
-/*
- *
  * Get a byte from a buffer
  * This method is unsafe, the caller is responsible for performing a check
  *
diff --git a/src/codec/SkCodec_libbmp.cpp b/src/codec/SkCodec_libbmp.cpp
index a96cd66..62cda95 100644
--- a/src/codec/SkCodec_libbmp.cpp
+++ b/src/codec/SkCodec_libbmp.cpp
@@ -18,18 +18,23 @@
  */
 static bool conversion_possible(const SkImageInfo& dst,
                                 const SkImageInfo& src) {
-    // All of the swizzles convert to kN32
-    // TODO: Update this when more swizzles are supported
-    if (kN32_SkColorType != dst.colorType()) {
+    // Ensure that the profile type is unchanged
+    if (dst.profileType() != src.profileType()) {
         return false;
     }
-    // Support the swizzle if the requested alpha type is the same as our guess
-    // for the input alpha type
-    if (src.alphaType() == dst.alphaType()) {
-        return true;
+
+    // Check for supported color and alpha types
+    switch (dst.colorType()) {
+        case kN32_SkColorType:
+            return src.alphaType() == dst.alphaType() ||
+                    (kPremul_SkAlphaType == dst.alphaType() &&
+                    kUnpremul_SkAlphaType == src.alphaType());
+        case kRGB_565_SkColorType:
+            return src.alphaType() == dst.alphaType() &&
+                    kOpaque_SkAlphaType == dst.alphaType();
+        default:
+            return false;
     }
-    // TODO: Support more swizzles, especially premul
-    return false;
 }
 
 /*
@@ -247,7 +252,7 @@
 
     // Create mask struct
     SkMasks::InputMasks inputMasks;
-    memset(&inputMasks, 0, 4*sizeof(uint32_t));
+    memset(&inputMasks, 0, sizeof(SkMasks::InputMasks));
 
     // Determine the input compression format and set bit masks if necessary
     uint32_t maskBytes = 0;
@@ -392,87 +397,30 @@
         return NULL;
     }
 
-    // Process the color table
-    uint32_t colorBytes = 0;
-    SkPMColor* colorTable = NULL;
-    if (bitsPerPixel < 16) {
-        // Verify the number of colors for the color table
-        const uint32_t maxColors = 1 << bitsPerPixel;
-        // Zero is a default for maxColors
-        // Also set numColors to maxColors when input is too large
-        if (numColors <= 0 || numColors > maxColors) {
-            numColors = maxColors;
-        }
-        colorTable = SkNEW_ARRAY(SkPMColor, maxColors);
-
-        // Construct the color table
-        colorBytes = numColors * bytesPerColor;
-        SkAutoTDeleteArray<uint8_t> cBuffer(SkNEW_ARRAY(uint8_t, colorBytes));
-        if (stream->read(cBuffer.get(), colorBytes) != colorBytes) {
-            SkDebugf("Error: unable to read color table.\n");
-            return NULL;
-        }
-
-        // Fill in the color table (colors are stored unpremultiplied)
-        uint32_t i = 0;
-        for (; i < numColors; i++) {
-            uint8_t blue = get_byte(cBuffer.get(), i*bytesPerColor);
-            uint8_t green = get_byte(cBuffer.get(), i*bytesPerColor + 1);
-            uint8_t red = get_byte(cBuffer.get(), i*bytesPerColor + 2);
-            uint8_t alpha = 0xFF;
-            if (kOpaque_SkAlphaType != alphaType) {
-                alpha = (inputMasks.alpha >> 24) &
-                        get_byte(cBuffer.get(), i*bytesPerColor + 3);
-            }
-            // Store the unpremultiplied color
-            colorTable[i] = SkPackARGB32NoCheck(alpha, red, green, blue);
-        }
-
-        // To avoid segmentation faults on bad pixel data, fill the end of the
-        // color table with black.  This is the same the behavior as the
-        // chromium decoder.
-        for (; i < maxColors; i++) {
-            colorTable[i] = SkPackARGB32NoCheck(0xFF, 0, 0, 0);
-        }
-    }
-
-    // Ensure that the stream now points to the start of the pixel array
-    uint32_t bytesRead = kBmpHeaderBytes + infoBytes + maskBytes + colorBytes;
-
-    // Check that we have not read past the pixel array offset
-    if(bytesRead > offset) {
-        // This may occur on OS 2.1 and other old versions where the color
-        // table defaults to max size, and the bmp tries to use a smaller color
-        // table.  This is invalid, and our decision is to indicate an error,
-        // rather than try to guess the intended size of the color table and
-        // rewind the stream to display the image.
-        SkDebugf("Error: pixel data offset less than header size.\n");
-        return NULL;
-    }
-
-    // Skip to the start of the pixel array
-    if (stream->skip(offset - bytesRead) != offset - bytesRead) {
-        SkDebugf("Error: unable to skip to image data.\n");
-        return NULL;
-    }
-
-    // Remaining bytes is only used for RLE
-    const int remainingBytes = totalBytes - offset;
-    if (remainingBytes <= 0 && kRLE_BitmapInputFormat == inputFormat) {
+    // Check for a valid number of total bytes when in RLE mode
+    if (totalBytes <= offset && kRLE_BitmapInputFormat == inputFormat) {
         SkDebugf("Error: RLE requires valid input size.\n");
         return NULL;
     }
+    const size_t RLEBytes = totalBytes - offset;
+
+    // Calculate the number of bytes read so far
+    const uint32_t bytesRead = kBmpHeaderBytes + infoBytes + maskBytes;
+    if (offset < bytesRead) {
+        SkDebugf("Error: pixel data offset less than header size.\n");
+        return NULL;
+    }
 
     // Return the codec
     // We will use ImageInfo to store width, height, and alpha type.  We will
-    // choose kN32_SkColorType as the input color type because that is the
-    // expected choice for a destination color type.  In reality, the input
-    // color type has many possible formats.
+    // set color type to kN32_SkColorType because that should be the default
+    // output.
     const SkImageInfo& imageInfo = SkImageInfo::Make(width, height,
             kN32_SkColorType, alphaType);
     return SkNEW_ARGS(SkBmpCodec, (imageInfo, stream, bitsPerPixel,
-                                   inputFormat, masks.detach(), colorTable,
-                                   rowOrder, remainingBytes));
+                                   inputFormat, masks.detach(), numColors,
+                                   bytesPerColor, offset - bytesRead,
+                                   rowOrder, RLEBytes));
 }
 
 /*
@@ -483,16 +431,19 @@
  */
 SkBmpCodec::SkBmpCodec(const SkImageInfo& info, SkStream* stream,
                        uint16_t bitsPerPixel, BitmapInputFormat inputFormat,
-                       SkMasks* masks, SkPMColor* colorTable,
-                       RowOrder rowOrder,
-                       const uint32_t remainingBytes)
+                       SkMasks* masks, uint32_t numColors,
+                       uint32_t bytesPerColor, uint32_t offset,
+                       RowOrder rowOrder, size_t RLEBytes)
     : INHERITED(info, stream)
     , fBitsPerPixel(bitsPerPixel)
     , fInputFormat(inputFormat)
     , fMasks(masks)
-    , fColorTable(colorTable)
+    , fColorTable(NULL)
+    , fNumColors(numColors)
+    , fBytesPerColor(bytesPerColor)
+    , fOffset(offset)
     , fRowOrder(rowOrder)
-    , fRemainingBytes(remainingBytes)
+    , fRLEBytes(RLEBytes)
 {}
 
 /*
@@ -504,6 +455,7 @@
                                         void* dst, size_t dstRowBytes,
                                         const Options&,
                                         SkPMColor*, int*) {
+    // Check for proper input and output formats
     if (!this->rewindIfNeeded()) {
         return kCouldNotRewind;
     }
@@ -516,6 +468,13 @@
         return kInvalidConversion;
     }
 
+    // Create the color table if necessary and prepare the stream for decode
+    if (!createColorTable(dstInfo.alphaType())) {
+        SkDebugf("Error: could not create color table.\n");
+        return kInvalidInput;
+    }
+
+    // Perform the decode
     switch (fInputFormat) {
         case kBitMask_BitmapInputFormat:
             return decodeMask(dstInfo, dst, dstRowBytes);
@@ -531,6 +490,92 @@
 
 /*
  *
+ * Process the color table for the bmp input
+ *
+ */
+ bool SkBmpCodec::createColorTable(SkAlphaType alphaType) {
+    // Allocate memory for color table
+    uint32_t colorBytes = 0;
+    uint32_t maxColors = 0;
+    SkPMColor colorTable[256];
+    if (fBitsPerPixel <= 8) {
+        // Zero is a default for maxColors
+        // Also set fNumColors to maxColors when it is too large
+        maxColors = 1 << fBitsPerPixel;
+        if (fNumColors == 0 || fNumColors >= maxColors) {
+            fNumColors = maxColors;
+        }
+
+        // Read the color table from the stream
+        colorBytes = fNumColors * fBytesPerColor;
+        SkAutoTDeleteArray<uint8_t> cBuffer(SkNEW_ARRAY(uint8_t, colorBytes));
+        if (stream()->read(cBuffer.get(), colorBytes) != colorBytes) {
+            SkDebugf("Error: unable to read color table.\n");
+            return false;
+        }
+
+        // Choose the proper packing function
+        SkPMColor (*packARGB) (uint32_t, uint32_t, uint32_t, uint32_t);
+        switch (alphaType) {
+            case kOpaque_SkAlphaType:
+            case kUnpremul_SkAlphaType:
+                packARGB = &SkPackARGB32NoCheck;
+                break;
+            case kPremul_SkAlphaType:
+                packARGB = &SkPreMultiplyARGB;
+                break;
+            default:
+                // This should not be reached because conversion possible
+                // should fail if the alpha type is not one of the above
+                // values.
+                SkASSERT(false);
+                packARGB = NULL;
+                break;
+        }
+
+        // Fill in the color table
+        uint32_t i = 0;
+        for (; i < fNumColors; i++) {
+            uint8_t blue = get_byte(cBuffer.get(), i*fBytesPerColor);
+            uint8_t green = get_byte(cBuffer.get(), i*fBytesPerColor + 1);
+            uint8_t red = get_byte(cBuffer.get(), i*fBytesPerColor + 2);
+            uint8_t alpha = kOpaque_SkAlphaType == alphaType ? 0xFF :
+                    (fMasks->getAlphaMask() >> 24) &
+                    get_byte(cBuffer.get(), i*fBytesPerColor + 3);
+            colorTable[i] = packARGB(alpha, red, green, blue);
+        }
+
+        // To avoid segmentation faults on bad pixel data, fill the end of the
+        // color table with black.  This is the same the behavior as the
+        // chromium decoder.
+        for (; i < maxColors; i++) {
+            colorTable[i] = SkPackARGB32NoCheck(0xFF, 0, 0, 0);
+        }
+    }
+
+    // Check that we have not read past the pixel array offset
+    if(fOffset < colorBytes) {
+        // This may occur on OS 2.1 and other old versions where the color
+        // table defaults to max size, and the bmp tries to use a smaller color
+        // table.  This is invalid, and our decision is to indicate an error,
+        // rather than try to guess the intended size of the color table.
+        SkDebugf("Error: pixel data offset less than color table size.\n");
+        return false;
+    }
+
+    // After reading the color table, skip to the start of the pixel array
+    if (stream()->skip(fOffset - colorBytes) != fOffset - colorBytes) {
+        SkDebugf("Error: unable to skip to image data.\n");
+        return false;
+    }
+
+    // Set the color table and return true on success
+    fColorTable.reset(SkNEW_ARGS(SkColorTable, (colorTable, maxColors)));
+    return true;
+}
+
+/*
+ *
  * Performs the bitmap decoding for bit masks input format
  *
  */
@@ -541,50 +586,50 @@
     const int height = dstInfo.height();
     const size_t rowBytes = SkAlign4(compute_row_bytes(width, fBitsPerPixel));
 
-    // Allocate space for a row buffer and a source for the swizzler
-    SkAutoTDeleteArray<uint8_t> srcBuffer(SkNEW_ARRAY(uint8_t, rowBytes));
-
-    // Get the destination start row and delta
-    SkPMColor* dstRow;
-    int delta;
-    if (kTopDown_RowOrder == fRowOrder) {
-        dstRow = (SkPMColor*) dst;
-        delta = (int) dstRowBytes;
-    } else {
-        dstRow = (SkPMColor*) SkTAddOffset<void>(dst, (height-1) * dstRowBytes);
-        delta = -((int) dstRowBytes);
-    }
+    // Allocate a buffer large enough to hold the full image
+    SkAutoTDeleteArray<uint8_t>
+        srcBuffer(SkNEW_ARRAY(uint8_t, height*rowBytes));
+    uint8_t* srcRow = srcBuffer.get();
 
     // Create the swizzler
-    SkMaskSwizzler* swizzler = SkMaskSwizzler::CreateMaskSwizzler(
-            dstInfo, fMasks, fBitsPerPixel);
+    SkAutoTDelete<SkMaskSwizzler> maskSwizzler(
+            SkMaskSwizzler::CreateMaskSwizzler(dstInfo, dst, dstRowBytes,
+            fMasks, fBitsPerPixel));
 
     // Iterate over rows of the image
     bool transparent = true;
     for (int y = 0; y < height; y++) {
         // Read a row of the input
-        if (stream()->read(srcBuffer.get(), rowBytes) != rowBytes) {
+        if (stream()->read(srcRow, rowBytes) != rowBytes) {
             SkDebugf("Warning: incomplete input stream.\n");
             return kIncompleteInput;
         }
 
         // Decode the row in destination format
-        SkSwizzler::ResultAlpha r = swizzler->next(dstRow, srcBuffer.get());
+        int row = kBottomUp_RowOrder == fRowOrder ? height - 1 - y : y;
+        SkSwizzler::ResultAlpha r = maskSwizzler->next(srcRow, row);
         transparent &= SkSwizzler::IsTransparent(r);
 
         // Move to the next row
-        dstRow = SkTAddOffset<SkPMColor>(dstRow, delta);
+        srcRow = SkTAddOffset<uint8_t>(srcRow, rowBytes);
     }
 
     // Some fully transparent bmp images are intended to be opaque.  Here, we
     // correct for this possibility.
-    dstRow = (SkPMColor*) dst;
     if (transparent) {
+        const SkImageInfo& opaqueInfo =
+                dstInfo.makeAlphaType(kOpaque_SkAlphaType);
+        SkAutoTDelete<SkMaskSwizzler> opaqueSwizzler(
+                SkMaskSwizzler::CreateMaskSwizzler(opaqueInfo, dst, dstRowBytes,
+                                                   fMasks, fBitsPerPixel));
+        srcRow = srcBuffer.get();
         for (int y = 0; y < height; y++) {
-            for (int x = 0; x < width; x++) {
-                dstRow[x] |= 0xFF000000;
-            }
-            dstRow = SkTAddOffset<SkPMColor>(dstRow, dstRowBytes);
+            // Decode the row in opaque format
+            int row = kBottomUp_RowOrder == fRowOrder ? height - 1 - y : y;
+            opaqueSwizzler->next(srcRow, row);
+
+            // Move to the next row
+            srcRow = SkTAddOffset<uint8_t>(srcRow, rowBytes);
         }
     }
 
@@ -597,13 +642,78 @@
  * Set an RLE pixel using the color table
  *
  */
-void SkBmpCodec::setRLEPixel(SkPMColor* dst, size_t dstRowBytes, int height,
-                             uint32_t x, uint32_t y, uint8_t index) {
+void SkBmpCodec::setRLEPixel(SkPMColor* dst, size_t dstRowBytes,
+                             const SkImageInfo& dstInfo, uint32_t x, uint32_t y,
+                             uint8_t index) {
+    // Set the row
+    int height = dstInfo.height();
+    int row;
     if (kBottomUp_RowOrder == fRowOrder) {
-        y = height - y - 1;
+        row = height - y - 1;
+    } else {
+        row = y;
     }
-    SkPMColor* dstRow = SkTAddOffset<SkPMColor>(dst, y * dstRowBytes);
-    dstRow[x] = fColorTable.get()[index];
+
+    // Set the pixel based on destination color type
+    switch (dstInfo.colorType()) {
+        case kN32_SkColorType: {
+            SkPMColor* dstRow = SkTAddOffset<SkPMColor>(dst,
+                    row * (int) dstRowBytes);
+            dstRow[x] = fColorTable->operator[](index);
+            break;
+        }
+        case kRGB_565_SkColorType: {
+            uint16_t* dstRow = SkTAddOffset<uint16_t>(dst,
+                    row * (int) dstRowBytes);
+            dstRow[x] = SkPixel32ToPixel16(fColorTable->operator[](index));
+            break;
+        }
+        default:
+            // This case should not be reached.  We should catch an invalid
+            // color type when we check that the conversion is possible.
+            SkASSERT(false);
+            break;
+    }
+}
+
+/*
+ *
+ * Set an RLE pixel from R, G, B values
+ *
+ */
+void SkBmpCodec::setRLE24Pixel(SkPMColor* dst, size_t dstRowBytes,
+                               const SkImageInfo& dstInfo, uint32_t x,
+                               uint32_t y, uint8_t red, uint8_t green,
+                               uint8_t blue) {
+    // Set the row
+    int height = dstInfo.height();
+    int row;
+    if (kBottomUp_RowOrder == fRowOrder) {
+        row = height - y - 1;
+    } else {
+        row = y;
+    }
+
+    // Set the pixel based on destination color type
+    switch (dstInfo.colorType()) {
+        case kN32_SkColorType: {
+            SkPMColor* dstRow = SkTAddOffset<SkPMColor>(dst,
+                    row * (int) dstRowBytes);
+            dstRow[x] = SkPackARGB32NoCheck(0xFF, red, green, blue);
+            break;
+        }
+        case kRGB_565_SkColorType: {
+            uint16_t* dstRow = SkTAddOffset<uint16_t>(dst,
+                    row * (int) dstRowBytes);
+            dstRow[x] = SkPack888ToRGB16(red, green, blue);
+            break;
+        }
+        default:
+            // This case should not be reached.  We should catch an invalid
+            // color type when we check that the conversion is possible.
+            SkASSERT(false);
+            break;
+    }
 }
 
 /*
@@ -626,9 +736,9 @@
 
     // Input buffer parameters
     uint32_t currByte = 0;
-    SkAutoTDeleteArray<uint8_t> buffer(SkNEW_ARRAY(uint8_t, fRemainingBytes));
-    size_t totalBytes = stream()->read(buffer.get(), fRemainingBytes);
-    if ((uint32_t) totalBytes < fRemainingBytes) {
+    SkAutoTDeleteArray<uint8_t> buffer(SkNEW_ARRAY(uint8_t, fRLEBytes));
+    size_t totalBytes = stream()->read(buffer.get(), fRLEBytes);
+    if (totalBytes < fRLEBytes) {
         SkDebugf("Warning: incomplete RLE file.\n");
     } else if (totalBytes <= 0) {
         SkDebugf("Error: could not read RLE image data.\n");
@@ -707,18 +817,16 @@
                         return kIncompleteInput;
                     }
                     // Set numPixels number of pixels
-                    SkPMColor* dstRow = SkTAddOffset<SkPMColor>(
-                            dstPtr, y * dstRowBytes);
                     while (numPixels > 0) {
                         switch(fBitsPerPixel) {
                             case 4: {
                                 SkASSERT(currByte < totalBytes);
                                 uint8_t val = buffer.get()[currByte++];
-                                setRLEPixel(dstPtr, dstRowBytes, height, x++, y,
-                                        val >> 4);
+                                setRLEPixel(dstPtr, dstRowBytes, dstInfo, x++,
+                                        y, val >> 4);
                                 numPixels--;
                                 if (numPixels != 0) {
-                                    setRLEPixel(dstPtr, dstRowBytes, height,
+                                    setRLEPixel(dstPtr, dstRowBytes, dstInfo,
                                             x++, y, val & 0xF);
                                     numPixels--;
                                 }
@@ -726,8 +834,8 @@
                             }
                             case 8:
                                 SkASSERT(currByte < totalBytes);
-                                setRLEPixel(dstPtr, dstRowBytes, height, x++, y,
-                                        buffer.get()[currByte++]);
+                                setRLEPixel(dstPtr, dstRowBytes, dstInfo, x++,
+                                        y, buffer.get()[currByte++]);
                                 numPixels--;
                                 break;
                             case 24: {
@@ -735,9 +843,8 @@
                                 uint8_t blue = buffer.get()[currByte++];
                                 uint8_t green = buffer.get()[currByte++];
                                 uint8_t red = buffer.get()[currByte++];
-                                SkPMColor color = SkPackARGB32NoCheck(
-                                        0xFF, red, green, blue);
-                                dstRow[x++] = color;
+                                setRLE24Pixel(dstPtr, dstRowBytes, dstInfo,
+                                            x++, y, red, green, blue);
                                 numPixels--;
                             }
                             default:
@@ -771,11 +878,9 @@
                 uint8_t blue = task;
                 uint8_t green = buffer.get()[currByte++];
                 uint8_t red = buffer.get()[currByte++];
-                SkPMColor color = SkPackARGB32NoCheck(0xFF, red, green, blue);
-                SkPMColor* dstRow =
-                        SkTAddOffset<SkPMColor>(dstPtr, y * dstRowBytes);
                 while (x < endX) {
-                    dstRow[x++] = color;
+                    setRLE24Pixel(dstPtr, dstRowBytes, dstInfo, x++, y, red,
+                            green, blue);
                 }
             } else {
                 // In RLE8 or RLE4, the second byte read gives the index in the
@@ -791,7 +896,7 @@
 
                 // Set the indicated number of pixels
                 for (int which = 0; x < endX; x++) {
-                    setRLEPixel(dstPtr, dstRowBytes, height, x, y,
+                    setRLEPixel(dstPtr, dstRowBytes, dstInfo, x, y,
                             indices[which]);
                     which = !which;
                 }
@@ -811,7 +916,6 @@
     const int width = dstInfo.width();
     const int height = dstInfo.height();
     const size_t rowBytes = SkAlign4(compute_row_bytes(width, fBitsPerPixel));
-    const uint32_t alphaMask = fMasks->getAlphaMask();
 
     // Get swizzler configuration
     SkSwizzler::SrcConfig config;
@@ -832,7 +936,7 @@
             config = SkSwizzler::kBGR;
             break;
         case 32:
-            if (0 == alphaMask) {
+            if (kOpaque_SkAlphaType == dstInfo.alphaType()) {
                 config = SkSwizzler::kBGRX;
             } else {
                 config = SkSwizzler::kBGRA;
@@ -844,8 +948,9 @@
     }
 
     // Create swizzler
-    SkSwizzler* swizzler = SkSwizzler::CreateSwizzler(config, fColorTable.get(),
-            dstInfo, dst, dstRowBytes, SkImageGenerator::kNo_ZeroInitialized);
+    SkAutoTDelete<SkSwizzler> swizzler(SkSwizzler::CreateSwizzler(config,
+            fColorTable->readColors(), dstInfo, dst, dstRowBytes,
+            SkImageGenerator::kNo_ZeroInitialized));
 
     // Allocate space for a row buffer and a source for the swizzler
     SkAutoTDeleteArray<uint8_t> srcBuffer(SkNEW_ARRAY(uint8_t, rowBytes));
diff --git a/src/codec/SkCodec_libbmp.h b/src/codec/SkCodec_libbmp.h
index 21dab1a..e6620d2 100644
--- a/src/codec/SkCodec_libbmp.h
+++ b/src/codec/SkCodec_libbmp.h
@@ -6,6 +6,7 @@
  */
 
 #include "SkCodec.h"
+#include "SkColorTable.h"
 #include "SkImageInfo.h"
 #include "SkMaskSwizzler.h"
 #include "SkStream.h"
@@ -75,6 +76,13 @@
 
     /*
      *
+     * Creates the color table
+     *
+     */
+     bool createColorTable(SkAlphaType alphaType);
+
+    /*
+     *
      * Performs the bitmap decoding for bit masks input format
      *
      */
@@ -86,8 +94,17 @@
      * Set an RLE pixel using the color table
      *
      */
-    void setRLEPixel(SkPMColor* dst, size_t dstRowBytes, int height,
-                     uint32_t x, uint32_t y, uint8_t index);
+    void setRLEPixel(SkPMColor* dst, size_t dstRowBytes,
+                     const SkImageInfo& dstInfo, uint32_t x, uint32_t y,
+                     uint8_t index);
+    /*
+     *
+     * Set an RLE24 pixel from R, G, B values
+     *
+     */
+    void setRLE24Pixel(SkPMColor* dst, size_t dstRowBytes,
+                       const SkImageInfo& dstInfo, uint32_t x, uint32_t y,
+                       uint8_t red, uint8_t green, uint8_t blue);
 
     /*
      *
@@ -115,11 +132,13 @@
      * @param format the format of the bmp file
      * @param masks optional color masks for certain bmp formats, passes
                     ownership to SkBmpCodec
-     * @param colorTable array representing the color table for index-based bmp
-     *                   formats, colors are unpremultiplied, passes ownership
-     *                   to SkBmpCodec
+     * @param numColors the number of colors in the color table
+     * @param bytesPerColor the number of bytes in the stream used to represent
+                            each color in the color table
+     * @param offset the offset of the image pixel data from the end of the
+     *               headers
      * @param rowOrder indicates whether rows are ordered top-down or bottom-up
-     * @param remainingBytes used only for RLE decodes, as we must decode all
+     * @param RLEBytes used only for RLE decodes, as we must decode all
      *                  of the data at once rather than row by row
      *                  it indicates the amount of data left in the stream
      *                  after decoding the headers
@@ -127,16 +146,19 @@
      */
     SkBmpCodec(const SkImageInfo& srcInfo, SkStream* stream,
                uint16_t bitsPerPixel, BitmapInputFormat format,
-               SkMasks* masks, SkPMColor* colorTable,
-               RowOrder rowOrder, uint32_t remainingBytes);
+               SkMasks* masks, uint32_t numColors, uint32_t bytesPerColor,
+               uint32_t offset, RowOrder rowOrder, size_t RLEByes);
 
     // Fields
     const uint16_t                      fBitsPerPixel;
     const BitmapInputFormat             fInputFormat;
     SkAutoTDelete<SkMasks>              fMasks;          // owned
-    const SkAutoTDeleteArray<SkPMColor> fColorTable;     // owned, unpremul
+    SkAutoTDelete<SkColorTable>         fColorTable;     // owned
+    uint32_t                            fNumColors;
+    const uint32_t                      fBytesPerColor;
+    const uint32_t                      fOffset;
     const RowOrder                      fRowOrder;
-    const uint32_t                      fRemainingBytes;
+    const size_t                        fRLEBytes;
 
     typedef SkCodec INHERITED;
 };
diff --git a/src/codec/SkCodec_libpng.cpp b/src/codec/SkCodec_libpng.cpp
index bf0647d..57653e7 100644
--- a/src/codec/SkCodec_libpng.cpp
+++ b/src/codec/SkCodec_libpng.cpp
@@ -347,19 +347,19 @@
 // Getting the pixels
 ///////////////////////////////////////////////////////////////////////////////
 
-static bool conversion_possible(const SkImageInfo& A, const SkImageInfo& B) {
+static bool conversion_possible(const SkImageInfo& dst, const SkImageInfo& src) {
     // TODO: Support other conversions
-    if (A.colorType() != B.colorType()) {
+    if (dst.colorType() != src.colorType()) {
         return false;
     }
-    if (A.profileType() != B.profileType()) {
+    if (dst.profileType() != src.profileType()) {
         return false;
     }
-    if (A.alphaType() == B.alphaType()) {
+    if (dst.alphaType() == src.alphaType()) {
         return true;
     }
-    return premul_and_unpremul(A.alphaType(), B.alphaType())
-            || premul_and_unpremul(B.alphaType(), A.alphaType());
+    return kPremul_SkAlphaType == dst.alphaType() &&
+            kUnpremul_SkAlphaType == src.alphaType();
 }
 
 SkCodec::Result SkPngCodec::onGetPixels(const SkImageInfo& requestedInfo, void* dst,
diff --git a/src/codec/SkMaskSwizzler.cpp b/src/codec/SkMaskSwizzler.cpp
index 8d9f6c6..944042d 100644
--- a/src/codec/SkMaskSwizzler.cpp
+++ b/src/codec/SkMaskSwizzler.cpp
@@ -9,12 +9,7 @@
 #include "SkColorPriv.h"
 #include "SkMaskSwizzler.h"
 
-/*
- *
- * Row procedure for masked color components with 16 bits per pixel
- *
- */
-static SkSwizzler::ResultAlpha swizzle_mask16_to_n32(
+static SkSwizzler::ResultAlpha swizzle_mask16_to_n32_opaque(
         void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks) {
 
     // Use the masks to decode to the destination
@@ -30,12 +25,7 @@
     return SkSwizzler::kOpaque_ResultAlpha;
 }
 
-/*
- *
- * Row procedure for masked color components with 16 bits per pixel with alpha
- *
- */
-static SkSwizzler::ResultAlpha swizzle_mask16_alpha_to_n32(
+static SkSwizzler::ResultAlpha swizzle_mask16_to_n32_unpremul(
         void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks) {
 
     // Use the masks to decode to the destination
@@ -54,12 +44,42 @@
     return COMPUTE_RESULT_ALPHA;
 }
 
-/*
- *
- * Row procedure for masked color components with 24 bits per pixel
- *
- */
-static SkSwizzler::ResultAlpha swizzle_mask24_to_n32(
+static SkSwizzler::ResultAlpha swizzle_mask16_to_n32_premul(
+        void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks) {
+
+    // Use the masks to decode to the destination
+    uint16_t* srcPtr = (uint16_t*) srcRow;
+    SkPMColor* dstPtr = (SkPMColor*) dstRow;
+    INIT_RESULT_ALPHA;
+    for (int i = 0; i < width; i++) {
+        uint16_t p = srcPtr[i];
+        uint8_t red = masks->getRed(p);
+        uint8_t green = masks->getGreen(p);
+        uint8_t blue = masks->getBlue(p);
+        uint8_t alpha = masks->getAlpha(p);
+        UPDATE_RESULT_ALPHA(alpha);
+        dstPtr[i] = SkPreMultiplyARGB(alpha, red, green, blue);
+    }
+    return COMPUTE_RESULT_ALPHA;
+}
+
+static SkSwizzler::ResultAlpha swizzle_mask16_to_565(
+        void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks) {
+
+    // Use the masks to decode to the destination
+    uint16_t* srcPtr = (uint16_t*) srcRow;
+    uint16_t* dstPtr = (uint16_t*) dstRow;
+    for (int i = 0; i < width; i++) {
+        uint16_t p = srcPtr[i];
+        uint8_t red = masks->getRed(p);
+        uint8_t green = masks->getGreen(p);
+        uint8_t blue = masks->getBlue(p);
+        dstPtr[i] = SkPack888ToRGB16(red, green, blue);
+    }
+    return SkSwizzler::kOpaque_ResultAlpha;
+}
+
+static SkSwizzler::ResultAlpha swizzle_mask24_to_n32_opaque(
         void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks) {
 
     // Use the masks to decode to the destination
@@ -74,12 +94,7 @@
     return SkSwizzler::kOpaque_ResultAlpha;
 }
 
-/*
- *
- * Row procedure for masked color components with 24 bits per pixel with alpha
- *
- */
-static SkSwizzler::ResultAlpha swizzle_mask24_alpha_to_n32(
+static SkSwizzler::ResultAlpha swizzle_mask24_to_n32_unpremul(
         void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks) {
 
     // Use the masks to decode to the destination
@@ -97,12 +112,40 @@
     return COMPUTE_RESULT_ALPHA;
 }
 
-/*
- *
- * Row procedure for masked color components with 32 bits per pixel
- *
- */
-static SkSwizzler::ResultAlpha swizzle_mask32_to_n32(
+static SkSwizzler::ResultAlpha swizzle_mask24_to_n32_premul(
+        void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks) {
+
+    // Use the masks to decode to the destination
+    SkPMColor* dstPtr = (SkPMColor*) dstRow;
+    INIT_RESULT_ALPHA;
+    for (int i = 0; i < 3*width; i += 3) {
+        uint32_t p = srcRow[i] | (srcRow[i + 1] << 8) | srcRow[i + 2] << 16;
+        uint8_t red = masks->getRed(p);
+        uint8_t green = masks->getGreen(p);
+        uint8_t blue = masks->getBlue(p);
+        uint8_t alpha = masks->getAlpha(p);
+        UPDATE_RESULT_ALPHA(alpha);
+        dstPtr[i/3] = SkPreMultiplyARGB(alpha, red, green, blue);
+    }
+    return COMPUTE_RESULT_ALPHA;
+}
+
+static SkSwizzler::ResultAlpha swizzle_mask24_to_565(
+        void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks) {
+
+    // Use the masks to decode to the destination
+    uint16_t* dstPtr = (uint16_t*) dstRow;
+    for (int i = 0; i < 3*width; i += 3) {
+        uint32_t p = srcRow[i] | (srcRow[i + 1] << 8) | srcRow[i + 2] << 16;
+        uint8_t red = masks->getRed(p);
+        uint8_t green = masks->getGreen(p);
+        uint8_t blue = masks->getBlue(p);
+        dstPtr[i/3] = SkPack888ToRGB16(red, green, blue);
+    }
+    return SkSwizzler::kOpaque_ResultAlpha;
+}
+
+static SkSwizzler::ResultAlpha swizzle_mask32_to_n32_opaque(
         void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks) {
 
     // Use the masks to decode to the destination
@@ -118,12 +161,7 @@
     return SkSwizzler::kOpaque_ResultAlpha;
 }
 
-/*
- *
- * Row procedure for masked color components with 32 bits per pixel
- *
- */
-static SkSwizzler::ResultAlpha swizzle_mask32_alpha_to_n32(
+static SkSwizzler::ResultAlpha swizzle_mask32_to_n32_unpremul(
         void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks) {
 
     // Use the masks to decode to the destination
@@ -142,44 +180,148 @@
     return COMPUTE_RESULT_ALPHA;
 }
 
+static SkSwizzler::ResultAlpha swizzle_mask32_to_n32_premul(
+        void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks) {
+
+    // Use the masks to decode to the destination
+    uint32_t* srcPtr = (uint32_t*) srcRow;
+    SkPMColor* dstPtr = (SkPMColor*) dstRow;
+    INIT_RESULT_ALPHA;
+    for (int i = 0; i < width; i++) {
+        uint32_t p = srcPtr[i];
+        uint8_t red = masks->getRed(p);
+        uint8_t green = masks->getGreen(p);
+        uint8_t blue = masks->getBlue(p);
+        uint8_t alpha = masks->getAlpha(p);
+        UPDATE_RESULT_ALPHA(alpha);
+        dstPtr[i] = SkPreMultiplyARGB(alpha, red, green, blue);
+    }
+    return COMPUTE_RESULT_ALPHA;
+}
+
+static SkSwizzler::ResultAlpha swizzle_mask32_to_565(
+        void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks) {
+
+    // Use the masks to decode to the destination
+    uint32_t* srcPtr = (uint32_t*) srcRow;
+    uint16_t* dstPtr = (uint16_t*) dstRow;
+    for (int i = 0; i < width; i++) {
+        uint32_t p = srcPtr[i];
+        uint8_t red = masks->getRed(p);
+        uint8_t green = masks->getGreen(p);
+        uint8_t blue = masks->getBlue(p);
+        dstPtr[i] = SkPack888ToRGB16(red, green, blue);
+    }
+    return SkSwizzler::kOpaque_ResultAlpha;
+}
+
 /*
  *
  * Create a new mask swizzler
  *
  */
 SkMaskSwizzler* SkMaskSwizzler::CreateMaskSwizzler(
-        const SkImageInfo& imageInfo, SkMasks* masks, uint32_t bitsPerPixel) {
+        const SkImageInfo& info, void* dst, size_t dstRowBytes, SkMasks* masks,
+        uint32_t bitsPerPixel) {
 
     // Choose the appropriate row procedure
     RowProc proc = NULL;
-    uint32_t alphaMask = masks->getAlphaMask();
     switch (bitsPerPixel) {
         case 16:
-            if (0 == alphaMask) {
-                proc = &swizzle_mask16_to_n32;
-            } else {
-                proc = &swizzle_mask16_alpha_to_n32;
+            switch (info.colorType()) {
+                case kN32_SkColorType:
+                    switch (info.alphaType()) {
+                        case kUnpremul_SkAlphaType:
+                            proc = &swizzle_mask16_to_n32_unpremul;
+                            break;
+                        case kPremul_SkAlphaType:
+                            proc = &swizzle_mask16_to_n32_premul;
+                            break;
+                        case kOpaque_SkAlphaType:
+                            proc = &swizzle_mask16_to_n32_opaque;
+                            break;
+                        default:
+                            break;
+                    }
+                    break;
+                case kRGB_565_SkColorType:
+                    switch (info.alphaType()) {
+                        case kOpaque_SkAlphaType:
+                            proc = &swizzle_mask16_to_565;
+                            break;
+                        default:
+                            break;
+                    }
+                    break;
+                default:
+                    break;
             }
             break;
         case 24:
-            if (0 == alphaMask) {
-                proc = &swizzle_mask24_to_n32;
-            } else {
-                proc = &swizzle_mask24_alpha_to_n32;
+            switch (info.colorType()) {
+                case kN32_SkColorType:
+                    switch (info.alphaType()) {
+                        case kUnpremul_SkAlphaType:
+                            proc = &swizzle_mask24_to_n32_unpremul;
+                            break;
+                        case kPremul_SkAlphaType:
+                            proc = &swizzle_mask24_to_n32_premul;
+                            break;
+                        case kOpaque_SkAlphaType:
+                            proc = &swizzle_mask24_to_n32_opaque;
+                            break;
+                        default:
+                            break;
+                    }
+                    break;
+                case kRGB_565_SkColorType:
+                    switch (info.alphaType()) {
+                        case kOpaque_SkAlphaType:
+                            proc = &swizzle_mask24_to_565;
+                            break;
+                        default:
+                            break;
+                    }
+                    break;
+                default:
+                    break;
             }
             break;
         case 32:
-            if (0 == alphaMask) {
-                proc = &swizzle_mask32_to_n32;
-            } else {
-                proc = &swizzle_mask32_alpha_to_n32;
+            switch (info.colorType()) {
+                case kN32_SkColorType:
+                    switch (info.alphaType()) {
+                        case kUnpremul_SkAlphaType:
+                            proc = &swizzle_mask32_to_n32_unpremul;
+                            break;
+                        case kPremul_SkAlphaType:
+                            proc = &swizzle_mask32_to_n32_premul;
+                            break;
+                        case kOpaque_SkAlphaType:
+                            proc = &swizzle_mask32_to_n32_opaque;
+                            break;
+                        default:
+                            break;
+                    }
+                    break;
+                case kRGB_565_SkColorType:
+                    switch (info.alphaType()) {
+                        case kOpaque_SkAlphaType:
+                            proc = &swizzle_mask32_to_565;
+                            break;
+                        default:
+                            break;
+                    }
+                    break;
+                default:
+                    break;
             }
             break;
         default:
             SkASSERT(false);
             return NULL;
     }
-    return SkNEW_ARGS(SkMaskSwizzler, (imageInfo, masks, proc));
+    return SkNEW_ARGS(SkMaskSwizzler, (info, dst, dstRowBytes, masks, proc));
 }
 
 /*
@@ -187,19 +329,25 @@
  * Constructor for mask swizzler
  *
  */
-SkMaskSwizzler::SkMaskSwizzler(const SkImageInfo& imageInfo,
-                               SkMasks* masks, RowProc proc)
-    : fImageInfo(imageInfo)
+SkMaskSwizzler::SkMaskSwizzler(const SkImageInfo& dstInfo, void* dst,
+                               size_t dstRowBytes, SkMasks* masks, RowProc proc)
+    : fDstInfo(dstInfo)
+    , fDst(dst)
+    , fDstRowBytes(dstRowBytes)
     , fMasks(masks)
     , fRowProc(proc)
 {}
 
 /*
  *
- * Swizzle the next row
+ * Swizzle the specified row
  *
  */
-SkSwizzler::ResultAlpha SkMaskSwizzler::next(void* dst,
-                                             const uint8_t* src) {
-    return fRowProc(dst, src, fImageInfo.width(), fMasks);
+SkSwizzler::ResultAlpha SkMaskSwizzler::next(const uint8_t* SK_RESTRICT src,
+        int y) {
+    // Choose the row
+    void* row = SkTAddOffset<void>(fDst, y*fDstRowBytes);
+
+    // Decode the row
+    return fRowProc(row, src, fDstInfo.width(), fMasks);
 }
diff --git a/src/codec/SkMaskSwizzler.h b/src/codec/SkMaskSwizzler.h
index 9351f02..6910302 100644
--- a/src/codec/SkMaskSwizzler.h
+++ b/src/codec/SkMaskSwizzler.h
@@ -25,15 +25,16 @@
      *
      */
     static SkMaskSwizzler* CreateMaskSwizzler(const SkImageInfo& imageInfo,
+                                              void* dst, size_t dstRowBytes,
                                               SkMasks* masks,
                                               uint32_t bitsPerPixel);
 
     /*
      *
-     * Swizzle the next row
+     * Swizzle the row with the specified y value
      *
      */
-    SkSwizzler::ResultAlpha next(void* dst, const uint8_t* src);
+    SkSwizzler::ResultAlpha next(const uint8_t* SK_RESTRICT src, int y);
 
 private:
 
@@ -51,10 +52,13 @@
      * Constructor for mask swizzler
      *
      */
-    SkMaskSwizzler(const SkImageInfo& info, SkMasks* masks, RowProc proc);
+    SkMaskSwizzler(const SkImageInfo& info, void* dst, size_t dstRowBytes,
+            SkMasks* masks, RowProc proc);
 
     // Fields
-    const SkImageInfo& fImageInfo;
-    SkMasks*           fMasks;     // unowned
+    const SkImageInfo& fDstInfo;
+    void*              fDst;
+    size_t             fDstRowBytes;
+    SkMasks*           fMasks;       // unowned
     const RowProc      fRowProc;
 };
diff --git a/src/codec/SkSwizzler.cpp b/src/codec/SkSwizzler.cpp
index 1aa3793..351b3be 100644
--- a/src/codec/SkSwizzler.cpp
+++ b/src/codec/SkSwizzler.cpp
@@ -44,6 +44,28 @@
     return COMPUTE_RESULT_ALPHA;
 }
 
+static SkSwizzler::ResultAlpha swizzle_small_index_to_565(
+        void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width,
+        int bitsPerPixel, int y, const SkPMColor ctable[]) {
+
+    uint16_t* SK_RESTRICT dst = (uint16_t*) dstRow;
+    const uint32_t pixelsPerByte = 8 / bitsPerPixel;
+    const size_t rowBytes = compute_row_bytes_ppb(width, pixelsPerByte);
+    const uint8_t mask = (1 << bitsPerPixel) - 1;
+    int x = 0;
+    for (uint32_t byte = 0; byte < rowBytes; byte++) {
+        uint8_t pixelData = src[byte];
+        for (uint32_t p = 0; p < pixelsPerByte && x < width; p++) {
+            uint8_t index = (pixelData >> (8 - bitsPerPixel)) & mask;
+            uint16_t c = SkPixel32ToPixel16(ctable[index]);
+            dst[x] = c;
+            pixelData <<= bitsPerPixel;
+            x++;
+        }
+    }
+    return SkSwizzler::kOpaque_ResultAlpha;
+}
+
 // kIndex
 
 static SkSwizzler::ResultAlpha swizzle_index_to_n32(
@@ -78,6 +100,19 @@
     return COMPUTE_RESULT_ALPHA;
 }
 
+static SkSwizzler::ResultAlpha swizzle_index_to_565(
+        void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width,
+        int bytesPerPixel, int y, const SkPMColor ctable[]) {
+
+    uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow;
+    for (int x = 0; x < width; x++) {
+        uint16_t c = SkPixel32ToPixel16(ctable[*src]);
+        dst[x] = c;
+        src++;
+    }
+    return SkSwizzler::kOpaque_ResultAlpha;
+}
+
 #undef A32_MASK_IN_PLACE
 
 static SkSwizzler::ResultAlpha swizzle_bgrx_to_n32(
@@ -92,9 +127,21 @@
     return SkSwizzler::kOpaque_ResultAlpha;
 }
 
+static SkSwizzler::ResultAlpha swizzle_bgrx_to_565(
+        void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width,
+        int bytesPerPixel, int y, const SkPMColor ctable[]) {
+
+    uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow;
+    for (int x = 0; x < width; x++) {
+        dst[x] = SkPack888ToRGB16(src[2], src[1], src[0]);
+        src += bytesPerPixel;
+    }
+    return SkSwizzler::kOpaque_ResultAlpha;
+}
+
 // kBGRA
 
-static SkSwizzler::ResultAlpha swizzle_bgra_to_n32(
+static SkSwizzler::ResultAlpha swizzle_bgra_to_n32_unpremul(
         void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width,
         int bytesPerPixel, int y, const SkPMColor ctable[]) {
 
@@ -109,6 +156,21 @@
     return COMPUTE_RESULT_ALPHA;
 }
 
+static SkSwizzler::ResultAlpha swizzle_bgra_to_n32_premul(
+        void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width,
+        int bytesPerPixel, int y, const SkPMColor ctable[]) {
+
+    SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
+    INIT_RESULT_ALPHA;
+    for (int x = 0; x < width; x++) {
+        uint8_t alpha = src[3];
+        UPDATE_RESULT_ALPHA(alpha);
+        dst[x] = SkPreMultiplyARGB(alpha, src[2], src[1], src[0]);
+        src += bytesPerPixel;
+    }
+    return COMPUTE_RESULT_ALPHA;
+}
+
 // n32
 static SkSwizzler::ResultAlpha swizzle_rgbx_to_n32(
         void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width,
@@ -220,6 +282,9 @@
                 case kN32_SkColorType:
                     proc = &swizzle_small_index_to_n32;
                     break;
+                case kRGB_565_SkColorType:
+                    proc = &swizzle_small_index_to_565;
+                    break;
                 default:
                     break;
             }
@@ -230,10 +295,15 @@
                     // We assume the color premultiplied ctable (or not) as desired.
                     if (SkImageGenerator::kYes_ZeroInitialized == zeroInit) {
                         proc = &swizzle_index_to_n32_skipZ;
+                        break;
                     } else {
                         proc = &swizzle_index_to_n32;
+                        break;
                     }
                     break;
+                case kRGB_565_SkColorType:
+                    proc = &swizzle_index_to_565;
+                    break;
                 default:
                     break;
             }
@@ -244,6 +314,9 @@
                 case kN32_SkColorType:
                     proc = &swizzle_bgrx_to_n32;
                     break;
+                case kRGB_565_SkColorType:
+                    proc = &swizzle_bgrx_to_565;
+                    break;
                 default:
                     break;
             }
@@ -251,7 +324,16 @@
         case kBGRA:
             switch (info.colorType()) {
                 case kN32_SkColorType:
-                    proc = &swizzle_bgra_to_n32;
+                    switch (info.alphaType()) {
+                        case kUnpremul_SkAlphaType:
+                            proc = &swizzle_bgra_to_n32_unpremul;
+                            break;
+                        case kPremul_SkAlphaType:
+                            proc = &swizzle_bgra_to_n32_premul;
+                            break;
+                        default:
+                            break;
+                    }
                     break;
                 default:
                     break;