Created
June 19, 2015 00:59
-
-
Save maxux/5c79862795e9b681d385 to your computer and use it in GitHub Desktop.
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 <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