view lunalcd/ppmtocmd.c @ 99:2e35070d289f

fc-simtool: savebin command implemented
author Mychaela Falconia <falcon@freecalypso.org>
date Mon, 25 Jan 2021 00:14:19 +0000
parents 09d26f19a2c2
children
line wrap: on
line source

#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);
}