This commit is contained in:
John Cupitt 2009-09-07 08:06:53 +00:00
parent 2e42e736a9
commit 616bb9ab7f
9 changed files with 186 additions and 193 deletions

View File

@ -26,6 +26,8 @@
- im_remainder() has a float result for float types
- im_measure() allows sel == NULL, meaning all patches
- added "deprecated" package
- faster, simpler, better im_max()
- im_max() returns true modulus, not square of modulus, for complex images
25/3/09 started 7.18.0
- revised version numbers

38
TODO
View File

@ -1,4 +1,17 @@
- im_stats() needs a rewrite ... scrap the stupid 42 thing
- new im_max() needs testing
im_avg() needs to work for complex: return modulus
use im_max() model to rewrite im_min(), im_stats()
- im_minpos(), im_maxpos() need partialing
- im_maxpos_vec needs gtkdoc
- 1-bit PNG read is broken?
@ -10,29 +23,6 @@
- im__cast_and_call() no longer does
out->Bbits = im_bits_of_fmt( out->BandFmt );
make sure we do this for each use of im__cast_and_call()
- im__cast_and_call() no longer casts input to output type, it casts inputs
up to the smallest common type
so we need to change all the buffer processors from
T op T -> T
to
T1 op T1 -> T2
done add/sub/mul, doing div
others?
- rename vipsCC in SWIG as pyvips?

View File

