OSSIM - Open Source Software Image Map  Version 1.9.0 (20180803)
ossimWriter.cpp
Go to the documentation of this file.
1 //---
2 //
3 // License: MIT
4 //
5 // Author: David Burken
6 //
7 // Description: Generic image writer class.
8 //
9 //---
10 // $Id$
11 
14 #include <ossim/base/ossimCommon.h>
18 #include <ossim/base/ossimRefPtr.h>
20 #include <ossim/base/ossimTrace.h>
24 
25 #include <limits>
26 #include <ostream>
27 
28 static const std::string ALIGN_TILES_KW = "align_tiles"; // bool
29 static const std::string BLOCK_SIZE_KW = "block_size"; // unsigned int
30 static const std::string FLUSH_TILES_KW = "flush_tiles"; // bool
31 static const std::string INCLUDE_BLANK_TILES_KW = "include_blank_tiles"; // bool
32 static const std::string TILE_SIZE_KW = "tile_size"; // (x,y) in pixels
33 static const std::string TRUE_KW = "true";
34 
35 static const ossimTrace traceDebug("ossimWriter:debug");
36 
39  m_str(0),
40  m_ownsStreamFlag(false),
41  m_kwl(new ossimKeywordlist()),
43 {
44  // Set default options:
46 
47  m_kwl->addPair( ALIGN_TILES_KW, TRUE_KW );
48  m_kwl->addPair( BLOCK_SIZE_KW, "4096" );
49  m_kwl->addPair( FLUSH_TILES_KW, TRUE_KW );
50  m_kwl->addPair( INCLUDE_BLANK_TILES_KW, TRUE_KW );
51  m_kwl->addPair( TILE_SIZE_KW, m_outputTileSize.toString().string() );
52 }
53 
55 {
56  close();
57 
58  // Not a leak, ref ptr.
59  m_kwl = 0;
60 }
61 
63 {
64  if (m_str)
65  {
66  m_str->flush();
67 
68  if (m_ownsStreamFlag)
69  {
70  delete m_str;
71  m_str = 0;
72  m_ownsStreamFlag = false;
73  }
74  }
75 }
76 
78 {
79  return ossimString("ossim_writer");
80 }
81 
83 {
84  return ossimString("ossim writer");
85 }
86 
88 {
89  return ossimString("ossimWriter");
90 }
91 
93 {
94  ossimString result = "";
95  if ( theOutputImageType == "ossim_ttbs" ) // tiled tiff band separate
96  {
97  result = "tif";
98  }
99  return result;
100 }
101 
102 void ossimWriter::getImageTypeList(std::vector<ossimString>& imageTypeList) const
103 {
104  // imageTypeList.push_back(ossimString("tiff_tiled_band_separate"));
105  imageTypeList.push_back(ossimString("ossim_ttbs")); // tmp drb
106 }
107 
109 {
110  return ( m_str ? true : false );
111 }
112 
114 {
115  bool status = false;
116 
117  close();
118 
120  {
121  std::ofstream* os = new std::ofstream();
122  os->open( theFilename.c_str(), ios::out | ios::binary );
123  if( os->is_open() )
124  {
125  m_str = os;
126  m_ownsStreamFlag = true;
127  status = true;
128  }
129  else
130  {
131  delete os;
132  os = 0;
133  }
134  }
135 
136  return status;
137 }
138 
139 bool ossimWriter::hasImageType(const ossimString& imageType) const
140 {
141  bool result = false;
142  if ( (imageType == "ossim_ttbs") || (imageType == "image/tif") )
143  {
144  result = true;
145  }
146  return result;
147 }
148 
150 {
151  bool status = true;
152 
153  if( theInputConnection.valid() &&
155  {
156  //---
157  // Check for stream if master process.
158  // Note only the master process is used for writing...
159  //---
161  {
162  if (!isOpen())
163  {
164  status = open();
165  }
166  }
167 
168  if ( status )
169  {
170  status = writeStream();
171 
172  // Flush and close the stream.
173  close();
174  }
175  }
176 
177  return status;
178 }
179 
181 {
182  //---
183  // This can be called publically so we must to the same checks as the
184  // writeFile method.
185  //---
186  bool status = false;
187 
188  // Must have a sequencer...
189  if( theInputConnection.valid() )
190  {
191  if ( isOpen() )
192  {
193  if ( theOutputImageType == "ossim_ttbs" )
194  {
195  if ( (theInputConnection->getTileWidth() !=
196  static_cast<ossim_uint32>(m_outputTileSize.x)) ||
198  static_cast<ossim_uint32>(m_outputTileSize.y)) )
199  {
201  }
202 
204  }
205  }
206  }
207 
208  return status;
209 }
210 
212 {
213  // Alway big tiff in native byte order.
214 
215  bool status = false;
216 
217  if ( writeTiffHdr() == true )
218  {
219  std::vector<ossim_uint64> tile_offsets;
220  std::vector<ossim_uint64> tile_byte_counts;
221 
222  //---
223  // Min/max arrays must start off empty for
224  // ossimImageData::computeMinMaxPix code.
225  //---
226  std::vector<ossim_float64> minBands(0);
227  std::vector<ossim_float64> maxBands(0);
228 
230  tile_offsets, tile_byte_counts, minBands, maxBands ) == true )
231  {
232  status = writeTiffTags( tile_offsets, tile_byte_counts, minBands, maxBands );
233  }
234  }
235 
236  return status;
237 }
238 
240 {
241  //---
242  // First two bytes, byte order indication.
243  // "MM"(big endian) or "II"(little endian.
244  //---
245  std::string s;
247  {
248  s = "II";
249  }
250  else
251  {
252  s = "MM";
253  }
254  m_str->write( s.c_str(), 2 );
255 
256  // Version, 42=classic tiff, 43=big tiff.
257  ossim_uint16 us16 = 43;
258  m_str->write( (const char*)&us16, 2 );
259 
260  // Byte size of offsets.
261  us16 = 8;
262  m_str->write( (const char*)&us16, 2 );
263 
264  // Always 0:
265  us16 = 0;
266  m_str->write( (const char*)&us16, 2 );
267 
268  // Offset to the IFD(image file directory).
269  ossim_uint64 ul64 = 16;
270  m_str->write( (const char*)&ul64, 8 );
271 
272  return m_str->good();
273 }
274 
275 bool ossimWriter::writeTiffTags( const std::vector<ossim_uint64>& tile_offsets,
276  const std::vector<ossim_uint64>& tile_byte_counts,
277  const std::vector<ossim_float64>& minBands,
278  const std::vector<ossim_float64>& maxBands )
279 {
280  bool status = false;
281 
284  if ( geom.valid() )
285  {
287  mapProj = dynamic_cast<ossimMapProjection*>( proj.get() );
288  }
289 
290  // Seek to the IFD.
291  m_str->seekp( 16, std::ios_base::beg );
292 
293  // tag count, this will be rewritten at the end:
294  ossim_uint64 tagCount = 0;
295  m_str->write( (const char*)&tagCount, 8 );
296 
297  //---
298  // This is where the tile offsets, tile byte counts and arrays bytes are
299  // written. Starting at byte position 512 which gives from
300  // 16 -> 512(496 bytes) to write tags.
301  //---
302  std::streamoff arrayWritePos = 512;
303 
304  // Used throughout:
305  ossim_uint16 tag;
306  ossim_uint16 type;
307  ossim_uint64 count;
308  ossim_uint16 value_ui16;
309  ossim_uint32 value_ui32;
310 
311  // image width tag 256:
313  count = 1;
315  {
316  type = ossim::OTIFF_SHORT;
317  value_ui16 = (ossim_uint16)theAreaOfInterest.width();
318  writeTiffTag<ossim_uint16>( tag, type, count, &value_ui16, arrayWritePos );
319  }
320  else
321  {
322  type = ossim::OTIFF_LONG;
323  value_ui32 = theAreaOfInterest.width();
324  writeTiffTag<ossim_uint32>( tag, type, count, &value_ui32, arrayWritePos );
325  }
326  ++tagCount;
327 
328  // image length tag 257:
330  count = 1;
332  {
333  type = ossim::OTIFF_SHORT;
334  value_ui16 = (ossim_uint16)theAreaOfInterest.height();
335  writeTiffTag<ossim_uint16>( tag, type, count, &value_ui16, arrayWritePos );
336  }
337  else
338  {
339  type = ossim::OTIFF_LONG;
340  value_ui32 = theAreaOfInterest.height();
341  writeTiffTag<ossim_uint32>( tag, type, count, &value_ui32, arrayWritePos );
342  }
343  ++tagCount;
344 
345  // bits per sample tag 258:
348  type = ossim::OTIFF_SHORT;
350  if ( count == 1 )
351  {
352  writeTiffTag<ossim_uint16>( tag, type, count, &value_ui16, arrayWritePos );
353  }
354  else
355  {
356  std::vector<ossim_uint16> v(count, value_ui16);
357  writeTiffTag<ossim_uint16>( tag, type, count, &v.front(), arrayWritePos );
358  }
359  ++tagCount;
360 
361  // compression tag 259:
363  type = ossim::OTIFF_SHORT;
364  count = 1;
365  value_ui16 = ossim::COMPRESSION_NONE; // tmp only uncompressed supported.
366  writeTiffTag<ossim_uint16>( tag, type, count, &value_ui16, arrayWritePos );
367  ++tagCount;
368 
369  // photo interpretation tag 262:
371  type = ossim::OTIFF_SHORT;
372  count = 1;
374  {
375  value_ui16 = ossim::OPHOTO_RGB;
376  }
377  else
378  {
379  value_ui16 = ossim::OPHOTO_MINISBLACK;
380  }
381  writeTiffTag<ossim_uint16>( tag, type, count, &value_ui16, arrayWritePos );
382  ++tagCount;
383 
384  // samples per pixel tag 277:
386  type = ossim::OTIFF_SHORT;
387  count = 1;
389  writeTiffTag<ossim_uint16>( tag, type, count, &value_ui16, arrayWritePos );
390  ++tagCount;
391 
392  // Writes two tags 280 and 281:
393  if ( writeMinMaxTiffTags( arrayWritePos ) == true )
394  {
395  tagCount += 2;
396  }
397 
398  // planar conf tag 284:
400  type = ossim::OTIFF_SHORT;
401  count = 1;
403  writeTiffTag<ossim_uint16>( tag, type, count, &value_ui16, arrayWritePos );
404  ++tagCount;
405 
406  if ( isTiled() )
407  {
408  // tile width tag 322:
410  count = 1;
412  {
413  type = ossim::OTIFF_SHORT;
414  value_ui16 = (ossim_uint16)m_outputTileSize.x;
415  writeTiffTag<ossim_uint16>( tag, type, count, &value_ui16, arrayWritePos );
416  }
417  else
418  {
419  type = ossim::OTIFF_LONG;
420  value_ui32 = (ossim_uint32)m_outputTileSize.x;
421  writeTiffTag<ossim_uint32>( tag, type, count, &value_ui32, arrayWritePos );
422  }
423  ++tagCount;
424 
425  // tile length tag 323:
427  count = 1;
429  {
430  type = ossim::OTIFF_SHORT;
431  value_ui16 = (ossim_uint16)m_outputTileSize.y;
432  writeTiffTag<ossim_uint16>( tag, type, count, &value_ui16, arrayWritePos );
433  }
434  else
435  {
436  type = ossim::OTIFF_LONG;
437  value_ui32 = (ossim_uint32)m_outputTileSize.y;
438  writeTiffTag<ossim_uint32>( tag, type, count, &value_ui32, arrayWritePos );
439  }
440  ++tagCount;
441  }
442 
443  // tile offsets tag 324:
445  count = tile_offsets.size();
446  type = ossim::OTIFF_LONG8;
447  writeTiffTag<ossim_uint64>( tag, type, count, &tile_offsets.front(), arrayWritePos );
448  ++tagCount;
449 
450  // tile byte counts tag 325:
452  count = tile_byte_counts.size();
453  type = ossim::OTIFF_LONG8;
454  writeTiffTag<ossim_uint64>( tag, type, count, &tile_byte_counts.front(), arrayWritePos );
455  ++tagCount;
456 
457  // sample format tag 339:
460  type = ossim::OTIFF_SHORT;
461  value_ui16 = getTiffSampleFormat();
462  if ( count == 1 )
463  {
464  writeTiffTag<ossim_uint16>( tag, type, count, &value_ui16, arrayWritePos );
465  }
466  else
467  {
468  std::vector<ossim_uint16> v(count, value_ui16);
469  writeTiffTag<ossim_uint16>( tag, type, count, &v.front(), arrayWritePos );
470  }
471  ++tagCount;
472 
473  // Writes two tags 340 and 341 (conditional on scalar type):
474  if ( writeSMinSMaxTiffTags( minBands, maxBands, arrayWritePos ) == true )
475  {
476  tagCount += 2;
477  }
478 
479  // Write geo keys if valid map projection:
480  if ( mapProj.valid() )
481  {
482  std::vector<ossim_float64> vf;
483  ossimDpt scale;
484  ossimDpt tie;
485 
486  if ( mapProj->isGeographic() )
487  {
488  ossimGpt gpt;
489  mapProj->lineSampleToWorld( theAreaOfInterest.ul(), gpt );
490  tie.x = gpt.lon;
491  tie.y = gpt.lat;
492  scale = mapProj->getDecimalDegreesPerPixel();
493  }
494  else
495  {
497  scale = mapProj->getMetersPerPixel();
498  }
499 
500  // model pixel scale tag 33550:
502  count = 3; // x, y, z
503  type = ossim::OTIFF_DOUBLE;
504  vf.resize( count );
505  vf[0] = scale.x;
506  vf[1] = scale.y;
507  vf[2] = 0.0;
508  writeTiffTag<ossim_float64>( tag, type, count, &vf.front(), arrayWritePos );
509  ++tagCount;
510 
511  // model tie point tag 33992:
513  count = 6; // x, y, z
514  type = ossim::OTIFF_DOUBLE;
515  vf.resize( count );
516  vf[0] = 0.0; // x image point
517  vf[1] = 0.0; // y image point
518  vf[2] = 0.0; // z image point
519  vf[3] = tie.x; // longitude or easting
520  vf[4] = tie.y; // latitude of northing
521  vf[5] = 0.0;
522  writeTiffTag<ossim_float64>( tag, type, count, &vf.front(), arrayWritePos );
523  ++tagCount;
524 
525  // geo key directory tag 34735:
527  count = 0; // set later.
528  type = ossim::OTIFF_SHORT;
529  std::vector<ossim_uint16> vs(0);
530 
531  // No
532  vs.push_back(1);
533  vs.push_back(1);
534  vs.push_back(0);
535  vs.push_back(10); // Updated later.
536 
537  vs.push_back(ossim::OGT_MODEL_TYPE_GEO_KEY); // 1024
538  vs.push_back(0);
539  vs.push_back(1);
540  vs.push_back(mapProj->isGeographic() ? ossim::OMODEL_TYPE_GEOGRAPHIC :
542 
543  vs.push_back(ossim::OGT_RASTER_TYPE_GEO_KEY); // 1025
544  vs.push_back(0);
545  vs.push_back(1);
546  vs.push_back(ossim::OPIXEL_IS_POINT);
547 
548  if ( mapProj->isGeographic() )
549  {
550  vs.push_back(ossim::OGEOGRAPHIC_TYPE_GEO_KEY); // 2048
551  vs.push_back(0);
552  vs.push_back(1);
553  vs.push_back((ossim_uint16)(mapProj->getPcsCode()));
554  }
555 
556  vs.push_back(ossim::OGEOG_GEODETIC_DATUM_GEO_KEY); // 2050
557  vs.push_back(0);
558  vs.push_back(1);
559  vs.push_back((ossim_uint16)(mapProj->getDatum()->epsgCode()));
560 
561  if ( mapProj->isGeographic() )
562  {
563  vs.push_back(ossim::OGEOG_ANGULAR_UNITS_GEO_KEY); // 2054
564  vs.push_back(0);
565  vs.push_back(1);
566  vs.push_back(ossim::OANGULAR_DEGREE);
567  }
568 
569  vs.push_back(ossim::OGEOG_ELLIPSOID_GEO_KEY); // 2056
570  vs.push_back(0);
571  vs.push_back(1);
572  vs.push_back((ossim_uint16)(mapProj->getDatum()->ellipsoid()->getEpsgCode()));
573 
574  // Stored in external OOGEO_DOUBLE_PARAMS_TAG
575  vs.push_back(ossim::OGEOG_SEMI_MAJOR_AXIS); // 2057
576  vs.push_back(ossim::OGEO_DOUBLE_PARAMS_TAG);
577  vs.push_back(1);
578  vs.push_back(0);
579 
580  vs.push_back(ossim::OGEOG_SEMI_MINOR_AXIS); // 2058
581  vs.push_back(ossim::OGEO_DOUBLE_PARAMS_TAG);
582  vs.push_back(1);
583  vs.push_back(1);
584 
585  vs.push_back(ossim::OPROJECTED_CS_TYPE_GEO_KEY); // 3072
586  vs.push_back(0);
587  vs.push_back(1);
588  vs.push_back((ossim_uint16)(mapProj->getPcsCode()));
589 
590  vs.push_back(ossim::OPROJECTION_GEO_KEY); // 3074
591  vs.push_back(0);
592  vs.push_back(1);
593  vs.push_back((ossim_uint16)(mapProj->getPcsCode()));
594 
595  if ( mapProj->isGeographic() == false )
596  {
597  vs.push_back(ossim::OPROJ_LINEAR_UNITS_GEO_KEY); // 3076
598  vs.push_back(0);
599  vs.push_back(1);
600  vs.push_back(ossim::OLINEAR_METER);
601  }
602 
603  count = vs.size();
604  vs[3] = (count / 4) - 1;
605  writeTiffTag<ossim_uint16>( tag, type, count, &vs.front(), arrayWritePos );
606  ++tagCount;
607 
608  // geo double params tag 33550:
610  count = 2; // ellipsoid major, minor axis
611  type = ossim::OTIFF_DOUBLE;
612  vf.resize( count );
613  vf[0] = mapProj->getDatum()->ellipsoid()->a();
614  vf[1] = mapProj->getDatum()->ellipsoid()->b();
615  writeTiffTag<ossim_float64>( tag, type, count, &vf.front(), arrayWritePos );
616  ++tagCount;
617  }
618 
619  // Write trailing zero indicading no more IFDs.
620  ossim_uint64 offsetToNextIfd = 0;
621  m_str->write( (const char*)&offsetToNextIfd, 8 );
622 
623  // Seek back and re-write the tag count.
624  m_str->seekp( 16, std::ios_base::beg );
625  m_str->write( (const char*)&tagCount, 8 );
626 
627  status = m_str->good();
628 
629  return status;
630 }
631 
632 bool ossimWriter::writeMinMaxTiffTags( std::streamoff& arrayWritePos )
633 {
634  bool status = true;
635 
636  // DEFAULT for OSSIM_UINT32.
637  ossim_uint16 minValue = 1;
638  ossim_uint16 maxValue = 255;
639 
641  {
642  case OSSIM_UINT8:
643  {
644  break; // defaulted above
645  }
646  case OSSIM_USHORT11:
647  {
648  maxValue = 2047;
649  break;
650  }
651  case OSSIM_USHORT12:
652  {
653  maxValue = 4095;
654  break;
655  }
656  case OSSIM_USHORT13:
657  {
658  maxValue = 8191;
659  break;
660  }
661  case OSSIM_USHORT14:
662  {
663  maxValue = 16383;
664  break;
665  }
666  case OSSIM_USHORT15:
667  {
668  maxValue = 32767;
669  break;
670  }
671  case OSSIM_UINT16:
672  {
673  maxValue = 65535;
674  break;
675  }
676  default:
677  status = false;
678  }
679 
680  if ( status )
681  {
682  writeTiffTag<ossim_uint16>( ossim::OTIFFTAG_MINSAMPLEVALUE,
684  1, &minValue, arrayWritePos );
685  writeTiffTag<ossim_uint16>( ossim::OTIFFTAG_MAXSAMPLEVALUE,
687  1, &maxValue, arrayWritePos );
688  }
689 
690  return status;
691 }
692 
693 bool ossimWriter::writeSMinSMaxTiffTags( const vector<ossim_float64>& minBands,
694  const vector<ossim_float64>& maxBands,
695  std::streamoff& arrayWritePos )
696 {
697  bool status = false;
698 
699  if(minBands.size() && maxBands.size())
700  {
701  ossim_float64 minValue = *std::min_element(minBands.begin(), minBands.end());
702  ossim_float64 maxValue = *std::max_element(maxBands.begin(), maxBands.end());
703 
705  {
706  case OSSIM_SINT16:
707  case OSSIM_UINT32:
708  case OSSIM_FLOAT32:
709  case OSSIM_FLOAT64:
712  {
713  ossim_float32 v = static_cast<ossim_float32>(minValue);
714  writeTiffTag<ossim_float32>( ossim::OTIFFTAG_SMINSAMPLEVALUE,
716  1, &v, arrayWritePos );
717  v = static_cast<ossim_float32>(maxValue);
718  writeTiffTag<ossim_float32>( ossim::OTIFFTAG_SMAXSAMPLEVALUE,
720  1, &v, arrayWritePos );
721  status = true;
722  break;
723  }
724  default:
725  {
726  break;
727  }
728  }
729  }
730  return status;
731 }
732 
733 template <class T>
735  ossim_uint16 tag, ossim_uint16 type, ossim_uint64 count,
736  const T* value, std::streamoff& arrayWritePos )
737 {
738  m_str->write( (const char*)&tag, 2 );
739  m_str->write( (const char*)&type, 2 );
740  m_str->write( (const char*)&count, 8 );
741 
742  ossim_uint64 bytes = sizeof( T ) * count;
743 
744  if ( bytes <= 8 )
745  {
746  m_str->write( (const char*)value, bytes );
747  if ( bytes < 8 )
748  {
749  // Fill remaining bytes with 0.
750  char c = '\0';
751  m_str->write( (const char*)&c, (8-bytes) );
752  }
753  }
754  else // Greater than 8 bytes, must write at end of file.
755  {
756  // Store the offset to array:
757  m_str->write( (const char*)&arrayWritePos, 8 );
758 
759  // Capture posistion:
760  std::streamoff currentPos = m_str->tellp();
761 
762  // Seek to end:
763  m_str->seekp( arrayWritePos, std::ios_base::beg );
764 
765  // Write:
766  m_str->write( (const char*)value, bytes );
767 
768  // Capture new offset for next array write.
769  arrayWritePos = m_str->tellp();
770 
771  // Seek back:
772  m_str->seekp( currentPos, std::ios_base::beg );
773  }
774 }
775 
776 bool ossimWriter::writeTiffTilesBandSeparate( std::vector<ossim_uint64>& tile_offsets,
777  std::vector<ossim_uint64>& tile_byte_counts,
778  std::vector<ossim_float64>& minBands,
779  std::vector<ossim_float64>& maxBands )
780 {
781  static const char* const MODULE = "ossimWriter::writeToTilesBandSeparate";
782  if ( traceDebug() ) CLOG << " Entered...\n";
783 
784  // Start the sequence at the first tile.
786 
787  // Control flags:
788  bool alignTiles = getAlignTilesFlag();
789  bool flushTiles = getFlushTilesFlag();
790  bool writeBlanks = getWriteBlanksFlag();
791  bool computeMinMax = needsMinMax();
792 
793  // Block size for write:
794  const std::streamsize BLOCK_SIZE = getBlockSize();
795 
799 
800  if (traceDebug())
801  {
803  << "align tiles flag: " << alignTiles
804  << "\nflush tiles flag: " << flushTiles
805  << "\nwrite blanks flag: " << writeBlanks
806  << "\ncompute min max flag: " << computeMinMax
807  << "\nwrite block size: " << BLOCK_SIZE
808  << "\nBANDS: " << BANDS
809  << "\nTILES_WIDE: " << TILES_WIDE
810  << "\nTILES_TOTAL: " << TILES_TOTAL << "\n";
811  }
812 
813  tile_offsets.resize( TILES_TOTAL*BANDS );
814  tile_byte_counts.resize( TILES_TOTAL*BANDS );
815 
817  ossim_int64 ossimTileIndex = 0;
818  ossim_int64 tiffTileIndex = 0;
819  ossim_int64 tileSizeInBytes = 0;
820  ossim_int64 bandOffsetInBytes = 0;
821 
822  //---
823  // Adjust the starting file position to make room for IFD tags, tile offset
824  // and tile byte counts and arrays.
825  //
826  // Assuming:
827  // IFD start = 16, end 512, gives 496 bytes for tags.
828  // Array section start = 512, end is start + (16 * tile_count * bands) + 256 bytes
829  // for geotiff array bytes.
830  //---
831  std::streamsize startPos = 512 + 16 * TILES_TOTAL * BANDS + 256;
832 
833  while ( ossimTileIndex < TILES_TOTAL )
834  {
836  if(!id)
837  {
839  << MODULE << " ERROR:"
840  << "Error returned writing tiff tile: " << ossimTileIndex
841  << "\nNULL Tile from input encountered"
842  << std::endl;
843  return false;
844  }
845 
846  tileStatus = id->getDataObjectStatus();
847 
848  if ( ossimTileIndex == 0 )
849  {
850  tileSizeInBytes = (ossim_int64)id->getSizePerBandInBytes();
851  bandOffsetInBytes = tileSizeInBytes * TILES_TOTAL;
852  }
853 
854  if ( computeMinMax )
855  {
856  if ( (tileStatus == OSSIM_FULL) || (tileStatus == OSSIM_PARTIAL) )
857  {
858  // Compute running min, max.
859  id->computeMinMaxPix(minBands, maxBands);
860  }
861  }
862 
863  // Band loop.
864  for (ossim_int32 band=0; band < BANDS; ++band)
865  {
866  tiffTileIndex = ossimTileIndex + band * TILES_TOTAL;
867 
868  if ( (writeBlanks == true) || (tileStatus == OSSIM_FULL) || (tileStatus == OSSIM_PARTIAL) )
869  {
870  // Grab a pointer to the tile for the band.
871  const char* data = (const char*)id->getBuf(band);
872 
873  // Compress data here(future maybe, i.e. jpeg, j2k...
874 
875  //---
876  // Write the tile.
877  // Note: tiles laid out, all the red tiles, all the green tiles all the
878  // blue tiles.
879  //---
880  if(data)
881  {
882  // Compute the stream position:
883  std::streampos pos = startPos + ossimTileIndex * tileSizeInBytes +
884  band * bandOffsetInBytes;
885 
886  if ( alignTiles )
887  {
888  // Snap to block boundary:
889  std::streampos overflow = pos % BLOCK_SIZE;
890  if ( overflow > 0 )
891  {
892  pos += BLOCK_SIZE - overflow;
893  }
894  }
895 
896  m_str->seekp( pos );
897 
898  if ( m_str->good() )
899  {
900  tile_offsets[ tiffTileIndex ] = (ossim_uint64)pos;
901  tile_byte_counts[ tiffTileIndex ] = (ossim_uint64)tileSizeInBytes;
902 
903  // Write the tile to stream:
904  m_str->write( data, (std::streamsize)tileSizeInBytes);
905 
906  if ( flushTiles )
907  {
908  m_str->flush();
909  }
910 
911  // Check stream:
912  if ( m_str->fail() == true )
913  {
915  << MODULE << " ERROR:\nWrite error on tiff tile: " << ossimTileIndex
916  << std::endl;
917  return false;
918  }
919  }
920  else
921  {
923  << MODULE << " ERROR:\nStream has gone bad!" << std::endl;
924  return false;
925  }
926 
927  }
928  else
929  {
931  << MODULE << " ERROR:\nNull input tile: " << ossimTileIndex
932  << std::endl;
933  return false;
934  }
935  }
936  else
937  {
938  //---
939  // Writing sparse tiff.
940  // Set the offset and byte count to 0 to indicate blank tile.
941  //---
942  if (traceDebug())
943  {
945  << "sparse blank tile[" << tiffTileIndex << "]: " << tiffTileIndex << "\n";
946  }
947  tile_offsets[ tiffTileIndex ] = 0;
948  tile_byte_counts[ tiffTileIndex ] = 0;
949  }
950 
951  } // End of band loop.
952 
953  ++ossimTileIndex;
954 
955  if( needsAborting() )
956  {
957  setPercentComplete(100);
958  break; // Get out...
959  }
960  else if ( ossimTileIndex % TILES_WIDE )
961  {
962  // Output percent complete every row of tiles.
963  double tileNum = ossimTileIndex;
964  double numTiles = TILES_TOTAL;
965  setPercentComplete(tileNum / numTiles * 100.0);
966  }
967 
968  } // End: while ( ossimTileIndex < TILES_TOTAL )
969 
970  if ( traceDebug() ) CLOG << " Exited...\n";
971 
972  return m_str->good();
973 }
974 
976 {
977  if (m_ownsStreamFlag && m_str)
978  {
979  delete m_str;
980  }
981  m_str = &stream;
982  m_ownsStreamFlag = false;
983  return true;
984 }
985 
986 void ossimWriter::setTileSize(const ossimIpt& tileSize)
987 {
988  if ( (tileSize.x % 16) || (tileSize.y % 16) )
989  {
990  if(traceDebug())
991  {
993  << "ossimWriter::setTileSize ERROR:"
994  << "\nTile size must be a multiple of 16!"
995  << "\nSize remains: " << m_outputTileSize
996  << std::endl;
997  }
998  }
999  else
1000  {
1001  m_outputTileSize = tileSize;
1002 
1003  // For save state:
1004  m_kwl->addPair( TILE_SIZE_KW, m_outputTileSize.toString().string() );
1005  }
1006 }
1007 
1009 {
1010  return m_outputTileSize;
1011 }
1012 
1013 bool ossimWriter::saveState( ossimKeywordlist& kwl, const char* prefix) const
1014 {
1015  // Lazy man save state...
1016  kwl.add( prefix, *(m_kwl.get()), true );
1017  return ossimImageFileWriter::saveState(kwl, prefix);
1018 }
1019 
1020 bool ossimWriter::loadState(const ossimKeywordlist& kwl, const char* prefix)
1021 {
1022  bool result = false;
1023  if ( ossimImageFileWriter::loadState(kwl, prefix) )
1024  {
1025  if ( theOutputImageType!="ossim_ttbs")
1026  {
1027  result = true;
1028 
1029  std::string pfx = prefix?prefix:"";
1030  std::string value;
1031 
1032  value = kwl.findKey( pfx, ALIGN_TILES_KW );
1033  if ( value.size() )
1034  {
1035  m_kwl->addPair( ALIGN_TILES_KW, value, true );
1036  }
1037 
1038  value = kwl.findKey( pfx, BLOCK_SIZE_KW );
1039  if ( value.size() )
1040  {
1041  m_kwl->addPair( BLOCK_SIZE_KW, value, true );
1042  }
1043 
1044  value = kwl.findKey( pfx, FLUSH_TILES_KW );
1045  if ( value.size() )
1046  {
1047  m_kwl->addPair( FLUSH_TILES_KW, value, true );
1048  }
1049 
1050  value = kwl.findKey( pfx, INCLUDE_BLANK_TILES_KW );
1051  if ( value.size() )
1052  {
1053  m_kwl->addPair( INCLUDE_BLANK_TILES_KW, value, true );
1054  }
1055 
1056  value = kwl.findKey( pfx, TILE_SIZE_KW );
1057  if ( value.size() )
1058  {
1059  m_outputTileSize.toPoint(value);
1060  m_kwl->addPair( TILE_SIZE_KW, m_outputTileSize.toString().string(), true );
1061  }
1062  }
1063  }
1064 
1065  return result;
1066 }
1067 
1069 {
1070  if( property.valid() )
1071  {
1072  // See if it's one of our properties:
1073  std::string key = property->getName().string();
1074 
1075  if ( traceDebug() )
1076  {
1077  ossimString value;
1078  property->valueToString(value);
1079 
1081  << "ossimWriter::setProperty DEBUG:"
1082  << "\nkey: " << key
1083  << "\nvalue: " << value << "\n";
1084  }
1085 
1086  if ( ( key == ALIGN_TILES_KW ) ||
1087  ( key == BLOCK_SIZE_KW ) ||
1088  ( key == FLUSH_TILES_KW ) ||
1089  ( key == INCLUDE_BLANK_TILES_KW ) )
1090  {
1091  ossimString value;
1092  property->valueToString(value);
1093  m_kwl->addPair( key, value.string(), true );
1094  }
1095  else if ( key == TILE_SIZE_KW )
1096  {
1097  // Comes in as a single int, e.g.: 256
1098  ossimString value;
1099  property->valueToString(value);
1100  m_outputTileSize.x = value.toInt32();
1102 
1103  // Store in keywordlist / save state as a point, e.g.: ( 256, 256 )
1105  }
1106  else
1107  {
1109  }
1110  }
1111 }
1112 
1114 {
1115  ossimRefPtr<ossimProperty> prop = 0;
1116 
1117  if ( name.string() == ALIGN_TILES_KW )
1118  {
1119  std::string value = m_kwl->findKey( ALIGN_TILES_KW );
1121  new ossimBooleanProperty(name, ossimString(value).toBool());
1122  prop = boolProp.get();
1123  }
1124  else if( name == BLOCK_SIZE_KW )
1125  {
1126  // Property a single int, e.g.: 4096
1127  ossim_int64 blockSize = getBlockSize();
1129  new ossimStringProperty(name, ossimString::toString(blockSize), false); // editable flag
1130  prop = stringProp.get();
1131  }
1132  else if ( name.string() == FLUSH_TILES_KW )
1133  {
1134  std::string value = m_kwl->findKey( FLUSH_TILES_KW );
1136  new ossimBooleanProperty(name, ossimString(value).toBool());
1137  prop = boolProp.get();
1138  }
1139  else if ( name.string() == INCLUDE_BLANK_TILES_KW )
1140  {
1141  std::string value = m_kwl->findKey( INCLUDE_BLANK_TILES_KW );
1143  new ossimBooleanProperty(name, ossimString(value).toBool());
1144  prop = boolProp.get();
1145  }
1146  else if( name == TILE_SIZE_KW )
1147  {
1148  // Property a single int, e.g.: 256
1150  new ossimStringProperty(name, ossimString::toString(m_outputTileSize.x), false); // editable flag
1151  stringProp->setReadOnlyFlag(false);
1153  stringProp->addConstraint(ossimString("16"));
1154  stringProp->addConstraint(ossimString("32"));
1155  stringProp->addConstraint(ossimString("64"));
1156  stringProp->addConstraint(ossimString("128"));
1157  stringProp->addConstraint(ossimString("256"));
1158  stringProp->addConstraint(ossimString("512"));
1159  stringProp->addConstraint(ossimString("1024"));
1160  stringProp->addConstraint(ossimString("2048"));
1161  prop = stringProp.get();
1162  }
1163  else
1164  {
1165  prop = ossimImageFileWriter::getProperty(name);
1166  }
1167  return prop;
1168 }
1169 
1170 void ossimWriter::getPropertyNames(std::vector<ossimString>& propertyNames) const
1171 {
1172  propertyNames.push_back(ossimString(ALIGN_TILES_KW));
1173  propertyNames.push_back(ossimString(BLOCK_SIZE_KW));
1174  propertyNames.push_back(ossimString(FLUSH_TILES_KW));
1175  propertyNames.push_back(ossimString(INCLUDE_BLANK_TILES_KW));
1176  propertyNames.push_back(ossimString(TILE_SIZE_KW));
1178 }
1179 
1181 {
1182  ossim_uint16 result = 0;
1184  {
1185  case OSSIM_UINT8:
1186  case OSSIM_USHORT11:
1187  case OSSIM_USHORT12:
1188  case OSSIM_USHORT13:
1189  case OSSIM_USHORT14:
1190  case OSSIM_USHORT15:
1191  case OSSIM_UINT16:
1192  case OSSIM_UINT32:
1193  result = ossim::OSAMPLEFORMAT_UINT;
1194  break;
1195 
1196  case OSSIM_SINT16:
1197  result = ossim::OSAMPLEFORMAT_INT;
1198  break;
1199 
1200  case OSSIM_FLOAT32:
1201  case OSSIM_FLOAT64:
1204  result = ossim::OSAMPLEFORMAT_IEEEFP;
1205  break;
1206 
1207  default:
1208  break;
1209  }
1210 
1211  return result;
1212 }
1213 
1215 {
1216  return ( theOutputImageType == "ossim_ttbs" );
1217 }
1218 
1220 {
1221  bool result = true; // default
1222  std::string value = m_kwl->findKey( ALIGN_TILES_KW );
1223  if ( value.size() )
1224  {
1225  result = ossimString(value).toBool();
1226  }
1227  return result;
1228 }
1229 
1231 {
1232  ossim_int64 result = 4096; // default
1233  std::string value = m_kwl->findKey( BLOCK_SIZE_KW );
1234  if ( value.size() )
1235  {
1236  result = ossimString(value).toInt64();
1237 
1238  // Disallow anything not on 1024 boundary.
1239  if ( result % 1024 )
1240  {
1241  result = 4096;
1243  << "ossimWriter::getBlockSize ERROR:"
1244  << "\nBlock size MUST be a multiple of 1024!"
1245  << "\nBlock size remains: " << result
1246  << std::endl;
1247  }
1248  }
1249  return result;
1250 }
1251 
1253 {
1254  bool result = true; // default
1255  std::string value = m_kwl->findKey( FLUSH_TILES_KW );
1256  if ( value.size() )
1257  {
1258  result = ossimString(value).toBool();
1259  }
1260  return result;
1261 }
1262 
1264 {
1265  bool result = true; // default
1266  std::string value = m_kwl->findKey( INCLUDE_BLANK_TILES_KW );
1267  if ( value.size() )
1268  {
1269  result = ossimString(value).toBool();
1270  }
1271  return result;
1272 }
1273 
1275 {
1276  bool result = false;
1278  {
1279  case OSSIM_SINT16:
1280  case OSSIM_UINT32:
1281  case OSSIM_FLOAT32:
1282  case OSSIM_FLOAT64:
1285  {
1286  result = true;
1287  break;
1288  }
1289  default:
1290  {
1291  break;
1292  }
1293  }
1294  return result;
1295 }
ossimString toString() const
Definition: ossimIpt.cpp:139
16 bit unsigned integer (15 bits used)
virtual ossimString getShortName() const
Definition: ossimWriter.cpp:77
#define OSSIM_DEFAULT_MAX_PIX_UINT16
virtual const ossimDpt & getDecimalDegreesPerPixel() const
Returns decimal degrees per pixel as an ossimDpt with "x" representing longitude and "y" representing...
bool hasImageType(const ossimString &imageType) const
bool hasImageType(const ossimString& imageType) const
virtual void close()
close Flushes and deletes stream if we own it.
Definition: ossimWriter.cpp:62
ossim_uint16 getTiffSampleFormat() const
Gets the tiff sample format based on scalar type.
bool isTiled() const
64 bit floating point
#define CLOG
Definition: ossimTrace.h:23
16 bit unsigned integer
ossim_uint32 getEpsgCode() const
virtual ossim_uint32 getTileWidth() const
Returns the default processing tile width.
virtual void setTileSize(const ossimIpt &tileSize)
Sets the output tile size for tiled formats.
bool writeTiffHdr()
Writes tiff header to stream.
Represents serializable keyword/value map.
virtual ossimString getExtension() const
Returns a 3-letter extension from the image type descriptor (theOutputImageType) that can be used for...
Definition: ossimWriter.cpp:92
const std::string & findKey(const std::string &key) const
Find methods that take std::string(s).
static const ossimErrorCode OSSIM_OK
virtual ossim_uint32 getNumberOfOutputBands() const
Returns the number of bands in a tile returned from this TileSource.
bool valid() const
Definition: ossimRefPtr.h:75
virtual ossimRefPtr< ossimProperty > getProperty(const ossimString &name) const
virtual ossim_uint32 getPcsCode() const
Returns the EPSG PCS code or 32767 if the projection is a custom (non-EPSG) projection.
float ossim_float32
virtual ossim_uint32 epsgCode() const
Definition: ossimDatum.h:59
virtual void getImageTypeList(std::vector< ossimString > &imageTypeList) const
getImageTypeList method.
virtual bool loadState(const ossimKeywordlist &kwl, const char *prefix=0)
double y
Definition: ossimDpt.h:165
ossim_uint32 height() const
Definition: ossimIrect.h:487
bool writeTiffTags(const std::vector< ossim_uint64 > &tile_offsets, const std::vector< ossim_uint64 > &tile_byte_counts, const std::vector< ossim_float64 > &minBands, const std::vector< ossim_float64 > &maxBands)
Writes tags to image file directory(IFD).
virtual ossimRefPtr< ossimImageData > getNextTile(ossim_uint32 resLevel=0)
virtual bool saveState(ossimKeywordlist &kwl, const char *prefix=0) const
ossimIrect theAreaOfInterest
static ossimString toString(bool aValue)
Numeric to string methods.
void setChangeType(int type, bool on=true)
virtual bool isGeographic() const
OSSIM_DLL void defaultTileSize(ossimIpt &tileSize)
16 bit signed integer
const ossimIpt & ul() const
Definition: ossimIrect.h:274
void addPair(const std::string &key, const std::string &value, bool overwrite=true)
OSSIM_DLL ossimByteOrder byteOrder()
Definition: ossimCommon.cpp:54
16 bit unsigned integer (14 bits used)
bool getFlushTilesFlag() const
16 bit unsigned integer (13 bits used)
virtual ossimString getClassName() const
Definition: ossimWriter.cpp:87
virtual bool setOutputStream(std::ostream &str)
Sets the output stream to write to.
virtual void setReadOnlyFlag(bool flag)
const double & b() const
void addConstraint(const ossimString &value)
32 bit floating point
Pure virtual base class for image file writers.
unsigned short ossim_uint16
virtual ~ossimWriter()
virtual destructor
Definition: ossimWriter.cpp:54
virtual void getPropertyNames(std::vector< ossimString > &propertyNames) const
32 bit unsigned integer
std::ostream * m_str
Definition: ossimWriter.h:289
bool writeSMinSMaxTiffTags(const std::vector< ossim_float64 > &minBands, const std::vector< ossim_float64 > &maxBands, std::streamoff &arrayWritePos)
Writes tags TIFFTAG_SMINSAMPLEVALUE(340) and TIFFTAG_SMAXSAMPLEVALUE(341).
#define OSSIM_DEFAULT_TILE_WIDTH
virtual ossim_uint32 getSizePerBandInBytes() const
Returns the number of bytes in single band of the tile.
bool writeMinMaxTiffTags(std::streamoff &arrayWritePos)
Writes tags TIFFTAG_MINSAMPLEVALUE(280) and TIFFTAG_MAXSAMPLEVALUE(281).
ossim_int32 toInt32() const
double ossim_float64
void add(const char *prefix, const ossimKeywordlist &kwl, bool overwrite=true)
virtual bool loadState(const ossimKeywordlist &kwl, const char *prefix=0)
Method to the load (recreate) the state of an object from a keyword list.
ossimRefPtr< ossimKeywordlist > m_kwl
Hold all options.
Definition: ossimWriter.h:293
virtual ossimGpt lineSampleToWorld(const ossimDpt &projectedPoint) const
virtual ossimScalarType getOutputScalarType() const
This will be used to query the output pixel type of the tile source.
const double & a() const
virtual const ossimDatum * getDatum() const
ossim_float64 lon
Definition: ossimGpt.h:266
virtual void lineSampleToEastingNorthing(const ossimDpt &liineSample, ossimDpt &eastingNorthing) const
std::string::size_type size() const
Definition: ossimString.h:405
ossimRefPtr< ossimImageSourceSequencer > theInputConnection
bool toBool() const
String to numeric methods.
ossim_int64 getBlockSize() const
unsigned long long ossim_uint64
unsigned int ossim_uint32
32 bit normalized floating point
virtual const ossimEllipsoid * ellipsoid() const
Definition: ossimDatum.h:60
virtual void getPropertyNames(std::vector< ossimString > &propertyNames) const
Pushes this&#39;s names onto the list of property names.
ossimIpt m_outputTileSize
Definition: ossimWriter.h:295
bool writeTiffTilesBandSeparate(std::vector< ossim_uint64 > &tile_offsets, std::vector< ossim_uint64 > &tile_byte_counts, std::vector< ossim_float64 > &minBands, std::vector< ossim_float64 > &maxBands)
Writes image data to stream.
virtual ossimRefPtr< ossimProperty > getProperty(const ossimString &name) const
ossim_uint32 width() const
Definition: ossimIrect.h:500
virtual void setProperty(ossimRefPtr< ossimProperty > property)
Will set the property whose name matches the argument "property->getName()".
virtual ossimRefPtr< ossimImageGeometry > getImageGeometry()
Returns the image geometry object associated with this tile source or NULL if not defined...
void toPoint(const std::string &s)
Initializes this point from string.
Definition: ossimIpt.cpp:170
OSSIM_DLL ossim_uint32 getBitsPerPixel(ossimScalarType scalarType)
Get bits per pixel for a given scalar type.
virtual const ossimIpt & getOutputTileSize() const
Gets the tile size.
return status
bool getWriteBlanksFlag() const
64 bit normalized floating point
const ossimProjection * getProjection() const
Access methods for projection (may be NULL pointer).
16 bit unsigned integer (11 bits used)
ossim_int64 getNumberOfTilesHorizontal() const
virtual ossim_uint32 getTileHeight() const
Returns the default processing tile height.
virtual bool writeFile()
Write out the file.
virtual void setProperty(ossimRefPtr< ossimProperty > property)
virtual ossimErrorCode getErrorStatus() const
virtual bool saveState(ossimKeywordlist &kwl, const char *prefix=0) const
Saves the state of the object.
ossim_int32 y
Definition: ossimIpt.h:142
virtual const void * getBuf() const
virtual bool writeStream()
Method to write the image to a stream.
bool needsMinMax() const
double x
Definition: ossimDpt.h:164
#define OSSIM_DEFAULT_TILE_HEIGHT
long long ossim_int64
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
ossim_int64 toInt64() const
bool m_ownsStreamFlag
Definition: ossimWriter.h:290
ossim_int32 x
Definition: ossimIpt.h:141
ossim_float64 lat
Definition: ossimGpt.h:265
std::basic_ofstream< char > ofstream
Class for char output file streams.
Definition: ossimIosFwd.h:47
bool getAlignTilesFlag() const
8 bit unsigned integer
virtual ossimString getLongName() const
Definition: ossimWriter.cpp:82
void writeTiffTag(ossim_uint16 tag, ossim_uint16 type, ossim_uint64 count, const T *value, std::streamoff &arrayWritePos)
Writes tiff tag to image file directory(IFD).
ossimDataObjectStatus
Definitions for data object status.
virtual void setPercentComplete(double percentComplete)
ossimWriter()
default constructor
Definition: ossimWriter.cpp:37
virtual ossimDpt getMetersPerPixel() const
virtual bool isOpen() const
isOpen
virtual bool open()
open
virtual void setTileSize(const ossimIpt &tileSize)
OSSIMDLLEXPORT std::ostream & ossimNotify(ossimNotifyLevel level=ossimNotifyLevel_WARN)
bool writeStreamTtbs()
Writes a tiled tiff band separate to stream.
std::basic_ostream< char > ostream
Base class for char output streams.
Definition: ossimIosFwd.h:23
int ossim_int32
const std::string & string() const
Definition: ossimString.h:414
16 bit unsigned integer (12 bits used)