14dcbe431244c2f1abef8416b95ebf2921708fa63joshualitt/*
24dcbe431244c2f1abef8416b95ebf2921708fa63joshualitt * Copyright 2016 Google Inc.
34dcbe431244c2f1abef8416b95ebf2921708fa63joshualitt *
44dcbe431244c2f1abef8416b95ebf2921708fa63joshualitt * Use of this source code is governed by a BSD-style license that can be
54dcbe431244c2f1abef8416b95ebf2921708fa63joshualitt * found in the LICENSE file.
64dcbe431244c2f1abef8416b95ebf2921708fa63joshualitt */
74dcbe431244c2f1abef8416b95ebf2921708fa63joshualitt
84dcbe431244c2f1abef8416b95ebf2921708fa63joshualitt#include "Request.h"
94dcbe431244c2f1abef8416b95ebf2921708fa63joshualitt
104dcbe431244c2f1abef8416b95ebf2921708fa63joshualitt#include "png.h"
114dcbe431244c2f1abef8416b95ebf2921708fa63joshualitt
124dcbe431244c2f1abef8416b95ebf2921708fa63joshualittconst int Request::kImageWidth = 1920;
134dcbe431244c2f1abef8416b95ebf2921708fa63joshualittconst int Request::kImageHeight = 1080;
144dcbe431244c2f1abef8416b95ebf2921708fa63joshualitt
154dcbe431244c2f1abef8416b95ebf2921708fa63joshualittstatic void write_png_callback(png_structp png_ptr, png_bytep data, png_size_t length) {
164dcbe431244c2f1abef8416b95ebf2921708fa63joshualitt    SkWStream* out = (SkWStream*) png_get_io_ptr(png_ptr);
174dcbe431244c2f1abef8416b95ebf2921708fa63joshualitt    out->write(data, length);
184dcbe431244c2f1abef8416b95ebf2921708fa63joshualitt}
194dcbe431244c2f1abef8416b95ebf2921708fa63joshualitt
204dcbe431244c2f1abef8416b95ebf2921708fa63joshualittstatic void write_png(const png_bytep rgba, png_uint_32 width, png_uint_32 height, SkWStream& out) {
214dcbe431244c2f1abef8416b95ebf2921708fa63joshualitt    png_structp png = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
224dcbe431244c2f1abef8416b95ebf2921708fa63joshualitt    SkASSERT(png != nullptr);
234dcbe431244c2f1abef8416b95ebf2921708fa63joshualitt    png_infop info_ptr = png_create_info_struct(png);
244dcbe431244c2f1abef8416b95ebf2921708fa63joshualitt    SkASSERT(info_ptr != nullptr);
254dcbe431244c2f1abef8416b95ebf2921708fa63joshualitt    if (setjmp(png_jmpbuf(png))) {
264dcbe431244c2f1abef8416b95ebf2921708fa63joshualitt        SkFAIL("png encode error");
274dcbe431244c2f1abef8416b95ebf2921708fa63joshualitt    }
284dcbe431244c2f1abef8416b95ebf2921708fa63joshualitt    png_set_IHDR(png, info_ptr, width, height, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE,
294dcbe431244c2f1abef8416b95ebf2921708fa63joshualitt                 PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
304dcbe431244c2f1abef8416b95ebf2921708fa63joshualitt    png_set_compression_level(png, 1);
314dcbe431244c2f1abef8416b95ebf2921708fa63joshualitt    png_bytepp rows = (png_bytepp) sk_malloc_throw(height * sizeof(png_byte*));
324dcbe431244c2f1abef8416b95ebf2921708fa63joshualitt    png_bytep pixels = (png_bytep) sk_malloc_throw(width * height * 3);
334dcbe431244c2f1abef8416b95ebf2921708fa63joshualitt    for (png_size_t y = 0; y < height; ++y) {
344dcbe431244c2f1abef8416b95ebf2921708fa63joshualitt        const png_bytep src = rgba + y * width * 4;
354dcbe431244c2f1abef8416b95ebf2921708fa63joshualitt        rows[y] = pixels + y * width * 3;
364dcbe431244c2f1abef8416b95ebf2921708fa63joshualitt        // convert from RGBA to RGB
374dcbe431244c2f1abef8416b95ebf2921708fa63joshualitt        for (png_size_t x = 0; x < width; ++x) {
384dcbe431244c2f1abef8416b95ebf2921708fa63joshualitt            rows[y][x * 3] = src[x * 4];
394dcbe431244c2f1abef8416b95ebf2921708fa63joshualitt            rows[y][x * 3 + 1] = src[x * 4 + 1];
404dcbe431244c2f1abef8416b95ebf2921708fa63joshualitt            rows[y][x * 3 + 2] = src[x * 4 + 2];
414dcbe431244c2f1abef8416b95ebf2921708fa63joshualitt        }
424dcbe431244c2f1abef8416b95ebf2921708fa63joshualitt    }
434dcbe431244c2f1abef8416b95ebf2921708fa63joshualitt    png_set_filter(png, 0, PNG_NO_FILTERS);
444dcbe431244c2f1abef8416b95ebf2921708fa63joshualitt    png_set_rows(png, info_ptr, &rows[0]);
454dcbe431244c2f1abef8416b95ebf2921708fa63joshualitt    png_set_write_fn(png, &out, write_png_callback, NULL);
464dcbe431244c2f1abef8416b95ebf2921708fa63joshualitt    png_write_png(png, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);
474dcbe431244c2f1abef8416b95ebf2921708fa63joshualitt    png_destroy_write_struct(&png, NULL);
484dcbe431244c2f1abef8416b95ebf2921708fa63joshualitt    sk_free(rows);
494dcbe431244c2f1abef8416b95ebf2921708fa63joshualitt}
504dcbe431244c2f1abef8416b95ebf2921708fa63joshualitt
514dcbe431244c2f1abef8416b95ebf2921708fa63joshualittSkBitmap* Request::getBitmapFromCanvas(SkCanvas* canvas) {
524dcbe431244c2f1abef8416b95ebf2921708fa63joshualitt    SkBitmap* bmp = new SkBitmap();
534dcbe431244c2f1abef8416b95ebf2921708fa63joshualitt    SkImageInfo info = SkImageInfo::Make(kImageWidth, kImageHeight, kRGBA_8888_SkColorType,
544dcbe431244c2f1abef8416b95ebf2921708fa63joshualitt                kOpaque_SkAlphaType);
554dcbe431244c2f1abef8416b95ebf2921708fa63joshualitt    bmp->setInfo(info);
564dcbe431244c2f1abef8416b95ebf2921708fa63joshualitt    if (!canvas->readPixels(bmp, 0, 0)) {
574dcbe431244c2f1abef8416b95ebf2921708fa63joshualitt        fprintf(stderr, "Can't read pixels\n");
584dcbe431244c2f1abef8416b95ebf2921708fa63joshualitt        return nullptr;
594dcbe431244c2f1abef8416b95ebf2921708fa63joshualitt    }
604dcbe431244c2f1abef8416b95ebf2921708fa63joshualitt    return bmp;
614dcbe431244c2f1abef8416b95ebf2921708fa63joshualitt}
624dcbe431244c2f1abef8416b95ebf2921708fa63joshualitt
634dcbe431244c2f1abef8416b95ebf2921708fa63joshualittSkData* Request::writeCanvasToPng(SkCanvas* canvas) {
644dcbe431244c2f1abef8416b95ebf2921708fa63joshualitt    // capture pixels
654dcbe431244c2f1abef8416b95ebf2921708fa63joshualitt    SkAutoTDelete<SkBitmap> bmp(getBitmapFromCanvas(canvas));
664dcbe431244c2f1abef8416b95ebf2921708fa63joshualitt    SkASSERT(bmp);
674dcbe431244c2f1abef8416b95ebf2921708fa63joshualitt
684dcbe431244c2f1abef8416b95ebf2921708fa63joshualitt    // write to png
694dcbe431244c2f1abef8416b95ebf2921708fa63joshualitt    SkDynamicMemoryWStream buffer;
704dcbe431244c2f1abef8416b95ebf2921708fa63joshualitt    write_png((const png_bytep) bmp->getPixels(), bmp->width(), bmp->height(), buffer);
714dcbe431244c2f1abef8416b95ebf2921708fa63joshualitt    return buffer.copyToData();
724dcbe431244c2f1abef8416b95ebf2921708fa63joshualitt}
734dcbe431244c2f1abef8416b95ebf2921708fa63joshualitt
744dcbe431244c2f1abef8416b95ebf2921708fa63joshualittSkCanvas* Request::getCanvas() {
754dcbe431244c2f1abef8416b95ebf2921708fa63joshualitt    GrContextFactory* factory = fContextFactory;
764dcbe431244c2f1abef8416b95ebf2921708fa63joshualitt    SkGLContext* gl = factory->getContextInfo(GrContextFactory::kNative_GLContextType,
774dcbe431244c2f1abef8416b95ebf2921708fa63joshualitt                                              GrContextFactory::kNone_GLContextOptions).fGLContext;
784dcbe431244c2f1abef8416b95ebf2921708fa63joshualitt    gl->makeCurrent();
794dcbe431244c2f1abef8416b95ebf2921708fa63joshualitt    SkASSERT(fDebugCanvas);
804dcbe431244c2f1abef8416b95ebf2921708fa63joshualitt    SkCanvas* target = fSurface->getCanvas();
814dcbe431244c2f1abef8416b95ebf2921708fa63joshualitt    return target;
824dcbe431244c2f1abef8416b95ebf2921708fa63joshualitt}
834dcbe431244c2f1abef8416b95ebf2921708fa63joshualitt
844dcbe431244c2f1abef8416b95ebf2921708fa63joshualittvoid Request::drawToCanvas(int n) {
854dcbe431244c2f1abef8416b95ebf2921708fa63joshualitt    SkCanvas* target = this->getCanvas();
864dcbe431244c2f1abef8416b95ebf2921708fa63joshualitt    fDebugCanvas->drawTo(target, n);
874dcbe431244c2f1abef8416b95ebf2921708fa63joshualitt}
884dcbe431244c2f1abef8416b95ebf2921708fa63joshualitt
894dcbe431244c2f1abef8416b95ebf2921708fa63joshualittSkData* Request::drawToPng(int n) {
904dcbe431244c2f1abef8416b95ebf2921708fa63joshualitt    this->drawToCanvas(n);
914dcbe431244c2f1abef8416b95ebf2921708fa63joshualitt    return writeCanvasToPng(this->getCanvas());
924dcbe431244c2f1abef8416b95ebf2921708fa63joshualitt}
934dcbe431244c2f1abef8416b95ebf2921708fa63joshualitt
944dcbe431244c2f1abef8416b95ebf2921708fa63joshualittSkSurface* Request::createCPUSurface() {
954dcbe431244c2f1abef8416b95ebf2921708fa63joshualitt    SkImageInfo info = SkImageInfo::Make(kImageWidth, kImageHeight, kN32_SkColorType,
964dcbe431244c2f1abef8416b95ebf2921708fa63joshualitt                                         kPremul_SkAlphaType);
974dcbe431244c2f1abef8416b95ebf2921708fa63joshualitt    return SkSurface::NewRaster(info);
984dcbe431244c2f1abef8416b95ebf2921708fa63joshualitt}
994dcbe431244c2f1abef8416b95ebf2921708fa63joshualitt
1004dcbe431244c2f1abef8416b95ebf2921708fa63joshualittSkSurface* Request::createGPUSurface() {
1014dcbe431244c2f1abef8416b95ebf2921708fa63joshualitt    GrContext* context = fContextFactory->get(GrContextFactory::kNative_GLContextType,
1024dcbe431244c2f1abef8416b95ebf2921708fa63joshualitt                                              GrContextFactory::kNone_GLContextOptions);
1034dcbe431244c2f1abef8416b95ebf2921708fa63joshualitt    int maxRTSize = context->caps()->maxRenderTargetSize();
1044dcbe431244c2f1abef8416b95ebf2921708fa63joshualitt    SkImageInfo info = SkImageInfo::Make(SkTMin(kImageWidth, maxRTSize),
1054dcbe431244c2f1abef8416b95ebf2921708fa63joshualitt                                         SkTMin(kImageHeight, maxRTSize),
1064dcbe431244c2f1abef8416b95ebf2921708fa63joshualitt                                         kN32_SkColorType, kPremul_SkAlphaType);
1074dcbe431244c2f1abef8416b95ebf2921708fa63joshualitt    uint32_t flags = 0;
1084dcbe431244c2f1abef8416b95ebf2921708fa63joshualitt    SkSurfaceProps props(flags, SkSurfaceProps::kLegacyFontHost_InitType);
1094dcbe431244c2f1abef8416b95ebf2921708fa63joshualitt    SkSurface* surface = SkSurface::NewRenderTarget(context, SkBudgeted::kNo, info, 0,
1104dcbe431244c2f1abef8416b95ebf2921708fa63joshualitt                                                    &props);
1114dcbe431244c2f1abef8416b95ebf2921708fa63joshualitt    return surface;
1124dcbe431244c2f1abef8416b95ebf2921708fa63joshualitt}
1134dcbe431244c2f1abef8416b95ebf2921708fa63joshualitt
114