www.pudn.com > ilib > IPPM.c


/*
 * IPPMC.c
 *
 * Image library
 *
 * Description:
 *	PPM/PGM routines.  PPM is 24-bit color.  PGM is 8-bit grayscale.
 *	If someone asks to write a color image to PGM, it will be written
 *	as PPM.
 *
 * History:
 *	23-Jul-99	Craig Knudsen	cknudsen@radix.net
 *			Added support for reading PGM.
 *	20-May-96	Craig Knudsen	cknudsen@radix.net
 *			Created
 *
 ****************************************************************************/

#include 
#include 
#include 
#include 

#include "Ilib.h"
#include "IlibP.h"


IError _IWritePPM ( fp, image, options )
FILE *fp;
IImageP *image;
IOptions options;
{
  int r, c;
  unsigned char *ptr;
  unsigned int red, green, blue;

  if ( options & IOPTION_ASCII ) {
    fprintf ( fp, "P3\n" );
    if ( image->comments )
      fprintf ( fp, "# %s\n", image->comments );
    fprintf ( fp, "%d %d\n255\n", image->width, image->height );
    for ( r = 0; r < image->height; r++ ) {
      for ( c = 0; c < image->width; c++ ) {
        if ( image->greyscale ) {
          ptr = image->data + ( r * image->width ) + c;
          red = green = blue = (unsigned int) *ptr;
        }
        else {
          ptr = image->data + ( r * image->width * 3 ) + ( c * 3 );
          red = (unsigned int) *ptr;
          green = (unsigned int) *( ptr + 1 );
          blue = (unsigned int) *( ptr + 2 );
        }
        fprintf ( fp, "%d %d %d\n", red, green, blue );
      }
    }
  }
  else {
    /* we could write PPM for greyscale, but right PGM since its 1/3 size */
    if ( image->greyscale ) {
      fprintf ( fp, "P5\n" );
      if ( image->comments )
        fprintf ( fp, "# %s\n", image->comments );
      fprintf ( fp, "%d %d\n255\n", image->width, image->height );
      if ( fwrite ( image->data, 1, image->width * image->height, fp ) <= 0 )
        return ( IErrorWriting );
    } else {
      fprintf ( fp, "P6\n" );
      if ( image->comments )
        fprintf ( fp, "# %s\n", image->comments );
      fprintf ( fp, "%d %d\n255\n", image->width, image->height );
      if ( fwrite ( image->data, 3, image->width * image->height, fp ) <= 0 )
        return ( IErrorWriting );
     }
  }

  return ( INoError );
}





IError _IReadPPM ( fp, options, image_return )
FILE *fp;
IOptions options;
IImageP **image_return;
{
  char data[1024];
  IImageP *image;
  int w, h;
  int i;
  unsigned int temp;
  unsigned char *ptr;
  char *p;
  char *comments = NULL;
  int maxcolors = 255;
  int greyscale = 0;

  fgets ( data, 1024, fp );
  if ( strncmp ( data, "P5", 2 ) == 0 ) {
    greyscale = 1;
    options |= IOPTION_GREYSCALE;
  } else if ( strncmp ( data, "P6", 2 ) )
    return ( IFileInvalid );

  fgets ( data, 1024, fp );
  while ( data[0] == '#' ) {
    if ( comments == NULL ) {
      for ( p = data + 1; *p != ' ' && *p != '\0'; p++) ;
      if ( strlen ( p ) ) {
        comments = (char *) malloc ( strlen ( p ) + 1 );
        strcpy ( comments, p );
      }
    }
    fgets ( data, 1024, fp );
  }
  /* should now contain width and height */
  if ( sscanf ( data, "%d %d", &w, &h ) != 2 )
    return ( IFileInvalid );
  fgets ( data, 1024, fp );
  while ( data[0] == '#' )
    fgets ( data, 1024, fp );
  /* should now contain maxcolor value */
  if ( sscanf ( data, "%d", &maxcolors ) != 1 )
    return ( IFileInvalid );

  image = (IImageP *) ICreateImage ( w, h, options );
  if ( comments )
    image->comments = comments;
  else {
    image->comments = (char *) malloc ( strlen ( IDEFAULT_COMMENT ) + 1 );
    strcpy ( image->comments, IDEFAULT_COMMENT );
  }

  if ( greyscale )
    fread ( image->data, 1, w * h, fp );
  else
    fread ( image->data, 1, w * h * 3, fp );

  /* Normalize to 255 if not already */
  if ( maxcolors != 255 ) {
    for ( i = 0; i < ( w * h * 3 ); i++ ) {
      ptr = image->data + i;
      temp = *ptr;
      temp = 255 * temp / maxcolors;
      *ptr = (unsigned char) temp;
    }
  }
  
  *image_return = image;

  return ( INoError );
}