1 #include "filter.h"
2 #include "file.h"
3 
4 static int lastCurTriangle = 0;
5 
getLastCurTriangle()6 int getLastCurTriangle() {
7 	return lastCurTriangle;
8 }
9 
10 // Solve equation
11 // a[0][0] * x[0] + a[0][1] * x[1] = b[0]
12 // a[1][0] * x[0] + a[1][1] * x[1] = b[1]
13 // return 0 if unique solution exists, else -1;
14 
SolveLinearEquation2(double a[2][2],double b[2],double x[2])15 int SolveLinearEquation2( double a[2][2], double b[2], double x[2] )
16 {
17 	double detA = a[0][0] * a[1][1] - a[0][1]*a[1][0];
18 
19 	if( detA == 0.0 )
20 		return -1;
21 
22 	x[0] = (b[0]*a[1][1] - a[0][1]*b[1]) / detA;
23 	x[1] = (b[1]*a[0][0] - a[1][0]*b[0]) / detA;
24 	return 0;
25 }
26 
27 
28 // Check if point x is inside triangle t
29 // if yes, return 0 and set c, so that
30 // x = T0 + c[0]*(T1-T0) + c[1]*(T2-T0)
31 // else return -1/+1
PointInTriangle(double x,double y,PTTriangle * T,double c[2])32 int PointInTriangle( double x, double y, PTTriangle *T, double c[2] )
33 {
34 	double a[2][2],b[2];
35 
36 
37 	a[0][0] = T->v[1].x - T->v[0].x;
38 	a[0][1] = T->v[2].x - T->v[0].x;
39 	a[1][0] = T->v[1].y - T->v[0].y;
40 	a[1][1] = T->v[2].y - T->v[0].y;
41 
42 	b[0]	= x - T->v[0].x;
43 	b[1]	= y - T->v[0].y;
44 
45 	if( SolveLinearEquation2( a, b, c ) != 0 )
46 		return -1;
47 
48 	return (c[0] < 0.0 || c[1] < 0.0 || c[0] + c[1] > 1.0);
49 
50 }
51 
52 
53 #if 0
54 int SetSourceTriangles( AlignInfo *g, int nIm, PTTriangle** t  )
55 {
56 	int i,j,nt=0;
57 	controlPoint *cp;
58 	double 	w2 	= (double) g->im[nIm].width  / 2.0 - 0.5;  // Steve's L
59 	double 	h2 	= (double) g->im[nIm].height / 2.0 - 0.5;
60 
61 
62 	*t = (PTTriangle*)malloc( g->nt  * sizeof( PTTriangle ) );
63 	if( *t== NULL )
64 	{
65 		PrintError("Not enough memory");
66 		return -1;
67 	}
68 
69 	for(i=0; i<g->nt; i++)
70 	{
71 		if( g->t[i].nIm == nIm )
72 		{
73 			for(j=0; j<3; j++)
74 			{
75 				cp = &g->cpt[g->t[i].vert[j]];
76 				(*t)[nt].v[j].x = cp->x[0] - w2;
77 				(*t)[nt].v[j].y = cp->y[0] - h2;
78 			}
79 			nt++;
80 		}
81 	}
82 	return nt;
83 }
84 #endif
85 
86 
87 // Allocate space for triangles, and set them to
88 // T = s * T0 + (1-s) * T1
89 // Controlpoints must be sorted
InterpolateTriangles(AlignInfo * g,int nIm,double s,PTTriangle ** t)90 int InterpolateTriangles( AlignInfo *g, int nIm, double s, PTTriangle** t  )
91 {
92 	int i,j,nt=0;
93 	double u = 1.0 - s;
94 	controlPoint *cp;
95 	double 	w2 	= (double) g->im[nIm].width  / 2.0 - 0.5;  // Steve's L
96 	double 	h2 	= (double) g->im[nIm].height / 2.0 - 0.5;
97 
98 	*t = (PTTriangle*)malloc( g->nt  * sizeof( PTTriangle ) );
99 	if( *t== NULL )
100 	{
101 		PrintError("Not enough memory");
102 		return -1;
103 	}
104 
105 	for(i=0; i<g->nt; i++)
106 	{
107 		if( g->t[i].nIm == nIm )
108 		{
109 			for(j=0; j<3; j++)
110 			{
111 				cp = &g->cpt[g->t[i].vert[j]];
112 				(*t)[nt].v[j].x = cp->x[0] * u + cp->x[1] * s - w2;
113 				(*t)[nt].v[j].y = cp->y[0] * u + cp->y[1] * s - h2;
114 			}
115 			nt++;
116 		}
117 	}
118 	return nt;
119 }
120 
SetSourceTriangles(AlignInfo * g,int nIm,PTTriangle ** t)121 int SetSourceTriangles( AlignInfo *g, int nIm, PTTriangle** t  )
122 {
123 	return InterpolateTriangles( g, nIm, 0.0, t  );
124 }
125 
SetDestTriangles(AlignInfo * g,int nIm,PTTriangle ** t)126 int SetDestTriangles( AlignInfo *g, int nIm, PTTriangle** t  )
127 {
128 	return InterpolateTriangles( g, nIm, 1.0, t  );
129 }
130 
131 
132 
133 // Put Controlpointcoordinates of image Nr nIm first
134 
SortControlPoints(AlignInfo * g,int nIm)135 void SortControlPoints( AlignInfo *g, int nIm )
136 {
137 	int i;
138 	controlPoint cp;
139 
140 	for(i=0; i<g->numPts; i++)
141 	{
142 		if( g->cpt[i].num[0] != nIm && g->cpt[i].num[1] == nIm )
143 		{
144 			memcpy( &cp, &g->cpt[i], sizeof(controlPoint));
145 
146 			g->cpt[i].num[0] = cp.num[1];
147 			g->cpt[i].num[1] = cp.num[0];
148 			g->cpt[i].x[0] 	 = cp.x[1];
149 			g->cpt[i].x[1] 	 = cp.x[0];
150 			g->cpt[i].y[0] 	 = cp.y[1];
151 			g->cpt[i].y[1] 	 = cp.y[0];
152 		}
153 	}
154 }
155 
156 
157 #define OUTSIDE 10000000.0
158 
tmorph(double x_dest,double y_dest,double * x_src,double * y_src,void * params)159 int tmorph( double x_dest,double  y_dest, double* x_src, double* y_src, void* params )
160 {
161 	static int CurTriangle = 0;
162 	double c[2];
163 	PTTriangle *s, *td = ((PTTriangle**)params)[0] ,*ts= ((PTTriangle**)params)[1];
164 	int nt = *((int**)params)[2];
165 
166 	//reset the CurTriangle if it exceeds the number of triangles passed in here
167 	if (CurTriangle >= nt)
168 		CurTriangle = 0;
169 
170 	//iterate through all triangles and find the one that contains the destination point
171 	if(  PointInTriangle( x_dest, y_dest, &td[CurTriangle], c ) != 0 )
172 	{
173 		for(CurTriangle = 0;
174 			CurTriangle < nt && PointInTriangle( x_dest, y_dest, &td[CurTriangle], c ) != 0;
175 			CurTriangle++) continue;
176 		if( CurTriangle == nt )
177 		{
178 			CurTriangle = 0;
179 			lastCurTriangle = CurTriangle;
180 			*x_src		= OUTSIDE;
181 			*y_src		= OUTSIDE;
182 			return 0;
183 		}
184 	}
185 
186 	// At this point c contains valid coordinates
187 	s = &ts[CurTriangle];
188 
189 	*x_src = s->v[0].x + c[0] * ( s->v[1].x - s->v[0].x ) + c[1] * ( s->v[2].x - s->v[0].x );
190 	*y_src = s->v[0].y + c[0] * ( s->v[1].y - s->v[0].y ) + c[1] * ( s->v[2].y - s->v[0].y );
191 	lastCurTriangle = CurTriangle;
192     return 1;
193 }
194 
195 
MorphImage(Image * src,Image * dst,PTTriangle * ts,PTTriangle * td,int nt)196 int MorphImage( Image *src, Image *dst, PTTriangle *ts, PTTriangle *td, int nt )
197 {
198 	TrformStr  	Tr;
199 	fDesc		fD;
200 	void		*params[3];
201 
202 
203 
204 	// Set dest image
205 	// memcpy( dst, src, sizeof( Image ));
206 	dst->data = (unsigned char**)mymalloc((size_t)dst->dataSize);
207 	if(dst->data == NULL)
208 	{
209 		PrintError("Not enough memory");
210 		return -1;
211 	}
212 
213   memset(&Tr, 0, sizeof(TrformStr));
214 	Tr.mode					= _show_progress;
215 	Tr.interpolator			= _spline36;
216 	Tr.gamma				= 1.0;
217     Tr.fastStep             = FAST_TRANSFORM_STEP_NONE;
218 	Tr.src					= src;
219 	Tr.dest					= dst;
220 	Tr.success				= 1;
221 
222 
223 	params[0] = (void*)td;
224 	params[1] = (void*)ts;
225 	params[2] = (void*)&nt;
226 
227 	fD.func	  = tmorph;
228 	fD.param  = (void*)params;
229 
230 	transForm( &Tr, &fD, 0 );
231 
232 	if( Tr.success )
233 		return 0;
234 	else
235 	{
236 		if(dst->data)
237 			myfree((void**)dst->data);
238 		return -1;
239 	}
240 }
241 
MorphImageFile(fullPath * sfile,fullPath * dfile,AlignInfo * g,int nIm)242 int MorphImageFile( fullPath *sfile, fullPath *dfile, AlignInfo *g,int nIm )
243 {
244 	PTTriangle *ts=NULL, *td=NULL;
245 	Image src, dst;
246 	int nt, result;
247 	double s = g->pano.cP.vertical_params[0];
248 
249 
250 	if( panoImageRead( &src, sfile ) == 0)
251 	{
252 		PrintError("Could not read image");
253 		return -1;
254 	}
255 
256 	// Set dest
257 
258 	memcpy(&dst, &src, sizeof(Image));
259 	dst.width	= g->pano.width;
260 	dst.height	= g->pano.height;
261 	dst.bytesPerLine = dst.width * 4;
262 	dst.dataSize = dst.height * dst.bytesPerLine;
263 
264 
265 
266 	SortControlPoints( g, nIm );
267 
268 	nt = SetSourceTriangles( g, nIm, &ts  );
269 	if( nt < 0 )	return -1;
270 	if( nt == 0 )	return 1; // Nothing to interpolate
271 
272 	SortControlPoints( g, 0 );
273 
274 	nt = InterpolateTriangles( g, nIm, s, &td  );
275 	if( nt < 0 )	return -1;
276 	if( nt == 0 )	return 1; // Nothing to interpolate
277 
278 
279 	result = MorphImage( &src, &dst, ts, td, nt );
280 
281 	myfree( (void**)src.data );
282 	if(ts) free( ts );
283 	if(td) free( td );
284 
285 	if( result == 0 ) // success
286 	{
287 		mycreate( dfile, '8BIM', '8BPS' );
288 		if( writePSD( &dst, dfile ) != 0)
289 		{
290 			PrintError("Could not write destination Image");
291 			result = -1;
292 		}
293 		myfree( (void**)dst.data );
294 	}
295 
296 	return result;
297 }
298 
299 
300 
301 
302 
303 
304 
blendImages(fullPath * f0,fullPath * f1,fullPath * result,double s)305 int blendImages( fullPath *f0,  fullPath *f1, fullPath *result, double s )
306 {
307 	double u = 1.0 - s, r;
308 	uint32_t x,y,cy,i;
309 	Image im0, im1;
310 	unsigned char *c0, *c1;
311 
312 	if( readPSD(&im0, f0, 1) != 0 )
313 	{
314 		PrintError("Error reading image file");
315 		return -1;
316 	}
317 	if( readPSD(&im1, f1, 1) != 0 )
318 	{
319 		PrintError("Error reading image file");
320 		return -1;
321 	}
322 
323 	for(y=0; y<im0.height; y++)
324 	{
325 		cy = y * im0.bytesPerLine;
326 		for(x=0; x<im0.width; x++)
327 		{
328 			c0 = *im0.data + cy + 4 * x;
329 			c1 = *im1.data + cy + 4 * x;
330 
331 			if( *c1 )
332 			{
333 				if( *c0 )
334 				{
335 					for(i=1; i<4; i++)
336 					{
337 						r = u * (double)c0[i] + s * (double)c1[i];
338 						DBL_TO_UC( c0[i], r );
339 					}
340 				}
341 				else
342 					memcpy( c0, c1, 4 );
343 			}
344 		}
345 	}
346 
347 	mycreate( result, '8BIM', '8BPS' );
348 	if( writePSD( &im0, result ) != 0)
349 	{
350 		PrintError("Could not write destination Image");
351 		return -1;
352 	}
353 	myfree( (void**)im0.data );
354 	myfree( (void**)im1.data );
355 
356 	return 0;
357 }
358 
359 
360 
361 
362 
InterpolateImageFile(fullPath * sfile,fullPath * dfile,AlignInfo * g,int nIm)363 int InterpolateImageFile( fullPath *sfile, fullPath *dfile, AlignInfo *g,int nIm )
364 {
365 	PTTriangle *ts=NULL, *td=NULL;
366 	Image src, dst;
367 	int nt, result;
368 	double s = g->pano.cP.vertical_params[0];
369 
370 
371 	if( panoImageRead( &src, sfile ) == 0 )
372 	{
373 		PrintError("Could not read image");
374 		return -1;
375 	}
376 
377 	// Set dest
378 
379 	memcpy(&dst, &src, sizeof(Image));
380 	dst.width	= g->pano.width;
381 	dst.height	= g->pano.height;
382 	dst.bytesPerLine = dst.width * 4;
383 	dst.dataSize = dst.height * dst.bytesPerLine;
384 
385 
386 
387 	SortControlPoints( g, nIm );
388 
389 	nt = SetSourceTriangles( g, nIm, &ts  );
390 	if( nt < 0 )	return -1;
391 	if( nt == 0 )	return 1; // Nothing to interpolate
392 
393 
394 	SortControlPoints( g, 0 );
395 
396 	nt = InterpolateTrianglesPerspective( g, nIm, s, &td  );
397 	if( nt < 0 )	return -1;
398 	if( nt == 0 )	return 1; // Nothing to interpolate
399 
400 
401 
402 	result = MorphImage( &src, &dst, ts, td, nt );
403 
404 
405 	myfree( (void**)src.data );
406 	if(ts) free( ts );
407 	if(td) free( td );
408 
409 	if( result == 0 ) // success
410 	{
411 		mycreate( dfile, '8BIM', '8BPS' );
412 		if( writePSD( &dst, dfile ) != 0)
413 		{
414 			PrintError("Could not write destination Image");
415 			result = -1;
416 		}
417 		myfree( (void**)dst.data );
418 	}
419 
420 	return result;
421 }
422 
423 
424 // Allocate space for triangles, and set them to
425 // T = s * T0 + (1-s) * T1
426 // Controlpoints must be sorted
InterpolateTrianglesPerspective(AlignInfo * g,int nIm,double s,PTTriangle ** t)427 int InterpolateTrianglesPerspective( AlignInfo *g, int nIm, double s, PTTriangle** t  )
428 {
429 	int i,j,nt=0;
430 	double u = 1.0 - s;
431 	controlPoint *cp;
432 	double 	w2 	= (double) g->im[nIm].width  / 2.0 - 0.5;  // Steve's L
433 	double 	h2 	= (double) g->im[nIm].height / 2.0 - 0.5;
434 	struct 	MakeParams	m0, m1;
435 	fDesc 	m0_stack[15], m1_stack[15];
436 	Image d0, dst;
437 	double x0,x1,y0,y1;
438 
439 	memcpy(&d0, &g->im[nIm], sizeof(Image));
440 	d0.yaw 		= 0.0;
441 	d0.roll		= 0.0;
442 	d0.pitch 	= 0.0;
443 
444 
445 	SetInvMakeParams( m0_stack, &m0, &g->im[0], &d0, 0 );
446 	SetInvMakeParams( m1_stack, &m1, &g->im[1], &d0, 0 );
447 
448 
449 	*t = (PTTriangle*)malloc( g->nt  * sizeof( PTTriangle ) );
450 	if( *t== NULL )
451 	{
452 		PrintError("Not enough memory");
453 		return -1;
454 	}
455 
456 	for(i=0; i<g->nt; i++)
457 	{
458 		if( g->t[i].nIm == nIm )
459 		{
460 			for(j=0; j<3; j++)
461 			{
462 				cp = &g->cpt[g->t[i].vert[j]];
463 				execute_stack( 	cp->x[0] - w2, cp->y[0] - h2, &x0, &y0, m0_stack );
464 				execute_stack( 	cp->x[1] - w2, cp->y[1] - h2, &x1, &y1, m1_stack );
465 				(*t)[nt].v[j].x = x0 * u + x1 * s;
466 				(*t)[nt].v[j].y = y0 * u + y1 * s;
467 			}
468 			nt++;
469 		}
470 	}
471 
472 	memcpy(&dst, &g->im[nIm], sizeof(Image));
473 	dst.hfov	= g->pano.hfov;
474 	dst.width	= g->pano.width;
475 	dst.height	= g->pano.height;
476 	dst.bytesPerLine = dst.width * 4;
477 	dst.dataSize = dst.height * dst.bytesPerLine;
478 	dst.yaw 	= (1.0 - s) * g->im[0].yaw 		+ s * g->im[1].yaw;
479 	dst.pitch 	= (1.0 - s) * g->im[0].pitch 	+ s * g->im[1].pitch;
480 	dst.roll 	= (1.0 - s) * g->im[0].roll 	+ s * g->im[1].roll;
481 
482 	SetMakeParams( m0_stack, &m0, &dst, &d0, 0 );
483 	for(i=0; i<nt; i++)
484 	{
485 		for(j=0; j<3; j++)
486 		{
487 			execute_stack( 	(*t)[i].v[j].x, (*t)[i].v[j].y, &x0, &y0, m0_stack );
488 			(*t)[i].v[j].x = x0;
489 			(*t)[i].v[j].y = y0;
490 		}
491 	}
492 
493 	return nt;
494 }
495 
496 
497 
498 
499