| Index: src/codec/SkBmpStandardCodec.cpp
|
| diff --git a/src/codec/SkBmpStandardCodec.cpp b/src/codec/SkBmpStandardCodec.cpp
|
| index 210498eb00f7439b8da7719e008d9fe5347371de..59bc917481698fb0a3caf5dab456312ac85631d7 100644
|
| --- a/src/codec/SkBmpStandardCodec.cpp
|
| +++ b/src/codec/SkBmpStandardCodec.cpp
|
| @@ -18,14 +18,15 @@
|
| SkBmpStandardCodec::SkBmpStandardCodec(const SkImageInfo& info, SkStream* stream,
|
| uint16_t bitsPerPixel, uint32_t numColors,
|
| uint32_t bytesPerColor, uint32_t offset,
|
| - SkBmpCodec::RowOrder rowOrder, bool inIco)
|
| + SkScanlineDecoder::SkScanlineOrder rowOrder, bool inIco)
|
| : INHERITED(info, stream, bitsPerPixel, rowOrder)
|
| , fColorTable(nullptr)
|
| , fNumColors(this->computeNumColors(numColors))
|
| , fBytesPerColor(bytesPerColor)
|
| , fOffset(offset)
|
| , fSwizzler(nullptr)
|
| - , fSrcBuffer(nullptr)
|
| + , fSrcRowBytes(SkAlign4(compute_row_bytes(this->getInfo().width(), this->bitsPerPixel())))
|
| + , fSrcBuffer(new uint8_t [fSrcRowBytes])
|
| , fInIco(inIco)
|
| {}
|
|
|
| @@ -53,23 +54,18 @@ SkCodec::Result SkBmpStandardCodec::onGetPixels(const SkImageInfo& dstInfo,
|
| return kInvalidConversion;
|
| }
|
|
|
| - // Create the color table if necessary and prepare the stream for decode
|
| - // Note that if it is non-nullptr, inputColorCount will be modified
|
| - if (!this->createColorTable(dstInfo.alphaType(), inputColorCount)) {
|
| - SkCodecPrintf("Error: could not create color table.\n");
|
| - return kInvalidInput;
|
| + Result result = this->prepareToDecode(dstInfo, opts, inputColorPtr, inputColorCount);
|
| + if (kSuccess != result) {
|
| + return result;
|
| }
|
| -
|
| - // Copy the color table to the client if necessary
|
| - copy_color_table(dstInfo, fColorTable, inputColorPtr, inputColorCount);
|
| -
|
| - // Initialize a swizzler if necessary
|
| - if (!this->initializeSwizzler(dstInfo, opts)) {
|
| - SkCodecPrintf("Error: cannot initialize swizzler.\n");
|
| - return kInvalidConversion;
|
| + result = this->decodeRows(dstInfo, dst, dstRowBytes, opts);
|
| + if (kSuccess != result) {
|
| + return result;
|
| }
|
| -
|
| - return this->decode(dstInfo, dst, dstRowBytes, opts);
|
| + if (fInIco) {
|
| + return this->decodeIcoMask(dstInfo, dst, dstRowBytes);
|
| + }
|
| + return kSuccess;
|
| }
|
|
|
| /*
|
| @@ -169,10 +165,6 @@ SkCodec::Result SkBmpStandardCodec::onGetPixels(const SkImageInfo& dstInfo,
|
|
|
| bool SkBmpStandardCodec::initializeSwizzler(const SkImageInfo& dstInfo,
|
| const Options& opts) {
|
| - // Allocate space for a row buffer
|
| - const size_t rowBytes = SkAlign4(compute_row_bytes(dstInfo.width(), this->bitsPerPixel()));
|
| - fSrcBuffer.reset(new uint8_t[rowBytes]);
|
| -
|
| // Get swizzler configuration
|
| SkSwizzler::SrcConfig config;
|
| switch (this->bitsPerPixel()) {
|
| @@ -216,122 +208,93 @@ bool SkBmpStandardCodec::initializeSwizzler(const SkImageInfo& dstInfo,
|
| return true;
|
| }
|
|
|
| -/*
|
| - * Choose a fill for failures due to an incomplete image. We will use zero as
|
| - * the default palette index, black for opaque images, and transparent for
|
| - * non-opaque images.
|
| - */
|
| -static uint32_t get_fill_color_or_index(uint16_t bitsPerPixels, SkAlphaType alphaType) {
|
| - uint32_t fillColorOrIndex;
|
| - switch (bitsPerPixels) {
|
| - case 1:
|
| - case 2:
|
| - case 4:
|
| - case 8:
|
| - fillColorOrIndex = 0;
|
| - break;
|
| - case 24:
|
| - fillColorOrIndex = SK_ColorBLACK;
|
| - break;
|
| - case 32:
|
| - if (kOpaque_SkAlphaType == alphaType) {
|
| - fillColorOrIndex = SK_ColorBLACK;
|
| - } else {
|
| - fillColorOrIndex = SK_ColorTRANSPARENT;
|
| - }
|
| - break;
|
| - default:
|
| - SkASSERT(false);
|
| - return 0;
|
| +SkCodec::Result SkBmpStandardCodec::prepareToDecode(const SkImageInfo& dstInfo,
|
| + const SkCodec::Options& options, SkPMColor inputColorPtr[], int* inputColorCount) {
|
| + // Create the color table if necessary and prepare the stream for decode
|
| + // Note that if it is non-NULL, inputColorCount will be modified
|
| + if (!this->createColorTable(dstInfo.alphaType(), inputColorCount)) {
|
| + SkCodecPrintf("Error: could not create color table.\n");
|
| + return SkCodec::kInvalidInput;
|
| }
|
| - return fillColorOrIndex;
|
| +
|
| + // Copy the color table to the client if necessary
|
| + copy_color_table(dstInfo, this->fColorTable, inputColorPtr, inputColorCount);
|
| +
|
| + // Initialize a swizzler if necessary
|
| + if (!this->initializeSwizzler(dstInfo, options)) {
|
| + SkCodecPrintf("Error: cannot initialize swizzler.\n");
|
| + return SkCodec::kInvalidConversion;
|
| + }
|
| + return SkCodec::kSuccess;
|
| }
|
|
|
| /*
|
| * Performs the bitmap decoding for standard input format
|
| */
|
| -SkCodec::Result SkBmpStandardCodec::decode(const SkImageInfo& dstInfo,
|
| - void* dst, size_t dstRowBytes,
|
| - const Options& opts) {
|
| - // Set constant values
|
| - const int width = dstInfo.width();
|
| - const int height = dstInfo.height();
|
| - const size_t rowBytes = SkAlign4(compute_row_bytes(width, this->bitsPerPixel()));
|
| -
|
| +SkCodec::Result SkBmpStandardCodec::decodeRows(const SkImageInfo& dstInfo,
|
| + void* dst, size_t dstRowBytes,
|
| + const Options& opts) {
|
| // Iterate over rows of the image
|
| + const int height = dstInfo.height();
|
| for (int y = 0; y < height; y++) {
|
| // Read a row of the input
|
| - if (this->stream()->read(fSrcBuffer.get(), rowBytes) != rowBytes) {
|
| + if (this->stream()->read(fSrcBuffer.get(), fSrcRowBytes) != fSrcRowBytes) {
|
| SkCodecPrintf("Warning: incomplete input stream.\n");
|
| // Fill the destination image on failure
|
| - // Get the fill color/index and check if it is 0
|
| - uint32_t fillColorOrIndex = get_fill_color_or_index(this->bitsPerPixel(),
|
| - dstInfo.alphaType());
|
| - bool zeroFill = (0 == fillColorOrIndex);
|
| -
|
| - if (kNo_ZeroInitialized == opts.fZeroInitialized || !zeroFill) {
|
| - // Get a pointer to the color table if it exists
|
| - const SkPMColor* colorPtr = get_color_ptr(fColorTable.get());
|
| -
|
| - void* dstStart = this->getDstStartRow(dst, dstRowBytes, y);
|
| - SkSwizzler::Fill(dstStart, dstInfo, dstRowBytes, dstInfo.height() - y,
|
| - fillColorOrIndex, colorPtr);
|
| - }
|
| + void* dstStart = this->getDstStartRow(dst, dstRowBytes, y);
|
| + const SkPMColor* colorPtr = get_color_ptr(fColorTable.get());
|
| + uint32_t fillColorOrIndex = get_fill_color_or_index(dstInfo.alphaType());
|
| + SkSwizzler::Fill(dstStart, dstInfo, dstRowBytes, dstInfo.height() - y,
|
| + fillColorOrIndex, colorPtr, opts.fZeroInitialized);
|
| return kIncompleteInput;
|
| }
|
|
|
| // Decode the row in destination format
|
| - uint32_t row;
|
| - if (SkBmpCodec::kTopDown_RowOrder == this->rowOrder()) {
|
| - row = y;
|
| - } else {
|
| - row = height - 1 - y;
|
| - }
|
| + uint32_t row = this->getDstRow(y, dstInfo.height());
|
|
|
| void* dstRow = SkTAddOffset<void>(dst, row * dstRowBytes);
|
| fSwizzler->swizzle(dstRow, fSrcBuffer.get());
|
| }
|
|
|
| - // Finally, apply the AND mask for bmp-in-ico images
|
| - if (fInIco) {
|
| - // BMP in ICO have transparency, so this cannot be 565, and this mask
|
| - // prevents us from using kIndex8. The below code depends on the output
|
| - // being an SkPMColor.
|
| - SkASSERT(dstInfo.colorType() == kN32_SkColorType);
|
| -
|
| - // The AND mask is always 1 bit per pixel
|
| - const size_t rowBytes = SkAlign4(compute_row_bytes(width, 1));
|
| + // Finished decoding the entire image
|
| + return kSuccess;
|
| +}
|
|
|
| - SkPMColor* dstPtr = (SkPMColor*) dst;
|
| - for (int y = 0; y < height; y++) {
|
| - // The srcBuffer will at least be large enough
|
| - if (stream()->read(fSrcBuffer.get(), rowBytes) != rowBytes) {
|
| - SkCodecPrintf("Warning: incomplete AND mask for bmp-in-ico.\n");
|
| - return kIncompleteInput;
|
| - }
|
| +// TODO (msarett): This function will need to be modified in order to perform row by row decodes
|
| +// when the Ico scanline decoder is implemented.
|
| +SkCodec::Result SkBmpStandardCodec::decodeIcoMask(const SkImageInfo& dstInfo,
|
| + void* dst, size_t dstRowBytes) {
|
| + // BMP in ICO have transparency, so this cannot be 565, and this mask
|
| + // prevents us from using kIndex8. The below code depends on the output
|
| + // being an SkPMColor.
|
| + SkASSERT(dstInfo.colorType() == kN32_SkColorType);
|
| +
|
| + // The AND mask is always 1 bit per pixel
|
| + const int width = this->getInfo().width();
|
| + const size_t rowBytes = SkAlign4(compute_row_bytes(width, 1));
|
| +
|
| + SkPMColor* dstPtr = (SkPMColor*) dst;
|
| + for (int y = 0; y < dstInfo.height(); y++) {
|
| + // The srcBuffer will at least be large enough
|
| + if (stream()->read(fSrcBuffer.get(), rowBytes) != rowBytes) {
|
| + SkCodecPrintf("Warning: incomplete AND mask for bmp-in-ico.\n");
|
| + return kIncompleteInput;
|
| + }
|
|
|
| - int row;
|
| - if (SkBmpCodec::kBottomUp_RowOrder == this->rowOrder()) {
|
| - row = height - y - 1;
|
| - } else {
|
| - row = y;
|
| - }
|
| + int row = this->getDstRow(y, dstInfo.height());
|
|
|
| - SkPMColor* dstRow =
|
| - SkTAddOffset<SkPMColor>(dstPtr, row * dstRowBytes);
|
| + SkPMColor* dstRow =
|
| + SkTAddOffset<SkPMColor>(dstPtr, row * dstRowBytes);
|
|
|
| - for (int x = 0; x < width; x++) {
|
| - int quotient;
|
| - int modulus;
|
| - SkTDivMod(x, 8, "ient, &modulus);
|
| - uint32_t shift = 7 - modulus;
|
| - uint32_t alphaBit =
|
| - (fSrcBuffer.get()[quotient] >> shift) & 0x1;
|
| - dstRow[x] &= alphaBit - 1;
|
| - }
|
| + for (int x = 0; x < width; x++) {
|
| + int quotient;
|
| + int modulus;
|
| + SkTDivMod(x, 8, "ient, &modulus);
|
| + uint32_t shift = 7 - modulus;
|
| + uint32_t alphaBit =
|
| + (fSrcBuffer.get()[quotient] >> shift) & 0x1;
|
| + dstRow[x] &= alphaBit - 1;
|
| }
|
| }
|
| -
|
| - // Finished decoding the entire image
|
| return kSuccess;
|
| }
|
|
|