Index: gm/image.cpp |
diff --git a/gm/image.cpp b/gm/image.cpp |
index 991b4014f02aa3bfff0a2a3126a29f5210a21591..ac72f63b36f96dc2ab271778578d9e31a588b35e 100644 |
--- a/gm/image.cpp |
+++ b/gm/image.cpp |
@@ -240,33 +240,33 @@ static void draw_contents(SkCanvas* canvas) { |
canvas->drawCircle(50, 50, 35, paint); |
} |
-static SkImage* make_raster(const SkImageInfo& info, GrContext*) { |
+static SkImage* make_raster(const SkImageInfo& info, GrContext*, void (*draw)(SkCanvas*)) { |
SkAutoTUnref<SkSurface> surface(SkSurface::NewRaster(info)); |
- draw_contents(surface->getCanvas()); |
+ draw(surface->getCanvas()); |
return surface->newImageSnapshot(); |
} |
-static SkImage* make_picture(const SkImageInfo& info, GrContext*) { |
+static SkImage* make_picture(const SkImageInfo& info, GrContext*, void (*draw)(SkCanvas*)) { |
SkPictureRecorder recorder; |
- draw_contents(recorder.beginRecording(SkRect::MakeIWH(info.width(), info.height()))); |
+ draw(recorder.beginRecording(SkRect::MakeIWH(info.width(), info.height()))); |
SkAutoTUnref<SkPicture> pict(recorder.endRecording()); |
return SkImage::NewFromPicture(pict, info.dimensions(), nullptr, nullptr); |
} |
-static SkImage* make_codec(const SkImageInfo& info, GrContext*) { |
- SkAutoTUnref<SkImage> image(make_raster(info, nullptr)); |
+static SkImage* make_codec(const SkImageInfo& info, GrContext*, void (*draw)(SkCanvas*)) { |
+ SkAutoTUnref<SkImage> image(make_raster(info, nullptr, draw)); |
SkAutoTUnref<SkData> data(image->encode()); |
return SkImage::NewFromEncoded(data); |
} |
-static SkImage* make_gpu(const SkImageInfo& info, GrContext* ctx) { |
+static SkImage* make_gpu(const SkImageInfo& info, GrContext* ctx, void (*draw)(SkCanvas*)) { |
if (!ctx) { return nullptr; } |
SkAutoTUnref<SkSurface> surface(SkSurface::NewRenderTarget(ctx, SkSurface::kNo_Budgeted, info)); |
- draw_contents(surface->getCanvas()); |
+ draw(surface->getCanvas()); |
return surface->newImageSnapshot(); |
} |
-typedef SkImage* (*ImageMakerProc)(const SkImageInfo&, GrContext*); |
+typedef SkImage* (*ImageMakerProc)(const SkImageInfo&, GrContext*, void (*)(SkCanvas*)); |
class ScalePixelsGM : public skiagm::GM { |
public: |
@@ -288,7 +288,7 @@ protected: |
make_codec, make_raster, make_picture, make_codec, make_gpu, |
}; |
for (auto& proc : procs) { |
- SkAutoTUnref<SkImage> image(proc(info, canvas->getGrContext())); |
+ SkAutoTUnref<SkImage> image(proc(info, canvas->getGrContext(), draw_contents)); |
if (image) { |
show_scaled_pixels(canvas, image); |
} |
@@ -300,3 +300,132 @@ private: |
typedef skiagm::GM INHERITED; |
}; |
DEF_GM( return new ScalePixelsGM; ) |
+ |
+/////////////////////////////////////////////////////////////////////////////////////////////////// |
+ |
+#include "SkImageGenerator.h" |
+ |
+static SkImageInfo make_info(SkImage* img) { |
+ return SkImageInfo::MakeN32(img->width(), img->height(), |
+ img->isOpaque() ? kOpaque_SkAlphaType : kPremul_SkAlphaType); |
+} |
+ |
+// Its simple, but I wonder if we should expose this formally? |
+// |
+class ImageGeneratorFromImage : public SkImageGenerator { |
+public: |
+ ImageGeneratorFromImage(SkImage* img) : INHERITED(make_info(img)), fImg(SkRef(img)) {} |
+ |
+protected: |
+ bool onGetPixels(const SkImageInfo& info, void* pixels, size_t rowBytes, SkPMColor ctable[], |
+ int* ctableCount) override { |
+ return fImg->readPixels(info, pixels, rowBytes, 0, 0); |
+ } |
+ |
+private: |
+ SkAutoTUnref<SkImage> fImg; |
+ |
+ typedef SkImageGenerator INHERITED; |
+}; |
+ |
+static void draw_opaque_contents(SkCanvas* canvas) { |
+ canvas->drawColor(0xFFFF8844); |
+ |
+ SkPaint paint; |
+ paint.setStyle(SkPaint::kStroke_Style); |
+ paint.setStrokeWidth(20); |
+ canvas->drawCircle(50, 50, 35, paint); |
+} |
+ |
+static SkImageGenerator* gen_raster(const SkImageInfo& info) { |
+ SkAutoTUnref<SkSurface> surface(SkSurface::NewRaster(info)); |
+ draw_opaque_contents(surface->getCanvas()); |
+ SkAutoTUnref<SkImage> img(surface->newImageSnapshot()); |
+ return new ImageGeneratorFromImage(img); |
+} |
+ |
+static SkImageGenerator* gen_picture(const SkImageInfo& info) { |
+ SkPictureRecorder recorder; |
+ draw_opaque_contents(recorder.beginRecording(SkRect::MakeIWH(info.width(), info.height()))); |
+ SkAutoTUnref<SkPicture> pict(recorder.endRecording()); |
+ return SkImageGenerator::NewFromPicture(info.dimensions(), pict, nullptr, nullptr); |
+} |
+ |
+static SkImageGenerator* gen_png(const SkImageInfo& info) { |
+ SkAutoTUnref<SkImage> image(make_raster(info, nullptr, draw_opaque_contents)); |
+ SkAutoTUnref<SkData> data(image->encode(SkImageEncoder::kPNG_Type, 100)); |
+ return SkImageGenerator::NewFromEncoded(data); |
+} |
+ |
+static SkImageGenerator* gen_jpg(const SkImageInfo& info) { |
+ SkAutoTUnref<SkImage> image(make_raster(info, nullptr, draw_opaque_contents)); |
+ SkAutoTUnref<SkData> data(image->encode(SkImageEncoder::kJPEG_Type, 100)); |
+ return SkImageGenerator::NewFromEncoded(data); |
+} |
+ |
+typedef SkImageGenerator* (*GeneratorMakerProc)(const SkImageInfo&); |
+ |
+static void show_scaled_generator(SkCanvas* canvas, SkImageGenerator* gen) { |
+ const SkImageInfo genInfo = gen->getInfo(); |
+ |
+ SkAutoCanvasRestore acr(canvas, true); |
+ |
+ SkBitmap bm; |
+ bm.allocPixels(genInfo); |
+ if (gen->getPixels(bm.info(), bm.getPixels(), bm.rowBytes())) { |
+ canvas->drawBitmap(bm, 0, 0, nullptr); |
+ } |
+ canvas->translate(110, 0); |
+ |
+ const float scales[] = { 0.75f, 0.5f, 0.25f }; |
+ for (auto scale : scales) { |
+ SkImageGenerator::SupportedSizes sizes; |
+ if (gen->computeScaledDimensions(scale, &sizes)) { |
+ const SkImageInfo info = SkImageInfo::MakeN32Premul(sizes.fSizes[0].width(), |
+ sizes.fSizes[0].height()); |
+ bm.allocPixels(info); |
+ SkPixmap pmap; |
+ bm.peekPixels(&pmap); |
+ if (gen->generateScaledPixels(pmap)) { |
+ canvas->drawBitmap(bm, 0, SkIntToScalar(genInfo.height() - info.height())/2); |
+ } |
+ } |
+ canvas->translate(100, 0); |
+ } |
+} |
+ |
+class ScaleGeneratorGM : public skiagm::GM { |
+public: |
+ ScaleGeneratorGM() {} |
+ |
+protected: |
+ SkString onShortName() override { |
+ return SkString("scale-generator"); |
+ } |
+ |
+ SkISize onISize() override { |
+ return SkISize::Make(500, 500); |
+ } |
+ |
+ void onDraw(SkCanvas* canvas) override { |
+ canvas->translate(10, 10); |
+ |
+ // explicitly make it opaque, so we can test JPEG (which is only ever opaque) |
+ const SkImageInfo info = SkImageInfo::MakeN32(100, 100, kOpaque_SkAlphaType); |
+ |
+ const GeneratorMakerProc procs[] = { |
+ gen_raster, gen_picture, gen_png, gen_jpg, |
+ }; |
+ for (auto& proc : procs) { |
+ SkAutoTDelete<SkImageGenerator> gen(proc(info)); |
+ if (gen) { |
+ show_scaled_generator(canvas, gen); |
+ } |
+ canvas->translate(0, 120); |
+ } |
+ } |
+ |
+private: |
+ typedef skiagm::GM INHERITED; |
+}; |
+DEF_GM( return new ScaleGeneratorGM; ) |