1/* 2 * Copyright 2015 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8#include "SkBmpMaskCodec.h" 9#include "SkCodecPriv.h" 10#include "SkColorPriv.h" 11 12/* 13 * Creates an instance of the decoder 14 */ 15SkBmpMaskCodec::SkBmpMaskCodec(const SkImageInfo& info, SkStream* stream, 16 uint16_t bitsPerPixel, SkMasks* masks, 17 SkCodec::SkScanlineOrder rowOrder) 18 : INHERITED(info, stream, bitsPerPixel, rowOrder) 19 , fMasks(masks) 20 , fMaskSwizzler(nullptr) 21 , fSrcBuffer(new uint8_t [this->srcRowBytes()]) 22{} 23 24/* 25 * Initiates the bitmap decode 26 */ 27SkCodec::Result SkBmpMaskCodec::onGetPixels(const SkImageInfo& dstInfo, 28 void* dst, size_t dstRowBytes, 29 const Options& opts, 30 SkPMColor* inputColorPtr, 31 int* inputColorCount, 32 int* rowsDecoded) { 33 if (opts.fSubset) { 34 // Subsets are not supported. 35 return kUnimplemented; 36 } 37 if (dstInfo.dimensions() != this->getInfo().dimensions()) { 38 SkCodecPrintf("Error: scaling not supported.\n"); 39 return kInvalidScale; 40 } 41 42 if (!conversion_possible(dstInfo, this->getInfo())) { 43 SkCodecPrintf("Error: cannot convert input type to output type.\n"); 44 return kInvalidConversion; 45 } 46 47 Result result = this->prepareToDecode(dstInfo, opts, inputColorPtr, inputColorCount); 48 if (kSuccess != result) { 49 return result; 50 } 51 52 int rows = this->decodeRows(dstInfo, dst, dstRowBytes, opts); 53 if (rows != dstInfo.height()) { 54 *rowsDecoded = rows; 55 return kIncompleteInput; 56 } 57 return kSuccess; 58} 59 60SkCodec::Result SkBmpMaskCodec::prepareToDecode(const SkImageInfo& dstInfo, 61 const SkCodec::Options& options, SkPMColor inputColorPtr[], int* inputColorCount) { 62 // Initialize the mask swizzler 63 fMaskSwizzler.reset(SkMaskSwizzler::CreateMaskSwizzler(dstInfo, this->getInfo(), fMasks, 64 this->bitsPerPixel(), options)); 65 SkASSERT(fMaskSwizzler); 66 67 return SkCodec::kSuccess; 68} 69 70/* 71 * Performs the decoding 72 */ 73int SkBmpMaskCodec::decodeRows(const SkImageInfo& dstInfo, 74 void* dst, size_t dstRowBytes, 75 const Options& opts) { 76 // Iterate over rows of the image 77 uint8_t* srcRow = fSrcBuffer.get(); 78 const int height = dstInfo.height(); 79 for (int y = 0; y < height; y++) { 80 // Read a row of the input 81 if (this->stream()->read(srcRow, this->srcRowBytes()) != this->srcRowBytes()) { 82 SkCodecPrintf("Warning: incomplete input stream.\n"); 83 return y; 84 } 85 86 // Decode the row in destination format 87 uint32_t row = this->getDstRow(y, height); 88 void* dstRow = SkTAddOffset<void>(dst, row * dstRowBytes); 89 fMaskSwizzler->swizzle(dstRow, srcRow); 90 } 91 92 // Finished decoding the entire image 93 return height; 94} 95