Index: src/codec/SkBmpCodec.cpp |
diff --git a/src/codec/SkBmpCodec.cpp b/src/codec/SkBmpCodec.cpp |
index 20af2da06fe0db122b86b49bef63b5c7ba6da8bc..b070e0ddb12842953e468d67ba655ece559de58f 100644 |
--- a/src/codec/SkBmpCodec.cpp |
+++ b/src/codec/SkBmpCodec.cpp |
@@ -11,6 +11,7 @@ |
#include "SkBmpStandardCodec.h" |
#include "SkCodecPriv.h" |
#include "SkColorPriv.h" |
+#include "SkScaledCodec.h" |
#include "SkStream.h" |
/* |
@@ -540,6 +541,14 @@ bool SkBmpCodec::onRewind() { |
return SkBmpCodec::ReadHeader(this->stream(), this->inIco(), NULL); |
} |
+int32_t SkBmpCodec::getDstRow(int32_t y) { |
+ if (SkBmpCodec::kTopDown_RowOrder == fRowOrder) { |
+ return y; |
+ } else { |
+ return this->getInfo().height() - y - 1; |
+ } |
+} |
+ |
/* |
* Get the destination row to start filling from |
* Used to fill the remainder of the image on incomplete input for bmps |
@@ -563,3 +572,77 @@ uint32_t SkBmpCodec::computeNumColors(uint32_t numColors) { |
} |
return numColors; |
} |
+ |
+/* |
+ * Scanline decoder for bmps |
+ */ |
+class SkBmpScanlineDecoder : public SkScanlineDecoder { |
+public: |
+ SkBmpScanlineDecoder(SkBmpCodec* codec) |
+ : INHERITED(codec->getInfo()) |
+ , fCodec(codec) |
+ {} |
+ |
+ SkEncodedFormat onGetEncodedFormat() const override { |
+ return kBMP_SkEncodedFormat; |
+ } |
+ |
+ SkCodec::Result onStart(const SkImageInfo& dstInfo, const SkCodec::Options& options, |
+ SkPMColor inputColorPtr[], int* inputColorCount) override { |
+ if (!fCodec->rewindIfNeeded()) { |
+ return SkCodec::kCouldNotRewind; |
+ } |
+ if (options.fSubset) { |
+ // Subsets are not supported. |
+ return SkCodec::kUnimplemented; |
+ } |
+ if (dstInfo.dimensions() != this->getInfo().dimensions()) { |
+ if (!SkScaledCodec::DimensionsSupportedForSampling(this->getInfo(), dstInfo)) { |
+ return SkCodec::kInvalidScale; |
+ } |
+ } |
+ if (!conversion_possible(dstInfo, this->getInfo())) { |
+ SkCodecPrintf("Error: cannot convert input type to output type.\n"); |
+ return SkCodec::kInvalidConversion; |
+ } |
+ |
+ return fCodec->prepareToDecode(dstInfo, options, inputColorPtr, inputColorCount); |
+ } |
+ |
+ SkCodec::Result onGetScanlines(void* dst, int count, size_t rowBytes) override { |
+ // Create a new image info representing the portion of the image to decode |
+ SkImageInfo rowInfo = this->dstInfo().makeWH(fCodec->getInfo().width(), count); |
+ |
+ // Decode the requested rows |
+ return fCodec->decode(rowInfo, dst, rowBytes, this->options()); |
+ } |
+ |
+ SkScanlineOrder onGetScanlineOrder() const override { |
+ if (SkBmpCodec::kTopDown_RowOrder == fCodec->fRowOrder) { |
+ return kTopDown_SkScanlineOrder; |
+ } else { |
+ return kOutOfOrder_SkScanlineOrder; |
+ } |
+ } |
+ |
+ int onGetY() const override { |
+ return fCodec->getDstRow(INHERITED::onGetY()); |
scroggo
2015/08/26 22:40:09
nit: this->INHERITED::onGetY()
|
+ } |
+ |
+ // TODO(msarett): Override default skipping with something more clever. |
+ // TODO(msarett): Consider other optimizations for this codec. |
+ |
+private: |
+ SkAutoTDelete<SkBmpCodec> fCodec; |
+ |
+ typedef SkScanlineDecoder INHERITED; |
+}; |
+ |
+SkScanlineDecoder* SkBmpCodec::NewSDFromStream(SkStream* stream) { |
+ SkAutoTDelete<SkBmpCodec> codec(static_cast<SkBmpCodec*>(SkBmpCodec::NewFromStream(stream))); |
+ if (!codec) { |
+ return NULL; |
+ } |
+ |
+ return SkNEW_ARGS(SkBmpScanlineDecoder, (codec.detach())); |
+} |