diff --git a/libvips/conversion/im_msb.c b/libvips/conversion/im_msb.c index 1258f49c..017d6f4e 100644 --- a/libvips/conversion/im_msb.c +++ b/libvips/conversion/im_msb.c @@ -1,21 +1,4 @@ -/* @(#) Convert a signed or unsigned, char or short or int image into unsigned - * @(#) char very quickly, by discarding the lower order bits. Signed values - * @(#) are converted to unsigned by adding 128. - * @(#) - * @(#) int - * @(#) im_msb( - * @(#) IMAGE *in, - * @(#) IMAGE *out - * @(#) ); - * @(#) - * @(#) As above, but also discard all but the specified band: - * @(#) - * @(#) int - * @(#) im_msb( - * @(#) IMAGE *in, - * @(#) IMAGE *out, - * @(#) int band - * @(#) ); +/* im_msb * * Copyright: 2006, The Nottingham Trent University * @@ -27,6 +10,9 @@ * 4/10/06 * - removed warning on uchar fallback: it happens a lot with nip2 and * isn't very serious + * 1/2/10 + * - revised, cleanups + * - gtkdoc */ /* @@ -62,283 +48,181 @@ #endif /*HAVE_CONFIG_H */ #include -#include - #include #ifdef WITH_DMALLOC #include #endif /*WITH_DMALLOC */ -/** MACROS **/ -/* BAND FORMAT TESTS */ +typedef struct _Msb { + size_t index; + size_t width; + size_t repeat; +} Msb; -#define SIZEOF_BAND(band_fmt) ( \ - ( IM_BANDFMT_UCHAR == (band_fmt) ) ? sizeof(unsigned char) \ - : ( IM_BANDFMT_CHAR == (band_fmt) ) ? sizeof(signed char) \ - : ( IM_BANDFMT_USHORT == (band_fmt) ) ? sizeof(unsigned short int) \ - : ( IM_BANDFMT_SHORT == (band_fmt) ) ? sizeof(signed short int) \ - : ( IM_BANDFMT_UINT == (band_fmt) ) ? sizeof(unsigned int) \ - : ( IM_BANDFMT_INT == (band_fmt) ) ? sizeof(signed int) \ - : ( IM_BANDFMT_FLOAT == (band_fmt) ) ? sizeof(float) \ - : ( IM_BANDFMT_DOUBLE == (band_fmt) ) ? sizeof(double) \ - : ( IM_BANDFMT_COMPLEX == (band_fmt) ) ? ( 2 * sizeof(float) ) \ - : ( 2 * sizeof(double) ) ) +static void +byte_select( unsigned char *in, unsigned char *out, int n, Msb *msb ) +{ + unsigned char *stop = out + n * msb->repeat; -#define BANDFMT_SHORT_CHAR(band_fmt) ( \ - IM_BANDFMT_SHORT == (band_fmt) \ - || IM_BANDFMT_USHORT == (band_fmt) \ - || IM_BANDFMT_CHAR == (band_fmt) \ - || IM_BANDFMT_UCHAR == (band_fmt) ) + for( in += msb->index; out < stop; in += msb->width, ++out ) + *out = *in; +} -#define BANDFMT_ANY_INT(band_fmt) ( \ - IM_BANDFMT_INT == (band_fmt) \ - || IM_BANDFMT_UINT == (band_fmt) \ - || BANDFMT_SHORT_CHAR(band_fmt) ) +static void +byte_select_flip( unsigned char *in, unsigned char *out, int n, Msb *msb ) +{ + unsigned char *stop = out + n * msb->repeat; -#define BANDFMT_UNSIGNED(band_fmt) ( \ - IM_BANDFMT_UINT == (band_fmt) \ - || IM_BANDFMT_USHORT == (band_fmt) \ - || IM_BANDFMT_UCHAR == (band_fmt) ) + for( in += msb->index; out < stop; in += msb->width, ++out ) + *out = 0x80 ^ *in; +} -/* IMAGE TESTS */ +static void +msb_labq( unsigned char *in, unsigned char *out, int n ) +{ + unsigned char *stop = in + (n << 2); -#define IM_ANY_INT(im) BANDFMT_ANY_INT((im)-> BandFmt) -#define IM_UNSIGNED(im) BANDFMT_UNSIGNED((im)-> BandFmt) -#define IM_UNCODED(im) ( IM_CODING_NONE == (im)-> Coding ) - -/** LOCAL FUNCTIONS DECLARATIONS **/ -static void byte_select (unsigned char *in, unsigned char *out, int n, - size_t * params); -static void byte_select_flip (unsigned char *in, unsigned char *out, int n, - size_t * params); -static void msb_labq (unsigned char *in, unsigned char *out, int n); - -/** EXPORTED FUNCTIONS **/ + for( ; in < stop; in += 4, out += 3 ) { + out[0] = in[0]; + out[1] = 0x80 ^ in[1]; + out[2] = 0x80 ^ in[2]; + } +} +/** + * im_msb: + * @in: input image + * @out: output image + * + * Turn any integer image to 8-bit unsigned char by discarding all but the most + * significant byte. + * Signed values are converted to unsigned by adding 128. + * + * This operator also works for LABQ coding. + * + * See also: im_msb_band(). + * + * Returns: 0 on success, -1 on error + */ int -im_msb (IMAGE * in, IMAGE * out) +im_msb( IMAGE *in, IMAGE *out ) { -#define FUNCTION_NAME "im_msb" + Msb *msb; + im_wrapone_fn func; - size_t *params; - im_wrapone_fn func; + if( in->Coding == IM_CODING_NONE && + in->BandFmt == IM_BANDFMT_UCHAR ) + return( im_copy( in, out ) ); -#define index (params[0]) -#define width (params[1]) -#define repeat (params[2]) + if( im_piocheck( in, out ) || + !(msb = IM_NEW( out, Msb )) ) + return( -1 ); - if (im_piocheck (in, out)) - return -1; + if( in->Coding == IM_CODING_NONE ) { + if( im_check_int( "im_msb", in ) ) + return( -1 ); - /* Stops a used-before-set warning. - */ - params = NULL; + msb->width = IM_IMAGE_SIZEOF_ELEMENT( in ); + msb->index = im_amiMSBfirst() ? 0 : msb->width - 1; + msb->repeat = in->Bands; - if (IM_UNCODED (in)) - { - - if (!IM_ANY_INT (in)) - { - im_error (FUNCTION_NAME, "%s", _("char, short or int only")); - return -1; + if( vips_bandfmt_isuint( in->BandFmt ) ) + func = (im_wrapone_fn) byte_select; + else + func = (im_wrapone_fn) byte_select_flip; + } + else if( IM_CODING_LABQ == in->Coding ) + func = (im_wrapone_fn) msb_labq; + else { + im_error( "im_msb", "%s", _( "unknown coding" ) ); + return( -1 ); } - params = IM_ARRAY (out, 3, size_t); + if( im_cp_desc( out, in ) ) + return( -1 ); + out->BandFmt = IM_BANDFMT_UCHAR; + out->Coding = IM_CODING_NONE; - if (!params) - return -1; - - width = SIZEOF_BAND (in->BandFmt); - -#if G_BYTE_ORDER == G_BIG_ENDIAN - index = 0; -#else - index = width - 1; -#endif - - repeat = in->Bands; - - if (IM_UNSIGNED (in)) - func = (im_wrapone_fn) byte_select; - else - func = (im_wrapone_fn) byte_select_flip; - - if (1 == width && (im_wrapone_fn) byte_select == func) - { - return im_copy (in, out); - } - } - - else if (IM_CODING_LABQ == in->Coding) - - func = (im_wrapone_fn) msb_labq; - - else - { - im_error (FUNCTION_NAME, "%s", _("unknown coding")); - return -1; - } - - if (im_cp_desc (out, in)) - return -1; - - out->BandFmt = IM_BANDFMT_UCHAR; - out->Coding = IM_CODING_NONE; - - return im_wrapone (in, out, func, (void *) params, NULL); - -#undef index -#undef width -#undef repeat - -#undef FUNCTION_NAME + return( im_wrapone( in, out, func, msb, NULL ) ); } +/** + * im_msb_band: + * @in: input image + * @out: output image + * @band: select this band + * + * Turn any integer image to a single-band 8-bit unsigned char by discarding + * all but the most significant byte from the selected band. + * Signed values are converted to unsigned by adding 128. + * + * This operator also works for LABQ coding. + * + * See also: im_msb_band(). + * + * Returns: 0 on success, -1 on error + */ int -im_msb_band (IMAGE * in, IMAGE * out, int band) +im_msb_band( IMAGE *in, IMAGE *out, int band ) { -#define FUNCTION_NAME "im_msb_band" + Msb *msb; + im_wrapone_fn func; - size_t *params; - im_wrapone_fn func; - -#define index (params[0]) -#define width (params[1]) -#define repeat (params[2]) - - if (band < 0) - { - im_error (FUNCTION_NAME, "%s", _("bad arguments")); - return -1; - } - - if (im_piocheck (in, out)) - return -1; - - params = IM_ARRAY (out, 3, size_t); - - if (!params) - return -1; - - if (IM_UNCODED (in)) - { - - if (!IM_ANY_INT (in)) - { - im_error (FUNCTION_NAME, "%s", _("char, short or int only")); - return -1; + if( band < 0 ) { + im_error( "im_msb_band", "%s", _( "bad arguments" ) ); + return( -1 ); } - if (band >= in->Bands) - { - im_error (FUNCTION_NAME, - "%s", _("image does not have that many bands")); - return -1; + if( im_piocheck( in, out ) || + !(msb = IM_NEW( out, Msb )) ) + return( -1 ); + + if( in->Coding == IM_CODING_NONE ) { + if( im_check_int( "im_msb_band", in ) ) + return( -1 ); + + if( band >= in->Bands ) { + im_error( "im_msb_band", "%s", + _( "image does not have that many bands" ) ); + return( -1 ); + } + + msb->width = IM_IMAGE_SIZEOF_ELEMENT( in ); + msb->index = im_amiMSBfirst() ? + msb->width * band : msb->width * (band + 1) - 1; + msb->repeat = 1; + + if( vips_bandfmt_isuint( in->BandFmt ) ) + func = (im_wrapone_fn) byte_select; + else + func = (im_wrapone_fn) byte_select_flip; + } + else if( IM_CODING_LABQ == in->Coding ) { + if( band > 2 ) { + im_error( "im_msb_band", "%s", + _( "image does not have that many bands" ) ); + return( -1 ); + } + msb->width = 4; + msb->repeat = 1; + msb->index = band; + + if( band ) + func = (im_wrapone_fn) byte_select_flip; + else + func = (im_wrapone_fn) byte_select; + } + else { + im_error( "im_msb", "%s", _( "unknown coding" ) ); + return( -1 ); } - width = SIZEOF_BAND (in->BandFmt); + if( im_cp_desc( out, in ) ) + return( -1 ); + out->BandFmt = IM_BANDFMT_UCHAR; + out->Coding = IM_CODING_NONE; + out->Bands = 1; -#if G_BYTE_ORDER == G_BIG_ENDIAN - index = width * band; -#else - index = (width * (band + 1)) - 1; -#endif - - width *= in->Bands; - repeat = 1; - - if (IM_UNSIGNED (in)) - func = (im_wrapone_fn) byte_select; - else - func = (im_wrapone_fn) byte_select_flip; - } - - else if (IM_CODING_LABQ == in->Coding) - { - - if (band > 2) - { - im_error (FUNCTION_NAME, - "%s", _("image does not have that many bands")); - return -1; - } - width = 4; - repeat = 1; - index = band; - - if (band) - func = (im_wrapone_fn) byte_select_flip; - else - func = (im_wrapone_fn) byte_select; - } - else - { - im_error (FUNCTION_NAME, "%s", _("unknown coding")); - return -1; - } - - if (im_cp_desc (out, in)) - return -1; - - out->Bands = 1; - out->BandFmt = IM_BANDFMT_UCHAR; - out->Coding = IM_CODING_NONE; - - return im_wrapone (in, out, func, (void *) params, NULL); - -#undef index -#undef width -#undef repeat - -#undef FUNCTION_NAME -} - -/** LOCAL FUNCTIONS DEFINITIONS **/ -static void -byte_select (unsigned char *in, unsigned char *out, int n, size_t * params) -{ -#define index (params[0]) -#define width (params[1]) -#define repeat (params[2]) - - unsigned char *stop = out + n * repeat; - - for (in += index; out < stop; in += width, ++out) - *out = *in; - -#undef index -#undef width -#undef repeat -} - -static void -byte_select_flip (unsigned char *in, unsigned char *out, int n, - size_t * params) -{ -#define index (params[0]) -#define width (params[1]) -#define repeat (params[2]) - - unsigned char *stop = out + n * repeat; - - for (in += index; out < stop; in += width, ++out) - *out = 0x80 ^ *in; - -#undef index -#undef width -#undef repeat -} - -static void -msb_labq (unsigned char *in, unsigned char *out, int n) -{ - unsigned char *stop = in + (n << 2); - - for (; in < stop; in += 4, out += 3) - { - out[0] = in[0]; - out[1] = 0x80 ^ in[1]; - out[2] = 0x80 ^ in[2]; - } + return( im_wrapone( in, out, func, msb, NULL ) ); }