/* 11/16/06, Kambhamettu:
   This program reads a jpeg gray level image, uses
   'djpeg' command to convert it into pgm format, and then
   skips the header to store the image in binary into 2D array */
/* Image size is rowsXcols, can be extracted from jpeg automatically */
/* 2D array is dynamic, so no need to know the size of the image ahead
   of time */
/* It uses a function to modify pixels, so we can see how double pointers
   get passed to functions */
/* note that pgm header has width first and then height, i.e, cols, then rows */

#include <stdio.h>
#include <stdlib.h>

void modify (unsigned char **,int,int);

void main()
{

unsigned char **image; /* This is a double pointer. It points to pointer of the image */
FILE *fr; /* File pointer to open the image */
FILE *fw; /* File pointer to write the image */

int i,j;
int rows,cols,highest_intensity; /* The pgm format header includes cols,rows highest
                                    intensity of the image */


system("djpeg -outfile temp.pgm cooke_engrav_xlarge.jpg"); /* djpeg is a unix command, which
                                       converts jpeg to other image formats - see man djpeg */

fr=fopen("temp.pgm","r");  /* Open the pgm file - this is the image written using above command */

fscanf(fr,"P5\n%d %d\n%d\n",&cols,&rows,&highest_intensity); /* P5 represents binary format of 
                                     a  pgm file, width(cols) and height(rows)  - in that order*/

image = (unsigned char *) calloc (rows, sizeof(unsigned char *) ) ; 
                               /* above statement allocates 'row' number of pointers that 
 				  point to each row of the array */

/* Allocates memory for each row of image seperately,  pointed by above row-number of pointers*/
 for (i = 0; i< rows; i++)
 {
image[i] = (unsigned char *) calloc (cols, sizeof(unsigned char *) ) ;
}

/* Read each row of the image */

 for (i = 0; i< rows; i++)
 {
 fread(image[i],1,cols,fr); /* After the header, pgm has raw image */
 }
fclose(fr);

/* send double pointer to the modify function to modify some pixels */
modify(image,rows,cols);

/* We will write the pgm file first */
fw=fopen("temp_modified.pgm","w");

/* With the header first and then the image in binary. note, width first, then height */
fprintf(fw,"P5\n%d %d\n255\n",cols,rows);

/* write each row, just the way we read each row */
 for (i = 0; i<rows; i++)
 {
 fwrite(image[i],1,cols,fw); 
 }
fclose(fw);

/* free up each row */
 for (i = 0; i< rows; i++)
 {
free(image[i]);
}

system("cjpeg -outfile final_modified.jpg temp_modified.pgm");
}

/* This function takes double pointer as input and modifies pixels */
/* Note, we can use indices to index the image, similar to static array access */

void modify(unsigned char **image, int rows, int cols)
{
int i,j;

for (i=50;i<250;i++)
for (j=50;j<250;j++)
image[i][j]=0;
}

