• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2016 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #include "Request.h"
9 
10 #include "png.h"
11 
12 const int Request::kImageWidth = 1920;
13 const int Request::kImageHeight = 1080;
14 
write_png_callback(png_structp png_ptr,png_bytep data,png_size_t length)15 static void write_png_callback(png_structp png_ptr, png_bytep data, png_size_t length) {
16     SkWStream* out = (SkWStream*) png_get_io_ptr(png_ptr);
17     out->write(data, length);
18 }
19 
write_png(const png_bytep rgba,png_uint_32 width,png_uint_32 height,SkWStream & out)20 static void write_png(const png_bytep rgba, png_uint_32 width, png_uint_32 height, SkWStream& out) {
21     png_structp png = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
22     SkASSERT(png != nullptr);
23     png_infop info_ptr = png_create_info_struct(png);
24     SkASSERT(info_ptr != nullptr);
25     if (setjmp(png_jmpbuf(png))) {
26         SkFAIL("png encode error");
27     }
28     png_set_IHDR(png, info_ptr, width, height, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE,
29                  PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
30     png_set_compression_level(png, 1);
31     png_bytepp rows = (png_bytepp) sk_malloc_throw(height * sizeof(png_byte*));
32     png_bytep pixels = (png_bytep) sk_malloc_throw(width * height * 3);
33     for (png_size_t y = 0; y < height; ++y) {
34         const png_bytep src = rgba + y * width * 4;
35         rows[y] = pixels + y * width * 3;
36         // convert from RGBA to RGB
37         for (png_size_t x = 0; x < width; ++x) {
38             rows[y][x * 3] = src[x * 4];
39             rows[y][x * 3 + 1] = src[x * 4 + 1];
40             rows[y][x * 3 + 2] = src[x * 4 + 2];
41         }
42     }
43     png_set_filter(png, 0, PNG_NO_FILTERS);
44     png_set_rows(png, info_ptr, &rows[0]);
45     png_set_write_fn(png, &out, write_png_callback, NULL);
46     png_write_png(png, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);
47     png_destroy_write_struct(&png, NULL);
48     sk_free(rows);
49 }
50 
getBitmapFromCanvas(SkCanvas * canvas)51 SkBitmap* Request::getBitmapFromCanvas(SkCanvas* canvas) {
52     SkBitmap* bmp = new SkBitmap();
53     SkImageInfo info = SkImageInfo::Make(kImageWidth, kImageHeight, kRGBA_8888_SkColorType,
54                 kOpaque_SkAlphaType);
55     bmp->setInfo(info);
56     if (!canvas->readPixels(bmp, 0, 0)) {
57         fprintf(stderr, "Can't read pixels\n");
58         return nullptr;
59     }
60     return bmp;
61 }
62 
writeCanvasToPng(SkCanvas * canvas)63 SkData* Request::writeCanvasToPng(SkCanvas* canvas) {
64     // capture pixels
65     SkAutoTDelete<SkBitmap> bmp(getBitmapFromCanvas(canvas));
66     SkASSERT(bmp);
67 
68     // write to png
69     SkDynamicMemoryWStream buffer;
70     write_png((const png_bytep) bmp->getPixels(), bmp->width(), bmp->height(), buffer);
71     return buffer.copyToData();
72 }
73 
getCanvas()74 SkCanvas* Request::getCanvas() {
75     GrContextFactory* factory = fContextFactory;
76     SkGLContext* gl = factory->getContextInfo(GrContextFactory::kNative_GLContextType,
77                                               GrContextFactory::kNone_GLContextOptions).fGLContext;
78     gl->makeCurrent();
79     SkASSERT(fDebugCanvas);
80     SkCanvas* target = fSurface->getCanvas();
81     return target;
82 }
83 
drawToCanvas(int n)84 void Request::drawToCanvas(int n) {
85     SkCanvas* target = this->getCanvas();
86     fDebugCanvas->drawTo(target, n);
87 }
88 
drawToPng(int n)89 SkData* Request::drawToPng(int n) {
90     this->drawToCanvas(n);
91     return writeCanvasToPng(this->getCanvas());
92 }
93 
createCPUSurface()94 SkSurface* Request::createCPUSurface() {
95     SkImageInfo info = SkImageInfo::Make(kImageWidth, kImageHeight, kN32_SkColorType,
96                                          kPremul_SkAlphaType);
97     return SkSurface::NewRaster(info);
98 }
99 
createGPUSurface()100 SkSurface* Request::createGPUSurface() {
101     GrContext* context = fContextFactory->get(GrContextFactory::kNative_GLContextType,
102                                               GrContextFactory::kNone_GLContextOptions);
103     int maxRTSize = context->caps()->maxRenderTargetSize();
104     SkImageInfo info = SkImageInfo::Make(SkTMin(kImageWidth, maxRTSize),
105                                          SkTMin(kImageHeight, maxRTSize),
106                                          kN32_SkColorType, kPremul_SkAlphaType);
107     uint32_t flags = 0;
108     SkSurfaceProps props(flags, SkSurfaceProps::kLegacyFontHost_InitType);
109     SkSurface* surface = SkSurface::NewRenderTarget(context, SkBudgeted::kNo, info, 0,
110                                                     &props);
111     return surface;
112 }
113 
114