// Very unfinished application that can view images and set the // wallpaper. It only supports ppm3 and ppm6 files. #include #include #include #include #include #include #include GUI_Window *global_w; struct PPM_IMAGE { uint8_t version; uint32_t width; uint32_t height; uint32_t maxval; long file_location; }; int parse_ppm_header(FILE *fp, struct PPM_IMAGE *img) { char magic[3]; int width; int height; int maxval; // TODO: Use %2s when scanf supports that char c1; char c2; fscanf(fp, "%c%c\n%d %d\n%d", &c1, &c2, &width, &height, &maxval); if ('P' != c1) return 0; if (!isdigit(c2)) return 0; img->version = c2 - '0'; if (3 != img->version && 6 != img->version) return 0; if (maxval > 255) { printf("maxval is: %d\n", maxval); return 0; } img->width = width; img->height = height; img->maxval = maxval; img->file_location = ftell(fp); printf("width: %d\n", img->width); printf("height: %d\n", img->height); return 1; } inline uint32_t low_32_reverse(uint32_t _value) { return (((_value & 0x000000FF) << 24) | ((_value & 0x0000FF00) << 8) | ((_value & 0x00FF0000) >> 8)); } int load_ppm6_file(FILE *fp, const struct PPM_IMAGE *img, uint32_t buf_width, uint32_t buf_height, uint32_t *buffer) { fseek(fp, img->file_location, SEEK_SET); const uint8_t modifier = 255 / img->maxval; int cx = 0; int cy = 0; const int n_pixels = img->width * img->height; printf("malloc\n"); uint8_t *rgb = malloc(3 * n_pixels); printf("end malloc\n"); printf("fread"); const int rc = fread(rgb, 3, n_pixels, fp); if (0 == rc) return 0; printf("end fread"); uint32_t *p = rgb; u32 buf_size = buf_height * buf_width; if (1 == modifier) { for (int i = 0; i < rc && i < buf_size; i++, p = ((uint8_t *)p) + 3) { if (cx > buf_width) { i--; } else { uint32_t v = *p; buffer[cy * buf_width + cx] = ((v & 0xFF) << 16) | ((v & 0xFF00)) | ((v & 0xFF0000) >> 16); } cx++; if (cx == img->width) { cx = 0; cy++; i--; continue; } } } else { for (int i = 0; i < rc && i < buf_size; i++, p = ((uint8_t *)p) + 3) { ((uint8_t *)p)[0] *= modifier; ((uint8_t *)p)[1] *= modifier; ((uint8_t *)p)[2] *= modifier; if (cx > buf_width) { i--; } else { uint32_t v = *p; buffer[cy * buf_width + cx] = ((v & 0xFF) << 16) | ((v & 0xFF00)) | ((v & 0xFF0000) >> 16); } cx++; if (cx == img->width) { cx = 0; cy++; i--; continue; } } } return 1; } int load_ppm3_file(FILE *fp, const struct PPM_IMAGE *img, uint32_t buf_width, uint32_t buf_height, uint32_t *buffer) { fseek(fp, img->file_location, SEEK_SET); uint8_t modifier = 255 / img->maxval; int cx = 0; int cy = 0; for (int i = 0; i < img->width * img->height; i++) { int red; int green; int blue; int rc = fscanf(fp, "%d %d %d", &red, &green, &blue); if (0 == rc) break; red &= 0xFF; green &= 0xFF; blue &= 0xFF; red *= modifier; green *= modifier; blue *= modifier; if (3 != rc) { printf("not 3: %d\n", rc); return 0; } buffer[cy * buf_width + cx] = (red << 8 * 2) | (green << 8 * 1) | (blue << 8 * 0); cx++; if (cx == img->width) { cx = 0; cy++; continue; } } return 1; } int load_ppm_file(FILE *fp, const struct PPM_IMAGE *img, uint32_t buf_width, uint32_t buf_height, uint32_t *buffer) { if (3 == img->version) return load_ppm3_file(fp, img, buf_width, buf_height, buffer); else if (6 == img->version) return load_ppm6_file(fp, img, buf_width, buf_height, buffer); return 0; } struct DISPLAY_INFO { uint32_t width; uint32_t height; uint8_t bpp; }; int main(int argc, char **argv) { if (argc < 2) { printf("provide command line arguments dumbass\n"); return 1; } argv++; int set_wallpaper = 0; // Parse commandline arguments(shitty) if (0 == strcmp(*argv, "-w")) { set_wallpaper = 1; argv++; } const char *file = *argv; struct PPM_IMAGE img; FILE *fp = fopen(file, "rb"); assert(fp); assert(parse_ppm_header(fp, &img)); if (!set_wallpaper) { global_w = GUI_CreateWindow(80, 80, img.width, img.height); assert(global_w); assert( load_ppm_file(fp, &img, img.width, img.height, global_w->bitmap_ptr)); GUI_UpdateWindow(global_w); fclose(fp); GUI_EventLoop(global_w, NULL); } else { int wallpaper_fd = shm_open("wallpaper", O_RDWR, 0); assert(wallpaper_fd >= 0); struct DISPLAY_INFO inf; int fd = open("/dev/display_info", O_READ, 0); assert(fd >= 0); assert(sizeof(inf) == read(fd, &inf, sizeof(inf))); void *rc = mmap(NULL, inf.width * inf.height * sizeof(uint32_t), 0, 0, wallpaper_fd, 0); assert(rc); assert(load_ppm_file(fp, &img, inf.width, inf.height, rc)); close(fd); } return 0; }