diff options
author | scroggo <scroggo@google.com> | 2015-03-02 12:23:48 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-03-02 12:23:48 -0800 |
commit | ca358852b4fed656d11107b2aaf28318a4518b49 (patch) | |
tree | 88ccb56a0f51ac9c40d639a095e328a3ac380257 /src/codec/SkSwizzler.cpp | |
parent | d0f5457c5ec974b3a0b080125a5ba07214c6d9d2 (diff) |
Add SkCodec, including PNG implementation.
DM:
Add a flag to use SkCodec instead of SkImageDecoder.
SkCodec:
Base class for codecs, allowing creation from an SkStream or an SkData.
An SkCodec, on creation, knows properties of the data like its width and height. Further calls can be used to generate the image.
TODO: Add scanline iterator
SkPngCodec:
New decoder for png. Wraps libpng. The code has been repurposed from SkImageDecoder_libpng.
TODO: Handle other destination colortypes
TODO: Substitute the transpose color
TODO: Allow silencing warnings
TODO: Use RGB instead of filler?
TODO: sRGB
SkSwizzler:
Simplified version of SkScaledSampler. Unlike the sampler, this object does no sampling.
TODO: Implement other swizzles.
BUG=skia:3257
Review URL: https://codereview.chromium.org/930283002
Diffstat (limited to 'src/codec/SkSwizzler.cpp')
-rw-r--r-- | src/codec/SkSwizzler.cpp | 221 |
1 files changed, 221 insertions, 0 deletions
diff --git a/src/codec/SkSwizzler.cpp b/src/codec/SkSwizzler.cpp new file mode 100644 index 0000000000..563933f13a --- /dev/null +++ b/src/codec/SkSwizzler.cpp @@ -0,0 +1,221 @@ +/* + * 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 "SkColorPriv.h" +#include "SkSwizzler.h" +#include "SkTemplates.h" + +// index + +#define A32_MASK_IN_PLACE (SkPMColor)(SK_A32_MASK << SK_A32_SHIFT) + +static bool swizzle_index_to_n32(void* SK_RESTRICT dstRow, + const uint8_t* SK_RESTRICT src, + int width, int deltaSrc, int, const SkPMColor ctable[]) { + + SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; + SkPMColor cc = A32_MASK_IN_PLACE; + for (int x = 0; x < width; x++) { + SkPMColor c = ctable[*src]; + cc &= c; + dst[x] = c; + src += deltaSrc; + } + return cc != A32_MASK_IN_PLACE; +} + +static bool swizzle_index_to_n32_skipZ(void* SK_RESTRICT dstRow, + const uint8_t* SK_RESTRICT src, + int width, int deltaSrc, int, + const SkPMColor ctable[]) { + + SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; + SkPMColor cc = A32_MASK_IN_PLACE; + for (int x = 0; x < width; x++) { + SkPMColor c = ctable[*src]; + cc &= c; + if (c != 0) { + dst[x] = c; + } + src += deltaSrc; + } + return cc != A32_MASK_IN_PLACE; +} + +#undef A32_MASK_IN_PLACE + +// n32 +static bool swizzle_rgbx_to_n32(void* SK_RESTRICT dstRow, + const uint8_t* SK_RESTRICT src, + int width, int deltaSrc, int, const SkPMColor[]) { + SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; + for (int x = 0; x < width; x++) { + dst[x] = SkPackARGB32(0xFF, src[0], src[1], src[2]); + src += deltaSrc; + } + return false; +} + +static bool swizzle_rgba_to_n32_premul(void* SK_RESTRICT dstRow, + const uint8_t* SK_RESTRICT src, + int width, int deltaSrc, int, const SkPMColor[]) { + SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; + unsigned alphaMask = 0xFF; + for (int x = 0; x < width; x++) { + unsigned alpha = src[3]; + dst[x] = SkPreMultiplyARGB(alpha, src[0], src[1], src[2]); + src += deltaSrc; + alphaMask &= alpha; + } + return alphaMask != 0xFF; +} + +static bool swizzle_rgba_to_n32_unpremul(void* SK_RESTRICT dstRow, + const uint8_t* SK_RESTRICT src, + int width, int deltaSrc, int, + const SkPMColor[]) { + uint32_t* SK_RESTRICT dst = reinterpret_cast<uint32_t*>(dstRow); + unsigned alphaMask = 0xFF; + for (int x = 0; x < width; x++) { + unsigned alpha = src[3]; + dst[x] = SkPackARGB32NoCheck(alpha, src[0], src[1], src[2]); + src += deltaSrc; + alphaMask &= alpha; + } + return alphaMask != 0xFF; +} + +static bool swizzle_rgba_to_n32_premul_skipZ(void* SK_RESTRICT dstRow, + const uint8_t* SK_RESTRICT src, + int width, int deltaSrc, int, + const SkPMColor[]) { + SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; + unsigned alphaMask = 0xFF; + for (int x = 0; x < width; x++) { + unsigned alpha = src[3]; + if (0 != alpha) { + dst[x] = SkPreMultiplyARGB(alpha, src[0], src[1], src[2]); + } + src += deltaSrc; + alphaMask &= alpha; + } + return alphaMask != 0xFF; +} + +/** + FIXME: This was my idea to cheat in order to continue taking advantage of skipping zeroes. + This would be fine for drawing normally, but not for drawing with transfer modes. Being + honest means we can draw correctly with transfer modes, with the cost of not being able + to take advantage of Android's free unwritten pages. Something to keep in mind when we + 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 width, int deltaSrc, int, + const SkPMColor[]) { + SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; + unsigned alphaMask = 0xFF; + 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 + // zero (implied by the request to skip zeroes). + if (0 != alpha) { + dst[x] = SkPackARGB32NoCheck(alpha, src[0], src[1], src[2]); + } + src += deltaSrc; + alphaMask &= alpha; + } + return alphaMask != 0xFF; +} +*/ + +SkSwizzler* SkSwizzler::CreateSwizzler(SkSwizzler::SrcConfig sc, const SkPMColor* ctable, + const SkImageInfo& info, void* dst, + size_t dstRowBytes, bool skipZeroes) { + if (info.colorType() == kUnknown_SkColorType) { + return NULL; + } + if (info.minRowBytes() > dstRowBytes) { + return NULL; + } + if (kIndex == sc && NULL == ctable) { + return NULL; + } + RowProc proc = NULL; + switch (sc) { + case kIndex: + switch (info.colorType()) { + case kN32_SkColorType: + // We assume the color premultiplied ctable (or not) as desired. + if (skipZeroes) { + proc = &swizzle_index_to_n32_skipZ; + } else { + proc = &swizzle_index_to_n32; + } + break; + + default: + break; + } + break; + case kRGBX: + // TODO: Support other swizzles. + switch (info.colorType()) { + case kN32_SkColorType: + proc = &swizzle_rgbx_to_n32; + break; + default: + break; + } + break; + case kRGBA: + switch (info.colorType()) { + case kN32_SkColorType: + if (info.alphaType() == kUnpremul_SkAlphaType) { + // Respect skipZeroes? + proc = &swizzle_rgba_to_n32_unpremul; + } else { + if (skipZeroes) { + proc = &swizzle_rgba_to_n32_premul_skipZ; + } else { + proc = &swizzle_rgba_to_n32_premul; + } + } + break; + default: + break; + } + break; + default: + break; + } + if (NULL == proc) { + return NULL; + } + return SkNEW_ARGS(SkSwizzler, (proc, ctable, BytesPerPixel(sc), info, dst, dstRowBytes)); +} + +SkSwizzler::SkSwizzler(RowProc proc, const SkPMColor* ctable, int srcBpp, + const SkImageInfo& info, void* dst, size_t rowBytes) + : fRowProc(proc) + , fColorTable(ctable) + , fSrcPixelSize(srcBpp) + , fDstInfo(info) + , fDstRow(dst) + , fDstRowBytes(rowBytes) + , fCurrY(0) +{ +} + +bool SkSwizzler::next(const uint8_t* SK_RESTRICT src) { + SkASSERT(fCurrY < fDstInfo.height()); + const bool hadAlpha = fRowProc(fDstRow, src, fDstInfo.width(), fSrcPixelSize, + fCurrY, fColorTable); + fCurrY++; + fDstRow = SkTAddOffset<void>(fDstRow, fDstRowBytes); + return hadAlpha; +} |