diff --git a/ChangeLog b/ChangeLog index 57a569df..abef4d30 100644 --- a/ChangeLog +++ b/ChangeLog @@ -3,7 +3,8 @@ - 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(), im_histnorm(), im_heq() + 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 diff --git a/libvips/deprecated/vips7compat.c b/libvips/deprecated/vips7compat.c index 71c8ed94..a3387cce 100644 --- a/libvips/deprecated/vips7compat.c +++ b/libvips/deprecated/vips7compat.c @@ -3324,6 +3324,70 @@ 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_histnorm( IMAGE *in, IMAGE *out ) +{ + VipsImage *x; + + if( vips_hist_norm( in, &x, NULL ) ) + return( -1 ); + + if( im_copy( x, out ) ) { + g_object_unref( x ); + return( -1 ); + } + g_object_unref( x ); + + return( 0 ); +} + +int +im_histeq( IMAGE *in, IMAGE *out ) +{ + IMAGE *t1; + + if( !(t1 = im_open_local( out, "im_histeq", "p" )) || + im_histcum( in, t1 ) || + im_histnorm( t1, out ) ) + return( -1 ); + + return( 0 ); +} + +int +im_heq( VipsImage *in, VipsImage *out, int bandno ) +{ + VipsImage *x; + + if( vips_hist_equal( in, &x, "band", bandno, 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 ) { diff --git a/libvips/histogram/Makefile.am b/libvips/histogram/Makefile.am index a3c3b929..e41ac1d8 100644 --- a/libvips/histogram/Makefile.am +++ b/libvips/histogram/Makefile.am @@ -1,12 +1,16 @@ noinst_LTLIBRARIES = libhistogram.la libhistogram_la_SOURCES = \ - maplut.c \ histogram.c \ phistogram.h \ + maplut.c \ + hist_buffer.c \ + hist_buffer.h \ + hist_cum.c \ + hist_norm.c \ + hist_equal.c \ + \ hist_dispatch.c \ - im_heq.c \ - im_histeq.c \ im_histnD.c \ im_histplot.c \ im_histindexed.c \ diff --git a/libvips/histogram/hist_buffer.c b/libvips/histogram/hist_buffer.c new file mode 100644 index 00000000..5a59f958 --- /dev/null +++ b/libvips/histogram/hist_buffer.c @@ -0,0 +1,117 @@ +/* a hist operation implemented as a buffer processor + * + * properties: + * - single hist to single hist + */ + +/* + + Copyright (C) 1991-2005 The National Gallery + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301 USA + + */ + +/* + + These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk + + */ + +/* +#define DEBUG + */ + +#ifdef HAVE_CONFIG_H +#include +#endif /*HAVE_CONFIG_H*/ +#include + +#include +#include +#include + +#include +#include + +#include "phistogram.h" +#include "hist_buffer.h" + +G_DEFINE_ABSTRACT_TYPE( VipsHistBuffer, vips_hist_buffer, VIPS_TYPE_HISTOGRAM ); + +static int +vips_hist_buffer_build( VipsObject *object ) +{ + VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( object ); + VipsHistogram *histogram = VIPS_HISTOGRAM( object ); + VipsHistBuffer *hist_buffer = VIPS_HIST_BUFFER( object ); + VipsHistBufferClass *hclass = VIPS_HIST_BUFFER_GET_CLASS( hist_buffer ); + + VipsPel *outbuf; + +#ifdef DEBUG + printf( "vips_hist_buffer_build: " ); + vips_object_print_name( object ); + printf( "\n" ); +#endif /*DEBUG*/ + + if( VIPS_OBJECT_CLASS( vips_hist_buffer_parent_class )-> + build( object ) ) + return( -1 ); + + 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( hist_buffer, + outbuf, VIPS_IMAGE_ADDR( histogram->in, 0, 0 ), + histogram->in->Xsize ); + + if( vips_image_write_line( histogram->out, 0, outbuf ) ) + return( -1 ); + + return( 0 ); +} + +static void +vips_hist_buffer_class_init( VipsHistBufferClass *class ) +{ + VipsObjectClass *vobject_class = VIPS_OBJECT_CLASS( class ); + + vobject_class->nickname = "hist_buffer"; + vobject_class->description = _( "hist_buffer operations" ); + vobject_class->build = vips_hist_buffer_build; + +} + +static void +vips_hist_buffer_init( VipsHistBuffer *hist_buffer ) +{ +} diff --git a/libvips/histogram/hist_buffer.h b/libvips/histogram/hist_buffer.h new file mode 100644 index 00000000..80468ba1 --- /dev/null +++ b/libvips/histogram/hist_buffer.h @@ -0,0 +1,82 @@ +/* base class for all hist_buffer operations + */ + +/* + + Copyright (C) 1991-2005 The National Gallery + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301 USA + + */ + +/* + + These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk + + */ + +#ifndef VIPS_PHIST_BUFFER_H +#define VIPS_PHIST_BUFFER_H + +#ifdef __cplusplus +extern "C" { +#endif /*__cplusplus*/ + +#include + +#define VIPS_TYPE_HIST_BUFFER (vips_hist_buffer_get_type()) +#define VIPS_HIST_BUFFER( obj ) \ + (G_TYPE_CHECK_INSTANCE_CAST( (obj), \ + VIPS_TYPE_HIST_BUFFER, VipsHistBuffer )) +#define VIPS_HIST_BUFFER_CLASS( klass ) \ + (G_TYPE_CHECK_CLASS_CAST( (klass), \ + VIPS_TYPE_HIST_BUFFER, VipsHistBufferClass)) +#define VIPS_IS_HIST_BUFFER( obj ) \ + (G_TYPE_CHECK_INSTANCE_TYPE( (obj), VIPS_TYPE_HIST_BUFFER )) +#define VIPS_IS_HIST_BUFFER_CLASS( klass ) \ + (G_TYPE_CHECK_CLASS_TYPE( (klass), VIPS_TYPE_HIST_BUFFER )) +#define VIPS_HIST_BUFFER_GET_CLASS( obj ) \ + (G_TYPE_INSTANCE_GET_CLASS( (obj), \ + VIPS_TYPE_HIST_BUFFER, VipsHistBufferClass )) + +struct _VipsHistBuffer; +typedef void (*VipsHistBufferProcessFn)( struct _VipsHistBuffer *hist_buffer, + VipsPel *out, VipsPel *in, int width ); + +typedef struct _VipsHistBuffer { + VipsHistogram parent_instance; + +} VipsHistBuffer; + +typedef struct _VipsHistBufferClass { + VipsHistogramClass parent_class; + + /* For each input format, what output format. + */ + const VipsBandFormat *format_table; + + VipsHistBufferProcessFn process; +} VipsHistBufferClass; + +GType vips_hist_buffer_get_type( void ); + +#ifdef __cplusplus +} +#endif /*__cplusplus*/ + +#endif /*VIPS_PHIST_BUFFER_H*/ + + diff --git a/libvips/histogram/hist_cum.c b/libvips/histogram/hist_cum.c index 87019aad..49d5e0b5 100644 --- a/libvips/histogram/hist_cum.c +++ b/libvips/histogram/hist_cum.c @@ -61,11 +61,17 @@ #include #include "phistogram.h" +#include "hist_buffer.h" + +typedef VipsHistBuffer VipsHistCum; +typedef VipsHistBufferClass VipsHistCumClass; + +G_DEFINE_TYPE( VipsHistCum, vips_hist_cum, VIPS_TYPE_HIST_BUFFER ); #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 +82,100 @@ } \ } -/** - * 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( VipsHistBuffer *hist_buffer, + 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; + VipsHistogram *histogram = VIPS_HISTOGRAM( hist_buffer ); + 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; + VipsHistBufferClass *hclass = VIPS_HIST_BUFFER_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 ); } diff --git a/libvips/histogram/hist_equal.c b/libvips/histogram/hist_equal.c new file mode 100644 index 00000000..32efa294 --- /dev/null +++ b/libvips/histogram/hist_equal.c @@ -0,0 +1,146 @@ +/* Histogram-equalise an image. + * + * Copyright: 1991, N. Dessipris. + * + * Author: Nicos Dessipris + * Written on: 27/03/1991 + * Modified on : + * 16/6/93 J.Cupitt + * - im_ioflag() changed to im_iocheck() + * 24/5/95 JC + * - ANSIfied and tidied up + * 3/3/01 JC + * - more cleanup + * 23/3/10 + * - gtkdoc + * 12/8/13 + * - redone as a class + */ + +/* + + This file is part of VIPS. + + VIPS is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301 USA + + */ + +/* + + These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk + + */ + +#ifdef HAVE_CONFIG_H +#include +#endif /*HAVE_CONFIG_H*/ +#include + +#include + +#include + +#include "phistogram.h" + +typedef struct _VipsHistEqual { + VipsHistogram parent_instance; + + /* -1 for all bands, or the band we scan. + */ + int which; +} VipsHistEqual; + +typedef VipsHistogramClass VipsHistEqualClass; + +G_DEFINE_TYPE( VipsHistEqual, vips_hist_equal, VIPS_TYPE_HISTOGRAM ); + +static int +vips_hist_equal_build( VipsObject *object ) +{ + VipsHistogram *histogram = VIPS_HISTOGRAM( object ); + VipsHistEqual *hist_equal = (VipsHistEqual *) histogram; + VipsImage **t = (VipsImage **) vips_object_local_array( object, 4 ); + + if( VIPS_OBJECT_CLASS( vips_hist_equal_parent_class )->build( object ) ) + return( -1 ); + + if( vips_hist_find( histogram->in, &t[0], + "band", hist_equal->which, + NULL ) || + vips_hist_cum( t[0], &t[1], NULL ) || + vips_hist_norm( t[1], &t[2], NULL ) || + vips_maplut( histogram->in, &t[3], t[2], NULL ) || + vips_image_write( t[3], histogram->out ) ) + return( -1 ); + + return( 0 ); +} + +static void +vips_hist_equal_class_init( VipsHistEqualClass *class ) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS( class ); + VipsObjectClass *object_class = (VipsObjectClass *) class; + + gobject_class->set_property = vips_object_set_property; + gobject_class->get_property = vips_object_get_property; + + object_class->nickname = "hist_equal"; + object_class->description = _( "histogram equalisation" ); + object_class->build = vips_hist_equal_build; + + VIPS_ARG_INT( class, "band", 110, + _( "Band" ), + _( "Equalise with this band" ), + VIPS_ARGUMENT_OPTIONAL_INPUT, + G_STRUCT_OFFSET( VipsHistEqual, which ), + -1, 100000, -1 ); +} + +static void +vips_hist_equal_init( VipsHistEqual *hist_equal ) +{ + hist_equal->which = -1; +} + +/** + * vips_hist_equal: + * @in: input image + * @out: output image + * + * Optional arguments: + * + * @band: band to equalise + * + * Histogram-equalise @in. Equalise using band @bandno, or if @bandno is -1, + * equalise bands independently. + * + * See also: + * + * Returns: 0 on success, -1 on error + */ +int +vips_hist_equal( VipsImage *in, VipsImage **out, ... ) +{ + va_list ap; + int result; + + va_start( ap, out ); + result = vips_call_split( "hist_equal", ap, in, out ); + va_end( ap ); + + return( result ); +} diff --git a/libvips/histogram/hist_norm.c b/libvips/histogram/hist_norm.c new file mode 100644 index 00000000..ac6e6177 --- /dev/null +++ b/libvips/histogram/hist_norm.c @@ -0,0 +1,159 @@ +/* histogram normalisation + * + * Author: N. Dessipris + * Written on: 02/08/1990 + * 24/5/95 JC + * - tidied up and ANSIfied + * 20/7/95 JC + * - smartened up again + * - now works for hists >256 elements + * 3/3/01 JC + * - broken into norm and norm ... helps im_histspec() + * - better behaviour for >8 bit hists + * 31/10/05 JC + * - was broken for vertical histograms, gah + * - neater im_histnorm() + * 23/7/07 + * - eek, off by 1 for more than 1 band hists + * 12/5/08 + * - histnorm works for signed hists now as well + * 24/3/10 + * - gtkdoc + * - small cleanups + * 12/8/13 + * - redone im_histnorm() as a class, vips_hist_norm() + */ + +/* + + This file is part of VIPS. + + VIPS is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301 USA + + */ + +/* + + These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk + + */ + +#ifdef HAVE_CONFIG_H +#include +#endif /*HAVE_CONFIG_H*/ +#include + +#include + +#include + +#include "phistogram.h" + +typedef VipsHistogram VipsHistNorm; +typedef VipsHistogramClass VipsHistNormClass; + +G_DEFINE_TYPE( VipsHistNorm, vips_hist_norm, VIPS_TYPE_HISTOGRAM ); + +static int +vips_hist_norm_build( VipsObject *object ) +{ + VipsHistogram *histogram = VIPS_HISTOGRAM( object ); + VipsImage **t = (VipsImage **) vips_object_local_array( object, 3 ); + + guint64 px; + int bands; + double *a, *b; + int y; + VipsBandFormat fmt; + + if( VIPS_OBJECT_CLASS( vips_hist_norm_parent_class )->build( object ) ) + return( -1 ); + + /* Need max for each channel. + */ + if( vips_stats( histogram->in, &t[0], NULL ) ) + return( -1 ); + + /* Scale each channel by px / channel max + */ + px = VIPS_IMAGE_N_PELS( histogram->in ); + bands = histogram->in->Bands; + if( !(a = VIPS_ARRAY( object, bands, double )) || + !(b = VIPS_ARRAY( object, bands, double )) ) + return( -1 ); + for( y = 0; y < bands; y++ ) { + a[y] = px / *VIPS_MATRIX( t[0], 1, y + 1 ); + b[y] = 0; + } + + if( vips_linear( histogram->in, &t[1], a, b, bands, NULL ) ) + return( -1 ); + + /* Make output format as small as we can. + */ + if( px <= 256 ) + fmt = VIPS_FORMAT_UCHAR; + else if( px <= 65536 ) + fmt = VIPS_FORMAT_USHORT; + else + fmt = VIPS_FORMAT_UINT; + + if( vips_cast( t[1], &t[2], fmt, NULL ) || + vips_image_write( t[2], histogram->out ) ) + return( -1 ); + + return( 0 ); +} + +static void +vips_hist_norm_class_init( VipsHistNormClass *class ) +{ + VipsObjectClass *object_class = (VipsObjectClass *) class; + + object_class->nickname = "hist_norm"; + object_class->description = _( "normalise histogram" ); + object_class->build = vips_hist_norm_build; +} + +static void +vips_hist_norm_init( VipsHistNorm *hist_norm ) +{ +} + +/** + * vips_hist_norm: + * @in: input image + * @out: output image + * + * Normalise histogram ... normalise range to make it square (ie. max == + * number of elements). Normalise each band separately. + * + * See also: vips_hist_cum(). + * + * Returns: 0 on success, -1 on error + */ +int +vips_hist_norm( VipsImage *in, VipsImage **out, ... ) +{ + va_list ap; + int result; + + va_start( ap, out ); + result = vips_call_split( "hist_norm", ap, in, out ); + va_end( ap ); + + return( result ); +} diff --git a/libvips/histogram/histogram.c b/libvips/histogram/histogram.c index e137848a..c8408271 100644 --- a/libvips/histogram/histogram.c +++ b/libvips/histogram/histogram.c @@ -1,7 +1,8 @@ /* base class for all histogram operations * * properties: - * - single output image + * - one input image + * - one output image */ /* @@ -78,7 +79,6 @@ G_DEFINE_ABSTRACT_TYPE( VipsHistogram, vips_histogram, VIPS_TYPE_OPERATION ); static int vips_histogram_build( VipsObject *object ) { - VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( object ); VipsHistogram *histogram = VIPS_HISTOGRAM( object ); #ifdef DEBUG @@ -87,13 +87,10 @@ 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 ) ) - return( -1 ); + g_object_set( histogram, "out", vips_image_new(), NULL ); return( 0 ); } @@ -137,6 +134,12 @@ void vips_histogram_operation_init( void ) { extern GType vips_maplut_get_type( void ); + extern GType vips_hist_cum_get_type( void ); + extern GType vips_hist_norm_get_type( void ); + extern GType vips_hist_equal_get_type( void ); vips_maplut_get_type(); + vips_hist_cum_get_type(); + vips_hist_norm_get_type(); + vips_hist_equal_get_type(); } diff --git a/libvips/histogram/im_heq.c b/libvips/histogram/im_heq.c deleted file mode 100644 index 6d985a17..00000000 --- a/libvips/histogram/im_heq.c +++ /dev/null @@ -1,79 +0,0 @@ -/* Histogram-equalise an image. - * - * Copyright: 1991, N. Dessipris. - * - * Author: Nicos Dessipris - * Written on: 27/03/1991 - * Modified on : - * 16/6/93 J.Cupitt - * - im_ioflag() changed to im_iocheck() - * 24/5/95 JC - * - ANSIfied and tidied up - * 3/3/01 JC - * - more cleanup - * 23/3/10 - * - gtkdoc - */ - -/* - - This file is part of VIPS. - - VIPS is free software; you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA - - */ - -/* - - These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk - - */ - -#ifdef HAVE_CONFIG_H -#include -#endif /*HAVE_CONFIG_H*/ -#include - -#include - -#include - -/** - * im_heq: - * @in: input image - * @out: output image - * @bandno: band to equalise - * - * Histogram-equalise @in. Equalise using band @bandno, or if @bandno is -1, - * equalise all bands. - * - * See also: im_lhisteq(), im_histgr(), im_histeq(). - * - * Returns: 0 on success, -1 on error - */ -int -im_heq( IMAGE *in, IMAGE *out, int bandno ) -{ - IMAGE *t[2]; - - if( im_open_local_array( out, t, 2, "im_heq", "p" ) || - im_histgr( in, t[0], bandno ) || - im_histeq( t[0], t[1] ) || - im_maplut( in, out, t[1] ) ) - return( -1 ); - - return( 0 ); -} diff --git a/libvips/histogram/im_histeq.c b/libvips/histogram/im_histeq.c deleted file mode 100644 index 1ee1d36c..00000000 --- a/libvips/histogram/im_histeq.c +++ /dev/null @@ -1,229 +0,0 @@ -/* histogram normalisation and cumulativisation - * - * Author: N. Dessipris - * Written on: 02/08/1990 - * 24/5/95 JC - * - tidied up and ANSIfied - * 20/7/95 JC - * - smartened up again - * - now works for hists >256 elements - * 3/3/01 JC - * - broken into cum and norm ... helps im_histspec() - * - better behaviour for >8 bit hists - * 31/10/05 JC - * - was broken for vertical histograms, gah - * - neater im_histnorm() - * 23/7/07 - * - eek, off by 1 for more than 1 band hists - * 12/5/08 - * - histcum works for signed hists now as well - * 24/3/10 - * - gtkdoc - * - small cleanups - */ - -/* - - This file is part of VIPS. - - VIPS is free software; you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA - - */ - -/* - - These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk - - */ - -#ifdef HAVE_CONFIG_H -#include -#endif /*HAVE_CONFIG_H*/ -#include - -#include - -#include - -#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 - * @out: output image - * - * Normalise histogram ... normalise range to make it square (ie. max == - * number of elements). Normalise each band separately. - * - * See also: im_histcum(). - * - * Returns: 0 on success, -1 on error - */ -int -im_histnorm( IMAGE *in, IMAGE *out ) -{ - const guint64 px = VIPS_IMAGE_N_PELS( in ); - DOUBLEMASK *stats; - double *a, *b; - int y; - IMAGE *t1; - int fmt; - - /* Need max for each channel. - */ - if( !(a = IM_ARRAY( out, in->Bands, double )) || - !(b = IM_ARRAY( out, in->Bands, double )) || - !(stats = im_stats( in )) ) - return( -1 ); - - /* Scale each channel by px / channel max - */ - for( y = 0; y < in->Bands; y++ ) { - a[y] = px / VIPS_MASK( stats, 1, y + 1 ); - b[y] = 0; - } - - im_free_dmask( stats ); - - if( !(t1 = im_open_local( out, "im_histnorm:2", "p" )) || - im_lintra_vec( in->Bands, a, in, b, t1 ) ) - return( -1 ); - - /* Make output format as small as we can. - */ - if( px <= 256 ) - fmt = IM_BANDFMT_UCHAR; - else if( px <= 65536 ) - fmt = IM_BANDFMT_USHORT; - else - fmt = IM_BANDFMT_UINT; - - if( im_clip2fmt( t1, out, fmt ) ) - return( -1 ); - - return( 0 ); -} - -/** - * im_histeq: - * @in: input image - * @out: output image - * - * Histogram equalisation: normalised cumulative histogram. - * - * See also: im_heq(). - * - * Returns: 0 on success, -1 on error - */ -int -im_histeq( IMAGE *in, IMAGE *out ) -{ - IMAGE *t1; - - /* Normalised cumulative. - */ - if( !(t1 = im_open_local( out, "im_histeq", "p" )) || - im_histcum( in, t1 ) || - im_histnorm( t1, out ) ) - return( -1 ); - - return( 0 ); -} diff --git a/libvips/histogram/maplut.c b/libvips/histogram/maplut.c index f4ee5c31..56f0ced8 100644 --- a/libvips/histogram/maplut.c +++ b/libvips/histogram/maplut.c @@ -71,11 +71,11 @@ #include -typedef struct _VipsMaplut { - VipsOperation parent_instance; +#include "phistogram.h" + +typedef struct _VipsMaplut { + VipsHistogram parent_instance; - VipsImage *in; - VipsImage *out; VipsImage *lut; int fmt; /* LUT image BandFmt */ @@ -88,9 +88,9 @@ typedef struct _VipsMaplut { } VipsMaplut; -typedef VipsOperationClass VipsMaplutClass; +typedef VipsHistogramClass VipsMaplutClass; -G_DEFINE_TYPE( VipsMaplut, vips_maplut, VIPS_TYPE_OPERATION ); +G_DEFINE_TYPE( VipsMaplut, vips_maplut, VIPS_TYPE_HISTOGRAM ); static void vips_maplut_preeval( VipsImage *image, VipsProgress *progress, @@ -142,13 +142,13 @@ vips_maplut_start( VipsImage *out, void *a, void *b ) /* Map through n non-complex luts. */ #define loop( OUT ) { \ - int b = st->nb; \ + int b = maplut->nb; \ \ for( y = to; y < bo; y++ ) { \ for( z = 0; z < b; z++ ) { \ VipsPel *p = VIPS_REGION_ADDR( ir, le, y ); \ OUT *q = (OUT *) VIPS_REGION_ADDR( or, le, y ); \ - OUT *tlut = (OUT *) st->table[z]; \ + OUT *tlut = (OUT *) maplut->table[z]; \ \ for( x = z; x < ne; x += b ) \ q[x] = tlut[p[x]]; \ @@ -165,7 +165,7 @@ vips_maplut_start( VipsImage *out, void *a, void *b ) for( z = 0; z < b; z++ ) { \ VipsPel *p = VIPS_REGION_ADDR( ir, le, y ) + z; \ OUT *q = (OUT *) VIPS_REGION_ADDR( or, le, y ) + z * 2; \ - OUT *tlut = (OUT *) st->table[z]; \ + OUT *tlut = (OUT *) maplut->table[z]; \ \ for( x = 0; x < ne; x += b ) { \ int n = p[x] * 2; \ @@ -179,19 +179,19 @@ vips_maplut_start( VipsImage *out, void *a, void *b ) } #define loopg( IN, OUT ) { \ - int b = st->nb; \ + int b = maplut->nb; \ \ for( y = to; y < bo; y++ ) { \ for( z = 0; z < b; z++ ) { \ IN *p = (IN *) VIPS_REGION_ADDR( ir, le, y ); \ OUT *q = (OUT *) VIPS_REGION_ADDR( or, le, y ); \ - OUT *tlut = (OUT *) st->table[z]; \ + OUT *tlut = (OUT *) maplut->table[z]; \ \ for( x = z; x < ne; x += b ) { \ int index = p[x]; \ \ - if( index > st->clp ) { \ - index = st->clp; \ + if( index > maplut->clp ) { \ + index = maplut->clp; \ seq->overflow++; \ } \ \ @@ -208,13 +208,13 @@ vips_maplut_start( VipsImage *out, void *a, void *b ) for( z = 0; z < b; z++ ) { \ IN *p = (IN *) VIPS_REGION_ADDR( ir, le, y ) + z; \ OUT *q = (OUT *) VIPS_REGION_ADDR( or, le, y ) + z * 2; \ - OUT *tlut = (OUT *) st->table[z]; \ + OUT *tlut = (OUT *) maplut->table[z]; \ \ for( x = 0; x < ne; x += b ) { \ int index = p[x]; \ \ - if( index > st->clp ) { \ - index = st->clp; \ + if( index > maplut->clp ) { \ + index = maplut->clp; \ seq->overflow++; \ } \ \ @@ -230,7 +230,7 @@ vips_maplut_start( VipsImage *out, void *a, void *b ) /* Map image through one non-complex lut. */ #define loop1( OUT ) { \ - OUT *tlut = (OUT *) st->table[0]; \ + OUT *tlut = (OUT *) maplut->table[0]; \ \ for( y = to; y < bo; y++ ) { \ OUT *q = (OUT *) VIPS_REGION_ADDR( or, le, y ); \ @@ -244,7 +244,7 @@ vips_maplut_start( VipsImage *out, void *a, void *b ) /* Map image through one complex lut. */ #define loop1c( OUT ) { \ - OUT *tlut = (OUT *) st->table[0]; \ + OUT *tlut = (OUT *) maplut->table[0]; \ \ for( y = to; y < bo; y++ ) { \ OUT *q = (OUT *) VIPS_REGION_ADDR( or, le, y ); \ @@ -264,7 +264,7 @@ vips_maplut_start( VipsImage *out, void *a, void *b ) * index the lut carefully, and record the number of overflows we detect. */ #define loop1g( IN, OUT ) { \ - OUT *tlut = (OUT *) st->table[0]; \ + OUT *tlut = (OUT *) maplut->table[0]; \ \ for( y = to; y < bo; y++ ) { \ OUT *q = (OUT *) VIPS_REGION_ADDR( or, le, y ); \ @@ -273,8 +273,8 @@ vips_maplut_start( VipsImage *out, void *a, void *b ) for( x = 0; x < ne; x++ ) { \ int index = p[x]; \ \ - if( index > st->clp ) { \ - index = st->clp; \ + if( index > maplut->clp ) { \ + index = maplut->clp; \ seq->overflow++; \ } \ \ @@ -284,7 +284,7 @@ vips_maplut_start( VipsImage *out, void *a, void *b ) } #define loop1cg( IN, OUT ) { \ - OUT *tlut = (OUT *) st->table[0]; \ + OUT *tlut = (OUT *) maplut->table[0]; \ \ for( y = to; y < bo; y++ ) { \ OUT *q = (OUT *) VIPS_REGION_ADDR( or, le, y ); \ @@ -293,8 +293,8 @@ vips_maplut_start( VipsImage *out, void *a, void *b ) for( x = 0; x < ne; x++ ) { \ int index = p[x]; \ \ - if( index > st->clp ) { \ - index = st->clp; \ + if( index > maplut->clp ) { \ + index = maplut->clp; \ seq->overflow++; \ } \ \ @@ -308,7 +308,7 @@ vips_maplut_start( VipsImage *out, void *a, void *b ) /* Map 1-band image through a many-band non-complex lut. */ #define loop1m( OUT ) { \ - OUT **tlut = (OUT **) st->table; \ + OUT **tlut = (OUT **) maplut->table; \ \ for( y = to; y < bo; y++ ) { \ OUT *q = (OUT *) VIPS_REGION_ADDR( or, le, y ); \ @@ -317,7 +317,7 @@ vips_maplut_start( VipsImage *out, void *a, void *b ) for( i = 0, x = 0; x < np; x++ ) { \ int n = p[x]; \ \ - for( z = 0; z < st->nb; z++, i++ ) \ + for( z = 0; z < maplut->nb; z++, i++ ) \ q[i] = tlut[z][n]; \ } \ } \ @@ -326,7 +326,7 @@ vips_maplut_start( VipsImage *out, void *a, void *b ) /* Map 1-band image through many-band complex lut. */ #define loop1cm( OUT ) { \ - OUT **tlut = (OUT **) st->table; \ + OUT **tlut = (OUT **) maplut->table; \ \ for( y = to; y < bo; y++ ) { \ OUT *q = (OUT *) VIPS_REGION_ADDR( or, le, y ); \ @@ -335,7 +335,7 @@ vips_maplut_start( VipsImage *out, void *a, void *b ) for( x = 0; x < np; x++ ) { \ int n = p[x] * 2; \ \ - for( z = 0; z < st->nb; z++ ) { \ + for( z = 0; z < maplut->nb; z++ ) { \ q[0] = tlut[z][n]; \ q[1] = tlut[z][n+1]; \ q += 2; \ @@ -347,7 +347,7 @@ vips_maplut_start( VipsImage *out, void *a, void *b ) /* Map 1-band uint or ushort image through a many-band non-complex LUT. */ #define loop1gm( IN, OUT ) { \ - OUT **tlut = (OUT **) st->table; \ + OUT **tlut = (OUT **) maplut->table; \ \ for( y = to; y < bo; y++ ) { \ IN *p = (IN *) VIPS_REGION_ADDR( ir, le, y ); \ @@ -356,12 +356,12 @@ vips_maplut_start( VipsImage *out, void *a, void *b ) for( i = 0, x = 0; x < np; x++ ) { \ int n = p[x]; \ \ - if( n > st->clp ) { \ - n = st->clp; \ + if( n > maplut->clp ) { \ + n = maplut->clp; \ seq->overflow++; \ } \ \ - for( z = 0; z < st->nb; z++, i++ ) \ + for( z = 0; z < maplut->nb; z++, i++ ) \ q[i] = tlut[z][n]; \ } \ } \ @@ -370,7 +370,7 @@ vips_maplut_start( VipsImage *out, void *a, void *b ) /* Map 1-band uint or ushort image through a many-band complex LUT. */ #define loop1cgm( IN, OUT ) { \ - OUT **tlut = (OUT **) st->table; \ + OUT **tlut = (OUT **) maplut->table; \ \ for( y = to; y < bo; y++ ) { \ IN *p = (IN *) VIPS_REGION_ADDR( ir, le, y ); \ @@ -379,12 +379,12 @@ vips_maplut_start( VipsImage *out, void *a, void *b ) for( x = 0; x < np; x++ ) { \ int n = p[x]; \ \ - if( n > st->clp ) { \ - n = st->clp; \ + if( n > maplut->clp ) { \ + n = maplut->clp; \ seq->overflow++; \ } \ \ - for( z = 0; z < st->nb; z++ ) { \ + for( z = 0; z < maplut->nb; z++ ) { \ q[0] = tlut[z][n * 2]; \ q[1] = tlut[z][n * 2 + 1]; \ q += 2; \ @@ -409,7 +409,7 @@ vips_maplut_start( VipsImage *out, void *a, void *b ) * uchar. */ #define outer_switch( UCHAR_F, UCHAR_FC, GEN_F, GEN_FC ) \ - switch( st->fmt ) { \ + switch( maplut->fmt ) { \ case VIPS_FORMAT_UCHAR: inner_switch( UCHAR_F, GEN_F, \ unsigned char ); break; \ case VIPS_FORMAT_CHAR: inner_switch( UCHAR_F, GEN_F, \ @@ -442,32 +442,28 @@ vips_maplut_gen( VipsRegion *or, void *vseq, void *a, void *b, { VipsMaplutSequence *seq = (VipsMaplutSequence *) vseq; VipsImage *in = (VipsImage *) a; - VipsMaplut *st = (VipsMaplut *) b; + VipsMaplut *maplut = (VipsMaplut *) b; VipsRegion *ir = seq->ir; VipsRect *r = &or->valid; int le = r->left; int to = r->top; - int bo = VIPS_RECT_BOTTOM(r); + int bo = VIPS_RECT_BOTTOM( r ); int np = r->width; /* Pels across region */ int ne = VIPS_REGION_N_ELEMENTS( or ); /* Number of elements */ int x, y, z, i; - /* Get input ready. - */ if( vips_region_prepare( ir, r ) ) return( -1 ); - /* Process! - */ - if( st->nb == 1 ) + if( maplut->nb == 1 ) /* One band lut. */ outer_switch( loop1, loop1c, loop1g, loop1cg ) else /* Many band lut. */ - if( ir->im->Bands == 1 ) + if( in->Bands == 1 ) /* ... but 1 band input. */ outer_switch( loop1m, loop1cm, loop1gm, loop1cgm ) @@ -511,6 +507,7 @@ static int vips_maplut_build( VipsObject *object ) { VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( object ); + VipsHistogram *histogram = VIPS_HISTOGRAM( object ); VipsMaplut *maplut = (VipsMaplut *) object; VipsImage **t = (VipsImage **) vips_object_local_array( object, 1 ); @@ -519,12 +516,10 @@ vips_maplut_build( VipsObject *object ) int i, x; VipsPel *q; - g_object_set( maplut, "out", vips_image_new(), NULL ); - if( VIPS_OBJECT_CLASS( vips_maplut_parent_class )->build( object ) ) return( -1 ); - in = maplut->in; + in = histogram->in; lut = maplut->lut; if( vips_check_hist( class->nickname, lut ) || @@ -543,17 +538,17 @@ vips_maplut_build( VipsObject *object ) vips_image_pio_input( in ) ) return( -1 ); - if( vips_image_copy_fieldsv( maplut->out, in, lut, NULL ) ) + if( vips_image_copy_fieldsv( histogram->out, in, lut, NULL ) ) return( -1 ); - vips_demand_hint( maplut->out, VIPS_DEMAND_STYLE_THINSTRIP, + vips_demand_hint( histogram->out, VIPS_DEMAND_STYLE_THINSTRIP, in, lut, NULL ); - maplut->out->BandFmt = lut->BandFmt; + histogram->out->BandFmt = lut->BandFmt; /* Output has same number of bands as LUT, unless LUT has 1 band, in * which case output has same number of bands as input. */ if( lut->Bands != 1 ) - maplut->out->Bands = lut->Bands; + histogram->out->Bands = lut->Bands; g_signal_connect( in, "preeval", G_CALLBACK( vips_maplut_preeval ), maplut ); @@ -588,7 +583,7 @@ vips_maplut_build( VipsObject *object ) q += maplut->es; } - if( vips_image_generate( maplut->out, + if( vips_image_generate( histogram->out, vips_maplut_start, vips_maplut_gen, vips_maplut_stop, in, maplut ) ) return( -1 ); @@ -600,30 +595,18 @@ static void vips_maplut_class_init( VipsMaplutClass *class ) { GObjectClass *gobject_class = G_OBJECT_CLASS( class ); - VipsObjectClass *vobject_class = VIPS_OBJECT_CLASS( class ); + VipsObjectClass *object_class = VIPS_OBJECT_CLASS( class ); VipsOperationClass *operation_class = VIPS_OPERATION_CLASS( class ); gobject_class->set_property = vips_object_set_property; gobject_class->get_property = vips_object_get_property; - vobject_class->nickname = "maplut"; - vobject_class->description = _( "map an image though a lut" ); - vobject_class->build = vips_maplut_build; + object_class->nickname = "maplut"; + object_class->description = _( "map an image though a lut" ); + object_class->build = vips_maplut_build; operation_class->flags = VIPS_OPERATION_SEQUENTIAL; - VIPS_ARG_IMAGE( class, "in", 0, - _( "Input" ), - _( "Input image" ), - VIPS_ARGUMENT_REQUIRED_INPUT, - G_STRUCT_OFFSET( VipsMaplut, in ) ); - - VIPS_ARG_IMAGE( class, "out", 1, - _( "Output" ), - _( "Output image" ), - VIPS_ARGUMENT_REQUIRED_OUTPUT, - G_STRUCT_OFFSET( VipsMaplut, out ) ); - VIPS_ARG_IMAGE( class, "lut", 2, _( "LUT" ), _( "Look-up table image" ), diff --git a/libvips/histogram/phistogram.h b/libvips/histogram/phistogram.h index c82793d4..b623bd85 100644 --- a/libvips/histogram/phistogram.h +++ b/libvips/histogram/phistogram.h @@ -55,8 +55,6 @@ extern "C" { typedef struct _VipsHistogram { VipsOperation parent_instance; - /* @in is checked to be a histogram. - */ VipsImage *in; VipsImage *out; diff --git a/libvips/include/vips/histogram.h b/libvips/include/vips/histogram.h index 07328638..1afe9601 100644 --- a/libvips/include/vips/histogram.h +++ b/libvips/include/vips/histogram.h @@ -40,6 +40,12 @@ extern "C" { int vips_maplut( VipsImage *in, VipsImage **out, VipsImage *lut, ... ) __attribute__((sentinel)); +int vips_hist_cum( VipsImage *in, VipsImage **out, ... ) + __attribute__((sentinel)); +int vips_hist_norm( VipsImage *in, VipsImage **out, ... ) + __attribute__((sentinel)); +int vips_hist_equal( VipsImage *in, VipsImage **out, ... ) + __attribute__((sentinel)); int im_histnD( VipsImage *in, VipsImage *out, int bins ); @@ -48,9 +54,6 @@ int im_hist_indexed( VipsImage *index, VipsImage *value, VipsImage *out ); 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 ); int im_histplot( VipsImage *in, VipsImage *out ); @@ -59,7 +62,6 @@ int im_hsp( VipsImage *in, VipsImage *ref, VipsImage *out ); int im_mpercent( VipsImage *in, double percent, int *out ); int im_mpercent_hist( VipsImage *hist, double percent, int *out ); -int im_heq( VipsImage *in, VipsImage *out, int bandno ); int im_lhisteq( VipsImage *in, VipsImage *out, int xwin, int ywin ); int im_stdif( VipsImage *in, VipsImage *out, double a, double m0, double b, double s0, int xwin, int ywin ); diff --git a/libvips/include/vips/vips7compat.h b/libvips/include/vips/vips7compat.h index c5057c68..1ef87008 100644 --- a/libvips/include/vips/vips7compat.h +++ b/libvips/include/vips/vips7compat.h @@ -852,6 +852,10 @@ 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 ); +int im_histnorm( VipsImage *in, VipsImage *out ); +int im_histeq( VipsImage *in, VipsImage *out ); +int im_heq( VipsImage *in, VipsImage *out, int bandno ); /* ruby-vips uses this */ diff --git a/libvips/iofuncs/image.c b/libvips/iofuncs/image.c index e4d4e62a..20caa021 100644 --- a/libvips/iofuncs/image.c +++ b/libvips/iofuncs/image.c @@ -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 ))) )