| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2012 The Android Open Source Project | 2 * Copyright 2012 The Android Open Source Project |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 6 */ | 6 */ |
| 7 | 7 |
| 8 #include "SkMorphologyImageFilter.h" | 8 #include "SkMorphologyImageFilter.h" |
| 9 #include "SkBitmap.h" | 9 #include "SkBitmap.h" |
| 10 #include "SkColorPriv.h" | 10 #include "SkColorPriv.h" |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 77 dptr += dstStrideY; | 77 dptr += dstStrideY; |
| 78 lp += srcStrideY; | 78 lp += srcStrideY; |
| 79 up += srcStrideY; | 79 up += srcStrideY; |
| 80 } | 80 } |
| 81 if (x >= radius) src += srcStrideX; | 81 if (x >= radius) src += srcStrideX; |
| 82 if (x + radius < width - 1) upperSrc += srcStrideX; | 82 if (x + radius < width - 1) upperSrc += srcStrideX; |
| 83 dst += dstStrideX; | 83 dst += dstStrideX; |
| 84 } | 84 } |
| 85 } | 85 } |
| 86 | 86 |
| 87 static void erodeX(const SkBitmap& src, SkBitmap* dst, int radiusX, const SkIRec
t& bounds) | |
| 88 { | |
| 89 SkMorphologyProc erodeXProc = SkMorphologyGetPlatformProc(kErodeX_SkMorpholo
gyProcType); | |
| 90 if (!erodeXProc) { | |
| 91 erodeXProc = erode<kX>; | |
| 92 } | |
| 93 erodeXProc(src.getAddr32(bounds.left(), bounds.top()), dst->getAddr32(0, 0), | |
| 94 radiusX, bounds.width(), bounds.height(), | |
| 95 src.rowBytesAsPixels(), dst->rowBytesAsPixels()); | |
| 96 } | |
| 97 | |
| 98 static void erodeY(const SkBitmap& src, SkBitmap* dst, int radiusY, const SkIRec
t& bounds) | |
| 99 { | |
| 100 SkMorphologyProc erodeYProc = SkMorphologyGetPlatformProc(kErodeY_SkMorpholo
gyProcType); | |
| 101 if (!erodeYProc) { | |
| 102 erodeYProc = erode<kY>; | |
| 103 } | |
| 104 erodeYProc(src.getAddr32(bounds.left(), bounds.top()), dst->getAddr32(0, 0), | |
| 105 radiusY, bounds.height(), bounds.width(), | |
| 106 src.rowBytesAsPixels(), dst->rowBytesAsPixels()); | |
| 107 } | |
| 108 | |
| 109 template<MorphDirection direction> | 87 template<MorphDirection direction> |
| 110 static void dilate(const SkPMColor* src, SkPMColor* dst, | 88 static void dilate(const SkPMColor* src, SkPMColor* dst, |
| 111 int radius, int width, int height, | 89 int radius, int width, int height, |
| 112 int srcStride, int dstStride) | 90 int srcStride, int dstStride) |
| 113 { | 91 { |
| 114 const int srcStrideX = direction == kX ? 1 : srcStride; | 92 const int srcStrideX = direction == kX ? 1 : srcStride; |
| 115 const int dstStrideX = direction == kX ? 1 : dstStride; | 93 const int dstStrideX = direction == kX ? 1 : dstStride; |
| 116 const int srcStrideY = direction == kX ? srcStride : 1; | 94 const int srcStrideY = direction == kX ? srcStride : 1; |
| 117 const int dstStrideY = direction == kX ? dstStride : 1; | 95 const int dstStrideY = direction == kX ? dstStride : 1; |
| 118 radius = SkMin32(radius, width - 1); | 96 radius = SkMin32(radius, width - 1); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 137 dptr += dstStrideY; | 115 dptr += dstStrideY; |
| 138 lp += srcStrideY; | 116 lp += srcStrideY; |
| 139 up += srcStrideY; | 117 up += srcStrideY; |
| 140 } | 118 } |
| 141 if (x >= radius) src += srcStrideX; | 119 if (x >= radius) src += srcStrideX; |
| 142 if (x + radius < width - 1) upperSrc += srcStrideX; | 120 if (x + radius < width - 1) upperSrc += srcStrideX; |
| 143 dst += dstStrideX; | 121 dst += dstStrideX; |
| 144 } | 122 } |
| 145 } | 123 } |
| 146 | 124 |
| 147 static void dilateX(const SkBitmap& src, SkBitmap* dst, int radiusX, const SkIRe
ct& bounds) | 125 static void callProcX(SkMorphologyImageFilter::Proc procX, const SkBitmap& src,
SkBitmap* dst, int radiusX, const SkIRect& bounds) |
| 148 { | 126 { |
| 149 SkMorphologyProc dilateXProc = SkMorphologyGetPlatformProc(kDilateX_SkMorpho
logyProcType); | 127 procX(src.getAddr32(bounds.left(), bounds.top()), dst->getAddr32(0, 0), |
| 150 if (!dilateXProc) { | 128 radiusX, bounds.width(), bounds.height(), |
| 151 dilateXProc = dilate<kX>; | 129 src.rowBytesAsPixels(), dst->rowBytesAsPixels()); |
| 152 } | |
| 153 dilateXProc(src.getAddr32(bounds.left(), bounds.top()), dst->getAddr32(0, 0)
, | |
| 154 radiusX, bounds.width(), bounds.height(), | |
| 155 src.rowBytesAsPixels(), dst->rowBytesAsPixels()); | |
| 156 } | 130 } |
| 157 | 131 |
| 158 static void dilateY(const SkBitmap& src, SkBitmap* dst, int radiusY, const SkIRe
ct& bounds) | 132 static void callProcY(SkMorphologyImageFilter::Proc procY, const SkBitmap& src,
SkBitmap* dst, int radiusY, const SkIRect& bounds) |
| 159 { | 133 { |
| 160 SkMorphologyProc dilateYProc = SkMorphologyGetPlatformProc(kDilateY_SkMorpho
logyProcType); | 134 procY(src.getAddr32(bounds.left(), bounds.top()), dst->getAddr32(0, 0), |
| 161 if (!dilateYProc) { | 135 radiusY, bounds.height(), bounds.width(), |
| 162 dilateYProc = dilate<kY>; | 136 src.rowBytesAsPixels(), dst->rowBytesAsPixels()); |
| 163 } | |
| 164 dilateYProc(src.getAddr32(bounds.left(), bounds.top()), dst->getAddr32(0, 0)
, | |
| 165 radiusY, bounds.height(), bounds.width(), | |
| 166 src.rowBytesAsPixels(), dst->rowBytesAsPixels()); | |
| 167 } | 137 } |
| 168 | 138 |
| 169 bool SkErodeImageFilter::onFilterImage(Proxy* proxy, | 139 bool SkMorphologyImageFilter::filterImageGeneric(SkMorphologyImageFilter::Proc p
rocX, |
| 170 const SkBitmap& source, const SkMatrix& c
tm, | 140 SkMorphologyImageFilter::Proc p
rocY, |
| 171 SkBitmap* dst, SkIPoint* offset) { | 141 Proxy* proxy, |
| 142 const SkBitmap& source, |
| 143 const SkMatrix& ctm, |
| 144 SkBitmap* dst, |
| 145 SkIPoint* offset) { |
| 172 SkBitmap src = source; | 146 SkBitmap src = source; |
| 173 SkIPoint srcOffset = SkIPoint::Make(0, 0); | 147 SkIPoint srcOffset = SkIPoint::Make(0, 0); |
| 174 if (getInput(0) && !getInput(0)->filterImage(proxy, source, ctm, &src, &srcO
ffset)) { | 148 if (getInput(0) && !getInput(0)->filterImage(proxy, source, ctm, &src, &srcO
ffset)) { |
| 175 return false; | 149 return false; |
| 176 } | 150 } |
| 177 | 151 |
| 178 if (src.config() != SkBitmap::kARGB_8888_Config) { | 152 if (src.config() != SkBitmap::kARGB_8888_Config) { |
| 179 return false; | 153 return false; |
| 180 } | 154 } |
| 181 | 155 |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 217 return true; | 191 return true; |
| 218 } | 192 } |
| 219 | 193 |
| 220 SkBitmap temp; | 194 SkBitmap temp; |
| 221 temp.setConfig(dst->config(), dst->width(), dst->height()); | 195 temp.setConfig(dst->config(), dst->width(), dst->height()); |
| 222 if (!temp.allocPixels()) { | 196 if (!temp.allocPixels()) { |
| 223 return false; | 197 return false; |
| 224 } | 198 } |
| 225 | 199 |
| 226 if (width > 0 && height > 0) { | 200 if (width > 0 && height > 0) { |
| 227 erodeX(src, &temp, width, srcBounds); | 201 callProcX(procX, src, &temp, width, srcBounds); |
| 228 SkIRect tmpBounds = SkIRect::MakeWH(srcBounds.width(), srcBounds.height(
)); | 202 SkIRect tmpBounds = SkIRect::MakeWH(srcBounds.width(), srcBounds.height(
)); |
| 229 erodeY(temp, dst, height, tmpBounds); | 203 callProcY(procY, temp, dst, height, tmpBounds); |
| 230 } else if (width > 0) { | 204 } else if (width > 0) { |
| 231 erodeX(src, dst, width, srcBounds); | 205 callProcX(procX, src, dst, width, srcBounds); |
| 232 } else if (height > 0) { | 206 } else if (height > 0) { |
| 233 erodeY(src, dst, height, srcBounds); | 207 callProcY(procY, src, dst, height, srcBounds); |
| 234 } | 208 } |
| 235 offset->fX = bounds.left(); | 209 offset->fX = bounds.left(); |
| 236 offset->fY = bounds.top(); | 210 offset->fY = bounds.top(); |
| 237 return true; | 211 return true; |
| 238 } | 212 } |
| 239 | 213 |
| 214 bool SkErodeImageFilter::onFilterImage(Proxy* proxy, |
| 215 const SkBitmap& source, const SkMatrix& c
tm, |
| 216 SkBitmap* dst, SkIPoint* offset) { |
| 217 Proc erodeXProc = SkMorphologyGetPlatformProc(kErodeX_SkMorphologyProcType); |
| 218 if (!erodeXProc) { |
| 219 erodeXProc = erode<kX>; |
| 220 } |
| 221 Proc erodeYProc = SkMorphologyGetPlatformProc(kErodeY_SkMorphologyProcType); |
| 222 if (!erodeYProc) { |
| 223 erodeYProc = erode<kY>; |
| 224 } |
| 225 return this->filterImageGeneric(erodeXProc, erodeYProc, proxy, source, ctm,
dst, offset); |
| 226 } |
| 227 |
| 240 bool SkDilateImageFilter::onFilterImage(Proxy* proxy, | 228 bool SkDilateImageFilter::onFilterImage(Proxy* proxy, |
| 241 const SkBitmap& source, const SkMatrix&
ctm, | 229 const SkBitmap& source, const SkMatrix&
ctm, |
| 242 SkBitmap* dst, SkIPoint* offset) { | 230 SkBitmap* dst, SkIPoint* offset) { |
| 243 SkBitmap src = source; | 231 Proc dilateXProc = SkMorphologyGetPlatformProc(kDilateX_SkMorphologyProcType
); |
| 244 SkIPoint srcOffset = SkIPoint::Make(0, 0); | 232 if (!dilateXProc) { |
| 245 if (getInput(0) && !getInput(0)->filterImage(proxy, source, ctm, &src, &srcO
ffset)) { | 233 dilateXProc = dilate<kX>; |
| 246 return false; | |
| 247 } | 234 } |
| 248 if (src.config() != SkBitmap::kARGB_8888_Config) { | 235 Proc dilateYProc = SkMorphologyGetPlatformProc(kDilateY_SkMorphologyProcType
); |
| 249 return false; | 236 if (!dilateYProc) { |
| 237 dilateYProc = dilate<kY>; |
| 250 } | 238 } |
| 251 | 239 return this->filterImageGeneric(dilateXProc, dilateYProc, proxy, source, ctm
, dst, offset); |
| 252 SkIRect bounds; | |
| 253 src.getBounds(&bounds); | |
| 254 bounds.offset(srcOffset); | |
| 255 if (!this->applyCropRect(&bounds, ctm)) { | |
| 256 return false; | |
| 257 } | |
| 258 | |
| 259 SkAutoLockPixels alp(src); | |
| 260 if (!src.getPixels()) { | |
| 261 return false; | |
| 262 } | |
| 263 | |
| 264 dst->setConfig(src.config(), bounds.width(), bounds.height()); | |
| 265 dst->allocPixels(); | |
| 266 if (!dst->getPixels()) { | |
| 267 return false; | |
| 268 } | |
| 269 | |
| 270 SkVector radius = SkVector::Make(SkIntToScalar(this->radius().width()), | |
| 271 SkIntToScalar(this->radius().height())); | |
| 272 ctm.mapVectors(&radius, 1); | |
| 273 int width = SkScalarFloorToInt(radius.fX); | |
| 274 int height = SkScalarFloorToInt(radius.fY); | |
| 275 | |
| 276 if (width < 0 || height < 0) { | |
| 277 return false; | |
| 278 } | |
| 279 | |
| 280 SkIRect srcBounds = bounds; | |
| 281 srcBounds.offset(-srcOffset); | |
| 282 | |
| 283 if (width == 0 && height == 0) { | |
| 284 src.extractSubset(dst, srcBounds); | |
| 285 offset->fX = bounds.left(); | |
| 286 offset->fY = bounds.top(); | |
| 287 return true; | |
| 288 } | |
| 289 | |
| 290 SkBitmap temp; | |
| 291 temp.setConfig(dst->config(), dst->width(), dst->height()); | |
| 292 if (!temp.allocPixels()) { | |
| 293 return false; | |
| 294 } | |
| 295 | |
| 296 if (width > 0 && height > 0) { | |
| 297 dilateX(src, &temp, width, srcBounds); | |
| 298 SkIRect tmpBounds = SkIRect::MakeWH(srcBounds.width(), srcBounds.height(
)); | |
| 299 dilateY(temp, dst, height, tmpBounds); | |
| 300 } else if (width > 0) { | |
| 301 dilateX(src, dst, width, srcBounds); | |
| 302 } else if (height > 0) { | |
| 303 dilateY(src, dst, height, srcBounds); | |
| 304 } | |
| 305 offset->fX = bounds.left(); | |
| 306 offset->fY = bounds.top(); | |
| 307 return true; | |
| 308 } | 240 } |
| 309 | 241 |
| 310 #if SK_SUPPORT_GPU | 242 #if SK_SUPPORT_GPU |
| 311 | 243 |
| 312 /////////////////////////////////////////////////////////////////////////////// | 244 /////////////////////////////////////////////////////////////////////////////// |
| 313 | 245 |
| 314 class GrGLMorphologyEffect; | 246 class GrGLMorphologyEffect; |
| 315 | 247 |
| 316 /** | 248 /** |
| 317 * Morphology effects. Depending upon the type of morphology, either the | 249 * Morphology effects. Depending upon the type of morphology, either the |
| (...skipping 254 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 572 GrContext::AutoRenderTarget art(context, ast.texture()->asRenderTarget()
); | 504 GrContext::AutoRenderTarget art(context, ast.texture()->asRenderTarget()
); |
| 573 apply_morphology_pass(context, src, srcRect, dstRect, radius.fHeight, | 505 apply_morphology_pass(context, src, srcRect, dstRect, radius.fHeight, |
| 574 morphType, Gr1DKernelEffect::kY_Direction); | 506 morphType, Gr1DKernelEffect::kY_Direction); |
| 575 src.reset(ast.detach()); | 507 src.reset(ast.detach()); |
| 576 } | 508 } |
| 577 return SkImageFilterUtils::WrapTexture(src, rect.width(), rect.height(), dst
); | 509 return SkImageFilterUtils::WrapTexture(src, rect.width(), rect.height(), dst
); |
| 578 } | 510 } |
| 579 | 511 |
| 580 }; | 512 }; |
| 581 | 513 |
| 582 bool SkDilateImageFilter::filterImageGPU(Proxy* proxy, const SkBitmap& src, cons
t SkMatrix& ctm, | 514 bool SkMorphologyImageFilter::filterImageGPUGeneric(bool dilate, |
| 583 SkBitmap* result, SkIPoint* offset) { | 515 Proxy* proxy, |
| 516 const SkBitmap& src, |
| 517 const SkMatrix& ctm, |
| 518 SkBitmap* result, |
| 519 SkIPoint* offset) { |
| 584 SkBitmap input; | 520 SkBitmap input; |
| 585 SkIPoint srcOffset = SkIPoint::Make(0, 0); | 521 SkIPoint srcOffset = SkIPoint::Make(0, 0); |
| 586 if (!SkImageFilterUtils::GetInputResultGPU(getInput(0), proxy, src, ctm, &in
put, &srcOffset)) { | 522 if (!SkImageFilterUtils::GetInputResultGPU(getInput(0), proxy, src, ctm, &in
put, &srcOffset)) { |
| 587 return false; | 523 return false; |
| 588 } | 524 } |
| 589 SkIRect bounds; | 525 SkIRect bounds; |
| 590 input.getBounds(&bounds); | 526 input.getBounds(&bounds); |
| 591 bounds.offset(srcOffset); | 527 bounds.offset(srcOffset); |
| 592 if (!this->applyCropRect(&bounds, ctm)) { | 528 if (!this->applyCropRect(&bounds, ctm)) { |
| 593 return false; | 529 return false; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 604 | 540 |
| 605 SkIRect srcBounds = bounds; | 541 SkIRect srcBounds = bounds; |
| 606 srcBounds.offset(-srcOffset); | 542 srcBounds.offset(-srcOffset); |
| 607 if (width == 0 && height == 0) { | 543 if (width == 0 && height == 0) { |
| 608 input.extractSubset(result, srcBounds); | 544 input.extractSubset(result, srcBounds); |
| 609 offset->fX = bounds.left(); | 545 offset->fX = bounds.left(); |
| 610 offset->fY = bounds.top(); | 546 offset->fY = bounds.top(); |
| 611 return true; | 547 return true; |
| 612 } | 548 } |
| 613 | 549 |
| 614 if (!apply_morphology(input, srcBounds, GrMorphologyEffect::kDilate_Morpholo
gyType, | 550 GrMorphologyEffect::MorphologyType type = dilate ? GrMorphologyEffect::kDila
te_MorphologyType : GrMorphologyEffect::kErode_MorphologyType; |
| 551 if (!apply_morphology(input, srcBounds, type, |
| 615 SkISize::Make(width, height), result)) { | 552 SkISize::Make(width, height), result)) { |
| 616 return false; | 553 return false; |
| 617 } | 554 } |
| 618 offset->fX = bounds.left(); | 555 offset->fX = bounds.left(); |
| 619 offset->fY = bounds.top(); | 556 offset->fY = bounds.top(); |
| 620 return true; | 557 return true; |
| 621 } | 558 } |
| 622 | 559 |
| 560 bool SkDilateImageFilter::filterImageGPU(Proxy* proxy, const SkBitmap& src, cons
t SkMatrix& ctm, |
| 561 SkBitmap* result, SkIPoint* offset) { |
| 562 return this->filterImageGPUGeneric(true, proxy, src, ctm, result, offset); |
| 563 } |
| 564 |
| 623 bool SkErodeImageFilter::filterImageGPU(Proxy* proxy, const SkBitmap& src, const
SkMatrix& ctm, | 565 bool SkErodeImageFilter::filterImageGPU(Proxy* proxy, const SkBitmap& src, const
SkMatrix& ctm, |
| 624 SkBitmap* result, SkIPoint* offset) { | 566 SkBitmap* result, SkIPoint* offset) { |
| 625 SkBitmap input; | 567 return this->filterImageGPUGeneric(false, proxy, src, ctm, result, offset); |
| 626 SkIPoint srcOffset = SkIPoint::Make(0, 0); | |
| 627 if (!SkImageFilterUtils::GetInputResultGPU(getInput(0), proxy, src, ctm, &in
put, &srcOffset)) { | |
| 628 return false; | |
| 629 } | |
| 630 SkIRect bounds; | |
| 631 input.getBounds(&bounds); | |
| 632 bounds.offset(srcOffset); | |
| 633 if (!this->applyCropRect(&bounds, ctm)) { | |
| 634 return false; | |
| 635 } | |
| 636 SkVector radius = SkVector::Make(SkIntToScalar(this->radius().width()), | |
| 637 SkIntToScalar(this->radius().height())); | |
| 638 ctm.mapVectors(&radius, 1); | |
| 639 int width = SkScalarFloorToInt(radius.fX); | |
| 640 int height = SkScalarFloorToInt(radius.fY); | |
| 641 | |
| 642 if (width < 0 || height < 0) { | |
| 643 return false; | |
| 644 } | |
| 645 | |
| 646 SkIRect srcBounds = bounds; | |
| 647 srcBounds.offset(-srcOffset); | |
| 648 | |
| 649 if (width == 0 && height == 0) { | |
| 650 input.extractSubset(result, srcBounds); | |
| 651 offset->fX = bounds.left(); | |
| 652 offset->fY = bounds.top(); | |
| 653 return true; | |
| 654 } | |
| 655 | |
| 656 if (!apply_morphology(input, srcBounds, GrMorphologyEffect::kErode_Morpholog
yType, | |
| 657 SkISize::Make(width, height), result)) { | |
| 658 return false; | |
| 659 } | |
| 660 offset->fX = bounds.left(); | |
| 661 offset->fY = bounds.top(); | |
| 662 return true; | |
| 663 } | 568 } |
| 664 | 569 |
| 665 #endif | 570 #endif |
| OLD | NEW |