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