changeset 69:1e6f05ede5ca

lunalcd: ppmtoimg utility added
author Mychaela Falconia <falcon@freecalypso.org>
date Thu, 07 May 2020 00:12:54 +0000
parents 72ff023ec6c9
children b1b027efce8e
files .hgignore lunalcd/Makefile lunalcd/ppmtoimg.c
diffstat 3 files changed, 182 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/.hgignore	Fri May 01 03:18:08 2020 +0000
+++ b/.hgignore	Thu May 07 00:12:54 2020 +0000
@@ -20,3 +20,4 @@
 ^lunalcd/gen-ht-init$
 ^lunalcd/gen-st-init$
 ^lunalcd/ppmtocmd$
+^lunalcd/ppmtoimg$
--- a/lunalcd/Makefile	Fri May 01 03:18:08 2020 +0000
+++ b/lunalcd/Makefile	Thu May 07 00:12:54 2020 +0000
@@ -1,6 +1,6 @@
 CC=	gcc
 CFLAGS=	-O2
-PROGS=	gen-ht-init gen-st-init ppmtocmd
+PROGS=	gen-ht-init gen-st-init ppmtocmd ppmtoimg
 
 HTINIT_OBJS=	common.o initmain.o haoran.o
 STINIT_OBJS=	common.o initmain.o startek.o
@@ -17,5 +17,8 @@
 ppmtocmd:	${PPMCONV_OBJS}
 	${CC} -o $@ ${PPMCONV_OBJS}
 
+ppmtoimg:	ppmtoimg.c
+	${CC} ${CFLAGS} -o $@ $@.c
+
 clean:
 	rm -f ${PROGS} *.o
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lunalcd/ppmtoimg.c	Thu May 07 00:12:54 2020 +0000
@@ -0,0 +1,177 @@
+/*
+ * This program converts a 176x220 pixel wallpaper image from PPM format
+ * into a raw binary image file that will be written into an ad hoc flash
+ * location with fc-loadtool; these images will then be displayed on our
+ * Luna LCD by a standalone target-utils program.
+ */
+
+#include <stdio.h>
+#include <ctype.h>
+#include <stdlib.h>
+
+static char *ppm_filename;
+static FILE *ppmfile;
+static int ppm_is_ascii;	/* P3 format instead of P6 */
+
+/*
+ * This function reads one ASCII-encoded integer from a PPM file.
+ * It handles the white space and comment rules of the PPM format.
+ */
+static int
+ppm_get_ascii_number()
+{
+	int accum, c;
+
+	do {
+		c = getc(ppmfile);
+		if (c < 0) {
+badeof:			fprintf(stderr, "%s: unexpected EOF\n", ppm_filename);
+			return(-1);
+		}
+		if (c == '#') {
+			do
+				c = getc(ppmfile);
+			while (c >= 0 && c != '\n');
+			if (c != '\n')
+				goto badeof;
+		}
+	} while (isspace(c));
+	if (!isdigit(c)) {
+		fprintf(stderr,
+			"%s: unexpected data where a number was expected\n",
+			ppm_filename);
+		return(-1);
+	}
+	for (accum = c - '0'; ; ) {
+		c = getc(ppmfile);
+		if (c < 0 || isspace(c))
+			break;
+		if (!isdigit(c)) {
+			fprintf(stderr,
+				"%s: bad character in the middle of a number\n",
+				ppm_filename);
+			return(-1);
+		}
+		accum = accum * 10 + c - '0';
+	}
+	return accum;
+}
+
+/*
+ * This function reads and parses the PPM header of our input file.
+ */
+static int
+ppm_read_header()
+{
+	int magic1, magic2;
+	int rd;
+
+	magic1 = getc(ppmfile);
+	magic2 = getc(ppmfile);
+	if (magic1 == 'P' && magic2 == '3')
+		ppm_is_ascii = 1;
+	else if (magic1 == 'P' && magic2 == '6')
+		ppm_is_ascii = 0;
+	else {
+		fprintf(stderr, "%s: P3 or P6 format expected\n", ppm_filename);
+		return(-1);
+	}
+	rd = ppm_get_ascii_number();
+	if (rd < 0)
+		return(-1);
+	if (rd != 176) {
+		fprintf(stderr, "%s: width is not 176\n", ppm_filename);
+		return(-1);
+	}
+	rd = ppm_get_ascii_number();
+	if (rd < 0)
+		return(-1);
+	if (rd != 220) {
+		fprintf(stderr, "%s: height is not 220\n", ppm_filename);
+		return(-1);
+	}
+	rd = ppm_get_ascii_number();
+	if (rd < 0)
+		return(-1);
+	if (rd != 255) {
+		fprintf(stderr, "%s: maxval is not 255\n", ppm_filename);
+		return(-1);
+	}
+	return(0);
+}
+
+/*
+ * This function reads a single R, G or B value from a PPM file.
+ */
+static int
+ppm_get_pixval()
+{
+	int c;
+
+	if (ppm_is_ascii)
+		return ppm_get_ascii_number();
+	c = getc(ppmfile);
+	if (c < 0) {
+		fprintf(stderr, "%s: EOF while reading binary pixel data\n",
+			ppm_filename);
+		return(-1);
+	}
+	return c;
+}
+
+static int
+ppm_get_rgb()
+{
+	int r, g, b;
+
+	r = ppm_get_pixval();
+	if (r < 0)
+		return(-1);
+	g = ppm_get_pixval();
+	if (g < 0)
+		return(-1);
+	b = ppm_get_pixval();
+	if (b < 0)
+		return(-1);
+	/* convert to 5:6:5 */
+	r >>= 3;
+	g >>= 2;
+	b >>= 3;
+	return (r << 11) | (g << 5) | b;
+}
+
+main(argc, argv)
+	char **argv;
+{
+	FILE *of;
+	int rc;
+	unsigned n;
+
+	if (argc != 3) {
+		fprintf(stderr, "usage: %s ppmfile binfile\n", argv[0]);
+		exit(1);
+	}
+	ppm_filename = argv[1];
+	ppmfile = fopen(ppm_filename, "r");
+	if (!ppmfile) {
+		perror(ppm_filename);
+		exit(1);
+	}
+	rc = ppm_read_header();
+	if (rc < 0)
+		exit(1);
+	of = fopen(argv[2], "w");
+	if (!of) {
+		perror(argv[2]);
+		exit(1);
+	}
+	for (n = 0; n < 176*220; n++) {
+		rc = ppm_get_rgb();
+		if (rc < 0)
+			exit(1);
+		putc(rc & 0xFF, of);
+		putc(rc >> 8, of);
+	}
+	fclose(of);
+	exit(0);
+}