more stuff

This commit is contained in:
John Cupitt 2009-08-18 15:24:56 +00:00
parent af3489558e
commit 0660bd1400
8 changed files with 242 additions and 221 deletions

View File

@ -21,13 +21,15 @@
- add and use im_check_uncoded() and friends
- matlab load handles column-major and plane-separated images (thanks Mikhail)
- JPEG save allows "none" for profile, meaning don't attach a profile
- saner, simpler, faster typecasting for im_add(), im_subtract()
- im_measure() allows sel == NULL, meaning all patches
25/3/09 started 7.18.0
- revised version numbers
- updated vipsmanual
- revised manpages
- removed name and "changed" from vipsobject since we don't use them yet
- explicitly link with stdc++ for nohalo etc stuff
- explicitly link with stdc++ for nohalo etc. stuff
- wrap im_gauss_imask_sep in C++/Python
6/3/09 started 7.17.3

View File

@ -1127,9 +1127,7 @@ static int
measure_vec( im_object *argv )
{
IMAGE_BOX box;
int h, v, i;
int *sel;
int nsel;
int h, v;
im_mask_object *mo = argv[1];
box.xstart = *((int *) argv[2]);
@ -1141,18 +1139,10 @@ measure_vec( im_object *argv )
h = *((int *) argv[6]);
v = *((int *) argv[7]);
nsel = h * v;
if( !(sel = IM_ARRAY( NULL, nsel, int )) )
return( -1 );
for( i = 0; i < nsel; i++ )
sel[i] = i + 1;
if( !(mo->mask =
im_measure( argv[0], &box, h, v, sel, nsel, mo->name )) ) {
im_free( sel );
im_measure( argv[0], &box, h, v, NULL, 0, mo->name )) ) {
return( -1 );
}
im_free( sel );
return( 0 );
}

View File

@ -104,6 +104,7 @@ add_buffer( PEL **in, PEL *out, int width, IMAGE *im )
case IM_BANDFMT_INT: LOOP( signed int, signed int ); break;
case IM_BANDFMT_FLOAT:
case IM_BANDFMT_COMPLEX:
#ifdef HAVE_LIBOIL
oil_add_f32( (float *) out,
(float *) in[0], (float *) in[1], sz );
@ -112,9 +113,10 @@ add_buffer( PEL **in, PEL *out, int width, IMAGE *im )
#endif /*HAVE_LIBOIL*/
break;
case IM_BANDFMT_DOUBLE: LOOP( double, double ); break;
case IM_BANDFMT_COMPLEX:LOOP( float, float ); break;
case IM_BANDFMT_DPCOMPLEX:LOOP( double, double ); break;
case IM_BANDFMT_DOUBLE:
case IM_BANDFMT_DPCOMPLEX:
LOOP( double, double );
break;
default:
assert( 0 );

View File

