add --uchar option to vips_linear()
This commit is contained in:
parent
a181ef1f2c
commit
e489d2e099
@ -35,6 +35,7 @@
|
||||
- redone im_fwfft(), im_invfft(), im_freqflt(), im_disp_ps(), im_fractsurf(),
|
||||
im_phasecor() as classes
|
||||
- vips_colourspace() allows B_W, GREY16, RGB16 as source / target
|
||||
- vips_linear() has a uchar output mode
|
||||
|
||||
9/1/14 started 7.36.6
|
||||
- fix some clang compiler warnings
|
||||
|
6
TODO
6
TODO
@ -1,13 +1,9 @@
|
||||
- now vips_linear() has uchar output, can we do something with orc?
|
||||
|
||||
- do restrict on some more packages, we've just done arithmetic so far
|
||||
|
||||
also resample, colour, some of conversion, create,
|
||||
|
||||
- orc is poor for float stuff ... if vips_linear() had a "preserve type"
|
||||
option we could do something
|
||||
|
||||
maybe a "uchar ouput" option? this seems to be a very common case
|
||||
|
||||
- maybe avg?
|
||||
|
||||
but avg doesn't subclass arithmetic, so we can't
|
||||
|
@ -554,8 +554,11 @@ vips_arithmetic_build( VipsObject *object )
|
||||
return( -1 );
|
||||
|
||||
arithmetic->out->Bands = arithmetic->ready[0]->Bands;
|
||||
arithmetic->out->BandFmt =
|
||||
aclass->format_table[arithmetic->ready[0]->BandFmt];
|
||||
if( arithmetic->format != VIPS_FORMAT_NOTSET )
|
||||
arithmetic->out->BandFmt = arithmetic->format;
|
||||
else
|
||||
arithmetic->out->BandFmt =
|
||||
aclass->format_table[arithmetic->ready[0]->BandFmt];
|
||||
|
||||
if( vips_image_generate( arithmetic->out,
|
||||
vips_start_many, vips_arithmetic_gen, vips_stop_many,
|
||||
@ -592,6 +595,7 @@ static void
|
||||
vips_arithmetic_init( VipsArithmetic *arithmetic )
|
||||
{
|
||||
arithmetic->base_bands = 1;
|
||||
arithmetic->format = VIPS_FORMAT_NOTSET;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -42,6 +42,8 @@
|
||||
* - 1ary is back, faster with gcc 4.8
|
||||
* 3/12/13
|
||||
* - try an ORC path with the band loop unrolled
|
||||
* 14/1/14
|
||||
* - add uchar output option
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -96,6 +98,10 @@ typedef struct _VipsLinear {
|
||||
VipsArea *a;
|
||||
VipsArea *b;
|
||||
|
||||
/* uchar output.
|
||||
*/
|
||||
gboolean uchar;
|
||||
|
||||
/* Our constants expanded to match arith->ready in size.
|
||||
*/
|
||||
int n;
|
||||
@ -159,6 +165,9 @@ vips_linear_build( VipsObject *object )
|
||||
}
|
||||
}
|
||||
|
||||
if( linear->uchar )
|
||||
arithmetic->format = VIPS_FORMAT_UCHAR;
|
||||
|
||||
if( VIPS_OBJECT_CLASS( vips_linear_parent_class )->build( object ) )
|
||||
return( -1 );
|
||||
|
||||
@ -198,7 +207,6 @@ vips_linear_build( VipsObject *object )
|
||||
} \
|
||||
}
|
||||
|
||||
|
||||
/* Complex input, complex output.
|
||||
*/
|
||||
#define LOOPCMPLXN( IN, OUT ) { \
|
||||
@ -214,6 +222,61 @@ vips_linear_build( VipsObject *object )
|
||||
} \
|
||||
}
|
||||
|
||||
/* Non-complex input, any output, all bands of the constant equal, uchar
|
||||
* output.
|
||||
*/
|
||||
#define LOOP1uc( IN ) { \
|
||||
IN * restrict p = (IN *) in[0]; \
|
||||
VipsPel * restrict q = (VipsPel *) out; \
|
||||
float a1 = a[0]; \
|
||||
float b1 = b[0]; \
|
||||
int sz = width * nb; \
|
||||
\
|
||||
for( x = 0; x < sz; x++ ) { \
|
||||
float t = a1 * p[x] + b1; \
|
||||
\
|
||||
q[x] = VIPS_CLIP( 0, t, 255 ); \
|
||||
} \
|
||||
}
|
||||
|
||||
/* Non-complex input, uchar output.
|
||||
*/
|
||||
#define LOOPNuc( IN ) { \
|
||||
IN * restrict p = (IN *) in[0]; \
|
||||
VipsPel * restrict q = (VipsPel *) out; \
|
||||
\
|
||||
for( i = 0, x = 0; x < width; x++ ) \
|
||||
for( k = 0; k < nb; k++, i++ ) { \
|
||||
double t = a[k] * p[i] + b[k]; \
|
||||
\
|
||||
q[i] = VIPS_CLIP( 0, t, 255 ); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define LOOPuc( IN ) { \
|
||||
if( linear->a->n == 1 && linear->b->n == 1 ) { \
|
||||
LOOP1uc( IN ); \
|
||||
} \
|
||||
else { \
|
||||
LOOPNuc( IN ); \
|
||||
} \
|
||||
}
|
||||
|
||||
/* Complex input, uchar output.
|
||||
*/
|
||||
#define LOOPCMPLXNuc( IN ) { \
|
||||
IN * restrict p = (IN *) in[0]; \
|
||||
VipsPel * restrict q = (VipsPel *) out; \
|
||||
\
|
||||
for( i = 0, x = 0; x < width; x++ ) \
|
||||
for( k = 0; k < nb; k++, i++ ) { \
|
||||
double t = a[k] * p[0] + b[k]; \
|
||||
\
|
||||
q[i] = VIPS_CLIP( 0, t, 255 ); \
|
||||
p += 2; \
|
||||
} \
|
||||
}
|
||||
|
||||
/* Lintra a buffer, n set of scale/offset.
|
||||
*/
|
||||
static void
|
||||
@ -228,21 +291,59 @@ vips_linear_buffer( VipsArithmetic *arithmetic,
|
||||
|
||||
int i, x, k;
|
||||
|
||||
switch( vips_image_get_format( im ) ) {
|
||||
case VIPS_FORMAT_UCHAR: LOOP( unsigned char, float ); break;
|
||||
case VIPS_FORMAT_CHAR: LOOP( signed char, float ); break;
|
||||
case VIPS_FORMAT_USHORT: LOOP( unsigned short, float ); break;
|
||||
case VIPS_FORMAT_SHORT: LOOP( signed short, float ); break;
|
||||
case VIPS_FORMAT_UINT: LOOP( unsigned int, float ); break;
|
||||
case VIPS_FORMAT_INT: LOOP( signed int, float ); break;
|
||||
case VIPS_FORMAT_FLOAT: LOOP( float, float ); break;
|
||||
case VIPS_FORMAT_DOUBLE: LOOP( double, double ); break;
|
||||
case VIPS_FORMAT_COMPLEX: LOOPCMPLXN( float, float ); break;
|
||||
case VIPS_FORMAT_DPCOMPLEX: LOOPCMPLXN( double, double ); break;
|
||||
if( linear->uchar )
|
||||
switch( vips_image_get_format( im ) ) {
|
||||
case VIPS_FORMAT_UCHAR:
|
||||
LOOPuc( unsigned char ); break;
|
||||
case VIPS_FORMAT_CHAR:
|
||||
LOOPuc( signed char ); break;
|
||||
case VIPS_FORMAT_USHORT:
|
||||
LOOPuc( unsigned short ); break;
|
||||
case VIPS_FORMAT_SHORT:
|
||||
LOOPuc( signed short ); break;
|
||||
case VIPS_FORMAT_UINT:
|
||||
LOOPuc( unsigned int ); break;
|
||||
case VIPS_FORMAT_INT:
|
||||
LOOPuc( signed int ); break;
|
||||
case VIPS_FORMAT_FLOAT:
|
||||
LOOPuc( float ); break;
|
||||
case VIPS_FORMAT_DOUBLE:
|
||||
LOOPuc( double ); break;
|
||||
case VIPS_FORMAT_COMPLEX:
|
||||
LOOPCMPLXNuc( float ); break;
|
||||
case VIPS_FORMAT_DPCOMPLEX:
|
||||
LOOPCMPLXNuc( double ); break;
|
||||
|
||||
default:
|
||||
g_assert( 0 );
|
||||
}
|
||||
else
|
||||
switch( vips_image_get_format( im ) ) {
|
||||
case VIPS_FORMAT_UCHAR:
|
||||
LOOP( unsigned char, float ); break;
|
||||
case VIPS_FORMAT_CHAR:
|
||||
LOOP( signed char, float ); break;
|
||||
case VIPS_FORMAT_USHORT:
|
||||
LOOP( unsigned short, float ); break;
|
||||
case VIPS_FORMAT_SHORT:
|
||||
LOOP( signed short, float ); break;
|
||||
case VIPS_FORMAT_UINT:
|
||||
LOOP( unsigned int, float ); break;
|
||||
case VIPS_FORMAT_INT:
|
||||
LOOP( signed int, float ); break;
|
||||
case VIPS_FORMAT_FLOAT:
|
||||
LOOP( float, float ); break;
|
||||
case VIPS_FORMAT_DOUBLE:
|
||||
LOOP( double, double ); break;
|
||||
case VIPS_FORMAT_COMPLEX:
|
||||
LOOPCMPLXN( float, float ); break;
|
||||
case VIPS_FORMAT_DPCOMPLEX:
|
||||
LOOPCMPLXN( double, double ); break;
|
||||
|
||||
default:
|
||||
g_assert( 0 );
|
||||
}
|
||||
|
||||
default:
|
||||
g_assert( 0 );
|
||||
}
|
||||
}
|
||||
|
||||
/* Save a bit of typing.
|
||||
@ -296,6 +397,14 @@ vips_linear_class_init( VipsLinearClass *class )
|
||||
VIPS_ARGUMENT_REQUIRED_INPUT,
|
||||
G_STRUCT_OFFSET( VipsLinear, b ),
|
||||
VIPS_TYPE_ARRAY_DOUBLE );
|
||||
|
||||
VIPS_ARG_BOOL( class, "uchar", 112,
|
||||
_( "uchar" ),
|
||||
_( "Output should be uchar" ),
|
||||
VIPS_ARGUMENT_OPTIONAL_INPUT,
|
||||
G_STRUCT_OFFSET( VipsLinear, uchar ),
|
||||
FALSE );
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
@ -331,9 +440,14 @@ vips_linearv( VipsImage *in, VipsImage **out,
|
||||
* @n: length of constant arrays
|
||||
* @...: %NULL-terminated list of optional named arguments
|
||||
*
|
||||
* Optional arguments:
|
||||
*
|
||||
* @uchar: output uchar pixels
|
||||
*
|
||||
* Pass an image through a linear transform, ie. (@out = @in * @a + @b). Output
|
||||
* is always float for integer input, double for double input, complex for
|
||||
* complex input and double complex for double complex input.
|
||||
* is float for integer input, double for double input, complex for
|
||||
* complex input and double complex for double complex input. Set @uchar to
|
||||
* output uchar pixels.
|
||||
*
|
||||
* If the arrays of constants have just one element, that constant is used for
|
||||
* all image bands. If the arrays have more than one element and they have
|
||||
@ -367,6 +481,10 @@ vips_linear( VipsImage *in, VipsImage **out, double *a, double *b, int n, ... )
|
||||
* @b: constant for addition
|
||||
* @...: %NULL-terminated list of optional named arguments
|
||||
*
|
||||
* Optional arguments:
|
||||
*
|
||||
* @uchar: output uchar pixels
|
||||
*
|
||||
* Run vips_linear() with a single constant.
|
||||
*
|
||||
* See also: vips_linear().
|
||||
|
@ -77,6 +77,10 @@ typedef struct _VipsArithmetic {
|
||||
/* The input images, ready for the operation.
|
||||
*/
|
||||
VipsImage **ready;
|
||||
|
||||
/* Set this to override class->format_table.
|
||||
*/
|
||||
VipsBandFormat format;
|
||||
} VipsArithmetic;
|
||||
|
||||
typedef struct _VipsArithmeticClass {
|
||||
|
@ -18,6 +18,8 @@
|
||||
* 30/5/13
|
||||
* - redo as a class
|
||||
* - add log scale and exponent as an option
|
||||
* 14/1/14
|
||||
* - use linear uchar mode
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -107,18 +109,20 @@ vips_scale_build( VipsObject *object )
|
||||
if( vips_pow_const1( scale->in, &t[2], scale->exp, NULL ) ||
|
||||
vips_linear1( t[2], &t[3], 1.0, 1.0, NULL ) ||
|
||||
vips_log10( t[3], &t[4], NULL ) ||
|
||||
vips_linear1( t[4], &t[5], f, 0.0, NULL ) ||
|
||||
vips_cast( t[5], &t[6], VIPS_FORMAT_UCHAR, NULL ) ||
|
||||
vips_image_write( t[6], conversion->out ) )
|
||||
vips_linear1( t[4], &t[5], f, 0.0,
|
||||
"uchar", TRUE,
|
||||
NULL ) ||
|
||||
vips_image_write( t[5], conversion->out ) )
|
||||
return( -1 );
|
||||
}
|
||||
else {
|
||||
double f = 255.0 / (mx - mn);
|
||||
double a = -(mn * f);
|
||||
|
||||
if( vips_linear1( scale->in, &t[2], f, a, NULL ) ||
|
||||
vips_cast( t[2], &t[3], VIPS_FORMAT_UCHAR, NULL ) ||
|
||||
vips_image_write( t[3], conversion->out ) )
|
||||
if( vips_linear1( scale->in, &t[2], f, a,
|
||||
"uchar", TRUE,
|
||||
NULL ) ||
|
||||
vips_image_write( t[2], conversion->out ) )
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
|
@ -115,15 +115,16 @@ vips_point_build( VipsObject *object )
|
||||
float range = max - min;
|
||||
|
||||
if( vips_linear1( in, &t[2],
|
||||
255.0 / range, -min * 255.0 / range, NULL ) ||
|
||||
vips_cast( t[2], &t[3], VIPS_FORMAT_UCHAR, NULL ) )
|
||||
255.0 / range, -min * 255.0 / range,
|
||||
"uchar", TRUE,
|
||||
NULL ) )
|
||||
return( -1 );
|
||||
in = t[3];
|
||||
in = t[2];
|
||||
|
||||
/* uchar mode always does B_W. We don't want FOURIER or
|
||||
* whatever in this case.
|
||||
*/
|
||||
t[3]->Type = VIPS_INTERPRETATION_B_W;
|
||||
in->Type = VIPS_INTERPRETATION_B_W;
|
||||
}
|
||||
|
||||
if( vips_image_write( in, create->out ) )
|
||||
|
Loading…
Reference in New Issue
Block a user