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
This commit is contained in:
parent
c88e115087
commit
eed039b5ff
@ -63,15 +63,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
|
||||
|
@ -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");
|
||||
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 @@ 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);
|
||||
@ -529,6 +488,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));
|
||||
|
@ -6,6 +6,7 @@
|
||||
*/
|
||||
|
||||
#include "SkCodec.h"
|
||||
#include "SkColorTable.h"
|
||||
#include "SkImageInfo.h"
|
||||
#include "SkMaskSwizzler.h"
|
||||
#include "SkStream.h"
|
||||
@ -73,6 +74,13 @@ private:
|
||||
kUnknown_BitmapInputFormat
|
||||
};
|
||||
|
||||
/*
|
||||
*
|
||||
* 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;
|
||||
};
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user