diff --git a/libvips/histogram/Makefile.am b/libvips/histogram/Makefile.am index b3e59043..706dcfed 100644 --- a/libvips/histogram/Makefile.am +++ b/libvips/histogram/Makefile.am @@ -1,10 +1,13 @@ noinst_LTLIBRARIES = libhistogram.la libhistogram_la_SOURCES = \ - maplut.c \ - hist_cum.c \ histogram.c \ phistogram.h \ + maplut.c \ + hist_buffer.c \ + hist_buffer.h \ + hist_cum.c \ + \ hist_dispatch.c \ im_heq.c \ im_histeq.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 aedcb9a5..49d5e0b5 100644 --- a/libvips/histogram/hist_cum.c +++ b/libvips/histogram/hist_cum.c @@ -61,11 +61,12 @@ #include #include "phistogram.h" +#include "hist_buffer.h" -typedef VipsHistogram VipsHistCum; -typedef VipsHistogramClass VipsHistCumClass; +typedef VipsHistBuffer VipsHistCum; +typedef VipsHistBufferClass VipsHistCumClass; -G_DEFINE_TYPE( VipsHistCum, vips_hist_cum, VIPS_TYPE_HISTOGRAM ); +G_DEFINE_TYPE( VipsHistCum, vips_hist_cum, VIPS_TYPE_HIST_BUFFER ); #define ACCUMULATE( ITYPE, OTYPE ) { \ for( b = 0; b < nb; b++ ) { \ @@ -82,9 +83,10 @@ G_DEFINE_TYPE( VipsHistCum, vips_hist_cum, VIPS_TYPE_HISTOGRAM ); } static void -vips_hist_cum_buffer( VipsHistogram *histogram, +vips_hist_cum_buffer( VipsHistBuffer *hist_buffer, VipsPel *out, VipsPel *in, int width ) { + 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; @@ -140,7 +142,7 @@ static void vips_hist_cum_class_init( VipsHistCumClass *class ) { VipsObjectClass *object_class = (VipsObjectClass *) class; - VipsHistogramClass *hclass = VIPS_HISTOGRAM_CLASS( class ); + VipsHistBufferClass *hclass = VIPS_HIST_BUFFER_CLASS( class ); object_class->nickname = "hist_cum"; object_class->description = _( "form cumulative histogram" ); diff --git a/libvips/histogram/hist_norm.c b/libvips/histogram/hist_norm.c new file mode 100644 index 00000000..f1724fda --- /dev/null +++ b/libvips/histogram/hist_norm.c @@ -0,0 +1,179 @@ +/* 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 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 + * 12/8/13 + * - redone im_histcum() as a class, vips_hist_cum() + */ + +/* + + 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 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; \ + OTYPE *q = (OTYPE *) out; \ + OTYPE total; \ + \ + total = 0; \ + for( x = b; x < mx; x += nb ) { \ + total += p[x]; \ + q[x] = total; \ + } \ + } \ +} + +static void +vips_hist_cum_buffer( VipsHistogram *histogram, + VipsPel *out, VipsPel *in, int width ) +{ + 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; + + int x, b; + + switch( vips_image_get_format( histogram->in ) ) { + case VIPS_FORMAT_CHAR: + ACCUMULATE( signed char, signed int ); break; + case VIPS_FORMAT_UCHAR: + ACCUMULATE( unsigned char, unsigned int ); break; + case VIPS_FORMAT_SHORT: + ACCUMULATE( signed short, signed int ); break; + case VIPS_FORMAT_USHORT: + ACCUMULATE( unsigned short, unsigned int ); break; + case VIPS_FORMAT_INT: + ACCUMULATE( signed int, signed int ); break; + case VIPS_FORMAT_UINT: + ACCUMULATE( unsigned int, unsigned int ); break; + + case VIPS_FORMAT_FLOAT: + case VIPS_FORMAT_COMPLEX: + ACCUMULATE( float, float ); break; + case VIPS_FORMAT_DOUBLE: + case VIPS_FORMAT_DPCOMPLEX: + ACCUMULATE( double, double ); break; + + default: + g_assert( 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 ); +} diff --git a/libvips/histogram/histogram.c b/libvips/histogram/histogram.c index 6ada5cd2..ee6cef43 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,11 +79,7 @@ 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 ); - VipsHistogramClass *hclass = VIPS_HISTOGRAM_GET_CLASS( histogram ); - - VipsPel *outbuf; #ifdef DEBUG printf( "vips_histogram_build: " ); @@ -95,31 +92,6 @@ vips_histogram_build( VipsObject *object ) 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 ); } diff --git a/libvips/histogram/maplut.c b/libvips/histogram/maplut.c index 63f1b848..afc260c1 100644 --- a/libvips/histogram/maplut.c +++ b/libvips/histogram/maplut.c @@ -74,10 +74,8 @@ #include "phistogram.h" typedef struct _VipsMaplut { - VipsOperation parent_instance; + VipsHistogram parent_instance; - VipsImage *in; - VipsImage *out; VipsImage *lut; int fmt; /* LUT image BandFmt */ @@ -90,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, @@ -144,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]]; \ @@ -167,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; \ @@ -181,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++; \ } \ \ @@ -210,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++; \ } \ \ @@ -232,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 ); \ @@ -246,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 ); \ @@ -266,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 ); \ @@ -275,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++; \ } \ \ @@ -286,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 ); \ @@ -295,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++; \ } \ \ @@ -310,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 ); \ @@ -319,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]; \ } \ } \ @@ -328,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 ); \ @@ -337,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; \ @@ -349,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 ); \ @@ -358,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]; \ } \ } \ @@ -372,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 ); \ @@ -381,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; \ @@ -411,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, \ @@ -444,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 ) @@ -513,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 ); @@ -521,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 ) || @@ -545,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 ); @@ -590,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 ); @@ -614,18 +607,6 @@ vips_maplut_class_init( VipsMaplutClass *class ) operation_class->flags = VIPS_OPERATION_SEQUENTIAL; - VIPS_ARG_IMAGE( class, "in", 0, - _( "Input" ), - _( "Input image" ), - VIPS_ARGUMENT_REQUIRED_INPUT, - G_STRUCT_OFFSET( VipsHistogram, in ) ); - - VIPS_ARG_IMAGE( class, "out", 1, - _( "Output" ), - _( "Output image" ), - VIPS_ARGUMENT_REQUIRED_OUTPUT, - G_STRUCT_OFFSET( VipsHistogram, 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 bc5f2e46..b623bd85 100644 --- a/libvips/histogram/phistogram.h +++ b/libvips/histogram/phistogram.h @@ -52,15 +52,9 @@ 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; - /* @in is checked to be a histogram. - */ VipsImage *in; VipsImage *out; @@ -70,11 +64,6 @@ 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 );