aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/codec/SkSwizzler.cpp
diff options
context:
space:
mode:
authorGravatar scroggo <scroggo@google.com>2015-03-02 12:23:48 -0800
committerGravatar Commit bot <commit-bot@chromium.org>2015-03-02 12:23:48 -0800
commitca358852b4fed656d11107b2aaf28318a4518b49 (patch)
tree88ccb56a0f51ac9c40d639a095e328a3ac380257 /src/codec/SkSwizzler.cpp
parentd0f5457c5ec974b3a0b080125a5ba07214c6d9d2 (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.cpp221
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;
+}