| 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 SkImage& source, |
| 136 const Context& ctx, | 139 const Context& ctx, |
| 137 SkBitmap* dst, | 140 SkAutoTUnref<SkImage>& dst, |
| 138 SkIPoint* offset) const { | 141 SkIPoint* offset) const { |
| 139 SkBitmap src = source; | 142 SkAutoTUnref<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)) { |
| 145 return false; |
| 146 } |
| 147 #if 0 |
| 148 if (src.colorType() != kN32_SkColorType) { |
| 149 return false; |
| 150 } |
| 151 #endif |
| 152 SkIRect bounds; |
| 153 if (!this->applyCropRect(ctx, proxy, *src, &srcOffset, &bounds, src)) { |
| 142 return false; | 154 return false; |
| 143 } | 155 } |
| 144 | 156 |
| 145 if (src.colorType() != kN32_SkColorType) { | 157 SkBitmap srcBitmap; |
| 158 if (!as_IB(src)->getROPixels(&srcBitmap)) { |
| 159 return false; |
| 160 } |
| 161 src.reset(NULL); |
| 162 SkAutoLockPixels alp(srcBitmap); |
| 163 if (!srcBitmap.getPixels()) { |
| 146 return false; | 164 return false; |
| 147 } | 165 } |
| 148 | 166 |
| 149 SkIRect bounds; | 167 SkBitmap dstBitmap; |
| 150 if (!this->applyCropRect(ctx, proxy, src, &srcOffset, &bounds, &src)) { | 168 if (!dstBitmap.tryAllocPixels(srcBitmap.info().makeWH(bounds.width(), bounds
.height()))) { |
| 151 return false; | 169 return false; |
| 152 } | 170 } |
| 153 | 171 |
| 154 SkAutoLockPixels alp(src); | |
| 155 if (!src.getPixels()) { | |
| 156 return false; | |
| 157 } | |
| 158 | |
| 159 if (!dst->tryAllocPixels(src.info().makeWH(bounds.width(), bounds.height()))
) { | |
| 160 return false; | |
| 161 } | |
| 162 | |
| 163 SkVector radius = SkVector::Make(SkIntToScalar(this->radius().width()), | 172 SkVector radius = SkVector::Make(SkIntToScalar(this->radius().width()), |
| 164 SkIntToScalar(this->radius().height())); | 173 SkIntToScalar(this->radius().height())); |
| 165 ctx.ctm().mapVectors(&radius, 1); | 174 ctx.ctm().mapVectors(&radius, 1); |
| 166 int width = SkScalarFloorToInt(radius.fX); | 175 int width = SkScalarFloorToInt(radius.fX); |
| 167 int height = SkScalarFloorToInt(radius.fY); | 176 int height = SkScalarFloorToInt(radius.fY); |
| 168 | 177 |
| 169 if (width < 0 || height < 0) { | 178 if (width < 0 || height < 0) { |
| 170 return false; | 179 return false; |
| 171 } | 180 } |
| 172 | 181 |
| 173 SkIRect srcBounds = bounds; | 182 SkIRect srcBounds = bounds; |
| 174 srcBounds.offset(-srcOffset); | 183 srcBounds.offset(-srcOffset); |
| 175 | 184 |
| 176 if (width == 0 && height == 0) { | 185 if (width == 0 && height == 0) { |
| 177 src.extractSubset(dst, srcBounds); | 186 srcBitmap.extractSubset(&dstBitmap, srcBounds); |
| 187 SkImage* image = SkNewImageFromBitmap(dstBitmap, true, NULL); |
| 188 if (NULL == image) { |
| 189 return false; |
| 190 } |
| 191 dst.reset(image); |
| 178 offset->fX = bounds.left(); | 192 offset->fX = bounds.left(); |
| 179 offset->fY = bounds.top(); | 193 offset->fY = bounds.top(); |
| 180 return true; | 194 return true; |
| 181 } | 195 } |
| 182 | 196 |
| 183 SkBitmap temp; | 197 SkBitmap temp; |
| 184 if (!temp.tryAllocPixels(dst->info())) { | 198 if (!temp.tryAllocPixels(dstBitmap.info())) { |
| 185 return false; | 199 return false; |
| 186 } | 200 } |
| 187 | 201 |
| 188 if (width > 0 && height > 0) { | 202 if (width > 0 && height > 0) { |
| 189 callProcX(procX, src, &temp, width, srcBounds); | 203 callProcX(procX, srcBitmap, &temp, width, srcBounds); |
| 190 SkIRect tmpBounds = SkIRect::MakeWH(srcBounds.width(), srcBounds.height(
)); | 204 SkIRect tmpBounds = SkIRect::MakeWH(srcBounds.width(), srcBounds.height(
)); |
| 191 callProcY(procY, temp, dst, height, tmpBounds); | 205 callProcY(procY, temp, &dstBitmap, height, tmpBounds); |
| 192 } else if (width > 0) { | 206 } else if (width > 0) { |
| 193 callProcX(procX, src, dst, width, srcBounds); | 207 callProcX(procX, srcBitmap, &dstBitmap, width, srcBounds); |
| 194 } else if (height > 0) { | 208 } else if (height > 0) { |
| 195 callProcY(procY, src, dst, height, srcBounds); | 209 callProcY(procY, srcBitmap, &dstBitmap, height, srcBounds); |
| 196 } | 210 } |
| 211 |
| 212 srcBitmap = SkBitmap(); |
| 213 temp = SkBitmap(); |
| 214 |
| 215 SkImage* image = SkNewImageFromBitmap(dstBitmap, true, NULL); |
| 216 if (NULL == image) { |
| 217 return false; |
| 218 } |
| 219 dst.reset(image); |
| 197 offset->fX = bounds.left(); | 220 offset->fX = bounds.left(); |
| 198 offset->fY = bounds.top(); | 221 offset->fY = bounds.top(); |
| 199 return true; | 222 return true; |
| 200 } | 223 } |
| 201 | 224 |
| 202 bool SkErodeImageFilter::onFilterImage(Proxy* proxy, | 225 bool SkErodeImageFilter::onFilterImage(Proxy* proxy, |
| 203 const SkBitmap& source, const Context& ct
x, | 226 SkImage& source, const Context& ctx, |
| 204 SkBitmap* dst, SkIPoint* offset) const { | 227 SkAutoTUnref<SkImage>& dst, SkIPoint* off
set) const { |
| 205 Proc erodeXProc = SkMorphologyGetPlatformProc(kErodeX_SkMorphologyProcType); | 228 Proc erodeXProc = SkMorphologyGetPlatformProc(kErodeX_SkMorphologyProcType); |
| 206 if (!erodeXProc) { | 229 if (!erodeXProc) { |
| 207 erodeXProc = erode<kX>; | 230 erodeXProc = erode<kX>; |
| 208 } | 231 } |
| 209 Proc erodeYProc = SkMorphologyGetPlatformProc(kErodeY_SkMorphologyProcType); | 232 Proc erodeYProc = SkMorphologyGetPlatformProc(kErodeY_SkMorphologyProcType); |
| 210 if (!erodeYProc) { | 233 if (!erodeYProc) { |
| 211 erodeYProc = erode<kY>; | 234 erodeYProc = erode<kY>; |
| 212 } | 235 } |
| 213 return this->filterImageGeneric(erodeXProc, erodeYProc, proxy, source, ctx,
dst, offset); | 236 return this->filterImageGeneric(erodeXProc, erodeYProc, proxy, source, ctx,
dst, offset); |
| 214 } | 237 } |
| 215 | 238 |
| 216 bool SkDilateImageFilter::onFilterImage(Proxy* proxy, | 239 bool SkDilateImageFilter::onFilterImage(Proxy* proxy, |
| 217 const SkBitmap& source, const Context& c
tx, | 240 SkImage& source, const Context& ctx, |
| 218 SkBitmap* dst, SkIPoint* offset) const { | 241 SkAutoTUnref<SkImage>& dst, SkIPoint* of
fset) const { |
| 219 Proc dilateXProc = SkMorphologyGetPlatformProc(kDilateX_SkMorphologyProcType
); | 242 Proc dilateXProc = SkMorphologyGetPlatformProc(kDilateX_SkMorphologyProcType
); |
| 220 if (!dilateXProc) { | 243 if (!dilateXProc) { |
| 221 dilateXProc = dilate<kX>; | 244 dilateXProc = dilate<kX>; |
| 222 } | 245 } |
| 223 Proc dilateYProc = SkMorphologyGetPlatformProc(kDilateY_SkMorphologyProcType
); | 246 Proc dilateYProc = SkMorphologyGetPlatformProc(kDilateY_SkMorphologyProcType
); |
| 224 if (!dilateYProc) { | 247 if (!dilateYProc) { |
| 225 dilateYProc = dilate<kY>; | 248 dilateYProc = dilate<kY>; |
| 226 } | 249 } |
| 227 return this->filterImageGeneric(dilateXProc, dilateYProc, proxy, source, ctx
, dst, offset); | 250 return this->filterImageGeneric(dilateXProc, dilateYProc, proxy, source, ctx
, dst, offset); |
| 228 } | 251 } |
| (...skipping 404 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 633 // Draw upper and lower margins with bounds; middle without. | 656 // Draw upper and lower margins with bounds; middle without. |
| 634 apply_morphology_rect(context, texture, lowerSrcRect, lowerDstRect, radi
us, | 657 apply_morphology_rect(context, texture, lowerSrcRect, lowerDstRect, radi
us, |
| 635 morphType, bounds, direction); | 658 morphType, bounds, direction); |
| 636 apply_morphology_rect(context, texture, upperSrcRect, upperDstRect, radi
us, | 659 apply_morphology_rect(context, texture, upperSrcRect, upperDstRect, radi
us, |
| 637 morphType, bounds, direction); | 660 morphType, bounds, direction); |
| 638 apply_morphology_rect_no_bounds(context, texture, middleSrcRect, middleD
stRect, radius, | 661 apply_morphology_rect_no_bounds(context, texture, middleSrcRect, middleD
stRect, radius, |
| 639 morphType, direction); | 662 morphType, direction); |
| 640 } | 663 } |
| 641 } | 664 } |
| 642 | 665 |
| 643 bool apply_morphology(const SkBitmap& input, | 666 bool apply_morphology(SkImage& input, |
| 644 const SkIRect& rect, | 667 const SkIRect& rect, |
| 645 GrMorphologyEffect::MorphologyType morphType, | 668 GrMorphologyEffect::MorphologyType morphType, |
| 646 SkISize radius, | 669 SkISize radius, |
| 647 SkBitmap* dst) { | 670 SkAutoTUnref<SkImage>& dst) { |
| 648 SkAutoTUnref<GrTexture> srcTexture(SkRef(input.getTexture())); | 671 SkAutoTUnref<GrTexture> srcTexture(SkRef(input.getTexture())); |
| 649 SkASSERT(srcTexture); | 672 SkASSERT(srcTexture); |
| 650 GrContext* context = srcTexture->getContext(); | 673 GrContext* context = srcTexture->getContext(); |
| 651 | 674 |
| 652 GrContext::AutoClip acs(context, SkRect::MakeWH(SkIntToScalar(srcTexture->wi
dth()), | 675 GrContext::AutoClip acs(context, SkRect::MakeWH(SkIntToScalar(srcTexture->wi
dth()), |
| 653 SkIntToScalar(srcTexture->he
ight()))); | 676 SkIntToScalar(srcTexture->he
ight()))); |
| 654 | 677 |
| 655 SkIRect dstRect = SkIRect::MakeWH(rect.width(), rect.height()); | 678 SkIRect dstRect = SkIRect::MakeWH(rect.width(), rect.height()); |
| 656 GrSurfaceDesc desc; | 679 GrSurfaceDesc desc; |
| 657 desc.fFlags = kRenderTarget_GrSurfaceFlag | kNoStencil_GrSurfaceFlag; | 680 desc.fFlags = kRenderTarget_GrSurfaceFlag | kNoStencil_GrSurfaceFlag; |
| (...skipping 22 matching lines...) Expand all Loading... |
| 680 if (radius.fHeight > 0) { | 703 if (radius.fHeight > 0) { |
| 681 GrTexture* texture = context->refScratchTexture(desc, GrContext::kApprox
_ScratchTexMatch); | 704 GrTexture* texture = context->refScratchTexture(desc, GrContext::kApprox
_ScratchTexMatch); |
| 682 if (NULL == texture) { | 705 if (NULL == texture) { |
| 683 return false; | 706 return false; |
| 684 } | 707 } |
| 685 GrContext::AutoRenderTarget art(context, texture->asRenderTarget()); | 708 GrContext::AutoRenderTarget art(context, texture->asRenderTarget()); |
| 686 apply_morphology_pass(context, srcTexture, srcRect, dstRect, radius.fHei
ght, | 709 apply_morphology_pass(context, srcTexture, srcRect, dstRect, radius.fHei
ght, |
| 687 morphType, Gr1DKernelEffect::kY_Direction); | 710 morphType, Gr1DKernelEffect::kY_Direction); |
| 688 srcTexture.reset(texture); | 711 srcTexture.reset(texture); |
| 689 } | 712 } |
| 690 SkImageFilter::WrapTexture(srcTexture, rect.width(), rect.height(), dst); | 713 if (!SkImageFilter::WrapTexture(srcTexture, rect.width(), rect.height(), dst
)) { |
| 714 return false; |
| 715 } |
| 691 return true; | 716 return true; |
| 692 } | 717 } |
| 693 | 718 |
| 694 }; | 719 }; |
| 695 | 720 |
| 696 bool SkMorphologyImageFilter::filterImageGPUGeneric(bool dilate, | 721 bool SkMorphologyImageFilter::filterImageGPUGeneric(bool dilate, |
| 697 Proxy* proxy, | 722 Proxy* proxy, |
| 698 const SkBitmap& src, | 723 SkImage& src, |
| 699 const Context& ctx, | 724 const Context& ctx, |
| 700 SkBitmap* result, | 725 SkAutoTUnref<SkImage>& resul
t, |
| 701 SkIPoint* offset) const { | 726 SkIPoint* offset) const { |
| 702 SkBitmap input = src; | 727 SkAutoTUnref<SkImage> input(SkRef(&src)); |
| 703 SkIPoint srcOffset = SkIPoint::Make(0, 0); | 728 SkIPoint srcOffset = SkIPoint::Make(0, 0); |
| 704 if (getInput(0) && !getInput(0)->getInputResultGPU(proxy, src, ctx, &input,
&srcOffset)) { | 729 if (getInput(0) && !getInput(0)->getInputResultGPU(proxy, src, ctx, input, &
srcOffset)) { |
| 705 return false; | 730 return false; |
| 706 } | 731 } |
| 707 SkIRect bounds; | 732 SkIRect bounds; |
| 708 if (!this->applyCropRect(ctx, proxy, input, &srcOffset, &bounds, &input)) { | 733 if (!this->applyCropRect(ctx, proxy, *input, &srcOffset, &bounds, input)) { |
| 709 return false; | 734 return false; |
| 710 } | 735 } |
| 711 SkVector radius = SkVector::Make(SkIntToScalar(this->radius().width()), | 736 SkVector radius = SkVector::Make(SkIntToScalar(this->radius().width()), |
| 712 SkIntToScalar(this->radius().height())); | 737 SkIntToScalar(this->radius().height())); |
| 713 ctx.ctm().mapVectors(&radius, 1); | 738 ctx.ctm().mapVectors(&radius, 1); |
| 714 int width = SkScalarFloorToInt(radius.fX); | 739 int width = SkScalarFloorToInt(radius.fX); |
| 715 int height = SkScalarFloorToInt(radius.fY); | 740 int height = SkScalarFloorToInt(radius.fY); |
| 716 | 741 |
| 717 if (width < 0 || height < 0) { | 742 if (width < 0 || height < 0) { |
| 718 return false; | 743 return false; |
| 719 } | 744 } |
| 720 | 745 |
| 721 SkIRect srcBounds = bounds; | 746 SkIRect srcBounds = bounds; |
| 722 srcBounds.offset(-srcOffset); | 747 srcBounds.offset(-srcOffset); |
| 723 if (width == 0 && height == 0) { | 748 if (width == 0 && height == 0) { |
| 724 input.extractSubset(result, srcBounds); | 749 SkImage* image = input->newImage(srcBounds.width(), srcBounds.height(),
&srcBounds); |
| 750 if (NULL == image) { |
| 751 return false; |
| 752 } |
| 753 result.reset(image); |
| 725 offset->fX = bounds.left(); | 754 offset->fX = bounds.left(); |
| 726 offset->fY = bounds.top(); | 755 offset->fY = bounds.top(); |
| 727 return true; | 756 return true; |
| 728 } | 757 } |
| 729 | 758 |
| 730 GrMorphologyEffect::MorphologyType type = dilate ? GrMorphologyEffect::kDila
te_MorphologyType : GrMorphologyEffect::kErode_MorphologyType; | 759 GrMorphologyEffect::MorphologyType type = dilate ? GrMorphologyEffect::kDila
te_MorphologyType : GrMorphologyEffect::kErode_MorphologyType; |
| 731 if (!apply_morphology(input, srcBounds, type, | 760 if (!apply_morphology(*input, srcBounds, type, |
| 732 SkISize::Make(width, height), result)) { | 761 SkISize::Make(width, height), result)) { |
| 733 return false; | 762 return false; |
| 734 } | 763 } |
| 735 offset->fX = bounds.left(); | 764 offset->fX = bounds.left(); |
| 736 offset->fY = bounds.top(); | 765 offset->fY = bounds.top(); |
| 737 return true; | 766 return true; |
| 738 } | 767 } |
| 739 | 768 |
| 740 bool SkDilateImageFilter::filterImageGPU(Proxy* proxy, const SkBitmap& src, cons
t Context& ctx, | 769 bool SkDilateImageFilter::filterImageGPU(Proxy* proxy, SkImage& src, const Conte
xt& ctx, |
| 741 SkBitmap* result, SkIPoint* offset) con
st { | 770 SkAutoTUnref<SkImage>& result, SkIPoint
* offset) const { |
| 742 return this->filterImageGPUGeneric(true, proxy, src, ctx, result, offset); | 771 return this->filterImageGPUGeneric(true, proxy, src, ctx, result, offset); |
| 743 } | 772 } |
| 744 | 773 |
| 745 bool SkErodeImageFilter::filterImageGPU(Proxy* proxy, const SkBitmap& src, const
Context& ctx, | 774 bool SkErodeImageFilter::filterImageGPU(Proxy* proxy, SkImage& src, const Contex
t& ctx, |
| 746 SkBitmap* result, SkIPoint* offset) cons
t { | 775 SkAutoTUnref<SkImage>& result, SkIPoint*
offset) const { |
| 747 return this->filterImageGPUGeneric(false, proxy, src, ctx, result, offset); | 776 return this->filterImageGPUGeneric(false, proxy, src, ctx, result, offset); |
| 748 } | 777 } |
| 749 | 778 |
| 750 #endif | 779 #endif |
| OLD | NEW |