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 
857 bool JPEG2000ImageIO::GetAvailableResolutions(std::vector<unsigned int>& res)
858 {
859  res = this->m_InternalReaders[0]->GetAvailableResolutions();
860 
861  if (res.empty())
862  return false;
863 
864  return true;
865 }
866 
867 
868 // Read image
869 void JPEG2000ImageIO::Read(void* buffer)
870 {
871  itk::TimeProbe chrono;
872  chrono.Start();
873 
874  // Check if conversion succeed
875  if (buffer == NULL)
876  {
877  itkExceptionMacro(<< "JPEG2000ImageIO : Bad alloc");
878  return;
879  }
880 
881  // Re-open the file if it was closed
882  bool open = true;
883  for(ReaderVectorType::iterator it = m_InternalReaders.begin();
884  it != m_InternalReaders.end();
885  ++it)
886  {
887  open = (*it)->m_IsOpen && open;
888  }
889 
890  if ( !open )
891  {
892  if ( !this->CanReadFile( m_FileName.c_str() ) )
893  {
894  itkExceptionMacro(<< "Cannot open file " << this->m_FileName << "!");
895  return;
896  }
897  }
898 
899  if (m_ResolutionFactor >= this->m_InternalReaders[0]->m_AvailableResolutions.size())
900  {
901  itkExceptionMacro(<< "Resolution not available in the file!");
902  return;
903  }
904 
905  std::vector<unsigned int> tileList = this->ComputeTileList();
906  if (tileList.empty())
907  {
908  for(ReaderVectorType::iterator it = m_InternalReaders.begin();
909  it != m_InternalReaders.end();
910  ++it)
911  {
912  (*it)->Clean();
913  }
914  itkExceptionMacro(<< " IORegion does not correspond to any tile!");
915  }
916 
917  // Here we sort between tiles from cache and tiles to read
918  std::vector<JPEG2000TileCache::CachedTileType> cachedTiles;
919  std::vector<JPEG2000TileCache::CachedTileType> toReadTiles;
920 
921  for (std::vector<unsigned int>::iterator itTile = tileList.begin(); itTile < tileList.end(); ++itTile)
922  {
923  opj_image_t * currentImage = m_TileCache->GetTile(*itTile);
924 
925  JPEG2000TileCache::CachedTileType currentTile = std::make_pair((*itTile), currentImage);
926 
927  if(!currentImage)
928  {
929  toReadTiles.push_back(currentTile);
930  }
931  else
932  {
933  cachedTiles.push_back(currentTile);
934  }
935  }
936 
937  // First, load tiles from cache
938  for (std::vector<JPEG2000TileCache::CachedTileType>::iterator itTile = cachedTiles.begin(); itTile < cachedTiles.end(); ++itTile)
939  {
940  this->LoadTileData(buffer, itTile->second);
941  }
942 
943 
944  int nbTileToRemove = static_cast<int>(toReadTiles.size())
946  if ( nbTileToRemove <= 0 )
947  nbTileToRemove = 0;
948 
949  // Remove from cache as many tiles that will be read in this step
950  for (int itTileR = 0; itTileR < nbTileToRemove; ++itTileR)
951  {
953  }
954 
955  // Decode all tiles not in cache in parallel
956  if(!toReadTiles.empty())
957  {
958  unsigned int nbThreads = itk::MultiThreader::GetGlobalDefaultNumberOfThreads();
959  if (nbThreads > toReadTiles.size())
960  {
961  nbThreads = toReadTiles.size();
962  }
963  this->GetMultiThreader()->SetNumberOfThreads(nbThreads);
964 
965  // Set up the multithreaded processing
966  ThreadStruct str;
968  str.Tiles = &toReadTiles;
969 
970  // Set-up multi-threader
971  this->GetMultiThreader()->SetSingleMethod(this->ThreaderCallback, &str);
972 
973  // multithread the execution
975  }
976 
977  // Load tiles that have been read
978  for (std::vector<JPEG2000TileCache::CachedTileType>::iterator itTile = toReadTiles.begin(); itTile < toReadTiles.end(); ++itTile)
979  {
980  this->LoadTileData(buffer, itTile->second);
981  }
982 
983 
984  // Now, do cache book-keeping if necessary
985  if (m_TileCache->GetCacheSizeInTiles() != 0)
986  {
987  for (std::vector<JPEG2000TileCache::CachedTileType>::iterator itTile = toReadTiles.begin(); itTile < toReadTiles.end(); ++itTile)
988  {
989  m_TileCache->AddTile(itTile->first, itTile->second);
990  }
991  }
992 
993  chrono.Stop();
994  otbMsgDevMacro( << "JPEG2000ImageIO::Read took " << chrono.GetTotal() << " sec");
995 
996  for(ReaderVectorType::iterator it = m_InternalReaders.begin();
997  it != m_InternalReaders.end();
998  ++it)
999  {
1000  (*it)->Clean();
1001  }
1002 }
1003 
1004 void JPEG2000ImageIO::LoadTileData(void * buffer, void * tile)
1005 {
1006  opj_image_t * currentTile = static_cast<opj_image_t *>(tile);
1007 
1008  if(!currentTile)
1009  {
1010  itkExceptionMacro(<<"Tile needed but not loaded.");
1011  }
1012 
1013  // Get nb. of lines and columns of the region to read
1014  int lNbLines = this->GetIORegion().GetSize()[1];
1015  int lNbColumns = this->GetIORegion().GetSize()[0];
1016  int lFirstLine = this->GetIORegion().GetIndex()[1]; // [1... ]
1017  int lFirstColumn = this->GetIORegion().GetIndex()[0]; // [1... ]
1018  unsigned int lWidthSrc; // Width of the input pixel in nb of pixel
1019  unsigned int lHeightDest; // Height of the area where write in nb of pixel
1020  unsigned int lWidthDest; // Width of the area where write in nb of pixel
1021  unsigned int lStartOffsetPxlDest; // Offset where begin to write the area in the otb buffer in nb of pixel
1022  unsigned int lStartOffsetPxlSrc; // Offset where begin to write the area in the otb buffer in nb of pixel
1023 
1024  ComputeOffsets(currentTile, this->GetIORegion(), lWidthSrc, lHeightDest, lWidthDest, lStartOffsetPxlDest, lStartOffsetPxlSrc);
1025 
1026  switch (this->GetComponentType())
1027  {
1028  case CHAR:
1029  {
1030  char *p = static_cast<char *> (buffer);
1031  for (unsigned int j = 0; j < lHeightDest; ++j)
1032  {
1033  char* current_dst_line = p + (lStartOffsetPxlDest + j * lNbColumns) * this->m_NumberOfComponents;
1034 
1035  for (unsigned int k = 0; k < lWidthDest; ++k)
1036  {
1037  for (unsigned int itComp = 0; itComp < this->m_NumberOfComponents; itComp++)
1038  {
1039  OPJ_INT32* data = currentTile->comps[itComp].data;
1040  *(current_dst_line++) = static_cast<char> (data[lStartOffsetPxlSrc + k + j * lWidthSrc]);
1041  }
1042  }
1043  }
1044  }
1045  break;
1046  case UCHAR:
1047  {
1048  unsigned char *p = static_cast<unsigned char *> (buffer);
1049  for (unsigned int j = 0; j < lHeightDest; ++j)
1050  {
1051  unsigned char* current_dst_line = p + (lStartOffsetPxlDest + j * lNbColumns) * this->m_NumberOfComponents;
1052 
1053  for (unsigned int k = 0; k < lWidthDest; ++k)
1054  {
1055  for (unsigned int itComp = 0; itComp < this->m_NumberOfComponents; itComp++)
1056  {
1057  OPJ_INT32* data = currentTile->comps[itComp].data;
1058  unsigned char component_val = data[lStartOffsetPxlSrc + k + j * lWidthSrc] & 0xff;
1059  *(current_dst_line++) = static_cast<unsigned char> (component_val);
1060  }
1061  }
1062  }
1063  }
1064  break;
1065  case SHORT:
1066  {
1067  short *p = static_cast<short *> (buffer);
1068  for (unsigned int j = 0; j < lHeightDest; ++j)
1069  {
1070  short* current_dst_line = p + (lStartOffsetPxlDest + j * lNbColumns) * this->m_NumberOfComponents;
1071 
1072  for (unsigned int k = 0; k < lWidthDest; ++k)
1073  {
1074  for (unsigned int itComp = 0; itComp < this->m_NumberOfComponents; itComp++)
1075  {
1076  OPJ_INT32* data = currentTile->comps[itComp].data;
1077  *(current_dst_line++) = static_cast<short> (data[lStartOffsetPxlSrc + k + j * lWidthSrc]);
1078  }
1079  }
1080  }
1081  }
1082  break;
1083  case USHORT:
1084  {
1085  unsigned short *p = static_cast<unsigned short *> (buffer);
1086  for (unsigned int j = 0; j < lHeightDest; ++j)
1087  {
1088  unsigned short* current_dst_line = p + (lStartOffsetPxlDest + j * lNbColumns) * this->m_NumberOfComponents;
1089 
1090  for (unsigned int k = 0; k < lWidthDest; ++k)
1091  {
1092  for (unsigned int itComp = 0; itComp < this->m_NumberOfComponents; itComp++)
1093  {
1094  OPJ_INT32* data = currentTile->comps[itComp].data;
1095  *(current_dst_line++) = static_cast<unsigned short> (data[lStartOffsetPxlSrc + k + j * lWidthSrc] & 0xffff);
1096  }
1097  }
1098  }
1099  }
1100  break;
1101  case INT:
1102  case UINT:
1103  default:
1104  itkGenericExceptionMacro(<< "This data type is not handled");
1105  break;
1106  }
1107 }
1108 
1110 {
1111  ThreadStruct *str;
1112  unsigned int total, threadCount;
1113  int threadId;
1114 
1115  threadId = ((itk::MultiThreader::ThreadInfoStruct *)(arg))->ThreadID;
1116  threadCount = ((itk::MultiThreader::ThreadInfoStruct *)(arg))->NumberOfThreads;
1117 
1118  str = (ThreadStruct *)(((itk::MultiThreader::ThreadInfoStruct *)(arg))->UserData);
1119 
1120  // Retrieve data
1121  std::vector<JPEG2000InternalReader *> readers = str->Readers;
1122  std::vector<JPEG2000TileCache::CachedTileType> * tiles = str->Tiles;
1123 
1124  total = std::min((unsigned int)tiles->size(), threadCount);
1125 
1126  if(total == 0)
1127  {
1128  return ITK_THREAD_RETURN_VALUE;
1129  }
1130 
1131 
1132  unsigned int tilesPerThread = tiles->size()/total;
1133  if(tilesPerThread == 0)
1134  {
1135  tilesPerThread = 1;
1136  }
1137 
1138  for(unsigned int i = threadId * tilesPerThread;
1139  i < tilesPerThread * (threadId+1);
1140  ++i)
1141  {
1142  tiles->at(i).second = readers.at(threadId)->DecodeTile(tiles->at(i).first);
1143 
1144  // Check if tile is valid
1145  if(!tiles->at(i).second)
1146  {
1147  readers.at(threadId)->Clean();
1148  itkGenericExceptionMacro(" otbopenjpeg failed to decode the desired tile "<<tiles->at(i).first << "!");
1149  }
1150  otbMsgDevMacro(<< " Tile " << tiles->at(i).first << " decoded by thread "<<threadId);
1151  }
1152 
1153  unsigned int lastTile = threadCount*tilesPerThread + threadId;
1154 
1155  // TODO: check this last part
1156 
1157  if(lastTile < tiles->size())
1158  {
1159  tiles->at(lastTile).second = readers.at(threadId)->DecodeTile(tiles->at(lastTile).first);
1160 
1161  if(!tiles->at(lastTile).second)
1162  {
1163  readers.at(threadId)->Clean();
1164  itkGenericExceptionMacro(" otbopenjpeg failed to decode the desired tile "<<tiles->at(lastTile).first << "!");
1165  }
1166  otbMsgDevMacro(<<" Tile " << tiles->at(lastTile).first << " decoded by thread "<<threadId);
1167  }
1168 
1169  return ITK_THREAD_RETURN_VALUE;
1170 }
1171 
1172 
1174 {
1175  // Extract metadata
1176  // In case the metadata are not set, the function silently returns, doing nothing
1177  itk::ExposeMetaData<unsigned int>(this->GetMetaDataDictionary(),
1180 
1181  itk::ExposeMetaData<unsigned int>(this->GetMetaDataDictionary(),
1184 
1185  // Now initialize the itk dictionary
1187 
1188  JPEG2000MetadataReader lJP2MetadataReader(m_FileName.c_str());
1189 
1190  if (lJP2MetadataReader.m_MetadataIsRead)
1191  {
1192  otbMsgDevMacro(<<"JPEG2000 file has metadata available!");
1193 
1194  /* GEOTRANSFORM */
1195  if (lJP2MetadataReader.HaveGeoTransform())
1196  {
1197  otbMsgDevMacro(<< "JPEG2000 file has a geotransform!");
1198  std::vector<double> geoTransform = lJP2MetadataReader.GetGeoTransform();
1199 
1200  itk::EncapsulateMetaData<MetaDataKey::VectorType>(dict, MetaDataKey::GeoTransformKey, geoTransform);
1201 
1202  /*std::cout << "from gml box, geotransform: ";
1203  for (int i = 0; i < 6; i++)
1204  {
1205  std::cout << geoTransform[i] << ", ";
1206  }
1207  std::cout << std::endl; */
1208 
1209  // Retrieve origin and spacing from the geo transform
1210  m_Origin[0] = geoTransform[0];
1211  m_Origin[1] = geoTransform[3];
1212  m_Spacing[0] = geoTransform[1];
1213  m_Spacing[1] = geoTransform[5];
1214 
1215  if ( m_Spacing[0]== 0 || m_Spacing[1] == 0)
1216  {
1217  // Manage case where axis are not standard
1218  if (geoTransform[2] != 0 && geoTransform[4] != 0 )
1219  {
1220  m_Spacing[0] = geoTransform[2];
1221  m_Spacing[1] = geoTransform[4];
1222  }
1223  else
1224  {
1225  otbWarningMacro(<< "JPEG2000 file has an incorrect geotransform (spacing = 0)!");
1226  m_Spacing[0] = 1;
1227  m_Spacing[1] = 1;
1228  }
1229  }
1230  }
1231 
1232  /* GCPs */
1233  if (lJP2MetadataReader.GetGCPCount() > 0)
1234  {
1235  // No GCPprojRef return by GDALJP2metadata
1236  std::string gcpProjectionKey = "UNKNOWN";
1237  itk::EncapsulateMetaData<std::string>(dict, MetaDataKey::GCPProjectionKey, gcpProjectionKey);
1238 
1239  int nbGCPs = lJP2MetadataReader.GetGCPCount();
1240  otbMsgDevMacro(<< "JPEG2000 file has "<< nbGCPs << " GCPs!");
1241  itk::EncapsulateMetaData<int>(dict, MetaDataKey::GCPCountKey, nbGCPs);
1242 
1243  std::vector<GDAL_GCP> gcps = lJP2MetadataReader.GetGCPs();
1244 
1245  std::string key;
1246  for (int cpt = 0; cpt < nbGCPs; ++cpt)
1247  {
1248  GDAL_GCP currentGCP = gcps[cpt];
1249  OTB_GCP pOtbGCP;
1250  pOtbGCP.m_Id = std::string(currentGCP.pszId);
1251  pOtbGCP.m_Info = std::string(currentGCP.pszInfo);
1252  pOtbGCP.m_GCPRow = currentGCP.dfGCPLine;
1253  pOtbGCP.m_GCPCol = currentGCP.dfGCPPixel;
1254  pOtbGCP.m_GCPX = currentGCP.dfGCPX;
1255  pOtbGCP.m_GCPY = currentGCP.dfGCPY;
1256  pOtbGCP.m_GCPZ = currentGCP.dfGCPZ;
1257 
1258  // Complete the key with the GCP number : GCP_i
1259  std::ostringstream lStream;
1260  lStream << MetaDataKey::GCPParametersKey << cpt;
1261  key = lStream.str();
1262 
1263  itk::EncapsulateMetaData<OTB_GCP>(dict, key, pOtbGCP);
1264  }
1265  }
1266 
1267  /* GMLMetadata*/
1268  char** papszGMLMetadata;
1269  papszGMLMetadata = lJP2MetadataReader.GetGMLMetadata();
1270  if (CSLCount(papszGMLMetadata) > 0)
1271  {
1272  otbMsgDevMacro(<< "JPEG2000 file has GMLMetadata!");
1273  std::string key;
1274 
1275  for (int cpt = 0; papszGMLMetadata[cpt] != NULL; ++cpt)
1276  {
1277  std::ostringstream lStream;
1278  lStream << MetaDataKey::MetadataKey << cpt;
1279  key = lStream.str();
1280 
1281  itk::EncapsulateMetaData<std::string>(dict, key, static_cast<std::string> (papszGMLMetadata[cpt]));
1282  otbMsgDevMacro( << static_cast<std::string>(papszGMLMetadata[cpt]));
1283  }
1284  }
1285 
1286 
1287  /* ProjectionRef*/
1288  if (lJP2MetadataReader.GetProjectionRef() && !std::string(lJP2MetadataReader.GetProjectionRef()).empty() )
1289  {
1290  OGRSpatialReferenceH pSR = OSRNewSpatialReference(NULL);
1291 
1292  const char * pszProjection = NULL;
1293  pszProjection = lJP2MetadataReader.GetProjectionRef();
1294 
1295  if (OSRImportFromWkt(pSR, (char **) (&pszProjection)) == OGRERR_NONE)
1296  {
1297  char * pszPrettyWkt = NULL;
1298  OSRExportToPrettyWkt(pSR, &pszPrettyWkt, FALSE);
1299 
1300  itk::EncapsulateMetaData<std::string> (dict, MetaDataKey::ProjectionRefKey,
1301  static_cast<std::string>(pszPrettyWkt));
1302 
1303  CPLFree(pszPrettyWkt);
1304  }
1305  else
1306  {
1307  itk::EncapsulateMetaData<std::string>(dict, MetaDataKey::ProjectionRefKey,
1308  static_cast<std::string>(lJP2MetadataReader.GetProjectionRef()));
1309  }
1310 
1311  if (pSR != NULL)
1312  {
1313  OSRRelease(pSR);
1314  pSR = NULL;
1315  }
1316  }
1317  else
1318  {
1319  otbMsgDevMacro( << "NO PROJECTION IN GML BOX => SENSOR MODEL " );
1320  m_Origin[0] = 0; m_Origin[1] = 0;
1321  m_Spacing[0] = 1; m_Spacing[1] = 1;
1322 
1323  lJP2MetadataReader.GetOriginFromGMLBox(m_Origin);
1324  }
1325 
1326  otbMsgDevMacro(<< "FROM GML box: " << "Origin: " << m_Origin[0] << ", " << m_Origin[1]
1327  << " | Spacing: " << m_Spacing[0] << ", " << m_Spacing[1] );
1328 
1329  }
1330  else
1331  {
1332  otbMsgDevMacro( << "JPEG2000 file has NO metadata available!");
1333  m_Origin[0] = 0;
1334  m_Origin[1] = 0;
1335  m_Spacing[0] = 1;
1336  m_Spacing[1] = 1;
1337  }
1338 
1339 
1340  // If the internal image was not open we open it.
1341  // This is usually done when the user sets the ImageIO manually
1342  if ( !m_InternalReaders.front()->m_IsOpen )
1343  {
1344  if ( !this->CanReadFile( m_FileName.c_str() ) )
1345  {
1346  itkExceptionMacro(<< "Cannot open file " << this->m_FileName << "!");
1347  return;
1348  }
1349  }
1350 
1351  // Check some internal parameters of the JPEG2000 file
1352  if ( !this->m_InternalReaders.front()->CanRead())
1353  {
1354  itkExceptionMacro(<< "Cannot read this file because some JPEG2000 parameters are not supported!");
1355  this->m_InternalReaders.front()->Clean();
1356  return;
1357  }
1358 
1359  // If one of the readers fails, clean everything
1360  if(this->m_ResolutionFactor != 0)
1361  {
1362  for(ReaderVectorType::iterator it = m_InternalReaders.begin();
1363  it != m_InternalReaders.end();
1364  ++it)
1365  {
1366  (*it)->Clean();
1367  }
1368 
1369  bool success = true;
1370 
1371  for(ReaderVectorType::iterator it = m_InternalReaders.begin();
1372  it != m_InternalReaders.end();
1373  ++it)
1374  {
1375 
1376  if ( !(*it)->Open( m_FileName.c_str(), this->m_ResolutionFactor ) )
1377  {
1378  success = false;
1379  }
1380  (*it)->m_IsOpen = true;
1381  }
1382 
1383  // If one of the readers fails, clean everything
1384  if(!success)
1385  {
1386  for(ReaderVectorType::iterator it = m_InternalReaders.begin();
1387  it != m_InternalReaders.end();
1388  ++it)
1389  {
1390  (*it)->Clean();
1391  }
1392 
1393  itkExceptionMacro(<< "Cannot open this file with this resolution!");
1394  return;
1395  }
1396  }
1397 
1398  // Encapsulate tile hints for streaming
1399  unsigned int tileHintX = m_InternalReaders.front()->m_TileWidth / static_cast<unsigned int>(vcl_pow(2.0, static_cast<int>(m_ResolutionFactor) ));
1400  unsigned int tileHintY = m_InternalReaders.front()->m_TileHeight / static_cast<unsigned int>(vcl_pow(2.0, static_cast<int>(m_ResolutionFactor) ));
1401 
1402  itk::EncapsulateMetaData<unsigned int>(dict, MetaDataKey::TileHintX, tileHintX);
1403  itk::EncapsulateMetaData<unsigned int>(dict, MetaDataKey::TileHintY, tileHintY);
1404 
1405  m_Spacing[0] *= vcl_pow(2.0, static_cast<double>(m_ResolutionFactor));
1406  m_Spacing[1] *= vcl_pow(2.0, static_cast<double>(m_ResolutionFactor));
1407 
1408  // If we have some spacing information we use it
1409  // could be needed for other j2k image but not for pleiades
1410  // if ( (m_InternalReaders.front()->m_XResolution.front() > 0) && (m_InternalReaders.front()->m_YResolution.front() > 0) )
1411  // {
1412  // // We check previously that the X and Y resolution is equal between the components
1413  // m_Spacing[0] *= m_InternalReaders.front()->m_XResolution[0];
1414  // m_Spacing[1] *= m_InternalReaders.front()->m_YResolution[0];
1415  // }
1416 
1417  m_Dimensions[0] = m_InternalReaders.front()->m_Width;
1418  m_Dimensions[1] = m_InternalReaders.front()->m_Height;
1419 
1420  this->SetNumberOfDimensions(2);
1421 
1422  if (m_Dimensions[0] == 0 || m_Dimensions[1] == 0)
1423  {
1424  itkExceptionMacro(<< "Image size is null.");
1425  }
1426 
1427  this->SetNumberOfComponents(m_InternalReaders.front()->m_NbOfComponent);
1428 
1429  // Automatically set the Type to Binary for JPEG2000 data
1430  this->SetFileTypeToBinary();
1431 
1432  // We check previously that these values are equal between all components
1433  unsigned int precision = m_InternalReaders.front()->m_Precision[0];
1434  int isSigned = m_InternalReaders.front()->m_Signed[0];
1435 
1436  if (precision <= 8)
1437  {
1438  m_BytePerPixel = 1;
1439  if (isSigned)
1440  {
1442  }
1443  else
1444  {
1446  }
1447  }
1448  else if (precision <= 16)
1449  {
1450  m_BytePerPixel = 2;
1451  if (isSigned)
1452  {
1454  }
1455  else
1456  {
1458  }
1459  }
1460  else
1461  {
1462  m_BytePerPixel = 4;
1463  if (isSigned)
1464  {
1466  }
1467  else
1468  {
1470  }
1471  }
1472 
1473  if (this->GetNumberOfComponents() == 1)
1474  {
1475  this->SetPixelType(SCALAR);
1476  }
1477  else
1478  {
1479  this->SetPixelType(VECTOR);
1480  }
1481 
1482  // Initialize some parameters of the tile cache
1483  this->m_TileCache->Initialize(m_InternalReaders.front()->m_TileWidth,
1484  m_InternalReaders.front()->m_TileHeight,
1485  m_InternalReaders.front()->m_NbOfComponent,
1488 
1489  // If available set the size of the cache
1490  if (this->m_CacheSizeInByte)
1492 
1493  otbMsgDebugMacro(<< "==========================");
1494  otbMsgDebugMacro(<< "ReadImageInformation: ");
1495  otbMsgDebugMacro(<< "Tile size (WxH): " << m_InternalReaders.front()->m_TileWidth << " x "
1496  << m_InternalReaders.front()->m_TileHeight);
1497  otbMsgDebugMacro(<< "Number of tiles (Xdim x Ydim) : " << m_InternalReaders.front()->m_XNbOfTile
1498  << " x " << m_InternalReaders.front()->m_YNbOfTile);
1499  otbMsgDebugMacro(<< "Precision: " << precision);
1500  otbMsgDebugMacro(<< "Signed: " << isSigned);
1501  otbMsgDebugMacro(<< "Number of octet per value: " << m_BytePerPixel);
1502  otbMsgDebugMacro(<< "==========================");
1503 
1504  otbMsgDebugMacro(<< "Driver to read: JPEG2000");
1505  otbMsgDebugMacro(<< " Read file : " << m_FileName);
1506  otbMsgDebugMacro(<< " Size : " << m_Dimensions[0] << "," << m_Dimensions[1]);
1507  otbMsgDebugMacro(<< " ComponentType : " << this->GetComponentType());
1508  otbMsgDebugMacro(<< " NumberOfComponents : " << this->GetNumberOfComponents());
1509  otbMsgDebugMacro(<< " ComponentSize : " << this->GetComponentSize());
1510  otbMsgDebugMacro(<< " GetPixelSize : " << this->GetPixelSize());
1511 }
1512 
1513 // Compute the tile index list from the GetRegion
1514 std::vector<unsigned int> JPEG2000ImageIO::ComputeTileList()
1515 {
1516  std::vector<unsigned int> tileVector;
1517 
1518  // Get nb. of lines and columns of the region to decode
1519  unsigned int startX = this->GetIORegion().GetIndex()[0];
1520  unsigned int endX = this->GetIORegion().GetIndex()[0] + this->GetIORegion().GetSize()[0];
1521  unsigned int startY = this->GetIORegion().GetIndex()[1];
1522  unsigned int endY = this->GetIORegion().GetIndex()[1] + this->GetIORegion().GetSize()[1];
1523 
1524  // Compute index of tile recover by the decoded area
1525  unsigned int tile_size_x = m_InternalReaders.front()->m_TileWidth;
1526  unsigned int tile_size_y = m_InternalReaders.front()->m_TileHeight;
1527  unsigned int width = m_Dimensions[0];
1528  unsigned int height = m_Dimensions[1];
1529  unsigned int nbOfTileX = m_InternalReaders.front()->GetCstrInfo()->tw;
1530  unsigned int nbOfTileY = m_InternalReaders.front()->GetCstrInfo()->th;
1531 
1532  unsigned int tilePosX0, tilePosX1;
1533  unsigned int tilePosY0, tilePosY1;
1534 
1535  for (unsigned int itTileY = 0; itTileY < nbOfTileY; itTileY++)
1536  {
1537  tilePosY0 = uint_ceildivpow2( itTileY*tile_size_y, m_ResolutionFactor );
1538  tilePosY1 = std::min( uint_ceildivpow2( (itTileY+1)*tile_size_y, m_ResolutionFactor ), height );
1539 
1540  for (unsigned int itTileX = 0; itTileX < nbOfTileX; itTileX++)
1541  {
1542  tilePosX0 = uint_ceildivpow2( itTileX*tile_size_x, m_ResolutionFactor );
1543  tilePosX1 = std::min( uint_ceildivpow2( (itTileX+1)*tile_size_x, m_ResolutionFactor ), width);
1544 
1545  if ( (tilePosX1 - tilePosX0) && (tilePosY1 - tilePosY0) &&
1546  (tilePosX1 > startX) && (tilePosX0 < endX ) &&
1547  (tilePosY1 > startY) && (tilePosY0 < endY ) )
1548  tileVector.push_back(itTileX + itTileY * nbOfTileX);
1549 
1550  }
1551  }
1552 
1553  return tileVector;
1554 }
1555 
1559 void ComputeOffsets( opj_image_t * currentTile,
1560  const itk::ImageIORegion & ioRegion,
1561  unsigned int &l_width_src, // Width of the input pixel in nb of pixel
1562  unsigned int &l_height_dest, // Height of the area where write in nb of pixel
1563  unsigned int &l_width_dest, // Width of the area where write in nb of pixel
1564  unsigned int &l_start_offset_dest, // Offset where begin to write the area in the otb buffer in nb of pixel
1565  unsigned int &l_start_offset_src // Offset where begin to read the data in the openjpeg decoded data in nb of pixel
1566  )
1567 {
1568  // Characteristics of the input buffer from openpjeg
1569  unsigned int l_x0_src = int_ceildivpow2(currentTile->x0, currentTile->comps->factor);
1570  unsigned int l_y0_src = int_ceildivpow2(currentTile->y0, currentTile->comps->factor);
1571  unsigned int l_x1_src = int_ceildivpow2(currentTile->x1, currentTile->comps->factor);
1572  unsigned int l_y1_src = int_ceildivpow2(currentTile->y1, currentTile->comps->factor);
1573 
1574  // Size of input buffer from openjpeg
1575  l_width_src = l_x1_src - l_x0_src;
1576  unsigned int l_height_src = l_y1_src - l_y0_src;
1577 
1578  // Characteristics of the otb region
1579  unsigned int l_x0_dest = ioRegion.GetIndex()[0];
1580  unsigned int l_x1_dest = ioRegion.GetIndex()[0] + ioRegion.GetSize()[0];
1581  unsigned int l_y0_dest = ioRegion.GetIndex()[1];
1582  unsigned int l_y1_dest = ioRegion.GetIndex()[1] + ioRegion.GetSize()[1];
1583 
1584  unsigned int l_start_x_dest, l_start_y_dest;
1585  unsigned int l_offset_x0_src, l_offset_y0_src;
1586 
1587  /*-----*/
1588  /* Compute the origin (l_offset_x0_src, l_offset_y0_src )
1589  * of the input buffer (decoded tile) which will be move
1590  * in the output buffer.
1591  * Compute the area of the output buffer (l_start_x_dest,
1592  * l_start_y_dest, l_width_dest, l_height_dest) which will be modified
1593  * by this input area.
1594  */
1595 
1596  if (l_x0_dest < l_x0_src)
1597  {
1598  l_start_x_dest = l_x0_src - l_x0_dest;
1599  l_offset_x0_src = 0;
1600 
1601  if (l_x1_dest >= l_x1_src)
1602  {
1603  l_width_dest = l_width_src;
1604  }
1605  else
1606  {
1607  l_width_dest = l_x1_dest - l_x0_src;
1608  }
1609  }
1610  else
1611  {
1612  l_start_x_dest = 0;
1613  l_offset_x0_src = l_x0_dest - l_x0_src;
1614 
1615  if (l_x1_dest >= l_x1_src)
1616  {
1617  l_width_dest = l_width_src - l_offset_x0_src;
1618  }
1619  else
1620  {
1621  l_width_dest = l_x1_dest - l_x0_dest;
1622  }
1623  }
1624 
1625  if (l_y0_dest < l_y0_src)
1626  {
1627  l_start_y_dest = l_y0_src - l_y0_dest;
1628  l_offset_y0_src = 0;
1629 
1630  if (l_y1_dest >= l_y1_src)
1631  {
1632  l_height_dest = l_height_src;
1633  }
1634  else
1635  {
1636  l_height_dest = l_y1_dest - l_y0_src;
1637  }
1638  }
1639  else
1640  {
1641  l_start_y_dest = 0;
1642  l_offset_y0_src = l_y0_dest - l_y0_src;
1643 
1644  if (l_y1_dest >= l_y1_src)
1645  {
1646  l_height_dest = l_height_src - l_offset_y0_src;
1647  }
1648  else
1649  {
1650  l_height_dest = l_y1_dest - l_y0_dest;
1651  }
1652  }
1653  /*-----*/
1654 
1655  /* Compute the input buffer offset */
1656  l_start_offset_src = l_offset_x0_src + l_offset_y0_src * l_width_src;
1657 
1658  /* Compute the output buffer offset */
1659  l_start_offset_dest = l_start_x_dest + l_start_y_dest * (l_x1_dest - l_x0_dest);
1660 
1661  /*
1662  std::cout << "SRC coordinates: l_start_x_src= " << l_x0_src << ", l_start_y_src= " << l_y0_src << ", l_width_src= "
1663  << l_width_src << ", l_height_src= " << l_height_src << std::endl;
1664  std::cout << "SRC tile offset: " << l_offset_x0_src << ", " << l_offset_y0_src << std::endl;
1665  std::cout << "SRC buffer offset: " << l_start_offset_src << std::endl;
1666 
1667  std::cout << "DEST coordinates: l_start_x_dest= " << l_start_x_dest << ", l_start_y_dest= " << l_start_y_dest
1668  << ", l_width_dest= " << l_width_dest << ", l_height_dest= " << l_height_dest << std::endl;
1669  std::cout << "DEST start offset: " << l_start_offset_dest << std::endl;
1670  */
1671 }
1672 
1673 // Not yet implemented
1674 bool JPEG2000ImageIO::CanWriteFile(const char* /*filename*/)
1675 {
1676  return false;
1677 }
1678 
1679 // Not yet implemented
1680 void JPEG2000ImageIO::Write(const void* /*buffer*/)
1681 {
1682 
1683 }
1684 
1686 {
1687  if (m_FileName == "")
1688  {
1689  itkExceptionMacro(<< "A FileName must be specified.");
1690  }
1691  if (CanWriteFile(m_FileName.c_str()) == false)
1692  {
1693  itkExceptionMacro(<< "The file " << m_FileName.c_str() << " is not defined as a JPEG2000 file");
1694  }
1695 
1696  otbMsgDebugMacro(<< "Driver to write: JPEG2000");
1697  otbMsgDebugMacro(<< " Write file : " << m_FileName);
1698  otbMsgDebugMacro(<< " Size : " << m_Dimensions[0] << "," << m_Dimensions[1]);
1699  otbMsgDebugMacro(<< " ComponentType : " << this->GetComponentType());
1700  otbMsgDebugMacro(<< " NumberOfComponents : " << this->GetNumberOfComponents());
1701  otbMsgDebugMacro(<< " ComponentSize : " << this->GetComponentSize());
1702  otbMsgDebugMacro(<< " GetPixelSize : " << this->GetPixelSize());
1703 
1704 }
1705 
1706 } // end namespace otb

Generated at Sun Feb 3 2013 00:31:40 for Orfeo Toolbox with doxygen 1.8.1.1