OSSIM - Open Source Software Image Map  Version 1.9.0 (20180803)
ossimMrSidWriter.cpp
Go to the documentation of this file.
1 //----------------------------------------------------------------------------
2 //
3 // License: LGPL
4 //
5 // See LICENSE.txt file in the top level directory for more details.
6 //
7 // Description: OSSIM MrSid writer class definition.
8 //
9 //----------------------------------------------------------------------------
10 // $Id: ossimMrSidWriter.cpp 2645 2011-05-26 15:21:34Z oscar.kramer $
11 
12 #ifdef OSSIM_ENABLE_MRSID_WRITE
13 
14 #include <ostream>
15 
17 #include <ossim/base/ossimDate.h>
18 #include <ossim/base/ossimDpt.h>
19 #include <ossim/base/ossimEndian.h>
22 #include <ossim/base/ossimTrace.h>
28 
29 //LizardTech Includes
30 #include <lt_base.h>
31 #include <lt_fileSpec.h>
32 #include <lt_ioFileStream.h>
33 #include <lti_imageReader.h>
34 #include <lti_pixel.h>
35 #include <lti_scene.h>
36 #include <lti_sceneBuffer.h>
37 #include <lt_fileSpec.h>
38 #include <lti_geoCoord.h>
39 #include <lt_ioFileStream.h>
40 #include <lti_pixelLookupTable.h>
41 #include <lti_utils.h>
42 #include <lti_metadataDatabase.h>
43 #include <lti_metadataRecord.h>
44 #include <lt_utilStatusStrings.h>
45 #include <ogr_spatialref.h>
46 
47 #include "ossimMrSidWriter.h"
48 
49 RTTI_DEF1(ossimMrSidWriter, "ossimMrSidWriter", ossimImageFileWriter)
50 
51 //---
52 // For trace debugging (to enable at runtime do:
53 // your_app -T "ossimMrSidWriter:debug" your_app_args
54 //---
55 static ossimTrace traceDebug("ossimMrSidWriter:debug");
56 
57 //---
58 // For the "ident" program which will find all exanded $Id: ossimMrSidWriter.cpp 2645 2011-05-26 15:21:34Z oscar.kramer $
59 // them.
60 //---
61 #if OSSIM_ID_ENABLED
62 static const char OSSIM_ID[] = "$Id: ossimMrSidWriter.cpp 2645 2011-05-26 15:21:34Z oscar.kramer $";
63 #endif
64 
65 template <class T>
66 class LTIDLLPixel : public T
67 {
68 public:
69  LTIDLLPixel(LTIColorSpace colorSpace, lt_uint16 numBands,
70  LTIDataType dataType) : T(colorSpace,numBands,dataType) {}
71  virtual ~LTIDLLPixel() {};
72 };
73 
74 ossimMrSidWriter::ossimMrSidWriter()
76 m_fileSize(0),
77 m_makeWorldFile(false)
78 {
79  // Set the output image type in the base class.
80  setOutputImageType(getShortName());
81 }
82 
83 ossimMrSidWriter::~ossimMrSidWriter()
84 {
85  close();
86 }
87 
88 ossimString ossimMrSidWriter::getShortName() const
89 {
90  return ossimString("ossim_mrsid");
91 }
92 
93 ossimString ossimMrSidWriter::getLongName() const
94 {
95  return ossimString("ossim mrsid writer");
96 }
97 
99 {
100  return ossimString("ossimMrSidWriter");
101 }
102 
104 {
105  // This method is called from ossimImageFileWriter::execute().
106  bool result = false;
107 
108  if( theInputConnection.valid() &&
109  (getErrorStatus() == ossimErrorCodes::OSSIM_OK) )
110  {
111  //---
112  // Note only the master process used for writing...
113  //---
114  if(theInputConnection->isMaster())
115  {
116  if (!isOpen())
117  {
118  open();
119  }
120  if ( isOpen() )
121  {
122  result = writeStream();
123  }
124  }
125  else // Slave process.
126  {
127  // This will return after all tiles for this node have been processed.
128  theInputConnection->slaveProcessTiles();
129  result = true;
130  }
131  }
132 
133  return result;
134 }
135 
136 bool ossimMrSidWriter::writeStream()
137 {
138  static const char MODULE[] = "ossimMrSidWriter::writeStream";
139 
140  if (traceDebug())
141  {
143  << MODULE << " entered..." << endl;
144  }
145 
146  //Since the LizardTech algorithms process an entire row at a time,
147  //we need to set the tile width equals to the width of theAreaOfInterest
148  //set the tile height to 32, so the writer will write 32 rows at a time
149  theInputConnection->setTileSize(theAreaOfInterest.width(), 32);
150  theInputConnection->initialize();
151 
152  theInputConnection->setAreaOfInterest(theAreaOfInterest);
153  theInputConnection->setToStartOfSequence();
154 
155  MrSIDDummyImageReader imageReader(theInputConnection);
156  if (!LT_SUCCESS(imageReader.initialize()))
157  {
159  << MODULE << ": Failed to open the input image!" << endl;
160  return false;
161  }
162  LTIMetadataDatabase& metadataDatabase =
163  const_cast<LTIMetadataDatabase&>(imageReader.getMetadata());
164  writeMetaDatabase(metadataDatabase);
165 
166  MG3ImageWriter imageWriter;
167  if (!LT_SUCCESS(imageWriter.initialize(&imageReader)))
168  {
169  return false;
170  }
171 
172  // set output filename
173  if (!LT_SUCCESS(imageWriter.setOutputFileSpec(theFilename)))
174  {
175  return false;
176  }
177 
178  LT_STATUS stat = imageWriter.setEncodingApplication(getShortName(), "1.0");
179 
180  if ( LT_FAILURE(stat) )
181  {
183  << "ossimMrSidWriter::writeMetaDatabase ERROR:"
184  << "\nMG3ImageWriter.setEncodingApplication() failed. "
185  << getLastStatusString(stat)
186  << std::endl;
187  return false;
188  }
189 
190  // Only allow the cartridge check disable when ossimMrSid is compiled for
191  // development mode. MRSID_DISABLE_CARTRIDGE_CHECK is defined as preprocessor
192  // in the project with ReleaseWithSymbols
193 #ifdef MRSID_DISABLE_CARTRIDGE_CHECK
194  imageWriter.setUsageMeterEnabled(false);
195 #else
196  // V Important: This enables proper usage of cartridge. Changing the param
197  // to false will cause Mr. Sid writer license violation.
198  imageWriter.setUsageMeterEnabled(true);
199 #endif
200 
201  imageWriter.setStripHeight(32); //set rows offset. it's same as the tile height
202  if (!LT_SUCCESS(imageWriter.params().setBlockSize(imageWriter.params().getBlockSize())))
203  {
204  return false;
205  }
206 
207  if (m_makeWorldFile)
208  {
209  imageWriter.setWorldFileSupport(m_makeWorldFile);
210  }
211 
212  if (m_fileSize > 0)
213  {
214  imageWriter.params().setTargetFilesize(m_fileSize);
215  }
216 
217  const LTIScene scene(0, 0, theInputConnection->getAreaOfInterest().width(),
218  theInputConnection->getAreaOfInterest().height(), 1.0);
219  if (!LT_SUCCESS(imageWriter.write(scene)))
220  {
222  << "ossimMrSidWriter::writeMetaDatabase ERROR:"
223  << "\nFailed to write SID file. Is cartridge installed correctly?"
224  << std::endl;
225  return false;
226  }
227 
228  return true;
229 }
230 
231 bool ossimMrSidWriter::saveState(ossimKeywordlist& kwl,
232  const char* prefix)const
233 {
234  return ossimImageFileWriter::saveState(kwl, prefix);
235 }
236 
237 bool ossimMrSidWriter::loadState(const ossimKeywordlist& kwl,
238  const char* prefix)
239 {
240  return ossimImageFileWriter::loadState(kwl, prefix);
241 }
242 
243 bool ossimMrSidWriter::isOpen() const
244 {
245  if (theFilename.size() > 0)
246  {
247  return true;
248  }
249  return false;
250 }
251 
252 bool ossimMrSidWriter::open()
253 {
254  bool result = false;
255 
256  // Check for empty filenames.
257  if (theFilename.size())
258  {
259  result = true;
260  }
261 
262  if (traceDebug())
263  {
265  << "ossimMrSidWriter::open()\n"
266  << "File " << theFilename << (result ? " opened" : " not opened")
267  << std::endl;
268  }
269 
270  return result;
271 }
272 
273 void ossimMrSidWriter::close()
274 {
275 }
276 
277 void ossimMrSidWriter::getImageTypeList(std::vector<ossimString>& imageTypeList)const
278 {
279  imageTypeList.push_back(getShortName());
280 }
281 
282 ossimString ossimMrSidWriter::getExtension() const
283 {
284  return ossimString("sid");
285 }
286 
287 bool ossimMrSidWriter::hasImageType(const ossimString& imageType) const
288 {
289  bool result = false;
290  if ( (imageType == getShortName()) ||
291  (imageType == "image/mrsid") )
292  {
293  result = true;
294  }
295  return result;
296 }
297 
298 void ossimMrSidWriter::setProperty(ossimRefPtr<ossimProperty> property)
299 {
300  if (property.get())
301  {
302  if(property->getName() == "FILESIZE")
303  {
304  m_fileSize = property->valueToString().toInt32();
305  }
306 
307  if(property->getName() == "WORLDFILE")
308  {
309  if (!property->valueToString().empty())
310  {
311  m_makeWorldFile = true;
312  }
313  }
314 
316  }
317 }
318 
319 ossimRefPtr<ossimProperty> ossimMrSidWriter::getProperty(
320  const ossimString& name)const
321 {
322  // Currently no properties.
324 }
325 
326 void ossimMrSidWriter::getPropertyNames(
327  std::vector<ossimString>& propertyNames)const
328 {
330 }
331 
332 void ossimMrSidWriter::writeMetaDatabase(LTIMetadataDatabase& metadataDatabase)
333 {
334  // Get current input geometry
335  ossimRefPtr<ossimImageGeometry> image_geom = theInputConnection->getImageGeometry();
336  if (!image_geom.valid())
337  {
339  << "ossimMrSidWriter::writeMetaDatabase WARNING:"
340  << "\ntheInputConnection->getImageGeometry returned NULL."
341  << std::endl;
342  return;
343  }
344 
345  ossimProjection* proj = image_geom->getProjection();
346  if (!proj)
347  {
349  << "ossimMrSidWriter::writeMetaDatabase WARNING:"
350  << "\nFailed to create projection!"
351  << std::endl;
352  return;
353  }
354 
356  if (!mapProj)
357  {
359  << "ossimMrSidWriter::writeMetaDatabase WARNING:"
360  << "\nProjection failed to cast to map projection!"
361  << std::endl;
362  return;
363  }
364 
365  ossimUnitType unitType = mapProj->getModelTransformUnitType();
366  int epsg_code = (int) mapProj->getPcsCode();
367 
368  if (mapProj->getProjectionName() == "ossimEquDistCylProjection" ||
369  mapProj->getProjectionName() == "ossimLlxyProjection")
370  {
371  LTIMetadataRecord mrGeoCSType( "GEOTIFF_NUM::2048::GeographicTypeGeoKey",
372  LTI_METADATA_DATATYPE_SINT32, &epsg_code);
373  metadataDatabase.add(mrGeoCSType);
374 
375  const char* angularUnit = NULL;
376  if (unitType == OSSIM_UNIT_UNKNOWN || unitType == OSSIM_DEGREES)
377  {
378  angularUnit = "Angular_Degree";
379  }
380  else if (unitType == OSSIM_MINUTES)
381  {
382  angularUnit = "Angular_Minute";
383  }
384  else if (unitType == OSSIM_SECONDS)
385  {
386  angularUnit = "Angular_Second";
387  }
388 
389  LTIMetadataRecord mrGeogAngularUnitsStr( "GEOTIFF_CHAR::GeogAngularUnitsGeoKey",
390  LTI_METADATA_DATATYPE_ASCII, &angularUnit);
391  metadataDatabase.add(mrGeogAngularUnitsStr);
392  }
393  else
394  {
395  LTIMetadataRecord mrProjectedCSType("GEOTIFF_NUM::3072::ProjectedCSTypeGeoKey",
396  LTI_METADATA_DATATYPE_SINT32, &epsg_code);
397  metadataDatabase.add(mrProjectedCSType);
398 
399  const char* projLinearUnitsStr = NULL;
400  if (unitType == OSSIM_UNIT_UNKNOWN || unitType == OSSIM_METERS)
401  {
402  projLinearUnitsStr = "Linear_Meter";
403  }
404  else if (unitType == OSSIM_FEET)
405  {
406  projLinearUnitsStr = "Linear_Foot";
407  }
408  else if (unitType == OSSIM_US_SURVEY_FEET)
409  {
410  projLinearUnitsStr = "Linear_Foot_US_Survey";
411  }
412  LTIMetadataRecord mrProjLinearUnitsStr( "GEOTIFF_CHAR::ProjLinearUnitsGeoKey",
413  LTI_METADATA_DATATYPE_ASCII, &projLinearUnitsStr );
414  metadataDatabase.add( mrProjLinearUnitsStr );
415  }
416 
417  const char* GTRasterType = "RasterPixelIsArea";
418  LTIMetadataRecord mrGTRasterType( "GEOTIFF_CHAR::GTRasterTypeGeoKey",
419  LTI_METADATA_DATATYPE_ASCII, &GTRasterType );
420  metadataDatabase.add( mrGTRasterType );
421 }
422 
423 MrSIDDummyImageReader::MrSIDDummyImageReader(ossimRefPtr<ossimImageSourceSequencer> theInputConnection)
424 : LTIImageReader(),
425 theInputSource(theInputConnection)
426 {
427  ltiPixel = NULL;
428 }
429 
430 MrSIDDummyImageReader::~MrSIDDummyImageReader()
431 {
432  if ( ltiPixel )
433  {
434  delete ltiPixel;
435  }
436 }
437 
438 LT_STATUS MrSIDDummyImageReader::initialize()
439 {
440  if ( !LT_SUCCESS(LTIImageReader::init()) )
441  return LT_STS_Failure;
442 
443  lt_uint16 numBands = (lt_uint16)theInputSource->getNumberOfOutputBands();
444  LTIColorSpace colorSpace = LTI_COLORSPACE_RGB;
445  switch ( numBands )
446  {
447  case 1:
448  colorSpace = LTI_COLORSPACE_GRAYSCALE;
449  break;
450  case 3:
451  colorSpace = LTI_COLORSPACE_RGB;
452  break;
453  default:
454  colorSpace = LTI_COLORSPACE_MULTISPECTRAL;
455  break;
456  }
457 
458  ossimScalarType scalarType = theInputSource->getOutputScalarType();
459 
460  switch (scalarType)
461  {
462  case OSSIM_UINT16:
463  sampleType = LTI_DATATYPE_UINT16;
464  break;
465  case OSSIM_SINT16:
466  sampleType = LTI_DATATYPE_SINT16;
467  break;
468  case OSSIM_UINT32:
469  sampleType = LTI_DATATYPE_UINT32;
470  break;
471  case OSSIM_SINT32:
472  sampleType = LTI_DATATYPE_SINT32;
473  break;
474  case OSSIM_FLOAT32:
475  sampleType = LTI_DATATYPE_FLOAT32;
476  break;
477  case OSSIM_FLOAT64:
478  sampleType = LTI_DATATYPE_FLOAT64;
479  break;
480  default:
481  sampleType = LTI_DATATYPE_UINT8;
482  break;
483  }
484 
485  ltiPixel = new LTIDLLPixel<LTIPixel>( colorSpace, numBands, sampleType );
486 
487  if ( !LT_SUCCESS(setPixelProps(*ltiPixel)) )
488  return LT_STS_Failure;
489 
490  if ( !LT_SUCCESS(setDimensions(theInputSource->getAreaOfInterest().width()+1, theInputSource->getAreaOfInterest().height()+1)))
491  {
492  return LT_STS_Failure;
493  }
494 
495  ossimRefPtr<ossimImageGeometry> image_geom = theInputSource->getImageGeometry();
496  if (!image_geom.valid())
497  {
498  return LT_STS_Failure;
499  }
500 
501  ossimProjection* proj = image_geom->getProjection();
502  if (!proj)
503  {
504  return LT_STS_Failure;
505  }
506 
507  ossimMapProjection* mapProj = dynamic_cast<ossimMapProjection*>(proj);
508  if (!mapProj)
509  {
510  return LT_STS_Failure;
511  }
512 
513  double ulx = 0.0;
514  double uly = 0.0;
515  double perPixelX = 0.0;
516  double perPixelY = 0.0;
517 
518  ossimString type(mapProj->getProjectionName());
519  if(type == "ossimLlxyProjection" || type == "ossimEquDistCylProjection")
520  {
521  perPixelX = mapProj->getDecimalDegreesPerPixel().x;
522  perPixelY = -mapProj->getDecimalDegreesPerPixel().y;
523  ulx = mapProj->getUlGpt().lond();
524  uly = mapProj->getUlGpt().latd();
525  }
526  else
527  {
528  perPixelX = mapProj->getMetersPerPixel().x;
529  perPixelY = -mapProj->getMetersPerPixel().y;
530  ulx = mapProj->getUlEastingNorthing().u;
531  uly = mapProj->getUlEastingNorthing().v;
532  }
533 
534  LTIGeoCoord geoCoord(ulx + fabs(perPixelX)/2,
535  uly - fabs(perPixelY)/2, perPixelX,perPixelY, 0.0, 0.0, NULL);
536 
537  ossimString wkt = getWkt(mapProj);
538  if (!wkt.empty())
539  {
540  geoCoord.setWKT(wkt.c_str());
541  }
542 
543  if ( !LT_SUCCESS(setGeoCoord(geoCoord)) )
544  {
545  return LT_STS_Failure;
546  }
547 
548  setDefaultDynamicRange();
549 
550  return LT_STS_Success;
551 }
552 
553 ossimString MrSIDDummyImageReader::getWkt(ossimMapProjection* map_proj)
554 {
555  ossimString wktString;
556  OGRSpatialReference spatialRef;
557 
558  if(map_proj == NULL)
559  {
560  return wktString;
561  }
562 
563  ossim_uint32 code = map_proj->getPcsCode();
564  if (code != 0)
565  {
566  spatialRef.importFromEPSG(code);
567 
568  char* exportString = NULL;
569  spatialRef.exportToWkt(&exportString);
570 
571  if(exportString)
572  {
573  wktString = exportString;
574  delete exportString;
575  }
576  }
577 
578  return wktString;
579 }
580 
581 LT_STATUS MrSIDDummyImageReader::decodeStrip(LTISceneBuffer& stripData,
582  const LTIScene& stripScene)
583 
584 {
585  ossimRefPtr<ossimImageData> imageData = theInputSource->getNextTile();
586  if (imageData.valid() && ( imageData->getDataObjectStatus() != OSSIM_NULL ) )
587  {
588  stripData.importDataBSQ(imageData->getBuf());
589  }
590  return LT_STS_Success;
591 }
592 
593 #endif /* #ifdef OSSIM_ENABLE_MRSID_WRITE */
virtual void valueToString(ossimString &valueResult) const =0
ossimUnitType getModelTransformUnitType() const
virtual const ossimDpt & getDecimalDegreesPerPixel() const
Returns decimal degrees per pixel as an ossimDpt with "x" representing longitude and "y" representing...
64 bit floating point
16 bit unsigned integer
double lond() const
Will convert the radian measure to degrees.
Definition: ossimGpt.h:97
ossimUnitType
Represents serializable keyword/value map.
double u
Definition: ossimDpt.h:164
static const ossimErrorCode OSSIM_OK
bool valid() const
Definition: ossimRefPtr.h:75
virtual ossim_uint32 getPcsCode() const
Returns the EPSG PCS code or 32767 if the projection is a custom (non-EPSG) projection.
virtual bool loadState(const ossimKeywordlist &kwl, const char *prefix=0)
double y
Definition: ossimDpt.h:165
virtual bool saveState(ossimKeywordlist &kwl, const char *prefix=0) const
16 bit signed integer
virtual ossimDataObjectStatus getDataObjectStatus() const
32 bit floating point
Pure virtual base class for image file writers.
double latd() const
Will convert the radian measure to degrees.
Definition: ossimGpt.h:87
virtual void getPropertyNames(std::vector< ossimString > &propertyNames) const
32 bit unsigned integer
virtual ossimString getShortName() const
Definition: ossimObject.cpp:48
32 bit signed integer
virtual ossimString getProjectionName() const
Returns the projection name.
unsigned int ossim_uint32
#define PTR_CAST(T, p)
Definition: ossimRtti.h:321
virtual ossimRefPtr< ossimProperty > getProperty(const ossimString &name) const
virtual const ossimGpt & getUlGpt() const
ossimScalarType
const ossimProjection * getProjection() const
Access methods for projection (may be NULL pointer).
bool writeFile()
virtual void setProperty(ossimRefPtr< ossimProperty > property)
virtual const void * getBuf() const
const char * getClassName(int idx)
double x
Definition: ossimDpt.h:164
const char * c_str() const
Returns a pointer to a null-terminated array of characters representing the string&#39;s contents...
Definition: ossimString.h:396
bool empty() const
Definition: ossimString.h:411
virtual const ossimDpt & getUlEastingNorthing() const
#define RTTI_DEF1(cls, name, b1)
Definition: ossimRtti.h:485
virtual ossimDpt getMetersPerPixel() const
OSSIMDLLEXPORT std::ostream & ossimNotify(ossimNotifyLevel level=ossimNotifyLevel_WARN)
double v
Definition: ossimDpt.h:165
const ossimString & getName() const