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 |