1 /* Panorama_Tools - Generate, Edit and Convert Panoramic Images
2 Copyright (C) 1998,1999 - Helmut Dersch der@fh-furtwangen.de
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
18 /*------------------------------------------------------------*/
22 // Lookup Tables for Trig-functions and interpolator
32 void matrix_matrix_mult ( double m1[3][3],double m2[3][3],double result[3][3]);
33 void PV_transForm( TrformStr *TrPtr, int dist_r, int dist_e, int mt[3][3]);
34 int PV_atan2(int y, int x);
35 int PV_sqrt( int x1, int x2 );
38 // Bilinear interpolator
40 static void bil( unsigned char *dst, unsigned char **rgb,
43 int yr, yg, yb,weight;
45 register unsigned char *r;
49 w1 = mweights[dx]; w2 = mweights[255 - dx];
53 rd = w2[*r++]; gd = w2[*r++]; bd = w2[*r++];
54 //weight = 255 - dx; rd = weight * *r++; gd = weight * *r++; bd = weight * *r++;
57 rd += w1[*r++]; gd += w1[*r++]; bd += w1[*r];
58 //rd += dx * *r++; gd += dx * *r++; bd += dx * *r;
63 yr = w2[*r++]; yg = w2[*r++]; yb = w2[*r++];
64 //rd = weight * *r++; gd = weight * *r++; bd = weight * *r++;
67 yr += w1[*r++]; yg += w1[*r++]; yb += w1[*r];
68 //rd += dx * *r++; gd += dx * *r++; bd += dx * *r;
71 rd = rd * weight + yr * dy;
72 gd = gd * weight + yg * dy;
73 bd = bd * weight + yb * dy;
82 // Extract image from pano in TrPtr->src
83 // using parameters in prefs (ignore image parameters
86 void PV_ExtractStill( TrformStr *TrPtr )
88 double a,b; // field of view in rad
95 a = DEG_TO_RAD( TrPtr->dest->hfov ); // field of view in rad
96 b = DEG_TO_RAD( TrPtr->src->hfov );
98 SetMatrix( DEG_TO_RAD( TrPtr->dest->pitch ),
99 DEG_TO_RAD( TrPtr->dest->yaw ),
105 p[0] = (double)TrPtr->dest->width/ (2.0 * tan( a / 2.0 ) );
106 p[1] = (double)TrPtr->src->width/ b;
110 mi[i][k] = 256 * mt[i][k];
115 PV_transForm( TrPtr, (int)(p[0]+.5), (int)(p[1]+.5), mi);
123 // Main transformation function. Destination image is calculated using transformation
124 // Function "func". Either all colors (color = 0) or one of rgb (color =1,2,3) are
125 // determined. If successful, TrPtr->success = 1. Memory for destination image
126 // must have been allocated and locked!
128 void PV_transForm( TrformStr *TrPtr, int dist_r, int dist_e, int mt[3][3])
130 register int x, y; // Loop through destination image
131 unsigned char *dest,*src,*sry, *dst;// Source and destination image data
132 long cy; // rownum in destimage
135 int xc; // Cartesian Coordinates of point ("target") in Destination image
138 unsigned char *rgb[2] ,
139 cdata[16]; // Image data handed to sampler
142 int mix = TrPtr->src->width - 1; // maximum x-index src
143 int miy = TrPtr->src->height - 1;// maximum y-index src
145 // Variables used to convert screen coordinates to cartesian coordinates
148 int w2 = TrPtr->dest->width / 2 ;
149 int h2 = TrPtr->dest->height / 2 ;
150 int sw2 = TrPtr->src->width / 2 ;
151 int sh2 = TrPtr->src->height / 2 ;
153 int BytesPerLine = TrPtr->src->bytesPerLine;
155 int x_min, x_max, y_min, y_max;
159 dr1 = mt[2][0] * dist_r;
160 dr2 = mt[2][1] * dist_r;
161 dr3 = mt[2][2] * dist_r;
167 dest = *TrPtr->dest->data;
168 src = *TrPtr->src->data; // is locked
170 x_min = -w2; x_max = TrPtr->dest->width - w2;
171 y_min = -h2; y_max = TrPtr->dest->height - h2;
175 if( TrPtr->interpolator == _bilinear )
177 for(y = y_min; y < y_max; y++, cy+=TrPtr->dest->bytesPerLine)
180 for(x = x_min; x < x_max; x++, dst+=4)
182 v[0] = mt[0][0] * x + mt[1][0] * y + dr1;
183 v[1] = mt[0][1] * x + mt[1][1] * y + dr2;
184 v[2] = mt[0][2] * x + mt[1][2] * y + dr3;
186 v[0] = v[0] >> 8; v[2] = v[2] >> 8;
188 xs = dist_e * PV_atan2( v[0], v[2] ) / NATAN ;
190 ys = dist_e * PV_atan2( v[1], PV_sqrt( abs(v[2]), abs(v[0]) ) ) / NATAN ;
192 dx = xs & 255; dy = ys & 255; // fraction
195 xs = (xs >> 8) + sw2;
196 ys = (ys >> 8) + sh2;
199 if( ys >= 0 && ys < miy && xs >= 0 && xs < mix ) // all interpolation pixels inside image
202 sry = src + ys * BytesPerLine + xs * 4;
204 rgb[1] = sry + BytesPerLine;
214 sry = src + miy * BytesPerLine;
216 sry = src + ys * BytesPerLine;
218 if( xs < 0 ) xs = mix;
219 if( xs > mix) xs = 0;
220 *(long*)rgb[0] = *(long*)(sry + xs*4);
223 if( xs < 0 ) xs = mix;
224 if( xs > mix) xs = 0;
225 *(long*)(rgb[0]+4) = *(long*)(sry + xs*4);
234 sry = src + miy * BytesPerLine;
236 sry = src + ys * BytesPerLine;
238 if( xs < 0 ) xs = mix;
239 if( xs > mix) xs = 0;
240 *(long*)rgb[1] = *(long*)(sry + xs*4);
242 if( xs < 0 ) xs = mix;
243 if( xs > mix) xs = 0;
244 *(long*)(rgb[1]+4) = *(long*)(sry + xs*4);
248 bil( dst, rgb, dx, dy );
252 else if( TrPtr->interpolator == _nn )
254 for(y = y_min; y < y_max; y++, cy+=TrPtr->dest->bytesPerLine)
257 for(x = x_min; x < x_max; x++, dst+=4)
259 v[0] = mt[0][0] * x + mt[1][0] * y + dr1;
260 v[1] = mt[0][1] * x + mt[1][1] * y + dr2;
261 v[2] = mt[0][2] * x + mt[1][2] * y + dr3;
263 v[0] = v[0] >> 8; v[2] = v[2] >> 8;
265 xs = dist_e * PV_atan2( v[0], v[2] ) / NATAN ;
267 ys = dist_e * PV_atan2( v[1], PV_sqrt( abs(v[2]), abs(v[0]) ) ) / NATAN ;
269 dx = xs & 255; dy = ys & 255; // fraction
272 xs = (xs >> 8) + sw2;
273 ys = (ys >> 8) + sh2;
276 if( xs > mix ) xs = mix;
278 if( ys > miy ) ys = miy;
280 *(long*)dst = *(long*)(src + ys * BytesPerLine + xs * 4);
290 void matrix_inv_mult( double m[3][3], double vector[3] )
293 register double v0 = vector[0];
294 register double v1 = vector[1];
295 register double v2 = vector[2];
299 vector[i] = m[0][i] * v0 + m[1][i] * v1 + m[2][i] * v2;
303 // Set matrix elements based on Euler angles a, b, c
305 void SetMatrix( double a, double b, double c , double m[3][3], int cl )
307 double mx[3][3], my[3][3], mz[3][3], dummy[3][3];
310 // Calculate Matrices;
312 mx[0][0] = 1.0 ; mx[0][1] = 0.0 ; mx[0][2] = 0.0;
313 mx[1][0] = 0.0 ; mx[1][1] = cos(a) ; mx[1][2] = sin(a);
314 mx[2][0] = 0.0 ; mx[2][1] =-mx[1][2] ; mx[2][2] = mx[1][1];
316 my[0][0] = cos(b); my[0][1] = 0.0 ; my[0][2] =-sin(b);
317 my[1][0] = 0.0 ; my[1][1] = 1.0 ; my[1][2] = 0.0;
318 my[2][0] = -my[0][2]; my[2][1] = 0.0 ; my[2][2] = my[0][0];
320 mz[0][0] = cos(c) ; mz[0][1] = sin(c) ; mz[0][2] = 0.0;
321 mz[1][0] =-mz[0][1] ; mz[1][1] = mz[0][0] ; mz[1][2] = 0.0;
322 mz[2][0] = 0.0 ; mz[2][1] = 0.0 ; mz[2][2] = 1.0;
325 matrix_matrix_mult( mz, mx, dummy);
327 matrix_matrix_mult( mx, mz, dummy);
328 matrix_matrix_mult( dummy, my, m);
331 void matrix_matrix_mult( double m1[3][3],double m2[3][3],double result[3][3])
339 result[i][k] = m1[i][0] * m2[0][k] + m1[i][1] * m2[1][k] + m1[i][2] * m2[2][k];
346 int PV_atan2(int y, int x)
348 // return atan2(y,x) * 256*NATAN;
353 return atan_LU[(int)( NATAN * y / ( x + y ))];
357 return -atan_LU[ (int)(NATAN * (-y) / ( x - y ))];
364 return (int)(256*NATAN*PI / 2.0);
366 return -(int)(256*NATAN*PI / 2.0);
371 return atan_LU[(int)( NATAN * y / ( x + y ))] - (int)(PI*256*NATAN);
375 return -atan_LU[ (int)(NATAN * (-y) / ( x - y ))] + (int)(PI*256*NATAN);
385 double dz = 1.0 / (double)NATAN;
388 atan_LU = (int*) malloc( (NATAN+1) * sizeof( int ));
390 if( atan_LU == NULL )
393 for( i=0; i< NATAN; i++, z+=dz )
394 atan_LU[i] = atan( z / (1.0 - z ) ) * NATAN * 256;
396 atan_LU[NATAN] = PI/4.0 * NATAN * 256;
400 for(i = -10; i< 10; i++)
403 for(k=-10; k<10; k++)
405 printf("i = %d k = %d atan2(i,k) = %g LUatan(i,k) = %g diff = %g\n", i,k,atan2(i,k),
406 (double)PV_atan2(i,k) / (256*NATAN) , atan2(i,k) - (double)PV_atan2(i,k) / (256*NATAN));
417 double dz = 1.0 / (double)NSQRT;
420 sqrt_LU = (int*) malloc( (NSQRT+1) * sizeof( int ));
422 if( sqrt_LU == NULL )
425 for( i=0; i< NSQRT; i++, z+=dz )
426 sqrt_LU[i] = sqrt( 1.0 + z*z ) * 256 * NSQRT;
428 sqrt_LU[NSQRT] = sqrt(2.0) * 256 * NSQRT;
439 mweights[i] = (int*)malloc( 256 * sizeof(int) );
440 if( mweights[i] == NULL ) return -1;
446 mweights[i][k] = i*k;
454 int PV_sqrt( int x1, int x2 )
458 return x1 * sqrt_LU[ NSQRT * x2 / x1 ] / NSQRT;
462 if( x2 == 0 ) return 0;
463 return x2 * sqrt_LU[ NSQRT * x1 / x2 ] / NSQRT;
482 // Find last jpeg inside image; create and copy to file jpeg
483 int extractJPEG( fullPath *image, fullPath *jpeg )
491 if( myopen( image, read_bin, fnum ) )
495 count = 1; i=0; // Get file length
499 myread( fnum, count, &ch );
506 im = (UCHAR*)malloc( count );
509 PrintError("Not enough memory");
513 if( myopen( image, read_bin, fnum ) )
516 myread(fnum,count,im);
524 for(i=0; i<count; i++)
526 if( im[i] == ID_0 && im[i+1] == ID_1 && im[i+2] == ID_2 && im[i+3] == ID_3
527 && im[i+4] == ID_4 && im[i+5] == ID_5 && im[i+6] == ID_6 && im[i+7] == ID_7
528 && im[i+8] == ID_8 && im[i+9] == ID_9 && im[i+10] == ID_10)
532 if( idx == -1 ) // No jpeg found
538 count = count + ID_LENGTH - idx;
540 mycreate( jpeg, 'GKON','JPEG');
541 if( myopen( jpeg, write_bin, fnum ) )
543 mywrite( fnum, count, im+idx );