diff options
-rw-r--r-- | bench/BitmapRegionDecoderBench.cpp | 68 | ||||
-rw-r--r-- | bench/BitmapRegionDecoderBench.h | 49 | ||||
-rw-r--r-- | bench/CodecBench.cpp | 17 | ||||
-rw-r--r-- | bench/CodecBenchPriv.h | 30 | ||||
-rw-r--r-- | bench/DecodingBench.cpp | 17 | ||||
-rw-r--r-- | bench/nanobench.cpp | 140 | ||||
-rw-r--r-- | bench/subset/SubsetBenchPriv.h | 20 | ||||
-rw-r--r-- | bench/subset/SubsetSingleBench.cpp | 3 | ||||
-rw-r--r-- | bench/subset/SubsetTranslateBench.cpp | 3 | ||||
-rw-r--r-- | bench/subset/SubsetZoomBench.cpp | 3 | ||||
-rw-r--r-- | dm/DM.cpp | 3 | ||||
-rw-r--r-- | dm/DMSrcSink.cpp | 3 | ||||
-rw-r--r-- | dm/DMSrcSink.h | 2 | ||||
-rw-r--r-- | gyp/bench.gypi | 1 | ||||
-rw-r--r-- | gyp/visualbench.gyp | 1 | ||||
-rw-r--r-- | tools/SkCodecTools.h | 15 |
16 files changed, 314 insertions, 61 deletions
diff --git a/bench/BitmapRegionDecoderBench.cpp b/bench/BitmapRegionDecoderBench.cpp new file mode 100644 index 0000000000..77d342331d --- /dev/null +++ b/bench/BitmapRegionDecoderBench.cpp @@ -0,0 +1,68 @@ +/* + * Copyright 2015 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "BitmapRegionDecoderBench.h" +#include "CodecBenchPriv.h" +#include "SkBitmap.h" +#include "SkCodecTools.h" +#include "SkOSFile.h" + +BitmapRegionDecoderBench::BitmapRegionDecoderBench(const char* baseName, SkData* encoded, + SkBitmapRegionDecoderInterface::Strategy strategy, SkColorType colorType, + uint32_t sampleSize, const SkIRect& subset) + : fBRD(nullptr) + , fData(SkRef(encoded)) + , fStrategy(strategy) + , fColorType(colorType) + , fSampleSize(sampleSize) + , fSubset(subset) +{ + // Choose a useful name for the region decoding strategy + const char* strategyName; + switch (strategy) { + case SkBitmapRegionDecoderInterface::kOriginal_Strategy: + strategyName = "Original"; + break; + case SkBitmapRegionDecoderInterface::kCanvas_Strategy: + strategyName = "Canvas"; + break; + default: + SkASSERT(false); + strategyName = ""; + break; + } + + // Choose a useful name for the color type + const char* colorName = color_type_to_str(colorType); + + fName.printf("BRD_%s_%s_%s", baseName, strategyName, colorName); + if (1 != sampleSize) { + fName.appendf("_%.3f", get_scale_from_sample_size(sampleSize)); + } +} + +const char* BitmapRegionDecoderBench::onGetName() { + return fName.c_str(); +} + +bool BitmapRegionDecoderBench::isSuitableFor(Backend backend) { + return kNonRendering_Backend == backend; +} + +void BitmapRegionDecoderBench::onPreDraw() { + SkStreamRewindable* stream = new SkMemoryStream(fData); + fBRD.reset(SkBitmapRegionDecoderInterface::CreateBitmapRegionDecoder(stream, fStrategy)); +} + +void BitmapRegionDecoderBench::onDraw(const int n, SkCanvas* canvas) { + SkAutoTDelete<SkBitmap> bitmap; + for (int i = 0; i < n; i++) { + bitmap.reset(fBRD->decodeRegion(fSubset.left(), fSubset.top(), fSubset.width(), + fSubset.height(), fSampleSize, fColorType)); + SkASSERT(nullptr != bitmap.get()); + } +} diff --git a/bench/BitmapRegionDecoderBench.h b/bench/BitmapRegionDecoderBench.h new file mode 100644 index 0000000000..7be770f472 --- /dev/null +++ b/bench/BitmapRegionDecoderBench.h @@ -0,0 +1,49 @@ +/* + * 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 BitmapRegionDecoderBench_DEFINED +#define BitmapRegionDecoderBench_DEFINED + +#include "Benchmark.h" +#include "SkBitmapRegionDecoderInterface.h" +#include "SkData.h" +#include "SkImageInfo.h" +#include "SkRefCnt.h" +#include "SkString.h" + +/** + * Benchmark Android's BitmapRegionDecoder for a particular colorType, sampleSize, and subset. + * + * fStrategy determines which of various implementations is to be used. + * + * nanobench.cpp handles creating benchmarks for interesting scaled subsets. We strive to test + * on real use cases. + */ +class BitmapRegionDecoderBench : public Benchmark { +public: + // Calls encoded->ref() + BitmapRegionDecoderBench(const char* basename, SkData* encoded, + SkBitmapRegionDecoderInterface::Strategy strategy, SkColorType colorType, + uint32_t sampleSize, const SkIRect& subset); + +protected: + const char* onGetName() override; + bool isSuitableFor(Backend backend) override; + void onDraw(const int n, SkCanvas* canvas) override; + void onPreDraw() override; + +private: + SkString fName; + SkAutoTDelete<SkBitmapRegionDecoderInterface> fBRD; + SkAutoTUnref<SkData> fData; + const SkBitmapRegionDecoderInterface::Strategy fStrategy; + const SkColorType fColorType; + const uint32_t fSampleSize; + const SkIRect fSubset; + typedef Benchmark INHERITED; +}; +#endif // BitmapRegionDecoderBench_DEFINED diff --git a/bench/CodecBench.cpp b/bench/CodecBench.cpp index 1e6b5207bf..a21aae1f0b 100644 --- a/bench/CodecBench.cpp +++ b/bench/CodecBench.cpp @@ -6,6 +6,7 @@ */ #include "CodecBench.h" +#include "CodecBenchPriv.h" #include "SkBitmap.h" #include "SkCodec.h" #include "SkOSFile.h" @@ -15,21 +16,7 @@ CodecBench::CodecBench(SkString baseName, SkData* encoded, SkColorType colorType , fData(SkRef(encoded)) { // Parse filename and the color type to give the benchmark a useful name - const char* colorName; - switch(colorType) { - case kN32_SkColorType: - colorName = "N32"; - break; - case kRGB_565_SkColorType: - colorName = "565"; - break; - case kAlpha_8_SkColorType: - colorName = "Alpha8"; - break; - default: - colorName = "Unknown"; - } - fName.printf("Codec_%s_%s", baseName.c_str(), colorName); + fName.printf("Codec_%s_%s", baseName.c_str(), color_type_to_str(colorType)); #ifdef SK_DEBUG // Ensure that we can create an SkCodec from this data. SkAutoTDelete<SkCodec> codec(SkCodec::NewFromData(fData)); diff --git a/bench/CodecBenchPriv.h b/bench/CodecBenchPriv.h new file mode 100644 index 0000000000..d8585b6006 --- /dev/null +++ b/bench/CodecBenchPriv.h @@ -0,0 +1,30 @@ +/* + * 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 CodecBenchPriv_DEFINED +#define CodecBenchPriv_DEFINED + +#include "SkImageInfo.h" + +inline const char* color_type_to_str(SkColorType colorType) { + switch (colorType) { + case kN32_SkColorType: + return "N32"; + case kRGB_565_SkColorType: + return "565"; + case kGray_8_SkColorType: + return "Gray8"; + case kIndex_8_SkColorType: + return "Index8"; + case kAlpha_8_SkColorType: + return "Alpha8"; + default: + return "Unknown"; + } +} + +#endif // CodecBenchPriv_DEFINED diff --git a/bench/DecodingBench.cpp b/bench/DecodingBench.cpp index 421cabe34a..7b6ad2bb0a 100644 --- a/bench/DecodingBench.cpp +++ b/bench/DecodingBench.cpp @@ -5,6 +5,7 @@ * found in the LICENSE file. */ +#include "CodecBenchPriv.h" #include "DecodingBench.h" #include "SkBitmap.h" #include "SkData.h" @@ -25,21 +26,7 @@ DecodingBench::DecodingBench(SkString path, SkColorType colorType) { // Parse filename and the color type to give the benchmark a useful name SkString baseName = SkOSPath::Basename(path.c_str()); - const char* colorName; - switch(colorType) { - case kN32_SkColorType: - colorName = "N32"; - break; - case kRGB_565_SkColorType: - colorName = "565"; - break; - case kAlpha_8_SkColorType: - colorName = "Alpha8"; - break; - default: - colorName = "Unknown"; - } - fName.printf("Decode_%s_%s", baseName.c_str(), colorName); + fName.printf("Decode_%s_%s", baseName.c_str(), color_type_to_str(colorType)); #ifdef SK_DEBUG // Ensure that we can create a decoder. diff --git a/bench/nanobench.cpp b/bench/nanobench.cpp index e7019dcb8c..a1db0acd80 100644 --- a/bench/nanobench.cpp +++ b/bench/nanobench.cpp @@ -10,7 +10,9 @@ #include "nanobench.h" #include "Benchmark.h" +#include "BitmapRegionDecoderBench.h" #include "CodecBench.h" +#include "CodecBenchPriv.h" #include "CrashHandler.h" #include "DecodingBench.h" #include "GMBench.h" @@ -19,13 +21,13 @@ #include "RecordingBench.h" #include "SKPAnimationBench.h" #include "SKPBench.h" -#include "SubsetBenchPriv.h" #include "SubsetSingleBench.h" #include "SubsetTranslateBench.h" #include "SubsetZoomBench.h" #include "Stats.h" #include "Timer.h" +#include "SkBitmapRegionDecoderInterface.h" #include "SkBBoxHierarchy.h" #include "SkCanvas.h" #include "SkCodec.h" @@ -525,7 +527,7 @@ static bool valid_subset_bench(const SkString& path, SkColorType colorType, bool colors, &colorCount) != SkCodec::kSuccess) { SkDebugf("Could not create scanline decoder for %s with color type %s. " - "Skipping bench.\n", path.c_str(), get_color_name(colorType)); + "Skipping bench.\n", path.c_str(), color_type_to_str(colorType)); return false; } *width = info.width(); @@ -539,7 +541,7 @@ static bool valid_subset_bench(const SkString& path, SkColorType colorType, bool //FIXME: See skbug.com/3921 if (kIndex_8_SkColorType == colorType || kGray_8_SkColorType == colorType) { SkDebugf("Cannot use image subset decoder for %s with color type %s. " - "Skipping bench.\n", path.c_str(), get_color_name(colorType)); + "Skipping bench.\n", path.c_str(), color_type_to_str(colorType)); return false; } if (!decoder->buildTileIndex(stream.detach(), width, height)) { @@ -557,6 +559,38 @@ static bool valid_subset_bench(const SkString& path, SkColorType colorType, bool return true; } +static bool valid_brd_bench(SkData* encoded, SkBitmapRegionDecoderInterface::Strategy strategy, + SkColorType colorType, uint32_t sampleSize, uint32_t minOutputSize, int* width, + int* height) { + SkStreamRewindable* stream = new SkMemoryStream(encoded); + SkAutoTDelete<SkBitmapRegionDecoderInterface> brd( + SkBitmapRegionDecoderInterface::CreateBitmapRegionDecoder(stream, strategy)); + if (nullptr == brd.get()) { + // This is indicates that subset decoding is not supported for a particular image format. + return false; + } + + SkAutoTDelete<SkBitmap> bitmap(brd->decodeRegion(0, 0, brd->width(), brd->height(), 1, + colorType)); + if (nullptr == bitmap.get() || colorType != bitmap->colorType()) { + // This indicates that conversion to the requested color type is not supported for the + // particular image. + return false; + } + + if (sampleSize * minOutputSize > (uint32_t) brd->width() || sampleSize * minOutputSize > + (uint32_t) brd->height()) { + // This indicates that the image is not large enough to decode a + // minOutputSize x minOutputSize subset at the given sampleSize. + return false; + } + + // Set the image width and height. The calling code will use this to choose subsets to decode. + *width = brd->width(); + *height = brd->height(); + return true; +} + static void cleanup_run(Target* target) { delete target; #if SK_SUPPORT_GPU @@ -580,9 +614,12 @@ public: , fCurrentCodec(0) , fCurrentImage(0) , fCurrentSubsetImage(0) + , fCurrentBRDImage(0) , fCurrentColorType(0) , fCurrentSubsetType(0) , fUseCodec(0) + , fCurrentBRDStrategy(0) + , fCurrentBRDSampleSize(0) , fCurrentAnimSKP(0) { for (int i = 0; i < FLAGS_skps.count(); i++) { if (SkStrEndsWith(FLAGS_skps[i], ".skp")) { @@ -876,6 +913,97 @@ public: fUseCodec++; } + // Run the BRDBenches + // We will benchmark multiple BRD strategies. + const SkBitmapRegionDecoderInterface::Strategy strategies[] = { + SkBitmapRegionDecoderInterface::kOriginal_Strategy, + SkBitmapRegionDecoderInterface::kCanvas_Strategy, + }; + + // We intend to create benchmarks that model the use cases in + // android/libraries/social/tiledimage. In this library, an image is decoded in 512x512 + // tiles. The image can be translated freely, so the location of a tile may be anywhere in + // the image. For that reason, we will benchmark decodes in five representative locations + // in the image. Additionally, this use case utilizes power of two scaling, so we will + // test on power of two sample sizes. The output tile is always 512x512, so, when a + // sampleSize is used, the size of the subset that is decoded is always + // (sampleSize*512)x(sampleSize*512). + // There are a few good reasons to only test on power of two sample sizes at this time: + // JPEG decodes using kOriginal_Strategy are broken for non-powers of two. + // skbug.com/4319 + // All use cases we are aware of only scale by powers of two. + // PNG decodes use the indicated sampling strategy regardless of the sample size, so + // these tests are sufficient to provide good coverage of our scaling options. + const uint32_t sampleSizes[] = { 1, 2, 4, 8, 16 }; + const uint32_t minOutputSize = 512; + while (fCurrentBRDImage < fImages.count()) { + while (fCurrentBRDStrategy < (int) SK_ARRAY_COUNT(strategies)) { + while (fCurrentColorType < fColorTypes.count()) { + while (fCurrentBRDSampleSize < (int) SK_ARRAY_COUNT(sampleSizes)) { + while (fCurrentSubsetType <= kLastSingle_SubsetType) { + const SkString& path = fImages[fCurrentBRDImage]; + const SkBitmapRegionDecoderInterface::Strategy strategy = + strategies[fCurrentBRDStrategy]; + SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(path.c_str())); + const SkColorType colorType = fColorTypes[fCurrentColorType]; + uint32_t sampleSize = sampleSizes[fCurrentBRDSampleSize]; + int currentSubsetType = fCurrentSubsetType++; + + int width = 0; + int height = 0; + if (!valid_brd_bench(encoded.get(), strategy, colorType, sampleSize, + minOutputSize, &width, &height)) { + break; + } + + SkString basename = SkOSPath::Basename(path.c_str()); + SkIRect subset; + const uint32_t subsetSize = sampleSize * minOutputSize; + switch (currentSubsetType) { + case kTopLeft_SubsetType: + basename.append("_TopLeft"); + subset = SkIRect::MakeXYWH(0, 0, subsetSize, subsetSize); + break; + case kTopRight_SubsetType: + basename.append("_TopRight"); + subset = SkIRect::MakeXYWH(width - subsetSize, 0, subsetSize, + subsetSize); + break; + case kMiddle_SubsetType: + basename.append("_Middle"); + subset = SkIRect::MakeXYWH((width - subsetSize) / 2, + (height - subsetSize) / 2, subsetSize, subsetSize); + break; + case kBottomLeft_SubsetType: + basename.append("_BottomLeft"); + subset = SkIRect::MakeXYWH(0, height - subsetSize, subsetSize, + subsetSize); + break; + case kBottomRight_SubsetType: + basename.append("_BottomRight"); + subset = SkIRect::MakeXYWH(width - subsetSize, + height - subsetSize, subsetSize, subsetSize); + break; + default: + SkASSERT(false); + } + + return new BitmapRegionDecoderBench(basename.c_str(), encoded.get(), + strategy, colorType, sampleSize, subset); + } + fCurrentSubsetType = 0; + fCurrentBRDSampleSize++; + } + fCurrentBRDSampleSize = 0; + fCurrentColorType++; + } + fCurrentColorType = 0; + fCurrentBRDStrategy++; + } + fCurrentBRDStrategy = 0; + fCurrentBRDImage++; + } + return nullptr; } @@ -907,7 +1035,8 @@ private: kBottomRight_SubsetType = 4, kTranslate_SubsetType = 5, kZoom_SubsetType = 6, - kLast_SubsetType = kZoom_SubsetType + kLast_SubsetType = kZoom_SubsetType, + kLastSingle_SubsetType = kBottomRight_SubsetType, }; const BenchRegistry* fBenches; @@ -932,9 +1061,12 @@ private: int fCurrentCodec; int fCurrentImage; int fCurrentSubsetImage; + int fCurrentBRDImage; int fCurrentColorType; int fCurrentSubsetType; int fUseCodec; + int fCurrentBRDStrategy; + int fCurrentBRDSampleSize; int fCurrentAnimSKP; }; diff --git a/bench/subset/SubsetBenchPriv.h b/bench/subset/SubsetBenchPriv.h index 02f7040a22..7e1dfb9530 100644 --- a/bench/subset/SubsetBenchPriv.h +++ b/bench/subset/SubsetBenchPriv.h @@ -13,26 +13,6 @@ #include "SkImageGenerator.h" /* - * Convert the color type to a string - */ -static const char* get_color_name(SkColorType colorType) { - switch(colorType) { - case kN32_SkColorType: - return "N32"; - case kRGB_565_SkColorType: - return "565"; - case kGray_8_SkColorType: - return "Gray8"; - case kIndex_8_SkColorType: - return "Index8"; - case kAlpha_8_SkColorType: - return "Alpha8"; - default: - return "Unknown"; - } -} - -/* * If we plan to decode to kIndex8, we must create a color table and pass it to the * bitmap when we allocate pixels. Otherwise, we simply allocate pixels using the * decode info. diff --git a/bench/subset/SubsetSingleBench.cpp b/bench/subset/SubsetSingleBench.cpp index ce00f20947..2e5703f508 100644 --- a/bench/subset/SubsetSingleBench.cpp +++ b/bench/subset/SubsetSingleBench.cpp @@ -5,6 +5,7 @@ * found in the LICENSE file. */ +#include "CodecBenchPriv.h" #include "SubsetSingleBench.h" #include "SubsetBenchPriv.h" #include "SkData.h" @@ -39,7 +40,7 @@ SubsetSingleBench::SubsetSingleBench(const SkString& path, SkString baseName = SkOSPath::Basename(path.c_str()); // Choose an informative color name - const char* colorName = get_color_name(fColorType); + const char* colorName = color_type_to_str(fColorType); fName.printf("%sSubsetSingle_%dx%d +%d_+%d_%s_%s", fUseCodec ? "Codec" : "Image", fSubsetWidth, fSubsetHeight, fOffsetLeft, fOffsetTop, baseName.c_str(), colorName); diff --git a/bench/subset/SubsetTranslateBench.cpp b/bench/subset/SubsetTranslateBench.cpp index 8f6f2ea21b..bed3580853 100644 --- a/bench/subset/SubsetTranslateBench.cpp +++ b/bench/subset/SubsetTranslateBench.cpp @@ -5,6 +5,7 @@ * found in the LICENSE file. */ +#include "CodecBenchPriv.h" #include "SubsetTranslateBench.h" #include "SubsetBenchPriv.h" #include "SkData.h" @@ -35,7 +36,7 @@ SubsetTranslateBench::SubsetTranslateBench(const SkString& path, SkString baseName = SkOSPath::Basename(path.c_str()); // Choose an informative color name - const char* colorName = get_color_name(fColorType); + const char* colorName = color_type_to_str(fColorType); fName.printf("%sSubsetTranslate_%dx%d_%s_%s", fUseCodec ? "Codec" : "Image", fSubsetWidth, fSubsetHeight, baseName.c_str(), colorName); diff --git a/bench/subset/SubsetZoomBench.cpp b/bench/subset/SubsetZoomBench.cpp index bbdca75a54..655285fdf8 100644 --- a/bench/subset/SubsetZoomBench.cpp +++ b/bench/subset/SubsetZoomBench.cpp @@ -5,6 +5,7 @@ * found in the LICENSE file. */ +#include "CodecBenchPriv.h" #include "SubsetZoomBench.h" #include "SubsetBenchPriv.h" #include "SkData.h" @@ -35,7 +36,7 @@ SubsetZoomBench::SubsetZoomBench(const SkString& path, SkString baseName = SkOSPath::Basename(path.c_str()); // Choose an informative color name - const char* colorName = get_color_name(fColorType); + const char* colorName = color_type_to_str(fColorType); fName.printf("%sSubsetZoom_%dx%d_%s_%s", fUseCodec ? "Codec" : "Image", fSubsetWidth, fSubsetHeight, baseName.c_str(), colorName); @@ -14,6 +14,7 @@ #include "SkBBHFactory.h" #include "SkChecksum.h" #include "SkCodec.h" +#include "SkCodecTools.h" #include "SkCommonFlags.h" #include "SkFontMgr.h" #include "SkForceLinking.h" @@ -396,7 +397,7 @@ static void push_brd_src(Path path, SkBitmapRegionDecoderInterface::Strategy str } if (1 != sampleSize) { - folder.appendf("_%.3f", BRDSrc::GetScale(sampleSize)); + folder.appendf("_%.3f", get_scale_from_sample_size(sampleSize)); } BRDSrc* src = new BRDSrc(path, strategy, mode, dstColorType, sampleSize); diff --git a/dm/DMSrcSink.cpp b/dm/DMSrcSink.cpp index 981e47d6c0..10cdd0965b 100644 --- a/dm/DMSrcSink.cpp +++ b/dm/DMSrcSink.cpp @@ -8,6 +8,7 @@ #include "DMSrcSink.h" #include "SamplePipeControllers.h" #include "SkCodec.h" +#include "SkCodecTools.h" #include "SkCommonFlags.h" #include "SkData.h" #include "SkDocument.h" @@ -216,7 +217,7 @@ Name BRDSrc::name() const { if (1 == fSampleSize) { return SkOSPath::Basename(fPath.c_str()); } - return get_scaled_name(fPath, BRDSrc::GetScale(fSampleSize)); + return get_scaled_name(fPath, get_scale_from_sample_size(fSampleSize)); } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ diff --git a/dm/DMSrcSink.h b/dm/DMSrcSink.h index fe6c91dfad..9e0ef49651 100644 --- a/dm/DMSrcSink.h +++ b/dm/DMSrcSink.h @@ -144,8 +144,6 @@ public: BRDSrc(Path, SkBitmapRegionDecoderInterface::Strategy, Mode, CodecSrc::DstColorType, uint32_t); - static float GetScale(uint32_t sampleSize) { return 1.0f / (float) sampleSize; } - Error draw(SkCanvas*) const override; SkISize size() const override; Name name() const override; diff --git a/gyp/bench.gypi b/gyp/bench.gypi index e102a97f1b..95073b0fba 100644 --- a/gyp/bench.gypi +++ b/gyp/bench.gypi @@ -18,6 +18,7 @@ 'dependencies': [ 'etc1.gyp:libetc1', 'skia_lib.gyp:skia_lib', + 'tools.gyp:bitmap_region_decoder', 'tools.gyp:resources', 'tools.gyp:sk_tool_utils', ], diff --git a/gyp/visualbench.gyp b/gyp/visualbench.gyp index 43816ee872..8dea597ef8 100644 --- a/gyp/visualbench.gyp +++ b/gyp/visualbench.gyp @@ -38,6 +38,7 @@ 'jsoncpp.gyp:jsoncpp', 'gputest.gyp:skgputest', 'skia_lib.gyp:skia_lib', + 'tools.gyp:bitmap_region_decoder', 'tools.gyp:proc_stats', 'tools.gyp:sk_tool_utils', 'tools.gyp:timer', diff --git a/tools/SkCodecTools.h b/tools/SkCodecTools.h new file mode 100644 index 0000000000..097915b5d7 --- /dev/null +++ b/tools/SkCodecTools.h @@ -0,0 +1,15 @@ +/* + * 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 SkCodecTools_DEFINED +#define SkCodecTools_DEFINED + +inline float get_scale_from_sample_size(uint32_t sampleSize) { + return 1.0f / (float) sampleSize; +} + +#endif // SkCodecTools_DEFINED |