Fix mapping from src to dst image space in SkAlphaThresholdFilter

This CL does 3 things:
   It updates the imagealphathreshold GMs so they would've caught this bug
   It updates SkAlphaImageThresholdFilter to fix the bug
   It updates the imagealphathreshold_surface GM to match the imagealphathreshold_crop GM (which it was, presumably, originally written to do)

The bug in question is that the prior mapping from src to dst space was correct as long as the imageOffset was (0, 0).

BUG=675332

Change-Id: I3aa1f463a2234576fb2277797caa2fc4aba2650d
Reviewed-on: https://skia-review.googlesource.com/6291
Reviewed-by: Brian Osman <brianosman@google.com>
Reviewed-by: Stephan White <senorblanco@chromium.org>
Commit-Queue: Robert Phillips <robertphillips@google.com>
This commit is contained in:
Robert Phillips 2016-12-19 16:51:53 -05:00 committed by Skia Commit-Bot
parent 86cedfc315
commit 22c57abe43
2 changed files with 47 additions and 25 deletions

View File

@ -7,27 +7,25 @@
#include "gm.h"
#include "SkAlphaThresholdFilter.h"
#include "SkRandom.h"
#include "SkOffsetImageFilter.h"
#include "SkSurface.h"
#define WIDTH 500
#define HEIGHT 500
namespace {
void draw_rects(SkCanvas* canvas) {
static void draw_rects(SkCanvas* canvas) {
SkPaint rectPaint;
rectPaint.setColor(0xFF0000FF);
rectPaint.setColor(SK_ColorBLUE);
canvas->drawRect(SkRect::MakeXYWH(0, 0, WIDTH / 2, HEIGHT / 2), rectPaint);
rectPaint.setColor(0xBFFF0000);
canvas->drawRect(SkRect::MakeXYWH(WIDTH / 2, 0, WIDTH / 2, HEIGHT / 2), rectPaint);
rectPaint.setColor(0x3F00FF00);
canvas->drawRect(SkRect::MakeXYWH(0, HEIGHT / 2, WIDTH / 2, HEIGHT / 2), rectPaint);
rectPaint.setColor(0x00000000);
rectPaint.setColor(SK_ColorTRANSPARENT);
canvas->drawRect(SkRect::MakeXYWH(WIDTH / 2, HEIGHT / 2, WIDTH / 2, HEIGHT / 2), rectPaint);
}
SkPaint create_filter_paint(SkImageFilter::CropRect* cropRect = nullptr) {
static SkPaint create_filter_paint(SkImageFilter::CropRect* cropRect = nullptr) {
SkIRect rects[2];
rects[0] = SkIRect::MakeXYWH(0, 150, WIDTH, HEIGHT - 300);
rects[1] = SkIRect::MakeXYWH(150, 0, WIDTH - 300, HEIGHT);
@ -35,18 +33,15 @@ SkPaint create_filter_paint(SkImageFilter::CropRect* cropRect = nullptr) {
region.setRects(rects, 2);
SkPaint paint;
paint.setImageFilter(SkAlphaThresholdFilter::Make(region, 0.2f, 0.7f, nullptr, cropRect));
sk_sp<SkImageFilter> offset(SkOffsetImageFilter::Make(25, 25, nullptr));
paint.setImageFilter(SkAlphaThresholdFilter::Make(region, 0.2f, 0.7f, std::move(offset), cropRect));
return paint;
}
};
namespace skiagm {
class ImageAlphaThresholdGM : public GM {
class ImageAlphaThresholdGM : public skiagm::GM {
public:
ImageAlphaThresholdGM(bool useCropRect) : fUseCropRect(useCropRect) {
this->setBGColor(0xFFFFFFFF);
this->setBGColor(SK_ColorWHITE);
}
protected:
@ -87,8 +82,31 @@ private:
typedef GM INHERITED;
};
// Create a 'width' x 'height' SkSurface that matches the colorType of 'canvas' as
// best we can
static sk_sp<SkSurface> make_color_matching_surface(SkCanvas* canvas, int width, int height,
SkAlphaType alphaType) {
class ImageAlphaThresholdSurfaceGM : public GM {
SkColorType ct = canvas->imageInfo().colorType();
sk_sp<SkColorSpace> cs(sk_ref_sp(canvas->imageInfo().colorSpace()));
if (kUnknown_SkColorType == ct) {
// For backends that aren't yet color-space aware we just fallback to N32.
ct = kN32_SkColorType;
cs = nullptr;
}
SkImageInfo info = SkImageInfo::Make(width, height, ct, alphaType, std::move(cs));
sk_sp<SkSurface> result = canvas->makeSurface(info);
if (!result) {
result = SkSurface::MakeRaster(info);
}
return result;
}
class ImageAlphaThresholdSurfaceGM : public skiagm::GM {
public:
ImageAlphaThresholdSurfaceGM() {
this->setBGColor(0xFFFFFFFF);
@ -104,12 +122,17 @@ protected:
}
void onDraw(SkCanvas* canvas) override {
SkImageInfo info = SkImageInfo::MakeS32(WIDTH, HEIGHT, kOpaque_SkAlphaType);
auto surface(canvas->makeSurface(info));
if (nullptr == surface) {
surface = SkSurface::MakeRaster(info);
}
surface->getCanvas()->clear(SK_ColorWHITE);
SkMatrix matrix;
matrix.reset();
matrix.setTranslate(WIDTH * .1f, HEIGHT * .1f);
matrix.postScale(.8f, .8f);
canvas->concat(matrix);
sk_sp<SkSurface> surface(make_color_matching_surface(canvas, WIDTH, HEIGHT,
kPremul_SkAlphaType));
surface->getCanvas()->clear(SK_ColorTRANSPARENT);
draw_rects(surface->getCanvas());
SkPaint paint = create_filter_paint();
@ -118,7 +141,7 @@ protected:
}
private:
typedef GM INHERITED;
typedef skiagm::GM INHERITED;
};
//////////////////////////////////////////////////////////////////////////////
@ -126,5 +149,3 @@ private:
DEF_GM(return new ImageAlphaThresholdGM(true);)
DEF_GM(return new ImageAlphaThresholdGM(false);)
DEF_GM(return new ImageAlphaThresholdSurfaceGM();)
}

View File

@ -225,8 +225,9 @@ sk_sp<SkSpecialImage> SkAlphaThresholdFilterImpl::onFilterImage(SkSpecialImage*
U8CPU outerThreshold = (U8CPU)(fOuterThreshold * 0xFF);
SkColor* dptr = dst.getAddr32(0, 0);
int dstWidth = dst.width(), dstHeight = dst.height();
SkIPoint srcOffset = { bounds.fLeft - inputOffset.fX, bounds.fTop - inputOffset.fY };
for (int y = 0; y < dstHeight; ++y) {
const SkColor* sptr = inputBM.getAddr32(bounds.fLeft, bounds.fTop+y);
const SkColor* sptr = inputBM.getAddr32(srcOffset.fX, srcOffset.fY+y);
for (int x = 0; x < dstWidth; ++x) {
const SkColor& source = sptr[x];