/* jspnm_image.h - uniform access to PGM and PPM images. */
/* Last edited on 2016-04-10 03:38:43 by stolfilocal */

#ifndef jspnm_image_H
#define jspnm_image_H

#include <jspnm.h>

/* Beware that the order of parameters is inconsitent: sometimes {chn,col,row},
   sometimes {col,row,chn}. */

typedef struct pnm_image_t
  { pnm_sample_t maxval;
    int cols;
    int rows;
    int chns;            /* Normally either 1 or 3. */
    pnm_sample_t **smp;  /* Rows of samples. */
  } pnm_image_t;
  /* A PGM ({chns=1}) or PPM ({chns=3}) image in memory.
    May also be used for other image formats with other
    values of {chns}. The sample in channel {c} of the
    pixel in row {y} and column {x} is {smp[y][x*chns + c]}. */

pnm_image_t *pnm_image_new(int cols, int rows, int chns);
  /* Alocates a new PPM image, including the header and 
    (if {rows*cols != 0}) the pixel arrays.  Sets the 
    {maxval} field to 0 (an invalid value); clients
    must set it explicitly. */
    
void pnm_image_free(pnm_image_t *img);
  /* Discards the pixel array and header of a PNM image. */

pnm_sample_t** pnm_image_alloc_pixel_array(int cols, int rows, int chns);
void pnm_image_free_pixel_array(pnm_sample_t **smp, int cols, int rows, int chns);
  /* Alocates/discards the sample array for a PNM image of the
    specified size and number of channels. */
    
pnm_sample_t* pnm_image_alloc_pixel_row(int cols, int chns);
void pnm_image_free_pixel_row(pnm_sample_t *smp, int cols, int chns);
  /* Alocates/discards a row of pixels for a PNM image of the
    specified width and number of channels. */
    
pnm_image_t *pnm_image_new_header(int cols, int rows, int chns);
  /* Creates a new header record for a image with the specified 
    size and number of channels, but leaves the pixel arrays as NULL
    and the {maxval} to 0 (an invalid value); clients
    must set it explicitly. */

pnm_sample_t pnm_image_get_sample(pnm_image_t *img, int c, int x, int y);
  /* Returns the sample value in channel {c}, column {x}, row {y} 
    of the image {img}. Non-existent channels
    are assumed to be all zeros. */

void pnm_image_set_sample(pnm_image_t *img, int c, int x, int y, pnm_sample_t pv);
  /* Stores the sample value {pv} in channel {c}, column {x}, row {y}
    of the image {img}. Fails if {x,y,c} are not a valid. */

pnm_image_t *pnm_image_crop(pnm_image_t *img, int ic, int nc, int ix, int nx, int iy, int ny);
  /* Returns the sub-image of {img} consisting of channels {ic..ic+nc-1},
     columns {ix..ix+nx-1}, and rows {iy..iy+ny-1}. */

pnm_image_t *pnm_image_read(char *name, bool_t verbose);
  /* Reads a PBM, PGM pr PPM image from the named file. The file format is
    determined by the file's `magic number': "P1" or "P4"
    for the PBM format (1 channel,0 or 1), "P2" or "P5" for PGM (1
    channel --- luminance), "P3" or "P6" for PPM (3 channels --- Red,
    Green, and Blue). If the {name} is "-", reads from {stdin}.
    The {maxval} field is set as specified in the file.
    If {verbose} is TRUE, prints a notice to {stderr}. */

void pnm_image_write(char *name, pnm_image_t *img, bool_t forceplain, bool_t verbose);
  /* Writes a PGM or PPM image to the specified file, in a format
    compatibe with {img.chns}: "P2" or "P5" if {chns == 1}, "P3" or
    "P6" if {chns == 3}. Fails if {chns} is anything else.
    The field {img->maxval} must have been set properly.
    
    The plain variant of the format ("P2" or "P3") is chosen if
    {forceplain} is true or {img->maxval} is too big for the raw
    variant ("P5" or "P6"). If {name} is "-", writes to {stdout}.
    If {verbose} is TRUE, prints a notice to {stderr}. */

pnm_image_t *pnm_image_fread (FILE *rd);
void pnm_image_fwrite(FILE *wr, pnm_image_t *img, bool_t forceplain);
  /* Same as {pnm_image_read} and {pnm_image_write}, 
    but from/to a previously opened file handle. */

void pnm_image_describe(FILE *wr, char *name, pnm_image_t *img);
  /* Prints the {name} and other parameters of image {img} 
    to stderr. */

#endif
