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