// read/write PPM (Portable Pixel Map) files
//
// assumes 8-bit data with max 255
//
#include <stdio.h>
#include <stdlib.h>
#include "ppm.h"

// print error message and exit
//
static void error( const char *msg)
{
  fprintf( stderr, "ppm: %s\n", msg);
  exit(1);
}

// create a 2D array of unsigned char
//
static unsigned char **amalloc( int rows, int cols)
{
  unsigned char **a;

  if( (a = malloc( rows*sizeof(char*))) == NULL ||
    (a[0] = malloc( rows*cols)) == NULL)
      error( "malloc failed.");

  for( int i = 1; i < rows; ++i) // set the row pointers
   a[i] = a[i-1] + cols;

  return a;
}

// create a new ppm structure
//
// initializes the ppm rows and cols fields,
// allocates but does not initialize the RGB data fields
//
ppm ppm_new( int rows, int cols)
{
  ppm p;

  p.rows = rows;
  p.cols = cols;

  p.r = amalloc( rows, cols);
  p.g = amalloc( rows, cols);
  p.b = amalloc( rows, cols);

  return p;
}

// read PPM data from stdin
//
ppm ppm_read( void)
{
  ppm p;  int rows, cols, max, r,g,b;

  if( getchar() != 'P' || getchar() != '6')
    error( "input is not P6 PPM format");

  if( scanf( "%i%i%i", &cols, &rows, &max) != 3)
   error( "scanf() failed.");

  getchar(); // skip newline

  p = ppm_new( rows, cols);

  for( int i = 0; i < p.rows; ++i)
    for( int j = 0; j < p.cols; ++j)
    {
      r = getchar(); g = getchar(); b = getchar();
      if( b < 0) error( "getchar() failed.");
      p.r[i][j] = r; p.g[i][j] = g; p.b[i][j] = b;
    }

  return p;
}

// write PPM data to stdout
//
void ppm_write( ppm p)
{
  printf( "P6 %i %i 255\n", p.cols, p.rows);

  for( int i = 0; i < p.rows; ++i)
    for( int j = 0; j < p.cols; ++j)
    {
      putchar( p.r[i][j]);
      putchar( p.g[i][j]);
      putchar( p.b[i][j]);
    }
}