diff lcdtest/showppm.c @ 17:43cc53581975

lcdtest: PPM image display implemented
author Mychaela Falconia <falcon@freecalypso.org>
date Sat, 07 Apr 2018 21:57:54 +0000
parents
children f3671d3ad953
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lcdtest/showppm.c	Sat Apr 07 21:57:54 2018 +0000
@@ -0,0 +1,168 @@
+#include <stdio.h>
+#include <ctype.h>
+#include <stdlib.h>
+
+char *ppm_filename;
+FILE *ppmfile;
+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;
+}
+
+cmd_show(argc, argv)
+	char **argv;
+{
+	int rc;
+	unsigned n;
+
+	ppm_filename = argv[1];
+	ppmfile = fopen(ppm_filename, "r");
+	if (!ppmfile) {
+		perror(ppm_filename);
+		return(-1);
+	}
+	rc = ppm_read_header();
+	if (rc < 0) {
+		fclose(ppmfile);
+		return(-1);
+	}
+	write_ir(0x20);
+	write_dr(0);
+	write_ir(0x21);
+	write_dr(0);
+	write_ir(0x22);
+	for (n = 0; n < 176*220; n++) {
+		rc = ppm_get_rgb();
+		if (rc < 0) {
+			fclose(ppmfile);
+			return(-1);
+		}
+		write_dr(rc);
+	}
+	fclose(ppmfile);
+	return(0);
+}