Created
June 18, 2015 21:44
-
-
Save maxux/786b2293bbf8c354f2d1 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> | |
#include <pthread.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 { | |
int red; | |
int green; | |
int blue; | |
int 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; | |
int i, j, x = 0; | |
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; j < fader->left->width; j++) { | |
pxl1.red = *(r1 + (j * 3) + 0); | |
pxl1.green = *(r1 + (j * 3) + 1); | |
pxl1.blue = *(r1 + (j * 3) + 2); | |
pxl2.red = *(r2 + (j * 3) + 0); | |
pxl2.green = *(r2 + (j * 3) + 1); | |
pxl2.blue = *(r2 + (j * 3) + 2); | |
fader->buffer[x++] = (pxl1.blue * factor + pxl2.blue * (1 - factor)); | |
fader->buffer[x++] = (pxl1.green * factor + pxl2.green * (1 - factor)); | |
fader->buffer[x++] = (pxl1.red * factor + pxl2.red * (1 - factor)); | |
} | |
} | |
// free own stuff | |
free(data); | |
return NULL; | |
} | |
void fade(png_t *left, png_t *right, float factor, screen_t *screen, char *buffer) { | |
fade_t *fader; | |
int units = 4, i; | |
pthread_t *thread; | |
printf("[+] fading (factor %.2f), with %d threads...\n", factor, units); | |
if(!(thread = (pthread_t *) malloc(sizeof(pthread_t) * units))) | |
diep("[-] malloc"); | |
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); | |
if(pthread_create(&thread[i], NULL, __fade, fader)) | |
diep("[-] pthread_create"); | |
} | |
for(i = 0; i < units; i++) | |
pthread_join(thread[i], NULL); | |
} | |
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 = 60; | |
for(id = 0; id <= iteration; id++) { | |
printf("[+] rendering: pass %u\n", id); | |
fade(images[0], images[1], id / iteration, &screen, dblbuff); | |
// 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