Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/*------------------------------------------------------------*/
+#include <stdlib.h>
+#include <stdint.h>
+#include <assert.h>
+
#include "filter.h"
+#include "utils_math.h"
+#include "utils_image.h"
+#define DEG_TO_RAD(x) ((x) * 2.0 * M_PI / 360.0 )
// Lookup Tables for Trig-functions and interpolator
#define NATAN 2048
#define NSQRT 2048
-int *atan_LU;
-int *sqrt_LU;
-int *mweights[256];
-
-
-void matrix_matrix_mult ( double m1[3][3],double m2[3][3],double result[3][3]);
-void PV_transForm( TrformStr *TrPtr, int dist_r, int dist_e, int mt[3][3]);
-int PV_atan2(int y, int x);
-int PV_sqrt( int x1, int x2 );
-
-
-// Bilinear interpolator
-
-static void bil( unsigned char *dst, unsigned char **rgb,
- int dx,int dy)
-{
- int yr, yg, yb,weight;
- int rd, gd, bd ;
- register unsigned char *r;
- int *w1, *w2;
-
-
- w1 = mweights[dx]; w2 = mweights[255 - dx];
-
- r = rgb[0] + 1;
-
- rd = w2[*r++]; gd = w2[*r++]; bd = w2[*r++];
- //weight = 255 - dx; rd = weight * *r++; gd = weight * *r++; bd = weight * *r++;
-
- r++;
- rd += w1[*r++]; gd += w1[*r++]; bd += w1[*r];
- //rd += dx * *r++; gd += dx * *r++; bd += dx * *r;
-
-
- r = rgb[1] + 1;
-
- yr = w2[*r++]; yg = w2[*r++]; yb = w2[*r++];
- //rd = weight * *r++; gd = weight * *r++; bd = weight * *r++;
-
- r++;
- yr += w1[*r++]; yg += w1[*r++]; yb += w1[*r];
- //rd += dx * *r++; gd += dx * *r++; bd += dx * *r;
-
- weight = 255 - dy;
- rd = rd * weight + yr * dy;
- gd = gd * weight + yg * dy;
- bd = bd * weight + yb * dy;
-
- *dst++ = rd >> 16;
- *dst++ = gd >> 16;
- *dst = bd >> 16;
-}
-
-
-
-// Extract image from pano in TrPtr->src
-// using parameters in prefs (ignore image parameters
-// in TrPtr)
-
-void PV_ExtractStill( TrformStr *TrPtr )
-{
- double a,b; // field of view in rad
- double p[2];
- double mt[3][3];
- int mi[3][3],i,k;
-
- TrPtr->success = 1;
-
- a = DEG_TO_RAD( TrPtr->dest->hfov ); // field of view in rad
- b = DEG_TO_RAD( TrPtr->src->hfov );
-
- SetMatrix( DEG_TO_RAD( TrPtr->dest->pitch ),
- DEG_TO_RAD( TrPtr->dest->yaw ),
- 0.0 ,
- mt,
- 1 );
-
-
- p[0] = (double)TrPtr->dest->width/ (2.0 * tan( a / 2.0 ) );
- p[1] = (double)TrPtr->src->width/ b;
-
- for(i=0; i<3; i++){
- for(k=0; k<3; k++){
- mi[i][k] = 256 * mt[i][k];
- }
- }
-
-
- PV_transForm( TrPtr, (int)(p[0]+.5), (int)(p[1]+.5), mi);
- return;
-}
-
-
-
-
-
-// Main transformation function. Destination image is calculated using transformation
-// Function "func". Either all colors (color = 0) or one of rgb (color =1,2,3) are
-// determined. If successful, TrPtr->success = 1. Memory for destination image
-// must have been allocated and locked!
-
-void PV_transForm( TrformStr *TrPtr, int dist_r, int dist_e, int mt[3][3])
-{
- register int x, y; // Loop through destination image
- unsigned char *dest,*src,*sry, *dst;// Source and destination image data
- long cy; // rownum in destimage
- int dx,dy;
-
- int xc; // Cartesian Coordinates of point ("target") in Destination image
- int xs, ys;
-
- unsigned char *rgb[2] ,
- cdata[16]; // Image data handed to sampler
-
-
- int mix = TrPtr->src->width - 1; // maximum x-index src
- int miy = TrPtr->src->height - 1;// maximum y-index src
-
- // Variables used to convert screen coordinates to cartesian coordinates
-
-
- int w2 = TrPtr->dest->width / 2 ;
- int h2 = TrPtr->dest->height / 2 ;
- int sw2 = TrPtr->src->width / 2 ;
- int sh2 = TrPtr->src->height / 2 ;
-
- int BytesPerLine = TrPtr->src->bytesPerLine;
- int v[3];
- int x_min, x_max, y_min, y_max;
-
- int dr1, dr2, dr3;
-
- dr1 = mt[2][0] * dist_r;
- dr2 = mt[2][1] * dist_r;
- dr3 = mt[2][2] * dist_r;
-
-
-
-
-
- dest = *TrPtr->dest->data;
- src = *TrPtr->src->data; // is locked
-
- x_min = -w2; x_max = TrPtr->dest->width - w2;
- y_min = -h2; y_max = TrPtr->dest->height - h2;
-
- cy = 0;
-
- if( TrPtr->interpolator == _bilinear )
- {
- for(y = y_min; y < y_max; y++, cy+=TrPtr->dest->bytesPerLine)
- {
- dst = dest + cy + 1;
- for(x = x_min; x < x_max; x++, dst+=4)
- {
- v[0] = mt[0][0] * x + mt[1][0] * y + dr1;
- v[1] = mt[0][1] * x + mt[1][1] * y + dr2;
- v[2] = mt[0][2] * x + mt[1][2] * y + dr3;
-
- v[0] = v[0] >> 8; v[2] = v[2] >> 8;
-
- xs = dist_e * PV_atan2( v[0], v[2] ) / NATAN ;
-
- ys = dist_e * PV_atan2( v[1], PV_sqrt( abs(v[2]), abs(v[0]) ) ) / NATAN ;
-
- dx = xs & 255; dy = ys & 255; // fraction
-
-
- xs = (xs >> 8) + sw2;
- ys = (ys >> 8) + sh2;
-
-
- if( ys >= 0 && ys < miy && xs >= 0 && xs < mix ) // all interpolation pixels inside image
- // (most pixels)
- {
- sry = src + ys * BytesPerLine + xs * 4;
- rgb[0] = sry;
- rgb[1] = sry + BytesPerLine;
- }
- else // edge pixels
- {
- xc = xs;
-
- rgb[0] = cdata;
- if( ys < 0 )
- sry = src;
- else if( ys > miy )
- sry = src + miy * BytesPerLine;
- else
- sry = src + ys * BytesPerLine;
-
- if( xs < 0 ) xs = mix;
- if( xs > mix) xs = 0;
- *(long*)rgb[0] = *(long*)(sry + xs*4);
-
- xs = xc+1;
- if( xs < 0 ) xs = mix;
- if( xs > mix) xs = 0;
- *(long*)(rgb[0]+4) = *(long*)(sry + xs*4);
-
-
-
- rgb[1] = cdata+8;
- ys+=1;
- if( ys < 0 )
- sry = src;
- else if( ys > miy )
- sry = src + miy * BytesPerLine;
- else
- sry = src + ys * BytesPerLine;
- xs = xc;
- if( xs < 0 ) xs = mix;
- if( xs > mix) xs = 0;
- *(long*)rgb[1] = *(long*)(sry + xs*4);
- xs = xc+1;
- if( xs < 0 ) xs = mix;
- if( xs > mix) xs = 0;
- *(long*)(rgb[1]+4) = *(long*)(sry + xs*4);
-
-
- }
- bil( dst, rgb, dx, dy );
- }
- }
- }
- else if( TrPtr->interpolator == _nn )
- {
- for(y = y_min; y < y_max; y++, cy+=TrPtr->dest->bytesPerLine)
- {
- dst = dest + cy;
- for(x = x_min; x < x_max; x++, dst+=4)
- {
- v[0] = mt[0][0] * x + mt[1][0] * y + dr1;
- v[1] = mt[0][1] * x + mt[1][1] * y + dr2;
- v[2] = mt[0][2] * x + mt[1][2] * y + dr3;
-
- v[0] = v[0] >> 8; v[2] = v[2] >> 8;
-
- xs = dist_e * PV_atan2( v[0], v[2] ) / NATAN ;
-
- ys = dist_e * PV_atan2( v[1], PV_sqrt( abs(v[2]), abs(v[0]) ) ) / NATAN ;
-
- dx = xs & 255; dy = ys & 255; // fraction
-
-
- xs = (xs >> 8) + sw2;
- ys = (ys >> 8) + sh2;
-
- if( xs < 0 ) xs = 0;
- if( xs > mix ) xs = mix;
- if( ys < 0) ys = 0;
- if( ys > miy ) ys = miy;
-
- *(long*)dst = *(long*)(src + ys * BytesPerLine + xs * 4);
- }
- }
- }
-
- TrPtr->success = 1;
- return;
-}
-
-
-void matrix_inv_mult( double m[3][3], double vector[3] )
+static void matrix_matrix_mult( double m1[3][3],double m2[3][3],double result[3][3])
{
- register int i;
- register double v0 = vector[0];
- register double v1 = vector[1];
- register double v2 = vector[2];
+ int i,k;
- for(i=0; i<3; i++)
- {
- vector[i] = m[0][i] * v0 + m[1][i] * v1 + m[2][i] * v2;
- }
-}
-
-// Set matrix elements based on Euler angles a, b, c
+ for(i=0;i<3;i++)
+ for(k=0; k<3; k++)
+ result[i][k] = m1[i][0] * m2[0][k] + m1[i][1] * m2[1][k] + m1[i][2] * m2[2][k];
+} /* void matrix_matrix_mult */
-void SetMatrix( double a, double b, double c , double m[3][3], int cl )
+/* Set matrix elements based on Euler angles a, b, c */
+static void set_transformation_matrix (double m[3][3],
+ double a, double b, double c)
{
double mx[3][3], my[3][3], mz[3][3], dummy[3][3];
mz[1][0] =-mz[0][1] ; mz[1][1] = mz[0][0] ; mz[1][2] = 0.0;
mz[2][0] = 0.0 ; mz[2][1] = 0.0 ; mz[2][2] = 1.0;
- if( cl )
- matrix_matrix_mult( mz, mx, dummy);
- else
- matrix_matrix_mult( mx, mz, dummy);
+ /* Calculate `m = mz * mx * my' */
+
+ matrix_matrix_mult( mz, mx, dummy);
matrix_matrix_mult( dummy, my, m);
-}
+} /* void SetMatrix */
-void matrix_matrix_mult( double m1[3][3],double m2[3][3],double result[3][3])
+/*
+ * Extract image from pano in TrPtr->src using parameters in prefs (ignore
+ * image parameters in TrPtr)
+ */
+typedef enum interpolator_e
{
- register int i,k;
-
- for(i=0;i<3;i++)
- {
- for(k=0; k<3; k++)
- {
- result[i][k] = m1[i][0] * m2[0][k] + m1[i][1] * m2[1][k] + m1[i][2] * m2[2][k];
- }
- }
-}
-
+ NNEIGHBOUR,
+ BILINEAR
+} interpolator_t;
+
+static int copy_pixel (ui_image_t *dest, const ui_image_t *src,
+ int x_dest, int y_dest,
+ double x_src_fp, double y_src_fp,
+ interpolator_t interp)
+{
+ uint32_t pixel_dest = (y_dest * dest->width) + x_dest;
+ interp = NNEIGHBOUR;
-int PV_atan2(int y, int x)
-{
- // return atan2(y,x) * 256*NATAN;
- if( x > 0 )
+ if (interp == NNEIGHBOUR)
{
- if( y > 0 )
+ int x_src = (int) (x_src_fp + 0.5) % src->width;
+ int y_src = (int) (y_src_fp + 0.5) % src->height;
+
+ if ((x_src < 0) || (x_src >= src->width)
+ || (y_src < 0) || (y_src >= src->height))
{
- return atan_LU[(int)( NATAN * y / ( x + y ))];
+ dest->data[0][pixel_dest] = 0;
+ dest->data[1][pixel_dest] = 0;
+ dest->data[2][pixel_dest] = 0;
}
else
{
- return -atan_LU[ (int)(NATAN * (-y) / ( x - y ))];
+ uint32_t pixel_src = (y_src * src->width) + x_src;
+
+ dest->data[0][pixel_dest] = src->data[0][pixel_src];
+ dest->data[1][pixel_dest] = src->data[1][pixel_src];
+ dest->data[2][pixel_dest] = src->data[2][pixel_src];
}
}
- if( x == 0 )
- {
- if( y > 0 )
- return (int)(256*NATAN*PI / 2.0);
- else
- return -(int)(256*NATAN*PI / 2.0);
- }
-
- if( y < 0 )
- {
- return atan_LU[(int)( NATAN * y / ( x + y ))] - (int)(PI*256*NATAN);
- }
- else
- {
- return -atan_LU[ (int)(NATAN * (-y) / ( x - y ))] + (int)(PI*256*NATAN);
- }
-
-}
-
+ return (0);
+} /* int copy_pixel */
+// Main transformation function. Destination image is calculated using transformation
+// Function "func". Either all colors (color = 0) or one of rgb (color =1,2,3) are
+// determined. If successful, TrPtr->success = 1. Memory for destination image
+// must have been allocated and locked!
-int SetUpAtan()
+int pl_extract_view (ui_image_t *view, const ui_image_t *pano,
+ double pitch, double yaw, double fov)
{
- int i;
- double dz = 1.0 / (double)NATAN;
- double z = 0.0;
-
- atan_LU = (int*) malloc( (NATAN+1) * sizeof( int ));
-
- if( atan_LU == NULL )
- return -1;
-
- for( i=0; i< NATAN; i++, z+=dz )
- atan_LU[i] = atan( z / (1.0 - z ) ) * NATAN * 256;
-
- atan_LU[NATAN] = PI/4.0 * NATAN * 256;
-
- // Print a test
-#if 0
- for(i = -10; i< 10; i++)
- {
- int k;
- for(k=-10; k<10; k++)
- {
- printf("i = %d k = %d atan2(i,k) = %g LUatan(i,k) = %g diff = %g\n", i,k,atan2(i,k),
- (double)PV_atan2(i,k) / (256*NATAN) , atan2(i,k) - (double)PV_atan2(i,k) / (256*NATAN));
- }
- }
- exit(0);
-#endif
- return 0;
-}
+ int x_dest, y_dest; // Loop through destination image
-int SetUpSqrt()
-{
- int i;
- double dz = 1.0 / (double)NSQRT;
- double z = 0.0;
+ int dest_width_left = view->width / 2 ;
+ int dest_height_top = view->height / 2 ;
+ int src_width_left = pano->width / 2 ;
+ int src_height_top = pano->height / 2 ;
- sqrt_LU = (int*) malloc( (NSQRT+1) * sizeof( int ));
-
- if( sqrt_LU == NULL )
- return -1;
-
- for( i=0; i< NSQRT; i++, z+=dz )
- sqrt_LU[i] = sqrt( 1.0 + z*z ) * 256 * NSQRT;
-
- sqrt_LU[NSQRT] = sqrt(2.0) * 256 * NSQRT;
-
- return 0;
-}
+ double v[3];
+ int x_min, x_max, y_min, y_max;
-int SetUpMweights()
-{
- int i,k;
-
- for(i=0; i<256; i++)
- {
- mweights[i] = (int*)malloc( 256 * sizeof(int) );
- if( mweights[i] == NULL ) return -1;
+ /* The transformation matrix */
+ double tm[3][3];
+
+ double dist_r;
+ double dist_e;
+
+ { /* What the fuck does this? -octo */
+ double a = DEG_TO_RAD (fov);
+ double b = 2.0 * M_PI; /* DEG_TO_RAD (360.0) */
+
+ dist_r = ((double) view->width) / (2.0 * tan (a / 2.0));
+ dist_e = ((double) pano->width) / b;
}
- for(i=0; i<256; i++)
+
+ set_transformation_matrix (tm, DEG_TO_RAD (pitch), DEG_TO_RAD (yaw), 0.0);
+
+ x_min = -dest_width_left; x_max = view->width - dest_width_left;
+ y_min = -dest_height_top; y_max = view->height - dest_height_top;
+
+ for(y_dest = y_min; y_dest < y_max; y_dest++)
{
- for(k=0; k<256; k++)
+ for(x_dest = x_min; x_dest < x_max; x_dest++)
{
- mweights[i][k] = i*k;
+ double x_src_fp;
+ double y_src_fp;
+
+ v[0] = tm[0][0] * x_dest + tm[1][0] * y_dest + tm[2][0] * dist_r;
+ v[1] = tm[0][1] * x_dest + tm[1][1] * y_dest + tm[2][1] * dist_r;
+ v[2] = tm[0][2] * x_dest + tm[1][2] * y_dest + tm[2][2] * dist_r;
+
+ x_src_fp = dist_e * atan2 (v[0], v[2]);
+ y_src_fp = dist_e * atan2 (v[1], sqrt (v[2] * v[2] + v[0] * v[0]));
+
+ copy_pixel (view, pano,
+ dest_width_left + x_dest, dest_height_top + y_dest,
+ src_width_left + x_src_fp, src_height_top + y_src_fp,
+ NNEIGHBOUR);
}
}
- return 0;
+ return (0);
}
-
-int PV_sqrt( int x1, int x2 )
+#if 0
+void matrix_inv_mult( double m[3][3], double vector[3] )
{
- if( x1 > x2 )
- {
- return x1 * sqrt_LU[ NSQRT * x2 / x1 ] / NSQRT;
- }
- else
+ register int i;
+ register double v0 = vector[0];
+ register double v1 = vector[1];
+ register double v2 = vector[2];
+
+ for(i=0; i<3; i++)
{
- if( x2 == 0 ) return 0;
- return x2 * sqrt_LU[ NSQRT * x1 / x2 ] / NSQRT;
+ vector[i] = m[0][i] * v0 + m[1][i] * v1 + m[2][i] * v2;
}
}
-
+#endif
#define ID_0 0xff
#define ID_1 0xd8
}
+/*
+ * vim: set tabstop=4 softtabstop=4 shiftwidth=4 :
+ */