@ -1,12 +1,4 @@
/* @(#) Find the average of an image. Takes any non-complex image format,
* @(#) returns a double. Finds the average of all bands.
* @(#)
* @(#) int
* @(#) im_avg( im, out )
* @(#) IMAGE *im;
* @(#) double *out;
* @(#)
* @(#) Returns 0 on success and -1 on error.
/* im_avg.c
*
* Copyright: 1990, J. Cupitt
*
@ -29,6 +21,8 @@
* - use 64 bit arithmetic
* 8/12/06
* - add liboil support
* 18/8/09
* - gtkdoc, minor reformatting
*/
/*
@ -123,27 +117,27 @@ scan_fn( REGION *reg, void *seq, void *a, void *b )
/* 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++;\
}\
}
#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 ) {
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_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:
#ifdef HAVE_LIBOIL
@ -156,7 +150,7 @@ scan_fn( REGION *reg, void *seq, void *a, void *b )
sum += t;
}
#else /*!HAVE_LIBOIL*/
loop(double);
LOOP( double );
#endif /*HAVE_LIBOIL*/
break;
@ -171,11 +165,24 @@ scan_fn( REGION *reg, void *seq, void *a, void *b )
return( 0 );
}
/* Find the average of an image.
/**
* im_avg:
* @in: input #IMAGE
* @out: output pixel average
*
* This operation finds the average value in an image. It operates on all
* bands of the input image: use im_stats() if you need to calculate an
* average for each band.
*
* Non-complex images only.
*
* See also: im_stats(), im_bandmean(), im_deviate(), im_rank()
*
* Returns: 0 on success, -1 on error
*/
int
im_avg( IMAGE *in, double *out )
{
{
double sum = 0.0;
gint64 vals, pels;

View File

@ -1,15 +1,12 @@
/* @(#) Average the bands in an image.
* @(#)
* @(#) int
* @(#) im_bandmean(in, out)
* @(#) IMAGE *in, *out;
* @(#)
* @(#) Returns 0 on success and -1 on error
/* im_bandmean.c
*
* Author: Simon Goodall
* Written on: 17/7/07
* 17/7/07 JC
* - hacked about a bit
* 18/8/09
* - gtkdoc
* - get rid of the complex case, just double the width
*/
/*
@ -58,13 +55,13 @@
TYPE *p1 = (TYPE *) p; \
TYPE *q1 = (TYPE *) q; \
\
for( i = 0; i < n; i++ ) { \
for( i = 0; i < sz; i++ ) { \
STYPE sum; \
\
sum = 0; \
for( j = 0; j < b; j++ ) \
sum += p1[j]; \
*q1++ = sum > 0 ? (sum + b / 2) / b : (sum - b / 2) / b; \
q1[i] = sum > 0 ? (sum + b / 2) / b : (sum - b / 2) / b; \
p1 += b; \
} \
}
@ -75,45 +72,27 @@
TYPE *p1 = (TYPE *) p; \
TYPE *q1 = (TYPE *) q; \
\
for( i = 0; i < n; i++ ) { \
for( i = 0; i < sz; i++ ) { \
TYPE sum; \
\
sum = 0; \
for( j = 0; j < b; j++ ) \
sum += p1[j]; \
*q1++ = sum / b; \
q1[i] = sum / b; \
p1 += b; \
} \
}
/* Complex loop. Mean reals and imaginaries separately.
*/
#define CLOOP( TYPE ) { \
TYPE *p1 = (TYPE *) p; \
TYPE *q1 = (TYPE *) q; \
\
for( i = 0; i < n * 2; i += 2 ) { \
TYPE sum; \
\
sum = 0; \
for( j = 0; j < b; j++ ) \
sum += p1[j * 2]; \
q1[0] = sum / b; \
sum = 0; \
for( j = 0; j < b; j++ ) \
sum += p1[j * 2 + 1]; \
q1[1] = sum / b; \
p1 += b; \
q1 += 2; \
} \
}
static void
bandmean_buffer( PEL *p, PEL *q, int n, IMAGE *in )
{
int i, j;
/* Complex just doubles the size.
*/
const int sz = n * (im_iscomplex( in ) ? 2 : 1);
const int b = in->Bands;
int i, j;
switch( in->BandFmt ) {
case IM_BANDFMT_CHAR: ILOOP( signed char, int ); break;
case IM_BANDFMT_UCHAR: ILOOP( unsigned char, unsigned int ); break;
@ -123,14 +102,28 @@ bandmean_buffer( PEL *p, PEL *q, int n, IMAGE *in )
case IM_BANDFMT_UINT: ILOOP( unsigned int, unsigned int ); break;
case IM_BANDFMT_FLOAT: FLOOP( float ); break;
case IM_BANDFMT_DOUBLE: FLOOP( double ); break;
case IM_BANDFMT_COMPLEX: CLOOP( float ); break;
case IM_BANDFMT_DPCOMPLEX: CLOOP( double ); break;
case IM_BANDFMT_COMPLEX:FLOOP( float ); break;
case IM_BANDFMT_DPCOMPLEX:FLOOP( double ); break;
default:
assert( 0 );
}
}
/**
* im_bandmean:
* @in: input #IMAGE
* @out: output #IMAGE
*
* im_bandmean() writes a one-band image where each pixel is the average of
* the bands for that pixel in the input image. The output band format is
* the same as the input band format. Integer types use round-to-nearest
* averaging.
*
* See also: im_add(), im_avg(), im_recomb()
*
* Returns: 0 on success, -1 on error
*/
int
im_bandmean( IMAGE *in, IMAGE *out )
{

View File

@ -152,25 +152,38 @@ measure_patches( IMAGE *im, double *coeff, IMAGE_BOX *box,
* @name: name to give to returned @DOUBLEMASK
*
* Analyse a grid of colour patches, producing a #DOUBLEMASK of patch averages.
* The operations issues a warning if any patch has a deviation more than 20% of
* the mean. Only the central 50% of each patch is averaged.
* The mask has a row for each measured patch, and a column for each image
* band. The operations issues a warning if any patch has a deviation more
* than 20% of
* the mean. Only the central 50% of each patch is averaged. If @sel is %NULL
* then all patches are measured.
*
* Example: 6 band image of 4x2 block of colour patches.
*
* +---+---+---+---+
* | 1 | 2 | 3 | 4 |
* +---+---+---+---+
* | 5 | 6 | 7 | 8 |
* +---+---+---+---+
*
* <tgroup cols='4' align='left' colsep='1' rowsep='1'>
* <tbody>
* <row>
* <entry>1</entry>
* <entry>2</entry>
* <entry>3</entry>
* <entry>4</entry>
* </row>
* <row>
* <entry>5</entry>
* <entry>6</entry>
* <entry>7</entry>
* <entry>8</entry>
* </row>
* </tbody>
* </tgroup>
*
* Then call im_measure( im, box, 4, 2, { 2, 4 }, 2, "fred" ) makes a mask
* "fred" which has 6 columns, two rows. The first row contains the averages
* for patch 2, the second for patch 4.
*
* Returns: #DOUBLEMASK with a row for each selected patch, a column for each
* image band.
*
* Related: im_avg(), im_deviate(), im_stats().
* See also: im_avg(), im_deviate(), im_stats().
*
* Returns: #DOUBLEMASK of measurements.
*/
DOUBLEMASK *
im_measure( IMAGE *im, IMAGE_BOX *box, int h, int v,
@ -197,13 +210,20 @@ im_measure( IMAGE *im, IMAGE_BOX *box, int h, int v,
return( mask );
}
if( im->Coding != IM_CODING_NONE ) {
im_error( "im_measure", "%s", _( "not uncoded" ) );
return( NULL );
}
if( im_iscomplex( im ) ) {
im_error( "im_measure", "%s", _( "bad input type" ) );
if( im_check_uncoded( "im_measure", im ) ||
im_check_noncomplex( "im_measure", im ) )
return( NULL );
/* Default to all patches if sel == NULL.
*/
if( sel == NULL ) {
int i;
nsel = h * v;
if( !(sel = IM_ARRAY( im, nsel, int )) )
return( NULL );
for( i = 0; i < nsel; i++ )
sel[i] = i + 1;
}
/* What size mask do we need?

View File

@ -29,6 +29,10 @@
* - updated for 1 band $op n band image -> n band image case
* 8/12/06
* - add liboil support
* 18/8/08
* - revise upcasting system
* - add gtkdoc comments
* - remove separate complex case, just double size
*/
/*
@ -78,77 +82,49 @@
#include <dmalloc.h>
#endif /*WITH_DMALLOC*/
/* Swap two IMAGE pointers.
*/
#define SWAP(A,B) { \
IMAGE *t; \
t = (A); (A) = (B); (B) = t; \
}
/* Complex multiply.
*/
#define cloop(TYPE) \
{\
TYPE *p1 = (TYPE *) in[0];\
TYPE *p2 = (TYPE *) in[1];\
TYPE *q = (TYPE *) out;\
#define LOOP( IN, OUT ) { \
IN *p1 = (IN *) in[0]; \
IN *p2 = (IN *) in[1]; \
OUT *q = (OUT *) out; \
\
for( x = 0; x < sz; x++ ) {\
double x1 = p1[0];\
double y1 = p1[1];\
double x2 = p2[0];\
double y2 = p2[1];\
\
p1 += 2;\
p2 += 2;\
\
q[0] = x1 * x2 - y1 * y2;\
q[1] = x1 * y2 + x2 * y1;\
\
q += 2;\
}\
}
/* Real multiply.
*/
#define rloop(TYPE) \
{\
TYPE *p1 = (TYPE *) in[0];\
TYPE *p2 = (TYPE *) in[1];\
TYPE *q = (TYPE *) out;\
\
for( x = 0; x < sz; x++ )\
q[x] = p1[x] * p2[x];\
for( x = 0; x < sz; x++ ) \
q[x] = p1[x] * p2[x]; \
}
static void
multiply_buffer( PEL **in, PEL *out, int width, IMAGE *im )
{
int x;
int sz = width * im->Bands;
/* Complex just doubles the size.
*/
const int sz = width * im->Bands * (im_iscomplex( im ) ? 2 : 1);
/* Multiply all input types.
int x;
/* Multiply all input types. Keep types here in sync with
* bandfmt_multiply[] below.
*/
switch( im->BandFmt ) {
case IM_BANDFMT_CHAR: rloop( signed char ); break;
case IM_BANDFMT_UCHAR: rloop( unsigned char ); break;
case IM_BANDFMT_SHORT: rloop( signed short ); break;
case IM_BANDFMT_USHORT: rloop( unsigned short ); break;
case IM_BANDFMT_INT: rloop( signed int ); break;
case IM_BANDFMT_UINT: rloop( unsigned int ); break;
case IM_BANDFMT_CHAR: LOOP( signed char, signed short ); break;
case IM_BANDFMT_UCHAR: LOOP( unsigned char, unsigned short ); break;
case IM_BANDFMT_SHORT: LOOP( signed short, signed int ); break;
case IM_BANDFMT_USHORT: LOOP( unsigned short, unsigned int ); break;
case IM_BANDFMT_INT: LOOP( signed int, signed int ); break;
case IM_BANDFMT_UINT: LOOP( unsigned int, unsigned int ); break;
case IM_BANDFMT_FLOAT:
case IM_BANDFMT_COMPLEX:
#ifdef HAVE_LIBOIL
oil_multiply_f32( (float *) out,
(float *) in[0], (float *) in[1], sz );
#else /*!HAVE_LIBOIL*/
rloop( float );
LOOP( float, float );
#endif /*HAVE_LIBOIL*/
break;
case IM_BANDFMT_DOUBLE: rloop( double ); break;
case IM_BANDFMT_COMPLEX: cloop( float ); break;
case IM_BANDFMT_DPCOMPLEX: cloop( double ); break;
case IM_BANDFMT_DOUBLE:
case IM_BANDFMT_DPCOMPLEX:
LOOP( double, double );
break;
default:
assert( 0 );
@ -164,45 +140,108 @@ multiply_buffer( PEL **in, PEL *out, int width, IMAGE *im )
#define UI IM_BANDFMT_UINT
#define I IM_BANDFMT_INT
#define F IM_BANDFMT_FLOAT
#define M IM_BANDFMT_COMPLEX
#define X IM_BANDFMT_COMPLEX
#define D IM_BANDFMT_DOUBLE
#define DM IM_BANDFMT_DPCOMPLEX
#define DX IM_BANDFMT_DPCOMPLEX
/* Type conversions for two integer inputs. Rules for float and complex
* encoded with ifs. We are sign and value preserving.
/* Type promotion for multiplication. Sign and value preserving. Make sure
* these match the case statement in multiply_buffer() above.
*/
static int iformat[6][6] = {
/* UC C US S UI I */
/* UC */ { US, S, UI, I, UI, I },
/* C */ { S, S, I, I, I, I },
/* US */ { UI, I, UI, I, UI, I },
/* S */ { I, I, I, I, I, I },
/* UI */ { UI, I, UI, I, UI, I },
/* I */ { I, I, I, I, I, I }
static int bandfmt_multiply[10] = {
/* UC C US S UI I F X D DX */
US, S, UI, I, UI, I, F, X, D, DX
};
/**
* im_multiply:
* @in1: input #IMAGE 1
* @in2: input #IMAGE 2
* @out: output #IMAGE
*
* This operation calculates @in1 * @in2 and writes the result to @out.
* The images must be the same size. They may have any format.
*
* If the number of bands differs, one of the images
* must have one band. In this case, an n-band image is formed from the
* one-band image by joining n copies of the one-band image together, and then
* the two n-band images are operated upon.
*
* The two input images are cast up to the smallest common type (see table
* Smallest common format in
* <link linkend="VIPS-arithmetic">arithmetic</link>), then the
* following table is used to determine the output type:
*
* <table>
* <title>im_add() type promotion</title>
* <tgroup cols='2' align='left' colsep='1' rowsep='1'>
* <thead>
* <row>
* <entry>input type</entry>
* <entry>output type</entry>
* </row>
* </thead>
* <tbody>
* <row>
* <entry>uchar</entry>
* <entry>ushort</entry>
* </row>
* <row>
* <entry>char</entry>
* <entry>short</entry>
* </row>
* <row>
* <entry>ushort</entry>
* <entry>uint</entry>
* </row>
* <row>
* <entry>short</entry>
* <entry>int</entry>
* </row>
* <row>
* <entry>uint</entry>
* <entry>uint</entry>
* </row>
* <row>
* <entry>int</entry>
* <entry>int</entry>
* </row>
* <row>
* <entry>float</entry>
* <entry>float</entry>
* </row>
* <row>
* <entry>double</entry>
* <entry>double</entry>
* </row>
* <row>
* <entry>complex</entry>
* <entry>complex</entry>
* </row>
* <row>
* <entry>double complex</entry>
* <entry>double complex</entry>
* </row>
* </tbody>
* </tgroup>
* </table>
*
* In other words, the output type is just large enough to hold the whole
* range of possible values.
*
* See also: im_divide(), im_lintra().
*
* Returns: 0 on success, -1 on error
*/
int
im_multiply( IMAGE *in1, IMAGE *in2, IMAGE *out )
{
/* Basic checks.
*/
if( im_piocheck( in1, out ) || im_pincheck( in2 ) )
if( im_piocheck( in1, out ) ||
im_pincheck( in2 ) ||
im_check_bands_1orn( "im_multiply", in1, in2 ) ||
im_check_uncoded( "im_multiply", in1 ) ||
im_check_uncoded( "im_multiply", in2 ) )
return( -1 );
if( in1->Xsize != in2->Xsize || in1->Ysize != in2->Ysize ) {
im_error( "im_multiply", "%s", _( "not same size" ) );
return( -1 );
}
if( in1->Bands != in2->Bands &&
(in1->Bands != 1 && in2->Bands != 1) ) {
im_error( "im_multiply",
"%s", _( "not same number of bands" ) );
return( -1 );
}
if( in1->Coding != IM_CODING_NONE || in2->Coding != IM_CODING_NONE ) {
im_error( "im_multiply", "%s", _( "not uncoded" ) );
return( -1 );
}
if( im_cp_descv( out, in1, in2, NULL ) )
return( -1 );
@ -210,45 +249,10 @@ im_multiply( IMAGE *in1, IMAGE *in2, IMAGE *out )
*/
out->Bands = IM_MAX( in1->Bands, in2->Bands );
/* Swap arguments to get the largest on the left.
*/
if( in1->Bbits < in2->Bbits )
SWAP( in1, in2 );
/* What output type will we write? int, float or complex.
*/
if( im_iscomplex( in1 ) || im_iscomplex( in2 ) ) {
/* Make sure we have complex on the left.
*/
if( !im_iscomplex( in1 ) )
SWAP( in1, in2 );
/* What kind of complex?
*/
if( in1->BandFmt == IM_BANDFMT_DPCOMPLEX )
/* Output will be DPCOMPLEX.
*/
out->BandFmt = IM_BANDFMT_DPCOMPLEX;
else
out->BandFmt = IM_BANDFMT_COMPLEX;
}
else if( im_isfloat( in1 ) || im_isfloat( in2 ) ) {
/* Make sure we have float on the left.
*/
if( !im_isfloat( in1 ) )
SWAP( in1, in2 );
/* What kind of float?
*/
if( in1->BandFmt == IM_BANDFMT_DOUBLE )
out->BandFmt = IM_BANDFMT_DOUBLE;
else
out->BandFmt = IM_BANDFMT_FLOAT;
}
else
/* Must be int+int = int.
*/
out->BandFmt = iformat[in2->BandFmt][in1->BandFmt];
out->BandFmt = bandfmt_multiply[im__format_common( in1, in2 )];
out->Bbits = im_bits_of_fmt( out->BandFmt );
/* And process!
*/

View File

@ -113,7 +113,9 @@ subtract_buffer( PEL **in, PEL *out, int width, IMAGE *im )
case IM_BANDFMT_USHORT: LOOP( unsigned short, signed int ); break;
case IM_BANDFMT_INT: LOOP( signed int, signed int ); break;
case IM_BANDFMT_UINT: LOOP( unsigned int, signed int ); break;
case IM_BANDFMT_FLOAT:
case IM_BANDFMT_COMPLEX:
#ifdef HAVE_LIBOIL
oil_subtract_f32( (float *) out,
(float *) in[0], (float *) in[1], sz );
@ -122,9 +124,10 @@ subtract_buffer( PEL **in, PEL *out, int width, IMAGE *im )
#endif /*HAVE_LIBOIL*/
break;
case IM_BANDFMT_DOUBLE: LOOP( double, double ); break;
case IM_BANDFMT_COMPLEX:LOOP( float, float ); break;
case IM_BANDFMT_DPCOMPLEX:LOOP( double, double ); break;
case IM_BANDFMT_DOUBLE:
case IM_BANDFMT_DPCOMPLEX:
LOOP( double, double );
break;
default:
assert( 0 );