VipsMin stops early if it can

if VipsMin sees a minimum value (eg. 0 for uchar) it'll stop searching
early
This commit is contained in:
John Cupitt 2011-09-05 14:10:56 +01:00
parent 6f125a6f31
commit 4ce3346a4f
5 changed files with 282 additions and 11 deletions

View File

@ -6,6 +6,7 @@
- added optional output args, eg. x/y for min
- CLI supports optional output args
- in im_vips2tiff, enable YCbCr compression for jpeg write
- VipsMin stops search early if it can
10/8/11 started 7.26.3
- don't use G_VALUE_COLLECT_INIT(), many platforms do not have a glib this

4
TODO
View File

@ -37,10 +37,6 @@
- max.c will need an early termination thing for vips_sink ... easy?
- support planar tiff

View File

@ -17,6 +17,8 @@
* - rewrite, from im_maxpos()
* 30/8/11
* - rewrite as a class
* 5/9/11
* - abandon scan if we find minimum possible value
*/
/*
@ -57,6 +59,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <limits.h>
#include <vips/vips.h>
#include <vips/internal.h>
@ -178,6 +181,8 @@ vips_min_stop( VipsStatistic *statistic, void *seq )
return( 0 );
}
/* real min with no limits.
*/
#define LOOP( TYPE ) { \
TYPE *p = (TYPE *) in; \
TYPE m; \
@ -199,6 +204,31 @@ vips_min_stop( VipsStatistic *statistic, void *seq )
min->set = TRUE; \
}
/* real min with a lower bound.
*/
#define LOOPL( TYPE, LOWER ) { \
TYPE *p = (TYPE *) in; \
TYPE m; \
\
if( min->set ) \
m = min->min; \
else \
m = p[0]; \
\
for( i = 0; i < sz; i++ ) { \
if( p[i] < m ) { \
m = p[i]; \
min->x = x + i / bands; \
min->y = y; \
if( m <= LOWER ) \
statistic->stop = TRUE; \
} \
} \
\
min->min = m; \
min->set = TRUE; \
}
#define CLOOP( TYPE ) { \
TYPE *p = (TYPE *) in; \
double m; \
@ -239,14 +269,16 @@ vips_min_scan( VipsStatistic *statistic, void *seq,
int i;
switch( vips_image_get_format( input ) ) {
case IM_BANDFMT_UCHAR: LOOP( unsigned char ); break;
case IM_BANDFMT_CHAR: LOOP( signed char ); break;
case IM_BANDFMT_USHORT: LOOP( unsigned short ); break;
case IM_BANDFMT_SHORT: LOOP( signed short ); break;
case IM_BANDFMT_UINT: LOOP( unsigned int ); break;
case IM_BANDFMT_INT: LOOP( signed int ); break;
case IM_BANDFMT_UCHAR: LOOPL( unsigned char, 0 ); break;
case IM_BANDFMT_CHAR: LOOPL( signed char, SCHAR_MIN ); break;
case IM_BANDFMT_USHORT: LOOPL( unsigned short, 0 ); break;
case IM_BANDFMT_SHORT: LOOPL( signed short, SHRT_MIN ); break;
case IM_BANDFMT_UINT: LOOPL( unsigned int, 0 ); break;
case IM_BANDFMT_INT: LOOPL( signed int, INT_MIN ); break;
case IM_BANDFMT_FLOAT: LOOP( float ); break;
case IM_BANDFMT_DOUBLE: LOOP( double ); break;
case IM_BANDFMT_COMPLEX: CLOOP( float ); break;
case IM_BANDFMT_DPCOMPLEX: CLOOP( double ); break;

View File

@ -35,7 +35,7 @@
*/
/*
#define DEBUG
#define VIPS_DEBUG
*/
#ifdef HAVE_CONFIG_H
@ -48,6 +48,7 @@
#include <math.h>
#include <vips/vips.h>
#include <vips/debug.h>
#include "statistic.h"
@ -86,6 +87,9 @@ vips_statistic_scan( VipsRegion *region,
int y;
PEL *p;
VIPS_DEBUG_MSG( "vips_statistic_scan: %d x %d @ %d x %d\n",
r->width, r->height, r->left, r->top );
p = (PEL *) IM_REGION_ADDR( region, r->left, r->top );
for( y = 0; y < r->height; y++ ) {
if( class->scan( statistic,

238
libvips/fred# Normal file

File diff suppressed because one or more lines are too long