Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Convert raw BGRA framebuffer to RGB png file
This program can be used to convert raw BGRA 8888 framebuffer to standard PNG file.
#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;
}
@JakubVanek

This comment has been minimized.

Copy link
Owner Author

commented Mar 11, 2016

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/.

@JakubVanek

This comment has been minimized.

Copy link
Owner Author

commented Mar 11, 2016

For this program to work correctly fbset must return rgba 8/16,8/8,8/0,0/0 and bit depth must be 32.

@JakubVanek

This comment has been minimized.

Copy link
Owner Author

commented Mar 11, 2016

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
You can’t perform that action at this time.