implement OpenGL screenshot

This commit is contained in:
Ted John 2016-06-11 03:06:30 +01:00
parent b0b0b82fd1
commit db01547ae6
7 changed files with 108 additions and 2 deletions

View File

@ -47,6 +47,7 @@ IDrawingEngine * DrawingEngineFactory::CreateOpenGL()
extern "C"
{
#include "../../../config.h"
#include "../../../interface/screenshot.h"
#include "../../../interface/window.h"
#include "../../../intro.h"
#include "../../drawing.h"
@ -328,8 +329,11 @@ public:
sint32 Screenshot() override
{
// Not implemented
return -1;
_canvasFramebuffer->Bind();
void * pixels = _canvasFramebuffer->GetPixels();
int result = screenshot_dump_png_32bpp(_width, _height, pixels);
Memory::Free(pixels);
return result;
}
void CopyRect(sint32 x, sint32 y, sint32 width, sint32 height, sint32 dx, sint32 dy) override

View File

@ -15,6 +15,7 @@
#pragma endregion
#include <SDL_video.h>
#include "../../../core/Memory.hpp"
#include "OpenGLFramebuffer.h"
constexpr GLuint BACKBUFFER_ID = 0;
@ -56,3 +57,24 @@ void OpenGLFramebuffer::Bind()
glBindFramebuffer(GL_FRAMEBUFFER, _id);
glViewport(0, 0, (GLsizei)_width, (GLsizei)_height);
}
void * OpenGLFramebuffer::GetPixels() const
{
void * pixels = Memory::Allocate<void>(_width * _height * 4);
glReadPixels(0, 0, _width, _height, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
// Flip pixels vertically
void * flippedPixels = Memory::Allocate<void>(_width * _height * 4);
size_t stride = _width * 4;
uint8 * src = (uint8 *)pixels + ((_height - 1) * stride);
uint8 * dst = (uint8 *)flippedPixels;
for (sint32 y = 0; y < _height; y++)
{
Memory::Copy(dst, src, stride);
src -= stride;
dst += stride;
}
Memory::Free(pixels);
return flippedPixels;
}

View File

@ -39,4 +39,5 @@ public:
GLuint GetTexture() const { return _texture; }
void Bind();
void * GetPixels() const;
};

View File

@ -171,6 +171,67 @@ bool image_io_png_write(const rct_drawpixelinfo *dpi, const rct_palette *palette
return true;
}
static void image_io_png_warning(png_structp png_ptr, const char *b)
{
log_warning(b);
}
static void image_io_png_error(png_structp png_ptr, const char *b)
{
log_error(b);
}
bool image_io_png_write_32bpp(sint32 width, sint32 height, const void *pixels, const utf8 *path)
{
// Setup PNG
png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, image_io_png_error, image_io_png_warning);
if (png_ptr == NULL) {
return false;
}
png_infop info_ptr = png_create_info_struct(png_ptr);
if (info_ptr == NULL) {
png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
return false;
}
// Open file for writing
SDL_RWops *file = SDL_RWFromFile(path, "wb");
if (file == NULL) {
png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
return false;
}
png_set_write_fn(png_ptr, file, my_png_write_data, my_png_flush);
// Set error handler
if (setjmp(png_jmpbuf(png_ptr))) {
png_destroy_write_struct(&png_ptr, &info_ptr);
SDL_RWclose(file);
return false;
}
// Write header
png_set_IHDR(
png_ptr, info_ptr, width, height, 8,
PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT
);
png_write_info(png_ptr, info_ptr);
// Write pixels
uint8 *bits = (uint8*)pixels;
for (int y = 0; y < height; y++) {
png_write_row(png_ptr, (png_byte *)bits);
bits += width * 4;
}
// Finish
png_write_end(png_ptr, NULL);
SDL_RWclose(file);
png_destroy_write_struct(&png_ptr, &info_ptr);
return true;
}
static void my_png_read_data(png_structp png_ptr, png_bytep data, png_size_t length)
{
SDL_RWops *file = (SDL_RWops*)png_get_io_ptr(png_ptr);

View File

@ -23,5 +23,6 @@
bool image_io_png_read(uint8 **pixels, uint32 *width, uint32 *height, const utf8 *path);
bool image_io_png_write(const rct_drawpixelinfo *dpi, const rct_palette *palette, const utf8 *path);
bool image_io_png_write_32bpp(sint32 width, sint32 height, const void *pixels, const utf8 *path);
#endif

View File

@ -115,6 +115,22 @@ int screenshot_dump_png(rct_drawpixelinfo *dpi)
}
}
int screenshot_dump_png_32bpp(sint32 width, sint32 height, const void *pixels)
{
// Get a free screenshot path
int index;
char path[MAX_PATH] = "";
if ((index = screenshot_get_next_path(path)) == -1) {
return -1;
}
if (image_io_png_write_32bpp(width, height, pixels, path)) {
return index;
} else {
return -1;
}
}
void screenshot_giant()
{
int originalRotation = get_current_rotation();

View File

@ -22,6 +22,7 @@
void screenshot_check();
int screenshot_dump();
int screenshot_dump_png(rct_drawpixelinfo *dpi);
int screenshot_dump_png_32bpp(sint32 width, sint32 height, const void *pixels);
void screenshot_giant();
int cmdline_for_screenshot(const char **argv, int argc);