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