diff --git a/dm/DM.cpp b/dm/DM.cpp index fe096434c6..9dcdff1a0f 100644 --- a/dm/DM.cpp +++ b/dm/DM.cpp @@ -212,12 +212,7 @@ static void push_codec_srcs(Path path) { // TODO (msarett): Add more scaling tests as we implement more flexible scaling. // TODO (msarett): Implement scaling tests for SkImageDecoder in order to compare with these // tests. SkImageDecoder supports downscales by integer factors. - // SkJpegCodec natively supports scaling to: 0.125, 0.25, 0.375, 0.5, 0.625, 0.75, 0.875 - // 0.1, 0.16, 0.2 etc allow us to test SkScaledCodec with sampleSize 10, 6, 5, etc - // 0.4, 0.7 etc allow to test what happens when the client requests a scale that - // does not exactly match a sampleSize or native scaling capability - const float scales[] = { 0.1f, 0.125f, 0.166f, 0.2f, 0.25f, 0.333f, 0.375f, 0.4f, 0.5f, 0.6f, - 0.625f, 0.750f, 0.8f, 0.875f, 1.0f }; + const float scales[] = { 0.125f, 0.25f, 0.375f, 0.5f, 0.625f, 0.750f, 0.875f, 1.0f }; for (float scale : scales) { if (scale != 1.0f && (path.endsWith(".webp") || path.endsWith(".WEBP"))) { diff --git a/dm/DMSrcSink.cpp b/dm/DMSrcSink.cpp index 9826f97822..f555b9fcbd 100644 --- a/dm/DMSrcSink.cpp +++ b/dm/DMSrcSink.cpp @@ -27,7 +27,6 @@ #include "SkScanlineDecoder.h" #include "SkStream.h" #include "SkXMLWriter.h" -#include "SkScaledCodec.h" DEFINE_bool(multiPage, false, "For document-type backends, render the source" " into multiple pages"); @@ -85,13 +84,9 @@ Error CodecSrc::draw(SkCanvas* canvas) const { if (!encoded) { return SkStringPrintf("Couldn't read %s.", fPath.c_str()); } - SkAutoTDelete codec(SkScaledCodec::NewFromData(encoded)); + SkAutoTDelete codec(SkCodec::NewFromData(encoded)); if (NULL == codec.get()) { - // scaledCodec not supported, try normal codec - codec.reset(SkCodec::NewFromData(encoded)); - if (NULL == codec.get()) { - return SkStringPrintf("Couldn't create codec for %s.", fPath.c_str()); - } + return SkStringPrintf("Couldn't create codec for %s.", fPath.c_str()); } // Choose the color type to decode to @@ -451,16 +446,13 @@ Error CodecSrc::draw(SkCanvas* canvas) const { SkISize CodecSrc::size() const { SkAutoTUnref encoded(SkData::NewFromFileName(fPath.c_str())); - SkAutoTDelete codec(SkScaledCodec::NewFromData(encoded)); - if (NULL == codec) { - // scaledCodec not supported, try regular codec - codec.reset(SkCodec::NewFromData(encoded)); - if (NULL == codec) { - return SkISize::Make(0, 0); - } + SkAutoTDelete codec(SkCodec::NewFromData(encoded)); + if (NULL != codec) { + SkISize size = codec->getScaledDimensions(fScale); + return size; + } else { + return SkISize::Make(0, 0); } - SkISize size = codec->getScaledDimensions(fScale); - return size; } Name CodecSrc::name() const { diff --git a/gyp/codec.gyp b/gyp/codec.gyp index b34c85e7d9..cc06945ce8 100644 --- a/gyp/codec.gyp +++ b/gyp/codec.gyp @@ -47,7 +47,6 @@ '../src/codec/SkJpegUtility_codec.cpp', '../src/codec/SkMaskSwizzler.cpp', '../src/codec/SkMasks.cpp', - '../src/codec/SkScaledCodec.cpp', '../src/codec/SkScanlineDecoder.cpp', '../src/codec/SkSwizzler.cpp', '../src/codec/SkWebpCodec.cpp', diff --git a/include/codec/SkCodec.h b/include/codec/SkCodec.h index 3465c1df5b..a0bd18a8e5 100644 --- a/include/codec/SkCodec.h +++ b/include/codec/SkCodec.h @@ -51,8 +51,6 @@ 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 deleted file mode 100644 index 1bcdf085b2..0000000000 --- a/include/codec/SkScaledCodec.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - * 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 c547f6701f..c233663dbd 100644 --- a/include/codec/SkScanlineDecoder.h +++ b/include/codec/SkScanlineDecoder.h @@ -45,18 +45,6 @@ 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. */ @@ -147,44 +135,14 @@ 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: diff --git a/src/codec/SkBmpStandardCodec.cpp b/src/codec/SkBmpStandardCodec.cpp index 1dfd04ee21..08146fc3e4 100644 --- a/src/codec/SkBmpStandardCodec.cpp +++ b/src/codec/SkBmpStandardCodec.cpp @@ -237,7 +237,7 @@ bool SkBmpStandardCodec::initializeSwizzler(const SkImageInfo& dstInfo, // Create swizzler fSwizzler.reset(SkSwizzler::CreateSwizzler(config, - colorPtr, dstInfo, opts.fZeroInitialized, this->getInfo())); + colorPtr, dstInfo, opts.fZeroInitialized)); if (NULL == fSwizzler.get()) { return false; diff --git a/src/codec/SkCodec_libgif.cpp b/src/codec/SkCodec_libgif.cpp index fa267e83e9..2e348cc856 100644 --- a/src/codec/SkCodec_libgif.cpp +++ b/src/codec/SkCodec_libgif.cpp @@ -444,12 +444,11 @@ SkCodec::Result SkGifCodec::onGetPixels(const SkImageInfo& dstInfo, // Create the subset swizzler swizzler.reset(SkSwizzler::CreateSwizzler( SkSwizzler::kIndex, colorTable, subsetDstInfo, - zeroInit, this->getInfo())); + zeroInit)); } else { // Create the fully dimensional swizzler swizzler.reset(SkSwizzler::CreateSwizzler( - SkSwizzler::kIndex, colorTable, dstInfo, - zeroInit, this->getInfo())); + SkSwizzler::kIndex, colorTable, dstInfo, zeroInit)); } // Stores output from dgiflib and input to the swizzler diff --git a/src/codec/SkCodec_libpng.cpp b/src/codec/SkCodec_libpng.cpp index 159aecd7ef..c94f371399 100644 --- a/src/codec/SkCodec_libpng.cpp +++ b/src/codec/SkCodec_libpng.cpp @@ -11,7 +11,6 @@ #include "SkColorTable.h" #include "SkBitmap.h" #include "SkMath.h" -#include "SkScaledCodec.h" #include "SkScanlineDecoder.h" #include "SkSize.h" #include "SkStream.h" @@ -463,7 +462,7 @@ SkCodec::Result SkPngCodec::initializeSwizzler(const SkImageInfo& requestedInfo, // Create the swizzler. SkPngCodec retains ownership of the color table. const SkPMColor* colors = get_color_ptr(fColorTable.get()); fSwizzler.reset(SkSwizzler::CreateSwizzler(fSrcConfig, colors, requestedInfo, - options.fZeroInitialized, this->getInfo())); + options.fZeroInitialized)); if (!fSwizzler) { // FIXME: CreateSwizzler could fail for another reason. return kUnimplemented; @@ -583,7 +582,8 @@ public: SkCodec::Result onStart(const SkImageInfo& dstInfo, const SkCodec::Options& options, - SkPMColor ctable[], int* ctableCount) override { + SkPMColor ctable[], int* ctableCount) override + { if (!fCodec->rewindIfNeeded()) { return SkCodec::kCouldNotRewind; } @@ -594,9 +594,7 @@ public: // Check to see if scaling was requested. if (dstInfo.dimensions() != this->getInfo().dimensions()) { - if (!SkScaledCodec::DimensionsSupportedForSampling(this->getInfo(), dstInfo)) { - return SkCodec::kInvalidScale; - } + return SkCodec::kInvalidScale; } const SkCodec::Result result = fCodec->initializeSwizzler(dstInfo, options, ctable, @@ -606,7 +604,7 @@ public: } fHasAlpha = false; - fStorage.reset(this->getInfo().width() * SkSwizzler::BytesPerPixel(fCodec->fSrcConfig)); + fStorage.reset(dstInfo.width() * SkSwizzler::BytesPerPixel(fCodec->fSrcConfig)); fSrcRow = static_cast(fStorage.get()); return SkCodec::kSuccess; @@ -645,11 +643,6 @@ public: bool onReallyHasAlpha() const override { return fHasAlpha; } - SkEncodedFormat onGetEncodedFormat() const override { - return kPNG_SkEncodedFormat; - } - - private: SkAutoTDelete fCodec; bool fHasAlpha; @@ -680,14 +673,12 @@ public: } if (!conversion_possible(dstInfo, this->getInfo())) { - return SkCodec::kInvalidConversion; + return SkCodec::kInvalidConversion; } // Check to see if scaling was requested. if (dstInfo.dimensions() != this->getInfo().dimensions()) { - if (!SkScaledCodec::DimensionsSupportedForSampling(this->getInfo(), dstInfo)) { - return SkCodec::kInvalidScale; - } + return SkCodec::kInvalidScale; } const SkCodec::Result result = fCodec->initializeSwizzler(dstInfo, options, ctable, @@ -699,7 +690,7 @@ public: fHasAlpha = false; fCurrentRow = 0; fHeight = dstInfo.height(); - fSrcRowBytes = this->getInfo().width() * SkSwizzler::BytesPerPixel(fCodec->fSrcConfig); + fSrcRowBytes = dstInfo.width() * SkSwizzler::BytesPerPixel(fCodec->fSrcConfig); fGarbageRow.reset(fSrcRowBytes); fGarbageRowPtr = static_cast(fGarbageRow.get()); fCanSkipRewind = true; @@ -762,14 +753,6 @@ public: bool onReallyHasAlpha() const override { return fHasAlpha; } - bool onRequiresPostYSampling() override { - return true; - } - - SkEncodedFormat onGetEncodedFormat() const override { - return kPNG_SkEncodedFormat; - } - private: SkAutoTDelete fCodec; bool fHasAlpha; diff --git a/src/codec/SkCodec_libpng.h b/src/codec/SkCodec_libpng.h index e8807499ea..890402200c 100644 --- a/src/codec/SkCodec_libpng.h +++ b/src/codec/SkCodec_libpng.h @@ -37,7 +37,6 @@ protected: SkEncodedFormat onGetEncodedFormat() const override { return kPNG_SkEncodedFormat; } bool onRewind() override; bool onReallyHasAlpha() const override { return fReallyHasAlpha; } - private: png_structp fPng_ptr; png_infop fInfo_ptr; @@ -53,6 +52,7 @@ private: SkPngCodec(const SkImageInfo&, SkStream*, png_structp, png_infop, int); + // Helper to set up swizzler and color table. Also calls png_read_update_info. Result initializeSwizzler(const SkImageInfo& requestedInfo, const Options&, SkPMColor*, int* ctableCount); diff --git a/src/codec/SkCodec_wbmp.cpp b/src/codec/SkCodec_wbmp.cpp index 3081a3bba9..6f98294fc6 100644 --- a/src/codec/SkCodec_wbmp.cpp +++ b/src/codec/SkCodec_wbmp.cpp @@ -9,7 +9,6 @@ #include "SkCodecPriv.h" #include "SkColorPriv.h" #include "SkColorTable.h" -#include "SkScaledCodec.h" #include "SkStream.h" #include "SkCodec_wbmp.h" @@ -81,8 +80,8 @@ SkSwizzler* SkWbmpCodec::initializeSwizzler(const SkImageInfo& info, case kIndex_8_SkColorType: case kN32_SkColorType: case kGray_8_SkColorType: - return SkSwizzler::CreateSwizzler(SkSwizzler::kBit, ctable, info, opts.fZeroInitialized, - this->getInfo()); + return SkSwizzler::CreateSwizzler( + SkSwizzler::kBit, ctable, info, opts.fZeroInitialized); default: return NULL; } @@ -202,9 +201,7 @@ public: return SkCodec::kUnimplemented; } if (dstInfo.dimensions() != this->getInfo().dimensions()) { - if (!SkScaledCodec::DimensionsSupportedForSampling(this->getInfo(), dstInfo)) { - return SkCodec::kInvalidScale; - } + return SkCodec::kInvalidScale; } if (!valid_alpha(dstInfo.alphaType(), this->getInfo().alphaType())) { @@ -223,16 +220,12 @@ public: fSwizzler.reset(fCodec->initializeSwizzler(dstInfo, get_color_ptr(fColorTable.get()), options)); if (NULL == fSwizzler.get()) { - return SkCodec::kInvalidConversion; + return SkCodec::kInvalidInput; } return SkCodec::kSuccess; } - SkEncodedFormat onGetEncodedFormat() const { - return kWBMP_SkEncodedFormat; - } - private: SkAutoTDelete fCodec; SkAutoTUnref fColorTable; diff --git a/src/codec/SkJpegCodec.cpp b/src/codec/SkJpegCodec.cpp index c094d50a3b..83656da42d 100644 --- a/src/codec/SkJpegCodec.cpp +++ b/src/codec/SkJpegCodec.cpp @@ -11,7 +11,6 @@ #include "SkJpegUtility_codec.h" #include "SkCodecPriv.h" #include "SkColorPriv.h" -#include "SkScaledCodec.h" #include "SkScanlineDecoder.h" #include "SkStream.h" #include "SkTemplates.h" @@ -149,14 +148,6 @@ SkJpegCodec::SkJpegCodec(const SkImageInfo& srcInfo, SkStream* stream, , fDecoderMgr(decoderMgr) {} -/* - * Return the row bytes of a particular image type and width - */ -static int get_row_bytes(const j_decompress_ptr dinfo) { - int colorBytes = (dinfo->out_color_space == JCS_RGB565) ? 2 : dinfo->out_color_components; - return dinfo->output_width * colorBytes; - -} /* * Return a valid set of output dimensions for this decoder, given an input scale */ @@ -267,10 +258,10 @@ bool SkJpegCodec::setOutputColorSpace(const SkImageInfo& dst) { } /* - * Checks if we can natively scale to the requested dimensions and natively scales the - * dimensions if possible + * Checks if we can scale to the requested dimensions and scales the dimensions + * if possible */ -bool SkJpegCodec::nativelyScaleToDimensions(uint32_t dstWidth, uint32_t dstHeight) { +bool SkJpegCodec::scaleToDimensions(uint32_t dstWidth, uint32_t dstHeight) { // libjpeg-turbo can scale to 1/8, 1/4, 3/8, 1/2, 5/8, 3/4, 7/8, and 1/1 fDecoderMgr->dinfo()->scale_denom = 8; fDecoderMgr->dinfo()->scale_num = 8; @@ -282,10 +273,7 @@ bool SkJpegCodec::nativelyScaleToDimensions(uint32_t dstWidth, uint32_t dstHeigh if (1 == fDecoderMgr->dinfo()->scale_num || dstWidth > fDecoderMgr->dinfo()->output_width || dstHeight > fDecoderMgr->dinfo()->output_height) { - // reset native scale settings on failure because this may be supported by the swizzler - this->fDecoderMgr->dinfo()->scale_num = 8; - chromium_jpeg_calc_output_dimensions(this->fDecoderMgr->dinfo()); - return false; + return fDecoderMgr->returnFalse("could not scale to requested dimensions"); } // Try the next scale @@ -325,7 +313,7 @@ SkCodec::Result SkJpegCodec::onGetPixels(const SkImageInfo& dstInfo, } // Perform the necessary scaling - if (!this->nativelyScaleToDimensions(dstInfo.width(), dstInfo.height())) { + if (!this->scaleToDimensions(dstInfo.width(), dstInfo.height())) { return fDecoderMgr->returnFailure("cannot scale to requested dims", kInvalidScale); } @@ -393,47 +381,6 @@ public: , fOpts() {} - /* - * Return a valid set of output dimensions for this decoder, given an input scale - */ - SkISize onGetScaledDimensions(float desiredScale) override { - return fCodec->onGetScaledDimensions(desiredScale); - } - - /* - * Create the swizzler based on the encoded format. - * The swizzler is only used for sampling in the x direction. - */ - - SkCodec::Result initializeSwizzler(const SkImageInfo& info, const SkCodec::Options& options) { - SkSwizzler::SrcConfig srcConfig; - switch (info.colorType()) { - case kGray_8_SkColorType: - srcConfig = SkSwizzler::kGray; - break; - case kRGBA_8888_SkColorType: - srcConfig = SkSwizzler::kRGBX; - break; - case kBGRA_8888_SkColorType: - srcConfig = SkSwizzler::kBGRX; - break; - case kRGB_565_SkColorType: - srcConfig = SkSwizzler::kRGB_565; - break; - default: - //would have exited before now if the colorType was supported by jpeg - SkASSERT(false); - } - - fSwizzler.reset(SkSwizzler::CreateSwizzler(srcConfig, NULL, info, options.fZeroInitialized, - this->getInfo())); - if (!fSwizzler) { - // FIXME: CreateSwizzler could fail for another reason. - return SkCodec::kUnimplemented; - } - return SkCodec::kSuccess; - } - SkCodec::Result onStart(const SkImageInfo& dstInfo, const SkCodec::Options& options, SkPMColor ctable[], int* ctableCount) override { @@ -454,23 +401,8 @@ public: } // Perform the necessary scaling - if (!fCodec->nativelyScaleToDimensions(dstInfo.width(), dstInfo.height())) { - // full native scaling to dstInfo dimensions not supported - - if (!SkScaledCodec::DimensionsSupportedForSampling(this->getInfo(), dstInfo)) { - return SkCodec::kInvalidScale; - } - // create swizzler for sampling - SkCodec::Result result = this->initializeSwizzler(dstInfo, options); - if (SkCodec::kSuccess != result) { - SkCodecPrintf("failed to initialize the swizzler.\n"); - return result; - } - fStorage.reset(get_row_bytes(fCodec->fDecoderMgr->dinfo())); - fSrcRow = static_cast(fStorage.get()); - } else { - fSrcRow = NULL; - fSwizzler.reset(NULL); + if (!fCodec->scaleToDimensions(dstInfo.width(), dstInfo.height())) { + return SkCodec::kInvalidScale; } // Now, given valid output dimensions, we can start the decompress @@ -501,16 +433,9 @@ public: if (setjmp(fCodec->fDecoderMgr->getJmpBuf())) { return fCodec->fDecoderMgr->returnFailure("setjmp", SkCodec::kInvalidInput); } - // Read rows one at a time - JSAMPLE* dstRow; - if (fSwizzler) { - // write data to storage row, then sample using swizzler - dstRow = fSrcRow; - } else { - // write data directly to dst - dstRow = (JSAMPLE*) dst; - } + // Read rows one at a time + JSAMPLE* dstRow = (JSAMPLE*) dst; for (int y = 0; y < count; y++) { // Read row of the image uint32_t rowsDecoded = @@ -527,17 +452,13 @@ public: // Convert to RGBA if necessary if (JCS_CMYK == fCodec->fDecoderMgr->dinfo()->out_color_space) { - convert_CMYK_to_RGBA(dstRow, fCodec->fDecoderMgr->dinfo()->output_width); + convert_CMYK_to_RGBA(dstRow, this->dstInfo().width()); } - if(fSwizzler) { - // use swizzler to sample row - fSwizzler->swizzle(dst, dstRow); - dst = SkTAddOffset(dst, rowBytes); - } else { - dstRow = SkTAddOffset(dstRow, rowBytes); - } + // Move to the next row + dstRow = SkTAddOffset(dstRow, rowBytes); } + return SkCodec::kSuccess; } @@ -545,7 +466,7 @@ public: // TODO (msarett): Make this a member function and avoid reallocating the // memory buffer on each call to skip. #define chromium_jpeg_skip_scanlines(dinfo, count) \ - SkAutoMalloc storage(get_row_bytes(dinfo)); \ + SkAutoMalloc storage(dinfo->output_width * dinfo->out_color_components); \ uint8_t* storagePtr = static_cast(storage.get()); \ for (int y = 0; y < count; y++) { \ chromium_jpeg_read_scanlines(dinfo, &storagePtr, 1); \ @@ -563,16 +484,13 @@ public: return SkCodec::kSuccess; } - SkEncodedFormat onGetEncodedFormat() const override { - return kJPEG_SkEncodedFormat; - } +#ifndef TURBO_HAS_SKIP +#undef chromium_jpeg_skip_scanlines +#endif private: SkAutoTDelete fCodec; - SkAutoMalloc fStorage; // Only used if sampling is needed - uint8_t* fSrcRow; // Only used if sampling is needed SkCodec::Options fOpts; - SkAutoTDelete fSwizzler; typedef SkScanlineDecoder INHERITED; }; @@ -584,7 +502,6 @@ SkScanlineDecoder* SkJpegCodec::NewSDFromStream(SkStream* stream) { } const SkImageInfo& srcInfo = codec->getInfo(); - // Return the new scanline decoder return SkNEW_ARGS(SkJpegScanlineDecoder, (srcInfo, codec.detach())); } diff --git a/src/codec/SkJpegCodec.h b/src/codec/SkJpegCodec.h index fac7d96075..62a5bbc4cf 100644 --- a/src/codec/SkJpegCodec.h +++ b/src/codec/SkJpegCodec.h @@ -110,13 +110,19 @@ private: bool setOutputColorSpace(const SkImageInfo& dst); /* - * Checks if we can natively scale to the requested dimensions and natively scales the - * dimensions if possible + * Checks if we can scale to the requested dimensions and scales the dimensions + * if possible */ - bool nativelyScaleToDimensions(uint32_t width, uint32_t height); + bool scaleToDimensions(uint32_t width, uint32_t height); + + /* + * Create the swizzler based on the encoded format + */ + void initializeSwizzler(const SkImageInfo& dstInfo, void* dst, size_t dstRowBytes, + const Options& options); SkAutoTDelete fDecoderMgr; - + friend class SkJpegScanlineDecoder; typedef SkCodec INHERITED; diff --git a/src/codec/SkScaledCodec.cpp b/src/codec/SkScaledCodec.cpp deleted file mode 100644 index e0158b6b4e..0000000000 --- a/src/codec/SkScaledCodec.cpp +++ /dev/null @@ -1,261 +0,0 @@ -/* - * 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 "SkCodecPriv.h" -#include "SkScaledCodec.h" -#include "SkStream.h" -#include "SkWebpCodec.h" - - -SkCodec* SkScaledCodec::NewFromStream(SkStream* stream) { - bool isWebp = SkWebpCodec::IsWebp(stream); - if (!stream->rewind()) { - return NULL; - } - if (isWebp) { - // Webp codec supports scaling and subsetting natively - return SkWebpCodec::NewFromStream(stream); - } - - SkAutoTDelete scanlineDecoder(SkScanlineDecoder::NewFromStream(stream)); - if (NULL == scanlineDecoder) { - return NULL; - } - - // wrap in new SkScaledCodec - return SkNEW_ARGS(SkScaledCodec, (scanlineDecoder.detach())); -} - -SkCodec* SkScaledCodec::NewFromData(SkData* data) { - if (!data) { - return NULL; - } - return NewFromStream(SkNEW_ARGS(SkMemoryStream, (data))); -} - -SkScaledCodec::SkScaledCodec(SkScanlineDecoder* scanlineDecoder) - : INHERITED(scanlineDecoder->getInfo(), NULL) - , fScanlineDecoder(scanlineDecoder) -{} - -SkScaledCodec::~SkScaledCodec() {} - -// 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 get_scaled_dimension(int srcDimension, int sampleSize) { - if (sampleSize > srcDimension) { - return 1; - } - return srcDimension / sampleSize; -} - -static SkISize best_scaled_dimensions(const SkISize& origDims, const SkISize& nativeDims, - const SkISize& scaledCodecDims, float desiredScale) { - if (nativeDims == scaledCodecDims) { - // does not matter which to return if equal. Return here to skip below calculations - return nativeDims; - } - float idealWidth = origDims.width() * desiredScale; - float idealHeight = origDims.height() * desiredScale; - - // calculate difference between native dimensions and ideal dimensions - float nativeWDiff = SkTAbs(idealWidth - nativeDims.width()); - float nativeHDiff = SkTAbs(idealHeight - nativeDims.height()); - float nativeDiff = (nativeWDiff + nativeHDiff) / 2; - - // calculate difference between scaledCodec dimensions and ideal dimensions - float scaledCodecWDiff = SkTAbs(idealWidth - scaledCodecDims.width()); - float scaledCodecHDiff = SkTAbs(idealHeight - scaledCodecDims.height()); - float scaledCodecDiff = (scaledCodecWDiff + scaledCodecHDiff) / 2; - - // return dimensions closest to ideal dimensions. - // If the differences are equal, return nativeDims, as native scaling is more efficient. - return nativeDiff > scaledCodecDiff ? scaledCodecDims : nativeDims; - -} -/* - * Return a valid set of output dimensions for this decoder, given an input scale - */ -SkISize SkScaledCodec::onGetScaledDimensions(float desiredScale) const { - SkISize nativeDimensions = fScanlineDecoder->getScaledDimensions(desiredScale); - // support scaling down by integer numbers. Ex: 1/2, 1/3, 1/4 ... - SkISize scaledCodecDimensions; - if (desiredScale > 0.5f) { - // sampleSize = 1 - scaledCodecDimensions = fScanlineDecoder->getInfo().dimensions(); - } - // sampleSize determines the step size between samples - // Ex: sampleSize = 2, sample every second pixel in x and y directions - int sampleSize = int(1 / desiredScale); - - int scaledWidth = get_scaled_dimension(this->getInfo().width(), sampleSize); - int scaledHeight = get_scaled_dimension(this->getInfo().height(), sampleSize); - - // Return the calculated output dimensions for the given scale - scaledCodecDimensions = SkISize::Make(scaledWidth, scaledHeight); - - return best_scaled_dimensions(this->getInfo().dimensions(), nativeDimensions, - scaledCodecDimensions, desiredScale); -} - -// check if scaling to dstInfo size from srcInfo size using sampleSize is possible -static bool scaling_supported(const SkImageInfo& dstInfo, const SkImageInfo& srcInfo, - int* sampleX, int* sampleY) { - SkScaledCodec::ComputeSampleSize(dstInfo, srcInfo, sampleX, sampleY); - const int dstWidth = dstInfo.width(); - const int dstHeight = dstInfo.height(); - const int srcWidth = srcInfo.width(); - const int srcHeight = srcInfo.height(); - // only support down sampling, not up sampling - if (dstWidth > srcWidth || dstHeight > srcHeight) { - return false; - } - // check that srcWidth is scaled down by an integer value - if (get_scaled_dimension(srcWidth, *sampleX) != dstWidth) { - return false; - } - // check that src height is scaled down by an integer value - if (get_scaled_dimension(srcHeight, *sampleY) != dstHeight) { - return false; - } - // 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) { - return false; - } - } - return true; -} - -// calculates sampleSize in x and y direction -void SkScaledCodec::ComputeSampleSize(const SkImageInfo& dstInfo, const SkImageInfo& srcInfo, - int* sampleXPtr, int* sampleYPtr) { - int srcWidth = srcInfo.width(); - int dstWidth = dstInfo.width(); - int srcHeight = srcInfo.height(); - int dstHeight = dstInfo.height(); - - int sampleX = srcWidth / dstWidth; - int 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 (get_scaled_dimension(srcWidth, sampleY) == dstWidth) { - sampleX = sampleY; - } else if (get_scaled_dimension(srcHeight, sampleX) == dstHeight) { - sampleY = sampleX; - } - } - } - - if (sampleXPtr) { - *sampleXPtr = sampleX; - } - if (sampleYPtr) { - *sampleYPtr = sampleY; - } -} - -// TODO: Implement subsetting in onGetPixels which works when and when not sampling - -SkCodec::Result SkScaledCodec::onGetPixels(const SkImageInfo& requestedInfo, void* dst, - size_t rowBytes, const Options& options, - SkPMColor ctable[], int* ctableCount) { - - if (options.fSubset) { - // Subsets are not supported. - return kUnimplemented; - } - - Result result = fScanlineDecoder->start(requestedInfo, &options, ctable, ctableCount); - if (kSuccess == result) { - // native decode supported - return fScanlineDecoder->getScanlines(dst, requestedInfo.height(), rowBytes); - - } - - if (kInvalidScale != result) { - // no scaling requested - return result; - } - - // scaling requested - int sampleX; - int sampleY; - if (!scaling_supported(requestedInfo, fScanlineDecoder->getInfo(), &sampleX, &sampleY)) { - return kInvalidScale; - } - // set first sample pixel in y direction - int Y0 = sampleY >> 1; - - int dstHeight = requestedInfo.height(); - int srcHeight = fScanlineDecoder->getInfo().height(); - - SkImageInfo info = requestedInfo; - // use original height as scanlineDecoder does not support y sampling natively - info = info.makeWH(requestedInfo.width(), srcHeight); - - // update scanlineDecoder with new info - result = fScanlineDecoder->start(info, &options, ctable, ctableCount); - if (kSuccess != result) { - return result; - } - - const bool requiresPostYSampling = fScanlineDecoder->requiresPostYSampling(); - - if (requiresPostYSampling) { - SkAutoMalloc storage(srcHeight * rowBytes); - uint8_t* storagePtr = static_cast(storage.get()); - result = fScanlineDecoder->getScanlines(storagePtr, srcHeight, rowBytes); - if (kSuccess != result) { - return result; - } - storagePtr += Y0 * rowBytes; - for (int y = 0; y < dstHeight; y++) { - memcpy(dst, storagePtr, rowBytes); - storagePtr += sampleY * rowBytes; - dst = SkTAddOffset(dst, rowBytes); - } - } else { - // does not require post y sampling - result = fScanlineDecoder->skipScanlines(Y0); - if (kSuccess != result) { - return result; - } - for (int y = 0; y < dstHeight; y++) { - result = fScanlineDecoder->getScanlines(dst, 1, rowBytes); - if (kSuccess != result) { - return result; - } - if (y < dstHeight - 1) { - result = fScanlineDecoder->skipScanlines(sampleY - 1); - if (kSuccess != result) { - return result; - } - } - dst = SkTAddOffset(dst, rowBytes); - } - } - return kSuccess; -} diff --git a/src/codec/SkSwizzler.cpp b/src/codec/SkSwizzler.cpp index 741fe18cde..b2b7f927ac 100644 --- a/src/codec/SkSwizzler.cpp +++ b/src/codec/SkSwizzler.cpp @@ -7,7 +7,6 @@ #include "SkCodecPriv.h" #include "SkColorPriv.h" -#include "SkScaledCodec.h" #include "SkSwizzler.h" #include "SkTemplates.h" #include "SkUtils.h" @@ -20,107 +19,114 @@ SkSwizzler::ResultAlpha SkSwizzler::GetResult(uint8_t zeroAlpha, return (((uint16_t) maxAlpha) << 8) | zeroAlpha; } -// samples the row. Does not do anything else but sampling -static SkSwizzler::ResultAlpha sample565(void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, - int width, int deltaSrc, int offset, const SkPMColor ctable[]){ - - src += offset; - uint16_t* SK_RESTRICT dst = (uint16_t*) dstRow; - for (int x = 0; x < width; x++) { - dst[x] = src[1] << 8 | src[0]; - src += deltaSrc; - } - // 565 is always opaque - return SkSwizzler::kOpaque_ResultAlpha; -} - // kBit // These routines exclusively choose between white and black #define GRAYSCALE_BLACK 0 #define GRAYSCALE_WHITE 0xFF - -// same as swizzle_bit_to_index and swizzle_bit_to_n32 except for value assigned to dst[x] static SkSwizzler::ResultAlpha swizzle_bit_to_grayscale( - void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth, - int deltaSrc, int offset, const SkPMColor* /*ctable*/) { - + void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width, + int /*bitsPerPixel*/, const SkPMColor* /*ctable*/) { uint8_t* SK_RESTRICT dst = (uint8_t*) dstRow; - // increment src by byte offset and bitIndex by bit offset - src += offset / 8; - int bitIndex = offset % 8; - uint8_t currByte = *src; - for (int x = 0; x < dstWidth; x++) { - dst[x] = ((currByte >> (7-bitIndex)) & 1) ? GRAYSCALE_WHITE : GRAYSCALE_BLACK; - int bitOffset = bitIndex + deltaSrc; - bitIndex = bitOffset % 8; - currByte = *(src += bitOffset / 8); + // Determine how many full bytes are in the row + int bytesInRow = width >> 3; + int i; + for (i = 0; i < bytesInRow; i++) { + U8CPU currByte = src[i]; + for (int j = 0; j < 8; j++) { + dst[j] = ((currByte >> (7 - j)) & 1) ? GRAYSCALE_WHITE : GRAYSCALE_BLACK; + } + dst += 8; } + // Finish the remaining bits + width &= 7; + if (width > 0) { + U8CPU currByte = src[i]; + for (int j = 0; j < width; j++) { + dst[j] = ((currByte >> 7) & 1) ? GRAYSCALE_WHITE : GRAYSCALE_BLACK; + currByte <<= 1; + } + } return SkSwizzler::kOpaque_ResultAlpha; } #undef GRAYSCALE_BLACK #undef GRAYSCALE_WHITE -// same as swizzle_bit_to_grayscale and swizzle_bit_to_n32 except for value assigned to dst[x] static SkSwizzler::ResultAlpha swizzle_bit_to_index( - void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth, - int deltaSrc, int offset, const SkPMColor* /*ctable*/) { + void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width, + int /*bitsPerPixel*/, const SkPMColor* /*ctable*/) { uint8_t* SK_RESTRICT dst = (uint8_t*) dstRow; - // increment src by byte offset and bitIndex by bit offset - src += offset / 8; - int bitIndex = offset % 8; - uint8_t currByte = *src; - for (int x = 0; x < dstWidth; x++) { - dst[x] = ((currByte >> (7-bitIndex)) & 1); - int bitOffset = bitIndex + deltaSrc; - bitIndex = bitOffset % 8; - currByte = *(src += bitOffset / 8); + // Determine how many full bytes are in the row + int bytesInRow = width >> 3; + int i; + for (i = 0; i < bytesInRow; i++) { + U8CPU currByte = src[i]; + for (int j = 0; j < 8; j++) { + dst[j] = (currByte >> (7 - j)) & 1; + } + dst += 8; } + // Finish the remaining bits + width &= 7; + if (width > 0) { + U8CPU currByte = src[i]; + for (int j = 0; j < width; j++) { + dst[j] = ((currByte >> 7) & 1); + currByte <<= 1; + } + } return SkSwizzler::kOpaque_ResultAlpha; } -// same as swizzle_bit_to_grayscale and swizzle_bit_to_index except for value assigned to dst[x] static SkSwizzler::ResultAlpha swizzle_bit_to_n32( - void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth, - int deltaSrc, int offset, const SkPMColor* /*ctable*/) { + void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width, + int /*bitsPerPixel*/, const SkPMColor* /*ctable*/) { SkPMColor* SK_RESTRICT dst = (SkPMColor*) dstRow; - // increment src by byte offset and bitIndex by bit offset - src += offset / 8; - int bitIndex = offset % 8; - uint8_t currByte = *src; - for (int x = 0; x < dstWidth; x++) { - dst[x] = ((currByte >> (7 - bitIndex)) & 1) ? SK_ColorWHITE : SK_ColorBLACK; - int bitOffset = bitIndex + deltaSrc; - bitIndex = bitOffset % 8; - currByte = *(src += bitOffset / 8); + // Determine how many full bytes are in the row + int bytesInRow = width >> 3; + int i; + for (i = 0; i < bytesInRow; i++) { + U8CPU currByte = src[i]; + for (int j = 0; j < 8; j++) { + dst[j] = ((currByte >> (7 - j)) & 1) ? SK_ColorWHITE : SK_ColorBLACK; + } + dst += 8; } + // Finish the remaining bits + width &= 7; + if (width > 0) { + U8CPU currByte = src[i]; + for (int j = 0; j < width; j++) { + dst[j] = ((currByte >> 7) & 1) ? SK_ColorWHITE : SK_ColorBLACK; + currByte <<= 1; + } + } return SkSwizzler::kOpaque_ResultAlpha; } // kIndex1, kIndex2, kIndex4 static SkSwizzler::ResultAlpha swizzle_small_index_to_index( - void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth, - int bitsPerPixel, int offset, const SkPMColor ctable[]) { + void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width, + int bitsPerPixel, const SkPMColor ctable[]) { - src += offset; uint8_t* SK_RESTRICT dst = (uint8_t*) dstRow; INIT_RESULT_ALPHA; const uint32_t pixelsPerByte = 8 / bitsPerPixel; - const size_t rowBytes = compute_row_bytes_ppb(dstWidth, pixelsPerByte); + const size_t rowBytes = compute_row_bytes_ppb(width, pixelsPerByte); const uint8_t mask = (1 << bitsPerPixel) - 1; int x = 0; for (uint32_t byte = 0; byte < rowBytes; byte++) { uint8_t pixelData = src[byte]; - for (uint32_t p = 0; p < pixelsPerByte && x < dstWidth; p++) { + for (uint32_t p = 0; p < pixelsPerByte && x < width; p++) { uint8_t index = (pixelData >> (8 - bitsPerPixel)) & mask; UPDATE_RESULT_ALPHA(ctable[index] >> SK_A32_SHIFT); dst[x] = index; @@ -132,19 +138,18 @@ static SkSwizzler::ResultAlpha swizzle_small_index_to_index( } static SkSwizzler::ResultAlpha swizzle_small_index_to_n32( - void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth, - int bitsPerPixel, int offset, const SkPMColor ctable[]) { + void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width, + int bitsPerPixel, const SkPMColor ctable[]) { - src += offset; SkPMColor* SK_RESTRICT dst = (SkPMColor*) dstRow; INIT_RESULT_ALPHA; const uint32_t pixelsPerByte = 8 / bitsPerPixel; - const size_t rowBytes = compute_row_bytes_ppb(dstWidth, pixelsPerByte); + const size_t rowBytes = compute_row_bytes_ppb(width, pixelsPerByte); const uint8_t mask = (1 << bitsPerPixel) - 1; int x = 0; for (uint32_t byte = 0; byte < rowBytes; byte++) { uint8_t pixelData = src[byte]; - for (uint32_t p = 0; p < pixelsPerByte && x < dstWidth; p++) { + for (uint32_t p = 0; p < pixelsPerByte && x < width; p++) { uint8_t index = (pixelData >> (8 - bitsPerPixel)) & mask; SkPMColor c = ctable[index]; UPDATE_RESULT_ALPHA(c >> SK_A32_SHIFT); @@ -159,75 +164,58 @@ static SkSwizzler::ResultAlpha swizzle_small_index_to_n32( // kIndex static SkSwizzler::ResultAlpha swizzle_index_to_index( - void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth, - int deltaSrc, int offset, const SkPMColor ctable[]) { + void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width, + int bytesPerPixel, const SkPMColor ctable[]) { - src += offset; uint8_t* SK_RESTRICT dst = (uint8_t*) dstRow; - INIT_RESULT_ALPHA; + memcpy(dst, src, width); // TODO (msarett): Should we skip the loop here and guess that the row is opaque/not opaque? // SkScaledBitmap sampler just guesses that it is opaque. This is dangerous // and probably wrong since gif and bmp (rarely) may have alpha. - if (1 == deltaSrc) { - // A non-zero offset is only used when sampling, meaning that deltaSrc will be - // greater than 1. The below loop relies on the fact that src remains unchanged. - SkASSERT(0 == offset); - memcpy(dst, src, dstWidth); - for (int x = 0; x < dstWidth; x++) { - UPDATE_RESULT_ALPHA(ctable[src[x]] >> SK_A32_SHIFT); - } - } else { - for (int x = 0; x < dstWidth; x++) { - dst[x] = *src; - UPDATE_RESULT_ALPHA(ctable[*src] >> SK_A32_SHIFT); - src += deltaSrc; - } + INIT_RESULT_ALPHA; + for (int x = 0; x < width; x++) { + UPDATE_RESULT_ALPHA(ctable[src[x]] >> SK_A32_SHIFT); } return COMPUTE_RESULT_ALPHA; } static SkSwizzler::ResultAlpha swizzle_index_to_n32( - void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth, - int deltaSrc, int offset, const SkPMColor ctable[]) { + void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width, + int bytesPerPixel, const SkPMColor ctable[]) { - src += offset; SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; INIT_RESULT_ALPHA; - for (int x = 0; x < dstWidth; x++) { - SkPMColor c = ctable[*src]; + for (int x = 0; x < width; x++) { + SkPMColor c = ctable[src[x]]; UPDATE_RESULT_ALPHA(c >> SK_A32_SHIFT); dst[x] = c; - src += deltaSrc; } return COMPUTE_RESULT_ALPHA; } static SkSwizzler::ResultAlpha swizzle_index_to_n32_skipZ( - void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth, - int deltaSrc, int offset, const SkPMColor ctable[]) { + void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width, + int bytesPerPixel, const SkPMColor ctable[]) { - src += offset; SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; INIT_RESULT_ALPHA; - for (int x = 0; x < dstWidth; x++) { - SkPMColor c = ctable[*src]; + for (int x = 0; x < width; x++) { + SkPMColor c = ctable[src[x]]; UPDATE_RESULT_ALPHA(c >> SK_A32_SHIFT); if (c != 0) { dst[x] = c; } - src += deltaSrc; } return COMPUTE_RESULT_ALPHA; } static SkSwizzler::ResultAlpha swizzle_index_to_565( - void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth, - int bytesPerPixel, int offset, const SkPMColor ctable[]) { + void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width, + int bytesPerPixel, const SkPMColor ctable[]) { // FIXME: Support dithering? Requires knowing y, which I think is a bigger // change. - src += offset; uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow; - for (int x = 0; x < dstWidth; x++) { + for (int x = 0; x < width; x++) { dst[x] = SkPixel32ToPixel16(ctable[*src]); src += bytesPerPixel; } @@ -240,42 +228,29 @@ static SkSwizzler::ResultAlpha swizzle_index_to_565( // kGray static SkSwizzler::ResultAlpha swizzle_gray_to_n32( - void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth, - int deltaSrc, int offset, const SkPMColor ctable[]) { + void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width, + int bytesPerPixel, const SkPMColor ctable[]) { - src += offset; SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; - for (int x = 0; x < dstWidth; x++) { - dst[x] = SkPackARGB32NoCheck(0xFF, *src, *src, *src); - src += deltaSrc; + for (int x = 0; x < width; x++) { + dst[x] = SkPackARGB32NoCheck(0xFF, src[x], src[x], src[x]); } return SkSwizzler::kOpaque_ResultAlpha; } static SkSwizzler::ResultAlpha swizzle_gray_to_gray( - void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth, - int deltaSrc, int offset, const SkPMColor ctable[]) { - - src += offset; - uint8_t* SK_RESTRICT dst = (uint8_t*) dstRow; - if (1 == deltaSrc) { - memcpy(dstRow, src, dstWidth); - } else { - for (int x = 0; x < dstWidth; x++) { - dst[x] = src[0]; - src += deltaSrc; - } - } + void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width, + int bytesPerPixel, const SkPMColor ctable[]) { + memcpy(dstRow, src, width); return SkSwizzler::kOpaque_ResultAlpha; } static SkSwizzler::ResultAlpha swizzle_gray_to_565( - void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth, - int bytesPerPixel, int offset, const SkPMColor ctable[]) { + void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width, + int bytesPerPixel, const SkPMColor ctable[]) { // FIXME: Support dithering? - src += offset; uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow; - for (int x = 0; x < dstWidth; x++) { + for (int x = 0; x < width; x++) { dst[x] = SkPack888ToRGB16(src[0], src[0], src[0]); src += bytesPerPixel; } @@ -285,14 +260,13 @@ static SkSwizzler::ResultAlpha swizzle_gray_to_565( // kBGRX static SkSwizzler::ResultAlpha swizzle_bgrx_to_n32( - void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth, - int deltaSrc, int offset, const SkPMColor ctable[]) { + void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width, + int bytesPerPixel, const SkPMColor ctable[]) { - src += offset; SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; - for (int x = 0; x < dstWidth; x++) { + for (int x = 0; x < width; x++) { dst[x] = SkPackARGB32NoCheck(0xFF, src[2], src[1], src[0]); - src += deltaSrc; + src += bytesPerPixel; } return SkSwizzler::kOpaque_ResultAlpha; } @@ -300,58 +274,54 @@ static SkSwizzler::ResultAlpha swizzle_bgrx_to_n32( // kBGRA static SkSwizzler::ResultAlpha swizzle_bgra_to_n32_unpremul( - void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth, - int deltaSrc, int offset, const SkPMColor ctable[]) { + void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width, + int bytesPerPixel, const SkPMColor ctable[]) { - src += offset; SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; INIT_RESULT_ALPHA; - for (int x = 0; x < dstWidth; x++) { + for (int x = 0; x < width; x++) { uint8_t alpha = src[3]; UPDATE_RESULT_ALPHA(alpha); dst[x] = SkPackARGB32NoCheck(alpha, src[2], src[1], src[0]); - src += deltaSrc; + src += bytesPerPixel; } return COMPUTE_RESULT_ALPHA; } static SkSwizzler::ResultAlpha swizzle_bgra_to_n32_premul( - void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth, - int deltaSrc, int offset, const SkPMColor ctable[]) { + void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width, + int bytesPerPixel, const SkPMColor ctable[]) { - src += offset; SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; INIT_RESULT_ALPHA; - for (int x = 0; x < dstWidth; x++) { + for (int x = 0; x < width; x++) { uint8_t alpha = src[3]; UPDATE_RESULT_ALPHA(alpha); dst[x] = SkPreMultiplyARGB(alpha, src[2], src[1], src[0]); - src += deltaSrc; + src += bytesPerPixel; } return COMPUTE_RESULT_ALPHA; } // kRGBX static SkSwizzler::ResultAlpha swizzle_rgbx_to_n32( - void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth, - int deltaSrc, int offset, const SkPMColor ctable[]) { + void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width, + int bytesPerPixel, const SkPMColor ctable[]) { - src += offset; SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; - for (int x = 0; x < dstWidth; x++) { + for (int x = 0; x < width; x++) { dst[x] = SkPackARGB32(0xFF, src[0], src[1], src[2]); - src += deltaSrc; + src += bytesPerPixel; } return SkSwizzler::kOpaque_ResultAlpha; } static SkSwizzler::ResultAlpha swizzle_rgbx_to_565( - void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth, - int bytesPerPixel, int offset, const SkPMColor ctable[]) { + void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width, + int bytesPerPixel, const SkPMColor ctable[]) { // FIXME: Support dithering? - src += offset; uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow; - for (int x = 0; x < dstWidth; x++) { + for (int x = 0; x < width; x++) { dst[x] = SkPack888ToRGB16(src[0], src[1], src[2]); src += bytesPerPixel; } @@ -361,51 +331,48 @@ static SkSwizzler::ResultAlpha swizzle_rgbx_to_565( // kRGBA static SkSwizzler::ResultAlpha swizzle_rgba_to_n32_premul( - void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth, - int deltaSrc, int offset, const SkPMColor ctable[]) { + void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width, + int bytesPerPixel, const SkPMColor ctable[]) { - src += offset; SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; INIT_RESULT_ALPHA; - for (int x = 0; x < dstWidth; x++) { + for (int x = 0; x < width; x++) { unsigned alpha = src[3]; UPDATE_RESULT_ALPHA(alpha); dst[x] = SkPreMultiplyARGB(alpha, src[0], src[1], src[2]); - src += deltaSrc; + src += bytesPerPixel; } return COMPUTE_RESULT_ALPHA; } static SkSwizzler::ResultAlpha swizzle_rgba_to_n32_unpremul( - void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth, - int deltaSrc, int offset, const SkPMColor ctable[]) { + void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width, + int bytesPerPixel, const SkPMColor ctable[]) { - src += offset; uint32_t* SK_RESTRICT dst = reinterpret_cast(dstRow); INIT_RESULT_ALPHA; - for (int x = 0; x < dstWidth; x++) { + for (int x = 0; x < width; x++) { unsigned alpha = src[3]; UPDATE_RESULT_ALPHA(alpha); dst[x] = SkPackARGB32NoCheck(alpha, src[0], src[1], src[2]); - src += deltaSrc; + src += bytesPerPixel; } return COMPUTE_RESULT_ALPHA; } static SkSwizzler::ResultAlpha swizzle_rgba_to_n32_premul_skipZ( - void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth, - int deltaSrc, int offset, const SkPMColor ctable[]) { + void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width, + int bytesPerPixel, const SkPMColor ctable[]) { - src += offset; SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; INIT_RESULT_ALPHA; - for (int x = 0; x < dstWidth; x++) { + for (int x = 0; x < width; x++) { unsigned alpha = src[3]; UPDATE_RESULT_ALPHA(alpha); if (0 != alpha) { dst[x] = SkPreMultiplyARGB(alpha, src[0], src[1], src[2]); } - src += deltaSrc; + src += bytesPerPixel; } return COMPUTE_RESULT_ALPHA; } @@ -418,12 +385,11 @@ static SkSwizzler::ResultAlpha swizzle_rgba_to_n32_premul_skipZ( decide whether to switch to unpremul default. static bool swizzle_rgba_to_n32_unpremul_skipZ(void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, - int dstWidth, int bitsPerPixel, int offset, + int width, int bitsPerPixel, const SkPMColor[]) { - src += offset; SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; unsigned alphaMask = 0xFF; - for (int x = 0; x < dstWidth; x++) { + for (int x = 0; x < width; x++) { unsigned alpha = src[3]; // NOTE: We cheat here. The caller requested unpremul and skip zeroes. It's possible // the color components are not zero, but we skip them anyway, meaning they'll remain @@ -440,10 +406,9 @@ static bool swizzle_rgba_to_n32_unpremul_skipZ(void* SK_RESTRICT dstRow, SkSwizzler* SkSwizzler::CreateSwizzler(SkSwizzler::SrcConfig sc, const SkPMColor* ctable, - const SkImageInfo& dstInfo, - SkCodec::ZeroInitialized zeroInit, - const SkImageInfo& srcInfo) { - if (dstInfo.colorType() == kUnknown_SkColorType || kUnknown == sc) { + const SkImageInfo& info, + SkCodec::ZeroInitialized zeroInit) { + if (info.colorType() == kUnknown_SkColorType || kUnknown == sc) { return NULL; } if ((kIndex == sc || kIndex4 == sc || kIndex2 == sc || kIndex1 == sc) @@ -451,10 +416,9 @@ SkSwizzler* SkSwizzler::CreateSwizzler(SkSwizzler::SrcConfig sc, return NULL; } RowProc proc = NULL; - switch (sc) { case kBit: - switch (dstInfo.colorType()) { + switch (info.colorType()) { case kN32_SkColorType: proc = &swizzle_bit_to_n32; break; @@ -471,7 +435,7 @@ SkSwizzler* SkSwizzler::CreateSwizzler(SkSwizzler::SrcConfig sc, case kIndex1: case kIndex2: case kIndex4: - switch (dstInfo.colorType()) { + switch (info.colorType()) { case kN32_SkColorType: proc = &swizzle_small_index_to_n32; break; @@ -483,7 +447,7 @@ SkSwizzler* SkSwizzler::CreateSwizzler(SkSwizzler::SrcConfig sc, } break; case kIndex: - switch (dstInfo.colorType()) { + switch (info.colorType()) { case kN32_SkColorType: // We assume the color premultiplied ctable (or not) as desired. if (SkCodec::kYes_ZeroInitialized == zeroInit) { @@ -505,7 +469,7 @@ SkSwizzler* SkSwizzler::CreateSwizzler(SkSwizzler::SrcConfig sc, } break; case kGray: - switch (dstInfo.colorType()) { + switch (info.colorType()) { case kN32_SkColorType: proc = &swizzle_gray_to_n32; break; @@ -521,7 +485,7 @@ SkSwizzler* SkSwizzler::CreateSwizzler(SkSwizzler::SrcConfig sc, break; case kBGR: case kBGRX: - switch (dstInfo.colorType()) { + switch (info.colorType()) { case kN32_SkColorType: proc = &swizzle_bgrx_to_n32; break; @@ -530,9 +494,9 @@ SkSwizzler* SkSwizzler::CreateSwizzler(SkSwizzler::SrcConfig sc, } break; case kBGRA: - switch (dstInfo.colorType()) { + switch (info.colorType()) { case kN32_SkColorType: - switch (dstInfo.alphaType()) { + switch (info.alphaType()) { case kUnpremul_SkAlphaType: proc = &swizzle_bgra_to_n32_unpremul; break; @@ -549,7 +513,7 @@ SkSwizzler* SkSwizzler::CreateSwizzler(SkSwizzler::SrcConfig sc, break; case kRGBX: // TODO: Support other swizzles. - switch (dstInfo.colorType()) { + switch (info.colorType()) { case kN32_SkColorType: proc = &swizzle_rgbx_to_n32; break; @@ -560,9 +524,9 @@ SkSwizzler* SkSwizzler::CreateSwizzler(SkSwizzler::SrcConfig sc, } break; case kRGBA: - switch (dstInfo.colorType()) { + switch (info.colorType()) { case kN32_SkColorType: - if (dstInfo.alphaType() == kUnpremul_SkAlphaType) { + if (info.alphaType() == kUnpremul_SkAlphaType) { // Respect zeroInit? proc = &swizzle_rgba_to_n32_unpremul; } else { @@ -578,7 +542,7 @@ SkSwizzler* SkSwizzler::CreateSwizzler(SkSwizzler::SrcConfig sc, } break; case kRGB: - switch (dstInfo.colorType()) { + switch (info.colorType()) { case kN32_SkColorType: proc = &swizzle_rgbx_to_n32; break; @@ -586,14 +550,6 @@ SkSwizzler* SkSwizzler::CreateSwizzler(SkSwizzler::SrcConfig sc, break; } break; - case kRGB_565: - switch (dstInfo.colorType()) { - case kRGB_565_SkColorType: - proc = &sample565; - break; - default: - break; - } default: break; } @@ -602,31 +558,22 @@ SkSwizzler* SkSwizzler::CreateSwizzler(SkSwizzler::SrcConfig sc, } // Store deltaSrc in bytes if it is an even multiple, otherwise use bits - int deltaSrc = SkIsAlign8(BitsPerPixel(sc)) ? BytesPerPixel(sc) : BitsPerPixel(sc); - - // get sampleX based on srcInfo and dstInfo dimensions - int sampleX; - SkScaledCodec::ComputeSampleSize(dstInfo, srcInfo, &sampleX, NULL); - - return SkNEW_ARGS(SkSwizzler, (proc, ctable, deltaSrc, dstInfo, sampleX)); + int deltaSrc = SkIsAlign8(BitsPerPixel(sc)) ? BytesPerPixel(sc) : + BitsPerPixel(sc); + return SkNEW_ARGS(SkSwizzler, (proc, ctable, deltaSrc, info)); } SkSwizzler::SkSwizzler(RowProc proc, const SkPMColor* ctable, - int deltaSrc, const SkImageInfo& info, int sampleX) + int deltaSrc, const SkImageInfo& info) : fRowProc(proc) , fColorTable(ctable) , fDeltaSrc(deltaSrc) , fDstInfo(info) - , fSampleX(sampleX) - , fX0(sampleX == 1 ? 0 : sampleX >> 1) -{ - // check that fX0 is less than original width - SkASSERT(fX0 >= 0 && fX0 < fDstInfo.width() * fSampleX); -} +{} SkSwizzler::ResultAlpha SkSwizzler::swizzle(void* dst, const uint8_t* SK_RESTRICT src) { SkASSERT(NULL != dst && NULL != src); - return fRowProc(dst, src, fDstInfo.width(), fSampleX * fDeltaSrc, fX0 * fDeltaSrc, fColorTable); + return fRowProc(dst, src, fDstInfo.width(), fDeltaSrc, fColorTable); } void SkSwizzler::Fill(void* dstStartRow, const SkImageInfo& dstInfo, size_t dstRowBytes, diff --git a/src/codec/SkSwizzler.h b/src/codec/SkSwizzler.h index b7132ce6d5..2fab7f66b6 100644 --- a/src/codec/SkSwizzler.h +++ b/src/codec/SkSwizzler.h @@ -117,22 +117,16 @@ public: /** * Create a new SkSwizzler. * @param SrcConfig Description of the format of the source. - * @param dstInfo describes the destination. + * @param SkImageInfo dimensions() describe both the src and the dst. + * Other fields describe the dst. * @param ZeroInitialized Whether dst is zero-initialized. The implementation may choose to skip writing zeroes * if set to kYes_ZeroInitialized. - * @param srcInfo is the info of the source. Used to calculate the width samplesize. - * Width sampling is supported by the swizzler, by skipping pixels when - swizzling the row. Height sampling is not supported by the swizzler, - but is implemented in SkScaledCodec. - Sampling in Y can be done by a client with a scanline decoder, - but sampling in X allows the swizzler to skip swizzling pixels and - reading from and writing to memory. * @return A new SkSwizzler or NULL on failure. */ static SkSwizzler* CreateSwizzler(SrcConfig, const SkPMColor* ctable, - const SkImageInfo& dstInfo, SkCodec::ZeroInitialized, - const SkImageInfo& srcInfo); + const SkImageInfo&, SkCodec::ZeroInitialized); + /** * Fill the remainder of the destination with a single color * @@ -187,16 +181,14 @@ private: * Method for converting raw data to Skia pixels. * @param dstRow Row in which to write the resulting pixels. * @param src Row of src data, in format specified by SrcConfig - * @param dstWidth Width in pixels of the destination + * @param width Width in pixels * @param deltaSrc if bitsPerPixel % 8 == 0, deltaSrc is bytesPerPixel * else, deltaSrc is bitsPerPixel * @param ctable Colors (used for kIndex source). - * @param offset The offset before the first pixel to sample. - Is in bytes or bits based on what deltaSrc is in. */ typedef ResultAlpha (*RowProc)(void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, - int dstWidth, int deltaSrc, int offset, + int width, int deltaSrc, const SkPMColor ctable[]); const RowProc fRowProc; @@ -207,10 +199,9 @@ private: // deltaSrc is bitsPerPixel const SkImageInfo fDstInfo; int fCurrY; - const int fX0; // first X coord to sample - const int fSampleX; // step between X samples - SkSwizzler(RowProc proc, const SkPMColor* ctable, int deltaSrc, const SkImageInfo& info, - int sampleX); + SkSwizzler(RowProc proc, const SkPMColor* ctable, int deltaSrc, + const SkImageInfo& info); + }; #endif // SkSwizzler_DEFINED