Developer Documentation
FileHeightFieldImage.cc
1 /*===========================================================================*\
2  * *
3  * OpenFlipper *
4  * Copyright (c) 2001-2015, RWTH-Aachen University *
5  * Department of Computer Graphics and Multimedia *
6  * All rights reserved. *
7  * www.openflipper.org *
8  * *
9  *---------------------------------------------------------------------------*
10  * This file is part of OpenFlipper. *
11  *---------------------------------------------------------------------------*
12  * *
13  * Redistribution and use in source and binary forms, with or without *
14  * modification, are permitted provided that the following conditions *
15  * are met: *
16  * *
17  * 1. Redistributions of source code must retain the above copyright notice, *
18  * this list of conditions and the following disclaimer. *
19  * *
20  * 2. Redistributions in binary form must reproduce the above copyright *
21  * notice, this list of conditions and the following disclaimer in the *
22  * documentation and/or other materials provided with the distribution. *
23  * *
24  * 3. Neither the name of the copyright holder nor the names of its *
25  * contributors may be used to endorse or promote products derived from *
26  * this software without specific prior written permission. *
27  * *
28  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
29  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
30  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
31  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
32  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
33  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
34  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
35  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
36  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
37  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
38  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
39  * *
40 \*===========================================================================*/
41 
42 /*===========================================================================*\
43 * *
44 * $Revision$ *
45 * $LastChangedBy$ *
46 * $Date$ *
47 * *
48 \*===========================================================================*/
49 
50 #include "FileHeightFieldImage.hh"
51 #include "ImageDialog.hh"
52 
53 #if QT_VERSION >= 0x050000
54 #else
55  #include <QtGui>
56 #endif
57 
59 }
60 
62  QList<QByteArray> imageFormats = QImageReader::supportedImageFormats();
63  QString formats;
64 
65  if ( imageFormats.contains("jpeg")) {
66  formats += "*.jpeg *.jpg ";
67  }
68 
69  if ( imageFormats.contains("tiff")) {
70  formats += "*.tiff ";
71  }
72 
73  if ( imageFormats.contains("tif")) {
74  formats += "*.tif ";
75  }
76 
77  if ( imageFormats.contains("png")) {
78  formats += "*.png";
79  }
80 
81  return QString( tr("HeightField PNG files ( ")+ formats + ")" );
82 };
83 
85  return QString( "" );
86 };
87 
90  return type;
91 }
92 
93 bool FileHeightFieldPNGPlugin::showImageDialog(const QImage& _image, int* _minX, int* _maxX, int* _minY, int* _maxY, double* _height)
94 {
95  ImageDialog imageDialog(_image);
96  imageDialog.heightValue->setValue(*_height);
97 
98  int result = imageDialog.exec();
99 
100  if ( result == QDialog::Accepted) {
101  *_minX = imageDialog.minX->value();
102  *_maxX = imageDialog.maxX->value();
103  *_minY = imageDialog.minY->value();
104  *_maxY = imageDialog.maxY->value();
105  *_height = imageDialog.heightValue->value();
106  } else {
107  return false;
108  }
109  return true;
110 }
111 
112 
113 int FileHeightFieldPNGPlugin::loadObject(QString _filename)
114 {
115 
116  QFile file(_filename);
117  if ( !file.exists() ) {
118  emit log(LOGERR,tr("Unable to load file: ") + _filename);
119  return -1;
120  }
121 
122  QImage image(_filename);
123 
124  // Prepare for taking specific regions from the file (defaults to full size)
125  int minX = 0;
126  int maxX = image.width();
127 
128  int minY = 0;
129  int maxY = image.height();
130 
131  // Try to calculate a reasonable height
132  double height = image.height() / 100;
133 
134  if ( OpenFlipper::Options::gui() ) {
135 
136  bool ret = false;
137  QMetaObject::invokeMethod(this,"showImageDialog",
138  // execute widget in main thread
139  (QThread::currentThread() != QApplication::instance()->thread()) ? Qt::BlockingQueuedConnection: Qt::DirectConnection,
140  Q_RETURN_ARG(bool, ret),
141  Q_ARG(const QImage&, image),
142  Q_ARG(int*,&minX),
143  Q_ARG(int*,&maxX),
144  Q_ARG(int*,&minY),
145  Q_ARG(int*,&maxY),
146  Q_ARG(double*,&height));
147  if (!ret)
148  return -1;
149  }
150 
151 
152  int id = -1;
153  emit addEmptyObject( DATA_TRIANGLE_MESH, id );
154 
155  TriMeshObject* object = 0;
156  if(PluginFunctions::getObject( id, object))
157  {
158  TriMesh* mesh = object->mesh();
159 
160  if ( mesh ) {
161 
162 
163  // Load the data into the mesh.
164  loadImageAsTriangleMesh(image,mesh,minX ,maxX , minY ,maxY, height);
165 
166  // Make sure everything is ready
167  emit updatedObject(object->id(), UPDATE_ALL);
168 
169  // Tell core about update
170  emit openedFile( id );
171 
172  }
173  }
174 
175  return id;
176 }
177 
178 void FileHeightFieldPNGPlugin::loadImageAsTriangleMesh(QImage& _image,TriMesh* _mesh,int _minX , int _maxX , int _minY , int _maxY, double _height) {
179 
180  const int mWidth = _maxY - _minY;
181  const int mHeigth = _maxX - _minX;
182 
183  // Reserve to get reasonable memory usage
184  _mesh->reserve( mWidth*mHeigth, mWidth*mHeigth * 4, mWidth*mHeigth * 2 );
185 
186  for ( int i = _minX ; i < _maxX ; ++i ) {
187  for ( int j = _minY ; j < _maxY ; ++j ) {
188  const QColor currentColor = _image.pixel(i,j);
189  double value = std::max(currentColor.redF(),currentColor.blueF());
190  value = std::max(currentColor.greenF(),value);
191  TriMesh::VertexHandle vh = _mesh->add_vertex(TriMesh::Point(i,j,-value * _height));
192  _mesh->set_color(vh,TriMesh::Color(currentColor.redF(),currentColor.greenF(),currentColor.blueF(),1.0f));
193  }
194  }
195 
196  // Triangulate
197  for ( int i = 0 ; i < mHeigth - 1 ; ++i ) {
198  const int upperStart = mWidth * i;
199  const int lowerStart = mWidth * (i + 1);
200 
201  for ( int j = 0 ; j < mWidth -1 ; ++j ) {
202  std::vector<TriMesh::VertexHandle> handles;
203  handles.push_back( _mesh->vertex_handle(upperStart + j) );
204  handles.push_back( _mesh->vertex_handle(lowerStart + j + 1) );
205  handles.push_back( _mesh->vertex_handle(lowerStart + j) );
206 
207 
208  _mesh->add_face(handles);
209 
210  handles.clear();
211 
212  handles.push_back( _mesh->vertex_handle(upperStart + j) );
213  handles.push_back( _mesh->vertex_handle(upperStart + j + 1) );
214  handles.push_back( _mesh->vertex_handle(lowerStart + j + 1) );
215 
216  _mesh->add_face(handles);
217  }
218  }
219 
220  //Calculate some normals
221  _mesh->update_normals();
222 }
223 
224 
225 bool FileHeightFieldPNGPlugin::saveObject(int _id, QString _filename) {
226  return false;
227 }
228 
229 #if QT_VERSION < 0x050000
230  Q_EXPORT_PLUGIN2( fileheightfieldPpngplugin , FileHeightFieldPNGPlugin );
231 #endif
232 
233 
Predefined datatypes.
Definition: DataTypes.hh:96
Type for a MeshObject containing a triangle mesh.
Definition: TriangleMesh.hh:73
bool getObject(int _identifier, BSplineCurveObject *&_object)
Kernel::Color Color
Color type.
Definition: PolyMeshT.hh:119
int id() const
Definition: BaseObject.cc:201
void initializePlugin()
Initialize Plugin.
Kernel::VertexHandle VertexHandle
Handle for referencing the corresponding item.
Definition: PolyMeshT.hh:139
Kernel::Point Point
Coordinate type.
Definition: PolyMeshT.hh:115
const UpdateType UPDATE_ALL(UpdateTypeSet(1))
Identifier for all updates.
#define DATA_TRIANGLE_MESH
Definition: TriangleMesh.hh:66
DataType supportedType()
Return your supported object type( e.g. DATA_TRIANGLE_MESH )