• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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