diff --git a/ChangeLog b/ChangeLog
index 2104e2a5..d351ebec 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -22,7 +22,8 @@
- 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_multiply(), im_divide()
+ im_multiply(), im_divide(), im_remainder()
+- im_remainder() has a float result for float types
- im_measure() allows sel == NULL, meaning all patches
25/3/09 started 7.18.0
diff --git a/README b/README
index 3211b68d..3b4c3cd1 100644
--- a/README
+++ b/README
@@ -9,24 +9,14 @@ colour. There's a GUI as well, see the VIPS website:
There are packages for most linuxes and OS X. There is a pre-compiled windows
binary on the vips website.
-Getting VIPS from SVN
-=====================
-
-Enter:
-
- svn co https://vips.svn.sourceforge.net/svnroot/vips/vips7
-
Building VIPS from source
=========================
In the VIPS directory, you should just be able to do:
- user% ./configure
- user% make
-
-then as root:
-
- root% make install
+ $ ./configure
+ $ make
+ $ sudo make install
By default this will install files to /usr/local.
@@ -49,6 +39,20 @@ There are packages in macports.
http://www.macports.org
+Building VIPS from SVN
+----------------------
+
+Checkout the latest sources with:
+
+ svn co https://vips.svn.sourceforge.net/svnroot/vips/vips7
+
+Then:
+
+ $ ./bootstrap.sh
+ $ CFLAGS="-g -Wall" CXXFLAGS="-g -Wall" ./configure --prefix=/home/john/vips --enable-gtk-doc
+ $ make
+ $ make install
+
Dependencies
============
diff --git a/libvips/arithmetic/arith_dispatch.c b/libvips/arithmetic/arith_dispatch.c
index 0c2fb31f..c4c22f57 100644
--- a/libvips/arithmetic/arith_dispatch.c
+++ b/libvips/arithmetic/arith_dispatch.c
@@ -44,7 +44,7 @@
/**
* SECTION: arithmetic
- * @short_description: operations which perform pixel arithmetic
+ * @short_description: operations which perform pixel arithmetic, trig, log
*
* @see_also: iofuncs
* @stability: Stable
diff --git a/libvips/arithmetic/im_remainder.c b/libvips/arithmetic/im_remainder.c
index ca317e1c..a90e5c69 100644
--- a/libvips/arithmetic/im_remainder.c
+++ b/libvips/arithmetic/im_remainder.c
@@ -11,6 +11,9 @@
* - oop, broken for _vec case :-(
* 14/5/08
* - better /0 test
+ * 27/8/08
+ * - revise upcasting system
+ * - add gtkdoc comments
*/
/*
@@ -56,7 +59,9 @@
#include
#endif /*WITH_DMALLOC*/
-#define RLOOP( IN, OUT ) { \
+/* Integer remainder-after-division.
+ */
+#define ILOOP( IN, OUT ) { \
IN *p1 = (IN *) in[0]; \
IN *p2 = (IN *) in[1]; \
OUT *q = (OUT *) out; \
@@ -68,19 +73,21 @@
q[x] = -1; \
}
-#define CLOOP( IN ) { \
+/* Float remainder-after-division.
+ */
+#define FLOOP( IN, OUT ) { \
IN *p1 = (IN *) in[0]; \
IN *p2 = (IN *) in[1]; \
- signed int *q = (signed int *) out; \
+ OUT *q = (OUT *) out; \
\
for( x = 0; x < sz; x++ ) { \
- if( p2[0] ) \
- q[x] = (int) p1[0] % (int) p2[0]; \
+ double a = p1[x]; \
+ double b = p2[x]; \
+ \
+ if( b ) \
+ q[x] = a - b * floor (a / b); \
else \
q[x] = -1; \
- \
- p1 += 2; \
- p2 += 2; \
} \
}
@@ -91,16 +98,14 @@ remainder_buffer( PEL **in, PEL *out, int width, IMAGE *im )
int sz = width * im->Bands;
switch( im->BandFmt ) {
- case IM_BANDFMT_CHAR: RLOOP( signed char, signed char ); break;
- case IM_BANDFMT_UCHAR: RLOOP( unsigned char, unsigned char ); break;
- case IM_BANDFMT_SHORT: RLOOP( signed short, signed short ); break;
- case IM_BANDFMT_USHORT: RLOOP( unsigned short, unsigned short ); break;
- case IM_BANDFMT_INT: RLOOP( signed int, signed int ); break;
- case IM_BANDFMT_UINT: RLOOP( unsigned int, unsigned int ); break;
- case IM_BANDFMT_FLOAT: RLOOP( float, signed int ); break;
- case IM_BANDFMT_COMPLEX:CLOOP( float ); break;
- case IM_BANDFMT_DOUBLE: RLOOP( double, signed int ); break;
- case IM_BANDFMT_DPCOMPLEX: CLOOP( double ); break;
+ case IM_BANDFMT_CHAR: ILOOP( signed char, signed char ); break;
+ case IM_BANDFMT_UCHAR: ILOOP( unsigned char, unsigned char ); break;
+ case IM_BANDFMT_SHORT: ILOOP( signed short, signed short ); break;
+ case IM_BANDFMT_USHORT: ILOOP( unsigned short, unsigned short ); break;
+ case IM_BANDFMT_INT: ILOOP( signed int, signed int ); break;
+ case IM_BANDFMT_UINT: ILOOP( unsigned int, unsigned int ); break;
+ case IM_BANDFMT_FLOAT: FLOOP( float, float ); break;
+ case IM_BANDFMT_DOUBLE: FLOOP( double, double ); break;
default:
assert( 0 );
@@ -125,18 +130,33 @@ remainder_buffer( PEL **in, PEL *out, int width, IMAGE *im )
*/
static int bandfmt_remainder[10] = {
/* UC C US S UI I F X D DX */
- UC, C, US, S, UI, I, I, I, I, I
+ UC, C, US, S, UI, I, F, X, D, DX
};
-/*
-.B im_remainder(3)
-calculates the remainder after integer division of two images. The output
-type is the same as the type of
-.B in1
-unless
-.B in1
-is float or complex, in which
-case the output type is signed integer.
+/**
+ * im_remainder:
+ * @in1: input #IMAGE 1
+ * @in2: input #IMAGE 2
+ * @out: output #IMAGE
+ *
+ * This operation calculates @in1 % @in2 (remainder after division) and writes
+ * the result to @out. The images must be the same size. They may have any
+ * non-complex format. For float types, im_remainder() calculates a - b *
+ * floor (a / b).
+ *
+ * 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
+ * arithmetic), and that format is the
+ * result type.
+ *
+ * See also: im_remainderconst(), im_divide().
+ *
+ * Returns: 0 on success, -1 on error
*/
int
im_remainder( IMAGE *in1, IMAGE *in2, IMAGE *out )
@@ -145,7 +165,9 @@ im_remainder( IMAGE *in1, IMAGE *in2, IMAGE *out )
im_pincheck( in2 ) ||
im_check_bands_1orn( "im_remainder", in1, in2 ) ||
im_check_uncoded( "im_remainder", in1 ) ||
- im_check_uncoded( "im_remainder", in2 ) )
+ im_check_uncoded( "im_remainder", in2 ) ||
+ im_check_noncomplex( "im_remainder", in1 ) ||
+ im_check_noncomplex( "im_remainder", in2 ) )
return( -1 );
if( im_cp_descv( out, in1, in2, NULL ) )
@@ -155,8 +177,7 @@ im_remainder( IMAGE *in1, IMAGE *in2, IMAGE *out )
*/
out->Bands = IM_MAX( in1->Bands, in2->Bands );
- /* What output type will we write? Same as LHS type, except float
- * and double become signed int.
+ /* What output type will we write? Same as LHS type.
*/
out->BandFmt = bandfmt_remainder[im__format_common( in1, in2 )];
out->Bbits = im_bits_of_fmt( out->BandFmt );
@@ -181,7 +202,9 @@ typedef struct _Remainderconst {
int *c;
} Remainderconst;
-#define const1_loop(TYPE) {\
+/* Integer remainder-after-divide.
+ */
+#define ICONST1LOOP( TYPE ) { \
TYPE *p = (TYPE *) in; \
TYPE *q = (TYPE *) out; \
\
@@ -198,19 +221,19 @@ remainderconst1_buffer( PEL *in, PEL *out, int width, Remainderconst *rc )
int x;
switch( im->BandFmt ) {
- case IM_BANDFMT_CHAR: const1_loop( signed char ); break;
- case IM_BANDFMT_UCHAR: const1_loop( unsigned char ); break;
- case IM_BANDFMT_SHORT: const1_loop( signed short ); break;
- case IM_BANDFMT_USHORT: const1_loop( unsigned short ); break;
- case IM_BANDFMT_INT: const1_loop( signed int ); break;
- case IM_BANDFMT_UINT: const1_loop( unsigned int ); break;
+ case IM_BANDFMT_CHAR: ICONST1LOOP( signed char ); break;
+ case IM_BANDFMT_UCHAR: ICONST1LOOP( unsigned char ); break;
+ case IM_BANDFMT_SHORT: ICONST1LOOP( signed short ); break;
+ case IM_BANDFMT_USHORT: ICONST1LOOP( unsigned short ); break;
+ case IM_BANDFMT_INT: ICONST1LOOP( signed int ); break;
+ case IM_BANDFMT_UINT: ICONST1LOOP( unsigned int ); break;
default:
assert( 0 );
}
}
-#define const_loop(TYPE) {\
+#define ICONSTLOOP( TYPE ) { \
TYPE *p = (TYPE *) in; \
TYPE *q = (TYPE *) out; \
\
@@ -228,18 +251,37 @@ remainderconst_buffer( PEL *in, PEL *out, int width, Remainderconst *rc )
int i, x, k;
switch( im->BandFmt ) {
- case IM_BANDFMT_CHAR: const_loop( signed char ); break;
- case IM_BANDFMT_UCHAR: const_loop( unsigned char ); break;
- case IM_BANDFMT_SHORT: const_loop( signed short ); break;
- case IM_BANDFMT_USHORT: const_loop( unsigned short ); break;
- case IM_BANDFMT_INT: const_loop( signed int ); break;
- case IM_BANDFMT_UINT: const_loop( unsigned int ); break;
+ case IM_BANDFMT_CHAR: ICONSTLOOP( signed char ); break;
+ case IM_BANDFMT_UCHAR: ICONSTLOOP( unsigned char ); break;
+ case IM_BANDFMT_SHORT: ICONSTLOOP( signed short ); break;
+ case IM_BANDFMT_USHORT: ICONSTLOOP( unsigned short ); break;
+ case IM_BANDFMT_INT: ICONSTLOOP( signed int ); break;
+ case IM_BANDFMT_UINT: ICONSTLOOP( unsigned int ); break;
default:
assert( 0 );
}
}
+/**
+ * im_remainderconst_vec:
+ * @in: input #IMAGE
+ * @out: output #IMAGE
+ * @n: number of elements in array
+ * @c: array of constants
+ *
+ * This operation calculates @in % @c (remainder after division by constant)
+ * and writes the result to @out. The image must be one of the integer types.
+ *
+ * If the array of constants has one element, that constant is used for each
+ * image band. If the array has more than one element, it must have the same
+ * number of elements as there are bands in the image, and one array element
+ * is used for each band.
+ *
+ * See also: im_remainder(), im_divide().
+ *
+ * Returns: 0 on success, -1 on error
+ */
int
im_remainderconst_vec( IMAGE *in, IMAGE *out, int n, double *c )
{
@@ -248,21 +290,15 @@ im_remainderconst_vec( IMAGE *in, IMAGE *out, int n, double *c )
/* Basic checks.
*/
- if( im_piocheck( in, out ) )
+ if( im_piocheck( in, out ) ||
+ im_check_vector( "im_remainder", n, in ) ||
+ im_check_uncoded( "im_remainder", in ) ||
+ im_check_int( "im_remainder", in ) )
return( -1 );
- if( in->Coding != IM_CODING_NONE ) {
- im_error( "im_remainderconst_vec", "%s", _( "not uncoded" ) );
- return( -1 );
- }
- if( n != 1 && n != in->Bands ) {
- im_error( "im_remainderconst_vec",
- _( "not 1 or %d elements in vector" ), in->Bands );
- return( -1 );
- }
if( im_cp_desc( out, in ) )
return( -1 );
- /* Make space for a little buffer.
+ /* Take a copy of the parameters.
*/
if( !(rc = IM_NEW( out, Remainderconst )) ||
!(rc->c = IM_ARRAY( out, n, int )) )
@@ -274,6 +310,10 @@ im_remainderconst_vec( IMAGE *in, IMAGE *out, int n, double *c )
/* Cast down to int ... we pass in double for consistency with
* the other _vec functions.
*/
+ if( c[i] != (int) c[i] )
+ im_warn( "im_remainderconst_vec",
+ _( "float constant %g truncated to integer" ),
+ c[i] );
rc->c[i] = c[i];
if( rc->c[i] == 0 ) {
@@ -283,20 +323,6 @@ im_remainderconst_vec( IMAGE *in, IMAGE *out, int n, double *c )
}
}
- /* What output type will we write? Same as input type, except float
- * and double become signed int.
- */
- if( im_isfloat( in ) || im_iscomplex( in ) ) {
- IMAGE *t = im_open_local( out, "im_remainderconst:1", "p" );
-
- out->BandFmt = IM_BANDFMT_INT;
- out->Bbits = IM_BBITS_INT;
- if( !t || im_clip2fmt( in, t, out->BandFmt ) )
- return( -1 );
-
- rc->in = in = t;
- }
-
if( n == 1 ) {
if( im_wrapone( in, out,
(im_wrapone_fn) remainderconst1_buffer, rc, NULL ) )
@@ -311,6 +337,19 @@ im_remainderconst_vec( IMAGE *in, IMAGE *out, int n, double *c )
return( 0 );
}
+/**
+ * im_remainderconst:
+ * @in: input #IMAGE
+ * @out: output #IMAGE
+ * @c: constant
+ *
+ * This operation calculates @in % @c (remainder after division by constant)
+ * and writes the result to @out. The image must be one of the integer types.
+ *
+ * See also: im_remainderconst_vec(), im_divide().
+ *
+ * Returns: 0 on success, -1 on error
+ */
int
im_remainderconst( IMAGE *in, IMAGE *out, double c )
{
diff --git a/libvips/include/vips/proto.h b/libvips/include/vips/proto.h
index 2bde108b..d0951235 100644
--- a/libvips/include/vips/proto.h
+++ b/libvips/include/vips/proto.h
@@ -140,6 +140,7 @@ int im_check_uncoded( const char *domain, IMAGE *im );
int im_check_bands_1orn( const char *domain, IMAGE *im1, IMAGE *im2 );
int im_check_noncomplex( const char *domain, IMAGE *im );
int im_check_complex( const char *domain, IMAGE *im );
+int im_check_int( const char *domain, IMAGE *im );
int im_check_size( const char *domain, IMAGE *im1, IMAGE *im2 );
int im_check_bands( const char *domain, IMAGE *im1, IMAGE *im2 );
int im_check_format( const char *domain, IMAGE *im1, IMAGE *im2 );
diff --git a/libvips/iofuncs/predicate.c b/libvips/iofuncs/predicate.c
index cd79ca1c..c5ae91f3 100644
--- a/libvips/iofuncs/predicate.c
+++ b/libvips/iofuncs/predicate.c
@@ -406,6 +406,17 @@ im_check_complex( const char *domain, IMAGE *im )
return( 0 );
}
+int
+im_check_int( const char *domain, IMAGE *im )
+{
+ if( !im_isint( im ) ) {
+ im_error( domain, "%s", _( "image must be integer" ) );
+ return( -1 );
+ }
+
+ return( 0 );
+}
+
int
im_check_size( const char *domain, IMAGE *im1, IMAGE *im2 )
{