1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-12-12 08:30:05 +00:00
CLK/Outputs/OpenGL/Screenshot.hpp

62 lines
1.8 KiB
C++

//
// 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<uint8_t> pixel_data;
int width, height;
};
}
}
}
#endif /* Screenshot_h */