diff options
author | 2017-11-16 10:01:16 -0500 | |
---|---|---|
committer | 2017-11-16 17:34:54 +0000 | |
commit | ba61af9bc1e5f12df10fe1a2bed7b7b1d39801b4 (patch) | |
tree | 9eab2876e683df2093cd0b57f674be041e401d97 | |
parent | 5f1c8ff5249729f140bd4be2400b5a0b54478462 (diff) |
test scalePixels and unpremul
Bug: skia:5733
Change-Id: I6c661408198f6a536e1e55ba01d976948446b8eb
Reviewed-on: https://skia-review.googlesource.com/70280
Commit-Queue: Mike Reed <reed@google.com>
Reviewed-by: Brian Osman <brianosman@google.com>
Reviewed-by: Mike Klein <mtklein@chromium.org>
-rw-r--r-- | gm/image.cpp | 36 | ||||
-rw-r--r-- | src/core/SkPixmap.cpp | 29 |
2 files changed, 63 insertions, 2 deletions
diff --git a/gm/image.cpp b/gm/image.cpp index 6bf9f01154..576d7e8f98 100644 --- a/gm/image.cpp +++ b/gm/image.cpp @@ -381,3 +381,39 @@ DEF_SIMPLE_GM(new_texture_image, canvas, 280, 60) { canvas->translate(kSize + kPad, 0); } } + +static void draw_pixmap(SkCanvas* canvas, const SkPixmap& pm, SkScalar x, SkScalar y) { + canvas->drawImage(SkImage::MakeRasterCopy(pm), x, y, nullptr); +} + +static void slam_ff(const SkPixmap& pm) { + for (int y = 0; y < pm.height(); ++y) { + for (int x = 0; x < pm.width(); ++x) { + *pm.writable_addr32(x, y) = *pm.addr32(x, y) | SkPackARGB32(0xFF, 0, 0, 0); + } + } +} + +DEF_SIMPLE_GM(scalepixels_unpremul, canvas, 1080, 280) { + SkImageInfo info = SkImageInfo::MakeN32(16, 16, kUnpremul_SkAlphaType); + SkAutoPixmapStorage pm; + pm.alloc(info); + for (int y = 0; y < 16; ++y) { + for (int x = 0; x < 16; ++x) { + *pm.writable_addr32(x, y) = SkPackARGB32NoCheck(0, (y << 4) | y, (x << 4) | x, 0xFF); + } + } + SkAutoPixmapStorage pm2; + pm2.alloc(SkImageInfo::MakeN32(256, 256, kUnpremul_SkAlphaType)); + + const SkFilterQuality qualities[] = { + kNone_SkFilterQuality, kLow_SkFilterQuality, kMedium_SkFilterQuality, kHigh_SkFilterQuality + }; + + for (auto fq : qualities) { + pm.scalePixels(pm2, fq); + slam_ff(pm2); + draw_pixmap(canvas, pm2, 10, 10); + canvas->translate(pm2.width() + 10.0f, 0); + } +} diff --git a/src/core/SkPixmap.cpp b/src/core/SkPixmap.cpp index bd6436e72a..5648405445 100644 --- a/src/core/SkPixmap.cpp +++ b/src/core/SkPixmap.cpp @@ -228,6 +228,10 @@ bool SkPixmap::erase(const SkColor4f& origColor, const SkIRect* subset) const { return true; } +static void set_alphatype(SkPixmap* dst, const SkPixmap& src, SkAlphaType at) { + dst->reset(src.info().makeAlphaType(at), src.addr(), src.rowBytes()); +} + bool SkPixmap::scalePixels(const SkPixmap& dst, SkFilterQuality quality) const { // Can't do anthing with empty src or dst if (this->width() <= 0 || this->height() <= 0 || dst.width() <= 0 || dst.height() <= 0) { @@ -239,13 +243,34 @@ bool SkPixmap::scalePixels(const SkPixmap& dst, SkFilterQuality quality) const { return this->readPixels(dst); } + // Temp storage in case we need to edit the requested alphatypes + SkPixmap storage_src, storage_dst; + const SkPixmap* srcPtr = this; + const SkPixmap* dstPtr = &dst; + + // Trick: if src and dst are both unpremul, we can give the correct result if we change both + // to premul (or opaque), since the draw will not try to blend or otherwise interpret + // the pixels' alpha. + // + // Today this works except in kHigh_SkFilterQuality, where we incorrectly clamp assuming the + // colors are premul. TODO: fix the HQ mode. + // + if (srcPtr->alphaType() == kUnpremul_SkAlphaType && + dstPtr->alphaType() == kUnpremul_SkAlphaType) + { + set_alphatype(&storage_src, *this, kPremul_SkAlphaType); + set_alphatype(&storage_dst, dst, kPremul_SkAlphaType); + srcPtr = &storage_src; + dstPtr = &storage_dst; + } + SkBitmap bitmap; - if (!bitmap.installPixels(*this)) { + if (!bitmap.installPixels(*srcPtr)) { return false; } bitmap.setIsVolatile(true); // so we don't try to cache it - auto surface(SkSurface::MakeRasterDirect(dst.info(), dst.writable_addr(), dst.rowBytes())); + auto surface(SkSurface::MakeRasterDirect(dstPtr->info(), dstPtr->writable_addr(), dstPtr->rowBytes())); if (!surface) { return false; } |