diff options
author | reed <reed@google.com> | 2015-12-02 14:19:47 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-12-02 14:19:47 -0800 |
commit | 7850eb2f357c215b2e2c50bf16d6c6df38c7967f (patch) | |
tree | a67b456a7b21c9ee3dbec07772882dd117672b52 /gm/image.cpp | |
parent | dc5685ac3752e90dd68179e9f1675ff6f15ed600 (diff) |
API to support native scaling by image-generator
BUG=skia:
Review URL: https://codereview.chromium.org/1396323007
Diffstat (limited to 'gm/image.cpp')
-rw-r--r-- | gm/image.cpp | 149 |
1 files changed, 139 insertions, 10 deletions
diff --git a/gm/image.cpp b/gm/image.cpp index 991b4014f0..ac72f63b36 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; ) |