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 |