Skip to content

Instantly share code, notes, and snippets.

@maxux
Created June 19, 2015 00:59
Show Gist options
  • Save maxux/5c79862795e9b681d385 to your computer and use it in GitHub Desktop.
Save maxux/5c79862795e9b681d385 to your computer and use it in GitHub Desktop.
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/fb.h>
#include <sys/mman.h>
#include <png.h>
typedef struct png_t {
png_struct *root;
png_info *info;
int width;
int height;
png_byte depth;
png_byte **rows;
} png_t;
typedef struct pixel_t {
char red;
char green;
char blue;
char alpha;
} pixel_t;
typedef struct screen_t {
char *buffer;
long size;
char *position;
int depth;
int byte;
int width;
int height;
} screen_t;
typedef struct fade_t {
png_t *left;
png_t *right;
float factor;
char *buffer;
int start;
int count;
} fade_t;
void diep(char *str) {
perror(str);
exit(EXIT_FAILURE);
}
void dies(char *str) {
fprintf(stderr, "%s\n", str);
exit(EXIT_FAILURE);
}
png_t *decode(char *filename) {
unsigned char header[8];
png_t *png;
FILE *fp;
int i;
// initializing object
if(!(png = (png_t *) malloc(sizeof(png_t))))
diep("[-] malloc");
// preparing file
if(!(fp = fopen(filename, "r")))
diep("[-] fopen");
if(fread(header, 1, 8, fp) != 8)
diep("[-] fread");
if(png_sig_cmp(header, 0, 8))
dies("[-] not a png file");
// initializing libpng
if(!(png->root = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL)))
dies("[-] png_create_read_struct failed");
if(!(png->info = png_create_info_struct(png->root)))
dies("[-] png_create_info_struct failed");
if(setjmp(png_jmpbuf(png->root)))
dies("[-] libpng failed to initialize");
png_init_io(png->root, fp);
png_set_sig_bytes(png->root, 8);
// initializing file info
png_read_info(png->root, png->info);
png->width = png_get_image_width(png->root, png->info);
png->height = png_get_image_height(png->root, png->info);
png->depth = png_get_bit_depth(png->root, png->info);
// colors = png_get_color_type(png, info);
printf("[+] png file: %dx%d, depth: %d\n", png->width, png->height, png->depth);
// number_of_passes = png_set_interlace_handling(png_ptr);
png_read_update_info(png->root, png->info);
if(setjmp(png_jmpbuf(png->root)))
dies("[-] cannot read png file");
png->rows = (png_byte **) malloc(sizeof(png_byte *) * png->height);
for(i = 0; i < png->height; i++)
png->rows[i] = (png_byte *) malloc(png_get_rowbytes(png->root, png->info));
png_read_image(png->root, png->rows);
fclose(fp);
return png;
}
int pixel(screen_t *screen, int offset, pixel_t *px) {
screen->buffer[offset + 0] = px->blue;
screen->buffer[offset + 1] = px->green;
screen->buffer[offset + 2] = px->red;
screen->buffer[offset + 3] = px->alpha;
return offset + screen->byte;
}
void fill(screen_t *screen, pixel_t *color) {
int i;
for(i = 0; i < screen->size;)
i = pixel(screen, i, color);
}
/*
void bufferise(png_t *image, char *buffer) {
int location = 0;
int i, j;
png_byte *row;
printf("[+] buffering...\n");
for(i = 0; i < image->height; i++) {
row = image->rows[i];
for(j = 0; j < image->width; j++) {
buffer[location++] = *(row + (j * 3) + 2);
buffer[location++] = *(row + (j * 3) + 1);
buffer[location++] = *(row + (j * 3) + 0);
}
}
}
*/
void __fade(void *data) { // png_t *left, png_t *right, float factor, char *buffer, int start, int count) {
fade_t *fader = (fade_t *) data;
// float factor = fader->factor;
short factor = fader->factor * 128; // avoid float
int i, j, x = 0, k;
pixel_t pxl1, pxl2;
png_byte *r1, *r2;
for(i = fader->start; i < fader->start + fader->count; i++) {
r1 = fader->left->rows[i];
r2 = fader->right->rows[i];
for(j = 0, k = 0; j < fader->left->width; j++, k += 3) {
pxl1.red = *(r1 + k + 0);
pxl1.green = *(r1 + k + 1);
pxl1.blue = *(r1 + k + 2);
pxl2.red = *(r2 + k + 0);
pxl2.green = *(r2 + k + 1);
pxl2.blue = *(r2 + k + 2);
fader->buffer[x++] = (pxl1.blue * 128 * factor + pxl2.blue * 128 * (128 - factor)) / (128 * 128);
fader->buffer[x++] = (pxl1.green * 128 * factor + pxl2.green * 128 * (128 - factor)) / (128 * 128);
fader->buffer[x++] = (pxl1.red * 128 * factor + pxl2.red * 128 * (128 - factor)) / (128 * 128);
}
}
free(data);
}
void fade(png_t *left, png_t *right, float factor, screen_t *screen, char *buffer) {
fade_t *fader;
int units = 8;
printf("[+] fading (factor %.2f), with %d threads...\n", factor, units);
int i;
#pragma omp parallel for
for(i = 0; i < units; i++) {
if(!(fader = malloc(sizeof(fade_t))))
diep("[-] malloc");
fader->left = left;
fader->right = right;
fader->factor = factor;
fader->start = (screen->height / units) * i;
fader->count = screen->height / units;
fader->buffer = buffer + (screen->width * screen->byte * i * fader->count);
__fade(fader);
}
}
int main(void) {
int fbfd = 0;
struct fb_var_screeninfo vinfo;
struct fb_fix_screeninfo finfo;
long int screensize = 0;
char *fbp = 0;
char *dblbuff = NULL;
unsigned int id;
png_t *images[2];
screen_t screen;
pixel_t pxl = {
.red = 0,
.green = 0,
.blue = 0,
.alpha = 255
};
//
// initialize framebuffer
//
if((fbfd = open("/dev/fb0", O_RDWR)) < -1)
diep("[-] /dev/fb0");
if(ioctl(fbfd, FBIOGET_FSCREENINFO, &finfo))
diep("[-] ioctl: get fixed screen info");
if(ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo))
diep("[-] ioctl: get variable screen info");
fbp = (char *) mmap(0, finfo.smem_len, PROT_READ | PROT_WRITE, MAP_SHARED, fbfd, 0);
if((int) fbp == -1)
diep("[-] mmap");
//
// initializing screen
//
screen.buffer = fbp;
screen.width = vinfo.xres;
screen.height = vinfo.yres;
screen.size = finfo.smem_len;
screen.position = 0;
screen.depth = vinfo.bits_per_pixel;
screen.byte = screen.depth / 8;
if(!(dblbuff = (char *) calloc(1, screen.size)))
diep("[-] malloc");
printf("[+] screen initialized: %dx%d, %d bpp\n", screen.width, screen.height, screen.depth);
printf("[+] screen buffer: %ld ko\n", screen.size / 1024);
//
// clear screen
//
fill(&screen, &pxl);
//
// initialize file
//
images[0] = decode("/tmp/process.png");
images[1] = decode("/tmp/process2.png");
//
// rendering
//
/*
for(id = 0; id < sizeof(images) / sizeof(png_t *); id++) {
printf("[+] rendering: image %u\n", id);
bufferise(images[id], dblbuff);
// commit new buffer
printf("[+] committing buffer\n");
memcpy(screen.buffer, dblbuff, screen.size);
}
*/
float iteration = 100;
for(id = 0; id <= iteration; id++) {
printf("[+] rendering: pass %u\n", id);
fade(images[0], images[1], id / iteration, &screen, screen.buffer);
// commit new buffer
// printf("[+] committing buffer\n");
// memcpy(screen.buffer, dblbuff, screen.size);
}
//
// clearing
//
munmap(fbp, screensize);
close(fbfd);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment