OSSIM - Open Source Software Image Map  Version 1.9.0 (20180803)
ossimGpkgWriter.cpp
Go to the documentation of this file.
1 //---
2 //
3 // File: ossimGpkgReader.cpp
4 //
5 // Author: David Burken
6 //
7 // License: MIT
8 //
9 // Description: OSSIM Geo Package writer.
10 //
11 //---
12 // $Id$
13 
14 #include "ossimGpkgWriter.h"
18 #include "ossimGpkgTileEntry.h"
19 #include "ossimGpkgTileRecord.h"
22 #include "ossimGpkgUtil.h"
23 #include "ossimSqliteUtil.h"
24 
26 #include <ossim/base/ossimCommon.h>
27 #include <ossim/base/ossimTrace.h>
28 #include <ossim/base/ossimDpt.h>
29 #include <ossim/base/ossimEndian.h>
31 #include <ossim/base/ossimGpt.h>
32 #include <ossim/base/ossimIrect.h>
38 #include <ossim/base/ossimTrace.h>
41 
49 
50 #include <ossim/matrix/myexcept.h>
51 
57 
58 #include <jpeglib.h>
59 #include <sqlite3.h>
60 
61 #include <algorithm> /* std::sort */
62 #include <cmath>
63 #include <sstream>
64 
66 
67 static const std::string ADD_ALPHA_CHANNEL_KW = "add_alpha_channel";
68 static const std::string ADD_ENTRY_KW = "add_entry";
69 static const std::string ADD_LEVELS_KW = "add_levels";
70 static const std::string ALIGN_TO_GRID_KW = "align_to_grid";
71 static const std::string APPEND_KW = "append";
72 static const std::string BATCH_SIZE_KW = "batch_size";
73 static const std::string CLIP_EXTENTS_KW = "clip_extents";
74 static const std::string CLIP_EXTENTS_ALIGN_TO_GRID_KW = "clip_extents_align_to_grid";
75 static const std::string COMPRESSION_LEVEL_KW = "compression_level";
76 static const std::string DEFAULT_FILE_NAME = "output.gpkg";
77 static const std::string EPSG_KW = "epsg";
78 static const std::string INCLUDE_BLANK_TILES_KW = "include_blank_tiles";
79 static const std::string TILE_SIZE_KW = "tile_size";
80 static const std::string TILE_TABLE_NAME_KW = "tile_table_name";
81 static const std::string TRUE_KW = "true";
82 static const std::string USE_PROJECTION_EXTENTS_KW = "use_projection_extents";
83 static const std::string WRITER_MODE_KW = "writer_mode";
84 static const std::string ZOOM_LEVELS_KW = "zoom_levels";
85 
86 //---
87 // For trace debugging (to enable at runtime do:
88 // your_app -T "ossimGpkgWriter:debug" your_app_args
89 //---
90 static ossimTrace traceDebug("ossimGpkgWriter:debug");
91 
92 // For the "ident" program:
93 #if OSSIM_ID_ENABLED
94 static const char OSSIM_ID[] = "$Id: ossimGpkgWriter.cpp 22466 2013-10-24 18:23:51Z dburken $";
95 #endif
96 
98  :
100  m_db(0),
101  m_batchCount(0),
102  m_batchSize(32),
103  m_projectionBoundingRect(0.0, 0.0, 0.0, 0.0, OSSIM_RIGHT_HANDED),
104  m_sceneBoundingRect(0.0, 0.0, 0.0, 0.0, OSSIM_RIGHT_HANDED),
105  m_clipRect(0.0, 0.0, 0.0, 0.0, OSSIM_RIGHT_HANDED),
106  m_outputRect(0.0, 0.0, 0.0, 0.0, OSSIM_RIGHT_HANDED),
107  m_tileSize(0,0),
108  m_tileTableName(),
109  m_srs_id(-1),
110  m_kwl(new ossimKeywordlist()),
111  m_fullTileCodec(0),
112  m_partialTileCodec(0),
113  m_fullTileCodecAlpha(false),
114  m_partialTileCodecAlpha(false),
115  m_zoomLevels(),
116  m_zoomLevelMatrixSizes(),
117  m_pStmt(0),
118  m_writeBlanks(false)
119 {
120  //---
121  // Uncomment for debug mode:
122  // traceDebug.setTraceFlag(true);
123  //---
124 
125  if (traceDebug())
126  {
128  << "ossimGpkgWriter::ossimGpkgWriter entered" << std::endl;
129 #if OSSIM_ID_ENABLED
131  << "OSSIM_ID: "
132  << OSSIM_ID
133  << std::endl;
134 #endif
135  }
136 
137  theOutputImageType = "ossim_gpkg"; // ossimImageFileWriter attribute.
138 
139  // Set default options:
140  m_kwl->addPair( ALIGN_TO_GRID_KW, TRUE_KW );
141  m_kwl->addPair( TILE_SIZE_KW, std::string("( 256, 256 )") );
142  m_kwl->addPair( WRITER_MODE_KW, std::string("mixed") );
143 
144  // Note batch size dramatically effects speed.
145  m_kwl->addPair( BATCH_SIZE_KW, "32" );
146 }
147 
149 {
150  close();
151 
152  // Not a leak, ref ptr.
153  m_kwl = 0;
154 }
155 
157 {
158  return ossimString("ossim_gpkg_writer");
159 }
160 
162 {
163  return ossimString("ossim gpkg writer");
164 }
165 
167 {
168  return ossimString("ossimGpkgWriter");
169 }
170 
172 {
173  return (m_db?true:false);
174 }
175 
177 {
178  bool status = false;
179 
180  close();
181 
182  if ( theFilename.size() )
183  {
184  int flags = SQLITE_OPEN_READWRITE;
185 
186  if ( theFilename.exists() )
187  {
188  if ( !append() )
189  {
191  flags |= SQLITE_OPEN_CREATE;
192  }
193  }
194  else
195  {
196  flags |= SQLITE_OPEN_CREATE;
197 
198  //---
199  // Set the append flags to false for down stream code since there was
200  // no file to append.
201  //---
202  m_kwl->addPair( ADD_ENTRY_KW, std::string("0"), true );
203  m_kwl->addPair( ADD_LEVELS_KW, std::string("0"), true );
204  }
205 
206  int rc = sqlite3_open_v2( theFilename.c_str(), &m_db, flags, 0 );
207  if ( rc == SQLITE_OK )
208  {
209  status = true;
210 
211  if ( !append() )
212  {
213  //---
214  // Set the application_id:
215  // Requirement 2: Every GeoPackage must contain 0x47503130 ("GP10" in ACII)
216  // in the application id field of the SQLite database header to indicate a
217  // GeoPackage version 1.0 file.
218  //---
219  const ossim_uint32 ID = 0x47503130;
220  std::ostringstream sql;
221  sql << "PRAGMA application_id = " << ID;
222  if ( ossim_sqlite::exec( m_db, sql.str() ) != SQLITE_DONE )
223  {
224  status = false;
225  }
226  }
227  }
228  else
229  {
230  close();
231  }
232  }
233 
234  return status;
235 }
236 
238 {
239  static const char MODULE[] = "ossimGpkgWriter::openFile";
240  if (traceDebug())
241  {
242  ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " entered...\n";
243  }
244 
245  bool status = false;
246 
247  if ( isOpen() )
248  {
249  close();
250  }
251 
252  // Add the passed in options to the default options.
253  m_kwl->add( 0, options, true );
254 
255  if (traceDebug())
256  {
258  << "\nwriter options/settings:\n"
259  << *(m_kwl.get()) << "\n";
260  }
261 
262  // Get the filename:
263  if ( getFilename( theFilename ) )
264  {
265  // Open it:
266  if ( open() )
267  {
268  if ( m_db )
269  {
270  if ( createTables( m_db ) )
271  {
272  if ( !append() )
273  {
274  // New file:
276  }
277  else // Existing gpkg....
278  {
279  // Get the zoom level info needed for disconnected writeTile checks.
280  std::string tileTableName;
281  getTileTableName( tileTableName );
282 
283  ossimGpkgTileEntry entry;
284  if ( ossim_gpkg::getTileEntry( m_db, tileTableName, entry ) )
285  {
286  entry.getZoomLevels( m_zoomLevels );
288  status = true;
289  }
290  }
291 
292  if ( status )
293  {
294  initializeCodec(); // Throws exception on error.
295 
296  m_writeBlanks = keyIsTrue( INCLUDE_BLANK_TILES_KW );
298  m_batchCount = 0;
299  }
300  }
301  }
302  }
303  }
304 
305  if (traceDebug())
306  {
308  << MODULE << " exit status: " << (status?"true":"false") << std::endl;
309  }
310 
311  // status = true;
312 
313  return status;
314 }
315 
316 // Method assumes new gpkg with no input connection.
318 {
319  static const char MODULE[] = "ossimGpkgWriter::initializeGpkg";
320  if (traceDebug())
321  {
322  ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " entered...\n";
323  }
324 
325  bool status = false;
326 
327  if ( alignToGrid() ) // Currently only handle align to grid mode.
328  {
329  // Set tile size:
331 
332  // Output projection:
334  if ( proj.valid() )
335  {
336  // Initialize m_projectionBoundingRect.
337  initializeProjectionRect( proj.get() );
338 
340  if ( m_srs_id != -1 )
341  {
342  // Initialize m_sceneBoundingRect:
343  if ( getWmsCutBox( m_sceneBoundingRect ) == false )
344  {
346  }
347 
348  bool needToExpandFlag = true;
349  //---
350  // Set the initial tie point. will make the AOI come out
351  // (0,0) to (n,n). Needed for getExpandedAoi code. Requires
352  // m_sceneBoundingRect or m_projectionBoundingRect(grid aligned).
353  //---
354  setProjectionTie( proj.get() );
355  // Set the clip rect.
356  if ( getClipExtents( m_clipRect, needToExpandFlag ) == false )
357  {
359  }
360 
361  // Get the zoom levels:
362  m_zoomLevels.clear();
363  m_zoomLevelMatrixSizes.clear();
365 
366  ossim_uint32 levels = m_zoomLevels.size();
367 
368  if ( levels )
369  {
370  // Get the gsd for the most expanded out level:
371  ossimDpt largestGsd;
372  getGsd( proj.get(), m_zoomLevels[0], largestGsd );
373 
374  // Get the gsd for the most expanded out level:
375  ossimDpt smallestGsd;
376  getGsd( proj.get(), m_zoomLevels[ levels-1 ], smallestGsd );
377 
378  //---
379  // Set the scale of projection to the largest gsd before
380  // expanding AOI. This will also recenter projection tie
381  // for new gsd.
382  //---
383  applyScaleToProjection( proj.get(), largestGsd );
384 
385  // AOI at zoomed out level:
386  ossimIrect aoi;
387  getAoiFromRect( proj.get(), m_clipRect, aoi );
388 
389  // Expand the AOI to even tile boundary:
390  ossimIrect expandedAoi = aoi;
391  if(needToExpandFlag)
392  {
393  getExpandedAoi( aoi, expandedAoi );
394  }
395 
396  initializeRect( proj.get(), expandedAoi, m_outputRect );
397 
398  if (traceDebug())
399  {
401  << "\n\nfirst level: " << m_zoomLevels[0]
402  << "\nlast level: " << m_zoomLevels[ levels-1 ]
403  << "\nlevel[" << m_zoomLevels[0] << "] gsd: " << largestGsd
404  << "\nlevel[" << m_zoomLevels[levels-1] << "] gsd: " << smallestGsd
405  << "\nexpanded aoi(first zoom level): " << expandedAoi
406  << "\ntile size: " << m_tileSize
407  << "\nscene rect: " << m_sceneBoundingRect
408  << "\nclip rect: " << m_clipRect
409  << "\noutput rect: " << m_outputRect
410  << "\n";
411  }
412 
414  {
416  {
417  ossimDpt gsd;
418  getGsd( proj.get(), gsd );
419 
420  // Write the tile matrix record for each zoom level.
421  std::vector<ossim_int32>::const_iterator zoomLevel = m_zoomLevels.begin();
422  while ( zoomLevel != m_zoomLevels.end() )
423  {
424  // Get the area of interest.
425  ossimIrect aoi;
426  getAoiFromRect( proj.get(), m_outputRect, aoi );
427 
428  // Clipped aoi:
429  ossimIrect clippedAoi;
430  getAoiFromRect( proj.get(), m_clipRect, clippedAoi );
431 
432  // Expanded to tile boundaries:
433  ossimIrect expandedAoi;
434  getExpandedAoi( aoi, expandedAoi );
435 
436  // Get the number of tiles:
437  ossimIpt matrixSize;
438  getMatrixSize( expandedAoi, matrixSize);
439 
440  // Capture for writeTile index check.
441  m_zoomLevelMatrixSizes.push_back( matrixSize );
442 
443  if (traceDebug())
444  {
446  << "\nlevel: " << (*zoomLevel)
447  << "\ngsd: " << gsd
448  << "\naoi: " << aoi
449  << "\nclippedAoi: " << clippedAoi
450  << "\nexpandedAoi: " << expandedAoi
451  << "\nmatrixSize: " << matrixSize
452  << "\n";
453  }
454 
455  if ( writeGpkgTileMatrixTable( m_db, (*zoomLevel), matrixSize, gsd ) )
456  {
457 
458  if ( writeGpkgNsgTileMatrixExtentTable( m_db, (*zoomLevel),
459  expandedAoi, clippedAoi ) )
460  {
461  status = true;
462  }
463  else
464  {
466  << MODULE
467  << " WARNING:\nwriteGpkgNsgTileMatrixExtentTable call failed!"
468  << std::endl;
469  }
470  }
471  else
472  {
474  << MODULE
475  << " WARNING:\nwriteGpkgTileMatrixTable call failed!" << std::endl;
476  }
477 
478  ++zoomLevel;
479 
480  if ( zoomLevel != m_zoomLevels.end() )
481  {
482  gsd = gsd / 2.0;
483 
484  ossimDpt scale( 0.5, 0.5 );
485  proj->applyScale( scale, true );
486  proj->update();
487  }
488 
489  } // Matches: while ( zoomLevel != zoomLevels.end() )
490 
491  } // Matches: if ( writeGpkgTileMatrixSetTable( m_db, m_outputRect ) )
492 
493  } // Matches: if ( writeGpkgContentsTable( m_db, m_outputRect ) )
494  }
495  else
496  {
498  << "Must have at least one zoom level!"
499  << "Set zoom_levels key in option keyword list."
500  << "e.g. \"zoom_levels:()4,5,6,7,8,9,10,11\""
501  << endl;
502  }
503  }
504  }
505  }
506  else if (traceDebug())
507  {
508  ossimNotify(ossimNotifyLevel_WARN) << "Non-grid-aligned mode not supported!\n";
509  }
510 
511  if (traceDebug())
512  {
514  << MODULE << " exit status: " << (status?"true":"false") << std::endl;
515  }
516 
517  return status;
518 }
519 
521 {
522  if ( m_db )
523  {
524  sqlite3_close( m_db );
525  m_db = 0;
526  }
527  m_fullTileCodec = 0;
528  m_partialTileCodec = 0;
529 
530  // ??? : if ( m_pStmt ) finalizeTileProcessing()
531 
532  m_pStmt = 0;
533  m_batchCount = 0;
534 }
535 
537 {
538  static const char MODULE[] = "ossimGpkgWriter::writeFile";
539 
540  if (traceDebug())
541  {
543  << MODULE << " entered..."
544  << "\nwriter options/settings:\n"
545  << *(m_kwl.get()) << "\n";
546  }
547 
548  bool status = false;
549 
551  m_batchCount = 0;
552 
553  try // Exceptions can be thrown...
554  {
556  {
557  //---
558  // To hold the original input to the image source sequencer. Only used
559  // if we mess with the input chain, e.g. add a scalar remapper.
560  //---
561  ossimRefPtr<ossimConnectableObject> originalSequencerInput = 0;
562 
563  //---
564  // Set up input connection for eight bit if needed.
565  // Some writers, e.g. jpeg are only 8 bit.
566  //---
568  requiresEightBit() )
569  {
570  originalSequencerInput = theInputConnection->getInput(0);
571 
573 
574  // Connect scalar remapper to sequencer input.
576 
577  // Connect sequencer to the scalar remapper.
580  }
581 
582  // Note only the master process used for writing...
584  {
585  if (!isOpen())
586  {
587  open();
588  }
589 
590  if ( m_db )
591  {
592  status = createTables( m_db );
593  }
594 
595  if ( status )
596  {
597  if ( keyIsTrue( ADD_LEVELS_KW ) )
598  {
599  status = addLevels();
600  }
601  else
602  {
603  status = writeEntry();
604  }
605  }
606 
607  close();
608  }
609  else // Matches: if( theInputConnection->isMaster() )
610  {
611  // Slave process only used to get tiles from the input.
613  }
614 
615  // Reset the connection if needed.
616  if( originalSequencerInput.valid() )
617  {
618  theInputConnection->connectMyInputTo(0, originalSequencerInput.get());
619  originalSequencerInput = 0;
620  }
621 
622  } // Matches: if ( theInputConnection.isValid() ... )
623  }
624  catch ( const ossimException& e )
625  {
627  << MODULE << " Caught exception!\n"
628  << e.what()
629  << std::endl;
630  status = false;
631  }
632  catch ( const RBD_COMMON::BaseException& me ) // Matrix exeption...
633  {
635  << MODULE << " Caught Matrix exception!\n"
636  << me.what()
637  << std::endl;
638  status = false;
639  }
640  catch ( ... )
641  {
643  << MODULE << " Caught unknown exception!\n"
644  << std::endl;
645  status = false;
646  }
647 
648  if (traceDebug())
649  {
651  << MODULE << " exit status: " << (status?"true":"false") << std::endl;
652  }
653 
654  return status;
655 
656 } // End: ossimGpkgWriter::writeFile
657 
659 {
660  static const char MODULE[] = "ossimGpkgWriter::writeEntry";
661 
662  bool status = false;
663 
664  // Get the image geometry from the input.
666 
667  // Input projection:
669 
670  // Raw area of interest:
671  ossimIrect sourceAoi = getAreaOfInterest();
672 
673  if ( geom.valid() && sourceProj.valid() && (sourceAoi.hasNans() == false) )
674  {
675  ossimRefPtr<ossimMapProjection> productProjection =
676  getNewOutputProjection( geom.get() );
677 
678  if ( productProjection.valid() )
679  {
680  ossimDpt sourceGsd;
681  getGsd( productProjection.get(), sourceGsd );
682 
683  bool gridAligned = alignToGrid();
684 
685  if ( gridAligned &&
686  ( productProjection->getClassName() == "ossimUtmProjection" ) )
687  {
688  // Turn off grid alignment for utm.
689  if (traceDebug())
690  {
692  << MODULE << " WARNING!"
693  << "\"align_to_grid\" option is invalid a UTM projection and is "
694  << "being disabled..."
695  << std::endl;
696  }
697 
698  m_kwl->addPair( ALIGN_TO_GRID_KW, std::string("0"), true );
699  gridAligned = false;
700  }
701 
702  // Initialize m_sceneBoundingRect:
703  initializeRect( sourceProj.get(), sourceAoi, m_sceneBoundingRect );
704 
705  if ( gridAligned )
706  {
707  // Initialize m_projectionBoundingRect. Only used if grid aligned.
708  initializeProjectionRect( productProjection.get() );
709  }
710 
711  //---
712  // Set the initial tie point. will make the AOI come out
713  // (0,0) to (n,n). Needed for getExpandedAoi code. Requires
714  // m_sceneBoundingRect or m_projectionBoundingRect(grid aligned).
715  //---
716  setProjectionTie( productProjection.get() );
717 
718  if ( gridAligned )
719  {
720  // Set the clip rect.
722  }
723  else
724  {
726  }
727 
728  // Set tile size:
730 
731  // Set the sequence tile size:
733 
734  // Get the first aoi from the clip rect.
735  ossimIrect aoi;
736  getAoiFromRect( productProjection.get(), m_clipRect, aoi );
737 
738  // Get the zoom levels to write:
739  ossimDpt fullResGsd;
740  std::vector<ossim_int32> zoomLevels;
741  getZoomLevels( productProjection.get(),
742  aoi,
743  sourceGsd,
744  zoomLevels,
745  fullResGsd );
746 
747  if ( zoomLevels.size() )
748  {
749  //---
750  // Start zoom level is full res.
751  // Stop zoom level is overview.
752  //---
753 
754  //---
755  // Set the initial full res scale:
756  // Must do this before the below call to
757  // "ossimMapProjection::applyScale"
758  //---
759  bool isGeographic = productProjection->isGeographic();
760  if ( isGeographic )
761  {
762  productProjection->setDecimalDegreesPerPixel( fullResGsd );
763  }
764  else
765  {
766  productProjection->setMetersPerPixel( fullResGsd );
767  }
768 
769  // Recenter tie point after resolution change.
770  setProjectionTie( productProjection.get() );
771 
772  // Stop gsd:
773  ossimDpt stopGsd;
774  getGsd( fullResGsd,
775  zoomLevels[zoomLevels.size()-1],
776  zoomLevels[0],
777  stopGsd );
778 
779  //---
780  // Set the scale of projection to the largest gsd before
781  // expanding AOI. This will also recenter projection tie
782  // for new gsd.
783  //---
784  applyScaleToProjection( productProjection.get(), stopGsd );
785 
786  // propagate to chains.
787  setView( productProjection.get() );
788 
789  // New aoi at zoomed out level:
790  getAoiFromRect( productProjection.get(), m_clipRect, aoi );
791 
792  // Expand the AOI to even tile boundary:
793  ossimIrect expandedAoi;
794  getExpandedAoi( aoi, expandedAoi );
795 
796  initializeRect( productProjection.get(), expandedAoi, m_outputRect );
797 
798  if (traceDebug())
799  {
801  << "source aoi: " << sourceAoi
802  << "\nproduct aoi: " << aoi
803  << "\nexpanded aoi(last zoom level): " << expandedAoi
804  << "\ngsd: " << fullResGsd
805  << "\nstop gsd: " << stopGsd
806  << "\ntile size: " << m_tileSize
807  << "\nscene rect: " << m_sceneBoundingRect
808  << "\nclip rect: " << m_clipRect
809  << "\noutput rect: " << m_outputRect
810  << "\n";
811 
812  if ( gridAligned )
813  {
815  << "\nproj rect: " << m_projectionBoundingRect << "\n";
816  }
817  }
818 
819  m_srs_id = writeGpkgSpatialRefSysTable( m_db, productProjection.get() );
820  if ( m_srs_id != -1 )
821  {
823  {
825  {
826  //---
827  // Note:
828  // Writer starts at "stop" zoom level(low res) and goes
829  // to "start"(high res). I know naming is confusing!
830  //---
832  productProjection.get(),
833  zoomLevels );
834  status = true;
835  }
836  }
837  }
838 
839  } // Matches: if ( zoomLevels.size() )
840 
841  } // Matches: if ( productProjection.valid() )
842 
843  } // Matches: if ( geom.valid() && ... )
844 
845  return status;
846 
847 } // End: ossimGpkgWriter::writeEntry()
848 
850 {
851  static const char MODULE[] = "ossimGpkgWriter::addLevels";
852 
853  bool status = false;
854 
855  // Get the image geometry from the input.
857 
858  // Input projection:
860 
861  // Raw area of interest:
862  ossimIrect sourceAoi = getAreaOfInterest();
863 
864  if ( geom.valid() && sourceProj.valid() && (sourceAoi.hasNans() == false) )
865  {
866  ossimRefPtr<ossimMapProjection> productProjection =
867  getNewOutputProjection( geom.get() );
868 
869  if ( productProjection.valid() )
870  {
871  std::string tileTableName;
872  getTileTableName( tileTableName );
873 
874  ossimGpkgTileEntry entry;
875  if ( ossim_gpkg::getTileEntry( m_db, tileTableName, entry ) )
876  {
877  // productProjection must match what's already in there.
878  if ( entry.getSrs().m_organization_coordsys_id ==
879  (ossim_int32)productProjection->getPcsCode() )
880  {
881  ossimDpt sourceGsd;
882  getGsd( productProjection.get(), sourceGsd );
883 
884  bool gridAligned = alignToGrid();
885 
886  if ( gridAligned &&
887  ( productProjection->getClassName() == "ossimUtmProjection" ) )
888  {
889  // Turn off grid alignment for utm.
890  if (traceDebug())
891  {
893  << MODULE << " WARNING!"
894  << "\"align_to_grid\" option is invalid a UTM projection and is "
895  << "being disabled..."
896  << std::endl;
897  }
898 
899  m_kwl->addPair( ALIGN_TO_GRID_KW, std::string("0"), true );
900  gridAligned = false;
901  }
902 
903  // Initialize m_sceneBoundingRect:
904  initializeRect( sourceProj.get(), sourceAoi, m_sceneBoundingRect );
905 
906  if ( gridAligned )
907  {
908  // Initialize m_projectionBoundingRect. Only used if grid aligned.
909  initializeProjectionRect( productProjection.get() );
910  }
911 
912  //---
913  // Set the initial tie point. Requires m_sceneBoundingRect or
914  // m_projectionBoundingRect(grid aligned).
915  //---
916  setProjectionTie( productProjection.get() );
917 
918  // Pull the output rect from the existing entry.
920 
921  if ( gridAligned )
922  {
923  // Set the clip rect.
925  }
926  else
927  {
929  }
930 
931  // Final clip rect to existing entry.
933 
934  // Set tile size:
936 
937  // Set the sequence tile size:
939 
940  // Get the first aoi from the clip rect.
941  ossimIrect aoi;
942  getAoiFromRect( productProjection.get(), m_clipRect, aoi );
943 
944  // Get the current(existing) zoom levels from the entry.
945  std::vector<ossim_int32> currentZoomLevels;
946  entry.getZoomLevels( currentZoomLevels );
947  std::sort( currentZoomLevels.begin(), currentZoomLevels.end() );
948 
949  // Get the zoom levels to write:
950  ossimDpt fullResGsd;
951  std::vector<ossim_int32> zoomLevels;
952  getZoomLevels( productProjection.get(),
953  aoi,
954  sourceGsd,
955  zoomLevels,
956  fullResGsd );
957 
958  // Sanity check. Throws exception:
959  checkLevels( currentZoomLevels, zoomLevels );
960 
961  if ( zoomLevels.size() )
962  {
963  //---
964  // Start zoom level is full res.
965  // Stop zoom level is overview.
966  //---
967 
968  //---
969  // Set the initial full res scale:
970  // Must do this before the below call to
971  // "ossimMapProjection::applyScale"
972  //---
973  bool isGeographic = productProjection->isGeographic();
974  if ( isGeographic )
975  {
976  productProjection->setDecimalDegreesPerPixel( fullResGsd );
977  }
978  else
979  {
980  productProjection->setMetersPerPixel( fullResGsd );
981  }
982 
983  // Recenter tie point after resolution change.
984  setProjectionTie( productProjection.get() );
985 
986  // Stop gsd:
987  ossimDpt stopGsd;
988  getGsd( fullResGsd,
989  zoomLevels[zoomLevels.size()-1],
990  zoomLevels[0],
991  stopGsd );
992 
993  //---
994  // Set the scale of projection to the largest gsd before
995  // expanding AOI. This will also recenter projection tie
996  // for new gsd.
997  //---
998  applyScaleToProjection( productProjection.get(), stopGsd );
999 
1000  // propagate to chains.
1001  setView( productProjection.get() );
1002 
1003  if (traceDebug())
1004  {
1006  << "source aoi: " << sourceAoi
1007  << "\nproduct aoi: " << aoi
1008  // << "\nexpanded aoi(last zoom level): " << expandedAoi
1009  << "\ngsd: " << fullResGsd
1010  << "\nstop gsd: " << stopGsd
1011  << "\ntile size: " << m_tileSize
1012  << "\nscene rect: " << m_sceneBoundingRect
1013  << "\nclip rect: " << m_clipRect
1014  << "\noutput rect: " << m_outputRect
1015  << "\n";
1016 
1017  if ( gridAligned )
1018  {
1020  << "\nproj rect: " << m_projectionBoundingRect << "\n";
1021  }
1022  }
1023 
1024  //---
1025  // Note:
1026  // Writer starts at "stop" zoom level(low res) and goes
1027  // to "start"(high res). I know naming is confusing!
1028  //---
1030  productProjection.get(),
1031  zoomLevels );
1032  status = true;
1033 
1034  } // Matches: if ( zoomLevels.size() )
1035 
1036  } // Matches: if ( entry.getSrs() ...
1037 
1038  } // Matches: if ( productProjection.valid() )
1039 
1040  } // Matches: if ( ossim_gpkg::getTileEntry( m_db, ... )
1041 
1042  } // Matches: if ( geom.valid() && ... )
1043 
1044  return status;
1045 
1046 } // End: ossimGpkgWriter::addLevels()
1047 
1049  ossimMapProjection* proj,
1050  const std::vector<ossim_int32>& zoomLevels )
1051 // ossim_int32 fullResZoomLevel,
1052 // ossim_int32 stopZoomLevel )
1053 
1054 {
1055  static const char MODULE[] = "ossimGpkgWriter::writeZoomLevels";
1056  if (traceDebug())
1057  {
1058  ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " entered..." << std::endl;
1059  }
1060 
1061  if ( db && proj )
1062  {
1063  initializeCodec(); // Throws exception on error.
1064 
1065  ossimDpt gsd;
1066  getGsd( proj, gsd );
1067 
1068  // To communicate the percent complete.
1069  ossim_float64 tilesWritten = 0.0;
1070  ossim_float64 totalTiles = 0.0;
1071 
1072  std::vector<ossim_int32>::const_iterator zoomLevel = zoomLevels.begin();
1073  while ( zoomLevel != zoomLevels.end() )
1074  {
1075  // Get the area of interest.
1076  ossimIrect aoi;
1077  getAoiFromRect( proj, m_outputRect, aoi );
1078 
1079  // Clipped aoi:
1080  ossimIrect clippedAoi;
1081  getAoiFromRect( proj, m_clipRect, clippedAoi );
1082 
1083  // Expanded to tile boundaries:
1084  ossimIrect expandedAoi;
1085  getExpandedAoi( aoi, expandedAoi );
1086 
1087  // Get the number of tiles:
1088  ossimIpt matrixSize;
1089  getMatrixSize( expandedAoi, matrixSize);
1090 
1091  if ( totalTiles < 1 )
1092  {
1093  //---
1094  // First time through, compute total tiles for percent complete output.
1095  // This will be inaccurate if user skips zoom levels for some reason.
1096  //
1097  // NOTE: Numbers get very large, i.e. billions of tiles.
1098  // Was busting the int 32 boundary multiplying
1099  // (matrixSize.x * matrixSize.y).
1100  //---
1101  ossim_float64 x = matrixSize.x;
1102  ossim_float64 y = matrixSize.y;
1103  totalTiles = x * y;
1104 
1105  ossim_int32 levels = zoomLevels.size();
1106  if ( levels > 1 )
1107  {
1108  // Tile count doubles in each direction with each additional level.
1109  ossim_int32 z = 1;
1110  do
1111  {
1112  x = x * 2.0;
1113  y = y * 2.0;
1114  totalTiles += (x * y);
1115  ++z;
1116  } while ( z < levels );
1117  }
1118 
1119  if (traceDebug())
1120  {
1122  << "total tiles: " << totalTiles << "\n";
1123  }
1124  }
1125  if (traceDebug())
1126  {
1128  << "ossimGpkgWriter::writeZoomLevels DEBUG:"
1129  << "\nlevel: " << (*zoomLevel)
1130  << "\ngsd: " << gsd
1131  << "\naoi: " << aoi
1132  << "\nclippedAoi: " << clippedAoi
1133  << "\nexpandedAoi: " << expandedAoi
1134  << "\nmatrixSize: " << matrixSize
1135  << "\n";
1136  }
1137 
1138  if ( writeGpkgTileMatrixTable( db, (*zoomLevel), matrixSize, gsd ) )
1139  {
1140 
1141  if ( writeGpkgNsgTileMatrixExtentTable( db, (*zoomLevel),
1142  expandedAoi, clippedAoi ) )
1143  {
1144  writeTiles( db, expandedAoi, (*zoomLevel), totalTiles, tilesWritten );
1145  // writeZoomLevel( db, expandedAoi, (*zoomLevel), totalTiles, tilesWritten );
1146  }
1147  else
1148  {
1150  << MODULE
1151  << " WARNING:\nwriteGpkgNsgTileMatrixExtentTable call failed!" << std::endl;
1152  }
1153  }
1154  else
1155  {
1157  << MODULE
1158  << " WARNING:\nwriteGpkgTileMatrixTable call failed!" << std::endl;
1159  }
1160 
1161  if ( needsAborting() ) break;
1162 
1163  ++zoomLevel;
1164 
1165  if ( zoomLevel != zoomLevels.end() )
1166  {
1167  gsd = gsd / 2.0;
1168 
1169  ossimDpt scale( 0.5, 0.5 );
1170  proj->applyScale( scale, true );
1171  proj->update();
1172 
1173  // Propagate projection to chains and update aoi's of cutters.
1174  setView( proj );
1175  }
1176 
1177  } // Matches: while ( zoomLevel != zoomLevels.end() )
1178 
1179  } // Matches: if ( db && proj )
1180 
1182  {
1183  char * sErrMsg = 0;
1184  sqlite3_exec(db, "END TRANSACTION", NULL, NULL, &sErrMsg);
1185  }
1186 
1187  if (traceDebug())
1188  {
1190  << MODULE << " exited...\n";
1191  }
1192 
1193 } // ossimGpkgWriter::writeZoomLevels( ... )
1194 
1196  const ossimIrect& aoi,
1197  ossim_int32 zoomLevel,
1198  const ossim_float64& totalTiles,
1199  ossim_float64& tilesWritten )
1200 {
1201  if ( db )
1202  {
1203  // Initialize the sequencer:
1206 
1209 
1210  char * sErrMsg = 0;
1211  sqlite3_stmt* pStmt = 0; // The current SQL statement
1212  std::ostringstream sql;
1213  sql << "INSERT INTO " << m_tileTableName << "( zoom_level, tile_column, tile_row, tile_data ) VALUES ( "
1214  << "?, " // 1: zoom level
1215  << "?, " // 2: col
1216  << "?, " // 3: row
1217  << "?" // 4: blob
1218  << " )";
1219 
1220  if (traceDebug())
1221  {
1223  << "sql:\n" << sql.str() << "\n";
1224  }
1225 
1226  int rc = sqlite3_prepare_v2(db, // Database handle
1227  sql.str().c_str(), // SQL statement, UTF-8 encoded
1228  -1, // Maximum length of zSql in bytes.
1229  &pStmt, // OUT: Statement handle
1230  NULL);
1231 
1232  bool writeBlanks = keyIsTrue( INCLUDE_BLANK_TILES_KW );
1233 
1234  if(rc == SQLITE_OK)
1235  {
1236  for ( ossim_int64 row = 0; row < ROWS; ++row )
1237  {
1238  for ( ossim_int64 col = 0; col < COLS; ++col )
1239  {
1240  // Grab the tile.
1242  if ( tile.valid() )
1243  {
1244  // Only write tiles that have data in them:
1245  if (tile->getDataObjectStatus() != OSSIM_NULL )
1246  {
1247  if( (tile->getDataObjectStatus() != OSSIM_EMPTY) || writeBlanks )
1248  {
1249  if(m_batchCount == 0)
1250  {
1251  sqlite3_exec(db, "BEGIN TRANSACTION", NULL, NULL, &sErrMsg);
1252  }
1253 
1254  writeTile( pStmt, db, tile, zoomLevel, row, col);//, quality );
1255  ++m_batchCount;
1256 
1257  if(m_batchCount == m_batchSize)
1258  {
1259  sqlite3_exec(db, "END TRANSACTION", NULL, NULL, &sErrMsg);
1260  m_batchCount = 0;
1261  }
1262  }
1263  }
1264  }
1265  else
1266  {
1267  std::ostringstream errMsg;
1268  errMsg << "ossimGpkgWriter::writeTiles ERROR: "
1269  << "Sequencer returned null tile pointer for ("
1270  << col << ", " << row << ")";
1271 
1272  throw ossimException( errMsg.str() );
1273  }
1274 
1275  // Always increment the tiles written thing.
1276  ++tilesWritten;
1277 
1278  if ( needsAborting() ) break;
1279 
1280  } // End: col loop
1281 
1282  setPercentComplete( (tilesWritten / totalTiles) * 100.0 );
1283 
1284  if ( needsAborting() )
1285  {
1286  setPercentComplete( 100 );
1287  break;
1288  }
1289 
1290  } // End: row loop
1291 
1292  sqlite3_finalize(pStmt);
1293  }
1294  else
1295  {
1297  << "sqlite3_prepare_v2 error: " << sqlite3_errmsg(db) << std::endl;
1298  }
1299 
1300  } // if ( db )
1301 
1302 } // End: ossimGpkgWriter::writeTiles( ... )
1303 
1304 void ossimGpkgWriter::writeTile( sqlite3_stmt* pStmt,
1305  sqlite3* db,
1307  ossim_int32 zoomLevel,
1308  ossim_int64 row,
1309  ossim_int64 col )
1310 {
1311  if ( db && tile.valid() )
1312  {
1313  std::vector<ossim_uint8> codecTile; // To hold the jpeg encoded tile.
1314  bool encodeStatus;
1315  std::string ext;
1316  int mode = getWriterMode();
1317 
1318  if ( tile->getDataObjectStatus() == OSSIM_FULL )
1319  {
1320  if ( m_fullTileCodecAlpha )
1321  {
1322  tile->computeAlphaChannel();
1323  }
1324  encodeStatus = m_fullTileCodec->encode(tile, codecTile);
1325  if((mode == OSSIM_GPGK_WRITER_MODE_JPEG)||(mode == OSSIM_GPGK_WRITER_MODE_MIXED)) ext = ".jpg";
1326  else ext = ".png";
1327  }
1328  else
1329  {
1331  {
1332  tile->computeAlphaChannel();
1333  }
1334  encodeStatus = m_partialTileCodec->encode(tile, codecTile);
1335  if(mode == OSSIM_GPGK_WRITER_MODE_JPEG) ext = ".jpg";
1336  else ext = ".png";
1337  }
1338 
1339  if ( encodeStatus )
1340  {
1341  // Insert into the database file(gpkg):
1342  int rc = sqlite3_bind_int (pStmt, 1, zoomLevel);
1343  rc |= sqlite3_bind_int (pStmt, 2, col);
1344  rc |= sqlite3_bind_int (pStmt, 3, row);
1345  rc |= sqlite3_bind_blob (pStmt,
1346  4,
1347  (void*)&codecTile.front(),
1348  codecTile.size(),
1349  SQLITE_TRANSIENT);
1350  if ( rc == SQLITE_OK )
1351  {
1352  rc = sqlite3_step(pStmt);
1353  if ( rc == SQLITE_OK )
1354  {
1356  << "sqlite3_step error: " << sqlite3_errmsg(db) << std::endl;
1357  }
1358 
1359  }
1360  else
1361  {
1363  << "sqlite3_bind_blob error: " << sqlite3_errmsg(db) << std::endl;
1364  }
1365 
1366  sqlite3_clear_bindings(pStmt);
1367  sqlite3_reset(pStmt);
1368  }
1369 
1370  } // Matches: if ( db && tile.valid() )
1371 }
1372 
1373 void ossimGpkgWriter::writeCodecTile( sqlite3_stmt* pStmt,
1374  sqlite3* db,
1375  ossim_uint8* codecTile,
1376  ossim_int32 codecTileSize,
1377  ossim_int32 zoomLevel,
1378  ossim_int64 row,
1379  ossim_int64 col )
1380 {
1381  if ( db && codecTile )
1382  {
1383  // Insert into the database file(gpkg):
1384  int rc = sqlite3_bind_int (pStmt, 1, zoomLevel);
1385  rc |= sqlite3_bind_int (pStmt, 2, col);
1386  rc |= sqlite3_bind_int (pStmt, 3, row);
1387  rc |= sqlite3_bind_blob (pStmt,
1388  4,
1389  (void*)codecTile,
1390  codecTileSize,
1391  SQLITE_TRANSIENT);
1392  if ( rc == SQLITE_OK )
1393  {
1394  rc = sqlite3_step(pStmt);
1395  if ( rc == SQLITE_OK )
1396  {
1398  << "sqlite3_step error: " << sqlite3_errmsg(db) << std::endl;
1399  }
1400 
1401  }
1402  else
1403  {
1405  << "sqlite3_bind_blob error: " << sqlite3_errmsg(db) << std::endl;
1406  }
1407 
1408  sqlite3_clear_bindings(pStmt);
1409  sqlite3_reset(pStmt);
1410 
1411  } // Matches: if ( db && tile.valid() )
1412 }
1413 
1414 // For connectionless write tiles:
1416 {
1417  std::ostringstream sql;
1418  sql << "INSERT INTO " << m_tileTableName << "( zoom_level, tile_column, tile_row, tile_data ) VALUES ( "
1419  << "?, " // 1: zoom level
1420  << "?, " // 2: col
1421  << "?, " // 3: row
1422  << "?" // 4: blob
1423  << " )";
1424 
1425  if (traceDebug())
1426  {
1428  << "sql:\n" << sql.str() << "\n";
1429  }
1430 
1431  return sqlite3_prepare_v2(m_db, // Database handle
1432  sql.str().c_str(), // SQL statement, UTF-8 encoded
1433  -1, // Maximum length of zSql in bytes.
1434  &m_pStmt, // OUT: Statement handle
1435  NULL);
1436 }
1437 
1438 // For connectionless write tiles:
1440  ossim_int32 zoomLevel,
1441  ossim_int64 row,
1442  ossim_int64 col )
1443 {
1444  bool status = false;
1445 
1446  if ( tile.valid() )
1447  {
1448  // Check for valid zoom level:
1449  if ( isValidZoomLevelRowCol( zoomLevel, row, col ) )
1450  {
1451 
1452  // Only write tiles that have data in them:
1453  if (tile->getDataObjectStatus() != OSSIM_NULL )
1454  {
1455  if( (tile->getDataObjectStatus() != OSSIM_EMPTY) || m_writeBlanks )
1456  {
1457  char* sErrMsg = 0;
1458 
1459  if(m_batchCount == 0)
1460  {
1461  sqlite3_exec(m_db, "BEGIN TRANSACTION", NULL, NULL, &sErrMsg);
1462  }
1463 
1464  writeTile( m_pStmt, m_db, tile, zoomLevel, row, col);//, quality );
1465  ++m_batchCount;
1466 
1467  if(m_batchCount == m_batchSize)
1468  {
1469  sqlite3_exec(m_db, "END TRANSACTION", NULL, NULL, &sErrMsg);
1470  m_batchCount = 0;
1471  }
1472  }
1473  }
1474 
1475  status = true;
1476  }
1477  }
1478 
1479  return status;
1480 }
1481 
1483  ossim_int32 codecTileSize,
1484  ossim_int32 zoomLevel,
1485  ossim_int64 row,
1486  ossim_int64 col)
1487 {
1488  bool status = true;
1489 
1490  char* sErrMsg = 0;
1491 
1492  if(m_batchCount == 0)
1493  {
1494  sqlite3_exec(m_db, "BEGIN TRANSACTION", NULL, NULL, &sErrMsg);
1495  }
1496 
1497  writeCodecTile( m_pStmt, m_db, codecTile, codecTileSize, zoomLevel, row, col);//, quality );
1498  ++m_batchCount;
1499 
1500  if(m_batchCount == m_batchSize)
1501  {
1502  sqlite3_exec(m_db, "END TRANSACTION", NULL, NULL, &sErrMsg);
1503  m_batchCount = 0;
1504  }
1505 
1506  return status;
1507 }
1509 {
1510  if ( m_batchCount )
1511  {
1512  char* sErrMsg = 0;
1513  sqlite3_exec(m_db, "END TRANSACTION", NULL, NULL, &sErrMsg);
1514  m_batchCount = 0;
1515  }
1516 
1517  sqlite3_finalize(m_pStmt);
1518  m_pStmt = 0;
1519 }
1520 
1522 {
1523  bool status = false;
1525  {
1527  {
1529  {
1531  {
1533  {
1536  }
1537  }
1538  }
1539  }
1540  }
1541  return status;
1542 }
1543 
1545  sqlite3* db, const ossimMapProjection* proj )
1546 {
1547  //---
1548  // NOTE: the "srs_id" is NOT synonomous with the m_organization_coordsys_id, e.g
1549  // 4326. We need this so that other records can tie themselves to the correct
1550  // gpkg_spatial_ref_sys record.
1551  //---
1552  ossim_int32 srs_id = -1;
1553  if ( db && proj )
1554  {
1556  ossimGpkgSpatialRefSysRecord::InitCode returnCode = record.init( db, proj );
1557  if ( returnCode == ossimGpkgSpatialRefSysRecord::OK )
1558  {
1559  if ( record.insert( db ) )
1560  {
1561  srs_id = record.m_srs_id;
1562  }
1563  }
1564  else if ( returnCode == ossimGpkgSpatialRefSysRecord::OK_EXISTS )
1565  {
1566  // Record exists in database already(epsg:4326):
1567  srs_id = record.m_srs_id;
1568  }
1569  else if ( returnCode == ossimGpkgSpatialRefSysRecord::ERROR )
1570  {
1572  << "ossimGpkgWriter::writeGpkgSpatialRefSysTable ERROR initialized record!\n";
1573  }
1574  }
1575  return srs_id;
1576 
1577 } // End: ossimGpkgWriter::writeGpkgSpatialRefSysTable
1578 
1579 bool ossimGpkgWriter::writeGpkgContentsTable( sqlite3* db, const ossimDrect& rect )
1580 {
1581  bool status = false;
1582  if ( db )
1583  {
1584  ossimGpkgContentsRecord record;
1585  ossimDpt minPt( rect.ul().x, rect.lr().y);
1586  ossimDpt maxPt( rect.lr().x, rect.ul().y);
1587 
1588  if ( record.init( m_tileTableName, m_srs_id, minPt, maxPt ) )
1589  {
1590  status = record.insert( db );
1591  }
1592  }
1593  return status;
1594 }
1595 
1597 {
1598  bool status = false;
1599  if ( db )
1600  {
1602  ossimDpt minPt( rect.ul().x, rect.lr().y);
1603  ossimDpt maxPt( rect.lr().x, rect.ul().y);
1604 
1605  if ( record.init( m_tileTableName, m_srs_id, minPt, maxPt ) )
1606  {
1607  status = record.insert( db );
1608  }
1609  }
1610  return status;
1611 
1612 } // End: ossimGpkgWriter::writeGpkgTileMatrixSetTable
1613 
1615  ossim_int32 zoom_level,
1616  const ossimIpt& matrixSize,
1617  const ossimDpt& gsd )
1618 {
1619  bool status = false;
1620  if ( db )
1621  {
1623  if ( record.init( m_tileTableName, zoom_level, matrixSize, m_tileSize, gsd ) )
1624  {
1625  status = record.insert( db );
1626  }
1627  }
1628  return status;
1629 
1630 } // End: ossimGpkgWriter::writeGpkgTileMatrixTable
1631 
1633  ossim_int32 zoom_level,
1634  const ossimIrect& expandedAoi,
1635  const ossimIrect& clippedAoi )
1636 {
1637  bool status = false;
1638  if ( db )
1639  {
1640  // Compute the image rect:
1641  ossimIrect imageRect( clippedAoi.ul().x - expandedAoi.ul().x,
1642  clippedAoi.ul().y - expandedAoi.ul().y,
1643  clippedAoi.lr().x - expandedAoi.ul().x,
1644  clippedAoi.lr().y - expandedAoi.ul().y );
1645 
1647  if ( record.init( m_tileTableName, zoom_level, imageRect, m_clipRect ) )
1648  {
1649  status = record.insert( db );
1650  }
1651  }
1652  return status;
1653 
1654 } // ossimGpkgWriter::writeGpkgNsgTileMatrixExtentTable( ... )
1655 
1656 bool ossimGpkgWriter::saveState(ossimKeywordlist& kwl, const char* prefix) const
1657 {
1658  if ( m_kwl.valid() )
1659  {
1660  // Lazy man save state...
1661  kwl.add( prefix, *(m_kwl.get()), true );
1662  }
1663  return ossimImageFileWriter::saveState(kwl, prefix);
1664 }
1665 
1666 bool ossimGpkgWriter::loadState(const ossimKeywordlist& kwl, const char* prefix)
1667 {
1668  if ( m_kwl.valid() )
1669  {
1670  ossimString regularExpression;
1671  if ( prefix )
1672  {
1673  regularExpression = prefix;
1674  }
1675 
1676  regularExpression += "*";
1677  kwl.extractKeysThatMatch( *(m_kwl.get()), regularExpression );
1678 
1679  if ( prefix )
1680  {
1681  regularExpression = prefix;
1682  m_kwl->stripPrefixFromAll( regularExpression );
1683  }
1684  }
1685 
1686  return ossimImageFileWriter::loadState(kwl, prefix);
1687 }
1688 
1689 void ossimGpkgWriter::getImageTypeList(std::vector<ossimString>& imageTypeList)const
1690 {
1691  imageTypeList.push_back(ossimString("ossim_gpkg"));
1692 }
1693 
1695 {
1696  return ossimString("gpkg");
1697 }
1698 
1699 bool ossimGpkgWriter::hasImageType(const ossimString& imageType) const
1700 {
1701  if ( (imageType == "ossim_gpkg") || (imageType == "image/gpkg") )
1702  {
1703  return true;
1704  }
1705 
1706  return false;
1707 }
1708 
1710 {
1711  if ( property.valid() )
1712  {
1713  // See if it's one of our properties:
1714  std::string key = property->getName().string();
1715  if ( ( key == ADD_ALPHA_CHANNEL_KW ) ||
1716  ( key == ADD_ENTRY_KW ) ||
1717  ( key == ADD_LEVELS_KW ) ||
1718  ( key == ALIGN_TO_GRID_KW ) ||
1719  ( key == APPEND_KW ) ||
1720  ( key == BATCH_SIZE_KW ) ||
1721  ( key == COMPRESSION_LEVEL_KW ) ||
1723  ( key == EPSG_KW ) ||
1724  ( key == INCLUDE_BLANK_TILES_KW ) ||
1725  ( key == TILE_SIZE_KW ) ||
1726  ( key == TILE_TABLE_NAME_KW ) ||
1727  ( key == WRITER_MODE_KW ) ||
1728  ( key == ZOOM_LEVELS_KW ) )
1729  {
1730  ossimString value;
1731  property->valueToString(value);
1732  m_kwl->addPair( key, value.string(), true );
1733  }
1734  else
1735  {
1737  }
1738  }
1739 }
1740 
1742 {
1743  ossimRefPtr<ossimProperty> prop = 0;
1744  prop = ossimImageFileWriter::getProperty(name);
1745  return prop;
1746 }
1747 
1748 void ossimGpkgWriter::getPropertyNames(std::vector<ossimString>& propertyNames)const
1749 {
1750  propertyNames.push_back(ossimString(ADD_ALPHA_CHANNEL_KW));
1751  propertyNames.push_back(ossimString(ADD_ENTRY_KW));
1752  propertyNames.push_back(ossimString(ADD_LEVELS_KW));
1753  propertyNames.push_back(ossimString(ALIGN_TO_GRID_KW));
1754  propertyNames.push_back(ossimString(APPEND_KW));
1755  propertyNames.push_back(ossimString(BATCH_SIZE_KW));
1756  propertyNames.push_back(ossimString(COMPRESSION_LEVEL_KW));
1757  propertyNames.push_back(ossimString(ossimKeywordNames::COMPRESSION_QUALITY_KW));
1758  propertyNames.push_back(ossimString(EPSG_KW));
1759  propertyNames.push_back(ossimString(INCLUDE_BLANK_TILES_KW));
1760  propertyNames.push_back(ossimString(TILE_SIZE_KW));
1761  propertyNames.push_back(ossimString(TILE_TABLE_NAME_KW));
1762  propertyNames.push_back(ossimString(WRITER_MODE_KW));
1763  propertyNames.push_back(ossimString(ZOOM_LEVELS_KW));
1764 
1766 }
1767 
1768 void ossimGpkgWriter::setCompressionQuality( const std::string& quality )
1769 {
1771  quality );
1772 }
1773 
1775 {
1776  ossim_uint32 quality = 0;
1777  std::string value = m_kwl->findKey( std::string(ossimKeywordNames::COMPRESSION_QUALITY_KW) );
1778  if ( value.size() )
1779  {
1780  quality = ossimString(value).toUInt32();
1781  }
1782  return quality;
1783 }
1784 
1786 {
1787  ossimString result = ossimString("z_default_compression");
1788 #if 0
1789  switch (theCompressionLevel)
1790  {
1791  case Z_NO_COMPRESSION:
1792  result = ossimString("z_no_compression");
1793  break;
1794 
1795  case Z_BEST_SPEED:
1796  result = ossimString("z_best_speed");
1797  break;
1798 
1799  case Z_BEST_COMPRESSION:
1800  result = ossimString("z_best_compression");
1801  break;
1802 
1803  default:
1804  break;
1805  }
1806 #endif
1807  return result;
1808 }
1809 
1811 {
1812  bool status = true;
1813 #if 0
1814  ossimString s = level;
1815  s.downcase();
1816 
1817  if(s == "z_no_compression")
1818  {
1819  theCompressionLevel = Z_NO_COMPRESSION;
1820  }
1821  else if(s == "z_best_speed")
1822  {
1823  theCompressionLevel = Z_BEST_SPEED;
1824  }
1825  else if(s == "z_best_compression")
1826  {
1827  theCompressionLevel = Z_BEST_COMPRESSION;
1828  }
1829  else if(s == "z_default_compression")
1830  {
1831  theCompressionLevel = Z_DEFAULT_COMPRESSION;
1832  }
1833  else
1834  {
1835  status = false;
1836  }
1837 
1838  if (traceDebug())
1839  {
1841  << "DEBUG:"
1842  << "\nossimGpkgWriter::setCompressionLevel DEBUG"
1843  << "passed in level: " << level.c_str()
1844  << "writer level: " << getCompressionLevel().c_str()
1845  << std::endl;
1846  }
1847 #endif
1848  return status;
1849 }
1850 
1851 void ossimGpkgWriter::getGsd( const ossimDpt& fullResGsd,
1852  ossim_int32 fullResZoomLevel,
1853  ossim_int32 currentZoomLevel,
1854  ossimDpt& gsd )
1855 {
1856  if ( fullResGsd.hasNans() == false )
1857  {
1858  double delta = fullResZoomLevel - currentZoomLevel;
1859  if ( delta > 0 )
1860  {
1861  gsd = fullResGsd * ( std::pow( 2.0, delta ) );
1862  }
1863  else if ( delta < 0 )
1864  {
1865  gsd = fullResGsd / ( std::pow( 2, std::fabs(delta) ) );
1866  }
1867  else
1868  {
1869  gsd = fullResGsd;
1870  }
1871  }
1872 }
1873 
1875  ossimDpt& gsd ) const
1876 {
1877  if ( proj )
1878  {
1879  if ( proj->isGeographic() )
1880  {
1881  gsd = proj->getDecimalDegreesPerPixel();
1882  }
1883  else
1884  {
1885  gsd = proj->getMetersPerPixel();
1886  }
1887  }
1888 }
1889 
1891  ossimDpt& gsd ) const
1892 {
1893  if ( geom )
1894  {
1895  const ossimMapProjection* proj = geom->getAsMapProjection();
1896  if ( proj )
1897  {
1898  if ( proj->isGeographic() )
1899  {
1900  geom->getDegreesPerPixel( gsd );
1901  }
1902  else
1903  {
1904  geom->getMetersPerPixel( gsd );
1905  }
1906  }
1907  }
1908 }
1909 
1911  const ossimMapProjection* proj, ossim_int32 zoomLevel, ossimDpt& gsd ) const
1912 {
1913  if ( proj )
1914  {
1915  if ( alignToGrid() )
1916  {
1917  ossimDpt dims;
1918  if ( proj->isGeographic() )
1919  {
1920  dims.x = 360.0;
1921  dims.y = 180.0;
1922 
1923  gsd.x = 360.0/(m_tileSize.x*2);
1924  gsd.y = 180.0/m_tileSize.y;
1925 
1926  }
1927  else
1928  {
1929  getProjectionDimensionsInMeters( proj, dims );
1930 
1931  // Gsd that puts Earth in one tile:
1932  gsd.x = dims.x/m_tileSize.x;
1933  gsd.y = dims.y/m_tileSize.y;
1934  }
1935 
1936  if ( zoomLevel )
1937  {
1938  gsd = gsd / ( std::pow( 2.0, zoomLevel ) );
1939  }
1940  }
1941  else
1942  {
1943  gsd.makeNan();
1944 
1945  // Error message??? (drb)
1946  }
1947  }
1948 }
1949 
1951 {
1952  return keyIsTrue( ALIGN_TO_GRID_KW );
1953 }
1954 
1956 {
1957  return ( keyIsTrue( ADD_ENTRY_KW ) || keyIsTrue( ADD_LEVELS_KW ) || keyIsTrue( APPEND_KW ) );
1958 }
1959 
1960 bool ossimGpkgWriter::keyIsTrue( const std::string& key ) const
1961 {
1962  bool result = false;
1963  std::string value = m_kwl->findKey( key );
1964  if ( value.size() )
1965  {
1966  result = ossimString(value).toBool();
1967  }
1968  return result;
1969 }
1970 
1972 {
1973  if ( theInputConnection.valid() && proj )
1974  {
1975  ossimTypeNameVisitor visitor( ossimString("ossimViewInterface"),
1976  false, // firstofTypeFlag
1979  theInputConnection->accept( visitor );
1980  if ( visitor.getObjects().size() )
1981  {
1982  for( ossim_uint32 i = 0; i < visitor.getObjects().size(); ++i )
1983  {
1984  ossimViewInterface* viewClient = visitor.getObjectAs<ossimViewInterface>( i );
1985  if (viewClient)
1986  {
1987  viewClient->setView( proj );
1988  }
1989  }
1990 
1991  //---
1992  // After a view change the combiners must reset their input rectangles
1993  // for each image.
1994  //---
1996 
1997  //---
1998  // Cutter, if present, must be updated since the view has been
1999  // changed and the cutter's AOI is no longer relative. Note
2000  // the original AOI was already saved for our writer.
2001  //---
2002  reInitializeCutters( proj );
2003 
2005  }
2006  }
2007 }
2008 
2010 {
2011  if ( theInputConnection.valid() )
2012  {
2013  ossimTypeNameVisitor visitor( ossimString("ossimImageCombiner"),
2014  false, // firstofTypeFlag
2017 
2018  theInputConnection->accept( visitor );
2019  if ( visitor.getObjects().size() )
2020  {
2021  for( ossim_uint32 i = 0; i < visitor.getObjects().size(); ++i )
2022  {
2023  ossimImageCombiner* combiner = visitor.getObjectAs<ossimImageCombiner>( i );
2024  if (combiner)
2025  {
2026  combiner->initialize();
2027  }
2028  }
2029  }
2030  }
2031 }
2032 
2034 {
2035  if ( theInputConnection.valid() && proj )
2036  {
2037  ossimTypeNameVisitor visitor( ossimString("ossimRectangleCutFilter"),
2038  false, // firstofTypeFlag
2041 
2042  theInputConnection->accept( visitor );
2043  if ( visitor.getObjects().size() )
2044  {
2045  ossimIrect rect;
2046  getAoiFromRect( proj, m_clipRect, rect );
2047 
2048  for( ossim_uint32 i = 0; i < visitor.getObjects().size(); ++i )
2049  {
2051  if (cutter)
2052  {
2053  // Set the clip rect of the cutter.
2054  cutter->setRectangle(rect);
2055 
2056  // Enable the getTile...
2057  cutter->setEnableFlag( true );
2058  }
2059  }
2060  }
2061  }
2062 }
2063 
2065  ossimImageGeometry* geom ) const
2066 {
2068 
2069  if ( geom )
2070  {
2071  // "epsg" is a writer prop so check for it. This overrides the input projection.
2072  proj = getNewOutputProjection();
2073 
2074  if ( proj.valid() == false )
2075  {
2077  if ( sourceProj.valid() )
2078  {
2079  // Check the input projection. This could have been set by the caller.
2080  if ( sourceProj->getClassName() == "ossimEquDistCylProjection" )
2081  {
2082  // This will be an equdist with origin at 0, 0.
2083  proj = getNewGeographicProjection();
2084  }
2085  else if ( sourceProj->getClassName() == "ossimMercatorProjection" )
2086  {
2087  // WGS 84 / World Mercator:
2089  }
2090  else if ( sourceProj->getClassName() == "ossimGoogleProjection" )
2091  {
2092  proj = new ossimGoogleProjection(); // sourceProj;
2093  }
2094  else if ( sourceProj->getClassName() == "ossimUtmProjection" )
2095  {
2096  proj = dynamic_cast<ossimMapProjection*>(sourceProj->dup());
2097  }
2098  }
2099 
2100  // Final default:
2101  if ( proj.valid() == false )
2102  {
2103  //---
2104  // DEFAULT: Geographic, WGS 84
2105  // Note: May need to switch default to ossimMercatorProjection:
2106  //---
2107  proj = getNewGeographicProjection();
2108  }
2109  }
2110 
2111  if ( proj.valid() )
2112  {
2113  bool isGeographic = proj->isGeographic();
2114  bool gridAligned = alignToGrid();
2115 
2116  // Set the gsd:
2117  ossimDpt fullResGsd;
2118  getGsd( geom, fullResGsd );
2119 
2120  if ( isGeographic )
2121  {
2122  if ( gridAligned )
2123  {
2124  // Make pixels square if not already.
2125  if ( fullResGsd.y < fullResGsd.x )
2126  {
2127  fullResGsd.x = fullResGsd.y;
2128  }
2129  else if ( fullResGsd.x < fullResGsd.y )
2130  {
2131  fullResGsd.y = fullResGsd.x;
2132  }
2133  }
2134  proj->setDecimalDegreesPerPixel( fullResGsd );
2135  }
2136  else
2137  {
2138  if ( gridAligned && (proj->getClassName() == "ossimUtmProjection" ) )
2139  {
2140  // Turn off grid alignment for utm.
2141  gridAligned = false;
2142  }
2143 
2144  if ( gridAligned )
2145  {
2146  // Make pixels square if not already.
2147  if ( fullResGsd.y < fullResGsd.x )
2148  {
2149  fullResGsd.x = fullResGsd.y;
2150  }
2151  else if ( fullResGsd.x < fullResGsd.y )
2152  {
2153  fullResGsd.y = fullResGsd.x;
2154  }
2155  }
2156  proj->setMetersPerPixel( fullResGsd );
2157  }
2158  }
2159 
2160  } // Matches: if ( geom )
2161 
2162  return proj;
2163 
2164 } // End: ossimGpkgWriter::getNewOutputProjection( geom )
2165 
2167 {
2169 
2170  // "epsg" is a writer prop so check for it. This overrides the input projection.
2171  ossim_uint32 epsgCode = getEpsgCode();
2172  if ( epsgCode )
2173  {
2174  if ( epsgCode == 4326 )
2175  {
2176  // Geographic, WGS 84
2177  proj = getNewGeographicProjection();
2178  }
2179  else if ( epsgCode == 3395 )
2180  {
2181  // WGS 84 / World Mercator:
2183  }
2184  else if ( ( epsgCode == 3857 ) || ( epsgCode == 900913) )
2185  {
2186  proj = new ossimGoogleProjection();
2187  }
2188  else
2189  {
2190  // Go to the factory:
2191  ossimString name = "EPSG:";
2192  name += ossimString::toString(epsgCode);
2195  if ( proj.valid() )
2196  {
2197  proj = dynamic_cast<ossimMapProjection*>( proj.get() );
2198  }
2199  }
2200  }
2201 
2202  return proj;
2203 
2204 } // End: ossimGpkgWriter::getNewOutputProjection()
2205 
2207 {
2208  // Geographic, WGS 84, with origin at 0,0 for square pixels in decimal degrees.
2211  ossimEllipsoid(),
2212  ossimGpt(0.0, 0.0, 0.0, ossimDatumFactory::instance()->wgs84()) );
2213  return result;
2214 }
2215 
2217 {
2218  // EPSG: 3395, "WGS 84 / World Mercator", with origin at 0,0.
2221  ossimEllipsoid(),
2222  ossimGpt(0.0, 0.0, 0.0, ossimDatumFactory::instance()->wgs84()) );
2223 
2224  // Set the pcs(epsg) code:
2225  result->setPcsCode( 3395 );
2226 
2227  return result;
2228 }
2229 
2231 {
2232  std::string value = m_kwl->findKey( TILE_SIZE_KW );
2233  if ( value.size() )
2234  {
2235  tileSize.toPoint( value );
2236  }
2237  else
2238  {
2239  ossim::defaultTileSize( tileSize );
2240  }
2241 }
2242 
2244 {
2245  ossim_uint64 size = 32; // ???
2246  std::string value = m_kwl->findKey( BATCH_SIZE_KW );
2247  if ( value.size() )
2248  {
2249  size = ossimString(value).toUInt64();
2250  }
2251  return size;
2252 }
2253 
2254 void ossimGpkgWriter::getZoomLevels( std::vector<ossim_int32>& zoomLevels ) const
2255 {
2256  std::string value = m_kwl->findKey( ZOOM_LEVELS_KW );
2257  if ( value.size() )
2258  {
2259  ossimString stringOfPoints(value);
2260  if ( ossim::toSimpleVector(zoomLevels, stringOfPoints) )
2261  {
2262  std::sort( zoomLevels.begin(), zoomLevels.end() );
2263 
2264  // Check for negative and disallow.
2265  if ( zoomLevels[0] < 0 )
2266  {
2267  zoomLevels.clear();
2268 
2269  // Warning message???
2270  }
2271  }
2272  else
2273  {
2274  zoomLevels.clear();
2275  }
2276  }
2277  else
2278  {
2279  zoomLevels.clear();
2280  }
2281 }
2282 
2283 
2285  const ossimIrect& aoi,
2286  const ossimDpt& sourceGsd,
2287  std::vector<ossim_int32>& zoomLevels,
2288  ossimDpt& fullResGsd ) const
2289 {
2290  if ( proj && (aoi.hasNans() == false) )
2291  {
2292  // Initial assignment of full res gsd. Will change if aligned to grid is on.
2293  fullResGsd = sourceGsd;
2294 
2295  // Check for user specified levels.
2296  getZoomLevels( zoomLevels );
2297 
2298  if ( zoomLevels.size() )
2299  {
2300  if ( alignToGrid() )
2301  {
2302  ossim_int32 zoomLevel = zoomLevels[zoomLevels.size()-1];
2303  if ( proj->isGeographic() )
2304  {
2305  fullResGsd.x = 360.0/(m_tileSize.x*2);
2306  fullResGsd.y = 180.0/m_tileSize.y;
2307  }
2308  else
2309  {
2310  ossimDpt dims;
2311  getProjectionDimensionsInMeters( proj, dims );
2312 
2313  // Gsd that puts Earth in one tile:
2314  fullResGsd.x = dims.x/m_tileSize.x;
2315  fullResGsd.y = dims.y/m_tileSize.y;
2316  }
2317 
2318  if ( zoomLevel )
2319  {
2320  fullResGsd = fullResGsd / ( std::pow( 2.0, zoomLevel ) );
2321  }
2322  }
2323  }
2324  else
2325  {
2326  ossim_int32 levels = getNumberOfZoomLevels( aoi );
2327  if ( levels )
2328  {
2329  if ( alignToGrid() )
2330  {
2331  ossimDpt zoomGsd;
2332 
2333  if ( proj->isGeographic() )
2334  {
2335  zoomGsd.x = 360.0/(m_tileSize.x*2);
2336  zoomGsd.y = 180.0/m_tileSize.y;
2337  }
2338  else
2339  {
2340  ossimDpt dims;
2341  getProjectionDimensionsInMeters( proj, dims );
2342 
2343  // Gsd that puts Earth in one tile:
2344  zoomGsd.x = dims.x/m_tileSize.x;
2345  zoomGsd.y = dims.y/m_tileSize.y;
2346  }
2347 
2348  if ( fullResGsd.hasNans() == false )
2349  {
2350  // If zoom level gsd is below this threshold we stop there.
2351  ossimDpt gsdThreshold = fullResGsd * 1.5;
2352 
2353  // Start full Earth in 2x1 tiles:
2354  ossim_int32 startZoomLevel = 0;
2355  while ( ( zoomGsd.x > gsdThreshold.x ) &&
2356  ( zoomGsd.y > gsdThreshold.y ) )
2357  {
2358  // Go to next level.
2359  zoomGsd = zoomGsd/2.0;
2360  fullResGsd = zoomGsd;
2361  ++startZoomLevel;
2362  }
2363 
2364  ossim_int32 stopZoomLevel = startZoomLevel-(levels-1);
2365 
2366  if ( stopZoomLevel < 0 ) stopZoomLevel = 0;
2367 
2368  for ( ossim_int32 i = stopZoomLevel; i <= startZoomLevel; ++i )
2369  {
2370  zoomLevels.push_back(i);
2371  }
2372  }
2373  }
2374  else // Not grid aligned.
2375  {
2376  //---
2377  // If not grid aligned the full res gsd is the inputs which is
2378  // already set.
2379  //---
2380  for ( ossim_int32 i = 0; i < levels; ++i )
2381  {
2382  zoomLevels.push_back(i);
2383  }
2384  }
2385  }
2386  }
2387  }
2388 
2389  if (traceDebug())
2390  {
2392  << "ossimGpkgWriter::getZoomLevels DEBUG"
2393  << "aoi: " << aoi << "\n"
2394  << "sourceGsd: " << sourceGsd << "\n"
2395  << "\nfullResGsd: " << fullResGsd << "\n"
2396  << "levels: (";
2397  std::vector<ossim_int32>::const_iterator i = zoomLevels.begin();
2398  while ( i != zoomLevels.end() )
2399  {
2401  ++i;
2402  if ( i != zoomLevels.end() )
2403  {
2405  }
2406  else
2407  {
2409  }
2410  }
2411  }
2412 
2413 } // End: ossimGpkgWriter::getZoomLevels( proj, aoi, ... )
2414 
2416 {
2417  ossim_int32 result = 0;
2418 
2419  if ( aoi.hasNans() == false )
2420  {
2421  ossim_float64 w = aoi.width();
2422  ossim_float64 h = aoi.height();
2423 
2424  // Take it down to at least a quarter of a tile.
2425  const ossim_float64 TW = m_tileSize.x/4;
2426  const ossim_float64 TH = m_tileSize.y/4;
2427  if ( w && h )
2428  {
2429  ++result; // At least one level.
2430  while ( ( TW < w ) && ( TH < h ) )
2431  {
2432  w /= 2.0;
2433  h /= 2.0;
2434  ++result;
2435  }
2436  }
2437  }
2438 
2439  if (traceDebug())
2440  {
2442  << "ossimGpkgWriter::getNumberOfZoomLevels DEBUG"
2443  << "\nlevels: " << result << "\n";
2444  }
2445 
2446  return result;
2447 }
2448 
2450  const ossimDrect& rect,
2451  ossimIrect& aoi )
2452 {
2453  static const char MODULE[] = "ossimGpkgWriter::getAoi";
2454 
2455  if (traceDebug())
2456  {
2457  ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " entered...\n";
2458  }
2459 
2460  // Take the aoi edges(minPt, maxPt), shift to center pixel and return the aoi.
2461  if ( proj )
2462  {
2463  ossimDpt gsd;
2464  getGsd( proj, gsd );
2465  ossimDpt halfGsd = gsd/2.0;
2466 
2467  if (traceDebug())
2468  {
2469  ossimNotify(ossimNotifyLevel_DEBUG) << "gsd: " << gsd << "\n";
2470  }
2471 
2472  ossimDpt ulDpt;
2473  ossimDpt lrDpt;
2474 
2475  if ( proj->isGeographic() )
2476  {
2477  // Convert the ground points to view space.
2478  ossimGpt ulGpt( rect.ul().y-halfGsd.y, rect.ul().x+halfGsd.x, 0.0 );
2479  ossimGpt lrGpt( rect.lr().y+halfGsd.y, rect.lr().x-halfGsd.x, 0.0 );
2480 
2481  // Get the view coords of the aoi.
2482  proj->worldToLineSample(ulGpt, ulDpt);
2483  proj->worldToLineSample(lrGpt, lrDpt);
2484 
2485  if (traceDebug())
2486  {
2488  << "\nulGpt: " << ulGpt
2489  << "\nlrGpt: " << lrGpt
2490  << "\nulDpt: " << ulDpt
2491  << "\nlrDpt: " << lrDpt
2492  << "\n";
2493  }
2494  }
2495  else
2496  {
2497  ossimDpt ulEnPt( rect.ul().x+halfGsd.x, rect.ul().y-halfGsd.y );
2498  ossimDpt lrEnPt( rect.lr().x-halfGsd.x, rect.lr().y+halfGsd.y );
2499 
2500  // Get the view coords of the aoi.
2501  proj->eastingNorthingToLineSample( ulEnPt, ulDpt );
2502  proj->eastingNorthingToLineSample( lrEnPt, lrDpt );
2503  }
2504 
2505  // Area of interest in view space on point boundaries.
2506  aoi = ossimIrect( ossimIpt(ulDpt), ossimIpt(lrDpt) );
2507 
2508  if (traceDebug())
2509  {
2511  << "aoi: " << aoi << "\n"
2512  << MODULE << " exited...\n";
2513  }
2514  }
2515 
2516 } // End: ossimGpkgWriter::getAoiFromRect( ... )
2517 
2519  ossimIrect& expandedAoi ) const
2520 {
2521  expandedAoi = aoi;
2522  expandedAoi.stretchToTileBoundary( m_tileSize );
2523 }
2524 
2526  const ossimIrect& rect, ossimIpt& matrixSize ) const
2527 {
2528  matrixSize.x = rect.width()/m_tileSize.x;
2529  if ( rect.width() % m_tileSize.x )
2530  {
2531  ++matrixSize.x;
2532  }
2533  matrixSize.y = rect.height()/m_tileSize.y;
2534  if ( rect.height() % m_tileSize.y )
2535  {
2536  ++matrixSize.y;
2537  }
2538 }
2539 
2541 {
2542  if ( proj )
2543  {
2544  ossimDpt gsd;
2545  getGsd( proj, gsd );
2546  ossimDpt halfGsd = gsd/2.0;
2547 
2548  bool gridAligned = alignToGrid();
2549  bool isGeographic = proj->isGeographic();
2550  if ( isGeographic )
2551  {
2552  ossimGpt tie(0.0, 0.0, 0.0);
2553  if ( gridAligned )
2554  {
2555  tie.lon = m_projectionBoundingRect.ul().x + halfGsd.x;
2556  tie.lat = m_projectionBoundingRect.ul().y - halfGsd.y;
2557  }
2558  else
2559  {
2560  tie.lon = m_sceneBoundingRect.ul().x + halfGsd.x;
2561  tie.lat = m_sceneBoundingRect.ul().y - halfGsd.y;
2562  }
2563  proj->setUlTiePoints(tie);
2564 
2565  if ( traceDebug() )
2566  {
2568  << "ossimGpkgWriter::setProjectionTie DEBUG:\n"
2569  << "tie: " << tie << std::endl;
2570  }
2571  }
2572  else
2573  {
2574  ossimDpt tie( 0.0, 0.0 );
2575  if ( gridAligned )
2576  {
2577  tie.x = m_projectionBoundingRect.ul().x + halfGsd.x;
2578  tie.y = m_projectionBoundingRect.ul().y - halfGsd.y;
2579  }
2580  else
2581  {
2582  tie.x = m_sceneBoundingRect.ul().x + halfGsd.x;
2583  tie.y = m_sceneBoundingRect.ul().y - halfGsd.y;
2584  }
2585 
2586  proj->setUlTiePoints(tie);
2587 
2588  if ( traceDebug() )
2589  {
2591  << "ossimGpkgWriter::setProjectionTie DEBUG:\n"
2592  << "tie: " << tie << std::endl;
2593  }
2594  }
2595  }
2596 
2597 } // End: ossimGpkgWriter::setProjectionTie
2598 
2600 {
2601  // Default to mixed.
2603 
2604  std::string value = m_kwl->findKey( WRITER_MODE_KW );
2605  if ( value.size() )
2606  {
2607  ossimString os(value);
2608  os.downcase();
2609 
2610  if ( os == "jpeg" )
2611  {
2613  }
2614  else if ( os == "png" )
2615  {
2617  }
2618  else if ( os == "pnga" )
2619  {
2621  }
2622  }
2623  return mode;
2624 }
2625 
2627 {
2628  std::string result;
2629  switch ( mode )
2630  {
2632  {
2633  result = "jpeg";
2634  break;
2635  }
2637  {
2638  result = "mixed";
2639  break;
2640  }
2642  {
2643  result = "png";
2644  break;
2645  }
2647  {
2648  result = "pnga";
2649  break;
2650  }
2652  default:
2653  {
2654  result = "unknown";
2655  break;
2656  }
2657  }
2658  return result;
2659 }
2660 
2662 {
2663  bool result = false;
2665  if ( mode == OSSIM_GPGK_WRITER_MODE_JPEG )
2666  {
2667  result = true;
2668  }
2669  return result;
2670 }
2671 
2673 {
2674  ossim_uint32 result = 0;
2675  std::string value = m_kwl->findKey( EPSG_KW );
2676  if ( value.size() )
2677  {
2678  result = ossimString(value).toUInt32();
2679  }
2680  return result;
2681 }
2682 
2684  const ossimMapProjection* proj, ossimDpt& dims ) const
2685 {
2686  if ( proj )
2687  {
2688  ossim_uint32 epsgCode = proj->getPcsCode();
2689 
2690  switch( epsgCode )
2691  {
2692  case 4326:
2693  {
2694  if ( proj->getOrigin().lat == 0.0 )
2695  {
2696  // 20015110.0 * 2 = 40030220.0;
2697  dims.x = 40030220.0;
2698 
2699  // 10007555.0 * 2 = 20015110;
2700  dims.y = 20015110;
2701  }
2702  else
2703  {
2704  std::ostringstream errMsg;
2705  errMsg << "ossimGpkgWriter::getProjectionDimensionsInMeters ERROR:\n"
2706  << "EPSG 4326 Origin latitude is not at 0.\n";
2707  throw ossimException( errMsg.str() );
2708  }
2709  break;
2710  }
2711  case 3395:
2712  {
2713  //---
2714  // http://spatialreference.org/ref/epsg/3395/
2715  // WGS84 Bounds: -180.0000, -80.0000, 180.0000, 84.0000
2716  // Projected Bounds: -20037508.3428, -15496570.7397, 20037508.3428, 18764656.2314
2717  //---
2718  dims.x = 40075016.6856;
2719  dims.y = 34261226.9711;
2720 
2721  break;
2722  }
2723  case 3857:
2724  {
2725  // Bounds:
2726  // -20037508.342789244,-20037508.342789244,20037508.342789244,20037508.342789244
2727  //
2728  dims.x = 40075016.685578488;//40075016.6856;
2729  dims.y = 40075016.685578488;//40075016.6856;
2730  break;
2731  }
2732  default:
2733  {
2734  std::ostringstream errMsg;
2735  errMsg << "ossimGpkgWriter::getProjectionDimensionsInMeters ERROR:\n"
2736  << "Unhandled espg code: " << epsgCode << "\n";
2737  throw ossimException( errMsg.str() );
2738  }
2739  }
2740  }
2741 
2742 } // End: ossimGpkgWriter::getProjectionDimensionsInMeters
2743 
2744 #if 0
2745 void ossimGpkgWriter::clipToProjectionBounds(
2746  const ossimMapProjection* proj, const ossimGpt& inUlGpt, const ossimGpt& inLrGpt,
2747  ossimGpt& outUlGpt, ossimGpt& outLrGpt ) const
2748 {
2749  if ( proj )
2750  {
2751  outUlGpt = inUlGpt;
2752  outLrGpt = inLrGpt;
2753 
2754  ossim_uint32 code = proj->getPcsCode();
2755 
2756  if ( code == 3395 )
2757  {
2758  //---
2759  // http://spatialreference.org/ref/epsg/3395/
2760  // WGS84 Bounds: -180.0000, -80.0000, 180.0000, 84.0000
2761  //---
2762  const ossim_float64 MAX_LAT = 84.0;
2763  const ossim_float64 MIN_LAT = -80.0;
2764 
2765  if ( outUlGpt.lat > MAX_LAT ) outUlGpt.lat = MAX_LAT;
2766  if ( outLrGpt.lat < MIN_LAT ) outLrGpt.lat = MIN_LAT;
2767  }
2768  else if ( code == 3857 )
2769  {
2770  //---
2771  // http://epsg.io/3857
2772  // WGS84 bounds: -180.0 -85.06, 180.0 85.06
2773  //---
2774  ossim_float64 MAX_LAT = 85.05112878;
2775  ossim_float64 MIN_LAT = -85.05112878;
2776 
2777  if ( outUlGpt.lat > MAX_LAT ) outUlGpt.lat = MAX_LAT;
2778  if ( outLrGpt.lat < MIN_LAT ) outLrGpt.lat = MIN_LAT;
2779  }
2780  }
2781 
2782 } // End: ossimGpkgWriter::clipToProjectionBounds
2783 #endif
2784 
2786 {
2787  if ( proj )
2788  {
2789  ossim_uint32 epsgCode = proj->getPcsCode();
2790 
2791  switch( epsgCode )
2792  {
2793  case 4326:
2794  {
2795  if ( proj->getOrigin().lat == 0.0 )
2796  {
2798  ossimDrect( -180.0, 90.0, 180.0, -90.0, OSSIM_RIGHT_HANDED);
2799  }
2800  else
2801  {
2802  std::ostringstream errMsg;
2803  errMsg << "ossimGpkgWriter::initializeProjectionRect ERROR:\n"
2804  << "EPSG 4326 Origin latitude is not at 0.\n";
2805  throw ossimException( errMsg.str() );
2806  }
2807  break;
2808  }
2809  case 3395:
2810  {
2811  //---
2812  // http://spatialreference.org/ref/epsg/3395/
2813  // WGS84 Bounds: -180.0000, -80.0000, 180.0000, 84.0000
2814  // Projected Bounds: -20037508.3428, -15496570.7397, 20037508.3428, 18764656.2314
2815  //---
2817  ossimDrect( -20037508.3428, 18764656.2314,
2818  20037508.3428, -15496570.7397, OSSIM_RIGHT_HANDED );
2819  break;
2820  }
2821  case 3857:
2822  {
2824  ossimDrect( -20037508.342789244, 20037508.342789244,
2825  20037508.342789244, -20037508.342789244, OSSIM_RIGHT_HANDED);
2826  break;
2827  }
2828  default:
2829  {
2830  std::ostringstream errMsg;
2831  errMsg << "ossimGpkgWriter::initializeProjectionRect ERROR:\n"
2832  << "Unhandled espg code: " << epsgCode << "\n";
2833  throw ossimException( errMsg.str() );
2834  }
2835  }
2836  }
2837 
2838  if (traceDebug())
2839  {
2841  << "ossimGpkgWriter::initializeProjectionRect:\n"
2842  << "projection bounding rect: " << m_projectionBoundingRect
2843  << std::endl;
2844  }
2845 
2846 } // End: ossimGpkgWriter::initializeProjectionRect
2847 
2849  const ossimIrect& aoi,
2850  ossimDrect& rect )
2851 {
2852  if ( proj )
2853  {
2854  ossimDpt gsd;
2855  getGsd( proj, gsd );
2856  ossimDpt halfGsd = gsd/2.0;
2857 
2858  ossimDpt ulLineSample = aoi.ul();
2859  ossimDpt lrLineSample = aoi.lr();
2860 
2861  if ( proj->isGeographic() )
2862  {
2863  // Convert line, sample to ground points:
2864  ossimGpt ulGpt;
2865  ossimGpt lrGpt;
2866  proj->lineSampleToWorld( ulLineSample, ulGpt );
2867  proj->lineSampleToWorld( lrLineSample, lrGpt );
2868 
2869  ossim_float64 ulx = ossim::max<ossim_float64>( ulGpt.lon - halfGsd.x, -180.0 );
2870  ossim_float64 uly = ossim::min<ossim_float64>( ulGpt.lat + halfGsd.y, 90.0 );
2871  ossim_float64 lrx = ossim::min<ossim_float64>( lrGpt.lon + halfGsd.x, 180.0 );
2872  ossim_float64 lry = ossim::max<ossim_float64>( lrGpt.lat - halfGsd.y, -90.0 );
2873 
2874  rect = ossimDrect( ulx, uly, lrx, lry, OSSIM_RIGHT_HANDED );
2875  }
2876  else
2877  {
2878  ossimDpt ulEastingNorthingPt;
2879  ossimDpt lrEastingNorthingPt;
2881  aoi.ul(), ulEastingNorthingPt );
2883  aoi.lr(), lrEastingNorthingPt );
2884 
2885  // Edge to edge scene bounding rect.
2886  rect = ossimDrect( ulEastingNorthingPt.x - halfGsd.x,
2887  ulEastingNorthingPt.y + halfGsd.y,
2888  lrEastingNorthingPt.x + halfGsd.x,
2889  lrEastingNorthingPt.y - halfGsd.y,
2891  }
2892 
2893  } // Matches: if ( proj.valid() )
2894 
2895  if (traceDebug())
2896  {
2898  << "ossimGpkgWriter::initializeRect:"
2899  << "\naoi: " << aoi
2900  << "\nrect: " << rect
2901  << std::endl;
2902  }
2903 
2904 } // End: ossimGpkgWriter::initializeRect
2905 
2906 void ossimGpkgWriter::getTileTableName( std::string& tileTableName ) const
2907 {
2908  std::string key = "tile_table_name";
2909  tileTableName = m_kwl->findKey( key );
2910  if ( tileTableName.empty() )
2911  {
2912  tileTableName = "tiles";
2913  }
2914 }
2915 
2917 {
2918  bool status = false;
2919  file.string() = m_kwl->findKey( std::string(ossimKeywordNames::FILENAME_KW) );
2920  if ( file.size() > 0 )
2921  {
2922  status = true;
2923  }
2924  return status;
2925 }
2926 
2928 {
2930  if ( mode == OSSIM_GPGK_WRITER_MODE_JPEG )
2931  {
2934  m_fullTileCodecAlpha = false;
2935  m_partialTileCodecAlpha = false;
2936  }
2937  else if(mode == OSSIM_GPGK_WRITER_MODE_PNG)
2938  {
2941  m_fullTileCodecAlpha = false;
2942  m_partialTileCodecAlpha = false;
2943  }
2944  else if( mode == OSSIM_GPGK_WRITER_MODE_PNGA )
2945  {
2948  m_fullTileCodecAlpha = true;
2949  m_partialTileCodecAlpha = true;
2950  }
2951  else if( mode == OSSIM_GPGK_WRITER_MODE_MIXED )
2952  {
2955  m_fullTileCodecAlpha = false;
2956  m_partialTileCodecAlpha = true;
2957  }
2958  else
2959  {
2960  m_fullTileCodec = 0;
2961  m_partialTileCodec = 0;
2962  }
2963 
2965  {
2966  // Note: This will only take for jpeg. Png uses compression_level and need to add.
2967  ossim_uint32 quality = getCompressionQuality();
2968  if ( !quality )
2969  {
2971  }
2972  m_fullTileCodec->setProperty("quality", ossimString::toString(quality));
2974  }
2975  else
2976  {
2977  std::ostringstream errMsg;
2978  errMsg << "ossimGpkgWriter::initializeCodec ERROR:\n"
2979  << "Unsupported writer mode: " << getWriterModeString( mode )
2980  << "\nCheck for ossim png plugin..."
2981  << "\n";
2982  throw ossimException( errMsg.str() );
2983  }
2984 }
2985 
2987 {
2988  const std::string KEY = "cut_wms_bbox";
2989  return getRect( KEY, rect );
2990 }
2991 
2992 bool ossimGpkgWriter::getClipExtents( ossimDrect& rect, bool& alignToGridFlag ) const
2993 {
2994  bool result = getRect( CLIP_EXTENTS_KW, rect );
2995  alignToGridFlag = true;
2996  ossimString value = m_kwl->findKey( CLIP_EXTENTS_ALIGN_TO_GRID_KW );
2997  if(!value.empty()) alignToGridFlag = value.toBool();
2998 
2999  return result;
3000 }
3001 
3002 bool ossimGpkgWriter::getRect( const std::string& key, ossimDrect& rect ) const
3003 {
3004  bool status = false;
3005  ossimString value;
3006  value.string() = m_kwl->findKey( key );
3007  if ( value.size() )
3008  {
3009  std::string replacementPattern = value.string() + std::string(":");
3010  ossimString bbox = value.downcase().replaceAllThatMatch(replacementPattern.c_str(),"");
3011  std::vector<ossimString> cutBox;
3012  bbox.split( cutBox, "," );
3013  if( cutBox.size() == 4 )
3014  {
3015  ossim_float64 minx = cutBox[0].toFloat64();
3016  ossim_float64 miny = cutBox[1].toFloat64();
3017  ossim_float64 maxx = cutBox[2].toFloat64();
3018  ossim_float64 maxy = cutBox[3].toFloat64();
3019  rect = ossimDrect( minx, maxy, maxx, miny );
3020  status = true;
3021  }
3022  }
3023  return status;
3024 }
3025 
3027  const std::vector<ossim_int32>& currentZoomLevels,
3028  const std::vector<ossim_int32>& newZoomLevels ) const
3029 {
3030  static const char MODULE[] = "ossimGpkgWriter::checkLevels";
3031 
3032  // Assuming sorted, low to high arrays.
3033  if ( currentZoomLevels.size() )
3034  {
3035  if ( newZoomLevels.size() )
3036  {
3037  // Check for new level lower then existing.
3038  if ( newZoomLevels[0] < currentZoomLevels[0] )
3039  {
3040  std::ostringstream errMsg;
3041  errMsg << MODULE
3042  << " ERROR:\n"
3043  << "New level[" << newZoomLevels[0]
3044  << "] will not fit in existing extents of level["
3045  << currentZoomLevels[0] << "].\n";
3046  throw ossimException( errMsg.str() );
3047  }
3048 
3049  // 2) level already present
3050  std::vector<ossim_int32>::const_iterator newIdx = newZoomLevels.begin();
3051  while ( newIdx < newZoomLevels.end() )
3052  {
3053  std::vector<ossim_int32>::const_iterator currentIdx = currentZoomLevels.begin();
3054  while ( currentIdx != currentZoomLevels.end() )
3055  {
3056  if ( (*newIdx) == (*currentIdx) )
3057  {
3058  std::ostringstream errMsg;
3059  errMsg << MODULE
3060  << " ERROR:\n"
3061  << "New level[" << (*newIdx)
3062  << "] already exists in current matrix set.\n";
3063  throw ossimException( errMsg.str() );
3064  }
3065  ++currentIdx;
3066  }
3067  ++newIdx;
3068  }
3069  }
3070  }
3071 
3072 } // End: ossimGpkgWriter::checkLevels
3073 
3075  ossim_int32 level, ossim_int32 row, ossim_int32 col ) const
3076 {
3077  bool status = false;
3078 
3079  if ( m_zoomLevels.size() && (m_zoomLevels.size() == m_zoomLevelMatrixSizes.size()) )
3080  {
3081  std::vector<ossim_int32>::const_iterator zIdx = m_zoomLevels.begin();
3082  std::vector<ossimIpt>::const_iterator sIdx = m_zoomLevelMatrixSizes.begin();
3083  while ( zIdx != m_zoomLevels.end() )
3084  {
3085  if ( (*zIdx) == level )
3086  {
3087  if ( ( row < (*sIdx).y ) && ( col < (*sIdx).x ) &&
3088  ( row > -1 ) && ( col > -1 ) )
3089  {
3090  status = true;
3091  break;
3092  }
3093  }
3094  ++zIdx;
3095  ++sIdx;
3096  }
3097  }
3098 
3099  return status;
3100 
3101 } // End: ossimGpkgWriter::isValidZoomLevel( ossim_int32 level ) const
3102 
3103 
3104 
3106  const ossimDpt& desiredGsd ) const
3107 {
3108  if ( proj )
3109  {
3110  if ( desiredGsd.hasNans() == false )
3111  {
3112  // Current projection gsd:
3113  ossimDpt currentGsd;
3114  getGsd( proj, currentGsd );
3115 
3116  //---
3117  // Set the scale of projection to the stop gsd:
3118  // True on applyScale is to recenter tie.
3119  //---
3120  ossimDpt scale;
3121  scale.x = desiredGsd.x / currentGsd.x;
3122  scale.y = desiredGsd.y / currentGsd.y;
3123  proj->applyScale( scale, true );
3124 
3125 #if 0
3126  cout << "ossimGpkgWriter::applyScaleToProjection DEBUG:"
3127  << "\nproj gsd: " << currentGsd
3128  << "\ndesired gsd: " << desiredGsd
3129  << "\nscale: " << scale
3130  << "\n";
3131 #endif
3132  }
3133  }
3134 }
3135 
void setRectangle(const ossimIrect &rect)
static ossimCodecFactoryRegistry * instance()
ossim_uint32 x
ossimGpkgWriterMode getWriterMode() const
Gets the writer mode.
bool insert(sqlite3 *db)
Inserst this record into gpkg_contents table.
virtual const ossimDpt & getDecimalDegreesPerPixel() const
Returns decimal degrees per pixel as an ossimDpt with "x" representing longitude and "y" representing...
static bool createTable(sqlite3 *db, const std::string &tableName)
Creates table in database.
virtual ~ossimGpkgWriter()
void checkLevels(const std::vector< ossim_int32 > &currentZoomLevels, const std::vector< ossim_int32 > &newZoomLevels) const
Checks for: new level lower then existing.
virtual ossimObject * dup() const =0
void stripPrefixFromAll(const ossimString &regularExpression)
void getTileSize(ossimIpt &tileSize) const
void initializeCodec()
Initializes m_fullTileCodec and m_partialTileCodec.
static bool remove(const ossimFilename &pathname)
Removes pathname from filesystem if supported by platform.
ossim_float64 max< ossim_float64 >(ossim_float64 a, ossim_float64 b)
Definition: ossimCommon.h:250
virtual bool writeTile(ossimRefPtr< ossimImageData > &tile, ossim_int32 zoomLevel, ossim_int64 row, ossim_int64 col)
Direct interface to writing a tile to database.
std::vector< ossim_int32 > m_zoomLevels
Holds zoom level indexes for connectionless write tile.
std::basic_ostringstream< char > ostringstream
Class for char output memory streams.
Definition: ossimIosFwd.h:35
bool append() const
Check if file is to be open new or appended.
bool writeGpkgTileMatrixSetTable(sqlite3 *db, const ossimDrect &boundingRect)
virtual void computeAlphaChannel()
Computes the alpha channel.
ossimRefPtr< ossimCodecBase > m_partialTileCodec
virtual void finalizeTileProcessing()
Calls sqlite3_finalize(pStmt) terminating tile processing.
ossimRefPtr< ossimMapProjection > getNewWorldMercatorProjection() const
virtual void getImageTypeList(std::vector< ossimString > &imageTypeList) const
void getImageTypeList(std::vector<ossimString>& imageTypeList)const
This will be a base for all combiners.
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
ossim_uint32 y
bool valid() const
Definition: ossimRefPtr.h:75
virtual bool isOpen() const
const ossimGpkgTileMatrixSetRecord & getTileMatrixSet() const
bool insert(sqlite3 *db)
Inserst this record into gpkg_spatial_ref_sys table.
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.
int exec(sqlite3 *db, const std::string &sql)
Preforms sqlite3_prepare_v2, sqlite3_step and sqlite3_finalize.
virtual ossimDpt worldToLineSample(const ossimGpt &worldPoint) const
const ossimDpt & ul() const
Definition: ossimDrect.h:339
bool insert(sqlite3 *db)
Inserst this record into gpkg_spatial_ref_sys table.
virtual bool loadState(const ossimKeywordlist &kwl, const char *prefix=0)
double y
Definition: ossimDpt.h:165
ossim_uint32 height() const
Definition: ossimIrect.h:487
ossim_int32 m_srs_id
virtual ossimRefPtr< ossimImageData > getNextTile(ossim_uint32 resLevel=0)
virtual bool saveState(ossimKeywordlist &kwl, const char *prefix=0) const
static bool createTable(sqlite3 *db)
Creates table in database.
ossim_int32 writeGpkgSpatialRefSysTable(sqlite3 *db, const ossimMapProjection *proj)
static ossimString toString(bool aValue)
Numeric to string methods.
void setProjectionTie(ossimMapProjection *proj) const
void getZoomLevelMatrixSizes(std::vector< ossimIpt > &zoomLevelMatrixSizes) const
Gets zoom level matrix of all tile matrixes.
virtual bool isGeographic() const
OSSIM_DLL void defaultTileSize(ossimIpt &tileSize)
bool initializeGpkg()
Initializes the output gpkg file.
const ossimIpt & ul() const
Definition: ossimIrect.h:274
void split(std::vector< ossimString > &result, const ossimString &separatorList, bool skipBlankFields=false) const
Splits this string into a vector of strings (fields) using the delimiter list specified.
virtual ossimDataObjectStatus getDataObjectStatus() const
ossim_int32 getNumberOfZoomLevels(const ossimIrect &aoi) const
Zoom levels needed to get AOI down to one tile.
void addPair(const std::string &key, const std::string &value, bool overwrite=true)
virtual ossimString getClassName() const
Definition: ossimObject.cpp:64
virtual void setDecimalDegreesPerPixel(const ossimDpt &gsd)
#define MAX_LAT
ossim_uint32 toUInt32() const
void getGsd(const ossimDpt &fullResGsd, ossim_int32 fullResZoomLevel, ossim_int32 currentZoomLevel, ossimDpt &gsd)
bool requiresEightBit() const
static bool createTable(sqlite3 *db)
Creates table in database.
Pure virtual base class for image file writers.
void getMatrixSize(const ossimIrect &rect, ossimIpt &matrixSize) const
ossimDpt getDegreesPerPixel() const
Returns the resolution of this image in degrees/pixel.
virtual void getPropertyNames(std::vector< ossimString > &propertyNames) const
Pushes this&#39;s names onto the list of property names.
bool getTileEntry(sqlite3 *db, const std::string &tileTableName, ossimGpkgTileEntry &entry)
Gets tile entry whos table_name field matches tileTableName.
ossimRefPtr< ossimKeywordlist > m_kwl
Hold all options.
std::string getWriterModeString(ossimGpkgWriterMode mode) const
Gets the writer mode as string.
bool isValidZoomLevelRowCol(ossim_int32 level, ossim_int32 row, ossim_int32 col) const
Checks to see if level, row, column are within range of existing gpkg.
virtual void getPropertyNames(std::vector< ossimString > &propertyNames) const
void getAoiFromRect(const ossimMapProjection *proj, const ossimDrect &rect, ossimIrect &aoi)
Get the view coordinates for edge to edge rect.
virtual void applyScale(const ossimDpt &scale, bool recenterTiePoint)
Applies scale to theDeltaLonPerPixel, theDeltaLatPerPixel and theMetersPerPixel data members (eg: the...
virtual void setMetersPerPixel(const ossimDpt &gsd)
virtual ossimString getExtension() const
Returns a 3-letter extension from the image type descriptor (theOutputImageType) that can be used for...
ossimDrect m_clipRect
AOI clipped to projection rect.
bool toSimpleVector(std::vector< T > &result, const ossimString &stringOfPoints)
Definition: ossimCommon.h:537
virtual ossimString getClassName() const
ossimConnectableObject * getInput(ossim_uint32 index=0)
returns the object at the specified index.
static bool createTable(sqlite3 *db)
Creates table in database.
double ossim_float64
void add(const char *prefix, const ossimKeywordlist &kwl, bool overwrite=true)
virtual bool init(sqlite3_stmt *pStmt)
Initialize from database.
static bool createTable(sqlite3 *db)
Creates gpkg_contents table in database.
virtual bool encode(const ossimRefPtr< ossimImageData > &in, std::vector< ossim_uint8 > &out) const =0
Encode method.
void writeTiles(sqlite3 *db, const ossimIrect &aoi, ossim_int32 zoomLevel, const ossim_float64 &totalTiles, ossim_float64 &tilesWritten)
ossimDrect clipToRect(const ossimDrect &rect) const
Definition: ossimDrect.cpp:769
virtual ossimGpt lineSampleToWorld(const ossimDpt &projectedPoint) const
virtual void setAreaOfInterest(const ossimIrect &areaOfInterest)
ossimString replaceAllThatMatch(const char *regularExpressionPattern, const char *value="") const
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 ossimScalarType getOutputScalarType() const
This will be used to query the output pixel type of the tile source.
ossim_uint64 m_batchSize
Number of transactions batched before being executed.
yy_size_t size
bool exists() const
virtual void setProperty(ossimRefPtr< ossimProperty > property)
Will set the property whose name matches the argument "property->getName()".
ossim_float64 lon
Definition: ossimGpt.h:266
virtual const char * what() const
Returns the error message.
virtual void setPcsCode(ossim_uint32 pcsCode)
virtual void lineSampleToEastingNorthing(const ossimDpt &liineSample, ossimDpt &eastingNorthing) const
ossimRefPtr< ossimMapProjection > getNewGeographicProjection() const
std::string::size_type size() const
Definition: ossimString.h:405
ossimRefPtr< ossimImageSourceSequencer > theInputConnection
std::vector< ossimIpt > m_zoomLevelMatrixSizes
Hold zoom level matrix sizes for connectionless write tile.
void setView(ossimMapProjection *proj)
bool toBool() const
String to numeric methods.
void setCompressionQuality(const std::string &quality)
virtual bool openFile(const ossimKeywordlist &options)
Opens file for writing, appending, merging without an input connection.
bool getRect(const std::string &key, ossimDrect &rect) const
Gets rectangle.
bool m_writeBlanks
Controlled by option key: "include_blank_tiles".
bool hasImageType(const ossimString &imageType) const
bool hasImageType(const ossimString& imageType) const
unsigned long long ossim_uint64
unsigned int ossim_uint32
sqlite3_stmt * m_pStmt
Holds Statement handle from sqlite3_prepare_v2(...) for connectionless write tile.
ossimDpt getMetersPerPixel() const
Returns the GSD associated with this image in the active projection.
virtual bool init(sqlite3_stmt *pStmt)
Initialize from database.
static ossimDatumFactory * instance()
void extractKeysThatMatch(ossimKeywordlist &kwl, const ossimString &regularExpression) const
std::string m_tileTableName
bool createTables(sqlite3 *db)
const ossimIpt & lr() const
Definition: ossimIrect.h:276
static ossimString downcase(const ossimString &aString)
Definition: ossimString.cpp:48
void initializeRect(const ossimMapProjection *proj, const ossimIrect &aoi, ossimDrect &rect)
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
const ossimGpkgSpatialRefSysRecord & getSrs() const
Spatial ref sys.
ossimRefPtr< ossimCodecBase > m_fullTileCodec
Will cache and hold the allocated codecs to use for the encoding.
virtual ossimRefPtr< ossimImageGeometry > getImageGeometry()
Returns the image geometry object associated with this tile source or NULL if not defined...
void applyScaleToProjection(ossimMapProjection *proj, const ossimDpt &desiredGsd) const
Get the current gsd from projection.
virtual void setEnableFlag(bool flag)
Definition: ossimSource.cpp:99
void toPoint(const std::string &s)
Initializes this point from string.
Definition: ossimIpt.cpp:170
ossim_uint32 getCompressionQuality() const
Gets the compression quality.
Container class that holds both 2D transform and 3D projection information for an image Only one inst...
ossim_uint32 getEpsgCode() const
const ossimGpt & getOrigin() const
virtual ossimString getLongName() const
#define MIN_LAT
void getTileTableName(std::string &tileTableName) const
Gets the tile table name.
return status
bool alignToGrid() const
virtual ossimCodecBase * createCodec(const ossimString &type) const
Will loop through all registered factories trying to allocate a codec for the passed in type...
virtual ossimString getShortName() const
bool writeGpkgTileMatrixTable(sqlite3 *db, ossim_int32 zoom_level, const ossimIpt &matrixSize, const ossimDpt &gsd)
Initialize method.
virtual const ossimFilename & getFilename() const
ossim_int64 getNumberOfTilesHorizontal() const
virtual ossimRefPtr< ossimProperty > getProperty(const ossimString &name) const
T * getObjectAs(ossim_uint32 idx=0)
Definition: ossimVisitor.h:64
ossim_uint64 getBatchSize() const
This is the number of transactions batched before being executed.
void getZoomLevels(std::vector< ossim_int32 > &zoomLevels) const
Gets zoom levels from options keyword list if set.
bool writeGpkgContentsTable(sqlite3 *db, const ossimDrect &boundingRect)
void reInitializeCutters(const ossimMapProjection *proj)
Finds all ossimRectangleCutter and calls setRectangle with a nan rect to reset the bounding box after...
virtual void setProperty(ossimRefPtr< ossimProperty > property)
virtual ossimErrorCode getErrorStatus() const
bool writeEntry()
Writes an entry to gpkg.
ossim_int32 y
Definition: ossimIpt.h:142
ossimDrect m_sceneBoundingRect
Holds the bounding rect of the scene edges either in decimal degrees for geographic projection or Eas...
ossimDrect m_outputRect
Expanded(final) AOI clipped to projection rect.
virtual void setProperty(const ossimString &name, const ossimString &value)
void initializeProjectionRect(const ossimMapProjection *productProj)
virtual bool setView(ossimObject *baseObject)=0
void getRect(ossimDrect &rect) const
Gets the rectangle from bounds.
static const char * COMPRESSION_QUALITY_KW
ossimRefPtr< ossimMapProjection > getNewOutputProjection() const
Gets projection from "epsg" code if in options list.
ossim_uint64 toUInt64() const
void reInitializeCombiners()
Finds all combiners and calls initialize to reset the bounding box after a view change.
double x
Definition: ossimDpt.h:164
ossimString getCompressionLevel() const
Get the gpkg compression level as a string.
virtual bool writeCodecTile(ossim_uint8 *codecTile, ossim_int32 codecTileSize, ossim_int32 zoomLevel, ossim_int64 row, ossim_int64 col)
Direct interface to writing a Codec tile to database.
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
bool empty() const
Definition: ossimString.h:411
virtual void eastingNorthingToLineSample(const ossimDpt &eastingNorthing, ossimDpt &lineSample) const
virtual ossimProjection * createProjection(const ossimFilename &filename, ossim_uint32 entryIdx) const
STUB. Not implemented.
void writeZoomLevels(sqlite3 *db, ossimMapProjection *proj, const std::vector< ossim_int32 > &zoomLevels)
void stretchToTileBoundary(const ossimIpt &tileWidthHeight)
Definition: ossimIrect.cpp:212
bool writeGpkgNsgTileMatrixExtentTable(sqlite3 *db, ossim_int32 zoom_level, const ossimIrect &expandedAoi, const ossimIrect &clippedAoi)
sqlite3 * m_db
database connection
bool hasNans() const
Definition: ossimIrect.h:337
virtual void setUlTiePoints(const ossimGpt &gpt)
virtual void accept(ossimVisitor &visitor)
We will add a visitor interface for all connectable objects.
ossim_int32 x
Definition: ossimIpt.h:141
ossim_float64 lat
Definition: ossimGpt.h:265
virtual void close()
8 bit unsigned integer
#define RTTI_DEF1(cls, name, b1)
Definition: ossimRtti.h:485
bool insert(sqlite3 *db)
Inserst this record into gpkg_spatial_ref_sys table.
virtual bool init(sqlite3_stmt *pStmt)
Initialize from database.
bool getWmsCutBox(ossimDrect &rect) const
Get rectangle in projected space from key: cut_wms_bbox key:value form: cut_wms_bbox: <minx>...
void getZoomLevels(std::vector< ossim_int32 > &zoomLevels) const
Gets zoom levels of all tile matrixes.
virtual void setPercentComplete(double percentComplete)
bool getClipExtents(ossimDrect &rect, bool &alignToGridFlag) const
Get clip rectangle in projected space from key: clip_extents key:value form: clip_extents: <minx>...
virtual bool init(sqlite3_stmt *pStmt)
Initialize from database.
virtual ossimIrect getAreaOfInterest() const
bool keyIsTrue(const std::string &key) const
virtual ossimDpt getMetersPerPixel() const
virtual bool writeFile()
Writes the file to disk or a stream.
virtual ossim_int32 beginTileProcessing()
Calls initial sqlite3_prepare_v2 statement.
virtual void setTileSize(const ossimIpt &tileSize)
const ossimDpt & lr() const
Definition: ossimDrect.h:341
ossimDrect m_projectionBoundingRect
Holds the bounding rect of the output projection edges either in decimal degrees for geographic proje...
bool addLevels()
Adds levels to an existing an gpkg.
static const char * FILENAME_KW
static bool createTable(sqlite3 *db)
Creates table in database.
bool setCompressionLevel(const ossimString &level)
Set the gpkg compression level from a string.
unsigned char ossim_uint8
static ossimEpsgProjectionFactory * instance()
Implements singleton pattern.
OSSIMDLLEXPORT std::ostream & ossimNotify(ossimNotifyLevel level=ossimNotifyLevel_WARN)
ossim_int64 getNumberOfTilesVertical() const
void makeNan()
Definition: ossimDpt.h:65
void getExpandedAoi(const ossimIrect &aoi, ossimIrect &expandedAoi) const
Gets aoi expanded to tile boundaries.
virtual bool open()
virtual bool saveState(ossimKeywordlist &kwl, const char *prefix=0) const
saves the state of the object.
int ossim_int32
const std::string & string() const
Definition: ossimString.h:414
void getProjectionDimensionsInMeters(const ossimMapProjection *proj, ossimDpt &dims) const
Gets the projection dimensions in meters.
ossim_uint64 m_batchCount
Working variable for holding the current batch count.
bool m_fullTileCodecAlpha
true if codec requires alpha channel.
ossim_float64 min< ossim_float64 >(ossim_float64 a, ossim_float64 b)
Definition: ossimCommon.h:223