view lunalcd/ppmtoimg.c @ 163:5f9dd4056420

vbat-adc/crude-cal-test: an experiment to prove VBAT MADC linearity
author Mychaela Falconia <falcon@freecalypso.org>
date Fri, 04 Jun 2021 03:02:18 +0000
parents 1e6f05ede5ca
children
line wrap: on
line source

/*
 * 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);
}