1 /* base class for all histogram operations
2  */
3 
4 /*
5 
6     Copyright (C) 1991-2005 The National Gallery
7 
8     This library is free software; you can redistribute it and/or
9     modify it under the terms of the GNU Lesser General Public
10     License as published by the Free Software Foundation; either
11     version 2.1 of the License, or (at your option) any later version.
12 
13     This library is distributed in the hope that it will be useful,
14     but WITHOUT ANY WARRANTY; without even the implied warranty of
15     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16     Lesser General Public License for more details.
17 
18     You should have received a copy of the GNU Lesser General Public
19     License along with this library; if not, write to the Free Software
20     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21     02110-1301  USA
22 
23  */
24 
25 /*
26 
27     These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
28 
29  */
30 
31 /*
32 #define DEBUG
33  */
34 
35 #ifdef HAVE_CONFIG_H
36 #include <config.h>
37 #endif /*HAVE_CONFIG_H*/
38 #include <vips/intl.h>
39 
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <math.h>
43 
44 #include <vips/vips.h>
45 #include <vips/internal.h>
46 
47 #include "phistogram.h"
48 
49 /**
50  * SECTION: histogram
51  * @short_description: find, manipulate and apply histograms and lookup tables
52  * @stability: Stable
53  * @see_also: <link linkend="VipsImage">image</link>
54  * <link linkend="libvips-arithmetic">arithmetic</link>
55  * <link linkend="libvips-create">create</link>
56  * @include: vips/vips.h
57  *
58  * Histograms and look-up tables are 1xn or nx1 images, where n is less than
59  * 256 or less than 65536, corresponding to 8- and 16-bit unsigned int images.
60  * They are tagged with a #VipsInterpretation of
61  * #VIPS_INTERPRETATION_HISTOGRAM and usually displayed by user-interfaces
62  * such as nip2 as plots rather than images.
63  *
64  * These functions can be broadly grouped as things to find or build
65  * histograms (vips_hist_find(), vips_hist_find_indexed(),
66  * vips_hist_find_ndim(), vips_buildlut(), vips_identity()),
67  * operations that
68  * manipulate histograms in some way (vips_hist_cum(), vips_hist_norm()),
69  * operations to apply histograms (vips_maplut()), and a variety of utility
70  * operations.
71  *
72  * A final group of operations build tone curves. These are useful in
73  * pre-press work for adjusting the appearance of images. They are designed
74  * for CIELAB images, but might be useful elsewhere.
75  */
76 
77 G_DEFINE_ABSTRACT_TYPE( VipsHistogram, vips_histogram, VIPS_TYPE_OPERATION );
78 
79 /* sizealike by expanding in just one dimension and copying the final element.
80  */
81 static int
vips__hist_sizealike_vec(VipsImage ** in,VipsImage ** out,int n)82 vips__hist_sizealike_vec( VipsImage **in, VipsImage **out, int n )
83 {
84 	int i;
85 	int max_size;
86 
87 	g_assert( n >= 1 );
88 
89 	max_size = VIPS_MAX( in[0]->Xsize, in[0]->Ysize );
90 	for( i = 1; i < n; i++ )
91 		max_size = VIPS_MAX( max_size,
92 			VIPS_MAX( in[0]->Xsize, in[0]->Ysize ) );
93 
94 	for( i = 0; i < n; i++ )
95 		if( in[i]->Ysize == 1 ) {
96 			if( vips_embed( in[i], &out[i], 0, 0, max_size, 1,
97 				"extend", VIPS_EXTEND_COPY,
98 				NULL ) )
99 				return( -1 );
100 		}
101 		else {
102 			if( vips_embed( in[i], &out[i], 0, 0, 1, max_size,
103 				"extend", VIPS_EXTEND_COPY,
104 				NULL ) )
105 				return( -1 );
106 		}
107 
108 	return( 0 );
109 }
110 
111 static int
vips_histogram_build(VipsObject * object)112 vips_histogram_build( VipsObject *object )
113 {
114 	VipsHistogram *histogram = VIPS_HISTOGRAM( object );
115 	VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( object );
116 	VipsHistogramClass *hclass = VIPS_HISTOGRAM_GET_CLASS( histogram );
117 
118 	VipsImage **decode;
119 	VipsImage **format;
120 	VipsImage **band;
121 	VipsImage **size;
122 	VipsImage **memory;
123 
124 	VipsPel *outbuf;
125 	VipsPel **inbuf;
126 	int i;
127 
128 #ifdef DEBUG
129 	printf( "vips_histogram_build: " );
130 	vips_object_print_name( object );
131 	printf( "\n" );
132 #endif /*DEBUG*/
133 
134 	if( VIPS_OBJECT_CLASS( vips_histogram_parent_class )->build( object ) )
135 		return( -1 );
136 
137 	g_assert( histogram->n > 0 );
138 
139 	/* Must be NULL-terminated.
140 	 */
141 	g_assert( !histogram->in[histogram->n] );
142 
143 	decode = (VipsImage **) vips_object_local_array( object, histogram->n );
144 	format = (VipsImage **) vips_object_local_array( object, histogram->n );
145 	band = (VipsImage **) vips_object_local_array( object, histogram->n );
146 	size = (VipsImage **) vips_object_local_array( object, histogram->n );
147 	memory = (VipsImage **) vips_object_local_array( object, histogram->n );
148 
149 	g_object_set( histogram, "out", vips_image_new(), NULL );
150 
151 	for( i = 0; i < histogram->n; i++ )
152 		if( vips_image_decode( histogram->in[i], &decode[i] ) ||
153 			vips_check_hist( class->nickname, decode[i] ) )
154 			return( -1 );
155 
156 	/* Cast our input images up to a common format, bands and size. If
157 	 * input_format is set, cast to a fixed input type.
158 	 */
159 	if( hclass->input_format != VIPS_FORMAT_NOTSET ) {
160 		for( i = 0; i < histogram->n; i++ )
161 			if( vips_cast( decode[i], &format[i],
162 				hclass->input_format, NULL ) )
163 				return( -1 );
164 	}
165 	else {
166 		if( vips__formatalike_vec( decode, format, histogram->n ) )
167 			return( -1 );
168 	}
169 
170 	if( vips__bandalike_vec( class->nickname,
171 		format, band, histogram->n, 1 ) ||
172 		vips__hist_sizealike_vec( band, size, histogram->n ) )
173 		return( -1 );
174 
175 	if( vips_image_pipeline_array( histogram->out,
176 		VIPS_DEMAND_STYLE_THINSTRIP, size ) )
177 		return( -1 );
178 
179 	/* Need a copy of the inputs in memory.
180 	 */
181 	if( !(inbuf = VIPS_ARRAY( object, histogram->n + 1, VipsPel * )) )
182                 return( -1 );
183 	for( i = 0; i < histogram->n; i++ ) {
184 		if( !(memory[i] = vips_image_copy_memory( size[i] )) )
185 			return( -1 );
186 		inbuf[i] = VIPS_IMAGE_ADDR( memory[i], 0, 0 );
187 	}
188 	inbuf[i] = NULL;
189 
190 	/* Keep a copy of the memory images here for subclasses.
191 	 */
192 	histogram->ready = memory;
193 
194 	histogram->out->Xsize = VIPS_IMAGE_N_PELS( histogram->ready[0] );
195 	histogram->out->Ysize = 1;
196 	if( hclass->format_table )
197 		histogram->out->BandFmt =
198 			hclass->format_table[histogram->ready[0]->BandFmt];
199 	histogram->out->Type = VIPS_INTERPRETATION_HISTOGRAM;
200 
201 	if( !(outbuf = vips_malloc( object,
202 		VIPS_IMAGE_SIZEOF_LINE( histogram->out ))) )
203                 return( -1 );
204 
205 	hclass->process( histogram, outbuf, inbuf, histogram->ready[0]->Xsize );
206 
207 	if( vips_image_write_line( histogram->out, 0, outbuf ) )
208 		return( -1 );
209 
210 	return( 0 );
211 }
212 
213 static void
vips_histogram_class_init(VipsHistogramClass * class)214 vips_histogram_class_init( VipsHistogramClass *class )
215 {
216 	GObjectClass *gobject_class = G_OBJECT_CLASS( class );
217 	VipsObjectClass *vobject_class = VIPS_OBJECT_CLASS( class );
218 
219 	gobject_class->set_property = vips_object_set_property;
220 	gobject_class->get_property = vips_object_get_property;
221 
222 	vobject_class->nickname = "histogram";
223 	vobject_class->description = _( "histogram operations" );
224 	vobject_class->build = vips_histogram_build;
225 
226 	class->input_format = VIPS_FORMAT_NOTSET;
227 
228 	/* Inputs set by subclassess.
229 	 */
230 
231 	VIPS_ARG_IMAGE( class, "out", 10,
232 		_( "Output" ),
233 		_( "Output image" ),
234 		VIPS_ARGUMENT_REQUIRED_OUTPUT,
235 		G_STRUCT_OFFSET( VipsHistogram, out ) );
236 
237 }
238 
239 static void
vips_histogram_init(VipsHistogram * histogram)240 vips_histogram_init( VipsHistogram *histogram )
241 {
242 	/* Sanity check this above.
243 	 */
244 	histogram->n = -1;
245 }
246 
247 /* Called from iofuncs to init all operations in this dir. Use a plugin system
248  * instead?
249  */
250 void
vips_histogram_operation_init(void)251 vips_histogram_operation_init( void )
252 {
253 	extern GType vips_maplut_get_type( void );
254 	extern GType vips_case_get_type( void );
255 	extern GType vips_percent_get_type( void );
256 	extern GType vips_hist_cum_get_type( void );
257 	extern GType vips_hist_norm_get_type( void );
258 	extern GType vips_hist_equal_get_type( void );
259 	extern GType vips_hist_plot_get_type( void );
260 	extern GType vips_hist_match_get_type( void );
261 	extern GType vips_hist_local_get_type( void );
262 	extern GType vips_hist_ismonotonic_get_type( void );
263 	extern GType vips_hist_entropy_get_type( void );
264 	extern GType vips_stdif_get_type( void );
265 
266 	vips_maplut_get_type();
267 	vips_case_get_type();
268 	vips_percent_get_type();
269 	vips_stdif_get_type();
270 	vips_hist_cum_get_type();
271 	vips_hist_norm_get_type();
272 	vips_hist_equal_get_type();
273 	vips_hist_plot_get_type();
274 	vips_hist_match_get_type();
275 	vips_hist_local_get_type();
276 	vips_hist_ismonotonic_get_type();
277 	vips_hist_entropy_get_type();
278 }
279