/* pgmminkowsky.c - read a portable graymap and calculate the Minkowski
** Integrals as a function of the threshold.
**
** Copyright (C) 2000 by Luuk van Dijk/Mind over Matter
**
** Based on pgmhist.c,
** Copyright (C) 1989 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 "pgm.h"
#include "mallocvar.h"
#define MAX2(a,b) ( ( (a)>(b) ) ? (a) : (b) )
#define MAX4(a,b,c,d) MAX2( MAX2((a),(b)), MAX2((c),(d)) )
int main( int argc, char** argv ){
FILE *ifp;
gray maxval;
int cols, rows, format;
gray* prevrow;
gray* thisrow;
gray* tmprow;
int* countTile;
int* countEdgeX;
int* countEdgeY;
int* countVertex;
int i, col, row;
int maxtiles, maxedgex, maxedgey, maxvertex;
int area, perimeter, eulerchi;
double l2inv, linv;
/*
* parse arg and initialize
*/
pgm_init( &argc, argv );
if ( argc > 2 ) pm_usage( "[pgmfile]" );
if ( argc == 2 )
ifp = pm_openr( argv[1] );
else
ifp = stdin;
/*
* initialize
*/
pgm_readpgminit( ifp, &cols, &rows, &maxval, &format );
prevrow = pgm_allocrow( cols );
thisrow = pgm_allocrow( cols );
MALLOCARRAY(countTile , maxval + 1 );
MALLOCARRAY(countEdgeX , maxval + 1 );
MALLOCARRAY(countEdgeY , maxval + 1 );
MALLOCARRAY(countVertex , maxval + 1 );
if (countTile == NULL || countEdgeX == NULL || countEdgeY == NULL ||
countVertex == NULL)
pm_error( "out of memory" );
for ( i = 0; i <= maxval; i++ ) countTile[i] = 0;
for ( i = 0; i <= maxval; i++ ) countEdgeX[i] = 0;
for ( i = 0; i <= maxval; i++ ) countEdgeY[i] = 0;
for ( i = 0; i <= maxval; i++ ) countVertex[i] = 0;
/* first row */
pgm_readpgmrow( ifp, thisrow, cols, maxval, format );
/* tiles */
for ( col = 0; col < cols; ++col ) ++countTile[thisrow[col]];
/* y-edges */
for ( col = 0; col < cols; ++col ) ++countEdgeY[thisrow[col]];
/* x-edges */
++countEdgeX[thisrow[0]];
for ( col = 0; col < cols-1; ++col )
++countEdgeX[ MAX2(thisrow[col], thisrow[col+1]) ];
++countEdgeX[thisrow[cols-1]];
/* shortcut: for the first row, countVertex == countEdgeX */
++countVertex[thisrow[0]];
for ( col = 0; col < cols-1; ++col )
++countVertex[ MAX2(thisrow[col], thisrow[col+1]) ];
++countVertex[thisrow[cols-1]];
for ( row = 1; row < rows; ++row ){
tmprow = prevrow;
prevrow = thisrow;
thisrow = tmprow;
pgm_readpgmrow( ifp, thisrow, cols, maxval, format );
/* tiles */
for ( col = 0; col < cols; ++col ) ++countTile[thisrow[col]];
/* y-edges */
for ( col = 0; col < cols; ++col )
++countEdgeY[ MAX2(thisrow[col], prevrow[col]) ];
/* x-edges */
++countEdgeX[thisrow[0]];
for ( col = 0; col < cols-1; ++col )
++countEdgeX[ MAX2(thisrow[col], thisrow[col+1]) ];
++countEdgeX[thisrow[cols-1]];
/* vertices */
++countVertex[ MAX2(thisrow[0],prevrow[0]) ];
for ( col = 0; col < cols-1; ++col )
++countVertex[
MAX4(thisrow[col], thisrow[col+1], prevrow[col], prevrow[col+1])
];
++countVertex[ MAX2(thisrow[cols-1],prevrow[cols-1]) ];
} /* for row */
/* now thisrow contains the top row*/
/* tiles and x-edges have been counted, now upper
y-edges and top vertices remain */
/* y-edges */
for ( col = 0; col < cols; ++col ) ++countEdgeY[ thisrow[col] ];
/* vertices */
++countVertex[thisrow[0]];
for ( col = 0; col < cols-1; ++col )
++countVertex[ MAX2(thisrow[col],thisrow[col+1]) ];
++countVertex[ thisrow[cols-1] ];
/* cleanup */
maxtiles = rows * cols;
maxedgex = rows * (cols+1);
maxedgey = (rows+1) * cols;
maxvertex= (rows+1) * (cols+1);
l2inv = 1.0/maxtiles;
linv = 0.5/(rows+cols);
/* And print it. */
printf( "#threshold\t tiles\tx-edges\ty-edges\tvertices\n" );
printf( "#---------\t -----\t-------\t-------\t--------\n" );
for ( i = 0; i <= maxval; i++ ){
if( !(countTile[i] || countEdgeX[i] || countEdgeY[i] || countVertex[i] ) )
continue; /* skip empty slots */
area = maxtiles;
perimeter = 2*maxedgex + 2*maxedgey - 4*maxtiles;
eulerchi = maxtiles - maxedgex - maxedgey + maxvertex;
printf( "%f\t%6d\t%7d\t%7d\t%8d\t%g\t%g\t%6d\n", (float) i/(1.0*maxval),
maxtiles, maxedgex, maxedgey, maxvertex,
area*l2inv, perimeter*linv, eulerchi
);
maxtiles -= countTile[i];
maxedgex -= countEdgeX[i];
maxedgey -= countEdgeY[i];
maxvertex-= countVertex[i];
/* i, countTile[i], countEdgeX[i], countEdgeY[i], countVertex[i] */
}
/* these should be zero: */
printf( "# check:\t%6d\t%7d\t%7d\t%8d\n",
maxtiles, maxedgex, maxedgey, maxvertex );
pm_close( ifp );
exit( 0 );
} /*main*/