1
0
mirror of git://projects.qi-hardware.com/ben-blinkenlights.git synced 2024-06-28 22:21:06 +03:00

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
This commit is contained in:
Werner Almesberger 2011-04-28 00:38:13 -03:00
parent 19f43a77c9
commit 080978ade0
6 changed files with 205 additions and 6 deletions

View File

@ -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

97
ubb-vga/ppm.c Normal file
View File

@ -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 <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#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;
}

23
ubb-vga/ppm.h Normal file
View File

@ -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 <stdint.h>
uint8_t *load_ppm(const char *name, int *x, int *y);
#endif /* !PPM_H */

63
ubb-vga/ppmimg.c Normal file
View File

@ -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 <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#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);
}

View File

@ -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 */

View File

@ -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]);