/*
*
* Name: ppm2sfimg.c
*
* Purpose: conversion of PPM to SFImage
*
* Created: 20 Oct 95 Michael Pichler
*
* Changed: 20 Oct 95 Michael Pichler
*
*/
/*
*
* This program reads a PPM file (raw format) and writes out a
* Texture2 SFImage with 3 components (RGB)
*
* The usual disclaimer applies (see VRweb's COPYRIGHT notice)
*
* Compile this program with any Ansi-C compiler.
* E.g.: gcc -O -Wall -o ppm2sfimg ppm2sfimg.c
*
* Please send further questions to
[email protected]
*
*/
#include <stdio.h>
#include <stdlib.h>
/* define this to dump input and output data to stderr */
/*#define DEBUGOUTPUT*/
#define USAGE "\nusage: ppm2sfimg [ppmfile] [> outputfile]\n" \
"ppmfile ... PPM raw file (default: stdin)\n" \
"output (RGB Texture2 image) is written to stdout\n\n"
typedef struct
{ unsigned char R, G, B;
} colorRGBi;
int sourceRows = 0;
int sourceCols = 0;
int maxColor = 0;
colorRGBi** sourcePPM = 0; /* source pixel */
void readSourcePPM (FILE*);
void writeSFImage (); /* to stdout */
/* tiny helper */
void checkformem (void* p)
{ if (!p)
{ fprintf (stderr, "fatal error: out of memory\n");
exit (2);
}
}
/***** main *****/
void main (int argc, char* argv[])
{
FILE* file;
if (argc > 2)
{ fprintf (stderr, USAGE);
exit (0);
}
if (argc > 1)
{
const char* filename = argv [1];
file = fopen (filename, "rb");
if (!file)
{ fprintf (stderr, "ssppm. error: could not open file '%s'" USAGE, filename);
exit (1);
}
}
else
file = stdin;
readSourcePPM (file);
fclose (file);
writeSFImage ();
} /* main */
/*** skipComment ***/
/* skip comment lines (beginning with '#') and empty lines */
void skipComment (FILE* file)
{
for (;;)
{
int chr = getc (file);
switch (chr)
{
case '#': /* skip comment line */
{
int c;
while ((c = getc (file)) != '\n' && c != EOF);
}
break;
case '\n':
break;
case EOF: /* end of file */
return;
default: /* data line */
ungetc (chr, file);
return;
}
} /* for */
} /* skipComment */
/***** readSourcePPM *****/
/* reads source PPM file (raw bits P6) */
void readSourcePPM (FILE* file)
{
int error, nextchar, row;
skipComment (file);
if (getc (file) != 'P' || getc (file) != '6')
{
fprintf (stderr, "ppm2sfimg. sorry, only able to deal with binary PPM files (header P6)\n");
exit (1);
}
skipComment (file);
error = fscanf (file, "%d", &sourceCols) != 1;
skipComment (file);
error = error || fscanf (file, "%d", &sourceRows) != 1;
skipComment (file);
error = error || fscanf (file, "%d", &maxColor) != 1 || !maxColor;
nextchar = getc (file); /* eat (exactly) one WS */
error = error || (nextchar != '\n' && nextchar != ' ' && nextchar != '\t');
if (error)
{ fprintf (stderr, "syntax error in PPM header - expected format:\n"
"'P5 width height maxcolor' followed by one whitespace and pixel bytes\n");
exit (1);
}
fprintf (stderr, "reading PPM of size %d x %d with RGB triples in range [0..%d].\n",
sourceCols, sourceRows, maxColor);
sourcePPM = (colorRGBi**) calloc (sourceRows, sizeof (colorRGBi*));
checkformem (sourcePPM);
for (row = 0; row < sourceRows; row++)
{
int col;
colorRGBi* thisrow = sourcePPM [row] = (colorRGBi*) calloc (sourceCols, sizeof (colorRGBi));
checkformem (thisrow);
for (col = 0; col < sourceCols; col++)
{
int pixelval = getc (file);
if (pixelval == EOF)
{ fprintf (stderr, "unexpected EOF on reading PGM file.");
exit (1);
}
thisrow->R = pixelval;
thisrow->G = getc (file);
thisrow->B = getc (file);
thisrow++;
} /* for each col */
} /* for each row */
/* for testing purposes: dump data to stderr */
#ifdef DEBUGOUTPUT
fprintf (stderr, "- input data -\n");
for (row = 0; row < sourceRows; row++)
{ for (int col = 0; col < sourceCols; col++)
{
const colorRGBi* pixel = sourcePPM [row][col];
fprintf (stderr, "(%3d, %3d, %3d) ", pixel->R, pixel->G, pixel->B);
}
fprintf (stderr, "\n");
}
fprintf (sderr, "- end of input data -\n");
#endif
} /* readSourcePGM */
/***** writeSFImage *****/
/* write SFImage data to stdout */
void writeSFImage ()
{
int row, col;
unsigned long value;
if (!sourcePPM)
return;
printf ("Texture2 { # created with ppm2sfimg\n");
printf ("\timage %d %d 3\n", sourceCols, sourceRows); /* 3 components (RGB) */
if (maxColor != 255)
{ fprintf (stderr, "ppm2sfimg. error: sorry, assuming color range of 0..255\n");
exit (1); /* just a scale in loop below, TODO */
}
row = sourceRows;
while (row--) /* bottom to top */
{
const colorRGBi* thisrow = sourcePPM [row];
printf ("\t");
col = sourceCols;
while (col--)
{
value = ((long) thisrow->R << 16) | ((int) thisrow->G << 8) | thisrow->B;
if (thisrow->R) /* hex representation (better readable) */
printf ("0x%lx ", value);
else /* decimal (shorter up to 999999) */
printf ("%ld ", value);
thisrow++;
} /* for each col */
printf ("\n");
} /* for each row */
printf ("}\n"); /* Texture2 image */
} /* writeDestinationPPM */