1 /* base class for correlation
2  *
3  * 7/11/13
4  * 	- from convolution.c
5  */
6 
7 /*
8 
9     This file is part of VIPS.
10 
11     VIPS is free software; you can redistribute it and/or modify
12     it under the terms of the GNU Lesser General Public License as published by
13     the Free Software Foundation; either version 2 of the License, or
14     (at your option) any later version.
15 
16     This program is distributed in the hope that it will be useful,
17     but WITHOUT ANY WARRANTY; without even the implied warranty of
18     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19     GNU Lesser General Public License for more details.
20 
21     You should have received a copy of the GNU Lesser General Public License
22     along with this program; if not, write to the Free Software
23     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
24     02110-1301  USA
25 
26  */
27 
28 /*
29 
30     These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
31 
32  */
33 
34 #ifdef HAVE_CONFIG_H
35 #include <config.h>
36 #endif /*HAVE_CONFIG_H*/
37 #include <vips/intl.h>
38 
39 #include <stdio.h>
40 #include <math.h>
41 
42 #include <vips/vips.h>
43 #include <vips/internal.h>
44 
45 #include "pconvolution.h"
46 #include "correlation.h"
47 
48 G_DEFINE_ABSTRACT_TYPE( VipsCorrelation, vips_correlation,
49 	VIPS_TYPE_OPERATION );
50 
51 static int
vips_correlation_gen(VipsRegion * or,void * seq,void * a,void * b,gboolean * stop)52 vips_correlation_gen( VipsRegion *or,
53 	void *seq, void *a, void *b, gboolean *stop )
54 {
55 	VipsRegion *ir = (VipsRegion *) seq;
56 	VipsCorrelation *correlation = (VipsCorrelation *) b;
57 	VipsCorrelationClass *cclass =
58 		VIPS_CORRELATION_GET_CLASS( correlation );
59 	VipsRect *r = &or->valid;
60 
61 	VipsRect irect;
62 
63 	/* What part of ir do we need?
64 	 */
65 	irect.left = r->left;
66 	irect.top = r->top;
67 	irect.width = r->width + correlation->ref_ready->Xsize - 1;
68 	irect.height = r->height + correlation->ref_ready->Ysize - 1;
69 
70 	if( vips_region_prepare( ir, &irect ) )
71 		return( -1 );
72 
73 	cclass->correlation( correlation, ir, or );
74 
75 	return( 0 );
76 }
77 
78 static int
vips_correlation_build(VipsObject * object)79 vips_correlation_build( VipsObject *object )
80 {
81 	VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( object );
82 	VipsCorrelationClass *cclass = VIPS_CORRELATION_CLASS( class );
83 	VipsCorrelation *correlation = (VipsCorrelation *) object;
84 	VipsImage **t = (VipsImage **) vips_object_local_array( object, 6 );
85 
86 	if( VIPS_OBJECT_CLASS( vips_correlation_parent_class )->
87 		build( object ) )
88 		return( -1 );
89 
90 	/* Stretch input out.
91 	 */
92 	if( vips_embed( correlation->in, &t[0],
93 		correlation->ref->Xsize / 2, correlation->ref->Ysize / 2,
94 		correlation->in->Xsize + correlation->ref->Xsize - 1,
95 		correlation->in->Ysize + correlation->ref->Ysize - 1,
96 		"extend", VIPS_EXTEND_COPY,
97 		NULL ) )
98 		return( -1 );
99 	if( vips__formatalike( t[0], correlation->ref, &t[1], &t[2] ) ||
100 		vips__bandalike( class->nickname, t[1], t[2], &t[3], &t[4] ) ||
101 		!(t[5] = vips_image_copy_memory( t[4] )) )
102 		return( -1 );
103 
104 	correlation->in_ready = t[3];
105 	correlation->ref_ready = t[5];
106 
107 	g_object_set( object, "out", vips_image_new(), NULL );
108 
109 	/* FATSTRIP is good for us as THINSTRIP will cause
110 	 * too many recalculations on overlaps.
111 	 */
112 	if( vips_image_pipelinev( correlation->out,
113 		VIPS_DEMAND_STYLE_FATSTRIP,
114 		correlation->in_ready, correlation->ref_ready, NULL ) )
115 		return( -1 );
116 	correlation->out->Xsize = correlation->in->Xsize;
117 	correlation->out->Ysize = correlation->in->Ysize;
118 	correlation->out->BandFmt =
119 		cclass->format_table[correlation->in_ready->BandFmt];
120 	if( cclass->pre_generate &&
121 		cclass->pre_generate( correlation ) )
122 		return( -1 );
123 	if( vips_image_generate( correlation->out,
124 		vips_start_one, vips_correlation_gen, vips_stop_one,
125 		correlation->in_ready, correlation ) )
126 		return( -1 );
127 
128 	vips_reorder_margin_hint( correlation->out,
129 		correlation->ref->Xsize * correlation->ref->Ysize );
130 
131 	return( 0 );
132 }
133 
134 static void
vips_correlation_class_init(VipsCorrelationClass * class)135 vips_correlation_class_init( VipsCorrelationClass *class )
136 {
137 	GObjectClass *gobject_class = G_OBJECT_CLASS( class );
138 	VipsObjectClass *object_class = (VipsObjectClass *) class;
139 	VipsOperationClass *operation_class = VIPS_OPERATION_CLASS( class );
140 
141 	gobject_class->set_property = vips_object_set_property;
142 	gobject_class->get_property = vips_object_get_property;
143 
144 	object_class->nickname = "correlation";
145 	object_class->description = _( "correlation operation" );
146 	object_class->build = vips_correlation_build;
147 
148 	operation_class->flags = VIPS_OPERATION_SEQUENTIAL;
149 
150 	VIPS_ARG_IMAGE( class, "in", 0,
151 		_( "Input" ),
152 		_( "Input image argument" ),
153 		VIPS_ARGUMENT_REQUIRED_INPUT,
154 		G_STRUCT_OFFSET( VipsCorrelation, in ) );
155 
156 	VIPS_ARG_IMAGE( class, "ref", 10,
157 		_( "Mask" ),
158 		_( "Input reference image" ),
159 		VIPS_ARGUMENT_REQUIRED_INPUT,
160 		G_STRUCT_OFFSET( VipsCorrelation, ref ) );
161 
162 	VIPS_ARG_IMAGE( class, "out", 20,
163 		_( "Output" ),
164 		_( "Output image" ),
165 		VIPS_ARGUMENT_REQUIRED_OUTPUT,
166 		G_STRUCT_OFFSET( VipsCorrelation, out ) );
167 
168 }
169 
170 static void
vips_correlation_init(VipsCorrelation * correlation)171 vips_correlation_init( VipsCorrelation *correlation )
172 {
173 }
174