From d518ea7927f9f4e0ed5b4134d1b4f48243855a47 Mon Sep 17 00:00:00 2001 From: emmaleer Date: Thu, 13 Aug 2015 13:07:03 -0700 Subject: SkScaledCodec class This class does scaling by using a scanlineDecoder. getScanlines and skipScanlines are used for y sampling, the swizzler is used for x sampling this class is currently only working for png and jpeg images I will update other Codec types to work soon For SkJpegCodec to implement width wise swizzling it now uses a swizzler. I ran performance tests on this change. Here are the performance test results: https://docs.google.com/a/google.com/spreadsheets/d/1D7-Q_GXD_dI68LZO005NNvb8Wq2Ee0wEBEPG72671yw/edit?usp=sharing BUG=skia: Committed: https://skia.googlesource.com/skia/+/0944100ac89f797714eeae0cf2875e2335ff52ee Review URL: https://codereview.chromium.org/1260673002 --- include/codec/SkCodec.h | 2 ++ include/codec/SkScaledCodec.h | 70 +++++++++++++++++++++++++++++++++++++++ include/codec/SkScanlineDecoder.h | 42 +++++++++++++++++++++++ 3 files changed, 114 insertions(+) create mode 100644 include/codec/SkScaledCodec.h (limited to 'include/codec') diff --git a/include/codec/SkCodec.h b/include/codec/SkCodec.h index a0bd18a8e5..3465c1df5b 100644 --- a/include/codec/SkCodec.h +++ b/include/codec/SkCodec.h @@ -51,6 +51,8 @@ public: * Return a size that approximately supports the desired scale factor. * The codec may not be able to scale efficiently to the exact scale * factor requested, so return a size that approximates that scale. + * The returned value is the codec's suggestion for the closest valid + * scale that it can natively support */ SkISize getScaledDimensions(float desiredScale) const { return this->onGetScaledDimensions(desiredScale); diff --git a/include/codec/SkScaledCodec.h b/include/codec/SkScaledCodec.h new file mode 100644 index 0000000000..1bcdf085b2 --- /dev/null +++ b/include/codec/SkScaledCodec.h @@ -0,0 +1,70 @@ +/* + * Copyright 2015 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ +#ifndef SkScaledCodec_DEFINED +#define SkScaledCodec_DEFINED + +#include "SkCodec.h" +#include "SkScanlineDecoder.h" + +class SkScanlineDecoder; +class SkStream; + +/** + * This class implements scaling, by sampling scanlines in the y direction. + * x-wise sampling is implemented in the swizzler, when getScanlines() is called. + */ +class SkScaledCodec : public SkCodec { +public: + static SkCodec* NewFromStream(SkStream*); + static SkCodec* NewFromData(SkData*); + + virtual ~SkScaledCodec(); + + /** + * returns whether a destination's dimensions are supported for down sampling + */ + static bool DimensionsSupportedForSampling(const SkImageInfo& srcInfo, + const SkImageInfo& dstInfo) { + // heights must be equal as no native y sampling is supported + if (dstInfo.height() != srcInfo.height()) { + return false; + } + // only support down sampling, dstWidth cannot be larger that srcWidth + if(dstInfo.width() > srcInfo.width()) { + return false; + } + return true; + } + + static void ComputeSampleSize(const SkImageInfo& dstInfo, const SkImageInfo& srcInfo, + int* sampleSizeX, int* sampleSizeY); + +protected: + /** + * Recommend a set of destination dimensions given a requested scale + */ + SkISize onGetScaledDimensions(float desiredScale) const override; + + Result onGetPixels(const SkImageInfo&, void*, size_t, const Options&, SkPMColor*, int*) + override; + SkEncodedFormat onGetEncodedFormat() const override { + return fScanlineDecoder->getEncodedFormat(); + } + + bool onReallyHasAlpha() const override { + return fScanlineDecoder->reallyHasAlpha(); + } + +private: + + SkAutoTDelete fScanlineDecoder; + + explicit SkScaledCodec(SkScanlineDecoder*); + + typedef SkCodec INHERITED; +}; +#endif // SkScaledCodec_DEFINED diff --git a/include/codec/SkScanlineDecoder.h b/include/codec/SkScanlineDecoder.h index c233663dbd..c547f6701f 100644 --- a/include/codec/SkScanlineDecoder.h +++ b/include/codec/SkScanlineDecoder.h @@ -45,6 +45,18 @@ public: */ virtual ~SkScanlineDecoder() {} + /** + * Return a size that approximately supports the desired scale factor. + * The codec may not be able to scale efficiently to the exact scale + * factor requested, so return a size that approximates that scale. + * The returned value is the codec's suggestion for the closest valid + * scale that it can natively support + * FIXME: share this with SkCodec + */ + SkISize getScaledDimensions(float desiredScale) { + return this->onGetScaledDimensions(desiredScale); + } + /** * Returns the default info, corresponding to the encoded data. */ @@ -135,14 +147,44 @@ public: return this->onReallyHasAlpha(); } + /** + * Format of the encoded data. + */ + SkEncodedFormat getEncodedFormat() const { return this->onGetEncodedFormat(); } + + /** + * returns true if the image must be scaled, in the y direction, after reading, not during. + * To scale afterwards, we first decode every line and then sample the lines we want afterwards. + * An example is interlaced pngs, where calling getScanlines once (regardless of the count + * used) needs to read the entire image, therefore it is inefficient to call + * getScanlines more than once. Instead, it should only ever be called with all the + * rows needed. + */ + bool requiresPostYSampling() { + return this->onRequiresPostYSampling(); + } + protected: SkScanlineDecoder(const SkImageInfo& srcInfo) : fSrcInfo(srcInfo) , fDstInfo() , fCurrScanline(0) {} + virtual SkISize onGetScaledDimensions(float /* desiredScale */) { + // By default, scaling is not supported. + return this->getInfo().dimensions(); + } + + virtual SkEncodedFormat onGetEncodedFormat() const = 0; + virtual bool onReallyHasAlpha() const { return false; } + /** + * returns true if the image type is hard to sample and must be scaled after reading, not during + * An example is interlaced pngs, where the entire image must be read for each decode + */ + virtual bool onRequiresPostYSampling() { return false; } + const SkImageInfo& dstInfo() const { return fDstInfo; } private: -- cgit v1.2.3