From c6418893eb2526f7a432cc43e21be1e88ab7b852 Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Thu, 17 Sep 2009 08:51:37 +0000 Subject: [PATCH] stuff --- ChangeLog | 2 + TODO | 44 +++++ libvips/arithmetic/arith_dispatch.c | 4 +- libvips/arithmetic/im_add.c | 72 ++++---- libvips/arithmetic/im_divide.c | 32 +--- libvips/arithmetic/im_multiply.c | 32 +--- libvips/arithmetic/im_remainder.c | 92 +++++++--- libvips/arithmetic/im_subtract.c | 32 +--- libvips/boolean/boolean.c | 254 +++++++--------------------- libvips/format/im_png2vips.c | 4 +- libvips/include/vips/internal.h | 5 +- 11 files changed, 232 insertions(+), 341 deletions(-) diff --git a/ChangeLog b/ChangeLog index ae2df416..ac131143 100644 --- a/ChangeLog +++ b/ChangeLog @@ -35,6 +35,8 @@ - im_max()/im_min() are now convenience functions - im_maxpos_avg() handles complex and multi-band images - added im_point(), rewrite im_point_bilinear() in terms of this +- close callbacks now happen *after* images have closed resources (such as + open files) ... this lets them delete temps and stuff. Expect breakage :( - added vips_interpolate_get_window_offset() 25/3/09 started 7.18.0 diff --git a/TODO b/TODO index 89ff0e04..ed9aa650 100644 --- a/TODO +++ b/TODO @@ -1,4 +1,48 @@ +- look at im_remainderconst_vec() + put that functionality into something like im__cast_and_call(), then share + with im_andimage_const_vec() + + working in im__arith_binary_const() + + +- experimenting with + + png_set_shift( read->pPng, 2 ); + + in im_png2vips.c + + test image in gmail + + +- Joe's new def + + +- we have im_andimage(), but im_and_vec(), argh + + shouldn't it be im_andimageconst_vec()? won't we have C++ problems the way + things are? + + + +Something like: + +const char *im_system_image( IMAGE *in, const char *command, char **log ); + +Actions: + +- create two empty temporary files +- write the image to the first +- call system() on the expanded command +- capture stdout/stderr into log +- delete the temp input file +- return the output filename, or NULL if the command failed (log is still + returned in this case) + + The caller would open the output file, either with im_open(), or with it's + own system (nip2 has it's own open file thing to give progress feedback and + use disc for format conversion), and be responsible for deleting the temp + output file at some point. - 1-bit PNG read is broken? diff --git a/libvips/arithmetic/arith_dispatch.c b/libvips/arithmetic/arith_dispatch.c index b60395e4..d181e58d 100644 --- a/libvips/arithmetic/arith_dispatch.c +++ b/libvips/arithmetic/arith_dispatch.c @@ -44,9 +44,7 @@ /** * SECTION: arithmetic - * @short_description: operations which perform pixel arithmetic, trig, log, - * statistics - * + * @short_description: operations which perform pixel arithmetic, trig, log, statistics * @see_also: iofuncs * @stability: Stable * @include: vips/vips.h diff --git a/libvips/arithmetic/im_add.c b/libvips/arithmetic/im_add.c index 43257811..e6e8f25a 100644 --- a/libvips/arithmetic/im_add.c +++ b/libvips/arithmetic/im_add.c @@ -25,6 +25,9 @@ * - im__cast_and_call() no longer sets bbits for you * - add gtkdoc comments * - remove separate complex case, just double size + * 11/9/09 + * - im__cast_and_call() becomes im__arith_binary() + * - more of operation scaffold moved inside */ /* @@ -151,7 +154,7 @@ static int bandfmt_largest[6][6] = { /* For two formats, find one which can represent the full range of both. */ -VipsBandFmt +static VipsBandFmt im__format_common( IMAGE *in1, IMAGE *in2 ) { if( im_iscomplex( in1 ) || im_iscomplex( in2 ) ) { @@ -206,16 +209,43 @@ im__bandup( IMAGE *in, IMAGE *out, int n ) return( im_gbandjoin( bands, out, n ) ); } -/* Cast in1 and in2 up to a common type and number of bands, then call the - * function. Also used by subtract, multiply, divide, etc. +/* The common part of most binary arithmetic, relational and boolean + * operators. We: + * + * - check in and out + * - cast in1 and in2 up to a common format + * - cast the common format to the output format with the supplied table + * - equalise bands + * - run the supplied buffer operation */ int -im__cast_and_call( IMAGE *in1, IMAGE *in2, IMAGE *out, +im__arith_binary( const char *name, + IMAGE *in1, IMAGE *in2, IMAGE *out, + int format_table[10], im_wrapmany_fn fn, void *a ) { VipsBandFmt fmt; IMAGE *t[5]; + if( im_piocheck( in1, out ) || + im_pincheck( in2 ) || + im_check_bands_1orn( name, in1, in2 ) || + im_check_uncoded( name, in1 ) || + im_check_uncoded( name, in2 ) ) + return( -1 ); + + if( im_cp_descv( out, in1, in2, NULL ) ) + return( -1 ); + + /* What number of bands will we write? + */ + out->Bands = IM_MAX( in1->Bands, in2->Bands ); + + /* What output type will we write? int, float or complex. + */ + out->BandFmt = format_table[im__format_common( in1, in2 )]; + out->Bbits = im_bits_of_fmt( out->BandFmt ); + if( im_open_local_array( out, t, 4, "type cast:1", "p" ) ) return( -1 ); @@ -331,33 +361,9 @@ static int bandfmt_add[10] = { */ int im_add( IMAGE *in1, IMAGE *in2, IMAGE *out ) -{ - if( im_piocheck( in1, out ) || - im_pincheck( in2 ) || - im_check_bands_1orn( "im_add", in1, in2 ) || - im_check_uncoded( "im_add", in1 ) || - im_check_uncoded( "im_add", in2 ) ) - return( -1 ); - - if( im_cp_descv( out, in1, in2, NULL ) ) - return( -1 ); - - /* What number of bands will we write? - */ - out->Bands = IM_MAX( in1->Bands, in2->Bands ); - - /* What output type will we write? int, float or complex. - */ - out->BandFmt = bandfmt_add[im__format_common( in1, in2 )]; - out->Bbits = im_bits_of_fmt( out->BandFmt ); - - /* And process! - */ - if( im__cast_and_call( in1, in2, out, - (im_wrapmany_fn) add_buffer, NULL ) ) - return( -1 ); - - /* Success! - */ - return( 0 ); +{ + return( im__arith_binary( "im_add", + in1, in2, out, + bandfmt_add, + (im_wrapmany_fn) add_buffer, NULL ) ); } diff --git a/libvips/arithmetic/im_divide.c b/libvips/arithmetic/im_divide.c index bdd9e189..7d20db20 100644 --- a/libvips/arithmetic/im_divide.c +++ b/libvips/arithmetic/im_divide.c @@ -271,32 +271,8 @@ static int bandfmt_divide[10] = { int im_divide( IMAGE *in1, IMAGE *in2, IMAGE *out ) { - if( im_piocheck( in1, out ) || - im_pincheck( in2 ) || - im_check_bands_1orn( "im_divide", in1, in2 ) || - im_check_uncoded( "im_divide", in1 ) || - im_check_uncoded( "im_divide", in2 ) ) - return( -1 ); - - if( im_cp_descv( out, in1, in2, NULL ) ) - return( -1 ); - - /* What number of bands will we write? - */ - out->Bands = IM_MAX( in1->Bands, in2->Bands ); - - /* What output type will we write? int, float or complex. - */ - out->BandFmt = bandfmt_divide[im__format_common( in1, in2 )]; - out->Bbits = im_bits_of_fmt( out->BandFmt ); - - /* And process! - */ - if( im__cast_and_call( in1, in2, out, - (im_wrapmany_fn) divide_buffer, NULL ) ) - return( -1 ); - - /* Success! - */ - return( 0 ); + return( im__arith_binary( "im_divide", + in1, in2, out, + bandfmt_divide, + (im_wrapmany_fn) divide_buffer, NULL ) ); } diff --git a/libvips/arithmetic/im_multiply.c b/libvips/arithmetic/im_multiply.c index 23f55200..4cc1fd5b 100644 --- a/libvips/arithmetic/im_multiply.c +++ b/libvips/arithmetic/im_multiply.c @@ -246,32 +246,8 @@ static int bandfmt_multiply[10] = { int im_multiply( IMAGE *in1, IMAGE *in2, IMAGE *out ) { - 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( im_cp_descv( out, in1, in2, NULL ) ) - return( -1 ); - - /* What number of bands will we write? - */ - out->Bands = IM_MAX( in1->Bands, in2->Bands ); - - /* What output type will we write? int, float or complex. - */ - out->BandFmt = bandfmt_multiply[im__format_common( in1, in2 )]; - out->Bbits = im_bits_of_fmt( out->BandFmt ); - - /* And process! - */ - if( im__cast_and_call( in1, in2, out, - (im_wrapmany_fn) multiply_buffer, NULL ) ) - return( -1 ); - - /* Success! - */ - return( 0 ); + return( im__arith_binary( "im_multiply", + in1, in2, out, + bandfmt_multiply, + (im_wrapmany_fn) multiply_buffer, NULL ) ); } diff --git a/libvips/arithmetic/im_remainder.c b/libvips/arithmetic/im_remainder.c index a90e5c69..6ed5f084 100644 --- a/libvips/arithmetic/im_remainder.c +++ b/libvips/arithmetic/im_remainder.c @@ -160,39 +160,85 @@ static int bandfmt_remainder[10] = { */ int im_remainder( IMAGE *in1, IMAGE *in2, IMAGE *out ) -{ - if( im_piocheck( in1, 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_noncomplex( "im_remainder", in1 ) || - im_check_noncomplex( "im_remainder", in2 ) ) +{ + return( im__arith_binary( "im_remainder", + in1, in2, out, + bandfmt_remainder, + (im_wrapmany_fn) remainder_buffer, NULL ) ); +} + +/* Cast a vector of double to a vector of TYPE. + */ +#define CAST( TYPE ) { \ + TYPE *tq = (TYPE *) q; \ + \ + for( i = 0; i < n; i++ ) \ + tq[i] = (TYPE) p[i]; \ +} + +/* Make a pixel of output type from a realvec. + */ +static PEL * +make_pixel( IMAGE *out, int n, double *p ) +{ + PEL *q; + int i; + + g_assert( n == out->Bands ); + + if( !(q = IM_ARRAY( out, IM_IMAGE_SIZEOF_PEL( out ), PEL )) ) + return( NULL ); + + switch( out->BandFmt ) { + case IM_BANDFMT_CHAR: CAST( signed char ); break; + case IM_BANDFMT_UCHAR: CAST( unsigned char ); break; + case IM_BANDFMT_SHORT: CAST( signed short ); break; + case IM_BANDFMT_USHORT: CAST( unsigned short ); break; + case IM_BANDFMT_INT: CAST( signed int ); break; + case IM_BANDFMT_UINT: CAST( unsigned int ); break; + + default: + g_assert( 0 ); + } + + return( q ); +} + +int +im__arith_binary_const( const char *name, + IMAGE *in, IMAGE *out, int n, double *c, + int format_table[10], + im_wrapone_fn fn, void *a ) +{ + int i; + PEL *vector; + + if( im_piocheck( in, out ) || + im_check_vector( name, n, in ) || + im_check_uncoded( name, in ) ) return( -1 ); - - if( im_cp_descv( out, in1, in2, NULL ) ) + if( im_cp_desc( out, in ) ) return( -1 ); - - /* What number of bands will we write? - */ - out->Bands = IM_MAX( in1->Bands, in2->Bands ); - - /* What output type will we write? Same as LHS type. - */ - out->BandFmt = bandfmt_remainder[im__format_common( in1, in2 )]; + out->BandFmt = format_table[in->BandFmt]; out->Bbits = im_bits_of_fmt( out->BandFmt ); - /* And process! + /* Cast vector to output type. */ - if( im__cast_and_call( in1, in2, out, - (im_wrapmany_fn) remainder_buffer, NULL ) ) + + /* + need to handle case where vector == 1 but bands == (eg.) 3 + */ + + if( !(vector = make_pixel( out, n, c )) ) + return( -1 ); + + if( im_wrapone( in, out, fn, a, vector ) ) return( -1 ); - /* Success! - */ return( 0 ); } + /* Parameters saved here. */ typedef struct _Remainderconst { diff --git a/libvips/arithmetic/im_subtract.c b/libvips/arithmetic/im_subtract.c index 983c34e8..675beb21 100644 --- a/libvips/arithmetic/im_subtract.c +++ b/libvips/arithmetic/im_subtract.c @@ -238,32 +238,8 @@ static int bandfmt_subtract[10] = { int im_subtract( IMAGE *in1, IMAGE *in2, IMAGE *out ) { - 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( im_cp_descv( out, in1, in2, NULL ) ) - return( -1 ); - - /* What number of bands will we write? - */ - out->Bands = IM_MAX( in1->Bands, in2->Bands ); - - /* What output type will we write? int, float or complex. - */ - out->BandFmt = bandfmt_subtract[im__format_common( in1, in2 )]; - out->Bbits = im_bits_of_fmt( out->BandFmt ); - - /* And process! - */ - if( im__cast_and_call( in1, in2, out, - (im_wrapmany_fn) subtract_buffer, NULL ) ) - return( -1 ); - - /* Success! - */ - return( 0 ); + return( im__arith_binary( "im_subtract", + in1, in2, out, + bandfmt_subtract, + (im_wrapmany_fn) subtract_buffer, NULL ) ); } diff --git a/libvips/boolean/boolean.c b/libvips/boolean/boolean.c index 9befe7dc..089f02e5 100644 --- a/libvips/boolean/boolean.c +++ b/libvips/boolean/boolean.c @@ -40,6 +40,9 @@ * layer if operator names are turned on * 30/6/04 * - now cast float/complex args to int + * 11/9/09 + * - use new im__cast_and__call() + * - therefore now supports 1-band $op n-band */ /* @@ -75,7 +78,6 @@ #include #include -#include #include @@ -83,102 +85,13 @@ #include #endif /*WITH_DMALLOC*/ -/* 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 M IM_BANDFMT_COMPLEX -#define D IM_BANDFMT_DOUBLE -#define DM IM_BANDFMT_DPCOMPLEX - -/* Type conversions for boolean. - */ -static int iformat[10][10] = { - /* UC C US S UI I F M D DM */ -/* UC */ { UC, C, US, S, UI, I, I, I, I, I }, -/* C */ { C, C, S, S, I, I, I, I, I, I }, -/* US */ { US, S, US, S, UI, I, I, I, I, I }, -/* S */ { S, S, S, S, I, I, I, I, I, I }, -/* UI */ { UI, I, UI, I, UI, I, I, I, I, I }, -/* I */ { I, I, I, I, I, I, I, I, I, I }, -/* F */ { I, I, I, I, I, I, I, I, I, I }, -/* M */ { I, I, I, I, I, I, I, I, I, I }, -/* D */ { I, I, I, I, I, I, I, I, I, I }, -/* DM */ { I, I, I, I, I, I, I, I, I, I } -}; - -/* Check args. Cast inputs to matching integer format. - */ -static int -check( IMAGE **in, IMAGE *out ) -{ - int i, n; - int fmt; - - /* Count args. - */ - for( n = 0; in[n]; n++ ) { - if( in[n]->Coding != IM_CODING_NONE ) { - im_error( "boolean", - "%s", _( "uncoded images only" ) ); - return( -1 ); - } - } - - /* Check sizes match. - */ - for( i = 1; i < n; i++ ) - if( in[0]->Bands != in[i]->Bands || - in[0]->Xsize != in[i]->Xsize || - in[0]->Ysize != in[i]->Ysize ) { - im_error( "boolean", - "%s", _( "images differ in size" ) ); - return( -1 ); - } - - /* Calculate type conversion ... just 1ary and 2ary. - */ - switch( n ) { - case 1: - fmt = iformat[0][in[0]->BandFmt]; - break; - - case 2: - fmt = iformat[in[1]->BandFmt][in[0]->BandFmt]; - break; - - default: - assert( FALSE ); - } - - for( i = 0; i < n; i++ ) { - IMAGE *t = im_open_local( out, "check-1", "p" ); - - if( !t || im_clip2fmt( in[i], t, fmt ) ) - return( -1 ); - in[i] = t; - } - - /* Prepare the output image. - */ - if( im_cp_desc_array( out, in ) ) - return( -1 ); - - return( 0 ); -} - -/* A selection of main loops. As with im_add(), only implement monotype - * operations. TYPE is some integer type, signed or unsigned. +/* A selection of main loops. Only implement monotype operations, ie. input + * type == output type. Float types are cast to int before we come here. */ #define AND2( TYPE ) { \ TYPE *tq = (TYPE *) q; \ - TYPE *tp1 = (TYPE *) p1; \ - TYPE *tp2 = (TYPE *) p2; \ + TYPE *tp1 = (TYPE *) p[0]; \ + TYPE *tp2 = (TYPE *) p[1]; \ \ for( x = 0; x < ne; x++ ) \ tq[x] = tp1[x] & tp2[x]; \ @@ -186,8 +99,8 @@ check( IMAGE **in, IMAGE *out ) #define OR2( TYPE ) { \ TYPE *tq = (TYPE *) q; \ - TYPE *tp1 = (TYPE *) p1; \ - TYPE *tp2 = (TYPE *) p2; \ + TYPE *tp1 = (TYPE *) p[0]; \ + TYPE *tp2 = (TYPE *) p[1]; \ \ for( x = 0; x < ne; x++ ) \ tq[x] = tp1[x] | tp2[x]; \ @@ -195,8 +108,8 @@ check( IMAGE **in, IMAGE *out ) #define EOR2( TYPE ) { \ TYPE *tq = (TYPE *) q; \ - TYPE *tp1 = (TYPE *) p1; \ - TYPE *tp2 = (TYPE *) p2; \ + TYPE *tp1 = (TYPE *) p[0]; \ + TYPE *tp2 = (TYPE *) p[1]; \ \ for( x = 0; x < ne; x++ ) \ tq[x] = tp1[x] ^ tp2[x]; \ @@ -237,11 +150,9 @@ check( IMAGE **in, IMAGE *out ) static void and_buffer( PEL **p, PEL *q, int n, IMAGE *im ) { + const int ne = n * im->Bands; + int x; - int bands = im->Bands; - int ne = n * bands; - PEL *p1 = p[0]; - PEL *p2 = p[1]; switch( im->BandFmt ) { case IM_BANDFMT_CHAR: AND2( signed char ); break; @@ -252,20 +163,18 @@ and_buffer( PEL **p, PEL *q, int n, IMAGE *im ) case IM_BANDFMT_UINT: AND2( unsigned int ); break; default: - error_exit( "im_and: internal error" ); + g_assert( 0 ); } } static void -or_buffer( PEL **p, PEL *q, int n, IMAGE *in1 ) +or_buffer( PEL **p, PEL *q, int n, IMAGE *im ) { - int x; - int bands = in1->Bands; - int ne = n * bands; - PEL *p1 = p[0]; - PEL *p2 = p[1]; + const int ne = n * im->Bands; - switch( in1->BandFmt ) { + int x; + + switch( im->BandFmt ) { case IM_BANDFMT_CHAR: OR2( signed char ); break; case IM_BANDFMT_UCHAR: OR2( unsigned char ); break; case IM_BANDFMT_SHORT: OR2( signed short ); break; @@ -274,20 +183,18 @@ or_buffer( PEL **p, PEL *q, int n, IMAGE *in1 ) case IM_BANDFMT_UINT: OR2( unsigned int ); break; default: - error_exit( "im_or: internal error" ); + g_assert( 0 ); } } static void eor_buffer( PEL **p, PEL *q, int n, IMAGE *in1 ) { - int x; - int bands = in1->Bands; - int ne = n * bands; - PEL *p1 = p[0]; - PEL *p2 = p[1]; + const int ne = n * im->Bands; - switch( in1->BandFmt ) { + int x; + + switch( im->BandFmt ) { case IM_BANDFMT_CHAR: EOR2( signed char ); break; case IM_BANDFMT_UCHAR: EOR2( unsigned char ); break; case IM_BANDFMT_SHORT: EOR2( signed short ); break; @@ -296,7 +203,7 @@ eor_buffer( PEL **p, PEL *q, int n, IMAGE *in1 ) case IM_BANDFMT_UINT: EOR2( unsigned int ); break; default: - error_exit( "im_eor: internal error" ); + g_assert( 0 ); } } @@ -315,7 +222,7 @@ andconst_buffer( PEL *p, PEL *q, int n, IMAGE *in, PEL *c ) case IM_BANDFMT_UINT: ANDCONST( unsigned int ); break; default: - error_exit( "im_andconst: internal error" ); + g_assert( 0 ); } } @@ -334,7 +241,7 @@ orconst_buffer( PEL *p, PEL *q, int n, IMAGE *in, PEL *c ) case IM_BANDFMT_UINT: ORCONST( unsigned int ); break; default: - error_exit( "im_orconst: internal error" ); + g_assert( 0 ); } } @@ -353,94 +260,53 @@ eorconst_buffer( PEL *p, PEL *q, int n, IMAGE *in, PEL *c ) case IM_BANDFMT_UINT: EORCONST( unsigned int ); break; default: - error_exit( "im_eorconst: internal error" ); + g_assert( 0 ); } } +/* 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 + +/* Type conversions for boolean. + */ +static int bandfmt_bool[10] = { +/* UC C US S UI I F X D DX */ + UC, C, US, S, UI, I, I, I, I, I }, +}; + /* The above, wrapped up as im_*() functions. */ int im_andimage( IMAGE *in1, IMAGE *in2, IMAGE *out ) { - IMAGE *invec[3]; - - /* Check images. - */ - invec[0] = in1; invec[1] = in2; invec[2] = NULL; - if( check( invec, out ) ) - return( -1 ); - - /* Process! - */ - if( im_wrapmany( invec, out, (im_wrapmany_fn) and_buffer, out, NULL ) ) - return( -1 ); - - return( 0 ); + return( im__arith_binary( "im_andimage", + in1, in2, out, + bandfmt_bool, + (im_wrapmany_fn) and_buffer, NULL ) ); } int im_orimage( IMAGE *in1, IMAGE *in2, IMAGE *out ) -{ - IMAGE *invec[3]; - - invec[0] = in1; invec[1] = in2; invec[2] = NULL; - if( check( invec, out ) ) - return( -1 ); - - if( im_wrapmany( invec, out, (im_wrapmany_fn) or_buffer, out, NULL ) ) - return( -1 ); - - return( 0 ); +{ + return( im__arith_binary( "im_orimage", + in1, in2, out, + bandfmt_bool, + (im_wrapmany_fn) or_buffer, NULL ) ); } int im_eorimage( IMAGE *in1, IMAGE *in2, IMAGE *out ) -{ - IMAGE *invec[3]; - - invec[0] = in1; invec[1] = in2; invec[2] = NULL; - if( check( invec, out ) ) - return( -1 ); - - if( im_wrapmany( invec, out, (im_wrapmany_fn) eor_buffer, out, NULL ) ) - return( -1 ); - - return( 0 ); -} - -/* Cast a vector of double to a vector of TYPE. - */ -#define CAST( TYPE ) { \ - TYPE *tq = (TYPE *) q; \ - \ - for( i = 0; i < out->Bands; i++ ) \ - tq[i] = (TYPE) p[i]; \ -} - -/* Make a pixel of output type from a realvec. - */ -static PEL * -make_pixel( IMAGE *out, int fmt, double *p ) { - PEL *q; - int i; - - if( !(q = IM_ARRAY( out, IM_IMAGE_SIZEOF_PEL( out ), PEL )) ) - return( NULL ); - - switch( fmt ) { - case IM_BANDFMT_CHAR: CAST( signed char ); break; - case IM_BANDFMT_UCHAR: CAST( unsigned char ); break; - case IM_BANDFMT_SHORT: CAST( signed short ); break; - case IM_BANDFMT_USHORT: CAST( unsigned short ); break; - case IM_BANDFMT_INT: CAST( signed int ); break; - case IM_BANDFMT_UINT: CAST( unsigned int ); break; - - default: - error_exit( "make_pixel: internal error" ); - } - - return( q ); + return( im__arith_binary( "im_eorimage", + in1, in2, out, + bandfmt_bool, + (im_wrapmany_fn) eor_buffer, NULL ) ); } int @@ -594,8 +460,7 @@ shiftleft_buffer( PEL *p, PEL *q, int len, IMAGE *in, int n ) case IM_BANDFMT_INT: SHIFTL( signed int ); break; default: - error_exit( "im_shiftleft: internal error" ); - /*NOTREACHED*/ + g_assert( 0 ); } } @@ -641,8 +506,7 @@ shiftright_buffer( PEL *p, PEL *q, int len, IMAGE *in, int n ) case IM_BANDFMT_INT: SHIFTR( signed int ); break; default: - error_exit( "im_shiftright: internal error" ); - /*NOTREACHED*/ + g_assert( 0 ); } } diff --git a/libvips/format/im_png2vips.c b/libvips/format/im_png2vips.c index 3194f188..64f12c5d 100644 --- a/libvips/format/im_png2vips.c +++ b/libvips/format/im_png2vips.c @@ -283,8 +283,10 @@ png2vips( Read *read, int header_only ) /* Expand <8 bit images to full bytes. */ - if( read->pInfo->bit_depth < 8 ) + if( read->pInfo->bit_depth < 8 ) { png_set_packing( read->pPng ); + png_set_shift( read->pPng, 2 ); + } /* If we're an INTEL byte order machine and this is 16bits, we need * to swap bytes. diff --git a/libvips/include/vips/internal.h b/libvips/include/vips/internal.h index 4864b239..50b01a27 100644 --- a/libvips/include/vips/internal.h +++ b/libvips/include/vips/internal.h @@ -131,9 +131,10 @@ char *im__gslist_gvalue_get( const GSList *list ); void im__buffer_init( void ); -int im__cast_and_call( IMAGE *in1, IMAGE *in2, IMAGE *out, +int im__arith_binary( const char *name, + IMAGE *in1, IMAGE *in2, IMAGE *out, + int format_table[10], 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 ); typedef int (*im__wrapscan_fn)( void *p, int n, void *seq, void *a, void *b );