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

Unified Diff: src/effects/SkMorphologyImageFilter.cpp

Issue 23892011: Implement crop rect for the dilate and erode (morphology) filters. This provoked some cleanup on th… (Closed) Base URL: https://skia.googlecode.com/svn/trunk
Patch Set: Embiggen GM to accommodate new test cases. Created 7 years, 3 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 | « include/effects/SkMorphologyImageFilter.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/effects/SkMorphologyImageFilter.cpp
diff --git a/src/effects/SkMorphologyImageFilter.cpp b/src/effects/SkMorphologyImageFilter.cpp
index 5d5f29058b705a704053d3c1873a81286e1f2cf9..ee998df673f24878b0c95da7845da056e01e7232 100644
--- a/src/effects/SkMorphologyImageFilter.cpp
+++ b/src/effects/SkMorphologyImageFilter.cpp
@@ -30,8 +30,8 @@ SkMorphologyImageFilter::SkMorphologyImageFilter(SkFlattenableReadBuffer& buffer
(fRadius.fHeight >= 0));
}
-SkMorphologyImageFilter::SkMorphologyImageFilter(int radiusX, int radiusY, SkImageFilter* input)
- : INHERITED(input), fRadius(SkISize::Make(radiusX, radiusY)) {
+SkMorphologyImageFilter::SkMorphologyImageFilter(int radiusX, int radiusY, SkImageFilter* input, const SkIRect* cropRect)
+ : INHERITED(input, cropRect), fRadius(SkISize::Make(radiusX, radiusY)) {
}
@@ -75,17 +75,17 @@ static void erode(const SkPMColor* src, SkPMColor* dst,
}
}
-static void erodeX(const SkBitmap& src, SkBitmap* dst, int radiusX)
+static void erodeX(const SkBitmap& src, SkBitmap* dst, int radiusX, const SkIRect& bounds)
{
- erode(src.getAddr32(0, 0), dst->getAddr32(0, 0),
- radiusX, src.width(), src.height(),
+ erode(src.getAddr32(bounds.left(), bounds.top()), dst->getAddr32(0, 0),
+ radiusX, bounds.width(), bounds.height(),
1, src.rowBytesAsPixels(), 1, dst->rowBytesAsPixels());
}
-static void erodeY(const SkBitmap& src, SkBitmap* dst, int radiusY)
+static void erodeY(const SkBitmap& src, SkBitmap* dst, int radiusY, const SkIRect& bounds)
{
- erode(src.getAddr32(0, 0), dst->getAddr32(0, 0),
- radiusY, src.height(), src.width(),
+ erode(src.getAddr32(bounds.left(), bounds.top()), dst->getAddr32(0, 0),
+ radiusY, bounds.height(), bounds.width(),
src.rowBytesAsPixels(), 1, dst->rowBytesAsPixels(), 1);
}
@@ -123,17 +123,17 @@ static void dilate(const SkPMColor* src, SkPMColor* dst,
}
}
-static void dilateX(const SkBitmap& src, SkBitmap* dst, int radiusX)
+static void dilateX(const SkBitmap& src, SkBitmap* dst, int radiusX, const SkIRect& bounds)
{
- dilate(src.getAddr32(0, 0), dst->getAddr32(0, 0),
- radiusX, src.width(), src.height(),
+ dilate(src.getAddr32(bounds.left(), bounds.top()), dst->getAddr32(0, 0),
+ radiusX, bounds.width(), bounds.height(),
1, src.rowBytesAsPixels(), 1, dst->rowBytesAsPixels());
}
-static void dilateY(const SkBitmap& src, SkBitmap* dst, int radiusY)
+static void dilateY(const SkBitmap& src, SkBitmap* dst, int radiusY, const SkIRect& bounds)
{
- dilate(src.getAddr32(0, 0), dst->getAddr32(0, 0),
- radiusY, src.height(), src.width(),
+ dilate(src.getAddr32(bounds.left(), bounds.top()), dst->getAddr32(0, 0),
+ radiusY, bounds.height(), bounds.width(),
src.rowBytesAsPixels(), 1, dst->rowBytesAsPixels(), 1);
}
@@ -149,12 +149,18 @@ bool SkErodeImageFilter::onFilterImage(Proxy* proxy,
return false;
}
+ SkIRect bounds;
+ src.getBounds(&bounds);
+ if (!this->applyCropRect(&bounds, ctm)) {
+ return false;
+ }
+
SkAutoLockPixels alp(src);
if (!src.getPixels()) {
return false;
}
- dst->setConfig(src.config(), src.width(), src.height());
+ dst->setConfig(src.config(), bounds.width(), bounds.height());
dst->allocPixels();
int width = radius().width();
@@ -165,7 +171,9 @@ bool SkErodeImageFilter::onFilterImage(Proxy* proxy,
}
if (width == 0 && height == 0) {
- src.copyTo(dst, dst->config());
+ src.extractSubset(dst, bounds);
+ offset->fX += bounds.left();
+ offset->fY += bounds.top();
return true;
}
@@ -176,13 +184,16 @@ bool SkErodeImageFilter::onFilterImage(Proxy* proxy,
}
if (width > 0 && height > 0) {
- erodeX(src, &temp, width);
- erodeY(temp, dst, height);
+ erodeX(src, &temp, width, bounds);
+ SkIRect tmpBounds = SkIRect::MakeWH(bounds.width(), bounds.height());
+ erodeY(temp, dst, height, tmpBounds);
} else if (width > 0) {
- erodeX(src, dst, width);
+ erodeX(src, dst, width, bounds);
} else if (height > 0) {
- erodeY(src, dst, height);
+ erodeY(src, dst, height, bounds);
}
+ offset->fX += bounds.left();
+ offset->fY += bounds.top();
return true;
}
@@ -197,12 +208,18 @@ bool SkDilateImageFilter::onFilterImage(Proxy* proxy,
return false;
}
+ SkIRect bounds;
+ src.getBounds(&bounds);
+ if (!this->applyCropRect(&bounds, ctm)) {
+ return false;
+ }
+
SkAutoLockPixels alp(src);
if (!src.getPixels()) {
return false;
}
- dst->setConfig(src.config(), src.width(), src.height());
+ dst->setConfig(src.config(), bounds.width(), bounds.height());
dst->allocPixels();
int width = radius().width();
@@ -213,7 +230,9 @@ bool SkDilateImageFilter::onFilterImage(Proxy* proxy,
}
if (width == 0 && height == 0) {
- src.copyTo(dst, dst->config());
+ src.extractSubset(dst, bounds);
+ offset->fX += bounds.left();
+ offset->fY += bounds.top();
return true;
}
@@ -224,13 +243,16 @@ bool SkDilateImageFilter::onFilterImage(Proxy* proxy,
}
if (width > 0 && height > 0) {
- dilateX(src, &temp, width);
- dilateY(temp, dst, height);
+ dilateX(src, &temp, width, bounds);
+ SkIRect tmpBounds = SkIRect::MakeWH(bounds.width(), bounds.height());
+ dilateY(temp, dst, height, tmpBounds);
} else if (width > 0) {
- dilateX(src, dst, width);
+ dilateX(src, dst, width, bounds);
} else if (height > 0) {
- dilateY(src, dst, height);
+ dilateY(src, dst, height, bounds);
}
+ offset->fX += bounds.left();
+ offset->fY += bounds.top();
return true;
}
@@ -450,7 +472,8 @@ namespace {
void apply_morphology_pass(GrContext* context,
GrTexture* texture,
- const SkIRect& rect,
+ const SkIRect& srcRect,
+ const SkIRect& dstRect,
int radius,
GrMorphologyEffect::MorphologyType morphType,
Gr1DKernelEffect::Direction direction) {
@@ -459,15 +482,19 @@ void apply_morphology_pass(GrContext* context,
direction,
radius,
morphType))->unref();
- context->drawRect(paint, SkRect::MakeFromIRect(rect));
+ context->drawRectToRect(paint, SkRect::MakeFromIRect(dstRect), SkRect::MakeFromIRect(srcRect));
}
-GrTexture* apply_morphology(GrTexture* srcTexture,
- const SkIRect& rect,
- GrMorphologyEffect::MorphologyType morphType,
- SkISize radius) {
+bool apply_morphology(const SkBitmap& input,
+ const SkIRect& rect,
+ GrMorphologyEffect::MorphologyType morphType,
+ SkISize radius,
+ SkBitmap* dst) {
+ GrTexture* srcTexture = input.getTexture();
+ SkASSERT(NULL != srcTexture);
GrContext* context = srcTexture->getContext();
srcTexture->ref();
+ SkAutoTUnref<GrTexture> src(srcTexture);
GrContext::AutoMatrix am;
am.setIdentity(context);
@@ -475,62 +502,101 @@ GrTexture* apply_morphology(GrTexture* srcTexture,
GrContext::AutoClip acs(context, SkRect::MakeWH(SkIntToScalar(srcTexture->width()),
SkIntToScalar(srcTexture->height())));
+ SkIRect dstRect = SkIRect::MakeWH(rect.width(), rect.height());
GrTextureDesc desc;
desc.fFlags = kRenderTarget_GrTextureFlagBit | kNoStencil_GrTextureFlagBit;
desc.fWidth = rect.width();
desc.fHeight = rect.height();
desc.fConfig = kSkia8888_GrPixelConfig;
+ SkIRect srcRect = rect;
if (radius.fWidth > 0) {
GrAutoScratchTexture ast(context, desc);
GrContext::AutoRenderTarget art(context, ast.texture()->asRenderTarget());
- apply_morphology_pass(context, srcTexture, rect, radius.fWidth,
+ apply_morphology_pass(context, src, srcRect, dstRect, radius.fWidth,
morphType, Gr1DKernelEffect::kX_Direction);
- SkIRect clearRect = SkIRect::MakeXYWH(rect.fLeft, rect.fBottom,
- rect.width(), radius.fHeight);
+ SkIRect clearRect = SkIRect::MakeXYWH(dstRect.fLeft, dstRect.fBottom,
+ dstRect.width(), radius.fHeight);
context->clear(&clearRect, 0x0);
- srcTexture->unref();
- srcTexture = ast.detach();
+ src.reset(ast.detach());
+ srcRect = dstRect;
}
if (radius.fHeight > 0) {
GrAutoScratchTexture ast(context, desc);
GrContext::AutoRenderTarget art(context, ast.texture()->asRenderTarget());
- apply_morphology_pass(context, srcTexture, rect, radius.fHeight,
+ apply_morphology_pass(context, src, srcRect, dstRect, radius.fHeight,
morphType, Gr1DKernelEffect::kY_Direction);
- srcTexture->unref();
- srcTexture = ast.detach();
+ src.reset(ast.detach());
}
- return srcTexture;
+ return SkImageFilterUtils::WrapTexture(src, rect.width(), rect.height(), dst);
}
};
bool SkDilateImageFilter::filterImageGPU(Proxy* proxy, const SkBitmap& src, const SkMatrix& ctm,
SkBitmap* result, SkIPoint* offset) {
- SkBitmap inputBM;
- if (!SkImageFilterUtils::GetInputResultGPU(getInput(0), proxy, src, ctm, &inputBM, offset)) {
+ SkBitmap input;
+ if (!SkImageFilterUtils::GetInputResultGPU(getInput(0), proxy, src, ctm, &input, offset)) {
return false;
}
- GrTexture* input = inputBM.getTexture();
SkIRect bounds;
src.getBounds(&bounds);
- SkAutoTUnref<GrTexture> resultTex(apply_morphology(input, bounds,
- GrMorphologyEffect::kDilate_MorphologyType, radius()));
- return SkImageFilterUtils::WrapTexture(resultTex, src.width(), src.height(), result);
+ if (!this->applyCropRect(&bounds, ctm)) {
+ return false;
+ }
+ int width = radius().width();
+ int height = radius().height();
+
+ if (width < 0 || height < 0) {
+ return false;
+ }
+
+ if (width == 0 && height == 0) {
+ src.extractSubset(result, bounds);
+ offset->fX += bounds.left();
+ offset->fY += bounds.top();
+ return true;
+ }
+
+ if (!apply_morphology(input, bounds, GrMorphologyEffect::kDilate_MorphologyType, radius(), result)) {
+ return false;
+ }
+ offset->fX += bounds.left();
+ offset->fY += bounds.top();
+ return true;
}
bool SkErodeImageFilter::filterImageGPU(Proxy* proxy, const SkBitmap& src, const SkMatrix& ctm,
SkBitmap* result, SkIPoint* offset) {
- SkBitmap inputBM;
- if (!SkImageFilterUtils::GetInputResultGPU(getInput(0), proxy, src, ctm, &inputBM, offset)) {
+ SkBitmap input;
+ if (!SkImageFilterUtils::GetInputResultGPU(getInput(0), proxy, src, ctm, &input, offset)) {
return false;
}
- GrTexture* input = inputBM.getTexture();
SkIRect bounds;
src.getBounds(&bounds);
- SkAutoTUnref<GrTexture> resultTex(apply_morphology(input, bounds,
- GrMorphologyEffect::kErode_MorphologyType, radius()));
- return SkImageFilterUtils::WrapTexture(resultTex, src.width(), src.height(), result);
+ if (!this->applyCropRect(&bounds, ctm)) {
+ return false;
+ }
+ int width = radius().width();
+ int height = radius().height();
+
+ if (width < 0 || height < 0) {
+ return false;
+ }
+
+ if (width == 0 && height == 0) {
+ src.extractSubset(result, bounds);
+ offset->fX += bounds.left();
+ offset->fY += bounds.top();
+ return true;
+ }
+
+ if (!apply_morphology(input, bounds, GrMorphologyEffect::kErode_MorphologyType, radius(), result)) {
+ return false;
+ }
+ offset->fX += bounds.left();
+ offset->fY += bounds.top();
+ return true;
}
#endif
« no previous file with comments | « include/effects/SkMorphologyImageFilter.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698