diff options
Diffstat (limited to 'userland/libppm')
| -rw-r--r-- | userland/libppm/.gitignore | 1 | ||||
| -rw-r--r-- | userland/libppm/Makefile | 15 | ||||
| -rw-r--r-- | userland/libppm/file.ppm | 7 | ||||
| -rw-r--r-- | userland/libppm/ppm.c | 199 | 
4 files changed, 222 insertions, 0 deletions
| diff --git a/userland/libppm/.gitignore b/userland/libppm/.gitignore new file mode 100644 index 0000000..2f046a8 --- /dev/null +++ b/userland/libppm/.gitignore @@ -0,0 +1 @@ +ppm diff --git a/userland/libppm/Makefile b/userland/libppm/Makefile new file mode 100644 index 0000000..405e1dd --- /dev/null +++ b/userland/libppm/Makefile @@ -0,0 +1,15 @@ +CC="i686-sb-gcc" +CFLAGS = -ggdb -O3 -Wall -Wextra -pedantic +LIB=-L../libgui -lgui +INC=-I../libgui/ +BINS=ppm +all: $(BINS) + +ppm.o: ppm.c +	$(CC) $(CFLAGS) $(INC) $(LIB) -o $@ -c $< + +ppm: ppm.o +	$(CC) $(CFLAGS) -o $@ $^ $(LIB) + +clean: +	rm $(BINS) *.o diff --git a/userland/libppm/file.ppm b/userland/libppm/file.ppm new file mode 100644 index 0000000..2925e2e --- /dev/null +++ b/userland/libppm/file.ppm @@ -0,0 +1,7 @@ +P3 +4 4 +15 + 0  0  0    0  0  0    0  0  0   15  0 15 + 0  0  0    0 15  7    0  0  0    0  0  0 + 0  0  0    0  0  0    0 15  7    0  0  0 +15  0 15    0  0  0    0  0  0    0  0  0 diff --git a/userland/libppm/ppm.c b/userland/libppm/ppm.c new file mode 100644 index 0000000..030c68d --- /dev/null +++ b/userland/libppm/ppm.c @@ -0,0 +1,199 @@ +// Very unfinished application that can view images and set the +// wallpaper. It only supports ppm3 and ppm6 files. +#include <assert.h> +#include <fcntl.h> +#include <libgui.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +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"); +  int rc = fread(rgb, 3, n_pixels, fp); +  if (0 == rc) +    return 0; +  printf("end fread"); + +  uint32_t *p = rgb; +  if (1 == modifier) { +    for (; rc--; p = ((uint8_t *)p) + 3) { +      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++; +        continue; +      } +    } +  } else { +    for (; rc--; p = ((uint8_t *)p) + 3) { +      ((uint8_t *)p)[0] *= modifier; +      ((uint8_t *)p)[1] *= modifier; +      ((uint8_t *)p)[2] *= modifier; +      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++; +        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; +} |