fix crash, and improve makefile
[7seg/.git] / shit.c
1 #include <stdlib.h>
2 #include <unistd.h>
3 #include <stdio.h>
4 #include <stdint.h>
5 #include <fcntl.h>
6 #include <linux/fb.h>
7 #include <sys/mman.h>
8 #include <sys/ioctl.h>
9 #include <assert.h>
10 #include <png.h>
11
12 #define MIN(x, y) ((x) < (y) ? (x) : (y))
13 #define MAX(x, y) ((x) > (y) ? (x) : (y))
14
15 int main(int argc, char** argv)
16 {
17     int fbfd = 0;
18     struct fb_var_screeninfo vinfo;
19     struct fb_fix_screeninfo finfo;
20     long int screensize = 0;
21     char *fbp = 0;
22     long int location = 0;
23     if (argc < 2) {
24       perror("Error: need a png to shit");
25       return 1;
26     }
27     FILE * fp = fopen(argv[1], "rb");
28     if (!fp) {
29       perror("Error: need a valid png to shit");
30       perror(argv[1]);
31       return 1;
32     }
33     png_structp png_ptr = png_create_read_struct( PNG_LIBPNG_VER_STRING, NULL,
34         NULL, NULL);;
35     if (!png_ptr) {
36       perror("THAT SHIT CRAY");
37       exit(1);
38     }
39     png_infop info_ptr = png_create_info_struct(png_ptr);
40     if (!info_ptr) {
41       perror("THAT SHIT CRAY");
42       exit(1);
43     }
44     png_init_io(png_ptr, fp);
45     png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);
46     png_bytepp row_pointers = png_get_rows(png_ptr, info_ptr);
47
48     // Open the file for reading and writing
49     fbfd = open("/dev/fb0", O_RDWR);
50     if (fbfd == -1) {
51         perror("Error: cannot open framebuffer device");
52         exit(1);
53     }
54     printf("The framebuffer device was opened successfully.\n");
55
56     // Get fixed screen information
57     if (ioctl(fbfd, FBIOGET_FSCREENINFO, &finfo) == -1) {
58         perror("Error reading fixed information");
59         exit(2);
60     }
61
62     // Get variable screen information
63     if (ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo) == -1) {
64         perror("Error reading variable information");
65         exit(3);
66     }
67
68     printf("%dx%d, %dbpp\n", vinfo.xres, vinfo.yres, vinfo.bits_per_pixel);
69
70     // Figure out the size of the screen in bytes
71     screensize = vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8;
72
73     // Map the device to memory
74     fbp = (char *)mmap(0, screensize, PROT_READ | PROT_WRITE, MAP_SHARED, fbfd, 0);
75     if ((int)fbp == -1) {
76         perror("Error: failed to map framebuffer device to memory");
77         exit(4);
78     }
79     printf("The framebuffer device was mapped to memory successfully.\n");
80     uint8_t channels = png_get_channels(png_ptr, info_ptr);
81
82     printf("png # of channels: %d\n", channels);
83
84     // dump this shit to a framebuffer nigga
85     assert(vinfo.bits_per_pixel == 32);
86     for (int y = 0; y < MIN(info_ptr->height, vinfo.yres-2); ++y) {
87       for (int x = 0; x < MIN(info_ptr->width, channels*vinfo.xres); ++x) {
88         assert(x*y*3 < channels*screensize);
89         location = (x+vinfo.xoffset) * (vinfo.bits_per_pixel/8) +
90                     (y+vinfo.yoffset) * finfo.line_length;
91
92         if (channels == 3 || channels == 4) {
93           *(fbp + location) = row_pointers[y][channels*x+2]; // BLUE
94           *(fbp + location + 1) = row_pointers[y][(channels*x)+1]; // GREEN
95           *(fbp + location + 2) = row_pointers[y][(channels*x)+0]; // RED
96         } else if (channels == 1) {
97           *(fbp + location) = row_pointers[y][x]; // BLUE
98           *(fbp + location + 1) = row_pointers[y][x]; // GREEN
99           *(fbp + location + 2) = row_pointers[y][x]; // RED
100         }
101         *(fbp + location + 3) = 0;      // No transparency
102       }
103     }
104     munmap(fbp, screensize);
105     close(fbfd);
106     fclose(fp);
107     return 0;
108 }