1 /* Use one mosiaced file to mosaic another set of images.
2 *
3 * 1/11/01 JC
4 * - from global_balance
5 * 25/02/02 JC
6 * - detect size change
7 * 10/4/06
8 * - spot file-not-found
9 * 18/6/20 kleisauke
10 * - convert to vips8
11 */
12
13 /*
14
15 This file is part of VIPS.
16
17 VIPS is free software; you can redistribute it and/or modify
18 it under the terms of the GNU Lesser General Public License as published by
19 the Free Software Foundation; either version 2 of the License, or
20 (at your option) any later version.
21
22 This program is distributed in the hope that it will be useful,
23 but WITHOUT ANY WARRANTY; without even the implied warranty of
24 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 GNU Lesser General Public License for more details.
26
27 You should have received a copy of the GNU Lesser General Public License
28 along with this program; if not, write to the Free Software
29 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
30 02110-1301 USA
31
32 */
33
34 /*
35
36 These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
37
38 */
39
40 /* Define for debug output.
41 #define DEBUG
42 */
43
44 #ifdef HAVE_CONFIG_H
45 #include <config.h>
46 #endif /*HAVE_CONFIG_H*/
47 #include <vips/intl.h>
48
49 #include <stdio.h>
50 #include <stdlib.h>
51 #include <string.h>
52 #include <stdarg.h>
53 #include <math.h>
54
55 #include <vips/vips.h>
56 #include <vips/transform.h>
57
58 #include "pmosaicing.h"
59 #include "global_balance.h"
60
61 typedef struct {
62 VipsOperation parent_instance;
63
64 VipsImage *in;
65 VipsImage *out;
66 char *old_str;
67 char *new_str;
68
69 int new_len;
70 int old_len;
71
72 } VipsRemosaic;
73
74 typedef VipsOperationClass VipsRemosaicClass;
75
76 G_DEFINE_TYPE( VipsRemosaic, vips_remosaic, VIPS_TYPE_OPERATION );
77
78 static VipsImage *
remosaic_fn(JoinNode * node,VipsRemosaic * remosaic)79 remosaic_fn( JoinNode *node, VipsRemosaic *remosaic )
80 {
81 SymbolTable *st = node->st;
82 VipsImage *im = node->im;
83
84 VipsImage *out;
85 char filename[FILENAME_MAX];
86 char *p;
87
88 if( !im ) {
89 vips_error( "vips_remosaic", _( "file \"%s\" not found" ),
90 node->name );
91 return( NULL );
92 }
93
94 /* Remove substring remosaic->old_str from in->filename, replace with
95 * remosaic->new_str.
96 */
97 vips_strncpy( filename, im->filename, FILENAME_MAX );
98 if( (p = vips_strrstr( filename, remosaic->old_str )) ) {
99 int offset = p - &filename[0];
100
101 vips_strncpy( p, remosaic->new_str, FILENAME_MAX - offset );
102 vips_strncpy( p + remosaic->new_len,
103 im->filename + offset + remosaic->old_len,
104 FILENAME_MAX - offset - remosaic->new_len );
105 }
106
107 #ifdef DEBUG
108 printf( "vips_remosaic: filename \"%s\" -> \"%s\"\n",
109 im->filename, filename );
110 #endif /*DEBUG*/
111
112 if( !(out = vips__global_open_image( st, filename )) )
113 return( NULL );
114
115 if( out->Xsize != im->Xsize || out->Ysize != im->Ysize ) {
116 vips_error( "vips_remosaic",
117 _( "substitute image \"%s\" is not "
118 "the same size as \"%s\"" ),
119 filename, im->filename );
120 return( NULL );
121 }
122
123 return( out );
124 }
125
126 static int
vips_remosaic_build(VipsObject * object)127 vips_remosaic_build( VipsObject *object )
128 {
129 VipsRemosaic *remosaic = (VipsRemosaic *) object;
130
131 SymbolTable *st;
132
133 g_object_set( remosaic, "out", vips_image_new(), NULL );
134
135 if( VIPS_OBJECT_CLASS( vips_remosaic_parent_class )->
136 build( object ) )
137 return( -1 );
138
139 if( !(st = vips__build_symtab( remosaic->out, SYM_TAB_SIZE )) ||
140 vips__parse_desc( st, remosaic->in ) )
141 return( -1 );
142
143 remosaic->old_len = strlen( remosaic->old_str );
144 remosaic->new_len = strlen( remosaic->new_str );
145 if( vips__build_mosaic( st, remosaic->out,
146 (transform_fn) remosaic_fn, remosaic ) )
147 return( -1 );
148
149 return( 0 );
150 }
151
152 static void
vips_remosaic_class_init(VipsRemosaicClass * class)153 vips_remosaic_class_init( VipsRemosaicClass *class )
154 {
155 GObjectClass *gobject_class = G_OBJECT_CLASS( class );
156 VipsObjectClass *object_class = (VipsObjectClass *) class;
157
158 gobject_class->set_property = vips_object_set_property;
159 gobject_class->get_property = vips_object_get_property;
160
161 object_class->nickname = "remosaic";
162 object_class->description = _( "rebuild an mosaiced image" );
163 object_class->build = vips_remosaic_build;
164
165 VIPS_ARG_IMAGE( class, "in", 1,
166 _( "Input" ),
167 _( "Input image" ),
168 VIPS_ARGUMENT_REQUIRED_INPUT,
169 G_STRUCT_OFFSET( VipsRemosaic, in ) );
170
171 VIPS_ARG_IMAGE( class, "out", 2,
172 _( "Output" ),
173 _( "Output image" ),
174 VIPS_ARGUMENT_REQUIRED_OUTPUT,
175 G_STRUCT_OFFSET( VipsRemosaic, out ) );
176
177 VIPS_ARG_STRING( class, "old_str", 5,
178 _( "old_str" ),
179 _( "Search for this string" ),
180 VIPS_ARGUMENT_REQUIRED_INPUT,
181 G_STRUCT_OFFSET( VipsRemosaic, old_str ),
182 "" );
183
184 VIPS_ARG_STRING( class, "new_str", 6,
185 _( "new_str" ),
186 _( "And swap for this string" ),
187 VIPS_ARGUMENT_REQUIRED_INPUT,
188 G_STRUCT_OFFSET( VipsRemosaic, new_str ),
189 "" );
190
191 }
192
193 static void
vips_remosaic_init(VipsRemosaic * remosaic)194 vips_remosaic_init( VipsRemosaic *remosaic )
195 {
196 }
197
198 /**
199 * vips_remosaic: (method)
200 * @in: mosaic to rebuild
201 * @out: (out): output image
202 * @old_str: gamma of source images
203 * @new_str: gamma of source images
204 * @...: %NULL-terminated list of optional named arguments
205 *
206 * vips_remosaic() works rather as vips_globalbalance(). It takes apart the
207 * mosaiced image @in and rebuilds it, substituting images.
208 *
209 * Unlike vips_globalbalance(), images are substituted based on their file‐
210 * names. The rightmost occurrence of the string @old_str is swapped
211 * for @new_str, that file is opened, and that image substituted for
212 * the old image.
213 *
214 * It's convenient for multispectral images. You can mosaic one band, then
215 * use that mosaic as a template for mosaicing the others automatically.
216 *
217 * See also: vips_globalbalance().
218 *
219 * Returns: 0 on success, -1 on error
220 */
221 int
vips_remosaic(VipsImage * in,VipsImage ** out,const char * old_str,const char * new_str,...)222 vips_remosaic( VipsImage *in, VipsImage **out,
223 const char *old_str, const char *new_str, ... )
224 {
225 va_list ap;
226 int result;
227
228 va_start( ap, new_str );
229 result = vips_call_split( "remosaic", ap, in, out, old_str, new_str );
230 va_end( ap );
231
232 return( result );
233 }
234