| 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" |
| 11 #include "SkImage.h" |
| 12 #include "SkImagePriv.h" |
| 13 #include "SkImage_Base.h" |
| 11 #include "SkReadBuffer.h" | 14 #include "SkReadBuffer.h" |
| 12 #include "SkWriteBuffer.h" | 15 #include "SkWriteBuffer.h" |
| 13 #include "SkRect.h" | 16 #include "SkRect.h" |
| 14 #include "SkMorphology_opts.h" | 17 #include "SkMorphology_opts.h" |
| 15 #if SK_SUPPORT_GPU | 18 #if SK_SUPPORT_GPU |
| 16 #include "GrContext.h" | 19 #include "GrContext.h" |
| 17 #include "GrInvariantOutput.h" | 20 #include "GrInvariantOutput.h" |
| 18 #include "GrTexture.h" | 21 #include "GrTexture.h" |
| 19 #include "effects/Gr1DKernelEffect.h" | 22 #include "effects/Gr1DKernelEffect.h" |
| 20 #include "gl/GrGLProcessor.h" | 23 #include "gl/GrGLProcessor.h" |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 125 static void callProcY(SkMorphologyImageFilter::Proc procY, const SkBitmap& src,
SkBitmap* dst, int radiusY, const SkIRect& bounds) | 128 static void callProcY(SkMorphologyImageFilter::Proc procY, const SkBitmap& src,
SkBitmap* dst, int radiusY, const SkIRect& bounds) |
| 126 { | 129 { |
| 127 procY(src.getAddr32(bounds.left(), bounds.top()), dst->getAddr32(0, 0), | 130 procY(src.getAddr32(bounds.left(), bounds.top()), dst->getAddr32(0, 0), |
| 128 radiusY, bounds.height(), bounds.width(), | 131 radiusY, bounds.height(), bounds.width(), |
| 129 src.rowBytesAsPixels(), dst->rowBytesAsPixels()); | 132 src.rowBytesAsPixels(), dst->rowBytesAsPixels()); |
| 130 } | 133 } |
| 131 | 134 |
| 132 bool SkMorphologyImageFilter::filterImageGeneric(SkMorphologyImageFilter::Proc p
rocX, | 135 bool SkMorphologyImageFilter::filterImageGeneric(SkMorphologyImageFilter::Proc p
rocX, |
| 133 SkMorphologyImageFilter::Proc p
rocY, | 136 SkMorphologyImageFilter::Proc p
rocY, |
| 134 Proxy* proxy, | 137 Proxy* proxy, |
| 135 const SkBitmap& source, | 138 const SkImage* source, |
| 136 const Context& ctx, | 139 const Context& ctx, |
| 137 SkBitmap* dst, | 140 SkAutoTUnref<const SkImage>& ds
t, |
| 138 SkIPoint* offset) const { | 141 SkIPoint* offset) const { |
| 139 SkBitmap src = source; | 142 SkAutoTUnref<const SkImage> src(SkRef(source)); |
| 140 SkIPoint srcOffset = SkIPoint::Make(0, 0); | 143 SkIPoint srcOffset = SkIPoint::Make(0, 0); |
| 141 if (getInput(0) && !getInput(0)->filterImage(proxy, source, ctx, &src, &srcO
ffset)) { | 144 if (getInput(0) && !getInput(0)->filterImage(proxy, source, ctx, src, &srcOf
fset)) { |
| 142 return false; | |
| 143 } | |
| 144 | |
| 145 if (src.colorType() != kN32_SkColorType) { | |
| 146 return false; | 145 return false; |
| 147 } | 146 } |
| 148 | 147 |
| 149 SkIRect bounds; | 148 SkIRect bounds; |
| 150 if (!this->applyCropRect(ctx, proxy, src, &srcOffset, &bounds, &src)) { | 149 if (!this->applyCropRect(ctx, proxy, src, &srcOffset, &bounds, src)) { |
| 151 return false; | 150 return false; |
| 152 } | 151 } |
| 153 | 152 |
| 154 SkAutoLockPixels alp(src); | 153 SkBitmap srcBitmap; |
| 155 if (!src.getPixels()) { | 154 SkAutoAdoptImageAsN32Bitmap aai(src, &srcBitmap); |
| 155 if (NULL == srcBitmap.getPixels()) { |
| 156 return false; | 156 return false; |
| 157 } | 157 } |
| 158 | 158 |
| 159 if (!dst->tryAllocPixels(src.info().makeWH(bounds.width(), bounds.height()))
) { | 159 SkBitmap dstBitmap; |
| 160 if (!dstBitmap.tryAllocPixels(srcBitmap.info().makeWH(bounds.width(), bounds
.height()))) { |
| 160 return false; | 161 return false; |
| 161 } | 162 } |
| 162 | 163 |
| 163 SkVector radius = SkVector::Make(SkIntToScalar(this->radius().width()), | 164 SkVector radius = SkVector::Make(SkIntToScalar(this->radius().width()), |
| 164 SkIntToScalar(this->radius().height())); | 165 SkIntToScalar(this->radius().height())); |
| 165 ctx.ctm().mapVectors(&radius, 1); | 166 ctx.ctm().mapVectors(&radius, 1); |
| 166 int width = SkScalarFloorToInt(radius.fX); | 167 int width = SkScalarFloorToInt(radius.fX); |
| 167 int height = SkScalarFloorToInt(radius.fY); | 168 int height = SkScalarFloorToInt(radius.fY); |
| 168 | 169 |
| 169 if (width < 0 || height < 0) { | 170 if (width < 0 || height < 0) { |
| 170 return false; | 171 return false; |
| 171 } | 172 } |
| 172 | 173 |
| 173 SkIRect srcBounds = bounds; | 174 SkIRect srcBounds = bounds; |
| 174 srcBounds.offset(-srcOffset); | 175 srcBounds.offset(-srcOffset); |
| 175 | 176 |
| 176 if (width == 0 && height == 0) { | 177 if (width == 0 && height == 0) { |
| 177 src.extractSubset(dst, srcBounds); | 178 srcBitmap.extractSubset(&dstBitmap, srcBounds); |
| 179 SkImage* image = SkNewImageFromBitmap(dstBitmap, NULL); |
| 180 if (NULL == image) { |
| 181 return false; |
| 182 } |
| 183 dst.reset(image); |
| 178 offset->fX = bounds.left(); | 184 offset->fX = bounds.left(); |
| 179 offset->fY = bounds.top(); | 185 offset->fY = bounds.top(); |
| 180 return true; | 186 return true; |
| 181 } | 187 } |
| 182 | 188 |
| 183 SkBitmap temp; | 189 SkBitmap temp; |
| 184 if (!temp.tryAllocPixels(dst->info())) { | 190 if (!temp.tryAllocPixels(dstBitmap.info())) { |
| 185 return false; | 191 return false; |
| 186 } | 192 } |
| 187 | 193 |
| 188 if (width > 0 && height > 0) { | 194 if (width > 0 && height > 0) { |
| 189 callProcX(procX, src, &temp, width, srcBounds); | 195 callProcX(procX, srcBitmap, &temp, width, srcBounds); |
| 190 SkIRect tmpBounds = SkIRect::MakeWH(srcBounds.width(), srcBounds.height(
)); | 196 SkIRect tmpBounds = SkIRect::MakeWH(srcBounds.width(), srcBounds.height(
)); |
| 191 callProcY(procY, temp, dst, height, tmpBounds); | 197 callProcY(procY, temp, &dstBitmap, height, tmpBounds); |
| 192 } else if (width > 0) { | 198 } else if (width > 0) { |
| 193 callProcX(procX, src, dst, width, srcBounds); | 199 callProcX(procX, srcBitmap, &dstBitmap, width, srcBounds); |
| 194 } else if (height > 0) { | 200 } else if (height > 0) { |
| 195 callProcY(procY, src, dst, height, srcBounds); | 201 callProcY(procY, srcBitmap, &dstBitmap, height, srcBounds); |
| 196 } | 202 } |
| 203 |
| 204 srcBitmap = SkBitmap(); |
| 205 temp = SkBitmap(); |
| 206 |
| 207 SkImage* image = SkNewImageFromBitmap(dstBitmap, NULL); |
| 208 if (NULL == image) { |
| 209 return false; |
| 210 } |
| 211 dst.reset(image); |
| 197 offset->fX = bounds.left(); | 212 offset->fX = bounds.left(); |
| 198 offset->fY = bounds.top(); | 213 offset->fY = bounds.top(); |
| 199 return true; | 214 return true; |
| 200 } | 215 } |
| 201 | 216 |
| 202 bool SkErodeImageFilter::onFilterImage(Proxy* proxy, | 217 bool SkErodeImageFilter::onFilterImage(Proxy* proxy, |
| 203 const SkBitmap& source, const Context& ct
x, | 218 const SkImage* source, const Context& ctx
, |
| 204 SkBitmap* dst, SkIPoint* offset) const { | 219 SkAutoTUnref<const SkImage>& dst, SkIPoin
t* offset) const { |
| 205 Proc erodeXProc = SkMorphologyGetPlatformProc(kErodeX_SkMorphologyProcType); | 220 Proc erodeXProc = SkMorphologyGetPlatformProc(kErodeX_SkMorphologyProcType); |
| 206 if (!erodeXProc) { | 221 if (!erodeXProc) { |
| 207 erodeXProc = erode<kX>; | 222 erodeXProc = erode<kX>; |
| 208 } | 223 } |
| 209 Proc erodeYProc = SkMorphologyGetPlatformProc(kErodeY_SkMorphologyProcType); | 224 Proc erodeYProc = SkMorphologyGetPlatformProc(kErodeY_SkMorphologyProcType); |
| 210 if (!erodeYProc) { | 225 if (!erodeYProc) { |
| 211 erodeYProc = erode<kY>; | 226 erodeYProc = erode<kY>; |
| 212 } | 227 } |
| 213 return this->filterImageGeneric(erodeXProc, erodeYProc, proxy, source, ctx,
dst, offset); | 228 return this->filterImageGeneric(erodeXProc, erodeYProc, proxy, source, ctx,
dst, offset); |
| 214 } | 229 } |
| 215 | 230 |
| 216 bool SkDilateImageFilter::onFilterImage(Proxy* proxy, | 231 bool SkDilateImageFilter::onFilterImage(Proxy* proxy, |
| 217 const SkBitmap& source, const Context& c
tx, | 232 const SkImage* source, const Context& ct
x, |
| 218 SkBitmap* dst, SkIPoint* offset) const { | 233 SkAutoTUnref<const SkImage>& dst, SkIPoi
nt* offset) const { |
| 219 Proc dilateXProc = SkMorphologyGetPlatformProc(kDilateX_SkMorphologyProcType
); | 234 Proc dilateXProc = SkMorphologyGetPlatformProc(kDilateX_SkMorphologyProcType
); |
| 220 if (!dilateXProc) { | 235 if (!dilateXProc) { |
| 221 dilateXProc = dilate<kX>; | 236 dilateXProc = dilate<kX>; |
| 222 } | 237 } |
| 223 Proc dilateYProc = SkMorphologyGetPlatformProc(kDilateY_SkMorphologyProcType
); | 238 Proc dilateYProc = SkMorphologyGetPlatformProc(kDilateY_SkMorphologyProcType
); |
| 224 if (!dilateYProc) { | 239 if (!dilateYProc) { |
| 225 dilateYProc = dilate<kY>; | 240 dilateYProc = dilate<kY>; |
| 226 } | 241 } |
| 227 return this->filterImageGeneric(dilateXProc, dilateYProc, proxy, source, ctx
, dst, offset); | 242 return this->filterImageGeneric(dilateXProc, dilateYProc, proxy, source, ctx
, dst, offset); |
| 228 } | 243 } |
| (...skipping 407 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 636 // Draw upper and lower margins with bounds; middle without. | 651 // Draw upper and lower margins with bounds; middle without. |
| 637 apply_morphology_rect(context, rt,texture, lowerSrcRect, lowerDstRect, r
adius, | 652 apply_morphology_rect(context, rt,texture, lowerSrcRect, lowerDstRect, r
adius, |
| 638 morphType, bounds, direction); | 653 morphType, bounds, direction); |
| 639 apply_morphology_rect(context, rt, texture, upperSrcRect, upperDstRect,
radius, | 654 apply_morphology_rect(context, rt, texture, upperSrcRect, upperDstRect,
radius, |
| 640 morphType, bounds, direction); | 655 morphType, bounds, direction); |
| 641 apply_morphology_rect_no_bounds(context, rt, texture, middleSrcRect, mid
dleDstRect, radius, | 656 apply_morphology_rect_no_bounds(context, rt, texture, middleSrcRect, mid
dleDstRect, radius, |
| 642 morphType, direction); | 657 morphType, direction); |
| 643 } | 658 } |
| 644 } | 659 } |
| 645 | 660 |
| 646 bool apply_morphology(const SkBitmap& input, | 661 bool apply_morphology(const SkImage* input, |
| 647 const SkIRect& rect, | 662 const SkIRect& rect, |
| 648 GrMorphologyEffect::MorphologyType morphType, | 663 GrMorphologyEffect::MorphologyType morphType, |
| 649 SkISize radius, | 664 SkISize radius, |
| 650 SkBitmap* dst) { | 665 SkAutoTUnref<const SkImage>& dst) { |
| 651 SkAutoTUnref<GrTexture> srcTexture(SkRef(input.getTexture())); | 666 SkAutoTUnref<GrTexture> srcTexture(SkRef(input->getTexture())); |
| 652 SkASSERT(srcTexture); | 667 SkASSERT(srcTexture); |
| 653 GrContext* context = srcTexture->getContext(); | 668 GrContext* context = srcTexture->getContext(); |
| 654 | 669 |
| 655 GrContext::AutoClip acs(context, SkRect::MakeWH(SkIntToScalar(srcTexture->wi
dth()), | 670 GrContext::AutoClip acs(context, SkRect::MakeWH(SkIntToScalar(srcTexture->wi
dth()), |
| 656 SkIntToScalar(srcTexture->he
ight()))); | 671 SkIntToScalar(srcTexture->he
ight()))); |
| 657 | 672 |
| 658 SkIRect dstRect = SkIRect::MakeWH(rect.width(), rect.height()); | 673 SkIRect dstRect = SkIRect::MakeWH(rect.width(), rect.height()); |
| 659 GrSurfaceDesc desc; | 674 GrSurfaceDesc desc; |
| 660 desc.fFlags = kRenderTarget_GrSurfaceFlag; | 675 desc.fFlags = kRenderTarget_GrSurfaceFlag; |
| 661 desc.fWidth = rect.width(); | 676 desc.fWidth = rect.width(); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 681 } | 696 } |
| 682 if (radius.fHeight > 0) { | 697 if (radius.fHeight > 0) { |
| 683 GrTexture* texture = context->refScratchTexture(desc, GrContext::kApprox
_ScratchTexMatch); | 698 GrTexture* texture = context->refScratchTexture(desc, GrContext::kApprox
_ScratchTexMatch); |
| 684 if (NULL == texture) { | 699 if (NULL == texture) { |
| 685 return false; | 700 return false; |
| 686 } | 701 } |
| 687 apply_morphology_pass(context, texture->asRenderTarget(), srcTexture, sr
cRect, dstRect, | 702 apply_morphology_pass(context, texture->asRenderTarget(), srcTexture, sr
cRect, dstRect, |
| 688 radius.fHeight, morphType, Gr1DKernelEffect::kY_Di
rection); | 703 radius.fHeight, morphType, Gr1DKernelEffect::kY_Di
rection); |
| 689 srcTexture.reset(texture); | 704 srcTexture.reset(texture); |
| 690 } | 705 } |
| 691 SkImageFilter::WrapTexture(srcTexture, rect.width(), rect.height(), dst); | 706 if (!SkImageFilter::WrapTexture(srcTexture, rect.width(), rect.height(), dst
)) { |
| 707 return false; |
| 708 } |
| 692 return true; | 709 return true; |
| 693 } | 710 } |
| 694 | 711 |
| 695 }; | 712 }; |
| 696 | 713 |
| 697 bool SkMorphologyImageFilter::filterImageGPUGeneric(bool dilate, | 714 bool SkMorphologyImageFilter::filterImageGPUGeneric(bool dilate, |
| 698 Proxy* proxy, | 715 Proxy* proxy, |
| 699 const SkBitmap& src, | 716 const SkImage* src, |
| 700 const Context& ctx, | 717 const Context& ctx, |
| 701 SkBitmap* result, | 718 SkAutoTUnref<const SkImage>&
result, |
| 702 SkIPoint* offset) const { | 719 SkIPoint* offset) const { |
| 703 SkBitmap input = src; | 720 SkAutoTUnref<const SkImage> input(SkRef(src)); |
| 704 SkIPoint srcOffset = SkIPoint::Make(0, 0); | 721 SkIPoint srcOffset = SkIPoint::Make(0, 0); |
| 705 if (getInput(0) && !getInput(0)->getInputResultGPU(proxy, src, ctx, &input,
&srcOffset)) { | 722 if (getInput(0) && !getInput(0)->getInputResultGPU(proxy, src, ctx, input, &
srcOffset)) { |
| 706 return false; | 723 return false; |
| 707 } | 724 } |
| 708 SkIRect bounds; | 725 SkIRect bounds; |
| 709 if (!this->applyCropRect(ctx, proxy, input, &srcOffset, &bounds, &input)) { | 726 if (!this->applyCropRect(ctx, proxy, input, &srcOffset, &bounds, input)) { |
| 710 return false; | 727 return false; |
| 711 } | 728 } |
| 712 SkVector radius = SkVector::Make(SkIntToScalar(this->radius().width()), | 729 SkVector radius = SkVector::Make(SkIntToScalar(this->radius().width()), |
| 713 SkIntToScalar(this->radius().height())); | 730 SkIntToScalar(this->radius().height())); |
| 714 ctx.ctm().mapVectors(&radius, 1); | 731 ctx.ctm().mapVectors(&radius, 1); |
| 715 int width = SkScalarFloorToInt(radius.fX); | 732 int width = SkScalarFloorToInt(radius.fX); |
| 716 int height = SkScalarFloorToInt(radius.fY); | 733 int height = SkScalarFloorToInt(radius.fY); |
| 717 | 734 |
| 718 if (width < 0 || height < 0) { | 735 if (width < 0 || height < 0) { |
| 719 return false; | 736 return false; |
| 720 } | 737 } |
| 721 | 738 |
| 722 SkIRect srcBounds = bounds; | 739 SkIRect srcBounds = bounds; |
| 723 srcBounds.offset(-srcOffset); | 740 srcBounds.offset(-srcOffset); |
| 724 if (width == 0 && height == 0) { | 741 if (width == 0 && height == 0) { |
| 725 input.extractSubset(result, srcBounds); | 742 SkImage* image = input->newImage(srcBounds.width(), srcBounds.height(),
&srcBounds); |
| 743 if (NULL == image) { |
| 744 return false; |
| 745 } |
| 746 result.reset(image); |
| 726 offset->fX = bounds.left(); | 747 offset->fX = bounds.left(); |
| 727 offset->fY = bounds.top(); | 748 offset->fY = bounds.top(); |
| 728 return true; | 749 return true; |
| 729 } | 750 } |
| 730 | 751 |
| 731 GrMorphologyEffect::MorphologyType type = dilate ? GrMorphologyEffect::kDila
te_MorphologyType : GrMorphologyEffect::kErode_MorphologyType; | 752 GrMorphologyEffect::MorphologyType type = dilate ? GrMorphologyEffect::kDila
te_MorphologyType : GrMorphologyEffect::kErode_MorphologyType; |
| 732 if (!apply_morphology(input, srcBounds, type, | 753 if (!apply_morphology(input, srcBounds, type, |
| 733 SkISize::Make(width, height), result)) { | 754 SkISize::Make(width, height), result)) { |
| 734 return false; | 755 return false; |
| 735 } | 756 } |
| 736 offset->fX = bounds.left(); | 757 offset->fX = bounds.left(); |
| 737 offset->fY = bounds.top(); | 758 offset->fY = bounds.top(); |
| 738 return true; | 759 return true; |
| 739 } | 760 } |
| 740 | 761 |
| 741 bool SkDilateImageFilter::filterImageGPU(Proxy* proxy, const SkBitmap& src, cons
t Context& ctx, | 762 bool SkDilateImageFilter::filterImageGPU(Proxy* proxy, const SkImage* src, const
Context& ctx, |
| 742 SkBitmap* result, SkIPoint* offset) con
st { | 763 SkAutoTUnref<const SkImage>& result, Sk
IPoint* offset) const { |
| 743 return this->filterImageGPUGeneric(true, proxy, src, ctx, result, offset); | 764 return this->filterImageGPUGeneric(true, proxy, src, ctx, result, offset); |
| 744 } | 765 } |
| 745 | 766 |
| 746 bool SkErodeImageFilter::filterImageGPU(Proxy* proxy, const SkBitmap& src, const
Context& ctx, | 767 bool SkErodeImageFilter::filterImageGPU(Proxy* proxy, const SkImage* src, const
Context& ctx, |
| 747 SkBitmap* result, SkIPoint* offset) cons
t { | 768 SkAutoTUnref<const SkImage>& result, SkI
Point* offset) const { |
| 748 return this->filterImageGPUGeneric(false, proxy, src, ctx, result, offset); | 769 return this->filterImageGPUGeneric(false, proxy, src, ctx, result, offset); |
| 749 } | 770 } |
| 750 | 771 |
| 751 #endif | 772 #endif |
| OLD | NEW |