aboutsummaryrefslogtreecommitdiffhomepage
path: root/gm/image.cpp
diff options
context:
space:
mode:
authorGravatar reed <reed@google.com>2015-12-02 14:19:47 -0800
committerGravatar Commit bot <commit-bot@chromium.org>2015-12-02 14:19:47 -0800
commit7850eb2f357c215b2e2c50bf16d6c6df38c7967f (patch)
treea67b456a7b21c9ee3dbec07772882dd117672b52 /gm/image.cpp
parentdc5685ac3752e90dd68179e9f1675ff6f15ed600 (diff)
API to support native scaling by image-generator
Diffstat (limited to 'gm/image.cpp')
-rw-r--r--gm/image.cpp149
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; )