fw4spl
SImageReader.cpp
1 /* ***** BEGIN LICENSE BLOCK *****
2  * FW4SPL - Copyright (C) IRCAD, 2009-2018.
3  * Distributed under the terms of the GNU Lesser General Public License (LGPL) as
4  * published by the Free Software Foundation.
5  * ****** END LICENSE BLOCK ****** */
6 
7 #include "ioVTK/SImageReader.hpp"
8 
9 #include <fwCom/HasSignals.hpp>
10 #include <fwCom/Signal.hpp>
11 #include <fwCom/Signal.hxx>
12 
13 #include <fwCore/base.hpp>
14 
15 #include <fwData/Image.hpp>
16 #include <fwData/location/Folder.hpp>
17 #include <fwData/mt/ObjectWriteLock.hpp>
18 
19 #include <fwDataIO/reader/IObjectReader.hpp>
20 
21 #include <fwGui/Cursor.hpp>
22 #include <fwGui/dialog/LocationDialog.hpp>
23 #include <fwGui/dialog/MessageDialog.hpp>
24 
25 #include <fwIO/IReader.hpp>
26 
27 #include <fwJobs/Aggregator.hpp>
28 #include <fwJobs/IJob.hpp>
29 #include <fwJobs/Job.hpp>
30 
31 #include <fwServices/macros.hpp>
32 #include <fwServices/registry/ActiveWorkers.hpp>
33 
34 #include <fwVtkIO/BitmapImageReader.hpp>
35 #include <fwVtkIO/ImageReader.hpp>
36 #include <fwVtkIO/MetaImageReader.hpp>
37 #include <fwVtkIO/VtiImageReader.hpp>
38 
39 #include <boost/algorithm/string.hpp>
40 #include <boost/filesystem/operations.hpp>
41 #include <boost/filesystem/path.hpp>
42 
43 #include <chrono>
44 #include <cstdint>
45 #include <thread>
46 
47 namespace ioVTK
48 {
49 
50 //------------------------------------------------------------------------------
51 
52 // Register a new reader of ::fwData::Image
53 fwServicesRegisterMacro( ::fwIO::IReader, ::ioVTK::SImageReader, ::fwData::Image );
54 
55 static const ::fwCom::Signals::SignalKeyType JOB_CREATED_SIGNAL = "jobCreated";
56 
57 //------------------------------------------------------------------------------
58 
60 {
61  return ::fwIO::FILE;
62 }
63 
64 //------------------------------------------------------------------------------
65 
67 {
68  static ::boost::filesystem::path _sDefaultPath;
69 
70  /* Initialize the available extensions for BitmapImageReader */
71  std::vector<std::string> ext;
73  std::string availableExtensions = "";
74 
75  if(ext.size() > 0)
76  {
77  availableExtensions = "*" + ext.at(0);
78  for(int i = 1; i < ext.size(); i++)
79  {
80  availableExtensions = availableExtensions + " *" + ext.at(i);
81  }
82  }
83 
85  dialogFile.setTitle(m_windowTitle.empty() ? "Choose a file to load an image" : m_windowTitle);
86  dialogFile.setDefaultLocation( ::fwData::location::Folder::New(_sDefaultPath) );
87  dialogFile.addFilter("Vtk", "*.vtk");
88  dialogFile.addFilter("Vti", "*.vti");
89  dialogFile.addFilter("MetaImage", "*.mhd");
90  dialogFile.addFilter("Bitmap image", availableExtensions);
91  dialogFile.setOption(::fwGui::dialog::ILocationDialog::READ);
92  dialogFile.setOption(::fwGui::dialog::ILocationDialog::FILE_MUST_EXIST);
93 
94  ::fwData::location::SingleFile::sptr result;
95  result = ::fwData::location::SingleFile::dynamicCast( dialogFile.show() );
96  if (result)
97  {
98  _sDefaultPath = result->getPath().parent_path();
99  dialogFile.saveDefaultLocation( ::fwData::location::Folder::New(_sDefaultPath) );
100  this->setFile(result->getPath());
101  }
102  else
103  {
104  this->clearLocations();
105  }
106 }
107 
108 //------------------------------------------------------------------------------
109 
111 {
112  m_sigJobCreated = newSignal< JobCreatedSignalType >( JOB_CREATED_SIGNAL );
113 }
114 
115 //------------------------------------------------------------------------------
116 
118 {
119 }
120 
121 //------------------------------------------------------------------------------
122 
124 {
125 }
126 
127 //------------------------------------------------------------------------------
128 
130 {
132 }
133 
134 //------------------------------------------------------------------------------
135 
136 void SImageReader::info( std::ostream& _sstream )
137 {
138  _sstream << "SImageReader::info";
139 }
140 
141 //------------------------------------------------------------------------------
142 
144 {
145  if( this->hasLocationDefined() )
146  {
147  ::fwData::Image::sptr image = this->getInOut< ::fwData::Image >(::fwIO::s_DATA_KEY);
148 
149  if (!image)
150  {
151  FW_DEPRECATED_KEY(::fwIO::s_DATA_KEY, "inout", "18.0");
152  // Retrieve dataStruct associated with this service
153  image = this->getObject< ::fwData::Image >();
154 
155  }
156  SLM_ASSERT("image not instanced", image);
157 
158  // Read new image path and update image. If the reading process is a success, we notify all listeners that image
159  // has been modified.
160 
161  ::fwGui::Cursor cursor;
162  cursor.setCursor(::fwGui::ICursor::BUSY);
163  try
164  {
165  // Notify other image services that a new image has been loaded.
166  if ( SImageReader::loadImage( this->getFile(), image, m_sigJobCreated ) )
167  {
169  {
170  ::fwCom::Connection::Blocker block(sig->getConnection(m_slotUpdate));
171  sig->asyncEmit();
172  }
173  }
174  }
175  catch(::fwTools::Failed& e)
176  {
177  OSLM_TRACE("Error : " << e.what());
178  FW_RAISE_EXCEPTION(e);
179  }
180 
181  cursor.setDefaultCursor();
182  }
183 }
184 
185 //------------------------------------------------------------------------------
186 
187 template< typename READER > typename READER::sptr configureReader(const ::boost::filesystem::path& imgFile )
188 {
189  typename READER::sptr reader = READER::New();
190  reader->setFile(imgFile);
191  return reader;
192 }
193 
194 //------------------------------------------------------------------------------
195 
196 bool SImageReader::loadImage( const ::boost::filesystem::path& imgFile,
197  const ::fwData::Image::sptr& img,
198  const SPTR(JobCreatedSignalType)& sigJobCreated)
199 {
200  bool ok = true;
201 
202  std::string ext = ::boost::filesystem::extension(imgFile);
203  ::boost::algorithm::to_lower(ext);
204 
205  ::fwDataIO::reader::IObjectReader::sptr imageReader;
206  if(ext == ".vtk")
207  {
208  imageReader = configureReader< ::fwVtkIO::ImageReader >( imgFile );
209  }
210  else if(ext == ".vti")
211  {
212  imageReader = configureReader< ::fwVtkIO::VtiImageReader >( imgFile );
213  }
214  else if(ext == ".mhd")
215  {
216  imageReader = configureReader< ::fwVtkIO::MetaImageReader >( imgFile );
217  }
218  else
219  {
220  /* Handle BitmapImageReader extensions */
221  std::vector<std::string> availableExtensions;
223 
224  /* If we find the current extensions in the available readers, we use it */
225  size_t i = 0;
226  for(; i < availableExtensions.size(); i++)
227  {
228  if(availableExtensions.at(i) == ext)
229  {
230  imageReader = configureReader< ::fwVtkIO::BitmapImageReader >( imgFile );
231  break;
232  }
233  }
234 
235  // If we didn't find any suitable extension with BitmapImageReader, we raise an exception */
236  if(i == availableExtensions.size())
237  {
238  i = 0;
239  std::string bitmapExtensions = "";
240  for(; i < availableExtensions.size(); i++)
241  {
242  bitmapExtensions = bitmapExtensions + availableExtensions.at(i) + ", ";
243  }
244  FW_RAISE_EXCEPTION(::fwTools::Failed("Only " + bitmapExtensions + ".vtk, .vti and .mhd are supported."));
245  }
246  }
247 
248  // Set the image (already created, but empty) that will be modified
250  imageReader->setObject(img);
251 
252  sigJobCreated->emit(imageReader->getJob());
253 
254  try
255  {
256  imageReader->read();
257  }
258  catch(::fwTools::Failed& e)
259  {
260  std::stringstream ss;
261  ss << "Warning during loading : " << e.what();
262 
264  "Warning",
265  ss.str(),
266  ::fwGui::dialog::IMessageDialog::WARNING);
267  ok = false;
268  // Raise exception for superior level
269  FW_RAISE_EXCEPTION(e);
270  }
271  catch (const std::exception& e)
272  {
273  std::stringstream ss;
274  ss << "Warning during loading : " << e.what();
275 
277  "Warning",
278  ss.str(),
279  ::fwGui::dialog::IMessageDialog::WARNING);
280  ok = false;
281  }
282  catch( ... )
283  {
285  "Warning",
286  "Warning during loading.",
287  ::fwGui::dialog::IMessageDialog::WARNING);
288  ok = false;
289  }
290 
291  return ok;
292 }
293 
294 } // namespace ioVtk
#define FW_DEPRECATED_KEY(newKey, access, version)
Use this macro when deprecating a service key to warn the developer.
Definition: spyLog.hpp:366
virtual FWGUI_API void setCursor(::fwGui::ICursor::CursorType cursor) override
Set the cursor.
#define SPTR(_cls_)
static FWVTKIO_API void getAvailableExtensions(std::vector< std::string > &ext)
Service reading a VTK Image using the fwVtkIO lib.
std::string m_windowTitle
Title of the window that will open when the configureWithIHM slot is called.
Definition: IReader.hpp:207
Class allowing to block a Connection.
Definition: Connection.hpp:20
FWIO_API bool hasLocationDefined() const
Returns if a location has been defined ( by the configuration process or directly by user ) ...
Definition: IReader.cpp:233
virtual FWIO_API void configuring() override
This method proposes to parse xml configuration to retrieve file/files/folder paths.
Definition: IReader.cpp:144
static FWGUI_API IMessageDialog::Buttons showMessageDialog(const std::string &title, const std::string &message,::fwGui::dialog::IMessageDialog::Icons icon=INFO)
virtual IOVTK_API void configuring() override
Method called when the service is stopped, does nothing.
static IOVTK_API bool loadImage(const ::boost::filesystem::path &vtkFile, const std::shared_ptr< ::fwData::Image > &image, const std::shared_ptr< JobCreatedSignalType > &sigJobCreated)
This method is used to load an vtk image using a file path.
virtual FWGUI_API void setDefaultLocation(::fwData::location::ILocation::sptr loc) override
Set the initial location for the dialog.
virtual IOVTK_API void starting() override
Method called when the service is started, does nothing.
FWGUI_API::fwGui::dialog::ILocationDialog & setOption(::fwGui::dialog::ILocationDialog::Options option) override
allow to set option to the file dialog mode=READ/WRITE, check=FILE_MUST_EXIST
FWGUI_API::fwData::location::ILocation::sptr show() override
Display the dialog.
virtual IOVTK_API::fwIO::IOPathType getIOPathType() const override
This method must be implemented by concrete service readers that use path file system to read data...
A helper to lock object on exclusive mode.
#define OSLM_TRACE(message)
Definition: spyLog.hpp:230
FWGUI_API void addFilter(const std::string &filterName, const std::string &wildcardList) override
specify some filtering when browsing files:
FWIO_APIconst::boost::filesystem::path & getFile() const
Returns the file path set by the user or set during service configuration.
Definition: IReader.cpp:62
UpdateSlotType::sptr m_slotUpdate
Slot to call update method.
Definition: IService.hpp:690
virtual IOVTK_API void configureWithIHM() override
Configure the image path with a dialogBox.
FWIO_API void setFile(const ::boost::filesystem::path &file)
Sets file path.
Definition: IReader.cpp:71
Reader service API. It manages extension points definition and extension configuration.
Definition: IReader.hpp:34
IOVTK_API SImageReader() noexcept
Constructor. Do nothing.
#define SLM_ASSERT(message, cond)
work like &#39;assert&#39; from &#39;cassert&#39;, with in addition a message logged by spylog (with FATAL loglevel) ...
Definition: spyLog.hpp:308
virtual IOVTK_API void stopping() override
Method called when the service is stopped, does nothing.
IOVTK_API void info(std::ostream &_sstream) override
Info method gives some informations on service.
IOPathType
IOPathType defines different type of paths used by service readers/writers.
Definition: ioTypes.hpp:19
static FWDATA_APIconst::fwCom::Signals::SignalKeyType s_MODIFIED_SIG
Key in m_signals map of signal m_sigModified.
Implements a failed exception class.
FWGUI_API void setTitle(const std::string &title) override
Set the title for the dialog.
Defines the generic file/folder selector dialog for IHM.
Defines the generic cursor for IHM. Use the Delegate design pattern.
This class defines an image.
FWIO_API void clearLocations()
Clear any location set by the setFile/setFiles/setFolder setter.
Definition: IReader.cpp:137
FWGUI_API void saveDefaultLocation(::fwData::location::ILocation::sptr loc) override
Save the specified default location for the dialog in preferences (if available)
The namespace ioVTK contains reader, writer and helper using the fwVtkIO lib for output and input act...
virtual FWGUI_API void setDefaultCursor() override
Set the default cursor.
IOVTK_API void updating() override
Updating method execute the read process.