Huge change, and it's almost working, too :)
[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 #include "utils_image.h"
26
27 #define DEG_TO_RAD(x) ((x) * 2.0 * M_PI / 360.0 )
28
29 // Lookup Tables for Trig-functions and interpolator
30
31 #define NATAN 2048
32 #define NSQRT 2048
33
34 static void matrix_matrix_mult( double m1[3][3],double m2[3][3],double result[3][3])
35 {
36         int i,k;
37         
38         for(i=0;i<3;i++)
39                 for(k=0; k<3; k++)
40                         result[i][k] = m1[i][0] * m2[0][k] + m1[i][1] * m2[1][k] + m1[i][2] * m2[2][k];
41 } /* void matrix_matrix_mult */
42
43 /* Set matrix elements based on Euler angles a, b, c */
44 static void set_transformation_matrix (double m[3][3],
45                 double a, double b, double c)
46 {
47         double mx[3][3], my[3][3], mz[3][3], dummy[3][3];
48         
49
50         // Calculate Matrices;
51
52         mx[0][0] = 1.0 ;                                mx[0][1] = 0.0 ;                                mx[0][2] = 0.0;
53         mx[1][0] = 0.0 ;                                mx[1][1] = cos(a) ;                     mx[1][2] = sin(a);
54         mx[2][0] = 0.0 ;                                mx[2][1] =-mx[1][2] ;                   mx[2][2] = mx[1][1];
55         
56         my[0][0] = cos(b);                              my[0][1] = 0.0 ;                                my[0][2] =-sin(b);
57         my[1][0] = 0.0 ;                                my[1][1] = 1.0 ;                                my[1][2] = 0.0;
58         my[2][0] = -my[0][2];                   my[2][1] = 0.0 ;                                my[2][2] = my[0][0];
59         
60         mz[0][0] = cos(c) ;                     mz[0][1] = sin(c) ;                     mz[0][2] = 0.0;
61         mz[1][0] =-mz[0][1] ;                   mz[1][1] = mz[0][0] ;                   mz[1][2] = 0.0;
62         mz[2][0] = 0.0 ;                                mz[2][1] = 0.0 ;                                mz[2][2] = 1.0;
63
64         /* Calculate `m = mz * mx * my' */
65
66         matrix_matrix_mult( mz, mx,     dummy);
67         matrix_matrix_mult( dummy, my, m);
68 } /* void SetMatrix */
69
70 /*
71  * Extract image from pano in TrPtr->src using parameters in prefs (ignore
72  * image parameters in TrPtr)
73  */
74 typedef enum interpolator_e
75 {
76         NNEIGHBOUR,
77         BILINEAR
78 } interpolator_t;
79
80 static int copy_pixel (ui_image_t *dest, const ui_image_t *src,
81                 int x_dest, int y_dest,
82                 double x_src_fp, double y_src_fp,
83                 interpolator_t interp)
84 {
85         uint32_t pixel_dest = (y_dest * dest->width) + x_dest;
86
87         interp = NNEIGHBOUR;
88
89         if (interp == NNEIGHBOUR)
90         {
91                 int x_src = (int) (x_src_fp + 0.5) % src->width;
92                 int y_src = (int) (y_src_fp + 0.5) % src->height;
93
94                 if ((x_src < 0) || (x_src >= src->width)
95                                 || (y_src < 0) || (y_src >= src->height))
96                 {
97                         dest->data[0][pixel_dest] = 0;
98                         dest->data[1][pixel_dest] = 0;
99                         dest->data[2][pixel_dest] = 0;
100                 }
101                 else
102                 {
103                         uint32_t pixel_src = (y_src * src->width) + x_src;
104
105                         dest->data[0][pixel_dest] = src->data[0][pixel_src];
106                         dest->data[1][pixel_dest] = src->data[1][pixel_src];
107                         dest->data[2][pixel_dest] = src->data[2][pixel_src];
108                 }
109         }
110
111         return (0);
112 } /* int copy_pixel */
113
114 //    Main transformation function. Destination image is calculated using transformation
115 //    Function "func". Either all colors (color = 0) or one of rgb (color =1,2,3) are
116 //    determined. If successful, TrPtr->success = 1. Memory for destination image
117 //    must have been allocated and locked!
118
119 int pl_extract_view (ui_image_t *view, const ui_image_t *pano,
120                 double pitch, double yaw, double fov)
121 {
122         int x_dest, y_dest; // Loop through destination image
123
124         int dest_width_left = view->width  / 2 ;  
125         int dest_height_top = view->height / 2 ;
126         int src_width_left =  pano->width   / 2 ;
127         int src_height_top =  pano->height  / 2 ;
128         
129         double v[3];
130         int     x_min, x_max, y_min, y_max;
131
132         /* The transformation matrix */
133         double tm[3][3];
134
135         double dist_r;
136         double dist_e;
137
138         { /* What the fuck does this? -octo */
139                 double a = DEG_TO_RAD (fov);
140                 double b = 2.0 * M_PI; /* DEG_TO_RAD (360.0) */
141
142                 dist_r = ((double) view->width) / (2.0 * tan (a / 2.0));
143                 dist_e = ((double) pano->width) / b;
144         }
145
146         set_transformation_matrix (tm, DEG_TO_RAD (pitch), DEG_TO_RAD (yaw), 0.0);
147
148         x_min = -dest_width_left; x_max = view->width - dest_width_left;
149         y_min = -dest_height_top; y_max = view->height - dest_height_top;
150
151         for(y_dest = y_min; y_dest < y_max; y_dest++)
152         {
153                 for(x_dest = x_min; x_dest < x_max; x_dest++)
154                 {
155                         double x_src_fp;
156                         double y_src_fp;
157
158                         v[0] = tm[0][0] * x_dest + tm[1][0] * y_dest + tm[2][0] * dist_r;
159                         v[1] = tm[0][1] * x_dest + tm[1][1] * y_dest + tm[2][1] * dist_r;
160                         v[2] = tm[0][2] * x_dest + tm[1][2] * y_dest + tm[2][2] * dist_r;
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 (view, pano,
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 (0);
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 #define ID_0 0xff
191 #define ID_1 0xd8
192 #define ID_2 0xff
193 #define ID_3 0xe0
194 #define ID_4 0x00
195 #define ID_5 0x10
196 #define ID_6 0x4a
197 #define ID_7 0x46
198 #define ID_8 0x49
199 #define ID_9 0x46
200 #define ID_10 0x00
201
202 #define ID_LENGTH 11
203
204 // Find last jpeg inside image; create and copy to file jpeg
205 int extractJPEG( fullPath *image, fullPath *jpeg )
206 {
207         file_spec                               fnum;
208         long                                    count;
209         unsigned char*                  im;
210         int                                     i, idx = -1;
211         unsigned char                   ch;
212                 
213         if( myopen( image, read_bin, fnum ) )
214                 return -1;
215         
216         
217         count = 1; i=0; // Get file length
218         
219         while( count == 1 )
220         {
221                 myread(  fnum, count, &ch ); 
222                 if(count==1) i++;
223         }
224         myclose(fnum);
225
226         count = i;
227         
228         im = (UCHAR*)malloc( count );
229         if( im == NULL )
230         {
231                 PrintError("Not enough memory");
232                 return -1;
233         }
234         
235         if( myopen( image, read_bin, fnum ) )
236                 return -1;
237                 
238         myread(fnum,count,im);
239         myclose(fnum);
240         
241         if( i != count )
242                 return -1;
243         
244         count -= ID_LENGTH;
245                 
246         for(i=0; i<count; i++)
247         {
248                 if( im[i] == ID_0 && im[i+1] == ID_1 && im[i+2] == ID_2 && im[i+3] == ID_3 
249                                         && im[i+4] == ID_4 && im[i+5] == ID_5 && im[i+6] == ID_6 && im[i+7] == ID_7
250                                         && im[i+8] == ID_8 && im[i+9] == ID_9 && im[i+10] == ID_10)
251                                 idx = i;
252         }
253
254         if( idx == -1 ) // No jpeg found
255         {
256                 free(im);
257                 return -1;
258         }
259         
260         count = count + ID_LENGTH - idx;
261         
262         mycreate( jpeg, 'GKON','JPEG');
263         if( myopen( jpeg, write_bin, fnum ) )
264                 return -1;
265         mywrite( fnum, count, im+idx );
266         free( im );
267         myclose( fnum );
268         return 0;
269 }
270                 
271
272 /*
273  * vim: set tabstop=4 softtabstop=4 shiftwidth=4 :
274  */