Last active
May 5, 2023 21:10
-
-
Save JakubVanek/4ec92317274c12d2dec9 to your computer and use it in GitHub Desktop.
Convert raw BGRA framebuffer to RGB png file
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This program can be used to convert raw BGRA 8888 framebuffer to standard PNG file. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <png.h> | |
#include <stdlib.h> | |
#include <stdio.h> | |
#include <stdint.h> | |
#include <string.h> | |
#include <errno.h> | |
typedef struct { | |
uint8_t red; | |
uint8_t green; | |
uint8_t blue; | |
} pixel_t; | |
typedef struct { | |
pixel_t *pixels; | |
size_t width; | |
size_t height; | |
} bitmap_t; | |
static pixel_t * pixel_at (bitmap_t *bitmap, int x, int y) { | |
return bitmap->pixels + x + bitmap->width * y; | |
} | |
static int save_png_to_file (bitmap_t *bitmap, const char* path) { | |
FILE *p_file; | |
png_structp p_png = NULL; | |
png_infop p_info = NULL; | |
size_t x, y; | |
png_byte ** row_pointers = NULL; | |
int status = -1; | |
int pixel_size = 3; | |
int depth = 8; | |
p_file = fopen(path, "wb"); | |
if (!p_file) { | |
goto fopen_failed; | |
} | |
p_png = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); | |
if (p_png == NULL) { | |
goto png_create_write_struct_failed; | |
} | |
p_info = png_create_info_struct (p_png); | |
if (p_info == NULL) { | |
goto png_create_info_struct_failed; | |
} | |
if (setjmp (png_jmpbuf (p_png))) { | |
goto png_failure; | |
} | |
png_set_IHDR ( p_png, | |
p_info, | |
bitmap->width, | |
bitmap->height, | |
depth, | |
PNG_COLOR_TYPE_RGB, | |
PNG_INTERLACE_NONE, | |
PNG_COMPRESSION_TYPE_DEFAULT, | |
PNG_FILTER_TYPE_DEFAULT); | |
row_pointers = png_malloc (p_png, bitmap->height * sizeof (png_byte*)); | |
for (y = 0; y < bitmap->height; ++y) { | |
png_byte *row = png_malloc (p_png, sizeof (uint8_t) * bitmap->width * pixel_size); | |
row_pointers[y] = row; | |
for (x = 0; x < bitmap->width; ++x) { | |
pixel_t *pixel = pixel_at (bitmap, x, y); | |
*row++ = pixel->red; | |
*row++ = pixel->green; | |
*row++ = pixel->blue; | |
} | |
} | |
png_init_io (p_png, p_file); | |
png_set_rows (p_png, p_info, row_pointers); | |
png_write_png (p_png, p_info, PNG_TRANSFORM_IDENTITY, NULL); | |
status = 0; | |
for (y = 0; y < bitmap->height; y++) { | |
png_free (p_png, row_pointers[y]); | |
} | |
png_free (p_png, row_pointers); | |
png_failure: | |
png_create_info_struct_failed: | |
png_destroy_write_struct(&p_png, &p_info); | |
png_create_write_struct_failed: | |
fclose(p_file); | |
fopen_failed: | |
return status; | |
} | |
int main (int argc, char **argv) { | |
size_t width, height, read = 0, length; | |
int i, status = 0; | |
char *input, *output; | |
uint8_t *buffer = NULL; | |
bitmap_t *bitmap = NULL; | |
pixel_t *pixel_out; | |
uint8_t *pixel_in; | |
FILE * fp = NULL; | |
if (argc != 5) { | |
printf("Usage: %s <width> <height> <input> <output>\n", argv[0]); | |
exit(1); | |
} | |
width = (size_t) atoi (argv[1]); | |
height = (size_t) atoi (argv[2]); | |
input = argv[3]; | |
output = argv[4]; | |
length = width * height * 4; | |
buffer = malloc (length); | |
bitmap = malloc (sizeof (pixel_t*) + sizeof (size_t) * 2); | |
bitmap->pixels = malloc(sizeof (pixel_t) * width * height); | |
bitmap->width = width; | |
bitmap->height = height; | |
fp = fopen(input, "rb"); | |
if (!fp) { | |
printf ("Error opening file (%d): %s.\n", errno, strerror (errno)); | |
status = 1; | |
goto free_val; | |
} | |
do { | |
read = fread (buffer + read, length - read, 1, fp); | |
} while (read > 0); | |
read = fclose (fp); | |
if (read == EOF) { | |
printf ("Error closing file (%d): %s.\n", errno, strerror (errno)); | |
status = 1; | |
goto free_val; | |
} | |
pixel_in = buffer; | |
pixel_out = bitmap->pixels; | |
for (i = 0; i < width * height; i++) { | |
pixel_out->blue = *(pixel_in++); | |
pixel_out->green = *(pixel_in++); | |
pixel_out->red = *(pixel_in++); | |
pixel_in++; // ignore alpha | |
pixel_out++; // to next pixel | |
} | |
pixel_in = NULL; | |
pixel_out = NULL; | |
int retval = save_png_to_file (bitmap, output); | |
if (retval != 0) { | |
printf ("Error saving PNG.\n"); | |
goto free_val; | |
} | |
free_val: | |
free(buffer); | |
free(bitmap->pixels); | |
free(bitmap); | |
return status; | |
} |
For this program to work correctly fbset must return rgba 8/16,8/8,8/0,0/0
and bit depth must be 32.
How to compile: enter this to terminal while you're in the directory with data.c
gcc data.c -O2 -lpng -o data
Usage:
- use framebuffer:
./data <fb width> <fb height> /dev/fb0 <out>.png
(replace <...> with corresponding values) - use framebuffer snapshot:
dd if=/dev/fb0 of=fb.raw
./data <fb width> <fb height> fb.raw <out>.png
Replace <...> with corresponding values.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Yes, there's unnecessary copying to bitmap_t, but I've created this mainly for fun. PNG write function comes from www.lemoda.net/c/write-png/.