@ -100,6 +100,19 @@ stop_fn( void *seq, void *a, void *b )
return( 0 );
}
/* Sum pels in this section.
*/
#define LOOP( TYPE ) { \
TYPE *p; \
\
for( y = to; y < bo; y++ ) { \
p = (TYPE *) IM_REGION_ADDR( reg, le, y ); \
\
for( x = 0; x < sz; x++ ) \
sum += *p++; \
} \
}
/* Loop over region, accumulating a sum in *tmp.
*/
static int
@ -115,19 +128,6 @@ scan_fn( REGION *reg, void *seq, void *a, void *b )
double sum = 0.0;
int x, y;
/* Sum pels in this section.
*/
#define LOOP( TYPE ) { \
TYPE *p; \
\
for( y = to; y < bo; y++ ) { \
p = (TYPE *) IM_REGION_ADDR( reg, le, y ); \
\
for( x = 0; x < sz; x++ ) \
sum += *p++; \
} \
}
/* Now generate code for all types.
*/
switch( im->BandFmt ) {

View File

@ -1,12 +1,4 @@
/* @(#) Function to find perform pixelwise linear regression on an array of
* @(#) single band images.
* @(#)
* @(#) int im_linreg(
* @(#) IMAGE **ins,
* @(#) IMAGE *out,
* @(#) double *xs
* @(#) );
* @(#)
/* im_linreg.c
*
* Copyright: 2006, The Nottingham Trent University
*
@ -16,6 +8,8 @@
*
* 12/5/09
* - make x_anal() static, fix some signed/unsigned warnings
* 3/9/09
* - gtkdoc comment
*/
/*
@ -148,6 +142,16 @@ SKIP_ALL_DECL( double );
/** EXPORTED FUNCTION DEFINITION **/
/** im_linreg:
* @ins: NULL-terminated array of input images
* @out: results of analysis
* @xs: X position of each image (pixel value is Y)
*
* Function to find perform pixelwise linear regression on an array of
* single band images. The output is a seven-band douuble image
*
* TODO: figure out how this works and fix up these docs!
*/
int im_linreg( IMAGE **ins, IMAGE *out, double *xs ){
#define FUNCTION_NAME "im_linreg"
int n;

View File

@ -18,6 +18,9 @@
* - random wrong result for >1 thread :-( (thanks Joe)
* 15/10/07
* - oh, heh, seq->inf was not being set correctly, not that it mattered
* 4/9/09
* - rewrite with im__value(), much simpler and fixes a race condition
* - gtkdoc comment
*/
/*
@ -58,7 +61,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <assert.h>
#include <vips/vips.h>
@ -66,39 +68,15 @@
#include <dmalloc.h>
#endif /*WITH_DMALLOC*/
/* Per-call state.
*/
typedef struct _MaxInfo {
/* Parameters.
*/
IMAGE *in;
double *out;
/* Global max so far.
*/
double value;
int valid; /* zero means value is unset */
} MaxInfo;
/* Per thread state.
*/
typedef struct _Seq {
MaxInfo *inf;
double value;
int valid; /* zero means value is unset */
} Seq;
/* New sequence value.
*/
static void *
max_start( IMAGE *in, void *a, void *b )
{
MaxInfo *inf = (MaxInfo *) a;
Seq *seq = IM_NEW( NULL, Seq );
double *value = (double *) a;
double *seq = IM_NEW( NULL, double );
seq->inf = inf;
seq->valid = 0;
*seq = *value;
return( (void *) seq );
}
@ -108,47 +86,19 @@ max_start( IMAGE *in, void *a, void *b )
static int
max_stop( void *vseq, void *a, void *b )
{
Seq *seq = (Seq *) vseq;
MaxInfo *inf = (MaxInfo *) a;
double *seq = (double *) vseq;
double *value = (double *) a;
if( seq->valid ) {
if( !inf->valid )
/* Just copy.
*/
inf->value = seq->value;
else
/* Merge.
*/
inf->value = IM_MAX( inf->value, seq->value );
inf->valid = 1;
}
/* Merge.
*/
*value = IM_MAX( *value, *seq );
im_free( seq );
return( 0 );
}
/* Loop over region, adding to seq.
*/
static int
max_scan( REGION *reg, void *vseq, void *a, void *b )
{
Seq *seq = (Seq *) vseq;
Rect *r = &reg->valid;
IMAGE *im = reg->im;
int le = r->left;
int to = r->top;
int bo = IM_RECT_BOTTOM(r);
int nel = IM_REGION_N_ELEMENTS( reg );
int x, y;
double m;
#define loop(TYPE) { \
m = *((TYPE *) IM_REGION_ADDR( reg, le, to )); \
\
#define LOOP( TYPE ) { \
for( y = to; y < bo; y++ ) { \
TYPE *p = (TYPE *) IM_REGION_ADDR( reg, le, y ); \
\
@ -161,22 +111,17 @@ max_scan( REGION *reg, void *vseq, void *a, void *b )
} \
}
#define complex_loop(TYPE) { \
TYPE *p = (TYPE *) IM_REGION_ADDR( reg, le, to ); \
double real = p[0]; \
double imag = p[1]; \
\
m = real * real + imag * imag; \
\
#define CLOOP( TYPE ) { \
for( y = to; y < bo; y++ ) { \
TYPE *p = (TYPE *) IM_REGION_ADDR( reg, le, y ); \
\
for( x = 0; x < nel * 2; x += 2 ) { \
double mod; \
for( x = 0; x < nel; x++ ) { \
double mod, re, im; \
\
real = p[x]; \
imag = p[x + 1]; \
mod = real * real + imag * imag; \
re = p[0]; \
im = p[1]; \
p += 2; \
mod = re * re + im * im; \
\
if( mod > m ) \
m = mod; \
@ -184,47 +129,76 @@ max_scan( REGION *reg, void *vseq, void *a, void *b )
} \
}
/* Loop over region, adding to seq.
*/
static int
max_scan( REGION *reg, void *vseq, void *a, void *b )
{
double *seq = (double *) vseq;
Rect *r = &reg->valid;
IMAGE *im = reg->im;
int le = r->left;
int to = r->top;
int bo = IM_RECT_BOTTOM(r);
int nel = IM_REGION_N_ELEMENTS( reg );
int x, y;
double m;
m = *seq;
switch( im->BandFmt ) {
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_FLOAT: loop( float ); break;
case IM_BANDFMT_DOUBLE: loop( double ); break;
case IM_BANDFMT_COMPLEX: complex_loop( float ); break;
case IM_BANDFMT_DPCOMPLEX: complex_loop( double ); break;
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_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;
default:
assert( 0 );
g_assert( 0 );
}
if( seq->valid ) {
seq->value = IM_MAX( seq->value, m );
}
else {
seq->value = m;
seq->valid = 1;
}
*seq = m;
#ifdef DEBUG
printf( "im_max: left = %d, top = %d, width = %d, height = %d\n",
r->left, r->top, r->width, r->height );
printf( " (max = %g)\n", seq->value );
printf( " (max = %g)\n", *seq );
#endif /*DEBUG*/
return( 0 );
}
/* Get the value of pixel (0, 0). Use this to init the min/max value for
* threads. Shared with im_min(), im_stats() etc. This will return mod for
* complex.
*/
int
im__value( IMAGE *im, double *value )
{
IMAGE *t;
if( !(t = im_open_local( im, "im__value", "p" )) ||
im_extract_area( im, t, 0, 0, 1, 1 ) ||
im_avg( t, value ) )
return( -1 );
return( 0 );
}
/**
* im_max:
* @in: input #IMAGE
* @out: output double
*
* Finds the the maximum value of image #in and returns it at the
* location pointed by out. If input is complex, the max square amplitude
* (re*re+im*im) is returned. im_max() finds the maximum of all bands: if you
* location pointed by out. If input is complex, the max modulus
* is returned. im_max() finds the maximum of all bands: if you
* want to find the maximum of each band separately, use im_stats().
*
* See also: im_maxpos(), im_min(), im_stats().
@ -233,21 +207,29 @@ max_scan( REGION *reg, void *vseq, void *a, void *b )
*/
int
im_max( IMAGE *in, double *out )
{
MaxInfo inf;
inf.in = in;
inf.out = out;
inf.valid = 0;
{
double value;
if( im_pincheck( in ) ||
im_check_uncoded( "im_max", in ) )
return( -1 );
if( im_iterate( in, max_start, max_scan, max_stop, &inf, NULL ) )
if( im__value( in, &value ) )
return( -1 );
/* We use square mod for scanning, for speed.
*/
if( im_iscomplex( in ) )
value *= value;
if( im_iterate( in, max_start, max_scan, max_stop, &value, NULL ) )
return( -1 );
*out = inf.value;
/* Back to modulus.
*/
if( im_iscomplex( in ) )
value = sqrt( value );
*out = value;
return( 0 );
}

View File

@ -1,15 +1,4 @@
/* @(#) Function to find the maximum of an image. Works for any
* @(#) image type. Returns a double and the location of max.
* @(#)
* @(#) Function im_maxpos() assumes that input
* @(#) is either memory mapped or in a buffer.
* @(#)
* @(#) int im_maxpos(in, xpos, ypos, max)
* @(#) IMAGE *in;
* @(#) int *xpos, *ypos;
* @(#) double *max;
* @(#)
* @(#) Returns 0 on success and -1 on error
/* im_maxpos.c
*
* Copyright: 1990, J. Cupitt
*
@ -21,6 +10,8 @@
* - im_incheck() call added
* 20/6/95 JC
* - now returns double for value, like im_max()
* 4/9/09
* - gtkdoc comment
*/
/*
@ -55,7 +46,6 @@
#include <vips/intl.h>
#include <stdio.h>
#include <assert.h>
#include <vips/vips.h>
@ -77,8 +67,22 @@
case IM_BANDFMT_COMPLEX: loopcmplx(float); break; \
case IM_BANDFMT_DPCOMPLEX: loopcmplx(double); break;
/* Find the position of the maximum of an image. Take any format, returns a
* float and its position.
/**
* im_maxpos:
* @in: image to search
* @xpos: returned x position of maximum
* @ypos: returned y position of maximum
* @out: returned pixel value at that position
*
* Function to find the maximum of an image. Works for any
* image type. Returns a double and the location of max.
*
* This is not a PIO operation! It may use a lot of memory and take a while.
* Needs a rewrite.
*
* See also: im_minpos(), im_min(), im_stats(), im_maxpos_avg().
*
* Returns: 0 on success, -1 on error
*/
int
im_maxpos( IMAGE *in, int *xpos, int *ypos, double *out )
@ -135,7 +139,7 @@ im_maxpos( IMAGE *in, int *xpos, int *ypos, double *out )
switch( in->BandFmt ) {
im_for_all_types();
default: {
assert( 0 );
g_assert( 0 );
return( -1 );
}
}

View File

@ -1,11 +1,4 @@
/* @(#) Function to find the minimum of an image. Works for any
* @(#) image type. Returns a double.
* @(#)
* @(#) int im_min(in, min)
* @(#) IMAGE *in;
* @(#) double *min;
* @(#)
* @(#) Returns 0 on success and -1 on error
/* im_min.c
*
* Copyright: 1990, J. Cupitt
*
@ -221,6 +214,20 @@ scan_fn( REGION *reg, void *vseq, void *a, void *b )
return( 0 );
}
/**
* im_min:
* @in: input #IMAGE
* @out: output double
*
* Finds the the minimum value of image @in and returns it at the
* location pointed by @out. If input is complex, the min square amplitude
* (re*re+im*im) is returned. im_min() finds the maximum of all bands: if you
* want to find the maximum of each band separately, use im_stats().
*
* See also: im_minpos(), im_max(), im_stats().
*
* Returns: 0 on success, -1 on error
*/
int
im_min( IMAGE *in, double *out )
{
@ -230,12 +237,9 @@ im_min( IMAGE *in, double *out )
inf.out = out;
inf.valid = 0;
if( im_pincheck( in ) )
if( im_pincheck( in ) ||
im_check_uncoded( "im_min", in ) )
return( -1 );
if( in->Coding != IM_CODING_NONE ) {
im_error( "im_min", "%s", _( "not uncoded" ) );
return( -1 );
}
if( im_iterate( in, start_fn, scan_fn, stop_fn, &inf, NULL ) )
return( -1 );

View File

@ -1,15 +1,4 @@
/* @(#) Function to find the minimim of an image. Works for any
* @(#) image type. Returns a double and the location of min
* @(#)
* @(#) Function im_minpos() assumes that input
* @(#) is either memory mapped or in a buffer.
* @(#)
* @(#) int im_minpos(in, xpos, ypos, out)
* @(#) IMAGE *in;
* @(#) int *xpos, *ypos;
* @(#) double *out;
* @(#)
* @(#) Returns 0 on success and -1 on error
/* im_minpos.c
*
* Copyright: 1990, J. Cupitt
*
@ -22,6 +11,8 @@
* - im_incheck() added
* 20/6/95 JC
* - now returns double for value, like im_max()
* 4/9/09
* - gtkdoc comment
*/
/*
@ -56,7 +47,6 @@
#include <vips/intl.h>
#include <stdio.h>
#include <assert.h>
#include <vips/vips.h>
@ -64,7 +54,23 @@
#include <dmalloc.h>
#endif /*WITH_DMALLOC*/
/* Find the minimum of an image. Take any format, returns a double. */
/**
* im_minpos:
* @in: image to search
* @xpos: returned x position of minimum
* @ypos: returned y position of minimum
* @out: returned pixel value at that position
*
* Function to find the minimum of an image. Works for any
* image type. Returns a double and the location of min.
*
* This is not a PIO operation! It may use a lot of memory and take a while.
* Needs a rewrite.
*
* See also: im_maxpos(), im_max(), im_stats(), im_maxpos_avg().
*
* Returns: 0 on success, -1 on error
*/
int
im_minpos( IMAGE *in, int *xpos, int *ypos, double *out )
{
@ -131,7 +137,7 @@ im_minpos( IMAGE *in, int *xpos, int *ypos, double *out )
case IM_BANDFMT_DPCOMPLEX: loopcmplx(double); break;
default:
assert( 0 );
g_assert( 0 );
}
/* Take out bands on x.

View File

@ -135,6 +135,7 @@ int im__cast_and_call( IMAGE *in1, IMAGE *in2, IMAGE *out,
im_wrapmany_fn fn, void *a );
VipsBandFmt im__format_common( IMAGE *in1, IMAGE *in2 );
int im__math( const char *name, IMAGE *in, IMAGE *out, im_wrapone_fn gen );
int im__value( IMAGE *im, double *value );
int im__test_kill( IMAGE *im );
void *im__mmap( int fd, int writeable, size_t length, gint64 offset );