im_stats fix

This commit is contained in:
John Cupitt 2009-09-01 14:16:32 +00:00
parent b2fc33313e
commit b5f2c3e86d

@ -18,6 +18,10 @@
* 13/1/05
* - use 64 bit arithmetic
1/9/09
- argh nope min/max was broken again for >1CPU in short pipelines on
some architectures
*/
/*
@ -46,6 +50,10 @@
*/
/*
#define DEBUG
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /*HAVE_CONFIG_H*/
@ -79,12 +87,16 @@ make_mask( IMAGE *im, void *a, void *b )
*/
out->offset = 42;
#ifdef DEBUG
printf( "make_mask: created %p\n", out );
#endif /*DEBUG*/
return( out );
}
/* Merge a temp DOUBLEMASK into the real DOUBLEMASK. Row 0 is unused, row 1
* has the stats for band 1. These are: (minimum, maximum, sum, sum^2). If the
* offset of out if 42, then it has not been inited yet and we just copy.
* offset of out is 42, then it has not been inited yet and we just copy.
*/
static int
merge_mask( void *seq, void *a, void *b )
@ -94,21 +106,20 @@ merge_mask( void *seq, void *a, void *b )
double *rowi, *rowo;
int z;
/* Merge, or just copy?
*/
if( out->offset != 42 )
/* Add info from tmp.
*/
for( z = 1; z < tmp->ysize; z++ ) {
rowi = tmp->coeff + z * 6;
rowo = out->coeff + z * 6;
#ifdef DEBUG
printf( "merge_mask: tmp = %p, out = %p\n", tmp, out );
im_print_dmask( tmp );
im_print_dmask( out );
#endif /*DEBUG*/
/* Merge, or just copy? Also, tmp might be uninited, so allow for that
* too.
*/
if( out->offset == 42 && tmp->offset != 42 ) {
#ifdef DEBUG
printf( "merge_mask: copying\n", tmp );
#endif /*DEBUG*/
rowo[0] = IM_MIN( rowi[0], rowo[0] );
rowo[1] = IM_MAX( rowi[1], rowo[1] );
rowo[2] += rowi[2];
rowo[3] += rowi[3];
}
else {
/* Copy info from tmp.
*/
for( z = 1; z < tmp->ysize; z++ ) {
@ -123,6 +134,23 @@ merge_mask( void *seq, void *a, void *b )
out->offset = 0;
}
else if( out->offset != 42 && tmp->offset != 42 ) {
#ifdef DEBUG
printf( "merge_mask: merging\n" );
#endif /*DEBUG*/
/* Add info from tmp.
*/
for( z = 1; z < tmp->ysize; z++ ) {
rowi = tmp->coeff + z * 6;
rowo = out->coeff + z * 6;
rowo[0] = IM_MIN( rowi[0], rowo[0] );
rowo[1] = IM_MAX( rowi[1], rowo[1] );
rowo[2] += rowi[2];
rowo[3] += rowi[3];
}
}
/* Can now free tmp.
*/
@ -152,50 +180,50 @@ scan_fn( REGION *reg, void *seq, void *a, void *b )
* Use temp variables of same type for min/max for faster comparisons.
* Use double to sum bands.
*/
#define non_complex_loop(TYPE) { \
TYPE *p, *q; \
TYPE value, small, big; \
double *row; \
\
/* Have min and max been initialised? \
*/ \
if( tmp->offset == 42 ) { \
/* Init min and max for each band. \
*/ \
p = (TYPE *) IM_REGION_ADDR( reg, le, to ); \
for( z = 1; z < bands + 1; z++ ) { \
row = tmp->coeff + z * 6; \
row[0] = p[z - 1]; \
row[1] = p[z - 1]; \
} \
tmp->offset = 0; \
} \
\
for( y = to; y < bo; y++ ) { \
p = (TYPE *) IM_REGION_ADDR( reg, le, y ); \
#define non_complex_loop(TYPE) \
{ TYPE *p, *q; \
TYPE value, small, big; \
double *row; \
\
for( z = 0; z < bands; z++ ) { \
q = p + z; \
row = tmp->coeff + (z + 1)*6; \
small = row[0]; \
big = row[1]; \
\
for( x = le; x < ri; x++ ) { \
value = *q; \
q += bands; \
row[2] += value;\
row[3] += (double)value*(double)value;\
if( value > big ) \
big = value; \
else if( value < small ) \
small = value;\
}\
/* Have min and max been initialised? \
*/ \
if( tmp->offset == 42 ) { \
/* Init min and max for each band. \
*/ \
p = (TYPE *) IM_REGION_ADDR( reg, le, to ); \
for( z = 0; z < bands; z++ ) { \
row = tmp->coeff + (z + 1) * 6; \
row[0] = p[z]; \
row[1] = p[z]; \
} \
tmp->offset = 0; \
} \
\
for( y = to; y < bo; y++ ) { \
p = (TYPE *) IM_REGION_ADDR( reg, le, y ); \
\
row[0] = small; \
row[1] = big; \
for( z = 0; z < bands; z++ ) { \
q = p + z; \
row = tmp->coeff + (z + 1)*6; \
small = row[0]; \
big = row[1]; \
\
for( x = le; x < ri; x++ ) { \
value = *q; \
q += bands; \
row[2] += value;\
row[3] += (double)value*(double)value;\
if( value > big ) \
big = value; \
else if( value < small ) \
small = value;\
}\
\
row[0] = small; \
row[1] = big; \
}\
}\
}\
}
}
/* Now generate code for all types.
*/
@ -216,20 +244,11 @@ scan_fn( REGION *reg, void *seq, void *a, void *b )
return( 0 );
}
/**
* im_stats:
* @in: image to analyze
*
* Find many image statistics in a single pass through the image. Works for
* any uncoded, non-complex image. Returns a
* #DOUBLEMASK of 6 columns by n+1 (where n is number of bands in image @in)
* rows.
*
* Columns are statistics, and are, in order: minimum, maximum, sum, sum of
* squares, mean, standard deviation. Row 0 has statistics for all bands
* together, row 1 has stats for band 1, and so on.
*
* Returns: a #DOUBLEMASK holding the image statistics
/* Find the statistics of an image. Take any non-complex format. Write the
* stats to a DOUBLEMASK of size 6 by (in->Bands+1). We hold a row for each
* band, plus one row for all bands. Row n has 6 elements, which are, in
* order, (minimum, maximum, sum, sum^2, mean, deviation) for band n. Row 0 has
* the figures for all bands together.
*/
DOUBLEMASK *
im_stats( IMAGE *in )
@ -285,5 +304,10 @@ im_stats( IMAGE *in )
base[5] = sqrt( fabs( base[3] - (base[2] * base[2] / vals) ) /
(vals - 1) );
#ifdef DEBUG
printf( "im_stats:\n" );
im_print_dmask( out );
#endif /*DEBUG*/
return( out );
}