// // Screenshot.hpp // Clock Signal // // Created by Thomas Harte on 27/02/2019. // Copyright © 2019 Thomas Harte. All rights reserved. // #ifndef Screenshot_h #define Screenshot_h #include "OpenGL.hpp" namespace Outputs { namespace Display { namespace OpenGL { /*! Upon construction, Screenshot will capture the centre portion of the currently-bound framebuffer, cropping to an image that matches the requested aspect ratio. The image will then be available as RGBA data, in raster order via the struct members. */ struct Screenshot { Screenshot(int aspect_width, int aspect_height) { // Get the current viewport to establish framebuffer size. Then determine how wide the // centre portion of that would be, allowing for the requested aspect ratio. GLint dimensions[4]; glGetIntegerv(GL_VIEWPORT, dimensions); height = int(dimensions[3]); width = (height * aspect_width) / aspect_height; pixel_data.resize(size_t(width * height * 4)); // Grab the framebuffer contents, temporarily setting single-byte alignment. int prior_alignment; glGetIntegerv(GL_PACK_ALIGNMENT, &prior_alignment); glReadPixels((dimensions[2] - GLint(width)) >> 1, 0, GLint(width), GLint(height), GL_RGBA, GL_UNSIGNED_BYTE, pixel_data.data()); glPixelStorei(GL_PACK_ALIGNMENT, prior_alignment); // Flip the contents into raster order. const size_t line_size = size_t(width * 4); for(size_t y = 0; y < size_t(height) / 2; ++y) { const size_t flipped_y = size_t(height - 1) - y; uint8_t temp[line_size]; memcpy(temp, &pixel_data[flipped_y * line_size], line_size); memcpy(&pixel_data[flipped_y * line_size], &pixel_data[y * line_size], line_size); memcpy(&pixel_data[y * line_size], temp, line_size); } } std::vector pixel_data; int width, height; }; } } } #endif /* Screenshot_h */