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 */
SkBmpMaskCodec(int width,int height,const SkEncodedInfo & info,SkStream * stream,uint16_t bitsPerPixel,SkMasks * masks,SkCodec::SkScanlineOrder rowOrder)15 SkBmpMaskCodec::SkBmpMaskCodec(int width, int height, const SkEncodedInfo& info, SkStream* stream,
16 uint16_t bitsPerPixel, SkMasks* masks,
17 SkCodec::SkScanlineOrder rowOrder)
18 : INHERITED(width, height, 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 */
onGetPixels(const SkImageInfo & dstInfo,void * dst,size_t dstRowBytes,const Options & opts,SkPMColor * inputColorPtr,int * inputColorCount,int * rowsDecoded)27 SkCodec::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 Result result = this->prepareToDecode(dstInfo, opts, inputColorPtr, inputColorCount);
43 if (kSuccess != result) {
44 return result;
45 }
46
47 int rows = this->decodeRows(dstInfo, dst, dstRowBytes, opts);
48 if (rows != dstInfo.height()) {
49 *rowsDecoded = rows;
50 return kIncompleteInput;
51 }
52 return kSuccess;
53 }
54
onPrepareToDecode(const SkImageInfo & dstInfo,const SkCodec::Options & options,SkPMColor inputColorPtr[],int * inputColorCount)55 SkCodec::Result SkBmpMaskCodec::onPrepareToDecode(const SkImageInfo& dstInfo,
56 const SkCodec::Options& options, SkPMColor inputColorPtr[], int* inputColorCount) {
57 if (this->colorXform()) {
58 this->resetXformBuffer(dstInfo.width());
59 }
60
61 SkImageInfo swizzlerInfo = dstInfo;
62 if (this->colorXform()) {
63 swizzlerInfo = swizzlerInfo.makeColorType(kXformSrcColorType);
64 if (kPremul_SkAlphaType == dstInfo.alphaType()) {
65 swizzlerInfo = swizzlerInfo.makeAlphaType(kUnpremul_SkAlphaType);
66 }
67 }
68
69 // Initialize the mask swizzler
70 fMaskSwizzler.reset(SkMaskSwizzler::CreateMaskSwizzler(swizzlerInfo, this->getInfo(),
71 fMasks.get(), this->bitsPerPixel(), options));
72 SkASSERT(fMaskSwizzler);
73
74 return SkCodec::kSuccess;
75 }
76
77 /*
78 * Performs the decoding
79 */
decodeRows(const SkImageInfo & dstInfo,void * dst,size_t dstRowBytes,const Options & opts)80 int SkBmpMaskCodec::decodeRows(const SkImageInfo& dstInfo,
81 void* dst, size_t dstRowBytes,
82 const Options& opts) {
83 // Iterate over rows of the image
84 uint8_t* srcRow = fSrcBuffer.get();
85 const int height = dstInfo.height();
86 for (int y = 0; y < height; y++) {
87 // Read a row of the input
88 if (this->stream()->read(srcRow, this->srcRowBytes()) != this->srcRowBytes()) {
89 SkCodecPrintf("Warning: incomplete input stream.\n");
90 return y;
91 }
92
93 // Decode the row in destination format
94 uint32_t row = this->getDstRow(y, height);
95 void* dstRow = SkTAddOffset<void>(dst, row * dstRowBytes);
96
97 if (this->colorXform()) {
98 SkImageInfo xformInfo = dstInfo.makeWH(fMaskSwizzler->swizzleWidth(), dstInfo.height());
99 fMaskSwizzler->swizzle(this->xformBuffer(), srcRow);
100 this->applyColorXform(xformInfo, dstRow, this->xformBuffer());
101 } else {
102 fMaskSwizzler->swizzle(dstRow, srcRow);
103 }
104 }
105
106 // Finished decoding the entire image
107 return height;
108 }
109