OpenGL snippets: Difference between revisions
Jump to navigation
Jump to search
Content added Content deleted
(C++/libpng) |
(add link) |
||
(2 intermediate revisions by the same user not shown) | |||
Line 35: | Line 35: | ||
glReadnPixels(0, 0, buffer_width, height, |
glReadnPixels(0, 0, buffer_width, height, |
||
GL_RGB, GL_UNSIGNED_BYTE, buffer_size, (void *) buffer); |
GL_RGB, GL_UNSIGNED_BYTE, buffer_size, (void *) buffer.get()); |
||
FILE *fp = fopen("output.png", "wb"); |
FILE *fp = fopen("output.png", "wb"); |
||
Line 69: | Line 69: | ||
The error handling leaves something to be desired for now. |
The error handling leaves something to be desired for now. |
||
== See also == |
|||
* [[GLSL snippets]] |
|||
[[Category:Graphics programming]] |
[[Category:Graphics programming]] |
Latest revision as of 14:48, 25 February 2020
Saving the framebuffer to file
Python/PIL
from PIL import Image
pixels = glReadPixels(0, 0, window_width, window_height, GL_RGB, GL_UNSIGNED_BYTE)
image = Image.frombytes(mode="RGB", size=(window_width, window_height), data=pixels)
image = image.transpose(Image.FLIP_TOP_BOTTOM)
image.save('output.png')
Note: This should work for any file type/extension that PIL supports.
May or may not work for widths which are not multiples of 4 or 8. YMMV.
C++/libpng
#include <libpng/png.h>
// http://www.labbookpages.co.uk/software/imgProc/libPNG.html
static void capture()
{
int width, height;
glfwGetFramebufferSize(window, &width, &height);
// round up width to a multiple of 8 avoid alignment problems
unsigned int buffer_width = (width + 7) & ~7;
unsigned int buffer_size = buffer_width * height * 3;
auto buffer = std::make_unique<char []>(buffer_size);
glReadnPixels(0, 0, buffer_width, height,
GL_RGB, GL_UNSIGNED_BYTE, buffer_size, (void *) buffer.get());
FILE *fp = fopen("output.png", "wb");
if (!fp)
error(EXIT_FAILURE, errno, "fopen()");
auto png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (!png_ptr)
error(EXIT_FAILURE, 0, "png_create_write_struct()");
auto info_ptr = png_create_info_struct(png_ptr);
if (!info_ptr)
error(EXIT_FAILURE, 0, "png_create_info_struct()");
png_init_io(png_ptr, fp);
png_set_IHDR(png_ptr, info_ptr, width, height,
8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE,
PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
png_write_info(png_ptr, info_ptr);
for (unsigned int y = 0; y < height; ++y)
png_write_row(png_ptr, (png_bytep) &buffer[3 * buffer_width * (height - y - 1)]);
png_write_end(png_ptr, info_ptr);
fclose(fp);
png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1);
png_destroy_write_struct(&png_ptr, (png_infopp) NULL);
}
This uses GLFW to obtain the frambuffer size, but should be easy to adapt to other windowing APIs.
The error handling leaves something to be desired for now.