aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar msarett <msarett@google.com>2015-03-18 11:11:19 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2015-03-18 11:11:19 -0700
commiteed039b5ffbdff958053ac80b09451ad6caa1787 (patch)
tree231161cc1da391effd685a5b69aeb6259c7b8d1d /src
parentc88e11508739f53514228f1ea487af3d7eef7f3e (diff)
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
Diffstat (limited to 'src')
-rw-r--r--src/codec/SkCodecPriv.h9
-rw-r--r--src/codec/SkCodec_libbmp.cpp375
-rw-r--r--src/codec/SkCodec_libbmp.h42
-rw-r--r--src/codec/SkCodec_libpng.cpp12
-rw-r--r--src/codec/SkMaskSwizzler.cpp264
-rw-r--r--src/codec/SkMaskSwizzler.h14
-rw-r--r--src/codec/SkSwizzler.cpp86
7 files changed, 577 insertions, 225 deletions
diff --git a/src/codec/SkCodecPriv.h b/src/codec/SkCodecPriv.h
index a0e5c94900..7c57a9fe77 100644
--- a/src/codec/SkCodecPriv.h
+++ b/src/codec/SkCodecPriv.h
@@ -65,15 +65,6 @@ static inline size_t compute_row_bytes(int width, uint32_t bitsPerPixel) {
/*
*
- * 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 a96cd665b8..62cda95733 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 @@ SkCodec* SkBmpCodec::NewFromStream(SkStream* stream) {
// 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 @@ SkCodec* SkBmpCodec::NewFromStream(SkStream* stream) {
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");
+ // 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;
- // Remaining bytes is only used for RLE
- const int remainingBytes = totalBytes - offset;
- if (remainingBytes <= 0 && kRLE_BitmapInputFormat == inputFormat) {
- SkDebugf("Error: RLE requires valid input size.\n");
+ // 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 @@ SkCodec* SkBmpCodec::NewFromStream(SkStream* stream) {
*/
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 @@ SkCodec::Result SkBmpCodec::onGetPixels(const SkImageInfo& dstInfo,
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 @@ SkCodec::Result SkBmpCodec::onGetPixels(const SkImageInfo& dstInfo,
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 @@ SkCodec::Result SkBmpCodec::onGetPixels(const SkImageInfo& dstInfo,
/*
*
+ * 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 @@ SkCodec::Result SkBmpCodec::decodeMask(const SkImageInfo& dstInfo,
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 @@ SkCodec::Result SkBmpCodec::decodeMask(const SkImageInfo& dstInfo,
* 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;
+ }
+
+ // 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;
}
- SkPMColor* dstRow = SkTAddOffset<SkPMColor>(dst, y * dstRowBytes);
- dstRow[x] = fColorTable.get()[index];
}
/*
@@ -626,9 +736,9 @@ SkCodec::Result SkBmpCodec::decodeRLE(const SkImageInfo& dstInfo,
// 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 @@ SkCodec::Result SkBmpCodec::decodeRLE(const SkImageInfo& dstInfo,
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 @@ SkCodec::Result SkBmpCodec::decodeRLE(const SkImageInfo& dstInfo,
}
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 @@ SkCodec::Result SkBmpCodec::decodeRLE(const SkImageInfo& dstInfo,
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 @@ SkCodec::Result SkBmpCodec::decodeRLE(const SkImageInfo& dstInfo,
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 @@ SkCodec::Result SkBmpCodec::decodeRLE(const SkImageInfo& dstInfo,
// 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 @@ SkCodec::Result SkBmpCodec::decode(const SkImageInfo& dstInfo,
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 @@ SkCodec::Result SkBmpCodec::decode(const SkImageInfo& dstInfo,
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 @@ SkCodec::Result SkBmpCodec::decode(const SkImageInfo& dstInfo,
}
// 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 21dab1a4d9..e6620d275d 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 @@ private:
/*
*
+ * Creates the color table
+ *
+ */
+ bool createColorTable(SkAlphaType alphaType);
+
+ /*
+ *
* Performs the bitmap decoding for bit masks input format
*
*/
@@ -86,8 +94,17 @@ private:
* 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 @@ private:
* @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 @@ private:
*/
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 bf0647dd24..57653e74df 100644
--- a/src/codec/SkCodec_libpng.cpp
+++ b/src/codec/SkCodec_libpng.cpp
@@ -347,19 +347,19 @@ SkPngCodec::~SkPngCodec() {
// 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 8d9f6c66b3..944042d1ab 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 @@ static SkSwizzler::ResultAlpha swizzle_mask16_to_n32(
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 @@ static SkSwizzler::ResultAlpha swizzle_mask16_alpha_to_n32(
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 @@ static SkSwizzler::ResultAlpha swizzle_mask24_to_n32(
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 @@ static SkSwizzler::ResultAlpha swizzle_mask24_alpha_to_n32(
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 @@ static SkSwizzler::ResultAlpha swizzle_mask32_to_n32(
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 @@ static SkSwizzler::ResultAlpha swizzle_mask32_alpha_to_n32(
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 @@ SkMaskSwizzler* SkMaskSwizzler::CreateMaskSwizzler(
* 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 9351f0228b..69103023c6 100644
--- a/src/codec/SkMaskSwizzler.h
+++ b/src/codec/SkMaskSwizzler.h
@@ -25,15 +25,16 @@ public:
*
*/
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 @@ private:
* 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 1aa3793f15..351b3be1d2 100644
--- a/src/codec/SkSwizzler.cpp
+++ b/src/codec/SkSwizzler.cpp
@@ -44,6 +44,28 @@ static SkSwizzler::ResultAlpha swizzle_small_index_to_n32(
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 @@ static SkSwizzler::ResultAlpha swizzle_index_to_n32_skipZ(
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 @@ static SkSwizzler::ResultAlpha swizzle_bgrx_to_n32(
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 @@ static SkSwizzler::ResultAlpha swizzle_bgra_to_n32(
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 @@ SkSwizzler* SkSwizzler::CreateSwizzler(SkSwizzler::SrcConfig sc,
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 @@ SkSwizzler* SkSwizzler::CreateSwizzler(SkSwizzler::SrcConfig sc,
// 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 @@ SkSwizzler* SkSwizzler::CreateSwizzler(SkSwizzler::SrcConfig sc,
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 @@ SkSwizzler* SkSwizzler::CreateSwizzler(SkSwizzler::SrcConfig sc,
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;