im_stats() redone as a class
This commit is contained in:
parent
90849a44c5
commit
ff2e7b26de
@ -8,7 +8,7 @@
|
|||||||
im_sintra(), im_costra(), im_tantra(), im_asintra(), im_acostra(),
|
im_sintra(), im_costra(), im_tantra(), im_asintra(), im_acostra(),
|
||||||
im_atantra(), im_exptra(), im_exp10tra(), im_logtra(), im_log10tra(),
|
im_atantra(), im_exptra(), im_exp10tra(), im_logtra(), im_log10tra(),
|
||||||
im_abs(), im_sign(), im_max(), im_maxpos(), im_deviate(), im_divide(),
|
im_abs(), im_sign(), im_max(), im_maxpos(), im_deviate(), im_divide(),
|
||||||
im_multiply()
|
im_multiply(), im_stats()
|
||||||
redone as classes
|
redone as classes
|
||||||
- added argument priorites to help control arg ordering
|
- added argument priorites to help control arg ordering
|
||||||
- generate has a 'stop' param to signal successful early termination
|
- generate has a 'stop' param to signal successful early termination
|
||||||
|
15
TODO
15
TODO
@ -1,5 +1,20 @@
|
|||||||
- add an INTERPRETATION for "array"
|
- add an INTERPRETATION for "array"
|
||||||
|
|
||||||
|
can move the whole of mask, plus headers, plus conversion/im_vips2mask and
|
||||||
|
mask2vips to deprecated
|
||||||
|
|
||||||
|
- try:
|
||||||
|
|
||||||
|
$ vips stats babe.jpg
|
||||||
|
|
||||||
|
reports leaks, we need to unref more stuff
|
||||||
|
|
||||||
|
- try:
|
||||||
|
|
||||||
|
$ vips add babe.jpg
|
||||||
|
|
||||||
|
GLib-GObject-CRITICAL **: g_o ....
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@ libarithmetic_la_SOURCES = \
|
|||||||
im_point_bilinear.c \
|
im_point_bilinear.c \
|
||||||
im_remainder.c \
|
im_remainder.c \
|
||||||
sign.c \
|
sign.c \
|
||||||
im_stats.c \
|
stats.c \
|
||||||
statistic.c \
|
statistic.c \
|
||||||
statistic.h \
|
statistic.h \
|
||||||
avg.c \
|
avg.c \
|
||||||
|
@ -514,6 +514,7 @@ vips_arithmetic_operation_init( void )
|
|||||||
extern GType vips_math_get_type( void );
|
extern GType vips_math_get_type( void );
|
||||||
extern GType vips_abs_get_type( void );
|
extern GType vips_abs_get_type( void );
|
||||||
extern GType vips_sign_get_type( void );
|
extern GType vips_sign_get_type( void );
|
||||||
|
extern GType vips_stats_get_type( void );
|
||||||
|
|
||||||
vips_add_get_type();
|
vips_add_get_type();
|
||||||
vips_subtract_get_type();
|
vips_subtract_get_type();
|
||||||
@ -528,5 +529,6 @@ vips_arithmetic_operation_init( void )
|
|||||||
vips_math_get_type();
|
vips_math_get_type();
|
||||||
vips_abs_get_type();
|
vips_abs_get_type();
|
||||||
vips_sign_get_type();
|
vips_sign_get_type();
|
||||||
|
vips_stats_get_type();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,351 +0,0 @@
|
|||||||
/* im_stats.c
|
|
||||||
*
|
|
||||||
(C) Kirk Martinez 1993
|
|
||||||
23/4/93 J.Cupitt
|
|
||||||
- adapted to partial images
|
|
||||||
- special struct abandoned; now returns DOUBLEMASK.
|
|
||||||
1/7/93 JC
|
|
||||||
- adapted for partial v2
|
|
||||||
- ANSIfied
|
|
||||||
27/7/93 JC
|
|
||||||
- init of mask changed to use actual values, not IM_MAXDOUBLE and
|
|
||||||
(-IM_MAXDOUBLE). These caused problems when assigned to floats.
|
|
||||||
funny business with offset==42, yuk!
|
|
||||||
31/8/93 JC
|
|
||||||
- forgot to init global max/min properly! sorry.
|
|
||||||
21/6/95 JC
|
|
||||||
- still did not init max and min correctly --- now fixed for good
|
|
||||||
|
|
||||||
* 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
|
|
||||||
* 7/9/09
|
|
||||||
* - rework based on new im__wrapscan() / im_max() ideas for a proper fix
|
|
||||||
* - gtkdoc comment
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
This file is part of VIPS.
|
|
||||||
|
|
||||||
VIPS is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
the Free Software Foundation; either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
#define DEBUG
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
#include <config.h>
|
|
||||||
#endif /*HAVE_CONFIG_H*/
|
|
||||||
#include <vips/intl.h>
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <math.h>
|
|
||||||
|
|
||||||
#include <vips/vips.h>
|
|
||||||
#include <vips/internal.h>
|
|
||||||
|
|
||||||
typedef struct _Wrapscan {
|
|
||||||
IMAGE *in;
|
|
||||||
im_start_fn start;
|
|
||||||
im__wrapscan_fn scan;
|
|
||||||
im_stop_fn stop;
|
|
||||||
void *a;
|
|
||||||
void *b;
|
|
||||||
} Wrapscan;
|
|
||||||
|
|
||||||
static void *
|
|
||||||
wrapscan_start( VipsImage *in, void *a, void *b )
|
|
||||||
{
|
|
||||||
Wrapscan *wrapscan = (Wrapscan *) a;
|
|
||||||
|
|
||||||
return( wrapscan->start( in, wrapscan->a, wrapscan->b ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
wrapscan_stop( void *seq, void *a, void *b )
|
|
||||||
{
|
|
||||||
Wrapscan *wrapscan = (Wrapscan *) a;
|
|
||||||
|
|
||||||
return( wrapscan->stop( seq, wrapscan->a, wrapscan->b ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
wrapscan_scan( REGION *reg, void *seq, void *a, void *b, gboolean *stop )
|
|
||||||
{
|
|
||||||
Wrapscan *wrapscan = (Wrapscan *) a;
|
|
||||||
Rect *r = ®->valid;
|
|
||||||
int lsk = IM_REGION_LSKIP( reg );
|
|
||||||
|
|
||||||
int y;
|
|
||||||
PEL *p;
|
|
||||||
|
|
||||||
p = (PEL *) IM_REGION_ADDR( reg, r->left, r->top );
|
|
||||||
for( y = 0; y < r->height; y++ ) {
|
|
||||||
if( wrapscan->scan( p, r->width, seq,
|
|
||||||
wrapscan->a, wrapscan->b ) )
|
|
||||||
return( -1 );
|
|
||||||
p += lsk;
|
|
||||||
}
|
|
||||||
|
|
||||||
return( 0 );
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Like vips_sink(), but the scan function works a line at a time, like
|
|
||||||
* im_wrap*(). Shared with im_min(), im_deviate() etc.
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
im__wrapscan( VipsImage *in,
|
|
||||||
VipsStartFn start, im__wrapscan_fn scan, VipsStopFn stop,
|
|
||||||
void *a, void *b )
|
|
||||||
{
|
|
||||||
Wrapscan wrapscan;
|
|
||||||
|
|
||||||
wrapscan.in = in;
|
|
||||||
wrapscan.start = start;
|
|
||||||
wrapscan.scan = scan;
|
|
||||||
wrapscan.stop = stop;
|
|
||||||
wrapscan.a = a;
|
|
||||||
wrapscan.b = b;
|
|
||||||
|
|
||||||
return( vips_sink( in,
|
|
||||||
wrapscan_start, wrapscan_scan, wrapscan_stop,
|
|
||||||
&wrapscan, NULL ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get the value of pixel (0, 0). Use this to init the min/max value for
|
|
||||||
* im_max()/im_stats()/etc.
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
im__value( IMAGE *im, double *value )
|
|
||||||
{
|
|
||||||
IMAGE *t;
|
|
||||||
|
|
||||||
if( !(t = im_open_local( im, "im__value", "p" )) ||
|
|
||||||
im_extract_areabands( im, t, 0, 0, 1, 1, 0, 1 ) ||
|
|
||||||
im_avg( t, value ) )
|
|
||||||
return( -1 );
|
|
||||||
|
|
||||||
return( 0 );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Track min/max/sum/sum-of-squares for each thread during a scan.
|
|
||||||
*/
|
|
||||||
static void *
|
|
||||||
stats_start( IMAGE *im, void *a, void *b )
|
|
||||||
{
|
|
||||||
double *global_stats = (double *) b;
|
|
||||||
|
|
||||||
double *stats;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if( !(stats = IM_ARRAY( NULL, 4 * im->Bands, double )) )
|
|
||||||
return( NULL );
|
|
||||||
|
|
||||||
for( i = 0; i < 4 * im->Bands; i++ )
|
|
||||||
stats[i] = global_stats[i];
|
|
||||||
|
|
||||||
return( stats );
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Merge a thread's output back into the global stats.
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
stats_stop( void *seq, void *a, void *b )
|
|
||||||
{
|
|
||||||
const IMAGE *im = (IMAGE *) a;
|
|
||||||
double *global_stats = (double *) b;
|
|
||||||
double *stats = (double *) seq;
|
|
||||||
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for( i = 0; i < 4 * im->Bands; i += 4 ) {
|
|
||||||
global_stats[0] = IM_MIN( global_stats[0], stats[0] );
|
|
||||||
global_stats[1] = IM_MAX( global_stats[1], stats[1] );
|
|
||||||
global_stats[2] += stats[2];
|
|
||||||
global_stats[3] += stats[3];
|
|
||||||
|
|
||||||
global_stats += 4;
|
|
||||||
stats += 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
im_free( seq );
|
|
||||||
|
|
||||||
return( 0 );
|
|
||||||
}
|
|
||||||
|
|
||||||
/* We scan lines bands times to avoid repeating band loops.
|
|
||||||
* Use temp variables of same type for min/max for faster comparisons.
|
|
||||||
*/
|
|
||||||
#define LOOP( TYPE ) { \
|
|
||||||
for( z = 0; z < im->Bands; z++ ) { \
|
|
||||||
TYPE *q = (TYPE *) in + z; \
|
|
||||||
double *row = stats + z * 4; \
|
|
||||||
TYPE small, big; \
|
|
||||||
double sum, sum2; \
|
|
||||||
\
|
|
||||||
small = row[0]; \
|
|
||||||
big = row[1]; \
|
|
||||||
sum = row[2]; \
|
|
||||||
sum2 = row[3]; \
|
|
||||||
\
|
|
||||||
for( x = 0; x < n; x++ ) { \
|
|
||||||
TYPE value = *q; \
|
|
||||||
\
|
|
||||||
sum += value;\
|
|
||||||
sum2 += (double) value * (double) value;\
|
|
||||||
if( value > big ) \
|
|
||||||
big = value; \
|
|
||||||
else if( value < small ) \
|
|
||||||
small = value;\
|
|
||||||
\
|
|
||||||
q += im->Bands; \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
row[0] = small; \
|
|
||||||
row[1] = big; \
|
|
||||||
row[2] = sum; \
|
|
||||||
row[3] = sum2; \
|
|
||||||
} \
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Loop over region, adding to seq.
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
stats_scan( void *in, int n, void *seq, void *a, void *b )
|
|
||||||
{
|
|
||||||
const IMAGE *im = (IMAGE *) a;
|
|
||||||
|
|
||||||
double *stats = (double *) seq;
|
|
||||||
|
|
||||||
int x, z;
|
|
||||||
|
|
||||||
/* Now generate code for all types.
|
|
||||||
*/
|
|
||||||
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_DOUBLE: LOOP( double ); break;
|
|
||||||
case IM_BANDFMT_FLOAT: LOOP( float ); break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
g_assert( 0 );
|
|
||||||
}
|
|
||||||
|
|
||||||
return( 0 );
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* im_stats:
|
|
||||||
* @in: image to scan
|
|
||||||
*
|
|
||||||
* Find many image statistics in a single pass through the data. 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.
|
|
||||||
*
|
|
||||||
* See also: im_maxpos(), im_min(), im_deviate().
|
|
||||||
*
|
|
||||||
* Returns: 0 on success, -1 on error
|
|
||||||
*/
|
|
||||||
DOUBLEMASK *
|
|
||||||
im_stats( IMAGE *im )
|
|
||||||
{
|
|
||||||
DOUBLEMASK *out;
|
|
||||||
double *row;
|
|
||||||
gint64 pels, vals;
|
|
||||||
double *global_stats;
|
|
||||||
int i, j;
|
|
||||||
double value;
|
|
||||||
|
|
||||||
if( im_pincheck( im ) ||
|
|
||||||
im_check_noncomplex( "im_stats", im ) ||
|
|
||||||
im_check_uncoded( "im_stats", im ) )
|
|
||||||
return( NULL );
|
|
||||||
|
|
||||||
if( !(global_stats = IM_ARRAY( im, 4 * im->Bands, double )) )
|
|
||||||
return( NULL );
|
|
||||||
if( im__value( im, &value ) )
|
|
||||||
return( NULL );
|
|
||||||
for( i = 0; i < 4 * im->Bands; i += 4 ) {
|
|
||||||
global_stats[i + 0] = value;
|
|
||||||
global_stats[i + 1] = value;
|
|
||||||
global_stats[i + 2] = 0.0;
|
|
||||||
global_stats[i + 3] = 0.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Loop over input, calculating min, max, sum, sum^2 for each band
|
|
||||||
* separately.
|
|
||||||
*/
|
|
||||||
if( im__wrapscan( im, stats_start, stats_scan, stats_stop,
|
|
||||||
im, global_stats ) )
|
|
||||||
return( NULL );
|
|
||||||
|
|
||||||
/* Calculate mean, deviation, plus overall stats.
|
|
||||||
*/
|
|
||||||
if( !(out = im_create_dmask( "stats", 6, im->Bands + 1 )) )
|
|
||||||
return( NULL );
|
|
||||||
|
|
||||||
/* Init global max/min/sum/sum2.
|
|
||||||
*/
|
|
||||||
out->coeff[0] = value;
|
|
||||||
out->coeff[1] = value;
|
|
||||||
out->coeff[2] = 0.0;
|
|
||||||
out->coeff[3] = 0.0;
|
|
||||||
|
|
||||||
pels = (gint64) im->Xsize * im->Ysize;
|
|
||||||
vals = pels * im->Bands;
|
|
||||||
|
|
||||||
for( i = 0; i < im->Bands; i++ ) {
|
|
||||||
row = out->coeff + (i + 1) * 6;
|
|
||||||
for( j = 0; j < 4; j++ )
|
|
||||||
row[j] = global_stats[i * 4 + j];
|
|
||||||
|
|
||||||
out->coeff[0] = IM_MIN( out->coeff[0], row[0] );
|
|
||||||
out->coeff[1] = IM_MAX( out->coeff[1], row[1] );
|
|
||||||
out->coeff[2] += row[2];
|
|
||||||
out->coeff[3] += row[3];
|
|
||||||
row[4] = row[2] / pels;
|
|
||||||
row[5] = sqrt( fabs( row[3] - (row[2] * row[2] / pels) ) /
|
|
||||||
(pels - 1) );
|
|
||||||
}
|
|
||||||
out->coeff[4] = out->coeff[2] / vals;
|
|
||||||
out->coeff[5] = sqrt( fabs( out->coeff[3] -
|
|
||||||
(out->coeff[2] * out->coeff[2] / vals) ) / (vals - 1) );
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
printf( "im_stats:\n" );
|
|
||||||
im_print_dmask( out );
|
|
||||||
#endif /*DEBUG*/
|
|
||||||
|
|
||||||
return( out );
|
|
||||||
}
|
|
@ -113,7 +113,7 @@ enum {
|
|||||||
COL_XMAX = 8,
|
COL_XMAX = 8,
|
||||||
COL_YMAX = 9,
|
COL_YMAX = 9,
|
||||||
COL_LAST = 10
|
COL_LAST = 10
|
||||||
}
|
};
|
||||||
|
|
||||||
/* Address a double in our array image.
|
/* Address a double in our array image.
|
||||||
*/
|
*/
|
||||||
@ -125,10 +125,15 @@ vips_stats_build( VipsObject *object )
|
|||||||
VipsStatistic *statistic = VIPS_STATISTIC( object );
|
VipsStatistic *statistic = VIPS_STATISTIC( object );
|
||||||
VipsStats *stats = (VipsStats *) object;
|
VipsStats *stats = (VipsStats *) object;
|
||||||
|
|
||||||
gint64 vals;
|
gint64 vals, pels;
|
||||||
|
double *row0;
|
||||||
|
int b;
|
||||||
|
|
||||||
if( statistic->in ) {
|
if( statistic->in ) {
|
||||||
int bands = vips_image_get_bands( statistic->in->Bands ) : 0;
|
int bands = vips_image_get_bands( statistic->in );
|
||||||
|
|
||||||
|
if( vips_check_noncomplex( "VipsStats", statistic->in ) )
|
||||||
|
return( -1 );
|
||||||
|
|
||||||
g_object_set( object,
|
g_object_set( object,
|
||||||
"out", vips_image_new_array( COL_LAST, bands + 1 ),
|
"out", vips_image_new_array( COL_LAST, bands + 1 ),
|
||||||
@ -138,32 +143,34 @@ vips_stats_build( VipsObject *object )
|
|||||||
if( VIPS_OBJECT_CLASS( vips_stats_parent_class )->build( object ) )
|
if( VIPS_OBJECT_CLASS( vips_stats_parent_class )->build( object ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
vals = (gint64)
|
pels = (gint64)
|
||||||
vips_image_get_width( statistic->in ) *
|
vips_image_get_width( statistic->in ) *
|
||||||
vips_image_get_height( statistic->in ) *
|
vips_image_get_height( statistic->in );
|
||||||
vips_image_get_bands( statistic->in );
|
vals = pels * vips_image_get_bands( statistic->in );
|
||||||
|
|
||||||
|
row0 = ARY( stats->out, 0, 0 );
|
||||||
|
|
||||||
|
row0[COL_MIN] = *ARY( stats->out, 0, COL_MIN );
|
||||||
|
row0[COL_MAX] = *ARY( stats->out, 0, COL_MAX );
|
||||||
|
row0[COL_SUM] = 0;
|
||||||
|
row0[COL_SUM2] = 0;
|
||||||
|
|
||||||
for( b = 0; b < vips_image_get_bands( statistic->in ); b++ ) {
|
for( b = 0; b < vips_image_get_bands( statistic->in ); b++ ) {
|
||||||
|
double *row = ARY( stats->out, 0, b + 1 );
|
||||||
|
|
||||||
|
row0[COL_MIN] = VIPS_MIN( row0[COL_MIN], row[COL_MIN] );
|
||||||
|
row0[COL_MAX] = VIPS_MAX( row0[COL_MAX], row[COL_MAX] );
|
||||||
|
row0[COL_SUM] += row[COL_SUM];
|
||||||
|
row0[COL_SUM2] += row[COL_SUM2];
|
||||||
|
|
||||||
|
row[COL_AVG] = row[COL_SUM] / pels;
|
||||||
|
row[COL_SD] = sqrt( fabs( row[COL_SUM2] -
|
||||||
|
(row[COL_SUM] * row[COL_SUM] / pels) ) / (pels - 1) );
|
||||||
row = out->coeff + (i + 1) * 6;
|
|
||||||
for( j = 0; j < 4; j++ )
|
|
||||||
row[j] = global_stats[i * 4 + j];
|
|
||||||
|
|
||||||
out->coeff[0] = IM_MIN( out->coeff[0], row[0] );
|
|
||||||
out->coeff[1] = IM_MAX( out->coeff[1], row[1] );
|
|
||||||
out->coeff[2] += row[2];
|
|
||||||
out->coeff[3] += row[3];
|
|
||||||
row[4] = row[2] / pels;
|
|
||||||
row[5] = sqrt( fabs( row[3] - (row[2] * row[2] / pels) ) /
|
|
||||||
(pels - 1) );
|
|
||||||
}
|
}
|
||||||
out->coeff[4] = out->coeff[2] / vals;
|
|
||||||
out->coeff[5] = sqrt( fabs( out->coeff[3] -
|
row0[COL_AVG] = row0[COL_SUM] / vals;
|
||||||
(out->coeff[2] * out->coeff[2] / vals) ) / (vals - 1) );
|
row0[COL_SD] = sqrt( fabs( row0[COL_SUM2] -
|
||||||
|
(row0[COL_SUM] * row0[COL_SUM] / vals) ) / (vals - 1) );
|
||||||
|
|
||||||
return( 0 );
|
return( 0 );
|
||||||
}
|
}
|
||||||
@ -173,7 +180,7 @@ vips_stats_build( VipsObject *object )
|
|||||||
static int
|
static int
|
||||||
vips_stats_stop( VipsStatistic *statistic, void *seq )
|
vips_stats_stop( VipsStatistic *statistic, void *seq )
|
||||||
{
|
{
|
||||||
int bands = vips_image_get_bands( statistic->in->Bands );
|
int bands = vips_image_get_bands( statistic->in );
|
||||||
VipsStats *global = (VipsStats *) statistic;
|
VipsStats *global = (VipsStats *) statistic;
|
||||||
VipsStats *local = (VipsStats *) seq;
|
VipsStats *local = (VipsStats *) seq;
|
||||||
|
|
||||||
@ -184,10 +191,10 @@ vips_stats_stop( VipsStatistic *statistic, void *seq )
|
|||||||
double *p = ARY( local->out, 0, b + 1 );
|
double *p = ARY( local->out, 0, b + 1 );
|
||||||
double *q = ARY( global->out, 0, b + 1 );
|
double *q = ARY( global->out, 0, b + 1 );
|
||||||
|
|
||||||
p[COL_MIN] = q[COL_MIN];
|
q[COL_MIN] = p[COL_MIN];
|
||||||
p[COL_MAX] = q[COL_MAX];
|
q[COL_MAX] = p[COL_MAX];
|
||||||
p[COL_SUM] = q[COL_SUM];
|
q[COL_SUM] = p[COL_SUM];
|
||||||
p[COL_SUM2] = q[COL_SUM2];
|
q[COL_SUM2] = p[COL_SUM2];
|
||||||
}
|
}
|
||||||
|
|
||||||
global->set = TRUE;
|
global->set = TRUE;
|
||||||
@ -215,7 +222,7 @@ vips_stats_stop( VipsStatistic *statistic, void *seq )
|
|||||||
static void *
|
static void *
|
||||||
vips_stats_start( VipsStatistic *statistic )
|
vips_stats_start( VipsStatistic *statistic )
|
||||||
{
|
{
|
||||||
int bands = vips_image_get_bands( statistic->in->Bands );
|
int bands = vips_image_get_bands( statistic->in );
|
||||||
|
|
||||||
VipsStats *stats;
|
VipsStats *stats;
|
||||||
|
|
||||||
@ -332,7 +339,7 @@ vips_stats_init( VipsStats *stats )
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
vips_stats( VipsImage *in, double *out, ... )
|
vips_stats( VipsImage *in, VipsImage **out, ... )
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
int result;
|
int result;
|
||||||
|
@ -725,7 +725,7 @@ im__dmsprint( im_object obj )
|
|||||||
band minimum maximum sum sum^2 mean deviation\
|
band minimum maximum sum sum^2 mean deviation\
|
||||||
\n" );
|
\n" );
|
||||||
for( j = 0; j < mask->ysize; j++ ) {
|
for( j = 0; j < mask->ysize; j++ ) {
|
||||||
row = mask->coeff + j * 6;
|
row = mask->coeff + j * mask->xsize;
|
||||||
if( j == 0 )
|
if( j == 0 )
|
||||||
printf( "all" );
|
printf( "all" );
|
||||||
else
|
else
|
||||||
|
@ -1604,3 +1604,21 @@ im_exp10tra( IMAGE *in, IMAGE *out )
|
|||||||
{
|
{
|
||||||
return( vips__math( in, out, VIPS_MATH_OPERATION_EXP10 ) );
|
return( vips__math( in, out, VIPS_MATH_OPERATION_EXP10 ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DOUBLEMASK *
|
||||||
|
im_stats( VipsImage *in )
|
||||||
|
{
|
||||||
|
VipsImage *t;
|
||||||
|
DOUBLEMASK *msk;
|
||||||
|
|
||||||
|
if( vips_stats( in, &t,
|
||||||
|
NULL ) )
|
||||||
|
return( NULL );
|
||||||
|
if( !(msk = im_vips2mask( t, "im_stats" )) ) {
|
||||||
|
g_object_unref( t );
|
||||||
|
return( NULL );
|
||||||
|
}
|
||||||
|
g_object_unref( t );
|
||||||
|
|
||||||
|
return( msk );
|
||||||
|
}
|
||||||
|
@ -96,6 +96,8 @@ int vips_abs( VipsImage *in, VipsImage **out, ... )
|
|||||||
__attribute__((sentinel));
|
__attribute__((sentinel));
|
||||||
int vips_sign( VipsImage *in, VipsImage **out, ... )
|
int vips_sign( VipsImage *in, VipsImage **out, ... )
|
||||||
__attribute__((sentinel));
|
__attribute__((sentinel));
|
||||||
|
int vips_stats( VipsImage *in, VipsImage **out, ... )
|
||||||
|
__attribute__((sentinel));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -104,7 +106,6 @@ DOUBLEMASK *im_measure_area( VipsImage *im,
|
|||||||
int left, int top, int width, int height,
|
int left, int top, int width, int height,
|
||||||
int h, int v,
|
int h, int v,
|
||||||
int *sel, int nsel, const char *name );
|
int *sel, int nsel, const char *name );
|
||||||
DOUBLEMASK *im_stats( VipsImage *in );
|
|
||||||
int im_maxpos_avg( VipsImage *im, double *xpos, double *ypos, double *out );
|
int im_maxpos_avg( VipsImage *im, double *xpos, double *ypos, double *out );
|
||||||
int im_maxpos_vec( VipsImage *im, int *xpos, int *ypos, double *maxima, int n );
|
int im_maxpos_vec( VipsImage *im, int *xpos, int *ypos, double *maxima, int n );
|
||||||
int im_minpos_vec( VipsImage *im, int *xpos, int *ypos, double *minima, int n );
|
int im_minpos_vec( VipsImage *im, int *xpos, int *ypos, double *minima, int n );
|
||||||
|
@ -535,6 +535,7 @@ int im_lintra( double a, VipsImage *in, double b, VipsImage *out );
|
|||||||
int im_lintra_vec( int n, double *a, VipsImage *in, double *b, VipsImage *out );
|
int im_lintra_vec( int n, double *a, VipsImage *in, double *b, VipsImage *out );
|
||||||
int im_abs( VipsImage *in, VipsImage *out );
|
int im_abs( VipsImage *in, VipsImage *out );
|
||||||
int im_sign( VipsImage *in, VipsImage *out );
|
int im_sign( VipsImage *in, VipsImage *out );
|
||||||
|
DOUBLEMASK *im_stats( VipsImage *in );
|
||||||
|
|
||||||
int im_sintra( VipsImage *in, VipsImage *out );
|
int im_sintra( VipsImage *in, VipsImage *out );
|
||||||
int im_costra( VipsImage *in, VipsImage *out );
|
int im_costra( VipsImage *in, VipsImage *out );
|
||||||
|
@ -388,7 +388,8 @@ vips_warn( const char *domain, const char *fmt, ... )
|
|||||||
* @Varargs: arguments to the format string
|
* @Varargs: arguments to the format string
|
||||||
*
|
*
|
||||||
* Sends a formatted error message to stderr, then sends the contents of the
|
* Sends a formatted error message to stderr, then sends the contents of the
|
||||||
* error buffer, if any, then terminates the program with an error code.
|
* error buffer, if any, then shuts down vips and terminates the program with
|
||||||
|
* an error code.
|
||||||
*
|
*
|
||||||
* @fmt may be %NULL, in which case only the error buffer is printed before
|
* @fmt may be %NULL, in which case only the error buffer is printed before
|
||||||
* exiting.
|
* exiting.
|
||||||
@ -412,6 +413,8 @@ vips_error_exit( const char *fmt, ... )
|
|||||||
|
|
||||||
fprintf( stderr, "%s", vips_error_buffer() );
|
fprintf( stderr, "%s", vips_error_buffer() );
|
||||||
|
|
||||||
|
vips_shutdown();
|
||||||
|
|
||||||
exit( 1 );
|
exit( 1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1850,6 +1850,7 @@ vips_object_print_all_cb( VipsObject *object, int *n )
|
|||||||
*n, G_OBJECT_TYPE_NAME( object ), object );
|
*n, G_OBJECT_TYPE_NAME( object ), object );
|
||||||
|
|
||||||
class->print_class( class, &buf );
|
class->print_class( class, &buf );
|
||||||
|
vips_buf_appends( &buf, " " );
|
||||||
class->print( object, &buf );
|
class->print( object, &buf );
|
||||||
fprintf( stderr, "%s\n", vips_buf_all( &buf ) );
|
fprintf( stderr, "%s\n", vips_buf_all( &buf ) );
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user