1 /* @(#) Generalised addition of two vasari images. Result (double or float)
2 * @(#)depends on inputs
3 * @(#) Function im_gfadd() assumes that the both input files
4 * @(#) are either memory mapped or in a buffer.
5 * @(#) Images must have the same no of bands and can be of any type
6 * @(#) No check for overflow is carried out. If in doubt use im_clip2...
7 * @(#) Result at eachpoint is a*in1 + b*in2 + c
8 * @(#)
9 * @(#) int im_gfadd(a, in1, b, in2, c, out)
10 * @(#) double a, b, c;
11 * @(#) IMAGE *in1, *in2, *out;
12 * @(#)
13 * @(#) Returns 0 on success and -1 on error
14 * @(#)
15 *
16 * Copyright: 1990, N. Dessipris.
17 *
18 * Author: Nicos Dessipris
19 * Written on: 02/05/1990
20 * Modified on:
21 * 15/6/93 J.Cupitt
22 * - externs removed
23 * - casts added to please ANSI C
24 * - includes rationalised
25 */
26
27 /*
28
29 This file is part of VIPS.
30
31 VIPS is free software; you can redistribute it and/or modify
32 it under the terms of the GNU Lesser General Public License as published by
33 the Free Software Foundation; either version 2 of the License, or
34 (at your option) any later version.
35
36 This program is distributed in the hope that it will be useful,
37 but WITHOUT ANY WARRANTY; without even the implied warranty of
38 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
39 GNU Lesser General Public License for more details.
40
41 You should have received a copy of the GNU Lesser General Public License
42 along with this program; if not, write to the Free Software
43 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
44 02110-1301 USA
45
46 */
47
48 /*
49
50 These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
51
52 */
53
54 #ifdef HAVE_CONFIG_H
55 #include <config.h>
56 #endif /*HAVE_CONFIG_H*/
57 #include <vips/intl.h>
58
59 #include <stdio.h>
60 #include <stdlib.h>
61 #include <math.h>
62
63 #include <vips/vips.h>
64 #include <vips/vips7compat.h>
65
66 /* uchar char ushort short uint int float double */
67 static int array[8][8] = {
68 /* uchar */ { 0, 0, 0, 0, 0, 0, 0, 1 },
69 /* char */ { 0, 0, 0, 0, 0, 0, 0, 1 },
70 /* ushort */ { 0, 0, 0, 0, 0, 0, 0, 1 },
71 /* short */ { 0, 0, 0, 0, 0, 0, 0, 1 },
72 /* uint */ { 0, 0, 0, 0, 0, 0, 0, 1 },
73 /* int */ { 0, 0, 0, 0, 0, 0, 0, 1 },
74 /* float */ { 0, 0, 0, 0, 0, 0, 0, 1 },
75 /* double */ { 1, 1, 1, 1, 1, 1, 1, 1 }
76 };
77
78 #define select_outdouble(IN2, OUT)\
79 switch(tmp1->BandFmt) {\
80 case IM_BANDFMT_DOUBLE: loop(double, IN2, OUT); break;\
81 default: im_error("im_gfadd","Wrong tmp1 format(d)");\
82 free( line); return( -1 );\
83 }
84
85 #define outfloat_2uchar(IN2, OUT)\
86 case IM_BANDFMT_UCHAR: loop(unsigned char, IN2, OUT); break;\
87 case IM_BANDFMT_CHAR: loop(signed char, IN2, OUT); break;\
88 case IM_BANDFMT_USHORT: loop(unsigned short, IN2, OUT); break;\
89 case IM_BANDFMT_SHORT: loop(signed short, IN2, OUT); break;\
90 case IM_BANDFMT_UINT: loop(unsigned int, IN2, OUT); break;\
91 case IM_BANDFMT_INT: loop(signed int, IN2, OUT); break;\
92 case IM_BANDFMT_FLOAT: loop(float, IN2, OUT); break;
93
94 #define outfloat_2char(IN2, OUT)\
95 case IM_BANDFMT_CHAR: loop(signed char, IN2, OUT); break;\
96 case IM_BANDFMT_USHORT: loop(unsigned short, IN2, OUT); break;\
97 case IM_BANDFMT_SHORT: loop(signed short, IN2, OUT); break;\
98 case IM_BANDFMT_UINT: loop(unsigned int, IN2, OUT); break;\
99 case IM_BANDFMT_INT: loop(signed int, IN2, OUT); break;\
100 case IM_BANDFMT_FLOAT: loop(float, IN2, OUT); break;
101
102 #define outfloat_2ushort(IN2, OUT)\
103 case IM_BANDFMT_USHORT: loop(unsigned short, IN2, OUT); break;\
104 case IM_BANDFMT_SHORT: loop(signed short, IN2, OUT); break;\
105 case IM_BANDFMT_UINT: loop(unsigned int, IN2, OUT); break;\
106 case IM_BANDFMT_INT: loop(signed int, IN2, OUT); break;\
107 case IM_BANDFMT_FLOAT: loop(float, IN2, OUT); break;
108
109 #define outfloat_2short(IN2, OUT)\
110 case IM_BANDFMT_SHORT: loop(signed short, IN2, OUT); break;\
111 case IM_BANDFMT_UINT: loop(unsigned int, IN2, OUT); break;\
112 case IM_BANDFMT_INT: loop(signed int, IN2, OUT); break;\
113 case IM_BANDFMT_FLOAT: loop(float, IN2, OUT); break;
114
115 #define outfloat_2uint(IN2, OUT)\
116 case IM_BANDFMT_UINT: loop(unsigned int, IN2, OUT); break;\
117 case IM_BANDFMT_INT: loop(signed int, IN2, OUT); break;\
118 case IM_BANDFMT_FLOAT: loop(float, IN2, OUT); break;
119
120 #define outfloat_2int(IN2, OUT)\
121 case IM_BANDFMT_INT: loop(signed int, IN2, OUT); break;\
122 case IM_BANDFMT_FLOAT: loop(float, IN2, OUT); break;
123
124 #define outfloat_2float(IN2, OUT)\
125 case IM_BANDFMT_FLOAT: loop(float, IN2, OUT); break;
126
127 /**
128 * im_gfadd:
129 *
130 * Deprecated.
131 */
im_gfadd(double a,IMAGE * in1,double b,IMAGE * in2,double c,IMAGE * out)132 int im_gfadd(double a, IMAGE *in1, double b, IMAGE *in2, double c, IMAGE *out)
133 {
134 static int fmt[] = { IM_BANDFMT_FLOAT, IM_BANDFMT_DOUBLE };
135 int y, x;
136 int first, second, result;
137 IMAGE *tmp1, *tmp2;
138 PEL *line;
139 int os; /* size of a line of output image */
140
141 /* fd, data filename must have been set before the function is called
142 * Check whether they are set properly */
143 if ((im_iocheck(in1, out) == -1) || (im_iocheck(in2, out) == -1))
144 { im_error("im_gfadd"," im_iocheck failed"); return( -1 ); }
145 /* Checks the arguments entered in in and prepares out */
146 if ( (in1->Xsize != in2->Xsize) || (in1->Ysize != in2->Ysize) ||
147 (in1->Bands != in2->Bands) || (in1->Coding != in2->Coding) )
148 { im_error("im_gfadd"," Input images differ"); return( -1 );}
149 if (in1->Coding != IM_CODING_NONE)
150 { im_error("im_gfadd"," images are coded"); return( -1 ); }
151
152 switch(in1->BandFmt) {
153 case IM_BANDFMT_UCHAR: first = 0; break;
154 case IM_BANDFMT_CHAR: first = 1; break;
155 case IM_BANDFMT_USHORT: first = 2; break;
156 case IM_BANDFMT_SHORT: first = 3; break;
157 case IM_BANDFMT_UINT: first = 4; break;
158 case IM_BANDFMT_INT: first = 5; break;
159 case IM_BANDFMT_FLOAT: first = 6; break;
160 case IM_BANDFMT_DOUBLE: first = 7; break;
161 default: im_error("im_gfadd"," unable to accept image1");
162 return( -1 );
163 }
164 switch(in2->BandFmt) {
165 case IM_BANDFMT_UCHAR: second = 0; break;
166 case IM_BANDFMT_CHAR: second = 1; break;
167 case IM_BANDFMT_USHORT: second = 2; break;
168 case IM_BANDFMT_SHORT: second = 3; break;
169 case IM_BANDFMT_UINT: second = 4; break;
170 case IM_BANDFMT_INT: second = 5; break;
171 case IM_BANDFMT_FLOAT: second = 6; break;
172 case IM_BANDFMT_DOUBLE: second = 7; break;
173 default: im_error("im_gfadd"," unable to accept image2");
174 return( -1 );
175 }
176 /* Define the output */
177 result = array[first][second];
178 /* Prepare output */
179 if ( im_cp_desc(out, in1) == -1)
180 { im_error("im_gfadd"," im_cp_desc failed"); return( -1 ); }
181 out->BandFmt = fmt[result];
182 if( im_setupout(out) == -1)
183 { im_error("im_gfadd"," im_setupout failed"); return( -1 ); }
184
185 /* Order in1 and in2 */
186 if ( first >= second )
187 { tmp1 = in1; tmp2 = in2; }
188 else
189 { tmp1 = in2; tmp2 = in1; }
190
191 /* Define what we do for each band element type. */
192
193 #define loop(IN1, IN2, OUT)\
194 { IN1 *input1 = (IN1 *) tmp1->data;\
195 IN2 *input2 = (IN2 *) tmp2->data;\
196 \
197 for (y=0; y <out->Ysize; y++) {\
198 OUT *cpline = (OUT*)line;\
199 for (x=0; x<os; x++)\
200 *cpline++ = (a*((OUT)*input1++) + \
201 b*((OUT)*input2++) + c);\
202 if (im_writeline(y, out, line) ) {\
203 im_error("im_gfadd"," im_writeline failed");\
204 free( line);\
205 return( -1 );\
206 }\
207 }\
208 }
209
210 os = out->Xsize * out->Bands;
211 line = (PEL *) calloc ( (unsigned)os, sizeof(double) );
212 if (line == NULL)
213 { im_error("im_gfadd"," unable to calloc"); return( -1 ); }
214
215 switch (out->BandFmt) {
216 case IM_BANDFMT_DOUBLE:
217 switch (tmp2->BandFmt) {
218 case IM_BANDFMT_UCHAR:
219 select_outdouble(unsigned char, double);
220 break;
221
222 case IM_BANDFMT_CHAR:
223 select_outdouble(signed char, double);
224 break;
225
226 case IM_BANDFMT_USHORT:
227 select_outdouble(unsigned short, double);
228 break;
229
230 case IM_BANDFMT_SHORT:
231 select_outdouble(signed short, double);
232 break;
233
234 case IM_BANDFMT_UINT:
235 select_outdouble(unsigned int, double);
236 break;
237
238 case IM_BANDFMT_INT:
239 select_outdouble(signed int, double);
240 break;
241
242 case IM_BANDFMT_FLOAT:
243 select_outdouble(float, double);
244 break;
245
246 case IM_BANDFMT_DOUBLE:
247 select_outdouble(double, double);
248 break;
249
250 default:
251 im_error("im_gfadd","Wrong tmp2 format(d)");
252 free( line );
253 return( -1 );
254 }
255
256 break;
257
258 case IM_BANDFMT_FLOAT :
259 switch (tmp2->BandFmt) {
260 case IM_BANDFMT_UCHAR:
261 switch (tmp1->BandFmt) {
262 outfloat_2uchar(unsigned char, float);
263
264 default:
265 im_error("im_gfadd"," Error (a)");
266 free( line );
267 return( -1 );
268 }
269 break;
270
271 case IM_BANDFMT_CHAR:
272 switch (tmp1->BandFmt) {
273 outfloat_2char(signed char, float);
274
275 default:
276 im_error("im_gfadd"," Error (b)");
277 free( line); return( -1 );
278 }
279 break;
280
281 case IM_BANDFMT_USHORT:
282 switch (tmp1->BandFmt) {
283 outfloat_2ushort(unsigned short, float);
284
285 default:
286 im_error("im_gfadd"," Error (c)");
287 free( line); return( -1 );
288 }
289 break;
290
291 case IM_BANDFMT_SHORT:
292 switch (tmp1->BandFmt) {
293 outfloat_2short(signed short, float);
294
295 default:
296 im_error("im_gfadd"," Error (d)");
297 free( line); return( -1 );
298 }
299 break;
300
301 case IM_BANDFMT_UINT:
302 switch (tmp1->BandFmt) {
303 outfloat_2uint(unsigned int, float);
304
305 default:
306 im_error("im_gfadd"," Error (e)");
307 free( line); return( -1 );
308 }
309 break;
310
311 case IM_BANDFMT_INT:
312 switch (tmp1->BandFmt) {
313 outfloat_2int(signed int, float);
314
315 default:
316 im_error("im_gfadd"," Error (f)");
317 free( line );
318 return( -1 );
319 }
320 break;
321
322 case IM_BANDFMT_FLOAT:
323 switch (tmp1->BandFmt) {
324 outfloat_2float(float, float);
325
326 default:
327 im_error("im_gfadd"," Error (g)");
328 free( line );
329 return( -1 );
330 }
331 break;
332
333 default:
334 im_error("im_gfadd"," Wrong tmp2 format(f)");
335 free( line );
336 return( -1 );
337 }
338
339 break;
340
341 default:
342 im_error("im_gfadd"," Impossible output state");
343 free( line );
344 return( -1 );
345 }
346
347 free( line );
348
349 return( 0 );
350 }
351