Basic Image AlgorithmS Library  2.8.0
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
ImageIO.cpp
1 /* This file is part of the BIAS library (Basic ImageAlgorithmS).
2 
3  Copyright (C) 2003-2009 (see file CONTACT for details)
4  Multimediale Systeme der Informationsverarbeitung
5  Institut fuer Informatik
6  Christian-Albrechts-Universitaet Kiel
7 
8 
9  BIAS is free software; you can redistribute it and/or modify
10  it under the terms of the GNU Lesser General Public License as published by
11  the Free Software Foundation; either version 2.1 of the License, or
12  (at your option) any later version.
13 
14  BIAS is distributed in the hope that it will be useful,
15  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  GNU Lesser General Public License for more details.
18 
19  You should have received a copy of the GNU Lesser General Public License
20  along with BIAS; if not, write to the Free Software
21  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
22 //#define ImageIO_DEBUG_IO
23 
24 #include "ImageIO.hh"
25 #include <Base/Common/FileHandling.hh>
26 
27 #ifndef WIN32
28 #include <unistd.h> // for usleep
29 #include <sys/stat.h>
30 #endif
31 
32 // ImageMagick support
33 #ifdef BIAS_HAVE_IMAGEMAGICKLIB
34 # include <Base/Common/BIASpragmaStart.hh>
35 # include <Magick++.h>
36 # include <Base/Common/BIASpragmaEnd.hh>
37 # if (MagickLibVersion >= 0x650)
38 # define MagickLib MagickCore
39 # endif
40 #endif
41 
42 // LibJPEG support: Sandro Esquivel 05/2008
43 #ifdef BIAS_HAVE_LIBJPEG
44 # include "CompressJpeg.hh"
45 #endif
46 
47 // required in header (not only cpp)
48 // due to public EXR PrintHeader interface
49 #ifdef BIAS_HAVE_OPENEXR
50 # ifdef WIN32
51 # pragma warning( push, 1)
52 # define PLATFORM_WINDOWS
53 # endif // WIN32
54 # include <half.h>
55 # include <ImfRgbaFile.h>
56 # include <ImfRgba.h>
57 # include <ImfArray.h>
58 # include <ImathBox.h>
59 # include <ImfInputFile.h>
60 # include <ImfOutputFile.h>
61 # include <ImfChannelList.h>
62 # include <ImfPixelType.h>
63 # include <ImfStringAttribute.h>
64 # include "OpenEXRInterface.hh"
65 # ifdef WIN32
66 # pragma warning( pop)
67 # endif // WIN32
68 #endif
69 
70 
71 #ifdef BIAS_HAVE_OPENCV
72 # include "WrapBias2Ipl.hh"
73 # include <cv.h>
74 # include <highgui.h>
75 #endif
76 
77 // use DevIL il with ilu (if DevIL is used at all)
78 #define USE_DEVIL_ILU
79 
80 #ifdef BIAS_HAVE_DEVIL
81 # include <IL/il.h>
82 # ifdef USE_DEVIL_ILU
83 # include <IL/ilu.h>
84 # endif // USE_DEVIL_ILU
85 //# include <IL/ilut.h>
86 #endif
87 
88 
89 #ifdef BIAS_HAVE_TIFF
90 # include <tiffio.h>
91 // check TIFF version from tiffvers.h
92 # if TIFFLIB_VERSION < 20051230
93 # error You need at least TIFF version 3.8.0 (TIFFLIB_VERSION >= 20051230) for muli plane tiff.
94 # endif
95 #endif
96 
97 
98 #include <Base/Debug/DebugSimple.hh>
99 
100 #ifdef BIAS_DEBUG
101 # include <Base/Debug/TimeMeasurement.hh>
102 # include <Base/Debug/LogFacility.hh>
103 #endif // BIAS_DEBUG
104 
105 #include <fstream>
106 #include <sstream>
107 
108 #include "ImageConvert.hh"
109 #include "ViffHeader.hh"
110 
111 // for transfrom:
112 #include <algorithm>
113 #include <cctype>
114 
115 // for O_APPEND
116 #include <fcntl.h>
117 
118 // for perror
119 #include <stdio.h>
120 
121 //replace old ImageMagick-namespace with new one
122 #ifdef BIAS_IMAGEMAGICKLIB_V2
123 # define MagickLib MagickCore
124 #endif //BIAS_IMAGEMAGICKLIB_V2
125 
126 
127 using namespace BIAS;
128 using namespace std;
129 
130 char *ImageIO::MemAlignedBuffer_ = NULL;
131 unsigned long int ImageIO::MemAlignedBufferSize_ = 0;
132 
133 
134 /// helper function for ExtensionName type casting @author Jan Woetzel
135 char myTolower(char c) {
136  return char(tolower(c));
137 }
138 
139 // try to Read MIP image and if that fails try all import functions.
140 int ImageIO::
141 Load(const string& FileNameConst, ImageBase &img)
142 {
143 #if defined(BIAS_DEBUG) && defined(ImageIO_DEBUG_IO)
144  CALLINFO;
145 #endif
146 
147  string FileName; // (FileNameConst); // non const copy for tilde expansion
148  FileHandling::FilenameExpansion(FileNameConst, FileName); // tilde
149 
150  int result = 0;
151 
152  ifstream is;
153  is.open( FileName.c_str() );
154  char identifier[IDENTIFIER_LENGTH];
155 
156  if (!is || !is.good()){
157  // file does not exist/is not readable!
158 #if defined(BIAS_DEBUG) || defined(ImageIO_DEBUG_IO)
159  BIASWARN("could not open fstream for file "<<FileName<<" with cwd="<<FileHandling::GetCwd());
160 #endif
161  result = -1;
162  } else {
163  is.read(identifier, IDENTIFIER_LENGTH);
164  if (!is.good()){
165  result = -2;
166  is.close();
167  } else {
168  if (identifier[0] == 'M' && identifier[1] == 'I' &&
169  identifier[2] == 'P'){ // mipimage
170  is.close();
171 #if defined(BIAS_DEBUG) && defined(ImageIO_DEBUG_IO)
172  COUT("MIP format detected\n");
173 #endif
174 
175  result = Read_(FileName, img);
176  } else {
177  // foreign image format
178  is.close();
179 #if defined(BIAS_DEBUG) && defined(ImageIO_DEBUG_IO)
180  COUT("image not in mip format\n");
181 #endif
182  result = ImageIO::ImportImage(FileName, img);
183  }
184  }
185  }
186 
187  return result;
188 }
189 
190 
191 #ifdef BIAS_HAVE_IMAGEMAGICKLIB
192 int ImageIO::
193 ImportMagickPP(const std::string& FileName,
194  ImageBase& result,
195  const bool & /*dummy*/,
196  const bool & readMetaData )
197 {
198 #if defined(BIAS_DEBUG) && defined(ImageIO_DEBUG_IO)
199  CALLINFO;
200 #endif
201 
202 #ifdef WIN32
203  //initialize DLL loaded library (not required on Linux but once on Windows)
204  Magick::InitializeMagick(NULL);
205 #endif
206 
207  Magick::Image image;
208  image.read( FileName );
209 
210  return ImageConvert::ImageMagick2BIAS(image,result);
211  if (readMetaData) {
212  //#ifdef BIAS_DEBUG
213  //BIAS::TimeMeasurement tm1("DBG get meta data inside ImportMagickPP ");
214  //#endif // BIAS_DEBUG
215 
216  /*
217  \TODO: crashes due to problem with const reference streaming !
218  e.g. on loading ibak "M34/Front/image00000000.jpg"
219  get the meta data from the (ASCII) comment field
220  string copy required because you canot directly stream a const
221  references!
222  - postpones the crash, but on leaving the scope it crashes, too.
223  MetaData operator<< problem?
224  \bug Only crash under windows in certain special cases: Needs to be compiled outside the bias library and needs to be run in the debugger of visual studio .net 2003 to reproduce crash. Maybe different libraries are used in this case? Even in that case it only crashes when the argument result is of type Image<unsigned char>. When result is of type ImageBase, it does not crash. In all other cases (linux and windows without .net) it works correctly. Neither valgrind nor efence (linux) find any suspicous activity here. MetaData.operator<< is *NOT* present in callstack. Maybe, buggy STL under windows?
225  */
226  string sTmp = image.comment();
227  stringstream strstr; // see above
228  strstr << sTmp;
229 #ifdef BIAS_DEBUG
230  // BLD("ImageIO::ImportMagickPP() : Read image.comment() = " << sTmp);
231 #endif
232  BIASASSERT(result.GetMetaData() != NULL);
233  strstr >> *(result.GetMetaData());
234  // [HACK] esquivel:
235  // Workaround to add simple comments to metadata. Comments consisting
236  // of an unformated ascii string are added to metadata tag #[Comment].
237  if (!image.comment().empty() && result.GetMetaData()->size() == 0) {
238 #ifdef BIAS_DEBUG
239  // BLD("Image comment was not added, add tag #[Comment] explicitely.");
240 #endif
241  result.GetMetaData()->Add("#[Comment]", image.comment());
242  }
243 #ifdef BIAS_DEBUG
244  //result.GetMetaData()->Dump();
245 #endif
246  }
247 
248  return BIAS_IO_SUCCESS;
249 }
250 #endif // BIAS_HAVE_IMAGEMAGICKLIB
251 
252 
253 #ifdef BIAS_HAVE_OPENCV
254 
255 int ImageIO::
256 ImportOpenCV(const std::string &filename, ImageBase &image)
257 {
258 #if defined(BIAS_DEBUG) && defined(ImageIO_DEBUG_IO)
259  CALLINFO;
260 #endif
261 
262  IplImage* p_cv = cvLoadImage(filename.c_str(), 1);
263  if (p_cv == NULL) {
264 #if defined(BIAS_DEBUG) && defined(ImageIO_DEBUG_IO)
265  BIASERR("Reading image from " << filename << " with OpenCV failed!");
266 #endif
267  return -1;
268  }
269 
270  // convert IPL image from BGR to RGB color space for consistency reasons
271  if (p_cv->nChannels == 4) {
272  cvCvtColor(p_cv, p_cv, CV_BGRA2RGBA);
273  strcpy(p_cv->channelSeq, "RGBA");
274  } else if (p_cv->nChannels == 3) {
275  cvCvtColor(p_cv, p_cv, CV_BGR2RGB);
276  strcpy(p_cv->channelSeq, "RGB");
277  }
278 
279  // copy IPL image into BIAS image data
280  int res = BIAS::WrapBias2Ipl::CreateBiasImageCopy(p_cv, image);
281  cvReleaseImage(&p_cv);
282  return res;
283 }
284 
285 int ImageIO::
286 ExportOpenCV(const std::string &filename, const ImageBase &image)
287 {
288 #if defined(BIAS_DEBUG) && defined(ImageIO_DEBUG_IO)
289  CALLINFO;
290 #endif
291 
292  IplImage* p_cv = NULL;
293  int res = BIAS::WrapBias2Ipl::CreateIplImageShared(&image, p_cv);
294  if (res == 0) {
295  // convert IPL image from BGR to RGB color space for consistency reasons
296  if (p_cv->nChannels == 4) {
297  cvCvtColor(p_cv, p_cv, CV_BGRA2RGBA);
298  strcpy(p_cv->channelSeq, "RGBA");
299  } else if (p_cv->nChannels == 3) {
300  cvCvtColor(p_cv, p_cv, CV_BGR2RGB);
301  strcpy(p_cv->channelSeq, "RGB");
302  }
303  if (cvSaveImage(filename.c_str(), p_cv) == 0) {
304 #if defined(BIAS_DEBUG) && defined(ImageIO_DEBUG_IO)
305  BIASERR("Writing image to " << filename << " with OpenCV failed!");
306 #endif
307  res = -1;
308  }
309  // swap channels back into original order
310  if (p_cv->nChannels == 4)
311  cvCvtColor(p_cv, p_cv, CV_BGRA2RGBA);
312  else if (p_cv->nChannels == 3)
313  cvCvtColor(p_cv, p_cv, CV_BGR2RGB);
314  }
315  return res;
316 }
317 
318 #endif // BIAS_HAVE_OPENCV
319 
320 
321 #ifdef BIAS_HAVE_OPENEXR
322 /** Print header information to stream
323 helper function
324 @author Jan Woetzel 09/2005 */
325 int PrintInfoEXR(const Imf::RgbaInputFile & f, std::ostream & os)
326 {
327  using namespace Imf;
328  using namespace Imath;
329  os<<"OpenEXR header information: "<<endl;
330  os<<"version: "<<f.version()<<endl;
331  //os<<"isComplete: "<<f.isComplete()<<endl;
332 
333  // (meta) header
334  const Imf::Header * h = &f.header();
335  BIASASSERT(h!=NULL);
336  // data windows
337  Box2i dw = f.dataWindow();
338 
339  os<<"hasPreviewImage: "<<h->hasPreviewImage()<<endl;
340  os<<"pixelAspectRatio:"<<h->pixelAspectRatio()<<endl;
341  // OpenEXR can handle special image coordinate systems.
342  os<<"dw dim: "<<dw.max.x - dw.min.x + 1
343  <<" x "
344  <<dw.max.y - dw.min.y + 1
345  <<endl;
346  os<<" dw.x: "<<dw.min.x<<".."<<dw.max.x <<endl;
347  os<<" dw.y: "<<dw.min.y<<".."<<dw.max.y <<endl;
348 
349  return BIAS_IO_SUCCESS;
350 }
351 
352 
353 
354 int ImageIO::
355 ExportOpenEXR(const std::string& FileName, const ImageBase& img)
356 {
357 #if defined(BIAS_DEBUG) && defined(ImageIO_DEBUG_IO)
358  CALLINFO;
359 #endif
360  OpenEXRInterface interfaceEXR;
361  return interfaceEXR.Export(FileName, img);
362 }
363 
364 int ImageIO::
365 ImportOpenEXR(const std::string& FileName, ImageBase& result)
366 {
367 #if defined(BIAS_DEBUG) && defined(ImageIO_DEBUG_IO)
368  CALLINFO;
369 #endif
370  OpenEXRInterface interfaceEXR;
371  return interfaceEXR.Import(FileName, result);
372 }
373 
374 #endif // BIAS_HAVE_OPENEXR
375 
376 
377 int ImageIO::
378 ImportImage(const string& filename, ImageBase &result )
379 {
380 #if defined(BIAS_DEBUG) && defined(ImageIO_DEBUG_IO)
381  CALLINFO;
382 #endif
383 
384  int res=-1; // init as file not read
385  ifstream ifs;
386  unsigned char tmpline[512];
387 
388 #ifdef WIN32
389  ifs.open(filename.c_str(),ios::binary);
390 #else //not WIN32
391  ifs.open(filename.c_str());
392 #endif //WIN32
393 
394  if (!ifs) {
395  BIASERR("ImportImage(): open of file \""<<filename<<"\" failed");
396  perror(filename.c_str());
397  ifs.close();
398  return -1;
399  }
400 
401  // invalidate old uid, since it may refer to a different image
402  result.InvalidateUID();
403 
404  // read first two chars to get a hint what this file is
405  ifs >>tmpline[0]>>tmpline[1];
406  if (!ifs){
407  res=-1;
408  BIASERR("unable to read from "<<filename);
409  ifs.close();
410  return res;
411  }
412 
413  // Check for famous P5/P6 in PNM, PGM, PBM to determine the fileformat
414  // and call our own reader if appropriate.
415  if (tmpline[0] =='P' && tmpline[1] == '5') {
416 #if defined(BIAS_DEBUG) && defined(ImageIO_DEBUG_IO)
417  COUT("reading single channel pnm/pgm/pbm image using ImportImagePnm_\n");
418 #endif
419  res = ImportImagePnm_(ifs, result, 1);
420  if (res!=BIAS_IO_SUCCESS)
421  BIASERR("error reading "<<filename<<" although P5 format detected.");
423  } else if (tmpline[0] =='P' && tmpline[1] == '6') {
424 #if defined(BIAS_DEBUG) && defined(ImageIO_DEBUG_IO)
425  COUT("reading 3 channel pnm/pgm/pbm image using ImportImagePnm_\n");
426 #endif
427  res = ImportImagePnm_(ifs, result, 3);
428  if (res!= BIAS_IO_SUCCESS)
429  BIASERR("error reading "<<filename<<" although P6 format detected.");
431  }
432 
433  // other loaders do not use file stream but operate on filename directly
434  // and open theirselves.
435  ifs.close();
436 
437  //
438  // Try to read using external image loaders.
439  //
440  //try matlab
441  if(res!=BIAS_IO_SUCCESS)
442  res = ImportMatrix(filename,result,false);
443  // try EXR
444 #ifdef BIAS_HAVE_OPENEXR
445  if (res!=BIAS_IO_SUCCESS)
446  res=ImportOpenEXR(filename, result);
447 #endif
448 
449 #ifdef BIAS_HAVE_IMAGEMAGICKLIB
450  if (res!=BIAS_IO_SUCCESS)
451  res=ImportMagickPP(filename, result);
452 #endif
453 
454 #ifdef BIAS_HAVE_DEVIL
455  if (res!=BIAS_IO_SUCCESS)
456  res=ImportDevIL(filename, result);
457 #endif
458 
459 #ifdef BIAS_HAVE_LIBJPEG
460  if (res!=BIAS_IO_SUCCESS)
461  res=ImportLibJPEG(filename, result);
462 #endif
463 
464 #ifdef BIAS_HAVE_OPENCV
465  if (res!=BIAS_IO_SUCCESS)
466  res=ImportOpenCV(filename, result);
467 #endif
468 
469  //#ifdef BIAS_HAVE_RADIANCE
470  if (res!=BIAS_IO_SUCCESS)
471  res=ImportRADIANCE(filename, result);
472  //#endif
473 
474  // try to read RAW4096/RAW04096/RAW0nnnn format
475  if (res!=BIAS_IO_SUCCESS)
476  res=ImportRAWwithHeader(filename, result);
477 
478 #ifdef WIN32 // winapi
479  if (res!=BIAS_IO_SUCCESS)
480  res=Import_BITMAP_winapi(filename, result);
481 #endif
482 
483  /*
484  \bug incorrectly loads .bmp occasionally
485  due to too simple header parsing
486  e.g. Ibak Beton1200_Front47.bmp !
487  try to read VIFF if anything else failed
488  this is last try because the routine is buggy.
489  */
490  if (res!=BIAS_IO_SUCCESS) {
491  // open fstream
492  std::ifstream ifs(filename.c_str(), std::ios::binary );
493  if (!ifs) {
494  BIASERR("could not open "<<filename);
495  } else {
496  // OK
497  res=ImportImageViff_(ifs, result );
498  }
499  }
500 
501 
502  if (res==0){
503  // --- handle meta data ----------------
504  AppData ad;
505  if (result.GetMetaData()->Find(AppData::MD_UUID,"#[UUID]", ad)>=0){
506  if (ad.tag==AppData::MD_USE_ASCII){
507  //cerr << "before |"<< ad.sdata <<"|"<< endl ;
508  while (ad.sdata.length()>0 && (ad.sdata[0]=='#' || ad.sdata[0]==' ' ||
509  ad.sdata[0]=='\n'))
510  ad.sdata.erase(0, 1);
511  if (ad.sdata.length()>36)
512  ad.sdata.erase(36, ad.sdata.length()-36);
513  //cerr<<"after |"<<ad.sdata<<"|"<<" length: "<<ad.sdata.length()<<endl;
514  UUID TempID(ad.sdata);
515  result.SetUID(TempID);
516  } else {
517  BIASERR("UUID is no meta datum in binary images");
518  BIASERR("possibly two concurrent UUIDs in one image");
519  //result.SetUID(*((UUID*)ad.data));
520  //BIASASSERT(false);
521  BIASABORT;
522  }
523  } else {
524 #ifdef BIAS_DEBUG
525 # ifdef BIAS_EXTRA_WARN
526  BIASERR("warning, no valid UID read, UUID must be set manually");
527 # endif
528 #endif
529  result.InvalidateUID();
530  }
531  //cerr <<"header in ImportImage"<<endl;
532  //result.PrintHeader(cout);
533  }
534  return res;
535 } // ImportImage
536 
537 
538 #ifdef BIAS_HAVE_LIBJPEG
539 int ImageIO::
540 ImportLibJPEG(const string& filename, ImageBase &result,
541  bool readComment)
542 {
543 #if defined(BIAS_DEBUG) && defined(ImageIO_DEBUG_IO)
544  CALLINFO;
545 #endif
546 
547  // Release result first
548  if (!result.IsEmpty()){
549  result.Release(true);
550  }
551 
552  // Data structures
553  int res = 0;
554  BIAS::JpegHandler jHandler;
556  jHandler.SetVerbose(false);
557  res = jHandler.Init();
558  if (res == 0) {
559  res = jHandler.ReadJPEG(filename);
560  }
561  if (res == 0) {
562  res = jHandler.Decompress(image, readComment);
563  }
564  jHandler.Release();
565 
566  // Apply image to result
567  if (res == 0) {
568  result = image;
569  }
570  return (res == 0 ? BIAS_IO_SUCCESS : -1);
571 }
572 #endif
573 
574 
575 int ImageIO::ImportImagePnm_(ifstream& ifs, ImageBase &result, int depth)
576 {
577 #if defined(BIAS_DEBUG) && defined(ImageIO_DEBUG_IO)
578  CALLINFO;
579 #endif
580 
581  int xres=-1, yres=-1, maxval=-1, read=0;
582  int res=0;
583  char c;
584 
585  if (!result.IsEmpty()) result.Release(true);
586  // start from the beginning and read line with P5 or P6
587  ifs.seekg(0,ios::beg);
588 
589  ifs >> c;
590  // cout << "format " << c;
591  if (c!='P'){
592  BIASERR("invalid magic cookie");
593  return -1;
594  }
595  ifs >> c;
596  //cout << c << endl;
597  if (c!='5' && c!='6'){
598  BIASERR("invalid magic cookie");
599  return -1;
600  }
601 
602  // this allows an arbitary amount of whitespace in between the header
603  while (read<3){
604  ifs >> c;
605  ifs.putback(c);
606  if (c=='#'){
607  ifs >> *result.GetMetaData();
608  if (!ifs){
609  BIASERR("error reading meta data");
610  return -1;
611  }
612  } else if (c>29 || c<40){ // number 0-9
613  switch (read){
614  case 0:
615  ifs >> xres;
616  // cerr << "xres: "<<xres<<endl;
617  read++;
618  break;
619  case 1:
620  ifs >> yres;
621  // cerr << "yres: "<<yres<<endl;
622  read++;
623  break;
624  case 2:
625  ifs >> maxval;
626  // cerr << "maxval: "<<maxval<<endl;
627  read++;
628  break;
629  default:
630  BIASERR("funny error: "
631  <<"there should be only 3 numerical values in pgm header");
632  return -1;
633  break;
634  }; // switch
635  } else { // if (c>29 || c<40){
636  BIASERR("corrupted image header "<<c);
637  }
638  }
639  ifs.read(&c, 1*sizeof(char)); // last whitespace
640 
641  //cerr <<"image has size "<<xres<<"x"<<yres<<" with maxval "<<maxval<<endl;
642  if (maxval==255){
643 #ifdef BIAS_DEBUG
646  BIASERR("warning trying to load an unsigned char image into an image of"
647  <<" storage type "<<result.GetStorageType());
648  //BIASASSERT(false);
649  BIASABORT;
650  }
651 #endif
652  result.Init(xres, yres, depth, ImageBase::ST_unsignedchar);
653  ifs.read(reinterpret_cast<char *>(result.GetImageData()), xres * yres * depth);
654  } else if (maxval==4095){ // 12 bit images
655 #ifdef BIAS_DEBUG
658  BIASERR("WARNING: Trying to load an unsigned short int image into an "
659  <<"image of storage type "<<result.GetStorageType() << "!");
660  }
661 #endif
662  result.Init(xres, yres, depth, ImageBase::ST_unsignedshortint);
663  result.SetBitDepth(12);
664  ifs.read(reinterpret_cast<char *>(result.GetImageData()),
665  sizeof(unsigned short int) * xres * yres * depth);
666  // check if bytes need swapping
667  unsigned short int *p=(unsigned short int *)result.GetImageData(), *pe;
668  pe=p+result.GetPixelCount()*result.GetChannelCount();
669  // check if pixel > maxval exist
670  bool swap=false;
671  while (p<pe) { swap = (swap || (*p > maxval)); p++; }
672  // swap bytes if pixel > maxval existed
673  if (swap){
674  BIASERR("Max. value > "<<maxval<<" : Swapping LSB and MSB!");
675  char *cp=(char *)result.GetImageData(), *cpe;
676  cpe=(char *)((unsigned short int *)cp + result.GetPixelCount()*
677  result.GetChannelCount());
678  char c;
679  while (cp<cpe){
680  c=cp[0]; cp[0]=cp[1]; cp[1]=c;
681  cp+=2;
682  }
683  }
684  } else if(maxval==65535){ // 16 bit images
685 #ifdef BIAS_DEBUG
688  BIASERR("WARNING: Trying to load an unsigned short int image into an "
689  <<"image of storage type "<<result.GetStorageType()<<"!");
690  }
691 #endif
692  result.Init(xres, yres, depth, ImageBase::ST_unsignedshortint);
693  result.SetBitDepth(16);
694  ifs.read(reinterpret_cast<char *>(result.GetImageData()),
695  sizeof(unsigned short int) * xres * yres * depth);
696  // check if bytes need swapping
697  unsigned short int *p=(unsigned short int *)result.GetImageData(), *pe;
698  pe=p+result.GetPixelCount()*result.GetChannelCount();
699  // check if pixel > maxval exist
700  bool swap=true;
701  while (p<pe) { swap = (swap || (*p > maxval)); p++; }
702  // swap bytes if pixel > maxval existed
703  if (swap){
704  BIASERR("Max. value > "<<maxval<<" : Swapping LSB and MSB!");
705  char *cp=(char *)result.GetImageData(), *cpe;
706  cpe=(char *)((unsigned short int *)cp + result.GetPixelCount()*
707  result.GetChannelCount());
708  char c;
709  while (cp<cpe){
710  c=cp[0]; cp[0]=cp[1]; cp[1]=c;
711  cp+=2;
712  }
713  }
714  }
715 
716  if (!ifs.good()){
717  BIASERR("error reading from ifs");
718  res=-1;
719  }
720  return res;
721 }
722 
723 
724 int ImageIO::
725 Save(const string& c_filename,
726  const ImageBase &img_const,
727  const enum TFileFormat c_FileFormat,
728  const bool sync,
729  const int c_jpeg_quality,
730  const bool forceNewID,
731  const bool & writeMetaData)
732 {
733 #if defined(BIAS_DEBUG) && defined(ImageIO_DEBUG_IO)
734  CALLINFO;
735 #endif
736  bool TriedIt = false;
737 
738  ImageBase img(img_const);
739  int result = -1;
740 #if defined(BIAS_HAVE_IMAGEMAGICKLIB) || defined(BIAS_HAVE_LIBJPEG)
741  int quality = c_jpeg_quality;
742 #endif
743 
744  // non const to change for auto detection:
745  TFileFormat FileFormat=c_FileFormat;
746  if (FileFormat==FF_auto)
747  {
748  // determine by filename extension:
749  FileFormat=GetFileFormat(c_filename);
750  // if we couldn't determine BIAS FileFormat
751  // give the external libs their own "low level" try
752  if (FileFormat==FF_unknown)
753  FileFormat=FF_auto;
754  }
755 
756  // non const for adding suffix
757  string filename(c_filename);
758  FileHandling::FilenameExpansion (c_filename, filename); // tilde
759 
761  BIASERR("cannot save images with StoragType ST_invalid. ");
762  return -1;
763  }
764 
765  // -----------------------------------------------------
766  // -- UUID handling following the idea
767  // -- if the image does not have a UUID we generate one that is written to disk.
768  // Q: Shall the ID be assigned to the orig. image "by ref." too
769  // which results in a *non* const image?
770  // A: Yes, we want the side effect of assigning the ID by reference,
771  // and not only to the local copy for disk only. (koeser, 12/Dec/2005)
772  // However, this behavior will change when we adopt the calling code
773  // to make img const.
774  // changed, woelk 09/2006
775  // -----------------------------------------------------
776 
777  // force a fresh UID
778  if (forceNewID) {
779  img.SetUID(UUID::GenerateUUID());
780  }
781 
782  // append to metadataonly if newID forced or metadata is
783  // really written to avoid side effect in the long run
784  if (writeMetaData && (!img.GetUID().IsValid()))
785  {
786  // the image to be saved will become const some day
787  BIASWARN("UUID assignment required. Please fix your code and assign a UID in the calling function if desired.");
788  img.SetUID(UUID::GenerateUUID());
789  }
790  // write uuid to meta data if valid (only temporary to utilize metadata i/o)
791  if (writeMetaData)
792  {
793  BIASASSERT( img.GetUID().IsValid() );
794  string suuid;
795  img.GetUID().GetString(suuid);
796  img.GetMetaData()->Add("#[UUID]", suuid);
797  }
798 
799 
800  // -------------------------------------------------------------
801  // --- try to write with our internal format handlers, first.
802  // -------------------------------------------------------------
803 
804  if (result!=BIAS_IO_SUCCESS)
805  {
806  // construct valid filename with appropriate extension
807  switch (FileFormat)
808  {
809  case FF_auto:
810  case FF_unknown:
811  // leave the filename as it is for fmt detection by filename.
812  break;
813  case FF_mip:
814  filename =ImageIO::ExtensionName( filename, GetExtension(FileFormat) );
815  result = Write_(filename, img, sync, forceNewID);
816  TriedIt = true;
817  break;
818  case FF_matrix:
819  filename =ImageIO::ExtensionName( filename, GetExtension(FileFormat) );
820  result = ExportMatrix(filename, img, false);
821  TriedIt = true;
822  break;
823  case FF_pgm:
824  case FF_ppm:
825  {
826  filename = ExtensionName( filename, GetExtension(FileFormat) );
827  // use our internal impl. only for 8bit, 16 bit is impl. incorrectly
828  if (img.GetDepth()==1) /* Byte per Channel */
829  {
830  if ((FileFormat==FF_pgm) && (img.GetChannelCount()!=1))
831  {
832  // we need to convert:
833  Image<unsigned char> greyIMG(img);
834  ImageConvert::IP_ToGrey(greyIMG);
835  result = ExportImagePnm_(filename,greyIMG,sync,writeMetaData);
836  TriedIt = true;
837  } else {
838  // no slow conversion, is already correct fmt
839  result = ExportImagePnm_(filename,img,sync,writeMetaData);
840  TriedIt = true;
841  };
842  }
843  }
844  break;
845  case FF_jpg:
846  #if defined(BIAS_HAVE_IMAGEMAGICKLIB) || defined(BIAS_HAVE_LIBJPEG)
847  filename = ImageIO::ExtensionName( filename, GetExtension(FileFormat) );
848  if (c_jpeg_quality < 0 || c_jpeg_quality > 100)
849  {
850  BIASERR("The quality "<<c_jpeg_quality
851  <<" is out of valid range 0..100 % falling back to 100% full quality." );
852  quality=100;
853  }
854  #else
855  BIASERR("No JPEG support activated in BIAS. Switch on ImageMagick or LibJPEG in BIAS to enable jpeg support.");
856  #endif
857 
858 
859  break;
860  //todo move writing raw4096 images from GrabApp here
861  case FF_raw4096:
862  BIASERR("writing raw4096 is not (yet) implemented in BIAS, only on WIN32 scorpion grab application.");
863  return -7;
864  break;
865  // we could add our internal handlers for pnm, here.
866  // however - the ImageMagic and DevIL versions
867  // are more reliable, in particular for hdr formats.
868  case FF_bmp:
869  case FF_pbm:
870  case FF_tif:
871  case FF_png:
872  case FF_viff:
873  case FF_exr:
874  case FF_dds:
875  filename = ExtensionName( filename, GetExtension(FileFormat) );
876  break;
877  default:
878  BIASERR("Unknown image file format for saving "<<c_filename<<" with format:"<<FileFormat<<" Nothing saved!");
879  return -1;
880  } // switch
881  }
882 
883  // --------------------------------------------------
884  // --- Try to write using external libraries. ---
885  // --------------------------------------------------
886 
887  if (result!=BIAS_IO_SUCCESS) {
888  if (FileFormat==FF_matrix) {
889  result= ExportMatrix(filename,img,false);
890  }
891  }
892 
893 #ifdef BIAS_HAVE_OPENEXR
894  if (result!=BIAS_IO_SUCCESS) {
895  // handle only those formats OpenEXR supports
896  if (FileFormat==FF_exr) {
897  result=ExportOpenEXR(filename, img );
898  TriedIt = true;
899  }
900  }
901 #endif
902 
903 #ifdef BIAS_HAVE_IMAGEMAGICKLIB
904  // try to use ImageMagick++ library.
905  if (result!=BIAS_IO_SUCCESS) {
906  // skip the formats ImageMagick cannot handle,
907  // at least those it claims to handle but is doing wrong things (e.g. dds)
908  if ((FileFormat!=FF_dds) && (FileFormat!=FF_exr) &&
909  (FileFormat!=FF_mip) && (FileFormat!=FF_raw4096))
910  {
911  result=ExportMagickPP (filename, img, quality, writeMetaData);
912  TriedIt = true;
913  }
914  }
915 #endif
916 
917 #ifdef BIAS_HAVE_DEVIL
918  // try to use DevIL library
919  if (result!=BIAS_IO_SUCCESS) {
920  if ((FileFormat!=FF_exr) && (FileFormat!=FF_mip) &&
921  (FileFormat!=FF_raw4096))
922  {
923  result=ExportDevIL(filename, img);
924  TriedIt = true;
925  }
926  }
927 #endif
928 
929 #ifdef BIAS_HAVE_LIBJPEG
930  // try to use jpeg library
931  if (result!=BIAS_IO_SUCCESS){
932  if (FileFormat == FF_jpg) {
933  result=ExportLibJPEG(filename, img);
934  TriedIt = true;
935  }
936  }
937 #endif
938 
939 #ifdef BIAS_HAVE_OPENCV
940  // try to use OpenCV library
941  if (result != BIAS_IO_SUCCESS) {
942  result = ExportOpenCV(filename, img);
943  TriedIt = true;
944  }
945 #endif
946 
947  if (!TriedIt)
948  BIASERR("Image not even tried to be written");
949 
950  // final result:
951  return result;
952 }
953 
954 #ifdef BIAS_HAVE_LIBJPEG
955 int ImageIO::
956 ExportLibJPEG(const std::string &filename,
957  const BIAS::ImageBase &image,
958  const int quality)
959 {
960 #if defined(BIAS_DEBUG) && defined(ImageIO_DEBUG_IO)
961  CALLINFO;
962 #endif
963 
964  if (quality < 0 || quality > 100) {
965  BIASERR("Invalid quality " << quality << " given for JPEG compression!");
966  return -1;
967  }
968 
969  // Convert image to unsigned char
972 
973  // Data structures
974  int res = 0;
975  BIAS::JpegHandler jHandler;
976  jHandler.SetVerbose(false);
977  res = jHandler.Init();
978  if (res == 0) {
979  res = jHandler.Compress(image_UC, quality);
980  }
981  if (res == 0) {
982  res = jHandler.WriteJPEG(filename);
983  }
984  jHandler.Release();
985 
986  return (res == 0 ? BIAS_IO_SUCCESS : -1);
987 }
988 #endif
989 
990 int ImageIO::
991 ExportImagePnm_(const string &FileName,
992  const ImageBase &img,
993  bool sync,
994  const bool & writeMetaData)
995 {
996 #if defined(BIAS_DEBUG) && defined(ImageIO_DEBUG_IO)
997  CALLINFO;
998 #endif
999  ofstream ofs;
1000  // bool sync=false;
1001 
1002 #ifdef WIN32
1003  ofs.open(FileName.c_str(),ios::binary);
1004 #else //not WIN32
1005  ofs.open(FileName.c_str());
1006 #endif //WIN32
1007 
1008  if (!ofs) {
1009  BIASERR("ExportImagePnm_() : open of file "<<FileName<<" failed");
1010  perror(FileName.c_str());
1011  return -1;
1012  }
1013 
1014 #ifdef BIASDEBUG
1015  if (img.GetDepth()!=1)
1016  BIASERR(FUNCNAME <<" supports only 8 bit per Channel images. Please call "
1017  <<"ExportImage or Save instead.");
1018 #endif // BIASDEBUG
1019 
1020  switch (img.GetChannelCount()) {
1021  case 3: // 8bit ppm
1022  ofs <<"P6"<<endl;
1023  break;
1024 
1025  case 1: // 8bit pgm
1026  ofs << "P5"<<endl;
1027  break;
1028  default:
1029  BIASERR("ExportImagePnm_() : unsupported number of channels: "<<
1030  img.GetChannelCount());
1031  return -1;
1032  }
1033 
1034  if (writeMetaData){
1035  img.GetMetaData()->WriteAscii(ofs);
1036  if (!ofs){
1037  BIASERR("writing MetaData failed");
1038  return -2;
1039  }
1040  };
1041 
1042  ofs << img.GetWidth()<<" "<<img.GetHeight()<<endl;
1043  ofs << "255"<<endl;
1044 
1045  ofs.write(reinterpret_cast<const char *>(img.GetImageData()), img.GetSizeByte());
1046  if(!ofs) {
1047  BIASERR("ExportImagePnm_() : write failed");
1048  return -1;
1049  }
1050 
1051  if (sync) {
1052  // flush streambuf from c++
1053  ofs.flush();
1054  // flush system buffers
1055 #ifndef _WIN32
1056 # if __GNUC__ < 3
1057  fsync(ofs.rdbuf()->fd());
1058 # else
1059  ofs.rdbuf()->pubsync();
1060 # endif
1061 #else // _WIN32
1062  ofs.rdbuf()->pubsync();
1063 #endif //_WIN32
1064  }
1065 
1066  ofs.close();
1067  return 0;
1068 }
1069 
1070 
1071 std::string ImageIO::
1072 ExtensionName(const std::string & oldName,
1073  const std::string & newExtension)
1074 {
1075  string name = oldName; // full name
1076  string ext = FileHandling::Extension( oldName );
1077  string base = FileHandling::DirectoryAndBasename(oldName );
1078  string newExtLC= FileHandling::LowerCase( newExtension );
1079 
1080  // catch empty file name:
1081  if (base.size()<1)
1082  base="out___"; // default
1083 
1084  // append extension if it is not the correct case insensitive extension:
1085  if (ext!=newExtLC) {
1086  name = base;
1087  if (name[name.size()-1] != '.')
1088  name+= ".";
1089  name+=newExtLC;
1090  }
1091  return name;
1092 }
1093 
1094 
1095 int ImageIO::
1096 Write_(const string& FileName, const ImageBase &img_const,
1097  bool sync, bool forceNewID)
1098 {
1099 #if defined(BIAS_DEBUG) && defined(ImageIO_DEBUG_IO)
1100  CALLINFO;
1101 #endif
1102 
1103  int res = 0;
1104  ofstream os;
1105 
1106  ImageBase img(img_const);
1107 
1108  // assign new id if forced or there is none yet
1109  if ((forceNewID) || (!img.GetUID().IsValid())) {
1110  img.SetUID(UUID::GenerateUUID());
1111  }
1112 
1113  // avoid ".mip.mip"
1114  string file = ImageIO::ExtensionName( FileName, "mip");
1115 
1116 #ifdef WIN32
1117  os.open(file.c_str(),ios::binary);
1118 #else //not WIN32
1119  os.open(file.c_str());
1120 #endif //WIN32
1121 
1122  if (!os){
1123  string Errorstring="Error opening "+file+" writing";
1124  perror(Errorstring.c_str());
1125  return -1;
1126  }
1127 
1128  //write image
1129  os << img;
1130 
1131  res = (os.good())?(0):(-5);
1132 
1133  if (res==0){
1134  //cerr <<"Writing MetaData\n";
1135  //img.GetMetaData()->Dump();
1136  img.GetMetaData()->WriteBinary(os);
1137  if (!os){
1138  BIASERR("writing MetaData failed");
1139  res=-6;
1140  }
1141  }
1142 
1143  if (sync) {
1144  // flush streambuf from c++
1145  os.flush();
1146  // flush system buffers
1147 #ifndef _WIN32
1148 # if __GNUC__ < 3 // in gcc 2.9x we can get a POSIX file descriptor
1149  fsync(os.rdbuf()->fd());
1150 # else // in gcc 3.x this is prohibited :-(
1151  os.rdbuf()->pubsync();
1152  // ::sync(); // this is systemcall sync() to sync all buffers
1153 # endif
1154 #else // _WIN32
1155  /** @todo Sync written files and buffers to disk under WIN32
1156  (evers 2004-10-14) */
1157  // os.rdbuf()->pubsync();
1158  // ::sync();
1159 #endif // _WIN32
1160  }
1161  os.close();
1162 
1163 #ifndef _WIN32 // alternative way to sync, reopen file to get a handle
1164  int fd = open(file.c_str(),O_APPEND);
1165  fsync(fd); // and now fsync()
1166  close(fd);
1167 #endif
1168  return res;
1169 }
1170 
1171 
1172 int ImageIO::
1173 WriteRAW_IMA(const string& FileName, const ImageBase &img_const)
1174 {
1175 #if defined(BIAS_DEBUG) && defined(ImageIO_DEBUG_IO)
1176  CALLINFO;
1177 #endif
1178 
1179  int res = 0;
1180  ofstream os;
1181 
1182  //is a planar image!
1183  ImageBase img(img_const);
1184  if(img.IsInterleaved()) {
1185  BIASERR("need planar image!");
1186  return -1;
1187  }
1188  short intro = 0;
1189  short width = static_cast<short>(img.GetWidth());
1190  short height = static_cast<short>(img.GetHeight());
1191  short channels = static_cast<short>(img.GetChannelCount());
1192  unsigned char* pel = (unsigned char*)img.GetImageData();
1193 
1194  string file = ImageIO::ExtensionName( FileName, "ima");
1195 
1196  // #ifdef WIN32
1197  // os.open(file.c_str(),ios::binary);
1198  // #else //not WIN32
1199  os.open(file.c_str(),ios::binary);
1200  // #endif //WIN32
1201 
1202  if (!os){
1203  string Errorstring="Error opening "+file+" writing";
1204  perror(Errorstring.c_str());
1205  return -1;
1206  }
1207 
1208  // cout<<sizeof(short)<<endl;
1209  os.write((char*)&intro, sizeof(short));
1210  os.write((char*)&width, sizeof(short));
1211  os.write((char*)&channels, sizeof(short));
1212  for(unsigned int i=0; i<(unsigned int)width*height*3; i++) {
1213  unsigned char out = 255 - pel[i] ;
1214  os.write((char*)&(out), sizeof(unsigned char));
1215  // cerr<<i<<endl;
1216  }
1217 
1218 
1219  res = (os.good())?(0):(-5);
1220 
1221  os.close();
1222 
1223 #ifndef _WIN32 // alternative way to sync, reopen file to get a handle
1224  int fd = open(file.c_str(),O_APPEND);
1225  fsync(fd); // and now fsync()
1226  close(fd);
1227 #endif
1228  return res;
1229 }
1230 
1231 int ImageIO::
1232 ImportMatrix(const std::string &FileName,
1233  ImageBase &img, const bool verbose)
1234 {
1235  if(FileHandling::Extension(FileName)!="matrix") return -1;
1236 
1237  if(verbose) cout<<"converting textfile to image matrix...\n";
1238  ifstream in(FileName.c_str());
1239  if (in.fail()) {
1240  BIASERR("could not load"<<FileName);
1241  return -2;
1242  }
1243  unsigned int rows,cols,cc, interleaved;
1244  in >> rows >> cols >> cc >> interleaved;
1245 
1246  if(verbose){
1247  cout<<"Rows:"<<rows<<" Cols:"<<cols
1248  <<" Channelcount:"<<cc<<" Interleaved:"<<interleaved<<"\n";
1249  }
1250  img.Init(cols, rows, 1, ImageBase::ST_float);
1251  float **data = (float**)img.GetImageDataArray();
1252  for (unsigned int h=0; h<rows; h++) {
1253  for (unsigned int w=0; w<cols; w++) {
1254  for (unsigned int c=0; c<cc; c++) {
1255  if(interleaved!=0) //interleaved case
1256  in >> data[h][w*cc+c];
1257  else //planar case
1258  in >> data[h+rows*c][w];
1259  }
1260  }
1261  }
1262  in.close();
1263  return 0;
1264 }
1265 
1266 
1267 int ImageIO::
1268 ExportMatrix(const std::string &FileName,
1269  const ImageBase &ipic,const bool verbose)
1270 {
1271  if(FileHandling::Extension(FileName)!="matrix") {
1272  return -1;
1273  }
1274 
1275  if(verbose) cout<<"converting image matrix to textfile...\n";
1276  if(ipic.GetChannelCount()!=1) {
1277  BIASERR("conversion only implemented for single channel images");
1278  return -2;
1279  }
1280  unsigned int rows,cols,cc, interleaved;
1281  rows = ipic.GetHeight();
1282  cols = ipic.GetWidth();
1283  cc = ipic.GetChannelCount();
1284  interleaved = ipic.IsInterleaved()?1:0;
1285  if(verbose)
1286  cout<<"Rows:"<<rows<<" Cols:"<<cols
1287  <<" Channelcount:"<<" interleaved:"<<interleaved<<cc<<"\n";
1288  //open file
1289  ofstream ofs(FileName.c_str());
1290  if(!ofs) {
1291  BIASERR("Could not open stream to "<<FileName);
1292  return -4;
1293  }
1294  ofs<<rows<<" "<<cols<<" "<<cc<<" "<<interleaved<<endl;
1295 
1296 
1297  if(ipic.GetStorageType() == ImageBase::ST_float)
1298  {
1299  float** imageDataArray = (float**)ipic.GetImageDataArray();
1300 
1301  for(unsigned int h = 0; h< rows; h++) {
1302  //image rows are matrix rows
1303  for(unsigned w = 0; w< cols; w++) {
1304  for(unsigned c = 0; c< cc; c++) {
1305  if(interleaved!=0) //interleaved case
1306  ofs<<imageDataArray[h][w*cc+c];
1307  else //planar case
1308  ofs<<imageDataArray[h+rows*c][w];
1309  ofs<<" ";
1310  }
1311  }
1312  ofs<<endl;
1313  }
1314  } else if(ipic.GetStorageType() == ImageBase::ST_unsignedchar)
1315  {
1316  unsigned char** imageDataArray = (unsigned char**)ipic.GetImageDataArray();
1317  for(unsigned int h = 0; h< rows; h++) {
1318  //image rows are matrix rows
1319  for(unsigned w = 0; w< cols; w++) {
1320  for(unsigned c = 0; c< cc; c++) {
1321  if(interleaved!=0) //interleaved case
1322  ofs<<imageDataArray[h][w*cc+c];
1323  else //planar case
1324  ofs<<imageDataArray[h+rows*c][w];
1325  ofs<<" ";
1326  }
1327  }
1328  ofs<<endl;
1329  }
1330  } else {
1331  BIASERR("Unsupported storage type of input image");
1332  return -3;
1333  }
1334  ofs.close();
1335  if (verbose) cout <<"done"<<endl;
1336  return 0;
1337 }
1338 
1339 
1340 int ImageIO::
1341 Read_(const string& FileName, ImageBase &img)
1342 {
1343 #if defined(BIAS_DEBUG) && defined(ImageIO_DEBUG_IO)
1344  CALLINFO;
1345 #endif
1346 
1347  int res=0;
1348  ifstream is;
1349 
1350 #ifdef WIN32
1351  is.open(FileName.c_str(),ios::binary);
1352 #else //not WIN32
1353  is.open(FileName.c_str());
1354 #endif //WIN32
1355 
1356  if (!is){
1357  string Errorstring="Error opening "+FileName+" for reading";
1358  perror(Errorstring.c_str());
1359  return -1;
1360  }
1361  is >> img;
1362 
1363 
1364  res = (is.good())?(0):(-5);
1365 
1366  if (res==0){
1367  // cerr << "ImageIO::Load() : "<<is.tellg()<<endl;
1368  is >> *img.GetMetaData();
1369  if (!is && !is.eof()){
1370  BIASERR("error reading MetaData");
1371  res = -6;
1372  }
1373  }
1374 
1375  // img.GetMetaData()->Dump();
1376 
1377  is.close();
1378 
1379 
1380  return res;
1381 }
1382 
1383 
1384 
1385 int ImageIO::
1386 ImportImageViff_(std::ifstream& ifs, ImageBase &result)
1387 {
1388 #if defined(BIAS_DEBUG) && defined(ImageIO_DEBUG_IO)
1389  CALLINFO;
1390 #endif
1391 
1392  /*class*/ xvimage viff;
1393  if (!ifs)
1394  return -1;
1395  if (!result.IsEmpty()) result.Release(true);
1396  ifs.seekg(0, ios::beg);
1397 
1398  // read header struct
1399  ifs.read((char*)&viff,sizeof(viff));
1400 #if defined(BIAS_DEBUG) && defined(ImageIO_DEBUG_IO)
1401  cout <<"read viff size "<<viff.row_size<<" x "<<viff.col_size<<endl;
1402 #endif
1403  // too big viff image size usually means it is no viff image
1404  // and would blow memory 08/2005)
1405  const unsigned long maxUsefulDim=4096*2;
1406  const unsigned long minUsefulDim=8;
1407  if ( viff.row_size>maxUsefulDim
1408  || viff.col_size>maxUsefulDim
1409  || viff.row_size<minUsefulDim
1410  || viff.col_size<minUsefulDim
1411  )
1412  {
1413  // corrupt image?
1414 #if defined(BIAS_DEBUG) && defined(ImageIO_DEBUG_IO)
1415  BIASERR(
1416  "viff image dim "<<viff.row_size<<"x"<<viff.col_size<<" is not useful(>"<<maxUsefulDim<<"),"<<endl
1417  <<"handling it as error. Skipping viff read. Adapt maxUsefulDim if you feel this behavior is wrong. "
1418  );
1419 #endif
1420  return -1; // error
1421  }
1422 
1423  // if (xres %4 >0) xresaligned = xres - xres%4;
1424  // else xresaligned = xres;
1425 
1426  //result.Init(xresaligned, yres, depth, ImageBase::ST_unsignedchar);
1427  result.Init(viff.row_size, viff.col_size,
1428  1, ImageBase::ST_float); // 1 is the number of channels
1429  // cerr << "initialized with " << xres << " " << yres
1430  // << " unsigned char" << endl;
1431 
1432  // read data area
1433  ifs.read(reinterpret_cast<char*>(result.GetImageData()), result.GetSizeByte());
1435 
1436  return 0; // ok
1437 }
1438 
1439 
1440 #ifdef BIAS_HAVE_IMAGEMAGICKLIB
1441  /** @brief: This routine is working inefficiently,
1442  because it doesn't know what to do about conversion if read and requested
1443  types don't match (10/2004)
1444  However it works and assumes RGB in case of doubt.
1445  \todo rewrite by making more use of type Image<..> instead of ImageBase
1446  because lossless conversions and warnings for unwanted lossy conversions
1447  are easier, then.
1448  @author Jan Woetzel 10/2004 */
1449 int ImageIO::
1450 ImportMagickPPAutoconvert(const std::string& FileName,
1451  ImageBase& result,
1452  const bool &/*assumeGrey*/,
1453  const bool &readMetaData )
1454 {
1455 #if defined(BIAS_DEBUG) && defined(ImageIO_DEBUG_IO)
1456  CALLINFO;
1457 #endif
1458 
1459 #ifdef WIN32
1460  // initialize DLL loaded library (not required on Linux but once on Windows)
1461  Magick::InitializeMagick(NULL);
1462 #endif
1463 
1464  try {
1465 
1466  Magick::Image image; // temporary converter for lib usage
1467 
1468  // Read a file into image object using Magick++ library function:
1469  image.read( FileName );
1470 
1471 #if defined(BIAS_DEBUG) && defined(ImageIO_DEBUG_IO)
1472  COUT(
1473  "DBG Read "<<image.columns()<<"x"<<image.rows()<<" "
1474  <<image.magick()<<" image "
1475  <<FileName<<" using ImageMagick++"<<endl
1476  <<" depth: "<<image.depth()<<" bit."<<endl
1477  <<" comment: "<<endl<<image.comment()<<endl
1478  );
1479 #endif
1480 
1481  // determine if import image format/channels and bit depth match:
1482  Magick::StorageType outputST=Magick::CharPixel; // output storage type
1483 
1484  /** keep the output storagetype
1485  \todo TODO HACK add dynamic cast test for templated Image<> to convert loaded float image automatically to uc etc..
1486  \todo add more knowledge about conversion and the option of errors if requested and read type don't match.
1487  check if at least StorageType and bit depth match:
1488  */
1489  //
1490  // first switch: ouput storagetype
1491  //
1492  switch (result.GetStorageType())
1493  {
1495  BIASERR("invalid Storagetype ST_invalid FileName="<<FileName<<endl);
1496  break;
1497 
1500  // 8 bit
1501  if (image.depth() != 8*sizeof(char)){
1502  BIASERR("StorageType is "<<8*sizeof(char)<<" bit but data has "<<image.depth()<<" bit depth. FileName="<<FileName<<endl);
1503  /** \todo handle conversion in extra routine
1504  with extra warnings in case of scaling or lossy conversion.
1505  -Add a 'normalized scale' per conversion for each Storagetype.
1506  -Add a flag to return errors instead of run-time warning. (discussion 26.Oct.2004) */
1507  return -1;
1508  } else {
1509  outputST=Magick::CharPixel;
1510  COUT("is an "<<8*sizeof(char)<<" bit (u)char image\n");
1511  };
1512  break;
1513 
1516  // 16 bit
1517  if (image.depth()!=8*sizeof(short)){
1518  BIASERR("StorageType is "<<8*sizeof(short)<<" bit "
1519  <<"but data has "<<image.depth()<<" bit depth. "
1520  <<"FileName="<<FileName<<endl);
1521  return -2;
1522  } else {
1523  outputST=Magick::ShortPixel;
1524  COUT("is a "<<8*sizeof(short)<<" bit (u)short image\n");
1525  };
1526  break;
1527 
1530  // 32 bit int
1531  if (image.depth()==8*sizeof(int)){
1532  BIASERR("StorageType is "<<8*sizeof(int)<<" bit but data has "<<image.depth()<<" bit depth. FileName="<<FileName<<endl);
1533  return -3;
1534  } else {
1535  outputST=Magick::IntegerPixel;
1536  COUT("is a "<<8*sizeof(int)<<" bit (u)int image\n");
1537  };
1538  break;
1539 
1540  /** \todo float and double pixel are 0..1 normalized range in ImageMagick++. Min, max meta data required */
1542  // 32 bit float
1543  if (image.depth()!=8*sizeof(float)) {
1544  BIASERR("StorageType is "<<8*sizeof(float)<<" bit but data has "<<image.depth()<<" bit depth. FileName="<<FileName<<endl);
1545  return -4;
1546  } else {
1547  outputST=Magick::FloatPixel;
1548  COUT("is a "<<8*sizeof(float)<<" bit float image\n");
1549  BIASERR("warning: You are using ImageMagick to read a float image. Be aware that ImageMagick float values are normalized to 0..1 !!!"<<endl);
1550  };
1551  break;
1552 
1554  // 64 bit double
1555  if (image.depth()!=8*sizeof(double)){
1556  BIASERR("StorageType is "<<8*sizeof(double)<<" bit but data has "<<image.depth()<<" bit depth. FileName="<<FileName<<endl);
1557  return -4;
1558  } else {
1559  outputST=Magick::DoublePixel;
1560  COUT("is a "<<8*sizeof(double)<<" bit float image\n");
1561  BIASERR("warning: You are using ImageMagick to read a double image. Be aware that ImageMagick float values are normalized to 0..1 !!!"<<endl);
1562  };
1563  break;
1564 
1565  default:
1566  BIASERR("StorageType "<<result.GetStorageType()<<" not supported. FileName="<<FileName<<endl);
1567  return -9; // error
1568  };
1569 
1570 
1571  //
1572  // second switch for channels: number and color model
1573  //
1574  string magickMap="RGB"; // default
1575  unsigned int nChannels=3;
1576  //determine import image format/channels:
1577  switch (result.GetColorModel()) {
1579  COUT("DBG CM_invalid. Setting default map RGB\n");
1580  nChannels=3;
1581  magickMap="RGB";
1582  break;
1583 
1585  COUT("DBG CM_Grey\n");
1586  magickMap="K"; // blacK=grey
1587  nChannels=1;
1588  break;
1590  //COUT("DBG CM_GreyA\n");
1591  magickMap="KA";
1592  nChannels=1;
1593  break;
1595  //COUT("DBG CM_RGB\n");
1596  magickMap="RGB";
1597  nChannels=3;
1598  break;
1600  //COUT("DBG CM_RGBA\n");
1601  magickMap="RGBA";
1602  nChannels=4;
1603  break;
1605  //COUT("DBG CM_BGR\n");
1606  magickMap="BGR";
1607  nChannels=3;
1608  break;
1609 
1610  default:
1611  BIASERR("unknown result Color Model "<<result.GetColorModel()<<" "
1612  <<"reading "<<FileName<<endl);
1613  };
1614 
1615  // init/allocate result color image data:
1616  if (!result.IsEmpty()) result.Release(true);
1617  result.Init((unsigned int)image.columns(), (unsigned int)image.rows(), nChannels);
1619 
1620 
1621  // get the pointer to our result BIAS image data:
1622  unsigned char* p_imageData = (unsigned char*)result.GetImageData();
1623  BIASASSERT( p_imageData != NULL);
1624  // write data array from read in ImageMagick++ image
1625  // to our own ImageData Array.
1626  // details: http://studio.imagemagick.org/Magick++/Image.html#write
1627  image.write(0,0, // upper left corner of region to extract
1628  result.GetWidth(), result.GetHeight(), // region size to extract
1629  "RGB", // map=output format in our pixel data, e.g RGBA
1630  outputST,
1631  p_imageData // pointer to our data array of type
1632  );
1633  if (readMetaData){
1634  BIASERR("reading of MetaData is not implemented for IMageMagick++ but could be done using BIAS::ImageAttributes class(10/2004)\n");
1635  }
1636  }
1637  catch( Magick::Exception &error_ ) {
1638  BIASERR("Reading "<<FileName<<" with Magick++ failed."<<endl
1639  <<" Caught exception: "<<endl
1640  <<" "<<error_.what()<<endl );
1641  return -1; // error
1642  }
1643  catch (...) {
1644  BIASERR("Reading "<<FileName<<" with Magick++ failed."<<endl);
1645  return -2; // error
1646  }
1647  return BIAS_IO_SUCCESS;// OK
1648 }
1649 
1650 
1651 int ImageIO::
1652 ExportMagickPP(const std::string& FileNameStr,
1653  ImageBase input,
1654  const int &quality,
1655  const bool &writeMetaData,
1656  const bool &forceBinaryPNMformat,
1657  const bool &losslesJpgMode,
1658  const bool &writeGZipped,
1659  const string & comment
1660  )
1661 {
1662 #if defined(BIAS_DEBUG) && defined(ImageIO_DEBUG_IO)
1663  CALLINFO;
1664 #endif
1665 
1666  // binding local namespace scope
1667  //using namespace Magick;
1668  //using namespace MagickLib;
1669 
1670  // const to var. conversio to add .gz suffix (later);
1671  string FileName(FileNameStr);
1672  string commentTmp;
1673  commentTmp.append(comment);
1674 
1675 #ifdef WIN32
1676  // initialize DLL loaded library (not required on Linux but once on Windows)
1677  Magick::InitializeMagick(NULL);
1678 #endif
1679 
1680  if(input.GetChannelCount()==1){
1681  string ext = FileHandling::LowerCase( FileHandling::Suffix(FileName) );
1682  if (ext == ".jpg" || ext == ".png"){
1683  cout << "One channel and file suffix is" << ext << endl;
1685  BIASWARN("JPEG / PNG does not support grey scale images. Converting image to RGB.");
1686  Image<unsigned char> source(input);
1687  Image<unsigned char> dest;
1688  ImageConvert::ToRGB(source, dest);
1689  ImageBase tmp = input;
1690  input.Release();
1691  input.Init(dest.GetWidth(),dest.GetHeight(),3);
1692  input = dest;
1694  }
1695  }
1696  }
1697  Magick::Image image;
1698  //convert Image
1699  int ret = BIAS::ImageConvert::BIAS2ImageMagick(input, image);
1700  if(ret != 0) return ret;
1701 
1702  try {
1703  // for jpeg compression:
1704  image.quality(quality);
1705  // ASCII / binary data format:
1706  if (forceBinaryPNMformat){
1707  string ext = FileHandling::LowerCase( FileHandling::Suffix(FileName) );
1708  // useful option only for pnm images
1709  if ((ext==".pnm")|| (ext==".pbm")|| (ext==".pgm")|| (ext==".ppm")) {
1710  // to write Binary data (instead of ASCII)
1711  // set any compression except "none" and "unknown", e.g. RLE works
1712  // no matter if this compression is really used by coder...
1713  //image.compressType(UndefinedCompression); // makes binary data, too.
1714  //image.compressType(NoCompression);
1715  //image.compressType(BZipCompression);
1716  //image.compressType(FaxCompression);
1717  //image.compressType(Group4Compression);
1718  //image.compressType(JPEGCompression);
1719  //image.compressType(JPEG2000Compression);
1720  //image.compressType(LosslessJPEGCompression);
1721  //image.compressType(LZWCompression);
1722  image.compressType(Magick::RLECompression);
1723  //image.compressType(ZipCompression);
1724  } else {
1725  // ASCII PNM - blows size up compared to binary writing
1726  image.compressType(Magick::NoCompression);
1727  }
1728  } // textInsteadOfBinaryMode
1729  if (losslesJpgMode){
1730  image.compressType(MagickLib::LosslessJPEGCompression);
1731  /// quality and compession are two different parameters in jpeg
1732  /// but the user usually wants lossles *and* no compression on lossless flag,
1733  /// so force 100% quality, here:
1734  image.quality(100);
1735  }
1736 
1737  // non const copy: add suffix for zipped format
1738  // useful for ASCII text format liek ASCII pgm --> .pgm.gz
1739  if (writeGZipped){
1740  if (FileHandling::Suffix(FileName)!=".gz")
1741  FileName+=".gz";
1742  }
1743  #if defined(BIAS_DEBUG) && defined(ImageIO_DEBUG_IO)
1744  COUT("DBG writing "<<input.GetWidth()<<"x"<<input.GetHeight()<<" "
1745  <<FileName <<"\" using ImageMagick++ "<<endl);
1746  #endif // BIAS_DEBUG
1747 
1748  if (writeMetaData) {
1749  /// Comment header is limited to 4096 Bytes for some formats
1750  /// and ASCII BIAS::MetaData representation may be too long to do so!
1751  string ext = FileHandling::LowerCase(FileHandling::Suffix(FileName));
1752  if(ext == ".png"){
1753  stringstream ss;
1754  BIASASSERT(input.GetMetaData() != NULL);
1755  input.GetMetaData()->WriteAscii(ss);
1756  commentTmp.append(ss.str());
1757  }
1758  else{
1759  #if defined(BIAS_DEBUG) && defined(ImageIO_DEBUG_IO)
1760  BIASERR("writing MetaData using ImageMagick IO is not implemented.");
1761  #endif
1762  }
1763  }
1764  // write supplied comment/description data
1765  if (commentTmp.size()>=4096){
1766  BIASWARN("comment size "<<comment.size()<<" is >= 4096 characters. This may be too long for some image formats.");
1767  }
1768  image.comment( commentTmp ); //< replaces
1769  // start *really* writing to disk using Magick++
1770  // output file type is automatically determined by magick file extension
1771  image.write(FileName);
1772  }
1773  catch( Magick::Exception &error_ ) {
1774  BIASERR("Writing "<<FileName<<" with Magick++ failed."<<endl
1775  <<" Caught exception: "<<endl
1776  <<" "<<error_.what()<<endl );
1777  return -1; // error
1778  }
1779  catch(...) {
1780  BIASERR("Writing "<<FileName<<" with Magick++ failed."<<endl);
1781  return -2; // error
1782  }
1783 
1784  return BIAS_IO_SUCCESS;// OK
1785 }
1786 
1787 #endif // BIAS_HAVE_IMAGEMAGICKLIB
1788 
1789 
1790 int ImageIO::
1791 ImportRAWwithHeader(const std::string & filename,
1792  BIAS::ImageBase & img)
1793 {
1794 #if defined(BIAS_DEBUG) && defined(ImageIO_DEBUG_IO)
1795  CALLINFO;
1796 #endif
1797 
1798  // header data size:
1799  unsigned int hdrSZ=0;
1800  // tags to find
1801  unsigned int Cols=0;
1802  unsigned int Rows=0;
1803 
1804 
1805  { // scope
1806  ifstream is;
1807  is.open(filename.c_str());
1808  //is.open(filename.c_str(), ios::binary);
1809  //is.open(filename.c_str(), ios_base::in |ios_base::binary );
1810  if (!is){
1811 #if defined(BIAS_DEBUG) && defined(ImageIO_DEBUG_IO)
1812  BIASERR("could not open image file: "<<filename);
1813 #endif
1814  is.close();
1815  return -1;
1816  }
1817  // OK
1818  string line;
1819  getline(is, line);
1820  //cout<<"DBG "<<FUNCNAME<<"line: "<<line<<endl;
1821  if (line.size()<3) return -2; // too small.
1822 
1823  // parse header:
1824  string ref7("RAW4096"); // 7 Bytes instead of std. 8 for backward compatibility
1825  string ref("RAW04096");
1826  if ( (0==line.compare(0, ref.size(), ref))
1827  || (0==line.compare(0, ref7.size(), ref7)) )
1828  {
1829  COUT("RAW04096/RAW4096 found."<<endl);
1830  hdrSZ=4096;
1831  } else {
1832  ref="RAW08192";
1833  if (0==line.compare(0, ref.size(), ref)){
1834  hdrSZ=8192;
1835  } else {
1836  ref="2048";
1837  if (0==line.compare(0, ref.size(), ref)){
1838  hdrSZ=2048;
1839  } else {
1840  ref="1024";
1841  if (0==line.compare(0, ref.size(), ref)){
1842  hdrSZ=1024;
1843  } else {
1844  ref="0512";
1845  if (0==line.compare(0, ref.size(), ref)){
1846  hdrSZ=0512;
1847  } else {
1848 #if defined(BIAS_DEBUG) && defined(ImageIO_DEBUG_IO)
1849  BIASERR(filename<<" is no RAW4096/RAWnnnn image. aborting.");
1850 #endif
1851  return -3;
1852  }
1853  }
1854  }
1855  }
1856  }
1857 
1858 
1859  // create string that can be used as char array:
1860  string hdr(hdrSZ,' ');
1861  is.seekg(ios::beg);
1862  // read data as a block:
1863  is.read(&(hdr[0]), hdrSZ);
1864 
1865  bool ok=true;
1866  //ok = ok && (0==Parse(hdr, "Cols=", Cols));
1867  ok = ok && (0==ParseRAWwithHeader(hdr, "RowInc=", Cols));
1868  ok = ok && (0==ParseRAWwithHeader(hdr, "Rows=", Rows));
1869 
1870  if (ok) cout<<"found dim "<<Cols<<"x"<<Rows<<endl;
1871  is.close();
1872  }
1873 
1874  if (!img.IsEmpty()) img.Release(true);
1875  // content of RAW is fixed for scorpion 1600x1200 as RAW 1 plane Bayer pattern, 8 bit.
1876  img.Init(Cols, Rows, 1);
1878 
1879 
1880  // reopen file with C fopen intead of C++ fstream
1881  // USE C because of higher performance (measured 15%)
1882  // Linux reads only one line - thu it is not using binary mode!
1883  FILE * fp=NULL;
1884 
1885 #ifdef WIN32
1886  if (fopen_s(&fp, filename.c_str(), "rt") != 0) {
1887  cout<<"could not open "<<filename<<" for C reading"<<endl;
1888  return -3;
1889  }
1890 #else //WIN32
1891  fp = fopen(filename.c_str(), "rt");
1892  if (fp==NULL){
1893  cout<<"could not open "<<filename<<" for C reading"<<endl;
1894  return -3;
1895  }
1896 #endif //WIN32
1897  //OK
1898  unsigned int dataSZ=Cols*Rows;
1899  //memset(&(img.GetImageData()[0]), 0, dataSZ);
1900  {
1901  char * p_data = new char[dataSZ];
1902  memset(p_data, 0, dataSZ);
1903 
1904  // skip header
1905  fread( p_data, hdrSZ, 1, fp );
1906 
1907  // read data:
1908  fread( p_data, dataSZ, 1, fp );
1909 
1910  img.CopyIn_NoInit(p_data);
1911  //tmp.CopyIn_NoInit(p_data);
1912 
1913  fclose(fp);
1914  delete p_data;
1915  }
1916 
1917  return 0; // OK
1918 }
1919 
1920 
1921 int ImageIO::
1922 ParseRAWwithHeader(const std::string & buf,
1923  const std::string & tag,
1924  unsigned int & retVal)
1925 {
1926  string::size_type posStart, posEnd;
1927  string valueStr;
1928  posStart=buf.find(tag, 0);
1929  if (posStart!=string::npos){
1930  // found tag
1931  posEnd = buf.find( string("\n"), posStart);
1932  if (posEnd!=string::npos){
1933  valueStr=buf.substr(posStart+tag.size(), posEnd-posStart-tag.size());
1934  stringstream ss;
1935  ss.str(valueStr);
1936  ss>>retVal;
1937  cout<<"valueStr="<<valueStr<<" : "<<retVal<<endl;
1938  }
1939  } else {
1940  cout<<"not found!"<<endl;
1941  return -1;
1942  }
1943  // OK.
1944  return 0;
1945 }
1946 
1947 
1948 #ifdef WIN32
1949 # pragma warning (push)
1950 # pragma warning (disable: 4702) // unreachable code
1951 int ImageIO::
1952 WriteUnbuffered(const std::string& /*FileName*/,
1953  const ImageBase &/*img*/)
1954 {
1955  BIASERR("ImageIO::WriteUnbuffered() not implemented in Win32");
1956  BIASABORT;
1957  return -1;
1958 }
1959 # pragma warning (pop)
1960 
1961 #else // WIN32
1962 # ifdef __APPLE__
1963 int ImageIO::
1964 WriteUnbuffered(const std::string& /*FileName*/,
1965  const ImageBase &/*img*/)
1966 {
1967  BIASERR("ImageIO::WriteUnbuffered() not implemented in Win32");
1968  BIASABORT;
1969  return -1;
1970 }
1971 # else // __APPLE__
1972 
1973 
1974 int ImageIO::
1975 WriteUnbuffered(const std::string& FileName,
1976  const ImageBase &img_const)
1977 {
1978 #if defined(BIAS_DEBUG) && defined(ImageIO_DEBUG_IO)
1979  CALLINFO;
1980 #endif // defined(BIAS_DEBUG) && defined(ImageIO_DEBUG_IO)
1981 
1982  ImageBase img(img_const);
1983 
1984  if (!img.GetUID().IsValid())
1985  img.SetUID(UUID::GenerateUUID());
1986 
1987  std::ostringstream FlatImage;
1988  FlatImage << img;
1989  img.GetMetaData()->WriteBinary(FlatImage);
1990  FlatImage.flush();
1991  unsigned long int is = FlatImage.str().size();
1992  // cout <<"FlatImage.size: "<<is<<endl;;
1993  if (MemAlignedBufferSize_ < is) {
1994  if (MemAlignedBuffer_ != NULL) free(MemAlignedBuffer_);
1995  MemAlignedBufferSize_ = 512;
1996  while (MemAlignedBufferSize_ < is)
1997  MemAlignedBufferSize_ +=512;
1998 
1999  // TODO: warning: dereferencing type-punned pointer will break strict-aliasing rules
2000 
2001  // cout <<"New MemAlignedBuffer_ with size "<<MemAlignedBufferSize_ <<endl;
2002  char** bufferPointer = &MemAlignedBuffer_;
2003  int r = posix_memalign((void**)bufferPointer, 512,
2004  MemAlignedBufferSize_);
2005  if (r!=0){
2006  BIASERR("posix_memalign failed: "<<r);
2007  return -1;
2008  }
2009 
2010  if (MemAlignedBuffer_ == NULL) {
2011  BIASERR("Can not posix_memalign()"<<MemAlignedBufferSize_<<" bytes");
2012  return -1;
2013  }
2014  }
2015  // copy flattened image into Buffer
2016  memcpy(MemAlignedBuffer_, FlatImage.str().c_str(), is);
2017 
2018  int fd = open(FileName.c_str(), O_WRONLY | O_CREAT | O_DIRECT, 0644);
2019  if (fd <0) {
2020  BIASERR("Can not open/create file ");
2021  perror(FileName.c_str());
2022  return -1;
2023  }
2024  fchmod(fd,S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
2025  int res = write(fd,MemAlignedBuffer_, MemAlignedBufferSize_);
2026  if (res <0) {
2027  BIASERR("Can not write with O_DIRECT to file ");
2028  perror(FileName.c_str());
2029  return -1;
2030  }
2031 
2032  close(fd);
2033 
2034  return 0;
2035 }
2036 # endif // __APPLE__
2037 #endif // WIN32
2038 
2039 
2040 
2041 #ifdef BIAS_HAVE_DEVIL
2042 void ImageIO::
2044 {
2045  static bool il_initialized=false;
2046  // once
2047  if (!il_initialized)
2048  {
2049 #if defined(BIAS_DEBUG) && defined(ImageIO_DEBUG_IO)
2050  // Check if the shared lib's version matches the executable's version.
2051  if (ilGetInteger(IL_VERSION_NUM) < IL_VERSION) {
2052  BIASERR("DevIL/OpenIL: "<<endl
2053  <<"IL versions of run-and compiletime are different. "<<endl
2054  <<"compile time IL_VERSION ="<<IL_VERSION<<endl
2055  <<"runtime IL_VERSION_NUM="<<ilGetInteger(IL_VERSION_NUM)<<endl
2056  <<"There is a risk that the headers dont match the shared library/DLL. ");
2057  };
2058 # ifdef USE_DEVIL_ILU
2059  if (iluGetInteger(ILU_VERSION_NUM) < ILU_VERSION) {
2060  BIASERR("DevIL/OpenIL: "
2061  <<"ILU versions of run-and compiletime are different. "
2062  <<" There is a risk that the headers dont match the DLL. ");
2063  };
2064 # endif // USE_DEVIL_ILU
2065 #endif // BIAS_DEBUG && ImageIO_DEBUG_IO
2066 
2067  // global state initialization, required once:
2068  ilInit();
2069 #ifdef USE_DEVIL_ILU
2070  iluInit();
2071 #endif
2072 
2073  // done:
2074  il_initialized=true;
2075 
2076 #if defined(BIAS_DEBUG) && defined(ImageIO_DEBUG_IO)
2077  COUT("initialized DevIL(OpenIL) runtime version: "
2078  <<ilGetInteger(IL_VERSION_NUM)<<endl );
2079 #endif
2080  }
2081 }
2082 
2083 
2084 void ImageIO::
2085 PrintInfoDevIL(std::ostream & os)
2086 {
2087  os
2088  <<"dim: "<<ilGetInteger(IL_IMAGE_WIDTH)<<"x"
2089  <<ilGetInteger(IL_IMAGE_HEIGHT)<<" pixel"<<endl
2090  <<"depth=planes "<<ilGetInteger(IL_IMAGE_DEPTH)<<" plane(s) ";
2091  if (ilGetInteger(IL_IMAGE_DEPTH)>1)
2092  os<<"(tex3D)";
2093  os<<endl;
2094  os<<"size of data "<<ilGetInteger(IL_IMAGE_SIZE_OF_DATA)<<" Byte total"<<endl
2095  <<"BytePerPixel "<<ilGetInteger(IL_IMAGE_BPP)<<endl
2096  <<"Bytes/Pixel "<<ilGetInteger(IL_IMAGE_BYTES_PER_PIXEL)<<endl
2097  <<"Bits/Pixel "<<ilGetInteger(IL_IMAGE_BITS_PER_PIXEL)<<endl
2098  <<"num images "<<ilGetInteger(IL_NUM_IMAGES)<<endl
2099  <<"num mipmaps "<<ilGetInteger(IL_NUM_MIPMAPS)<<endl
2100 
2101  <<"origin_set "<<ilGetInteger(IL_ORIGIN_SET)<<" "
2102  <<"image_origin "<<ilGetInteger(IL_IMAGE_ORIGIN)<<" "
2103  ;
2104  switch (ilGetInteger(IL_IMAGE_ORIGIN)) {
2105  case IL_ORIGIN_SET:
2106  os<<"IL_ORIGIN_SET"; break;
2107  case IL_ORIGIN_LOWER_LEFT:
2108  os<<"IL_ORIGIN_LOWER_LEFT"; break;
2109  case IL_ORIGIN_UPPER_LEFT:
2110  os<<"IL_ORIGIN_UPPER_LEFT"; break;
2111  case IL_ORIGIN_MODE:
2112  os<<"IL_ORIGIN_MODE"; break;
2113  };
2114  os<<endl;
2115 
2116  os<<"offset "
2117  <<ilGetInteger(IL_IMAGE_OFFX)<<" "<<ilGetInteger(IL_IMAGE_OFFY)<<endl
2118  ;
2119 }
2120 
2121 int ImageIO::
2122 ImportDevIL(const std::string& FileName,
2123  ImageBase& result,
2124  const unsigned int & tex3DplaneZ )
2125 {
2126 #if defined(BIAS_DEBUG) && defined(ImageIO_DEBUG_IO)
2127  CALLINFO;
2128 #endif
2129 
2130  if (!result.IsEmpty()) result.Release(true);
2131 
2132  InitDevIL();
2133  ILuint id(0), err(0);
2134  ilGenImages(1, &id);
2135  ilBindImage( id );
2136 
2137  bool ok = (IL_TRUE==ilLoadImage( (char*)(FileName.c_str()) ));
2138 
2139  err = ilGetError();
2140  if (err!=IL_NO_ERROR || !ok) {
2141 #if defined(BIAS_DEBUG) && defined(ImageIO_DEBUG_IO)
2142  stringstream ss;
2143  ss<<"could not load "<<FileName<<" ";
2144 # ifdef USE_DEVIL_ILU
2145  // there is no erro msg of !ok is the reason for failure and no err
2146  if (err!=IL_NO_ERROR)
2147  ss<<": "<<iluErrorString(err);
2148 # endif
2149  BIASERR(ss.str());
2150 #endif // BIAS_DEBUG && ImageIO_DEBUG_IO
2151  ilDeleteImages(1, &id);
2152  return -1;
2153  }
2154 
2155 #if defined(BIAS_DEBUG) && defined(ImageIO_DEBUG_IO)
2156  PrintInfoDevIL();
2157 #endif
2158 
2159  // multiple pages/planes per image, useful for tiff etc.
2160  const int nDepthPlanes = int( ilGetInteger(IL_IMAGE_DEPTH) );
2161  if (nDepthPlanes>1){
2162 
2163  BIASERR("detected tex3D with "<<nDepthPlanes<<" planes. It is a volume, not a 2D texture. NOT implemented.");
2164  BIASBREAK;
2165  ilDeleteImages(1, &id);
2166  return -1;
2167  }
2168 
2169  // tex3D access?
2170  if (nDepthPlanes<(int)tex3DplaneZ ){
2171  BIASERR("Image has only "<<nDepthPlanes<<" z planes, but you requested tex3DplaneZ="<<tex3DplaneZ);
2172  BIASBREAK;
2173  ilDeleteImages(1, &id);
2174  return -1;
2175  }
2176 
2177  // determine pixel data type:
2179  const int typeIL = (int)ilGetInteger(IL_IMAGE_TYPE);
2180  switch (typeIL)
2181  {
2182  case IL_BYTE:
2183  st = ImageBase::ST_char; break;
2184  case IL_UNSIGNED_BYTE:
2185  st = ImageBase::ST_unsignedchar; break;
2186  case IL_SHORT:
2187  st = ImageBase::ST_shortint; break;
2188  case IL_UNSIGNED_SHORT:
2189  st = ImageBase::ST_unsignedshortint; break;
2190  case IL_INT:
2191  st = ImageBase::ST_int; break;
2192  case IL_UNSIGNED_INT:
2193  st = ImageBase::ST_unsignedint; break;
2194  case IL_FLOAT:
2195  st = ImageBase::ST_float; break;
2196  case IL_DOUBLE:
2197  st = ImageBase::ST_double; break;
2198  default:
2199  BIASERR("unsupported storage type");
2200  }
2201 
2202  unsigned int channels=3;
2204  // switch fmt to determine nr. of channels, channel order and seq.
2205  int formatIL = (int)ilGetInteger(IL_IMAGE_FORMAT);
2206  switch (formatIL)
2207  {
2208  case IL_RGB:
2209  channels=3;
2211  break;
2212  case IL_RGBA:
2213  channels=4;
2215  break;
2216  case IL_BGR:
2217  channels=3;
2219  break;
2220  case IL_BGRA:
2221  channels=4;
2223  break;
2224  case IL_LUMINANCE:
2225  channels=1;
2227  break;
2228  case IL_LUMINANCE_ALPHA:
2229  channels=2;
2231  break;
2232  default:
2233  BIASERR("unsupported format");
2234  }
2235 
2236  // always interleaved
2237  const bool interleaved = true;
2238  // dim in pixel
2239  const unsigned int w = ilGetInteger(IL_IMAGE_WIDTH);
2240  const unsigned int h = ilGetInteger(IL_IMAGE_HEIGHT);
2241 
2242  // allocate new image
2243  result.Init(
2244  w,h,
2245  channels,
2246  st,
2247  interleaved );
2248  result.SetColorModel(cm);
2249 
2250 #ifdef BIAS_DEBUG
2251  const int bytePerPixIL = int(ilGetInteger(IL_IMAGE_BYTES_PER_PIXEL));
2252  const int bitPerPixIL = int(ilGetInteger(IL_IMAGE_BITS_PER_PIXEL ));
2253  BIASASSERT(int(result.GetDepth()*result.GetChannelCount()) == bytePerPixIL);
2254  BIASASSERT(int(result.GetBitDepth()*result.GetChannelCount()) >= bitPerPixIL );
2255 
2256  {
2257  const int ilSZ = ilGetInteger(IL_IMAGE_SIZE_OF_DATA);
2258  BIASASSERT(int(result.GetPixelCount()*result.GetDepth()*result.GetChannelCount()) == ilSZ);
2259  }
2260 #endif
2261 
2262  if (ilGetData() == NULL){
2263  BIASERR("ilGetData NULL");
2264  ilDeleteImages(1, &id);
2265  return -1;
2266  };
2267 
2268  // copy the data area
2269  //result.CopyIn_NoInit( ilGetData() );
2270  //result.CopyIn_NoInit( ilGetData() );
2271  ilCopyPixels(0,0,0, /* x y z offset */
2272  w,h,
2273  tex3DplaneZ, /* depth planes, 1 for tex2D */
2274  formatIL, /* format, e.g. IL_RGBA */
2275  typeIL, /* type, e.g. UL_UNSIGNED_BYTE */
2276  result.GetImageData() /* dest ptr */
2277  );
2279 
2280  // free temporary devIL image
2281  ilDeleteImages(1, &id);
2282 
2283  return BIAS_IO_SUCCESS; // OK
2284 }
2285 
2286 
2287 int ImageIO::
2288 ExportDevIL(const std::string& FileName,
2289  const ImageBase& img,
2290  const bool &fileOverwrite,
2291  const bool &allowPadding )
2292 {
2293 #if defined(BIAS_DEBUG) && defined(ImageIO_DEBUG_IO)
2294  CALLINFO;
2295 #endif
2296 
2297  InitDevIL();
2298 
2299  ILuint id=0;
2300  ILuint err=0;
2301  ilGenImages(1, &id);
2302  ilBindImage( id );
2303 
2304  // fill attributes and data
2305  unsigned int w=img.GetWidth();
2306  unsigned int h=img.GetHeight();
2307  unsigned int depth=img.GetDepth();
2308  ILenum ilFormat=IL_RGB; //< defaut
2309  ILenum ilType =IL_BYTE; //< default
2310 
2311  // overwrite file if exists?
2312  if (fileOverwrite) {
2313  ilEnable(IL_FILE_OVERWRITE);
2314  } else {
2315  ilDisable(IL_FILE_OVERWRITE);
2316  }
2317 
2318 
2319  // native storage data type:
2320  switch (img.GetStorageType())
2321  {
2322  case ImageBase::ST_char:
2323  ilType=IL_BYTE; break;
2325  ilType=IL_UNSIGNED_BYTE; break;
2327  ilType=IL_SHORT; break;
2329  ilType=IL_UNSIGNED_SHORT; break;
2330  case ImageBase::ST_int:
2331  ilType=IL_INT; break;
2333  ilType=IL_UNSIGNED_INT; break;
2334  case ImageBase::ST_float:
2335  ilType=IL_FLOAT; break;
2336  case ImageBase::ST_double:
2337  ilType=IL_DOUBLE; break;
2338  default:
2339  BIASERR("unsupported storage type");
2340  }
2341 
2342  //#ifdef BIAS_DEBUG
2343  // const unsigned int channels=img.GetChannelCount();
2344  //#endif
2345 
2346  // format --> native nr+seq of channels and color model
2347  switch (img.GetColorModel())
2348  {
2350  ilFormat=IL_RGB;
2351  BIASASSERT(img.GetChannelCount()==3);
2352  break;
2354  ilFormat=IL_RGBA;
2355  BIASASSERT(img.GetChannelCount()==4);
2356  break;
2358  ilFormat=IL_BGR;
2359  BIASASSERT(img.GetChannelCount()==3);
2360  break;
2362  ilFormat=IL_BGRA;
2363  BIASASSERT(img.GetChannelCount()==4);
2364  break;
2366  ilFormat=IL_LUMINANCE;
2367  BIASASSERT(img.GetChannelCount()==1);
2368  break;
2370  ilFormat=IL_LUMINANCE_ALPHA;
2371  BIASASSERT(img.GetChannelCount()==2);
2372  break;
2373  default:
2374  BIASERR("unsupported color model/channelcount/ DevIL type");
2375  }
2376 
2377  // Byte per Pixel, e.g. 3 for "unsigned char RGB" image
2378  unsigned int BytePerPixel = img.GetDepth()*img.GetChannelCount();
2379 
2380  // create temporary DevIL image
2381  // setting attributes and copy data
2382  if (!ilTexImage(
2383  w,h,
2384  depth,
2385  ILubyte (BytePerPixel),
2386  ilFormat,
2387  ilType,
2388  //(ILvoid*)(img.GetImageData())
2389  NULL
2390  ))
2391  {
2392  BIASERR("could not set DevIL attributes for saving "<<FileName);
2393  ilDeleteImages(1, &id);
2394  return -1;
2395  }
2396 
2397  // BIAS image coordinate system has origin in upper left corner
2398  // (in contrast to OpenGLs lower left)
2399  ilRegisterOrigin(IL_ORIGIN_UPPER_LEFT);
2400 
2401  BIASASSERT(img.GetImageData()!=NULL);
2402  // memcopy the image data:
2403  ilSetData((ILvoid*)(img.GetImageData()) );
2404 
2405  // check status
2406  err = ilGetError();
2407  if (err!=IL_NO_ERROR) {
2408  stringstream ss;
2409  ss<<"could not set DevIL for saving "<<FileName<<" ";
2410 #ifdef USE_DEVIL_ILU
2411  ss<<": "<<iluErrorString(err);
2412 #endif
2413  BIASERR(ss.str());
2414  ilDeleteImages(1, &id);
2415  return -1;
2416  }
2417 
2418  BIASASSERT(int(img.GetDepth())==int(ilGetInteger(IL_IMAGE_DEPTH)) );
2419 #ifdef BIAS_DEBUG
2420  {
2421  const int ilSZ = ilGetInteger(IL_IMAGE_SIZE_OF_DATA);
2422  BIASASSERT(
2423  int(img.GetPixelCount()*img.GetDepth()*img.GetChannelCount())==ilSZ
2424  );
2425  }
2426 #endif
2427 
2428  err = ilGetError();
2429  if (err!=IL_NO_ERROR) {
2430  stringstream ss;
2431  ss<<"could not save to file "<<FileName<<" ";
2432 #ifdef USE_DEVIL_ILU
2433  ss<<": "<<iluErrorString(err);
2434 #endif
2435  PrintInfoDevIL();
2436  BIASERR(ss.str());
2437  ilDeleteImages(1, &id);
2438  return -2;
2439  }
2440 
2441  // write to disk:
2442  bool ok = (IL_TRUE==ilSaveImage( (char*)(FileName.c_str()) ));
2443 
2444  // check status again:
2445  err = ilGetError();
2446  if (err!=IL_NO_ERROR || !ok)
2447  {
2448  stringstream ss;
2449  ss<<"could not save to file "<<FileName<<" ";
2450 #ifdef USE_DEVIL_ILU
2451  ss<<": "<<iluErrorString(err);
2452 #endif
2453  if (err==IL_BAD_DIMENSIONS && allowPadding) {
2454  // try if padding helps:
2455  // fallback tmp padded image
2456  BIAS::ImageBase tmpIMG(img);
2457  tmpIMG.PadToPowerOfTwo();
2458  // do not allow padding again or we will get an endless loop!
2459  int resultPadded=ExportDevIL(
2460  FileName,
2461  tmpIMG,
2462  fileOverwrite,
2463  false /*allowPading?*/ );
2464  if (resultPadded==0)
2465  {
2466  // everything is fine, give msg that we paded.
2467  ss<<endl<<"Some formats (e.g. DDS) require power of two size (and depth) "<<endl
2468  <<"Padding from dim "<<w<<"x"<<h<<" "
2469  <<"(depth="<<depth<<" ChannelCount="<<tmpIMG.GetChannelCount()<<") "
2470  <<"to "<<tmpIMG.GetWidth()<<"x"<<tmpIMG.GetHeight()<<" "
2471  <<"(depth="<<tmpIMG.GetDepth()<<" channels="<<tmpIMG.GetChannelCount()<<") "<<endl
2472  <<"was required to save "<<FileName;
2473  BIASWARN(ss.str());
2474  } else {
2475  // padding did not help
2476  BIASERR(ss.str());
2477  ilDeleteImages(1, &id);
2478  return -3;
2479  }
2480  } else {
2481  // error we could do nothing about
2482  BIASERR(ss.str());
2483  ilDeleteImages(1, &id);
2484  return -4;
2485  }
2486  }
2487 
2488  // OK:
2489  // free temporary devIL image
2490  ilDeleteImages(1, &id);
2491 
2492  return BIAS_IO_SUCCESS;
2493 }
2494 #endif // BIAS_HAVE_DEVIL
2495 
2496 
2497 
2498 std::string ImageIO::
2500 {
2501  string s;
2502  switch (fmt)
2503  {
2504  case FF_mip:
2505  s="mip"; break;
2506  case FF_ppm:
2507  s="ppm"; break;
2508  case FF_pgm:
2509  s="pgm"; break;
2510  case FF_pbm:
2511  s="pbm"; break;
2512  case FF_jpg:
2513  s="jpg"; break;
2514  case FF_tif:
2515  s="tif"; break;
2516  case FF_png:
2517  s="png"; break;
2518  case FF_viff:
2519  s="vif"; break;
2520  case FF_exr:
2521  s="exr"; break;
2522  case FF_dds:
2523  s="dds"; break;
2524  case FF_raw4096:
2525  s="raw"; break;
2526  case FF_bmp:
2527  s="bmp"; break;
2528  case FF_Real32:
2529  s="real32"; break;
2530  case FF_matrix:
2531  s="matrix"; break;
2532  case FF_auto:
2533  case FF_unknown:
2534  default:
2535  BIASERR("Unknown FileFormat "<<fmt<<" Please add switch case");
2536  }
2537  return s;
2538 }
2539 
2540 
2541 
2543 GetFileFormat(const std::string &str)
2544 {
2545  // suffix = "dot"+extension
2547  // compare ext to all FF_* fixed formats:
2548  // if no extension specified use mip automatically as default - Fernandez 04/09
2549  if (ext=="mip" || ext == "") {
2550  return FF_mip;
2551  } else if (
2552  (ext=="ppm") ||
2553  (ext=="pnm") /* pNm can be pbm, pgm, ppm. assume color for pnm. */
2554  )
2555  {
2556  return FF_ppm;
2557  } else if (ext=="pgm") {
2558  return FF_pgm;
2559  } else if (ext=="pbm") {
2560  return FF_pbm;
2561  } else if (
2562  (ext=="jpg") ||
2563  (ext=="jpe") ||
2564  (ext=="jpeg")
2565  )
2566  {
2567  return FF_jpg;
2568  } else if (
2569  (ext=="tif") ||
2570  (ext=="tiff")
2571  )
2572  {
2573  return FF_tif;
2574  } else if (ext=="png") {
2575  return FF_png;
2576  } else if (
2577  (ext=="vif") ||
2578  (ext=="vff") ||
2579  (ext=="viff"))
2580  {
2581  return FF_viff;
2582  } else if (ext=="exr") {
2583  return FF_exr;
2584  } else if (
2585  (ext=="dds") ||
2586  (ext=="dxt") ||
2587  (ext=="dxt1") ||
2588  (ext=="dxt3") ||
2589  (ext=="dxt5") ||
2590  (ext=="dxtc") ||
2591  (ext=="s3tc")
2592  )
2593  {
2594  // S3's S3TC format and DXTC are essentially the same
2595  return FF_dds;
2596  } else if (
2597  (ext=="raw") ||
2598  (ext=="raw4096") ||
2599  (ext=="scorpion")
2600  )
2601  {
2602  return FF_raw4096;
2603  } else if ((ext=="real32") || (ext=="f32")){
2604  // Mathematica Real32 raw
2605  return FF_Real32;
2606  } else if (ext=="bmp") {
2607  return FF_bmp;
2608  }else if (ext=="matrix") {
2609  //text file format
2610  return FF_matrix;
2611  }
2612  else {
2613  // unknown ext.
2614  // give the external image writer libs a try,
2615  // they may support a wider range of extensions.
2616  // Thus use "FF_auto" on returned "FF_unknown"
2617  return FF_unknown;
2618  }
2619 }
2620 
2621 
2622 //#ifdef BIAS_HAVE_RADIANCE
2623 int BIAS::ImageIO::
2624 ImportRADIANCE(const std::string& FileName, ImageBase& result)
2625 {
2626  ifstream is;
2627  is.open(FileName.c_str(), ios::binary);
2628  if (!is){
2629 #if defined(BIAS_DEBUG) && defined(ImageIO_DEBUG_IO)
2630  BIASERR("Could not open file "<<FileName);
2631 #endif
2632  return -1;
2633  }
2634  //is.seekg(0,ios::beg);
2635  string buf;
2636  unsigned int line=0;
2637  getline(is, buf); line++;
2638  //cout<<line<<". = "<<buf<<endl;
2639 
2640  const string signatureRAD("#?RADIANCE");
2641  if (buf!= signatureRAD )
2642  {
2643 #if defined(BIAS_DEBUG) && defined(ImageIO_DEBUG_IO)
2644  BIASERR("signatureRAD "<<signatureRAD<<" not found in file "<<FileName);
2645 #endif
2646  return -2;
2647  };
2648  // OK, is a RADIANCE file.
2649 
2650  bool flipY=false, flipX=false;
2651  unsigned int width=0, height=0;
2652  //float exposure=1.0;
2653 
2654  // parse for FORMAT
2655  while (is){
2656  getline(is, buf); line++;
2657  //cout<<line<<". = "<<buf<<endl;
2658  // skip comments:
2659  if (0==buf.compare(0,1,"#")) {
2660  //cout<<"found comment: "<<buf<<endl;
2661  continue;
2662  }
2663  if (0==buf.compare(0,6,"FORMAT")) {
2664  // check format:
2665  if (0==buf.compare("FORMAT=32-bit_rle_rgbe")){
2666  break; // OK
2667  } else {
2668  BIASERR("Only 32-bit_rle_rgbe FORMAT supported but "<<buf<<" found. Failed to load.");
2669  return -5;
2670  }
2671  };
2672  }
2673 
2674  // parse for -Y or +Y
2675  while (is){
2676  getline(is, buf); line++;
2677  //cout<<line<<". = "<<buf<<endl;
2678  // skip comments:
2679  if (0==buf.compare(0,1,"#")) {
2680  //cout<<"found comment: "<<buf<<endl;
2681  continue;
2682  }
2683  if (0==buf.compare(0,2,"-Y")
2684  || 0==buf.compare(0,2,"-Y"))
2685  {
2686  // parse x and y value:
2687  stringstream ss(buf);
2688  string dummy;
2689  ss>>dummy; // Y
2690  if (dummy=="+Y"){
2691  flipY=true;
2692  } else if (dummy=="-Y") {
2693  // OK, no flip
2694  } else {
2695  BIASERR("expected +Y or -Y but failed.");
2696  return -8;
2697  }
2698  // read Y value
2699  ss>>height;
2700 
2701  ss>>dummy;// X
2702  if (dummy=="+X"){
2703  // OK, no flip
2704  } else if (dummy=="-X") {
2705  flipX=true;
2706  } else {
2707  BIASERR("expected +X or -X but failed.");
2708  return -9;
2709  }
2710  // read X value
2711  ss>>width;
2712  break;
2713  }
2714  };
2715  cout<<FUNCNAME<<" found "<<width<<"x"<<height<<" RADIANCE rle RGBE image. "<<FileName<<endl;
2716  // get RGBE data:
2717  if (!result.IsEmpty()) result.Release(true);
2718  result.Init(width, height, 4, BIAS::ImageBase::ST_unsignedchar, true );
2719 
2720  // get data
2721  char col[4]={0};
2722  unsigned int y=0;
2723  //unsigned int x=0;
2724  //int pos=0;
2725  //int start=0;
2726  //int step=1;
2727  for (y=0; y<height; y++) {
2728  //start = bFlippedY ? (height-y-1)*width : y*width;
2729  //step = bFlippedX ? -1 : 1;
2730 
2731  // read 4 Bytes of line:
2732  is.read(col,4);
2733  // is the image /line RLE compressed?
2734  if ( (col[0]==0x2)
2735  && (col[1]==0x2)
2736  && (col[2]==0x0) )
2737  {
2738  BIASERR("unsupported new RADIANCE compression detected in line y="<<y);
2739  // clear the line:
2740  memset( result.GetImageDataArray()[y], 0, 4*width);
2741 
2742  } else if ( (col[0]==0x1)
2743  && (col[1]==0x1)
2744  && (col[2]==0x1) )
2745  {
2746  BIASERR("unsupported old RADIANCE run scheme in line y="<<y);
2747  memset( result.GetImageDataArray()[y], 0, 4*width);
2748 
2749  } else {
2750 
2751  BIASERR("sorry, RADAINCE not completely implemented TODO: RLE (un-)compression is missing.");
2752  return -99;
2753  /// \todo: decode the runlength encode line, map the RGBE to float or do it in ColorConverion?
2754 
2755  // for now do the following two lines to avoid gcc warnings:
2756  flipY = !flipY;
2757  flipX = !flipX;
2758  /*
2759  // OK, assume line contains only raw data
2760  //start = flipY ? (height-y-1)*width : y*width;
2761  //step = flipX ? -1 : 1;
2762  // Do the run
2763  int nPixel = ((int) col[3])&0xFF;
2764  unsigned char r = pBuffer[(pos-step)*4];
2765  unsigned char g = pBuffer[(pos-step)*4+1];
2766  unsigned char b = pBuffer[(pos-step)*4+2];
2767  unsigned char e = pBuffer[(pos-step)*4+3];
2768 
2769  for( int i=0; i<num; i++ ) {
2770  pBuffer[pos*4] = r;
2771  pBuffer[pos*4+1] = g;
2772  pBuffer[pos*4+2] = b;
2773  pBuffer[pos*4+3] = e;
2774  pos += step;
2775  }
2776 
2777  x += num-1;
2778  */
2779  }
2780  }
2781  return 0; // OK
2782 }
2783 //#endif // BIAS_HAVE_RADIANCE
2784 
2785 
2786 
2787 int BIAS::ImageIO::
2788 ImportReal32(const std::string& FileName, ImageBase& result)
2789 {
2790 #if defined(BIAS_DEBUG) && defined(ImageIO_DEBUG_IO)
2791  CALLINFO;
2792 #endif
2793 
2794  ifstream is;
2795  is.open(FileName.c_str(), ios::binary);
2796  if (!is){
2797  BIASERR("Could not open file "<<FileName);
2798  is.close();
2799  return -1;
2800  }
2801 
2802  // header: 4 float
2803  // format, width, height, nchannels
2804  vector<float> header(4, 0);
2805  //unsigned int version=0;
2806  if (is)
2807  is.read( (char*)(&(header[0])), header.size()*sizeof(float) );
2808 
2809  if (!is)
2810  return -101;
2811 
2812  // supported format? simple check for now.
2813  const float fmt=header[0];
2814  if ((1.0f <= fmt) && (fmt<=1.01f)) {
2815  //version=1;
2816  } else {
2817  return -1; // unsupported
2818  }
2819  unsigned int width = (unsigned int)( header[1] );
2820  unsigned int height = (unsigned int)( header[2] );
2821  unsigned int nchannels = (unsigned int)( header[3] );
2822 
2823  // only small GPU suitable images are written, currently:
2824  // check useful header values:
2825  if (!(0<width))
2826  return -2;
2827  if (!(width<=4096))
2828  return -3;
2829  if (!(0<height))
2830  return -4;
2831  if (!(height<4096))
2832  return -5;
2833  if (!(0<nchannels))
2834  return -6;
2835  if (!(nchannels<=4))
2836  return -7;
2837 
2838  // (re-)allocate
2839  if (!result.IsEmpty()) result.Release(true);
2840  result.Init(width, height, nchannels, ImageBase::ST_float, true);
2841 
2842  // read the raw data:
2843  BIASASSERT(is);
2844  is.read( (char*)(result.GetImageData()),
2845  sizeof(float)*width*height*nchannels );
2846 
2847  is.close();
2848  return 0;
2849 }
2850 
2851 
2852 
2853 #ifdef WIN32
2854  // implement WINAPI specific calls for BMP loading via disk or memory
2855 
2856 int BIAS::ImageIO::
2857 Import_BITMAP_winapi(const std::string& FileName,
2858  ImageBase& result,
2859  const bool flipY )
2860 {
2861 #if defined(BIAS_DEBUG) && defined(ImageIO_DEBUG_IO)
2862  CALLINFO;
2863 #endif
2864 
2865  // the WINAPI interface
2866  HBITMAP hbm=NULL;
2867 
2868  // convert from stl string to WINAPI string
2869  // TODO: what about UNICODE strings: use LPTSTR ?
2870  LPCSTR szFileName = FileName.c_str();
2871 
2872  // load the image from disk into a DIBSection
2873  hbm = (HBITMAP)
2874  LoadImage( NULL, szFileName, IMAGE_BITMAP, 0, 0,
2875  LR_LOADFROMFILE | LR_CREATEDIBSECTION | LR_DEFAULTSIZE );
2876 
2877  // check success
2878  if( hbm == NULL ){
2879 #if defined(BIAS_DEBUG) && defined(ImageIO_DEBUG_IO)
2880  BIASERR("could not load "<<FileName );
2881 #endif
2882  return -1; // error, could not load
2883  }
2884 
2885  // we have a valid HBITMAP, now.
2886  // create object and copy in, now.
2887  return BIAS::ImageIO::Import_HBITMAP_winapi(hbm,
2888  result,
2889  flipY );
2890 }
2891 
2892 
2893 int BIAS::ImageIO::
2894 Import_HBITMAP_winapi(const HBITMAP & hbm,
2895  ImageBase& result,
2896  const bool flipY )
2897 {
2898  // create object from handle
2899  BITMAP bm;
2900  const int nBytesHeader =
2901  GetObject( hbm, sizeof(BITMAP), &bm );
2902  if (nBytesHeader==0) {
2903  BIASERR("could not GetObject");
2904  return -1;
2905  }
2906  //cout<<"created object with "<<nBytes<<" Bytes."<<endl; // typically 24
2907 
2908  // we have a valid BITMAP, now,
2909  // load pixel data
2910  return BIAS::ImageIO::Import_BITMAP_winapi(bm,
2911  result,
2912  flipY );
2913 }
2914 
2915 
2916 int BIAS::ImageIO::
2917 Import_BITMAP_winapi(const BITMAP & bm,
2918  ImageBase& result,
2919  const bool flipY )
2920 {
2921  // If DIBSection is 256 color or less --> color table
2922  if( ( bm.bmBitsPixel * bm.bmPlanes ) <= 8 ){
2923 #if defined(BIAS_DEBUG) && defined(ImageIO_DEBUG_IO)
2924  BIASERR("Could not load winapi BITMAP because it contains a color table (not implemented)" );
2925 #endif
2926  return -2;
2927  }
2928 
2929  // tested only with 3 channel(BGR) interleaved images with one plane
2930  if (bm.bmPlanes != 1){
2931 #if defined(BIAS_DEBUG) && defined(ImageIO_DEBUG_IO)
2932  BIASERR("Could not load winapi BITMAP because it contains more than one plane." );
2933 #endif
2934  return -3;
2935  }
2936 
2937  //
2938  // copy pixel data into BIAS layout
2939  // assume 3 channel uc (3*8=24bit) interleaved DIB for now.
2940  //
2941  {
2942  BIAS::Image<unsigned char> img(bm.bmWidth, bm.bmHeight, 3 );
2943  img.SetColorModel(BIAS::ImageBase::CM_BGR); // Windows DIB = BGR
2944 
2945  const int nBytes = bm.bmWidthBytes*bm.bmHeight;
2946  memcpy(img.GetImageData(), (unsigned char*)bm.bmBits, nBytes );
2947  if (flipY){
2948  // Windows BMP has down-up vertical order like OpenGL
2949  img.Flip();
2950  }
2951 
2952  // Image<uc> --> ImageBase
2953  result = img;
2954  }
2955 
2956  return EXIT_SUCCESS;
2957 }
2958 #endif // WIN32
2959 
2960 
2961 
2962 
2963 
2964 #ifdef BIAS_HAVE_TIFF
2965 // see http://www.ibm.com/developerworks/linux/library/l-libtiff/
2966 int BIAS::ImageIO::
2967 ExportTIFFLIB(const std::string& FileName,
2968  const ImageBase& img,
2969  const unsigned int rowsPerStripArg,
2970  const unsigned int compressionAlgo,
2971  const string & comment )
2972 {
2973 #if defined(BIAS_DEBUG) && defined(ImageIO_DEBUG_IO)
2974  CALLINFO;
2975 #endif
2976  try {
2977 
2978  TIFF* tif = TIFFOpen(FileName.c_str(), "w");
2979  if (tif==NULL){
2980 #if defined(BIAS_DEBUG) && defined(ImageIO_DEBUG_IO)
2981  BIASERR("Could not open image for TIFFLIB for writing:" << FileName);
2982 #endif
2983  return -1;
2984  }
2985  BIASASSERT(tif!=NULL);
2986  // work:
2987 
2988  TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, img.GetWidth() );
2989  TIFFSetField(tif, TIFFTAG_IMAGELENGTH, img.GetHeight() );
2990  TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, img.GetChannelCount() );
2991  const unsigned short bitspersample =
2992  8* (unsigned short)img.GetDepth(); // img.GetBiTDepth()
2993  TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, bitspersample ); // more than enough
2994  TIFFSetField(tif, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT); // origin 0,0
2995  // assume planar tiff cfg., needs one channel or interleaved pixel data
2996  BIASASSERT((img.GetChannelCount()==1) || (img.IsInterleaved()) );
2997  TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
2998 
2999 
3000  //TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_NONE); //(300 msec)
3001  //TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_LZW); // works, lossless Lempel Ziff Welch (650msec)
3002  //TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_DEFLATE); // works,lossless compression known as Zip-in-TIFF (1750 msec)
3003  TIFFSetField(tif, TIFFTAG_COMPRESSION, compressionAlgo); // TODO: check if this is a valid compressoinalgorithm
3004 
3005  // size of strips = nr. of lines taht form a strip
3006  unsigned int rowsPerStrip = rowsPerStripArg;
3007  if (rowsPerStrip <= 0)
3008  rowsPerStrip = img.GetHeight();
3009  if (rowsPerStrip>img.GetHeight()) {
3010  BIASERR("rowsPerStrip="<<rowsPerStrip<<" exceed limit. resetting to img height="<<img.GetHeight());
3011  rowsPerStrip=img.GetHeight();
3012  }
3013  /// \todo TODO: do we need to check that rowsPerStrip is modulo image height?
3014  BIASASSERT(rowsPerStrip >= 0 );
3015  BIASASSERT(rowsPerStrip <= img.GetHeight() );
3016  TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, rowsPerStrip);
3017 
3018  //TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK);
3019  //TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);
3020  //TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_PALETTE);
3021  switch (img.GetChannelCount()){
3022  case 1:
3023  TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK); break;
3024  //case 2:
3025  case 3:
3026  TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB); break;
3027  //case 4:
3028  default:
3029  {
3030  BIASERR("unhandled nr. of channels.");
3031  return -1;
3032  }
3033  }
3034 
3035  //// optional tags
3036  TIFFSetField(tif, TIFFTAG_IMAGEDESCRIPTION, "written Jan Woetzel");
3037  const string cvsVersion = "CVS $Revision: 2.170 $";
3038  stringstream swSS;
3039  swSS <<"BIAS::ImageIO "
3040  <<"BIAS-"<<BIAS_VERSION_MAJOR<<"."<<BIAS_VERSION_MINOR<<"."<<BIAS_VERSION_PATCH
3041  <<" "<<cvsVersion<<" (Jan Woetzel)";
3042  TIFFSetField(tif, TIFFTAG_SOFTWARE, swSS.str().c_str() );
3043 
3044  //TIFFSetField(tif, TIFFTAG_XRESOLUTION, 150.0);
3045  //TIFFSetField(tif, TIFFTAG_YRESOLUTION, 150.0);
3046  //TIFFSetField(tif, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH); // RESUNIT_CENTIMETER
3047 
3048  // write TIFF in scanlines
3049  int res=0;
3050  //if (rowsPerStrip==1)
3051  //{
3052  // // use scanline based API
3053  // 0000000000000000 these are scanlines
3054  // 1111111111111111
3055  // 2222222222222222
3056  // for (unsigned int y=0; y<img.GetHeight(); y+=rowsPerStrip ){
3057  // void* pd = img.GetImageDataArray()[y];
3058  // // 1is returned on success
3059  // res = TIFFWriteScanline(tif, pd, y, 0);
3060  // BIASASSERT(res==1);
3061  // }
3062  //}
3063  //else
3064  {
3065  // use strip based API, possibly encoded
3066  // 0000000000 these are strips
3067  // 0000000000
3068  // 1111111111
3069  // 1111111111
3070  // TODO must rowsPerStrip be module height?
3071  const unsigned int nBytes = rowsPerStrip * img.GetWidth()*img.GetChannelCount()*img.GetDepth() ;
3072  int strip =0;
3073  for (unsigned int y=0; y<img.GetHeight(); y+=rowsPerStrip){
3074  // the number of written Bytes is returned
3075  res = TIFFWriteEncodedStrip(tif, strip, img.GetImageDataArray()[y], nBytes );
3076  BIASASSERT((int)res==(int)nBytes);
3077  strip++;
3078  }
3079  }
3080 
3081  TIFFClose(tif);
3082  return EXIT_SUCCESS;
3083 
3084  } catch (...){
3085  BIASERR("catched tifflib exception");
3086  return -1;
3087  }
3088 }
3089 
3090 
3091 int BIAS::ImageIO::
3092 ImportTIFFLIB(const std::string& FileName, ImageBase& img )
3093 {
3094  // /*
3095  //#if defined(BIAS_DEBUG) && defined(ImageIO_DEBUG_IO)
3096  // CALLINFO;
3097  //#endif
3098  // try {
3099  //
3100  // TIFF* tif = TIFFOpen(FileName.c_str(), "r");
3101  // if (tif==NULL){
3102  //#if defined(BIAS_DEBUG) && defined(ImageIO_DEBUG_IO)
3103  // BIASERR("Could not open image for TIFFLIB for reading:" << FileName);
3104  //#endif
3105  // return -1;
3106  // }
3107  // BIASASSERT(tif!=NULL);
3108  //
3109  // // work:
3110  //
3111  // int width=0, height=0, channelcount=0, bitpersample=0;
3112  //
3113  // // Check that it is of a type that we support
3114  //
3115  //
3116  //
3117  // if((== 0) || (bps != 1)){
3118  // fprintf(stderr, "Either undefined or unsupported number of bits per sample\n");
3119  // exit(42);
3120  // }
3121  //
3122  // if((TIFFGetField(image, TIFFTAG_SAMPLESPERPIXEL, &spp) == 0) || (spp != 1)){
3123  // fprintf(stderr, "Either undefined or unsupported number of samples per pixel\n");
3124  // exit(42);
3125  // }
3126  //
3127  // TIFFGetField(image, TIFFTAG_BITSPERSAMPLE, &bitpersample) ;
3128  //
3129  //
3130  // TIFFGetField(tif, TIFFTAG_IMAGEDESCRIPTION, "written by BIAS::ImageIO (Jan Woetzel)");
3131  // TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, img.GetWidth() );
3132  // TIFFGetField(tif, TIFFTAG_IMAGELENGTH, img.GetHeight() );
3133  // TIFFGetField(tif, TIFFTAG_SAMPLESPERPIXEL, img.GetChannelCount() );
3134  // TIFFGetField(tif, TIFFTAG_BITSPERSAMPLE, 8*img.GetDepth() ); // more than enough
3135  // //TIFFGetField(tif, TIFFTAG_BITSPERSAMPLE, img.GetBitDepth() ); // exactly enough
3136  // TIFFGetField(tif, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT); // origin 0,0
3137  // // assume planar tiff cfg., needs one channel or interleaved pixel data
3138  // BIASASSERT((img.GetChannelCount()==1) || (img.IsInterleaved()) );
3139  // TIFFGetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
3140  //
3141  //
3142  // // read TIFF in scanlines
3143  // int res=0;
3144  // //if (rowsPerStrip==1)
3145  // //{
3146  // // // use scanline based API
3147  // // 0000000000000000 these are scanlines
3148  // // 1111111111111111
3149  // // 2222222222222222
3150  // // for (unsigned int y=0; y<img.GetHeight(); y+=rowsPerStrip ){
3151  // // void* pd = img.GetImageDataArray()[y];
3152  // // // 1is returned on success
3153  // // res = TIFFReadScanline(tif, pd, y, 0);
3154  // // BIASASSERT(res==1);
3155  // // }
3156  // //}
3157  // //else
3158  // {
3159  // // use strip based API, possibly encoded
3160  // // 0000000000 these are strips
3161  // // 0000000000
3162  // // 1111111111
3163  // // 1111111111
3164  // // TODO must rowsPerStrip be module height?
3165  // const unsigned int nBytes = rowsPerStrip * img.GetWidth()*img.GetChannelCount()*img.GetDepth() ;
3166  // int strip =0;
3167  // for (unsigned int y=0; y<img.GetHeight(); y+=rowsPerStrip){
3168  // // the number of written Bytes is returned
3169  // res = TIFFReadEncodedStrip(tif, strip, img.GetImageDataArray()[y], nBytes );
3170  // BIASASSERT((int)res==(int)nBytes);
3171  // strip++;
3172  // }
3173  // }
3174  //
3175  // TIFFClose(tif);
3176  // return EXIT_SUCCESS;
3177  //
3178  // } catch (...){
3179  // BIASERR("catched tifflib exception");
3180  // return -1;
3181  // }
3182  // */
3183  return -1;
3184 }
3185 #endif // BIAS_HAVE_TIFF
3186 
EColorModel
These are the most often used color models.
Definition: ImageBase.hh:127
std::ostream & WriteAscii(std::ostream &os) const
Writes only the meta datas where AppData::tag==MD_USE_ASCII to os.
Definition: MetaData.cpp:449
Wrapper for fast libjpeg methods.
Definition: CompressJpeg.hh:50
void SetBitDepth(unsigned bitdepth)
needed by ImageIO
Definition: ImageBase.hh:581
static int ExportDevIL(const std::string &FileName, const ImageBase &img, const bool &fileOverwrite=true, const bool &allowPadding=true)
Save to disk using the DevIL/OpenIL library.
Definition: ImageIO.cpp:2288
static int ExportOpenEXR(const std::string &FileName, const ImageBase &input)
save an .exr OpenEXR image to disk.
Definition: ImageIO.cpp:355
void GetString(std::string &sUUID) const
writes the UUID into a string object
Definition: UUID.cpp:366
static int ParseRAWwithHeader(const std::string &buf, const std::string &tag, unsigned int &retVal)
helper function for ImportRAWwithHeader Parses buf for tag
Definition: ImageIO.cpp:1922
static int ImportOpenEXR(const std::string &FileName, ImageBase &result)
load an .exr OpenEXR image from disk.
Definition: ImageIO.cpp:365
static int ExportImagePnm_(const std::string &FileName, const ImageBase &img, bool sync=false, const bool &writeMetaData=true)
Definition: ImageIO.cpp:991
(16bit) unsigned integer image storage type
Definition: ImageBase.hh:114
static int ImportImage(const std::string &filename, ImageBase &result)
Try to load/import an image from a file using external libs.
Definition: ImageIO.cpp:378
unsigned int GetDepth() const
returns the bytes per channel, which is the sizeof(StorageType) Should match GetSizeDepth(GetStorageT...
Definition: ImageBase.hh:328
gray values, 1 channel
Definition: ImageBase.hh:130
static int ExportMatrix(const std::string &FileName, const ImageBase &img, const bool verbose)
Export BIAS images to text images.
Definition: ImageIO.cpp:1268
bool IsEmpty() const
check if ImageData_ points to allocated image buffer or not
Definition: ImageBase.hh:245
void CopyIn_NoInit(void *data)
Take some data and fill it into the Image.
Definition: ImageBase.cpp:827
bool IsInterleaved() const
Definition: ImageBase.hh:491
int ReadJPEG(const std::string &filename)
Read JPEG file named filename and store its informations in compressed data field.
(8bit) signed char image storage type
Definition: ImageBase.hh:113
int WriteJPEG(const std::string &filename)
Write previously compressed data to file named filename.
static int ImportImageViff_(std::ifstream &ifs, ImageBase &result)
import a one channel grey float viff image (Khoros image format) for compatibility to old stereo code...
Definition: ImageIO.cpp:1386
void SetColorModel(EColorModel Model)
Definition: ImageBase.hh:561
unsigned int GetSizeByte() const
returns the nr.
Definition: ImageBase.hh:352
unsigned long col_size
Definition: ViffHeader.hh:100
Bayer_RGGB, 1 channel RGB image Bayer tile.
Definition: ImageBase.hh:143
MetaData * GetMetaData()
Definition: ImageBase.hh:456
float image storage type
Definition: ImageBase.hh:118
static std::string ExtensionName(const std::string &oldName, const std::string &newExtension)
appends extension to name if extension is not already extension, avoids double extension like &quot;...
Definition: ImageIO.cpp:1072
double image storage type
Definition: ImageBase.hh:119
static int CreateBiasImageCopy(const IplImage *p_src, BIAS::ImageBase &dest)
helper function to create a copy (!) BIAS image from a master Ipl image Data area is NOT shared but...
static BIAS::ImageIO::TFileFormat GetFileFormat(const std::string &str)
determines the BIAS::ImageIO::TFileFormat for a given filename/ extension Decision based on extension...
Definition: ImageIO.cpp:2543
void Add(enum AppData::TAppData ID, unsigned int length, char *data)
Add a new binary meta datum.
Definition: MetaData.cpp:317
static int ImportMagickPP(const std::string &FileName, ImageBase &result, const bool &dummy=false, const bool &readMetaData=true)
Reads an image from disk using the ImageMagick++ library.
Definition: ImageIO.cpp:193
unsigned int GetWidth() const
Definition: ImageBase.hh:312
unsigned int GetBitDepth() const
returns the bits per channel Is not necessairily 8*sizeof(StorageType), could be fewer bits...
Definition: ImageBase.hh:344
std::string sdata
the data as given in ascii meta data
Definition: MetaData.hh:102
static int ImportImagePnm_(std::ifstream &ifs, ImageBase &result, int depth)
Definition: ImageIO.cpp:575
static std::string GetCwd()
Return current working directory as string.
const BIAS::UUID & GetUID() const
returns the UUID of the image
Definition: ImageBase.hh:449
static void InitDevIL()
initialize devIL once globally.
Definition: ImageIO.cpp:2043
static int ImportRAWwithHeader(const std::string &filename, BIAS::ImageBase &img)
Reads a proprietary .RAW format from disk A typical file consists of these blocks: ...
Definition: ImageIO.cpp:1791
static int WriteUnbuffered(const std::string &FileName, const ImageBase &img)
Write a mip binary image to disk circumventing OS caches as good as possible.
Definition: ImageIO.cpp:1975
invalid not set image storage type
Definition: ImageBase.hh:111
(16bit) signed integer image storage type
Definition: ImageBase.hh:115
color values, 3 channels, order: blue,green,red
Definition: ImageBase.hh:132
const void * GetImageData() const
Definition: ImageBase.hh:280
int Compress(BIAS::Image< unsigned char > &srcImg, int quality=60)
Start compression for given BIAS::Image into buffer.
static int Read_(const std::string &FileName, ImageBase &img)
Read a proprietary mip binary Image from disk and allocate memory structure.
Definition: ImageIO.cpp:1341
static int ImportMagickPPAutoconvert(const std::string &FileName, ImageBase &result, const bool &assumeGrey=false, const bool &readMetaData=false)
Reads an image from disk using the ImageMagick++ library.
Definition: ImageIO.cpp:1450
static int ImportOpenCV(const std::string &filename, ImageBase &image)
Reads an image from disk using the OpenCV library.
Definition: ImageIO.cpp:256
static int CreateIplImageShared(const BIAS::ImageBase *p_src, IplImage *&p_dest)
helper function to create a slave ipl image which shares the data area with the master ref...
void ** GetImageDataArray() const
Get an array of pointers to image data.
Definition: ImageBase.hh:305
static int ExportOpenCV(const std::string &filename, const ImageBase &image)
Write an image to disk using the OpenCV library.
Definition: ImageIO.cpp:286
Methods for reading and writing OpenEXR files into and from BIAS ImageBase.
static int ConvertST(const BIAS::ImageBase &source, BIAS::ImageBase &dest, ImageBase::EStorageType targetST)
Function to convert the storage type of images e.g.
unsigned int GetChannelCount() const
returns the number of Color channels, e.g.
Definition: ImageBase.hh:382
color values, 3 channels, order: red,green,blue
Definition: ImageBase.hh:131
int Import(const std::string &FileName, ImageBase &result)
TFileFormat
format specifier when writing an image to a file Do NOT change order or associated enum value because...
Definition: ImageIO.hh:76
void SetVerbose(const bool verbose)
Print error messages to standard output or keep quiet?
int Export(const std::string &FileName, const ImageBase &input, const Imf::Compression &compression=Imf::ZIP_COMPRESSION)
unsigned int GetHeight() const
Definition: ImageBase.hh:319
int Decompress(BIAS::Image< unsigned char > &destImg, bool readComment=false)
Start decompression of previously given data (from ReadJPEG() or SetCompressedData()), results will be stored in destination image.
static int ImportLibJPEG(const std::string &filename, BIAS::ImageBase &result, bool readComment=true)
Reads an image from disk using the LibJPEG library encapsulated in ImportImage.
Definition: ImageIO.cpp:540
int Find(const enum AppData::TAppData tag, AppData &data) const
searches for tag in binary coded AppDatas.
Definition: MetaData.cpp:363
std::ostream & WriteBinary(std::ostream &os) const
Writes only the meta datas where AppData::tag!=MD_USE_ASCII to os.
Definition: MetaData.cpp:439
static int Write_(const std::string &FileName, const ImageBase &img, const bool sync=false, const bool forceNewID=true)
Write a proprietary mip binary Image to disk.
Definition: ImageIO.cpp:1096
static int ExportMagickPP(const std::string &FileName, const ImageBase img, const int &quality=BIAS_DEFAULT_IMAGE_QUALITY, const bool &writeMetaData=false, const bool &forceBinaryPNMformat=true, const bool &losslesJpgMode=false, const bool &writeGZipped=false, const std::string &comment=std::string(""))
Reads an image from disk using the ImageMagick++ library.
Definition: ImageIO.cpp:1652
void Release()
Releases allocated memory.
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
enum TAppData tag
The tag defines the type of data, e.g.
Definition: MetaData.hh:94
static int FilenameExpansion(const std::string &in, std::string &out)
Expand filename, e.g.
static int ImportRADIANCE(const std::string &FileName, ImageBase &result)
import Greg Wards Radiance RGBE image format (.hdr, .rad) A high dynamic range RGBE image contains 24...
Definition: ImageIO.cpp:2624
static std::string DirectoryAndBasename(const std::string &fullname)
Get path and file base name (without suffix) from given path and filename.
void InvalidateUID()
sets the image&#39;s uid to invalid
Definition: ImageBase.hh:597
const StorageType * GetImageData() const
overloaded GetImageData() from ImageBase
Definition: Image.hh:137
void SetUID(const BIAS::UUID &id)
Definition: ImageBase.hh:589
unsigned long row_size
Definition: ViffHeader.hh:97
RGBA, 4 channels, order: red,green,blue,alpha.
Definition: ImageBase.hh:141
void Release(const bool reset_storage_type=false)
Free the allocated data structures Hands off: Do !!NOT!! change the default of reset_storage_type: Im...
Definition: ImageBase.cpp:350
enum EColorModel GetColorModel() const
Definition: ImageBase.hh:407
static std::string GetExtension(const BIAS::ImageIO::TFileFormat &fmt)
return the default extension for a given FileFormat enum
Definition: ImageIO.cpp:2499
(32bit) signed integer image storage type
Definition: ImageBase.hh:117
static std::string Extension(const std::string &fullname)
Get file extension (without dot!) from given path and filename.
static std::string Suffix(const std::string &fullname)
Get file suffix (including dot!) from given path and filename.
static int ImportTIFFLIB(const std::string &FileName, ImageBase &img)
read a tiff image from disk using TiffLib directly
Definition: ImageIO.cpp:3092
static int ImportReal32(const std::string &FileName, ImageBase &result)
Loads proprietary raw floating point 2d image from Mathematica Real32 values Example how to export in...
Definition: ImageIO.cpp:2788
void Init(unsigned int width, unsigned int height, unsigned int nChannels=1, enum EStorageType storageType=ST_unsignedchar, const bool interleaved=true)
Initialize image size and channels.
Definition: ImageBase.cpp:229
static int ImportDevIL(const std::string &FileName, ImageBase &result, const unsigned int &tex3DplaneZ=1)
Reads an image from disk using the DevIL/OpenIL library.
Definition: ImageIO.cpp:2122
static int Load(const std::string &FileName, ImageBase &img)
first tries a call to Read MIP image and if that fails, tries to Import Image with all other availabl...
Definition: ImageIO.cpp:141
int Init(long size=10485760)
Initialize object with standard values and limit shared memory area to given size (in byte...
static unsigned long int MemAlignedBufferSize_
Definition: ImageIO.hh:567
static int BIAS2ImageMagick(const BIAS::ImageBase &input, Magick::Image &dest)
Returns a new, separate ImageMagick Image for use with ImageMagick created from the source BIAS Image...
static void PrintInfoDevIL(std::ostream &os=std::cout)
print info in currently bound DevIL image
Definition: ImageIO.cpp:2085
invalid (not set) image format
Definition: ImageBase.hh:129
enum EStorageType GetStorageType() const
Definition: ImageBase.hh:414
(8bit) unsigned char image storage type
Definition: ImageBase.hh:112
int UpdateImageDataArrayFromImageData_()
recomputes pointer array returned by GetImageDataArray
Definition: ImageBase.cpp:302
static char * MemAlignedBuffer_
Definition: ImageIO.hh:566
static int ImportMatrix(const std::string &FileName, ImageBase &img, const bool verbose)
Import text images to BIAS.
Definition: ImageIO.cpp:1232
int Flip()
flips the image vertically (row order is inverted) In place function return 0 in case of success...
Definition: ImageBase.cpp:834
static int ExportTIFFLIB(const std::string &FileName, const BIAS::ImageBase &img, const unsigned int rowsPerStripArg=0, const unsigned int compressionAlgo=BIAS_COMPRESSION_NONE, const std::string &comment=std::string("BIAS::ImageIO Jan Woetzel"))
Write image to disk using TiffLib directly.
Definition: ImageIO.cpp:2967
static int ImageMagick2BIAS(Magick::Image &image, BIAS::ImageBase &result)
Returns a new, separate BIAS Image created from the source ImageMagick Image.
static int ExportLibJPEG(const std::string &filename, const BIAS::ImageBase &image, const int quality=100)
Writes an image to disk using the LibJPEG library encapsulated in ExportImage.
Definition: ImageIO.cpp:956
interface class for producing/storing Universally Unique IDentifiers
Definition: UUID.hh:98
static int WriteRAW_IMA(const std::string &FileName, const ImageBase &img_const)
Write image in binary file format needed by RealEyes.
Definition: ImageIO.cpp:1173
unsigned long int GetPixelCount() const
returns number of pixels in image
Definition: ImageBase.hh:422
GreyA, 2 channels, grey plus Alpha.
Definition: ImageBase.hh:142
This is the base class for images in BIAS.
Definition: ImageBase.hh:102
static std::string LowerCase(const std::string &input)
Return lower case string of input.
static int ToRGB(const Image< StorageType > &source, Image< StorageType > &dest)
Create a RGB converted copy of source image in this.
int PadToPowerOfTwo(BIAS::ImageBase &dest, const int &padVal=0) const
increase the size of this image to next power of two (e.g.
Definition: ImageBase.cpp:1154
static UUID GenerateUUID(const bool &consecutively=DEFAULT_UUID_CONSECUTIVELY)
static function which simply produces a uuid and returns
Definition: UUID.cpp:235
bool IsValid() const
checks whether this uuid is valid(true) or unitialized(false)
Definition: UUID.hh:210
static int IP_ToGrey(Image< StorageType > &img)
In place conversion to gray image.
this is a chunk of metadata, also see MetaData
Definition: MetaData.hh:49
BGRA color values, 4 channels, order: blue,green,red,alpha.
Definition: ImageBase.hh:150
(32bit) unsigned integer image storage type
Definition: ImageBase.hh:116