OSSIM - Open Source Software Image Map  Version 1.9.0 (20180803)
ossimPdfWriter.cpp
Go to the documentation of this file.
1 //----------------------------------------------------------------------------
2 //
3 // License: See top level LICENSE.txt file
4 //
5 // Author: David Burken
6 //
7 // Description: OSSIM Portable Document Format (PDF) writer.
8 //
9 //----------------------------------------------------------------------------
10 // $Id$
11 
14 #include <ossim/base/ossimCommon.h>
16 #include <ossim/base/ossimTrace.h>
17 #include <ossim/base/ossimDpt.h>
18 #include <ossim/base/ossimEndian.h>
19 #include <ossim/base/ossimIpt.h>
20 #include <ossim/base/ossimIrect.h>
23 #include <ossim/base/ossimString.h>
36 #include <ctime>
37 #include <fstream>
38 #include <iomanip>
39 #include <ostream>
40 #include <sstream>
41 #include <string>
42 #include <vector>
43 #include <jpeglib.h>
44 
46  "ossimPdfWriter",
48 
49 //---
50 // For trace debugging (to enable at runtime do:
51 // your_app -T "ossimPdfWriter:debug" your_app_args
52 //---
53 static ossimTrace traceDebug("ossimPdfWriter:debug");
54 static ossimTrace traceLog("ossimPdfWriter:log");
55 
56 // Property keywords:
57 static const std::string AUTHOR_KW = "Author";
58 static const std::string CREATOR_KW = "Creator";
59 static const std::string CREATION_DATE_KW = "CreationDate";
60 static const std::string KEYWORDS_KW = "Keywords";
61 static const std::string MOD_DATE_KW = "ModDate";
62 static const std::string PRODUCER_KW = "Producer";
63 static const std::string SUBJECT_KW = "Subject";
64 static const std::string TITLE_KW = "Title";
65 
66 //---
67 // For the "ident" program which will find all exanded $Id$ macros and print them.
68 //---
69 #if OSSIM_ID_ENABLED
70 static const char OSSIM_ID[] = "$Id$";
71 #endif
72 
75  m_str(0),
76  m_ownsStream(false),
77  m_savedInput(0),
78  m_kwl( new ossimKeywordlist() ),
79  m_mutex()
80 {
81  if (traceDebug())
82  {
84  << "ossimPdfWriter::ossimPdfWriter entered" << std::endl;
85 #if OSSIM_ID_ENABLED
87  << "OSSIM_ID: "
88  << OSSIM_ID
89  << std::endl;
90 #endif
91  }
92 
93  // Since there is no internal geometry set the flag to write out one.
94  setWriteExternalGeometryFlag(true);
95 
96  theOutputImageType = "ossim_pdf";
97 }
98 
100 {
101  // This will flush stream and delete it if we own it.
102  close();
103 
104  m_kwl = 0; // Not a leak, ossimRefPtr
105 }
106 
108 {
109  return ossimString("ossim_pdf_writer");
110 }
111 
113 {
114  return ossimString("ossim pdf writer");
115 }
116 
118 {
119  return ossimString("ossimPdfWriter");
120 }
121 
123 {
124  bool result = false;
125 
127  {
128  //---
129  // Make sure we can open the file. Note only the master process is used for
130  // writing...
131  //---
133  {
134  if (!isOpen())
135  {
136  open();
137  }
138  }
139 
140  result = writeStream();
141  }
142 
143  return result;
144 }
145 
147 {
148  static const char MODULE[] = "ossimPdfWriter::writeStream";
149  if (traceDebug())
150  {
152  << MODULE << " entered..."
153  << "\nCurrent options:\n"
154  << *(m_kwl.get()) << std::endl;
155  }
156 
157  bool result = false;
158 
159  if ( isOpen() )
160  {
161  // Make sure we have a region of interest.
162  if( theAreaOfInterest.hasNans() )
163  {
166  }
167  else
168  {
170  }
171 
174 
175  // std::cout <<"BANDS ======== " << bands << " scalarType = " << scalarType << std::endl;
176  if(((bands == 3) || (bands == 1))&&(scalarType == OSSIM_UINT8))
177  {
178  // Write the image:
179  result = writeImage( m_str );
180  }
181  else
182  {
183  ossimNotify(ossimNotifyLevel_INFO) << MODULE << " result = false" << std::endl;
184  // need some kind of error
185  result = false;
186  }
187 
188  close();
189 
190 
191  // Reset the input to the image source sequence if it was modified.
192  if ( m_savedInput.get() != theInputConnection->getInput( 0 ) )
193  {
195  }
196  }
197 
198  if (traceDebug())
199  {
201  << MODULE << " exit status = " << (result?"true":"false") << std::endl;
202  }
203 
204  return result;
205 
206 } // bool ossimPdfWriter::writeStream()
207 
209 {
210  // Header:
211  if ( str )
212  {
213  // Open in binary mode:
214  std::ostringstream os( std::ios_base::out|std::ios_base::binary );
215 
216  os << "%PDF-1.7\n";
217 
218  //---
219  // Add comment with four characters greater than 127 to flag "binary pdf".
220  // Standard/norm from spec is "0xE2E3CFD3":
221  //---
222  std::vector<ossim_uint8> binData(4);
223  binData[0] = 0xE2;
224  binData[1] = 0xE3;
225  binData[2] = 0xCF;
226  binData[3] = 0xD3;
227 
228  os << "%";
229  os.write( (char*)&binData.front(), binData.size() );
230  os << "\n";
231 
232  // Write it:
233  str->write( os.str().data(), os.str().size() );
234 
235  if ( traceLog() )
236  {
237  // Has binary data in it???
238  ossimNotify(ossimNotifyLevel_DEBUG) << os.str() << "\n";
239  }
240  }
241 }
242 
244  std::vector<std::streamoff>& xref )
245 {
246  // Write the Catalog object. This assumes an order of:
247  if ( str )
248  {
249  // Capture position:
250  xref.push_back( (std::streamoff)m_str->tellp() );
251 
252  std::ostringstream os; // tmp stream...
253  os << xref.size() << " 0 obj\n"
254  << " << /Type /Catalog\n"
255  << " /Pages " << xref.size()+1 << " 0 R\n" // Reference to Pages.
256  << " >>\n"
257  << "endobj\n";
258 
259  // Write it:
260  str->write( os.str().data(), os.str().size() );
261 
262  if ( traceLog() )
263  {
264  // Has binary data in it???
265  ossimNotify(ossimNotifyLevel_DEBUG) << os.str() << "\n";
266  }
267  }
268 }
269 
270 #if 0
271 void ossimPdfWriter::writeOutlines( std::ostream* str,
272  std::vector<std::streamoff>& xref )
273 {
274  // Write the Outlines object:
275  if ( str )
276  {
277  // Capture position:
278  xref.push_back( (std::streamoff)m_str->tellp() );
279 
280  std::ostringstream os; // tmp stream...
281  os << xref.size() << " 0 obj\n"
282  << " << /Type /Outlines\n"
283  << " /Count 0\n"
284  << " >>\n"
285  << "endobj\n";
286 
287  str->write( os.str().data(), os.str().size() );
288 
289  if ( traceLog() )
290  {
291  // Has binary data in it???
292  ossimNotify(ossimNotifyLevel_DEBUG) << os.str() << "\n";
293  }
294  }
295 }
296 #endif
297 
299  std::vector<std::streamoff>& xref )
300 {
301  // Write Pages object.
302  if ( str )
303  {
304  // Capture position:
305  xref.push_back( (std::streamoff)str->tellp() );
306 
308  os << xref.size() << " 0 obj\n"
309  << " << /Type /Pages\n"
310  << " /Kids [ " << xref.size()+1 << " 0 R ]\n" // Reference to Page.
311  << " /Count 1\n"
312  << " >>\n"
313  << "endobj\n";
314 
315  str->write( os.str().data(), os.str().size() );
316 
317  if ( traceLog() )
318  {
319  ossimNotify(ossimNotifyLevel_DEBUG) << os.str() << "\n";
320  }
321  }
322 }
323 
325  std::vector<std::streamoff>& xref )
326 {
327  // Write Pages object.
328  if ( str )
329  {
330  // Capture position:
331  xref.push_back( (std::streamoff)str->tellp() );
332 
334  os << xref.size() << " 0 obj % Document Information Dictionary\n";
335 
336  // Tile:
337  std::string s;
338  getTitle( s );
339  if ( s.size() )
340  {
341  os << " << /Title (" << s << ")\n";
342  }
343 
344  // Author:
345  getAuthor( s );
346  if ( s.size() )
347  {
348  os << " /Author (" << s << ")\n";
349  }
350 
351  // Creator:
352  getCreator( s );
353  if ( s.size() )
354  {
355  os << " /Creator (" << s << ")\n";
356  }
357 
358  // Producer:
359  getProducer( s );
360  if ( s.size() )
361  {
362  os << " /Producer (" << s << ")\n";
363  }
364 
365  // Creation date ( D : YYYYMMDDHHmmSSOHH ' mm ' ):
366  getCreationDate( s );
367  if ( s.size() )
368  {
369  os << " /CreationDate " << s << "\n";
370  }
371 
372  // Modification date ( D : YYYYMMDDHHmmSSOHH ' mm ' ):
373  getModDate( s );
374  if ( s.size() )
375  {
376  os << " /ModDate " << s << "\n";
377  }
378 
379  os << " >>\n"
380  << "endobj\n";
381 
382  str->write( os.str().data(), os.str().size() );
383 
384  if ( traceLog() )
385  {
386  ossimNotify(ossimNotifyLevel_DEBUG) << os.str() << "\n";
387  }
388  }
389 
390 } // End: ossimPdfWriter::writeInfo
391 
393 {
394  bool status = false;
395 
396  if ( str )
397  {
398 
399  //---
400  // This will remap input to eight bit if not already and make input one or
401  // three band depending on number of bands.
402  //---
403  setupInputChain();
404 
405  // Set the sequence tile size:
406  ossimIpt tileSize;
407  getTileSize( tileSize );
408  theInputConnection->setTileSize( tileSize );
409 
410  // Start the sequence at the first tile.
412 
413  const ossim_uint32 WIDTH = theAreaOfInterest.width();
414  const ossim_uint32 HEIGHT = theAreaOfInterest.height();
418 
419 #if 0 /* Please save for debug. (drb) */
422  << "\nBounding rect: " << theInputConnection->getBoundingRect()
423  << "\nAOI: " << theAreaOfInterest
424  << "\nBands: " << theInputConnection->getNumberOfOutputBands()
425  << "\ntilesWide: " << TW
426  << "\ntilesHigh: " << TH
427  << "\ntileWidth: " << tileWidth
428  << "\ntileHeight " << tileHeight << std::endl;
429 #endif
430 
431  if ( traceLog() )
432  {
433  ossimKeywordlist logKwl;
435  ossimFilename logFile = getFilename();
436  logFile.setExtension("log");
437  ossimKeywordlist kwl;
439  kwl.write(logFile.c_str() );
440  }
441 
442  // Cross reference(xref) table. Holds the offset of each object. Written at the end.
443  std::vector<std::streamoff> xref;
444 
445  //---
446  // Header:
447  //---
448  writeHeader( str );
449 
450  //---
451  // Catalog object:
452  //---
453  writeCatalog( str, xref );
454 
455  //---
456  // Outlines object:
457  //---
458  // writeOutlines( m_str, xref );
459 
460  //---
461  // Pages object:
462  //---
463  writePages( str, xref );
464 
465  //---
466  // Page object:
467  //---
468 
469  // Capture position:
470  xref.push_back( (std::streamoff)str->tellp() );
471 
472  std::ostringstream os1;
473  os1 << xref.size() << " 0 obj\n"
474  << " << /Type /Page\n"
475  << " /Parent " << xref.size()-1 << " 0 R\n" // Parent always one back.
476  << " /Resources " << xref.size()+1 << " 0 R\n" // Next object.
477  << " /MediaBox[0.0 0.0 " << WIDTH << " " << HEIGHT << "]\n"
478  // Contents = Resources_dictionary + tiles + base_form + 1):
479  << " /Contents[" << (xref.size()+TILES+3) << " 0 R]\n";
480 
482  if ( geom.valid() )
483  {
484  // Coordinate Transformation Matrix (CTM)
485  std::string lgiDictString;
486  getLgiDict( geom.get(), theAreaOfInterest, lgiDictString );
487 
488  if ( lgiDictString.size() )
489  {
490  os1 << lgiDictString;
491  }
492  }
493 
494  os1 << " >>\n"
495  << "endobj\n"; // Matches: <</Type /Page"
496 
497  str->write( os1.str().data(), os1.str().size() );
498  if ( traceLog() )
499  {
500  ossimNotify(ossimNotifyLevel_DEBUG) << os1.str() << "\n";
501  }
502 
503  // End /Page object
504 
505  //---
506  // Resource dictionary for page:
507  //---
508 
509  // Capture position:
510  xref.push_back( (std::streamoff)str->tellp() );
511 
513  os2 << xref.size() << " 0 obj % Resource dictionary for page.\n"
514  << " << /ProcSet[/PDF/ImageB/ImageC]\n"
515  << " /XObject << /Basemap_Form " << (xref.size()+TILES+1) << " 0 R ";
516 
517  // Write in the tiles:
518  ossim_uint32 objIndex = static_cast<ossim_uint32>(xref.size()+1);
521  for ( x = 0; x < TW; ++x )
522  {
523  for ( y = 0; y < TH; ++y )
524  {
525  os2 << getTileString( x, y ) << " " << objIndex << " 0 R ";
526 
527  ++objIndex;
528  }
529 
530  }
531  os2 << ">>\n" // Matches: /XObject<<
532  << " >>\nendobj\n"; // Matches: % Resources...";
533 
534  str->write( os2.str().data(), os2.str().size() );
535  if ( traceLog() )
536  {
537  ossimNotify(ossimNotifyLevel_DEBUG) << os2.str() << "\n";
538  }
539 
540  // End Resources dictionary.
541 
542  //---
543  // Now write the XObjects jpeg tiles:
544  //---
546  std::vector<ossimIrect> outputTileRects;
547  while ( tileNumber < TILES )
548  {
550  if( id.valid() )
551  {
552  // To hold output tile rect clamped to AOI.
553  ossimIrect outputTileRect;
554 
555  switch ( getImageType() )
556  {
557  case ossimPdfWriter::RAW:
558  {
559  writeRawTile( str, xref, id.get(), theAreaOfInterest, outputTileRect );
560  break;
561  }
563  default:
564  {
565  writeJpegTile( str, xref, id.get(), theAreaOfInterest, outputTileRect );
566  break;
567  }
568  }
569 
570  // Capture tile rect:
571  outputTileRects.push_back( outputTileRect );
572  }
573  else
574  {
576  << "ossimPdfWriter::writeImage ERROR:"
577  << "\nNULL Tile encountered, tile number=" << tileNumber
578  << std::endl;
579  status = false;
580  break;
581  }
582 
583  ++tileNumber;
584 
585  setPercentComplete( tileNumber / TILES * 100.0 );
586  }
587 
588  if ( tileNumber == TILES )
589  {
590  status = true;
591  }
592 
593  if ( status )
594  {
595  //---
596  // XObect Form for image tiles:
597  //---
598 
599  // Capture position:
600  xref.push_back( (std::streamoff)str->tellp() );
601 
602  ossimIpt llPageOffset;
603  getLowerLeftPageOffset( theAreaOfInterest, llPageOffset );
604 
605  std::ostringstream os3;
606 
607  // Tile loop - ontents for each ile:
608  tileNumber = 0;
609  ossim_uint32 x;
610  ossim_uint32 y;
611  for ( x = 0; x < TW; ++x )
612  {
613  for ( y = 0; y < TH; ++y )
614  {
615  //---
616  // PDF space is positive y = up, positive x = right.
617  // ossim image space is positive y down.
618  // 0, 0 is lower left corner in pdf space so "y of 0" in pdf space is
619  // theAreaOfInterest.ll().y in image space.
620  //---
621  ossim_int32 width = outputTileRects[tileNumber].width();
622 
623  ossim_int32 height = outputTileRects[tileNumber].height();
624 
625  ossim_int32 llOffsetX =
626  llPageOffset.x + outputTileRects[tileNumber].ll().x - theAreaOfInterest.ll().x;
627 
628  ossim_int32 llOffsetY = llPageOffset.y + theAreaOfInterest.lr().y -
629  outputTileRects[tileNumber].ll().y;
630 
631  os3 << " q\n" // Save graphics state
632  << " " << width << " 0 0 " << height << " "
633  << llOffsetX << " " << llOffsetY << " cm\n"
634  << " " << getTileString( x, y ) << " Do\n"
635  << " Q\n"; // Restore graphics state.
636  ++tileNumber;
637  }
638  }
639 
640  std::ostringstream os4;
641  os4 << xref.size() << " 0 obj % /XObject/Form dictionary for image tiles.\n"
642  << " << /Type /XObject\n"
643  << " /Subtype /Form\n"
644  << " /Length " << os3.str().size() << "\n"
645  << " /BBox["
646  << llPageOffset.x << " " << llPageOffset.y << " "
647  << WIDTH << " " << HEIGHT << "]\n"
648  << " >>\n"
649  << "stream\n";
650 
651  // Write the content stream to tmp stream.
652  os4.write( os3.str().data(), os3.str().size() );
653 
654  os4 << "\n"
655  << "endstream\n"
656  << "endobj\n";
657 
658  // Write the tmp stream to output stream.
659  str->write( os4.str().data(), os4.str().size() );
660 
661  if ( traceLog() )
662  {
664  << os4.str() << "\n";
665  }
666 
667  //---
668  // Contents of page:
669  //---
670 
671  // Capture position:
672  xref.push_back( (std::streamoff)str->tellp() );
673 
674  std::ostringstream os5;
675  os5 << "/Basemap_Form Do";
676 
677  std::ostringstream os6;
678  os6 << xref.size() << " 0 obj % Contents of page.\n"
679  << " << /Length " << os5.str().size() << " >>\n"
680  << "stream\n";
681 
682  os6.write( os5.str().data(), os5.str().size() );
683  os6 << "\n"
684  << "endstream\n"
685  << "endobj\n";
686 
687  str->write( os6.str().data(), os6.str().size() );
688  if ( traceLog() )
689  {
690  ossimNotify(ossimNotifyLevel_DEBUG) << os6.str() << "\n";
691  }
692 
693  m_mutex.lock(); // Code not thread safe.
694 
695  // Document Information dictionary:
696  writeInfo( str, xref );
697 
698  m_mutex.unlock();
699 
700  //---
701  // Cross reference tables:
702  //---
703 
704  // Capture start of xref for the second to last line:
705  std::streamoff xrefOffset = (std::streamoff)m_str->tellp();
706 
707  writeXref( m_str, xref );
708 
709  //---
710  // Trailer:
711  //---
712  writeTrailer( m_str, static_cast<ossim_uint32>(xref.size()+1), xrefOffset );
713  }
714 
715  } // Matches: if ( str ...
716 
717  return status;
718 
719 } // End: ossimPdfWriter::writeImage
720 
722  std::vector<std::streamoff>& xref,
723  ossimImageData* id,
724  const ossimIrect& aoi,
725  ossimIrect& outputTileRect )
726 {
727  //---
728  // Most of code and comments below are from jpeg-6b "example.c" file. See
729  // http://www4.cs.fau.de/Services/Doc/graphics/doc/jpeg/libjpeg.html
730  //---
731 
732  //---
733  // Initialize JPEG compression library:
734  // Note: JDIMENSION is typedefed to an unsigned int.
735  //---
736  struct jpeg_compress_struct cinfo;
737  struct jpeg_error_mgr jerr;
738  cinfo.err = jpeg_std_error( &jerr );
739  jpeg_create_compress(&cinfo);
740 
741  //---
742  // Need to define a custom ostream destination manager for jpeglib to write compressed block:
743  // Note: Write the tile to a temp memory stream to get the size up front.
744  //---
745  std::ostringstream tileStream;
746  jpeg_cpp_stream_dest(&cinfo, tileStream);
747 
748 
749  // Setting the parameters of the output file here.
750  const ossim_uint32 BANDS = id->getNumberOfBands();
751  const ossim_uint32 TW = id->getWidth();
752  const ossim_uint32 TH = id->getHeight();
753 
754 
755  // Assign width, height clamping to the aoi.
756  cinfo.image_width = ossim::min<ossim_uint32>(
757  TW, aoi.lr().x - id->getOrigin().x + 1 );
758  cinfo.image_height = ossim::min<ossim_uint32>(
759  TH, aoi.lr().y - id->getOrigin().y + 1 );
760  cinfo.input_components = BANDS;
761 
762  // Capture the output tile rect:
763  outputTileRect = ossimIrect( id->getOrigin(),
764  ossimIpt( id->getOrigin().x + cinfo.image_width - 1,
765  id->getOrigin().y + cinfo.image_height - 1 ) );
766 
767  // colorspace of input image
768  if ( BANDS == 3 )
769  {
770  cinfo.in_color_space = JCS_RGB;
771  }
772  else
773  {
774  cinfo.in_color_space = JCS_GRAYSCALE;
775  }
776 
777  // Default compression parameters...
778  jpeg_set_defaults( &cinfo );
779 
780  /* Now do the compression .. */
781  jpeg_start_compress( &cinfo, TRUE );
782 
783  // Compress the tile on line at a time:
784  JSAMPLE** samp_array = new JSAMPLE* [cinfo.image_height];
785 
786  //---
787  // Get a pointer to the source data.
788  // Needs to be band interleaved by pixel(BIP), so convert if needed.
789  //---
790  ossimRefPtr<ossimImageData> tempTile = 0;
791  ossim_uint8* tile = 0;
792  if ( ( BANDS == 1 ) &&
793  ( cinfo.image_width == id->getWidth() ) &&
794  ( cinfo.image_height == id->getHeight() ) )
795  {
796  tile = id->getUcharBuf();
797  }
798  else
799  {
800  // Convert from OSSIM's native BSQ interleave to BIP.
801  tempTile = new ossimImageData(
802  0, OSSIM_UINT8, BANDS, cinfo.image_width, cinfo.image_height );
803  tempTile->setOrigin( id->getOrigin() );
804  tempTile->initialize();
805  tile = tempTile->getUcharBuf();
806  id->unloadTile( tile, tempTile->getImageRectangle(), OSSIM_BIP );
807  }
808 
809  for ( ossim_uint32 row=0; row<cinfo.image_height; ++row )
810  {
811  samp_array[row] = (JSAMPLE*) tile + row*cinfo.input_components*cinfo.image_width;
812  }
813 
814  jpeg_write_scanlines( &cinfo, samp_array, cinfo.image_height );
815 
816  //---
817  // Clean up after done compressing:
818  // Note: MUST do before writing to output stream below.
819  //---
820  jpeg_finish_compress( &cinfo );
821  jpeg_destroy_compress( &cinfo );
822  delete [] samp_array;
823  samp_array = 0;
824 
825  // Capture position:
826  xref.push_back( (std::streamoff)str->tellp() );
827 
828  std::ostringstream os1;
829  os1 << xref.size() << " 0 obj\n"
830  << " << /Type /XObject\n"
831  << " /Subtype /Image\n"
832  << " /Length " << tileStream.str().size() << "\n"
833  << " /Filter[/DCTDecode]\n"
834  << " /BitsPerComponent 8"
835  << " /ColorSpace " << (BANDS==1?"/DeviceGray\n":"/DeviceRGB\n")
836  << " /Width " << cinfo.image_width
837  << " /Height " << cinfo.image_height
838  << " >>\n"
839  << "stream\n";
840 
841  str->write( os1.str().data(), os1.str().size() );
842 
843  if ( traceLog() )
844  {
846  << os1.str()
847  << "*** image stream not displayed ***\n"
848  << "endstream\n"
849  << "endobj\n\n";
850  }
851 
852  // Write the image tile from memory to output stream.
853  str->write( tileStream.str().data(), tileStream.str().size() );
854 
855  // Close out stream object.
856  *str << "\n"
857  << "endstream\n"
858  << "endobj\n";
859 
860 } // End: ossimPdfWriter::writeJpegTile( ... )
861 
863  std::vector<std::streamoff>& xref,
864  ossimImageData* id,
865  const ossimIrect& aoi,
866  ossimIrect& outputTileRect )
867 {
868  const ossim_uint32 BANDS = id->getNumberOfBands();
869  const ossim_uint32 TW = id->getWidth();
870  const ossim_uint32 TH = id->getHeight();
871 
872  // Assign width, height clamping to the aoi.
873  ossim_uint32 width = ossim::min<ossim_uint32>(
874  TW, aoi.lr().x - id->getOrigin().x + 1 );
875  ossim_uint32 height = ossim::min<ossim_uint32>(
876  TH, aoi.lr().y - id->getOrigin().y + 1 );
877 
878  // Capture the output tile rect:
879  outputTileRect = ossimIrect( id->getOrigin(),
880  ossimIpt( id->getOrigin().x + width - 1,
881  id->getOrigin().y + height - 1 ) );
882 
883  //---
884  // Get a pointer to the source data.
885  // Needs to be band interleaved by pixel(BIP), so convert if needed.
886  //---
887  ossimRefPtr<ossimImageData> tempTile = 0;
888  ossim_uint8* tile = 0;
889  ossim_uint32 length = 0;
890  if ( ( BANDS == 1 ) && ( width == id->getWidth() ) && ( height == id->getHeight() ) )
891  {
892  tile = id->getUcharBuf();
893  length = id->getSizeInBytes();
894  }
895  else
896  {
897  // Convert from OSSIM's native BSQ interleave to BIP.
898  tempTile = new ossimImageData( 0, OSSIM_UINT8, BANDS, width, height );
899  tempTile->setOrigin( id->getOrigin() );
900  tempTile->initialize();
901  tile = tempTile->getUcharBuf();
902  id->unloadTile( tile, tempTile->getImageRectangle(), OSSIM_BIP );
903  length = tempTile->getSizeInBytes();
904  }
905 
906  // Capture position:
907  xref.push_back( (std::streamoff)str->tellp() );
908 
909  std::ostringstream os1;
910  os1 << xref.size() << " 0 obj\n"
911  << " << /Type /XObject\n"
912  << " /Subtype /Image\n"
913  << " /Length " << length << "\n"
914  << " /BitsPerComponent 8"
915  << " /ColorSpace " << (BANDS==1?"/DeviceGray\n":"/DeviceRGB\n")
916  << " /Width " << width
917  << " /Height " << height
918  << " >>\n"
919  << "stream\n";
920 
921  str->write( os1.str().data(), os1.str().size() );
922 
923  if ( traceLog() )
924  {
926  << os1.str()
927  << "*** image stream not displayed ***\n"
928  << "endstream\n"
929  << "endobj\n\n";
930  }
931 
932  // Write the image tile from memory to output stream.
933  str->write( (char*)tile, length );
934 
935  // Close out stream object.
936  *str << "\n"
937  << "endstream\n"
938  << "endobj\n";
939 
940 } // End ossimPdfWriter::writeRawTile( ... )
941 
943  const std::vector<std::streamoff>& xref )
944 {
945  if ( str )
946  {
948  os << "xref\n"
949  << "0 " << (xref.size()+1) << "\n"
950  << "0000000000 65535 f \n";
951 
952  std::vector<std::streamoff>::const_iterator i = xref.begin();
953  while ( i != xref.end() )
954  {
955  os << std::setiosflags(std::ios_base::fixed|std::ios_base::right)
956  << std::setfill('0')
957  << std::setw(10)
958  << (*i)
959  << " 00000 n \n";
960  ++i;
961  }
962 
963  // os << "\n";
964 
965  str->write( os.str().data(), os.str().size() );
966 
967  if ( traceLog() )
968  {
969  ossimNotify(ossimNotifyLevel_DEBUG) << os.str() << "\n";
970  }
971  }
972 }
973 
975  ossim_uint32 entrySize,
976  std::streamoff xrefOffset )
977 {
978  if ( str )
979  {
981  os << "trailer\n"
982  << " << /Size " << entrySize << "\n"
983  << " /Root 1 0 R\n"
984  << " /Info " << entrySize-1 << " 0 R\n"
985  << " >>\n"
986  << "startxref\n"
987  << xrefOffset << "\n"
988  << "%%EOF\n";
989  // << "%%EOF";
990 
991  str->write( os.str().data(), os.str().size() );
992 
993  if ( traceLog() )
994  {
995  ossimNotify(ossimNotifyLevel_DEBUG) << os.str() << "\n";
996  }
997  }
998 }
999 
1000 #if 0
1001 void ossimPdfWriter::writeDummy( std::ostream* str,
1002  std::vector<std::streamoff>& xref )
1003 {
1004  // Write a blank object.
1005  if ( str )
1006  {
1007  // Capture position:
1008  xref.push_back( (std::streamoff)str->tellp() );
1009 
1010  std::ostringstream os;
1011  os << xref.size() << " 0 obj % dummy\n"
1012  << "endobj\n";
1013 
1014  str->write( os.str().data(), os.str().size() );
1015 
1016  if ( traceLog() )
1017  {
1018  ossimNotify(ossimNotifyLevel_DEBUG) << os.str() << "\n";
1019  }
1020  }
1021 }
1022 #endif
1023 
1025  const char* prefix)const
1026 {
1027  return ossimImageFileWriter::saveState(kwl, prefix);
1028 }
1029 
1031  const char* prefix)
1032 {
1033  return ossimImageFileWriter::loadState(kwl, prefix);
1034 }
1035 
1037 {
1038  bool result = false;
1039  if (m_str)
1040  {
1041  const std::ofstream* fs = dynamic_cast<const std::ofstream*>(m_str);
1042  if ( fs )
1043  {
1044  result = fs->is_open();
1045  }
1046  else
1047  {
1048  // Pointer good enough...
1049  result = true;
1050  }
1051  }
1052  return result;
1053 }
1054 
1055 
1057 {
1058  bool result = false;
1059 
1060  close();
1061 
1062  // Check for empty filenames.
1063  if (theFilename.size())
1064  {
1065  std::ofstream* os = new std::ofstream();
1066  os->open(theFilename.c_str(), ios::out | ios::binary);
1067  if(os->is_open())
1068  {
1069  m_str = os;
1070  m_ownsStream = true;
1071  result = true;
1072  }
1073  else
1074  {
1075  delete os;
1076  os = 0;
1077  }
1078  }
1079  return result;
1080 }
1081 
1083 {
1084  if (m_str)
1085  {
1086  m_str->flush();
1087 
1088  if (m_ownsStream)
1089  {
1090  delete m_str;
1091  m_str = 0;
1092  m_ownsStream = false;
1093  }
1094  }
1095 }
1096 
1097 void ossimPdfWriter::getImageTypeList(std::vector<ossimString>& imageTypeList)const
1098 {
1099  imageTypeList.push_back(ossimString("ossim_pdf"));
1100 }
1101 
1103 {
1104  return ossimString("pdf");
1105 }
1106 
1107 bool ossimPdfWriter::hasImageType(const ossimString& imageType) const
1108 {
1109  bool result = false;
1110  if ( (imageType == "ossim_pdf") || (imageType == "image/pdf")||(imageType == "application/pdf") )
1111  {
1112  result = true;
1113  }
1114  return result;
1115 }
1116 
1118 {
1119  if ( property.valid() )
1120  {
1121  std::string name = property->getName().string();
1122  if ( name.size() )
1123  {
1124  if ( ( name == ossimKeywordNames::IMAGE_TYPE_KW ) ||
1125  ( name == AUTHOR_KW ) ||
1126  ( name == CREATOR_KW ) ||
1127  ( name == CREATION_DATE_KW ) ||
1128  ( name == KEYWORDS_KW ) ||
1129  ( name == MOD_DATE_KW ) ||
1131  ( name == PRODUCER_KW ) ||
1132  ( name == SUBJECT_KW ) ||
1133  ( name == TITLE_KW ) )
1134  {
1135  addOption( name, property->valueToString().string() );
1136  }
1137  else
1138  {
1140  }
1141  }
1142  }
1143 
1144 } // ossimPdfWriter::setProperty
1145 
1147 {
1148  ossimRefPtr<ossimProperty> prop = 0;
1149 
1150  if ( name.size() )
1151  {
1152  if ( name == AUTHOR_KW )
1153  {
1154  ossimString value;
1155  getAuthor( value.string() );
1157  new ossimStringProperty( name, value, true);
1158  prop = stringProp.get();
1159  }
1160  else if ( name == CREATOR_KW )
1161  {
1162  ossimString value;
1163  getCreator( value.string() );
1165  new ossimStringProperty( name, value, true);
1166  prop = stringProp.get();
1167  }
1168  else if ( name == CREATION_DATE_KW )
1169  {
1170  ossimString value;
1171  getCreationDate( value.string() );
1173  new ossimStringProperty( name, value, true);
1174  prop = stringProp.get();
1175  }
1176  else if ( name == ossimKeywordNames::IMAGE_TYPE_KW )
1177  {
1178  ossimString value;
1179  getImageType( value.string() );
1181  new ossimStringProperty( name, value, false); // editable flag = false
1182 
1183  // Alway support jpeg.
1184  stringProp->addConstraint( ossimString("jpeg") );
1185 
1186  // Alway support raw (general raster).
1187  stringProp->addConstraint( ossimString("raw") );
1188 
1189  prop = stringProp.get();
1190  }
1191  else if ( name == KEYWORDS_KW )
1192  {
1193  ossimString value;
1194  getKeywords( value.string() );
1196  new ossimStringProperty( name, value, true);
1197  prop = stringProp.get();
1198  }
1199  else if ( name == MOD_DATE_KW )
1200  {
1201  ossimString value;
1202  getModDate( value.string() );
1204  new ossimStringProperty( name, value, true);
1205  prop = stringProp.get();
1206  }
1207  else if( name == ossimKeywordNames::OUTPUT_TILE_SIZE_KW )
1208  {
1209  ossimString value;
1210  getTileSize( value.string() );
1212  new ossimStringProperty( name, value, false);
1213  stringProp->addConstraint(ossimString("16"));
1214  stringProp->addConstraint(ossimString("32"));
1215  stringProp->addConstraint(ossimString("64"));
1216  stringProp->addConstraint(ossimString("128"));
1217  stringProp->addConstraint(ossimString("256"));
1218  stringProp->addConstraint(ossimString("512"));
1219  stringProp->addConstraint(ossimString("1024"));
1220  stringProp->addConstraint(ossimString("2048"));
1221  prop = stringProp.get();
1222  }
1223  else if ( name == SUBJECT_KW )
1224  {
1225  ossimString value;
1226  getSubject( value.string() );
1228  new ossimStringProperty( name, value, true);
1229  prop = stringProp.get();
1230  }
1231  else if ( name == TITLE_KW )
1232  {
1233  ossimString value;
1234  getSubject( value.string() );
1236  new ossimStringProperty( name, value, true);
1237  prop = stringProp.get();
1238  }
1239  else
1240  {
1241  prop = ossimImageFileWriter::getProperty(name);
1242  }
1243  }
1244 
1245  return prop;
1246 
1247 } // End: ossimPdfWriter::getProperty
1248 
1249 void ossimPdfWriter::getPropertyNames(std::vector<ossimString>& propertyNames)const
1250 {
1251  propertyNames.push_back( ossimString( AUTHOR_KW ) );
1252  propertyNames.push_back( ossimString( CREATOR_KW ) );
1253  propertyNames.push_back( ossimString( CREATION_DATE_KW ) );
1254  propertyNames.push_back( ossimString( ossimKeywordNames::IMAGE_TYPE_KW ) );
1255  propertyNames.push_back( ossimString( KEYWORDS_KW ) );
1256  propertyNames.push_back( ossimString( MOD_DATE_KW ) );
1257  propertyNames.push_back( ossimString( ossimKeywordNames::OUTPUT_TILE_SIZE_KW ) );
1258  propertyNames.push_back( ossimString( PRODUCER_KW ) );
1259  propertyNames.push_back( ossimString( SUBJECT_KW ) );
1260  propertyNames.push_back( ossimString( TITLE_KW ) );
1261 
1263 }
1264 
1266 {
1267  if (m_ownsStream && m_str)
1268  {
1269  delete m_str;
1270  }
1271  m_str = &stream;
1272  m_ownsStream = false;
1273  return true;
1274 }
1275 
1277 {
1278  if ( theInputConnection.get() )
1279  {
1280  // Capture the input to the image source sequencer(theInputConnection).
1282 
1285 
1286  if( inputScalar != OSSIM_UINT8 )
1287  {
1288  // Make eight bit.
1289  if (traceDebug())
1290  {
1292  << "ossimPdfWriter::setupInputChain WARNING:"
1293  << "\nData is being scaled to 8 bit!"
1294  << "\nOriginal scalar type: "
1296  getEntryString(inputScalar).c_str()
1297  << std::endl;
1298  }
1299 
1300  //---
1301  // Attach a scalar remapper to the end of the input chain. This will
1302  // need to be unattached and deleted at the end of this.
1303  //---
1305 
1306  // Connect remapper's input to sequencer input.
1308 
1309  // Connet sequencer to remapper.
1311 
1312  // Initialize connections.
1314  }
1315 
1316  // Must be one or three band. Note bands are zero based...
1317  if ( ( bands != 1 ) && ( bands != 3 ) )
1318  {
1319  std::vector<ossim_uint32> bandList;
1320 
1321  // Always have one band.
1322  bandList.push_back( 0 );
1323 
1324  if ( bands > 3 )
1325  {
1326  // Use the first three bands.
1327  bandList.push_back( 1 );
1328  bandList.push_back( 2 );
1329  }
1330 
1331  if (traceDebug())
1332  {
1334  << "ossimPdfWriter::setupInputChain WARNING:"
1335  << "\nOutput bands must be 1 or 3 and are being filterd!"
1336  << "\nOriginal band count: " << bands
1337  << "\nNew band count: " << bandList.size()
1338  << std::endl;
1339  }
1340 
1342 
1343  // Set the the band selector list.
1344  bs->setOutputBandList( bandList );
1345 
1346  // Connect band selector's input to sequencer input.
1348 
1349  // Connet sequencer to band selector.
1351 
1352  // Initialize connections.
1354  }
1355 
1356  if ( m_savedInput != theInputConnection->getInput( 0 ) )
1357  {
1358  //---
1359  // If the input to the image source sequencer change the AOI
1360  // MUST be reset as it gets wiped.
1361  //---
1363  }
1364 
1365  } // Matches: if ( theInputConnection )
1366 
1367 } // End: void ossimPdfWriter::setupInputChain()
1368 
1370 {
1372 
1373  // Get the type and downcase.
1374  ossimString os;
1375  getImageType( os.string() );
1376  os.downcase();
1377 
1378  if ( os == "jpeg" )
1379  {
1380  result = ossimPdfWriter::JPEG;
1381  }
1382  else if ( os == "raw" )
1383  {
1384  result = ossimPdfWriter::RAW;
1385  }
1386  else
1387  {
1388  // Unknown value:
1390  << "ossimPdfWriter::getImageCompression WARN\n"
1391  << "Unhandled image compression type: " << os << std::endl;
1392  }
1393  return result;
1394 }
1395 
1396 void ossimPdfWriter::getImageType( std::string& type ) const
1397 {
1398  type = m_kwl->findKey( std::string(ossimKeywordNames::IMAGE_TYPE_KW) );
1399  if ( type.empty() )
1400  {
1401  type = "jpeg"; // default
1402  }
1403 }
1404 
1405 void ossimPdfWriter::addOption( const std::string& key, const std::string& value )
1406 {
1407  m_mutex.lock();
1408  if ( m_kwl.valid() )
1409  {
1410  if ( key.size() && value.size() )
1411  {
1412  m_kwl->addPair( key, value );
1413  }
1414  }
1415  m_mutex.unlock();
1416 }
1417 
1418 #if 0
1419 void ossimPdfWriter::getMediaBoxSize( ossim_uint32 imageWidth,
1420  ossim_uint32 imageHeight,
1421  ossimIpt& size ) const
1422 {
1423  //---
1424  // This could be an option / property.
1425  // 612 x 792 = 8.5 x 11 inches at 72 dots per inch (612/72 x 792/72)
1426  //---
1427  size.x = static_cast<ossim_uint32>(imageWidth);
1428  size.y = static_cast<ossim_uint32>(imageHeight);
1429 }
1430 #endif
1431 
1433 {
1434  if ( aoi.hasNans() == false )
1435  {
1436  // Get the page size.
1437  // ossimIpt mediaBoxSize;
1438  // getMediaBoxSize( mediaBoxSize );
1439 
1440  // Temp hard coded. (drb)
1441  offset.x = 0;
1442  offset.y = 0;
1443  }
1444  else
1445  {
1446  offset.x = 0;
1447  offset.y = 0;
1448  }
1449 }
1450 
1452  const ossimIrect& aoi,
1453  std::string& s ) const
1454 {
1455  s.clear(); // Empty string indicates error.
1456 
1457  if ( geom && !aoi.hasNans() )
1458  {
1459  // Coordinate Transformation Matrix (CTM)
1460  std::string ctmString;
1461  getLgiDictCtm( geom, aoi, ctmString );
1462 
1463  if ( ctmString.size() )
1464  {
1465  // ProjectionType
1466  std::string projectionString;
1467  getLgiDictProjection( geom, projectionString );
1468 
1469  if ( projectionString.size() )
1470  {
1471  //---
1472  // Neatline: Not required for single frame.
1473  // std::string neatLineString;
1474  // getLgiDictNeatline( geom, neatLineString );
1475  //---
1476 
1477  // if ( neatLineString.size() )
1478  // {
1479  // cout << "d..." << endl;
1480 
1481  // Description
1482  std::string descriptionString;
1483  getLgiDictDescription( geom, descriptionString );
1484 
1485  if ( descriptionString.size() )
1486  {
1487  std::ostringstream os;
1488  os << "/LGIDict"
1489  << "[<<"
1490  << ctmString
1491  << "/Version(2.1)"
1492  << projectionString
1493  // << neatLineString
1494  << descriptionString
1495  << "/Type/LGIDict>>]";
1496 
1497  s = os.str();
1498  // }
1499  }
1500  }
1501  }
1502  }
1503 
1504 } // End: ossimPdfWriter::getLgiDictString
1505 
1507  std::string& s ) const
1508 {
1509  s.clear();
1510  if ( geom )
1511  {
1513  if ( mapProj.valid() )
1514  {
1515  const ossimDatum* datum = mapProj->getDatum();
1516  if ( datum )
1517  {
1518  s = "/Datum(";
1519  s += datum->code().string();
1520  s += ")";
1521  }
1522  }
1523  }
1524 
1525 } // End: ossimPdfWriter::getLgiDictDatum
1526 
1528  std::string& s ) const
1529 {
1530  s.clear();
1531  if ( geom )
1532  {
1534  if ( mapProj.valid() )
1535  {
1536  const ossimDatum* datum = mapProj->getDatum();
1537  if ( datum )
1538  {
1539  std::string code = datum->code().string();
1540 
1541  if ( code == "WGE" )
1542  {
1543  s = "/Description(WGS 84)";
1544  }
1545  }
1546  }
1547  }
1548 
1549 } // End: ossimPdfWriter::getLgiDictDescription
1550 
1551 #if 0
1552 void ossimPdfWriter::getLgiDictNeatline( ossimImageGeometry* geom,
1553  std::string& s ) const
1554 {
1555  s.clear();
1556  if ( geom )
1557  {
1558  std::ostringstream os;
1559 
1560  // Tmp drb...
1561  os << "/Neatline[(0.0000000000)(0.0000000000)(0.0000000000)(718.0800000000)(609.8400000000)(718.0800000000)(609.8400000000)(0.0000000000)]";
1562 
1563  s = os.str();
1564  }
1565 
1566 } // End: ossimPdfWriter::getLgiDictNeatline
1567 #endif
1568 
1570  std::string& s ) const
1571 {
1572  s.clear(); // Empty string indicates error.
1573 
1574  // Projection:
1575  std::string projType;
1576  getLgiDictProjectionType( geom, projType );
1577 
1578  // Datum:
1579  std::string datumString;
1580  getLgiDictDatum( geom, datumString );
1581 
1582  // Description
1583  std::string descriptionString;
1584  getLgiDictDescription( geom, descriptionString );
1585 
1586  if ( projType.size() && datumString.size() )
1587  {
1588  std::ostringstream os;
1589  os << "/Projection<<"
1590  << projType
1591  << descriptionString
1592  << datumString
1593  << "/Type/Projection>>"
1594  << "/Display<<"
1595  << projType
1596  << descriptionString
1597  << datumString
1598  << "/Type/Projection>>";
1599 
1600  s = os.str();
1601  }
1602 
1603 } // End: ossimPdfWriter::getLgiDictProjection
1604 
1606  const ossimIrect& aoi,
1607  std::string& s ) const
1608 {
1609  s.clear(); // Empty string indicates error.
1610 
1611  ossimDpt scale;
1612  scale.makeNan();
1613  ossimDpt dTie;
1614  dTie.makeNan();
1615 
1617  if ( proj.valid() )
1618  {
1619  ossimRefPtr<ossimMapProjection> mapProj = dynamic_cast<ossimMapProjection*>( proj.get() );
1620  if ( mapProj.valid() )
1621  {
1622  if ( mapProj->isGeographic() )
1623  {
1624  // Degrees per pixel.
1625  geom->getDegreesPerPixel( scale );
1626 
1627  if ( !scale.hasNans() )
1628  {
1629  // Tie point: Lat, lon of lower left corner.
1630  ossimGpt gTie;
1631  geom->localToWorld( ossimDpt( aoi.ll() ), gTie );
1632 
1633  // Check just lat and lon disregard height.
1634  if ( !ossim::isnan(gTie.lon) && !ossim::isnan(gTie.lon) )
1635  {
1636  dTie.x = gTie.lon;
1637  dTie.y = gTie.lat;
1638  }
1639  }
1640  }
1641  }
1642  }
1643 
1644  if ( !scale.hasNans() && !dTie.hasNans() )
1645  {
1646  //---
1647  // Example string:
1648  // (0.0000381944)(0.0000000000)(0.0000000000)(0.0000381944)(-77.0558525000)(38.8388091667)
1649  // NOTE: (0,0) is lower left corner in pdf space.
1650  ossim_float64 d = 0.0;
1651  std::ostringstream os;
1652  os << setprecision(15) // Not sure if this should be 10??? (drb)
1653  << std::setiosflags(std::ios_base::fixed|std::ios_base::right)
1654  << std::setfill('0')
1655  << "/CTM[(" << scale.x << ")(" << d << ")(" << d << ")("
1656  << scale.y << ")(" << dTie.x << ")(" << dTie.y << ")]";
1657 
1658  s = os.str();
1659  }
1660 
1661 } // End: ossimPdfWriter::getCtmString
1662 
1664 {
1665  //---
1666  // Initialize the projection string from geometry:
1667  // Currently only coded for geographic and UTM projection.
1668  //---
1669 
1670  s.clear(); // Empty string indicates error.
1671 
1672  if ( geom )
1673  {
1675  if ( mapProj.valid() )
1676  {
1677  if ( mapProj->isGeographic() )
1678  {
1679  s = "/ProjectionType(GEOGRAPHIC)";
1680  }
1681  else
1682  {
1683  // Check for UTM:
1685  dynamic_cast<const ossimUtmProjection*>( mapProj.get() );
1686  if ( utmProj.valid() )
1687  {
1688  ossim_int32 zone = utmProj->getZone();
1689  char hemisphere = utmProj->getHemisphere();
1690  std::ostringstream os;
1691  os << "/ProjectionType(UT)"
1692  << "/Zone(" << zone << ")"
1693  << "/Hemisphere(" << hemisphere << ")";
1694  s = os.str();
1695  }
1696  }
1697  }
1698 
1699  } // Matches if ( geom )
1700 
1701 } // End: ossimPdfWriter::getProjectionType
1702 
1704 {
1705  ossim_uint32 code = 32767;
1706  if ( geom )
1707  {
1709  if ( proj.valid() )
1710  {
1711  // Map projection:
1713  dynamic_cast<const ossimMapProjection*>( proj.get() );
1714 
1715  if ( mapProj.valid() )
1716  {
1717  code = mapProj->getPcsCode();
1718  }
1719  }
1720  }
1721  return code;
1722 }
1723 
1724 #if 0
1725 void ossimPdfWriter::getNumberOfTiles( ossim_uint32 imageWidth,
1726  ossim_uint32 imageHeight,
1727  ossimIpt size ) const
1728 {
1729  const ossim_int32 DEFAULT_TILE_DIMENSION = 1024;
1730 
1731  size.x = imageWidth / DEFAULT_TILE_DIMENSION;
1732  size.y = imageHeight / DEFAULT_TILE_DIMENSION;
1733 
1734  if ( imageWidth % DEFAULT_TILE_DIMENSION )
1735  {
1736  ++size.x;
1737  }
1738  if ( imageHeight % DEFAULT_TILE_DIMENSION )
1739  {
1740  ++size.y;
1741  }
1742 
1743 } // End: getNumberOfTiles( ... )
1744 #endif
1745 
1746 void ossimPdfWriter::getTitle( std::string& s ) const
1747 {
1748  // Check if in keyword list.
1749  s = m_kwl->findKey( TITLE_KW );
1750 
1751  if ( s.empty() )
1752  {
1753  if ( theFilename.size() )
1754  {
1755  // Set to basename of file.
1756  s = theFilename.file().string();
1757  }
1758  }
1759 }
1760 
1761 void ossimPdfWriter::getAuthor( std::string& s ) const
1762 {
1763  // Check if in keyword list.
1764  s = m_kwl->findKey( AUTHOR_KW );
1765 
1766  if ( s.empty() )
1767  {
1768  s = "ossim"; // Default: ???
1769  }
1770 }
1771 
1772 void ossimPdfWriter::getSubject( std::string& s ) const
1773 {
1774  // Check if in keyword list.
1775  s = m_kwl->findKey( SUBJECT_KW );
1776 }
1777 
1778 void ossimPdfWriter::getKeywords( std::string& s ) const
1779 {
1780  // Check if in keyword list.
1781  s = m_kwl->findKey( KEYWORDS_KW );
1782 }
1783 
1784 void ossimPdfWriter::getCreator( std::string& s ) const
1785 {
1786  // Check if in keyword list.
1787  s = m_kwl->findKey( CREATOR_KW );
1788 
1789  if ( s.empty() )
1790  {
1791  s = "ossim"; // Default: ???
1792  }
1793 }
1794 
1795 void ossimPdfWriter::getProducer( std::string& s ) const
1796 {
1797  // Check if in keyword list.
1798  s = m_kwl->findKey( PRODUCER_KW );
1799 
1800  if ( s.empty() )
1801  {
1802  s = "ossim"; // Default: ???
1803  }
1804 }
1805 
1806 void ossimPdfWriter::getCreationDate( std::string& s ) const
1807 {
1808  // Check if in keyword list.
1809  s = m_kwl->findKey( CREATION_DATE_KW );
1810 
1811  if ( s.empty() )
1812  {
1813  getGmtDate( s );
1814  }
1815 }
1816 
1817 void ossimPdfWriter::getModDate( std::string& s ) const
1818 {
1819  // Check if in keyword list.
1820  s = m_kwl->findKey( MOD_DATE_KW );
1821 
1822  if ( s.empty() )
1823  {
1824  getGmtDate( s );
1825  }
1826 }
1827 
1828 void ossimPdfWriter::getGmtDate( std::string& s ) const
1829 {
1830  // Get the time:
1831  time_t now;
1832  time(&now);
1833 
1834  // Convert to UTC:
1835  tm* gt = gmtime(&now);
1836 
1837  if ( gt )
1838  {
1839  //---
1840  // Format(26 charactors including trailing null):
1841  // (D:YYYYMMDDHHmmSSZ00'00')
1842  char dateChars[26];
1843  dateChars[25] = '\0';
1844  strftime(dateChars, 26, "(D:%Y%m%d%H%M%SZ00'00')", gt);
1845  s = dateChars;
1846  }
1847 
1848 } // End: ossimPdfWriter::getGmtDate
1849 
1850 void ossimPdfWriter::getTileSize( std::string& s ) const
1851 {
1852  // Check if in keyword list.
1853  s = m_kwl->findKey( std::string( ossimKeywordNames::OUTPUT_TILE_SIZE_KW ) );
1854  if ( s.empty() )
1855  {
1856  ossimIpt tileSize;
1857  ossim::defaultTileSize( tileSize );
1858  s = ossimString::toString( tileSize.x ).string();
1859  }
1860 }
1861 
1862 void ossimPdfWriter::getTileSize( ossimIpt& tileSize ) const
1863 {
1864  std::string s;
1865  getTileSize( s );
1866  if ( s.size() )
1867  {
1868  tileSize.x = ossimString(s).toInt32();
1869  }
1870  else
1871  {
1872  tileSize.x = 1024; // default
1873  }
1874  tileSize.y = tileSize.x;
1875 }
1876 
1878 {
1879  // Format like: /Tile_0001_0002
1880  std::ostringstream os;
1881  os << std::setiosflags(std::ios_base::fixed|std::ios_base::right)
1882  << std::setfill('0')
1883  << "/Tile_"
1884  << std::setw(4) << x
1885  << "_"
1886  << std::setw(4) << y;
1887 
1888  return os.str();
1889 }
std::ostringstream os2
virtual void valueToString(ossimString &valueResult) const =0
virtual ossim_uint32 getWidth() const
ossim_uint32 x
void writeHeader(std::ostream *str)
Writes header.
void writeTrailer(std::ostream *str, ossim_uint32 entrySize, std::streamoff xrefOffset)
Writes trailer.
ossimPdfWriter()
default constructor
void getLgiDict(ossimImageGeometry *geom, const ossimIrect &aoi, std::string &s) const
Get the LGIDict string.
std::basic_ostringstream< char > ostringstream
Class for char output memory streams.
Definition: ossimIosFwd.h:35
virtual ossimString getClassName() const
void getCreator(std::string &s) const
Gets the Creator.
ossim_uint32 tileNumber
virtual ossimString getShortName() const
virtual const ossim_uint8 * getUcharBuf() const
Represents serializable keyword/value map.
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.
ossim_uint32 y
static const char * OUTPUT_TILE_SIZE_KW
bool valid() const
Definition: ossimRefPtr.h:75
virtual bool writeStream()
Method to write the image to a stream.
const ossimMapProjection * getAsMapProjection() const
virtual ossim_uint32 getPcsCode() const
Returns the EPSG PCS code or 32767 if the projection is a custom (non-EPSG) projection.
virtual bool setOutputStream(std::ostream &stream)
Sets the output stream to write to.
std::string getTileString(ossim_uint32 x, ossim_uint32 y) const
void getLowerLeftPageOffset(const ossimIrect &aoi, ossimIpt &offset) const
Gets the page size.
std::mutex m_mutex
void writeXref(std::ostream *str, const std::vector< std::streamoff > &xref)
Writes Cross Reference(xref) section.
virtual bool loadState(const ossimKeywordlist &kwl, const char *prefix=0)
double y
Definition: ossimDpt.h:165
ossim_uint32 height() const
Definition: ossimIrect.h:487
virtual ossimRefPtr< ossimImageData > getNextTile(ossim_uint32 resLevel=0)
void getTitle(std::string &s) const
Gets the Title.
virtual bool saveState(ossimKeywordlist &kwl, const char *prefix=0) const
ossimIrect theAreaOfInterest
virtual const ossimString & code() const
Definition: ossimDatum.h:57
static ossimString toString(bool aValue)
Numeric to string methods.
virtual bool isGeographic() const
OSSIM_DLL void defaultTileSize(ossimIpt &tileSize)
virtual ossim_uint32 getHeight() const
void addPair(const std::string &key, const std::string &value, bool overwrite=true)
ossimRefPtr< ossimConnectableObject > m_savedInput
Holds the origin end of the chain connected to theInputConnection.
virtual ossim_uint32 saveStateOfAllInputs(ossimKeywordlist &kwl, bool saveThisStateFlag=true, ossim_uint32 objectIndex=1, const char *prefix=0) const
Save the state of all inputs to a keyword list.
Pure virtual base class for image file writers.
References:
ossimDpt getDegreesPerPixel() const
Returns the resolution of this image in degrees/pixel.
void getKeywords(std::string &s) const
Gets the Keywords.
const ossimIpt & ll() const
Definition: ossimIrect.h:277
virtual void getPropertyNames(std::vector< ossimString > &propertyNames) const
virtual bool write(const char *file, const char *comment=0) const
Methods to dump the ossimKeywordlist to a file on disk.
void getModDate(std::string &s) const
Gets the Producer.
ossimRefPtr< ossimKeywordlist > m_kwl
Holds all options in key, value pair map.
virtual void initialize()
Initialize the data buffer.
void writeJpegTile(std::ostream *str, std::vector< std::streamoff > &xref, ossimImageData *id, const ossimIrect &aoi, ossimIrect &outputTileRect)
Write a JPEG-compresses the raster tile buffer to the output stream provided.
virtual bool isOpen() const
ossimConnectableObject * getInput(ossim_uint32 index=0)
returns the object at the specified index.
ossim_int32 toInt32() const
double ossim_float64
void getLgiDictProjection(ossimImageGeometry *geom, std::string &s) const
Gets projection part of LGIDict string.
static ossimScalarTypeLut * instance()
Returns the static instance of an ossimScalarTypeLut object.
virtual void setAreaOfInterest(const ossimIrect &areaOfInterest)
virtual bool saveState(ossimKeywordlist &kwl, const char *prefix=0) const
saves the state of the object.
virtual ossimScalarType getOutputScalarType() const
This will be used to query the output pixel type of the tile source.
virtual ossim_uint32 getSizeInBytes() const
Returns the total number of bytes for all bands.
yy_size_t size
void getSubject(std::string &s) const
Gets the Subject.
virtual const ossimDatum * getDatum() const
ossim_float64 lon
Definition: ossimGpt.h:266
bool localToWorld(const ossimDpt &local_pt, ossimGpt &world_pt) const
Exposes the 3D projection from image to world coordinates.
std::string::size_type size() const
Definition: ossimString.h:405
ossimRefPtr< ossimImageSourceSequencer > theInputConnection
virtual ossimRefPtr< ossimProperty > getProperty(const ossimString &name) const
Gets property for name.
virtual ossimIrect getBoundingRect(ossim_uint32 resLevel=0) const
This will return the bounding rect of the source.
void getLgiDictProjectionType(ossimImageGeometry *geom, std::string &s) const
Gets neatline part of LGIDict string from geom.
unsigned int ossim_uint32
virtual void getImageTypeList(std::vector< ossimString > &imageTypeList) const
void getImageTypeList(std::vector<ossimString>& imageTypeList)const
virtual ossimIrect getImageRectangle() const
virtual bool open()
Open method.
const ossimIpt & lr() const
Definition: ossimIrect.h:276
static ossimString downcase(const ossimString &aString)
Definition: ossimString.cpp:48
ossim_uint32 getEpsgCode(const ossimImageGeometry *geom) const
Gets the EPSG/PCS code from geometry.
virtual bool hasImageType(const ossimString &imageType) const
bool hasImageType(const ossimString& imageType) const
virtual ossim_int32 connectMyInputTo(ossimConnectableObject *inputObject, bool makeOutputConnection=true, bool createEventFlag=true)
Will try to connect this objects input to the passed in object.
virtual ossimRefPtr< ossimProperty > getProperty(const ossimString &name) const
ossim_uint32 width() const
Definition: ossimIrect.h:500
bool hasNans() const
Definition: ossimDpt.h:67
virtual ossimRefPtr< ossimImageGeometry > getImageGeometry()
Returns the image geometry object associated with this tile source or NULL if not defined...
std::vector< ossimIrect > outputTileRects
virtual void setProperty(ossimRefPtr< ossimProperty > property)
Will set the property whose name matches the argument "property->getName()".
void addOption(const std::string &key, const std::string &value)
Adds option to m_kwl with mutex lock.
Container class that holds both 2D transform and 3D projection information for an image Only one inst...
ossimScalarType
virtual void setOrigin(const ossimIpt &origin)
ossimPdfImageType getImageType() const
Gets the enumerated value of IMAGE_TYPE_KW lookup.
return status
bool writeImage(std::ostream *str)
Writes the image dictionary and associated objects.
virtual bool writeFile()
Writes the file to disk or a stream.
virtual ~ossimPdfWriter()
virtual destructor
const ossimProjection * getProjection() const
Access methods for projection (may be NULL pointer).
virtual ossimString getLongName() const
virtual const ossimFilename & getFilename() const
ossim_int64 getNumberOfTilesHorizontal() const
void getTileSize(std::string &s) const
Gets tiles size as string.
virtual void setProperty(ossimRefPtr< ossimProperty > property)
void writeInfo(std::ostream *str, std::vector< std::streamoff > &xref)
Writes document infomation dictionary.
virtual ossimErrorCode getErrorStatus() const
void getGmtDate(std::string &s) const
Get&#39;s the date in format of: (D:YYYYMMDDHHmmSSZ00&#39;00&#39;)
ossim_int32 y
Definition: ossimIpt.h:142
void setupInputChain()
Writes "dummy" or blank object just to keep object references in line.
virtual void setOutputBandList(const vector< ossim_uint32 > &outputBandList, bool disablePassThru=false)
Sets the output band list.
virtual void close()
Closes file.
double x
Definition: ossimDpt.h:164
void getLgiDictCtm(ossimImageGeometry *geom, const ossimIrect &aoi, std::string &s) const
Gets Coordinate Transformation Matrix(CTM) part of LGIDict string from geom.
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
void getLgiDictDatum(ossimImageGeometry *geom, std::string &s) const
Gets datum part of LGIDict string from geom.
ossim_int32 getZone() const
void getProducer(std::string &s) const
Gets the Producer.
virtual void getPropertyNames(std::vector< ossimString > &propertyNames) const
Pushes this&#39;s names onto the list of property names.
bool hasNans() const
Definition: ossimIrect.h:337
ossimFilename file() const
void getCreationDate(std::string &s) const
Gets the Producer.
const ossimIrect & getAreaOfInterest() const
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
8 bit unsigned integer
#define RTTI_DEF1(cls, name, b1)
Definition: ossimRtti.h:485
void getAuthor(std::string &s) const
Gets the Author.
void writeCatalog(std::ostream *str, std::vector< std::streamoff > &xref)
Writes Catalog object.
static const char * IMAGE_TYPE_KW
virtual void setPercentComplete(double percentComplete)
OSSIM_DLL void jpeg_cpp_stream_dest(jpeg_compress_struct *cinfo, std::ostream &stream)
Method which uses memory instead of a FILE* to write to.
ossimFilename & setExtension(const ossimString &e)
Sets the extension of a file name.
virtual bool loadState(const ossimKeywordlist &kwl, const char *prefix=0)
Method to the load (recreate) the state of an object from a keyword list.
virtual void setTileSize(const ossimIpt &tileSize)
virtual ossimString getExtension() const
Returns a 3-letter extension from the image type descriptor (theOutputImageType) that can be used for...
std::ostream * m_str
virtual const ossimIpt & getOrigin() const
unsigned char ossim_uint8
void writePages(std::ostream *str, std::vector< std::streamoff > &xref)
Writes Outlines object.
OSSIMDLLEXPORT std::ostream & ossimNotify(ossimNotifyLevel level=ossimNotifyLevel_WARN)
ossim_int64 getNumberOfTilesVertical() const
void getLgiDictDescription(ossimImageGeometry *geom, std::string &s) const
Gets description part of LGIDict string from geom.
void makeNan()
Definition: ossimDpt.h:65
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
bool isnan(const float &v)
isnan Test for floating point Not A Number (NAN) value.
Definition: ossimCommon.h:91
void writeRawTile(std::ostream *str, std::vector< std::streamoff > &xref, ossimImageData *id, const ossimIrect &aoi, ossimIrect &outputTileRect)
Write raw raster tile buffer to the output stream provided.