Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(898)

Unified Diff: src/images/SkScaledBitmapSampler.cpp

Issue 1828433004: Revert of Delete SkImageDecoder (Closed) Base URL: https://skia.googlesource.com/skia.git@fix-animator
Patch Set: Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/images/SkScaledBitmapSampler.h ('k') | src/images/bmpdecoderhelper.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/images/SkScaledBitmapSampler.cpp
diff --git a/src/images/SkScaledBitmapSampler.cpp b/src/images/SkScaledBitmapSampler.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..5ffd64889396b57ac8b5bf893f7f106212be00f1
--- /dev/null
+++ b/src/images/SkScaledBitmapSampler.cpp
@@ -0,0 +1,877 @@
+/*
+ * Copyright 2007 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#include "SkScaledBitmapSampler.h"
+#include "SkBitmap.h"
+#include "SkColorPriv.h"
+#include "SkDither.h"
+#include "SkTypes.h"
+
+// 8888
+
+static bool Sample_Gray_D8888(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[0], src[0]);
+ src += deltaSrc;
+ }
+ return false;
+}
+
+static SkScaledBitmapSampler::RowProc
+get_gray_to_8888_proc(const SkScaledBitmapSampler::Options& opts) {
+ // Dither, unpremul, and skipZeroes have no effect
+ return Sample_Gray_D8888;
+}
+
+static bool Sample_RGBx_D8888(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 SkScaledBitmapSampler::RowProc
+get_RGBx_to_8888_proc(const SkScaledBitmapSampler::Options& opts) {
+ // Dither, unpremul, and skipZeroes have no effect
+ return Sample_RGBx_D8888;
+}
+
+static bool Sample_RGBA_D8888(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 Sample_RGBA_D8888_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 Sample_RGBA_D8888_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;
+}
+
+static SkScaledBitmapSampler::RowProc
+get_RGBA_to_8888_proc(const SkScaledBitmapSampler::Options& opts) {
+ // Dither has no effect.
+ if (!opts.fPremultiplyAlpha) {
+ // We could check each component for a zero, at the expense of extra checks.
+ // For now, just return unpremul.
+ return Sample_RGBA_D8888_Unpremul;
+ }
+ // Supply the versions that premultiply the colors
+ if (opts.fSkipZeros) {
+ return Sample_RGBA_D8888_SkipZ;
+ }
+ return Sample_RGBA_D8888;
+}
+
+// 565
+
+static bool Sample_Gray_D565(void* SK_RESTRICT dstRow,
+ const uint8_t* SK_RESTRICT src,
+ int width, int deltaSrc, int, const SkPMColor[]) {
+ uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow;
+ for (int x = 0; x < width; x++) {
+ dst[x] = SkPack888ToRGB16(src[0], src[0], src[0]);
+ src += deltaSrc;
+ }
+ return false;
+}
+
+static bool Sample_Gray_D565_D(void* SK_RESTRICT dstRow,
+ const uint8_t* SK_RESTRICT src,
+ int width, int deltaSrc, int y, const SkPMColor[]) {
+ uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow;
+ DITHER_565_SCAN(y);
+ for (int x = 0; x < width; x++) {
+ dst[x] = SkDitherRGBTo565(src[0], src[0], src[0], DITHER_VALUE(x));
+ src += deltaSrc;
+ }
+ return false;
+}
+
+static SkScaledBitmapSampler::RowProc
+get_gray_to_565_proc(const SkScaledBitmapSampler::Options& opts) {
+ // Unpremul and skip zeroes make no difference
+ if (opts.fDither) {
+ return Sample_Gray_D565_D;
+ }
+ return Sample_Gray_D565;
+}
+
+static bool Sample_RGBx_D565(void* SK_RESTRICT dstRow,
+ const uint8_t* SK_RESTRICT src,
+ int width, int deltaSrc, int, const SkPMColor[]) {
+ uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow;
+ for (int x = 0; x < width; x++) {
+ dst[x] = SkPack888ToRGB16(src[0], src[1], src[2]);
+ src += deltaSrc;
+ }
+ return false;
+}
+
+static bool Sample_RGBx_D565_D(void* SK_RESTRICT dstRow,
+ const uint8_t* SK_RESTRICT src,
+ int width, int deltaSrc, int y,
+ const SkPMColor[]) {
+ uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow;
+ DITHER_565_SCAN(y);
+ for (int x = 0; x < width; x++) {
+ dst[x] = SkDitherRGBTo565(src[0], src[1], src[2], DITHER_VALUE(x));
+ src += deltaSrc;
+ }
+ return false;
+}
+
+static SkScaledBitmapSampler::RowProc
+get_RGBx_to_565_proc(const SkScaledBitmapSampler::Options& opts) {
+ // Unpremul and skip zeroes make no difference
+ if (opts.fDither) {
+ return Sample_RGBx_D565_D;
+ }
+ return Sample_RGBx_D565;
+}
+
+
+static bool Sample_D565_D565(void* SK_RESTRICT dstRow,
+ const uint8_t* SK_RESTRICT src,
+ int width, int deltaSrc, int, const SkPMColor[]) {
+ uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow;
+ uint16_t* SK_RESTRICT castedSrc = (uint16_t*) src;
+ for (int x = 0; x < width; x++) {
+ dst[x] = castedSrc[0];
+ castedSrc += deltaSrc >> 1;
+ }
+ return false;
+}
+
+static SkScaledBitmapSampler::RowProc
+get_565_to_565_proc(const SkScaledBitmapSampler::Options& opts) {
+ // Unpremul, dither, and skip zeroes have no effect
+ return Sample_D565_D565;
+}
+
+// 4444
+
+static bool Sample_Gray_D4444(void* SK_RESTRICT dstRow,
+ const uint8_t* SK_RESTRICT src,
+ int width, int deltaSrc, int, const SkPMColor[]) {
+ SkPMColor16* SK_RESTRICT dst = (SkPMColor16*)dstRow;
+ for (int x = 0; x < width; x++) {
+ unsigned gray = src[0] >> 4;
+ dst[x] = SkPackARGB4444(0xF, gray, gray, gray);
+ src += deltaSrc;
+ }
+ return false;
+}
+
+static bool Sample_Gray_D4444_D(void* SK_RESTRICT dstRow,
+ const uint8_t* SK_RESTRICT src,
+ int width, int deltaSrc, int y, const SkPMColor[]) {
+ SkPMColor16* SK_RESTRICT dst = (SkPMColor16*)dstRow;
+ DITHER_4444_SCAN(y);
+ for (int x = 0; x < width; x++) {
+ dst[x] = SkDitherARGB32To4444(0xFF, src[0], src[0], src[0],
+ DITHER_VALUE(x));
+ src += deltaSrc;
+ }
+ return false;
+}
+
+static SkScaledBitmapSampler::RowProc
+get_gray_to_4444_proc(const SkScaledBitmapSampler::Options& opts) {
+ // Skip zeroes and unpremul make no difference
+ if (opts.fDither) {
+ return Sample_Gray_D4444_D;
+ }
+ return Sample_Gray_D4444;
+}
+
+static bool Sample_RGBx_D4444(void* SK_RESTRICT dstRow,
+ const uint8_t* SK_RESTRICT src,
+ int width, int deltaSrc, int, const SkPMColor[]) {
+ SkPMColor16* SK_RESTRICT dst = (SkPMColor16*)dstRow;
+ for (int x = 0; x < width; x++) {
+ dst[x] = SkPackARGB4444(0xF, src[0] >> 4, src[1] >> 4, src[2] >> 4);
+ src += deltaSrc;
+ }
+ return false;
+}
+
+static bool Sample_RGBx_D4444_D(void* SK_RESTRICT dstRow,
+ const uint8_t* SK_RESTRICT src,
+ int width, int deltaSrc, int y, const SkPMColor[]) {
+ SkPMColor16* dst = (SkPMColor16*)dstRow;
+ DITHER_4444_SCAN(y);
+
+ for (int x = 0; x < width; x++) {
+ dst[x] = SkDitherARGB32To4444(0xFF, src[0], src[1], src[2],
+ DITHER_VALUE(x));
+ src += deltaSrc;
+ }
+ return false;
+}
+
+static SkScaledBitmapSampler::RowProc
+get_RGBx_to_4444_proc(const SkScaledBitmapSampler::Options& opts) {
+ // Skip zeroes and unpremul make no difference
+ if (opts.fDither) {
+ return Sample_RGBx_D4444_D;
+ }
+ return Sample_RGBx_D4444;
+}
+
+static bool Sample_RGBA_D4444(void* SK_RESTRICT dstRow,
+ const uint8_t* SK_RESTRICT src,
+ int width, int deltaSrc, int, const SkPMColor[]) {
+ SkPMColor16* SK_RESTRICT dst = (SkPMColor16*)dstRow;
+ unsigned alphaMask = 0xFF;
+
+ for (int x = 0; x < width; x++) {
+ unsigned alpha = src[3];
+ SkPMColor c = SkPreMultiplyARGB(alpha, src[0], src[1], src[2]);
+ dst[x] = SkPixel32ToPixel4444(c);
+ src += deltaSrc;
+ alphaMask &= alpha;
+ }
+ return alphaMask != 0xFF;
+}
+
+static bool Sample_RGBA_D4444_SkipZ(void* SK_RESTRICT dstRow,
+ const uint8_t* SK_RESTRICT src,
+ int width, int deltaSrc, int,
+ const SkPMColor[]) {
+ SkPMColor16* SK_RESTRICT dst = (SkPMColor16*)dstRow;
+ unsigned alphaMask = 0xFF;
+
+ for (int x = 0; x < width; x++) {
+ unsigned alpha = src[3];
+ if (alpha != 0) {
+ SkPMColor c = SkPreMultiplyARGB(alpha, src[0], src[1], src[2]);
+ dst[x] = SkPixel32ToPixel4444(c);
+ }
+ src += deltaSrc;
+ alphaMask &= alpha;
+ }
+ return alphaMask != 0xFF;
+}
+
+
+static bool Sample_RGBA_D4444_D(void* SK_RESTRICT dstRow,
+ const uint8_t* SK_RESTRICT src,
+ int width, int deltaSrc, int y,
+ const SkPMColor[]) {
+ SkPMColor16* SK_RESTRICT dst = (SkPMColor16*)dstRow;
+ unsigned alphaMask = 0xFF;
+ DITHER_4444_SCAN(y);
+
+ for (int x = 0; x < width; x++) {
+ unsigned alpha = src[3];
+ SkPMColor c = SkPreMultiplyARGB(alpha, src[0], src[1], src[2]);
+ dst[x] = SkDitherARGB32To4444(c, DITHER_VALUE(x));
+ src += deltaSrc;
+ alphaMask &= alpha;
+ }
+ return alphaMask != 0xFF;
+}
+
+static bool Sample_RGBA_D4444_D_SkipZ(void* SK_RESTRICT dstRow,
+ const uint8_t* SK_RESTRICT src,
+ int width, int deltaSrc, int y,
+ const SkPMColor[]) {
+ SkPMColor16* SK_RESTRICT dst = (SkPMColor16*)dstRow;
+ unsigned alphaMask = 0xFF;
+ DITHER_4444_SCAN(y);
+
+ for (int x = 0; x < width; x++) {
+ unsigned alpha = src[3];
+ if (alpha != 0) {
+ SkPMColor c = SkPreMultiplyARGB(alpha, src[0], src[1], src[2]);
+ dst[x] = SkDitherARGB32To4444(c, DITHER_VALUE(x));
+ }
+ src += deltaSrc;
+ alphaMask &= alpha;
+ }
+ return alphaMask != 0xFF;
+}
+
+static SkScaledBitmapSampler::RowProc
+get_RGBA_to_4444_proc(const SkScaledBitmapSampler::Options& opts) {
+ if (!opts.fPremultiplyAlpha) {
+ // Unpremultiplied is not supported for 4444
+ return nullptr;
+ }
+ if (opts.fSkipZeros) {
+ if (opts.fDither) {
+ return Sample_RGBA_D4444_D_SkipZ;
+ }
+ return Sample_RGBA_D4444_SkipZ;
+ }
+ if (opts.fDither) {
+ return Sample_RGBA_D4444_D;
+ }
+ return Sample_RGBA_D4444;
+}
+
+// Index
+
+#define A32_MASK_IN_PLACE (SkPMColor)(SK_A32_MASK << SK_A32_SHIFT)
+
+static bool Sample_Index_D8888(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 Sample_Index_D8888_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;
+}
+
+static SkScaledBitmapSampler::RowProc
+get_index_to_8888_proc(const SkScaledBitmapSampler::Options& opts) {
+ // The caller is expected to have created the source colortable
+ // properly with respect to opts.fPremultiplyAlpha, so premul makes
+ // no difference here.
+ // Dither makes no difference
+ if (opts.fSkipZeros) {
+ return Sample_Index_D8888_SkipZ;
+ }
+ return Sample_Index_D8888;
+}
+
+static bool Sample_Index_D565(void* SK_RESTRICT dstRow,
+ const uint8_t* SK_RESTRICT src,
+ int width, int deltaSrc, int, const SkPMColor ctable[]) {
+
+ uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow;
+ for (int x = 0; x < width; x++) {
+ dst[x] = SkPixel32ToPixel16(ctable[*src]);
+ src += deltaSrc;
+ }
+ return false;
+}
+
+static bool Sample_Index_D565_D(void* SK_RESTRICT dstRow,
+ const uint8_t* SK_RESTRICT src, int width,
+ int deltaSrc, int y, const SkPMColor ctable[]) {
+
+ uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow;
+ DITHER_565_SCAN(y);
+
+ for (int x = 0; x < width; x++) {
+ SkPMColor c = ctable[*src];
+ dst[x] = SkDitherRGBTo565(SkGetPackedR32(c), SkGetPackedG32(c),
+ SkGetPackedB32(c), DITHER_VALUE(x));
+ src += deltaSrc;
+ }
+ return false;
+}
+
+static SkScaledBitmapSampler::RowProc
+get_index_to_565_proc(const SkScaledBitmapSampler::Options& opts) {
+ // Unpremultiplied and skip zeroes make no difference
+ if (opts.fDither) {
+ return Sample_Index_D565_D;
+ }
+ return Sample_Index_D565;
+}
+
+static bool Sample_Index_D4444(void* SK_RESTRICT dstRow,
+ const uint8_t* SK_RESTRICT src, int width,
+ int deltaSrc, int y, const SkPMColor ctable[]) {
+
+ SkPMColor16* SK_RESTRICT dst = (SkPMColor16*)dstRow;
+ SkPMColor cc = A32_MASK_IN_PLACE;
+ for (int x = 0; x < width; x++) {
+ SkPMColor c = ctable[*src];
+ cc &= c;
+ dst[x] = SkPixel32ToPixel4444(c);
+ src += deltaSrc;
+ }
+ return cc != A32_MASK_IN_PLACE;
+}
+
+static bool Sample_Index_D4444_D(void* SK_RESTRICT dstRow,
+ const uint8_t* SK_RESTRICT src, int width,
+ int deltaSrc, int y, const SkPMColor ctable[]) {
+
+ SkPMColor16* SK_RESTRICT dst = (SkPMColor16*)dstRow;
+ SkPMColor cc = A32_MASK_IN_PLACE;
+ DITHER_4444_SCAN(y);
+
+ for (int x = 0; x < width; x++) {
+ SkPMColor c = ctable[*src];
+ cc &= c;
+ dst[x] = SkDitherARGB32To4444(c, DITHER_VALUE(x));
+ src += deltaSrc;
+ }
+ return cc != A32_MASK_IN_PLACE;
+}
+
+static bool Sample_Index_D4444_SkipZ(void* SK_RESTRICT dstRow,
+ const uint8_t* SK_RESTRICT src, int width,
+ int deltaSrc, int y, const SkPMColor ctable[]) {
+
+ SkPMColor16* SK_RESTRICT dst = (SkPMColor16*)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] = SkPixel32ToPixel4444(c);
+ }
+ src += deltaSrc;
+ }
+ return cc != A32_MASK_IN_PLACE;
+}
+
+static bool Sample_Index_D4444_D_SkipZ(void* SK_RESTRICT dstRow,
+ const uint8_t* SK_RESTRICT src, int width,
+ int deltaSrc, int y, const SkPMColor ctable[]) {
+
+ SkPMColor16* SK_RESTRICT dst = (SkPMColor16*)dstRow;
+ SkPMColor cc = A32_MASK_IN_PLACE;
+ DITHER_4444_SCAN(y);
+
+ for (int x = 0; x < width; x++) {
+ SkPMColor c = ctable[*src];
+ cc &= c;
+ if (c != 0) {
+ dst[x] = SkDitherARGB32To4444(c, DITHER_VALUE(x));
+ }
+ src += deltaSrc;
+ }
+ return cc != A32_MASK_IN_PLACE;
+}
+
+static SkScaledBitmapSampler::RowProc
+get_index_to_4444_proc(const SkScaledBitmapSampler::Options& opts) {
+ // Unpremul not allowed
+ if (!opts.fPremultiplyAlpha) {
+ return nullptr;
+ }
+ if (opts.fSkipZeros) {
+ if (opts.fDither) {
+ return Sample_Index_D4444_D_SkipZ;
+ }
+ return Sample_Index_D4444_SkipZ;
+ }
+ if (opts.fDither) {
+ return Sample_Index_D4444_D;
+ }
+ return Sample_Index_D4444;
+}
+
+static bool Sample_Index_DI(void* SK_RESTRICT dstRow,
+ const uint8_t* SK_RESTRICT src,
+ int width, int deltaSrc, int, const SkPMColor[]) {
+ if (1 == deltaSrc) {
+ memcpy(dstRow, src, width);
+ } else {
+ uint8_t* SK_RESTRICT dst = (uint8_t*)dstRow;
+ for (int x = 0; x < width; x++) {
+ dst[x] = src[0];
+ src += deltaSrc;
+ }
+ }
+ return false;
+}
+
+static SkScaledBitmapSampler::RowProc
+get_index_to_index_proc(const SkScaledBitmapSampler::Options& opts) {
+ // Unpremul not allowed
+ if (!opts.fPremultiplyAlpha) {
+ return nullptr;
+ }
+ // Ignore dither and skip zeroes
+ return Sample_Index_DI;
+}
+
+// A8
+static bool Sample_Gray_DA8(void* SK_RESTRICT dstRow,
+ const uint8_t* SK_RESTRICT src,
+ int width, int deltaSrc, int,
+ const SkPMColor[]) {
+ // Sampling Gray to A8 uses the same function as Index to Index8,
+ // except we assume that there is alpha for speed, since an A8
+ // bitmap with no alpha is not interesting.
+ (void) Sample_Index_DI(dstRow, src, width, deltaSrc, /* y unused */ 0,
+ /* ctable unused */ nullptr);
+ return true;
+}
+
+static SkScaledBitmapSampler::RowProc
+get_gray_to_A8_proc(const SkScaledBitmapSampler::Options& opts) {
+ if (!opts.fPremultiplyAlpha) {
+ return nullptr;
+ }
+ // Ignore skip and dither.
+ return Sample_Gray_DA8;
+}
+
+typedef SkScaledBitmapSampler::RowProc (*RowProcChooser)(const SkScaledBitmapSampler::Options&);
+///////////////////////////////////////////////////////////////////////////////
+
+#include "SkScaledBitmapSampler.h"
+
+SkScaledBitmapSampler::SkScaledBitmapSampler(int width, int height,
+ int sampleSize) {
+ fCTable = nullptr;
+ fDstRow = nullptr;
+ fRowProc = nullptr;
+
+ if (width <= 0 || height <= 0) {
+ sk_throw();
+ }
+
+ SkDEBUGCODE(fSampleMode = kUninitialized_SampleMode);
+
+ if (sampleSize <= 1) {
+ fScaledWidth = width;
+ fScaledHeight = height;
+ fX0 = fY0 = 0;
+ fDX = fDY = 1;
+ return;
+ }
+
+ int dx = SkMin32(sampleSize, width);
+ int dy = SkMin32(sampleSize, height);
+
+ fScaledWidth = width / dx;
+ fScaledHeight = height / dy;
+
+ SkASSERT(fScaledWidth > 0);
+ SkASSERT(fScaledHeight > 0);
+
+ fX0 = dx >> 1;
+ fY0 = dy >> 1;
+
+ SkASSERT(fX0 >= 0 && fX0 < width);
+ SkASSERT(fY0 >= 0 && fY0 < height);
+
+ fDX = dx;
+ fDY = dy;
+
+ SkASSERT(fDX > 0 && (fX0 + fDX * (fScaledWidth - 1)) < width);
+ SkASSERT(fDY > 0 && (fY0 + fDY * (fScaledHeight - 1)) < height);
+}
+
+bool SkScaledBitmapSampler::begin(SkBitmap* dst, SrcConfig sc,
+ const Options& opts,
+ const SkPMColor ctable[]) {
+ static const RowProcChooser gProcChoosers[] = {
+ get_gray_to_8888_proc,
+ get_RGBx_to_8888_proc,
+ get_RGBA_to_8888_proc,
+ get_index_to_8888_proc,
+ nullptr, // 565 to 8888
+
+ get_gray_to_565_proc,
+ get_RGBx_to_565_proc,
+ get_RGBx_to_565_proc, // The source alpha will be ignored.
+ get_index_to_565_proc,
+ get_565_to_565_proc,
+
+ get_gray_to_4444_proc,
+ get_RGBx_to_4444_proc,
+ get_RGBA_to_4444_proc,
+ get_index_to_4444_proc,
+ nullptr, // 565 to 4444
+
+ nullptr, // gray to index
+ nullptr, // rgbx to index
+ nullptr, // rgba to index
+ get_index_to_index_proc,
+ nullptr, // 565 to index
+
+ get_gray_to_A8_proc,
+ nullptr, // rgbx to a8
+ nullptr, // rgba to a8
+ nullptr, // index to a8
+ nullptr, // 565 to a8
+ };
+
+ // The jump between dst configs in the table
+ static const int gProcDstConfigSpan = 5;
+ static_assert(SK_ARRAY_COUNT(gProcChoosers) == 5 * gProcDstConfigSpan,
+ "gProcs_has_the_wrong_number_of_entries");
+
+ fCTable = ctable;
+
+ int index = 0;
+ switch (sc) {
+ case SkScaledBitmapSampler::kGray:
+ fSrcPixelSize = 1;
+ index += 0;
+ break;
+ case SkScaledBitmapSampler::kRGB:
+ fSrcPixelSize = 3;
+ index += 1;
+ break;
+ case SkScaledBitmapSampler::kRGBX:
+ fSrcPixelSize = 4;
+ index += 1;
+ break;
+ case SkScaledBitmapSampler::kRGBA:
+ fSrcPixelSize = 4;
+ index += 2;
+ break;
+ case SkScaledBitmapSampler::kIndex:
+ fSrcPixelSize = 1;
+ index += 3;
+ break;
+ case SkScaledBitmapSampler::kRGB_565:
+ fSrcPixelSize = 2;
+ index += 4;
+ break;
+ default:
+ return false;
+ }
+
+ switch (dst->colorType()) {
+ case kN32_SkColorType:
+ index += 0 * gProcDstConfigSpan;
+ break;
+ case kRGB_565_SkColorType:
+ index += 1 * gProcDstConfigSpan;
+ break;
+ case kARGB_4444_SkColorType:
+ index += 2 * gProcDstConfigSpan;
+ break;
+ case kIndex_8_SkColorType:
+ index += 3 * gProcDstConfigSpan;
+ break;
+ case kAlpha_8_SkColorType:
+ index += 4 * gProcDstConfigSpan;
+ break;
+ default:
+ return false;
+ }
+
+ RowProcChooser chooser = gProcChoosers[index];
+ if (nullptr == chooser) {
+ fRowProc = nullptr;
+ } else {
+ fRowProc = chooser(opts);
+ }
+ fDstRow = (char*)dst->getPixels();
+ fDstRowBytes = dst->rowBytes();
+ fCurrY = 0;
+ return fRowProc != nullptr;
+}
+
+bool SkScaledBitmapSampler::begin(SkBitmap* dst, SrcConfig sc,
+ const SkImageDecoder& decoder,
+ const SkPMColor ctable[]) {
+ return this->begin(dst, sc, Options(decoder), ctable);
+}
+
+bool SkScaledBitmapSampler::next(const uint8_t* SK_RESTRICT src) {
+ SkASSERT(kInterlaced_SampleMode != fSampleMode);
+ SkDEBUGCODE(fSampleMode = kConsecutive_SampleMode);
+ SkASSERT((unsigned)fCurrY < (unsigned)fScaledHeight);
+
+ bool hadAlpha = fRowProc(fDstRow, src + fX0 * fSrcPixelSize, fScaledWidth,
+ fDX * fSrcPixelSize, fCurrY, fCTable);
+ fDstRow += fDstRowBytes;
+ fCurrY += 1;
+ return hadAlpha;
+}
+
+bool SkScaledBitmapSampler::sampleInterlaced(const uint8_t* SK_RESTRICT src, int srcY) {
+ SkASSERT(kConsecutive_SampleMode != fSampleMode);
+ SkDEBUGCODE(fSampleMode = kInterlaced_SampleMode);
+ // Any line that should be a part of the destination can be created by the formula:
+ // fY0 + (some multiplier) * fDY
+ // so if srcY - fY0 is not an integer multiple of fDY that srcY will be skipped.
+ const int srcYMinusY0 = srcY - fY0;
+ if (srcYMinusY0 % fDY != 0) {
+ // This line is not part of the output, so return false for alpha, since we have
+ // not added an alpha to the output.
+ return false;
+ }
+ // Unlike in next(), where the data is used sequentially, this function skips around,
+ // so fDstRow and fCurrY are never updated. fDstRow must always be the starting point
+ // of the destination bitmap's pixels, which is used to calculate the destination row
+ // each time this function is called.
+ const int dstY = srcYMinusY0 / fDY;
+ if (dstY >= fScaledHeight) {
+ return false;
+ }
+ char* dstRow = fDstRow + dstY * fDstRowBytes;
+ return fRowProc(dstRow, src + fX0 * fSrcPixelSize, fScaledWidth,
+ fDX * fSrcPixelSize, dstY, fCTable);
+}
+
+#ifdef SK_DEBUG
+// The following code is for a test to ensure that changing the method to get the right row proc
+// did not change the row proc unintentionally. Tested by ImageDecodingTest.cpp
+
+// friend of SkScaledBitmapSampler solely for the purpose of accessing fRowProc.
+class RowProcTester {
+public:
+ static SkScaledBitmapSampler::RowProc getRowProc(const SkScaledBitmapSampler& sampler) {
+ return sampler.fRowProc;
+ }
+};
+
+
+// Table showing the expected RowProc for each combination of inputs.
+// Table formated as follows:
+// Each group of 5 consecutive rows represents sampling from a single
+// SkScaledBitmapSampler::SrcConfig.
+// Within each set, each row represents a different destination SkBitmap::Config
+// Each column represents a different combination of dither and unpremul.
+// D = dither ~D = no dither
+// U = unpremul ~U = no unpremul
+// ~D~U D~U ~DU DU
+SkScaledBitmapSampler::RowProc gTestProcs[] = {
+ // Gray
+ Sample_Gray_DA8, Sample_Gray_DA8, nullptr, nullptr, // to A8
+ nullptr, nullptr, nullptr, nullptr, // to Index8
+ Sample_Gray_D565, Sample_Gray_D565_D, Sample_Gray_D565, Sample_Gray_D565_D, // to 565
+ Sample_Gray_D4444, Sample_Gray_D4444_D, Sample_Gray_D4444, Sample_Gray_D4444_D, // to 4444
+ Sample_Gray_D8888, Sample_Gray_D8888, Sample_Gray_D8888, Sample_Gray_D8888, // to 8888
+ // Index
+ nullptr, nullptr, nullptr, nullptr, // to A8
+ Sample_Index_DI, Sample_Index_DI, nullptr, nullptr, // to Index8
+ Sample_Index_D565, Sample_Index_D565_D, Sample_Index_D565, Sample_Index_D565_D, // to 565
+ Sample_Index_D4444, Sample_Index_D4444_D, nullptr, nullptr, // to 4444
+ Sample_Index_D8888, Sample_Index_D8888, Sample_Index_D8888, Sample_Index_D8888, // to 8888
+ // RGB
+ nullptr, nullptr, nullptr, nullptr, // to A8
+ nullptr, nullptr, nullptr, nullptr, // to Index8
+ Sample_RGBx_D565, Sample_RGBx_D565_D, Sample_RGBx_D565, Sample_RGBx_D565_D, // to 565
+ Sample_RGBx_D4444, Sample_RGBx_D4444_D, Sample_RGBx_D4444, Sample_RGBx_D4444_D, // to 4444
+ Sample_RGBx_D8888, Sample_RGBx_D8888, Sample_RGBx_D8888, Sample_RGBx_D8888, // to 8888
+ // RGBx is the same as RGB
+ nullptr, nullptr, nullptr, nullptr, // to A8
+ nullptr, nullptr, nullptr, nullptr, // to Index8
+ Sample_RGBx_D565, Sample_RGBx_D565_D, Sample_RGBx_D565, Sample_RGBx_D565_D, // to 565
+ Sample_RGBx_D4444, Sample_RGBx_D4444_D, Sample_RGBx_D4444, Sample_RGBx_D4444_D, // to 4444
+ Sample_RGBx_D8888, Sample_RGBx_D8888, Sample_RGBx_D8888, Sample_RGBx_D8888, // to 8888
+ // RGBA
+ nullptr, nullptr, nullptr, nullptr, // to A8
+ nullptr, nullptr, nullptr, nullptr, // to Index8
+ Sample_RGBx_D565, Sample_RGBx_D565_D, Sample_RGBx_D565, Sample_RGBx_D565_D, // to 565
+ Sample_RGBA_D4444, Sample_RGBA_D4444_D, nullptr, nullptr, // to 4444
+ Sample_RGBA_D8888, Sample_RGBA_D8888, Sample_RGBA_D8888_Unpremul, Sample_RGBA_D8888_Unpremul, // to 8888
+ // RGB_565
+ nullptr, nullptr, nullptr, nullptr, // to A8
+ nullptr, nullptr, nullptr, nullptr, // to Index8
+ Sample_D565_D565, Sample_D565_D565, Sample_D565_D565, Sample_D565_D565, // to 565
+ nullptr, nullptr, nullptr, nullptr, // to 4444
+ nullptr, nullptr, nullptr, nullptr, // to 8888
+};
+
+// Dummy class that allows instantiation of an ImageDecoder, so begin can query its fields.
+class DummyDecoder : public SkImageDecoder {
+public:
+ DummyDecoder() {}
+protected:
+ Result onDecode(SkStream*, SkBitmap*, SkImageDecoder::Mode) override {
+ return kFailure;
+ }
+};
+
+void test_row_proc_choice();
+void test_row_proc_choice() {
+ const SkColorType colorTypes[] = {
+ kAlpha_8_SkColorType, kIndex_8_SkColorType, kRGB_565_SkColorType, kARGB_4444_SkColorType,
+ kN32_SkColorType
+ };
+
+ SkBitmap dummyBitmap;
+ DummyDecoder dummyDecoder;
+ size_t procCounter = 0;
+ for (int sc = SkScaledBitmapSampler::kGray; sc <= SkScaledBitmapSampler::kRGB_565; ++sc) {
+ for (size_t c = 0; c < SK_ARRAY_COUNT(colorTypes); ++c) {
+ for (int unpremul = 0; unpremul <= 1; ++unpremul) {
+ for (int dither = 0; dither <= 1; ++dither) {
+ // Arbitrary width/height/sampleSize to allow SkScaledBitmapSampler to
+ // be considered valid.
+ SkScaledBitmapSampler sampler(10, 10, 1);
+ dummyBitmap.setInfo(SkImageInfo::Make(10, 10,
+ colorTypes[c], kPremul_SkAlphaType));
+ dummyDecoder.setDitherImage(SkToBool(dither));
+ dummyDecoder.setRequireUnpremultipliedColors(SkToBool(unpremul));
+ sampler.begin(&dummyBitmap, (SkScaledBitmapSampler::SrcConfig) sc,
+ dummyDecoder);
+ SkScaledBitmapSampler::RowProc expected = gTestProcs[procCounter];
+ SkScaledBitmapSampler::RowProc actual = RowProcTester::getRowProc(sampler);
+ SkASSERT(expected == actual);
+ procCounter++;
+ }
+ }
+ }
+ }
+ SkASSERT(SK_ARRAY_COUNT(gTestProcs) == procCounter);
+}
+#endif // SK_DEBUG
« no previous file with comments | « src/images/SkScaledBitmapSampler.h ('k') | src/images/bmpdecoderhelper.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698