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 #include "panoinc_WX.h"
24 #include "panoinc.h"
25 #include "TexCoordRemapper.h"
27 #include "ViewState.h"
28 
29 // higher values make the mesh more detailed, but slower and using more memory:
30 // Value is in faces per pixel in each direction, so it should be positive and
31 // less than 1. Faces will be around this size, approximately square.
32 const double mesh_frequency = 0.07;
33 
36  VisualizationState *visualization_state)
37  : MeshRemapper(m_pano, image, visualization_state)
38 {
39 
40 }
41 
43 {
44  // work what area we should cover in what detail.
45  SetSize();
46  // we want to make a remapped mesh, get the transformation we need:
47 // HuginBase::SrcPanoImage *src_img = visualization_state->GetSrcImage(image_number);
49 // DEBUG_INFO("updating mesh for image " << image_number
50 // << ", using faces spaced about " << scale << " units apart.\n");
51  // fill the map with transformed points.
52  for (unsigned int x = 0; x < divisions_x; x++)
53  {
54  for (unsigned int y = 0; y < divisions_y; y++)
55  {
57  map[x][y].y,
58  (double) x * face_width + start_x,
59  (double) y * face_height + start_y);
60  // texture coordinates on the image range from 0 to 1.
61  map[x][y].x /= width;
62  map[x][y].y /= height;
63  }
64  }
65  face_index = 0;
66  SetCrop();
67 }
68 
70 {
71  result->tex_c = texture_coords;
72  result->vertex_c = vertex_coords;
73  // return any remaining results of a previous clipping operation.
74  if (GiveClipFaceResult(result)) return true;
75  // try to find a face that is at least partly covered by the image.
76  while (true)
77  {
78  if (face_index == number_of_faces) return false;
79  unsigned int x_f = face_index % (divisions_x - 1),
80  y_f = face_index / (divisions_x - 1);
81  bool all_left = true, all_right = true,
82  all_above = true, all_below = true;
83  for (unsigned short int x = 0; x < 2; x++)
84  {
85  for (unsigned short int y = 0; y < 2; y++)
86  {
87  unsigned int xt = x_f + x, yt = y_f + y;
88  if (map[xt][yt].x > crop_x1) all_left = false;
89  if (map[xt][yt].x < crop_x2) all_right = false;
90  if (map[xt][yt].y > crop_y1) all_above = false;
91  if (map[xt][yt].y < crop_y2) all_below = false;
92  }
93  }
94  /* check if this quad shows any of the input image.
95  * We could possibly drop some more faces, but this is a pretty good
96  * optimisation by itself. Proper clipping will alert us otherwise.
97  */
98  if (!(all_left || all_right || all_above || all_below)) break;
99  face_index++;
100  }
101  // now set the coordinates.
102  unsigned int x_f = face_index % (divisions_x - 1),
103  y_f = face_index / (divisions_x - 1);
104  for (unsigned short int x = 0; x < 2; x++)
105  {
106  for (unsigned short int y = 0; y < 2; y++)
107  {
108  unsigned int xt = x_f + x, yt = y_f + y;
109  result->tex_c[x][y][0] = map[xt][yt].x;
110  result->tex_c[x][y][1] = map[xt][yt].y;
111  result->vertex_c[x][y][0] = (double) xt * face_width + start_x;
112  result->vertex_c[x][y][1] = (double) yt * face_height + start_y;
113  }
114  }
115  face_index++;
116  /* Since we only crop to convex regions, having all four points inside the
117  * wanted region implies we don't need to do any clipping. It should be
118  * faster to test for this and skip full clipping in that case, as the vast
119  * majority of faces will not need any clipping or fail the test above.
120  */
121 // HuginBase::SrcPanoImage *src_img = visualization_state->GetSrcImage(image_number);
122  if ( image->isInside(vigra::Point2D(int(result->tex_c[0][0][0] * width),
123  int(result->tex_c[0][0][1] * height)))
124  && image->isInside(vigra::Point2D(int(result->tex_c[0][1][0] * width),
125  int(result->tex_c[0][1][1] * height)))
126  && image->isInside(vigra::Point2D(int(result->tex_c[1][0][0] * width),
127  int(result->tex_c[1][0][1] * height)))
128  && image->isInside(vigra::Point2D(int(result->tex_c[1][1][0] * width),
129  int(result->tex_c[1][1][1] * height))))
130  {
131  // all inside, doesn't need clipping.
132  /* FIXME Alber's equal area conic projection needs to be clipped to the
133  * sides space in the output that maps to the panorama...
134  */
135  return true;
136  }
137  /* We have to clip the face to the source image. This may produce many faces
138  * or none, so we store a list and pop elements off it until the list is
139  * empty, or try from the top in the case we get none.
140  */
141  ClipFace(result);
142  if (GiveClipFaceResult(result))
143  {
144  return true;
145  } else {
146  return GetNextFaceCoordinates(result);
147  }
148 }
149 
151 {
152 // const HuginBase::SrcPanoImage *src = visualization_state->GetSrcImage(image_number);
153  width = (double) image->getSize().width();
154  height = (double) image->getSize().height();
155  // set the bounding rectangle.
156  // FIXME
157  // 1. If there is an efficient way to find a good bounding rectangle, use it
158  // (I had a look at ComputeImageROI but seemed a bit brute force)
159  // 2. With zooming, we could clip the stuff off the edge of the screen.
160  // For now we stick with everything that is visible.
161  vigra::Rect2D visible_area = visualization_state->GetVisibleArea();
162  start_x = (double) visible_area.left() - 0.5;
163  start_y = (double) visible_area.top() - 0.5;
164  end_x = (double) visible_area.right() - 0.5;
165  end_y = (double) visible_area.bottom() - 0.5;
166  o_width = end_x - start_x;
167  o_height = end_y - start_y;
168  // use the scale to determine edge lengths in pixels for subdivision
170  // round the number of divisions we need to get a whole number of faces
171  divisions_x = (int) ((end_x - start_x) * scale + 0.5);
172  if (divisions_x < 2) divisions_x = 2;
173  divisions_y = (int) ((end_y - start_y) * scale + 0.5);
174  if (divisions_y < 2) divisions_y = 2;
175  // the face height and width uses the rounded number, we don't want gaps at
176  // the edges of the panorama. Therefore scale is approximate now.
177  /* FIXME there is a line on the bottom edge when an image covers the top
178  * pole in equirectangular sometimes. These will get clipped, but it means
179  * extra stuff is being done along a wrong edge.
180  */
181  // the minus 1 is because we need the last division to cover the far edge.
182  // note we have divisions_x - 1 faces to cover the divisions_x vertices.
183  face_width = o_width / (double) (divisions_x - 1);
184  face_height = o_height / (double) (divisions_y - 1);
185  // work out the number of faces.
186  number_of_faces = (divisions_x - 1) * (divisions_y - 1);
187  // resize our data stucture for holding the vertex locations.
188  map.resize(divisions_x);
189  for (unsigned int column = 0; column < divisions_x; column++)
190  {
191  map[column].resize(divisions_y);
192  }
193 }
194 
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]