/* PGM Statistics Calculator v1.1.0 Ver.: OK (c) 08/07 - Christos Iosifides */
/*
   Name:			PGM_Statistics
   Version:		    1.1.0
   Copyright:	    Ch Iossif @ 2007-2009
   Author:		    Christos Iosifidis
   Date:			30/08/07 14:30
   Modified:		09/10/09 16:44
   Description:	    PGM Statistics Calculator

   Copyright (C) June 2009 Ch Iossif <chiossif@yahoo.com>

   This program is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

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

void error(const char *);
void warning(const char *);

int main(int argc,char **argv) {
    FILE *fp;
    int PGM_mode, PGM_row, PGM_col, PGM_scale, ch;
    int maxi, mini, med, k, d;
    unsigned long int sum, histo[65536];
    double s, ss;
    unsigned short **image;
    char buff[BUFSIZ];
    register int r, c;

    if (argc!=2)
        error("Usage: PGM_Statistics fname");
    if ((fp=fopen(argv[1],"rb"))==NULL)
        error("Bad input file name");

    /* Reading PGM header info - Checking for correct file version */
    if (getc(fp)!='P')
        error("This file is not a PGM file.\n");
    if ((ch=getc(fp))==EOF)
        error("Bad file read");
    PGM_mode=ch-'0';
    if (PGM_mode!=5)
        error("This file is not a PGM5 file");
    do {
        if (fgets(buff,BUFSIZ,fp)!=buff)
            error("Bad read at filename.");
    } while (buff[0]=='#' || buff[0]<' ');
    sscanf(buff, "%d %d", &PGM_col, &PGM_row);
    do {
        if (fgets(buff,BUFSIZ,fp)!=buff)
            error("Bad read at filename.");
    } while (buff[0]=='#' || buff[0]<' ');
    sscanf(buff, "%d", &PGM_scale);

    /* Check image dimensions and allocate memory */
    if (PGM_row<0)
        error("Bad rows value");
    if (PGM_col<0)
        error("Bad columns value");
    if ((image=malloc(PGM_row*sizeof(short*)))==NULL)
        error("Not enough memory avaliable");
    for (r=0;r<PGM_row;r++)
        if ((image[r]=malloc(PGM_col*sizeof(short)))==NULL)
            error("Not enough memory avaliable");

    /* Read image and close file */
    for (r=0;r<PGM_row;r++)
        if (fread(image[r], sizeof(short), PGM_col, fp)!=PGM_col)
            error("End Of File encountered");
    fclose(fp);

    /* Initialize statistics */
    k=s=ss=0;
    mini=65536;
    maxi=0;
    for (r=0;r<65536;r++)
        histo[r]=0;

    /* Calculate statistics */
    for (r=0;r<PGM_row;r++) {
        for (c=0;c<PGM_col;c++) {
            if ((d=image[r][c])<PGM_scale) {
                k++;
                s+=(double)d;
                ss+=(double)d*d;
                histo[d]++;
                if (mini>(int)d)
                    mini=(int)d;
                if (maxi<(int)d)
                    maxi=(int)d;
            }
        }
    }
    if (k<1||k>PGM_row*PGM_col)
        error("Bad image data");

    med=k/2;
    sum=0;
    for (c=mini;sum<med;r=c++)
        sum+=histo[c];
    med=r;

    /* Display statistics */
    printf( "\nPGM_Statistics results :\n" );
    printf( "Minimum             = %7d\n", mini );
    printf( "Maximum             = %7d\n", maxi );
    printf( "Average             = %9.1lf\n", s/k );
    printf( "Median              = %7d\n", med );
    printf( "Standard Deviation  = %12.4lf\n", sqrt((ss-s*s/k)/k) );

    /* Free'em all and exit */
    for (r=0;r<PGM_row;r++)
        free(image[r]);
    free(image);

    printf("\n\nPGM_Statistics by Ch Iossif (c) Sep 2007-2009.\n\n\n");
    return 0;
}

void error(const char *s) {
    printf("PGM_Statistics reports: Error: %s.\n",s);
    exit(1);
}

void warning(const char *s) {
    printf("PGM_Statistics reports: Warning: %s.\n",s);
}

