changeset 66:09d26f19a2c2

lunalcd: ppmtocmd program written
author Mychaela Falconia <falcon@freecalypso.org>
date Thu, 19 Mar 2020 01:38:57 +0000
parents cdf2c99e5025
children 286289d551ee
files .hgignore lunalcd/Makefile lunalcd/ppmtocmd.c
diffstat 3 files changed, 175 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/.hgignore	Thu Mar 19 01:31:05 2020 +0000
+++ b/.hgignore	Thu Mar 19 01:38:57 2020 +0000
@@ -18,3 +18,4 @@
 ^lcdtest/lcdtest$
 
 ^lunalcd/gen-st-init$
+^lunalcd/ppmtocmd$
--- a/lunalcd/Makefile	Thu Mar 19 01:31:05 2020 +0000
+++ b/lunalcd/Makefile	Thu Mar 19 01:38:57 2020 +0000
@@ -1,13 +1,17 @@
 CC=	gcc
 CFLAGS=	-O2
-PROGS=	gen-st-init
+PROGS=	gen-st-init ppmtocmd
 
 STINIT_OBJS=	common.o initmain.o startek.o
+PPMCONV_OBJS=	common.o ppmtocmd.o
 
 all:	${PROGS}
 
 gen-st-init:	${STINIT_OBJS}
 	${CC} -o $@ ${STINIT_OBJS}
 
+ppmtocmd:	${PPMCONV_OBJS}
+	${CC} -o $@ ${PPMCONV_OBJS}
+
 clean:
 	rm -f ${PROGS} *.o
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lunalcd/ppmtocmd.c	Thu Mar 19 01:38:57 2020 +0000
@@ -0,0 +1,169 @@
+#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;
+{
+	int rc;
+	unsigned n;
+
+	if (argc != 3) {
+		fprintf(stderr, "usage: %s ppmfile output-mode\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);
+	set_output_mode(argv[2]);
+	write_ir(0x20);
+	write_dr(0);
+	write_ir(0x21);
+	write_dr(0);
+	write_ir(0x22);
+	bulk_wd_prep();
+	for (n = 0; n < 176*220; n++) {
+		rc = ppm_get_rgb();
+		if (rc < 0)
+			exit(1);
+		bulk_wd(rc);
+	}
+	exit(0);
+}