Hide legacy imagefilters::image using filter-quality
Small diffs in a GM -- due to the dual nature of kMedium (cpu and gpu)
Another reason to stop using it, and switch to the more-explicit
sampling.
Bug: skia:7650
Change-Id: Ie7575071b19778626da7f94804abaaa11861a050
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/370259
Reviewed-by: Mike Reed <reed@google.com>
Commit-Queue: Mike Reed <reed@google.com>
diff --git a/fuzz/FuzzCanvas.cpp b/fuzz/FuzzCanvas.cpp
index cd258de..271c240 100644
--- a/fuzz/FuzzCanvas.cpp
+++ b/fuzz/FuzzCanvas.cpp
@@ -630,7 +630,8 @@
SkFilterQuality filterQuality;
fuzz->next(&srcRect, &dstRect);
fuzz->nextEnum(&filterQuality, SkFilterQuality::kLast_SkFilterQuality);
- return SkImageFilters::Image(std::move(image), srcRect, dstRect, filterQuality);
+ return SkImageFilters::Image(std::move(image), srcRect, dstRect,
+ SkSamplingOptions(filterQuality));
}
case 11:
return make_fuzz_lighting_imagefilter(fuzz, depth - 1);
diff --git a/gm/imagesource.cpp b/gm/imagesource.cpp
index b7d0583..84de781 100644
--- a/gm/imagesource.cpp
+++ b/gm/imagesource.cpp
@@ -58,6 +58,7 @@
const SkRect dstRect = SkRect::MakeXYWH(0, 10, 60, 60);
const SkRect clipRect = SkRect::MakeXYWH(0, 0, 100, 100);
const SkRect bounds = SkRect::MakeIWH(fImage->width(), fImage->height());
+ const SkSamplingOptions sampling({1/3.0f, 1/3.0f});
{
// Draw an unscaled bitmap.
@@ -68,21 +69,21 @@
{
// Draw an unscaled subset of the source bitmap (srcRect -> srcRect).
sk_sp<SkImageFilter> imageSourceSrcRect(
- SkImageFilters::Image(fImage, srcRect, srcRect, kHigh_SkFilterQuality));
+ SkImageFilters::Image(fImage, srcRect, srcRect, sampling));
fill_rect_filtered(canvas, clipRect, std::move(imageSourceSrcRect));
canvas->translate(SkIntToScalar(100), 0);
}
{
// Draw a subset of the bitmap scaled to a destination rect (srcRect -> dstRect).
sk_sp<SkImageFilter> imageSourceSrcRectDstRect(
- SkImageFilters::Image(fImage, srcRect, dstRect, kHigh_SkFilterQuality));
+ SkImageFilters::Image(fImage, srcRect, dstRect, sampling));
fill_rect_filtered(canvas, clipRect, std::move(imageSourceSrcRectDstRect));
canvas->translate(SkIntToScalar(100), 0);
}
{
// Draw the entire bitmap scaled to a destination rect (bounds -> dstRect).
sk_sp<SkImageFilter> imageSourceDstRectOnly(
- SkImageFilters::Image(fImage, bounds, dstRect, kHigh_SkFilterQuality));
+ SkImageFilters::Image(fImage, bounds, dstRect, sampling));
fill_rect_filtered(canvas, clipRect, std::move(imageSourceDstRectOnly));
canvas->translate(SkIntToScalar(100), 0);
}
diff --git a/gm/imagesource2.cpp b/gm/imagesource2.cpp
index 005a626..8825c1b 100644
--- a/gm/imagesource2.cpp
+++ b/gm/imagesource2.cpp
@@ -27,7 +27,8 @@
// is shifted for high quality mode between cpu and gpu.
class ImageSourceGM : public GM {
public:
- ImageSourceGM(const char* suffix, SkFilterQuality filter) : fSuffix(suffix), fFilter(filter) {
+ ImageSourceGM(const char* suffix, const SkSamplingOptions& sampling)
+ : fSuffix(suffix), fSampling(sampling) {
this->setBGColor(0xFFFFFFFF);
}
@@ -77,7 +78,7 @@
const SkRect dstRect = SkRect::MakeLTRB(0.75f, 0.75f, 225.75f, 225.75f);
SkPaint p;
- p.setImageFilter(SkImageFilters::Image(fImage, srcRect, dstRect, fFilter));
+ p.setImageFilter(SkImageFilters::Image(fImage, srcRect, dstRect, fSampling));
canvas->saveLayer(nullptr, &p);
canvas->restore();
@@ -86,17 +87,18 @@
private:
static constexpr int kImageSize = 503;
- SkString fSuffix;
- SkFilterQuality fFilter;
- sk_sp<SkImage> fImage;
+ SkString fSuffix;
+ SkSamplingOptions fSampling;
+ sk_sp<SkImage> fImage;
using INHERITED = GM;
};
//////////////////////////////////////////////////////////////////////////////
-DEF_GM(return new ImageSourceGM("none", kNone_SkFilterQuality);)
-DEF_GM(return new ImageSourceGM("low", kLow_SkFilterQuality);)
-DEF_GM(return new ImageSourceGM("med", kMedium_SkFilterQuality);)
-DEF_GM(return new ImageSourceGM("high", kHigh_SkFilterQuality);)
+DEF_GM(return new ImageSourceGM("none", SkSamplingOptions());)
+DEF_GM(return new ImageSourceGM("low", SkSamplingOptions(SkFilterMode::kLinear));)
+DEF_GM(return new ImageSourceGM("med", SkSamplingOptions(SkFilterMode::kLinear,
+ SkMipmapMode::kLinear));)
+DEF_GM(return new ImageSourceGM("high", SkSamplingOptions({1/3.0f, 1/3.0f}));)
} // namespace skiagm
diff --git a/gm/pictureimagefilter.cpp b/gm/pictureimagefilter.cpp
index df0a330..b9eb287 100644
--- a/gm/pictureimagefilter.cpp
+++ b/gm/pictureimagefilter.cpp
@@ -78,14 +78,14 @@
fLCDPicture = make_LCD_picture();
}
- sk_sp<SkImageFilter> make(sk_sp<SkPicture> pic, SkRect r, SkFilterQuality fq) {
+ sk_sp<SkImageFilter> make(sk_sp<SkPicture> pic, SkRect r, const SkSamplingOptions& sampling) {
SkISize dim = { SkScalarRoundToInt(r.width()), SkScalarRoundToInt(r.height()) };
auto img = SkImage::MakeFromPicture(pic, dim, nullptr, nullptr,
SkImage::BitDepth::kU8, SkColorSpace::MakeSRGB());
- return SkImageFilters::Image(img, r, r, fq);
+ return SkImageFilters::Image(img, r, r, sampling);
}
- sk_sp<SkImageFilter> make(SkFilterQuality fq) {
- return make(fPicture, fPicture->cullRect(), fq);
+ sk_sp<SkImageFilter> make(const SkSamplingOptions& sampling) {
+ return make(fPicture, fPicture->cullRect(), sampling);
}
void onDraw(SkCanvas* canvas) override {
@@ -98,8 +98,8 @@
sk_sp<SkImageFilter> pictureSourceSrcRect(SkImageFilters::Picture(fPicture, srcRect));
sk_sp<SkImageFilter> pictureSourceEmptyRect(SkImageFilters::Picture(fPicture,
emptyRect));
- sk_sp<SkImageFilter> pictureSourceResampled = make(kLow_SkFilterQuality);
- sk_sp<SkImageFilter> pictureSourcePixelated = make(kNone_SkFilterQuality);
+ sk_sp<SkImageFilter> pictureSourceResampled = make(SkSamplingOptions(SkFilterMode::kLinear));
+ sk_sp<SkImageFilter> pictureSourcePixelated = make(SkSamplingOptions());
canvas->save();
// Draw the picture unscaled.
@@ -122,7 +122,7 @@
canvas->drawRect(bounds, stroke);
SkPaint paint;
- paint.setImageFilter(make(fLCDPicture, fPicture->cullRect(), kNone_SkFilterQuality));
+ paint.setImageFilter(make(fLCDPicture, fPicture->cullRect(), SkSamplingOptions()));
canvas->scale(4, 4);
canvas->translate(-0.9f*srcRect.fLeft, -2.45f*srcRect.fTop);
diff --git a/gm/resizeimagefilter.cpp b/gm/resizeimagefilter.cpp
index c9b1a89..3518bc9 100644
--- a/gm/resizeimagefilter.cpp
+++ b/gm/resizeimagefilter.cpp
@@ -108,7 +108,8 @@
SkRect inRect = SkRect::MakeXYWH(-4, -4, 20, 20);
SkRect outRect = SkRect::MakeXYWH(-24, -24, 120, 120);
sk_sp<SkImageFilter> source(
- SkImageFilters::Image(std::move(image), inRect, outRect, kHigh_SkFilterQuality));
+ SkImageFilters::Image(std::move(image), inRect, outRect,
+ SkSamplingOptions({1/3.0f, 1/3.0f})));
canvas->translate(srcRect.width() + SkIntToScalar(10), 0);
this->draw(canvas, srcRect, deviceSize, samplings[3], std::move(source));
}
diff --git a/include/effects/SkImageFilters.h b/include/effects/SkImageFilters.h
index c7e3a4f..4175051 100644
--- a/include/effects/SkImageFilters.h
+++ b/include/effects/SkImageFilters.h
@@ -19,6 +19,10 @@
#include <cstddef>
+#ifndef SK_SUPPORT_LEGACY_IMAGEFILTER_IMAGE
+#define SK_SUPPORT_LEGACY_IMAGEFILTER_IMAGE
+#endif
+
class SkColorFilter;
class SkPaint;
class SkRegion;
@@ -185,25 +189,38 @@
/**
* Create a filter that draws the 'srcRect' portion of image into 'dstRect' using the given
* filter quality. Similar to SkCanvas::drawImageRect. Returns null if 'image' is null.
- * @param image The image that is output by the filter, subset by 'srcRect'.
- * @param srcRect The source pixels sampled into 'dstRect'
- * @param dstRect The local rectangle to draw the image into.
- * @param filterQuality The filter quality that is used when sampling the image.
+ * @param image The image that is output by the filter, subset by 'srcRect'.
+ * @param srcRect The source pixels sampled into 'dstRect'
+ * @param dstRect The local rectangle to draw the image into.
+ * @param sampling The sampling to use when drawing the image.
*/
static sk_sp<SkImageFilter> Image(sk_sp<SkImage> image, const SkRect& srcRect,
- const SkRect& dstRect, SkFilterQuality filterQuality);
+ const SkRect& dstRect, const SkSamplingOptions& sampling);
+
/**
- * Create a filter that produces the image contents.
- * @param image The image that is output by the filter.
+ * Create a filter that draws the image using the given sampling.
+ * Similar to SkCanvas::drawImage. Returns null if 'image' is null.
+ * @param image The image that is output by the filter.
+ * @param sampling The sampling to use when drawing the image.
+ */
+ static sk_sp<SkImageFilter> Image(sk_sp<SkImage> image, const SkSamplingOptions& sampling);
+
+ /**
+ * Create a filter that draws the image using Mitchel cubic resampling.
+ * @param image The image that is output by the filter.
*/
static sk_sp<SkImageFilter> Image(sk_sp<SkImage> image) {
- // Defaults to kHigh_SkFilterQuality because the dstRect of the image filter will be mapped
- // by the layer matrix set during filtering. If that has a scale factor, then the image
- // will not be drawn at a 1-to-1 pixel scale, even that is what this appears to create here.
- SkRect r = image ? SkRect::MakeWH(image->width(), image->height()) : SkRect::MakeEmpty();
- return Image(std::move(image), r, r, kHigh_SkFilterQuality);
+ return Image(std::move(image), SkSamplingOptions({1/3.0f, 1/3.0f}));
}
+#ifdef SK_SUPPORT_LEGACY_IMAGEFILTER_IMAGE
+ static sk_sp<SkImageFilter> Image(sk_sp<SkImage> image, const SkRect& srcRect,
+ const SkRect& dstRect, SkFilterQuality filterQuality) {
+ SkSamplingOptions sampling(filterQuality, SkSamplingOptions::kMedium_asMipmapLinear);
+ return Image(std::move(image), srcRect, dstRect, sampling);
+ }
+#endif
+
/**
* Create a filter that mimics a zoom/magnifying lens effect.
* @param srcRect
diff --git a/src/core/SkPicturePriv.h b/src/core/SkPicturePriv.h
index 4484727..82ca186 100644
--- a/src/core/SkPicturePriv.h
+++ b/src/core/SkPicturePriv.h
@@ -95,10 +95,11 @@
kSamplingInDrawImage_Version = 81,
kPictureShaderFilterParam_Version = 82,
kMatrixImageFilterSampling_Version = 83,
+ kImageFilterImageSampling_Version = 84,
// Only SKPs within the min/current picture version range (inclusive) can be read.
kMin_Version = kEdgeAAQuadColor4f_Version,
- kCurrent_Version = kMatrixImageFilterSampling_Version
+ kCurrent_Version = kImageFilterImageSampling_Version
};
static_assert(SkPicturePriv::kMin_Version <= SkPicturePriv::kCubicResamplerImageShader_Version,
diff --git a/src/effects/imagefilters/SkImageFilters.cpp b/src/effects/imagefilters/SkImageFilters.cpp
index c216acd..7c31403 100644
--- a/src/effects/imagefilters/SkImageFilters.cpp
+++ b/src/effects/imagefilters/SkImageFilters.cpp
@@ -87,8 +87,17 @@
sk_sp<SkImageFilter> SkImageFilters::Image(
sk_sp<SkImage> image, const SkRect& srcRect, const SkRect& dstRect,
- SkFilterQuality filterQuality) {
- return SkImageSource::Make(std::move(image), srcRect, dstRect, filterQuality);
+ const SkSamplingOptions& sampling) {
+ return SkImageSource::Make(std::move(image), srcRect, dstRect, sampling);
+}
+
+sk_sp<SkImageFilter> SkImageFilters::Image(sk_sp<SkImage> image,
+ const SkSamplingOptions& sampling) {
+ if (image) {
+ auto r = SkRect::MakeIWH(image->width(), image->height());
+ return Image(std::move(image), r, r, sampling);
+ }
+ return nullptr;
}
sk_sp<SkImageFilter> SkImageFilters::Magnifier(
diff --git a/src/effects/imagefilters/SkImageSource.cpp b/src/effects/imagefilters/SkImageSource.cpp
index e0438bf..d5eeef2 100644
--- a/src/effects/imagefilters/SkImageSource.cpp
+++ b/src/effects/imagefilters/SkImageSource.cpp
@@ -12,6 +12,7 @@
#include "include/core/SkString.h"
#include "src/core/SkImageFilter_Base.h"
#include "src/core/SkReadBuffer.h"
+#include "src/core/SkSamplingPriv.h"
#include "src/core/SkSpecialImage.h"
#include "src/core/SkSpecialSurface.h"
#include "src/core/SkWriteBuffer.h"
@@ -21,12 +22,12 @@
class SkImageSourceImpl final : public SkImageFilter_Base {
public:
SkImageSourceImpl(sk_sp<SkImage> image, const SkRect& srcRect, const SkRect& dstRect,
- SkFilterQuality filterQuality)
+ const SkSamplingOptions& sampling)
: INHERITED(nullptr, 0, nullptr)
, fImage(std::move(image))
, fSrcRect(srcRect)
, fDstRect(dstRect)
- , fFilterQuality(filterQuality) {}
+ , fSampling(sampling) {}
SkRect computeFastBounds(const SkRect& src) const override;
@@ -42,30 +43,25 @@
friend void SkImageSource::RegisterFlattenables();
SK_FLATTENABLE_HOOKS(SkImageSourceImpl)
- sk_sp<SkImage> fImage;
- SkRect fSrcRect, fDstRect;
- SkFilterQuality fFilterQuality;
+ sk_sp<SkImage> fImage;
+ SkRect fSrcRect, fDstRect;
+ SkSamplingOptions fSampling;
using INHERITED = SkImageFilter_Base;
};
} // end namespace
-sk_sp<SkImageFilter> SkImageSource::Make(sk_sp<SkImage> image) {
- SkRect rect = image ? SkRect::MakeIWH(image->width(), image->height()) : SkRect::MakeEmpty();
- return SkImageSource::Make(std::move(image), rect, rect, kHigh_SkFilterQuality);
-}
-
sk_sp<SkImageFilter> SkImageSource::Make(sk_sp<SkImage> image,
const SkRect& srcRect,
const SkRect& dstRect,
- SkFilterQuality filterQuality) {
+ const SkSamplingOptions& sampling) {
if (!image || srcRect.width() <= 0.0f || srcRect.height() <= 0.0f) {
return nullptr;
}
return sk_sp<SkImageFilter>(new SkImageSourceImpl(
- std::move(image), srcRect, dstRect, filterQuality));
+ std::move(image), srcRect, dstRect, sampling));
}
void SkImageSource::RegisterFlattenables() {
@@ -77,7 +73,13 @@
///////////////////////////////////////////////////////////////////////////////////////////////////
sk_sp<SkFlattenable> SkImageSourceImpl::CreateProc(SkReadBuffer& buffer) {
- SkFilterQuality filterQuality = buffer.checkFilterQuality();
+ SkSamplingOptions sampling;
+ if (buffer.isVersionLT(SkPicturePriv::kImageFilterImageSampling_Version)) {
+ sampling = SkSamplingOptions(buffer.checkFilterQuality(),
+ SkSamplingOptions::kMedium_asMipmapLinear);
+ } else {
+ sampling = buffer.readSampling();
+ }
SkRect src, dst;
buffer.readRect(&src);
@@ -88,11 +90,11 @@
return nullptr;
}
- return SkImageSource::Make(std::move(image), src, dst, filterQuality);
+ return SkImageSource::Make(std::move(image), src, dst, sampling);
}
void SkImageSourceImpl::flatten(SkWriteBuffer& buffer) const {
- buffer.writeInt(fFilterQuality);
+ SkSamplingPriv::Write(buffer, fSampling);
buffer.writeRect(fSrcRect);
buffer.writeRect(fDstRect);
buffer.writeImage(fImage.get());
@@ -140,12 +142,9 @@
dstRect.offset(-SkIntToScalar(dstIRect.fLeft), -SkIntToScalar(dstIRect.fTop));
paint.setBlendMode(SkBlendMode::kSrc);
- // TODO: take sampling explicitly, rather than filter-quality
- SkSamplingOptions sampling(fFilterQuality, canvas->recordingContext() ?
- SkSamplingOptions::kMedium_asMipmapLinear :
- SkSamplingOptions::kMedium_asMipmapNearest);
// FIXME: this probably shouldn't be necessary, but drawImageRect asserts
- // None filtering when it's translate-only
+ SkSamplingOptions sampling = fSampling;
+ // None filtering when it's translate-only (even for cubicresampling? <reed>)
if (fSrcRect.width() == dstRect.width() && fSrcRect.height() == dstRect.height()) {
sampling = SkSamplingOptions();
}
diff --git a/src/effects/imagefilters/SkImageSource.h b/src/effects/imagefilters/SkImageSource.h
index 1572df7..c2f2d03 100644
--- a/src/effects/imagefilters/SkImageSource.h
+++ b/src/effects/imagefilters/SkImageSource.h
@@ -11,14 +11,12 @@
#include "include/core/SkImage.h"
#include "include/core/SkImageFilter.h"
-// DEPRECATED: Use include/effects/SkImageFilters::Image
-class SK_API SkImageSource {
+class SkImageSource {
public:
- static sk_sp<SkImageFilter> Make(sk_sp<SkImage> image);
static sk_sp<SkImageFilter> Make(sk_sp<SkImage> image,
const SkRect& srcRect,
const SkRect& dstRect,
- SkFilterQuality filterQuality);
+ const SkSamplingOptions& sampling);
static void RegisterFlattenables();
diff --git a/tests/ImageFilterTest.cpp b/tests/ImageFilterTest.cpp
index ea16907..9a1d46b 100644
--- a/tests/ImageFilterTest.cpp
+++ b/tests/ImageFilterTest.cpp
@@ -1981,7 +1981,9 @@
// Specified src and dst rects.
SkRect src(SkRect::MakeXYWH(0.5, 0.5, 100.5, 100.5));
SkRect dst(SkRect::MakeXYWH(-10.5, -10.5, 120.5, 120.5));
- sk_sp<SkImageFilter> source2(SkImageFilters::Image(image, src, dst, kMedium_SkFilterQuality));
+ sk_sp<SkImageFilter> source2(SkImageFilters::Image(image, src, dst,
+ SkSamplingOptions(SkFilterMode::kLinear,
+ SkMipmapMode::kLinear)));
REPORTER_ASSERT(reporter,
dst.roundOut() == source2->filterBounds(input, SkMatrix::I(),
SkImageFilter::kForward_MapDirection,
diff --git a/tests/Skbug6389.cpp b/tests/Skbug6389.cpp
index 0b93cfb..1aa20ab 100644
--- a/tests/Skbug6389.cpp
+++ b/tests/Skbug6389.cpp
@@ -17,6 +17,6 @@
SkPaint p;
p.setMaskFilter(SkMaskFilter::MakeBlur(SkBlurStyle::kNormal_SkBlurStyle, 5));
p.setImageFilter(SkImageFilters::Image(GetResourceAsImage("images/mandrill_512.png"),
- {0, 0, 0, 0}, {0, 0, 0, 0}, kNone_SkFilterQuality));
+ {0, 0, 0, 0}, {0, 0, 0, 0}, SkSamplingOptions()));
s->getCanvas()->drawPaint(p);
}