8b9f30b427ea9edeb6f60f455e613d22bb9b6b95
[libopano.git] / src / panolib.c
1 /* Panorama_Tools       -       Generate, Edit and Convert Panoramic Images
2    Copyright (C) 1998,1999 - Helmut Dersch  der@fh-furtwangen.de
3    
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)
7    any later version.
8
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.
13
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.  */
17
18 /*------------------------------------------------------------*/
19 #include <stdlib.h>
20 #include <stdint.h>
21 #include <assert.h>
22
23 #include "filter.h"
24 #include "utils_math.h"
25
26 #define DEG_TO_RAD(x) ((x) * 2.0 * M_PI / 360.0 )
27
28 // Lookup Tables for Trig-functions and interpolator
29
30 #define NATAN 2048
31 #define NSQRT 2048
32
33 int *atan_LU;
34 int *sqrt_LU;
35
36
37 void    matrix_matrix_mult      ( double m1[3][3],double m2[3][3],double result[3][3]);
38 void    PV_transForm( TrformStr *TrPtr, double dist_r, double dist_e, int mt[3][3]);
39 int     PV_sqrt( int x1, int x2 );
40
41
42 /*
43  * Extract image from pano in TrPtr->src using parameters in prefs (ignore
44  * image parameters in TrPtr)
45  */
46 void PV_ExtractStill( TrformStr *TrPtr )
47 {
48         /* field of view in rad */
49         double a;
50         double b;
51
52         double      p[2];
53         double          mt[3][3];
54         int             mi[3][3],i,k;
55
56         a =      DEG_TO_RAD( TrPtr->dest->hfov );       // field of view in rad         
57         b =      DEG_TO_RAD( TrPtr->src->hfov );
58
59         /* Set up the transformation matrix `mt' using Euler angles (somehow..) */
60         SetMatrix (DEG_TO_RAD (TrPtr->dest->pitch), /* alpha */
61                         DEG_TO_RAD (TrPtr->dest->yaw), /* beta */
62                         0.0, /* gamma */
63                         mt, /* output */
64                         1);
65
66
67         p[0] = (double)TrPtr->dest->width/ (2.0 * tan( a / 2.0 ) );
68         p[1] = (double) TrPtr->src->width / b;
69         
70         for(i=0; i<3; i++){
71                 for(k=0; k<3; k++){
72                         mi[i][k] = 256 * mt[i][k];
73                 }
74         }
75
76
77         PV_transForm( TrPtr, p[0], p[1], mi);
78         return;
79 }
80
81 typedef enum interpolator_e
82 {
83         NNEIGHBOUR,
84         BILINEAR
85 } interpolator_t;
86
87 static int copy_pixel (Image *dest, Image *src,
88                 int x_dest, int y_dest,
89                 double x_src_fp, double y_src_fp,
90                 interpolator_t interp)
91 {
92         uint32_t pixel_value;
93         uint32_t *src_data  = (uint32_t *) (*src->data);
94         uint32_t *dest_data = (uint32_t *) (*dest->data);
95
96         interp = NNEIGHBOUR;
97
98         if (interp == NNEIGHBOUR)
99         {
100                 int x_src = (int) (x_src_fp + 0.5) % src->width;
101                 int y_src = (int) (y_src_fp + 0.5) % src->height;
102
103                 if ((x_src < 0) || (x_src >= src->width)
104                                 || (y_src < 0) || (y_src >= src->height))
105                         pixel_value = 0x000000FF;
106                 else
107                         pixel_value = src_data[(y_src * src->width) + x_src];
108         }
109
110         dest_data[(y_dest * dest->width) + x_dest] = pixel_value;
111
112         return (0);
113 } /* int copy_pixel */
114
115 //    Main transformation function. Destination image is calculated using transformation
116 //    Function "func". Either all colors (color = 0) or one of rgb (color =1,2,3) are
117 //    determined. If successful, TrPtr->success = 1. Memory for destination image
118 //    must have been allocated and locked!
119
120 void PV_transForm( TrformStr *TrPtr, double dist_r, double dist_e, int mt[3][3])
121 {
122         int x_dest, y_dest;                     // Loop through destination image
123         unsigned char           *dest,*src;// Source and destination image data
124
125         // Variables used to convert screen coordinates to cartesian coordinates
126
127                 
128         int                             dest_width_left = TrPtr->dest->width  / 2 ;  
129         int                             dest_height_top = TrPtr->dest->height / 2 ;
130         int                             src_width_left =  TrPtr->src->width   / 2 ;
131         int                             src_height_top =  TrPtr->src->height  / 2 ;
132         
133         int                             v[3];
134         int                                     x_min, x_max, y_min, y_max;
135
136         int                                     dr1, dr2, dr3;
137
138         dr1 = mt[2][0] * dist_r;
139         dr2 = mt[2][1] * dist_r;
140         dr3 = mt[2][2] * dist_r;
141         
142         dest = *TrPtr->dest->data;
143         src  = *TrPtr->src->data; // is locked
144
145         x_min = -dest_width_left; x_max = TrPtr->dest->width - dest_width_left;
146         y_min = -dest_height_top; y_max = TrPtr->dest->height - dest_height_top;
147
148         for(y_dest = y_min; y_dest < y_max; y_dest++)
149         {
150                 for(x_dest = x_min; x_dest < x_max; x_dest++)
151                 {
152                         double x_src_fp;
153                         double y_src_fp;
154
155                         v[0] = mt[0][0] * x_dest + mt[1][0] * y_dest + dr1;
156                         v[1] = mt[0][1] * x_dest + mt[1][1] * y_dest + dr2;
157                         v[2] = mt[0][2] * x_dest + mt[1][2] * y_dest + dr3;
158
159                         v[0] = v[0] >> 8; v[2] = v[2] >> 8;
160                         v[1] = v[1] >> 8;
161
162                         x_src_fp = dist_e * atan2 (v[0], v[2]);
163                         y_src_fp = dist_e * atan2 (v[1], sqrt (v[2] * v[2] + v[0] * v[0]));
164
165                         copy_pixel (TrPtr->dest, TrPtr->src,
166                                         dest_width_left + x_dest, dest_height_top + y_dest,
167                                         src_width_left + x_src_fp, src_height_top + y_src_fp,
168                                         NNEIGHBOUR);
169                 }
170         }
171         
172         return;
173 }
174
175 #if 0
176 void matrix_inv_mult( double m[3][3], double vector[3] )
177 {
178         register int i;
179         register double v0 = vector[0];
180         register double v1 = vector[1];
181         register double v2 = vector[2];
182         
183         for(i=0; i<3; i++)
184         {
185                 vector[i] = m[0][i] * v0 + m[1][i] * v1 + m[2][i] * v2;
186         }
187 }
188 #endif
189
190 // Set matrix elements based on Euler angles a, b, c
191
192 void SetMatrix( double a, double b, double c , double m[3][3], int cl )
193 {
194         double mx[3][3], my[3][3], mz[3][3], dummy[3][3];
195         
196
197         // Calculate Matrices;
198
199         mx[0][0] = 1.0 ;                                mx[0][1] = 0.0 ;                                mx[0][2] = 0.0;
200         mx[1][0] = 0.0 ;                                mx[1][1] = cos(a) ;                     mx[1][2] = sin(a);
201         mx[2][0] = 0.0 ;                                mx[2][1] =-mx[1][2] ;                   mx[2][2] = mx[1][1];
202         
203         my[0][0] = cos(b);                              my[0][1] = 0.0 ;                                my[0][2] =-sin(b);
204         my[1][0] = 0.0 ;                                my[1][1] = 1.0 ;                                my[1][2] = 0.0;
205         my[2][0] = -my[0][2];                   my[2][1] = 0.0 ;                                my[2][2] = my[0][0];
206         
207         mz[0][0] = cos(c) ;                     mz[0][1] = sin(c) ;                     mz[0][2] = 0.0;
208         mz[1][0] =-mz[0][1] ;                   mz[1][1] = mz[0][0] ;                   mz[1][2] = 0.0;
209         mz[2][0] = 0.0 ;                                mz[2][1] = 0.0 ;                                mz[2][2] = 1.0;
210
211         /* Calculate `m = mz * mx * my' */
212
213         if( cl )
214                 matrix_matrix_mult( mz, mx,     dummy);
215         else
216                 matrix_matrix_mult( mx, mz,     dummy);
217         matrix_matrix_mult( dummy, my, m);
218 } /* void SetMatrix */
219
220 void matrix_matrix_mult( double m1[3][3],double m2[3][3],double result[3][3])
221 {
222         register int i,k;
223         
224         for(i=0;i<3;i++)
225                 for(k=0; k<3; k++)
226                         result[i][k] = m1[i][0] * m2[0][k] + m1[i][1] * m2[1][k] + m1[i][2] * m2[2][k];
227 } /* void matrix_matrix_mult */
228
229 #define ID_0 0xff
230 #define ID_1 0xd8
231 #define ID_2 0xff
232 #define ID_3 0xe0
233 #define ID_4 0x00
234 #define ID_5 0x10
235 #define ID_6 0x4a
236 #define ID_7 0x46
237 #define ID_8 0x49
238 #define ID_9 0x46
239 #define ID_10 0x00
240
241 #define ID_LENGTH 11
242
243 // Find last jpeg inside image; create and copy to file jpeg
244 int extractJPEG( fullPath *image, fullPath *jpeg )
245 {
246         file_spec                               fnum;
247         long                                    count;
248         unsigned char*                  im;
249         int                                     i, idx = -1;
250         unsigned char                   ch;
251                 
252         if( myopen( image, read_bin, fnum ) )
253                 return -1;
254         
255         
256         count = 1; i=0; // Get file length
257         
258         while( count == 1 )
259         {
260                 myread(  fnum, count, &ch ); 
261                 if(count==1) i++;
262         }
263         myclose(fnum);
264
265         count = i;
266         
267         im = (UCHAR*)malloc( count );
268         if( im == NULL )
269         {
270                 PrintError("Not enough memory");
271                 return -1;
272         }
273         
274         if( myopen( image, read_bin, fnum ) )
275                 return -1;
276                 
277         myread(fnum,count,im);
278         myclose(fnum);
279         
280         if( i != count )
281                 return -1;
282         
283         count -= ID_LENGTH;
284                 
285         for(i=0; i<count; i++)
286         {
287                 if( im[i] == ID_0 && im[i+1] == ID_1 && im[i+2] == ID_2 && im[i+3] == ID_3 
288                                         && im[i+4] == ID_4 && im[i+5] == ID_5 && im[i+6] == ID_6 && im[i+7] == ID_7
289                                         && im[i+8] == ID_8 && im[i+9] == ID_9 && im[i+10] == ID_10)
290                                 idx = i;
291         }
292
293         if( idx == -1 ) // No jpeg found
294         {
295                 free(im);
296                 return -1;
297         }
298         
299         count = count + ID_LENGTH - idx;
300         
301         mycreate( jpeg, 'GKON','JPEG');
302         if( myopen( jpeg, write_bin, fnum ) )
303                 return -1;
304         mywrite( fnum, count, im+idx );
305         free( im );
306         myclose( fnum );
307         return 0;
308 }
309                 
310
311 /*
312  * vim: set tabstop=4 softtabstop=4 shiftwidth=4 :
313  */