Basic Image AlgorithmS Library  2.8.0
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
biasdetectunvignettewx.cpp
1 #include <Base/Common/W32Compat.hh>
2 
3 #include <wx/wx.h>
4 #include <wx/spinctrl.h>
5 #include <wx/dnd.h>
6 #include <wx/filename.h>
7 #include <wx/arrstr.h>
8 
9 
10 #include <string>
11 #include <sstream>
12 #include <Gui/StringConv.hh>
13 #include <Gui/ImageCanvas.hh>
14 #include <Base/Image/ImageIO.hh>
15 #include <Base/ImageUtils/ImageDraw.hh>
16 #include <Image/Camera.hh>
17 #include <Image/UnVignette.hh>
18 
19 
20 #define FRAME_DEFAULT_SIZE wxSize(700,580)
21 
22 using namespace std;
23 using namespace BIAS;
24 
25 #undef WXWIN_COMPATIBILITY
26 
27 #if !wxUSE_DRAG_AND_DROP
28 # error The dndFileTarget class requires drag and drop support in the WX library. Please recompile wxWidgets. __FILE__: __LINE__
29 #endif
30 
31 
32 /**
33  * \cond HIDDEN_SYMBOLS
34  @file
35  @relates Unvignette
36  @brief Tool to detect the vignetting function (radial light fall off in images)
37  see biasdetectunvignettewx.cpp
38  @ingroup g_tools
39  @author ischiller
40  @date 2006
41 */
42 
43 /*
44 ===============================================================================
45 MainFrame
46 ===============================================================================
47 */
48 enum
49 {
50  // menu item IDs
51  ID_Load=wxID_HIGHEST+2231,
52  ID_Exit,
53  ID_About,
54  ID_Timer,
55  ID_Steps,
56  ID_UnVig,
57  ID_WriteCameraData,
58  ID_PPX,
59  ID_PPY
60 };
61 
62 /** \internal */
63 class MainFrame : public wxFrame
64 {
65 public:
66  friend class DragAndDropTarget;
67 
68  MainFrame(const wxString& title, const wxPoint& pos, const wxSize& size);
69 
70  bool LoadImagesAndCalculate(const wxArrayString &fileNames);
71 
72  /// fits the frame size if it is too small for curent image
73  void FitSizetIfTooSmall();
74 
75  double CalcImageMean3x3(BIAS::Image<unsigned char> img, int x,int y);
76 
77 public:
78  wxArrayString ImageFileNames_;
79 
80  //members /////////////////////////////
81 protected:
82 
83  BIAS::UnVignette UnVignette_;
84 
85  ImageCanvas* ImageCanvasUC_;
86 
87  wxTimer Timer_;
88  wxStaticText* StaticLabel_;
89  wxTextCtrl* StepsTextCtrl_;
90  wxTextCtrl* PPXTextCtrl_;
91  wxTextCtrl* PPYTextCtrl_;
92 
93  bool bUnVignetteParamsReady_;
94  bool bImageLoaded_;
95  int dNumberOfSteps_;
96  // for file open dialog
97  wxString DefaultFile_;
98  wxString DefaultDir_;
99  wxString fileName_;
100 
101  // the unsigned char image for display
102  Image<unsigned char> unVigImage_;
103  Image<unsigned char> ucImage_;
104  ImageBase origImage_;
105 
106  std::vector<double> controlPoints_;
107  std::vector<double> VignettePercentage_;
108 
109  int dGroundThruthWhite_;
110 
111  int ImageWidth_;
112  int ImageHeight_;
113 
114  //offsets from image center (pixel)
115  int PrinciplePointX_;
116  int PrinciplePointY_;
117 
118  //member functions ///////////////////////
119 protected:
120  // event handlers
121  void OnLoad(wxCommandEvent& event);
122  void OnExit(wxCommandEvent& event);
123  void OnAbout(wxCommandEvent& event);
124 
125  void OnTimer(wxTimerEvent& event);
126  void OnIdle(wxIdleEvent& event);
127  void OnSize(wxSizeEvent& event);
128 
129  void OnStepsEnter(wxCommandEvent& event);
130 
131  void CalculateSteps(int dImageNumber);
132  void UnVignette();
133  void SaveUnVignetted(wxCommandEvent& event);
134  void WriteCameraData(wxCommandEvent& event);
135 
136  void RefitClients();
137  DECLARE_EVENT_TABLE()
138 };
139 
140 BEGIN_EVENT_TABLE(MainFrame, wxFrame)
141 EVT_MENU (ID_Load, MainFrame::OnLoad)
142 EVT_MENU (ID_Exit, MainFrame::OnExit)
143 EVT_MENU (ID_About, MainFrame::OnAbout)
144 EVT_MENU (ID_WriteCameraData, MainFrame::WriteCameraData)
145 EVT_TEXT_ENTER (ID_Steps, MainFrame::OnStepsEnter)
146 EVT_TEXT_ENTER (ID_PPX, MainFrame::OnStepsEnter)
147 EVT_TEXT_ENTER (ID_PPY, MainFrame::OnStepsEnter)
148 
149 EVT_BUTTON (ID_UnVig, MainFrame::SaveUnVignetted)
150 EVT_BUTTON (ID_WriteCameraData, MainFrame::WriteCameraData)
151 
152 EVT_TIMER (ID_Timer, MainFrame::OnTimer)
153 EVT_IDLE (MainFrame::OnIdle)
154 EVT_SIZE (MainFrame::OnSize)
155 END_EVENT_TABLE()
156 
157 
158 // ctor
159 MainFrame::MainFrame(const wxString& title, const wxPoint& pos, const wxSize& size)
160 : wxFrame((wxFrame*)NULL, -1, title, pos, size)
161 ,ImageCanvasUC_(NULL)
162 {
163  DefaultFile_ = wxT("test.pgm");
164  DefaultDir_ = wxT("");
165  dNumberOfSteps_ = 10;
166  PrinciplePointX_ = 0;
167  PrinciplePointY_ = 0;
168  dGroundThruthWhite_ = 0;
169  bUnVignetteParamsReady_ = false;
170  bImageLoaded_ = false;
171  // init timer
172  Timer_.SetOwner(this, ID_Timer);
173 
174  // create file menu
175  wxMenu* fileMenu = new wxMenu;
176  fileMenu->Append(ID_Load, wxT("&Open/Load...\tCtrl-O"), wxT("Open a file from disk for loading"));
177  fileMenu->Append(ID_WriteCameraData, wxT("&Write Camera Data...\tCtrl-W"), wxT("Save camera vignette parameters"));
178  fileMenu->AppendSeparator();
179 
180  // create help menu
181  wxMenu* helpMenu = new wxMenu;
182  helpMenu->Append(ID_About, wxT("&About...\tF1"));
183 
184  // create menu bar
185  wxMenuBar* menuBar = new wxMenuBar;
186  menuBar->Append(fileMenu, wxT("&File"));
187  menuBar->Append(helpMenu, wxT("&Help"));
188  SetMenuBar(menuBar);
189 
190  wxToolBar* toolBar = CreateToolBar();
191  toolBar->SetSize(1200,200);
192  StepsTextCtrl_ = new wxTextCtrl(toolBar, ID_Steps, wxT("10"), wxDefaultPosition,wxDefaultSize,wxTE_PROCESS_ENTER);
193  toolBar->AddControl(new wxStaticText(toolBar, -1, wxT(" Nr. of Steps: ")));
194  toolBar->AddControl(StepsTextCtrl_);
195 
196  toolBar->AddSeparator();
197  toolBar->AddControl(new wxButton(toolBar, ID_UnVig, wxT("Save Unvignetted")));
198  toolBar->AddControl(new wxButton(toolBar, ID_WriteCameraData, wxT("Write Cameradata")));
199  toolBar->AddSeparator();
200  PPXTextCtrl_ = new wxTextCtrl(toolBar, ID_PPX, wxT("0"), wxDefaultPosition, wxDefaultSize,wxTE_PROCESS_ENTER);
201  PPYTextCtrl_ = new wxTextCtrl(toolBar, ID_PPY, wxT("0"), wxDefaultPosition, wxDefaultSize,wxTE_PROCESS_ENTER);
202 
203  toolBar->AddControl(new wxStaticText(toolBar, -1, wxT(" PPX: ")));
204  toolBar->AddControl(PPXTextCtrl_);
205  toolBar->AddControl(new wxStaticText(toolBar, -1, wxT(" PPY: ")));
206  toolBar->AddControl(PPYTextCtrl_);
207 
208  toolBar->Realize();
209 
210 
211  // create status bar
212  const int numFields = 2;
213  CreateStatusBar(numFields);
214  int widths[] = { -3, -1 };
215  SetStatusWidths(numFields, widths);
216  SetStatusText(wxT("Welcome to Unvignette detection"), 0);
217 
218 }
219 
220 void MainFrame::WriteCameraData(wxCommandEvent& /*event*/)
221 {
222  if(!bUnVignetteParamsReady_)
223  {
224  wxMessageDialog mDlg(this,wxT("Camera unvignette parameters are not ready, compute first!"),
225  wxT("Not ready!"),wxOK);
226  mDlg.ShowModal();
227  return;
228  }
229  std::ofstream OutStream;
230  wxArrayString paths;
231  wxFileDialog fileDialog(
232  this, // parent
233  wxT("Choose xml file to save Camera Data."), // message
234  DefaultDir_, // default directory
235  wxT("UnVignetteParams.xml"), // default file
236  wxT("*.xml"), // wildcard
237  wxFD_SAVE|wxFD_OVERWRITE_PROMPT); // style
238 
239  if (fileDialog.ShowModal() == wxID_OK)
240  {
241  // get file names
242  fileDialog.GetPaths(paths);
243  } else {
244  SetStatusText(wxT("Writing Camera Data cancelled"));
245  return;
246  }
247 
248  DefaultDir_= fileDialog.GetDirectory();
249 
250  OutStream.open(WxToAscii(paths.Last()),ios_base::out | ios_base::trunc);
251  OutStream << setprecision(10);
252  OutStream<<"<VignetteCalib>\n";
253  for(unsigned int i = 0;i<controlPoints_.size();i++)
254  OutStream<<"<MeasPt Dist=\""<<controlPoints_[i]<<"\" Fac=\""<<VignettePercentage_[i]<<"\"/>"<<endl;
255  OutStream<<"</VignetteCalib>"<<endl;
256  OutStream.flush();
257  OutStream.close();
258 }
259 
260 void MainFrame::SaveUnVignetted(wxCommandEvent& /*event*/)
261 {
262  if(unVigImage_.IsEmpty())
263  {
264  wxMessageDialog mDlg(this,wxT("No image loaded, load first!"),
265  wxT("Not ready!"),wxOK);
266  mDlg.ShowModal();
267  return;
268  }
269  wxArrayString paths;
270  wxFileDialog fileDialog(
271  this, // parent
272  wxT("Choose image file to save unvignetted image."), // message
273  DefaultDir_, // default directory
274  wxT("TestUnVignette.mip"), // default file
275  wxT("*.mip"), // wildcard
276  wxFD_SAVE|wxFD_OVERWRITE_PROMPT); // style
277 
278  if (fileDialog.ShowModal() == wxID_OK)
279  {
280  // get file names
281  fileDialog.GetPaths(paths);
282  } else {
283  SetStatusText(wxT("Writing unvignetted image cancelled"));
284  return;
285  }
286 
287  DefaultDir_= fileDialog.GetDirectory();
288  //BIAS::ImageIO::Save(WxToAscii(paths.Last()),unVigImage_);
289  BIAS::ImageIO::Save(WxToAscii(paths.Last()),unVigImage_);
290 }
291 
292 void MainFrame::OnStepsEnter(wxCommandEvent& /*event*/)
293 {
294  LoadImagesAndCalculate(ImageFileNames_);
295  StepsTextCtrl_->SetFocus();
296 }
297 
298 void MainFrame::CalculateSteps(int dImageNumber)
299 {
300  ucImage_ = origImage_;
301 
302  ImageWidth_ = ucImage_.GetWidth();
303  ImageHeight_ = ucImage_.GetHeight();
304 
305  if(dImageNumber == 0){
306  controlPoints_.clear();
307  VignettePercentage_.clear();
308  }
309  //this is diagonal distance of image rectangle
310  double diagonal = sqrt(pow((double)ImageWidth_,2)+pow((double)ImageHeight_,2));
311  //calculate stepswidth
312  int step = int ( diagonal / (dNumberOfSteps_*2) );
313  int currentRadius=0;
314  int valueX=0, valueY=0;
315  double mean=0.0, mean1=0.0, mean2=0.0, mean3=0.0, mean4=0.0;
316 
317  double alpha = atan((double)ImageHeight_/(double)ImageWidth_);
318 // unsigned char ** ida = ucImage_.GetImageDataArray();
319  //go over steps and draw lines and calculate values
320  for(int currentstep =0;currentstep <=dNumberOfSteps_;currentstep++)
321  {
322  // go into all 4 corners and build mean of 4 measurements
323  for(int corner=0;corner<4;corner++)
324  {
325  // calculate ControlPoints on diagonal of image and on circle around PrinciplePoint with radius
326  if(corner==0) // left top corner
327  {
328  valueX = ImageWidth_/2 + PrinciplePointX_ - int(currentRadius * cos(alpha));
329  valueY= ImageHeight_/2 + PrinciplePointY_ - int(currentRadius * sin(alpha));
330 
331  //only save control points if first image and first corner
332  if(valueX<(ImageWidth_-1)&&valueY <(ImageHeight_-1)&& valueY >= 0 && valueX >= 0)
333  {
334  mean1 = CalcImageMean3x3(ucImage_,valueX,valueY);
335  if(mean1 >= 0 && dImageNumber == 0)
336  controlPoints_.push_back((double)currentRadius/((double)ImageWidth_/2));
337  else if(mean1 < 0.0){
338  corner =5;
339  break;
340  }
341  }
342  }
343  else if(corner==1) //right top corner
344  {
345  valueX = int(currentRadius * cos(alpha) + ImageWidth_/2 + PrinciplePointX_);
346  valueY= ImageHeight_/2 + PrinciplePointY_ - int(currentRadius * sin(alpha));
347  mean2 = CalcImageMean3x3(ucImage_,valueX,valueY);
348  if(mean2 <0.0){
349  corner =5;
350  break;
351  }
352 
353  }
354  else if(corner==2) //left bottom corner
355  {
356  valueX = ImageWidth_/2 + PrinciplePointX_ - int(currentRadius * cos(alpha));
357  valueY= int(currentRadius * sin(alpha) + ImageHeight_/2 + PrinciplePointY_);
358  mean3 = CalcImageMean3x3(ucImage_,valueX,valueY);
359  if(mean3 <0.0){
360  corner =5;
361  break;
362  }
363  }
364  else if(corner==3) // right bottom corner
365  {
366  valueX = int(currentRadius * cos(alpha) + ImageWidth_/2 + PrinciplePointX_);
367  valueY= int(currentRadius * sin(alpha) + ImageHeight_/2 + PrinciplePointY_);
368  mean4 = CalcImageMean3x3(ucImage_,valueX,valueY);
369  if(mean4 <0.0){
370  corner =5;
371  break;
372  }
373  }
374  }// end go over corners
375 
376  //check if all positions were in the image and valid else break;
377  if(! (mean1>=0.0 && mean2>=0.0 && mean3>=0.0 && mean4>=0.0))
378  break;
379  // this is mean of all 4 corners
380  mean =(mean1+mean2+mean3+mean4)/4;
381  //this is the center, save the value as fixpoint
382  double percentage = 0.0;
383  if(currentstep==0){
384  dGroundThruthWhite_ = int(mean);
385  percentage = 1.0;
386  }
387  else
388  percentage = ((double)dGroundThruthWhite_/mean);
389  //only push_back if first image else make mean
390  if(dImageNumber==0)
391  {
392  if(percentage>=0.0)
393  VignettePercentage_.push_back(percentage);
394  else
395  VignettePercentage_.push_back(0.0);
396  }
397  else
398  {
399  if(percentage >=0.0)
400  {
401  VignettePercentage_[currentstep] *= dImageNumber;
402  VignettePercentage_[currentstep] += percentage;
403  VignettePercentage_[currentstep] /=(dImageNumber+1);
404  }
405  }//end else
406 
407  //Draw circels in image
408  BIAS::ImageDraw<unsigned char>::CircleCenter(ucImage_,ImageWidth_/2+ PrinciplePointX_,
409  ImageHeight_/2+ PrinciplePointY_,currentRadius);
410 
411  currentRadius += step;
412  }
413 
414  ImageCanvasUC_->Show(ucImage_, WxToAscii(fileName_));
415  if (ImageCanvasUC_) ImageCanvasUC_->SetFocus();
416 
417 }
418 
419 void MainFrame::UnVignette()
420 {
421  if(!bImageLoaded_)
422  {
423  /*wxMessageDialog mDlg(this,"No image loaded, load first!",
424  "Not ready!",wxOK);
425  mDlg.ShowModal();*/
426  return;
427  }
428  unVigImage_ = origImage_;
429  UnVignette_.Init(controlPoints_,VignettePercentage_,unVigImage_.GetWidth(),
430  unVigImage_.GetHeight(),PrinciplePointX_+unVigImage_.GetWidth()/2,
431  PrinciplePointY_+unVigImage_.GetHeight()/2,LEAST_SQUARES);
432  UnVignette_.Compute(unVigImage_);
433 
434  bUnVignetteParamsReady_ = true;
435 }
436 
437 void MainFrame::RefitClients()
438 {
439  // canvas needs to be refitted on windows after loading (not sure why)
440  int w, h;
441  GetClientSize(&w, &h);
442  if (ImageCanvasUC_!=NULL)
443  ImageCanvasUC_->SetSize(0, 0, w, h);
444 }
445 
446 bool MainFrame::LoadImagesAndCalculate(const wxArrayString &fileNames)
447 {
448  dNumberOfSteps_ = atoi(WxToAscii(StepsTextCtrl_->GetValue()));
449  PrinciplePointX_ = atoi(WxToAscii(PPXTextCtrl_->GetValue()));
450  PrinciplePointY_ = atoi(WxToAscii(PPYTextCtrl_->GetValue()));
451  for(unsigned int k=0;k<fileNames.Count();k++)
452  {
453  // load image
454  fileName_ = fileNames[k];
455 
456  if (ImageIO::Load(WxToAscii(fileName_), origImage_)!=0)
457  {
458  stringstream msg;
459  msg << "Error loading " << fileName_;
460  BIASERR(msg.str());
461  SetStatusText(AsciiToWx(msg.str()));
462  }
463  else
464  {
465 
466  // create uc image canvas
467  if(ImageCanvasUC_ == NULL)
468  {
469  ImageCanvasUC_ = new ImageCanvas(this, GetStatusBar(), 1);
470  }
471  bImageLoaded_ = true;
472 
473  //calculate steps and show image
474  this->CalculateSteps(k);
475 
476  this->RefitClients();
477 
478  }//end else (means loading succeeded
479 
480  }//end for
481 
482  //after collection of all data, finally unvignette
483  this->UnVignette();
484 
485  return true;
486 }
487 
488 void MainFrame::OnLoad(wxCommandEvent& /*event*/)
489 {
490  wxFileDialog fileDialog(
491  this, // parent
492  wxT("Choose file(s) to load"), // message
493  DefaultDir_, // default directory
494  DefaultFile_, // default file
495  wxT("*.*"), // wildcard
496  wxFD_OPEN | wxFD_MULTIPLE); // style
497 
498  if (fileDialog.ShowModal() == wxID_OK)
499  {
500  // get file names
501 
502  fileDialog.GetPaths(ImageFileNames_);
503  // load last item
504  LoadImagesAndCalculate(ImageFileNames_);
505  } else {
506  SetStatusText(wxT("Loading canceled"));
507  cout << "Canceled loading image" << endl;
508  }
509 
510  DefaultDir_= fileDialog.GetDirectory();
511 
512 }
513 
514 double MainFrame::
515 CalcImageMean3x3(BIAS::Image<unsigned char> img, int x,int y)
516 {
517  int width, height;
518  width = img.GetWidth();
519  height = img.GetHeight();
520  if( (x>1) && (y>1) && (x<width-1) && (y<height-1))
521  {
522  double mean = ((double)img.PixelValue(x-1,y-1) +
523  (double)img.PixelValue(x,y-1)+(double)img.PixelValue(x+1,y-1)+
524  (double)img.PixelValue(x-1,y)+ (double)img.PixelValue(x,y)+
525  (double)img.PixelValue(x+1,y)+ (double)img.PixelValue(x-1,y+1) +
526  (double)img.PixelValue(x,y+1) + (double)img.PixelValue(x+1,y+1))/9;
527  return mean;
528  }
529  else
530  return -1.0;
531 }
532 
533 void MainFrame::OnExit(wxCommandEvent& /*event*/){}
534 void MainFrame::OnAbout(wxCommandEvent& /*event*/)
535 {
536 stringstream msg;
537 
538  msg << "The BIAS Vignette Detection Program\n\n"
539  << "http://www.mip.informatik.uni-kiel.de\n\n"
540  << "build on " << __DATE__ << " " << __TIME__ << "\n"
541  << "from file " << __FILE__ << "\n"
542  << "GUI using: " << wxVERSION_STRING << "\n"
543  << "Author : Ingo Schiller "<< "\n"
544  << "\n";
545 
546  wxMessageBox(AsciiToWx(msg.str()), wxT("About biasdetectunvignettewx"),
547  wxOK | wxICON_INFORMATION, this);
548 }
549 
550 void MainFrame::OnTimer(wxTimerEvent& /*event*/){}
551 void MainFrame::OnIdle(wxIdleEvent& /*event*/){}
552 void MainFrame::OnSize(wxSizeEvent& /*event*/){ this->RefitClients();}
553 
554 /*
555 ===============================================================================
556 DragAndDropTarget
557 ===============================================================================
558 */
559 
560 /** @brief drag and drop files onto application.
561 drag a file from MS explorer or kde file manager directly onto an application
562 (instaed of using a load from filename function.)
563 */
564 class DragAndDropTarget : public wxFileDropTarget
565 {
566 public:
567  DragAndDropTarget(MainFrame* frame);
568 
569  virtual bool OnDropFiles(wxCoord x, wxCoord y, const wxArrayString& filenames);
570 protected:
571  MainFrame* Frame_;
572 };
573 
574 DragAndDropTarget::DragAndDropTarget(MainFrame* frame)
575 {
576  Frame_ = frame;
577 }
578 
579 bool DragAndDropTarget::OnDropFiles(wxCoord /*x*/, wxCoord /*y*/, const wxArrayString& filenames)
580 {
581  BIASASSERT( Frame_ != NULL);
582  Frame_->ImageFileNames_ = filenames;
583  Frame_->LoadImagesAndCalculate(filenames);
584 
585  return true;
586 }
587 
588 
589 /*
590 ===============================================================================
591 BiasDetectUnvignetteApp
592 ===============================================================================
593 */
594 
595 class BiasDetectUnvignetteApp : public wxApp
596 {
597 public:
598  virtual bool OnInit();
599 };
600 
601 bool BiasDetectUnvignetteApp::OnInit()
602 {
603 
604  MainFrame* frame = new MainFrame(wxT("BiasDetectUnvignetteApp"), wxPoint(50,50), FRAME_DEFAULT_SIZE );
605 
606 
607  // create drag and drop target
608  DragAndDropTarget* dndTarget = new DragAndDropTarget(frame);
609  frame->SetDropTarget(dndTarget);
610 
611  // show frame
612  frame->Show(TRUE);
613  SetTopWindow(frame);
614 
615  return TRUE;
616 }
617 
618 
619 IMPLEMENT_APP(BiasDetectUnvignetteApp)
620 /** \endcond */
621 
622 
wxString AsciiToWx(const char *thestring)
Converts a C string to a wxString.
Definition: StringConv.hh:32
Unvignette algorithm for images.
Definition: UnVignette.hh:61
display image in wx application, provides zoom and investigation functionality
Definition: ImageCanvas.hh:38
unsigned int GetWidth() const
Definition: ImageBase.hh:312
StorageType PixelValue(const unsigned int x, const unsigned int y, const unsigned short int channel=0) const
Returns value of pixel at specific position, using specific channel as offset.
Definition: Image.hh:91
static int CircleCenter(Image< StorageType > &im, unsigned int CenterX, unsigned int CenterY, unsigned int Radius, const StorageType Value[]=NULL)
draws a circular line, either using Value or a good contrast value
Definition: ImageDraw.cpp:977
unsigned int GetHeight() const
Definition: ImageBase.hh:319
static int Save(const std::string &filename, const ImageBase &img, const enum TFileFormat FileFormat=FF_auto, const bool sync=BIAS_DEFAULT_SYNC, const int c_jpeg_quality=BIAS_DEFAULT_IMAGE_QUALITY, const bool forceNewID=BIAS_DEFAULT_FORCENEWID, const bool &writeMetaData=true)
Export image as file using extrnal libs.
Definition: ImageIO.cpp:725
This is the base class for images in BIAS.
Definition: ImageBase.hh:102