Chromium Code Reviews| Index: include/codec/SkScaledCodec.h |
| diff --git a/include/codec/SkScaledCodec.h b/include/codec/SkScaledCodec.h |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..7794c0fc324b15721f44f4d45485159682bf58e7 |
| --- /dev/null |
| +++ b/include/codec/SkScaledCodec.h |
| @@ -0,0 +1,117 @@ |
| +/* |
| + * 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; |
| + } |
| + |
| + // returns a scaled dimension based on the original dimension and the sampleSize |
| + // NOTE: we round down here for scaled dimension to match the behavior of SkImageDecoder |
| + static int getScaledDimension(int srcDimension, int sampleSize) { |
|
msarett
2015/08/13 15:45:10
nit: GetScaledDimension because it is static.
Leo
scroggo
2015/08/13 16:10:45
In general, that is a sign it may not need to be a
emmaleer
2015/08/13 17:49:11
This is no longer a member function.
|
| + if (sampleSize > srcDimension) { |
| + return 1; |
| + } |
| + return srcDimension / sampleSize; |
| + } |
| + |
| + struct SampleSize { |
|
scroggo
2015/08/13 16:10:45
I do not think this object is necessary. It has a
emmaleer
2015/08/13 17:49:11
Okay, I like that way better too.
|
| + int sampleX; // sampleSize in the x direction |
| + int sampleY; // sampleSize in the y direction |
| + |
| + // calculates sampleSize in x and y direction |
| + SampleSize(const SkImageInfo& srcInfo, const SkImageInfo& dstInfo) { |
| + int srcWidth = srcInfo.width(); |
| + int dstWidth = dstInfo.width(); |
| + int srcHeight = srcInfo.height(); |
| + int dstHeight = dstInfo.height(); |
| + |
| + sampleX = srcWidth / dstWidth; |
| + sampleY = srcHeight / dstHeight; |
| + |
| + // only support down sampling, not up sampling |
| + SkASSERT(dstWidth <= srcWidth); |
| + SkASSERT(dstHeight <= srcHeight); |
| + |
| + // sampleX and sampleY should be equal unless the original sampleSize requested was |
| + // larger than srcWidth or srcHeight. |
| + // If so, the result of this is dstWidth or dstHeight = 1. This functionality |
| + // allows for tall thin images to still be scaled down by scaling factors. |
| + |
| + if (sampleX != sampleY){ |
| + if (1 != dstWidth && 1 != dstHeight) { |
| + |
| + // rounding during onGetScaledDimensions can cause different sampleSizes |
| + // Ex: srcWidth = 79, srcHeight = 20, sampleSize = 10 |
| + // dstWidth = 7, dstHeight = 2, sampleX = 79/7 = 11, sampleY = 20/2 = 10 |
| + // correct for this rounding by comparing width to sampleY and height to sampleX |
| + |
| + if (getScaledDimension(srcWidth, sampleY) == dstWidth) { |
| + sampleX = sampleY; |
| + } else if (getScaledDimension(srcHeight, sampleX) == dstHeight) { |
| + sampleY = sampleX; |
| + } |
| + } |
| + } |
| + } |
| + }; |
| + |
| +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<SkScanlineDecoder> fScanlineDecoder; |
| + |
| + explicit SkScaledCodec(SkScanlineDecoder*); |
| + |
| + typedef SkCodec INHERITED; |
| +}; |
| +#endif // SkScaledCodec_DEFINED |