Orfeo Toolbox  4.0
otbJPEG2000ImageIO.cxx
Go to the documentation of this file.
1 /*=========================================================================
2 
3  Program: ORFEO Toolbox
4  Language: C++
5  Date: $Date$
6  Version: $Revision$
7 
8 
9  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
10  See OTBCopyright.txt for details.
11 
12 
13  This software is distributed WITHOUT ANY WARRANTY; without even
14  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  PURPOSE. See the above copyright notices for more information.
16 
17 =========================================================================*/
18 #include "otbJPEG2000ImageIO.h"
19 
20 #include <iomanip>
21 #include <iostream>
22 #include <fstream>
23 
24 #include "otbMacro.h"
25 #include "itksys/SystemTools.hxx"
26 #include "itkTimeProbe.h"
27 #include "itkMacro.h"
28 #include "itkMetaDataObject.h"
29 #include "otbMetaDataKey.h"
30 
31 #include <deque>
32 
33 extern "C"
34 {
35 #include "openjpeg.h"
36 }
37 
38 #include "gdal.h"
39 #include "gdaljp2metadata.h"
40 #include "cpl_string.h"
41 #include "ogr_spatialref.h"
42 #include "ogr_srs_api.h"
43 
44 #include "itksys/SystemTools.hxx"
45 
46 #include "otbTinyXML.h"
47 
48 #include "itkMutexLock.h"
49 #include "itkMutexLockHolder.h"
50 
51 void OpjImageDestroy(opj_image_t * img)
52 {
53  if(img)
54  {
55  otbopenjpeg_opj_image_destroy(img);
56  }
57 }
58 
59 void OpjCodestreamDestroy(opj_codestream_info_v2 * cstr)
60 {
61  otbopenjpeg_opj_destroy_cstr_info_v2(&cstr);
62 }
63 
64 void FileDestroy(FILE * file)
65 {
66  if(file)
67  {
68  fclose(file);
69  }
70 }
71 
76 inline int int_ceildivpow2(int a, int b) {
77  return (a + (1 << b) - 1) >> b;
78 }
79 
80 inline unsigned int uint_ceildivpow2(unsigned int a, unsigned int b) {
81  return (a + (1 << b) - 1) >> b;
82 }
83 
87 void error_callback(const char *msg, void *client_data)
88 {
89  (void) msg;
90  (void) client_data;
91  otbMsgDevMacro(<< "OpenJPEG error: " << msg);
92 }
96 void warning_callback(const char *msg, void *client_data)
97 {
98  (void) msg;
99  (void) client_data;
100  otbMsgDevMacro(<< "OpenJPEG warning: " << msg);
101 }
105 void info_callback(const char *msg, void *client_data)
106 {
107  (void) msg;
108  (void) client_data;
109  otbMsgDevMacro(<< "OpenJPEG info: " << msg);
110 }
111 
112 namespace otb
113 {
114 
123 void ComputeOffsets(opj_image_t * tile,
124  const itk::ImageIORegion & ioRegion,
125  unsigned int &l_width_src,
126  unsigned int &l_height_dest,
127  unsigned int &l_width_dest,
128  unsigned int &l_start_offset_dest,
129  unsigned int &l_start_offset_src);
130 
131 /************************************************************************/
132 /* JPEG2000 metadata reader based on GDAL functionalities */
133 /************************************************************************/
135 {
136 public:
137  JPEG2000MetadataReader(const char *filename )
138  {
139  m_MetadataIsRead = false;
140 
141  if( m_JP2Metadata.ReadAndParse(filename) )
142  {
143  m_MetadataIsRead = true;
144  }
145 
146  };
147 
149 
151  std::vector<double> GetGeoTransform(){
152  std::vector<double> geoTransform;
153  for (unsigned int i = 0; i< 6; i++ )
154  geoTransform.push_back(m_JP2Metadata.adfGeoTransform[i]);
155  return geoTransform;
156  };
157 
160  return static_cast<bool>(m_JP2Metadata.bHaveGeoTransform);
161  };
162 
164  int GetGCPCount(){
165  return m_JP2Metadata.nGCPCount;
166  };
167 
169  std::vector<GDAL_GCP> GetGCPs(){
170  std::vector<GDAL_GCP> gcps;
171  int nbGCP = m_JP2Metadata.nGCPCount;
172  for (int i = 0; i< nbGCP; i++ )
173  gcps.push_back(m_JP2Metadata.pasGCPList[i]);
174  return gcps;
175  };
176 
178  const char* GetProjectionRef() {
179  if (m_JP2Metadata.pszProjection)
180  return m_JP2Metadata.pszProjection;
181  else
182  return NULL;
183  };
184 
186  char** GetGMLMetadata() {
187  if (m_JP2Metadata.papszGMLMetadata)
188  return m_JP2Metadata.papszGMLMetadata;
189  else
190  return NULL;
191  };
192 
193  // Get the origin from GML box (use tinyxml to parse the GML box)
194  bool GetOriginFromGMLBox (std::vector<double> &origin);
195 
198 
199 private:
201  GDALJP2Metadata m_JP2Metadata;
202 
203 };
204 
205 bool JPEG2000MetadataReader::GetOriginFromGMLBox (std::vector<double> &origin)
206 {
207  if (!m_MetadataIsRead)
208  return false;
209 
210  std::string gmlString = static_cast<std::string> (m_JP2Metadata.papszGMLMetadata[0]);
211  gmlString.erase(0,18); // We need to remove first part to create a true xml stream
212  otbMsgDevMacro( << "XML extract from GML box: " << gmlString );
213 
214  TiXmlDocument doc;
215  doc.Parse(gmlString.c_str()); // Create xml doc from a string
216 
217  TiXmlHandle docHandle( &doc );
218  TiXmlElement* originTag = docHandle.FirstChild( "gml:FeatureCollection" )
219  .FirstChild( "gml:featureMember" )
220  .FirstChild( "gml:FeatureCollection" )
221  .FirstChild( "gml:featureMember" )
222  .FirstChild( "gml:GridCoverage" )
223  .FirstChild( "gml:gridDomain")
224  .FirstChild( "gml:Grid" )
225  .FirstChild( "gml:limits" )
226  .FirstChild( "gml:GridEnvelope" )
227  .FirstChild( "gml:low").ToElement();
228  if(originTag)
229  {
230  otbMsgDevMacro( << "\t Origin (" << originTag->Value() <<" tag)= "<< originTag->GetText());
231  }
232  else
233  {
234  otbMsgDevMacro( << "Didn't find the GML element which indicate the origin!" );
235  return false;
236  }
237 
238  std::vector<itksys::String> originValues;
239  originValues = itksys::SystemTools::SplitString(originTag->GetText(),' ', false);
240 
241  std::istringstream ss0 (originValues[0]);
242  std::istringstream ss1 (originValues[1]);
243  ss0 >> origin[1];
244  ss1 >> origin[0];
245  origin[0]--;
246  origin[1]--;
247 
248  otbMsgDevMacro( << "\t Origin from GML box: " << origin[0] << ", " << origin[1] );
249 
250  return true;
251 }
252 
253 
254 /************************************************************************/
255 /* JPEG2000 internal reader based on openjpeg */
256 /************************************************************************/
258 {
259 public:
261 
263  {
264  this->Clean();
265  }
266 
267  boost::shared_ptr<opj_image_t> DecodeTile(unsigned int tileIndex);
268 
269  const std::vector<unsigned int> & GetAvailableResolutions(){return this->m_AvailableResolutions; };
270 
271  void Clean();
272 
273  int CanRead();
274 
275  int Open(const char *filename, unsigned int resolution);
276 
277  bool m_IsOpen;
278  OPJ_CODEC_FORMAT m_CodecFormat;
279 
280  unsigned int m_Width;
281  unsigned int m_Height;
282 
283  unsigned int m_NbOfComponent;
284 
285  std::vector<unsigned int> m_XResolution;
286  std::vector<unsigned int> m_YResolution;
287  std::vector<unsigned int> m_Precision;
288  std::vector<int> m_Signed;
289 
290  unsigned int m_TileWidth;
291  unsigned int m_TileHeight;
292  unsigned int m_XNbOfTile;
293  unsigned int m_YNbOfTile;
294 
295  std::vector<unsigned int> m_AvailableResolutions;
296 
297  unsigned int m_ResolutionFactor;
298 
299 private:
300  boost::shared_ptr<FILE> m_File;
301  int Initialize();
302 };
303 
304 
305 int JPEG2000InternalReader::Open(const char *filename, unsigned int resolution)
306 {
307  this->Clean();
308 
309  // Open the file
310  this->m_File = boost::shared_ptr<FILE>(fopen(filename, "rb"),FileDestroy);
311  if (!this->m_File)
312  {
313  this->Clean();
314  return 0;
315  }
316 
317  // Find the codec file format
318  std::string lFileName(filename);
319 
320  if (itksys::SystemTools::LowerCase(itksys::SystemTools::GetFilenameLastExtension(lFileName)) == ".j2k")
321  {
322  this->m_CodecFormat = CODEC_J2K;
323  }
324  else if (itksys::SystemTools::LowerCase(itksys::SystemTools::GetFilenameLastExtension(lFileName)) == ".jp2"
325  || itksys::SystemTools::LowerCase(itksys::SystemTools::GetFilenameLastExtension(lFileName)) == ".jpx")
326  {
327  this->m_CodecFormat = CODEC_JP2;
328  }
329  else
330  {
331  this->Clean();
332  return 0;
333  }
334 
335  this->m_ResolutionFactor = resolution;
336 
337  // Initialize the codec and the stream
338  if (!this->Initialize())
339  {
340  this->Clean();
341  return 0;
342  }
343 
344  this->m_IsOpen = true;
345  return 1;
346 }
347 
349 {
350  m_File = boost::shared_ptr<FILE>();
351 
352  this->m_XResolution.clear();
353  this->m_YResolution.clear();
354  this->m_Precision.clear();
355  this->m_Signed.clear();
356  m_AvailableResolutions.clear();
357 
358  this->m_Width = 0;
359  this->m_Height = 0;
360  this->m_NbOfComponent = 0;
361  this->m_TileWidth = 0;
362  this->m_TileHeight = 0;
363  this->m_XNbOfTile = 0;
364  this->m_YNbOfTile = 0;
365 
366  this->m_IsOpen = false;
367  this->m_CodecFormat = CODEC_UNKNOWN;
368 }
369 
370 boost::shared_ptr<opj_image_t> JPEG2000InternalReader::DecodeTile(unsigned int tileIndex)
371 {
372 
373  if (!m_File)
374  {
375  this->Clean();
376  return boost::shared_ptr<opj_image_t>();
377  }
378 
379  // Creating the file stream
380  boost::shared_ptr<opj_stream_t> stream = boost::shared_ptr<opj_stream_t>(otbopenjpeg_opj_stream_create_default_file_stream(m_File.get(), true),otbopenjpeg_opj_stream_destroy);
381  if (!stream)
382  {
383  this->Clean();
384  return boost::shared_ptr<opj_image_t>();
385  }
386 
387  // Creating the codec
388  boost::shared_ptr<opj_codec_t> codec = boost::shared_ptr<opj_codec_t>(otbopenjpeg_opj_create_decompress_v2(this->m_CodecFormat),otbopenjpeg_opj_destroy_codec);
389 
390  if (!codec)
391  {
392  this->Clean();
393  return boost::shared_ptr<opj_image_t>();
394  }
395 
396  // Setting default parameters
397  opj_dparameters_t parameters;
398  otbopenjpeg_opj_set_default_decoder_parameters(&parameters);
399  parameters.cp_reduce = static_cast<int>(this->m_ResolutionFactor);
400 
401  // Set default event mgr
402  opj_event_mgr_t eventManager;
403  eventManager.info_handler = info_callback;
404  eventManager.warning_handler = warning_callback;
405  eventManager.error_handler = error_callback;
406 
407  // Setup the decoder decoding parameters using user parameters
408  if (!otbopenjpeg_opj_setup_decoder_v2(codec.get(), &parameters, &eventManager))
409  {
410  this->Clean();
411  return boost::shared_ptr<opj_image_t>();
412  }
413 
414  // Read the main header of the codestream and if necessary the JP2
415  // boxes
416  opj_image_t * unsafeOpjImgPtr = NULL;
417 
418  if (!otbopenjpeg_opj_read_header(stream.get(), codec.get(),&unsafeOpjImgPtr))
419  {
420  boost::shared_ptr<opj_image_t> image = boost::shared_ptr<opj_image_t>(unsafeOpjImgPtr,OpjImageDestroy);
421  this->Clean();
422  return boost::shared_ptr<opj_image_t>();
423  }
424 
425  boost::shared_ptr<opj_image_t> image = boost::shared_ptr<opj_image_t>(unsafeOpjImgPtr,OpjImageDestroy);
426 
427  if( otbopenjpeg_opj_get_decoded_tile(codec.get(), stream.get(), image.get(), tileIndex))
428  {
429  otbMsgDevMacro(<<"Tile "<<tileIndex<<" read from file");
430 
431  return image;
432  }
433  else
434  {
435  this->Clean();
436  return boost::shared_ptr<opj_image_t>();
437  }
438 }
439 
441 {
442  this->Clean();
443 }
444 
446 {
447  if (m_File)
448  {
449  // Creating the file stream
450  boost::shared_ptr<opj_stream_t> stream = boost::shared_ptr<opj_stream_t>(otbopenjpeg_opj_stream_create_default_file_stream(m_File.get(), true),otbopenjpeg_opj_stream_destroy);
451  if (!stream)
452  {
453  this->Clean();
454  return 0;
455  }
456 
457  // Creating the codec
458  boost::shared_ptr<opj_codec_t> codec = boost::shared_ptr<opj_codec_t>(otbopenjpeg_opj_create_decompress_v2(this->m_CodecFormat),otbopenjpeg_opj_destroy_codec);
459 
460  if (!codec)
461  {
462  this->Clean();
463  return 0;
464  }
465 
466  // Setting default parameters
467  opj_dparameters_t parameters;
468  otbopenjpeg_opj_set_default_decoder_parameters(&parameters);
469  parameters.cp_reduce = static_cast<int>(this->m_ResolutionFactor);
470 
471  // Set default event mgr
472  opj_event_mgr_t eventManager;
473  eventManager.info_handler = info_callback;
474  eventManager.warning_handler = warning_callback;
475  eventManager.error_handler = error_callback;
476 
477  // Setup the decoder decoding parameters using user parameters
478  if (!otbopenjpeg_opj_setup_decoder_v2(codec.get(), &parameters, &eventManager))
479  {
480  this->Clean();
481  return 0;
482  }
483 
484  // Read the main header of the codestream and if necessary the JP2
485  // boxes
486  opj_image_t * unsafeOpjImgPtr = NULL;
487 
488  if (!otbopenjpeg_opj_read_header(stream.get(), codec.get(),&unsafeOpjImgPtr))
489  {
490  boost::shared_ptr<opj_image_t> image = boost::shared_ptr<opj_image_t>(unsafeOpjImgPtr,OpjImageDestroy);
491  this->Clean();
492  return 0;
493  }
494 
495  boost::shared_ptr<opj_image_t> image = boost::shared_ptr<opj_image_t>(unsafeOpjImgPtr,OpjImageDestroy);
496 
497  // Get the codestream information
498  boost::shared_ptr<opj_codestream_info_v2> cstrInfo = boost::shared_ptr<opj_codestream_info_v2>(otbopenjpeg_opj_get_cstr_info(codec.get()),OpjCodestreamDestroy);
499 
500  if (!cstrInfo)
501  {
502  std::cerr << "ERROR while get codestream info" << std::endl;
503  this->Clean();
504  return 0;
505  }
506 
507  // We can now retrieve the main information of the image and the codestream
508  // (based on the first component and with no subsampling)
509  this->m_Width = image->comps->w;
510  this->m_Height = image->comps->h;
511 
512  otbMsgDevMacro(<< "JPEG2000InternalReader dimension (after reading header) = " << image->comps->w << " x "
513  << image->comps->w << " x " << image->comps->h );
514 
515  this->m_TileHeight = cstrInfo->tdy;
516  this->m_TileWidth = cstrInfo->tdx;
517  this->m_XNbOfTile = cstrInfo->tw;
518  this->m_YNbOfTile = cstrInfo->th;
519 
520  this->m_NbOfComponent = image->numcomps;
521 
522  for (unsigned int itComp = 0; itComp < this->m_NbOfComponent; itComp++)
523  {
524  this->m_Precision.push_back( image->comps[itComp].prec);
525  this->m_Signed.push_back( image->comps[itComp].sgnd);
526  this->m_XResolution.push_back( image->comps[itComp].dx);
527  this->m_YResolution.push_back( image->comps[itComp].dy);
528  }
529 
530  // Warning: This value is based on the first component of the default tile parameters.
531  unsigned int numResAvailable = cstrInfo->m_default_tile_info.tccp_info[0].numresolutions;
532  m_AvailableResolutions.clear();
533  for (unsigned int itRes = 0; itRes < numResAvailable; itRes++)
534  {
535  m_AvailableResolutions.push_back(itRes);
536  }
537  }
538 
539  return 1;
540 }
541 
542 
544  {
545  if (Initialize() &&
546  ( this->m_Width > 0 ) && ( this->m_Height > 0 ) &&
547  ( this->m_TileWidth > 0 ) && ( this->m_TileHeight > 0 ) &&
548  ( this->m_XNbOfTile > 0 ) && ( this->m_YNbOfTile > 0 ) &&
549  ( this->m_NbOfComponent > 0 ) )
550  {
551 
552  // We manage only JPEG2000 file with characteristics which are equal between components
553  for(unsigned int itComp = 0; itComp < this->m_NbOfComponent - 1; itComp++)
554  {
555  if ( (this->m_Precision[itComp] != this->m_Precision[itComp+1]) &&
556  (this->m_Signed[itComp] != this->m_Signed[itComp+1]) &&
557  (this->m_XResolution[itComp] != this->m_XResolution[itComp+1]) &&
558  (!this->m_XResolution[itComp]) &&
559  (this->m_YResolution[itComp] != this->m_YResolution[itComp+1]) &&
560  (!this->m_YResolution[itComp]) )
561  {
562  return 0;
563  }
564  }
565 
566  return 1;
567  }
568  else return 0;
569  }
570 
571 /************************************************************************/
572 /* Class to manage JPEG2000 tile cache system */
573 /************************************************************************/
575 {
576 public:
579 
580  typedef std::pair<unsigned int, boost::shared_ptr<opj_image_t> > CachedTileType;
581  typedef std::deque<CachedTileType> TileCacheType;
582 
585  boost::shared_ptr<opj_image_t> GetTile(unsigned int tileIndex);
586 
588  void AddTile(unsigned int tileIndex, boost::shared_ptr<opj_image_t> tileData);
589 
591  void RemoveOneTile();
592 
594  void Clear();
595 
597  void Initialize(unsigned int originalWidthTile, unsigned int originalHeightTile,
598  unsigned int nbComponent,
599  unsigned int precision,
600  unsigned int resolution)
601  {
602  this->EstimateTileCacheSize(originalWidthTile, originalHeightTile,
603  nbComponent,
604  precision,
605  resolution);
607  m_IsReady = true;
608  };
609 
611  void SetCacheSizeInTiles(unsigned int nbOfTiles)
612  {
613  if (nbOfTiles > 0 && m_IsReady)
614  {
615  m_CacheSizeInTiles = nbOfTiles;
617  }
618  };
619 
621  unsigned int GetCacheSizeInTiles() {return m_CacheSizeInTiles; };
622 
624  void SetCacheSizeInByte(unsigned int sizeInByte)
625  {
626  if (sizeInByte > 0 && m_IsReady)
627  {
628  m_CacheSizeInByte = sizeInByte;
631  else
632  m_CacheSizeInTiles = 0;
633  }
634  };
635 
637  {
638  return static_cast<unsigned int>(m_Cache.size());
639  };
640 
641 private:
643  unsigned int m_CacheSizeInTiles;
644  unsigned int m_CacheSizeInByte;
645  unsigned int m_TileCacheSizeInByte;
646  bool m_IsReady;
647 
649 
651  void EstimateTileCacheSize(unsigned int originalWidthTile, unsigned int originalHeightTile,
652  unsigned int nbComponent,
653  unsigned int precision,
654  unsigned int resolution);
655 
656 };
657 
658 JPEG2000TileCache::JPEG2000TileCache() : m_Cache(), m_CacheSizeInTiles(4), m_CacheSizeInByte(0), m_IsReady(false)
659 {}
660 
662 {
663  this->Clear();
664 }
665 
666 
667 void JPEG2000TileCache::EstimateTileCacheSize(unsigned int originalWidthTile, unsigned int originalHeightTile,
668  unsigned int nbComponent,
669  unsigned int precision,
670  unsigned int resolution)
671 {
672  this->m_TileCacheSizeInByte = originalWidthTile * originalHeightTile
673  * nbComponent
674  * sizeof(OPJ_INT32)
675  / vcl_pow(2, 2*static_cast<double>(resolution) );
676 
677  if (!this->m_TileCacheSizeInByte)
678  {
679  otbMsgDevMacro( << "TileCacheSizeInByte is estimated at " << m_TileCacheSizeInByte
680  << " bytes so we don't used the cache");
681  }
682 
683  otbMsgDevMacro( << "m_TileCacheSizeInByte = " << m_TileCacheSizeInByte );
684 }
685 
687 {
688  m_Cache.clear();
689 }
690 
691 
692 boost::shared_ptr<opj_image_t> JPEG2000TileCache::GetTile(unsigned int tileIndex)
693 {
694  for(TileCacheType::iterator it = m_Cache.begin();
695  it != m_Cache.end(); ++it)
696  {
697  if(it->first == tileIndex)
698  {
699  otbMsgDevMacro(<<"Tile "<<it->first<<" loaded from cache");
700  return it->second;
701  }
702  }
703  return boost::shared_ptr<opj_image_t>();
704 }
705 
707 {
708  if(!m_Cache.empty())
709  {
710  m_Cache.pop_front();
711  }
712 }
713 
714 void JPEG2000TileCache::AddTile(unsigned int tileIndex, boost::shared_ptr<opj_image_t> tileData)
715 {
716  // This helper class makes sure the Mutex is unlocked
717  // in the event an exception is thrown.
719 
720  if(!m_IsReady)
721  {
722  std::cerr<<(this)<<" Cache is not configured !"<<std::endl;
723  }
724 
725  for(TileCacheType::const_iterator it = m_Cache.begin();
726  it != m_Cache.end(); ++it)
727  {
728  if(it->first == tileIndex)
729  {
730  return;
731  }
732  }
733  if(m_Cache.size() >= m_CacheSizeInTiles)
734  {
735  this->RemoveOneTile();
736  }
737  m_Cache.push_back(CachedTileType(tileIndex, tileData));
738 }
739 
740 /************************************************************************/
741 /* JPEG2000ImageIO */
742 /************************************************************************/
744 {
745  // Initialize multi-threader
747  m_NumberOfThreads = m_Threader->GetNumberOfThreads();
748 
749  for(int i = 0; i<m_NumberOfThreads; ++i)
750  {
751  m_InternalReaders.push_back(boost::shared_ptr<JPEG2000InternalReader>(new JPEG2000InternalReader));
752  }
753  m_TileCache = boost::shared_ptr<JPEG2000TileCache>(new JPEG2000TileCache);
754 
755  // By default set number of dimensions to two.
756  this->SetNumberOfDimensions(2);
759 
760  // Set default spacing to one
761  m_Spacing[0] = 1.0;
762  m_Spacing[1] = 1.0;
763  // Set default origin to zero
764  m_Origin[0] = 0.0;
765  m_Origin[1] = 0.0;
766 
767  m_BytePerPixel = 1;
768  m_ResolutionFactor = 0; // Full resolution by default
769 
770  m_CacheSizeInByte = 0; // By default no cache
771 }
772 
774 {}
775 
776 bool JPEG2000ImageIO::CanReadFile(const char* filename)
777 {
778  if (filename == NULL)
779  {
780  itkDebugMacro(<< "No filename specified.");
781  return false;
782  }
783 
784  bool success = true;
785 
786  for(ReaderVectorType::iterator it = m_InternalReaders.begin();
787  it != m_InternalReaders.end();
788  ++it)
789  {
790 
791  if ( !(*it)->Open(filename, m_ResolutionFactor) )
792  {
793  success = false;
794  }
795  }
796 
797  // If one of the readers fails, clean everything
798  if(!success)
799  {
800  for(ReaderVectorType::iterator it = m_InternalReaders.begin();
801  it != m_InternalReaders.end();
802  ++it)
803  {
804  (*it)->Clean();
805  }
806  }
807  return success;
808 }
809 
810 // Used to print information about this object
811 void JPEG2000ImageIO::PrintSelf(std::ostream& os, itk::Indent indent) const
812 {
813  Superclass::PrintSelf(os, indent);
814  os << indent << "Resolution Factor: " << m_ResolutionFactor << "\n";
815 }
816 
817 // Read a 3D image not implemented yet
819 {
820 }
821 
824 {
825  std::vector<boost::shared_ptr<JPEG2000InternalReader> > Readers;
826  std::vector<JPEG2000TileCache::CachedTileType> * Tiles;
828  boost::shared_ptr<JPEG2000TileCache> Cache;
829  void * Buffer;
830 };
831 
832 
834 bool JPEG2000ImageIO::GetResolutionInfo(std::vector<unsigned int>& res, std::vector<std::string>& desc)
835 {
836  res = this->m_InternalReaders[0]->GetAvailableResolutions();
837 
838  if (res.empty())
839  return false;
840 
841  int originalWidth = m_InternalReaders[0]->m_Width;
842  int originalHeight = m_InternalReaders[0]->m_Height;
843 
844  for (std::vector<unsigned int>::iterator itRes = res.begin(); itRes < res.end(); itRes++)
845  {
846  // For each resolution we will compute the tile dim and image dim
847  std::ostringstream oss;
848 
849  int w = int_ceildivpow2( originalWidth, *itRes);
850  int h = int_ceildivpow2( originalHeight, *itRes);
851 
852  int tw = int_ceildivpow2(m_InternalReaders[0]->m_TileWidth, *itRes);
853  int th = int_ceildivpow2(m_InternalReaders[0]->m_TileHeight, *itRes);
854 
855  oss << "Resolution: " << *itRes << " (Image [w x h]: " << w << "x" << h << ", Tile [w x h]: " << tw << "x" << th << ")";
856 
857  desc.push_back(oss.str());
858  }
859 
860 
861  return true;
862 }
863 
864 bool JPEG2000ImageIO::GetAvailableResolutions(std::vector<unsigned int>& res)
865 {
866  res = this->m_InternalReaders[0]->GetAvailableResolutions();
867 
868  if (res.empty())
869  return false;
870 
871  return true;
872 }
873 
875 {
876  std::vector<unsigned int> tempResList = this->m_InternalReaders[0]->GetAvailableResolutions();
877 
878  if (tempResList.empty())
879  {
880  itkExceptionMacro(<< "Available resolutions in JPEG2000 is empty");
881  }
882 
883  return tempResList.size() - 1;
884 }
885 
886 
887 // Read image
888 void JPEG2000ImageIO::Read(void* buffer)
889 {
890  itk::TimeProbe chrono;
891  chrono.Start();
892 
893  // Check if conversion succeed
894  if (buffer == NULL)
895  {
896  itkExceptionMacro(<< "JPEG2000ImageIO : Bad alloc");
897  return;
898  }
899 
900  // Re-open the file if it was closed
901  bool open = true;
902  for(ReaderVectorType::iterator it = m_InternalReaders.begin();
903  it != m_InternalReaders.end();
904  ++it)
905  {
906  open = (*it)->m_IsOpen && open;
907  }
908 
909  if ( !open )
910  {
911  if ( !this->CanReadFile( m_FileName.c_str() ) )
912  {
913  itkExceptionMacro(<< "Cannot open file " << this->m_FileName << "!");
914  return;
915  }
916  }
917 
918  if (m_ResolutionFactor >= this->m_InternalReaders[0]->m_AvailableResolutions.size())
919  {
920  itkExceptionMacro(<< "Resolution not available in the file!");
921  return;
922  }
923 
924  std::vector<unsigned int> tileList = this->ComputeTileList();
925  if (tileList.empty())
926  {
927  for(ReaderVectorType::iterator it = m_InternalReaders.begin();
928  it != m_InternalReaders.end();
929  ++it)
930  {
931  (*it)->Clean();
932  }
933  itkExceptionMacro(<< " IORegion does not correspond to any tile!");
934  }
935 
936  // Here we sort between tiles from cache and tiles to read
937  std::vector<JPEG2000TileCache::CachedTileType> cachedTiles;
938  std::vector<JPEG2000TileCache::CachedTileType> toReadTiles;
939 
940  for (std::vector<unsigned int>::iterator itTile = tileList.begin(); itTile < tileList.end(); ++itTile)
941  {
942  boost::shared_ptr<opj_image_t> currentImage(m_TileCache->GetTile(*itTile));
943 
944  JPEG2000TileCache::CachedTileType currentTile = std::make_pair((*itTile), currentImage);
945 
946  if(!currentImage)
947  {
948  toReadTiles.push_back(currentTile);
949  }
950  else
951  {
952  cachedTiles.push_back(currentTile);
953  }
954  }
955 
956  // First, load tiles from cache
957  for (std::vector<JPEG2000TileCache::CachedTileType>::iterator itTile = cachedTiles.begin(); itTile < cachedTiles.end(); ++itTile)
958  {
959  this->LoadTileData(buffer, itTile->second.get());
960  }
961 
962  // If we will read more tiles than the cache size, clear it
963  if(toReadTiles.size() > m_TileCache->GetCacheSizeInTiles())
964  {
965  m_TileCache->Clear();
966  }
967  // Else if there is not enough rooms from new tiles
968  else if(toReadTiles.size() > (m_TileCache->GetCacheSizeInTiles() - m_TileCache->GetCurrentNumberOfTileInCache()))
969  {
970  int nbTileToRemove = toReadTiles.size() - (m_TileCache->GetCacheSizeInTiles() - m_TileCache->GetCurrentNumberOfTileInCache());
971  // Remove from cache as many tiles that will be read in this step
972  for (int itTileR = 0; itTileR < nbTileToRemove; ++itTileR)
973  {
974  m_TileCache->RemoveOneTile();
975  }
976  }
977 
978  // Decode all tiles not in cache in parallel
979  if(!toReadTiles.empty())
980  {
981  unsigned int nbThreads = itk::MultiThreader::GetGlobalDefaultNumberOfThreads();
982  if (nbThreads > toReadTiles.size())
983  {
984  nbThreads = toReadTiles.size();
985  }
986  this->GetMultiThreader()->SetNumberOfThreads(nbThreads);
987 
988  // Set up the multithreaded processing
989  ThreadStruct str;
991  str.Tiles = &toReadTiles;
992  str.IO = this;
993  str.Cache = m_TileCache;
994  str.Buffer = buffer;
995 
996  // Set-up multi-threader
997  this->GetMultiThreader()->SetSingleMethod(this->ThreaderCallback, &str);
998 
999  // multithread the execution
1001  }
1002 
1003  chrono.Stop();
1004  otbMsgDevMacro( << "JPEG2000ImageIO::Read took " << chrono.GetTotal() << " sec");
1005 
1006  for(ReaderVectorType::iterator it = m_InternalReaders.begin();
1007  it != m_InternalReaders.end();
1008  ++it)
1009  {
1010  (*it)->Clean();
1011  }
1012 }
1013 
1014 // The void * interface prevent us to propagate shared_ptr here
1015 void JPEG2000ImageIO::LoadTileData(void * buffer, void * currentTile)
1016 {
1017  opj_image_t * tile = static_cast<opj_image_t *>(currentTile);
1018 
1019  if(!tile)
1020  {
1021  itkExceptionMacro(<<"Tile needed but not loaded.");
1022  }
1023 
1024  // Get nb. of lines and columns of the region to read
1025  /* -Wunused-variable
1026  int lNbLines = this->GetIORegion().GetSize()[1];
1027  */
1028  int lNbColumns = this->GetIORegion().GetSize()[0];
1029  /* -Wunused-variable
1030  int lFirstLine = this->GetIORegion().GetIndex()[1]; // [1... ]
1031  int lFirstColumn = this->GetIORegion().GetIndex()[0]; // [1... ]
1032  */
1033  unsigned int lWidthSrc; // Width of the input pixel in nb of pixel
1034  unsigned int lHeightDest; // Height of the area where write in nb of pixel
1035  unsigned int lWidthDest; // Width of the area where write in nb of pixel
1036  unsigned int lStartOffsetPxlDest; // Offset where begin to write the area in the otb buffer in nb of pixel
1037  unsigned int lStartOffsetPxlSrc; // Offset where begin to write the area in the otb buffer in nb of pixel
1038 
1039  ComputeOffsets(tile, this->GetIORegion(), lWidthSrc, lHeightDest, lWidthDest, lStartOffsetPxlDest, lStartOffsetPxlSrc);
1040 
1041  switch (this->GetComponentType())
1042  {
1043  case CHAR:
1044  {
1045  char *p = static_cast<char *> (buffer);
1046  for (unsigned int j = 0; j < lHeightDest; ++j)
1047  {
1048  char* current_dst_line = p + (lStartOffsetPxlDest + j * lNbColumns) * this->m_NumberOfComponents;
1049 
1050  for (unsigned int k = 0; k < lWidthDest; ++k)
1051  {
1052  for (unsigned int itComp = 0; itComp < this->m_NumberOfComponents; itComp++)
1053  {
1054  OPJ_INT32* data = tile->comps[itComp].data;
1055  *(current_dst_line++) = static_cast<char> (data[lStartOffsetPxlSrc + k + j * lWidthSrc]);
1056  }
1057  }
1058  }
1059  }
1060  break;
1061  case UCHAR:
1062  {
1063  unsigned char *p = static_cast<unsigned char *> (buffer);
1064  for (unsigned int j = 0; j < lHeightDest; ++j)
1065  {
1066  unsigned char* current_dst_line = p + (lStartOffsetPxlDest + j * lNbColumns) * this->m_NumberOfComponents;
1067 
1068  for (unsigned int k = 0; k < lWidthDest; ++k)
1069  {
1070  for (unsigned int itComp = 0; itComp < this->m_NumberOfComponents; itComp++)
1071  {
1072  OPJ_INT32* data = tile->comps[itComp].data;
1073  unsigned char component_val = data[lStartOffsetPxlSrc + k + j * lWidthSrc] & 0xff;
1074  *(current_dst_line++) = static_cast<unsigned char> (component_val);
1075  }
1076  }
1077  }
1078  }
1079  break;
1080  case SHORT:
1081  {
1082  short *p = static_cast<short *> (buffer);
1083  for (unsigned int j = 0; j < lHeightDest; ++j)
1084  {
1085  short* current_dst_line = p + (lStartOffsetPxlDest + j * lNbColumns) * this->m_NumberOfComponents;
1086 
1087  for (unsigned int k = 0; k < lWidthDest; ++k)
1088  {
1089  for (unsigned int itComp = 0; itComp < this->m_NumberOfComponents; itComp++)
1090  {
1091  OPJ_INT32* data = tile->comps[itComp].data;
1092  *(current_dst_line++) = static_cast<short> (data[lStartOffsetPxlSrc + k + j * lWidthSrc]);
1093  }
1094  }
1095  }
1096  }
1097  break;
1098  case USHORT:
1099  {
1100  unsigned short *p = static_cast<unsigned short *> (buffer);
1101  for (unsigned int j = 0; j < lHeightDest; ++j)
1102  {
1103  unsigned short* current_dst_line = p + (lStartOffsetPxlDest + j * lNbColumns) * this->m_NumberOfComponents;
1104 
1105  for (unsigned int k = 0; k < lWidthDest; ++k)
1106  {
1107  for (unsigned int itComp = 0; itComp < this->m_NumberOfComponents; itComp++)
1108  {
1109  OPJ_INT32* data = tile->comps[itComp].data;
1110  *(current_dst_line++) = static_cast<unsigned short> (data[lStartOffsetPxlSrc + k + j * lWidthSrc] & 0xffff);
1111  }
1112  }
1113  }
1114  }
1115  break;
1116  case INT:
1117  case UINT:
1118  default:
1119  itkGenericExceptionMacro(<< "This data type is not handled");
1120  break;
1121  }
1122 }
1123 
1125 {
1126  ThreadStruct *str;
1127  unsigned int total, threadCount;
1128  itk::ThreadIdType threadId;
1129 
1130  threadId = ((itk::MultiThreader::ThreadInfoStruct *)(arg))->ThreadID;
1131  threadCount = ((itk::MultiThreader::ThreadInfoStruct *)(arg))->NumberOfThreads;
1132 
1133  str = (ThreadStruct *)(((itk::MultiThreader::ThreadInfoStruct *)(arg))->UserData);
1134 
1135  // Retrieve data
1136  std::vector<boost::shared_ptr<JPEG2000InternalReader> > readers = str->Readers;
1137  std::vector<JPEG2000TileCache::CachedTileType> * tiles = str->Tiles;
1138  JPEG2000ImageIO::Pointer io = str->IO;
1139  boost::shared_ptr<JPEG2000TileCache> cache = str->Cache;
1140  void * buffer = str->Buffer;
1141 
1142  total = std::min((unsigned int)tiles->size(), threadCount);
1143 
1144  if(total == 0)
1145  {
1146  return ITK_THREAD_RETURN_VALUE;
1147  }
1148 
1149 
1150  unsigned int tilesPerThread = tiles->size()/total;
1151  if(tilesPerThread == 0)
1152  {
1153  tilesPerThread = 1;
1154  }
1155 
1156  for(unsigned int i = threadId * tilesPerThread;
1157  i < tilesPerThread * (threadId+1);
1158  ++i)
1159  {
1160  boost::shared_ptr<opj_image_t> currentTile = readers.at(threadId)->DecodeTile(tiles->at(i).first);
1161 
1162  // Check if tile is valid
1163  if(!currentTile)
1164  {
1165  readers.at(threadId)->Clean();
1166  itkGenericExceptionMacro(" otbopenjpeg failed to decode the desired tile "<<tiles->at(i).first << "!");
1167  }
1168 
1169  otbMsgDevMacro(<< " Tile " << tiles->at(i).first << " decoded by thread "<<threadId);
1170 
1171  io->LoadTileData(buffer, currentTile.get());
1172 
1173  if (cache->GetCacheSizeInTiles() != 0)
1174  {
1175  cache->AddTile(tiles->at(i).first, currentTile);
1176  }
1177  }
1178 
1179  unsigned int lastTile = threadCount*tilesPerThread + threadId;
1180 
1181  // TODO: check this last part
1182 
1183  if(lastTile < tiles->size())
1184  {
1185  boost::shared_ptr<opj_image_t> currentTile = readers.at(threadId)->DecodeTile(tiles->at(lastTile).first);
1186 
1187  // Check if tile is valid
1188  if(!currentTile)
1189  {
1190  readers.at(threadId)->Clean();
1191  itkGenericExceptionMacro(" otbopenjpeg failed to decode the desired tile "<<tiles->at(lastTile).first << "!");
1192  }
1193 
1194  otbMsgDevMacro(<< " Tile " <<tiles->at(lastTile).first << " decoded by thread "<<threadId);
1195 
1196  io->LoadTileData(buffer, currentTile.get());
1197 
1198  if (cache->GetCacheSizeInTiles() != 0)
1199  {
1200  cache->AddTile(tiles->at(lastTile).first, currentTile);
1201  }
1202  }
1203 
1204  return ITK_THREAD_RETURN_VALUE;
1205 }
1206 
1208 {
1209  itk::ExposeMetaData<unsigned int>(this->GetMetaDataDictionary(),
1212 
1213  // Initialize some parameters of the tile cache
1214  this->m_TileCache->Initialize(m_InternalReaders.front()->m_TileWidth,
1215  m_InternalReaders.front()->m_TileHeight,
1216  m_InternalReaders.front()->m_NbOfComponent,
1219 
1220  // If available set the size of the cache
1221  if (this->m_CacheSizeInByte)
1222  this->m_TileCache->SetCacheSizeInByte(this->m_CacheSizeInByte);
1223 }
1224 
1226 {
1227  // Extract metadata
1228  // In case the metadata are not set, the function silently returns, doing nothing
1229  itk::ExposeMetaData<unsigned int>(this->GetMetaDataDictionary(),
1232 
1233  // Now initialize the itk dictionary
1235 
1236  JPEG2000MetadataReader lJP2MetadataReader(m_FileName.c_str());
1237 
1238  if (lJP2MetadataReader.m_MetadataIsRead)
1239  {
1240  otbMsgDevMacro(<<"JPEG2000 file has metadata available!");
1241 
1242  /* GEOTRANSFORM */
1243  if (lJP2MetadataReader.HaveGeoTransform())
1244  {
1245  otbMsgDevMacro(<< "JPEG2000 file has a geotransform!");
1246  std::vector<double> geoTransform = lJP2MetadataReader.GetGeoTransform();
1247 
1248  itk::EncapsulateMetaData<MetaDataKey::VectorType>(dict, MetaDataKey::GeoTransformKey, geoTransform);
1249 
1250  /*std::cout << "from gml box, geotransform: ";
1251  for (int i = 0; i < 6; i++)
1252  {
1253  std::cout << geoTransform[i] << ", ";
1254  }
1255  std::cout << std::endl; */
1256 
1257  // Retrieve origin and spacing from the geo transform
1258  m_Origin[0] = geoTransform[0];
1259  m_Origin[1] = geoTransform[3];
1260  m_Spacing[0] = geoTransform[1];
1261  m_Spacing[1] = geoTransform[5];
1262 
1263  if ( m_Spacing[0]== 0 || m_Spacing[1] == 0)
1264  {
1265  // Manage case where axis are not standard
1266  if (geoTransform[2] != 0 && geoTransform[4] != 0 )
1267  {
1268  m_Spacing[0] = geoTransform[2];
1269  m_Spacing[1] = geoTransform[4];
1270  }
1271  else
1272  {
1273  otbWarningMacro(<< "JPEG2000 file has an incorrect geotransform (spacing = 0)!");
1274  m_Spacing[0] = 1;
1275  m_Spacing[1] = 1;
1276  }
1277  }
1278  }
1279 
1280  /* GCPs */
1281  if (lJP2MetadataReader.GetGCPCount() > 0)
1282  {
1283  // No GCPprojRef return by GDALJP2metadata
1284  std::string gcpProjectionKey = "UNKNOWN";
1285  itk::EncapsulateMetaData<std::string>(dict, MetaDataKey::GCPProjectionKey, gcpProjectionKey);
1286 
1287  int nbGCPs = lJP2MetadataReader.GetGCPCount();
1288  otbMsgDevMacro(<< "JPEG2000 file has "<< nbGCPs << " GCPs!");
1289  itk::EncapsulateMetaData<int>(dict, MetaDataKey::GCPCountKey, nbGCPs);
1290 
1291  std::vector<GDAL_GCP> gcps = lJP2MetadataReader.GetGCPs();
1292 
1293  std::string key;
1294  for (int cpt = 0; cpt < nbGCPs; ++cpt)
1295  {
1296  GDAL_GCP currentGCP = gcps[cpt];
1297  OTB_GCP pOtbGCP;
1298  pOtbGCP.m_Id = std::string(currentGCP.pszId);
1299  pOtbGCP.m_Info = std::string(currentGCP.pszInfo);
1300  pOtbGCP.m_GCPRow = currentGCP.dfGCPLine;
1301  pOtbGCP.m_GCPCol = currentGCP.dfGCPPixel;
1302  pOtbGCP.m_GCPX = currentGCP.dfGCPX;
1303  pOtbGCP.m_GCPY = currentGCP.dfGCPY;
1304  pOtbGCP.m_GCPZ = currentGCP.dfGCPZ;
1305 
1306  // Complete the key with the GCP number : GCP_i
1307  std::ostringstream lStream;
1308  lStream << MetaDataKey::GCPParametersKey << cpt;
1309  key = lStream.str();
1310 
1311  itk::EncapsulateMetaData<OTB_GCP>(dict, key, pOtbGCP);
1312  }
1313  }
1314 
1315  /* GMLMetadata*/
1316  char** papszGMLMetadata;
1317  papszGMLMetadata = lJP2MetadataReader.GetGMLMetadata();
1318  if (CSLCount(papszGMLMetadata) > 0)
1319  {
1320  otbMsgDevMacro(<< "JPEG2000 file has GMLMetadata!");
1321  std::string key;
1322 
1323  for (int cpt = 0; papszGMLMetadata[cpt] != NULL; ++cpt)
1324  {
1325  std::ostringstream lStream;
1326  lStream << MetaDataKey::MetadataKey << cpt;
1327  key = lStream.str();
1328 
1329  itk::EncapsulateMetaData<std::string>(dict, key, static_cast<std::string> (papszGMLMetadata[cpt]));
1330  otbMsgDevMacro( << static_cast<std::string>(papszGMLMetadata[cpt]));
1331  }
1332  }
1333 
1334 
1335  /* ProjectionRef*/
1336  if (lJP2MetadataReader.GetProjectionRef() && !std::string(lJP2MetadataReader.GetProjectionRef()).empty() )
1337  {
1338  OGRSpatialReferenceH pSR = OSRNewSpatialReference(NULL);
1339 
1340  const char * pszProjection = NULL;
1341  pszProjection = lJP2MetadataReader.GetProjectionRef();
1342 
1343  if (OSRImportFromWkt(pSR, (char **) (&pszProjection)) == OGRERR_NONE)
1344  {
1345  char * pszPrettyWkt = NULL;
1346  OSRExportToPrettyWkt(pSR, &pszPrettyWkt, FALSE);
1347 
1348  itk::EncapsulateMetaData<std::string> (dict, MetaDataKey::ProjectionRefKey,
1349  static_cast<std::string>(pszPrettyWkt));
1350 
1351  CPLFree(pszPrettyWkt);
1352  }
1353  else
1354  {
1355  itk::EncapsulateMetaData<std::string>(dict, MetaDataKey::ProjectionRefKey,
1356  static_cast<std::string>(lJP2MetadataReader.GetProjectionRef()));
1357  }
1358 
1359  if (pSR != NULL)
1360  {
1361  OSRRelease(pSR);
1362  pSR = NULL;
1363  }
1364  }
1365  else
1366  {
1367  otbMsgDevMacro( << "NO PROJECTION IN GML BOX => SENSOR MODEL " );
1368  m_Origin[0] = 0; m_Origin[1] = 0;
1369  m_Spacing[0] = 1; m_Spacing[1] = 1;
1370 
1371  lJP2MetadataReader.GetOriginFromGMLBox(m_Origin);
1372  }
1373 
1374  otbMsgDevMacro(<< "FROM GML box: " << "Origin: " << m_Origin[0] << ", " << m_Origin[1]
1375  << " | Spacing: " << m_Spacing[0] << ", " << m_Spacing[1] );
1376 
1377  }
1378  else
1379  {
1380  otbMsgDevMacro( << "JPEG2000 file has NO metadata available!");
1381  m_Origin[0] = 0;
1382  m_Origin[1] = 0;
1383  m_Spacing[0] = 1;
1384  m_Spacing[1] = 1;
1385  }
1386 
1387 
1388  // If the internal image was not open we open it.
1389  // This is usually done when the user sets the ImageIO manually
1390  if ( !m_InternalReaders.front()->m_IsOpen )
1391  {
1392  if ( !this->CanReadFile( m_FileName.c_str() ) )
1393  {
1394  itkExceptionMacro(<< "Cannot open file " << this->m_FileName << "!");
1395  return;
1396  }
1397  }
1398 
1399  // Check some internal parameters of the JPEG2000 file
1400  if ( !this->m_InternalReaders.front()->CanRead())
1401  {
1402  itkExceptionMacro(<< "Cannot read this file because some JPEG2000 parameters are not supported!");
1403  this->m_InternalReaders.front()->Clean();
1404  return;
1405  }
1406 
1407  // If one of the readers fails, clean everything
1408  if(this->m_ResolutionFactor != 0)
1409  {
1410  for(ReaderVectorType::iterator it = m_InternalReaders.begin();
1411  it != m_InternalReaders.end();
1412  ++it)
1413  {
1414  (*it)->Clean();
1415  }
1416 
1417  bool success = true;
1418 
1419  for(ReaderVectorType::iterator it = m_InternalReaders.begin();
1420  it != m_InternalReaders.end();
1421  ++it)
1422  {
1423 
1424  if ( !(*it)->Open( m_FileName.c_str(), this->m_ResolutionFactor ) )
1425  {
1426  success = false;
1427  }
1428  (*it)->m_IsOpen = true;
1429  }
1430 
1431  // If one of the readers fails, clean everything
1432  if(!success)
1433  {
1434  for(ReaderVectorType::iterator it = m_InternalReaders.begin();
1435  it != m_InternalReaders.end();
1436  ++it)
1437  {
1438  (*it)->Clean();
1439  }
1440 
1441  itkExceptionMacro(<< "Cannot open this file with this resolution!");
1442  return;
1443  }
1444  }
1445 
1446  // Encapsulate tile hints for streaming
1447  unsigned int tileHintX = m_InternalReaders.front()->m_TileWidth / static_cast<unsigned int>(vcl_pow(2.0, static_cast<int>(m_ResolutionFactor) ));
1448  unsigned int tileHintY = m_InternalReaders.front()->m_TileHeight / static_cast<unsigned int>(vcl_pow(2.0, static_cast<int>(m_ResolutionFactor) ));
1449 
1450  itk::EncapsulateMetaData<unsigned int>(dict, MetaDataKey::TileHintX, tileHintX);
1451  itk::EncapsulateMetaData<unsigned int>(dict, MetaDataKey::TileHintY, tileHintY);
1452 
1453  m_Spacing[0] *= vcl_pow(2.0, static_cast<double>(m_ResolutionFactor));
1454  m_Spacing[1] *= vcl_pow(2.0, static_cast<double>(m_ResolutionFactor));
1455 
1456  // If we have some spacing information we use it
1457  // could be needed for other j2k image but not for pleiades
1458  // if ( (m_InternalReaders.front()->m_XResolution.front() > 0) && (m_InternalReaders.front()->m_YResolution.front() > 0) )
1459  // {
1460  // // We check previously that the X and Y resolution is equal between the components
1461  // m_Spacing[0] *= m_InternalReaders.front()->m_XResolution[0];
1462  // m_Spacing[1] *= m_InternalReaders.front()->m_YResolution[0];
1463  // }
1464 
1465  m_Dimensions[0] = m_InternalReaders.front()->m_Width;
1466  m_Dimensions[1] = m_InternalReaders.front()->m_Height;
1467 
1468  this->SetNumberOfDimensions(2);
1469 
1470  if (m_Dimensions[0] == 0 || m_Dimensions[1] == 0)
1471  {
1472  itkExceptionMacro(<< "Image size is null.");
1473  }
1474 
1475  this->SetNumberOfComponents(m_InternalReaders.front()->m_NbOfComponent);
1476 
1477  // Automatically set the Type to Binary for JPEG2000 data
1478  this->SetFileTypeToBinary();
1479 
1480  // We check previously that these values are equal between all components
1481  unsigned int precision = m_InternalReaders.front()->m_Precision[0];
1482  int isSigned = m_InternalReaders.front()->m_Signed[0];
1483 
1484  if (precision <= 8)
1485  {
1486  m_BytePerPixel = 1;
1487  if (isSigned)
1488  {
1490  }
1491  else
1492  {
1494  }
1495  }
1496  else if (precision <= 16)
1497  {
1498  m_BytePerPixel = 2;
1499  if (isSigned)
1500  {
1502  }
1503  else
1504  {
1506  }
1507  }
1508  else
1509  {
1510  m_BytePerPixel = 4;
1511  if (isSigned)
1512  {
1514  }
1515  else
1516  {
1518  }
1519  }
1520 
1521  if (this->GetNumberOfComponents() == 1)
1522  {
1523  this->SetPixelType(SCALAR);
1524  }
1525  else
1526  {
1527  this->SetPixelType(VECTOR);
1528  }
1529 
1530  this->ConfigureCache();
1531 
1532  otbMsgDebugMacro(<< "==========================");
1533  otbMsgDebugMacro(<< "ReadImageInformation: ");
1534  otbMsgDebugMacro(<< "Tile size (WxH): " << m_InternalReaders.front()->m_TileWidth << " x "
1535  << m_InternalReaders.front()->m_TileHeight);
1536  otbMsgDebugMacro(<< "Number of tiles (Xdim x Ydim) : " << m_InternalReaders.front()->m_XNbOfTile
1537  << " x " << m_InternalReaders.front()->m_YNbOfTile);
1538  otbMsgDebugMacro(<< "Precision: " << precision);
1539  otbMsgDebugMacro(<< "Signed: " << isSigned);
1540  otbMsgDebugMacro(<< "Number of octet per value: " << m_BytePerPixel);
1541  otbMsgDebugMacro(<< "==========================");
1542 
1543  otbMsgDebugMacro(<< "Driver to read: JPEG2000");
1544  otbMsgDebugMacro(<< " Read file : " << m_FileName);
1545  otbMsgDebugMacro(<< " Size : " << m_Dimensions[0] << "," << m_Dimensions[1]);
1546  otbMsgDebugMacro(<< " ComponentType : " << this->GetComponentType());
1547  otbMsgDebugMacro(<< " NumberOfComponents : " << this->GetNumberOfComponents());
1548  otbMsgDebugMacro(<< " ComponentSize : " << this->GetComponentSize());
1549  otbMsgDebugMacro(<< " GetPixelSize : " << this->GetPixelSize());
1550 }
1551 
1552 // Compute the tile index list from the GetRegion
1553 std::vector<unsigned int> JPEG2000ImageIO::ComputeTileList()
1554 {
1555  std::vector<unsigned int> tileVector;
1556 
1557  // Get nb. of lines and columns of the region to decode
1558  unsigned int startX = this->GetIORegion().GetIndex()[0];
1559  unsigned int endX = this->GetIORegion().GetIndex()[0] + this->GetIORegion().GetSize()[0];
1560  unsigned int startY = this->GetIORegion().GetIndex()[1];
1561  unsigned int endY = this->GetIORegion().GetIndex()[1] + this->GetIORegion().GetSize()[1];
1562 
1563  // Compute index of tile recover by the decoded area
1564  unsigned int tile_size_x = m_InternalReaders.front()->m_TileWidth;
1565  unsigned int tile_size_y = m_InternalReaders.front()->m_TileHeight;
1566  unsigned int width = m_Dimensions[0];
1567  unsigned int height = m_Dimensions[1];
1568  unsigned int nbOfTileX = m_InternalReaders.front()->m_XNbOfTile;
1569  unsigned int nbOfTileY = m_InternalReaders.front()->m_YNbOfTile;
1570 
1571  unsigned int tilePosX0, tilePosX1;
1572  unsigned int tilePosY0, tilePosY1;
1573 
1574  for (unsigned int itTileY = 0; itTileY < nbOfTileY; itTileY++)
1575  {
1576  tilePosY0 = uint_ceildivpow2( itTileY*tile_size_y, m_ResolutionFactor );
1577  tilePosY1 = std::min( uint_ceildivpow2( (itTileY+1)*tile_size_y, m_ResolutionFactor ), height );
1578 
1579  for (unsigned int itTileX = 0; itTileX < nbOfTileX; itTileX++)
1580  {
1581  tilePosX0 = uint_ceildivpow2( itTileX*tile_size_x, m_ResolutionFactor );
1582  tilePosX1 = std::min( uint_ceildivpow2( (itTileX+1)*tile_size_x, m_ResolutionFactor ), width);
1583 
1584  if ( (tilePosX1 - tilePosX0) && (tilePosY1 - tilePosY0) &&
1585  (tilePosX1 > startX) && (tilePosX0 < endX ) &&
1586  (tilePosY1 > startY) && (tilePosY0 < endY ) )
1587  tileVector.push_back(itTileX + itTileY * nbOfTileX);
1588 
1589  }
1590  }
1591 
1592  return tileVector;
1593 }
1594 
1598 void ComputeOffsets( opj_image_t * currentTile,
1599  const itk::ImageIORegion & ioRegion,
1600  unsigned int &l_width_src, // Width of the input pixel in nb of pixel
1601  unsigned int &l_height_dest, // Height of the area where write in nb of pixel
1602  unsigned int &l_width_dest, // Width of the area where write in nb of pixel
1603  unsigned int &l_start_offset_dest, // Offset where begin to write the area in the otb buffer in nb of pixel
1604  unsigned int &l_start_offset_src // Offset where begin to read the data in the openjpeg decoded data in nb of pixel
1605  )
1606 {
1607  // Characteristics of the input buffer from openpjeg
1608  unsigned int l_x0_src = int_ceildivpow2(currentTile->x0, currentTile->comps->factor);
1609  unsigned int l_y0_src = int_ceildivpow2(currentTile->y0, currentTile->comps->factor);
1610  unsigned int l_x1_src = int_ceildivpow2(currentTile->x1, currentTile->comps->factor);
1611  unsigned int l_y1_src = int_ceildivpow2(currentTile->y1, currentTile->comps->factor);
1612 
1613  // Size of input buffer from openjpeg
1614  l_width_src = l_x1_src - l_x0_src;
1615  unsigned int l_height_src = l_y1_src - l_y0_src;
1616 
1617  // Characteristics of the otb region
1618  unsigned int l_x0_dest = ioRegion.GetIndex()[0];
1619  unsigned int l_x1_dest = ioRegion.GetIndex()[0] + ioRegion.GetSize()[0];
1620  unsigned int l_y0_dest = ioRegion.GetIndex()[1];
1621  unsigned int l_y1_dest = ioRegion.GetIndex()[1] + ioRegion.GetSize()[1];
1622 
1623  unsigned int l_start_x_dest, l_start_y_dest;
1624  unsigned int l_offset_x0_src, l_offset_y0_src;
1625 
1626  /*-----*/
1627  /* Compute the origin (l_offset_x0_src, l_offset_y0_src )
1628  * of the input buffer (decoded tile) which will be move
1629  * in the output buffer.
1630  * Compute the area of the output buffer (l_start_x_dest,
1631  * l_start_y_dest, l_width_dest, l_height_dest) which will be modified
1632  * by this input area.
1633  */
1634 
1635  if (l_x0_dest < l_x0_src)
1636  {
1637  l_start_x_dest = l_x0_src - l_x0_dest;
1638  l_offset_x0_src = 0;
1639 
1640  if (l_x1_dest >= l_x1_src)
1641  {
1642  l_width_dest = l_width_src;
1643  }
1644  else
1645  {
1646  l_width_dest = l_x1_dest - l_x0_src;
1647  }
1648  }
1649  else
1650  {
1651  l_start_x_dest = 0;
1652  l_offset_x0_src = l_x0_dest - l_x0_src;
1653 
1654  if (l_x1_dest >= l_x1_src)
1655  {
1656  l_width_dest = l_width_src - l_offset_x0_src;
1657  }
1658  else
1659  {
1660  l_width_dest = l_x1_dest - l_x0_dest;
1661  }
1662  }
1663 
1664  if (l_y0_dest < l_y0_src)
1665  {
1666  l_start_y_dest = l_y0_src - l_y0_dest;
1667  l_offset_y0_src = 0;
1668 
1669  if (l_y1_dest >= l_y1_src)
1670  {
1671  l_height_dest = l_height_src;
1672  }
1673  else
1674  {
1675  l_height_dest = l_y1_dest - l_y0_src;
1676  }
1677  }
1678  else
1679  {
1680  l_start_y_dest = 0;
1681  l_offset_y0_src = l_y0_dest - l_y0_src;
1682 
1683  if (l_y1_dest >= l_y1_src)
1684  {
1685  l_height_dest = l_height_src - l_offset_y0_src;
1686  }
1687  else
1688  {
1689  l_height_dest = l_y1_dest - l_y0_dest;
1690  }
1691  }
1692  /*-----*/
1693 
1694  /* Compute the input buffer offset */
1695  l_start_offset_src = l_offset_x0_src + l_offset_y0_src * l_width_src;
1696 
1697  /* Compute the output buffer offset */
1698  l_start_offset_dest = l_start_x_dest + l_start_y_dest * (l_x1_dest - l_x0_dest);
1699 
1700  /*
1701  std::cout << "SRC coordinates: l_start_x_src= " << l_x0_src << ", l_start_y_src= " << l_y0_src << ", l_width_src= "
1702  << l_width_src << ", l_height_src= " << l_height_src << std::endl;
1703  std::cout << "SRC tile offset: " << l_offset_x0_src << ", " << l_offset_y0_src << std::endl;
1704  std::cout << "SRC buffer offset: " << l_start_offset_src << std::endl;
1705 
1706  std::cout << "DEST coordinates: l_start_x_dest= " << l_start_x_dest << ", l_start_y_dest= " << l_start_y_dest
1707  << ", l_width_dest= " << l_width_dest << ", l_height_dest= " << l_height_dest << std::endl;
1708  std::cout << "DEST start offset: " << l_start_offset_dest << std::endl;
1709  */
1710 }
1711 
1712 // Not yet implemented
1713 bool JPEG2000ImageIO::CanWriteFile(const char* /*filename*/)
1714 {
1715  return false;
1716 }
1717 
1718 // Not yet implemented
1719 void JPEG2000ImageIO::Write(const void* /*buffer*/)
1720 {
1721 
1722 }
1723 
1725 {
1726  if (m_FileName == "")
1727  {
1728  itkExceptionMacro(<< "A FileName must be specified.");
1729  }
1730  if (CanWriteFile(m_FileName.c_str()) == false)
1731  {
1732  itkExceptionMacro(<< "The file " << m_FileName.c_str() << " is not defined as a JPEG2000 file");
1733  }
1734 
1735  otbMsgDebugMacro(<< "Driver to write: JPEG2000");
1736  otbMsgDebugMacro(<< " Write file : " << m_FileName);
1737  otbMsgDebugMacro(<< " Size : " << m_Dimensions[0] << "," << m_Dimensions[1]);
1738  otbMsgDebugMacro(<< " ComponentType : " << this->GetComponentType());
1739  otbMsgDebugMacro(<< " NumberOfComponents : " << this->GetNumberOfComponents());
1740  otbMsgDebugMacro(<< " ComponentSize : " << this->GetComponentSize());
1741  otbMsgDebugMacro(<< " GetPixelSize : " << this->GetPixelSize());
1742 
1743 }
1744 
1745 } // end namespace otb

Generated at Sat Mar 8 2014 16:02:45 for Orfeo Toolbox with doxygen 1.8.3.1