im_histcum() as a class
This commit is contained in:
parent
c60b75aed2
commit
4e9ed44432
@ -3,7 +3,7 @@
|
||||
- rename image arrays as image matrices ... INTERPRETATION_ARRAY ->
|
||||
INTERPRETATION_MATRIX etc.
|
||||
- rewrite im_buildlut(), im_identity*(), im_maplut(), im_falsecolour(),
|
||||
im_gammacorrect(), im_histgr() as classes
|
||||
im_gammacorrect(), im_histgr(), im_histcum() as classes
|
||||
- added vips_error_freeze() / vips_error_thaw()
|
||||
- used freeze() / thaw() to stop file format sniffers logging spurious errors
|
||||
- vipsthumbnail uses embedded jpg thumbnails if it can
|
||||
|
@ -3324,6 +3324,23 @@ im_maplut( IMAGE *in, IMAGE *out, IMAGE *lut )
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
int
|
||||
im_histcum( IMAGE *in, IMAGE *out )
|
||||
{
|
||||
VipsImage *x;
|
||||
|
||||
if( vips_hist_cum( in, &x, NULL ) )
|
||||
return( -1 );
|
||||
|
||||
if( im_copy( x, out ) ) {
|
||||
g_object_unref( x );
|
||||
return( -1 );
|
||||
}
|
||||
g_object_unref( x );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
int
|
||||
im_hist( IMAGE *in, IMAGE *out, int bandno )
|
||||
{
|
||||
|
@ -2,6 +2,7 @@ noinst_LTLIBRARIES = libhistogram.la
|
||||
|
||||
libhistogram_la_SOURCES = \
|
||||
maplut.c \
|
||||
hist_cum.c \
|
||||
histogram.c \
|
||||
phistogram.h \
|
||||
hist_dispatch.c \
|
||||
|
@ -62,10 +62,15 @@
|
||||
|
||||
#include "phistogram.h"
|
||||
|
||||
typedef VipsHistogram VipsHistCum;
|
||||
typedef VipsHistogramClass VipsHistCumClass;
|
||||
|
||||
G_DEFINE_TYPE( VipsHistCum, vips_hist_cum, VIPS_TYPE_HISTOGRAM );
|
||||
|
||||
#define ACCUMULATE( ITYPE, OTYPE ) { \
|
||||
for( b = 0; b < nb; b++ ) { \
|
||||
ITYPE *p = (ITYPE *) in->data; \
|
||||
OTYPE *q = (OTYPE *) outbuf; \
|
||||
ITYPE *p = (ITYPE *) in; \
|
||||
OTYPE *q = (OTYPE *) out; \
|
||||
OTYPE total; \
|
||||
\
|
||||
total = 0; \
|
||||
@ -76,74 +81,99 @@
|
||||
} \
|
||||
}
|
||||
|
||||
/**
|
||||
* im_histcum:
|
||||
* @in: input image
|
||||
* @out: output image
|
||||
*
|
||||
* Form cumulative histogram.
|
||||
*
|
||||
* See also: im_histnorm().
|
||||
*
|
||||
* Returns: 0 on success, -1 on error
|
||||
*/
|
||||
int
|
||||
im_histcum( IMAGE *in, IMAGE *out )
|
||||
static void
|
||||
vips_hist_cum_buffer( VipsHistogram *histogram,
|
||||
VipsPel *out, VipsPel *in, int width )
|
||||
{
|
||||
const guint64 px = VIPS_IMAGE_N_PELS( in );
|
||||
const int nb = vips_bandfmt_iscomplex( in->BandFmt ) ?
|
||||
in->Bands * 2 : in->Bands;
|
||||
const guint64 mx = px * nb;
|
||||
const int bands = vips_image_get_bands( histogram->in );
|
||||
const int nb = vips_bandfmt_iscomplex( histogram->in->BandFmt ) ?
|
||||
bands * 2 : bands;
|
||||
int mx = width * nb;
|
||||
|
||||
VipsPel *outbuf;
|
||||
guint64 b, x;
|
||||
int x, b;
|
||||
|
||||
if( im_check_uncoded( "im_histcum", in ) ||
|
||||
im_check_hist( "im_histcum", in ) ||
|
||||
im_iocheck( in, out ) )
|
||||
return( -1 );
|
||||
|
||||
if( im_cp_desc( out, in ) )
|
||||
return( -1 );
|
||||
out->Xsize = px;
|
||||
out->Ysize = 1;
|
||||
if( vips_bandfmt_isuint( in->BandFmt ) )
|
||||
out->BandFmt = IM_BANDFMT_UINT;
|
||||
else if( vips_bandfmt_isint( in->BandFmt ) )
|
||||
out->BandFmt = IM_BANDFMT_INT;
|
||||
if( im_setupout( out ) )
|
||||
return( -1 );
|
||||
|
||||
if( !(outbuf = im_malloc( out, IM_IMAGE_SIZEOF_LINE( out ))) )
|
||||
return( -1 );
|
||||
|
||||
switch( in->BandFmt ) {
|
||||
case IM_BANDFMT_CHAR:
|
||||
switch( vips_image_get_format( histogram->in ) ) {
|
||||
case VIPS_FORMAT_CHAR:
|
||||
ACCUMULATE( signed char, signed int ); break;
|
||||
case IM_BANDFMT_UCHAR:
|
||||
case VIPS_FORMAT_UCHAR:
|
||||
ACCUMULATE( unsigned char, unsigned int ); break;
|
||||
case IM_BANDFMT_SHORT:
|
||||
case VIPS_FORMAT_SHORT:
|
||||
ACCUMULATE( signed short, signed int ); break;
|
||||
case IM_BANDFMT_USHORT:
|
||||
case VIPS_FORMAT_USHORT:
|
||||
ACCUMULATE( unsigned short, unsigned int ); break;
|
||||
case IM_BANDFMT_INT:
|
||||
case VIPS_FORMAT_INT:
|
||||
ACCUMULATE( signed int, signed int ); break;
|
||||
case IM_BANDFMT_UINT:
|
||||
case VIPS_FORMAT_UINT:
|
||||
ACCUMULATE( unsigned int, unsigned int ); break;
|
||||
|
||||
case IM_BANDFMT_FLOAT:
|
||||
case IM_BANDFMT_COMPLEX:
|
||||
case VIPS_FORMAT_FLOAT:
|
||||
case VIPS_FORMAT_COMPLEX:
|
||||
ACCUMULATE( float, float ); break;
|
||||
case IM_BANDFMT_DOUBLE:
|
||||
case IM_BANDFMT_DPCOMPLEX:
|
||||
case VIPS_FORMAT_DOUBLE:
|
||||
case VIPS_FORMAT_DPCOMPLEX:
|
||||
ACCUMULATE( double, double ); break;
|
||||
|
||||
default:
|
||||
g_assert( 0 );
|
||||
}
|
||||
|
||||
if( im_writeline( 0, out, outbuf ) )
|
||||
return( -1 );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/* Save a bit of typing.
|
||||
*/
|
||||
#define UC VIPS_FORMAT_UCHAR
|
||||
#define C VIPS_FORMAT_CHAR
|
||||
#define US VIPS_FORMAT_USHORT
|
||||
#define S VIPS_FORMAT_SHORT
|
||||
#define UI VIPS_FORMAT_UINT
|
||||
#define I VIPS_FORMAT_INT
|
||||
#define F VIPS_FORMAT_FLOAT
|
||||
#define X VIPS_FORMAT_COMPLEX
|
||||
#define D VIPS_FORMAT_DOUBLE
|
||||
#define DX VIPS_FORMAT_DPCOMPLEX
|
||||
|
||||
static const VipsBandFormat vips_bandfmt_hist_cum[10] = {
|
||||
/* UC C US S UI I F X D DX */
|
||||
UI, I, UI, I, UI, I, F, F, D, D
|
||||
};
|
||||
|
||||
static void
|
||||
vips_hist_cum_class_init( VipsHistCumClass *class )
|
||||
{
|
||||
VipsObjectClass *object_class = (VipsObjectClass *) class;
|
||||
VipsHistogramClass *hclass = VIPS_HISTOGRAM_CLASS( class );
|
||||
|
||||
object_class->nickname = "hist_cum";
|
||||
object_class->description = _( "form cumulative histogram" );
|
||||
|
||||
hclass->format_table = vips_bandfmt_hist_cum;
|
||||
hclass->process = vips_hist_cum_buffer;
|
||||
}
|
||||
|
||||
static void
|
||||
vips_hist_cum_init( VipsHistCum *hist_cum )
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* vips_hist_cum:
|
||||
* @in: input image
|
||||
* @out: output image
|
||||
*
|
||||
* Form cumulative histogram.
|
||||
*
|
||||
* See also: vips_hist_norm().
|
||||
*
|
||||
* Returns: 0 on success, -1 on error
|
||||
*/
|
||||
int
|
||||
vips_hist_cum( VipsImage *in, VipsImage **out, ... )
|
||||
{
|
||||
va_list ap;
|
||||
int result;
|
||||
|
||||
va_start( ap, out );
|
||||
result = vips_call_split( "hist_cum", ap, in, out );
|
||||
va_end( ap );
|
||||
|
||||
return( result );
|
||||
}
|
||||
|
@ -80,6 +80,9 @@ vips_histogram_build( VipsObject *object )
|
||||
{
|
||||
VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( object );
|
||||
VipsHistogram *histogram = VIPS_HISTOGRAM( object );
|
||||
VipsHistogramClass *hclass = VIPS_HISTOGRAM_GET_CLASS( histogram );
|
||||
|
||||
VipsPel *outbuf;
|
||||
|
||||
#ifdef DEBUG
|
||||
printf( "vips_histogram_build: " );
|
||||
@ -87,12 +90,34 @@ vips_histogram_build( VipsObject *object )
|
||||
printf( "\n" );
|
||||
#endif /*DEBUG*/
|
||||
|
||||
g_object_set( histogram, "out", vips_image_new(), NULL );
|
||||
|
||||
if( VIPS_OBJECT_CLASS( vips_histogram_parent_class )->build( object ) )
|
||||
return( -1 );
|
||||
|
||||
if( vips_check_hist( class->nickname, histogram->in ) )
|
||||
g_object_set( histogram, "out", vips_image_new(), NULL );
|
||||
|
||||
if( vips_check_hist( class->nickname, histogram->in ) ||
|
||||
vips_check_uncoded( class->nickname, histogram->in ) )
|
||||
return( -1 );
|
||||
|
||||
if( vips_image_wio_input( histogram->in ) ||
|
||||
vips_image_copy_fields( histogram->out, histogram->in ) )
|
||||
return( -1 );
|
||||
|
||||
histogram->out->Xsize = VIPS_IMAGE_N_PELS( histogram->in );
|
||||
histogram->out->Ysize = 1;
|
||||
if( hclass->format_table )
|
||||
histogram->out->BandFmt =
|
||||
hclass->format_table[histogram->in->BandFmt];
|
||||
|
||||
if( !(outbuf = vips_malloc( object,
|
||||
VIPS_IMAGE_SIZEOF_LINE( histogram->out ))) )
|
||||
return( -1 );
|
||||
|
||||
hclass->process( histogram,
|
||||
outbuf, VIPS_IMAGE_ADDR( histogram->in, 0, 0 ),
|
||||
histogram->in->Xsize );
|
||||
|
||||
if( vips_image_write_line( histogram->out, 0, outbuf ) )
|
||||
return( -1 );
|
||||
|
||||
return( 0 );
|
||||
@ -137,6 +162,8 @@ void
|
||||
vips_histogram_operation_init( void )
|
||||
{
|
||||
extern GType vips_maplut_get_type( void );
|
||||
extern GType vips_hist_cum_get_type( void );
|
||||
|
||||
vips_maplut_get_type();
|
||||
vips_hist_cum_get_type();
|
||||
}
|
||||
|
@ -58,93 +58,6 @@
|
||||
|
||||
#include <vips/vips.h>
|
||||
|
||||
#define ACCUMULATE( ITYPE, OTYPE ) { \
|
||||
for( b = 0; b < nb; b++ ) { \
|
||||
ITYPE *p = (ITYPE *) in->data; \
|
||||
OTYPE *q = (OTYPE *) outbuf; \
|
||||
OTYPE total; \
|
||||
\
|
||||
total = 0; \
|
||||
for( x = b; x < mx; x += nb ) { \
|
||||
total += p[x]; \
|
||||
q[x] = total; \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
/**
|
||||
* im_histcum:
|
||||
* @in: input image
|
||||
* @out: output image
|
||||
*
|
||||
* Form cumulative histogram.
|
||||
*
|
||||
* See also: im_histnorm().
|
||||
*
|
||||
* Returns: 0 on success, -1 on error
|
||||
*/
|
||||
int
|
||||
im_histcum( IMAGE *in, IMAGE *out )
|
||||
{
|
||||
const guint64 px = VIPS_IMAGE_N_PELS( in );
|
||||
const int nb = vips_bandfmt_iscomplex( in->BandFmt ) ?
|
||||
in->Bands * 2 : in->Bands;
|
||||
const guint64 mx = px * nb;
|
||||
|
||||
VipsPel *outbuf;
|
||||
guint64 b, x;
|
||||
|
||||
if( im_check_uncoded( "im_histcum", in ) ||
|
||||
im_check_hist( "im_histcum", in ) ||
|
||||
im_iocheck( in, out ) )
|
||||
return( -1 );
|
||||
|
||||
if( im_cp_desc( out, in ) )
|
||||
return( -1 );
|
||||
out->Xsize = px;
|
||||
out->Ysize = 1;
|
||||
if( vips_bandfmt_isuint( in->BandFmt ) )
|
||||
out->BandFmt = IM_BANDFMT_UINT;
|
||||
else if( vips_bandfmt_isint( in->BandFmt ) )
|
||||
out->BandFmt = IM_BANDFMT_INT;
|
||||
if( im_setupout( out ) )
|
||||
return( -1 );
|
||||
|
||||
if( !(outbuf = im_malloc( out, IM_IMAGE_SIZEOF_LINE( out ))) )
|
||||
return( -1 );
|
||||
|
||||
switch( in->BandFmt ) {
|
||||
case IM_BANDFMT_CHAR:
|
||||
ACCUMULATE( signed char, signed int ); break;
|
||||
case IM_BANDFMT_UCHAR:
|
||||
ACCUMULATE( unsigned char, unsigned int ); break;
|
||||
case IM_BANDFMT_SHORT:
|
||||
ACCUMULATE( signed short, signed int ); break;
|
||||
case IM_BANDFMT_USHORT:
|
||||
ACCUMULATE( unsigned short, unsigned int ); break;
|
||||
case IM_BANDFMT_INT:
|
||||
ACCUMULATE( signed int, signed int ); break;
|
||||
case IM_BANDFMT_UINT:
|
||||
ACCUMULATE( unsigned int, unsigned int ); break;
|
||||
|
||||
case IM_BANDFMT_FLOAT:
|
||||
case IM_BANDFMT_COMPLEX:
|
||||
ACCUMULATE( float, float ); break;
|
||||
case IM_BANDFMT_DOUBLE:
|
||||
case IM_BANDFMT_DPCOMPLEX:
|
||||
ACCUMULATE( double, double ); break;
|
||||
|
||||
default:
|
||||
g_assert( 0 );
|
||||
}
|
||||
|
||||
if( im_writeline( 0, out, outbuf ) )
|
||||
return( -1 );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* im_histnorm:
|
||||
* @in: input image
|
||||
|
@ -52,6 +52,10 @@ extern "C" {
|
||||
(G_TYPE_INSTANCE_GET_CLASS( (obj), \
|
||||
VIPS_TYPE_HISTOGRAM, VipsHistogramClass ))
|
||||
|
||||
struct _VipsHistogram;
|
||||
typedef void (*VipsHistogramProcessFn)( struct _VipsHistogram *histogram,
|
||||
VipsPel *out, VipsPel *in, int width );
|
||||
|
||||
typedef struct _VipsHistogram {
|
||||
VipsOperation parent_instance;
|
||||
|
||||
@ -66,6 +70,11 @@ typedef struct _VipsHistogram {
|
||||
typedef struct _VipsHistogramClass {
|
||||
VipsOperationClass parent_class;
|
||||
|
||||
/* For each input format, what output format.
|
||||
*/
|
||||
const VipsBandFormat *format_table;
|
||||
|
||||
VipsHistogramProcessFn process;
|
||||
} VipsHistogramClass;
|
||||
|
||||
GType vips_histogram_get_type( void );
|
||||
|
@ -40,6 +40,8 @@ extern "C" {
|
||||
|
||||
int vips_maplut( VipsImage *in, VipsImage **out, VipsImage *lut, ... )
|
||||
__attribute__((sentinel));
|
||||
int vips_hist_cum( VipsImage *in, VipsImage **out, ... )
|
||||
__attribute__((sentinel));
|
||||
|
||||
|
||||
int im_histnD( VipsImage *in, VipsImage *out, int bins );
|
||||
@ -49,7 +51,6 @@ int im_invertlut( DOUBLEMASK *input, VipsImage *output, int lut_size );
|
||||
int im_project( VipsImage *in, VipsImage *hout, VipsImage *vout );
|
||||
|
||||
int im_histnorm( VipsImage *in, VipsImage *out );
|
||||
int im_histcum( VipsImage *in, VipsImage *out );
|
||||
int im_histeq( VipsImage *in, VipsImage *out );
|
||||
int im_histspec( VipsImage *in, VipsImage *ref, VipsImage *out );
|
||||
int im_ismonotonic( VipsImage *lut, int *out );
|
||||
|
@ -852,6 +852,7 @@ int im_quadratic( IMAGE *in, IMAGE *out, IMAGE *coeff );
|
||||
int im_maplut( VipsImage *in, VipsImage *out, VipsImage *lut );
|
||||
int im_hist( VipsImage *in, VipsImage *out, int bandno );
|
||||
int im_histgr( VipsImage *in, VipsImage *out, int bandno );
|
||||
int im_histcum( VipsImage *in, VipsImage *out );
|
||||
|
||||
/* ruby-vips uses this
|
||||
*/
|
||||
|
@ -1923,8 +1923,6 @@ vips_image_write_prepare( VipsImage *image )
|
||||
break;
|
||||
|
||||
case VIPS_IMAGE_SETBUF:
|
||||
/* Allocate memory.
|
||||
*/
|
||||
if( !image->data &&
|
||||
!(image->data = vips_tracked_malloc(
|
||||
VIPS_IMAGE_SIZEOF_IMAGE( image ))) )
|
||||
|
Loading…
Reference in New Issue
Block a user