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

Generated at Sun May 19 2013 00:33:01 for Orfeo Toolbox with doxygen 1.8.3.1