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