/* pbmminkowsky.c - read a portable bitmap and calculate the Minkowski Integrals
**
** Copyright (C) 2000 by Luuk van Dijk/Mind over Matter
**
** Based on pbmlife.c,
** Copyright (C) 1988,1 1991 by Jef Poskanzer.
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation.  This software is provided "as is" without express or
** implied warranty.
*/

#include "pbm.h"

#define ISWHITE(x) ((x) == PBM_WHITE)


int main(int argc, const char ** argv) {

    FILE * ifP;

    bit * prevrow;
    bit * thisrow;
    bit * tmprow;
  
    int row;
    int col; 

    int countTile;
    int countEdgeX;
    int countEdgeY;
    int countVertex;
  
    int rows;
    int cols;
    int format;

    int area, perimeter, eulerchi;


    pm_proginit(&argc, argv);
  
    if (argc > 2)
        pm_usage("[pbmfile]");
  
    if (argc == 2)
        ifP = pm_openr(argv[1]);
    else
        ifP = stdin;
  
    pbm_readpbminit(ifP, &cols, &rows, &format);

    prevrow = pbm_allocrow(cols);
    thisrow = pbm_allocrow(cols);


    /* first row */

    pbm_readpbmrow(ifP, thisrow, cols, format);

    countTile   = 0;
    countEdgeX  = 0;
    countEdgeY  = 0;
    countVertex = 0;

    /* tiles */

    for (col = 0; col < cols; ++col) 
        if (ISWHITE(thisrow[col]))
            ++countTile;
  
    /* shortcut: for the first row, edgeY == countTile */
    countEdgeY = countTile;

    /* x-edges */

    if (ISWHITE(thisrow[0]))
        ++countEdgeX;

    for (col = 0; col < cols-1; ++col) 
        if (ISWHITE(thisrow[col]) || ISWHITE(thisrow[col+1]))
            ++countEdgeX;

    if (ISWHITE(thisrow[cols-1]))
        ++countEdgeX;

    /* shortcut: for the first row, countVertex == countEdgeX */
  
    countVertex = countEdgeX;
  

    for (row = 1; row < rows; ++row) {  
    
        tmprow  = prevrow; 
        prevrow = thisrow;
        thisrow = tmprow;
 
        pbm_readpbmrow(ifP, thisrow, cols, format);
  
        /* tiles */

        for (col = 0; col < cols; ++col) 
            if (ISWHITE(thisrow[col]))
                ++countTile;
    
        /* y-edges */

        for (col = 0; col < cols; ++col) 
            if (ISWHITE(thisrow[col]) || ISWHITE(prevrow[col]))
                ++countEdgeY;
    
        /* x-edges */

        if (ISWHITE(thisrow[0]))
            ++countEdgeX;

        for (col = 0; col < cols-1; ++col) 
            if (ISWHITE(thisrow[col]) || ISWHITE(thisrow[col+1]))
                ++countEdgeX;
    
        if (ISWHITE(thisrow[cols-1]))
            ++countEdgeX;
    
        /* vertices */

        if (ISWHITE(thisrow[0]) || ISWHITE(prevrow[0]))
            ++countVertex;

        for (col = 0; col < cols-1; ++col) 
            if (ISWHITE(thisrow[col]) || ISWHITE(thisrow[col+1]) 
                || ISWHITE(prevrow[col]) || ISWHITE(prevrow[col+1]))
                ++countVertex;

        if (ISWHITE(thisrow[cols-1]) || ISWHITE(prevrow[cols-1]))
            ++countVertex;

	  
    } /* for row */

    /* now thisrow contains the top row*/
    /* tiles and x-edges have been counted, now y-edges and top
       vertices remain
    */

  
    /* y-edges */

    for (col = 0; col < cols; ++col) 
        if (ISWHITE(thisrow[col]))
            ++countEdgeY;

    /* vertices */
  
    if (ISWHITE(thisrow[0]))
        ++countVertex;

    for (col = 0; col < cols-1; ++col) 
        if (ISWHITE(thisrow[col]) || ISWHITE(thisrow[col+1]))
            ++countVertex;

    if (ISWHITE(thisrow[cols-1]))
        ++countVertex;

    /* cleanup */

    pm_close(ifP);

    /* print results */

    printf("   tiles:\t%d\n x-edges:\t%d\n y-edges:\t%d\nvertices:\t%d\n",
           countTile, countEdgeX, countEdgeY,countVertex);

    area      = countTile;
    perimeter = 2*countEdgeX + 2*countEdgeY - 4*countTile;
    eulerchi  = countTile - countEdgeX - countEdgeY + countVertex;

    printf("    area:\t%d\nperimeter:\t%d\n eulerchi:\t%d\n",
           area, perimeter, eulerchi );
  
    return 0;
}

