Hugintrunk  0.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
TexCoordRemapper.cpp
Go to the documentation of this file.
1 // -*- c-basic-offset: 4 -*-
2 
23 #ifdef __WXMAC__
24 #include "panoinc_WX.h"
25 #include "panoinc.h"
26 #endif
27 
28 #include "TexCoordRemapper.h"
30 #include "ViewState.h"
31 
32 // higher values make the mesh more detailed, but slower and using more memory:
33 // Value is in faces per pixel in each direction, so it should be positive and
34 // less than 1. Faces will be around this size, approximately square.
35 const double mesh_frequency = 0.07;
36 
39  VisualizationState *visualization_state)
40  : MeshRemapper(m_pano, image, visualization_state)
41 {
42 
43 }
44 
46 {
47  // work what area we should cover in what detail.
48  SetSize();
49  // we want to make a remapped mesh, get the transformation we need:
50 // HuginBase::SrcPanoImage *src_img = visualization_state->GetSrcImage(image_number);
52 // DEBUG_INFO("updating mesh for image " << image_number
53 // << ", using faces spaced about " << scale << " units apart.\n");
54  // fill the map with transformed points.
55  for (unsigned int x = 0; x < divisions_x; x++)
56  {
57  for (unsigned int y = 0; y < divisions_y; y++)
58  {
60  map[x][y].y,
61  (double) x * face_width + start_x,
62  (double) y * face_height + start_y);
63  // texture coordinates on the image range from 0 to 1.
64  map[x][y].x /= width;
65  map[x][y].y /= height;
66  }
67  }
68  face_index = 0;
69  SetCrop();
70 }
71 
73 {
74  result->tex_c = texture_coords;
75  result->vertex_c = vertex_coords;
76  // return any remaining results of a previous clipping operation.
77  if (GiveClipFaceResult(result)) return true;
78  // try to find a face that is at least partly covered by the image.
79  while (true)
80  {
81  if (face_index == number_of_faces) return false;
82  unsigned int x_f = face_index % (divisions_x - 1),
83  y_f = face_index / (divisions_x - 1);
84  bool all_left = true, all_right = true,
85  all_above = true, all_below = true;
86  for (unsigned short int x = 0; x < 2; x++)
87  {
88  for (unsigned short int y = 0; y < 2; y++)
89  {
90  unsigned int xt = x_f + x, yt = y_f + y;
91  if (map[xt][yt].x > crop_x1) all_left = false;
92  if (map[xt][yt].x < crop_x2) all_right = false;
93  if (map[xt][yt].y > crop_y1) all_above = false;
94  if (map[xt][yt].y < crop_y2) all_below = false;
95  }
96  }
97  /* check if this quad shows any of the input image.
98  * We could possibly drop some more faces, but this is a pretty good
99  * optimisation by itself. Proper clipping will alert us otherwise.
100  */
101  if (!(all_left || all_right || all_above || all_below)) break;
102  face_index++;
103  }
104  // now set the coordinates.
105  unsigned int x_f = face_index % (divisions_x - 1),
106  y_f = face_index / (divisions_x - 1);
107  for (unsigned short int x = 0; x < 2; x++)
108  {
109  for (unsigned short int y = 0; y < 2; y++)
110  {
111  unsigned int xt = x_f + x, yt = y_f + y;
112  result->tex_c[x][y][0] = map[xt][yt].x;
113  result->tex_c[x][y][1] = map[xt][yt].y;
114  result->vertex_c[x][y][0] = (double) xt * face_width + start_x;
115  result->vertex_c[x][y][1] = (double) yt * face_height + start_y;
116  }
117  }
118  face_index++;
119  /* Since we only crop to convex regions, having all four points inside the
120  * wanted region implies we don't need to do any clipping. It should be
121  * faster to test for this and skip full clipping in that case, as the vast
122  * majority of faces will not need any clipping or fail the test above.
123  */
124 // HuginBase::SrcPanoImage *src_img = visualization_state->GetSrcImage(image_number);
125  if ( image->isInside(vigra::Point2D(int(result->tex_c[0][0][0] * width),
126  int(result->tex_c[0][0][1] * height)))
127  && image->isInside(vigra::Point2D(int(result->tex_c[0][1][0] * width),
128  int(result->tex_c[0][1][1] * height)))
129  && image->isInside(vigra::Point2D(int(result->tex_c[1][0][0] * width),
130  int(result->tex_c[1][0][1] * height)))
131  && image->isInside(vigra::Point2D(int(result->tex_c[1][1][0] * width),
132  int(result->tex_c[1][1][1] * height))))
133  {
134  // all inside, doesn't need clipping.
135  /* FIXME Alber's equal area conic projection needs to be clipped to the
136  * sides space in the output that maps to the panorama...
137  */
138  return true;
139  }
140  /* We have to clip the face to the source image. This may produce many faces
141  * or none, so we store a list and pop elements off it until the list is
142  * empty, or try from the top in the case we get none.
143  */
144  ClipFace(result);
145  if (GiveClipFaceResult(result))
146  {
147  return true;
148  } else {
149  return GetNextFaceCoordinates(result);
150  }
151 }
152 
154 {
155 // const HuginBase::SrcPanoImage *src = visualization_state->GetSrcImage(image_number);
156  width = (double) image->getSize().width();
157  height = (double) image->getSize().height();
158  // set the bounding rectangle.
159  // FIXME
160  // 1. If there is an efficient way to find a good bounding rectangle, use it
161  // (I had a look at ComputeImageROI but seemed a bit brute force)
162  // 2. With zooming, we could clip the stuff off the edge of the screen.
163  // For now we stick with everything that is visible.
164  vigra::Rect2D visible_area = visualization_state->GetVisibleArea();
165  start_x = (double) visible_area.left() - 0.5;
166  start_y = (double) visible_area.top() - 0.5;
167  end_x = (double) visible_area.right() - 0.5;
168  end_y = (double) visible_area.bottom() - 0.5;
169  o_width = end_x - start_x;
170  o_height = end_y - start_y;
171  // use the scale to determine edge lengths in pixels for subdivision
173  // round the number of divisions we need to get a whole number of faces
174  divisions_x = (int) ((end_x - start_x) * scale + 0.5);
175  if (divisions_x < 2) divisions_x = 2;
176  divisions_y = (int) ((end_y - start_y) * scale + 0.5);
177  if (divisions_y < 2) divisions_y = 2;
178  // the face height and width uses the rounded number, we don't want gaps at
179  // the edges of the panorama. Therefore scale is approximate now.
180  /* FIXME there is a line on the bottom edge when an image covers the top
181  * pole in equirectangular sometimes. These will get clipped, but it means
182  * extra stuff is being done along a wrong edge.
183  */
184  // the minus 1 is because we need the last division to cover the far edge.
185  // note we have divisions_x - 1 faces to cover the divisions_x vertices.
186  face_width = o_width / (double) (divisions_x - 1);
187  face_height = o_height / (double) (divisions_y - 1);
188  // work out the number of faces.
189  number_of_faces = (divisions_x - 1) * (divisions_y - 1);
190  // resize our data stucture for holding the vertex locations.
191  map.resize(divisions_x);
192  for (unsigned int column = 0; column < divisions_x; column++)
193  {
194  map[column].resize(divisions_y);
195  }
196 }
197 
bool GiveClipFaceResult(Coords *result)
Get a face that was produced by ClipFace.
double vertex_coords[2][2][2]
An abstract base class for objects that calculate an approximate remap specified by quadrilatrials...
Definition: MeshRemapper.h:43
unsigned int face_index
TexCoordRemapper(HuginBase::Panorama *m_pano, HuginBase::SrcPanoImage *image, VisualizationState *visualization_state)
double crop_x1
Definition: MeshRemapper.h:100
double crop_x2
Definition: MeshRemapper.h:100
A class for exchanging pointers to coordinates.
Definition: MeshRemapper.h:60
HuginBase::SrcPanoImage * image
Definition: MeshRemapper.h:85
include file for the hugin project
double(* tex_c)[2][2]
The coordinate in the source image ranging from 0 to 1.
Definition: MeshRemapper.h:64
bool isInside(vigra::Point2D p, bool ignoreMasks=false) const
check if a coordinate is inside the source image
VisualizationState * visualization_state
Definition: MeshRemapper.h:83
Model for a panorama.
Definition: Panorama.h:152
void ClipFace(Coords *face)
Crop a face to the source image, return true if there is anything left.
std::vector< std::vector< hugin_utils::FDiff2D > > map
const double mesh_frequency
void SetCrop()
Fill the crop values of the MeshRemapper from the source image.
vigra::Rect2D GetVisibleArea()
Definition: ViewState.h:222
double height
The sizes of the input images in pixels.
Definition: MeshRemapper.h:94
double crop_y1
Definition: MeshRemapper.h:100
float scale
The number number of units between vertex coorinates that gives a pixel in the display.
Definition: MeshRemapper.h:89
unsigned int divisions_y
unsigned int number_of_faces
HuginBase::PTools::Transform transform
A transform to use to remap the images.
Definition: MeshRemapper.h:96
include file for the hugin project
bool transformImgCoord(double &x_dest, double &y_dest, double x_src, double y_src) const
like transform, but return image coordinates, not cartesian coordinates
virtual HuginBase::PanoramaOptions * GetOptions()
Definition: ViewState.cpp:468
double width
Definition: MeshRemapper.h:94
double crop_y2
Definition: MeshRemapper.h:100
virtual bool GetNextFaceCoordinates(Coords *result)
Get the texture and vertex coordinates for the next face.
virtual void UpdateAndResetIndex()
unsigned int divisions_x
double(* vertex_c)[2][2]
The coordinate in the panorama, in its pixel space.
Definition: MeshRemapper.h:66
All variables of a source image.
Definition: SrcPanoImage.h:194
void createTransform(const vigra::Diff2D &srcSize, VariableMap srcVars, Lens::LensProjectionFormat srcProj, const vigra::Diff2D &destSize, PanoramaOptions::ProjectionFormat destProj, const std::vector< double > &destProjParam, double destHFOV, const vigra::Diff2D &origSrcSize)
initialize pano-&gt;image transformation
double texture_coords[2][2][2]