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 /*------------------------------------------------------------*/
20 #include "utils_math.h"
23 // Lookup Tables for Trig-functions and interpolator
33 void matrix_matrix_mult ( double m1[3][3],double m2[3][3],double result[3][3]);
34 void PV_transForm( TrformStr *TrPtr, int dist_r, int dist_e, int mt[3][3]);
35 int PV_atan2(int y, int x);
36 int PV_sqrt( int x1, int x2 );
39 // Bilinear interpolator
41 static void bil( unsigned char *dst, unsigned char **rgb,
44 int yr, yg, yb,weight;
46 register unsigned char *r;
50 w1 = mweights[dx]; w2 = mweights[255 - dx];
54 rd = w2[*r++]; gd = w2[*r++]; bd = w2[*r++];
55 //weight = 255 - dx; rd = weight * *r++; gd = weight * *r++; bd = weight * *r++;
58 rd += w1[*r++]; gd += w1[*r++]; bd += w1[*r];
59 //rd += dx * *r++; gd += dx * *r++; bd += dx * *r;
64 yr = w2[*r++]; yg = w2[*r++]; yb = w2[*r++];
65 //rd = weight * *r++; gd = weight * *r++; bd = weight * *r++;
68 yr += w1[*r++]; yg += w1[*r++]; yb += w1[*r];
69 //rd += dx * *r++; gd += dx * *r++; bd += dx * *r;
72 rd = rd * weight + yr * dy;
73 gd = gd * weight + yg * dy;
74 bd = bd * weight + yb * dy;
84 * Extract image from pano in TrPtr->src using parameters in prefs (ignore
85 * image parameters in TrPtr)
87 void PV_ExtractStill( TrformStr *TrPtr )
89 /* field of view in rad */
97 a = DEG_TO_RAD( TrPtr->dest->hfov ); // field of view in rad
98 b = DEG_TO_RAD( TrPtr->src->hfov );
100 /* Set up the transformation matrix `mt' using Euler angles (somehow..) */
101 SetMatrix (DEG_TO_RAD (TrPtr->dest->pitch), /* alpha */
102 DEG_TO_RAD (TrPtr->dest->yaw), /* beta */
108 p[0] = (double)TrPtr->dest->width/ (2.0 * tan( a / 2.0 ) );
109 p[1] = (double) TrPtr->src->width / b;
113 mi[i][k] = 256 * mt[i][k];
118 PV_transForm( TrPtr, (int)(p[0]+.5), (int)(p[1]+.5), mi);
126 // Main transformation function. Destination image is calculated using transformation
127 // Function "func". Either all colors (color = 0) or one of rgb (color =1,2,3) are
128 // determined. If successful, TrPtr->success = 1. Memory for destination image
129 // must have been allocated and locked!
131 void PV_transForm( TrformStr *TrPtr, int dist_r, int dist_e, int mt[3][3])
133 int x_dest, y_dest; // Loop through destination image
134 unsigned char *dest,*src,*sry, *dst;// Source and destination image data
135 long cy; // rownum in destimage
140 unsigned char *rgb[2] ,
141 cdata[16]; // Image data handed to sampler
144 int mix = TrPtr->src->width - 1; // maximum x-index src
145 int miy = TrPtr->src->height - 1;// maximum y-index src
147 // Variables used to convert screen coordinates to cartesian coordinates
150 int w2 = TrPtr->dest->width / 2 ;
151 int h2 = TrPtr->dest->height / 2 ;
152 int sw2 = TrPtr->src->width / 2 ;
153 int sh2 = TrPtr->src->height / 2 ;
155 int BytesPerLine = TrPtr->src->bytesPerLine;
157 int x_min, x_max, y_min, y_max;
161 dr1 = mt[2][0] * dist_r;
162 dr2 = mt[2][1] * dist_r;
163 dr3 = mt[2][2] * dist_r;
165 dest = *TrPtr->dest->data;
166 src = *TrPtr->src->data; // is locked
168 x_min = -w2; x_max = TrPtr->dest->width - w2;
169 y_min = -h2; y_max = TrPtr->dest->height - h2;
173 if( TrPtr->interpolator == _bilinear )
175 for(y_dest = y_min; y_dest < y_max; y_dest++, cy+=TrPtr->dest->bytesPerLine)
178 for(x_dest = x_min; x_dest < x_max; x_dest++, dst+=4)
180 v[0] = mt[0][0] * x_dest + mt[1][0] * y_dest + dr1;
181 v[1] = mt[0][1] * x_dest + mt[1][1] * y_dest + dr2;
182 v[2] = mt[0][2] * x_dest + mt[1][2] * y_dest + dr3;
184 v[0] = v[0] >> 8; v[2] = v[2] >> 8;
186 x_src = dist_e * PV_atan2( v[0], v[2] ) / NATAN ;
187 y_src = dist_e * PV_atan2( v[1], utils_sqrt2 ( abs(v[2]), abs(v[0]) ) ) / NATAN ;
189 dx = x_src & 255; dy = y_src & 255; // fraction
191 x_src = (x_src >> 8) + sw2;
192 y_src = (y_src >> 8) + sh2;
195 if( y_src >= 0 && y_src < miy && x_src >= 0 && x_src < mix ) // all interpolation pixels inside image
198 sry = src + y_src * BytesPerLine + x_src * 4;
200 rgb[1] = sry + BytesPerLine;
209 else if( y_src > miy )
210 sry = src + miy * BytesPerLine;
212 sry = src + y_src * BytesPerLine;
214 if( x_src < 0 ) x_src = mix;
215 if( x_src > mix) x_src = 0;
216 *(long*)rgb[0] = *(long*)(sry + x_src*4);
219 if( x_src < 0 ) x_src = mix;
220 if( x_src > mix) x_src = 0;
221 *(long*)(rgb[0]+4) = *(long*)(sry + x_src*4);
229 else if( y_src > miy )
230 sry = src + miy * BytesPerLine;
232 sry = src + y_src * BytesPerLine;
234 if( x_src < 0 ) x_src = mix;
235 if( x_src > mix) x_src = 0;
236 *(long*)rgb[1] = *(long*)(sry + x_src*4);
238 if( x_src < 0 ) x_src = mix;
239 if( x_src > mix) x_src = 0;
240 *(long*)(rgb[1]+4) = *(long*)(sry + x_src*4);
244 bil( dst, rgb, dx, dy );
248 else if( TrPtr->interpolator == _nn )
250 for(y_dest = y_min; y_dest < y_max; y_dest++, cy+=TrPtr->dest->bytesPerLine)
253 for(x_dest = x_min; x_dest < x_max; x_dest++, dst+=4)
255 v[0] = mt[0][0] * x_dest + mt[1][0] * y_dest + dr1;
256 v[1] = mt[0][1] * x_dest + mt[1][1] * y_dest + dr2;
257 v[2] = mt[0][2] * x_dest + mt[1][2] * y_dest + dr3;
259 v[0] = v[0] >> 8; v[2] = v[2] >> 8;
261 x_src = dist_e * PV_atan2( v[0], v[2] ) / NATAN ;
263 y_src = dist_e * PV_atan2( v[1], utils_sqrt2( abs(v[2]), abs(v[0]) ) ) / NATAN ;
265 dx = x_src & 255; dy = y_src & 255; // fraction
268 x_src = (x_src >> 8) + sw2;
269 y_src = (y_src >> 8) + sh2;
271 if( x_src < 0 ) x_src = 0;
272 if( x_src > mix ) x_src = mix;
273 if( y_src < 0) y_src = 0;
274 if( y_src > miy ) y_src = miy;
276 *(long*)dst = *(long*)(src + y_src * BytesPerLine + x_src * 4);
286 void matrix_inv_mult( double m[3][3], double vector[3] )
289 register double v0 = vector[0];
290 register double v1 = vector[1];
291 register double v2 = vector[2];
295 vector[i] = m[0][i] * v0 + m[1][i] * v1 + m[2][i] * v2;
300 // Set matrix elements based on Euler angles a, b, c
302 void SetMatrix( double a, double b, double c , double m[3][3], int cl )
304 double mx[3][3], my[3][3], mz[3][3], dummy[3][3];
307 // Calculate Matrices;
309 mx[0][0] = 1.0 ; mx[0][1] = 0.0 ; mx[0][2] = 0.0;
310 mx[1][0] = 0.0 ; mx[1][1] = cos(a) ; mx[1][2] = sin(a);
311 mx[2][0] = 0.0 ; mx[2][1] =-mx[1][2] ; mx[2][2] = mx[1][1];
313 my[0][0] = cos(b); my[0][1] = 0.0 ; my[0][2] =-sin(b);
314 my[1][0] = 0.0 ; my[1][1] = 1.0 ; my[1][2] = 0.0;
315 my[2][0] = -my[0][2]; my[2][1] = 0.0 ; my[2][2] = my[0][0];
317 mz[0][0] = cos(c) ; mz[0][1] = sin(c) ; mz[0][2] = 0.0;
318 mz[1][0] =-mz[0][1] ; mz[1][1] = mz[0][0] ; mz[1][2] = 0.0;
319 mz[2][0] = 0.0 ; mz[2][1] = 0.0 ; mz[2][2] = 1.0;
321 /* Calculate `m = mz * mx * my' */
324 matrix_matrix_mult( mz, mx, dummy);
326 matrix_matrix_mult( mx, mz, dummy);
327 matrix_matrix_mult( dummy, my, m);
328 } /* void SetMatrix */
330 void matrix_matrix_mult( double m1[3][3],double m2[3][3],double result[3][3])
336 result[i][k] = m1[i][0] * m2[0][k] + m1[i][1] * m2[1][k] + m1[i][2] * m2[2][k];
337 } /* void matrix_matrix_mult */
341 int PV_atan2(int y, int x)
343 // return atan2(y,x) * 256*NATAN;
348 return atan_LU[(int)( NATAN * y / ( x + y ))];
352 return -atan_LU[ (int)(NATAN * (-y) / ( x - y ))];
359 return (int)(256*NATAN*PI / 2.0);
361 return -(int)(256*NATAN*PI / 2.0);
366 return atan_LU[(int)( NATAN * y / ( x + y ))] - (int)(PI*256*NATAN);
370 return -atan_LU[ (int)(NATAN * (-y) / ( x - y ))] + (int)(PI*256*NATAN);
380 double dz = 1.0 / (double)NATAN;
383 atan_LU = (int*) malloc( (NATAN+1) * sizeof( int ));
385 if( atan_LU == NULL )
388 for( i=0; i< NATAN; i++, z+=dz )
389 atan_LU[i] = atan( z / (1.0 - z ) ) * NATAN * 256;
391 atan_LU[NATAN] = PI/4.0 * NATAN * 256;
395 for(i = -10; i< 10; i++)
398 for(k=-10; k<10; k++)
400 printf("i = %d k = %d atan2(i,k) = %g LUatan(i,k) = %g diff = %g\n", i,k,atan2(i,k),
401 (double)PV_atan2(i,k) / (256*NATAN) , atan2(i,k) - (double)PV_atan2(i,k) / (256*NATAN));
412 double dz = 1.0 / (double)NSQRT;
415 sqrt_LU = (int*) malloc( (NSQRT+1) * sizeof( int ));
417 if( sqrt_LU == NULL )
420 for( i=0; i< NSQRT; i++, z+=dz )
421 sqrt_LU[i] = sqrt( 1.0 + z*z ) * 256 * NSQRT;
423 sqrt_LU[NSQRT] = sqrt(2.0) * 256 * NSQRT;
434 mweights[i] = (int*)malloc( 256 * sizeof(int) );
435 if( mweights[i] == NULL ) return -1;
441 mweights[i][k] = i*k;
449 int PV_sqrt( int x1, int x2 )
453 return x1 * sqrt_LU[ NSQRT * x2 / x1 ] / NSQRT;
457 if( x2 == 0 ) return 0;
458 return x2 * sqrt_LU[ NSQRT * x1 / x2 ] / NSQRT;
477 // Find last jpeg inside image; create and copy to file jpeg
478 int extractJPEG( fullPath *image, fullPath *jpeg )
486 if( myopen( image, read_bin, fnum ) )
490 count = 1; i=0; // Get file length
494 myread( fnum, count, &ch );
501 im = (UCHAR*)malloc( count );
504 PrintError("Not enough memory");
508 if( myopen( image, read_bin, fnum ) )
511 myread(fnum,count,im);
519 for(i=0; i<count; i++)
521 if( im[i] == ID_0 && im[i+1] == ID_1 && im[i+2] == ID_2 && im[i+3] == ID_3
522 && im[i+4] == ID_4 && im[i+5] == ID_5 && im[i+6] == ID_6 && im[i+7] == ID_7
523 && im[i+8] == ID_8 && im[i+9] == ID_9 && im[i+10] == ID_10)
527 if( idx == -1 ) // No jpeg found
533 count = count + ID_LENGTH - idx;
535 mycreate( jpeg, 'GKON','JPEG');
536 if( myopen( jpeg, write_bin, fnum ) )
538 mywrite( fnum, count, im+idx );
546 * vim: set tabstop=4 softtabstop=4 shiftwidth=4 :