From 080978ade0464da28a0119f0ce0c71e4a1e47bd1 Mon Sep 17 00:00:00 2001 From: Werner Almesberger Date: Thu, 28 Apr 2011 00:38:13 -0300 Subject: [PATCH] ubb-vga2: added support for showing a PPM image - Makefile (OBJS): added ppm.o and ppmimg.o - ppm.h (load_ppm), ppm.c: PPM file loader, adapted from eda-tools/schhist/ppmdiff/ppmdiff.c - ubb-vga.h (img_name, ppmimg), ppmimg.c: PPM image to frame buffer converter - ubb-vga2.c (usage, main): the threshold is now set with the option -l - ubb-vga2.c (usage, main): if a second argument is given, treat it as a PPM file - ubb-vga2.c (usage): also documented option -t --- ubb-vga/Makefile | 2 +- ubb-vga/ppm.c | 97 ++++++++++++++++++++++++++++++++++++++++++++++ ubb-vga/ppm.h | 23 +++++++++++ ubb-vga/ppmimg.c | 63 ++++++++++++++++++++++++++++++ ubb-vga/ubb-vga.h | 10 +++++ ubb-vga/ubb-vga2.c | 16 +++++--- 6 files changed, 205 insertions(+), 6 deletions(-) create mode 100644 ubb-vga/ppm.c create mode 100644 ubb-vga/ppm.h create mode 100644 ubb-vga/ppmimg.c diff --git a/ubb-vga/Makefile b/ubb-vga/Makefile index fe32285..1674f8a 100644 --- a/ubb-vga/Makefile +++ b/ubb-vga/Makefile @@ -3,7 +3,7 @@ CC=mipsel-linux-gcc CFLAGS=-Wall -g -O9 -march=mips32 LDFLAGS=-lm -OBJS=ubb-vga2.o grabfb.o tstimg.o +OBJS=ubb-vga2.o grabfb.o tstimg.o ppm.o ppmimg.o .PHONY: all asm sch clean spotless diff --git a/ubb-vga/ppm.c b/ubb-vga/ppm.c new file mode 100644 index 0000000..7fd5aca --- /dev/null +++ b/ubb-vga/ppm.c @@ -0,0 +1,97 @@ +/* + * ppm.c - Load a PPM image + * + * Written 2010-2011 by Werner Almesberger + * Copyright 2010-2011 Werner Almesberger + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + + +#include +#include +#include +#include + +#include "ppm.h" + + +static char *fgets_comment(char *line, int n, FILE *file) +{ + do { + if (!fgets(line, n, file)) + return NULL; + } + while (*line == '#'); + return line; +} + + +uint8_t *load_ppm(const char *name, int *x, int *y) +{ + FILE *file; + char line[100]; + int this_x, this_y, depth; + int n; + uint8_t *img; + + file = fopen(name, "r"); + if (!file) { + perror(name); + exit(1); + } + if (!fgets_comment(line, sizeof(line), file)) { + fprintf(stderr, "can't read file type\n"); + exit(1); + } + if (strcmp(line, "P6\n")) { + fprintf(stderr, "file type must be P6, not %s", line); + exit(1); + } + if (!fgets_comment(line, sizeof(line), file)) { + fprintf(stderr, "can't read resolution\n"); + exit(1); + } + if (sscanf(line, "%d %d", &this_x, &this_y) != 2) { + fprintf(stderr, "can't parse resolution: %s", line); + exit(1); + } + if (*x || *y) { + if (*x != this_x || *y != this_y) { + fprintf(stderr, + "resolution changed from %dx%d to %dx%d\n", + *x, *y, this_x, this_y); + exit(1); + } + } else { + *x = this_x; + *y = this_y; + } + if (!fgets_comment(line, sizeof(line), file)) { + fprintf(stderr, "can't read depth\n"); + exit(1); + } + if (sscanf(line, "%d", &depth) != 1) { + fprintf(stderr, "can't parse depth: %s", line); + exit(1); + } + if (depth != 255) { + fprintf(stderr, "depth must be 255, not %d\n", depth); + exit(1); + } + n = *x**y*3; + img = malloc(n); + if (!img) { + perror("malloc"); + exit(1); + } + if (fread(img, 1, n, file) != n) { + fprintf(stderr, "can't read %d bytes\n", n); + exit(1); + } + fclose(file); + return img; +} diff --git a/ubb-vga/ppm.h b/ubb-vga/ppm.h new file mode 100644 index 0000000..dd29bb1 --- /dev/null +++ b/ubb-vga/ppm.h @@ -0,0 +1,23 @@ +/* + * ppm.h - Load a PPM image + * + * Written 2011 by Werner Almesberger + * Copyright 2011 Werner Almesberger + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + + +#ifndef PPM_H +#define PPM_H + +#include + + +uint8_t *load_ppm(const char *name, int *x, int *y); + +#endif /* !PPM_H */ + diff --git a/ubb-vga/ppmimg.c b/ubb-vga/ppmimg.c new file mode 100644 index 0000000..d15f064 --- /dev/null +++ b/ubb-vga/ppmimg.c @@ -0,0 +1,63 @@ +/* + * ppmimg.c - Convert a PPM image + * + * Written 2011 by Werner Almesberger + * Copyright 2011 Werner Almesberger + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + + +#include +#include +#include + +#include "ppm.h" +#include "ubb-vga.h" + + +char *img_name; + + +static uint8_t pattern(int r, int g, int b) +{ + return ((r ? R_VAL : 0) | (g ? G_VAL : 0) | (b ? B_VAL : 0))*0x11; +} + + +static void convert(uint8_t *f, int xres, int yres, uint8_t *ppm) +{ + int x, y; + uint8_t v, last = 0; + + for (y = 0; y != yres; y++) + for (x = 0; x != xres; x++) { + v = pattern(ppm[0] >= thres, ppm[1] >= thres, + ppm[2] >= thres); + if (x & 1) { + *f++ = last | v; + } else { + last = v << 4; + } + ppm += 3; + } +} + + +void ppmimg(void *f, int xres, int yres) +{ + uint8_t *ppm; + int xr = 0, yr = 0; + + ppm = load_ppm(img_name, &xr, &yr); + if (xr != xres || yr != yres) { + fprintf(stderr, "image is %dx%d, display is %dx%d\n", + xr, yr, xres, yres); + exit(1); + } + convert(f, xres, yres, ppm); + free(ppm); +} diff --git a/ubb-vga/ubb-vga.h b/ubb-vga/ubb-vga.h index f2d7568..60e2cfe 100644 --- a/ubb-vga/ubb-vga.h +++ b/ubb-vga/ubb-vga.h @@ -26,10 +26,20 @@ void *map(off_t addr, size_t size); +/* grabfb.c */ + extern uint8_t thres; void grabfb(void *f, int xres, int yres); +/* tstimg.c */ + void tstimg(void *f, int xres, int yres); +/* ppmimg.c */ + +extern char *img_name; + +void ppmimg(void *f, int xres, int yres); + #endif /* !UBB_VGA_H */ diff --git a/ubb-vga/ubb-vga2.c b/ubb-vga/ubb-vga2.c index 1188f0f..3d836d7 100644 --- a/ubb-vga/ubb-vga2.c +++ b/ubb-vga/ubb-vga2.c @@ -410,9 +410,11 @@ static void session(void (*gen)(void *fb, int xres, int yres), int frames) static void usage(const char *name) { fprintf(stderr, -"usage: %s frames [threshold]\n\n" -" frames number of frames to display\n" -" threshold channel on/off threshold\n\n" +"usage: %s [-l threshold] [-t] frames [file]\n\n" +" frames number of frames to display\n" +" file PPM file\n\n" +" -l threshold channel on/off threshold\n" +" -t generate a test image\n" , name); exit(1); } @@ -424,8 +426,11 @@ int main(int argc, char *const *argv) int frames; int c; - while ((c = getopt(argc, argv, "t")) != EOF) + while ((c = getopt(argc, argv, "l:t")) != EOF) switch (c) { + case 'l': + thres = atoi(optarg); + break; case 't': gen = tstimg; break; @@ -435,7 +440,8 @@ int main(int argc, char *const *argv) switch (argc-optind) { case 2: - thres = atoi(argv[optind+1]); + img_name = argv[optind+1]; + gen = ppmimg; /* fall through */ case 1: frames = atoi(argv[optind]);