diff --git a/bootstrap.sh b/bootstrap.sh index d5b9a7fb..76dd6efc 100755 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -12,7 +12,7 @@ rm -f swig/vipsCC/*.cxx rm -f swig/vipsCC/VImage.h rm -f swig/vipsCC/VImage.py python/vipsCC/VError.py python/vipsCC/VMask.py python/vipsCC/Display.py rm -f benchmark/temp* -( cd doc ; mkdir poop ; mv reference/VIPS-docs.sgml.in poop ; mv reference/Makefile.am poop ; rm -rf reference/* ; mv poop/* reference ; rmdir poop ) +( cd doc ; mkdir poop ; mv reference/libvips-docs.sgml.in poop ; mv reference/Makefile.am poop ; rm -rf reference/* ; mv poop/* reference ; rmdir poop ) gtkdocize --copy --docdir doc/reference --flavour no-tmpl || exit 1 diff --git a/configure.in b/configure.in index 39e8c53d..ef611c53 100644 --- a/configure.in +++ b/configure.in @@ -548,7 +548,7 @@ AC_OUTPUT([ man/Makefile doc/Makefile doc/reference/Makefile - doc/reference/VIPS-docs.sgml + doc/reference/libvips-docs.sgml po/Makefile.in ]) diff --git a/doc/reference/Makefile.am b/doc/reference/Makefile.am index 83dc8192..c9b312db 100644 --- a/doc/reference/Makefile.am +++ b/doc/reference/Makefile.am @@ -9,10 +9,12 @@ AUTOMAKE_OPTIONS = 1.6 # of using the various options. # The name of the module, e.g. 'glib'. -DOC_MODULE=VIPS +# (vips: we put the version in the module name rather than defining +# DOC_MODULE_VERSION to avoid some broken links) +DOC_MODULE=libvips # Uncomment for versioned docs and specify the version of the module, e.g. '2'. -DOC_MODULE_VERSION=7 +#DOC_MODULE_VERSION=7 # The top-level SGML file. You can change this if you want to. DOC_MAIN_SGML_FILE=$(DOC_MODULE)-docs.sgml @@ -92,10 +94,10 @@ include $(top_srcdir)/gtk-doc.make # Files not to distribute # for --rebuild-types in $(SCAN_OPTIONS), e.g. $(DOC_MODULE).types # for --rebuild-sections in $(SCAN_OPTIONS) e.g. $(DOC_MODULE)-sections.txt -DISTCLEANFILES = VIPS.types +DISTCLEANFILES = libvips.types # Comment this out if you want your docs-status tested during 'make check' if ENABLE_GTK_DOC -#TESTS_ENVIRONMENT = cd $(srcsrc) -#TESTS = $(GTKDOC_CHECK) +TESTS_ENVIRONMENT = cd $(srcsrc) +TESTS = $(GTKDOC_CHECK) endif diff --git a/doc/reference/VIPS-docs.sgml.in b/doc/reference/libvips-docs.sgml.in similarity index 100% rename from doc/reference/VIPS-docs.sgml.in rename to doc/reference/libvips-docs.sgml.in diff --git a/libvips/arithmetic/arith_dispatch.c b/libvips/arithmetic/arith_dispatch.c index 15b64512..57e42b63 100644 --- a/libvips/arithmetic/arith_dispatch.c +++ b/libvips/arithmetic/arith_dispatch.c @@ -53,7 +53,7 @@ * These operations perform pixel arithmetic, that is, they perform an * arithmetic operation, such as addition, on every pixel in an image or a * pair of images. All (except in a few cases noted below) will work with - * images of any type (or any mixture of types), of any size and of any number + * images of any type or any mixture of types, of any size and of any number * of bands. * * For binary operations, if the number of bands differs, one of the images diff --git a/libvips/arithmetic/im_add.c b/libvips/arithmetic/im_add.c index ef1d6a72..73f42765 100644 --- a/libvips/arithmetic/im_add.c +++ b/libvips/arithmetic/im_add.c @@ -20,6 +20,11 @@ * - ... so 1 band + 4 band image -> 4 band image * 8/12/06 * - add liboil support + * 18/8/08 + * - revise upcasting system + * - im__cast_and_call() no longer sets bbits for you + * - add gtkdoc comments + * - remove separate complex case, just double size */ /* @@ -69,33 +74,7 @@ #include #endif /*WITH_DMALLOC*/ -/* Complex add. - */ -#define cloop(TYPE) { \ - TYPE *p1 = (TYPE *) in[0]; \ - TYPE *p2 = (TYPE *) in[1]; \ - TYPE *q = (TYPE *) out; \ - \ - for( x = 0; x < sz; x++ ) { \ - double rp1 = p1[0]; \ - double ip1 = p1[1]; \ - \ - double rp2 = p2[0]; \ - double ip2 = p2[1]; \ - \ - p1 += 2; \ - p2 += 2; \ - \ - q[0] = rp1 + rp2; \ - q[1] = ip1 + ip2; \ - \ - q += 2; \ - } \ -} - -/* Real add. - */ -#define rloop(IN, OUT) { \ +#define LOOP( IN, OUT ) { \ IN *p1 = (IN *) in[0]; \ IN *p2 = (IN *) in[1]; \ OUT *q = (OUT *) out; \ @@ -107,31 +86,35 @@ static void add_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); - /* Add all input types. Kep types here in sync with bandfmt_add[] below. + int x; + + /* Add all input types. Keep types here in sync with bandfmt_add[] + * below. */ switch( im->BandFmt ) { - case IM_BANDFMT_UCHAR: rloop( unsigned char, unsigned short ); break; - case IM_BANDFMT_CHAR: rloop( signed char, signed short ); break; - case IM_BANDFMT_USHORT: rloop( unsigned short, unsigned int ); break; - case IM_BANDFMT_SHORT: rloop( signed short, signed int ); break; - case IM_BANDFMT_UINT: rloop( unsigned int, unsigned int ); break; - case IM_BANDFMT_INT: rloop( signed int, signed int ); break; + case IM_BANDFMT_UCHAR: LOOP( unsigned char, unsigned short ); break; + case IM_BANDFMT_CHAR: LOOP( signed char, signed short ); break; + case IM_BANDFMT_USHORT: LOOP( unsigned short, unsigned int ); break; + case IM_BANDFMT_SHORT: LOOP( signed short, signed int ); break; + case IM_BANDFMT_UINT: LOOP( unsigned int, unsigned int ); break; + case IM_BANDFMT_INT: LOOP( signed int, signed int ); break; case IM_BANDFMT_FLOAT: #ifdef HAVE_LIBOIL oil_add_f32( (float *) out, (float *) in[0], (float *) in[1], sz ); #else /*!HAVE_LIBOIL*/ - rloop( float, float ); + LOOP( float, float ); #endif /*HAVE_LIBOIL*/ break; - case IM_BANDFMT_DOUBLE: rloop( double, double ); break; - case IM_BANDFMT_COMPLEX:cloop( float ); break; - case IM_BANDFMT_DPCOMPLEX:cloop( double ); 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; default: assert( 0 ); @@ -147,9 +130,9 @@ add_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 /* For two integer types, the "largest", ie. one which can represent the * full range of both. @@ -166,7 +149,7 @@ static int bandfmt_largest[6][6] = { /* For two formats, find one which can represent the full range of both. */ -static VipsBandFmt +VipsBandFmt im__format_common( IMAGE *in1, IMAGE *in2 ) { if( im_iscomplex( in1 ) || im_iscomplex( in2 ) ) { @@ -260,8 +243,8 @@ im__cast_and_call( IMAGE *in1, IMAGE *in2, IMAGE *out, * match the case statement in add_buffer() above. */ static int bandfmt_add[10] = { -/* UC C US S UI I F M D DM */ - US, S, UI, I, UI, I, F, M, D, DM +/* UC C US S UI I F X D DX */ + US, S, UI, I, UI, I, F, X, D, DX }; /** @@ -270,10 +253,13 @@ static int bandfmt_add[10] = { * @in2: input image 2 * @out: output image * - * This operation adds corresponding pixels in images @in1 and - * @in2 and writes the result to the image descriptor @out. The images must be - * the same size, but may have any type. If one of the images has a single - * band, it is added to every band of the other 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 diff --git a/libvips/arithmetic/im_subtract.c b/libvips/arithmetic/im_subtract.c index 6491b6ed..24865141 100644 --- a/libvips/arithmetic/im_subtract.c +++ b/libvips/arithmetic/im_subtract.c @@ -32,6 +32,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 */ /* @@ -81,70 +85,46 @@ #include #endif /*WITH_DMALLOC*/ -/* Complex subtract. - */ -#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 rp1 = p1[0];\ - double ip1 = p1[1];\ - \ - double rp2 = p2[0];\ - double ip2 = p2[1];\ - \ - p1 += 2;\ - p2 += 2;\ - \ - q[0] = rp1 - rp2;\ - q[1] = ip1 - ip2;\ - \ - q += 2;\ - }\ -} - -/* Real subtract. - */ -#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 subtract_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); - /* Subtract all input types. + int x; + + /* Add all input types. Keep types here in sync with bandfmt_subtract[] + * 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, signed short ); break; + case IM_BANDFMT_SHORT: LOOP( signed short, signed int ); break; + 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: #ifdef HAVE_LIBOIL oil_subtract_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: LOOP( double, double ); break; + case IM_BANDFMT_COMPLEX:LOOP( float, float ); break; + case IM_BANDFMT_DPCOMPLEX:LOOP( double, double ); break; default: assert( 0 ); @@ -153,40 +133,115 @@ subtract_buffer( PEL **in, PEL *out, int width, IMAGE *im ) /* Save a bit of typing. */ +#define UC IM_BANDFMT_UCHAR +#define C IM_BANDFMT_CHAR +#define US IM_BANDFMT_USHORT #define S IM_BANDFMT_SHORT +#define UI IM_BANDFMT_UINT #define I IM_BANDFMT_INT +#define F IM_BANDFMT_FLOAT +#define X IM_BANDFMT_COMPLEX #define D IM_BANDFMT_DOUBLE +#define DX IM_BANDFMT_DPCOMPLEX -/* Type conversions for two integer inputs. Rules for float and complex - * input encoded with ifs. We are sign and value preserving. +/* Type promotion for subtraction. Sign and value preserving. Make sure these + * match the case statement in subtract_buffer() above. */ -static int iformat[6][6] = { - /* UC C US S UI I */ -/* UC */ { S, S, I, I, I, I }, -/* C */ { S, S, I, I, I, I }, -/* US */ { I, I, I, I, I, I }, -/* S */ { I, I, I, I, I, I }, -/* UI */ { I, I, I, I, I, I }, -/* I */ { I, I, I, I, I, I } +static int bandfmt_subtract[10] = { +/* UC C US S UI I F X D DX */ + S, S, I, I, I, I, F, X, D, DX }; +/** + * im_subtract: + * @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 + * arithmetic), then the + * following table is used to determine the output type: + * + * + * im_subtract() type promotion + * + * + * + * input type + * output type + * + * + * + * + * uchar + * short + * + * + * char + * short + * + * + * ushort + * int + * + * + * short + * int + * + * + * uint + * int + * + * + * int + * int + * + * + * float + * float + * + * + * double + * double + * + * + * complex + * complex + * + * + * double complex + * double complex + * + * + * + *
+ * + * In other words, the output type is just large enough to hold the whole + * range of possible values. + * + * See also: im_add(), im_lintra(). + * + * Returns: 0 on success, -1 on error + */ int im_subtract( 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_subtract", in1, in2 ) || + im_check_uncoded( "im_subtract", in1 ) || + im_check_uncoded( "im_subtract", in2 ) ) return( -1 ); - if( in1->Bands != in2->Bands && - (in1->Bands != 1 && in2->Bands != 1) ) { - im_error( "im_subtract", - "%s", _( "not same number of bands" ) ); - return( -1 ); - } - if( in1->Coding != IM_CODING_NONE || in2->Coding != IM_CODING_NONE ) { - im_error( "im_subtract", "%s", _( "not uncoded" ) ); - return( -1 ); - } + if( im_cp_descv( out, in1, in2, NULL ) ) return( -1 ); @@ -196,30 +251,8 @@ im_subtract( IMAGE *in1, IMAGE *in2, IMAGE *out ) /* What output type will we write? int, float or complex. */ - if( im_iscomplex( in1 ) || im_iscomplex( in2 ) ) { - /* What kind of complex? - */ - if( in1->BandFmt == IM_BANDFMT_DPCOMPLEX || - in2->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 ) ) { - /* What kind of float? - */ - if( in1->BandFmt == IM_BANDFMT_DOUBLE || - in2->BandFmt == IM_BANDFMT_DOUBLE ) - out->BandFmt = IM_BANDFMT_DOUBLE; - else - out->BandFmt = IM_BANDFMT_FLOAT; - } - else - /* Must be int+int -> int. - */ - out->BandFmt = iformat[in1->BandFmt][in2->BandFmt]; + out->BandFmt = bandfmt_subtract[im__format_common( in1, in2 )]; + out->Bbits = im_bits_of_fmt( out->BandFmt ); /* And process! */ diff --git a/libvips/format/im_vips2jpeg.c b/libvips/format/im_vips2jpeg.c index 58c73952..6e07eeac 100644 --- a/libvips/format/im_vips2jpeg.c +++ b/libvips/format/im_vips2jpeg.c @@ -27,6 +27,8 @@ * - write CMYK if Bands == 4 and Type == CMYK * 12/5/09 * - fix signed/unsigned warning + * 13/8/09 + * - allow "none" for profile, meaning don't embed one */ /* @@ -612,8 +614,10 @@ write_vips( Write *write, int qfac, const char *profile ) return( -1 ); /* A profile supplied as an argument overrides an embedded profile. + * "none" means don't attach a profile. */ if( profile && + strcmp( profile, "none" ) != 0 && write_profile_file( write, profile ) ) return( -1 ); if( !profile && diff --git a/libvips/include/vips/internal.h b/libvips/include/vips/internal.h index 627d9f10..3c65698f 100644 --- a/libvips/include/vips/internal.h +++ b/libvips/include/vips/internal.h @@ -131,7 +131,10 @@ char *im__gslist_gvalue_get( const GSList *list ); void im__buffer_init( void ); -int im__cast_and_call(); +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__test_kill( IMAGE *im ); void *im__mmap( int fd, int writeable, size_t length, gint64 offset ); int im__munmap( void *start, size_t length );