/* pbmio
 * 
 * Routines for reading and writing the standad PBM image format in ASCII
 *
 * Jerod Weinman
 * 9 Jun 2008
 */

#include "pbmio.h"
#include <stdio.h>
#include <string.h>
#include <pbm.h>
#include <assert.h>

/* Read a pbm file from disk.
 *
 * If there is any failure, an error is printed to STDERR and a
 * negative value is returned. Otherwise zero is returned and the
 * pbm_t is filled in. 
 *
 * Uses libnetpbm function that may cause program abort upon
 * failure.
 */

int pbmread( const char* file, pbm_t *im)
{

     FILE *imfp;   /* File stream for image file */
     bit **imbits; /* Pointer to loaded image data */
     
     assert( im != NULL);
     
     imfp = fopen(file, "r"); /* Open file for reading */

     if (imfp == NULL)
     {
          perror("Unable to open file");
          return -1;
     }

     imbits = pbm_readpbm(imfp, &im->cols, &im->rows); /* libnetpbm call */

     im->bits = imbits;  /* Set image data */

     fclose(imfp);

     return 0;
}

/* Write a pbm file to disk.
 *
 * If there is any failure, an error is printed to STDERR and a
 * negative value is returned. Otherwise zero is returned and the
 * pbm_t  is filled in. 
 *
 * Uses libnetpbm function that may cause program abort upon
 * failure.
 */

int pbmwrite( const char* file, pbm_t *im)
{
     FILE *imfp;  /* File stream for image file */

     assert( im != NULL);
     
     imfp = fopen(file, "w"); /* Open file for reading */

     if (imfp == NULL)
     {
          perror("Unable to open file");
          return -1;
     }

     pbm_writepbm(imfp, im->bits, im->cols, im->rows, 0); /* libnetpbm call */

     return 0;
}


/* Allocate memory for the pbm_t  */
int pbmalloc(pbm_t *im, int rows, int cols)
{
     bit **bits;

     bits = malloc( rows * sizeof(bit*) );

     if (bits==NULL)
     {
       fprintf(stderr,"Unable to allocate space for image.");
       return -1;
     }

     int i;

     for (i=0 ; i<rows ; i++)
     {
          bits[i] = malloc( cols * sizeof(bit) );

          if (bits[i]==NULL)
          {
               fprintf(stderr,"Unable to allocate space for image.");
               return -1;
               /* We fail to free the already-allocated memory. */
          }
     }

     im->bits = bits;
     im->rows = rows;
     im->cols = cols;

     return 0;
}

/* Free a pbm structure */
void pbmfree (pbm_t *im)
{
     int i;
     for (i=0 ; i < im->rows ; i++)
          free(im->bits[i]);

     free(im->bits);
}

/* Copy the data from one pbm_t to another.
 * Assumes the buffers are the same size */
int pbmcopy( pbm_t *dst, const pbm_t *src)
{
     
     if (dst->rows != src->rows || dst->cols != src->cols )
         
     {
          fprintf(stderr,"Image buffers must be the same size to copy");
          return -1;
     }
     
     int i;
     for (i=0; i < dst->rows ; i++)
     {
          memcpy(dst->bits[i],src->bits[i], src->cols * sizeof(bit) );
     }

     return 0;
}
