[ossim-plugins] 01/02: Imported Upstream version 1.8.20.3+ds

Sebastiaan Couwenberg sebastic at moszumanska.debian.org
Sat May 28 01:58:07 UTC 2016


This is an automated email from the git hooks/post-receive script.

sebastic pushed a commit to branch master
in repository ossim-plugins.

commit 92103167dca5e13d1884a87fbd322ad561100576
Author: Bas Couwenberg <sebastic at xs4all.nl>
Date:   Sat May 28 02:15:00 2016 +0200

    Imported Upstream version 1.8.20.3+ds
---
 ossim_plugins/CMakeLists.txt                       |  185 +
 ossim_plugins/LICENSE.txt                          |  141 +
 ossim_plugins/README.txt                           |   94 +
 ossim_plugins/contrib/CMakeLists.txt               |   35 +
 ossim_plugins/contrib/makefile.vc                  |   58 +
 ossim_plugins/contrib/ossimCFARFilter.cpp          |  933 +++
 ossim_plugins/contrib/ossimCFARFilter.h            |   95 +
 ossim_plugins/contrib/ossimComplexAbs.cpp          |  283 +
 ossim_plugins/contrib/ossimComplexAbs.h            |   59 +
 ossim_plugins/contrib/ossimContribExports.h        |   31 +
 .../contrib/ossimContribImageSourceFactory.cpp     |   68 +
 .../contrib/ossimContribImageSourceFactory.h       |   26 +
 ossim_plugins/contrib/ossimContribPluginInit.cpp   |   69 +
 ossim_plugins/contrib/ossimSPOTNatural.cpp         |  305 +
 ossim_plugins/contrib/ossimSPOTNatural.h           |   65 +
 ossim_plugins/csm/CMakeLists.txt                   |   61 +
 ossim_plugins/csm/ossimCsmPluginInit.cpp           |  116 +
 ossim_plugins/csm/ossimCsmProjectionFactory.cpp    |   91 +
 ossim_plugins/csm/ossimCsmProjectionFactory.h      |   64 +
 ossim_plugins/csm/ossimCsmSensorModel.cpp          |  249 +
 ossim_plugins/csm/ossimCsmSensorModel.h            |   58 +
 ossim_plugins/csm/ossimCsmSupport.cpp              |   45 +
 ossim_plugins/csm/ossimCsmSupport.h                |   24 +
 ossim_plugins/gdal/CMakeLists.txt                  |   72 +
 ossim_plugins/gdal/gdal.vcproj                     |  359 +
 .../libgdalplugin.xcodeproj/project.pbxproj        |  327 +
 ossim_plugins/gdal/makefile.vc                     |   75 +
 ossim_plugins/gdal/ossimEsriShapeFileFilter.cpp    |  769 ++
 ossim_plugins/gdal/ossimEsriShapeFileFilter.h      |  272 +
 ossim_plugins/gdal/ossimGdalDataset.cpp            |  306 +
 ossim_plugins/gdal/ossimGdalDataset.h              |  141 +
 ossim_plugins/gdal/ossimGdalFactory.cpp            |  357 +
 ossim_plugins/gdal/ossimGdalFactory.h              |   84 +
 ossim_plugins/gdal/ossimGdalImageWriterFactory.cpp |  201 +
 ossim_plugins/gdal/ossimGdalImageWriterFactory.h   |   70 +
 ossim_plugins/gdal/ossimGdalInfoFactory.cpp        |   63 +
 ossim_plugins/gdal/ossimGdalInfoFactory.h          |   58 +
 ossim_plugins/gdal/ossimGdalObjectFactory.cpp      |   96 +
 ossim_plugins/gdal/ossimGdalObjectFactory.h        |   61 +
 .../gdal/ossimGdalOgrVectorAnnotation.cpp          | 2544 ++++++
 ossim_plugins/gdal/ossimGdalOgrVectorAnnotation.h  |  184 +
 ossim_plugins/gdal/ossimGdalOverviewBuilder.cpp    |  505 ++
 ossim_plugins/gdal/ossimGdalOverviewBuilder.h      |  182 +
 .../gdal/ossimGdalOverviewBuilderFactory.cpp       |   68 +
 .../gdal/ossimGdalOverviewBuilderFactory.h         |   68 +
 ossim_plugins/gdal/ossimGdalPluginInit.cpp         |  128 +
 ossim_plugins/gdal/ossimGdalProjectionFactory.cpp  |  438 +
 ossim_plugins/gdal/ossimGdalProjectionFactory.h    |   68 +
 ossim_plugins/gdal/ossimGdalTileSource.cpp         | 2492 ++++++
 ossim_plugins/gdal/ossimGdalTileSource.h           |  347 +
 ossim_plugins/gdal/ossimGdalTiledDataset.cpp       |  556 ++
 ossim_plugins/gdal/ossimGdalTiledDataset.h         |  123 +
 ossim_plugins/gdal/ossimGdalType.cpp               |   94 +
 ossim_plugins/gdal/ossimGdalType.h                 |   20 +
 ossim_plugins/gdal/ossimGdalWriter.cpp             | 1872 +++++
 ossim_plugins/gdal/ossimGdalWriter.h               |  146 +
 ossim_plugins/gdal/ossimHdfInfo.cpp                |  203 +
 ossim_plugins/gdal/ossimHdfInfo.h                  |   64 +
 ossim_plugins/gdal/ossimHdfReader.cpp              |  442 +
 ossim_plugins/gdal/ossimHdfReader.h                |  203 +
 ossim_plugins/gdal/ossimOgcWktTranslator.cpp       | 1083 +++
 ossim_plugins/gdal/ossimOgcWktTranslator.h         |   65 +
 ossim_plugins/gdal/ossimOgrGdalTileSource.cpp      |  269 +
 ossim_plugins/gdal/ossimOgrGdalTileSource.h        |  207 +
 ossim_plugins/gdal/ossimOgrInfo.cpp                |  664 ++
 ossim_plugins/gdal/ossimOgrInfo.h                  |   86 +
 ossim_plugins/gdal/ossimOgrVectorTileSource.cpp    |  513 ++
 ossim_plugins/gdal/ossimOgrVectorTileSource.h      |  196 +
 ossim_plugins/gdal/ossimShapeDatabase.cpp          |  358 +
 ossim_plugins/gdal/ossimShapeDatabase.h            |   87 +
 ossim_plugins/gdal/ossimShapeFile.cpp              |  483 ++
 ossim_plugins/gdal/ossimShapeFile.h                |  124 +
 ossim_plugins/gdal/shapefil.h                      |  558 ++
 ossim_plugins/geopdf/CMakeLists.txt                |   54 +
 ossim_plugins/geopdf/ossimGeoPdfInfo.cpp           |  202 +
 ossim_plugins/geopdf/ossimGeoPdfInfo.h             |   70 +
 ossim_plugins/geopdf/ossimGeoPdfInfoFactory.cpp    |   55 +
 ossim_plugins/geopdf/ossimGeoPdfInfoFactory.h      |   57 +
 ossim_plugins/geopdf/ossimGeoPdfPluginInit.cpp     |   83 +
 ossim_plugins/geopdf/ossimGeoPdfReader.cpp         | 2163 +++++
 ossim_plugins/geopdf/ossimGeoPdfReader.h           |  329 +
 ossim_plugins/geopdf/ossimGeoPdfReaderFactory.cpp  |  172 +
 ossim_plugins/geopdf/ossimGeoPdfReaderFactory.h    |  116 +
 ossim_plugins/hdf/CMakeLists.txt                   |   53 +
 ossim_plugins/hdf/ossimH5ImageDataset.cpp          |  348 +
 ossim_plugins/hdf/ossimH5ImageDataset.h            |  126 +
 ossim_plugins/hdf/ossimH5Info.cpp                  |  141 +
 ossim_plugins/hdf/ossimH5Info.h                    |   63 +
 ossim_plugins/hdf/ossimH5Reader.cpp                | 1173 +++
 ossim_plugins/hdf/ossimH5Reader.h                  |  313 +
 ossim_plugins/hdf/ossimH5Util.cpp                  | 1107 +++
 ossim_plugins/hdf/ossimH5Util.h                    |  181 +
 ossim_plugins/hdf/ossimHdf4Reader.cpp              | 1490 ++++
 ossim_plugins/hdf/ossimHdf4Reader.h                |  305 +
 ossim_plugins/hdf/ossimHdf4SubDataset.cpp          |  390 +
 ossim_plugins/hdf/ossimHdf4SubDataset.h            |  185 +
 ossim_plugins/hdf/ossimHdf5Reader.cpp              |  998 +++
 ossim_plugins/hdf/ossimHdf5Reader.h                |  268 +
 ossim_plugins/hdf/ossimHdf5SubDataset.cpp          |  474 ++
 ossim_plugins/hdf/ossimHdf5SubDataset.h            |  135 +
 ossim_plugins/hdf/ossimHdfGridModel.cpp            |  942 +++
 ossim_plugins/hdf/ossimHdfGridModel.h              |  132 +
 ossim_plugins/hdf/ossimHdfInfo.cpp                 |  171 +
 ossim_plugins/hdf/ossimHdfInfo.h                   |   68 +
 ossim_plugins/hdf/ossimHdfInfoFactory.cpp          |   68 +
 ossim_plugins/hdf/ossimHdfInfoFactory.h            |   58 +
 ossim_plugins/hdf/ossimHdfPluginInit.cpp           |   92 +
 ossim_plugins/hdf/ossimHdfProjectionFactory.cpp    |  160 +
 ossim_plugins/hdf/ossimHdfProjectionFactory.h      |   54 +
 ossim_plugins/hdf/ossimHdfReaderFactory.cpp        |  248 +
 ossim_plugins/hdf/ossimHdfReaderFactory.h          |  110 +
 ossim_plugins/hdf4/CMakeLists.txt                  |   44 +
 ossim_plugins/hdf4/ossimHdf4Reader.cpp             | 1494 ++++
 ossim_plugins/hdf4/ossimHdf4Reader.h               |  305 +
 ossim_plugins/hdf4/ossimHdf4SubDataset.cpp         |  390 +
 ossim_plugins/hdf4/ossimHdf4SubDataset.h           |  185 +
 ossim_plugins/hdf4/ossimHdfGridModel.cpp           |  348 +
 ossim_plugins/hdf4/ossimHdfGridModel.h             |   80 +
 ossim_plugins/hdf4/ossimHdfInfo.cpp                |  144 +
 ossim_plugins/hdf4/ossimHdfInfo.h                  |   66 +
 ossim_plugins/hdf4/ossimHdfInfoFactory.cpp         |   54 +
 ossim_plugins/hdf4/ossimHdfInfoFactory.h           |   58 +
 ossim_plugins/hdf4/ossimHdfPluginInit.cpp          |   92 +
 ossim_plugins/hdf4/ossimHdfProjectionFactory.cpp   |  160 +
 ossim_plugins/hdf4/ossimHdfProjectionFactory.h     |   54 +
 ossim_plugins/hdf4/ossimHdfReaderFactory.cpp       |  187 +
 ossim_plugins/hdf4/ossimHdfReaderFactory.h         |  110 +
 ossim_plugins/hdf5/CMakeLists.txt                  |   52 +
 ossim_plugins/hdf5/ossimH5GridModel.cpp            | 1036 +++
 ossim_plugins/hdf5/ossimH5GridModel.h              |  128 +
 ossim_plugins/hdf5/ossimH5ImageDataset.cpp         |  369 +
 ossim_plugins/hdf5/ossimH5ImageDataset.h           |  143 +
 ossim_plugins/hdf5/ossimH5Info.cpp                 |  141 +
 ossim_plugins/hdf5/ossimH5Info.h                   |   63 +
 ossim_plugins/hdf5/ossimH5InfoFactory.cpp          |   59 +
 ossim_plugins/hdf5/ossimH5InfoFactory.h            |   59 +
 ossim_plugins/hdf5/ossimH5PluginInit.cpp           |   94 +
 ossim_plugins/hdf5/ossimH5ProjectionFactory.cpp    |  163 +
 ossim_plugins/hdf5/ossimH5ProjectionFactory.h      |   54 +
 ossim_plugins/hdf5/ossimH5Reader.cpp               |  989 +++
 ossim_plugins/hdf5/ossimH5Reader.h                 |  300 +
 ossim_plugins/hdf5/ossimH5ReaderFactory.cpp        |  160 +
 ossim_plugins/hdf5/ossimH5ReaderFactory.h          |  112 +
 ossim_plugins/hdf5/ossimH5Util.cpp                 | 1507 ++++
 ossim_plugins/hdf5/ossimH5Util.h                   |  209 +
 ossim_plugins/kakadu/CMakeLists.txt                |  108 +
 ossim_plugins/kakadu/LICENSE.txt                   |   45 +
 ossim_plugins/kakadu/makefile.vc                   |   64 +
 .../kakadu/ossimJpipProjectionFactory.cpp          |   87 +
 ossim_plugins/kakadu/ossimJpipProjectionFactory.h  |   45 +
 ossim_plugins/kakadu/ossimKakaduCommon.cpp         |  889 ++
 ossim_plugins/kakadu/ossimKakaduCommon.h           |  168 +
 .../kakadu/ossimKakaduCompressedTarget.cpp         |   99 +
 ossim_plugins/kakadu/ossimKakaduCompressedTarget.h |   68 +
 ossim_plugins/kakadu/ossimKakaduCompressor.cpp     | 1771 ++++
 ossim_plugins/kakadu/ossimKakaduCompressor.h       |  357 +
 ossim_plugins/kakadu/ossimKakaduJ2kReader.cpp      |  777 ++
 ossim_plugins/kakadu/ossimKakaduJ2kReader.h        |  354 +
 ossim_plugins/kakadu/ossimKakaduJp2Reader.cpp      | 1201 +++
 ossim_plugins/kakadu/ossimKakaduJp2Reader.h        |  311 +
 ossim_plugins/kakadu/ossimKakaduJp2Writer.cpp      |  448 +
 ossim_plugins/kakadu/ossimKakaduJp2Writer.h        |  148 +
 ossim_plugins/kakadu/ossimKakaduJpipHandler.cpp    | 1219 +++
 ossim_plugins/kakadu/ossimKakaduJpipHandler.h      |  116 +
 .../kakadu/ossimKakaduJpipHandlerFactory.cpp       |  225 +
 .../kakadu/ossimKakaduJpipHandlerFactory.h         |  120 +
 .../kakadu/ossimKakaduJpipImageGeometryFactory.cpp |  114 +
 .../kakadu/ossimKakaduJpipImageGeometryFactory.h   |   43 +
 ossim_plugins/kakadu/ossimKakaduJpipInfo.cpp       |  160 +
 ossim_plugins/kakadu/ossimKakaduJpipInfo.h         |   66 +
 .../kakadu/ossimKakaduJpipInfoFactory.cpp          |   43 +
 ossim_plugins/kakadu/ossimKakaduJpipInfoFactory.h  |   37 +
 ossim_plugins/kakadu/ossimKakaduKeywords.h         |   22 +
 ossim_plugins/kakadu/ossimKakaduMessaging.h        |   69 +
 .../kakadu/ossimKakaduNitfOverviewBuilder.cpp      |  798 ++
 .../kakadu/ossimKakaduNitfOverviewBuilder.h        |  157 +
 ossim_plugins/kakadu/ossimKakaduNitfReader.cpp     | 1124 +++
 ossim_plugins/kakadu/ossimKakaduNitfReader.h       |  405 +
 ossim_plugins/kakadu/ossimKakaduNitfWriter.cpp     |  554 ++
 ossim_plugins/kakadu/ossimKakaduNitfWriter.h       |  146 +
 .../kakadu/ossimKakaduOverviewBuilderFactory.cpp   |   58 +
 .../kakadu/ossimKakaduOverviewBuilderFactory.h     |   70 +
 ossim_plugins/kakadu/ossimKakaduPluginInit.cpp     |  167 +
 ossim_plugins/kakadu/ossimKakaduReaderFactory.cpp  |  267 +
 ossim_plugins/kakadu/ossimKakaduReaderFactory.h    |  131 +
 ossim_plugins/kakadu/ossimKakaduWriterFactory.cpp  |  173 +
 ossim_plugins/kakadu/ossimKakaduWriterFactory.h    |  113 +
 ossim_plugins/kmlsuperoverlay/CMakeLists.txt       |   42 +
 .../ossimKmlSuperOverlayPluginInit.cpp             |   83 +
 .../kmlsuperoverlay/ossimKmlSuperOverlayReader.cpp |  438 +
 .../kmlsuperoverlay/ossimKmlSuperOverlayReader.h   |  154 +
 .../ossimKmlSuperOverlayReaderFactory.cpp          |  152 +
 .../ossimKmlSuperOverlayReaderFactory.h            |  106 +
 .../kmlsuperoverlay/ossimKmlSuperOverlayWriter.cpp |  938 +++
 .../kmlsuperoverlay/ossimKmlSuperOverlayWriter.h   |  175 +
 .../ossimKmlSuperOverlayWriterFactory.cpp          |  132 +
 .../ossimKmlSuperOverlayWriterFactory.h            |  115 +
 ossim_plugins/las/CMakeLists.txt                   |   32 +
 ossim_plugins/las/ossimLasPluginInit.cpp           |   72 +
 ossim_plugins/las/ossimLasPointRecord1.cpp         |  193 +
 ossim_plugins/las/ossimLasPointRecord1.h           |   91 +
 ossim_plugins/las/ossimLasPointRecord2.cpp         |  204 +
 ossim_plugins/las/ossimLasPointRecord2.h           |  108 +
 ossim_plugins/las/ossimLasPointRecord3.cpp         |  209 +
 ossim_plugins/las/ossimLasPointRecord3.h           |  109 +
 ossim_plugins/las/ossimLasPointRecord4.cpp         |  228 +
 ossim_plugins/las/ossimLasPointRecord4.h           |  113 +
 ossim_plugins/las/ossimLasPointRecordInterface.h   |   42 +
 ossim_plugins/las/ossimLasReader.cpp               | 1141 +++
 ossim_plugins/las/ossimLasReader.h                 |  314 +
 ossim_plugins/las/ossimLasReaderFactory.cpp        |  133 +
 ossim_plugins/las/ossimLasReaderFactory.h          |  100 +
 ossim_plugins/libraw/CMakeLists.txt                |   37 +
 ossim_plugins/libraw/LibRaw-0.9.0/dcraw/.gdbinit   |    2 +
 ossim_plugins/libraw/LibRaw-0.9.0/dcraw/dcraw.c    | 8784 ++++++++++++++++++++
 .../libraw/LibRaw-0.9.0/internal/dcraw_common.cpp  | 8737 +++++++++++++++++++
 .../libraw/LibRaw-0.9.0/internal/dcraw_fileio.cpp  |  215 +
 .../libraw/LibRaw-0.9.0/internal/defines.h         |  133 +
 .../LibRaw-0.9.0/internal/libraw_internal_funcs.h  |  183 +
 .../libraw/LibRaw-0.9.0/internal/var_defines.h     |  185 +
 ossim_plugins/libraw/LibRaw-0.9.0/libraw/libraw.h  |  234 +
 .../libraw/LibRaw-0.9.0/libraw/libraw_alloc.h      |   92 +
 .../libraw/LibRaw-0.9.0/libraw/libraw_const.h      |  157 +
 .../libraw/LibRaw-0.9.0/libraw/libraw_datastream.h |  316 +
 .../libraw/LibRaw-0.9.0/libraw/libraw_internal.h   |  224 +
 .../libraw/LibRaw-0.9.0/libraw/libraw_types.h      |  295 +
 .../libraw/LibRaw-0.9.0/libraw/libraw_version.h    |   46 +
 .../libraw/LibRaw-0.9.0/src/libraw_c_api.cpp       |  170 +
 .../libraw/LibRaw-0.9.0/src/libraw_cxx.cpp         | 1956 +++++
 ossim_plugins/libraw/ossimLibRawPluginInit.cpp     |   89 +
 ossim_plugins/libraw/ossimLibRawReader.cpp         |  350 +
 ossim_plugins/libraw/ossimLibRawReader.h           |  151 +
 ossim_plugins/libraw/ossimLibRawReaderFactory.cpp  |  129 +
 ossim_plugins/libraw/ossimLibRawReaderFactory.h    |   99 +
 ossim_plugins/make.opt.in                          |  100 +
 ossim_plugins/make_platform.opt.in                 |   21 +
 ossim_plugins/makefile.inc                         |   71 +
 ossim_plugins/makefile.targ.inc                    |   27 +
 ossim_plugins/makefile.vc                          |  133 +
 ossim_plugins/mrsid/CMakeLists.txt                 |   63 +
 ossim_plugins/mrsid/ossimMG4LidarReader.cpp        |  602 ++
 ossim_plugins/mrsid/ossimMG4LidarReader.h          |  210 +
 ossim_plugins/mrsid/ossimMrSidPluginInit.cpp       |   90 +
 ossim_plugins/mrsid/ossimMrSidReader.cpp           | 1002 +++
 ossim_plugins/mrsid/ossimMrSidReader.h             |  236 +
 ossim_plugins/mrsid/ossimMrSidReaderFactory.cpp    |  187 +
 ossim_plugins/mrsid/ossimMrSidReaderFactory.h      |  116 +
 ossim_plugins/mrsid/ossimMrSidWriter.cpp           |  594 ++
 ossim_plugins/mrsid/ossimMrSidWriter.h             |  164 +
 ossim_plugins/mrsid/ossimMrSidWriterFactory.cpp    |  144 +
 ossim_plugins/mrsid/ossimMrSidWriterFactory.h      |  124 +
 ossim_plugins/ndf/CMakeLists.txt                   |   38 +
 ossim_plugins/ndf/makefile.vc                      |   47 +
 ossim_plugins/ndf/ndf_test.cpp                     |   24 +
 ossim_plugins/ndf/ossimNdfHeader.cpp               |  591 ++
 ossim_plugins/ndf/ossimNdfHeader.h                 |   79 +
 ossim_plugins/ndf/ossimNdfPluginInit.cpp           |   63 +
 ossim_plugins/ndf/ossimNdfReaderFactory.cpp        |  124 +
 ossim_plugins/ndf/ossimNdfReaderFactory.h          |   49 +
 ossim_plugins/ndf/ossimNdfTileSource.cpp           |  304 +
 ossim_plugins/ndf/ossimNdfTileSource.h             |   76 +
 ossim_plugins/nitro/ossimNitroHandler.cpp          | 1525 ++++
 ossim_plugins/nitro/ossimNitroHandler.h            |  224 +
 .../nitro/ossimNitroImageHandlerFactory.cpp        |  158 +
 .../nitro/ossimNitroImageHandlerFactory.h          |   63 +
 ossim_plugins/nitro/ossimNitroPluginInit.cpp       |  102 +
 ossim_plugins/nmake.opt                            |   89 +
 ossim_plugins/nui/ossimNuiExports.h                |   31 +
 ossim_plugins/nui/ossimNuiFactory.cpp              |  147 +
 ossim_plugins/nui/ossimNuiFactory.h                |   63 +
 ossim_plugins/nui/ossimNuiHandler.cpp              |  716 ++
 ossim_plugins/nui/ossimNuiHandler.h                |  103 +
 ossim_plugins/nui/ossimNuiPluginInit.cpp           |   57 +
 ossim_plugins/nui/ossimnui_plugin.vcproj           |  207 +
 ossim_plugins/opencv/CMakeLists.txt                |   46 +
 ossim_plugins/opencv/ossimIvtGeomXform.cpp         |   60 +
 ossim_plugins/opencv/ossimIvtGeomXform.h           |   36 +
 ossim_plugins/opencv/ossimIvtGeomXformVisitor.cpp  |   40 +
 ossim_plugins/opencv/ossimIvtGeomXformVisitor.h    |   25 +
 ossim_plugins/opencv/ossimOpenCvObjectFactory.cpp  |   90 +
 ossim_plugins/opencv/ossimOpenCvObjectFactory.h    |   71 +
 ossim_plugins/opencv/ossimOpenCvPluginInit.cpp     |   72 +
 .../opencv/ossimTieMeasurementGenerator.cpp        |  728 ++
 .../opencv/ossimTieMeasurementGenerator.h          |  149 +
 ossim_plugins/openjpeg/CMakeLists.txt              |   70 +
 ossim_plugins/openjpeg/ossimOpjColor.cpp           |  544 ++
 ossim_plugins/openjpeg/ossimOpjColor.h             |   53 +
 ossim_plugins/openjpeg/ossimOpjCommon.cpp          |  925 +++
 ossim_plugins/openjpeg/ossimOpjCommon.h            |  101 +
 ossim_plugins/openjpeg/ossimOpjCompressor.cpp      | 1257 +++
 ossim_plugins/openjpeg/ossimOpjCompressor.h        |  330 +
 ossim_plugins/openjpeg/ossimOpjJp2Reader.cpp       | 1012 +++
 ossim_plugins/openjpeg/ossimOpjJp2Reader.h         |  232 +
 ossim_plugins/openjpeg/ossimOpjJp2Writer.cpp       |  581 ++
 ossim_plugins/openjpeg/ossimOpjJp2Writer.h         |  176 +
 ossim_plugins/openjpeg/ossimOpjKeywords.h          |   24 +
 ossim_plugins/openjpeg/ossimOpjNitfReader.cpp      |  283 +
 ossim_plugins/openjpeg/ossimOpjNitfReader.h        |   69 +
 ossim_plugins/openjpeg/ossimOpjPluginInit.cpp      |   81 +
 ossim_plugins/openjpeg/ossimOpjReaderFactory.cpp   |  244 +
 ossim_plugins/openjpeg/ossimOpjReaderFactory.h     |  134 +
 ossim_plugins/openjpeg/ossimOpjWriterFactory.cpp   |  151 +
 ossim_plugins/openjpeg/ossimOpjWriterFactory.h     |  120 +
 ossim_plugins/ossim/AlosPalsar/AlosPalsarData.cpp  |  187 +
 ossim_plugins/ossim/AlosPalsar/AlosPalsarData.h    |   96 +
 .../AlosPalsar/AlosPalsarDataFileDescriptor.cpp    |   81 +
 .../AlosPalsar/AlosPalsarDataFileDescriptor.h      |  119 +
 .../ossim/AlosPalsar/AlosPalsarDataSetSummary.cpp  |  763 ++
 .../ossim/AlosPalsar/AlosPalsarDataSetSummary.h    | 1025 +++
 .../ossim/AlosPalsar/AlosPalsarFacilityData.cpp    | 1168 +++
 .../ossim/AlosPalsar/AlosPalsarFacilityData.h      | 1809 ++++
 .../ossim/AlosPalsar/AlosPalsarFileDescriptor.cpp  |  445 +
 .../ossim/AlosPalsar/AlosPalsarFileDescriptor.h    |  879 ++
 .../ossim/AlosPalsar/AlosPalsarLeader.cpp          |  327 +
 ossim_plugins/ossim/AlosPalsar/AlosPalsarLeader.h  |  112 +
 .../ossim/AlosPalsar/AlosPalsarLeaderFactory.cpp   |   40 +
 .../ossim/AlosPalsar/AlosPalsarLeaderFactory.h     |   47 +
 .../AlosPalsar/AlosPalsarMapProjectionData.cpp     |  211 +
 .../ossim/AlosPalsar/AlosPalsarMapProjectionData.h |  322 +
 .../AlosPalsar/AlosPalsarPlatformPositionData.cpp  |  256 +
 .../AlosPalsar/AlosPalsarPlatformPositionData.h    |  299 +
 .../AlosPalsar/AlosPalsarPositionVectorRecord.cpp  |   88 +
 .../AlosPalsar/AlosPalsarPositionVectorRecord.h    |   90 +
 .../ossim/AlosPalsar/AlosPalsarRadiometricData.cpp |   64 +
 .../ossim/AlosPalsar/AlosPalsarRadiometricData.h   |  111 +
 .../ossim/AlosPalsar/AlosPalsarRecord.cpp          |   34 +
 ossim_plugins/ossim/AlosPalsar/AlosPalsarRecord.h  |   78 +
 .../ossim/AlosPalsar/AlosPalsarRecordFactory.cpp   |   53 +
 .../ossim/AlosPalsar/AlosPalsarRecordFactory.h     |   63 +
 .../ossim/AlosPalsar/AlosPalsarRecordHeader.cpp    |   84 +
 .../ossim/AlosPalsar/AlosPalsarRecordHeader.h      |  142 +
 .../ossim/AlosPalsar/AlosPalsarSignalData.cpp      |  195 +
 .../ossim/AlosPalsar/AlosPalsarSignalData.h        |  122 +
 ossim_plugins/ossim/CMakeLists.txt                 |   38 +
 .../ossim/EnvisatAsar/AntennaElevationPatterns.cpp |   97 +
 .../ossim/EnvisatAsar/AntennaElevationPatterns.h   |  146 +
 .../ossim/EnvisatAsar/ChirpParameters.cpp          |  200 +
 ossim_plugins/ossim/EnvisatAsar/ChirpParameters.h  |  254 +
 .../EnvisatAsar/DopplerCentroidParameters.cpp      |  159 +
 .../ossim/EnvisatAsar/DopplerCentroidParameters.h  |  176 +
 .../ossim/EnvisatAsar/EnvisatAsarData.cpp          |  284 +
 ossim_plugins/ossim/EnvisatAsar/EnvisatAsarData.h  |   93 +
 .../ossim/EnvisatAsar/EnvisatAsarDataFactory.cpp   |   50 +
 .../ossim/EnvisatAsar/EnvisatAsarDataFactory.h     |   45 +
 .../ossim/EnvisatAsar/EnvisatAsarRecord.cpp        |   31 +
 .../ossim/EnvisatAsar/EnvisatAsarRecord.h          |  113 +
 .../ossim/EnvisatAsar/EnvisatAsarRecordFactory.cpp |   42 +
 .../ossim/EnvisatAsar/EnvisatAsarRecordFactory.h   |   61 +
 .../ossim/EnvisatAsar/GeolocationGrid.cpp          |  218 +
 ossim_plugins/ossim/EnvisatAsar/GeolocationGrid.h  |  254 +
 .../ossim/EnvisatAsar/MainProcessingParameters.cpp |  990 +++
 .../ossim/EnvisatAsar/MainProcessingParameters.h   | 1384 +++
 ossim_plugins/ossim/EnvisatAsar/SQ_ADSR.cpp        |  365 +
 ossim_plugins/ossim/EnvisatAsar/SQ_ADSR.h          |  497 ++
 .../ossim/EnvisatAsar/SRGRConversionParameters.cpp |  111 +
 .../ossim/EnvisatAsar/SRGRConversionParameters.h   |  178 +
 ossim_plugins/ossim/EnvisatAsar/dsd.cpp            |  158 +
 ossim_plugins/ossim/EnvisatAsar/dsd.h              |  176 +
 ossim_plugins/ossim/EnvisatAsar/mph.cpp            |  820 ++
 ossim_plugins/ossim/EnvisatAsar/mph.h              |  990 +++
 ossim_plugins/ossim/EnvisatAsar/sph.cpp            |  787 ++
 ossim_plugins/ossim/EnvisatAsar/sph.h              | 1017 +++
 .../ossim/RadarSat/CommonRecord/AttitudeData.cpp   |   95 +
 .../ossim/RadarSat/CommonRecord/AttitudeData.h     |  156 +
 .../CommonRecord/BeamInformationRecord.cpp         |   79 +
 .../RadarSat/CommonRecord/BeamInformationRecord.h  |  115 +
 .../RadarSat/CommonRecord/BeamPixelCountRecord.cpp |   71 +
 .../RadarSat/CommonRecord/BeamPixelCountRecord.h   |   88 +
 .../CommonRecord/CompensationDataRecord.cpp        |  147 +
 .../RadarSat/CommonRecord/CompensationDataRecord.h |  163 +
 .../RadarSat/CommonRecord/DataHistogramRecord.cpp  |  237 +
 .../RadarSat/CommonRecord/DataHistogramRecord.h    |  303 +
 .../CommonRecord/DataHistogramSignalData.cpp       |   94 +
 .../CommonRecord/DataHistogramSignalData.h         |  161 +
 .../RadarSat/CommonRecord/DataPointDataRecord.cpp  |  144 +
 .../RadarSat/CommonRecord/DataPointDataRecord.h    |  218 +
 .../ossim/RadarSat/CommonRecord/DataQuality.cpp    |  294 +
 .../ossim/RadarSat/CommonRecord/DataQuality.h      |  401 +
 .../ossim/RadarSat/CommonRecord/DataSetSummary.cpp |  775 ++
 .../ossim/RadarSat/CommonRecord/DataSetSummary.h   | 1076 +++
 .../CommonRecord/DopplerCentroidEstimateRecord.cpp |   79 +
 .../CommonRecord/DopplerCentroidEstimateRecord.h   |   98 +
 .../ossim/RadarSat/CommonRecord/FileDescriptor.cpp |  336 +
 .../ossim/RadarSat/CommonRecord/FileDescriptor.h   |  630 ++
 .../CommonRecord/MisregistrationRecord.cpp         |   57 +
 .../RadarSat/CommonRecord/MisregistrationRecord.h  |   87 +
 .../RadarSat/CommonRecord/ProcessingParameters.cpp |  902 ++
 .../RadarSat/CommonRecord/ProcessingParameters.h   | 1162 +++
 .../CommonRecord/RadiometricCompensationData.cpp   |   92 +
 .../CommonRecord/RadiometricCompensationData.h     |  153 +
 .../RadarSat/CommonRecord/RadiometricData.cpp      |  189 +
 .../ossim/RadarSat/CommonRecord/RadiometricData.h  |  237 +
 .../CommonRecord/RadiometryUncertaintyRecord.cpp   |   57 +
 .../CommonRecord/RadiometryUncertaintyRecord.h     |   86 +
 .../CommonRecord/SRGRCoefficientSetRecord.cpp      |   72 +
 .../CommonRecord/SRGRCoefficientSetRecord.h        |   88 +
 .../CommonRecord/TemperatureSettingsRecord.cpp     |   65 +
 .../CommonRecord/TemperatureSettingsRecord.h       |   76 +
 ossim_plugins/ossim/RadarSat/Data/Data.cpp         |  236 +
 ossim_plugins/ossim/RadarSat/Data/Data.h           |   87 +
 ossim_plugins/ossim/RadarSat/Data/DataFactory.cpp  |   42 +
 ossim_plugins/ossim/RadarSat/Data/DataFactory.h    |   42 +
 .../RadarSat/Data/ImageOptionsFileDescriptor.cpp   |  386 +
 .../RadarSat/Data/ImageOptionsFileDescriptor.h     |  668 ++
 .../ossim/RadarSat/Data/ProcessedDataRecord.cpp    |  223 +
 .../ossim/RadarSat/Data/ProcessedDataRecord.h      |  423 +
 .../RadarSat/Leader/DataHistogramProcessedData.cpp |   95 +
 .../RadarSat/Leader/DataHistogramProcessedData.h   |  173 +
 ossim_plugins/ossim/RadarSat/Leader/Leader.cpp     |  201 +
 ossim_plugins/ossim/RadarSat/Leader/Leader.h       |  109 +
 .../ossim/RadarSat/Leader/LeaderFactory.cpp        |   59 +
 .../ossim/RadarSat/Leader/LeaderFactory.h          |   45 +
 .../ossim/RadarSat/Leader/PlatformPositionData.cpp |  252 +
 .../ossim/RadarSat/Leader/PlatformPositionData.h   |  296 +
 .../ossim/RadarSat/Leader/PositionVectorRecord.cpp |   84 +
 .../ossim/RadarSat/Leader/PositionVectorRecord.h   |   86 +
 ossim_plugins/ossim/RadarSat/RadarSatRecord.cpp    |   31 +
 ossim_plugins/ossim/RadarSat/RadarSatRecord.h      |   77 +
 .../ossim/RadarSat/RadarSatRecordFactory.cpp       |   42 +
 .../ossim/RadarSat/RadarSatRecordFactory.h         |   61 +
 .../ossim/RadarSat/RadarSatRecordHeader.cpp        |   81 +
 .../ossim/RadarSat/RadarSatRecordHeader.h          |  140 +
 ossim_plugins/ossim/RadarSat/Trailer/Trailer.cpp   |  173 +
 ossim_plugins/ossim/RadarSat/Trailer/Trailer.h     |  104 +
 .../ossim/RadarSat/Trailer/TrailerFactory.cpp      |   57 +
 .../ossim/RadarSat/Trailer/TrailerFactory.h        |   45 +
 .../ossim/RadarSat/VolumeDir/FilePointerRecord.cpp |  164 +
 .../ossim/RadarSat/VolumeDir/FilePointerRecord.h   |  306 +
 .../ossim/RadarSat/VolumeDir/TextRecord.cpp        |  105 +
 .../ossim/RadarSat/VolumeDir/TextRecord.h          |  200 +
 .../RadarSat/VolumeDir/VolumeDescriptorRecord.cpp  |  215 +
 .../RadarSat/VolumeDir/VolumeDescriptorRecord.h    |  394 +
 .../ossim/RadarSat/VolumeDir/VolumeDir.cpp         |  140 +
 ossim_plugins/ossim/RadarSat/VolumeDir/VolumeDir.h |   92 +
 .../ossim/RadarSat/VolumeDir/VolumeDirFactory.cpp  |   48 +
 .../ossim/RadarSat/VolumeDir/VolumeDirFactory.h    |   45 +
 .../ossim/erssar/ErsSarDataSetSummary.cpp          |  776 ++
 ossim_plugins/ossim/erssar/ErsSarDataSetSummary.h  | 1071 +++
 ossim_plugins/ossim/erssar/ErsSarFacilityData.cpp  | 1167 +++
 ossim_plugins/ossim/erssar/ErsSarFacilityData.h    | 1810 ++++
 .../ossim/erssar/ErsSarFileDescriptor.cpp          |  338 +
 ossim_plugins/ossim/erssar/ErsSarFileDescriptor.h  |  635 ++
 ossim_plugins/ossim/erssar/ErsSarLeader.cpp        |  291 +
 ossim_plugins/ossim/erssar/ErsSarLeader.h          |  109 +
 ossim_plugins/ossim/erssar/ErsSarLeaderFactory.cpp |   48 +
 ossim_plugins/ossim/erssar/ErsSarLeaderFactory.h   |   49 +
 .../ossim/erssar/ErsSarMapProjectionData.cpp       |  210 +
 .../ossim/erssar/ErsSarMapProjectionData.h         |  324 +
 .../ossim/erssar/ErsSarPlatformPositionData.cpp    |  251 +
 .../ossim/erssar/ErsSarPlatformPositionData.h      |  299 +
 .../ossim/erssar/ErsSarPositionVectorRecord.cpp    |   86 +
 .../ossim/erssar/ErsSarPositionVectorRecord.h      |   90 +
 ossim_plugins/ossim/erssar/ErsSarRecord.cpp        |   32 +
 ossim_plugins/ossim/erssar/ErsSarRecord.h          |   79 +
 ossim_plugins/ossim/erssar/ErsSarRecordFactory.cpp |   43 +
 ossim_plugins/ossim/erssar/ErsSarRecordFactory.h   |   67 +
 ossim_plugins/ossim/erssar/ErsSarRecordHeader.cpp  |   83 +
 ossim_plugins/ossim/erssar/ErsSarRecordHeader.h    |  143 +
 ossim_plugins/ossim/ossimAlosPalsarModel.cpp       |  794 ++
 ossim_plugins/ossim/ossimAlosPalsarModel.h         |  132 +
 ossim_plugins/ossim/ossimCosmoSkymedModel.cpp      |  398 +
 ossim_plugins/ossim/ossimCosmoSkymedModel.h        |   96 +
 ossim_plugins/ossim/ossimEnvisatAsarModel.cpp      |  678 ++
 ossim_plugins/ossim/ossimEnvisatAsarModel.h        |  140 +
 ossim_plugins/ossim/ossimErsSarModel.cpp           |  687 ++
 ossim_plugins/ossim/ossimErsSarModel.h             |  129 +
 .../ossim/ossimFormosatDimapSupportData.cpp        | 2693 ++++++
 .../ossim/ossimFormosatDimapSupportData.h          |  322 +
 ossim_plugins/ossim/ossimFormosatModel.cpp         |  798 ++
 ossim_plugins/ossim/ossimFormosatModel.h           |  167 +
 .../ossim/ossimGeometricSarSensorModel.cpp         |  811 ++
 ossim_plugins/ossim/ossimGeometricSarSensorModel.h |  248 +
 .../ossim/ossimPleiadesDimapSupportData.cpp        | 2905 +++++++
 .../ossim/ossimPleiadesDimapSupportData.h          |  374 +
 ossim_plugins/ossim/ossimPleiadesModel.cpp         |  385 +
 ossim_plugins/ossim/ossimPleiadesModel.h           |  114 +
 ossim_plugins/ossim/ossimPluginCommon.cpp          |  190 +
 ossim_plugins/ossim/ossimPluginCommon.h            |   93 +
 ossim_plugins/ossim/ossimPluginInit.cpp            |   97 +
 .../ossim/ossimPluginProjectionFactory.cpp         |  563 ++
 ossim_plugins/ossim/ossimPluginProjectionFactory.h |   61 +
 ossim_plugins/ossim/ossimPluginReaderFactory.cpp   |  179 +
 ossim_plugins/ossim/ossimPluginReaderFactory.h     |  105 +
 ossim_plugins/ossim/ossimRadarSat2Model.cpp        | 1595 ++++
 ossim_plugins/ossim/ossimRadarSat2Model.h          |  199 +
 ossim_plugins/ossim/ossimRadarSat2ProductDoc.cpp   | 1153 +++
 ossim_plugins/ossim/ossimRadarSat2ProductDoc.h     |  232 +
 ossim_plugins/ossim/ossimRadarSat2RPCModel.cpp     |  666 ++
 ossim_plugins/ossim/ossimRadarSat2RPCModel.h       |  153 +
 ossim_plugins/ossim/ossimRadarSat2TiffReader.cpp   |  316 +
 ossim_plugins/ossim/ossimRadarSat2TiffReader.h     |  107 +
 ossim_plugins/ossim/ossimRadarSatModel.cpp         | 1232 +++
 ossim_plugins/ossim/ossimRadarSatModel.h           |  169 +
 ossim_plugins/ossim/ossimSpot6DimapSupportData.cpp | 2217 +++++
 ossim_plugins/ossim/ossimSpot6DimapSupportData.h   |  348 +
 ossim_plugins/ossim/ossimSpot6Model.cpp            |  372 +
 ossim_plugins/ossim/ossimSpot6Model.h              |  114 +
 ossim_plugins/ossim/ossimTerraSarModel.cpp         | 2468 ++++++
 ossim_plugins/ossim/ossimTerraSarModel.h           |  330 +
 ossim_plugins/ossim/ossimTerraSarProductDoc.cpp    | 1477 ++++
 ossim_plugins/ossim/ossimTerraSarProductDoc.h      |  281 +
 ossim_plugins/ossim/ossimTerraSarTiffReader.cpp    |  345 +
 ossim_plugins/ossim/ossimTerraSarTiffReader.h      |  110 +
 ossim_plugins/ossim/ossimTileMapModel.cpp          |  288 +
 ossim_plugins/ossim/ossimTileMapModel.h            |  166 +
 ossim_plugins/ossim/otb/Arithmetic.h               |   44 +
 ossim_plugins/ossim/otb/CivilDateTime.cpp          |  474 ++
 ossim_plugins/ossim/otb/CivilDateTime.h            |  188 +
 ossim_plugins/ossim/otb/Coordinate.cpp             |   62 +
 ossim_plugins/ossim/otb/Coordinate.h               |   75 +
 ossim_plugins/ossim/otb/Ephemeris.cpp              |  202 +
 ossim_plugins/ossim/otb/Ephemeris.h                |  132 +
 ossim_plugins/ossim/otb/Equation.cpp               |  933 +++
 ossim_plugins/ossim/otb/Equation.h                 |  145 +
 ossim_plugins/ossim/otb/GMSTDateTime.cpp           |   52 +
 ossim_plugins/ossim/otb/GMSTDateTime.h             |   92 +
 ossim_plugins/ossim/otb/GalileanEphemeris.cpp      |  296 +
 ossim_plugins/ossim/otb/GalileanEphemeris.h        |   78 +
 ossim_plugins/ossim/otb/GeodesicCoordinate.cpp     |   45 +
 ossim_plugins/ossim/otb/GeodesicCoordinate.h       |   56 +
 ossim_plugins/ossim/otb/GeographicEphemeris.cpp    |   86 +
 ossim_plugins/ossim/otb/GeographicEphemeris.h      |   75 +
 ossim_plugins/ossim/otb/HermiteInterpolator.cpp    |  355 +
 ossim_plugins/ossim/otb/HermiteInterpolator.h      |   97 +
 ossim_plugins/ossim/otb/ImageNoise.cpp             |  283 +
 ossim_plugins/ossim/otb/ImageNoise.h               |  163 +
 ossim_plugins/ossim/otb/IncidenceAngles.cpp        |  162 +
 ossim_plugins/ossim/otb/IncidenceAngles.h          |  105 +
 ossim_plugins/ossim/otb/InfoIncidenceAngle.cpp     |  124 +
 ossim_plugins/ossim/otb/InfoIncidenceAngle.h       |  102 +
 ossim_plugins/ossim/otb/InfoSceneCoord.cpp         |  196 +
 ossim_plugins/ossim/otb/InfoSceneCoord.h           |  134 +
 ossim_plugins/ossim/otb/JSDDateTime.cpp            |  237 +
 ossim_plugins/ossim/otb/JSDDateTime.h              |  135 +
 ossim_plugins/ossim/otb/JulianDate.cpp             |  147 +
 ossim_plugins/ossim/otb/JulianDate.h               |  103 +
 ossim_plugins/ossim/otb/MJDDateTime.cpp            |   52 +
 ossim_plugins/ossim/otb/MJDDateTime.h              |   92 +
 ossim_plugins/ossim/otb/Noise.cpp                  |  161 +
 ossim_plugins/ossim/otb/Noise.h                    |  119 +
 ossim_plugins/ossim/otb/PlatformPosition.cpp       |  276 +
 ossim_plugins/ossim/otb/PlatformPosition.h         |  137 +
 ossim_plugins/ossim/otb/RadarSat2NoiseLevel.cpp    |  317 +
 ossim_plugins/ossim/otb/RadarSat2NoiseLevel.h      |  161 +
 ossim_plugins/ossim/otb/RectangularCoordinate.cpp  |  108 +
 ossim_plugins/ossim/otb/RectangularCoordinate.h    |   59 +
 ossim_plugins/ossim/otb/RefPoint.cpp               |  199 +
 ossim_plugins/ossim/otb/RefPoint.h                 |   89 +
 ossim_plugins/ossim/otb/SarSensor.cpp              |  237 +
 ossim_plugins/ossim/otb/SarSensor.h                |   72 +
 ossim_plugins/ossim/otb/SceneCoord.cpp             |  166 +
 ossim_plugins/ossim/otb/SceneCoord.h               |  105 +
 ossim_plugins/ossim/otb/Sensor.cpp                 |   41 +
 ossim_plugins/ossim/otb/Sensor.h                   |   62 +
 ossim_plugins/ossim/otb/SensorParams.cpp           |  272 +
 ossim_plugins/ossim/otb/SensorParams.h             |  267 +
 ossim_plugins/ossimPluginConstants.h               |   43 +
 ossim_plugins/pdal/CMakeLists.txt                  |   71 +
 ossim_plugins/pdal/ossimPdalFileReader.cpp         |  259 +
 ossim_plugins/pdal/ossimPdalFileReader.h           |   55 +
 ossim_plugins/pdal/ossimPdalPluginInit.cpp         |   80 +
 ossim_plugins/pdal/ossimPdalReader.cpp             |  336 +
 ossim_plugins/pdal/ossimPdalReader.h               |   80 +
 ossim_plugins/pdal/ossimPdalReaderFactory.cpp      |  107 +
 ossim_plugins/pdal/ossimPdalReaderFactory.h        |   60 +
 ossim_plugins/pdal/ossimRialtoReader.cpp           |  206 +
 ossim_plugins/pdal/ossimRialtoReader.h             |   58 +
 ossim_plugins/pdal/test/CMakeLists.txt             |   39 +
 ossim_plugins/pdal/test/README.txt                 |   39 +
 ossim_plugins/pdal/test/autzen.las                 |  Bin 0 -> 363585 bytes
 ossim_plugins/pdal/test/autzen.xml                 |    8 +
 ossim_plugins/pdal/test/pdal-EXPECTED.tif          |  Bin 0 -> 1049014 bytes
 ossim_plugins/pdal/test/plugin-test.cpp            |  170 +
 ossim_plugins/pdal/test/rialto-EXPECTED.tif        |  Bin 0 -> 524710 bytes
 ossim_plugins/png/CMakeLists.txt                   |   61 +
 ossim_plugins/png/makefile.vc                      |   59 +
 ossim_plugins/png/ossimPngCodec.cpp                |  500 ++
 ossim_plugins/png/ossimPngCodec.h                  |   93 +
 ossim_plugins/png/ossimPngCodecFactory.cpp         |   94 +
 ossim_plugins/png/ossimPngCodecFactory.h           |   73 +
 ossim_plugins/png/ossimPngPluginInit.cpp           |   87 +
 ossim_plugins/png/ossimPngReader.cpp               | 1350 +++
 ossim_plugins/png/ossimPngReader.h                 |  323 +
 ossim_plugins/png/ossimPngReaderFactory.cpp        |  164 +
 ossim_plugins/png/ossimPngReaderFactory.h          |  122 +
 ossim_plugins/png/ossimPngWriter.cpp               | 1017 +++
 ossim_plugins/png/ossimPngWriter.h                 |  395 +
 ossim_plugins/png/ossimPngWriterFactory.cpp        |  146 +
 ossim_plugins/png/ossimPngWriterFactory.h          |  112 +
 ossim_plugins/registration/CMakeLists.txt          |   51 +
 ossim_plugins/registration/makefile.vc             |   68 +
 ossim_plugins/registration/ossimChipMatch.cpp      |  584 ++
 ossim_plugins/registration/ossimChipMatch.h        |  110 +
 ossim_plugins/registration/ossimDensityReducer.cpp |  269 +
 ossim_plugins/registration/ossimDensityReducer.h   |   57 +
 ossim_plugins/registration/ossimExtremaFilter.cpp  |  305 +
 ossim_plugins/registration/ossimExtremaFilter.h    |   62 +
 ossim_plugins/registration/ossimHarrisCorners.cpp  |  400 +
 ossim_plugins/registration/ossimHarrisCorners.h    |  108 +
 .../registration/ossimImageCorrelator.cpp          |  679 ++
 ossim_plugins/registration/ossimImageCorrelator.h  |  147 +
 ossim_plugins/registration/ossimModelOptimizer.cpp |  279 +
 ossim_plugins/registration/ossimModelOptimizer.h   |   92 +
 ossim_plugins/registration/ossimMultiplier.cpp     |  328 +
 ossim_plugins/registration/ossimMultiplier.h       |   52 +
 ossim_plugins/registration/ossimNCC_FFTW.cpp       |  269 +
 ossim_plugins/registration/ossimNCC_FFTW.h         |  174 +
 .../registration/ossimOutlierRejection.cpp         |  314 +
 ossim_plugins/registration/ossimOutlierRejection.h |   73 +
 .../registration/ossimRegistrationExports.h        |   31 +
 .../ossimRegistrationImageSourceFactory.cpp        |  130 +
 .../ossimRegistrationImageSourceFactory.h          |   25 +
 .../registration/ossimRegistrationMiscFactory.cpp  |   62 +
 .../registration/ossimRegistrationMiscFactory.h    |   31 +
 .../registration/ossimRegistrationPluginInit.cpp   |   75 +
 ossim_plugins/registration/ossimRunningSum.cpp     |  108 +
 ossim_plugins/registration/ossimRunningSum.h       |   32 +
 ossim_plugins/registration/ossimSquareFunction.cpp |  285 +
 ossim_plugins/registration/ossimSquareFunction.h   |   47 +
 ossim_plugins/registration/ossimTieGenerator.cpp   |  211 +
 ossim_plugins/registration/ossimTieGenerator.h     |   98 +
 ossim_plugins/registration/ossimreg_plugin.vcproj  |  323 +
 ossim_plugins/sqlite/CMakeLists.txt                |   72 +
 ossim_plugins/sqlite/ossimGpkgContentsRecord.cpp   |  328 +
 ossim_plugins/sqlite/ossimGpkgContentsRecord.h     |  101 +
 .../sqlite/ossimGpkgDatabaseRecordBase.cpp         |   41 +
 ossim_plugins/sqlite/ossimGpkgDatabaseRecordBase.h |   67 +
 ossim_plugins/sqlite/ossimGpkgInfo.cpp             |  209 +
 ossim_plugins/sqlite/ossimGpkgInfo.h               |   60 +
 .../sqlite/ossimGpkgNsgTileMatrixExtentRecord.cpp  |  342 +
 .../sqlite/ossimGpkgNsgTileMatrixExtentRecord.h    |  105 +
 ossim_plugins/sqlite/ossimGpkgReader.cpp           |  984 +++
 ossim_plugins/sqlite/ossimGpkgReader.h             |  293 +
 .../sqlite/ossimGpkgSpatialRefSysRecord.cpp        |  468 ++
 .../sqlite/ossimGpkgSpatialRefSysRecord.h          |  112 +
 ossim_plugins/sqlite/ossimGpkgTileEntry.cpp        |  435 +
 ossim_plugins/sqlite/ossimGpkgTileEntry.h          |  183 +
 ossim_plugins/sqlite/ossimGpkgTileMatrixRecord.cpp |  313 +
 ossim_plugins/sqlite/ossimGpkgTileMatrixRecord.h   |  119 +
 .../sqlite/ossimGpkgTileMatrixSetRecord.cpp        |  274 +
 .../sqlite/ossimGpkgTileMatrixSetRecord.h          |  110 +
 ossim_plugins/sqlite/ossimGpkgTileRecord.cpp       |  333 +
 ossim_plugins/sqlite/ossimGpkgTileRecord.h         |  104 +
 ossim_plugins/sqlite/ossimGpkgUtil.cpp             |  627 ++
 ossim_plugins/sqlite/ossimGpkgUtil.h               |  168 +
 ossim_plugins/sqlite/ossimGpkgWriter.cpp           | 3128 +++++++
 ossim_plugins/sqlite/ossimGpkgWriter.h             |  715 ++
 ossim_plugins/sqlite/ossimSqliteInfoFactory.cpp    |   60 +
 ossim_plugins/sqlite/ossimSqliteInfoFactory.h      |   58 +
 ossim_plugins/sqlite/ossimSqlitePluginInit.cpp     |   91 +
 ossim_plugins/sqlite/ossimSqliteReaderFactory.cpp  |  157 +
 ossim_plugins/sqlite/ossimSqliteReaderFactory.h    |  103 +
 ossim_plugins/sqlite/ossimSqliteUtil.cpp           |  126 +
 ossim_plugins/sqlite/ossimSqliteUtil.h             |   63 +
 ossim_plugins/sqlite/ossimSqliteWriterFactory.cpp  |  146 +
 ossim_plugins/sqlite/ossimSqliteWriterFactory.h    |  112 +
 .../unit_test/ossimUnitTestImageSourceFactory.cpp  |  100 +
 .../unit_test/ossimUnitTestImageSourceFactory.h    |   23 +
 .../unit_test/ossimUnitTestPluginInit.cpp          |   76 +
 .../unit_test/ossimUnitTestPolyCutter.cpp          |  122 +
 ossim_plugins/unit_test/ossimUnitTestPolyCutter.h  |   34 +
 ossim_plugins/unit_test/unit_test.vcproj           |  153 +
 ossim_plugins/web/CMakeLists.txt                   |   52 +
 ossim_plugins/web/ossimCurlHttpRequest.cpp         |  110 +
 ossim_plugins/web/ossimCurlHttpRequest.h           |   44 +
 ossim_plugins/web/ossimWebPluginInit.cpp           |   82 +
 ossim_plugins/web/ossimWebPluginRequestFactory.cpp |   34 +
 ossim_plugins/web/ossimWebPluginRequestFactory.h   |   17 +
 ossim_plugins/worldwind/ossimDiskCache.cpp         |  368 +
 ossim_plugins/worldwind/ossimDiskCache.h           |  107 +
 .../worldwind/ossimSharedDiskCacheManager.cpp      |   75 +
 .../worldwind/ossimSharedDiskCacheManager.h        |   23 +
 ossim_plugins/worldwind/ossimWorldWindExports.h    |   31 +
 ossim_plugins/worldwind/ossimWorldWindFactory.cpp  |  146 +
 ossim_plugins/worldwind/ossimWorldWindFactory.h    |   63 +
 ossim_plugins/worldwind/ossimWorldWindHandler.cpp  |  857 ++
 ossim_plugins/worldwind/ossimWorldWindHandler.h    |  111 +
 .../worldwind/ossimWorldWindJpegImage.cpp          |  260 +
 ossim_plugins/worldwind/ossimWorldWindJpegImage.h  |   14 +
 .../worldwind/ossimWorldWindPluginInit.cpp         |   57 +
 .../worldwind/ossimworldwind_plugin.vcproj         |  252 +
 .../xcode/ossim_plugins.xcodeproj/project.pbxproj  | 4680 +++++++++++
 682 files changed, 210888 insertions(+)

diff --git a/ossim_plugins/CMakeLists.txt b/ossim_plugins/CMakeLists.txt
new file mode 100644
index 0000000..0d0ae73
--- /dev/null
+++ b/ossim_plugins/CMakeLists.txt
@@ -0,0 +1,185 @@
+project(ossimplugins)
+MESSAGE("**********************Setting up ossimplugins********************")
+
+IF(NOT APPLE)
+  cmake_minimum_required(VERSION 2.6)
+ELSE(NOT APPLE)
+  cmake_minimum_required(VERSION 2.8)
+ENDIF(NOT APPLE)
+
+include(OssimVersion)
+include(OssimCommonVariables)
+include(OssimUtilities)
+
+############################### OVERRIDE THE DEFAULTS TO APPEND THE PLUGIN INFORMATION###################
+
+
+OPTION(OSSIM_INSTALL_PLUGINS_WITH_VERSION "Set to ON to build OSSIM's plugins to install with a version prefix like ossim-<version>/plugins.  Use OFF to not add a version and make it ossim/plugins." OFF)
+OPTION(BUILD_OSSIM_PLUGIN "Set to ON to build OSSIM's core plugins that depend only on ossim.  Use OFF to skip this plugin." ON)
+OPTION(BUILD_OSSIMCONTRIB_PLUGIN "Set to ON to build OSSIM's contrib plugin.  Use OFF to skip this plugin." OFF)
+OPTION(BUILD_OSSIMCSM_PLUGIN "Set to ON to build OSSIM's csm  plugin.  Use OFF to skip this plugin." OFF)
+OPTION(BUILD_OSSIMGDAL_PLUGIN "Set to ON to build OSSIM's gdal plugin.  Use OFF to skip this plugin." OFF)
+OPTION(BUILD_OSSIMGEOPDF_PLUGIN "Set to ON to build OSSIM's geopdf plugin.  Use OFF to skip this plugin." OFF)
+
+# Old hdf plugin:
+OPTION(BUILD_OSSIMHDF_PLUGIN "Set to ON to build OSSIM's hdf plugin.  Use OFF to skip this plugin." OFF)
+
+# New split out hdf4 and hdf5 plugins:
+OPTION(BUILD_OSSIMHDF4_PLUGIN "Set to ON to build OSSIM's hdf4 plugin.  Use OFF to skip this plugin." OFF)
+OPTION(BUILD_OSSIMHDF5_PLUGIN "Set to ON to build OSSIM's hdf5 plugin.  Use OFF to skip this plugin." OFF)
+
+OPTION(BUILD_OSSIMKAKADU_PLUGIN "Set to ON to build OSSIM's kakadu plugin.  Use OFF to skip this plugin." OFF)
+OPTION(BUILD_OSSIMKMLSUPEROVERLAY_PLUGIN "Set to ON to build OSSIM's kml super overvlay plugin.  Use OFF to skip this plugin." OFF)
+OPTION(BUILD_OSSIMLAS_PLUGIN "Set to ON to build OSSIM's LAS plugin.  Use OFF to skip this plugin." OFF)
+OPTION(BUILD_OSSIMLIBRAW_PLUGIN "Set to ON to build OSSIM's lib raw plugin that is an interface to draw plugin.  Use OFF to skip this plugin." ON)
+OPTION(BUILD_OSSIMMRSID_PLUGIN "Set to ON to build OSSIM's mrsid plugin.  Use OFF to skip this plugin." OFF)
+OPTION(BUILD_OSSIMNDF_PLUGIN "Set to ON to build OSSIM's ndf plugin.  Use OFF to skip this plugin." OFF)
+OPTION(BUILD_OSSIMOPENCV_PLUGIN "Set to ON to build OSSIM's opencv plugin.  Use OFF to skip this plugin." OFF)
+OPTION(BUILD_OSSIMOPENJPEG_PLUGIN "Set to ON to build OSSIM's openjpeg plugin.  Use OFF to skip this plugin." OFF)
+OPTION(BUILD_OSSIMPDAL_PLUGIN "Set to ON to build OSSIM's pdal plugin.  Use OFF to skip this plugin." OFF)
+OPTION(BUILD_OSSIMPNG_PLUGIN "Set to ON to build OSSIM's png plugin.  Use OFF to skip this plugin." OFF)
+OPTION(BUILD_OSSIMREGISTRATION_PLUGIN "Set to ON to build OSSIM's registration plugin.  Use OFF to skip this plugin." OFF)
+OPTION(BUILD_OSSIMSQLITE_PLUGIN "Set to ON to build OSSIM's sqlite plugin.  Use OFF to skip this plugin." OFF)
+OPTION(BUILD_OSSIMWEB_PLUGIN "Set to ON to build OSSIM's web plugin.  Use OFF to skip this plugin." OFF)
+
+find_package(OpenThreads)
+find_package(ossim)
+
+IF(OSSIM_INSTALL_PLUGINS_WITH_VERSION)
+  SET(INSTALL_RUNTIME_DIR   "${INSTALL_LIBRARY_DIR}/ossim-${OSSIM_VERSION}/plugins")
+ELSE()
+  SET(INSTALL_RUNTIME_DIR   "${INSTALL_LIBRARY_DIR}/ossim/plugins")
+ENDIF()
+
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
+INCLUDE_DIRECTORIES(${OSSIM_INCLUDE_DIR})
+INCLUDE_DIRECTORIES(${OPENTHREADS_INCLUDE_DIR})
+
+SET(BUILD_OSSIM_FRAMEWORKS "OFF")
+SET(OSSIM_PLUGIN_LINK_TYPE "SHARED")
+
+if(BUILD_OSSIM_PLUGIN)
+   SUBDIRS(ossim)
+ENDIF(BUILD_OSSIM_PLUGIN)
+
+IF(BUILD_OSSIMCONTRIB_PLUGIN)
+   MESSAGE(WARNING "BUILD_OSSIMCONTRIB_PLUGIN: We have not created a CMakeList.txt for the contrib plugin yet.")
+ENDIF(BUILD_OSSIMCONTRIB_PLUGIN)
+
+if(BUILD_OSSIMCSM_PLUGIN)
+   SUBDIRS(csm)
+ENDiF(BUILD_OSSIMCSM_PLUGIN)
+
+if(BUILD_OSSIMGDAL_PLUGIN)
+   SUBDIRS(gdal)
+ENDIF(BUILD_OSSIMGDAL_PLUGIN)
+
+if(BUILD_OSSIMGEOPDF_PLUGIN)
+   SUBDIRS(geopdf)
+ENDIF(BUILD_OSSIMGEOPDF_PLUGIN)
+
+if(BUILD_OSSIMHDF_PLUGIN)
+   SUBDIRS(hdf)
+ENDIF(BUILD_OSSIMHDF_PLUGIN)
+
+if(BUILD_OSSIMHDF4_PLUGIN)
+   SUBDIRS(hdf4)
+ENDIF(BUILD_OSSIMHDF4_PLUGIN)
+
+if(BUILD_OSSIMHDF5_PLUGIN)
+   SUBDIRS(hdf5)
+ENDIF(BUILD_OSSIMHDF5_PLUGIN)
+
+if(BUILD_OSSIMKAKADU_PLUGIN)
+   SUBDIRS(kakadu)
+ENDIF(BUILD_OSSIMKAKADU_PLUGIN)
+
+if(BUILD_OSSIMKMLSUPEROVERLAY_PLUGIN)
+   SUBDIRS(kmlsuperoverlay)
+ENDIF(BUILD_OSSIMKMLSUPEROVERLAY_PLUGIN)
+
+IF(BUILD_OSSIMLAS_PLUGIN)
+   SUBDIRS(las)
+ENDIF(BUILD_OSSIMLAS_PLUGIN)
+
+IF(BUILD_OSSIMLIBLAS_PLUGIN)
+   SUBDIRS(liblas)
+ENDIF(BUILD_OSSIMLIBLAS_PLUGIN)
+
+IF(BUILD_OSSIMLIBRAW_PLUGIN)
+   SUBDIRS(libraw)
+ENDIF(BUILD_OSSIMLIBRAW_PLUGIN)
+
+IF(BUILD_OSSIMMRSID_PLUGIN)
+   SUBDIRS(mrsid)  
+ENDIF(BUILD_OSSIMMRSID_PLUGIN)
+
+IF(BUILD_OSSIMNDF_PLUGIN)
+   SUBDIRS(ndf) 
+ENDIF(BUILD_OSSIMNDF_PLUGIN)
+
+IF(BUILD_OSSIMOPENCV_PLUGIN)
+   SUBDIRS(opencv)
+ENDIF(BUILD_OSSIMOPENCV_PLUGIN)
+
+IF(BUILD_OSSIMOPENJPEG_PLUGIN)
+   SUBDIRS(openjpeg) 
+ENDIF(BUILD_OSSIMOPENJPEG_PLUGIN)
+
+IF(BUILD_OSSIMPDAL_PLUGIN)
+   SUBDIRS(pdal)
+ENDIF(BUILD_OSSIMPDAL_PLUGIN)
+
+if(BUILD_OSSIMPNG_PLUGIN)
+   SUBDIRS(png)
+ENDIF(BUILD_OSSIMPNG_PLUGIN)
+
+if(BUILD_OSSIMREGISTRATION_PLUGIN)
+   SUBDIRS(registration)
+ENDIF(BUILD_OSSIMREGISTRATION_PLUGIN)
+
+if(BUILD_OSSIMSQLITE_PLUGIN)
+   SUBDIRS(sqlite)
+ENDIF(BUILD_OSSIMSQLITE_PLUGIN)
+
+if(BUILD_OSSIMWEB_PLUGIN)
+   SUBDIRS(web)
+ENDIF(BUILD_OSSIMWEB_PLUGIN)
+
+IF(OSSIM_BUILD_ADDITIONAL_PLUGIN_DIRECTORIES)
+    FOREACH(it IN LISTS OSSIM_BUILD_ADDITIONAL_PLUGIN_DIRECTORIES)
+        SUBDIRS(${it})
+    ENDFOREACH(it)
+ELSE(OSSIM_BUILD_ADDITIONAL_PLUGIN_DIRECTORIES)
+    SET(OSSIM_BUILD_ADDITIONAL_PLUGIN_DIRECTORIES "" CACHE PATH "Specify full paths separated by ; to additional plugins you wish to include into the ossim build framework" FORCE)
+ENDIF()
+
+MESSAGE( STATUS "BUILD_OSSIM_PLUGIN                 = ${BUILD_OSSIM_PLUGIN}" )
+MESSAGE( STATUS "BUILD_OSSIMCONTRIB_PLUGIN          = ${BUILD_OSSIMCONTRIB_PLUGIN}" )
+MESSAGE( STATUS "BUILD_OSSIMCSM_PLUGIN              = ${BUILD_OSSIMCSM_PLUGIN}" )
+MESSAGE( STATUS "BUILD_OSSIMGDAL_PLUGIN             = ${BUILD_OSSIMGDAL_PLUGIN}" )
+MESSAGE( STATUS "BUILD_OSSIMGEOPDF_PLUGIN           = ${BUILD_OSSIMGEOPDF_PLUGIN}" )
+MESSAGE( STATUS "BUILD_OSSIMHDF_PLUGIN              = ${BUILD_OSSIMHDF_PLUGIN}" )
+MESSAGE( STATUS "BUILD_OSSIMHDF4_PLUGIN             = ${BUILD_OSSIMHDF4_PLUGIN}" )
+MESSAGE( STATUS "BUILD_OSSIMHDF5_PLUGIN             = ${BUILD_OSSIMHDF5_PLUGIN}" )
+MESSAGE( STATUS "BUILD_OSSIMKAKADU_PLUGIN           = ${BUILD_OSSIMKAKADU_PLUGIN}" )
+MESSAGE( STATUS "BUILD_OSSIMKMLSUPEROVERLAY_PLUGIN  = ${BUILD_OSSIMKMLSUPEROVERLAY_PLUGIN}" )
+MESSAGE( STATUS "BUILD_OSSIMLAS_PLUGIN              = ${BUILD_OSSIMLAS_PLUGIN}" )
+MESSAGE( STATUS "BUILD_OSSIMLIBLAS_PLUGIN           = ${BUILD_OSSIMLIBLAS_PLUGIN}" )
+MESSAGE( STATUS "BUILD_OSSIMLIBRAW_PLUGIN           = ${BUILD_OSSIMLIBRAW_PLUGIN}" )
+MESSAGE( STATUS "BUILD_OSSIMMRSID_PLUGIN            = ${BUILD_OSSIMMRSID_PLUGIN}" )
+MESSAGE( STATUS "BUILD_OSSIMNDF_PLUGIN              = ${BUILD_OSSIMNDF_PLUGIN}" )
+MESSAGE( STATUS "BUILD_OSSIMOPENCV_PLUGIN           = ${BUILD_OSSIMOPENCV_PLUGIN}" )
+MESSAGE( STATUS "BUILD_OSSIMOPENJPEG_PLUGIN         = ${BUILD_OSSIMOPENJPEG_PLUGIN}" )
+MESSAGE( STATUS "BUILD_OSSIMPDAL_PLUGIN             = ${BUILD_OSSIMPDAL_PLUGIN}" )
+MESSAGE( STATUS "BUILD_OSSIMPNG_PLUGIN              = ${BUILD_OSSIMPNG_PLUGIN}" )
+MESSAGE( STATUS "BUILD_OSSIMREGISTRATION_PLUGIN     = ${BUILD_OSSIMREGISTRATION_PLUGIN}" )
+MESSAGE( STATUS "BUILD_OSSIMSQLITE_PLUGIN           = ${BUILD_OSSIMSQLITE_PLUGIN}" )
+MESSAGE( STATUS "BUILD_OSSIMWEB_PLUGIN              = ${BUILD_OSSIMWEB_PLUGIN}" )
+MESSAGE( STATUS "OPENTHREADS_LIBRARY                = ${OPENTHREADS_LIBRARY}" )
+MESSAGE( STATUS "OPENTHREADS_INCLUDE                = ${OPENTHREADS_INCLUDE_DIR}" )
+MESSAGE( STATUS "OSSIM_LIBRARY                      = ${OSSIM_LIBRARY}" )
+MESSAGE( STATUS "OSSIM_INCLUDE                      = ${OSSIM_INCLUDE_DIR}" )
+MESSAGE( STATUS "OSSIM_INSTALL_PLUGINS_WITH_VERSION = ${OSSIM_INSTALL_PLUGINS_WITH_VERSION}" )
+
+OSSIM_ADD_COMMON_MAKE_UNINSTALL()
diff --git a/ossim_plugins/LICENSE.txt b/ossim_plugins/LICENSE.txt
new file mode 100644
index 0000000..edc42b3
--- /dev/null
+++ b/ossim_plugins/LICENSE.txt
@@ -0,0 +1,141 @@
+GNU LESSER GENERAL PUBLIC LICENSE 
+
+Version 2.1, February 1999
+
+(The master copy of this license lives on the GNU website.) 
+
+Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+Everyone is permitted to copy and distribute verbatim copies
+of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL.  It also counts
+as the successor of the GNU Library Public License, version 2, hence
+the version number 2.1.]
+
+Preamble
+
+The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. 
+
+This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. 
+
+When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. 
+
+To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. 
+
+For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. 
+
+We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. 
+
+To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. 
+
+Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder.  Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. 
+
+Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. 
+
+When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. 
+
+We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. 
+
+For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. 
+
+In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. 
+
+Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of aprogram that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. 
+
+The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from thelibrary, whereas the latter must be combined with the library in order to run. 
+
+TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 
+
+0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". 
+
+A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. 
+
+The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) 
+
+"Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. 
+
+Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 
+
+1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. 
+
+You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 
+
+2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, andcopy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all ofthese conditions: 
+
+a) The modified work must itself be a software library. 
+b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. 
+c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. 
+d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. 
+
+(For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) 
+
+These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose p [...]
+
+Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. 
+
+In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 
+
+3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these  [...]
+
+Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. 
+
+This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 
+
+4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. 
+
+If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 
+
+5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. 
+
+However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library(because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. 
+
+When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. 
+
+If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) 
+
+Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 
+
+6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. 
+
+You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: 
+
+a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It i [...]
+
+For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler,kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. 
+
+It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 
+
+7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: 
+
+a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 
+
+8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 
+
+9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works ba [...]
+
+10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a licensefrom the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 
+
+11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not dis [...]
+
+If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. 
+
+It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor [...]
+
+This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 
+
+12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographicaldistribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 
+
+13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. 
+
+Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 
+
+14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two  goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software g [...]
+
+NO WARRANTY 
+
+15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU.  [...]
+
+16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO  [...]
+
+END OF TERMS AND CONDITIONS
diff --git a/ossim_plugins/README.txt b/ossim_plugins/README.txt
new file mode 100644
index 0000000..7d8661a
--- /dev/null
+++ b/ossim_plugins/README.txt
@@ -0,0 +1,94 @@
+$Id: README.txt 10595 2007-03-07 15:26:48Z dburken $
+
+README file for "Open Source Software Image Map (OSSIM) plugins module".
+
+Web site:  http://www.ossim.org/
+
+Mailing list: http://lists.sourceforge.net/lists/listinfo/ossim-developer 
+
+//---
+// SVS access via http:
+// This will check out ossim_plugins to current working directory.
+// You can use "http" or if you are a committer you should use "https".
+//---
+svn co http://svn.osgeo.org/ossim/trunk/ossim_plugins
+
+Build instructions:
+
+NOTE:  You must have "gdal" built for the gdal plugin.  There are brief
+       instructions for that below.
+
+Asuming you have a gdal library built, for most unix type platforms via 
+command line:
+1) If you do not have make.opt or a make_platform.opt you should run
+"gmake make_options" to create them.
+
+2) Edit the "make.opt" file.  This has specific details for different plugins.
+
+3) Edit the make_platform.opt file if needed.  This is for operating system
+overrides.  Usually this shouldn't need to be touched.
+
+4) cd to the plugin directory you witch to build.
+
+5) Type "gmake".
+
+
+To add your plugin via the ossim preferences:
+
+Note:  
+There is an ossim preferences file template in our source code at:
+ossim/etc/templates/ossim_preferences_template
+
+
+1) Set the environment variable "OSSIM_PREFS_FILE".
+   tcsh:     setenv OSSIM_PREFS_FILE your_path_to/ossim_preferences
+     or
+   bash/sh:  export OSSIM_PREFS_FILE=your_path_to/ossim_preferences
+
+2) In your preferences file add the line for your plugin:
+plugin.file1: /work/drb/ossim_plugins/lib/libgdalplugin.so
+
+
+To build gdal here is what I do:
+
+In this example code in parallel in "/work/drb/" directory.
+
+// If you haven't got the code already login to maptools cvs pserver:
+cvs -d :pserver:cvsanon at cvs.maptools.org:/cvs/maptools/cvsroot login
+password:  <hit return for password>
+
+// Get libtiff
+cvs -d :pserver:cvsanon at cvs.maptools.org:/cvs/maptools/cvsroot co libtiff
+
+// Get geotiff
+cvs -d :pserver:cvsanon at cvs.maptools.org:/cvs/maptools/cvsroot co geotiff
+
+// Get gdal
+cvs -d :pserver:cvsanon at cvs.maptools.org:/cvs/maptools/cvsroot co gdal
+
+// Build libtiff
+cd /work/drb/libtiff
+cvs -z 3 update -d -P
+./configure --prefix=/work/drb/libtiff
+make
+make install
+
+// Build geotiff
+cd /work/drb/geotiff/libgeotiff
+cvs -z 3 update -d -P
+./configure --prefix=/work/drb/geotiff --with-libtiff=/work/drb/libtiff
+make
+make install
+cd ../..
+
+// Build gdal
+cd /work/drb/gdal
+cvs -z 3 update -d -P
+./configure --prefix=/work/drb/geotiff --with-libtiff=/work/drb/libtiff
+make
+make install
+cd ../..
+./configure --prefix=/work/drb/gdal --without-libtool --with-libtiff=/work/drb/libtiff --with-geotiff=/work/drb/geotiff
+make
+make install
+
diff --git a/ossim_plugins/contrib/CMakeLists.txt b/ossim_plugins/contrib/CMakeLists.txt
new file mode 100644
index 0000000..db80d89
--- /dev/null
+++ b/ossim_plugins/contrib/CMakeLists.txt
@@ -0,0 +1,35 @@
+set(LIB_NAME ossimcontrib_plugin)
+MESSAGE( "************** LIBRARY SETUP FOR ossimcontrib_plugin******************")
+
+# Include ossim cmake stuff:
+include(OssimVersion)
+include(OssimCommonVariables)
+include(OssimUtilities)
+
+SET(OSSIM_FRAMEWORK_GENERATION "OFF")
+SET(OSSIM_USER_DEFINED_DYNAMIC_OR_STATIC "SHARED")
+
+find_package(ossim)
+
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
+INCLUDE_DIRECTORIES(${OPENTHREADS_INCLUDE_DIR})
+INCLUDE_DIRECTORIES(${GDAL_INCLUDE_DIR})
+INCLUDE_DIRECTORIES(${TIFF_INCLUDE_DIR})
+INCLUDE_DIRECTORIES(${GEOTIFF_INCLUDE_DIR})
+
+FILE(GLOB_RECURSE OSSIMPLUGIN_SRCS *.cpp)
+FILE(GLOB_RECURSE OSSIMPLUGIN_HEADERS *.h)
+
+# Adjust the install library path:
+if(OSSIM_INSTALL_PLUGINS_WITH_VERSION)
+   set(INSTALL_LIBRARY_DIR   "${INSTALL_LIBRARY_DIR}/ossim-${OSSIM_VERSION}/plugins")
+else(OSSIM_INSTALL_PLUGINS_WITH_VERSION)
+   set(INSTALL_LIBRARY_DIR   "${INSTALL_LIBRARY_DIR}/ossim/plugins")
+endif(OSSIM_INSTALL_PLUGINS_WITH_VERSION)
+
+OSSIM_LINK_LIBRARY(${LIB_NAME}
+                   COMPONENT_NAME ossim TYPE "${OSSIM_PLUGIN_LINK_TYPE}"
+		   LIBRARIES ${OSSIM_LIBRARIES} 
+                   HEADERS "${OSSIMPLUGIN_HEADERS}"
+		   SOURCE_FILES "${OSSIMPLUGIN_SRCS}"
+                   INSTALL_LIB)
diff --git a/ossim_plugins/contrib/makefile.vc b/ossim_plugins/contrib/makefile.vc
new file mode 100644
index 0000000..bb1727b
--- /dev/null
+++ b/ossim_plugins/contrib/makefile.vc
@@ -0,0 +1,58 @@
+###
+# $Id: makefile.vc 12864 2008-05-15 13:13:28Z dburken $
+#
+# Windows nmake make file.  This code should compile with the Microsoft .NET
+# compiler.
+# 
+# Currently for a typical build on windows you would do the following.
+# - nmake /f makefile
+#
+# NOTE:  If you make shared apps it's handy to copy the ossim.dll to the bin
+#        directory. 
+###
+
+!INCLUDE ..\nmake.opt
+PLUGIN_ROOT = ossim_contrib_plugin
+
+###
+# Note: EMBED_MANIFEST variable is set in nmake.opt so make sure it is included
+# before this test.
+###
+!if "$(EMBED_MANIFEST)" == "1"
+!include ..\makefile.inc
+OSSIM_VC_MANIFEST_EMBED_DLL=$(_VC_MANIFEST_EMBED_DLL)
+OSSIM_VC_MANIFEST_CLEAN=$(_VC_MANIFEST_CLEAN)
+!else
+OSSIM_VC_MANIFEST_EMBED_DLL=
+OSSIM_VC_MANIFEST_CLEAN=
+!endif
+
+###
+# Contrib includes and libs.
+# WINDOWS : use IntelCompiler7 prebuilt binaries (issues with Visual Studio)
+###
+INC	=	-I.. -I. $(INC)
+LINK	=	link
+
+OBJ = \
+ossimCFARFilter.obj \
+ossimComplexAbs.obj \
+ossimContribImageSourceFactory.obj \
+ossimContribPluginInit.obj \
+ossimSPOTNatural.obj
+
+default:	$(OBJ)
+	link /NOLOGO /SUBSYSTEM:WINDOWS /VERSION:$(VERSION_STRING) /DLL /OUT:"$(PLUGIN_ROOT).dll" /IMPLIB:"$(PLUGIN_ROOT).lib" $(OBJ) $(OSSIM_HOME)\lib\ossim.lib
+	$(OSSIM_VC_MANIFEST_EMBED_DLL)
+
+install:
+	$(CP) $(PLUGIN_ROOT).dll $(INSTALL_DIR)
+
+clean:
+	$(RM) *.obj
+	$(RM) $(OSSIM_PLUGIN_LIB_PATH)\$(PLUGIN_ROOT).*
+	$(OSSIM_VC_MANIFEST_CLEAN)
+
+!if "$(EMBED_MANIFEST)" == "1"
+!include ..\makefile.targ.inc
+!endif
diff --git a/ossim_plugins/contrib/ossimCFARFilter.cpp b/ossim_plugins/contrib/ossimCFARFilter.cpp
new file mode 100644
index 0000000..11e3ba4
--- /dev/null
+++ b/ossim_plugins/contrib/ossimCFARFilter.cpp
@@ -0,0 +1,933 @@
+// Copyright (C) 2006 Apogee Imaging International. 
+//
+//  OSSIM LGPL.  See top level LICENSE.txt in the ossim repository
+//  
+// Author: Tisham Dhar (tisham at apogee.com.au)
+// Description: Implementation of the CFAR Edge Detector as a series 
+// of convolutions and thresholding
+//
+//*************************************************************************
+// $Id: ossimCFARFilter.cpp 13026 2008-06-13 17:07:35Z sbortman $
+//
+#include <cstdlib>
+#include <ossim/base/ossimRefPtr.h>
+#include "ossimCFARFilter.h"
+#include <ossim/imaging/ossimU8ImageData.h>
+#include <ossim/base/ossimConstants.h>
+#include <ossim/base/ossimCommon.h>
+#include <ossim/base/ossimKeywordlist.h>
+#include <ossim/base/ossimKeywordNames.h>
+#include <ossim/base/ossimRefPtr.h>
+#include <ossim/base/ossimIrect.h>
+#include <ossim/imaging/ossimImageDataFactory.h>
+#include <ossim/base/ossimMatrixProperty.h>
+#include <ossim/base/ossimContainerProperty.h>
+#include <ossim/base/ossimNumericProperty.h>
+
+
+
+   //TODO: Implement the tile wide CFAR algorithm here
+   //Need to consider different thresholds across the
+   //Image for ScanSAR modes and WideSwath Modes
+
+   //CFAR Thresholds k-values determined by analysis of
+   //Image windows.
+
+	//Refer to ossim3x3ConvolutionFilter - for manual implementation of convolution
+	//Refer to ossimNCC_FFTW - for FFTW3 based optimized implementation of convolution
+	
+   //Step 1: Find Mean with a small window use convolution
+   //Step 2: Find Mean with a large window with a hole in the middle
+   //Step 3: Find Std.dev. of the large window - std. dev = sqrt(mean of squares - square of means)
+   //So square and convolve again to obtain mean
+   //Step 4: Find k-statistics using formula per pixel
+   //Step 5: Threshold k-statistics
+
+RTTI_DEF1(ossimCFARFilter, "ossimCFARFilter", ossimImageSourceFilter);
+
+ossimCFARFilter::ossimCFARFilter(ossimObject* owner)
+   :ossimImageSourceFilter(owner),
+    theTile(NULL),
+    theThreshold(2.0),
+    theNullPixValue(0),
+    theMinPixValue(0),
+    theMaxPixValue(0)
+{
+   theKernel[0][0] = 0.0625; theKernel[0][1] = 0.0625; theKernel[0][2] = 0.0625;
+   theKernel[0][3] = 0.0625; theKernel[0][4] = 0.0625;
+   theKernel[1][0] = 0.0625; theKernel[1][1] = 0.0; theKernel[1][2] = 0.0;
+   theKernel[1][3] = 0.0;    theKernel[1][4] = 0.0625;
+   theKernel[2][0] = 0.0625; theKernel[2][1] = 0.0; theKernel[2][2] = 0.0;
+   theKernel[2][3] = 0.0;theKernel[2][4] = 0.0625;
+   theKernel[3][0] = 0.0625; theKernel[3][1] = 0.0; theKernel[3][2] = 0.0;
+   theKernel[3][3] = 0.0;theKernel[3][4] = 0.0625;
+   theKernel[4][0] = 0.0625; theKernel[4][1] = 0.0625; theKernel[4][2] = 0.0625;
+   theKernel[4][3] = 0.0625;theKernel[4][4] = 0.0625;
+   
+}
+
+ossimCFARFilter::~ossimCFARFilter()
+{
+}
+
+ossimRefPtr<ossimImageData> ossimCFARFilter::getTile(const ossimIrect& tileRect,
+                                                     ossim_uint32 resLevel)
+{
+   if(!theInputConnection)
+   {
+      return theTile;
+   }
+
+   if(!isSourceEnabled())
+   {
+      return theInputConnection->getTile(tileRect, resLevel);
+   }
+
+   //---
+   // We have a 5x5 matrix so stretch the rect out to cover
+   // the required pixels.  We only need 2 pixels to the left
+   // and right of the center pixel.
+   //---
+   ossimIrect newRect(ossimIpt(tileRect.ul().x - 2,
+                               tileRect.ul().y - 2),
+                      ossimIpt(tileRect.lr().x + 2,
+                               tileRect.lr().y + 2));
+   
+   ossimRefPtr<ossimImageData> data = theInputConnection->getTile(newRect,
+                                                                  resLevel);
+
+   if(!data.valid() || !data->getBuf())
+   {
+      return data;
+   }
+
+    // First time through or after an initialize()...
+   if (!theTile.valid())
+   {
+      allocate();
+      if (!theTile.valid()) // Should never happen!
+      {
+         return data;
+      }
+   }
+
+   // First time through, after an initialize() or a setKernel()...
+   if (!theNullPixValue.size())
+   {
+      computeNullMinMax();
+      if (!theNullPixValue.size()) // Should never happen!
+      {
+         return data;
+      }
+   }
+
+   theTile->setImageRectangle(tileRect);
+   theTile->makeBlank();
+   
+   switch(data->getScalarType())
+   {
+      case OSSIM_UCHAR:
+      {
+         if(data->getDataObjectStatus() == OSSIM_FULL)
+         {
+            convolveFull(static_cast<ossim_uint8>(0), data, theTile);
+         }
+         else
+         {
+            convolvePartial(static_cast<ossim_uint8>(0), data, theTile);
+         }
+         break;
+      }
+      case OSSIM_FLOAT: 
+      case OSSIM_NORMALIZED_FLOAT:
+      {
+         if(data->getDataObjectStatus() == OSSIM_FULL)
+         {
+            convolveFull(static_cast<float>(0), data, theTile);
+         }
+         else
+         {
+            convolvePartial(static_cast<float>(0), data, theTile);
+         }
+         break;
+      }
+      case OSSIM_USHORT16:
+      case OSSIM_USHORT11:
+      {
+         if(data->getDataObjectStatus() == OSSIM_FULL)
+         {
+            convolveFull(static_cast<ossim_uint16>(0), data, theTile);
+         }
+         else
+         {
+            convolvePartial(static_cast<ossim_uint16>(0), data, theTile);
+         }
+         break;
+      }
+      case OSSIM_SSHORT16:
+      {
+         if(data->getDataObjectStatus() == OSSIM_FULL)
+         {
+            convolveFull(static_cast<ossim_sint16>(0), data, theTile);
+         }
+         else
+         {
+            convolvePartial(static_cast<ossim_sint16>(0), data, theTile);
+         }
+         break;
+      }
+      case OSSIM_DOUBLE:
+      case OSSIM_NORMALIZED_DOUBLE:
+      {
+         if(data->getDataObjectStatus() == OSSIM_FULL)
+         {
+            convolveFull(static_cast<double>(0), data, theTile);
+      }
+      else
+      {
+         convolvePartial(static_cast<double>(0), data, theTile);
+      }
+         break;
+      }
+      default:
+      {
+         ossimNotify(ossimNotifyLevel_WARN)
+            << "ossimCFARFilter::getTile WARNING:\n"
+            << "Scalar type = " << theTile->getScalarType()
+            << " Not supported by ossimCFARFilter" << endl;
+         break;
+      }
+   }
+   theTile->validate();
+   
+   return theTile;
+}
+
+
+template<class T> void ossimCFARFilter::convolvePartial(
+   T,
+   ossimRefPtr<ossimImageData> inputData,
+   ossimRefPtr<ossimImageData> outputData)
+{
+   // let's set up some temporary variables so we don't
+   // have to call the functions in loops.  Iknow that compilers
+   // typically optimize this out but if we are in debug mode 
+   // with no optimization it will still run fast
+   //
+   double sum = 0.0,sqrsum = 0.0, variance = 0.0;
+   ossim_int32 inputW          = (ossim_int32)inputData->getWidth();
+   ossim_int32 outputW         = (ossim_int32)outputData->getWidth();
+   ossim_int32 outputH         = (ossim_int32)outputData->getHeight();
+   ossim_int32 numberOfBands   = (ossim_int32)inputData->getNumberOfBands();
+   ossimIpt outputOrigin  = outputData->getOrigin();
+   ossimIpt inputOrigin   = inputData->getOrigin();
+   
+   ossim_int32 startInputOffset = std::abs(outputOrigin.y - inputOrigin.y)*
+      inputW + std::abs(outputOrigin.x - inputOrigin.x);
+      
+   ossim_int32 ulKernelStart    = -(2*inputW) - 2;
+   ossim_int32 ul1KernelStart    = -inputW - 1;
+   ossim_int32 leftKernelStart  = -2;
+   ossim_int32 ll1KernelStart    = inputW  - 1;
+   ossim_int32 llKernelStart    = (2*inputW)  - 2;
+   
+   //populate kernel offset indices
+   
+   ossim_int32 KernelStart[BOXSIZE];
+   T* KernelStartBuf[BOXSIZE];
+   
+   for(ossim_uint16 i=0;i<BOXSIZE;i++)
+   {
+      int offset = i-(BOXSIZE/2);
+   	KernelStart[i] = offset*inputW + offset;
+   	KernelStartBuf[i] = NULL;
+   }
+   
+   
+   
+   T* ulKernelStartBuf   = NULL;
+   T* ul1KernelStartBuf   = NULL;
+   T* leftKernelStartBuf = NULL;
+   T* ll1KernelStartBuf   = NULL;   
+   T* llKernelStartBuf   = NULL;
+   
+   for(ossim_int32 band = 0; band < numberOfBands; ++band)
+   {
+      T* inputBuf  = static_cast<T*>(inputData->getBuf(band))+startInputOffset;
+      T* outputBuf = static_cast<T*>(outputData->getBuf(band));
+      T maxPix     = static_cast<T>(getMaxPixelValue(band));
+      T minPix     = static_cast<T>(getMinPixelValue(band));      
+      T nullPix    = static_cast<T>(inputData->getNullPix(band));
+      T oNullPix   = static_cast<T>(getNullPixelValue(band));
+      
+      if(inputBuf&&outputBuf)
+      {
+         for(ossim_int32 row = 0; row < outputW; ++row)
+         {
+            ossim_int32 rowOffset    = inputW*row;
+            ulKernelStartBuf   = inputBuf + (rowOffset + ulKernelStart);
+            ul1KernelStartBuf   = inputBuf + (rowOffset + ul1KernelStart);
+            leftKernelStartBuf = inputBuf + (rowOffset + leftKernelStart);
+            ll1KernelStartBuf   = inputBuf + (rowOffset + ll1KernelStart);
+            llKernelStartBuf   = inputBuf + (rowOffset + llKernelStart);
+            
+            for(ossim_uint16 i=0;i<BOXSIZE;i++)
+            {
+            	KernelStartBuf[i] = inputBuf + (rowOffset + KernelStart[i]);
+            }
+                        
+            for(ossim_int32 col = 0; col < outputH; ++col)
+            {
+					//TODO: Need to have an efficient means of detecting nulls
+					
+               if((ulKernelStartBuf[0]   != nullPix)&&
+                  (ulKernelStartBuf[1]   != nullPix)&&
+                  (ulKernelStartBuf[2]   != nullPix)&&
+                  (leftKernelStartBuf[0] != nullPix)&&
+                  (leftKernelStartBuf[1] != nullPix)&&
+                  (leftKernelStartBuf[2] != nullPix)&&
+                  (llKernelStartBuf[0]   != nullPix)&&
+                  (llKernelStartBuf[1]   != nullPix)&&
+                  (llKernelStartBuf[2]   != nullPix))
+               {
+               	//calculate mean
+               	sum = 0.0;
+               	sqrsum = 0.0;
+               	
+               	
+            		for(ossim_uint32 r=0; r<5; ++r)
+            			sum += theKernel[0][r]*(double)ulKernelStartBuf[r];
+            		for(ossim_uint32 r=0; r<5; ++r)
+            			sum += theKernel[1][r]*(double)ul1KernelStartBuf[r];
+            		for(ossim_uint32 r=0; r<5; ++r)
+            			sum += theKernel[2][r]*(double)leftKernelStartBuf[r];
+            		for(ossim_uint32 r=0; r<5; ++r)
+            			sum += theKernel[3][r]*(double)ll1KernelStartBuf[r];
+	            	for(ossim_uint32 r=0; r<5; ++r)
+   	         		sum += theKernel[4][r]*(double)llKernelStartBuf[r];
+   	         	
+   	         	/*
+   	         	for(ossim_uint16 i=0;i<BOXSIZE;i++)
+	   	         {
+	   	         	for(ossim_uint32 r=0; r<5; ++r)
+	   	         	{
+								sum += theKernel[i][r]*(double)KernelStartBuf[i][r];
+								sqrsum += theKernel[i][r]*(double)KernelStartBuf[i][r]
+         	   			*(double)KernelStartBuf[i][r];
+         	   		}
+   	      	   }
+   	      	   */  	         	
+   	         	//calculate mean of squares
+   	         	
+   	         	for(ossim_uint32 r=0; r<5; ++r)
+            			sqrsum += theKernel[0][r]*(double)ulKernelStartBuf[r]
+            			*(double)ulKernelStartBuf[r];
+            		for(ossim_uint32 r=0; r<5; ++r)
+            			sqrsum += theKernel[1][r]*(double)ul1KernelStartBuf[r]
+            			*(double)ul1KernelStartBuf[r];
+            		for(ossim_uint32 r=0; r<5; ++r)
+            			sqrsum += theKernel[2][r]*(double)leftKernelStartBuf[r]
+            			*(double)leftKernelStartBuf[r];
+            		for(ossim_uint32 r=0; r<5; ++r)
+            			sqrsum += theKernel[3][r]*(double)ll1KernelStartBuf[r]
+            			*(double)ll1KernelStartBuf[r];
+            		for(ossim_uint32 r=0; r<5; ++r)
+            			sqrsum += theKernel[4][r]*(double)llKernelStartBuf[r]
+            			*(double)llKernelStartBuf[r];
+            		
+						//calculate variance
+						variance = sqrsum - (sum*sum);
+					
+						
+						//calculate k-value
+						sum = ((double)leftKernelStartBuf[2] - sum)/sqrt(variance);;
+					
+						//Threshold k-value
+						if(sum < theThreshold)
+							sum = minPix;
+						else
+							sum = maxPix;
+						
+                  /*
+                  sum = theKernel[0][0]*(double)ulKernelStartBuf[0] +
+                        theKernel[0][1]*(double)ulKernelStartBuf[1] +
+                        theKernel[0][2]*(double)ulKernelStartBuf[2] +
+                        theKernel[1][0]*(double)leftKernelStartBuf[0] +
+                        theKernel[1][1]*(double)leftKernelStartBuf[1] +
+                        theKernel[1][2]*(double)leftKernelStartBuf[2] +
+                        theKernel[2][0]*(double)llKernelStartBuf[0] +
+                        theKernel[2][1]*(double)llKernelStartBuf[1] +
+                        theKernel[2][2]*(double)llKernelStartBuf[2];
+                  */
+                  if(sum > maxPix)
+                  {
+                     *outputBuf = maxPix;
+                  }
+                  else if(sum < minPix)
+                  {
+                     *outputBuf = minPix;
+                  }
+                  else
+                  {
+                     *outputBuf = static_cast<T>(sum);
+                  }
+               }
+               else {
+                  *outputBuf = oNullPix;
+               }
+               //
+               // Need to implement the convolution here
+               //
+               
+               ++ulKernelStartBuf;
+               ++ul1KernelStartBuf;
+               ++leftKernelStartBuf;
+               ++ll1KernelStartBuf;
+               ++llKernelStartBuf;
+               ++outputBuf;
+            }
+         }
+      }
+   }
+}
+
+template<class T> void ossimCFARFilter::convolveFull(
+   T,
+   ossimRefPtr<ossimImageData> inputData,
+   ossimRefPtr<ossimImageData> outputData)
+{
+   // let's set up some temporary variables so we don't
+   // have to call the functions in loops.  Iknow that compilers
+   // typically optimize this out but if we are in debug mode 
+   // with no optimization it will still run fast
+   //
+   double sum = 0.0,sqrsum = 0.0,variance = 0.0;
+   ossim_int32 inputW = static_cast<ossim_int32>(inputData->getWidth());
+   ossim_uint32 outputW       = outputData->getWidth();
+   ossim_uint32 outputH       = outputData->getHeight();
+   ossim_uint32 numberOfBands = inputData->getNumberOfBands();
+   ossimIpt outputOrigin = outputData->getOrigin();
+   ossimIpt inputOrigin  = inputData->getOrigin();
+   
+   ossim_int32 startInputOffset = std::abs(outputOrigin.y - inputOrigin.y)*
+      inputW + std::abs(outputOrigin.x - inputOrigin.x);
+   
+   ossim_int32 ulKernelStart    = -(2*inputW) - 2;
+   ossim_int32 ul1KernelStart    = -inputW - 1;
+   ossim_int32 leftKernelStart  = -2;
+   ossim_int32 ll1KernelStart    = inputW  - 1;
+   ossim_int32 llKernelStart    = (2*inputW)  - 2;
+   
+   //populate kernel offset indices
+   
+   ossim_int32 KernelStart[BOXSIZE];
+   T* KernelStartBuf[BOXSIZE];
+   
+   for(ossim_uint16 i=0;i<BOXSIZE;i++)
+   {
+   	int offset = i-(BOXSIZE/2);
+   	KernelStart[i] = offset*inputW + offset;
+   	KernelStartBuf[i] = NULL;
+   }
+   
+   T* ulKernelStartBuf   = NULL;
+   T* ul1KernelStartBuf   = NULL;
+   T* leftKernelStartBuf = NULL;
+   T* ll1KernelStartBuf   = NULL;   
+   T* llKernelStartBuf   = NULL;
+   
+   for(ossim_uint32 band = 0; band < numberOfBands; ++band)
+   {
+      T* inputBuf  = static_cast<T*>(inputData->getBuf(band))+startInputOffset;
+      T* outputBuf = static_cast<T*>(outputData->getBuf(band));
+      T maxPix     = static_cast<T>(getMaxPixelValue(band));
+      T minPix     = static_cast<T>(getMinPixelValue(band));
+      
+      if(inputBuf&&outputBuf)
+      {
+         for(ossim_uint32 row = 0; row < outputW; ++row)
+         {
+            ossim_int32 rowOffset    = inputW*row;
+            ulKernelStartBuf   = inputBuf + (rowOffset + ulKernelStart);
+            ul1KernelStartBuf   = inputBuf + (rowOffset + ul1KernelStart);
+            leftKernelStartBuf = inputBuf + (rowOffset + leftKernelStart);
+            ll1KernelStartBuf   = inputBuf + (rowOffset + ll1KernelStart);
+            llKernelStartBuf   = inputBuf + (rowOffset + llKernelStart);
+            
+            for(ossim_uint16 i=0;i<BOXSIZE;i++)
+            {
+            	KernelStartBuf[i] = inputBuf + (rowOffset + KernelStart[i]);
+            }
+            
+            for(ossim_uint32 col = 0; col < outputH; ++col)
+            {
+            	//calculate mean
+            	sum = 0.0;
+            	sqrsum = 0.0;
+            	
+            	for(ossim_uint32 r=0; r<5; ++r)
+            		sum += theKernel[0][r]*(double)ulKernelStartBuf[r];
+            	for(ossim_uint32 r=0; r<5; ++r)
+            		sum += theKernel[1][r]*(double)ul1KernelStartBuf[r];
+            	for(ossim_uint32 r=0; r<5; ++r)
+            		sum += theKernel[2][r]*(double)leftKernelStartBuf[r];
+            	for(ossim_uint32 r=0; r<5; ++r)
+            		sum += theKernel[3][r]*(double)ll1KernelStartBuf[r];
+            	for(ossim_uint32 r=0; r<5; ++r)
+            		sum += theKernel[4][r]*(double)llKernelStartBuf[r];
+            	/*
+            	for(ossim_uint16 i=0;i<BOXSIZE;i++)
+	   	      {
+	   	         for(ossim_uint32 r=0; r<5; ++r)
+	   	         {
+							sum += theKernel[i][r]*(double)KernelStartBuf[i][r];
+							sqrsum += theKernel[i][r]*(double)KernelStartBuf[i][r]
+         	   		*(double)KernelStartBuf[i][r];
+         	   	}
+   	      	}
+   	      	*/
+            	
+            	//calculate mean of squares
+            	
+            	for(ossim_uint32 r=0; r<5; ++r)
+            		sqrsum += theKernel[0][r]*(double)ulKernelStartBuf[r]
+            		*(double)ulKernelStartBuf[r];
+            	for(ossim_uint32 r=0; r<5; ++r)
+            		sqrsum += theKernel[1][r]*(double)ul1KernelStartBuf[r]
+            		*(double)ul1KernelStartBuf[r];
+            	for(ossim_uint32 r=0; r<5; ++r)
+            		sqrsum += theKernel[2][r]*(double)leftKernelStartBuf[r]
+            		*(double)leftKernelStartBuf[r];
+            	for(ossim_uint32 r=0; r<5; ++r)
+            		sqrsum += theKernel[3][r]*(double)ll1KernelStartBuf[r]
+            		*(double)ll1KernelStartBuf[r];
+            	for(ossim_uint32 r=0; r<5; ++r)
+            		sqrsum += theKernel[4][r]*(double)llKernelStartBuf[r]
+            		*(double)llKernelStartBuf[r];
+					
+					//calculate variance
+					variance = sqrsum - (sum*sum);
+					
+					//calculate k-value
+					sum = ((double)leftKernelStartBuf[2] - sum)/sqrt(variance);
+					
+					//Threshold k-value
+					if(sum < theThreshold)
+						sum = minPix;
+					else
+						sum = maxPix;
+					
+					/*            
+               sum = theKernel[0][0]*(double)ulKernelStartBuf[0] +
+                     theKernel[0][1]*(double)ulKernelStartBuf[1] +
+                     theKernel[0][2]*(double)ulKernelStartBuf[2] +
+                     theKernel[1][0]*(double)leftKernelStartBuf[0] +
+                     theKernel[1][1]*(double)leftKernelStartBuf[1] +
+                     theKernel[1][2]*(double)leftKernelStartBuf[2] +
+                     theKernel[2][0]*(double)llKernelStartBuf[0] +
+                     theKernel[2][1]*(double)llKernelStartBuf[1] +
+                     theKernel[2][2]*(double)llKernelStartBuf[2];
+               */
+               if(sum > maxPix)
+               {
+                  *outputBuf = maxPix;
+               }
+               else if(sum < minPix)
+               {
+                  *outputBuf = minPix;
+               }
+               else
+               {
+                  *outputBuf = static_cast<T>(sum);
+               }
+               //
+               // Need to implement the convolution here.
+               //
+
+               
+               ++ulKernelStartBuf;
+               ++ul1KernelStartBuf;
+               ++leftKernelStartBuf;
+               ++ll1KernelStartBuf;
+               ++llKernelStartBuf;
+               ++outputBuf;
+            }
+         }
+      }
+   }
+}
+
+void ossimCFARFilter::initialize()
+{
+   //---
+   // NOTE:
+   // Since initialize get called often sequentially we will wipe things slick
+   // but not reallocate to avoid multiple delete/allocates.
+   //
+   // On the first getTile call things will be reallocated/computed.
+   //---
+   theTile = NULL;
+   clearNullMinMax();
+}
+
+void ossimCFARFilter::allocate()
+{   
+   if(theInputConnection)
+   {
+      ossimImageDataFactory* idf = ossimImageDataFactory::instance();
+      
+      theTile = idf->create(this,
+                            this);
+      
+      theTile->initialize();
+   }
+}
+
+void ossimCFARFilter::setProperty(ossimRefPtr<ossimProperty> property)
+{
+   if(!property) return;
+   ossimString name = property->getName();
+
+	if(name == "threshold")
+	{
+		theThreshold = property->valueToString().toDouble();
+	}
+   else if(name == "Kernel")
+   {
+      ossimMatrixProperty* matrixProperty = PTR_CAST(ossimMatrixProperty,
+                                                     property.get());
+      if(matrixProperty)
+      {
+      	for(ossim_int32 r = 0; r < 5; r++)
+   		{
+      		for(ossim_int32 c = 0; c < 5; c++)
+      		{
+      			theKernel[r][c] = (*matrixProperty)(r,c);
+      		}
+   		}
+   		/*
+         theKernel[0][0] = (*matrixProperty)(0,0);
+         theKernel[1][0] = (*matrixProperty)(1,0);
+         theKernel[2][0] = (*matrixProperty)(2,0);
+         theKernel[0][1] = (*matrixProperty)(0,1);
+         theKernel[1][1] = (*matrixProperty)(1,1);
+         theKernel[2][1] = (*matrixProperty)(2,1);
+         theKernel[0][2] = (*matrixProperty)(0,2);
+         theKernel[1][2] = (*matrixProperty)(1,2);
+         theKernel[2][2] = (*matrixProperty)(2,2);
+			*/
+      }
+      else
+      {
+         ossimImageSourceFilter::setProperty(property);
+      }
+   }
+   else
+   {
+      ossimImageSourceFilter::setProperty(property);
+   }
+}
+
+ossimRefPtr<ossimProperty> ossimCFARFilter::getProperty(const ossimString& name)const
+{
+   if(name == "Kernel")
+   {
+      ossimMatrixProperty* property = new ossimMatrixProperty(name);
+      property->resize(5,5);
+      for(ossim_int32 r = 0; r < 5; r++)
+   	{
+      	for(ossim_int32 c = 0; c < 5; c++)
+      	{
+      		(*property)(r,c) = theKernel[r][c];
+      	}
+   	}
+   	/*
+      (*property)(0,0) = theKernel[0][0];
+      (*property)(1,0) = theKernel[1][0];
+      (*property)(2,0) = theKernel[2][0];
+      (*property)(3,0) = theKernel[3][0];
+      (*property)(4,0) = theKernel[4][0];
+      (*property)(0,1) = theKernel[0][1];
+      (*property)(1,1) = theKernel[1][1];
+      (*property)(2,1) = theKernel[2][1];
+      (*property)(3,1) = theKernel[3][1];
+      (*property)(4,1) = theKernel[4][1];
+      (*property)(0,2) = theKernel[0][2];
+      (*property)(1,2) = theKernel[1][2];
+      (*property)(2,2) = theKernel[2][2];
+      (*property)(3,2) = theKernel[3][2];
+      (*property)(4,2) = theKernel[4][2];
+      (*property)(0,3) = theKernel[0][3];
+      (*property)(1,3) = theKernel[1][3];
+      (*property)(2,3) = theKernel[2][3];
+      (*property)(3,3) = theKernel[3][3];
+      (*property)(4,3) = theKernel[4][3];
+      (*property)(0,4) = theKernel[0][4];
+      (*property)(1,4) = theKernel[1][4];
+      (*property)(2,4) = theKernel[2][4];
+      (*property)(3,4) = theKernel[3][4];
+      (*property)(4,4) = theKernel[4][4];
+      */
+      property->setCacheRefreshBit();
+
+      return property;
+   }
+   if(name == "threshold")
+   {
+   	 ossimNumericProperty* numeric = new ossimNumericProperty(name,
+                                                               ossimString::toString(getThreshold()),
+                                                               -10.0, 10.0);
+      numeric->setNumericType(ossimNumericProperty::ossimNumericPropertyType_FLOAT64);
+      numeric->setCacheRefreshBit();
+      return numeric;
+   }
+   return ossimImageSourceFilter::getProperty(name);
+}
+
+void ossimCFARFilter::getPropertyNames(std::vector<ossimString>& propertyNames)const
+{
+   ossimImageSourceFilter::getPropertyNames(propertyNames);
+   propertyNames.push_back("Kernel");
+   propertyNames.push_back("threshold");
+}
+
+
+/***************************************************************
+* This method saves the filter state between property box edits
+***************************************************************/
+bool ossimCFARFilter::saveState(ossimKeywordlist& kwl,
+                                          const char* prefix)const
+{   
+   kwl.add(prefix,
+           "rows",
+           5,
+           true);
+   
+   kwl.add(prefix,
+           "cols",
+           5,
+           true);
+   
+   for(ossim_int32 row = 0; row < 5; ++row)
+   {
+      for(ossim_int32 col =0; col < 5; ++col)
+      {
+         ossimString newPrefix = "m" +
+                                 ossimString::toString(row+1) + "_" +
+                                 ossimString::toString(col+1);
+         kwl.add(prefix,
+                 newPrefix,
+                 theKernel[row][col],
+                 true);          
+      }
+   }   
+   
+	kwl.add(prefix,
+           "threshold",
+           theThreshold,
+           true);
+   
+   return ossimImageSourceFilter::saveState(kwl, prefix);
+}
+
+/***************************************************************
+* This method loads the filter state between property box edits
+***************************************************************/
+bool ossimCFARFilter::loadState(const ossimKeywordlist& kwl,
+                                          const char* prefix)
+{
+   ossimString newPrefix = prefix;
+   newPrefix += ossimString("m");
+   
+   for(ossim_int32 r = 0; r < 5; r++)
+   {
+      for(ossim_int32 c = 0; c < 5; c++)
+      {
+         theKernel[r][c] = 0.0;
+         
+         ossimString value = ossimString::toString(r+1);
+         value += "_";
+         value += ossimString::toString(c+1);
+         
+         const char* v = kwl.find(newPrefix.c_str(),
+                                  value.c_str());
+         if(v)
+         {
+            theKernel[r][c] = ossimString(v).toDouble();
+         }
+      }
+   }
+   const char* threshold = kwl.find(prefix, "threshold");
+   if(threshold)
+   {
+      theThreshold = ossimString(threshold).toDouble();
+   }
+   
+   return ossimImageSourceFilter::loadState(kwl, prefix);
+}
+
+void ossimCFARFilter::getKernel(double kernel[5][5])
+{
+
+   for(ossim_int32 r = 0; r < 5; r++)
+   {
+      for(ossim_int32 c = 0; c < 5; c++)
+      {
+      	kernel[r][c] = theKernel[r][c];
+      }
+   }
+   /*
+   kernel[0][0] = theKernel[0][0];
+   kernel[0][1] = theKernel[0][1];
+   kernel[0][2] = theKernel[0][2];
+   kernel[1][0] = theKernel[1][0];
+   kernel[1][1] = theKernel[1][1];
+   kernel[1][2] = theKernel[1][2];
+   kernel[2][0] = theKernel[2][0];
+   kernel[2][1] = theKernel[2][1];
+   kernel[2][2] = theKernel[2][2];
+   */
+}
+
+void ossimCFARFilter::setKernel(double kernel[5][5])
+{
+	for(ossim_int32 r = 0; r < 5; r++)
+   {
+      for(ossim_int32 c = 0; c < 5; c++)
+      {
+      	theKernel[r][c] = kernel[r][c];
+      }
+   }
+   /*
+   theKernel[0][0] = kernel[0][0];
+   theKernel[0][1] = kernel[0][1];
+   theKernel[0][2] = kernel[0][2];
+   theKernel[1][0] = kernel[1][0];
+   theKernel[1][1] = kernel[1][1];
+   theKernel[1][2] = kernel[1][2];
+   theKernel[2][0] = kernel[2][0];
+   theKernel[2][1] = kernel[2][1];
+   theKernel[2][2] = kernel[2][2];
+	*/
+   // Will be recomputed first getTile call.
+   clearNullMinMax();
+}
+
+ossim_float64 ossimCFARFilter::getThreshold()const
+{
+	return theThreshold;
+}
+
+
+void ossimCFARFilter::setThreshold(ossim_float64 threshold)
+{
+	theThreshold = threshold;
+}
+
+double ossimCFARFilter::getNullPixelValue(ossim_uint32 band)const
+{
+   if( isSourceEnabled() && (band < theNullPixValue.size()) )
+   {
+      return theNullPixValue[band];
+   }
+
+   return ossim::defaultNull(getOutputScalarType());
+}
+
+double ossimCFARFilter::getMinPixelValue(ossim_uint32 band)const
+{
+   if( isSourceEnabled() && (band < theMinPixValue.size()) )
+   {
+      return theMinPixValue[band];
+   }
+   
+   return ossimImageSource::getMinPixelValue(band);
+}
+
+double ossimCFARFilter::getMaxPixelValue(ossim_uint32 band)const
+{
+   if( isSourceEnabled() && (band < theMaxPixValue.size()) )
+   {
+      return theMaxPixValue[band];
+   }
+
+   return ossimImageSource::getMaxPixelValue(band);
+}
+
+void ossimCFARFilter::clearNullMinMax()
+{
+   theNullPixValue.clear();
+   theMinPixValue.clear();
+   theMaxPixValue.clear();
+}
+
+void ossimCFARFilter::computeNullMinMax()
+{
+   const ossim_uint32 BANDS = getNumberOfOutputBands();
+
+   theNullPixValue.resize(BANDS);
+   theMinPixValue.resize(BANDS);
+   theMaxPixValue.resize(BANDS);
+
+   ossim_float64 defaultNull = ossim::defaultNull(getOutputScalarType());
+   ossim_float64 defaultMin = ossim::defaultMin(getOutputScalarType());
+   ossim_float64 defaultMax = ossim::defaultMax(getOutputScalarType());
+  
+   for (ossim_uint32 band = 0; band < BANDS; ++band)
+   {
+      if(theInputConnection)
+      {
+         ossim_float64 inputNull = theInputConnection->getNullPixelValue(band);
+         ossim_float64 inputMin  = theInputConnection->getMinPixelValue(band);
+         ossim_float64 inputMax  = theInputConnection->getMaxPixelValue(band);
+         ossim_float64 tempMin   = 0.0;
+         ossim_float64 tempMax   = 0.0;
+         ossim_float64 k         = 0.0;
+         for(int i=0;i<5;++i)
+         {
+            for(int j=0;j<5;++j)
+            {
+               k=theKernel[i][j];
+               tempMin += (k<0.0) ? k*inputMax : k*inputMin;
+               tempMax += (k>0.0) ? k*inputMax : k*inputMin;
+            }
+         }
+
+         if((inputNull < getMinPixelValue(band)) ||
+            (inputNull > getMaxPixelValue(band)))
+         {
+            theNullPixValue[band] = inputNull;
+         }
+         else
+         {
+            theNullPixValue[band] = defaultNull;
+         }
+
+         if((tempMin >= defaultMin) && (tempMin <= defaultMax))
+         {
+            theMinPixValue[band] = tempMin;
+         }
+         else
+         {
+            theMinPixValue[band] = defaultMin;
+         }
+
+         if((tempMax >= defaultMin) && (tempMax <= defaultMax))
+         {
+            theMaxPixValue[band] = tempMax;
+         }
+         else
+         {
+            theMaxPixValue[band] = defaultMax;
+         }
+         
+      }
+      else // No input connection...
+      {
+         theNullPixValue[band] = defaultNull;
+         theMinPixValue[band]  = defaultMin;
+         theMaxPixValue[band]  = defaultMax;
+      }
+      
+   } // End of band loop.
+}
diff --git a/ossim_plugins/contrib/ossimCFARFilter.h b/ossim_plugins/contrib/ossimCFARFilter.h
new file mode 100644
index 0000000..9f36da6
--- /dev/null
+++ b/ossim_plugins/contrib/ossimCFARFilter.h
@@ -0,0 +1,95 @@
+#ifndef ossimCFARFilter_HEADER
+#define ossimCFARFilter_HEADER
+#include <ossim/plugin/ossimSharedObjectBridge.h>
+#include <ossim/base/ossimString.h>
+#include <ossim/imaging/ossimImageSourceFilter.h>
+
+#define BOXSIZE 5
+
+class ossimCFARFilter : public ossimImageSourceFilter
+{
+public:
+   ossimCFARFilter(ossimObject* owner=NULL);
+   virtual ~ossimCFARFilter();
+
+   virtual ossimString getShortName()const{return ossimString("CFAR detector");}
+   virtual ossimString getLongName()const{return ossimString("Constant False Alarm Rate Edge Detector");}
+
+   virtual void getKernel(double kernel[5][5]);
+   
+   virtual void setKernel(double kernel[5][5]);
+   
+   virtual ossim_float64 getThreshold() const;
+   
+   virtual void setThreshold(ossim_float64 threshold);
+
+   virtual ossimRefPtr<ossimImageData> getTile(const ossimIrect& tileRect,
+                                               ossim_uint32 resLevel=0);
+
+   virtual void initialize();
+
+   virtual double getNullPixelValue(ossim_uint32 band=0) const;
+   virtual double getMinPixelValue(ossim_uint32 band=0)  const;
+   virtual double getMaxPixelValue(ossim_uint32 band=0)  const;
+
+   virtual void setProperty(ossimRefPtr<ossimProperty> property);
+   virtual ossimRefPtr<ossimProperty> getProperty(const ossimString& name)const;
+   virtual void getPropertyNames(std::vector<ossimString>& propertyNames)const;
+
+
+   virtual bool loadState(const ossimKeywordlist& kwl,
+                          const char* prefix = 0);
+   
+   virtual bool saveState(ossimKeywordlist& kwl,
+                          const char* prefix = 0)const;
+   
+protected:
+
+   /**
+    * Allocates theTile.
+    */
+   void allocate();
+
+   /**
+    * Clears data members theNullPixValue, theMinPixValue, and
+    * theMaxPixValue.
+    */
+   void clearNullMinMax();
+
+   /**
+    * Computes null, min, and max considering input connection and theKernel.
+    */
+   void computeNullMinMax();
+   
+   ossimRefPtr<ossimImageData> theTile;
+   double theKernel[5][5];
+   ossim_float64 theThreshold;
+
+   vector<double> theNullPixValue;
+   vector<double> theMinPixValue;
+   vector<double> theMaxPixValue;   
+   
+   /*!
+    * Convolve full means that the input data is full and has
+    * no null data.  We don't have to compare for nulls here
+    */
+   template<class T>
+   void convolveFull(T,
+                     ossimRefPtr<ossimImageData> inputData,
+                     ossimRefPtr<ossimImageData> outputData);
+   
+   /*!
+    * Convolve partial means that the input data is has some
+    * null data.  We will have to compare nulls
+    */
+   template<class T>
+   void convolvePartial(T,
+                        ossimRefPtr<ossimImageData> inputData,
+                        ossimRefPtr<ossimImageData> outputData);
+                       
+
+
+TYPE_DATA
+};
+
+#endif
diff --git a/ossim_plugins/contrib/ossimComplexAbs.cpp b/ossim_plugins/contrib/ossimComplexAbs.cpp
new file mode 100644
index 0000000..2b2e97f
--- /dev/null
+++ b/ossim_plugins/contrib/ossimComplexAbs.cpp
@@ -0,0 +1,283 @@
+// Copyright (C) 2006 Apogee Imaging International
+//
+// OSSIM is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License 
+// as published by the Free Software Foundation.
+//
+// This software is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
+//
+// You should have received a copy of the GNU General Public License
+// along with this software. If not, write to the Free Software 
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-
+// 1307, USA.
+//
+// See the GPL in the COPYING.GPL file for more details.
+//
+// Author: Tisham Dhar (tisham at apogee.com.au)
+// Description: Converts complex data is ossim format to absolute values
+//
+//*************************************************************************
+// $Id: ossimComplexAbs.cpp 10108 2006-12-14 16:15:30Z gpotts $
+#include <ossim/base/ossimRefPtr.h>
+#include "ossimComplexAbs.h"
+#include <ossim/imaging/ossimU8ImageData.h>
+#include <ossim/base/ossimConstants.h>
+#include <ossim/base/ossimCommon.h>
+#include <ossim/base/ossimKeywordlist.h>
+#include <ossim/base/ossimKeywordNames.h>
+#include <ossim/imaging/ossimImageDataFactory.h>
+#include <ossim/imaging/ossimImageSourceFactoryBase.h>
+#include <ossim/imaging/ossimImageSourceFactoryRegistry.h>
+#include <ossim/base/ossimRefPtr.h>
+
+/*************************************************************************
+* Absolute value = sqrt(real^2 + imag^2)
+* The number of input bands has to be even
+* The number of output bands 1/2 the input bands
+* output data type == double/float64 (input data type can be double,float or int)
+**************************************************************************/
+
+RTTI_DEF1(ossimComplexAbs, "ossimComplexAbs", ossimImageSourceFilter)
+
+ossimComplexAbs::ossimComplexAbs(ossimObject* owner)
+   :ossimImageSourceFilter(owner),
+    theTile(NULL),
+	 theOutputBandCount(1)
+{
+}
+
+ossimComplexAbs::ossimComplexAbs(ossimImageSource* inputSource,
+                                           unsigned int outputbandcount)
+   : ossimImageSourceFilter(NULL, inputSource),
+     theTile(NULL),
+     theOutputBandCount(outputbandcount)     
+{
+}
+
+ossimComplexAbs::ossimComplexAbs(ossimObject* owner,
+                                           ossimImageSource* inputSource,
+                                           unsigned int outputbandcount)
+   : ossimImageSourceFilter(owner, inputSource),
+     theTile(NULL),
+     theOutputBandCount(outputbandcount)
+{
+}
+
+ossimComplexAbs::~ossimComplexAbs()
+{
+}
+
+ossimRefPtr<ossimImageData> ossimComplexAbs::getTile(const ossimIrect& tileRect,
+                                                                ossim_uint32 resLevel)
+{
+   if(!theInputConnection)
+   {
+      return theTile;
+   }
+
+   if(!isSourceEnabled())
+   {
+      return theInputConnection->getTile(tileRect, resLevel);
+   }
+   ossimRefPtr<ossimImageData> data = theInputConnection->getTile(tileRect,
+                                                                  resLevel);
+	
+   // First time through or after an initialize()...
+   if (!theTile.valid())
+   {
+      allocate();
+      if (!theTile.valid()) // Should never happen!
+      {
+         return data;
+      }
+   }
+	
+   theTile->setImageRectangle(tileRect);
+   theTile->makeBlank();
+   if(!data.valid() || !data->getBuf())
+   {
+      return theTile.get();
+   }
+   
+   switch(data->getScalarType())
+   {
+      case OSSIM_UCHAR:
+      {
+         runAbsCalc(static_cast<ossim_uint8>(0), data, theTile);
+         break;
+      }
+      case OSSIM_FLOAT: 
+      case OSSIM_NORMALIZED_FLOAT:
+      {
+         runAbsCalc(static_cast<float>(0), data, theTile);
+         break;
+      }
+      case OSSIM_USHORT16:
+      case OSSIM_USHORT11:
+      {
+         runAbsCalc(static_cast<ossim_uint16>(0), data, theTile);
+         break;
+      }
+      case OSSIM_SSHORT16:
+      {
+         runAbsCalc(static_cast<ossim_sint16>(0), data, theTile);
+         break;
+      }
+      case OSSIM_DOUBLE:
+      case OSSIM_NORMALIZED_DOUBLE:
+      {
+         runAbsCalc(static_cast<double>(0), data, theTile);
+         break;
+      }
+      default:
+      {
+         ossimNotify(ossimNotifyLevel_WARN)
+            << "ossimComplexAbs::getTile WARNING:\n"
+            << "Scalar type = " << theTile->getScalarType()
+            << " Not supported by ossimComplexAbs" << endl;
+         break;
+      }
+   }
+   theTile->validate();
+   
+   return theTile;
+}
+
+void ossimComplexAbs::initialize()
+{
+   if(theInputConnection)
+   {
+      theInputBandCount  = theInputConnection->getNumberOfOutputBands();
+      theOutputBandCount = theInputBandCount/2;
+      theTile = 0;
+   }
+}
+
+void ossimComplexAbs::allocate()
+{   
+   if(theInputConnection)
+   {
+      theTile = ossimImageDataFactory::instance()->create(this,
+                                                          this);
+      
+      theTile->initialize();
+   }
+}
+
+ossim_uint32 ossimComplexAbs::getNumberOfOutputBands() const
+{
+   if(!isSourceEnabled()||((theInputBandCount%2) != 0))
+   {
+      return ossimImageSourceFilter::getNumberOfOutputBands();
+   }
+   return theOutputBandCount;
+}
+
+bool ossimComplexAbs::isSourceEnabled()const
+{
+   if(ossimSource::isSourceEnabled())
+   {
+      if((theInputBandCount%2) != 0)
+      {
+         return false;
+      }
+   }
+   return ossimSource::isSourceEnabled();
+}
+
+bool ossimComplexAbs::saveState(ossimKeywordlist& kwl,
+                                     const char* prefix)const
+{
+   ossimImageSourceFilter::saveState(kwl, prefix);
+
+   kwl.add(prefix,
+           "bandcount",
+           theOutputBandCount,
+           true);
+   
+   return true;
+}
+
+bool ossimComplexAbs::loadState(const ossimKeywordlist& kwl,
+                                     const char* prefix)
+{
+   ossimImageSourceFilter::loadState(kwl, prefix);
+
+   const char* lookup = kwl.find(prefix, "bandcount");
+   if(lookup)
+   {
+      theOutputBandCount = ossimString(lookup).toUInt32();
+   }
+   return true;
+}
+
+template<class T> void ossimComplexAbs::runAbsCalc(T,
+                                                   ossimRefPtr<ossimImageData> inputData,
+                                                   ossimRefPtr<ossimImageData> outputData)
+{
+   T* bandSrc[2];
+   T* bandDest;
+   
+   unsigned int inputBandCount = inputData->getNumberOfBands();
+   unsigned int n = 0;
+
+   if(inputData->getDataObjectStatus() == OSSIM_EMPTY) return;
+   if(!inputData->getBuf()) return;
+   if(inputData->getDataObjectStatus() == OSSIM_PARTIAL)
+   {
+      for(unsigned int m =0 ; m < inputBandCount ; m+=2 )
+      {
+         T np1 = (T)inputData->getNullPix(m);
+         T np2 = (T)inputData->getNullPix(m+1);
+         bandSrc[0]  = static_cast<T*>(inputData->getBuf(m));
+         bandSrc[1]  = static_cast<T*>(inputData->getBuf(m+1));
+         
+         bandDest = static_cast<T*>(outputData->getBuf(n));
+         
+         long offset;
+         
+         long upperBound = outputData->getWidth()*outputData->getHeight();
+         
+         for(offset = 0; offset < upperBound; ++offset)
+         {
+            if((bandSrc[0][offset] != np1) &&
+               (bandSrc[1][offset] != np2))
+            {
+               bandDest[offset] = static_cast<T>(sqrt((double)
+                                                      (bandSrc[0][offset]*bandSrc[0][offset]) +
+                                                      (double)(bandSrc[1][offset]*bandSrc[1][offset])));
+            }
+         }
+         
+         n++;
+      }
+   }
+   else
+   {
+      for(unsigned int m =0 ; m < inputBandCount ; m+=2 )
+      {
+         bandSrc[0]  = static_cast<T*>(inputData->getBuf(m));
+         bandSrc[1]  = static_cast<T*>(inputData->getBuf(m+1));
+         
+         bandDest = static_cast<T*>(outputData->getBuf(n));
+         
+         long offset;
+         
+         long upperBound = outputData->getWidth()*outputData->getHeight();
+         
+         for(offset = 0; offset < upperBound; ++offset)
+         {
+            bandDest[offset] = static_cast<T>(sqrt((double)
+                                                   (bandSrc[0][offset]*bandSrc[0][offset]) +
+                                                   (double)(bandSrc[1][offset]*bandSrc[1][offset])));
+         }
+         
+         n++;
+      }
+   }
+   
+   
+   outputData->validate();
+}
diff --git a/ossim_plugins/contrib/ossimComplexAbs.h b/ossim_plugins/contrib/ossimComplexAbs.h
new file mode 100644
index 0000000..9cd3536
--- /dev/null
+++ b/ossim_plugins/contrib/ossimComplexAbs.h
@@ -0,0 +1,59 @@
+#ifndef ossimComplexAbs_HEADER
+#define ossimComplexAbs_HEADER
+#include <ossim/plugin/ossimSharedObjectBridge.h>
+#include <ossim/base/ossimString.h>
+#include <ossim/imaging/ossimImageSourceFilter.h>
+
+class ossimComplexAbs : public ossimImageSourceFilter
+{
+public:
+   ossimComplexAbs(ossimObject* owner=NULL);
+   ossimComplexAbs(ossimImageSource* inputSource,unsigned int outputbands=1);
+   ossimComplexAbs(ossimObject* owner,
+                        ossimImageSource* inputSource,unsigned int outputbands=1);
+                      
+   virtual ~ossimComplexAbs();
+   ossimString getShortName()const
+      {
+         return ossimString("ComplexAbs");
+      }
+   
+   ossimString getLongName()const
+      {
+         return ossimString("Get absolute value for Complex data");
+      }
+   
+   virtual ossimRefPtr<ossimImageData> getTile(const ossimIrect& tileRect, ossim_uint32 resLevel=0);
+   
+   virtual void initialize();
+   
+   virtual void allocate();
+   
+   ossim_uint32 getNumberOfOutputBands() const;
+   virtual bool isSourceEnabled()const;
+ 
+   virtual bool saveState(ossimKeywordlist& kwl,
+                          const char* prefix=0)const;
+   
+   /*!
+    * Method to the load (recreate) the state of an object from a keyword
+    * list.  Return true if ok or false on error.
+    */
+   virtual bool loadState(const ossimKeywordlist& kwl,
+                          const char* prefix=0);
+
+protected:
+   ossimRefPtr<ossimImageData> theBlankTile;
+   ossimRefPtr<ossimImageData> theTile;
+   
+   template<class T>
+   void runAbsCalc(T,
+                     ossimRefPtr<ossimImageData> inputData,
+                     ossimRefPtr<ossimImageData> outputData);
+                     
+   ossim_uint32 theOutputBandCount;
+   ossim_uint32 theInputBandCount; 
+TYPE_DATA
+};
+
+#endif
diff --git a/ossim_plugins/contrib/ossimContribExports.h b/ossim_plugins/contrib/ossimContribExports.h
new file mode 100644
index 0000000..0866a8f
--- /dev/null
+++ b/ossim_plugins/contrib/ossimContribExports.h
@@ -0,0 +1,31 @@
+//----------------------------------------------------------------------------
+// Copyright (c) 2005, Garrett Potts, all rights reserved.
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author:  Garrett Potts
+//
+// Description: Constants file for ossim plugins.
+//
+// $Id: ossimContribExports.h 23664 2015-12-14 14:17:27Z dburken $
+//----------------------------------------------------------------------------
+#ifndef ossimContribExports_HEADER
+#define ossimContribExports_HEADER
+
+#if defined(__MINGW32__) || defined(__CYGWIN__) || defined(_MSC_VER) || defined(__VISUALC__) || defined(__BORLANDC__) || defined(__WATCOMC__)
+#  define OSSIM_CONTRIB_EXPORT __declspec(dllexport)
+#  define OSSIM_CONTRIB_IMPORT __declspec(dllexport)
+
+#  ifdef OSSIM_CONTRIB_MAKINGDLL
+#     define OSSIM_CONTRIB_DLL OSSIM_CONTRIB_EXPORT
+#  else
+#     define  OSSIM_CONTRIB_DLL OSSIM_CONTRIB_IMPORT
+#  endif
+#else
+# define OSSIM_CONTRIB_DLL
+#endif
+
+#endif /* #ifndef ossimRegistrationExports_HEADER */
+
diff --git a/ossim_plugins/contrib/ossimContribImageSourceFactory.cpp b/ossim_plugins/contrib/ossimContribImageSourceFactory.cpp
new file mode 100644
index 0000000..382dd40
--- /dev/null
+++ b/ossim_plugins/contrib/ossimContribImageSourceFactory.cpp
@@ -0,0 +1,68 @@
+#include "ossimContribImageSourceFactory.h"
+#include "ossimCFARFilter.h"
+#include "ossimSPOTNatural.h"
+#include "ossimComplexAbs.h"
+#include <ossim/imaging/ossimImageSourceFactoryRegistry.h>
+#include <ossim/base/ossimKeywordNames.h>
+
+RTTI_DEF1(ossimContribImageSourceFactory, "ossimContribImageSourceFactory", ossimContribImageSourceFactory);
+
+ossimContribImageSourceFactory* ossimContribImageSourceFactory::theInstance = 0;
+
+ossimContribImageSourceFactory* ossimContribImageSourceFactory::instance()
+{
+   if(!theInstance)
+   {
+     theInstance = new ossimContribImageSourceFactory;
+   }
+
+   return theInstance;
+}
+
+ossimObject* ossimContribImageSourceFactory::createObject(const ossimString& typeName)const
+{
+   if(typeName == STATIC_TYPE_NAME(ossimCFARFilter))
+   {
+      return new ossimCFARFilter;
+   }
+   if(typeName == STATIC_TYPE_NAME(ossimSPOTNatural))
+   {
+      return new ossimSPOTNatural;
+   }
+   if(typeName == STATIC_TYPE_NAME(ossimComplexAbs))
+   {
+      return new ossimComplexAbs;
+   }
+
+   return (ossimObject*)NULL;
+}
+
+ossimObject* ossimContribImageSourceFactory::createObject(const ossimKeywordlist& kwl,
+                                          const char* prefix)const
+{
+   const char* type = kwl.find(prefix, ossimKeywordNames::TYPE_KW);
+   ossimObject* result = NULL;
+   if(type)
+   {
+      result = createObject(ossimString(type));
+      if(result)
+      {
+         result->loadState(kwl, prefix);
+      }
+   }
+
+   return result;
+}
+
+void ossimContribImageSourceFactory::getTypeNameList(std::vector<ossimString>& typeList)const
+{
+   typeList.push_back(STATIC_TYPE_NAME(ossimCFARFilter));
+   typeList.push_back(STATIC_TYPE_NAME(ossimSPOTNatural));
+   typeList.push_back(STATIC_TYPE_NAME(ossimComplexAbs));
+}
+
+ossimContribImageSourceFactory::~ossimContribImageSourceFactory()
+{
+   ossimImageSourceFactoryRegistry::instance()->unregisterFactory(theInstance);
+   theInstance = 0;
+}
diff --git a/ossim_plugins/contrib/ossimContribImageSourceFactory.h b/ossim_plugins/contrib/ossimContribImageSourceFactory.h
new file mode 100644
index 0000000..304d97d
--- /dev/null
+++ b/ossim_plugins/contrib/ossimContribImageSourceFactory.h
@@ -0,0 +1,26 @@
+#ifndef ossimContribImageSourceFactory_HEADER
+#define ossimContribImageSourceFactory_HEADER
+#include <ossim/imaging/ossimImageSourceFactoryBase.h>
+
+class ossimContribImageSourceFactory : public ossimImageSourceFactoryBase
+{
+public:
+   ossimContribImageSourceFactory()
+   {
+      theInstance = this;
+   }
+   virtual ~ossimContribImageSourceFactory();
+   
+   static ossimContribImageSourceFactory* instance();
+   virtual ossimObject* createObject(const ossimString& typeName)const;
+   virtual ossimObject* createObject(const ossimKeywordlist& kwl,
+                                     const char* prefix=0)const;
+   virtual void getTypeNameList(std::vector<ossimString>& typeList)const;
+protected:
+   static ossimContribImageSourceFactory* theInstance;
+
+TYPE_DATA
+};
+
+
+#endif
diff --git a/ossim_plugins/contrib/ossimContribPluginInit.cpp b/ossim_plugins/contrib/ossimContribPluginInit.cpp
new file mode 100644
index 0000000..b15784e
--- /dev/null
+++ b/ossim_plugins/contrib/ossimContribPluginInit.cpp
@@ -0,0 +1,69 @@
+//*******************************************************************
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author:  Garrett Potts
+//*******************************************************************
+//  $Id: ossimContribPluginInit.cpp 23664 2015-12-14 14:17:27Z dburken $
+#include <ossim/plugin/ossimSharedObjectBridge.h>
+#include "ossimContribExports.h"
+#include <ossim/base/ossimObjectFactoryRegistry.h>
+#include <ossim/imaging/ossimImageSourceFactoryRegistry.h>
+#include "ossimContribImageSourceFactory.h"
+#include <ossim/base/ossimString.h>
+
+extern "C"
+{
+   static ossimSharedObjectInfo theContribInfo;
+   static ossimString theContribDescription;
+   static std::vector<ossimString> theContribObjectList;
+
+   static const char* getContribDescription()
+   {
+      return theContribDescription.c_str();
+   }
+
+   static int getContribNumberOfClassNames()
+   {
+      return (int)theContribObjectList.size();
+   }
+
+   static const char* getContribClassName(int idx)
+   {
+      if(idx < (int)theContribObjectList.size())
+      {
+         return theContribObjectList[idx].c_str();
+      }
+      
+      return 0;
+   }
+
+   /* Note symbols need to be exported on windoze... */ 
+   OSSIM_CONTRIB_DLL void ossimSharedLibraryInitialize(ossimSharedObjectInfo** info)
+   {
+      theContribInfo.getDescription = getContribDescription;
+      theContribInfo.getNumberOfClassNames = getContribNumberOfClassNames;
+      theContribInfo.getClassName = getContribClassName;
+
+      theContribDescription = "Shared Library for Contributions from the OSSIM community\n\n"
+                               "Contributors:\n\n"
+                               "   Apogee Imaging International\n"
+                               "      Contributions include the CFAR filter.";
+      ossimImageSourceFactoryRegistry::instance()->registerFactory(ossimContribImageSourceFactory::instance());
+
+      if(!theContribObjectList.size())
+      {
+         ossimImageSourceFactoryRegistry::instance()->getTypeNameList(theContribObjectList);
+      }
+      *info = &theContribInfo;
+  }
+
+   /* Note symbols need to be exported on windoze... */ 
+  OSSIM_CONTRIB_DLL void ossimSharedLibraryFinalize()
+  {
+     ossimImageSourceFactoryRegistry::instance()->unregisterFactory(ossimContribImageSourceFactory::instance());
+  }
+}
+
diff --git a/ossim_plugins/contrib/ossimSPOTNatural.cpp b/ossim_plugins/contrib/ossimSPOTNatural.cpp
new file mode 100644
index 0000000..d8d3cd4
--- /dev/null
+++ b/ossim_plugins/contrib/ossimSPOTNatural.cpp
@@ -0,0 +1,305 @@
+// Copyright (C) 2006 Apogee Imaging International
+//
+// OSSIM is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License 
+// as published by the Free Software Foundation.
+//
+// This software is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
+//
+// You should have received a copy of the GNU General Public License
+// along with this software. If not, write to the Free Software 
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-
+// 1307, USA.
+//
+// See the GPL in the COPYING.GPL file for more details.
+//
+// Author: Tisham Dhar (tisham at apogee.com.au)
+// Description: SPOT False Natural Colour Genertion Algorithm
+//
+//*************************************************************************
+// $Id: ossimSPOTNatural.cpp 16169 2009-12-22 15:41:54Z dburken $
+
+#include <vector>
+
+#include <ossim/base/ossimRefPtr.h>
+#include "ossimSPOTNatural.h"
+#include <ossim/imaging/ossimU8ImageData.h>
+#include <ossim/base/ossimConstants.h>
+#include <ossim/base/ossimCommon.h>
+#include <ossim/base/ossimKeywordlist.h>
+#include <ossim/base/ossimKeywordNames.h>
+#include <ossim/imaging/ossimImageDataFactory.h>
+#include <ossim/imaging/ossimImageSourceFactoryBase.h>
+#include <ossim/imaging/ossimImageSourceFactoryRegistry.h>
+#include <ossim/base/ossimRefPtr.h>
+
+/*************************************************************************
+* SPOT and ASTER False Natural Colour Algorithm, output is in Byte
+* R = Band 2
+* G = (3*Band 1 + Band 3)/4
+* B = (3*Band 1 - band 3)/4
+* Band 1 = Green
+* Band 2 = Red
+* Band 3 = NIR
+**************************************************************************/
+
+RTTI_DEF1(ossimSPOTNatural, "ossimSPOTNatural", ossimImageSourceFilter)
+
+ossimSPOTNatural::ossimSPOTNatural(ossimObject* owner)
+   :ossimImageSourceFilter(owner),
+    theTile(NULL),
+    theC1(1.0/3.0),
+    theC2(1.0/3.0),
+    theC3(1.0/3.0)
+{
+}
+
+ossimSPOTNatural::ossimSPOTNatural(ossimImageSource* inputSource,
+                                           double c1,
+                                           double c2,
+                                           double c3)
+   : ossimImageSourceFilter(NULL, inputSource),
+     theTile(NULL),
+     theC1(c1),
+     theC2(c2),
+     theC3(c3)
+{
+}
+
+ossimSPOTNatural::ossimSPOTNatural(ossimObject* owner,
+                                           ossimImageSource* inputSource,
+                                           double c1,
+                                           double c2,
+                                           double c3)
+   : ossimImageSourceFilter(owner, inputSource),
+     theTile(NULL),
+     theC1(c1),
+     theC2(c2),
+     theC3(c3)
+{
+}
+
+ossimSPOTNatural::~ossimSPOTNatural()
+{
+}
+
+ossimRefPtr<ossimImageData> ossimSPOTNatural::getTile(const ossimIrect& tileRect,
+                                                                ossim_uint32 resLevel)
+{
+   if(!theInputConnection)
+   {
+      return theTile;
+   }
+
+   if(!isSourceEnabled())
+   {
+      return theInputConnection->getTile(tileRect, resLevel);
+   }
+   ossimRefPtr<ossimImageData> data = theInputConnection->getTile(tileRect,
+                                                                  resLevel);
+   if(!data.valid() || !data->getBuf())
+   {
+      return data;
+   }
+	
+   // First time through or after an initialize()...
+   if (!theTile.valid())
+   {
+      allocate();
+      if (!theTile.valid()) // Should never happen!
+      {
+         return data;
+      }
+   }
+	
+   theTile->setImageRectangle(tileRect);
+   theTile->makeBlank();
+   
+   switch(data->getScalarType())
+   {
+      case OSSIM_UCHAR:
+      {
+         runNatColour(static_cast<ossim_uint8>(0), data, theTile);
+         break;
+      }
+      case OSSIM_FLOAT: 
+      case OSSIM_NORMALIZED_FLOAT:
+      {
+         runNatColour(static_cast<float>(0), data, theTile);
+         break;
+      }
+      case OSSIM_USHORT16:
+      case OSSIM_USHORT11:
+      {
+         runNatColour(static_cast<ossim_uint16>(0), data, theTile);
+         break;
+      }
+      case OSSIM_SSHORT16:
+      {
+         runNatColour(static_cast<ossim_sint16>(0), data, theTile);
+         break;
+      }
+      case OSSIM_DOUBLE:
+      case OSSIM_NORMALIZED_DOUBLE:
+      {
+         runNatColour(static_cast<double>(0), data, theTile);
+         break;
+      }
+      default:
+      {
+         ossimNotify(ossimNotifyLevel_WARN)
+            << "ossimSPOTNatural::getTile WARNING:\n"
+            << "Scalar type = " << theTile->getScalarType()
+            << " Not supported by ossimSPOTNatural" << endl;
+         break;
+      }
+   }
+   theTile->validate();
+   
+   return theTile;
+}
+
+void ossimSPOTNatural::initialize()
+{
+   if(theInputConnection)
+   {
+      theTile = NULL;
+      /*
+      theTile = new ossimU8ImageData(this,
+                                     3,
+                                     theInputConnection->getTileWidth(),
+                                     theInputConnection->getTileHeight());  
+      theTile->initialize();
+      */
+   }
+}
+
+void ossimSPOTNatural::allocate()
+{   
+   if(theInputConnection)
+   {
+      ossimImageDataFactory* idf = ossimImageDataFactory::instance();
+      
+      theTile = idf->create(this,
+                            this);
+      
+      theTile->initialize();
+   }
+}
+
+ossim_uint32 ossimSPOTNatural::getNumberOfOutputBands() const
+{
+   if(!isSourceEnabled())
+   {
+      return ossimImageSourceFilter::getNumberOfOutputBands();
+   }
+   return 3;
+}
+
+bool ossimSPOTNatural::saveState(ossimKeywordlist& kwl,
+                                     const char* prefix)const
+{
+   ossimImageSourceFilter::saveState(kwl, prefix);
+
+   kwl.add(prefix,
+           "c1",
+           theC1,
+           true);
+   kwl.add(prefix,
+           "c2",
+           theC2,
+           true);
+   kwl.add(prefix,
+           "c3",
+           theC3,
+           true);
+   
+   return true;
+}
+
+bool ossimSPOTNatural::loadState(const ossimKeywordlist& kwl,
+                                     const char* prefix)
+{
+   ossimImageSourceFilter::loadState(kwl, prefix);
+
+   const char* lookup = kwl.find(prefix, "c1");
+   if(lookup)
+   {
+      theC1 = ossimString(lookup).toDouble();
+   }
+   lookup = kwl.find(prefix, "c2");
+   if(lookup)
+   {
+      theC2 = ossimString(lookup).toDouble();
+   }
+   lookup = kwl.find(prefix, "c3");
+   if(lookup)
+   {
+      theC3 = ossimString(lookup).toDouble();
+   }
+   return true;
+}
+
+template<class T> void ossimSPOTNatural::runNatColour(T,
+   ossimRefPtr<ossimImageData> inputData,
+   ossimRefPtr<ossimImageData> outputData)
+{   
+   std::vector<T*> bandSrc(inputData->getNumberOfBands());
+   std::vector<T*> bandDest(3);
+   
+   if(inputData->getNumberOfBands() == 1)
+   {
+      bandSrc[0]  = static_cast<T*>(inputData->getBuf(0));
+      bandSrc[1]  = static_cast<T*>(inputData->getBuf(0));
+      bandSrc[2]  = static_cast<T*>(inputData->getBuf(0));
+   }
+   else if(inputData->getNumberOfBands() == 2)
+   {
+      bandSrc[0]  = static_cast<T*>(inputData->getBuf(0));
+      bandSrc[1]  = static_cast<T*>(inputData->getBuf(1));
+      bandSrc[2]  = static_cast<T*>(inputData->getBuf(1));      
+   }
+   else if(inputData->getNumberOfBands() == 3)
+   {
+      bandSrc[0]  = static_cast<T*>(inputData->getBuf(0));
+      bandSrc[1]  = static_cast<T*>(inputData->getBuf(1));
+      bandSrc[2]  = static_cast<T*>(inputData->getBuf(2));      
+   }
+   
+   bandDest[0] = static_cast<T*>(outputData->getBuf(0));
+   bandDest[1] = static_cast<T*>(outputData->getBuf(1));
+   bandDest[2] = static_cast<T*>(outputData->getBuf(2));
+   
+   long offset;
+	
+   long upperBound = outputData->getWidth()*outputData->getHeight();
+   
+   for(offset = 0; offset < upperBound; ++offset)
+   {
+      T value1,value2,value3;
+      
+      value1 = static_cast<T>(bandSrc[1][offset]);
+      value2 = static_cast<T>(0.75*(double)bandSrc[0][offset]
+      					+0.25*(double)bandSrc[2][offset]);
+      value3 = static_cast<T>(0.75*(double)bandSrc[0][offset]
+      					-0.25*(double)bandSrc[2][offset]);
+      /*
+      value1 = value1<255?value1:255;
+      value1 = value1>0?value1:0;
+      
+      value2 = value2<255?value2:255;
+      value2 = value2>0?value2:0;
+      
+      value3 = value3<255?value3:255;
+      value3 = value3>0?value3:0;
+		*/
+		
+      bandDest[0][offset] = value1;
+      bandDest[1][offset] = value2;
+      bandDest[2][offset] = value3;
+   }
+
+   outputData->validate();
+}
diff --git a/ossim_plugins/contrib/ossimSPOTNatural.h b/ossim_plugins/contrib/ossimSPOTNatural.h
new file mode 100644
index 0000000..0d3bac6
--- /dev/null
+++ b/ossim_plugins/contrib/ossimSPOTNatural.h
@@ -0,0 +1,65 @@
+#ifndef ossimSPOTNatural_HEADER
+#define ossimSPOTNatural_HEADER
+#include <ossim/plugin/ossimSharedObjectBridge.h>
+#include <ossim/base/ossimString.h>
+#include <ossim/imaging/ossimImageSourceFilter.h>
+
+class ossimSPOTNatural : public ossimImageSourceFilter
+{
+public:
+   ossimSPOTNatural(ossimObject* owner=NULL);
+   ossimSPOTNatural(ossimImageSource* inputSource,
+                        double c1 = 1.0/3.0,
+                        double c2 = 1.0/3.0,
+                        double c3 = 1.0/3.0);
+   ossimSPOTNatural(ossimObject* owner,
+                        ossimImageSource* inputSource,
+                        double c1 = 1.0/3.0,
+                        double c2 = 1.0/3.0,
+                        double c3 = 1.0/3.0);
+   virtual ~ossimSPOTNatural();
+   ossimString getShortName()const
+      {
+         return ossimString("SPOTNatural");
+      }
+   
+   ossimString getLongName()const
+      {
+         return ossimString("SPOT False Natural Colour Generation");
+      }
+   
+   virtual ossimRefPtr<ossimImageData> getTile(const ossimIrect& tileRect, ossim_uint32 resLevel=0);
+   
+   virtual void initialize();
+   
+   virtual void allocate();
+   
+   ossim_uint32 getNumberOfOutputBands() const;
+ 
+   virtual bool saveState(ossimKeywordlist& kwl,
+                          const char* prefix=0)const;
+   
+   /*!
+    * Method to the load (recreate) the state of an object from a keyword
+    * list.  Return true if ok or false on error.
+    */
+   virtual bool loadState(const ossimKeywordlist& kwl,
+                          const char* prefix=0);
+
+protected:
+   ossimRefPtr<ossimImageData> theBlankTile;
+   ossimRefPtr<ossimImageData> theTile;
+   
+   template<class T>
+   void runNatColour(T,
+                     ossimRefPtr<ossimImageData> inputData,
+                     ossimRefPtr<ossimImageData> outputData);
+                     
+   double theC1;
+   double theC2;
+   double theC3;
+
+TYPE_DATA
+};
+
+#endif
diff --git a/ossim_plugins/csm/CMakeLists.txt b/ossim_plugins/csm/CMakeLists.txt
new file mode 100644
index 0000000..9d25a99
--- /dev/null
+++ b/ossim_plugins/csm/CMakeLists.txt
@@ -0,0 +1,61 @@
+set(LIB_NAME ossimcsm_plugin)
+MESSAGE( "************** LIBRARY SETUP FOR ossimcsm_plugin******************")
+
+# Include ossim cmake stuff:
+include(OssimVersion)
+include(OssimCommonVariables)
+include(OssimUtilities)
+
+set(requiredLibs)
+
+# OSSIM - Required: 
+find_package(ossim)
+if(OSSIM_FOUND)
+   include_directories( ${OSSIM_INCLUDE_DIR} )
+   set( requiredLibs ${requiredLibs} ${OSSIM_LIBRARIES} )
+else(OSSIM_FOUND)
+   message(FATAL_ERROR "Could not find ossim")
+endif(OSSIM_FOUND)
+
+# OpenThreads - Required:
+find_package( OpenThreads )
+if( OPENTHREADS_FOUND )
+   include_directories( ${OPENTHREADS_INCLUDE_DIR} )
+   set( requiredLibs ${requiredLibs} ${OPENTHREADS_LIBRARY} )
+else( OPENTHREADS_FOUND )
+   message( FATAL_ERROR "Could not find required OpenThreads package!" )
+endif( OPENTHREADS_FOUND )
+
+# csmApi - Required:
+
+find_package(csmApi)
+if (CSMAPI_FOUND)
+   include_directories(${CSMAPI_INCLUDE_DIRS})
+   set( requiredLibs ${requiredLibs} ${CSMAPI_LIBRARIES} )
+else(CSMAPI_FOUND)
+   message(FATAL_ERROR "Could not find csmApi")
+endif(CSMAPI_FOUND)
+
+
+FILE(GLOB OSSIMPLUGIN_SRCS *.cpp)
+FILE(GLOB OSSIMPLUGIN_HEADERS *.h)
+
+#---
+# OSSIMPLUGINSMAKINGDLL controls dll linkage on windows.  
+# Adding this sets OSSIM_PLUGINS_DLL #define TO "__declspec(dllexport)".
+#---
+add_definitions("-DOSSIMPLUGINSMAKINGDLL")
+
+# Adjust the install library path:
+if(OSSIM_INSTALL_PLUGINS_WITH_VERSION)
+   set(INSTALL_LIBRARY_DIR   "${INSTALL_LIBRARY_DIR}/ossim-${OSSIM_VERSION}/plugins")
+else(OSSIM_INSTALL_PLUGINS_WITH_VERSION)
+   set(INSTALL_LIBRARY_DIR   "${INSTALL_LIBRARY_DIR}/ossim/plugins")
+endif(OSSIM_INSTALL_PLUGINS_WITH_VERSION)
+
+OSSIM_LINK_LIBRARY(${LIB_NAME}
+                   COMPONENT_NAME ossim TYPE "${OSSIM_PLUGIN_LINK_TYPE}"
+		   LIBRARIES ${requiredLibs}
+                   HEADERS "${OSSIMPLUGIN_HEADERS}" 
+		   SOURCE_FILES "${OSSIMPLUGIN_SRCS}"
+                   INSTALL_LIB)
diff --git a/ossim_plugins/csm/ossimCsmPluginInit.cpp b/ossim_plugins/csm/ossimCsmPluginInit.cpp
new file mode 100644
index 0000000..f2ad11e
--- /dev/null
+++ b/ossim_plugins/csm/ossimCsmPluginInit.cpp
@@ -0,0 +1,116 @@
+//----------------------------------------------------------------------------
+//
+// License:  See top level LICENSE.txt file
+//
+// Author:  Bill Watkins
+//
+// Description: //
+//----------------------------------------------------------------------------
+// $Id: ossimPngPluginInit.cpp 11046 2007-05-25 18:03:03Z gpotts $
+#include <ossim/plugin/ossimSharedObjectBridge.h>
+#include "CSMSensorModelLoader.h"
+
+#include "ossimPluginConstants.h"
+#include "ossimCsmProjectionFactory.h"
+#include "ossimCsmSupport.h"
+#include <ossim/projection/ossimProjectionFactoryRegistry.h>
+#include <vector>
+#include <sstream>
+
+static void setDescription(ossimString& description)
+{
+   std::string pError;
+   ossimFilename pluginDir = ossimCsmSupport::instance()->csmPluginDirectory();
+   
+   if (!pluginDir.empty()) 
+   {
+      if(*(pluginDir.begin()+(pluginDir.size()-1)) != pluginDir.getPathSeparator())
+      {
+         pluginDir = ossimFilename(pluginDir + pluginDir.getPathSeparator());
+      }
+   }
+   std::vector<string> pluginNames;
+   if(!pluginDir.empty()&&pluginDir.exists())
+   {
+      pluginNames = CSMSensorModelLoader::getAvailablePluginNames(pluginDir.c_str(), pError );
+   }
+
+   std::ostringstream out;
+   out  << "Community Sensor Model Plugin\n" << "\nAvailable plugins are: \n\n";
+      	 
+   if(!pError.empty())
+   {
+      out << "ERROR loading! Result = " << pError << "\n";
+      description = out.str();
+      return;
+   }
+   if(pluginNames.empty())
+   {
+      out << "No CSM plugins available.  Please make sure your ossim preference variable csm_plugin_path\n"
+          << " is set or an environment variable CSM_PLUGIN_PATH is set\n";
+   }
+   ossim_uint32 idx = 0;
+   for(idx = 0; idx < pluginNames.size(); ++idx)
+   {
+      out << "\t" << pluginNames[idx] << " , supported models:\n";
+      std::vector<string> sensorModelNames = CSMSensorModelLoader::getAvailableSensorModelNames( pluginDir, pluginNames[idx].c_str(),  pError );    
+      ossim_uint32 idx2=0;
+      for(idx2 = 0; idx2 < sensorModelNames.size(); ++idx2)
+      { 
+         out << "\t\t" << sensorModelNames[idx2] << "\n";
+      }       
+   }
+   description = out.str();
+}
+
+
+extern "C"
+{
+   ossimSharedObjectInfo  myInfo;
+   ossimString theDescription;
+   std::vector<ossimString> theObjList;
+
+   const char* getDescription()
+   {
+      return theDescription.c_str();
+   }
+
+   int getNumberOfClassNames()
+   {
+      return (int)theObjList.size();
+   }
+
+   const char* getClassName(int idx)
+   {
+      if(idx < (int)theObjList.size())
+      {
+         return theObjList[0].c_str();
+      }
+      return (const char*)0;
+   }
+
+   /* Note symbols need to be exported on windoze... */ 
+   OSSIM_PLUGINS_DLL void ossimSharedLibraryInitialize(
+      ossimSharedObjectInfo** info, 
+      const char* /* options */ )
+   {    
+      myInfo.getDescription = getDescription;
+      myInfo.getNumberOfClassNames = getNumberOfClassNames;
+      myInfo.getClassName = getClassName;
+      
+      *info = &myInfo;
+      /* Register the readers... */
+      ossimProjectionFactoryRegistry::instance()->
+        registerFactoryToFront(ossimCsmProjectionFactory::instance());
+ 
+      setDescription(theDescription);
+
+   }
+
+   /* Note symbols need to be exported on windoze... */ 
+   OSSIM_PLUGINS_DLL void ossimSharedLibraryFinalize()
+   {
+      ossimProjectionFactoryRegistry::instance()->
+         unregisterFactory(ossimCsmProjectionFactory::instance());
+   }
+}
diff --git a/ossim_plugins/csm/ossimCsmProjectionFactory.cpp b/ossim_plugins/csm/ossimCsmProjectionFactory.cpp
new file mode 100644
index 0000000..df10853
--- /dev/null
+++ b/ossim_plugins/csm/ossimCsmProjectionFactory.cpp
@@ -0,0 +1,91 @@
+//*****************************************************************************
+// License:  See top level LICENSE.txt file.
+//
+// DESCRIPTION:
+//   Contains implementation of class ossimMapProjectionFactory
+//
+//*****************************************************************************
+//  $Id: ossimCsmProjectionFactory.cpp 13037 2008-06-18 15:12:55Z gpotts $
+#include <sstream>
+#include "ossimCsmProjectionFactory.h"
+#include <ossim/base/ossimKeywordNames.h>
+#include <ossim/projection/ossimProjectionFactoryRegistry.h>
+#include <ossim/base/ossimTrace.h>
+#include <ossim/base/ossimTieGptSet.h>
+#include <ossim/base/ossimUnitConversionTool.h>
+#include <ossim/base/ossimUnitTypeLut.h>
+#include "ossimCsmSensorModel.h"
+#include "ossimCsmSupport.h"
+
+static ossimTrace traceDebug("ossimCsmProjectionFactory:debug");
+
+ossimCsmProjectionFactory* ossimCsmProjectionFactory::theInstance = 0;
+
+ossimCsmProjectionFactory* ossimCsmProjectionFactory::instance()
+{
+   if(!theInstance)
+   {
+      theInstance = new ossimCsmProjectionFactory;
+   }
+
+   return (ossimCsmProjectionFactory*) theInstance;
+}
+
+ossimProjection* ossimCsmProjectionFactory::createProjection(const ossimFilename& filename,
+                                                             ossim_uint32 /* entryIdx */)const
+{
+    ossimRefPtr<ossimCsmSensorModel> model = new ossimCsmSensorModel;
+
+   if(!model->setSensorModel(filename, ossimCsmSupport::instance()->csmPluginDirectory()))
+    {
+       model = 0;
+    }
+
+    return model.release();
+
+}
+
+ossimProjection* ossimCsmProjectionFactory::createProjection(const ossimKeywordlist &keywordList,
+                                                             const char *prefix) const
+{
+   const char *lookup = keywordList.find(prefix, ossimKeywordNames::TYPE_KW);
+   ossimProjection* result = 0;
+   if(lookup)
+   {
+      result = createProjection(ossimString(lookup));
+      if(result)
+      {
+         result->loadState(keywordList); 	
+
+      }
+   }
+   return result;
+}
+
+ossimProjection* ossimCsmProjectionFactory::createProjection(const ossimString &name) const
+{
+   ossimProjection* result = 0;
+   
+   if(name == STATIC_TYPE_NAME(ossimCsmSensorModel))
+   {
+      result = new ossimCsmSensorModel();
+   }
+   
+   return result;
+}
+
+ossimObject* ossimCsmProjectionFactory::createObject(const ossimString& typeName)const
+{
+   return createProjection(typeName);
+}
+
+ossimObject* ossimCsmProjectionFactory::createObject(const ossimKeywordlist& kwl,
+                                                     const char* prefix)const
+{
+   return createProjection(kwl, prefix);
+}
+
+void ossimCsmProjectionFactory::getTypeNameList(std::vector<ossimString>& typeList)const
+{
+   typeList.push_back(STATIC_TYPE_NAME(ossimCsmSensorModel));
+}
diff --git a/ossim_plugins/csm/ossimCsmProjectionFactory.h b/ossim_plugins/csm/ossimCsmProjectionFactory.h
new file mode 100644
index 0000000..9ba1cd3
--- /dev/null
+++ b/ossim_plugins/csm/ossimCsmProjectionFactory.h
@@ -0,0 +1,64 @@
+//*******************************************************************
+//
+// License:  See top level LICENSE.txt file.
+// 
+// Author:  Garrett Potts
+//
+//*******************************************************************
+//  $Id: ossimCsmProjectionFactory.h 9118 2006-06-14 19:05:21Z gpotts $
+
+#ifndef ossimCsmProjectionFactory_HEADER
+#define ossimCsmProjectionFactory_HEADER
+
+#include <ossim/projection/ossimProjectionFactoryBase.h>
+#include <ossimPluginConstants.h>
+class ossimProjection;
+class ossimString;
+
+class ossimCsmProjectionFactory : public ossimProjectionFactoryBase
+{
+public:
+   /*!
+    * METHOD: instance()
+    * Instantiates singleton instance of this class:
+    */
+   static ossimCsmProjectionFactory* instance();
+
+   virtual ossimProjection* createProjection(const ossimFilename& filename,
+                                             ossim_uint32 entryIdx)const;
+   /*!
+    * METHOD: create()
+    * Attempts to create an instance of the projection specified by name.
+    * Returns successfully constructed projection or NULL.
+    */
+   virtual ossimProjection* createProjection(const ossimString& name)const;
+   virtual ossimProjection* createProjection(const ossimKeywordlist& kwl,
+                                             const char* prefix = 0)const;
+
+   virtual ossimObject* createObject(const ossimString& typeName)const;
+
+   /*!
+    * Creates and object given a keyword list.
+    */
+   virtual ossimObject* createObject(const ossimKeywordlist& kwl,
+                                     const char* prefix=0)const;
+   
+   /*!
+    * This should return the type name of all objects in all factories.
+    * This is the name used to construct the objects dynamially and this
+    * name must be unique.
+    */
+   virtual void getTypeNameList(std::vector<ossimString>& typeList)const;
+
+   /*!
+    * METHOD: getList()
+    * Returns list of all projections represented by this factory:
+    */
+//   virtual std::list<ossimString> getList()const;
+
+protected:
+   ossimCsmProjectionFactory() {}
+   static ossimCsmProjectionFactory*  theInstance;
+};
+
+#endif
diff --git a/ossim_plugins/csm/ossimCsmSensorModel.cpp b/ossim_plugins/csm/ossimCsmSensorModel.cpp
new file mode 100644
index 0000000..4f1a68b
--- /dev/null
+++ b/ossim_plugins/csm/ossimCsmSensorModel.cpp
@@ -0,0 +1,249 @@
+//*****************************************************************************
+// License:  See top level LICENSE.txt file.
+//
+// DESCRIPTION:
+//   Contains implementation of class ossimMapProjectionFactory
+//
+//*****************************************************************************
+//  $Id: ossimCsmProjectionFactory.cpp 13037 2008-06-18 15:12:55Z gpotts $
+#include "ossimCsmSensorModel.h"
+//#ifdef __APPLE__
+//#include <csmapi/csmapi.h>
+//#else
+#include <csmApi/CSMSensorModelLoader.h>
+//#endif
+#include <ossim/elevation/ossimElevManager.h>
+
+RTTI_DEF1(ossimCsmSensorModel, "ossimCsmSensorModel", ossimSensorModel);
+
+ossimCsmSensorModel::ossimCsmSensorModel()
+:m_model(0),
+m_pluginDir(""), 
+m_pluginName(""),
+m_sensorName("")
+{
+}
+
+ossimCsmSensorModel::ossimCsmSensorModel(const ossimCsmSensorModel& src)
+:m_model(0),
+m_pluginDir(""), 
+m_pluginName(""),
+m_sensorName(""){
+   setSensorModel(src.m_imageFile, src.m_pluginDir, src.m_pluginName, src.m_sensorName);
+}
+
+ossimCsmSensorModel::~ossimCsmSensorModel()
+{
+   if(m_model)
+   {
+      delete m_model;
+      m_model = 0;
+   }
+}
+
+
+void ossimCsmSensorModel::imagingRay(const ossimDpt& image_point,
+                                     ossimEcefRay&   image_ray) const
+{
+   if(m_model)
+   {
+      double locus[6] = {0.0, 0.0, 0.0,
+      0.0, 0.0, 0.0};
+      double AP = 0.0;
+      m_model->imageToRemoteImagingLocus(image_point.y, image_point.x, locus, AP);
+      ossimEcefVector v(locus[3], locus[4], locus[5]);	
+      image_ray.setOrigin(ossimEcefPoint(locus[0], locus[1], locus[2]));
+      image_ray.setDirection(v);
+   } 
+}
+
+void ossimCsmSensorModel::lineSampleHeightToWorld(const ossimDpt& image_point,
+                                                  const double&   heightEllipsoid,
+                                                  ossimGpt&       worldPoint) const
+{
+   if (!insideImage(image_point))
+   {
+      worldPoint.makeNan();
+      worldPoint = extrapolate(image_point, heightEllipsoid);
+   }
+   else
+   {
+      //***
+      // First establish imaging ray from image point:
+      //***
+      ossimEcefRay ray;
+      imagingRay(image_point, ray);
+      ossimEcefPoint Pecf (ray.intersectAboveEarthEllipsoid(heightEllipsoid));
+      worldPoint = ossimGpt(Pecf);
+   }
+   
+}
+
+void ossimCsmSensorModel::lineSampleToWorld(const ossimDpt& image_point,
+                                            ossimGpt&       gpt) const
+{
+   if(image_point.hasNans())
+   {
+      gpt.makeNan();
+      return;
+   }
+   //***
+   // Determine imaging ray and invoke elevation source object's services to
+   // intersect ray with terrain model:
+   //***
+   ossimEcefRay ray;
+   imagingRay(image_point, ray);
+   ossimElevManager::instance()->intersectRay(ray, gpt);   
+}
+
+bool ossimCsmSensorModel::setSensorModel(const ossimFilename& imageFile, 
+                                         const ossimFilename& pluginDir, 
+                                         const ossimString& pluginName,
+                                         const ossimString& sensorName)
+{
+   if(m_model)
+   {
+      delete m_model; m_model = 0;
+   }
+   ossimString error;
+   m_pluginDir  = pluginDir;
+   m_pluginName = pluginName;
+   m_sensorName = sensorName;
+   m_imageFile  = imageFile;
+   if(!m_pluginDir.exists()||!m_imageFile.exists()) return false;
+   if(!m_sensorName.empty()&&!m_pluginName.empty())
+   {
+      m_model = CSMSensorModelLoader::newSensorModel(m_pluginDir.c_str(), 
+                                                     m_pluginName, 
+                                                     m_sensorName.c_str(), 
+                                                     m_imageFile.c_str(), error, false);
+      if(!error.empty()&&m_model)
+      {
+         delete m_model;
+         m_model = 0;
+      }
+   }
+   else
+   {
+      std::vector<string> pluginNames = CSMSensorModelLoader::getAvailablePluginNames(m_pluginDir, error );    
+      ossim_uint32 idx = 0;
+      
+      for(idx = 0; ((idx < pluginNames.size())&&(!m_model)); ++idx)
+      {
+         std::vector<string> sensorModelNames = CSMSensorModelLoader::getAvailableSensorModelNames( pluginDir, 
+                                                                                                   pluginNames[idx].c_str(),  error );    
+         ossim_uint32 idx2=0;
+         for(idx2 = 0; ((idx2 < sensorModelNames.size())&&(!m_model)); ++idx2)
+         { 
+            error = "";
+            TSMSensorModel* model = CSMSensorModelLoader::newSensorModel(pluginDir, 
+                                                                         pluginNames[idx].c_str(), 
+                                                                         sensorModelNames[idx2].c_str(), 
+                                                                         m_imageFile.c_str(), error, false);
+            if(model&&error.empty())
+            {
+               m_sensorName = sensorModelNames[idx2].c_str();
+               m_pluginName = pluginNames[idx];
+               m_model = model;
+            }
+            else if(model)
+            {
+               delete model;
+               model = 0;
+            }
+         }
+      }
+   }
+   if(m_model)
+   {
+      int nLines, nSamples;
+      m_model->getImageSize(nLines, nSamples);	
+      
+      theImageClipRect = ossimIrect(-nLines, -nSamples, 2*nLines, 2*nSamples);
+      theRefImgPt = theImageClipRect.midPoint();
+      int nParams = 0;
+      m_model->getNumParameters(nParams);
+      int idx = 0;
+      ossimString name;
+      resizeAdjustableParameterArray(nParams);
+      double paramValue = 0.0;
+      TSMMisc::Param_CharType paramType;
+      for(idx = 0; idx < nParams; ++idx)
+      {
+         m_model->getParameterName(idx, name);
+         m_model->getCurrentParameterValue(idx, paramValue);
+         setParameterCenter(idx, paramValue);
+         setAdjustableParameter(idx, 0.0, 1.0);
+         setParameterDescription(idx, name.c_str());
+         m_model->getParameterType(idx, paramType); 
+         setParameterUnit(idx, "");
+      }
+      try
+      {
+         computeGsd();
+      }
+      catch (...) 
+      {
+      }
+      
+   }
+   
+   return (m_model != 0);
+}
+
+
+void ossimCsmSensorModel::updateModel()
+{
+   if(!m_model) return;
+   
+   int nParams = getNumberOfAdjustableParameters();
+   
+   
+   int idx = 0;
+   for(idx = 0; idx < nParams; ++idx)
+   {
+      m_model->setCurrentParameterValue(idx, computeParameterOffset(idx));
+   }
+}
+
+bool ossimCsmSensorModel::saveState(ossimKeywordlist& kwl,
+                                    const char* prefix) const
+{
+   bool result = ossimSensorModel::saveState(kwl, prefix);
+   
+   if(result)
+   {
+      //      ossimString state;
+      //      if(m_model->getSensorModelState(state))
+      //      {
+      //          kwl.add(prefix, "state", state);
+      //      }
+      //      else
+      {
+         kwl.add(prefix, "plugin_dir", m_pluginDir, true);
+         kwl.add(prefix, "plugin_name", m_pluginName, true);
+         kwl.add(prefix, "sensor_name", m_sensorName, true);
+         kwl.add(prefix, "image_file", m_imageFile, true);
+      }
+   }
+   
+   return result;
+}
+
+bool ossimCsmSensorModel::loadState(const ossimKeywordlist& kwl,
+                                    const char* prefix)
+{
+   bool result = ossimSensorModel::loadState(kwl, prefix);
+   if(result)
+   {
+      ossimString plugin_dir = kwl.find(prefix, "plugin_dir");
+      ossimString plugin_name = kwl.find(prefix, "plugin_name");
+      ossimString sensor_name = kwl.find(prefix, "sensor_name");
+      ossimString image_file  = kwl.find(prefix, "image_file");
+      
+      result = setSensorModel(image_file.c_str(), plugin_dir.c_str(), plugin_name.c_str(), sensor_name.c_str());
+      
+   }
+   
+   return result;
+}
diff --git a/ossim_plugins/csm/ossimCsmSensorModel.h b/ossim_plugins/csm/ossimCsmSensorModel.h
new file mode 100644
index 0000000..bbd6ff5
--- /dev/null
+++ b/ossim_plugins/csm/ossimCsmSensorModel.h
@@ -0,0 +1,58 @@
+//----------------------------------------------------------------------------
+//
+// License:  See top level LICENSE.txt file
+//
+// Author:  Bill Watkins
+//
+// Description: //
+//----------------------------------------------------------------------------
+// $Id: ossimPngPluginInit.cpp 11046 2007-05-25 18:03:03Z gpotts $
+#ifndef ossimCsmSensorModel_HEADER
+#define ossimCsmSensorModel_HEADER
+#include <ossim/projection/ossimSensorModel.h>
+#include <ossim/base/ossimFilename.h>
+//#ifdef __APPLE__
+//#include <csmapi/csmapi.h>
+//#else
+#include <csmApi/TSM/TSMSensorModel.h>
+//#endif
+class ossimCsmSensorModel : public ossimSensorModel
+{
+public:
+   ossimCsmSensorModel();
+   ossimCsmSensorModel(const ossimCsmSensorModel& src);
+   virtual ~ossimCsmSensorModel();
+   ossimObject* dup()const{return new ossimCsmSensorModel(*this);}
+   inline virtual bool useForward()const {return false;} //!image to ground faster   
+   virtual void imagingRay(const ossimDpt& image_point,
+                           ossimEcefRay&   image_ray) const;
+
+   virtual void lineSampleHeightToWorld(const ossimDpt& image_point,
+                                        const double&   height,
+                                        ossimGpt&       world_point) const;
+   virtual void lineSampleToWorld(const ossimDpt& image_point,
+                                   ossimGpt&       world_point) const;
+   virtual void updateModel();
+   bool setSensorModel(const ossimFilename& imageFile, 
+                       const ossimFilename& pluginDir,
+                       const ossimString& pluginName = "", 
+                       const ossimString& sensorName="");   
+
+
+   virtual bool saveState(ossimKeywordlist& kwl,
+                          const char* prefix=0) const;
+   
+   virtual bool loadState(const ossimKeywordlist& kwl,
+                          const char* prefix=0);
+   
+protected:
+   
+   TSMSensorModel* m_model;
+   ossimFilename m_pluginDir;
+   ossimString m_pluginName;
+   ossimString m_sensorName;   
+   ossimFilename m_imageFile;
+TYPE_DATA
+};
+
+#endif
diff --git a/ossim_plugins/csm/ossimCsmSupport.cpp b/ossim_plugins/csm/ossimCsmSupport.cpp
new file mode 100644
index 0000000..16b1f7a
--- /dev/null
+++ b/ossim_plugins/csm/ossimCsmSupport.cpp
@@ -0,0 +1,45 @@
+//----------------------------------------------------------------------------
+//
+// License:  See top level LICENSE.txt file
+//
+// Author:  Bill Watkins
+//
+// Description: //
+//----------------------------------------------------------------------------
+// $Id: ossimPngPluginInit.cpp 11046 2007-05-25 18:03:03Z gpotts $
+#include "ossimCsmSupport.h"
+#include <ossim/base/ossimEnvironmentUtility.h>
+#include <ossim/base/ossimPreferences.h>
+#include <iostream>
+ossimCsmSupport* ossimCsmSupport::m_instance=0;
+
+ossimCsmSupport::ossimCsmSupport()
+{
+   m_instance = this;
+}
+
+ossimCsmSupport* ossimCsmSupport::instance()
+{
+   if(!m_instance)
+   {
+      m_instance = new ossimCsmSupport();
+      m_instance->init();
+   }
+   
+   return m_instance;
+}
+
+const ossimFilename& ossimCsmSupport::csmPluginDirectory()
+{
+   return m_pluginDirectory;
+}
+
+void ossimCsmSupport::init()
+{
+   m_pluginDirectory = ossimFilename(ossimPreferences::instance()->findPreference("csm_plugin_path"));
+
+   if(m_pluginDirectory.empty() || !m_pluginDirectory.exists())
+   {
+      m_pluginDirectory = ossimFilename(ossimEnvironmentUtility::instance()->getEnvironmentVariable("CSM_PLUGIN_PATH"));
+   }
+}
diff --git a/ossim_plugins/csm/ossimCsmSupport.h b/ossim_plugins/csm/ossimCsmSupport.h
new file mode 100644
index 0000000..7e32d83
--- /dev/null
+++ b/ossim_plugins/csm/ossimCsmSupport.h
@@ -0,0 +1,24 @@
+//----------------------------------------------------------------------------
+//
+// License:  See top level LICENSE.txt file
+//
+// Author:  Bill Watkins
+//
+// Description: //
+//----------------------------------------------------------------------------
+// $Id: ossimPngPluginInit.cpp 11046 2007-05-25 18:03:03Z gpotts $
+#ifndef ossimCsmSupport_HEADER
+#define ossimCsmSupport_HEADER
+#include <ossim/base/ossimFilename.h>
+class ossimCsmSupport
+{
+public:
+   static ossimCsmSupport* instance();
+   const ossimFilename& csmPluginDirectory();
+   void init();
+protected:
+   ossimCsmSupport();
+   static ossimCsmSupport* m_instance;
+   ossimFilename m_pluginDirectory;
+};
+#endif
diff --git a/ossim_plugins/gdal/CMakeLists.txt b/ossim_plugins/gdal/CMakeLists.txt
new file mode 100644
index 0000000..56d3da1
--- /dev/null
+++ b/ossim_plugins/gdal/CMakeLists.txt
@@ -0,0 +1,72 @@
+set(LIB_NAME ossimgdal_plugin)
+MESSAGE( "************** LIBRARY SETUP FOR ossimgdal_plugin******************")
+
+# Include ossim cmake stuff:
+include(OssimVersion)
+include(OssimCommonVariables)
+include(OssimUtilities)
+
+SET(OSSIM_FRAMEWORK_GENERATION "OFF")
+SET(OSSIM_USER_DEFINED_DYNAMIC_OR_STATIC "SHARED")
+
+find_package(TIFF)
+find_package(ZLIB)
+find_package(GDAL)
+find_package(CURL)
+find_package(EXPAT)
+find_library(SQLITE_LIBRARY NAMES sqlite sqlite3)
+find_library(PROJ4_LIBRARY NAMES proj proj4)
+
+MESSAGE( STATUS "GDAL_LIBRARY        = ${GDAL_LIBRARY}" )
+MESSAGE( STATUS "GDAL_INCLUDE        = ${GDAL_INCLUDE_DIR}" )
+MESSAGE( STATUS "TIFF_LIBRARY        = ${TIFF_LIBRARY}" )
+MESSAGE( STATUS "TIFF_INCLUDE        = ${TIFF_INCLUDE_DIR}" )
+MESSAGE( STATUS "EXPAT_LIBRARY       = ${EXPAT_LIBRARY}" )
+MESSAGE( STATUS "SQLITE_LIBRARY      = ${SQLITE_LIBRARY}" )
+MESSAGE( STATUS "PROJ4_LIBRARY       = ${PROJ4_LIBRARY}" )
+
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
+INCLUDE_DIRECTORIES(${OPENTHREADS_INCLUDE_DIR})
+INCLUDE_DIRECTORIES(${GDAL_INCLUDE_DIR})
+INCLUDE_DIRECTORIES(${TIFF_INCLUDE_DIR})
+INCLUDE_DIRECTORIES(${GEOTIFF_INCLUDE_DIR})
+
+IF(NOT SQLITE_LIBRARY)
+   SET(SQLITE_LIBRARY "")
+ENDIF(NOT SQLITE_LIBRARY)
+
+IF(NOT PROJ4_LIBRARY)
+   SET(PROJ4_LIBRARY "")
+ENDIF(NOT PROJ4_LIBRARY)
+
+IF(NOT CURL_FOUND)
+   SET(CURL_LIBRARY "")
+ENDIF(NOT CURL_FOUND)
+
+IF(NOT EXPAT_FOUND)
+   SET(EXPAT_LIBRARY "")
+ENDIF(NOT EXPAT_FOUND)
+
+FILE(GLOB_RECURSE OSSIMPLUGIN_SRCS *.cpp)
+FILE(GLOB_RECURSE OSSIMPLUGIN_HEADERS *.h)
+
+####
+# OSSIMPLUGINSMAKINGDLL controls dll linkage on windows.  
+# Adding this sets OSSIM_PLUGINS_DLL #define TO "__declspec(dllexport)".
+###
+add_definitions("-DOSSIMPLUGINSMAKINGDLL")
+
+# Adjust the install library path:
+if(OSSIM_INSTALL_PLUGINS_WITH_VERSION)
+   set(INSTALL_LIBRARY_DIR   "${INSTALL_LIBRARY_DIR}/ossim-${OSSIM_VERSION}/plugins")
+else(OSSIM_INSTALL_PLUGINS_WITH_VERSION)
+   set(INSTALL_LIBRARY_DIR   "${INSTALL_LIBRARY_DIR}/ossim/plugins")
+endif(OSSIM_INSTALL_PLUGINS_WITH_VERSION)
+
+OSSIM_LINK_LIBRARY(${LIB_NAME}
+                   COMPONENT_NAME ossim TYPE "${OSSIM_PLUGIN_LINK_TYPE}"
+		   LIBRARIES ${OSSIM_LIBRARIES} ${OPENTHREADS_LIBRARY} ${GDAL_LIBRARY} ${KAKADU_LIBRARY} ${KAKADU_AUX_LIBRARY}  ${KAKADU_ADDITIONAL_OBJS}  ${TIFF_LIBRARY} ${CURL_LIBRARY} ${PROJ4_LIBRARY} ${SQLITE_LIBRARY} ${EXPAT_LIBRARIES} ${ZLIB_LIBRARY} ${GEOTIFF_LIBRARY}
+                   HEADERS "${OSSIMPLUGIN_HEADERS}"
+		   SOURCE_FILES "${OSSIMPLUGIN_SRCS}"
+                   INSTALL_LIB)
+
diff --git a/ossim_plugins/gdal/gdal.vcproj b/ossim_plugins/gdal/gdal.vcproj
new file mode 100755
index 0000000..91b6b7c
--- /dev/null
+++ b/ossim_plugins/gdal/gdal.vcproj
@@ -0,0 +1,359 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="9.00"
+	Name="ossimgdal_plugin"
+	ProjectGUID="{EBE45707-ED93-47B0-95BA-B90CEC765C41}"
+	RootNamespace="ossimgdal_plugin"
+	Keyword="Win32Proj"
+	TargetFrameworkVersion="131072"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="Debug|Win32"
+			OutputDirectory="$(ProjectDir)"
+			IntermediateDirectory="$(ConfigurationName)"
+			ConfigurationType="2"
+			InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="..\..\ossim_plugins\gdal;..\..\ossim\include;..\..\ossim_plugins;"$(OSSIM_DEPENDENCIES)\include""
+				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="ossimd.lib gdal_i.lib"
+				OutputFile="$(OutDir)..\bin\$(ProjectName)d.dll"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories=""$(OSSIM_HOME)/lib";"$(OSSIM_DEPENDENCIES)/lib""
+				IgnoreDefaultLibraryNames="libcd"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/gdal.pdb"
+				SubSystem="2"
+				RandomizedBaseAddress="1"
+				DataExecutionPrevention="0"
+				ImportLibrary="$(OutDir)..\lib\ossimgdal_plugind.lib"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|Win32"
+			OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+			IntermediateDirectory="$(ConfigurationName)"
+			ConfigurationType="2"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				InlineFunctionExpansion="0"
+				AdditionalIncludeDirectories="..\..\ossim_plugins\gdal;..\..\ossim\include;..\..\ossim_plugins;"$(OSSIM_DEPENDENCIES)\include""
+				PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;OSSIMUSINGDLL;HAVE_CONFIG_H"
+				RuntimeLibrary="2"
+				RuntimeTypeInfo="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="false"
+				DebugInformationFormat="0"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="ossim.lib gdal_i.lib"
+				OutputFile="$(OutDir)\bin\$(ProjectName).dll"
+				LinkIncremental="1"
+				AdditionalLibraryDirectories=""$(OSSIM_HOME)/lib";"$(OSSIM_DEPENDENCIES)/lib""
+				IgnoreDefaultLibraryNames="libcd"
+				GenerateDebugInformation="false"
+				SubSystem="0"
+				OptimizeReferences="0"
+				EnableCOMDATFolding="0"
+				RandomizedBaseAddress="1"
+				DataExecutionPrevention="0"
+				SupportUnloadOfDelayLoadedDLL="true"
+				ImportLibrary="$(OutDir)\lib\$(ProjectName).lib"
+				TargetMachine="0"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="Source Files"
+			Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
+			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+			>
+			<File
+				RelativePath=".\ossimEsriShapeFileFilter.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\ossimGdalDataset.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\ossimGdalFactory.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\ossimGdalImageWriterFactory.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\ossimGdalObjectFactory.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\ossimGdalOgrVectorAnnotation.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\ossimGdalOverviewBuilder.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\ossimGdalOverviewBuilderFactory.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\ossimGdalPluginInit.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\ossimGdalProjectionFactory.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\ossimGdalTiledDataset.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\ossimGdalTileSource.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\ossimGdalType.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\ossimGdalWriter.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\ossimOgcWktTranslator.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\ossimOgrGdalTileSource.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\ossimShapeDatabase.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\ossimShapeFile.cpp"
+				>
+			</File>
+		</Filter>
+		<Filter
+			Name="Header Files"
+			Filter="h;hpp;hxx;hm;inl;inc;xsd"
+			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+			>
+			<File
+				RelativePath=".\ossimEsriShapeFileFilter.h"
+				>
+			</File>
+			<File
+				RelativePath=".\ossimGdalDataset.h"
+				>
+			</File>
+			<File
+				RelativePath=".\ossimGdalFactory.h"
+				>
+			</File>
+			<File
+				RelativePath=".\ossimGdalImageWriterFactory.h"
+				>
+			</File>
+			<File
+				RelativePath=".\ossimGdalObjectFactory.h"
+				>
+			</File>
+			<File
+				RelativePath=".\ossimGdalOgrVectorAnnotation.h"
+				>
+			</File>
+			<File
+				RelativePath=".\ossimGdalOverviewBuilder.h"
+				>
+			</File>
+			<File
+				RelativePath=".\ossimGdalOverviewBuilderFactory.h"
+				>
+			</File>
+			<File
+				RelativePath=".\ossimGdalProjectionFactory.h"
+				>
+			</File>
+			<File
+				RelativePath=".\ossimGdalTiledDataset.h"
+				>
+			</File>
+			<File
+				RelativePath=".\ossimGdalTileSource.h"
+				>
+			</File>
+			<File
+				RelativePath=".\ossimGdalType.h"
+				>
+			</File>
+			<File
+				RelativePath=".\ossimGdalWriter.h"
+				>
+			</File>
+			<File
+				RelativePath=".\ossimOgcWktTranslator.h"
+				>
+			</File>
+			<File
+				RelativePath=".\ossimOgrGdalTileSource.h"
+				>
+			</File>
+			<File
+				RelativePath="..\ossimPluginConstants.h"
+				>
+			</File>
+			<File
+				RelativePath=".\ossimShapeDatabase.h"
+				>
+			</File>
+			<File
+				RelativePath=".\ossimShapeFile.h"
+				>
+			</File>
+			<File
+				RelativePath=".\shapefil.h"
+				>
+			</File>
+		</Filter>
+		<Filter
+			Name="Resource Files"
+			Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
+			UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+			>
+		</Filter>
+		<File
+			RelativePath=".\gdal.vcproj.7.10.old"
+			>
+		</File>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
diff --git a/ossim_plugins/gdal/macosx/libgdalplugin/libgdalplugin.xcodeproj/project.pbxproj b/ossim_plugins/gdal/macosx/libgdalplugin/libgdalplugin.xcodeproj/project.pbxproj
new file mode 100644
index 0000000..86e2450
--- /dev/null
+++ b/ossim_plugins/gdal/macosx/libgdalplugin/libgdalplugin.xcodeproj/project.pbxproj
@@ -0,0 +1,327 @@
+// !$*UTF8*$!
+{
+	archiveVersion = 1;
+	classes = {
+	};
+	objectVersion = 42;
+	objects = {
+
+/* Begin PBXBuildFile section */
+		1FC39D7508DD1F25003E4D9E /* ossimGdalProjectionFactory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1FC39D7308DD1F25003E4D9E /* ossimGdalProjectionFactory.cpp */; };
+		1FC39D7608DD1F25003E4D9E /* ossimGdalProjectionFactory.h in Headers */ = {isa = PBXBuildFile; fileRef = 1FC39D7408DD1F25003E4D9E /* ossimGdalProjectionFactory.h */; };
+		1FF6100F082ED83D004EB1E4 /* ossimGdalTileSource.h in Headers */ = {isa = PBXBuildFile; fileRef = 1FF60FFB082ED83C004EB1E4 /* ossimGdalTileSource.h */; };
+		1FF61010082ED83D004EB1E4 /* ossimGdalType.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1FF60FFC082ED83C004EB1E4 /* ossimGdalType.cpp */; };
+		1FF61011082ED83D004EB1E4 /* ossimGdalType.h in Headers */ = {isa = PBXBuildFile; fileRef = 1FF60FFD082ED83D004EB1E4 /* ossimGdalType.h */; };
+		1FF61012082ED83D004EB1E4 /* ossimGdalOgrVectorAnnotation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1FF60FFE082ED83D004EB1E4 /* ossimGdalOgrVectorAnnotation.cpp */; };
+		1FF61013082ED83D004EB1E4 /* ossimGdalImageWriterFactory.h in Headers */ = {isa = PBXBuildFile; fileRef = 1FF60FFF082ED83D004EB1E4 /* ossimGdalImageWriterFactory.h */; };
+		1FF61014082ED83D004EB1E4 /* ossimGdalFactory.h in Headers */ = {isa = PBXBuildFile; fileRef = 1FF61000082ED83D004EB1E4 /* ossimGdalFactory.h */; };
+		1FF61015082ED83D004EB1E4 /* ossimGdalTileSource.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1FF61001082ED83D004EB1E4 /* ossimGdalTileSource.cpp */; };
+		1FF61016082ED83D004EB1E4 /* ossimOgcWktTranslator.h in Headers */ = {isa = PBXBuildFile; fileRef = 1FF61002082ED83D004EB1E4 /* ossimOgcWktTranslator.h */; };
+		1FF61017082ED83D004EB1E4 /* ossimGdalWriter.h in Headers */ = {isa = PBXBuildFile; fileRef = 1FF61003082ED83D004EB1E4 /* ossimGdalWriter.h */; };
+		1FF61018082ED83D004EB1E4 /* ossimGdalTiledDataset.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1FF61004082ED83D004EB1E4 /* ossimGdalTiledDataset.cpp */; };
+		1FF61019082ED83D004EB1E4 /* ossimOgcWktTranslator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1FF61005082ED83D004EB1E4 /* ossimOgcWktTranslator.cpp */; };
+		1FF6101A082ED83D004EB1E4 /* ossimGdalFactory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1FF61006082ED83D004EB1E4 /* ossimGdalFactory.cpp */; };
+		1FF6101B082ED83D004EB1E4 /* ossimOgrGdalTileSource.h in Headers */ = {isa = PBXBuildFile; fileRef = 1FF61007082ED83D004EB1E4 /* ossimOgrGdalTileSource.h */; };
+		1FF6101C082ED83D004EB1E4 /* ossimGdalPluginInit.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1FF61008082ED83D004EB1E4 /* ossimGdalPluginInit.cpp */; };
+		1FF6101D082ED83D004EB1E4 /* ossimGdalTiledDataset.h in Headers */ = {isa = PBXBuildFile; fileRef = 1FF61009082ED83D004EB1E4 /* ossimGdalTiledDataset.h */; };
+		1FF6101E082ED83D004EB1E4 /* ossimGdalImageWriterFactory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1FF6100A082ED83D004EB1E4 /* ossimGdalImageWriterFactory.cpp */; };
+		1FF6101F082ED83D004EB1E4 /* ossimOgrGdalTileSource.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1FF6100B082ED83D004EB1E4 /* ossimOgrGdalTileSource.cpp */; };
+		1FF61021082ED83D004EB1E4 /* ossimGdalWriter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1FF6100D082ED83D004EB1E4 /* ossimGdalWriter.cpp */; };
+		1FF61022082ED83D004EB1E4 /* ossimGdalOgrVectorAnnotation.h in Headers */ = {isa = PBXBuildFile; fileRef = 1FF6100E082ED83D004EB1E4 /* ossimGdalOgrVectorAnnotation.h */; };
+		1FF6102A082ED87D004EB1E4 /* gdal.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1FF61029082ED87D004EB1E4 /* gdal.framework */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXFileReference section */
+		1F17DABB08CCDE780099C7F4 /* ossim.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ossim.framework; path = /Library/Frameworks/ossim.framework; sourceTree = "<absolute>"; };
+		1FC39D7308DD1F25003E4D9E /* ossimGdalProjectionFactory.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = ossimGdalProjectionFactory.cpp; path = ../../ossimGdalProjectionFactory.cpp; sourceTree = SOURCE_ROOT; };
+		1FC39D7408DD1F25003E4D9E /* ossimGdalProjectionFactory.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = ossimGdalProjectionFactory.h; path = ../../ossimGdalProjectionFactory.h; sourceTree = SOURCE_ROOT; };
+		1FF60FFB082ED83C004EB1E4 /* ossimGdalTileSource.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = ossimGdalTileSource.h; path = ../../ossimGdalTileSource.h; sourceTree = SOURCE_ROOT; };
+		1FF60FFC082ED83C004EB1E4 /* ossimGdalType.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = ossimGdalType.cpp; path = ../../ossimGdalType.cpp; sourceTree = SOURCE_ROOT; };
+		1FF60FFD082ED83D004EB1E4 /* ossimGdalType.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = ossimGdalType.h; path = ../../ossimGdalType.h; sourceTree = SOURCE_ROOT; };
+		1FF60FFE082ED83D004EB1E4 /* ossimGdalOgrVectorAnnotation.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = ossimGdalOgrVectorAnnotation.cpp; path = ../../ossimGdalOgrVectorAnnotation.cpp; sourceTree = SOURCE_ROOT; };
+		1FF60FFF082ED83D004EB1E4 /* ossimGdalImageWriterFactory.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = ossimGdalImageWriterFactory.h; path = ../../ossimGdalImageWriterFactory.h; sourceTree = SOURCE_ROOT; };
+		1FF61000082ED83D004EB1E4 /* ossimGdalFactory.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = ossimGdalFactory.h; path = ../../ossimGdalFactory.h; sourceTree = SOURCE_ROOT; };
+		1FF61001082ED83D004EB1E4 /* ossimGdalTileSource.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = ossimGdalTileSource.cpp; path = ../../ossimGdalTileSource.cpp; sourceTree = SOURCE_ROOT; };
+		1FF61002082ED83D004EB1E4 /* ossimOgcWktTranslator.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = ossimOgcWktTranslator.h; path = ../../ossimOgcWktTranslator.h; sourceTree = SOURCE_ROOT; };
+		1FF61003082ED83D004EB1E4 /* ossimGdalWriter.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = ossimGdalWriter.h; path = ../../ossimGdalWriter.h; sourceTree = SOURCE_ROOT; };
+		1FF61004082ED83D004EB1E4 /* ossimGdalTiledDataset.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = ossimGdalTiledDataset.cpp; path = ../../ossimGdalTiledDataset.cpp; sourceTree = SOURCE_ROOT; };
+		1FF61005082ED83D004EB1E4 /* ossimOgcWktTranslator.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = ossimOgcWktTranslator.cpp; path = ../../ossimOgcWktTranslator.cpp; sourceTree = SOURCE_ROOT; };
+		1FF61006082ED83D004EB1E4 /* ossimGdalFactory.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = ossimGdalFactory.cpp; path = ../../ossimGdalFactory.cpp; sourceTree = SOURCE_ROOT; };
+		1FF61007082ED83D004EB1E4 /* ossimOgrGdalTileSource.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = ossimOgrGdalTileSource.h; path = ../../ossimOgrGdalTileSource.h; sourceTree = SOURCE_ROOT; };
+		1FF61008082ED83D004EB1E4 /* ossimGdalPluginInit.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = ossimGdalPluginInit.cpp; path = ../../ossimGdalPluginInit.cpp; sourceTree = SOURCE_ROOT; };
+		1FF61009082ED83D004EB1E4 /* ossimGdalTiledDataset.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = ossimGdalTiledDataset.h; path = ../../ossimGdalTiledDataset.h; sourceTree = SOURCE_ROOT; };
+		1FF6100A082ED83D004EB1E4 /* ossimGdalImageWriterFactory.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = ossimGdalImageWriterFactory.cpp; path = ../../ossimGdalImageWriterFactory.cpp; sourceTree = SOURCE_ROOT; };
+		1FF6100B082ED83D004EB1E4 /* ossimOgrGdalTileSource.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = ossimOgrGdalTileSource.cpp; path = ../../ossimOgrGdalTileSource.cpp; sourceTree = SOURCE_ROOT; };
+		1FF6100D082ED83D004EB1E4 /* ossimGdalWriter.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = ossimGdalWriter.cpp; path = ../../ossimGdalWriter.cpp; sourceTree = SOURCE_ROOT; };
+		1FF6100E082ED83D004EB1E4 /* ossimGdalOgrVectorAnnotation.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = ossimGdalOgrVectorAnnotation.h; path = ../../ossimGdalOgrVectorAnnotation.h; sourceTree = SOURCE_ROOT; };
+		1FF61029082ED87D004EB1E4 /* gdal.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = gdal.framework; path = /Library/Frameworks/gdal.framework; sourceTree = "<absolute>"; };
+		D2AAC0630554660B00DB518D /* libgdalplugin.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libgdalplugin.dylib; sourceTree = BUILT_PRODUCTS_DIR; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+		D289988505E68E00004EDB86 /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				1FF6102A082ED87D004EB1E4 /* gdal.framework in Frameworks */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+		08FB7794FE84155DC02AAC07 /* libgdalplugin */ = {
+			isa = PBXGroup;
+			children = (
+				08FB7795FE84155DC02AAC07 /* Source */,
+				1FF61026082ED84E004EB1E4 /* Libraries */,
+				1AB674ADFE9D54B511CA2CBB /* Products */,
+			);
+			name = libgdalplugin;
+			sourceTree = "<group>";
+		};
+		08FB7795FE84155DC02AAC07 /* Source */ = {
+			isa = PBXGroup;
+			children = (
+				1FC39D7308DD1F25003E4D9E /* ossimGdalProjectionFactory.cpp */,
+				1FC39D7408DD1F25003E4D9E /* ossimGdalProjectionFactory.h */,
+				1FF61006082ED83D004EB1E4 /* ossimGdalFactory.cpp */,
+				1FF61000082ED83D004EB1E4 /* ossimGdalFactory.h */,
+				1FF60FFF082ED83D004EB1E4 /* ossimGdalImageWriterFactory.h */,
+				1FF6100A082ED83D004EB1E4 /* ossimGdalImageWriterFactory.cpp */,
+				1FF60FFE082ED83D004EB1E4 /* ossimGdalOgrVectorAnnotation.cpp */,
+				1FF6100E082ED83D004EB1E4 /* ossimGdalOgrVectorAnnotation.h */,
+				1FF61008082ED83D004EB1E4 /* ossimGdalPluginInit.cpp */,
+				1FF61004082ED83D004EB1E4 /* ossimGdalTiledDataset.cpp */,
+				1FF61009082ED83D004EB1E4 /* ossimGdalTiledDataset.h */,
+				1FF60FFB082ED83C004EB1E4 /* ossimGdalTileSource.h */,
+				1FF61007082ED83D004EB1E4 /* ossimOgrGdalTileSource.h */,
+				1FF60FFC082ED83C004EB1E4 /* ossimGdalType.cpp */,
+				1FF60FFD082ED83D004EB1E4 /* ossimGdalType.h */,
+				1FF6100D082ED83D004EB1E4 /* ossimGdalWriter.cpp */,
+				1FF61003082ED83D004EB1E4 /* ossimGdalWriter.h */,
+				1FF61002082ED83D004EB1E4 /* ossimOgcWktTranslator.h */,
+				1FF61005082ED83D004EB1E4 /* ossimOgcWktTranslator.cpp */,
+				1FF61001082ED83D004EB1E4 /* ossimGdalTileSource.cpp */,
+				1FF6100B082ED83D004EB1E4 /* ossimOgrGdalTileSource.cpp */,
+			);
+			name = Source;
+			sourceTree = "<group>";
+		};
+		1AB674ADFE9D54B511CA2CBB /* Products */ = {
+			isa = PBXGroup;
+			children = (
+				D2AAC0630554660B00DB518D /* libgdalplugin.dylib */,
+			);
+			name = Products;
+			sourceTree = "<group>";
+		};
+		1FF61026082ED84E004EB1E4 /* Libraries */ = {
+			isa = PBXGroup;
+			children = (
+				1F17DABB08CCDE780099C7F4 /* ossim.framework */,
+				1FF61029082ED87D004EB1E4 /* gdal.framework */,
+			);
+			name = Libraries;
+			sourceTree = "<group>";
+		};
+/* End PBXGroup section */
+
+/* Begin PBXHeadersBuildPhase section */
+		D2AAC0600554660B00DB518D /* Headers */ = {
+			isa = PBXHeadersBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				1FF6100F082ED83D004EB1E4 /* ossimGdalTileSource.h in Headers */,
+				1FF61011082ED83D004EB1E4 /* ossimGdalType.h in Headers */,
+				1FF61013082ED83D004EB1E4 /* ossimGdalImageWriterFactory.h in Headers */,
+				1FF61014082ED83D004EB1E4 /* ossimGdalFactory.h in Headers */,
+				1FF61016082ED83D004EB1E4 /* ossimOgcWktTranslator.h in Headers */,
+				1FF61017082ED83D004EB1E4 /* ossimGdalWriter.h in Headers */,
+				1FF6101B082ED83D004EB1E4 /* ossimOgrGdalTileSource.h in Headers */,
+				1FF6101D082ED83D004EB1E4 /* ossimGdalTiledDataset.h in Headers */,
+				1FF61022082ED83D004EB1E4 /* ossimGdalOgrVectorAnnotation.h in Headers */,
+				1FC39D7608DD1F25003E4D9E /* ossimGdalProjectionFactory.h in Headers */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXHeadersBuildPhase section */
+
+/* Begin PBXNativeTarget section */
+		D2AAC0620554660B00DB518D /* libgdalplugin */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 1F29D57F08CCDD7100DA2723 /* Build configuration list for PBXNativeTarget "libgdalplugin" */;
+			buildPhases = (
+				D2AAC0600554660B00DB518D /* Headers */,
+				D2AAC0610554660B00DB518D /* Sources */,
+				D289988505E68E00004EDB86 /* Frameworks */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = libgdalplugin;
+			productName = libgdalplugin;
+			productReference = D2AAC0630554660B00DB518D /* libgdalplugin.dylib */;
+			productType = "com.apple.product-type.library.dynamic";
+		};
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+		08FB7793FE84155DC02AAC07 /* Project object */ = {
+			isa = PBXProject;
+			buildConfigurationList = 1F29D58308CCDD7100DA2723 /* Build configuration list for PBXProject "libgdalplugin" */;
+			hasScannedForEncodings = 1;
+			mainGroup = 08FB7794FE84155DC02AAC07 /* libgdalplugin */;
+			projectDirPath = "";
+			targets = (
+				D2AAC0620554660B00DB518D /* libgdalplugin */,
+			);
+		};
+/* End PBXProject section */
+
+/* Begin PBXSourcesBuildPhase section */
+		D2AAC0610554660B00DB518D /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				1FF61010082ED83D004EB1E4 /* ossimGdalType.cpp in Sources */,
+				1FF61012082ED83D004EB1E4 /* ossimGdalOgrVectorAnnotation.cpp in Sources */,
+				1FF61015082ED83D004EB1E4 /* ossimGdalTileSource.cpp in Sources */,
+				1FF61018082ED83D004EB1E4 /* ossimGdalTiledDataset.cpp in Sources */,
+				1FF61019082ED83D004EB1E4 /* ossimOgcWktTranslator.cpp in Sources */,
+				1FF6101A082ED83D004EB1E4 /* ossimGdalFactory.cpp in Sources */,
+				1FF6101C082ED83D004EB1E4 /* ossimGdalPluginInit.cpp in Sources */,
+				1FF6101E082ED83D004EB1E4 /* ossimGdalImageWriterFactory.cpp in Sources */,
+				1FF6101F082ED83D004EB1E4 /* ossimOgrGdalTileSource.cpp in Sources */,
+				1FF61021082ED83D004EB1E4 /* ossimGdalWriter.cpp in Sources */,
+				1FC39D7508DD1F25003E4D9E /* ossimGdalProjectionFactory.cpp in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXSourcesBuildPhase section */
+
+/* Begin XCBuildConfiguration section */
+		1F29D58008CCDD7100DA2723 /* Development */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				COPY_PHASE_STRIP = NO;
+				DYLIB_COMPATIBILITY_VERSION = 1;
+				DYLIB_CURRENT_VERSION = 1;
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_ENABLE_FIX_AND_CONTINUE = YES;
+				GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
+				GCC_MODEL_TUNING = G5;
+				GCC_OPTIMIZATION_LEVEL = 0;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				HEADER_SEARCH_PATHS = /usr/local/include/ossim;
+				INSTALL_PATH = /usr/local/lib;
+				LIBRARY_STYLE = DYNAMIC;
+				MACH_O_TYPE = mh_dylib;
+				PREBINDING = NO;
+				PRODUCT_NAME = libgdalplugin;
+				ZERO_LINK = YES;
+			};
+			name = Development;
+		};
+		1F29D58108CCDD7100DA2723 /* Deployment */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				COPY_PHASE_STRIP = YES;
+				DYLIB_COMPATIBILITY_VERSION = 1;
+				DYLIB_CURRENT_VERSION = 1;
+				GCC_ENABLE_FIX_AND_CONTINUE = NO;
+				GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
+				GCC_MODEL_TUNING = G5;
+				GCC_PREPROCESSOR_DEFINITIONS = (
+					__OSSIM_DARWIN__,
+					DARWIN,
+					MACOSX,
+					"MPI_SETTING=1",
+					"FREETYPE_SETTING=1",
+					GEOTIFF_ENABLED,
+					"_FILE_OFFSET_BITS=64",
+					_LARGE_FILES,
+				);
+				GCC_WARN_ABOUT_RETURN_TYPE = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				HEADER_SEARCH_PATHS = (
+					../../../../ossim/src/ossim_core,
+					../../../../ossim_plugins,
+				);
+				INSTALL_PATH = /usr/local/lib;
+				LIBRARY_STYLE = DYNAMIC;
+				MACH_O_TYPE = mh_dylib;
+				OTHER_CFLAGS = "";
+				PREBINDING = NO;
+				PRODUCT_NAME = libgdalplugin;
+				ZERO_LINK = NO;
+			};
+			name = Deployment;
+		};
+		1F29D58208CCDD7100DA2723 /* Default */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				DYLIB_COMPATIBILITY_VERSION = 1;
+				DYLIB_CURRENT_VERSION = 1;
+				GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
+				GCC_MODEL_TUNING = G5;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				HEADER_SEARCH_PATHS = /usr/local/include/ossim;
+				INSTALL_PATH = /usr/local/lib;
+				LIBRARY_STYLE = DYNAMIC;
+				MACH_O_TYPE = mh_dylib;
+				PREBINDING = NO;
+				PRODUCT_NAME = libgdalplugin;
+			};
+			name = Default;
+		};
+		1F29D58408CCDD7100DA2723 /* Development */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+			};
+			name = Development;
+		};
+		1F29D58508CCDD7100DA2723 /* Deployment */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				GCC_PREPROCESSOR_DEFINITIONS = "";
+				GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS = "";
+			};
+			name = Deployment;
+		};
+		1F29D58608CCDD7100DA2723 /* Default */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+			};
+			name = Default;
+		};
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+		1F29D57F08CCDD7100DA2723 /* Build configuration list for PBXNativeTarget "libgdalplugin" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				1F29D58008CCDD7100DA2723 /* Development */,
+				1F29D58108CCDD7100DA2723 /* Deployment */,
+				1F29D58208CCDD7100DA2723 /* Default */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Default;
+		};
+		1F29D58308CCDD7100DA2723 /* Build configuration list for PBXProject "libgdalplugin" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				1F29D58408CCDD7100DA2723 /* Development */,
+				1F29D58508CCDD7100DA2723 /* Deployment */,
+				1F29D58608CCDD7100DA2723 /* Default */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Default;
+		};
+/* End XCConfigurationList section */
+	};
+	rootObject = 08FB7793FE84155DC02AAC07 /* Project object */;
+}
diff --git a/ossim_plugins/gdal/makefile.vc b/ossim_plugins/gdal/makefile.vc
new file mode 100644
index 0000000..fd1bc26
--- /dev/null
+++ b/ossim_plugins/gdal/makefile.vc
@@ -0,0 +1,75 @@
+###
+# $Id: makefile.vc 13411 2008-08-08 14:43:52Z dburken $
+#
+# Windows nmake make file.  This code should compile with the Microsoft .NET
+# compiler.
+# 
+# Currently for a typical build on windows you would do the following.
+# - cd src packages
+# - untar the gdal package
+# - cd gdal and edit the nmake.opt file appropriately.
+# - cd back to the ossim top and edit its nmake.opt file appropriately.
+# - nmake /f makefile
+# - nmake /f makefile install (if you want the apps in the bin directory.
+#
+# NOTE:  If you make shared apps it's handy to copy the ossim.dll to the bin
+#        directory. 
+###
+
+!INCLUDE ..\nmake.opt
+PLUGIN_ROOT = ossim_gdal_plugin
+
+###
+# Note: EMBED_MANIFEST variable is set in nmake.opt so make sure it is included
+# before this test.
+###
+!if "$(EMBED_MANIFEST)" == "1"
+!include ..\makefile.inc
+OSSIM_VC_MANIFEST_EMBED_DLL=$(_VC_MANIFEST_EMBED_DLL)
+OSSIM_VC_MANIFEST_CLEAN=$(_VC_MANIFEST_CLEAN)
+!else
+OSSIM_VC_MANIFEST_EMBED_DLL=
+OSSIM_VC_MANIFEST_CLEAN=
+!endif
+
+INC = -I.. -I. $(INC) $(GDAL_INC)
+LINK	=	link
+LFLAGS	=	/NOLOGO /DELAYLOAD:comdlg32.dll /DELAYLOAD:oleaut32.dll /DELAYLOAD:winmm.dll /DELAYLOAD:wsock32.dll /DELAYLOAD:winspool.dll /SUBSYSTEM:WINDOWS /LIBPATH:"$(QTDIR)\lib" /LIBPATH:"$(OSSIM_QT_HOME)\lib" /LIBPATH:"$(OSSIM_HOME)\lib
+
+LIBS	= "$(OSSIM_LIB)
+
+OBJ	= \
+ossimEsriShapeFileFilter.obj \
+ossimGdalDataset.obj \
+ossimGdalFactory.obj \
+ossimGdalImageWriterFactory.obj \
+ossimGdalObjectFactory.obj \
+ossimGdalOgrVectorAnnotation.obj \
+ossimGdalOverviewBuilder.obj \
+ossimGdalOverviewBuilderFactory.obj \
+ossimGdalPluginInit.obj \
+ossimGdalProjectionFactory.obj \
+ossimGdalTiledDataset.obj \
+ossimGdalTileSource.obj \
+ossimGdalType.obj \
+ossimGdalWriter.obj \
+ossimOgcWktTranslator.obj \
+ossimOgrGdalTileSource.obj \
+ossimShapeDatabase.obj \
+ossimShapeFile.obj
+
+
+default:	$(OBJ)
+	link /VERSION:$(VERSION_STRING) /DLL /OUT:"$(PLUGIN_ROOT).dll" /IMPLIB:"$(PLUGIN_ROOT).lib" /NOLOGO $(OBJ) /LIBPATH:$(LIB_DIR) $(GDAL_LIBS) $(JPEG_LIB) $(OSSIM_LIB) $(LINK_EXTERNALS)
+	$(OSSIM_VC_MANIFEST_EMBED_DLL)
+
+install:
+	$(CP) $(PLUGIN_ROOT).dll $(INSTALL_DIR)
+
+clean:
+	$(RM) *.obj $(PLUGIN_ROOT).*
+	$(OSSIM_VC_MANIFEST_CLEAN)
+
+!if "$(EMBED_MANIFEST)" == "1"
+!include ..\makefile.targ.inc
+!endif
diff --git a/ossim_plugins/gdal/ossimEsriShapeFileFilter.cpp b/ossim_plugins/gdal/ossimEsriShapeFileFilter.cpp
new file mode 100644
index 0000000..0f8565f
--- /dev/null
+++ b/ossim_plugins/gdal/ossimEsriShapeFileFilter.cpp
@@ -0,0 +1,769 @@
+//*******************************************************************
+// Copyright (C) 2000 ImageLinks Inc. 
+//
+// License: See LICENSE.txt file in the top level directory.
+//
+// Author: Garrett Potts
+//
+//*************************************************************************
+// $Id: ossimEsriShapeFileFilter.cpp 19669 2011-05-27 13:27:29Z gpotts $
+
+#include <cstdio>
+#include <cstdlib>
+#include <sstream>
+using namespace std;
+
+#include <ossimEsriShapeFileFilter.h>
+#include <ossimShapeFile.h>
+#include <ossim/imaging/ossimAnnotationPolyObject.h>
+#include <ossim/imaging/ossimGeoAnnotationPolyLineObject.h>
+#include <ossim/imaging/ossimAnnotationObject.h>
+#include <ossim/imaging/ossimGeoAnnotationPolyObject.h>
+#include <ossim/imaging/ossimGeoAnnotationEllipseObject.h>
+#include <ossim/base/ossimTrace.h>
+#include <ossim/base/ossimCommon.h>
+#include <ossim/base/ossimConstants.h>
+#include <ossim/base/ossimKeywordNames.h>
+#include <ossim/base/ossimTrace.h>
+#include <ossim/base/ossimNotifyContext.h>
+#include <ossim/base/ossimFilename.h>
+#include <ossim/base/ossimGeoPolygon.h>
+#include <ossim/base/ossimUnitConversionTool.h>
+#include <ossim/projection/ossimProjection.h>
+#include <ossim/projection/ossimProjectionFactoryRegistry.h>
+#include <ossim/projection/ossimMapProjection.h>
+#include <ossim/projection/ossimEquDistCylProjection.h>
+
+RTTI_DEF2(ossimEsriShapeFileFilter,
+          "ossimEsriShapeFileFilter",
+          ossimAnnotationSource,
+          ossimViewInterface);
+
+static const ossimTrace traceDebug("ossimEsriShapeFileFilter:debug");
+
+ossimEsriShapeFileFilter::ossimEsriShapeFileFilter(ossimImageSource* inputSource)
+   :ossimAnnotationSource(inputSource),
+    ossimViewInterface(),
+    theCoordinateSystem(OSSIM_GEOGRAPHIC_SPACE),
+    theUnitType(OSSIM_METERS),
+    theTree((SHPTree*)0),
+    theMaxQuadTreeLevels(10),
+    thePenColor(255,255,255),
+    theBrushColor(255,255,255),
+    theFillFlag(false),
+    theThickness(1),
+    thePointWidthHeight(1, 1),
+    theBorderSize(0.0),
+    theBorderSizeUnits(OSSIM_DEGREES)
+{
+   ossimViewInterface::theObject = this;
+   ossimAnnotationSource::setNumberOfBands(3);
+   theBoundingRect.makeNan();
+   theMinArray[0] = theMinArray[1] = theMinArray[2] = theMinArray[3] = ossim::nan();
+   theMaxArray[0] = theMaxArray[1] = theMaxArray[2] = theMaxArray[3] = ossim::nan();
+}
+
+ossimEsriShapeFileFilter::~ossimEsriShapeFileFilter()
+{
+   removeViewProjection();
+   
+   if(theTree)
+   {
+      SHPDestroyTree(theTree);
+   }
+
+   deleteCache();
+}
+
+bool ossimEsriShapeFileFilter::setView(ossimObject* baseObject)
+{
+   ossimProjection* proj = PTR_CAST(ossimProjection, baseObject);
+   if(proj)
+   {
+      if(theImageGeometry.valid())
+      {
+         theImageGeometry->setProjection(proj);
+      }
+      else
+      {
+         theImageGeometry = new ossimImageGeometry(0, proj);
+      }
+      return true;
+   }
+   else
+   {
+      ossimImageGeometry* geom = dynamic_cast<ossimImageGeometry*> (baseObject);
+      if(geom)
+      {
+         theImageGeometry = geom;
+         return true;
+      }
+   }
+
+   return false;
+}
+
+ossimObject* ossimEsriShapeFileFilter::getView()
+{
+   return theImageGeometry.get();
+}
+
+const ossimObject* ossimEsriShapeFileFilter::getView()const
+{
+   return theImageGeometry.get();
+}
+
+bool ossimEsriShapeFileFilter::addObject(ossimAnnotationObject* /*anObject*/)
+{
+   ossimNotify(ossimNotifyLevel_WARN)
+      << "ossimEsriShapeFileFilter::addObject\n"
+      << "Can't add objects to layer, must go through Esri loadShapeFile"
+      <<endl;
+   
+   return false;
+}
+
+void ossimEsriShapeFileFilter::computeBoundingRect()
+{
+//   ossimAnnotationSource::computeBoundingRect();
+   
+   std::multimap<int, ossimAnnotationObject*>::iterator iter = theShapeCache.begin();
+   
+   theBoundingRect.makeNan();
+   while(iter != theShapeCache.end())
+   {
+       ossimDrect rect = (*iter).second->getBoundingRect();
+      if(theBoundingRect.hasNans())
+      {
+         theBoundingRect = rect;
+      }
+      else
+      {
+         if(!rect.hasNans())
+         {
+            theBoundingRect = theBoundingRect.combine(rect);
+         }
+      }
+      
+      ++iter;
+   }
+}
+
+ossimIrect ossimEsriShapeFileFilter::getBoundingRect(ossim_uint32 resLevel)const
+{
+   if(!isSourceEnabled()||
+      getInput())
+   {
+      if(getInput())
+      {
+         ossimImageSource* input = PTR_CAST(ossimImageSource, getInput());
+         if(input)
+         {
+            return input->getBoundingRect(resLevel);
+         }
+      }
+   }
+   return theBoundingRect;
+}
+
+void ossimEsriShapeFileFilter::drawAnnotations(ossimRefPtr<ossimImageData> tile)
+{
+   ossimAnnotationSource::drawAnnotations(tile);
+   
+   if (!theTree||!theShapeFile.isOpen()) return;
+   if(theImageGeometry.valid())
+   {
+      ossimIrect rect = tile->getImageRectangle();
+
+      rect = ossimIrect(rect.ul().x,
+                        rect.ul().y,
+                        rect.lr().x,
+                        rect.lr().y);
+      double boundsMin[2];
+      double boundsMax[2];
+      
+      ossimGpt gp1;
+      ossimGpt gp2;
+      ossimGpt gp3;
+      ossimGpt gp4;
+
+      theImageGeometry->localToWorld(rect.ul(),
+                                           gp1);
+      theImageGeometry->localToWorld(rect.ur(),
+                                           gp2);
+      theImageGeometry->localToWorld(rect.lr(),
+                                           gp3);
+      theImageGeometry->localToWorld(rect.ll(),
+                                           gp4);
+
+      ossimDrect boundsRect( ossimDpt(gp1.lond(),
+                                      gp1.latd()),
+                             ossimDpt(gp2.lond(),
+                                      gp2.latd()),
+                             ossimDpt(gp3.lond(),
+                                      gp3.latd()),
+                             ossimDpt(gp4.lond(),
+                                      gp4.latd()),
+                             OSSIM_RIGHT_HANDED);
+
+      boundsMin[0] = boundsRect.ul().x;
+      boundsMin[1] = boundsRect.lr().y;
+
+      boundsMax[0] = boundsRect.lr().x;
+      boundsMax[1] = boundsRect.ul().y;
+
+      int n;
+      int *array=(int*)0;
+      
+      array = SHPTreeFindLikelyShapes(theTree,
+                                      boundsMin,
+                                      boundsMax,
+                                      &n);
+      
+      theImage->setCurrentImageData(tile);
+      if(n&&array)
+      {
+         for(int i = 0; i < n; ++i)
+         {
+            std::multimap<int, ossimAnnotationObject*>::iterator iter = theShapeCache.find(array[i]);
+            while( ((*iter).first == array[i]) && (iter != theShapeCache.end()) )
+            {
+               (*iter).second->draw(*theImage);
+               ++iter;
+            }
+         }
+         
+         free(array);
+      }
+   }
+}
+
+void ossimEsriShapeFileFilter::transformObjects(ossimImageGeometry* geom)
+{
+   std::multimap<int, ossimAnnotationObject*>::iterator iter = theShapeCache.begin();
+
+
+   ossimImageGeometry* tempGeom = theImageGeometry.get();
+   if(geom)
+   {
+      tempGeom = geom;
+   }
+
+   if(!tempGeom) return;
+   
+   while(iter != theShapeCache.end())
+   {
+      ossimGeoAnnotationObject* obj = PTR_CAST(ossimGeoAnnotationObject,
+                                               (*iter).second);
+      if(obj)
+      {
+         obj->transform(tempGeom);
+      }
+      ++iter;
+   }
+
+   computeBoundingRect();
+}
+
+void ossimEsriShapeFileFilter::setImageGeometry(ossimImageGeometry* geom)
+{
+   theImageGeometry = geom;
+   transformObjects();
+}
+
+//**************************************************************************************************
+//! Returns the image geometry object associated with this tile source or NULL if non defined.
+//! The geometry contains full-to-local image transform as well as projection (image-to-world)
+//**************************************************************************************************
+ossimRefPtr<ossimImageGeometry> ossimEsriShapeFileFilter::getImageGeometry()
+{
+   if( !theImageGeometry )
+   {
+      theImageGeometry = new ossimImageGeometry(0, new ossimEquDistCylProjection());
+   }
+   return theImageGeometry;
+}
+
+void ossimEsriShapeFileFilter::removeViewProjection()
+{
+   theImageGeometry = 0;
+}
+
+void ossimEsriShapeFileFilter::deleteCache()
+{
+   std::multimap<int, ossimAnnotationObject*>::iterator iter = theShapeCache.begin();
+
+
+   while(iter != theShapeCache.end())
+   {
+      if ((*iter).second)
+      {
+        (*iter).second->unref();
+      }
+      ++iter;
+   }
+
+   theShapeCache.clear();
+}
+
+void ossimEsriShapeFileFilter::checkAndSetDefaultView()
+{
+   if(!theImageGeometry.valid())
+   {
+      getImageGeometry();
+      if(theImageGeometry.valid())
+      {
+         transformObjects();
+      }
+   }
+}
+
+bool ossimEsriShapeFileFilter::loadShapeFile(const ossimFilename& shapeFile)
+{
+   if(theTree)
+   {
+      SHPDestroyTree(theTree);
+      theTree = (SHPTree*)0;
+   }
+   theShapeFile.open(shapeFile);
+   deleteCache();
+   deleteAll();
+   
+   if(theShapeFile.isOpen())
+   {
+      theShapeFile.getBounds(theMinArray[0],theMinArray[1],theMinArray[2],theMinArray[3],
+                             theMaxArray[0],theMaxArray[1],theMaxArray[2],theMaxArray[3]);
+
+      theTree = SHPCreateTree(theShapeFile.getHandle(),
+                              2,
+                              theMaxQuadTreeLevels,
+                              theMinArray,
+                              theMaxArray);  
+      
+      ossimShapeObject obj;
+      for(int index = 0 ; index < theShapeFile.getNumberOfShapes(); ++index)
+      {
+         obj.loadShape(theShapeFile,
+                       index);
+         
+         if(obj.isLoaded())
+         {
+            switch(obj.getType())
+            {
+               case SHPT_POLYGON:
+               case SHPT_POLYGONZ:
+               {
+                  loadPolygon(obj);
+                  break;
+               }
+               case SHPT_POINT:
+               case SHPT_POINTZ:
+               {
+                  loadPoint(obj);
+                  break;
+               }
+               case SHPT_ARC:
+               case SHPT_ARCZ:
+               {
+                  loadArc(obj);
+                  break;
+               }
+               case SHPT_NULL:
+               {
+                  break;
+               }
+               default:
+               {
+                  ossimNotify(ossimNotifyLevel_WARN)
+                     << "ossimEsriShapeFileFilter::loadShapeFile\n"
+                     << "SHAPE " << obj.getTypeByName()
+                     << " Not supported" <<  endl;
+                  break;
+               }
+            }
+         }
+      }
+      
+      theCurrentObject = theShapeCache .begin();
+      if(theImageGeometry.valid())
+      {
+         transformObjects();
+      }
+      else
+      {
+         checkAndSetDefaultView();
+      }
+   }
+   
+   return true;
+}
+
+void ossimEsriShapeFileFilter::loadPolygon(ossimShapeObject& obj)
+{
+   int starti = 0;
+   int endi   = 0;
+   if(obj.getNumberOfParts() > 1)
+   {
+      starti = obj.getShapeObject()->panPartStart[0];
+      endi   = obj.getShapeObject()->panPartStart[1];
+   }
+   else
+   {
+      starti = 0;
+      endi   = obj.getShapeObject()->nVertices;
+   }
+   
+   vector<ossimGpt> groundPolygon;
+   for(ossim_uint32 part = 0; part < obj.getNumberOfParts(); ++part)
+   {
+      if(obj.getPartType(part) != SHPP_RING)
+      {
+         ossimNotify(ossimNotifyLevel_WARN)
+            << "ossimEsriShapeFileFilter::loadPolygon\n"
+            << "Part = " << obj.getPartByName(part)
+            << " not supported for shape = "
+            << obj.getTypeByName() << endl;
+         break;
+      }
+      groundPolygon.clear();
+      for(ossim_int32 vertexNumber = starti; vertexNumber < endi; ++vertexNumber)
+      {
+         groundPolygon.push_back(ossimGpt(obj.getShapeObject()->padfY[vertexNumber],
+                                          obj.getShapeObject()->padfX[vertexNumber]));
+         
+      }
+      starti = endi;   
+      if((part + 2) < obj.getNumberOfParts())
+      {  
+         endi = obj.getShapeObject()->panPartStart[part+2];
+      }
+      else
+      {
+         endi = obj.getShapeObject()->nVertices;
+      }
+      
+      ossimRgbVector color;
+      
+      if(theFillFlag)
+      {
+         color = theBrushColor;
+      }
+      else
+      {
+         color = thePenColor;
+      }
+
+      if(theBorderSize != 0.0)
+      {
+         ossimGeoPolygon tempPoly(groundPolygon);
+         ossimGeoPolygon tempPoly2;
+         
+         tempPoly.stretchOut(tempPoly2,
+                             theBorderSize);
+         groundPolygon = tempPoly2.getVertexList();
+
+      }
+      
+      ossimGeoAnnotationObject *newGeoObj = new ossimGeoAnnotationPolyObject(groundPolygon,
+                                                                             theFillFlag,
+                                                                             color.getR(),
+                                                                             color.getG(),
+                                                                             color.getB(),
+                                                                             theThickness);
+      newGeoObj->setName(theFeatureName);
+      theShapeCache.insert(make_pair(obj.getId(),
+                                     newGeoObj));
+   }
+}
+
+void ossimEsriShapeFileFilter::loadPoint(ossimShapeObject& obj)
+{
+   int n   = obj.getNumberOfVertices();
+
+   if(n)
+   {
+      ossimGpt gpt(obj.getShapeObject()->padfY[0],
+                   obj.getShapeObject()->padfX[0]);
+      
+      ossimRgbVector color;
+      
+      if(theFillFlag)
+      {
+         color = theBrushColor;
+      }
+      else
+      {
+         color = thePenColor;
+      }
+      ossimGeoAnnotationEllipseObject *newGeoObj =
+         new ossimGeoAnnotationEllipseObject(gpt,
+                                             thePointWidthHeight,
+                                             theFillFlag,
+                                             color.getR(),
+                                             color.getG(),
+                                             color.getB(),
+                                             theThickness);
+      newGeoObj->setEllipseWidthHeightUnitType(OSSIM_PIXEL);
+      newGeoObj->setName(theFeatureName);
+      theShapeCache.insert(make_pair(obj.getId(),
+                                     newGeoObj));
+
+   }
+}
+
+void ossimEsriShapeFileFilter::loadArc(ossimShapeObject& obj)
+{
+   int starti = 0;
+   int endi   = 0;
+   if(obj.getNumberOfParts() > 1)
+   {
+      starti = obj.getShapeObject()->panPartStart[0];
+      endi   = obj.getShapeObject()->panPartStart[1];
+   }
+   else
+   {
+      starti = 0;
+      endi   = obj.getShapeObject()->nVertices;
+   }
+   
+   vector<ossimGpt> groundPolygon;
+   for(ossim_uint32 part = 0; part < obj.getNumberOfParts(); ++part)
+   {
+      if(obj.getPartType(part) != SHPP_RING)
+      {
+         ossimNotify(ossimNotifyLevel_WARN)
+            << "ossimEsriShapeFileFilter::loadArc\n"
+            << "Part = " << obj.getPartByName(part)
+            << " not supported for shape = "
+            << obj.getTypeByName() << endl;
+         break;
+      }
+      groundPolygon.clear();
+      for(ossim_int32 vertexNumber = starti; vertexNumber < endi; ++vertexNumber)
+      {
+         groundPolygon.push_back(ossimGpt(obj.getShapeObject()->padfY[vertexNumber],
+                                          obj.getShapeObject()->padfX[vertexNumber]));
+         
+      }
+      starti = endi;   
+      if((part + 2) < obj.getNumberOfParts())
+      {  
+         endi = obj.getShapeObject()->panPartStart[part+2];
+      }
+      else
+      {
+         endi = obj.getShapeObject()->nVertices;
+      }
+      
+      ossimRgbVector color;
+      
+      if(theFillFlag)
+      {
+         color = theBrushColor;
+      }
+      else
+      {
+         color = thePenColor;
+      }
+      
+      ossimGeoAnnotationObject *newGeoObj = new ossimGeoAnnotationPolyLineObject(groundPolygon,
+                                                                                 color.getR(),
+                                                                                 color.getG(),
+                                                                                 color.getB(),
+                                                                                 theThickness);
+      newGeoObj->setName(theFeatureName);
+      theShapeCache.insert(make_pair(obj.getId(),
+                                     newGeoObj));
+   }
+}
+
+bool ossimEsriShapeFileFilter::saveState(ossimKeywordlist& kwl,
+                                         const char* prefix)const
+{
+   ossimString s;
+   
+   kwl.add(prefix,
+           ossimKeywordNames::FILENAME_KW,
+           theShapeFile.getFilename(),
+           true);
+
+   kwl.add(prefix,
+           ossimKeywordNames::MAX_QUADTREE_LEVELS_KW,
+           theMaxQuadTreeLevels,
+           true);
+
+   s = ossimString::toString((int)thePenColor.getR()) + " " +
+       ossimString::toString((int)thePenColor.getG()) + " " +
+       ossimString::toString((int)thePenColor.getB());
+   
+   kwl.add(prefix,
+           ossimKeywordNames::PEN_COLOR_KW,
+           s.c_str(),
+           true);
+
+   s = ossimString::toString((int)theBrushColor.getR()) + " " +
+       ossimString::toString((int)theBrushColor.getG()) + " " +
+       ossimString::toString((int)theBrushColor.getB());
+   
+   kwl.add(prefix,
+           ossimKeywordNames::BRUSH_COLOR_KW,
+           s.c_str(),
+           true);
+
+   kwl.add(prefix,
+           ossimKeywordNames::FILL_FLAG_KW,
+           (int)theFillFlag,
+           true);
+
+   kwl.add(prefix,
+           ossimKeywordNames::FEATURE_NAME_KW,
+           theFeatureName.c_str(),
+           true);
+
+   kwl.add(prefix,
+           ossimKeywordNames::THICKNESS_KW,
+           theThickness,
+           true);
+
+   ossimString border;
+   border = ossimString::toString(theBorderSize);
+   border += " degrees";
+   kwl.add(prefix,
+           ossimKeywordNames::BORDER_SIZE_KW,
+           border,
+           true);
+   
+   s = ossimString::toString((int)thePointWidthHeight.x) + " " +
+       ossimString::toString((int)thePointWidthHeight.y) + " ";
+   
+   kwl.add(prefix,
+           ossimKeywordNames::POINT_WIDTH_HEIGHT_KW,
+           s.c_str(),
+           true);
+   
+   if(theImageGeometry.valid())
+   {
+      ossimString newPrefix = prefix;
+      newPrefix += "view_proj.";
+      theImageGeometry->saveState(kwl, newPrefix.c_str());
+   }
+   
+   return ossimAnnotationSource::saveState(kwl, prefix);
+}
+
+bool ossimEsriShapeFileFilter::loadState(const ossimKeywordlist& kwl,
+                                         const char* prefix)
+{
+   
+   const char* quadLevels  = kwl.find(prefix, ossimKeywordNames::MAX_QUADTREE_LEVELS_KW);
+   const char* filename    = kwl.find(prefix, ossimKeywordNames::FILENAME_KW);
+   const char* penColor    = kwl.find(prefix, ossimKeywordNames::PEN_COLOR_KW);
+   const char* brushColor  = kwl.find(prefix, ossimKeywordNames::BRUSH_COLOR_KW);
+   const char* featureName = kwl.find(prefix, ossimKeywordNames::FEATURE_NAME_KW);
+   const char* fillFlag    = kwl.find(prefix, ossimKeywordNames::FILL_FLAG_KW);
+   const char* thickness   = kwl.find(prefix, ossimKeywordNames::THICKNESS_KW);
+   const char* pointWh     = kwl.find(prefix, ossimKeywordNames::POINT_WIDTH_HEIGHT_KW);
+   const char* border_size = kwl.find(prefix, ossimKeywordNames::BORDER_SIZE_KW);
+   
+   deleteCache();
+
+   if(thickness)
+   {
+      theThickness = ossimString(thickness).toLong();
+   }
+   if(quadLevels)
+   {
+      theMaxQuadTreeLevels = ossimString(quadLevels).toLong();
+   }
+   
+   if(penColor)
+   {
+      int r, g, b;
+      istringstream s(penColor);
+      s>>r>>g>>b;
+      thePenColor = ossimRgbVector((ossim_uint8)r, (ossim_uint8)g, (ossim_uint8)b);
+   }
+
+   if(brushColor)
+   {
+      int r, g, b;
+      istringstream s(brushColor);
+      s>>r>>g>>b;
+      theBrushColor = ossimRgbVector((ossim_uint8)r, (ossim_uint8)g, (ossim_uint8)b);
+   }
+   if(pointWh)
+   {
+      double w, h;
+      istringstream s(pointWh);
+      s>>w>>h;
+      thePointWidthHeight = ossimDpt(w, h);
+   }
+   
+   if(fillFlag)
+   {
+      theFillFlag = ossimString(fillFlag).toBool();
+   }
+
+   if(border_size)
+   {
+      istringstream input(border_size);
+
+      ossimString s;
+      input >> s;
+
+      theBorderSize = s.toDouble();
+      
+      ossimString s2;
+      
+      input >> s2;
+
+      s2 = s2.upcase();
+      
+      if(s2 == "US")
+      {
+         theBorderSizeUnits = OSSIM_US_SURVEY_FEET;
+      }
+      else if(s2 == "METERS")
+      {
+         theBorderSizeUnits = OSSIM_METERS;
+      }
+      else if(s2 == "FEET")
+      {
+         theBorderSizeUnits = OSSIM_FEET;
+      }
+      else
+      {
+         theBorderSizeUnits = OSSIM_DEGREES;
+      }
+      ossimUnitConversionTool unitConvert(theBorderSize,
+                                          theBorderSizeUnits);
+      
+      theBorderSize      = unitConvert.getValue(OSSIM_DEGREES);
+      theBorderSizeUnits = OSSIM_DEGREES;
+   }
+   else
+   {
+      theBorderSize      = 0.0;
+      theBorderSizeUnits = OSSIM_DEGREES;
+   }
+   
+   theFeatureName = featureName;
+   
+   ossimString newPrefix = prefix;
+   newPrefix += "view_proj.";
+   
+   theImageGeometry = new ossimImageGeometry;
+   if(!theImageGeometry->loadState(kwl, newPrefix.c_str()))
+   {
+      theImageGeometry = 0;
+   }
+   
+   if(filename)
+   {
+      loadShapeFile(ossimFilename(filename));
+   }
+   
+   checkAndSetDefaultView();
+   
+   return ossimAnnotationSource::loadState(kwl, prefix);
+}
diff --git a/ossim_plugins/gdal/ossimEsriShapeFileFilter.h b/ossim_plugins/gdal/ossimEsriShapeFileFilter.h
new file mode 100644
index 0000000..fd29db3
--- /dev/null
+++ b/ossim_plugins/gdal/ossimEsriShapeFileFilter.h
@@ -0,0 +1,272 @@
+//*******************************************************************
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author: Garrett Potts
+//
+//*************************************************************************
+// $Id: ossimEsriShapeFileFilter.h 23664 2015-12-14 14:17:27Z dburken $
+
+#ifndef ossimEsriShapeFileFilter_HEADER
+#define ossimEsriShapeFileFilter_HEADER
+
+#include <map>
+#include <shapefil.h>
+#include <ossimShapeFile.h>
+#include <ossim/imaging/ossimAnnotationSource.h>
+#include <ossim/base/ossimRtti.h>
+#include <ossim/base/ossimViewInterface.h>
+#include <ossim/base/ossimRgbVector.h>
+#include <ossim/imaging/ossimImageGeometry.h>
+
+class ossimGeoAnnotationObject;
+class ossimAnnotationObject;
+class ossimProjection;
+
+/*!
+ * class ossimEsriShapeFileFilter
+ *
+ * This class is used to render shape files.  Iif this filter has
+ * an input connection to an ossimImageSourceInterface then it will
+ * draw any vectors over the input tile.  If it is not connected
+ * it will just render its vector data to a tile and return it.
+ * <pre>
+ * supported keywords:
+ *
+ *   max_quadtree_levels:    // number of levels for faster hit testing
+ *                           // defaults to 10
+ *
+ *   fill_flag:              // 1 for true 0 for false.  Default is false
+ *                           // and specifies how all closed surfaces are
+ *                           // to be drawn
+ *
+ *   feature_name:           // currently not used.
+ *
+ *   pen_color:              // specified in Red Green Blue and is the color used
+ *                           // if the fill flag is not specified.  Future changes
+ *                           // might be to include this as an outline color for
+ *                           // filled objects.  Default is white. Example: 255 255 255
+ *
+ *   brush_color:            // Color used by objects that have the fill flag enabled
+ *                           // format is Red Green Blue. Default is white.
+ *
+ *   line_thickness:         // line drawing thickness in pixels.
+ *
+ *   border_size:            // can be us feet, feet, meters, degrees,
+ *                           // will automatically expand all polygons by the
+ *                           // specified size.  Uses the centroid to estimate
+ *                           // non degree units when converting to degrees.
+ *
+ *   point_width_height:     // Specifies the width and height of a point object in
+ *                           // pixels.  Default is 1 and has the following format
+ *                           // w h.  Example 1 1
+ *
+ *   filename:               // The esri shape file to be used
+ *
+ * example Keyword list:  See ossimAnnotationSource for any additional keywords
+ *
+ *
+ * brush_color:  255 255 255
+ * feature_name:
+ * filename:
+ * fill_flag:  0
+ * max_quadtree_levels:  10
+ * pen_color:  255 255 255
+ * point_width_height:  1 1
+ * thickness:  1
+ * border_size: 25 meters
+ * type:  ossimEsriShapeFileFilter
+ *
+ * </pre>
+ */
+class OSSIM_PLUGINS_DLL ossimEsriShapeFileFilter :
+   public ossimAnnotationSource,
+   public ossimViewInterface
+{
+public:
+   ossimEsriShapeFileFilter(ossimImageSource* inputSource=NULL);
+   ~ossimEsriShapeFileFilter();
+
+   virtual bool setView(ossimObject* baseObject);
+
+   virtual ossimObject*       getView();
+   virtual const ossimObject* getView()const;
+
+   virtual bool addObject(ossimAnnotationObject* anObject);
+   virtual void transformObjects(ossimImageGeometry* geom=0);
+   virtual void setImageGeometry(ossimImageGeometry* projection);
+
+   //! Returns the image geometry object associated with this tile source or NULL if non defined.
+   //! The geometry contains full-to-local image transform as well as projection (image-to-world)
+   virtual ossimRefPtr<ossimImageGeometry> getImageGeometry();
+
+   virtual ossimIrect getBoundingRect(ossim_uint32 resLevel=0)const;
+   virtual void computeBoundingRect();
+
+   virtual void drawAnnotations(ossimRefPtr<ossimImageData> tile);
+   /*!
+    * Will delete the current objects within the layer and add all
+    * objects in the passed in file.
+    */
+   virtual bool loadShapeFile(const ossimFilename& shapeFile);
+
+   virtual ossimFilename getFilename()const
+      {
+         return theShapeFile.getFilename();
+      }
+   virtual ossim_int32 getMaxQuadTreeLevels()const
+      {
+         return theMaxQuadTreeLevels;
+      }
+
+   virtual void setMaxQuadTreeLevels(ossim_int32 levels)
+      {
+         theMaxQuadTreeLevels = (levels>0?levels:10);
+      }
+
+   virtual void setBrushColor(const ossimRgbVector& brushColor)
+      {
+         theBrushColor = brushColor;
+      }
+
+   virtual void setPenColor(const ossimRgbVector& penColor)
+      {
+         thePenColor = penColor;
+      }
+
+   virtual ossimRgbVector getPenColor()const
+      {
+         return thePenColor;
+      }
+
+   virtual ossimRgbVector getBrushColor()const
+      {
+         return theBrushColor;
+      }
+
+   virtual bool getFillFlag()const
+      {
+         return theFillFlag;
+      }
+
+   virtual void setFillFlag(bool flag)
+      {
+         theFillFlag=flag;
+      }
+   virtual ossimString getFeatureName()const
+      {
+         return theFeatureName;
+      }
+   virtual void setFeatureName(const ossimString& name)
+      {
+         theFeatureName = name;
+      }
+
+   virtual void setThickness(ossim_int32 thickness)
+      {
+         theThickness = thickness >= 0? thickness:1;
+      }
+   virtual ossim_int32 getThickness()const
+      {
+         return theThickness;
+      }
+   virtual void setPointRadius(double r)
+      {
+         thePointWidthHeight = ossimDpt(fabs(r)*2, fabs(r)*2);
+      }
+   virtual double getPointRadius()const
+      {
+         return thePointWidthHeight.x/2.0;
+      }
+
+   virtual ossimAnnotationObject* nextObject(bool restart=false)
+      {
+         if(restart)
+         {
+            theCurrentObject = theShapeCache.begin();
+         }
+         else
+         {
+            if(theCurrentObject != theShapeCache.end())
+            {
+               ++theCurrentObject;
+            }
+
+         }
+
+         if(theCurrentObject == theShapeCache.end())
+         {
+            return (ossimAnnotationObject*)NULL;
+         }
+         return (*theCurrentObject).second;
+      }
+
+
+   virtual bool saveState(ossimKeywordlist& kwl,
+                          const char* prefix=NULL)const;
+
+   virtual bool loadState(const ossimKeywordlist& kwl,
+                          const char* prefix=NULL);
+protected:
+
+   /*!
+    *  This holds the output projection.  This is used to transform
+    * the objects to the projection plane.
+    */
+   ossimRefPtr<ossimImageGeometry> theImageGeometry;
+
+   /*!
+    * If the shape file is projected we must know the projector.
+    * This will allow us to define the geographic objects correctly.
+    */
+   ossimRefPtr<ossimProjection> theShapeFileProjection;
+
+   /*!
+    * Specifies if its image/pixel space, Geographic, projected ...etc.
+    */
+   ossimCoordinateSystemType theCoordinateSystem;
+
+   /*!
+    * If its projected this spceifies the type of unit.  We
+    * need to know if the projection is in meters, feet, us survey feet
+    * ... etc.
+    */
+   ossimUnitType             theUnitType;
+
+   SHPTree*                  theTree;
+
+   ossimShapeFile            theShapeFile;
+
+   double                    theMinArray[4];
+   double                    theMaxArray[4];
+
+   int                       theMaxQuadTreeLevels;
+   ossimRgbVector            thePenColor;
+   ossimRgbVector            theBrushColor;
+   bool                      theFillFlag;
+   ossim_int32               theThickness;
+   ossimString               theFeatureName;
+   ossimDpt                  thePointWidthHeight;
+   double                    theBorderSize;
+   ossimUnitType             theBorderSizeUnits;
+
+   mutable std::multimap<int, ossimAnnotationObject*>::iterator theCurrentObject;
+
+   std::multimap<int, ossimAnnotationObject*> theShapeCache;
+   ossimDrect theBoundingRect;
+
+   void removeViewProjection();
+   void deleteCache();
+   void checkAndSetDefaultView();
+
+   virtual void loadPolygon(ossimShapeObject& obj);
+   virtual void loadPoint(ossimShapeObject& obj);
+   virtual void loadArc(ossimShapeObject& obj);
+
+TYPE_DATA
+};
+
+#endif
+
diff --git a/ossim_plugins/gdal/ossimGdalDataset.cpp b/ossim_plugins/gdal/ossimGdalDataset.cpp
new file mode 100644
index 0000000..b1c793c
--- /dev/null
+++ b/ossim_plugins/gdal/ossimGdalDataset.cpp
@@ -0,0 +1,306 @@
+//----------------------------------------------------------------------------
+//
+// License:  See top level LICENSE.txt file
+//
+// Author:  David Burken
+//
+// Description: A gdal data set from an ossim image handler.
+//
+//----------------------------------------------------------------------------
+// $Id: ossimGdalDataset.cpp 23003 2014-11-24 17:13:40Z dburken $
+
+
+#include <fstream>
+
+#include <ossimGdalDataset.h>
+#include <ossimGdalType.h>
+#include <ossim/base/ossimFilename.h>
+#include <ossim/base/ossimNotify.h>
+#include <ossim/base/ossimTrace.h>
+#include <ossim/imaging/ossimImageHandler.h>
+#include <ossim/imaging/ossimImageHandlerRegistry.h>
+
+static GDALDriver *poOssimGdalDriver = 0;
+
+static const ossimTrace traceDebug(ossimString("ossimGdalDataset:debug"));
+
+
+CPL_C_START
+void	GDALRegister_ossimGdalDataset(void);
+CPL_C_END
+
+#ifdef OSSIM_ID_ENABLED
+static const char OSSIM_ID[] = "$Id: ossimGdalDataset.cpp 23003 2014-11-24 17:13:40Z dburken $";
+#endif
+
+ossimGdalDataset::ossimGdalDataset()
+   : theImageHandler(0)
+{
+   if (!poOssimGdalDriver)
+   {
+      GDALRegister_ossimGdalDataset();
+      poDriver     = poOssimGdalDriver;
+   }
+      
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimGdalDataset::ossimGdalDataset  entered..."
+         << std::endl;
+#ifdef OSSIM_ID_ENABLED
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "OSSIM_ID:  "
+         << OSSIM_ID
+         << std::endl;
+#endif       
+   }
+}
+
+ossimGdalDataset::~ossimGdalDataset()
+
+{
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimGdalDataset::~ossimGdalDataset "
+         << "\n"
+         << std::endl;
+   }
+
+   if (theImageHandler.valid())
+      theImageHandler = 0;
+}
+
+bool ossimGdalDataset::open(const ossimFilename& file)
+{
+   theImageHandler = ossimImageHandlerRegistry::instance()->open(file);
+   
+   if ( !theImageHandler.valid() )
+   {
+      if (traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG)
+            << "ossimGdalDataset::open DEBUG:"
+            << "\nCould not open:  " << file.c_str() << std::endl;
+      }
+      return false;
+   }
+   
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimGdalDataset::open DEBUG:"
+         << "\nOpened:  " << file.c_str() << std::endl;
+   }
+
+   init();
+   return true;
+}
+
+
+GDALDataset* ossimGdalDataset::Open( GDALOpenInfo * poOpenInfo )
+
+{
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimGdalDataset::Open  entered..."
+         << std::endl;
+   }
+
+   ossimFilename f = poOpenInfo->pszFilename;
+   GDALDataset* ds = new ossimGdalDataset;
+   if ( ((ossimGdalDataset*)ds)->open(f) == true)
+   {
+      return ds;
+   }
+
+   return 0;
+}
+
+void ossimGdalDataset::setImageHandler(ossimImageHandler* ih)
+{
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimGdalDataset::setImageHandler entered..."
+         << std::endl;
+   }
+
+   theImageHandler = ih;
+   init();
+}
+
+const ossimImageHandler* ossimGdalDataset::getImageHandler() const
+{
+   return theImageHandler.get();
+}
+
+ossimImageHandler* ossimGdalDataset::getImageHandler()
+{
+   return theImageHandler.get();
+}
+
+void ossimGdalDataset::initGdalOverviewManager()
+{
+   ossimFilename f = theImageHandler->getFilename();
+   sDescription = f.c_str();
+   
+   if (theImageHandler.valid())
+   {
+      oOvManager.Initialize( this, f.c_str() );
+   }
+}
+
+void ossimGdalDataset::init()
+{
+   nRasterXSize = theImageHandler->getImageRectangle(0).width();
+   nRasterYSize = theImageHandler->getImageRectangle(0).height();
+   nBands       = theImageHandler->getNumberOfOutputBands();
+   eAccess      = GA_ReadOnly;
+   
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+            << "ossimGdalDataset::init DEBUG:"
+            << "\nWidth:  " << nRasterXSize
+            << "\nHeight: " << nRasterYSize
+            << "\nBands:  " << nBands << std::endl;
+   }
+   
+   for( int iBand = 0; iBand < nBands; ++iBand )
+   {
+      ossimGdalDatasetRasterBand* rb =
+         new ossimGdalDatasetRasterBand( this,
+                                         iBand+1,
+                                         theImageHandler.get());
+      SetBand( iBand+1, rb );
+   }
+}
+
+void ossimGdalDataset::setGdalAcces(GDALAccess access)
+{
+   eAccess = access;
+}
+
+ossimGdalDatasetRasterBand::ossimGdalDatasetRasterBand(ossimGdalDataset* ds,
+                                                       int band,
+                                                       ossimImageHandler* ih)
+   : GDALPamRasterBand(),
+     theImageHandler(ih)
+
+{
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimGdalDatasetRasterBand::ossimGdalDatasetRasterBand entered..."
+         << "band: " << band
+         << std::endl;
+   }
+   if (!ih)
+   {
+      return;
+   }
+   
+   poDS     = ds;
+   nBand    = band;
+
+   nRasterXSize     = theImageHandler->getImageRectangle(0).width();
+   nRasterYSize     = theImageHandler->getImageRectangle(0).height();
+   
+   // eAccess  = GA_ReadOnly;
+   eAccess  = GA_Update;
+   
+   ossimGdalType gt;
+   eDataType = gt.toGdal(theImageHandler->getOutputScalarType());
+   
+   nBlockXSize      = theImageHandler->getTileWidth();
+   nBlockYSize      = theImageHandler->getTileHeight();
+
+    // ESH 06/2009: Prevent divide by zero.
+   nBlockXSize      = (nBlockXSize==0) ? 1 : nBlockXSize;
+   nBlockYSize      = (nBlockYSize==0) ? 1 : nBlockYSize;
+   
+   nBlocksPerRow    = nRasterXSize / nBlockXSize;
+   nBlocksPerColumn = nRasterYSize / nBlockYSize;
+   if (nRasterXSize % nBlockXSize) ++nBlocksPerRow;
+   if (nRasterYSize % nBlockYSize) ++nBlocksPerColumn;
+
+   nSubBlocksPerRow = 0;
+   nSubBlocksPerColumn = 0;
+
+   bSubBlockingActive = FALSE;
+   papoBlocks = 0;
+
+   nBlockReads = 0;
+   bForceCachedIO = false;
+}
+
+ossimGdalDatasetRasterBand::~ossimGdalDatasetRasterBand()
+{
+}
+
+CPLErr ossimGdalDatasetRasterBand::IReadBlock(int nBlockXOff,
+                                              int nBlockYOff,
+                                              void * pImage )
+{
+   if ( !theImageHandler.valid() || !pImage)
+   {
+      return CE_Failure;
+   }
+
+   ossimIpt startPt(nBlockXOff*nBlockXSize, nBlockYOff*nBlockYSize);
+//    ossimIpt endPt( min(startPt.x+nBlockXSize-1, nRasterXSize-1),
+//                    min(startPt.y+nBlockYSize-1, nRasterYSize-1));
+   ossimIpt endPt( startPt.x+nBlockXSize-1,
+                   startPt.y+nBlockYSize-1);
+   ossimIrect rect( startPt, endPt);
+
+   ossimRefPtr<ossimImageData> id = theImageHandler->getTile(rect, 0);
+   
+   if (id.valid())
+   {
+      if( (id->getDataObjectStatus() == OSSIM_FULL) ||
+          (id->getDataObjectStatus() == OSSIM_PARTIAL) )
+      {
+         id->unloadBand(pImage, rect, nBand-1);
+         return CE_None;
+      }
+   }
+
+   memset(pImage, 0, nBlockXSize * nBlockYSize);      
+
+   return CE_None;
+}
+
+double ossimGdalDatasetRasterBand::GetNoDataValue( int * /* pbSuccess */)
+
+{
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimGdalDatasetRasterBand::GetNoDataValue entered..."
+         << "\n"
+         << std::endl;
+   }
+
+   return 0.0;
+}
+
+void GDALRegister_ossimGdalDataset()
+
+{
+   GDALDriver	*poDriver;
+   
+   if( poOssimGdalDriver == 0 )
+   {
+      poDriver = new GDALDriver();
+      poOssimGdalDriver = poDriver;
+      
+      poDriver->SetDescription( "ossimGdalDataset" );
+      poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
+                                 "ossim data set" );
+      poDriver->pfnOpen = ossimGdalDataset::Open;
+      GetGDALDriverManager()->RegisterDriver( poDriver );
+   }
+}
diff --git a/ossim_plugins/gdal/ossimGdalDataset.h b/ossim_plugins/gdal/ossimGdalDataset.h
new file mode 100644
index 0000000..506935a
--- /dev/null
+++ b/ossim_plugins/gdal/ossimGdalDataset.h
@@ -0,0 +1,141 @@
+//----------------------------------------------------------------------------
+//
+// License:  See top level LICENSE.txt file
+//
+// Author:  David Burken
+//
+// Description: A gdal data set from an ossim image handler.
+//
+//----------------------------------------------------------------------------
+// $Id: ossimGdalDataset.h 15766 2009-10-20 12:37:09Z gpotts $
+#ifndef ossimGdalDataset_HEADER
+#define ossimGdalDataset_HEADER
+
+
+#include <gdal_pam.h>
+#include <cpl_string.h>
+#include <ossim/base/ossimRefPtr.h>
+#include <ossim/imaging/ossimImageHandler.h>
+
+class ossimGdalDatasetRasterBand;
+class ossimFilename;
+
+/**
+ * @brief ossimGdalDataset This is a gdal data set that wraps an ossim image
+ * handler.
+ *
+ * @note
+ * Currently no write implemented.
+ */
+class ossimGdalDataset : public GDALPamDataset
+{
+public:
+
+   /** @brief default constructor */
+   ossimGdalDataset();
+
+   /** @brief virtual destructor */
+   virtual ~ossimGdalDataset();
+
+   /**
+    * @brief open method.
+    * @param file The file to open.
+    * @return true on success, false on error.
+    */
+   bool open(const ossimFilename& file);
+
+   /**
+    * @brief Open for static gdal driver.
+    */
+   static GDALDataset *Open( GDALOpenInfo * );
+
+   /**
+    * @brief Sets theImageHandler.
+    * @param ih Pointer to image handler.
+    */
+   void setImageHandler(ossimImageHandler* ih);
+
+   /** @return Pointer(const) to the image handler or 0 if not set. */
+   const ossimImageHandler* getImageHandler() const;
+
+   /** @return Pointer(not const) to the image handler or 0 if not set. */
+   ossimImageHandler*       getImageHandler();
+
+   /**
+    * @brief Calls gdal's oOvManager.Initialize.  This must be called if
+    * you are building overviews or the code will fail.
+    */
+   void initGdalOverviewManager();
+
+   /**
+    * @brief Set the access data member.
+    * Either GA_ReadOnly = 0, or GA_Update = 1
+    */
+   void setGdalAcces(GDALAccess access);
+
+private:
+   
+   /**
+    * Initializes this object from the image handler.
+    */
+   void init();
+   
+   friend class ossimGdalDatasetRasterBand;
+
+   ossimRefPtr<ossimImageHandler>  theImageHandler;
+};
+
+/**
+ * @brief ossimGdalDatasetRasterBand Represents a single band within the
+ * image.
+ */
+class ossimGdalDatasetRasterBand : public GDALPamRasterBand
+{
+   friend class ossimGdalDataset;
+   
+public:
+
+   /**
+    * @brief Constructor that takes a ossimGdalDataset, band and image handler.
+    * @param ds The parent data set.
+    * @param band The "ONE" based band.
+    * @param ih The pointer to the image handler.
+    */
+   ossimGdalDatasetRasterBand( ossimGdalDataset* ds,
+                               int band,
+                               ossimImageHandler* ih);
+
+   /** virtual destructor */
+   virtual ~ossimGdalDatasetRasterBand();
+
+   /**
+    * This returns 0 right now and should probably be implemented if anything
+    * serious is to be done with this data set with the gdal library.
+    */
+   virtual double GetNoDataValue( int *pbSuccess = 0 );
+   
+protected:
+
+   /**
+    * @brief Read block method.
+    * 
+    * @param nBlockXOff X Block offset, "0" being upper left sample of image,
+    * 1 being sample at nBlockXOff * nBlockXSize and so on.
+    * 
+    * @param nBlockYOff YBlock offset, "0" being upper left sample of image,
+    * 1 being sample at nBlockYOff * nBlockYSize and so on.
+    *
+    * @param pImage Buffer to put image data in.  Must be at least:
+    * pixel_size_in_bytes * nBlockXSize * nBlockYSize
+    *
+    * @return CE_None on success, CE_Failure on failure.
+    */
+   virtual CPLErr IReadBlock(int nBlockXOff,
+                             int nBlockYOff,
+                             void* pImage);
+
+private:
+   ossimRefPtr<ossimImageHandler> theImageHandler;
+};
+
+#endif /* End of "#ifndef ossimGdalDataset_HEADER" */
diff --git a/ossim_plugins/gdal/ossimGdalFactory.cpp b/ossim_plugins/gdal/ossimGdalFactory.cpp
new file mode 100644
index 0000000..8af005e
--- /dev/null
+++ b/ossim_plugins/gdal/ossimGdalFactory.cpp
@@ -0,0 +1,357 @@
+//*******************************************************************
+// Copyright (C) 2000 ImageLinks Inc.
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author:  Garrett Potts
+//*******************************************************************
+//  $Id: ossimGdalFactory.cpp 23664 2015-12-14 14:17:27Z dburken $
+
+#include <ossimGdalFactory.h>
+#include <ossimGdalTileSource.h>
+#include <ossimOgrGdalTileSource.h>
+#include <ossimOgrVectorTileSource.h>
+#include <ossimHdfReader.h>
+
+#include <ossim/base/ossimKeywordlist.h>
+#include <ossim/base/ossimString.h>
+#include <ossim/imaging/ossimImageHandler.h>
+#include <ossim/base/ossimTrace.h>
+#include <ossim/base/ossimKeywordNames.h>
+
+#include <gdal.h>
+#include <ogrsf_frmts.h>
+
+static const ossimTrace traceDebug("ossimGdalFactory:debug");
+
+RTTI_DEF1(ossimGdalFactory, "ossimGdalFactory", ossimImageHandlerFactoryBase);
+
+ossimGdalFactory* ossimGdalFactory::theInstance = 0;
+ossimGdalFactory::~ossimGdalFactory()
+{
+   theInstance = (ossimGdalFactory*)NULL;
+}
+
+
+ossimGdalFactory* ossimGdalFactory::instance()
+{
+   if(!theInstance)
+   {
+      theInstance = new ossimGdalFactory;
+      CPLSetErrorHandler((CPLErrorHandler)CPLQuietErrorHandler);
+      GDALAllRegister();
+      OGRRegisterAll();
+   }
+
+   // lets turn off gdal error reporting
+   //
+//   GDALSetCacheMax(1024*1024*20);
+//   GDALSetCacheMax(0);
+
+   return theInstance;
+}
+   
+ossimImageHandler* ossimGdalFactory::open(const ossimFilename& fileName,
+                                          bool openOverview)const
+{
+   // For GDAL we can't check for file exists since they support encoded opens for
+   // subdatasets
+   //
+   
+   if(fileName.ext().downcase() == "nui") return 0;
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimGdalFactory::open(filename) DEBUG: entered..." << std::endl;
+   }
+   
+   ossimRefPtr<ossimImageHandler> result;
+
+   //try hdf reader first
+   if (traceDebug())
+   {
+     ossimNotify(ossimNotifyLevel_DEBUG)
+       << "ossimGdalFactory::open(filename) DEBUG:"
+       << "\ntrying ossimHdfReader"
+       << std::endl;
+   }
+   result = new ossimHdfReader;
+   result->setOpenOverviewFlag(openOverview);
+   if(result->open(fileName))
+   {
+     return result.release();
+   }
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimGdalFactory::open(filename) DEBUG:"
+         << "\ntrying ossimGdalTileSource"
+         << std::endl;
+   }
+
+   result = new ossimGdalTileSource;
+   result->setOpenOverviewFlag(openOverview);   
+   if(result->open(fileName))
+   {
+      return result.release();
+   }
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimGdalFactory::open(filename) DEBUG:"
+         << "\ntrying ossimOgrVectorTileSource\n";
+   }
+
+   // No need to set overview flag.
+   result = new ossimOgrVectorTileSource;
+   if(result->open(fileName))
+   {
+     return result.release();
+   }
+   
+   // we will have vector datasets only open if file exists.
+   if(!fileName.exists() || 
+       fileName.before(":", 3).upcase() == "SDE" || 
+       fileName.before(":", 4).upcase() == "GLTP" || 
+       fileName.ext().downcase() == "mdb")
+   {
+      result = 0;
+      return result.release();
+   }
+
+   // No need to set overview flag.
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimGdalFactory::open(filename) DEBUG:"
+         << "\ntrying ossimOgrGdalTileSource\n";
+   }
+   
+   result = new ossimOgrGdalTileSource;
+   if(result->open(fileName))
+   {
+      return result.release();
+   }
+   result = 0;
+   return result.release();
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimGdalFactory::open(filename) DEBUG: leaving..."
+         << std::endl;
+   }
+   
+   return (ossimImageHandler*)NULL;
+}
+
+ossimImageHandler* ossimGdalFactory::open(const ossimKeywordlist& kwl,
+                                          const char* prefix)const
+{
+   ossimRefPtr<ossimImageHandler> result;
+   
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG) << "ossimGdalFactory::open(kwl, prefix) DEBUG: entered..." << std::endl;
+   }
+   if(traceDebug())
+   {
+     ossimNotify(ossimNotifyLevel_DEBUG) << "ossimGdalFactory::open(kwl, prefix) DEBUG: trying ossimHdfReader" << std::endl;
+   }
+   result = new ossimHdfReader;
+   if(result->loadState(kwl, prefix))
+   {
+     return result.release();
+   }
+   result = 0;
+   
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG) << "ossimGdalFactory::open(kwl, prefix) DEBUG: trying ossimGdalTileSource" << std::endl;
+   }
+   result = new ossimGdalTileSource;
+   if(result->loadState(kwl, prefix))
+   {
+      return result.release();
+   }
+   result = 0;
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG) << "ossimGdalFactory::open(kwl, prefix) DEBUG: trying ossimOgrGdalTileSource" << std::endl;
+   }
+   
+   result = new ossimOgrGdalTileSource;
+   if(result->loadState(kwl, prefix))
+   {
+      return result.release();
+   }
+   result = 0;
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG) << "ossimGdalFactory::open(kwl, prefix) DEBUG: leaving..." << std::endl;
+   }
+   
+   return result.release();
+}
+
+ossimRefPtr<ossimImageHandler> ossimGdalFactory::openOverview(
+   const ossimFilename& file ) const
+{
+   ossimRefPtr<ossimImageHandler> result = 0;
+   if ( file.size() )
+   {
+      result = new ossimGdalTileSource;
+      
+      result->setOpenOverviewFlag( false ); // Always false.
+
+      if ( result->open( file ) == false )
+      {
+         result = 0;
+      }
+   }
+   return result;
+}
+
+ossimObject* ossimGdalFactory::createObject(const ossimString& typeName)const
+{
+   if(STATIC_TYPE_NAME(ossimHdfReader) == typeName)
+   {
+     return new ossimHdfReader();
+   }
+   if(STATIC_TYPE_NAME(ossimGdalTileSource) == typeName)
+   {
+      return new ossimGdalTileSource();
+   }
+   if(STATIC_TYPE_NAME(ossimOgrGdalTileSource) == typeName)
+   {
+      return new ossimOgrGdalTileSource();
+   }
+   
+   return (ossimObject*)0;
+}
+
+ossimObject* ossimGdalFactory::createObject(const ossimKeywordlist& kwl,
+                                            const char* prefix)const
+{
+   ossimRefPtr<ossimObject> result;
+   const char* type = kwl.find(prefix, ossimKeywordNames::TYPE_KW);
+
+   if(type)
+   {
+      if (ossimString(type).trim() == STATIC_TYPE_NAME(ossimImageHandler))
+      {
+         const char* lookup = kwl.find(prefix, ossimKeywordNames::FILENAME_KW);
+         if (lookup)
+         {
+            // Call the open that takes a filename...
+            result = this->open(kwl, prefix);//ossimFilename(lookup));
+         }
+      }
+      else
+      {
+         result = createObject(ossimString(type));
+         if(result.valid())
+         {
+            result->loadState(kwl, prefix);
+         }
+      }
+   }
+
+   return result.release();
+}
+ 
+void ossimGdalFactory::getTypeNameList(std::vector<ossimString>& typeList)const
+{
+   typeList.push_back(STATIC_TYPE_NAME(ossimHdfReader));
+   typeList.push_back(STATIC_TYPE_NAME(ossimGdalTileSource));
+   typeList.push_back(STATIC_TYPE_NAME(ossimOgrGdalTileSource));
+}
+
+void ossimGdalFactory::getSupportedExtensions(ossimImageHandlerFactoryBase::UniqueStringList& extensionList)const
+{
+   // ossimOgrGdalTileSource - shape file reader:
+   extensionList.push_back( ossimString("shp") );
+   
+   int driverCount = GDALGetDriverCount();
+   int idx = 0;
+   
+   for(idx = 0; idx < driverCount; ++idx)
+   {
+      GDALDriverH driver =  GDALGetDriver(idx);  
+      
+      if(driver)
+      {
+         const char* metaData = GDALGetMetadataItem(driver, GDAL_DMD_EXTENSION, 0);
+         int nMetaData = metaData ? strlen(metaData) : 0;
+         if(metaData && nMetaData>0 )
+         {
+            std::vector<ossimString> splitArray;
+            ossimString(metaData).split(splitArray, " /");
+
+            ossim_uint32 idxExtension = 0;
+
+            for(idxExtension = 0; idxExtension < splitArray.size(); ++idxExtension)
+            {
+               extensionList.push_back(splitArray[idxExtension].downcase());
+            }
+         }
+      }
+   }
+
+   if(GDALGetDriverByName("AAIGrid"))
+   {
+      extensionList.push_back("adf");
+   }
+}
+
+void ossimGdalFactory::getImageHandlersBySuffix(
+   ossimImageHandlerFactoryBase::ImageHandlerList& result, const ossimString& ext) const
+{
+   if ( ext == "shp" )
+   {
+      result.push_back(new ossimOgrGdalTileSource);
+   }
+   else
+   {
+      ossimImageHandlerFactoryBase::UniqueStringList extList;
+      getSupportedExtensions(extList);
+      
+      ossimString testExt = ext.downcase();
+      
+      if(std::find(extList.getList().begin(),
+                   extList.getList().end(), testExt) != extList.getList().end())
+      {
+         result.push_back(new ossimGdalTileSource);
+      }
+   }
+}
+
+void ossimGdalFactory::getImageHandlersByMimeType(ossimImageHandlerFactoryBase::ImageHandlerList& result, const ossimString& mimeType)const
+{
+   int driverCount = GDALGetDriverCount();
+   int idx = 0;
+   
+   for(idx = 0; idx < driverCount; ++idx)
+   {
+      GDALDriverH driver =  GDALGetDriver(idx);  
+      
+      if(driver)
+      {
+         const char* metaData = GDALGetMetadataItem(driver, GDAL_DMD_MIMETYPE, 0);
+         int nMetaData = metaData ? strlen(metaData) : 0;
+         if(metaData && nMetaData>0 )
+         {
+            if(ossimString(metaData) == mimeType)
+            {
+               result.push_back(new ossimGdalTileSource());
+               return;
+            }
+         }
+      }
+   }
+}
+
+
diff --git a/ossim_plugins/gdal/ossimGdalFactory.h b/ossim_plugins/gdal/ossimGdalFactory.h
new file mode 100644
index 0000000..74efa16
--- /dev/null
+++ b/ossim_plugins/gdal/ossimGdalFactory.h
@@ -0,0 +1,84 @@
+//*******************************************************************
+// Copyright (C) 2000 ImageLinks Inc.
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author:  Garrett Potts
+//*******************************************************************
+// $Id: ossimGdalFactory.h 23664 2015-12-14 14:17:27Z dburken $
+
+#ifndef ossimGdalFactory_HEADER
+#define ossimGdalFactory_HEADER 1
+
+#include <ossim/imaging/ossimImageHandlerFactoryBase.h>
+#include <ossim/base/ossimString.h>
+
+class ossimGdal;
+class ossimFilename;
+class ossimKeywordlist;
+
+//*******************************************************************
+// CLASS:  ossimGdalFactory
+//*******************************************************************
+class ossimGdalFactory : public ossimImageHandlerFactoryBase
+{
+public:
+   virtual ~ossimGdalFactory();
+   static ossimGdalFactory* instance();
+   
+   /**
+    * @brief open that takes a filename.
+    * @param fileName File to open.
+    * @param trySuffixFirst If true calls code to try to open by suffix first,
+    * then goes through the list of available handlers. default=true.
+    * @param openOverview If true image handler will attempt to open overview.
+    * default = true
+    * @return Pointer to image handler or null if cannot open.
+    */
+   virtual ossimImageHandler* open(const ossimFilename& fileName,
+                                   bool openOverview=true)const;
+   virtual ossimImageHandler* open(const ossimKeywordlist& kwl,
+                                   const char* prefix=0)const;
+
+   /**
+    * @brief Open overview that takes a file name.
+    *
+    * @param file File to open.
+    *
+    * @return ossimRefPtr to image handler on success or null on failure.
+    */
+   virtual ossimRefPtr<ossimImageHandler> openOverview(
+      const ossimFilename& file ) const;
+   
+   virtual ossimObject* createObject(const ossimString& typeName)const;
+   
+   /*!
+    * Creates and object given a keyword list.
+    */
+   virtual ossimObject* createObject(const ossimKeywordlist& kwl,
+                                     const char* prefix=0)const;
+   
+   /*!
+    * This should return the type name of all objects in all factories.
+    * This is the name used to construct the objects dynamially and this
+    * name must be unique.
+    */
+   virtual void getTypeNameList(std::vector<ossimString>& typeList)const;
+   virtual void getSupportedExtensions(ossimImageHandlerFactoryBase::UniqueStringList& extensionList)const;
+   virtual void getImageHandlersBySuffix(ossimImageHandlerFactoryBase::ImageHandlerList& result, const ossimString& ext)const;
+   virtual void getImageHandlersByMimeType(ossimImageHandlerFactoryBase::ImageHandlerList& result, const ossimString& mimeType)const;
+  
+protected:
+   ossimGdalFactory(){}
+   ossimGdalFactory(const ossimGdalFactory&){}
+   void operator = (const ossimGdalFactory&){}
+
+   static ossimGdalFactory* theInstance;
+
+TYPE_DATA
+};
+
+#endif
+
diff --git a/ossim_plugins/gdal/ossimGdalImageWriterFactory.cpp b/ossim_plugins/gdal/ossimGdalImageWriterFactory.cpp
new file mode 100644
index 0000000..00f4b1d
--- /dev/null
+++ b/ossim_plugins/gdal/ossimGdalImageWriterFactory.cpp
@@ -0,0 +1,201 @@
+//*******************************************************************
+// Copyright (C) 2000 ImageLinks Inc.
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author:  Garrett Potts
+//
+//*******************************************************************
+//  $Id: ossimGdalImageWriterFactory.cpp 23664 2015-12-14 14:17:27Z dburken $
+
+#include "ossimGdalImageWriterFactory.h"
+#include "ossimGdalWriter.h"
+#include <ossim/base/ossimKeywordNames.h>
+
+ossimGdalImageWriterFactory* ossimGdalImageWriterFactory::theInstance = (ossimGdalImageWriterFactory*)NULL;
+
+
+ossimGdalImageWriterFactory* ossimGdalImageWriterFactory::instance()
+{
+   if(!theInstance)
+   {
+      theInstance = new ossimGdalImageWriterFactory;
+   }
+
+   return theInstance;
+}
+
+ossimGdalImageWriterFactory::~ossimGdalImageWriterFactory()
+{
+   theInstance = (ossimGdalImageWriterFactory*)NULL;
+}
+
+ossimImageFileWriter*
+ossimGdalImageWriterFactory::createWriter(const ossimKeywordlist& kwl,
+                                          const char *prefix)const
+{
+   ossimString type = kwl.find(prefix, ossimKeywordNames::TYPE_KW);
+   ossimImageFileWriter* result = (ossimImageFileWriter*)NULL;
+   if(type != "")
+   {
+      result = createWriter(type);
+      if (result)
+      {
+         if (result->hasImageType(type))
+         {
+            ossimKeywordlist kwl2(kwl);
+            kwl2.add(prefix,
+                     ossimKeywordNames::IMAGE_TYPE_KW,
+                     type,
+                     true);
+         
+            result->loadState(kwl2, prefix);
+         }
+         else
+         {
+            result->loadState(kwl, prefix);
+         }
+      }
+   }
+
+   return result;
+}
+
+ossimImageFileWriter* ossimGdalImageWriterFactory::createWriter(const ossimString& typeName)const
+{
+   ossimRefPtr<ossimGdalWriter> writer = new ossimGdalWriter;
+   if (writer->getClassName() == typeName)
+   {
+      return writer.release();
+   }
+
+   if (writer->hasImageType(typeName))
+   {
+      writer->setOutputImageType(typeName);
+      return writer.release();
+   }
+
+   writer = 0;
+   
+   return writer.release();
+}
+
+ossimObject* ossimGdalImageWriterFactory::createObject(const ossimKeywordlist& kwl,
+                                                   const char *prefix)const
+{
+   return createWriter(kwl, prefix);
+}
+
+ossimObject* ossimGdalImageWriterFactory::createObject(const ossimString& typeName)const
+{
+   return createWriter(typeName);
+}
+
+
+void ossimGdalImageWriterFactory::getExtensions(std::vector<ossimString>& result)const
+{
+   result.push_back("img");
+   result.push_back("jp2");
+   result.push_back("png");
+}
+
+void ossimGdalImageWriterFactory::getTypeNameList(std::vector<ossimString>& typeList)const
+{
+   getImageTypeList(typeList);
+}
+
+void ossimGdalImageWriterFactory::getImageTypeList(std::vector<ossimString>& imageTypeList)const
+{
+   ossimGdalWriter* writer = new ossimGdalWriter;
+   writer->getImageTypeList(imageTypeList);
+   delete writer;
+}
+
+void ossimGdalImageWriterFactory::getImageFileWritersBySuffix(ossimImageWriterFactoryBase::ImageFileWriterList& result,
+                                                              const ossimString& ext)const
+{
+   int c = GDALGetDriverCount();
+   int idx = 0;
+   for(idx = 0; idx < c; ++idx)
+   {
+      
+      GDALDriverH h = GDALGetDriver(idx);
+      if(canWrite(h))
+      {
+         ossimString  driverName = GDALGetDriverShortName(h);
+         driverName = "gdal_" + driverName.upcase();
+         ossimString metaData(GDALGetMetadataItem(h, GDAL_DMD_EXTENSION, 0));
+         if(!metaData.empty())
+         {
+            std::vector<ossimString> splitArray;
+            metaData.split(splitArray, " /");
+            
+            ossim_uint32 idxExtension = 0;
+            
+            for(idxExtension = 0; idxExtension < splitArray.size(); ++idxExtension)
+            {
+               if(ext == splitArray[idxExtension])
+               {
+                  ossimGdalWriter* writer = new ossimGdalWriter;
+                  writer->setOutputImageType(driverName);
+                  result.push_back(writer);
+                  if ( driverName == "gdal_JP2KAK" )
+                  {
+                     // Make it lossless for starters.  User can still override.
+                     ossimKeywordlist kwl;
+                     kwl.add("property0.name", "QUALITY");
+                     kwl.add("property0.value", "100");
+                     writer->loadState(kwl, NULL);
+                  }
+                  return;
+               }
+            }
+         }
+      }
+   }
+}
+
+void ossimGdalImageWriterFactory::getImageFileWritersByMimeType(ossimImageWriterFactoryBase::ImageFileWriterList& result,
+                                                                const ossimString& mimeType)const
+{
+   int c = GDALGetDriverCount();
+   int idx = 0;
+   for(idx = 0; idx < c; ++idx)
+   {
+      
+      GDALDriverH h = GDALGetDriver(idx);
+      if(canWrite(h))
+      {
+         ossimString  driverName = GDALGetDriverShortName(h);
+         driverName = "gdal_" + driverName.upcase();
+         ossimString metaData(GDALGetMetadataItem(h, GDAL_DMD_MIMETYPE, 0));
+         if(!metaData.empty())
+         {
+            if(metaData == mimeType)
+            {
+               ossimGdalWriter* writer = new ossimGdalWriter;
+               writer->setOutputImageType(driverName);
+               result.push_back(writer);
+               if ( driverName == "gdal_JP2KAK" )
+               {
+                  // Make it lossless for starters.  User can still override.
+                  ossimKeywordlist kwl;
+                  kwl.add("property0.name", "QUALITY");
+                  kwl.add("property0.value", "100");
+                  writer->loadState(kwl, NULL);
+               }
+               return;
+            }
+         }
+      }
+   }
+}
+
+bool ossimGdalImageWriterFactory::canWrite(GDALDatasetH handle)const
+{
+   return ( GDALGetMetadataItem(handle, GDAL_DCAP_CREATE, 0)||  GDALGetMetadataItem(handle, GDAL_DCAP_CREATECOPY, 0));
+}
+
+
diff --git a/ossim_plugins/gdal/ossimGdalImageWriterFactory.h b/ossim_plugins/gdal/ossimGdalImageWriterFactory.h
new file mode 100644
index 0000000..84788aa
--- /dev/null
+++ b/ossim_plugins/gdal/ossimGdalImageWriterFactory.h
@@ -0,0 +1,70 @@
+//*******************************************************************
+// Copyright (C) 2000 ImageLinks Inc.
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author:  Garrett Potts
+//
+//*******************************************************************
+//  $Id: ossimGdalImageWriterFactory.h 23664 2015-12-14 14:17:27Z dburken $
+
+#ifndef ossimGdalImageWriterFactory_HEADER
+#define ossimGdalImageWriterFactory_HEADER
+#include <ossim/imaging/ossimImageWriterFactoryBase.h>
+#include <gdal.h>
+class ossimImageFileWriter;
+class ossimKeywordlist;
+class ossimImageWriterFactory;
+
+class ossimGdalImageWriterFactory: public ossimImageWriterFactoryBase
+{   
+public:
+   virtual ~ossimGdalImageWriterFactory();
+   static ossimGdalImageWriterFactory* instance();
+   virtual ossimImageFileWriter* createWriter(const ossimKeywordlist& kwl,
+                                              const char *prefix=0)const;
+   virtual ossimImageFileWriter* createWriter(const ossimString& typeName)const;
+   
+   virtual ossimObject* createObject(const ossimKeywordlist& kwl,
+                                     const char *prefix=0)const;
+   virtual ossimObject* createObject(const ossimString& typeName)const;
+   
+   virtual void getExtensions(std::vector<ossimString>& result)const;
+   
+   virtual void getTypeNameList(std::vector<ossimString>& typeList)const;
+   
+   /**
+    * void getImageTypeList(std::vector<ossimString>& imageTypeList)const
+    *
+    * Appends this writer image types to list "imageTypeList".
+    *
+    * This writer can have the following types dependent upon how the gdal
+    * library was compiled:
+    * gdal_imagine_hfa
+    * gdal_nitf_rgb_band_separate
+    * gdal_jpeg2000
+    * gdal_arc_info_aig
+    * gdal_arc_info_gio
+    * gdal_arc_info_ascii_grid
+    *
+    * @param imageTypeList stl::vector<ossimString> list to append to.
+    */
+   virtual void getImageTypeList(std::vector<ossimString>& imageTypeList)const;
+   
+   virtual void getImageFileWritersBySuffix(ossimImageWriterFactoryBase::ImageFileWriterList& result,
+                                            const ossimString& ext)const;
+   virtual void getImageFileWritersByMimeType(ossimImageWriterFactoryBase::ImageFileWriterList& result,
+                                              const ossimString& mimeType)const;
+protected:
+   ossimGdalImageWriterFactory() {theInstance = this;}
+
+   static ossimGdalImageWriterFactory* theInstance;
+   
+   ossimString convertToDriverName(const ossimString& imageTypeName)const;
+   bool canWrite(GDALDatasetH handle)const;
+};
+
+#endif
+
diff --git a/ossim_plugins/gdal/ossimGdalInfoFactory.cpp b/ossim_plugins/gdal/ossimGdalInfoFactory.cpp
new file mode 100644
index 0000000..a831d36
--- /dev/null
+++ b/ossim_plugins/gdal/ossimGdalInfoFactory.cpp
@@ -0,0 +1,63 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author:  Mingjie Su
+//
+// Description: Factory for Ogr info objects.
+// 
+//----------------------------------------------------------------------------
+// $Id: ossimGdalInfoFactory.cpp 2645 2011-05-26 15:21:34Z oscar.kramer $
+
+#include <ossimGdalInfoFactory.h>
+#include <ossimOgrInfo.h>
+#include <ossimHdfInfo.h>
+
+#include <ossim/support_data/ossimInfoFactory.h>
+#include <ossim/support_data/ossimInfoBase.h>
+#include <ossim/base/ossimFilename.h>
+#include <ossim/base/ossimRefPtr.h>
+
+ossimGdalInfoFactory::~ossimGdalInfoFactory()
+{}
+
+ossimGdalInfoFactory* ossimGdalInfoFactory::instance()
+{
+   static ossimGdalInfoFactory sharedInstance;
+
+   return &sharedInstance;
+}
+
+ossimInfoBase* ossimGdalInfoFactory::create(const ossimFilename& file) const
+{
+   // Test hdf...
+   ossimRefPtr<ossimInfoBase> result = 0;
+   result = new ossimHdfInfo();
+   if ( result->open(file) )
+   {
+      return result.release();
+   }
+
+   // Test ogr...
+   result = new ossimOgrInfo();
+   if ( result->open(file) )
+   {
+      return result.release();
+   }
+   return 0;
+}
+
+ossimGdalInfoFactory::ossimGdalInfoFactory()
+{}
+
+ossimGdalInfoFactory::ossimGdalInfoFactory(const ossimGdalInfoFactory& /* obj */ )
+{}
+
+const ossimGdalInfoFactory& ossimGdalInfoFactory::operator=(
+   const ossimGdalInfoFactory& /* rhs */)
+{
+   return *this;
+}
+
diff --git a/ossim_plugins/gdal/ossimGdalInfoFactory.h b/ossim_plugins/gdal/ossimGdalInfoFactory.h
new file mode 100644
index 0000000..af40413
--- /dev/null
+++ b/ossim_plugins/gdal/ossimGdalInfoFactory.h
@@ -0,0 +1,58 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author:  Mingjie Su
+//
+// Description: Info factory for gdal info objects.
+// 
+//----------------------------------------------------------------------------
+// $Id: ossimGdalInfoFactory.h 539 2010-02-23 20:32:45Z ming.su $
+
+#ifndef ossimGdalInfoFactory_HEADER
+#define ossimGdalInfoFactory_HEADER 1
+
+#include <ossim/base/ossimConstants.h>
+#include <ossim/support_data/ossimInfoFactoryInterface.h>
+
+class ossimFilename;
+class ossimInfoBase;
+
+/**
+ * @brief Info factory.
+ */
+class ossimGdalInfoFactory : public ossimInfoFactoryInterface
+{
+public:
+
+   /** virtual destructor */
+   virtual ~ossimGdalInfoFactory();
+
+   static ossimGdalInfoFactory* instance();
+
+   /**
+    * @brief create method.
+    *
+    * @param file Some file you want info for.
+    *
+    * @return ossimInfoBase* on success 0 on failure.  Caller is responsible
+    * for memory.
+    */
+   virtual ossimInfoBase* create(const ossimFilename& file) const;
+   
+private:
+   
+   /** hidden from use default constructor */
+   ossimGdalInfoFactory();
+
+   /** hidden from use copy constructor */
+   ossimGdalInfoFactory(const ossimGdalInfoFactory& obj);
+
+   /** hidden from use operator = */
+   const ossimGdalInfoFactory& operator=(const ossimGdalInfoFactory& rhs);
+};
+
+#endif /* End of "#ifndef ossimGdalInfoFactory_HEADER" */
+
diff --git a/ossim_plugins/gdal/ossimGdalObjectFactory.cpp b/ossim_plugins/gdal/ossimGdalObjectFactory.cpp
new file mode 100644
index 0000000..dfdc61d
--- /dev/null
+++ b/ossim_plugins/gdal/ossimGdalObjectFactory.cpp
@@ -0,0 +1,96 @@
+//----------------------------------------------------------------------------
+//
+// License:  See top level LICENSE.txt file
+//
+// Author:  David Burken
+//
+// Description: Factory for OSSIM objects from the gdal plugin.
+//----------------------------------------------------------------------------
+
+#include <ossimGdalObjectFactory.h>
+#include <ossimShapeDatabase.h>
+#include <ossimShapeFile.h>
+#include <ossimEsriShapeFileFilter.h>
+
+RTTI_DEF1(ossimGdalObjectFactory,
+          "ossimGdalObjectFactory",
+          ossimObjectFactory);
+
+ossimGdalObjectFactory* ossimGdalObjectFactory::theInstance = 0;
+
+ossimGdalObjectFactory* ossimGdalObjectFactory::instance()
+{
+   if ( !theInstance )
+   {
+      theInstance = new ossimGdalObjectFactory();
+   }
+   return theInstance;
+}
+
+ossimGdalObjectFactory::~ossimGdalObjectFactory()
+{}
+
+ossimObject* ossimGdalObjectFactory::createObject(
+   const ossimString& typeName)const
+{
+   ossimObject* result = 0;
+
+   if (typeName == "ossimShapeFile")
+   {
+      result = new ossimShapeFile();
+   }
+   else if (typeName == "ossimShapeDatabase")
+   {
+      result = new ossimShapeDatabase();
+   }
+   else if (typeName == "ossimEsriShapeFileFilter")
+   {
+      result = new ossimEsriShapeFileFilter();
+   }
+   
+   return result;
+   
+}
+
+ossimObject* ossimGdalObjectFactory::createObject(const ossimKeywordlist& kwl,
+                                                  const char* prefix)const
+{
+   ossimObject* result = 0;
+
+   const char* type = kwl.find(prefix, "type");
+   if(type)
+   {
+      result = createObject(ossimString(type));
+      if(result)
+      {
+         result->loadState(kwl, prefix);
+      }
+   }
+
+   return result; 
+}
+   
+void ossimGdalObjectFactory::getTypeNameList(
+   std::vector<ossimString>& typeList)const
+{
+   typeList.push_back(ossimString("ossimShapeFile"));
+   typeList.push_back(ossimString("ossimShapeDatabase"));
+   typeList.push_back(ossimString("ossimEsriShapeFileFilter"));
+}
+
+ossimGdalObjectFactory::ossimGdalObjectFactory()
+   : ossimObjectFactory()
+{
+}
+
+ossimGdalObjectFactory::ossimGdalObjectFactory(
+   const ossimGdalObjectFactory& /* rhs */)
+   : ossimObjectFactory()
+{
+}
+
+const ossimGdalObjectFactory& ossimGdalObjectFactory::operator=(
+   const ossimGdalObjectFactory& /* rhs */ )
+{
+   return *this;
+}
diff --git a/ossim_plugins/gdal/ossimGdalObjectFactory.h b/ossim_plugins/gdal/ossimGdalObjectFactory.h
new file mode 100644
index 0000000..d2856d0
--- /dev/null
+++ b/ossim_plugins/gdal/ossimGdalObjectFactory.h
@@ -0,0 +1,61 @@
+//----------------------------------------------------------------------------
+//
+// License:  See top level LICENSE.txt file
+//
+// Author:  David Burken
+//
+// Description: Factory for OSSIM objects from the gdal plugin.
+//----------------------------------------------------------------------------
+// $Id: ossimGdalObjectFactory.h 10110 2006-12-14 18:20:54Z dburken $
+#ifndef ossimGdalObjectFactory_HEADER
+#define ossimGdalObjectFactory_HEADER 1
+
+#include <ossimPluginConstants.h>
+#include <ossim/base/ossimRtti.h>
+#include <ossim/base/ossimObjectFactory.h>
+
+class OSSIM_PLUGINS_DLL ossimGdalObjectFactory : public ossimObjectFactory
+{
+public:
+
+   static ossimGdalObjectFactory* instance();
+
+   /** virtual destructor */
+   virtual ~ossimGdalObjectFactory();
+
+   /**
+    * @brief Object from string.
+    * @return Pointer to object or 0 if not in this factory.
+    */
+   virtual ossimObject* createObject(const ossimString& typeName)const;
+
+   /**
+    * @brief Object from keyword list.
+    * @return Pointer to object or 0 if not in this factory.
+    */
+   virtual ossimObject* createObject(const ossimKeywordlist& kwl,
+                                     const char* prefix=0)const;
+   
+   /**
+    * @brief Adds list of objects this factory supports.
+    */
+   virtual void getTypeNameList(std::vector<ossimString>& typeList)const;
+   
+private:
+
+   /** hidden from use default construtor. */
+   ossimGdalObjectFactory();
+
+   /** hidden from use copy construtor. */
+   ossimGdalObjectFactory(const ossimGdalObjectFactory& rhs);
+
+   /** hidden from use operator= . */
+   const ossimGdalObjectFactory& operator=(const ossimGdalObjectFactory& rhs);
+
+   /** The single instance of this class. */
+   static ossimGdalObjectFactory* theInstance;
+
+TYPE_DATA
+};
+
+#endif /* #ifndef ossimGdalObjectFactory_HEADER */
diff --git a/ossim_plugins/gdal/ossimGdalOgrVectorAnnotation.cpp b/ossim_plugins/gdal/ossimGdalOgrVectorAnnotation.cpp
new file mode 100644
index 0000000..375d106
--- /dev/null
+++ b/ossim_plugins/gdal/ossimGdalOgrVectorAnnotation.cpp
@@ -0,0 +1,2544 @@
+//*******************************************************************
+// License:  See top level LICENSE.txt file.
+//
+// Author:  Garrett Potts
+//
+//*******************************************************************
+//  $Id: ossimGdalOgrVectorAnnotation.cpp 22897 2014-09-25 16:16:13Z dburken $
+
+#include <ossimGdalOgrVectorAnnotation.h>
+#include <ossimOgcWktTranslator.h>
+#include <ossimGdalType.h>
+#include <ossimOgcWktTranslator.h>
+#include <ossim/base/ossimTrace.h>
+#include <ossim/base/ossimPreferences.h>
+#include <ossim/base/ossimColorProperty.h>
+#include <ossim/base/ossimBooleanProperty.h>
+#include <ossim/base/ossimTextProperty.h>
+#include <ossim/base/ossimNumericProperty.h>
+#include <ossim/base/ossimNotify.h>
+#include <ossim/base/ossimIpt.h>
+#include <ossim/base/ossimDpt.h>
+#include <ossim/base/ossimGeoPolygon.h>
+#include <ossim/base/ossimFilename.h>
+#include <ossim/base/ossimKeywordlist.h>
+#include <ossim/base/ossimKeywordNames.h>
+#include <ossim/imaging/ossimImageData.h>
+#include <ossim/imaging/ossimAnnotationLineObject.h>
+#include <ossim/imaging/ossimAnnotationMultiLineObject.h>
+#include <ossim/imaging/ossimAnnotationPolyObject.h>
+#include <ossim/imaging/ossimGeoAnnotationPolyObject.h>
+#include <ossim/imaging/ossimGeoAnnotationPolyLineObject.h>
+#include <ossim/imaging/ossimGeoAnnotationEllipseObject.h>
+#include <ossim/imaging/ossimGeoAnnotationMultiEllipseObject.h>
+#include <ossim/imaging/ossimGeoAnnotationMultiPolyObject.h>
+#include <ossim/base/ossimPolyLine.h>
+#include <ossim/base/ossimCommon.h>
+#include <ossim/base/ossimErrorContext.h>
+#include <ossim/imaging/ossimRgbImage.h>
+#include <ossim/projection/ossimProjectionFactoryRegistry.h>
+#include <ossim/projection/ossimProjection.h>
+#include <ossim/projection/ossimEquDistCylProjection.h>
+#include <ossim/projection/ossimImageProjectionModel.h>
+#include <ossim/base/ossimUnitTypeLut.h>
+#include <ossim/base/ossimUnitConversionTool.h>
+#include <ossim/support_data/ossimFgdcXmlDoc.h>
+#include <ogr_api.h>
+#include <sstream>
+
+RTTI_DEF2(ossimGdalOgrVectorAnnotation,
+          "ossimGdalOgrVectorAnnotation",
+          ossimAnnotationSource,
+          ossimViewInterface);
+
+static ossimOgcWktTranslator wktTranslator;
+static ossimTrace traceDebug("ossimGdalOgrVectorAnnotation:debug");
+
+static const char SHAPEFILE_COLORS_AUTO_KW[] =
+   "shapefile_colors_auto";
+
+static const char NORMALIZED_RGB_BRUSH_COLOR_KW[] =
+   "shapefile_normalized_rgb_brush_color";
+
+static const char NORMALIZED_RGB_PEN_COLOR_KW[] =
+   "shapefile_normalized_rgb_pen_color";
+
+static const char POINT_SIZE_KW[] =
+   "shapefile_point_size";
+
+
+bool doubleLess(double first, double second, double epsilon, bool orequal = false) 
+{
+   if (fabs(first - second) < epsilon) 
+   {
+      return (orequal);
+   }
+   return (first < second);
+}
+
+bool doubleGreater(double first, double second, double epsilon, bool orequal = false) 
+{
+   if (fabs(first - second) < epsilon) 
+   {
+      return (orequal);
+   }
+   return (first > second);
+}
+
+/** container class for rgb value. */
+class ossimRgbColor
+{
+public:
+   /** Default constructor (green) */
+   ossimRgbColor() : r(1), g(255), b(1) {}
+
+   /** Constructor that takes an rgb. */
+   ossimRgbColor(ossim_uint8 r, ossim_uint8 g, ossim_uint8 b)
+      : r(r), g(g), b(b) {}
+   
+   ossim_uint8 r;
+   ossim_uint8 g;
+   ossim_uint8 b;
+};
+
+// The index of the current color.
+static ossim_uint32 currentAutoColorArrayIndex = 0;
+
+// Array count of colors.
+static const ossim_uint32 AUTO_COLOR_ARRAY_COUNT = 9;
+
+// Static array to index for auto colors.
+static const ossimRgbColor autoColorArray[AUTO_COLOR_ARRAY_COUNT] =
+{
+   ossimRgbColor(255,   1,   1), // red
+   ossimRgbColor(  1, 255,   1), // green
+   ossimRgbColor(  1,   1, 255), // blue
+   
+   ossimRgbColor(1,   255, 255),  // cyan
+   ossimRgbColor(255,   1, 255),  // magenta
+   ossimRgbColor(255, 255,   1),  // yellow
+
+   ossimRgbColor(255, 165,   1), // orange
+   ossimRgbColor(160,  32, 240), // purple
+   ossimRgbColor(238, 130, 238) // violet
+};
+
+class ossimOgrGdalFeatureNode
+{
+public:
+   ossimOgrGdalFeatureNode(long id,
+                           const ossimDrect& rect)
+      :theId(id),
+       theBoundingRect(rect)
+      {
+      }
+                           
+   bool intersects(const ossimDrect& rect)const
+      {
+         return theBoundingRect.intersects(rect);
+      }
+   bool intersects(double minX, double minY,
+                   double maxX, double maxY)const
+      {
+         return theBoundingRect.intersects(ossimDrect(minX, minY, maxX, maxY));
+      }
+   long theId;
+   ossimDrect theBoundingRect;
+};
+
+class ossimOgrGdalLayerNode
+{
+public:
+   ossimOgrGdalLayerNode(const ossimDrect& bounds)
+      : theBoundingRect(bounds)
+      {
+      }
+   bool intersects(const ossimDrect& rect)const
+      {
+         return theBoundingRect.intersects(rect);
+      }
+   bool intersects(double minX, double minY,
+                   double maxX, double maxY)const
+      {
+         return theBoundingRect.intersects(ossimDrect(minX, minY, maxX, maxY));
+      }
+   void getIdList(std::list<long>& idList,
+                  const ossimDrect& aoi)const;
+   std::vector<ossimOgrGdalFeatureNode> theFeatureList;
+
+   ossimDrect theBoundingRect;
+};
+void ossimOgrGdalLayerNode::getIdList(std::list<long>& idList,
+                                      const ossimDrect& aoi)const
+{
+   if(!intersects(aoi))
+   {
+      return;
+   }
+   if(theBoundingRect.completely_within(aoi))
+   {
+      for(ossim_uint32 i = 0; i < theFeatureList.size(); ++i)
+      {
+         idList.push_back(theFeatureList[i].theId);
+      }
+   }
+   else
+   {
+      for(ossim_uint32 i = 0; i < theFeatureList.size(); ++i)
+      {
+         if(theFeatureList[i].intersects(aoi))
+         {
+            idList.push_back(theFeatureList[i].theId);
+         }
+      }
+   }
+}
+
+ossimGdalOgrVectorAnnotation::ossimGdalOgrVectorAnnotation(ossimImageSource* inputSource)
+   :ossimAnnotationSource(inputSource),
+    ossimViewInterface(),
+    theDataSource(0),
+    theDriver(0),
+    theFilename(),
+    theBoundingExtent(),
+    theLayersToRenderFlagList(),
+    theLayerTable(),
+    thePenColor(255,255,255),
+    theBrushColor(255,255,255),
+    theFillFlag(false),
+    theThickness(1),
+    thePointWidthHeight(1, 1),
+    theBorderSize(0.0),
+    theBorderSizeUnits(OSSIM_DEGREES),
+    theImageBound(),
+    theIsExternalGeomFlag(false),
+    m_query(""),
+    m_needPenColor(false),
+    m_geometryDistance(0.0),
+    m_geometryDistanceType(OSSIM_UNIT_UNKNOWN),
+    m_layerName("")
+{
+   // Pick up colors from preference file if set.
+   getDefaults();
+   
+   theObject = this;
+   theImageBound.makeNan();
+   ossimAnnotationSource::setNumberOfBands(3);
+}
+
+ossimGdalOgrVectorAnnotation::~ossimGdalOgrVectorAnnotation()
+{
+   ossimViewInterface::theObject = 0;
+   close();
+}
+
+void ossimGdalOgrVectorAnnotation::close()
+{
+   deleteTables();
+   if(theDataSource)
+   {
+      delete theDataSource;
+      theDataSource = 0;
+   }
+   if (theImageGeometry.valid())
+   {
+      theImageGeometry = 0;
+   }
+}
+ossimFilename ossimGdalOgrVectorAnnotation::getFilename()const
+{
+   return theFilename;
+}
+
+void ossimGdalOgrVectorAnnotation::setQuery(const ossimString& query)
+{
+  m_query = query;
+  open(theFilename);
+}
+
+void ossimGdalOgrVectorAnnotation::setGeometryBuffer(ossim_float64 distance, ossimUnitType type)
+{
+   m_geometryDistance = distance;
+   m_geometryDistanceType = type;
+}
+
+bool ossimGdalOgrVectorAnnotation::open(const ossimFilename& file)
+{
+   const char* MODULE = "ossimGdalOgrVectorAnnotation::open";
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_NOTICE) << MODULE << " entered...\nfile: " << file << "\n";
+   }
+   
+   if(isOpen())
+   {
+      close();
+   }
+   m_layerNames.clear();
+   if(file == "") return false;
+
+#if 0 /* Commented out but please leave until I test. drb - 15 July 2011 */
+   ossimString ext = file.ext().downcase();
+   if ( ext != "shp" )
+   {
+      //---
+      // OGRSFDriverRegistrar::Open very touchy and crashes if given a file it cannot handle.
+      // Only allow one type of extension to open file.
+      //---
+      return false;
+   }
+#endif
+   
+   // theDataSource = OGRSFDriverRegistrar::Open( file.c_str(), false, &theDriver );
+   theDataSource = (OGRDataSource*) OGROpen( file.c_str(), false, NULL );
+   if ( theDataSource )
+   {
+      theDriver  = (OGRSFDriver*) theDataSource->GetDriver();
+   }
+   
+   if ( !theDataSource || !theDriver )
+   {
+      if(traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_NOTICE) << "OGRSFDriverRegistrar::Open failed...\n";
+      }
+      return false;   
+   }
+   
+   // Capture the file.  Need here for loadExternalGeometryFile method.
+   theFilename = file;
+
+   // This will set theViewProjection if "file.geom" is present and valid.
+   loadExternalGeometryFile();
+
+   // This will load external pen, brush and point attributes.
+   loadOmdFile();
+   
+   theLayersToRenderFlagList.clear();
+   vector<ossimGpt> points;
+   if(isOpen())
+   {
+      int i = 0;
+      int layerCount = 0;
+      if (!m_query.empty())
+      {
+        layerCount = 1;
+      }
+      else if (!m_layerName.empty())
+      {
+         layerCount = 1;
+      }
+      else
+      {
+        layerCount = theDataSource->GetLayerCount();
+      }
+      
+      bool successfulTest = true;
+      if(layerCount)
+      {
+         theLayersToRenderFlagList.resize(layerCount);
+         for(i = 0; (i < layerCount)&&successfulTest; ++i)
+         {
+            OGRLayer* layer = NULL;
+            if (!m_query.empty())
+            {
+              layer = theDataSource->ExecuteSQL(m_query, NULL, NULL);
+            }
+            else if (!m_layerName.empty())
+            {
+               layer = theDataSource->GetLayerByName(m_layerName.c_str());
+            }
+            else
+            {
+              layer = theDataSource->GetLayer(i);
+            }
+            
+            if(layer)
+            {
+               OGRSpatialReference* spatialReference = layer->GetSpatialRef();
+               theLayersToRenderFlagList[i] = true;
+               m_layerNames.push_back(ossimString(layer->GetLayerDefn()->GetName()));
+               
+               if(!spatialReference)
+               {
+                  //try xml file
+                  if (!theImageGeometry.valid())
+                  {
+                     loadExternalImageGeometryFromXml();
+                  }
+
+                  if(traceDebug())
+                  {
+                     ossimNotify(ossimNotifyLevel_NOTICE)
+                     << MODULE
+                     << " No spatial reference given, assuming geographic"
+                     << endl;
+                  }
+               }
+               else if(spatialReference->IsLocal())
+               {
+                  if(traceDebug())
+                  {
+                     ossimNotify(ossimNotifyLevel_NOTICE)
+                     << MODULE
+                     << " Only geographic vectors and  projected vectors "
+                     << "are supported, layer " << i << " is local" << endl;
+                  }
+                  successfulTest = false;
+               }
+               
+            }
+            else
+            {
+
+               if(traceDebug())
+               {
+                  ossimNotify(ossimNotifyLevel_NOTICE)
+                  
+                     << MODULE
+                     << " layer " << i << " is null." << endl;
+               }
+               successfulTest = false;
+            }
+            
+            if(successfulTest&&layer)
+            {
+               if (!theImageGeometry.valid())
+               {
+                  ossimRefPtr<ossimProjection> proj = createProjFromReference(layer->GetSpatialRef());
+                  if(proj.valid())
+                  {
+                     theImageGeometry = new ossimImageGeometry(0, proj.get());
+                  }
+               }
+               ossimMapProjection* mapProj = 0;
+               if(theImageGeometry.valid())
+               {
+                 mapProj = PTR_CAST(ossimMapProjection, theImageGeometry->getProjection());
+               }
+               if (!mapProj)
+               {
+                  theImageGeometry = 0; 
+               }
+               
+               if(i == 0)
+               {
+                  layer->GetExtent(&theBoundingExtent, true);
+                  if(mapProj)
+                  {
+                     if (layer->GetSpatialRef())
+                     {
+                        double unitValue = layer->GetSpatialRef()->GetLinearUnits();
+                        theBoundingExtent.MinX = theBoundingExtent.MinX * unitValue;
+                        theBoundingExtent.MaxY = theBoundingExtent.MaxY * unitValue;
+                        theBoundingExtent.MaxX = theBoundingExtent.MaxX * unitValue;
+                        theBoundingExtent.MinY = theBoundingExtent.MinY * unitValue;
+                     }
+
+                     ossimDrect rect(theBoundingExtent.MinX,
+                                     theBoundingExtent.MaxY,
+                                     theBoundingExtent.MaxX,
+                                     theBoundingExtent.MinY,
+                                     OSSIM_RIGHT_HANDED);
+                     
+                     ossimGpt g1 = mapProj->inverse(rect.ul());
+                     ossimGpt g2 = mapProj->inverse(rect.ur());
+                     ossimGpt g3 = mapProj->inverse(rect.lr());
+                     ossimGpt g4 = mapProj->inverse(rect.ll());
+                     ossimDrect rect2 = ossimDrect(ossimDpt(g1),
+                                                   ossimDpt(g2),
+                                                   ossimDpt(g3),
+                                                   ossimDpt(g4));
+                     
+                     theBoundingExtent.MinX = rect2.ul().x;
+                     theBoundingExtent.MinY = rect2.ul().y;
+                     theBoundingExtent.MaxX = rect2.lr().x;
+                     theBoundingExtent.MaxY = rect2.lr().y;
+
+                     //insert the bounding values to points to convert to bounding rect
+                     points.push_back(g1);
+                     points.push_back(g2);
+                     points.push_back(g3);
+                     points.push_back(g4);
+                  }
+               }
+               else
+               {
+                  OGREnvelope extent;
+                  layer->GetExtent(&extent, true);
+                  if(mapProj)
+                  {
+                     ossimDrect rect(extent.MinX,
+                                     extent.MaxY,
+                                     extent.MaxX,
+                                     extent.MinY,
+                                     OSSIM_RIGHT_HANDED);
+                  
+                     ossimGpt g1 = mapProj->inverse(rect.ul());
+                     ossimGpt g2 = mapProj->inverse(rect.ur());
+                     ossimGpt g3 = mapProj->inverse(rect.lr());
+                     ossimGpt g4 = mapProj->inverse(rect.ll());
+                     ossimDrect rect2 = ossimDrect(ossimDpt(g1),
+                                                   ossimDpt(g2),
+                                                   ossimDpt(g3),
+                                                   ossimDpt(g4));
+                     extent.MinX = rect2.ul().x;
+                     extent.MinY = rect2.ul().y;
+                     extent.MaxX = rect2.lr().x;
+                     extent.MaxY = rect2.lr().y;
+
+                     //compare the current values of points with the first layer to
+                     //get the MBR of the datasource
+                     if (points.size() == 4)
+                     {
+                        if (doubleLess(g1.lon, points[0].lon, 0.0001))
+                        {
+                           points[0].lon = g1.lon;
+                        }
+                        if (doubleGreater(g1.lat, points[0].lat, 0.0001))
+                        {
+                           points[0].lat = g1.lat;
+                        }
+                        if (doubleGreater(g2.lon, points[1].lon, 0.0001))
+                        {
+                           points[1].lon = g2.lon;
+                        }
+                        if (doubleGreater(g2.lat, points[1].lat, 0.0001))
+                        {
+                           points[1].lat = g2.lat;
+                        }
+                        if (doubleGreater(g3.lon, points[2].lon, 0.0001))
+                        {
+                           points[2].lon = g3.lon;
+                        }
+                        if (doubleLess(g3.lat, points[2].lat, 0.0001))
+                        {
+                           points[2].lat = g3.lat;
+                        }
+                        if (doubleLess(g4.lon, points[3].lon, 0.0001))
+                        {
+                           points[3].lon = g4.lon;
+                        }
+                        if (doubleLess(g4.lat, points[3].lat, 0.0001))
+                        {
+                           points[3].lat = g4.lat;
+                        }
+                     }
+                  }
+                  theBoundingExtent.MinX = std::min(extent.MinX,
+                                                    theBoundingExtent.MinX);
+                  theBoundingExtent.MinY = std::min(extent.MinY,
+                                                    theBoundingExtent.MinY);
+                  theBoundingExtent.MaxX = std::max(extent.MaxX,
+                                                    theBoundingExtent.MaxX);
+                  theBoundingExtent.MaxY = std::max(extent.MaxY,
+                                                    theBoundingExtent.MaxY);
+               }
+            }
+
+            //if an OGRLayer pointer representing a results set from the query, this layer is 
+            //in addition to the layers in the data store and must be destroyed with 
+            //OGRDataSource::ReleaseResultSet() before the data source is closed (destroyed).
+            if (!m_query.empty() && layer != NULL)
+            {
+              theDataSource->ReleaseResultSet(layer);
+            }  
+         }
+      }
+      if(!successfulTest)
+      {
+         delete theDataSource;
+         theDataSource = NULL;
+         theLayersToRenderFlagList.clear();
+         
+         return false;
+      }
+   }
+   if(traceDebug())
+   {
+      CLOG << "Extents = "
+           << theBoundingExtent.MinX << ", "
+           << theBoundingExtent.MinY << ", "
+           << theBoundingExtent.MaxX << ", "
+           << theBoundingExtent.MaxY << endl;
+   }
+   if(!theImageGeometry.valid())
+   {
+      computeDefaultView();
+   }
+   else
+   {
+      verifyViewParams();
+   }
+
+   //initialize the bounding rect
+   initializeBoundingRec(points);
+  
+   //only initializeTables when need to draw features. This eliminate the memory allocate problem
+   //when only do ossim-info for a large shape file
+   //initializeTables();
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " DEBUG:"
+         << "\ntheViewProjection:"
+         << endl;
+      if(theImageGeometry.valid())
+      {
+         theImageGeometry->print(ossimNotify(ossimNotifyLevel_DEBUG));
+      }
+      print(ossimNotify(ossimNotifyLevel_DEBUG));
+   }
+
+   return (theDataSource!=NULL);
+}
+
+void ossimGdalOgrVectorAnnotation::initializeBoundingRec(vector<ossimGpt> points)
+{
+   theImageBound.makeNan();
+
+   //if the projection is default or geographic, uses the bounding of the OGR Layer
+   if (points.size() == 0)
+   {
+      points.push_back(ossimGpt(theBoundingExtent.MaxY, theBoundingExtent.MinX));
+      points.push_back(ossimGpt(theBoundingExtent.MaxY, theBoundingExtent.MaxX));
+      points.push_back(ossimGpt(theBoundingExtent.MinY, theBoundingExtent.MaxX));
+      points.push_back(ossimGpt(theBoundingExtent.MinY, theBoundingExtent.MinX));
+   }
+
+   if(theImageGeometry.valid())
+   {
+      std::vector<ossimDpt> rectTmp;
+      rectTmp.resize(points.size());
+      for(std::vector<ossimGpt>::size_type index=0; index < points.size(); ++index)
+      {
+         theImageGeometry->worldToLocal(points[(int)index], rectTmp[(int)index]);
+      }
+
+      if (rectTmp.size() > 3)
+      {
+         ossimDrect rect2 = ossimDrect(rectTmp[0],
+            rectTmp[1],
+            rectTmp[2],
+            rectTmp[3]);
+
+         theImageBound = rect2;
+      }
+   }
+}
+
+bool ossimGdalOgrVectorAnnotation::setView(ossimObject* baseObject)
+{
+   bool result = false;
+
+   if(baseObject)
+   {
+      // Test for projection...
+      ossimProjection* p = PTR_CAST(ossimProjection, baseObject);
+      if (p)
+      {
+         if(!theImageGeometry)
+         {
+            theImageGeometry = new ossimImageGeometry(0, p);
+         }
+         else
+         {
+            theImageGeometry->setProjection(p);
+         }
+         
+         // Reproject the points to the current new projection.
+         transformObjectsFromView();
+         result = true;
+         
+      }
+      else
+      {
+         ossimImageGeometry* geom = dynamic_cast<ossimImageGeometry*> (baseObject);
+         if(geom)
+         {
+            theImageGeometry = geom;
+            // Reproject the points to the current new projection.
+            transformObjectsFromView();
+            result = true;
+         }
+      }
+   } // if (baseObject)
+
+   return result;
+}
+
+ossimObject* ossimGdalOgrVectorAnnotation::getView()
+{
+   return theImageGeometry.get();
+}
+
+//! Returns the image geometry object associated with this tile source or NULL if non defined.
+//! The geometry contains full-to-local image transform as well as projection (image-to-world)
+ossimRefPtr<ossimImageGeometry> ossimGdalOgrVectorAnnotation::getImageGeometry() const
+{
+   return theImageGeometry;
+}
+
+void ossimGdalOgrVectorAnnotation::computeDefaultView()
+{
+   if (theImageGeometry.valid())
+      return;
+
+   if(!isOpen())
+      return;
+
+   // double horizontal = fabs(theBoundingExtent.MinX - theBoundingExtent.MaxX);
+   // double vertical   = fabs(theBoundingExtent.MinY - theBoundingExtent.MaxY);
+
+   //    if((horizontal > 0.0) && (vertical > 0.0))
+   ossimEquDistCylProjection* proj = new ossimEquDistCylProjection;
+
+   ossim_float64 centerLat = (theBoundingExtent.MaxY + theBoundingExtent.MinY ) / 2.0;
+   ossim_float64 centerLon = (theBoundingExtent.MaxX + theBoundingExtent.MinX ) / 2.0;
+   ossim_float64 deltaLat  = theBoundingExtent.MaxY - theBoundingExtent.MinY;
+
+   // Scale that gives 1024 pixel in the latitude direction.
+   ossim_float64 scaleLat = deltaLat / 1024.0;
+   ossim_float64 scaleLon = scaleLat*ossim::cosd(std::fabs(centerLat)); 
+   ossimGpt origin(centerLat, centerLon, 0.0);
+   ossimDpt scale(scaleLon, scaleLat);
+
+   // Set the origin.
+   proj->setOrigin(origin);
+
+   // Set the tie point.
+   proj->setUlGpt( ossimGpt(theBoundingExtent.MaxY,
+      theBoundingExtent.MinX) );
+
+   // Set the scale.  Note this will handle computing meters per pixel.
+   proj->setDecimalDegreesPerPixel(scale);
+
+   // Capture the projection.
+   theImageGeometry = new ossimImageGeometry(0, proj);
+}
+
+ossimIrect ossimGdalOgrVectorAnnotation::getBoundingRect(ossim_uint32 /* resLevel */ )const
+{
+   return theImageBound;
+}
+
+void ossimGdalOgrVectorAnnotation::computeBoundingRect()
+{
+   std::multimap<long, ossimAnnotationObject*>::iterator iter = theFeatureCacheTable.begin();
+   
+   theImageBound.makeNan();
+   while(iter != theFeatureCacheTable.end())
+   {
+      ossimGeoAnnotationObject* obj = PTR_CAST(ossimGeoAnnotationObject,
+                                               (*iter).second);
+      
+      if(obj)
+      {
+         ossimDrect rect;
+         obj->getBoundingRect(rect);
+         
+         if(theImageBound.hasNans())
+         {
+            theImageBound = rect;
+         }
+         else
+         {
+            if(!rect.hasNans())
+            {
+               theImageBound = theImageBound.combine(rect);
+            }
+         }
+      }
+
+      ++iter;
+   }
+
+   theImageBound.stretchOut();
+}
+
+void ossimGdalOgrVectorAnnotation::drawAnnotations(
+   ossimRefPtr<ossimImageData> tile)
+{
+   if (theFeatureCacheTable.size() == 0)
+   {
+      initializeTables();
+   }
+
+   if( theImageGeometry.valid())
+   {
+      list<long> featuresToRender;
+      ossimIrect tileRect = tile->getImageRectangle();
+      
+      getFeatures(featuresToRender, tileRect);
+      
+      list<long>::iterator current = featuresToRender.begin();
+      
+      ossimRefPtr<ossimRgbImage> image = new ossimRgbImage;
+      
+      image->setCurrentImageData(tile);
+      vector<ossimAnnotationObject*> objectList;
+      
+      while(current!=featuresToRender.end())
+      {
+         getFeature(objectList, *current);
+         ++current;
+      }
+      
+      for(ossim_uint32 i = 0; i < objectList.size();++i)
+      {
+         objectList[i]->draw(*image.get());
+
+        if (theFillFlag && m_needPenColor) //need to draw both the brush and line (pen) for a polygon
+        {
+          ossimObject* objectDup = objectList[i]->dup();
+          ossimGeoAnnotationPolyObject* polyObject = PTR_CAST(ossimGeoAnnotationPolyObject, objectDup);
+          if (polyObject)//check if it is the polygon object
+          {
+            polyObject->setColor(thePenColor.getR(), thePenColor.getG(), thePenColor.getB());
+            polyObject->setThickness(theThickness);
+            polyObject->setFillFlag(false);
+            polyObject->draw(*image.get());
+          }
+          delete objectDup;
+        }
+      }
+      
+      tile->validate();
+   }
+}
+
+void ossimGdalOgrVectorAnnotation::updateAnnotationSettings()
+{
+   std::multimap<long, ossimAnnotationObject*>::iterator iter = theFeatureCacheTable.begin();
+
+   while(iter != theFeatureCacheTable.end())
+   {
+      iter->second->setThickness(theThickness);
+
+      iter->second->setColor(thePenColor.getR(),
+                             thePenColor.getG(),
+                             thePenColor.getB());
+      
+      if(PTR_CAST(ossimGeoAnnotationPolyObject, iter->second))
+      {
+         ossimGeoAnnotationPolyObject* poly =
+            (ossimGeoAnnotationPolyObject*)(iter->second);
+         poly->setFillFlag(theFillFlag);
+      }
+      else if(PTR_CAST(ossimGeoAnnotationMultiPolyObject, iter->second))
+      {
+         ossimGeoAnnotationMultiPolyObject* poly =
+            (ossimGeoAnnotationMultiPolyObject*)(iter->second);
+         poly->setFillFlag(theFillFlag);
+      }
+      else if(PTR_CAST(ossimGeoAnnotationEllipseObject, iter->second))
+      {
+         ossimGeoAnnotationEllipseObject* ell = (ossimGeoAnnotationEllipseObject*)(iter->second);
+
+         ell->setWidthHeight(thePointWidthHeight);
+         ell->setFillFlag(theFillFlag);
+         ell->transform(theImageGeometry.get());
+      }
+      if(theFillFlag)
+      {
+         iter->second->setColor(theBrushColor.getR(),
+                                theBrushColor.getG(),
+                                theBrushColor.getB());
+      }
+      ++iter;
+   }
+}
+
+void ossimGdalOgrVectorAnnotation::setProperty(ossimRefPtr<ossimProperty> property)
+{
+   if(!property.valid()) return;
+
+   ossimString name  = property->getName();
+   ossimString value = property->valueToString();
+
+   if(name == ossimKeywordNames::PEN_COLOR_KW)
+   {
+      int r;  
+      int g;  
+      int b;
+      std::istringstream in(value);
+      in >> r >> g >> b;
+      thePenColor.setR((unsigned char)r);
+      thePenColor.setG((unsigned char)g);
+      thePenColor.setB((unsigned char)b);
+      updateAnnotationSettings();
+   }
+   else if(name == ossimKeywordNames::BRUSH_COLOR_KW)
+   {
+      int r;  
+      int g;  
+      int b;
+      std::istringstream in(value);
+      in >> r >> g >> b;
+      theBrushColor.setR((unsigned char)r);
+      theBrushColor.setG((unsigned char)g);
+      theBrushColor.setB((unsigned char)b);
+      updateAnnotationSettings();
+   }
+   else if(name == ossimKeywordNames::FILL_FLAG_KW)
+   {
+      theFillFlag = value.toBool();
+      updateAnnotationSettings();
+   }
+   else if(name == ossimKeywordNames::THICKNESS_KW)
+   {
+      setThickness(value.toInt32());
+      updateAnnotationSettings();
+   }
+   else if(name == ossimKeywordNames::BORDER_SIZE_KW)
+   {
+   }
+   else if(name == ossimKeywordNames::POINT_WIDTH_HEIGHT_KW)
+   {
+      std::istringstream in(value);
+      in >> thePointWidthHeight.x;
+      in >> thePointWidthHeight.y;
+      updateAnnotationSettings();
+   }
+   else
+   {
+      ossimAnnotationSource::setProperty(property);
+   }
+}
+
+ossimRefPtr<ossimProperty> ossimGdalOgrVectorAnnotation::getProperty(const ossimString& name)const
+{
+   ossimRefPtr<ossimProperty> result;
+   if(name == ossimKeywordNames::PEN_COLOR_KW)
+   {
+      result = new ossimColorProperty(name,
+                                      thePenColor);
+      result->setCacheRefreshBit();
+   }
+   else if(name == ossimKeywordNames::BRUSH_COLOR_KW)
+   {
+      result = new ossimColorProperty(name,
+                                      theBrushColor);
+      result->setCacheRefreshBit();
+   }
+   else if(name == ossimKeywordNames::FILL_FLAG_KW)
+   {
+      result = new ossimBooleanProperty(name,
+                                        theFillFlag);
+      result->setCacheRefreshBit();
+      
+   }
+   else if(name == ossimKeywordNames::THICKNESS_KW)
+   {
+      ossimNumericProperty* prop =
+         new ossimNumericProperty(name,
+                                  ossimString::toString(getThickness()),
+                                  1.0,
+                                  255.0);
+      prop->setNumericType(ossimNumericProperty::ossimNumericPropertyType_INT);
+      result = prop;
+      result->setFullRefreshBit();
+   }
+   else if(name == ossimKeywordNames::BORDER_SIZE_KW)
+   {
+   }
+   else if(name == ossimKeywordNames::POINT_WIDTH_HEIGHT_KW)
+   {
+      result = new ossimTextProperty(name,
+                                     ossimString::toString(thePointWidthHeight.x) +
+                                     " " +
+                                     ossimString::toString(thePointWidthHeight.y));
+      result->setFullRefreshBit();
+   }
+   else
+   {
+      result = ossimAnnotationSource::getProperty(name);
+   }
+   
+   return result;
+}
+
+void ossimGdalOgrVectorAnnotation::getPropertyNames(std::vector<ossimString>& propertyNames)const
+{
+   
+   propertyNames.push_back(ossimKeywordNames::PEN_COLOR_KW);
+   propertyNames.push_back(ossimKeywordNames::BRUSH_COLOR_KW);
+   propertyNames.push_back(ossimKeywordNames::FILL_FLAG_KW);
+   propertyNames.push_back(ossimKeywordNames::THICKNESS_KW);
+   propertyNames.push_back(ossimKeywordNames::BORDER_SIZE_KW);
+   propertyNames.push_back(ossimKeywordNames::POINT_WIDTH_HEIGHT_KW);
+}
+
+
+bool ossimGdalOgrVectorAnnotation::saveState(ossimKeywordlist& kwl,
+                                             const char* prefix)const
+{
+   ossimString s;
+   
+   kwl.add(prefix,
+           ossimKeywordNames::FILENAME_KW,
+           theFilename.c_str(),
+           true);
+
+
+   s = ossimString::toString((int)thePenColor.getR()) + " " +
+       ossimString::toString((int)thePenColor.getG()) + " " +
+       ossimString::toString((int)thePenColor.getB());
+   
+   kwl.add(prefix,
+           ossimKeywordNames::PEN_COLOR_KW,
+           s.c_str(),
+           true);
+
+   s = ossimString::toString((int)theBrushColor.getR()) + " " +
+       ossimString::toString((int)theBrushColor.getG()) + " " +
+       ossimString::toString((int)theBrushColor.getB());
+   
+   kwl.add(prefix,
+           ossimKeywordNames::BRUSH_COLOR_KW,
+           s.c_str(),
+           true);
+
+   kwl.add(prefix,
+           ossimKeywordNames::FILL_FLAG_KW,
+           (int)theFillFlag,
+           true);
+
+   kwl.add(prefix,
+           ossimKeywordNames::THICKNESS_KW,
+           getThickness(),
+           true);
+
+   ossimString border;
+   border = ossimString::toString(theBorderSize);
+   border += " degrees";
+   kwl.add(prefix,
+           ossimKeywordNames::BORDER_SIZE_KW,
+           border,
+           true);
+
+   kwl.add(prefix,
+           ossimString(ossimString(ossimKeywordNames::BORDER_SIZE_KW)+
+                       "."+
+                       ossimKeywordNames::UNITS_KW).c_str(),
+           ossimUnitTypeLut::instance()->getEntryString(theBorderSizeUnits),
+           true);
+   
+   s = ossimString::toString((int)thePointWidthHeight.x) + " " +
+       ossimString::toString((int)thePointWidthHeight.y);
+   
+   kwl.add(prefix,
+           ossimKeywordNames::POINT_WIDTH_HEIGHT_KW,
+           s.c_str(),
+           true);
+
+   if (!m_query.empty())
+   {
+     kwl.add(prefix,
+       ossimKeywordNames::QUERY_KW,
+       m_query.c_str(),
+       true);
+   }
+   
+   if(theImageGeometry.valid())
+   {
+      ossimString newPrefix = prefix;
+      newPrefix += "view_proj.";
+      theImageGeometry->saveState(kwl,
+                                   newPrefix.c_str());
+   }
+   
+   return ossimAnnotationSource::saveState(kwl, prefix);
+}
+
+bool ossimGdalOgrVectorAnnotation::loadState(const ossimKeywordlist& kwl,
+                                             const char* prefix)
+{
+   const char* filename    = kwl.find(prefix, ossimKeywordNames::FILENAME_KW);
+   const char* penColor    = kwl.find(prefix, ossimKeywordNames::PEN_COLOR_KW);
+   const char* brushColor  = kwl.find(prefix, ossimKeywordNames::BRUSH_COLOR_KW);
+   const char* fillFlag    = kwl.find(prefix, ossimKeywordNames::FILL_FLAG_KW);
+   const char* thickness   = kwl.find(prefix, ossimKeywordNames::THICKNESS_KW);
+   const char* pointWh     = kwl.find(prefix, ossimKeywordNames::POINT_WIDTH_HEIGHT_KW);
+   const char* border_size = kwl.find(prefix, ossimKeywordNames::BORDER_SIZE_KW);
+   const char* query       = kwl.find(prefix, ossimKeywordNames::QUERY_KW);
+   
+   deleteTables();
+   if(thickness)
+   {
+      setThickness(ossimString(thickness).toInt32());
+   }
+   
+   if(penColor)
+   {
+      int r = 0;
+      int g = 0;
+      int b = 0;
+      ossimString penColorStr = ossimString(penColor);
+      if (penColorStr.split(",").size() == 3)
+      {
+         r = penColorStr.split(",")[0].toInt();
+         g = penColorStr.split(",")[1].toInt();
+         b = penColorStr.split(",")[2].toInt();
+         if (r == 0 && g == 0 && b == 0)
+         {
+            r = 1;
+            g = 1;
+            b = 1;
+         }
+      }
+      thePenColor = ossimRgbVector((ossim_uint8)r, (ossim_uint8)g, (ossim_uint8)b);
+      m_needPenColor = true;
+   }
+
+   if(brushColor)
+   {
+      int r = 0;
+      int g = 0;
+      int b = 0;
+      ossimString brushColorStr = ossimString(brushColor);
+      if (brushColorStr.split(",").size() == 3)
+      {
+         r = brushColorStr.split(",")[0].toInt();
+         g = brushColorStr.split(",")[1].toInt();
+         b = brushColorStr.split(",")[2].toInt();
+         if (r == 0 && g == 0 && b == 0)
+         {
+            r = 1;
+            g = 1;
+            b = 1;
+         }
+      }
+
+      theBrushColor = ossimRgbVector((ossim_uint8)r, (ossim_uint8)g, (ossim_uint8)b);
+   }
+   if(pointWh)
+   {
+      double w, h;
+      std::istringstream s(pointWh);
+      s>>w>>h;
+      thePointWidthHeight = ossimDpt(w, h);
+   }
+   
+   if(fillFlag)
+   {
+      theFillFlag = ossimString(fillFlag).toBool();
+   }
+   theBorderSize = 0.0;
+   if(border_size)
+   {
+      theBorderSize = ossimString(border_size).toDouble();
+      ossimString unitPrefix = ossimString(prefix) +
+                               ossimKeywordNames::BORDER_SIZE_KW +
+                               ossimString(".");
+      
+      theBorderSizeUnits = (ossimUnitType)ossimUnitTypeLut::instance()->
+         getEntryNumber(kwl,
+                                                                                unitPrefix.c_str());
+      if(theBorderSizeUnits != OSSIM_UNIT_UNKNOWN)
+      {
+         ossimUnitConversionTool unitConvert(theBorderSize,
+                                             theBorderSizeUnits);
+         
+         theBorderSize      = unitConvert.getValue(OSSIM_DEGREES);
+         theBorderSizeUnits = OSSIM_DEGREES;
+      }
+      else // assume degrees
+      {
+         theBorderSizeUnits = OSSIM_DEGREES;
+      }
+   }
+   else
+   {
+      theBorderSize      = 0.0;
+      theBorderSizeUnits = OSSIM_DEGREES;
+   }
+   
+   if(filename)
+   {
+      if(!open(ossimFilename(filename)))
+      {
+         return false;
+      }
+   }
+
+   if (query)
+   {
+     setQuery(query);
+   }
+
+   bool status = ossimAnnotationSource::loadState(kwl, prefix);
+   
+   initializeTables();
+
+   return status;
+}
+
+std::ostream& ossimGdalOgrVectorAnnotation::print(std::ostream& out) const
+{
+   out << "ossimGdalOgrVectorAnnotation::print"
+       << "\ntheLayersToRenderFlagList.size(): "
+       << theLayersToRenderFlagList.size()
+       << "\ntheLayerTable.size(): " << theLayerTable.size();
+
+   ossim_uint32 i;
+   for(i=0; i<theLayersToRenderFlagList.size(); ++i)
+   {
+      out << "layer[" << i << "]:"
+          << (theLayersToRenderFlagList[i]?"enabled":"disabled")
+          << std::endl;
+   }
+   return ossimAnnotationSource::print(out);
+}
+
+void ossimGdalOgrVectorAnnotation::transformObjectsFromView()
+{
+   if (theImageGeometry.valid())
+   {
+      if (theFeatureCacheTable.size() == 0)
+      {
+         initializeTables();
+      }
+      std::multimap<long, ossimAnnotationObject*>::iterator iter =
+         theFeatureCacheTable.begin();
+      
+      while(iter != theFeatureCacheTable.end())
+      {
+         ossimGeoAnnotationObject* obj = PTR_CAST(ossimGeoAnnotationObject,
+                                                  (*iter).second);
+         
+         if(obj&&theImageGeometry.valid())
+         {
+            obj->transform(theImageGeometry.get());
+         }
+         ++iter;
+      }
+      computeBoundingRect();
+   }
+}
+
+void ossimGdalOgrVectorAnnotation::getFeatures(std::list<long>& result,
+                                               const ossimIrect& rect)
+{
+   if (isOpen())
+   {
+      ossimGpt gp1;
+      ossimGpt gp2;
+      ossimGpt gp3;
+      ossimGpt gp4;
+      ossimDpt dp1 = rect.ul();
+      ossimDpt dp2 = rect.ur();
+      ossimDpt dp3 = rect.lr();
+      ossimDpt dp4 = rect.ll();
+      
+      if (theImageGeometry.valid())
+      {
+         theImageGeometry->localToWorld(dp1, gp1);
+         theImageGeometry->localToWorld(dp2, gp2);
+         theImageGeometry->localToWorld(dp3, gp3);
+         theImageGeometry->localToWorld(dp4, gp4);
+
+         double maxX = std::max( gp1.lond(), std::max( gp2.lond(), std::max(gp3.lond(), gp4.lond())));
+         double minX = std::min( gp1.lond(), std::min( gp2.lond(), std::min(gp3.lond(), gp4.lond())));
+         double maxY = std::max( gp1.latd(), std::max( gp2.latd(), std::max(gp3.latd(), gp4.latd())));
+         double minY = std::min( gp1.latd(), std::min( gp2.latd(), std::min(gp3.latd(), gp4.latd())));
+         
+         ossimDrect bounds(minX, minY, maxX, maxY);
+         
+         for(ossim_uint32 layerI = 0;
+             layerI < theLayersToRenderFlagList.size();
+             ++layerI)
+         {
+            if(theLayersToRenderFlagList[layerI])
+            {
+               if(theLayerTable[layerI])
+               {
+                  theLayerTable[layerI]->getIdList(result, bounds);
+               }
+            }
+         }
+      }
+   }
+}
+
+void ossimGdalOgrVectorAnnotation::initializeTables()
+{
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG) << "ossimGdalOgrVectorAnnotation::initializeTables(): entered.........." << std::endl;
+   }
+   if(theLayerTable.size())
+   {
+      deleteTables();
+   }
+
+   if(isOpen())
+   {
+      int upper = theLayersToRenderFlagList.size();
+      theLayerTable.resize(upper);
+
+      for(int i = 0; i < upper; ++i)
+      {  
+         if(theLayersToRenderFlagList[i])
+         {
+            OGREnvelope extent;
+            OGRLayer* layer = NULL;
+            if (!m_query.empty())
+            {
+              layer = theDataSource->ExecuteSQL(m_query, NULL, NULL);
+            }
+            else if (!m_layerName.empty())
+            {
+               layer = theDataSource->GetLayerByName(m_layerName.c_str());
+            }
+            else
+            {
+              layer = theDataSource->GetLayer(i);
+            }
+
+            ossimRefPtr<ossimProjection> proj;
+            if (theIsExternalGeomFlag&&theImageGeometry.valid())
+            {
+               proj = theImageGeometry->getProjection();
+            }
+            else
+            {
+               proj = createProjFromReference(layer->GetSpatialRef());
+            }
+
+            ossimMapProjection* mapProj = PTR_CAST(ossimMapProjection, proj.get());
+            
+            layer->ResetReading();
+            layer->GetExtent(&extent, true);
+            layer->ResetReading();
+
+            OGRFeature* feature = NULL;
+            if(mapProj)
+            {
+               ossimDrect rect(extent.MinX,
+                               extent.MaxY,
+                               extent.MaxX,
+                               extent.MinY,
+                               OSSIM_RIGHT_HANDED);
+               ossimGpt g1 = mapProj->inverse(rect.ul());
+               ossimGpt g2 = mapProj->inverse(rect.ur());
+               ossimGpt g3 = mapProj->inverse(rect.lr());
+               ossimGpt g4 = mapProj->inverse(rect.ll());
+
+               ossimDrect rect2 = ossimDrect(ossimDpt(g1),
+                                            ossimDpt(g2),
+                                            ossimDpt(g3),
+                                            ossimDpt(g4));
+               theLayerTable[i] = new ossimOgrGdalLayerNode(rect2);
+            }
+            else
+            {
+               theLayerTable[i] = new ossimOgrGdalLayerNode(ossimDrect(extent.MinX,
+                                                                       extent.MinY,
+                                                                       extent.MaxX,
+                                                                       extent.MaxY));
+            }
+           
+            while( (feature = layer->GetNextFeature()) != NULL)
+            {
+                  if(feature)
+                  {
+                     OGRGeometry* geom = feature->GetGeometryRef();
+                     
+                     if(geom)
+                     {
+                        switch(geom->getGeometryType())
+                        {
+                           case wkbMultiPoint:
+                           case wkbMultiPoint25D:
+                           {
+                              if(traceDebug())
+                              {
+                                 ossimNotify(ossimNotifyLevel_DEBUG) << "Loading multi point" << std::endl;
+                              }
+                              loadMultiPoint(feature->GetFID(),
+                                             (OGRMultiPoint*)geom,
+                                             mapProj);
+                              break;
+                           }
+                           case wkbPolygon25D:
+                           case wkbPolygon:
+                           {
+                              if(traceDebug())
+                              {
+                                 ossimNotify(ossimNotifyLevel_DEBUG) << "Loading polygon" << std::endl;
+                              }
+                              if (m_geometryDistance > 0.0)
+                              {
+                                 OGRPolygon* poly = (OGRPolygon*)geom;
+                                 OGRLinearRing* ring = poly->getExteriorRing();
+                                 int numPoints = ring->getNumPoints();
+                                 OGRGeometry* bufferGeom = geom->Buffer(m_geometryDistance, numPoints);
+                                 loadPolygon(feature->GetFID(),
+                                    (OGRPolygon*)bufferGeom,
+                                    mapProj);
+                              }
+                              else
+                              {
+                                 loadPolygon(feature->GetFID(),
+                                    (OGRPolygon*)geom,
+                                    mapProj);
+                              }
+
+                              break;
+                           }
+                           case wkbLineString25D:
+                           case wkbLineString:
+                           {
+                              if(traceDebug())
+                              {
+                                 ossimNotify(ossimNotifyLevel_DEBUG) << "Loading line string" << std::endl;
+                              }
+                              loadLineString(feature->GetFID(),
+                                             (OGRLineString*)geom,
+                                             mapProj);
+                              break;
+                           }
+                           case wkbPoint:
+                           case wkbPoint25D:
+                           {
+                              if(traceDebug())
+                              {
+                                 ossimNotify(ossimNotifyLevel_DEBUG) << "Loading point" << std::endl;
+                              }
+                              loadPoint(feature->GetFID(),
+                                        (OGRPoint*)geom,
+                                        mapProj);
+                              break;
+                           }
+                           case wkbMultiPolygon25D:
+                           case wkbMultiPolygon:
+                           {
+                              if(traceDebug())
+                              {
+                                 ossimNotify(ossimNotifyLevel_DEBUG) << "Loading multi polygon" << std::endl;
+                              }
+                              if (m_geometryDistance > 0.0)
+                              {
+                                 OGRGeometry* bufferGeom = geom->Buffer(m_geometryDistance);
+                                 loadMultiPolygon(feature->GetFID(),
+                                    (OGRMultiPolygon*)bufferGeom,
+                                    mapProj);
+                              }
+                              else
+                              {
+                                 loadMultiPolygon(feature->GetFID(),
+                                    (OGRMultiPolygon*)geom,
+                                    mapProj);
+                              }
+                              break;
+                                               
+                           }
+                           case wkbMultiLineString:
+                           {
+                              if(traceDebug())
+                              {
+                                 ossimNotify(ossimNotifyLevel_DEBUG) << "Loading line string" << std::endl;
+                              }
+                              loadMultiLineString(feature->GetFID(),
+                                    (OGRMultiLineString*)geom,
+                                    mapProj);
+                                 break;
+                              }
+                           default:
+                           {
+                              if(traceDebug())
+                              {
+                                 ossimNotify(ossimNotifyLevel_WARN)
+                                    << "ossimGdalOgrVectorAnnotation::initializeTables WARNING\n"
+                                    
+                                    << OGRGeometryTypeToName(geom->getGeometryType())
+                                    <<" NOT SUPPORTED!"
+                                    << endl;
+                              }
+                              break;
+                           }
+                        }
+                        geom->getEnvelope(&extent);
+                        if(mapProj)
+                        {
+                           ossimDrect rect(extent.MinX,
+                                           extent.MaxY,
+                                           extent.MaxX,
+                                           extent.MinY,
+                                           OSSIM_RIGHT_HANDED);
+                           ossimGpt g1 = mapProj->inverse(rect.ul());
+                           ossimGpt g2 = mapProj->inverse(rect.ur());
+                           ossimGpt g3 = mapProj->inverse(rect.lr());
+                           ossimGpt g4 = mapProj->inverse(rect.ll());
+                           
+                           theLayerTable[i]->theFeatureList.push_back(ossimOgrGdalFeatureNode(feature->GetFID(),
+                                                                                              ossimDrect(ossimDpt(g1),
+                                                                                                         ossimDpt(g2),
+                                                                                                         ossimDpt(g3),
+                                                                                                         ossimDpt(g4))));
+                           
+                        }
+                        else
+                        {
+                           theLayerTable[i]->theFeatureList.push_back(ossimOgrGdalFeatureNode(feature->GetFID(),
+                                                                                              ossimDrect(extent.MinX,
+                                                                                                         extent.MinY,
+                                                                                                         extent.MaxX,
+                                                                                                         extent.MaxY)));
+                        }
+                     }
+               }
+               delete feature;
+            }
+
+            //if an OGRLayer pointer representing a results set from the query, this layer is 
+            //in addition to the layers in the data store and must be destroyed with 
+            //OGRDataSource::ReleaseResultSet() before the data source is closed (destroyed).
+            if (!m_query.empty() && layer != NULL)
+            {
+              theDataSource->ReleaseResultSet(layer);
+            }  
+         }
+         else
+         {
+            theLayerTable[i] = NULL;
+         }
+      }
+   }
+   computeBoundingRect();
+   updateAnnotationSettings();
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimGdalOgrVectorAnnotation::initializeTables(): leaving..."
+         << std::endl;
+   }
+}
+
+void ossimGdalOgrVectorAnnotation::deleteTables()
+{
+   for(ossim_uint32 i = 0; i < theLayerTable.size(); ++i)
+   {
+      if(theLayerTable[i])
+      {
+         delete theLayerTable[i];
+      }
+   }
+
+   theLayerTable.clear();
+   std::multimap<long, ossimAnnotationObject*>::iterator current = theFeatureCacheTable.begin();
+
+   while(current != theFeatureCacheTable.end())
+   {
+      ((*current).second)->unref();
+      ++current;
+   }
+   
+   theFeatureCacheTable.clear();
+}
+
+
+void ossimGdalOgrVectorAnnotation::getFeature(vector<ossimAnnotationObject*>& featureList,
+                                              long id)
+{
+   std::multimap<long, ossimAnnotationObject*>::iterator iter = theFeatureCacheTable.find(id);
+   
+   while( (iter != theFeatureCacheTable.end()) && ((*iter).first == id)  )
+   {
+      featureList.push_back((*iter).second);
+      ++iter;
+   }
+}
+
+ossimProjection* ossimGdalOgrVectorAnnotation::createProjFromReference(OGRSpatialReference* reference)const
+{
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG) << "ossimGdalOgrVectorAnnotation::createProjFromReference:   entered........" << std::endl;
+   }
+   if(!reference)
+   {
+      if(traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG) << "ossimGdalOgrVectorAnnotation::createProjFromReference:   leaving 1........" << std::endl;
+      }
+      return NULL;
+   }
+   if(reference->IsGeographic()||reference->IsLocal())
+   {
+      if(traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG) << "ossimGdalOgrVectorAnnotation::createProjFromReference:   leaving 2........" << std::endl;
+      }
+      return NULL;
+   }
+   char* wktString = NULL;
+   ossimKeywordlist kwl;
+   reference->exportToWkt(&wktString);
+   wktTranslator.toOssimKwl(wktString,
+                            kwl);
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG) << "wktString === " << wktString << std::endl;
+      ossimNotify(ossimNotifyLevel_DEBUG) << "KWL === " << kwl << std::endl;
+   }
+   OGRFree(wktString);
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG) << "ossimGdalOgrVectorAnnotation::createProjFromReference:   returning........" << std::endl;
+   }
+   return ossimProjectionFactoryRegistry::instance()->createProjection(kwl);
+}
+
+void ossimGdalOgrVectorAnnotation::loadPolygon(long id, OGRPolygon* poly, ossimMapProjection* mapProj)
+{
+   OGRLinearRing* ring = poly->getExteriorRing();
+   
+   ossimGpt origin;
+   
+   if(theImageGeometry.valid()&&theImageGeometry->getProjection())
+   {
+      origin = theImageGeometry->getProjection()->origin();
+   }
+   
+   ossimRgbVector color;
+   
+   if(theFillFlag)
+   {
+      color = theBrushColor;
+   }
+   else
+   {
+      color = thePenColor;
+   }
+   
+   if(ring)
+   {
+      int upper = ring->getNumPoints();
+      vector<ossimGpt> points(upper);
+      for(int i = 0; i < upper; ++i)
+      {
+         OGRPoint ogrPt;
+         ring->getPoint(i, &ogrPt);
+         if(mapProj)
+         {
+            points[i] = mapProj->inverse(ossimDpt(ogrPt.getX(),
+                                                  ogrPt.getY()));
+
+         }
+         else
+         {
+            points[i] = ossimGpt(ogrPt.getY(),
+                                 ogrPt.getX(),
+                                 ogrPt.getZ(),
+                                 origin.datum());
+         }
+      }
+      ossimGeoAnnotationObject* annotation =
+         new ossimGeoAnnotationPolyObject(points,
+                                          theFillFlag,
+                                          color.getR(),
+                                          color.getG(),
+                                          color.getB(),
+                                          theThickness);
+      if(theImageGeometry.valid())
+      {
+         annotation->transform(theImageGeometry.get());
+      }
+      
+      theFeatureCacheTable.insert(make_pair(id,
+                                            annotation));
+   }
+   int bound = poly->getNumInteriorRings();
+   if(bound)
+   {
+      for(int i = 0; i < bound; ++i)
+       {
+          ring = poly->getInteriorRing(i);
+          if(ring)
+          {
+             int j = 0;
+             int upper = ring->getNumPoints();
+             vector<ossimGpt> points(upper);
+             for(j = 0; j < upper; ++j)
+             {
+                OGRPoint ogrPt;
+                ring->getPoint(j, &ogrPt);
+                if(mapProj)
+                {
+                   ossimDpt eastingNorthing(ogrPt.getX(),
+                                            ogrPt.getY());
+                   
+                   points[j] = mapProj->inverse(eastingNorthing);
+                   
+                }
+                else
+                {
+                   points[j] = ossimGpt(ogrPt.getY(),
+                                        ogrPt.getX(),
+                                        ogrPt.getZ(),
+                                        origin.datum());
+                }
+             }
+             ossimGeoAnnotationPolyObject* annotation =
+                new ossimGeoAnnotationPolyObject(points,
+                                                 theFillFlag,
+                                                 color.getR(),
+                                                 color.getG(),
+                                                 color.getB(),
+                                                 theThickness);
+             annotation->setPolyType(ossimGeoAnnotationPolyObject::OSSIM_POLY_INTERIOR_RING);
+       
+             if(theImageGeometry.valid())
+             {
+                annotation->transform(theImageGeometry.get());
+             }
+
+             theFeatureCacheTable.insert(make_pair(id,
+                                              annotation));
+
+          }
+       }
+    }
+}
+
+void ossimGdalOgrVectorAnnotation::loadLineString(long id, OGRLineString* lineString,
+                                            ossimMapProjection* mapProj)
+{
+    int upper = lineString->getNumPoints();
+    ossimGpt origin;
+    if(theImageGeometry.valid()&&theImageGeometry->getProjection())
+    {
+       origin = theImageGeometry->getProjection()->origin();
+    }
+    
+   ossimRgbVector color;
+   
+   if(theFillFlag)
+   {
+      color = theBrushColor;
+   }
+   else
+   {
+      color = thePenColor;
+   }
+   vector<ossimGpt> polyLine(upper);
+   for(int i = 0; i < upper; ++i)
+   {
+      OGRPoint ogrPt;
+      
+      lineString->getPoint(i, &ogrPt);
+      
+      if(mapProj)
+      {
+         ossimDpt eastingNorthing(ogrPt.getX(),
+                                  ogrPt.getY());
+         
+         polyLine[i] = mapProj->inverse(eastingNorthing);
+      }
+      else
+      {
+         polyLine[i] = ossimGpt(ogrPt.getY(),
+                                ogrPt.getX(),
+                                ogrPt.getZ(),
+                                origin.datum());
+      }
+   }
+   
+   ossimGeoAnnotationPolyLineObject* annotation =
+      new ossimGeoAnnotationPolyLineObject(polyLine,
+                                           color.getR(),
+                                           color.getG(),
+                                           color.getB(),
+                                           theThickness);
+   if(theImageGeometry.valid())
+   {
+      annotation->transform(theImageGeometry.get());
+   }
+
+   theFeatureCacheTable.insert(make_pair(id,
+                                         annotation));
+}
+
+void ossimGdalOgrVectorAnnotation::loadMultiLineString(long id, OGRMultiLineString* multiLineString,
+   ossimMapProjection* mapProj)
+{
+   ossimRgbVector color;
+
+   if(theFillFlag)
+   {
+      color = theBrushColor;
+   }
+   else
+   {
+      color = thePenColor;
+   }
+
+   ossim_uint32 numGeometries = multiLineString->getNumGeometries();
+   ossimGpt origin;
+   if(theImageGeometry.valid()&&theImageGeometry->getProjection())
+   {
+      origin = theImageGeometry->getProjection()->origin();
+   }
+
+   vector<ossimGeoPolygon> geoPoly;
+   for(ossim_uint32 geomIdx = 0; geomIdx < numGeometries; ++geomIdx)
+   {
+      OGRGeometry* geomRef = multiLineString->getGeometryRef(geomIdx);
+      OGRLineString* lineString = (OGRLineString*)geomRef;
+      if (lineString)
+      {
+         int upper = lineString->getNumPoints();
+         vector<ossimGpt> polyLine(upper);
+         for(int i = 0; i < upper; ++i)
+         {
+            OGRPoint ogrPt;
+
+            lineString->getPoint(i, &ogrPt);
+
+            if(mapProj)
+            {
+               ossimDpt eastingNorthing(ogrPt.getX(),
+                  ogrPt.getY());
+
+               polyLine[i] = mapProj->inverse(eastingNorthing);
+            }
+            else
+            {
+               polyLine[i] = ossimGpt(ogrPt.getY(),
+                  ogrPt.getX(),
+                  ogrPt.getZ(),
+                  origin.datum());
+            }
+         }
+
+         ossimGeoAnnotationPolyLineObject* annotation =
+            new ossimGeoAnnotationPolyLineObject(polyLine,
+            color.getR(),
+            color.getG(),
+            color.getB(),
+            theThickness);
+         if(theImageGeometry.valid())
+         {
+            annotation->transform(theImageGeometry.get());
+         }
+
+         theFeatureCacheTable.insert(make_pair(id,
+            annotation));
+      }
+   }
+}
+
+void ossimGdalOgrVectorAnnotation::loadPoint(long id, OGRPoint* point, ossimMapProjection* mapProj)
+{
+   ossimGpt origin;
+   ossimRgbVector color;
+   
+   if(theFillFlag)
+   {
+      color = theBrushColor;
+   }
+   else
+   {
+      color = thePenColor;
+   }
+   if(theImageGeometry.valid()&&theImageGeometry->getProjection())
+   {
+      origin = theImageGeometry->getProjection()->origin();
+   }
+   
+   ossimGpt gpt;
+   if(mapProj)
+   {
+      ossimDpt eastingNorthing(point->getX(),
+                               point->getY());
+      
+      gpt = mapProj->inverse(eastingNorthing);
+   }
+   else
+   {
+      gpt = ossimGpt(point->getY(),
+                     point->getX(),
+                     point->getZ(),
+                     origin.datum());
+   }
+   
+   
+   ossimGeoAnnotationEllipseObject* annotation =
+      new ossimGeoAnnotationEllipseObject(gpt,
+                                          thePointWidthHeight,
+                                          theFillFlag,
+                                          color.getR(),
+                                          color.getG(),
+                                          color.getB(),
+                                          theThickness);
+   if(theImageGeometry.valid())
+   {
+      annotation->transform(theImageGeometry.get());
+   }
+   theFeatureCacheTable.insert(make_pair(id, annotation));
+}
+
+void ossimGdalOgrVectorAnnotation::loadMultiPoint(long id,
+                                                  OGRMultiPoint* multiPoint,
+                                                  ossimMapProjection* mapProj)
+{
+   ossim_uint32 numGeometries = multiPoint->getNumGeometries();
+   ossimRgbVector color;
+   
+   if(theFillFlag)
+   {
+      color = theBrushColor;
+   }
+   else
+   {
+      color = thePenColor;
+   }
+   
+   ossimGeoAnnotationMultiEllipseObject* annotation =
+      new ossimGeoAnnotationMultiEllipseObject(thePointWidthHeight,
+                                               theFillFlag,
+                                               color.getR(),
+                                               color.getG(),
+                                               color.getB(),
+                                               theThickness);
+   ossimGpt origin;
+   if(theImageGeometry.valid()&&theImageGeometry->getProjection())
+   {
+      origin = theImageGeometry->getProjection()->origin();
+   }
+   for(ossim_uint32 i = 0; i < numGeometries; ++i)
+   {
+      OGRGeometry* geomRef = multiPoint->getGeometryRef(i);
+      if( geomRef &&
+          ( (geomRef->getGeometryType()==wkbPoint) ||
+            (geomRef->getGeometryType()==wkbPoint25D) ) )
+      {
+         OGRPoint* point = (OGRPoint*)geomRef;
+         
+         if(mapProj)
+         {
+            ossimDpt eastingNorthing(point->getX(),
+                                     point->getY());
+            
+            annotation->addPoint(mapProj->inverse(eastingNorthing));
+         }
+         annotation->addPoint(ossimGpt(point->getY(),
+                                       point->getX(),
+                                       point->getZ(),
+                                       origin.datum()));
+      }
+   }
+   if(theImageGeometry.valid())
+   {
+      annotation->transform(theImageGeometry.get());
+   }
+
+   theFeatureCacheTable.insert(make_pair(id, annotation));
+}
+
+
+void ossimGdalOgrVectorAnnotation::loadMultiPolygon(
+   long id,
+   OGRMultiPolygon* multiPolygon,
+   ossimMapProjection* mapProj)
+{
+   ossimRgbVector color;
+   
+   if(theFillFlag)
+   {
+      color = theBrushColor;
+   }
+   else
+   {
+      color = thePenColor;
+   }
+   ossimGpt origin;
+   ossim_uint32 numGeometries = multiPolygon->getNumGeometries();
+
+   if(theImageGeometry.valid()&&theImageGeometry->getProjection())
+   {
+      origin = theImageGeometry->getProjection()->origin();
+   }
+
+   vector<ossimGeoPolygon> geoPoly;
+   for(ossim_uint32 geomIdx = 0; geomIdx < numGeometries; ++geomIdx)
+   {
+      OGRGeometry* geomRef = multiPolygon->getGeometryRef(geomIdx);
+      if( geomRef &&
+          ( (geomRef->getGeometryType()==wkbPolygon) ||
+            (geomRef->getGeometryType()==wkbPolygon25D) ) )
+      {
+         geoPoly.push_back(ossimGeoPolygon());
+         OGRPolygon* poly = (OGRPolygon*)geomRef;
+         OGRLinearRing* ring = poly->getExteriorRing();
+         ossim_uint32 currentPoly = geoPoly.size()-1;
+
+         if(ring)
+         {
+            ossim_uint32 upper = ring->getNumPoints();
+
+            for(ossim_uint32 ringPointIdx = 0;
+                ringPointIdx < upper;
+                ++ringPointIdx)
+            {
+               OGRPoint ogrPt;
+               ring->getPoint(ringPointIdx, &ogrPt);
+               if(mapProj)
+               {
+                  geoPoly[currentPoly].addPoint(
+                     mapProj->inverse(ossimDpt(ogrPt.getX(), ogrPt.getY())));
+               }
+               else
+               {
+                  geoPoly[currentPoly].addPoint(ogrPt.getY(),
+                                                ogrPt.getX(),
+                                                ogrPt.getZ(),
+                                                origin.datum());
+               }
+            }
+         }
+         
+         ossim_uint32 bound = poly->getNumInteriorRings();
+
+         if(bound)
+         {
+            for(ossim_uint32 interiorRingIdx = 0;
+                interiorRingIdx < bound;
+                ++interiorRingIdx)
+            {
+               ring = poly->getInteriorRing(interiorRingIdx);
+
+               if(ring)
+               {
+                  geoPoly.push_back(ossimGeoPolygon());
+                  currentPoly = geoPoly.size()-1;
+
+                  ossim_uint32 upper = ring->getNumPoints();
+
+                  for(ossim_uint32 interiorRingPointIdx = 0;
+                      interiorRingPointIdx < upper;
+                      ++interiorRingPointIdx)
+                  {
+                     OGRPoint ogrPt;
+                     ring->getPoint(interiorRingPointIdx, &ogrPt);
+                     if(mapProj)
+                     {
+                        geoPoly[currentPoly].addPoint(
+                           mapProj->inverse(ossimDpt(ogrPt.getX(),
+                                                     ogrPt.getY())));
+                     }
+                     else
+                     {
+                        geoPoly[currentPoly].addPoint(ogrPt.getY(),
+                                                      ogrPt.getX(),
+                                                      ogrPt.getZ(),
+                                                      origin.datum());
+                     }
+                  }
+               }
+            }
+         }
+      }
+   }
+   
+   if(geoPoly.size())
+   {
+      ossimGeoAnnotationMultiPolyObject* annotation =
+         new ossimGeoAnnotationMultiPolyObject(geoPoly,
+                                               theFillFlag,
+                                               color.getR(),
+                                               color.getG(),
+                                               color.getB(),
+                                               theThickness);
+      if(theImageGeometry.valid())
+      {
+         annotation->transform(theImageGeometry.get());
+      }
+
+      theFeatureCacheTable.insert(make_pair(id, annotation));
+   }
+}
+
+bool ossimGdalOgrVectorAnnotation::open()
+{
+   return open(theFilename);
+}
+
+bool ossimGdalOgrVectorAnnotation::isOpen()const
+{
+   return (theDataSource!=NULL);
+}
+
+const ossimObject* ossimGdalOgrVectorAnnotation::getView()const
+{
+   return theImageGeometry.get();
+}
+
+void ossimGdalOgrVectorAnnotation::setBrushColor(const ossimRgbVector& brushColor)
+{
+   theBrushColor = brushColor;
+}
+   
+void ossimGdalOgrVectorAnnotation::setPenColor(const ossimRgbVector& penColor)
+{
+   thePenColor = penColor;
+}
+
+ossimRgbVector ossimGdalOgrVectorAnnotation::getPenColor()const
+{
+   return thePenColor;
+}
+
+ossimRgbVector ossimGdalOgrVectorAnnotation::getBrushColor()const
+{
+   return theBrushColor;
+}
+
+double ossimGdalOgrVectorAnnotation::getPointRadius()const
+{
+   return thePointWidthHeight.x/2.0;
+}
+
+void ossimGdalOgrVectorAnnotation::setPointRadius(double r)
+{
+   thePointWidthHeight = ossimDpt(fabs(r)*2, fabs(r)*2);
+}
+
+bool ossimGdalOgrVectorAnnotation::getFillFlag()const
+{
+   return theFillFlag;
+}
+
+void ossimGdalOgrVectorAnnotation::setFillFlag(bool flag)
+{
+   theFillFlag=flag;
+}
+
+void ossimGdalOgrVectorAnnotation::setThickness(ossim_int32 thickness)
+{
+   if ( (thickness > 0) && (thickness < 256) )
+   {
+      theThickness = static_cast<ossim_uint8>(thickness);
+   }
+   else
+   {
+      ossimNotify(ossimNotifyLevel_WARN)
+         << "ossimGdalOgrVectorAnnotation::setThickness range error: "
+         << thickness
+         << "\nValid range: 1 to 255"
+         << std::endl;
+   }
+}
+
+ossim_int32 ossimGdalOgrVectorAnnotation::getThickness()const
+{
+   return static_cast<ossim_int32>(theThickness);
+}
+
+void ossimGdalOgrVectorAnnotation::loadExternalGeometryFile()
+{
+   ossimFilename filename = theFilename;
+   filename.setExtension(".geom");
+   if(!filename.exists())
+   {
+      filename.setExtension(".GEOM");
+      if(!filename.exists())
+      {
+         return;
+      }
+   }
+
+   ossimKeywordlist kwl;
+   if(kwl.addFile(filename))
+   {
+      ossimRefPtr<ossimImageGeometry> geom = new ossimImageGeometry;
+      geom->loadState(kwl);
+      if(geom->getProjection())
+      {
+         theImageGeometry = geom;
+         ossimMapProjection* mapProj = PTR_CAST(ossimMapProjection, theImageGeometry->getProjection());
+         if (mapProj)
+         {
+            // drb...
+            //mapProj->setUlGpt(mapProj->origin());
+            theIsExternalGeomFlag = true;
+
+            if (traceDebug())
+            {
+               ossimNotify(ossimNotifyLevel_DEBUG)
+                  << "ossimGdalOgrVectorAnnotation::loadExternalGeometryFile"
+                  << " DEBUG:"
+                  << "\nExternal projection loaded from geometry file."
+                  << "\nProjection dump:" << std::endl;
+               mapProj->print(ossimNotify(ossimNotifyLevel_DEBUG));
+            }
+         }
+      }
+   }
+}
+
+void ossimGdalOgrVectorAnnotation::loadExternalImageGeometryFromXml()
+{
+   ossimFilename filename = theFilename;
+   ossimString fileBase = filename.noExtension();
+   ossimFilename xmlFile = ossimString(fileBase + ".xml");
+   if (!xmlFile.exists())//try the xml file which includes the entire source file name
+   {
+      xmlFile = theFilename + ".xml";
+   }
+   if (!xmlFile.exists())
+   {
+      return;
+   }
+   ossimFgdcXmlDoc* fgdcXmlDoc = new ossimFgdcXmlDoc;
+   if ( fgdcXmlDoc->open(xmlFile) )
+   {
+      ossimRefPtr<ossimProjection> proj = fgdcXmlDoc->getProjection();
+      if ( proj.valid() )
+      {
+         theImageGeometry = new ossimImageGeometry;
+         theImageGeometry->setProjection( proj.get() );
+         theIsExternalGeomFlag = true;
+      }
+   }
+   delete fgdcXmlDoc;
+   fgdcXmlDoc = 0;
+}
+
+void ossimGdalOgrVectorAnnotation::loadOmdFile()
+{
+   ossimFilename filename = theFilename;
+   filename.setExtension(".omd");
+   if(!filename.exists())
+   {
+      filename.setExtension(".OMD");
+   }
+
+   if( filename.exists() )
+   {
+      ossimKeywordlist kwl;
+      if( kwl.addFile(filename) )
+      {
+         //---
+         // Because loadState can call open() we will not call it here to
+         // avoid a circuliar loop.  This duplicates some code but is safer.
+         //---
+         const char* lookup = 0;
+
+         // Border:
+         lookup = kwl.find(ossimKeywordNames::BORDER_SIZE_KW);
+         if (lookup)
+         {
+            theBorderSize = ossimString(lookup).toDouble();
+            ossimString unitPrefix = ossimKeywordNames::BORDER_SIZE_KW +
+               ossimString(".");
+      
+            theBorderSizeUnits = (ossimUnitType)ossimUnitTypeLut::instance()->
+               getEntryNumber(kwl, unitPrefix.c_str());
+            if(theBorderSizeUnits != OSSIM_UNIT_UNKNOWN)
+            {
+               ossimUnitConversionTool unitConvert(theBorderSize,
+                                                   theBorderSizeUnits);
+         
+               theBorderSize      = unitConvert.getValue(OSSIM_DEGREES);
+               theBorderSizeUnits = OSSIM_DEGREES;
+            }
+            else // assume degrees
+            {
+               theBorderSizeUnits = OSSIM_DEGREES;
+            }
+         }
+
+         // Brush color:
+         lookup = kwl.find(ossimKeywordNames::BRUSH_COLOR_KW);
+         if (lookup)
+         {
+            int r, g, b;
+            std::istringstream s(lookup);
+            s>>r>>g>>b;
+            theBrushColor = ossimRgbVector((ossim_uint8)r,
+                                           (ossim_uint8)g,
+                                           (ossim_uint8)b);
+         }
+         else
+         {
+            lookup = kwl.find(NORMALIZED_RGB_BRUSH_COLOR_KW);
+            if (lookup)
+            {
+               ossim_float64 r;
+               ossim_float64 g;
+               ossim_float64 b;
+               
+               std::istringstream in(lookup);
+               in >> r >> g >> b;
+               
+               if ( (r >= 0.0) && (r <=1.0) )
+               {
+                  theBrushColor.setR(static_cast<ossim_uint8>(r*255.0+0.5));
+               }
+               if ( (g >= 0.0) && (g <=1.0) )
+               {
+                  theBrushColor.setG(static_cast<ossim_uint8>(g*255.0+0.5));
+               }
+               if ( (b >= 0.0) && (b <=1.0) )
+               {
+                  theBrushColor.setB(static_cast<ossim_uint8>(b*255.0+0.5));
+               }
+            }
+         }
+
+         // Fill:
+         lookup = kwl.find(ossimKeywordNames::FILL_FLAG_KW);
+         if (lookup)
+         {
+            theFillFlag = ossimString(lookup).toBool();
+         }
+         
+         // Pen color:
+         lookup = kwl.find(ossimKeywordNames::PEN_COLOR_KW);
+         if (lookup)
+         {
+            int r, g, b;
+            std::istringstream s(lookup);
+            s>>r>>g>>b;
+            thePenColor = ossimRgbVector((ossim_uint8)r,
+                                         (ossim_uint8)g,
+                                         (ossim_uint8)b);
+         }
+         else
+         {
+            lookup = kwl.find(NORMALIZED_RGB_PEN_COLOR_KW);
+            if (lookup)
+            {
+               ossim_float64 r;
+               ossim_float64 g;
+               ossim_float64 b;
+               
+               std::istringstream in(lookup);
+               in >> r >> g >> b;
+               
+               if ( (r >= 0.0) && (r <=1.0) )
+               {
+                  thePenColor.setR(static_cast<ossim_uint8>(r * 255.0 + 0.5));
+               }
+               if ( (g >= 0.0) && (g <=1.0) )
+               {
+                  thePenColor.setG(static_cast<ossim_uint8>(g * 255.0 + 0.5));
+               }
+               if ( (b >= 0.0) && (b <=1.0) )
+               {
+                  thePenColor.setB(static_cast<ossim_uint8>(b * 255.0 + 0.5));
+               }
+            }
+         }
+
+         // Point size:
+         lookup = kwl.find(ossimKeywordNames::POINT_WIDTH_HEIGHT_KW);
+         if (!lookup)
+         {
+            lookup = kwl.find(POINT_SIZE_KW);
+         }
+         if (lookup)
+         {
+            ossim_float64 x;
+            ossim_float64 y;
+            
+            std::istringstream in(lookup);
+            in >> x >> y;
+            
+            if ( (x > 0.0) && (y > 0.0) )
+            {
+               thePointWidthHeight.x = x;
+               thePointWidthHeight.y = y;
+            }
+         }
+
+         // Thickness:
+         lookup = kwl.find(ossimKeywordNames::THICKNESS_KW);
+         if (lookup)
+         {
+            setThickness(ossimString(lookup).toInt32());
+         }
+
+         // Update the feature table.
+         updateAnnotationSettings();
+         
+      } // matches: if( kwl.addFile(filename) )
+      
+   } // matches: if(filename.exists())
+}
+
+void ossimGdalOgrVectorAnnotation::getDefaults()
+{
+   const char* lookup;
+
+   // Look for auto color flag:
+   bool autocolors = false;
+   lookup = ossimPreferences::instance()->
+      findPreference(SHAPEFILE_COLORS_AUTO_KW);
+   if (lookup)
+   {
+      autocolors = ossimString::toBool(ossimString(lookup));
+   }
+   
+   if (autocolors)
+   {
+      // Ensure the static index is within bounds of the array.
+      if (currentAutoColorArrayIndex >= AUTO_COLOR_ARRAY_COUNT)
+      {
+         currentAutoColorArrayIndex = 0;
+      }
+
+      thePenColor.setR(autoColorArray[currentAutoColorArrayIndex].r);
+      thePenColor.setG(autoColorArray[currentAutoColorArrayIndex].g);
+      thePenColor.setB(autoColorArray[currentAutoColorArrayIndex].b);
+
+      theBrushColor.setR(autoColorArray[currentAutoColorArrayIndex].r);
+      theBrushColor.setG(autoColorArray[currentAutoColorArrayIndex].g);
+      theBrushColor.setB(autoColorArray[currentAutoColorArrayIndex].b);
+      
+      ++currentAutoColorArrayIndex;
+      if (currentAutoColorArrayIndex >= AUTO_COLOR_ARRAY_COUNT)
+      {
+         currentAutoColorArrayIndex = 0;
+      }
+      
+   } // End of: if (autocolors)
+   else
+   {
+      // Look for pen color.
+      lookup = ossimPreferences::instance()->
+         findPreference(NORMALIZED_RGB_PEN_COLOR_KW);
+      if (lookup)
+      {
+         ossim_float64 r;
+         ossim_float64 g;
+         ossim_float64 b;
+         
+         std::istringstream in(lookup);
+         in >> r >> g >> b;
+         
+         if ( (r >= 0.0) && (r <=1.0) )
+         {
+            thePenColor.setR(static_cast<ossim_uint8>(r * 255.0 + 0.5));
+         }
+         if ( (g >= 0.0) && (g <=1.0) )
+         {
+            thePenColor.setG(static_cast<ossim_uint8>(g * 255.0 + 0.5));
+         }
+         if ( (b >= 0.0) && (b <=1.0) )
+         {
+            thePenColor.setB(static_cast<ossim_uint8>(b * 255.0 + 0.5));
+         }
+      }
+      
+      // Look for brush color.
+      lookup = ossimPreferences::instance()->
+         findPreference(NORMALIZED_RGB_BRUSH_COLOR_KW);
+      if (lookup)
+      {
+         ossim_float64 r;
+         ossim_float64 g;
+         ossim_float64 b;
+         
+         std::istringstream in(lookup);
+         in >> r >> g >> b;
+         
+         if ( (r >= 0.0) && (r <=1.0) )
+         {
+            theBrushColor.setR(static_cast<ossim_uint8>(r * 255.0 + 0.5));
+         }
+         if ( (g >= 0.0) && (g <=1.0) )
+         {
+            theBrushColor.setG(static_cast<ossim_uint8>(g * 255.0 + 0.5));
+         }
+         if ( (b >= 0.0) && (b <=1.0) )
+         {
+            theBrushColor.setB(static_cast<ossim_uint8>(b * 255.0 + 0.5));
+         }
+      }
+      
+   } // End of: if (autocolors){...}else{
+
+   // Look for point size.
+   lookup = ossimPreferences::instance()->
+      findPreference(POINT_SIZE_KW);
+   if (lookup)
+   {
+      ossim_float64 x;
+      ossim_float64 y;
+      
+      std::istringstream in(lookup);
+      in >> x >> y;
+
+      if ( (x > 0.0) && (y > 0.0) )
+      {
+         thePointWidthHeight.x = x;
+         thePointWidthHeight.y = y;
+      }
+   }   
+}
+
+void ossimGdalOgrVectorAnnotation::verifyViewParams()
+{
+   if (!theImageGeometry.valid())
+   {
+      return;
+   }
+   
+   ossimMapProjection* proj = PTR_CAST(ossimMapProjection,
+                                       theImageGeometry->getProjection());
+   if (!proj)
+   {
+      return;
+   }
+
+   ossimGpt ulGpt = proj->getUlGpt();
+   if ( ulGpt.isLatNan() || ulGpt.isLonNan() )
+   {
+      proj->setUlGpt( ossimGpt(theBoundingExtent.MaxY,
+                               theBoundingExtent.MinX) );
+   }
+   
+   if (proj->isGeographic())
+   {
+      ossimDpt pt = proj->getDecimalDegreesPerPixel();
+      if( pt.hasNans() )
+      {
+         // roughly... 10 meters per pixel in decimal degrees.
+         ossim_float64 d = 1.0 / 11131.49079;
+         proj->setDecimalDegreesPerPixel(ossimDpt(d, d));
+      }
+
+   }
+   else
+   {
+      ossimDpt pt = proj->getMetersPerPixel();
+      if (pt.hasNans())
+      {
+         proj->setMetersPerPixel(ossimDpt(10.0, 10.0));
+      }
+   }
+}
+
+std::multimap<long, ossimAnnotationObject*> ossimGdalOgrVectorAnnotation::getFeatureTable()
+{
+   if (theFeatureCacheTable.size() == 0)
+   {
+      initializeTables();
+   }
+   return theFeatureCacheTable;
+}
+
+bool ossimGdalOgrVectorAnnotation::setCurrentEntry(ossim_uint32 entryIdx)
+{
+   if (entryIdx < m_layerNames.size())
+   {
+      m_layerName = m_layerNames[entryIdx];
+      return open(theFilename);
+   }
+   return false;
+}
diff --git a/ossim_plugins/gdal/ossimGdalOgrVectorAnnotation.h b/ossim_plugins/gdal/ossimGdalOgrVectorAnnotation.h
new file mode 100644
index 0000000..224e0b5
--- /dev/null
+++ b/ossim_plugins/gdal/ossimGdalOgrVectorAnnotation.h
@@ -0,0 +1,184 @@
+//*******************************************************************
+// License: MIT
+//
+// See top level LICENSE.txt file.
+//
+// Author:  Garrett Potts
+//
+// Description:
+//
+// Contains class implementaiton for the class "ossimOgrGdalTileSource".
+//
+//*******************************************************************
+//  $Id: ossimGdalOgrVectorAnnotation.h 23664 2015-12-14 14:17:27Z dburken $
+#ifndef ossimGdalOgrVectorAnnotation_HEADER
+#define ossimGdalOgrVectorAnnotation_HEADER
+
+#include <map>
+#include <vector>
+#include <list>
+#include <gdal.h>
+#include <ogrsf_frmts.h>
+#include "../ossimPluginConstants.h"
+#include <ossim/base/ossimViewInterface.h>
+#include <ossim/base/ossimRgbVector.h>
+#include <ossim/imaging/ossimAnnotationSource.h>
+#include <ossim/imaging/ossimImageGeometry.h>
+#include <ossim/projection/ossimProjection.h>
+
+class ossimProjection;
+class ossimMapProjection;
+class ossimOgrGdalLayerNode;
+class ossimOgrGdalFeatureNode;
+class ossimAnnotationObject;
+
+class OSSIM_PLUGINS_DLL ossimGdalOgrVectorAnnotation :
+   public ossimAnnotationSource,
+   public ossimViewInterface
+{
+public:
+   ossimGdalOgrVectorAnnotation(ossimImageSource* inputSource=0);
+   virtual ~ossimGdalOgrVectorAnnotation();
+   virtual bool open();
+   virtual bool open(const ossimFilename& file);
+   virtual bool isOpen()const;
+   virtual void close();
+   virtual ossimFilename getFilename()const;
+   
+   virtual bool setView(ossimObject* baseObject);
+   
+   virtual ossimObject*       getView();
+   virtual const ossimObject* getView()const;
+
+   //! Returns the image geometry object associated with this tile source or NULL if non defined.
+   //! The geometry contains full-to-local image transform as well as projection (image-to-world)
+   virtual ossimRefPtr<ossimImageGeometry> getImageGeometry() const;
+
+   virtual ossimIrect getBoundingRect(ossim_uint32 resLevel=0)const;
+   virtual void computeBoundingRect();
+
+   virtual void drawAnnotations(ossimRefPtr<ossimImageData> tile);
+
+
+   virtual void setBrushColor(const ossimRgbVector& brushColor);
+   virtual void setPenColor(const ossimRgbVector& penColor);
+   virtual ossimRgbVector getPenColor()const;
+   virtual ossimRgbVector getBrushColor()const;
+   virtual double getPointRadius()const;
+   virtual void setPointRadius(double r);
+   virtual bool getFillFlag()const;
+   virtual void setFillFlag(bool flag);
+   virtual void setThickness(ossim_int32 thickness);
+   virtual ossim_int32 getThickness()const;
+
+   virtual void setProperty(ossimRefPtr<ossimProperty> property);
+   virtual ossimRefPtr<ossimProperty> getProperty(const ossimString& name)const;
+   virtual void getPropertyNames(std::vector<ossimString>& propertyNames)const;
+   
+   virtual bool saveState(ossimKeywordlist& kwl,
+                          const char* prefix=0)const;
+
+   virtual bool loadState(const ossimKeywordlist& kwl,
+                          const char* prefix=0);
+
+   virtual std::ostream& print(std::ostream& out) const;
+
+   std::multimap<long, ossimAnnotationObject*> getFeatureTable();
+
+   void setQuery(const ossimString& query);
+
+   void setGeometryBuffer(ossim_float64 distance, ossimUnitType type);
+
+   //OGRLayer::GetExtent() returns the MBR (minimal bounding rect) of the data in the layer. 
+   //So when only do ossim-info, it is not necessary to go through each feature to calculate
+   //the bounding which cause the memory allocate problem when the shape file is large.
+   void initializeBoundingRec(vector<ossimGpt> points);
+
+   bool setCurrentEntry(ossim_uint32 entryIdx);
+
+protected:
+   OGRDataSource                      *theDataSource;
+   OGRSFDriver                        *theDriver;
+   ossimFilename                       theFilename;
+   OGREnvelope                         theBoundingExtent;
+   ossimRefPtr<ossimImageGeometry>     theImageGeometry;
+   vector<bool>                        theLayersToRenderFlagList;
+   std::vector<ossimOgrGdalLayerNode*> theLayerTable;
+   ossimRgbVector                      thePenColor;
+   ossimRgbVector                      theBrushColor;
+   bool                                theFillFlag;
+   ossim_uint8                         theThickness;
+   ossimDpt                            thePointWidthHeight;
+   double                              theBorderSize;
+   ossimUnitType                       theBorderSizeUnits;
+   ossimDrect                          theImageBound;
+   bool                                theIsExternalGeomFlag;
+   
+   std::multimap<long, ossimAnnotationObject*> theFeatureCacheTable;
+
+   ossimString                                 m_query;
+   bool                                        m_needPenColor;
+   ossim_float64                               m_geometryDistance;
+   ossimUnitType                               m_geometryDistanceType;
+   ossimString                                 m_layerName;
+   std::vector<ossimString>                    m_layerNames;
+   
+   void computeDefaultView();
+
+   /** Uses theViewProjection */
+   void transformObjectsFromView();
+   
+   void loadPoint(long id, OGRPoint* point, ossimMapProjection* mapProj);
+   void loadMultiPoint(long id, OGRMultiPoint* multiPoint, ossimMapProjection* mapProj);
+   void loadMultiPolygon(long id, OGRMultiPolygon* multiPolygon, ossimMapProjection* mapProj);
+   void loadPolygon(long id, OGRPolygon* polygon, ossimMapProjection* mapProj);
+   void loadLineString(long id, OGRLineString* lineString, ossimMapProjection* mapProj);
+   void loadMultiLineString(long id, OGRMultiLineString* multiLineString, ossimMapProjection* mapProj);
+   
+   void getFeatures(std::list<long>& result,
+                    const ossimIrect& rect);
+   void getFeature(vector<ossimAnnotationObject*>& featureList,
+                   long id);
+   ossimProjection* createProjFromReference(OGRSpatialReference* reference)const;
+   void initializeTables();
+   void deleteTables();
+   void updateAnnotationSettings();
+
+   /**
+    * Will set theViewProjection if geometry file is present with projection.
+    * Also sets theIsExternalGeomFlag.
+    */
+   void loadExternalGeometryFile();
+
+   /**
+    * Will set theViewProjection if xml file is present with projection.
+    * Also sets theIsExternalGeomFlag.
+    */
+   void loadExternalImageGeometryFromXml();
+
+   /**
+    * Looks for "file.omd" and loads pen, brush and point settings if present.
+    */
+   void loadOmdFile();
+
+   /**
+    * Will set thePenColor and theBrushColor if keyword found in preferences.
+    *
+    * Keyword example:
+    * shapefile_normalized_rgb_pen_color:   0.004 1.0 0.004
+    * shapefile_normalized_rgb_brush_color: 0.004 1.0 0.004
+    */
+   void getDefaults();
+
+   /**
+    * @brief Checks for nan scale and tie point.  Sets to some default if
+    * nan.
+    */
+   void verifyViewParams();
+
+TYPE_DATA
+   
+}; // End of: class ossimGdalOgrVectorAnnotation
+
+#endif
+
diff --git a/ossim_plugins/gdal/ossimGdalOverviewBuilder.cpp b/ossim_plugins/gdal/ossimGdalOverviewBuilder.cpp
new file mode 100644
index 0000000..2fde512
--- /dev/null
+++ b/ossim_plugins/gdal/ossimGdalOverviewBuilder.cpp
@@ -0,0 +1,505 @@
+//----------------------------------------------------------------------------
+//
+// License:  See top level LICENSE.txt file.
+//
+// Author:  David Burken
+//
+// Description:  OSSIM wrapper for building gdal overviews (tiff or hfa) from
+// an ossim image handler using the GDAL library.
+//
+//----------------------------------------------------------------------------
+// $Id: ossimGdalOverviewBuilder.cpp 15766 2009-10-20 12:37:09Z gpotts $
+
+#include <cmath>
+#include <gdal_priv.h>
+
+#include <ossimGdalOverviewBuilder.h>
+#include <ossimGdalTiledDataset.h>
+#include <ossimGdalDataset.h>
+#include <ossim/base/ossimFilename.h>
+#include <ossim/base/ossimTrace.h>
+#include <ossim/imaging/ossimImageSource.h>
+#include <ossim/imaging/ossimImageHandler.h>
+#include <ossim/imaging/ossimImageSourceSequencer.h>
+
+RTTI_DEF1(ossimGdalOverviewBuilder,
+          "ossimGdalOverviewBuilder",
+          ossimOverviewBuilderBase);
+
+static const char* OVR_TYPE[] = { "unknown",
+                                  "gdal_tiff_nearest",
+                                  "gdal_tiff_average",
+                                  "gdal_hfa_nearest",
+                                  "gdal_hfa_average" };
+
+static const ossimTrace traceDebug(
+   ossimString("ossimGdalOverviewBuilder:debug"));
+
+ossimGdalOverviewBuilder::ossimGdalOverviewBuilder()
+   :
+   theDataset(0),
+   theOutputFile(),
+   theOverviewType(ossimGdalOverviewTiffAverage),
+   theLevels(0),
+   theGenerateHfaStatsFlag(false)
+{
+}
+
+ossimGdalOverviewBuilder::~ossimGdalOverviewBuilder()
+{
+   if ( theDataset )
+   {
+      delete theDataset;
+      theDataset = 0;
+   }
+}
+
+void ossimGdalOverviewBuilder::setOutputFile(const ossimFilename& file)
+{
+   theOutputFile = file;
+}
+
+ossimFilename ossimGdalOverviewBuilder::getOutputFile() const
+{
+   if (theOutputFile == ossimFilename::NIL)
+   {
+      if (theDataset)
+      {
+         if (theDataset->getImageHandler())
+         {
+            ossimFilename outputFile =
+               theDataset->getImageHandler()->getFilename();
+
+            switch (theOverviewType)
+            {
+               case ossimGdalOverviewHfaNearest:
+               case ossimGdalOverviewHfaAverage:  
+                  outputFile.setExtension(getExtensionFromType());
+                  break;
+               default:
+                  outputFile += ".ovr";
+                  break;
+            }
+            return outputFile;
+         }
+      }
+   }
+   
+   return theOutputFile;
+}
+
+bool ossimGdalOverviewBuilder::open(const ossimFilename& file)
+{
+   if (theDataset)
+   {
+      delete theDataset;
+   }
+   theDataset = new ossimGdalDataset;
+   return theDataset->open(file);
+}
+
+bool ossimGdalOverviewBuilder::setInputSource(ossimImageHandler* imageSource)
+{
+   if ( !imageSource )
+   {
+      return false;
+   }
+   
+   if (theDataset)
+   {
+      delete theDataset;
+   }
+
+   theDataset = new ossimGdalDataset();
+   theDataset->setImageHandler(imageSource);
+   return true;
+}
+
+bool ossimGdalOverviewBuilder::setOverviewType(const ossimString& type)
+{
+   if(type == OVR_TYPE[ossimGdalOverviewTiffNearest])
+   {
+      theOverviewType = ossimGdalOverviewTiffNearest;
+   }
+   else if(type == OVR_TYPE[ossimGdalOverviewTiffAverage])
+   {
+      theOverviewType = ossimGdalOverviewTiffAverage;
+   }
+   else if(type == OVR_TYPE[ossimGdalOverviewHfaNearest])
+   {
+      theOverviewType = ossimGdalOverviewHfaNearest;
+   }
+   else if(type == OVR_TYPE[ossimGdalOverviewHfaAverage])
+   {
+      theOverviewType = ossimGdalOverviewHfaAverage;
+   }
+   else
+   {
+      return false;
+   }
+   return true;
+}
+
+ossimString ossimGdalOverviewBuilder::getOverviewType() const
+{
+   return ossimString(OVR_TYPE[theOverviewType]);
+}
+
+void ossimGdalOverviewBuilder::getTypeNameList(
+   std::vector<ossimString>& typeList)const
+{
+   typeList.push_back(
+      ossimString(OVR_TYPE[ossimGdalOverviewTiffNearest]));
+   typeList.push_back(
+      ossimString(OVR_TYPE[ossimGdalOverviewTiffAverage]));
+   typeList.push_back(
+      ossimString(OVR_TYPE[ossimGdalOverviewHfaNearest]));
+   typeList.push_back(
+      ossimString(OVR_TYPE[ossimGdalOverviewHfaAverage]));
+}
+
+bool ossimGdalOverviewBuilder::execute()
+{
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimGdalOverviewBuilder::execute entered..."
+         << endl;
+   }
+
+   bool result = false;
+   
+   if (!theDataset || !theDataset->getImageHandler())
+   {
+      return result;
+   }
+
+   // Get the output file.
+   ossimFilename overviewFile = getOutputFile();
+
+   // Check the file.  Disallow same file overview building.
+   if (theDataset->getImageHandler()->getFilename() == overviewFile)
+   {
+      ossimNotify(ossimNotifyLevel_WARN)
+         << "Source image file and overview file cannot be the same!"
+         << std::endl;
+      return result;
+   }
+
+   if (theGenerateHfaStatsFlag)
+   {
+      theDataset->setGdalAcces(GA_Update);
+      theDataset->initGdalOverviewManager();
+      if (generateHfaStats() == false)
+      {
+         cerr << " generateHfaStats failed..." << endl;
+      }
+      else
+      {
+         // delete theDataset;
+         // return true;
+      }
+   }
+
+   // theDataset->setGdalAcces(GA_Update);
+
+   theDataset->initGdalOverviewManager();
+   
+   // Get the number of bands.
+   // ossim_uint32 bands = theDataset->getImageHandler()->
+   // getNumberOfOutputBands();
+
+   // Get the resampling string.
+   ossimString pszResampling = getGdalResamplingType();
+
+   // Compute the number of levels.
+   ossimIrect bounds = theDataset->getImageHandler()->getBoundingRect();
+   ossim_uint32 minBound = ossim::min( bounds.width(), bounds.height() );
+
+   //---
+   // Set the decimation levels.  If set through the property interface use
+   // that; else compute.
+   //---
+   ossim_int32 numberOfLevels = 0;
+
+   if (theLevels.size())
+   {
+      numberOfLevels = theLevels.size();
+   }
+   else
+   {
+      ossim_uint32 stopDim = getOverviewStopDimension();
+      while (minBound > stopDim)
+      {
+         minBound = minBound / 2;
+         ++numberOfLevels;
+      }
+      
+      if (numberOfLevels == 0)
+      {
+         return result; // nothing to do.
+      }
+   }
+   
+   ossim_int32* levelDecimationFactor = new ossim_int32[numberOfLevels];
+
+   ossim_uint32 idx;
+
+   if (theLevels.size())
+   {
+      for (idx = 0; idx < theLevels.size(); ++idx)
+      {
+         levelDecimationFactor[idx] = theLevels[idx];
+      }
+   }
+   else
+   {
+      levelDecimationFactor[0] = 2;
+      for(idx = 1; idx < static_cast<ossim_uint32>(numberOfLevels); ++idx)
+      {
+         levelDecimationFactor[idx] = levelDecimationFactor[idx-1]*2;
+      }
+   }
+   
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimGdalOverviewBuilder::execute DEBUG:"
+         << "\noverviewFilename:   " << overviewFile
+         << "\npszResampling:      " << pszResampling
+         << "\nnumberOfLevels:     " << numberOfLevels
+         << endl;
+      for(idx = 0; idx < static_cast<ossim_uint32>(numberOfLevels); ++idx)
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG)
+            << "levelDecimationFactor["
+            << idx << "]: " << levelDecimationFactor[idx]
+            << endl;
+      }
+   }
+
+   CPLErr eErr = CE_None;
+
+   if ( (theOverviewType == ossimGdalOverviewHfaAverage) ||
+        (theOverviewType == ossimGdalOverviewHfaNearest) )
+   {
+      CPLSetConfigOption("USE_RRD", "YES");
+   }
+
+   if( theDataset->BuildOverviews( pszResampling.c_str(), 
+                                   numberOfLevels,
+                                   levelDecimationFactor,
+                                   0,
+                                   0,
+                                   GDALTermProgress,
+                                   0 ) != CE_None )
+   {
+      ossimNotify(ossimNotifyLevel_WARN)
+         << "Overview building failed." << std::endl;
+   }
+
+   if ( levelDecimationFactor )
+   {
+      delete [] levelDecimationFactor;
+      levelDecimationFactor = 0;
+   }
+   
+   if (eErr  == CE_None )
+   {
+      result = true;
+   }
+
+   if (result == true)
+   {
+      ossimNotify(ossimNotifyLevel_NOTICE)
+         << "Wrote file:  " << overviewFile << std::endl;
+   }
+
+   return result;
+}
+
+void ossimGdalOverviewBuilder::setProperty(ossimRefPtr<ossimProperty> property)
+{
+   if (property.valid() == false)
+   {
+      return;
+   }
+
+   ossimString s = property->getName();
+   s.downcase();
+   if ( s == "levels" )
+   {
+      ossimString value;
+      property->valueToString(value);
+      
+      if (traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG)
+            << "ossimGdalOverviewBuilder::setProperty DEBUG:"
+            << std::endl;
+      }
+      theLevels.clear();
+      std::vector<ossimString> v1 = value.split(",");
+      for (ossim_uint32 i = 0; i < v1.size(); ++i)
+      {
+         ossim_int32 level = v1[i].toInt32();
+         theLevels.push_back(level);
+         if (traceDebug())
+         {
+            ossimNotify(ossimNotifyLevel_DEBUG)
+               << "level[" << i << "]:  " << level << std::endl;
+         }
+      }
+   }
+   else if ( s == "generate-hfa-stats" )
+   {
+      theGenerateHfaStatsFlag = true;
+   }
+}
+
+void ossimGdalOverviewBuilder::getPropertyNames(
+   std::vector<ossimString>& propertyNames)const
+{
+   propertyNames.push_back(ossimString("levels"));
+   propertyNames.push_back(ossimString("generate-hfa-stats"));
+}
+
+std::ostream& ossimGdalOverviewBuilder::print(std::ostream& out) const
+{
+   out << "ossimGdalOverviewBuilder::print"
+       << "\nfilename: " << theOutputFile.c_str()
+       << "\noverview_type: "
+       << OVR_TYPE[theOverviewType]
+       << "\nresampling type: " << getGdalResamplingType()
+       << std::endl;
+   return out;
+}
+
+bool ossimGdalOverviewBuilder::generateHfaStats() const
+{
+   // GDALAllRegister();
+   
+   //---
+   // Equivalent:
+   // gdal_translate -of HFA -co AUX=YES -co STATISTICS=YES
+   // -co DEPENDENT_FILE=utm.tif utm.tif utm.aux
+   //---
+   bool result = false;
+
+   if (!theDataset)
+   {
+      return result;
+   }
+   if (!theDataset->getImageHandler())
+   {
+      return result;
+   }
+   
+   ossimFilename sourceImageFile =
+      theDataset->getImageHandler()->getFilename();
+   if (sourceImageFile.empty())
+   {
+      return result;
+   }
+
+   // This is the output driver.
+   GDALDriverH hDriver = GDALGetDriverByName( "HFA" );
+   if (!hDriver)
+   {
+      return false;
+   }
+
+   // This is the source data set.
+   GDALDatasetH hDataset = theDataset;
+
+   GDALDatasetH	hOutDS   = 0; 
+   int bStrict = true;
+   
+   char** papszCreateOptions = 0;
+   GDALProgressFunc pfnProgress = GDALTermProgress;
+   
+   ossimString s = "DEPENDENT_FILE=";
+   s += sourceImageFile.file(); // Must not have absolute path...
+   
+   papszCreateOptions = CSLAddString( papszCreateOptions, "AUX=YES");
+   papszCreateOptions = CSLAddString( papszCreateOptions, "STATISTICS=YES");
+   papszCreateOptions = CSLAddString( papszCreateOptions, s.c_str() );
+
+   hOutDS = GDALCreateCopy( hDriver,
+                            getOutputFile().c_str(),
+                            hDataset, 
+                            bStrict,
+                            papszCreateOptions, 
+                            pfnProgress,
+                            0 );
+
+   CSLDestroy( papszCreateOptions );
+   if( hOutDS != 0 )
+   {
+      GDALClose( hOutDS );
+   }
+   
+   return true;
+}
+
+ossimString ossimGdalOverviewBuilder::getGdalResamplingType() const
+{
+   ossimString result;
+   switch (theOverviewType)
+   {
+      case ossimGdalOverviewTiffNearest:
+      case ossimGdalOverviewHfaNearest:
+         result = "nearest";
+         break;
+      case ossimGdalOverviewTiffAverage:
+      case ossimGdalOverviewHfaAverage:
+         result = "average";
+         break;
+      case ossimGdalOverviewType_UNKNOWN:
+         result = "unknown";
+         break;
+   }
+   return result;
+}
+
+ossimString ossimGdalOverviewBuilder::getExtensionFromType() const
+{
+   ossimString result;
+   switch (theOverviewType)
+   {
+      case ossimGdalOverviewHfaNearest:
+      case ossimGdalOverviewHfaAverage:  
+         result = "aux";
+         break;
+
+      default:
+         result = "ovr";
+         break;
+   }
+   return result;
+}
+
+
+
+ossimObject* ossimGdalOverviewBuilder::getObject()
+{
+   return this;
+}
+
+const ossimObject* ossimGdalOverviewBuilder::getObject() const
+{
+   return this;
+}
+
+bool ossimGdalOverviewBuilder::canConnectMyInputTo(
+   ossim_int32 index,
+   const ossimConnectableObject* obj) const
+{
+   if ( (index == 0) &&
+        PTR_CAST(ossimImageHandler, obj) )
+   {
+      return true;
+   }
+
+   return false;
+}
diff --git a/ossim_plugins/gdal/ossimGdalOverviewBuilder.h b/ossim_plugins/gdal/ossimGdalOverviewBuilder.h
new file mode 100644
index 0000000..feea4b4
--- /dev/null
+++ b/ossim_plugins/gdal/ossimGdalOverviewBuilder.h
@@ -0,0 +1,182 @@
+//----------------------------------------------------------------------------
+//
+// License:  See top level LICENSE.txt file.
+//
+// Author:  David Burken
+//
+// Description:  OSSIM wrapper for building gdal overviews (tiff or hfa) from
+// an ossim image source.
+//
+//----------------------------------------------------------------------------
+// $Id: ossimGdalOverviewBuilder.h 15833 2009-10-29 01:41:53Z eshirschorn $
+
+#ifndef ossimGdalOverviewBuilder_HEADER
+#define ossimGdalOverviewBuilder_HEADER
+
+#include <vector>
+
+#include <ossim/base/ossimConstants.h>
+#include <ossim/base/ossimFilename.h>
+#include <ossim/base/ossimRefPtr.h>
+#include <ossim/base/ossimProperty.h>
+#include <ossim/imaging/ossimOverviewBuilderBase.h>
+
+class ossimImageSource;
+class ossimGdalDataset;
+
+/**
+ * @brief ossimGdalOverviewBuilder Class to build overviews from the GDAL
+ * library.
+ */
+class ossimGdalOverviewBuilder
+   :
+   public ossimOverviewBuilderBase
+{
+public:
+
+   /** @brief Enumerations for the type of GDAL overviews to build. */
+   enum ossimGdalOverviewType
+   {
+      ossimGdalOverviewType_UNKNOWN = 0,
+      ossimGdalOverviewTiffNearest  = 1,
+      ossimGdalOverviewTiffAverage  = 2,
+      ossimGdalOverviewHfaNearest   = 3,
+      ossimGdalOverviewHfaAverage   = 4
+   };
+
+   /** @brief default constructor */
+   ossimGdalOverviewBuilder();
+
+   /** @brief virtual destructor */
+   virtual ~ossimGdalOverviewBuilder();
+
+   /**
+    * @brief Open that takes a file name.
+    * @param file The file to open.
+    * @return true on success, false on error.
+    */
+   bool open(const ossimFilename& file);
+
+   /**
+    * @brief Builds the overviews.
+    *
+    * @return true on success, false on error.
+    *
+    * @note If setOutputFile was not called the output name will be derived
+    * from the image name.  If image was "foo.tif" the overview file will
+    * be "foo.rrd" or "foo.ovr".
+    */
+   virtual bool execute();
+
+      /**
+    * @brief Sets the input to the builder. Satisfies pure virtual from
+    * ossimOverviewBuilderBase.
+    * @param imageSource The input to the builder.
+    * @return True on successful initializion, false on error.
+    */
+   virtual bool setInputSource(ossimImageHandler* imageSource);
+   
+   /**
+    * @brief Sets the output filename.
+    * Satisfies pure virtual from ossimOverviewBuilderBase.
+    * @param file The output file name.
+    */
+   virtual void  setOutputFile(const ossimFilename& file);
+
+   /**
+    * Returns the output.  This will be derived from the input file if not
+    * explicitly set.
+    * 
+    * @return The output filename.
+    */
+   virtual ossimFilename getOutputFile() const;
+
+   /**
+    * @brief Sets the overview output type.
+    *
+    * Satisfies pure virtual from ossimOverviewBuilderBase.
+    * 
+    * Currently handled types are:
+    * "ossim_tiff_nearest" and "ossim_tiff_box"
+    *
+    * @param type This should be the string representing the type.  This method
+    * will do nothing if type is not handled and return false.
+    *
+    * @return true if type is handled, false if not.
+    */
+   virtual bool setOverviewType(const ossimString& type);
+
+   /**
+    * @brief Gets the overview type.
+    * Satisfies pure virtual from ossimOverviewBuilderBase.
+    * @return The overview output type as a string.
+    */
+   virtual ossimString getOverviewType() const;
+
+   /**
+    * @brief Method to populate class supported types.
+    * Satisfies pure virtual from ossimOverviewBuilderBase.
+    * @param typeList List of ossimStrings to add to.
+    */
+   virtual void getTypeNameList(std::vector<ossimString>& typeList)const;
+
+   /**
+    * @return ossimObject* to this object. Satisfies pure virtual.
+    */
+   virtual ossimObject* getObject();
+
+   /**
+    * @return const ossimObject* to this object.  Satisfies pure virtual.
+    */
+   virtual const ossimObject* getObject() const;
+
+   /**
+    * @return true if input is an image handler.  Satisfies pure virtual.
+    */
+   virtual bool canConnectMyInputTo(ossim_int32 index,
+                                    const ossimConnectableObject* obj) const;
+
+   /**
+    * @brief Method to set properties.
+    * @param property Property to set.
+    *
+    * @note Currently supported property:
+    * name=levels, value should be list of levels separated by a comma with
+    * no spaces. Example: "2,4,8,16,32,64"
+    */
+   virtual void setProperty(ossimRefPtr<ossimProperty> property);
+
+   /**
+    * @brief Method to populate the list of property names.
+    * @param propertyNames List to populate.  This does not clear the list
+    * just adds to it.
+    */
+   virtual void getPropertyNames(std::vector<ossimString>& propertyNames)const;
+   
+   /**
+    * @brief print method.
+    * @return std::ostream&
+    */
+   virtual std::ostream& print(std::ostream& out) const;
+
+private:
+
+   bool generateHfaStats() const;
+
+   /** @return The gdal resampling string from theOverviewType. */
+   ossimString getGdalResamplingType() const;
+
+   /** @return extension like "ovr" or "rrd". */
+   ossimString getExtensionFromType() const;
+   
+   ossimGdalDataset*               theDataset;
+   ossimFilename                   theOutputFile;
+   ossimGdalOverviewType           theOverviewType;
+   std::vector<ossim_int32>        theLevels; // like 2, 4, 8, 16, 32
+   bool                            theGenerateHfaStatsFlag;
+
+   /** for rtti stuff */
+   TYPE_DATA
+};
+
+#endif /* End if "#ifndef ossimGdalOverviewBuilder_HEADER" */
diff --git a/ossim_plugins/gdal/ossimGdalOverviewBuilderFactory.cpp b/ossim_plugins/gdal/ossimGdalOverviewBuilderFactory.cpp
new file mode 100644
index 0000000..1ba1c8b
--- /dev/null
+++ b/ossim_plugins/gdal/ossimGdalOverviewBuilderFactory.cpp
@@ -0,0 +1,68 @@
+//----------------------------------------------------------------------------
+// 
+// See top level LICENSE.txt file.
+//
+// Author:  David Burken
+//
+// Description: .
+//
+//----------------------------------------------------------------------------
+// $Id: ossimGdalOverviewBuilderFactory.cpp 16273 2010-01-06 00:42:09Z gpotts $
+
+#include <ossimGdalOverviewBuilderFactory.h>
+#include <ossimGdalOverviewBuilder.h>
+
+ossimGdalOverviewBuilderFactory*
+ossimGdalOverviewBuilderFactory::theInstance = 0;
+
+ossimGdalOverviewBuilderFactory* ossimGdalOverviewBuilderFactory::instance()
+{
+   if ( !theInstance )
+   {
+      theInstance = new ossimGdalOverviewBuilderFactory();
+   }
+   return theInstance;
+}
+
+ossimGdalOverviewBuilderFactory::~ossimGdalOverviewBuilderFactory()
+{
+   theInstance = 0;
+}
+
+ossimOverviewBuilderBase* ossimGdalOverviewBuilderFactory::createBuilder(
+   const ossimString& typeName) const
+{
+   ossimRefPtr<ossimOverviewBuilderBase> result = new  ossimGdalOverviewBuilder();
+   if ( result->hasOverviewType(typeName) == true )
+   {
+      // Capture the type.  (This builder has more than one.)
+      result->setOverviewType(typeName);
+   }
+   else
+   {
+      result = 0;
+   }
+   
+   return result.release();
+}
+
+void ossimGdalOverviewBuilderFactory::getTypeNameList(
+   std::vector<ossimString>& typeList) const
+{
+   ossimRefPtr<ossimOverviewBuilderBase> builder = new  ossimGdalOverviewBuilder();
+   builder->getTypeNameList(typeList);
+}
+
+ossimGdalOverviewBuilderFactory::ossimGdalOverviewBuilderFactory()
+{
+}
+
+ossimGdalOverviewBuilderFactory::ossimGdalOverviewBuilderFactory(
+   const ossimGdalOverviewBuilderFactory& /* obj */)
+{
+}
+
+void ossimGdalOverviewBuilderFactory::operator=(
+   const ossimGdalOverviewBuilderFactory& /* rhs */)
+{
+}
diff --git a/ossim_plugins/gdal/ossimGdalOverviewBuilderFactory.h b/ossim_plugins/gdal/ossimGdalOverviewBuilderFactory.h
new file mode 100644
index 0000000..b4cb04b
--- /dev/null
+++ b/ossim_plugins/gdal/ossimGdalOverviewBuilderFactory.h
@@ -0,0 +1,68 @@
+//----------------------------------------------------------------------------
+// 
+// See top level LICENSE.txt file.
+//
+// Author:  David Burken
+//
+// Description: The ossim overview builder factory.
+//
+//----------------------------------------------------------------------------
+// $Id: ossimGdalOverviewBuilderFactory.h 15833 2009-10-29 01:41:53Z eshirschorn $
+
+#ifndef ossimGdalOverviewBuilderFactory_HEADER
+#define ossimGdalOverviewBuilderFactory_HEADER
+
+#include <ossim/base/ossimConstants.h>
+#include <ossim/imaging/ossimOverviewBuilderFactoryBase.h>
+
+
+class ossimOverviewBuilderBase;
+class ossimString;
+
+/**
+ * @class ossimGdalOverviewBuilderFactory
+ * @brief The ossim overview builder factory.
+ */
+class ossimGdalOverviewBuilderFactory:
+   public ossimOverviewBuilderFactoryBase
+{
+public:
+
+   /** @brief static instance method. */
+   static ossimGdalOverviewBuilderFactory* instance();
+   
+   /** virtual destructor */
+   virtual ~ossimGdalOverviewBuilderFactory();
+
+   /**
+    * @brief Creates a builder from a string.  This should match a string from
+    * the getTypeNameList() method.  Pure virtual.
+    * 
+    * @return Pointer to ossimOverviewBuilderBase or NULL is not found
+    * within registered factories.
+    */
+   virtual ossimOverviewBuilderBase* createBuilder(
+      const ossimString& typeName) const;
+
+   /**
+    * @brief Method to populate a list of supported types for the factory.
+    * registered to this registry.  Pure virtual.
+    *
+    * @param typeList List of ossimStrings to add to.
+    */
+   virtual void getTypeNameList(std::vector<ossimString>& typeList)const;
+
+private:
+   /** default constructor hidden from use */
+   ossimGdalOverviewBuilderFactory();
+
+   /** copy constructor hidden from use */
+   ossimGdalOverviewBuilderFactory(const ossimGdalOverviewBuilderFactory& obj);
+
+   /** operator= hidden from use. */
+   void operator=(const ossimGdalOverviewBuilderFactory& rhs);
+
+   static ossimGdalOverviewBuilderFactory* theInstance;
+};
+
+#endif /* #ifndef ossimGdalOverviewBuilderFactory_HEADER */
diff --git a/ossim_plugins/gdal/ossimGdalPluginInit.cpp b/ossim_plugins/gdal/ossimGdalPluginInit.cpp
new file mode 100644
index 0000000..bf89d88
--- /dev/null
+++ b/ossim_plugins/gdal/ossimGdalPluginInit.cpp
@@ -0,0 +1,128 @@
+//*******************************************************************
+// Copyright (C) 2005 David Burken, all rights reserved.
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author:  David Burken
+//*******************************************************************
+//  $Id: ossimGdalPluginInit.cpp 23664 2015-12-14 14:17:27Z dburken $
+#include <gdal.h>
+#include <ossim/plugin/ossimSharedObjectBridge.h>
+#include <ossimPluginConstants.h>
+#include <ossimGdalFactory.h>
+#include <ossimGdalObjectFactory.h>
+#include <ossimGdalImageWriterFactory.h>
+#include <ossimGdalInfoFactory.h>
+#include <ossimGdalProjectionFactory.h>
+#include <ossimGdalOverviewBuilderFactory.h>
+#include <ossim/base/ossimObjectFactoryRegistry.h>
+#include <ossim/imaging/ossimImageHandlerRegistry.h>
+#include <ossim/imaging/ossimImageWriterFactoryRegistry.h>
+#include <ossim/imaging/ossimOverviewBuilderFactoryRegistry.h>
+#include <ossim/projection/ossimProjectionFactoryRegistry.h>
+#include <ossim/support_data/ossimInfoFactoryRegistry.h>
+
+static void setDescription(ossimString& description)
+{
+   description = "GDAL Plugin\n\n";
+   
+   int driverCount = GDALGetDriverCount();
+   int idx = 0;
+   description += "GDAL Supported formats\n";
+   for(idx = 0; idx < driverCount; ++idx)
+   {
+      GDALDriverH driver = GDALGetDriver(idx);
+      if(driver)
+      {
+         description += "  name: ";
+         description += ossimString(GDALGetDriverShortName(driver)) + " " + ossimString(GDALGetDriverLongName(driver)) + "\n";
+      }
+   }
+}
+
+
+extern "C"
+{
+   ossimSharedObjectInfo  myInfo;
+   ossimString theDescription;
+   std::vector<ossimString> theObjList;
+   const char* getDescription()
+   {
+      return theDescription.c_str();
+   }
+   int getNumberOfClassNames()
+   {
+      return (int)theObjList.size();
+   }
+   const char* getClassName(int idx)
+   {
+      if(idx < (int)theObjList.size())
+      {
+         return theObjList[0].c_str();
+      }
+      return (const char*)0;
+   }
+
+   /* Note symbols need to be exported on windoze... */ 
+   OSSIM_PLUGINS_DLL void ossimSharedLibraryInitialize(
+               ossimSharedObjectInfo** info, 
+               const char* options)
+   {    
+      myInfo.getDescription = getDescription;
+      myInfo.getNumberOfClassNames = getNumberOfClassNames;
+      myInfo.getClassName = getClassName;
+      
+      *info = &myInfo;
+      ossimKeywordlist kwl;
+      kwl.parseString(ossimString(options));
+
+      /* Register the readers... */
+     ossimImageHandlerRegistry::instance()->
+        registerFactory(ossimGdalFactory::instance(), ossimString(kwl.find("read_factory.location")).downcase() == "front" );
+
+     /* Register the writers... */
+     ossimImageWriterFactoryRegistry::instance()->
+        registerFactory(ossimGdalImageWriterFactory::instance(), ossimString(kwl.find("writer_factory.location")).downcase() == "front" );
+
+     /* Register the overview builder factory. */
+     ossimOverviewBuilderFactoryRegistry::instance()->
+        registerFactory(ossimGdalOverviewBuilderFactory::instance());
+
+     ossimProjectionFactoryRegistry::instance()->
+        registerFactory(ossimGdalProjectionFactory::instance());
+
+     /* Register generic objects... */
+     ossimObjectFactoryRegistry::instance()->
+        registerFactory(ossimGdalObjectFactory::instance());
+
+     /* Register gdal info factoy... */
+     ossimInfoFactoryRegistry::instance()->
+       registerFactory(ossimGdalInfoFactory::instance());
+
+     setDescription(theDescription);
+  }
+
+   /* Note symbols need to be exported on windoze... */ 
+  OSSIM_PLUGINS_DLL void ossimSharedLibraryFinalize()
+  {
+     ossimImageHandlerRegistry::instance()->
+        unregisterFactory(ossimGdalFactory::instance());
+
+     ossimImageWriterFactoryRegistry::instance()->
+        unregisterFactory(ossimGdalImageWriterFactory::instance());
+
+     ossimOverviewBuilderFactoryRegistry::instance()->
+        unregisterFactory(ossimGdalOverviewBuilderFactory::instance());
+
+     ossimProjectionFactoryRegistry::instance()->unregisterFactory(ossimGdalProjectionFactory::instance());
+
+     ossimObjectFactoryRegistry::instance()->
+        unregisterFactory(ossimGdalObjectFactory::instance());
+
+     ossimInfoFactoryRegistry::instance()->
+       unregisterFactory(ossimGdalInfoFactory::instance());
+  }
+}
+
diff --git a/ossim_plugins/gdal/ossimGdalProjectionFactory.cpp b/ossim_plugins/gdal/ossimGdalProjectionFactory.cpp
new file mode 100644
index 0000000..cf3d6f1
--- /dev/null
+++ b/ossim_plugins/gdal/ossimGdalProjectionFactory.cpp
@@ -0,0 +1,438 @@
+//*****************************************************************************
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+// DESCRIPTION:
+//   Contains implementation of class ossimMapProjectionFactory
+//
+//*****************************************************************************
+//  $Id: ossimGdalProjectionFactory.cpp 23664 2015-12-14 14:17:27Z dburken $
+#include <sstream>
+#include "ossimGdalProjectionFactory.h"
+#include "ossimGdalTileSource.h"
+#include <ossim/base/ossimKeywordNames.h>
+#include <ossim/projection/ossimProjectionFactoryRegistry.h>
+#include <ossim/projection/ossimUtmProjection.h>
+#include <ossim/projection/ossimEquDistCylProjection.h>
+#include <ossim/projection/ossimEquDistCylProjection.h>
+#include <ossim/projection/ossimTransMercatorProjection.h>
+#include <ossim/projection/ossimOrthoGraphicProjection.h>
+#include "ossimOgcWktTranslator.h"
+#include <ossim/base/ossimTrace.h>
+#include "ossimOgcWktTranslator.h"
+#include <ossim/projection/ossimPolynomProjection.h>
+#include <ossim/projection/ossimBilinearProjection.h>
+#include <gdal_priv.h>
+#include <cpl_string.h>
+#include <ossim/base/ossimTieGptSet.h>
+#include <ossim/base/ossimUnitConversionTool.h>
+#include <ossim/base/ossimUnitTypeLut.h>
+
+static ossimTrace traceDebug("ossimGdalProjectionFactory:debug");
+
+ossimGdalProjectionFactory* ossimGdalProjectionFactory::theInstance = 0;
+static ossimOgcWktTranslator wktTranslator;
+
+ossimGdalProjectionFactory* ossimGdalProjectionFactory::instance()
+{
+   if(!theInstance)
+   {
+      theInstance = new ossimGdalProjectionFactory;
+   }
+
+   return (ossimGdalProjectionFactory*) theInstance;
+}
+
+ossimProjection* ossimGdalProjectionFactory::createProjection(const ossimFilename& filename,
+                                                             ossim_uint32 entryIdx)const
+{
+   ossimKeywordlist kwl;
+//    ossimRefPtr<ossimImageHandler> h = new ossimGdalTileSource;
+   //std::cout << "ossimGdalProjectionFactory::createProjection: " << filename << std::endl;
+   GDALDatasetH  h; 
+   GDALDriverH   driverH = 0;
+   ossimProjection* proj = 0;
+
+   if(ossimString(filename).trim().empty()) return 0;
+
+   h = GDALOpen(filename.c_str(), GA_ReadOnly);
+   if(h)
+   {
+      driverH = GDALGetDatasetDriver( h );
+      ossimString driverName( driverH ? GDALGetDriverShortName( driverH ) : "" );
+      // use OSSIM's projection loader for NITF
+      //
+      if(driverName == "NITF")
+      {
+         GDALClose(h);
+         return 0;
+      }
+      if(entryIdx != 0)
+      {
+         char** papszMetadata = GDALGetMetadata( h, "SUBDATASETS" );
+
+         //---
+         // ??? (drb) Should this be:
+         // if ( entryIdx >= CSLCount(papszMetadata) ) close...
+         //---
+         if( papszMetadata&&(CSLCount(papszMetadata) < static_cast<ossim_int32>(entryIdx)) )
+         {
+            ossimNotify(ossimNotifyLevel_WARN) << "ossimGdalProjectionFactory::createProjection: We don't support multi entry handlers through the factory yet, only through the handler!";
+            GDALClose(h);
+            return 0;
+         }
+         else
+         {
+            GDALClose(h);
+            return 0;
+         }
+      }
+
+      ossimString wkt(GDALGetProjectionRef( h ));
+      double geoTransform[6];
+      bool transOk = GDALGetGeoTransform( h, geoTransform ) == CE_None;
+      bool wktTranslatorOk = wkt.empty()?false:wktTranslator.toOssimKwl(wkt, kwl);
+      if(!wktTranslatorOk)
+      {
+         ossim_uint32 gcpCount = GDALGetGCPCount(h);
+         if(gcpCount > 3)
+         {
+            ossim_uint32 idx = 0;
+            const GDAL_GCP* gcpList = GDALGetGCPs(h);
+            ossimTieGptSet tieSet;
+            if(gcpList)
+            {
+               for(idx = 0; idx < gcpCount; ++idx)
+               {
+                  ossimDpt dpt(gcpList[idx].dfGCPPixel,
+                               gcpList[idx].dfGCPLine);
+                  ossimGpt gpt(gcpList[idx].dfGCPY,
+                               gcpList[idx].dfGCPX,
+                               gcpList[idx].dfGCPZ);
+                  tieSet.addTiePoint(new ossimTieGpt(gpt, dpt, .5));
+               }
+
+               //ossimPolynomProjection* tempProj = new ossimPolynomProjection;
+               ossimBilinearProjection* tempProj = new ossimBilinearProjection;
+			   //tempProj->setupOptimizer("1 x y x2 xy y2 x3 y3 xy2 x2y z xz yz");
+               tempProj->optimizeFit(tieSet);
+               proj = tempProj;
+            }
+         }
+      }
+      if ( transOk && proj==0 )
+      {
+         ossimString proj_type(kwl.find(ossimKeywordNames::TYPE_KW));
+         ossimString datum_type(kwl.find(ossimKeywordNames::DATUM_KW));
+         ossimString units(kwl.find(ossimKeywordNames::UNITS_KW));
+         if ( proj_type.trim().empty() &&
+              (driverName == "MrSID" || driverName == "JP2MrSID") )
+         {
+            bool bClose = true;
+            // ESH 04/2008, #54: if no rotation factors use geographic system
+            if( geoTransform[2] == 0.0 && geoTransform[4] == 0.0 )
+            {
+               ossimString projTag( GDALGetMetadataItem( h, "IMG__PROJECTION_NAME", "" ) );
+               if ( projTag.contains("Geographic") )
+               {
+                  bClose = false;
+
+                  kwl.add(ossimKeywordNames::TYPE_KW,
+                          "ossimEquDistCylProjection", true);
+                  proj_type = kwl.find( ossimKeywordNames::TYPE_KW );
+
+                  // Assign units if set in Metadata
+                  ossimString unitTag( GDALGetMetadataItem( h, "IMG__HORIZONTAL_UNITS", "" ) );
+                  if ( unitTag.contains("dd") ) // decimal degrees
+                  {
+                     units = "degrees";
+                  }
+                  else if ( unitTag.contains("dm") ) // decimal minutes
+                  {
+                     units = "minutes";
+                  }
+                  else if ( unitTag.contains("ds") ) // decimal seconds
+                  {
+                     units = "seconds";
+                  }
+               }
+            }
+
+            if ( bClose == true )
+            {
+               GDALClose(h);
+               return 0;
+            }
+         }
+
+         // Pixel-is-point of pixel-is area affects the location of the tiepoint since OSSIM is
+         // always pixel-is-point so 1/2 pixel shift may be necessary:
+         if((driverName == "MrSID") || (driverName == "JP2MrSID") || (driverName == "AIG"))
+         {
+            const char* rasterTypeStr = GDALGetMetadataItem( h, "GEOTIFF_CHAR__GTRasterTypeGeoKey", "" );
+            ossimString rasterTypeTag( rasterTypeStr );
+
+            // If the raster type is pixel_is_area, shift the tie point by
+            // half a pixel to locate it at the pixel center.
+            if ((driverName == "AIG") || (rasterTypeTag.contains("RasterPixelIsArea")))
+            {
+               geoTransform[0] += fabs(geoTransform[1]) / 2.0;
+               geoTransform[3] -= fabs(geoTransform[5]) / 2.0;
+            }
+         }
+         else
+         {
+            // Conventionally, HFA stores the pixel alignment type for each band. Here assume all
+            // bands are the same. Consider only the first band:
+            GDALRasterBandH bBand = GDALGetRasterBand( h, 1 );
+            char** papszMetadata = GDALGetMetadata( bBand, NULL );
+            if (CSLCount(papszMetadata) > 0)
+            {
+               for(int i = 0; papszMetadata[i] != NULL; i++ )
+               {
+                  ossimString metaStr = papszMetadata[i];
+                  metaStr.upcase();
+                  if (metaStr.contains("AREA_OR_POINT"))
+                  {
+                     ossimString pixel_is_point_or_area = metaStr.split("=")[1];
+                     pixel_is_point_or_area.upcase();
+                     if (pixel_is_point_or_area.contains("AREA"))
+                     {
+                        // Need to shift the tie point so that pixel is point:
+                        geoTransform[0] += fabs(geoTransform[1]) / 2.0;
+                        geoTransform[3] -= fabs(geoTransform[5]) / 2.0;
+                     }
+                     break;
+                  }
+               }
+            }
+         }
+
+         kwl.remove(ossimKeywordNames::UNITS_KW);
+         ossimDpt gsd(fabs(geoTransform[1]), fabs(geoTransform[5]));
+         ossimDpt tie(geoTransform[0], geoTransform[3]);
+
+         ossimUnitType savedUnitType =
+            static_cast<ossimUnitType>(ossimUnitTypeLut::instance()->getEntryNumber(units));
+         ossimUnitType unitType = savedUnitType;
+         if(unitType == OSSIM_UNIT_UNKNOWN)
+            unitType = OSSIM_METERS;
+
+         if((proj_type == "ossimLlxyProjection") || (proj_type == "ossimEquDistCylProjection"))
+         {
+            // ESH 09/2008 -- Add the orig_lat and central_lon if the image
+            // is using geographic coordsys.  This is used to convert the
+            // gsd to linear units.
+
+            // Half the number of pixels in lon/lat directions
+            int nPixelsLon = GDALGetRasterXSize(h)/2.0;
+            int nPixelsLat = GDALGetRasterYSize(h)/2.0;
+
+            // Shift from image corner to center in lon/lat
+            double shiftLon =  nPixelsLon * fabs(gsd.x);
+            double shiftLat = -nPixelsLat * fabs(gsd.y);
+
+            // lon/lat of center pixel of the image
+            double centerLon = tie.x + shiftLon;
+            double centerLat = tie.y + shiftLat;
+
+            kwl.add(ossimKeywordNames::ORIGIN_LATITUDE_KW,
+                    centerLat,
+                    true);
+            kwl.add(ossimKeywordNames::CENTRAL_MERIDIAN_KW,
+                    centerLon,
+                    true);
+
+            kwl.add(ossimKeywordNames::TIE_POINT_LAT_KW,
+                    tie.y,
+                    true);
+            kwl.add(ossimKeywordNames::TIE_POINT_LON_KW,
+                    tie.x,
+                    true);
+
+            kwl.add(ossimKeywordNames::DECIMAL_DEGREES_PER_PIXEL_LAT,
+                    gsd.y,
+                    true);
+            kwl.add(ossimKeywordNames::DECIMAL_DEGREES_PER_PIXEL_LON,
+                    gsd.x,
+                    true);
+
+            if(savedUnitType == OSSIM_UNIT_UNKNOWN)
+            {
+               unitType = OSSIM_DEGREES;
+            }
+         }
+
+         kwl.add(ossimKeywordNames::PIXEL_SCALE_XY_KW,
+                 gsd.toString(),
+                 true);
+         kwl.add(ossimKeywordNames::PIXEL_SCALE_UNITS_KW,
+                 units,
+                 true);
+         kwl.add(ossimKeywordNames::TIE_POINT_XY_KW,
+                 tie.toString(),
+                 true);
+         kwl.add(ossimKeywordNames::TIE_POINT_UNITS_KW,
+                 units,
+                 true);
+
+         std::stringstream mString;
+         // store as a 4x4 matrix
+         mString << ossimString::toString(geoTransform[1], 20)
+                 << " " << ossimString::toString(geoTransform[2], 20)
+                 << " " << 0 << " "
+                 << ossimString::toString(geoTransform[0], 20)
+                 << " " << ossimString::toString(geoTransform[4], 20)
+                 << " " << ossimString::toString(geoTransform[5], 20)
+                 << " " << 0 << " "
+                 << ossimString::toString(geoTransform[3], 20)
+                 << " " << 0 << " " << 0 << " " << 1 << " " << 0
+                 << " " << 0 << " " << 0 << " " << 0 << " " << 1;
+
+         kwl.add(ossimKeywordNames::IMAGE_MODEL_TRANSFORM_MATRIX_KW, mString.str().c_str(), true);
+
+         //---
+         // SPECIAL CASE:  ArcGrid in British National Grid
+         //---
+         if(driverName == "AIG" && datum_type == "OSGB_1936")
+         {
+            ossimFilename prj_file = filename.path() + "/prj.adf";
+
+            if(prj_file.exists())
+            {
+               ossimKeywordlist prj_kwl(' ');
+               prj_kwl.addFile(prj_file);
+
+               ossimString proj = prj_kwl.find("Projection");
+
+               // Reset projection and Datum correctly for BNG.
+               if(proj.upcase().contains("GREATBRITAIN"))
+               {
+
+                  kwl.add(ossimKeywordNames::TYPE_KW,
+                          "ossimBngProjection", true);
+
+                  ossimString datum  = prj_kwl.find("Datum");
+
+                  if(datum != "")
+                  {
+                     if(datum == "OGB_A")
+                        datum = "OGB-A";
+                     else if(datum == "OGB_B")
+                        datum = "OGB-B";
+                     else if(datum == "OGB_C")
+                        datum = "OGB-C";
+                     else if(datum == "OGB_D")
+                        datum = "OGB-D";
+                     else if(datum == "OGB_M")
+                        datum = "OGB-M";
+                     else if(datum == "OGB_7")
+                        datum = "OGB-7";
+
+                     kwl.add(ossimKeywordNames::DATUM_KW,
+                             datum, true);
+                  }
+               }
+            }
+         }
+     }
+	 if(traceDebug())
+	 {
+		 ossimNotify(ossimNotifyLevel_DEBUG) << "ossimGdalProjectionFactory: createProjection KWL = \n " << kwl << std::endl;
+	 }
+      GDALClose(h);
+      proj = ossimProjectionFactoryRegistry::instance()->createProjection(kwl);
+  }
+
+   return proj;
+}
+
+ossimProjection* ossimGdalProjectionFactory::createProjection(const ossimKeywordlist &keywordList,
+                                                             const char *prefix) const
+{
+   const char *lookup = keywordList.find(prefix, ossimKeywordNames::TYPE_KW);
+   if(lookup&&(!ossimString(lookup).empty()))
+   {
+      ossimProjection* proj = createProjection(ossimString(lookup));
+      if(proj)
+      {
+         // make sure we restore any passed in tie points and meters per pixel information
+         ossimKeywordlist tempKwl;
+         ossimKeywordlist tempKwl2;
+         proj->saveState(tempKwl);
+         tempKwl2.add(keywordList, prefix, true);
+         tempKwl.add(prefix, tempKwl2,  true);
+         tempKwl.add(prefix, ossimKeywordNames::TYPE_KW, proj->getClassName(), true);
+	 proj->loadState(tempKwl);
+         if(traceDebug())
+         {
+            tempKwl.clear();
+            proj->saveState(tempKwl);
+            if(traceDebug())
+            {
+               ossimNotify(ossimNotifyLevel_DEBUG)<< "ossimGdalProjectionFactory::createProjection Debug: resulting projection \n " << tempKwl << std::endl;
+            }
+         }
+
+         return proj;
+      }
+   }
+   return 0;
+}
+
+ossimProjection* ossimGdalProjectionFactory::createProjection(const ossimString &name) const
+{
+   ossimString tempName = name;
+   if(traceDebug())
+   {
+       ossimNotify(ossimNotifyLevel_WARN) << "ossimGdalProjectionFactory::createProjection: "<< name << "\n";
+   }
+   tempName = tempName.trim();
+
+   if ( tempName.size() >= 6 )
+   {
+      ossimString testName(tempName.begin(),
+                           tempName.begin()+6);
+      testName = testName.upcase();
+      if((testName == "PROJCS")||
+         (testName == "GEOGCS"))
+      {
+         ossimKeywordlist kwl;
+         if ( theWktTranslator.toOssimKwl(name.c_str(), kwl, "") )
+         {
+            if(traceDebug())
+            {
+               ossimNotify(ossimNotifyLevel_DEBUG)<< "ossimGdalProjectionFactory::createProjection Debug: trying to create projection \n " << kwl << std::endl;
+            }
+            return ossimProjectionFactoryRegistry::instance()->createProjection(kwl,"");
+        }
+      }
+   }
+
+   return 0;
+}
+
+ossimObject* ossimGdalProjectionFactory::createObject(const ossimString& typeName)const
+{
+   return createProjection(typeName);
+}
+
+ossimObject* ossimGdalProjectionFactory::createObject(const ossimKeywordlist& kwl,
+                                                     const char* prefix)const
+{
+   return createProjection(kwl, prefix);
+}
+
+void ossimGdalProjectionFactory::getTypeNameList(std::vector<ossimString>& /* typeList */)const
+{
+}
+
+std::list<ossimString> ossimGdalProjectionFactory::getList()const
+{
+   std::list<ossimString> result;
+
+   return result;
+}
+
diff --git a/ossim_plugins/gdal/ossimGdalProjectionFactory.h b/ossim_plugins/gdal/ossimGdalProjectionFactory.h
new file mode 100644
index 0000000..5509c35
--- /dev/null
+++ b/ossim_plugins/gdal/ossimGdalProjectionFactory.h
@@ -0,0 +1,68 @@
+//*******************************************************************
+// Copyright (C) 2005 Garrett Potts
+//
+// License:  See top level LICENSE.txt file.
+// 
+// Author:  Garrett Potts
+//
+//*******************************************************************
+//  $Id: ossimGdalProjectionFactory.h 19908 2011-08-05 19:57:34Z dburken $
+
+#ifndef ossimGdalProjectionFactory_HEADER
+#define ossimGdalProjectionFactory_HEADER
+
+#include <ossim/projection/ossimProjectionFactoryBase.h>
+#include "ossimOgcWktTranslator.h"
+#include "../ossimPluginConstants.h"
+#include <list>
+class ossimProjection;
+class ossimString;
+
+class ossimGdalProjectionFactory : public ossimProjectionFactoryBase
+{
+public:
+   /*!
+    * METHOD: instance()
+    * Instantiates singleton instance of this class:
+    */
+   static ossimGdalProjectionFactory* instance();
+
+   virtual ossimProjection* createProjection(const ossimFilename& filename,
+                                             ossim_uint32 entryIdx)const;
+   /*!
+    * METHOD: create()
+    * Attempts to create an instance of the projection specified by name.
+    * Returns successfully constructed projection or NULL.
+    */
+   virtual ossimProjection* createProjection(const ossimString& name)const;
+   virtual ossimProjection* createProjection(const ossimKeywordlist& kwl,
+                                             const char* prefix = 0)const;
+
+   virtual ossimObject* createObject(const ossimString& typeName)const;
+
+   /*!
+    * Creates and object given a keyword list.
+    */
+   virtual ossimObject* createObject(const ossimKeywordlist& kwl,
+                                     const char* prefix=0)const;
+   
+   /*!
+    * This should return the type name of all objects in all factories.
+    * This is the name used to construct the objects dynamially and this
+    * name must be unique.
+    */
+   virtual void getTypeNameList(std::vector<ossimString>& typeList)const;
+
+   /*!
+    * METHOD: getList()
+    * Returns list of all projections represented by this factory:
+    */
+   virtual std::list<ossimString> getList()const;
+
+protected:
+   ossimGdalProjectionFactory() {}
+   ossimOgcWktTranslator theWktTranslator;
+   static ossimGdalProjectionFactory*  theInstance;
+};
+
+#endif
diff --git a/ossim_plugins/gdal/ossimGdalTileSource.cpp b/ossim_plugins/gdal/ossimGdalTileSource.cpp
new file mode 100644
index 0000000..07f5973
--- /dev/null
+++ b/ossim_plugins/gdal/ossimGdalTileSource.cpp
@@ -0,0 +1,2492 @@
+//*******************************************************************
+//
+// License:  See top level LICENSE.txt file.
+//
+// Author:  Garrett Potts
+//
+// Description:
+//
+// Contains class implementaiton for the class "ossimGdalTileSource".
+//
+//*******************************************************************
+//  $Id: ossimGdalTileSource.cpp 23191 2015-03-14 15:01:39Z dburken $
+
+#include "ossimGdalTileSource.h"
+#include "ossimGdalType.h"
+#include "ossimOgcWktTranslator.h"
+#include <ossim/base/ossimBooleanProperty.h>
+#include <ossim/base/ossimCommon.h>
+#include <ossim/base/ossimDpt.h>
+#include <ossim/base/ossimException.h>
+#include <ossim/base/ossimFilename.h>
+#include <ossim/base/ossimGrect.h>
+#include <ossim/base/ossimIpt.h>
+#include <ossim/base/ossimKeywordlist.h>
+#include <ossim/base/ossimKeywordNames.h>
+#include <ossim/base/ossimNotify.h>
+#include <ossim/base/ossimPreferences.h>
+#include <ossim/base/ossimStringProperty.h>
+#include <ossim/base/ossimTieGptSet.h>
+#include <ossim/base/ossimTrace.h>
+#include <ossim/base/ossimUnitConversionTool.h>
+#include <ossim/base/ossimUnitTypeLut.h>
+#include <ossim/imaging/ossimImageDataFactory.h>
+#include <ossim/imaging/ossimImageGeometryRegistry.h>
+#include <ossim/imaging/ossimTiffTileSource.h>
+#include <ossim/projection/ossimBilinearProjection.h>
+#include <ossim/projection/ossimMapProjection.h>
+#include <ossim/projection/ossimPolynomProjection.h>
+#include <ossim/projection/ossimProjection.h>
+#include <ossim/projection/ossimProjectionFactoryRegistry.h>
+#include <ossim/projection/ossimRpcSolver.h>
+#include <ossim/projection/ossimRpcProjection.h>
+#include <ossim/support_data/ossimFgdcXmlDoc.h>
+
+#include <gdal_priv.h>
+#include <cpl_string.h>
+
+#include <sstream>
+
+RTTI_DEF1(ossimGdalTileSource, "ossimGdalTileSource", ossimImageHandler)
+
+static ossimOgcWktTranslator wktTranslator;
+static ossimTrace traceDebug("ossimGdalTileSource:debug");
+
+static const char DRIVER_SHORT_NAME_KW[] = "driver_short_name";
+static const char PRESERVE_PALETTE_KW[]  = "preserve_palette";
+
+
+using namespace ossim;
+
+//*******************************************************************
+// Public Constructor:
+//*******************************************************************
+ossimGdalTileSource::ossimGdalTileSource()
+   :
+      ossimImageHandler(),
+      theDataset(0),
+      theTile(0),
+      theSingleBandTile(0),
+      theImageBound(),
+      theMinPixValues(0),
+      theMaxPixValues(0),
+      theNullPixValues(0),
+      theEntryNumberToRender(0),
+      theSubDatasets(),
+      theIsComplexFlag(false),
+      theAlphaChannelFlag(false),
+      m_preservePaletteIndexesFlag(false),
+      m_outputBandList(0),
+      m_isBlocked(false)
+{
+   // Pick up any default settings from preference file if set.
+   getDefaults();
+}
+
+//*******************************************************************
+// Destructor:
+//*******************************************************************
+ossimGdalTileSource::~ossimGdalTileSource()
+{
+   close();
+}
+
+void ossimGdalTileSource::close()
+{
+   if(theDataset)
+   {
+      GDALClose(theDataset);
+      theDataset = 0;
+   }
+
+   theTile = 0;
+   theSingleBandTile = 0;
+
+   if(theMinPixValues)
+   {
+      delete [] theMinPixValues;
+      theMinPixValues = 0;
+   }
+   if(theMaxPixValues)
+   {
+      delete [] theMaxPixValues;
+      theMaxPixValues = 0;
+   }
+   if(theNullPixValues)
+   {
+      delete [] theNullPixValues;
+      theNullPixValues = 0;
+   }
+   deleteRlevelCache();
+
+   m_preservePaletteIndexesFlag = false;
+   theAlphaChannelFlag = false;
+   theIsComplexFlag = false;
+}
+
+//*******************************************************************
+// Public Method:
+//*******************************************************************
+bool ossimGdalTileSource::open()
+{
+   
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_WARN)
+         << "ossimGdalTileSource::open() DEBUG: entered ..."
+         << std::endl;
+   }
+
+   if(isOpen())
+   {
+      close();
+   }
+   ossimString driverNameTmp;
+
+   if (theSubDatasets.size() == 0)
+   {
+      // Note:  Cannot feed GDALOpen a NULL string!
+      if (theImageFile.size())
+      {
+         theDataset = GDALOpen(theImageFile.c_str(), GA_ReadOnly); 
+         if( theDataset == 0 )
+         {
+            return false;
+         }
+      }
+      else
+      {
+         return false;
+      }
+
+      if (traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG)
+            << "ossimGdalTileSource::open DEBUG:"
+            << "\nOpened image:  "
+            << theImageFile.c_str()
+            << std::endl;
+      }
+
+      // Check if it is nitf data for deciding whether or not open each sub-dataset
+      //This will be removed eventually when ossim can handle 2GB nitf file.
+      GDALDriverH driverTmp = GDALGetDatasetDriver(theDataset);
+      bool isNtif = false;
+      if (driverTmp != 0)
+      {
+         driverNameTmp = ossimString(GDALGetDriverShortName(driverTmp));
+         driverNameTmp = driverNameTmp.upcase();
+         if (driverNameTmp == "NITF")
+         {
+            isNtif = true;
+         }
+      }
+      
+      // Check for sub data sets...
+      char** papszMetadata = GDALGetMetadata( theDataset, "SUBDATASETS" );
+      if( CSLCount(papszMetadata) > 0 )
+      {
+         theSubDatasets.clear();
+         
+         for( int i = 0; papszMetadata[i] != 0; ++i )
+         {
+            ossimString os = papszMetadata[i];
+            if (os.contains("_NAME="))
+            {
+               //Sub sets have already been set. Open each sub-dataset really slow down the process
+               //specially for hdf data which sometimes has over 100 sub-datasets. Since following code
+               //only for ntif cloud checking, so only open each sub-dataset here if the dataset is
+               //nitf. This will be removed eventually when ossim can handle 2GB nitf file. 
+               //Otherwise open a sub-dataset when setCurrentEntry() gets called.
+               if (isNtif)
+               {
+                  GDALDatasetH subDataset = GDALOpen(filterSubDatasetsString(os),
+                     GA_ReadOnly);
+                  if ( subDataset != 0 )
+                  {
+                     // ESH 12/2008: Ticket #482 
+                     // "Worldview ingest should ignore subimages when NITF_ICAT=CLOUD"
+                     // Hack: Ignore NITF subimages marked as cloud layers.
+                     ossimString nitfIcatTag( GDALGetMetadataItem( subDataset, "NITF_ICAT", "" ) );
+                     if ( nitfIcatTag.contains("CLOUD") == false )
+                     {
+                        theSubDatasets.push_back(filterSubDatasetsString(os));
+                     }
+                  }
+                  GDALClose(subDataset);
+               }
+               else
+               {
+                  theSubDatasets.push_back(filterSubDatasetsString(os));
+               }
+            }
+         }
+
+         if (traceDebug())
+         {
+            ossimNotify(ossimNotifyLevel_DEBUG)
+               << "ossimGdalTileSource::open DEBUG:" << std::endl;
+            for (ossim_uint32 idx = 0; idx < theSubDatasets.size(); ++idx)
+            {
+               ossimNotify(ossimNotifyLevel_DEBUG)
+                  << "Sub_data_set[" << idx << "] "
+                  << theSubDatasets[idx] << std::endl;
+            }
+         }
+
+         //---
+         // Have multiple entries.  We're going to default to open the first
+         // entry like cidcadrg.
+         //---
+         close();
+         
+         theDataset = GDALOpen(theSubDatasets[theEntryNumberToRender].c_str(),
+                               GA_ReadOnly);
+         if (theDataset == 0)
+         {
+            if(traceDebug())
+            {
+               ossimNotify(ossimNotifyLevel_WARN) << "Could not open sub dataset = " << theSubDatasets[theEntryNumberToRender] << "\n";
+            }
+            return false;
+         }
+         if (traceDebug())
+         {
+            ossimNotify(ossimNotifyLevel_DEBUG)
+               << "ossimGdalTileSource::open DEBUG:"
+               << "\nOpened sub data set:  "
+               << theSubDatasets[theEntryNumberToRender].c_str()
+               << std::endl;
+         }
+         
+      }  // End of has subsets block.
+      
+   }  // End of "if (theSubdatasets.size() == 0)"
+   else
+   {
+      // Sub sets have already been set.
+      theDataset = GDALOpen(theSubDatasets[theEntryNumberToRender].c_str(),
+                            GA_ReadOnly);
+      if (theDataset == 0)
+      {
+         return false;
+      }
+      
+      if (traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG)
+            << "ossimGdalTileSource::open DEBUG:"
+            << "\nOpened sub data set:  "
+            << theSubDatasets[theEntryNumberToRender].c_str()
+            << std::endl;
+      }
+   }
+
+   // Set the driver.
+   theDriver = GDALGetDatasetDriver( theDataset );
+
+   if(!theDriver) return false;
+
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimGdalTileSource::open Driver: "
+         << GDALGetDriverShortName( theDriver )
+         << "/" << GDALGetDriverLongName( theDriver ) << std::endl;
+   }
+
+   theGdtType = GDT_Byte;
+   theOutputGdtType = GDT_Byte;
+
+   if(getNumberOfInputBands() < 1 )
+   {
+      if(CSLCount(GDALGetMetadata(theDataset, "SUBDATASETS")))
+      {
+         ossimNotify(ossimNotifyLevel_WARN)
+            << "ossimGdalTileSource::open WARNING:"
+            << "\nHas multiple sub datasets and need to set the data before"
+            << " we can get to the bands" << std::endl;
+      }
+      
+      close();
+      ossimNotify(ossimNotifyLevel_WARN)
+      << "ossimGdalTileSource::open WARNING:"
+      << "\nNo band data present in ossimGdalTileSource::open" << std::endl;
+      return false;
+   }
+   
+   ossim_int32 i = 0;
+   GDALRasterBandH bBand = GDALGetRasterBand( theDataset, 1 );
+   theGdtType  = GDALGetRasterDataType(bBand);
+
+   // Establish raster-pixel alignment type:
+   thePixelType = OSSIM_PIXEL_IS_POINT; //default
+   char** papszMetadata = GDALGetMetadata( bBand, NULL );
+   if (CSLCount(papszMetadata) > 0)
+   {
+      for(int i = 0; papszMetadata[i] != NULL; i++ )
+      {
+         ossimString metaStr = papszMetadata[i];
+         if (metaStr.contains("AREA_OR_POINT"))
+         {
+            ossimString pixel_is_point_or_area = metaStr.split("=")[1];
+            pixel_is_point_or_area.downcase();
+            if (pixel_is_point_or_area.contains("area"))
+               thePixelType = OSSIM_PIXEL_IS_AREA;
+            break;
+         }
+      }
+   }
+
+   if(!isIndexed(1))
+   {
+      for(i = 0; i  < GDALGetRasterCount(theDataset); ++i)
+      {
+         if(theGdtType != GDALGetRasterDataType(GDALGetRasterBand( theDataset,
+                                                                   i+1 )))
+         {
+            ossimNotify(ossimNotifyLevel_WARN)
+               << "ossimGdalTileSource::open WARNING"
+               << "\nWe currently do not support different scalar type bands."
+               << std::endl;
+            close();
+            return false;
+         }
+//          if(GDALGetRasterColorInterpretation(GDALGetRasterBand(
+//                                                 theDataset,
+//                                                 i+1 )) == GCI_PaletteIndex)
+//          {
+//             ossimNotify(ossimNotifyLevel_WARN)
+//                << "ossimGdalTileSource::open WARNING"
+//                << "Index palette bands are not supported." << endl;
+//             close();
+//             return false;
+//          }
+      }
+   }
+   theOutputGdtType = theGdtType;
+   switch(theGdtType)
+   {
+      case GDT_CInt16:
+      {
+//          theOutputGdtType = GDT_Int16;
+         theIsComplexFlag = true;
+         break;
+      }
+      case GDT_CInt32:
+      {
+//          theOutputGdtType = GDT_Int32;
+         theIsComplexFlag = true;
+         break;
+      }
+      case GDT_CFloat32:
+      {
+//          theOutputGdtType = GDT_Float32;
+         theIsComplexFlag = true;
+         break;
+      }
+      case GDT_CFloat64:
+      {
+//          theOutputGdtType = GDT_Float64;
+         theIsComplexFlag = true;
+         break;
+      }
+      default:
+      {
+         theIsComplexFlag = false;
+         break;
+      }
+   }
+
+   if((ossimString(GDALGetDriverShortName( theDriver )) == "PNG")&&
+      (getNumberOfInputBands() == 4))
+   {
+      theAlphaChannelFlag = true;
+   }
+   populateLut();
+   computeMinMax();
+   completeOpen();
+   
+   theTile = ossimImageDataFactory::instance()->create(this, this);
+   theSingleBandTile = ossimImageDataFactory::instance()->create(this, getInputScalarType(), 1);
+
+   if ( m_preservePaletteIndexesFlag )
+   {
+      theTile->setIndexedFlag(true);
+      theSingleBandTile->setIndexedFlag(true);
+   }
+
+   theTile->initialize();
+   theSingleBandTile->initialize();
+
+   theGdalBuffer.resize(0);
+   if(theIsComplexFlag)
+   {
+      theGdalBuffer.resize(theSingleBandTile->getSizePerBandInBytes()*2);
+   }
+   
+   theImageBound = ossimIrect(0
+                              ,0
+                              ,GDALGetRasterXSize(theDataset)-1
+                              ,GDALGetRasterYSize(theDataset)-1);
+   
+   if(traceDebug())
+   {
+      
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimGdalTileSoruce::open\n"
+         << "data type = " << theTile->getScalarType() << std::endl;
+      
+      for(ossim_uint32 i = 0; i < getNumberOfInputBands(); ++i)
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG)
+            << "min pix   " << i << ":" << getMinPixelValue(i)
+            << "\nmax pix   " << i << ":" << getMaxPixelValue(i)
+            << "\nnull pix  " << i << ":" << getNullPixelValue(i) << std::endl;
+      }
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "theTile:\n" << *theTile
+         << "theSingleBandTile:\n" << *theSingleBandTile
+         << std::endl;
+   }
+   
+   int xSize=0, ySize=0;
+   GDALGetBlockSize(GDALGetRasterBand( theDataset, 1 ),
+                    &xSize,
+                    &ySize);
+   // Garrett: 
+   // For now,  I will just enable te block reads with the JPIP and JP2 tyope drivers
+   // if it's a block encoded image
+   //
+   // 
+   if(driverNameTmp.contains("JPIP")||driverNameTmp.contains("JP2"))
+   {
+      m_isBlocked = ((xSize > 1)&&(ySize > 1));
+   }
+   else
+   {
+      m_isBlocked = false;
+   }
+   if(m_isBlocked)
+   {
+      setRlevelCache();
+   }
+   return true;
+}
+
+ossimRefPtr<ossimImageData> ossimGdalTileSource::getTile(const  ossimIrect& tileRect,
+                                                         ossim_uint32 resLevel)
+{
+   // This tile source bypassed, or invalid res level, return a blank tile.
+   if (!isSourceEnabled() || !theDataset)
+   {
+      return ossimRefPtr<ossimImageData>();
+   }
+
+   // Check for intersect.
+   ossimIrect imageBound = getBoundingRect(resLevel);
+   if(!tileRect.intersects(imageBound))
+   {
+      theTile->setImageRectangle(tileRect);
+      theTile->makeBlank();
+      return theTile;
+   }
+
+   if(m_isBlocked)
+   {
+      return getTileBlockRead(tileRect, resLevel);
+   }
+  // Check for overview.
+   if(resLevel)
+   {
+      if ( m_preservePaletteIndexesFlag )
+      {
+         // No mechanism for this coded for reduce resolution levels.
+         throw ossimException( std::string("ossimGdalTileSource::getTile ERROR: Accessing reduced resolution level with the preservePaletteIndexesFlag set!") );
+      }
+         
+      if(theOverview.valid() && theOverview->isValidRLevel(resLevel))
+      {
+         ossimRefPtr<ossimImageData> tileData = theOverview->getTile(tileRect, resLevel);
+         tileData->setScalarType(getOutputScalarType());
+         return tileData;
+      }
+      
+#if 1
+      //---
+      // Note: This code was shut off since we currently don't utilize gdal overviews.
+      // ossimGdalTileSource::getNumberOfDecimationLevels has been fixed accordingly.
+      // drb - 20110503
+      //---
+      else if(GDALGetRasterCount(theDataset))
+      {
+         GDALRasterBandH band = GDALGetRasterBand(theDataset, 1);
+         if(static_cast<int>(resLevel) > GDALGetOverviewCount(band))
+         {
+            return ossimRefPtr<ossimImageData>();
+         }
+      }
+#endif
+   }
+
+   // Set the rectangle of the tile.
+   theTile->setImageRectangle(tileRect);
+
+   // Compute clip rectangle with respect to the image bounds.
+   ossimIrect clipRect   = tileRect.clipToRect(imageBound);
+
+   theSingleBandTile->setImageRectangle(clipRect);
+
+   if (tileRect.completely_within(clipRect) == false)
+   {
+      // Not filling whole tile so blank it out first.
+      theTile->makeBlank();
+   }
+
+   // Always blank the single band tile.
+   theSingleBandTile->makeBlank();
+   
+   ossim_uint32 anOssimBandIndex = 0;
+   ossim_uint32 aGdalBandIndex   = 1;
+
+   ossim_uint32 rasterCount = GDALGetRasterCount(theDataset);
+   if (m_outputBandList.size() > 0)
+   {
+      rasterCount = (ossim_uint32) m_outputBandList.size();
+   }
+   
+   ossim_uint32 outputBandIndex = 0;
+   for(ossim_uint32 aBandIndex =1; aBandIndex <= rasterCount; ++aBandIndex)
+   {
+      if (m_outputBandList.size() > 0)
+      {
+         aGdalBandIndex = m_outputBandList[outputBandIndex] + 1;
+         outputBandIndex++;
+      }
+      else
+      {
+         aGdalBandIndex = aBandIndex;
+      }
+      GDALRasterBandH aBand = resolveRasterBand( resLevel, aGdalBandIndex );
+      if ( aBand )
+      {
+         bool bReadSuccess;
+         if(!theIsComplexFlag)
+         {
+            bReadSuccess = (GDALRasterIO(aBand
+                                         , GF_Read
+                                         , clipRect.ul().x
+                                         , clipRect.ul().y
+                                         , clipRect.width()
+                                         , clipRect.height()
+                                         , theSingleBandTile->getBuf()
+                                         , clipRect.width()
+                                         , clipRect.height()
+                                         , theOutputGdtType
+                                         , 0 
+                                         , 0 ) == CE_None) ? true : false;
+
+            if ( bReadSuccess == true )
+            {
+               if(isIndexed(aGdalBandIndex))
+               {
+                  if(isIndexTo3Band(aGdalBandIndex))
+                  {
+                     if ( m_preservePaletteIndexesFlag )
+                     {
+                        theTile->loadBand((void*)theSingleBandTile->getBuf(),
+                                          clipRect, anOssimBandIndex);
+                        anOssimBandIndex += 1;
+                     }
+                     else
+                     {
+                        loadIndexTo3BandTile(clipRect, aGdalBandIndex, anOssimBandIndex);
+                        anOssimBandIndex+=3;
+                     }
+                  }
+                  else if(isIndexTo1Band(aGdalBandIndex))
+                  { 
+                     // ??? Ignoring (drb)
+                     anOssimBandIndex += 1;
+                  }
+               }
+               else
+               {
+                  if(theAlphaChannelFlag&&(aGdalBandIndex==rasterCount))
+                  {
+                     theTile->nullTileAlpha((ossim_uint8*)theSingleBandTile->getBuf(),
+                                            theSingleBandTile->getImageRectangle(),
+                                            clipRect,
+                                            false);
+                  }
+                  else
+                  {
+                     // Note fix rectangle to represent theBuffer's rect in image space.
+                     theTile->loadBand((void*)theSingleBandTile->getBuf()
+                                       , clipRect
+                                       , anOssimBandIndex);
+                     ++anOssimBandIndex;
+                  }
+               }
+            }
+            else
+            {
+               ++anOssimBandIndex;
+            }
+         } 
+         else // matches if(!theIsComplexFlag){} 
+         {
+            bReadSuccess = (GDALRasterIO(aBand
+                                         , GF_Read
+                                         , clipRect.ul().x
+                                         , clipRect.ul().y
+                                         , clipRect.width()
+                                         , clipRect.height()
+                                         , &theGdalBuffer.front()
+                                         , clipRect.width()
+                                         , clipRect.height()
+                                         , theOutputGdtType
+                                         , 0
+                                         , 0 ) == CE_None) ? true : false;
+            if (  bReadSuccess == true )
+            {
+               ossim_uint32 byteSize = ossim::scalarSizeInBytes(theSingleBandTile->getScalarType());
+               ossim_uint32 byteSize2 = byteSize*2;
+               ossim_uint8* complexBufPtr = (ossim_uint8*)(&theGdalBuffer.front()); // start at first real part
+               ossim_uint8* outBufPtr  = (ossim_uint8*)(theSingleBandTile->getBuf());
+               ossim_uint32 idxMax = theSingleBandTile->getWidth()*theSingleBandTile->getHeight();
+               ossim_uint32 idx = 0;
+               for(idx = 0; idx < idxMax; ++idx)
+               {
+                  memcpy(outBufPtr, complexBufPtr, byteSize);
+                  complexBufPtr += byteSize2;
+                  outBufPtr     += byteSize;
+               }
+               theTile->loadBand((void*)theSingleBandTile->getBuf()
+                                 , clipRect
+                                 , anOssimBandIndex);
+               ++anOssimBandIndex;
+               complexBufPtr = (ossim_uint8*)(&theGdalBuffer.front()) + byteSize; // start at first imaginary part
+               outBufPtr  = (ossim_uint8*)(theSingleBandTile->getBuf());
+               for(idx = 0; idx < idxMax; ++idx)
+               {
+                  memcpy(outBufPtr, complexBufPtr, byteSize);
+                  complexBufPtr += byteSize2;
+                  outBufPtr     += byteSize;
+               }
+               theTile->loadBand((void*)theSingleBandTile->getBuf()
+                                 , clipRect
+                                 , anOssimBandIndex);
+               ++anOssimBandIndex;
+            }
+            else
+            {
+               anOssimBandIndex += 2;
+            }
+         }
+      }
+   }
+
+   theTile->validate();
+   return theTile;
+}
+
+ossimRefPtr<ossimImageData> ossimGdalTileSource::getTileBlockRead(const ossimIrect& tileRect,
+                                                                  ossim_uint32 resLevel)
+{
+   ossimRefPtr<ossimImageData> result;
+   ossimIrect imageBound = getBoundingRect(resLevel);
+   theTile->setImageRectangle(tileRect);
+   
+   // Compute clip rectangle with respect to the image bounds.
+   ossimIrect clipRect   = tileRect.clipToRect(imageBound);
+   
+   if (tileRect.completely_within(clipRect) == false)
+   {
+      // Not filling whole tile so blank it out first.
+      theTile->makeBlank();
+   }
+   if(m_isBlocked)
+   {
+      int xSize=0, ySize=0;
+      GDALGetBlockSize(resolveRasterBand( resLevel, 1 ),
+                       &xSize,
+                       &ySize);
+      ossimIrect blockRect = clipRect;
+      blockRect.stretchToTileBoundary(ossimIpt(xSize, ySize));
+      blockRect = blockRect.clipToRect(getBoundingRect(resLevel));
+      
+      // we need to cache here
+      //
+      ossim_int64 x = blockRect.ul().x;
+      ossim_int64 y = blockRect.ul().y;
+      ossim_int64 maxx = blockRect.lr().x;
+      ossim_int64 maxy = blockRect.lr().y;
+      ossim_uint32 aGdalBandIndex   = 1;
+      ossim_uint32 rasterCount = GDALGetRasterCount(theDataset);
+      if (m_outputBandList.size() > 0)
+      {
+         rasterCount = m_outputBandList.size();
+      }
+    
+     ossim_uint32 outputBandIndex = 0;
+      for(;x < maxx;x+=xSize)
+      {
+         for(;y < maxy;y+=ySize)
+         {
+            ossimIpt origin(x,y);
+            
+            ossimRefPtr<ossimImageData> cacheTile = ossimAppFixedTileCache::instance()->getTile(m_rlevelBlockCache[resLevel], origin);
+            
+            if(!cacheTile.valid())
+            {
+               ossimIrect rect(origin.x,origin.y,origin.x+xSize-1, origin.y+ySize-1);
+               theSingleBandTile->setImageRectangle(rect);
+               ossimIrect validRect = rect.clipToRect(imageBound);
+               cacheTile = ossimImageDataFactory::instance()->create(this, this);
+               cacheTile->setImageRectangle(validRect);
+               cacheTile->initialize();                          
+               for(ossim_uint32 aBandIndex =1; aBandIndex <= rasterCount; ++aBandIndex)
+               {
+                  if (m_outputBandList.size() > 0)
+                  {
+                     aGdalBandIndex = m_outputBandList[outputBandIndex] + 1;
+                     outputBandIndex++;
+                  }
+                  else
+                  {
+                     aGdalBandIndex = aBandIndex;
+                  }
+                  GDALRasterBandH aBand = resolveRasterBand( resLevel, aGdalBandIndex );
+                  if ( aBand )
+                  {
+                     try{
+                        
+                       bool bReadSuccess =  (GDALReadBlock(aBand, x/xSize, y/ySize, theSingleBandTile->getBuf() )== CE_None) ? true : false;
+                        if(bReadSuccess)
+                        {
+                           cacheTile->loadBand(theSingleBandTile->getBuf(), theSingleBandTile->getImageRectangle(), aBandIndex-1);
+                        }
+                     }
+                     catch(...)
+                     {
+                     }
+                  }
+               }
+               cacheTile->validate();
+               ossimAppFixedTileCache::instance()->addTile(m_rlevelBlockCache[resLevel], cacheTile.get(), false);
+            }
+            theTile->loadTile(cacheTile->getBuf(), cacheTile->getImageRectangle(), OSSIM_BSQ);
+            result = theTile;
+         }
+      }
+   }
+   if(result.valid()) result->validate();
+   
+   return result;
+}
+
+//*******************************************************************
+// Public Method:
+//*******************************************************************
+ossim_uint32 ossimGdalTileSource::getNumberOfInputBands() const
+{
+   if(isOpen())
+   {
+       if (m_outputBandList.size() > 0)
+       {
+          return (ossim_uint32) m_outputBandList.size();
+       }
+
+      if(isIndexed(1))
+      {
+         return getIndexBandOutputNumber(1);
+      }
+
+      if(!theIsComplexFlag)
+      {
+         return GDALGetRasterCount(theDataset);
+      }
+      return GDALGetRasterCount(theDataset)*2;
+   }
+   return 0;
+}
+
+/*!
+ * Returns the number of bands in a tile returned from this TileSource.
+ * Note: we are supporting sources that can have multiple data objects.
+ * If you want to know the scalar type of an object you can pass in the 
+ */
+ossim_uint32 ossimGdalTileSource::getNumberOfOutputBands() const
+{
+   ossim_uint32 result = 0;
+   if( isIndexTo3Band() )
+   {
+      if ( m_preservePaletteIndexesFlag )
+      {
+         result = 1; // Passing palette indexes not expanded rgb values.
+      }
+      else
+      {
+         result = 3;
+      }
+   }
+   else if (theAlphaChannelFlag)
+   {
+      result = 3;
+   }
+   else
+   {
+      // the number of outputs will be the same as the number of inputs
+      result = getNumberOfInputBands();
+   }
+   return result;
+}
+
+//*******************************************************************
+// Public Method:
+//*******************************************************************
+ossim_uint32 ossimGdalTileSource::getNumberOfLines(ossim_uint32 reduced_res_level) const
+{
+   
+   ossim_uint32 result = 0;
+   if ( isOpen() && isValidRLevel(reduced_res_level) )
+   {
+      if(theOverview.valid() && theOverview->isValidRLevel(reduced_res_level))
+      {
+         result = theOverview->getNumberOfLines(reduced_res_level);
+      }
+      else
+      {
+         int x, y;
+         getMaxSize(reduced_res_level, x, y);
+         result = y;
+      }
+   }
+   
+   return result;
+}
+
+//*******************************************************************
+// Public Method:
+//*******************************************************************
+ossim_uint32 ossimGdalTileSource::getNumberOfSamples(ossim_uint32 reduced_res_level) const
+{
+   ossim_uint32 result = 0;
+   if ( isOpen() && isValidRLevel(reduced_res_level) )
+   {
+      if(theOverview.valid() && theOverview->isValidRLevel(reduced_res_level))
+      {
+         result = theOverview->getNumberOfLines(reduced_res_level);
+      }
+      else
+      {
+         int x, y;
+         getMaxSize(reduced_res_level, x, y);
+         result = x;
+      }
+   }
+   return result;
+}
+
+//*******************************************************************
+// Public Method:
+//*******************************************************************
+ossimIrect ossimGdalTileSource::getImageRectangle(ossim_uint32 reduced_res_level) const
+{
+   ossimIrect result;
+   result.makeNan();
+   
+   int x, y;
+   getMaxSize(reduced_res_level, x, y);
+   if(x&&y)
+   {
+      return ossimIrect(0,
+                        0,
+                        x - 1,
+                        y - 1);
+   }
+
+   if (result.hasNans())
+   {
+      return ossimImageHandler::getImageRectangle(reduced_res_level);
+   }
+   
+   return result;
+}
+
+//*******************************************************************
+// Public Method:
+//*******************************************************************
+void ossimGdalTileSource::getDecimationFactor(ossim_uint32 resLevel,
+                                              ossimDpt& result) const
+{
+   if (resLevel == 0)
+   {
+      result.x = 1.0;
+      result.y = 1.0;
+   }
+   else
+   {
+      /* 
+         ESH 02/2009 -- No longer assume powers of 2 reduction 
+         in linear size from resLevel 0 (Tickets # 467,529).
+      */
+      ossim_int32 x  = getNumberOfLines(resLevel);
+      ossim_int32 x0 = getNumberOfLines(0);
+
+      if ( x > 0 && x0 > 0 )
+      {
+         result.x = ((double)x) / x0;
+      }
+      else
+      {
+         result.x = 1.0 / (1<<resLevel);
+      }
+
+      result.y = result.x;
+   }
+}
+
+GDALDriverH ossimGdalTileSource::getDriver()
+{
+   return theDriver;
+}
+
+//*******************************************************************
+// Public method:
+//*******************************************************************
+bool ossimGdalTileSource::saveState(ossimKeywordlist& kwl,
+                                    const char* prefix) const
+{
+   kwl.add(prefix, 
+	   "entry",
+	   theEntryNumberToRender,
+	   true);
+   if (theEntryNumberToRender < theSubDatasets.size())
+   {
+      kwl.add(prefix,
+              "entry_string",
+              theSubDatasets[theEntryNumberToRender].c_str(),
+              true);
+   }
+   
+   bool result = ossimImageHandler::saveState(kwl, prefix);
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "DEBUG:"
+         << "\nossimGdalTileSource::saveState keywordlist:\n"
+         << kwl
+         << std::endl;
+   }
+
+   return result;
+}
+
+//*******************************************************************
+// Public method:
+//*******************************************************************
+bool ossimGdalTileSource::loadState(const ossimKeywordlist& kwl,
+                                    const char* prefix)
+{
+   // Call base class first to set "theImageFile".
+   if (ossimImageHandler::loadState(kwl, prefix))
+   {
+      // Check for an entry.
+      const char* lookup = kwl.find(prefix, "entry");
+      if(lookup)
+      {
+         ossim_uint32 entry = ossimString(lookup).toUInt32();
+
+         // setCurrentEntry calls open but does not have a return.
+         setCurrentEntry(entry);
+         return isOpen();
+      }
+      lookup = kwl.find(prefix, PRESERVE_PALETTE_KW);
+      if ( lookup )
+      {
+         setPreservePaletteIndexesFlag(ossimString(lookup).toBool());
+      }
+
+      return open();
+   }
+
+   return false;
+}
+
+//*****************************************************************************
+//! Returns the image geometry object associated with this tile source or
+//! NULL if non defined.
+//! The geometry contains full-to-local image transform as well as projection
+//! (image-to-world).
+//*****************************************************************************
+ossimRefPtr<ossimImageGeometry> ossimGdalTileSource::getImageGeometry()
+{
+   if ( !theGeometry )
+   {
+      //---
+      // Check factory for external geom:
+      //---
+      theGeometry = getExternalImageGeometry();
+
+      if ( !theGeometry )
+      {
+         //---
+         // WARNING:
+         // Must create/set the geometry at this point or the next call to
+         // ossimImageGeometryRegistry::extendGeometry will put us in an infinite loop
+         // as it does a recursive call back to ossimImageHandler::getImageGeometry().
+         //---
+         theGeometry = new ossimImageGeometry();
+
+         //---
+         // And finally allow factories to extend the internal geometry.
+         // This allows plugins for tagged formats with tags not know in the base
+         // to extend the internal geometry.
+         //
+         // Plugins can do handler->getImageGeometry() then modify/extend.
+         //---
+         if( !ossimImageGeometryRegistry::instance()->extendGeometry( this ) )
+         {
+            // Check for internal, for geotiff, nitf and so on as last resort for getting
+            // some kind of geometry
+            // loaded
+            theGeometry = getInternalImageGeometry();
+         }
+
+         if ( !theGeometry )
+         {
+            theGeometry = getExternalImageGeometryFromXml();
+         }
+      }
+
+      // Set image things the geometry object should know about.
+      initImageParameters( theGeometry.get() );
+   }
+
+  return theGeometry;
+}
+
+ossimRefPtr<ossimImageGeometry> ossimGdalTileSource::getExternalImageGeometryFromXml() const
+{
+  ossimRefPtr<ossimImageGeometry> geom = 0;
+
+  ossimString fileBase = theImageFile.noExtension();
+  ossimFilename xmlFile = ossimString(fileBase + ".xml");
+  if (!xmlFile.exists())//try the xml file which includes the entire source file name
+  {
+    xmlFile = theImageFile + ".xml";
+  }
+  ossimFgdcXmlDoc* fgdcXmlDoc = new ossimFgdcXmlDoc;
+  if ( fgdcXmlDoc->open(xmlFile) )
+  {
+     ossimRefPtr<ossimProjection> proj = fgdcXmlDoc->getProjection();
+     if ( proj.valid() )
+     {
+        geom = new ossimImageGeometry;
+        geom->setProjection( proj.get() );
+     }
+  }
+  delete fgdcXmlDoc;
+  fgdcXmlDoc = 0;
+  
+  return geom;
+}
+
+//*************************************************************************************************
+//! Returns the image geometry object associated with this tile source or NULL if non defined.
+//! The geometry contains full-to-local image transform as well as projection (image-to-world)
+//*************************************************************************************************
+ossimRefPtr<ossimImageGeometry> ossimGdalTileSource::getInternalImageGeometry() const
+{
+   static const char MODULE[] = "ossimGdalTileSource::getImageGeometry";
+   
+   if( !isOpen())
+   {
+      return ossimRefPtr<ossimImageGeometry>();
+   }
+   
+   // GDAL Driver Name
+   ossimString driverName = theDriver ? GDALGetDriverShortName( theDriver ) : "";
+   
+   // Projection Reference
+   const char* wkt = GDALGetProjectionRef( theDataset );
+   ossim_uint32 gcpCount = GDALGetGCPCount(theDataset);
+   if(!ossimString(wkt).empty() && gcpCount < 4)
+   {
+      if(traceDebug())
+      {
+         CLOG << "WKT PROJECTION STRING = " << wkt << std::endl;
+      }
+   }
+   else
+   {
+      // if ESAT driver we will for now try to creae a projection for it
+      //
+      if (traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG)
+            << "GDALGetGCPCount = " << gcpCount << std::endl;
+      }
+      
+      if(gcpCount > 3)
+      {
+         ossimRefPtr<ossimProjection> projGcp = 0;
+         wkt = GDALGetGCPProjection(theDataset);
+         if (!ossimString(wkt).empty())
+         {
+            ossimKeywordlist kwl;
+            
+            if (wktTranslator.toOssimKwl(wkt, kwl))
+            {
+               projGcp = ossimProjectionFactoryRegistry::instance()->createProjection(kwl);
+            }
+         }
+         
+         bool isGeo = true;
+         if (projGcp.valid())
+         {
+            ossimRefPtr<ossimMapProjection> mapProj = PTR_CAST(ossimMapProjection, projGcp.get());
+            if (mapProj.valid())
+            {
+               if (!mapProj->isGeographic())
+               {
+                  isGeo = false;
+               }
+            }
+         }
+         ossim_uint32 idx = 0;
+         const GDAL_GCP* gcpList = GDALGetGCPs(theDataset);
+         ossimTieGptSet tieSet;
+         if(!gcpList) return ossimRefPtr<ossimImageGeometry>();
+         
+         for(idx = 0; idx < gcpCount; ++idx)
+         {
+            //---
+            // Modified to add all tie points if gcpCount is < than
+            // 40 as dataset with five gcp's was failing because only one
+            // tiepoint was set from "if (idx%10 == 0)" logic.
+            // (drb - 20080615)
+            //---
+            if ((gcpCount < 40) || (idx%10 == 0))
+            {
+               ossimDpt dpt(gcpList[idx].dfGCPPixel, gcpList[idx].dfGCPLine);
+               ossimGpt gpt;
+               if (isGeo == false)
+               {
+                  ossimDpt dptEastingNorthing(gcpList[idx].dfGCPX, gcpList[idx].dfGCPY);
+                  gpt = projGcp->inverse(dptEastingNorthing);
+                  gpt.hgt = gcpList[idx].dfGCPZ;
+               }
+               else
+               {
+                  gpt = ossimGpt(gcpList[idx].dfGCPY, gcpList[idx].dfGCPX, gcpList[idx].dfGCPZ);
+               }
+               
+               tieSet.addTiePoint(new ossimTieGpt(gpt, dpt, .5));
+               
+               if (traceDebug())
+               {
+                  ossimNotify(ossimNotifyLevel_DEBUG)
+                     << "Added tie point for gcp[" << idx << "]: "
+                     << dpt << ", " << gpt << std::endl;
+               }
+            }
+         }
+         
+         ossimRefPtr<ossimBilinearProjection> bilinProj = new ossimBilinearProjection;
+         bilinProj->optimizeFit(tieSet);
+         
+         // Set the projection and return this handler's image geometry:
+         ossimRefPtr<ossimImageGeometry> geom = new ossimImageGeometry();
+         geom->setProjection(bilinProj.get());
+         return geom;
+      }
+   }
+   
+   // Geometric Transform
+   double geoTransform[6];
+   bool transOk = GDALGetGeoTransform( theDataset, geoTransform ) == CE_None;
+   if (!transOk)
+   {
+      if (traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG)
+            << MODULE << "DEBUG: GDALGetGeoTransform failed..." << std::endl;
+      }
+      return ossimRefPtr<ossimImageGeometry>();
+   }
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG: Geo transform = <" 
+         << geoTransform[0] << ", " << geoTransform[1] << ", " << geoTransform[2] << ", "
+         << geoTransform[3] << ", " << geoTransform[2] << ", " << geoTransform[5] << ">" 
+         << std::endl;
+   }
+  
+   // Convert WKT string to OSSIM keywordlist
+   ossimKeywordlist kwl;
+   if ( !wktTranslator.toOssimKwl(wkt, kwl) )
+   {
+      // sometimes geographic is just encoded in the matrix transform.  We can do a crude test
+      // to see if the tie points
+      // are within geographic bounds and then assume geographic so we can still load 
+      // projections
+      //
+      if(transOk&&(driverName=="AAIGrid"))
+      {
+         if(traceDebug())
+         {
+            ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG:TESTING GEOGRAPHIC = <" 
+               << geoTransform[0] << ", " << geoTransform[1] << ", " << geoTransform[2] << ", "
+               << geoTransform[3] << ", " << geoTransform[2] << ", " << geoTransform[5] << ">" 
+               << std::endl;
+         }
+         if((std::fabs(geoTransform[0]) < (180.0+FLT_EPSILON))&&
+            (std::fabs(geoTransform[3]) < (90.0 + FLT_EPSILON)))
+         {
+            ossimTieGptSet tieSet;
+            ossimIrect rect = getBoundingRect();
+            if(rect.hasNans()) return ossimRefPtr<ossimImageGeometry>();
+            // we will do an affine transform for the projeciton information
+            //
+            ossimDpt ul = rect.ul();
+            tieSet.addTiePoint(new ossimTieGpt(ossimGpt(geoTransform[3] + ul.x*geoTransform[4] + ul.y*geoTransform[5],
+               geoTransform[0] + ul.x*geoTransform[1] + ul.y*geoTransform[2]), 
+               ul, .5));
+            ossimDpt ur = rect.ur();
+            tieSet.addTiePoint(new ossimTieGpt(ossimGpt(geoTransform[3] + ur.x*geoTransform[4] + ur.y*geoTransform[5],
+               geoTransform[0] + ur.x*geoTransform[1] + ur.y*geoTransform[2]), 
+               ur, .5));
+            ossimDpt lr = rect.lr();
+            tieSet.addTiePoint(new ossimTieGpt(ossimGpt(geoTransform[3] + lr.x*geoTransform[4] + lr.y*geoTransform[5],
+               geoTransform[0] + lr.x*geoTransform[1] + lr.y*geoTransform[2]), 
+               lr, .5));
+            ossimDpt ll = rect.ll();
+            tieSet.addTiePoint(new ossimTieGpt(ossimGpt(geoTransform[3] + ll.x*geoTransform[4] + ll.y*geoTransform[5],
+               geoTransform[0] + ll.x*geoTransform[1] + ll.y*geoTransform[2]), 
+               ll, .5));
+            ossimRefPtr<ossimBilinearProjection> bilinProj = new ossimBilinearProjection;
+            bilinProj->optimizeFit(tieSet);
+
+            // Set the projection and return this handler's image geometry:
+            ossimRefPtr<ossimImageGeometry> geom = new ossimImageGeometry();
+            geom->setProjection(bilinProj.get());
+            return geom;
+         }
+         else
+         {
+            return ossimRefPtr<ossimImageGeometry>();
+         }
+      }
+      else
+      {
+         if (traceDebug())
+         {
+            ossimNotify(ossimNotifyLevel_DEBUG)
+               << MODULE << "DEBUG:  wktTranslator.toOssimKwl failed..." << std::endl;
+         }
+         return ossimRefPtr<ossimImageGeometry>();
+      }
+   }
+
+   // GARRETT! Where is this coming from?
+   // Projection, Datum, and Units
+   const char* prefix = 0; // legacy code. KWL is used internally now so don't need prefix
+   ossimString proj_type  = kwl.find(prefix, ossimKeywordNames::TYPE_KW);
+   ossimString datum_type = kwl.find(prefix, ossimKeywordNames::DATUM_KW);
+   ossimString units      = kwl.find(prefix, ossimKeywordNames::UNITS_KW);
+
+   ossimDpt gsd(fabs(geoTransform[1]), fabs(geoTransform[5]));
+
+   ossimUnitType savedUnitType = static_cast<ossimUnitType>(ossimUnitTypeLut::instance()->getEntryNumber(units)); 
+   ossimUnitType unitType = savedUnitType;
+   if(unitType == OSSIM_UNIT_UNKNOWN)
+   {
+      unitType = OSSIM_METERS;
+      units = "meters";
+   }
+   
+   // AIG driver considered pixel is area:
+   if(driverName == "AIG")
+      thePixelType = OSSIM_PIXEL_IS_AREA;
+
+   ossimDpt tie(geoTransform[0], geoTransform[3]);
+
+   if (thePixelType == OSSIM_PIXEL_IS_AREA)
+   {
+      tie.x += gsd.x/2.0;
+      tie.y -= gsd.y/2.0;
+   }
+
+   geoTransform[0] = tie.x;
+   geoTransform[3] = tie.y;
+
+   if(proj_type == "ossimLlxyProjection" ||
+      proj_type == "ossimEquDistCylProjection")
+   {
+      if(savedUnitType == OSSIM_UNIT_UNKNOWN)
+      {
+         unitType = OSSIM_DEGREES;
+         units = "degrees";
+      }
+   }
+   kwl.add(prefix, ossimKeywordNames::PIXEL_SCALE_XY_KW,    gsd.toString(), true);
+   kwl.add(prefix, ossimKeywordNames::PIXEL_SCALE_UNITS_KW, units,          true);
+   kwl.add(prefix, ossimKeywordNames::TIE_POINT_XY_KW,      tie.toString(), true);
+   kwl.add(prefix, ossimKeywordNames::TIE_POINT_UNITS_KW,   units,          true);
+   kwl.add(prefix, ossimKeywordNames::TIE_POINT_UNITS_KW,   units,          true);
+   std::stringstream mString;
+   mString << ossimString::toString(geoTransform[1], 20) << " " << ossimString::toString(geoTransform[2], 20)
+           << " " << 0 << " " << ossimString::toString(geoTransform[0], 20)
+           << " " << ossimString::toString(geoTransform[4], 20) << " " << ossimString::toString(geoTransform[5], 20)
+           << " " << 0 << " " << ossimString::toString(geoTransform[3], 20)
+           << " " << 0 << " " << 0 << " " << 1 << " " << 0
+           << " " << 0 << " " << 0 << " " << 0 << " " << 1;
+   
+   kwl.add(prefix, ossimKeywordNames::IMAGE_MODEL_TRANSFORM_MATRIX_KW, mString.str().c_str(), true);
+   kwl.add(prefix, ossimKeywordNames::IMAGE_MODEL_TRANSFORM_UNIT_KW, units, true);
+   
+   //---
+   // SPECIAL CASE:  ArcGrid in British National Grid
+   //---
+   if(driverName == "AIG" && datum_type.contains("OGB"))
+   {
+      ossimFilename prj_file = theImageFile.path() + "/prj.adf";
+      
+      if(prj_file.exists())
+      {
+         ossimKeywordlist prj_kwl(' ');
+         prj_kwl.addFile(prj_file);
+         
+         ossimString proj = prj_kwl.find("Projection");
+         
+         // Reset projection and Datum correctly for BNG.
+         if(proj.upcase().contains("GREATBRITAIN"))
+         {
+
+            kwl.add(prefix, ossimKeywordNames::TYPE_KW,
+               "ossimBngProjection", true);
+
+            ossimString datum  = prj_kwl.find("Datum");
+
+            if(datum != "")
+            {
+               if(datum == "OGB_A")
+                  datum = "OGB-A";
+               else if(datum == "OGB_B")
+                  datum = "OGB-B";
+               else if(datum == "OGB_C")
+                  datum = "OGB-C";
+               else if(datum == "OGB_D")
+                  datum = "OGB-D";
+               else if(datum == "OGB_M")
+                  datum = "OGB-M";
+               else if(datum == "OGB_7")
+                  datum = "OGB-7";
+
+               kwl.add(prefix, ossimKeywordNames::DATUM_KW, 
+                       datum, true);
+            }
+         }
+      }
+      else
+      {
+         if (traceDebug())
+         {
+            ossimNotify(ossimNotifyLevel_DEBUG)
+               << "MODULE DEBUG:"
+               << "\nUnable to accurately support ArcGrid due to missing"
+               << " prj.adf file." << std::endl;
+         }
+         return ossimRefPtr<ossimImageGeometry>();
+      }
+      
+   } // End of "if(driverName == "AIG" && datum_type == "OSGB_1936")"
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE <<  " DEBUG:"
+         << "\nwktTranslator keyword list:\n"
+         << kwl
+         << std::endl;
+   }
+
+   // Save for next time...
+   ossimProjection* proj = ossimProjectionFactoryRegistry::instance()->createProjection(kwl);
+   ossimRefPtr<ossimImageGeometry> geom = new ossimImageGeometry();
+   geom->setProjection(proj); // assumes ownership via ossiRefPtr mechanism
+
+   return geom;
+}
+
+//*******************************************************************
+// Public method:
+//*******************************************************************
+ossim_uint32 ossimGdalTileSource::getTileWidth() const
+{
+   return ( theTile.valid() ? theTile->getWidth() : 0 );
+}
+
+//*******************************************************************
+// Public method:
+//*******************************************************************
+ossim_uint32 ossimGdalTileSource::getTileHeight() const
+{
+   return ( theTile.valid() ? theTile->getHeight() : 0 );
+}
+
+ossimScalarType ossimGdalTileSource::getOutputScalarType() const
+{   
+   ossimScalarType result = getInputScalarType();
+
+   //---
+   // If theLut is valid typical output is eight bit RGB unless the flag is set to preserve
+   // palette indexes in which case it is typically 16 bit.
+   //---
+   if ( theLut.valid() && !m_preservePaletteIndexesFlag )
+   {
+      // Input different than output.
+      result = OSSIM_UINT8;
+   }
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimGdalTileSource::getOutputScalarType debug:"
+         << "\nOutput scalar: " << result << std::endl;
+   }
+
+   return result;
+}
+
+ossimScalarType ossimGdalTileSource::getInputScalarType() const
+{   
+   ossimScalarType result = OSSIM_SCALAR_UNKNOWN;
+
+
+   switch(theGdtType)
+   {
+      case GDT_Byte:
+      {
+         result = OSSIM_UINT8;
+         break;
+      }
+      case GDT_UInt16:
+      {
+         result = OSSIM_USHORT16;
+         break;
+      }
+      case GDT_Int16:
+      {
+         result = OSSIM_SSHORT16;
+         break;
+      }
+      case GDT_UInt32:
+      {
+         result = OSSIM_UINT32;
+         break;
+         
+      }
+      case GDT_Int32:
+      {
+         ossim_int32 sizeType = GDALGetDataTypeSize(theGdtType)/8;
+         if(sizeType == 2)
+         {
+            result = OSSIM_SSHORT16;
+            theGdtType = GDT_Int16;
+         }
+         else
+         {
+            result = OSSIM_SINT32;
+            theGdtType = GDT_Int32;
+         }
+         break;
+      }
+      case GDT_Float32:
+      {
+         result = OSSIM_FLOAT;
+         break;
+      }
+      case GDT_Float64:
+      {
+         result = OSSIM_DOUBLE;
+         break;
+      }
+      case GDT_CInt16:
+      {
+         result = OSSIM_SINT16;
+         break;
+      }
+      case  GDT_CInt32:
+      {
+         result = OSSIM_SINT32;
+         break;
+      }
+      case GDT_CFloat32:
+      {
+         result = OSSIM_FLOAT32;
+         break;
+      }
+      case GDT_CFloat64:
+      {
+         result = OSSIM_FLOAT64;
+         break;
+      }
+      default:
+         break;
+   }
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimGdalTileSource::getInputScalarType debug:"
+         << "\nGDAL Type:    " << theGdtType
+         << "\nInput scalar: " << result << std::endl;
+   }
+
+   return result;
+}
+
+double ossimGdalTileSource::getNullPixelValue(ossim_uint32 band)const
+{
+   double result = ossim::defaultNull(getOutputScalarType());
+
+   if ( theLut.valid() )
+   {
+      //---
+      // If serving up lut data zero may not be null.
+      // If m_preservePaletteIndexesFlag is set use the first alpha set to zero in the lut.
+      //---
+      ossim_int32 np = theLut->getNullPixelIndex();
+      if ( np != -1 ) // -1 means the lut does not know a null value.
+      {
+         result = theLut->getNullPixelIndex();
+      }
+   }
+   else if(theMetaData.getNumberOfBands())
+   {
+      result = ossimImageHandler::getNullPixelValue(band);
+   }
+   else if (theNullPixValues && (band < getNumberOfOutputBands()) )
+   {
+      result = theNullPixValues[band];
+   }
+   return result;
+}
+
+double ossimGdalTileSource::getMinPixelValue(ossim_uint32 band)const
+{
+   double result = ossim::defaultMin(getOutputScalarType());
+   if (  theLut.valid() )
+   {
+      result = 0;
+   }
+   else if(theMetaData.getNumberOfBands())
+   {
+      result = ossimImageHandler::getMinPixelValue(band);
+   }
+   else if (theMinPixValues && (band < getNumberOfOutputBands()) )
+   {
+      result = theMinPixValues[band];
+   }
+   return result;
+}
+
+double ossimGdalTileSource::getMaxPixelValue(ossim_uint32 band)const
+{
+   double result = ossim::defaultMax(getOutputScalarType());
+   if ( m_preservePaletteIndexesFlag && theLut.valid() && theLut->getNumberOfEntries() )
+   {
+      result = theLut->getNumberOfEntries() - 1;
+   }
+   else if(theMetaData.getNumberOfBands())
+   {
+      result = ossimImageHandler::getMaxPixelValue(band);
+   }
+   else if ( theMaxPixValues && (band < getNumberOfOutputBands()) )
+   {
+      result = theMaxPixValues[band];
+   }
+   return result;
+}
+
+void ossimGdalTileSource::computeMinMax()
+{
+   ossim_uint32 bands = GDALGetRasterCount(theDataset);
+
+   if(theMinPixValues)
+   {
+      delete [] theMinPixValues;
+      theMinPixValues = 0;
+   }
+   if(theMaxPixValues)
+   {
+      delete [] theMaxPixValues;
+      theMaxPixValues = 0;
+   }
+   if(theNullPixValues)
+   {
+      delete [] theNullPixValues;
+      theNullPixValues = 0;
+   }
+   if(isIndexTo3Band())
+   {
+      int i = 0;
+      theMinPixValues  = new double[3];
+      theMaxPixValues  = new double[3];
+      theNullPixValues = new double[3];
+
+      for(i = 0; i < 3; ++i)
+      {
+         theMinPixValues[i] = 1;
+         theMaxPixValues[i] = 255;
+         theNullPixValues[i] = 0;
+      }
+   }
+   else if(isIndexTo1Band())
+   {
+      theMinPixValues  = new double[1];
+      theMaxPixValues  = new double[1];
+      theNullPixValues = new double[1];
+      
+      *theNullPixValues = 0;
+      *theMaxPixValues = 255;
+      *theMinPixValues = 1;
+   }
+   else
+   {
+      if(!theMinPixValues && !theMaxPixValues&&bands)
+      {
+         theMinPixValues = new double[bands];
+         theMaxPixValues = new double[bands];
+         theNullPixValues = new double[bands];
+      }
+      for(ossim_int32 band = 0; band < (ossim_int32)bands; ++band)
+      {
+         GDALRasterBandH aBand=0;
+         
+         aBand = GDALGetRasterBand(theDataset, band+1);
+         
+         int minOk=1;
+         int maxOk=1;
+         int nullOk=1;
+         
+         if(aBand)
+         {
+	   if(hasMetaData())
+           {
+              theMinPixValues[band] = theMetaData.getMinPix(band);
+              theMaxPixValues[band] = theMetaData.getMaxPix(band);
+              theNullPixValues[band] = theMetaData.getNullPix(band);
+           }
+	   else 
+           {
+              ossimString driverName = theDriver ? GDALGetDriverShortName( theDriver ) : "";
+
+              // ESH 12/2008 -- Allow OSSIM to rescale the image data 
+              // to the min/max values found in the raster data only 
+              // if it was not acquired with the following drivers:
+              if ( driverName.contains("JP2KAK")   ||
+                   driverName.contains("JPEG2000") ||
+                   driverName.contains("NITF") )
+              {
+                 theMinPixValues[band] = ossim::defaultMin(getOutputScalarType());
+                 theMaxPixValues[band] = ossim::defaultMax(getOutputScalarType());
+                 theNullPixValues[band] = ossim::defaultNull(getOutputScalarType());
+              }
+              else
+              {
+                 theMinPixValues[band]  = GDALGetRasterMinimum(aBand, &minOk);
+                 theMaxPixValues[band]  = GDALGetRasterMaximum(aBand, &maxOk);
+                 theNullPixValues[band] = GDALGetRasterNoDataValue(aBand, &nullOk);
+              }
+              
+              if(!nullOk)
+              {
+                 theNullPixValues[band] = ossim::defaultNull(getOutputScalarType());
+              }
+           }
+
+           if(!minOk||!maxOk)
+           {
+               theMinPixValues[band] = ossim::defaultMin(getOutputScalarType());
+               theMaxPixValues[band] = ossim::defaultMax(getOutputScalarType());
+            }
+         }
+         else
+         {
+            theMinPixValues[band] = ossim::defaultMin(getOutputScalarType());
+            theMaxPixValues[band] = ossim::defaultMax(getOutputScalarType());
+         }
+      }
+   }
+}
+
+ossim_uint32 ossimGdalTileSource::getNumberOfDecimationLevels() const
+{
+   ossim_uint32 result = 1;
+   //---
+   // Note: This code was shut off since we currently don't utilize gdal overviews.  Returning
+   // this causes the overview builder will incorrectly start at the wrong res level.
+   // drb - 20110503
+   //---
+   if(theDataset&&!theOverview)
+   {
+      if(GDALGetRasterCount(theDataset))
+      {
+         GDALRasterBandH band = GDALGetRasterBand(theDataset, 1);
+         if(GDALGetOverviewCount(band))
+         {
+            result += (GDALGetOverviewCount(band));
+         }
+      }
+   }
+   if (theOverview.valid())
+   {
+      result += theOverview->getNumberOfDecimationLevels();
+   }
+   return result;
+}
+
+void ossimGdalTileSource::loadIndexTo3BandTile(const ossimIrect& clipRect,
+                                               ossim_uint32 aGdalBandStart,
+                                               ossim_uint32 anOssimBandStart)
+{
+   // Typical case 16 bit indexes, eight bit out, NOT 16 bit out.
+   ossimScalarType inScalar  = getInputScalarType();
+   ossimScalarType outScalar = getOutputScalarType();
+
+   if ( ( inScalar == OSSIM_UINT8 ) && ( outScalar == OSSIM_UINT8 ) )
+   {
+      loadIndexTo3BandTileTemplate(ossim_uint8(0), // input type
+                                   ossim_uint8(0), // output type
+                                   clipRect,
+                                   aGdalBandStart,
+                                   anOssimBandStart);
+   }
+   else if ( ( inScalar == OSSIM_UINT16 ) && ( outScalar == OSSIM_UINT8 ) )
+   {
+      loadIndexTo3BandTileTemplate(ossim_uint16(0), // input type
+                                   ossim_uint8(0),  // output type
+                                   clipRect,
+                                   aGdalBandStart,
+                                   anOssimBandStart);
+   }
+
+   else if ( ( inScalar == OSSIM_UINT16 ) && ( outScalar == OSSIM_UINT16 ) )
+   {
+      loadIndexTo3BandTileTemplate(ossim_uint16(0), // input type
+                                   ossim_uint16(0),  // output type
+                                   clipRect,
+                                   aGdalBandStart,
+                                   anOssimBandStart);
+   }
+   else if ( ( inScalar == OSSIM_SINT16 ) && ( outScalar == OSSIM_SINT16 ) )
+   {
+      loadIndexTo3BandTileTemplate(ossim_sint16(0), // input type
+                                   ossim_sint16(0),  // output type
+                                   clipRect,
+                                   aGdalBandStart,
+                                   anOssimBandStart);
+   }
+   else if ( ( inScalar == OSSIM_FLOAT32 ) && ( outScalar == OSSIM_FLOAT32 ) )
+   {
+      loadIndexTo3BandTileTemplate(ossim_float32(0.0), // input type
+                                   ossim_float32(0.0),  // output type
+                                   clipRect,
+                                   aGdalBandStart,
+                                   anOssimBandStart);
+   }
+   else if ( ( inScalar == OSSIM_FLOAT64 ) && ( outScalar == OSSIM_FLOAT64 ) )
+   {
+      loadIndexTo3BandTileTemplate(ossim_float64(0.0), // input type
+                                   ossim_float64(0.0),  // output type
+                                   clipRect,
+                                   aGdalBandStart,
+                                   anOssimBandStart);
+   }
+   else if ( ( inScalar == OSSIM_FLOAT64 ) && ( outScalar == OSSIM_UINT8 ) )
+   {
+      loadIndexTo3BandTileTemplate(ossim_float64(0.0), // input type
+                                   ossim_uint8(0.0),  // output type
+                                   clipRect,
+                                   aGdalBandStart,
+                                   anOssimBandStart);
+   }
+   else
+   {
+      ossimNotify(ossimNotifyLevel_WARN)
+         << __FILE__ << __LINE__
+         << " ossimGdalTileSource::loadIndexTo3BandTile WARNING!\n"
+         << "Unsupported scalar types:\nInupt scalar: " << inScalar
+         << "\nOutput scalar: " << outScalar
+         << std::endl;
+   }
+}
+
+template<class InputType, class OutputType>
+void ossimGdalTileSource::loadIndexTo3BandTileTemplate(InputType /* in */,
+                                                       OutputType /* out */,
+                                                       const ossimIrect& clipRect,
+                                                       ossim_uint32 aGdalBandStart,
+                                                       ossim_uint32 anOssimBandStart)
+{
+   const InputType* s = reinterpret_cast<const InputType*>(theSingleBandTile->getBuf());
+   GDALRasterBandH aBand=0;
+   aBand = GDALGetRasterBand(theDataset, aGdalBandStart);
+   GDALColorTableH table = GDALGetRasterColorTable(aBand);
+   
+   // ossim_uint32 rasterCount = GDALGetRasterCount(theDataset); 
+   ossim_uint32 anOssimBandEnd = anOssimBandStart + 2; 
+   if(getNumberOfOutputBands() < anOssimBandEnd)
+   {
+      return;
+   }
+   // Get the width of the buffers.
+   ossim_uint32 s_width = theSingleBandTile->getWidth();
+   ossim_uint32 d_width = theTile->getWidth();
+   ossimIrect src_rect  = theSingleBandTile->getImageRectangle();
+   ossimIrect img_rect  = theTile->getImageRectangle();
+   
+   // Move the pointers to the first valid pixel.
+   s += (clipRect.ul().y - src_rect.ul().y) * s_width +
+   clipRect.ul().x - src_rect.ul().x;
+   ossim_uint32 clipHeight = clipRect.height();
+   ossim_uint32 clipWidth  = clipRect.width();
+
+   OutputType* d[3];
+   d[0]= static_cast<OutputType*>(theTile->getBuf(anOssimBandStart));
+   d[1]= static_cast<OutputType*>(theTile->getBuf(anOssimBandStart + 1));
+   d[2]= static_cast<OutputType*>(theTile->getBuf(anOssimBandStart + 2));
+
+#if 0 /* Code shut off to treat all indexes as valid. */   
+   OutputType np[3];
+   np[0] = (OutputType)theTile->getNullPix(0);
+   np[1] = (OutputType)theTile->getNullPix(1);
+   np[2] = (OutputType)theTile->getNullPix(2);
+   
+   OutputType minp[3];
+   minp[0] = (OutputType)theTile->getMinPix(0);
+   minp[1] = (OutputType)theTile->getMinPix(1);
+   minp[2] = (OutputType)theTile->getMinPix(2);
+#endif
+   
+   ossim_uint32 offset = (clipRect.ul().y - img_rect.ul().y) * d_width +
+   clipRect.ul().x  - img_rect.ul().x;
+   d[0] += offset;
+   d[1] += offset;
+   d[2] += offset;
+   
+   // Copy the data.
+
+   GDALPaletteInterp interp = GDALGetPaletteInterpretation(table);
+
+   for (ossim_uint32 line = 0; line < clipHeight; ++line)
+   {
+      for (ossim_uint32 sample = 0; sample < clipWidth; ++sample)
+      {
+         GDALColorEntry entry;
+         if(GDALGetColorEntryAsRGB(table, s[sample], &entry))
+         {
+            if(interp == GPI_RGB)
+            {
+               if(!entry.c4)
+               {
+                  d[0][sample] = 0;
+                  d[1][sample] = 0;
+                  d[2][sample] = 0;
+               }
+               else
+               {
+#if 0 /* Code shut off to treat all indexes as valid. */
+                  d[0][sample] = entry.c1==np[0]?minp[0]:entry.c1;
+                  d[1][sample] = entry.c2==np[1]?minp[1]:entry.c2;
+                  d[2][sample] = entry.c3==np[2]?minp[2]:entry.c3;
+#endif
+                  d[0][sample] = entry.c1;
+                  d[1][sample] = entry.c2;
+                  d[2][sample] = entry.c3;
+                  
+               }
+            }
+            else
+            {
+               d[0][sample] = entry.c1;
+               d[1][sample] = entry.c2;
+               d[2][sample] = entry.c3;
+            }
+         }
+         else
+         {
+            d[0][sample] = 0;
+            d[1][sample] = 0;
+            d[2][sample] = 0;
+         }
+      }
+      
+      s += s_width;
+      d[0] += d_width;
+      d[1] += d_width;
+      d[2] += d_width;
+   }
+   
+}
+
+bool ossimGdalTileSource::isIndexTo3Band(int bandNumber)const
+{
+   GDALRasterBandH band = GDALGetRasterBand(theDataset, bandNumber);
+   if(GDALGetRasterColorInterpretation(band)==GCI_PaletteIndex)
+   {
+      GDALColorTableH table = GDALGetRasterColorTable(band);
+      GDALPaletteInterp interp = GDALGetPaletteInterpretation(table);
+      if( (interp == GPI_RGB) ||
+          (interp == GPI_HLS)||
+          (interp == GPI_CMYK))
+      {
+         return true;
+      }
+   }
+
+   return false;
+}
+
+bool ossimGdalTileSource::isIndexTo1Band(int bandNumber)const
+{
+   GDALRasterBandH band = GDALGetRasterBand(theDataset, bandNumber);
+   if(GDALGetRasterColorInterpretation(band)==GCI_PaletteIndex)
+   {
+      GDALColorTableH table = GDALGetRasterColorTable(band);
+      GDALPaletteInterp interp = GDALGetPaletteInterpretation(table);
+      if(interp == GPI_Gray)
+      {
+         return true;
+      }
+   }
+
+   return false;
+}
+
+ossim_uint32 ossimGdalTileSource::getIndexBandOutputNumber(int bandNumber)const
+{
+   if(isIndexed(bandNumber))
+   {
+      GDALRasterBandH band = GDALGetRasterBand(theDataset, bandNumber);
+      if(GDALGetRasterColorInterpretation(band)==GCI_PaletteIndex)
+      {
+         GDALColorTableH table = GDALGetRasterColorTable(band);
+         GDALPaletteInterp interp = GDALGetPaletteInterpretation(table);
+         switch(interp)
+         {
+            case GPI_CMYK:
+            case GPI_RGB:
+            case GPI_HLS:
+            {
+               return 3;
+            }
+            case GPI_Gray:
+            {
+               return 1;
+            }
+         }
+      }
+   }
+
+   return 0;
+}
+
+bool ossimGdalTileSource::isIndexed(int aGdalBandNumber)const
+{
+   if(aGdalBandNumber <= GDALGetRasterCount(theDataset))
+   {
+      GDALRasterBandH band = GDALGetRasterBand(theDataset, aGdalBandNumber);
+      if(!band) return false;
+      if(GDALGetRasterColorInterpretation(band)==GCI_PaletteIndex)
+      {
+         return true;
+      }
+   }
+   
+   return false;
+}
+
+// Temp "return 128x128;" until I can figure out how to tell if tiled (gcp)
+ossim_uint32 ossimGdalTileSource::getImageTileWidth() const
+{
+   return 128;
+}
+
+ossim_uint32 ossimGdalTileSource::getImageTileHeight() const
+{
+   return 128;
+}
+
+void ossimGdalTileSource::getMaxSize(ossim_uint32 resLevel,
+                                     int& maxX,
+                                     int& maxY)const
+{
+   int aGdalBandIndex = 0;
+   maxX = 0;
+   maxY = 0;
+   
+   if(theOverview.valid() && theOverview->isValidRLevel(resLevel))
+   {
+      ossimIrect rect = theOverview->getBoundingRect(resLevel);
+      if(!rect.hasNans())
+      {
+         maxX = rect.width();
+         maxY = rect.height();
+      }
+      return;
+   }
+   
+   for(aGdalBandIndex=1;
+       (int)aGdalBandIndex <= (int)GDALGetRasterCount(theDataset);
+       ++aGdalBandIndex)
+   {
+      GDALRasterBandH aBand = resolveRasterBand(resLevel, aGdalBandIndex);
+      if(aBand)
+      {
+         maxY = ossim::max<int>((int)GDALGetRasterBandYSize(aBand), maxY);
+         maxX = ossim::max<int>((int)GDALGetRasterBandXSize(aBand), maxX);
+      }
+      else
+      {
+         break;
+      }
+   }
+}
+
+GDALRasterBandH ossimGdalTileSource::resolveRasterBand( ossim_uint32 resLevel,
+                                                        int aGdalBandIndex ) const
+{
+   GDALRasterBandH aBand = GDALGetRasterBand( theDataset, aGdalBandIndex );
+
+   if( resLevel > 0 )
+   {
+      int overviewIndex = resLevel-1;
+
+      GDALRasterBandH overviewBand = GDALGetOverview( aBand, overviewIndex );
+      if ( overviewBand )
+      {
+         aBand = overviewBand;
+      }
+   }
+
+   return aBand;
+}
+
+ossimString ossimGdalTileSource::getShortName()const
+{
+   ossimString result = "gdal";
+   if ( theDriver )
+   {
+      const char* driver = GDALGetDriverShortName(theDriver);
+      if ( driver )
+      {
+         result += "_";
+         result += driver;
+      }
+   }
+   return result;
+}
+
+ossimString ossimGdalTileSource::getLongName()const
+{
+   return ossimString("gdal reader");
+}
+
+ossimString ossimGdalTileSource::getClassName()const
+{
+   return ossimString("ossimGdalTileSource");
+}
+
+bool ossimGdalTileSource::isOpen()const
+{
+   return (theDataset != 0);
+}
+
+ossim_uint32 ossimGdalTileSource::getCurrentEntry()const
+{
+   return theEntryNumberToRender;
+}
+
+bool ossimGdalTileSource::setCurrentEntry(ossim_uint32 entryIdx)
+{
+   if ( isOpen() && (theEntryNumberToRender == entryIdx) )
+   {
+      return true; // Nothing to do...
+   }
+   theDecimationFactors.clear();
+   theGeometry = 0;
+   theOverview = 0;
+   theOverviewFile.clear();
+   m_outputBandList.clear();
+   theEntryNumberToRender = entryIdx;
+   return open();
+}
+
+void ossimGdalTileSource::getEntryList(std::vector<ossim_uint32>& entryList) const
+{
+   entryList.clear();
+   if (theSubDatasets.size())
+   {
+      for (ossim_uint32 i = 0; i < theSubDatasets.size(); ++i)
+      {
+         entryList.push_back(i);
+      }
+   }
+   else
+   {
+      entryList.push_back(0);
+   }
+}
+
+void ossimGdalTileSource:: getEntryNames(std::vector<ossimString>& entryStringList) const
+{
+   if (theSubDatasets.size())
+   {
+      entryStringList = theSubDatasets;
+   }
+   else
+   {
+      ossimImageHandler::getEntryNames(entryStringList);
+   }
+}
+
+ossimString ossimGdalTileSource::filterSubDatasetsString(const ossimString& subString) const
+{
+   //---
+   // Skip up to and including '=' and filter out the quotes '"'.
+   //---
+   ossimString s;
+   bool atStart = false;
+   for (ossim_uint32 pos = 0; pos < subString.size(); ++pos)
+   {
+      if ( *(subString.begin()+pos) == '=')
+      {
+         atStart = true; // Start recording after this.
+         continue;       // Skip the '='.
+      }
+      if (atStart)
+      {
+         //if (*(subString.begin()+pos) == '\"')
+         //{
+          //  continue;  // Skip the '='.
+         //}
+         s.push_back(*(subString.begin()+pos)); // Record the character.
+      }
+   }
+   return s;
+}
+
+bool ossimGdalTileSource::isBlocked( int /* band */ )const
+{
+   return m_isBlocked;
+}
+
+void ossimGdalTileSource::populateLut()
+{
+   theLut = 0; // ossimRefPtr not a leak.
+   
+   if(isIndexed(1)&&theDataset)
+   {
+      GDALColorTableH aTable = GDALGetRasterColorTable(GDALGetRasterBand( theDataset, 1 ));
+      GDALPaletteInterp interp = GDALGetPaletteInterpretation(aTable);
+      if(aTable && ( (interp == GPI_Gray) || (interp == GPI_RGB)))
+      {
+         GDALColorEntry colorEntry;
+         ossim_uint32 numberOfElements = GDALGetColorEntryCount(aTable);
+         ossim_uint32 idx = 0;
+         if(numberOfElements)
+         {
+            // GPI_Gray Grayscale (in GDALColorEntry.c1)
+            // GPI_RGB Red, Green, Blue and Alpha in (in c1, c2, c3 and c4)
+            theLut = new ossimNBandLutDataObject(numberOfElements,
+                                                 4,
+                                                 OSSIM_UINT8,
+                                                 -1);
+
+            bool nullSet = false;
+            for(idx = 0; idx < numberOfElements; ++idx)
+            {
+               switch(interp)
+               {
+                  case GPI_RGB:
+                  {
+                     if(GDALGetColorEntryAsRGB(aTable, idx, &colorEntry))
+                     {
+                        (*theLut)[idx][0] = colorEntry.c1;
+                        (*theLut)[idx][1] = colorEntry.c2;
+                        (*theLut)[idx][2] = colorEntry.c3;
+                        (*theLut)[idx][3] = colorEntry.c4;
+
+                        if ( !nullSet )
+                        {
+                           if ( m_preservePaletteIndexesFlag )
+                           {
+                              // If preserving palette set the null to the fix alpha of 0.
+                              if ( (*theLut)[idx][3] == 0 )
+                              {
+                                 theLut->setNullPixelIndex(idx);
+                                 nullSet = true;
+                              }
+                           }
+                           else
+                           {
+                              //---
+                              // Not using alpha.
+                              // Since the alpha is currently not used, look for the null
+                              // pixel index and set if we find. If at some point the alpha
+                              // is taken out this can be removed.
+                              //---
+                              if ( ( (*theLut)[idx][0] == 0 ) &&
+                                   ( (*theLut)[idx][1] == 0 ) &&
+                                   ( (*theLut)[idx][2] == 0 ) )
+                              {
+                                 theLut->setNullPixelIndex(idx);
+                                 nullSet = true;
+                              }
+                           }
+                        }
+                     }
+                     else
+                     {
+                        (*theLut)[idx][0] = 0;
+                        (*theLut)[idx][1] = 0;
+                        (*theLut)[idx][2] = 0;
+                        (*theLut)[idx][3] = 0;
+
+                        // Look for the null pixel index and set if we find.
+                        if ( !nullSet )
+                        {
+                           if ( (*theLut)[idx][0] == 0 )
+                           {
+                              theLut->setNullPixelIndex(idx);
+                           }
+                        }
+                     }
+                     break;
+                  }
+                  case GPI_Gray:
+                  {
+                     const GDALColorEntry* constEntry =  GDALGetColorEntry(aTable, idx);
+                     if(constEntry)
+                     {
+                        (*theLut)[idx][0] = constEntry->c1;
+                     }
+                     else
+                     {
+                        (*theLut)[idx][0] = 0;
+                     }
+                     break;
+                  }
+                  default:
+                  {
+                     break;
+                  }
+               }
+            }
+         }
+      }
+
+      ossim_uint32 rasterCount = GDALGetRasterCount(theDataset);
+      for(ossim_uint32 aGdalBandIndex=1; aGdalBandIndex <= rasterCount; ++aGdalBandIndex)
+      {
+         GDALRasterBandH aBand = GDALGetRasterBand( theDataset, aGdalBandIndex );
+         if (aBand)
+         {
+            GDALRasterAttributeTableH hRAT = GDALGetDefaultRAT(aBand);
+            int colCount = GDALRATGetColumnCount(hRAT);
+            for (ossim_int32 col = 0; col < colCount; col++)
+            {
+               const char* colName = GDALRATGetNameOfCol(hRAT, col);
+               if (colName)
+               {
+                  if (strcmp(colName, "Class_Names") == 0)
+                  {
+                     std::vector<ossimString> entryLabels;
+                     ossim_int32 rowCount = GDALRATGetRowCount(hRAT);
+                     for (ossim_int32 row = 0; row < rowCount; row++)
+                     {
+                        const char* className = GDALRATGetValueAsString(hRAT, row, col);
+                        ossimString entryLabel(className);
+                        entryLabels.push_back(entryLabel);
+                     }
+                     theLut->setEntryLables(aGdalBandIndex-1, entryLabels);
+                  }
+               }
+            }
+         }
+      }
+   }
+}
+
+void ossimGdalTileSource::setProperty(ossimRefPtr<ossimProperty> property)
+{
+   if ( property->getName() == PRESERVE_PALETTE_KW )
+   {
+      ossimString s;
+      property->valueToString(s);
+
+      // Go through set method as it will adjust theTile bands if need be.
+      setPreservePaletteIndexesFlag(s.toBool());
+   }
+   else
+   {
+      ossimImageHandler::setProperty(property);
+   }
+}
+
+ossimRefPtr<ossimProperty> ossimGdalTileSource::getProperty(const ossimString& name)const
+{
+   ossimRefPtr<ossimProperty> result = 0;
+   
+   if( (name == DRIVER_SHORT_NAME_KW) && isOpen() )
+   {
+      ossimString driverName = GDALGetDriverShortName( theDriver );
+      result = new ossimStringProperty(name, driverName);
+   }
+   else if ( (name == "imag") && isOpen() )
+   {
+      if (theDataset)
+      {
+         ossimString nitfImagTag( GDALGetMetadataItem( theDataset, "NITF_IMAG", "" ) );
+         if (!nitfImagTag.empty())
+         {
+            result = new ossimStringProperty(name, nitfImagTag);
+         }
+      }
+   }
+   else if ( name == PRESERVE_PALETTE_KW )
+   {
+      result = new ossimBooleanProperty(name, m_preservePaletteIndexesFlag);
+   }
+   else
+   {
+     result = ossimImageHandler::getProperty(name);
+   }
+   return result;
+}
+
+void ossimGdalTileSource::getPropertyNames(std::vector<ossimString>& propertyNames)const
+{
+   propertyNames.push_back(DRIVER_SHORT_NAME_KW);
+   propertyNames.push_back(PRESERVE_PALETTE_KW);
+   ossimImageHandler::getPropertyNames(propertyNames);
+}
+
+bool ossimGdalTileSource::setOutputBandList(const vector<ossim_uint32>& outputBandList)
+{
+   m_outputBandList.clear();
+   if (outputBandList.size())
+   {
+      ossim_uint32 bandCount = GDALGetRasterCount(theDataset);
+      for (ossim_uint32 i = 0; i < outputBandList.size(); i++)
+      {
+         if (outputBandList[i] > bandCount)//check if it is a valid band
+         {
+            return false;
+         }
+      }
+      m_outputBandList = outputBandList;  // Assign the new list.
+      return true;
+   }
+   return false;
+}
+
+void ossimGdalTileSource::setPreservePaletteIndexesFlag(bool flag)
+{
+   bool stateChanged = (flag && !m_preservePaletteIndexesFlag);
+
+   //---
+   // Affects: ossimGdalTileSource::getNumberOfOutputBands
+   //          ossimGdalTileSource::getOutputScalarType
+   //---
+   m_preservePaletteIndexesFlag = flag; 
+   
+   if ( isOpen() && stateChanged )
+   {
+      //---
+      // Already went through open so we must change the output tile from 3 band to 1 and the
+      // output scalar type may have also changed.
+      // Note the ossimImageDataFactory::create will call back to us for bands and scalr type
+      // which have now changed.
+      //---
+      theTile = ossimImageDataFactory::instance()->create(this, this);
+      theTile->setIndexedFlag(true);
+      theTile->initialize();
+
+      theSingleBandTile = ossimImageDataFactory::instance()->create(this, this);
+      theSingleBandTile->setIndexedFlag(true);
+      theSingleBandTile->initialize();
+
+      if ( m_preservePaletteIndexesFlag && theLut.valid() )
+      {
+         ossim_int32 nullIndex = theLut->getFirstNullAlphaIndex();
+         if ( nullIndex > -1 ) // Returns -1 if not found.
+         {
+            // This will be used for fill in leiu of theTile->makeBlank().
+            theLut->setNullPixelIndex(nullIndex);
+         }
+      }
+   }
+}
+
+bool ossimGdalTileSource::getPreservePaletteIndexesFlag() const
+{
+   return m_preservePaletteIndexesFlag;
+}
+
+//---
+// Overrides ossimImageSource::isIndexedData to palette indicate we are passing palette indexes
+// not rgb pixel data down the stream.
+//---
+bool ossimGdalTileSource::isIndexedData() const
+{
+   return m_preservePaletteIndexesFlag;
+}
+
+void ossimGdalTileSource::getDefaults()
+{
+   // Look for the preserve_palette flag:
+   const char* lookup = ossimPreferences::instance()->findPreference(PRESERVE_PALETTE_KW);
+   if (lookup)
+   {
+      setPreservePaletteIndexesFlag(ossimString(lookup).toBool());
+   }
+}
+void ossimGdalTileSource::deleteRlevelCache()
+{
+   //ossimAppFixedTileCache::instance()->deleteCache(m_blockCacheId);
+   ossim_uint32 idx = 0;
+   for(idx = 0; idx < m_rlevelBlockCache.size();++idx)
+   {
+      ossimAppFixedTileCache::instance()->deleteCache(m_rlevelBlockCache[idx]);
+   }
+   m_rlevelBlockCache.clear();
+}
+
+void ossimGdalTileSource::setRlevelCache()
+{
+   if(m_isBlocked)
+   {
+      if(m_rlevelBlockCache.size() > 0) deleteRlevelCache();
+      ossim_uint32 nLevels = getNumberOfDecimationLevels();
+      ossim_uint32 idx = 0;
+      int xSize=0, ySize=0;
+      m_rlevelBlockCache.resize(nLevels);
+      for(idx =0; idx < nLevels; ++idx)
+      {
+         GDALGetBlockSize(resolveRasterBand( idx, 1 ),
+                          &xSize,
+                          &ySize);
+         ossimIpt blockSize(xSize, ySize);
+         ossimIrect rectBounds = getBoundingRect(idx);
+         rectBounds.stretchToTileBoundary(blockSize);
+         m_rlevelBlockCache[idx] = ossimAppFixedTileCache::instance()->newTileCache(rectBounds, blockSize); 
+      }
+   }
+}
diff --git a/ossim_plugins/gdal/ossimGdalTileSource.h b/ossim_plugins/gdal/ossimGdalTileSource.h
new file mode 100644
index 0000000..d551032
--- /dev/null
+++ b/ossim_plugins/gdal/ossimGdalTileSource.h
@@ -0,0 +1,347 @@
+//*******************************************************************
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author:  Garrett Potts
+//
+// Description:
+//
+// Contains class definition for the class "ossimGdalTileSource".
+//
+//*******************************************************************
+//  $Id: ossimGdalTileSource.h 23664 2015-12-14 14:17:27Z dburken $
+
+#ifndef ossimGdalTileSource_HEADER
+#define ossimGdalTileSource_HEADER 1
+
+#include <ossim/imaging/ossimImageHandler.h>
+#include "../ossimPluginConstants.h"
+#include <ossim/base/ossimConstants.h>
+#include <ossim/base/ossimIrect.h>
+#include <ossim/base/ossimString.h>
+#include <ossim/imaging/ossimImageData.h>
+#include <gdal.h>
+#include <vector>
+#include <ossim/imaging/ossimAppFixedTileCache.h>
+
+class ossimImageData;
+
+class OSSIM_PLUGINS_DLL ossimGdalTileSource : public ossimImageHandler
+{
+public:
+   ossimGdalTileSource();
+   virtual ~ossimGdalTileSource();
+
+   /**
+    * @return "gdal_"+"driver_shortname", e.g. "gdal_GIF" or just gdal if not
+    * initialized."
+    */
+   virtual ossimString getShortName()const;
+   
+   virtual ossimString getLongName()const;
+   virtual ossimString getClassName()const;
+
+   virtual void close();
+
+   /**
+    *  @return Returns true on success, false on error.
+    *
+    *  @note This method relies on the data member ossimImageData::theImageFile
+    *  being set.  Callers should do a "setFilename" prior to calling this
+    *  method or use the ossimImageHandler::open that takes a file name and an
+    *  entry index.
+    */   
+   virtual bool open();
+
+   /**
+    *  Returns a pointer to a tile given an origin representing the upper
+    *  left corner of the tile to grab from the image.
+    *  Satisfies pure virtual from TileSource class.
+    */
+   virtual ossimRefPtr<ossimImageData> getTile(const ossimIrect& tileRect,
+                                   ossim_uint32 resLevel=0);
+
+   /**
+    *  Returns the number of bands in the image.
+    *  Satisfies pure virtual from ImageHandler class.
+    */
+   virtual ossim_uint32 getNumberOfInputBands() const;
+
+    /**
+    * Returns the number of bands in a tile returned from this TileSource.
+    * Note: we are supporting sources that can have multiple data objects.
+    * If you want to know the scalar type of an object you can pass in the 
+    */
+   virtual ossim_uint32 getNumberOfOutputBands() const;
+  
+   /**
+    *  Returns the number of bands in the image.
+    *  Satisfies pure virtual from ImageHandler class.
+    */
+   virtual ossim_uint32 getNumberOfLines(ossim_uint32 reduced_res_level = 0) const;
+
+   /**
+    *  Returns the number of bands available from an image.
+    *  Satisfies pure virtual from ImageHandler class.
+    */
+   virtual ossim_uint32 getNumberOfSamples(ossim_uint32 reduced_res_level = 0) const;
+
+   /**
+    * Returns the number of reduced resolution data sets (rrds).
+    * Note:  The full res image is counted as a data set so an image with no
+    *        reduced resolution data set will have a count of one.
+    */
+   virtual ossim_uint32 getNumberOfDecimationLevels() const;
+
+   /**
+    * Returns the zero based image rectangle for the reduced resolution data
+    * set (rrds) passed in.  Note that rrds 0 is the highest resolution rrds.
+    */
+   virtual ossimIrect getImageRectangle(ossim_uint32 reduced_res_level = 0) const;
+
+   /**
+    * Method to save the state of an object to a keyword list.
+    * Return true if ok or false on error.
+    */
+   virtual bool saveState(ossimKeywordlist& kwl,
+                          const char* prefix=0)const;
+
+   /**
+    * Method to the load (recreate) the state of an object from a keyword
+    * list.  Return true if ok or false on error.
+    */
+   virtual bool loadState(const ossimKeywordlist& kwl,
+                          const char* prefix=0);
+
+   /**
+    * Returns the image geometry object associated with this tile source or
+    * NULL if non defined.  The geometry contains full-to-local image
+    * transform as well as projection (image-to-world).
+    */
+   virtual ossimRefPtr<ossimImageGeometry> getImageGeometry();
+   
+   /**
+    * Returns the image geometry object associated with this tile source or NULL if non defined.
+    * The geometry contains full-to-local image transform as well as projection (image-to-world)
+    */
+   virtual ossimRefPtr<ossimImageGeometry> getInternalImageGeometry() const;
+
+   /**
+    * Returns the output pixel type of the tile source.
+    */
+   virtual ossimScalarType getOutputScalarType() const;
+
+   /**
+    * @brief Gets the input scalar type of the tile source. Note this could be
+    * different than the output scalar type if for instance the input is
+    * lut data or complex data.
+    * @return The input scalar type
+    */
+   ossimScalarType getInputScalarType() const;
+
+   /**
+    * Returns the width of the output tile.
+    */
+   virtual ossim_uint32 getTileWidth() const;
+   
+   /**
+    * Returns the height of the output tile.
+    */
+   virtual ossim_uint32 getTileHeight() const;
+
+   /**
+    * Returns the tile width of the image or 0 if the image is not tiled.
+    * Note: this is not the same as the ossimImageSource::getTileWidth which
+    * returns the output tile width which can be different than the internal
+    * image tile width on disk.
+    */
+   virtual ossim_uint32 getImageTileWidth() const;
+
+   /**
+    * Returns the tile width of the image or 0 if the image is not tiled.
+    * Note: this is not the same as the ossimImageSource::getTileWidth which
+    * returns the output tile width which can be different than the internal
+    * image tile width on disk.
+    */
+   virtual ossim_uint32 getImageTileHeight() const;
+
+   /**
+    * @return The current entry number.
+    */
+   virtual ossim_uint32 getCurrentEntry()const;
+   
+   /**
+    * @param entryIdx Entry number to select.  This will set the data member
+    * "theEntryNumberToRender", then call open().
+    */
+   virtual bool setCurrentEntry(ossim_uint32 entryIdx);
+
+   /**
+    * @param entryList This is the list to initialize with entry indexes.
+    */
+   virtual void getEntryList(std::vector<ossim_uint32>& entryList)const;
+
+   /**
+    * @param entryStringList List to initialize with strings associated with
+    * entries.
+    */
+   virtual void getEntryNames(
+      std::vector<ossimString>& entryStringList) const;
+   
+   virtual bool isOpen()const;
+   
+   virtual double getNullPixelValue(ossim_uint32 band=0)const;
+   virtual double getMinPixelValue(ossim_uint32 band=0)const;
+   virtual double getMaxPixelValue(ossim_uint32 band=0)const;
+
+   /**
+    * @brief Set propterty method. Overrides ossimImageHandler::setProperty.
+    *
+    * Current property name handled:
+    * "scale" One double value representing the scale in meters per pixel. It is
+    * assumed the scale is same for x and y direction.
+    * 
+    * @param property to set.
+    */
+   virtual void setProperty(ossimRefPtr<ossimProperty> property);
+   
+   /**
+    * @brief Get propterty method. Overrides ossimImageHandler::getProperty.
+    * @param name Property name to get.
+    */
+   virtual ossimRefPtr<ossimProperty> getProperty(const ossimString& name) const;
+
+   /**
+    * @brief Get propterty names. Overrides ossimImageHandler::getPropertyNames.
+    * @param propertyNames Array to initialize.
+    */
+   virtual void getPropertyNames(std::vector<ossimString>& propertyNames) const; 
+
+   /**
+    * @param resLevel Reduced resolution set for requested decimation.
+    *
+    * @param result ossimDpt to initialize with requested decimation.
+    * 
+    * @note Initialized "result" with the decimation factor for the passed in
+    * resLevel.
+    * Most of the time the returned factor is a square decimation along x
+    * and y indicated by result.x and .y  = 1.0/(resLevel^2) where ^
+    * means rasing to the power of.  If the resLevel is 1 then the return
+    * decimation .5, .5. this is not the decimation to each resolution
+    * level but the total decimation from res level 0.
+    * So if resLevel is 2 then the return is .25, .25.
+    *
+    * @note Derived classes should override if the decimation is anything other
+    * than a power of two change in each direction per res level.
+    */
+   virtual void getDecimationFactor(ossim_uint32 resLevel,
+                                    ossimDpt& result) const;
+
+   GDALDriverH getDriver();
+
+   virtual bool setOutputBandList(const std::vector<ossim_uint32>& band_list);
+
+   /**
+    * @brief Sets preserve palette indexes flag.
+    *
+    * If true and the image is paletted, the tile returned will contain the
+    * indexes instead of the LUT values. Default=false.
+    * 
+    * @param flag
+    */
+   void setPreservePaletteIndexesFlag(bool flag);
+
+   /** @return Preserve palette flag. */
+   bool getPreservePaletteIndexesFlag() const;
+
+   /**
+    * @brief Indicated data is indexed.
+    *
+    * Overrides ossimImageSource::isIndexedData to indicate we are passing
+    * palette indexes not rgb pixel data down the stream.
+    * 
+    * @return Flag indicating the data contains pallete indexes.
+    */
+   virtual bool isIndexedData() const;
+   
+private:
+
+   /**
+    * @param clipRect The requested tile rectangle clipped  to the image
+    * bounds.
+    *
+    * @param resLevel Reduced resolution level to load from.
+    */
+   ossimRefPtr<ossimImageData> getTileBlockRead(const ossimIrect& tileRect,
+                                                ossim_uint32 resLevel);
+
+   /**
+    * Filters string from "GDALGetMetadata( theDataset, "SUBDATASETS" )
+    *
+    * @return Filtered string that GDALOpen will handle.
+    */
+   ossimString filterSubDatasetsString(const ossimString& subString) const;
+   
+   void computeMinMax();
+   void loadIndexTo3BandTile(const ossimIrect& clipRect,
+                             ossim_uint32 aGdalBandStart = 1,
+                             ossim_uint32 anOssimBandStart = 0);
+   template<class InputType, class OutputType>
+   void loadIndexTo3BandTileTemplate(InputType in,
+                                     OutputType out,
+                                     const ossimIrect& clipRect,
+                                     ossim_uint32 aGdalBandStart = 1,
+                                     ossim_uint32 anOssimBandStart = 0);
+   
+   bool isIndexTo3Band(int bandNumber = 1)const;
+   bool isIndexTo1Band(int bandNumber = 1)const;
+   ossim_uint32 getIndexBandOutputNumber(int bandNumber)const;
+   bool isIndexed(int aGdalBandNumber = 1)const;
+   void getMaxSize(ossim_uint32 resLevel,
+                   int& maxX,
+                   int& maxY)const;
+   bool isBlocked(int band)const;
+   void populateLut();
+
+   /**
+    * For the given resolution level and GDAL band index, 
+    * return a corresponding GDAL raster band.
+    */
+   GDALRasterBandH resolveRasterBand( ossim_uint32 resLevel,
+                                      int gdalBandIndex ) const;
+
+   ossimRefPtr<ossimImageGeometry> getExternalImageGeometryFromXml() const;
+   void deleteRlevelCache();
+   void setRlevelCache();
+   /** @brief Checks prefences for default settings. */
+   void getDefaults();  
+   
+   GDALDatasetH        theDataset;
+   GDALDriverH         theDriver;
+
+   ossimRefPtr<ossimImageData> theTile;
+   ossimRefPtr<ossimImageData> theSingleBandTile;
+   std::vector<ossim_uint8>    theGdalBuffer;
+   ossimIrect                  theImageBound;
+   mutable GDALDataType        theGdtType;
+   mutable GDALDataType        theOutputGdtType;
+   double*                     theMinPixValues;
+   double*                     theMaxPixValues;
+   double*                     theNullPixValues;
+   ossim_uint32                theEntryNumberToRender;
+   std::vector<ossimString>    theSubDatasets;
+   bool                        theIsComplexFlag;
+   bool                        theAlphaChannelFlag;
+   bool                        m_preservePaletteIndexesFlag;
+   vector<ossim_uint32>        m_outputBandList;
+   bool                        m_isBlocked;
+
+   std::vector<ossimAppFixedTileCache::ossimAppFixedCacheId> m_rlevelBlockCache;
+  
+TYPE_DATA
+};
+
+#endif
+
diff --git a/ossim_plugins/gdal/ossimGdalTiledDataset.cpp b/ossim_plugins/gdal/ossimGdalTiledDataset.cpp
new file mode 100644
index 0000000..d921b95
--- /dev/null
+++ b/ossim_plugins/gdal/ossimGdalTiledDataset.cpp
@@ -0,0 +1,556 @@
+//------------------------------------------------------------------------
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author:  Garrett Potts
+//
+// $Id: ossimGdalTiledDataset.cpp 23664 2015-12-14 14:17:27Z dburken $
+//------------------------------------------------------------------------
+#include "ossimGdalTiledDataset.h"
+#include <ossim/vpfutil/set.h>
+#include "ossimGdalType.h"
+
+#include <ossim/imaging/ossimImageSourceSequencer.h>
+#include <ossim/imaging/ossimImageData.h>
+#include <ossim/imaging/ossimImageDataFactory.h>
+#include <ossim/base/ossimProcessProgressEvent.h>
+#include <cpl_string.h>
+
+static GDALDriver	*poMEMTiledDriver = NULL;
+
+#include <ossim/base/ossimTrace.h>
+static ossimTrace traceDebug(ossimString("ossimGdalTiledDataset:debug"));
+
+GDALRasterBandH MEMTiledCreateRasterBand( GDALDataset *poDS, int nBand, 
+                                          GByte *pabyData, GDALDataType eType, 
+                                          int nPixelOffset, int nLineOffset, 
+                                          int bAssumeOwnership )
+
+{
+    return (GDALRasterBandH) 
+        new MEMTiledRasterBand( poDS, nBand, pabyData, eType, nPixelOffset, 
+                                nLineOffset, bAssumeOwnership );
+}
+
+/************************************************************************/
+/*                           MEMTiledRasterBand()                            */
+/************************************************************************/
+
+MEMTiledRasterBand::MEMTiledRasterBand( GDALDataset *poDS,
+                                        int nBand,
+                                        GByte *pabyData,
+                                        GDALDataType eType,
+                                        int nPixelOffset,
+                                        int nLineOffset,
+                                        int bAssumeOwnership )
+   :
+   MEMRasterBand(poDS,
+                 nBand,
+                 pabyData,
+                 eType,
+                 nPixelOffset,
+                 nLineOffset,
+                 bAssumeOwnership),
+   theDataset(NULL),
+   theInterface(NULL)
+{
+}
+
+/************************************************************************/
+/*                           ~MEMTiledRasterBand()                           */
+/************************************************************************/
+
+MEMTiledRasterBand::~MEMTiledRasterBand()
+
+{
+    CPLDebug( "MEM", "~MEMTiledRasterBand(%p)", this );
+    if( bOwnData )
+    {
+        CPLDebug( "MEM", "~MEMTiledRasterBand() - free raw data." );
+        VSIFree( pabyData );
+    }
+}
+
+
+/************************************************************************/
+/*                             IReadBlock()                             */
+/************************************************************************/
+
+CPLErr MEMTiledRasterBand::IReadBlock( int nBlockXOff,
+                                       int nBlockYOff,
+                                       void * pImage )
+
+{
+#if 0
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "MEMTiledRasterBand::IReadBlock DEBUG: entered..."
+         << "\nnBlockXSize:  " << nBlockXSize
+         << "\nnBlockYSize:  " << nBlockYSize
+         << "\nnBlockXOff:   " << nBlockXSize
+         << "\nnBlockYOff:   " << nBlockYSize
+         
+         << endl;
+   }
+#endif
+
+   if (!theDataset->theData)  // Check for a valid buffer.
+   {
+      return CE_None;
+   }
+
+   ossimIrect bufferRect = theDataset->theData->getImageRectangle();
+
+   ossimIpt ul(theDataset->theAreaOfInterest.ul().x + nBlockXOff*nBlockXSize,
+               theDataset->theAreaOfInterest.ul().y + nBlockYOff*nBlockYSize);
+
+   ossimIrect requestRect(ul.x,
+                          ul.y,
+                          ul.x + nBlockXSize - 1,
+                          ul.y + nBlockYSize - 1);
+#if 0
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "\nrequestRect:  " << requestRect
+         << "\nbufferRect:   " << bufferRect
+         << endl;
+   }
+#endif
+
+   if(requestRect.height() > 1)
+   {
+      ossimNotify(ossimNotifyLevel_WARN)
+         << "MEMTiledRasterBand::IReadBlock WARN!"
+         << "\nOnly one scanline block reads allowed" << endl;
+      return CE_None;
+   }
+
+   if(nBlockYOff==0)
+   {
+      theDataset->theInterface->setToStartOfSequence();
+   }
+
+   bool loadBuffer = false;
+   
+   if ( (requestRect.completely_within(bufferRect) == false)  ||
+        (theDataset->theData->getDataObjectStatus() == OSSIM_EMPTY) )
+   {
+      loadBuffer = true;
+   }
+
+#if 0
+   ossim_int32 scanlineTile = ((nBlockYOff*nBlockYSize)%theDataset->theTileSize.y);
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "\nscanlineTile: " << scanlineTile
+         << endl;
+   }
+#endif
+
+   if(loadBuffer)
+   {
+      theDataset->theData->makeBlank();
+      theDataset->theData->setOrigin(requestRect.ul());
+      // fill the tile with one row;
+      ossim_uint32 numberOfTiles = (ossim_uint32)theDataset->theInterface->getNumberOfTilesHorizontal();
+      for(ossim_uint32 i = 0; i < numberOfTiles; ++i)
+      {
+         ossimIpt tileOrigin(ul.x+theDataset->theTileSize.x*i, ul.y);
+#if 0
+         if (traceDebug())
+         {
+            ossimNotify(ossimNotifyLevel_DEBUG)
+               << "\ntileOrigin:  " << tileOrigin << endl;
+         }
+#endif
+         ossimRefPtr<ossimImageData> data =
+            theDataset->theInterface->getTile(
+               ossimIrect(tileOrigin.x,
+                          tileOrigin.y,
+                          tileOrigin.x + (theDataset->theTileSize.x - 1),
+                          tileOrigin.y + (theDataset->theTileSize.y - 1)));
+         if(data.valid())
+         {
+            if (data->getBuf())
+            {
+               theDataset->theData->loadTile(data.get());
+            }
+            else
+            {
+               // Hmmm???
+               ossimRefPtr<ossimImageData> tempData =
+                  (ossimImageData*)data->dup();
+               tempData->initialize();
+               theDataset->theData->loadTile(tempData.get());
+            }
+         }
+      }
+      theDataset->theData->validate();
+
+      // Capture the buffer rectangle.
+      bufferRect = theDataset->theData->getImageRectangle();
+   }
+
+#if 0
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "nBlockYOff:  " << nBlockYOff
+         << "\ntheDataset->theData->getImageRectangle()"
+         << theDataset->theData->getImageRectangle()
+         << endl;
+   }
+#endif
+   
+   // Bytes per pixel.
+   const ossim_int32 BPP = static_cast<ossim_int32>(
+      theDataset->theData->getScalarSizeInBytes());
+
+   if(theDataset->theData->getDataObjectStatus() == OSSIM_EMPTY)
+   {
+      copyNulls(pImage, nBlockYSize * nBlockXSize);
+   }
+   else 
+   {
+      int nWordSize = GDALGetDataTypeSize( eDataType ) / 8;
+      CPLAssert( nBlockXOff == 0 );
+
+      if( nPixelOffset == nWordSize )
+      {
+         ossim_uint32 offset = (ul.y - bufferRect.ul().y) *
+            bufferRect.width() * BPP +
+            (ul.x - bufferRect.ul().x) * BPP;
+
+         GByte *pabyCur = ((GByte*) (theDataset->theData->getBuf(nBand-1)))
+            + offset;
+
+         memcpy( pImage,
+                 pabyCur,
+                 nPixelOffset * nBlockXSize);
+      }
+      else
+      {
+         ossimNotify(ossimNotifyLevel_WARN)
+            << "MEMTiledRasterBand::IReadBlock WARN!"
+            << "\nUnhandled wordsize..."
+            << endl;
+#if 0
+         // shift to start of scanline
+         GByte *pabyCur = (GByte*) (theDataset->theData->getBuf(nBand-1))
+                          + (theDataset->theData->getScalarSizeInBytes()*
+                             theDataset->theData->getWidth()*scanlineTile);
+         
+         for( int iPixel = 0; iPixel < nBlockXSize; iPixel++ )
+         {
+            memcpy( (GByte *) pImage+ iPixel*nWordSize, 
+                    pabyCur + iPixel*nPixelOffset,
+                    nWordSize );
+         }
+#endif
+      }
+   }
+
+   return CE_None;
+}
+
+/************************************************************************/
+/*                            IWriteBlock()                             */
+/************************************************************************/
+
+CPLErr MEMTiledRasterBand::IWriteBlock( int /*nBlockXOff*/, int /*nBlockYOff*/,
+                                     void * /*pImage*/ )
+
+{
+//     int     nWordSize = GDALGetDataTypeSize( eDataType );
+//     CPLAssert( nBlockXOff == 0 );
+
+//     if( nPixelOffset*8 == nWordSize )
+//     {
+//         memcpy( pabyData+nLineOffset*nBlockYOff, 
+//                 pImage, 
+//                 nPixelOffset * nBlockXSize );
+//     }
+//     else
+//     {
+//         GByte *pabyCur = pabyData + nLineOffset*nBlockYOff;
+
+//         for( int iPixel = 0; iPixel < nBlockXSize; iPixel++ )
+//         {
+//             memcpy( pabyCur + iPixel*nPixelOffset, 
+//                     ((GByte *) pImage) + iPixel*nWordSize, 
+//                     nWordSize );
+//         }
+//     }
+
+    return CE_None;
+}
+
+/************************************************************************/
+/* ==================================================================== */
+/*      MEMTiledDataset                                                     */
+/* ==================================================================== */
+/************************************************************************/
+
+
+/************************************************************************/
+/*                            MEMTiledDataset()                             */
+/************************************************************************/
+
+MEMTiledDataset::MEMTiledDataset()
+   :
+   MEMDataset(),
+   theData(),
+   theInterface(NULL),
+   theTileSize(),
+   theAreaOfInterest(),
+   theJustCreatedFlag(false),
+   theSetNoDataValueFlag(true)
+{
+}
+
+MEMTiledDataset::MEMTiledDataset(ossimImageSourceSequencer* iface)
+   :
+   MEMDataset(),
+   theData(),
+   theInterface(iface),
+   theTileSize(),
+   theAreaOfInterest(),
+   theJustCreatedFlag(false),
+   theSetNoDataValueFlag(true)
+{
+   create(theInterface);
+}
+
+/************************************************************************/
+/*                            ~MEMTiledDataset()                            */
+/************************************************************************/
+
+MEMTiledDataset::~MEMTiledDataset()
+
+{
+    FlushCache();
+}
+
+/************************************************************************/
+/*                               Create()                               */
+/************************************************************************/
+void MEMTiledDataset::create(ossimImageSourceSequencer* iface)
+{
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "MEMTiledDataset::create DEBUG: entered..."
+         << endl;
+   }
+
+   theInterface = iface;
+   
+   if(theInterface)
+   {
+
+      ossimKeywordlist kwl;
+
+      GByte  	**papBandData;
+      int nBands = theInterface->getNumberOfOutputBands();
+      theData = ossimImageDataFactory::instance()->create(NULL, // no owner specified
+                                                          theInterface);
+      
+      GDALDataType gdalType = ossimGdalType().toGdal(theInterface->getOutputScalarType());
+      int         nWordSize = GDALGetDataTypeSize(gdalType) / 8;
+      int tw = theInterface->getTileWidth();
+      int th = theInterface->getTileHeight();
+      int band = 0;
+
+      papBandData = (GByte **) CPLCalloc(sizeof(void *),nBands);
+      
+      for( band = 0; band < nBands; band++ )
+      {
+         papBandData[band] = (GByte *) VSICalloc( nWordSize, tw * th );
+      }
+      
+      poDriver = poMEMTiledDriver;
+      ossimIrect bounds = theInterface->getBoundingRect();
+
+      theTileSize = ossimIpt(theInterface->getTileWidth(),
+                             theInterface->getTileHeight());
+      
+      nRasterXSize = bounds.width();
+      nRasterYSize = bounds.height();
+
+      if (traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG)
+            << "DEBUG:"
+            << "\nnRasterXSize" << nRasterXSize
+            << "\nnRasterYSize" << nRasterYSize
+            << endl;
+      }
+
+      eAccess      = GA_Update;
+      if(theData.valid())
+      {
+         theData->setWidth(nRasterXSize);
+         theData->setHeight(theTileSize.y);
+         theData->initialize();
+      }
+
+      if (traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG)
+            << "DEBUG:"
+            << "\ntheData:  " << *theData.get()
+            << endl;
+      }
+
+
+/* -------------------------------------------------------------------- */
+/*      Create band information objects.                                */
+/* -------------------------------------------------------------------- */
+
+      for( band = 0; band < nBands; band++ )
+      {
+       
+         MEMTiledRasterBand* rasterBand =
+            new MEMTiledRasterBand( this,
+                                    band+1,
+                                    papBandData[band],
+                                    gdalType,
+                                    0,
+                                    0,
+                                    TRUE );
+         rasterBand->theDataset = this;
+         if (theSetNoDataValueFlag)
+         {
+            rasterBand->SetNoDataValue(theInterface->getNullPixelValue(band));
+         }
+         SetBand( band+1, 
+                  rasterBand);
+      }
+
+      theJustCreatedFlag = true;
+      CPLFree( papBandData );
+
+      theAreaOfInterest = theInterface->getBoundingRect();
+/* -------------------------------------------------------------------- */
+/*      Try to return a regular handle on the file.                     */
+/* -------------------------------------------------------------------- */
+   }
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "MEMTiledDataset::create DEBUG: exited..."
+         << endl;
+   }
+
+}
+
+void MEMTiledDataset::setNoDataValueFlag(bool flag)
+{
+   theSetNoDataValueFlag = flag;
+}
+
+/************************************************************************/
+/*                          GDALRegister_MEM()                          */
+/************************************************************************/
+
+void GDALRegister_MEMTiled()
+
+{
+    GDALDriver	*poDriver;
+
+    if( poMEMTiledDriver == NULL )
+    {
+        poMEMTiledDriver = poDriver = new GDALDriver();
+        
+        poDriver->SetDescription( "MEM TILED" );
+        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
+                                   "In Memory Raster OSSIM tile bridge" );
+
+        poDriver->pfnOpen   = MEMDataset::Open;
+        poDriver->pfnCreate = MEMDataset::Create;
+
+        GetGDALDriverManager()->RegisterDriver( poDriver );
+    }
+}
+
+void MEMTiledRasterBand::copyNulls(void* pImage, int count) const
+{
+   if (theDataset && pImage)
+   {
+      if (theDataset->theData.valid())
+      {
+         switch (theDataset->theData->getScalarType())
+         {
+            case OSSIM_UINT8:
+            {
+               return copyNulls(pImage, count, ossim_uint8(0));
+            }
+            case OSSIM_SINT8:
+            {
+               return copyNulls(pImage, count, ossim_sint8(0));
+            }
+            
+            case OSSIM_UINT16:
+            case OSSIM_USHORT11:
+            {
+               return copyNulls(pImage, count, ossim_uint16(0));
+            }  
+            case OSSIM_SINT16:
+            {
+               return copyNulls(pImage, count, ossim_sint16(0));
+            }
+            
+            case OSSIM_UINT32:
+            {
+               return copyNulls(pImage, count, ossim_uint32(0));
+            }  
+            case OSSIM_SINT32:
+            {
+               return copyNulls(pImage, count, ossim_sint32(0));
+            }  
+            case OSSIM_FLOAT32:
+            case OSSIM_NORMALIZED_FLOAT:
+            {
+               return copyNulls(pImage, count, ossim_float32(0.0));
+            }
+            
+            case OSSIM_NORMALIZED_DOUBLE:
+            case OSSIM_FLOAT64:
+            {
+               return copyNulls(pImage, count, ossim_float64(0.0));
+            }  
+            case OSSIM_SCALAR_UNKNOWN:
+            default:
+            {
+               break;
+            }
+            
+         } // End of "switch (theDataset->theData->getScalarType())"
+         
+      } // End of "if (theDataset->theData.valid())"
+      
+   } // End of "if (theDataset && pImage)"
+}
+
+template <class T>
+void MEMTiledRasterBand::copyNulls(void* pImage,
+                                   int count,
+                                   T /* dummyTemplate */ ) const
+{
+   // All pointer checking performed by caller.
+   
+   T* p       = static_cast<T*>(pImage);
+   T  nullPix = static_cast<T>(theDataset->theData->getNullPix(0));
+
+   for (int i = 0; i < count; ++i)
+   {
+      p[i] = nullPix;
+   }
+}
+
diff --git a/ossim_plugins/gdal/ossimGdalTiledDataset.h b/ossim_plugins/gdal/ossimGdalTiledDataset.h
new file mode 100644
index 0000000..3499c31
--- /dev/null
+++ b/ossim_plugins/gdal/ossimGdalTiledDataset.h
@@ -0,0 +1,123 @@
+//*******************************************************************
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author:  Garrett Potts
+//
+//*******************************************************************
+//  $Id: ossimGdalTiledDataset.h 23664 2015-12-14 14:17:27Z dburken $
+#ifndef ossimGdalTiledDataset_HEADER
+#define ossimGdalTiledDataset_HEADER
+
+#include <gdal_priv.h>
+#include <memdataset.h>
+#include <ossim/vpfutil/set.h>
+#include <ossim/base/ossimRefPtr.h>
+#include <ossim/base/ossimListenerManager.h>
+#include <ossim/base/ossimIpt.h>
+#include <ossim/base/ossimIrect.h>
+
+class MEMTiledRasterBand;
+class ossimImageSourceSequencer;
+class ossimImageData;
+
+class CPL_DLL MEMTiledDataset : public MEMDataset,
+   public ossimListenerManager
+{
+private:
+   friend class MEMTiledRasterBand;
+
+   ossimRefPtr<ossimImageData> theData;
+   ossimImageSourceSequencer*  theInterface;
+   ossimIpt                    theTileSize;
+   ossimIrect                  theAreaOfInterest;
+   bool                        theJustCreatedFlag;
+
+   /**
+    * DRB - 20081020
+    * If true (default) the no data value will be set to null pixel
+    * value.
+    */
+   bool theSetNoDataValueFlag;
+   
+   void create(ossimImageSourceSequencer* iface);
+
+ 
+
+public:
+   MEMTiledDataset();
+   MEMTiledDataset(ossimImageSourceSequencer* iface);
+   ~MEMTiledDataset();
+
+   static GDALDataset *Create( const char * pszFilename,
+                               int nXSize, int nYSize, int nBands,
+                               GDALDataType eType, char ** papszParmList );
+
+   /**
+    * DRB - 20081020
+    * If true (default) the no data value will be set to null pixel
+    * value.
+    *
+    * The call to rasterBand->SetNoDataValue causes snow with some viewer
+    * with some data types.  Like J2K.  This can disable it.
+    *
+    * @param flag If true the call to rasterBand->SetNoDataValue will be
+    * performed.  If false it will be bypassed.
+    */
+   void setNoDataValueFlag(bool flag);
+};
+
+/************************************************************************/
+/*                            MEMRasterBand                             */
+/************************************************************************/
+
+class CPL_DLL MEMTiledRasterBand : public MEMRasterBand
+{
+protected:
+   
+   friend class MEMTiledDataset;
+   MEMTiledDataset* theDataset;
+   ossimImageSourceSequencer* theInterface;
+   
+public:
+
+   MEMTiledRasterBand( GDALDataset *poDS,
+                       int nBand,
+                       GByte *pabyData,
+                       GDALDataType eType,
+                       int nPixelOffset,
+                       int nLineOffset,
+                       int bAssumeOwnership );
+   
+    virtual        ~MEMTiledRasterBand();
+
+    // should override RasterIO eventually.
+    
+    virtual CPLErr IReadBlock( int, int, void * );
+    virtual CPLErr IWriteBlock( int, int, void * );
+
+private:
+
+    /**
+     * Copies null values to pImage.
+     * @param pImage Buffer to copy to.
+     * @param count pixels to null out.
+     */
+    void copyNulls(void* pImage, int count) const;
+    
+    /**
+     * Copies null values to pImage.
+     * @param pImage Buffer to copy to.
+     * @param count pixels to null out.
+     * @param dummyTemplate Dummy for scalar type.
+     */
+    template <class T> void copyNulls(void* pImage,
+                                      int count,
+                                      T dummyTemplate) const;
+    
+};
+
+#endif
+
diff --git a/ossim_plugins/gdal/ossimGdalType.cpp b/ossim_plugins/gdal/ossimGdalType.cpp
new file mode 100644
index 0000000..04bf08c
--- /dev/null
+++ b/ossim_plugins/gdal/ossimGdalType.cpp
@@ -0,0 +1,94 @@
+//------------------------------------------------------------------------
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author:  Garrett Potts
+//
+// $Id: ossimGdalType.cpp 23664 2015-12-14 14:17:27Z dburken $
+//------------------------------------------------------------------------
+
+#include "ossimGdalType.h"
+#include <ossim/base/ossimCommon.h>
+
+ossimScalarType ossimGdalType::toOssim(GDALDataType gdalType)const
+{
+   switch(gdalType)
+   {
+      case GDT_Byte:
+      {
+         return OSSIM_UCHAR;
+      }
+      case GDT_UInt16:
+      {
+         return OSSIM_USHORT16;
+      }
+      case GDT_Int16:
+      {
+         return OSSIM_SSHORT16;
+      }
+      case GDT_Int32:
+      {
+         ossim_int32 sizeType = GDALGetDataTypeSize(gdalType)/8;
+         if(sizeType == 2)
+         {
+            return OSSIM_SSHORT16;
+         }
+         break;
+      }
+      case GDT_Float32:
+      {
+         return OSSIM_FLOAT;
+         break;
+      }
+      case GDT_Float64:
+      {
+         return OSSIM_DOUBLE;
+         break;
+      }
+      default:
+         break;
+   }
+   
+   return OSSIM_SCALAR_UNKNOWN;
+}
+
+GDALDataType ossimGdalType::toGdal(ossimScalarType ossimType)const
+{
+   switch(ossimType)
+   {
+      case OSSIM_UCHAR:
+      {
+         return  GDT_Byte;
+      }
+      case OSSIM_USHORT11:
+      case OSSIM_USHORT16:
+      {
+         return  GDT_UInt16;
+      }
+      case OSSIM_SSHORT16:
+      {
+         return GDT_Int16;
+         break;
+      }
+      case OSSIM_FLOAT:
+      case OSSIM_NORMALIZED_FLOAT:
+      {
+         return GDT_Float32;
+      }
+      case OSSIM_DOUBLE:
+      case OSSIM_NORMALIZED_DOUBLE:
+      {
+         return GDT_Float64;
+      }
+      case OSSIM_SCALAR_UNKNOWN:
+      {
+         break;
+      }
+      default:
+         break;
+   }
+
+   return GDT_Unknown;
+}
+
diff --git a/ossim_plugins/gdal/ossimGdalType.h b/ossim_plugins/gdal/ossimGdalType.h
new file mode 100644
index 0000000..a4a0983
--- /dev/null
+++ b/ossim_plugins/gdal/ossimGdalType.h
@@ -0,0 +1,20 @@
+//------------------------------------------------------------------------
+// License:  See top level LICENSE.txt file.
+//
+// Author:  Garrett Potts
+//
+// $Id: ossimGdalType.h 11440 2007-07-30 12:35:26Z dburken $
+//------------------------------------------------------------------------
+#ifndef ossimGdalType_HEADER
+#define ossimGdalType_HEADER
+#include <ossim/base/ossimConstants.h>
+#include <gdal.h>
+
+class ossimGdalType
+{
+public:
+   ossimScalarType toOssim(GDALDataType gdalType)const;
+   GDALDataType    toGdal(ossimScalarType)const;
+};
+
+#endif
diff --git a/ossim_plugins/gdal/ossimGdalWriter.cpp b/ossim_plugins/gdal/ossimGdalWriter.cpp
new file mode 100644
index 0000000..172d3ee
--- /dev/null
+++ b/ossim_plugins/gdal/ossimGdalWriter.cpp
@@ -0,0 +1,1872 @@
+//*******************************************************************
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author:  Garrett Potts
+//
+//*******************************************************************
+//  $Id: ossimGdalWriter.cpp 23664 2015-12-14 14:17:27Z dburken $
+
+#include "ossimGdalWriter.h"
+#include "ossimOgcWktTranslator.h"
+#include "ossimGdalTiledDataset.h"
+#include <ossim/base/ossimBooleanProperty.h>
+#include <ossim/base/ossimKeywordNames.h>
+#include <ossim/base/ossimListener.h>
+#include <ossim/base/ossimNotify.h>
+#include <ossim/base/ossimNumericProperty.h>
+#include <ossim/base/ossimRefPtr.h>
+#include <ossim/base/ossimStringProperty.h>
+#include <ossim/base/ossimTrace.h>
+#include <ossim/base/ossimXmlAttribute.h>
+#include <ossim/base/ossimXmlNode.h>
+#include <ossim/imaging/ossimImageChain.h>
+#include <ossim/imaging/ossimImageGeometry.h>
+#include <ossim/imaging/ossimImageHandler.h>
+#include <ossim/projection/ossimMapProjection.h>
+#include <ossim/projection/ossimMapProjectionInfo.h>
+#include <ossim/projection/ossimProjectionFactoryRegistry.h>
+#include <ossim/vpfutil/set.h>
+#include <cmath>
+#include <iterator>
+#include <sstream>
+using namespace std;
+
+static int CPL_STDCALL gdalProgressFunc(double percentComplete,
+                            const char* msg,
+                            void* data)
+{
+   ossimGdalWriter* writer = (ossimGdalWriter*)data;
+   
+   ossimProcessProgressEvent event(writer,
+                                   percentComplete*100.0,
+                                   msg,
+                                   false);
+   
+   writer->fireEvent(event);
+   
+   return !writer->needsAborting();
+}
+
+static ossimTrace traceDebug(ossimString("ossimGdalWriter:debug"));
+
+RTTI_DEF1(ossimGdalWriter, "ossimGdalWriter", ossimImageFileWriter);
+
+static ossimOgcWktTranslator translator;
+
+ossimGdalWriter::ossimGdalWriter()
+   :ossimImageFileWriter(),
+    theDriverName(""),
+    theDriver((GDALDriverH)0),
+    theDataset((GDALDatasetH)0),
+    theJpeg2000TileSize(),
+    theDriverOptionValues(),
+    theGdalDriverOptions(0),
+    theGdalOverviewType(ossimGdalOverviewType_NONE),
+    theColorLutFlag(false),
+    theColorLut(0),
+    theLutFilename(),
+    theNBandToIndexFilter(0)
+{ 
+}
+
+ossimGdalWriter::~ossimGdalWriter()
+{
+   deleteGdalDriverOptions();
+   close();
+   theDataset = 0;
+   theDriverName = "";
+}
+
+bool ossimGdalWriter::isOpen()const
+{
+   return (theDriver != 0);
+}
+
+bool ossimGdalWriter::open()
+{
+   theDriverName = convertToDriverName(theOutputImageType);
+   theDriver = GDALGetDriverByName(theDriverName.c_str());
+
+   if(theDriver)
+   {
+      return true;
+   }
+
+   return false;
+}
+
+void ossimGdalWriter::close()
+{
+   if(theDataset)
+   {
+      GDALClose(theDataset);
+      theDataset = 0;
+   }
+}
+
+void  ossimGdalWriter::setOutputImageType(const ossimString& type)
+{
+   ossimImageFileWriter::setOutputImageType(type);
+   theDriverOptionValues.clear();
+}
+
+void ossimGdalWriter::setLut(const ossimNBandLutDataObject& lut)
+{
+  theColorLutFlag = true;
+  theColorLut = (ossimNBandLutDataObject*)lut.dup();
+}
+
+/*!
+ * saves the state of the object.
+ */
+bool ossimGdalWriter::saveState(ossimKeywordlist& kwl,
+                                const char* prefix)const
+{
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimGdalWriter::saveState entered ..."
+         << "\nprefix:         " << prefix << std::endl;
+   }
+
+   ossimString rrdOption = CPLGetConfigOption("HFA_USE_RRD","");
+   if(rrdOption != "")
+   {
+      kwl.add(prefix,
+              "HFA_USE_RRD",
+              rrdOption,
+              true);
+   }
+   kwl.add(prefix,
+           "gdal_overview_type",
+           gdalOverviewTypeToString(),
+           true);
+   kwl.add(prefix, theDriverOptionValues);
+
+   kwl.add(prefix,
+     "color_lut_flag",
+     (ossim_uint32)theColorLutFlag,
+     true);
+
+   if(theColorLutFlag)
+   {
+     if(theLutFilename != "")
+     {
+       kwl.add(prefix,
+         "lut_filename",
+         theLutFilename.c_str(),
+         true);
+     }
+     else
+     {
+        if ( theColorLut.valid() )
+        {
+           ossimString newPrefix = ossimString(prefix) + "lut.";
+           theColorLut->saveState(kwl, newPrefix.c_str());
+        }
+     }
+   }
+   
+   return ossimImageFileWriter::saveState(kwl, prefix);
+}
+
+/*!
+ * Method to the load (recreate) the state of an object from a keyword
+ * list.  Return true if ok or false on error.
+ */
+bool ossimGdalWriter::loadState(const ossimKeywordlist& kwl,
+                                const char* prefix)
+{
+   ossimImageFileWriter::loadState(kwl, prefix);
+
+   ossimString regExpression =  (ossimString("^") +
+                                 ossimString(prefix) +
+                                 "property[0-9]+");
+   const char* hfa_use_rrd = kwl.find(prefix, "HFA_USE_RRD");
+
+   if(hfa_use_rrd)
+   {
+      CPLSetConfigOption("HFA_USE_RRD", hfa_use_rrd);
+   }
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimGdalWriter::loadState entered ..."
+         << "\nprefix:         " << (prefix?prefix:"null")
+         << "\nregExpression:  " << regExpression
+         << "\nkwl:" << kwl << std::endl;
+   }
+   const char* overviewType = kwl.find(prefix, "gdal_overview_type");
+
+   if(overviewType)
+   {
+      theGdalOverviewType = gdalOverviewTypeFromString(ossimString(overviewType));
+   }
+
+   ossimString newPrefix = ossimString(prefix) + "lut.";
+
+   const char* colorLutFlag = kwl.find(prefix, "color_lut_flag");
+   if(colorLutFlag)
+   {
+     theColorLutFlag = ossimString(colorLutFlag).toBool();
+   }
+   else
+   {
+     theColorLutFlag = false;
+   }
+
+   theLutFilename = ossimFilename(kwl.find(prefix, "lut_filename"));
+   theLutFilename = ossimFilename(theLutFilename.trim());
+   if ( theColorLut.valid() == false ) theColorLut = new ossimNBandLutDataObject();
+   if(theLutFilename != "")
+   {
+     theColorLut->open(theLutFilename);
+   }
+   else
+   {
+     theColorLut->loadState(kwl, newPrefix.c_str());
+   }
+   
+   vector<ossimString> keys = kwl.getSubstringKeyList( regExpression );
+   theDriverOptionValues.clear();
+   
+   deleteGdalDriverOptions();
+
+   kwl.extractKeysThatMatch(theDriverOptionValues,
+                            regExpression);
+
+   if(prefix)
+   {
+      theDriverOptionValues.stripPrefixFromAll(prefix);
+   }
+   
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimGdalWriter::loadState exiting..." << std::endl;
+   }
+   return true;
+}
+
+void ossimGdalWriter::getSupportedWriters(vector<ossimString>& /* writers */)
+{
+}
+
+bool ossimGdalWriter::isLutEnabled()const
+{
+  return (theColorLutFlag);
+}
+
+void ossimGdalWriter::checkColorLut()
+{
+   bool needColorLut = false;
+   bool needLoop = true;
+   ossimRefPtr<ossimNBandLutDataObject> colorLut = 0;
+   ossimConnectableObject::ConnectableObjectList imageInputs = theInputConnection->getInputList();
+   if (imageInputs.size() > 0)
+   {
+      for (ossim_uint32 i = 0; i < imageInputs.size(); i++)
+      {
+         if (needLoop == false)
+         {
+            break;
+         }
+         ossimImageChain* source = PTR_CAST(ossimImageChain, imageInputs[i].get());
+         if (source)
+         {
+            ossimConnectableObject::ConnectableObjectList imageChains = source->getInputList();
+            for (ossim_uint32 j = 0; j < imageChains.size(); j++)
+            {
+               if (needLoop == false)
+               {
+                  break;
+               }
+               ossimImageChain* imageChain = PTR_CAST(ossimImageChain, imageChains[j].get());
+               if (imageChain)
+               {
+                  ossimConnectableObject::ConnectableObjectList imageHandlers =
+                     imageChain->findAllObjectsOfType(STATIC_TYPE_INFO(ossimImageHandler), false);
+
+                  for (ossim_uint32 h= 0; h < imageHandlers.size(); h++)
+                  {
+                     ossimImageHandler* handler =
+                        PTR_CAST(ossimImageHandler, imageHandlers[h].get());
+                     if (handler)
+                     {
+                        if (handler->hasLut() != 0) //
+                        {
+                           colorLut = handler->getLut();
+                           needColorLut = true;
+                        }
+                        else //if not all handlers have color luts, ignore the color lut.
+                        {
+                           needColorLut = false;
+                           needLoop = false;
+                           break;
+                        }
+                     }
+                  }
+               }
+            }
+         }
+      }
+   }
+
+   if (needColorLut && colorLut != 0)
+   {
+      setLut(*colorLut.get());
+   }
+}
+
+bool ossimGdalWriter::writeFile()
+{
+   bool result = true; // On failure set to false.
+   
+   const char *MODULE = "ossimGdalWriter::writeFile()";
+
+   if(traceDebug())
+   {
+      CLOG << "entered..." << std::endl;
+   }
+      
+   if(theDataset)
+   {
+      close();
+   }
+
+   checkColorLut();
+
+   //---
+   // If isInputDataIndexed is true the data fed to writer is already in palette index form so
+   // the addition of the ossimNBandToIndexFilter is not needed.
+   //---
+   if( isLutEnabled() && !isInputDataIndexed() )
+   {
+      theNBandToIndexFilter = new ossimNBandToIndexFilter;
+      theNBandToIndexFilter->connectMyInputTo(0, theInputConnection->getInput());
+      theNBandToIndexFilter->setLut(*theColorLut.get());
+      theNBandToIndexFilter->initialize();
+      theInputConnection->disconnect();
+      theInputConnection->connectMyInputTo(0, theNBandToIndexFilter.get());
+      theInputConnection->initialize();
+   }
+   else
+   {
+      theNBandToIndexFilter = 0;
+   }
+
+   //---
+   // setup gdal driver options
+   //---
+   ossimRefPtr<ossimProperty> blockSize =
+      getProperty(theDriverName+ossimString("_BLOCKSIZE"));
+   if(blockSize.valid())
+   {
+      ossim_uint32 size = blockSize->valueToString().toUInt32();
+      ossimIpt tileSize;
+      if(size > 0)
+      {
+         tileSize = ossimIpt(size, size);
+         theInputConnection->setTileSize(tileSize);
+      }
+      else
+      {
+         ossimIpt defaultSize = theInputConnection->getTileSize();
+         if(defaultSize.y != defaultSize.x)
+         {
+            defaultSize.y = defaultSize.x;
+            theInputConnection->setTileSize(defaultSize);
+         }
+         blockSize->setValue(ossimString::toString(defaultSize.x));
+         setProperty(blockSize);
+         theInputConnection->setTileSize(defaultSize);
+      }
+   }
+   allocateGdalDriverOptions();
+
+   if(!theInputConnection->isMaster()) // MPI slave process...
+   {
+      theInputConnection->slaveProcessTiles();
+      if(theNBandToIndexFilter.valid())
+      {
+        theInputConnection->connectMyInputTo(0, theNBandToIndexFilter->getInput());
+        theNBandToIndexFilter = 0;
+      }
+      result = true;
+   }
+   else // MPI master process.
+   {
+      open();
+      
+      if(isOpen())
+      {
+         GDALDataType gdalType = getGdalDataType(theInputConnection->
+                                                 getOutputScalarType());
+         ossim_uint32 bandCount = theInputConnection->getNumberOfOutputBands();
+				 
+         theDataset = GDALCreate( theDriver ,
+                                  theFilename.c_str(),
+                                  (int)theAreaOfInterest.width(),
+                                  (int)theAreaOfInterest.height(),
+                                  (int)bandCount,
+                                  gdalType,
+                                  theGdalDriverOptions);
+
+         // ESH 09/2009 -- If no raster bands do block write.
+         int nRasterBands = GDALGetRasterCount( theDataset );
+
+         if(theDataset && nRasterBands>0)
+         {
+            writeProjectionInfo(theDataset);
+
+            if (theColorLutFlag)
+            {
+              writeColorMap(nRasterBands);
+            }
+            
+            theInputConnection->setToStartOfSequence();
+            ossimRefPtr<ossimImageData> currentTile =
+               theInputConnection->getNextTile();
+            ossimRefPtr<ossimImageData> outputTile =
+               (ossimImageData*)currentTile->dup();
+            outputTile->initialize();
+
+            //---
+            // DRB 20081017
+            // Trac #404: Setting no data value for imagine (hfa) and j2k
+            // causing view issues with ArcMap and Erdas Imagine when null
+            // values are present in
+            // valid image data.
+            //---
+            if (theDriver)
+            {
+               ossimString driverName = GDALGetDriverShortName(theDriver);
+               if ( (driverName != "HFA") && (driverName != "JP2MrSID") && 
+                    (driverName != "JP2KAK") && (driverName != "JPEG2000") )
+               {
+                  for(ossim_uint32 band = 0;
+                      band < currentTile->getNumberOfBands();
+                      ++band)
+                  {
+                     GDALRasterBandH aBand =
+                        GDALGetRasterBand(theDataset, band+1);
+                     if(aBand)
+                     {
+                        GDALSetRasterNoDataValue(
+                           aBand, theInputConnection->getNullPixelValue(band));
+                     }
+                  }
+                  if(traceDebug())
+                  {
+                     ossimNotify(ossimNotifyLevel_DEBUG)
+                        << "GDALSetRasterNoDataValue called for driver: "
+                        << driverName << std::endl;
+                  }
+               }
+               else 
+               {
+                  if(traceDebug())
+                  {
+                     ossimNotify(ossimNotifyLevel_DEBUG)
+                        << "GDALSetRasterNoDataValue not called for driver: "
+                        << driverName << std::endl;
+                  }
+               }
+
+               // ESH 05/2009: Add min/max to gdal metadata
+               ossim_uint32 numberOfBands = currentTile->getNumberOfBands();
+               for( ossim_uint32 idx = 0; idx < numberOfBands; ++idx )
+               {
+                  GDALRasterBandH aBand =
+                     GDALGetRasterBand(theDataset, idx+1);
+                  if(aBand)
+                  {
+                     // GDAL always assumes "area".
+                     GDALSetMetadataItem( aBand, "AREA_OR_POINT", "Area", 0 );
+
+                     double minPix = (double)currentTile->getMinPix( idx );
+                     double maxPix = (double)currentTile->getMaxPix( idx );
+
+                     // Only set the metadata if the values makes some sense.
+                     if ( maxPix > 0.0 && minPix < maxPix )
+                     {
+                        char szValue[128];
+                        sprintf( szValue, "%.14g", minPix );
+                        GDALSetMetadataItem( aBand, "STATISTICS_MINIMUM", szValue, 0 );
+
+                        sprintf( szValue, "%.14g", maxPix );
+                        GDALSetMetadataItem( aBand, "STATISTICS_MAXIMUM", szValue, 0 );
+                     }
+                  }
+               }
+            }
+   
+            ossim_uint32 numberOfTiles =
+               (theInputConnection->getNumberOfTiles()*
+                theInputConnection->getNumberOfOutputBands());
+   
+            ossim_uint32 tileNumber = 0;
+            while(currentTile.valid()&&(!needsAborting()))
+            {
+               ossimIrect clipRect =
+                  currentTile->getImageRectangle().clipToRect(theAreaOfInterest);
+               outputTile->setImageRectangle(clipRect);
+               outputTile->loadTile(currentTile.get());
+               //ossimIpt offset = currentTile->getOrigin() -
+               //theAreaOfInterest.ul();
+               ossimIpt offset = clipRect.ul() - theAreaOfInterest.ul();
+      
+               for(ossim_uint32 band = 0;
+                   ((band < (currentTile->getNumberOfBands()))&&
+                    (!needsAborting()));
+                   ++band)
+               {
+                  GDALRasterBandH aBand=0;
+                  aBand = GDALGetRasterBand(theDataset, band+1);
+
+                  if(aBand)
+                  {
+                     GDALRasterIO( aBand,
+                        GF_Write,
+                        offset.x,
+                        offset.y,
+                        clipRect.width(),
+                        clipRect.height(),
+                        outputTile->getBuf(band),
+                        outputTile->getWidth(),
+                        outputTile->getHeight(),
+                        gdalType,
+                        0,
+                        0);
+                  }
+
+                  ++tileNumber;
+                  ossimProcessProgressEvent event(this,
+                                                  ((double)tileNumber/
+                                                   (double)numberOfTiles)*100.0,
+                                                  "",
+                                                  false);
+                  
+                  fireEvent(event);
+               }
+               currentTile = theInputConnection->getNextTile();
+               
+            }
+            
+            if(theDataset)
+            {
+               close();
+               if((theGdalOverviewType != ossimGdalOverviewType_NONE)&&
+                  (!needsAborting()))
+               {
+                  theDataset= GDALOpen( theFilename.c_str(), GA_Update );
+                  
+                  if( theDataset == 0 )
+                  {
+                     theDataset = GDALOpen( theFilename.c_str(), GA_ReadOnly );
+                  }
+                  buildGdalOverviews();
+                  close();
+               }
+            }
+            else
+            {
+               ossimNotify(ossimNotifyLevel_WARN)
+                  << "ossimGdalWriter::writeFile unable to create dataset"
+                  << std::endl;
+               result = false;
+            }
+            
+         } // End of "if (theDataset)"
+         else
+         {
+            result = writeBlockFile();
+         }
+         
+      } 
+      else // open failed...
+      {
+         result = false;
+         if(traceDebug())
+         {
+            CLOG << "Unable to open file for writing. Exiting ..."
+                 << std::endl;
+         }
+      }
+
+      if (result)
+      {
+         // Clean up files...
+         postProcessOutput();
+      }
+
+   } // End of "else // MPI master process."
+
+   if(theNBandToIndexFilter.valid())
+   {
+     theInputConnection->connectMyInputTo(0, theNBandToIndexFilter->getInput());
+     theNBandToIndexFilter = 0;
+   }
+
+   return result;
+   
+} // End of: ossimGdalWriter::writeFile
+
+bool ossimGdalWriter::writeBlockFile()
+{
+   theInputConnection->setAreaOfInterest(theAreaOfInterest);
+   theInputConnection->setToStartOfSequence();
+   
+   MEMTiledDataset* tiledDataset = new MEMTiledDataset(theInputConnection.get());
+
+   //---
+   // DRB 20081017
+   // Trac #404: Setting no data value for imagine (hfa) and j2k causing view
+   // issues with ArcMap and Erdas Imagine when null values are present in
+   // valid image data.
+   //---
+   if (theDriver)
+   {
+      ossimString driverName = GDALGetDriverShortName(theDriver);
+      if ( (driverName == "HFA") || (driverName == "JP2MrSID") || 
+           (driverName == "JP2KAK") || (driverName == "JPEG2000") )
+      {
+         tiledDataset->setNoDataValueFlag(false);
+      }
+   }
+
+   ossimString driverName="null";
+   if (theDriver)
+   {
+      driverName = GDALGetDriverShortName(theDriver);
+   }
+
+   writeProjectionInfo(tiledDataset);
+   theDataset = GDALCreateCopy( theDriver,
+                                theFilename.c_str(),
+                                tiledDataset ,
+                                true,
+                                theGdalDriverOptions,
+                                (GDALProgressFunc)&gdalProgressFunc,
+                                this);
+   
+   if(theDataset&&!needsAborting())
+   {
+      if(theGdalOverviewType != ossimGdalOverviewType_NONE)
+      {
+         buildGdalOverviews();
+      }
+      close();
+   }
+   else
+   {
+      if(traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG) << "ossimGdalWriter::writeBlockFile(): Unable to create dataset for file " << theFilename << std::endl;
+      }
+      return false;
+   }
+   // Trac #299: Ingest tasks are failing when generating png thumbnails
+   // ESH 08/2008: Added in a NULL check on theDataset, since GDALGetDriverShortName 
+   // crashes the app if given a NULL pointer.
+   if( theDataset && ossimString(GDALGetDriverShortName(theDataset)) == ossimString("PNG") )
+   {
+      setWriteExternalGeometryFlag(true);
+   }
+
+   return true;
+}
+
+void ossimGdalWriter::writeColorMap(int bands)
+{
+   if ( theDataset && theColorLut.valid() )
+   {
+      bool hasAlpha = (theColorLut->getNumberOfBands() == 4);
+
+      for (int band = 0; band < bands; band++)
+      {
+         GDALRasterBandH aBand=0;
+         aBand = GDALGetRasterBand(theDataset, band+1);
+         if(aBand)
+         {
+            bool hasEntryLabel = false;
+            ossim_uint32 entryNum = theColorLut->getNumberOfEntries();
+            std::vector<ossimString> entryLabels = theColorLut->getEntryLabels(band);
+            if (entryLabels.size() == entryNum)
+            {
+               hasEntryLabel = true;
+            }
+            
+            GDALColorTable* gdalColorTable = new GDALColorTable();
+            for(ossim_uint32 entryIndex = 0; entryIndex < entryNum; entryIndex++)
+            {
+               GDALColorEntry colorEntry;
+               colorEntry.c1 = (*theColorLut)[entryIndex][0];
+               colorEntry.c2 = (*theColorLut)[entryIndex][1];
+               colorEntry.c3 = (*theColorLut)[entryIndex][2];
+               colorEntry.c4 = hasAlpha ? (*theColorLut)[entryIndex][3] : 255;
+#if 0
+               if (hasEntryLabel)
+               {
+                  char* labelName = const_cast<char*>(entryLabels[entryIndex].c_str());
+                  colorEntry.poLabel = labelName;
+               }
+               else
+               {
+                  colorEntry.poLabel = NULL;
+               }
+#endif
+               
+               gdalColorTable->SetColorEntry(entryIndex, &colorEntry);
+            }
+            
+            GDALSetRasterColorTable(aBand, gdalColorTable);
+            delete gdalColorTable;
+         }
+      }
+   }
+}
+
+void ossimGdalWriter::writeProjectionInfo(GDALDatasetH dataset)
+{
+   // Get current input geometry
+   ossimRefPtr<ossimImageGeometry> geom = theInputConnection->getImageGeometry();
+   if(geom.valid())
+   {
+      const ossimMapProjection* mapProj =
+         PTR_CAST(ossimMapProjection, geom->getProjection());
+
+      if (mapProj)
+      {
+         ossim_uint32 pcs_code = mapProj->getPcsCode();
+         if (pcs_code == 0)
+            pcs_code = 32767;
+
+         double geoTransform[6] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
+
+         ossimDpt tiePoint;
+         ossimDpt scale;
+         if (mapProj->isGeographic())
+         {
+            // Get the ground tie point.
+            ossimGpt gpt;
+            mapProj->lineSampleToWorld(theAreaOfInterest.ul(), gpt);
+            tiePoint = gpt;
+
+            // Get the scale.
+            scale.x =  mapProj->getDecimalDegreesPerPixel().x;
+            scale.y = -mapProj->getDecimalDegreesPerPixel().y;
+         }
+         else
+         {
+            // Get the easting northing tie point.
+            mapProj->lineSampleToEastingNorthing(theAreaOfInterest.ul(),
+                                                 tiePoint);
+
+            // Get the scale.
+            scale.x =  mapProj->getMetersPerPixel().x;
+            scale.y = -mapProj->getMetersPerPixel().y;
+         }
+         
+         geoTransform[1] = scale.x;
+         geoTransform[5] = scale.y;
+         geoTransform[0] = tiePoint.x;
+         geoTransform[3] = tiePoint.y;
+
+         //---
+         // Since OSSIM is pixel_is_point, shift the tie point by
+         // half a pixel since GDAL output is pixel_is_area.
+         //---
+         geoTransform[0] -= fabs(scale.x) / 2.0;
+         geoTransform[3] += fabs(scale.y) / 2.0;
+
+         // Translate projection information to GDAL settable WKT
+         ossimString wktString = "";
+         if( mapProj->getProjectionName() == ossimString("ossimBngProjection") )
+         {
+            wktString = "PROJCS[\"OSGB 1936 / British National Grid\",GEOGCS[\"OSGB 1936\","
+               "DATUM[\"OSGB_1936\",SPHEROID[\"Airy 1830\",6377563.396,299.3249646]],PRIMEM[\""
+               "Greenwich\",0],UNIT[\"degree\",0.0174532925199433]],PROJECTION[\"Transverse_Mercator\"],"
+               "PARAMETER[\"latitude_of_origin\",49],PARAMETER[\"central_meridian\",-2],PARAMETER[\""
+               "scale_factor\",0.999601272],PARAMETER[\"false_easting\",400000],PARAMETER[\"false_"
+               "northing\",-100000],UNIT[\"meter\",1]]";
+         }
+         else if (mapProj->getProjectionName() == ossimString("ossimAlbersProjection") )
+         {
+            wktString = "PROJCS[\"Albers Conical Equal Area\",GEOGCS[\"NAD83\",DATUM[\"North_American_Datum_1983\","
+               "SPHEROID[\"GRS 1980\",6378137,298.257222101,AUTHORITY[\"EPSG\",\"7019\"]],"
+               "TOWGS84[0,0,0,0,0,0,0],AUTHORITY[\"EPSG\",\"6269\"]],PRIMEM[\"Greenwich\",0,"
+               "AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9108\"]],"
+               "AUTHORITY[\"EPSG\",\"4269\"]],PROJECTION[\"Albers_Conic_Equal_Area\"],PARAMETER[\"standard_parallel_1\",29.5],"
+               "PARAMETER[\"standard_parallel_2\",45.5],PARAMETER[\"latitude_of_center\",23],PARAMETER[\"longitude_of_center\",-96],"
+               "PARAMETER[\"false_easting\",0],PARAMETER[\"false_northing\",0],UNIT[\"meters\",1]]";
+         }
+         else
+         {
+            ossimKeywordlist kwl;
+            mapProj->saveState(kwl);
+            wktString = translator.fromOssimKwl(kwl);
+         }
+
+         // Set GDAL projection and corner coordinates.
+         GDALSetProjection(dataset, wktString.c_str());
+         GDALSetGeoTransform(dataset, geoTransform);
+
+      } // matches: if (mapProj)
+
+   } // matches: if(geom.valid())
+}
+
+void ossimGdalWriter::setOptions(ossimKeywordlist& /* kwl */,
+                                 const char* prefix)
+{
+   ossimString regExpression = ossimString("^(") +
+                               ossimString(prefix) +
+                               "option[0-9]+.)";
+
+//    while(numberOfMatches < static_cast<unsigned long>(numberOfSources))
+//    {
+//       ossimString newPrefix = prefix;
+//       newPrefix += ossimString("option");
+//       newPrefix += ossimString::toString(i);
+//       newPrefix += ossimString(".");
+
+//       const char* name  = kwl.find(newPrefix.c_str(), "name");
+//       const char* value = kwl.find(newPrefix.c_str(), "value");
+
+//       if(ossimString(name) == "tilewidth")
+//       {
+//          theJpeg2000TileSize.x = ossimString(value).toInt();
+//       }
+//       else if(ossimString(name) == "tileheight")
+//       {
+//          theJpeg2000TileSize.y = ossimString(value).toInt();
+//       }
+//    }
+
+}
+
+
+GDALDataType ossimGdalWriter::getGdalDataType(ossimScalarType scalar)
+{
+   GDALDataType dataType = GDT_Unknown;
+   
+   switch(scalar)
+   {
+      case OSSIM_UCHAR:
+      {
+         dataType = GDT_Byte;
+         break;
+      }
+      case OSSIM_USHORT11:
+      case OSSIM_USHORT16:
+      {
+         dataType = GDT_UInt16;
+         break;
+      }
+      case OSSIM_SSHORT16:
+      {
+         dataType = GDT_Int16;
+         break;
+      }
+      case OSSIM_FLOAT:
+      case OSSIM_NORMALIZED_FLOAT:
+      {
+         dataType = GDT_Float32;
+         break;
+      }
+      case OSSIM_DOUBLE:
+      case OSSIM_NORMALIZED_DOUBLE:
+      {
+         dataType = GDT_Float64;
+         break;
+      }
+      default:
+         break;
+   }
+
+   return dataType;
+}
+
+void ossimGdalWriter::allocateGdalDriverOptions()
+{
+   deleteGdalDriverOptions();
+   ossimString regExpression =  (ossimString("^")+
+                                 "property[0-9]+");
+   vector<ossimString> keys = theDriverOptionValues.getSubstringKeyList( regExpression );
+
+   if(keys.size())
+   {
+      ossim_uint32 i = 0;
+      theGdalDriverOptions = new char*[keys.size()+1];
+      for(i = 0 ; i < keys.size(); ++i)
+      {
+         ossimString name    = theDriverOptionValues.find(keys[i] +".name");
+         ossimString value   = theDriverOptionValues.find(keys[i] +".value");
+
+         //---
+         // Special hack...
+         // 
+         // Lossless compression for non 8 bit data not supported for kakadu.
+         //---
+         if (theInputConnection.valid() && (GDALGetDriverByName("JP2KAK")) && (name == "QUALITY"))
+         {
+            if (theInputConnection->getOutputScalarType() != OSSIM_UINT8)
+            {
+               double d = value.toDouble();
+               if (d >= 99.5)
+               {
+                  if (traceDebug())
+                  {
+                     ossimNotify(ossimNotifyLevel_DEBUG)
+                        << "DEBUG:"
+                        << "\nLossless quality not valid for non 8 bit data"
+                        << "\nResetting to 99.0"
+                        << std::endl;
+                  }
+
+                  value = "99.0";
+               }
+            }
+         }
+
+         // ESH 01/2009 -- For HFA handling of SRS's that come from pcs codes:
+         // use new option in HFA driver (gdal-1.6.0). This option forces the
+         // coordinate system tags to be more compatible with ArcGIS. We might 
+         // have to add in a check for the pcs code here if that is possible.
+         //---
+         // Special hack...
+         //---
+         if ( (GDALGetDriverByName("HFA")) &&
+              (name == "FORCETOPESTRING") )
+         {
+            value = "TRUE";
+         }
+
+         ossimString combine = name + "=" + value;
+         
+         theGdalDriverOptions[i] = new char[combine.size() + 1];
+		   strcpy(theGdalDriverOptions[i], combine.c_str());
+         
+         if (traceDebug())
+         {
+            ossimNotify(ossimNotifyLevel_DEBUG)
+               << "\nkey:  " << keys[i]
+               << "\nname:  " << name
+               << "\nvalue: " << value
+               << "\ngdal option:  " << combine
+               << std::endl;
+         }
+      }
+      theGdalDriverOptions[keys.size()] = 0;
+   }
+}
+
+void ossimGdalWriter::appendGdalOption(const ossimString& name,
+                                       const ossimString& value,
+                                       bool replaceFlag)
+{
+   ossimString regExpression =  (ossimString("^")+
+                                 "property[0-9]+");
+   vector<ossimString> keys = theDriverOptionValues.getSubstringKeyList( regExpression );
+   if(keys.size())
+   {
+      ossim_uint32 i = 0;
+      for(i = 0 ; i < keys.size(); ++i)
+      {
+         ossimString tempName    = theDriverOptionValues.find(keys[i] +".name");
+         if(tempName == name)
+         {
+            if(replaceFlag)
+            {
+               theDriverOptionValues.add(keys[i]+".value",
+                                         value,
+                                         true);
+            }
+            
+            return;
+         }
+      }
+   }
+   ossimString prefix = "property" + ossimString::toString((ossim_uint32)keys.size()) + ".";
+   
+   theDriverOptionValues.add(prefix,
+                             "name",
+                             name,
+                             true);
+   theDriverOptionValues.add(prefix,
+                             "value",
+                             value,
+                             true);
+}
+
+void ossimGdalWriter::deleteGdalDriverOptions()
+{
+   int i = 0;
+
+   if(theGdalDriverOptions)
+   {
+      char* currentOption = theGdalDriverOptions[i];
+
+      while(currentOption)
+      {
+         ++i;
+         delete [] currentOption;
+         currentOption = theGdalDriverOptions[i];
+      }
+      delete [] theGdalDriverOptions;
+      theGdalDriverOptions = 0;
+   }
+}
+
+ossimString ossimGdalWriter::convertToDriverName(const ossimString& imageTypeName)const
+{
+   ossimString strippedName = imageTypeName;
+   strippedName = strippedName.substitute("gdal_", "");
+   if(GDALGetDriverByName(strippedName.c_str()))
+   {
+      return strippedName;
+   }
+
+   // check for mime types
+   //
+   if(imageTypeName == "image/jp2")
+   {
+      if(GDALGetDriverByName("JP2KAK"))
+      {
+         return "JP2KAK";
+      }
+      else if(GDALGetDriverByName("JPEG2000"))
+      {
+         return "JPEG2000";
+      }
+      else if(GDALGetDriverByName("JP2MrSID"))
+      {
+         return "JP2MrSID";
+      }
+   }
+   if(imageTypeName == "image/png")
+   {
+      return "PNG";
+   }
+   if(imageTypeName == "image/wbmp")
+   {
+	   return "BMP";
+   }
+   if(imageTypeName == "image/bmp")
+   {
+	   return "BMP";
+   }
+   if(imageTypeName == "image/jpeg")
+   {
+      return "JPEG";
+   }
+   if(imageTypeName == "image/gif")
+   {
+      return "GIF";
+   }
+   
+
+   // keep these for backward compatibility
+   //
+   if( imageTypeName == "gdal_imagine_hfa")
+   {
+      return "HFA";
+   }
+   if(imageTypeName == "gdal_nitf_rgb_band_separate")
+   {
+      return "NITF";
+   }
+   if(imageTypeName == "gdal_jpeg2000")
+   {
+      if(GDALGetDriverByName("JP2KAK"))
+      {
+         return "JP2KAK";
+      }
+      else if(GDALGetDriverByName("JPEG2000"))
+      {
+         return "JPEG2000";
+      }
+      else if(GDALGetDriverByName("JP2MrSID"))
+      {
+         return "JP2MrSID";
+      }
+   }                                       
+   if(imageTypeName == "gdal_arc_info_aig")
+   {
+      return "AIG";
+   }
+   if(imageTypeName == "gdal_arc_info_gio")
+   {
+      return "GIO";
+   }
+   if(imageTypeName == "gdal_arc_info_ascii_grid")
+   {
+      return "AAIGrid";
+   }
+   if(imageTypeName == "gdal_mrsid")
+   {
+      return "MrSID";
+   }
+   if(imageTypeName == "gdal_jp2mrsid")
+   {
+      return "JP2MrSID";
+   }
+   if(imageTypeName == "gdal_png")
+   {
+      return "PNG";
+   }
+   if(imageTypeName == "gdal_jpeg")
+   {
+      return "JPEG";
+   }
+      
+   if(imageTypeName == "gdal_gif")
+   {
+      return "GIF";
+   }
+   if(imageTypeName == "gdal_dted")
+   {
+      return "DTED";
+   }
+   if(imageTypeName == "gdal_usgsdem")
+   {
+      return "USGSDEM";
+   }
+   if(imageTypeName == "gdal_bmp")
+   {
+      return "BMP";
+   }
+   if(imageTypeName == "gdal_raw_envi")
+   {
+      return "ENVI";
+   }
+   if(imageTypeName == "gdal_raw_esri")
+   {
+      return "EHdr";
+   }
+   if(imageTypeName == "gdal_raw_pci")
+   {
+      return "PAux";
+   }
+   if(imageTypeName == "gdal_pcidsk")
+   {
+      return "PCIDSK";
+   }
+   if(imageTypeName == "gdal_sdts")
+   {
+      return "SDTS";
+   }
+   if(imageTypeName == "gdal_jp2ecw")
+   {
+      return "JP2ECW";
+   }
+   if(imageTypeName == "gdal_ecw")
+   {
+      return "ECW";
+   }
+   return imageTypeName;
+}
+
+void ossimGdalWriter::getImageTypeList(std::vector<ossimString>& imageTypeList)const
+{
+   int driverCount = GDALGetDriverCount();
+   int idx = 0;
+
+   for(idx = 0; idx < driverCount; ++idx)
+   {
+      GDALDriverH driver =  GDALGetDriver(idx);
+
+      
+      if(driver)
+      {
+         const char* metaData = GDALGetMetadataItem(driver, GDAL_DCAP_CREATE, 0);
+         if(metaData)
+         {
+            imageTypeList.push_back("gdal_" + ossimString(GDALGetDriverShortName(driver)));
+         }
+         else
+         {
+            metaData = GDALGetMetadataItem(driver, GDAL_DCAP_CREATECOPY, 0);
+            if(metaData)
+            {
+               imageTypeList.push_back("gdal_" + ossimString(GDALGetDriverShortName(driver)));
+            }
+         }
+      }
+   }
+}
+
+bool ossimGdalWriter::hasImageType(const ossimString& imageType) const
+{
+   // check for non standard image types found in the
+   // getImageTypeList
+   //
+   if((imageType == "gdal_imagine_hfa") ||
+      (imageType == "gdal_nitf_rgb_band_separate") ||
+      (imageType == "gdal_jpeg2000") ||
+      (imageType == "gdal_jp2ecw") ||
+      (imageType == "gdal_arc_info_aig") ||
+      (imageType == "gdal_arc_info_gio") ||
+      (imageType == "gdal_arc_info_ascii_grid") ||
+      (imageType == "gdal_mrsid") ||
+      (imageType == "image/mrsid") ||
+      (imageType == "gdal_jp2mrsid") ||
+      (imageType == "image/jp2mrsid") ||
+      (imageType == "gdal_png") ||
+      (imageType == "image/png") ||
+      (imageType == "image/bmp") ||
+      (imageType == "image/wbmp") ||
+      (imageType == "gdal_jpeg") ||
+      (imageType == "image/jpeg") ||
+      (imageType == "gdal_gif") ||
+      (imageType == "image/gif") ||
+      (imageType == "gdal_dted") ||
+      (imageType == "image/dted") ||
+      (imageType == "gdal_bmp") ||
+      (imageType == "gdal_xpm") ||
+      (imageType == "image/x-xpixmap") ||
+      (imageType == "gdal_raw_envi") ||
+      (imageType == "gdal_raw_esri") ||
+      (imageType == "gdal_raw_esri") ||
+      (imageType == "gdal_pcidsk") ||
+      (imageType == "gdal_sdts"))
+   {
+      return true;
+   }
+   
+   return ossimImageFileWriter::hasImageType(imageType);
+}
+
+ossimString ossimGdalWriter::getExtension() const
+{
+   ossimString result;
+   
+   ossimString driverName = convertToDriverName(theOutputImageType);
+   GDALDriverH driver =  GDALGetDriverByName(driverName.c_str());
+   
+   if(driver)
+   {
+      result  = ossimString(GDALGetMetadataItem(driver, GDAL_DMD_EXTENSION, 0));
+      std::vector<ossimString> splitString;
+      result.split(splitString, "/");
+      if(!splitString.empty()) result = splitString[0];
+   }   
+   return result;
+   
+   //  we now use the metadata interface to get access to a drivers default file extension
+#if 0
+   ossimString imgTypeStr(theOutputImageType);
+   imgTypeStr.downcase();
+
+   // mime types
+   if(imgTypeStr == "image/jp2")
+   {
+      return ossimString("jp2");
+   }
+   if(imgTypeStr == "image/png")
+   {
+      return ossimString("png");
+   }
+   if(imgTypeStr == "image/wbmp")
+   {
+      return ossimString("bmp");
+   }
+   if(imgTypeStr == "image/bmp")
+   {
+      return ossimString("bmp");
+   }
+   if(imgTypeStr == "image/jpeg")
+   {
+      return ossimString("jpg");
+   }
+   if(imgTypeStr == "image/gif")
+   {
+      return ossimString("gif");
+   }
+
+
+   // keep these for backward compatibility
+   //
+   if( imgTypeStr == "gdal_imagine_hfa")
+   {
+      return ossimString("hfa");
+   }
+   if(imgTypeStr == "gdal_nitf_rgb_band_separate")
+   {
+      return ossimString("ntf");
+   }
+   if(imgTypeStr == "gdal_jpeg2000")
+   {
+      return ossimString("jp2");
+   }                                       
+   if(imgTypeStr == "gdal_arc_info_aig")
+   {
+      return ossimString("aig");
+   }
+   if(imgTypeStr == "gdal_arc_info_gio")
+   {
+      return ossimString("gio");
+   }
+   if(imgTypeStr == "gdal_arc_info_ascii_grid")
+   {
+      return ossimString("aig");
+   }
+   if(imgTypeStr == "gdal_mrsid")
+   {
+      return ossimString("sid");
+   }
+   if(imgTypeStr == "gdal_jp2mrsid")
+   {
+      return ossimString("jp2");
+   }
+   if(imgTypeStr == "gdal_png")
+   {
+      return ossimString("png");
+   }
+   if(imgTypeStr == "gdal_jpeg")
+   {
+      return ossimString("jpg");
+   }
+
+   if(imgTypeStr == "gdal_gif")
+   {
+      return ossimString("gif");
+   }
+   if(imgTypeStr == "gdal_dted")
+   {
+      return ossimString("dte");
+   }
+   if(imgTypeStr == "gdal_usgsdem")
+   {
+      return ossimString("dem");
+   }
+   if(imgTypeStr == "gdal_bmp")
+   {
+      return ossimString("bmp");
+   }
+   if(imgTypeStr == "gdal_raw_envi")
+   {
+      return ossimString("raw");
+   }
+   if(imgTypeStr == "gdal_raw_esri")
+   {
+      return ossimString("raw");
+   }
+   if(imgTypeStr == "gdal_raw_pci")
+   {
+      return ossimString("raw");
+   }
+   if(imgTypeStr == "gdal_pcidsk")
+   {
+      return ossimString("pix");
+   }
+   if(imgTypeStr == "gdal_sdts")
+   {
+      return ossimString("sdt");
+   }
+   if(imgTypeStr == "gdal_jp2ecw")
+   {
+      return ossimString("jp2");
+   }
+   if(imgTypeStr == "gdal_ecw")
+   {
+      return ossimString("ecw");
+   }
+   return ossimString("ext");
+#endif
+}
+
+void ossimGdalWriter::setProperty(ossimRefPtr<ossimProperty> property)
+{
+   if(!property.valid()) return;
+	 ossimString propName = property->getName();
+   if(!validProperty(property->getName()))
+   {
+      if(property->getName() == "image_type")
+      {
+         theDriverOptionValues.clear();
+      }
+      ossimImageFileWriter::setProperty(property);
+      return;
+   }
+
+   ossimString driverName = convertToDriverName(theOutputImageType);
+   ossimString name = property->getName();
+
+   if(name == "HFA_USE_RRD")
+   {
+      bool value = property->valueToString().toBool();
+      CPLSetConfigOption("HFA_USE_RRD", value?"YES":"NO");
+   }
+   else if(name == "gdal_overview_type")
+   {
+      theGdalOverviewType = gdalOverviewTypeFromString(property->valueToString());
+   }
+   else if (name == "format")
+   {
+      storeProperty(name,
+                    property->valueToString());
+   }
+   else if(name == "lut_file")
+   {
+     theLutFilename = ossimFilename(property->valueToString());
+     theColorLut->open(theLutFilename);
+   }
+   else if(name == "color_lut_flag")
+   {
+     theColorLutFlag = property->valueToString().toBool();
+   }
+   else
+   {
+      name = name.substitute(driverName+"_","");
+      storeProperty(name,
+                    property->valueToString());
+   }
+}
+
+ossimRefPtr<ossimProperty> ossimGdalWriter::getProperty(const ossimString& name)const
+{
+
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG) << "ossimGdalWriter::getProperty: entered..." << std::endl;
+   }
+
+   if(!validProperty(name))
+   {
+      return ossimImageFileWriter::getProperty(name);
+   }
+
+   if(name == "HFA_USE_RRD")
+   {
+      return  new ossimBooleanProperty(name, ossimString(CPLGetConfigOption(name.c_str(),"NO")).toBool());
+   }
+   else if(name == "gdal_overview_type")
+   {
+      ossimStringProperty* prop =  new ossimStringProperty(name, gdalOverviewTypeToString(), false);
+
+      prop->addConstraint("none");
+      prop->addConstraint("nearest");
+      prop->addConstraint("average");
+      
+      return prop;
+   }
+   const ossimRefPtr<ossimXmlNode>  node = getGdalOptions();
+   ossimString driverName = convertToDriverName(theOutputImageType);
+   GDALDriverH driver =  GDALGetDriverByName(driverName.c_str());
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG) << "Driver name = " << driverName << "\n"
+                                          << "name        = " << name << std::endl;
+   }
+
+   bool storedValueFlag=false;
+   ossimString storedValue;
+
+   if(node.valid()&&driver&&name.contains(driverName))
+   {
+      ossimString storedName = name;
+      storedName = storedName.substitute(driverName+"_","");
+      storedValueFlag = getStoredPropertyValue(storedName,
+                                               storedValue);
+      vector<ossimRefPtr<ossimXmlNode> > nodelist;
+      node->findChildNodes("Option", nodelist);
+      ossim_uint32 idx = 0;
+      for(idx = 0; idx < nodelist.size(); ++idx)
+      {
+         ossimRefPtr<ossimXmlAttribute> nameAttribute = nodelist[idx]->findAttribute("name");
+         if(nameAttribute.valid())
+         {
+            if((driverName+"_"+nameAttribute->getValue())== name)
+            {
+               ossimRefPtr<ossimXmlAttribute> type = nodelist[idx]->findAttribute("type");
+               
+               vector<ossimRefPtr<ossimXmlNode> > valuelist;
+               
+               if(type.valid())
+               {
+                  ossimRefPtr<ossimXmlAttribute> descriptionAttribute = nodelist[idx]->findAttribute("description");
+                  nodelist[idx]->findChildNodes("Value",
+                                       valuelist);
+                  ossimString description;
+                  ossimString typeValue = type->getValue();
+                  typeValue = typeValue.downcase();
+
+                  if(descriptionAttribute.valid())
+                  {
+                     description = descriptionAttribute->getValue();
+                  }
+                  if((typeValue == "int")||
+                     (typeValue == "integer"))
+                  {
+                     ossimNumericProperty* prop = new ossimNumericProperty(name,
+                                                                           storedValue);
+                     prop->setNumericType(ossimNumericProperty::ossimNumericPropertyType_INT);
+                     prop->setDescription(description);
+                     return prop;
+                  }
+                  else if(typeValue == "unsigned int")
+                  {
+                     ossimNumericProperty* prop = new ossimNumericProperty(name,
+                                                                           storedValue);
+                     prop->setNumericType(ossimNumericProperty::ossimNumericPropertyType_UINT);
+                     prop->setDescription(description);
+                     return prop;
+                  }
+                  else if(typeValue == "float")
+                  {
+                     ossimNumericProperty* prop = new ossimNumericProperty(name,
+                                                                           storedValue);
+                     prop->setNumericType(ossimNumericProperty::ossimNumericPropertyType_FLOAT32);
+                     prop->setDescription(description);
+                     return prop;
+                  }
+                  else if(typeValue == "boolean")
+                  {
+                     ossimBooleanProperty* prop = new ossimBooleanProperty(name,
+                                                                           storedValue.toBool());
+
+                     prop->setDescription(description);
+                     return prop;
+                  }
+                  else if((typeValue == "string-select")||
+                          (typeValue == "string"))
+                  {
+                     ossim_uint32 idx2 = 0;
+                     ossimString defaultValue = "";
+                     
+                     if(storedValueFlag)
+                     {
+                        defaultValue = storedValue;
+                     }
+                     else if(valuelist.size())
+                     {
+                        defaultValue = valuelist[0]->getText();
+                     }
+                     ossimStringProperty* prop = new ossimStringProperty(name,
+                                                                         defaultValue,
+                                                                         false);
+                     for(idx2 = 0; idx2 < valuelist.size();++idx2)
+                     {
+                        prop->addConstraint(valuelist[idx2]->getText());
+                     }
+                     prop->setDescription(description);
+                     return prop;
+                  }
+                  else
+                  {
+                     if(traceDebug())
+                     {
+                        ossimNotify(ossimNotifyLevel_INFO) << "************************TYPE VALUE = " << typeValue << " NOT HANDLED************"<< std::endl;
+                        ossimNotify(ossimNotifyLevel_INFO) << "************************DEFAULTING TO TEXT ************" << std::endl;
+                     }
+                     ossim_uint32 idx2 = 0;
+                     ossimString defaultValue = "";
+                     
+                     if(storedValueFlag)
+                     {
+                        defaultValue = storedValue;
+                     }
+                     else if(valuelist.size())
+                     {
+                        defaultValue = valuelist[0]->getText();
+                     }
+                     ossimStringProperty* prop = new ossimStringProperty(name,
+                                                                         defaultValue,
+                                                                         false);
+                     for(idx2 = 0; idx2 < valuelist.size();++idx2)
+                     {
+                        prop->addConstraint(valuelist[idx2]->getText());
+                     }
+                     prop->setDescription(description);
+                     return prop;
+                  }
+               }
+            }
+         }
+      }
+   }
+   
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG) << "ossimGdalWriter::getProperty: entered..." << std::endl;
+   }
+   return 0;
+}
+
+void ossimGdalWriter::getPropertyNames(std::vector<ossimString>& propertyNames)const
+{
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG) << "ossimGdalWriter::getPropertyNames: entered......." << std::endl;
+   }
+   ossimImageFileWriter::getPropertyNames(propertyNames);
+   propertyNames.push_back("gdal_overview_type");
+   propertyNames.push_back("HFA_USE_RRD");
+   getGdalPropertyNames(propertyNames);
+}
+
+void ossimGdalWriter::getGdalPropertyNames(std::vector<ossimString>& propertyNames)const
+{
+   ossimString driverName = convertToDriverName(theOutputImageType);
+   GDALDriverH driver =  GDALGetDriverByName(driverName.c_str());
+
+   if(driver)
+   {
+      const ossimRefPtr<ossimXmlNode>  node = getGdalOptions();
+      
+      if(node.valid())
+      {
+         vector<ossimRefPtr<ossimXmlNode> > nodelist;
+         node->findChildNodes("Option", nodelist);
+
+         if(traceDebug())
+         {
+            ossimNotify(ossimNotifyLevel_DEBUG) << "GDAL XML PROPERTY LIST" << std::endl
+                                                << node.get() << std::endl;
+         }
+         ossim_uint32 idx = 0;
+         for(idx= 0; idx < nodelist.size(); ++idx)
+         {
+            ossimRefPtr<ossimXmlAttribute> name = nodelist[idx]->findAttribute("name");
+            if(name.valid())
+            {
+               if(traceDebug())
+               {
+                  ossimNotify(ossimNotifyLevel_DEBUG) << "Adding property = " << name->getValue() << std::endl;
+               }
+               propertyNames.push_back(driverName + "_" + name->getValue());
+            }
+         }
+      }         
+   }
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG) << "ossimGdalWriter::getPropertyNames: leaving......." << std::endl;
+   }
+   
+}
+
+const ossimRefPtr<ossimXmlNode> ossimGdalWriter::getGdalOptions()const
+{
+   ossimString driverName = convertToDriverName(theOutputImageType);
+   GDALDriverH driver =  GDALGetDriverByName(driverName.c_str());
+
+   if(driver)
+   {
+      const char* metaData = GDALGetMetadataItem(driver, GDAL_DMD_CREATIONOPTIONLIST, 0);
+      if(metaData)
+      {
+         istringstream in(metaData);
+         ossimRefPtr<ossimXmlNode>  node = new ossimXmlNode(in);
+         vector<ossimRefPtr<ossimXmlNode> > nodelist;
+         node->findChildNodes("Option", nodelist);
+         if(nodelist.size())
+         {
+            return node;
+         }
+      }
+   }
+   return 0;
+}
+
+void ossimGdalWriter::storeProperty(const ossimString& name,
+                                    const ossimString& value)
+{
+   ossimString regExpression =  (ossimString("^") +
+                                 "property[0-9]+");
+
+   vector<ossimString> keys = theDriverOptionValues.getSubstringKeyList( regExpression );
+   ossim_uint32 idx = 0;
+   for(idx = 0; idx < keys.size(); ++idx)
+   {
+      ossimString storedName    = theDriverOptionValues.find(keys[idx] +".name");
+
+      if(storedName == name)
+      {
+         theDriverOptionValues.add(keys[idx] +".value",
+                                   value,
+                                   true);
+         return;
+      }
+   }
+   ossimString prefix = (ossimString("property") +
+                         ossimString::toString(theDriverOptionValues.getSize()/2) +
+                         ".");
+   theDriverOptionValues.add(prefix.c_str(),
+                             "name",
+                             name,
+                             true);
+   theDriverOptionValues.add(prefix.c_str(),
+                             "value",
+                             value,
+                             true);
+}
+
+bool ossimGdalWriter::getStoredPropertyValue(const ossimString& name,
+                                             ossimString& value)const
+{
+   ossimString regExpression =  (ossimString("^") +
+                                 "property[0-9]+");
+
+   vector<ossimString> keys = theDriverOptionValues.getSubstringKeyList( regExpression );
+   ossim_uint32 idx = 0;
+   for(idx = 0; idx < keys.size(); ++idx)
+   {
+      ossimString storedName    = theDriverOptionValues.find(keys[idx] +".name");
+      if(storedName == name)
+      {
+         value   = ossimString(theDriverOptionValues.find(keys[idx] +".value"));
+         return true;
+      }
+   }
+   
+   return false;
+}
+
+bool ossimGdalWriter::validProperty(const ossimString& name)const
+{
+   std::vector<ossimString> propertyNames;
+
+   if((name == "gdal_overview_type")||
+      (name == "HFA_USE_RRD") || name == "format")
+   {
+      return true;
+   }
+   getGdalPropertyNames(propertyNames);
+
+   ossim_uint32 idx = 0;
+   for(idx = 0; idx < propertyNames.size(); ++idx)
+   {
+      if(name == propertyNames[idx])
+      {
+         return true;
+      }
+   }
+
+   return false;
+}
+
+ossimString ossimGdalWriter::gdalOverviewTypeToString()const
+{
+   switch(theGdalOverviewType)
+   {
+      case ossimGdalOverviewType_NONE:
+      {
+         return "none";
+      }
+      case ossimGdalOverviewType_NEAREST:
+      {
+         return "nearest";
+      }
+      case ossimGdalOverviewType_AVERAGE:
+      {
+         return "average";
+      }
+   }
+
+   return "none";
+}
+
+ossimGdalWriter::ossimGdalOverviewType ossimGdalWriter::gdalOverviewTypeFromString(const ossimString& typeString)const
+{
+   ossimString tempType = typeString;
+   tempType = tempType.downcase();
+   tempType = tempType.trim();
+
+   if(tempType == "nearest")
+   {
+      return ossimGdalOverviewType_NEAREST;
+   }
+   else if(tempType == "average")
+   {
+      return ossimGdalOverviewType_AVERAGE;
+   }
+
+   return ossimGdalOverviewType_NONE;
+}
+
+void ossimGdalWriter::buildGdalOverviews()
+{
+
+  if(!theDataset)
+  {
+    return;
+  }
+  ossimIrect bounds = theInputConnection->getBoundingRect();
+  
+  ossim_uint32 minValue = ossim::min((ossim_uint32)bounds.width(),
+				   (ossim_uint32)bounds.height());
+  
+  int nLevels = static_cast<int>(std::log((double)minValue)/std::log(2.0));
+  int idx = 0;
+  if(nLevels)
+    {
+      ossim_int32* levelsPtr = new ossim_int32[nLevels];
+      *levelsPtr = 2;
+      for(idx = 1; idx < nLevels;++idx)
+	{
+	  levelsPtr[idx] = levelsPtr[idx-1]*2;
+	}
+      if(GDALBuildOverviews(theDataset,
+			    gdalOverviewTypeToString().c_str(),
+			    nLevels,
+			    levelsPtr,
+			    0,
+			    0,
+			    GDALTermProgress,
+			    0)!=CE_None)
+	{
+	  ossimNotify(ossimNotifyLevel_WARN) << "ossimGdalWriter::buildGdalOverviews():  Overview building failed" 
+					     << std::endl;
+	}
+      delete [] levelsPtr;
+    }
+}
+
+void ossimGdalWriter::postProcessOutput() const
+{
+   //---
+   // DRB 20081029
+   // Trac #419:
+   //
+   // The file.aux.xml file contains nodata value keys which is causing view
+   // issues with ArcMap and Erdas Imagine when null values are present in
+   // valid image data.
+   //--- 
+   if (theDriver)
+   {
+      ossimString driverName = GDALGetDriverShortName(theDriver);
+      if ( (driverName == "JP2MrSID") || (driverName != "JP2KAK") ||
+           (driverName == "JPEG2000") )
+      {
+         ossimFilename auxXmlFile = theFilename;
+         auxXmlFile += ".aux.xml";
+         if ( auxXmlFile.exists() )
+         {
+            if ( auxXmlFile.remove() )
+            {
+               ossimNotify(ossimNotifyLevel_NOTICE)
+                  << "ossimGdalWriter::postProcessOutput NOTICE:"
+                  << "\nFile removed:  " << auxXmlFile << std::endl;
+            }
+         }
+      }
+   }
+}
+
+bool ossimGdalWriter::isInputDataIndexed()
+{
+   bool result = false;
+   if ( theInputConnection.valid() )
+   {
+      result = theInputConnection->isIndexedData();
+   }
+   return result;
+}
+
diff --git a/ossim_plugins/gdal/ossimGdalWriter.h b/ossim_plugins/gdal/ossimGdalWriter.h
new file mode 100644
index 0000000..b72aade
--- /dev/null
+++ b/ossim_plugins/gdal/ossimGdalWriter.h
@@ -0,0 +1,146 @@
+//*******************************************************************
+//
+// License:  See top level LICENSE.txt file.
+//
+// Author:  Garrett Potts
+//
+//*******************************************************************
+//  $Id: ossimGdalWriter.h 19733 2011-06-06 23:35:25Z dburken $
+#ifndef ossimGdalWriter_HEADER
+#define ossimGdalWriter_HEADER 1
+
+#include <gdal.h>
+#include <ossim/imaging/ossimImageFileWriter.h>
+#include <ossim/base/ossimKeywordlist.h>
+#include <ossim/imaging/ossimNBandToIndexFilter.h>
+
+class ossimXmlNode;
+
+class ossimGdalWriter : public ossimImageFileWriter
+{
+public:
+   enum ossimGdalOverviewType
+   {
+      ossimGdalOverviewType_NONE    = 0,
+      ossimGdalOverviewType_NEAREST = 1,
+      ossimGdalOverviewType_AVERAGE = 2
+   };
+   ossimGdalWriter();
+   virtual              ~ossimGdalWriter();
+
+   
+   ossimGdalWriter(ossimImageSource *inputSource,
+                   const ossimFilename& filename);
+
+   /**
+    * void getImageTypeList(std::vector<ossimString>& imageTypeList)const
+    *
+    * Appends this writer image types to list "imageTypeList".
+    *
+    * @param imageTypeList stl::vector<ossimString> list to append to.
+    */
+   virtual void getImageTypeList(std::vector<ossimString>& imageTypeList)const;
+   virtual bool hasImageType(const ossimString& imageType) const;
+
+   /**
+    * Returns a 3-letter extension from the image type descriptor 
+    * (theOutputImageType) that can be used for image file extensions.
+    *
+    * @param imageType string representing image type.
+    *
+    * @return the 3-letter string extension.
+    */
+   virtual ossimString getExtension() const;
+
+   virtual bool isOpen()const;
+   
+   virtual bool open();
+   virtual void close();
+
+   /*!
+    * saves the state of the object.
+    */
+   virtual bool saveState(ossimKeywordlist& kwl,
+                          const char* prefix=0)const;
+   
+   /*!
+    * Method to the load (recreate) the state of an object from a keyword
+    * list.  Return true if ok or false on error.
+    */
+   virtual bool loadState(const ossimKeywordlist& kwl,
+                          const char* prefix=0);
+
+   static void getSupportedWriters(vector<ossimString>& writers);
+   
+   virtual void setProperty(ossimRefPtr<ossimProperty> property);
+   virtual ossimRefPtr<ossimProperty> getProperty(const ossimString& name)const;
+   virtual void getPropertyNames(std::vector<ossimString>& propertyNames)const;
+
+   virtual void  setOutputImageType(const ossimString&  type);
+
+   void setLut(const ossimNBandLutDataObject& lut);
+
+protected:
+   virtual bool writeFile();
+   virtual bool writeBlockFile();
+   virtual void writeProjectionInfo(GDALDatasetH dataset);
+   
+   virtual void writeColorMap(int bands);
+   
+   virtual void setOptions(ossimKeywordlist& kwl,
+                           const char* prefix=NULL);
+   void deleteGdalDriverOptions();
+   ossimString convertToDriverName(const ossimString& imageTypeName)const;
+   
+   GDALDataType getGdalDataType(ossimScalarType scalar);
+   void getGdalPropertyNames(std::vector<ossimString>& propertyNames)const;
+   const ossimRefPtr<ossimXmlNode> getGdalOptions()const;
+   ossim_int32 findOptionIdx(const ossimString& name)const;
+   void allocateGdalDriverOptions();
+   void storeProperty(const ossimString& name,
+                      const ossimString& value);
+   bool getStoredPropertyValue(const ossimString& name,
+                               ossimString& value)const;
+   bool validProperty(const ossimString& name)const;
+   ossimString gdalOverviewTypeToString()const;
+   ossimGdalOverviewType gdalOverviewTypeFromString(const ossimString& typeString)const;
+   void buildGdalOverviews();
+   void appendGdalOption(const ossimString& name, const ossimString& value, bool replaceFlag = true);
+
+   /**
+    * @brief Method called after good writeFile to clean up any unwanted
+    * files.
+    */
+   void postProcessOutput() const;
+
+   bool isLutEnabled()const;
+
+   void checkColorLut();
+
+   /**
+    * @brief Check input to see if it's indexed.
+    * 
+    * @return True if input data is indexed pallete data, false if not.
+    */
+   bool isInputDataIndexed();
+   
+   ossimString  theDriverName;
+   
+   GDALDriverH  theDriver;
+   GDALDatasetH theDataset;
+
+   ossimIpt theJpeg2000TileSize;
+   ossimKeywordlist theDriverOptionValues;
+   
+   char** theGdalDriverOptions;
+   ossimGdalOverviewType theGdalOverviewType;
+
+   bool                                         theColorLutFlag;
+   ossimRefPtr<ossimNBandLutDataObject>         theColorLut;
+   ossimFilename                                theLutFilename;
+   mutable ossimRefPtr<ossimNBandToIndexFilter> theNBandToIndexFilter;
+   
+TYPE_DATA
+};
+
+#endif
diff --git a/ossim_plugins/gdal/ossimHdfInfo.cpp b/ossim_plugins/gdal/ossimHdfInfo.cpp
new file mode 100644
index 0000000..26602c5
--- /dev/null
+++ b/ossim_plugins/gdal/ossimHdfInfo.cpp
@@ -0,0 +1,203 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author:  Mingjie Su
+//
+// Description: Ogr Info object.
+// 
+//----------------------------------------------------------------------------
+// $Id: ossimHdfInfo.cpp 2645 2011-05-26 15:21:34Z oscar.kramer $
+
+//gdal includes
+#include <gdal_priv.h>
+#include <cpl_string.h>
+
+//ossim includes
+#include <ossim/base/ossimNotify.h>
+#include <ossim/base/ossimTrace.h>
+#include <ossim/base/ossimKeywordlist.h>
+#include <ossimHdfInfo.h>
+
+// Static trace for debugging
+static ossimTrace traceDebug("ossimHdfInfo:debug");
+
+ossimHdfInfo::ossimHdfInfo()
+   : ossimInfoBase(),
+     theFile(),
+     m_hdfReader(0),
+     m_driverName()
+{
+}
+
+ossimHdfInfo::~ossimHdfInfo()
+{
+   m_hdfReader = 0;
+   m_globalMeta.clear();
+   m_globalMetaVector.clear();
+}
+
+bool ossimHdfInfo::open(const ossimFilename& file)
+{
+   static const char MODULE[] = "ossimHdfInfo::open";
+   if (traceDebug())
+   {    
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " entered...\n"
+         << "file: " << file << "\n";
+   }
+
+   bool result = false;
+   
+   ossimString ext = file.ext();
+   ext.downcase();
+
+   if ( ext == "hdf" || ext == "h4" || ext == "hdf4" || 
+     ext == "he4" || ext == "hdf5" || ext == "he5" || ext == "h5" || 
+     ext == "l1r")
+   {
+     m_hdfReader = new ossimHdfReader;
+     m_hdfReader->setFilename(file);
+
+     if ( m_hdfReader->open() )
+     {
+       m_driverName = m_hdfReader->getDriverName();
+       if (m_driverName.contains("HDF4"))
+       {
+         m_driverName = "hdf4";
+       }
+       else if (m_driverName.contains("HDF5"))
+       {
+         m_driverName = "hdf5";
+       }
+
+       theFile = file;
+       m_globalMeta.clear();
+       m_globalMetaVector.clear();
+       GDALDatasetH dataset = GDALOpen(theFile.c_str(), GA_ReadOnly);
+       if (dataset != 0)
+       {
+          char** papszMetadata = GDALGetMetadata(dataset, NULL);
+          if( CSLCount(papszMetadata) > 0 )
+          {
+             for(ossim_uint32 metaIndex = 0; papszMetadata[metaIndex] != 0; ++metaIndex)
+             {
+                ossimString metaInfo = papszMetadata[metaIndex];
+                if (metaInfo.contains("="))
+                {
+                   std::vector<ossimString> metaInfos = metaInfo.split("=");
+                   if (metaInfos.size() > 1)
+                   {
+                      ossimString key = metaInfos[0];
+                      ossimString keyStr = key.substitute(":", ".", true);
+                      keyStr = keyStr + ": ";
+                      ossimString valueStr = metaInfos[1];
+                      m_globalMeta[keyStr] = valueStr;
+                      m_globalMetaVector.push_back(ossimString(keyStr + valueStr));
+                   }
+                }
+             }
+          }
+       }
+       GDALClose(dataset);
+
+       result = true;
+     }
+   }
+
+   if (traceDebug())
+   {    
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " exit status = " << (result?"true\n":"false\n");
+   }
+
+   return result;
+}
+
+std::ostream& ossimHdfInfo::print(std::ostream& out) const
+{
+   static const char MODULE[] = "ossimHdfInfo::print";
+   if (traceDebug())
+   {    
+      ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " entered...\n";
+   }
+
+   ossimString prefix = ossimString(m_driverName + ".").downcase();
+
+   //print out global meta first
+   for (ossim_uint32 i = 0; i < m_globalMetaVector.size(); i++)
+   {
+       out << prefix << m_globalMetaVector[i] << "\n";
+   }
+
+   ossim_uint32 entryNum = m_hdfReader->getNumberOfEntries();
+   for (ossim_uint32 i = 0; i < entryNum; i++)
+   {
+      ossimString imagePrefix = "image" + ossimString::toString(i) + ".";
+      ossimString fileName = m_hdfReader->getEntryString(i);
+      if (!fileName.empty())
+      {
+         GDALDatasetH dataset = GDALOpen(fileName.c_str(), GA_ReadOnly);
+         if (dataset != 0)
+         {
+            ossim_uint32 numOfBands = GDALGetRasterCount(dataset);
+            for (ossim_uint32 j = 0; j < numOfBands; j++)
+            {
+               ossimString bandPrefix = "band" + ossimString::toString(j) + ".";
+               ossimString prefixStr = prefix + imagePrefix + bandPrefix;
+               ossimString nameStr = "name: ";
+               ossimString subDatasetName = fileName;
+               std::vector<ossimString> subFileList = fileName.split(":");
+               if (subFileList.size() > 2)
+               {
+                  if (m_driverName == "hdf4")
+                  {
+                     subDatasetName = subFileList[1] + ":" + subFileList[subFileList.size() - 2] + ":" + subFileList[subFileList.size() - 1];
+                  }
+                  else if (m_driverName == "hdf5")
+                  {
+                     subDatasetName = subFileList[subFileList.size() - 1];
+                  }
+               }
+               out << prefixStr << nameStr << subDatasetName << "\n";
+
+               char** papszMetadata = GDALGetMetadata(dataset, NULL);
+               if( CSLCount(papszMetadata) > 0 )
+               {
+                  for(ossim_uint32 metaIndex = 0; papszMetadata[metaIndex] != 0; ++metaIndex)
+                  {
+                     ossimString metaInfo = papszMetadata[metaIndex];
+                     if (metaInfo.contains("="))
+                     {
+                        std::vector<ossimString> metaInfos = metaInfo.split("=");
+                        if (metaInfos.size() > 1)
+                        {
+                           ossimString key = metaInfos[0];
+                           ossimString keyStr = key.substitute(":", ".", true);
+                           keyStr = keyStr + ": ";
+                           ossimString valueStr = metaInfos[1];
+                           std::map<ossimString, ossimString, ossimStringLtstr>::const_iterator itSub = m_globalMeta.find(keyStr);
+                           if (itSub == m_globalMeta.end())//avoid to print global again
+                           {
+                              out << prefixStr << keyStr << valueStr << "\n";
+                           } 
+                        }
+                     }
+                  }
+               }
+            }
+            GDALClose(dataset);
+         }//end if (dataset != 0)
+      }//end if (!fileName.empty())
+   }//end for
+   
+   if (traceDebug())
+   {    
+      ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " exited...\n";
+   }
+
+   return out;
+}
+
diff --git a/ossim_plugins/gdal/ossimHdfInfo.h b/ossim_plugins/gdal/ossimHdfInfo.h
new file mode 100644
index 0000000..dde1f56
--- /dev/null
+++ b/ossim_plugins/gdal/ossimHdfInfo.h
@@ -0,0 +1,64 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author:  Mingjie Su
+//
+// Description: Info object for HDF data.
+// 
+//----------------------------------------------------------------------------
+// $Id: ossimHdfInfo.h 2645 2011-05-26 15:21:34Z oscar.kramer $
+#ifndef ossimHdfInfo_HEADER
+#define ossimHdfInfo_HEADER 1
+
+#include <ossim/base/ossimConstants.h>
+#include <ossim/base/ossimRefPtr.h>
+#include <ossim/support_data/ossimInfoBase.h>
+#include <ossim/base/ossimFilename.h>
+#include <ossimHdfReader.h>
+
+/**
+ * @brief HDF info class.
+ *
+ * Encapsulates the HDF functionality.
+ */
+class ossimHdfInfo : public ossimInfoBase
+{
+public:
+   
+   /** default constructor */
+   ossimHdfInfo();
+   
+   /** virtual destructor */
+   virtual ~ossimHdfInfo();
+   
+   /**
+    * @brief open method.
+    *
+    * @param file File name to open.
+    * @return true on success false on error.
+    */
+   virtual bool open(const ossimFilename& file);
+   
+   /**
+    * Print method.
+    *
+    * @param out Stream to print to.
+    * 
+    * @return std::ostream&
+    */
+   virtual std::ostream& print(std::ostream& out) const;
+   
+private: 
+   
+   ossimFilename                       theFile;
+   ossimRefPtr<ossimHdfReader>         m_hdfReader;
+   ossimString                         m_driverName;
+   std::map<ossimString, ossimString, ossimStringLtstr>  m_globalMeta;
+   std::vector<ossimString>            m_globalMetaVector;
+};
+
+#endif /* End of "#ifndef ossimHdfInfo_HEADER" */
+
diff --git a/ossim_plugins/gdal/ossimHdfReader.cpp b/ossim_plugins/gdal/ossimHdfReader.cpp
new file mode 100644
index 0000000..b959694
--- /dev/null
+++ b/ossim_plugins/gdal/ossimHdfReader.cpp
@@ -0,0 +1,442 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Description:  Class definition for HDF reader.
+//
+//----------------------------------------------------------------------------
+// $Id: ossimHdfReader.cpp 2645 2011-05-26 15:21:34Z oscar.kramer $
+
+//Std includes
+#include <set>
+
+//ossim includes
+#include <ossimHdfReader.h>
+#include <ossim/base/ossimScalarTypeLut.h>
+#include <ossim/base/ossimTrace.h>
+#include <ossim/base/ossimUnitTypeLut.h>
+#include <ossim/imaging/ossimImageGeometryRegistry.h>
+#include <ossim/imaging/ossimImageDataFactory.h>
+
+#ifdef OSSIM_ID_ENABLED
+static const char OSSIM_ID[] = "$Id";
+#endif
+
+static ossimTrace traceDebug("ossimHdfReader:debug");
+
+RTTI_DEF1_INST(ossimHdfReader, "ossimHdfReader", ossimImageHandler)
+
+bool doubleEquals(ossim_float64 left, ossim_float64 right, ossim_float64 epsilon) 
+{
+  return (fabs(left - right) < epsilon);
+}
+
+ossimHdfReader::ossimHdfReader()
+  : ossimImageHandler(),
+    m_gdalTileSource(0),
+    m_entryFileList(),
+    m_numberOfBands(0),
+    m_scalarType(OSSIM_SCALAR_UNKNOWN),
+    m_currentEntryRender(0),
+    m_tile(0)
+{
+}
+
+ossimHdfReader::~ossimHdfReader()
+{
+   close();
+   ossimImageHandler::close();
+}
+
+ossimString ossimHdfReader::getShortName()const
+{
+   return ossimString("ossim_hdf_reader");
+}
+
+ossimString ossimHdfReader::getLongName()const
+{
+   return ossimString("ossim hdf reader");
+}
+
+ossimString ossimHdfReader::getClassName()const
+{
+   return ossimString("ossimHdfReader");
+}
+
+ossim_uint32 ossimHdfReader::getNumberOfLines(
+   ossim_uint32 resLevel) const
+{
+   ossim_uint32 result = 0;
+   if (resLevel == 0)
+   {
+      if (m_gdalTileSource.valid())
+      {
+         result = m_gdalTileSource->getNumberOfLines(resLevel);
+      }
+   }
+   else if (theOverview.valid())
+   {
+      result = theOverview->getNumberOfSamples(resLevel);
+   }
+   return result;
+}
+
+ossim_uint32 ossimHdfReader::getNumberOfSamples(
+   ossim_uint32 resLevel) const
+{
+   ossim_uint32 result = 0;
+   if (resLevel == 0)
+   {
+      if (m_gdalTileSource.valid())
+      {
+         result = m_gdalTileSource->getNumberOfSamples(resLevel);
+      }
+   }
+   else if (theOverview.valid())
+   {
+      result = theOverview->getNumberOfSamples(resLevel);
+   }
+   return result;
+}
+
+bool ossimHdfReader::open()
+{
+   static const char MODULE[] = "ossimHdfReader::open";
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " entered...\n"
+         << "image: " << theImageFile << "\n";
+   }
+
+   bool result = false;
+
+   if (!isSupportedExtension())
+   {
+      return false;
+   }
+
+   if (m_entryFileList.size() == 0)
+   {
+      if(isOpen())
+      {
+         close();
+      }
+
+      m_gdalTileSource = new ossimGdalTileSource;
+      m_gdalTileSource->setFilename(theImageFile);
+
+      if ( m_gdalTileSource->open() == false )
+      {
+         m_gdalTileSource = 0;
+         return false;
+      }
+
+      std::vector<ossimString> entryStringList;
+      if (m_gdalTileSource != 0)
+      {
+         m_gdalTileSource->getEntryNames(entryStringList);
+      }
+      
+      // bool isSwathImage = false;
+      if (entryStringList.size() > 0)
+      {
+         for (ossim_uint32 i = 0; i < entryStringList.size(); i++)
+         {
+            m_entryFileList.push_back(i);
+         }
+      }
+      else
+      {
+        result = false;
+      }
+   }
+      
+   //set entry id for the gdal tile source
+   if (m_currentEntryRender < m_entryFileList.size())
+   {
+      
+      m_gdalTileSource->setCurrentEntry(m_currentEntryRender);
+      m_numberOfBands = m_gdalTileSource->getNumberOfInputBands();
+
+      m_tile = ossimImageDataFactory::instance()->create(this, this);
+      m_tile->initialize();
+      
+      completeOpen();
+      result = true;
+   }
+   else
+   {
+      result = false;
+   }
+   
+   if (result == false)
+   {
+      close();
+   }
+   
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " exit status = " << (result?"true":"false\n")
+         << std::endl;
+   }
+   
+   return result;
+}
+
+bool ossimHdfReader::isSDSDataset(ossimString fileName)
+{
+  std::vector<ossimString> fileList = fileName.split(":");
+  if (fileList.size() > 0)
+  {
+    ossimString  subName = fileList[0];
+    if (subName.contains("_SDS"))
+    {
+      return true;
+    }
+  }
+  return false;
+}
+
+bool ossimHdfReader::isOpen()const
+{
+   return m_gdalTileSource.get();
+}
+
+void ossimHdfReader::close()
+{
+   m_tile = 0;
+
+   if (m_gdalTileSource.valid())
+   {
+      m_gdalTileSource = 0;
+   }
+   m_entryFileList.clear();
+}
+
+ossimRefPtr<ossimImageData> ossimHdfReader::getTile(const ossimIrect& tile_rect, 
+                                                    ossim_uint32 resLevel)
+{
+   if (m_tile.valid())
+   {
+      // Image rectangle must be set prior to calling getTile.
+      m_tile->setImageRectangle(tile_rect);
+      
+      if ( getTile( m_tile.get(), resLevel ) == false )
+      {
+         if (m_tile->getDataObjectStatus() != OSSIM_NULL)
+         {
+            m_tile->makeBlank();
+         }
+      }
+   }
+
+   return m_tile;
+}
+
+bool ossimHdfReader::getTile(ossimImageData* result,
+                             ossim_uint32 resLevel)
+{
+   bool status = false;
+
+   //---
+   // Not open, this tile source bypassed, or invalid res level,
+   // return a blank tile.
+   //---
+   if( isOpen() && isSourceEnabled() && isValidRLevel(resLevel) &&
+       result && (result->getNumberOfBands() == getNumberOfOutputBands()) )
+   {
+      result->ref();  // Increment ref count.
+
+      //---
+      // Check for overview tile.  Some overviews can contain r0 so always
+      // call even if resLevel is 0.  Method returns true on success, false
+      // on error.
+      //---
+      status = getOverviewTile(resLevel, result);
+
+      if (!status) // Did not get an overview tile.
+      {
+         status = true;
+
+         ossimIrect tile_rect = result->getImageRectangle();     
+
+         if (getImageRectangle().intersects(tile_rect))
+         {
+            // Make a clip rect.
+            ossimIrect clipRect = tile_rect.clipToRect(getImageRectangle());
+
+            if (tile_rect.completely_within(clipRect) == false)
+            {
+               // Not filling whole tile so blank it out first.
+               result->makeBlank();
+            }
+
+            if (m_gdalTileSource.valid())
+            {
+               ossimRefPtr<ossimImageData> imageData =
+                  m_gdalTileSource->getTile(tile_rect, resLevel);
+               result->loadTile(imageData->getBuf(), tile_rect, clipRect, OSSIM_BSQ);
+            }
+     
+         }
+         else // No intersection...
+         {
+            result->makeBlank();
+         }
+      }
+      result->validate();
+
+      result->unref();  // Decrement ref count.
+   }
+
+   return status;
+}
+
+bool ossimHdfReader::isSupportedExtension()
+{
+   ossimString ext = theImageFile.ext();
+   ext.downcase();
+
+   if ( ext == "hdf" || ext == "h4" || ext == "hdf4" || 
+     ext == "he4" || ext == "hdf5" || ext == "he5" || ext == "h5" || 
+     ext == "l1r")
+   {
+      return true;
+   }
+   return false;
+}
+
+ossim_uint32 ossimHdfReader::getNumberOfInputBands() const
+{
+   return m_numberOfBands;
+}
+
+ossim_uint32 ossimHdfReader::getNumberOfOutputBands()const
+{
+   return m_numberOfBands;
+}
+
+ossim_uint32 ossimHdfReader::getImageTileWidth() const
+{
+   ossim_uint32 result = 128;
+   if (m_gdalTileSource.valid())
+   {
+      result = m_gdalTileSource->getImageTileWidth();
+   }
+   return result;
+}
+
+ossim_uint32 ossimHdfReader::getImageTileHeight() const
+{
+   ossim_uint32 result = 128;
+   if (m_gdalTileSource.valid())
+   {
+      result = m_gdalTileSource->getImageTileHeight();
+   }
+   return result;
+}
+
+ossimScalarType ossimHdfReader::getOutputScalarType() const
+{
+   if (m_gdalTileSource.valid())
+   {
+      return m_gdalTileSource->getOutputScalarType(); 
+   }
+   return m_scalarType;
+}
+
+ossimRefPtr<ossimImageGeometry> ossimHdfReader::getImageGeometry()
+{
+   if ( !theGeometry )
+   {
+      // Check the internal geometry first to avoid a factory call.
+      if ( m_gdalTileSource.valid() )
+      {
+         theGeometry = m_gdalTileSource->getImageGeometry();
+      }
+   }
+   return theGeometry;
+}
+
+bool ossimHdfReader::loadState(const ossimKeywordlist& kwl, const char* prefix)
+{
+   bool result = false;
+   if ( ossimImageHandler::loadState(kwl, prefix) )
+   {
+      result = open();
+   }
+   return result;
+}
+
+bool ossimHdfReader::setCurrentEntry(ossim_uint32 entryIdx)
+{
+   if (m_currentEntryRender == entryIdx)
+   {
+      return true; // Nothing to do...
+   }
+   theDecimationFactors.clear();
+   theGeometry = 0;
+   theOverview = 0;
+   theOverviewFile.clear();
+   m_currentEntryRender = entryIdx;
+   return open();
+}
+
+ossim_uint32 ossimHdfReader::getNumberOfEntries()const
+{
+   return m_entryFileList.size();
+}
+
+void ossimHdfReader::getEntryList(std::vector<ossim_uint32>& entryList) const
+{
+   entryList.clear();
+   for (ossim_uint32 i = 0; i < m_entryFileList.size(); i++)
+   {
+      entryList.push_back(m_entryFileList[i]);
+   }
+}
+
+ossimString ossimHdfReader::getEntryString(ossim_uint32 entryId) const 
+{
+   if (m_gdalTileSource.valid())
+   {
+      std::vector<ossimString> entryStringList;
+      m_gdalTileSource->getEntryNames(entryStringList);
+      if (entryId < entryStringList.size())
+      {
+         return entryStringList[entryId];
+      }
+   }
+   return "";
+}
+
+ossimString ossimHdfReader::getDriverName()
+{
+   ossimString result = "";
+   if (m_gdalTileSource.valid())
+   {
+      GDALDriverH driver = m_gdalTileSource->getDriver();
+      if (driver)
+      {
+         result = GDALGetDriverShortName(driver);
+      }
+   }
+   return result;
+}
+
+bool ossimHdfReader::setOutputBandList(const vector<ossim_uint32>& outputBandList)
+{
+   if (outputBandList.size() && m_gdalTileSource != 0)
+   {
+      m_gdalTileSource->setOutputBandList(outputBandList);
+      open();
+      return true;
+   }
+   return false;
+}
+
diff --git a/ossim_plugins/gdal/ossimHdfReader.h b/ossim_plugins/gdal/ossimHdfReader.h
new file mode 100644
index 0000000..a3bd41d
--- /dev/null
+++ b/ossim_plugins/gdal/ossimHdfReader.h
@@ -0,0 +1,203 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Description:  Class declaration HDF reader.
+//
+// Specification: ISO/IEC 15444
+//
+//----------------------------------------------------------------------------
+// $Id: ossimHdfReader.h 2645 2011-05-26 15:21:34Z oscar.kramer $
+
+#ifndef ossimHdfReader_HEADER
+#define ossimHdfReader_HEADER 1
+
+//ossim includes
+#include "../ossimPluginConstants.h"
+#include <ossim/base/ossimIpt.h>
+#include <ossim/base/ossimIrect.h>
+#include <ossim/base/ossimRefPtr.h>
+#include <ossim/imaging/ossimImageHandler.h>
+#include <ossim/support_data/ossimJ2kSizRecord.h>
+#include <ossim/imaging/ossimAppFixedTileCache.h>
+#include <ossimGdalTileSource.h>
+
+// Forward class declarations.
+class ossimImageData;
+
+class OSSIM_PLUGINS_DLL ossimHdfReader : public ossimImageHandler
+{
+public:
+
+   /** default construtor */
+   ossimHdfReader();
+   
+   /** virtural destructor */
+   virtual ~ossimHdfReader();
+
+   /**
+    * @brief Returns short name.
+    * @return "ossim_hdf_reader"
+    */
+   virtual ossimString getShortName() const;
+   
+   /**
+    * @brief Returns long  name.
+    * @return "ossim hdf reader"
+    */
+   virtual ossimString getLongName()  const;
+
+   /**
+    * @brief Returns class name.
+    * @return "ossimHdfReader"
+    */
+   virtual ossimString getClassName() const;
+
+   /**
+    *  @brief Method to grab a tile(rectangle) from image.
+    *
+    *  @param rect The zero based rectangle to grab.
+    *
+    *  @param resLevel The reduced resolution level to grab from.
+    *
+    *  @return The ref pointer with the image data pointer.
+    */
+   virtual ossimRefPtr<ossimImageData> getTile(const  ossimIrect& rect,
+                                               ossim_uint32 resLevel=0);
+
+   virtual bool getTile(ossimImageData* result, ossim_uint32 resLevel=0);   
+
+   /**
+    *  Returns the number of bands in the image.
+    *  Satisfies pure virtual from ImageHandler class.
+    */
+   virtual ossim_uint32 getNumberOfInputBands() const;
+
+   /**
+    * Returns the number of bands in a tile returned from this TileSource.
+    * Note: we are supporting sources that can have multiple data objects.
+    * If you want to know the scalar type of an object you can pass in the
+    */
+   virtual ossim_uint32 getNumberOfOutputBands()const; 
+   /**
+    * Returns the tile width of the image or 0 if the image is not tiled.
+    * Note: this is not the same as the ossimImageSource::getTileWidth which
+    * returns the output tile width which can be different than the internal
+    * image tile width on disk.
+    */
+   virtual ossim_uint32 getImageTileWidth() const;
+
+   /**
+    * Returns the tile width of the image or 0 if the image is not tiled.
+    * Note: this is not the same as the ossimImageSource::getTileHeight which
+    * returns the output tile height which can be different than the internal
+    * image tile height on disk.
+    */
+   virtual ossim_uint32 getImageTileHeight() const;
+
+   /**
+    * Returns the output pixel type of the tile source.
+    */
+   virtual ossimScalarType getOutputScalarType() const;
+ 
+
+   /**
+    * @brief Gets number of lines for res level.
+    *
+    *  @param resLevel Reduced resolution level to return lines of.
+    *  Default = 0
+    *
+    *  @return The number of lines for specified reduced resolution level.
+    */
+   virtual ossim_uint32 getNumberOfLines(ossim_uint32 resLevel = 0) const;
+
+   /**
+    *  @brief Gets the number of samples for res level.
+    *
+    *  @param resLevel Reduced resolution level to return samples of.
+    *  Default = 0
+    *
+    *  @return The number of samples for specified reduced resolution level.
+    */
+   virtual ossim_uint32 getNumberOfSamples(ossim_uint32 resLevel = 0) const;
+
+   /**
+    * @brief Open method.
+    * @return true on success, false on error.
+    */
+   virtual bool open();
+
+   /**
+    *  @brief Method to test for open file stream.
+    *
+    *  @return true if open, false if not.
+    */
+   virtual bool isOpen()const;
+
+   /**
+    * @brief Method to close current entry.
+    *
+    */
+   virtual void close();
+
+   /**
+    * Returns the image geometry object associated with this tile source or
+    * NULL if non defined.  The geometry contains full-to-local image
+    * transform as well as projection (image-to-world).
+    */
+   virtual ossimRefPtr<ossimImageGeometry> getImageGeometry();
+
+   /**
+    * Method to the load (recreate) the state of an object from a keyword
+    * list.  Return true if ok or false on error.
+    */
+   virtual bool loadState(const ossimKeywordlist& kwl,
+                          const char* prefix=0);   
+
+   virtual bool setCurrentEntry(ossim_uint32 entryIdx);
+
+    /**
+    * @return The number of entries (images) in the image file.
+    */
+   virtual ossim_uint32 getNumberOfEntries()const;
+   
+   /**
+    * @param entryList This is the list to initialize with entry indexes.
+    *
+    * @note This implementation returns puts one entry "0" in the list.
+    */
+   virtual void getEntryList(std::vector<ossim_uint32>& entryList) const;
+
+   /**
+    * @return The current entry number.
+    *
+    */
+   virtual ossim_uint32 getCurrentEntry() const { return m_currentEntryRender; }
+
+   bool isSupportedExtension();
+
+   std::vector<ossim_uint32> getCurrentEntryList(ossim_uint32 entryId) const;
+
+   ossimString getEntryString(ossim_uint32 entryId) const;
+
+   ossimString getDriverName();
+
+   virtual bool setOutputBandList(const std::vector<ossim_uint32>& band_list);
+
+private:
+
+  bool isSDSDataset(ossimString fileName);
+
+  ossimRefPtr<ossimGdalTileSource>                              m_gdalTileSource;
+  mutable std::vector<ossim_uint32>                             m_entryFileList;
+  ossim_uint32                                                  m_numberOfBands;
+  ossimScalarType                                               m_scalarType;
+  ossim_uint32                                                  m_currentEntryRender;
+  ossimRefPtr<ossimImageData>                                   m_tile;
+TYPE_DATA
+};
+
+#endif /* #ifndef ossimHdfReader_HEADER */
+
diff --git a/ossim_plugins/gdal/ossimOgcWktTranslator.cpp b/ossim_plugins/gdal/ossimOgcWktTranslator.cpp
new file mode 100644
index 0000000..7f7adb4
--- /dev/null
+++ b/ossim_plugins/gdal/ossimOgcWktTranslator.cpp
@@ -0,0 +1,1083 @@
+//*******************************************************************
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author:  Frank Warmerdam (warmerda at home.com)
+// Contributor: David A. Horner
+//
+// Description:
+//
+// Contains code implementation translation between OGC WKT format,
+// and OSSIM projection keyword lists.  Note that services from 
+// GDAL's OGRSpatialReference class are used via the GDAL bridge to
+// accomplish the translation. 
+//
+//*******************************************************************
+//  $Id: ossimOgcWktTranslator.cpp 23664 2015-12-14 14:17:27Z dburken $
+
+#include <cstdio>
+#include <gdal.h>
+#include <geovalues.h>
+
+#include "ossimOgcWktTranslator.h"
+#include <ogr_spatialref.h>
+#include <ossim/base/ossimKeywordNames.h>
+#include <ossim/base/ossimTrace.h>
+#include <ossim/base/ossimKeyword.h>
+#include <ossim/base/ossimKeywordlist.h>
+#include <ossim/projection/ossimAlbersProjection.h>
+#include <ossim/projection/ossimCylEquAreaProjection.h>
+#include <ossim/projection/ossimTransMercatorProjection.h>
+#include <ossim/projection/ossimUtmProjection.h>
+#include <ossim/projection/ossimProjectionFactoryRegistry.h>
+#include <ossim/projection/ossimEpsgProjectionDatabase.h>
+#include <ossim/projection/ossimEpsgProjectionFactory.h>
+#include <ossim/base/ossimUnitConversionTool.h>
+#include <ossim/base/ossimUnitTypeLut.h>
+
+static const double SEMI_MAJOR_AXIS_WGS84 = 6378137.0;
+static const double SEMI_MINOR_AXIS_WGS84 = 6356752.3142;
+
+static ossimTrace traceDebug("ossimOgcWktTranslator:debug");
+
+//*******************************************************************
+// Public Function:
+//*******************************************************************
+ossimOgcWktTranslator::ossimOgcWktTranslator()
+{
+   initializeDatumTable();
+   initializeProjectionTable();
+}
+
+#define EPSG_CODE_MAX 32767
+#define USER_DEFINED  32767
+ossimString ossimOgcWktTranslator::fromOssimKwl(const ossimKeywordlist &kwl,
+                                                const char *prefix)const
+{
+   ossimString projType = kwl.find(ossimKeywordNames::TYPE_KW);
+   ossimString datumType = kwl.find(ossimKeywordNames::DATUM_KW);
+   
+   ossimString wktString;
+   OGRSpatialReference oSRS;
+   
+   if(projType == "")
+   {
+      return wktString;
+   }
+   
+   ossimString zone = kwl.find(prefix, ossimKeywordNames::ZONE_KW);
+   ossimString hemisphere = kwl.find(prefix, ossimKeywordNames::HEMISPHERE_KW);
+   ossimString parallel1  = kwl.find(prefix, ossimKeywordNames::STD_PARALLEL_1_KW);
+   ossimString parallel2  = kwl.find(prefix, ossimKeywordNames::STD_PARALLEL_2_KW);
+   ossimString originLat  = kwl.find(prefix, ossimKeywordNames::ORIGIN_LATITUDE_KW);
+   ossimString centralMeridian = kwl.find(prefix, ossimKeywordNames::CENTRAL_MERIDIAN_KW);
+   ossimString scale = kwl.find(prefix, ossimKeywordNames::SCALE_FACTOR_KW);
+   ossimString pcsCode = kwl.find(prefix, ossimKeywordNames::PCS_CODE_KW);
+
+   ossimDpt falseEastingNorthing;
+   // Get the false easting northing.
+   falseEastingNorthing.x = 0.0;
+   falseEastingNorthing.y = 0.0;
+   const char *lookup =
+      kwl.find(prefix, ossimKeywordNames::FALSE_EASTING_NORTHING_UNITS_KW);
+   if (lookup)
+   {
+      ossimUnitType units =
+         static_cast<ossimUnitType>(ossimUnitTypeLut::instance()->
+                                    getEntryNumber(lookup));
+      
+      lookup = kwl.find(prefix, ossimKeywordNames::FALSE_EASTING_NORTHING_KW);
+      if (lookup)
+      {
+         ossimDpt eastingNorthing;
+         eastingNorthing.toPoint(std::string(lookup));
+         
+         switch (units)
+         {
+            case OSSIM_METERS:
+            {
+               falseEastingNorthing = eastingNorthing;
+               break;
+            }
+            case OSSIM_FEET:
+            case OSSIM_US_SURVEY_FEET:
+            {
+               ossimUnitConversionTool ut;
+               ut.setValue(eastingNorthing.x, units);
+               falseEastingNorthing.x = ut.getValue(OSSIM_METERS);
+               ut.setValue(eastingNorthing.y, units);
+               falseEastingNorthing.y = ut.getValue(OSSIM_METERS);
+               break;
+            }
+            default:
+            {
+               // Unhandled unit type!
+               ossimNotify(ossimNotifyLevel_WARN)
+                  << "ossimOgcWktTranslator::fromOssimKwl WARNING!"
+                  << "Unhandled unit type for "
+                  << ossimKeywordNames::FALSE_EASTING_NORTHING_UNITS_KW
+                  << ":  " 
+                  << ( ossimUnitTypeLut::instance()->
+                       getEntryString(units).c_str() )
+                  << endl;
+               break;
+            }
+         } // End of switch (units)
+         
+      }  // End of if (FALSE_EASTING_NORTHING_KW)
+
+   } // End of if (FALSE_EASTING_NORTHING_UNITS_KW)
+   else
+   {
+      // BACKWARDS COMPATIBILITY LOOKUPS...
+      lookup =  kwl.find(prefix, ossimKeywordNames::FALSE_EASTING_KW);
+      if(lookup)
+      {
+         falseEastingNorthing.x = fabs(ossimString(lookup).toFloat64());
+      }
+      
+      lookup =  kwl.find(prefix, ossimKeywordNames::FALSE_NORTHING_KW);
+      if(lookup)
+      {
+         falseEastingNorthing.y = fabs(ossimString(lookup).toFloat64());
+      }
+   }
+
+   oSRS.SetLinearUnits("Meter", 1.0);
+
+   int pcsCodeVal = (pcsCode.empty() == false) ? pcsCode.toInt() : EPSG_CODE_MAX;
+   
+   // since approximately ossim version r20036
+   // kwl.find(prefix, ossimKeywordNames::PCS_CODE_KW)
+   // return 0 instead of "" previously.
+   // the to following lines ensure backward compatibility
+   // Since EPSG:0 is not a valid epsg code, the fix is safe
+   // (ref http://spatialreference.org/ref/epsg/)
+   if(pcsCodeVal == 0)
+        pcsCodeVal = EPSG_CODE_MAX;
+   
+   if(pcsCodeVal < EPSG_CODE_MAX)
+   {
+      // ESH 06/2008 -- HACK!!!
+      // If the PCS code is for a HARN state plane and the implied pcs code's units 
+      // is feet (us or intl), we find the equivalent code for units of meters.  
+      // We're doing this because ArcMap (9.2 and less) doesn't understand the 
+      // non-meters HARN codes.  However, the units are left unchanged in this 
+      // process, so the units can be different than the user-specified pcs code. 
+      // ArcMap 9.2 seems to understand the mixed definition just fine.
+      ossimEpsgProjectionDatabase* proj_db = ossimEpsgProjectionDatabase::instance();
+      ossimString pcsCodeName = proj_db->findProjectionName(pcsCodeVal);
+      if ( pcsCodeName.contains("HARN") && pcsCodeName.contains("_Feet") )
+      {
+         ossimString feetStr("_Feet");
+         ossimString newPcsCodeName( pcsCodeName.before(feetStr).c_str() );
+         ossimString epsg_spec = proj_db->findProjectionCode(newPcsCodeName);
+         ossim_uint32 new_code = epsg_spec.after(":").toUInt32();
+         if (new_code)
+          pcsCodeVal = new_code;
+      }
+      oSRS.importFromEPSG( pcsCodeVal );
+   }
+   if(projType == "ossimUtmProjection")
+   {
+#if 0
+      hemisphere = hemisphere.trim().upcase();
+      
+      if(hemisphere != "")
+      {
+         oSRS.SetUTM(zone.toLong(), hemisphere != "S");
+      }
+      else
+      {
+         oSRS.SetUTM(zone.toLong(), true);
+      }
+#else
+      // ESH 09/2008: Adapting code from ossimTiffWriter.cpp for 
+      // converting UTM zone,hemisphere to a PCS code.
+
+      short gcs = USER_DEFINED;
+
+      if (datumType == "WGE") gcs = GCS_WGS_84;
+      else if (datumType == "WGD") gcs = GCS_WGS_72;
+      else if (datumType == "NAR-C") gcs = GCS_NAD83;
+      else if (datumType == "NAR") gcs = GCS_NAD83;
+      else if (datumType == "NAS-C") gcs = GCS_NAD27;
+      else if (datumType == "NAS") gcs = GCS_NAD27;
+      else if (datumType == "ADI-M") gcs = GCS_Adindan;
+      else if (datumType == "ARF-M") gcs = GCS_Arc_1950;
+      else if (datumType == "ARS-M") gcs = GCS_Arc_1960;
+      else if (datumType == "EUR-7" || datumType == "EUR-M") gcs = GCS_ED50;
+      else if ((datumType == "OGB-7") ||
+               (datumType == "OGB-M") ||
+               (datumType == "OGB-A") ||
+               (datumType == "OGB-B") ||
+               (datumType == "OGB-C") ||
+               (datumType == "OGB-D")) gcs = GCS_OSGB_1936;
+      else if  (datumType == "TOY-M")  gcs = GCS_Tokyo;
+      else
+      {
+         if(traceDebug())
+         {
+            ossimNotify(ossimNotifyLevel_DEBUG)
+               << "DATUM = " << datumType << " tag not written " << std::endl
+               << "Please let us know so we can add it"          << std::endl;
+         }
+      }
+
+      int mapZone = zone.toInt();
+      hemisphere = hemisphere.trim().upcase();
+      bool bDoImportFromEPSG = false;
+
+      switch ( gcs )
+      {
+         case GCS_WGS_84:
+         {
+            if (hemisphere == "N") // Northern hemisphere.
+            {
+               pcsCodeVal = 32600 + mapZone;
+            }
+            else // Southern hemisphere.
+            {
+               pcsCodeVal = 32700 + mapZone;
+            }
+            bDoImportFromEPSG = true;
+            break;
+         }
+
+         case GCS_WGS_72:
+         {
+            if (hemisphere == "N") // Northern hemisphere.
+            {
+               pcsCodeVal = 32200 + mapZone;
+            }
+            else // Southern hemisphere.
+            {
+               pcsCodeVal = 32300 + mapZone;
+            }
+            bDoImportFromEPSG = true;
+            break;
+         }
+
+         case GCS_NAD27:
+         {
+            if (hemisphere == "N") // Northern hemisphere.
+            {
+               pcsCodeVal = 26700 + mapZone;
+            }
+            else // Southern hemisphere.
+            {
+               pcsCodeVal = 32000 + mapZone;
+            }
+            bDoImportFromEPSG = true;
+            break;
+         }
+
+         case GCS_NAD83:
+         {
+            if (hemisphere == "N") // Northern hemisphere.
+            {
+               pcsCodeVal = 26900 + mapZone;
+            }
+            else // Southern hemisphere.
+            {
+               pcsCodeVal = 32100 + mapZone;
+            }
+            bDoImportFromEPSG = true;
+            break;
+         }
+
+         default:
+         {
+            //***
+            // Use a projection code that does not imply a datum.
+            // See section "6.3.3.2 Projection Codes" for definition.
+            //***
+            if (mapZone > 0) // Northern hemisphere.
+            {
+               pcsCodeVal = 16000 + mapZone;
+            }
+            else if (mapZone < 0) // Southern hemisphere.
+            {
+               hemisphere = "S";
+               pcsCodeVal = 16100 + abs(mapZone);
+            }
+            break;
+         }
+      } // End of "switch ( gcs )"
+
+      if ( bDoImportFromEPSG == true )
+         oSRS.importFromEPSG( pcsCodeVal );
+      else
+      {
+         if(hemisphere != "")
+         {
+            oSRS.SetUTM(zone.toLong(), hemisphere != "S");
+         }
+         else
+         {
+            oSRS.SetUTM(zone.toLong(), true);
+         }
+      }
+#endif
+   }
+   else if(projType == "ossimLlxyProjection")
+   {
+      OGRSpatialReference oGeogCS;
+      
+      oGeogCS.SetEquirectangular(0.0,
+                                 0.0,
+                                 0.0,
+                                 0.0);
+      oGeogCS.SetAngularUnits(SRS_UA_DEGREE, atof(SRS_UA_DEGREE_CONV));
+      
+      oSRS.CopyGeogCSFrom( &oGeogCS );  
+   }
+   else if(projType == "ossimEquDistCylProjection")
+   {
+      OGRSpatialReference oGeogCS;
+      
+      oGeogCS.SetEquirectangular(originLat.toDouble(),
+                                 centralMeridian.toDouble(),
+                                 falseEastingNorthing.x,
+                                 falseEastingNorthing.y);
+      oGeogCS.SetAngularUnits(SRS_UA_DEGREE, atof(SRS_UA_DEGREE_CONV));
+      
+      oSRS.CopyGeogCSFrom( &oGeogCS );  
+   }
+   else if(projType == "ossimSinusoidalProjection")
+   {
+      oSRS.SetSinusoidal(centralMeridian.toDouble(),
+                         falseEastingNorthing.x,
+                         falseEastingNorthing.y);
+   }
+   else if(projType == "ossimCylEquAreaProjection")
+   {
+      oSRS.SetCEA(originLat.toDouble(),
+                  centralMeridian.toDouble(),
+                  falseEastingNorthing.x,
+                  falseEastingNorthing.y);
+   }
+   else if(projType == "ossimCassiniProjection")
+   {
+      oSRS.SetCS(originLat.toDouble(),
+                 centralMeridian.toDouble(),
+                 falseEastingNorthing.x,
+                 falseEastingNorthing.y);
+   }
+   else if(projType == "ossimAlbersProjection")
+   {
+      oSRS.SetACEA(parallel1.toDouble(),
+                   parallel2.toDouble(),
+                   originLat.toDouble(),
+                   centralMeridian.toDouble(),
+                   falseEastingNorthing.x,
+                   falseEastingNorthing.y);
+   }
+   else if(projType == "ossimAzimEquDistProjection")
+   {
+      oSRS.SetAE(originLat.toDouble(),
+                 centralMeridian.toDouble(),
+                 falseEastingNorthing.x,
+                 falseEastingNorthing.y);
+   }
+   else if(projType == "ossimEckert4Projection")
+   {
+      oSRS.SetEckertIV(centralMeridian.toDouble(),
+                       falseEastingNorthing.x,
+                       falseEastingNorthing.y);
+   }
+   else if(projType == "ossimEckert6Projection")
+   {
+      oSRS.SetEckertVI(centralMeridian.toDouble(),
+                       falseEastingNorthing.x,
+                       falseEastingNorthing.y);
+   }
+   else if(projType == "ossimGnomonicProjection")
+   {
+      oSRS.SetGnomonic(originLat.toDouble(),
+                       centralMeridian.toDouble(),
+                       falseEastingNorthing.x,
+                       falseEastingNorthing.y);
+   }
+   else if(projType == "ossimLambertConformalConicProjection")
+   {
+      oSRS.SetLCC(parallel1.toDouble(),
+                  parallel2.toDouble(),
+                  originLat.toDouble(),
+                  centralMeridian.toDouble(),
+                  falseEastingNorthing.x,
+                  falseEastingNorthing.y);
+   }
+   else if(projType == "ossimVanDerGrintenProjection")
+   {
+      oSRS.SetVDG(centralMeridian.toDouble(),
+                  falseEastingNorthing.x,
+                  falseEastingNorthing.y);
+   }
+   else if(projType == "ossimMillerProjection")
+   {
+      oSRS.SetMC(originLat.toDouble(),
+                 centralMeridian.toDouble(),
+                 falseEastingNorthing.x,
+                 falseEastingNorthing.y);
+   }
+   else if(projType == "ossimMercatorProjection")
+   {
+      oSRS.SetMercator(originLat.toDouble(),
+                       centralMeridian.toDouble(),
+                       scale.toDouble(),
+                       falseEastingNorthing.x,
+                       falseEastingNorthing.y);
+   }
+   else if(projType == "ossimMollweidProjection")
+   {
+      oSRS.SetMollweide(centralMeridian.toDouble(),
+                        falseEastingNorthing.x,
+                        falseEastingNorthing.y);
+   }
+   else if(projType == "ossimNewZealandMapGridProjection")
+   {
+      oSRS.SetNZMG(originLat.toDouble(),
+                   centralMeridian.toDouble(),
+                   falseEastingNorthing.x,
+                   falseEastingNorthing.y);
+   }
+   else if(projType == "ossimOrthoGraphicProjection")
+   {
+      oSRS.SetOrthographic(originLat.toDouble(),
+                           centralMeridian.toDouble(),
+                           falseEastingNorthing.x,
+                           falseEastingNorthing.y);
+   }
+   else if(projType == "ossimPolarStereoProjection")
+   {
+      oSRS.SetPS(originLat.toDouble(),
+                 centralMeridian.toDouble(),
+                 scale.toDouble(),
+                 falseEastingNorthing.x,
+                 falseEastingNorthing.y);
+   }
+   else if(projType == "ossimPolyconicProjectio")
+   {
+      oSRS.SetPolyconic(originLat.toDouble(),
+                        centralMeridian.toDouble(),
+                        falseEastingNorthing.x,
+                        falseEastingNorthing.y);
+   }
+   else if(projType == "ossimStereographicProjection")
+   {
+      oSRS.SetStereographic(originLat.toDouble(),
+                            centralMeridian.toDouble(),
+                            scale.toDouble(),
+                            falseEastingNorthing.x,
+                            falseEastingNorthing.y);
+   }
+   else if(projType == "ossimTransMercatorProjection")
+   {
+      oSRS.SetTM(originLat.toDouble(),
+                 centralMeridian.toDouble(),
+                 scale.toDouble(),
+                 falseEastingNorthing.x,
+                 falseEastingNorthing.y);
+   }
+   else 
+   {
+      cerr << "ossimOgcWktTranslator::fromOssimKwl:\n"
+           << "Projection translation for "
+           << projType
+           << " not supported "
+           << endl;
+   }
+   
+   if(pcsCodeVal >= EPSG_CODE_MAX)
+   {
+      datumType =  datumType.upcase();
+      
+      if(datumType == "WGE")
+      {
+         oSRS.SetWellKnownGeogCS("WGS84");
+      }
+      else if(datumType == "WGD")
+      {
+         oSRS.SetWellKnownGeogCS("WGS72");      
+      }
+      else if(datumType == "NAS-C") //1927
+      {
+         oSRS.SetWellKnownGeogCS("NAD27");      
+      }
+      else if(datumType == "NAS") //1927
+      {
+         oSRS.SetWellKnownGeogCS("NAD27");      
+      }
+      else if(datumType == "NAR-C") // 1983
+      {
+         oSRS.SetWellKnownGeogCS("NAD83");
+      }
+      else if(datumType == "NAR") // 1983
+      {
+         oSRS.SetWellKnownGeogCS("NAD83");
+      }
+      else if(datumType == "NTF")
+      {
+        oSRS.SetWellKnownGeogCS("EPSG:4275");
+      }
+      else
+      {
+         cerr << "ossimOgcWktTranslator::fromOssimKwl: Datum translation for "
+              << datumType
+              <<" not supported"
+              << endl;
+      }
+   }
+
+   char* exportString = NULL;
+   oSRS.exportToWkt(&exportString);
+   
+   if(exportString)
+   {
+      wktString = exportString;
+      OGRFree(exportString);
+   }
+
+   return wktString;
+   
+}
+
+bool ossimOgcWktTranslator::toOssimKwl( const ossimString& wktString,
+                                        ossimKeywordlist &kwl,
+                                        const char *prefix)const
+
+{
+   static const char MODULE[] = "ossimOgcWktTranslator::toOssimKwl";
+
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " entered...\n";
+   }
+   
+   const char* wkt = wktString.c_str();
+   
+   OGRSpatialReferenceH  hSRS = NULL;
+   ossimDpt falseEastingNorthing;
+   
+   // Translate the WKT into an OGRSpatialReference. 
+   hSRS = OSRNewSpatialReference(NULL);
+   if( OSRImportFromWkt( hSRS, (char **) &wkt ) != OGRERR_NONE )
+   {
+      OSRDestroySpatialReference( hSRS );
+      return false;
+   }
+   
+   // Determine if State Plane Coordinate System
+   ossimString ossimProj = "";
+   const char* epsg_code = OSRGetAttrValue( hSRS, "AUTHORITY", 1 );
+
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "epsg_code: " << (epsg_code?epsg_code:"null") << "\n";
+   }
+   
+   //---
+   // Extract Units 
+   // ESH 11/2008: Check for geographic system when setting default units. 
+   // If geographic, use degrees.
+   //---
+//   const char* units = OSRGetAttrValue( hSRS, "UNIT", 0 );
+   const char* units = NULL;
+   OGR_SRSNode* node = ((OGRSpatialReference *)hSRS)->GetRoot();
+   int nbChild  = node->GetChildCount();
+   for (int i = 0; i < nbChild; i++)
+   {
+      OGR_SRSNode* curChild = node->GetChild(i);
+      if (strcmp(curChild->GetValue(), "UNIT") == 0)
+      {
+         units = curChild->GetChild(0)->GetValue();
+      }
+   }
+
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "units: " << (units?units:"null") << "\n";
+   }
+   
+   ossimString ossim_units;
+   bool bGeog = OSRIsGeographic(hSRS);
+   if ( bGeog == false )
+   {
+      ossim_units = "meters";
+      if ( units != NULL )
+      {
+         // Down case to avoid case mismatch.
+         ossimString s = units;
+         s.downcase();
+         
+         if( ( s == ossimString("us survey foot") ) ||
+             ( s == ossimString("u.s. foot") ) ||
+             ( s == ossimString("foot_us") ) )
+         {
+            ossim_units = "us_survey_feet";
+         }
+         else if( s == ossimString("degree") )
+         {
+            ossim_units = "degrees";
+         }
+         else if( ( s == ossimString("meter") ) ||
+                  ( s == ossimString("metre") ) )
+         {
+            ossim_units = "meters";
+         }
+      }
+   }
+   else
+   {
+      ossim_units = "degrees";
+   }
+
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossim_units: " << ossim_units << "\n";
+   }
+
+   // OLK 05/2010 -- ossimProj string was never being set to projection type (except state plane
+   // which is not even a projection type)! This was a bug. Using EPSG factory to attempt to get 
+   // proper projection:
+   if (epsg_code)
+   {
+      ossimString epsg_spec ("EPSG:"); 
+      epsg_spec += ossimString::toString(ossimString(epsg_code));
+      ossimProjection* proj = ossimEpsgProjectionFactory::instance()->createProjection(epsg_spec);
+      if (proj)
+         ossimProj = proj->getClassName();
+      delete proj;
+   }
+
+   if(ossimProj == "") 
+   {
+      // Determine which other Projection System is represented.
+      const char* pszProjection = OSRGetAttrValue( hSRS, "PROJECTION", 0 );
+      if(pszProjection)
+      {
+         ossimProj = wktToOssimProjection(pszProjection);
+      }
+      else
+      {
+         ossimString localCs = OSRGetAttrValue( hSRS, "LOCAL_CS", 0 );
+         localCs = localCs.upcase();
+         if(localCs == "GREATBRITAIN_GRID")
+         {
+            ossimProj = "ossimBngProjection";
+         }
+         else if (ossim_units.contains("degree"))
+         {
+            // Assumption...
+            ossimProj = "ossimEquDistCylProjection";
+         }
+      }
+   }
+
+   // ESH 11/2008: Ticket #479, if we've got a geographic coordsys 
+   // make sure the units are set to degrees.
+   if(ossimProj == "ossimEquDistCylProjection" )
+      ossim_units = "degrees";
+
+   // ESH 11/2008: Ticket #479, don't set units until we've checked
+   // whether or not the projection was updated.
+   kwl.add(prefix, ossimKeywordNames::UNITS_KW, ossim_units, true);
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << "DEBUG:"
+         << "\nossimProj = " << ossimProj << endl;
+   }
+   
+   kwl.add(prefix, ossimKeywordNames::TYPE_KW, ossimProj.c_str(), true);
+
+   falseEastingNorthing.x = OSRGetProjParm(hSRS, SRS_PP_FALSE_EASTING, 0.0, NULL);
+   falseEastingNorthing.y = OSRGetProjParm(hSRS, SRS_PP_FALSE_NORTHING, 0.0, NULL);
+   if (epsg_code)
+   {
+      kwl.add(prefix, ossimKeywordNames::PCS_CODE_KW, epsg_code, true);
+   }
+   if(ossimProj == "ossimBngProjection")
+   {
+      kwl.add(prefix,
+              ossimKeywordNames::TYPE_KW,
+              "ossimBngProjection",
+              true);
+   }
+   else if(ossimProj == "ossimCylEquAreaProjection")
+   {
+      kwl.add(prefix,
+              ossimKeywordNames::STD_PARALLEL_1_KW,
+              OSRGetProjParm(hSRS, SRS_PP_STANDARD_PARALLEL_1, 0.0, NULL),
+              true);
+      
+      kwl.add(prefix,
+              ossimKeywordNames::ORIGIN_LATITUDE_KW,
+              OSRGetProjParm(hSRS, SRS_PP_STANDARD_PARALLEL_1, 0.0, NULL),
+              true);
+
+      ossimUnitType units =
+         static_cast<ossimUnitType>(ossimUnitTypeLut::instance()->
+                                    getEntryNumber(ossim_units.c_str()));
+      if ( units == OSSIM_METERS || 
+           units == OSSIM_FEET   || 
+           units == OSSIM_US_SURVEY_FEET )
+      {
+         kwl.add(prefix,
+                 ossimKeywordNames::FALSE_EASTING_NORTHING_KW,
+                 falseEastingNorthing.toString(),
+                 true);
+         kwl.add(prefix,
+                 ossimKeywordNames::FALSE_EASTING_NORTHING_UNITS_KW,
+                 ossim_units,
+                 true);
+      }
+   }
+   else if(ossimProj == "ossimEquDistCylProjection")
+   {
+      kwl.add(prefix,
+              ossimKeywordNames::TYPE_KW,
+              "ossimEquDistCylProjection",
+              true);
+      
+      ossimUnitType units =
+         static_cast<ossimUnitType>(ossimUnitTypeLut::instance()->
+                                    getEntryNumber(ossim_units.c_str()));
+      if ( units == OSSIM_METERS || 
+           units == OSSIM_FEET   || 
+           units == OSSIM_US_SURVEY_FEET )
+      {
+         kwl.add(prefix,
+                 ossimKeywordNames::FALSE_EASTING_NORTHING_KW,
+                 falseEastingNorthing.toString(),
+                 true);
+         kwl.add(prefix,
+                 ossimKeywordNames::FALSE_EASTING_NORTHING_UNITS_KW,
+                 ossim_units,
+                 true);
+      }
+
+      kwl.add(prefix,
+              ossimKeywordNames::ORIGIN_LATITUDE_KW,
+              OSRGetProjParm(hSRS, SRS_PP_LATITUDE_OF_ORIGIN, 0.0, NULL),
+              true);
+      kwl.add(prefix,
+              ossimKeywordNames::CENTRAL_MERIDIAN_KW,
+              OSRGetProjParm(hSRS, SRS_PP_CENTRAL_MERIDIAN, 0.0, NULL),
+              true);
+   }
+   else if( (ossimProj == "ossimLambertConformalConicProjection") ||
+            (ossimProj == "ossimAlbersProjection") )
+   {
+      kwl.add(prefix,
+              ossimKeywordNames::TYPE_KW,
+              ossimProj.c_str(),
+              true);
+      kwl.add(prefix,
+              ossimKeywordNames::FALSE_EASTING_NORTHING_KW,
+              falseEastingNorthing.toString(),
+              true);
+      kwl.add(prefix,
+              ossimKeywordNames::FALSE_EASTING_NORTHING_UNITS_KW,
+              ossim_units,
+              true);
+      kwl.add(prefix,
+              ossimKeywordNames::ORIGIN_LATITUDE_KW,
+              OSRGetProjParm(hSRS, SRS_PP_LATITUDE_OF_ORIGIN, 0.0, NULL),
+              true);
+      kwl.add(prefix,
+              ossimKeywordNames::CENTRAL_MERIDIAN_KW,
+              OSRGetProjParm(hSRS, SRS_PP_CENTRAL_MERIDIAN, 0.0, NULL),
+              true);
+      kwl.add(prefix,
+              ossimKeywordNames::STD_PARALLEL_1_KW,
+              OSRGetProjParm(hSRS, SRS_PP_STANDARD_PARALLEL_1, 0.0, NULL),
+              true);
+      kwl.add(prefix,
+              ossimKeywordNames::STD_PARALLEL_2_KW,
+              OSRGetProjParm(hSRS, SRS_PP_STANDARD_PARALLEL_2, 0.0, NULL),
+              true);
+   }
+   else if(ossimProj == "ossimMercatorProjection")
+   {
+      kwl.add(prefix,
+              ossimKeywordNames::TYPE_KW,
+              "ossimMercatorProjection",
+              true);
+      kwl.add(prefix,
+              ossimKeywordNames::ORIGIN_LATITUDE_KW,
+              OSRGetProjParm(hSRS, SRS_PP_LATITUDE_OF_ORIGIN, 0.0, NULL),
+              true);
+      kwl.add(prefix,
+              ossimKeywordNames::CENTRAL_MERIDIAN_KW,
+              OSRGetProjParm(hSRS, SRS_PP_CENTRAL_MERIDIAN, 0.0, NULL),
+              true);
+      kwl.add(prefix,
+              ossimKeywordNames::FALSE_EASTING_NORTHING_KW,
+              falseEastingNorthing.toString(),
+              true);
+      kwl.add(prefix,
+              ossimKeywordNames::FALSE_EASTING_NORTHING_UNITS_KW,
+              ossim_units,
+              true);
+   }
+   else if(ossimProj == "ossimSinusoidalProjection")
+   {
+      kwl.add(prefix,
+              ossimKeywordNames::TYPE_KW,
+              "ossimSinusoidalProjection",
+              true);
+      kwl.add(prefix,
+              ossimKeywordNames::CENTRAL_MERIDIAN_KW,
+              OSRGetProjParm(hSRS, SRS_PP_CENTRAL_MERIDIAN, 0.0, NULL),
+              true);
+      kwl.add(prefix,
+              ossimKeywordNames::FALSE_EASTING_NORTHING_KW,
+              falseEastingNorthing.toString(),
+              true);
+      kwl.add(prefix,
+              ossimKeywordNames::FALSE_EASTING_NORTHING_UNITS_KW,
+              ossim_units,
+              true);
+   }
+   else if(ossimProj == "ossimTransMercatorProjection")
+   {
+      int bNorth;
+      int nZone = OSRGetUTMZone( hSRS, &bNorth );
+      if( nZone != 0 )
+      {
+         kwl.add(prefix,
+                 ossimKeywordNames::TYPE_KW,
+                 "ossimUtmProjection",
+                 true);
+         
+         kwl.add(prefix,
+                 ossimKeywordNames::ZONE_KW,
+                 nZone,
+                 true);
+         if( bNorth )
+         {
+            kwl.add(prefix, ossimKeywordNames::HEMISPHERE_KW, "N", true);
+         }
+         else
+         {
+            kwl.add(prefix, ossimKeywordNames::HEMISPHERE_KW, "S", true);
+         }
+      }            
+      else
+      {
+         kwl.add(prefix,
+                 ossimKeywordNames::TYPE_KW,
+                 "ossimTransMercatorProjection",
+                 true);
+         kwl.add(prefix,
+                 ossimKeywordNames::SCALE_FACTOR_KW,
+                 OSRGetProjParm(hSRS, SRS_PP_SCALE_FACTOR, 1.0, NULL),
+                 true);
+         
+         kwl.add(prefix,
+                 ossimKeywordNames::ORIGIN_LATITUDE_KW,
+                 OSRGetProjParm(hSRS, SRS_PP_LATITUDE_OF_ORIGIN, 0.0, NULL),
+                 true);
+         kwl.add(prefix,
+                 ossimKeywordNames::CENTRAL_MERIDIAN_KW,
+                 OSRGetProjParm(hSRS, SRS_PP_CENTRAL_MERIDIAN, 0.0, NULL),
+                 true);
+         kwl.add(prefix,
+                 ossimKeywordNames::FALSE_EASTING_NORTHING_KW,
+                 falseEastingNorthing.toString(),
+                 true);
+         kwl.add(prefix,
+                 ossimKeywordNames::FALSE_EASTING_NORTHING_UNITS_KW,
+                 ossim_units,
+                 true);
+      }
+   }
+   else
+   {
+      if (traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG)
+            << "ossimOgcWktTranslator::toOssimKwl DEBUG:\n"
+            << "Projection conversion to OSSIM not supported !!!!!!!!!\n"
+            << "Please send the following string to the development staff\n" 
+            << "to be added to the transaltion to OSSIM\n"
+            << wkt << endl;
+      }
+      return false;
+   }
+
+   // extract out the datum
+   //
+   const char *datum = OSRGetAttrValue( hSRS, "DATUM", 0 );
+   ossimString oDatum = "WGE";
+    
+   if( datum )
+   {
+      oDatum = wktToOssimDatum(datum);
+      if(oDatum == "")
+      {
+         oDatum = "WGE";
+      }
+   }
+   
+   // Trouble with ESPG 3857 
+   // The ellipsoid used by ossim is the WGS84 one with minor and major axis differs. 
+   // We need to build our own projection in this case. 
+   if( oDatum == "WGE" && ossimString(epsg_code) == "3857" ) 
+   { 
+      oDatum = "6055";
+   }     
+   kwl.add(prefix, ossimKeywordNames::DATUM_KW, oDatum, true);
+     
+   OSRDestroySpatialReference( hSRS );
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " exit status = true"
+         << std::endl;
+   }    
+      
+   return true;
+}
+
+
+void ossimOgcWktTranslator::initializeDatumTable()
+{
+//    theWktToOssimDatumTranslation.insert(make_pair(ossimString("North_American_Datum_1927"),
+//                                                   ossimString("NAS-C")));
+  
+//    theWktToOssimDatumTranslation.insert(make_pair(ossimString("North_American_Datum_1983"),
+//                                                   ossimString("NAR-C")));
+//    theWktToOssimDatumTranslation.insert(make_pair(ossimString("WGS_1984"),
+//                                                   ossimString("WGE")));
+//    theWktToOssimDatumTranslation.insert(make_pair(ossimString("OSGB_1936"),
+//                                                   ossimString("OSGB_1936")));
+  
+   theOssimToWktDatumTranslation.insert(make_pair(std::string("NAS-C"),
+                                                  std::string("North_American_Datum_1927")));
+   theOssimToWktDatumTranslation.insert(make_pair(std::string("NAR-C"),
+                                                  std::string("North_American_Datum_1983")));
+   theOssimToWktDatumTranslation.insert(make_pair(std::string("NAS"),
+                                                  std::string("North_American_Datum_1927")));
+   theOssimToWktDatumTranslation.insert(make_pair(std::string("NAR"),
+                                                  std::string("North_American_Datum_1983")));
+   theOssimToWktDatumTranslation.insert(make_pair(std::string("WGE"),
+                                                  std::string("WGS_1984")));
+   theWktToOssimDatumTranslation.insert(make_pair(std::string("OSGB_1936"),
+                                                  std::string("OGB-B"))); 
+   theWktToOssimDatumTranslation.insert(make_pair(std::string("Nouvelle_Triangulation_Francaise"),
+                                                  std::string("NTF")));
+}
+
+void ossimOgcWktTranslator::initializeProjectionTable()
+{
+   theWktToOssimProjectionTranslation.insert(make_pair(std::string(SRS_PT_TRANSVERSE_MERCATOR),
+                                                       std::string("ossimTransMercatorProjection")));
+   theWktToOssimProjectionTranslation.insert(make_pair(std::string(SRS_PT_EQUIRECTANGULAR),
+                                                       std::string("ossimEquDistCylProjection")));
+   theWktToOssimProjectionTranslation.insert(make_pair(std::string(SRS_PT_ALBERS_CONIC_EQUAL_AREA),
+                                                       std::string("ossimAlbersProjection")));
+   theWktToOssimProjectionTranslation.insert(make_pair(std::string(SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP),
+                                                       std::string("ossimLambertConformalConicProjection")));
+   theWktToOssimProjectionTranslation.insert(make_pair(std::string(SRS_PT_SINUSOIDAL),
+                                                       std::string("ossimSinusoidalProjection")));
+   theWktToOssimProjectionTranslation.insert(make_pair(std::string(SRS_PT_MERCATOR_1SP),
+                                                       std::string("ossimMercatorProjection")));
+   theOssimToWktProjectionTranslation.insert(make_pair(std::string("ossimTransMercatorProjection"),
+                                                       std::string(SRS_PT_TRANSVERSE_MERCATOR)));
+   theOssimToWktProjectionTranslation.insert(make_pair(std::string("ossimEquDistCylProjection"),
+                                                       std::string(SRS_PT_EQUIRECTANGULAR)));
+   theOssimToWktProjectionTranslation.insert(make_pair(std::string("ossimAlbersProjection"),
+                                                       std::string(SRS_PT_ALBERS_CONIC_EQUAL_AREA)));
+   theOssimToWktProjectionTranslation.insert(make_pair(std::string("ossimLambertConformalConicProjection"),
+                                                       std::string(SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP)));
+   theOssimToWktProjectionTranslation.insert(make_pair(std::string("ossimSinusoidalProjection"),
+                                                       std::string(SRS_PT_SINUSOIDAL)));
+   theOssimToWktProjectionTranslation.insert(make_pair(std::string("ossimMercatorProjection"),
+                                                       std::string(SRS_PT_MERCATOR_1SP)));
+   
+}
+
+ossimString ossimOgcWktTranslator::wktToOssimDatum(const ossimString& datum)const
+{
+   if(datum.contains("North_American_Datum_1927"))
+   {
+      return "NAS-C";
+   }
+   if(datum.contains("North_American_Datum_1983"))
+   {
+      return "NAR-C";
+   }
+   if(datum.contains("WGS_1984"))
+   {
+      return "WGE";
+   }
+   if(datum.contains("OSGA"))
+   {
+      return "OGB-A";
+   }
+   if(datum.contains("OSGB"))
+   {
+      return "OGB-B";
+   }
+   if(datum.contains("OSGC"))
+   {
+      return "OGB-C";
+   }
+   if(datum.contains("OSGD"))
+   {
+      return "OGB-D";
+   }
+   if(datum.contains("Nouvelle_Triangulation_Francaise"))
+   {
+      return "NTF";
+   }
+   
+   return "";
+}
+
+ossimString ossimOgcWktTranslator::ossimToWktDatum(const ossimString& datum)const
+{
+   ossimString result;
+   map<std::string, std::string>::const_iterator i = theOssimToWktDatumTranslation.find(datum);
+   if(i != theOssimToWktDatumTranslation.end())
+   {
+      result = (*i).second;
+   }
+   return result;
+}
+
+ossimString ossimOgcWktTranslator::wktToOssimProjection(const ossimString& datum)const
+{
+   std::string result;
+   map<std::string, std::string>::const_iterator i =
+      theWktToOssimProjectionTranslation.find(datum);
+   if(i != theWktToOssimProjectionTranslation.end())
+   {
+      result = (*i).second;
+   }
+   return result;
+}
+
+ossimString ossimOgcWktTranslator::ossimToWktProjection(const ossimString& datum)const
+{
+   ossimString result;
+   map<std::string, std::string>::const_iterator i =
+      theOssimToWktProjectionTranslation.find(datum);
+   if(i != theOssimToWktProjectionTranslation.end())
+   {
+      result = (*i).second;
+   }
+   return result;
+}
+
+
diff --git a/ossim_plugins/gdal/ossimOgcWktTranslator.h b/ossim_plugins/gdal/ossimOgcWktTranslator.h
new file mode 100644
index 0000000..a15cc12
--- /dev/null
+++ b/ossim_plugins/gdal/ossimOgcWktTranslator.h
@@ -0,0 +1,65 @@
+//*******************************************************************
+// Copyright (C) 2000 ImageLinks Inc.
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author:  Frank Warmerdam (warmerda at home.com)
+//
+// Description:
+//
+// Contains function declarations for translating between OGC WKT strings,
+// and OSSIM projection definitions.
+//*******************************************************************
+//  $Id: ossimOgcWktTranslator.h 23664 2015-12-14 14:17:27Z dburken $
+
+#ifndef ossimOgcWktTranslator_HEADER
+#define ossimOgcWktTranslator_HEADER
+
+#include <ossimPluginConstants.h>
+
+#include <ossim/base/ossimCommon.h>
+#include <ossim/base/ossimString.h>
+
+#include <map>
+#include <string>
+
+class ossimKeywordlist;
+
+class OSSIM_PLUGINS_DLL ossimOgcWktTranslator
+{
+public:
+   ossimOgcWktTranslator();
+   
+   bool toOssimKwl(const ossimString& wktString,
+                   ossimKeywordlist& kwl,
+                   const char* prefix=NULL)const;
+   
+   ossimString fromOssimKwl(const ossimKeywordlist& kwl,
+                            const char* prefix=NULL)const;
+   /*!
+    * Returns the empty string if the datum is not found
+    *
+    */
+   ossimString wktToOssimDatum(const ossimString& datum)const;
+   ossimString ossimToWktDatum(const ossimString& datum)const;
+
+   ossimString wktToOssimProjection(const ossimString& projection)const;
+   ossimString ossimToWktProjection(const ossimString& projection)const;
+   
+protected:
+
+   std::map<std::string, std::string> theWktToOssimDatumTranslation;
+   std::map<std::string, std::string> theWktToOssimProjectionTranslation;
+
+   std::map<std::string, std::string> theOssimToWktDatumTranslation;
+   std::map<std::string, std::string> theOssimToWktProjectionTranslation;
+
+   void initializeDatumTable();
+   void initializeProjectionTable();
+   
+};
+
+#endif
+
diff --git a/ossim_plugins/gdal/ossimOgrGdalTileSource.cpp b/ossim_plugins/gdal/ossimOgrGdalTileSource.cpp
new file mode 100644
index 0000000..c336cc2
--- /dev/null
+++ b/ossim_plugins/gdal/ossimOgrGdalTileSource.cpp
@@ -0,0 +1,269 @@
+//*******************************************************************
+//
+// License:  See top level LICENSE.txt file.
+//
+// Author:  Garrett Potts
+//
+// Description:
+//
+// Contains class implementaiton for the class "ossimOgrGdalTileSource".
+//
+//*******************************************************************
+//  $Id: ossimOgrGdalTileSource.cpp 20133 2011-10-12 19:03:47Z oscarkramer $
+
+#include <ossimOgrGdalTileSource.h>
+
+RTTI_DEF3(ossimOgrGdalTileSource,
+          "ossimOgrGdalTileSource",
+          ossimImageHandler,
+          ossimViewInterface,
+          ossimEsriShapeFileInterface);
+
+//*******************************************************************
+// Public Constructor:
+//*******************************************************************
+ossimOgrGdalTileSource::ossimOgrGdalTileSource()
+   :
+      ossimImageHandler(),
+      ossimViewInterface(),
+      ossimEsriShapeFileInterface()
+{
+   theObject = this;
+   theAnnotationSource = new ossimGdalOgrVectorAnnotation();
+   thePixelType = OSSIM_PIXEL_IS_AREA;
+}
+
+//*******************************************************************
+// Destructor:
+//*******************************************************************
+ossimOgrGdalTileSource::~ossimOgrGdalTileSource()
+{
+   ossimViewInterface::theObject = 0;
+   close();
+   
+}
+
+//*******************************************************************
+// Public Method:
+//*******************************************************************
+bool ossimOgrGdalTileSource::open()
+{
+   return theAnnotationSource->open(theImageFile);
+}
+
+//*******************************************************************
+// Public method:
+//*******************************************************************
+bool ossimOgrGdalTileSource::saveState(ossimKeywordlist& kwl,
+                                       const char* prefix) const
+{
+   if(theAnnotationSource.valid())
+   {
+      theAnnotationSource->saveState(kwl, prefix);
+   }
+   return ossimImageHandler::saveState(kwl, prefix);
+}
+
+//*******************************************************************
+// Public method:
+//*******************************************************************
+bool ossimOgrGdalTileSource::loadState(const ossimKeywordlist& kwl,
+                                       const char* prefix)
+{
+   if (ossimImageHandler::loadState(kwl, prefix))
+   {
+      thePixelType = OSSIM_PIXEL_IS_AREA;
+      if (open())
+      {
+         if(theAnnotationSource.valid())
+         {
+            theAnnotationSource->loadState(kwl, prefix);
+         }
+         return true;
+      }
+   }
+
+   return false;
+}
+
+ossim_uint32 ossimOgrGdalTileSource::getImageTileWidth() const
+{
+   return 0;
+}
+
+ossim_uint32 ossimOgrGdalTileSource::getImageTileHeight() const
+{
+   return 0;
+}
+
+ossimRefPtr<ossimImageGeometry> ossimOgrGdalTileSource::getInternalImageGeometry() const
+{
+   theGeometry = theAnnotationSource->getImageGeometry();
+
+   return theGeometry;  
+}
+
+void ossimOgrGdalTileSource::close()
+{
+   theAnnotationSource->close();
+}
+
+ossimRefPtr<ossimImageData> ossimOgrGdalTileSource::getTile(
+   const ossimIrect& tileRect, ossim_uint32 resLevel)
+{
+   return theAnnotationSource->getTile(tileRect, resLevel);
+}
+
+ossim_uint32 ossimOgrGdalTileSource::getNumberOfInputBands() const
+{
+   return theAnnotationSource->getNumberOfOutputBands();
+}
+
+ossim_uint32 ossimOgrGdalTileSource::getNumberOfOutputBands() const
+{
+   return theAnnotationSource->getNumberOfOutputBands();
+}
+
+ossim_uint32 ossimOgrGdalTileSource::getNumberOfLines(ossim_uint32 /* reduced_res_level */ ) const
+{
+   ossimIrect theBounds = theAnnotationSource->getBoundingRect();
+   
+   if(theBounds.hasNans())
+   {
+      return theBounds.ul().x;
+   }
+   
+   return theBounds.height();
+}
+
+ossim_uint32 ossimOgrGdalTileSource::getNumberOfSamples(ossim_uint32 /* reduced_res_level */ ) const
+{
+   ossimIrect theBounds = theAnnotationSource->getBoundingRect();
+   
+   if(theBounds.hasNans())
+   {
+      return theBounds.ul().x;
+   }
+   
+   return theBounds.height();
+}
+
+ossim_uint32 ossimOgrGdalTileSource::getNumberOfDecimationLevels() const
+{
+   return 32;
+}
+
+ossimIrect ossimOgrGdalTileSource::getImageRectangle(ossim_uint32 /* reduced_res_level */ ) const
+{
+   return theAnnotationSource->getBoundingRect();
+}
+
+ossimScalarType ossimOgrGdalTileSource::getOutputScalarType() const
+{
+   return theAnnotationSource->getOutputScalarType();
+}
+
+ossim_uint32 ossimOgrGdalTileSource::getTileWidth() const
+{
+   return theAnnotationSource->getTileWidth();         
+}
+
+ossim_uint32 ossimOgrGdalTileSource::getTileHeight() const
+{
+   return theAnnotationSource->getTileHeight();
+}
+
+bool ossimOgrGdalTileSource::isOpen()const
+{
+   return theAnnotationSource->isOpen();
+}
+   
+double ossimOgrGdalTileSource::getNullPixelValue(ossim_uint32 band)const
+{
+   return theAnnotationSource->getNullPixelValue(band);
+}
+
+double ossimOgrGdalTileSource::getMinPixelValue(ossim_uint32 band)const
+{
+   return theAnnotationSource->getMinPixelValue(band);
+}
+
+double ossimOgrGdalTileSource::getMaxPixelValue(ossim_uint32 band)const
+{
+   return theAnnotationSource->getMaxPixelValue(band);
+}
+
+ossimObject* ossimOgrGdalTileSource::getView()
+{
+   return theAnnotationSource->getView();
+}
+
+const ossimObject* ossimOgrGdalTileSource::getView()const
+{
+   return theAnnotationSource->getView();
+}
+
+bool ossimOgrGdalTileSource::setView(ossimObject*  baseObject)
+{
+   return theAnnotationSource->setView(baseObject);
+}
+
+void ossimOgrGdalTileSource::setProperty(ossimRefPtr<ossimProperty> property)
+{
+   if(theAnnotationSource.valid())
+   {
+      theAnnotationSource->setProperty(property);
+   }
+}
+
+ossimRefPtr<ossimProperty> ossimOgrGdalTileSource::getProperty(const ossimString& name)const
+{
+   if(theAnnotationSource.valid())
+   {
+      return theAnnotationSource->getProperty(name);
+   }
+   
+   return 0;
+}
+
+void ossimOgrGdalTileSource::getPropertyNames(std::vector<ossimString>& propertyNames)const
+{
+   if(theAnnotationSource.valid())
+   {
+      theAnnotationSource->getPropertyNames(propertyNames); 
+   }
+}
+
+std::multimap<long, ossimAnnotationObject*> ossimOgrGdalTileSource::getFeatureTable()
+{
+  if(theAnnotationSource.valid())
+  {
+    return theAnnotationSource->getFeatureTable();
+  }
+  return std::multimap<long, ossimAnnotationObject*>();
+}
+
+void ossimOgrGdalTileSource::setQuery(const ossimString& query)
+{
+  if (theAnnotationSource.valid())
+  {
+    theAnnotationSource->setQuery(query);
+  }
+}
+
+void ossimOgrGdalTileSource::setGeometryBuffer(ossim_float64 distance, ossimUnitType type)
+{
+   if (theAnnotationSource.valid())
+   {
+      theAnnotationSource->setGeometryBuffer(distance, type);
+   }
+}
+
+bool ossimOgrGdalTileSource::setCurrentEntry(ossim_uint32 entryIdx)
+{
+   if (theAnnotationSource.valid())
+   {
+      return theAnnotationSource->setCurrentEntry(entryIdx);
+   }
+   return false;
+}
diff --git a/ossim_plugins/gdal/ossimOgrGdalTileSource.h b/ossim_plugins/gdal/ossimOgrGdalTileSource.h
new file mode 100644
index 0000000..215d198
--- /dev/null
+++ b/ossim_plugins/gdal/ossimOgrGdalTileSource.h
@@ -0,0 +1,207 @@
+//*******************************************************************
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author:  Garrett Potts
+//
+// Description:
+//
+// Contains class definition for the class "ossimOgrGdalTileSource".
+// ossimOgrGdalTileSource is derived from ImageHandler which is derived from
+// TileSource.
+//
+//*******************************************************************
+//  $Id: ossimOgrGdalTileSource.h 23664 2015-12-14 14:17:27Z dburken $
+
+#ifndef ossimOgrGdalTileSource_HEADER
+#define ossimOgrGdalTileSource_HEADER 1
+
+#include <vector>
+#include <list>
+#include <map>
+
+#include <ossimGdalOgrVectorAnnotation.h>
+#include "../ossimPluginConstants.h"
+#include <ossim/imaging/ossimImageHandler.h>
+#include <ossim/imaging/ossimEsriShapeFileInterface.h>
+#include <ossim/base/ossimIrect.h>
+#include <ossim/base/ossimViewInterface.h>
+
+class ossimGdalOgrVectorAnnotation;
+class ossimProjection;
+class ossimMapProjection;
+class ossimImageProjectionModel;
+class ossimOgrGdalLayerNode;
+class ossimOgrGdalFeatureNode;
+class ossimAnnotationObject;
+
+class OSSIM_PLUGINS_DLL ossimOgrGdalTileSource :
+   public ossimImageHandler,
+   public ossimViewInterface,
+   public ossimEsriShapeFileInterface
+{
+public:
+   ossimOgrGdalTileSource();
+   virtual ~ossimOgrGdalTileSource();
+
+   virtual void close();
+
+   /**
+    *  @return Returns true on success, false on error.
+    *
+    *  @note This method relies on the data member ossimImageData::theImageFile
+    *  being set.  Callers should do a "setFilename" prior to calling this
+    *  method or use the ossimImageHandler::open that takes a file name and an
+    *  entry index.
+    */      
+   virtual bool open();
+
+   /*!
+    *  Returns a pointer to a tile given an origin representing the upper
+    *  left corner of the tile to grab from the image.
+    *  Satisfies pure virtual from TileSource class.
+    */
+   virtual ossimRefPtr<ossimImageData> getTile(const ossimIrect& tileRect,
+                                               ossim_uint32 resLevel=0);
+
+   /*!
+    *  Returns the number of bands in the image.
+    *  Satisfies pure virtual from ImageHandler class.
+    */
+   virtual ossim_uint32 getNumberOfInputBands() const;
+
+    /*!
+    * Returns the number of bands in a tile returned from this TileSource.
+    * Note: we are supporting sources that can have multiple data objects.
+    * If you want to know the scalar type of an object you can pass in the 
+    */
+   virtual ossim_uint32 getNumberOfOutputBands() const;
+  
+   /*!
+    *  Returns the number of bands in the image.
+    *  Satisfies pure virtual from ImageHandler class.
+    */
+   virtual ossim_uint32 getNumberOfLines(ossim_uint32 reduced_res_level = 0) const;
+
+   /*!
+    *  Returns the number of bands available from an image.
+    *  Satisfies pure virtual from ImageHandler class.
+    */
+   virtual ossim_uint32 getNumberOfSamples(ossim_uint32 reduced_res_level = 0) const;
+
+   /*!
+    * Returns the number of reduced resolution data sets (rrds).
+    * 
+    * Note:  Shape files should never have reduced res sets so this method is
+    * returns "8" to avoid the question of "Do you want to build res sets".
+    */
+   virtual ossim_uint32 getNumberOfDecimationLevels() const;
+
+   /*!
+    * Returns the zero based image rectangle for the reduced resolution data
+    * set (rrds) passed in.  Note that rrds 0 is the highest resolution rrds.
+    */
+   virtual ossimIrect getImageRectangle(ossim_uint32 reduced_res_level = 0) const;
+
+   /*!
+    * Method to save the state of an object to a keyword list.
+    * Return true if ok or false on error.
+    */
+   virtual bool saveState(ossimKeywordlist& kwl,
+                          const char* prefix=0)const;
+
+   /*!
+    * Method to the load (recreate) the state of an object from a keyword
+    * list.  Return true if ok or false on error.
+    */
+   virtual bool loadState(const ossimKeywordlist& kwl,
+                          const char* prefix=0);
+   
+   //! Returns the image geometry object associated with this tile source or NULL if non defined.
+   //! The geometry contains full-to-local image transform as well as projection (image-to-world)
+   virtual ossimRefPtr<ossimImageGeometry> getInternalImageGeometry() const;
+
+   /*!
+    * Returns the output pixel type of the tile source.
+    */
+   virtual ossimScalarType getOutputScalarType() const;
+
+   /*!
+    * Returns the width of the output tile.
+    */
+   virtual ossim_uint32 getTileWidth() const;
+   
+   /*!
+    * Returns the height of the output tile.
+    */
+   virtual ossim_uint32 getTileHeight() const;
+
+   /*!
+    * Returns the tile width of the image or 0 if the image is not tiled.
+    * Note: this is not the same as the ossimImageSource::getTileWidth which
+    * returns the output tile width which can be different than the internal
+    * image tile width on disk.
+    */
+   virtual ossim_uint32 getImageTileWidth() const;
+
+   /*!
+    * Returns the tile width of the image or 0 if the image is not tiled.
+    * Note: this is not the same as the ossimImageSource::getTileWidth which
+    * returns the output tile width which can be different than the internal
+    * image tile width on disk.
+    */
+   virtual ossim_uint32 getImageTileHeight() const;   
+
+   virtual bool isOpen()const;
+   
+   virtual double getNullPixelValue(ossim_uint32 band=0)const;
+
+   virtual double getMinPixelValue(ossim_uint32 band=0)const;
+      
+   virtual double getMaxPixelValue(ossim_uint32 band=0)const;
+
+   virtual ossimObject* getView();
+
+   virtual const ossimObject* getView()const;
+
+   /**
+    * @brief Sets the output view.
+    *
+    * This will transform the shape file points to the view passed in.
+    *
+    * @param baseObject This can be a ossimProjection or an
+    * ossimImageProjectionModel.  If ossimImageProjectionModel this will
+    * transform world points to line sample; then, convert any
+    * line sample to the correct target rrds point.  The target rrds is
+    * set via ossimImageModel::setTargetRrds.
+    *
+    * @param ownsItFlag If true the memory will be handled for baseObject by
+    * the underlying code.
+    *
+    * @return True on success, false on error.
+    *
+    * @see ossimImageModel::setTargetRrds
+    */
+   virtual bool setView(ossimObject*  baseObject);
+
+   virtual void setProperty(ossimRefPtr<ossimProperty> property);
+   virtual ossimRefPtr<ossimProperty> getProperty(const ossimString& name)const;
+   virtual void getPropertyNames(std::vector<ossimString>& propertyNames)const;
+
+   virtual std::multimap<long, ossimAnnotationObject*> getFeatureTable(); 
+
+   virtual void setQuery(const ossimString& query);
+
+   virtual void setGeometryBuffer(ossim_float64 distance, ossimUnitType type);
+
+   virtual bool setCurrentEntry(ossim_uint32 entryIdx);
+
+private:
+   ossimRefPtr<ossimGdalOgrVectorAnnotation> theAnnotationSource;
+TYPE_DATA
+};
+
+#endif
+
diff --git a/ossim_plugins/gdal/ossimOgrInfo.cpp b/ossim_plugins/gdal/ossimOgrInfo.cpp
new file mode 100644
index 0000000..7914b20
--- /dev/null
+++ b/ossim_plugins/gdal/ossimOgrInfo.cpp
@@ -0,0 +1,664 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author:  Mingjie Su
+//
+// Description: Ogr Info object.
+// 
+//----------------------------------------------------------------------------
+// $Id: ossimOgrInfo.cpp 2645 2011-05-26 15:21:34Z oscar.kramer $
+
+#include <ossimOgrInfo.h>
+#include <ossim/base/ossimTrace.h>
+#include <ossim/base/ossimKeywordlist.h>
+
+#include <ogr_api.h>
+
+#include <fstream>
+#include <iostream>
+#include <iomanip>
+#include <sstream>
+
+// Static trace for debugging
+static ossimTrace traceDebug("ossimOgrInfo:debug");
+static ossimTrace traceDump("ossimOgrInfo:dump"); // This will dump offsets.
+
+ossimString getKeyValue(ossimString metaPrefix,
+                        ossimString prefix,
+                        ossimString metaNameValue,
+                        ossimKeywordlist& kwl)
+{
+  if (!metaNameValue.contains("{") && !metaNameValue.contains("}"))
+  {
+    std::vector<int> indexVector;
+    ossimString name = metaNameValue.split(":")[0].downcase().trim().substitute(" ", "_", true);
+    ossimString keyValue = ossimString(metaPrefix + prefix + name);
+    std::vector<ossimString> allMatchKeys;
+    kwl.findAllKeysThatMatch(allMatchKeys, keyValue);
+
+    if (allMatchKeys.size() == 0)
+    {
+      return name;
+    }
+    else
+    {
+      for (ossim_uint32 i = 0; i < allMatchKeys.size(); i++)
+      {
+        ossimString keyMatchValue = allMatchKeys[i];
+        ossimString intValue = keyMatchValue.after(keyValue);
+        if (!intValue.empty())
+        {
+          indexVector.push_back(intValue.toInt());
+        }
+      }
+      if (indexVector.size() == 0) //only found one entry, e.g vpf.cat.Coverage_name
+      {
+        const char* tmpValue = kwl.find(keyValue);
+        ossimString metaValue = tmpValue;
+        kwl.remove(keyValue);
+        ossimString newPrefix = ossimString(prefix + name + ossimString::toString(0));
+        kwl.add(metaPrefix, 
+                newPrefix,
+                metaValue,
+                true);
+        return ossimString(name + ossimString::toString(1));
+      }
+      else // e.g vpf.cat.Coverage_name0 found
+      {
+        double max = 0; 
+        for (ossim_uint32 i = 0; i < indexVector.size(); i++)
+        {
+          if (max < indexVector.at(i)) 
+          {
+            max = indexVector.at(i);
+          }
+        }
+        return ossimString(name + ossimString::toString(max+1));
+      }
+    }
+  }
+  return ossimString("");
+}
+
+ossimOgrInfo::ossimOgrInfo()
+   : ossimInfoBase(),
+     m_file(),
+     m_ogrDatasource(0),
+     m_ogrDriver(0)
+{
+}
+
+ossimOgrInfo::~ossimOgrInfo()
+{
+  if (m_ogrDatasource != NULL)
+  {
+    OGRDataSource::DestroyDataSource(m_ogrDatasource);
+    m_ogrDatasource = 0;
+  }
+}
+
+bool ossimOgrInfo::open(const ossimFilename& file)
+{
+   if ( m_ogrDatasource )
+   {
+      OGRDataSource::DestroyDataSource(m_ogrDatasource);
+      m_ogrDatasource = 0;
+   }
+
+   // Below interface removed in gdal.
+   // m_file = file;
+   // m_ogrDatasource = OGRSFDriverRegistrar::Open(file.c_str(), false, &m_ogrDriver);
+
+   m_ogrDatasource = (OGRDataSource*) OGROpen( file.c_str(), false, NULL );
+   if ( m_ogrDatasource )
+   {
+      m_ogrDriver = (OGRSFDriver*) m_ogrDatasource->GetDriver();
+      if ( m_ogrDriver )
+      {
+         m_file = file;
+      }
+
+      if ( !m_ogrDriver ) 
+      {
+         OGRDataSource::DestroyDataSource( m_ogrDatasource );
+         m_ogrDatasource = 0;
+      }
+   }
+
+   return ( m_ogrDatasource ? true : false );
+}
+
+void ossimOgrInfo::parseMetadata(ossimString metaData, 
+                                 ossimKeywordlist& kwl, 
+                                 ossimString metaPrefix) const
+{
+   std::vector<ossimString> metaList = metaData.split("\n");
+   bool isCat = false;	
+   bool isLat = false;
+   bool isDht = false;
+   bool isLht = false;
+   bool isGrt = false;
+   bool isDqt = false;
+   bool isFcs = false;
+   bool isFca = false;
+
+   ossimString catKeyPrefix = "cat.";
+   ossimString latKeyPrefix = "lat.";
+   ossimString dhtKeyPrefix = "dht.";
+   ossimString lhtKeyPrefix = "lht.";
+   ossimString grtKeyPrefix = "grt.";
+   ossimString dqtKeyPrefix = "dqt.";
+   ossimString fcsKeyPrefix = "fcs.";
+   ossimString fcaKeyPrefix = "fca.";
+   
+   for (ossim_uint32 i = 0; i < metaList.size(); i++)
+   {
+     ossimString metaNameValue = metaList[i].trim();
+     ossimString metaStr = metaList[i].downcase().trim();
+     if (metaStr.contains("(cat)"))
+     {
+       isCat = true;
+       isLat = false; //set others to false
+       isDht = false;
+       isLht = false;
+       isGrt = false;
+       isDqt = false;
+       isFcs = false;
+       isFca = false;
+       continue;
+     }
+     if (isCat)
+     {
+       if (metaStr.contains(":") && 
+           !metaStr.contains("(lat)") && 
+           !metaStr.contains("(dht)") && 
+           !metaStr.contains("(lht)") && 
+           !metaStr.contains("(grt)") && 
+           !metaStr.contains("(dqt)") && 
+           !metaStr.contains("(fcs)") && 
+           !metaStr.contains("} } }  { family"))
+       {
+         ossimString keyValue = getKeyValue(metaPrefix, catKeyPrefix, 
+                                            metaNameValue, kwl);
+         ossimString metaValue = metaNameValue.split(":")[1].trim();
+         ossimString prefix = ossimString(catKeyPrefix + keyValue);
+         kwl.add(metaPrefix,
+           prefix,
+           metaValue,
+           false);
+       }
+     }
+
+     if (metaStr.contains("(lat)"))
+     {
+       isLat = true;
+       isCat = false; //set others to false
+       isDht = false;
+       isLht = false;
+       isGrt = false;
+       isDqt = false;
+       isFcs = false;
+       isFca = false;
+       continue;
+     }
+     if (isLat)
+     {
+       if (metaStr.contains(":") && 
+         !metaStr.contains("(cat)") && 
+         !metaStr.contains("(dht)") && 
+         !metaStr.contains("(lht)") && 
+         !metaStr.contains("(grt)") && 
+         !metaStr.contains("(dqt)") && 
+         !metaStr.contains("(fcs)") && 
+         !metaStr.contains("} } }  { family"))
+       {
+         //do nothing. no need for lat info for now.
+       }
+     }
+
+     if (metaStr.contains("(dht)"))
+     {
+       isDht = true;
+       isCat = false;
+       isLat = false;
+       isLht = false;
+       isGrt = false;
+       isDqt = false;
+       isFcs = false;
+       isFca = false;
+       continue;
+     }
+     if (isDht)
+     {
+       if (metaStr.contains(":") && 
+         !metaStr.contains("(lat)") && 
+         !metaStr.contains("(cat)") && 
+         !metaStr.contains("(lht)") && 
+         !metaStr.contains("(grt)") && 
+         !metaStr.contains("(dqt)") && 
+         !metaStr.contains("(fcs)") && 
+         !metaStr.contains("} } }  { family"))
+       {
+         ossimString keyValue = getKeyValue(metaPrefix, dhtKeyPrefix, 
+                                            metaNameValue, kwl);
+         ossimString metaValue = metaNameValue.split(":")[1].trim();
+         ossimString prefix = ossimString(dhtKeyPrefix + keyValue);
+         kwl.add(metaPrefix,
+           prefix,
+           metaValue,
+           false);
+       }
+     }
+
+     if (metaStr.contains("(lht)"))
+     {
+       isLht = true;
+       isDht = false;
+       isCat = false;
+       isLat = false;
+       isGrt = false;
+       isDqt = false;
+       isFcs = false;
+       isFca = false;
+       continue;
+     }
+     if (isLht)
+     {
+       if (metaStr.contains(":") && 
+         !metaStr.contains("(lat)") && 
+         !metaStr.contains("(dht)") && 
+         !metaStr.contains("(cat)") && 
+         !metaStr.contains("(grt)") && 
+         !metaStr.contains("(dqt)") && 
+         !metaStr.contains("(fcs)") && 
+         !metaStr.contains("} } }  { family"))
+       {
+         ossimString keyValue = getKeyValue(metaPrefix, lhtKeyPrefix, 
+                                            metaNameValue, kwl);
+         ossimString metaValue = metaNameValue.split(":")[1].trim();
+         ossimString prefix = ossimString(lhtKeyPrefix + keyValue);
+         kwl.add(metaPrefix,
+           prefix,
+           metaValue,
+           false);
+       }
+     }
+
+     if (metaStr.contains("(grt)"))
+     {
+       isGrt = true;
+       isLht = false;
+       isDht = false;
+       isCat = false;
+       isLat = false;
+       isDqt = false;
+       isFcs = false;
+       isFca = false;
+       continue;
+     }
+     if (isGrt)
+     {
+       if (metaStr.contains(":") && 
+         !metaStr.contains("(lat)") && 
+         !metaStr.contains("(dht)") && 
+         !metaStr.contains("(lht)") && 
+         !metaStr.contains("(cat)") && 
+         !metaStr.contains("(dqt)") && 
+         !metaStr.contains("(fcs)") && 
+         !metaStr.contains("} } }  { family"))
+       {
+         ossimString keyValue = getKeyValue(metaPrefix, grtKeyPrefix, 
+                                            metaNameValue, kwl);
+         ossimString metaValue = metaNameValue.split(":")[1].trim();
+         ossimString prefix = ossimString(grtKeyPrefix + keyValue);
+         kwl.add(metaPrefix,
+           prefix,
+           metaValue,
+           false);
+       }
+     }
+
+     if (metaStr.contains("(dqt)"))
+     {
+       isDqt = true;
+       isGrt = false;
+       isLht = false;
+       isDht = false;
+       isCat = false;
+       isLat = false;
+       isFcs = false;
+       isFca = false;
+       continue;
+     }
+     if (isDqt)
+     {
+       if (metaStr.contains(":") && 
+         !metaStr.contains("(lat)") && 
+         !metaStr.contains("(dht)") && 
+         !metaStr.contains("(lht)") && 
+         !metaStr.contains("(grt)") && 
+         !metaStr.contains("(cat)") && 
+         !metaStr.contains("(fcs)") && 
+         !metaStr.contains("} } }  { family"))
+       {
+         ossimString keyValue = getKeyValue(metaPrefix, dqtKeyPrefix, 
+                                            metaNameValue, kwl);
+         ossimString metaValue = metaNameValue.split(":")[1].trim();
+         ossimString prefix = ossimString(dqtKeyPrefix + keyValue);
+         kwl.add(metaPrefix,
+           prefix,
+           metaValue,
+           false);
+       }
+     }
+
+     if (metaStr.contains("(fcs)"))
+     {
+       isFcs = true;
+       isDqt = false;
+       isGrt = false;
+       isLht = false;
+       isDht = false;
+       isCat = false;
+       isLat = false;
+       isFca = false;
+       continue;
+     }
+     if (isFcs)
+     {
+       if (metaStr.contains(":") && 
+         !metaStr.contains("(lat)") && 
+         !metaStr.contains("(dht)") && 
+         !metaStr.contains("(lht)") && 
+         !metaStr.contains("(grt)") && 
+         !metaStr.contains("(dqt)") && 
+         !metaStr.contains("(cat)") && 
+         !metaStr.contains("} } }  { family"))
+       {
+         ossimString keyValue = getKeyValue(metaPrefix, fcsKeyPrefix, 
+                                            metaNameValue, kwl);
+         ossimString metaValue = metaNameValue.split(":")[1].trim();
+         ossimString prefix = ossimString(fcsKeyPrefix + keyValue);
+         kwl.add(metaPrefix,
+           prefix,
+           metaValue,
+           false);
+       }
+     }
+
+     if (metaStr.contains("} } }  { family"))
+     {
+       isFca = true;
+       isDqt = false;
+       isGrt = false;
+       isLht = false;
+       isDht = false;
+       isCat = false;
+       isLat = false;
+       isFcs = false;
+     }
+     if (isFca)
+     {
+       if (!metaStr.contains("(lat)") && 
+         !metaStr.contains("(dht)") && 
+         !metaStr.contains("(lht)") && 
+         !metaStr.contains("(grt)") && 
+         !metaStr.contains("(dqt)") && 
+         !metaStr.contains("(fcs)"))
+       {
+         std::vector<ossimString> fcaTmpVector = metaNameValue.split("}}");
+         ossimString fcaClassName;
+         for (ossim_uint32 i = 0; i < fcaTmpVector.size(); i++)
+         {
+           ossimString fcaTemp = fcaTmpVector[i].trim();
+           if (!fcaTemp.empty())
+           {
+             if (fcaTemp.contains("family"))
+             {
+               if (fcaTemp.split(" ").size() > 1)
+               {
+                 fcaClassName = fcaTemp.split(" ")[2].trim();
+               }
+             }
+             else
+             {
+               std::vector<ossimString> fcaValues;
+               if (fcaTemp.contains("<Grassland>displaymetadata {"))
+               {
+                 ossimString displaymetadataVector = fcaTemp.after("<Grassland>displaymetadata {").trim();
+                 if (!displaymetadataVector.empty())
+                 {
+                   fcaValues = displaymetadataVector.split("{");
+                 }
+               }
+               else
+               {
+                 fcaValues = fcaTemp.split("{");
+               }
+
+               if (fcaValues.size() > 2)
+               {
+                 ossimString fcaKey = fcaValues[1].trim();
+                 ossimString fcaValue = fcaValues[2].trim();
+
+                 ossimString prefix = ossimString(fcaKeyPrefix + fcaClassName + "." + fcaKey);
+                 kwl.add(metaPrefix,
+                   prefix,
+                   fcaValue,
+                   false);
+               }
+             }
+           }          
+         }
+       }
+     }
+   }
+}
+
+bool ossimOgrInfo::getKeywordlist(ossimKeywordlist& kwl) const
+{  
+  if (m_ogrDatasource != NULL)  
+  {
+    ossimString driverName = getDriverName(ossimString(GDALGetDriverShortName(m_ogrDriver)).downcase());
+
+    ossimString metaPrefix = ossimString(driverName + ".");
+
+    //get meta data
+    ossimString strValue;
+    char** metaData = 0; // tmp drb m_ogrDatasource->GetMetadata("metadata");
+    ossimString keyName = "tableinfo";
+    size_t nLen = strlen(keyName.c_str());
+    if (metaData != NULL && driverName == "vpf")
+    {
+      while(*metaData != NULL)
+      {
+        if (EQUALN(*metaData, keyName.c_str(), nLen)
+          && ( (*metaData)[nLen] == '=' || 
+          (*metaData)[nLen] == ':' ) )
+        {
+          strValue = (*metaData)+nLen+1;
+        }
+        metaData++;
+      }
+
+      if (!strValue.empty())
+     {
+        parseMetadata(strValue, kwl, metaPrefix);
+      }
+   }
+
+    //get geometry data
+    ossimString geomType;
+    int layerCount = m_ogrDatasource->GetLayerCount();
+    ossimString prefixInt = ossimString(metaPrefix + "layer");
+    for(int i = 0; i < layerCount; ++i)
+    {
+      ossimString prefix = prefixInt + ossimString::toString(i) + ".";
+      ossimString specialPrefix = "layer" + ossimString::toString(i) + ".";
+
+      OGRLayer* layer = m_ogrDatasource->GetLayer(i);
+      if(layer)
+      {
+        //get feature count and geometry type
+        int featureCount = layer->GetFeatureCount();
+        const char* layerName = layer->GetLayerDefn()->GetName();
+
+        OGRFeature* feature = layer->GetFeature(0);
+        if(feature)
+        {
+          OGRGeometry* geom = feature->GetGeometryRef(); 
+          if(geom)
+          {
+            switch(geom->getGeometryType())
+            {
+            case wkbMultiPoint:
+            case wkbMultiPoint25D:
+              {
+                geomType = "Multi Points";
+                break;
+              }
+            case wkbPolygon25D:
+            case wkbPolygon:
+              {
+                geomType = "Polygon";
+                break;
+              }
+            case wkbLineString25D:
+            case wkbLineString:
+              {
+                geomType = "LineString";
+                break;
+              }
+            case wkbPoint:
+            case wkbPoint25D:
+              {
+                geomType = "Points";
+                break;
+              }
+            case wkbMultiPolygon25D:
+            case wkbMultiPolygon:
+              {
+                geomType = "Multi Polygon";
+                break;
+
+              }
+            default:
+              {
+                geomType = "Unknown Type";
+                break;
+              }
+            }
+          }
+        }//end if feature
+        OGRFeature::DestroyFeature(feature);
+
+        kwl.add(specialPrefix,
+          "features",
+          featureCount,
+          true);
+
+        //get all attribute fields
+        OGRFeatureDefn* featureDefn = layer->GetLayerDefn();
+        if (featureDefn)
+        {
+          for(int iField = 0; iField < featureDefn->GetFieldCount(); iField++ )
+          {
+            OGRFieldDefn* fieldDefn = featureDefn->GetFieldDefn(iField);
+            ossimString fieldType;
+            if (fieldDefn)
+            {
+              ossimString fieldName = ossimString(fieldDefn->GetNameRef());
+              if( fieldDefn->GetType() == OFTInteger )
+              {
+                fieldType = "Integer";
+              }
+              else if( fieldDefn->GetType() == OFTReal )
+              {
+                fieldType = "Real";
+              }
+              else if( fieldDefn->GetType() == OFTString )
+              {
+                fieldType = "String";
+              }
+              else if ( fieldDefn->GetType() == OFTWideString)
+              {
+                fieldType = "WideString";
+              }
+              else if ( fieldDefn->GetType() == OFTBinary )
+              {
+                fieldType = "Binary";
+              }
+              else if ( fieldDefn->GetType() == OFTDate )
+              {
+                fieldType = "Date";
+              }
+              else if ( fieldDefn->GetType() == OFTTime )
+              {
+                fieldType = "Time";
+              }
+              else if ( fieldDefn->GetType() == OFTDateTime )
+              {
+                fieldType = "DateTime";
+              }
+              else
+              {
+                fieldType = "String";
+              }
+
+              ossimString fieldInfo = ossimString(fieldName + " (" + fieldType + ")");
+
+              ossimString colPrefix = prefix + "column" + ossimString::toString(iField);
+              kwl.add(colPrefix,
+                "",
+                fieldInfo,
+                true);
+            }
+          }
+        }
+
+        kwl.add(specialPrefix,
+          "name",
+          layerName,
+          true);
+
+        kwl.add(specialPrefix,
+          "geometry",
+          geomType,
+          true);
+      } //end if layer
+    }// end i
+    return true;
+  }// end if datasource
+  return false;
+}
+
+std::ostream& ossimOgrInfo::print(std::ostream& out) const
+{
+  static const char MODULE[] = "ossimOgrInfo::print";
+  if (traceDebug())
+  {    
+     ossimNotify(ossimNotifyLevel_DEBUG)
+      << MODULE << " DEBUG Entered...\n";
+  }
+  return out;
+}
+
+ossimString ossimOgrInfo::getDriverName(ossimString driverName) const
+{
+  if (driverName == "esri shapefile")
+  {
+    return "shp";
+  }
+  else if (driverName == "ogdi")
+  {
+    return "vpf";
+  }
+  else
+  {
+    return driverName;
+  }
+}
+
diff --git a/ossim_plugins/gdal/ossimOgrInfo.h b/ossim_plugins/gdal/ossimOgrInfo.h
new file mode 100644
index 0000000..78e0a0a
--- /dev/null
+++ b/ossim_plugins/gdal/ossimOgrInfo.h
@@ -0,0 +1,86 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author:  Mingjie Su
+//
+// Description: Gdal Ogr Info object.
+// 
+//----------------------------------------------------------------------------
+// $Id: ossimOgrInfo.h 2645 2011-05-26 15:21:34Z oscar.kramer $
+#ifndef ossimOgrInfo_HEADER
+#define ossimOgrInfo_HEADER 1
+
+#include <ossim/base/ossimConstants.h>
+#include <ossim/support_data/ossimInfoBase.h>
+#include <ossim/base/ossimFilename.h>
+
+//OGR Includes
+// #include <ogrsf_frmts/ogrsf_frmts.h>
+#include <ogrsf_frmts.h>
+#include <gdal.h>
+
+#include <iosfwd>
+#include <string>
+#include <vector>
+
+class ossimKeywordlist;
+
+/**
+ * @brief Ogr info class.
+ *
+ * Encapsulates the Ogr functionality.
+ */
+class ossimOgrInfo : public ossimInfoBase
+{
+public:
+
+   /** default constructor */
+   ossimOgrInfo();
+
+   /** virtual destructor */
+   virtual ~ossimOgrInfo();
+
+   /**
+    * @brief open method.
+    *
+    * @param file File name to open.
+    * The example of SDE file name: SDE:server,instance,database,username,password,layername
+    * e.g ossim-info -p -d SDE:SPATCDT001,5151,SDE,SADATABASE,SAPASSWORD,SATABLENAME
+    *
+    * The example of VPF file name: C:/vpfdata/mpp1/vmaplv0/eurnasia/cat
+    * e.g ossim-info -p -d D:/OSSIM_Data/vpf_data/WVSPLUS/WVS120M/CAT
+    *
+    * @return true on success false on error.
+    */
+   virtual bool open(const ossimFilename& file);
+
+   /**
+    * Print method.
+    *
+    * @param out Stream to print to.
+    * 
+    * @return std::ostream&
+    */
+   virtual std::ostream& print(std::ostream& out) const;
+
+   virtual bool getKeywordlist(ossimKeywordlist& kwl)const;
+
+   private: 
+     ossimString getDriverName(ossimString driverName)const;
+
+     /**
+    * Parse the VPF metadata
+    *
+    */
+     void parseMetadata(ossimString metaData, ossimKeywordlist& kwl, ossimString metaPrefix)const;
+
+     ossimFilename  m_file;
+     OGRDataSource* m_ogrDatasource;
+     OGRSFDriver*   m_ogrDriver;
+};
+
+#endif /* End of "#ifndef ossimOgrInfo_HEADER" */
+
diff --git a/ossim_plugins/gdal/ossimOgrVectorTileSource.cpp b/ossim_plugins/gdal/ossimOgrVectorTileSource.cpp
new file mode 100644
index 0000000..e6b04a3
--- /dev/null
+++ b/ossim_plugins/gdal/ossimOgrVectorTileSource.cpp
@@ -0,0 +1,513 @@
+//*******************************************************************
+//
+// License:  See top level LICENSE.txt file.
+//
+// Author:  Mingjie Su
+//
+// Description:
+//
+// Contains class implementaiton for the class "ossimOgrVectorTileSource".
+//
+//*******************************************************************
+//  $Id: ossimOgrVectorTileSource.cpp 1347 2010-08-23 17:03:06Z oscar.kramer $
+
+#include <ossimOgrVectorTileSource.h>
+#include <ossimOgcWktTranslator.h>
+#include <ossimGdalType.h>
+
+#include <ossim/base/ossimTrace.h>
+#include <ossim/base/ossimNotify.h>
+#include <ossim/base/ossimIpt.h>
+#include <ossim/base/ossimDpt.h>
+#include <ossim/base/ossimFilename.h>
+#include <ossim/base/ossimKeywordlist.h>
+#include <ossim/base/ossimKeywordNames.h>
+#include <ossim/imaging/ossimImageGeometry.h>
+#include <ossim/projection/ossimProjectionFactoryRegistry.h>
+#include <ossim/projection/ossimEquDistCylProjection.h>
+
+#include <ogr_api.h>
+
+RTTI_DEF1(ossimOgrVectorTileSource,
+          "ossimOgrVectorTileSource",
+          ossimImageHandler);
+
+static ossimOgcWktTranslator wktTranslator;
+static ossimTrace traceDebug("ossimOgrVectorTileSource:debug");
+
+class ossimOgrVectorLayerNode
+{
+public:
+   ossimOgrVectorLayerNode(const ossimDrect& bounds)
+      : theBoundingRect(bounds)
+   {
+   }
+   ~ossimOgrVectorLayerNode()
+   {
+      theGeoImage.release();
+      theGeoImage = 0;
+   }
+
+   bool intersects(const ossimDrect& rect)const
+   {
+      return theBoundingRect.intersects(rect);
+   }
+
+   bool intersects(double minX, double minY,
+                   double maxX, double maxY)const
+   {
+      return theBoundingRect.intersects(ossimDrect(minX, minY, maxX, maxY));
+   }
+ 
+   void setGeoImage(ossimRefPtr<ossimImageGeometry> image)
+   {
+      theGeoImage = image;
+   }
+
+   ossimDrect theBoundingRect;  //world
+   ossimRefPtr<ossimImageGeometry> theGeoImage;
+};
+
+//*******************************************************************
+// Public Constructor:
+//*******************************************************************
+ossimOgrVectorTileSource::ossimOgrVectorTileSource()
+   :ossimImageHandler(),
+    theDataSource(0),
+    theImageBound(),
+    theBoundingExtent()
+{
+}
+
+//*******************************************************************
+// Destructor:
+//*******************************************************************
+ossimOgrVectorTileSource::~ossimOgrVectorTileSource()
+{
+   close();
+}
+
+//*******************************************************************
+// Public Method:
+//*******************************************************************
+bool ossimOgrVectorTileSource::open()
+{
+   const char* MODULE = "ossimOgrVectorTileSource::open";
+
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_NOTICE)
+         << MODULE << " entered...\nFile: " << theImageFile.c_str() << std::endl;
+   }
+
+   if(isOpen())
+   {
+      close();
+   }
+  
+   if ( isOgrVectorDataSource() )
+   {
+      //---
+      // Old interface removed in gdal. 
+      // theDataSource = OGRSFDriverRegistrar::Open(theImageFile,
+      //                                            false);
+      //---
+      theDataSource = (OGRDataSource*) OGROpen( theImageFile.c_str(), false, NULL );
+      if (theDataSource)
+      {
+         int layerCount = theDataSource->GetLayerCount();
+         theLayerVector.resize(layerCount);
+         if(layerCount)
+         {
+            for(int i = 0; i < layerCount; ++i)
+            {
+               OGRLayer* layer = theDataSource->GetLayer(i);
+               if(layer)
+               {
+                  OGRSpatialReference* spatialReference = layer->GetSpatialRef();
+                  
+                  if(!spatialReference)
+                  {
+                     if(traceDebug())
+                     {
+                        ossimNotify(ossimNotifyLevel_NOTICE)
+                           << MODULE
+                           << " No spatial reference given, assuming geographic"
+                           << endl;
+                     }
+                  }
+               }
+               else
+               {
+                  if(traceDebug())
+                  {
+                     ossimNotify(ossimNotifyLevel_NOTICE)
+                        
+                        << MODULE
+                        << " layer " << i << " is null." << endl;
+                  }
+               }
+               
+               if (layer)
+               {
+                  layer->GetExtent(&theBoundingExtent, true);
+                  
+                  ossimRefPtr<ossimProjection> proj = createProjFromReference(layer->GetSpatialRef());
+                  ossimRefPtr<ossimImageGeometry> imageGeometry = 0;
+                  bool isDefaultProjection = false;
+                  if(proj.valid())
+                  {
+                     imageGeometry = new ossimImageGeometry(0, proj.get());
+                  }
+                  
+                  ossimMapProjection* mapProj = 0;
+                  if(imageGeometry.valid())
+                  {
+                     mapProj = PTR_CAST(ossimMapProjection, imageGeometry->getProjection());
+                  }
+                  else
+                  {
+                     mapProj = createDefaultProj();
+                     imageGeometry = new ossimImageGeometry(0, mapProj);
+                     isDefaultProjection = true;
+                  }
+
+                  if(mapProj)
+                  {
+                     ossimDrect rect(theBoundingExtent.MinX,
+                                     theBoundingExtent.MaxY,
+                                     theBoundingExtent.MaxX,
+                                     theBoundingExtent.MinY,
+                                     OSSIM_RIGHT_HANDED);
+            
+                     std::vector<ossimGpt> points;
+                     if (isDefaultProjection || mapProj->isGeographic())
+                     {
+                        ossimGpt g1(rect.ul().y, rect.ul().x);
+                        ossimGpt g2(rect.ur().y, rect.ur().x);
+                        ossimGpt g3(rect.lr().y, rect.lr().x);
+                        ossimGpt g4(rect.ll().y, rect.ll().x);
+
+                        points.push_back(g1);
+                        points.push_back(g2);
+                        points.push_back(g3);
+                        points.push_back(g4);
+                     }
+                     else
+                     {
+                        ossimGpt g1 = mapProj->inverse(rect.ul());
+                        ossimGpt g2 = mapProj->inverse(rect.ur());
+                        ossimGpt g3 = mapProj->inverse(rect.lr());
+                        ossimGpt g4 = mapProj->inverse(rect.ll());
+
+                        points.push_back(g1);
+                        points.push_back(g2);
+                        points.push_back(g3);
+                        points.push_back(g4);
+                     }
+            
+                     std::vector<ossimDpt> rectTmp;
+                     rectTmp.resize(4);
+
+                     for(std::vector<ossimGpt>::size_type index=0; index < 4; ++index)
+                     {
+                        imageGeometry->worldToLocal(points[(int)index], rectTmp[(int)index]);
+                     }
+
+                     ossimDrect rect2 = ossimDrect(rectTmp[0],
+                                                   rectTmp[1],
+                                                   rectTmp[2],
+                                                   rectTmp[3]);
+
+                     theLayerVector[i] = new ossimOgrVectorLayerNode(rect2);
+                     theLayerVector[i]->setGeoImage(imageGeometry);
+
+                     // Initialize the image geometry to the first layer's geometry:
+                     if (i == 0)
+                        theImageGeometry = imageGeometry;
+                  }
+               }
+            }
+               
+         } // if(layerCount)
+         else
+         {
+            OGR_DS_Destroy( theDataSource );
+            theDataSource = 0;
+         }
+            
+      } // Matches: if (theDataSource)
+         
+   } // Matches: if ( isOgrVectorDataSource() )
+   
+   return ( theDataSource ? true : false );
+}
+
+//*******************************************************************
+// Public method:
+//*******************************************************************
+bool ossimOgrVectorTileSource::saveState(ossimKeywordlist& kwl,
+                                         const char* prefix) const
+{
+   for (unsigned int i = 0; i < theLayerVector.size(); i++)
+   {
+      ossimRefPtr<ossimImageGeometry> imageGeometry = theLayerVector[i]->theGeoImage;
+      if(theImageGeometry.valid())
+      {
+         theImageGeometry->saveState(kwl, prefix);
+      }
+   }
+
+   return ossimImageHandler::saveState(kwl, prefix);
+}
+
+//*******************************************************************
+// Public method:
+//*******************************************************************
+bool ossimOgrVectorTileSource::loadState(const ossimKeywordlist& kwl, const char* prefix)
+{
+   bool success = ossimImageHandler::loadState(kwl, prefix);
+   if (success)
+   {
+      theImageGeometry = new ossimImageGeometry();
+      success = theImageGeometry->loadState(kwl, prefix);
+   }
+   return success;
+}
+
+ossim_uint32 ossimOgrVectorTileSource::getImageTileWidth() const
+{
+   return 0;
+}
+
+ossim_uint32 ossimOgrVectorTileSource::getImageTileHeight() const
+{
+   return 0;
+}
+
+ossimRefPtr<ossimImageGeometry> ossimOgrVectorTileSource::getInternalImageGeometry() const
+{
+   return theImageGeometry;
+}
+
+void ossimOgrVectorTileSource::close()
+{
+   for(ossim_uint32 i = 0; i < theLayerVector.size(); ++i)
+   {
+      if(theLayerVector[i])
+      {
+         delete theLayerVector[i];
+      }
+   }
+   
+   theLayerVector.clear();
+   
+   if(theDataSource)
+   {
+      delete theDataSource;
+      theDataSource = 0;
+   }
+}
+
+ossimRefPtr<ossimImageData> ossimOgrVectorTileSource::getTile(
+   const ossimIrect& /* tileRect */, ossim_uint32 /* resLevel */)
+{
+   return 0;
+}
+
+ossim_uint32 ossimOgrVectorTileSource::getNumberOfInputBands() const
+{
+   return 0;
+}
+
+ossim_uint32 ossimOgrVectorTileSource::getNumberOfOutputBands() const
+{
+   return 0;
+}
+
+ossim_uint32 ossimOgrVectorTileSource::getNumberOfLines(ossim_uint32 /* reduced_res_level */ ) const
+{
+   if(theImageBound.hasNans())
+   {
+      return theImageBound.ul().x;
+   }
+   
+   return theImageBound.height();
+}
+
+ossim_uint32 ossimOgrVectorTileSource::getNumberOfSamples(ossim_uint32 /* reduced_res_level */ ) const
+{
+   if(theImageBound.hasNans())
+   {
+      return theImageBound.ul().y;
+   }
+   
+   return theImageBound.width();
+}
+
+ossim_uint32 ossimOgrVectorTileSource::getNumberOfDecimationLevels() const
+{
+   return 32;
+}
+
+ossimIrect ossimOgrVectorTileSource::getImageRectangle(ossim_uint32 /* reduced_res_level */ ) const
+{
+   return theImageBound;
+}
+
+ossimRefPtr<ossimImageGeometry> ossimOgrVectorTileSource::getImageGeometry()
+{
+   return theImageGeometry;
+}
+
+ossimScalarType ossimOgrVectorTileSource::getOutputScalarType() const
+{
+   return OSSIM_SCALAR_UNKNOWN;
+}
+
+ossim_uint32 ossimOgrVectorTileSource::getTileWidth() const
+{
+   return 0;         
+}
+
+ossim_uint32 ossimOgrVectorTileSource::getTileHeight() const
+{
+   return 0;
+}
+
+bool ossimOgrVectorTileSource::isOpen()const
+{
+   return (theDataSource!=0);
+}
+
+bool ossimOgrVectorTileSource::isOgrVectorDataSource()const
+{
+   if (!theImageFile.empty())
+   {
+      if (theImageFile.before(":", 3).upcase() != "SDE" && 
+          theImageFile.before(":", 4).upcase() != "GLTP" && 
+          theImageFile.ext().downcase() != "mdb")
+      {
+         return false;
+      }
+   }
+   else
+   {
+      return false;
+   }
+   
+   return true;
+}
+
+double ossimOgrVectorTileSource::getNullPixelValue(ossim_uint32 /* band */)const
+{
+   return 0.0;
+}
+
+double ossimOgrVectorTileSource::getMinPixelValue(ossim_uint32 /* band */)const
+{
+   return 0.0;
+}
+
+double ossimOgrVectorTileSource::getMaxPixelValue(ossim_uint32 /* band */)const
+{
+   return 0.0;
+}
+
+bool ossimOgrVectorTileSource::setCurrentEntry(ossim_uint32 entryIdx)
+{
+   if(theLayerVector.size() > 0)
+   {
+      if (theLayerVector.size() > entryIdx)
+      {
+         theImageGeometry = 0;
+         theImageBound.makeNan();
+         theImageGeometry = theLayerVector[entryIdx]->theGeoImage;
+         theImageBound = theLayerVector[entryIdx]->theBoundingRect;
+         if (theImageGeometry.valid())
+         {
+            return true;
+         }
+      }
+   }
+   return false;
+}
+
+ossim_uint32 ossimOgrVectorTileSource::getNumberOfEntries() const
+{
+   return theLayerVector.size();
+}
+
+void ossimOgrVectorTileSource::getEntryList(std::vector<ossim_uint32>& entryList) const
+{
+   if (theLayerVector.size() > 0)
+   {
+      for (ossim_uint32 i = 0; i < getNumberOfEntries(); i++)
+      {
+         entryList.push_back(i);
+      }
+   }
+   else
+   {
+      ossimImageHandler::getEntryList(entryList);
+   }
+}
+
+ossimProjection* ossimOgrVectorTileSource::createProjFromReference(OGRSpatialReference* reference)const
+{
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG) << "ossimOgrVectorTileSource::createProjFromReference:   entered........" << std::endl;
+   }
+   if(!reference)
+   {
+      if(traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG) << "ossimOgrVectorTileSource::createProjFromReference:   leaving........" << std::endl;
+      }
+      return 0;
+   }
+   char* wktString = 0;
+   ossimKeywordlist kwl;
+   reference->exportToWkt(&wktString);
+   wktTranslator.toOssimKwl(wktString,
+                            kwl);
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG) << "wktString === " << wktString << std::endl;
+      ossimNotify(ossimNotifyLevel_DEBUG) << "KWL === " << kwl << std::endl;
+   }
+   OGRFree(wktString);
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG) << "ossimOgrVectorTileSource::createProjFromReference:   returning........" << std::endl;
+   }
+   return ossimProjectionFactoryRegistry::instance()->createProjection(kwl);
+}
+
+ossimMapProjection* ossimOgrVectorTileSource::createDefaultProj()
+{
+   ossimEquDistCylProjection* proj = new ossimEquDistCylProjection;
+   
+   ossim_float64 centerLat = (theBoundingExtent.MaxY + theBoundingExtent.MinY ) / 2.0;
+   ossim_float64 centerLon = (theBoundingExtent.MaxX + theBoundingExtent.MinX ) / 2.0;
+   ossim_float64 deltaLat  = theBoundingExtent.MaxY - theBoundingExtent.MinY;
+   
+   // Scale that gives 1024 pixel in the latitude direction.
+   ossim_float64 scaleLat = deltaLat / 1024.0;
+   ossim_float64 scaleLon = scaleLat*ossim::cosd(std::fabs(centerLat)); 
+   ossimGpt origin(centerLat, centerLon, 0.0);
+   ossimDpt scale(scaleLon, scaleLat);
+   
+   // Set the origin.
+   proj->setOrigin(origin);
+   
+  // Set the tie point.
+   proj->setUlGpt( ossimGpt(theBoundingExtent.MaxY,
+                            theBoundingExtent.MinX) );
+   
+   // Set the scale.  Note this will handle computing meters per pixel.
+   proj->setDecimalDegreesPerPixel(scale);
+   
+   return proj;
+}
diff --git a/ossim_plugins/gdal/ossimOgrVectorTileSource.h b/ossim_plugins/gdal/ossimOgrVectorTileSource.h
new file mode 100644
index 0000000..fd69ceb
--- /dev/null
+++ b/ossim_plugins/gdal/ossimOgrVectorTileSource.h
@@ -0,0 +1,196 @@
+
+//*******************************************************************
+// Copyright (C) 2000 ImageLinks Inc.
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author:  Mingjie Su
+//
+// Description:
+//
+// Contains class definition for the class "ossimOgrVectorTileSource".
+// ossimOgrVectorTileSource is derived from ImageHandler which is derived from
+// TileSource. It is for displaying the information from OGR vector dataset
+// like SDE and VPF.
+//
+//*******************************************************************
+//  $Id: ossimOgrVectorTileSource.h 1347 2010-08-23 17:03:06Z oscar.kramer $
+
+#ifndef ossimOgrVectorTileSource_HEADER
+#define ossimOgrVectorTileSource_HEADER
+#include <vector>
+#include <list>
+#include <map>
+
+#include <ossim/imaging/ossimImageHandler.h>
+#include <ossim/base/ossimIrect.h>
+#include <ossim/base/ossimDrect.h>
+
+//OGR Includes
+  // #include <ogrsf_frmts/ogrsf_frmts.h>
+#include <ogrsf_frmts.h>
+#include <gdal.h>
+
+class ossimProjection;
+class ossimMapProjection;
+class ossimImageProjectionModel;
+class ossimOgrVectorLayerNode;
+
+class ossimOgrVectorTileSource :
+   public ossimImageHandler
+{
+public:
+   ossimOgrVectorTileSource();
+   virtual ~ossimOgrVectorTileSource();
+
+   virtual void close();
+
+   /**
+    *  @return Returns true on success, false on error.
+    *
+    *  @note This method relies on the data member ossimImageData::theImageFile
+    *  being set.  Callers should do a "setFilename" prior to calling this
+    *  method or use the ossimImageHandler::open that takes a file name and an
+    *  entry index.
+    */      
+   virtual bool open();
+
+   /*!
+    *  Returns a pointer to a tile given an origin representing the upper
+    *  left corner of the tile to grab from the image.
+    *  Satisfies pure virtual from TileSource class.
+    */
+   virtual ossimRefPtr<ossimImageData> getTile(const ossimIrect& tileRect,
+                                               ossim_uint32 resLevel=0);
+
+   /*!
+    *  Returns the number of bands in the image.
+    *  Satisfies pure virtual from ImageHandler class.
+    */
+   virtual ossim_uint32 getNumberOfInputBands() const;
+
+    /*!
+    * Returns the number of bands in a tile returned from this TileSource.
+    * Note: we are supporting sources that can have multiple data objects.
+    * If you want to know the scalar type of an object you can pass in the 
+    */
+   virtual ossim_uint32 getNumberOfOutputBands() const;
+  
+   /*!
+    *  Returns the number of bands in the image.
+    *  Satisfies pure virtual from ImageHandler class.
+    */
+   virtual ossim_uint32 getNumberOfLines(ossim_uint32 reduced_res_level = 0) const;
+
+   /*!
+    *  Returns the number of bands available from an image.
+    *  Satisfies pure virtual from ImageHandler class.
+    */
+   virtual ossim_uint32 getNumberOfSamples(ossim_uint32 reduced_res_level = 0) const;
+
+   /*!
+    * Returns the number of reduced resolution data sets (rrds).
+    * 
+    * Note:  Shape files should never have reduced res sets so this method is
+    * returns "8" to avoid the question of "Do you want to build res sets".
+    */
+   virtual ossim_uint32 getNumberOfDecimationLevels() const;
+
+   /*!
+    * Returns the zero based image rectangle for the reduced resolution data
+    * set (rrds) passed in.  Note that rrds 0 is the highest resolution rrds.
+    */
+   virtual ossimIrect getImageRectangle(ossim_uint32 reduced_res_level = 0) const;
+
+   /*!
+    * Method to save the state of an object to a keyword list.
+    * Return true if ok or false on error.
+    */
+   virtual bool saveState(ossimKeywordlist& kwl,
+                          const char* prefix=0)const;
+
+   /*!
+    * Method to the load (recreate) the state of an object from a keyword
+    * list.  Return true if ok or false on error.
+    */
+   virtual bool loadState(const ossimKeywordlist& kwl,
+                          const char* prefix=0);
+   
+   //! Returns the image geometry object associated with this tile source or NULL if non defined.
+   //! The geometry contains full-to-local image transform as well as projection (image-to-world)
+   virtual ossimRefPtr<ossimImageGeometry> getInternalImageGeometry() const;
+
+   virtual ossimRefPtr<ossimImageGeometry> getImageGeometry();
+
+   /*!
+    * Returns the output pixel type of the tile source.
+    */
+   virtual ossimScalarType getOutputScalarType() const;
+
+   /*!
+    * Returns the width of the output tile.
+    */
+   virtual ossim_uint32 getTileWidth() const;
+   
+   /*!
+    * Returns the height of the output tile.
+    */
+   virtual ossim_uint32 getTileHeight() const;
+
+   /*!
+    * Returns the tile width of the image or 0 if the image is not tiled.
+    * Note: this is not the same as the ossimImageSource::getTileWidth which
+    * returns the output tile width which can be different than the internal
+    * image tile width on disk.
+    */
+   virtual ossim_uint32 getImageTileWidth() const;
+
+   /*!
+    * Returns the tile width of the image or 0 if the image is not tiled.
+    * Note: this is not the same as the ossimImageSource::getTileWidth which
+    * returns the output tile width which can be different than the internal
+    * image tile width on disk.
+    */
+   virtual ossim_uint32 getImageTileHeight() const;   
+
+   virtual bool isOpen()const;
+   
+   virtual double getNullPixelValue(ossim_uint32 band=0)const;
+
+   virtual double getMinPixelValue(ossim_uint32 band=0)const;
+      
+   virtual double getMaxPixelValue(ossim_uint32 band=0)const;
+
+   virtual bool setCurrentEntry(ossim_uint32 entryIdx);
+
+    /**
+    * @return The number of entries (images) in the image file.
+    */
+   virtual ossim_uint32 getNumberOfEntries()const;
+   
+   /**
+    * @param entryList This is the list to initialize with entry indexes.
+    *
+    * @note This implementation returns puts one entry "0" in the list.
+    */
+   virtual void getEntryList(std::vector<ossim_uint32>& entryList) const;
+
+   ossimProjection* createProjFromReference(OGRSpatialReference* reference) const;
+
+   ossimMapProjection* createDefaultProj();
+
+   bool isOgrVectorDataSource()const;
+
+private:
+   std::vector<ossimOgrVectorLayerNode*> theLayerVector;
+   OGRDataSource*                      theDataSource;
+   ossimRefPtr<ossimImageGeometry>     theImageGeometry;
+   ossimDrect                          theImageBound;
+   OGREnvelope                         theBoundingExtent;
+TYPE_DATA
+};
+
+#endif
+
diff --git a/ossim_plugins/gdal/ossimShapeDatabase.cpp b/ossim_plugins/gdal/ossimShapeDatabase.cpp
new file mode 100644
index 0000000..1f593f4
--- /dev/null
+++ b/ossim_plugins/gdal/ossimShapeDatabase.cpp
@@ -0,0 +1,358 @@
+
+#include <iomanip>
+
+#include <ossimShapeDatabase.h>
+#include <ossimShapeFile.h>
+
+RTTI_DEF1(ossimShapeDatabase, "ossimShapeDatabase", ossimObject);
+using namespace std;
+
+ossimString ossimShapeDatabaseField::fieldTypeAsString()const
+{
+   switch(theFieldType)
+   {
+   case FTString:
+   {
+      return "String";
+   }
+   case FTInteger:
+   {
+      return "Integer";
+   }
+   case FTDouble:
+   {
+      return "Double";
+   }
+   default:
+   {
+      return "Unknown";
+   }
+   };
+
+   return "";
+   
+}
+
+bool ossimShapeDatabaseRecord::getField(ossimShapeDatabaseField& result,
+                                        ossim_uint32 i)
+{
+   if(i < theFieldArray.size())
+   {
+      result = theFieldArray[i];
+      return true;
+   }
+   return false;
+}
+
+bool ossimShapeDatabaseRecord::setField(const ossimShapeDatabaseField& field,
+                                        ossim_uint32 i)
+{
+   if(i < theFieldArray.size())
+   {
+      theFieldArray[i] = field;
+      return true;
+   }
+   return false;
+}
+
+int ossimShapeDatabaseRecord::getNumberOfFields()const
+{
+   return theFieldArray.size();
+}
+
+void ossimShapeDatabaseRecord::setNumberOfFields(int n)
+{
+   if(n)
+   {
+      theFieldArray.resize(n);
+   }
+   else
+   {
+      theFieldArray.clear();
+   }
+}
+
+ossim_int32 ossimShapeDatabaseRecord::getFieldIdx(const ossimString& name,
+                                                  bool caseInsensitive)const
+{
+   ossimString searchString = name;
+   if(caseInsensitive) searchString = searchString.downcase();
+   ossim_int32 idx = 0;
+   for(idx = 0; idx < (int)theFieldArray.size(); ++idx)
+   {
+      if(caseInsensitive)
+      {
+         if(ossimString(theFieldArray[idx].theName).downcase() == searchString)
+         {
+            return idx;
+         }
+      }
+      else
+      {
+         if(theFieldArray[idx].theName == searchString)
+         {
+            return idx;
+         }
+      }
+   }
+   return -1;
+}
+
+std::ostream& operator <<(std::ostream& out, const ossimShapeDatabase& rhs)
+{
+   rhs.print(out);
+   
+   return out;
+}
+
+ossimShapeDatabase::ossimShapeDatabase()
+   :theHandle(NULL),
+    theFilename("")
+{
+   theRecordNumber = -1;
+}
+
+ossimShapeDatabase::~ossimShapeDatabase()
+{
+   close();
+}
+
+bool ossimShapeDatabase::open(const ossimFilename& file,
+                              const ossimString& flags)
+{
+   if(isOpen()) close();
+
+   theHandle = DBFOpen(file.c_str(), flags.c_str());
+   if(theHandle)
+   {
+      theFilename = file;
+      theRecordNumber = -1;
+   }
+
+   return (theHandle != NULL);
+}
+
+void ossimShapeDatabase::close()
+{
+   if(isOpen())
+   {
+      DBFClose(theHandle);
+      theHandle = NULL;
+      theRecordNumber = -1;
+   }
+}
+int ossimShapeDatabase::getNumberOfRecords()const
+{
+   if(isOpen())
+   {
+      return theHandle->nRecords;
+   }
+
+   return 0;
+}
+
+bool ossimShapeDatabase::getRecord(ossimShapeDatabaseRecord& result)
+{
+   if(isOpen()&&( (theRecordNumber < theHandle->nRecords) ))
+   {
+      if(result.getNumberOfFields() != theHandle->nFields)
+      {
+         result.setNumberOfFields(theHandle->nFields);
+      }
+      
+      char name[1024] = {'\0'};
+      int width       = 0;
+      int decimals    = 0;
+      int iField      = 0;
+      std::vector<int>         fieldWidths;
+      
+      for(iField = 0; iField < theHandle->nFields; ++iField)
+      {   
+         DBFFieldType fieldType = DBFGetFieldInfo(theHandle,
+                                                  iField,
+                                                  name,
+                                                  &width,
+                                                  &decimals);
+         ossimShapeDatabaseField field;
+         field.theName = name;
+         field.theWidth = width;
+         field.theDecimals = decimals;
+         field.theFieldType = fieldType;
+            
+         ossimString key = "field";
+         key+=ossimString::toString(iField+1);
+         key+=(ossimString(".")+name+":");
+         
+         switch(fieldType)
+         {
+         case FTString:
+         {
+            field.theValue = DBFReadStringAttribute(theHandle, theRecordNumber, iField);
+            break;
+         }
+         case FTInteger:
+         {
+            field.theValue = ossimString::toString(DBFReadIntegerAttribute(theHandle, theRecordNumber, iField));
+            break;
+         }
+         case FTDouble:
+         {
+            field.theValue = ossimString::toString(DBFReadDoubleAttribute(theHandle, theRecordNumber, iField));
+            break;
+         }
+		 case FTLogical:
+		 {
+			 break;
+		 }
+		 case FTInvalid:
+		 {
+			 break;
+		 }
+         }
+
+         result.setField(field,
+                         iField);
+      }
+      return true;
+   }
+
+   return false;
+}
+
+bool ossimShapeDatabase::getRecord(ossimShapeDatabaseRecord& result,
+                                   int recordNumber)
+{
+   if(isOpen())
+   {
+      if(recordNumber < getNumberOfRecords())
+      {
+         theRecordNumber = recordNumber;
+         return getRecord(result);
+      }
+   }
+   
+   return false;
+}
+   
+bool ossimShapeDatabase::getNextRecord(ossimShapeDatabaseRecord& result)
+{
+   if(isOpen() && ((theRecordNumber+1) < getNumberOfRecords()))
+   {
+      ++theRecordNumber;
+      return getRecord(result);
+   }
+   
+   return false;
+}
+
+bool ossimShapeDatabase::isOpen()const
+{
+   return (theHandle!=NULL);
+}
+
+DBFHandle ossimShapeDatabase::getHandle()
+{
+   return theHandle;
+}
+
+const DBFHandle& ossimShapeDatabase::getHandle()const
+{
+   return theHandle;
+}
+
+std::ostream& ossimShapeDatabase::print(std::ostream& out)const
+{
+   if(isOpen())
+   {
+      out << std::setw(15)<<setiosflags(std::ios::left)
+          <<"DB filename:" << theFilename << std::endl
+          << std::setw(15)<<setiosflags(std::ios::left)
+          <<"records:" << theHandle->nRecords << std::endl
+          << std::setw(15)<<setiosflags(std::ios::left)
+          <<"fields:" << theHandle->nFields << std::endl;
+
+      char name[1024] = {'\0'};
+      int width       = 0;
+      int decimals    = 0;
+      int iField      = 0;
+      std::vector<int>         fieldWidths;
+
+      
+      for(iField = 0; iField < theHandle->nFields; ++iField)
+      {
+         DBFFieldType fieldType = DBFGetFieldInfo(theHandle,
+                                                  iField,
+                                                  name,
+                                                  &width,
+                                                  &decimals);
+         ossimString s = "field " + ossimString::toString(iField+1) + " name:";
+         switch(fieldType)
+         {
+         case FTString:
+         case FTInteger:
+         case FTDouble:
+         {
+            out << std::setw(15) << setiosflags(std::ios::left) << s.c_str() << name << std::endl;
+            break;
+         }
+         default:
+         {
+            out << std::setw(15) << setiosflags(std::ios::left) << s.c_str() << "INVALID"<<std::endl;
+            break;
+         }
+         }
+      }
+      for(int iShape = 0; iShape < theHandle->nRecords; ++iShape)
+      {
+         for(iField = 0; iField < theHandle->nFields; ++iField)
+         {   
+            DBFFieldType fieldType = DBFGetFieldInfo(theHandle,
+                                                     iField,
+                                                     name,
+                                                     &width,
+                                                     &decimals);
+            
+            ossimString key = "field";
+            key+=ossimString::toString(iField+1);
+            key+=(ossimString(".")+name+":");
+            
+            switch(fieldType)
+            {
+            case FTString:
+            {
+               
+               out << std::setw(25) << setiosflags(std::ios::left) << key.c_str()
+                   << DBFReadStringAttribute(theHandle, iShape, iField) <<std::endl;
+               
+               break;
+            }
+            case FTInteger:
+            {
+               out << std::setw(25) << setiosflags(std::ios::left) << key.c_str()
+                   << DBFReadIntegerAttribute(theHandle, iShape, iField) << std::endl;
+               
+               break;
+            }
+            case FTDouble:
+            {
+               out << std::setw(25) << setiosflags(std::ios::left) << key.c_str()
+                   << DBFReadDoubleAttribute(theHandle, iShape, iField) << std::endl;
+               
+               break;
+            }
+			case FTLogical:
+			{
+				break;
+			}
+			case FTInvalid:
+			{
+				break;
+			}
+            }
+         }
+         out << "_________________________________"<<std::endl;
+      }
+   }
+
+   return out;
+}
diff --git a/ossim_plugins/gdal/ossimShapeDatabase.h b/ossim_plugins/gdal/ossimShapeDatabase.h
new file mode 100644
index 0000000..13f2153
--- /dev/null
+++ b/ossim_plugins/gdal/ossimShapeDatabase.h
@@ -0,0 +1,87 @@
+#ifndef ossimShapeDatabase_HEADER
+#define ossimShapeDatabase_HEADER 1
+
+#include <iostream>
+#include <shapefil.h>
+
+#include "../ossimPluginConstants.h"
+#include <ossim/base/ossimRtti.h>
+#include <ossim/base/ossimObject.h>
+#include <ossim/base/ossimFilename.h>
+
+#include <ossim/base/ossimString.h>
+
+
+class ossimShapeDatabaseField
+{
+public:
+   ossimString fieldTypeAsString()const;
+   
+   ossimString  theName;
+   int         theWidth;
+   int         theDecimals;
+   DBFFieldType theFieldType;
+   ossimString  theValue;
+};
+
+class OSSIM_PLUGINS_DLL ossimShapeDatabaseRecord
+{
+   
+public:
+   bool getField(ossimShapeDatabaseField& result,
+                 ossim_uint32 i);
+
+   bool setField(const ossimShapeDatabaseField& field,
+                 ossim_uint32 i);
+
+   int getNumberOfFields()const;
+
+   void setNumberOfFields(int n);
+
+   ossim_int32 getFieldIdx(const ossimString& name,
+                           bool caseInsensitive=true)const;
+protected:
+	std::vector<ossimShapeDatabaseField> theFieldArray;
+};
+
+class OSSIM_PLUGINS_DLL ossimShapeDatabase : public ossimObject
+{
+public:
+   friend std::ostream& operator <<(std::ostream& out,
+                                    const ossimShapeDatabase& rhs);
+   
+   ossimShapeDatabase();
+   virtual ~ossimShapeDatabase();
+   
+   virtual bool open(const ossimFilename& file,
+                     const ossimString& flags=ossimString("rb"));
+   
+   virtual void close();
+   
+   bool getRecord(ossimShapeDatabaseRecord& result);
+   
+   bool getRecord(ossimShapeDatabaseRecord& result,
+                  int recordNumber);
+
+   bool getNextRecord(ossimShapeDatabaseRecord& result);
+
+   int getNumberOfRecords()const;
+   
+   bool isOpen()const;
+
+   virtual DBFHandle getHandle();
+
+   virtual const DBFHandle& getHandle()const;
+   
+   virtual std::ostream& print(std::ostream& out)const;
+
+protected:
+   DBFHandle theHandle;
+   ossimFilename theFilename;
+
+   int theRecordNumber;
+
+TYPE_DATA
+};
+
+#endif
diff --git a/ossim_plugins/gdal/ossimShapeFile.cpp b/ossim_plugins/gdal/ossimShapeFile.cpp
new file mode 100644
index 0000000..c9028fa
--- /dev/null
+++ b/ossim_plugins/gdal/ossimShapeFile.cpp
@@ -0,0 +1,483 @@
+//*******************************************************************
+// License:  See top level LICENSE.txt file.
+//
+// Author: Garrett Potts
+// 
+// Description: This class extends the stl's string class.
+//
+//********************************************************************
+// $Id: ossimShapeFile.cpp 22453 2013-10-23 18:12:16Z gpotts $
+//
+
+#include <iomanip>
+#include <ossimShapeFile.h>
+
+RTTI_DEF1(ossimShapeFile, "ossimShapeFile", ossimObject);
+
+using namespace std;
+std::ostream& operator<<(std::ostream& out, const ossimShapeObject& rhs)
+{
+   if(rhs.isLoaded())
+   {
+      double minx, miny, minz, minm;
+      double maxx, maxy, maxz, maxm;
+      ossim_uint32 i = 0;
+      
+      rhs.getBounds(minx, miny, minz, minm,
+                    maxx, maxy, maxz, maxm);
+      
+      out << std::setw(15) << setiosflags(std::ios::left)<<"type:"<<rhs.getTypeByName() << std::endl
+          << std::setw(15) << setiosflags(std::ios::left)<<"id:"<<rhs.getId()<<std::endl
+          << std::setw(15) << setiosflags(std::ios::left)<<"minx:"<<minx <<std::endl
+          << std::setw(15) << setiosflags(std::ios::left)<<"miny:"<<miny <<std::endl
+          << std::setw(15) << setiosflags(std::ios::left)<<"minz:"<<minz <<std::endl
+          << std::setw(15) << setiosflags(std::ios::left)<<"minm:"<<minm <<std::endl
+          << std::setw(15) << setiosflags(std::ios::left)<<"maxx:"<<maxx <<std::endl
+          << std::setw(15) << setiosflags(std::ios::left)<<"maxy:"<<maxy <<std::endl
+          << std::setw(15) << setiosflags(std::ios::left)<<"maxz:"<<maxz <<std::endl
+          << std::setw(15) << setiosflags(std::ios::left)<<"maxm:"<<maxm <<std::endl
+          << std::setw(15) << setiosflags(std::ios::left)<<"parts:"<<rhs.getNumberOfParts()<<std::endl
+          << std::setw(15) << setiosflags(std::ios::left)<<"vertices:"<<rhs.getNumberOfVertices();
+
+      if(rhs.getNumberOfParts())
+      {
+         out << std::endl;
+         for(i = 0; i < rhs.getNumberOfParts()-1; ++i)
+         {
+            ossimString s1 = "part start ";
+            ossimString s2 = "part type ";
+            s1 += (ossimString::toString(i+1)+":");
+            s2 += (ossimString::toString(i+1)+":");
+            
+            out << std::setw(15) << setiosflags(std::ios::left) << s1.c_str() << rhs.theShape->panPartStart[i]<<std::endl;
+            out << std::setw(15) << setiosflags(std::ios::left) << s2.c_str() <<  SHPPartTypeName(rhs.theShape->panPartType[i])<<std::endl;
+         }
+         ossimString s1 = "part start ";
+         ossimString s2 = "part type ";
+         
+         s1 += (ossimString::toString(rhs.getNumberOfParts())+":");
+         out << std::setw(15) << setiosflags(std::ios::left) << s1.c_str() <<  rhs.theShape->panPartStart[i]<<std::endl;
+         out << std::setw(15) << setiosflags(std::ios::left) << s2.c_str() <<  SHPPartTypeName(rhs.theShape->panPartType[i]);
+      }
+      
+      out << std::setw(0);
+      
+   }
+   return out;   
+}
+
+ossimShapeObject::ossimShapeObject()
+   :theShape((SHPObject*)NULL),
+    theIndex(-1)
+{
+}
+
+ossimShapeObject::~ossimShapeObject()
+{
+   if(theShape)
+   {
+      SHPDestroyObject(theShape);
+      theShape = NULL;
+   }
+}
+
+void ossimShapeObject::getBoundingRect(ossimDrect& result,
+                                       ossimCoordSysOrientMode orient)const
+{
+   double minx, miny, maxx, maxy;
+   
+   if(theShape)
+   {
+      getBounds(minx, miny, maxx, maxy);
+      
+      if(orient == OSSIM_RIGHT_HANDED)
+      {
+         result = ossimDrect(minx, maxy, maxx, miny, orient);
+      }
+      else
+      {
+         result = ossimDrect(minx, miny, maxx, maxy, orient);         
+      }
+   }
+   else
+   {
+      result = ossimDrect(0,0,0,0,orient);
+      result.makeNan();
+   }
+}
+
+void ossimShapeObject::setShape(SHPObject* obj)
+{
+   if(theShape)
+   {
+      SHPDestroyObject(theShape);
+      theShape = NULL;            
+   }
+   
+   theShape = obj;
+}
+
+bool ossimShapeObject::isLoaded()const
+{
+   return (theShape!=NULL);
+}
+
+long ossimShapeObject::getIndex()const
+{
+   return theIndex;
+}
+
+long ossimShapeObject::getId()const
+{
+   if(theShape)
+   {
+      return theShape->nShapeId;
+   }
+   
+   return -1;
+}
+
+bool ossimShapeObject::loadShape(const ossimShapeFile& shapeFile,
+                                 long shapeRecord)
+{
+   if(theShape)
+   {
+      SHPDestroyObject(theShape);
+      theShape = NULL;            
+   }
+   if(shapeFile.isOpen())
+   {
+      theShape = SHPReadObject(shapeFile.getHandle(),
+                               shapeRecord);
+      theIndex = shapeRecord;
+   }
+   else
+   {
+      theIndex = -1;
+   }
+   return (theShape != (SHPObject*)NULL);
+}
+
+ossim_uint32 ossimShapeObject::getNumberOfParts()const
+{
+   if(theShape)
+   {
+      return theShape->nParts;
+   }
+   
+   return 0;
+}
+
+ossim_uint32 ossimShapeObject::getNumberOfVertices()const
+{
+   if(theShape)
+   {
+      return theShape->nVertices;
+   }
+   
+   return 0;
+}
+
+void ossimShapeObject::getBounds(
+   double& minX, double& minY, double& minZ, double& minM,
+   double& maxX, double& maxY, double& maxZ, double& maxM)const
+{
+   if(theShape)
+   {
+      minX = theShape->dfXMin;
+      minY = theShape->dfYMin;
+      minZ = theShape->dfZMin;
+      minM = theShape->dfMMin;
+      maxX = theShape->dfXMax;
+      maxY = theShape->dfYMax;
+      maxZ = theShape->dfZMax;
+      maxM = theShape->dfMMax;
+   }
+   else
+   {
+      minX = minY = minZ = minM =
+         maxX = maxY = maxZ = maxM = ossim::nan();
+   }
+}
+
+void ossimShapeObject::getBounds(double& minX, double& minY,
+                                 double& maxX, double& maxY)const
+{
+   if(theShape)
+   {
+      minX = theShape->dfXMin;
+      minY = theShape->dfYMin;
+      maxX = theShape->dfXMax;
+      maxY = theShape->dfYMax;
+   }
+   else
+   {
+      minX = minY = 
+         maxX = maxY = ossim::nan();
+   }
+}
+
+ossimDrect ossimShapeObject::getBoundingRect(
+   ossimCoordSysOrientMode orient)const
+{
+   ossimDrect result;
+   
+   getBoundingRect(result, orient);
+   
+   return result;
+}
+   
+int ossimShapeObject::getType()const
+{
+   if(theShape)
+   {
+      return theShape->nSHPType;
+   }
+   return SHPT_NULL;
+}
+
+ossimString ossimShapeObject::getTypeByName()const
+{
+   if(theShape)
+   {
+      return ossimString(SHPTypeName(theShape->nSHPType));
+   }
+   return "unknown";
+}
+
+int ossimShapeObject::getPartType(ossim_uint32 partIndex)const
+{
+   if((partIndex > getNumberOfParts())||
+      (!theShape))
+   {
+      return -1;
+   }
+   
+   return theShape->panPartType[partIndex];
+}
+
+ossimString ossimShapeObject::getPartByName(ossim_uint32 partIndex)const
+{
+   if((partIndex > getNumberOfParts())||
+      (!theShape))
+   {
+   }
+   switch(theShape->panPartType[partIndex])
+   {
+      case SHPP_TRISTRIP:
+      {
+         ossimString("tristrip");
+         break;
+      }
+      case SHPP_TRIFAN:
+      {
+         ossimString("trifan");
+         break;
+      }
+      case SHPP_OUTERRING:
+      {
+         ossimString("outerring");
+         break;
+      }
+      case SHPP_INNERRING:
+      {
+         ossimString("innerring");
+         break;
+      }
+      case SHPP_RING:
+      {
+         ossimString("ring");
+         break;
+      }
+   }
+   return ossimString("unknown");
+}
+
+SHPObject* ossimShapeObject::getShapeObject()
+{
+   return theShape;
+}
+
+const SHPObject* ossimShapeObject::getShapeObject()const
+{
+   return theShape;
+}
+   
+std::ostream& operator <<(std::ostream& out, const ossimShapeFile& rhs)
+{
+   rhs.print(out);
+   
+   return out;
+}
+
+
+ossimShapeFile::ossimShapeFile()
+   :theHandle(NULL)
+{
+}
+
+ossimShapeFile::~ossimShapeFile()
+{
+   close();
+}
+
+void ossimShapeFile::close()
+{
+   if(theHandle)
+   {
+      SHPClose(theHandle);
+      theHandle = NULL;
+   }
+}
+
+bool ossimShapeFile::open(const ossimFilename& file,
+                          const ossimString& flags)
+{
+   if(isOpen()) close();
+   
+   theHandle = SHPOpen( file.c_str(),
+                        flags.c_str());
+   if(isOpen())
+   {
+      theFilename = file;
+   }
+   
+   return (theHandle != NULL);
+}
+
+bool ossimShapeFile::isOpen()const
+{
+   return (theHandle!=NULL);
+}
+
+SHPHandle ossimShapeFile::getHandle()
+{
+   return theHandle;
+}
+   
+const SHPHandle& ossimShapeFile::getHandle()const
+{
+   return theHandle;
+}
+
+long ossimShapeFile::getNumberOfShapes()const
+{
+   if(theHandle)
+   {
+      return theHandle->nRecords;
+   }
+   return 0;
+}
+
+void ossimShapeFile::getBounds(
+   double& minX, double& minY, double& minZ, double& minM,
+   double& maxX, double& maxY, double& maxZ, double& maxM)const
+{
+   if(theHandle)
+   {
+      minX = theHandle->adBoundsMin[0];
+      minY = theHandle->adBoundsMin[1];
+      minZ = theHandle->adBoundsMin[2];
+      minM = theHandle->adBoundsMin[3];
+      maxX = theHandle->adBoundsMax[0];
+      maxY = theHandle->adBoundsMax[1];
+      maxZ = theHandle->adBoundsMax[2];
+      maxM = theHandle->adBoundsMax[3];
+   }
+   else
+   {
+      minX = minY = minZ = minM =
+         maxX = maxY = maxZ = maxM = ossim::nan();
+   }
+}
+   
+void ossimShapeFile::getBounds(double& minX, double& minY,
+                               double& maxX, double& maxY)const
+{
+   if(theHandle)
+   {
+      minX = theHandle->adBoundsMin[0];
+      minY = theHandle->adBoundsMin[1];
+      maxX = theHandle->adBoundsMax[0];
+      maxY = theHandle->adBoundsMax[1];
+   }
+   else
+   {
+      minX = minY = maxX = maxY = ossim::nan();
+   }
+}
+
+std::ostream& ossimShapeFile::print(std::ostream& out) const
+{
+   if(isOpen())
+   {
+      out << std::setw(15) << setiosflags(std::ios::left)<<"Shp filename:" << theFilename << std::endl;
+      out << std::setw(15) << setiosflags(std::ios::left)<<"Record count:" << theHandle->nRecords << std::endl;
+      out << std::setw(15) << setiosflags(std::ios::left)<<"File type:" << getShapeTypeString().c_str() << std::endl;
+      out << std::setw(15) << setiosflags(std::ios::left)<<"minx:" << theHandle->adBoundsMin[0] << std::endl;
+      out << std::setw(15) << setiosflags(std::ios::left)<<"miny:" << theHandle->adBoundsMin[1] << std::endl;
+      out << std::setw(15) << setiosflags(std::ios::left)<<"minz:" << theHandle->adBoundsMin[2] << std::endl;
+      out << std::setw(15) << setiosflags(std::ios::left)<<"minm:" << theHandle->adBoundsMin[3] << std::endl;
+      out << std::setw(15) << setiosflags(std::ios::left)<<"maxx:" << theHandle->adBoundsMax[0] << std::endl;
+      out << std::setw(15) << setiosflags(std::ios::left)<<"maxy:" << theHandle->adBoundsMax[1] << std::endl;
+      out << std::setw(15) << setiosflags(std::ios::left)<<"maxz:" << theHandle->adBoundsMax[2] << std::endl;
+      out << std::setw(15) << setiosflags(std::ios::left)<<"maxm:" << theHandle->adBoundsMax[3] << std::endl;
+
+      ossimShapeObject shape;
+      
+      if(theHandle->nRecords)
+      {
+         out << std::setw(30) << std::setfill('_') << "" << std::setfill(' ')<<std::endl;
+      }
+      for(int i=0; i < theHandle->nRecords; ++i)
+      {
+         if(shape.loadShape(*this, i))
+         {
+            out << shape << std::endl;
+            out << std::setw(30) << std::setfill('_') << ""<<std::setfill(' ')<<std::endl;
+         }
+      }
+   }
+   return out;
+}
+
+
+ossimString ossimShapeFile::getShapeTypeString()const
+{
+   if(theHandle)
+   {
+      return SHPTypeName(theHandle->nShapeType);
+   }
+   return "";
+}
+
+void ossimShapeFile::getBoundingRect(ossimDrect& result,
+                                     ossimCoordSysOrientMode orient)const
+{
+   double minx, miny, maxx, maxy;
+   
+   getBounds(minx, miny, maxx, maxy);
+   if(orient == OSSIM_RIGHT_HANDED)
+   {
+      result = ossimDrect(minx, maxy, maxx, miny, orient);
+   }
+   else
+   {
+      result = ossimDrect(minx, miny, maxx, maxy, orient);         
+   }
+}
+
+ossimDrect ossimShapeFile::getBoundingRect(
+   ossimCoordSysOrientMode orient)const
+{
+   ossimDrect result;
+   
+   getBoundingRect(result, orient);
+   
+   return result;
+}
+
+const ossimFilename& ossimShapeFile::getFilename()const
+{
+   return theFilename;
+}
diff --git a/ossim_plugins/gdal/ossimShapeFile.h b/ossim_plugins/gdal/ossimShapeFile.h
new file mode 100644
index 0000000..b85f6bc
--- /dev/null
+++ b/ossim_plugins/gdal/ossimShapeFile.h
@@ -0,0 +1,124 @@
+//*******************************************************************
+//
+// License:  See top level LICENSE.txt file.
+// 
+// Author: Garrett Potts
+//
+//*************************************************************************
+// $Id: ossimShapeFile.h 19908 2011-08-05 19:57:34Z dburken $
+
+#ifndef ossimShapeFile_HEADER
+#define ossimShapeFile_HEADER 1
+
+#include <iostream>
+
+#include <shapefil.h>
+
+#include "../ossimPluginConstants.h"
+#include <ossim/base/ossimRtti.h>
+#include <ossim/base/ossimObject.h>
+#include <ossim/base/ossimFilename.h>
+#include <ossim/base/ossimString.h>
+#include <ossim/base/ossimDrect.h>
+
+
+class ossimShapeFile;
+class ossimAnnotationObject;
+
+class ossimShapeObject
+{
+public:
+   friend std::ostream& operator<<(std::ostream& out,
+                                   const ossimShapeObject& rhs);
+   
+   ossimShapeObject();
+      
+   ~ossimShapeObject();
+
+   void setShape(SHPObject* obj);
+   bool isLoaded()const;
+   long getIndex()const;
+   long getId()const;
+
+   bool loadShape(const ossimShapeFile& shapeFile, long shapeRecord);
+   
+   ossim_uint32 getNumberOfParts()const;
+
+   ossim_uint32 getNumberOfVertices()const;
+   
+   void getBounds(double& minX, double& minY, double& minZ, double& minM,
+                  double& maxX, double& maxY, double& maxZ, double& maxM)const;
+   
+   void getBounds(double& minX, double& minY,
+                  double& maxX, double& maxY)const;
+   
+   void getBoundingRect(ossimDrect& result,
+                        ossimCoordSysOrientMode orient = OSSIM_RIGHT_HANDED)const;
+   
+   ossimDrect getBoundingRect(ossimCoordSysOrientMode orient = OSSIM_RIGHT_HANDED)const;
+   
+   int getType()const;
+
+   ossimString getTypeByName()const;
+
+   int getPartType(ossim_uint32 partIndex)const;
+
+   ossimString getPartByName(ossim_uint32 partIndex)const;
+
+   SHPObject* getShapeObject();
+
+   const SHPObject* getShapeObject()const;
+   
+protected:
+   SHPObject* theShape;
+   long       theIndex;
+};
+
+class OSSIM_PLUGINS_DLL ossimShapeFile : public ossimObject
+{
+public:
+   friend std::ostream& operator <<(std::ostream& out,
+                                    const ossimShapeFile& rhs);
+   
+   ossimShapeFile();
+   virtual ~ossimShapeFile();
+   
+   virtual bool open(const ossimFilename& file,
+                     const ossimString& flags=ossimString("rb"));
+   
+   virtual void close();
+
+   bool isOpen()const;
+
+   virtual SHPHandle getHandle();
+
+   virtual const SHPHandle& getHandle()const;
+
+   virtual std::ostream& print(std::ostream& out) const;
+
+   virtual ossimString getShapeTypeString()const;
+   
+   
+   virtual long getNumberOfShapes()const;
+
+   void getBounds(double& minX, double& minY, double& minZ, double& minM,
+                  double& maxX, double& maxY, double& maxZ, double& maxM)const;
+   
+   void getBounds(double& minX, double& minY,
+                  double& maxX, double& maxY)const;
+   
+   void getBoundingRect(ossimDrect& result,
+                        ossimCoordSysOrientMode orient = OSSIM_RIGHT_HANDED)const;
+   
+   ossimDrect getBoundingRect(ossimCoordSysOrientMode orient = OSSIM_RIGHT_HANDED)const;
+
+   const ossimFilename& getFilename()const;
+
+protected:
+   SHPHandle	 theHandle;
+   ossimFilename theFilename;
+
+TYPE_DATA
+};
+
+#endif
diff --git a/ossim_plugins/gdal/shapefil.h b/ossim_plugins/gdal/shapefil.h
new file mode 100644
index 0000000..16713e8
--- /dev/null
+++ b/ossim_plugins/gdal/shapefil.h
@@ -0,0 +1,558 @@
+#ifndef _SHAPEFILE_H_INCLUDED
+#define _SHAPEFILE_H_INCLUDED
+
+/******************************************************************************
+ * $Id: shapefil.h 13274 2007-12-06 14:00:51Z warmerdam $
+ *
+ * Project:  Shapelib
+ * Purpose:  Primary include file for Shapelib.
+ * Author:   Frank Warmerdam, warmerdam at pobox.com
+ *
+ ******************************************************************************
+ * Copyright (c) 1999, Frank Warmerdam
+ *
+ * This software is available under the following "MIT Style" license,
+ * or at the option of the licensee under the LGPL (see LICENSE.LGPL).  This
+ * option is discussed in more detail in shapelib.html.
+ *
+ * --
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ******************************************************************************
+ *
+ * $Log: shapefil.h,v $
+ * Revision 1.40  2007/12/06 07:00:25  fwarmerdam
+ * dbfopen now using SAHooks for fileio
+ *
+ * Revision 1.39  2007/12/04 20:37:56  fwarmerdam
+ * preliminary implementation of hooks api for io and errors
+ *
+ * Revision 1.38  2007/11/21 22:39:56  fwarmerdam
+ * close shx file in readonly mode (GDAL #1956)
+ *
+ * Revision 1.37  2007/10/27 03:31:14  fwarmerdam
+ * limit default depth of tree to 12 levels (gdal ticket #1594)
+ *
+ * Revision 1.36  2007/09/10 23:33:15  fwarmerdam
+ * Upstreamed support for visibility flag in SHPAPI_CALL for the needs
+ * of GDAL (gdal ticket #1810).
+ *
+ * Revision 1.35  2007/09/03 19:48:10  fwarmerdam
+ * move DBFReadAttribute() static dDoubleField into dbfinfo
+ *
+ * Revision 1.34  2006/06/17 15:33:32  fwarmerdam
+ * added pszWorkField - bug 1202 (rso)
+ *
+ * Revision 1.33  2006/02/15 01:14:30  fwarmerdam
+ * added DBFAddNativeFieldType
+ *
+ * Revision 1.32  2006/01/26 15:07:32  fwarmerdam
+ * add bMeasureIsUsed flag from Craig Bruce: Bug 1249
+ *
+ * Revision 1.31  2006/01/05 01:27:27  fwarmerdam
+ * added dbf deletion mark/fetch
+ *
+ * Revision 1.30  2005/01/03 22:30:13  fwarmerdam
+ * added support for saved quadtrees
+ *
+ * Revision 1.29  2004/09/26 20:09:35  fwarmerdam
+ * avoid rcsid warnings
+ *
+ * Revision 1.28  2003/12/29 06:02:18  fwarmerdam
+ * added cpl_error.h option
+ *
+ * Revision 1.27  2003/04/21 18:30:37  warmerda
+ * added header write/update public methods
+ *
+ * Revision 1.26  2002/09/29 00:00:08  warmerda
+ * added FTLogical and logical attribute read/write calls
+ *
+ * Revision 1.25  2002/05/07 13:46:30  warmerda
+ * added DBFWriteAttributeDirectly().
+ *
+ * Revision 1.24  2002/04/10 16:59:54  warmerda
+ * added SHPRewindObject
+ *
+ * Revision 1.23  2002/01/15 14:36:07  warmerda
+ * updated email address
+ *
+ * Revision 1.22  2002/01/15 14:32:00  warmerda
+ * try to improve SHPAPI_CALL docs
+ */
+
+#include <stdio.h>
+
+#ifdef USE_DBMALLOC
+#include <dbmalloc.h>
+#endif
+
+#ifdef USE_CPL
+#include "cpl_error.h"
+#include "cpl_vsi.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/************************************************************************/
+/*                        Configuration options.                        */
+/************************************************************************/
+
+/* -------------------------------------------------------------------- */
+/*      Should the DBFReadStringAttribute() strip leading and           */
+/*      trailing white space?                                           */
+/* -------------------------------------------------------------------- */
+#define TRIM_DBF_WHITESPACE
+
+/* -------------------------------------------------------------------- */
+/*      Should we write measure values to the Multipatch object?        */
+/*      Reportedly ArcView crashes if we do write it, so for now it     */
+/*      is disabled.                                                    */
+/* -------------------------------------------------------------------- */
+#define DISABLE_MULTIPATCH_MEASURE
+    
+/* -------------------------------------------------------------------- */
+/*      SHPAPI_CALL                                                     */
+/*                                                                      */
+/*      The following two macros are present to allow forcing           */
+/*      various calling conventions on the Shapelib API.                */
+/*                                                                      */
+/*      To force __stdcall conventions (needed to call Shapelib         */
+/*      from Visual Basic and/or Dephi I believe) the makefile could    */
+/*      be modified to define:                                          */
+/*                                                                      */
+/*        /DSHPAPI_CALL=__stdcall                                       */
+/*                                                                      */
+/*      If it is desired to force export of the Shapelib API without    */
+/*      using the shapelib.def file, use the following definition.      */
+/*                                                                      */
+/*        /DSHAPELIB_DLLEXPORT                                          */
+/*                                                                      */
+/*      To get both at once it will be necessary to hack this           */
+/*      include file to define:                                         */
+/*                                                                      */
+/*        #define SHPAPI_CALL __declspec(dllexport) __stdcall           */
+/*        #define SHPAPI_CALL1 __declspec(dllexport) * __stdcall        */
+/*                                                                      */
+/*      The complexity of the situtation is partly caused by the        */
+/*      peculiar requirement of Visual C++ that __stdcall appear        */
+/*      after any "*"'s in the return value of a function while the     */
+/*      __declspec(dllexport) must appear before them.                  */
+/* -------------------------------------------------------------------- */
+
+#ifdef SHAPELIB_DLLEXPORT
+#  define SHPAPI_CALL __declspec(dllexport)
+#  define SHPAPI_CALL1(x)  __declspec(dllexport) x
+#endif
+
+#ifndef SHPAPI_CALL
+#  if defined(USE_GCC_VISIBILITY_FLAG)
+#    define SHPAPI_CALL     __attribute__ ((visibility("default")))
+#    define SHPAPI_CALL1(x) __attribute__ ((visibility("default")))     x
+#  else
+#    define SHPAPI_CALL
+#  endif
+#endif
+
+#ifndef SHPAPI_CALL1
+#  define SHPAPI_CALL1(x)      x SHPAPI_CALL
+#endif
+    
+/* -------------------------------------------------------------------- */
+/*      Macros for controlling CVSID and ensuring they don't appear     */
+/*      as unreferenced variables resulting in lots of warnings.        */
+/* -------------------------------------------------------------------- */
+#ifndef DISABLE_CVSID
+#  define SHP_CVSID(string)     static char cpl_cvsid[] = string; \
+static char *cvsid_aw() { return( cvsid_aw() ? ((char *) NULL) : cpl_cvsid ); }
+#else
+#  define SHP_CVSID(string)
+#endif
+    
+/* -------------------------------------------------------------------- */
+/*      IO/Error hook functions.                                        */
+/* -------------------------------------------------------------------- */
+typedef int *SAFile;
+
+#ifndef SAOffset
+typedef unsigned long SAOffset;
+#endif
+
+typedef struct {
+    SAFile     (*FOpen) ( const char *filename, const char *path);
+    SAOffset   (*FRead) ( void *p, SAOffset size, SAOffset nmemb, SAFile file);
+    SAOffset   (*FWrite)( void *p, SAOffset size, SAOffset nmemb, SAFile file);
+    SAOffset   (*FSeek) ( SAFile file, SAOffset offset, int whence );
+    SAOffset   (*FTell) ( SAFile file );
+    int        (*FFlush)( SAFile file );
+    int        (*FClose)( SAFile file );
+
+    void       (*Error) ( const char *message );
+} SAHooks;
+
+void SHPAPI_CALL SASetupDefaultHooks( SAHooks *psHooks );
+
+/************************************************************************/
+/*                             SHP Support.                             */
+/************************************************************************/
+typedef	struct
+{
+    SAHooks sHooks;
+
+    SAFile      fpSHP;
+    SAFile 	fpSHX;
+
+    int		nShapeType;				/* SHPT_* */
+    
+    int		nFileSize;				/* SHP file */
+
+    int         nRecords;
+    int		nMaxRecords;
+    int		*panRecOffset;
+    int		*panRecSize;
+
+    double	adBoundsMin[4];
+    double	adBoundsMax[4];
+
+    int		bUpdated;
+
+    unsigned char *pabyRec;
+    int         nBufSize;
+} SHPInfo;
+
+typedef SHPInfo * SHPHandle;
+
+/* -------------------------------------------------------------------- */
+/*      Shape types (nSHPType)                                          */
+/* -------------------------------------------------------------------- */
+#define SHPT_NULL	0
+#define SHPT_POINT	1
+#define SHPT_ARC	3
+#define SHPT_POLYGON	5
+#define SHPT_MULTIPOINT	8
+#define SHPT_POINTZ	11
+#define SHPT_ARCZ	13
+#define SHPT_POLYGONZ	15
+#define SHPT_MULTIPOINTZ 18
+#define SHPT_POINTM	21
+#define SHPT_ARCM	23
+#define SHPT_POLYGONM	25
+#define SHPT_MULTIPOINTM 28
+#define SHPT_MULTIPATCH 31
+
+
+/* -------------------------------------------------------------------- */
+/*      Part types - everything but SHPT_MULTIPATCH just uses           */
+/*      SHPP_RING.                                                      */
+/* -------------------------------------------------------------------- */
+
+#define SHPP_TRISTRIP	0
+#define SHPP_TRIFAN	1
+#define SHPP_OUTERRING	2
+#define SHPP_INNERRING	3
+#define SHPP_FIRSTRING	4
+#define SHPP_RING	5
+
+/* -------------------------------------------------------------------- */
+/*      SHPObject - represents on shape (without attributes) read       */
+/*      from the .shp file.                                             */
+/* -------------------------------------------------------------------- */
+typedef struct
+{
+    int		nSHPType;
+
+    int		nShapeId; /* -1 is unknown/unassigned */
+
+    int		nParts;
+    int		*panPartStart;
+    int		*panPartType;
+    
+    int		nVertices;
+    double	*padfX;
+    double	*padfY;
+    double	*padfZ;
+    double	*padfM;
+
+    double	dfXMin;
+    double	dfYMin;
+    double	dfZMin;
+    double	dfMMin;
+
+    double	dfXMax;
+    double	dfYMax;
+    double	dfZMax;
+    double	dfMMax;
+
+    int		bMeasureIsUsed;
+} SHPObject;
+
+/* -------------------------------------------------------------------- */
+/*      SHP API Prototypes                                              */
+/* -------------------------------------------------------------------- */
+
+/* If pszAccess is read-only, the fpSHX field of the returned structure */
+/* will be NULL as it is not necessary to keep the SHX file open */
+SHPHandle SHPAPI_CALL
+      SHPOpen( const char * pszShapeFile, const char * pszAccess );
+SHPHandle SHPAPI_CALL
+      SHPOpenLL( const char *pszShapeFile, const char *pszAccess, 
+                 SAHooks *psHooks );
+SHPHandle SHPAPI_CALL
+      SHPCreate( const char * pszShapeFile, int nShapeType );
+SHPHandle SHPAPI_CALL
+      SHPCreateLL( const char * pszShapeFile, int nShapeType,
+                   SAHooks *psHooks );
+void SHPAPI_CALL
+      SHPGetInfo( SHPHandle hSHP, int * pnEntities, int * pnShapeType,
+                  double * padfMinBound, double * padfMaxBound );
+
+SHPObject SHPAPI_CALL1(*)
+      SHPReadObject( SHPHandle hSHP, int iShape );
+int SHPAPI_CALL
+      SHPWriteObject( SHPHandle hSHP, int iShape, SHPObject * psObject );
+
+void SHPAPI_CALL
+      SHPDestroyObject( SHPObject * psObject );
+void SHPAPI_CALL
+      SHPComputeExtents( SHPObject * psObject );
+SHPObject SHPAPI_CALL1(*)
+      SHPCreateObject( int nSHPType, int nShapeId, int nParts, 
+                       const int * panPartStart, const int * panPartType,
+                       int nVertices, 
+                       const double * padfX, const double * padfY,
+                       const double * padfZ, const double * padfM );
+SHPObject SHPAPI_CALL1(*)
+      SHPCreateSimpleObject( int nSHPType, int nVertices,
+                             const double * padfX, 
+                             const double * padfY, 
+                             const double * padfZ );
+
+int SHPAPI_CALL
+      SHPRewindObject( SHPHandle hSHP, SHPObject * psObject );
+
+void SHPAPI_CALL SHPClose( SHPHandle hSHP );
+void SHPAPI_CALL SHPWriteHeader( SHPHandle hSHP );
+
+const char SHPAPI_CALL1(*)
+      SHPTypeName( int nSHPType );
+const char SHPAPI_CALL1(*)
+      SHPPartTypeName( int nPartType );
+
+/* -------------------------------------------------------------------- */
+/*      Shape quadtree indexing API.                                    */
+/* -------------------------------------------------------------------- */
+
+/* this can be two or four for binary or quad tree */
+#define MAX_SUBNODE	4
+
+/* upper limit of tree levels for automatic estimation */
+#define MAX_DEFAULT_TREE_DEPTH 12
+
+typedef struct shape_tree_node
+{
+    /* region covered by this node */
+    double	adfBoundsMin[4];
+    double	adfBoundsMax[4];
+
+    /* list of shapes stored at this node.  The papsShapeObj pointers
+       or the whole list can be NULL */
+    int		nShapeCount;
+    int		*panShapeIds;
+    SHPObject   **papsShapeObj;
+
+    int		nSubNodes;
+    struct shape_tree_node *apsSubNode[MAX_SUBNODE];
+    
+} SHPTreeNode;
+
+typedef struct
+{
+    SHPHandle   hSHP;
+    
+    int		nMaxDepth;
+    int		nDimension;
+    int         nTotalCount;
+    
+    SHPTreeNode	*psRoot;
+} SHPTree;
+
+SHPTree SHPAPI_CALL1(*)
+      SHPCreateTree( SHPHandle hSHP, int nDimension, int nMaxDepth,
+                     double *padfBoundsMin, double *padfBoundsMax );
+void    SHPAPI_CALL
+      SHPDestroyTree( SHPTree * hTree );
+
+int	SHPAPI_CALL
+      SHPWriteTree( SHPTree *hTree, const char * pszFilename );
+SHPTree SHPAPI_CALL
+      SHPReadTree( const char * pszFilename );
+
+int	SHPAPI_CALL
+      SHPTreeAddObject( SHPTree * hTree, SHPObject * psObject );
+int	SHPAPI_CALL
+      SHPTreeAddShapeId( SHPTree * hTree, SHPObject * psObject );
+int	SHPAPI_CALL
+      SHPTreeRemoveShapeId( SHPTree * hTree, int nShapeId );
+
+void 	SHPAPI_CALL
+      SHPTreeTrimExtraNodes( SHPTree * hTree );
+
+int    SHPAPI_CALL1(*)
+      SHPTreeFindLikelyShapes( SHPTree * hTree,
+                               double * padfBoundsMin,
+                               double * padfBoundsMax,
+                               int * );
+int     SHPAPI_CALL
+      SHPCheckBoundsOverlap( double *, double *, double *, double *, int );
+
+int SHPAPI_CALL1(*) 
+SHPSearchDiskTree( FILE *fp, 
+                   double *padfBoundsMin, double *padfBoundsMax,
+                   int *pnShapeCount );
+
+/************************************************************************/
+/*                             DBF Support.                             */
+/************************************************************************/
+typedef	struct
+{
+    SAHooks sHooks;
+
+    SAFile	fp;
+
+    int         nRecords;
+
+    int		nRecordLength;
+    int		nHeaderLength;
+    int		nFields;
+    int		*panFieldOffset;
+    int		*panFieldSize;
+    int		*panFieldDecimals;
+    char	*pachFieldType;
+
+    char	*pszHeader;
+
+    int		nCurrentRecord;
+    int		bCurrentRecordModified;
+    char	*pszCurrentRecord;
+
+    int         nWorkFieldLength;
+    char        *pszWorkField;
+    
+    int		bNoHeader;
+    int		bUpdated;
+
+    double      dfDoubleField;
+} DBFInfo;
+
+typedef DBFInfo * DBFHandle;
+
+typedef enum {
+  FTString,
+  FTInteger,
+  FTDouble,
+  FTLogical,
+  FTInvalid
+} DBFFieldType;
+
+#define XBASE_FLDHDR_SZ       32
+
+
+DBFHandle SHPAPI_CALL
+      DBFOpen( const char * pszDBFFile, const char * pszAccess );
+DBFHandle SHPAPI_CALL
+      DBFOpenLL( const char * pszDBFFile, const char * pszAccess,
+                 SAHooks *psHooks );
+DBFHandle SHPAPI_CALL
+      DBFCreate( const char * pszDBFFile );
+DBFHandle SHPAPI_CALL
+      DBFCreateLL( const char * pszDBFFile, SAHooks *psHooks );
+
+int	SHPAPI_CALL
+      DBFGetFieldCount( DBFHandle psDBF );
+int	SHPAPI_CALL
+      DBFGetRecordCount( DBFHandle psDBF );
+int	SHPAPI_CALL
+      DBFAddField( DBFHandle hDBF, const char * pszFieldName,
+                   DBFFieldType eType, int nWidth, int nDecimals );
+
+int	SHPAPI_CALL
+      DBFAddNativeFieldType( DBFHandle hDBF, const char * pszFieldName,
+                             char chType, int nWidth, int nDecimals );
+
+DBFFieldType SHPAPI_CALL
+      DBFGetFieldInfo( DBFHandle psDBF, int iField, 
+                       char * pszFieldName, int * pnWidth, int * pnDecimals );
+
+int SHPAPI_CALL
+      DBFGetFieldIndex(DBFHandle psDBF, const char *pszFieldName);
+
+int 	SHPAPI_CALL
+      DBFReadIntegerAttribute( DBFHandle hDBF, int iShape, int iField );
+double 	SHPAPI_CALL
+      DBFReadDoubleAttribute( DBFHandle hDBF, int iShape, int iField );
+const char SHPAPI_CALL1(*)
+      DBFReadStringAttribute( DBFHandle hDBF, int iShape, int iField );
+const char SHPAPI_CALL1(*)
+      DBFReadLogicalAttribute( DBFHandle hDBF, int iShape, int iField );
+int     SHPAPI_CALL
+      DBFIsAttributeNULL( DBFHandle hDBF, int iShape, int iField );
+
+int SHPAPI_CALL
+      DBFWriteIntegerAttribute( DBFHandle hDBF, int iShape, int iField, 
+                                int nFieldValue );
+int SHPAPI_CALL
+      DBFWriteDoubleAttribute( DBFHandle hDBF, int iShape, int iField,
+                               double dFieldValue );
+int SHPAPI_CALL
+      DBFWriteStringAttribute( DBFHandle hDBF, int iShape, int iField,
+                               const char * pszFieldValue );
+int SHPAPI_CALL
+     DBFWriteNULLAttribute( DBFHandle hDBF, int iShape, int iField );
+
+int SHPAPI_CALL
+     DBFWriteLogicalAttribute( DBFHandle hDBF, int iShape, int iField,
+			       const char lFieldValue);
+int SHPAPI_CALL
+     DBFWriteAttributeDirectly(DBFHandle psDBF, int hEntity, int iField,
+                               void * pValue );
+const char SHPAPI_CALL1(*)
+      DBFReadTuple(DBFHandle psDBF, int hEntity );
+int SHPAPI_CALL
+      DBFWriteTuple(DBFHandle psDBF, int hEntity, void * pRawTuple );
+
+int SHPAPI_CALL DBFIsRecordDeleted( DBFHandle psDBF, int iShape );
+int SHPAPI_CALL DBFMarkRecordDeleted( DBFHandle psDBF, int iShape, 
+                                      int bIsDeleted );
+
+DBFHandle SHPAPI_CALL
+      DBFCloneEmpty(DBFHandle psDBF, const char * pszFilename );
+ 
+void	SHPAPI_CALL
+      DBFClose( DBFHandle hDBF );
+void    SHPAPI_CALL
+      DBFUpdateHeader( DBFHandle hDBF );
+char    SHPAPI_CALL
+      DBFGetNativeFieldType( DBFHandle hDBF, int iField );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ndef _SHAPEFILE_H_INCLUDED */
diff --git a/ossim_plugins/geopdf/CMakeLists.txt b/ossim_plugins/geopdf/CMakeLists.txt
new file mode 100644
index 0000000..23b0856
--- /dev/null
+++ b/ossim_plugins/geopdf/CMakeLists.txt
@@ -0,0 +1,54 @@
+set(LIB_NAME ossimgeopdf_plugin)
+MESSAGE( "************** LIBRARY SETUP FOR ossimgeopdf_plugin******************")
+
+# Include ossim cmake stuff:
+include(OssimVersion)
+include(OssimCommonVariables)
+include(OssimUtilities)
+
+find_package(ossim)
+find_package(OpenThreads)
+find_package(TIFF)
+find_package(Podofo)
+
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
+INCLUDE_DIRECTORIES(${OPENTHREADS_INCLUDE_DIR})
+INCLUDE_DIRECTORIES(${TIFF_INCLUDE_DIR})
+
+IF(NOT PODOFO_INCLUDE_DIR)
+        MESSAGE(SEND_ERROR "Please pass in the PODOFO_INCLUDE_DIR and point it to the includes")
+	SET(PODOFO_INCLUDE_DIR "" CACHE STRING "Specify the full path to the includes")
+ENDIF(NOT PODOFO_INCLUDE_DIR)
+
+IF(NOT PODOFO_LIBRARY)
+        MESSAGE(SEND_ERROR "Please pass in the PODOFO_LIBRARY and point it to the library")
+	SET(PODOFO_LIBRARY "" CACHE STRING "Specify the full path to the library to link to")
+ENDIF(NOT PODOFO_LIBRARY)
+
+INCLUDE_DIRECTORIES( ${PODOFO_INCLUDE_DIR} )
+
+MESSAGE( STATUS "PODOFO_INCLUDE_DIR = ${PODOFO_INCLUDE_DIR}")
+MESSAGE( STATUS "PODOFO_LIBRARY = ${PODOFO_LIBRARY}")
+
+FILE(GLOB OSSIMPLUGIN_SRCS *.cpp)
+FILE(GLOB OSSIMPLUGIN_HEADERS *.h)
+
+####
+# OSSIMPLUGINSMAKINGDLL controls dll linkage on windows.  
+# Adding this sets OSSIM_PLUGINS_DLL #define TO "__declspec(dllexport)".
+###
+add_definitions("-DOSSIMPLUGINSMAKINGDLL")
+
+# Adjust the install library path:
+if(OSSIM_INSTALL_PLUGINS_WITH_VERSION)
+   set(INSTALL_LIBRARY_DIR   "${INSTALL_LIBRARY_DIR}/ossim-${OSSIM_VERSION}/plugins")
+else(OSSIM_INSTALL_PLUGINS_WITH_VERSION)
+   set(INSTALL_LIBRARY_DIR   "${INSTALL_LIBRARY_DIR}/ossim/plugins")
+endif(OSSIM_INSTALL_PLUGINS_WITH_VERSION)
+
+OSSIM_LINK_LIBRARY(${LIB_NAME}
+                   COMPONENT_NAME ossim TYPE "${OSSIM_PLUGIN_LINK_TYPE}"
+		   LIBRARIES ${OSSIM_LIBRARIES} ${OPENTHREADS_LIBRARY} ${PODOFO_LIBRARY} ${TIFF_LIBRARY}
+                   HEADERS "${OSSIMPLUGIN_HEADERS}"
+		   SOURCE_FILES "${OSSIMPLUGIN_SRCS}"
+                   INSTALL_LIB)
diff --git a/ossim_plugins/geopdf/ossimGeoPdfInfo.cpp b/ossim_plugins/geopdf/ossimGeoPdfInfo.cpp
new file mode 100644
index 0000000..b76075b
--- /dev/null
+++ b/ossim_plugins/geopdf/ossimGeoPdfInfo.cpp
@@ -0,0 +1,202 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author:  Mingjie Su
+//
+// Description: Ogr Info object.
+// 
+//----------------------------------------------------------------------------
+// $Id: ossimGeoPdfInfo.cpp 23664 2015-12-14 14:17:27Z dburken $
+#include <iostream>
+#include <iomanip>
+#include <sstream>
+#include <cstring> // for memset
+
+//PoDoFo includes
+#include <podofo/doc/PdfMemDocument.h>
+#include <podofo/base/PdfString.h>
+
+//ossim includes
+#include <ossim/base/ossimTrace.h>
+#include <ossim/base/ossimKeywordlist.h>
+
+#include "ossimGeoPdfInfo.h"
+
+// Static trace for debugging
+static ossimTrace traceDebug("ossimGeoPdfInfo:debug");
+static ossimTrace traceDump("ossimGeoPdfInfo:dump"); // This will dump offsets.
+
+ossimGeoPdfInfo::ossimGeoPdfInfo()
+   : ossimInfoBase(),
+     theFile(),
+     m_PdfMemDocument(NULL)
+{
+}
+
+ossimGeoPdfInfo::~ossimGeoPdfInfo()
+{
+  if (m_PdfMemDocument != NULL)
+  {
+    delete m_PdfMemDocument;
+    m_PdfMemDocument = 0;
+  }
+}
+
+bool ossimGeoPdfInfo::open(const ossimFilename& file)
+{
+   theFile = file;
+   if (isOpen())
+   {
+     PoDoFo::PdfError::EnableDebug(false); //do not print out debug info
+     m_PdfMemDocument = new PoDoFo::PdfMemDocument(theFile.c_str());
+
+     if (m_PdfMemDocument == NULL)
+     {
+       return false;
+     }
+     return true;
+   }
+   return false;
+}
+
+bool ossimGeoPdfInfo::isOpen()
+{
+  ossimString ext = theFile.ext().downcase();
+
+  if(ext == "pdf")
+  {
+    return true;
+  }
+  else
+  {
+    return false;
+  }
+}
+
+std::ostream& ossimGeoPdfInfo::print(std::ostream& out) const
+{
+  static const char MODULE[] = "ossimGeoPdfInfo::print";
+ 
+  int count = m_PdfMemDocument->GetPageCount();
+  PoDoFo::PdfString author = m_PdfMemDocument->GetInfo()->GetAuthor();
+  PoDoFo::PdfString creator = m_PdfMemDocument->GetInfo()->GetCreator();
+  PoDoFo::PdfString title = m_PdfMemDocument->GetInfo()->GetTitle();
+  PoDoFo::PdfString subject = m_PdfMemDocument->GetInfo()->GetSubject();
+  PoDoFo::PdfString keywords = m_PdfMemDocument->GetInfo()->GetKeywords();
+  PoDoFo::PdfString producer = m_PdfMemDocument->GetInfo()->GetProducer();
+
+
+  ossimString createDate;
+  ossimString modifyDate;
+  PoDoFo::PdfObject* obj = m_PdfMemDocument->GetInfo()->GetObject();
+  if (obj->IsDictionary())
+  {
+    PoDoFo::PdfDictionary pdfDictionary = obj->GetDictionary();
+
+    PoDoFo::TKeyMap keyMap = pdfDictionary.GetKeys();
+    PoDoFo::TKeyMap::iterator it = keyMap.begin();
+    while (it != keyMap.end())
+    {
+      ossimString refName = ossimString(it->first.GetName());
+      PoDoFo::PdfObject* refObj = it->second;
+
+      std::string objStr;
+      refObj->ToString(objStr);
+      
+      if (refName == "CreationDate")
+      {
+        createDate = ossimString(objStr);
+        createDate = createDate.substitute("(", "", true).trim();
+        createDate = createDate.substitute(")", "", true).trim();
+        createDate = createDate.substitute("D:", "", true).trim();
+      }
+      else if (refName == "ModDate")
+      {
+        modifyDate = ossimString(objStr);
+        modifyDate = modifyDate.substitute("(", "", true).trim();
+        modifyDate = modifyDate.substitute(")", "", true).trim();
+        modifyDate = modifyDate.substitute("D:", "", true).trim();
+      }
+      it++;
+    }
+  }
+
+  try
+  {
+     m_PdfMemDocument->FreeObjectMemory(obj);
+  }
+  catch (...)
+  {  
+  }
+
+  ossimString authorStr = author.GetString();
+  ossimString creatorStr = creator.GetString();
+  ossimString titleStr = title.GetString();
+  ossimString producerStr = producer.GetString();
+  ossimString subjectStr = subject.GetString();
+  ossimString keywordsStr = keywords.GetString();
+
+  ossimString prefix = "geopdf.";
+
+  out << prefix << "pagecount:  "
+    << ossimString::toString(count).c_str() << "\n";
+
+  if (!authorStr.empty())
+  {
+    out << prefix << "author:  "
+      << authorStr.c_str() << "\n";
+  }
+
+  if (!creatorStr.empty())
+  {
+    out << prefix << "creator:  "
+      << creatorStr.c_str() << "\n";
+  }
+
+  if (!titleStr.empty())
+  {
+    out << prefix << "title:  "
+      << titleStr.c_str() << "\n";
+  }
+
+  if (!producerStr.empty())
+  {
+    out << prefix << "producer:  "
+      << producerStr.c_str() << "\n";
+  }
+
+  if (!subjectStr.empty())
+  {
+    out << prefix << "subject:  "
+      << subjectStr.c_str() << "\n";
+  }
+
+  if (!keywordsStr.empty())
+  {
+    out << prefix << "keywords:  "
+      << keywordsStr.c_str() << "\n";
+  }
+
+  if (!createDate.empty())
+  {
+    out << prefix << "creationdate:  "
+      << createDate.c_str() << "\n";
+  }
+
+  if (!modifyDate.empty())
+  {
+    out << prefix << "modificationdate:  "
+      << modifyDate.c_str() << "\n";
+  }
+
+  if (traceDebug())
+  {    
+     ossimNotify(ossimNotifyLevel_DEBUG)
+      << MODULE << " DEBUG Entered...\n";
+  }
+  return out;
+}
+
diff --git a/ossim_plugins/geopdf/ossimGeoPdfInfo.h b/ossim_plugins/geopdf/ossimGeoPdfInfo.h
new file mode 100644
index 0000000..8cba5b2
--- /dev/null
+++ b/ossim_plugins/geopdf/ossimGeoPdfInfo.h
@@ -0,0 +1,70 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author:  Mingjie Su
+//
+// Description: Gdal Ogr Info object.
+// 
+//----------------------------------------------------------------------------
+// $Id: ossimGeoPdfInfo.h 23664 2015-12-14 14:17:27Z dburken $
+#ifndef ossimGeoPdfInfo_HEADER
+#define ossimGeoPdfInfo_HEADER
+
+#include <iosfwd>
+#include <string>
+#include <vector>
+
+//PoDoFo includes
+#include <podofo/podofo.h>
+
+#include <ossim/base/ossimConstants.h>
+#include <ossim/support_data/ossimInfoBase.h>
+#include <ossim/base/ossimFilename.h>
+
+class ossimKeywordlist;
+class PdfMemDocument;
+/**
+ * @brief GeoPdf info class.
+ *
+ * Encapsulates the GeoPdf functionality.
+ */
+class ossimGeoPdfInfo : public ossimInfoBase
+{
+public:
+
+   /** default constructor */
+   ossimGeoPdfInfo();
+
+   /** virtual destructor */
+   virtual ~ossimGeoPdfInfo();
+
+   /**
+    * @brief open method.
+    *
+    * @param file File name to open.
+    * @return true on success false on error.
+    */
+   virtual bool open(const ossimFilename& file);
+
+   /**
+    * Print method.
+    *
+    * @param out Stream to print to.
+    * 
+    * @return std::ostream&
+    */
+   virtual std::ostream& print(std::ostream& out) const;
+
+   bool isOpen();
+
+   private: 
+   
+     ossimFilename              theFile;
+     PoDoFo::PdfMemDocument*    m_PdfMemDocument;
+};
+
+#endif /* End of "#ifndef ossimGeoPdfInfo_HEADER" */
+
diff --git a/ossim_plugins/geopdf/ossimGeoPdfInfoFactory.cpp b/ossim_plugins/geopdf/ossimGeoPdfInfoFactory.cpp
new file mode 100644
index 0000000..b7a2530
--- /dev/null
+++ b/ossim_plugins/geopdf/ossimGeoPdfInfoFactory.cpp
@@ -0,0 +1,55 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author:  Mingjie Su
+//
+// Description: Factory for info objects.
+// 
+//----------------------------------------------------------------------------
+// $Id: ossimGeoPdfInfoFactory.cpp 23664 2015-12-14 14:17:27Z dburken $
+
+#include <ossim/support_data/ossimInfoFactory.h>
+#include <ossim/support_data/ossimInfoBase.h>
+#include <ossim/base/ossimFilename.h>
+#include <ossim/base/ossimRefPtr.h>
+
+#include "ossimGeoPdfInfoFactory.h"
+#include "ossimGeoPdfInfo.h"
+
+ossimGeoPdfInfoFactory::~ossimGeoPdfInfoFactory()
+{}
+
+ossimGeoPdfInfoFactory* ossimGeoPdfInfoFactory::instance()
+{
+   static ossimGeoPdfInfoFactory sharedInstance;
+
+   return &sharedInstance;
+}
+
+ossimInfoBase* ossimGeoPdfInfoFactory::create(const ossimFilename& file) const
+{
+   ossimRefPtr<ossimInfoBase> result = 0;
+
+   result = new ossimGeoPdfInfo();
+   if ( result->open(file) )
+   {
+      return result.release();
+   }
+   return 0;
+}
+
+ossimGeoPdfInfoFactory::ossimGeoPdfInfoFactory()
+{}
+
+ossimGeoPdfInfoFactory::ossimGeoPdfInfoFactory(const ossimGeoPdfInfoFactory& /* obj */ )
+{}
+
+const ossimGeoPdfInfoFactory& ossimGeoPdfInfoFactory::operator=(
+   const ossimGeoPdfInfoFactory& /* rhs */)
+{
+   return *this;
+}
+
diff --git a/ossim_plugins/geopdf/ossimGeoPdfInfoFactory.h b/ossim_plugins/geopdf/ossimGeoPdfInfoFactory.h
new file mode 100644
index 0000000..280d434
--- /dev/null
+++ b/ossim_plugins/geopdf/ossimGeoPdfInfoFactory.h
@@ -0,0 +1,57 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author:  Mingjie Su
+//
+// Description: Factory for Ogr info objects.
+// 
+//----------------------------------------------------------------------------
+// $Id: ossimGeoPdfInfoFactory.h 23664 2015-12-14 14:17:27Z dburken $
+#ifndef ossimGeoPdfInfoFactory_HEADER
+#define ossimGeoPdfInfoFactory_HEADER
+
+#include <ossim/base/ossimConstants.h>
+#include <ossim/support_data/ossimInfoFactoryInterface.h>
+
+class ossimFilename;
+class ossimInfoBase;
+
+/**
+ * @brief Info factory.
+ */
+class ossimGeoPdfInfoFactory : public ossimInfoFactoryInterface
+{
+public:
+
+   /** virtual destructor */
+   virtual ~ossimGeoPdfInfoFactory();
+
+   static ossimGeoPdfInfoFactory* instance();
+
+   /**
+    * @brief create method.
+    *
+    * @param file Some file you want info for.
+    *
+    * @return ossimInfoBase* on success 0 on failure.  Caller is responsible
+    * for memory.
+    */
+   virtual ossimInfoBase* create(const ossimFilename& file) const;
+   
+private:
+   
+   /** hidden from use default constructor */
+   ossimGeoPdfInfoFactory();
+
+   /** hidden from use copy constructor */
+   ossimGeoPdfInfoFactory(const ossimGeoPdfInfoFactory& obj);
+
+   /** hidden from use operator = */
+   const ossimGeoPdfInfoFactory& operator=(const ossimGeoPdfInfoFactory& rhs);
+};
+
+#endif /* End of "#ifndef ossimInfoFactory_HEADER" */
+
diff --git a/ossim_plugins/geopdf/ossimGeoPdfPluginInit.cpp b/ossim_plugins/geopdf/ossimGeoPdfPluginInit.cpp
new file mode 100644
index 0000000..3f54f0d
--- /dev/null
+++ b/ossim_plugins/geopdf/ossimGeoPdfPluginInit.cpp
@@ -0,0 +1,83 @@
+//----------------------------------------------------------------------------
+//
+// License:  See top level LICENSE.txt file
+//
+// Author:  Mingjie Su
+//
+// Description: OSSIM GeoPdf plugin initialization
+// code.
+//
+//----------------------------------------------------------------------------
+// $Id: ossimGeoPdfPluginInit.cpp 20935 2012-05-18 14:19:30Z dburken $
+
+#include <ossim/plugin/ossimSharedObjectBridge.h>
+#include <ossimPluginConstants.h>
+#include <ossim/imaging/ossimImageHandlerRegistry.h>
+#include <ossim/imaging/ossimOverviewBuilderFactoryRegistry.h>
+#include <ossim/support_data/ossimInfoFactoryRegistry.h>
+
+#include "ossimGeoPdfReaderFactory.h"
+#include "ossimGeoPdfInfoFactory.h"
+
+static void setDescription(ossimString& description)
+{
+   description = "GeoPdf reader plugin\n\n";
+}
+
+
+extern "C"
+{
+   ossimSharedObjectInfo  myInfo;
+   ossimString theDescription;
+   std::vector<ossimString> theObjList;
+
+   const char* getDescription()
+   {
+      return theDescription.c_str();
+   }
+
+   int getNumberOfClassNames()
+   {
+      return (int)theObjList.size();
+   }
+
+   const char* getClassName(int idx)
+   {
+      if(idx < (int)theObjList.size())
+      {
+         return theObjList[0].c_str();
+      }
+      return (const char*)0;
+   }
+
+   /* Note symbols need to be exported on windoze... */ 
+   OSSIM_PLUGINS_DLL void ossimSharedLibraryInitialize(
+      ossimSharedObjectInfo** info)
+   {    
+      myInfo.getDescription = getDescription;
+      myInfo.getNumberOfClassNames = getNumberOfClassNames;
+      myInfo.getClassName = getClassName;
+      
+      *info = &myInfo;
+      
+      /* Register the readers... */
+      ossimImageHandlerRegistry::instance()->
+         registerFactory(ossimGeoPdfReaderFactory::instance(), false);
+
+      /* Register GeoPdf info objects... */
+      ossimInfoFactoryRegistry::instance()->
+        registerFactory(ossimGeoPdfInfoFactory::instance());
+
+      setDescription(theDescription);
+   }
+   
+   /* Note symbols need to be exported on windoze... */ 
+   OSSIM_PLUGINS_DLL void ossimSharedLibraryFinalize()
+   {
+      ossimImageHandlerRegistry::instance()->
+         unregisterFactory(ossimGeoPdfReaderFactory::instance());
+         
+      ossimInfoFactoryRegistry::instance()->
+         unregisterFactory(ossimGeoPdfInfoFactory::instance());
+   }
+}
diff --git a/ossim_plugins/geopdf/ossimGeoPdfReader.cpp b/ossim_plugins/geopdf/ossimGeoPdfReader.cpp
new file mode 100644
index 0000000..82e98f4
--- /dev/null
+++ b/ossim_plugins/geopdf/ossimGeoPdfReader.cpp
@@ -0,0 +1,2163 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author:  Mingjie Su
+//
+// Description:  Class definition for GeoPdf reader.
+//
+//----------------------------------------------------------------------------
+// $Id: ossimGeoPdfReader.cpp 23664 2015-12-14 14:17:27Z dburken $
+
+#include <fstream>
+#include <iostream>
+#include <string>
+
+//PoDoFo includes
+#include <podofo/doc/PdfMemDocument.h>
+#include <podofo/base/PdfName.h>
+#include <podofo/base/PdfObject.h>
+
+//ossim includes
+#include <ossim/base/ossimCommon.h>
+#include <ossim/base/ossimDpt.h>
+#include <ossim/base/ossimGrect.h>
+#include <ossim/base/ossimEndian.h>
+#include <ossim/base/ossimException.h>
+#include <ossim/base/ossimIoStream.h>
+#include <ossim/base/ossimKeywordlist.h>
+#include <ossim/base/ossimNotify.h>
+#include <ossim/base/ossimScalarTypeLut.h>
+#include <ossim/base/ossimTrace.h>
+#include <ossim/base/ossimUnitTypeLut.h>
+#include <ossim/imaging/ossimImageDataFactory.h>
+#include <ossim/imaging/ossimImageGeometryRegistry.h>
+#include <ossim/projection/ossimProjection.h>
+#include <ossim/projection/ossimProjectionFactoryRegistry.h>
+#include <ossim/projection/ossimEpsgProjectionFactory.h>
+#include <ossim/projection/ossimAlbersProjection.h>
+#include <ossim/projection/ossimAzimEquDistProjection.h>
+#include <ossim/projection/ossimBonneProjection.h>
+#include <ossim/projection/ossimCassiniProjection.h>
+#include <ossim/projection/ossimCylEquAreaProjection.h>
+#include <ossim/projection/ossimEckert4Projection.h>
+#include <ossim/projection/ossimEckert6Projection.h>
+#include <ossim/projection/ossimEquDistCylProjection.h>
+#include <ossim/projection/ossimGnomonicProjection.h>
+#include <ossim/projection/ossimLambertConformalConicProjection.h>
+#include <ossim/projection/ossimMercatorProjection.h>
+#include <ossim/projection/ossimMillerProjection.h>
+#include <ossim/projection/ossimMollweidProjection.h>
+#include <ossim/projection/ossimNewZealandMapGridProjection.h>
+#include <ossim/projection/ossimObliqueMercatorProjection.h>
+#include <ossim/projection/ossimPolarStereoProjection.h>
+#include <ossim/projection/ossimPolyconicProjection.h>
+#include <ossim/projection/ossimSinusoidalProjection.h>
+#include <ossim/projection/ossimStereographicProjection.h>
+#include <ossim/projection/ossimTransMercatorProjection.h>
+#include <ossim/projection/ossimTransCylEquAreaProjection.h>
+#include <ossim/projection/ossimUtmProjection.h>
+#include <ossim/projection/ossimVanDerGrintenProjection.h>
+#include <ossim/projection/ossimUpsProjection.h>
+#include <ossim/support_data/ossimAuxFileHandler.h>
+
+#include "ossimGeoPdfReader.h"
+
+#ifdef OSSIM_ID_ENABLED
+static const char OSSIM_ID[] = "$Id";
+#endif
+ 
+static ossimTrace traceDebug("ossimGeoPdfReader:debug");
+static ossimTrace traceDump("ossimGeoPdfReader:dump");
+//static ossimOgcWktTranslator wktTranslator;
+
+RTTI_DEF1_INST(ossimGeoPdfReader,
+               "ossimGeoPdfReader",
+               ossimImageHandler);
+
+static ossimString originLatKey = "OriginLatitude";
+static ossimString centralMeridianKey = "CentralMeridian";
+static ossimString standardParallelOneKey = "StandardParallelOne";
+static ossimString standardParallelTwoKey = "StandardParallelTwo";
+static ossimString falseEastingKey = "FalseEasting";
+static ossimString falseNorthingKey = "FalseNorthing";
+static ossimString scaleFactorKey = "ScaleFactor";
+static ossimString latitudeOneKey = "LatitudeOne";
+static ossimString longitudeOneKey = "LongitudeOne";
+static ossimString latitudeTwoKey = "LatitudeTwo";
+static ossimString longitudeTwoKey = "LongitudeTwo";
+static ossimString zoneKey = "Zone";
+static ossimString hemisphereKey = "Hemisphere";
+
+class ossimGeoPdfVectorPageNode
+{
+public:
+   ossimGeoPdfVectorPageNode()
+      : m_boundingRect(),
+        m_geoImage(0)
+      {};
+   
+   ~ossimGeoPdfVectorPageNode()
+      {
+         if (m_geoImage.valid())
+         {
+            m_geoImage = 0;
+         }
+      }
+   
+   void setGeoImage(ossimRefPtr<ossimImageGeometry> image)
+      {
+         m_geoImage = image;
+      }
+   
+   void setBoundingBox(const ossimDrect& bounds)
+      {
+         m_boundingRect = bounds;
+      }
+   
+   ossimDrect m_boundingRect;  //world
+   ossimRefPtr<ossimImageGeometry> m_geoImage;
+};
+
+ossimString getValueFromMap(std::map<ossimString, ossimString, ossimStringLtstr> info,
+                            ossimString key)
+{
+   ossimString valueStr;
+   std::map<ossimString, ossimString, ossimStringLtstr>::iterator it = info.find(key);
+   if (it != info.end())
+   {
+      valueStr = it->second;
+   }
+   return valueStr;
+}
+ 
+ossimGeoPdfReader::ossimGeoPdfReader()
+   : ossimImageHandler(),
+     m_imageRect(OSSIM_INT_NAN, OSSIM_INT_NAN, OSSIM_INT_NAN, OSSIM_INT_NAN),
+     m_numberOfBands(0),
+     m_numberOfLines(0),
+     m_numberOfSamples(0),
+     m_numOfFramesVertical(0),
+     m_numOfFramesHorizontal(0),
+     m_currentRow(-1),
+     m_currentCol(-1),
+     m_frameWidthVector(),
+     m_frameHeightVector(),
+     m_scalarType(OSSIM_UINT8),
+     m_tile(0),
+     m_pdfMemDocument(NULL),
+     m_isLGIDict(false),
+     m_isJpeg(true),
+     m_pageVector(0),
+     m_cacheTile(0),
+     m_cacheSize(0),
+     m_cacheId(-1),
+     m_frameEntryArray(0)
+{
+}
+
+ossimGeoPdfReader::~ossimGeoPdfReader()
+{
+   closeEntry();
+}
+
+void ossimGeoPdfReader::resetCacheBuffer(ossimFrameEntryData entry)
+{
+   ossim_int32 row = entry.theRow;
+   ossim_int32 col = entry.theCol;
+   ossim_int32 width = m_frameWidthVector[col];
+   ossim_int32 height = m_frameHeightVector[row];
+   ossim_int32 pixelRow = entry.thePixelRow;
+   ossim_int32 pixelCol = entry.thePixelCol;
+
+   ossimIrect imageRect(pixelCol, pixelRow, pixelCol+width-1, pixelRow+height-1);
+
+   ossimIrect cacheRect(pixelCol, pixelRow, pixelCol+m_cacheSize.x-1, pixelRow+m_cacheSize.y-1);
+
+   ossimIrect clipRect = cacheRect.clipToRect(imageRect);
+
+   m_cacheTile->setImageRectangle(clipRect);
+
+   if (!cacheRect.completely_within(imageRect))
+   {
+      m_cacheTile->makeBlank();
+   }
+
+   m_cacheTile->validate();
+
+   void* lineBuffer = 0;
+   std::vector<PoDoFo::PdfObject*> imageObjects = entry.theFrameEntry;
+   if (imageObjects.size() == 1)
+   {
+      PoDoFo::PdfMemStream* pStream = dynamic_cast<PoDoFo::PdfMemStream*>(imageObjects[0]->GetStream());
+      pStream->Uncompress();
+      PoDoFo::pdf_long length = pStream->GetLength(); 
+      pStream->GetCopy((char**)&lineBuffer, &length);
+      if (lineBuffer)
+      {
+         m_cacheTile->loadTile(lineBuffer, imageRect, clipRect, OSSIM_BIP);
+         delete [] (char*)lineBuffer;
+         lineBuffer = 0;
+      }
+   }
+   else
+   {
+      for (ossim_uint32 band = 0; band < m_numberOfBands; ++band)
+      {
+         PoDoFo::PdfMemStream* pStream = dynamic_cast<PoDoFo::PdfMemStream*>(imageObjects[band]->GetStream());
+         pStream->Uncompress();
+         PoDoFo::pdf_long length = pStream->GetLength(); 
+         pStream->GetCopy((char**)&lineBuffer, &length);
+
+         if (lineBuffer)
+         {
+            m_cacheTile->loadBand(lineBuffer, imageRect,clipRect, band);
+            delete [] (char*)lineBuffer;
+            lineBuffer = 0;
+         }
+      }
+   }
+   if (lineBuffer != NULL)
+   {
+      delete [] (char*)lineBuffer;
+      lineBuffer = 0;
+   }
+}
+
+ossimString ossimGeoPdfReader::getShortName()const
+{
+   return ossimString("ossim_geopdf_reader");
+}
+
+ossimString ossimGeoPdfReader::getLongName()const
+{
+   return ossimString("ossim geopdf reader");
+}
+
+ossimString ossimGeoPdfReader::getClassName()const
+{
+   return ossimString("ossimGeoPdfReader");
+}
+
+ossim_uint32 ossimGeoPdfReader::getNumberOfLines(
+   ossim_uint32 resLevel) const
+{
+   if (resLevel == 0)
+   {
+      return m_numberOfLines;
+   }
+   else if ( theOverview.valid() )
+   {
+      return theOverview->getNumberOfLines(resLevel);
+   }
+
+   return 0;
+}
+
+ossim_uint32 ossimGeoPdfReader::getNumberOfSamples(
+   ossim_uint32 resLevel) const
+{
+   if (resLevel == 0)
+   {
+      return m_numberOfSamples;
+   }
+   else if ( theOverview.valid() )
+   {
+      return theOverview->getNumberOfSamples(resLevel);
+   }
+
+   return 0;
+}
+
+bool ossimGeoPdfReader::open()
+{
+   static const char MODULE[] = "ossimGeoPdfReader::open";
+   
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " entered...\n"
+         << "image: " << theImageFile << "\n";
+   }
+   
+   bool result = false;
+   closeEntry();
+   
+   if ( theImageFile.size() )
+   {
+      PoDoFo::PdfError::EnableDebug(false);//do not print out debug info
+      
+      try
+      {
+         m_pdfMemDocument = new PoDoFo::PdfMemDocument(theImageFile.c_str());
+      }
+      catch (...)
+      {
+         return false;
+      }
+   
+      if (m_pdfMemDocument != NULL)
+      {
+         int count = m_pdfMemDocument->GetPageCount();
+         for(int i = 0; i < count; ++i)
+         {
+            PoDoFo::PdfPage* pdfPage = m_pdfMemDocument->GetPage(i);
+            if( pdfPage ) 
+            {
+               PoDoFo::PdfObject* pdfObject = pdfPage->GetObject();
+               PoDoFo::PdfObject* geoPdfObject = NULL;
+               if( pdfObject->GetDictionary().HasKey(PoDoFo::PdfName("LGIDict") ) )
+               {
+                  geoPdfObject = pdfObject->GetDictionary().GetKey(PoDoFo::PdfName("LGIDict"));
+                  m_isLGIDict = true;
+               }
+               else if (pdfObject->GetDictionary().HasKey(PoDoFo::PdfName("VP") ))
+               {
+                  geoPdfObject = pdfObject->GetDictionary().GetKey(PoDoFo::PdfName("VP"));
+               }
+            
+               if (geoPdfObject)
+               {
+                  std::string imagInfo; //try to get tile structure information
+                  geoPdfObject->ToString(imagInfo);
+                  ossimString imagInfoStr = imagInfo;
+               
+                  if (imagInfoStr.downcase().contains("tile") == false)//if not, try to get tile structure info from source object
+                  {
+                     PoDoFo::PdfObject* pSource = pdfPage->GetResources();
+                     pSource->ToString(imagInfo);
+                     imagInfoStr = imagInfo;
+                  }
+                  std::vector<ossimString> imageInfoVector;
+                  imageInfoVector.push_back(imagInfoStr);
+                  parseTileStructure(imageInfoVector);
+                  setPodofoImageInfo();
+                  buildFrameEntryArray();
+                  setPodofoInfo(geoPdfObject);
+               }
+               else
+               {
+                  continue;
+               }
+
+               // Create the geometry.
+               ossimRefPtr<ossimImageGeometry> geoImage = new ossimImageGeometry();
+               geoImage->setProjection(getGeoProjection());
+               geoImage->setImageSize(ossimIpt(m_numberOfSamples, m_numberOfLines));
+
+               // Create the node.
+               ossimGeoPdfVectorPageNode* node = new ossimGeoPdfVectorPageNode();
+               node->setGeoImage(geoImage);
+               node->setBoundingBox(computeBoundingRect(geoImage));
+
+               // Add to array.
+               m_pageVector.push_back(node);
+            
+               m_pdfMemDocument->FreeObjectMemory(pdfObject);
+            }
+         
+         } // Matches: for(int i = 0; i < count; ++i)
+      
+         if ( m_pageVector.size() )
+         {
+            result = true;
+         }
+      }
+   
+      m_tile = ossimImageDataFactory::instance()->create(this, this);
+      m_tile->initialize();
+      m_cacheTile = (ossimImageData*)m_tile->dup();
+      m_cacheTile->initialize();
+   
+      m_cacheSize.x = m_frameWidthVector[0];
+      m_cacheSize.y = m_frameHeightVector[0];
+   
+      ossimAppFixedTileCache::instance()->deleteCache(m_cacheId);
+      m_cacheId = ossimAppFixedTileCache::instance()->newTileCache(getImageRectangle(), m_cacheSize);
+   
+      completeOpen();
+   
+      if (result == false)
+      {
+         closeEntry();
+      }
+      
+   } // Matches: if ( theImageFile.size() )
+   
+   return result;
+}
+
+void ossimGeoPdfReader::parseTileStructure(std::vector<ossimString> tileInfo)
+{
+   m_podofoTileInfo.clear();
+   std::vector<ossimString> tileInfoVector;
+   for (ossim_uint32 index = 0; index < tileInfo.size(); ++index)
+   {
+      std::vector<ossimString> tmpVector = tileInfo[index].split("\n");
+      for (ossim_uint32 i = 0; i < tmpVector.size(); i++)
+      {
+         ossimString tmpStr = tmpVector[i];
+         if (tmpStr.downcase().contains("layer_"))
+         {
+            buildTileInfo(tmpStr);
+         }
+         else if (tmpStr.downcase().contains("tile"))
+         {
+            tileInfoVector.push_back(tmpStr);
+         }
+      }
+   }
+
+   if (m_podofoTileInfo.size() == 0)//does not layer information, try tile information
+   {
+      for (ossim_uint32 index = 0; index < tileInfoVector.size(); ++index)
+      {
+         buildTileInfo(tileInfoVector[index]);
+      }
+   }
+  
+   tileInfoVector.clear();
+}
+
+void ossimGeoPdfReader::buildTileInfo(ossimString tileInfo)
+{
+   std::vector<ossimString> tmpKeyValue = tileInfo.split(" ");
+
+   if (tmpKeyValue.size() > 1)
+   {
+      std::vector<ossimString> layerNameVector = tmpKeyValue[0].split("_");
+      ossim_int32 col = layerNameVector[layerNameVector.size()-2].toInt();
+      ossim_int32 row = layerNameVector[layerNameVector.size()-1].toInt();
+      std::pair<ossim_int32, ossim_int32> tileRowCol;
+      tileRowCol = make_pair(row, col);
+      ossim_int32 tileIndex = tmpKeyValue[1].toInt();
+
+      m_podofoTileInfo[tileIndex] = tileRowCol;
+   }
+}
+
+ossimDrect ossimGeoPdfReader::computeBoundingRect(ossimRefPtr<ossimImageGeometry> geoImage)
+{
+   // ossim_uint32 entry = 0;
+   ossimKeywordlist kwl; 
+   ossimString pfx = "image";
+   pfx += ossimString::toString(0);
+   pfx += ".";
+
+   double ll_lat = 0.0;
+   double ll_lon = 0.0;
+   double lr_lat = 0.0;
+   double lr_lon = 0.0;
+   double ul_lat = 0.0;
+   double ul_lon = 0.0;
+   double ur_lat = 0.0;
+   double ur_lon = 0.0;
+   ossimDrect rect2(ossimDpt(0,0), ossimDpt(0,0),ossimDpt(0,0),ossimDpt(0,0));
+
+   ossimProjection* proj = geoImage->getProjection();
+   if (m_isLGIDict)
+   {
+      ossimString bBoxStr = getValueFromMap(m_podofoProjInfo, "Registration");
+      std::vector<ossimString> tmpVector = bBoxStr.split(")");
+      std::vector<ossimString> tmpVector1;
+      for (ossim_uint32 i = 0; i < tmpVector.size(); i++)
+      {
+         ossimString tmpStr = tmpVector[i];
+         if (tmpStr.contains("(") || tmpStr.contains(")"))
+         {
+            tmpStr = tmpStr.substitute("[", "", true).trim();
+            tmpStr = tmpStr.substitute("]", "", true).trim();
+            tmpStr = tmpStr.substitute("(", "", true).trim();
+            tmpStr = tmpStr.substitute(")", "", true).trim();
+            tmpVector1.push_back(tmpStr);
+         }
+      }
+
+      if (tmpVector1.size() == 8)
+      {
+         ll_lon = tmpVector1[2].toDouble();
+         ll_lat = tmpVector1[3].toDouble();
+         ur_lon = tmpVector1[6].toDouble();
+         ur_lat = tmpVector1[7].toDouble();
+
+         lr_lon = tmpVector1[6].toDouble();
+         lr_lat = tmpVector1[3].toDouble();
+         ul_lon = tmpVector1[2].toDouble();
+         ul_lat = tmpVector1[7].toDouble();
+      }
+      else if (tmpVector1.size() == 16)
+      {
+         ll_lon = tmpVector1[2].toDouble();
+         ll_lat = tmpVector1[3].toDouble();
+         lr_lon = tmpVector1[6].toDouble();
+         lr_lat = tmpVector1[7].toDouble();
+
+         ur_lon = tmpVector1[10].toDouble();
+         ur_lat = tmpVector1[11].toDouble();
+         ul_lon = tmpVector1[14].toDouble();
+         ul_lat = tmpVector1[15].toDouble();
+      }
+   }
+   else
+   {
+      std::vector<ossimString> tmpVector;
+      ossimString coodStr = getValueFromMap(m_podofoProjInfo, "GPTS");
+      if (!coodStr.empty())
+      {
+         std::vector<ossimString> coodVector = coodStr.split(" ");
+
+         for (ossim_uint32 i = 0; i < coodVector.size(); i++)
+         {
+            ossimString tmp = coodVector[i].trim();
+            if (!tmp.empty() && tmp.contains("[") == false &&  tmp.contains("]") == false)
+            {
+               tmpVector.push_back(tmp);
+            }
+         }
+
+         ll_lat = tmpVector[0].toDouble();
+         ll_lon = tmpVector[1].toDouble();
+         lr_lat = tmpVector[2].toDouble();
+         lr_lon = tmpVector[3].toDouble();
+         ur_lat = tmpVector[4].toDouble();
+         ur_lon = tmpVector[5].toDouble();
+         ul_lat = tmpVector[6].toDouble();
+         ul_lon = tmpVector[7].toDouble();
+      }
+   }
+
+   if(proj)
+   {
+      ossimMapProjection* mapProj = dynamic_cast<ossimMapProjection*>(proj);
+  
+      ossimDrect rect(ossimDpt(ul_lon, ul_lat),
+                      ossimDpt(ur_lon, ur_lat),
+                      ossimDpt(lr_lon, lr_lat),
+                      ossimDpt(ll_lon, ll_lat), OSSIM_RIGHT_HANDED); 
+
+      std::vector<ossimGpt> points;
+      if (mapProj->isGeographic())
+      {
+         ossimGpt g1(ul_lat, ul_lon);
+         ossimGpt g2(ur_lat, ur_lon);
+         ossimGpt g3(lr_lat, lr_lon);
+         ossimGpt g4(ll_lat, ll_lon);
+
+         points.push_back(g1);
+         points.push_back(g2);
+         points.push_back(g3);
+         points.push_back(g4);
+         ossimGpt tie(ul_lat, ul_lon);
+         mapProj->setUlTiePoints(tie);
+         if (m_numberOfLines != 0 && m_numberOfSamples != 0)
+         {
+            ossim_float64 scaleLat = (ul_lat - lr_lat)/m_numberOfLines;
+            ossim_float64 scaleLon = (lr_lon - ul_lon)/m_numberOfSamples;
+
+            ossimDpt gsd(fabs(scaleLon), fabs(scaleLat));
+            mapProj->setDecimalDegreesPerPixel(gsd);
+         }
+      }
+      else if (!mapProj->isGeographic() && m_isLGIDict == false)
+      {
+         ossimGpt g1(ul_lat, ul_lon);
+         ossimGpt g2(ur_lat, ur_lon);
+         ossimGpt g3(lr_lat, lr_lon);
+         ossimGpt g4(ll_lat, ll_lon);
+
+         points.push_back(g1);
+         points.push_back(g2);
+         points.push_back(g3);
+         points.push_back(g4);
+        
+         if (m_numberOfLines != 0 && m_numberOfSamples != 0)
+         {
+            ossimDpt ulEn = mapProj->forward(g1);
+            ossimDpt lrEn = mapProj->forward(g3);
+
+            mapProj->setUlEastingNorthing(ulEn);
+
+            ossim_float64 scaleLat = (ulEn.y - lrEn.y)/m_numberOfLines;
+            ossim_float64 scaleLon = (lrEn.x - ulEn.x)/m_numberOfSamples;
+
+            ossimDpt gsd(fabs(scaleLon), fabs(scaleLat));
+            mapProj->setMetersPerPixel(gsd);
+         }
+      }
+      else
+      {
+         ossimGpt g1 = proj->inverse(rect.ul());
+         ossimGpt g2 = proj->inverse(rect.ur());
+         ossimGpt g3 = proj->inverse(rect.lr());
+         ossimGpt g4 = proj->inverse(rect.ll());
+
+         points.push_back(g1);
+         points.push_back(g2);
+         points.push_back(g3);
+         points.push_back(g4);
+
+         ossimDpt tie(ul_lon, ul_lat);
+         if (mapProj)
+         {
+            mapProj->setUlTiePoints(tie);
+            if (m_numberOfLines != 0 && m_numberOfSamples != 0)
+            {
+               ossim_float64 scaleLat = (ul_lat - lr_lat)/m_numberOfLines;
+               ossim_float64 scaleLon = (ur_lon - ll_lon)/m_numberOfSamples; 
+               ossimDpt gsd(fabs(scaleLon), fabs(scaleLat));
+               mapProj->setMetersPerPixel(gsd);
+            }
+         }
+      }
+
+      std::vector<ossimDpt> rectTmp;
+      rectTmp.resize(4);
+
+      for(std::vector<ossimGpt>::size_type index=0; index < 4; ++index)
+      {
+         geoImage->worldToLocal(points[(int)index], rectTmp[(int)index]);
+      }
+
+      rect2 = ossimDrect(rectTmp);
+     
+   }
+   return rect2;
+}
+
+bool ossimGeoPdfReader::setCurrentEntry(ossim_uint32 entryIdx)
+{
+   if (m_pageVector.size() > entryIdx)
+   {
+      theGeometry = 0;
+      m_imageRect.makeNan();
+      theGeometry = m_pageVector[entryIdx]->m_geoImage;
+      m_imageRect = m_pageVector[entryIdx]->m_boundingRect;
+      if (theGeometry.valid())
+      {
+         return true;
+      }
+   }
+   return false;
+}
+
+bool ossimGeoPdfReader::saveState(ossimKeywordlist& kwl,
+                                  const char* prefix) const
+{
+   for (ossim_uint32 i = 0; i < m_pageVector.size(); i++)
+   {
+      ossimRefPtr<ossimImageGeometry> imageGeometry = m_pageVector[i]->m_geoImage;
+      if(imageGeometry.valid())
+      {
+         imageGeometry->saveState(kwl, prefix);
+      }
+   }
+
+   return ossimImageHandler::saveState(kwl, prefix);
+}
+
+bool ossimGeoPdfReader::isOpen()const
+{
+   ossimString ext = theImageFile.ext().downcase();
+
+   if(ext == "pdf")
+   {
+      return true;
+   }
+   else
+   {
+      return false;
+   }
+}
+
+void ossimGeoPdfReader::closeEntry()
+{
+   m_tile = 0;
+   m_cacheTile = 0;
+   m_podofoProjInfo.clear();
+   m_podofoTileInfo.clear();
+   m_frameWidthVector.clear();
+   m_frameHeightVector.clear();
+   
+   if (m_pdfMemDocument)
+   {
+      std::map<int, PoDoFo::PdfObject*>::iterator it = m_podofoImageObjs.begin();
+      while (it != m_podofoImageObjs.end())
+      {
+         m_pdfMemDocument->FreeObjectMemory(it->second);
+         it++;
+      }
+   }
+   m_podofoImageObjs.clear();
+
+   if (m_frameEntryArray.size() > 0)
+   {
+      for (ossim_uint32 i = 0; i < m_frameEntryArray.size(); i++)
+      {
+         std::vector< std::vector<PoDoFo::PdfObject*> > tmpVector = m_frameEntryArray[i];
+         for (ossim_uint32 j = 0; j < tmpVector.size(); j++)
+         {
+            std::vector<PoDoFo::PdfObject*> tmpVector1 = tmpVector[j];
+            for (ossim_uint32 k = 0; k < tmpVector1.size(); k++)
+            {
+               m_pdfMemDocument->FreeObjectMemory(tmpVector1[k]);
+            }
+         }
+      }
+   }
+  m_frameEntryArray.clear();
+   
+   if (m_pdfMemDocument != NULL)
+   {
+      delete m_pdfMemDocument;
+      m_pdfMemDocument = 0;
+   }
+   
+   for(ossim_uint32 i = 0; i < m_pageVector.size(); ++i)
+   {
+      if(m_pageVector[i])
+      {
+         delete m_pageVector[i];
+      }
+   }
+   m_pageVector.clear();
+   
+   ossimImageHandler::close();
+}
+
+ossim_uint32 ossimGeoPdfReader::getNumberOfEntries() const
+{
+   return (ossim_uint32)m_pageVector.size();
+}
+
+void ossimGeoPdfReader::getEntryList(std::vector<ossim_uint32>& entryList) const
+{
+   if (m_pageVector.size() > 0)
+   {
+      for (ossim_uint32 i = 0; i < getNumberOfEntries(); i++)
+      {
+         entryList.push_back(i);
+      }
+   }
+   else
+   {
+      ossimImageHandler::getEntryList(entryList);
+   }
+}
+
+ossimRefPtr<ossimImageData> ossimGeoPdfReader::getTile(
+   const ossimIrect& rect, ossim_uint32 resLevel)
+{
+   if (m_tile.valid())
+   {
+      // Image rectangle must be set prior to calling getTile.
+      m_tile->setImageRectangle(rect);
+
+      if ( getTile( m_tile.get(), resLevel ) == false )
+      {
+         if (m_tile->getDataObjectStatus() != OSSIM_NULL)
+         {
+            m_tile->makeBlank();
+         }
+      }
+   }
+
+   return m_tile;
+}
+
+bool ossimGeoPdfReader::getTile(ossimImageData* result,
+                                ossim_uint32 resLevel)
+{
+   bool status = false;
+
+   //---
+   // Not open, this tile source bypassed, or invalid res level,
+   // return a blank tile.
+   //---
+   if( isOpen() && isSourceEnabled() && isValidRLevel(resLevel) &&
+       result && (result->getNumberOfBands() == getNumberOfOutputBands()) )
+   {
+      result->ref();  // Increment ref count.
+
+      //---
+      // Check for overview tile.  Some overviews can contain r0 so always
+      // call even if resLevel is 0.  Method returns true on success, false
+      // on error.
+      //---
+      status = getOverviewTile(resLevel, result);
+
+      if (!status) // Did not get an overview tile.
+      {
+         status = true;
+
+         ossimIrect tile_rect = result->getImageRectangle();     
+
+         if (getImageRectangle().intersects(tile_rect))
+         {
+            // Make a clip rect.
+            ossimIrect clip_rect = tile_rect.clipToRect(getImageRectangle());
+
+            std::vector<ossimFrameEntryData> frames = getIntersectingEntries(clip_rect);
+
+            if (!tile_rect.completely_within(getImageRectangle()) )
+            {
+               result->makeBlank();
+            }
+
+            for(ossim_uint32 idx = 0; idx < frames.size(); ++idx)
+            {
+               resetCacheBuffer(frames[idx]);
+               m_currentRow = frames[idx].theRow;
+
+               fillTile(ossim_uint8(0), clip_rect, result);
+            }
+         }
+         else // No intersection...
+         {
+            result->makeBlank();
+         }
+      }
+
+      result->unref();  // Decrement ref count.
+   }
+
+   return status;
+}
+
+template <class T>
+void ossimGeoPdfReader::fillTile(T, // dummy template variable
+                                 const ossimIrect& clip_rect,
+                                 ossimImageData* tile)
+{ 
+   if (m_isJpeg == true)
+   {
+      tile->loadTile(m_cacheTile.get());
+   }
+   else
+   {
+      const ossimIrect img_rect = tile->getImageRectangle();
+      ossimIrect src_rect = m_cacheTile->getImageRectangle();
+      if (!img_rect.intersects(src_rect) )
+      {
+         return; // Nothing to do here.
+      }
+
+      // Check the clip rect.
+      if (!clip_rect.completely_within(img_rect))
+      {
+         return;
+      }
+
+      ossimIrect clipRect = clip_rect.clipToRect(src_rect);
+      void* src = (void*)m_cacheTile->getBuf();
+      if (!src)
+      {
+         // Set the error...
+         ossimSetError(getClassName(),
+                       ossimErrorCodes::OSSIM_ERROR,
+                       "%s File %s line %d\nNULL pointer passed to method!");
+         return;
+      }
+
+      // Check the status and allocate memory if needed.
+      if (tile->getDataObjectStatus() == OSSIM_NULL)
+      {
+         tile->initialize();
+      }
+
+      // Get the width of the buffers.
+      ossim_uint32 num_bands = tile->getNumberOfBands();
+      ossim_uint32 s_width = src_rect.width();
+      ossim_uint32 d_width = tile->getWidth();
+      ossim_uint32 s_band_offset = s_width * src_rect.height();
+
+      const T* s = static_cast<const T*>(src);
+
+      ossim_uint32 destinationOffset = (clipRect.ul().y - img_rect.ul().y) * d_width +
+         (clipRect.ul().x - img_rect.ul().x);
+
+      ossim_uint32 destinationIndex = destinationOffset;
+
+      ossim_uint32 clipHeight = clipRect.height();
+      ossim_uint32 clipWidth = clipRect.width();
+
+      ossim_uint32 sourceOffset = (src_rect.ll().y - clipRect.ul().y) * s_width +
+         (clipRect.ul().x - src_rect.ul().x);
+      ossim_uint32 sourceIndex = sourceOffset;
+
+      // Copy the data.
+      for (ossim_uint32 band=0; band<num_bands; band++)
+      {
+         T* destinationBand = static_cast<T*>(tile->getBuf(band));
+         destinationIndex = destinationOffset;
+         sourceIndex = sourceOffset + s_band_offset*band;
+
+         for (ossim_uint32 line = 0; line < clipHeight; ++line)
+         {
+            for (ossim_uint32 sample = 0; sample < clipWidth; ++sample)
+            {
+               destinationBand[destinationIndex + sample]
+                  = s[sourceIndex+sample];
+            }
+            sourceIndex -= s_width;
+            destinationIndex += d_width;
+         }
+      }
+   }
+   tile->validate();
+}
+
+ossim_uint32 ossimGeoPdfReader::getNumberOfInputBands() const
+{
+   return m_numberOfBands;
+}
+
+ossim_uint32 ossimGeoPdfReader::getNumberOfOutputBands()const
+{
+   return m_numberOfBands;
+}
+
+ossim_uint32 ossimGeoPdfReader::getImageTileWidth() const
+{
+   return 0;
+}
+
+ossim_uint32 ossimGeoPdfReader::getImageTileHeight() const
+{
+   return 0;
+}
+
+ossimScalarType ossimGeoPdfReader::getOutputScalarType() const
+{
+   return m_scalarType;
+}
+
+ossimRefPtr<ossimImageGeometry> ossimGeoPdfReader::getImageGeometry()
+{
+   if ( !theGeometry )
+   {
+      // Check for external geom:
+      theGeometry = getExternalImageGeometry();
+      
+      if ( !theGeometry.valid() )
+      {
+         // Internnal geom:
+         theGeometry = getInternalImageGeometry();
+         
+         if ( !theGeometry.valid() )
+         {
+            theGeometry = new ossimImageGeometry();
+         }
+
+         // Check for set projection.
+         if ( !theGeometry->getProjection() )
+         {
+            // Try factories for projection.
+            ossimImageGeometryRegistry::instance()->extendGeometry(this);
+         }
+      }
+
+      // Set image things the geometry object should know about.
+      initImageParameters( theGeometry.get() );
+   }
+   return theGeometry;
+}
+
+ossimRefPtr<ossimImageGeometry> ossimGeoPdfReader::getInternalImageGeometry() const
+{
+   ossimRefPtr<ossimImageGeometry> geom = 0;
+   if (m_pageVector.size() > 0)
+   {
+      geom = m_pageVector[0]->m_geoImage;
+   }
+   return geom;
+}
+
+bool ossimGeoPdfReader::loadState(const ossimKeywordlist& kwl, const char* prefix)
+{
+   bool result = false;
+   ossimString type = kwl.find(prefix, ossimKeywordNames::TYPE_KW);
+   if( (type == "ossimGeoPdfReader") || (type == "ossimImageHandler") )
+   {
+      if ( ossimImageHandler::loadState(kwl, prefix) )
+      {
+         result = open();
+      }
+   }
+   return result;
+}
+
+ossimProjection* ossimGeoPdfReader::getGeoProjection()
+{
+   if (m_isLGIDict)
+   {
+      return getLGIDictGeoProjection();
+   }
+   else
+   {
+      return getVPGeoProjection();
+   }
+   return NULL;
+}
+
+ossimProjection* ossimGeoPdfReader::getVPGeoProjection()
+{
+   ossimKeywordlist kwl; 
+   ossimString pfx = "image";
+   pfx += ossimString::toString(0);
+   pfx += ".";
+
+   ossimProjection* proj = NULL;
+
+   ossimString projCode = getValueFromMap(m_podofoProjInfo, "EPSG");
+   if (!projCode.empty())
+   {
+      kwl.add(pfx.c_str(), ossimKeywordNames::PCS_CODE_KW, projCode, true);
+      projCode = ossimString("EPSG:") + projCode;
+      proj = ossimEpsgProjectionFactory::instance()->createProjection(projCode);
+   }
+   return proj;
+}
+
+ossimProjection* ossimGeoPdfReader::getLGIDictGeoProjection()
+{
+   ossimProjection* proj = NULL;
+   ossimString projContents = getValueFromMap(m_podofoProjInfo, "Projection");
+   if (!projContents.empty())
+   {
+      proj = getProjectionFromStr(projContents);
+   }
+   return proj;
+}
+
+void ossimGeoPdfReader::setPodofoInfo(PoDoFo::PdfObject* object)
+{
+   m_podofoProjInfo.clear();
+   if (object->IsReference())
+   {
+      setPodofoRefInfo(object);
+   }
+   else if (object->IsDictionary())
+   {
+      setPodofoDictInfo(object);
+   }
+   else if (object->IsArray())
+   {
+      setPodofoArrayInfo(object);
+   }
+}
+
+void ossimGeoPdfReader::setPodofoArrayInfo(PoDoFo::PdfObject* object)
+{
+   PoDoFo::PdfArray arrayObj = object->GetArray();
+   for (ossim_uint32 i = 0; i < arrayObj.size(); i++)
+   {
+      PoDoFo::PdfObject objTmp = arrayObj[i];
+      if (objTmp.IsDictionary())
+      {
+         setPodofoDictInfo(&objTmp);
+      }
+      else if (objTmp.IsReference())
+      {
+         setPodofoRefInfo(&objTmp);
+      }
+   }
+}
+
+void ossimGeoPdfReader::setPodofoRefInfo(PoDoFo::PdfObject* object)
+{
+   PoDoFo::PdfReference pdfReference = object->GetReference();
+   PoDoFo::PdfVecObjects objVector = m_pdfMemDocument->GetObjects();
+   if (pdfReference.IsIndirect())
+   {
+      PoDoFo::PdfObject* refObj = objVector.GetObject(pdfReference);
+      if (refObj->IsDictionary())
+      {
+         setPodofoDictInfo(refObj);
+      }
+   }
+}
+
+void ossimGeoPdfReader::setPodofoDictInfo(PoDoFo::PdfObject* object)
+{
+   std::string valueStr;
+   PoDoFo::PdfDictionary pdfDictionary = object->GetDictionary();
+   PoDoFo::TKeyMap keyMap = pdfDictionary.GetKeys();
+   PoDoFo::TKeyMap::iterator it = keyMap.begin();
+   while (it != keyMap.end())
+   {
+      ossimString refName = ossimString(it->first.GetName());
+      PoDoFo::PdfObject* refObj = it->second;
+      if (refObj->IsReference())
+      {
+         setPodofoRefInfo(refObj);
+      }
+      else
+      {
+         refObj->ToString(valueStr);
+         if (valueStr != "")
+         {
+            m_podofoProjInfo[refName] = valueStr;
+         }
+      }
+      it++;
+   }
+}
+
+void ossimGeoPdfReader::setPodofoImageInfo()
+{
+   PoDoFo::PdfObject*  pObj  = NULL;
+   m_podofoImageObjs.clear();
+   std::vector<ossimString> tmpForm;
+   int count = 1;
+   int rowCount = 0;
+   bool isDctDecode = false;
+   PoDoFo::TCIVecObjects it = m_pdfMemDocument->GetObjects().begin();
+   while( it != m_pdfMemDocument->GetObjects().end() )
+   {
+      if ((*it)->IsDictionary())
+      {
+         pObj = (*it)->GetDictionary().GetKey( PoDoFo::PdfName::KeyType );
+         if( pObj && pObj->IsName() && ( pObj->GetName().GetName() == "XObject" ))
+         {
+            pObj = (*it)->GetDictionary().GetKey( PoDoFo::PdfName::KeySubtype );
+            if( pObj && pObj->IsName() && ( pObj->GetName().GetName() == "Form" ))
+            {
+               std::string imageTileInfo;
+               (*it)->ToString(imageTileInfo);
+               ossimString imageTileInfoStr = imageTileInfo;
+               if (imageTileInfoStr.downcase().contains("tile"))
+               {
+                  tmpForm.push_back(imageTileInfoStr);
+               }
+            }
+            else if( pObj && pObj->IsName() && ( pObj->GetName().GetName() == "Image" ))
+            {
+               pObj = (*it)->GetDictionary().GetKey( PoDoFo::PdfName::KeyFilter );
+               if( pObj->IsName() && ( pObj->GetName().GetName() == "DCTDecode" ))
+               {
+                  m_podofoImageObjs[count] = (*it);
+                  isDctDecode = true;
+               }
+               else if( pObj->IsArray() && pObj->GetArray().GetSize() == 1 && 
+                        pObj->GetArray()[0].IsName() && (pObj->GetArray()[0].GetName().GetName() == "DCTDecode"))
+               {
+                  m_podofoImageObjs[count] = (*it);
+                  isDctDecode = true;
+               }
+               else if (pObj->IsName() && (pObj->GetName().GetName() == "FlateDecode") )
+               {
+                  if (isDctDecode == false)
+                  {
+                     std::pair<ossim_int32, ossim_int32> tileRowCol;
+                     tileRowCol = make_pair(rowCount, 0);
+                     m_podofoTileInfo[count] = tileRowCol;
+                     m_podofoImageObjs[count] = (*it);
+                     m_isJpeg = false;
+                  }
+                  rowCount++;
+               }
+            }
+         }
+      }
+      ++it;
+      ++count;
+   }
+
+   if (m_isJpeg == false)
+   {
+      std::map<ossim_int32, ossim_int32> widthMap;
+      std::map<ossim_int32, PoDoFo::PdfObject*>::iterator it = m_podofoImageObjs.begin();
+      while (it != m_podofoImageObjs.end())
+      {
+         PoDoFo::PdfObject* tmpObj = it->second;
+         PoDoFo::PdfImage image(tmpObj);
+         int width = image.GetWidth();
+         widthMap[it->first] = width;
+         it++;
+      }
+
+      std::map<ossim_int32, ossim_int32>::iterator itWidth =  widthMap.begin();
+      ossim_int32 firstId = itWidth->first;
+      ossim_int32 firstWidth = itWidth->second;
+      widthMap.erase(itWidth);
+
+      itWidth = widthMap.end();
+      itWidth--;
+      ossim_int32 lastId = itWidth->first;
+      ossim_int32 lastWidth = itWidth->second;
+    
+      itWidth = widthMap.begin();
+      ossim_int32 invalidId = 0;
+      while (itWidth != widthMap.end())
+      {
+         ossim_int32 tmpWidth = itWidth->second;
+         ossim_int32 tmpId = itWidth->first;
+         if (firstWidth == tmpWidth)
+         {
+            invalidId = lastId;
+         }
+         else if ( lastWidth == tmpWidth )
+         {
+            invalidId = firstId;
+         }
+         else
+         {
+            invalidId = tmpId;
+         }
+         break;
+         itWidth++;
+      }
+
+      it = m_podofoImageObjs.find(invalidId);
+      if (it != m_podofoImageObjs.end())
+      {
+         m_podofoImageObjs.erase(it);
+      }
+   
+      std::map<ossim_int32, std::pair<ossim_int32, ossim_int32> >::iterator itTile = m_podofoTileInfo.find(invalidId);
+      if (itTile != m_podofoTileInfo.end())
+      {
+         m_podofoTileInfo.erase(itTile);
+      }
+
+      if (invalidId == firstId)
+      {
+         itTile = m_podofoTileInfo.begin();
+         while (itTile != m_podofoTileInfo.end())
+         {
+            ossim_int32 index = itTile->first;
+            ossim_int32 tileRow = itTile->second.first;
+            if (tileRow > 0)
+            {
+               std::pair<ossim_int32, ossim_int32> tileRowCol;
+               tileRowCol = make_pair(tileRow-1, 0);
+               m_podofoTileInfo[index] = tileRowCol;
+            }
+            else
+            {
+               break;
+            }
+            itTile++;
+         }
+      }
+      widthMap.clear();
+   }
+  
+   if (tmpForm.size() > 0 && m_podofoTileInfo.size() == 0)
+   {
+      parseTileStructure(tmpForm);
+   }
+   tmpForm.clear();
+}
+
+void ossimGeoPdfReader::buildFrameEntryArray()
+{
+   m_frameWidthVector.clear();
+   m_frameHeightVector.clear();
+   ossim_int32 row = 0;
+   ossim_int32 col = 0;
+   if (m_podofoImageObjs.size() > 0 && m_podofoTileInfo.size() > 0)
+   {
+      //Podofo libary may skip some objects when reading file which cause the count of objects 
+      //different between tile info and image info. need offset to correct it.
+      std::map<ossim_int32, std::pair<ossim_int32, ossim_int32> >::iterator itTileEnd;
+      itTileEnd = m_podofoTileInfo.end();
+      itTileEnd--;
+
+      std::map<ossim_int32, PoDoFo::PdfObject*>::iterator itObjeEnd;
+      itObjeEnd = m_podofoImageObjs.end();
+      itObjeEnd--;
+
+      ossim_int32 indexOffset = itTileEnd->first - itObjeEnd->first;
+
+      std::map<ossim_int32, std::pair<ossim_int32, ossim_int32> >::iterator it = m_podofoTileInfo.begin();
+      //get number of vertical frames and number of horizontal frames
+      while (it != m_podofoTileInfo.end())
+      {
+         ossim_int32 index = it->first;
+         if (indexOffset > 0)
+         {
+            index = index - indexOffset;
+         }
+         std::map<ossim_int32, PoDoFo::PdfObject*>::iterator itObj = m_podofoImageObjs.find(index);
+         if (itObj != m_podofoImageObjs.end())
+         {
+            row = it->second.first;
+            col = it->second.second;
+            if (m_numOfFramesHorizontal <= col)
+            {
+               m_numOfFramesHorizontal = col;
+            }
+            if (m_numOfFramesVertical <= row)
+            {
+               m_numOfFramesVertical = row;
+            }
+         }
+         it++;
+      }
+
+      //set up array size
+      m_numOfFramesHorizontal = m_numOfFramesHorizontal + 1;
+      m_numOfFramesVertical = m_numOfFramesVertical + 1;
+
+      m_frameEntryArray.resize(m_numOfFramesVertical);
+      for(ossim_uint32 index = 0; index < m_frameEntryArray.size(); index++)
+      {
+         m_frameEntryArray[index].resize(m_numOfFramesHorizontal);
+      }
+
+      //build array
+      it = m_podofoTileInfo.begin();
+      std::vector<PoDoFo::PdfObject*> tmpObjVector;
+      while (it != m_podofoTileInfo.end())
+      {
+         ossim_int32 index = it->first;
+         if (indexOffset > 0)
+         {
+            index = index - indexOffset;
+         }
+         std::map<ossim_int32, PoDoFo::PdfObject*>::iterator itObj = m_podofoImageObjs.find(index);
+         if (itObj != m_podofoImageObjs.end())
+         {
+            ossim_int32 rowCount = it->second.first;
+            ossim_int32 colCount = it->second.second;
+            m_frameEntryArray[rowCount][colCount].push_back(itObj->second);
+         }
+         it++;
+      }
+   
+      //calculate lines and samples
+      for (row = 0; row < m_numOfFramesVertical; ++row)
+      {
+         PoDoFo::PdfObject* tmpObj = m_frameEntryArray[row][0][0];
+         PoDoFo::PdfImage image(tmpObj);
+         int height = image.GetHeight();
+         m_frameHeightVector[row] = height;
+      }
+
+      for (col = 0; col < m_numOfFramesHorizontal; ++col)
+      {
+         PoDoFo::PdfObject* tmpObj = m_frameEntryArray[0][col][0];
+         PoDoFo::PdfImage image(tmpObj);
+         int width = image.GetWidth();
+         m_frameWidthVector[col] = width;
+      }
+   
+      std::map<ossim_int32, ossim_int32>::iterator  itWidth = m_frameWidthVector.begin();
+      while (itWidth != m_frameWidthVector.end())
+      {
+         m_numberOfSamples = m_numberOfSamples + itWidth->second;
+         itWidth++;
+      }
+
+      std::map<ossim_int32, ossim_int32>::iterator  itHeight = m_frameHeightVector.begin();
+      while (itHeight != m_frameHeightVector.end())
+      {
+         m_numberOfLines = m_numberOfLines + itHeight->second;
+         itHeight++;
+      }
+      m_imageRect = ossimIrect(0, 0, m_numberOfSamples-1, m_numberOfLines-1);
+  
+      //get the number of bands
+      if (m_frameEntryArray[0][0].size() > 2)
+      {
+         m_numberOfBands = (ossim_uint32) m_frameEntryArray[0][0].size();
+      }
+      else
+      {
+         PoDoFo::PdfObject* tmpObject = m_frameEntryArray[0][0][0];
+         PoDoFo::PdfMemStream* pStream = dynamic_cast<PoDoFo::PdfMemStream*>(tmpObject->GetStream());
+         pStream->Uncompress();
+         ossim_int32 length = pStream->GetLength();
+         m_numberOfBands = length/(m_frameHeightVector[0]*m_frameWidthVector[0]);
+      }
+   }
+}
+
+std::vector<ossimGeoPdfReader::ossimFrameEntryData> ossimGeoPdfReader::getIntersectingEntries(const ossimIrect& rect)
+{
+   std::vector<ossimFrameEntryData> result;
+
+   // make sure we have the Toc entry to render
+   if(!isOpen()) return result;
+
+   ossimIrect imageRect = getImageRectangle();
+   if(rect.intersects(imageRect))
+   {
+      ossimIrect clipRect  = rect.clipToRect(imageRect);
+      ossimIrect frameRect(clipRect.ul().x/m_frameWidthVector[0],
+                           clipRect.ul().y/m_frameHeightVector[0],
+                           clipRect.lr().x/m_frameWidthVector[0],
+                           clipRect.lr().y/m_frameHeightVector[0]);
+
+      for(ossim_int32 row = frameRect.ul().y; row <= frameRect.lr().y; ++row)
+      {
+         for(ossim_int32 col = frameRect.ul().x; col <= frameRect.lr().x; ++col)
+         {
+            ossim_int32 pixelRow = 0;
+            ossim_int32 pixelCol = 0;
+            for (ossim_int32 iRow = 0; iRow < row; ++iRow)
+            {
+               pixelRow = pixelRow + m_frameHeightVector[iRow];
+            }
+            for (ossim_int32 iCol = 0; iCol < col; ++iCol)
+            {
+               pixelCol = pixelCol + m_frameWidthVector[iCol];
+            }
+            std::vector<PoDoFo::PdfObject*> tempEntry = m_frameEntryArray[row][col];
+            if(tempEntry.size() > 0)
+            {
+               result.push_back(ossimFrameEntryData(row, 
+                                                    col, 
+                                                    pixelRow,
+                                                    pixelCol,
+                                                    tempEntry));
+            }
+         }
+      }
+   }
+
+   return result;
+}
+
+ossimProjection* ossimGeoPdfReader::getProjectionFromStr(ossimString projContents)
+{
+   std::vector<ossimString> tmpVector = projContents.split("\n");
+   std::map<ossimString, ossimString, ossimStringLtstr> projectionMap;
+
+   for (ossim_uint32 i = 0; i < tmpVector.size(); i++)
+   {
+      ossimString tmpStr = tmpVector[i];
+      if (tmpStr.contains("/"))
+      {
+         std::vector<ossimString> tmpKeyValue = tmpStr.split(" ");
+         ossimString key;
+         ossimString valueStr;
+         for (ossim_uint32 j = 0; j < tmpKeyValue.size(); j++)
+         {
+            if (tmpKeyValue[j].contains("/"))
+            {
+               key = tmpKeyValue[j].substitute("/", "", true).trim();
+            }
+            else 
+            {
+               valueStr = tmpKeyValue[j].substitute(")", "", true).trim();
+               valueStr = valueStr.substitute("(", "", true).trim();
+            }
+         }
+         if (!key.empty() && !valueStr.empty())
+         {
+            projectionMap[key] = valueStr;
+         }
+      }
+   }
+
+   ossimString projCode = getValueFromMap(projectionMap, "ProjectionType");
+   ossimString datumCode = getValueFromMap(projectionMap, "Datum");
+
+   ossimString originLatitudeStr = getValueFromMap(projectionMap, originLatKey); 
+   ossimString centralMeridianStr = getValueFromMap(projectionMap, centralMeridianKey);
+   ossimString standardParallelOneStr = getValueFromMap(projectionMap, standardParallelOneKey); 
+   ossimString standardParallelTwoStr = getValueFromMap(projectionMap, standardParallelTwoKey); 
+   ossimString falseEastingStr = getValueFromMap(projectionMap, falseEastingKey); 
+   ossimString falseNorthingStr = getValueFromMap(projectionMap, falseNorthingKey);
+   ossimString scaleFactorStr = getValueFromMap(projectionMap, scaleFactorKey);
+
+   if (projCode == "GEODETIC" || projCode == "GEOGRAPHIC")
+   {
+      ossimString codeName = "EPSG:4326";
+      if (datumCode == "WD")
+      {
+         codeName = "EPSG:4322";
+      }
+      ossimProjection* proj = ossimEpsgProjectionFactory::instance()->createProjection(codeName);
+      return proj;
+   }
+   else if (projCode == "UT")
+   {
+      ossimString zoneStr = getValueFromMap(projectionMap, zoneKey);
+      ossimString hemisphereStr = getValueFromMap(projectionMap, hemisphereKey);
+      ossimUtmProjection* utm = new ossimUtmProjection(zoneStr.toInt32());
+      if (!datumCode.empty())
+      {
+         utm->setDatum(ossimDatumFactory::instance()->create(datumCode));
+      }
+
+      if (!zoneStr.empty())
+      {
+         utm->setZone(zoneStr.toInt32());
+      }
+
+      if (!hemisphereStr.empty())
+      {
+         utm->setHemisphere(*hemisphereStr.c_str());
+      }
+
+      return utm;
+   }
+   else if (projCode == "UP")
+   {
+      ossimString hemiStr = getValueFromMap(projectionMap, hemisphereKey);
+      ossimUpsProjection* ups = new ossimUpsProjection();
+
+      if (!datumCode.empty())
+      {
+         ups->setDatum(ossimDatumFactory::instance()->create(datumCode));
+      }
+
+      if (!hemiStr.empty())
+      {
+         ups->setHemisphere(*hemiStr.c_str());
+      }
+
+      return ups;
+   }
+   else if (projCode == "SPCS")
+   {
+      ossimString zoneStr = getValueFromMap(projectionMap, zoneKey);
+
+      ossimString spcsCode;
+      if (datumCode.upcase().contains("NAR"))
+      {
+         spcsCode = ossimString("NAD83_" + projCode + "_" + zoneStr);
+      }
+      else if (datumCode.upcase().contains("NAS"))
+      {
+         spcsCode = ossimString("NAD83_SPAF_" + zoneStr);
+      }
+   
+      // State plane projections are represented in the EPSG database. Search for corresponding proj
+      // by name. Name needs to be exact match as found in the EPSG database files:
+      ossimProjection* stateProj = ossimEpsgProjectionFactory::instance()->createProjection(spcsCode);
+      if (stateProj)
+      {
+         return stateProj;
+      }
+   }
+   else if (projCode == "AC")
+   {
+      ossimGpt origin(originLatitudeStr.toDouble(), centralMeridianStr.toDouble());
+
+      ossimAlbersProjection* albers = new ossimAlbersProjection();
+
+      if (!datumCode.empty())
+      {
+         albers->setDatum(ossimDatumFactory::instance()->create(datumCode));
+      }
+
+      if (!origin.isNan())
+      {
+         albers->setOrigin(origin);
+      }
+
+      if (!standardParallelOneStr.empty())
+      {
+         albers->setStandardParallel1(standardParallelOneStr.toDouble());
+      }
+
+      if (!standardParallelTwoStr.empty())
+      {
+         albers->setStandardParallel2(standardParallelTwoStr.toDouble());
+      }
+
+      if (!falseEastingStr.empty())
+      {
+         albers->setFalseEasting(falseEastingStr.toDouble());
+      }
+
+      if (!falseNorthingStr.empty())
+      {
+         albers->setFalseNorthing(falseNorthingStr.toDouble());
+      }
+
+      return albers;
+   }
+   else if (projCode == "AL")
+   {
+      ossimAzimEquDistProjection* azimEqud = new ossimAzimEquDistProjection();
+
+      ossimGpt origin(originLatitudeStr.toDouble(), centralMeridianStr.toDouble());
+
+      if (!datumCode.empty())
+      {
+         azimEqud->setDatum(ossimDatumFactory::instance()->create(datumCode));
+      }
+
+      if (!origin.isNan())
+      {
+         azimEqud->setOrigin(origin);
+      }
+
+      if (!falseEastingStr.empty())
+      {
+         azimEqud->setFalseEasting(falseEastingStr.toDouble());
+      }
+
+      if (!falseNorthingStr.empty())
+      {
+         azimEqud->setFalseNorthing(falseNorthingStr.toDouble());
+      }
+
+      return azimEqud;
+   }
+   else if (projCode == "BF")
+   {
+      ossimBonneProjection* bonne = new ossimBonneProjection();
+
+      ossimGpt origin(originLatitudeStr.toDouble(), centralMeridianStr.toDouble());
+
+      if (!datumCode.empty())
+      {
+         bonne->setDatum(ossimDatumFactory::instance()->create(datumCode));
+      }
+
+      if (!origin.isNan())
+      {
+         bonne->setOrigin(origin);
+      }
+
+      if (!falseEastingStr.empty())
+      {
+         bonne->setFalseEasting(falseEastingStr.toDouble());
+      }
+
+      if (!falseNorthingStr.empty())
+      {
+         bonne->setFalseNorthing(falseNorthingStr.toDouble());
+      }
+
+      return bonne;
+   }
+   else if (projCode == "CS")
+   {
+      ossimCassiniProjection* cassin = new ossimCassiniProjection();
+
+      ossimGpt origin(originLatitudeStr.toDouble(), centralMeridianStr.toDouble());
+
+      if (!datumCode.empty())
+      {
+         cassin->setDatum(ossimDatumFactory::instance()->create(datumCode));
+      }
+
+      if (!origin.isNan())
+      {
+         cassin->setOrigin(origin);
+      }
+
+      if (!falseEastingStr.empty())
+      {
+         cassin->setFalseEasting(falseEastingStr.toDouble());
+      }
+
+      if (!falseNorthingStr.empty())
+      {
+         cassin->setFalseNorthing(falseNorthingStr.toDouble());
+      }
+
+      return cassin;
+   }
+   else if (projCode == "LI")
+   {
+      ossimCylEquAreaProjection* cyeq = new ossimCylEquAreaProjection();
+
+      ossimGpt origin(originLatitudeStr.toDouble(), centralMeridianStr.toDouble());
+
+      if (!datumCode.empty())
+      {
+         cyeq->setDatum(ossimDatumFactory::instance()->create(datumCode));
+      }
+
+      if (!origin.isNan())
+      {
+         cyeq->setOrigin(origin);
+      }
+
+      if (!falseEastingStr.empty())
+      {
+         cyeq->setFalseEasting(falseEastingStr.toDouble());
+      }
+
+      if (!falseNorthingStr.empty())
+      {
+         cyeq->setFalseNorthing(falseNorthingStr.toDouble());
+      }
+
+      return cyeq;
+   }
+   else if (projCode == "EF")
+   {
+      ossimEckert4Projection* ecker4 = new ossimEckert4Projection();
+
+      ossimGpt origin(originLatitudeStr.toDouble(), centralMeridianStr.toDouble());
+
+      if (!datumCode.empty())
+      {
+         ecker4->setDatum(ossimDatumFactory::instance()->create(datumCode));
+      }
+
+      if (!origin.isNan())
+      {
+         ecker4->setOrigin(origin);
+      }
+
+      if (!falseEastingStr.empty())
+      {
+         ecker4->setFalseEasting(falseEastingStr.toDouble());
+      }
+
+      if (!falseNorthingStr.empty())
+      {
+         ecker4->setFalseNorthing(falseNorthingStr.toDouble());
+      }
+
+      return ecker4;
+   }
+   else if (projCode == "ED")
+   {
+      ossimEckert6Projection* ecker6 = new ossimEckert6Projection();
+
+      if (!datumCode.empty())
+      {
+         ecker6->setDatum(ossimDatumFactory::instance()->create(datumCode));
+      }
+
+      if (!centralMeridianStr.empty())
+      {
+         ecker6->setCentralMeridian(centralMeridianStr.toDouble());
+      }
+
+      if (!falseEastingStr.empty())
+      {
+         ecker6->setFalseEasting(falseEastingStr.toDouble());
+      }
+
+      if (!falseNorthingStr.empty())
+      {
+         ecker6->setFalseNorthing(falseNorthingStr.toDouble());
+      }
+
+      return ecker6;
+   }
+   else if (projCode == "GN")
+   {
+      ossimGnomonicProjection* gnomon = new ossimGnomonicProjection();
+
+      ossimGpt origin(originLatitudeStr.toDouble(), centralMeridianStr.toDouble());
+
+      if (!datumCode.empty())
+      {
+         gnomon->setDatum(ossimDatumFactory::instance()->create(datumCode));
+      }
+
+      if (!origin.isNan())
+      {
+         gnomon->setOrigin(origin);
+      }
+
+      if (!falseEastingStr.empty())
+      {
+         gnomon->setFalseEasting(falseEastingStr.toDouble());
+      }
+
+      if (!falseNorthingStr.empty())
+      {
+         gnomon->setFalseNorthing(falseNorthingStr.toDouble());
+      }
+
+      return gnomon;
+   }
+   else if (projCode == "LE")
+   {
+      ossimGpt origin(originLatitudeStr.toDouble(), centralMeridianStr.toDouble());
+
+      ossimLambertConformalConicProjection* lamber = new ossimLambertConformalConicProjection();
+
+      if (!datumCode.empty())
+      {
+         lamber->setDatum(ossimDatumFactory::instance()->create(datumCode));
+      }
+
+      if (!origin.isNan())
+      {
+         lamber->setOrigin(origin);
+      }
+
+      if (!standardParallelOneStr.empty())
+      {
+         lamber->setStandardParallel1(standardParallelOneStr.toDouble());
+      }
+
+      if (!standardParallelTwoStr.empty())
+      {
+         lamber->setStandardParallel2(standardParallelTwoStr.toDouble());
+      }
+
+      if (!falseEastingStr.empty())
+      {
+         lamber->setFalseEasting(falseEastingStr.toDouble());
+      }
+
+      if (!falseNorthingStr.empty())
+      {
+         lamber->setFalseNorthing(falseNorthingStr.toDouble());
+      }
+
+      return lamber;
+   }
+   else if (projCode == "MC")
+   {
+      ossimMercatorProjection* mercator = new ossimMercatorProjection();
+
+      ossimGpt origin(originLatitudeStr.toDouble(), centralMeridianStr.toDouble());
+
+      if (!datumCode.empty())
+      {
+         mercator->setDatum(ossimDatumFactory::instance()->create(datumCode));
+      }
+
+      if (!origin.isNan())
+      {
+         mercator->setOrigin(origin);
+      }
+
+      if (!scaleFactorStr.empty())
+      {
+         mercator->setScaleFactor(scaleFactorStr.toDouble());
+      }
+
+      if (!falseEastingStr.empty())
+      {
+         mercator->setFalseEasting(falseEastingStr.toDouble());
+      }
+
+      if (!falseNorthingStr.empty())
+      {
+         mercator->setFalseNorthing(falseNorthingStr.toDouble());
+      }
+
+      return mercator;
+   }
+   else if (projCode == "MH")
+   {
+      ossimMillerProjection* miller = new ossimMillerProjection();
+
+      if (!datumCode.empty())
+      {
+         miller->setDatum(ossimDatumFactory::instance()->create(datumCode));
+      }
+
+      if (!centralMeridianStr.empty())
+      {
+         miller->setCentralMeridian(centralMeridianStr.toDouble());
+      }
+
+      if (!falseEastingStr.empty())
+      {
+         miller->setFalseEasting(falseEastingStr.toDouble());
+      }
+
+      if (!falseNorthingStr.empty())
+      {
+         miller->setFalseNorthing(falseNorthingStr.toDouble());
+      }
+
+      return miller;
+   }
+   else if (projCode == "MP")
+   {
+      ossimMollweidProjection* mollweid = new ossimMollweidProjection();
+
+      if (!datumCode.empty())
+      {
+         mollweid->setDatum(ossimDatumFactory::instance()->create(datumCode));
+      }
+
+      if (!centralMeridianStr.empty())
+      {
+         mollweid->setCentralMeridian(centralMeridianStr.toDouble());
+      }
+
+      if (!falseEastingStr.empty())
+      {
+         mollweid->setFalseEasting(falseEastingStr.toDouble());
+      }
+
+      if (!falseNorthingStr.empty())
+      {
+         mollweid->setFalseNorthing(falseNorthingStr.toDouble());
+      }
+
+      return mollweid;
+   }
+   else if (projCode == "NT")
+   {
+      ossimNewZealandMapGridProjection* newzealand = new ossimNewZealandMapGridProjection();
+      if (!datumCode.empty())
+      {
+         newzealand->setDatum(ossimDatumFactory::instance()->create(datumCode));
+      }
+      return newzealand;
+   }
+   else if (projCode == "OC")
+   {
+      ossimString latOne = getValueFromMap(projectionMap, latitudeOneKey);
+      ossimString lonOne = getValueFromMap(projectionMap, longitudeOneKey);
+      ossimString latTwo = getValueFromMap(projectionMap, latitudeTwoKey);
+      ossimString lonTwo = getValueFromMap(projectionMap, longitudeTwoKey);
+
+      ossimObliqueMercatorProjection* oblique = new ossimObliqueMercatorProjection();
+
+      ossimGpt origin1(latOne.toDouble(), lonOne.toDouble());
+      ossimGpt origin2(latTwo.toDouble(), lonTwo.toDouble());
+
+      if (!datumCode.empty())
+      {
+         oblique->setDatum(ossimDatumFactory::instance()->create(datumCode));
+      }
+
+      if (!origin1.isNan())
+      {
+         oblique->setCentralPoint1(origin1);
+      }
+
+      if (!origin2.isNan())
+      {
+         oblique->setCentralPoint2(origin2);
+      }
+
+      if (!scaleFactorStr.empty())
+      {
+         oblique->setScaleFactor(scaleFactorStr.toDouble());
+      }
+
+      if (!falseEastingStr.empty())
+      {
+         oblique->setFalseEasting(falseEastingStr.toDouble());
+      }
+
+      if (!falseNorthingStr.empty())
+      {
+         oblique->setFalseNorthing(falseNorthingStr.toDouble());
+      }
+
+      return oblique;
+   }
+   else if (projCode == "PG")
+   {
+      ossimString originLat = getValueFromMap(projectionMap, "LatitudeTrueScale");
+      ossimString originLon = getValueFromMap(projectionMap, "LongitudeDownFromPole");
+      ossimGpt origin(originLat.toDouble(), originLon.toDouble());
+
+      ossimPolarStereoProjection* polar = new ossimPolarStereoProjection();
+
+      if (!datumCode.empty())
+      {
+         polar->setDatum(ossimDatumFactory::instance()->create(datumCode));
+      }
+
+      if (!origin.isNan())
+      {
+         polar->setOrigin(origin);
+      }
+
+      if (!falseEastingStr.empty())
+      {
+         polar->setFalseEasting(falseEastingStr.toDouble());
+      }
+
+      if (!falseNorthingStr.empty())
+      {
+         polar->setFalseNorthing(falseNorthingStr.toDouble());
+      }
+
+      return polar;
+   }
+   else if (projCode == "PH")
+   {
+      ossimPolyconicProjection* polyconic = new ossimPolyconicProjection();
+
+      ossimGpt origin(originLatitudeStr.toDouble(), centralMeridianStr.toDouble());
+
+      if (!datumCode.empty())
+      {
+         polyconic->setDatum(ossimDatumFactory::instance()->create(datumCode));
+      }
+
+      if (!origin.isNan())
+      {
+         polyconic->setOrigin(origin);
+      }
+
+      if (!falseEastingStr.empty())
+      {
+         polyconic->setFalseEasting(falseEastingStr.toDouble());
+      }
+
+      if (!falseNorthingStr.empty())
+      {
+         polyconic->setFalseNorthing(falseNorthingStr.toDouble());
+      }
+
+      return polyconic;
+   }
+   else if (projCode == "SA")
+   {
+      ossimSinusoidalProjection* sinusoidal = new ossimSinusoidalProjection();
+
+      if (!datumCode.empty())
+      {
+         sinusoidal->setDatum(ossimDatumFactory::instance()->create(datumCode));
+      }
+
+      if (!centralMeridianStr.empty())
+      {
+         sinusoidal->setCentralMeridian(centralMeridianStr.toDouble());
+      }
+
+      if (!falseEastingStr.empty())
+      {
+         sinusoidal->setFalseEasting(falseEastingStr.toDouble());
+      }
+
+      if (!falseNorthingStr.empty())
+      {
+         sinusoidal->setFalseNorthing(falseNorthingStr.toDouble());
+      }
+
+      return sinusoidal;
+   }
+   else if (projCode == "SD")
+   {
+      ossimStereographicProjection* stereo = new ossimStereographicProjection();
+
+      ossimGpt origin(originLatitudeStr.toDouble(), centralMeridianStr.toDouble());
+
+      if (!datumCode.empty())
+      {
+         stereo->setDatum(ossimDatumFactory::instance()->create(datumCode));
+      }
+
+      if (!origin.isNan())
+      {
+         stereo->setOrigin(origin);
+      }
+
+      if (!falseEastingStr.empty())
+      {
+         stereo->setFalseEasting(falseEastingStr.toDouble());
+      }
+
+      if (!falseNorthingStr.empty())
+      {
+         stereo->setFalseNorthing(falseNorthingStr.toDouble());
+      }
+
+      return stereo;
+   }
+   else if (projCode == "TC")
+   {
+      ossimTransMercatorProjection* trans = new ossimTransMercatorProjection();
+
+      ossimGpt origin(originLatitudeStr.toDouble(), centralMeridianStr.toDouble());
+
+      if (!datumCode.empty())
+      {
+         trans->setDatum(ossimDatumFactory::instance()->create(datumCode));
+      }
+
+      if (!origin.isNan())
+      {
+         trans->setOrigin(origin);
+      }
+
+      if (!scaleFactorStr.empty())
+      {
+         trans->setScaleFactor(scaleFactorStr.toDouble());
+      }
+
+      if (!falseEastingStr.empty())
+      {
+         trans->setFalseEasting(falseEastingStr.toDouble());
+      }
+
+      if (!falseNorthingStr.empty())
+      {
+         trans->setFalseNorthing(falseNorthingStr.toDouble());
+      }
+
+      return trans;
+   }
+   else if (projCode == "TX")
+   {
+      ossimTransCylEquAreaProjection* transCyl = new ossimTransCylEquAreaProjection();
+
+      ossimGpt origin(originLatitudeStr.toDouble(), centralMeridianStr.toDouble());
+
+      if (!datumCode.empty())
+      {
+         transCyl->setDatum(ossimDatumFactory::instance()->create(datumCode));
+      }
+
+      if (!origin.isNan())
+      {
+         transCyl->setOrigin(origin);
+      }
+
+      if (!scaleFactorStr.empty())
+      {
+         transCyl->setScaleFactor(scaleFactorStr.toDouble());
+      }
+
+      if (!falseEastingStr.empty())
+      {
+         transCyl->setFalseEasting(falseEastingStr.toDouble());
+      }
+
+      if (!falseNorthingStr.empty())
+      {
+         transCyl->setFalseNorthing(falseNorthingStr.toDouble());
+      }
+
+      return transCyl;
+   }
+   else if (projCode == "VA")
+   {
+      ossimVanDerGrintenProjection* vander = new ossimVanDerGrintenProjection();
+
+      if (!datumCode.empty())
+      {
+         vander->setDatum(ossimDatumFactory::instance()->create(datumCode));
+      }
+
+      if (!centralMeridianStr.empty())
+      {
+         vander->setCentralMeridian(centralMeridianStr.toDouble());
+      }
+
+      if (!falseEastingStr.empty())
+      {
+         vander->setFalseEasting(falseEastingStr.toDouble());
+      }
+
+      if (!falseNorthingStr.empty())
+      {
+         vander->setFalseNorthing(falseNorthingStr.toDouble());
+      }
+
+      return vander;
+   }
+   else 
+   {
+      if (traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG)
+            << "ossimGeoPdfReader: No projection information. \n"
+            << std::endl;
+      }
+   }
+
+   return NULL;
+}
+
diff --git a/ossim_plugins/geopdf/ossimGeoPdfReader.h b/ossim_plugins/geopdf/ossimGeoPdfReader.h
new file mode 100644
index 0000000..6760b3b
--- /dev/null
+++ b/ossim_plugins/geopdf/ossimGeoPdfReader.h
@@ -0,0 +1,329 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author:  Mingjie Su
+//
+// Description:  Class declaration GeoPdf reader.
+//
+// Specification: ISO/IEC 15444
+//
+//----------------------------------------------------------------------------
+// $Id: ossimGeoPdfReader.h 23664 2015-12-14 14:17:27Z dburken $
+
+#ifndef ossimGeoPdfReader_HEADER
+#define ossimGeoPdfReader_HEADER 1
+
+#include <iosfwd>
+#include <fstream>
+#include <vector>
+
+//PoDoFo includes
+#include <podofo/podofo.h>
+
+//ossim includes
+#include "../ossimPluginConstants.h"
+#include <ossim/base/ossimIpt.h>
+#include <ossim/base/ossimIrect.h>
+#include <ossim/imaging/ossimImageHandler.h>
+#include <ossim/support_data/ossimJ2kSizRecord.h>
+#include <ossim/imaging/ossimAppFixedTileCache.h>
+
+// Forward class declarations.
+class ossimImageData;
+class ossimDpt;
+class ossimProjection;
+class PdfMemDocument;
+class PdfObject;
+class ossimGeoPdfVectorPageNode;
+
+class OSSIM_PLUGINS_DLL ossimGeoPdfReader : public ossimImageHandler
+{
+public:
+
+   /** default construtor */
+   ossimGeoPdfReader();
+   
+   /** virtural destructor */
+   virtual ~ossimGeoPdfReader();
+
+   /**
+    * @brief Returns short name.
+    * @return "ossim_mrsid_reader"
+    */
+   virtual ossimString getShortName() const;
+   
+   /**
+    * @brief Returns long  name.
+    * @return "ossim mrsid reader"
+    */
+   virtual ossimString getLongName()  const;
+
+   /**
+    * @brief Returns class name.
+    * @return "ossimGeoPdfReader"
+    */
+   virtual ossimString getClassName() const;
+
+   /**
+    *  @brief Method to grab a tile(rectangle) from image.
+    *
+    *  @param rect The zero based rectangle to grab.
+    *
+    *  @param resLevel The reduced resolution level to grab from.
+    *
+    *  @return The ref pointer with the image data pointer.
+    */
+   virtual ossimRefPtr<ossimImageData> getTile(const  ossimIrect& rect,
+                                               ossim_uint32 resLevel=0);
+
+   /**
+    * Method to get a tile.   
+    *
+    * @param result The tile to stuff.  Note The requested rectangle in full
+    * image space and bands should be set in the result tile prior to
+    * passing.  It will be an error if:
+    * result.getNumberOfBands() != this->getNumberOfOutputBands()
+    *
+    * @return true on success false on error.  If return is false, result
+    *  is undefined so caller should handle appropriately with makeBlank or
+    * whatever.
+    */
+   virtual bool getTile(ossimImageData* result, ossim_uint32 resLevel=0);
+
+   /**
+    *  Returns the number of bands in the image.
+    *  Satisfies pure virtual from ImageHandler class.
+    */
+   virtual ossim_uint32 getNumberOfInputBands() const;
+
+   /**
+    * Returns the number of bands in a tile returned from this TileSource.
+    * Note: we are supporting sources that can have multiple data objects.
+    * If you want to know the scalar type of an object you can pass in the
+    */
+   virtual ossim_uint32 getNumberOfOutputBands()const; 
+   /**
+    * Returns the tile width of the image or 0 if the image is not tiled.
+    * Note: this is not the same as the ossimImageSource::getTileWidth which
+    * returns the output tile width which can be different than the internal
+    * image tile width on disk.
+    */
+   virtual ossim_uint32 getImageTileWidth() const;
+
+   /**
+    * Returns the tile width of the image or 0 if the image is not tiled.
+    * Note: this is not the same as the ossimImageSource::getTileHeight which
+    * returns the output tile height which can be different than the internal
+    * image tile height on disk.
+    */
+   virtual ossim_uint32 getImageTileHeight() const;
+
+   /**
+    * Returns the output pixel type of the tile source.
+    */
+   virtual ossimScalarType getOutputScalarType() const;
+   
+   /**
+    * @brief Gets number of lines for res level.
+    *
+    *  @param resLevel Reduced resolution level to return lines of.
+    *  Default = 0
+    *
+    *  @return The number of lines for specified reduced resolution level.
+    */
+   virtual ossim_uint32 getNumberOfLines(ossim_uint32 resLevel = 0) const;
+
+   /**
+    *  @brief Gets the number of samples for res level.
+    *
+    *  @param resLevel Reduced resolution level to return samples of.
+    *  Default = 0
+    *
+    *  @return The number of samples for specified reduced resolution level.
+    */
+   virtual ossim_uint32 getNumberOfSamples(ossim_uint32 resLevel = 0) const;
+
+   /**
+    * @brief Open method.
+    * @return true on success, false on error.
+    */
+   virtual bool open();
+
+   /**
+    *  @brief Method to test for open file stream.
+    *
+    *  @return true if open, false if not.
+    */
+   virtual bool isOpen()const;
+
+   /**
+    * @brief Method to close current entry.
+    *
+    * @note There is a bool kdu_compressed_source::close() and a
+    * void ossimImageHandler::close(); hence, a new close to avoid conflicting
+    * return types.
+    */
+   virtual void closeEntry();
+
+   /**
+    * Returns the image geometry object associated with this tile source or
+    * NULL if non defined.  The geometry contains full-to-local image
+    * transform as well as projection (image-to-world).
+    */
+   virtual ossimRefPtr<ossimImageGeometry> getImageGeometry();
+
+   /**
+    * @param Method to get geometry.
+    */
+   virtual ossimRefPtr<ossimImageGeometry> getInternalImageGeometry() const;
+
+   /**
+    * Method to the load (recreate) the state of an object from a keyword
+    * list.  Return true if ok or false on error.
+    */
+   virtual bool loadState(const ossimKeywordlist& kwl,
+                          const char* prefix=0);   
+
+   virtual bool setCurrentEntry(ossim_uint32 entryIdx);
+
+    /**
+    * @return The number of entries (images) in the image file.
+    */
+   virtual ossim_uint32 getNumberOfEntries()const;
+   
+   /**
+    * @param entryList This is the list to initialize with entry indexes.
+    *
+    * @note This implementation returns puts one entry "0" in the list.
+    */
+   virtual void getEntryList(std::vector<ossim_uint32>& entryList) const;
+
+   /*!
+    * Method to save the state of an object to a keyword list.
+    * Return true if ok or false on error.
+    */
+   virtual bool saveState(ossimKeywordlist& kwl,
+                          const char* prefix=0)const;
+
+protected:
+
+  struct ossimFrameEntryData
+  {
+    ossimFrameEntryData()
+      :theRow(-1),
+      theCol(-1),
+      thePixelRow(-1),
+      thePixelCol(-1)
+    {}
+    ossimFrameEntryData(ossim_int32 row,
+      ossim_int32 col,
+      ossim_int32 pixelRow,
+      ossim_int32 pixelCol,
+      std::vector<PoDoFo::PdfObject*> entry)
+      :theRow(row),
+      theCol(col),
+      thePixelRow(pixelRow),
+      thePixelCol(pixelCol),
+      theFrameEntry(entry)
+    {}
+    ossimFrameEntryData(const ossimFrameEntryData& rhs)
+      :theRow(rhs.theRow),
+      theCol(rhs.theCol),
+      thePixelRow(rhs.thePixelRow),
+      thePixelCol(rhs.thePixelCol),
+      theFrameEntry(rhs.theFrameEntry)
+    {}
+    ossim_int32 theRow;
+    ossim_int32 theCol;
+    ossim_int32 thePixelRow;
+    ossim_int32 thePixelCol;
+    std::vector<PoDoFo::PdfObject*> theFrameEntry;
+  };
+
+  /**
+    * It is important to note that each frame is organized into an easting northing
+    * type orientation.  This means that a frame at 0,0 is at the lower left corner.
+    * Each frame's pixel data is has 0,0 at the upper left.
+    *
+    * It will take the curent region to render and then find all entries that intersect
+    * that region.
+    *
+    * @param rect the current region to render.
+    * @return The list of entry data objects found for this rect.
+    */
+  std::vector<ossimFrameEntryData> getIntersectingEntries(const ossimIrect& rect);
+   
+private:
+
+  ossimProjection* getGeoProjection();
+
+  ossimProjection* getVPGeoProjection();
+
+  ossimProjection* getLGIDictGeoProjection();
+
+  ossimProjection* getProjectionFromStr(ossimString projContents);
+
+  ossimDrect computeBoundingRect(ossimRefPtr<ossimImageGeometry> geoImage);
+
+  void setPodofoInfo(PoDoFo::PdfObject* object);
+
+  void setPodofoRefInfo(PoDoFo::PdfObject* object);
+
+  void setPodofoArrayInfo(PoDoFo::PdfObject* object);
+
+  void setPodofoDictInfo(PoDoFo::PdfObject* object);
+
+  void parseTileStructure(std::vector<ossimString> tileInfo);
+
+  void setPodofoImageInfo();
+
+  void buildFrameEntryArray();
+
+  void buildTileInfo(ossimString tileInfo);
+
+  void resetCacheBuffer(ossimFrameEntryData entry);
+
+  /**
+    * @note this method assumes that setImageRectangle has been called on
+    * theTile.
+    */
+  template <class T>
+  void fillTile(T, // dummy template variable
+                const ossimIrect& clip_rect, 
+                ossimImageData* tile);
+   
+  ossimIrect                                                   m_imageRect; /** Has sub image offset. */
+  ossim_uint32                                                 m_numberOfBands;
+  ossim_uint32                                                 m_numberOfLines;
+  ossim_uint32                                                 m_numberOfSamples;
+  ossim_int32                                                  m_numOfFramesVertical;
+  ossim_int32                                                  m_numOfFramesHorizontal;
+  ossim_int32                                                  m_currentRow;
+  ossim_int32                                                  m_currentCol;
+  std::map<ossim_int32, ossim_int32>                           m_frameWidthVector;
+  std::map<ossim_int32, ossim_int32>                           m_frameHeightVector;
+  ossimScalarType                                              m_scalarType;
+  ossimRefPtr<ossimImageData>                                  m_tile;
+  
+  std::map<ossimString, ossimString, ossimStringLtstr>         m_podofoProjInfo;
+
+  //std::map<tileIndex, std::map<row, column> >
+  std::map<ossim_int32, std::pair<ossim_int32, ossim_int32> >  m_podofoTileInfo;  
+  std::map<ossim_int32, PoDoFo::PdfObject*>                    m_podofoImageObjs;
+  PoDoFo::PdfMemDocument*                                      m_pdfMemDocument;
+  bool                                                         m_isLGIDict;
+  bool                                                         m_isJpeg;
+  std::vector<ossimGeoPdfVectorPageNode*>                      m_pageVector;
+
+  ossimRefPtr<ossimImageData>                                  m_cacheTile;
+  ossimIpt                                                     m_cacheSize;
+  ossimAppFixedTileCache::ossimAppFixedCacheId                 m_cacheId;
+  std::vector<std::vector< std::vector<PoDoFo::PdfObject*> > > m_frameEntryArray;
+TYPE_DATA
+};
+
+#endif /* #ifndef ossimGeoPdfReader_HEADER */
+
diff --git a/ossim_plugins/geopdf/ossimGeoPdfReaderFactory.cpp b/ossim_plugins/geopdf/ossimGeoPdfReaderFactory.cpp
new file mode 100644
index 0000000..5cbe1b1
--- /dev/null
+++ b/ossim_plugins/geopdf/ossimGeoPdfReaderFactory.cpp
@@ -0,0 +1,172 @@
+//----------------------------------------------------------------------------
+//
+// License:  See top level LICENSE.txt file
+//
+// Author:  Mingjie Su
+//
+// Description: Factory for OSSIM GeoPdf reader using kakadu library.
+//----------------------------------------------------------------------------
+// $Id: ossimGeoPdfReaderFactory.cpp 20935 2012-05-18 14:19:30Z dburken $
+
+#include "ossimGeoPdfReaderFactory.h"
+#include <ossim/base/ossimKeywordlist.h>
+#include <ossim/base/ossimRefPtr.h>
+#include <ossim/base/ossimString.h>
+#include <ossim/base/ossimTrace.h>
+#include <ossim/imaging/ossimImageHandler.h>
+#include "ossimGeoPdfReader.h"
+
+static const ossimTrace traceDebug("ossimGeoPdfReaderFactory:debug");
+
+class ossimImageHandler;
+
+RTTI_DEF1(ossimGeoPdfReaderFactory,
+   "ossimGeoPdfReaderFactory",
+   ossimImageHandlerFactoryBase);
+
+ossimGeoPdfReaderFactory* ossimGeoPdfReaderFactory::theInstance = 0;
+
+ossimGeoPdfReaderFactory::~ossimGeoPdfReaderFactory()
+{
+   theInstance = 0;
+}
+
+ossimGeoPdfReaderFactory* ossimGeoPdfReaderFactory::instance()
+{
+   if(!theInstance)
+   {
+      theInstance = new ossimGeoPdfReaderFactory;
+   }
+   return theInstance;
+}
+
+ossimImageHandler* ossimGeoPdfReaderFactory::open(const ossimFilename& fileName,
+   bool openOverview)const
+{
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimGeoPdfReaderFactory::open(filename) DEBUG: entered..."
+         << "\ntrying ossimKakaduNitfReader"
+         << std::endl;
+   }
+
+   ossimRefPtr<ossimImageHandler> reader = 0;
+
+   if ( hasExcludedExtension(fileName) == false )
+   {
+      reader = new ossimGeoPdfReader;
+      reader->setOpenOverviewFlag(openOverview);
+      if(reader->open(fileName) == false)
+      {
+         reader = 0;
+      }
+   }
+
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimGeoPdfReaderFactory::open(filename) DEBUG: leaving..."
+         << std::endl;
+   }
+
+   return reader.release();
+}
+
+ossimImageHandler* ossimGeoPdfReaderFactory::open(const ossimKeywordlist& kwl,
+   const char* prefix)const
+{
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimGeoPdfReaderFactory::open(kwl, prefix) DEBUG: entered..."
+         << "Trying ossimKakaduNitfReader"
+         << std::endl;
+   }
+
+   ossimRefPtr<ossimImageHandler> reader = new ossimGeoPdfReader;
+   if(reader->loadState(kwl, prefix) == false)
+   {
+      reader = 0;
+   }
+
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimGeoPdfReaderFactory::open(kwl, prefix) DEBUG: leaving..."
+         << std::endl;
+   }
+
+   return reader.release();
+}
+
+ossimObject* ossimGeoPdfReaderFactory::createObject(
+   const ossimString& typeName)const
+{
+   ossimRefPtr<ossimObject> result = 0;
+   if(typeName == "ossimGeoPdfReader")
+   {
+      result = new ossimGeoPdfReader;
+   }
+
+   return result.release();
+}
+
+ossimObject* ossimGeoPdfReaderFactory::createObject(
+   const ossimKeywordlist& kwl,
+   const char* prefix)const
+{
+   return this->open(kwl, prefix);
+}
+
+void ossimGeoPdfReaderFactory::getTypeNameList(
+   std::vector<ossimString>& typeList)const
+{
+   typeList.push_back(ossimString("ossimGeoPdfReader"));
+}
+
+void ossimGeoPdfReaderFactory::getSupportedExtensions(
+   ossimImageHandlerFactoryBase::UniqueStringList& extensionList)const
+{
+   extensionList.push_back(ossimString("pdf"));
+}
+
+bool ossimGeoPdfReaderFactory::hasExcludedExtension(
+   const ossimFilename& file) const
+{
+   bool result = true;
+   ossimString ext = file.ext().downcase();
+   if (ext == "pdf") //only include the file with .pdf extension and exclude any other files
+   {
+      result = false;
+   }
+   return result;
+}
+
+void ossimGeoPdfReaderFactory::getImageHandlersBySuffix(ossimImageHandlerFactoryBase::ImageHandlerList& result,
+   const ossimString& ext)const
+{
+   ossimString testExt = ext.downcase();
+   if(ext == "pdf")
+   {
+      result.push_back(new ossimGeoPdfReader);
+   }
+}
+
+void ossimGeoPdfReaderFactory::getImageHandlersByMimeType(ossimImageHandlerFactoryBase::ImageHandlerList& result,
+   const ossimString& mimeType)const
+{
+   ossimString testExt = mimeType.downcase();
+   if(testExt == "image/pdf")
+   {
+      result.push_back(new ossimGeoPdfReader);
+   }
+}
+
+ossimGeoPdfReaderFactory::ossimGeoPdfReaderFactory(){}
+
+ossimGeoPdfReaderFactory::ossimGeoPdfReaderFactory(const ossimGeoPdfReaderFactory&){}
+
+void ossimGeoPdfReaderFactory::operator=(const ossimGeoPdfReaderFactory&){}
+
+
diff --git a/ossim_plugins/geopdf/ossimGeoPdfReaderFactory.h b/ossim_plugins/geopdf/ossimGeoPdfReaderFactory.h
new file mode 100644
index 0000000..c50e4d5
--- /dev/null
+++ b/ossim_plugins/geopdf/ossimGeoPdfReaderFactory.h
@@ -0,0 +1,116 @@
+//----------------------------------------------------------------------------
+//
+// License:  See top level LICENSE.txt file
+//
+// Author:  Mingjie Su
+//
+// Description: Factory for OSSIM GeoPdf reader using Lizard library.
+//----------------------------------------------------------------------------
+// $Id: ossimGeoPdfReaderFactory.h 20935 2012-05-18 14:19:30Z dburken $
+
+#ifndef ossimGeoPdfReaderFactory_HEADER
+#define ossimGeoPdfReaderFactory_HEADER
+
+#include <ossim/imaging/ossimImageHandlerFactoryBase.h>
+
+class ossimString;
+class ossimFilename;
+class ossimKeywordlist;
+
+/** @brief Factory for GeoPdf image reader. */
+class ossimGeoPdfReaderFactory : public ossimImageHandlerFactoryBase
+{
+public:
+
+   /** @brief virtual destructor */
+   virtual ~ossimGeoPdfReaderFactory();
+
+   /**
+    * @brief static method to return instance (the only one) of this class.
+    * @return pointer to instance of this class.
+    */
+   static ossimGeoPdfReaderFactory* instance();
+
+   /**
+    * @brief open that takes a file name.
+    * @param file The file to open.
+    * @param openOverview If true image handler will attempt to open overview.
+    * default = true 
+    * @return pointer to image handler on success, NULL on failure.
+    */
+   virtual ossimImageHandler* open(const ossimFilename& fileName,
+                                   bool openOverview=true) const;
+
+   /**
+    * @brief open that takes a keyword list and prefix.
+    * @param kwl The keyword list.
+    * @param prefix the keyword list prefix.
+    * @return pointer to image handler on success, NULL on failure.
+    */
+   virtual ossimImageHandler* open(const ossimKeywordlist& kwl,
+                                   const char* prefix=0)const;
+
+   /**
+    * @brief createObject that takes a class name (ossimGeoPdfReader)
+    * @param typeName Should be "ossimKakaduReader".
+    * @return pointer to image writer on success, NULL on failure.
+    */
+   virtual ossimObject* createObject(const ossimString& typeName)const;
+   
+   /**
+    * @brief Creates and object given a keyword list and prefix.
+    * @param kwl The keyword list.
+    * @param prefix the keyword list prefix.
+    * @return pointer to image handler on success, NULL on failure.
+    */
+   virtual ossimObject* createObject(const ossimKeywordlist& kwl,
+                                     const char* prefix=0)const;
+   
+   /**
+    * @brief Adds ossimGeoPdfWriter to the typeList.
+    * @param typeList List to add to.
+    */
+   virtual void getTypeNameList(std::vector<ossimString>& typeList)const;
+
+   /**
+    * @brief Method to add supported extension to the list, like "pdf".
+    *
+    * @param extensionList The list to add to.
+    */
+   virtual void getSupportedExtensions(
+      ossimImageHandlerFactoryBase::UniqueStringList& extensionList)const;
+
+   virtual void getImageHandlersBySuffix(ImageHandlerList& result,
+      const ossimString& ext)const;
+   virtual void getImageHandlersByMimeType(ImageHandlerList& result,
+      const ossimString& mimeType)const;
+  
+protected:
+
+   /**
+    * @brief Method to weed out extensions that this plugin knows it does
+    * not support.  This is to avoid a costly open on say a tiff or jpeg that
+    * is not handled by this plugin.
+    *
+    * @return true if extension, false if not.
+    */
+   bool hasExcludedExtension(const ossimFilename& file) const;
+   
+   /** @brief hidden from use default constructor */
+   ossimGeoPdfReaderFactory();
+
+   /** @brief hidden from use copy constructor */
+   ossimGeoPdfReaderFactory(const ossimGeoPdfReaderFactory&);
+
+   /** @brief hidden from use copy constructor */
+   void operator=(const ossimGeoPdfReaderFactory&);
+
+   /** static instance of this class */
+   static ossimGeoPdfReaderFactory* theInstance;
+
+TYPE_DATA
+};
+
+#endif /* end of #ifndef ossimGeoPdfReaderFactory_HEADER */
+
+
diff --git a/ossim_plugins/hdf/CMakeLists.txt b/ossim_plugins/hdf/CMakeLists.txt
new file mode 100644
index 0000000..d68162b
--- /dev/null
+++ b/ossim_plugins/hdf/CMakeLists.txt
@@ -0,0 +1,53 @@
+set(LIB_NAME ossimhdf_plugin)
+MESSAGE( "************** LIBRARY SETUP FOR ossimhdf_plugin******************")
+
+# Include ossim cmake stuff:
+include(OssimVersion)
+include(OssimCommonVariables)
+include(OssimUtilities)
+
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
+
+SET(requiredLibs)
+
+find_package(HDF4)
+IF(HDF4_FOUND)
+   INCLUDE_DIRECTORIES( ${HDF4_INCLUDE_DIR} )
+   SET(requiredLibs ${requiredLibs} ${HDF4_LIBRARIES} )
+ELSE(HDF4_FOUND)
+   MESSAGE(FATAL_ERROR "Could not find hdf4")
+ENDIF(HDF4_FOUND)
+
+set(HDF5_USE_STATIC_LIBRARIES FALSE)
+find_package(HDF5 COMPONENTS CXX C)
+IF(HDF5_FOUND)
+   INCLUDE_DIRECTORIES( ${HDF5_INCLUDE_DIR} )
+   SET(requiredLibs ${requiredLibs} ${HDF5_CXX_LIBRARIES} ${HDF5_LIBRARIES} )
+ELSE(HDF5_FOUND)
+   MESSAGE(FATAL_ERROR "Could not find hdf5")
+ENDIF(HDF5_FOUND)
+
+FILE(GLOB_RECURSE OSSIMPLUGIN_SRCS *.cpp)
+FILE(GLOB_RECURSE OSSIMPLUGIN_HEADERS *.h)
+
+####
+# OSSIMPLUGINSMAKINGDLL controls dll linkage on windows.  
+# Adding this sets OSSIM_PLUGINS_DLL #define TO "__declspec(dllexport)".
+###
+add_definitions("-DOSSIMPLUGINSMAKINGDLL")
+
+# Adjust the install library path:
+if(OSSIM_INSTALL_PLUGINS_WITH_VERSION)
+   set(INSTALL_LIBRARY_DIR   "${INSTALL_LIBRARY_DIR}/ossim-${OSSIM_VERSION}/plugins")
+else(OSSIM_INSTALL_PLUGINS_WITH_VERSION)
+   set(INSTALL_LIBRARY_DIR   "${INSTALL_LIBRARY_DIR}/ossim/plugins")
+endif(OSSIM_INSTALL_PLUGINS_WITH_VERSION)
+
+OSSIM_LINK_LIBRARY(${LIB_NAME}
+                   COMPONENT_NAME ossim TYPE "${OSSIM_PLUGIN_LINK_TYPE}"
+		   LIBRARIES ${OSSIM_LIBRARY} ${requiredLibs}
+                   HEADERS "${OSSIMPLUGIN_HEADERS}"
+		   SOURCE_FILES "${OSSIMPLUGIN_SRCS}"
+                   INSTALL_LIB)
+
+MESSAGE( STATUS "HDF Plugin required libs          = ${requiredLibs}" )
diff --git a/ossim_plugins/hdf/ossimH5ImageDataset.cpp b/ossim_plugins/hdf/ossimH5ImageDataset.cpp
new file mode 100644
index 0000000..6e5c845
--- /dev/null
+++ b/ossim_plugins/hdf/ossimH5ImageDataset.cpp
@@ -0,0 +1,348 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author:  David Burken
+//
+// Description: OSSIM HDF5 Image DataSet.
+//
+//----------------------------------------------------------------------------
+// $Id
+
+#include "ossimH5ImageDataset.h"
+#include "ossimH5Util.h"
+#include <ossim/base/ossimCommon.h>
+#include <ossim/base/ossimEndian.h>
+#include <ossim/base/ossimIrect.h>
+#include <ossim/base/ossimNotify.h>
+#include <ossim/base/ossimScalarTypeLut.h>
+
+//---
+// This includes everything!  Note the H5 includes are order dependent; hence,
+// the mongo include.
+//---
+#include <hdf5.h>
+#include <H5Cpp.h>
+
+#include <iostream>
+using namespace std;
+
+ossimH5ImageDataset::ossimH5ImageDataset()
+   :
+   m_dataset(0),
+   m_datasetName(),
+   m_scalar(OSSIM_SCALAR_UNKNOWN),
+   m_bands(1),
+   m_lines(0),
+   m_samples(0),
+   m_endian(0)
+{
+}
+
+ossimH5ImageDataset::ossimH5ImageDataset( const ossimH5ImageDataset& obj )
+   :
+   m_dataset( ( (obj.m_dataset)?new H5::DataSet(*(obj.m_dataset)):0 ) ),
+   m_datasetName(obj.m_datasetName),
+   m_scalar(obj.m_scalar),
+   m_bands(obj.m_bands),
+   m_lines(obj.m_lines),
+   m_samples(obj.m_samples),
+   m_endian( obj.m_endian ? new ossimEndian() : 0 )
+{
+   if ( obj.m_dataset )
+   {
+      m_dataset = new H5::DataSet( *(obj.m_dataset) );
+   }
+}
+
+ossimH5ImageDataset::~ossimH5ImageDataset()
+{
+   close();
+}
+
+const ossimH5ImageDataset& ossimH5ImageDataset::operator=( const ossimH5ImageDataset& rhs )
+{
+   if ( this != &rhs )
+   {
+      if ( m_dataset )
+      {
+         delete m_dataset;
+      }
+      if ( rhs.m_dataset )
+      {
+         m_dataset = new H5::DataSet( *(rhs.m_dataset) );
+      }
+      else
+      {
+         m_dataset = 0;
+      }
+      m_datasetName = rhs.m_datasetName;
+      m_scalar      = rhs.m_scalar;
+      m_bands       = rhs.m_bands;
+      m_lines       = rhs.m_lines;
+      m_samples     = rhs.m_samples;
+      m_endian      = ( rhs.m_endian ? new ossimEndian() : 0 );
+   }
+   return *this;
+}
+
+void ossimH5ImageDataset::initialize( const H5::DataSet& dataset,
+                                      const std::string& datasetName )
+{
+   // Clear old stuff.
+   close();
+   
+   m_dataset = new H5::DataSet( dataset );
+   m_datasetName = datasetName;
+
+   // Get the extents:
+   std::vector<ossim_uint32> extents;
+   ossim_hdf5::getExtents( m_dataset, extents );
+   if ( extents.size() >= 2 )
+   {
+      m_samples = extents[1];
+      m_lines   = extents[0];
+      if ( extents.size() >= 3 )
+      {
+         m_bands = extents[2];
+      }
+      else
+      {
+         m_bands = 1;
+      }
+
+      // Scalar type:
+      m_scalar = ossim_hdf5::getScalarType( m_dataset );
+
+      if ( m_scalar != OSSIM_SCALAR_UNKNOWN )
+      {
+         // Byte swapping logic:
+         if ( ( ossim::scalarSizeInBytes( m_scalar ) > 1 ) &&
+              ( ossim::byteOrder() != ossim_hdf5::getByteOrder( m_dataset ) ) )
+         {
+            m_endian = new ossimEndian();
+         }
+      }
+      else
+      {
+         // Unknown scalar!!! Exception here??? (drb)
+         close();
+      }
+      
+   }
+   else // Matches: if ( extents.size() >= 2 ){...}
+   {
+      // One dimensional dataset:
+      close();
+   }
+   
+} // End: ossimH5ImageDataset::initialize
+
+void ossimH5ImageDataset::close()
+{
+   if ( m_dataset )
+   {
+      m_dataset->close();
+      delete m_dataset;
+      m_dataset = 0;
+   }
+   if ( m_endian )
+   {
+      delete m_endian;
+      m_endian = 0;
+   }
+}
+
+const H5::DataSet* ossimH5ImageDataset::getDataset() const
+{
+   return m_dataset;
+}
+
+H5::DataSet* ossimH5ImageDataset::getDataset()
+{
+   return m_dataset;
+}
+
+const std::string& ossimH5ImageDataset::getName() const
+{
+   return m_datasetName;
+}
+
+ossimScalarType ossimH5ImageDataset::getScalarType() const
+{
+   return m_scalar;
+}
+
+ossim_uint32 ossimH5ImageDataset::getNumberOfBands() const
+{
+   return m_bands;
+}
+
+ossim_uint32 ossimH5ImageDataset::getNumberOfLines() const
+{
+   return m_lines;
+}
+
+ossim_uint32 ossimH5ImageDataset::getNumberOfSamples() const
+{
+   return m_samples;
+}
+
+bool ossimH5ImageDataset::getSwapFlag() const
+{
+   return (m_endian ? true: false);
+}
+
+void ossimH5ImageDataset::getTileBuf(void* buffer, const ossimIrect& rect, ossim_uint32 band)
+{
+   static const char MODULE[] = "ossimH5ImageDataset::getTileBuf";
+
+   if ( m_dataset )
+   {
+      try
+      {
+         //--
+         // Turn off the auto-printing when failure occurs so that we can
+         // handle the errors appropriately
+         //---
+         // H5::Exception::dontPrint();
+
+         // NOTE: rank == array dimensions in hdf5 documentation lingo.
+
+         // Get dataspace of the dataset.
+         H5::DataSpace imageDataSpace = m_dataset->getSpace();
+      
+         // Number of dimensions of the input dataspace.:
+         const ossim_int32 IN_DIM_COUNT = imageDataSpace.getSimpleExtentNdims();
+
+         // Native type:
+         H5::DataType dataType = m_dataset->getDataType();
+      
+         std::vector<hsize_t> inputCount(IN_DIM_COUNT);
+         std::vector<hsize_t> inputOffset(IN_DIM_COUNT);
+
+         if ( IN_DIM_COUNT == 2 )
+         {
+            inputOffset[0] = rect.ul().y;
+            inputOffset[1] = rect.ul().x;
+         
+            inputCount[0] = rect.height();
+            inputCount[1] = rect.width();
+         }
+         else
+         {
+            inputOffset[0] = band;
+            inputOffset[1] = rect.ul().y;
+            inputOffset[2] = rect.ul().x;
+         
+            inputCount[0] = 1;
+            inputCount[1] = rect.height();
+            inputCount[2] = rect.width();
+         }
+      
+         // Define hyperslab in the dataset; implicitly giving strike strike and block NULL.
+         imageDataSpace.selectHyperslab( H5S_SELECT_SET,
+                                         &inputCount.front(),
+                                         &inputOffset.front() );
+      
+         // Output dataspace dimensions.
+         const ossim_int32 OUT_DIM_COUNT = 3;
+         std::vector<hsize_t> outputCount(OUT_DIM_COUNT);
+         outputCount[0] = 1;             // single band
+         outputCount[1] = rect.height(); // lines
+         outputCount[2] = rect.width();  // samples
+
+         // Output dataspace offset.
+         std::vector<hsize_t> outputOffset(OUT_DIM_COUNT);
+         outputOffset[0] = 0;
+         outputOffset[1] = 0;
+         outputOffset[2] = 0;
+      
+         // Output dataspace.
+         H5::DataSpace bufferDataSpace( OUT_DIM_COUNT, &outputCount.front());
+         bufferDataSpace.selectHyperslab( H5S_SELECT_SET,
+                                          &outputCount.front(),
+                                          &outputOffset.front() );
+      
+         // Read data from file into the buffer.
+         m_dataset->read( buffer, dataType, bufferDataSpace, imageDataSpace );
+
+         if ( m_endian )
+         {
+            // If the m_endian pointer is initialized(not zero) swap the bytes.
+            m_endian->swap( m_scalar, buffer, rect.area() );
+         }
+      
+         // Cleanup:
+         bufferDataSpace.close();
+         dataType.close();
+         imageDataSpace.close();
+         
+         // memSpace.close();
+         // dataType.close();
+         // dataSpace.close();
+      }
+      catch( const H5::FileIException& error )
+      {
+         ossimNotify(ossimNotifyLevel_WARN)
+            << MODULE << " caught H5::FileIException!" << std::endl;
+         error.printError();
+      }
+   
+      // catch failure caused by the DataSet operations
+      catch( const H5::DataSetIException& error )
+      {
+         ossimNotify(ossimNotifyLevel_WARN)
+            << MODULE << " caught H5::DataSetIException!" << std::endl;
+         error.printError();
+         abort();
+      }
+   
+      // catch failure caused by the DataSpace operations
+      catch( const H5::DataSpaceIException& error )
+      {
+         ossimNotify(ossimNotifyLevel_WARN)
+            << MODULE << " caught H5::DataSpaceIException!" << std::endl;
+         error.printError();
+      }
+   
+      // catch failure caused by the DataSpace operations
+      catch( const H5::DataTypeIException& error )
+      {
+         ossimNotify(ossimNotifyLevel_WARN)
+            << MODULE << " caught H5::DataTypeIException!" << std::endl;
+         error.printError();
+      }
+      catch( ... )
+      {
+         ossimNotify(ossimNotifyLevel_WARN)
+            << MODULE << " caught unknown exception !" << std::endl;
+      }
+      
+   } // Matches: if ( m_dataset )
+   
+} // End: ossimH5ImageDataset::getTileBuf
+
+
+std::ostream& ossimH5ImageDataset::print( std::ostream& out ) const
+{
+   out << "ossimH5ImageDataset: "
+       << "\nH5::DataSet::id: " << (m_dataset?m_dataset->getId():0)
+       << "\nname:            " << m_datasetName
+       << "\nscalar:          " << ossimScalarTypeLut::instance()->getEntryString( m_scalar )
+       << "\nbands:           " << m_bands
+       << "\nlines:           " << m_lines
+       << "\nsamples:         " << m_samples
+       << "\nswap_flage:      " << (m_endian?"true":"false")
+       << std::endl;
+   return out;
+}
+
+std::ostream& operator<<( std::ostream& out, const ossimH5ImageDataset& obj )
+{
+   return obj.print( out );
+}
+
+
diff --git a/ossim_plugins/hdf/ossimH5ImageDataset.h b/ossim_plugins/hdf/ossimH5ImageDataset.h
new file mode 100644
index 0000000..c37c63e
--- /dev/null
+++ b/ossim_plugins/hdf/ossimH5ImageDataset.h
@@ -0,0 +1,126 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author:  David Burken
+//
+// Description: OSSIM HDF5 Image DataSet.
+//
+//----------------------------------------------------------------------------
+// $Id
+
+#ifndef ossimH5ImageDataset_HEADER
+#define ossimH5ImageDataset_HEADER 1
+
+#include <ossim/base/ossimConstants.h>
+#include <iosfwd>
+#include <string>
+
+// Forward class declarations:
+class ossimImageData;
+class ossimEndian;
+class ossimIrect;
+namespace H5
+{
+   class DataSet;
+   class H5File;
+}
+
+/**
+ * @brief Class encapsulates a HDF5 Data set that can be loaded as an image.
+ */
+class ossimH5ImageDataset
+{
+public:
+   /** default constructor */
+   ossimH5ImageDataset();
+   
+   /** copy constructor */
+   ossimH5ImageDataset( const ossimH5ImageDataset& obj );
+   
+   /** destructor */
+   ~ossimH5ImageDataset();
+
+   /** @brief Calls H5::DataSet::close then deletes data set. */
+   void close();
+
+   const ossimH5ImageDataset& operator=( const ossimH5ImageDataset& rhs );
+
+   /**
+    * @brief Opens datasetName and initializes all data members on success.
+    * @return true on success, false on error.
+    */
+   void initialize( const H5::DataSet& dataset,
+                    const std::string& datasetName );
+
+   /**
+    * @brief Get const pointer to dataset.
+    *
+    * This can be null if not open.
+    * 
+    * @return const pointer to dataset.
+    */
+   const H5::DataSet* getDataset() const;
+   
+   /**
+    * @brief Get pointer to dataset.
+    *
+    * This can be null if not open.
+    * 
+    * @return pointer to dataset.
+    */
+   H5::DataSet* getDataset();
+
+   /** @return The dataset name.  This is the full path used for open. */
+   const std::string& getName() const;
+
+   /** @return The output scalar type. */
+   ossimScalarType getScalarType() const;
+
+   /** @return the number of . */
+   ossim_uint32 getNumberOfBands() const;
+
+   /** @return The number of lines. */
+   ossim_uint32 getNumberOfLines() const;
+   
+   /** @return The number of samples. */
+   ossim_uint32 getNumberOfSamples() const;
+
+   /** @return The swap flag. */
+   bool getSwapFlag() const;
+
+   /**
+    *  @brief Method to grab a tile(rectangle) from image.
+    *
+    *  @param buffer Buffer for data for this method to copy data to.
+    *  Should be the size of rect * bytes_per_pixel for scalar type.
+    *
+    *  @param rect The zero based rectangle to grab.
+    *
+    *  @param band
+    */
+   void getTileBuf(void* buffer, const ossimIrect& rect, ossim_uint32 band);   
+
+   /**
+    * @brief print method.
+    * @return std::ostream&
+    */
+   std::ostream& print(std::ostream& out) const;
+
+   friend OSSIMDLLEXPORT std::ostream& operator<<(std::ostream& out,
+                                                  const ossimH5ImageDataset& obj);
+private:
+   H5::DataSet*    m_dataset;
+   std::string     m_datasetName;
+   ossimScalarType m_scalar;
+   ossim_uint32    m_bands;
+   ossim_uint32    m_lines;
+   ossim_uint32    m_samples;
+   ossimEndian*    m_endian; // For byte swapping if needed.
+   
+}; // End: class ossimH5ImageDataset
+
+#endif /* #ifndef ossimH5ImageDataset_HEADER */
+
diff --git a/ossim_plugins/hdf/ossimH5Info.cpp b/ossim_plugins/hdf/ossimH5Info.cpp
new file mode 100644
index 0000000..09103e1
--- /dev/null
+++ b/ossim_plugins/hdf/ossimH5Info.cpp
@@ -0,0 +1,141 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author:  David Burken
+//
+// Description: HDF5 Info class.
+// 
+//----------------------------------------------------------------------------
+// $Id$
+
+#include "ossimH5Info.h"
+#include "ossimH5Util.h"
+
+#include <ossim/base/ossimCommon.h>
+#include <ossim/base/ossimEndian.h>
+#include <ossim/base/ossimNotify.h>
+#include <ossim/base/ossimTrace.h>
+
+//---
+// This includes everything!  Note the H5 includes are order dependent; hence,
+// the mongo include.
+//---
+#include <hdf5.h>
+#include <H5Cpp.h>
+
+#include <fstream>
+#include <iostream>
+#include <iomanip>
+#include <sstream>
+
+static ossimTrace traceDebug("ossimH5Info:debug");
+
+ossimH5Info::ossimH5Info()
+   : ossimInfoBase(),
+     m_file()
+{
+}
+
+ossimH5Info::~ossimH5Info()
+{
+}
+
+bool ossimH5Info::open(const ossimFilename& file)
+{
+   bool result = false;
+
+   // Check for empty filename.
+   if (file.size())
+   {
+      try
+      {
+         //--
+         // Turn off the auto-printing when failure occurs so that we can
+         // handle the errors appropriately
+         //---
+         H5::Exception::dontPrint();
+         
+         if ( H5::H5File::isHdf5( file.string() ) )
+         {
+            m_file = file;
+            result = true;
+         }
+      }
+      catch( const H5::Exception& e )
+      {
+         e.getDetailMsg();
+      }
+      catch( ... )
+      {
+         if ( traceDebug() )
+         {
+            ossimNotify(ossimNotifyLevel_WARN)
+               << "ossimH5Info::open WARNING Caught unhandled exception for file:\n"
+               << file.c_str() << std::endl;
+         }
+      }
+   }
+
+   return result;
+}
+
+std::ostream& ossimH5Info::print(std::ostream& out) const
+{
+   static const char MODULE[] = "ossimH5Info::open";
+   
+   if ( traceDebug() )
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " entered..."
+         << "File:  " << m_file.c_str()
+         << std::endl;
+   }
+
+   // Check for empty filename.
+   if (m_file.size())
+   {
+      try
+      {
+         //--
+         // Turn off the auto-printing when failure occurs so that we can
+         // handle the errors appropriately
+         //---
+         H5::Exception::dontPrint();
+
+         H5::H5File* h5File = new H5::H5File();
+         
+         H5::FileAccPropList access_plist = H5::FileAccPropList::DEFAULT;
+         
+         h5File->openFile( m_file.string(), H5F_ACC_RDONLY, access_plist );
+         
+         // std::vector<std::string> names;
+         // ossim_hdf5::getDatasetNames( h5File, names );
+         ossim_hdf5::print( h5File, out );
+
+         // cleanup...
+         h5File->close();
+         delete h5File;
+         h5File = 0;
+         
+      } // End: try block
+      catch( const H5::Exception& e )
+      {
+         e.getDetailMsg();
+      }
+      catch( ... )
+      {
+         if ( traceDebug() )
+         {
+            ossimNotify(ossimNotifyLevel_WARN)
+               << "ossimH5Info::print WARNIN: Caught unhandled exception!"
+               << std::endl;
+         }
+      }
+   }
+
+   return out;
+}
+
diff --git a/ossim_plugins/hdf/ossimH5Info.h b/ossim_plugins/hdf/ossimH5Info.h
new file mode 100644
index 0000000..4bc1c6c
--- /dev/null
+++ b/ossim_plugins/hdf/ossimH5Info.h
@@ -0,0 +1,63 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author:  David Burken
+//
+// Description: HDF5 Info class.
+// 
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef ossimH5Info_HEADER
+#define ossimH5Info_HEADER 1
+
+#include <ossim/base/ossimConstants.h>
+#include <ossim/support_data/ossimInfoBase.h>
+#include <ossim/base/ossimFilename.h>
+#include "../ossimPluginConstants.h"
+
+class ossimEndian;
+
+/**
+ * @brief TIFF info class.
+ *
+ * Encapsulates the listgeo functionality.
+ */
+class OSSIM_PLUGINS_DLL ossimH5Info : public ossimInfoBase
+{
+public:
+   
+   /** default constructor */
+   ossimH5Info();
+
+   /** virtual destructor */
+   virtual ~ossimH5Info();
+
+   /**
+    * @brief open method.
+    *
+    * @param file File name to open.
+    *
+    * @return true on success false on error.
+    */
+   virtual bool open(const ossimFilename& file);
+   
+   /**
+    * Print method.
+    *
+    * @param out Stream to print to.
+    * 
+    * @return std::ostream&
+    */
+   virtual std::ostream& print(std::ostream& out) const;
+
+private:
+
+   ossimFilename  m_file;
+};
+
+#endif /* End of "#ifndef ossimH5Info_HEADER" */
+
diff --git a/ossim_plugins/hdf/ossimH5Reader.cpp b/ossim_plugins/hdf/ossimH5Reader.cpp
new file mode 100644
index 0000000..21625ce
--- /dev/null
+++ b/ossim_plugins/hdf/ossimH5Reader.cpp
@@ -0,0 +1,1173 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author:  David Burken
+//
+// Description: OSSIM HDF5 Reader.
+//
+//----------------------------------------------------------------------------
+// $Id: ossimH5Reader.cpp 19878 2011-07-28 16:27:26Z dburken $
+
+#include "ossimH5Reader.h"
+#include "ossimH5Util.h"
+#include "ossimHdfGridModel.h"
+
+#include <ossim/base/ossimConstants.h>
+#include <ossim/base/ossimIpt.h>
+#include <ossim/base/ossimDpt.h>
+#include <ossim/base/ossimEndian.h>
+#include <ossim/base/ossimGpt.h>
+#include <ossim/base/ossimIrect.h>
+#include <ossim/base/ossimFilename.h>
+#include <ossim/base/ossimKeywordlist.h>
+#include <ossim/base/ossimNotify.h>
+#include <ossim/base/ossimProperty.h>
+#include <ossim/base/ossimScalarTypeLut.h>
+#include <ossim/base/ossimString.h>
+#include <ossim/base/ossimStringProperty.h>
+#include <ossim/base/ossimTrace.h>
+
+#include <ossim/imaging/ossimImageDataFactory.h>
+#include <ossim/imaging/ossimImageGeometry.h>
+#include <ossim/imaging/ossimImageGeometryRegistry.h>
+#include <ossim/imaging/ossimTiffTileSource.h>
+#include <ossim/imaging/ossimU8ImageData.h>
+
+#include <ossim/projection/ossimBilinearProjection.h>
+#include <ossim/projection/ossimEquDistCylProjection.h>
+#include <ossim/projection/ossimProjection.h>
+
+//---
+// This includes everything!  Note the H5 includes are order dependent; hence,
+// the mongo include.
+//---
+#include <hdf5.h>
+#include <H5Cpp.h>
+
+RTTI_DEF1(ossimH5Reader, "ossimH5Reader", ossimImageHandler)
+
+#ifdef OSSIM_ID_ENABLED
+   static const char OSSIM_ID[] = "$Id$";
+#endif
+   
+static ossimTrace traceDebug("ossimH5Reader:debug");
+
+static const std::string LAYER_KW = "layer";
+
+ossimH5Reader::ossimH5Reader()
+   :
+      ossimImageHandler(),
+      m_h5File(0),
+      m_entries(),
+      m_currentEntry(0),
+      m_tile(0),
+      m_projection(0),
+      m_mutex()
+{
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimH5Reader::ossimH5Reader entered..." << std::endl;
+#ifdef OSSIM_ID_ENABLED
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "OSSIM_ID:  " << OSSIM_ID << endl;
+#endif
+   }
+}
+
+ossimH5Reader::~ossimH5Reader()
+{
+   if (isOpen())
+   {
+      close();
+   }
+}
+
+void ossimH5Reader::allocate()
+{
+   m_tile = ossimImageDataFactory::instance()->create(this, this);
+   m_tile->initialize();
+}
+
+ossimRefPtr<ossimImageData> ossimH5Reader::getTile(
+   const ossimIrect& rect, ossim_uint32 resLevel)
+{
+   if ( m_tile.valid() == false ) // First time through.
+   {
+      allocate();
+   }
+   
+   if (m_tile.valid())
+   {
+      // Image rectangle must be set prior to calling getTile.
+      m_tile->setImageRectangle(rect);
+      
+      if ( getTile( m_tile.get(), resLevel ) == false )
+      {
+         if (m_tile->getDataObjectStatus() != OSSIM_NULL)
+         {
+            m_tile->makeBlank();
+         }
+      }
+   }
+   
+   return m_tile;
+}
+
+bool ossimH5Reader::getTile(ossimImageData* result, ossim_uint32 resLevel)
+{
+   bool status = false;
+   
+   //---
+   // Not open, this tile source bypassed, or invalid res level,
+   // return a blank tile.
+   //---
+   if( isOpen() && isSourceEnabled() && isValidRLevel(resLevel) &&
+       result && (result->getNumberOfBands() == getNumberOfOutputBands()) )
+   {
+      result->ref(); // Increment ref count.
+      
+      //---
+      // Check for overview tile.  Some overviews can contain r0 so always
+      // call even if resLevel is 0.  Method returns true on success, false
+      // on error.
+      //---
+      status = getOverviewTile(resLevel, result);
+
+      if (!status) // Did not get an overview tile.
+      {
+         status = true;
+         
+         ossimIrect tile_rect = result->getImageRectangle();
+
+         if ( ! tile_rect.completely_within(getImageRectangle(0)) )
+         {
+            // We won't fill totally so make blank first.
+            result->makeBlank();
+         }
+         
+         if (getImageRectangle(0).intersects(tile_rect))
+         {
+            // Make a clip rect.
+            ossimIrect clipRect = tile_rect.clipToRect(getImageRectangle(0));
+            
+            if (tile_rect.completely_within( clipRect) == false)
+            {
+               // Not filling whole tile so blank it out first.
+               result->makeBlank();
+            }
+
+            // Create buffer to hold the clip rect for a single band.
+            ossim_uint32 clipRectSizeInBytes = clipRect.area() *
+               ossim::scalarSizeInBytes( m_entries[m_currentEntry].getScalarType() );
+            vector<char> dataBuffer(clipRectSizeInBytes);
+
+            // Get the data.
+            for (ossim_uint32 band = 0; band < getNumberOfInputBands(); ++band)
+            {
+               // Hdf5 file to buffer:
+               m_entries[m_currentEntry].getTileBuf(&dataBuffer.front(), clipRect, band);
+
+               if ( m_entries[m_currentEntry].getScalarType() == OSSIM_FLOAT32 )
+               {
+                  //---
+                  // NPP VIIRS data has null of "-999.3".
+                  // Scan and fix non-standard null value.
+                  //---
+                  const ossim_float32 NP = getNullPixelValue(band);
+                  const ossim_uint32 COUNT = clipRect.area();
+                  ossim_float32* float_buffer = (ossim_float32*)&dataBuffer.front();
+                  for ( ossim_uint32 i = 0; i < COUNT; ++i )
+                  {
+                     if ( float_buffer[i] <= -999.0 ) float_buffer[i] = NP;
+                  }
+               }
+
+               // Buffer to tile:
+               result->loadBand((void*)&dataBuffer.front(), clipRect, band);
+            }
+
+            // Validate the tile, i.e. full, partial, empty.
+            result->validate();
+         }
+         else // No intersection...
+         {
+            result->makeBlank();
+         }
+      }
+
+      result->unref();  // Decrement ref count.
+   }
+
+   return status;
+}
+
+ossimIrect
+ossimH5Reader::getImageRectangle(ossim_uint32 reduced_res_level) const
+{
+   return ossimIrect(0,
+                     0,
+                     getNumberOfSamples(reduced_res_level) - 1,
+                     getNumberOfLines(reduced_res_level)   - 1);
+}
+
+bool ossimH5Reader::saveState(ossimKeywordlist& kwl,
+                               const char* prefix) const
+{
+   return ossimImageHandler::saveState(kwl, prefix);
+}
+
+bool ossimH5Reader::loadState(const ossimKeywordlist& kwl,
+                               const char* prefix)
+{
+   if (ossimImageHandler::loadState(kwl, prefix))
+   {
+      return open();
+   }
+
+   return false;
+}
+
+bool ossimH5Reader::open()
+{
+   static const char MODULE[] = "ossimH5Reader::open";
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " entered..."
+         << "File:  " << theImageFile.c_str()
+         << std::endl;
+   }
+
+   bool status = false;
+   
+   // Start with a clean slate.
+   if (isOpen())
+   {
+      close();
+   }
+
+   // Check for empty filename.
+   if (theImageFile.size())
+   {
+      try
+      {
+         //--
+         // Turn off the auto-printing when failure occurs so that we can
+         // handle the errors appropriately
+         //---
+         // H5::Exception::dontPrint();
+
+         theImageFile = theImageFile.expand();
+
+         if ( H5::H5File::isHdf5( theImageFile.c_str() ) )
+         {
+            m_h5File = new H5::H5File();
+
+            H5::FileAccPropList access_plist = H5::FileAccPropList::DEFAULT;
+            
+            m_h5File->openFile( theImageFile.string(), H5F_ACC_RDONLY, access_plist );
+
+            std::vector<std::string> names;
+            ossim_hdf5::getDatasetNames( m_h5File, names );
+
+            if ( names.size() )
+            {
+               if ( traceDebug() )
+               {
+                  ossimNotify(ossimNotifyLevel_DEBUG)
+                     << MODULE << " DEBUG\nDataset names:\n"; 
+                  for ( ossim_uint32 i = 0; i < names.size(); ++i )
+                  {
+                     ossimNotify(ossimNotifyLevel_DEBUG)
+                        << "dataset[" << i << "]: " << names[i] << "\n";
+                  }
+               }
+
+               // Add the image dataset entries.
+               addImageDatasetEntries( names );
+
+               if ( m_entries.size() )
+               {
+                  // Set the return status.
+                  status = true;
+               }
+               else
+               {
+                  m_h5File->close();
+                  delete m_h5File;
+                  m_h5File = 0;
+               }
+            }
+         }
+         
+      } // End: try block
+      
+      catch( const H5::FileIException& error )
+      {
+         if ( traceDebug() )
+         {
+            error.printError();
+         }
+      }
+      
+      // catch failure caused by the DataSet operations
+      catch( const H5::DataSetIException& error )
+      {
+         if ( traceDebug() )
+         {
+            error.printError();
+         }
+      }
+      
+      // catch failure caused by the DataSpace operations
+      catch( const H5::DataSpaceIException& error )
+      {
+         if ( traceDebug() )
+         {
+            error.printError();
+         }
+      }
+      
+      // catch failure caused by the DataSpace operations
+      catch( const H5::DataTypeIException& error )
+      {
+         if ( traceDebug() )
+         {
+            error.printError();
+         }
+      }
+      catch( ... )
+      {
+         
+      }
+      
+      if ( status )
+      {
+         completeOpen();
+      }
+   }
+
+   return status;
+}
+
+void ossimH5Reader::addImageDatasetEntries(const std::vector<std::string>& names)
+{
+   if ( m_h5File && names.size() )
+   {
+      std::vector<std::string>::const_iterator i = names.begin();
+      while ( i != names.end() )
+      {
+         if ( ossim_hdf5::isExcludedDataset( *i ) == false )
+         {
+            H5::DataSet dataset = m_h5File->openDataSet( *i );
+
+            // Get the class of the datatype that is used by the dataset.
+            H5T_class_t type_class = dataset.getTypeClass();
+            
+            if ( ( type_class == H5T_INTEGER ) || ( type_class == H5T_FLOAT ) )
+            {
+               // Get the extents:
+               std::vector<ossim_uint32> extents;
+               ossim_hdf5::getExtents( &dataset, extents ); 
+
+               if ( extents.size() >= 2 )
+               {
+                  if ( ( extents[0] > 1 ) && ( extents[1] > 1 ) )
+                  {
+                     ossimH5ImageDataset hids;
+                     hids.initialize( dataset, *i );
+                     m_entries.push_back( hids );
+                  }     
+               }
+            }
+
+            dataset.close();
+         }
+            
+         ++i;
+      }
+   }
+   
+#if 0 /* Please leave for debug. (drb) */
+   std::vector<ossimH5ImageDataset>::const_iterator i = m_entries.begin();
+   while ( i != m_entries.end() )
+   {
+      std::cout << (*i) << endl;
+      ++i;
+   }
+#endif
+      
+} // End: ossimH5Reader::addImageDatasetEntries
+
+ossim_uint32 ossimH5Reader::getNumberOfLines(ossim_uint32 reduced_res_level) const
+{
+   ossim_uint32 result = 0;
+   
+   if ( (reduced_res_level == 0) && ( m_currentEntry < m_entries.size() ) )
+   {
+      result = m_entries[m_currentEntry].getNumberOfLines();
+   }
+   else if ( theOverview.valid() )
+   {
+      result = theOverview->getNumberOfLines(reduced_res_level);
+   }
+   
+   return result;
+}
+
+ossim_uint32 ossimH5Reader::getNumberOfSamples(ossim_uint32 reduced_res_level) const
+{
+   ossim_uint32 result = 0;
+   
+   if ( (reduced_res_level == 0) && ( m_currentEntry < m_entries.size() ) )
+   {
+      result = m_entries[m_currentEntry].getNumberOfSamples();
+   }
+   else if ( theOverview.valid() )
+   {
+      result = theOverview->getNumberOfSamples(reduced_res_level);
+   }
+   
+   return result; 
+}
+
+ossim_uint32 ossimH5Reader::getImageTileWidth() const
+{
+   return 0; // Not tiled format.
+}
+
+ossim_uint32 ossimH5Reader::getImageTileHeight() const
+{
+   return 0; // Not tiled format.
+}
+
+ossimString ossimH5Reader::getShortName()const
+{
+   return ossimString("ossim_hdf5_reader");
+}
+   
+ossimString ossimH5Reader::getLongName()const
+{
+   return ossimString("ossim hdf5 reader");
+}
+
+ossimString  ossimH5Reader::getClassName()const
+{
+   return ossimString("ossimH5Reader");
+}
+
+ossim_uint32 ossimH5Reader::getNumberOfInputBands() const
+{
+   ossim_uint32 result = 1;
+
+   if ( m_currentEntry < m_entries.size() )
+   {
+      result = m_entries[m_currentEntry].getNumberOfBands();
+   }
+
+   return result;
+}
+
+ossim_uint32 ossimH5Reader::getNumberOfOutputBands()const
+{
+   // Currently not band selectable.
+   return getNumberOfInputBands();
+}
+
+ossimScalarType ossimH5Reader::getOutputScalarType() const
+{
+   ossimScalarType result = OSSIM_SCALAR_UNKNOWN;
+   
+   if ( m_currentEntry < m_entries.size() )
+   {
+      result = m_entries[m_currentEntry].getScalarType();
+   }
+   
+   return result;
+}
+
+bool ossimH5Reader::isOpen()const
+{
+   return ( m_entries.size() && ( m_currentEntry < m_entries.size() ) ) ? true : false ;
+}
+
+void ossimH5Reader::close()
+{
+   // Close the datasets.
+   m_entries.clear();
+
+   // Then the file.
+   if ( m_h5File )
+   {
+      m_h5File->close();
+      delete m_h5File;
+      m_h5File = 0;
+   }
+
+   // ossimRefPtr so assign to 0(unreferencing) will handle memory.
+   m_tile = 0;
+   m_projection = 0;
+
+   ossimImageHandler::close();
+}
+
+ossim_uint32 ossimH5Reader::getNumberOfEntries() const
+{
+   return (ossim_uint32)m_entries.size();
+}
+
+void ossimH5Reader::getEntryName( ossim_uint32 entryIdx, std::string& name ) const
+{
+   if ( entryIdx < m_entries.size() )
+   {
+      name = m_entries[ entryIdx ].getName();
+   }
+   else
+   {
+      name.clear();
+   }
+}
+
+void ossimH5Reader::getEntryList(std::vector<ossim_uint32>& entryList) const
+{
+   const ossim_uint32 SIZE = m_entries.size();
+   entryList.resize( SIZE );
+   for ( ossim_uint32 i = 0; i < SIZE; ++i )
+   {
+      entryList[i] = i; 
+   }
+}
+
+bool ossimH5Reader::setCurrentEntry( ossim_uint32 entryIdx )
+{
+   bool result = true;
+   if (m_currentEntry != entryIdx)
+   {
+      if ( isOpen() )
+      {
+         // Entries always start at zero and increment sequentially..
+         if ( entryIdx < m_entries.size() )
+         {
+            //---
+            // Note: Currently sharing ONE geometry so there is no need to clear the geometry
+            // file.  This may have to be changed if data has entries that are not relative
+            // to same geometry file.
+            //---
+            // Clear the geometry.
+            // theGeometry = 0;
+            
+            // Must clear or openOverview will use last entries.
+            theOverviewFile.clear();
+            
+            m_currentEntry = entryIdx;
+            
+            //---
+            // Since we were previously open and the the entry has changed we
+            // need to reinitialize some things. Setting tile to 0 will force an
+            // allocate call on first getTile.
+            //---
+            
+            // ossimRefPtr so assign to 0(unreferencing) will handle memory.
+            m_tile = 0;
+            
+            completeOpen();
+         }
+         else
+         {
+            result = false; // Entry index out of range.
+         }
+      }
+      else
+      {
+         //---
+         // Not open.
+         // Allow this knowing that open will check for out of range.
+         //---
+         m_currentEntry = entryIdx;
+      }
+   }
+
+   return result;
+}
+
+ossim_uint32 ossimH5Reader::getCurrentEntry() const
+{
+   return m_currentEntry;
+}
+
+ossimRefPtr<ossimImageGeometry> ossimH5Reader::getImageGeometry()
+{
+   if ( !theGeometry )
+   {
+      //---
+      // Check for external geom:
+      //---
+      theGeometry = getExternalImageGeometry();
+      
+      if ( !theGeometry )
+      {
+         //---
+         // WARNING:
+         // Must create/set the geometry at this point or the next call to
+         // ossimImageGeometryRegistry::extendGeometry will put us in an infinite loop
+         // as it does a recursive call back to ossimImageHandler::getImageGeometry().
+         //---
+
+         // Check the internal geometry first to avoid a factory call.
+         m_mutex.lock();
+         theGeometry = getInternalImageGeometry();
+         m_mutex.unlock();
+
+         // At this point it is assured theGeometry is set.
+
+         // Check for set projection.
+         if ( !theGeometry->getProjection() )
+         {
+            // Try factories for projection.
+            ossimImageGeometryRegistry::instance()->extendGeometry(this);
+         }
+      }
+
+      // Set image things the geometry object should know about.
+      initImageParameters( theGeometry.get() );
+   }
+
+   return theGeometry;
+}
+
+ossimRefPtr<ossimImageGeometry> ossimH5Reader::getInternalImageGeometry()
+{
+   ossimRefPtr<ossimImageGeometry> geom = new ossimImageGeometry();
+
+   if ( m_projection.valid() )
+   {
+      // Stored projection, currently shared by all entries.
+      geom->setProjection( m_projection.get() );
+   }
+   else
+   {
+      if ( m_h5File )
+      {
+         // Find the "Latitude" and "Longitude" datasets if present.
+         std::string latName;
+         std::string lonName;
+         if ( getLatLonDatasetNames(  m_h5File, latName, lonName ) )
+         {
+            H5::DataSet latDataSet = m_h5File->openDataSet( latName );
+            H5::DataSet lonDataSet = m_h5File->openDataSet( lonName );
+
+            ossimIrect imageRect = getImageRectangle(0);
+            
+            ossimIrect validRect;
+            if ( ossim_hdf5::getBoundingRect( latDataSet, validRect ) )
+            {
+               ossimRefPtr<ossimProjection> proj = 0;
+               
+               if ( imageRect == validRect )
+               {
+                  // Try for a coarse projection first:
+                  proj = processCoarseGridProjection( latDataSet, lonDataSet );
+               }
+                  
+               if ( proj.valid() == false )
+               {
+                  ossimIrect rect;
+                  proj = processBilinearProjection( latDataSet, lonDataSet, validRect );
+               }
+               
+               if ( proj.valid() )
+               {
+                  // Store it for next time:
+                  m_projection = proj;
+                  
+                  // Set the geometry projection
+                  geom->setProjection( proj.get() ); 
+               }
+            }
+               
+            latDataSet.close();
+            lonDataSet.close();
+         }
+      }
+   }
+ 
+   return geom;
+}
+
+ossimRefPtr<ossimProjection> ossimH5Reader::processBilinearProjection(
+   H5::DataSet& latDataSet, H5::DataSet& lonDataSet, const ossimIrect& validRect ) const
+{
+   ossimRefPtr<ossimProjection> proj = 0;
+
+   // Get dataspace of the dataset.
+   H5::DataSpace latDataSpace = latDataSet.getSpace();
+   H5::DataSpace lonDataSpace = lonDataSet.getSpace();
+         
+   // Number of dimensions of the input dataspace:
+   const ossim_int32 DIM_COUNT = latDataSpace.getSimpleExtentNdims();
+         
+   if ( DIM_COUNT == 2 )
+   {
+      // Get the extents. Assuming dimensions are same for lat lon dataset. 
+      std::vector<hsize_t> dimsOut(DIM_COUNT);
+      latDataSpace.getSimpleExtentDims( &dimsOut.front(), 0 );
+
+      if ( dimsOut[0] && dimsOut[1] )
+      {
+         std::vector<hsize_t> inputCount(DIM_COUNT);
+         std::vector<hsize_t> inputOffset(DIM_COUNT);
+               
+         inputOffset[0] = 0;
+         inputOffset[1] = 0;
+               
+         inputCount[0] = 1;
+         inputCount[1] = 1;
+               
+         // Output dataspace dimensions.
+         const ossim_int32 OUT_DIM_COUNT = 3;
+         std::vector<hsize_t> outputCount(OUT_DIM_COUNT);
+         outputCount[0] = 1; // single band
+         outputCount[1] = 1; // single line
+         outputCount[2] = 1; // single sample
+               
+         // Output dataspace offset.
+         std::vector<hsize_t> outputOffset(OUT_DIM_COUNT);
+         outputOffset[0] = 0;
+         outputOffset[1] = 0;
+         outputOffset[2] = 0;
+               
+         ossimScalarType scalar = ossim_hdf5::getScalarType( &latDataSet );
+         if ( scalar == OSSIM_FLOAT32 )
+         {
+            // See if we need to swap bytes:
+            ossimEndian* endian = 0;
+            if ( ( ossim::byteOrder() != ossim_hdf5::getByteOrder( &latDataSet ) ) )
+            {
+               endian = new ossimEndian();
+            }
+
+            // Native type:
+            H5::DataType latDataType = latDataSet.getDataType();
+            H5::DataType lonDataType = lonDataSet.getDataType();
+                  
+            std::vector<ossimDpt> ipts;
+            std::vector<ossimGpt> gpts;
+            ossimGpt gpt(0.0, 0.0, 0.0); // Assuming WGS84...
+            ossim_float32 latValue = 0.0;
+            ossim_float32 lonValue = 0.0;
+                  
+            // Only grab every 128th value.:
+            const ossim_int32 GRID_SIZE = 128;
+                  
+            // Output dataspace always the same one pixel.
+            H5::DataSpace bufferDataSpace( OUT_DIM_COUNT, &outputCount.front());
+            bufferDataSpace.selectHyperslab( H5S_SELECT_SET,
+                                             &outputCount.front(),
+                                             &outputOffset.front() );
+
+            //---
+            // Dataset sample has NULL lines at the end so scan for valid rect.
+            // Use "<= -999" for test as per NOAA as it seems the NULL value is
+            // fuzzy.  e.g. -999.3.
+            //---
+            const ossim_float32 NULL_VALUE = -999.0;
+
+            //---
+            // Get the tie points within the valid rect:
+            //---
+            ossimDpt ipt = validRect.ul();
+            while ( ipt.y <= validRect.lr().y )
+            {
+               inputOffset[0] = static_cast<hsize_t>(ipt.y);
+               
+               // Sample loop:
+               ipt.x = validRect.ul().x;
+               while ( ipt.x <= validRect.lr().x )
+               {
+                  inputOffset[1] = static_cast<hsize_t>(ipt.x);
+                  
+                  latDataSpace.selectHyperslab( H5S_SELECT_SET,
+                                                &inputCount.front(),
+                                                &inputOffset.front() );
+                  lonDataSpace.selectHyperslab( H5S_SELECT_SET,
+                                                &inputCount.front(),
+                                                &inputOffset.front() );
+                  
+                  // Read data from file into the buffer.
+                  latDataSet.read( &latValue, latDataType, bufferDataSpace, latDataSpace );
+                  lonDataSet.read( &lonValue, lonDataType, bufferDataSpace, lonDataSpace );
+                  
+                  if ( endian )
+                  {
+                     // If the endian pointer is initialized(not zero) swap the bytes.
+                     endian->swap( latValue );
+                     endian->swap( lonValue );  
+                  }
+                  
+                  if ( ( latValue > NULL_VALUE ) && ( lonValue > NULL_VALUE ) )
+                  {
+                     gpt.lat = latValue;
+                     gpt.lon = lonValue;
+                     
+                     ipts.push_back( ipt );
+                     gpts.push_back( gpt );
+                  }
+                  
+                  if ( ipt.x < validRect.lr().x )
+                  {
+                     ipt.x += GRID_SIZE;
+                     if ( ipt.x > validRect.lr().x )
+                     {
+                        ipt.x = validRect.lr().x; // Clamp to last sample.
+                     }
+                  }
+                  else
+                  {  
+                     break; // At the end:
+                  }
+                  
+               } // End sample loop.
+
+               if ( ipt.y < validRect.lr().y )
+               {
+                  ipt.y += GRID_SIZE;
+                  if ( ipt.y > validRect.lr().y )
+                  {
+                     ipt.y = validRect.lr().y; // Clamp to last line.
+                  }
+               }
+               else
+               {  
+                  break; // At the end:
+               }
+               
+            } // End line loop.
+                  
+            if ( ipts.size() )
+            {
+               // Create the projection:
+               ossimRefPtr<ossimBilinearProjection> bp = new ossimBilinearProjection();
+                     
+               // Add the tie points:
+               bp->setTiePoints( ipts, gpts );
+                     
+               // Assign to output projection:
+               proj = bp.get();
+            }
+         }
+         else // Matches: if ( scalar == OSSIM_FLOAT32 ){...}
+         {
+            ossimNotify(ossimNotifyLevel_WARN)
+               << "ossimH5Reader::processBilinearProjection WARNING!"
+               << "\nUnhandled scalar type: "
+               << ossimScalarTypeLut::instance()->getEntryString( scalar )
+               << std::endl;
+         }
+               
+      } // Matches: if ( dimsOut...
+            
+   } // Matches: if ( IN_DIM_COUNT == 2 )
+         
+   latDataSpace.close();
+   lonDataSpace.close();
+   
+   return proj;
+   
+} // End: ossimH5Reader::processBilinearProjection()
+
+ossimRefPtr<ossimProjection> ossimH5Reader::processCoarseGridProjection(
+   H5::DataSet& latDataSet, H5::DataSet& lonDataSet ) const
+{
+   ossimRefPtr<ossimProjection> proj = 0;
+
+   ossimRefPtr<ossimHdfGridModel> model = new ossimHdfGridModel();
+   
+   try
+   {
+      if ( model->setGridNodes( &latDataSet,
+                                &lonDataSet,
+                                getNumberOfLines(0), 
+                                getNumberOfSamples(0) ) )
+      {
+         proj = model.get();
+         // proj->print(cout);
+      }
+   }
+   catch ( const ossimException& e )
+   {
+      if ( traceDebug() )
+      {
+         ossimNotify(ossimNotifyLevel_WARN)
+            << "ossimH5Reader::processCoarseGridProjection caught exception\n"
+            << e.what() << std::endl;
+      }
+   }
+
+   return proj;
+}
+
+bool ossimH5Reader::getLatLonDatasetNames( H5::H5File* h5File,
+                                           std::string& latName,
+                                           std::string& lonName ) const
+{
+   bool result = false;
+
+   if ( h5File )
+   {
+      latName.clear();
+      lonName.clear();
+      
+      // Get the list of datasets.
+      std::vector<std::string> datasetNames;
+      ossim_hdf5::getDatasetNames( h5File, datasetNames );
+      
+      if ( datasetNames.size() )
+      {
+         std::vector<std::string>::const_iterator i = datasetNames.begin();
+         while ( i != datasetNames.end() )
+         {
+            ossimString os = *i;
+            if ( os.contains( "Latitude" ) )
+            {
+               latName = *i;
+            }
+            else if ( os.contains( "Longitude" ) )
+            {
+               lonName = *i;
+            }
+            
+            if ( latName.size() && lonName.size() )
+            {
+               result = true;
+               break;
+            }
+            
+            ++i;
+         }
+      }
+   }
+   
+   return result;
+
+} // End: ossimH5Reader::getLatLonDatasetNames
+
+bool ossimH5Reader::getLatLonDatasets( H5::H5File* h5File,
+                                       H5::DataSet& latDataSet,
+                                       H5::DataSet& lonDataSet ) const
+{
+   bool status = false;
+
+   if ( h5File )
+   {
+      std::string latName;
+      std::string lonName;
+      if ( getLatLonDatasetNames( h5File, latName, lonName ) )
+      {
+         // Set the return status:
+         status = true;
+         latDataSet = h5File->openDataSet( latName );
+         lonDataSet = h5File->openDataSet( lonName ); 
+      }
+      else
+      {
+         // Look for the key: /N_GEO_Ref
+         std::string group = "/";
+         std::string key   = "N_GEO_Ref";
+         std::string value;
+            
+         if ( ossim_hdf5::getGroupAttributeValue( h5File, group, key, value ) )
+         {
+            ossimFilename f = value;
+ 	    ossimFilename latLonFile = theImageFile.path();
+            latLonFile = latLonFile.dirCat( f );
+
+            if ( latLonFile.exists() )
+            {
+               if ( H5::H5File::isHdf5( latLonFile.string() ) )
+               {
+                  H5::H5File* h5File = new H5::H5File();
+                  
+                  H5::FileAccPropList access_plist = H5::FileAccPropList::DEFAULT;
+                  h5File->openFile( latLonFile.string(), H5F_ACC_RDONLY, access_plist );
+
+                  if ( getLatLonDatasetNames( h5File, latName, lonName ) )
+                  {
+                     // Set the return status:
+                     status = true;
+                     latDataSet = h5File->openDataSet( latName );
+                     lonDataSet = h5File->openDataSet( lonName ); 
+                  }
+                  h5File->close();
+                  delete h5File;
+                  h5File = 0;
+               }
+            }
+         }
+      }
+   }
+
+   return status;
+   
+} // End: ossimH5Reader::getLatLonDatasets( ... )
+
+bool ossimH5Reader::isNppMission( H5::H5File* h5File ) const
+{
+   bool result = false;
+   
+   // Look for "Mission_Name"
+   const std::string GROUP = "/";
+   const std::string KEY = "Mission_Name";
+   std::string value;
+   
+   if ( ossim_hdf5::getGroupAttributeValue( h5File, GROUP, KEY, value ) )
+   {
+      if ( value == "NPP" )
+      {
+         result = true;
+      }
+   }
+   
+   return result;
+}
+
+double ossimH5Reader::getNullPixelValue( ossim_uint32 band ) const
+{
+   return ossimImageHandler::getNullPixelValue( band );
+#if 0
+   double result;
+   ossimScalarType scalar = getOutputScalarType();
+   if ( scalar == OSSIM_FLOAT32 )
+   {
+      result = -9999.0;
+   }
+   else
+   {
+      result = ossimImageHandler::getNullPixelValue( band );
+   }
+   return result;
+#endif
+}
+
+void ossimH5Reader::setProperty(ossimRefPtr<ossimProperty> property)
+{
+   if ( property.valid() )
+   {
+      if ( property->getName().string() == LAYER_KW )
+      {
+         ossimString s;
+         property->valueToString(s);
+         ossim_uint32 SIZE = (ossim_uint32)m_entries.size();
+         for ( ossim_uint32 i = 0; i < SIZE; ++i )
+         {
+            if ( m_entries[i].getName() == s.string() )
+            {
+               setCurrentEntry( i );
+            }
+         }
+      }
+      else
+      {
+         ossimImageHandler::setProperty(property);
+      }
+   }
+}
+
+ossimRefPtr<ossimProperty> ossimH5Reader::getProperty(const ossimString& name)const
+{
+   ossimRefPtr<ossimProperty> prop = 0;
+   if ( name.string() == LAYER_KW )
+   {
+      if ( m_currentEntry < m_entries.size() )
+      {
+         ossimString value = m_entries[m_currentEntry].getName();
+         prop = new ossimStringProperty(name, value);
+      }
+   }
+   else
+   {
+      prop = ossimImageHandler::getProperty(name);
+   }
+   return prop;
+}
+
+void ossimH5Reader::getPropertyNames(std::vector<ossimString>& propertyNames)const
+{
+   propertyNames.push_back( ossimString("layer") );
+   ossimImageHandler::getPropertyNames(propertyNames);
+}
+
+
+void ossimH5Reader::addMetadata( ossimKeywordlist* kwl, const std::string& prefix ) const
+{
+   // Note: hdf5 library throws exception if groupd is not found:
+   
+   if ( kwl && m_h5File )
+   {
+      // Look for country code(s): hdf5.CountryCodes: CA,MX,US
+      std::string group = "/";
+      std::string key = "CountryCodes";
+      std::string value;
+
+      if ( ossim_hdf5::getGroupAttributeValue( m_h5File, group, key, value ) )
+      {
+         key = "country_code";
+         kwl->addPair( prefix, key, value );
+      }
+
+      // Look for mission id: hdf5.Mission_Name: NPP
+      key = "Mission_Name";
+      if ( ossim_hdf5::getGroupAttributeValue( m_h5File, group, key, value ) )
+      {
+         key = "mission_id";
+         kwl->addPair( prefix, key, value );
+      }
+         
+
+      //---
+      // Look for sensor type:
+      // hdf5.Data_Products.VIIRS-DNB-SDR.Instrument_Short_Name: VIIRS
+      //---
+      group = "/Data_Products/VIIRS-DNB-SDR";
+      key = "Instrument_Short_Name";
+      if ( ossim_hdf5::getGroupAttributeValue( m_h5File, group, key, value ) )
+      {
+         key = "sensor_id";
+         kwl->addPair( prefix, key, value );
+      }
+      
+      //---
+      // Look for acquisition date:
+      // hdf5.Data_Products.VIIRS-DNB-SDR.VIIRS-DNB-SDR_Aggr.AggregateBeginningDate: 20140113
+      // hdf5.Data_Products.VIIRS-DNB-SDR.VIIRS-DNB-SDR_Aggr.AggregateBeginningTime: 082810.354645Z
+      //---
+      group = "Data_Products/VIIRS-DNB-SDR/VIIRS-DNB-SDR_Aggr";
+      key = "AggregateBeginningDate";
+      if ( ossim_hdf5::getDatasetAttributeValue( m_h5File, group, key, value ) )
+      {
+         std::string time;
+         key = "AggregateBeginningTime";
+         if ( ossim_hdf5::getDatasetAttributeValue( m_h5File, group, key, time ) )
+         {
+            // Only grab yyyymmddmmss in the form ISO 8601: 2014-01-26T10:32:28Z
+            if ( (value.size() >= 8) && ( time.size() >= 6 ) )
+            {
+               std::string dateTime =
+                  ossimString( ossimString(value.begin(), value.begin() + 4) + "-"
+                               + ossimString(value.begin() + 4, value.begin() + 6) + "-"
+                               + ossimString(value.begin() + 6, value.begin() + 8) + "T"
+                               + ossimString(time.begin(), time.begin() + 2) + ":"
+                               + ossimString(time.begin() + 2, time.begin() + 4) + ":"
+                               + ossimString(time.begin() + 4, time.begin() + 6) + "Z" ).string();
+               key = "acquisition_date";
+               kwl->addPair( prefix, key, dateTime );
+            }
+         }
+      }
+   }
+}
+
diff --git a/ossim_plugins/hdf/ossimH5Reader.h b/ossim_plugins/hdf/ossimH5Reader.h
new file mode 100644
index 0000000..4329c1b
--- /dev/null
+++ b/ossim_plugins/hdf/ossimH5Reader.h
@@ -0,0 +1,313 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author:  David Burken
+//
+// Description: OSSIM HDF5 Reader.
+//
+//----------------------------------------------------------------------------
+// $Id
+
+#ifndef ossimH5Reader_HEADER
+#define ossimH5Reader_HEADER 1
+
+#include "../ossimPluginConstants.h"
+#include <ossim/base/ossimIrect.h>
+#include <ossim/base/ossimRefPtr.h>
+#include <ossim/base/ossimMetadataInterface.h>
+#include <ossim/imaging/ossimImageData.h>
+#include <ossim/imaging/ossimImageHandler.h>
+#include "ossimH5ImageDataset.h"
+
+#include <OpenThreads/Mutex>
+
+#include <vector>
+
+// Forward class declarations:
+namespace H5
+{
+   class DataSet;
+   class H5File;
+}
+
+class OSSIM_PLUGINS_DLL ossimH5Reader : public ossimImageHandler, public ossimMetadataInterface
+{
+public:
+
+   /** default constructor */
+   ossimH5Reader();
+
+   /** virtual destructor */
+   virtual ~ossimH5Reader();
+
+   /** @return "hdf5" */
+   virtual ossimString getShortName() const;
+
+   /** @return "ossim hdf5" */
+   virtual ossimString getLongName()  const;
+
+   /** @return "ossimH5Reader" */
+   virtual ossimString getClassName()    const;
+
+   /**
+    *  Returns a pointer to a tile given an origin representing the upper
+    *  left corner of the tile to grab from the image.
+    *  Satisfies pure virtual from TileSource class.
+    */
+   virtual ossimRefPtr<ossimImageData> getTile(const  ossimIrect& rect,
+                                               ossim_uint32 resLevel=0);
+   /**
+    * Method to get a tile.   
+    *
+    * @param result The tile to stuff.  Note The requested rectangle in full
+    * image space and bands should be set in the result tile prior to
+    * passing.  It will be an error if:
+    * result.getNumberOfBands() != this->getNumberOfOutputBands()
+    *
+    * @return true on success false on error.  If return is false, result
+    *  is undefined so caller should handle appropriately with makeBlank or
+    * whatever.
+    */
+   virtual bool getTile(ossimImageData* result, ossim_uint32 resLevel=0);
+
+    /**
+     *  Returns the number of bands in the image.
+     *  Satisfies pure virtual from ImageHandler class.
+     */
+   virtual ossim_uint32 getNumberOfInputBands() const;
+
+   /**
+    * Returns the number of bands in a tile returned from this TileSource.
+    * Note: we are supporting sources that can have multiple data objects.
+    * If you want to know the scalar type of an object you can pass in the
+    */
+   virtual ossim_uint32 getNumberOfOutputBands()const;
+
+   /**
+     *  Returns the number of lines in the image.
+     *  Satisfies pure virtual from ImageHandler class.
+     */
+   virtual ossim_uint32 getNumberOfLines(ossim_uint32 reduced_res_level = 0) const;
+
+   /**
+    *  Returns the number of samples in the image.
+    *  Satisfies pure virtual from ImageHandler class.
+    */
+   virtual ossim_uint32 getNumberOfSamples(ossim_uint32 reduced_res_level = 0) const;
+
+   /**
+    * Returns the zero based image rectangle for the reduced resolution data
+    * set (rrds) passed in.  Note that rrds 0 is the highest resolution rrds.
+    */
+   virtual ossimIrect getImageRectangle(ossim_uint32 reduced_res_level = 0) const;
+
+   /**
+    * Method to save the state of an object to a keyword list.
+    * Return true if ok or false on error.
+    */
+   virtual bool saveState(ossimKeywordlist& kwl,
+                          const char* prefix=0)const;
+
+   /**
+    * Method to the load (recreate) the state of an object from a keyword
+    * list.  Return true if ok or false on error.
+    */
+   virtual bool loadState(const ossimKeywordlist& kwl,
+                          const char* prefix=0);
+
+   /**
+    * Returns the output pixel type of the tile source.
+    */
+   virtual ossimScalarType getOutputScalarType() const;
+
+   /**
+    * Returns the tile width of the image or 0 if the image is not tiled.
+    * Note: this is not the same as the ossimImageSource::getTileWidth which
+    * returns the output tile width which can be different than the internal
+    * image tile width on disk.
+    */
+   virtual ossim_uint32 getImageTileWidth() const;
+
+   /**
+    * Returns the tile width of the image or 0 if the image is not tiled.
+    * Note: this is not the same as the ossimImageSource::getTileWidth which
+    * returns the output tile width which can be different than the internal
+    * image tile width on disk.
+    */
+   virtual ossim_uint32 getImageTileHeight() const;
+
+   bool isOpen()const;
+
+   /** Close method. */
+   virtual void close();
+
+   /**
+    * @return The number of entries (images) in the image file.
+    */
+   virtual ossim_uint32 getNumberOfEntries()const;
+
+   /**
+    * @brief Get the name of entry as a string.
+    *
+    * Example given from HDF5 file:
+    * 
+    * entry_name: /All_Data/VIIRS-IMG-GTM-EDR-GEO_All/QF1_VIIRSGTMGEO
+    *
+    * @param entryIdx Zero based entry index. If out of range name will
+    * be cleared.
+    * 
+    * @param name Initialized by this.
+    */
+   virtual void getEntryName( ossim_uint32 entryIdx,
+                              std::string& name ) const;
+
+   /**
+    * @param entryList This is the list to initialize with entry indexes.
+    *
+    * @note This implementation returns puts one entry "0" in the list.
+    */
+   virtual void getEntryList(std::vector<ossim_uint32>& entryList) const;
+
+   virtual bool setCurrentEntry(ossim_uint32 entryIdx);
+
+   /**
+    * @return The current entry number.
+    */
+   virtual ossim_uint32 getCurrentEntry() const;
+
+   /**
+    * Returns the image geometry object associated with this tile source or
+    * NULL if non defined.  The geometry contains full-to-local image
+    * transform as well as projection (image-to-world).
+    */
+   virtual ossimRefPtr<ossimImageGeometry> getImageGeometry();
+
+   /** @return Null pixel value. */
+   virtual double getNullPixelValue(ossim_uint32 band=0)const;
+
+   /**
+    * @brief Set propterty method. Overrides ossimImageHandler::setProperty.
+    *
+    * Current property name handled:
+    * "scale" One double value representing the scale in meters per pixel. It is
+    * assumed the scale is same for x and y direction.
+    * 
+    * @param property to set.
+    */
+   virtual void setProperty(ossimRefPtr<ossimProperty> property);
+
+   /**
+     * @brief Get propterty method. Overrides ossimImageHandler::getProperty.
+    * @param name Property name to get.
+    */
+   virtual ossimRefPtr<ossimProperty> getProperty(const ossimString& name) const;
+
+   /**
+    * @brief Get propterty names. Overrides ossimImageHandler::getPropertyNames.
+    * @param propertyNames Array to initialize.
+    */
+   virtual void getPropertyNames(std::vector<ossimString>& propertyNames) const;
+
+   /**
+    * @brief Adds metadata to keyword list.
+    *
+    * This will add metadata to keyword list if found.  Implemented to pass
+    * specific data to keyword list if found, e.g. acquisition_date, sensor_id,
+    * country_code
+    *
+    * Satisfies pure virtual ossimMetadataInterface::addMetadata(...)
+    * 
+    * @param kwl Initialized by this.
+    * @param prefix e.g. "image0." (can be empty)
+    */
+   virtual void addMetadata( ossimKeywordlist* kwl,
+                             const std::string& prefix ) const;
+
+protected:
+
+   /** @brief Method to get geometry from hdf file. */
+   virtual ossimRefPtr<ossimImageGeometry> getInternalImageGeometry();
+
+   /**
+    * @brief Gets bilinear projection from four corners of Latitude, Longitude
+    * if present.  This is a fallback for coarse grid where there are nulls in
+    * the data.
+    *
+    * @param latDataSet H5::DataSet& to layer,
+    *    e.g. /All_Data/VIIRS-DNB-GEO_All/Latitude
+    * @param lonDataSet H5::DataSet& to layer,
+    *    e.g. /All_Data/VIIRS-DNB-GEO_All/Longitude
+    */
+   ossimRefPtr<ossimProjection> processBilinearProjection(
+      H5::DataSet& latDataSet, H5::DataSet& lonDataSet,
+      const ossimIrect& validRect ) const;
+
+   /**
+    * @brief Gets projection from Latitude, Longitude, Height datasets if
+    * present.
+    *
+    * @param latDataSet H5::DataSet& to layer,
+    *    e.g. /All_Data/VIIRS-DNB-GEO_All/Latitude
+    * @param lonDataSet H5::DataSet& to layer,
+    *    e.g. /All_Data/VIIRS-DNB-GEO_All/Longitude
+    */
+   ossimRefPtr<ossimProjection> processCoarseGridProjection(
+      H5::DataSet& latDataSet, H5::DataSet& lonDataSet ) const;
+
+   /**
+    * @brief Get dataset names for Latiitude and Longitude datasets.
+    * @param h5File Pointer to file.
+    * @param latName Initializes by this.
+    * @param lonName Initializes by this.
+    * @return true on sucess, false on error.
+    */
+   bool getLatLonDatasetNames(  H5::H5File* h5File,
+                                std::string& latName,
+                                std::string& lonName ) const;
+   /**
+    * @param Initializes lat and lon data sets.
+    * @param h5File Pointer to file.
+    * @param latDataSet Initialized by this.
+    * @param lonDataSet Initialized by this.
+    */
+   bool getLatLonDatasets( H5::H5File* h5File,
+                           H5::DataSet& latDataSet,
+                           H5::DataSet& lonDataSet ) const; 
+   
+   bool getDataSetRect( std::string& name, std::string& lonName ) const;
+   
+  /**
+    *  @brief open method.
+    *  @return true on success, false on error.
+    */
+   virtual bool open();
+
+   /** @brief Allocates the tile. */ 
+   void allocate();
+
+   /**
+    * @brief Adds image datasets from list of names.
+    * @param names List of dataset paths from hdf5 file.
+    */
+   void addImageDatasetEntries(const std::vector<std::string>& names);
+
+   /**
+    * @return true if key "Mission_Name" is equal to NPP.
+    */
+   bool isNppMission( H5::H5File* h5File ) const;
+   
+   H5::H5File*                      m_h5File;
+   std::vector<ossimH5ImageDataset> m_entries;
+   ossim_uint32                     m_currentEntry;
+   ossimRefPtr<ossimImageData>      m_tile;
+   ossimRefPtr<ossimProjection>     m_projection;
+   OpenThreads::Mutex               m_mutex;
+   
+TYPE_DATA
+};
+
+#endif /* #ifndef ossimH5Reader_HEADER */
+
diff --git a/ossim_plugins/hdf/ossimH5Util.cpp b/ossim_plugins/hdf/ossimH5Util.cpp
new file mode 100644
index 0000000..503c548
--- /dev/null
+++ b/ossim_plugins/hdf/ossimH5Util.cpp
@@ -0,0 +1,1107 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author:  David Burken
+//
+// Description: OSSIM HDF5 utility class.
+//
+//----------------------------------------------------------------------------
+// $Id
+
+#include <ossimH5Util.h>
+#include <ossim/base/ossimCommon.h>
+#include <ossim/base/ossimEndian.h>
+#include <ossim/base/ossimIrect.h>
+#include <ossim/base/ossimKeywordNames.h>
+#include <ossim/base/ossimNotify.h>
+#include <ossim/base/ossimScalarTypeLut.h>
+
+//---
+// This includes everything!  Note the H5 includes are order dependent; hence,
+// the mongo include.
+//---
+#include <hdf5.h>
+#include <H5Cpp.h>
+
+#include <iostream> /* tmp */
+#include <ostream>
+using namespace std;
+
+std::ostream& ossim_hdf5::print(H5::H5File* file, std::ostream& out)
+{
+   if ( file )
+   {
+      std::string groupName     = "/";
+      std::string prefix        = "hdf5";
+      ossim_uint32 recurseCount = 0;
+      
+      ossim_hdf5::printIterative( file, groupName, prefix, recurseCount, out );
+   }
+
+   return out;
+}
+
+void ossim_hdf5::printIterative( H5::H5File* file,
+                                 const std::string& groupName,
+                                 const std::string& prefix,
+                                 ossim_uint32& recursedCount,
+                                 std::ostream& out )
+{
+   if ( file && groupName.size() )
+   {
+      ++recursedCount;
+      
+      H5::Group* group = new H5::Group( file->openGroup(groupName) );
+
+      // Print attributes:
+      const ossim_uint32 ATTRS_COUNT = group->getNumAttrs();
+      for ( ossim_uint32 aIdx = 0; aIdx < ATTRS_COUNT; ++aIdx )
+      {
+         H5::Attribute attr( group->openAttribute( aIdx ) );
+         ossim_hdf5::printAttribute( attr, prefix, out );
+         attr.close();
+      }
+      
+      const hsize_t OBJ_COUNT = group->getNumObjs();
+      for ( hsize_t i = 0; i < OBJ_COUNT; ++i )
+      {
+         std::string objName = group->getObjnameByIdx(i);
+
+         if ( objName.size() )
+         {
+            char separator = '/';
+            std::string combinedName;
+            combine( groupName, objName, separator, combinedName );
+            
+            separator = '.';
+            std::string combinedPrefix;
+            combine( prefix, objName, separator, combinedPrefix );
+            
+            H5G_obj_t objType   = group->getObjTypeByIdx(i);
+
+#if 0
+            std::cout << "combinedName: " << combinedName
+                      << "\ncombinedPrefix: " << combinedPrefix
+                      << "\ngetObjnameByIdx[" << i << "]: " << objName
+                      << "\ngetObjTypeByIdx[" << i << "]: " << objType
+                      << std::endl;
+#endif
+            
+            if ( objType == H5G_GROUP )
+            {
+               // Recursive call:
+               if ( recursedCount < ossim_hdf5::MAX_RECURSION_LEVEL )
+               {
+                  ossim_hdf5::printIterative(
+                     file, combinedName, combinedPrefix, recursedCount, out );
+               }
+               else
+               {
+                  ossimNotify(ossimNotifyLevel_WARN)
+                     << "ossim_hdf5::printIterative WARNING!"
+                     << "\nMax iterations reached!" << std::endl;
+               }
+            }
+            else if ( objType == H5G_DATASET )
+            {
+               printObject( file, combinedName, combinedPrefix, out );
+            }
+            else
+            {
+               ossimNotify(ossimNotifyLevel_WARN)
+                  << "ossim_hdf5::printIterative WARNING!"
+                  << "\nUnhandled object type: " << objType << std::endl;
+            }
+         }
+      }
+      
+      group->close();
+      delete group;
+      group = 0;
+      --recursedCount;
+      
+   } // Matches: if ( file )
+   
+} // End: void ossim_hdf5::printIterative method.
+
+void ossim_hdf5::printObject(  H5::H5File* file,
+                               const std::string& objectName,
+                               const std::string& prefix,
+                               std::ostream& out )
+{
+#if 0
+   std::cout << "printObject entered..."
+             << "\nobjectName: " << objectName
+             << "\nprefix: " << prefix
+             << std::endl;
+#endif
+   
+   H5::DataSet dataset = file->openDataSet( objectName );
+   
+   // Get the class of the datatype that is used by the dataset.
+   H5T_class_t type_class = dataset.getTypeClass();
+   out << prefix << ".class_type: "
+       << ossim_hdf5::getDatatypeClassType( type_class ) << std::endl;
+
+   const ossim_uint32 ATTRS_COUNT = dataset.getNumAttrs();
+   for ( ossim_uint32 aIdx = 0; aIdx < ATTRS_COUNT; ++aIdx )
+   {
+      H5::Attribute attr = dataset.openAttribute( aIdx );
+      ossim_hdf5::printAttribute( attr, prefix, out );
+      attr.close();
+   }
+
+   // Extents:
+   std::vector<ossim_uint32> extents;
+   ossim_hdf5::getExtents( &dataset, extents );
+   for ( ossim_uint32 i = 0; i < extents.size(); ++i )
+   {
+      ossimString os;
+      std::string exStr = ".extent";
+      exStr += os.toString(i).string();
+      out << prefix << exStr << ": " << extents[i] << std::endl;
+   }
+
+   // ossimScalarType scalar = getScalarType( type_class, dataset.getId() );
+   ossimScalarType scalar = ossim_hdf5::getScalarType( dataset.getId() );
+   if ( scalar != OSSIM_SCALAR_UNKNOWN)
+   {
+      out << prefix << "." << ossimKeywordNames::SCALAR_TYPE_KW << ": "
+          << ossimScalarTypeLut::instance()->getEntryString( scalar ) << std::endl;
+
+      if ( ossim::scalarSizeInBytes( scalar ) > 1 )
+      {
+         ossimByteOrder byteOrder = ossim_hdf5::getByteOrder( &dataset );
+         std::string byteOrderString = "little_endian";
+         if ( byteOrder == OSSIM_BIG_ENDIAN )
+         {
+            byteOrderString = "big_endian";
+         }
+         out << prefix << "." <<ossimKeywordNames::BYTE_ORDER_KW << ": "
+             << byteOrderString << std::endl;
+      }
+   }
+
+#if 0
+   // Attributes:
+   int numberOfAttrs = dataset.getNumAttrs();
+   cout << "numberOfAttrs: " << numberOfAttrs << endl;
+   for ( ossim_int32 attrIdx = 0; attrIdx < numberOfAttrs; ++attrIdx )
+   {
+      H5::Attribute attribute = dataset.openAttribute( attrIdx );
+      cout << "attribute.from class: " << attribute.fromClass() << endl;
+   }
+#endif
+   dataset.close();
+   
+} // End: printObject
+
+bool ossim_hdf5::getGroupAttributeValue( H5::H5File* file,
+                                         const std::string& group,
+                                         const std::string& key,
+                                         std::string& value )
+{
+   static const char MODULE[] = "ossim_hdf5::getGroupAttributeValue";
+   
+   bool result = false;
+   
+   if (  file )
+   {
+      try // HDF5 library throws exceptions so wrap with try{}catch...
+      {
+         // Open the root group:
+         H5::Group* h5Group = new H5::Group( file->openGroup( group ) );
+         
+         // Lookw for key:
+         H5::Attribute attr      = h5Group->openAttribute( key );
+         std::string   name      = attr.getName();
+         H5::DataType  type      = attr.getDataType();
+         H5T_class_t   typeClass = attr.getTypeClass();
+         
+         if ( ( name == key ) && ( typeClass == H5T_STRING ) )
+         {
+            attr.read( type, value );
+            result = true;
+         }
+
+         // Cleanup:
+         attr.close();
+         h5Group->close();
+         delete h5Group;
+         h5Group = 0;
+      }
+      catch( const H5::Exception& e )
+      {
+         ossimNotify(ossimNotifyLevel_WARN)
+            << MODULE << " WARNING: Caught exception!\n"
+            << e.getDetailMsg() << std::endl;
+      }
+      catch( ... )
+      {
+         ossimNotify(ossimNotifyLevel_WARN)
+            << MODULE << " WARNING: Caught unknown exception!" << std::endl;
+      }      
+   }
+
+   return result;
+   
+} // End: ossim_hdf5::getGroupAttributeValue
+
+bool ossim_hdf5::getDatasetAttributeValue( H5::H5File* file,
+                                           const std::string& objectName,
+                                           const std::string& key,
+                                           std::string& value )
+{
+   static const char MODULE[] = "ossim_hdf5::getDatasetAttributeValue";
+
+   bool result = false;
+   
+   if (  file )
+   {
+      try // HDF5 library throws exceptions so wrap with try{}catch...
+      {
+         // Open the dataset:
+         H5::DataSet dataset = file->openDataSet( objectName );
+         
+         // Lookw for key:
+         H5::Attribute attr = dataset.openAttribute( key );
+
+         std::string  name = attr.getName();
+         H5::DataType type = attr.getDataType();
+         H5T_class_t  typeClass = attr.getTypeClass();
+         
+         if ( ( name == key ) && ( typeClass == H5T_STRING ) )
+         {
+            attr.read( type, value );
+            result = true;
+         }
+
+         // Cleanup:
+         attr.close();
+         dataset.close();
+      }
+      catch( const H5::Exception& e )
+      {
+         ossimNotify(ossimNotifyLevel_WARN)
+            << MODULE << " WARNING: Caught exception!\n"
+            << e.getDetailMsg() << std::endl;
+      }
+      catch( ... )
+      {
+         ossimNotify(ossimNotifyLevel_WARN)
+            << MODULE << " WARNING: Caught unknown exception!" << std::endl;
+      }      
+   }
+
+   return result;
+   
+} // End: ossim_hdf5::getDatasetAttributeValue
+
+void ossim_hdf5::printAttribute( const H5::Attribute& attr,
+                                 const std::string& prefix,
+                                 std::ostream& out )
+{
+   std::string  name      = attr.getName();
+   H5::DataType type      = attr.getDataType();
+   H5T_class_t  typeClass = attr.getTypeClass();
+   size_t       size      = type.getSize();
+   
+   std::string  value; // Initialized below.
+
+   if ( ( typeClass == H5T_INTEGER ) || ( typeClass == H5T_FLOAT ) )
+   {
+      H5::IntType intType = attr.getIntType();
+
+      ossimScalarType scalar = ossim_hdf5::getScalarType( intType.getId() );
+      
+      ossimByteOrder order = ossim_hdf5::getByteOrder( &attr );
+      ossimEndian* endian = 0;
+      if ( ( size > 1 ) && ( order != ossim::byteOrder() ) )
+      {
+         endian = new ossimEndian(); // If set used as flag to byte swap.
+      }
+      
+      if ( typeClass == H5T_INTEGER )
+      {
+         switch ( scalar )
+         {
+            case OSSIM_UINT8:
+            {
+               if ( size == 1 )
+               {
+                  ossim_uint8 i;
+                  attr.read( type, (void*)&i );
+                  value = ossimString::toString( ossim_int32(i) ).string();
+               }
+               break;
+            }
+            case OSSIM_SINT8:
+            {
+               if ( size == 1 )
+               {
+                  ossim_sint8 i;
+                  attr.read( type, (void*)&i );
+                  value = ossimString::toString( ossim_int32(i) ).string();
+               }
+               break;
+            }
+            case OSSIM_UINT16:            
+            {
+               if ( size == 2 )
+               {
+                  ossim_uint16 i;
+                  attr.read( type, (void*)&i );
+                  if ( endian )
+                  {
+                     endian->swap( i );
+                  }  
+                  value = ossimString::toString( i ).string();
+               }
+               break;
+            }
+            case OSSIM_SINT16:
+            {
+               if ( size == 2 )
+               {
+                  ossim_sint16 i;
+                  attr.read( type, (void*)&i );
+                  if ( endian )
+                  {
+                     endian->swap( i );
+                  }
+                  value = ossimString::toString( i ).string();
+               }
+               break;
+            }
+            case OSSIM_UINT32:        
+            {
+               if ( size == 4 )
+               {
+                  ossim_uint32 i;
+                  attr.read( type, (void*)&i );
+                  if ( endian )
+                  {
+                     endian->swap( i );
+                  }  
+                  value = ossimString::toString( i ).string();
+               }
+               break;
+            }
+            case OSSIM_SINT32:
+            {
+               if ( size == 4 )
+               {
+                  ossim_sint32 i;
+                  attr.read( type, (void*)&i );
+                  if ( endian )
+                  {
+                     endian->swap( i );
+                  }
+                  value = ossimString::toString( i ).string();
+               }
+               break;
+            }
+            case OSSIM_UINT64:        
+            {
+               if ( size == 8 )
+               {
+                  ossim_uint64 i;
+                  attr.read( type, (void*)&i );
+                  if ( endian )
+                  {
+                     endian->swap( i );
+                  }  
+                  value = ossimString::toString( i ).string();
+               }
+               break;
+            }
+            case OSSIM_SINT64:
+            {
+               if ( size == 8 )
+               {
+                  ossim_sint32 i;
+                  attr.read( type, (void*)&i );
+                  if ( endian )
+                  {
+                     endian->swap( i );
+                  }
+                  value = ossimString::toString( i ).string();
+               }
+               break;
+            }
+            default:
+               break;
+         }
+      }
+      else if ( typeClass == H5T_FLOAT )
+      {
+         if ( scalar == OSSIM_FLOAT32 )
+         {
+            if ( size == 4 )
+            {
+               ossim_float32 f;
+               attr.read( type, (void*)&f );
+               if ( endian )
+               {
+                  endian->swap( f );
+               }
+               value = ossimString::toString( f ).string();
+            }
+         }
+         if ( scalar == OSSIM_FLOAT64 )
+         {
+            if ( size == 8 )
+            {
+               ossim_float64 f;
+               attr.read( type, (void*)&f );
+               if ( endian )
+               {
+                  endian->swap( f );
+               }
+               value = ossimString::toString( f ).string();
+            }
+         }
+      }
+
+      if ( endian )
+      {
+         delete endian;
+         endian = 0;
+      }
+   }
+   else if ( typeClass == H5T_STRING )
+   {
+      attr.read( type, value );
+   }
+   else
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimH5Util::printAttribute WARN: Unhandled type class: " << typeClass
+         << std::endl;
+   }
+
+   out << prefix << "." << name << ": " << value << std::endl;
+   
+} // End: ossim_hdf5::printAttribute
+
+void ossim_hdf5::combine( const std::string& left,
+                          const std::string& right,
+                          char separator,
+                          std::string& result )
+{
+   if ( left.size() && right.size() )
+   {
+      result = left;
+      if ( ( left[ left.size()-1 ] != separator ) && ( right[0] != separator ) )
+      {
+         result.push_back(separator);
+      }
+      result += right;
+   }
+}
+
+void ossim_hdf5::getDatasetNames(H5::H5File* file,
+                                 std::vector<std::string>& datasetNames )
+{
+   datasetNames.clear();
+   
+   if ( file )
+   {
+      std::string groupName = "/";
+      ossim_uint32 recurseCount = 0;
+      ossim_hdf5::iterateGroupForDatasetNames( file, groupName, datasetNames, recurseCount );
+#if 0
+      std::vector<std::string>::const_iterator i = datasetNames.begin();
+      while ( i != datasetNames.end() )
+      {
+         std::cout << "dataset: " << (*i) << std::endl;
+         ++i;
+      }
+#endif
+   }
+}
+
+std::string ossim_hdf5::getDatatypeClassType( ossim_int32 type )
+{
+   H5T_class_t classType = (H5T_class_t)type;
+   
+   std::string result;
+   switch ( classType )
+   {
+      case H5T_INTEGER:
+         result = "H5T_INTEGER";
+         break;
+      case H5T_FLOAT:
+         result = "H5T_FLOAT";
+         break;         
+      case H5T_TIME:
+         result = "H5T_TIME";
+         break;
+      case H5T_STRING:
+         result = "H5T_STRING";
+         break;
+      case H5T_BITFIELD:
+         result = "H5T_BITFIELD";
+         break;
+      case H5T_OPAQUE:
+         result = "H5T_OPAQUE";
+         break;         
+      case H5T_COMPOUND:
+         result = "H5T_COMPOUND";
+         break;
+      case H5T_REFERENCE:
+         result = "H5T_REFERENCE";
+         break;         
+      case H5T_ENUM:
+         result = "H5T_ENUM";
+         break;
+      case H5T_VLEN:
+         result = "H5T_VLEN";
+         break;         
+      case H5T_ARRAY:
+         result = "H5T_ARRAY";
+         break;
+      case H5T_NO_CLASS:
+      default:
+         result = "H5T_ARRAY";
+         break;
+   }
+   return result;
+}
+
+bool ossim_hdf5::isLoadableAsImage( H5::H5File* file, const std::string& datasetName )
+{
+   bool result = false;
+
+   // std::cout << "isLoadable entered..." << std::endl;
+   if ( file && datasetName.size() )
+   {
+      if ( isExcludedDataset( datasetName ) == false )
+      {
+         H5::DataSet dataset = file->openDataSet( datasetName );
+         
+         // Get the class of the datatype that is used by the dataset.
+         H5T_class_t type_class = dataset.getTypeClass();
+         // std::cout << "Class type: " << ossim_hdf5::getDatatypeClassType( type_class )
+         // << std::endl;
+         
+         if ( ( type_class == H5T_INTEGER ) || ( type_class == H5T_FLOAT ) )
+         {
+            // Get dataspace of the dataset.
+            // H5::DataSpace dataspace = dataset.getSpace();
+            
+            // Get the extents:
+            std::vector<ossim_uint32> extents;
+            ossim_hdf5::getExtents( &dataset, extents );
+            
+            if ( extents.size() >= 2 )
+            {
+               if ( ( extents[0] > 1 ) && ( extents[1] > 1 ) )
+               {
+                  // std::cout << "Accepting dataset: " << datasetName << std::endl;
+                  result = true;
+               }     
+            }
+            
+         }
+         
+         dataset.close();
+      }
+   }
+      
+   // std::cout << "isLoadable exit status: " << (result?"true":"false") << std::endl;
+   
+   return result;
+}
+
+bool ossim_hdf5::isExcludedDataset( const std::string& datasetName )
+{
+   bool result = false;
+   
+   ossimFilename f = datasetName;
+   f = f.file();
+#if 1
+   if ( f != "Radiance" )
+   {
+      result = true;
+   }
+#endif
+   
+#if 0
+   if ( ( f == "Latitude" )        ||
+        ( f == "Longitude" )       ||
+        ( f == "SCAttitude" )      ||
+        ( f == "SCPosition" )      ||
+        ( f == "SCVelocity" ) )
+   {
+      result = true;
+   }
+#endif
+   
+   return result;
+}
+
+void ossim_hdf5::iterateGroupForDatasetNames(  H5::H5File* file,
+                                               const std::string& groupName,
+                                               std::vector<std::string>& datasetNames,
+                                               ossim_uint32& recursedCount )
+{
+   if ( file && groupName.size() )
+   {
+      ++recursedCount;
+      
+      // std::cout << "iterateGroup: " << groupName << std::endl;
+      
+      H5::Group* group = new H5::Group( file->openGroup(groupName) );
+      
+      const hsize_t OBJ_COUNT = group->getNumObjs();
+      
+      for ( hsize_t i = 0; i < OBJ_COUNT; ++i )
+      {
+         std::string objName = group->getObjnameByIdx(i);
+
+         if ( objName.size() )
+         {
+            char separator = '/';
+            std::string combinedName;
+            combine( groupName, objName, separator, combinedName );
+            
+            H5G_obj_t objType   = group->getObjTypeByIdx(i);
+
+#if 0
+            std::cout << "combinedName: " << combinedName
+                      << "\ngetObjnameByIdx[" << i << "]: " << objName
+                      << "\ngetObjTypeByIdx[" << i << "]: " << objType
+                      << std::endl;
+#endif
+
+            if ( objType == H5G_GROUP )
+            {
+               // Recursive call:
+               if ( recursedCount < ossim_hdf5::MAX_RECURSION_LEVEL )
+               {
+                  ossim_hdf5::iterateGroupForDatasetNames(
+                     file, combinedName, datasetNames, recursedCount );
+               }
+               else
+               {
+                  ossimNotify(ossimNotifyLevel_WARN)
+                     << "ossim_hdf5::iterateGroupForDatasetNames WARNING!"
+                     << "\nMax iterations reached!" << std::endl;
+               }
+            }
+            else if ( objType == H5G_DATASET )
+            {
+               datasetNames.push_back( combinedName );
+            }
+            else
+            {
+               ossimNotify(ossimNotifyLevel_WARN)
+                     << "ossim_hdf5::iterateGroupForDatasetNames WARNING!"
+                     << "\nUnhandled object type: " << objType << std::endl;
+            }
+         }
+      }
+      
+      group->close();
+      delete group;
+      group = 0;
+      --recursedCount;
+      
+   } // Matches: if ( file )
+   
+} // End: void ossim_hdf5::iterateGroupForDatasetNames
+
+void ossim_hdf5::getExtents( const H5::DataSet* dataset,
+                             std::vector<ossim_uint32>& extents )
+{
+   extents.clear();
+   
+   if ( dataset )
+   {
+      // Get dataspace of the dataset.
+      H5::DataSpace dataspace = dataset->getSpace();
+      
+      // Number of dimensions:
+      int ndims = dataspace.getSimpleExtentNdims();
+      if ( ndims )
+      {
+         //hsize_t dims_out[ndims];
+         std::vector<hsize_t> dims_out(ndims);
+         dataspace.getSimpleExtentDims( &dims_out.front(), 0 );
+         for ( ossim_int32 i = 0; i < ndims; ++i )
+         {
+            extents.push_back(static_cast<ossim_uint32>(dims_out[i]));
+         }
+      }
+
+      dataspace.close();
+   }
+}
+
+ossimScalarType ossim_hdf5::getScalarType( const H5::DataSet* dataset )
+{
+   // cout << "typeClass: " << typeClass << "\nid: " << id << endl;
+
+   ossimScalarType scalar = OSSIM_SCALAR_UNKNOWN;
+
+   if ( dataset )
+   {
+      ossim_int32 typeClass = dataset->getTypeClass();
+      
+      if ( ( typeClass == H5T_INTEGER ) || ( typeClass == H5T_FLOAT ) )
+      {
+         // hid_t mem_type_id = H5Dget_type(id);
+         hid_t mem_type_id = H5Dget_type( dataset->getId() );
+         
+         // cout << "mem_type_id: " << mem_type_id << endl;
+         
+         if( mem_type_id > -1 )
+         {
+            hid_t native_type = H5Tget_native_type(mem_type_id, H5T_DIR_DEFAULT);
+            // hid_t native_type = H5Tget_native_type(id, H5T_DIR_DEFAULT);
+            
+            if( H5Tequal(H5T_NATIVE_CHAR, native_type) )
+            {
+               scalar = OSSIM_SINT8;
+            }
+            else if ( H5Tequal( H5T_NATIVE_UCHAR, native_type) )
+            {
+               scalar = OSSIM_UINT8;
+            }
+            else if( H5Tequal( H5T_NATIVE_SHORT, native_type) ) 
+            {
+               scalar = OSSIM_SINT16;
+            }
+            else if(H5Tequal(H5T_NATIVE_USHORT, native_type)) 
+            {
+               scalar = OSSIM_UINT16;
+            }
+            else if(H5Tequal( H5T_NATIVE_INT, native_type)) 
+            {
+               scalar = OSSIM_SINT32;
+            }
+            else if(H5Tequal( H5T_NATIVE_UINT, native_type ) ) 
+            {
+               scalar = OSSIM_UINT32;
+            }
+            else if(H5Tequal( H5T_NATIVE_LONG, native_type)) 
+            {
+               scalar = OSSIM_SINT32;
+            }
+            else if(H5Tequal( H5T_NATIVE_ULONG, native_type))
+            {
+               scalar = OSSIM_UINT32;
+            }
+            else if(H5Tequal( H5T_NATIVE_LLONG, native_type)) 
+            {
+               scalar = OSSIM_SINT64;
+            }
+            else if(H5Tequal( H5T_NATIVE_ULLONG, native_type))
+            {
+               scalar = OSSIM_UINT64;
+            }
+            else if(H5Tequal( H5T_NATIVE_FLOAT, native_type)) 
+            {
+               scalar = OSSIM_FLOAT32;
+            }
+            else if(H5Tequal( H5T_NATIVE_DOUBLE, native_type)) 
+            {
+               scalar = OSSIM_FLOAT64;
+            }
+         }
+         
+      } // Matches: if ( ( typeClass == ...
+      
+   } // Matches: if ( dataset ){
+   
+   return scalar;
+   
+} // End: ossim_hdf5::getScalarType( const H5::DataSet* dataset )
+
+ossimScalarType ossim_hdf5::getScalarType( ossim_int32 id )
+{
+   ossimScalarType scalar = OSSIM_SCALAR_UNKNOWN;
+   
+   H5T_class_t type_class = H5Tget_class(id);
+   size_t      size       = H5Tget_size(id);
+   H5T_sign_t  sign       = H5Tget_sign(id);
+   
+   if ( type_class == H5T_INTEGER )
+   {
+      if ( size == 1 && sign == H5T_SGN_2)
+      {
+         scalar = OSSIM_SINT8;
+      }
+      else if ( size == 2 && sign == H5T_SGN_2)
+      {
+         scalar = OSSIM_SINT16;
+      }
+      else if ( size == 4 && sign == H5T_SGN_2)
+      {
+         scalar = OSSIM_SINT32;
+      }
+      else if ( size == 8 && sign == H5T_SGN_2)
+      {
+         scalar = OSSIM_SINT64;
+      }
+      else if ( size == 1 && sign == H5T_SGN_NONE)
+      {
+         scalar = OSSIM_UINT8;
+      }
+      else if ( size == 2 && sign == H5T_SGN_NONE)
+      {
+         scalar = OSSIM_UINT16;
+      }
+      else if ( size == 4 && sign == H5T_SGN_NONE)
+      {
+         scalar = OSSIM_UINT32;
+      }
+      else if ( size == 8 && sign == H5T_SGN_NONE)
+      {
+         scalar = OSSIM_UINT64;
+      }
+   }
+   else if ( type_class == H5T_FLOAT )
+   {
+      if ( size == 4)
+      {
+         scalar = OSSIM_FLOAT32;
+      }
+      else if ( size == 8)
+      {
+         scalar = OSSIM_FLOAT64;
+      }
+   }
+   
+   return scalar;
+}
+
+ossimByteOrder ossim_hdf5::getByteOrder( const H5::AbstractDs* obj )
+{
+   ossimByteOrder byteOrder = ossim::byteOrder();
+   if ( obj )
+   {
+      // Get the class of the datatype that is used by the dataset.
+      H5T_class_t typeClass = obj->getTypeClass();
+
+      H5T_order_t order = H5T_ORDER_NONE;
+      
+      if ( typeClass == H5T_INTEGER )
+      {
+         H5::IntType intype = obj->getIntType();
+         order = intype.getOrder();
+      }
+      else if ( typeClass == H5T_FLOAT )
+      {
+         H5::FloatType floatType = obj->getFloatType();
+         order = floatType.getOrder(); 
+      }
+      
+      if ( order == H5T_ORDER_LE )
+      {
+         byteOrder = OSSIM_LITTLE_ENDIAN;
+      }
+      else if ( order == H5T_ORDER_BE )
+      {
+         byteOrder = OSSIM_BIG_ENDIAN;
+      }
+   }
+   return byteOrder;
+}
+
+bool ossim_hdf5::getBoundingRect( H5::DataSet& dataset, ossimIrect& rect )
+{
+   bool result = false;
+   
+   H5::DataSpace dataspace = dataset.getSpace();
+         
+   // Number of dimensions of the input dataspace:
+   const ossim_int32 DIM_COUNT = dataspace.getSimpleExtentNdims();
+         
+   if ( DIM_COUNT == 2 )
+   {
+      // Get the extents. Assuming dimensions are same for lat lon dataset. 
+      std::vector<hsize_t> dimsOut(DIM_COUNT);
+      dataspace.getSimpleExtentDims( &dimsOut.front(), 0 );
+
+      if ( dimsOut[0] && dimsOut[1] )
+      {
+         //---
+         // Capture the rectangle:
+         // dimsOut[0] is height, dimsOut[1] is width:
+         //---
+         rect = ossimIrect( 0, 0,
+                            static_cast<ossim_int32>( dimsOut[1]-1 ),
+                            static_cast<ossim_int32>( dimsOut[0]-1 ) );
+               
+         std::vector<hsize_t> inputCount(DIM_COUNT);
+         std::vector<hsize_t> inputOffset(DIM_COUNT);
+         
+         inputOffset[0] = 0;
+         inputOffset[1] = 0;
+         
+         inputCount[0] = 1;
+         inputCount[1] = 1;
+         
+         // Output dataspace dimensions.
+         const ossim_int32 OUT_DIM_COUNT = 3;
+         std::vector<hsize_t> outputCount(OUT_DIM_COUNT);
+         outputCount[0] = 1; // single band
+         outputCount[1] = 1; // single line
+         outputCount[2] = 1; // single sample
+               
+         // Output dataspace offset.
+         std::vector<hsize_t> outputOffset(OUT_DIM_COUNT);
+         outputOffset[0] = 0;
+         outputOffset[1] = 0;
+         outputOffset[2] = 0;
+               
+         ossimScalarType scalar = ossim_hdf5::getScalarType( &dataset );
+         if ( scalar == OSSIM_FLOAT32 )
+         {
+            // See if we need to swap bytes:
+            ossimEndian* endian = 0;
+            if ( ( ossim::byteOrder() != ossim_hdf5::getByteOrder( &dataset ) ) )
+            {
+               endian = new ossimEndian();
+            }
+
+            // Native type:
+            H5::DataType datatype = dataset.getDataType();
+                  
+            // Output dataspace always the same one pixel.
+            H5::DataSpace bufferDataSpace( OUT_DIM_COUNT, &outputCount.front());
+            bufferDataSpace.selectHyperslab( H5S_SELECT_SET,
+                                             &outputCount.front(),
+                                             &outputOffset.front() );
+
+            //---
+            // Dataset sample has NULL lines at the end so scan for valid rect.
+            // Use "<= -999" for test as per NOAA as it seems the NULL value is
+            // fuzzy.  e.g. -999.3.
+            //---
+            const ossim_float32 NULL_VALUE = -999.0;
+            ossim_float32 value = 0.0;
+
+            // Find the ul pixel:
+            ossimIpt ulIpt = rect.ul();
+            bool found = false;
+                  
+            // Line loop to find upper left pixel:
+            while ( ulIpt.y <= rect.lr().y )
+            {
+               inputOffset[0] = static_cast<hsize_t>(ulIpt.y);
+                     
+               // Sample loop:
+               ulIpt.x = rect.ul().x;
+               while ( ulIpt.x <= rect.lr().x )
+               {
+                  inputOffset[1] = static_cast<hsize_t>(ulIpt.x);
+                        
+                  dataspace.selectHyperslab( H5S_SELECT_SET,
+                                                &inputCount.front(),
+                                                &inputOffset.front() );
+                        
+                  // Read data from file into the buffer.
+                  dataset.read( &value, datatype, bufferDataSpace, dataspace );
+                        
+                  if ( endian )
+                  {
+                     // If the endian pointer is initialized(not zero) swap the bytes.
+                     endian->swap( value );
+                  }
+                        
+                  if ( value > NULL_VALUE )
+                  {
+                     found = true;
+                     break;
+                  }
+                  ++ulIpt.x;
+                     
+               } // End: sample loop
+                     
+               if ( found )
+               {
+                  break;
+               }
+
+               ++ulIpt.y;
+                     
+            } // End line loop to find ul pixel:
+
+            // Find the lower right pixel:
+            ossimIpt lrIpt = rect.lr();
+            found = false;
+                  
+            // Line loop to find last pixel:
+            while ( lrIpt.y >= rect.ul().y )
+            {
+               inputOffset[0] = static_cast<hsize_t>(lrIpt.y);
+                     
+               // Sample loop:
+               lrIpt.x = rect.lr().x;
+               while ( lrIpt.x >= rect.ul().x )
+               {
+                  inputOffset[1] = static_cast<hsize_t>(lrIpt.x);
+                        
+                  dataspace.selectHyperslab( H5S_SELECT_SET,
+                                             &inputCount.front(),
+                                             &inputOffset.front() );
+                        
+                  // Read data from file into the buffer.
+                  dataset.read( &value, datatype, bufferDataSpace, dataspace );
+                        
+                  if ( endian )
+                  {
+                     // If the endian pointer is initialized(not zero) swap the bytes.
+                     endian->swap( value );
+                  }
+                  
+                  if ( value > NULL_VALUE )
+                  {
+                     found = true;
+                     break;
+                  }
+                  --lrIpt.x;
+                     
+               } // End: sample loop
+                     
+               if ( found )
+               {
+                  break;
+               }
+
+               --lrIpt.y;
+                     
+            } // End line loop to find lower right pixel.
+
+            rect = ossimIrect( ulIpt, lrIpt );
+
+            result = true;
+
+            //cout << "ossim_hdf5::getBoundingRect rect: " << rect << endl;
+            
+         } 
+         else // Matches: if ( scalar == OSSIM_FLOAT32 ){...}
+         {
+            ossimNotify(ossimNotifyLevel_WARN)
+               << "ossim_hdf5::getBoundingRect WARNING!"
+               << "\nUnhandled scalar type: "
+               << ossimScalarTypeLut::instance()->getEntryString( scalar )
+               << std::endl;
+         }
+               
+      } // Matches: if ( dimsOut...
+            
+   } // Matches: if ( IN_DIM_COUNT == 2 )
+         
+   dataspace.close();
+
+   return result;
+   
+} // End: ossim_hdf5::getBoundingRect(...)
+
diff --git a/ossim_plugins/hdf/ossimH5Util.h b/ossim_plugins/hdf/ossimH5Util.h
new file mode 100644
index 0000000..353e28b
--- /dev/null
+++ b/ossim_plugins/hdf/ossimH5Util.h
@@ -0,0 +1,181 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author:  David Burken
+//
+// Description: OSSIM HDF5 utility class.
+//
+//----------------------------------------------------------------------------
+// $Id
+
+#ifndef ossimH5Util_HEADER
+#define ossimH5Util_HEADER 1
+
+#include <ossim/base/ossimConstants.h>
+
+#include <iosfwd>
+#include <string>
+#include <vector>
+
+// Forward class declarations:
+class ossimIrect;
+namespace H5
+{
+   class AbstractDs;
+   class Attribute;
+   class DataSet;
+   class H5File;
+}
+
+// Anonymous enums:
+enum 
+{
+   OSSIM_H5_MAX_RECURSION_LEVEL = 8
+};
+
+namespace ossim_hdf5
+{
+   // Anonymous enums:
+   enum 
+   {
+      //---
+      // Used by iterateGroupForDatasetNames which can recursively call itself
+      // to avoid blowing away the stack on an error.
+      //---
+      MAX_RECURSION_LEVEL = 8
+   };
+
+   /**
+    * @brief Print method.
+    *
+    * @param file Pointer to H5File instance.
+    * @param out Stream to print to.
+    * @return std::ostream&
+    */
+   std::ostream& print( H5::H5File* file,
+                        std::ostream& out );   
+
+   /**
+    * @brief Iterative print method.
+    * @param file Pointer to H5File instance.
+    * @param prefix to start the walk with.
+    * @param recursedCount Callers should start at zero. This is used
+    * internally to avoid an infinite loop as this method recursively
+    * calls itself.
+    * @param out Stream to print to.
+    */   
+   void printIterative( H5::H5File* file,
+                        const std::string& groupName,
+                        const std::string& prefix,
+                        ossim_uint32& recursedCount,
+                        std::ostream& out );
+
+   /**
+    * @brief Prints an object.
+    * @param file Pointer to H5File instance.
+    * @param prefix to start the walk with.
+    * @param recursedCount Callers should start at zero. This is used
+    * internally to avoid an infinite loop as this method recursively
+    * calls itself.
+    * @param out Stream to print to.
+    */ 
+   void printObject(  H5::H5File* file,
+                      const std::string& objectName,
+                      const std::string& prefix,
+                      std::ostream& out );
+
+   /**
+    * @brief Gets string value for attribute key.
+    *
+    * This assumes H5::Attribute type class is a H5T_STRING.
+    * 
+    * @param file Pointer to H5File instance.
+    *
+    * @param group Group to open. Examples:
+    * "/"
+    * "/Data_Products/VIIRS-DNB-GEO"
+    * 
+    * @param key This is key string. Examples:
+    * "Mission_Name"
+    * "N_Collection_Short_Name"
+    *
+    * @param value Initialized by this.
+    *
+    * @return true on success, false on error.
+    */    
+   bool getGroupAttributeValue( H5::H5File* file,
+                                const std::string& group,
+                                const std::string& key,
+                                std::string& value );
+   
+   /**
+    * @brief Gets string value for attribute key.
+    *
+    * This assumes H5::Attribute type class is a H5T_STRING.
+    * 
+    * @param file Pointer to H5File instance.
+    *
+    * @param dataset Data to open. Examples:
+    * "/"
+    * "/Data_Products/VIIRS-DNB-GEO"
+    * 
+    * @param key This is key string. Examples:
+    * "Mission_Name"
+    * "N_Collection_Short_Name"
+    *
+    * @param value Initialized by this.
+    *
+    * @return true on success, false on error.
+    */    
+   bool getDatasetAttributeValue( H5::H5File* file,
+                                const std::string& objectName,
+                                const std::string& key,
+                                std::string& value );
+   
+   void printAttribute( const H5::Attribute& attr,
+                        const std::string& prefix,
+                        std::ostream& out );
+   
+   void combine( const std::string& left,
+                 const std::string& right,
+                 char separator,
+                 std::string& result );
+   
+   void getDatasetNames(H5::H5File* file, std::vector<std::string>& names );
+
+   std::string getDatatypeClassType( ossim_int32 type );
+
+   bool isLoadableAsImage( H5::H5File* file,
+                           const std::string& datasetName );
+
+   bool isExcludedDataset( const std::string& datasetName );
+
+   void iterateGroupForDatasetNames( H5::H5File* file,
+                                     const std::string& group,
+                                     std::vector<std::string>& names,
+                                     ossim_uint32& recursedCount );
+
+   void getExtents( const H5::DataSet* dataset,
+                    std::vector<ossim_uint32>& extents );
+
+   // ossimScalarType getScalarType( ossim_int32 typeClass, ossim_int32 id );
+   ossimScalarType getScalarType( const H5::DataSet* dataset );
+
+
+   ossimScalarType getScalarType( ossim_int32 id );
+   
+   ossimByteOrder getByteOrder( const H5::AbstractDs* dataset );
+
+   /**
+    * @brief Gets the bounding rect of the dataset.
+    * @param dataset
+    * @param rect Initialized by this.
+    */
+   bool getBoundingRect( H5::DataSet& dataset, ossimIrect& rect );
+}
+
+#endif /* #ifndef ossimH5Util_HEADER */
+
diff --git a/ossim_plugins/hdf/ossimHdf4Reader.cpp b/ossim_plugins/hdf/ossimHdf4Reader.cpp
new file mode 100644
index 0000000..b6c2b4a
--- /dev/null
+++ b/ossim_plugins/hdf/ossimHdf4Reader.cpp
@@ -0,0 +1,1490 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Description:  Class definition for HDF4 reader.
+//
+//----------------------------------------------------------------------------
+// $Id: ossimHdf4Reader.cpp 2645 2011-05-26 15:21:34Z oscar.kramer $
+
+#include "ossimHdf4Reader.h"
+
+#include <fstream>
+#include <iostream>
+#include <string>
+
+//ossim includes
+#include <ossim/base/ossimCommon.h>
+#include <ossim/base/ossimDpt.h>
+#include <ossim/base/ossimIpt.h>
+#include <ossim/base/ossimEndian.h>
+#include <ossim/base/ossimException.h>
+#include <ossim/base/ossimIoStream.h>
+#include <ossim/base/ossimKeywordlist.h>
+#include <ossim/base/ossimNotify.h>
+#include <ossim/base/ossimScalarTypeLut.h>
+#include <ossim/base/ossimTrace.h>
+#include <ossim/base/ossimUnitTypeLut.h>
+
+#include <ossim/imaging/ossimImageDataFactory.h>
+#include <ossim/imaging/ossimImageGeometryRegistry.h>
+
+#include <ossim/projection/ossimProjection.h>
+#include <ossim/projection/ossimProjectionFactoryRegistry.h>
+#include <ossim/projection/ossimEpsgProjectionFactory.h>
+#include <ossim/projection/ossimUtmProjection.h>
+#include <ossim/projection/ossimEquDistCylProjection.h>
+#include <ossim/projection/ossimLambertConformalConicProjection.h>
+#include <ossim/projection/ossimMercatorProjection.h>
+#include <ossim/projection/ossimPolarStereoProjection.h>
+#include <ossim/projection/ossimPolyconicProjection.h>
+#include <ossim/projection/ossimAzimEquDistProjection.h>
+#include <ossim/projection/ossimObliqueMercatorProjection.h>
+#include <ossim/projection/ossimSpaceObliqueMercatorProjection.h>
+#include <ossim/projection/ossimSinusoidalProjection.h>
+
+#include <ossim/support_data/ossimAuxFileHandler.h>
+
+
+/////////////////////////////////////////
+#include <ossim/base/ossimTieGptSet.h>
+//////////////////////////////////////////
+
+#include "ossimHdf4SubDataset.h"
+#include "ossimHdfGridModel.h"
+
+#ifdef OSSIM_ID_ENABLED
+static const char OSSIM_ID[] = "$Id";
+#endif
+
+const ossimString ossimHdf4Reader::HDF4_EOS_GRID = "GRID";              
+const ossimString ossimHdf4Reader::HDF4_EOS_SWATH = "SWATH";                   
+const ossimString ossimHdf4Reader::HDF4_SEAWIFS_L1A = "SEAWIFS_L1A";		    
+const ossimString ossimHdf4Reader::HDF4_SEAWIFS_L2 = "SEAWIFS_L2";	          
+const ossimString ossimHdf4Reader::HDF4_SEAWIFS_L3 = "SEAWIFS_L3";		       
+const ossimString ossimHdf4Reader::HDF4_HYPERION_L1 = "HYPERION_L1"; 
+const ossimString ossimHdf4Reader::HDF4_SDS = "HDF4_SDS";
+
+static ossimTrace traceDebug("ossimHdf4Reader:debug");
+static ossimTrace traceDump("ossimHdf4Reader:dump");
+
+RTTI_DEF1_INST(ossimHdf4Reader,
+               "ossimHdf4Reader",
+               ossimImageHandler)
+
+               ossimHdf4Reader::ossimHdf4Reader()
+               : ossimImageHandler(),
+               m_fid(-1),
+               m_sd_id(-1),
+               m_imageRect(),
+               m_numberOfBands(0),
+               m_scalarType(OSSIM_SCALAR_UNKNOWN),
+               m_tile(0),
+               m_isHdfEos(false),
+               m_currentEntryRender(0),
+               m_currentSubDataset(NULL),
+               m_structMetadata("")
+{
+}
+
+ossimHdf4Reader::~ossimHdf4Reader()
+{
+   closeEntry();
+}
+
+ossimString ossimHdf4Reader::getShortName()const
+{
+   return ossimString("ossim_hdf4_reader");
+}
+
+ossimString ossimHdf4Reader::getLongName()const
+{
+   return ossimString("ossim hdf4 reader");
+}
+
+ossimString ossimHdf4Reader::getClassName()const
+{
+   return ossimString("ossimHdf4Reader");
+}
+
+ossim_uint32 ossimHdf4Reader::getNumberOfLines(ossim_uint32 resLevel) const
+{
+   ossim_uint32 result = 0;
+   if ( isValidRLevel(resLevel) )
+   {
+      if (resLevel == 0)
+      {
+         if (m_currentSubDataset != NULL)
+         {
+            return m_currentSubDataset->getNumberOfLines();
+         }
+      }
+      else if (theOverview.valid())
+      {
+         result = theOverview->getNumberOfSamples(resLevel);
+      }
+   }
+   return result;
+}
+
+ossim_uint32 ossimHdf4Reader::getNumberOfSamples(ossim_uint32 resLevel) const
+{
+   ossim_uint32 result = 0;
+   if ( isValidRLevel(resLevel) )
+   {
+      if (resLevel == 0)
+      {
+         if (m_currentSubDataset != NULL)
+         {
+            return m_currentSubDataset->getNumberOfSamples();
+         }
+      }
+      else if (theOverview.valid())
+      {
+         result = theOverview->getNumberOfSamples(resLevel);
+      }
+   }
+   return result;
+}
+
+bool ossimHdf4Reader::open()
+{
+   static const char MODULE[] = "ossimHdf4Reader::open";
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " entered...\n"
+         << "image: " << theImageFile << "\n";
+   }
+
+   bool result = false;
+
+   if (Hishdf(theImageFile.c_str()) <= 0)
+   {
+      return false;
+   }
+
+   if (m_subDatasets.size() == 0)
+   {
+      if(isOpen())
+      {
+         closeEntry();
+      }
+
+      if (m_subDatasets.size() == 0)
+      {
+         m_fid = Hopen(theImageFile.c_str(), DFACC_READ, 0);
+         if (m_fid <= 0)
+         {
+            closeEntry();
+            return false;  
+         }
+
+         m_sd_id = SDstart(theImageFile.c_str(), DFACC_READ );
+
+         if (m_sd_id == -1)
+         {
+            closeEntry();
+            return false;  
+         }
+
+         result = initGlobalMeta();      
+      }
+   }
+
+   if (m_currentEntryRender < m_subDatasets.size())
+   {
+      //close file before open file in sub-dataset
+      closeEntry();
+      ossimHdfSubdataset subData = m_subDatasets[m_currentEntryRender];
+      m_numberOfBands = subData.m_bands;
+      m_currentSubDataset = new ossimHdf4SubDataset();
+      m_currentSubDataset->setHdfSdsIndex(subData.m_sdsIndex);
+      m_currentSubDataset->setOutputScalarType(subData.m_dataType);
+      m_currentSubDataset->setNumberOfBands(subData.m_bands);
+      m_currentSubDataset->setNumberOfLines(subData.m_rows);
+      m_currentSubDataset->setNumberOfSamples(subData.m_cols);
+      m_currentSubDataset->setAttributeCount(subData.m_attributes);
+      m_currentSubDataset->setSdsRank(subData.m_rank);
+      m_currentSubDataset->setSdsName(subData.m_name);
+      m_currentSubDataset->setHdfDataType(m_hdfDataType);
+
+      m_currentSubDataset->setHdfFilename(theImageFile);
+
+      m_tile = ossimImageDataFactory::instance()->create(this, this);
+      m_tile->initialize();
+
+      // Call the base complete open to pick up overviews.
+      completeOpen();
+      result = true;
+   }
+   else
+   {
+      closeEntry();
+      result = false;
+   }
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " exit status = " << (result?"true":"false\n")
+         << std::endl;
+   }
+
+   return result;
+}
+
+bool ossimHdf4Reader::initGlobalMeta()
+{
+   int32	numAttributes;
+   int32 numValues;
+   int32 numDatasets;
+   int32 dataType;
+   char	attrName[100];
+
+   m_globalMeta.clear();
+   m_structMetadata = "";
+
+   //Obtain number of SDSs and global attributes in input file. 
+   if ( SDfileinfo(m_sd_id, &numDatasets, &numAttributes ) != 0 )
+   {
+      return false;
+   }
+
+   // Loop through the all attributes
+   for (ossim_int32 i = 0; i < numAttributes; i++ )
+   {
+      // Get information about the attribute. Note that the first
+      // parameter is an SD interface identifier.
+      SDattrinfo(m_sd_id, i, attrName, &dataType, &numValues);
+
+      if (i == 0)
+      {
+         char* attrVersion = (char*)malloc(numValues * sizeof (dataType));
+         attrVersion[numValues] = '\0';
+         SDreadattr(m_sd_id, i, attrVersion);
+         m_globalMeta.push_back(ossimString(ossimString(attrName).trim() 
+            + ": " + ossimString(attrVersion).trim()));
+         free(attrVersion);
+         continue;
+      }
+
+      if ( ossimString(attrName).downcase().contains("coremetadata.")     ||
+         ossimString(attrName).downcase().contains("archivemetadata.")    ||
+         ossimString(attrName).downcase().contains("productmetadata.")    ||
+         ossimString(attrName).downcase().contains("badpixelinformation") ||
+         ossimString(attrName).downcase().contains("product_summary")     ||
+         ossimString(attrName).downcase().contains("dem_specific")        ||
+         ossimString(attrName).downcase().contains("bts_specific")        ||
+         ossimString(attrName).downcase().contains("etse_specific")       ||
+         ossimString(attrName).downcase().contains("dst_specific")        ||
+         ossimString(attrName).downcase().contains( "acv_specific")       ||
+         ossimString(attrName).downcase().contains("act_specific")        ||
+         ossimString(attrName).downcase().contains("etst_specific")       ||
+         ossimString(attrName).downcase().contains("level_1_carryover"))
+      {
+         char* attrValues = (char*)malloc(numValues * sizeof (dataType));
+         attrValues[numValues] = '\0';
+         SDreadattr(m_sd_id, i, attrValues);
+         parseMetaString(ossimString(attrValues));
+         free(attrValues);
+      }
+      else if (ossimString(attrName).downcase().contains("structmetadata."))
+      {
+         m_isHdfEos = true;
+         char* attrStructureChar = (char*)malloc(numValues * sizeof (dataType));
+         attrStructureChar[numValues] = '\0';
+         SDreadattr(m_sd_id, i, attrStructureChar);
+         m_structMetadata = m_structMetadata + ossimString(attrStructureChar);
+         free(attrStructureChar);
+         continue;
+      }
+      else
+      {
+         if ( dataType == DFNT_CHAR8 || dataType == DFNT_UCHAR8 )
+         {
+            char* attrValue = (char*)malloc(numValues * sizeof (dataType));
+            attrValue[numValues] = '\0';
+            SDreadattr(m_sd_id, i, attrValue);
+            m_globalMeta.push_back(ossimString(attrName) + ": " + ossimString(attrValue));
+            free(attrValue);
+         }
+         else
+         {
+            ossim_int32 size = getSizeByType(dataType);
+            char* attrValue = new char[size * numValues];
+            SDreadattr(m_sd_id, i, (VOIDP)attrValue);
+            ossimString values = getAttribuitValues(dataType, numValues, attrValue);
+            m_globalMeta.push_back(ossimString(attrName) + ": " + values);
+            delete[] attrValue;
+         }   
+      }
+   }
+
+   initHdfDataType();
+   initSubdatasetNames();
+   initGroupInfos();
+
+   return initSubDatasets(numDatasets);
+}
+
+ossim_int32 ossimHdf4Reader::getSizeByType(int32 dataType) const
+{
+   if ( dataType == DFNT_CHAR8 || dataType == DFNT_UCHAR8 )
+   {
+      return 1;
+   }
+   else if (dataType == DFNT_INT8 || dataType == DFNT_UINT8)
+   {
+      return 1;
+   }
+   else if (dataType == DFNT_INT16 || dataType == DFNT_UINT16)
+   {
+      return 2;
+   }
+   else if (dataType == DFNT_INT32 || dataType == DFNT_UINT32 
+      || dataType == DFNT_FLOAT32)
+   {
+      return 4;
+   }
+   else if (dataType == DFNT_DOUBLE || dataType == DFNT_FLOAT64)
+   {
+      return 8;
+   }
+
+   return 4;
+}
+
+void ossimHdf4Reader::initSubdatasetNames()
+{
+   m_subDatasetNames.clear();
+   std::vector<ossimString> attrList = m_structMetadata.split("\n");
+   std::vector<ossimString> attrInfos;
+   ossimString groupIdentifier;
+   ossimString endGroupIdentifier;
+   ossimString groupName;
+
+   for (ossim_uint32 i  = 0; i < attrList.size(); i++)
+   {
+      ossimString attrInfo = attrList[i].trim();
+      if (attrInfo.contains("GROUP=SwathStructure") && m_subDatasetNames.size() == 0)//initialize the type and group name
+      {
+         m_hdfDataType = HDF4_EOS_SWATH;
+         groupIdentifier = "GROUP=SWATH_";
+         groupName = "SwathName";
+      }
+      else if (attrInfo.contains("GROUP=GridStructure") && m_subDatasetNames.size() == 0)//initialize the type and group name
+      {
+         m_hdfDataType = HDF4_EOS_GRID;
+         groupIdentifier = "GROUP=GRID_";
+         groupName = "GridName";
+      }
+      else //get sub dataset infos
+      {
+         if (attrInfo.contains(groupIdentifier) && attrInfo.contains("END_") == false)
+         {
+            endGroupIdentifier = "END_" + attrInfo;
+         }
+         if (attrInfo != endGroupIdentifier)
+         {
+            attrInfos.push_back(attrInfo);
+         } 
+         else
+         {
+            parseGroupName(attrInfos, groupName);
+            attrInfos.clear();
+         }
+      }
+   }
+}
+
+void ossimHdf4Reader::parseGroupName(std::vector<ossimString> groupInfo,
+                                     ossimString groupName)
+{
+   for (ossim_uint32 i = 0; i < groupInfo.size(); i++)
+   {
+      ossimString info = groupInfo[i];
+      if (info.contains(groupName))
+      {
+         groupName = info.split("=")[1].trim();
+         groupName = groupName.substitute("\"", "", true);
+      }
+      if (info.contains("GeoFieldName") || info.contains("DataFieldName"))
+      {
+         ossimString fieldName = info.split("=")[1].trim();
+         fieldName = fieldName.substitute("\"", "", true);
+         m_subDatasetNames.insert(ossimString(groupName + ":" + fieldName));
+      }
+   }
+}
+
+void ossimHdf4Reader::initGroupInfos()
+{
+   m_groupInfos.clear();
+
+   char vgName[1024];	/* Object name */
+   char vgClass[1024];	/* Object class */
+   int32 vgRef = -1;
+   int32 vgroupId;
+
+   Vstart(m_fid);
+   while (1)
+   {
+      // Get Vgroup reference number 
+      vgRef = Vgetid(m_fid, vgRef);
+
+      // If no more then exist search loop
+      if (vgRef == -1)
+      {
+         break;
+      }
+
+      // Get Vgroup ID, name, and class 
+      vgroupId = Vattach(m_fid, vgRef, "r");
+      Vgetname(vgroupId, vgName);
+      Vgetclass(vgroupId, vgClass);
+
+      //get "Fields" and "Attributes" info (SDS ids) from Vgroups
+      if (m_isHdfEos)
+      {
+         if (ossimString(vgClass).upcase() == m_hdfDataType)
+         {
+            int32 numObjects = Vntagrefs(vgroupId); //Get # of entries within this Vgroup and search for SDS
+
+            int32* tags = (int32 *) malloc(sizeof(int32) * numObjects);
+            int32* refs = (int32 *) malloc(sizeof(int32) * numObjects);
+
+            Vgettagrefs(vgroupId, tags, refs, numObjects); 
+
+            for (ossim_int32 i = 0; i < numObjects; i++) // Get tag and ref # for each Vgroup objects
+            {
+               int32 vgRefId = Vattach(m_fid, refs[i], "r");
+
+               int32 numRefObjects = Vntagrefs(vgRefId);
+               int32* tagsObj = (int32 *) malloc(sizeof(int32) * numRefObjects);
+               int32* refsObj = (int32 *) malloc(sizeof(int32) * numRefObjects);
+
+               Vgettagrefs(vgRefId, tagsObj, refsObj, numRefObjects);
+
+               for (ossim_int32 j = 0; j < numRefObjects; j++)
+               {
+                  if (tagsObj[j] == DFTAG_NDG)
+                  {
+                     int32 index = SDreftoindex(m_sd_id, refsObj[j]);
+                     int32 sdid = SDselect(m_sd_id, index);
+                     m_groupInfos[sdid] = ossimString(vgName);
+                  }
+               }
+               free(tagsObj);
+               free(refsObj);
+            }
+            free(tags);
+            free(refs);
+         }
+      }
+      // Detach Vgroup 
+      Vdetach(vgroupId);
+   }
+   Vend(m_fid);  
+}
+
+bool ossimHdf4Reader::initSubDatasets(int32 numDatasets)
+{
+   m_subDatasets.clear();
+   m_groupDatasets.clear();
+
+   int32 dim_sizes[H4_MAX_VAR_DIMS];
+   int32 rank, data_type, n_attrs;
+   char  name[H4_MAX_NC_NAME];
+   int32 bands, rows, cols;
+
+   std::vector<ossimHdfSubdataset> subDatasets;
+   for (ossim_int32 index = 0; index < numDatasets; index++)
+   {
+      int32 sds_id = SDselect (m_sd_id, index);
+      // int32 status = SDgetinfo (sds_id, name, &rank, dim_sizes, &data_type, &n_attrs);
+      SDgetinfo (sds_id, name, &rank, dim_sizes, &data_type, &n_attrs);
+
+      //get bands, rows, cols info
+      if (rank == 3)
+      {
+         bands = dim_sizes[0];
+         rows = dim_sizes[1];
+         cols = dim_sizes[2];
+      }
+      else if (rank == 2)
+      {
+         bands = 1;
+         rows = dim_sizes[0];
+         cols = dim_sizes[1];
+      }
+      else if (rank == 1)
+      {
+         bands = dim_sizes[0];
+         rows = 0;
+         cols = 0;
+      }
+      else
+      {
+         bands = 0;
+         rows = 0;
+         cols = 0;
+      }
+
+      if (m_isHdfEos)
+      {
+         std::map<int32, ossimString>::iterator it = m_groupInfos.find(sds_id);
+         if (it != m_groupInfos.end())
+         {
+            ossimString groupName = it->second;
+
+            ossimString subsetdataName = groupName + ":" + ossimString(name);
+
+            std::set<ossimString>::iterator subIt = m_subDatasetNames.find(subsetdataName);
+
+            if (subIt != m_subDatasetNames.end())
+            {
+               subDatasets.push_back(ossimHdfSubdataset(index, 
+                  subsetdataName, 
+                  data_type, 
+                  rank, 
+                  bands, 
+                  rows, 
+                  cols,
+                  n_attrs));
+            }
+         }
+      }
+      else
+      {
+         if (m_hdfDataType == HDF4_HYPERION_L1)
+         {
+            if (rank == 3)
+            {
+               bands = dim_sizes[1];
+               rows = dim_sizes[0];
+               cols = dim_sizes[2];
+            }
+         }
+         subDatasets.push_back(ossimHdfSubdataset(index, 
+            ossimString(name), 
+            data_type, 
+            rank, 
+            bands, 
+            rows, 
+            cols,
+            n_attrs));
+      }
+
+      SDendaccess(sds_id);
+   }
+
+   if (subDatasets.size() > 0)
+   {
+      if (m_isHdfEos)
+      {
+         ossimString subName = subDatasets[0].m_name;
+         ossimString groupName = subName.split(":")[0];
+         ossim_uint32 index;
+         std::vector<ossimHdfSubdataset> geoSubDatasets;
+         std::vector<ossimHdfSubdataset> dataSubDatasets;
+         for (index = 0; index < subDatasets.size(); index++)
+         {
+            ossimString subNameTmp = subDatasets[index].m_name;
+            ossimString groupNameTmp = subNameTmp.split(":")[0];
+            ossimString fieldName = subNameTmp.split(":")[1];
+            if (groupNameTmp == groupName)
+            {
+               if (fieldName == "Longitude" || fieldName == "Latitude")
+               {
+                  geoSubDatasets.push_back(subDatasets[index]);
+               }
+               else
+               {
+                  dataSubDatasets.push_back(subDatasets[index]);
+               }
+            }
+            else
+            {
+               m_groupDatasets.push_back(ossimHdfGroupData(groupName,
+                  geoSubDatasets,
+                  dataSubDatasets));
+
+               groupName = groupNameTmp;
+               geoSubDatasets.clear();
+               dataSubDatasets.clear();
+
+               //insert first dataset for a different group
+               if (fieldName == "Longitude" || fieldName == "Latitude")
+               {
+                  geoSubDatasets.push_back(subDatasets[index]);
+               }
+               else
+               {
+                  dataSubDatasets.push_back(subDatasets[index]);
+               }
+            }
+         }
+
+         //insert last datasets to the group 
+         if (index == subDatasets.size())
+         {
+            m_groupDatasets.push_back(ossimHdfGroupData(groupName,
+               geoSubDatasets,
+               dataSubDatasets));
+         }
+      }
+      else
+      {
+         m_subDatasets = subDatasets;
+      }
+   }
+
+   //only insert data field data to the vector of sub datasets, not geo field data
+   for (ossim_uint32 index = 0; index < m_groupDatasets.size(); index++)
+   {
+      std::vector<ossimHdfSubdataset> dataSubdatasets = m_groupDatasets[index].m_dataSubdatasets;
+      for (ossim_uint32 dataIndex = 0; dataIndex < dataSubdatasets.size(); dataIndex++)
+      {
+         m_subDatasets.push_back(dataSubdatasets[dataIndex]);
+      }
+   }
+
+   if (m_subDatasets.size() > 0)
+   {
+      return true;
+   }
+   return false;
+}
+
+ossimString ossimHdf4Reader::getAttribuitValues(int32 dataType, 
+                                                int32 numValues,
+                                                void* attrValue) const
+{
+   ossimString values;
+
+   if (dataType == DFNT_INT8)
+   {
+      int8* int8Data = (int8*)attrValue;
+      for (ossim_int32 j = 0; j < numValues; j++)
+      {
+         ossimString valueStr = ossimString::toString(int8Data[j]);
+         values = values + ossimString(valueStr + " ");
+      }
+   }
+   else if (dataType == DFNT_UINT8)
+   {
+      uint8* uint8Data = (uint8*)attrValue;
+      for (ossim_int32 j = 0; j < numValues; j++)
+      {
+         ossimString valueStr = ossimString::toString(uint8Data[j]);
+         values = values + ossimString(valueStr + " ");
+      }
+   }
+   else if (dataType == DFNT_INT16)
+   {
+      int16* int16Data = (int16*)attrValue;
+      for (ossim_int32 j = 0; j < numValues; j++)
+      {
+         ossimString valueStr = ossimString::toString(int16Data[j]);
+         values = values + ossimString(valueStr + " ");
+      }
+   }
+   else if (dataType == DFNT_UINT16)
+   {
+      uint16* uint16Data = (uint16*)attrValue;
+      for (ossim_int32 j = 0; j < numValues; j++)
+      {
+         ossimString valueStr = ossimString::toString(uint16Data[j]);
+         values = values + ossimString(valueStr + " ");
+      }
+   }
+   else if (dataType == DFNT_INT32 || dataType == DFNT_UINT32)
+   {
+      ossim_int32* int32Data = (ossim_int32*)attrValue;
+      for (ossim_int32 j = 0; j < numValues; j++)
+      {
+         ossimString valueStr = ossimString::toString(int32Data[j]);
+         values = values + ossimString(valueStr + " ");
+      }
+   }
+   else if (dataType == DFNT_FLOAT64 || dataType == DFNT_DOUBLE)
+   {
+      double* doubleData = (double*)attrValue;
+      for (ossim_int32 j = 0; j < numValues; j++)
+      {
+         ossimString valueStr = ossimString::toString(doubleData[j]);
+         values = values + ossimString(valueStr + " ");
+      }
+   }
+   else
+   {
+      float32* floatData = (float32*)attrValue;
+      for (ossim_int32 j = 0; j < numValues; j++)
+      {
+         ossimString valueStr = ossimString::toString(floatData[j]);
+         values = values + ossimString(valueStr + " ");
+      }
+   }
+   return values;
+}
+
+void ossimHdf4Reader::parseMetaString(ossimString attrStr)
+{
+   std::vector<ossimString> attrList = attrStr.split("\n");
+   ossimString className = "";
+   for (ossim_uint32 i  = 0; i < attrList.size(); i++)
+   {
+      ossimString attrValue = attrList[i];
+
+      if (attrValue.contains("OBJECT") && attrValue.contains("=") && !attrValue.contains("END_OBJECT"))
+      {
+         if (attrValue.split("=").size() > 1)
+         {
+            if (attrValue.split("=")[1].trim() != "PARAMETERVALUE") //will use the value of this class
+            {
+               className = attrValue.split("=")[1].trim();
+            }
+         }
+      }
+      else if (attrValue.contains("VALUE") && attrValue.contains("="))
+      {
+         if (attrValue.split("=").size() > 1)
+         {
+            ossimString classValue = attrValue.split("=")[1].trim();
+            classValue = classValue.substitute("\"", "", true);
+            classValue = classValue.substitute("(", "", true);
+            classValue = classValue.substitute(")", "", true);
+            if (className == "ADDITIONALATTRIBUTENAME") //skip this class name to get the value for this class
+            {
+               className = classValue;
+               continue;
+            }
+            if (classValue != "PARAMETERVALUE")
+            {
+               m_globalMeta.push_back(ossimString(className +  ": " + classValue));
+            }
+         }
+      }
+   }
+}
+
+void ossimHdf4Reader::initHdfDataType()
+{
+   for (ossim_uint32 i = 0; i < m_globalMeta.size(); i++)
+   {
+      ossimString meta = m_globalMeta[i];
+      ossimString metaName = meta.split(":")[0];
+      ossimString metaValue = meta.split(":")[1];
+      if (metaName == "Title")
+      {
+         if (metaValue == "SeaWiFS Level-1A Data")
+         {
+            m_hdfDataType = HDF4_SEAWIFS_L1A;
+         }
+         else if (metaValue == "SeaWiFS Level-2 Data")
+         {
+            m_hdfDataType = HDF4_SEAWIFS_L2;
+         }
+         else if (metaValue == "SeaWiFS Level-3 Standard Mapped Image")
+         {
+            m_hdfDataType = HDF4_SEAWIFS_L3;
+         }
+      }
+      else if (metaName == "L1 File Generated By")
+      {
+         if (metaValue.contains("HYP version "))
+         {
+            m_hdfDataType = HDF4_HYPERION_L1;
+         }
+      }
+      else if (metaName == "HDFEOSVersion")
+      {
+         m_isHdfEos = true;
+      }
+      else
+      {
+         m_hdfDataType = "UNKNOWN";
+      }
+   }
+}
+
+bool ossimHdf4Reader::isOpen()const
+{
+   return m_currentSubDataset != NULL;
+}
+
+void ossimHdf4Reader::closeEntry()
+{
+   m_tile = 0;
+   SDendaccess(m_sd_id);
+   SDend(m_sd_id); 
+   Hclose(m_fid);
+
+   if (m_currentSubDataset != NULL)
+   {
+      delete m_currentSubDataset;
+      m_currentSubDataset = 0;
+   }
+   ossimImageHandler::close();
+}
+
+ossimRefPtr<ossimImageData> ossimHdf4Reader::getTile(const ossimIrect& tile_rect, 
+                                                     ossim_uint32 resLevel)
+{
+   if (m_tile.valid())
+   {
+      // Image rectangle must be set prior to calling getTile.
+      m_tile->setImageRectangle(tile_rect);
+
+      if ( getTile( m_tile.get(), resLevel ) == false )
+      {
+         if (m_tile->getDataObjectStatus() != OSSIM_NULL)
+         {
+            m_tile->makeBlank();
+         }
+      }
+   }
+
+   return m_tile;
+}
+
+bool ossimHdf4Reader::getTile(ossimImageData* result,
+                              ossim_uint32 resLevel)
+{
+   bool status = false;
+
+   //---
+   // Not open, this tile source bypassed, or invalid res level,
+   // return a blank tile.
+   //---
+   if( isOpen() && isSourceEnabled() && isValidRLevel(resLevel) &&
+      result && (result->getNumberOfBands() == getNumberOfOutputBands()) )
+   {
+      result->ref();  // Increment ref count.
+
+      //---
+      // Check for overview tile.  Some overviews can contain r0 so always
+      // call even if resLevel is 0.  Method returns true on success, false
+      // on error.
+      //---
+      status = getOverviewTile(resLevel, result);
+
+      if (!status) // Did not get an overview tile.
+      {
+         status = true;
+
+         ossimIrect tile_rect = result->getImageRectangle();     
+
+         if (getImageRectangle().intersects(tile_rect))
+         {
+            // Make a clip rect.
+            ossimIrect clipRect = tile_rect.clipToRect(getImageRectangle());
+
+            if (tile_rect.completely_within(clipRect) == false)
+            {
+               // Not filling whole tile so blank it out first.
+               result->makeBlank();
+            }
+
+            if (m_currentSubDataset != NULL)
+            {
+               for (ossim_uint32 band = 0; band < getNumberOfInputBands(); band++)
+               {
+                  void* dataBuffer = m_currentSubDataset->getTileBuf(clipRect, band);
+                  result->loadBand(dataBuffer, clipRect, band);
+                  delete[] (char*)dataBuffer;
+               }
+            }
+         }
+         else // No intersection...
+         {
+            result->makeBlank();
+         }
+      }
+      result->validate();
+      result->unref();  // Decrement ref count.
+   }
+
+   return status;
+}
+
+ossim_uint32 ossimHdf4Reader::getNumberOfInputBands() const
+{
+   if (m_currentSubDataset != NULL)
+   {
+      return m_currentSubDataset->getNumberOfInputBands();
+   }
+   return m_numberOfBands;
+}
+
+ossim_uint32 ossimHdf4Reader::getNumberOfOutputBands()const
+{
+   return getNumberOfInputBands();
+}
+
+ossim_uint32 ossimHdf4Reader::getImageTileWidth() const
+{
+   return m_imageRect.width();
+}
+
+ossim_uint32 ossimHdf4Reader::getImageTileHeight() const
+{
+   return m_imageRect.height();
+}
+
+ossimScalarType ossimHdf4Reader::getOutputScalarType() const
+{
+   if (m_currentSubDataset != NULL)
+   {
+      return m_currentSubDataset->getOutputScalarType();
+   }
+   return m_scalarType;
+}
+
+ossimRefPtr<ossimImageGeometry> ossimHdf4Reader::getImageGeometry()
+{
+   if ( !theGeometry )
+   {
+      //---
+      // Check for external geom:
+      //---
+      theGeometry = getExternalImageGeometry();
+
+      if ( !theGeometry )
+      {
+         //---
+         // Check the internal geometry first to avoid a factory call.
+         //---
+         theGeometry = getInternalImageGeometry();
+
+         // At this point it is assured theGeometry is set.
+
+         // Check for set projection.
+         if ( !theGeometry->getProjection() )
+         {
+            // Try factories for projection.
+            ossimImageGeometryRegistry::instance()->extendGeometry(this);
+         }
+      }
+
+      // Set image things the geometry object should know about.
+      initImageParameters( theGeometry.get() );
+   }
+
+   return theGeometry;
+}
+
+ossimRefPtr<ossimImageGeometry> ossimHdf4Reader::getInternalImageGeometry() const
+{
+   static const char MODULE[] = "ossimHdf4Reader::getInternalImageGeometry";
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " entered...\n";
+   }
+
+   ossimRefPtr<ossimImageGeometry> geom = new ossimImageGeometry();
+
+   // Set the projection and return this handler's image geometry:
+   if (m_hdfDataType == HDF4_EOS_SWATH)
+   {
+      geom->setProjection(processSwathProjection().get());
+   }
+   else if (m_hdfDataType == HDF4_EOS_GRID)
+   {
+      geom->setProjection(processGridProjection().get());
+   }
+   else if (m_hdfDataType == HDF4_SEAWIFS_L3)
+   {
+      if (m_currentEntryRender < m_subDatasets.size())
+      {
+         ossim_float64 ulx = getMetaValue("Westernmost Longitude").toDouble();
+         ossim_float64 uly = getMetaValue("Northernmost Latitude").toDouble();
+         ossim_float64 lrx = getMetaValue("Easternmost Longitude").toDouble();
+         ossim_float64 lry = getMetaValue("Southernmost Latitude").toDouble();
+
+         int32 rows = m_subDatasets[m_currentEntryRender].m_rows;
+         int32 cols = m_subDatasets[m_currentEntryRender].m_cols;
+
+         ossim_float64 xRes = (lrx - ulx)/cols;
+         ossim_float64 yRes = (uly - lry)/rows;
+         ossimDpt gsd(fabs(xRes), fabs(yRes));
+
+         ossimGpt gTie(uly, ulx);
+         ossimString name = "EPSG:4326";
+         ossimRefPtr<ossimProjection> proj = ossimEpsgProjectionFactory::instance()->createProjection(name);
+         ossimMapProjection* mapProj = dynamic_cast<ossimMapProjection*>(proj.get());
+         mapProj->setUlTiePoints(gTie);
+         mapProj->setDecimalDegreesPerPixel(gsd);
+
+         geom->setProjection(mapProj);
+      }
+   }
+
+   return geom;
+}
+
+ossimRefPtr<ossimProjection> ossimHdf4Reader::processGridProjection() const
+{
+   if (m_structMetadata.empty())
+      return 0;
+
+   int32   zoneCode = 0;
+   int32   sphereCode = 0;
+   int32   xSize, ySize;
+   std::vector<ossim_float64> upLeftValues;
+   std::vector<ossim_float64> lowRightValues;
+   std::vector<ossim_float64> projParms;
+   ossimString projName;
+
+   std::vector<ossimString> attrList = m_structMetadata.split("\n");
+   for (ossim_uint32 i = 0; i < attrList.size(); i++)
+   {
+      ossimString attrInfo = attrList[i].trim();
+      attrInfo = attrInfo.substitute("\"", "", true);
+      attrInfo = attrInfo.substitute("(", "", true);
+      attrInfo = attrInfo.substitute(")", "", true);
+      if (attrInfo.contains("="))
+      {
+         ossimString metaName = attrInfo.split("=")[0].trim();
+         ossimString metaValue = attrInfo.split("=")[1].trim();
+         if (metaName == "XDim")
+         {
+            xSize = metaValue.toInt();
+         }
+         if (metaName == "YDim")
+         {
+            ySize = metaValue.toInt32();
+         }
+         if (metaName == "Projection")
+         {
+            projName = metaValue;
+         }
+         if (metaName == "ZoneCode")
+         {
+            zoneCode = metaValue.toInt32();
+         }
+         if (metaName == "ProjParams")
+         {
+            for (ossim_uint32 paramIndex = 0; paramIndex < metaValue.split(",").size(); paramIndex++)
+            {
+               projParms.push_back(metaValue.split(",")[paramIndex].toDouble());
+            }
+         }
+         if (metaName == "UpperLeftPointMtrs")
+         {
+            for (ossim_uint32 ulIndex = 0; ulIndex < metaValue.split(",").size(); ulIndex++)
+            {
+               upLeftValues.push_back(metaValue.split(",")[ulIndex].toDouble());
+            }
+         }
+         if (metaName == "LowerRightMtrs")
+         {
+            for (ossim_uint32 lrIndex = 0; lrIndex < metaValue.split(",").size(); lrIndex++)
+            {
+               lowRightValues.push_back(metaValue.split(",")[lrIndex].toDouble());
+            }
+         }
+         if (metaName == "SphereCode")
+         {
+            sphereCode = metaValue.toInt32();
+         } 
+      }
+   }
+
+   //calculate w-e pixel resolution and n-s pixel resolution 
+   ossim_float64 xRes = 0.0;
+   ossim_float64 yRes = 0.0;
+   if (lowRightValues.size() == 2 && upLeftValues.size() == 2 && ySize > 0 && xSize > 0)
+   {
+      xRes = (lowRightValues[0] - upLeftValues[0]) / xSize;
+      yRes = (lowRightValues[1] - upLeftValues[1]) / ySize;
+   }
+   ossimDpt gsd(fabs(xRes), fabs(yRes));
+
+   //create the map projection
+   ossimRefPtr<ossimMapProjection> mapProj = 0;
+   if (projName == "GCTP_GEO") //Geographic
+   {
+      // Tie point is expressed as lat lon:
+      ossimGpt gTie(upLeftValues[1], upLeftValues[0]);
+      ossimString epsg("EPSG:4326");
+      mapProj = PTR_CAST(ossimMapProjection, 
+         ossimEpsgProjectionFactory::instance()->createProjection(epsg));
+      mapProj->setUlTiePoints(gTie);
+      mapProj->setDecimalDegreesPerPixel(gsd);
+   }
+   else 
+   {
+      // Map projection, tie point expressed as easting northing:
+      ossimDpt tie(upLeftValues[0], upLeftValues[1]);
+
+      if (projName == "GCTP_UTM")
+         mapProj = new ossimUtmProjection(zoneCode);
+      else if (projName == "GCTP_LAMCC") 
+         mapProj = new ossimLambertConformalConicProjection();
+      else if (projName == "GCTP_PS") 
+         mapProj = new ossimPolarStereoProjection();
+      else if (projName == "GCTP_POLYC") 
+         mapProj = new ossimPolyconicProjection();
+      else if (projName == "GCTP_TM") 
+         mapProj = new ossimMercatorProjection();
+      else if (projName == "GCTP_LAMAZ") 
+         mapProj = new ossimAzimEquDistProjection();
+      else if (projName == "GCTP_HOM") 
+         mapProj = new ossimObliqueMercatorProjection();
+      else if (projName == "GCTP_SOM") 
+         mapProj = new ossimSpaceObliqueMercatorProjection();
+      else if (projName == "GCTP_ISINUS" || projName == "GCTP_SNSOID") 
+         mapProj = new ossimSinusoidalProjection();
+
+      mapProj->setUlTiePoints(tie);
+      mapProj->setMetersPerPixel(gsd);
+   }
+
+   ossimRefPtr<ossimProjection> return_pointer (mapProj.get());
+   return return_pointer;
+}
+
+ossimRefPtr<ossimProjection> ossimHdf4Reader::processSwathProjection() const
+{
+   if (m_currentEntryRender < m_subDatasets.size())
+   {
+      ossim_int32 latGridIndex = -1;
+      ossim_int32 lonGridIndex = -1;
+      ossim_int32 spacingX = -1;
+      ossim_int32 spacingY = -1;
+      ossim_int32 latticePointIndex = -1;
+
+      ossim_int32 latGridRows = 0;
+      ossim_int32 latGridCols = 0;
+      ossim_int32 lonGridRows = 0;
+      ossim_int32 lonGridCols = 0;
+      bool hasGeoData = false;
+    
+      std::vector<float64> latticeYPoints;
+      std::vector<float64> latticeXPoints;
+
+      ossimString subDatasetName = m_subDatasets[m_currentEntryRender].m_name;
+      ossimString groupName = subDatasetName.split(":")[0];
+
+      for (ossim_uint32 i = 0; i < m_groupDatasets.size(); i++)
+      {
+         if (groupName == m_groupDatasets[i].m_groupName)
+         {
+            //get lat and lon info
+            if (m_groupDatasets[i].m_geoSubdatasets.size() > 0)
+            {
+               for (ossim_uint32 j = 0; j < m_groupDatasets[i].m_geoSubdatasets.size(); j++)
+               {
+                  if (m_groupDatasets[i].m_geoSubdatasets[j].m_name.contains("Longitude"))
+                  {
+                     lonGridIndex = m_groupDatasets[i].m_geoSubdatasets[j].m_sdsIndex;
+                     lonGridCols = m_groupDatasets[i].m_geoSubdatasets[j].m_cols;
+                     lonGridRows = m_groupDatasets[i].m_geoSubdatasets[j].m_rows;
+                     hasGeoData = true;
+                  }
+                  if (m_groupDatasets[i].m_geoSubdatasets[j].m_name.contains("Latitude"))
+                  {
+                     latGridIndex = m_groupDatasets[i].m_geoSubdatasets[j].m_sdsIndex;
+                     latGridCols = m_groupDatasets[i].m_geoSubdatasets[j].m_cols;
+                     latGridRows = m_groupDatasets[i].m_geoSubdatasets[j].m_rows;
+                     hasGeoData = true;
+                  }
+               }
+            }
+
+            //get lattice point info
+            if (m_groupDatasets[i].m_dataSubdatasets.size() > 0)
+            {
+               for (ossim_uint32 j = 0; j < m_groupDatasets[i].m_dataSubdatasets.size(); j++)
+               {
+                  if (m_groupDatasets[i].m_dataSubdatasets[j].m_name.contains("LatticePoint"))
+                  {
+                     latticePointIndex = m_groupDatasets[i].m_dataSubdatasets[j].m_sdsIndex;
+                  }
+               }
+            }
+         }
+      }
+
+      if (hasGeoData)
+      {
+         if (latticePointIndex < 0)
+         {
+            ossim_uint32 rows = m_subDatasets[m_currentEntryRender].m_rows;
+            ossim_uint32 cols = m_subDatasets[m_currentEntryRender].m_cols;
+            if (rows % latGridRows == 0 && cols % lonGridCols == 0)
+            {
+               spacingY = rows/latGridRows; //line increment step
+               spacingX = cols/lonGridCols; //pixel increment step
+            }
+            else if (rows % (latGridRows-1) == 0 && cols % (lonGridCols-1) == 0)//ASTER L1A and L1B
+            {
+               spacingY = rows/(latGridRows-1); //line increment step
+               spacingX = cols/(lonGridCols-1); //pixel increment step
+            }
+            else if (rows % latGridRows == 0 && cols % (lonGridCols-1) == 0)
+            {
+               spacingY = rows/latGridRows; //line increment step
+               spacingX = cols/(lonGridCols-1); //pixel increment step
+            }
+            else if (rows % (latGridRows-1) == 0 && cols % lonGridCols == 0)
+            {
+               spacingY = rows/(latGridRows-1); //line increment step
+               spacingX = cols/lonGridCols; //pixel increment step
+            }
+            else if ((rows+1) % latGridRows == 0 && (cols+1) % lonGridCols == 0)
+            {
+               spacingY = (rows+1)/latGridRows; //line increment step
+               spacingX = (cols+1)/lonGridCols; //pixel increment step
+            }
+            else if ((rows+1) % latGridRows == 0 && cols % lonGridCols == 0)
+            {
+               spacingY = (rows+1)/latGridRows; //line increment step
+               spacingX = cols/lonGridCols; //pixel increment step
+            }
+            else if (rows % latGridRows == 0 && (cols+1) % lonGridCols == 0)
+            {
+               spacingY = rows/latGridRows; //line increment step
+               spacingX = (cols+1)/lonGridCols; //pixel increment step
+            }
+            ossimIpt spacing(spacingX, spacingY);
+            ossimDrect rect(0, 0, cols-1, rows-1);
+            return new ossimHdfGridModel(theImageFile, rect, 
+                                         ossimString::toString(latGridIndex),
+                                         ossimString::toString(lonGridIndex), spacing);
+         }  
+         else
+         {
+            int32 dim_sizes[H4_MAX_VAR_DIMS];
+            int32 rank, data_type, n_attrs;
+            char  name[H4_MAX_NC_NAME];
+            int32 start[H4_MAX_NC_DIMS], edges[H4_MAX_NC_DIMS];
+
+            std::vector<float64> lat;
+            std::vector<float64> lon;
+            int32 sd_id = SDstart(theImageFile.c_str(), DFACC_READ);
+            int32 sds_id = SDselect(sd_id, latGridIndex);
+            int32 status = SDgetinfo(sds_id, name, &rank, dim_sizes, &data_type, &n_attrs);
+
+            if (status != -1)
+            {
+               start[0] = 0;
+               start[1] = 0;
+               edges[0] = dim_sizes[0];
+               edges[1] = dim_sizes[1];
+
+               ossim_int32 size = getSizeByType(data_type);
+               char* values = new char[size * dim_sizes[0]* dim_sizes[1]];
+
+               // intn statusN = SDreaddata(sds_id, start, NULL, edges, (VOIDP)values);
+               SDreaddata(sds_id, start, NULL, edges, (VOIDP)values);
+
+               if (data_type == DFNT_FLOAT64 || data_type == DFNT_DOUBLE)
+               {
+                  float64* doubleData = (float64*)values;
+                  for (int i = 0; i < dim_sizes[0]* dim_sizes[1]; i++)
+                  {
+                     lat.push_back(doubleData[i]);
+                  }
+               }
+               else
+               {
+                  float32* floatData = (float32*)values;
+                  for (int i = 0; i < dim_sizes[0]* dim_sizes[1]; i++)
+                  {
+                     lat.push_back(floatData[i]);
+                  }
+               }
+               delete[] values;
+            }
+            SDendaccess(sds_id); 
+
+            sds_id = SDselect(sd_id, lonGridIndex);
+            status = SDgetinfo(sds_id, name, &rank, dim_sizes, &data_type, &n_attrs);
+
+            if (status != -1)
+            {
+               start[0] = 0;
+               start[1] = 0;
+               edges[0] = dim_sizes[0];
+               edges[1] = dim_sizes[1];
+
+               ossim_int32 size = getSizeByType(data_type);
+               char* values = new char[size * dim_sizes[0]* dim_sizes[1]];
+
+               // intn statusN = SDreaddata(sds_id, start, NULL, edges, (VOIDP)values);
+               SDreaddata(sds_id, start, NULL, edges, (VOIDP)values);
+
+               if (data_type == DFNT_FLOAT64 || data_type == DFNT_DOUBLE)
+               {
+                  float64* doubleData = (float64*)values;
+                  for (int i = 0; i < dim_sizes[0]* dim_sizes[1]; i++)
+                  {
+                     lon.push_back(doubleData[i]);
+                  }
+               }
+               else
+               {
+                  float32* floatData = (float32*)values;
+                  for (int i = 0; i < dim_sizes[0]* dim_sizes[1]; i++)
+                  {
+                     lon.push_back(floatData[i]);
+                  }
+               }
+               delete[] values;
+               SDendaccess(sds_id); 
+
+
+               sds_id = SDselect(sd_id, latticePointIndex);
+               status = SDgetinfo(sds_id, name, &rank, dim_sizes, &data_type, &n_attrs);
+               if (rank == 3)
+               {
+                  int32 loopIndex = dim_sizes[0];
+                  int32 latticeY = dim_sizes[1];
+                  int32 latticeX = dim_sizes[2];
+                  for (int32 latticeIndex = 0; latticeIndex < loopIndex; latticeIndex++)
+                  {
+                     start[0] = latticeIndex;
+                     start[1] = 0;
+                     start[2] = 0;
+                     edges[0] = 1;
+                     edges[1] = latticeY; 
+                     edges[2] = latticeX; 
+
+                     ossim_int32 size = getSizeByType(data_type);
+                     char* values = new char[size * latticeY*latticeX];
+
+                     // intn statusLattice = SDreaddata(sds_id, start, NULL, edges, (VOIDP)values);
+                     SDreaddata(sds_id, start, NULL, edges, (VOIDP)values);
+
+                     if (data_type == DFNT_INT32)
+                     {
+                        int32* intData = (int32*)values;
+                        for (int i = 0; i < latticeY*latticeX; i+=2)
+                        {
+                           latticeXPoints.push_back(intData[i]);
+                           latticeYPoints.push_back(intData[i+1]);
+                        }
+                     }
+                     else
+                     {
+                        float32* floatData = (float32*)values;
+                        for (int i = 0; i < latticeY* latticeX; i+=2)
+                        {
+                           latticeXPoints.push_back(floatData[i]);
+                           latticeYPoints.push_back(floatData[i+1]);
+                        }
+                     }
+                     delete[] values;
+                  }
+               }
+               SDendaccess(sds_id);
+               SDend (sd_id); 
+            }
+
+            ossimTieGptSet tieSet;
+            int iStepX = MAX(1,((dim_sizes[1]-1) / 11));
+            int iStepY = MAX(1,((dim_sizes[0]-1) / 11));
+
+            for (int y = 0; y < dim_sizes[0]; y += iStepY)
+            {
+               for (int x = 0; x < dim_sizes[1]; x += iStepX)
+               {
+                  int index = x + (y * dim_sizes[1]);
+                  if (index%10 == 0)
+                  {
+                     double dPixel = latticeXPoints[index] + 0.5;
+                     double dLine = latticeYPoints[index] + 0.5;
+
+                     ossimDpt dpt(dPixel, dLine);
+                     ossimGpt gpt(lat[index], lon[index]);
+                     tieSet.addTiePoint(new ossimTieGpt(gpt, dpt, .5));
+                  }
+               }
+            }
+
+            ossimRefPtr<ossimBilinearProjection> bilinProj = new ossimBilinearProjection;
+            bilinProj->optimizeFit(tieSet);
+            return bilinProj.get();
+         }
+      }
+   }
+
+   return ossimRefPtr<ossimProjection>();
+}
+
+bool ossimHdf4Reader::loadState(const ossimKeywordlist& kwl,
+                                const char* prefix)
+{
+   bool result = false;
+
+   if ( ossimImageHandler::loadState(kwl, prefix) )
+   {
+      result = open();
+   }
+
+   return result;
+}
+
+ossim_uint32 ossimHdf4Reader::getNumberOfEntries()const
+{
+   return (ossim_uint32) m_subDatasets.size();
+}
+
+bool ossimHdf4Reader::setCurrentEntry(ossim_uint32 entryIdx)
+{
+   if (m_currentEntryRender == entryIdx)
+   {
+      return true; // Nothing to do...
+   }
+   m_currentEntryRender = entryIdx;
+   theGeometry = 0;
+   theOverview = 0;
+   theOverviewFile.clear();
+   m_tile = 0;
+   return open();
+}
+
+std::vector<ossimString> ossimHdf4Reader::getSubDatasetMeta()
+{
+   if (m_currentSubDataset != NULL)
+   {
+      return m_currentSubDataset->getMetadata();
+   }
+   return std::vector<ossimString>();
+}
+
+void ossimHdf4Reader::getEntryList(std::vector<ossim_uint32>& entryList)const
+{
+   for (ossim_uint32 i = 0; i < m_subDatasets.size(); i++)
+   {
+      entryList.push_back(i);
+   }
+}
+
+ossimString ossimHdf4Reader::getMetaValue(const ossimString& key) const
+{
+   for (ossim_uint32 i = 0; i < m_globalMeta.size(); i++)
+   {
+      ossimString info = m_globalMeta[i];
+      ossimString keyTmp = info.split(":")[0].trim();
+      ossimString value = info.split(":")[1].trim();
+      if (keyTmp == key)
+      {
+         return value;
+      }
+   }
+   return "";
+}
+
+ossim_uint32 ossimHdf4Reader::getCurrentEntry()const
+{
+   return m_currentEntryRender;
+}
+
+
diff --git a/ossim_plugins/hdf/ossimHdf4Reader.h b/ossim_plugins/hdf/ossimHdf4Reader.h
new file mode 100644
index 0000000..70be514
--- /dev/null
+++ b/ossim_plugins/hdf/ossimHdf4Reader.h
@@ -0,0 +1,305 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Description:  Class declaration HDF4 reader.
+//
+// Specification: ISO/IEC 15444
+//
+//----------------------------------------------------------------------------
+// $Id: ossimHdf4Reader.h 2645 2011-05-26 15:21:34Z oscar.kramer $
+
+#ifndef ossimHdf4Reader_HEADER
+#define ossimHdf4Reader_HEADER 1
+
+#include "../ossimPluginConstants.h"
+#include <ossim/base/ossimIpt.h>
+#include <ossim/base/ossimIrect.h>
+#include <ossim/imaging/ossimImageHandler.h>
+#include <ossim/imaging/ossimAppFixedTileCache.h>
+
+//HDF4 Includes
+// #include <hdf/hdf.h>
+// #include <hdf/mfhdf.h>
+#include <hdf.h>
+#include <mfhdf.h>
+
+#include <iosfwd>
+#include <fstream>
+#include <vector>
+#include <set>
+
+// Forward class declarations.
+class ossimImageData;
+class ossimDpt;
+class ossimHdf4SubDataset;
+class ossimBilinearProjection;
+
+class OSSIM_PLUGINS_DLL ossimHdf4Reader : public ossimImageHandler
+{
+public:
+
+   /** default construtor */
+   ossimHdf4Reader();
+   
+   /** virtural destructor */
+   virtual ~ossimHdf4Reader();
+
+   /**
+    * @brief Returns short name.
+    * @return "ossim_hdf4_reader"
+    */
+   virtual ossimString getShortName() const;
+   
+   /**
+    * @brief Returns long  name.
+    * @return "ossim hdf4 reader"
+    */
+   virtual ossimString getLongName()  const;
+
+   /**
+    * @brief Returns class name.
+    * @return "ossimHdf4Reader"
+    */
+   virtual ossimString getClassName() const;
+
+   /**
+    *  @brief Method to grab a tile(rectangle) from image.
+    *
+    *  @param rect The zero based rectangle to grab.
+    *
+    *  @param resLevel The reduced resolution level to grab from.
+    *
+    *  @return The ref pointer with the image data pointer.
+    */
+   virtual ossimRefPtr<ossimImageData> getTile(const  ossimIrect& rect,
+                                               ossim_uint32 resLevel=0);
+
+   virtual bool getTile(ossimImageData* result, ossim_uint32 resLevel=0);   
+
+   /**
+    *  Returns the number of bands in the image.
+    *  Satisfies pure virtual from ImageHandler class.
+    */
+   virtual ossim_uint32 getNumberOfInputBands() const;
+
+   /**
+    * Returns the number of bands in a tile returned from this TileSource.
+    * Note: we are supporting sources that can have multiple data objects.
+    * If you want to know the scalar type of an object you can pass in the
+    */
+   virtual ossim_uint32 getNumberOfOutputBands()const; 
+   /**
+    * Returns the tile width of the image or 0 if the image is not tiled.
+    * Note: this is not the same as the ossimImageSource::getTileWidth which
+    * returns the output tile width which can be different than the internal
+    * image tile width on disk.
+    */
+   virtual ossim_uint32 getImageTileWidth() const;
+
+   /**
+    * Returns the tile width of the image or 0 if the image is not tiled.
+    * Note: this is not the same as the ossimImageSource::getTileHeight which
+    * returns the output tile height which can be different than the internal
+    * image tile height on disk.
+    */
+   virtual ossim_uint32 getImageTileHeight() const;
+
+   /**
+    * Returns the output pixel type of the tile source.
+    */
+   virtual ossimScalarType getOutputScalarType() const;
+   
+
+   /**
+    * @brief Gets number of lines for res level.
+    *
+    *  @param resLevel Reduced resolution level to return lines of.
+    *  Default = 0
+    *
+    *  @return The number of lines for specified reduced resolution level.
+    */
+   virtual ossim_uint32 getNumberOfLines(ossim_uint32 resLevel = 0) const;
+
+   /**
+    *  @brief Gets the number of samples for res level.
+    *
+    *  @param resLevel Reduced resolution level to return samples of.
+    *  Default = 0
+    *
+    *  @return The number of samples for specified reduced resolution level.
+    */
+   virtual ossim_uint32 getNumberOfSamples(ossim_uint32 resLevel = 0) const;
+
+   /**
+    * @brief Open method.
+    * @return true on success, false on error.
+    */
+   virtual bool open();
+
+   /**
+    *  @brief Method to test for open file stream.
+    *
+    *  @return true if open, false if not.
+    */
+   virtual bool isOpen()const;
+
+   /**
+    * @brief Method to close current entry.
+    *
+    * @note There is a bool kdu_compressed_source::close() and a
+    * void ossimImageHandler::close(); hence, a new close to avoid conflicting
+    * return types.
+    */
+   virtual void closeEntry();
+
+   /**
+    * Returns the image geometry object associated with this tile source or
+    * NULL if non defined.  The geometry contains full-to-local image
+    * transform as well as projection (image-to-world).
+    */
+   virtual ossimRefPtr<ossimImageGeometry> getImageGeometry();
+
+   /**
+    * @param Method to get geometry.
+    */
+   virtual ossimRefPtr<ossimImageGeometry> getInternalImageGeometry() const;
+
+   /**
+    * @return The number of entries (images) in the image file.
+    */
+   virtual ossim_uint32 getNumberOfEntries()const;
+
+   /**
+    * @param entryList This is the list to initialize with entry indexes.
+    *
+    * @note This implementation returns puts one entry "0" in the list.
+    */
+   virtual void getEntryList(std::vector<ossim_uint32>& entryList) const;
+
+   /**
+    * Method to the load (recreate) the state of an object from a keyword
+    * list.  Return true if ok or false on error.
+    */
+   virtual bool loadState(const ossimKeywordlist& kwl, const char* prefix=0);   
+
+   virtual bool setCurrentEntry(ossim_uint32 entryIdx);
+
+   /**
+   * @return The current entry number.
+   */
+   virtual ossim_uint32 getCurrentEntry()const;
+
+   std::vector<ossimString> getGlobalMeta() { return m_globalMeta; }
+
+   std::vector<ossimString> getSubDatasetMeta();
+
+   ossimString getHdfDataType() const { return m_hdfDataType; }
+
+   ossimString getMetaValue(const ossimString& key) const;
+
+   static const ossimString HDF4_EOS_GRID;              // HDF-EOS Grid
+   static const ossimString HDF4_EOS_SWATH;             // HDF-EOS Swath
+   static const ossimString HDF4_SEAWIFS_L1A;		     // SeaWiFS Level-1A Data
+   static const ossimString HDF4_SEAWIFS_L2;	           // SeaWiFS Level-2 Data
+   static const ossimString HDF4_SEAWIFS_L3;		        // SeaWiFS Level-3 Standard Mapped Image
+   static const ossimString HDF4_HYPERION_L1;           // Hyperion L1 Data Product
+   static const ossimString HDF4_SDS;                   // SDS
+
+private:
+
+   struct ossimHdfSubdataset
+   {
+      ossimHdfSubdataset(int32        sdsIndex,
+                         ossimString  name,
+                         int32        dataType,
+                         int32        rank,
+                         int32        bands,
+                         int32        rows,
+                         int32        cols,
+                         int32        attributes)
+         :m_sdsIndex(sdsIndex),
+         m_name(name),
+         m_dataType(dataType),
+         m_rank(rank),
+         m_bands(bands),
+         m_rows(rows),
+         m_cols(cols),
+         m_attributes(attributes)
+      {}
+     
+      int32        m_sdsIndex;
+      ossimString  m_name;
+      int32        m_dataType;
+      int32        m_rank;
+      int32        m_bands;
+      int32        m_rows;
+      int32        m_cols;
+      int32        m_attributes;
+   };
+
+   struct ossimHdfGroupData
+   {
+      ossimHdfGroupData(ossimString groupName,
+         std::vector<ossimHdfSubdataset> geoSubdatasets,
+         std::vector<ossimHdfSubdataset> dataSubdatasets)
+
+         :m_groupName(groupName),
+         m_geoSubdatasets(geoSubdatasets),
+         m_dataSubdatasets(dataSubdatasets)
+      {}
+
+      ossimString m_groupName;
+      std::vector<ossimHdfSubdataset> m_geoSubdatasets;
+      std::vector<ossimHdfSubdataset> m_dataSubdatasets;
+   };
+
+  bool initGlobalMeta();
+
+  bool initSubDatasets(int32 numDatasets);
+
+  void initSubdatasetNames();
+
+  void parseGroupName(std::vector<ossimString> groupInfo, ossimString groupName);
+
+  void initGroupInfos();
+
+  ossimString getAttribuitValues(int32 dataType, int32 numValues, void* attrValue) const;
+
+  void parseMetaString(ossimString attrStr);
+
+  void initHdfDataType();
+
+  ossimRefPtr<ossimProjection> processSwathProjection() const;
+
+  ossimRefPtr<ossimProjection> processGridProjection() const;
+
+  ossim_int32 getSizeByType(int32 dataType) const;
+
+  ossim_int32                                        m_fid;
+  ossim_int32                                        m_sd_id;
+
+  ossimIrect                                         m_imageRect; /** Has sub image offset. */
+  
+  ossim_uint32                                       m_numberOfBands;
+  ossimScalarType                                    m_scalarType;
+  ossimRefPtr<ossimImageData>                        m_tile;
+
+  std::map<int32, ossimString>                       m_groupInfos;
+  std::set<ossimString>                              m_subDatasetNames;
+  std::vector<ossimHdfSubdataset>                    m_subDatasets;
+  std::vector<ossimHdfGroupData>                     m_groupDatasets;
+  std::vector<ossimString>                           m_globalMeta;
+  ossimString                                        m_hdfDataType;
+  bool                                               m_isHdfEos;
+  ossim_uint32                                       m_currentEntryRender;
+  ossimHdf4SubDataset*                               m_currentSubDataset;
+  ossimString                                        m_structMetadata;
+
+TYPE_DATA
+};
+
+#endif /* #ifndef ossimHdf4Reader_HEADER */
+
diff --git a/ossim_plugins/hdf/ossimHdf4SubDataset.cpp b/ossim_plugins/hdf/ossimHdf4SubDataset.cpp
new file mode 100644
index 0000000..85c1332
--- /dev/null
+++ b/ossim_plugins/hdf/ossimHdf4SubDataset.cpp
@@ -0,0 +1,390 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Description:  Class definition for HDF reader.
+//
+//----------------------------------------------------------------------------
+// $Id: ossimHdf4SubDataset.cpp 2645 2011-05-26 15:21:34Z oscar.kramer $
+
+//Std includes
+#include <set>
+
+//ossim includes
+#include "ossimHdf4SubDataset.h"
+#include <ossim/base/ossimScalarTypeLut.h>
+#include <ossim/base/ossimTrace.h>
+#include <ossim/base/ossimUnitTypeLut.h>
+#include <ossim/imaging/ossimImageGeometryRegistry.h>
+#include <ossim/imaging/ossimImageDataFactory.h>
+//#include <ossim/base/ossimDrect.h>
+
+#ifdef OSSIM_ID_ENABLED
+static const char OSSIM_ID[] = "$Id";
+#endif
+
+static ossimTrace traceDebug("ossimHdf4SubDataset:debug");
+
+RTTI_DEF_INST(ossimHdf4SubDataset, "ossimHdf4SubDataset")
+
+bool doubleEquals(ossim_float64 left, ossim_float64 right, ossim_float64 epsilon) 
+{
+  return (fabs(left - right) < epsilon);
+}
+
+ossimHdf4SubDataset::ossimHdf4SubDataset() :
+   m_fileName(""), 
+   m_sd_name(""),
+   m_sds_index(-1),
+   m_sds_id(-1),
+   m_sd_id(-1),
+   m_rank(0),
+   m_numberOfBands(0),
+   m_numberOfSamples(0),
+   m_numberOfLines(0),
+   m_attributes(0),
+   m_isGeoField(false),
+   m_scalarType(OSSIM_SCALAR_UNKNOWN),
+   m_dataType(0),
+   m_hdfDataType(),
+   m_meta(0)
+{
+}
+
+ossimHdf4SubDataset::~ossimHdf4SubDataset()
+{
+   SDendaccess (m_sds_id); 
+   SDend (m_sd_id); 
+   m_meta.clear();
+}
+
+ossim_uint32 ossimHdf4SubDataset::getNumberOfLines(ossim_uint32 /* resLevel */) const
+{
+   return m_numberOfLines;
+}
+
+ossim_uint32 ossimHdf4SubDataset::getNumberOfSamples(ossim_uint32 /* resLevel */) const
+{
+   return m_numberOfSamples;
+}
+
+bool ossimHdf4SubDataset::open()
+{
+   static const char MODULE[] = "ossimHdf4SubDataset::open";
+
+   bool result = false;
+ 
+   m_sd_id = SDstart(m_fileName.c_str(), DFACC_READ);
+   if (m_sd_id < 0)
+   {
+      result = false;
+   }
+   else
+   {
+      result = true;
+   }
+
+   m_sds_id = SDselect(m_sd_id, m_sds_index);
+   if (m_sds_id < 0)
+   {
+      result = false;
+   }
+   else
+   {
+      result = true;
+   }
+
+   if (result == false)
+   {
+      SDendaccess (m_sds_id); 
+      SDend (m_sd_id); 
+   }
+   
+   initMeta();
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " exit status = " << (result?"true":"false\n")
+         << std::endl;
+   }
+
+   return result;
+}
+
+void ossimHdf4SubDataset::initMeta()
+{
+   m_meta.clear();
+
+   //insert name first
+   m_meta.push_back("name: " + ossimString(m_hdfDataType + ":" + m_sd_name));
+
+   char	attrName[100];
+   int32 numValues;
+   int32 dataType;
+
+   for (ossim_int32 i = 0; i < m_attributes; i++ )
+   {
+      // Get information about the attribute. Note that the first
+      // parameter is an SD interface identifier.
+      SDattrinfo(m_sds_id, i, attrName, &dataType, &numValues);
+      
+      ossim_int32 size = getDataTypeSize(dataType);
+      char* attrValue = new char[size * numValues + 1];
+      
+      SDreadattr(m_sds_id, i, attrValue);
+
+      if ( dataType == DFNT_CHAR8 || dataType == DFNT_UCHAR8 )
+      {
+         attrValue[numValues] = '\0';
+         m_meta.push_back(ossimString(attrName) + ": " + ossimString(attrValue).trim());
+      }
+      else
+      {
+         ossimString values = getAttribuitValues(dataType, numValues, attrValue);
+         m_meta.push_back(ossimString(attrName) + ": " + values);
+      }
+      delete [] attrValue;
+   }
+}
+
+ossimString ossimHdf4SubDataset::getAttribuitValues(int32 dataType, 
+                                                int32 numValues,
+                                                void* attrValue)
+{
+   ossimString values;
+
+   if (dataType == DFNT_INT8)
+   {
+      int8* int8Data = (int8*)attrValue;
+      for (ossim_int32 j = 0; j < numValues; j++)
+      {
+         ossimString valueStr = ossimString::toString(int8Data[j]);
+         values = values + ossimString(valueStr + " ");
+      }
+   }
+   else if (dataType == DFNT_UINT8)
+   {
+      uint8* uint8Data = (uint8*)attrValue;
+      for (ossim_int32 j = 0; j < numValues; j++)
+      {
+         ossimString valueStr = ossimString::toString(uint8Data[j]);
+         values = values + ossimString(valueStr + " ");
+      }
+   }
+   else if (dataType == DFNT_INT16)
+   {
+      int16* int16Data = (int16*)attrValue;
+      for (ossim_int32 j = 0; j < numValues; j++)
+      {
+         ossimString valueStr = ossimString::toString(int16Data[j]);
+         values = values + ossimString(valueStr + " ");
+      }
+   }
+   else if (dataType == DFNT_UINT16)
+   {
+      uint16* uint16Data = (uint16*)attrValue;
+      for (ossim_int32 j = 0; j < numValues; j++)
+      {
+         ossimString valueStr = ossimString::toString(uint16Data[j]);
+         values = values + ossimString(valueStr + " ");
+      }
+   }
+   else if (dataType == DFNT_INT32 || dataType == DFNT_UINT32)
+   {
+      ossim_int32* int32Data = (ossim_int32*)attrValue;
+      for (ossim_int32 j = 0; j < numValues; j++)
+      {
+         ossimString valueStr = ossimString::toString(int32Data[j]);
+         values = values + ossimString(valueStr + " ");
+      }
+   }
+   else if (dataType == DFNT_FLOAT64 || dataType == DFNT_DOUBLE)
+   {
+      double* doubleData = (double*)attrValue;
+      for (ossim_int32 j = 0; j < numValues; j++)
+      {
+         ossimString valueStr = ossimString::toString(doubleData[j]);
+         values = values + ossimString(valueStr + " ");
+      }
+   }
+   else
+   {
+      float32* floatData = (float32*)attrValue;
+      for (ossim_int32 j = 0; j < numValues; j++)
+      {
+         ossimString valueStr = ossimString::toString(floatData[j]);
+         values = values + ossimString(valueStr + " ");
+      }
+   }
+   return values;
+}
+
+char* ossimHdf4SubDataset::getTileBuf(const  ossimIrect& rect, ossim_uint32 band)
+{
+   // bool status = false;
+   int32 start[H4_MAX_NC_DIMS], edges[H4_MAX_NC_DIMS];
+   if (m_rank == 3)
+   {
+      start[0] = band;
+      start[1] = rect.ul().y;
+      start[2] = rect.ul().x;
+      edges[0] = 1;
+      edges[1] = rect.height(); 
+      edges[2] = rect.width(); 
+   }
+   else if (m_rank == 2)
+   {
+      start[0] = rect.ul().y;
+      start[1] = rect.ul().x;
+      edges[0] = rect.height(); 
+      edges[1] = rect.width(); 
+   }
+   
+   int32 numValues = rect.width() * rect.height();
+   ossim_int32 size = getDataTypeSize(m_dataType);
+   
+   char* data = new char[size * numValues];
+   // intn statusSd = SDreaddata(m_sds_id, start, NULL, edges, (VOIDP)data);
+   SDreaddata(m_sds_id, start, NULL, edges, (VOIDP)data);   
+  
+   return data;
+}
+
+ossim_uint32 ossimHdf4SubDataset::getNumberOfInputBands() const
+{
+   return m_numberOfBands;
+}
+
+ossimScalarType ossimHdf4SubDataset::getOutputScalarType() const
+{
+   return m_scalarType;
+}
+
+void ossimHdf4SubDataset::setNumberOfLines(int32 lines)
+{
+   m_numberOfLines = lines;
+}
+
+void ossimHdf4SubDataset::setNumberOfSamples(int32 samples)
+{
+   m_numberOfSamples = samples;
+}
+
+void ossimHdf4SubDataset::setNumberOfBands(int32 bands)
+{
+   m_numberOfBands = bands;
+}
+
+void ossimHdf4SubDataset::setSdsName(ossimString name)
+{
+   m_sd_name = name;
+}
+
+void ossimHdf4SubDataset::setHdfSdsIndex(int32 sds_index)
+{
+   m_sds_index = sds_index;
+}
+
+void ossimHdf4SubDataset::setAttributeCount(int32 attributes)
+{
+   m_attributes = attributes;
+}
+
+void ossimHdf4SubDataset::setSdsRank(int32 rank)
+{
+   m_rank = rank;
+}
+
+void ossimHdf4SubDataset::setHdfFilename(ossimString fileName)
+{
+   m_fileName = fileName;
+   open();
+}
+
+void ossimHdf4SubDataset::setOutputScalarType(int32 dataType)
+{
+   m_dataType = dataType;
+   switch (dataType)
+   {
+   case DFNT_UINT8:
+      {
+         m_scalarType = OSSIM_UINT8;
+         break;
+      }
+   case DFNT_INT8:
+      {
+         m_scalarType = OSSIM_SINT8;
+         break;
+      }
+   case DFNT_UINT16:
+      {
+         m_scalarType = OSSIM_UINT16;
+         break;
+      }
+   case DFNT_INT16:
+      {
+         m_scalarType = OSSIM_SINT16;
+         break;
+      }
+   case DFNT_UINT32:
+      {
+         m_scalarType = OSSIM_UINT32;
+         break;
+      }
+   case DFNT_INT32:
+      {
+         m_scalarType = OSSIM_SINT32;
+         break;
+      }
+   case DFNT_FLOAT32:
+      {
+         m_scalarType = OSSIM_FLOAT32;
+         break;
+      }
+   case DFNT_FLOAT64:
+      {
+         m_scalarType = OSSIM_FLOAT64;
+         break;
+      }
+   default:
+      {
+         m_scalarType = OSSIM_SCALAR_UNKNOWN;
+         break;
+      }
+   }
+}
+
+ossim_int32 ossimHdf4SubDataset::getDataTypeSize(int32 type)
+{
+   ossim_int32 size = 0;
+   if ( type == DFNT_CHAR8 || type == DFNT_UCHAR8 )
+   {
+      size = 1;
+   }
+   else if (type == DFNT_INT8 || type == DFNT_UINT8)
+   {
+      size = 1;
+   }
+   else if (type == DFNT_INT16 || type == DFNT_UINT16)
+   {
+      size = 2;
+   }
+   else if (type == DFNT_INT32 || type == DFNT_UINT32 
+      || type == DFNT_FLOAT32)
+   {
+      size = 4;
+   }
+   else if (type == DFNT_DOUBLE || type == DFNT_FLOAT64)
+   {
+      size = 8;
+   }
+   else
+   {
+      size = 4;
+   }
+   return size;
+}
+
diff --git a/ossim_plugins/hdf/ossimHdf4SubDataset.h b/ossim_plugins/hdf/ossimHdf4SubDataset.h
new file mode 100644
index 0000000..493ac19
--- /dev/null
+++ b/ossim_plugins/hdf/ossimHdf4SubDataset.h
@@ -0,0 +1,185 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Description:  Class declaration HDF reader.
+//
+// Specification: ISO/IEC 15444
+//
+//----------------------------------------------------------------------------
+// $Id: ossimHdf4SubDataset.h 2645 2011-05-26 15:21:34Z oscar.kramer $
+
+#ifndef ossimHdf4SubDataset_HEADER
+#define ossimHdf4SubDataset_HEADER 1
+
+//ossim includes
+#include "../ossimPluginConstants.h"
+#include <ossim/base/ossimIpt.h>
+#include <ossim/base/ossimIrect.h>
+#include <ossim/base/ossimRefPtr.h>
+#include <ossim/imaging/ossimImageHandler.h>
+#include <ossim/support_data/ossimJ2kSizRecord.h>
+#include <ossim/imaging/ossimAppFixedTileCache.h>
+
+//HDF4 Includes
+// #include <hdf/hdf.h>
+// #include <hdf/mfhdf.h>
+#include <hdf.h>
+#include <mfhdf.h>
+
+
+
+// Forward class declarations.
+class ossimImageData;
+
+class OSSIM_PLUGINS_DLL ossimHdf4SubDataset 
+{
+public:
+
+   /** default construtor */
+   ossimHdf4SubDataset();
+   
+   /** virtural destructor */
+   virtual ~ossimHdf4SubDataset();
+
+   /**
+    *  @brief Method to grab a tile(rectangle) from image.
+    *
+    *  @param rect The zero based rectangle to grab.
+    *
+    *  @param resLevel The reduced resolution level to grab from.
+    *
+    *  @return The ref pointer with the image data pointer.
+    */
+   char* getTileBuf(const  ossimIrect& rect, ossim_uint32 band);   
+
+   /**
+    *  Returns the number of bands in the image.
+    *  Satisfies pure virtual from ImageHandler class.
+    */
+   virtual ossim_uint32 getNumberOfInputBands() const;
+
+   /**
+    * Returns the output pixel type of the tile source.
+    */
+   virtual ossimScalarType getOutputScalarType() const;
+
+
+   /**
+    * @brief Gets number of lines for res level.
+    *
+    *  @param resLevel Reduced resolution level to return lines of.
+    *  Default = 0
+    *
+    *  @return The number of lines for specified reduced resolution level.
+    */
+   virtual ossim_uint32 getNumberOfLines(ossim_uint32 resLevel = 0) const;
+
+   /**
+    *  @brief Gets the number of samples for res level.
+    *
+    *  @param resLevel Reduced resolution level to return samples of.
+    *  Default = 0
+    *
+    *  @return The number of samples for specified reduced resolution level.
+    */
+   virtual ossim_uint32 getNumberOfSamples(ossim_uint32 resLevel = 0) const;
+
+   std::vector<ossimString> getMetadata() const { return m_meta; }
+
+   /**
+    * @brief sets number of lines.
+    *
+    */
+   void setNumberOfLines(int32 lines);
+
+   /**
+    *  @brief sets the number of samples.
+    *
+    */
+   void setNumberOfSamples(int32 samples);
+
+   /**
+    *  @brief sets the number of samples.
+    *
+    */
+   void setNumberOfBands(int32 bands);
+
+   /**
+    * @brief sets the output pixel type of the tile source.
+    *
+    */
+   void setOutputScalarType(int32 dataType);
+
+   /**
+    *  @brief Method to set number of attributes for dataset.
+    *
+    */
+   void setAttributeCount(int32 attributes); 
+
+   /**
+    *  @brief Method to set sds name for dataset.
+    *
+    */
+   void setSdsName(ossimString name); 
+
+   /**
+    *  @brief Method to set sds rank for dataset.
+    *
+    */
+   void setSdsRank(int32 rank); 
+
+   /**
+    * @brief Open method.
+    * @return true on success, false on error.
+    */
+   virtual bool open();
+
+   /**
+    *  @brief Method to set hdf file name for open file.
+    *
+    */
+   void setHdfFilename(ossimString fileName);
+
+   /**
+    *  @brief Method to set SDS id of hdf file for open file.
+    *
+    */
+   void setHdfDataType(ossimString hdfDatyType) { m_hdfDataType = hdfDatyType; }
+
+   /**
+    *  @brief Method to set Scientific Data Set Id for get data.
+    *
+    */
+   void setHdfSdsIndex(int32 sds_index);   
+
+private:
+
+  ossim_int32 getDataTypeSize(int32 type);
+
+  ossimString getAttribuitValues(int32 dataType, int32 numValues, void* attrValue);
+
+  void initMeta();
+
+  ossimString                       m_fileName;
+  ossimString                       m_sd_name;//SDS name
+  int32                             m_sds_index; //SDS index 
+  int32                             m_sds_id; //SDS selected id
+  int32                             m_sd_id; //SDS id of HDF file
+  int32                             m_rank;
+  ossim_uint32                      m_numberOfBands;
+  ossim_uint32                      m_numberOfSamples;
+  ossim_uint32                      m_numberOfLines;
+  int32                             m_attributes;
+  bool                              m_isGeoField;
+  ossimScalarType                   m_scalarType;
+  int32                             m_dataType;
+  ossimString                       m_hdfDataType;
+  std::vector<ossimString>          m_meta;
+TYPE_DATA
+};
+
+#endif /* #ifndef ossimHdf4SubDataset_HEADER */
+
diff --git a/ossim_plugins/hdf/ossimHdf5Reader.cpp b/ossim_plugins/hdf/ossimHdf5Reader.cpp
new file mode 100644
index 0000000..c36a4f4
--- /dev/null
+++ b/ossim_plugins/hdf/ossimHdf5Reader.cpp
@@ -0,0 +1,998 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Description:  Class definition for HDF4 reader.
+//
+//----------------------------------------------------------------------------
+// $Id: ossimHdf5Reader.cpp 2645 2011-05-26 15:21:34Z oscar.kramer $
+
+#include "ossimHdf5Reader.h"
+#include "ossimHdf5SubDataset.h"
+#include "ossimHdfGridModel.h"
+
+#include <ossim/base/ossimCommon.h>
+#include <ossim/base/ossimDpt.h>
+#include <ossim/base/ossimEndian.h>
+#include <ossim/base/ossimException.h>
+#include <ossim/base/ossimTieGptSet.h>
+#include <ossim/base/ossimIoStream.h>
+#include <ossim/base/ossimKeywordlist.h>
+#include <ossim/base/ossimNotify.h>
+#include <ossim/base/ossimScalarTypeLut.h>
+#include <ossim/base/ossimTrace.h>
+#include <ossim/base/ossimUnitTypeLut.h>
+
+#include <ossim/imaging/ossimImageDataFactory.h>
+#include <ossim/imaging/ossimImageGeometryRegistry.h>
+
+#include <ossim/projection/ossimProjection.h>
+#include <ossim/projection/ossimProjectionFactoryRegistry.h>
+#include <ossim/projection/ossimEpsgProjectionFactory.h>
+#include <ossim/projection/ossimUtmProjection.h>
+#include <ossim/projection/ossimEquDistCylProjection.h>
+#include <ossim/projection/ossimLambertConformalConicProjection.h>
+#include <ossim/projection/ossimMercatorProjection.h>
+#include <ossim/projection/ossimPolarStereoProjection.h>
+#include <ossim/projection/ossimPolyconicProjection.h>
+#include <ossim/projection/ossimAzimEquDistProjection.h>
+#include <ossim/projection/ossimObliqueMercatorProjection.h>
+#include <ossim/projection/ossimSpaceObliqueMercatorProjection.h>
+#include <ossim/projection/ossimSinusoidalProjection.h>
+
+#include <ossim/support_data/ossimAuxFileHandler.h>
+
+#include <fstream>
+#include <iostream>
+#include <string>
+
+#ifdef OSSIM_ID_ENABLED
+static const char OSSIM_ID[] = "$Id";
+#endif
+
+const ossimString ossimHdf5Reader::HDF5_EOS_GRID = "GRIDS";              
+const ossimString ossimHdf5Reader::HDF5_EOS_SWATH = "SWATHS";                   
+const ossimString ossimHdf5Reader::FILE_META_PATH = "/HDFEOS/ADDITIONAL/FILE_ATTRIBUTES";		
+const ossimString ossimHdf5Reader::ROOT_META_PATH = "HDFEOS";
+const ossimString ossimHdf5Reader::DATA_META_NAME = "ColumnAmountAerosol";	          
+const ossimString ossimHdf5Reader::STRUCT_META_PATH = "/HDFEOS INFORMATION/StructMetadata.0";		       
+
+static ossimTrace traceDebug("ossimHdf5Reader:debug");
+static ossimTrace traceDump("ossimHdf5Reader:dump");
+
+herr_t Hdf5AttrIterate(hid_t hdfObjId, const char* attrName, void* reader)
+{
+   hid_t           attrId;
+   hid_t           attrTypeID;
+   hid_t           attrNativeType;
+   hid_t           attrSpace;
+
+   char*           dataValue = NULL;
+   hsize_t         size[64];
+   unsigned int    attrElmts;
+   hsize_t         attrSize;
+   hsize_t         i;
+   void*           buf = NULL;
+   ossim_uint32    attrDims;
+   ossimString     attrValue;
+
+   ossimHdf5Reader* hdf5Reader = (ossimHdf5Reader*)reader;
+
+   attrId          = H5Aopen_name(hdfObjId, attrName);
+   attrTypeID      = H5Aget_type(attrId);
+   attrNativeType  = H5Tget_native_type(attrTypeID, H5T_DIR_DEFAULT);
+   attrSpace       = H5Aget_space(attrId);
+   attrDims        = H5Sget_simple_extent_dims(attrSpace, size, NULL);
+
+   if( H5Tget_class(attrNativeType) == H5T_STRING ) 
+   {
+      attrSize = H5Tget_size(attrTypeID);
+      dataValue = (char*)malloc(attrSize+1);
+      H5Aread(attrId, attrNativeType, dataValue);
+      dataValue[attrSize]='\0';
+      attrValue = ossimString(dataValue);
+      hdf5Reader->setGlobalMeta(ossimString(attrName), attrValue);
+   }
+   else 
+   {
+      attrElmts = 1;
+      for( i=0; i < attrDims; i++ ) 
+      {
+         attrElmts *= size[i];
+      }
+      if( attrElmts > 0 ){
+         buf = (void *)malloc(attrElmts*H5Tget_size(attrNativeType));
+         dataValue = (char*)malloc(8192);
+         dataValue[0]='\0';
+         H5Aread(attrId, attrNativeType, buf);
+      }
+
+      if(H5Tequal(H5T_NATIVE_CHAR, attrNativeType) || H5Tequal( H5T_NATIVE_UCHAR, attrNativeType))
+      {
+         for(i = 0; i < attrElmts; i++ ) 
+         {
+            attrValue += ossimString(((ossim_uint8*)buf)[i]) + " ";
+         }
+      }
+      else if(H5Tequal( H5T_NATIVE_SHORT, attrNativeType)) 
+      {
+         for(i = 0; i < attrElmts; i++ ) 
+         {
+            attrValue += ossimString::toString(((ossim_int16*) buf)[i]) + " ";
+         }
+      }
+      else if(H5Tequal(H5T_NATIVE_USHORT, attrNativeType)) 
+      {
+         for(i = 0; i < attrElmts; i++) 
+         {
+            attrValue += ossimString::toString(((ossim_uint16*)buf)[i]) + " ";
+         }
+      }
+      else if(H5Tequal( H5T_NATIVE_INT, attrNativeType)) 
+      {
+         for(i = 0; i < attrElmts; i++) 
+         {
+            attrValue += ossimString::toString(((ossim_int32*) buf)[i]) + " ";
+         }
+      }
+      else if(H5Tequal( H5T_NATIVE_UINT, attrNativeType ) ) 
+      {
+         for(i = 0; i < attrElmts; i++)  
+         {
+            attrValue += ossimString::toString(((ossim_uint32*) buf)[i]) + " ";   
+         }
+      }
+      else if(H5Tequal( H5T_NATIVE_LONG, attrNativeType)) 
+      {
+         for(i = 0; i < attrElmts; i++)  
+         {
+            attrValue += ossimString::toString(((ossim_int64*)buf)[i]) + " ";         
+         }
+      }
+      else if(H5Tequal( H5T_NATIVE_ULONG, attrNativeType))
+      {
+         for(i = 0; i < attrElmts; i++)  
+         {
+            attrValue += ossimString::toString(((ossim_uint64*)buf)[i]) + " ";
+         }
+      }
+      else if(H5Tequal( H5T_NATIVE_FLOAT, attrNativeType)) 
+      {
+         for(i = 0; i < attrElmts; i++)  
+         {
+            attrValue += ossimString::toString(((ossim_float32*)buf)[i]) + " ";
+         }
+      }
+      else if(H5Tequal( H5T_NATIVE_DOUBLE, attrNativeType)) 
+      {
+         for(i = 0; i < attrElmts; i++)  
+         {
+            attrValue += ossimString::toString(((ossim_float64*)buf)[i]);
+         }
+      }
+      hdf5Reader->setGlobalMeta(ossimString(attrName), attrValue);
+
+      free(buf);
+   }
+   H5Aclose(attrId);
+   free(dataValue);
+
+   return 0;
+}
+
+RTTI_DEF1_INST(ossimHdf5Reader,
+               "ossimHdf5Reader",
+               ossimImageHandler)
+
+ossimHdf5Reader::ossimHdf5Reader()
+   :
+   ossimImageHandler(),
+   m_fid(-1),
+   m_imageRect(ossimIrect(0, 0, 127,127)),
+   m_numberOfBands(0),
+   m_scalarType(OSSIM_SCALAR_UNKNOWN),
+   m_tile(0),
+   m_subDatasetNames(0),
+   m_geoDatasetNames(0),
+   m_globalMeta(0),
+   m_hdfDataType("UNKNOWN"),
+   m_currentEntryRender(0),
+   m_currentSubDataset(0),
+   m_structMetadata("")
+{
+}
+
+ossimHdf5Reader::~ossimHdf5Reader()
+{
+   closeEntry();
+}
+
+ossimString ossimHdf5Reader::getShortName()const
+{
+   return ossimString("ossim_hdf5_reader");
+}
+
+ossimString ossimHdf5Reader::getLongName()const
+{
+   return ossimString("ossim hdf5 reader");
+}
+
+ossimString ossimHdf5Reader::getClassName()const
+{
+   return ossimString("ossimHdf5Reader");
+}
+
+ossim_uint32 ossimHdf5Reader::getNumberOfLines(ossim_uint32 resLevel) const
+{
+   ossim_uint32 result = 0;
+   if ( isValidRLevel(resLevel) )
+   {
+      if (resLevel == 0)
+      {
+         if (m_currentSubDataset != NULL)
+         {
+            return m_currentSubDataset->getNumberOfLines();
+         }
+      }
+      else if (theOverview.valid())
+      {
+         result = theOverview->getNumberOfSamples(resLevel);
+      }
+   }
+   return result;
+}
+
+ossim_uint32 ossimHdf5Reader::getNumberOfSamples(ossim_uint32 resLevel) const
+{
+   ossim_uint32 result = 0;
+   if ( isValidRLevel(resLevel) )
+   {
+      if (resLevel == 0)
+      {
+         if (m_currentSubDataset != NULL)
+         {
+            return m_currentSubDataset->getNumberOfSamples();
+         }
+      }
+      else if (theOverview.valid())
+      {
+         result = theOverview->getNumberOfSamples(resLevel);
+      }
+   }
+   return result;
+}
+
+bool ossimHdf5Reader::open()
+{
+   static const char MODULE[] = "ossimHdf5Reader::open";
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " entered...\n"
+         << "image: " << theImageFile << "\n";
+   }
+
+   bool result = false;
+
+   if (m_subDatasetNames.size() == 0)
+   {
+      if (isOpen())
+      {
+         closeEntry();
+      }
+
+      m_fid = H5Fopen(theImageFile.c_str(), H5F_ACC_RDONLY, H5P_DEFAULT);
+
+      if (m_fid < 0)
+      {
+         closeEntry();
+         return false;
+      }
+
+      initSubdatasetNames();
+
+      result = initGlobalMeta(); 
+   }
+
+   if (m_currentEntryRender < m_subDatasetNames.size())
+   {
+      //close file before open file in sub-dataset
+      if (m_currentSubDataset != NULL)
+      {
+         delete m_currentSubDataset;
+         m_currentSubDataset = 0;
+      }
+      ossimString subDataName = m_subDatasetNames[m_currentEntryRender];
+      m_currentSubDataset = new ossimHdf5SubDataset();
+      m_currentSubDataset->setSubdatasetName(subDataName);
+      m_currentSubDataset->setHdfFilename(theImageFile);
+
+      m_tile = ossimImageDataFactory::instance()->create(this, this);
+      m_tile->initialize();
+
+      // Call the base complete open to pick up overviews.
+      completeOpen();
+      result = true;
+   }
+   else
+   {
+      closeEntry();
+      result = false;
+   }
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " exit status = " << (result?"true":"false\n")
+         << std::endl;
+   }
+
+   return result;
+}
+
+bool ossimHdf5Reader::initGlobalMeta()
+{
+   bool result = false;
+   m_globalMeta.clear();
+   //---
+   // H5Gopen1 is depreciated.  Need to fix. (drb)
+   // Should call H5Gopen2 which is typedef H5Gopen.
+   // hid_t groupId = H5Gopen(m_fid, FILE_META_PATH);
+   //---
+   hid_t groupId = H5Gopen1(m_fid, FILE_META_PATH);    
+   if (groupId > 0)
+   {
+      ossimHdf5Reader* reader = this;
+      //---
+      // H5Aiterate1 is depreciated.  Need to fix. (drb)
+      // Should call H5Aiterate2 which typedef H5Aiterate.
+      // herr_t ret = H5Aiterate(groupId, 0, Hdf5AttrIterate, (void*)reader);
+      //---
+      herr_t ret = H5Aiterate1(groupId, 0, Hdf5AttrIterate, (void*)reader);
+      if (ret == 0)
+      {
+         result = true;
+      }
+   }
+   H5Gclose(groupId);
+
+   ossimString columnMeta = ossimString("/" + ROOT_META_PATH + "/" + m_hdfDataType + "/" + DATA_META_NAME);
+   
+   // depreciated...
+   // groupId = H5Gopen(m_fid, columnMeta);
+   groupId = H5Gopen1(m_fid, columnMeta);
+   if (groupId > 0)
+   {
+      ossimHdf5Reader* reader = this;
+      
+      //---
+      // H5Aiterate1 id depreciated.  Need to fix. (drb)
+      // Should call H5Aiterate2 which is typedef H5Aiterate.
+      // herr_t ret = H5Aiterate(groupId, NULL, Hdf5AttrIterate, (void*)reader);
+      //---
+      herr_t ret = H5Aiterate1(groupId, NULL, Hdf5AttrIterate, (void*)reader);
+      if (ret == 0)
+      {
+         result = true;
+      }
+   }
+   H5Gclose(groupId);
+   return result;
+}
+
+void ossimHdf5Reader::initSubdatasetNames()
+{
+   m_subDatasetNames.clear();
+   m_geoDatasetNames.clear();
+   std::vector<ossimString> attrInfos;
+   ossimString groupIdentifier;
+   ossimString endGroupIdentifier;
+   ossimString groupName;
+
+   // Depreciated, need to fix... (drb)
+   // hid_t datasetId = H5Dopen(m_fid, STRUCT_META_PATH);
+   hid_t datasetId = H5Dopen1(m_fid, STRUCT_META_PATH);
+   if (datasetId >= 0)
+   {
+      hid_t datatype = H5Dget_type(datasetId);
+      size_t t_size = H5Tget_size(datatype);
+      hid_t dataspace = H5Dget_space(datasetId);    /* dataspace handle */
+
+      char* attrValues = new char[t_size];
+      // herr_t status = H5Dread (datasetId,
+      H5Dread (datasetId,                               
+               datatype, 
+               dataspace,
+               dataspace,
+               H5P_DEFAULT, 
+               attrValues);
+
+      m_structMetadata = ossimString(attrValues);
+      delete[] attrValues;
+
+      std::vector<ossimString> attrList = m_structMetadata.split("\n");
+
+      for (ossim_uint32 i  = 0; i < attrList.size(); i++)
+      {
+         ossimString attrInfo = attrList[i].trim();
+         if (attrInfo.contains("GROUP=SwathStructure") && m_subDatasetNames.size() == 0)//initialize the type and group name
+         {
+            m_hdfDataType = HDF5_EOS_SWATH;
+            groupIdentifier = "GROUP=SWATH_";
+            groupName = "SwathName";
+         }
+         else if (attrInfo.contains("GROUP=GridStructure") && m_subDatasetNames.size() == 0)//initialize the type and group name
+         {
+            m_hdfDataType = HDF5_EOS_GRID;
+            groupIdentifier = "GROUP=GRID_";
+            groupName = "GridName";
+         }
+         else //get sub dataset infos
+         {
+            if (attrInfo.contains(groupIdentifier) && attrInfo.contains("END_") == false)
+            {
+               endGroupIdentifier = "END_" + attrInfo;
+            }
+            if (attrInfo != endGroupIdentifier)
+            {
+               attrInfos.push_back(attrInfo);
+            } 
+            else
+            {
+               parseGroupName(attrInfos, groupName);
+               attrInfos.clear();
+            }
+         }
+      }
+      H5Sclose (dataspace);
+   }
+   H5Dclose(datasetId);
+}
+
+void ossimHdf5Reader::parseGroupName(std::vector<ossimString> groupInfo,
+                                     ossimString groupName)
+{
+   for (ossim_uint32 i = 0; i < groupInfo.size(); i++)
+   {
+      ossimString info = groupInfo[i];
+      if (info.contains(groupName))
+      {
+         groupName = info.split("=")[1].trim();
+         groupName = groupName.substitute("\"", "", true);
+      }
+      if (info.contains("DataFieldName"))
+      {
+         ossimString fieldName = info.split("=")[1].trim();
+
+         fieldName = fieldName.substitute("\"", "", true);
+         m_subDatasetNames.push_back(ossimString("/" + ROOT_META_PATH + "/" + 
+            m_hdfDataType + "/" + groupName + "/Data Fields/" + fieldName));
+
+         if (fieldName.contains("Latitude") || fieldName.contains("Longitude"))
+         {
+            fieldName = fieldName.substitute("\"", "", true);
+            m_geoDatasetNames.push_back(ossimString("/" + ROOT_META_PATH + "/" + 
+               m_hdfDataType + "/" + groupName + "/Data Fields/" + fieldName));
+         } 
+      }
+      else if (info.contains("GeoFieldName"))
+      {
+         ossimString fieldName = info.split("=")[1].trim();
+         fieldName = fieldName.substitute("\"", "", true);
+         m_geoDatasetNames.push_back(ossimString("/" + ROOT_META_PATH + "/" + 
+            m_hdfDataType + "/" + groupName + "/Geolocation Fields/" + fieldName));
+      }
+   }
+}
+
+bool ossimHdf5Reader::isOpen()const
+{
+   return m_currentSubDataset != NULL;
+}
+
+void ossimHdf5Reader::closeEntry()
+{
+   m_tile = 0;
+   H5Fclose(m_fid);
+
+   if (m_currentSubDataset != NULL)
+   {
+      delete m_currentSubDataset;
+      m_currentSubDataset = 0;
+   }
+   ossimImageHandler::close();
+}
+
+ossimRefPtr<ossimImageData> ossimHdf5Reader::getTile(const ossimIrect& tile_rect, 
+                                                     ossim_uint32 resLevel)
+{
+   if (m_tile.valid())
+   {
+      // Image rectangle must be set prior to calling getTile.
+      m_tile->setImageRectangle(tile_rect);
+
+      if ( getTile( m_tile.get(), resLevel ) == false )
+      {
+         if (m_tile->getDataObjectStatus() != OSSIM_NULL)
+         {
+            m_tile->makeBlank();
+         }
+      }
+   }
+
+   return m_tile;
+}
+
+bool ossimHdf5Reader::getTile(ossimImageData* result,
+                              ossim_uint32 resLevel)
+{
+   bool status = false;
+
+   //---
+   // Not open, this tile source bypassed, or invalid res level,
+   // return a blank tile.
+   //---
+   if( isOpen() && isSourceEnabled() && isValidRLevel(resLevel) &&
+      result && (result->getNumberOfBands() == getNumberOfOutputBands()) )
+   {
+      result->ref();  // Increment ref count.
+
+      //---
+      // Check for overview tile.  Some overviews can contain r0 so always
+      // call even if resLevel is 0.  Method returns true on success, false
+      // on error.
+      //---
+      status = getOverviewTile(resLevel, result);
+
+      if (!status) // Did not get an overview tile.
+      {
+         status = true;
+
+         ossimIrect tile_rect = result->getImageRectangle();     
+
+         if (getImageRectangle().intersects(tile_rect))
+         {
+            // Make a clip rect.
+            ossimIrect clipRect = tile_rect.clipToRect(getImageRectangle());
+
+            if (tile_rect.completely_within(clipRect) == false)
+            {
+               // Not filling whole tile so blank it out first.
+               result->makeBlank();
+            }
+
+            if (m_currentSubDataset != NULL)
+            {
+               for (ossim_uint32 band = 0; band < getNumberOfInputBands(); band++)
+               {
+                  void* dataBuffer = m_currentSubDataset->getTileBuf(clipRect, band);
+                  result->loadBand(dataBuffer, clipRect, band);
+                   delete[] (char*)dataBuffer;
+               }
+            }
+         }
+         else // No intersection...
+         {
+            result->makeBlank();
+         }
+      }
+      result->validate();
+
+      result->unref();  // Decrement ref count.
+   }
+
+   return status;
+}
+
+ossim_uint32 ossimHdf5Reader::getNumberOfInputBands() const
+{
+   if (m_currentSubDataset != NULL)
+   {
+      return m_currentSubDataset->getNumberOfInputBands();
+   }
+   return m_numberOfBands;
+}
+
+ossim_uint32 ossimHdf5Reader::getNumberOfOutputBands()const
+{
+   return getNumberOfInputBands();
+}
+
+ossim_uint32 ossimHdf5Reader::getImageTileWidth() const
+{
+   return m_imageRect.width();
+}
+
+ossim_uint32 ossimHdf5Reader::getImageTileHeight() const
+{
+   return m_imageRect.height();
+}
+
+ossimScalarType ossimHdf5Reader::getOutputScalarType() const
+{
+   if (m_currentSubDataset != NULL)
+   {
+      return m_currentSubDataset->getOutputScalarType();
+   }
+   return m_scalarType;
+}
+
+ossimRefPtr<ossimImageGeometry> ossimHdf5Reader::getImageGeometry()
+{
+   if ( !theGeometry )
+   {
+      //---
+      // Check for external geom:
+      //---
+      theGeometry = getExternalImageGeometry();
+
+      if ( !theGeometry )
+      {
+         //---
+         // Check the internal geometry first to avoid a factory call.
+         //---
+         theGeometry = getInternalImageGeometry();
+
+         // At this point it is assured theGeometry is set.
+
+         // Check for set projection.
+         if ( !theGeometry->getProjection() )
+         {
+            // Try factories for projection.
+            ossimImageGeometryRegistry::instance()->extendGeometry(this);
+         }
+      }
+
+      // Set image things the geometry object should know about.
+      initImageParameters( theGeometry.get() );
+   }
+
+   return theGeometry;
+}
+
+ossimRefPtr<ossimImageGeometry> ossimHdf5Reader::getInternalImageGeometry() const
+{
+   static const char MODULE[] = "ossimHdf5Reader::getInternalImageGeometry";
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " entered...\n";
+   }
+
+   ossimRefPtr<ossimImageGeometry> geom = new ossimImageGeometry();
+
+   if (m_hdfDataType == HDF5_EOS_GRID)
+   {
+      // Set the projection and return this handler's image geometry:
+      geom->setProjection(processGridProjection().get());
+   }
+   else if (m_hdfDataType == HDF5_EOS_SWATH)
+   {
+      geom->setProjection(processSwathProjection().get());
+   }
+
+   return geom;
+}
+
+ossimRefPtr<ossimProjection> ossimHdf5Reader::processGridProjection() const
+{
+   ossimString geoLatName = "";
+   ossimString geoLonName = "";
+   for (ossim_uint32 i = 0; i < m_geoDatasetNames.size(); i++)
+   {
+      if (m_geoDatasetNames[i].contains("/Latitude"))
+      {
+         geoLatName = m_geoDatasetNames[i];
+      }
+      else if (m_geoDatasetNames[i].contains("/Longitude"))
+      {
+         geoLonName = m_geoDatasetNames[i];
+      }
+   }
+
+   ossim_float32 ll_lat = 0.0;
+   ossim_float32 ll_lon = 0.0;
+
+   ossim_float32 lr_lat = 0.0;
+   ossim_float32 lr_lon = 0.0;
+
+   ossim_float32 ul_lat = 0.0;
+   ossim_float32 ul_lon = 0.0;
+
+   ossim_float32 ur_lat = 0.0;
+   ossim_float32 ur_lon = 0.0;
+
+   hsize_t dims_out[2]; //dataset dimensions
+
+   // Depreciated, need to fix... (drb)
+   // hid_t datasetId = H5Dopen(m_fid, geoLatName);
+   hid_t datasetId = H5Dopen1(m_fid, geoLatName);
+   
+   ossim_int32 index = 0;
+   if (datasetId >= 0)
+   {
+      hid_t datatype = H5Dget_type(datasetId);
+      hid_t dataspace = H5Dget_space(datasetId);    //dataspace handle
+      int rank = H5Sget_simple_extent_ndims(dataspace);
+      if (rank == 2)
+      {
+         H5Sget_simple_extent_dims(dataspace, dims_out, NULL);
+         ossim_int32 rows = dims_out[0];
+         ossim_int32 cols = dims_out[1];
+         if( H5Tequal(H5T_NATIVE_FLOAT,  datatype))
+         {
+            ossim_float32* data_out = new ossim_float32[rows * cols];
+            H5Dread(datasetId, datatype, dataspace, dataspace,
+               H5P_DEFAULT, data_out);
+
+            for (ossim_int32 y = 0; y < rows; y++)
+            {
+               for (ossim_int32 x = 0; x < cols; x++)
+               {
+                  index = x + y * cols;
+                  if (x == 0 && y == 0)
+                  {
+                     ul_lat = data_out[index];
+                  }
+                  else if (x == (cols-1) && y == 0)
+                  {
+                     ur_lat = data_out[index];
+                  }
+                  else if (x == 0 && y == (rows-1))
+                  {
+                     ll_lat = data_out[index];
+                  }
+                  else if (x == (cols-1) && y == (rows-1))
+                  {
+                     lr_lat = data_out[index];
+                  }
+               }
+            }
+            delete[] data_out;
+         }
+         else if( H5Tequal(H5T_NATIVE_DOUBLE,  datatype))
+         {
+            ossim_float64* data_out = new ossim_float64[rows * cols];
+            H5Dread(datasetId, datatype, dataspace, dataspace,
+               H5P_DEFAULT, data_out);
+
+            for (ossim_int32 y = 0; y < rows; y++)
+            {
+               for (ossim_int32 x = 0; x < cols; x++)
+               {
+                  index = x + y * cols;
+                  if (x == 0 && y == 0)
+                  {
+                     ul_lat = data_out[index];
+                  }
+                  else if (x == (cols-1) && y == 0)
+                  {
+                     ur_lat = data_out[index];
+                  }
+                  else if (x == 0 && y == (rows-1))
+                  {
+                     ll_lat = data_out[index];
+                  }
+                  else if (x == (cols-1) && y == (rows-1))
+                  {
+                     lr_lat = data_out[index];
+                  }
+               }
+            }
+            delete[] data_out;
+         }
+      }
+      H5Tclose(datatype);
+      H5Sclose(dataspace);
+   }
+   H5Dclose(datasetId);
+
+   // Depreciated, need to fix... (drb)
+   // datasetId = H5Dopen(m_fid, geoLonName);
+   datasetId = H5Dopen1(m_fid, geoLonName);
+   if (datasetId >= 0)
+   {
+      hid_t datatype = H5Dget_type(datasetId);
+      hid_t dataspace = H5Dget_space(datasetId);    /* dataspace handle */
+      int rank = H5Sget_simple_extent_ndims(dataspace);
+
+      if (rank == 2)
+      {
+         H5Sget_simple_extent_dims(dataspace, dims_out, NULL);
+         ossim_int32 rows = dims_out[0];
+         ossim_int32 cols = dims_out[1];
+         if( H5Tequal(H5T_NATIVE_FLOAT,  datatype))
+         {
+            ossim_float32* data_out = new ossim_float32[rows * cols];
+            H5Dread(datasetId, datatype, dataspace, dataspace,
+               H5P_DEFAULT, data_out);
+
+            for (ossim_int32 y = 0; y < rows; y++)
+            {
+               for (ossim_int32 x = 0; x < cols; x++)
+               {
+                  index = x + y * cols;
+                  if (x == 0 && y == 0)
+                  {
+                     ul_lon = data_out[index];
+                  }
+                  else if (x == (cols-1) && y == 0)
+                  {
+                     ur_lon = data_out[index];
+                  }
+                  else if (x == 0 && y == (rows-1))
+                  {
+                     ll_lon = data_out[index];
+                  }
+                  else if (x == (cols-1) && y == (rows-1))
+                  {
+                     lr_lon = data_out[index];
+                  }
+               }
+            }
+            delete[] data_out;
+         }
+         else if( H5Tequal(H5T_NATIVE_DOUBLE,  datatype))
+         {
+            ossim_float64* data_out = new ossim_float64[rows * cols];
+            H5Dread(datasetId, datatype, dataspace, dataspace,
+               H5P_DEFAULT, data_out);
+
+            for (ossim_int32 y = 0; y < rows; y++)
+            {
+               for (ossim_int32 x = 0; x < cols; x++)
+               {
+                  index = x + y * cols;
+                  if (x == 0 && y == 0)
+                  {
+                     ul_lon = data_out[index];
+                  }
+                  else if (x == (cols-1) && y == 0)
+                  {
+                     ur_lon = data_out[index];
+                  }
+                  else if (x == 0 && y == (rows-1))
+                  {
+                     ll_lon = data_out[index];
+                  }
+                  else if (x == (cols-1) && y == (rows-1))
+                  {
+                     lr_lon = data_out[index];
+                  }
+               }
+            }
+            delete[] data_out;
+         }
+      }
+      H5Tclose(datatype);
+      H5Sclose(dataspace);
+   }
+   H5Dclose(datasetId);
+
+   if (m_currentSubDataset != NULL)
+   {
+      ossimString epsg("EPSG:4326");
+      ossimRefPtr<ossimMapProjection> mapProj = PTR_CAST(ossimMapProjection, 
+         ossimEpsgProjectionFactory::instance()->createProjection(epsg));
+
+      ossim_uint32 rows = m_currentSubDataset->getNumberOfLines();
+      ossim_uint32 cols = m_currentSubDataset->getNumberOfSamples();
+     
+      ossim_float64 xRes = (lr_lon - ul_lon)/cols;
+      ossim_float64 yRes = (lr_lat - ul_lat)/rows;
+      ossimDpt gsd(fabs(xRes), fabs(yRes));
+
+      mapProj->setUlTiePoints(ossimGpt(ul_lat, ul_lon));
+      mapProj->setDecimalDegreesPerPixel(gsd);
+      return mapProj.get();
+   }
+
+   return ossimRefPtr<ossimProjection>();
+}
+
+ossimRefPtr<ossimProjection> ossimHdf5Reader::processSwathProjection() const
+{
+   ossimString geoLatName = "";
+   ossimString geoLonName = "";
+   for (ossim_uint32 i = 0; i < m_geoDatasetNames.size(); i++)
+   {
+      if (m_geoDatasetNames[i].contains("/Latitude"))
+      {
+         geoLatName = m_geoDatasetNames[i];
+      }
+      else if (m_geoDatasetNames[i].contains("/Longitude"))
+      {
+         geoLonName = m_geoDatasetNames[i];
+      }
+   }
+
+   if (m_currentSubDataset != NULL)
+   {
+      ossim_uint32 rows = m_currentSubDataset->getNumberOfLines();
+      ossim_uint32 cols = m_currentSubDataset->getNumberOfSamples();
+      ossimIpt spacing(cols, rows);
+      ossimDrect rect(0, 0, cols-1, rows-1);
+      return new ossimHdfGridModel(theImageFile, rect, geoLatName, geoLonName, spacing);
+   }
+
+   return ossimRefPtr<ossimProjection>();
+}
+
+bool ossimHdf5Reader::loadState(const ossimKeywordlist& kwl,
+                                const char* prefix)
+{
+   bool result = false;
+
+   if ( ossimImageHandler::loadState(kwl, prefix) )
+   {
+      result = open();
+   }
+
+   return result;
+}
+
+ossim_uint32 ossimHdf5Reader::getNumberOfEntries()const
+{
+   return (ossim_uint32) m_subDatasetNames.size();
+}
+
+bool ossimHdf5Reader::setCurrentEntry(ossim_uint32 entryIdx)
+{
+   if (m_currentEntryRender == entryIdx)
+   {
+      return true; // Nothing to do...
+   }
+   m_currentEntryRender = entryIdx;
+   theOverview = 0;
+   theOverviewFile.clear();
+   m_tile = 0;
+   return open();
+}
+
+std::vector<ossimString> ossimHdf5Reader::getSubDatasetMeta()
+{
+   if (m_currentSubDataset != NULL)
+   {
+      return m_currentSubDataset->getMetadata();
+   }
+   return std::vector<ossimString>();
+}
+
+void ossimHdf5Reader::getEntryList(std::vector<ossim_uint32>& entryList)const
+{
+   for (ossim_uint32 i = 0; i < m_subDatasetNames.size(); i++)
+   {
+      entryList.push_back(i);
+   }
+}
+
+ossimString ossimHdf5Reader::getMetaValue(const ossimString& key) const
+{
+   for (ossim_uint32 i = 0; i < m_globalMeta.size(); i++)
+   {
+      ossimString info = m_globalMeta[i];
+      ossimString keyTmp = info.split(":")[0].trim();
+      ossimString value = info.split(":")[1].trim();
+      if (keyTmp == key)
+      {
+         return value;
+      }
+   }
+   return "";
+}
+
+void ossimHdf5Reader::setGlobalMeta(const ossimString& key, const ossimString& value)
+{
+   ossimString meta = ossimString(key + ": " + value);
+   m_globalMeta.push_back(meta);
+}
+
+ossim_uint32 ossimHdf5Reader::getCurrentEntry()const
+{
+   return m_currentEntryRender;
+}
+
+
+
diff --git a/ossim_plugins/hdf/ossimHdf5Reader.h b/ossim_plugins/hdf/ossimHdf5Reader.h
new file mode 100644
index 0000000..29f9cc2
--- /dev/null
+++ b/ossim_plugins/hdf/ossimHdf5Reader.h
@@ -0,0 +1,268 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Description:  Class declaration HDF5 reader.
+//
+// Specification: ISO/IEC 15444
+//
+//----------------------------------------------------------------------------
+// $Id: ossimHdf5Reader.h 2645 2011-05-26 15:21:34Z oscar.kramer $
+
+#ifndef ossimHdf5Reader_HEADER
+#define ossimHdf5Reader_HEADER 1
+
+//HDF5 Includes
+#include "hdf5.h"
+
+#include <iosfwd>
+#include <fstream>
+#include <vector>
+#include <set>
+#include "../ossimPluginConstants.h"
+#include <ossim/base/ossimIpt.h>
+#include <ossim/base/ossimIrect.h>
+#include <ossim/imaging/ossimImageHandler.h>
+#include <ossim/imaging/ossimAppFixedTileCache.h>
+
+// Forward class declarations.
+class ossimImageData;
+class ossimDpt;
+class ossimHdf5SubDataset;
+class ossimHdfGridModel;
+
+herr_t Hdf5AttrIterate(hid_t hdfObjId, const char* attrName, void* reader);
+
+class OSSIM_PLUGINS_DLL ossimHdf5Reader : public ossimImageHandler
+{
+public:
+
+   /** default construtor */
+   ossimHdf5Reader();
+   
+   /** virtural destructor */
+   virtual ~ossimHdf5Reader();
+
+   /**
+    * @brief Returns short name.
+    * @return "ossim_hdf4_reader"
+    */
+   virtual ossimString getShortName() const;
+   
+   /**
+    * @brief Returns long  name.
+    * @return "ossim hdf4 reader"
+    */
+   virtual ossimString getLongName()  const;
+
+   /**
+    * @brief Returns class name.
+    * @return "ossimHdf5Reader"
+    */
+   virtual ossimString getClassName() const;
+
+   /**
+    *  @brief Method to grab a tile(rectangle) from image.
+    *
+    *  @param rect The zero based rectangle to grab.
+    *
+    *  @param resLevel The reduced resolution level to grab from.
+    *
+    *  @return The ref pointer with the image data pointer.
+    */
+   virtual ossimRefPtr<ossimImageData> getTile(const  ossimIrect& rect,
+                                               ossim_uint32 resLevel=0);
+
+   virtual bool getTile(ossimImageData* result, ossim_uint32 resLevel=0);   
+
+   /**
+    *  Returns the number of bands in the image.
+    *  Satisfies pure virtual from ImageHandler class.
+    */
+   virtual ossim_uint32 getNumberOfInputBands() const;
+
+   /**
+    * Returns the number of bands in a tile returned from this TileSource.
+    * Note: we are supporting sources that can have multiple data objects.
+    * If you want to know the scalar type of an object you can pass in the
+    */
+   virtual ossim_uint32 getNumberOfOutputBands()const; 
+   /**
+    * Returns the tile width of the image or 0 if the image is not tiled.
+    * Note: this is not the same as the ossimImageSource::getTileWidth which
+    * returns the output tile width which can be different than the internal
+    * image tile width on disk.
+    */
+   virtual ossim_uint32 getImageTileWidth() const;
+
+   /**
+    * Returns the tile width of the image or 0 if the image is not tiled.
+    * Note: this is not the same as the ossimImageSource::getTileHeight which
+    * returns the output tile height which can be different than the internal
+    * image tile height on disk.
+    */
+   virtual ossim_uint32 getImageTileHeight() const;
+
+   /**
+    * Returns the output pixel type of the tile source.
+    */
+   virtual ossimScalarType getOutputScalarType() const;
+   
+
+   /**
+    * @brief Gets number of lines for res level.
+    *
+    *  @param resLevel Reduced resolution level to return lines of.
+    *  Default = 0
+    *
+    *  @return The number of lines for specified reduced resolution level.
+    */
+   virtual ossim_uint32 getNumberOfLines(ossim_uint32 resLevel = 0) const;
+
+   /**
+    *  @brief Gets the number of samples for res level.
+    *
+    *  @param resLevel Reduced resolution level to return samples of.
+    *  Default = 0
+    *
+    *  @return The number of samples for specified reduced resolution level.
+    */
+   virtual ossim_uint32 getNumberOfSamples(ossim_uint32 resLevel = 0) const;
+
+   /**
+    * @brief Open method.
+    * @return true on success, false on error.
+    */
+   virtual bool open();
+
+   /**
+    *  @brief Method to test for open file stream.
+    *
+    *  @return true if open, false if not.
+    */
+   virtual bool isOpen()const;
+
+   /**
+    * @brief Method to close current entry.
+    *
+    * @note There is a bool kdu_compressed_source::close() and a
+    * void ossimImageHandler::close(); hence, a new close to avoid conflicting
+    * return types.
+    */
+   virtual void closeEntry();
+
+   /**
+    * Returns the image geometry object associated with this tile source or
+    * NULL if non defined.  The geometry contains full-to-local image
+    * transform as well as projection (image-to-world).
+    */
+   virtual ossimRefPtr<ossimImageGeometry> getImageGeometry();
+
+   /**
+    * @param Method to get geometry.
+    */
+   virtual ossimRefPtr<ossimImageGeometry> getInternalImageGeometry() const;
+
+   /**
+    * @return The number of entries (images) in the image file.
+    */
+   virtual ossim_uint32 getNumberOfEntries()const;
+
+   /**
+    * @param entryList This is the list to initialize with entry indexes.
+    *
+    * @note This implementation returns puts one entry "0" in the list.
+    */
+   virtual void getEntryList(std::vector<ossim_uint32>& entryList) const;
+
+   /**
+    * Method to the load (recreate) the state of an object from a keyword
+    * list.  Return true if ok or false on error.
+    */
+   virtual bool loadState(const ossimKeywordlist& kwl, const char* prefix=0);   
+
+   virtual bool setCurrentEntry(ossim_uint32 entryIdx);
+
+   /**
+   * @return The current entry number.
+   */
+   virtual ossim_uint32 getCurrentEntry()const;
+
+   std::vector<ossimString> getGlobalMeta() { return m_globalMeta; }
+
+   void setGlobalMeta(const ossimString& key, const ossimString& value);
+
+   std::vector<ossimString> getSubDatasetMeta();
+
+   ossimString getHdfDataType() const { return m_hdfDataType; }
+
+   ossimString getMetaValue(const ossimString& key) const;
+
+   static const ossimString HDF5_EOS_GRID;              // HDF-EOS Grid
+   static const ossimString HDF5_EOS_SWATH;             // HDF-EOS Swath
+   static const ossimString ROOT_META_PATH;
+   static const ossimString FILE_META_PATH;		        // Path for file meta data
+   static const ossimString DATA_META_NAME;		        // Path for data field and geo field meta data
+   static const ossimString STRUCT_META_PATH;		     // Path for structmetadata.0
+
+private:
+
+   struct ossimHdf5Object
+   {
+      ossimHdf5Object(ossimString name,
+         ossim_int32 dataset_id,
+         ossim_int32 rank,
+         hsize_t     dims,
+         hid_t       native,
+         hid_t       hdataType)
+         :m_name(name),
+         m_dataset_id(dataset_id),
+         m_rank(rank),
+         m_dims(dims),
+         m_native(native),
+         m_hdataType(hdataType)
+      {}
+
+      ossimString m_name;
+      ossim_int32 m_dataset_id;
+      ossim_int32 m_rank;
+      hsize_t     m_dims;
+      hid_t       m_native;
+      hid_t       m_hdataType;
+   };
+
+  bool initGlobalMeta();
+
+  void initSubdatasetNames();
+
+  void parseGroupName(std::vector<ossimString> groupInfo, ossimString groupName);
+
+  void initGroupInfos();
+
+  ossimRefPtr<ossimProjection> processSwathProjection() const;
+
+  ossimRefPtr<ossimProjection> processGridProjection() const;
+
+  hid_t                                              m_fid;          // identifier of file
+ 
+  ossimIrect                                         m_imageRect; /** Has sub image offset. */
+  
+  ossim_uint32                                       m_numberOfBands;
+  ossimScalarType                                    m_scalarType;
+  ossimRefPtr<ossimImageData>                        m_tile;
+
+  std::vector<ossimString>                           m_subDatasetNames;
+  std::vector<ossimString>                           m_geoDatasetNames;
+  std::vector<ossimString>                           m_globalMeta;
+  ossimString                                        m_hdfDataType;
+  ossim_uint32                                       m_currentEntryRender;
+  ossimHdf5SubDataset*                               m_currentSubDataset;
+  ossimString                                        m_structMetadata;
+ 
+TYPE_DATA
+};
+
+#endif /* #ifndef ossimHdf5Reader_HEADER */
+
diff --git a/ossim_plugins/hdf/ossimHdf5SubDataset.cpp b/ossim_plugins/hdf/ossimHdf5SubDataset.cpp
new file mode 100644
index 0000000..e4da87d
--- /dev/null
+++ b/ossim_plugins/hdf/ossimHdf5SubDataset.cpp
@@ -0,0 +1,474 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Description:  Class definition for HDF reader.
+//
+//----------------------------------------------------------------------------
+// $Id: ossimHdf5SubDataset.cpp 2645 2011-05-26 15:21:34Z oscar.kramer $
+
+//ossim includes
+#include "ossimHdf5SubDataset.h"
+#include <ossim/base/ossimScalarTypeLut.h>
+#include <ossim/base/ossimTrace.h>
+#include <ossim/base/ossimUnitTypeLut.h>
+#include <ossim/imaging/ossimImageGeometryRegistry.h>
+#include <ossim/imaging/ossimImageDataFactory.h>
+
+#include <cstdlib> /* for malloc */
+
+#ifdef OSSIM_ID_ENABLED
+static const char OSSIM_ID[] = "$Id";
+#endif
+
+static ossimTrace traceDebug("ossimHdf5SubDataset:debug");
+
+RTTI_DEF_INST(ossimHdf5SubDataset, "ossimHdf5SubDataset")
+
+herr_t Hdf5SubAttrIterate(hid_t hdfObjId, const char* attrName, void* reader)
+{
+   hid_t           attrId;
+   hid_t           attrTypeID;
+   hid_t           attrNativeType;
+   hid_t           attrSpace;
+
+   char*           dataValue = NULL;
+   hsize_t         size[64];
+   unsigned int    attrElmts;
+   hsize_t         attrSize;
+   hsize_t         i;
+   void*           buf = NULL;
+   ossim_uint32    attrDims;
+   ossimString     attrValue;
+
+   ossimHdf5SubDataset* hdf5Reader = (ossimHdf5SubDataset*)reader;
+
+   attrId          = H5Aopen_name(hdfObjId, attrName);
+   attrTypeID      = H5Aget_type(attrId);
+   attrNativeType  = H5Tget_native_type(attrTypeID, H5T_DIR_DEFAULT);
+   attrSpace       = H5Aget_space(attrId);
+   attrDims        = H5Sget_simple_extent_dims(attrSpace, size, NULL);
+
+   if( H5Tget_class(attrNativeType) == H5T_STRING ) 
+   {
+      attrSize = H5Tget_size(attrTypeID);
+      dataValue = (char*)malloc(attrSize+1);
+      H5Aread(attrId, attrNativeType, dataValue);
+      dataValue[attrSize]='\0';
+      attrValue = ossimString(dataValue);
+      hdf5Reader->setMeta(ossimString(attrName), attrValue);
+   }
+   else 
+   {
+      attrElmts = 1;
+      for( i=0; i < attrDims; i++ ) 
+      {
+         attrElmts *= size[i];
+      }
+      if( attrElmts > 0 ){
+         buf = (void *)malloc(attrElmts*H5Tget_size(attrNativeType));
+         dataValue = (char*)malloc(8192);
+         dataValue[0]='\0';
+         H5Aread(attrId, attrNativeType, buf);
+      }
+
+      if (H5Tequal(H5T_NATIVE_CHAR, attrNativeType))
+      {
+         for(i = 0; i < attrElmts; i++ ) 
+         {
+            attrValue += ossimString(((ossim_int8*)buf)[i]) + " ";
+         }
+      }
+      if (H5Tequal( H5T_NATIVE_UCHAR, attrNativeType))
+      {
+         for(i = 0; i < attrElmts; i++ ) 
+         {
+            attrValue += ossimString(((ossim_uint8*)buf)[i]) + " ";
+         }
+      }
+      else if(H5Tequal( H5T_NATIVE_SHORT, attrNativeType)) 
+      {
+         for(i = 0; i < attrElmts; i++ ) 
+         {
+            attrValue += ossimString::toString(((ossim_int16*) buf)[i]) + " ";
+         }
+      }
+      else if(H5Tequal(H5T_NATIVE_USHORT, attrNativeType)) 
+      {
+         for(i = 0; i < attrElmts; i++) 
+         {
+            attrValue += ossimString::toString(((ossim_uint16*)buf)[i]) + " ";
+         }
+      }
+      else if(H5Tequal( H5T_NATIVE_INT, attrNativeType)) 
+      {
+         for(i = 0; i < attrElmts; i++) 
+         {
+            attrValue += ossimString::toString(((ossim_int32*) buf)[i]) + " ";
+         }
+      }
+      else if(H5Tequal( H5T_NATIVE_UINT, attrNativeType ) ) 
+      {
+         for(i = 0; i < attrElmts; i++)  
+         {
+            attrValue += ossimString::toString(((ossim_uint32*) buf)[i]) + " ";   
+         }
+      }
+      else if(H5Tequal( H5T_NATIVE_LONG, attrNativeType)) 
+      {
+         for(i = 0; i < attrElmts; i++)  
+         {
+            attrValue += ossimString::toString(((ossim_int64*)buf)[i]) + " ";         
+         }
+      }
+      else if(H5Tequal( H5T_NATIVE_ULONG, attrNativeType))
+      {
+         for(i = 0; i < attrElmts; i++)  
+         {
+            attrValue += ossimString::toString(((ossim_uint64*)buf)[i]) + " ";
+         }
+      }
+      else if(H5Tequal( H5T_NATIVE_FLOAT, attrNativeType)) 
+      {
+         for(i = 0; i < attrElmts; i++)  
+         {
+            attrValue += ossimString::toString(((ossim_float32*)buf)[i]) + " ";
+         }
+      }
+      else if(H5Tequal( H5T_NATIVE_DOUBLE, attrNativeType)) 
+      {
+         for(i = 0; i < attrElmts; i++)  
+         {
+            attrValue += ossimString::toString(((ossim_float64*)buf)[i]);
+         }
+      }
+      hdf5Reader->setMeta(ossimString(attrName), attrValue);
+
+      free(buf);
+   }
+   H5Aclose(attrId);
+   free(dataValue);
+
+   return 0;
+}
+
+ossimHdf5SubDataset::ossimHdf5SubDataset()
+                         : m_fileName(""),
+                           m_dataset_name(""),
+                           m_fid(-1),
+                           m_dataset_id(-1),
+                           m_rank(0),
+                           m_native(-1),
+                           m_dataType(-1),
+                           m_dataspace(0),
+                           m_size(0),
+                           m_dataSize(0),
+                           m_numberOfBands(0),
+                           m_numberOfSamples(0),
+                           m_numberOfLines(0),
+                           m_scalarType(OSSIM_SCALAR_UNKNOWN),
+                           m_hdfDataType(),
+                           m_meta()
+{
+}
+
+ossimHdf5SubDataset::~ossimHdf5SubDataset()
+{
+   close();
+}
+
+void ossimHdf5SubDataset::close()
+{
+   H5Tclose(m_dataType);
+   H5Dclose(m_dataset_id);
+   H5Sclose(m_dataspace);
+   H5Fclose(m_fid);
+
+   m_meta.clear();
+}
+
+ossim_uint32 ossimHdf5SubDataset::getNumberOfLines( ossim_uint32 /* resLevel */) const
+{
+   return m_numberOfLines;
+}
+
+ossim_uint32 ossimHdf5SubDataset::getNumberOfSamples( ossim_uint32 /* resLevel */) const
+{
+   return m_numberOfSamples;
+}
+
+bool ossimHdf5SubDataset::open()
+{
+   static const char MODULE[] = "ossimHdf5SubDataset::open";
+
+   bool result = false;
+
+   m_fid = H5Fopen(m_fileName.c_str(), H5F_ACC_RDONLY, H5P_DEFAULT);
+   if (m_fid < 0)
+   {
+      H5Fclose(m_fid);
+      return false;
+   }
+
+   // Third arg added for compile fix but not checked. (drb)
+   m_dataset_id = H5Dopen(m_fid, m_dataset_name, 0); 
+
+   if (m_dataset_id < 0)
+   {
+      close();
+      return false;
+   }
+
+   m_dataType = H5Dget_type(m_dataset_id);
+   m_native = H5Tget_native_type(m_dataType, H5T_DIR_ASCEND );
+   setOutputScalarType();
+
+   H5Tget_class(m_dataType);   
+   H5Tget_order(m_dataType);
+
+   m_size = H5Tget_size(m_dataType);
+
+   m_dataspace = H5Dget_space(m_dataset_id);    /* dataspace handle */
+   m_rank = H5Sget_simple_extent_ndims(m_dataspace);
+
+   if (m_rank == 4)
+   {
+      hsize_t  dims_out[4];
+      herr_t status_n  = H5Sget_simple_extent_dims(m_dataspace, dims_out, NULL);
+      if (status_n >= 0)
+      {
+         m_numberOfBands = dims_out[2];
+         m_numberOfLines = dims_out[0];
+         m_numberOfSamples = dims_out[1];
+      }
+   }
+   else if (m_rank == 3)
+   {
+      hsize_t  dims_out[3];
+      herr_t status_n  = H5Sget_simple_extent_dims(m_dataspace, dims_out, NULL);
+      if (status_n >= 0)
+      {
+         if (dims_out[2] < dims_out[0] && dims_out[2] < dims_out[1])
+         {
+            m_numberOfBands = dims_out[2];
+            m_numberOfLines = dims_out[0];
+            m_numberOfSamples = dims_out[1];
+         }
+         else
+         {
+            m_numberOfBands = dims_out[0];
+            m_numberOfLines = dims_out[1];
+            m_numberOfSamples = dims_out[2];
+         }
+      }
+   }
+   else if (m_rank == 2)
+   {
+      hsize_t  dims_out[2];
+      herr_t status_n  = H5Sget_simple_extent_dims(m_dataspace, dims_out, NULL);
+      if (status_n >= 0)
+      {
+         m_numberOfBands = 1;
+         m_numberOfLines = dims_out[0];
+         m_numberOfSamples = dims_out[1];
+      }
+   }
+   else if (m_rank == 1)
+   {
+      hsize_t  dims_out[1];
+      herr_t status_n  = H5Sget_simple_extent_dims(m_dataspace, dims_out, NULL);
+      if (status_n >= 0)
+      {
+         m_numberOfBands = 0;
+         m_numberOfLines = dims_out[0];
+         m_numberOfSamples = 0;
+      }
+   }
+   else
+   {
+      m_numberOfBands = 0;
+      m_numberOfLines = 0;
+      m_numberOfSamples = 0;
+   }
+
+   result = initMeta();
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " exit status = " << (result?"true":"false\n")
+         << std::endl;
+   }
+
+   return result;
+}
+
+bool ossimHdf5SubDataset::initMeta()
+{
+   m_meta.clear();
+
+   //insert name first
+   m_meta.push_back("name: " + m_dataset_name);
+
+   ossimHdf5SubDataset* reader = this;
+
+   //---
+   // H5Aiterate1 id depreciated.  Need to fix. (drb)
+   // Should call H5Aiterate2 which is typedef H5Aiterate.
+   // herr_t ret = H5Aiterate(m_dataset_id, (H5_index_t)0, Hdf5SubAttrIterate, (void*)reader);
+   //---
+   herr_t ret = H5Aiterate1(m_dataset_id, 0, Hdf5SubAttrIterate, (void*)reader);   
+
+   if (ret == 0)
+   {
+      return true;
+   }
+   return false;
+}
+
+char* ossimHdf5SubDataset::getTileBuf(const  ossimIrect& rect, ossim_uint32 band)
+{
+   hsize_t     count[3];
+   hsize_t     offset[3];
+   hid_t       memspace;
+   hsize_t     col_dims[3];
+
+   if (m_rank == 3)
+   {
+      offset[0] = band;
+      offset[1] = rect.ul().y;
+      offset[2] = rect.ul().x;
+
+      count[0] = 1;
+      count[1] = rect.height();
+      count[2] = rect.width();
+
+      col_dims[0] = 1;
+      col_dims[1] = rect.height();
+      col_dims[2] = rect.width();
+   }
+   else
+   {
+      offset[0] = rect.ul().y;
+      offset[1] = rect.ul().x;
+
+      count[0] = rect.height();
+      count[1] = rect.width();
+
+      col_dims[0] = rect.height();
+      col_dims[1] = rect.width();
+   }
+
+   // herr_t status =  H5Sselect_hyperslab(m_dataspace, H5S_SELECT_SET, offset, NULL, count, NULL );
+   H5Sselect_hyperslab(m_dataspace, H5S_SELECT_SET, offset, NULL, count, NULL );   
+
+   memspace = H5Screate_simple(m_rank, col_dims, NULL);
+   hsize_t mem_offset[3];
+   mem_offset[0] = 0;
+   mem_offset[1] = 0;
+   mem_offset[2] = 0;
+   // int status =  H5Sselect_hyperslab(memspace, H5S_SELECT_SET, mem_offset, NULL, count, NULL);
+   H5Sselect_hyperslab(memspace, H5S_SELECT_SET, mem_offset, NULL, count, NULL);
+
+   ossim_int32 numValues = rect.width() * rect.height();
+   char* data = new char[m_dataSize * numValues];
+   // status = H5Dread(m_dataset_id, m_dataType, memspace, m_dataspace, H5P_DEFAULT, (void*)data);
+   H5Dread(m_dataset_id, m_dataType, memspace, m_dataspace, H5P_DEFAULT, (void*)data);   
+
+   H5Sclose(memspace);
+   return data;
+}
+
+ossim_uint32 ossimHdf5SubDataset::getNumberOfInputBands() const
+{
+   return m_numberOfBands;
+}
+
+ossimScalarType ossimHdf5SubDataset::getOutputScalarType() const
+{
+   return m_scalarType;
+}
+
+void ossimHdf5SubDataset::setSubdatasetName(const ossimString& name)
+{
+   m_dataset_name = name;
+}
+
+void ossimHdf5SubDataset::setHdfFilename(ossimString fileName)
+{
+   m_fileName = fileName;
+   open();
+}
+
+void ossimHdf5SubDataset::setOutputScalarType()
+{
+   if( H5Tequal(H5T_NATIVE_CHAR, m_dataType ) || H5Tequal(H5T_NATIVE_UCHAR,  m_dataType))
+   {
+      m_scalarType = OSSIM_UINT8;
+      m_dataSize = 1;
+   }
+   else if( H5Tequal( H5T_NATIVE_SHORT, m_dataType))
+   {
+      m_scalarType = OSSIM_SSHORT16;
+      m_dataSize = 2;
+   }
+   else if( H5Tequal( H5T_NATIVE_USHORT, m_dataType)) 
+   {
+      m_scalarType = OSSIM_UINT16;
+      m_dataSize = 2;
+   }
+   else if( H5Tequal(H5T_NATIVE_INT, m_dataType)) 
+   {
+      m_scalarType = OSSIM_SINT32;
+      m_dataSize = 4;
+   }  
+   else if( H5Tequal(H5T_NATIVE_UINT, m_dataType)) 
+   {
+      m_scalarType = OSSIM_UINT32;
+      m_dataSize = 4;
+   }
+   else if( H5Tequal(H5T_NATIVE_LONG, m_dataType)) 
+   {
+      if( sizeof(long) == 4 )
+      {
+         m_scalarType = OSSIM_SINT32;
+         m_dataSize = 4;
+      }
+   }
+   else if(H5Tequal(H5T_NATIVE_ULONG, m_dataType)) 
+   {
+      if( sizeof(unsigned long) == 4 )
+      {
+         m_scalarType = OSSIM_UINT32;
+         m_dataSize = 4;
+      }
+   }
+   else if( H5Tequal(H5T_NATIVE_FLOAT,  m_dataType)) 
+   {
+      m_scalarType = OSSIM_FLOAT32;
+      m_dataSize = 4;
+   }
+   else if( H5Tequal(H5T_NATIVE_DOUBLE, m_dataType)) 
+   {
+      m_scalarType = OSSIM_FLOAT64;
+      m_dataSize = 8;
+   }
+   else if( H5Tequal( H5T_NATIVE_LLONG, m_dataType) || H5Tequal( H5T_NATIVE_ULLONG, m_dataType )) 
+   {
+      m_scalarType = OSSIM_SCALAR_UNKNOWN;
+   }
+   else if( H5Tequal( H5T_NATIVE_DOUBLE, m_dataType)) 
+   {
+      m_scalarType = OSSIM_SCALAR_UNKNOWN;
+      m_dataSize = 8;
+   }
+}
+
+void ossimHdf5SubDataset::setMeta(const ossimString& key, const ossimString& value)
+{
+   ossimString meta = ossimString(key + ": " + value);
+   m_meta.push_back(meta);
+}
+
diff --git a/ossim_plugins/hdf/ossimHdf5SubDataset.h b/ossim_plugins/hdf/ossimHdf5SubDataset.h
new file mode 100644
index 0000000..1e68a17
--- /dev/null
+++ b/ossim_plugins/hdf/ossimHdf5SubDataset.h
@@ -0,0 +1,135 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Description:  Class declaration HDF reader.
+//
+// Specification: ISO/IEC 15444
+//
+//----------------------------------------------------------------------------
+// $Id: ossimHdf5SubDataset.h 2645 2011-05-26 15:21:34Z oscar.kramer $
+
+#ifndef ossimHdf5SubDataset_HEADER
+#define ossimHdf5SubDataset_HEADER 1
+
+//ossim includes
+#include "../ossimPluginConstants.h"
+#include <ossim/base/ossimIpt.h>
+#include <ossim/base/ossimIrect.h>
+#include <ossim/base/ossimRefPtr.h>
+#include <ossim/imaging/ossimImageHandler.h>
+
+//HDF4 Includes
+#include <hdf5.h>
+
+// Forward class declarations.
+class ossimImageData;
+
+class OSSIM_PLUGINS_DLL ossimHdf5SubDataset 
+{
+public:
+
+   /** default construtor */
+   ossimHdf5SubDataset();
+   
+   /** virtural destructor */
+   virtual ~ossimHdf5SubDataset();
+
+   /**
+    *  @brief Method to grab a tile(rectangle) from image.
+    *
+    *  @param rect The zero based rectangle to grab.
+    *
+    *  @param resLevel The reduced resolution level to grab from.
+    *
+    *  @return The ref pointer with the image data pointer.
+    */
+   char* getTileBuf(const  ossimIrect& rect, ossim_uint32 band);   
+
+   /**
+    *  Returns the number of bands in the image.
+    *  Satisfies pure virtual from ImageHandler class.
+    */
+   virtual ossim_uint32 getNumberOfInputBands() const;
+
+   /**
+    * Returns the output pixel type of the tile source.
+    */
+   virtual ossimScalarType getOutputScalarType() const;
+
+
+   /**
+    * @brief Gets number of lines for res level.
+    *
+    *  @param resLevel Reduced resolution level to return lines of.
+    *  Default = 0
+    *
+    *  @return The number of lines for specified reduced resolution level.
+    */
+   virtual ossim_uint32 getNumberOfLines(ossim_uint32 resLevel = 0) const;
+
+   /**
+    *  @brief Gets the number of samples for res level.
+    *
+    *  @param resLevel Reduced resolution level to return samples of.
+    *  Default = 0
+    *
+    *  @return The number of samples for specified reduced resolution level.
+    */
+   virtual ossim_uint32 getNumberOfSamples(ossim_uint32 resLevel = 0) const;
+
+   std::vector<ossimString> getMetadata() const { return m_meta; }
+
+   void setMeta(const ossimString& key, const ossimString& value);
+
+   /**
+    *  @brief Method to set sds name for dataset.
+    *
+    */
+   void setSubdatasetName(const ossimString& name); 
+
+   /**
+    * @brief Open method.
+    * @return true on success, false on error.
+    */
+   virtual bool open();
+
+   /**
+    *  @brief Method to set hdf file name for open file.
+    *
+    */
+   void setHdfFilename(ossimString fileName);
+
+   void setOutputScalarType();
+
+   void close();
+
+private:
+
+  bool initMeta();
+
+  ossimString                       m_fileName;
+  ossimString                       m_dataset_name;// name
+  hid_t                             m_fid;
+  hid_t                             m_dataset_id; //SDS selected id
+  ossim_int32                       m_rank;
+  hid_t                             m_native;
+  hid_t                             m_dataType;
+  hid_t                             m_dataspace;
+  size_t                            m_size;
+  ossim_int32                       m_dataSize;
+
+  ossim_uint32                      m_numberOfBands;
+  ossim_uint32                      m_numberOfSamples;
+  ossim_uint32                      m_numberOfLines;
+  ossimScalarType                   m_scalarType;
+  ossimString                       m_hdfDataType;
+  std::vector<ossimString>          m_meta;
+TYPE_DATA
+};
+
+#endif /* #ifndef ossimHdf5SubDataset_HEADER */
+
+
diff --git a/ossim_plugins/hdf/ossimHdfGridModel.cpp b/ossim_plugins/hdf/ossimHdfGridModel.cpp
new file mode 100644
index 0000000..c13adc6
--- /dev/null
+++ b/ossim_plugins/hdf/ossimHdfGridModel.cpp
@@ -0,0 +1,942 @@
+//*****************************************************************************
+// FILE: ossimHdfGridModel.cc
+//
+// License:  See LICENSE.txt file in the top level directory.
+//
+// AUTHOR: Mingjie Su
+//
+// DESCRIPTION:
+//   Contains implementation of class ossimHdfGridModel. This is an
+//   implementation of an interpolation sensor model. 
+//
+//   IMPORTANT: The lat/lon grid is for ground points on the ellipsoid.
+//   The dLat/dHgt and dLon/dHgt partials therefore are used against
+//   elevations relative to the ellipsoid.
+//
+//*****************************************************************************
+//  $Id: ossimHdfGridModel.cpp 2645 2011-05-26 15:21:34Z oscar.kramer $
+
+#include "ossimHdfGridModel.h"
+#include "ossimH5Util.h"
+
+#include <ossim/base/ossimCommon.h>
+#include <ossim/base/ossimEndian.h>
+#include <ossim/base/ossimException.h>
+#include <ossim/base/ossimTrace.h>
+
+#include <hdf.h>
+// Not in latest 4.2.9 code: #include <hdf4_netcdf.h>
+#include <mfhdf.h>
+#include <hdf5.h>
+#include <H5Cpp.h>
+
+#include <sstream>
+
+static ossimTrace traceDebug("ossimHdfGridModel:debug");
+
+RTTI_DEF1(ossimHdfGridModel, "ossimHdfGridModel", ossimCoarseGridModel);
+
+ossimHdfGridModel::ossimHdfGridModel()
+   :
+   ossimCoarseGridModel(),
+   m_isHdf4(false)
+{
+   theLatGrid.setDomainType(ossimDblGrid::SAWTOOTH_90);
+   theLonGrid.setDomainType(ossimDblGrid::WRAP_180);
+}
+
+//*****************************************************************************
+//  CONSTRUCTOR: ossimHdfGridModel(filename)
+//  
+//  Constructs model from geometry file
+//  
+//*****************************************************************************
+ossimHdfGridModel::ossimHdfGridModel(const ossimFilename& file,
+                                     const ossimDrect& imageRect,
+                                     ossimString latGridIndexOrName,
+                                     ossimString lonGridIndexOrName,
+                                     const ossimIpt& gridSpacing)
+   :  ossimCoarseGridModel(),
+   m_isHdf4(true)
+{
+   theLatGrid.setDomainType(ossimDblGrid::SAWTOOTH_90);
+   theLonGrid.setDomainType(ossimDblGrid::WRAP_180);
+
+   if (latGridIndexOrName.contains("/Latitude") == false && 
+       lonGridIndexOrName.contains("/Longitude") == false)//hdf4
+   {
+      ossim_int32 latGridIndex = ossimString::toInt(latGridIndexOrName);
+      ossim_int32 lonGridIndex = ossimString::toInt(lonGridIndexOrName);
+      ossim_int32 sd_id = SDstart(file.c_str(), DFACC_READ);
+      if (sd_id > 0)
+      {
+         ossim_int32 sds_id = SDselect(sd_id, latGridIndex);
+         if (sds_id > 0)
+         {
+            setGridNodes(theLatGrid, sds_id, gridSpacing);
+         }
+         SDendaccess (sds_id); 
+
+         sds_id = SDselect(sd_id, lonGridIndex);
+         if (sds_id > 0)
+         {
+            setGridNodes(theLonGrid, sds_id, gridSpacing);
+         }
+         SDendaccess (sds_id); 
+      }
+      SDend(sd_id);
+   }
+   else //hdf5
+   {
+      m_isHdf4 = false;
+      ossim_int32 file_id = H5Fopen(file.c_str(), H5F_ACC_RDONLY, H5P_DEFAULT);
+
+      // Depreciated, need to fix... (drb)
+      // ossim_int32 dataset_id = H5Dopen(file_id, latGridIndexOrName);
+      ossim_int32 dataset_id = H5Dopen1(file_id, latGridIndexOrName);
+      if (dataset_id >= 0)
+      {
+         setGridNodes(theLatGrid, dataset_id, gridSpacing);
+      }
+      H5Dclose(dataset_id);
+
+      // Depreciated, need to fix... (drb)
+      // dataset_id = H5Dopen(file_id, lonGridIndexOrName);
+      dataset_id = H5Dopen1(file_id, lonGridIndexOrName);      
+      if (dataset_id > 0)
+      {
+         setGridNodes(theLatGrid, dataset_id, gridSpacing);
+      }
+      H5Dclose(dataset_id);
+
+      H5Fclose(file_id);
+   }
+   
+
+   // Filter this HDF data as it is often very noisy:
+   double filter_kernel[81];
+   double weight = 1.0/81.0;
+   for (int i=0; i<81; i++)
+      filter_kernel[i] = weight;
+   theLatGrid.filter(9,9, filter_kernel);
+   theLonGrid.filter(9,9, filter_kernel);
+
+   theLatGrid.enableExtrapolation();
+   theLonGrid.enableExtrapolation();
+   theHeightEnabledFlag = false;
+   initializeModelParams(imageRect);
+   
+   //debugDump(); //###
+}
+
+ossimHdfGridModel::~ossimHdfGridModel()
+{
+}
+
+void ossimHdfGridModel::setGridNodes(ossimDblGrid& grid, ossim_int32 sds_id, const ossimIpt& spacing)
+{
+   int x=0, y=0;
+   ossim_uint32 index = 0;
+   if (m_isHdf4)
+   {
+      int32 dim_sizes[MAX_VAR_DIMS];
+      int32 rank, data_type, n_attrs;
+      char  name[MAX_NC_NAME];
+
+      ossim_int32 status = SDgetinfo(sds_id, name, &rank, dim_sizes, &data_type, &n_attrs);
+      if (status == -1)
+         return;
+
+      int32 origin[2] = {0, 0}; 
+      ossim_int32 num_rows = dim_sizes[0]; 
+      ossim_int32 num_cols = dim_sizes[1]; 
+
+      ossimDpt grid_origin(0,0); // The grid as used in base class, has UV-space always at 0,0 origin
+      ossimIpt grid_size (num_cols, num_rows);
+      ossimDpt dspacing (spacing);
+      grid.initialize(grid_size, grid_origin, dspacing);
+
+      float32* values = new float32 [num_rows * num_cols]; 
+      intn statusN = SDreaddata(sds_id, origin, NULL, dim_sizes, (VOIDP)values);
+      if (statusN > -1)
+      {
+         for (y = 0; y < num_rows; y++)
+         {
+            for (x = 0; x < num_cols; x++)
+            {
+               grid.setNode(x, y, values[index++]);
+            }
+         }
+      }
+      delete values;
+   }
+   else
+   {
+      hsize_t dims_out[2]; //dataset dimensions
+      hid_t datatype = H5Dget_type(sds_id);
+      hid_t dataspace = H5Dget_space(sds_id);    //dataspace handle
+      int rank = H5Sget_simple_extent_ndims(dataspace);
+      if (rank == 2)
+      {
+         H5Sget_simple_extent_dims(dataspace, dims_out, NULL);
+
+         ossim_int32 latGridRows = dims_out[0];
+         ossim_int32 lonGridCols = dims_out[1];
+
+         ossim_int32 cols = spacing.x;
+         ossim_int32 rows = spacing.y;
+
+         ossim_int32 spacingX = 0;
+         ossim_int32 spacingY = 0;
+
+         if (rows % latGridRows == 0 && cols % lonGridCols == 0)
+         {
+            spacingY = rows/latGridRows; //line increment step
+            spacingX = cols/lonGridCols; //pixel increment step
+         }
+         
+         ossimIpt gridSpacing(spacingX, spacingY);
+
+         ossimDpt grid_origin(0,0); // The grid as used in base class, has UV-space always at 0,0 origin
+         ossimIpt grid_size (cols, rows);
+         ossimDpt dspacing (gridSpacing);
+         grid.initialize(grid_size, grid_origin, dspacing);
+
+         if( H5Tequal(H5T_NATIVE_FLOAT,  datatype))
+         {
+            ossim_float32* data_out = new ossim_float32[dims_out[0] * dims_out[1]];
+            H5Dread(sds_id, datatype, dataspace, dataspace, H5P_DEFAULT, data_out);
+
+            index = 0;
+            for (y = 0; y < rows; y++)
+            {
+               for (x = 0; x < cols; x++)
+               {
+                  index = x + y * cols;
+
+                  //---
+                  // NPP VIIRS data has null of "-999.3".
+                  // Scan and fix non-standard null value.
+                  //---
+                  ossim_float32 d = data_out[index];
+                  if ( d < -999.0 )
+                  {
+                     d = ossim::nan();
+                  }
+                  grid.setNode(x, y, d);
+               }
+            }
+            delete[] data_out;
+         }
+         else if( H5Tequal(H5T_NATIVE_DOUBLE,  datatype))
+         {
+            ossim_float64* data_out = new ossim_float64[dims_out[0] * dims_out[1]];
+            H5Dread(sds_id, datatype, dataspace, dataspace, H5P_DEFAULT, data_out);
+
+            index = 0;
+            for (y = 0; y < rows; y++)
+            {
+               for (x = 0; x < cols; x++)
+               {
+                  index = x + y * cols;
+
+                  //---
+                  // NPP VIIRS data has null of "-999.3".
+                  // Scan and fix non-standard null value.
+                  //---
+                  ossim_float64 d = data_out[index];
+                  if ( d < -999.0 )
+                  {
+                     d = ossim::nan();
+                  }
+                  grid.setNode(x, y, d);
+               }
+            }
+            delete[] data_out;
+         }
+      }
+      H5Tclose(datatype);
+      H5Sclose(dataspace);
+   }
+}
+
+bool ossimHdfGridModel::setGridNodes( H5::H5File* h5File,
+                                      const std::string& latDataSetName,
+                                      const std::string& lonDataSetName,
+                                      ossim_uint32 imageRows,
+                                      ossim_uint32 imageCols )
+
+{
+   bool status = false;
+
+   if ( h5File )
+   {
+      H5::DataSet latDataSet = h5File->openDataSet( latDataSetName );
+      H5::DataSet lonDataSet = h5File->openDataSet( lonDataSetName );  
+
+      try
+      {
+         status = setGridNodes( &latDataSet, &lonDataSet, imageRows, imageCols );
+      }
+      catch ( const ossimException& e )
+      {
+         if ( traceDebug() )
+         {
+            ossimNotify(ossimNotifyLevel_WARN)
+               << "ossimHdfGridModel::setGridNodes caught exception\n"
+               << e.what() << std::endl;
+         }
+      }
+
+      latDataSet.close();
+      lonDataSet.close();
+   }
+   
+   return status;
+}
+
+bool ossimHdfGridModel::setGridNodes( H5::DataSet* latDataSet,
+                                      H5::DataSet* lonDataSet,
+                                      ossim_uint32 imageRows,
+                                      ossim_uint32 imageCols )
+{
+   bool status = false;
+
+   if ( latDataSet && lonDataSet )
+   {
+      const ossim_uint32 GRID_SIZE = 32; // Only grab every 32nd value.
+
+      // Get dataspace of the dataset.
+      H5::DataSpace latDataSpace = latDataSet->getSpace();
+      H5::DataSpace lonDataSpace = lonDataSet->getSpace();
+      const ossim_int32 LAT_DIM_COUNT = latDataSpace.getSimpleExtentNdims();
+      const ossim_int32 LON_DIM_COUNT = latDataSpace.getSimpleExtentNdims();
+      
+      // Number of dimensions of the input dataspace:
+      if ( ( LAT_DIM_COUNT == 2 ) && ( LON_DIM_COUNT == 2 ) )
+      {
+         //---
+         // Get the extents:
+         // dimsOut[0] is height, dimsOut[1] is width:         //---
+         std::vector<hsize_t> latDimsOut(LAT_DIM_COUNT);
+         latDataSpace.getSimpleExtentDims( &latDimsOut.front(), 0 );
+         std::vector<hsize_t> lonDimsOut(LON_DIM_COUNT);
+         lonDataSpace.getSimpleExtentDims( &lonDimsOut.front(), 0 );
+         
+         // Verify same as image:
+         if ( (latDimsOut[0] == imageRows) &&
+              (lonDimsOut[0] == imageRows) &&
+              (latDimsOut[1] == imageCols) &&
+              (lonDimsOut[1] == imageCols) )
+         {
+            //---
+            // Capture the rectangle:
+            // dimsOut[0] is height, dimsOut[1] is width:
+            //---
+            ossimIrect rect = ossimIrect( 0, 0,
+                                          static_cast<ossim_int32>( latDimsOut[1]-1 ),
+                                          static_cast<ossim_int32>( latDimsOut[0]-1 ) );
+            
+            //----
+            // Initialize the ossimDblGrids:
+            //---
+            ossimDpt dspacing (GRID_SIZE, GRID_SIZE);
+            
+            ossim_uint32 gridRows = imageRows / GRID_SIZE + 1;
+            ossim_uint32 gridCols = imageCols / GRID_SIZE + 1;
+            
+            // Round up if size doesn't fall on end pixel.
+            if ( imageRows % GRID_SIZE) ++gridRows;
+            if ( imageCols % GRID_SIZE) ++gridCols;
+            
+            ossimIpt gridSize (gridCols, gridRows);
+            
+            // The grid as used in base class, has UV-space always at 0,0 origin            
+            ossimDpt gridOrigin(0.0,0.0);
+
+            const ossim_float64 NULL_VALUE = -999.0;
+            theLatGrid.setNullValue(ossim::nan());
+            theLonGrid.setNullValue(ossim::nan());
+            theLatGrid.initialize(gridSize, gridOrigin, dspacing);
+            theLonGrid.initialize(gridSize, gridOrigin, dspacing);            
+            
+            std::vector<hsize_t> inputCount(LAT_DIM_COUNT);
+            std::vector<hsize_t> inputOffset(LAT_DIM_COUNT);
+            
+            inputOffset[0] = 0; // row
+            inputOffset[1] = 0; // col
+            
+            inputCount[0] = 1; // row
+            inputCount[1] = (hsize_t)imageCols; // col
+            
+            // Output dataspace dimensions. Reading a line at a time.
+            const ossim_int32 OUT_DIM_COUNT = 3;
+            std::vector<hsize_t> outputCount(OUT_DIM_COUNT);
+            outputCount[0] = 1; // band
+            outputCount[1] = 1; // row
+            outputCount[2] = imageCols; // col
+            
+            // Output dataspace offset.
+            std::vector<hsize_t> outputOffset(OUT_DIM_COUNT);
+            outputOffset[0] = 0;
+            outputOffset[1] = 0;
+            outputOffset[2] = 0;
+            
+            ossimScalarType scalar = ossim_hdf5::getScalarType( latDataSet );
+            if ( scalar == OSSIM_FLOAT32 )
+            {
+               // Set the return status to true if we get here...
+               status = true;
+               
+               // See if we need to swap bytes:
+               ossimEndian* endian = 0;
+               if ( ( ossim::byteOrder() != ossim_hdf5::getByteOrder( latDataSet ) ) )
+               {
+                  endian = new ossimEndian();
+               }
+               
+               // Native type:
+               H5::DataType latDataType = latDataSet->getDataType();
+               H5::DataType lonDataType = lonDataSet->getDataType();
+
+               // Output dataspace always the same, width of one line.
+               H5::DataSpace bufferDataSpace( OUT_DIM_COUNT, &outputCount.front());
+               bufferDataSpace.selectHyperslab( H5S_SELECT_SET,
+                                                &outputCount.front(),
+                                                &outputOffset.front() );
+
+               //  Arrays to hold a single line of latitude longitude values.
+               vector<ossim_float32> latValue(imageCols);
+               vector<ossim_float32> lonValue(imageCols);
+               hsize_t row = 0;
+
+               // Line loop:
+               for ( ossim_uint32 y = 0; y < gridRows; ++y )
+               {
+                  // row = line in image space
+                  row = y*GRID_SIZE;
+
+                  bool hitNans = false;
+                  
+                  if ( row < imageRows )
+                  {
+                     inputOffset[0] = row;
+
+                     latDataSpace.selectHyperslab( H5S_SELECT_SET,
+                                                   &inputCount.front(),
+                                                   &inputOffset.front() );
+                     lonDataSpace.selectHyperslab( H5S_SELECT_SET,
+                                                   &inputCount.front(),
+                                                   &inputOffset.front() );
+                  
+                     // Read data from file into the buffer.
+                     latDataSet->read( &(latValue.front()), latDataType,
+                                       bufferDataSpace, latDataSpace );
+                     lonDataSet->read( &(lonValue.front()), lonDataType,
+                                       bufferDataSpace, lonDataSpace );
+                  
+                     if ( endian )
+                     {
+                        // If the endian pointer is initialized(not zero) swap the bytes.
+                        endian->swap( &(latValue.front()), imageCols );
+                        endian->swap( &(lonValue.front()), imageCols );  
+                     }
+                  
+                     // Sample loop:
+                     hsize_t col = 0;
+                     
+                     for ( ossim_uint32 x = 0; x < gridCols; ++x )
+                     {
+                        ossim_float32 lat = ossim::nan();
+                        ossim_float32 lon = ossim::nan();
+                        
+                        // col = sample in image space
+                        col = x*GRID_SIZE;
+
+                        if ( col < imageCols )
+                        {
+                           if ( (latValue[col] > NULL_VALUE)&&(lonValue[col] > NULL_VALUE) )
+                           {
+                              lat = latValue[col];
+                              lon = lonValue[col];
+                           }
+                           else
+                           {
+                              hitNans = true;
+                           }
+                        }
+                        else // Last column is outside of image bounds.
+                        {
+                           ossim_float32 latSpacing = ossim::nan();
+                           ossim_float32 lonSpacing = ossim::nan();
+
+                           // Get the last two latitude values:
+                           ossim_float32 lat1 = latValue[imageCols-2];
+                           ossim_float32 lat2 = latValue[imageCols-1];
+                           
+                           // Get the last two longitude values
+                           ossim_float32 lon1 = lonValue[imageCols-2];
+                           ossim_float32 lon2 = lonValue[imageCols-1];
+
+                           if ( ( lat1 > NULL_VALUE ) && ( lat2 > NULL_VALUE ) )
+                           {
+                              // Delta between last two latitude values.
+                              latSpacing = lat2 - lat1;
+                           
+                              // Compute:
+                              lat = lat2 + ( col - (imageCols-1) ) * latSpacing;
+                           }
+                           else
+                           {
+                              hitNans = true;
+                           }
+
+                           if ( ( lon1 > NULL_VALUE ) && ( lon2 > NULL_VALUE ) )
+                           {
+                              // Consider dateline crossing.
+                              if ( (lon1 > 0.0) && ( lon2 < 0.0 ) )
+                              {
+                                 lon2 += 360.0;
+                              }
+                           
+                              // Delta between last two longitude values.
+                              lonSpacing = lon2 - lon1;
+                           
+                              // Compute:
+                              lon = lon2 + ( col - (imageCols-1) ) * lonSpacing;
+
+                              // Check for wrap:
+                              if ( lon > 180 )
+                              {
+                                 lon -= 360.0;
+                              }
+                           }
+                           else
+                           {
+                              hitNans = true;
+                           }
+
+#if 0 /* Please leave for debug. (drb) */                        
+                           cout << "lat1: " << lat1 << " lat2 " << lat2
+                                << " lon1 " << lon1  << " lon2 " << lon2
+                                << "\n";
+#endif
+                        }
+
+                        if ( hitNans )
+                        {
+                           std::string errMsg =
+                              "ossimHdfGridModel::setGridNodes encountered nans!";
+                           throw ossimException(errMsg);
+                        }
+                        
+                        // Assign the latitude and longitude.
+                        theLatGrid.setNode( x, y, lat );
+                        theLonGrid.setNode( x, y, lon );
+                        
+#if 0 /* Please leave for debug. (drb) */ 
+                        cout << "x,y,col,row,lat,lon:" << x << "," << y << ","
+                             << col << "," << row << ","
+                             << theLatGrid.getNode(x, y)
+                             << "," << theLonGrid.getNode( x, y) << "\n";
+#endif
+                     
+                     } // End sample loop.
+                     
+                  }
+                  else // Row is outside of image bounds:
+                  {
+                     // Read the last two rows in.
+                     vector<ossim_float32> latValue2(imageCols);
+                     vector<ossim_float32> lonValue2(imageCols);
+
+                     inputOffset[0] = imageRows-2; // 2nd to last line
+
+                     latDataSpace.selectHyperslab( H5S_SELECT_SET,
+                                                   &inputCount.front(),
+                                                   &inputOffset.front() );
+                     lonDataSpace.selectHyperslab( H5S_SELECT_SET,
+                                                   &inputCount.front(),
+                                                   &inputOffset.front() );
+                  
+                     // Read data from file into the buffer.
+                     latDataSet->read( &(latValue.front()), latDataType,
+                                       bufferDataSpace, latDataSpace );
+                     lonDataSet->read( &(lonValue.front()), lonDataType,
+                                       bufferDataSpace, lonDataSpace );
+                  
+                     inputOffset[0] = imageRows-1; // last line
+
+                     latDataSpace.selectHyperslab( H5S_SELECT_SET,
+                                                   &inputCount.front(),
+                                                   &inputOffset.front() );
+                     lonDataSpace.selectHyperslab( H5S_SELECT_SET,
+                                                   &inputCount.front(),
+                                                   &inputOffset.front() );
+                  
+                     // Read data from file into the buffer.
+                     latDataSet->read( &(latValue2.front()), latDataType,
+                                       bufferDataSpace, latDataSpace );
+                     lonDataSet->read( &(lonValue2.front()), lonDataType,
+                                       bufferDataSpace, lonDataSpace );
+                  
+                     if ( endian )
+                     {
+                        // If the endian pointer is initialized(not zero) swap the bytes.
+                        endian->swap( &(latValue.front()), imageCols );
+                        endian->swap( &(lonValue.front()), imageCols );
+                        endian->swap( &(latValue2.front()), imageCols );
+                        endian->swap( &(lonValue2.front()), imageCols );  
+                     }
+
+                     // Sample loop:
+                     hsize_t col = 0;
+                     for ( ossim_uint32 x = 0; x < gridCols; ++x )
+                     {
+                        col = x*GRID_SIZE; // Sample in image space.
+                     
+                        ossim_float32 lat        = ossim::nan();
+                        ossim_float32 lat1       = ossim::nan();
+                        ossim_float32 lat2       = ossim::nan();
+                        ossim_float32 latSpacing = ossim::nan();
+                        ossim_float32 lon        = ossim::nan();
+                        ossim_float32 lon1       = ossim::nan();
+                        ossim_float32 lon2       = ossim::nan();
+                        ossim_float32 lonSpacing = ossim::nan();
+                     
+                        if ( col < imageCols )
+                        {
+                           lat1 = latValue[col];
+                           lat2 = latValue2[col];
+                           lon1 = lonValue[col];
+                           lon2 = lonValue2[col];
+                        }
+                        else // Very last grid point.
+                        {
+                           // Compute the missing column for the last two image lines:
+                           lat1 = latValue[imageCols-1] + ( col - (imageCols-1)) *
+                              ( latValue[imageCols-1] - latValue[imageCols-2] );
+
+                           lat2 = latValue2[imageCols-1] + ( col - (imageCols-1)) *
+                              ( latValue2[imageCols-1] - latValue2[imageCols-2] );
+
+                           lon1 = lonValue[imageCols-1] + ( col - (imageCols-1)) *
+                              ( lonValue[imageCols-1] - lonValue[imageCols-2] );
+
+                           lon2 = lonValue2[imageCols-1] + ( col - (imageCols-1)) *
+                              ( lonValue2[imageCols-1] - lonValue2[imageCols-2] );
+                        }
+
+#if 0 /* Please leave for debug. (drb) */
+                        cout << "lat1: " << lat1 << " lat2 " << lat2
+                             << " lon1 " << lon1  << " lon2 " << lon2
+                             << "\n";
+#endif
+
+                        if ( ( lon1 > NULL_VALUE ) && ( lon2 > NULL_VALUE ) )
+                        {
+                           // Consider dateline crossing.
+                           if ( (lon1 > 0.0) && ( lon2 < 0.0 ) )
+                           {
+                              lon2 += 360.0;
+                           }
+                        
+                           // Delta between last two longitude values.
+                           lonSpacing = lon2 - lon1;
+                        
+                           // Compute:
+                           lon = lon2 + ( row - (imageRows-1) ) * lonSpacing;
+
+                           // Check for wrap:
+                           if ( lon > 180 )
+                           {
+                              lon -= 360.0;
+                           }
+                        }
+                        else
+                        {
+                           hitNans = true;
+                        }
+                     
+                        if ( ( lat1 > NULL_VALUE ) && ( lat2 > NULL_VALUE ) )
+                        {
+                           // Delta between last two latitude values.
+                           latSpacing = lat2 - lat1;
+                        
+                           // Compute:
+                           lat = lat2 + ( row - (imageRows-1) ) * latSpacing;
+                        }
+                        else
+                        {
+                           hitNans = true;
+                        }
+
+                        if ( hitNans )
+                        {
+                           std::string errMsg =
+                              "ossimHdfGridModel::setGridNodes encountered nans!";
+                           throw ossimException(errMsg);
+                        }
+
+                        // Assign the latitude::
+                        theLatGrid.setNode( x, y, lat );
+
+                        // Assign the longitude.
+                        theLonGrid.setNode( x, y, lon );
+
+#if 0 /* Please leave for debug. (drb) */
+                        cout << "x,y,col,row,lat,lon:" << x << "," << y << ","
+                             << col << "," << row << "," << lat << "," << lon << "\n";
+#endif
+                     
+                     } // End sample loop.
+                  
+                  } // Matches if ( row < imageRows ){...}else{
+                  
+               } // End line loop.
+
+               latDataSpace.close();
+               lonDataSpace.close();
+
+               if ( status )
+               {
+                  theLatGrid.enableExtrapolation();
+                  theLonGrid.enableExtrapolation();
+                  theHeightEnabledFlag = false;
+                  ossimDrect imageRect(rect);
+                  initializeModelParams(imageRect);
+                  // debugDump();
+               }
+               
+            } // Matches: if ( scalar == OSSIM_FLOAT32 )
+            
+         } // Matches: if ( (latDimsOut[0] == imageRows) ...
+         
+      } // Matches: if ( ( LAT_DIM_COUNT == 2 ) ...
+
+   } // Matches: if ( latDataSet && lonDataSet
+   
+   return status;
+   
+} // End: bool ossimHdfGridModel::setGridNodes( H5::DataSet* latDataSet, ... )
+
+bool ossimHdfGridModel::saveState(ossimKeywordlist& kwl, const char* prefix) const
+{
+   bool status = ossimCoarseGridModel::saveState( kwl, prefix );
+   if ( status )
+   {
+      std::string myPrefix = ( prefix ? prefix: "" );
+
+      // Add the is hdf4 flag:
+      std::string key = "is_hdf4";
+      std::string value = ossimString::toString( m_isHdf4 ).string();
+      kwl.addPair( myPrefix, key, value, true );
+      
+      if ( getWktFootprint( value ) )
+      {   
+         std::string key = "wkt_footprint";
+         kwl.addPair( myPrefix, key, value, true );
+      }
+   }
+   return status;
+}     
+
+bool ossimHdfGridModel::loadState(const ossimKeywordlist& kwl, const char* prefix)
+{
+   bool result = false;
+   
+   std::string myPrefix = ( prefix ? prefix: "" );
+
+   // Look for type key:
+   std::string typeKey = "type";
+   std::string value = kwl.findKey( myPrefix, typeKey );
+   if ( value == "ossimHdfGridModel" )
+   {
+      // Look for "is_hdf4" key:
+      std::string key   = "is_hdf4";
+      value = kwl.findKey( myPrefix, key );
+      if ( value.size() )
+      {
+         m_isHdf4 = ossimString(value).toBool();
+      }
+      
+      // Make a copy of kwl so we can change type.
+      ossimKeywordlist myKwl = kwl;
+      value = "ossimCoarseGridModel";
+      myKwl.addPair( myPrefix, typeKey, value, true );
+
+      // Load the state of base class.
+      result = ossimCoarseGridModel::loadState( myKwl, prefix );
+   }
+   
+   return result;                    
+}
+
+bool ossimHdfGridModel::getWktFootprint( std::string& s ) const
+{
+   bool status = true;
+
+   // Loop until complete or a "nan" is hit.
+   while ( 1 )
+   {
+      ossim_float32 lat = 0.0;
+      ossim_float32 lon = 0.0;
+
+      std::ostringstream os;
+
+      os <<  setprecision(10) << "POLYGON((";
+      const ossim_int32 STEP = 128;
+      
+      ossimIrect rect( 0, 0, theImageSize.x-1, theImageSize.y-1 );  
+
+      ossim_int32 x = 0;
+      ossim_int32 y = 0;
+      
+      // Walk the top line:
+      while ( x < theImageSize.x )
+      {
+         lat = theLatGrid( x, y );
+         lon = theLonGrid( x, y );
+
+         if ( ossim::isnan(lat) || ossim::isnan(lon) )
+         {
+            status = false;
+            break;
+         }
+         
+         os << lon << " " << lat << ",";
+         
+         if ( x != rect.ur().x )
+         {
+            x = ossim::min<ossim_int32>( x+STEP, rect.ur().x );
+         }
+         else
+         {
+            break; // End of top line walk.
+         }
+      }
+
+      if ( !status ) break; // Found "nan" so get out.
+      
+      // Walk the right edge:
+      y = ossim::min<ossim_int32>( y+STEP, rect.lr().y );
+      while ( y < theImageSize.y )
+      {
+         lat = theLatGrid( x, y );
+         lon = theLonGrid( x, y );
+
+         if ( ossim::isnan(lat) || ossim::isnan(lon) )
+         {
+            status = false;
+            break;
+         }
+
+         os << lon << " " << lat << ",";
+         
+         if ( y != rect.lr().y )
+         {
+            y = ossim::min<ossim_int32>( y+STEP, rect.lr().y );
+         }
+         else
+         {
+            break;
+         }
+      }
+
+      if ( !status ) break; // Found "nan" so get out.
+      
+      // Walk the bottom line from right to left:
+      x = ossim::max<ossim_int32>( rect.lr().x-STEP, 0 );
+      while ( x >= 0 )
+      {
+         lat = theLatGrid( x, y );
+         lon = theLonGrid( x, y );
+         
+         if ( ossim::isnan(lat) || ossim::isnan(lon) )
+         {
+            status = false;
+            break;
+         }
+
+         os << lon << " " << lat << ",";
+         
+         if ( x != 0 )
+         {
+            x = ossim::max<ossim_int32>( x-STEP, 0 );
+         }
+         else
+         {
+            break;
+         }
+      }
+
+      if ( !status ) break; // Found "nan" so get out.
+      
+      // Walk the left edge from bottom to top:
+      y = ossim::max<ossim_int32>( y-STEP, 0 );
+      while ( y >= 0 )
+      {
+         lat = theLatGrid( x, y );
+         lon = theLonGrid( x, y );
+
+         if ( ossim::isnan(lat) || ossim::isnan(lon) )
+         {
+            status = false;
+            break;
+         }
+
+         if ( ( x == 0 ) && ( y == 0 ) )
+         {
+            os << lon << " " << lat; // Last point:
+         }
+         else
+         {
+            os << lon << " " << lat << ",";
+         }
+         
+         if ( y != 0 )
+         {
+            y = ossim::max<ossim_int32>( y-STEP, 0 );
+         }
+         else
+         {
+            break;
+         }
+      }
+
+      if ( !status ) break; // Found "nan" so get out.
+      
+      os << "))";
+      s = os.str();
+
+      // Trailing break from while ( FOREVER ) loop:
+      break;
+      
+   } // Matches: while ( 1 )
+   
+   return status;
+}
+
+void ossimHdfGridModel::debugDump()
+{
+   ossimIpt step (theImageSize/200);
+   int margin = 0;
+   double lat, lon;
+   ossimDpt pt (0,0);
+   ofstream fslat ("lat_grid.dat");
+   ofstream fslon ("lon_grid.dat");
+   fslat<< setprecision(10) <<endl;
+   fslon<< setprecision(10) <<endl;
+   for (pt.v = -margin*step.v; pt.v < theImageSize.v+margin*step.v; pt.v += step.y)
+   {
+      for (pt.u = -margin*step.u; pt.u < theImageSize.u+margin*step.u ; pt.u += step.u)
+      {
+         lat = theLatGrid(pt.u, pt.v);
+         lon = theLonGrid(pt.u, pt.v);
+         fslat << pt.u << " " << pt.v << " " << lat << endl;
+         fslon << pt.u << " " << pt.v << " " << lon << endl;
+      }
+   }
+   fslat.close();
+   fslon.close();
+}
diff --git a/ossim_plugins/hdf/ossimHdfGridModel.h b/ossim_plugins/hdf/ossimHdfGridModel.h
new file mode 100644
index 0000000..3dc0749
--- /dev/null
+++ b/ossim_plugins/hdf/ossimHdfGridModel.h
@@ -0,0 +1,132 @@
+//*****************************************************************************
+// FILE: ossimHdfGridModel.h
+//
+// Copyright (C) 2001 ImageLinks, Inc.
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// AUTHOR: Mingjie Su
+//
+// DESCRIPTION:
+//   Contains declaration of class ossimHdfGridModel. This is an
+//   implementation of an interpolation sensor model.
+//
+//*****************************************************************************
+//  $Id: ossimHdfGridModel.h 2645 2011-05-26 15:21:34Z oscar.kramer $
+
+#ifndef ossimHdfGridModel_HEADER
+#define ossimHdfGridModel_HEADER 1
+
+#include <ossim/projection/ossimCoarseGridModel.h>
+#include "../ossimPluginConstants.h"
+
+#include <string>
+
+//HDF4 Includes
+// #include <hdf/hdf.h>
+// #include <hdf/mfhdf.h>
+// #include <hdf.h>
+// #include <mfhdf.h>
+
+//HDF5 Includes
+// #include <hdf5.h>
+
+// Forward class declarations:
+namespace H5
+{
+   class DataSet;
+   class H5File;
+}
+
+
+/******************************************************************************
+ *
+ * CLASS:  ossimHdfGridModel
+ *
+ *****************************************************************************/
+
+
+
+class OSSIM_PLUGINS_DLL ossimHdfGridModel : public ossimCoarseGridModel
+{
+public:
+
+   /** @brief default constructor. */
+   ossimHdfGridModel();
+   
+    //! CONSTRUCTOR (filename) Accepts name of hdf file and the index of SDS data
+   ossimHdfGridModel(const ossimFilename& file, 
+                    const ossimDrect& imageRect,
+                    ossimString latGridIndexOrName, 
+                    ossimString lonGridIndexOrName, 
+                    const ossimIpt& gridSpacing);
+
+   /** @brief virtual destructor */
+   virtual ~ossimHdfGridModel();
+
+   /**
+    * @brief Initializes the latitude and longitude ossimDblGrids from file.
+    * @param h5File Pointer to file.
+    * @param latDataSetName e.g. /All_Data/VIIRS-DNB-GEO_All/Latitude
+    * @param lonDataSetName e.g. /All_Data/VIIRS-DNB-GEO_All/Longitude
+    * @param imageRows Number of lines in the image.
+    * @param imageCols Number of samples in the image.
+    * @return true on success, false on error.
+    */
+   bool setGridNodes( H5::H5File* h5File,
+                      const std::string& latDataSetName,
+                      const std::string& lonDataSetName,
+                      ossim_uint32 imageRows,
+                      ossim_uint32 imageCols );
+
+   /**
+    * @brief Initializes the latitude and longitude ossimDblGrids from file.
+    * @param latDataSet H5::DataSet* to layer,
+    *    e.g. /All_Data/VIIRS-DNB-GEO_All/Latitude
+    * @param lonDataSet H5::DataSet* to layer,
+    *    e.g. /All_Data/VIIRS-DNB-GEO_All/Longitude
+    * @param imageRows Number of lines in the image.
+    * @param imageCols Number of samples in the image.
+    * @return true on success, false on error.
+    *
+    * This can throw an ossimException on nans.
+    */
+   bool setGridNodes( H5::DataSet* latDataSet,
+                      H5::DataSet* lonDataSet,
+                      ossim_uint32 imageRows,
+                      ossim_uint32 imageCols );
+
+   /**
+    * @brief saveState Saves state of object to a keyword list.
+    * @param kwl Initialized by this.
+    * @param prefix E.g. "image0.geometry.projection."
+    * @return true on success, false on error.
+    */
+   virtual bool saveState(ossimKeywordlist& kwl, const char* prefix=0) const;
+
+   /**
+    * @brief loadState Loads state of object from a keyword list.
+    * @param kwl Keyword list to initialize from.
+    * @param prefix E.g. "image0.geometry.projection."
+    * @return true on success, false on error.
+    */
+   virtual bool loadState(const ossimKeywordlist& kwl, const char* prefix=0);
+   
+private:
+   
+   void setGridNodes(ossimDblGrid& grid, ossim_int32 sds_id, const ossimIpt& spacing);
+
+   bool getWktFootprint( std::string& s ) const;
+   
+   void debugDump();
+   
+
+   bool m_isHdf4;
+
+   TYPE_DATA
+};
+
+#endif
+
diff --git a/ossim_plugins/hdf/ossimHdfInfo.cpp b/ossim_plugins/hdf/ossimHdfInfo.cpp
new file mode 100644
index 0000000..027c27a
--- /dev/null
+++ b/ossim_plugins/hdf/ossimHdfInfo.cpp
@@ -0,0 +1,171 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author:  Mingjie Su
+//
+// Description: Hdf Info object.
+// 
+//----------------------------------------------------------------------------
+// $Id: ossimHdfInfo.cpp 2645 2011-05-26 15:21:34Z oscar.kramer $
+
+//ossim includes
+#include "ossimHdfInfo.h"
+#include <ossim/base/ossimNotify.h>
+#include <ossim/base/ossimTrace.h>
+#include <ossim/base/ossimKeywordlist.h>
+
+// Static trace for debugging
+static ossimTrace traceDebug("ossimHdfInfo:debug");
+
+ossimHdfInfo::ossimHdfInfo()
+: ossimInfoBase(),
+theFile(),
+m_hdf4Reader(0),
+m_driverName()
+{
+}
+
+ossimHdfInfo::~ossimHdfInfo()
+{
+   if (m_hdf4Reader.valid())
+   {
+      m_hdf4Reader = 0;
+   }
+   if (m_hdf5Reader.valid())
+   {
+      m_hdf5Reader = 0;
+   }
+   m_metaInfos.clear();
+   std::map<ossim_uint32, std::vector<ossimString> >::iterator it = m_subMetaInfos.begin();
+   while (it != m_subMetaInfos.end())
+   {
+      it->second.clear();
+      it++;
+   }
+   m_subMetaInfos.clear();
+}
+
+bool ossimHdfInfo::open(const ossimFilename& file)
+{
+   static const char MODULE[] = "ossimHdfInfo::open";
+   if (traceDebug())
+   {    
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " entered...\n"
+         << "file: " << file << "\n";
+   }
+
+   bool result = false;
+
+   ossimString ext = file.ext();
+   ext.downcase();
+
+   if ( ext == "hdf" || ext == "h4" || ext == "hdf4" || 
+      ext == "he4" || ext == "hdf5" || ext == "he5" || ext == "h5" || 
+      ext == "l1r")
+   {
+      m_metaInfos.clear();
+      m_bandVector.clear();
+
+      m_hdf4Reader = new ossimHdf4Reader;
+      m_hdf4Reader->setFilename(file);
+
+      if ( m_hdf4Reader->open() )
+      {
+         m_metaInfos = m_hdf4Reader->getGlobalMeta();
+
+         ossim_uint32 entryNum = m_hdf4Reader->getNumberOfEntries();
+         for (ossim_uint32 i = 0; i < entryNum; i++)
+         {
+            m_hdf4Reader->setCurrentEntry(i);
+            m_bandVector.push_back(m_hdf4Reader->getNumberOfOutputBands());
+            m_subMetaInfos[i] = m_hdf4Reader->getSubDatasetMeta();
+         }
+         m_driverName = "hdf4";
+         theFile = file;
+         result = true;
+      }
+      else
+      {
+         m_hdf4Reader = 0;
+      }
+
+      //try hdf5 reader
+      if (m_hdf4Reader == 0)
+      {
+         m_hdf5Reader = new ossimHdf5Reader;
+         m_hdf5Reader->setFilename(file);
+         if (m_hdf5Reader->open())
+         {
+            m_driverName = "hdf5";
+            m_metaInfos = m_hdf5Reader->getGlobalMeta();
+
+            ossim_uint32 entryNum = m_hdf5Reader->getNumberOfEntries();
+            for (ossim_uint32 i = 0; i < entryNum; i++)
+            {
+               m_hdf5Reader->setCurrentEntry(i);
+               m_bandVector.push_back(m_hdf5Reader->getNumberOfOutputBands());
+               m_subMetaInfos[i] = m_hdf5Reader->getSubDatasetMeta();
+            }
+            theFile = file;
+            result = true;
+         }
+      }
+   }
+
+   if (traceDebug())
+   {    
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " exit status = " << (result?"true\n":"false\n");
+   }
+
+   return result;
+}
+
+std::ostream& ossimHdfInfo::print(std::ostream& out) const
+{
+   static const char MODULE[] = "ossimHdfInfo::print";
+   if (traceDebug())
+   {    
+      ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " entered...\n";
+   }
+
+   //display global meta first
+   ossimString prefix = ossimString(m_driverName + ".").downcase();
+   for (ossim_uint32 i = 0; i < m_metaInfos.size(); i++)
+   {
+      out << prefix << m_metaInfos[i] << "\n";
+   }
+
+   ossim_uint32 index = 0;
+   std::map<ossim_uint32, std::vector<ossimString> >::const_iterator it = m_subMetaInfos.begin();
+   while (it != m_subMetaInfos.end())
+   {
+      ossimString imagePrefix = prefix + "image" + ossimString::toString(index) + ".";
+      std::vector<ossimString> subMeta = it->second;
+      ossim_uint32 numOfBands = m_bandVector[index];
+      for (ossim_uint32 i = 0; i < numOfBands; i++)
+      {
+         ossimString bandPrefix = "band" + ossimString::toString(i) + ".";
+         ossimString prefixStr = imagePrefix + bandPrefix;
+         for (ossim_uint32 j = 0; j < subMeta.size(); j++)
+         {
+            out << prefixStr << subMeta[j] << "\n";
+         }
+      }
+      index++;
+      it++;
+   }
+
+   if (traceDebug())
+   {    
+      ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " exited...\n";
+   }
+
+   return out;
+}
+
+
diff --git a/ossim_plugins/hdf/ossimHdfInfo.h b/ossim_plugins/hdf/ossimHdfInfo.h
new file mode 100644
index 0000000..f987b84
--- /dev/null
+++ b/ossim_plugins/hdf/ossimHdfInfo.h
@@ -0,0 +1,68 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author:  Mingjie Su
+//
+// Description: Info object for HDF data.
+// 
+//----------------------------------------------------------------------------
+// $Id: ossimHdfInfo.h 2645 2011-05-26 15:21:34Z oscar.kramer $
+#ifndef ossimHdfInfo_HEADER
+#define ossimHdfInfo_HEADER
+
+#include <ossim/base/ossimConstants.h>
+#include <ossim/base/ossimRefPtr.h>
+#include <ossim/support_data/ossimInfoBase.h>
+#include <ossim/base/ossimFilename.h>
+#include "ossimHdf4Reader.h"
+#include "ossimHdf5Reader.h"
+
+/**
+ * @brief HDF info class.
+ *
+ * Encapsulates the HDF functionality.
+ */
+class ossimHdfInfo : public ossimInfoBase
+{
+public:
+   
+   /** default constructor */
+   ossimHdfInfo();
+   
+   /** virtual destructor */
+   virtual ~ossimHdfInfo();
+   
+   /**
+    * @brief open method.
+    *
+    * @param file File name to open.
+    * @return true on success false on error.
+    */
+   virtual bool open(const ossimFilename& file);
+   
+   /**
+    * Print method.
+    *
+    * @param out Stream to print to.
+    * 
+    * @return std::ostream&
+    */
+   virtual std::ostream& print(std::ostream& out) const;
+   
+private: 
+   
+   ossimFilename                                     theFile;
+   ossimRefPtr<ossimHdf4Reader>                      m_hdf4Reader;
+   ossimRefPtr<ossimHdf5Reader>                      m_hdf5Reader;
+   ossimString                                       m_driverName;
+   std::vector<ossimString>                          m_metaInfos;
+   std::map<ossim_uint32, std::vector<ossimString> > m_subMetaInfos;
+   std::vector<ossim_uint32>                         m_bandVector;
+};
+
+#endif /* End of "#ifndef ossimHdfInfo_HEADER" */
+
+
diff --git a/ossim_plugins/hdf/ossimHdfInfoFactory.cpp b/ossim_plugins/hdf/ossimHdfInfoFactory.cpp
new file mode 100644
index 0000000..886b68b
--- /dev/null
+++ b/ossim_plugins/hdf/ossimHdfInfoFactory.cpp
@@ -0,0 +1,68 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author:  Mingjie Su
+//
+// Description: Factory for info objects.
+// 
+//----------------------------------------------------------------------------
+// $Id: ossimHdfInfoFactory.cpp 2645 2011-05-26 15:21:34Z oscar.kramer $
+
+#include "ossimHdfInfoFactory.h"
+#include <ossim/support_data/ossimInfoFactory.h>
+#include <ossim/support_data/ossimInfoBase.h>
+#include <ossim/base/ossimFilename.h>
+#include <ossim/base/ossimRefPtr.h>
+#include "ossimHdfInfo.h"
+#include "ossimH5Info.h"
+
+ossimHdfInfoFactory::~ossimHdfInfoFactory()
+{}
+
+ossimHdfInfoFactory* ossimHdfInfoFactory::instance()
+{
+   static ossimHdfInfoFactory sharedInstance;
+
+   return &sharedInstance;
+}
+
+ossimInfoBase* ossimHdfInfoFactory::create(const ossimFilename& file) const
+{
+   ossimRefPtr<ossimInfoBase> result = 0;
+
+#if 1
+   // cout << "Calling ossimH5Info ***********************" << endl;
+   result = new ossimH5Info();
+   if ( result->open(file) )
+   {
+      return result.release();
+   }
+#endif
+
+   // cout << "Calling ossimHdfInfo ***********************" << endl;
+
+   // Note old info.  Left in as it handles hdf4.
+   result = new ossimHdfInfo();
+   if ( result->open(file) )
+   {
+      return result.release();
+   }
+   return 0;
+}
+
+ossimHdfInfoFactory::ossimHdfInfoFactory()
+{}
+
+ossimHdfInfoFactory::ossimHdfInfoFactory(const ossimHdfInfoFactory& /* obj */ )
+{}
+
+const ossimHdfInfoFactory& ossimHdfInfoFactory::operator=(
+   const ossimHdfInfoFactory& /* rhs */)
+{
+   return *this;
+}
+
+
diff --git a/ossim_plugins/hdf/ossimHdfInfoFactory.h b/ossim_plugins/hdf/ossimHdfInfoFactory.h
new file mode 100644
index 0000000..368e256
--- /dev/null
+++ b/ossim_plugins/hdf/ossimHdfInfoFactory.h
@@ -0,0 +1,58 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author:  Mingjie Su
+//
+// Description: Factory for hdf info objects.
+// 
+//----------------------------------------------------------------------------
+// $Id: ossimHdfInfoFactory.h 2645 2011-05-26 15:21:34Z oscar.kramer $
+#ifndef ossimHdfInfoFactory_HEADER
+#define ossimHdfInfoFactory_HEADER
+
+#include <ossim/base/ossimConstants.h>
+#include <ossim/support_data/ossimInfoFactoryInterface.h>
+
+class ossimFilename;
+class ossimInfoBase;
+
+/**
+ * @brief Info factory.
+ */
+class ossimHdfInfoFactory : public ossimInfoFactoryInterface
+{
+public:
+
+   /** virtual destructor */
+   virtual ~ossimHdfInfoFactory();
+
+   static ossimHdfInfoFactory* instance();
+
+   /**
+    * @brief create method.
+    *
+    * @param file Some file you want info for.
+    *
+    * @return ossimInfoBase* on success 0 on failure.  Caller is responsible
+    * for memory.
+    */
+   virtual ossimInfoBase* create(const ossimFilename& file) const;
+   
+private:
+   
+   /** hidden from use default constructor */
+   ossimHdfInfoFactory();
+
+   /** hidden from use copy constructor */
+   ossimHdfInfoFactory(const ossimHdfInfoFactory& obj);
+
+   /** hidden from use operator = */
+   const ossimHdfInfoFactory& operator=(const ossimHdfInfoFactory& rhs);
+};
+
+#endif /* End of "#ifndef ossimInfoFactory_HEADER" */
+
+
diff --git a/ossim_plugins/hdf/ossimHdfPluginInit.cpp b/ossim_plugins/hdf/ossimHdfPluginInit.cpp
new file mode 100644
index 0000000..b143467
--- /dev/null
+++ b/ossim_plugins/hdf/ossimHdfPluginInit.cpp
@@ -0,0 +1,92 @@
+//----------------------------------------------------------------------------
+//
+// License:  See top level LICENSE.txt file
+//
+// Author:  Mingjie Su
+//
+// Description: OSSIM HDF plugin initialization
+// code.
+//
+//----------------------------------------------------------------------------
+// $Id: ossimHdfPluginInit.cpp 2645 2011-05-26 15:21:34Z oscar.kramer $
+
+#include <ossim/plugin/ossimSharedObjectBridge.h>
+#include <ossim/imaging/ossimImageHandlerRegistry.h>
+#include <ossim/imaging/ossimImageWriterFactoryRegistry.h>
+#include <ossim/imaging/ossimOverviewBuilderFactoryRegistry.h>
+#include <ossim/projection/ossimProjectionFactoryRegistry.h>
+#include <ossim/support_data/ossimInfoFactoryRegistry.h>
+
+#include "../ossimPluginConstants.h"
+#include "ossimHdfReaderFactory.h"
+#include "ossimHdfInfoFactory.h"
+#include "ossimHdfProjectionFactory.h"
+
+static void setDescription(ossimString& description)
+{
+   description = "Hdf reader plugin\n\n";
+}
+
+extern "C"
+{
+   ossimSharedObjectInfo  myInfo;
+   ossimString theDescription;
+   std::vector<ossimString> theObjList;
+
+   const char* getDescription()
+   {
+      return theDescription.c_str();
+   }
+
+   int getNumberOfClassNames()
+   {
+      return (int)theObjList.size();
+   }
+
+   const char* getClassName(int idx)
+   {
+      if(idx < (int)theObjList.size())
+      {
+         return theObjList[0].c_str();
+      }
+      return (const char*)0;
+   }
+
+   /* Note symbols need to be exported on windoze... */ 
+   OSSIM_PLUGINS_DLL void ossimSharedLibraryInitialize(
+      ossimSharedObjectInfo** info)
+   {    
+      myInfo.getDescription = getDescription;
+      myInfo.getNumberOfClassNames = getNumberOfClassNames;
+      myInfo.getClassName = getClassName;
+
+      *info = &myInfo;
+
+      /* Register the readers... */
+      ossimImageHandlerRegistry::instance()->
+         registerFactory(ossimHdfReaderFactory::instance());
+
+      /* Register hdf info factoy... */
+      ossimInfoFactoryRegistry::instance()->
+         registerFactory(ossimHdfInfoFactory::instance());
+
+      /* Register hdf projection factoy... */
+      ossimProjectionFactoryRegistry::instance()->
+         registerFactoryToFront(ossimHdfProjectionFactory::instance());
+
+      setDescription(theDescription);
+   }
+
+   /* Note symbols need to be exported on windoze... */ 
+   OSSIM_PLUGINS_DLL void ossimSharedLibraryFinalize()
+   {
+      ossimImageHandlerRegistry::instance()->
+         unregisterFactory(ossimHdfReaderFactory::instance());
+
+      ossimInfoFactoryRegistry::instance()->
+         unregisterFactory(ossimHdfInfoFactory::instance());
+
+      ossimProjectionFactoryRegistry::instance()->
+         unregisterFactory(ossimHdfProjectionFactory::instance());
+   }
+}
diff --git a/ossim_plugins/hdf/ossimHdfProjectionFactory.cpp b/ossim_plugins/hdf/ossimHdfProjectionFactory.cpp
new file mode 100644
index 0000000..30a00e5
--- /dev/null
+++ b/ossim_plugins/hdf/ossimHdfProjectionFactory.cpp
@@ -0,0 +1,160 @@
+//----------------------------------------------------------------------------
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//----------------------------------------------------------------------------
+// $Id$
+
+#include "ossimHdfProjectionFactory.h"
+#include <ossim/base/ossimKeywordNames.h>
+#include <ossim/base/ossimRefPtr.h>
+#include <ossim/projection/ossimProjection.h>
+#include "ossimHdfGridModel.h"
+
+//---
+// Define Trace flags for use within this file:
+//---
+#include <ossim/base/ossimTrace.h>
+static ossimTrace traceExec  = ossimTrace("ossimHdfProjectionFactory:exec");
+static ossimTrace traceDebug = ossimTrace("ossimHdfProjectionFactory:debug");
+
+ossimHdfProjectionFactory* ossimHdfProjectionFactory::instance()
+{
+   static ossimHdfProjectionFactory* factoryInstance =
+      new ossimHdfProjectionFactory();
+
+   return factoryInstance;
+}
+   
+ossimProjection* ossimHdfProjectionFactory::createProjection(
+   const ossimFilename& filename, ossim_uint32 /*entryIdx*/)const
+{
+   static const char MODULE[] = "ossimHdfProjectionFactory::createProjection(ossimFilename& filename)";
+   ossimRefPtr<ossimProjection> projection = 0;
+
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " DEBUG: testing ossimHdfGridModel" << std::endl;
+   }
+
+   ossimKeywordlist kwl;
+   ossimRefPtr<ossimProjection> model = 0;
+   ossimFilename geomFile = filename;
+   geomFile = geomFile.setExtension("geom");
+   
+   if(geomFile.exists()&&
+      kwl.addFile(filename.c_str()))
+   {
+      ossimFilename coarseGrid;
+      
+      const char* type = kwl.find(ossimKeywordNames::TYPE_KW);
+      if(type)
+      {
+         if( ossimString(type) == ossimString("ossimHdfGridModel") )
+         {
+            ossimFilename coarseGrid = geomFile;
+            geomFile.setFile(coarseGrid.fileNoExtension()+"_ocg");
+            
+            if(coarseGrid.exists() &&(coarseGrid != ""))
+            {
+               kwl.add("grid_file_name",
+                       coarseGrid.c_str(),
+                       true);
+               projection = new ossimHdfGridModel();
+               if ( projection->loadState( kwl ) == false )
+               {
+                  projection = 0;
+               }
+            }
+         }
+      }
+   }
+
+   // Must release or pointer will self destruct when it goes out of scope.
+   return projection.release();
+}
+
+ossimProjection* ossimHdfProjectionFactory::createProjection(
+   const ossimString& name)const
+{
+   static const char MODULE[] = "ossimHdfProjectionFactory::createProjection(ossimString& name)";
+
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " DEBUG: Entering ...." << std::endl;
+   }
+
+   if ( name == "ossimHdfGridModel" )
+   {
+      return new ossimHdfGridModel();
+   }
+
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+           << MODULE << " DEBUG: Leaving ...." << std::endl;
+   }
+
+   return 0;
+}
+
+ossimProjection* ossimHdfProjectionFactory::createProjection(
+   const ossimKeywordlist& kwl, const char* prefix)const
+{
+   ossimRefPtr<ossimProjection> result = 0;
+   static const char MODULE[] = "ossimHdfProjectionFactory::createProjection(ossimKeywordlist& kwl)";
+
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " DEBUG: Start ...." << std::endl;
+   }
+   
+   const char* lookup = kwl.find(prefix, ossimKeywordNames::TYPE_KW);
+   if (lookup)
+   {
+      ossimString type = lookup;
+      
+      if (type == "ossimHdfGridModel")
+      {
+         result = new ossimHdfGridModel();
+         if ( !result->loadState(kwl, prefix) )
+         {
+            result = 0;
+         }
+      }
+   }
+
+   if(traceDebug())
+   {
+    	ossimNotify(ossimNotifyLevel_DEBUG)
+        	   << MODULE << " DEBUG: End ...." << std::endl;
+   }
+   
+   return result.release();
+}
+
+ossimObject* ossimHdfProjectionFactory::createObject(
+   const ossimString& typeName)const
+{
+   return createProjection(typeName);
+}
+
+ossimObject* ossimHdfProjectionFactory::createObject(
+   const ossimKeywordlist& kwl, const char* prefix)const
+{
+   return createProjection(kwl, prefix);
+}
+
+
+void ossimHdfProjectionFactory::getTypeNameList(std::vector<ossimString>& typeList)const
+{
+   typeList.push_back(ossimString("ossimHdfGridModel"));
+}
+
+ossimHdfProjectionFactory::ossimHdfProjectionFactory()
+{
+}
+
diff --git a/ossim_plugins/hdf/ossimHdfProjectionFactory.h b/ossim_plugins/hdf/ossimHdfProjectionFactory.h
new file mode 100644
index 0000000..32b53e0
--- /dev/null
+++ b/ossim_plugins/hdf/ossimHdfProjectionFactory.h
@@ -0,0 +1,54 @@
+//----------------------------------------------------------------------------
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef ossimHdfProjectionFactory_HEADER
+#define ossimHdfProjectionFactory_HEADER 1
+
+#include <ossimPluginConstants.h>
+#include <ossim/projection/ossimProjectionFactoryBase.h>
+
+class OSSIM_PLUGINS_DLL ossimHdfProjectionFactory : public ossimProjectionFactoryBase
+{
+public:
+
+   static ossimHdfProjectionFactory* instance();
+
+   /**
+    * @bief Takes a filename. This filename can be an image file or
+    * it can also be a ossim .geom file.  It could be other
+    * forms of geom files as well.  The factories job will be to
+    * determine what parser to use and return a projection if
+    * successful.
+    */
+   virtual ossimProjection* createProjection(const ossimFilename& filename,
+                                             ossim_uint32 entryIdx)const;
+   
+   /** @brief Take a projection type name. */
+   virtual ossimProjection* createProjection(const ossimString& name)const;
+
+   /** @brief Take a keywordlist. */
+   virtual ossimProjection* createProjection(const ossimKeywordlist& kwl,
+                                             const char* prefix=0)const;
+   
+   virtual ossimObject* createObject(const ossimString& typeName)const;
+   
+   /*!
+    * Creates and object given a keyword list.
+    */
+   virtual ossimObject* createObject(const ossimKeywordlist& kwl,
+                                     const char* prefix=0)const;
+   
+   virtual void getTypeNameList(std::vector<ossimString>& typeList)const;
+
+protected:
+   
+   ossimHdfProjectionFactory();
+   
+}; // End: class ossimHdfProjectionFactory{ ... }
+
+#endif /* #ifndef ossimHdfProjectionFactory_HEADER */
+
diff --git a/ossim_plugins/hdf/ossimHdfReaderFactory.cpp b/ossim_plugins/hdf/ossimHdfReaderFactory.cpp
new file mode 100644
index 0000000..2bd279e
--- /dev/null
+++ b/ossim_plugins/hdf/ossimHdfReaderFactory.cpp
@@ -0,0 +1,248 @@
+//----------------------------------------------------------------------------
+//
+// License:  See top level LICENSE.txt file
+//
+// Author:  Mingjie Su
+//
+// Description: Factory for OSSIM HDF reader using Hdf4 and Hdf5 libraries.
+//----------------------------------------------------------------------------
+// $Id: ossimHdfReaderFactory.cpp 2645 2011-05-26 15:21:34Z oscar.kramer $
+
+#include "ossimHdfReaderFactory.h"
+#include <ossim/base/ossimKeywordNames.h>
+#include <ossim/base/ossimKeywordlist.h>
+#include <ossim/base/ossimRefPtr.h>
+#include <ossim/base/ossimString.h>
+#include <ossim/base/ossimTrace.h>
+#include <ossim/imaging/ossimImageHandler.h>
+#include "ossimHdf4Reader.h"
+#include "ossimHdf5Reader.h"
+#include "ossimH5Reader.h"
+
+static const ossimTrace traceDebug("ossimHdfReaderFactory:debug");
+
+class ossimImageHandler;
+
+RTTI_DEF1(ossimHdfReaderFactory,
+          "ossimHdfReaderFactory",
+          ossimImageHandlerFactoryBase);
+
+ossimHdfReaderFactory* ossimHdfReaderFactory::theInstance = 0;
+
+ossimHdfReaderFactory::~ossimHdfReaderFactory()
+{
+   theInstance = 0;
+}
+
+ossimHdfReaderFactory* ossimHdfReaderFactory::instance()
+{
+   if(!theInstance)
+   {
+      theInstance = new ossimHdfReaderFactory;
+   }
+   return theInstance;
+}
+
+ossimImageHandler* ossimHdfReaderFactory::open(const ossimFilename& fileName,
+                                               bool openOverview)const
+{
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimHdfReaderFactory::open(filename, openOverview) DEBUG: entered..."
+         << std::endl;
+   }
+
+   ossimRefPtr<ossimImageHandler> reader = 0;
+
+   if ( hasExcludedExtension(fileName) == false )
+   {
+      if (reader == 0) //try hdf5 reader
+      {
+         // cout << "Calling ossimHdf5Reader ***********************" << endl;
+         if(traceDebug())
+         {
+            ossimNotify(ossimNotifyLevel_DEBUG)
+               << "trying ossimH5Reader..."
+               << std::endl;
+         }
+         reader = new ossimH5Reader;
+         reader->setOpenOverviewFlag(openOverview);
+         if(reader->open(fileName) == false)
+         {
+            reader = 0;
+         }
+      }
+
+      if ( !reader.valid()) //try hdf4 reader
+      {
+         // cout << "Calling ossimHdf4Reader ***********************" << endl;
+         if(traceDebug())
+         {
+            ossimNotify(ossimNotifyLevel_DEBUG)
+               << "trying ossimHdf4Reader..."
+               << std::endl;
+         }
+         reader = new ossimHdf4Reader;
+         reader->setOpenOverviewFlag(openOverview);
+         if(reader->open(fileName) == false)
+         {
+            reader = 0;
+         }
+      }
+    
+      if(!reader.valid())
+      {
+         if(traceDebug())
+         {
+            ossimNotify(ossimNotifyLevel_DEBUG)
+               << "Could not open any handler..."
+               << std::endl;
+         }
+      }  
+#if 0 /* Old HDF5 reader. (drb) */
+      if (reader == 0) //try hdf5 reader
+      {
+         cout << "Calling ossimHdf5Reader ***********************" << endl;
+         reader = new ossimHdf5Reader;
+         reader->setOpenOverviewFlag(openOverview);
+         if(reader->open(fileName) == false)
+         {
+            reader = 0;
+         }
+      }
+#endif
+      
+   }
+
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimHdfReaderFactory::open(filename, openOverview) DEBUG: leaving..."
+         << std::endl;
+   }
+
+   return reader.release();
+}
+
+ossimImageHandler* ossimHdfReaderFactory::open(const ossimKeywordlist& kwl,
+                                               const char* prefix)const
+{
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimHdfReaderFactory::open(kwl, prefix) DEBUG: entered..."
+         << "Trying ossimKakaduNitfReader"
+         << std::endl;
+   }
+
+   ossimString type = kwl.find(prefix, ossimKeywordNames::TYPE_KW);
+   ossimRefPtr<ossimImageHandler> reader;
+   if(type)
+   {
+      if(type == STATIC_TYPE_NAME(ossimHdf4Reader))
+      {
+         reader = new ossimHdf4Reader();
+      }
+      else if (type == STATIC_TYPE_NAME(ossimH5Reader))
+      {
+         reader = new ossimH5Reader();
+      }
+   }
+   if(reader.valid())
+   {
+      if(!reader->loadState(kwl, prefix))
+      {
+         reader = 0;
+      }
+   }
+   else
+   {
+      reader = new ossimHdf4Reader;
+      if(reader->loadState(kwl, prefix))
+      {
+         reader = 0;
+      }
+      if(reader.valid())
+      {
+         reader = new ossimH5Reader();
+         if(!reader->loadState(kwl, prefix))
+         {
+            reader = 0;
+         }
+      }
+   }
+
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimHdfReaderFactory::open(kwl, prefix) DEBUG: leaving..."
+         << std::endl;
+   }
+
+   return reader.release();
+}
+
+ossimObject* ossimHdfReaderFactory::createObject(
+   const ossimString& typeName)const
+{
+   ossimRefPtr<ossimObject> result = 0;
+   if(typeName == STATIC_TYPE_NAME(ossimHdf4Reader))
+   {
+      result = new ossimHdf4Reader;
+   }
+   else if(typeName == STATIC_TYPE_NAME(ossimH5Reader))
+   {
+      result = new ossimH5Reader;
+   }
+
+   return result.release();
+}
+
+ossimObject* ossimHdfReaderFactory::createObject(
+   const ossimKeywordlist& kwl,
+   const char* prefix)const
+{
+   return this->open(kwl, prefix);
+}
+
+void ossimHdfReaderFactory::getTypeNameList(
+   std::vector<ossimString>& typeList)const
+{
+   typeList.push_back(STATIC_TYPE_NAME(ossimHdf4Reader));
+   typeList.push_back(STATIC_TYPE_NAME(ossimH5Reader));
+}
+
+void ossimHdfReaderFactory::getSupportedExtensions(
+   ossimImageHandlerFactoryBase::UniqueStringList& extensionList)const
+{
+   extensionList.push_back(ossimString("h4"));
+   extensionList.push_back(ossimString("h5"));
+   extensionList.push_back(ossimString("he4"));
+   extensionList.push_back(ossimString("he5"));
+   extensionList.push_back(ossimString("hdf4"));
+   extensionList.push_back(ossimString("hdf5"));   
+   extensionList.push_back(ossimString("hdf"));
+}
+
+bool ossimHdfReaderFactory::hasExcludedExtension(
+   const ossimFilename& file) const
+{
+   bool result = true;
+   ossimString ext = file.ext().downcase();
+   //only include the file with those extension and exclude any other files
+   if ( ext == "hdf" || ext == "h4" || ext == "hdf4" || 
+      ext == "he4" || ext == "hdf5" || ext == "he5" || ext == "h5" || 
+      ext == "l1r")
+   {
+      result = false;
+   }
+   return result;
+}
+
+ossimHdfReaderFactory::ossimHdfReaderFactory(){}
+
+ossimHdfReaderFactory::ossimHdfReaderFactory(const ossimHdfReaderFactory&){}
+
+void ossimHdfReaderFactory::operator=(const ossimHdfReaderFactory&){}
+
diff --git a/ossim_plugins/hdf/ossimHdfReaderFactory.h b/ossim_plugins/hdf/ossimHdfReaderFactory.h
new file mode 100644
index 0000000..c9126a8
--- /dev/null
+++ b/ossim_plugins/hdf/ossimHdfReaderFactory.h
@@ -0,0 +1,110 @@
+//----------------------------------------------------------------------------
+//
+// License:  See top level LICENSE.txt file
+//
+// Author:  Mingjie Su
+//
+// Description: Factory for OSSIM HDF reader using Hdf4 and Hdf5 libraries.
+//----------------------------------------------------------------------------
+// $Id: ossimHdfReaderFactory.h 2645 2011-05-26 15:21:34Z oscar.kramer $
+
+#ifndef ossimHdfReaderFactory_HEADER
+#define ossimHdfReaderFactory_HEADER
+
+#include <ossim/imaging/ossimImageHandlerFactoryBase.h>
+
+class ossimString;
+class ossimFilename;
+class ossimKeywordlist;
+
+/** @brief Factory for Hdf image reader. */
+class ossimHdfReaderFactory : public ossimImageHandlerFactoryBase
+{
+public:
+
+   /** @brief virtual destructor */
+   virtual ~ossimHdfReaderFactory();
+
+   /**
+    * @brief static method to return instance (the only one) of this class.
+    * @return pointer to instance of this class.
+    */
+   static ossimHdfReaderFactory* instance();
+
+   /**
+    * @brief open that takes a file name.
+    * @param file The file to open.
+    * @param openOverview If true image handler will attempt to open overview.
+    * default = true 
+    * @return pointer to image handler on success, NULL on failure.
+    */
+   virtual ossimImageHandler* open(const ossimFilename& fileName,
+                                   bool openOverview=true) const;
+
+   /**
+    * @brief open that takes a keyword list and prefix.
+    * @param kwl The keyword list.
+    * @param prefix the keyword list prefix.
+    * @return pointer to image handler on success, NULL on failure.
+    */
+   virtual ossimImageHandler* open(const ossimKeywordlist& kwl,
+                                   const char* prefix=0)const;
+
+   /**
+    * @brief createObject that takes a class name (ossimHdf4Reader)
+    * @param typeName Should be "ossimHdf4Reader" or "ossimHdf5Reader".
+    * @return pointer to image writer on success, NULL on failure.
+    */
+   virtual ossimObject* createObject(const ossimString& typeName)const;
+   
+   /**
+    * @brief Creates and object given a keyword list and prefix.
+    * @param kwl The keyword list.
+    * @param prefix the keyword list prefix.
+    * @return pointer to image handler on success, NULL on failure.
+    */
+   virtual ossimObject* createObject(const ossimKeywordlist& kwl,
+                                     const char* prefix=0)const;
+   
+   /**
+    * @brief Adds ossimHdfReader to the typeList.
+    * @param typeList List to add to.
+    */
+   virtual void getTypeNameList(std::vector<ossimString>& typeList)const;
+
+   /**
+    * @brief Method to add supported extension to the list, like "hdf".
+    *
+    * @param extensionList The list to add to.
+    */
+   virtual void getSupportedExtensions(
+      ossimImageHandlerFactoryBase::UniqueStringList& extensionList)const;
+  
+protected:
+
+   /**
+    * @brief Method to weed out extensions that this plugin knows it does
+    * not support.  This is to avoid a costly open on say a tiff or jpeg that
+    * is not handled by this plugin.
+    *
+    * @return true if extension, false if not.
+    */
+   bool hasExcludedExtension(const ossimFilename& file) const;
+   
+   /** @brief hidden from use default constructor */
+   ossimHdfReaderFactory();
+
+   /** @brief hidden from use copy constructor */
+   ossimHdfReaderFactory(const ossimHdfReaderFactory&);
+
+   /** @brief hidden from use copy constructor */
+   void operator=(const ossimHdfReaderFactory&);
+
+   /** static instance of this class */
+   static ossimHdfReaderFactory* theInstance;
+
+TYPE_DATA
+};
+
+#endif /* end of #ifndef ossimHdfReaderFactory_HEADER */
+
diff --git a/ossim_plugins/hdf4/CMakeLists.txt b/ossim_plugins/hdf4/CMakeLists.txt
new file mode 100644
index 0000000..737fbed
--- /dev/null
+++ b/ossim_plugins/hdf4/CMakeLists.txt
@@ -0,0 +1,44 @@
+set(LIB_NAME ossimhdf4_plugin)
+MESSAGE( "************** LIBRARY SETUP FOR ossimhdf4_plugin******************")
+
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
+
+# Include ossim cmake stuff:
+include(OssimVersion)
+include(OssimCommonVariables)
+include(OssimUtilities)
+
+SET(requiredLibs)
+
+find_package(HDF4)
+IF(HDF4_FOUND)
+   INCLUDE_DIRECTORIES( ${HDF4_INCLUDE_DIR} )
+   SET(requiredLibs ${requiredLibs} ${HDF4_LIBRARIES} )
+ELSE(HDF4_FOUND)
+   MESSAGE(FATAL_ERROR "Could not find hdf4")
+ENDIF(HDF4_FOUND)
+
+FILE(GLOB_RECURSE OSSIMPLUGIN_SRCS *.cpp)
+FILE(GLOB_RECURSE OSSIMPLUGIN_HEADERS *.h)
+
+####
+# OSSIMPLUGINSMAKINGDLL controls dll linkage on windows.  
+# Adding this sets OSSIM_PLUGINS_DLL #define TO "__declspec(dllexport)".
+###
+add_definitions("-DOSSIMPLUGINSMAKINGDLL")
+
+# Adjust the install library path:
+if(OSSIM_INSTALL_PLUGINS_WITH_VERSION)
+   set(INSTALL_LIBRARY_DIR   "${INSTALL_LIBRARY_DIR}/ossim-${OSSIM_VERSION}/plugins")
+else(OSSIM_INSTALL_PLUGINS_WITH_VERSION)
+   set(INSTALL_LIBRARY_DIR   "${INSTALL_LIBRARY_DIR}/ossim/plugins")
+endif(OSSIM_INSTALL_PLUGINS_WITH_VERSION)
+
+OSSIM_LINK_LIBRARY(${LIB_NAME}
+                   COMPONENT_NAME ossim TYPE "${OSSIM_PLUGIN_LINK_TYPE}"
+		   LIBRARIES ${OSSIM_LIBRARY} ${requiredLibs}
+                   HEADERS "${OSSIMPLUGIN_HEADERS}"
+		   SOURCE_FILES "${OSSIMPLUGIN_SRCS}"
+                   INSTALL_LIB)
+
+MESSAGE( STATUS "HDF4 Plugin required libs         = ${requiredLibs}" )
diff --git a/ossim_plugins/hdf4/ossimHdf4Reader.cpp b/ossim_plugins/hdf4/ossimHdf4Reader.cpp
new file mode 100644
index 0000000..39bb467
--- /dev/null
+++ b/ossim_plugins/hdf4/ossimHdf4Reader.cpp
@@ -0,0 +1,1494 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Description:  Class definition for HDF4 reader.
+//
+//----------------------------------------------------------------------------
+// $Id: ossimHdf4Reader.cpp 2645 2011-05-26 15:21:34Z oscar.kramer $
+
+#include "ossimHdf4Reader.h"
+
+#include <fstream>
+#include <iostream>
+#include <string>
+
+//ossim includes
+#include <ossim/base/ossimCommon.h>
+#include <ossim/base/ossimDpt.h>
+#include <ossim/base/ossimIpt.h>
+#include <ossim/base/ossimEndian.h>
+#include <ossim/base/ossimException.h>
+#include <ossim/base/ossimIoStream.h>
+#include <ossim/base/ossimKeywordlist.h>
+#include <ossim/base/ossimNotify.h>
+#include <ossim/base/ossimScalarTypeLut.h>
+#include <ossim/base/ossimTrace.h>
+#include <ossim/base/ossimUnitTypeLut.h>
+
+#include <ossim/imaging/ossimImageDataFactory.h>
+#include <ossim/imaging/ossimImageGeometryRegistry.h>
+
+#include <ossim/projection/ossimProjection.h>
+#include <ossim/projection/ossimProjectionFactoryRegistry.h>
+#include <ossim/projection/ossimEpsgProjectionFactory.h>
+#include <ossim/projection/ossimUtmProjection.h>
+#include <ossim/projection/ossimEquDistCylProjection.h>
+#include <ossim/projection/ossimLambertConformalConicProjection.h>
+#include <ossim/projection/ossimMercatorProjection.h>
+#include <ossim/projection/ossimPolarStereoProjection.h>
+#include <ossim/projection/ossimPolyconicProjection.h>
+#include <ossim/projection/ossimAzimEquDistProjection.h>
+#include <ossim/projection/ossimObliqueMercatorProjection.h>
+#include <ossim/projection/ossimSpaceObliqueMercatorProjection.h>
+#include <ossim/projection/ossimSinusoidalProjection.h>
+
+#include <ossim/support_data/ossimAuxFileHandler.h>
+
+
+/////////////////////////////////////////
+#include <ossim/base/ossimTieGptSet.h>
+//////////////////////////////////////////
+
+#include "ossimHdf4SubDataset.h"
+#include "ossimHdfGridModel.h"
+
+#ifdef OSSIM_ID_ENABLED
+static const char OSSIM_ID[] = "$Id";
+#endif
+
+const ossimString ossimHdf4Reader::HDF4_EOS_GRID = "GRID";              
+const ossimString ossimHdf4Reader::HDF4_EOS_SWATH = "SWATH";                   
+const ossimString ossimHdf4Reader::HDF4_SEAWIFS_L1A = "SEAWIFS_L1A";		    
+const ossimString ossimHdf4Reader::HDF4_SEAWIFS_L2 = "SEAWIFS_L2";	          
+const ossimString ossimHdf4Reader::HDF4_SEAWIFS_L3 = "SEAWIFS_L3";		       
+const ossimString ossimHdf4Reader::HDF4_HYPERION_L1 = "HYPERION_L1"; 
+const ossimString ossimHdf4Reader::HDF4_SDS = "HDF4_SDS";
+
+static ossimTrace traceDebug("ossimHdf4Reader:debug");
+static ossimTrace traceDump("ossimHdf4Reader:dump");
+
+RTTI_DEF1_INST(ossimHdf4Reader,
+               "ossimHdf4Reader",
+               ossimImageHandler)
+
+               ossimHdf4Reader::ossimHdf4Reader()
+               : ossimImageHandler(),
+               m_fid(-1),
+               m_sd_id(-1),
+               m_imageRect(),
+               m_numberOfBands(0),
+               m_scalarType(OSSIM_SCALAR_UNKNOWN),
+               m_tile(0),
+               m_isHdfEos(false),
+               m_currentEntryRender(0),
+               m_currentSubDataset(NULL),
+               m_structMetadata("")
+{
+}
+
+ossimHdf4Reader::~ossimHdf4Reader()
+{
+   closeEntry();
+}
+
+ossimString ossimHdf4Reader::getShortName()const
+{
+   return ossimString("ossim_hdf4_reader");
+}
+
+ossimString ossimHdf4Reader::getLongName()const
+{
+   return ossimString("ossim hdf4 reader");
+}
+
+ossimString ossimHdf4Reader::getClassName()const
+{
+   return ossimString("ossimHdf4Reader");
+}
+
+ossim_uint32 ossimHdf4Reader::getNumberOfLines(ossim_uint32 resLevel) const
+{
+   ossim_uint32 result = 0;
+   if ( isValidRLevel(resLevel) )
+   {
+      if (resLevel == 0)
+      {
+         if (m_currentSubDataset != NULL)
+         {
+            return m_currentSubDataset->getNumberOfLines();
+         }
+      }
+      else if (theOverview.valid())
+      {
+         result = theOverview->getNumberOfSamples(resLevel);
+      }
+   }
+   return result;
+}
+
+ossim_uint32 ossimHdf4Reader::getNumberOfSamples(ossim_uint32 resLevel) const
+{
+   ossim_uint32 result = 0;
+   if ( isValidRLevel(resLevel) )
+   {
+      if (resLevel == 0)
+      {
+         if (m_currentSubDataset != NULL)
+         {
+            return m_currentSubDataset->getNumberOfSamples();
+         }
+      }
+      else if (theOverview.valid())
+      {
+         result = theOverview->getNumberOfSamples(resLevel);
+      }
+   }
+   return result;
+}
+
+bool ossimHdf4Reader::open()
+{
+   static const char MODULE[] = "ossimHdf4Reader::open";
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " entered...\n"
+         << "image: " << theImageFile << "\n";
+   }
+
+   bool result = false;
+
+   if ( theImageFile.size() )
+   {
+      if (Hishdf(theImageFile.c_str()) > 0)
+      {
+         if (m_subDatasets.size() == 0)
+         {
+            if(isOpen())
+            {
+               closeEntry();
+            }
+            
+            if (m_subDatasets.size() == 0)
+            {
+               m_fid = Hopen(theImageFile.c_str(), DFACC_READ, 0);
+               if (m_fid <= 0)
+               {
+                  closeEntry();
+                  return false;  
+               }
+               
+               m_sd_id = SDstart(theImageFile.c_str(), DFACC_READ );
+               
+               if (m_sd_id == -1)
+               {
+                  closeEntry();
+                  return false;  
+               }
+               
+               result = initGlobalMeta();      
+            }
+         }
+         
+         if (m_currentEntryRender < m_subDatasets.size())
+         {
+            //close file before open file in sub-dataset
+            closeEntry();
+            ossimHdfSubdataset subData = m_subDatasets[m_currentEntryRender];
+            m_numberOfBands = subData.m_bands;
+            m_currentSubDataset = new ossimHdf4SubDataset();
+            m_currentSubDataset->setHdfSdsIndex(subData.m_sdsIndex);
+            m_currentSubDataset->setOutputScalarType(subData.m_dataType);
+            m_currentSubDataset->setNumberOfBands(subData.m_bands);
+            m_currentSubDataset->setNumberOfLines(subData.m_rows);
+            m_currentSubDataset->setNumberOfSamples(subData.m_cols);
+            m_currentSubDataset->setAttributeCount(subData.m_attributes);
+            m_currentSubDataset->setSdsRank(subData.m_rank);
+            m_currentSubDataset->setSdsName(subData.m_name);
+            m_currentSubDataset->setHdfDataType(m_hdfDataType);
+            
+            m_currentSubDataset->setHdfFilename(theImageFile);
+            
+            m_tile = ossimImageDataFactory::instance()->create(this, this);
+            m_tile->initialize();
+            
+            // Call the base complete open to pick up overviews.
+            completeOpen();
+            result = true;
+         }
+         else
+         {
+            closeEntry();
+            result = false;
+         }
+         
+      } // if (Hishdf(theImageFile.c_str()) > 0)
+      
+   } // if ( theImageFile.size() )
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " exit status = " << (result?"true":"false\n")
+         << std::endl;
+   }
+
+   return result;
+}
+
+bool ossimHdf4Reader::initGlobalMeta()
+{
+   int32	numAttributes;
+   int32 numValues;
+   int32 numDatasets;
+   int32 dataType;
+   char	attrName[100];
+
+   m_globalMeta.clear();
+   m_structMetadata = "";
+
+   //Obtain number of SDSs and global attributes in input file. 
+   if ( SDfileinfo(m_sd_id, &numDatasets, &numAttributes ) != 0 )
+   {
+      return false;
+   }
+
+   // Loop through the all attributes
+   for (ossim_int32 i = 0; i < numAttributes; i++ )
+   {
+      // Get information about the attribute. Note that the first
+      // parameter is an SD interface identifier.
+      SDattrinfo(m_sd_id, i, attrName, &dataType, &numValues);
+
+      if (i == 0)
+      {
+         char* attrVersion = (char*)malloc(numValues * sizeof (dataType));
+         attrVersion[numValues] = '\0';
+         SDreadattr(m_sd_id, i, attrVersion);
+         m_globalMeta.push_back(ossimString(ossimString(attrName).trim() 
+            + ": " + ossimString(attrVersion).trim()));
+         free(attrVersion);
+         continue;
+      }
+
+      if ( ossimString(attrName).downcase().contains("coremetadata.")     ||
+         ossimString(attrName).downcase().contains("archivemetadata.")    ||
+         ossimString(attrName).downcase().contains("productmetadata.")    ||
+         ossimString(attrName).downcase().contains("badpixelinformation") ||
+         ossimString(attrName).downcase().contains("product_summary")     ||
+         ossimString(attrName).downcase().contains("dem_specific")        ||
+         ossimString(attrName).downcase().contains("bts_specific")        ||
+         ossimString(attrName).downcase().contains("etse_specific")       ||
+         ossimString(attrName).downcase().contains("dst_specific")        ||
+         ossimString(attrName).downcase().contains( "acv_specific")       ||
+         ossimString(attrName).downcase().contains("act_specific")        ||
+         ossimString(attrName).downcase().contains("etst_specific")       ||
+         ossimString(attrName).downcase().contains("level_1_carryover"))
+      {
+         char* attrValues = (char*)malloc(numValues * sizeof (dataType));
+         attrValues[numValues] = '\0';
+         SDreadattr(m_sd_id, i, attrValues);
+         parseMetaString(ossimString(attrValues));
+         free(attrValues);
+      }
+      else if (ossimString(attrName).downcase().contains("structmetadata."))
+      {
+         m_isHdfEos = true;
+         char* attrStructureChar = (char*)malloc(numValues * sizeof (dataType));
+         attrStructureChar[numValues] = '\0';
+         SDreadattr(m_sd_id, i, attrStructureChar);
+         m_structMetadata = m_structMetadata + ossimString(attrStructureChar);
+         free(attrStructureChar);
+         continue;
+      }
+      else
+      {
+         if ( dataType == DFNT_CHAR8 || dataType == DFNT_UCHAR8 )
+         {
+            char* attrValue = (char*)malloc(numValues * sizeof (dataType));
+            attrValue[numValues] = '\0';
+            SDreadattr(m_sd_id, i, attrValue);
+            m_globalMeta.push_back(ossimString(attrName) + ": " + ossimString(attrValue));
+            free(attrValue);
+         }
+         else
+         {
+            ossim_int32 size = getSizeByType(dataType);
+            char* attrValue = new char[size * numValues];
+            SDreadattr(m_sd_id, i, (VOIDP)attrValue);
+            ossimString values = getAttribuitValues(dataType, numValues, attrValue);
+            m_globalMeta.push_back(ossimString(attrName) + ": " + values);
+            delete[] attrValue;
+         }   
+      }
+   }
+
+   initHdfDataType();
+   initSubdatasetNames();
+   initGroupInfos();
+
+   return initSubDatasets(numDatasets);
+}
+
+ossim_int32 ossimHdf4Reader::getSizeByType(int32 dataType) const
+{
+   if ( dataType == DFNT_CHAR8 || dataType == DFNT_UCHAR8 )
+   {
+      return 1;
+   }
+   else if (dataType == DFNT_INT8 || dataType == DFNT_UINT8)
+   {
+      return 1;
+   }
+   else if (dataType == DFNT_INT16 || dataType == DFNT_UINT16)
+   {
+      return 2;
+   }
+   else if (dataType == DFNT_INT32 || dataType == DFNT_UINT32 
+      || dataType == DFNT_FLOAT32)
+   {
+      return 4;
+   }
+   else if (dataType == DFNT_DOUBLE || dataType == DFNT_FLOAT64)
+   {
+      return 8;
+   }
+
+   return 4;
+}
+
+void ossimHdf4Reader::initSubdatasetNames()
+{
+   m_subDatasetNames.clear();
+   std::vector<ossimString> attrList = m_structMetadata.split("\n");
+   std::vector<ossimString> attrInfos;
+   ossimString groupIdentifier;
+   ossimString endGroupIdentifier;
+   ossimString groupName;
+
+   for (ossim_uint32 i  = 0; i < attrList.size(); i++)
+   {
+      ossimString attrInfo = attrList[i].trim();
+      if (attrInfo.contains("GROUP=SwathStructure") && m_subDatasetNames.size() == 0)//initialize the type and group name
+      {
+         m_hdfDataType = HDF4_EOS_SWATH;
+         groupIdentifier = "GROUP=SWATH_";
+         groupName = "SwathName";
+      }
+      else if (attrInfo.contains("GROUP=GridStructure") && m_subDatasetNames.size() == 0)//initialize the type and group name
+      {
+         m_hdfDataType = HDF4_EOS_GRID;
+         groupIdentifier = "GROUP=GRID_";
+         groupName = "GridName";
+      }
+      else //get sub dataset infos
+      {
+         if (attrInfo.contains(groupIdentifier) && attrInfo.contains("END_") == false)
+         {
+            endGroupIdentifier = "END_" + attrInfo;
+         }
+         if (attrInfo != endGroupIdentifier)
+         {
+            attrInfos.push_back(attrInfo);
+         } 
+         else
+         {
+            parseGroupName(attrInfos, groupName);
+            attrInfos.clear();
+         }
+      }
+   }
+}
+
+void ossimHdf4Reader::parseGroupName(std::vector<ossimString> groupInfo,
+                                     ossimString groupName)
+{
+   for (ossim_uint32 i = 0; i < groupInfo.size(); i++)
+   {
+      ossimString info = groupInfo[i];
+      if (info.contains(groupName))
+      {
+         groupName = info.split("=")[1].trim();
+         groupName = groupName.substitute("\"", "", true);
+      }
+      if (info.contains("GeoFieldName") || info.contains("DataFieldName"))
+      {
+         ossimString fieldName = info.split("=")[1].trim();
+         fieldName = fieldName.substitute("\"", "", true);
+         m_subDatasetNames.insert(ossimString(groupName + ":" + fieldName));
+      }
+   }
+}
+
+void ossimHdf4Reader::initGroupInfos()
+{
+   m_groupInfos.clear();
+
+   char vgName[1024];	/* Object name */
+   char vgClass[1024];	/* Object class */
+   int32 vgRef = -1;
+   int32 vgroupId;
+
+   Vstart(m_fid);
+   while (1)
+   {
+      // Get Vgroup reference number 
+      vgRef = Vgetid(m_fid, vgRef);
+
+      // If no more then exist search loop
+      if (vgRef == -1)
+      {
+         break;
+      }
+
+      // Get Vgroup ID, name, and class 
+      vgroupId = Vattach(m_fid, vgRef, "r");
+      Vgetname(vgroupId, vgName);
+      Vgetclass(vgroupId, vgClass);
+
+      //get "Fields" and "Attributes" info (SDS ids) from Vgroups
+      if (m_isHdfEos)
+      {
+         if (ossimString(vgClass).upcase() == m_hdfDataType)
+         {
+            int32 numObjects = Vntagrefs(vgroupId); //Get # of entries within this Vgroup and search for SDS
+
+            int32* tags = (int32 *) malloc(sizeof(int32) * numObjects);
+            int32* refs = (int32 *) malloc(sizeof(int32) * numObjects);
+
+            Vgettagrefs(vgroupId, tags, refs, numObjects); 
+
+            for (ossim_int32 i = 0; i < numObjects; i++) // Get tag and ref # for each Vgroup objects
+            {
+               int32 vgRefId = Vattach(m_fid, refs[i], "r");
+
+               int32 numRefObjects = Vntagrefs(vgRefId);
+               int32* tagsObj = (int32 *) malloc(sizeof(int32) * numRefObjects);
+               int32* refsObj = (int32 *) malloc(sizeof(int32) * numRefObjects);
+
+               Vgettagrefs(vgRefId, tagsObj, refsObj, numRefObjects);
+
+               for (ossim_int32 j = 0; j < numRefObjects; j++)
+               {
+                  if (tagsObj[j] == DFTAG_NDG)
+                  {
+                     int32 index = SDreftoindex(m_sd_id, refsObj[j]);
+                     int32 sdid = SDselect(m_sd_id, index);
+                     m_groupInfos[sdid] = ossimString(vgName);
+                  }
+               }
+               free(tagsObj);
+               free(refsObj);
+            }
+            free(tags);
+            free(refs);
+         }
+      }
+      // Detach Vgroup 
+      Vdetach(vgroupId);
+   }
+   Vend(m_fid);  
+}
+
+bool ossimHdf4Reader::initSubDatasets(int32 numDatasets)
+{
+   m_subDatasets.clear();
+   m_groupDatasets.clear();
+
+   int32 dim_sizes[H4_MAX_VAR_DIMS];
+   int32 rank, data_type, n_attrs;
+   char  name[H4_MAX_NC_NAME];
+   int32 bands, rows, cols;
+
+   std::vector<ossimHdfSubdataset> subDatasets;
+   for (ossim_int32 index = 0; index < numDatasets; index++)
+   {
+      int32 sds_id = SDselect (m_sd_id, index);
+      // int32 status = SDgetinfo (sds_id, name, &rank, dim_sizes, &data_type, &n_attrs);
+      SDgetinfo (sds_id, name, &rank, dim_sizes, &data_type, &n_attrs);
+
+      //get bands, rows, cols info
+      if (rank == 3)
+      {
+         bands = dim_sizes[0];
+         rows = dim_sizes[1];
+         cols = dim_sizes[2];
+      }
+      else if (rank == 2)
+      {
+         bands = 1;
+         rows = dim_sizes[0];
+         cols = dim_sizes[1];
+      }
+      else if (rank == 1)
+      {
+         bands = dim_sizes[0];
+         rows = 0;
+         cols = 0;
+      }
+      else
+      {
+         bands = 0;
+         rows = 0;
+         cols = 0;
+      }
+
+      if (m_isHdfEos)
+      {
+         std::map<int32, ossimString>::iterator it = m_groupInfos.find(sds_id);
+         if (it != m_groupInfos.end())
+         {
+            ossimString groupName = it->second;
+
+            ossimString subsetdataName = groupName + ":" + ossimString(name);
+
+            std::set<ossimString>::iterator subIt = m_subDatasetNames.find(subsetdataName);
+
+            if (subIt != m_subDatasetNames.end())
+            {
+               subDatasets.push_back(ossimHdfSubdataset(index, 
+                  subsetdataName, 
+                  data_type, 
+                  rank, 
+                  bands, 
+                  rows, 
+                  cols,
+                  n_attrs));
+            }
+         }
+      }
+      else
+      {
+         if (m_hdfDataType == HDF4_HYPERION_L1)
+         {
+            if (rank == 3)
+            {
+               bands = dim_sizes[1];
+               rows = dim_sizes[0];
+               cols = dim_sizes[2];
+            }
+         }
+         subDatasets.push_back(ossimHdfSubdataset(index, 
+            ossimString(name), 
+            data_type, 
+            rank, 
+            bands, 
+            rows, 
+            cols,
+            n_attrs));
+      }
+
+      SDendaccess(sds_id);
+   }
+
+   if (subDatasets.size() > 0)
+   {
+      if (m_isHdfEos)
+      {
+         ossimString subName = subDatasets[0].m_name;
+         ossimString groupName = subName.split(":")[0];
+         ossim_uint32 index;
+         std::vector<ossimHdfSubdataset> geoSubDatasets;
+         std::vector<ossimHdfSubdataset> dataSubDatasets;
+         for (index = 0; index < subDatasets.size(); index++)
+         {
+            ossimString subNameTmp = subDatasets[index].m_name;
+            ossimString groupNameTmp = subNameTmp.split(":")[0];
+            ossimString fieldName = subNameTmp.split(":")[1];
+            if (groupNameTmp == groupName)
+            {
+               if (fieldName == "Longitude" || fieldName == "Latitude")
+               {
+                  geoSubDatasets.push_back(subDatasets[index]);
+               }
+               else
+               {
+                  dataSubDatasets.push_back(subDatasets[index]);
+               }
+            }
+            else
+            {
+               m_groupDatasets.push_back(ossimHdfGroupData(groupName,
+                  geoSubDatasets,
+                  dataSubDatasets));
+
+               groupName = groupNameTmp;
+               geoSubDatasets.clear();
+               dataSubDatasets.clear();
+
+               //insert first dataset for a different group
+               if (fieldName == "Longitude" || fieldName == "Latitude")
+               {
+                  geoSubDatasets.push_back(subDatasets[index]);
+               }
+               else
+               {
+                  dataSubDatasets.push_back(subDatasets[index]);
+               }
+            }
+         }
+
+         //insert last datasets to the group 
+         if (index == subDatasets.size())
+         {
+            m_groupDatasets.push_back(ossimHdfGroupData(groupName,
+               geoSubDatasets,
+               dataSubDatasets));
+         }
+      }
+      else
+      {
+         m_subDatasets = subDatasets;
+      }
+   }
+
+   //only insert data field data to the vector of sub datasets, not geo field data
+   for (ossim_uint32 index = 0; index < m_groupDatasets.size(); index++)
+   {
+      std::vector<ossimHdfSubdataset> dataSubdatasets = m_groupDatasets[index].m_dataSubdatasets;
+      for (ossim_uint32 dataIndex = 0; dataIndex < dataSubdatasets.size(); dataIndex++)
+      {
+         m_subDatasets.push_back(dataSubdatasets[dataIndex]);
+      }
+   }
+
+   if (m_subDatasets.size() > 0)
+   {
+      return true;
+   }
+   return false;
+}
+
+ossimString ossimHdf4Reader::getAttribuitValues(int32 dataType, 
+                                                int32 numValues,
+                                                void* attrValue) const
+{
+   ossimString values;
+
+   if (dataType == DFNT_INT8)
+   {
+      int8* int8Data = (int8*)attrValue;
+      for (ossim_int32 j = 0; j < numValues; j++)
+      {
+         ossimString valueStr = ossimString::toString(int8Data[j]);
+         values = values + ossimString(valueStr + " ");
+      }
+   }
+   else if (dataType == DFNT_UINT8)
+   {
+      uint8* uint8Data = (uint8*)attrValue;
+      for (ossim_int32 j = 0; j < numValues; j++)
+      {
+         ossimString valueStr = ossimString::toString(uint8Data[j]);
+         values = values + ossimString(valueStr + " ");
+      }
+   }
+   else if (dataType == DFNT_INT16)
+   {
+      int16* int16Data = (int16*)attrValue;
+      for (ossim_int32 j = 0; j < numValues; j++)
+      {
+         ossimString valueStr = ossimString::toString(int16Data[j]);
+         values = values + ossimString(valueStr + " ");
+      }
+   }
+   else if (dataType == DFNT_UINT16)
+   {
+      uint16* uint16Data = (uint16*)attrValue;
+      for (ossim_int32 j = 0; j < numValues; j++)
+      {
+         ossimString valueStr = ossimString::toString(uint16Data[j]);
+         values = values + ossimString(valueStr + " ");
+      }
+   }
+   else if (dataType == DFNT_INT32 || dataType == DFNT_UINT32)
+   {
+      ossim_int32* int32Data = (ossim_int32*)attrValue;
+      for (ossim_int32 j = 0; j < numValues; j++)
+      {
+         ossimString valueStr = ossimString::toString(int32Data[j]);
+         values = values + ossimString(valueStr + " ");
+      }
+   }
+   else if (dataType == DFNT_FLOAT64 || dataType == DFNT_DOUBLE)
+   {
+      double* doubleData = (double*)attrValue;
+      for (ossim_int32 j = 0; j < numValues; j++)
+      {
+         ossimString valueStr = ossimString::toString(doubleData[j]);
+         values = values + ossimString(valueStr + " ");
+      }
+   }
+   else
+   {
+      float32* floatData = (float32*)attrValue;
+      for (ossim_int32 j = 0; j < numValues; j++)
+      {
+         ossimString valueStr = ossimString::toString(floatData[j]);
+         values = values + ossimString(valueStr + " ");
+      }
+   }
+   return values;
+}
+
+void ossimHdf4Reader::parseMetaString(ossimString attrStr)
+{
+   std::vector<ossimString> attrList = attrStr.split("\n");
+   ossimString className = "";
+   for (ossim_uint32 i  = 0; i < attrList.size(); i++)
+   {
+      ossimString attrValue = attrList[i];
+
+      if (attrValue.contains("OBJECT") && attrValue.contains("=") && !attrValue.contains("END_OBJECT"))
+      {
+         if (attrValue.split("=").size() > 1)
+         {
+            if (attrValue.split("=")[1].trim() != "PARAMETERVALUE") //will use the value of this class
+            {
+               className = attrValue.split("=")[1].trim();
+            }
+         }
+      }
+      else if (attrValue.contains("VALUE") && attrValue.contains("="))
+      {
+         if (attrValue.split("=").size() > 1)
+         {
+            ossimString classValue = attrValue.split("=")[1].trim();
+            classValue = classValue.substitute("\"", "", true);
+            classValue = classValue.substitute("(", "", true);
+            classValue = classValue.substitute(")", "", true);
+            if (className == "ADDITIONALATTRIBUTENAME") //skip this class name to get the value for this class
+            {
+               className = classValue;
+               continue;
+            }
+            if (classValue != "PARAMETERVALUE")
+            {
+               m_globalMeta.push_back(ossimString(className +  ": " + classValue));
+            }
+         }
+      }
+   }
+}
+
+void ossimHdf4Reader::initHdfDataType()
+{
+   for (ossim_uint32 i = 0; i < m_globalMeta.size(); i++)
+   {
+      ossimString meta = m_globalMeta[i];
+      ossimString metaName = meta.split(":")[0];
+      ossimString metaValue = meta.split(":")[1];
+      if (metaName == "Title")
+      {
+         if (metaValue == "SeaWiFS Level-1A Data")
+         {
+            m_hdfDataType = HDF4_SEAWIFS_L1A;
+         }
+         else if (metaValue == "SeaWiFS Level-2 Data")
+         {
+            m_hdfDataType = HDF4_SEAWIFS_L2;
+         }
+         else if (metaValue == "SeaWiFS Level-3 Standard Mapped Image")
+         {
+            m_hdfDataType = HDF4_SEAWIFS_L3;
+         }
+      }
+      else if (metaName == "L1 File Generated By")
+      {
+         if (metaValue.contains("HYP version "))
+         {
+            m_hdfDataType = HDF4_HYPERION_L1;
+         }
+      }
+      else if (metaName == "HDFEOSVersion")
+      {
+         m_isHdfEos = true;
+      }
+      else
+      {
+         m_hdfDataType = "UNKNOWN";
+      }
+   }
+}
+
+bool ossimHdf4Reader::isOpen()const
+{
+   return m_currentSubDataset != NULL;
+}
+
+void ossimHdf4Reader::closeEntry()
+{
+   m_tile = 0;
+   SDendaccess(m_sd_id);
+   SDend(m_sd_id); 
+   Hclose(m_fid);
+
+   if (m_currentSubDataset != NULL)
+   {
+      delete m_currentSubDataset;
+      m_currentSubDataset = 0;
+   }
+   ossimImageHandler::close();
+}
+
+ossimRefPtr<ossimImageData> ossimHdf4Reader::getTile(const ossimIrect& tile_rect, 
+                                                     ossim_uint32 resLevel)
+{
+   if (m_tile.valid())
+   {
+      // Image rectangle must be set prior to calling getTile.
+      m_tile->setImageRectangle(tile_rect);
+
+      if ( getTile( m_tile.get(), resLevel ) == false )
+      {
+         if (m_tile->getDataObjectStatus() != OSSIM_NULL)
+         {
+            m_tile->makeBlank();
+         }
+      }
+   }
+
+   return m_tile;
+}
+
+bool ossimHdf4Reader::getTile(ossimImageData* result,
+                              ossim_uint32 resLevel)
+{
+   bool status = false;
+
+   //---
+   // Not open, this tile source bypassed, or invalid res level,
+   // return a blank tile.
+   //---
+   if( isOpen() && isSourceEnabled() && isValidRLevel(resLevel) &&
+      result && (result->getNumberOfBands() == getNumberOfOutputBands()) )
+   {
+      result->ref();  // Increment ref count.
+
+      //---
+      // Check for overview tile.  Some overviews can contain r0 so always
+      // call even if resLevel is 0.  Method returns true on success, false
+      // on error.
+      //---
+      status = getOverviewTile(resLevel, result);
+
+      if (!status) // Did not get an overview tile.
+      {
+         status = true;
+
+         ossimIrect tile_rect = result->getImageRectangle();     
+
+         if (getImageRectangle().intersects(tile_rect))
+         {
+            // Make a clip rect.
+            ossimIrect clipRect = tile_rect.clipToRect(getImageRectangle());
+
+            if (tile_rect.completely_within(clipRect) == false)
+            {
+               // Not filling whole tile so blank it out first.
+               result->makeBlank();
+            }
+
+            if (m_currentSubDataset != NULL)
+            {
+               for (ossim_uint32 band = 0; band < getNumberOfInputBands(); band++)
+               {
+                  void* dataBuffer = m_currentSubDataset->getTileBuf(clipRect, band);
+                  result->loadBand(dataBuffer, clipRect, band);
+                  delete[] (char*)dataBuffer;
+               }
+            }
+         }
+         else // No intersection...
+         {
+            result->makeBlank();
+         }
+      }
+      result->validate();
+      result->unref();  // Decrement ref count.
+   }
+
+   return status;
+}
+
+ossim_uint32 ossimHdf4Reader::getNumberOfInputBands() const
+{
+   if (m_currentSubDataset != NULL)
+   {
+      return m_currentSubDataset->getNumberOfInputBands();
+   }
+   return m_numberOfBands;
+}
+
+ossim_uint32 ossimHdf4Reader::getNumberOfOutputBands()const
+{
+   return getNumberOfInputBands();
+}
+
+ossim_uint32 ossimHdf4Reader::getImageTileWidth() const
+{
+   return m_imageRect.width();
+}
+
+ossim_uint32 ossimHdf4Reader::getImageTileHeight() const
+{
+   return m_imageRect.height();
+}
+
+ossimScalarType ossimHdf4Reader::getOutputScalarType() const
+{
+   if (m_currentSubDataset != NULL)
+   {
+      return m_currentSubDataset->getOutputScalarType();
+   }
+   return m_scalarType;
+}
+
+ossimRefPtr<ossimImageGeometry> ossimHdf4Reader::getImageGeometry()
+{
+   if ( !theGeometry )
+   {
+      //---
+      // Check for external geom:
+      //---
+      theGeometry = getExternalImageGeometry();
+
+      if ( !theGeometry )
+      {
+         //---
+         // Check the internal geometry first to avoid a factory call.
+         //---
+         theGeometry = getInternalImageGeometry();
+
+         // At this point it is assured theGeometry is set.
+
+         // Check for set projection.
+         if ( !theGeometry->getProjection() )
+         {
+            // Try factories for projection.
+            ossimImageGeometryRegistry::instance()->extendGeometry(this);
+         }
+      }
+
+      // Set image things the geometry object should know about.
+      initImageParameters( theGeometry.get() );
+   }
+
+   return theGeometry;
+}
+
+ossimRefPtr<ossimImageGeometry> ossimHdf4Reader::getInternalImageGeometry() const
+{
+   static const char MODULE[] = "ossimHdf4Reader::getInternalImageGeometry";
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " entered...\n";
+   }
+
+   ossimRefPtr<ossimImageGeometry> geom = new ossimImageGeometry();
+
+   // Set the projection and return this handler's image geometry:
+   if (m_hdfDataType == HDF4_EOS_SWATH)
+   {
+      geom->setProjection(processSwathProjection().get());
+   }
+   else if (m_hdfDataType == HDF4_EOS_GRID)
+   {
+      geom->setProjection(processGridProjection().get());
+   }
+   else if (m_hdfDataType == HDF4_SEAWIFS_L3)
+   {
+      if (m_currentEntryRender < m_subDatasets.size())
+      {
+         ossim_float64 ulx = getMetaValue("Westernmost Longitude").toDouble();
+         ossim_float64 uly = getMetaValue("Northernmost Latitude").toDouble();
+         ossim_float64 lrx = getMetaValue("Easternmost Longitude").toDouble();
+         ossim_float64 lry = getMetaValue("Southernmost Latitude").toDouble();
+
+         int32 rows = m_subDatasets[m_currentEntryRender].m_rows;
+         int32 cols = m_subDatasets[m_currentEntryRender].m_cols;
+
+         ossim_float64 xRes = (lrx - ulx)/cols;
+         ossim_float64 yRes = (uly - lry)/rows;
+         ossimDpt gsd(fabs(xRes), fabs(yRes));
+
+         ossimGpt gTie(uly, ulx);
+         ossimString name = "EPSG:4326";
+         ossimRefPtr<ossimProjection> proj = ossimEpsgProjectionFactory::instance()->createProjection(name);
+         ossimMapProjection* mapProj = dynamic_cast<ossimMapProjection*>(proj.get());
+         mapProj->setUlTiePoints(gTie);
+         mapProj->setDecimalDegreesPerPixel(gsd);
+
+         geom->setProjection(mapProj);
+      }
+   }
+
+   return geom;
+}
+
+ossimRefPtr<ossimProjection> ossimHdf4Reader::processGridProjection() const
+{
+   if (m_structMetadata.empty())
+      return 0;
+
+   int32   zoneCode = 0;
+   int32   sphereCode = 0;
+   int32   xSize = 0;
+   int32   ySize = 0;
+   std::vector<ossim_float64> upLeftValues;
+   std::vector<ossim_float64> lowRightValues;
+   std::vector<ossim_float64> projParms;
+   ossimString projName;
+
+   std::vector<ossimString> attrList = m_structMetadata.split("\n");
+   for (ossim_uint32 i = 0; i < attrList.size(); i++)
+   {
+      ossimString attrInfo = attrList[i].trim();
+      attrInfo = attrInfo.substitute("\"", "", true);
+      attrInfo = attrInfo.substitute("(", "", true);
+      attrInfo = attrInfo.substitute(")", "", true);
+      if (attrInfo.contains("="))
+      {
+         ossimString metaName = attrInfo.split("=")[0].trim();
+         ossimString metaValue = attrInfo.split("=")[1].trim();
+         if (metaName == "XDim")
+         {
+            xSize = metaValue.toInt();
+         }
+         if (metaName == "YDim")
+         {
+            ySize = metaValue.toInt32();
+         }
+         if (metaName == "Projection")
+         {
+            projName = metaValue;
+         }
+         if (metaName == "ZoneCode")
+         {
+            zoneCode = metaValue.toInt32();
+         }
+         if (metaName == "ProjParams")
+         {
+            for (ossim_uint32 paramIndex = 0; paramIndex < metaValue.split(",").size(); paramIndex++)
+            {
+               projParms.push_back(metaValue.split(",")[paramIndex].toDouble());
+            }
+         }
+         if (metaName == "UpperLeftPointMtrs")
+         {
+            for (ossim_uint32 ulIndex = 0; ulIndex < metaValue.split(",").size(); ulIndex++)
+            {
+               upLeftValues.push_back(metaValue.split(",")[ulIndex].toDouble());
+            }
+         }
+         if (metaName == "LowerRightMtrs")
+         {
+            for (ossim_uint32 lrIndex = 0; lrIndex < metaValue.split(",").size(); lrIndex++)
+            {
+               lowRightValues.push_back(metaValue.split(",")[lrIndex].toDouble());
+            }
+         }
+         if (metaName == "SphereCode")
+         {
+            sphereCode = metaValue.toInt32();
+         } 
+      }
+   }
+
+   //calculate w-e pixel resolution and n-s pixel resolution 
+   ossim_float64 xRes = 0.0;
+   ossim_float64 yRes = 0.0;
+   if (lowRightValues.size() == 2 && upLeftValues.size() == 2 && ySize > 0 && xSize > 0)
+   {
+      xRes = (lowRightValues[0] - upLeftValues[0]) / xSize;
+      yRes = (lowRightValues[1] - upLeftValues[1]) / ySize;
+   }
+   ossimDpt gsd(fabs(xRes), fabs(yRes));
+
+   //create the map projection
+   ossimRefPtr<ossimMapProjection> mapProj = 0;
+   if (projName == "GCTP_GEO") //Geographic
+   {
+      // Tie point is expressed as lat lon:
+      ossimGpt gTie(upLeftValues[1], upLeftValues[0]);
+      ossimString epsg("EPSG:4326");
+      mapProj = PTR_CAST(ossimMapProjection, 
+         ossimEpsgProjectionFactory::instance()->createProjection(epsg));
+      mapProj->setUlTiePoints(gTie);
+      mapProj->setDecimalDegreesPerPixel(gsd);
+   }
+   else 
+   {
+      // Map projection, tie point expressed as easting northing:
+      ossimDpt tie(upLeftValues[0], upLeftValues[1]);
+
+      if (projName == "GCTP_UTM")
+         mapProj = new ossimUtmProjection(zoneCode);
+      else if (projName == "GCTP_LAMCC") 
+         mapProj = new ossimLambertConformalConicProjection();
+      else if (projName == "GCTP_PS") 
+         mapProj = new ossimPolarStereoProjection();
+      else if (projName == "GCTP_POLYC") 
+         mapProj = new ossimPolyconicProjection();
+      else if (projName == "GCTP_TM") 
+         mapProj = new ossimMercatorProjection();
+      else if (projName == "GCTP_LAMAZ") 
+         mapProj = new ossimAzimEquDistProjection();
+      else if (projName == "GCTP_HOM") 
+         mapProj = new ossimObliqueMercatorProjection();
+      else if (projName == "GCTP_SOM") 
+         mapProj = new ossimSpaceObliqueMercatorProjection();
+      else if (projName == "GCTP_ISINUS" || projName == "GCTP_SNSOID") 
+         mapProj = new ossimSinusoidalProjection();
+
+      mapProj->setUlTiePoints(tie);
+      mapProj->setMetersPerPixel(gsd);
+   }
+
+   ossimRefPtr<ossimProjection> return_pointer (mapProj.get());
+   return return_pointer;
+}
+
+ossimRefPtr<ossimProjection> ossimHdf4Reader::processSwathProjection() const
+{
+   if (m_currentEntryRender < m_subDatasets.size())
+   {
+      ossim_int32 latGridIndex = -1;
+      ossim_int32 lonGridIndex = -1;
+      ossim_int32 spacingX = -1;
+      ossim_int32 spacingY = -1;
+      ossim_int32 latticePointIndex = -1;
+
+      ossim_int32 latGridRows = 0;
+      ossim_int32 latGridCols = 0;
+      ossim_int32 lonGridRows = 0;
+      ossim_int32 lonGridCols = 0;
+      bool hasGeoData = false;
+    
+      std::vector<float64> latticeYPoints;
+      std::vector<float64> latticeXPoints;
+
+      ossimString subDatasetName = m_subDatasets[m_currentEntryRender].m_name;
+      ossimString groupName = subDatasetName.split(":")[0];
+
+      for (ossim_uint32 i = 0; i < m_groupDatasets.size(); i++)
+      {
+         if (groupName == m_groupDatasets[i].m_groupName)
+         {
+            //get lat and lon info
+            if (m_groupDatasets[i].m_geoSubdatasets.size() > 0)
+            {
+               for (ossim_uint32 j = 0; j < m_groupDatasets[i].m_geoSubdatasets.size(); j++)
+               {
+                  if (m_groupDatasets[i].m_geoSubdatasets[j].m_name.contains("Longitude"))
+                  {
+                     lonGridIndex = m_groupDatasets[i].m_geoSubdatasets[j].m_sdsIndex;
+                     lonGridCols = m_groupDatasets[i].m_geoSubdatasets[j].m_cols;
+                     lonGridRows = m_groupDatasets[i].m_geoSubdatasets[j].m_rows;
+                     hasGeoData = true;
+                  }
+                  if (m_groupDatasets[i].m_geoSubdatasets[j].m_name.contains("Latitude"))
+                  {
+                     latGridIndex = m_groupDatasets[i].m_geoSubdatasets[j].m_sdsIndex;
+                     latGridCols = m_groupDatasets[i].m_geoSubdatasets[j].m_cols;
+                     latGridRows = m_groupDatasets[i].m_geoSubdatasets[j].m_rows;
+                     hasGeoData = true;
+                  }
+               }
+            }
+
+            //get lattice point info
+            if (m_groupDatasets[i].m_dataSubdatasets.size() > 0)
+            {
+               for (ossim_uint32 j = 0; j < m_groupDatasets[i].m_dataSubdatasets.size(); j++)
+               {
+                  if (m_groupDatasets[i].m_dataSubdatasets[j].m_name.contains("LatticePoint"))
+                  {
+                     latticePointIndex = m_groupDatasets[i].m_dataSubdatasets[j].m_sdsIndex;
+                  }
+               }
+            }
+         }
+      }
+
+      if (hasGeoData)
+      {
+         if (latticePointIndex < 0)
+         {
+            ossim_uint32 rows = m_subDatasets[m_currentEntryRender].m_rows;
+            ossim_uint32 cols = m_subDatasets[m_currentEntryRender].m_cols;
+            if (rows % latGridRows == 0 && cols % lonGridCols == 0)
+            {
+               spacingY = rows/latGridRows; //line increment step
+               spacingX = cols/lonGridCols; //pixel increment step
+            }
+            else if (rows % (latGridRows-1) == 0 && cols % (lonGridCols-1) == 0)//ASTER L1A and L1B
+            {
+               spacingY = rows/(latGridRows-1); //line increment step
+               spacingX = cols/(lonGridCols-1); //pixel increment step
+            }
+            else if (rows % latGridRows == 0 && cols % (lonGridCols-1) == 0)
+            {
+               spacingY = rows/latGridRows; //line increment step
+               spacingX = cols/(lonGridCols-1); //pixel increment step
+            }
+            else if (rows % (latGridRows-1) == 0 && cols % lonGridCols == 0)
+            {
+               spacingY = rows/(latGridRows-1); //line increment step
+               spacingX = cols/lonGridCols; //pixel increment step
+            }
+            else if ((rows+1) % latGridRows == 0 && (cols+1) % lonGridCols == 0)
+            {
+               spacingY = (rows+1)/latGridRows; //line increment step
+               spacingX = (cols+1)/lonGridCols; //pixel increment step
+            }
+            else if ((rows+1) % latGridRows == 0 && cols % lonGridCols == 0)
+            {
+               spacingY = (rows+1)/latGridRows; //line increment step
+               spacingX = cols/lonGridCols; //pixel increment step
+            }
+            else if (rows % latGridRows == 0 && (cols+1) % lonGridCols == 0)
+            {
+               spacingY = rows/latGridRows; //line increment step
+               spacingX = (cols+1)/lonGridCols; //pixel increment step
+            }
+            ossimIpt spacing(spacingX, spacingY);
+            ossimDrect rect(0, 0, cols-1, rows-1);
+            return new ossimHdfGridModel(theImageFile, rect, 
+                                         ossimString::toString(latGridIndex),
+                                         ossimString::toString(lonGridIndex), spacing);
+         }  
+         else
+         {
+            int32 dim_sizes[H4_MAX_VAR_DIMS];
+            int32 rank, data_type, n_attrs;
+            char  name[H4_MAX_NC_NAME];
+            int32 start[H4_MAX_NC_DIMS], edges[H4_MAX_NC_DIMS];
+
+            std::vector<float64> lat;
+            std::vector<float64> lon;
+            int32 sd_id = SDstart(theImageFile.c_str(), DFACC_READ);
+            int32 sds_id = SDselect(sd_id, latGridIndex);
+            int32 status = SDgetinfo(sds_id, name, &rank, dim_sizes, &data_type, &n_attrs);
+
+            if (status != -1)
+            {
+               start[0] = 0;
+               start[1] = 0;
+               edges[0] = dim_sizes[0];
+               edges[1] = dim_sizes[1];
+
+               ossim_int32 size = getSizeByType(data_type);
+               char* values = new char[size * dim_sizes[0]* dim_sizes[1]];
+
+               // intn statusN = SDreaddata(sds_id, start, NULL, edges, (VOIDP)values);
+               SDreaddata(sds_id, start, NULL, edges, (VOIDP)values);
+
+               if (data_type == DFNT_FLOAT64 || data_type == DFNT_DOUBLE)
+               {
+                  float64* doubleData = (float64*)values;
+                  for (int i = 0; i < dim_sizes[0]* dim_sizes[1]; i++)
+                  {
+                     lat.push_back(doubleData[i]);
+                  }
+               }
+               else
+               {
+                  float32* floatData = (float32*)values;
+                  for (int i = 0; i < dim_sizes[0]* dim_sizes[1]; i++)
+                  {
+                     lat.push_back(floatData[i]);
+                  }
+               }
+               delete[] values;
+            }
+            SDendaccess(sds_id); 
+
+            sds_id = SDselect(sd_id, lonGridIndex);
+            status = SDgetinfo(sds_id, name, &rank, dim_sizes, &data_type, &n_attrs);
+
+            if (status != -1)
+            {
+               start[0] = 0;
+               start[1] = 0;
+               edges[0] = dim_sizes[0];
+               edges[1] = dim_sizes[1];
+
+               ossim_int32 size = getSizeByType(data_type);
+               char* values = new char[size * dim_sizes[0]* dim_sizes[1]];
+
+               // intn statusN = SDreaddata(sds_id, start, NULL, edges, (VOIDP)values);
+               SDreaddata(sds_id, start, NULL, edges, (VOIDP)values);
+
+               if (data_type == DFNT_FLOAT64 || data_type == DFNT_DOUBLE)
+               {
+                  float64* doubleData = (float64*)values;
+                  for (int i = 0; i < dim_sizes[0]* dim_sizes[1]; i++)
+                  {
+                     lon.push_back(doubleData[i]);
+                  }
+               }
+               else
+               {
+                  float32* floatData = (float32*)values;
+                  for (int i = 0; i < dim_sizes[0]* dim_sizes[1]; i++)
+                  {
+                     lon.push_back(floatData[i]);
+                  }
+               }
+               delete[] values;
+               SDendaccess(sds_id); 
+
+
+               sds_id = SDselect(sd_id, latticePointIndex);
+               status = SDgetinfo(sds_id, name, &rank, dim_sizes, &data_type, &n_attrs);
+               if (rank == 3)
+               {
+                  int32 loopIndex = dim_sizes[0];
+                  int32 latticeY = dim_sizes[1];
+                  int32 latticeX = dim_sizes[2];
+                  for (int32 latticeIndex = 0; latticeIndex < loopIndex; latticeIndex++)
+                  {
+                     start[0] = latticeIndex;
+                     start[1] = 0;
+                     start[2] = 0;
+                     edges[0] = 1;
+                     edges[1] = latticeY; 
+                     edges[2] = latticeX; 
+
+                     ossim_int32 size = getSizeByType(data_type);
+                     char* values = new char[size * latticeY*latticeX];
+
+                     // intn statusLattice = SDreaddata(sds_id, start, NULL, edges, (VOIDP)values);
+                     SDreaddata(sds_id, start, NULL, edges, (VOIDP)values);
+
+                     if (data_type == DFNT_INT32)
+                     {
+                        int32* intData = (int32*)values;
+                        for (int i = 0; i < latticeY*latticeX; i+=2)
+                        {
+                           latticeXPoints.push_back(intData[i]);
+                           latticeYPoints.push_back(intData[i+1]);
+                        }
+                     }
+                     else
+                     {
+                        float32* floatData = (float32*)values;
+                        for (int i = 0; i < latticeY* latticeX; i+=2)
+                        {
+                           latticeXPoints.push_back(floatData[i]);
+                           latticeYPoints.push_back(floatData[i+1]);
+                        }
+                     }
+                     delete[] values;
+                  }
+               }
+               SDendaccess(sds_id);
+               SDend (sd_id); 
+            }
+
+            ossimTieGptSet tieSet;
+            int iStepX = MAX(1,((dim_sizes[1]-1) / 11));
+            int iStepY = MAX(1,((dim_sizes[0]-1) / 11));
+
+            for (int y = 0; y < dim_sizes[0]; y += iStepY)
+            {
+               for (int x = 0; x < dim_sizes[1]; x += iStepX)
+               {
+                  int index = x + (y * dim_sizes[1]);
+                  if (index%10 == 0)
+                  {
+                     double dPixel = latticeXPoints[index] + 0.5;
+                     double dLine = latticeYPoints[index] + 0.5;
+
+                     ossimDpt dpt(dPixel, dLine);
+                     ossimGpt gpt(lat[index], lon[index]);
+                     tieSet.addTiePoint(new ossimTieGpt(gpt, dpt, .5));
+                  }
+               }
+            }
+
+            ossimRefPtr<ossimBilinearProjection> bilinProj = new ossimBilinearProjection;
+            bilinProj->optimizeFit(tieSet);
+            return bilinProj.get();
+         }
+      }
+   }
+
+   return ossimRefPtr<ossimProjection>();
+}
+
+bool ossimHdf4Reader::loadState(const ossimKeywordlist& kwl,
+                                const char* prefix)
+{
+   bool result = false;
+
+   if ( ossimImageHandler::loadState(kwl, prefix) )
+   {
+      result = open();
+   }
+
+   return result;
+}
+
+ossim_uint32 ossimHdf4Reader::getNumberOfEntries()const
+{
+   return (ossim_uint32) m_subDatasets.size();
+}
+
+bool ossimHdf4Reader::setCurrentEntry(ossim_uint32 entryIdx)
+{
+   if (m_currentEntryRender == entryIdx)
+   {
+      return true; // Nothing to do...
+   }
+   m_currentEntryRender = entryIdx;
+   theGeometry = 0;
+   theOverview = 0;
+   theOverviewFile.clear();
+   m_tile = 0;
+   return open();
+}
+
+std::vector<ossimString> ossimHdf4Reader::getSubDatasetMeta()
+{
+   if (m_currentSubDataset != NULL)
+   {
+      return m_currentSubDataset->getMetadata();
+   }
+   return std::vector<ossimString>();
+}
+
+void ossimHdf4Reader::getEntryList(std::vector<ossim_uint32>& entryList)const
+{
+   for (ossim_uint32 i = 0; i < m_subDatasets.size(); i++)
+   {
+      entryList.push_back(i);
+   }
+}
+
+ossimString ossimHdf4Reader::getMetaValue(const ossimString& key) const
+{
+   for (ossim_uint32 i = 0; i < m_globalMeta.size(); i++)
+   {
+      ossimString info = m_globalMeta[i];
+      ossimString keyTmp = info.split(":")[0].trim();
+      ossimString value = info.split(":")[1].trim();
+      if (keyTmp == key)
+      {
+         return value;
+      }
+   }
+   return "";
+}
+
+ossim_uint32 ossimHdf4Reader::getCurrentEntry()const
+{
+   return m_currentEntryRender;
+}
+
+
diff --git a/ossim_plugins/hdf4/ossimHdf4Reader.h b/ossim_plugins/hdf4/ossimHdf4Reader.h
new file mode 100644
index 0000000..70be514
--- /dev/null
+++ b/ossim_plugins/hdf4/ossimHdf4Reader.h
@@ -0,0 +1,305 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Description:  Class declaration HDF4 reader.
+//
+// Specification: ISO/IEC 15444
+//
+//----------------------------------------------------------------------------
+// $Id: ossimHdf4Reader.h 2645 2011-05-26 15:21:34Z oscar.kramer $
+
+#ifndef ossimHdf4Reader_HEADER
+#define ossimHdf4Reader_HEADER 1
+
+#include "../ossimPluginConstants.h"
+#include <ossim/base/ossimIpt.h>
+#include <ossim/base/ossimIrect.h>
+#include <ossim/imaging/ossimImageHandler.h>
+#include <ossim/imaging/ossimAppFixedTileCache.h>
+
+//HDF4 Includes
+// #include <hdf/hdf.h>
+// #include <hdf/mfhdf.h>
+#include <hdf.h>
+#include <mfhdf.h>
+
+#include <iosfwd>
+#include <fstream>
+#include <vector>
+#include <set>
+
+// Forward class declarations.
+class ossimImageData;
+class ossimDpt;
+class ossimHdf4SubDataset;
+class ossimBilinearProjection;
+
+class OSSIM_PLUGINS_DLL ossimHdf4Reader : public ossimImageHandler
+{
+public:
+
+   /** default construtor */
+   ossimHdf4Reader();
+   
+   /** virtural destructor */
+   virtual ~ossimHdf4Reader();
+
+   /**
+    * @brief Returns short name.
+    * @return "ossim_hdf4_reader"
+    */
+   virtual ossimString getShortName() const;
+   
+   /**
+    * @brief Returns long  name.
+    * @return "ossim hdf4 reader"
+    */
+   virtual ossimString getLongName()  const;
+
+   /**
+    * @brief Returns class name.
+    * @return "ossimHdf4Reader"
+    */
+   virtual ossimString getClassName() const;
+
+   /**
+    *  @brief Method to grab a tile(rectangle) from image.
+    *
+    *  @param rect The zero based rectangle to grab.
+    *
+    *  @param resLevel The reduced resolution level to grab from.
+    *
+    *  @return The ref pointer with the image data pointer.
+    */
+   virtual ossimRefPtr<ossimImageData> getTile(const  ossimIrect& rect,
+                                               ossim_uint32 resLevel=0);
+
+   virtual bool getTile(ossimImageData* result, ossim_uint32 resLevel=0);   
+
+   /**
+    *  Returns the number of bands in the image.
+    *  Satisfies pure virtual from ImageHandler class.
+    */
+   virtual ossim_uint32 getNumberOfInputBands() const;
+
+   /**
+    * Returns the number of bands in a tile returned from this TileSource.
+    * Note: we are supporting sources that can have multiple data objects.
+    * If you want to know the scalar type of an object you can pass in the
+    */
+   virtual ossim_uint32 getNumberOfOutputBands()const; 
+   /**
+    * Returns the tile width of the image or 0 if the image is not tiled.
+    * Note: this is not the same as the ossimImageSource::getTileWidth which
+    * returns the output tile width which can be different than the internal
+    * image tile width on disk.
+    */
+   virtual ossim_uint32 getImageTileWidth() const;
+
+   /**
+    * Returns the tile width of the image or 0 if the image is not tiled.
+    * Note: this is not the same as the ossimImageSource::getTileHeight which
+    * returns the output tile height which can be different than the internal
+    * image tile height on disk.
+    */
+   virtual ossim_uint32 getImageTileHeight() const;
+
+   /**
+    * Returns the output pixel type of the tile source.
+    */
+   virtual ossimScalarType getOutputScalarType() const;
+   
+
+   /**
+    * @brief Gets number of lines for res level.
+    *
+    *  @param resLevel Reduced resolution level to return lines of.
+    *  Default = 0
+    *
+    *  @return The number of lines for specified reduced resolution level.
+    */
+   virtual ossim_uint32 getNumberOfLines(ossim_uint32 resLevel = 0) const;
+
+   /**
+    *  @brief Gets the number of samples for res level.
+    *
+    *  @param resLevel Reduced resolution level to return samples of.
+    *  Default = 0
+    *
+    *  @return The number of samples for specified reduced resolution level.
+    */
+   virtual ossim_uint32 getNumberOfSamples(ossim_uint32 resLevel = 0) const;
+
+   /**
+    * @brief Open method.
+    * @return true on success, false on error.
+    */
+   virtual bool open();
+
+   /**
+    *  @brief Method to test for open file stream.
+    *
+    *  @return true if open, false if not.
+    */
+   virtual bool isOpen()const;
+
+   /**
+    * @brief Method to close current entry.
+    *
+    * @note There is a bool kdu_compressed_source::close() and a
+    * void ossimImageHandler::close(); hence, a new close to avoid conflicting
+    * return types.
+    */
+   virtual void closeEntry();
+
+   /**
+    * Returns the image geometry object associated with this tile source or
+    * NULL if non defined.  The geometry contains full-to-local image
+    * transform as well as projection (image-to-world).
+    */
+   virtual ossimRefPtr<ossimImageGeometry> getImageGeometry();
+
+   /**
+    * @param Method to get geometry.
+    */
+   virtual ossimRefPtr<ossimImageGeometry> getInternalImageGeometry() const;
+
+   /**
+    * @return The number of entries (images) in the image file.
+    */
+   virtual ossim_uint32 getNumberOfEntries()const;
+
+   /**
+    * @param entryList This is the list to initialize with entry indexes.
+    *
+    * @note This implementation returns puts one entry "0" in the list.
+    */
+   virtual void getEntryList(std::vector<ossim_uint32>& entryList) const;
+
+   /**
+    * Method to the load (recreate) the state of an object from a keyword
+    * list.  Return true if ok or false on error.
+    */
+   virtual bool loadState(const ossimKeywordlist& kwl, const char* prefix=0);   
+
+   virtual bool setCurrentEntry(ossim_uint32 entryIdx);
+
+   /**
+   * @return The current entry number.
+   */
+   virtual ossim_uint32 getCurrentEntry()const;
+
+   std::vector<ossimString> getGlobalMeta() { return m_globalMeta; }
+
+   std::vector<ossimString> getSubDatasetMeta();
+
+   ossimString getHdfDataType() const { return m_hdfDataType; }
+
+   ossimString getMetaValue(const ossimString& key) const;
+
+   static const ossimString HDF4_EOS_GRID;              // HDF-EOS Grid
+   static const ossimString HDF4_EOS_SWATH;             // HDF-EOS Swath
+   static const ossimString HDF4_SEAWIFS_L1A;		     // SeaWiFS Level-1A Data
+   static const ossimString HDF4_SEAWIFS_L2;	           // SeaWiFS Level-2 Data
+   static const ossimString HDF4_SEAWIFS_L3;		        // SeaWiFS Level-3 Standard Mapped Image
+   static const ossimString HDF4_HYPERION_L1;           // Hyperion L1 Data Product
+   static const ossimString HDF4_SDS;                   // SDS
+
+private:
+
+   struct ossimHdfSubdataset
+   {
+      ossimHdfSubdataset(int32        sdsIndex,
+                         ossimString  name,
+                         int32        dataType,
+                         int32        rank,
+                         int32        bands,
+                         int32        rows,
+                         int32        cols,
+                         int32        attributes)
+         :m_sdsIndex(sdsIndex),
+         m_name(name),
+         m_dataType(dataType),
+         m_rank(rank),
+         m_bands(bands),
+         m_rows(rows),
+         m_cols(cols),
+         m_attributes(attributes)
+      {}
+     
+      int32        m_sdsIndex;
+      ossimString  m_name;
+      int32        m_dataType;
+      int32        m_rank;
+      int32        m_bands;
+      int32        m_rows;
+      int32        m_cols;
+      int32        m_attributes;
+   };
+
+   struct ossimHdfGroupData
+   {
+      ossimHdfGroupData(ossimString groupName,
+         std::vector<ossimHdfSubdataset> geoSubdatasets,
+         std::vector<ossimHdfSubdataset> dataSubdatasets)
+
+         :m_groupName(groupName),
+         m_geoSubdatasets(geoSubdatasets),
+         m_dataSubdatasets(dataSubdatasets)
+      {}
+
+      ossimString m_groupName;
+      std::vector<ossimHdfSubdataset> m_geoSubdatasets;
+      std::vector<ossimHdfSubdataset> m_dataSubdatasets;
+   };
+
+  bool initGlobalMeta();
+
+  bool initSubDatasets(int32 numDatasets);
+
+  void initSubdatasetNames();
+
+  void parseGroupName(std::vector<ossimString> groupInfo, ossimString groupName);
+
+  void initGroupInfos();
+
+  ossimString getAttribuitValues(int32 dataType, int32 numValues, void* attrValue) const;
+
+  void parseMetaString(ossimString attrStr);
+
+  void initHdfDataType();
+
+  ossimRefPtr<ossimProjection> processSwathProjection() const;
+
+  ossimRefPtr<ossimProjection> processGridProjection() const;
+
+  ossim_int32 getSizeByType(int32 dataType) const;
+
+  ossim_int32                                        m_fid;
+  ossim_int32                                        m_sd_id;
+
+  ossimIrect                                         m_imageRect; /** Has sub image offset. */
+  
+  ossim_uint32                                       m_numberOfBands;
+  ossimScalarType                                    m_scalarType;
+  ossimRefPtr<ossimImageData>                        m_tile;
+
+  std::map<int32, ossimString>                       m_groupInfos;
+  std::set<ossimString>                              m_subDatasetNames;
+  std::vector<ossimHdfSubdataset>                    m_subDatasets;
+  std::vector<ossimHdfGroupData>                     m_groupDatasets;
+  std::vector<ossimString>                           m_globalMeta;
+  ossimString                                        m_hdfDataType;
+  bool                                               m_isHdfEos;
+  ossim_uint32                                       m_currentEntryRender;
+  ossimHdf4SubDataset*                               m_currentSubDataset;
+  ossimString                                        m_structMetadata;
+
+TYPE_DATA
+};
+
+#endif /* #ifndef ossimHdf4Reader_HEADER */
+
diff --git a/ossim_plugins/hdf4/ossimHdf4SubDataset.cpp b/ossim_plugins/hdf4/ossimHdf4SubDataset.cpp
new file mode 100644
index 0000000..85c1332
--- /dev/null
+++ b/ossim_plugins/hdf4/ossimHdf4SubDataset.cpp
@@ -0,0 +1,390 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Description:  Class definition for HDF reader.
+//
+//----------------------------------------------------------------------------
+// $Id: ossimHdf4SubDataset.cpp 2645 2011-05-26 15:21:34Z oscar.kramer $
+
+//Std includes
+#include <set>
+
+//ossim includes
+#include "ossimHdf4SubDataset.h"
+#include <ossim/base/ossimScalarTypeLut.h>
+#include <ossim/base/ossimTrace.h>
+#include <ossim/base/ossimUnitTypeLut.h>
+#include <ossim/imaging/ossimImageGeometryRegistry.h>
+#include <ossim/imaging/ossimImageDataFactory.h>
+//#include <ossim/base/ossimDrect.h>
+
+#ifdef OSSIM_ID_ENABLED
+static const char OSSIM_ID[] = "$Id";
+#endif
+
+static ossimTrace traceDebug("ossimHdf4SubDataset:debug");
+
+RTTI_DEF_INST(ossimHdf4SubDataset, "ossimHdf4SubDataset")
+
+bool doubleEquals(ossim_float64 left, ossim_float64 right, ossim_float64 epsilon) 
+{
+  return (fabs(left - right) < epsilon);
+}
+
+ossimHdf4SubDataset::ossimHdf4SubDataset() :
+   m_fileName(""), 
+   m_sd_name(""),
+   m_sds_index(-1),
+   m_sds_id(-1),
+   m_sd_id(-1),
+   m_rank(0),
+   m_numberOfBands(0),
+   m_numberOfSamples(0),
+   m_numberOfLines(0),
+   m_attributes(0),
+   m_isGeoField(false),
+   m_scalarType(OSSIM_SCALAR_UNKNOWN),
+   m_dataType(0),
+   m_hdfDataType(),
+   m_meta(0)
+{
+}
+
+ossimHdf4SubDataset::~ossimHdf4SubDataset()
+{
+   SDendaccess (m_sds_id); 
+   SDend (m_sd_id); 
+   m_meta.clear();
+}
+
+ossim_uint32 ossimHdf4SubDataset::getNumberOfLines(ossim_uint32 /* resLevel */) const
+{
+   return m_numberOfLines;
+}
+
+ossim_uint32 ossimHdf4SubDataset::getNumberOfSamples(ossim_uint32 /* resLevel */) const
+{
+   return m_numberOfSamples;
+}
+
+bool ossimHdf4SubDataset::open()
+{
+   static const char MODULE[] = "ossimHdf4SubDataset::open";
+
+   bool result = false;
+ 
+   m_sd_id = SDstart(m_fileName.c_str(), DFACC_READ);
+   if (m_sd_id < 0)
+   {
+      result = false;
+   }
+   else
+   {
+      result = true;
+   }
+
+   m_sds_id = SDselect(m_sd_id, m_sds_index);
+   if (m_sds_id < 0)
+   {
+      result = false;
+   }
+   else
+   {
+      result = true;
+   }
+
+   if (result == false)
+   {
+      SDendaccess (m_sds_id); 
+      SDend (m_sd_id); 
+   }
+   
+   initMeta();
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " exit status = " << (result?"true":"false\n")
+         << std::endl;
+   }
+
+   return result;
+}
+
+void ossimHdf4SubDataset::initMeta()
+{
+   m_meta.clear();
+
+   //insert name first
+   m_meta.push_back("name: " + ossimString(m_hdfDataType + ":" + m_sd_name));
+
+   char	attrName[100];
+   int32 numValues;
+   int32 dataType;
+
+   for (ossim_int32 i = 0; i < m_attributes; i++ )
+   {
+      // Get information about the attribute. Note that the first
+      // parameter is an SD interface identifier.
+      SDattrinfo(m_sds_id, i, attrName, &dataType, &numValues);
+      
+      ossim_int32 size = getDataTypeSize(dataType);
+      char* attrValue = new char[size * numValues + 1];
+      
+      SDreadattr(m_sds_id, i, attrValue);
+
+      if ( dataType == DFNT_CHAR8 || dataType == DFNT_UCHAR8 )
+      {
+         attrValue[numValues] = '\0';
+         m_meta.push_back(ossimString(attrName) + ": " + ossimString(attrValue).trim());
+      }
+      else
+      {
+         ossimString values = getAttribuitValues(dataType, numValues, attrValue);
+         m_meta.push_back(ossimString(attrName) + ": " + values);
+      }
+      delete [] attrValue;
+   }
+}
+
+ossimString ossimHdf4SubDataset::getAttribuitValues(int32 dataType, 
+                                                int32 numValues,
+                                                void* attrValue)
+{
+   ossimString values;
+
+   if (dataType == DFNT_INT8)
+   {
+      int8* int8Data = (int8*)attrValue;
+      for (ossim_int32 j = 0; j < numValues; j++)
+      {
+         ossimString valueStr = ossimString::toString(int8Data[j]);
+         values = values + ossimString(valueStr + " ");
+      }
+   }
+   else if (dataType == DFNT_UINT8)
+   {
+      uint8* uint8Data = (uint8*)attrValue;
+      for (ossim_int32 j = 0; j < numValues; j++)
+      {
+         ossimString valueStr = ossimString::toString(uint8Data[j]);
+         values = values + ossimString(valueStr + " ");
+      }
+   }
+   else if (dataType == DFNT_INT16)
+   {
+      int16* int16Data = (int16*)attrValue;
+      for (ossim_int32 j = 0; j < numValues; j++)
+      {
+         ossimString valueStr = ossimString::toString(int16Data[j]);
+         values = values + ossimString(valueStr + " ");
+      }
+   }
+   else if (dataType == DFNT_UINT16)
+   {
+      uint16* uint16Data = (uint16*)attrValue;
+      for (ossim_int32 j = 0; j < numValues; j++)
+      {
+         ossimString valueStr = ossimString::toString(uint16Data[j]);
+         values = values + ossimString(valueStr + " ");
+      }
+   }
+   else if (dataType == DFNT_INT32 || dataType == DFNT_UINT32)
+   {
+      ossim_int32* int32Data = (ossim_int32*)attrValue;
+      for (ossim_int32 j = 0; j < numValues; j++)
+      {
+         ossimString valueStr = ossimString::toString(int32Data[j]);
+         values = values + ossimString(valueStr + " ");
+      }
+   }
+   else if (dataType == DFNT_FLOAT64 || dataType == DFNT_DOUBLE)
+   {
+      double* doubleData = (double*)attrValue;
+      for (ossim_int32 j = 0; j < numValues; j++)
+      {
+         ossimString valueStr = ossimString::toString(doubleData[j]);
+         values = values + ossimString(valueStr + " ");
+      }
+   }
+   else
+   {
+      float32* floatData = (float32*)attrValue;
+      for (ossim_int32 j = 0; j < numValues; j++)
+      {
+         ossimString valueStr = ossimString::toString(floatData[j]);
+         values = values + ossimString(valueStr + " ");
+      }
+   }
+   return values;
+}
+
+char* ossimHdf4SubDataset::getTileBuf(const  ossimIrect& rect, ossim_uint32 band)
+{
+   // bool status = false;
+   int32 start[H4_MAX_NC_DIMS], edges[H4_MAX_NC_DIMS];
+   if (m_rank == 3)
+   {
+      start[0] = band;
+      start[1] = rect.ul().y;
+      start[2] = rect.ul().x;
+      edges[0] = 1;
+      edges[1] = rect.height(); 
+      edges[2] = rect.width(); 
+   }
+   else if (m_rank == 2)
+   {
+      start[0] = rect.ul().y;
+      start[1] = rect.ul().x;
+      edges[0] = rect.height(); 
+      edges[1] = rect.width(); 
+   }
+   
+   int32 numValues = rect.width() * rect.height();
+   ossim_int32 size = getDataTypeSize(m_dataType);
+   
+   char* data = new char[size * numValues];
+   // intn statusSd = SDreaddata(m_sds_id, start, NULL, edges, (VOIDP)data);
+   SDreaddata(m_sds_id, start, NULL, edges, (VOIDP)data);   
+  
+   return data;
+}
+
+ossim_uint32 ossimHdf4SubDataset::getNumberOfInputBands() const
+{
+   return m_numberOfBands;
+}
+
+ossimScalarType ossimHdf4SubDataset::getOutputScalarType() const
+{
+   return m_scalarType;
+}
+
+void ossimHdf4SubDataset::setNumberOfLines(int32 lines)
+{
+   m_numberOfLines = lines;
+}
+
+void ossimHdf4SubDataset::setNumberOfSamples(int32 samples)
+{
+   m_numberOfSamples = samples;
+}
+
+void ossimHdf4SubDataset::setNumberOfBands(int32 bands)
+{
+   m_numberOfBands = bands;
+}
+
+void ossimHdf4SubDataset::setSdsName(ossimString name)
+{
+   m_sd_name = name;
+}
+
+void ossimHdf4SubDataset::setHdfSdsIndex(int32 sds_index)
+{
+   m_sds_index = sds_index;
+}
+
+void ossimHdf4SubDataset::setAttributeCount(int32 attributes)
+{
+   m_attributes = attributes;
+}
+
+void ossimHdf4SubDataset::setSdsRank(int32 rank)
+{
+   m_rank = rank;
+}
+
+void ossimHdf4SubDataset::setHdfFilename(ossimString fileName)
+{
+   m_fileName = fileName;
+   open();
+}
+
+void ossimHdf4SubDataset::setOutputScalarType(int32 dataType)
+{
+   m_dataType = dataType;
+   switch (dataType)
+   {
+   case DFNT_UINT8:
+      {
+         m_scalarType = OSSIM_UINT8;
+         break;
+      }
+   case DFNT_INT8:
+      {
+         m_scalarType = OSSIM_SINT8;
+         break;
+      }
+   case DFNT_UINT16:
+      {
+         m_scalarType = OSSIM_UINT16;
+         break;
+      }
+   case DFNT_INT16:
+      {
+         m_scalarType = OSSIM_SINT16;
+         break;
+      }
+   case DFNT_UINT32:
+      {
+         m_scalarType = OSSIM_UINT32;
+         break;
+      }
+   case DFNT_INT32:
+      {
+         m_scalarType = OSSIM_SINT32;
+         break;
+      }
+   case DFNT_FLOAT32:
+      {
+         m_scalarType = OSSIM_FLOAT32;
+         break;
+      }
+   case DFNT_FLOAT64:
+      {
+         m_scalarType = OSSIM_FLOAT64;
+         break;
+      }
+   default:
+      {
+         m_scalarType = OSSIM_SCALAR_UNKNOWN;
+         break;
+      }
+   }
+}
+
+ossim_int32 ossimHdf4SubDataset::getDataTypeSize(int32 type)
+{
+   ossim_int32 size = 0;
+   if ( type == DFNT_CHAR8 || type == DFNT_UCHAR8 )
+   {
+      size = 1;
+   }
+   else if (type == DFNT_INT8 || type == DFNT_UINT8)
+   {
+      size = 1;
+   }
+   else if (type == DFNT_INT16 || type == DFNT_UINT16)
+   {
+      size = 2;
+   }
+   else if (type == DFNT_INT32 || type == DFNT_UINT32 
+      || type == DFNT_FLOAT32)
+   {
+      size = 4;
+   }
+   else if (type == DFNT_DOUBLE || type == DFNT_FLOAT64)
+   {
+      size = 8;
+   }
+   else
+   {
+      size = 4;
+   }
+   return size;
+}
+
diff --git a/ossim_plugins/hdf4/ossimHdf4SubDataset.h b/ossim_plugins/hdf4/ossimHdf4SubDataset.h
new file mode 100644
index 0000000..493ac19
--- /dev/null
+++ b/ossim_plugins/hdf4/ossimHdf4SubDataset.h
@@ -0,0 +1,185 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Description:  Class declaration HDF reader.
+//
+// Specification: ISO/IEC 15444
+//
+//----------------------------------------------------------------------------
+// $Id: ossimHdf4SubDataset.h 2645 2011-05-26 15:21:34Z oscar.kramer $
+
+#ifndef ossimHdf4SubDataset_HEADER
+#define ossimHdf4SubDataset_HEADER 1
+
+//ossim includes
+#include "../ossimPluginConstants.h"
+#include <ossim/base/ossimIpt.h>
+#include <ossim/base/ossimIrect.h>
+#include <ossim/base/ossimRefPtr.h>
+#include <ossim/imaging/ossimImageHandler.h>
+#include <ossim/support_data/ossimJ2kSizRecord.h>
+#include <ossim/imaging/ossimAppFixedTileCache.h>
+
+//HDF4 Includes
+// #include <hdf/hdf.h>
+// #include <hdf/mfhdf.h>
+#include <hdf.h>
+#include <mfhdf.h>
+
+
+
+// Forward class declarations.
+class ossimImageData;
+
+class OSSIM_PLUGINS_DLL ossimHdf4SubDataset 
+{
+public:
+
+   /** default construtor */
+   ossimHdf4SubDataset();
+   
+   /** virtural destructor */
+   virtual ~ossimHdf4SubDataset();
+
+   /**
+    *  @brief Method to grab a tile(rectangle) from image.
+    *
+    *  @param rect The zero based rectangle to grab.
+    *
+    *  @param resLevel The reduced resolution level to grab from.
+    *
+    *  @return The ref pointer with the image data pointer.
+    */
+   char* getTileBuf(const  ossimIrect& rect, ossim_uint32 band);   
+
+   /**
+    *  Returns the number of bands in the image.
+    *  Satisfies pure virtual from ImageHandler class.
+    */
+   virtual ossim_uint32 getNumberOfInputBands() const;
+
+   /**
+    * Returns the output pixel type of the tile source.
+    */
+   virtual ossimScalarType getOutputScalarType() const;
+
+
+   /**
+    * @brief Gets number of lines for res level.
+    *
+    *  @param resLevel Reduced resolution level to return lines of.
+    *  Default = 0
+    *
+    *  @return The number of lines for specified reduced resolution level.
+    */
+   virtual ossim_uint32 getNumberOfLines(ossim_uint32 resLevel = 0) const;
+
+   /**
+    *  @brief Gets the number of samples for res level.
+    *
+    *  @param resLevel Reduced resolution level to return samples of.
+    *  Default = 0
+    *
+    *  @return The number of samples for specified reduced resolution level.
+    */
+   virtual ossim_uint32 getNumberOfSamples(ossim_uint32 resLevel = 0) const;
+
+   std::vector<ossimString> getMetadata() const { return m_meta; }
+
+   /**
+    * @brief sets number of lines.
+    *
+    */
+   void setNumberOfLines(int32 lines);
+
+   /**
+    *  @brief sets the number of samples.
+    *
+    */
+   void setNumberOfSamples(int32 samples);
+
+   /**
+    *  @brief sets the number of samples.
+    *
+    */
+   void setNumberOfBands(int32 bands);
+
+   /**
+    * @brief sets the output pixel type of the tile source.
+    *
+    */
+   void setOutputScalarType(int32 dataType);
+
+   /**
+    *  @brief Method to set number of attributes for dataset.
+    *
+    */
+   void setAttributeCount(int32 attributes); 
+
+   /**
+    *  @brief Method to set sds name for dataset.
+    *
+    */
+   void setSdsName(ossimString name); 
+
+   /**
+    *  @brief Method to set sds rank for dataset.
+    *
+    */
+   void setSdsRank(int32 rank); 
+
+   /**
+    * @brief Open method.
+    * @return true on success, false on error.
+    */
+   virtual bool open();
+
+   /**
+    *  @brief Method to set hdf file name for open file.
+    *
+    */
+   void setHdfFilename(ossimString fileName);
+
+   /**
+    *  @brief Method to set SDS id of hdf file for open file.
+    *
+    */
+   void setHdfDataType(ossimString hdfDatyType) { m_hdfDataType = hdfDatyType; }
+
+   /**
+    *  @brief Method to set Scientific Data Set Id for get data.
+    *
+    */
+   void setHdfSdsIndex(int32 sds_index);   
+
+private:
+
+  ossim_int32 getDataTypeSize(int32 type);
+
+  ossimString getAttribuitValues(int32 dataType, int32 numValues, void* attrValue);
+
+  void initMeta();
+
+  ossimString                       m_fileName;
+  ossimString                       m_sd_name;//SDS name
+  int32                             m_sds_index; //SDS index 
+  int32                             m_sds_id; //SDS selected id
+  int32                             m_sd_id; //SDS id of HDF file
+  int32                             m_rank;
+  ossim_uint32                      m_numberOfBands;
+  ossim_uint32                      m_numberOfSamples;
+  ossim_uint32                      m_numberOfLines;
+  int32                             m_attributes;
+  bool                              m_isGeoField;
+  ossimScalarType                   m_scalarType;
+  int32                             m_dataType;
+  ossimString                       m_hdfDataType;
+  std::vector<ossimString>          m_meta;
+TYPE_DATA
+};
+
+#endif /* #ifndef ossimHdf4SubDataset_HEADER */
+
diff --git a/ossim_plugins/hdf4/ossimHdfGridModel.cpp b/ossim_plugins/hdf4/ossimHdfGridModel.cpp
new file mode 100644
index 0000000..c04ef53
--- /dev/null
+++ b/ossim_plugins/hdf4/ossimHdfGridModel.cpp
@@ -0,0 +1,348 @@
+//*****************************************************************************
+// FILE: ossimHdfGridModel.cc
+//
+// License:  See LICENSE.txt file in the top level directory.
+//
+// AUTHOR: Mingjie Su
+//
+// DESCRIPTION:
+//   Contains implementation of class ossimHdfGridModel. This is an
+//   implementation of an interpolation sensor model. 
+//
+//   IMPORTANT: The lat/lon grid is for ground points on the ellipsoid.
+//   The dLat/dHgt and dLon/dHgt partials therefore are used against
+//   elevations relative to the ellipsoid.
+//
+//*****************************************************************************
+//  $Id: ossimHdfGridModel.cpp 2645 2011-05-26 15:21:34Z oscar.kramer $
+
+#include "ossimHdfGridModel.h"
+
+#include <ossim/base/ossimCommon.h>
+#include <ossim/base/ossimEndian.h>
+#include <ossim/base/ossimException.h>
+#include <ossim/base/ossimTrace.h>
+
+#include <hdf.h>
+// Not in latest 4.2.9 code: #include <hdf4_netcdf.h>
+#include <mfhdf.h>
+
+#include <sstream>
+
+static ossimTrace traceDebug("ossimHdfGridModel:debug");
+
+RTTI_DEF1(ossimHdfGridModel, "ossimHdfGridModel", ossimCoarseGridModel);
+
+ossimHdfGridModel::ossimHdfGridModel()
+   :
+   ossimCoarseGridModel()
+{
+   theLatGrid.setDomainType(ossimDblGrid::SAWTOOTH_90);
+   theLonGrid.setDomainType(ossimDblGrid::WRAP_180);
+}
+
+//*****************************************************************************
+//  CONSTRUCTOR: ossimHdfGridModel(filename)
+//  
+//  Constructs model from geometry file
+//  
+//*****************************************************************************
+ossimHdfGridModel::ossimHdfGridModel(const ossimFilename& file,
+                                     const ossimDrect& imageRect,
+                                     ossimString latGridIndexOrName,
+                                     ossimString lonGridIndexOrName,
+                                     const ossimIpt& gridSpacing)
+   :  ossimCoarseGridModel()
+{
+   theLatGrid.setDomainType(ossimDblGrid::SAWTOOTH_90);
+   theLonGrid.setDomainType(ossimDblGrid::WRAP_180);
+
+   if (latGridIndexOrName.contains("/Latitude") == false && 
+       lonGridIndexOrName.contains("/Longitude") == false)//hdf4
+   {
+      ossim_int32 latGridIndex = ossimString::toInt(latGridIndexOrName);
+      ossim_int32 lonGridIndex = ossimString::toInt(lonGridIndexOrName);
+      ossim_int32 sd_id = SDstart(file.c_str(), DFACC_READ);
+      if (sd_id > 0)
+      {
+         ossim_int32 sds_id = SDselect(sd_id, latGridIndex);
+         if (sds_id > 0)
+         {
+            setGridNodes(theLatGrid, sds_id, gridSpacing);
+         }
+         SDendaccess (sds_id); 
+
+         sds_id = SDselect(sd_id, lonGridIndex);
+         if (sds_id > 0)
+         {
+            setGridNodes(theLonGrid, sds_id, gridSpacing);
+         }
+         SDendaccess (sds_id); 
+      }
+      SDend(sd_id);
+   }
+
+   // Filter this HDF data as it is often very noisy:
+   double filter_kernel[81];
+   double weight = 1.0/81.0;
+   for (int i=0; i<81; i++)
+      filter_kernel[i] = weight;
+   theLatGrid.filter(9,9, filter_kernel);
+   theLonGrid.filter(9,9, filter_kernel);
+
+   theLatGrid.enableExtrapolation();
+   theLonGrid.enableExtrapolation();
+   theHeightEnabledFlag = false;
+   initializeModelParams(imageRect);
+   
+   //debugDump(); //###
+}
+
+ossimHdfGridModel::~ossimHdfGridModel()
+{
+}
+
+void ossimHdfGridModel::setGridNodes(ossimDblGrid& grid, ossim_int32 sds_id, const ossimIpt& spacing)
+{
+   int x=0, y=0;
+   ossim_uint32 index = 0;
+
+   int32 dim_sizes[MAX_VAR_DIMS];
+   int32 rank, data_type, n_attrs;
+   char  name[MAX_NC_NAME];
+   
+   ossim_int32 status = SDgetinfo(sds_id, name, &rank, dim_sizes, &data_type, &n_attrs);
+   if (status == -1)
+      return;
+   
+   int32 origin[2] = {0, 0}; 
+   ossim_int32 num_rows = dim_sizes[0]; 
+   ossim_int32 num_cols = dim_sizes[1]; 
+   
+   ossimDpt grid_origin(0,0); // The grid as used in base class, has UV-space always at 0,0 origin
+   ossimIpt grid_size (num_cols, num_rows);
+   ossimDpt dspacing (spacing);
+   grid.initialize(grid_size, grid_origin, dspacing);
+   
+   float32* values = new float32 [num_rows * num_cols]; 
+   intn statusN = SDreaddata(sds_id, origin, NULL, dim_sizes, (VOIDP)values);
+   if (statusN > -1)
+   {
+      for (y = 0; y < num_rows; y++)
+      {
+         for (x = 0; x < num_cols; x++)
+         {
+            grid.setNode(x, y, values[index++]);
+         }
+      }
+   }
+   delete values;
+}
+
+bool ossimHdfGridModel::saveState(ossimKeywordlist& kwl, const char* prefix) const
+{
+   bool status = ossimCoarseGridModel::saveState( kwl, prefix );
+   if ( status )
+   {
+      std::string myPrefix = ( prefix ? prefix: "" );
+      std::string value;
+      if ( getWktFootprint( value ) )
+      {   
+         std::string key = "wkt_footprint";
+         kwl.addPair( myPrefix, key, value, true );
+      }
+   }
+   return status;
+}     
+
+bool ossimHdfGridModel::loadState(const ossimKeywordlist& kwl, const char* prefix)
+{
+   bool result = false;
+   
+   std::string myPrefix = ( prefix ? prefix: "" );
+
+   // Look for type key:
+   std::string typeKey = "type";
+   std::string value = kwl.findKey( myPrefix, typeKey );
+   if ( value == "ossimHdfGridModel" )
+   {
+      // Make a copy of kwl so we can change type.
+      ossimKeywordlist myKwl = kwl;
+      value = "ossimCoarseGridModel";
+      myKwl.addPair( myPrefix, typeKey, value, true );
+
+      // Load the state of base class.
+      result = ossimCoarseGridModel::loadState( myKwl, prefix );
+   }
+   
+   return result;                    
+}
+
+bool ossimHdfGridModel::getWktFootprint( std::string& s ) const
+{
+   bool status = true;
+
+   // Loop until complete or a "nan" is hit.
+   while ( 1 )
+   {
+      ossim_float32 lat = 0.0;
+      ossim_float32 lon = 0.0;
+
+      std::ostringstream os;
+
+      os <<  setprecision(10) << "POLYGON((";
+      const ossim_int32 STEP = 128;
+      
+      ossimIrect rect( 0, 0, theImageSize.x-1, theImageSize.y-1 );  
+
+      ossim_int32 x = 0;
+      ossim_int32 y = 0;
+      
+      // Walk the top line:
+      while ( x < theImageSize.x )
+      {
+         lat = theLatGrid( x, y );
+         lon = theLonGrid( x, y );
+
+         if ( ossim::isnan(lat) || ossim::isnan(lon) )
+         {
+            status = false;
+            break;
+         }
+         
+         os << lon << " " << lat << ",";
+         
+         if ( x != rect.ur().x )
+         {
+            x = ossim::min<ossim_int32>( x+STEP, rect.ur().x );
+         }
+         else
+         {
+            break; // End of top line walk.
+         }
+      }
+
+      if ( !status ) break; // Found "nan" so get out.
+      
+      // Walk the right edge:
+      y = ossim::min<ossim_int32>( y+STEP, rect.lr().y );
+      while ( y < theImageSize.y )
+      {
+         lat = theLatGrid( x, y );
+         lon = theLonGrid( x, y );
+
+         if ( ossim::isnan(lat) || ossim::isnan(lon) )
+         {
+            status = false;
+            break;
+         }
+
+         os << lon << " " << lat << ",";
+         
+         if ( y != rect.lr().y )
+         {
+            y = ossim::min<ossim_int32>( y+STEP, rect.lr().y );
+         }
+         else
+         {
+            break;
+         }
+      }
+
+      if ( !status ) break; // Found "nan" so get out.
+      
+      // Walk the bottom line from right to left:
+      x = ossim::max<ossim_int32>( rect.lr().x-STEP, 0 );
+      while ( x >= 0 )
+      {
+         lat = theLatGrid( x, y );
+         lon = theLonGrid( x, y );
+         
+         if ( ossim::isnan(lat) || ossim::isnan(lon) )
+         {
+            status = false;
+            break;
+         }
+
+         os << lon << " " << lat << ",";
+         
+         if ( x != 0 )
+         {
+            x = ossim::max<ossim_int32>( x-STEP, 0 );
+         }
+         else
+         {
+            break;
+         }
+      }
+
+      if ( !status ) break; // Found "nan" so get out.
+      
+      // Walk the left edge from bottom to top:
+      y = ossim::max<ossim_int32>( y-STEP, 0 );
+      while ( y >= 0 )
+      {
+         lat = theLatGrid( x, y );
+         lon = theLonGrid( x, y );
+
+         if ( ossim::isnan(lat) || ossim::isnan(lon) )
+         {
+            status = false;
+            break;
+         }
+
+         if ( ( x == 0 ) && ( y == 0 ) )
+         {
+            os << lon << " " << lat; // Last point:
+         }
+         else
+         {
+            os << lon << " " << lat << ",";
+         }
+         
+         if ( y != 0 )
+         {
+            y = ossim::max<ossim_int32>( y-STEP, 0 );
+         }
+         else
+         {
+            break;
+         }
+      }
+
+      if ( !status ) break; // Found "nan" so get out.
+      
+      os << "))";
+      s = os.str();
+
+      // Trailing break from while ( FOREVER ) loop:
+      break;
+      
+   } // Matches: while ( 1 )
+   
+   return status;
+}
+
+void ossimHdfGridModel::debugDump()
+{
+   ossimIpt step (theImageSize/200);
+   int margin = 0;
+   double lat, lon;
+   ossimDpt pt (0,0);
+   ofstream fslat ("lat_grid.dat");
+   ofstream fslon ("lon_grid.dat");
+   fslat<< setprecision(10) <<endl;
+   fslon<< setprecision(10) <<endl;
+   for (pt.v = -margin*step.v; pt.v < theImageSize.v+margin*step.v; pt.v += step.y)
+   {
+      for (pt.u = -margin*step.u; pt.u < theImageSize.u+margin*step.u ; pt.u += step.u)
+      {
+         lat = theLatGrid(pt.u, pt.v);
+         lon = theLonGrid(pt.u, pt.v);
+         fslat << pt.u << " " << pt.v << " " << lat << endl;
+         fslon << pt.u << " " << pt.v << " " << lon << endl;
+      }
+   }
+   fslat.close();
+   fslon.close();
+}
diff --git a/ossim_plugins/hdf4/ossimHdfGridModel.h b/ossim_plugins/hdf4/ossimHdfGridModel.h
new file mode 100644
index 0000000..9508e8b
--- /dev/null
+++ b/ossim_plugins/hdf4/ossimHdfGridModel.h
@@ -0,0 +1,80 @@
+//*****************************************************************************
+// FILE: ossimHdfGridModel.h
+//
+// Copyright (C) 2001 ImageLinks, Inc.
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// AUTHOR: Mingjie Su
+//
+// DESCRIPTION:
+//   Contains declaration of class ossimHdfGridModel. This is an
+//   implementation of an interpolation sensor model.
+//
+//*****************************************************************************
+//  $Id: ossimHdfGridModel.h 2645 2011-05-26 15:21:34Z oscar.kramer $
+
+#ifndef ossimHdfGridModel_HEADER
+#define ossimHdfGridModel_HEADER 1
+
+#include <ossim/projection/ossimCoarseGridModel.h>
+#include "../ossimPluginConstants.h"
+
+#include <string>
+
+/******************************************************************************
+ *
+ * CLASS:  ossimHdfGridModel
+ *
+ *****************************************************************************/
+
+
+
+class OSSIM_PLUGINS_DLL ossimHdfGridModel : public ossimCoarseGridModel
+{
+public:
+
+   /** @brief default constructor. */
+   ossimHdfGridModel();
+   
+    //! CONSTRUCTOR (filename) Accepts name of hdf file and the index of SDS data
+   ossimHdfGridModel(const ossimFilename& file, 
+                    const ossimDrect& imageRect,
+                    ossimString latGridIndexOrName, 
+                    ossimString lonGridIndexOrName, 
+                    const ossimIpt& gridSpacing);
+
+   /** @brief virtual destructor */
+   virtual ~ossimHdfGridModel();
+
+   /**
+    * @brief saveState Saves state of object to a keyword list.
+    * @param kwl Initialized by this.
+    * @param prefix E.g. "image0.geometry.projection."
+    * @return true on success, false on error.
+    */
+   virtual bool saveState(ossimKeywordlist& kwl, const char* prefix=0) const;
+
+   /**
+    * @brief loadState Loads state of object from a keyword list.
+    * @param kwl Keyword list to initialize from.
+    * @param prefix E.g. "image0.geometry.projection."
+    * @return true on success, false on error.
+    */
+   virtual bool loadState(const ossimKeywordlist& kwl, const char* prefix=0);
+   
+private:
+   
+   void setGridNodes(ossimDblGrid& grid, ossim_int32 sds_id, const ossimIpt& spacing);
+
+   bool getWktFootprint( std::string& s ) const;
+   
+   void debugDump();
+
+   TYPE_DATA
+};
+
+#endif
+
diff --git a/ossim_plugins/hdf4/ossimHdfInfo.cpp b/ossim_plugins/hdf4/ossimHdfInfo.cpp
new file mode 100644
index 0000000..dd0f207
--- /dev/null
+++ b/ossim_plugins/hdf4/ossimHdfInfo.cpp
@@ -0,0 +1,144 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author:  Mingjie Su
+//
+// Description: Hdf Info object.
+// 
+//----------------------------------------------------------------------------
+// $Id: ossimHdfInfo.cpp 2645 2011-05-26 15:21:34Z oscar.kramer $
+
+//ossim includes
+#include "ossimHdfInfo.h"
+#include <ossim/base/ossimNotify.h>
+#include <ossim/base/ossimTrace.h>
+#include <ossim/base/ossimKeywordlist.h>
+
+// Static trace for debugging
+static ossimTrace traceDebug("ossimHdfInfo:debug");
+
+ossimHdfInfo::ossimHdfInfo()
+: ossimInfoBase(),
+theFile(),
+m_hdf4Reader(0),
+m_driverName()
+{
+}
+
+ossimHdfInfo::~ossimHdfInfo()
+{
+   if (m_hdf4Reader.valid())
+   {
+      m_hdf4Reader = 0;
+   }
+   m_metaInfos.clear();
+   std::map<ossim_uint32, std::vector<ossimString> >::iterator it = m_subMetaInfos.begin();
+   while (it != m_subMetaInfos.end())
+   {
+      it->second.clear();
+      it++;
+   }
+   m_subMetaInfos.clear();
+}
+
+bool ossimHdfInfo::open(const ossimFilename& file)
+{
+   static const char MODULE[] = "ossimHdfInfo::open";
+   if (traceDebug())
+   {    
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " entered...\n"
+         << "file: " << file << "\n";
+   }
+
+   bool result = false;
+
+   ossimString ext = file.ext();
+   ext.downcase();
+
+   if ( ext == "hdf" || ext == "h4" || ext == "hdf4" || 
+        ext == "he4" || ext == "l1r" )
+   {
+      m_metaInfos.clear();
+      m_bandVector.clear();
+
+      m_hdf4Reader = new ossimHdf4Reader;
+      m_hdf4Reader->setFilename(file);
+
+      if ( m_hdf4Reader->open() )
+      {
+         m_metaInfos = m_hdf4Reader->getGlobalMeta();
+
+         ossim_uint32 entryNum = m_hdf4Reader->getNumberOfEntries();
+         for (ossim_uint32 i = 0; i < entryNum; i++)
+         {
+            m_hdf4Reader->setCurrentEntry(i);
+            m_bandVector.push_back(m_hdf4Reader->getNumberOfOutputBands());
+            m_subMetaInfos[i] = m_hdf4Reader->getSubDatasetMeta();
+         }
+         m_driverName = "hdf4";
+         theFile = file;
+         result = true;
+      }
+      else
+      {
+         m_hdf4Reader = 0;
+      }
+   }
+
+   if (traceDebug())
+   {    
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " exit status = " << (result?"true\n":"false\n");
+   }
+
+   return result;
+}
+
+std::ostream& ossimHdfInfo::print(std::ostream& out) const
+{
+   static const char MODULE[] = "ossimHdfInfo::print";
+   if (traceDebug())
+   {    
+      ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " entered...\n";
+   }
+
+   //display global meta first
+   ossimString prefix = ossimString(m_driverName + ".").downcase();
+   for (ossim_uint32 i = 0; i < m_metaInfos.size(); i++)
+   {
+      out << prefix << m_metaInfos[i] << "\n";
+   }
+
+   ossim_uint32 index = 0;
+   std::map<ossim_uint32, std::vector<ossimString> >::const_iterator it = m_subMetaInfos.begin();
+   while (it != m_subMetaInfos.end())
+   {
+      ossimString imagePrefix = prefix + "image" + ossimString::toString(index) + ".";
+      std::vector<ossimString> subMeta = it->second;
+      ossim_uint32 numOfBands = m_bandVector[index];
+      for (ossim_uint32 i = 0; i < numOfBands; i++)
+      {
+         ossimString bandPrefix = "band" + ossimString::toString(i) + ".";
+         ossimString prefixStr = imagePrefix + bandPrefix;
+         for (ossim_uint32 j = 0; j < subMeta.size(); j++)
+         {
+            out << prefixStr << subMeta[j] << "\n";
+         }
+      }
+      index++;
+      it++;
+   }
+
+   if (traceDebug())
+   {    
+      ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " exited...\n";
+   }
+
+   return out;
+}
+
+
diff --git a/ossim_plugins/hdf4/ossimHdfInfo.h b/ossim_plugins/hdf4/ossimHdfInfo.h
new file mode 100644
index 0000000..f9cac2e
--- /dev/null
+++ b/ossim_plugins/hdf4/ossimHdfInfo.h
@@ -0,0 +1,66 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author:  Mingjie Su
+//
+// Description: Info object for HDF data.
+// 
+//----------------------------------------------------------------------------
+// $Id: ossimHdfInfo.h 2645 2011-05-26 15:21:34Z oscar.kramer $
+#ifndef ossimHdfInfo_HEADER
+#define ossimHdfInfo_HEADER
+
+#include <ossim/base/ossimConstants.h>
+#include <ossim/base/ossimRefPtr.h>
+#include <ossim/support_data/ossimInfoBase.h>
+#include <ossim/base/ossimFilename.h>
+#include "ossimHdf4Reader.h"
+
+/**
+ * @brief HDF info class.
+ *
+ * Encapsulates the HDF functionality.
+ */
+class ossimHdfInfo : public ossimInfoBase
+{
+public:
+   
+   /** default constructor */
+   ossimHdfInfo();
+   
+   /** virtual destructor */
+   virtual ~ossimHdfInfo();
+   
+   /**
+    * @brief open method.
+    *
+    * @param file File name to open.
+    * @return true on success false on error.
+    */
+   virtual bool open(const ossimFilename& file);
+   
+   /**
+    * Print method.
+    *
+    * @param out Stream to print to.
+    * 
+    * @return std::ostream&
+    */
+   virtual std::ostream& print(std::ostream& out) const;
+   
+private: 
+   
+   ossimFilename                                     theFile;
+   ossimRefPtr<ossimHdf4Reader>                      m_hdf4Reader;
+   ossimString                                       m_driverName;
+   std::vector<ossimString>                          m_metaInfos;
+   std::map<ossim_uint32, std::vector<ossimString> > m_subMetaInfos;
+   std::vector<ossim_uint32>                         m_bandVector;
+};
+
+#endif /* End of "#ifndef ossimHdfInfo_HEADER" */
+
+
diff --git a/ossim_plugins/hdf4/ossimHdfInfoFactory.cpp b/ossim_plugins/hdf4/ossimHdfInfoFactory.cpp
new file mode 100644
index 0000000..c581e23
--- /dev/null
+++ b/ossim_plugins/hdf4/ossimHdfInfoFactory.cpp
@@ -0,0 +1,54 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author:  Mingjie Su
+//
+// Description: Factory for info objects.
+// 
+//----------------------------------------------------------------------------
+// $Id: ossimHdfInfoFactory.cpp 2645 2011-05-26 15:21:34Z oscar.kramer $
+
+#include "ossimHdfInfoFactory.h"
+#include <ossim/support_data/ossimInfoFactory.h>
+#include <ossim/support_data/ossimInfoBase.h>
+#include <ossim/base/ossimFilename.h>
+#include <ossim/base/ossimRefPtr.h>
+#include "ossimHdfInfo.h"
+
+ossimHdfInfoFactory::~ossimHdfInfoFactory()
+{}
+
+ossimHdfInfoFactory* ossimHdfInfoFactory::instance()
+{
+   static ossimHdfInfoFactory sharedInstance;
+
+   return &sharedInstance;
+}
+
+ossimInfoBase* ossimHdfInfoFactory::create(const ossimFilename& file) const
+{
+   ossimRefPtr<ossimInfoBase> result = 0;
+   result = new ossimHdfInfo();
+   if ( result->open(file) )
+   {
+      return result.release();
+   }
+   return 0;
+}
+
+ossimHdfInfoFactory::ossimHdfInfoFactory()
+{}
+
+ossimHdfInfoFactory::ossimHdfInfoFactory(const ossimHdfInfoFactory& /* obj */ )
+{}
+
+const ossimHdfInfoFactory& ossimHdfInfoFactory::operator=(
+   const ossimHdfInfoFactory& /* rhs */)
+{
+   return *this;
+}
+
+
diff --git a/ossim_plugins/hdf4/ossimHdfInfoFactory.h b/ossim_plugins/hdf4/ossimHdfInfoFactory.h
new file mode 100644
index 0000000..368e256
--- /dev/null
+++ b/ossim_plugins/hdf4/ossimHdfInfoFactory.h
@@ -0,0 +1,58 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author:  Mingjie Su
+//
+// Description: Factory for hdf info objects.
+// 
+//----------------------------------------------------------------------------
+// $Id: ossimHdfInfoFactory.h 2645 2011-05-26 15:21:34Z oscar.kramer $
+#ifndef ossimHdfInfoFactory_HEADER
+#define ossimHdfInfoFactory_HEADER
+
+#include <ossim/base/ossimConstants.h>
+#include <ossim/support_data/ossimInfoFactoryInterface.h>
+
+class ossimFilename;
+class ossimInfoBase;
+
+/**
+ * @brief Info factory.
+ */
+class ossimHdfInfoFactory : public ossimInfoFactoryInterface
+{
+public:
+
+   /** virtual destructor */
+   virtual ~ossimHdfInfoFactory();
+
+   static ossimHdfInfoFactory* instance();
+
+   /**
+    * @brief create method.
+    *
+    * @param file Some file you want info for.
+    *
+    * @return ossimInfoBase* on success 0 on failure.  Caller is responsible
+    * for memory.
+    */
+   virtual ossimInfoBase* create(const ossimFilename& file) const;
+   
+private:
+   
+   /** hidden from use default constructor */
+   ossimHdfInfoFactory();
+
+   /** hidden from use copy constructor */
+   ossimHdfInfoFactory(const ossimHdfInfoFactory& obj);
+
+   /** hidden from use operator = */
+   const ossimHdfInfoFactory& operator=(const ossimHdfInfoFactory& rhs);
+};
+
+#endif /* End of "#ifndef ossimInfoFactory_HEADER" */
+
+
diff --git a/ossim_plugins/hdf4/ossimHdfPluginInit.cpp b/ossim_plugins/hdf4/ossimHdfPluginInit.cpp
new file mode 100644
index 0000000..6fd6abc
--- /dev/null
+++ b/ossim_plugins/hdf4/ossimHdfPluginInit.cpp
@@ -0,0 +1,92 @@
+//----------------------------------------------------------------------------
+//
+// License:  See top level LICENSE.txt file
+//
+// Author:  Mingjie Su
+//
+// Description: OSSIM HDF plugin initialization
+// code.
+//
+//----------------------------------------------------------------------------
+// $Id: ossimHdfPluginInit.cpp 2645 2011-05-26 15:21:34Z oscar.kramer $
+
+#include <ossim/plugin/ossimSharedObjectBridge.h>
+#include <ossim/imaging/ossimImageHandlerRegistry.h>
+#include <ossim/imaging/ossimImageWriterFactoryRegistry.h>
+#include <ossim/imaging/ossimOverviewBuilderFactoryRegistry.h>
+#include <ossim/projection/ossimProjectionFactoryRegistry.h>
+#include <ossim/support_data/ossimInfoFactoryRegistry.h>
+
+#include "../ossimPluginConstants.h"
+#include "ossimHdfReaderFactory.h"
+#include "ossimHdfInfoFactory.h"
+#include "ossimHdfProjectionFactory.h"
+
+static void setDescription(ossimString& description)
+{
+   description = "HDF4 reader plugin\n\n";
+}
+
+extern "C"
+{
+   ossimSharedObjectInfo  myInfo;
+   ossimString theDescription;
+   std::vector<ossimString> theObjList;
+
+   const char* getDescription()
+   {
+      return theDescription.c_str();
+   }
+
+   int getNumberOfClassNames()
+   {
+      return (int)theObjList.size();
+   }
+
+   const char* getClassName(int idx)
+   {
+      if(idx < (int)theObjList.size())
+      {
+         return theObjList[0].c_str();
+      }
+      return (const char*)0;
+   }
+
+   /* Note symbols need to be exported on windoze... */ 
+   OSSIM_PLUGINS_DLL void ossimSharedLibraryInitialize(
+      ossimSharedObjectInfo** info)
+   {    
+      myInfo.getDescription = getDescription;
+      myInfo.getNumberOfClassNames = getNumberOfClassNames;
+      myInfo.getClassName = getClassName;
+
+      *info = &myInfo;
+
+      /* Register the readers... */
+      ossimImageHandlerRegistry::instance()->
+         registerFactory(ossimHdfReaderFactory::instance());
+
+      /* Register hdf info factoy... */
+      ossimInfoFactoryRegistry::instance()->
+         registerFactory(ossimHdfInfoFactory::instance());
+
+      /* Register hdf projection factoy... */
+      ossimProjectionFactoryRegistry::instance()->
+         registerFactoryToFront(ossimHdfProjectionFactory::instance());
+
+      setDescription(theDescription);
+   }
+
+   /* Note symbols need to be exported on windoze... */ 
+   OSSIM_PLUGINS_DLL void ossimSharedLibraryFinalize()
+   {
+      ossimImageHandlerRegistry::instance()->
+         unregisterFactory(ossimHdfReaderFactory::instance());
+
+      ossimInfoFactoryRegistry::instance()->
+         unregisterFactory(ossimHdfInfoFactory::instance());
+
+      ossimProjectionFactoryRegistry::instance()->
+         unregisterFactory(ossimHdfProjectionFactory::instance());
+   }
+}
diff --git a/ossim_plugins/hdf4/ossimHdfProjectionFactory.cpp b/ossim_plugins/hdf4/ossimHdfProjectionFactory.cpp
new file mode 100644
index 0000000..30a00e5
--- /dev/null
+++ b/ossim_plugins/hdf4/ossimHdfProjectionFactory.cpp
@@ -0,0 +1,160 @@
+//----------------------------------------------------------------------------
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//----------------------------------------------------------------------------
+// $Id$
+
+#include "ossimHdfProjectionFactory.h"
+#include <ossim/base/ossimKeywordNames.h>
+#include <ossim/base/ossimRefPtr.h>
+#include <ossim/projection/ossimProjection.h>
+#include "ossimHdfGridModel.h"
+
+//---
+// Define Trace flags for use within this file:
+//---
+#include <ossim/base/ossimTrace.h>
+static ossimTrace traceExec  = ossimTrace("ossimHdfProjectionFactory:exec");
+static ossimTrace traceDebug = ossimTrace("ossimHdfProjectionFactory:debug");
+
+ossimHdfProjectionFactory* ossimHdfProjectionFactory::instance()
+{
+   static ossimHdfProjectionFactory* factoryInstance =
+      new ossimHdfProjectionFactory();
+
+   return factoryInstance;
+}
+   
+ossimProjection* ossimHdfProjectionFactory::createProjection(
+   const ossimFilename& filename, ossim_uint32 /*entryIdx*/)const
+{
+   static const char MODULE[] = "ossimHdfProjectionFactory::createProjection(ossimFilename& filename)";
+   ossimRefPtr<ossimProjection> projection = 0;
+
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " DEBUG: testing ossimHdfGridModel" << std::endl;
+   }
+
+   ossimKeywordlist kwl;
+   ossimRefPtr<ossimProjection> model = 0;
+   ossimFilename geomFile = filename;
+   geomFile = geomFile.setExtension("geom");
+   
+   if(geomFile.exists()&&
+      kwl.addFile(filename.c_str()))
+   {
+      ossimFilename coarseGrid;
+      
+      const char* type = kwl.find(ossimKeywordNames::TYPE_KW);
+      if(type)
+      {
+         if( ossimString(type) == ossimString("ossimHdfGridModel") )
+         {
+            ossimFilename coarseGrid = geomFile;
+            geomFile.setFile(coarseGrid.fileNoExtension()+"_ocg");
+            
+            if(coarseGrid.exists() &&(coarseGrid != ""))
+            {
+               kwl.add("grid_file_name",
+                       coarseGrid.c_str(),
+                       true);
+               projection = new ossimHdfGridModel();
+               if ( projection->loadState( kwl ) == false )
+               {
+                  projection = 0;
+               }
+            }
+         }
+      }
+   }
+
+   // Must release or pointer will self destruct when it goes out of scope.
+   return projection.release();
+}
+
+ossimProjection* ossimHdfProjectionFactory::createProjection(
+   const ossimString& name)const
+{
+   static const char MODULE[] = "ossimHdfProjectionFactory::createProjection(ossimString& name)";
+
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " DEBUG: Entering ...." << std::endl;
+   }
+
+   if ( name == "ossimHdfGridModel" )
+   {
+      return new ossimHdfGridModel();
+   }
+
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+           << MODULE << " DEBUG: Leaving ...." << std::endl;
+   }
+
+   return 0;
+}
+
+ossimProjection* ossimHdfProjectionFactory::createProjection(
+   const ossimKeywordlist& kwl, const char* prefix)const
+{
+   ossimRefPtr<ossimProjection> result = 0;
+   static const char MODULE[] = "ossimHdfProjectionFactory::createProjection(ossimKeywordlist& kwl)";
+
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " DEBUG: Start ...." << std::endl;
+   }
+   
+   const char* lookup = kwl.find(prefix, ossimKeywordNames::TYPE_KW);
+   if (lookup)
+   {
+      ossimString type = lookup;
+      
+      if (type == "ossimHdfGridModel")
+      {
+         result = new ossimHdfGridModel();
+         if ( !result->loadState(kwl, prefix) )
+         {
+            result = 0;
+         }
+      }
+   }
+
+   if(traceDebug())
+   {
+    	ossimNotify(ossimNotifyLevel_DEBUG)
+        	   << MODULE << " DEBUG: End ...." << std::endl;
+   }
+   
+   return result.release();
+}
+
+ossimObject* ossimHdfProjectionFactory::createObject(
+   const ossimString& typeName)const
+{
+   return createProjection(typeName);
+}
+
+ossimObject* ossimHdfProjectionFactory::createObject(
+   const ossimKeywordlist& kwl, const char* prefix)const
+{
+   return createProjection(kwl, prefix);
+}
+
+
+void ossimHdfProjectionFactory::getTypeNameList(std::vector<ossimString>& typeList)const
+{
+   typeList.push_back(ossimString("ossimHdfGridModel"));
+}
+
+ossimHdfProjectionFactory::ossimHdfProjectionFactory()
+{
+}
+
diff --git a/ossim_plugins/hdf4/ossimHdfProjectionFactory.h b/ossim_plugins/hdf4/ossimHdfProjectionFactory.h
new file mode 100644
index 0000000..32b53e0
--- /dev/null
+++ b/ossim_plugins/hdf4/ossimHdfProjectionFactory.h
@@ -0,0 +1,54 @@
+//----------------------------------------------------------------------------
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef ossimHdfProjectionFactory_HEADER
+#define ossimHdfProjectionFactory_HEADER 1
+
+#include <ossimPluginConstants.h>
+#include <ossim/projection/ossimProjectionFactoryBase.h>
+
+class OSSIM_PLUGINS_DLL ossimHdfProjectionFactory : public ossimProjectionFactoryBase
+{
+public:
+
+   static ossimHdfProjectionFactory* instance();
+
+   /**
+    * @bief Takes a filename. This filename can be an image file or
+    * it can also be a ossim .geom file.  It could be other
+    * forms of geom files as well.  The factories job will be to
+    * determine what parser to use and return a projection if
+    * successful.
+    */
+   virtual ossimProjection* createProjection(const ossimFilename& filename,
+                                             ossim_uint32 entryIdx)const;
+   
+   /** @brief Take a projection type name. */
+   virtual ossimProjection* createProjection(const ossimString& name)const;
+
+   /** @brief Take a keywordlist. */
+   virtual ossimProjection* createProjection(const ossimKeywordlist& kwl,
+                                             const char* prefix=0)const;
+   
+   virtual ossimObject* createObject(const ossimString& typeName)const;
+   
+   /*!
+    * Creates and object given a keyword list.
+    */
+   virtual ossimObject* createObject(const ossimKeywordlist& kwl,
+                                     const char* prefix=0)const;
+   
+   virtual void getTypeNameList(std::vector<ossimString>& typeList)const;
+
+protected:
+   
+   ossimHdfProjectionFactory();
+   
+}; // End: class ossimHdfProjectionFactory{ ... }
+
+#endif /* #ifndef ossimHdfProjectionFactory_HEADER */
+
diff --git a/ossim_plugins/hdf4/ossimHdfReaderFactory.cpp b/ossim_plugins/hdf4/ossimHdfReaderFactory.cpp
new file mode 100644
index 0000000..8a8fc7a
--- /dev/null
+++ b/ossim_plugins/hdf4/ossimHdfReaderFactory.cpp
@@ -0,0 +1,187 @@
+//----------------------------------------------------------------------------
+//
+// License:  See top level LICENSE.txt file
+//
+// Author:  Mingjie Su
+//
+// Description: Factory for OSSIM HDF reader using Hdf4 and Hdf5 libraries.
+//----------------------------------------------------------------------------
+// $Id: ossimHdfReaderFactory.cpp 2645 2011-05-26 15:21:34Z oscar.kramer $
+
+#include "ossimHdfReaderFactory.h"
+#include <ossim/base/ossimKeywordNames.h>
+#include <ossim/base/ossimKeywordlist.h>
+#include <ossim/base/ossimRefPtr.h>
+#include <ossim/base/ossimString.h>
+#include <ossim/base/ossimTrace.h>
+#include <ossim/imaging/ossimImageHandler.h>
+#include "ossimHdf4Reader.h"
+
+static const ossimTrace traceDebug("ossimHdfReaderFactory:debug");
+
+class ossimImageHandler;
+
+RTTI_DEF1(ossimHdfReaderFactory,
+          "ossimHdfReaderFactory",
+          ossimImageHandlerFactoryBase);
+
+ossimHdfReaderFactory* ossimHdfReaderFactory::theInstance = 0;
+
+ossimHdfReaderFactory::~ossimHdfReaderFactory()
+{
+   theInstance = 0;
+}
+
+ossimHdfReaderFactory* ossimHdfReaderFactory::instance()
+{
+   if(!theInstance)
+   {
+      theInstance = new ossimHdfReaderFactory;
+   }
+   return theInstance;
+}
+
+ossimImageHandler* ossimHdfReaderFactory::open(const ossimFilename& fileName,
+                                               bool openOverview)const
+{
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimHdfReaderFactory::open(filename, openOverview) DEBUG: entered..."
+         << std::endl;
+   }
+
+   ossimRefPtr<ossimImageHandler> reader = 0;
+
+   if ( hasExcludedExtension(fileName) == false )
+   {
+      if ( !reader.valid()) //try hdf4 reader
+      {
+         // cout << "Calling ossimHdf4Reader ***********************" << endl;
+         if(traceDebug())
+         {
+            ossimNotify(ossimNotifyLevel_DEBUG)
+               << "trying ossimHdf4Reader..."
+               << std::endl;
+         }
+         reader = new ossimHdf4Reader;
+         reader->setOpenOverviewFlag(openOverview);
+         if(reader->open(fileName) == false)
+         {
+            reader = 0;
+         }
+      }
+    
+      if(!reader.valid())
+      {
+         if(traceDebug())
+         {
+            ossimNotify(ossimNotifyLevel_DEBUG)
+               << "Could not open any handler..."
+               << std::endl;
+         }
+      }  
+   }
+
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimHdfReaderFactory::open(filename, openOverview) DEBUG: leaving..."
+         << std::endl;
+   }
+
+   return reader.release();
+}
+
+ossimImageHandler* ossimHdfReaderFactory::open(const ossimKeywordlist& kwl,
+                                               const char* prefix)const
+{
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimHdfReaderFactory::open(kwl, prefix) DEBUG: entered..."
+         << "Trying ossimKakaduNitfReader"
+         << std::endl;
+   }
+
+   ossimString type = kwl.find(prefix, ossimKeywordNames::TYPE_KW);
+   ossimRefPtr<ossimImageHandler> reader;
+   if(type)
+   {
+      if( (type == "ossimHdf4Reader") ||
+          (type == "ossimImageHandler") )
+      {
+         reader = new ossimHdf4Reader();
+      }
+   }
+   if(reader.valid())
+   {
+      if(!reader->loadState(kwl, prefix))
+      {
+         reader = 0;
+      }
+   }
+
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimHdfReaderFactory::open(kwl, prefix) DEBUG: leaving..."
+         << std::endl;
+   }
+
+   return reader.release();
+}
+
+ossimObject* ossimHdfReaderFactory::createObject(
+   const ossimString& typeName)const
+{
+   ossimRefPtr<ossimObject> result = 0;
+   if(typeName == STATIC_TYPE_NAME(ossimHdf4Reader))
+   {
+      result = new ossimHdf4Reader;
+   }
+   return result.release();
+}
+
+ossimObject* ossimHdfReaderFactory::createObject(
+   const ossimKeywordlist& kwl,
+   const char* prefix)const
+{
+   return this->open(kwl, prefix);
+}
+
+void ossimHdfReaderFactory::getTypeNameList(
+   std::vector<ossimString>& typeList)const
+{
+   typeList.push_back(STATIC_TYPE_NAME(ossimHdf4Reader));
+}
+
+void ossimHdfReaderFactory::getSupportedExtensions(
+   ossimImageHandlerFactoryBase::UniqueStringList& extensionList)const
+{
+   extensionList.push_back(ossimString("h4"));
+   extensionList.push_back(ossimString("he4"));
+   extensionList.push_back(ossimString("hdf4"));
+}
+
+bool ossimHdfReaderFactory::hasExcludedExtension(
+   const ossimFilename& file) const
+{
+   bool result = true;
+   ossimString ext = file.ext().downcase();
+   //only include the file with those extension and exclude any other files
+   if ( ext == "hdf" || ext == "h4" || ext == "hdf4" || 
+      ext == "he4" || ext == "hdf5" || ext == "he5" || ext == "h5" || 
+      ext == "l1r")
+   {
+      result = false;
+   }
+   return result;
+}
+
+ossimHdfReaderFactory::ossimHdfReaderFactory(){}
+
+ossimHdfReaderFactory::ossimHdfReaderFactory(const ossimHdfReaderFactory&){}
+
+void ossimHdfReaderFactory::operator=(const ossimHdfReaderFactory&){}
+
diff --git a/ossim_plugins/hdf4/ossimHdfReaderFactory.h b/ossim_plugins/hdf4/ossimHdfReaderFactory.h
new file mode 100644
index 0000000..c9126a8
--- /dev/null
+++ b/ossim_plugins/hdf4/ossimHdfReaderFactory.h
@@ -0,0 +1,110 @@
+//----------------------------------------------------------------------------
+//
+// License:  See top level LICENSE.txt file
+//
+// Author:  Mingjie Su
+//
+// Description: Factory for OSSIM HDF reader using Hdf4 and Hdf5 libraries.
+//----------------------------------------------------------------------------
+// $Id: ossimHdfReaderFactory.h 2645 2011-05-26 15:21:34Z oscar.kramer $
+
+#ifndef ossimHdfReaderFactory_HEADER
+#define ossimHdfReaderFactory_HEADER
+
+#include <ossim/imaging/ossimImageHandlerFactoryBase.h>
+
+class ossimString;
+class ossimFilename;
+class ossimKeywordlist;
+
+/** @brief Factory for Hdf image reader. */
+class ossimHdfReaderFactory : public ossimImageHandlerFactoryBase
+{
+public:
+
+   /** @brief virtual destructor */
+   virtual ~ossimHdfReaderFactory();
+
+   /**
+    * @brief static method to return instance (the only one) of this class.
+    * @return pointer to instance of this class.
+    */
+   static ossimHdfReaderFactory* instance();
+
+   /**
+    * @brief open that takes a file name.
+    * @param file The file to open.
+    * @param openOverview If true image handler will attempt to open overview.
+    * default = true 
+    * @return pointer to image handler on success, NULL on failure.
+    */
+   virtual ossimImageHandler* open(const ossimFilename& fileName,
+                                   bool openOverview=true) const;
+
+   /**
+    * @brief open that takes a keyword list and prefix.
+    * @param kwl The keyword list.
+    * @param prefix the keyword list prefix.
+    * @return pointer to image handler on success, NULL on failure.
+    */
+   virtual ossimImageHandler* open(const ossimKeywordlist& kwl,
+                                   const char* prefix=0)const;
+
+   /**
+    * @brief createObject that takes a class name (ossimHdf4Reader)
+    * @param typeName Should be "ossimHdf4Reader" or "ossimHdf5Reader".
+    * @return pointer to image writer on success, NULL on failure.
+    */
+   virtual ossimObject* createObject(const ossimString& typeName)const;
+   
+   /**
+    * @brief Creates and object given a keyword list and prefix.
+    * @param kwl The keyword list.
+    * @param prefix the keyword list prefix.
+    * @return pointer to image handler on success, NULL on failure.
+    */
+   virtual ossimObject* createObject(const ossimKeywordlist& kwl,
+                                     const char* prefix=0)const;
+   
+   /**
+    * @brief Adds ossimHdfReader to the typeList.
+    * @param typeList List to add to.
+    */
+   virtual void getTypeNameList(std::vector<ossimString>& typeList)const;
+
+   /**
+    * @brief Method to add supported extension to the list, like "hdf".
+    *
+    * @param extensionList The list to add to.
+    */
+   virtual void getSupportedExtensions(
+      ossimImageHandlerFactoryBase::UniqueStringList& extensionList)const;
+  
+protected:
+
+   /**
+    * @brief Method to weed out extensions that this plugin knows it does
+    * not support.  This is to avoid a costly open on say a tiff or jpeg that
+    * is not handled by this plugin.
+    *
+    * @return true if extension, false if not.
+    */
+   bool hasExcludedExtension(const ossimFilename& file) const;
+   
+   /** @brief hidden from use default constructor */
+   ossimHdfReaderFactory();
+
+   /** @brief hidden from use copy constructor */
+   ossimHdfReaderFactory(const ossimHdfReaderFactory&);
+
+   /** @brief hidden from use copy constructor */
+   void operator=(const ossimHdfReaderFactory&);
+
+   /** static instance of this class */
+   static ossimHdfReaderFactory* theInstance;
+
+TYPE_DATA
+};
+
+#endif /* end of #ifndef ossimHdfReaderFactory_HEADER */
+
diff --git a/ossim_plugins/hdf5/CMakeLists.txt b/ossim_plugins/hdf5/CMakeLists.txt
new file mode 100644
index 0000000..20a6278
--- /dev/null
+++ b/ossim_plugins/hdf5/CMakeLists.txt
@@ -0,0 +1,52 @@
+set(LIB_NAME ossimhdf5_plugin)
+MESSAGE( "************** LIBRARY SETUP FOR ossimhdf5_plugin******************")
+
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
+# Include ossim cmake stuff:
+include(OssimVersion)
+include(OssimCommonVariables)
+include(OssimUtilities)
+
+SET(requiredLibs)
+
+set(HDF5_USE_STATIC_LIBRARIES FALSE)
+
+# Look for HDF5A first; if not found, fall back to HDF5.
+find_package(HDF5A)
+IF(HDF5A_FOUND)
+   INCLUDE_DIRECTORIES( ${HDF5A_INCLUDE_DIR} )
+   SET(requiredLibs ${requiredLibs} ${HDF5A_LIBRARIES} )
+ELSE(HDF5A_FOUND)
+   find_package(HDF5 COMPONENTS CXX C)
+   IF(HDF5_FOUND)
+      INCLUDE_DIRECTORIES( ${HDF5_INCLUDE_DIR} )
+      SET(requiredLibs ${requiredLibs} ${HDF5_CXX_LIBRARIES} ${HDF5_LIBRARIES} )
+   ELSE(HDF5_FOUND)
+      MESSAGE(FATAL_ERROR "Could not find hdf5")
+   ENDIF(HDF5_FOUND)
+ENDIF(HDF5A_FOUND)
+
+FILE(GLOB_RECURSE OSSIMPLUGIN_SRCS *.cpp)
+FILE(GLOB_RECURSE OSSIMPLUGIN_HEADERS *.h)
+
+####
+# OSSIMPLUGINSMAKINGDLL controls dll linkage on windows.  
+# Adding this sets OSSIM_PLUGINS_DLL #define TO "__declspec(dllexport)".
+###
+add_definitions("-DOSSIMPLUGINSMAKINGDLL")
+
+# Adjust the install library path:
+if(OSSIM_INSTALL_PLUGINS_WITH_VERSION)
+   set(INSTALL_LIBRARY_DIR   "${INSTALL_LIBRARY_DIR}/ossim-${OSSIM_VERSION}/plugins")
+else(OSSIM_INSTALL_PLUGINS_WITH_VERSION)
+   set(INSTALL_LIBRARY_DIR   "${INSTALL_LIBRARY_DIR}/ossim/plugins")
+endif(OSSIM_INSTALL_PLUGINS_WITH_VERSION)
+
+OSSIM_LINK_LIBRARY(${LIB_NAME}
+                   COMPONENT_NAME ossim TYPE "${OSSIM_PLUGIN_LINK_TYPE}"
+		   LIBRARIES ${OSSIM_LIBRARY} ${requiredLibs}
+                   HEADERS "${OSSIMPLUGIN_HEADERS}"
+		   SOURCE_FILES "${OSSIMPLUGIN_SRCS}"
+                   INSTALL_LIB)
+
+MESSAGE( STATUS "HDF5 Plugin required libs         = ${requiredLibs}" )
diff --git a/ossim_plugins/hdf5/ossimH5GridModel.cpp b/ossim_plugins/hdf5/ossimH5GridModel.cpp
new file mode 100644
index 0000000..f2dffff
--- /dev/null
+++ b/ossim_plugins/hdf5/ossimH5GridModel.cpp
@@ -0,0 +1,1036 @@
+//*****************************************************************************
+// FILE: ossimH5GridModel.cc
+//
+// License:  See LICENSE.txt file in the top level directory.
+//
+// AUTHOR: David Burken
+//
+// Copied from Mingjie Su's ossimHdfGridModel.
+//
+// DESCRIPTION:
+//   Contains implementation of class ossimH5GridModel. This is an
+//   implementation of an interpolation sensor model. 
+//
+//   IMPORTANT: The lat/lon grid is for ground points on the ellipsoid.
+//   The dLat/dHgt and dLon/dHgt partials therefore are used against
+//   elevations relative to the ellipsoid.
+//
+//*****************************************************************************
+//  $Id$
+
+#include "ossimH5GridModel.h"
+#include "ossimH5Util.h"
+
+#include <ossim/base/ossimCommon.h>
+#include <ossim/base/ossimEndian.h>
+#include <ossim/base/ossimException.h>
+#include <ossim/base/ossimTrace.h>
+#include <ossim/projection/ossimProjectionFactoryRegistry.h>
+
+#include <hdf5.h>
+#include <H5Cpp.h>
+
+#include <sstream>
+
+static ossimTrace traceDebug("ossimH5GridModel:debug");
+
+static const std::string CROSSES_DATELINE_KW = "crosses_dateline";
+static const std::string GROUND_POLYGON_KW   = "ground_polygon"; 
+static const std::string WKT_FOOTPRINT_KW    = "wkt_footprint";
+
+RTTI_DEF1(ossimH5GridModel, "ossimH5GridModel", ossimCoarseGridModel);
+
+ossimH5GridModel::ossimH5GridModel()
+   :
+   ossimCoarseGridModel(),
+   m_crossesDateline(false),
+   m_boundGndPolygon()
+{
+   theLatGrid.setDomainType(ossimDblGrid::SAWTOOTH_90);
+}
+
+ossimH5GridModel::~ossimH5GridModel()
+{
+}
+
+bool ossimH5GridModel::setGridNodes( H5::DataSet* latDataSet,
+                                     H5::DataSet* lonDataSet,
+                                     const ossimIrect& validRect )
+{
+   bool status = false;
+
+   if ( latDataSet && lonDataSet )
+   {
+      m_crossesDateline = ossim_hdf5::crossesDateline( *lonDataSet, validRect );
+      
+      if ( m_crossesDateline )
+      {
+         theLonGrid.setDomainType(ossimDblGrid::CONTINUOUS);
+      }
+      else
+      {
+         // Add 360 to any negative numbers.
+         theLonGrid.setDomainType(ossimDblGrid::WRAP_180);
+      }
+
+      // Get dataspace of the dataset.
+      H5::DataSpace latDataSpace = latDataSet->getSpace();
+      H5::DataSpace lonDataSpace = lonDataSet->getSpace();
+      const ossim_int32 LAT_DIM_COUNT = latDataSpace.getSimpleExtentNdims();
+      const ossim_int32 LON_DIM_COUNT = lonDataSpace.getSimpleExtentNdims();
+      
+      // Number of dimensions of the input dataspace:
+      if ( ( LAT_DIM_COUNT == 2 ) && ( LON_DIM_COUNT == 2 ) )
+      {
+         const ossim_uint32 ROWS = validRect.height();
+         const ossim_uint32 COLS = validRect.width();
+         const ossim_uint32 GRID_SIZE = 4; // Only grab every 4th value.
+
+         //---
+         // Get the extents:
+         // dimsOut[0] is height, dimsOut[1] is width:
+         //---
+         std::vector<hsize_t> latDimsOut(LAT_DIM_COUNT);
+         latDataSpace.getSimpleExtentDims( &latDimsOut.front(), 0 );
+         std::vector<hsize_t> lonDimsOut(LON_DIM_COUNT);
+         lonDataSpace.getSimpleExtentDims( &lonDimsOut.front(), 0 );
+         
+         // Verify valid rect within our bounds:
+         if ( (ROWS <= latDimsOut[0] ) && (ROWS <= lonDimsOut[0] ) &&
+              (COLS <= latDimsOut[1] ) && (COLS <= lonDimsOut[1] ) )
+         {
+            //----
+            // Initialize the ossimDblGrids:
+            //---
+            ossimDpt dspacing (GRID_SIZE, GRID_SIZE);
+            
+            ossim_uint32 gridRows = ROWS / GRID_SIZE + 1;
+            ossim_uint32 gridCols = COLS / GRID_SIZE + 1;
+            
+            // Round up if size doesn't fall on end pixel.
+            if ( ROWS % GRID_SIZE) ++gridRows;
+            if ( COLS % GRID_SIZE) ++gridCols;
+
+            ossimIpt gridSize (gridCols, gridRows);
+            
+            // The grid as used in base class, has UV-space always at 0,0 origin            
+            ossimDpt gridOrigin(0.0,0.0);
+
+            const ossim_float64 NULL_VALUE = -999.0;
+            
+            theLatGrid.setNullValue(ossim::nan());
+            theLonGrid.setNullValue(ossim::nan());
+            theLatGrid.initialize(gridSize, gridOrigin, dspacing);
+            theLonGrid.initialize(gridSize, gridOrigin, dspacing);            
+            
+            std::vector<hsize_t> inputCount(LAT_DIM_COUNT);
+            std::vector<hsize_t> inputOffset(LAT_DIM_COUNT);
+            
+            inputOffset[0] = 0; // row is set below.
+            inputOffset[1] = validRect.ul().x; // col
+            
+            inputCount[0] = 1; // row
+            inputCount[1] = (hsize_t)COLS; // col
+            
+            // Output dataspace dimensions. Reading a line at a time.
+            const ossim_int32 OUT_DIM_COUNT = 3;
+            std::vector<hsize_t> outputCount(OUT_DIM_COUNT);
+            outputCount[0] = 1;    // band
+            outputCount[1] = 1;    // row
+            outputCount[2] = COLS; // col
+            
+            // Output dataspace offset.
+            std::vector<hsize_t> outputOffset(OUT_DIM_COUNT);
+            outputOffset[0] = 0;
+            outputOffset[1] = 0;
+            outputOffset[2] = 0;
+            
+            ossimScalarType scalar = ossim_hdf5::getScalarType( latDataSet );
+            if ( scalar == OSSIM_FLOAT32 )
+            {
+               // Set the return status to true if we get here...
+               status = true;
+               
+               // See if we need to swap bytes:
+               ossimEndian* endian = 0;
+               if ( ( ossim::byteOrder() != ossim_hdf5::getByteOrder( latDataSet ) ) )
+               {
+                  endian = new ossimEndian();
+               }
+               
+               // Native type:
+               H5::DataType latDataType = latDataSet->getDataType();
+               H5::DataType lonDataType = lonDataSet->getDataType();
+
+               // Output dataspace always the same, width of one line.
+               H5::DataSpace bufferDataSpace( OUT_DIM_COUNT, &outputCount.front());
+               bufferDataSpace.selectHyperslab( H5S_SELECT_SET,
+                                                &outputCount.front(),
+                                                &outputOffset.front() );
+
+               //  Arrays to hold a single line of latitude longitude values.
+               vector<ossim_float32> latValue(COLS);
+               vector<ossim_float32> lonValue(COLS);
+               hsize_t row = 0;
+
+               // Line loop:
+               for ( ossim_uint32 y = 0; y < gridRows; ++y )
+               {
+                  // row = line in image space
+                  row = y*GRID_SIZE;
+
+                  if ( row < ROWS )
+                  {
+                     inputOffset[0] = row + validRect.ul().y;
+
+                     latDataSpace.selectHyperslab( H5S_SELECT_SET,
+                                                   &inputCount.front(),
+                                                   &inputOffset.front() );
+                     lonDataSpace.selectHyperslab( H5S_SELECT_SET,
+                                                   &inputCount.front(),
+                                                   &inputOffset.front() );
+                  
+                     // Read data from file into the buffer.
+                     latDataSet->read( &(latValue.front()), latDataType,
+                                       bufferDataSpace, latDataSpace );
+                     lonDataSet->read( &(lonValue.front()), lonDataType,
+                                       bufferDataSpace, lonDataSpace );
+                  
+                     if ( endian )
+                     {
+                        // If the endian pointer is initialized(not zero) swap the bytes.
+                        endian->swap( &(latValue.front()), COLS );
+                        endian->swap( &(lonValue.front()), COLS );  
+                     }
+                  
+                     // Sample loop:
+                     hsize_t col = 0;
+                     
+                     for ( ossim_uint32 x = 0; x < gridCols; ++x )
+                     {
+                        ossim_float32 lat = ossim::nan();
+                        ossim_float32 lon = ossim::nan();
+                        
+                        // col = sample in image space
+                        col = x*GRID_SIZE;
+
+                        if ( col < COLS )
+                        {
+                           if ( (latValue[col] > NULL_VALUE)&&(lonValue[col] > NULL_VALUE) )
+                           {
+                              lat = latValue[col];
+                              lon = lonValue[col];
+                              if ( m_crossesDateline )
+                              {
+                                 if ( lon < 0.0 ) lon += 360;
+                              }
+                           }
+                           else // Nulls in grid!
+                           {
+                              std::string errMsg =
+                                 "ossimH5GridModel::setGridNodes encountered nans!";
+                              throw ossimException(errMsg); 
+                           }
+                        }
+                        else // Last column is outside of image bounds.
+                        {
+                           // Get the last two latitude values:
+                           ossim_float32 lat1 = theLatGrid.getNode( x-2, y );
+                           ossim_float32 lat2 = theLatGrid.getNode( x-1, y );
+
+                           // Get the last two longitude values
+                           ossim_float32 lon1 = theLonGrid.getNode( x-2, y );
+                           ossim_float32 lon2 = theLonGrid.getNode( x-1, y );
+                           
+                           if ( ( lat1 > NULL_VALUE ) && ( lat2 > NULL_VALUE ) )
+                           {
+                              // Delta between last two latitude grid values.
+                              ossim_float32 latSpacing = lat2 - lat1;
+                           
+                              // Compute:
+                              lat = lat2 + latSpacing;
+                           }
+                           else // Nulls in grid!
+                           {
+                              std::string errMsg =
+                                 "ossimH5GridModel::setGridNodes encountered nans!";
+                              throw ossimException(errMsg);
+                           }
+
+                           if ( ( lon1 > NULL_VALUE ) && ( lon2 > NULL_VALUE ) )
+                           {
+                              // Delta between last two longitude values.
+                              ossim_float32 lonSpacing = lon2 - lon1;
+                           
+                              // Compute:
+                              lon = lon2 + lonSpacing;
+
+                              // Check for wrap:
+                              if ( !m_crossesDateline && ( lon > 180 ) )
+                              {
+                                 lon -= 360.0;
+                              }
+                           }
+                           else // Nulls in grid!
+                           {
+                              std::string errMsg =
+                                 "ossimH5GridModel::setGridNodes encountered nans!";
+                              throw ossimException(errMsg);
+                           }
+
+#if 0 /* Please leave for debug. (drb) */                        
+                           cout << "lat1: " << lat1 << " lat2 " << lat2
+                                << " lon1 " << lon1  << " lon2 " << lon2
+                                << "\n";
+#endif
+                        }
+                        
+                        // Assign the latitude and longitude.
+                        theLatGrid.setNode( x, y, lat );
+                        theLonGrid.setNode( x, y, lon );
+                        
+#if 0 /* Please leave for debug. (drb) */ 
+                        cout << "x,y,col,row,lat,lon:" << x << "," << y << ","
+                             << col << "," << row << ","
+                             << theLatGrid.getNode(x, y)
+                             << "," << theLonGrid.getNode( x, y) << "\n";
+#endif
+                        
+                     } // End sample loop.
+                     
+                  }
+                  else // Row is outside of image bounds:
+                  {
+                     // Sample loop:
+                     for ( ossim_uint32 x = 0; x < gridCols; ++x )
+                     {
+                        ossim_float32 lat        = ossim::nan();
+                        ossim_float32 lon        = ossim::nan();
+                        
+                        ossim_float32 lat1 = theLatGrid.getNode( x, y-2 );
+                        ossim_float32 lat2 = theLatGrid.getNode( x, y-1 );
+                        ossim_float32 lon1 = theLonGrid.getNode( x, y-2 );
+                        ossim_float32 lon2 = theLonGrid.getNode( x, y-1 );
+                        
+                        if ( ( lon1 > NULL_VALUE ) && ( lon2 > NULL_VALUE ) )
+                        {
+                           // Delta between last two longitude values.
+                           ossim_float32 lonSpacing = lon2 - lon1;
+                           
+                           // Compute:
+                           lon = lon2 + lonSpacing;
+                           
+                           // Check for wrap:
+                           if ( !m_crossesDateline && ( lon > 180 ) )
+                           {
+                              lon -= 360.0;
+                           }
+                        }
+                        else // Nulls in grid!
+                        {
+                           std::string errMsg =
+                              "ossimH5GridModel::setGridNodes encountered nans!";
+                           throw ossimException(errMsg);
+                        }
+                        
+                        if ( ( lat1 > NULL_VALUE ) && ( lat2 > NULL_VALUE ) )
+                        {
+                           // Delta between last two latitude values.
+                           ossim_float32 latSpacing = lat2 - lat1;
+
+                           lat = lat2 + latSpacing;
+                        }
+                        else // Nulls in grid!
+                        {
+                           std::string errMsg =
+                              "ossimH5GridModel::setGridNodes encountered nans!";
+                           throw ossimException(errMsg);
+                        }
+                        
+#if 0 /* Please leave for debug. (drb) */
+                        hsize_t col = x*GRID_SIZE; // Sample in image space
+                        cout << "lat1: " << lat1 << " lat2 " << lat2
+                             << " lon1 " << lon1  << " lon2 " << lon2
+                             << "\nx,y,col,row,lat,lon:" << x << "," << y << ","
+                             << col << "," << row << "," << lat << "," << lon << "\n";
+#endif
+                        // Assign the latitude::
+                        theLatGrid.setNode( x, y, lat );
+
+                        // Assign the longitude.
+                        theLonGrid.setNode( x, y, lon );
+                     
+                     } // End sample loop.
+                  
+                  } // Matches if ( row < imageRows ){...}else{
+                  
+               } // End line loop.
+
+               latDataSpace.close();
+               lonDataSpace.close();
+
+               if ( status )
+               {
+                  theSeedFunction = ossim_hdf5::getBilinearProjection(
+                     *latDataSet,*lonDataSet, validRect );
+                  
+                  // Bileaner projection to handle
+                  ossimDrect imageRect(validRect);
+                  initializeModelParams(imageRect);
+
+                  // debugDump();
+               }
+
+               if ( endian )
+               {
+                  delete endian;
+                  endian = 0;
+               }
+               
+            } // Matches: if ( scalar == OSSIM_FLOAT32 )
+            
+         } // Matches: if ( (latDimsOut[0] == imageRows) ...
+         
+      } // Matches: if ( ( LAT_DIM_COUNT == 2 ) ...
+
+   } // Matches: if ( latDataSet && lonDataSet
+
+   return status;
+   
+} // End: bool ossimH5GridModel::setGridNodes( H5::DataSet* latDataSet, ... )
+
+bool ossimH5GridModel::saveState(ossimKeywordlist& kwl, const char* prefix) const
+{
+   // Base save state.  This will save the "type" key to "ossimH5GridModel".
+   bool status = ossimCoarseGridModel::saveState( kwl, prefix );
+   
+   if ( status )
+   {
+      std::string myPrefix = ( prefix ? prefix: "" );
+      std::string value;
+
+      // m_crossesDateline:
+      value = ossimString::toString(m_crossesDateline).string();
+      kwl.addPair( myPrefix,CROSSES_DATELINE_KW, value, true );
+
+      // Computed wkt footprint:
+      if ( getWktFootprint( value ) )
+      {   
+         kwl.addPair( myPrefix, WKT_FOOTPRINT_KW, value, true );
+      }      
+
+      // m_boundGndPolygon:
+      if ( m_boundGndPolygon.getNumberOfVertices() )
+      {
+         std::string polyPrefix = myPrefix;
+         polyPrefix += GROUND_POLYGON_KW;
+         polyPrefix += ".";         
+         m_boundGndPolygon.saveState( kwl, polyPrefix.c_str() );
+      }
+
+      //---
+      // theSeedFunction: This is in the base class ossimSensorModel but is not
+      // in the ossimSensorModel::saveState so do it here.
+      //---
+      if ( theSeedFunction.valid() )
+      {
+         ossimString seedPrefix = myPrefix;
+         seedPrefix += "seed_projection.";
+         status = theSeedFunction->saveState(kwl, seedPrefix.c_str());
+      }
+   }
+
+   return status;
+}     
+
+bool ossimH5GridModel::loadState(const ossimKeywordlist& kwl, const char* prefix)
+{
+   bool result = false;
+   
+   std::string myPrefix = ( prefix ? prefix: "" );
+
+   // Look for type key:
+   std::string key = "type";
+   std::string value = kwl.findKey( myPrefix, key );
+
+   if ( value.size() )
+   {
+      // ossimHdfGridModel included for backward compatibility.
+      if ( ( value == "ossimH5GridModel" ) || ( value == "ossimHdfGridModel" ) )
+      {
+         //---
+         // theSeedFunction: This is in the base class ossimSensorModel but is not
+         // in the ossimSensorModel::loadState so do it here.
+         //---
+         std::string seedPrefix = myPrefix;
+         seedPrefix += "seed_projection.";
+         value = kwl.findKey( seedPrefix, key );
+         if ( value.size() )
+         {
+            // Only do expensive factory call if key is found...
+            theSeedFunction = ossimProjectionFactoryRegistry::instance()->
+               createProjection(kwl, seedPrefix.c_str());         
+         }
+         
+         // m_crossesDateline:
+         value = kwl.findKey( myPrefix, CROSSES_DATELINE_KW );
+         if ( value.size() )
+         {
+            m_crossesDateline = ossimString(value).toBool();
+         }
+
+         // m_boundGndPolygon:
+         std::string polyPrefix = myPrefix;
+         polyPrefix += GROUND_POLYGON_KW;
+         polyPrefix += ".";
+         m_boundGndPolygon.clear();
+         m_boundGndPolygon.loadState( kwl, polyPrefix.c_str() );
+      
+         // Make a copy of kwl so we can change type.
+         ossimKeywordlist myKwl = kwl;
+         value = "ossimCoarseGridModel";
+         myKwl.addPair( myPrefix, key, value, true );
+
+         // Load the state of base class.
+         result = ossimCoarseGridModel::loadState( myKwl, prefix );
+      }
+   }
+   
+   return result;
+   
+} // End: ossimH5GridModel::loadState( ... )
+
+//---------------------------------------------------------------------------**
+//  METHOD: ossimSensorModel::worldToLineSample()
+//  
+//  Performs forward projection of ground point to image space.
+//  
+//---------------------------------------------------------------------------**
+void ossimH5GridModel::worldToLineSample(const ossimGpt& worldPoint,
+                                         ossimDpt&       ip) const
+{
+   static const double PIXEL_THRESHOLD    = .1; // acceptable pixel error
+   static const int    MAX_NUM_ITERATIONS = 20;
+
+   if(worldPoint.isLatNan() || worldPoint.isLonNan())
+   {
+      ip.makeNan();
+      return;
+   }
+      
+   //---
+   // First check if the world point is inside bounding rectangle:
+   //---
+   int iters = 0;
+   ossimDpt wdp (worldPoint);
+   if ( m_crossesDateline && (wdp.x < 0.0) )
+   {
+      // Longitude points stored between 0 and 360.
+      wdp.x += 360.0;
+   }
+   
+   if( (m_boundGndPolygon.getNumberOfVertices() > 0) &&
+       (!m_boundGndPolygon.hasNans()) )
+   {
+      if (!(m_boundGndPolygon.pointWithin(wdp)))
+      {
+         // if(theSeedFunction.valid())
+         // {
+         //    theSeedFunction->worldToLineSample(worldPoint, ip);
+         // }
+         // else if(!theExtrapolateGroundFlag) // if I am not already in the extrapolation routine
+         // {
+         //    ip = extrapolate(worldPoint);
+         // }
+      ip.makeNan();
+         return;
+      } 
+
+   }
+
+   //---
+   // Substitute zero for null elevation if present:
+   //---
+   double height = worldPoint.hgt;
+   if ( ossim::isnan(height) )
+   {
+      height = 0.0;
+   }
+
+   //---
+   // Utilize iterative scheme for arriving at image point. Begin with guess
+   // at image center:
+   //---
+   if(theSeedFunction.valid())
+   {
+      theSeedFunction->worldToLineSample(worldPoint, ip);
+   }
+   else
+   {
+      ip.u = theRefImgPt.u;
+      ip.v = theRefImgPt.v;
+   }
+   
+   ossimDpt ip_du;
+   ossimDpt ip_dv;
+
+   ossimGpt gp, gp_du, gp_dv;
+   double dlat_du, dlat_dv, dlon_du, dlon_dv;
+   double delta_lat, delta_lon, delta_u, delta_v;
+   double inverse_norm;
+   bool done = false;
+   //---
+   // Begin iterations:
+   //---
+   do
+   {
+      //---
+      // establish perturbed image points about the guessed point:
+      //---
+      ip_du.u = ip.u + 1.0;
+      ip_du.v = ip.v;
+      ip_dv.u = ip.u;
+      ip_dv.v = ip.v + 1.0;
+      
+      //---
+      // Compute numerical partials at current guessed point:
+      //---
+      lineSampleHeightToWorld(ip,    height, gp);
+      lineSampleHeightToWorld(ip_du, height, gp_du);
+      lineSampleHeightToWorld(ip_dv, height, gp_dv);
+      
+      if(gp.isLatNan() || gp.isLonNan())
+      {
+         gp = ossimCoarseGridModel::extrapolate(ip);
+      }
+      if(gp_du.isLatNan() || gp_du.isLonNan())
+      {
+         gp_du = ossimCoarseGridModel::extrapolate(ip_du);
+      }
+      if(gp_dv.isLatNan() || gp_dv.isLonNan())
+      {
+         gp_dv = ossimCoarseGridModel::extrapolate(ip_dv);
+         
+      }
+
+      if ( m_crossesDateline )
+      {
+         // Longitude set to between 0 and 360.
+         if ( gp.lon < 0.0 )    gp.lon    += 360.0;
+         if ( gp_du.lon < 0.0 ) gp_du.lon += 360.0;
+         if ( gp_dv.lon < 0.0 ) gp_dv.lon += 360.0;
+      }
+      
+      dlat_du = gp_du.lat - gp.lat; //e
+      dlon_du = gp_du.lon - gp.lon; //g
+      dlat_dv = gp_dv.lat - gp.lat; //f
+      dlon_dv = gp_dv.lon - gp.lon; //h
+      
+      //---
+      // Test for convergence:
+      // Use the wdp as it was corrected if there was a date line cross.
+      //
+      delta_lat = wdp.lat - gp.lat;
+      delta_lon = wdp.lon - gp.lon;
+
+      // Compute linearized estimate of image point given gp delta:
+      inverse_norm = dlat_dv*dlon_du - dlat_du*dlon_dv; // fg-eh
+      
+      if (!ossim::almostEqual(inverse_norm, 0.0, DBL_EPSILON))
+      {
+         delta_u = (-dlon_dv*delta_lat + dlat_dv*delta_lon)/inverse_norm;
+         delta_v = ( dlon_du*delta_lat - dlat_du*delta_lon)/inverse_norm;
+         ip.u += delta_u;
+         ip.v += delta_v;
+      }
+      else
+      {
+         delta_u = 0;
+         delta_v = 0;
+      }
+
+#if 0
+      cout << "gp:    " << gp
+           << "\ngp_du: " << gp_du
+           << "\ngp_dv: " << gp_dv
+           << "\ndelta_lat: " << delta_lat
+           << "\ndelta_lon: " << delta_lon     
+           << "\ndelta_u: " << delta_u
+           << "\ndelta_v: " << delta_v
+           << endl;
+#endif      
+      
+      done = ((fabs(delta_u) < PIXEL_THRESHOLD)&&
+              (fabs(delta_v) < PIXEL_THRESHOLD));
+      ++iters;
+
+   } while ( (!done) && (iters < MAX_NUM_ITERATIONS));
+
+   //---
+   // Note that this error mesage appears only if max count was reached while
+   // iterating. A linear (no iteration) solution would finish with iters =
+   // MAX_NUM_ITERATIONS + 1:
+   //---
+#if 0 /* please leave for debug: */
+   if (iters >= MAX_NUM_ITERATIONS)
+   {
+      std::cout << "MAX ITERATION!!!" << std::endl;
+      std::cout << "delta_u = "   << delta_u
+                << "\ndelta_v = " << delta_v << "\n";
+   }
+   else
+   {
+      std::cout << "ITERS === " << iters << std::endl;
+   }
+   std::cout << "iters = " << iters << "\n";
+#endif   
+
+   //---
+   // The image point computed this way corresponds to full image space.
+   // Apply image offset in the case this is a sub-image rectangle:
+   //---
+   ip -= theSubImageOffset;
+   
+} // End: worldToLineSample( ... )
+
+void ossimH5GridModel::initializeModelParams(ossimIrect imageBounds)
+{
+   theLatGrid.enableExtrapolation();
+   theLonGrid.enableExtrapolation();
+   theHeightEnabledFlag = false;
+
+   // NOTE: it is assumed that the grid size and spacing is the same for ALL grids:
+   ossimIpt gridSize (theLatGrid.size());
+   ossimDpt spacing  (theLatGrid.spacing());
+   ossimDpt v[4];
+   v[0].lat = theLatGrid.getNode(0,0);
+   v[0].lon = theLonGrid.getNode(0,0);
+   v[1].lat = theLatGrid.getNode(gridSize.x-1, 0);
+   v[1].lon = theLonGrid.getNode(gridSize.x-1, 0);
+   v[2].lat = theLatGrid.getNode(gridSize.x-1, gridSize.y-1);
+   v[2].lon = theLonGrid.getNode(gridSize.x-1, gridSize.y-1);
+   v[3].lat = theLatGrid.getNode(0, gridSize.y-1);
+   v[3].lon = theLonGrid.getNode(0, gridSize.y-1);
+
+   if ( m_crossesDateline )
+   {
+      // Longitude values between 0 and 360.
+      m_boundGndPolygon = ossimPolygon(4, v);
+   }
+   
+   // Guaranty longitude values are -180 to 180
+   for (int i=0; i<4; ++i)
+   {
+      if (v[i].lon > 180.0) v[i].lon -= 360.0;
+   }
+
+   theBoundGndPolygon = ossimPolygon(4, v);
+
+   if ( !m_crossesDateline )
+   {
+      // Longitude values between -180 and 180.
+      m_boundGndPolygon = theBoundGndPolygon;
+   }
+   
+   theImageSize  = ossimDpt(imageBounds.width(), imageBounds.height());
+   theRefImgPt   = imageBounds.midPoint();
+   theRefGndPt.lat = theLatGrid(theRefImgPt);
+   theRefGndPt.lon = theLonGrid(theRefImgPt);
+   
+   ossimDpt ref_ip_dx (theRefImgPt.x+1.0, theRefImgPt.y    );
+   ossimDpt ref_ip_dy (theRefImgPt.x    , theRefImgPt.y+1.0);
+   ossimGpt ref_gp_dx (theLatGrid(ref_ip_dx), theLonGrid(ref_ip_dx));
+   ossimGpt ref_gp_dy (theLatGrid(ref_ip_dy), theLonGrid(ref_ip_dy));
+
+   theGSD.x   = theRefGndPt.distanceTo(ref_gp_dx);
+   theGSD.y   = theRefGndPt.distanceTo(ref_gp_dy);
+
+   theMeanGSD = (theGSD.line + theGSD.samp)/2.0;
+   theImageClipRect  = imageBounds;
+
+   // Image is clipped to valid rect so no sub image offset.
+   theSubImageOffset = ossimDpt(0.0, 0.0); //imageBounds.ul();
+
+   theRefGndPt.limitLonTo180();
+
+   // debugDump();
+   
+} // End: initializeModelParams
+
+
+ossimDpt ossimH5GridModel::extrapolate( const ossimGpt& gpt ) const
+{
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         <<  "DEBUG ossimH5GridModel::extrapolate: entering... " << std::endl;
+   }
+
+   theExtrapolateGroundFlag = true;
+   double height = 0.0;
+
+   //---
+   // If ground point supplied has NaN components, return now with a NaN point.
+   //---
+   if ( (ossim::isnan(gpt.lat)) || (ossim::isnan(gpt.lon)) )
+   {
+      theExtrapolateGroundFlag = false;
+      if (traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG)
+            << "DEBUG ossimH5GridModel::extrapolate: returning..." << std::endl;
+      }
+      return ossimDpt(ossim::nan(), ossim::nan());
+   }
+   
+   if(ossim::isnan(gpt.hgt) == false)
+   {
+      height = gpt.hgt;
+   }
+   
+   if(theSeedFunction.valid())
+   {
+      ossimDpt ipt;
+      
+      theSeedFunction->worldToLineSample(gpt, ipt);
+      
+      theExtrapolateGroundFlag = false;
+      return ipt;
+   }
+   
+   //---
+   // Determine which edge is intersected by the radial, and establish
+   // intersection:
+   //---
+   ossimDpt edgePt (gpt);
+   ossimDpt image_center (theRefGndPt);
+   if ( m_crossesDateline )
+   {
+      // Longitude points between 0 and 360.
+      if (edgePt.lon < 0.0 ) edgePt.lon += 360.0;
+      if ( image_center.lon < 0.0 ) image_center.lon += 360.0;
+   }
+   
+   m_boundGndPolygon.clipLineSegment(image_center, edgePt);
+
+   //---
+   // Compute an epsilon perturbation in the direction away from edgePt for
+   // later computing directional derivative:
+   //---
+   const double  DEG_PER_MTR =  8.983152841e-06; // Equator WGS-84...
+   double epsilon = theMeanGSD*DEG_PER_MTR; //degrees (latitude) per pixel
+   ossimDpt deltaPt (edgePt-image_center);
+   ossimDpt epsilonPt (deltaPt*epsilon/deltaPt.length());
+   edgePt -= epsilonPt;
+   ossimDpt edgePt_prime (edgePt - epsilonPt);
+       
+   //---
+   // Establish image point corresponding to edge point and edgePt+epsilon:
+   //---
+   ossimGpt edgeGP       (edgePt.lat,       edgePt.lon,       height);//gpt.hgt);
+   ossimGpt edgeGP_prime (edgePt_prime.lat, edgePt_prime.lon, height);//gpt.hgt);
+   if ( m_crossesDateline )
+   {
+      // Put longitude back between -180 and 180.
+      edgeGP.limitLonTo180();
+      edgeGP_prime.limitLonTo180();
+   }
+
+   worldToLineSample(edgeGP, edgePt);
+   worldToLineSample(edgeGP_prime, edgePt_prime);
+
+   //---
+   // Compute approximate directional derivatives of line and sample along
+   // radial at the edge:
+   //---
+   double dsamp_drad = (edgePt.samp - edgePt_prime.samp)/epsilon;
+   double dline_drad = (edgePt.line - edgePt_prime.line)/epsilon;
+
+   //---
+   // Now extrapolate to point of interest:
+   //---
+   double delta = (ossimDpt(gpt) - ossimDpt(edgeGP)).length();
+
+   
+   ossimDpt extrapolated_ip (edgePt.samp + delta*dsamp_drad,
+                             edgePt.line + delta*dline_drad);
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "DEBUG ossimH5GridModel::extrapolate: returning..." << std::endl;  
+   }
+   
+   theExtrapolateGroundFlag = false;
+   return extrapolated_ip;
+   
+} // ossimH5GridModel::extrapolate
+
+bool ossimH5GridModel::getWktFootprint( std::string& s ) const
+{
+   bool status = true;
+
+   // Loop until complete or a "nan" is hit.
+   while ( 1 )
+   {
+      ossim_float32 lat = 0.0;
+      ossim_float32 lon = 0.0;
+
+      std::ostringstream os;
+
+      os <<  setprecision(10) << "MULTIPOLYGON(((";
+      const ossim_int32 STEP = 128;
+      
+      ossimIrect rect( 0, 0, theImageSize.x-1, theImageSize.y-1 );  
+
+      ossim_int32 x = 0;
+      ossim_int32 y = 0;
+      
+      // Walk the top line:
+      while ( x < theImageSize.x )
+      {
+         lat = theLatGrid( x, y );
+         lon = theLonGrid( x, y );
+
+         if ( ossim::isnan(lat) || ossim::isnan(lon) )
+         {
+            status = false;
+            break;
+         }
+         
+         os << lon << " " << lat << ",";
+         
+         if ( x != rect.ur().x )
+         {
+            x = ossim::min<ossim_int32>( x+STEP, rect.ur().x );
+         }
+         else
+         {
+            break; // End of top line walk.
+         }
+      }
+
+      if ( !status ) break; // Found "nan" so get out.
+      
+      // Walk the right edge:
+      y = ossim::min<ossim_int32>( y+STEP, rect.lr().y );
+      while ( y < theImageSize.y )
+      {
+         lat = theLatGrid( x, y );
+         lon = theLonGrid( x, y );
+
+         if ( ossim::isnan(lat) || ossim::isnan(lon) )
+         {
+            status = false;
+            break;
+         }
+
+         os << lon << " " << lat << ",";
+         
+         if ( y != rect.lr().y )
+         {
+            y = ossim::min<ossim_int32>( y+STEP, rect.lr().y );
+         }
+         else
+         {
+            break;
+         }
+      }
+
+      if ( !status ) break; // Found "nan" so get out.
+      
+      // Walk the bottom line from right to left:
+      x = ossim::max<ossim_int32>( rect.lr().x-STEP, 0 );
+      while ( x >= 0 )
+      {
+         lat = theLatGrid( x, y );
+         lon = theLonGrid( x, y );
+         
+         if ( ossim::isnan(lat) || ossim::isnan(lon) )
+         {
+            status = false;
+            break;
+         }
+
+         os << lon << " " << lat << ",";
+         
+         if ( x != 0 )
+         {
+            x = ossim::max<ossim_int32>( x-STEP, 0 );
+         }
+         else
+         {
+            break;
+         }
+      }
+
+      if ( !status ) break; // Found "nan" so get out.
+      
+      // Walk the left edge from bottom to top:
+      y = ossim::max<ossim_int32>( y-STEP, 0 );
+      while ( y >= 0 )
+      {
+         lat = theLatGrid( x, y );
+         lon = theLonGrid( x, y );
+
+         if ( ossim::isnan(lat) || ossim::isnan(lon) )
+         {
+            status = false;
+            break;
+         }
+
+         if ( ( x == 0 ) && ( y == 0 ) )
+         {
+            os << lon << " " << lat; // Last point:
+         }
+         else
+         {
+            os << lon << " " << lat << ",";
+         }
+         
+         if ( y != 0 )
+         {
+            y = ossim::max<ossim_int32>( y-STEP, 0 );
+         }
+         else
+         {
+            break;
+         }
+      }
+
+      if ( !status ) break; // Found "nan" so get out.
+      
+      os << ")))";
+      s = os.str();
+
+      // Trailing break from while ( FOREVER ) loop:
+      break;
+      
+   } // Matches: while ( 1 )
+   
+   return status;
+}
+
+void ossimH5GridModel::debugDump()
+{
+   ossimIpt step (theImageSize/200);
+   int margin = 0;
+   double lat, lon;
+   ossimDpt pt (0,0);
+   ofstream fslat ("lat_grid.dat");
+   ofstream fslon ("lon_grid.dat");
+   fslat<< setprecision(10) <<endl;
+   fslon<< setprecision(10) <<endl;
+   for (pt.v = -margin*step.v; pt.v < theImageSize.v+margin*step.v; pt.v += step.y)
+   {
+      for (pt.u = -margin*step.u; pt.u < theImageSize.u+margin*step.u ; pt.u += step.u)
+      {
+         lat = theLatGrid(pt.u, pt.v);
+         lon = theLonGrid(pt.u, pt.v);
+         fslat << pt.u << " " << pt.v << " " << lat << endl;
+         fslon << pt.u << " " << pt.v << " " << lon << endl;
+      }
+   }
+   fslat.close();
+   fslon.close();
+}
diff --git a/ossim_plugins/hdf5/ossimH5GridModel.h b/ossim_plugins/hdf5/ossimH5GridModel.h
new file mode 100644
index 0000000..e0bd926
--- /dev/null
+++ b/ossim_plugins/hdf5/ossimH5GridModel.h
@@ -0,0 +1,128 @@
+//*****************************************************************************
+// FILE: ossimH5GridModel.h
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// AUTHOR: David Burken
+//
+// Copied from Mingjie Su's ossimHdfGridModel.
+//
+// DESCRIPTION:
+//   Contains declaration of class ossimHdfGridModel. This is an
+//   implementation of an interpolation sensor model.
+//
+//*****************************************************************************
+//  $Id$
+
+#ifndef ossimH5GridModel_HEADER
+#define ossimH5GridModel_HEADER 1
+#include <ossim/base/ossimPolygon.h>
+#include <ossim/projection/ossimCoarseGridModel.h>
+
+#include "../ossimPluginConstants.h"
+
+#include <string>
+
+// Forward class declarations:
+class ossimDpt;
+class ossimGpt;
+namespace H5
+{
+   class DataSet;
+   class H5File;
+}
+
+/******************************************************************************
+ *
+ * CLASS:  ossimH5GridModel
+ *
+ *****************************************************************************/
+class OSSIM_PLUGINS_DLL ossimH5GridModel : public ossimCoarseGridModel
+{
+public:
+
+   /** @brief default constructor. */
+   ossimH5GridModel();
+   
+   /** @brief virtual destructor */
+   virtual ~ossimH5GridModel();
+
+   /**
+    * @brief Initializes the latitude and longitude ossimDblGrids from file.
+    * @param latDataSet H5::DataSet* to layer,
+    *    e.g. /All_Data/VIIRS-DNB-GEO_All/Latitude
+    * @param lonDataSet H5::DataSet* to layer,
+    *    e.g. /All_Data/VIIRS-DNB-GEO_All/Longitude
+    * @param validRect Valid rectangle of image.
+    * @return true on success, false on error.
+    *
+    * This can throw an ossimException on nans.
+    */
+   bool setGridNodes( H5::DataSet* latDataSet,
+                      H5::DataSet* lonDataSet,
+                      const ossimIrect& validRect );
+   
+   /**
+    * @brief saveState Saves state of object to a keyword list.
+    * @param kwl Initialized by this.
+    * @param prefix E.g. "image0.geometry.projection."
+    * @return true on success, false on error.
+    */
+   virtual bool saveState(ossimKeywordlist& kwl, const char* prefix=0) const;
+
+   /**
+    * @brief loadState Loads state of object from a keyword list.
+    * @param kwl Keyword list to initialize from.
+    * @param prefix E.g. "image0.geometry.projection."
+    * @return true on success, false on error.
+    */
+   virtual bool loadState(const ossimKeywordlist& kwl, const char* prefix=0);
+
+   /**
+    * METHOD: extrapolate()
+    * Extrapolates solutions for points outside of the image. The second
+    * version accepts a height value -- if left at the default, the elevation
+    * will be looked up via theElevation object.
+    */
+   virtual void  worldToLineSample(const ossimGpt& world_point,
+                                   ossimDpt&       image_point) const;
+
+protected:
+
+   /**
+    * @brief Initializes base class data members after grids have been assigned.
+    *
+    * Overrides base class method to handle date line cross.
+    */
+   void initializeModelParams(ossimIrect imageBounds);
+
+   /**
+    * @brief extrapolate()
+    * Extrapolates solutions for points outside of the image.
+    *
+    * Overrides base class method to handle date line cross.
+    */
+   virtual ossimDpt extrapolate( const ossimGpt& gp ) const;
+   
+private:
+   
+   bool getWktFootprint( std::string& s ) const;
+   
+   void debugDump();
+
+   bool m_crossesDateline;
+
+   //---
+   // This polygon differs from base "theBoundGndPolygon" in that if the
+   // scene crosses the dateline the longitude values are stored between
+   // 0 and 360 degress as opposed to -180 to 180.
+   //---
+   ossimPolygon m_boundGndPolygon;
+   
+   TYPE_DATA
+};
+
+#endif /* Matches: #ifndef ossimH5GridModel_HEADER */
+
diff --git a/ossim_plugins/hdf5/ossimH5ImageDataset.cpp b/ossim_plugins/hdf5/ossimH5ImageDataset.cpp
new file mode 100644
index 0000000..dedd73c
--- /dev/null
+++ b/ossim_plugins/hdf5/ossimH5ImageDataset.cpp
@@ -0,0 +1,369 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author:  David Burken
+//
+// Description: OSSIM HDF5 Image DataSet.
+//
+//----------------------------------------------------------------------------
+// $Id
+
+#include "ossimH5ImageDataset.h"
+#include "ossimH5Util.h"
+#include <ossim/base/ossimCommon.h>
+#include <ossim/base/ossimEndian.h>
+#include <ossim/base/ossimIpt.h>
+#include <ossim/base/ossimIrect.h>
+#include <ossim/base/ossimNotify.h>
+#include <ossim/base/ossimScalarTypeLut.h>
+
+//---
+// This includes everything!  Note the H5 includes are order dependent; hence,
+// the mongo include.
+//---
+#include <hdf5.h>
+#include <H5Cpp.h>
+
+#include <iostream>
+using namespace std;
+
+ossimH5ImageDataset::ossimH5ImageDataset()
+   :
+   m_dataset(0),
+   m_datasetName(),
+   m_scalar(OSSIM_SCALAR_UNKNOWN),
+   m_bands(1),
+   m_lines(0),
+   m_samples(0),
+   m_validRect(),
+   m_endian(0)
+{   
+}
+
+ossimH5ImageDataset::ossimH5ImageDataset( const ossimH5ImageDataset& obj )
+   :
+   m_dataset( ( (obj.m_dataset)?new H5::DataSet(*(obj.m_dataset)):0 ) ),
+   m_datasetName(obj.m_datasetName),
+   m_scalar(obj.m_scalar),
+   m_bands(obj.m_bands),
+   m_lines(obj.m_lines),
+   m_samples(obj.m_samples),
+   m_validRect(obj.m_validRect),
+   m_endian( obj.m_endian ? new ossimEndian() : 0 )
+{
+   if ( obj.m_dataset )
+   {
+      m_dataset = new H5::DataSet( *(obj.m_dataset) );
+   }
+}
+
+ossimH5ImageDataset::~ossimH5ImageDataset()
+{
+   close();
+}
+
+const ossimH5ImageDataset& ossimH5ImageDataset::operator=( const ossimH5ImageDataset& rhs )
+{
+   if ( this != &rhs )
+   {
+      if ( m_dataset )
+      {
+         delete m_dataset;
+      }
+      if ( rhs.m_dataset )
+      {
+         m_dataset = new H5::DataSet( *(rhs.m_dataset) );
+      }
+      else
+      {
+         m_dataset = 0;
+      }
+      m_datasetName = rhs.m_datasetName;
+      m_scalar      = rhs.m_scalar;
+      m_bands       = rhs.m_bands;
+      m_lines       = rhs.m_lines;
+      m_samples     = rhs.m_samples;
+      m_validRect   = rhs.m_validRect;
+      m_endian      = ( rhs.m_endian ? new ossimEndian() : 0 );
+   }
+   return *this;
+}
+
+bool ossimH5ImageDataset::initialize( const H5::DataSet& dataset,
+                                      const std::string& datasetName )
+{
+   bool result = false;
+   
+   // Clear old stuff.
+   close();
+   
+   m_dataset = new H5::DataSet( dataset );
+   m_datasetName = datasetName;
+
+   if ( ossim_hdf5::getValidBoundingRect( *m_dataset, m_datasetName, m_validRect ) )
+   {
+      // Get the extents:
+      std::vector<ossim_uint32> extents;
+      ossim_hdf5::getExtents( m_dataset, extents );
+      if ( extents.size() >= 2 )
+      {
+         m_samples = extents[1];
+         m_lines   = extents[0];
+         if ( extents.size() >= 3 )
+         {
+            m_bands = extents[2];
+         }
+         else
+         {
+            m_bands = 1;
+         }
+         
+         // Scalar type:
+         m_scalar = ossim_hdf5::getScalarType( m_dataset );
+         
+         if ( m_scalar != OSSIM_SCALAR_UNKNOWN )
+         {
+            result = true;
+            
+            // Byte swapping logic:
+            if ( ( ossim::scalarSizeInBytes( m_scalar ) > 1 ) &&
+                 ( ossim::byteOrder() != ossim_hdf5::getByteOrder( m_dataset ) ) )
+            {
+               m_endian = new ossimEndian();
+            }
+         }
+      }
+   }
+
+   if ( !result )
+   {
+      // One dimensional dataset:
+      close();
+   }
+
+   return result;
+   
+} // End: ossimH5ImageDataset::initialize
+
+void ossimH5ImageDataset::close()
+{
+   if ( m_dataset )
+   {
+      m_dataset->close();
+      delete m_dataset;
+      m_dataset = 0;
+   }
+   if ( m_endian )
+   {
+      delete m_endian;
+      m_endian = 0;
+   }
+}
+
+const H5::DataSet* ossimH5ImageDataset::getDataset() const
+{
+   return m_dataset;
+}
+
+H5::DataSet* ossimH5ImageDataset::getDataset()
+{
+   return m_dataset;
+}
+
+const std::string& ossimH5ImageDataset::getName() const
+{
+   return m_datasetName;
+}
+
+ossimScalarType ossimH5ImageDataset::getScalarType() const
+{
+   return m_scalar;
+}
+
+ossim_uint32 ossimH5ImageDataset::getNumberOfBands() const
+{
+   return m_bands;
+}
+
+ossim_uint32 ossimH5ImageDataset::getNumberOfLines() const
+{
+   return m_validRect.height();
+}
+
+ossim_uint32 ossimH5ImageDataset::getNumberOfSamples() const
+{
+   return m_validRect.width();
+}
+
+bool ossimH5ImageDataset::getSwapFlag() const
+{
+   return (m_endian ? true: false);
+}
+
+const ossimIpt& ossimH5ImageDataset::getSubImageOffset() const
+{
+   return m_validRect.ul();
+}
+
+const ossimIrect& ossimH5ImageDataset::getValidImageRect() const
+{
+   return m_validRect;
+}
+
+void ossimH5ImageDataset::getTileBuf(void* buffer, const ossimIrect& rect, ossim_uint32 band)
+{
+   static const char MODULE[] = "ossimH5ImageDataset::getTileBuf";
+
+   if ( m_dataset )
+   {
+      try
+      {
+         // Shift rectangle by the sub image offse (if any) from the m_validRect.
+         ossimIrect irect = rect + m_validRect.ul();
+         
+         //--
+         // Turn off the auto-printing when failure occurs so that we can
+         // handle the errors appropriately
+         //---
+         // H5::Exception::dontPrint();
+
+         // NOTE: rank == array dimensions in hdf5 documentation lingo.
+
+         // Get dataspace of the dataset.
+         H5::DataSpace imageDataSpace = m_dataset->getSpace();
+      
+         // Number of dimensions of the input dataspace.:
+         const ossim_int32 IN_DIM_COUNT = imageDataSpace.getSimpleExtentNdims();
+
+         // Native type:
+         H5::DataType dataType = m_dataset->getDataType();
+      
+         std::vector<hsize_t> inputCount(IN_DIM_COUNT);
+         std::vector<hsize_t> inputOffset(IN_DIM_COUNT);
+
+         if ( IN_DIM_COUNT == 2 )
+         {
+            inputOffset[0] = irect.ul().y;
+            inputOffset[1] = irect.ul().x;
+         
+            inputCount[0] = irect.height();
+            inputCount[1] = irect.width();
+         }
+         else
+         {
+            inputOffset[0] = band;
+            inputOffset[1] = irect.ul().y;
+            inputOffset[2] = irect.ul().x;
+         
+            inputCount[0] = 1;
+            inputCount[1] = irect.height();
+            inputCount[2] = irect.width();
+         }
+      
+         // Define hyperslab in the dataset; implicitly giving strike strike and block NULL.
+         imageDataSpace.selectHyperslab( H5S_SELECT_SET,
+                                         &inputCount.front(),
+                                         &inputOffset.front() );
+      
+         // Output dataspace dimensions.
+         const ossim_int32 OUT_DIM_COUNT = 3;
+         std::vector<hsize_t> outputCount(OUT_DIM_COUNT);
+         outputCount[0] = 1;             // single band
+         outputCount[1] = irect.height(); // lines
+         outputCount[2] = irect.width();  // samples
+
+         // Output dataspace offset.
+         std::vector<hsize_t> outputOffset(OUT_DIM_COUNT);
+         outputOffset[0] = 0;
+         outputOffset[1] = 0;
+         outputOffset[2] = 0;
+      
+         // Output dataspace.
+         H5::DataSpace bufferDataSpace( OUT_DIM_COUNT, &outputCount.front());
+         bufferDataSpace.selectHyperslab( H5S_SELECT_SET,
+                                          &outputCount.front(),
+                                          &outputOffset.front() );
+      
+         // Read data from file into the buffer.
+         m_dataset->read( buffer, dataType, bufferDataSpace, imageDataSpace );
+
+         if ( m_endian )
+         {
+            // If the m_endian pointer is initialized(not zero) swap the bytes.
+            m_endian->swap( m_scalar, buffer, irect.area() );
+         }
+      
+         // Cleanup:
+         bufferDataSpace.close();
+         dataType.close();
+         imageDataSpace.close();
+         
+         // memSpace.close();
+         // dataType.close();
+         // dataSpace.close();
+      }
+      catch( const H5::FileIException& error )
+      {
+         ossimNotify(ossimNotifyLevel_WARN)
+            << MODULE << " caught H5::FileIException!" << std::endl;
+         error.printError();
+      }
+   
+      // catch failure caused by the DataSet operations
+      catch( const H5::DataSetIException& error )
+      {
+         ossimNotify(ossimNotifyLevel_WARN)
+            << MODULE << " caught H5::DataSetIException!" << std::endl;
+         error.printError();
+      }
+   
+      // catch failure caused by the DataSpace operations
+      catch( const H5::DataSpaceIException& error )
+      {
+         ossimNotify(ossimNotifyLevel_WARN)
+            << MODULE << " caught H5::DataSpaceIException!" << std::endl;
+         error.printError();
+      }
+   
+      // catch failure caused by the DataSpace operations
+      catch( const H5::DataTypeIException& error )
+      {
+         ossimNotify(ossimNotifyLevel_WARN)
+            << MODULE << " caught H5::DataTypeIException!" << std::endl;
+         error.printError();
+      }
+      catch( ... )
+      {
+         ossimNotify(ossimNotifyLevel_WARN)
+            << MODULE << " caught unknown exception !" << std::endl;
+      }
+      
+   } // Matches: if ( m_dataset )
+   
+} // End: ossimH5ImageDataset::getTileBuf
+
+
+std::ostream& ossimH5ImageDataset::print( std::ostream& out ) const
+{
+   out << "ossimH5ImageDataset: "
+       << "\nH5::DataSet::id: " << (m_dataset?m_dataset->getId():0)
+       << "\nname:            " << m_datasetName
+       << "\nscalar:          " << ossimScalarTypeLut::instance()->getEntryString( m_scalar )
+       << "\nbands:           " << m_bands
+       << "\nlines:           " << m_lines
+       << "\nsamples:         " << m_samples
+       << "\nvalid rect:      " << m_validRect
+       << "\nswap_flage:      " << (m_endian?"true":"false")
+       << std::endl;
+   return out;
+}
+
+std::ostream& operator<<( std::ostream& out, const ossimH5ImageDataset& obj )
+{
+   return obj.print( out );
+}
+
+
diff --git a/ossim_plugins/hdf5/ossimH5ImageDataset.h b/ossim_plugins/hdf5/ossimH5ImageDataset.h
new file mode 100644
index 0000000..0f03520
--- /dev/null
+++ b/ossim_plugins/hdf5/ossimH5ImageDataset.h
@@ -0,0 +1,143 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author:  David Burken
+//
+// Description: OSSIM HDF5 Image DataSet.
+//
+//----------------------------------------------------------------------------
+// $Id
+
+#ifndef ossimH5ImageDataset_HEADER
+#define ossimH5ImageDataset_HEADER 1
+
+#include <ossim/base/ossimConstants.h>
+#include <ossim/base/ossimIrect.h>
+#include <iosfwd>
+#include <string>
+
+// Forward class declarations:
+class ossimImageData;
+class ossimEndian;
+class ossimIpt;
+class ossimIrect;
+namespace H5
+{
+   class DataSet;
+   class H5File;
+}
+
+/**
+ * @brief Class encapsulates a HDF5 Data set that can be loaded as an image.
+ */
+class ossimH5ImageDataset
+{
+public:
+   /** default constructor */
+   ossimH5ImageDataset();
+   
+   /** copy constructor */
+   ossimH5ImageDataset( const ossimH5ImageDataset& obj );
+   
+   /** destructor */
+   ~ossimH5ImageDataset();
+
+   /** @brief Calls H5::DataSet::close then deletes data set. */
+   void close();
+
+   const ossimH5ImageDataset& operator=( const ossimH5ImageDataset& rhs );
+
+   /**
+    * @brief Opens datasetName and initializes all data members on success.
+    * @return true on success, false on error.
+    */
+   bool initialize( const H5::DataSet& dataset,
+                    const std::string& datasetName );
+
+   /**
+    * @brief Get const pointer to dataset.
+    *
+    * This can be null if not open.
+    * 
+    * @return const pointer to dataset.
+    */
+   const H5::DataSet* getDataset() const;
+   
+   /**
+    * @brief Get pointer to dataset.
+    *
+    * This can be null if not open.
+    * 
+    * @return pointer to dataset.
+    */
+   H5::DataSet* getDataset();
+
+   /** @return The dataset name.  This is the full path used for open. */
+   const std::string& getName() const;
+
+   /** @return The output scalar type. */
+   ossimScalarType getScalarType() const;
+
+   /** @return the number of . */
+   ossim_uint32 getNumberOfBands() const;
+
+   /** @return The number of lines. */
+   ossim_uint32 getNumberOfLines() const;
+   
+   /** @return The number of samples. */
+   ossim_uint32 getNumberOfSamples() const;
+
+   /** @return The swap flag. */
+   bool getSwapFlag() const;
+
+   const ossimIpt& getSubImageOffset() const;
+
+   const ossimIrect& getValidImageRect() const;
+
+   /**
+    *  @brief Method to grab a tile(rectangle) from image.
+    *
+    *  @param buffer Buffer for data for this method to copy data to.
+    *  Should be the size of rect * bytes_per_pixel for scalar type.
+    *
+    *  @param rect The zero based rectangle to grab.  Rectangle is relative to
+    *  any sub image offset. E.g. A request for 0,0 is the upper left corner
+    *  of the valid image rect.
+    *
+    *  @param band
+    */
+   void getTileBuf(void* buffer, const ossimIrect& rect, ossim_uint32 band);   
+
+   /**
+    * @brief print method.
+    * @return std::ostream&
+    */
+   std::ostream& print(std::ostream& out) const;
+
+   friend OSSIMDLLEXPORT std::ostream& operator<<(std::ostream& out,
+                                                  const ossimH5ImageDataset& obj);
+private:
+   H5::DataSet*    m_dataset;
+   std::string     m_datasetName;
+   ossimScalarType m_scalar;
+   ossim_uint32    m_bands;   
+   ossim_uint32    m_lines;
+   ossim_uint32    m_samples;
+
+   /**
+    * Zero based image rect:
+    *
+    * H5 data can have null rows on the front or end.  The valid rect is the
+    * scanned rectangle disregarding leading or trailing nulls.  This does
+    * not handle null rows in the middle of the image.
+    */
+   ossimIrect      m_validRect; // Zero based image rect:
+   ossimEndian*    m_endian; // For byte swapping if needed.
+   
+}; // End: class ossimH5ImageDataset
+
+#endif /* #ifndef ossimH5ImageDataset_HEADER */
+
diff --git a/ossim_plugins/hdf5/ossimH5Info.cpp b/ossim_plugins/hdf5/ossimH5Info.cpp
new file mode 100644
index 0000000..09103e1
--- /dev/null
+++ b/ossim_plugins/hdf5/ossimH5Info.cpp
@@ -0,0 +1,141 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author:  David Burken
+//
+// Description: HDF5 Info class.
+// 
+//----------------------------------------------------------------------------
+// $Id$
+
+#include "ossimH5Info.h"
+#include "ossimH5Util.h"
+
+#include <ossim/base/ossimCommon.h>
+#include <ossim/base/ossimEndian.h>
+#include <ossim/base/ossimNotify.h>
+#include <ossim/base/ossimTrace.h>
+
+//---
+// This includes everything!  Note the H5 includes are order dependent; hence,
+// the mongo include.
+//---
+#include <hdf5.h>
+#include <H5Cpp.h>
+
+#include <fstream>
+#include <iostream>
+#include <iomanip>
+#include <sstream>
+
+static ossimTrace traceDebug("ossimH5Info:debug");
+
+ossimH5Info::ossimH5Info()
+   : ossimInfoBase(),
+     m_file()
+{
+}
+
+ossimH5Info::~ossimH5Info()
+{
+}
+
+bool ossimH5Info::open(const ossimFilename& file)
+{
+   bool result = false;
+
+   // Check for empty filename.
+   if (file.size())
+   {
+      try
+      {
+         //--
+         // Turn off the auto-printing when failure occurs so that we can
+         // handle the errors appropriately
+         //---
+         H5::Exception::dontPrint();
+         
+         if ( H5::H5File::isHdf5( file.string() ) )
+         {
+            m_file = file;
+            result = true;
+         }
+      }
+      catch( const H5::Exception& e )
+      {
+         e.getDetailMsg();
+      }
+      catch( ... )
+      {
+         if ( traceDebug() )
+         {
+            ossimNotify(ossimNotifyLevel_WARN)
+               << "ossimH5Info::open WARNING Caught unhandled exception for file:\n"
+               << file.c_str() << std::endl;
+         }
+      }
+   }
+
+   return result;
+}
+
+std::ostream& ossimH5Info::print(std::ostream& out) const
+{
+   static const char MODULE[] = "ossimH5Info::open";
+   
+   if ( traceDebug() )
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " entered..."
+         << "File:  " << m_file.c_str()
+         << std::endl;
+   }
+
+   // Check for empty filename.
+   if (m_file.size())
+   {
+      try
+      {
+         //--
+         // Turn off the auto-printing when failure occurs so that we can
+         // handle the errors appropriately
+         //---
+         H5::Exception::dontPrint();
+
+         H5::H5File* h5File = new H5::H5File();
+         
+         H5::FileAccPropList access_plist = H5::FileAccPropList::DEFAULT;
+         
+         h5File->openFile( m_file.string(), H5F_ACC_RDONLY, access_plist );
+         
+         // std::vector<std::string> names;
+         // ossim_hdf5::getDatasetNames( h5File, names );
+         ossim_hdf5::print( h5File, out );
+
+         // cleanup...
+         h5File->close();
+         delete h5File;
+         h5File = 0;
+         
+      } // End: try block
+      catch( const H5::Exception& e )
+      {
+         e.getDetailMsg();
+      }
+      catch( ... )
+      {
+         if ( traceDebug() )
+         {
+            ossimNotify(ossimNotifyLevel_WARN)
+               << "ossimH5Info::print WARNIN: Caught unhandled exception!"
+               << std::endl;
+         }
+      }
+   }
+
+   return out;
+}
+
diff --git a/ossim_plugins/hdf5/ossimH5Info.h b/ossim_plugins/hdf5/ossimH5Info.h
new file mode 100644
index 0000000..4bc1c6c
--- /dev/null
+++ b/ossim_plugins/hdf5/ossimH5Info.h
@@ -0,0 +1,63 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author:  David Burken
+//
+// Description: HDF5 Info class.
+// 
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef ossimH5Info_HEADER
+#define ossimH5Info_HEADER 1
+
+#include <ossim/base/ossimConstants.h>
+#include <ossim/support_data/ossimInfoBase.h>
+#include <ossim/base/ossimFilename.h>
+#include "../ossimPluginConstants.h"
+
+class ossimEndian;
+
+/**
+ * @brief TIFF info class.
+ *
+ * Encapsulates the listgeo functionality.
+ */
+class OSSIM_PLUGINS_DLL ossimH5Info : public ossimInfoBase
+{
+public:
+   
+   /** default constructor */
+   ossimH5Info();
+
+   /** virtual destructor */
+   virtual ~ossimH5Info();
+
+   /**
+    * @brief open method.
+    *
+    * @param file File name to open.
+    *
+    * @return true on success false on error.
+    */
+   virtual bool open(const ossimFilename& file);
+   
+   /**
+    * Print method.
+    *
+    * @param out Stream to print to.
+    * 
+    * @return std::ostream&
+    */
+   virtual std::ostream& print(std::ostream& out) const;
+
+private:
+
+   ossimFilename  m_file;
+};
+
+#endif /* End of "#ifndef ossimH5Info_HEADER" */
+
diff --git a/ossim_plugins/hdf5/ossimH5InfoFactory.cpp b/ossim_plugins/hdf5/ossimH5InfoFactory.cpp
new file mode 100644
index 0000000..cda0017
--- /dev/null
+++ b/ossim_plugins/hdf5/ossimH5InfoFactory.cpp
@@ -0,0 +1,59 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author: David Burken
+//
+// Copied from Mingjie Su's ossimHdfInfoFactory
+//
+// Description: Factory for info objects.
+// 
+//----------------------------------------------------------------------------
+// $Id$
+
+#include "ossimH5InfoFactory.h"
+#include <ossim/support_data/ossimInfoFactory.h>
+#include <ossim/support_data/ossimInfoBase.h>
+#include <ossim/base/ossimFilename.h>
+#include <ossim/base/ossimRefPtr.h>
+#include "ossimH5Info.h"
+
+ossimH5InfoFactory::~ossimH5InfoFactory()
+{}
+
+ossimH5InfoFactory* ossimH5InfoFactory::instance()
+{
+   static ossimH5InfoFactory sharedInstance;
+
+   return &sharedInstance;
+}
+
+ossimInfoBase* ossimH5InfoFactory::create(const ossimFilename& file) const
+{
+   ossimRefPtr<ossimInfoBase> result = 0;
+
+   // cout << "Calling ossimH5Info ***********************" << endl;
+   result = new ossimH5Info();
+   if ( result->open(file) )
+   {
+      return result.release();
+   }
+
+   return 0;
+}
+
+ossimH5InfoFactory::ossimH5InfoFactory()
+{}
+
+ossimH5InfoFactory::ossimH5InfoFactory(const ossimH5InfoFactory& /* obj */ )
+{}
+
+const ossimH5InfoFactory& ossimH5InfoFactory::operator=(
+   const ossimH5InfoFactory& /* rhs */)
+{
+   return *this;
+}
+
+
diff --git a/ossim_plugins/hdf5/ossimH5InfoFactory.h b/ossim_plugins/hdf5/ossimH5InfoFactory.h
new file mode 100644
index 0000000..3ccf9f1
--- /dev/null
+++ b/ossim_plugins/hdf5/ossimH5InfoFactory.h
@@ -0,0 +1,59 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author: David Burken
+//
+// Copied from Mingjie Su's ossimHdfInfoFactory
+//
+// Description: Factory for hdf info objects.
+// 
+//----------------------------------------------------------------------------
+// $Id$
+#ifndef ossimH5InfoFactory_HEADER
+#define ossimH5InfoFactory_HEADER 1
+
+#include <ossim/base/ossimConstants.h>
+#include <ossim/support_data/ossimInfoFactoryInterface.h>
+
+class ossimFilename;
+class ossimInfoBase;
+
+/**
+ * @brief Info factory.
+ */
+class ossimH5InfoFactory : public ossimInfoFactoryInterface
+{
+public:
+
+   /** virtual destructor */
+   virtual ~ossimH5InfoFactory();
+
+   static ossimH5InfoFactory* instance();
+
+   /**
+    * @brief create method.
+    *
+    * @param file Some file you want info for.
+    *
+    * @return ossimInfoBase* on success 0 on failure.  Caller is responsible
+    * for memory.
+    */
+   virtual ossimInfoBase* create(const ossimFilename& file) const;
+   
+private:
+   
+   /** hidden from use default constructor */
+   ossimH5InfoFactory();
+
+   /** hidden from use copy constructor */
+   ossimH5InfoFactory(const ossimH5InfoFactory& obj);
+
+   /** hidden from use operator = */
+   const ossimH5InfoFactory& operator=(const ossimH5InfoFactory& rhs);
+};
+
+#endif /* End of "#ifndef ossimH5InfoFactory_HEADER" */
+
diff --git a/ossim_plugins/hdf5/ossimH5PluginInit.cpp b/ossim_plugins/hdf5/ossimH5PluginInit.cpp
new file mode 100644
index 0000000..a942d4c
--- /dev/null
+++ b/ossim_plugins/hdf5/ossimH5PluginInit.cpp
@@ -0,0 +1,94 @@
+//----------------------------------------------------------------------------
+//
+// License:  See top level LICENSE.txt file
+//
+// Author: David Burken
+//
+// Copied from Mingjie Su's ossimHdfPluginInit.
+//
+// Description: OSSIM HDF plugin initialization
+// code.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include <ossim/plugin/ossimSharedObjectBridge.h>
+#include <ossim/imaging/ossimImageHandlerRegistry.h>
+#include <ossim/imaging/ossimImageWriterFactoryRegistry.h>
+#include <ossim/imaging/ossimOverviewBuilderFactoryRegistry.h>
+#include <ossim/projection/ossimProjectionFactoryRegistry.h>
+#include <ossim/support_data/ossimInfoFactoryRegistry.h>
+
+#include "../ossimPluginConstants.h"
+#include "ossimH5ReaderFactory.h"
+#include "ossimH5InfoFactory.h"
+#include "ossimH5ProjectionFactory.h"
+
+static void setDescription(ossimString& description)
+{
+   description = "HDF5 reader plugin\n\n";
+}
+
+extern "C"
+{
+   ossimSharedObjectInfo  myInfo;
+   ossimString theDescription;
+   std::vector<ossimString> theObjList;
+
+   const char* getDescription()
+   {
+      return theDescription.c_str();
+   }
+
+   int getNumberOfClassNames()
+   {
+      return (int)theObjList.size();
+   }
+
+   const char* getClassName(int idx)
+   {
+      if(idx < (int)theObjList.size())
+      {
+         return theObjList[0].c_str();
+      }
+      return (const char*)0;
+   }
+
+   /* Note symbols need to be exported on windoze... */ 
+   OSSIM_PLUGINS_DLL void ossimSharedLibraryInitialize(
+      ossimSharedObjectInfo** info)
+   {    
+      myInfo.getDescription = getDescription;
+      myInfo.getNumberOfClassNames = getNumberOfClassNames;
+      myInfo.getClassName = getClassName;
+
+      *info = &myInfo;
+
+      /* Register the readers... */
+      ossimImageHandlerRegistry::instance()->
+         registerFactory(ossimH5ReaderFactory::instance());
+
+      /* Register hdf info factoy... */
+      ossimInfoFactoryRegistry::instance()->
+         registerFactory(ossimH5InfoFactory::instance());
+
+      /* Register hdf projection factoy... */
+      ossimProjectionFactoryRegistry::instance()->
+         registerFactoryToFront(ossimH5ProjectionFactory::instance());
+
+      setDescription(theDescription);
+   }
+
+   /* Note symbols need to be exported on windoze... */ 
+   OSSIM_PLUGINS_DLL void ossimSharedLibraryFinalize()
+   {
+      ossimImageHandlerRegistry::instance()->
+         unregisterFactory(ossimH5ReaderFactory::instance());
+
+      ossimInfoFactoryRegistry::instance()->
+         unregisterFactory(ossimH5InfoFactory::instance());
+
+      ossimProjectionFactoryRegistry::instance()->
+         unregisterFactory(ossimH5ProjectionFactory::instance());
+   }
+}
diff --git a/ossim_plugins/hdf5/ossimH5ProjectionFactory.cpp b/ossim_plugins/hdf5/ossimH5ProjectionFactory.cpp
new file mode 100644
index 0000000..3bbbca5
--- /dev/null
+++ b/ossim_plugins/hdf5/ossimH5ProjectionFactory.cpp
@@ -0,0 +1,163 @@
+//----------------------------------------------------------------------------
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//----------------------------------------------------------------------------
+// $Id$
+
+#include "ossimH5ProjectionFactory.h"
+#include <ossim/base/ossimKeywordNames.h>
+#include <ossim/base/ossimRefPtr.h>
+#include <ossim/projection/ossimProjection.h>
+#include "ossimH5GridModel.h"
+
+//---
+// Define Trace flags for use within this file:
+//---
+#include <ossim/base/ossimTrace.h>
+static ossimTrace traceExec  = ossimTrace("ossimH5ProjectionFactory:exec");
+static ossimTrace traceDebug = ossimTrace("ossimH5ProjectionFactory:debug");
+
+ossimH5ProjectionFactory* ossimH5ProjectionFactory::instance()
+{
+   static ossimH5ProjectionFactory* factoryInstance =
+      new ossimH5ProjectionFactory();
+
+   return factoryInstance;
+}
+   
+ossimProjection* ossimH5ProjectionFactory::createProjection(
+   const ossimFilename& filename, ossim_uint32 /*entryIdx*/)const
+{
+   static const char MODULE[] = "ossimH5ProjectionFactory::createProjection(ossimFilename& filename)";
+   ossimRefPtr<ossimProjection> projection = 0;
+
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " DEBUG: testing ossimH5GridModel" << std::endl;
+   }
+
+   ossimKeywordlist kwl;
+   ossimRefPtr<ossimProjection> model = 0;
+   ossimFilename geomFile = filename;
+   geomFile = geomFile.setExtension("geom");
+   
+   if(geomFile.exists()&&
+      kwl.addFile(filename.c_str()))
+   {
+      ossimFilename coarseGrid;
+      
+      const char* type = kwl.find(ossimKeywordNames::TYPE_KW);
+      if(type)
+      {
+         // ossimHdfGridModel included for backward compatibility.
+         if( ( ossimString(type) == ossimString("ossimH5GridModel") ) ||
+             ( ossimString(type) == ossimString("ossimHdfGridModel") ) )
+         {
+            ossimFilename coarseGrid = geomFile;
+            geomFile.setFile(coarseGrid.fileNoExtension()+"_ocg");
+            
+            if(coarseGrid.exists() &&(coarseGrid != ""))
+            {
+               kwl.add("grid_file_name",
+                       coarseGrid.c_str(),
+                       true);
+               projection = new ossimH5GridModel();
+               if ( projection->loadState( kwl ) == false )
+               {
+                  projection = 0;
+               }
+            }
+         }
+      }
+   }
+
+   // Must release or pointer will self destruct when it goes out of scope.
+   return projection.release();
+}
+
+ossimProjection* ossimH5ProjectionFactory::createProjection(
+   const ossimString& name)const
+{
+   static const char MODULE[] = "ossimH5ProjectionFactory::createProjection(ossimString& name)";
+
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " DEBUG: Entering ...." << std::endl;
+   }
+
+   // ossimHdfGridModel included for backward compatibility.
+   if ( ( name == "ossimH5GridModel" ) || ( name == "ossimHdfGridModel" ) )
+   {
+      return new ossimH5GridModel();
+   }
+
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+           << MODULE << " DEBUG: Leaving ...." << std::endl;
+   }
+
+   return 0;
+}
+
+ossimProjection* ossimH5ProjectionFactory::createProjection(
+   const ossimKeywordlist& kwl, const char* prefix)const
+{
+   ossimRefPtr<ossimProjection> result = 0;
+   static const char MODULE[] = "ossimH5ProjectionFactory::createProjection(ossimKeywordlist& kwl)";
+
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " DEBUG: Start ...." << std::endl;
+   }
+   
+   const char* lookup = kwl.find(prefix, ossimKeywordNames::TYPE_KW);
+   if (lookup)
+   {
+      ossimString type = lookup;
+      
+      if ( (type == "ossimH5GridModel") || ( type == "ossimHdfGridModel" ) )
+      {
+         result = new ossimH5GridModel();
+         if ( !result->loadState(kwl, prefix) )
+         {
+            result = 0;
+         }
+      }
+   }
+
+   if(traceDebug())
+   {
+    	ossimNotify(ossimNotifyLevel_DEBUG)
+        	   << MODULE << " DEBUG: End ...." << std::endl;
+   }
+   
+   return result.release();
+}
+
+ossimObject* ossimH5ProjectionFactory::createObject(
+   const ossimString& typeName)const
+{
+   return createProjection(typeName);
+}
+
+ossimObject* ossimH5ProjectionFactory::createObject(
+   const ossimKeywordlist& kwl, const char* prefix)const
+{
+   return createProjection(kwl, prefix);
+}
+
+
+void ossimH5ProjectionFactory::getTypeNameList(std::vector<ossimString>& typeList)const
+{
+   typeList.push_back(ossimString("ossimH5GridModel"));
+}
+
+ossimH5ProjectionFactory::ossimH5ProjectionFactory()
+{
+}
+
diff --git a/ossim_plugins/hdf5/ossimH5ProjectionFactory.h b/ossim_plugins/hdf5/ossimH5ProjectionFactory.h
new file mode 100644
index 0000000..733d5a6
--- /dev/null
+++ b/ossim_plugins/hdf5/ossimH5ProjectionFactory.h
@@ -0,0 +1,54 @@
+//----------------------------------------------------------------------------
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef ossimH5ProjectionFactory_HEADER
+#define ossimH5ProjectionFactory_HEADER 1
+
+#include <ossimPluginConstants.h>
+#include <ossim/projection/ossimProjectionFactoryBase.h>
+
+class OSSIM_PLUGINS_DLL ossimH5ProjectionFactory : public ossimProjectionFactoryBase
+{
+public:
+
+   static ossimH5ProjectionFactory* instance();
+
+   /**
+    * @bief Takes a filename. This filename can be an image file or
+    * it can also be a ossim .geom file.  It could be other
+    * forms of geom files as well.  The factories job will be to
+    * determine what parser to use and return a projection if
+    * successful.
+    */
+   virtual ossimProjection* createProjection(const ossimFilename& filename,
+                                             ossim_uint32 entryIdx)const;
+   
+   /** @brief Take a projection type name. */
+   virtual ossimProjection* createProjection(const ossimString& name)const;
+
+   /** @brief Take a keywordlist. */
+   virtual ossimProjection* createProjection(const ossimKeywordlist& kwl,
+                                             const char* prefix=0)const;
+   
+   virtual ossimObject* createObject(const ossimString& typeName)const;
+   
+   /*!
+    * Creates and object given a keyword list.
+    */
+   virtual ossimObject* createObject(const ossimKeywordlist& kwl,
+                                     const char* prefix=0)const;
+   
+   virtual void getTypeNameList(std::vector<ossimString>& typeList)const;
+
+protected:
+   
+   ossimH5ProjectionFactory();
+   
+}; // End: class ossimH5ProjectionFactory{ ... }
+
+#endif /* #ifndef ossimH5ProjectionFactory_HEADER */
+
diff --git a/ossim_plugins/hdf5/ossimH5Reader.cpp b/ossim_plugins/hdf5/ossimH5Reader.cpp
new file mode 100644
index 0000000..e03e354
--- /dev/null
+++ b/ossim_plugins/hdf5/ossimH5Reader.cpp
@@ -0,0 +1,989 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author:  David Burken
+//
+// Description: OSSIM HDF5 Reader.
+//
+//----------------------------------------------------------------------------
+// $Id: ossimH5Reader.cpp 19878 2011-07-28 16:27:26Z dburken $
+
+#include "ossimH5Reader.h"
+#include "ossimH5Util.h"
+#include "ossimH5GridModel.h"
+
+#include <ossim/base/ossimConstants.h>
+#include <ossim/base/ossimIpt.h>
+#include <ossim/base/ossimDpt.h>
+#include <ossim/base/ossimEndian.h>
+#include <ossim/base/ossimGpt.h>
+#include <ossim/base/ossimIrect.h>
+#include <ossim/base/ossimFilename.h>
+#include <ossim/base/ossimKeywordlist.h>
+#include <ossim/base/ossimNotify.h>
+#include <ossim/base/ossimProperty.h>
+#include <ossim/base/ossimScalarTypeLut.h>
+#include <ossim/base/ossimString.h>
+#include <ossim/base/ossimStringProperty.h>
+#include <ossim/base/ossimTrace.h>
+
+#include <ossim/imaging/ossimImageDataFactory.h>
+#include <ossim/imaging/ossimImageGeometry.h>
+#include <ossim/imaging/ossimImageGeometryRegistry.h>
+#include <ossim/imaging/ossimTiffTileSource.h>
+#include <ossim/imaging/ossimU8ImageData.h>
+
+#include <ossim/projection/ossimBilinearProjection.h>
+#include <ossim/projection/ossimEquDistCylProjection.h>
+#include <ossim/projection/ossimProjection.h>
+
+//---
+// This includes everything!  Note the H5 includes are order dependent; hence,
+// the mongo include.
+//---
+#include <hdf5.h>
+#include <H5Cpp.h>
+
+RTTI_DEF1(ossimH5Reader, "ossimH5Reader", ossimImageHandler)
+
+#ifdef OSSIM_ID_ENABLED
+   static const char OSSIM_ID[] = "$Id$";
+#endif
+   
+static ossimTrace traceDebug("ossimH5Reader:debug");
+
+static const std::string LAYER_KW = "layer";
+
+ossimH5Reader::ossimH5Reader()
+   :
+      ossimImageHandler(),
+      m_h5File(0),
+      m_entries(),
+      m_currentEntry(0),
+      m_tile(0),
+      m_projection(0),
+      m_mutex()
+{
+   // traceDebug.setTraceFlag(true);
+   
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimH5Reader::ossimH5Reader entered..." << std::endl;
+#ifdef OSSIM_ID_ENABLED
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "OSSIM_ID:  " << OSSIM_ID << endl;
+#endif
+   }
+}
+
+ossimH5Reader::~ossimH5Reader()
+{
+   if (isOpen())
+   {
+      close();
+   }
+}
+
+void ossimH5Reader::allocate()
+{
+   m_mutex.lock();
+   m_tile = ossimImageDataFactory::instance()->create(this, this);
+   m_tile->initialize();
+   m_mutex.unlock();
+}
+
+ossimRefPtr<ossimImageData> ossimH5Reader::getTile(
+   const ossimIrect& rect, ossim_uint32 resLevel)
+{
+   if ( m_tile.valid() == false ) // First time through.
+   {
+      allocate();
+   }
+   
+   if (m_tile.valid())
+   {
+      // Image rectangle must be set prior to calling getTile.
+      m_mutex.lock();
+      m_tile->setImageRectangle(rect);
+      m_mutex.unlock();
+      
+      if ( getTile( m_tile.get(), resLevel ) == false )
+      {
+         m_mutex.lock();
+         if (m_tile->getDataObjectStatus() != OSSIM_NULL)
+         {
+            m_tile->makeBlank();
+         }
+         m_mutex.unlock();
+      }
+   }
+   
+   return m_tile;
+}
+
+bool ossimH5Reader::getTile(ossimImageData* result, ossim_uint32 resLevel)
+{
+   bool status = false;
+
+   m_mutex.lock();
+   
+   //---
+   // Not open, this tile source bypassed, or invalid res level,
+   // return a blank tile.
+   //---
+   if( isOpen() && isSourceEnabled() && isValidRLevel(resLevel) &&
+       result && (result->getNumberOfBands() == getNumberOfOutputBands()) )
+   {
+      result->ref(); // Increment ref count.
+      
+      //---
+      // Check for overview tile.  Some overviews can contain r0 so always
+      // call even if resLevel is 0.  Method returns true on success, false
+      // on error.
+      //---
+      status = getOverviewTile(resLevel, result);
+
+      if (!status) // Did not get an overview tile.
+      {
+         status = true;
+         
+         ossimIrect tile_rect = result->getImageRectangle();
+
+         if ( ! tile_rect.completely_within(getImageRectangle(0)) )
+         {
+            // We won't fill totally so make blank first.
+            result->makeBlank();
+         }
+         
+         if (getImageRectangle(0).intersects(tile_rect))
+         {
+            // Make a clip rect.
+            ossimIrect clipRect = tile_rect.clipToRect(getImageRectangle(0));
+            
+            if (tile_rect.completely_within( clipRect) == false)
+            {
+               // Not filling whole tile so blank it out first.
+               result->makeBlank();
+            }
+
+            // Create buffer to hold the clip rect for a single band.
+            ossim_uint32 clipRectSizeInBytes = clipRect.area() *
+               ossim::scalarSizeInBytes( m_entries[m_currentEntry].getScalarType() );
+            vector<char> dataBuffer(clipRectSizeInBytes);
+
+            // Get the data.
+            for (ossim_uint32 band = 0; band < getNumberOfInputBands(); ++band)
+            {
+               // Hdf5 file to buffer:
+               m_entries[m_currentEntry].getTileBuf(&dataBuffer.front(), clipRect, band);
+
+               if ( m_entries[m_currentEntry].getScalarType() == OSSIM_FLOAT32 )
+               {
+                  //---
+                  // NPP VIIRS data has null of "-999.3".
+                  // Scan and fix non-standard null value.
+                  //---
+                  const ossim_float32 NP = getNullPixelValue(band);
+                  const ossim_uint32 COUNT = clipRect.area();
+                  ossim_float32* float_buffer = (ossim_float32*)&dataBuffer.front();
+                  for ( ossim_uint32 i = 0; i < COUNT; ++i )
+                  {
+                     if ( float_buffer[i] <= -999.0 ) float_buffer[i] = NP;
+                  }
+               }
+
+               // Buffer to tile:
+               result->loadBand((void*)&dataBuffer.front(), clipRect, band);
+            }
+
+            // Validate the tile, i.e. full, partial, empty.
+            result->validate();
+         }
+         else // No intersection...
+         {
+            result->makeBlank();
+         }
+      }
+
+      result->unref();  // Decrement ref count.
+   }
+
+   m_mutex.unlock();
+
+   return status;
+}
+
+ossimIrect
+ossimH5Reader::getImageRectangle(ossim_uint32 reduced_res_level) const
+{
+   return ossimIrect(0,
+                     0,
+                     getNumberOfSamples(reduced_res_level) - 1,
+                     getNumberOfLines(reduced_res_level)   - 1);
+}
+
+bool ossimH5Reader::saveState(ossimKeywordlist& kwl,
+                               const char* prefix) const
+{
+   return ossimImageHandler::saveState(kwl, prefix);
+}
+
+bool ossimH5Reader::loadState(const ossimKeywordlist& kwl,
+                               const char* prefix)
+{
+   if (ossimImageHandler::loadState(kwl, prefix))
+   {
+      return open();
+   }
+
+   return false;
+}
+
+bool ossimH5Reader::open()
+{
+   static const char MODULE[] = "ossimH5Reader::open";
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " entered..."
+         << "File:  " << theImageFile.c_str()
+         << std::endl;
+   }
+
+   bool status = false;
+   
+   // Start with a clean slate.
+   if (isOpen())
+   {
+      close();
+   }
+
+   // Check for empty filename.
+   if (theImageFile.size())
+   {
+      try
+      {
+         //--
+         // Turn off the auto-printing when failure occurs so that we can
+         // handle the errors appropriately
+         //---
+         // H5::Exception::dontPrint();
+
+         theImageFile = theImageFile.expand();
+
+         if ( H5::H5File::isHdf5( theImageFile.c_str() ) )
+         {
+            m_h5File = new H5::H5File();
+
+            H5::FileAccPropList access_plist = H5::FileAccPropList::DEFAULT;
+            
+            m_h5File->openFile( theImageFile.string(), H5F_ACC_RDONLY, access_plist );
+
+            std::vector<std::string> names;
+            ossim_hdf5::getDatasetNames( m_h5File, names );
+
+            if ( names.size() )
+            {
+               if ( traceDebug() )
+               {
+                  ossimNotify(ossimNotifyLevel_DEBUG)
+                     << MODULE << " DEBUG\nDataset names:\n"; 
+                  for ( ossim_uint32 i = 0; i < names.size(); ++i )
+                  {
+                     ossimNotify(ossimNotifyLevel_DEBUG)
+                        << "dataset[" << i << "]: " << names[i] << "\n";
+                  }
+               }
+
+               // Add the image dataset entries.
+               addImageDatasetEntries( names );
+               if ( m_entries.size() )
+               {
+                  // Set the return status.
+                  status = true;
+               }
+               else
+               {
+                  m_h5File->close();
+                  delete m_h5File;
+                  m_h5File = 0;
+               }
+            }
+         }
+         
+      } // End: try block
+      
+      catch( const H5::FileIException& error )
+      {
+         if ( traceDebug() )
+         {
+            error.printError();
+         }
+      }
+      
+      // catch failure caused by the DataSet operations
+      catch( const H5::DataSetIException& error )
+      {
+         if ( traceDebug() )
+         {
+            error.printError();
+         }
+      }
+      
+      // catch failure caused by the DataSpace operations
+      catch( const H5::DataSpaceIException& error )
+      {
+         if ( traceDebug() )
+         {
+            error.printError();
+         }
+      }
+      
+      // catch failure caused by the DataSpace operations
+      catch( const H5::DataTypeIException& error )
+      {
+         if ( traceDebug() )
+         {
+            error.printError();
+         }
+      }
+      catch( ... )
+      {
+         
+      }
+      
+      if ( status )
+      {
+         completeOpen();
+      }
+   }
+
+   return status;
+}
+
+void ossimH5Reader::addImageDatasetEntries(const std::vector<std::string>& names)
+{
+   if ( m_h5File && names.size() )
+   {
+      std::vector<std::string>::const_iterator i = names.begin();
+      while ( i != names.end() )
+      {
+         if ( ossim_hdf5::isExcludedDataset( *i ) == false )
+         {
+            H5::DataSet dataset = m_h5File->openDataSet( *i );
+
+            // Get the class of the datatype that is used by the dataset.
+            H5T_class_t type_class = dataset.getTypeClass();
+            
+            if ( ( type_class == H5T_INTEGER ) || ( type_class == H5T_FLOAT ) )
+            {
+               // Get the extents:
+               std::vector<ossim_uint32> extents;
+               ossim_hdf5::getExtents( &dataset, extents ); 
+
+               if ( extents.size() >= 2 )
+               {
+                  if ( ( extents[0] > 1 ) && ( extents[1] > 1 ) )
+                  {
+                     ossimH5ImageDataset hids;
+                     hids.initialize( dataset, *i );
+                     m_entries.push_back( hids );
+                  }     
+               }
+            }
+
+            dataset.close();
+         }
+            
+         ++i;
+      }
+   }
+   
+#if 0 /* Please leave for debug. (drb) */
+   std::vector<ossimH5ImageDataset>::const_iterator i = m_entries.begin();
+   while ( i != m_entries.end() )
+   {
+      std::cout << (*i) << endl;
+      ++i;
+   }
+#endif
+      
+} // End: ossimH5Reader::addImageDatasetEntries
+
+ossim_uint32 ossimH5Reader::getNumberOfLines(ossim_uint32 reduced_res_level) const
+{
+   ossim_uint32 result = 0;
+   
+   if ( (reduced_res_level == 0) && ( m_currentEntry < m_entries.size() ) )
+   {
+      result = m_entries[m_currentEntry].getNumberOfLines();
+   }
+   else if ( theOverview.valid() )
+   {
+      result = theOverview->getNumberOfLines(reduced_res_level);
+   }
+   
+   return result;
+}
+
+ossim_uint32 ossimH5Reader::getNumberOfSamples(ossim_uint32 reduced_res_level) const
+{
+   ossim_uint32 result = 0;
+   
+   if ( (reduced_res_level == 0) && ( m_currentEntry < m_entries.size() ) )
+   {
+      result = m_entries[m_currentEntry].getNumberOfSamples();
+   }
+   else if ( theOverview.valid() )
+   {
+      result = theOverview->getNumberOfSamples(reduced_res_level);
+   }
+   
+   return result; 
+}
+
+ossim_uint32 ossimH5Reader::getImageTileWidth() const
+{
+   return 0; // Not tiled format.
+}
+
+ossim_uint32 ossimH5Reader::getImageTileHeight() const
+{
+   return 0; // Not tiled format.
+}
+
+ossimString ossimH5Reader::getShortName()const
+{
+   return ossimString("ossim_hdf5_reader");
+}
+   
+ossimString ossimH5Reader::getLongName()const
+{
+   return ossimString("ossim hdf5 reader");
+}
+
+ossimString  ossimH5Reader::getClassName()const
+{
+   return ossimString("ossimH5Reader");
+}
+
+ossim_uint32 ossimH5Reader::getNumberOfInputBands() const
+{
+   ossim_uint32 result = 1;
+
+   if ( m_currentEntry < m_entries.size() )
+   {
+      result = m_entries[m_currentEntry].getNumberOfBands();
+   }
+
+   return result;
+}
+
+ossim_uint32 ossimH5Reader::getNumberOfOutputBands()const
+{
+   // Currently not band selectable.
+   return getNumberOfInputBands();
+}
+
+ossimScalarType ossimH5Reader::getOutputScalarType() const
+{
+   ossimScalarType result = OSSIM_SCALAR_UNKNOWN;
+   
+   if ( m_currentEntry < m_entries.size() )
+   {
+      result = m_entries[m_currentEntry].getScalarType();
+   }
+   
+   return result;
+}
+
+bool ossimH5Reader::isOpen()const
+{
+   return ( ( m_h5File != 0 ) &&
+            m_entries.size() &&
+            ( m_currentEntry < m_entries.size() ) ) ? true : false ;
+}
+
+void ossimH5Reader::close()
+{
+   // Close the datasets.
+   m_entries.clear();
+
+   // Then the file.
+   if ( m_h5File )
+   {
+      m_h5File->close();
+      delete m_h5File;
+      m_h5File = 0;
+   }
+
+   // ossimRefPtr so assign to 0(unreferencing) will handle memory.
+   m_tile = 0;
+   m_projection = 0;
+
+   ossimImageHandler::close();
+}
+
+ossim_uint32 ossimH5Reader::getNumberOfEntries() const
+{
+   return (ossim_uint32)m_entries.size();
+}
+
+void ossimH5Reader::getEntryNames(std::vector<ossimString>& entryNames) const
+{
+   entryNames.clear();
+   for (ossim_uint32 i=0; i<m_entries.size(); ++i )
+   {
+      entryNames.push_back(m_entries[i].getName());
+   }
+}
+
+void ossimH5Reader::getEntryList(std::vector<ossim_uint32>& entryList) const
+{
+   const ossim_uint32 SIZE = m_entries.size();
+   entryList.resize( SIZE );
+   for ( ossim_uint32 i = 0; i < SIZE; ++i )
+   {
+      entryList[i] = i; 
+   }
+}
+
+bool ossimH5Reader::setCurrentEntry( ossim_uint32 entryIdx )
+{
+   bool result = true;
+   if (m_currentEntry != entryIdx)
+   {
+      if ( isOpen() )
+      {
+         // Entries always start at zero and increment sequentially..
+         if ( entryIdx < m_entries.size() )
+         {
+            // Clear the geometry.
+            theGeometry = 0;
+            
+            // Must clear or openOverview will use last entries.
+            theOverviewFile.clear();
+            
+            m_currentEntry = entryIdx;
+            
+            //---
+            // Since we were previously open and the the entry has changed we
+            // need to reinitialize some things. Setting tile to 0 will force an
+            // allocate call on first getTile.
+            //---
+            
+            // ossimRefPtr so assign to 0(unreferencing) will handle memory.
+            m_tile = 0;
+            
+            completeOpen();
+         }
+         else
+         {
+            result = false; // Entry index out of range.
+         }
+      }
+      else
+      {
+         //---
+         // Not open.
+         // Allow this knowing that open will check for out of range.
+         //---
+         m_currentEntry = entryIdx;
+      }
+   }
+
+   return result;
+}
+
+ossim_uint32 ossimH5Reader::getCurrentEntry() const
+{
+   return m_currentEntry;
+}
+
+ossimRefPtr<ossimImageGeometry> ossimH5Reader::getImageGeometry()
+{
+   if ( !theGeometry )
+   {
+      //---
+      // Check for external geom:
+      //---
+      theGeometry = getExternalImageGeometry();
+      
+      if ( !theGeometry )
+      {
+         //---
+         // WARNING:
+         // Must create/set the geometry at this point or the next call to
+         // ossimImageGeometryRegistry::extendGeometry will put us in an infinite loop
+         // as it does a recursive call back to ossimImageHandler::getImageGeometry().
+         //---
+
+         // Check the internal geometry first to avoid a factory call.
+         m_mutex.lock();
+         theGeometry = getInternalImageGeometry();
+         m_mutex.unlock();
+
+         // At this point it is assured theGeometry is set.
+
+         // Check for set projection.
+         if ( !theGeometry->getProjection() )
+         {
+            // Try factories for projection.
+            ossimImageGeometryRegistry::instance()->extendGeometry(this);
+         }
+      }
+
+      // Set image things the geometry object should know about.
+      initImageParameters( theGeometry.get() );
+   }
+
+   return theGeometry;
+}
+
+ossimRefPtr<ossimImageGeometry> ossimH5Reader::getInternalImageGeometry()
+{
+   ossimRefPtr<ossimImageGeometry> geom = new ossimImageGeometry();
+
+   if ( m_projection.valid() )
+   {
+      // Stored projection, currently shared by all entries.
+      geom->setProjection( m_projection.get() );
+   }
+   else if ( isOpen() )
+   {
+      // Find the "Latitude" and "Longitude" datasets if present.
+      std::string latName;
+      std::string lonName;
+      if ( getLatLonDatasetNames(  m_h5File, latName, lonName ) )
+      {
+         H5::DataSet latDataSet = m_h5File->openDataSet( latName );
+         H5::DataSet lonDataSet = m_h5File->openDataSet( lonName );
+
+         // Get the valid rectangle of the dataset.
+         ossimIrect validRect = m_entries[m_currentEntry].getValidImageRect();
+
+         // Try for a coarse projection first:
+         ossimRefPtr<ossimProjection> proj =
+            processCoarseGridProjection( latDataSet,
+                                         lonDataSet,
+                                         validRect );
+         
+         if ( proj.valid() == false )
+         {
+            ossimIrect rect;
+            proj = ossim_hdf5::getBilinearProjection( latDataSet, lonDataSet, validRect );
+         }
+         
+         if ( proj.valid() )
+         {
+            // Store it for next time:
+            m_projection = proj;
+            
+            // Set the geometry projection
+            geom->setProjection( proj.get() ); 
+         }
+               
+         latDataSet.close();
+         lonDataSet.close();
+      }
+   }
+ 
+   return geom;
+}
+
+ossimRefPtr<ossimProjection> ossimH5Reader::processCoarseGridProjection(
+   H5::DataSet& latDataSet,
+   H5::DataSet& lonDataSet,
+   const ossimIrect& validRect ) const
+{
+   ossimRefPtr<ossimProjection> proj = 0;
+
+   ossimRefPtr<ossimH5GridModel> model = new ossimH5GridModel();
+   
+   try
+   {
+      if ( model->setGridNodes( &latDataSet,
+                                &lonDataSet,
+                                validRect ) )
+      {
+         proj = model.get();
+      }
+   }
+   catch ( const ossimException& e )
+   {
+      if ( traceDebug() )
+      {
+         ossimNotify(ossimNotifyLevel_WARN)
+            << "ossimH5Reader::processCoarseGridProjection caught exception\n"
+            << e.what() << std::endl;
+      }
+   }
+
+   return proj;
+}
+
+bool ossimH5Reader::getLatLonDatasetNames( H5::H5File* h5File,
+                                           std::string& latName,
+                                           std::string& lonName ) const
+{
+   bool result = false;
+
+   if ( h5File )
+   {
+      latName.clear();
+      lonName.clear();
+      
+      // Get the list of datasets.
+      std::vector<std::string> datasetNames;
+      ossim_hdf5::getDatasetNames( h5File, datasetNames );
+      
+      if ( datasetNames.size() )
+      {
+         std::vector<std::string>::const_iterator i = datasetNames.begin();
+         while ( i != datasetNames.end() )
+         {
+            ossimString os = *i;
+            if ( os.contains( "Latitude" ) )
+            {
+               latName = *i;
+            }
+            else if ( os.contains( "Longitude" ) )
+            {
+               lonName = *i;
+            }
+            
+            if ( latName.size() && lonName.size() )
+            {
+               result = true;
+               break;
+            }
+            
+            ++i;
+         }
+      }
+   }
+   
+   return result;
+
+} // End: ossimH5Reader::getLatLonDatasetNames
+
+bool ossimH5Reader::getLatLonDatasets( H5::H5File* h5File,
+                                       H5::DataSet& latDataSet,
+                                       H5::DataSet& lonDataSet ) const
+{
+   bool status = false;
+
+   if ( h5File )
+   {
+      std::string latName;
+      std::string lonName;
+      if ( getLatLonDatasetNames( h5File, latName, lonName ) )
+      {
+         // Set the return status:
+         status = true;
+         latDataSet = h5File->openDataSet( latName );
+         lonDataSet = h5File->openDataSet( lonName ); 
+      }
+      else
+      {
+         // Look for the key: /N_GEO_Ref
+         std::string group = "/";
+         std::string key   = "N_GEO_Ref";
+         std::string value;
+            
+         if ( ossim_hdf5::getGroupAttributeValue( h5File, group, key, value ) )
+         {
+            ossimFilename f = value;
+ 	    ossimFilename latLonFile = theImageFile.path();
+            latLonFile = latLonFile.dirCat( f );
+
+            if ( latLonFile.exists() )
+            {
+               if ( H5::H5File::isHdf5( latLonFile.string() ) )
+               {
+                  H5::H5File* h5File = new H5::H5File();
+                  
+                  H5::FileAccPropList access_plist = H5::FileAccPropList::DEFAULT;
+                  h5File->openFile( latLonFile.string(), H5F_ACC_RDONLY, access_plist );
+
+                  if ( getLatLonDatasetNames( h5File, latName, lonName ) )
+                  {
+                     // Set the return status:
+                     status = true;
+                     latDataSet = h5File->openDataSet( latName );
+                     lonDataSet = h5File->openDataSet( lonName ); 
+                  }
+                  h5File->close();
+                  delete h5File;
+                  h5File = 0;
+               }
+            }
+         }
+      }
+   }
+
+   return status;
+   
+} // End: ossimH5Reader::getLatLonDatasets( ... )
+
+bool ossimH5Reader::isNppMission( H5::H5File* h5File ) const
+{
+   bool result = false;
+   
+   // Look for "Mission_Name"
+   const std::string GROUP = "/";
+   const std::string KEY = "Mission_Name";
+   std::string value;
+   
+   if ( ossim_hdf5::getGroupAttributeValue( h5File, GROUP, KEY, value ) )
+   {
+      if ( value == "NPP" )
+      {
+         result = true;
+      }
+   }
+   
+   return result;
+}
+
+double ossimH5Reader::getNullPixelValue( ossim_uint32 band ) const
+{
+   return ossimImageHandler::getNullPixelValue( band );
+#if 0
+   double result;
+   ossimScalarType scalar = getOutputScalarType();
+   if ( scalar == OSSIM_FLOAT32 )
+   {
+      result = -9999.0;
+   }
+   else
+   {
+      result = ossimImageHandler::getNullPixelValue( band );
+   }
+   return result;
+#endif
+}
+
+void ossimH5Reader::setProperty(ossimRefPtr<ossimProperty> property)
+{
+   if ( property.valid() )
+   {
+      if ( property->getName().string() == LAYER_KW )
+      {
+         ossimString s;
+         property->valueToString(s);
+         ossim_uint32 SIZE = (ossim_uint32)m_entries.size();
+         for ( ossim_uint32 i = 0; i < SIZE; ++i )
+         {
+            if ( m_entries[i].getName() == s.string() )
+            {
+               setCurrentEntry( i );
+            }
+         }
+      }
+      else
+      {
+         ossimImageHandler::setProperty(property);
+      }
+   }
+}
+
+ossimRefPtr<ossimProperty> ossimH5Reader::getProperty(const ossimString& name)const
+{
+   ossimRefPtr<ossimProperty> prop = 0;
+   if ( name.string() == LAYER_KW )
+   {
+      if ( m_currentEntry < m_entries.size() )
+      {
+         ossimString value = m_entries[m_currentEntry].getName();
+         prop = new ossimStringProperty(name, value);
+      }
+   }
+   else
+   {
+      prop = ossimImageHandler::getProperty(name);
+   }
+   return prop;
+}
+
+void ossimH5Reader::getPropertyNames(std::vector<ossimString>& propertyNames)const
+{
+   propertyNames.push_back( ossimString("layer") );
+   ossimImageHandler::getPropertyNames(propertyNames);
+}
+
+
+void ossimH5Reader::addMetadata( ossimKeywordlist* kwl, const std::string& prefix ) const
+{
+   // Note: hdf5 library throws exception if groupd is not found:
+   
+   if ( kwl && m_h5File )
+   {
+      // Look for country code(s): hdf5.CountryCodes: CA,MX,US
+      std::string group = "/";
+      std::string key = "CountryCodes";
+      std::string value;
+
+      if ( ossim_hdf5::getGroupAttributeValue( m_h5File, group, key, value ) )
+      {
+         key = "country_code";
+         kwl->addPair( prefix, key, value );
+      }
+
+      // Look for mission id: hdf5.Mission_Name: NPP
+      key = "Mission_Name";
+      if ( ossim_hdf5::getGroupAttributeValue( m_h5File, group, key, value ) )
+      {
+         key = "mission_id";
+         kwl->addPair( prefix, key, value );
+      }
+         
+
+      //---
+      // Look for sensor type:
+      // hdf5.Data_Products.VIIRS-DNB-SDR.Instrument_Short_Name: VIIRS
+      //---
+      group = "/Data_Products/VIIRS-DNB-SDR";
+      key = "Instrument_Short_Name";
+      if ( ossim_hdf5::getGroupAttributeValue( m_h5File, group, key, value ) )
+      {
+         key = "sensor_id";
+         kwl->addPair( prefix, key, value );
+      }
+      
+      //---
+      // Look for acquisition date:
+      // hdf5.Data_Products.VIIRS-DNB-SDR.VIIRS-DNB-SDR_Aggr.AggregateBeginningDate: 20140113
+      // hdf5.Data_Products.VIIRS-DNB-SDR.VIIRS-DNB-SDR_Aggr.AggregateBeginningTime: 082810.354645Z
+      //---
+      group = "Data_Products/VIIRS-DNB-SDR/VIIRS-DNB-SDR_Aggr";
+      key = "AggregateBeginningDate";
+      if ( ossim_hdf5::getDatasetAttributeValue( m_h5File, group, key, value ) )
+      {
+         std::string time;
+         key = "AggregateBeginningTime";
+         if ( ossim_hdf5::getDatasetAttributeValue( m_h5File, group, key, time ) )
+         {
+            // Only grab yyyymmddmmss in the form ISO 8601: 2014-01-26T10:32:28Z
+            if ( (value.size() >= 8) && ( time.size() >= 6 ) )
+            {
+               std::string dateTime =
+                  ossimString( ossimString(value.begin(), value.begin() + 4) + "-"
+                               + ossimString(value.begin() + 4, value.begin() + 6) + "-"
+                               + ossimString(value.begin() + 6, value.begin() + 8) + "T"
+                               + ossimString(time.begin(), time.begin() + 2) + ":"
+                               + ossimString(time.begin() + 2, time.begin() + 4) + ":"
+                               + ossimString(time.begin() + 4, time.begin() + 6) + "Z" ).string();
+               key = "acquisition_date";
+               kwl->addPair( prefix, key, dateTime );
+            }
+         }
+      }
+   }
+}
+
diff --git a/ossim_plugins/hdf5/ossimH5Reader.h b/ossim_plugins/hdf5/ossimH5Reader.h
new file mode 100644
index 0000000..fb09308
--- /dev/null
+++ b/ossim_plugins/hdf5/ossimH5Reader.h
@@ -0,0 +1,300 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author:  David Burken
+//
+// Description: OSSIM HDF5 Reader.
+//
+//----------------------------------------------------------------------------
+// $Id
+
+#ifndef ossimH5Reader_HEADER
+#define ossimH5Reader_HEADER 1
+
+#include "../ossimPluginConstants.h"
+#include <ossim/base/ossimIrect.h>
+#include <ossim/base/ossimRefPtr.h>
+#include <ossim/base/ossimMetadataInterface.h>
+#include <ossim/imaging/ossimImageData.h>
+#include <ossim/imaging/ossimImageHandler.h>
+#include "ossimH5ImageDataset.h"
+
+#include <OpenThreads/Mutex>
+
+#include <vector>
+
+// Forward class declarations:
+namespace H5
+{
+   class DataSet;
+   class H5File;
+}
+
+class OSSIM_PLUGINS_DLL ossimH5Reader : public ossimImageHandler, public ossimMetadataInterface
+{
+public:
+
+   /** default constructor */
+   ossimH5Reader();
+
+   /** virtual destructor */
+   virtual ~ossimH5Reader();
+
+   /** @return "hdf5" */
+   virtual ossimString getShortName() const;
+
+   /** @return "ossim hdf5" */
+   virtual ossimString getLongName()  const;
+
+   /** @return "ossimH5Reader" */
+   virtual ossimString getClassName()    const;
+
+   /**
+    *  Returns a pointer to a tile given an origin representing the upper
+    *  left corner of the tile to grab from the image.
+    *  Satisfies pure virtual from TileSource class.
+    */
+   virtual ossimRefPtr<ossimImageData> getTile(const  ossimIrect& rect,
+                                               ossim_uint32 resLevel=0);
+   /**
+    * Method to get a tile.   
+    *
+    * @param result The tile to stuff.  Note The requested rectangle in full
+    * image space and bands should be set in the result tile prior to
+    * passing.  It will be an error if:
+    * result.getNumberOfBands() != this->getNumberOfOutputBands()
+    *
+    * @return true on success false on error.  If return is false, result
+    *  is undefined so caller should handle appropriately with makeBlank or
+    * whatever.
+    */
+   virtual bool getTile(ossimImageData* result, ossim_uint32 resLevel=0);
+
+    /**
+     *  Returns the number of bands in the image.
+     *  Satisfies pure virtual from ImageHandler class.
+     */
+   virtual ossim_uint32 getNumberOfInputBands() const;
+
+   /**
+    * Returns the number of bands in a tile returned from this TileSource.
+    * Note: we are supporting sources that can have multiple data objects.
+    * If you want to know the scalar type of an object you can pass in the
+    */
+   virtual ossim_uint32 getNumberOfOutputBands()const;
+
+   /**
+     *  Returns the number of lines in the image.
+     *  Satisfies pure virtual from ImageHandler class.
+     */
+   virtual ossim_uint32 getNumberOfLines(ossim_uint32 reduced_res_level = 0) const;
+
+   /**
+    *  Returns the number of samples in the image.
+    *  Satisfies pure virtual from ImageHandler class.
+    */
+   virtual ossim_uint32 getNumberOfSamples(ossim_uint32 reduced_res_level = 0) const;
+
+   /**
+    * Returns the zero based image rectangle for the reduced resolution data
+    * set (rrds) passed in.  Note that rrds 0 is the highest resolution rrds.
+    */
+   virtual ossimIrect getImageRectangle(ossim_uint32 reduced_res_level = 0) const;
+
+   /**
+    * Method to save the state of an object to a keyword list.
+    * Return true if ok or false on error.
+    */
+   virtual bool saveState(ossimKeywordlist& kwl,
+                          const char* prefix=0)const;
+
+   /**
+    * Method to the load (recreate) the state of an object from a keyword
+    * list.  Return true if ok or false on error.
+    */
+   virtual bool loadState(const ossimKeywordlist& kwl,
+                          const char* prefix=0);
+
+   /**
+    * Returns the output pixel type of the tile source.
+    */
+   virtual ossimScalarType getOutputScalarType() const;
+
+   /**
+    * Returns the tile width of the image or 0 if the image is not tiled.
+    * Note: this is not the same as the ossimImageSource::getTileWidth which
+    * returns the output tile width which can be different than the internal
+    * image tile width on disk.
+    */
+   virtual ossim_uint32 getImageTileWidth() const;
+
+   /**
+    * Returns the tile width of the image or 0 if the image is not tiled.
+    * Note: this is not the same as the ossimImageSource::getTileWidth which
+    * returns the output tile width which can be different than the internal
+    * image tile width on disk.
+    */
+   virtual ossim_uint32 getImageTileHeight() const;
+
+   bool isOpen()const;
+
+   /** Close method. */
+   virtual void close();
+
+   /**
+    * @return The number of entries (images) in the image file.
+    */
+   virtual ossim_uint32 getNumberOfEntries()const;
+
+   /**
+    * @brief Get the name of entry as a string.
+    *
+    * Example given from HDF5 file:
+    * 
+    * entry_name: /All_Data/VIIRS-IMG-GTM-EDR-GEO_All/QF1_VIIRSGTMGEO
+    *
+    * @param entryIdx Zero based entry index. If out of range name will
+    * be cleared.
+    * 
+    * @param name Initialized by this.
+    */
+   virtual void getEntryNames(std::vector<ossimString>& entryNames) const;
+
+   /**
+    * @param entryList This is the list to initialize with entry indexes.
+    *
+    * @note This implementation returns puts one entry "0" in the list.
+    */
+   virtual void getEntryList(std::vector<ossim_uint32>& entryList) const;
+
+   virtual bool setCurrentEntry(ossim_uint32 entryIdx);
+
+   /**
+    * @return The current entry number.
+    */
+   virtual ossim_uint32 getCurrentEntry() const;
+
+   /**
+    * Returns the image geometry object associated with this tile source or
+    * NULL if non defined.  The geometry contains full-to-local image
+    * transform as well as projection (image-to-world).
+    */
+   virtual ossimRefPtr<ossimImageGeometry> getImageGeometry();
+
+   /** @return Null pixel value. */
+   virtual double getNullPixelValue(ossim_uint32 band=0)const;
+
+   /**
+    * @brief Set propterty method. Overrides ossimImageHandler::setProperty.
+    *
+    * Current property name handled:
+    * "scale" One double value representing the scale in meters per pixel. It is
+    * assumed the scale is same for x and y direction.
+    * 
+    * @param property to set.
+    */
+   virtual void setProperty(ossimRefPtr<ossimProperty> property);
+
+   /**
+     * @brief Get propterty method. Overrides ossimImageHandler::getProperty.
+    * @param name Property name to get.
+    */
+   virtual ossimRefPtr<ossimProperty> getProperty(const ossimString& name) const;
+
+   /**
+    * @brief Get propterty names. Overrides ossimImageHandler::getPropertyNames.
+    * @param propertyNames Array to initialize.
+    */
+   virtual void getPropertyNames(std::vector<ossimString>& propertyNames) const;
+
+   /**
+    * @brief Adds metadata to keyword list.
+    *
+    * This will add metadata to keyword list if found.  Implemented to pass
+    * specific data to keyword list if found, e.g. acquisition_date, sensor_id,
+    * country_code
+    *
+    * Satisfies pure virtual ossimMetadataInterface::addMetadata(...)
+    * 
+    * @param kwl Initialized by this.
+    * @param prefix e.g. "image0." (can be empty)
+    */
+   virtual void addMetadata( ossimKeywordlist* kwl,
+                             const std::string& prefix ) const;
+
+protected:
+
+   /** @brief Method to get geometry from hdf file. */
+   virtual ossimRefPtr<ossimImageGeometry> getInternalImageGeometry();
+
+   /**
+    * @brief Gets projection from Latitude, Longitude, Height datasets if
+    * present.
+    *
+    * @param latDataSet H5::DataSet& to layer,
+    *    e.g. /All_Data/VIIRS-DNB-GEO_All/Latitude
+    * @param lonDataSet H5::DataSet& to layer,
+    *    e.g. /All_Data/VIIRS-DNB-GEO_All/Longitude
+    */
+   ossimRefPtr<ossimProjection> processCoarseGridProjection(
+      H5::DataSet& latDataSet,
+      H5::DataSet& lonDataSet,
+      const ossimIrect& validRect ) const;
+
+   /**
+    * @brief Get dataset names for Latiitude and Longitude datasets.
+    * @param h5File Pointer to file.
+    * @param latName Initializes by this.
+    * @param lonName Initializes by this.
+    * @return true on sucess, false on error.
+    */
+   bool getLatLonDatasetNames(  H5::H5File* h5File,
+                                std::string& latName,
+                                std::string& lonName ) const;
+   /**
+    * @param Initializes lat and lon data sets.
+    * @param h5File Pointer to file.
+    * @param latDataSet Initialized by this.
+    * @param lonDataSet Initialized by this.
+    */
+   bool getLatLonDatasets( H5::H5File* h5File,
+                           H5::DataSet& latDataSet,
+                           H5::DataSet& lonDataSet ) const; 
+   
+   bool getDataSetRect( std::string& name, std::string& lonName ) const;
+   
+  /**
+    *  @brief open method.
+    *  @return true on success, false on error.
+    */
+   virtual bool open();
+
+   /** @brief Allocates the tile. */ 
+   void allocate();
+
+   /**
+    * @brief Adds image datasets from list of names.
+    * @param names List of dataset paths from hdf5 file.
+    */
+   void addImageDatasetEntries(const std::vector<std::string>& names);
+
+   /**
+    * @return true if key "Mission_Name" is equal to NPP.
+    */
+   bool isNppMission( H5::H5File* h5File ) const;
+   
+   H5::H5File*                      m_h5File;
+   std::vector<ossimH5ImageDataset> m_entries;
+   ossim_uint32                     m_currentEntry;
+   ossimRefPtr<ossimImageData>      m_tile;
+   ossimRefPtr<ossimProjection>     m_projection;
+   OpenThreads::Mutex               m_mutex;
+   
+TYPE_DATA
+};
+
+#endif /* #ifndef ossimH5Reader_HEADER */
+
diff --git a/ossim_plugins/hdf5/ossimH5ReaderFactory.cpp b/ossim_plugins/hdf5/ossimH5ReaderFactory.cpp
new file mode 100644
index 0000000..44ebb19
--- /dev/null
+++ b/ossim_plugins/hdf5/ossimH5ReaderFactory.cpp
@@ -0,0 +1,160 @@
+//----------------------------------------------------------------------------
+//
+// License:  See top level LICENSE.txt file
+//
+// Author: David Burken
+//
+// Copied from Mingjie Su's ossimHdfReaderFactory.
+//
+// Description: Factory for OSSIM HDF5 reader using HDF5 libraries.
+//----------------------------------------------------------------------------
+// $Id: ossimH5ReaderFactory.cpp 2645 2011-05-26 15:21:34Z oscar.kramer $
+
+#include "ossimH5ReaderFactory.h"
+#include <ossim/base/ossimKeywordlist.h>
+#include <ossim/base/ossimRefPtr.h>
+#include <ossim/base/ossimString.h>
+#include <ossim/base/ossimTrace.h>
+#include <ossim/imaging/ossimImageHandler.h>
+#include "ossimH5Reader.h"
+
+static const ossimTrace traceDebug("ossimH5ReaderFactory:debug");
+
+class ossimImageHandler;
+
+RTTI_DEF1(ossimH5ReaderFactory,
+          "ossimH5ReaderFactory",
+          ossimImageHandlerFactoryBase);
+
+ossimH5ReaderFactory* ossimH5ReaderFactory::theInstance = 0;
+
+ossimH5ReaderFactory::~ossimH5ReaderFactory()
+{
+   theInstance = 0;
+}
+
+ossimH5ReaderFactory* ossimH5ReaderFactory::instance()
+{
+   if(!theInstance)
+   {
+      theInstance = new ossimH5ReaderFactory;
+   }
+   return theInstance;
+}
+
+ossimImageHandler* ossimH5ReaderFactory::open(const ossimFilename& fileName,
+                                              bool openOverview)const
+{
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimH5ReaderFactory::open(filename) DEBUG: entered..."
+         << "\ntrying ossimH5Reader"
+         << std::endl;
+   }
+
+   ossimRefPtr<ossimImageHandler> reader = 0;
+
+   if ( hasExcludedExtension(fileName) == false )
+   {
+      if (reader == 0) //try hdf5 reader
+      {
+         // cout << "Calling ossimH5Reader ***********************" << endl;
+         reader = new ossimH5Reader;
+         reader->setOpenOverviewFlag(openOverview);
+         if(reader->open(fileName) == false)
+         {
+            reader = 0;
+         }
+      }
+   }
+
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimH5ReaderFactory::open(filename) DEBUG: leaving..."
+         << std::endl;
+   }
+
+   return reader.release();
+}
+
+ossimImageHandler* ossimH5ReaderFactory::open(const ossimKeywordlist& kwl,
+                                              const char* prefix)const
+{
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimH5ReaderFactory::open(kwl, prefix) DEBUG: entered..."
+         << "Trying ossimKakaduNitfReader"
+         << std::endl;
+   }
+
+   ossimRefPtr<ossimImageHandler> reader = new ossimH5Reader;
+   if(reader->loadState(kwl, prefix) == false)
+   {
+      reader = 0;
+   }
+
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimH5ReaderFactory::open(kwl, prefix) DEBUG: leaving..."
+         << std::endl;
+   }
+
+   return reader.release();
+}
+
+ossimObject* ossimH5ReaderFactory::createObject(
+   const ossimString& typeName)const
+{
+   ossimRefPtr<ossimObject> result = 0;
+   if(typeName == "ossimH5Reader")
+   {
+      result = new ossimH5Reader;
+   }
+
+   return result.release();
+}
+
+ossimObject* ossimH5ReaderFactory::createObject(
+   const ossimKeywordlist& kwl,
+   const char* prefix)const
+{
+   return this->open(kwl, prefix);
+}
+
+void ossimH5ReaderFactory::getTypeNameList(
+   std::vector<ossimString>& typeList)const
+{
+   typeList.push_back(ossimString("ossimH5Reader"));
+}
+
+void ossimH5ReaderFactory::getSupportedExtensions(
+   ossimImageHandlerFactoryBase::UniqueStringList& extensionList)const
+{
+   extensionList.push_back(ossimString("h5"));
+   extensionList.push_back(ossimString("he5"));
+   extensionList.push_back(ossimString("hdf5"));   
+}
+
+bool ossimH5ReaderFactory::hasExcludedExtension(
+   const ossimFilename& file) const
+{
+   bool result = true;
+   ossimString ext = file.ext().downcase();
+   //only include the file with those extension and exclude any other files
+   if ( (ext == "h5") || (ext == "hdf5") || (ext == "he5") )
+   {
+      result = false;
+   }
+   return result;
+}
+
+ossimH5ReaderFactory::ossimH5ReaderFactory(){}
+
+ossimH5ReaderFactory::ossimH5ReaderFactory(const ossimH5ReaderFactory&){}
+
+void ossimH5ReaderFactory::operator=(const ossimH5ReaderFactory&){}
+
diff --git a/ossim_plugins/hdf5/ossimH5ReaderFactory.h b/ossim_plugins/hdf5/ossimH5ReaderFactory.h
new file mode 100644
index 0000000..02b0627
--- /dev/null
+++ b/ossim_plugins/hdf5/ossimH5ReaderFactory.h
@@ -0,0 +1,112 @@
+//----------------------------------------------------------------------------
+//
+// License:  See top level LICENSE.txt file
+//
+// Author: David Burken
+//
+// Copied from Mingjie Su's ossimHdfReaderFactory.
+//
+// Description: Factory for OSSIM HDF reader using HDF5 libraries.
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef ossimH5ReaderFactory_HEADER
+#define ossimH5ReaderFactory_HEADER 1
+
+#include <ossim/imaging/ossimImageHandlerFactoryBase.h>
+
+class ossimString;
+class ossimFilename;
+class ossimKeywordlist;
+
+/** @brief Factory for Hdf image reader. */
+class ossimH5ReaderFactory : public ossimImageHandlerFactoryBase
+{
+public:
+
+   /** @brief virtual destructor */
+   virtual ~ossimH5ReaderFactory();
+
+   /**
+    * @brief static method to return instance (the only one) of this class.
+    * @return pointer to instance of this class.
+    */
+   static ossimH5ReaderFactory* instance();
+
+   /**
+    * @brief open that takes a file name.
+    * @param file The file to open.
+    * @param openOverview If true image handler will attempt to open overview.
+    * default = true 
+    * @return pointer to image handler on success, NULL on failure.
+    */
+   virtual ossimImageHandler* open(const ossimFilename& fileName,
+                                   bool openOverview=true) const;
+
+   /**
+    * @brief open that takes a keyword list and prefix.
+    * @param kwl The keyword list.
+    * @param prefix the keyword list prefix.
+    * @return pointer to image handler on success, NULL on failure.
+    */
+   virtual ossimImageHandler* open(const ossimKeywordlist& kwl,
+                                   const char* prefix=0)const;
+
+   /**
+    * @brief createObject that takes a class name (ossimH5Reader)
+    * @param typeName Should be "ossimH5Reader".
+    * @return pointer to image writer on success, NULL on failure.
+    */
+   virtual ossimObject* createObject(const ossimString& typeName)const;
+   
+   /**
+    * @brief Creates and object given a keyword list and prefix.
+    * @param kwl The keyword list.
+    * @param prefix the keyword list prefix.
+    * @return pointer to image handler on success, NULL on failure.
+    */
+   virtual ossimObject* createObject(const ossimKeywordlist& kwl,
+                                     const char* prefix=0)const;
+   
+   /**
+    * @brief Adds ossimH5Reader to the typeList.
+    * @param typeList List to add to.
+    */
+   virtual void getTypeNameList(std::vector<ossimString>& typeList)const;
+
+   /**
+    * @brief Method to add supported extension to the list, like "hdf".
+    *
+    * @param extensionList The list to add to.
+    */
+   virtual void getSupportedExtensions(
+      ossimImageHandlerFactoryBase::UniqueStringList& extensionList)const;
+  
+protected:
+
+   /**
+    * @brief Method to weed out extensions that this plugin knows it does
+    * not support.  This is to avoid a costly open on say a tiff or jpeg that
+    * is not handled by this plugin.
+    *
+    * @return true if extension, false if not.
+    */
+   bool hasExcludedExtension(const ossimFilename& file) const;
+   
+   /** @brief hidden from use default constructor */
+   ossimH5ReaderFactory();
+
+   /** @brief hidden from use copy constructor */
+   ossimH5ReaderFactory(const ossimH5ReaderFactory&);
+
+   /** @brief hidden from use copy constructor */
+   void operator=(const ossimH5ReaderFactory&);
+
+   /** static instance of this class */
+   static ossimH5ReaderFactory* theInstance;
+
+TYPE_DATA
+};
+
+#endif /* end of #ifndef ossimH5ReaderFactory_HEADER */
+
diff --git a/ossim_plugins/hdf5/ossimH5Util.cpp b/ossim_plugins/hdf5/ossimH5Util.cpp
new file mode 100644
index 0000000..b5e9424
--- /dev/null
+++ b/ossim_plugins/hdf5/ossimH5Util.cpp
@@ -0,0 +1,1507 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author:  David Burken
+//
+// Description: OSSIM HDF5 utility class.
+//
+//----------------------------------------------------------------------------
+// $Id
+
+#include <ossimH5Util.h>
+#include <ossim/base/ossimCommon.h>
+#include <ossim/base/ossimEndian.h>
+#include <ossim/base/ossimIrect.h>
+#include <ossim/base/ossimKeywordNames.h>
+#include <ossim/base/ossimNotify.h>
+#include <ossim/base/ossimScalarTypeLut.h>
+#include <ossim/base/ossimTrace.h>
+#include <ossim/projection/ossimBilinearProjection.h>
+
+//---
+// This includes everything!  Note the H5 includes are order dependent; hence,
+// the mongo include.
+//---
+#include <hdf5.h>
+#include <H5Cpp.h>
+
+#include <iomanip> /* tmp */
+#include <iostream> /* tmp */
+#include <ostream>
+using namespace std;
+
+static ossimTrace traceDebug("ossimH5Util:debug");
+
+std::ostream& ossim_hdf5::print(H5::H5File* file, std::ostream& out)
+{
+   if ( file )
+   {
+      std::string groupName     = "/";
+      std::string prefix        = "hdf5";
+      ossim_uint32 recurseCount = 0;
+      
+      ossim_hdf5::printIterative( file, groupName, prefix, recurseCount, out );
+   }
+
+   return out;
+}
+
+void ossim_hdf5::printIterative( H5::H5File* file,
+                                 const std::string& groupName,
+                                 const std::string& prefix,
+                                 ossim_uint32& recursedCount,
+                                 std::ostream& out )
+{
+   if ( file && groupName.size() )
+   {
+      ++recursedCount;
+      
+      H5::Group* group = new H5::Group( file->openGroup(groupName) );
+
+      // Print attributes:
+      const ossim_uint32 ATTRS_COUNT = group->getNumAttrs();
+      for ( ossim_uint32 aIdx = 0; aIdx < ATTRS_COUNT; ++aIdx )
+      {
+         H5::Attribute attr( group->openAttribute( aIdx ) );
+         ossim_hdf5::printAttribute( attr, prefix, out );
+         attr.close();
+      }
+      
+      const hsize_t OBJ_COUNT = group->getNumObjs();
+      for ( hsize_t i = 0; i < OBJ_COUNT; ++i )
+      {
+         std::string objName = group->getObjnameByIdx(i);
+
+         if ( objName.size() )
+         {
+            char separator = '/';
+            std::string combinedName;
+            combine( groupName, objName, separator, combinedName );
+            
+            separator = '.';
+            std::string combinedPrefix;
+            combine( prefix, objName, separator, combinedPrefix );
+            
+            H5G_obj_t objType   = group->getObjTypeByIdx(i);
+
+#if 0
+            std::cout << "combinedName: " << combinedName
+                      << "\ncombinedPrefix: " << combinedPrefix
+                      << "\ngetObjnameByIdx[" << i << "]: " << objName
+                      << "\ngetObjTypeByIdx[" << i << "]: " << objType
+                      << std::endl;
+#endif
+            
+            if ( objType == H5G_GROUP )
+            {
+               // Recursive call:
+               if ( recursedCount < ossim_hdf5::MAX_RECURSION_LEVEL )
+               {
+                  ossim_hdf5::printIterative(
+                     file, combinedName, combinedPrefix, recursedCount, out );
+               }
+               else
+               {
+                  ossimNotify(ossimNotifyLevel_WARN)
+                     << "ossim_hdf5::printIterative WARNING!"
+                     << "\nMax iterations reached!" << std::endl;
+               }
+            }
+            else if ( objType == H5G_DATASET )
+            {
+               printObject( file, combinedName, combinedPrefix, out );
+            }
+            else
+            {
+               ossimNotify(ossimNotifyLevel_WARN)
+                  << "ossim_hdf5::printIterative WARNING!"
+                  << "\nUnhandled object type: " << objType << std::endl;
+            }
+         }
+      }
+      
+      group->close();
+      delete group;
+      group = 0;
+      --recursedCount;
+      
+   } // Matches: if ( file )
+   
+} // End: void ossim_hdf5::printIterative method.
+
+void ossim_hdf5::printObject(  H5::H5File* file,
+                               const std::string& objectName,
+                               const std::string& prefix,
+                               std::ostream& out )
+{
+#if 0
+   std::cout << "printObject entered..."
+             << "\nobjectName: " << objectName
+             << "\nprefix: " << prefix
+             << std::endl;
+#endif
+   
+   H5::DataSet dataset = file->openDataSet( objectName );
+   
+   // Get the class of the datatype that is used by the dataset.
+   H5T_class_t type_class = dataset.getTypeClass();
+   out << prefix << ".class_type: "
+       << ossim_hdf5::getDatatypeClassType( type_class ) << std::endl;
+
+   const ossim_uint32 ATTRS_COUNT = dataset.getNumAttrs();
+   for ( ossim_uint32 aIdx = 0; aIdx < ATTRS_COUNT; ++aIdx )
+   {
+      H5::Attribute attr = dataset.openAttribute( aIdx );
+      ossim_hdf5::printAttribute( attr, prefix, out );
+      attr.close();
+   }
+
+   // Extents:
+   std::vector<ossim_uint32> extents;
+   ossim_hdf5::getExtents( &dataset, extents );
+   for ( ossim_uint32 i = 0; i < extents.size(); ++i )
+   {
+      ossimString os;
+      std::string exStr = ".extent";
+      exStr += os.toString(i).string();
+      out << prefix << exStr << ": " << extents[i] << std::endl;
+   }
+
+   // ossimScalarType scalar = getScalarType( type_class, dataset.getId() );
+   ossimScalarType scalar = ossim_hdf5::getScalarType( dataset.getId() );
+   if ( scalar != OSSIM_SCALAR_UNKNOWN)
+   {
+      out << prefix << "." << ossimKeywordNames::SCALAR_TYPE_KW << ": "
+          << ossimScalarTypeLut::instance()->getEntryString( scalar ) << std::endl;
+
+      if ( ossim::scalarSizeInBytes( scalar ) > 1 )
+      {
+         ossimByteOrder byteOrder = ossim_hdf5::getByteOrder( &dataset );
+         std::string byteOrderString = "little_endian";
+         if ( byteOrder == OSSIM_BIG_ENDIAN )
+         {
+            byteOrderString = "big_endian";
+         }
+         out << prefix << "." <<ossimKeywordNames::BYTE_ORDER_KW << ": "
+             << byteOrderString << std::endl;
+      }
+   }
+
+#if 0
+   // Attributes:
+   int numberOfAttrs = dataset.getNumAttrs();
+   cout << "numberOfAttrs: " << numberOfAttrs << endl;
+   for ( ossim_int32 attrIdx = 0; attrIdx < numberOfAttrs; ++attrIdx )
+   {
+      H5::Attribute attribute = dataset.openAttribute( attrIdx );
+      cout << "attribute.from class: " << attribute.fromClass() << endl;
+   }
+#endif
+   dataset.close();
+   
+} // End: printObject
+
+bool ossim_hdf5::getGroupAttributeValue( H5::H5File* file,
+                                         const std::string& group,
+                                         const std::string& key,
+                                         std::string& value )
+{
+   static const char MODULE[] = "ossim_hdf5::getGroupAttributeValue";
+   
+   bool result = false;
+   
+   if (  file )
+   {
+      try // HDF5 library throws exceptions so wrap with try{}catch...
+      {
+         // Open the root group:
+         H5::Group* h5Group = new H5::Group( file->openGroup( group ) );
+         
+         // Lookw for key:
+         H5::Attribute attr      = h5Group->openAttribute( key );
+         std::string   name      = attr.getName();
+         H5::DataType  type      = attr.getDataType();
+         H5T_class_t   typeClass = attr.getTypeClass();
+         
+         if ( ( name == key ) && ( typeClass == H5T_STRING ) )
+         {
+            attr.read( type, value );
+            result = true;
+         }
+
+         // Cleanup:
+         attr.close();
+         h5Group->close();
+         delete h5Group;
+         h5Group = 0;
+      }
+      catch( const H5::Exception& e )
+      {
+         if (traceDebug())
+         {
+            ossimNotify(ossimNotifyLevel_WARN)
+               << MODULE << " WARNING: Caught exception!\n"
+               << e.getDetailMsg() << std::endl;
+         }
+      }
+      catch( ... )
+      {
+         ossimNotify(ossimNotifyLevel_WARN)
+            << MODULE << " WARNING: Caught unknown exception!" << std::endl;
+      }      
+   }
+
+   return result;
+   
+} // End: ossim_hdf5::getGroupAttributeValue
+
+bool ossim_hdf5::getDatasetAttributeValue( H5::H5File* file,
+                                           const std::string& objectName,
+                                           const std::string& key,
+                                           std::string& value )
+{
+   static const char MODULE[] = "ossim_hdf5::getDatasetAttributeValue";
+
+   bool result = false;
+   
+   if (  file )
+   {
+      try // HDF5 library throws exceptions so wrap with try{}catch...
+      {
+         // Open the dataset:
+         H5::DataSet dataset = file->openDataSet( objectName );
+         
+         // Lookw for key:
+         H5::Attribute attr = dataset.openAttribute( key );
+
+         std::string  name = attr.getName();
+         H5::DataType type = attr.getDataType();
+         H5T_class_t  typeClass = attr.getTypeClass();
+         
+         if ( ( name == key ) && ( typeClass == H5T_STRING ) )
+         {
+            attr.read( type, value );
+            result = true;
+         }
+
+         // Cleanup:
+         attr.close();
+         dataset.close();
+      }
+      catch( const H5::Exception& e )
+      {
+         ossimNotify(ossimNotifyLevel_WARN)
+            << MODULE << " WARNING: Caught exception!\n"
+            << e.getDetailMsg() << std::endl;
+      }
+      catch( ... )
+      {
+         ossimNotify(ossimNotifyLevel_WARN)
+            << MODULE << " WARNING: Caught unknown exception!" << std::endl;
+      }      
+   }
+
+   return result;
+   
+} // End: ossim_hdf5::getDatasetAttributeValue
+
+void ossim_hdf5::printAttribute( const H5::Attribute& attr,
+                                 const std::string& prefix,
+                                 std::ostream& out )
+{
+   std::string  name      = attr.getName();
+   H5::DataType type      = attr.getDataType();
+   H5T_class_t  typeClass = attr.getTypeClass();
+   size_t       size      = type.getSize();
+   
+   std::string  value; // Initialized below.
+
+   if ( ( typeClass == H5T_INTEGER ) || ( typeClass == H5T_FLOAT ) )
+   {
+      H5::IntType intType = attr.getIntType();
+
+      ossimScalarType scalar = ossim_hdf5::getScalarType( intType.getId() );
+      
+      ossimByteOrder order = ossim_hdf5::getByteOrder( &attr );
+      ossimEndian* endian = 0;
+      if ( ( size > 1 ) && ( order != ossim::byteOrder() ) )
+      {
+         endian = new ossimEndian(); // If set used as flag to byte swap.
+      }
+      
+      if ( typeClass == H5T_INTEGER )
+      {
+         switch ( scalar )
+         {
+            case OSSIM_UINT8:
+            {
+               if ( size == 1 )
+               {
+                  ossim_uint8 i;
+                  attr.read( type, (void*)&i );
+                  value = ossimString::toString( ossim_int32(i) ).string();
+               }
+               break;
+            }
+            case OSSIM_SINT8:
+            {
+               if ( size == 1 )
+               {
+                  ossim_sint8 i;
+                  attr.read( type, (void*)&i );
+                  value = ossimString::toString( ossim_int32(i) ).string();
+               }
+               break;
+            }
+            case OSSIM_UINT16:            
+            {
+               if ( size == 2 )
+               {
+                  ossim_uint16 i;
+                  attr.read( type, (void*)&i );
+                  if ( endian )
+                  {
+                     endian->swap( i );
+                  }  
+                  value = ossimString::toString( i ).string();
+               }
+               break;
+            }
+            case OSSIM_SINT16:
+            {
+               if ( size == 2 )
+               {
+                  ossim_sint16 i;
+                  attr.read( type, (void*)&i );
+                  if ( endian )
+                  {
+                     endian->swap( i );
+                  }
+                  value = ossimString::toString( i ).string();
+               }
+               break;
+            }
+            case OSSIM_UINT32:        
+            {
+               if ( size == 4 )
+               {
+                  ossim_uint32 i;
+                  attr.read( type, (void*)&i );
+                  if ( endian )
+                  {
+                     endian->swap( i );
+                  }  
+                  value = ossimString::toString( i ).string();
+               }
+               break;
+            }
+            case OSSIM_SINT32:
+            {
+               if ( size == 4 )
+               {
+                  ossim_sint32 i;
+                  attr.read( type, (void*)&i );
+                  if ( endian )
+                  {
+                     endian->swap( i );
+                  }
+                  value = ossimString::toString( i ).string();
+               }
+               break;
+            }
+            case OSSIM_UINT64:        
+            {
+               if ( size == 8 )
+               {
+                  ossim_uint64 i;
+                  attr.read( type, (void*)&i );
+                  if ( endian )
+                  {
+                     endian->swap( i );
+                  }  
+                  value = ossimString::toString( i ).string();
+               }
+               break;
+            }
+            case OSSIM_SINT64:
+            {
+               if ( size == 8 )
+               {
+                  ossim_sint32 i;
+                  attr.read( type, (void*)&i );
+                  if ( endian )
+                  {
+                     endian->swap( i );
+                  }
+                  value = ossimString::toString( i ).string();
+               }
+               break;
+            }
+            default:
+               break;
+         }
+      }
+      else if ( typeClass == H5T_FLOAT )
+      {
+         if ( scalar == OSSIM_FLOAT32 )
+         {
+            if ( size == 4 )
+            {
+               ossim_float32 f;
+               attr.read( type, (void*)&f );
+               if ( endian )
+               {
+                  endian->swap( f );
+               }
+               value = ossimString::toString( f ).string();
+            }
+         }
+         if ( scalar == OSSIM_FLOAT64 )
+         {
+            if ( size == 8 )
+            {
+               ossim_float64 f;
+               attr.read( type, (void*)&f );
+               if ( endian )
+               {
+                  endian->swap( f );
+               }
+               value = ossimString::toString( f ).string();
+            }
+         }
+      }
+
+      if ( endian )
+      {
+         delete endian;
+         endian = 0;
+      }
+   }
+   else if ( typeClass == H5T_STRING )
+   {
+      attr.read( type, value );
+   }
+   else
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimH5Util::printAttribute WARN: Unhandled type class: " << typeClass
+         << std::endl;
+   }
+
+   out << prefix << "." << name << ": " << value << std::endl;
+   
+} // End: ossim_hdf5::printAttribute
+
+void ossim_hdf5::combine( const std::string& left,
+                          const std::string& right,
+                          char separator,
+                          std::string& result )
+{
+   if ( left.size() && right.size() )
+   {
+      result = left;
+      if ( ( left[ left.size()-1 ] != separator ) && ( right[0] != separator ) )
+      {
+         result.push_back(separator);
+      }
+      result += right;
+   }
+}
+
+void ossim_hdf5::getDatasetNames(H5::H5File* file,
+                                 std::vector<std::string>& datasetNames )
+{
+   datasetNames.clear();
+   
+   if ( file )
+   {
+      std::string groupName = "/";
+      ossim_uint32 recurseCount = 0;
+      ossim_hdf5::iterateGroupForDatasetNames( file, groupName, datasetNames, recurseCount );
+#if 0
+      std::vector<std::string>::const_iterator i = datasetNames.begin();
+      while ( i != datasetNames.end() )
+      {
+         std::cout << "dataset: " << (*i) << std::endl;
+         ++i;
+      }
+#endif
+   }
+}
+
+std::string ossim_hdf5::getDatatypeClassType( ossim_int32 type )
+{
+   H5T_class_t classType = (H5T_class_t)type;
+   
+   std::string result;
+   switch ( classType )
+   {
+      case H5T_INTEGER:
+         result = "H5T_INTEGER";
+         break;
+      case H5T_FLOAT:
+         result = "H5T_FLOAT";
+         break;         
+      case H5T_TIME:
+         result = "H5T_TIME";
+         break;
+      case H5T_STRING:
+         result = "H5T_STRING";
+         break;
+      case H5T_BITFIELD:
+         result = "H5T_BITFIELD";
+         break;
+      case H5T_OPAQUE:
+         result = "H5T_OPAQUE";
+         break;         
+      case H5T_COMPOUND:
+         result = "H5T_COMPOUND";
+         break;
+      case H5T_REFERENCE:
+         result = "H5T_REFERENCE";
+         break;         
+      case H5T_ENUM:
+         result = "H5T_ENUM";
+         break;
+      case H5T_VLEN:
+         result = "H5T_VLEN";
+         break;         
+      case H5T_ARRAY:
+         result = "H5T_ARRAY";
+         break;
+      case H5T_NO_CLASS:
+      default:
+         result = "H5T_ARRAY";
+         break;
+   }
+   return result;
+}
+
+bool ossim_hdf5::isLoadableAsImage( H5::H5File* file, const std::string& datasetName )
+{
+   bool result = false;
+
+   // std::cout << "isLoadable entered..." << std::endl;
+   if ( file && datasetName.size() )
+   {
+      if ( isExcludedDataset( datasetName ) == false )
+      {
+         H5::DataSet dataset = file->openDataSet( datasetName );
+         
+         // Get the class of the datatype that is used by the dataset.
+         H5T_class_t type_class = dataset.getTypeClass();
+         // std::cout << "Class type: " << ossim_hdf5::getDatatypeClassType( type_class )
+         // << std::endl;
+         
+         if ( ( type_class == H5T_INTEGER ) || ( type_class == H5T_FLOAT ) )
+         {
+            // Get dataspace of the dataset.
+            // H5::DataSpace dataspace = dataset.getSpace();
+            
+            // Get the extents:
+            std::vector<ossim_uint32> extents;
+            ossim_hdf5::getExtents( &dataset, extents );
+            
+            if ( extents.size() >= 2 )
+            {
+               if ( ( extents[0] > 1 ) && ( extents[1] > 1 ) )
+               {
+                  // std::cout << "Accepting dataset: " << datasetName << std::endl;
+                  result = true;
+               }     
+            }
+            
+         }
+         
+         dataset.close();
+      }
+   }
+      
+   // std::cout << "isLoadable exit status: " << (result?"true":"false") << std::endl;
+   
+   return result;
+}
+
+bool ossim_hdf5::isExcludedDataset( const std::string& datasetName )
+{
+   bool result = false;
+   
+   ossimFilename f = datasetName;
+   f = f.file();
+#if 1
+   if ( f != "Radiance" )
+   {
+      result = true;
+   }
+#endif
+   
+#if 0
+   if ( ( f == "Latitude" )        ||
+        ( f == "Longitude" )       ||
+        ( f == "SCAttitude" )      ||
+        ( f == "SCPosition" )      ||
+        ( f == "SCVelocity" ) )
+   {
+      result = true;
+   }
+#endif
+   
+   return result;
+}
+
+void ossim_hdf5::iterateGroupForDatasetNames(  H5::H5File* file,
+                                               const std::string& groupName,
+                                               std::vector<std::string>& datasetNames,
+                                               ossim_uint32& recursedCount )
+{
+   if ( file && groupName.size() )
+   {
+      ++recursedCount;
+      
+      // std::cout << "iterateGroup: " << groupName << std::endl;
+      
+      H5::Group* group = new H5::Group( file->openGroup(groupName) );
+      
+      const hsize_t OBJ_COUNT = group->getNumObjs();
+      
+      for ( hsize_t i = 0; i < OBJ_COUNT; ++i )
+      {
+         std::string objName = group->getObjnameByIdx(i);
+
+         if ( objName.size() )
+         {
+            char separator = '/';
+            std::string combinedName;
+            combine( groupName, objName, separator, combinedName );
+            
+            H5G_obj_t objType   = group->getObjTypeByIdx(i);
+
+#if 0
+            std::cout << "combinedName: " << combinedName
+                      << "\ngetObjnameByIdx[" << i << "]: " << objName
+                      << "\ngetObjTypeByIdx[" << i << "]: " << objType
+                      << std::endl;
+#endif
+
+            if ( objType == H5G_GROUP )
+            {
+               // Recursive call:
+               if ( recursedCount < ossim_hdf5::MAX_RECURSION_LEVEL )
+               {
+                  ossim_hdf5::iterateGroupForDatasetNames(
+                     file, combinedName, datasetNames, recursedCount );
+               }
+               else
+               {
+                  ossimNotify(ossimNotifyLevel_WARN)
+                     << "ossim_hdf5::iterateGroupForDatasetNames WARNING!"
+                     << "\nMax iterations reached!" << std::endl;
+               }
+            }
+            else if ( objType == H5G_DATASET )
+            {
+               datasetNames.push_back( combinedName );
+            }
+            else
+            {
+               ossimNotify(ossimNotifyLevel_WARN)
+                     << "ossim_hdf5::iterateGroupForDatasetNames WARNING!"
+                     << "\nUnhandled object type: " << objType << std::endl;
+            }
+         }
+      }
+      
+      group->close();
+      delete group;
+      group = 0;
+      --recursedCount;
+      
+   } // Matches: if ( file )
+   
+} // End: void ossim_hdf5::iterateGroupForDatasetNames
+
+void ossim_hdf5::getExtents( const H5::DataSet* dataset,
+                             std::vector<ossim_uint32>& extents )
+{
+   extents.clear();
+   
+   if ( dataset )
+   {
+      // Get dataspace of the dataset.
+      H5::DataSpace dataspace = dataset->getSpace();
+      
+      // Number of dimensions:
+      int ndims = dataspace.getSimpleExtentNdims();
+      if ( ndims )
+      {
+         //hsize_t dims_out[ndims];
+         std::vector<hsize_t> dims_out(ndims);
+         dataspace.getSimpleExtentDims( &dims_out.front(), 0 );
+         for ( ossim_int32 i = 0; i < ndims; ++i )
+         {
+            extents.push_back(static_cast<ossim_uint32>(dims_out[i]));
+         }
+      }
+
+      dataspace.close();
+   }
+}
+
+ossimScalarType ossim_hdf5::getScalarType( const H5::DataSet* dataset )
+{
+   // cout << "typeClass: " << typeClass << "\nid: " << id << endl;
+
+   ossimScalarType scalar = OSSIM_SCALAR_UNKNOWN;
+
+   if ( dataset )
+   {
+      ossim_int32 typeClass = dataset->getTypeClass();
+      
+      if ( ( typeClass == H5T_INTEGER ) || ( typeClass == H5T_FLOAT ) )
+      {
+         // hid_t mem_type_id = H5Dget_type(id);
+         hid_t mem_type_id = H5Dget_type( dataset->getId() );
+         
+         // cout << "mem_type_id: " << mem_type_id << endl;
+         
+         if( mem_type_id > -1 )
+         {
+            hid_t native_type = H5Tget_native_type(mem_type_id, H5T_DIR_DEFAULT);
+            // hid_t native_type = H5Tget_native_type(id, H5T_DIR_DEFAULT);
+            
+            if( H5Tequal(H5T_NATIVE_CHAR, native_type) )
+            {
+               scalar = OSSIM_SINT8;
+            }
+            else if ( H5Tequal( H5T_NATIVE_UCHAR, native_type) )
+            {
+               scalar = OSSIM_UINT8;
+            }
+            else if( H5Tequal( H5T_NATIVE_SHORT, native_type) ) 
+            {
+               scalar = OSSIM_SINT16;
+            }
+            else if(H5Tequal(H5T_NATIVE_USHORT, native_type)) 
+            {
+               scalar = OSSIM_UINT16;
+            }
+            else if(H5Tequal( H5T_NATIVE_INT, native_type)) 
+            {
+               scalar = OSSIM_SINT32;
+            }
+            else if(H5Tequal( H5T_NATIVE_UINT, native_type ) ) 
+            {
+               scalar = OSSIM_UINT32;
+            }
+            else if(H5Tequal( H5T_NATIVE_LONG, native_type)) 
+            {
+               scalar = OSSIM_SINT32;
+            }
+            else if(H5Tequal( H5T_NATIVE_ULONG, native_type))
+            {
+               scalar = OSSIM_UINT32;
+            }
+            else if(H5Tequal( H5T_NATIVE_LLONG, native_type)) 
+            {
+               scalar = OSSIM_SINT64;
+            }
+            else if(H5Tequal( H5T_NATIVE_ULLONG, native_type))
+            {
+               scalar = OSSIM_UINT64;
+            }
+            else if(H5Tequal( H5T_NATIVE_FLOAT, native_type)) 
+            {
+               scalar = OSSIM_FLOAT32;
+            }
+            else if(H5Tequal( H5T_NATIVE_DOUBLE, native_type)) 
+            {
+               scalar = OSSIM_FLOAT64;
+            }
+         }
+         
+      } // Matches: if ( ( typeClass == ...
+      
+   } // Matches: if ( dataset ){
+   
+   return scalar;
+   
+} // End: ossim_hdf5::getScalarType( const H5::DataSet* dataset )
+
+ossimScalarType ossim_hdf5::getScalarType( ossim_int32 id )
+{
+   ossimScalarType scalar = OSSIM_SCALAR_UNKNOWN;
+   
+   H5T_class_t type_class = H5Tget_class(id);
+   size_t      size       = H5Tget_size(id);
+   H5T_sign_t  sign       = H5Tget_sign(id);
+   
+   if ( type_class == H5T_INTEGER )
+   {
+      if ( size == 1 && sign == H5T_SGN_2)
+      {
+         scalar = OSSIM_SINT8;
+      }
+      else if ( size == 2 && sign == H5T_SGN_2)
+      {
+         scalar = OSSIM_SINT16;
+      }
+      else if ( size == 4 && sign == H5T_SGN_2)
+      {
+         scalar = OSSIM_SINT32;
+      }
+      else if ( size == 8 && sign == H5T_SGN_2)
+      {
+         scalar = OSSIM_SINT64;
+      }
+      else if ( size == 1 && sign == H5T_SGN_NONE)
+      {
+         scalar = OSSIM_UINT8;
+      }
+      else if ( size == 2 && sign == H5T_SGN_NONE)
+      {
+         scalar = OSSIM_UINT16;
+      }
+      else if ( size == 4 && sign == H5T_SGN_NONE)
+      {
+         scalar = OSSIM_UINT32;
+      }
+      else if ( size == 8 && sign == H5T_SGN_NONE)
+      {
+         scalar = OSSIM_UINT64;
+      }
+   }
+   else if ( type_class == H5T_FLOAT )
+   {
+      if ( size == 4)
+      {
+         scalar = OSSIM_FLOAT32;
+      }
+      else if ( size == 8)
+      {
+         scalar = OSSIM_FLOAT64;
+      }
+   }
+   
+   return scalar;
+}
+
+ossimByteOrder ossim_hdf5::getByteOrder( const H5::AbstractDs* obj )
+{
+   ossimByteOrder byteOrder = ossim::byteOrder();
+   if ( obj )
+   {
+      // Get the class of the datatype that is used by the dataset.
+      H5T_class_t typeClass = obj->getTypeClass();
+
+      H5T_order_t order = H5T_ORDER_NONE;
+      
+      if ( typeClass == H5T_INTEGER )
+      {
+         H5::IntType intype = obj->getIntType();
+         order = intype.getOrder();
+      }
+      else if ( typeClass == H5T_FLOAT )
+      {
+         H5::FloatType floatType = obj->getFloatType();
+         order = floatType.getOrder(); 
+      }
+      
+      if ( order == H5T_ORDER_LE )
+      {
+         byteOrder = OSSIM_LITTLE_ENDIAN;
+      }
+      else if ( order == H5T_ORDER_BE )
+      {
+         byteOrder = OSSIM_BIG_ENDIAN;
+      }
+   }
+   return byteOrder;
+}
+
+bool ossim_hdf5::getValidBoundingRect( H5::DataSet& dataset,
+                                       const std::string& name,
+                                       ossimIrect& rect )
+{
+   bool result = false;
+   H5::DataSpace imageDataspace = dataset.getSpace();
+   const ossim_int32 IN_DIM_COUNT = imageDataspace.getSimpleExtentNdims();
+         
+   if ( IN_DIM_COUNT == 2 )
+   {
+      // Get the extents. Assuming dimensions are same for lat lon dataset. 
+      std::vector<hsize_t> dimsOut(IN_DIM_COUNT);
+      imageDataspace.getSimpleExtentDims( &dimsOut.front(), 0 );
+
+      if ( dimsOut[0] && dimsOut[1] )
+      {
+         
+         //---
+         // Capture the rectangle:
+         // dimsOut[0] is height, dimsOut[1] is width:
+         //---
+         rect = ossimIrect( 0, 0,
+                            static_cast<ossim_int32>( dimsOut[1]-1 ),
+                            static_cast<ossim_int32>( dimsOut[0]-1 ) );
+         
+         const ossim_int32 WIDTH  = rect.width();
+               
+         std::vector<hsize_t> inputCount(IN_DIM_COUNT);
+         std::vector<hsize_t> inputOffset(IN_DIM_COUNT);
+         
+         inputOffset[0] = 0;
+         inputOffset[1] = 0;
+         
+         inputCount[0] = 1;
+         inputCount[1] = WIDTH;
+         
+         // Output dataspace dimensions.
+         const ossim_int32 OUT_DIM_COUNT = 3;
+         std::vector<hsize_t> outputCount(OUT_DIM_COUNT);
+         outputCount[0] = 1;     // single band
+         outputCount[1] = 1;     // single line
+         outputCount[2] = WIDTH; // whole line
+               
+         // Output dataspace offset.
+         std::vector<hsize_t> outputOffset(OUT_DIM_COUNT);
+         outputOffset[0] = 0;
+         outputOffset[1] = 0;
+         outputOffset[2] = 0;
+               
+         ossimScalarType scalar = ossim_hdf5::getScalarType( &dataset );
+         if ( scalar == OSSIM_FLOAT32 )
+         {
+            // See if we need to swap bytes:
+            ossimEndian* endian = 0;
+            if ( ( ossim::byteOrder() != ossim_hdf5::getByteOrder( &dataset ) ) )
+            {
+               endian = new ossimEndian();
+            }
+
+            // Native type:
+            H5::DataType datatype = dataset.getDataType();
+                  
+            // Output dataspace always the same one line.
+            H5::DataSpace bufferDataSpace( OUT_DIM_COUNT, &outputCount.front());
+            bufferDataSpace.selectHyperslab( H5S_SELECT_SET,
+                                             &outputCount.front(),
+                                             &outputOffset.front() );
+
+            //---
+            // Dataset sample has NULL lines at the end so scan for valid rect.
+            // Use "<= -999" for test as per NOAA as it seems the NULL value is
+            // fuzzy.  e.g. -999.3.
+            //---
+            const ossim_float32 NULL_VALUE = -999.0;
+
+            //---
+            // VIIRS Radiance data has a -1.5e-9 in the first column.
+            // Treat this as a null.
+            //---
+            const ossim_float32 NULL_VALUE2 = ( name == "/All_Data/VIIRS-DNB-SDR_All/Radiance" )
+               ? -1.5e-9 : NULL_VALUE;
+            const ossim_float32 TOLERANCE = 0.1e-9; // For ossim::almostEqual()
+
+            // Hold one line:
+            std::vector<ossim_float32> values( WIDTH );
+
+            // Find the ul pixel:
+            ossimIpt ulIpt = rect.ul();
+            bool found = false;
+                  
+            // Line loop to find upper left pixel:
+            while ( ulIpt.y <= rect.lr().y )
+            {
+               inputOffset[0] = static_cast<hsize_t>(ulIpt.y);
+               imageDataspace.selectHyperslab( H5S_SELECT_SET,
+                                               &inputCount.front(),
+                                               &inputOffset.front() );
+               
+               // Read data from file into the buffer.
+               dataset.read( (void*)&values.front(), datatype, bufferDataSpace, imageDataspace );
+               
+               if ( endian )
+               {
+                  // If the endian pointer is initialized(not zero) swap the bytes.
+                  endian->swap( scalar, (void*)&values.front(), WIDTH );
+               }
+               
+               // Sample loop:
+               ulIpt.x = rect.ul().x;
+               ossim_int32 index = 0;
+               while ( ulIpt.x <= rect.lr().x )
+               {
+                  if ( !ossim::almostEqual(values[index], NULL_VALUE2, TOLERANCE) &&
+                       ( values[index] > NULL_VALUE ) )
+                  {
+                     found = true; // Found valid pixel.
+                     break;
+                  }
+                  ++ulIpt.x;
+                  ++index;
+                     
+               } // End: sample loop
+                     
+               if ( found )
+               {
+                  break;
+               }
+
+               ++ulIpt.y;
+                     
+            } // End line loop to find ul pixel:
+
+            // Find the lower right pixel:
+            ossimIpt lrIpt = rect.lr();
+            found = false;
+                  
+            // Line loop to find last pixel:
+            while ( lrIpt.y >= rect.ul().y )
+            {
+               inputOffset[0] = static_cast<hsize_t>(lrIpt.y);
+               imageDataspace.selectHyperslab( H5S_SELECT_SET,
+                                               &inputCount.front(),
+                                               &inputOffset.front() );
+               
+               // Read data from file into the buffer.
+               dataset.read( (void*)&values.front(), datatype, bufferDataSpace, imageDataspace );
+
+               if ( endian )
+               {
+                  // If the endian pointer is initialized(not zero) swap the bytes.
+                  endian->swap( scalar, (void*)&values.front(), WIDTH );
+               }
+            
+               // Sample loop:
+               lrIpt.x = rect.lr().x;
+               ossim_int32 index = WIDTH-1;
+               
+               while ( lrIpt.x >= rect.ul().x )
+               {
+                  if ( !ossim::almostEqual(values[index], NULL_VALUE2, TOLERANCE) &&
+                       ( values[index] > NULL_VALUE ) )
+                  {
+                     found = true; // Found valid pixel.
+                     break;
+                  }
+                  --lrIpt.x;
+                  --index;
+                     
+               } // End: sample loop
+                     
+               if ( found )
+               {
+                  break;
+               }
+
+               --lrIpt.y;
+                     
+            } // End line loop to find lower right pixel.
+
+            rect = ossimIrect( ulIpt, lrIpt );
+
+            // Cleanup:
+            if ( endian )
+            {
+               delete endian;
+               endian = 0;
+            }
+
+            result = true;
+            
+         } 
+         else // Matches: if ( scalar == OSSIM_FLOAT32 ){...}
+         {
+            ossimNotify(ossimNotifyLevel_WARN)
+               << "ossim_hdf5::getBoundingRect WARNING!"
+               << "\nUnhandled scalar type: "
+               << ossimScalarTypeLut::instance()->getEntryString( scalar )
+               << std::endl;
+         }
+               
+      } // Matches: if ( dimsOut...
+            
+   } // Matches: if ( IN_DIM_COUNT == 2 )
+         
+   imageDataspace.close();
+
+   return result;
+   
+} // End: ossim_hdf5::getBoundingRect(...)
+
+bool ossim_hdf5::crossesDateline( H5::DataSet& dataset, const ossimIrect& validRect )
+{
+   bool result = false;
+
+   H5::DataSpace dataspace = dataset.getSpace();
+         
+   // Number of dimensions of the input dataspace:
+   const ossim_int32 DIM_COUNT = dataspace.getSimpleExtentNdims();
+         
+   if ( DIM_COUNT == 2 )
+   {
+      const ossim_uint32 ROWS = validRect.height();
+      const ossim_uint32 COLS = validRect.width();
+      
+      // Get the extents. Assuming dimensions are same for lat lon dataset. 
+      std::vector<hsize_t> dimsOut(DIM_COUNT);
+      dataspace.getSimpleExtentDims( &dimsOut.front(), 0 );
+
+      if ( (ROWS <= dimsOut[0]) && (COLS <= dimsOut[1]) )
+      {
+         std::vector<hsize_t> inputCount(DIM_COUNT);
+         std::vector<hsize_t> inputOffset(DIM_COUNT);
+         
+         inputCount[0] = 1;    // row
+         inputCount[1] = COLS; // col
+         
+         // Output dataspace dimensions.
+         const ossim_int32 OUT_DIM_COUNT = 3;
+         std::vector<hsize_t> outputCount(OUT_DIM_COUNT);
+         outputCount[0] = 1; // single band
+         outputCount[1] = 1; // single line
+         outputCount[2] = COLS; // single sample
+               
+         // Output dataspace offset.
+         std::vector<hsize_t> outputOffset(OUT_DIM_COUNT);
+         outputOffset[0] = 0;
+         outputOffset[1] = 0;
+         outputOffset[2] = 0;
+               
+         ossimScalarType scalar = ossim_hdf5::getScalarType( &dataset );
+         if ( scalar == OSSIM_FLOAT32 )
+         {
+            // See if we need to swap bytes:
+            ossimEndian* endian = 0;
+            if ( ( ossim::byteOrder() != ossim_hdf5::getByteOrder( &dataset ) ) )
+            {
+               endian = new ossimEndian();
+            }
+
+            // Native type:
+            H5::DataType datatype = dataset.getDataType();
+                  
+            // Output dataspace always the same one line.
+            H5::DataSpace bufferDataSpace( OUT_DIM_COUNT, &outputCount.front());
+            bufferDataSpace.selectHyperslab( H5S_SELECT_SET,
+                                             &outputCount.front(),
+                                             &outputOffset.front() );
+
+            //---
+            // Dataset sample has NULL lines at the end so scan for valid rect.
+            // Use "<= -999" for test as per NOAA as it seems the NULL value is
+            // fuzzy.  e.g. -999.3.
+            //---
+
+            // Buffer to hold a line:
+            std::vector<ossim_float32> lineBuffer(validRect.width());
+
+            // Read the first line:
+            inputOffset[0] = static_cast<hsize_t>(validRect.ul().y);
+            inputOffset[1] = static_cast<hsize_t>(validRect.ul().x);
+            dataspace.selectHyperslab( H5S_SELECT_SET,
+                                       &inputCount.front(),
+                                       &inputOffset.front() );
+            dataset.read( &(lineBuffer.front()), datatype, bufferDataSpace, dataspace );
+
+            if ( endian )
+            {
+               // If the endian pointer is initialized(not zero) swap the bytes.
+               endian->swap( &(lineBuffer.front()), COLS );
+            }
+
+            // Test the first line:
+            result = ossim_hdf5::crossesDateline( lineBuffer );
+
+            if ( !result )
+            {
+               // Test the last line:
+               inputOffset[0] = static_cast<hsize_t>(validRect.ll().y);
+               inputOffset[1] = static_cast<hsize_t>(validRect.ll().x);
+               dataspace.selectHyperslab( H5S_SELECT_SET,
+                                          &inputCount.front(),
+                                          &inputOffset.front() );
+               dataset.read( &(lineBuffer.front()), datatype, bufferDataSpace, dataspace );
+
+               result = ossim_hdf5::crossesDateline( lineBuffer );
+            }
+
+            if ( endian )
+            {
+               delete endian;
+               endian = 0;
+            }
+         }
+         else // Matches: if ( scalar == OSSIM_FLOAT32 ){...}
+         {
+            ossimNotify(ossimNotifyLevel_WARN)
+               << "ossim_hdf5::crossesDateline WARNING!"
+               << "\nUnhandled scalar type: "
+               << ossimScalarTypeLut::instance()->getEntryString( scalar )
+               << std::endl;
+         }
+         
+      } // Matches: if ( dimsOut...
+      
+   } // Matches: if ( IN_DIM_COUNT == 2 )
+   
+   dataspace.close();
+   
+   return result;
+   
+} // End: ossim_hdf5::crossesDateline(...)
+
+bool ossim_hdf5::crossesDateline( const std::vector<ossim_float32>& lineBuffer)
+{
+   bool result = false;
+
+   ossim_int32 longitude = 0;
+   bool found179 = false;
+   bool found181 = false;
+
+   for ( ossim_uint32 i = 0; i < lineBuffer.size(); ++i)
+   {
+      longitude = (ossim_int32)lineBuffer[i]; // Cast to integer.
+
+      // look for 179 -> -179...
+      if ( !found179 )
+      {
+         if ( longitude == 179 )
+         {
+            found179 = true;
+            continue;
+         }
+      }
+      else // found179 == true
+      {
+         if ( longitude == 178 )
+         {
+            break; // Going West, 179 -> 178
+         }
+         else if ( longitude == -179 )
+         {
+            result = true;
+            break;
+         }
+      }
+      
+      // look for -179 -> 179...
+      if ( !found181 )
+      {
+         if ( longitude == -179 )
+         {
+            found181 = true;
+            continue;
+         }
+      }
+      else // found181 == true
+      {
+         if ( longitude == -178 )
+         {
+            break; // Going East -179 -> -178
+         }
+         else if ( longitude == 179 )
+         {
+            result = true;
+            break;
+         }
+      }
+   }
+   
+   return result;
+   
+} // End: ossim_hdf5::crossesDateline( lineBuffer )
+
+ossimRefPtr<ossimProjection> ossim_hdf5::getBilinearProjection(
+   H5::DataSet& latDataSet, H5::DataSet& lonDataSet, const ossimIrect& validRect )
+{
+   ossimRefPtr<ossimProjection> proj = 0;
+
+   // Get dataspace of the dataset.
+   H5::DataSpace latDataSpace = latDataSet.getSpace();
+   H5::DataSpace lonDataSpace = lonDataSet.getSpace();
+         
+   // Number of dimensions of the input dataspace:
+   const ossim_int32 DIM_COUNT = latDataSpace.getSimpleExtentNdims();
+         
+   if ( DIM_COUNT == 2 )
+   {
+      // Get the extents. Assuming dimensions are same for lat lon dataset. 
+      std::vector<hsize_t> dimsOut(DIM_COUNT);
+      latDataSpace.getSimpleExtentDims( &dimsOut.front(), 0 );
+
+      if ( dimsOut[0] && dimsOut[1] )
+      {
+         std::vector<hsize_t> inputCount(DIM_COUNT);
+         std::vector<hsize_t> inputOffset(DIM_COUNT);
+               
+         inputOffset[0] = 0;
+         inputOffset[1] = 0;
+               
+         inputCount[0] = 1;
+         inputCount[1] = 1;
+               
+         // Output dataspace dimensions.
+         const ossim_int32 OUT_DIM_COUNT = 3;
+         std::vector<hsize_t> outputCount(OUT_DIM_COUNT);
+         outputCount[0] = 1; // single band
+         outputCount[1] = 1; // single line
+         outputCount[2] = 1; // single sample
+               
+         // Output dataspace offset.
+         std::vector<hsize_t> outputOffset(OUT_DIM_COUNT);
+         outputOffset[0] = 0;
+         outputOffset[1] = 0;
+         outputOffset[2] = 0;
+               
+         ossimScalarType scalar = ossim_hdf5::getScalarType( &latDataSet );
+         if ( scalar == OSSIM_FLOAT32 )
+         {
+            // See if we need to swap bytes:
+            ossimEndian* endian = 0;
+            if ( ( ossim::byteOrder() != ossim_hdf5::getByteOrder( &latDataSet ) ) )
+            {
+               endian = new ossimEndian();
+            }
+
+            // Native type:
+            H5::DataType latDataType = latDataSet.getDataType();
+            H5::DataType lonDataType = lonDataSet.getDataType();
+                  
+            std::vector<ossimDpt> ipts;
+            std::vector<ossimGpt> gpts;
+            ossimGpt gpt(0.0, 0.0, 0.0); // Assuming WGS84...
+            ossim_float32 latValue = 0.0;
+            ossim_float32 lonValue = 0.0;
+                  
+            // Only grab every 256th value.:
+            const ossim_int32 GRID_SIZE = 256;
+                  
+            // Output dataspace always the same one pixel.
+            H5::DataSpace bufferDataSpace( OUT_DIM_COUNT, &outputCount.front());
+            bufferDataSpace.selectHyperslab( H5S_SELECT_SET,
+                                             &outputCount.front(),
+                                             &outputOffset.front() );
+
+            //---
+            // Dataset sample has NULL lines at the end so scan for valid rect.
+            // Use "<= -999" for test as per NOAA as it seems the NULL value is
+            // fuzzy.  e.g. -999.3.
+            //---
+            const ossim_float32 NULL_VALUE = -999.0;
+
+            //---
+            // Get the tie points within the valid rect:
+            //---
+            ossimDpt ipt = validRect.ul();
+            while ( ipt.y <= validRect.lr().y )
+            {
+               inputOffset[0] = static_cast<hsize_t>(ipt.y);
+               
+               // Sample loop:
+               ipt.x = validRect.ul().x;
+               while ( ipt.x <= validRect.lr().x )
+               {
+                  inputOffset[1] = static_cast<hsize_t>(ipt.x);
+                  
+                  latDataSpace.selectHyperslab( H5S_SELECT_SET,
+                                                &inputCount.front(),
+                                                &inputOffset.front() );
+                  lonDataSpace.selectHyperslab( H5S_SELECT_SET,
+                                                &inputCount.front(),
+                                                &inputOffset.front() );
+                  
+                  // Read data from file into the buffer.
+                  latDataSet.read( &latValue, latDataType, bufferDataSpace, latDataSpace );
+                  lonDataSet.read( &lonValue, lonDataType, bufferDataSpace, lonDataSpace );
+                  
+                  if ( endian )
+                  {
+                     // If the endian pointer is initialized(not zero) swap the bytes.
+                     endian->swap( latValue );
+                     endian->swap( lonValue );  
+                  }
+                  
+                  if ( ( latValue > NULL_VALUE ) && ( lonValue > NULL_VALUE ) )
+                  {
+                     gpt.lat = latValue;
+                     gpt.lon = lonValue;
+                     gpts.push_back( gpt );
+                     
+                     // Add the image point subtracting the image offset.
+                     ossimIpt shiftedIpt = ipt - validRect.ul();
+                     ipts.push_back( shiftedIpt );
+                  }
+
+                  // Go to next point:
+                  if ( ipt.x < validRect.lr().x )
+                  {
+                     ipt.x += GRID_SIZE;
+                     if ( ipt.x > validRect.lr().x )
+                     {
+                        ipt.x = validRect.lr().x; // Clamp to last sample.
+                     }
+                  }
+                  else
+                  {  
+                     break; // At the end:
+                  }
+                  
+               } // End sample loop.
+
+               if ( ipt.y < validRect.lr().y )
+               {
+                  ipt.y += GRID_SIZE;
+                  if ( ipt.y > validRect.lr().y )
+                  {
+                     ipt.y = validRect.lr().y; // Clamp to last line.
+                  }
+               }
+               else
+               {  
+                  break; // At the end:
+               }
+               
+            } // End line loop.
+                  
+            if ( ipts.size() )
+            {
+               // Create the projection:
+               ossimRefPtr<ossimBilinearProjection> bp = new ossimBilinearProjection();
+                     
+               // Add the tie points:
+               bp->setTiePoints( ipts, gpts );
+                     
+               // Assign to output projection:
+               proj = bp.get();
+            }
+
+            // Cleanup:
+            if ( endian )
+            {
+               delete endian;
+               endian = 0;
+            }
+         }
+         else // Matches: if ( scalar == OSSIM_FLOAT32 ){...}
+         {
+            ossimNotify(ossimNotifyLevel_WARN)
+               << "ossim_hdf5::getBilinearProjection WARNING!"
+               << "\nUnhandled scalar type: "
+               << ossimScalarTypeLut::instance()->getEntryString( scalar )
+               << std::endl;
+         }
+               
+      } // Matches: if ( dimsOut...
+            
+   } // Matches: if ( IN_DIM_COUNT == 2 )
+         
+   latDataSpace.close();
+   lonDataSpace.close();
+   
+   return proj;
+   
+} // End: ossim_hdf5::getBilinearProjection()
+
diff --git a/ossim_plugins/hdf5/ossimH5Util.h b/ossim_plugins/hdf5/ossimH5Util.h
new file mode 100644
index 0000000..3a41040
--- /dev/null
+++ b/ossim_plugins/hdf5/ossimH5Util.h
@@ -0,0 +1,209 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author:  David Burken
+//
+// Description: OSSIM HDF5 utility class.
+//
+//----------------------------------------------------------------------------
+// $Id
+
+#ifndef ossimH5Util_HEADER
+#define ossimH5Util_HEADER 1
+
+#include <ossim/base/ossimConstants.h>
+#include <ossim/base/ossimRefPtr.h>
+#include <ossim/projection/ossimProjection.h>
+
+#include <iosfwd>
+#include <string>
+#include <vector>
+
+// Forward class declarations:
+class ossimIrect;
+namespace H5
+{
+   class AbstractDs;
+   class Attribute;
+   class DataSet;
+   class H5File;
+}
+
+// Anonymous enums:
+enum 
+{
+   OSSIM_H5_MAX_RECURSION_LEVEL = 8
+};
+
+namespace ossim_hdf5
+{
+   // Anonymous enums:
+   enum 
+   {
+      //---
+      // Used by iterateGroupForDatasetNames which can recursively call itself
+      // to avoid blowing away the stack on an error.
+      //---
+      MAX_RECURSION_LEVEL = 8
+   };
+
+   /**
+    * @brief Print method.
+    *
+    * @param file Pointer to H5File instance.
+    * @param out Stream to print to.
+    * @return std::ostream&
+    */
+   std::ostream& print( H5::H5File* file,
+                        std::ostream& out );   
+
+   /**
+    * @brief Iterative print method.
+    * @param file Pointer to H5File instance.
+    * @param prefix to start the walk with.
+    * @param recursedCount Callers should start at zero. This is used
+    * internally to avoid an infinite loop as this method recursively
+    * calls itself.
+    * @param out Stream to print to.
+    */   
+   void printIterative( H5::H5File* file,
+                        const std::string& groupName,
+                        const std::string& prefix,
+                        ossim_uint32& recursedCount,
+                        std::ostream& out );
+
+   /**
+    * @brief Prints an object.
+    * @param file Pointer to H5File instance.
+    * @param prefix to start the walk with.
+    * @param recursedCount Callers should start at zero. This is used
+    * internally to avoid an infinite loop as this method recursively
+    * calls itself.
+    * @param out Stream to print to.
+    */ 
+   void printObject(  H5::H5File* file,
+                      const std::string& objectName,
+                      const std::string& prefix,
+                      std::ostream& out );
+
+   /**
+    * @brief Gets string value for attribute key.
+    *
+    * This assumes H5::Attribute type class is a H5T_STRING.
+    * 
+    * @param file Pointer to H5File instance.
+    *
+    * @param group Group to open. Examples:
+    * "/"
+    * "/Data_Products/VIIRS-DNB-GEO"
+    * 
+    * @param key This is key string. Examples:
+    * "Mission_Name"
+    * "N_Collection_Short_Name"
+    *
+    * @param value Initialized by this.
+    *
+    * @return true on success, false on error.
+    */    
+   bool getGroupAttributeValue( H5::H5File* file,
+                                const std::string& group,
+                                const std::string& key,
+                                std::string& value );
+   
+   /**
+    * @brief Gets string value for attribute key.
+    *
+    * This assumes H5::Attribute type class is a H5T_STRING.
+    * 
+    * @param file Pointer to H5File instance.
+    *
+    * @param dataset Data to open. Examples:
+    * "/"
+    * "/Data_Products/VIIRS-DNB-GEO"
+    * 
+    * @param key This is key string. Examples:
+    * "Mission_Name"
+    * "N_Collection_Short_Name"
+    *
+    * @param value Initialized by this.
+    *
+    * @return true on success, false on error.
+    */    
+   bool getDatasetAttributeValue( H5::H5File* file,
+                                const std::string& objectName,
+                                const std::string& key,
+                                std::string& value );
+   
+   void printAttribute( const H5::Attribute& attr,
+                        const std::string& prefix,
+                        std::ostream& out );
+   
+   void combine( const std::string& left,
+                 const std::string& right,
+                 char separator,
+                 std::string& result );
+   
+   void getDatasetNames(H5::H5File* file, std::vector<std::string>& names );
+
+   std::string getDatatypeClassType( ossim_int32 type );
+
+   bool isLoadableAsImage( H5::H5File* file,
+                           const std::string& datasetName );
+
+   bool isExcludedDataset( const std::string& datasetName );
+
+   void iterateGroupForDatasetNames( H5::H5File* file,
+                                     const std::string& group,
+                                     std::vector<std::string>& names,
+                                     ossim_uint32& recursedCount );
+
+   void getExtents( const H5::DataSet* dataset,
+                    std::vector<ossim_uint32>& extents );
+
+   // ossimScalarType getScalarType( ossim_int32 typeClass, ossim_int32 id );
+   ossimScalarType getScalarType( const H5::DataSet* dataset );
+
+
+   ossimScalarType getScalarType( ossim_int32 id );
+   
+   ossimByteOrder getByteOrder( const H5::AbstractDs* dataset );
+
+   /**
+    * @brief Gets the valid bounding rect of the dataset excluding nulls on front and back.
+    * @param dataset
+    * @param name Name of dataset.  Used for null scanning.
+    * @param rect Initialized by this.
+    */
+   bool getValidBoundingRect( H5::DataSet& dataset,
+                              const std::string& name,
+                              ossimIrect& rect );
+
+   /**
+    * @brief Gets bilinear projection from Latitude, Longitude layer.
+    *
+    * @param latDataSet H5::DataSet& to layer,
+    *    e.g. /All_Data/VIIRS-DNB-GEO_All/Latitude
+    * @param lonDataSet H5::DataSet& to layer,
+    *    e.g. /All_Data/VIIRS-DNB-GEO_All/Longitude
+    */
+   ossimRefPtr<ossimProjection> getBilinearProjection(
+      H5::DataSet& latDataSet,
+      H5::DataSet& lonDataSet,
+      const ossimIrect& validRect );
+
+   /**
+    * @brief Checks for dateline cross.
+    * @param dataset
+    * @param validRect Initialized by this.
+    * @return true if dateline cross is detected, false if not.
+    */
+   bool crossesDateline( H5::DataSet& dataset, const ossimIrect& validRect );
+   bool crossesDateline( const std::vector<ossim_float32>& lineBuffer);
+   
+} // End: namespace ossim_hdf5{...}
+
+#endif /* #ifndef ossimH5Util_HEADER */
+
diff --git a/ossim_plugins/kakadu/CMakeLists.txt b/ossim_plugins/kakadu/CMakeLists.txt
new file mode 100644
index 0000000..5daf379
--- /dev/null
+++ b/ossim_plugins/kakadu/CMakeLists.txt
@@ -0,0 +1,108 @@
+set(LIB_NAME ossimkakadu_plugin)
+
+message( "************** LIBRARY SETUP FOR ossimkakadu_plugin ******************")
+
+# Include ossim cmake stuff:
+include(OssimVersion)
+include(OssimCommonVariables)
+include(OssimUtilities)
+
+set(requiredLibs)
+
+# CURL - Optional:
+find_package( CURL )
+if( CURL_FOUND )
+   include_directories( ${CURL_INCLUDE_DIR} )
+   set( requiredLibs ${requiredLibs} ${CURL_LIBRARY} )
+   add_definitions("-DKAKADU_USE_CURL=1")
+else( CURL_FOUND )
+   message( STATUS "*** curl support is disabled in kakadu plugin.  No Curl library found ***")
+   add_definitions("-DKAKADU_USE_CURL=0")   
+endif( CURL_FOUND )
+
+# OpenThreads - Required:
+find_package( OpenThreads )
+if( OPENTHREADS_FOUND )
+   include_directories( ${OPENTHREADS_INCLUDE_DIR} )
+   set( requiredLibs ${requiredLibs} ${OPENTHREADS_LIBRARY} )
+else( OPENTHREADS_FOUND )
+   message( FATAL_ERROR "Could not find required OpenThreads package!" )
+endif( OPENTHREADS_FOUND )
+
+# TIFF - Required:
+find_package( TIFF )
+if( TIFF_FOUND )
+   include_directories( ${TIFF_INCLUDE_DIR} )
+   set( requiredLibs ${requiredLibs} ${TIFF_LIBRARY} )
+else( TIFF_FOUND )
+   message( FATAL_ERROR "Could not find required tiff package!" )
+endif( TIFF_FOUND )
+
+# OSSIM - Required: 
+find_package(ossim)
+if(OSSIM_FOUND)
+   include_directories( ${OSSIM_INCLUDE_DIR} )
+   set( requiredLibs ${requiredLibs} ${OSSIM_LIBRARIES} )
+else(OSSIM_FOUND)
+   message(FATAL_ERROR "Could not find ossim")
+endif(OSSIM_FOUND)
+
+if(KAKADU_ROOT_SRC)
+   include_directories(${KAKADU_ROOT_SRC}/coresys
+                       ${KAKADU_ROOT_SRC}/managed/all_includes)
+else(KAKADU_ROOT_SRC)
+   message(SEND_ERROR "Please pass in the KAKADU_ROOT_SRC and point it to the root source tree")
+   set(KAKADU_ROOT_SRC "" CACHE STRING "Specify the root location where the kakadu source tree is located")
+endif(KAKADU_ROOT_SRC)
+
+if(KAKADU_AUX_LIBRARY)
+   set(requiredLibs ${requiredLibs} ${KAKADU_AUX_LIBRARY})
+else(KAKADU_AUX_LIBRARY)
+   message(SEND_ERROR "Please pass in the KAKADU_AUX_LIBRARY and point it to the library")
+   set(KAKADU_AUX_LIBRARY "" CACHE STRING "Specify the full path to the library to link to")
+endif(KAKADU_AUX_LIBRARY)
+
+if(KAKADU_LIBRARY)
+   set(requiredLibs ${requiredLibs} ${KAKADU_LIBRARY})
+else(KAKADU_LIBRARY)
+   message(SEND_ERROR "Please pass in the KAKADU_LIBRARY and point it to the library")
+   set(KAKADU_LIBRARY "" CACHE STRING "Specify the full path to the library to link to")
+endif(KAKADU_LIBRARY)
+
+include_directories(${CMAKE_CURRENT_SOURCE_DIR})
+
+file(GLOB OSSIMPLUGIN_SRCS *.cpp)
+file(GLOB OSSIMPLUGIN_HEADERS *.h)
+
+message( STATUS "KAKADU_ROOT_SRC    = ${KAKADU_ROOT_SRC}")
+message( STATUS "KAKADU_LIBRARY     = ${KAKADU_LIBRARY}")
+message( STATUS "KAKADU_AUX_LIBRARY = ${KAKADU_LIBRARY}")
+message( STATUS "Kakadu plugin required libs = ${requiredLibs}")
+
+#---
+# OSSIMPLUGINSMAKINGDLL controls dll linkage on windows.  
+# Adding this sets OSSIM_PLUGINS_DLL #define TO "__declspec(dllexport)".
+#---
+add_definitions("-DOSSIMPLUGINSMAKINGDLL")
+
+#---
+# Kakadu library compatibilty define:
+# This must match whatever kakadu library was compiled with.
+# Look in Kakadu_library_root/coresys/make/Makefile-xxxx.
+#---
+add_definitions("-DKDU_X86_INTRINSICS")
+add_definitions("-DKDU_NO_AVX2")
+
+# Adjust the install library path:
+if(OSSIM_INSTALL_PLUGINS_WITH_VERSION)
+   set(INSTALL_LIBRARY_DIR   "${INSTALL_LIBRARY_DIR}/ossim-${OSSIM_VERSION}/plugins")
+else(OSSIM_INSTALL_PLUGINS_WITH_VERSION)
+   set(INSTALL_LIBRARY_DIR   "${INSTALL_LIBRARY_DIR}/ossim/plugins")
+endif(OSSIM_INSTALL_PLUGINS_WITH_VERSION)
+
+OSSIM_LINK_LIBRARY(${LIB_NAME}
+                   COMPONENT_NAME ossim TYPE "${OSSIM_PLUGIN_LINK_TYPE}"
+		   LIBRARIES ${requiredLibs}
+                   HEADERS "${OSSIMPLUGIN_HEADERS}" 
+		   SOURCE_FILES "${OSSIMPLUGIN_SRCS}"
+                   INSTALL_LIB)
diff --git a/ossim_plugins/kakadu/LICENSE.txt b/ossim_plugins/kakadu/LICENSE.txt
new file mode 100644
index 0000000..1d539e3
--- /dev/null
+++ b/ossim_plugins/kakadu/LICENSE.txt
@@ -0,0 +1,45 @@
+The OSSIM tree embeds some code from other libraries as well new code.  We will describe the license terms of the embedded modules as well as the license of the ossim core engine.  All code derived or embedded in the ossim core engine should not restrict the use of commercial purposes.
+
+1.  OSSIM engine abides by the LGPL license terms.  We grant you the use of the OSSIM core engine in commercial or non commercial use without royalty as long as the credits for the original authors stay within the source code.  See the top level LGPL.txt found found here along side the LICENSE.txt.
+
+2.  shapelib.  The shape library was written by Frank Warmerdam and has an MIT Style license these files include:
+       dbfopen.c shpopen.c shptree.c
+and are located in src/ossim/vec directory.  They have the following copyright 
+******************************************************************************
+ * Copyright (c) 1999, Frank Warmerdam
+ *
+ * This software is available under the following "MIT Style" license,
+ * or at the option of the licensee under the LGPL (see LICENSE.LGPL).  This
+ * option is discussed in more detail in shapelib.html.
+ *
+ * --
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+
+
+
+3. The matrix library was written by Robert Davies.  At the time of download the site was located at http://www.robertnz.net. He gives free use in commercial and non commercial as long as his code remains in tact and the credits for the author are known.
+
+4. The kbool library does polygon boolean operation and is used by the ossimPolyArea2d class.  The license terms are based on the wxwidgets licensing which gives free use in commercial and non-commercial libraries.  At the time of download the module used could be found at: http://boolean.klaasholwerda.nl/download/download.html
+
+5. Geotrans.  The geotrans library is a set of map projections that are certified and hosted by NGA.  They give free use in commercial and non commercial software packages and at the time of download the geotrans modules could be found at http://earth-info.nga.mil/GandG/geotrans/.  We have embedded the datum, ellipsoid, and map projections into the ossim baseline and wrapped in C++ classes so to remove the global variable access common in the raw getorans c library.
+
+6. KAKADU:  This OSSIM plugin utilizes the kakadu library for compression/
+decompression.  Users must adhere to kakadu licensing.
+See:  http://www.kakadusoftware.com
diff --git a/ossim_plugins/kakadu/makefile.vc b/ossim_plugins/kakadu/makefile.vc
new file mode 100755
index 0000000..b315005
--- /dev/null
+++ b/ossim_plugins/kakadu/makefile.vc
@@ -0,0 +1,64 @@
+###
+# $Id: makefile.vc 12864 2008-05-15 13:13:28Z dburken $
+#
+# Windows nmake make file.  This code should compile with the Microsoft .NET
+# compiler.
+# 
+# Currently for a typical build on windows you would do the following.
+# - cd back to the ossim top and edit its nmake.opt file appropriately.
+# - nmake /f makefile
+#
+# NOTE:  If you make shared apps it's handy to copy the ossim.dll to the bin
+#        directory. 
+###
+
+!INCLUDE ..\nmake.opt
+PLUGIN_ROOT = ossim_kakadu_plugin
+
+###
+# Note: EMBED_MANIFEST variable is set in nmake.opt so make sure it is included
+# before this test.
+###
+!if "$(EMBED_MANIFEST)" == "1"
+!include ..\makefile.inc
+OSSIM_VC_MANIFEST_EMBED_DLL=$(_VC_MANIFEST_EMBED_DLL)
+OSSIM_VC_MANIFEST_CLEAN=$(_VC_MANIFEST_CLEAN)
+!else
+OSSIM_VC_MANIFEST_EMBED_DLL=
+OSSIM_VC_MANIFEST_CLEAN=
+!endif
+
+INC	=	-I.. -I. $(INC) $(KAK_INC)
+LINK	=	link
+
+OBJ = \
+ossimKakaduCommon.obj \
+ossimKakaduCompressedTarget.obj \
+ossimKakaduCompressor.obj \
+ossimKakaduJ2kReader.obj \
+ossimKakaduJp2Reader.obj \
+ossimKakaduJp2Writer.obj \
+ossimKakaduNitfOverviewBuilder.obj \
+ossimKakaduNitfReader.obj \
+ossimKakaduNitfWriter.obj \
+ossimKakaduOverviewBuilderFactory.obj \
+ossimKakaduPluginInit.obj \
+ossimKakaduReaderFactory.obj \
+ossimKakaduWriterFactory.obj
+
+
+default:	$(OBJ)
+	link /NOLOGO /SUBSYSTEM:WINDOWS /VERSION:$(VERSION_STRING) /DLL /OUT:"$(PLUGIN_ROOT).dll" /IMPLIB:"$(PLUGIN_ROOT).lib" $(OBJ) $(OSSIM_HOME)\lib\ossim.lib $(KAK_LIB)
+	$(OSSIM_VC_MANIFEST_EMBED_DLL)
+
+install:
+	$(CP) $(PLUGIN_ROOT).dll $(INSTALL_DIR)
+
+clean:
+	$(RM) *.obj
+	$(RM) $(OSSIM_PLUGIN_LIB_PATH)\$(PLUGIN_ROOT).*
+	$(OSSIM_VC_MANIFEST_CLEAN)
+
+!if "$(EMBED_MANIFEST)" == "1"
+!include ..\makefile.targ.inc
+!endif
diff --git a/ossim_plugins/kakadu/ossimJpipProjectionFactory.cpp b/ossim_plugins/kakadu/ossimJpipProjectionFactory.cpp
new file mode 100644
index 0000000..14f567e
--- /dev/null
+++ b/ossim_plugins/kakadu/ossimJpipProjectionFactory.cpp
@@ -0,0 +1,87 @@
+#include "ossimJpipProjectionFactory.h"
+#include <ossim/base/ossimFilename.h>
+#include <ossim/base/ossimUrl.h>
+#include <ossim/support_data/ossimInfoBase.h>
+#include <ossim/support_data/ossimInfoFactoryRegistry.h>
+#include <ossim/projection/ossimProjectionFactoryRegistry.h>
+
+RTTI_DEF1(ossimJpipProjectionFactory, "ossimJpipProjectionFactory", ossimProjectionFactoryBase)
+ossimJpipProjectionFactory::ossimJpipProjectionFactory()
+{
+}
+
+ossimJpipProjectionFactory* ossimJpipProjectionFactory::instance()
+{
+   static ossimJpipProjectionFactory inst;
+   return &inst;
+}
+
+ossimProjection* ossimJpipProjectionFactory::createProjection(const ossimFilename& filename,
+                                          ossim_uint32 entryIdx)const
+{
+   ossimProjection* result = 0;
+   bool canGetInfo = (filename.ext().downcase() == "jpip");
+   if(!canGetInfo)
+   {
+      ossimUrl url(filename.c_str());
+      ossimString protocol  =url.getProtocol().downcase();
+      if((protocol == "jpip")||
+         (protocol == "jpips"))
+      {
+         canGetInfo = true;
+      }
+   }
+      
+   if(canGetInfo)
+   {
+      ossimRefPtr<ossimInfoBase> infoBase = ossimInfoFactoryRegistry::instance()->create(filename);
+      if(infoBase.valid())
+      {
+         ossimKeywordlist kwl;
+         infoBase->getKeywordlist(kwl);
+         ossimString prefix = "jpip.image" + ossimString::toString(entryIdx) + ".";
+         result = ossimProjectionFactoryRegistry::instance()->createProjection(kwl, prefix.c_str());
+      }
+   }
+   return result;
+}
+
+ossimProjection* ossimJpipProjectionFactory::createProjection(const ossimString& /*name*/)const
+{
+   return 0;
+}
+
+ossimProjection* ossimJpipProjectionFactory::createProjection(const ossimKeywordlist& kwl,
+                                          const char* prefix)const
+{
+   ossimProjection* result = 0;
+   ossimString geojp2Prefix = ossimString(prefix) + "geojp2.";
+   if(kwl.getNumberOfSubstringKeys(geojp2Prefix) > 0)
+   {
+      // try creating an ossim projection from a geojp2
+      result = ossimProjectionFactoryRegistry::instance()->createProjection(kwl, geojp2Prefix.c_str());
+   }
+   else
+   {
+      // we will try to pick out XML type projeciton information
+      //
+   }
+   return result;
+}
+
+ossimObject* ossimJpipProjectionFactory::createObject(const ossimString& /*typeName*/)const
+{
+   return 0;
+}
+
+ossimObject* ossimJpipProjectionFactory::createObject(const ossimKeywordlist& /*kwl*/,
+                                  const char* /*prefix*/)const
+{
+   return 0;
+}
+
+void ossimJpipProjectionFactory::getTypeNameList(std::vector<ossimString>& /*typeList*/)const
+{
+   
+}
+
diff --git a/ossim_plugins/kakadu/ossimJpipProjectionFactory.h b/ossim_plugins/kakadu/ossimJpipProjectionFactory.h
new file mode 100644
index 0000000..e0f4d75
--- /dev/null
+++ b/ossim_plugins/kakadu/ossimJpipProjectionFactory.h
@@ -0,0 +1,45 @@
+#ifndef ossimJpipProjectionFactory_HEADER
+#define ossimJpipProjectionFactory_HEADER 1
+#include <ossim/projection/ossimProjectionFactoryBase.h>
+
+class ossimJpipProjectionFactory : public ossimProjectionFactoryBase
+{
+public:
+   /*!
+    * METHOD: instance()
+    * Instantiates singleton instance of this class:
+    */
+   static ossimJpipProjectionFactory* instance();
+   
+   virtual ossimProjection* createProjection(const ossimFilename& filename,
+                                             ossim_uint32 entryIdx)const;
+   /*!
+    * METHOD: create()
+    * Attempts to create an instance of the projection specified by name.
+    * Returns successfully constructed projection or NULL.
+    */
+   virtual ossimProjection* createProjection(const ossimString& name)const;
+   virtual ossimProjection* createProjection(const ossimKeywordlist& kwl,
+                                             const char* prefix = 0)const;
+   virtual ossimObject* createObject(const ossimString& typeName)const;
+   
+   /*!
+    * Creates and object given a keyword list.
+    */
+   virtual ossimObject* createObject(const ossimKeywordlist& kwl,
+                                     const char* prefix=0)const;
+   
+   /*!
+    * This should return the type name of all objects in all factories.
+    * This is the name used to construct the objects dynamially and this
+    * name must be unique.
+    */
+   virtual void getTypeNameList(std::vector<ossimString>& typeList)const;
+   
+protected:
+   ossimJpipProjectionFactory();
+
+TYPE_DATA;
+};
+
+#endif
diff --git a/ossim_plugins/kakadu/ossimKakaduCommon.cpp b/ossim_plugins/kakadu/ossimKakaduCommon.cpp
new file mode 100644
index 0000000..5e7f58a
--- /dev/null
+++ b/ossim_plugins/kakadu/ossimKakaduCommon.cpp
@@ -0,0 +1,889 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Description: Common code for this plugin.
+//
+//----------------------------------------------------------------------------
+// $Id: ossimKakaduCommon.cpp 23664 2015-12-14 14:17:27Z dburken $
+
+#include "ossimKakaduCommon.h"
+#include "ossimKakaduCompressedTarget.h"
+
+#include <ossim/base/ossimException.h>
+#include <ossim/base/ossimIrect.h>
+#include <ossim/base/ossimPreferences.h>
+#include <ossim/base/ossimTrace.h>
+#include <ossim/imaging/ossimImageData.h>
+#include <ossim/imaging/ossimOverviewBuilderBase.h>
+#include <ossim/imaging/ossimTiffWriter.h>
+
+#include <jp2.h>
+#include <kdu_region_decompressor.h>
+#include <kdu_compressed.h>
+#include <kdu_threads.h>
+
+#include <ostream>
+#include <sstream>
+
+static const ossimTrace traceDebug( ossimString("ossimKakaduCommon:debug") );
+
+void ossim::getDims(const ossimIrect& rect, kdu_core::kdu_dims& dims)
+{
+   dims.pos.x = rect.ul().x;
+   dims.pos.y = rect.ul().y;
+   dims.size.x = static_cast<int>(rect.width());
+   dims.size.y = static_cast<int>(rect.height());
+}
+
+void ossim::getRect(const kdu_core::kdu_dims& dims, ossimIrect& rect)
+{
+   rect = ossimIrect(dims.pos.x,
+                     dims.pos.y,
+                     dims.pos.x + dims.size.x - 1,
+                     dims.pos.y + dims.size.y - 1);
+}
+
+bool ossim::clipRegionToImage(kdu_core::kdu_codestream& codestream,
+                              kdu_core::kdu_dims& region,
+                              int discard_levels,
+                              kdu_core::kdu_dims& clipRegion)
+{
+   // Clip the region to the image dimensions.
+
+   bool result = false;
+
+   if ( codestream.exists() )
+   {
+      codestream.apply_input_restrictions(
+         0, 0, discard_levels, 0, NULL, kdu_core::KDU_WANT_OUTPUT_COMPONENTS);
+      
+      kdu_core::kdu_dims dims;
+      codestream.get_dims(0, dims);
+      if ( region.intersects(dims) )
+      {
+         clipRegion = region.intersection(dims);
+         result = true;
+      }
+   }
+
+   return result;
+}
+
+bool ossim::getCodestreamDimensions(kdu_core::kdu_codestream& codestream,
+                                    std::vector<ossimIrect>& imageDims,
+                                    std::vector<ossimIrect>& tileDims)
+{
+   bool result = true;
+   
+   imageDims.clear();
+   tileDims.clear();
+
+   if ( codestream.exists() )
+   {
+      kdu_core::kdu_coords tileIdx(0, 0);
+      
+      ossim_uint32 levels = codestream.get_min_dwt_levels();
+
+      for (ossim_uint32 level=0; level <= levels; ++level)
+      {
+         // Get the image dimensions.
+
+         codestream.apply_input_restrictions(
+            0,     // first_component
+            0,     // max_components (0 = all remaining will appear)
+            level, // highest resolution level
+            0,     // max_layers (0 = all layers retained)
+            NULL,  // expanded out to block boundary.
+            kdu_core::KDU_WANT_OUTPUT_COMPONENTS);
+         
+         kdu_core::kdu_dims dims;
+         codestream.get_dims(0, dims);
+         
+         // Make the imageRect upper left relative to any sub image offset.
+         ossimIrect imageRect;
+         getRect(dims, imageRect);
+         
+         imageDims.push_back(imageRect);
+
+         // Get the tile dimensions.
+         
+         kdu_core::kdu_dims mappedRegion;
+         codestream.map_region(0, dims, mappedRegion, true);
+         
+         kdu_core::kdu_tile tile = codestream.open_tile(tileIdx);
+         if ( tile.exists() )
+         {
+            codestream.get_tile_dims( tile.get_tile_idx(), 0, dims );
+            
+            // Make the tile rect zero based.
+            ossimIrect tileRect(0,
+                                0,
+                                dims.size.x-1,
+                                dims.size.y-1);
+            
+            tileDims.push_back(tileRect);
+
+            // Every open has a close.
+            tile.close();
+         }
+         else
+         {
+            result = false;
+         }
+         
+      } // matches: for (ossim_uint32 level=0; level <= levels; ++level)
+
+      // Set things back to level 0.
+      codestream.apply_input_restrictions(
+         0,     // first_component
+         0,     // max_components (0 = all remaining will appear)
+         0, // highest resolution level
+         0,     // max_layers (0 = all layers retained)
+         NULL,  // expanded out to block boundary.
+         kdu_core::KDU_WANT_OUTPUT_COMPONENTS);
+
+      // Should be the same sizes as levels.
+      if ( (imageDims.size() != tileDims.size()) ||
+           (tileDims.size() != levels+1) )
+      {
+         result = false;
+      }
+   } 
+   else // codestream.exists() == false
+   {
+      result = false;
+   }
+
+   return result;
+}
+
+// Takes a channel map and decompresses all bands at once.
+bool ossim::copyRegionToTile(kdu_supp::kdu_channel_mapping* channelMapping,
+                             kdu_core::kdu_codestream& codestream,
+                             int discard_levels,
+                             kdu_core::kdu_thread_env* threadEnv,
+                             kdu_core::kdu_thread_queue* threadQueue,
+                             ossimImageData* destTile)
+{
+   bool result = true;
+
+   if ( channelMapping && destTile && codestream.exists())// && threadEnv && threadQueue )
+   {
+      try // Kakadu throws exceptions...
+      {
+         kdu_core::kdu_dims region;
+         getDims(destTile->getImageRectangle(), region);
+      
+         kdu_core::kdu_dims clipRegion;
+         if ( clipRegionToImage(codestream,
+                                region,
+                                discard_levels,
+                                clipRegion) )
+         {
+            if (region != clipRegion)
+            {
+               // Not filling whole tile.
+               destTile->makeBlank();
+            }
+         
+            const ossim_uint32 BANDS = destTile->getNumberOfBands();
+            const ossimScalarType SCALAR = destTile->getScalarType();
+         
+            int max_layers = INT_MAX;
+            kdu_core::kdu_coords expand_numerator(1,1);
+            kdu_core::kdu_coords expand_denominator(1,1);
+            bool precise = true;
+            kdu_core::kdu_component_access_mode access_mode =
+               kdu_core::KDU_WANT_OUTPUT_COMPONENTS;
+            bool fastest = false;
+
+            // Start the kdu_region_decompressor.
+            kdu_supp::kdu_region_decompressor krd;
+            if ( krd.start( codestream,
+                            channelMapping,
+                            -1,
+                            discard_levels,
+                            max_layers,
+                            clipRegion,
+                            expand_numerator,
+                            expand_denominator,
+                            precise,
+                            access_mode,
+                            fastest,
+                            threadEnv,
+                            threadQueue )
+                 == false)
+            {
+               std::string e = "kdu_region_decompressor::start error!";
+               throw(ossimException(e));
+            }
+
+            bool expand_monochrome = false;
+            int pixel_gap = 1;
+            kdu_core::kdu_coords buffer_origin;
+            buffer_origin.x = destTile->getImageRectangle().ul().x;
+            buffer_origin.y = destTile->getImageRectangle().ul().y;
+            int row_gap = region.size.x;
+            int suggested_increment = static_cast<int>(destTile->getSize());
+            int max_region_pixels = suggested_increment;
+            kdu_core::kdu_dims incomplete_region = clipRegion;
+            kdu_core::kdu_dims new_region;
+            bool measure_row_gap_in_pixels = true;
+         
+            // For signed int set precision bit to 0 for kakadu.
+            int precision_bits = (SCALAR != OSSIM_SINT16) ? codestream.get_bit_depth(0, true) : 0;
+
+            switch (SCALAR)
+            {
+               case OSSIM_UINT8:
+               {
+                  // Get pointers to the tile buffers.
+                  std::vector<kdu_core::kdu_byte*> channel_bufs(BANDS);
+                  for ( ossim_uint32 band = 0; band < BANDS; ++band )
+                  {
+                     channel_bufs[band] = destTile->getUcharBuf(band);
+                  }
+
+                  while ( !incomplete_region.is_empty() )
+                  {
+                     if ( krd.process( &channel_bufs.front(),
+                                       expand_monochrome,
+                                       pixel_gap,
+                                       buffer_origin,
+                                       row_gap, 
+                                       suggested_increment,
+                                       max_region_pixels,
+                                       incomplete_region,
+                                       new_region,
+                                       precision_bits,
+                                       measure_row_gap_in_pixels ) == false )
+                     {
+                        break;
+                     }
+                  }
+
+                  // Wait for things to finish.
+                  if( threadEnv && threadQueue )
+                  {
+                     //---
+                     // Wait for all queues descended from `root_queue' to identify themselves
+                     // as "finished" via the `kdu_thread_queue::all_done' function.
+                     //---
+                     threadEnv->join(threadQueue, true);
+                  }
+                  
+                  // Validate the tile.
+                  destTile->validate();
+
+                  break;
+               }
+               case OSSIM_USHORT11:
+               case OSSIM_UINT16:
+               case OSSIM_SINT16:
+               {
+                  // Get pointers to the tile buffers.
+                  std::vector<kdu_core::kdu_uint16*> channel_bufs(BANDS);
+                  for ( ossim_uint32 band = 0; band < BANDS; ++band )
+                  {
+                     channel_bufs[band] = static_cast<kdu_core::kdu_uint16*>(
+                        destTile->getBuf(band));
+                  }
+
+                  while ( !incomplete_region.is_empty() )
+                  {
+                     //---
+                     // Note: precision_bits set to 0 to indicate "signed" data
+                     // for the region decompressor.
+                     //---
+                     if ( krd.process( &channel_bufs.front(),
+                                       expand_monochrome,
+                                       pixel_gap,
+                                       buffer_origin,
+                                       row_gap, 
+                                       suggested_increment,
+                                       max_region_pixels,
+                                       incomplete_region,
+                                       new_region,
+                                       precision_bits,
+                                       measure_row_gap_in_pixels ) == false )
+                     {
+                        break;
+                     }
+                  }
+
+                  // Wait for things to finish.
+                  if( threadEnv && threadQueue )
+                  {
+                     //---
+                     // Wait for all queues descended from `root_queue' to identify themselves
+                     // as "finished" via the `kdu_thread_queue::all_done' function.
+                     //---
+                     threadEnv->join(threadQueue, true);
+                  }
+                  
+                  // Validate the tile.
+                  destTile->validate();
+
+                  break;
+               }
+               case OSSIM_SINT32:
+               case OSSIM_FLOAT32:
+               {
+                  //---
+                  // NOTES:
+                  // 1) Signed 32 bit integer data gets normalized when compressed
+                  //    so use the same code path as float data.
+                  // 2) Cannot call "ossimImageData::getFloatBuf" as it will return a
+                  //    null pointer if the destination tile is OSSIM_SINT32 scalar type.
+                  //---
+
+                  // Get pointers to the tile buffers.
+                  std::vector<ossim_float32*> channel_bufs(BANDS);
+                  for ( ossim_uint32 band = 0; band < BANDS; ++band )
+                  {
+                     channel_bufs[band] = static_cast<ossim_float32*>(destTile->getBuf(band));
+                  }
+
+                  while ( !incomplete_region.is_empty() )
+                  {
+                     //---
+                     // Note: precision_bits set to 0 to indicate "signed" data
+                     // for the region decompressor.
+                     //---
+                     if ( krd.process( &channel_bufs.front(),
+                                       expand_monochrome,
+                                       pixel_gap,
+                                       buffer_origin,
+                                       row_gap,
+                                       suggested_increment,
+                                       max_region_pixels,
+                                       incomplete_region,
+                                       new_region,
+                                       true, // normalize
+                                       measure_row_gap_in_pixels ) )
+                     {
+                        break;
+                     }
+                  }
+                  
+                  if( threadEnv && threadQueue )
+                  {
+                     //---
+                     // Wait for all queues descended from `root_queue' to identify themselves
+                     // as "finished" via the `kdu_thread_queue::all_done' function.
+                     //---
+                     threadEnv->join(threadQueue, true);
+                  }
+                  
+                  // Un-normalize.
+                  ossim::unNormalizeTile(destTile);
+                  
+                  // Validate the tile.
+                  destTile->validate();
+
+                  break;
+               }
+               default:
+               {
+                  ossimNotify(ossimNotifyLevel_WARN)
+                     << __FILE__ << " " << __LINE__ << " Unhandle scalar: "
+                     << destTile->getScalarType() << "\n";
+                  result = false;
+                  break;
+               }
+               
+            } // End of:  switch (theScalarType)
+            
+            // Every call to kdu_region_decompressor::start has a finish.
+            if ( krd.finish() == false )
+            {
+               ossimNotify(ossimNotifyLevel_WARN)
+                  << __FILE__ << " " << __LINE__
+                  << "kdu_region_decompressor::proces error!\n";
+            }
+         }
+         else // No region intersect with image.
+         {
+            destTile->makeBlank();
+         }
+         
+      } // Matches: try{ ...
+      
+      // Catch and rethrow exceptions.
+      catch( const ossimException& /* e */ )
+      {
+         throw;
+      }
+      catch ( kdu_core::kdu_exception exc )
+      {
+         // kdu_exception is an int typedef.
+         if ( threadEnv != 0 )
+         {
+            threadEnv->handle_exception(exc);
+         }
+         ostringstream e;
+         e << "Caught exception from kdu_region_decompressor: " << exc << "\n";
+         throw ossimException( e.str() );
+      }
+      catch ( std::bad_alloc& )
+      {
+         if ( threadEnv != 0 )
+         {
+            threadEnv->handle_exception(KDU_MEMORY_EXCEPTION);
+         }
+         std::string e =
+            "Caught exception from kdu_region_decompressor: std::bad_alloc";
+         throw ossimException( e );
+      }
+      catch( ... )
+      {
+         std::string e =
+            "Caught unhandled exception from kdu_region_decompressor";
+         throw ossimException( e );
+      }
+   }
+   else  // no codestream
+   {
+      result = false;
+   }
+
+#if 0  /* Please leave for serious debug. (drb) */
+   if (destTile)
+   {
+      static int tileNumber = 0;
+      if (destTile)
+      {
+         ossimFilename f = "tile-dump";
+         f += ossimString::toString(tileNumber);
+         f += ".ras";
+         if (destTile->write(f))
+         {
+            ossimNotify(ossimNotifyLevel_DEBUG)
+               << "wrote: " << f << std::endl;
+            ++tileNumber;
+         }
+      }
+   }
+#endif
+   
+   return result;
+
+} // End: ossim::copyRegionToTile
+
+// Takes a codestream and decompresses band at a time.
+bool ossim::copyRegionToTile(kdu_core::kdu_codestream& codestream,
+                             int discard_levels,
+                             kdu_core::kdu_thread_env* threadEnv,
+                             kdu_core::kdu_thread_queue* threadQueue,
+                             ossimImageData* destTile)
+{
+   bool result = true;
+
+   if ( destTile && codestream.exists())// && threadEnv && threadQueue )
+   {
+      try // Kakadu throws exceptions...
+      {
+         kdu_core::kdu_dims region;
+         getDims(destTile->getImageRectangle(), region);
+
+         kdu_core::kdu_dims clipRegion;
+         if ( clipRegionToImage(codestream,
+                                region,
+                                discard_levels,
+                                clipRegion) )
+         {
+            if (region != clipRegion)
+            {
+               // Not filling whole tile.
+               destTile->makeBlank();
+            }
+            
+            const ossimScalarType SCALAR = destTile->getScalarType();
+            const ossim_uint32 BANDS = destTile->getNumberOfBands();
+            
+            kdu_supp::kdu_channel_mapping* mapping = 0;
+            int max_layers = INT_MAX;
+            kdu_core::kdu_coords expand_numerator(1,1);
+            kdu_core::kdu_coords expand_denominator(1,1);
+            bool precise = true;
+            kdu_core::kdu_component_access_mode access_mode =
+               kdu_core::KDU_WANT_OUTPUT_COMPONENTS;
+            bool fastest = false;
+            
+            //---
+            // band loop:
+            // Note: At some point we may want to be a band selector;
+            // in which case, we would loop through the band list.
+            // For now just go through all bands and let the ossimBandSelector
+            // weed them out.
+            //---
+            for (ossim_uint32 band = 0; band < BANDS; ++band)
+            {
+               int single_component = band;
+            
+               // Start the kdu_region_decompressor.
+               kdu_supp::kdu_region_decompressor krd;
+               
+               if ( krd.start( codestream,
+                               mapping,
+                               single_component,
+                               discard_levels,
+                               max_layers,
+                               clipRegion,
+                               expand_numerator,
+                               expand_denominator,
+                               precise,
+                               access_mode,
+                               fastest,
+                               threadEnv,
+                               threadQueue )
+                    == false)
+               {
+                  std::string e = "kdu_region_decompressor::start error!";
+                  throw(ossimException(e));
+               }
+               
+               vector<int> channel_offsets(1);
+               channel_offsets[0] = 0;
+               int pixel_gap = 1;
+               kdu_core::kdu_coords buffer_origin;
+               buffer_origin.x = destTile->getImageRectangle().ul().x;
+               buffer_origin.y = destTile->getImageRectangle().ul().y;
+               int row_gap = region.size.x;
+               int suggested_increment = static_cast<int>(destTile->getSize());
+               int max_region_pixels = suggested_increment;
+               kdu_core::kdu_dims incomplete_region = clipRegion;
+               kdu_core::kdu_dims new_region;
+               bool measure_row_gap_in_pixels = true;
+               
+               // For signed int set precision bit to 0 for kakadu.
+               int precision_bits = (SCALAR != OSSIM_SINT16) ? codestream.get_bit_depth(0, true) : 0;
+               
+               switch (SCALAR)
+               {
+                  case OSSIM_UINT8:
+                  {
+                     // Get pointer to the tile buffer.
+                     kdu_core::kdu_byte* buffer = destTile->getUcharBuf(band);
+                     
+                     while ( !incomplete_region.is_empty() )
+                     {
+                        if ( krd.process( buffer,
+                                          &channel_offsets.front(),
+                                          pixel_gap,
+                                          buffer_origin,
+                                          row_gap,
+                                          suggested_increment,
+                                          max_region_pixels,
+                                          incomplete_region,
+                                          new_region,
+                                          precision_bits,
+                                          measure_row_gap_in_pixels ) )
+                        {
+                           break;
+                        }
+                     }
+
+                     if( threadEnv && threadQueue)
+                     {
+                        //---
+                        // Wait for all queues descended from `root_queue' to identify themselves
+                        // as "finished" via the `kdu_thread_queue::all_done' function.
+                        //---
+                        threadEnv->join(threadQueue, true);
+                     }
+                     
+                     // Validate the tile.
+                     destTile->validate();
+
+                     break;
+                  }
+                  case OSSIM_USHORT11:
+                  case OSSIM_UINT16:
+                  case OSSIM_SINT16:   
+                  {
+                     // Get pointer to the tile buffer.
+                     kdu_core::kdu_uint16* buffer =
+                        static_cast<kdu_core::kdu_uint16*>(destTile->getBuf(band));
+                     
+                     while ( !incomplete_region.is_empty() )
+                     {
+                        //---
+                        // Note: precision_bits set to 0 to indicate "signed" data
+                        // for the region decompressor.
+                        //---
+                        if ( krd.process( buffer,
+                                          &channel_offsets.front(),
+                                          pixel_gap,
+                                          buffer_origin,
+                                          row_gap,
+                                          suggested_increment,
+                                          max_region_pixels,
+                                          incomplete_region,
+                                          new_region,
+                                          precision_bits,
+                                          measure_row_gap_in_pixels ) == false )
+                        {
+                           break;
+                        }
+                     }
+                     
+                     //---
+                     // Wait for all queues descended from `root_queue' to identify themselves
+                     // as "finished" via the `kdu_thread_queue::all_done' function.
+                     //---
+                     if( threadEnv && threadQueue)
+                     {
+                        threadEnv->join(threadQueue, true);
+                     }
+                     
+                     // Validate the tile.
+                     destTile->validate();
+                  
+                     break;
+                  }
+                  case OSSIM_SINT32:
+                  case OSSIM_FLOAT32:
+                  {
+                     //---
+                     // NOTES:
+                     // 1) Signed 32 bit integer data gets normalized when compressed
+                     //    so use the same code path as float data.
+                     // 2) Cannot call "ossimImageData::getFloatBuf" as it will return a
+                     //    null pointer if the destination tile is OSSIM_SINT32 scalar type.
+                     //---
+                     
+                     // Get pointer to the tile buffer.
+                     ossim_float32* buffer = static_cast<ossim_float32*>(destTile->getBuf(band));
+                     
+                     while ( !incomplete_region.is_empty() )
+                     {
+                        //---
+                        // Note: precision_bits set to 0 to indicate "signed" data
+                        // for the region decompressor.
+                        //---
+                        if ( krd.process( buffer,
+                                          &channel_offsets.front(),
+                                          pixel_gap,
+                                          buffer_origin,
+                                          row_gap,
+                                          suggested_increment,
+                                          max_region_pixels,
+                                          incomplete_region,
+                                          new_region,
+                                          true, // normalize
+                                          measure_row_gap_in_pixels ) == false )
+                        {
+                           break;
+                        }
+                     }
+               
+                     if( threadEnv && threadQueue)
+                     {
+                        //---
+                        // Wait for all queues descended from `root_queue' to identify themselves
+                        // as "finished" via the `kdu_thread_queue::all_done' function.
+                        //---
+                        threadEnv->join(threadQueue, true);
+                     }
+               
+                     // Un-normalize.
+                     ossim::unNormalizeTile(destTile);
+                     
+                     // Validate the tile.
+                     destTile->validate();
+                     
+                     break;
+                  }
+                  
+                  default:
+                  {
+                     ossimNotify(ossimNotifyLevel_WARN)
+                        << __FILE__ << " " << __LINE__ << " Unhandle scalar: "
+                        << destTile->getScalarType() << "\n";
+                     result = false;
+                     break;
+                  }
+         
+               } // End of:  switch (theScalarType)
+            
+               // Every call to kdu_region_decompressor::start has a finish.
+               if ( krd.finish() == false )
+               {
+                  result = false;
+                  ossimNotify(ossimNotifyLevel_WARN)
+                     << __FILE__ << " " << __LINE__
+                     << " kdu_region_decompressor::proces error!" << std::endl;
+               }
+               
+         
+            } // End of band loop.
+         }
+         else // No region intersect with image.
+         {
+            destTile->makeBlank();
+         }
+         
+      } // Matches: try{ ...
+
+      // Catch and rethrow exceptions.
+      catch( const ossimException& /* e */ )
+      {
+         throw;
+      }
+      catch ( kdu_core::kdu_exception exc )
+      {
+         // kdu_exception is an int typedef.
+         if ( threadEnv != 0 )
+         {
+            threadEnv->handle_exception(exc);
+         }
+         ostringstream e;
+         e << "Caught exception from kdu_region_decompressor: " << exc << "\n";
+         throw ossimException( e.str() );
+         
+      }
+      catch ( std::bad_alloc& )
+      {
+         if ( threadEnv != 0 )
+         {
+            threadEnv->handle_exception(KDU_MEMORY_EXCEPTION);
+         }
+         std::string e =
+            "Caught exception from kdu_region_decompressor: std::bad_alloc";
+         throw ossimException( e );
+      }
+      catch( ... )
+      {
+         std::string e =
+            "Caught unhandled exception from kdu_region_decompressor";
+         throw ossimException(e);
+      }
+   }
+   else  // no codestream
+   {
+      result = false;
+   }
+
+#if 0  /* Please leave for serious debug. (drb) */
+   if (destTile)
+   {
+      static int tileNumber = 0;
+      if (destTile)
+      {
+         ossimFilename f = "tile-dump";
+         f += ossimString::toString(tileNumber);
+         f += ".ras";
+         if (destTile->write(f))
+         {
+            ossimNotify(ossimNotifyLevel_DEBUG)
+               << "wrote: " << f << std::endl;
+            ++tileNumber;
+         }
+      }
+   }
+#endif
+   
+   return result;
+
+} // End: ossim::copyRegionToTile
+
+void ossim::unNormalizeTile(ossimImageData* result)
+{
+   if (result)
+   {
+      const ossim_uint32  SIZE  = result->getSize();
+      const ossim_float64 MINP  = result->getMinPix(0);
+      const ossim_float64 MAXP  = result->getMaxPix(0);
+      const ossim_float64 RANGE = MAXP - MINP;
+      
+      if ( result->getScalarType() == OSSIM_FLOAT32 )
+      {
+         const ossim_float32 NULLP = static_cast<ossim_float32>(result->getNullPix(0));         
+         ossim_float32* buf = result->getFloatBuf();
+         for(ossim_uint32 idx = 0; idx < SIZE; ++idx)
+         {
+            ossim_float64 p = buf[idx];
+            if(p > 0.0)
+            {
+               p = MINP + RANGE * p;
+               p = (p < MAXP ? (p > MINP ? p : MINP) : MAXP);
+               buf[idx] = static_cast<ossim_float32>(p);
+            }
+            else
+            {
+               buf[idx] = NULLP;
+            }
+         }
+      }
+      else if ( result->getScalarType() == OSSIM_SINT32 )
+      {
+         const ossim_sint32 NULLP = static_cast<ossim_sint32>(result->getNullPix(0));
+         ossim_float32* inBuf = static_cast<ossim_float32*>(result->getBuf());
+         ossim_sint32* outBuf = static_cast<ossim_sint32*>(result->getBuf());
+         for(ossim_uint32 idx = 0; idx < SIZE; ++idx)
+         {
+            ossim_float64 p = inBuf[idx];
+            if(p > 0.0)
+            {
+               p = MINP + RANGE * p;
+               p = (p < MAXP ? (p > MINP ? p : MINP) : MAXP);
+               outBuf[idx] = static_cast<ossim_sint32>(p);
+            }
+            else
+            {
+               outBuf[idx] = NULLP;
+            }
+         }         
+      }
+      else
+      {
+         ossimNotify(ossimNotifyLevel_WARN)
+            << __FILE__ << " " << __LINE__ << " Unhandle scalar: "
+            << result->getScalarType() << "\n";
+      }
+   }
+
+} // End: ossim::unNormalizeTile
+
+std::ostream& ossim::print(std::ostream& out, kdu_core::kdu_codestream& cs)
+{
+   out << "codestream debug:"
+       << "exists: " << (cs.exists()?"true":"false");
+   if (cs.exists())
+   {
+      const int BANDS = cs.get_num_components(true);
+      out << "\ncomponents: " << BANDS;
+      for (int i = 0; i < BANDS; ++i)
+      {
+         kdu_core::kdu_dims dims;
+         cs.get_dims(i, dims, true);
+         out << "\nbit_depth[" << i << "]: " << cs.get_bit_depth(i, true)
+             << "\nsigned[" << i << "]: " << cs.get_signed(i, true)
+             << "\ndims[" << i << "]: ";
+         ossim::print(out, dims);
+      }
+      out << "\nlevels: " << cs.get_min_dwt_levels();
+   }
+   return out;
+}
+
+std::ostream& ossim::print(std::ostream& out, const kdu_core::kdu_dims& dims)
+{
+   out << "pos: ";
+   print(out, dims.pos);
+   out << ", size: ";
+   print(out, dims.size);
+   out << "\n";
+   return out;
+}
+
+std::ostream& ossim::print(std::ostream& out, const kdu_core::kdu_coords& coords)
+{
+   out << "(" << coords.x << ", " << coords.y << ")";
+   return out;
+}
+
diff --git a/ossim_plugins/kakadu/ossimKakaduCommon.h b/ossim_plugins/kakadu/ossimKakaduCommon.h
new file mode 100644
index 0000000..6aea244
--- /dev/null
+++ b/ossim_plugins/kakadu/ossimKakaduCommon.h
@@ -0,0 +1,168 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Description: Common code for this plugin.
+//
+//----------------------------------------------------------------------------
+// $Id: ossimKakaduCommon.h 23664 2015-12-14 14:17:27Z dburken $
+
+#ifndef ossimKakaduCommon_HEADER
+#define ossimKakaduCommon_HEADER 1
+
+#include <ossim/base/ossimConstants.h>
+#include <iosfwd>
+#include <vector>
+
+class jp2_source;
+
+namespace kdu_core
+{
+   class kdu_codestream;
+   class kdu_thread_env;
+   class kdu_thread_queue;
+
+   struct kdu_coords;
+   struct kdu_dims;
+}
+
+namespace kdu_supp
+{
+  struct kdu_channel_mapping;
+}
+
+
+class ossimImageData;
+class ossimIrect;
+
+namespace ossim
+{
+   /**
+    * @brief Convenience method to convert ossimIrect to kdu_dims.
+    * 
+    * @param rect The ossimIrect to convert.
+    * 
+    * @param dims This kdu_dim to initialize.
+    */
+   void getDims(const ossimIrect& rect, kdu_core::kdu_dims& dims);
+   
+   /**
+    * @brief Convenience method to convert kdu_core::kdu_dims to ossimIrect.
+    * 
+    * @param dims This kdu_dim to convert.
+    * 
+    * @param rect The ossimIrect to initialize.
+    */
+   void getRect(const kdu_core::kdu_dims& dims, ossimIrect& rect);
+   
+   /**
+    * @brief Sets clipRegion from region, and image dimensions for level.
+    *
+    * This will clip region to the image dimensions for
+    * the given discard_levels.  Returns false
+    * if no intersection.
+    * 
+    * @param codestream Stream to pull from.
+    * 
+    * @param region The region wanted from codestream.
+    * 
+    * @param discard_levels The resolution level, 0 being full res.
+    * 
+    * @param clipRegion The region to initialize.
+    * 
+    * @return true on success, false if no intersection or there were
+    * codestream or pointer issues.
+    */
+   bool clipRegionToImage(kdu_core::kdu_codestream& codestream,
+                          kdu_core::kdu_dims& region,
+                          int discard_levels,
+                          kdu_core::kdu_dims& clipRegion);
+   
+   /**
+    * @brief Gets image and tile dimensions from codestream for each
+    * resolution level (rlevel).  Note that on entry the arrays are cleared
+    * so they will be empty on failure.
+    * 
+    * @param codestream The codestream to read from.
+    *
+    * @param imageDims Array to initialize with image size of each rlevel.
+    * This will have any sub image offset applied to it.
+    * 
+    * @param tileDims Array to initialize with tile size of each rlevel.
+    * This is zero base tile size.  No sub image offset if there is one.
+    * 
+    * @return true on success, false on error.
+    *
+    * @note On entry the arrays are cleared so they will can be empty on
+    * failure.
+    */
+   bool getCodestreamDimensions(kdu_core::kdu_codestream& codestream,
+                                std::vector<ossimIrect>& imageDims,
+                                std::vector<ossimIrect>& tileDims);
+
+   /**
+    * @brief Copies region from codestream to tile at a given rlevel.
+    *
+    * This method takes a channelMapping and decompresses all bands at once.
+    * Specifically needed to convert YCC color space to RGB.
+    *
+    * @param Kakadu channel mapping object.
+    * @param codestream Stream to pull from.
+    * @param region The region wanted from codestream.
+    * @param discard_levels The resolution level, 0 being full res.
+    * @param threadEnv Pointer to kdu_thread_env.
+    * @param threadQueue Pointer to kdu_thread_queue.
+    * @param destTile The ossimImageData object to copy to.
+    * @return true on success, false on error.
+    */
+   bool copyRegionToTile(kdu_supp::kdu_channel_mapping* channelMapping,
+                         kdu_core::kdu_codestream& codestream,
+                         int discard_levels,
+                         kdu_core::kdu_thread_env* threadEnv,
+                         kdu_core::kdu_thread_queue* threadQueue,
+                         ossimImageData* destTile);
+   
+   /**
+    * @brief Copies region from codestream to tile at a given rlevel.
+    *
+    * This method takes a codestream and decompresses each band separately.
+    * Specifically needed for n-band data where the kdu_channel_mapping will
+    * not work.
+    * 
+    * @param codestream Stream to pull from.
+    * @param region The region wanted from codestream.
+    * @param discard_levels The resolution level, 0 being full res.
+    * @param threadEnv Pointer to kdu_thread_env.
+    * @param threadQueue Pointer to kdu_thread_queue.
+    * @param destTile The ossimImageData object to copy to.
+    * @return true on success, false on error.
+    */
+   bool copyRegionToTile(kdu_core::kdu_codestream& codestream,
+                         int discard_levels,
+                         kdu_core::kdu_thread_env* threadEnv,
+                         kdu_core::kdu_thread_queue* threadQueue,
+                         ossimImageData* destTile);
+
+   /**
+    * @brief Un-normalizes float tile from kdu_region_decompressor::process method.
+    *
+    * Takes tile which is assumed to be normalized by kakadu and stretches between the
+    * tile min and max.
+    */
+   void unNormalizeTile(ossimImageData* result);
+
+   /** @brief Convenience print method for kdu_codestream */
+   std::ostream& print(std::ostream& out, kdu_core::kdu_codestream& cs);
+
+   /** @brief Convenience print method for kdu_dims */
+   std::ostream& print(std::ostream& out, const kdu_core::kdu_dims& dims);
+   
+   /** @brief Convenience print method for kdu_coords */
+   std::ostream& print(std::ostream& out, const kdu_core::kdu_coords& coords);
+
+} // matches: namespace ossim
+
+#endif /* matches: #ifndef ossimKakaduCommon_HEADER */
+
diff --git a/ossim_plugins/kakadu/ossimKakaduCompressedTarget.cpp b/ossim_plugins/kakadu/ossimKakaduCompressedTarget.cpp
new file mode 100644
index 0000000..a8e6684
--- /dev/null
+++ b/ossim_plugins/kakadu/ossimKakaduCompressedTarget.cpp
@@ -0,0 +1,99 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Description:
+//
+// Class definition for JPEG2000 (J2K) kdu_compressed_target that uses an
+// ostream for writing to the file.
+//
+//----------------------------------------------------------------------------
+// $Id: ossimKakaduCompressedTarget.cpp 23664 2015-12-14 14:17:27Z dburken $
+
+#include "ossimKakaduCompressedTarget.h"
+#include <iostream>
+#include <ostream>
+
+ossimKakaduCompressedTarget::ossimKakaduCompressedTarget()
+   : m_stream(0),
+     m_restorePosition(0)
+{
+}
+
+ossimKakaduCompressedTarget::~ossimKakaduCompressedTarget()
+{
+}
+ 
+void ossimKakaduCompressedTarget::setStream(std::ostream* stream)
+{
+   if ( stream )
+   {
+      m_stream = stream;
+
+      //---
+      // Keep track of the stream position for the start_rewrite call.
+      // ostream::tellp() on windows visual studio 10 x64 fails past
+      // 2^31-1(2GB) even though the std::streamoff held in the
+      // std::streampos is eight bytes.
+      // This call is safe as the stream is typically at 0.
+      //---
+      m_restorePosition = stream->tellp();
+   }
+}
+
+bool ossimKakaduCompressedTarget::write(const kdu_core::kdu_byte *buf, int num_bytes)
+{
+   if ( m_restorePosition == 0 )
+   {
+      //---
+      // First write call.  Do a tellp in case the stream was moved as in the case of
+      // nitf where the nitf header and nitf image header get written before we write
+      // pixel data.
+      //---
+      m_restorePosition = m_stream->tellp();
+   }
+   
+   bool result = false;
+   if (m_stream)
+   {
+      m_stream->write((const char*)buf,
+                      static_cast<std::streamsize>(num_bytes));
+      
+      //---
+      // Keep track of the stream postition for the start_rewrite call.  Do it
+      // manually as ostream::tellp() on windows visual studio 10 x64 fails
+      // past 2^31-1(2GB) even though the std::streamoff held in the
+      // std::streampos is eight bytes.
+      //---
+      m_restorePosition += static_cast<std::streamoff>(num_bytes);
+      
+      result = m_stream->good();
+   }
+   return result;
+}
+
+bool ossimKakaduCompressedTarget::start_rewrite(kdu_core::kdu_long backtrack)
+{
+   bool result = false;
+   if (m_stream)
+   {
+      std::streamoff off = m_restorePosition - static_cast<std::streamoff>(backtrack);
+      m_stream->seekp(off, std::ios_base::beg);
+      result = m_stream->good();
+   }
+   return result;
+}
+
+bool ossimKakaduCompressedTarget::end_rewrite()
+{
+   bool result = false;
+   if (m_stream)
+   {
+      m_stream->seekp(m_restorePosition, std::ios_base::beg);
+      result = m_stream->good();
+   }
+   return result;
+}
+
diff --git a/ossim_plugins/kakadu/ossimKakaduCompressedTarget.h b/ossim_plugins/kakadu/ossimKakaduCompressedTarget.h
new file mode 100644
index 0000000..9f71efd
--- /dev/null
+++ b/ossim_plugins/kakadu/ossimKakaduCompressedTarget.h
@@ -0,0 +1,68 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Description:
+//
+// Class declaration for JPEG2000 (J2K) kdu_compressed_target that uses an
+// ostream for writing to the file.
+//
+//----------------------------------------------------------------------------
+// $Id: ossimKakaduCompressedTarget.h 23664 2015-12-14 14:17:27Z dburken $
+
+#ifndef ossimKakaduCompressedTarget_HEADER
+#define ossimKakaduCompressedTarget_HEADER 1
+
+#include "../ossimPluginConstants.h"
+#include <kdu_compressed.h>
+#include <kdu_elementary.h>
+#include <iosfwd>
+
+/**
+ * @brief ossimKakaduCompressedTarget JPEG2000 (J2K) kdu_compressed_target
+ * that uses an ostream for writing to the file.
+ */
+class ossimKakaduCompressedTarget :
+   public kdu_core::kdu_compressed_target
+{
+public:
+
+   /** default construtor */
+   ossimKakaduCompressedTarget();
+   
+   /** virtural destructor */
+   virtual ~ossimKakaduCompressedTarget();
+
+   /**
+    * @brief Sets the output stream.
+    *
+    * Note the ossimKakaduCompressedTarget only uses the stream it does not
+    * take over(delete) memory on destruction.
+    * 
+    * @param stream  The output stream.
+    */
+   void setStream(std::ostream* stream);
+
+   /**
+    * @brief Write method.
+    * @param buf The buffer to pull from.
+    * @param num_bytes The number of bytes to write.
+    * @return true on success, false on error.
+    */
+   virtual bool write(const kdu_core::kdu_byte *buf, int num_bytes);
+
+   virtual bool start_rewrite(kdu_core::kdu_long backtrack);
+
+   virtual bool end_rewrite();
+
+private:
+
+   std::ostream*  m_stream;
+   std::streamoff m_restorePosition; // For end_rewrite.
+
+};
+
+#endif /* #ifndef ossimKakaduCompressedTarget_HEADER */
+
diff --git a/ossim_plugins/kakadu/ossimKakaduCompressor.cpp b/ossim_plugins/kakadu/ossimKakaduCompressor.cpp
new file mode 100644
index 0000000..0804075
--- /dev/null
+++ b/ossim_plugins/kakadu/ossimKakaduCompressor.cpp
@@ -0,0 +1,1771 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author:  David Burken
+//
+// Description: Wrapper class to compress whole tiles using kdu_analysis
+// object.
+//
+//----------------------------------------------------------------------------
+// $Id: ossimKakaduCompressor.cpp 23664 2015-12-14 14:17:27Z dburken $
+
+#include "ossimKakaduCompressor.h"
+#include "ossimKakaduCommon.h"
+#include "ossimKakaduCompressedTarget.h"
+#include "ossimKakaduKeywords.h"
+
+#include <ossim/base/ossimBooleanProperty.h>
+#include <ossim/base/ossimCommon.h>
+#include <ossim/base/ossimException.h>
+#include <ossim/base/ossimIpt.h>
+#include <ossim/base/ossimKeywordlist.h>
+#include <ossim/base/ossimKeywordNames.h>
+#include <ossim/base/ossimNotify.h>
+#include <ossim/base/ossimNumericProperty.h>
+#include <ossim/base/ossimPreferences.h>
+#include <ossim/base/ossimStringProperty.h>
+#include <ossim/base/ossimTrace.h>
+
+#include <ossim/imaging/ossimImageData.h>
+#include <ossim/imaging/ossimImageGeometry.h>
+
+#include <ossim/support_data/ossimGeoTiff.h>
+
+#include <jp2.h>
+#include <cmath> /* ceil */
+
+//---
+// For trace debugging (to enable at runtime do:
+// your_app -T "ossimKakaduCompressor:debug" your_app_args
+//---
+static ossimTrace traceDebug("ossimKakaduCompressor:debug");
+
+static const ossim_int32 DEFAULT_LEVELS = 5;
+
+// Matches ossimKakaduCompressionQuality enumeration:
+static const ossimString COMPRESSION_QUALITY[] = { "unknown",
+                                                   "user_defined",
+                                                   "numerically_lossless",
+                                                   "visually_lossless",
+                                                   "lossy" };
+
+static void transfer_bytes(
+   kdu_core::kdu_line_buf &dest, kdu_core::kdu_byte *src,
+   int num_samples, int sample_gap, int src_bits, int original_bits)
+{
+   if (dest.get_buf16() != 0)
+   {
+      kdu_core::kdu_sample16 *dp = dest.get_buf16();
+      kdu_core::kdu_int16 off = ((kdu_core::kdu_int16)(1<<src_bits))>>1;
+      kdu_core::kdu_int16 mask = ~((kdu_core::kdu_int16)((-1)<<src_bits));
+      if (!dest.is_absolute())
+      {
+         int shift = KDU_FIX_POINT - src_bits; assert(shift >= 0);
+         for (; num_samples > 0; num_samples--, src+=sample_gap, dp++)
+            dp->ival = ((((kdu_core::kdu_int16) *src) & mask) - off) << shift;
+      }
+      else if (src_bits < original_bits)
+      { // Reversible processing; source buffer has too few bits
+         int shift = original_bits - src_bits;
+         for (; num_samples > 0; num_samples--, src+=sample_gap, dp++)
+            dp->ival = ((((kdu_core::kdu_int16) *src) & mask) - off) << shift;
+      }
+      else if (src_bits > original_bits)
+      { // Reversible processing; source buffer has too many bits
+         int shift = src_bits - original_bits;
+         off -= (1<<shift)>>1; // For rounded down-shifting
+         for (; num_samples > 0; num_samples--, src+=sample_gap, dp++)
+            dp->ival = ((((kdu_core::kdu_int16) *src) & mask) - off) >> shift;
+      }
+      else
+      { // Reversible processing, `src_bits'=`original_bits'
+         for (; num_samples > 0; num_samples--, src+=sample_gap, dp++)
+            dp->ival = (((kdu_core::kdu_int16) *src) & mask) - off;
+      }
+   }
+   else
+   {
+      kdu_core::kdu_sample32 *dp = dest.get_buf32();
+      kdu_core::kdu_int32 off = ((kdu_core::kdu_int32)(1<<src_bits))>>1;
+      kdu_core::kdu_int32 mask = ~((kdu_core::kdu_int32)((-1)<<src_bits));
+      if (!dest.is_absolute())
+      {
+         float scale = 1.0F / (float)(1<<src_bits);
+         for (; num_samples > 0; num_samples--, src+=sample_gap, dp++)
+            dp->fval = scale * (float)((((kdu_core::kdu_int32) *src) & mask) - off);
+      }
+      else if (src_bits < original_bits)
+      { // Reversible processing; source buffer has too few bits
+         int shift = original_bits - src_bits;
+         for (; num_samples > 0; num_samples--, src+=sample_gap, dp++)
+            dp->ival = ((((kdu_core::kdu_int32) *src) & mask) - off) << shift;
+      }
+      else if (src_bits > original_bits)
+      { // Reversible processing; source buffer has too many bits
+         int shift = src_bits - original_bits;
+         off -= (1<<shift)>>1; // For rounded down-shifting
+         for (; num_samples > 0; num_samples--, src+=sample_gap, dp++)
+            dp->ival = ((((kdu_core::kdu_int32) *src) & mask) - off) >> shift;
+      }
+      else
+      { // Reversible processing, `src_bits'=`original_bits'
+         for (; num_samples > 0; num_samples--, src+=sample_gap, dp++)
+            dp->ival = (((kdu_core::kdu_int32) *src) & mask) - off;
+      }
+   }
+}
+
+static void transfer_words(
+   kdu_core::kdu_line_buf &dest, kdu_core::kdu_int16 *src, int num_samples,
+   int sample_gap, int src_bits, int original_bits,
+   bool is_signed)
+{
+   if (dest.get_buf16() != 0)
+   {
+      kdu_core::kdu_sample16 *dp = dest.get_buf16();
+      int upshift = 16-src_bits; assert(upshift >= 0);
+      if (!dest.is_absolute())
+      {
+         if (is_signed)
+            for (; num_samples > 0; num_samples--, src+=sample_gap, dp++)
+               dp->ival = ((*src) << upshift) >> (16-KDU_FIX_POINT);
+         else
+            for (; num_samples > 0; num_samples--, src+=sample_gap, dp++)
+               dp->ival = (((*src) << upshift) - 0x8000) >> (16-KDU_FIX_POINT);
+      }
+      else
+      {
+         // Reversible processing
+         int downshift = 16-original_bits; assert(downshift >= 0);
+         if (is_signed)
+         {
+            for (; num_samples > 0; num_samples--, src+=sample_gap, dp++)
+            {
+               dp->ival = ((*src) << upshift) >> downshift;
+            }
+         }
+         else
+         {
+            for (; num_samples > 0; num_samples--, src+=sample_gap, dp++)
+            {
+               dp->ival = (((*src) << upshift) - 0x8000) >> downshift;
+            }
+         }
+      }
+   }
+   else
+   {
+      kdu_core::kdu_sample32 *dp = dest.get_buf32();
+      int upshift = 32-src_bits; assert(upshift >= 0);
+
+      if (!dest.is_absolute())
+      {
+         float scale = 1.0F / (((float)(1<<16)) * ((float)(1<<16)));
+         if (is_signed)
+            for (; num_samples > 0; num_samples--, src+=sample_gap, dp++)
+               dp->fval = scale * (float)(((kdu_core::kdu_int32) *src)<<upshift);
+         else
+            for (; num_samples > 0; num_samples--, src+=sample_gap, dp++)
+               dp->fval = scale * (float)((((kdu_core::kdu_int32) *src)<<upshift)-(1<<31));
+      }
+      else
+      {
+         int downshift = 32-original_bits; assert(downshift >= 0);
+         
+         if (is_signed)
+            for (; num_samples > 0; num_samples--, src+=sample_gap, dp++)
+            {
+               dp->ival = (((kdu_core::kdu_int32) *src)<<upshift) >> downshift;
+            }
+         else
+            for (; num_samples > 0; num_samples--, src+=sample_gap, dp++)
+               dp->ival = ((((kdu_core::kdu_int32) *src)<<upshift)-(1<<31)) >> downshift;
+      }
+   }
+}
+
+void transfer_dwords(kdu_core::kdu_line_buf &dest, kdu_core::kdu_int32 *src,
+                     int num_samples, int sample_gap, int src_bits, int original_bits,
+                     bool is_signed)
+{
+   if (dest.get_buf16() != NULL)
+   {
+      kdu_core::kdu_sample16 *dp = dest.get_buf16();
+      int upshift = 32-src_bits; assert(upshift >= 0);
+      if (!dest.is_absolute())
+      {
+         if (is_signed)
+            for (; num_samples > 0; num_samples--, src+=sample_gap, dp++)
+               dp->ival = (kdu_core::kdu_int16)
+                  (((*src) << upshift) >> (32-KDU_FIX_POINT));
+         else
+            for (; num_samples > 0; num_samples--, src+=sample_gap, dp++)
+               dp->ival = (kdu_core::kdu_int16)
+                  ((((*src) << upshift)-0x80000000) >> (32-KDU_FIX_POINT));
+      }
+      else
+      { // Reversible processing
+         int downshift = 32-original_bits; assert(downshift >= 0);
+         if (is_signed)
+            for (; num_samples > 0; num_samples--, src+=sample_gap, dp++)
+               dp->ival = (kdu_core::kdu_int16)
+                  (((*src) << upshift) >> downshift);
+         else
+            for (; num_samples > 0; num_samples--, src+=sample_gap, dp++)
+               dp->ival = (kdu_core::kdu_int16)
+                  ((((*src) << upshift) - 0x80000000) >> downshift);
+      }
+   }
+   else
+   {
+      kdu_core::kdu_sample32 *dp = dest.get_buf32();
+      int upshift = 32-src_bits; assert(upshift >= 0);
+      if (!dest.is_absolute())
+      {
+         float scale = 1.0F / (((float)(1<<16)) * ((float)(1<<16)));
+         if (is_signed)
+            for (; num_samples > 0; num_samples--, src+=sample_gap, dp++)
+               dp->fval = scale * (float)((*src)<<upshift);
+         else
+            for (; num_samples > 0; num_samples--, src+=sample_gap, dp++)
+               dp->fval = scale * (float)(((*src)<<upshift)-(1<<31));
+      }
+      else
+      {
+         int downshift = 32-original_bits; assert(downshift >= 0);
+         if (is_signed)
+            for (; num_samples > 0; num_samples--, src+=sample_gap, dp++)
+               dp->ival = ((*src)<<upshift) >> downshift;
+         else
+            for (; num_samples > 0; num_samples--, src+=sample_gap, dp++)
+               dp->ival = (((*src)<<upshift)-(1<<31)) >> downshift;
+      }
+   }
+}
+
+ossimKakaduCompressor::ossimKakaduCompressor()
+   : 
+   m_target(0),
+   m_jp2FamTgt(0),
+   m_jp2Target(0),
+   m_codestream(),
+   m_threadEnv(0),
+   m_threadQueue(0),
+   m_layerSpecCount(0),
+   m_layerByteSizes(0),
+   m_imageRect(),
+   m_reversible(true),
+   m_alpha(false),
+   m_levels(0),
+   m_threads(1),
+   m_options(),
+   m_qualityType(ossimKakaduCompressor::OKP_NUMERICALLY_LOSSLESS),
+   m_normTile(0)
+{
+}
+
+ossimKakaduCompressor::~ossimKakaduCompressor()
+{
+   finish();
+}
+
+void ossimKakaduCompressor::create(std::ostream* os,
+                                   ossimScalarType scalar,
+                                   ossim_uint32 bands,
+                                   const ossimIrect& imageRect,
+                                   const ossimIpt& tileSize,
+                                   ossim_uint32 tilesToWrite,
+                                   bool jp2)
+{
+   static const char MODULE[] = "ossimKakaduCompressor::create";
+   if ( traceDebug() )
+   {
+      ossimNotify(ossimNotifyLevel_WARN) << MODULE << " entered...\n";
+   }
+   
+#if 0 /* Please leave for debug. (drb) */
+   cout << "levels:      " << m_levels
+        << "\nreversible:  " << m_reversible
+        << "\nthreads:     " << m_threads
+        << "\nscalar:    " << scalar
+        << "\nbands:     " << bands
+        << "\nimageRect: " << imageRect
+        << "\ntileSize:  " << tileSize
+        << "\njp2:       " << jp2
+        << endl;
+#endif
+
+   // In case we were reused.
+   finish();
+
+   if ( !os )
+   {
+      std::string errMsg = MODULE;
+      errMsg += " ERROR: Null stream passed to method!";
+      throw ossimException(errMsg);
+   }
+   
+   if ( !os->good() )
+   {
+      std::string errMsg = MODULE;
+      errMsg += " ERROR: Stream state has error!";
+      throw ossimException(errMsg);
+   }
+   
+   if ( ossim::getActualBitsPerPixel(scalar) > 31 )
+   {
+      // Data is not reversible.
+      if ( m_reversible )
+      {
+         std::string errMsg = MODULE;
+         errMsg += " ERROR: Reversible processing not possible with 32 bit data!";
+         throw ossimException(errMsg);
+      }
+
+      // Create a tile for normalization.
+      m_normTile = new ossimImageData(0,
+                                      OSSIM_NORMALIZED_FLOAT,
+                                      bands,
+                                      static_cast<ossim_uint32>(tileSize.x),
+                                      static_cast<ossim_uint32>(tileSize.y));
+      m_normTile->initialize();
+   }
+   
+   // Store for tile clip.
+   m_imageRect = imageRect;
+   
+   m_target =  new ossimKakaduCompressedTarget();
+   m_target->setStream(os);
+   
+   if (jp2)
+   {
+      //---
+      // Note the jp2_family_tgt and the jp2_target classes merely store
+      // the target and do not delete on close or destroy.
+      //---
+      m_jp2FamTgt = new kdu_supp::jp2_family_tgt();
+      m_jp2FamTgt->open(m_target);
+      m_jp2Target = new kdu_supp::jp2_target();
+      m_jp2Target->open(m_jp2FamTgt);
+   }
+
+   if (m_alpha)
+   {
+      if ( (bands != 1) && (bands != 3) )
+      {
+         m_alpha = false;
+         if ( traceDebug() )
+         {
+            ossimNotify(ossimNotifyLevel_WARN)
+               << "Alpha channel being unset! Can only be used with "
+               << "one or three band data.\n"
+               << "Source image bands: " << bands << "\n";
+         }
+      }
+   }
+   
+   kdu_core::siz_params siz;
+   
+   // Set the bands:
+   siz.set(Scomponents, 0, 0, static_cast<ossim_int32>( (m_alpha?bands+1:bands) ) );
+   
+   // Set the verical size.
+   siz.set(Ssize, 0, 0, static_cast<ossim_int32>(imageRect.height()));
+   siz.set(Sdims, 0, 0, static_cast<ossim_int32>(imageRect.height()));
+   
+   // Set the horizontal size.
+   siz.set(Ssize, 0, 1, static_cast<ossim_int32>(imageRect.width()));
+   siz.set(Sdims, 0, 1, static_cast<ossim_int32>(imageRect.width()));
+   
+   // Set the tile verical size.
+   siz.set(Stiles, 0, 0, tileSize.y);
+   
+   // Set the tile horizontal size.
+   siz.set(Stiles, 0, 1, tileSize.x);
+   
+   // Set the signed bit.
+   siz.set(Ssigned, 0, 0, ossim::isSigned(scalar));
+   
+   // Set the precision bits.
+   siz.set(Sprecision, 0, 0,
+           static_cast<ossim_int32>(ossim::getActualBitsPerPixel(scalar)) );
+   
+   siz.finalize_all();
+
+   // Set up threads:
+   m_threadEnv = new kdu_core::kdu_thread_env();
+   m_threadEnv->create();
+   if ( m_threads == 1 )
+   {
+      // Look in prefs for threads:
+      const char* lookup = ossimPreferences::instance()->findPreference("kakadu_threads");
+      if ( lookup )
+      {
+         m_threads = ossimString::toUInt32(lookup);
+      }
+   }
+   if ( m_threads > 1 )
+   {
+      for (int nt=1; nt < m_threads; ++nt)
+      {
+         if ( !m_threadEnv->add_thread() )
+         {
+            if (traceDebug())
+            {
+               ossimNotify(ossimNotifyLevel_WARN)
+                  << "Unable to create thread!\n";
+            }
+         }
+      }
+   }
+   
+   m_threadQueue = m_threadEnv->add_queue(0, 0, "tile-compressor-root");
+   
+   kdu_supp::jp2_dimensions dims;
+   
+   if (jp2)
+   {
+      //---
+      // Configure jp2 header attributes jp2_dimensions', `
+      // jp2_colour', `jp2_channels', etc.) as appropriate.
+      //---
+      
+      //---
+      // Set dimensional information
+      // (all redundant with the SIZ marker segment)
+      //---
+      dims = m_jp2Target->access_dimensions();
+      dims.init(&siz);
+      
+      //---
+      // Set colour space information (mandatory)
+      // Since JP2 can only describe one and three band data if not three
+      // band we will use the first channel only.
+      //----
+      kdu_supp::jp2_colour colour = m_jp2Target->access_colour();
+      if (bands == 3)
+      {
+         colour.init( kdu_supp::JP2_sRGB_SPACE );
+      }
+      else
+      {
+         colour.init( kdu_supp::JP2_sLUM_SPACE );
+      }
+      
+      //---
+      // Set the channel mapping.  See note on colour space.
+      //---
+      int num_colours = static_cast<int>( (bands==3)?bands:1 );
+      kdu_supp::jp2_channels channels = m_jp2Target->access_channels();
+      channels.init(num_colours);
+      for (int c=0; c < num_colours; ++c)
+      {
+         channels.set_colour_mapping(c,c);
+      }
+      
+      if (m_alpha)
+      {
+         if (bands == 1)
+         {
+            channels.set_opacity_mapping(0,1);
+         }
+         else if (bands == 3)
+         {
+            channels.set_opacity_mapping(0,3);
+            channels.set_opacity_mapping(1,3);
+            channels.set_opacity_mapping(2,3);               
+         }
+      }
+      
+      m_codestream.create(&siz, m_jp2Target, 0, 0, 0, m_threadEnv);
+   }
+   else // Not a jp2
+   {
+      m_codestream.create(&siz, m_target, 0, 0, 0, m_threadEnv);
+   }
+   
+   // Requests the insertion of TLM (tile-part-length) marker.
+   setTlmTileCount(tilesToWrite);
+   
+   //---
+   // Set up coding defaults.
+   //---
+   kdu_core::kdu_params* cod = m_codestream.access_siz()->access_cluster(COD_params);
+   if (cod)
+   {
+      initializeCodingParams(cod, imageRect);
+   }
+
+   
+   // Set options if any.
+   std::vector<ossimString>::const_iterator optionIter = m_options.begin();
+   while ( optionIter != m_options.end() )
+   {
+      m_codestream.access_siz()->parse_string( (*optionIter).c_str() );
+      ++optionIter;
+   }
+   
+   // Finalize preparation for compression
+   m_codestream.access_siz()->finalize_all();
+   
+   if (jp2)
+   {
+      // Call `write_header' to write the JP2 header.
+      m_jp2Target->write_header();
+      m_jp2Target->close();
+      
+      // Write out the geotiff_box:
+      // writeGeotffBox(m_jp2Target);
+      
+      //---
+      // Optionally write additional boxes, opening them using the base
+      // object's
+      // `jp2_output_box::open_next' function, writing their contents (or
+      // sub-boxes) and closing them using `jp2_output_box::close'.
+      //---
+   }
+
+   if ( traceDebug() )
+   {
+      ossimNotify(ossimNotifyLevel_WARN) << MODULE << " exiting...\n";
+   }
+}
+
+void ossimKakaduCompressor::openJp2Codestream()
+{
+   if (m_jp2Target)
+
+   {
+      //---
+      // Call `open_codestream' prior to any call to
+      // `kdu_codestream::flush'.
+      //---
+      m_jp2Target->open_codestream(true);
+   }
+}
+
+bool ossimKakaduCompressor::writeTile(ossimImageData& srcTile)
+{
+   bool result = true;
+
+   if (srcTile.getDataObjectStatus() != OSSIM_NULL)
+   {
+      // tile samples:
+      const ossim_int32 TILE_SAMPS =
+         static_cast<ossim_int32>(srcTile.getWidth());
+
+      // Samples to copy clipping to image width:
+      const ossim_int32 SAMPS =
+         ossim::min(TILE_SAMPS, m_imageRect.lr().x-srcTile.getOrigin().x+1);
+      
+      // tile lines:
+      const ossim_int32 TILE_LINES =
+         static_cast<ossim_int32>(srcTile.getHeight());
+
+      // Lines to copy:
+      const ossim_int32 LINES =
+         ossim::min(TILE_LINES, m_imageRect.lr().y-srcTile.getOrigin().y+1);
+      
+      // Get the tile index.
+      kdu_core::kdu_coords tileIndex;
+      tileIndex.x = (srcTile.getOrigin().x - m_imageRect.ul().x) / TILE_SAMPS;
+      tileIndex.y = (srcTile.getOrigin().y - m_imageRect.ul().y) / TILE_LINES;
+
+      kdu_core::kdu_tile tile = m_codestream.open_tile(tileIndex);
+
+      kdu_core::kdu_dims tile_dims;
+      m_codestream.get_tile_dims(tileIndex, 0, tile_dims);
+
+      if ( tile.exists() )
+      {  
+         // Bands:
+         const ossim_int32 BANDS =
+            static_cast<ossim_int32>(m_alpha?srcTile.getNumberOfBands()+1:
+                                     srcTile.getNumberOfBands());
+
+         tile.set_components_of_interest(BANDS);
+         
+         // Scalar:
+         const ossimScalarType SCALAR = srcTile.getScalarType();
+         
+         // Signed:
+         const bool SIGNED = ossim::isSigned(SCALAR);
+         
+         // Set up common things to both scalars.
+         std::vector<kdu_core::kdu_push_ifc> engine(BANDS);
+         std::vector<kdu_core::kdu_line_buf> lineBuf(BANDS);
+
+         // Precision:
+         ossim_int32 src_bits = ossim::getActualBitsPerPixel(SCALAR);
+
+         std::vector<ossim_int32> original_bits(BANDS);
+
+         // Initialize tile-components 
+         kdu_core::kdu_tile_comp tc;
+         kdu_core::kdu_resolution res;
+         bool reversible;
+         bool use_shorts;
+         kdu_core::kdu_sample_allocator allocator;
+
+         ossim_int32 band;
+         for (band = 0; band < BANDS; ++band)
+         {
+            original_bits[band] = m_codestream.get_bit_depth(band,true);
+
+            tc = tile.access_component(band);
+            res = tc.access_resolution();
+            if ( ossim::getActualBitsPerPixel(SCALAR) > 31 )
+            {
+               // Data is not reversible.
+               reversible = false;
+               use_shorts = false;
+            }
+            else
+            {
+               reversible = tc.get_reversible();
+               use_shorts = (tc.get_bit_depth(true) <= 16);
+            }
+            
+            res.get_dims(tile_dims);
+
+            engine[band] = kdu_core::kdu_analysis(res,
+                                        &allocator,
+                                        use_shorts,
+                                        1.0F,
+                                        0,
+                                        m_threadEnv,
+                                        m_threadQueue);
+
+            lineBuf[band].pre_create(&allocator,
+                                     SAMPS,
+                                     reversible, // tmp drb
+                                     use_shorts,
+                                     0,          // extend_left
+                                     0);         // extend_right
+         }
+         
+         // Complete sample buffer allocation
+         allocator.finalize( m_codestream );
+
+         for (band = 0; band < BANDS; ++band)
+         {
+            lineBuf[band].create();
+         }
+
+         switch (SCALAR)
+         {
+            case OSSIM_UINT8:
+            {
+               std::vector<kdu_core::kdu_byte*> srcBuf(BANDS);
+               for (band = 0; band < BANDS; ++band)
+               {
+                  void* p = const_cast<void*>(srcTile.getBuf(band));
+                  srcBuf[band] = static_cast<kdu_core::kdu_byte*>(p);
+               }
+               if (m_alpha)
+               {
+                  // Ugly casting...
+                  const void* cp =
+                     static_cast<const void*>(srcTile.getAlphaBuf());
+                  void* p = const_cast<void*>(cp);
+                  srcBuf[BANDS-1] = static_cast<kdu_core::kdu_byte*>(p);
+               }
+               for (ossim_int32 line = 0; line < LINES; ++line)
+               {
+                  for (band = 0; band < BANDS; ++band)
+                  {
+                     transfer_bytes(lineBuf[band],
+                                    srcBuf[band],
+                                    SAMPS,
+                                    1,
+                                    src_bits,
+                                    original_bits[band]);
+                     
+                     engine[band].push(lineBuf[band], m_threadEnv);
+
+                     // Increment the line buffers.
+                     srcBuf[band] = srcBuf[band]+TILE_SAMPS;
+                  }
+               }
+               break;
+            }
+            case OSSIM_USHORT11:
+            case OSSIM_UINT16:
+            {
+               if (!m_alpha)
+               {
+                  std::vector<kdu_core::kdu_int16*> srcBuf(BANDS);
+                  for (band = 0; band < BANDS; ++band)
+                  {
+                     void* p = const_cast<void*>(srcTile.getBuf(band));
+                     srcBuf[band] = static_cast<kdu_core::kdu_int16*>(p);
+                  }
+                  
+                  for (ossim_int32 line = 0; line < LINES; ++line)
+                  {
+                     for (band = 0; band < BANDS; ++band)
+                     {
+                        transfer_words(lineBuf[band],
+                                       srcBuf[band],
+                                       SAMPS,
+                                       1,
+                                       src_bits,
+                                       original_bits[band],
+                                       SIGNED);
+                     
+                        engine[band].push(lineBuf[band], m_threadEnv);
+                     
+                        // Increment the line buffers.
+                        srcBuf[band] = srcBuf[band]+TILE_SAMPS;
+                     }
+                  }
+               }
+               else // Need to write an alpha channel.
+               {
+                  //---
+                  // Alpha currently stored a eight bit so we must move 255 to
+                  // 2047 (11 bit) or 255 to 65535 for 16 bit.
+                  //---
+                  ossim_float64 d = 0.0;
+                  if (SCALAR == OSSIM_USHORT11)
+                  {
+                     d = 2047.0/255.0;
+                  }
+                  else
+                  {
+                     d = 65535/255.0;
+                  }
+
+                  ossim_int32 dataBands = BANDS-1;
+                  std::vector<kdu_core::kdu_int16*> srcBuf(dataBands);
+                  for (band = 0; band < dataBands; ++band)
+                  {
+                     void* p = const_cast<void*>(srcTile.getBuf(band));
+                     srcBuf[band] = static_cast<kdu_core::kdu_int16*>(p);
+                  }
+                  
+                  const ossim_uint8* alphaPtr = srcTile.getAlphaBuf();;
+                  std::vector<kdu_core::kdu_int16> alphaLine(SAMPS);
+                  
+                  for (ossim_int32 line = 0; line < LINES; ++line)
+                  {
+                     for (band = 0; band < dataBands; ++band)
+                     {
+                        transfer_words(lineBuf[band],
+                                       srcBuf[band],
+                                       SAMPS,
+                                       1,
+                                       src_bits,
+                                       original_bits[band],
+                                       SIGNED);
+                        
+                        engine[band].push(lineBuf[band], m_threadEnv);
+                        
+                        // Increment the line buffers.
+                        srcBuf[band] = srcBuf[band]+TILE_SAMPS;
+                     }
+                     
+                     // Transfer alpha channel:
+                     for (ossim_int32 samp = 0; samp < SAMPS; ++samp)
+                     {
+                        alphaLine[samp] = static_cast<kdu_core::kdu_int16>(alphaPtr[samp]*d);
+                     }
+
+                     transfer_words(lineBuf[band],
+                                    &alphaLine.front(),
+                                    SAMPS,
+                                    1,
+                                    src_bits,
+                                    original_bits[band],
+                                    SIGNED);
+                     
+                     engine[band].push(lineBuf[band], m_threadEnv);
+                     
+                     alphaPtr = alphaPtr+TILE_SAMPS;
+                  }
+               } // End of alpha section.
+               break;
+            }
+            case OSSIM_SINT16:
+            {
+               std::vector<ossim_sint16*> srcBuf(BANDS);
+               for (band = 0; band < BANDS; ++band)
+               {
+                  void* p = const_cast<void*>(srcTile.getBuf(band));
+                  srcBuf[band] = static_cast<ossim_sint16*>(p);
+               }
+
+               for (ossim_int32 line = 0; line < LINES; ++line)
+               {
+                  for (band = 0; band < BANDS; ++band)
+                  {
+                     transfer_words(lineBuf[band],
+                                    srcBuf[band],
+                                    SAMPS,
+                                    1,
+                                    src_bits,
+                                    original_bits[band],
+                                    SIGNED);
+                     
+                     engine[band].push(lineBuf[band], m_threadEnv);
+
+                     // Increment the line buffers.
+                     srcBuf[band] = srcBuf[band]+TILE_SAMPS;
+                  }
+               }
+               break;
+            }
+
+            //---
+            // ??? This should probably take the same path as OSSIM_SINT32 data.
+            // Need test case.
+            //---
+            case OSSIM_UINT32:
+            {
+               std::vector<kdu_core::kdu_int32*> srcBuf(BANDS);
+               for (band = 0; band < BANDS; ++band)
+               {
+                  void* p = const_cast<void*>(srcTile.getBuf(band));
+                  srcBuf[band] = static_cast<kdu_core::kdu_int32*>(p);
+               }
+               
+               for (ossim_int32 line = 0; line < LINES; ++line)
+               {
+                  for (band = 0; band < BANDS; ++band)
+                  {
+                     transfer_dwords(lineBuf[band],
+                                     srcBuf[band],
+                                     SAMPS,
+                                     1,
+                                     src_bits,
+                                     original_bits[band],
+                                     SIGNED);
+                     
+                     engine[band].push(lineBuf[band], m_threadEnv);
+                     
+                     // Increment the line buffers.
+                     srcBuf[band] = srcBuf[band]+TILE_SAMPS;
+                  }
+               }
+               break;  
+            }
+
+            case OSSIM_SINT32:
+            case OSSIM_FLOAT32:
+            {
+               //---
+               // Kakadu wants float data normalized between -0.5 and 0.5:
+               // 1) Normalize between 0.0 and 1.0 using ossim code.
+               // 2) Copy applying -0.5 offset.
+               //---
+               srcTile.copyTileToNormalizedBuffer(m_normTile->getFloatBuf());
+               
+               std::vector<ossim_float32*> srcBuf(BANDS);
+               for (band = 0; band < BANDS; ++band)
+               {
+                  srcBuf[band] = m_normTile->getFloatBuf(band);
+               }
+
+               for (ossim_int32 line = 0; line < LINES; ++line)
+               {
+                  for (band = 0; band < BANDS; ++band)
+                  {
+                     kdu_core::kdu_sample32* dp = lineBuf[band].get_buf32();
+                     for (ossim_int32 samp = 0; samp < SAMPS; ++samp)
+                     {
+                        dp[samp].fval = srcBuf[band][samp] - 0.5; // -.5 for kakadu.
+                     }
+                     engine[band].push(lineBuf[band], m_threadEnv);
+
+                     // Increment the line buffers.
+                     srcBuf[band] = srcBuf[band]+TILE_SAMPS;
+                  }
+               }
+               break;
+            }
+            default:
+            {
+               ossimNotify(ossimNotifyLevel_WARN)
+                  << __FILE__ << " " << __LINE__ << " Unhandle scalar!\n";
+               result = false;
+               break;
+            }
+            
+         }  // End:  switch(scalar)
+
+         if (m_threadEnv)
+         {
+            // m_threadEnv->synchronize(m_threadQueue);
+
+            //---
+            // Snip from kdu_threads.h:
+            // If `descendants_only' is true, the function waits for all queues
+            // descended from `root_queue' to identify themselves as "finished"
+            // via the `kdu_thread_queue::all_done' function.
+            //---
+            m_threadEnv->join(m_threadQueue,
+                              true); // descendants_only flag
+         }
+         
+         for (band = 0; band < BANDS; ++band)
+         {
+            engine[band].destroy();
+            lineBuf[band].destroy();
+         }
+         tile.close();
+         allocator.restart();
+
+         // Done with tile flush it...
+         m_codestream.flush( &(m_layerByteSizes.front()),  // layerbytes,
+                             m_layerSpecCount,        // num_layer_specs
+                             0, // layer_thresholds
+                             true, // trim_to_rate
+                             true, // record_in_comseg
+                             0.0, // tolerence,
+                             m_threadEnv); // env
+         
+      } // if (tile.exists())
+      else
+      {
+         result = false;
+      }
+   }
+   else // srcTile has null status...
+   {
+      result = false;
+   }
+
+   return result;
+   
+} // End: ossimKakaduCompressor::writeTile
+
+void ossimKakaduCompressor::finish()
+{
+   // Kakadu kdu_thread_entity::terminate throws exceptions...
+   try
+   {
+      // Cleanup processing environment
+      if ( m_threadEnv )
+      {
+         m_threadEnv->join(NULL,true); // Wait until all internal processing is complete.
+         m_threadEnv->terminate(m_threadQueue, true);      
+         m_threadEnv->cs_terminate(m_codestream);   // Terminates background codestream processing.
+
+         // kdu_codestream::destroy causing "double free or corruption" exception.
+         // m_codestream.destroy();
+
+         m_threadEnv->destroy();
+         delete m_threadEnv;
+         m_threadEnv = 0;
+      }
+      
+      m_normTile = 0;
+      
+      if (m_threadQueue)
+      {
+         m_threadQueue = 0;
+      }
+      
+      if (m_jp2FamTgt)
+      {
+         delete m_jp2FamTgt;
+         m_jp2FamTgt = 0;
+      }
+      
+      if (m_jp2Target)
+      {
+         delete m_jp2Target;
+         m_jp2Target = 0;
+      }
+      
+      if (m_target)
+      {
+         delete m_target;
+         m_target = 0;
+      }
+   }
+   catch ( kdu_core::kdu_exception exc )
+   {
+      // kdu_exception is an int typedef.
+      if ( m_threadEnv != 0 )
+      {
+         m_threadEnv->handle_exception(exc);
+      }
+      ostringstream e;
+      e << "ossimKakaduNitfReader::~ossimKakaduNitfReader\n"
+        << "Caught exception from kdu_region_decompressor: " << exc << "\n";
+      ossimNotify(ossimNotifyLevel_WARN) << e.str() << std::endl;
+   }
+   catch ( std::bad_alloc& )
+   {
+      if ( m_threadEnv != 0 )
+      {
+         m_threadEnv->handle_exception(KDU_MEMORY_EXCEPTION);
+      }
+      std::string e =
+         "Caught exception from kdu_region_decompressor: std::bad_alloc";
+      ossimNotify(ossimNotifyLevel_WARN) << e << std::endl;
+   }
+   catch( ... )
+   {
+      std::string e =
+         "Caught unhandled exception from kdu_region_decompressor";
+      ossimNotify(ossimNotifyLevel_WARN) << e << std::endl;
+   }
+   
+   m_layerByteSizes.clear();
+}
+
+void ossimKakaduCompressor::setQualityType(ossimKakaduCompressionQuality type)
+{
+   m_qualityType = type;
+
+   //---
+   // Set the reversible flag for appropriate type.
+   // Not sure what to set for unknown and user defined but visually lossless
+   // and lossy need to set the reversible flag to false.
+   //---
+   if ( (type == ossimKakaduCompressor::OKP_VISUALLY_LOSSLESS) ||
+        (type == ossimKakaduCompressor::OKP_LOSSY) )
+   {
+      setReversibleFlag(false);
+   }
+   else
+   {
+      setReversibleFlag(true);
+   }
+}
+
+ossimKakaduCompressor::ossimKakaduCompressionQuality ossimKakaduCompressor::getQualityType() const
+{
+   return m_qualityType;
+   
+}
+
+void ossimKakaduCompressor::setReversibleFlag(bool reversible)
+{
+   m_reversible = reversible;
+}
+
+bool ossimKakaduCompressor::getReversibleFlag() const
+{
+   return m_reversible;
+}
+
+void ossimKakaduCompressor::setAlphaChannelFlag(bool flag)
+{
+   m_alpha = flag;
+}
+
+bool ossimKakaduCompressor::getAlphaChannelFlag() const
+{
+   return m_alpha;
+}
+
+void ossimKakaduCompressor::setLevels(ossim_int32 levels)
+{
+   if (levels)
+   {
+      m_levels = levels;
+   }
+}
+
+ossim_int32 ossimKakaduCompressor::getLevels() const
+{
+   return m_levels;
+}
+
+void ossimKakaduCompressor::setThreads(ossim_int32 threads)
+{
+   if (threads)
+   {
+      m_threads = threads;
+   }
+}
+
+ossim_int32 ossimKakaduCompressor::getThreads() const
+{
+   return m_threads;
+}
+
+void ossimKakaduCompressor::setOptions(const std::vector<ossimString>& options)
+{
+   std::vector<ossimString>::const_iterator i = options.begin();
+   while ( i != options.end() )
+   {
+      m_options.push_back( (*i) );
+      ++i;
+   }
+}
+
+bool ossimKakaduCompressor::setProperty(ossimRefPtr<ossimProperty> property)
+{
+   bool consumed = false;
+   
+   if ( property.valid() )
+   {
+      ossimString key = property->getName();
+
+      if ( traceDebug() )
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG)
+            << "ossimKakaduCompressor::setProperty DEBUG:"
+            << "\nkey: " << key
+            << " values: " << property->valueToString() << std::endl;
+      }
+      
+      if (key == ossimKeywordNames::COMPRESSION_QUALITY_KW)
+      {
+         setQualityTypeString(property->valueToString());
+         consumed = true;
+      }
+      else if ( (key == LEVELS_KW) || (key ==  "Clevels") )
+      {
+         m_levels = property->valueToString().toInt32();
+         consumed = true;
+      }
+      else if( (key == REVERSIBLE_KW) || (key == "Creversible") )
+      {
+         setReversibleFlag(property->valueToString().toBool());
+         consumed = true;
+      }
+      else if (key == ADD_ALPHA_CHANNEL_KW)
+      {
+         m_alpha = property->valueToString().toBool();
+         consumed = true;
+      }
+      else if ( key == THREADS_KW)
+      {
+         m_threads = property->valueToString().toInt32();
+         consumed = true;
+      }
+      else if ( (key == "Clayers") ||
+                (key == "Cprecincts") )
+      {
+         // Generic options passed through kdu_params::parse_string.
+
+         // Make in the form of "key=value" for kdu_params::parse_string.
+         ossimString option = key;
+         option += "=";
+         option += property->valueToString();
+         
+         // Add to list.
+         m_options.push_back(option);
+         
+         consumed = true;
+      } 
+   }
+
+   return consumed;
+}
+
+ossimRefPtr<ossimProperty> ossimKakaduCompressor::getProperty(
+   const ossimString& name)const
+{
+   ossimRefPtr<ossimProperty> p = 0;
+
+   if (name == ossimKeywordNames::COMPRESSION_QUALITY_KW)
+   {
+      // property value
+      ossimString value = getQualityTypeString();
+
+      if ( (value == COMPRESSION_QUALITY[ossimKakaduCompressor::OKP_USER_DEFINED] ) ||
+           (value == COMPRESSION_QUALITY[ossimKakaduCompressor::OKP_UNKNOWN])
+          )
+      {
+         value = COMPRESSION_QUALITY[ossimKakaduCompressor::OKP_NUMERICALLY_LOSSLESS];
+      }
+         
+      // constraint list
+      vector<ossimString> constraintList;
+      constraintList.push_back(COMPRESSION_QUALITY[ossimKakaduCompressor::
+                                                   OKP_NUMERICALLY_LOSSLESS]);
+      constraintList.push_back(COMPRESSION_QUALITY[ossimKakaduCompressor::
+                                                   OKP_VISUALLY_LOSSLESS]);
+      constraintList.push_back(COMPRESSION_QUALITY[ossimKakaduCompressor::
+                                                   OKP_LOSSY]);
+      
+      p = new ossimStringProperty(name,
+                                  value,
+                                  false, // not editable
+                                  constraintList);
+   }
+   else if (name == LEVELS_KW)
+   {
+      p = new ossimNumericProperty(name, ossimString::toString(m_levels));
+   }
+   else if (name == REVERSIBLE_KW)
+   {
+      p = new ossimBooleanProperty(name, m_reversible);
+   }
+   else if (name == ADD_ALPHA_CHANNEL_KW)
+   {
+      p = new ossimBooleanProperty(name, m_alpha);
+   }
+   else if (name == THREADS_KW)
+   {
+      p = new ossimNumericProperty(name, ossimString::toString(m_threads));
+   }   
+   
+   return p;
+}
+
+void ossimKakaduCompressor::getPropertyNames(
+   std::vector<ossimString>& propertyNames)const
+{
+   propertyNames.push_back(ossimKeywordNames::COMPRESSION_QUALITY_KW);
+   propertyNames.push_back(LEVELS_KW);
+   propertyNames.push_back(REVERSIBLE_KW);
+   propertyNames.push_back(THREADS_KW);
+}
+
+bool ossimKakaduCompressor::saveState(ossimKeywordlist& kwl,
+                                      const char* prefix)const
+{
+   kwl.add( prefix,
+            ossimKeywordNames::COMPRESSION_QUALITY_KW,
+            getQualityTypeString().c_str(),
+            true );
+   
+   kwl.add( prefix,
+            LEVELS_KW,
+            ossimString::toString(m_levels),
+            true );
+   
+   kwl.add( prefix,
+            REVERSIBLE_KW,
+            ossimString::toString(m_reversible),
+            true );
+
+   kwl.add( prefix,
+            ADD_ALPHA_CHANNEL_KW,
+            ossimString::toString(m_alpha),
+            true ); 
+   
+   kwl.add( prefix,
+            THREADS_KW,
+            ossimString::toString(m_threads),
+            true );
+
+   std::vector<ossimString>::size_type size = m_options.size();
+   for (ossim_uint32 i = 0; i < size; ++i)
+   {
+      ossimString key = "option";
+      key += ossimString::toString(i);
+      
+      kwl.add( prefix,
+               key.c_str(),
+               m_options[i].c_str(),
+               true );
+   }
+   
+   return true;
+}
+
+bool ossimKakaduCompressor::loadState(const ossimKeywordlist& kwl,
+                                      const char* prefix)
+{
+   const char* value = 0;
+
+   value = kwl.find(prefix, ossimKeywordNames::COMPRESSION_QUALITY_KW);
+   if(value)
+   {
+      setQualityTypeString( ossimString(value) );
+   }
+   
+   value = kwl.find(prefix, LEVELS_KW);
+   if(value)
+   {
+      m_levels = ossimString(value).toInt32();
+   }
+   
+   value = kwl.find(prefix, REVERSIBLE_KW);
+   if(value)
+   {
+      setReversibleFlag(ossimString(value).toBool());
+   }
+
+   value = kwl.find(prefix, ADD_ALPHA_CHANNEL_KW);
+   if(value)
+   {
+      m_alpha = ossimString(value).toBool();
+   }
+   
+   value = kwl.find(prefix, THREADS_KW);
+   if(value)
+   {
+      m_threads = ossimString(value).toInt32();
+   }
+
+   ossimString searchKey;
+   if (prefix)
+   {
+      searchKey = prefix;
+   }
+   searchKey += "option";
+   ossim_uint32 nOptions = kwl.numberOf(searchKey);
+   for (ossim_uint32 i = 0; i < nOptions; ++i)
+   {
+      ossimString key = searchKey;
+      key += ossimString::toString(i);
+      
+      const char* lookup = kwl.find(key.c_str());
+      if (lookup)
+      {
+         m_options.push_back(ossimString(lookup));
+      }
+   }
+   
+   return true;
+}
+
+
+bool ossimKakaduCompressor::writeGeotiffBox(const ossimImageGeometry* geom,
+                                            const ossimIrect& rect,
+                                            const ossimFilename& tmpFile,
+                                            ossimPixelType pixelType)
+{
+   bool result = false;
+   
+   if ( geom && m_jp2Target )
+   {
+      ossimRefPtr<const ossimImageGeometry> imgGeom = geom;
+      ossimRefPtr<const ossimProjection> proj = imgGeom->getProjection();
+      if ( proj.valid() )
+      {
+         //---
+         // Make a temp file.  No means currently write a tiff straight to
+         // memory.
+         //---
+         
+         // Buffer to hold the tiff box.
+         std::vector<ossim_uint8> buf;
+
+         // Write to buffer.
+         if ( ossimGeoTiff::writeJp2GeotiffBox(tmpFile,
+                                               rect,
+                                               proj.get(),
+                                               buf,
+                                               pixelType) )
+         {
+            //---
+            // JP2 box type uuid in ascii expressed as an int.
+            // "u(75), u(75), i(69), d(64"
+            //---
+            const ossim_uint32 UUID_TYPE = 0x75756964;
+            
+            // Write to a box on the JP2 file.
+            m_jp2Target->open_next( UUID_TYPE );
+            m_jp2Target->write(
+               static_cast<kdu_core::kdu_byte*>(&buf.front()), static_cast<int>(buf.size()));
+            
+            m_jp2Target->close();
+            result = true;
+         }
+      }
+   }
+
+   return result;
+   
+} // End: ossimKakaduCompressor::writeGeotiffBox
+
+void ossimKakaduCompressor::initializeCodingParams(kdu_core::kdu_params* cod,
+                                                   const ossimIrect& imageRect)
+{
+   static const char MODULE[] = "ossimKakaduCompressor::initializeCodingParams";
+   
+   if ( traceDebug() )
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " entered...\n";
+   }
+   
+   if (cod)
+   {
+      // No ycc.
+      cod->set(Cycc, 0, 0, false);
+
+      // Set the number of levels
+      setLevels(cod, imageRect, m_levels);
+
+      // Set the block size.  Note 64x64 is the current kakadu default.
+      setCodeBlockSize(cod, 64, 64);
+
+      //---
+      // Set the compression order.  Note LRCP is the current kakadu default.
+      // L=layer; R=resolution C=component; P=position
+      //---
+      setProgressionOrder(cod, Corder_LRCP);
+      
+      // total pixels
+      const ossim_float64 TP = imageRect.area();
+
+      if ( traceDebug() )
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG)
+            << "quality type: " << getQualityTypeString() << endl;
+      }
+
+      //---
+      // Rate is a ratio of desired bytes / total bytes.  So if you
+      // want 4 bits per pixels it's total_pixels * 4 / 8 or
+      // total_pixels * 4 * 0.125.
+      //---
+      
+      switch (m_qualityType)
+      {
+         case ossimKakaduCompressor::OKP_NUMERICALLY_LOSSLESS:
+         {
+            setReversibleFlag(true);
+
+            setWaveletKernel(cod, Ckernels_W5X3);
+            
+            m_layerSpecCount = 20;
+            m_layerByteSizes.resize(m_layerSpecCount);
+
+            m_layerByteSizes[0] =
+               static_cast<kdu_core::kdu_long>(std::ceil( TP * 0.03125 * 0.125 ));
+            m_layerByteSizes[1] =
+               static_cast<kdu_core::kdu_long>(std::ceil(TP * 0.0625* 0.125 ));
+            m_layerByteSizes[2] =
+               static_cast<kdu_core::kdu_long>(std::ceil(TP * 0.125* 0.125 ));
+            m_layerByteSizes[3] =
+               static_cast<kdu_core::kdu_long>(std::ceil(TP * 0.25* 0.125 ));
+            m_layerByteSizes[4] =
+               static_cast<kdu_core::kdu_long>(std::ceil(TP * 0.5* 0.125 ));
+            m_layerByteSizes[5] =
+               static_cast<kdu_core::kdu_long>(std::ceil(TP * 0.6* 0.125 ));
+            m_layerByteSizes[6] =
+               static_cast<kdu_core::kdu_long>(std::ceil(TP * 0.7* 0.125 ));
+            m_layerByteSizes[7] =
+               static_cast<kdu_core::kdu_long>(std::ceil(TP * 0.8* 0.125 ));
+            m_layerByteSizes[8] =
+               static_cast<kdu_core::kdu_long>(std::ceil(TP * 0.9* 0.125 ));
+            m_layerByteSizes[9] =
+               static_cast<kdu_core::kdu_long>(std::ceil(TP * 1.0* 0.125 ));
+            m_layerByteSizes[10] =
+               static_cast<kdu_core::kdu_long>(std::ceil(TP * 1.1* 0.125 ));
+            m_layerByteSizes[11] =
+               static_cast<kdu_core::kdu_long>(std::ceil(TP * 1.2* 0.125 ));
+            m_layerByteSizes[12] =
+               static_cast<kdu_core::kdu_long>(std::ceil(TP * 1.3* 0.125 ));
+            m_layerByteSizes[13] =
+               static_cast<kdu_core::kdu_long>(std::ceil(TP * 1.5* 0.125 ));
+            m_layerByteSizes[14] =
+               static_cast<kdu_core::kdu_long>(std::ceil(TP * 1.7* 0.125 ));
+            m_layerByteSizes[15] =
+               static_cast<kdu_core::kdu_long>(std::ceil(TP * 2.0* 0.125 ));
+            m_layerByteSizes[16] =
+               static_cast<kdu_core::kdu_long>(std::ceil(TP * 2.3* 0.125 ));
+            m_layerByteSizes[17] =
+               static_cast<kdu_core::kdu_long>(std::ceil(TP * 2.8* 0.125 ));
+            m_layerByteSizes[18] =
+               static_cast<kdu_core::kdu_long>(std::ceil(TP * 3.5* 0.125 ));
+
+            //---
+            // Indicate that the final quality layer should include all
+            // compressed bits.
+            //---
+            m_layerByteSizes[19] = KDU_LONG_MAX;
+
+            break;
+         }
+         case ossimKakaduCompressor::OKP_VISUALLY_LOSSLESS:
+         {
+            setReversibleFlag(false);
+            
+            setWaveletKernel(cod, Ckernels_W9X7);
+            
+            m_layerSpecCount = 19;
+            m_layerByteSizes.resize(m_layerSpecCount);
+            m_layerByteSizes[0] =
+               static_cast<kdu_core::kdu_long>(std::ceil( TP * 0.03125 * 0.125 ));
+            m_layerByteSizes[1] =
+               static_cast<kdu_core::kdu_long>(std::ceil(TP * 0.0625* 0.125 ));
+            m_layerByteSizes[2] =
+               static_cast<kdu_core::kdu_long>(std::ceil(TP * 0.125* 0.125 ));
+            m_layerByteSizes[3] =
+               static_cast<kdu_core::kdu_long>(std::ceil(TP * 0.25* 0.125 ));
+            m_layerByteSizes[4] =
+               static_cast<kdu_core::kdu_long>(std::ceil(TP * 0.5* 0.125 ));
+            m_layerByteSizes[5] =
+               static_cast<kdu_core::kdu_long>(std::ceil(TP * 0.6* 0.125 ));
+            m_layerByteSizes[6] =
+               static_cast<kdu_core::kdu_long>(std::ceil(TP * 0.7* 0.125 ));
+            m_layerByteSizes[7] =
+               static_cast<kdu_core::kdu_long>(std::ceil(TP * 0.8* 0.125 ));
+            m_layerByteSizes[8] =
+               static_cast<kdu_core::kdu_long>(std::ceil(TP * 0.9* 0.125 ));
+            m_layerByteSizes[9] =
+               static_cast<kdu_core::kdu_long>(std::ceil(TP * 1.0* 0.125 ));
+            m_layerByteSizes[10] =
+               static_cast<kdu_core::kdu_long>(std::ceil(TP * 1.1* 0.125 ));
+             m_layerByteSizes[11] =
+               static_cast<kdu_core::kdu_long>(std::ceil(TP * 1.2* 0.125 ));
+            m_layerByteSizes[12] =
+               static_cast<kdu_core::kdu_long>(std::ceil(TP * 1.3* 0.125 ));
+            m_layerByteSizes[13] =
+               static_cast<kdu_core::kdu_long>(std::ceil(TP * 1.5* 0.125 ));
+            m_layerByteSizes[14] =
+               static_cast<kdu_core::kdu_long>(std::ceil(TP * 1.7* 0.125 ));
+            m_layerByteSizes[15] =
+               static_cast<kdu_core::kdu_long>(std::ceil(TP * 2.0* 0.125 ));
+            m_layerByteSizes[16] =
+               static_cast<kdu_core::kdu_long>(std::ceil(TP * 2.3* 0.125 ));
+            m_layerByteSizes[17] =
+               static_cast<kdu_core::kdu_long>(std::ceil(TP * 2.8* 0.125 ));
+            m_layerByteSizes[18] =
+               static_cast<kdu_core::kdu_long>(std::ceil(TP * 3.5* 0.125 ));
+            break;
+         }
+         case ossimKakaduCompressor::OKP_LOSSY:
+         {
+            setReversibleFlag(false);
+            
+            setWaveletKernel(cod, Ckernels_W9X7);
+            
+            m_layerSpecCount = 10;
+            m_layerByteSizes.resize(m_layerSpecCount);
+
+            m_layerByteSizes[0] =
+               static_cast<kdu_core::kdu_long>(std::ceil( TP * 0.03125 * 0.125 ));
+            m_layerByteSizes[1] =
+               static_cast<kdu_core::kdu_long>(std::ceil(TP * 0.0625* 0.125 ));
+            m_layerByteSizes[2] =
+               static_cast<kdu_core::kdu_long>(std::ceil(TP * 0.125* 0.125 ));
+            m_layerByteSizes[3] =
+               static_cast<kdu_core::kdu_long>(std::ceil(TP * 0.25* 0.125 ));
+            m_layerByteSizes[4] =
+               static_cast<kdu_core::kdu_long>(std::ceil(TP * 0.5* 0.125 ));
+            m_layerByteSizes[5] =
+               static_cast<kdu_core::kdu_long>(std::ceil(TP * 0.6* 0.125 ));
+            m_layerByteSizes[6] =
+               static_cast<kdu_core::kdu_long>(std::ceil(TP * 0.7* 0.125 ));
+            m_layerByteSizes[7] =
+               static_cast<kdu_core::kdu_long>(std::ceil(TP * 0.8* 0.125 ));
+            m_layerByteSizes[8] =
+               static_cast<kdu_core::kdu_long>(std::ceil(TP * 0.9* 0.125 ));
+            m_layerByteSizes[9] =
+               static_cast<kdu_core::kdu_long>(std::ceil(TP * 1.0* 0.125 ));
+            break;
+         }
+
+         default:
+         {
+            m_layerSpecCount = 1;
+            m_layerByteSizes.resize(m_layerSpecCount);
+            m_layerByteSizes[0] = 0;
+
+            if (traceDebug())
+            {
+               ossimNotify(ossimNotifyLevel_WARN)
+                  << "unspecified quality type\n";
+            }
+         }
+         
+      } // matches: switch (m_qualityType)
+
+      //---
+      // Set reversible flag, note, this controls the kernel.
+      // W5X3(default) if reversible = true, W9X7 if reversible is false.
+      //---
+      cod->set(Creversible, 0, 0, m_reversible);
+
+      // Set the quality layers.
+      setQualityLayers(cod, m_layerSpecCount);
+
+      if ( traceDebug() )
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG)
+            << "reversible: " << m_reversible
+            << "\nLevels: " << m_levels
+            << "\nLayers: " << m_layerSpecCount;
+         for (int n = 0; n < m_layerSpecCount; ++n)
+         {
+            ossimNotify(ossimNotifyLevel_DEBUG)
+               << "\nsize:  " << m_layerByteSizes[n];
+         }
+         ossimNotify(ossimNotifyLevel_DEBUG) << std::endl;
+      }
+      
+
+   } // matches: if (cod)
+      
+   if ( traceDebug() )
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " exited...\n";
+   }
+}
+
+int ossimKakaduCompressor::getNumberOfLayers() const
+{
+   return m_layerSpecCount;
+}
+
+ossimString ossimKakaduCompressor::getQualityTypeString() const
+{
+   return COMPRESSION_QUALITY[m_qualityType];
+}
+
+void ossimKakaduCompressor::setQualityTypeString(const ossimString& s)
+{
+   ossimString type = s;
+   type.downcase();
+   
+   if ( type == COMPRESSION_QUALITY[ossimKakaduCompressor::OKP_UNKNOWN] )
+   {
+      setQualityType(ossimKakaduCompressor::OKP_UNKNOWN);
+   }
+   else if ( type == COMPRESSION_QUALITY[ossimKakaduCompressor::OKP_USER_DEFINED] )
+   {
+      setQualityType(ossimKakaduCompressor::OKP_USER_DEFINED);
+   }
+   else if ( type == COMPRESSION_QUALITY[ossimKakaduCompressor::OKP_NUMERICALLY_LOSSLESS] )
+   {
+      setQualityType(ossimKakaduCompressor::OKP_NUMERICALLY_LOSSLESS);
+   }
+   else if ( type == COMPRESSION_QUALITY[ossimKakaduCompressor::OKP_VISUALLY_LOSSLESS] )
+   {
+      setQualityType(ossimKakaduCompressor::OKP_VISUALLY_LOSSLESS);
+   }
+   else if (type == "lossy")
+   {
+      setQualityType(ossimKakaduCompressor::OKP_LOSSY);
+   }
+   else
+   {
+      if ( traceDebug() )
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG)
+            << "ossimKakaduCompressor::setQualityTypeString DEBUG"
+            << "\nUnhandled quality type: " << type
+            << std::endl;
+      }
+   }
+}
+
+void ossimKakaduCompressor::setLevels(kdu_core::kdu_params* cod,
+                                      const ossimIrect& imageRect,
+                                      ossim_int32 levels)
+{
+   //---
+   // Number of wavelet decomposition levels, or stages.  May not exceed 32.
+   // Default is 5
+   //---
+   if (cod)
+   {
+      if (levels == 0)
+      {
+         levels = (ossim_int32)ossim::computeLevels(imageRect);
+         if (levels == 0)
+         {
+            levels = 1; // Must have at least one.
+         }
+      }
+      if ( (levels < 1) || (levels > 32) )
+      {
+         levels = 5;
+      }
+      cod->set(Clevels, 0, 0, levels);
+
+      // Set the class attribute:
+      setLevels(levels);
+   }
+}
+
+void ossimKakaduCompressor::setCodeBlockSize(kdu_core::kdu_params* cod,
+                                             ossim_int32 xSize,
+                                             ossim_int32 ySize)
+{
+   //---
+   // Nominal code-block dimensions (must be powers of 2 no less than 4 and
+   // no greater than 1024).
+   // Default block dimensions are {64,64}
+   //---
+   if (cod)
+   {
+      cod->set(Cblk,0,0,ySize);
+      cod->set(Cblk,0,1,xSize);
+   }
+}
+
+void ossimKakaduCompressor::setProgressionOrder(kdu_core::kdu_params* cod,
+                                                ossim_int32 corder)
+{
+   //---
+   // Default progression order (may be overridden by Porder).
+   // The four character identifiers have the following interpretation:
+   // L=layer; R=resolution; C=component; P=position.
+   // The first character in the identifier refers to the index which
+   // progresses most slowly, while the last refers to the index which
+   // progresses most quickly.  [Default is LRCP]
+   // Enumerations:  (LRCP=0,RLCP=1,RPCL=2,PCRL=3,CPRL=4)
+   //---
+   if (cod)
+   {
+      if ( (corder < 0) || (corder > 4) )
+      {
+         corder = Corder_LRCP;
+      }
+      cod->set(Corder,0,0,corder);
+   }
+}
+ 
+void ossimKakaduCompressor::setWaveletKernel(kdu_core::kdu_params* cod,
+                                             ossim_int32 kernel)
+{
+   //---
+   // Wavelet kernels to use.  The special value, `ATK' means that an ATK
+   // (Arbitrary Transform Kernel) marker segment is used to store the DWT
+   // kernel.  In this case, the `Catk' attribute must be non-zero.
+   // [Default is W5X3 if `Creversible' is true, W9X7 if `Creversible' is
+   // false, and ATK if `Catk' is non-zero.
+   // Enumerations: (W9X7=0,W5X3=1,ATK=-1)
+   //---
+   if (cod)
+   {
+      if ( (kernel < -1) || (kernel > 1) )
+      {
+         if ( m_reversible )
+         {
+            kernel = Ckernels_W5X3;
+         }
+         else
+         {
+            kernel = Ckernels_W9X7; 
+         }
+      }
+      cod->set(Ckernels,0,0,kernel);
+   }
+}
+
+void ossimKakaduCompressor::setQualityLayers(kdu_core::kdu_params* cod,
+                                             ossim_int32 layers)
+{
+   //---
+   // Number of quality layers. May not exceed 16384. Kakadu default is 1.
+   //---
+   if (cod)
+   {
+      if ( (layers < 1) || (layers > 16384) )
+      {
+         layers = 1;
+      }
+      cod->set(Clayers,0,0,layers);
+   }
+}
+
+void ossimKakaduCompressor::setTlmTileCount(ossim_uint32 tilesToWrite)
+{
+   //---
+   // Identifies the maximum number of tile-parts which will be written to the
+   // code-stream for each tile.
+   //
+   // See Kakadu kdu_params.h "Macro = `ORGgen_tlm'" for more.
+   //---
+   ossimString s = "ORGgen_tlm=1";
+   m_codestream.access_siz()->parse_string( s.c_str() );
+}
+
diff --git a/ossim_plugins/kakadu/ossimKakaduCompressor.h b/ossim_plugins/kakadu/ossimKakaduCompressor.h
new file mode 100644
index 0000000..161f807
--- /dev/null
+++ b/ossim_plugins/kakadu/ossimKakaduCompressor.h
@@ -0,0 +1,357 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Description: Wrapper class to compress whole tiles using kdu_analysis
+// object.
+//
+//----------------------------------------------------------------------------
+// $Id: ossimKakaduCompressor.h 23664 2015-12-14 14:17:27Z dburken $
+
+#ifndef ossimKakaduCompressor_HEADER
+#define ossimKakaduCompressor_HEADER 1
+
+#include <ossim/base/ossimConstants.h>
+#include <ossim/base/ossimIrect.h>
+#include <ossim/base/ossimProperty.h>
+#include <ossim/base/ossimRefPtr.h>
+#include <ossim/base/ossimString.h>
+
+#include <kdu_compressed.h>
+#include <kdu_elementary.h>
+#include <kdu_sample_processing.h>
+#include <kdu_stripe_compressor.h>
+
+#include <iosfwd>
+
+class ossimFilename;
+class ossimImageData;
+class ossimImageGeometry;
+class ossimIpt;
+class ossimKakaduCompressedTarget;
+
+namespace kdu_supp
+{
+   class jp2_family_tgt;
+   class jp2_target; 
+}
+
+class ossimKakaduCompressor
+{
+public:
+
+   // Matches static "COMPRESSION_QUALITY" string array in .cpp.
+   enum ossimKakaduCompressionQuality
+   {
+      // Prefixed with OKP for OSSIM Kakadu Plugin to avoid clashes.
+      OKP_UNKNOWN              = 0,
+      OKP_USER_DEFINED         = 1,
+      OKP_NUMERICALLY_LOSSLESS = 2,
+      OKP_VISUALLY_LOSSLESS    = 3,
+      OKP_LOSSY                = 4
+   };
+
+   /** default constructor */
+   ossimKakaduCompressor();
+
+   /** destructor */
+   ~ossimKakaduCompressor();
+
+   /**
+    * @brief Create method.
+    * @param os Stream to write to.
+    * @param scalar Scalar type of source tiles to be fed to compressor.
+    * @param bands Number of bands in source tiles to be fed to compressor.
+    * @param imageRect The image rectangle.
+    * @param tileSize The size of a tile.
+    * @param tilesTileWrite The number of tiles to be written.
+    * If zero, the tlm marker segment will not be used.
+    * @param jp2 If true jp2 header and jp2 geotiff block will be written out.
+    * @note Throws ossimException on error.
+    */
+ void create(std::ostream* os,
+             ossimScalarType scalar,
+             ossim_uint32 bands,
+             const ossimIrect& imageRect,
+             const ossimIpt& tileSize,
+             ossim_uint32 tilesToWrite,
+             bool jp2);
+
+   /**
+    * @brief Calls "open_codestream" on the m_jp2Target.
+    *
+    * Note: Only valid if create method was called with jp2 = true.
+    */
+   void openJp2Codestream();
+
+   /**
+    * @brief Write tile method.
+    *
+    * Writes tiles stream provided to create method.  Note that tiles should
+    * be fed to compressor in left to right, top to bottom order.
+    * 
+    * @param srcTile The source tile to write.
+    *
+    * @return true on success, false on error.
+    */
+   bool writeTile(ossimImageData& srcTile);
+
+   /**
+    * @brief Finish method.  Every call to "create" should be matched by a
+    * "finish".  Note the destructor calls finish.
+    */
+   void finish();
+
+   /**
+    * @brief Sets the quality type.
+    * @param type See enumeration for types.
+    */
+   void setQualityType(ossimKakaduCompressionQuality type);
+
+   /** @return The quality type setting. */
+   ossimKakaduCompressionQuality getQualityType() const;
+
+   /**
+    * @brief Sets the m_reversible flag.
+    *
+    * If set to true the compression will be lossless; if not, lossy.
+    * Default is lossless.
+    * 
+    * @param reversible Flag to set.
+    */
+   void setReversibleFlag(bool reversible);
+   
+   /** @return The reversible flag. */
+   bool getReversibleFlag() const;
+   
+   /**
+    * Set the writer to add an alpha channel to the output png image.
+    *
+    * @param flag true to create an alpha channel.
+    */
+   void setAlphaChannelFlag( bool flag );
+
+   /**
+    * Retrieve the writer's setting for whether or not to add an 
+    * alpha channel to the output png image.
+    *
+    * @return true if the writer is configured to create an alpha channel.
+    */
+   bool getAlphaChannelFlag() const;
+
+   /**
+    * @brief Sets the number of levels.
+    *
+    * This must be positive and at least 1.
+    * Default = 5 ( r0 - r5 )
+    *
+    * @param levels Levels to set.
+    */
+   void setLevels(ossim_int32 levels);
+
+   /** @return The number of levels. */
+   ossim_int32 getLevels() const;
+   
+    /**
+    * @brief Sets the number of threads.
+    *
+    * This must be positive and at least 1.  Default = 1 thread.
+    *
+    * @param threads The number of threads.
+    */
+   void setThreads(ossim_int32 threads);
+
+   /** @return The number of threads. */
+   ossim_int32 getThreads() const;
+
+   /**
+    * @brief Sets the options array.
+    *
+    * These get passed to the generic kdu_params::parse_string method.  Note
+    * this adds options to the list.  Does not zero out existing options.
+    *
+    * @param options Array of options to add.
+    */
+   void setOptions(const std::vector<ossimString>& options);
+   
+   /**
+    * @brief Get the array of options.
+    * @param options Array to initialize.
+    */
+   void getOptions(std::vector<ossimString>& options) const;
+  
+   /**
+    * saves the state of the object.
+    */
+   bool saveState(ossimKeywordlist& kwl, const char* prefix=0)const;
+   
+   /**
+    * Method to the load (recreate) the state of an object from a keyword
+    * list.  Return true if ok or false on error.
+    */
+   bool loadState(const ossimKeywordlist& kwl, const char* prefix=0);
+   
+   /**
+    * Will set the property whose name matches the argument
+    * "property->getName()".
+    *
+    * @param property Object containing property to set.
+    *
+    * @return true if property was consumed, false if not.
+    */
+   bool setProperty(ossimRefPtr<ossimProperty> property);
+   
+   /**
+    * @param name Name of property to return.
+    * 
+    * @returns A pointer to a property object which matches "name".
+    */
+   ossimRefPtr<ossimProperty> getProperty(const ossimString& name)const;
+   
+   /**
+    * Pushes this's names onto the list of property names.
+    *
+    * @param propertyNames array to add this's property names to.
+    */
+   void getPropertyNames(std::vector<ossimString>& propertyNames)const;
+
+   /**
+    * @brief Writes the geotiff box to the jp2
+    * @param geom Output image geometry.
+    * @param rect Output rectangle (view rect).
+    * @param tmpFile Temp tiff file to write out for reading back in.
+    * @param pixelType OSSIM_PIXEL_IS_POINT(0) or OSSIM_PIXEL_IS_AREA(1)
+    */
+   bool writeGeotiffBox(const ossimImageGeometry* geom,
+                        const ossimIrect& rect,
+                        const ossimFilename& tmpFile,
+                        ossimPixelType pixelType);
+   
+private:
+
+   void initializeCodingParams(kdu_core::kdu_params* cod, const ossimIrect& imageRect);
+   
+   int  getNumberOfLayers() const;
+
+   ossimString getQualityTypeString() const;
+   void setQualityTypeString(const ossimString& s);
+
+   /**
+    * @brief Set levels
+    *
+    * Number of wavelet decomposition levels, or stages.  May not exceed 32.
+    * Kakadu Default is 5
+    *
+    * @param cod Pointer to cod_params object.
+    * @param imageRect The image rectangle.
+    * @param levels Number of levels.
+    */
+   void setLevels(kdu_core::kdu_params* cod,
+                  const ossimIrect& imageRect,
+                  ossim_int32 levels);
+
+   /**
+    * @brief Set code block size.
+    *
+    * Nominal code-block dimensions (must be powers of 2 no less than 4 and
+    * no greater than 1024).
+    * Kakadu Default block dimensions are {64,64}
+    *
+    * @param xSize
+    * @param ySize
+    */   
+   void setCodeBlockSize(kdu_core::kdu_params* cod,
+                         ossim_int32 xSize,
+                         ossim_int32 ySize);
+
+   /**
+    * @brief Sets progression order.
+    *
+    * Default progression order (may be overridden by Porder).
+    * The four character identifiers have the following interpretation:
+    * L=layer; R=resolution; C=component; P=position.
+    * The first character in the identifier refers to the index which
+    * progresses most slowly, while the last refers to the index which
+    * progresses most quickly.  [Default is LRCP]
+    * Enumerations:  (LRCP=0,RLCP=1,RPCL=2,PCRL=3,CPRL=4) 
+    *
+    * @param corder The progression order which should be one of the above
+    * enumerations.
+    */   
+   void setProgressionOrder(kdu_core::kdu_params* cod,
+                            ossim_int32 corder);
+
+   /**
+    * @brief Sets the wavelet kernel to use.
+    *
+    * Wavelet kernels to use.  The special value, `ATK' means that an ATK
+    * (Arbitrary Transform Kernel) marker segment is used to store the DWT
+    * kernel.  In this case, the `Catk' attribute must be non-zero.
+    * [Default is W5X3 if `Creversible' is true, W9X7 if `Creversible' is
+    * false, and ATK if `Catk' is non-zero.
+    * 
+    * Enumerations: (W9X7=0,W5X3=1,ATK=-1) 
+    *
+    * @param kernel The kernel which should be one of the above enumerations.
+    */   
+   
+   void setWaveletKernel(kdu_core::kdu_params* cod, ossim_int32 kernel);
+
+   /**
+    * @brief Sets the number of quality layers.
+    *
+    * Number of quality layers. May not exceed 16384. Kakadu default is 1.
+    *
+    * @param layers.
+    */   
+   void setQualityLayers(kdu_core::kdu_params* cod, ossim_int32 layers);
+
+   void setTlmTileCount(ossim_uint32 tilesToWrite);
+
+   ossimKakaduCompressedTarget* m_target;
+   
+   kdu_supp::jp2_family_tgt*    m_jp2FamTgt;
+   kdu_supp::jp2_target*        m_jp2Target;
+   kdu_core::kdu_codestream     m_codestream;
+   kdu_core::kdu_thread_env*    m_threadEnv;
+   kdu_core::kdu_thread_queue*  m_threadQueue;
+
+   /** Num specs provided in 'flush' calls. */
+   int                          m_layerSpecCount;
+
+   /** Layer sizes provided in 'flush' calls. */
+   std::vector<kdu_core::kdu_long> m_layerByteSizes;
+   
+   /** Layer slopes array provided in 'flush' calls. */
+   // std::vector<kdu_uint16>      m_layerSlopes;
+
+   /** Image rectangle.  Used for clip in writeTile. */
+   ossimIrect                   m_imageRect;
+
+   /** Lossless or lossy */
+   bool                         m_reversible;
+
+   /** If true write alpha channel. */
+   bool                         m_alpha;
+
+   /** Reduced resolution levels. */
+   ossim_int32                  m_levels;
+
+   /** Number of threads. */
+   ossim_int32                  m_threads;
+
+   /** Container for kakadu options to pass to kdu_params::parse_string. */
+   std::vector<ossimString> m_options;
+
+   ossimKakaduCompressionQuality m_qualityType;
+
+   /** tile to use for normalized float data. */
+   ossimRefPtr<ossimImageData> m_normTile;
+ 
+};
+
+#endif /* matches: #ifndef ossimKakaduCompressor_HEADER */
+ 
+
diff --git a/ossim_plugins/kakadu/ossimKakaduJ2kReader.cpp b/ossim_plugins/kakadu/ossimKakaduJ2kReader.cpp
new file mode 100644
index 0000000..d38e4b9
--- /dev/null
+++ b/ossim_plugins/kakadu/ossimKakaduJ2kReader.cpp
@@ -0,0 +1,777 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author:  David Burken
+//
+// Description:
+//
+// Class definition for JPEG2000 (J2K) reader.
+//
+//----------------------------------------------------------------------------
+// $Id: ossimKakaduJ2kReader.cpp 23664 2015-12-14 14:17:27Z dburken $
+
+#include "ossimKakaduJ2kReader.h"
+#include "ossimKakaduCommon.h"
+#include "ossimKakaduMessaging.h"
+
+#include <ossim/base/ossimCommon.h>
+#include <ossim/base/ossimEndian.h>
+#include <ossim/base/ossimException.h>
+#include <ossim/base/ossimNotify.h>
+#include <ossim/base/ossimPreferences.h>
+#include <ossim/base/ossimScalarTypeLut.h>
+#include <ossim/base/ossimTrace.h>
+ 
+#include <ossim/imaging/ossimTiffTileSource.h>
+#include <ossim/imaging/ossimImageDataFactory.h>
+
+#include <ossim/support_data/ossimJ2kSizRecord.h>
+#include <ossim/support_data/ossimJ2kSotRecord.h>
+
+#include <kdu_sample_processing.h>
+#include <kdu_region_decompressor.h>
+#include <kdu_threads.h>
+
+#include <fstream>
+#include <iostream>
+ 
+ 
+#ifdef OSSIM_ID_ENABLED
+static const char OSSIM_ID[] = "$Id";
+#endif
+ 
+static const ossimTrace traceDebug( ossimString("ossimKakaduJ2kReader:debug") );
+static const ossimTrace traceDump( ossimString("ossimKakaduJ2kReader:dump" ) );
+
+RTTI_DEF1_INST(ossimKakaduJ2kReader,
+               "ossimKakaduJ2kReader",
+               ossimImageHandler)
+ 
+ossimKakaduJ2kReader::ossimKakaduJ2kReader()
+   : ossimImageHandler(),
+     theCodestream(),
+     theThreadEnv(0),
+     theOpenTileThreadQueue(0),
+     theMinDwtLevels(0),
+     theFileStr(),
+     theSizRecord(),
+     theScalarType(OSSIM_SCALAR_UNKNOWN),
+     theImageRect(),
+     theTile(),
+     theCacheTile(),
+     theTileSizeX(0),
+     theTileSizeY(0),
+     theCacheId(-1)
+{
+   kdu_customize_warnings(&pretty_cout); // Deliver warnings to stdout.
+   kdu_customize_errors(&pretty_cerr); // Deliver errors to stderr + throw exc
+}
+
+ossimKakaduJ2kReader::~ossimKakaduJ2kReader()
+{
+   closeEntry();
+}
+
+ossimString ossimKakaduJ2kReader::getShortName()const
+{
+   return ossimString("ossim_kakadu_j2k_reader");
+}
+
+ossimString ossimKakaduJ2kReader::getLongName()const
+{
+   return ossimString("ossim kakadu j2k reader");
+}
+
+ossimString ossimKakaduJ2kReader::getClassName()const
+{
+   return ossimString("ossimKakaduJ2kReader");
+}
+
+void ossimKakaduJ2kReader::getDecimationFactor(ossim_uint32 resLevel,
+                                               ossimDpt& result) const
+{
+   if (resLevel == 0)
+   {
+      //---
+      // Assumption r0 or first layer is full res.  Might need to change to
+      // use nitf IMAG field.
+      //---
+      result.x = 1.0;
+      result.y = 1.0;
+   }
+   else if ( theOverview.valid() && (resLevel > theMinDwtLevels) &&
+             (resLevel < getNumberOfDecimationLevels()) )
+   {
+      //---
+      // External overview file.
+      // 
+      // Use the real lines and samples in case an resLevel is skipped.
+      //
+      // Note we must subtract the internal overviews as the external
+      // overview reader does not know about them.
+      //---
+      ossim_float64 r0 = getNumberOfSamples(0);
+      ossim_float64 rL =
+         theOverview->getNumberOfSamples(resLevel-theMinDwtLevels);
+      
+      if (r0) // Divide by zero check
+      {
+         result.x = rL/r0;
+      }
+      else
+      {
+         result.x = ossim::nan();
+      }
+      r0 = getNumberOfLines(0);
+      rL = theOverview->getNumberOfLines(resLevel-theMinDwtLevels);
+      
+      if (r0) // Divide by zero check.
+      {
+         result.y = rL/r0;
+      }
+      else
+      {
+         result.y = ossim::nan();
+      }
+   }
+   else
+   {
+      // Internal overviews are on power of two decimation.
+      result.x = 1.0 / pow((double)2, (double)resLevel);
+      result.y = result.x;
+   }
+}
+
+void ossimKakaduJ2kReader::getDecimationFactors(
+   vector<ossimDpt>& decimations) const
+{
+   const ossim_uint32 LEVELS = getNumberOfDecimationLevels();
+   decimations.resize(LEVELS);
+   for (ossim_uint32 level = 0; level < LEVELS; ++level)
+   {
+      getDecimationFactor(level, decimations[level]);
+   }
+}
+
+ossim_uint32 ossimKakaduJ2kReader::getNumberOfDecimationLevels()const
+{
+   ossim_uint32 result = 1; // Add r0
+
+   if (theMinDwtLevels)
+   {
+      //---
+      // Add internal overviews.
+      //---
+      result += theMinDwtLevels;
+   }
+
+   if (theOverview.valid())
+   {
+      //---
+      // Add external overviews.
+      //
+      // NOTE: The ossimTiffTileSource will count r0 if present or it will
+      //       add 1 to the decimation count if r0 is NOT present. Since
+      //       since r0 has already be added subtract one.
+      //---
+      result += theOverview->getNumberOfDecimationLevels()-1;
+   }
+
+   return result;
+}
+
+ossim_uint32 ossimKakaduJ2kReader::getNumberOfLines(
+   ossim_uint32 resLevel) const
+{
+   ossim_uint32 result = 0;
+   if (resLevel < getNumberOfDecimationLevels())
+   {
+      result = theSizRecord.m_Ysiz;
+      if ( resLevel > 0 )
+      {
+         ossimDpt dpt;
+         getDecimationFactor(resLevel, dpt);
+         if ( !dpt.hasNans() )
+         {
+            result = static_cast<ossim_uint32>(result * dpt.y);
+         }
+      }
+   }
+   return result;
+}
+
+ossim_uint32 ossimKakaduJ2kReader::getNumberOfSamples(
+   ossim_uint32 resLevel) const
+{
+   ossim_uint32 result = 0;
+   if (resLevel < getNumberOfDecimationLevels())
+   {
+      result = theSizRecord.m_Xsiz;
+      if ( resLevel > 0 )
+      {
+         ossimDpt dpt;
+         getDecimationFactor(resLevel, dpt);
+         result = static_cast<ossim_uint32>(result * dpt.x);
+      }
+   }
+   return result;
+}
+
+bool ossimKakaduJ2kReader::open()
+{
+   static const char MODULE[] = "ossimKakaduJ2kReader::open";
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " entered...\n";
+   }
+   
+   bool result = false;
+   
+   if(isOpen())
+   {
+      closeEntry();
+   }
+
+   // Open up a stream to the file.
+   theFileStr.open(theImageFile.c_str(), ios::in | ios::binary);
+   if ( theFileStr.good() )
+   {
+      //---
+      // Check for the Start Of Codestream (SOC) and Size (SIZ) markers which
+      // are required as first and second fields in the main header.
+      //---
+      ossim_uint16 soc;
+      ossim_uint16 siz;
+      theFileStr.read((char*)&soc,  2);
+      theFileStr.read((char*)&siz,  2);
+      
+      if (ossim::byteOrder() == OSSIM_LITTLE_ENDIAN) // Alway big endian.
+      {
+         ossimEndian().swap(soc);
+         ossimEndian().swap(siz);
+      }
+
+      const ossim_uint16 SOC_MARKER = 0xff4f; // start of codestream marker
+      const ossim_uint16 SIZ_MARKER = 0xff51; // size maker
+
+      if ( (soc == SOC_MARKER) && (siz == SIZ_MARKER) )
+      {
+         // Read in and store the size record.
+         theSizRecord.parseStream(theFileStr);
+
+         // Position to start of code stream prior to create call.
+         theFileStr.seekg(0);
+ 
+         //---
+         // Initialize the codestream.  The class ossimKakaduNitfReader is a
+         // kdu_compressed source so we feed ourself to the codestream.
+         //
+         // TODO:  Currently no kdu_thread_env.  This should be implemented for
+         // speed...
+         //---
+         
+         //---
+         // Construct multi-threaded processing environment if required.
+         // Temp hard coded to a single thread.
+         //---
+         
+         if (theThreadEnv)
+         {
+            theThreadEnv->terminate(NULL, true);
+            theThreadEnv->destroy();
+         }
+         else
+         {
+            theThreadEnv = new kdu_core::kdu_thread_env();
+         }
+         
+         theThreadEnv->create(); // Creates the single "owner" thread
+
+         // Check for threads in prefs file.
+         ossim_uint32 threads = 1;
+         const char* lookup = ossimPreferences::instance()->findPreference("kakadu_threads");
+         if ( lookup )
+         {
+            threads = ossimString::toUInt32(lookup);
+            if ( threads > 1 )
+            {
+               for (ossim_uint32 nt=1; nt < threads; ++nt)
+               {
+                  if ( !theThreadEnv->add_thread() )
+                  {
+                     if (traceDebug())
+                     {
+                        ossimNotify(ossimNotifyLevel_WARN)
+                           << "Unable to create thread!\n";
+                     }
+                  }
+               }
+            }
+         }
+         
+         theOpenTileThreadQueue = theThreadEnv->add_queue(NULL,NULL,"open_tile_q");
+         
+         theCodestream.create(this, theThreadEnv);
+         
+         if ( theCodestream.exists() )
+         {
+            //---
+            // We have to store things here in this non-const method because
+            // NONE of the kakadu methods are const.
+            //---
+            theMinDwtLevels = theCodestream.get_min_dwt_levels();
+            
+            theCodestream.set_persistent(); // ????
+            theCodestream.enable_restart(); // ????
+            
+            kdu_core::kdu_dims region_of_interest;
+            region_of_interest.pos.x = 0;
+            region_of_interest.pos.y = 0;
+            region_of_interest.size.x = getNumberOfSamples(0);
+            region_of_interest.size.y = getNumberOfLines(0);
+
+            theCodestream.apply_input_restrictions(
+               0, // first_component
+               0, // max_components (0 = all remaining will appear)
+               0, // highest resolution level
+               0, // max_layers (0 = all layers retained)
+               &region_of_interest, // expanded out to block boundary.
+               //KDU_WANT_CODESTREAM_COMPONENTS);
+               kdu_core::KDU_WANT_OUTPUT_COMPONENTS);
+            
+            // Set the scalar:
+            theScalarType = theSizRecord.getScalarType();
+            if (theScalarType != OSSIM_SCALAR_UNKNOWN)
+            {
+               //---
+               // NOTE: Please leave commented out code for now.
+               //---
+               // Capture the sub image offset.
+               // theSubImageOffset.x = theSizRecord.theXOsiz;
+               // theSubImageOffset.y = theSizRecord.theYOsiz;
+               
+               // Initialize the image rect.
+               theImageRect = ossimIrect(0,
+                                         0,
+                                         theSizRecord.m_Xsiz-1,
+                                         theSizRecord.m_Ysiz-1);
+
+               // Initialize the cache.
+               if (theCacheId != -1)
+               {
+                  ossimAppFixedTileCache::instance()->deleteCache(theCacheId);
+                  theCacheId = -1;
+               }
+               ossimIpt tileSize(theSizRecord.m_XTsiz, theSizRecord.m_YTsiz);
+
+               // Stretch to tile boundary for the cache.
+               ossimIrect fullImgRect = theImageRect;
+               fullImgRect.stretchToTileBoundary(tileSize);
+               
+               // Set up the tile cache.
+               theCacheId = ossimAppFixedTileCache::instance()->
+                  newTileCache(fullImgRect, tileSize);
+
+               // Add the sub image rect after the 
+               
+               // Initialize the tile we will return.
+               initializeTile();
+
+               // Call the base complete open to pick up overviews.
+               completeOpen();
+               
+               // We should be good now so set the return result to true.
+               result = true;
+
+               if (traceDebug())
+               {
+                  ossimNotify(ossimNotifyLevel_DEBUG)
+                     << "\nSIZ marker segment"
+                     << theSizRecord
+                     << "theCodestream.get_num_components(false): "
+                     << theCodestream.get_num_components(false)
+                     << "\ntheCodestream.get_num_components(true): "
+                     << theCodestream.get_num_components(true)
+                     << "\ntheCodestream.get_bit_depth(0, true): "
+                     << theCodestream.get_bit_depth(0, true)
+                     << "\ntheCodestream.get_signed(0, true): "
+                     << theCodestream.get_signed(0, true)
+                     << "\ntheCodestream.get_min_dwt_levels(): "
+                     << theCodestream.get_min_dwt_levels()
+                     << "\ntheImageRect: " << theImageRect
+                     << "\nFull image rect: " << fullImgRect
+                     << "\nthreads: " << threads
+                     << "\n";
+                  
+                  vector<ossimDpt> decimations;
+                  getDecimationFactors(decimations);
+                  for (ossim_uint32 i = 0; i < decimations.size(); ++i)
+                  {
+                     ossimNotify(ossimNotifyLevel_DEBUG)
+                        << theCodestream.get_min_dwt_levels()
+                        << "Decimation factor[" << i << "]: "
+                        << decimations[i]
+                        << "\nsamples[" << i << "]: "
+                        << getNumberOfSamples(i)
+                        << "\nlines[" << i << "]: "
+                        << getNumberOfLines(i)
+                        << std::endl;
+                     
+                  }
+               }
+            }
+               
+         } // matches: if ( theCodestream.exists() )
+         
+      } //  matches: if ( (soc == SOC_MARKER) && (siz == SIZ_MARKER) )
+      
+   } // matches: if ( theFileStr.good() )
+   else
+   {
+      if(traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG)
+            << MODULE << " ERROR:"
+            << "\nCannot open:  " << theImageFile.c_str() << endl;
+      }
+   }
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " exit status = " << (result?"true":"false\n")
+         << std::endl;
+   }
+
+   return result;
+}
+
+bool ossimKakaduJ2kReader::isOpen()const
+{
+   // return theFileStr.is_open();
+
+   // Temp fix for gcc's that don't have a const "ifstream::is_open() const"
+   return theTile.valid();
+}
+
+void ossimKakaduJ2kReader::closeEntry()
+{
+   theFileStr.close();
+
+   // Cleanup processing environment
+   if ( theThreadEnv )
+   {
+      theThreadEnv->join(NULL,true); // Wait until all internal processing is complete.
+      theThreadEnv->terminate(theOpenTileThreadQueue, true);
+      theThreadEnv->cs_terminate(theCodestream);   // Terminates background codestream processing.
+      theThreadEnv->destroy();
+      delete theThreadEnv;
+      theThreadEnv = 0;
+   }
+   
+   if(theCodestream.exists())
+   {
+      theCodestream.destroy();
+   }
+
+   if (theOpenTileThreadQueue)
+   {
+      theOpenTileThreadQueue = 0;
+   }
+
+   if (theCacheId != -1)
+   {
+      ossimAppFixedTileCache::instance()->deleteCache(theCacheId);
+      theCacheId = -1;
+   }
+
+   theTile      = 0;
+   theCacheTile = 0;
+   theTileSizeX = 0;
+   theTileSizeY = 0;
+
+   ossimImageHandler::close();
+}
+
+bool ossimKakaduJ2kReader::loadState(const ossimKeywordlist& kwl,
+                                     const char* prefix)
+{
+   bool result = false;
+   
+   if ( ossimImageHandler::loadState(kwl, prefix) )
+   {
+      result = open();
+   }
+   
+   return result;
+}
+
+
+ossimRefPtr<ossimImageData> ossimKakaduJ2kReader::getTile(
+   const ossimIrect& rect, ossim_uint32 resLevel)
+{
+   // This tile source bypassed, or invalid res level, return a blank tile.
+   if(!isSourceEnabled() || !isOpen() || !isValidRLevel(resLevel))
+   {
+      return ossimRefPtr<ossimImageData>();
+   }
+
+   if (theTile.valid())
+   {
+      // Rectangle must be set prior to getOverviewTile call.
+      theTile->setImageRectangle(rect);
+
+      if (resLevel)
+      {
+         if ( getOverviewTile(resLevel, theTile.get() ) == false )
+         {
+            theTile->makeBlank();
+         }
+      }
+      else
+      {
+         //---
+         // See if the whole tile is going to be filled, if not, start out with
+         // a blank tile so data from a previous load gets wiped out.
+         //---
+         if ( !rect.completely_within(theImageRect) )
+         {
+            // Start with a blank tile.
+            theTile->makeBlank();
+         }
+         
+         //---
+         // See if any point of the requested tile is in the image.
+         //---
+         if ( rect.intersects(theImageRect) )
+         {
+            ossimIrect clipRect = rect.clipToRect(theImageRect);
+
+            ossimIrect exandedRect  = clipRect;
+
+            //---
+            // Shift the upper left corner of the "clip_rect" to the an even
+            // j2k tile boundry.  
+            //---
+            exandedRect.stretchToTileBoundary(ossimIpt(theTileSizeX,
+                                                       theTileSizeY));
+            
+            // Vertical tile loop.
+            ossim_int32 y = exandedRect.ul().y;
+            while (y < exandedRect.lr().y)
+            {
+               // Horizontal tile loop.
+               ossim_int32 x = exandedRect.ul().x;
+               while (x < exandedRect.lr().x)
+               {
+                  if ( loadTileFromCache(x, y, clipRect) == false )
+                  {
+                     if ( loadTile(x, y) )
+                     {
+                        //---
+                        // Note: Clip the cache tile to the image clipRect
+                        // since there are j2k tiles that go beyond the image
+                        // dimensions, i.e., edge tiles.
+                        //---    
+                        ossimIrect cr =
+                           theCacheTile->getImageRectangle().
+                           clipToRect(clipRect);
+                        
+                        theTile->loadTile(theCacheTile->getBuf(),
+                                          theCacheTile->getImageRectangle(),
+                                          cr,
+                                          OSSIM_BSQ);
+                     }
+                     
+                  }
+                  
+                  x += theTileSizeX; // Go to next tile.
+               }
+               
+               y += theTileSizeY; // Go to next row of tiles.
+            }
+
+            // Set the tile status.
+            theTile->validate();
+            
+         } // matches: if ( rect.intersects(theImageRect) )
+         
+      } // r0 block
+      
+   } // matches: if (theTile.valid())
+
+   return theTile;
+}
+
+bool ossimKakaduJ2kReader::getOverviewTile(ossim_uint32 resLevel,
+                                           ossimImageData* result)
+{
+   bool status = false;
+
+   if ( (resLevel < getNumberOfDecimationLevels()) && result &&
+        (result->getNumberOfBands() == getNumberOfOutputBands()) )
+   {
+      if (resLevel <= theMinDwtLevels)
+      {
+         // Internal overviews...
+         try
+         {
+            status = ossim::copyRegionToTile(theCodestream,
+                                             static_cast<int>(resLevel),
+                                             theThreadEnv,
+                                             theOpenTileThreadQueue,
+                                             result);
+         }
+         catch(const ossimException& e)
+         {
+            ossimNotify(ossimNotifyLevel_WARN)
+               << __FILE__ << " " << __LINE__ << " caught exception\n"
+               << e.what();
+            status = false;
+         }
+
+      } // matches:  if (resLevel <= theMinDwtLevels)
+      else
+      {
+         // External overviews...
+         status = theOverview->getTile(result, resLevel - theMinDwtLevels);
+      }
+   }
+
+   return status;
+}
+
+ossim_uint32 ossimKakaduJ2kReader::getNumberOfInputBands() const
+{
+   return theSizRecord.m_Csiz;
+}
+
+ossim_uint32 ossimKakaduJ2kReader::getNumberOfOutputBands()const
+{
+   return theSizRecord.m_Csiz;
+}
+
+ossim_uint32 ossimKakaduJ2kReader::getImageTileWidth() const
+{
+   ossim_uint32 result = 0;
+   if ( (theSizRecord.m_XTsiz <= 1024) && (theSizRecord.m_YTsiz <= 1024) )
+   {
+      result = theSizRecord.m_XTsiz;
+   }
+   return result;
+}
+
+ossim_uint32 ossimKakaduJ2kReader::getImageTileHeight() const
+{
+   ossim_uint32 result = 0;
+   if ( (theSizRecord.m_XTsiz <= 1024) && (theSizRecord.m_YTsiz <= 1024) )
+   {
+      result = theSizRecord.m_YTsiz;
+   }
+   return result;
+}
+
+ossimScalarType ossimKakaduJ2kReader::getOutputScalarType() const
+{
+   return theSizRecord.getScalarType();
+}
+ 
+void ossimKakaduJ2kReader::initializeTile()
+{
+   theTileSizeX = this->getImageTileWidth();
+   theTileSizeY = this->getImageTileHeight();
+
+   // Check for zero width, height and limit output tile sizes to 1024.
+   if ( !theTileSizeX || !theTileSizeY ||
+        ( theTileSizeX > 1024) || (theTileSizeY > 1024) )
+   {
+      ossimIpt tileSize;
+      ossim::defaultTileSize(tileSize);
+
+      theTileSizeX = tileSize.x;
+      theTileSizeY = tileSize.y;
+   }
+   
+   theTile = ossimImageDataFactory::instance()->
+      create( this,
+              this->getOutputScalarType(),
+              this->getNumberOfOutputBands(),
+              theTileSizeX,
+              theTileSizeY);
+
+   theTile->initialize();
+
+   theCacheTile = ossimImageDataFactory::instance()->
+      create( this,
+              this->getOutputScalarType(),
+              this->getNumberOfOutputBands(),
+              theTileSizeX,
+              theTileSizeY);
+   
+   theCacheTile->initialize();
+}
+
+bool ossimKakaduJ2kReader::loadTileFromCache(ossim_uint32 x, ossim_uint32 y,
+                                             const ossimIrect& clipRect)
+{
+   bool result = false;
+
+   ossimIpt origin(x, y);
+
+   ossimRefPtr<ossimImageData> tempTile =
+      ossimAppFixedTileCache::instance()->getTile(theCacheId, origin);
+
+   if (tempTile.valid())
+   {
+      //---
+      // Note: Clip the cache j2k tile to the image clipRect since
+      // there are j2k tiles that go beyond the image dimensions, i.e.,
+      // edge tiles.
+      //---
+      ossimIrect cr =
+         tempTile->getImageRectangle().clipToRect(clipRect);
+      
+      theTile->loadTile(tempTile.get()->getBuf(),
+                        tempTile->getImageRectangle(),
+                        cr,
+                        OSSIM_BSQ);
+      result = true;
+   }
+   return result;
+}
+
+bool ossimKakaduJ2kReader::loadTile(ossim_uint32 x, ossim_uint32 y)
+{
+   bool result = true;
+   
+   ossimIpt ul(x, y);
+   ossimIpt lr(ul.x + theTileSizeX - 1,
+               ul.y + theTileSizeY - 1);
+
+   // Set the cache rectangle to be an even j2k tile.
+   theCacheTile->setImageRectangle(ossimIrect(ul, lr));
+
+   //---
+   // Let the getOverviewTile do the rest of the work.
+   if ( getOverviewTile(0, theCacheTile.get()) )
+   {
+      // Add it to the cache for the next time.
+      ossimAppFixedTileCache::instance()->addTile(theCacheId, theCacheTile);
+   }
+   else
+   {
+      ossimNotify(ossimNotifyLevel_WARN)
+         << __FILE__ << __LINE__
+         << " ossimKakaduJ2kReader::loadBlock failed!"
+         << std::endl;
+      result = false;
+   }
+   
+   return result;
+}
+
diff --git a/ossim_plugins/kakadu/ossimKakaduJ2kReader.h b/ossim_plugins/kakadu/ossimKakaduJ2kReader.h
new file mode 100644
index 0000000..393705f
--- /dev/null
+++ b/ossim_plugins/kakadu/ossimKakaduJ2kReader.h
@@ -0,0 +1,354 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Description:
+//
+// Class declaration for JPEG2000 (J2K) reader.
+//
+//----------------------------------------------------------------------------
+// $Id: ossimKakaduJ2kReader.h 23664 2015-12-14 14:17:27Z dburken $
+
+#ifndef ossimKakaduJ2kReader_HEADER
+#define ossimKakaduJ2kReader_HEADER 1
+
+#include "../ossimPluginConstants.h"
+#include <ossim/base/ossimIrect.h>
+#include <ossim/imaging/ossimImageHandler.h>
+#include <ossim/support_data/ossimJ2kSizRecord.h>
+#include <ossim/imaging/ossimAppFixedTileCache.h>
+#include <iosfwd>
+#include <fstream>
+
+// Forward class declarations.
+class ossimImageData;
+
+//---
+// Kakadu put multiple classes in header:  kdu_compressed_source, kd_thread_env
+//---
+#include <kdu_compressed.h>
+// #include <kdu_region_decompressor.h>
+
+namespace kdu_core
+{
+   class kdu_line_buf;
+   class kdu_thread_queue;
+}
+
+/**
+ * @brief ossimKakaduJ2kReader class for reading images with JPEG2000
+ * (J2K) compressed blocks using kakadu library for decompression. 
+ */
+class OSSIM_PLUGINS_DLL ossimKakaduJ2kReader :
+   public ossimImageHandler, public kdu_core::kdu_compressed_source
+{
+public:
+
+   /** default construtor */
+   ossimKakaduJ2kReader();
+   
+   /** virtural destructor */
+   virtual ~ossimKakaduJ2kReader();
+
+   /**
+    * @brief Returns short name.
+    * @return "ossim_kakadu_j2k_reader"
+    */
+   virtual ossimString getShortName() const;
+   
+   /**
+    * @brief Returns long  name.
+    * @return "ossim kakadu j2k reader"
+    */
+   virtual ossimString getLongName()  const;
+
+   /**
+    * @brief Returns short name.
+    * @return "ossim_kakadu_j2k_reader"
+    */
+   virtual ossimString getClassName() const;
+
+   /**
+    *  @brief Method to grab a tile(rectangle) from image.
+    *
+    *  @param rect The zero based rectangle to grab.
+    *
+    *  @param resLevel The reduced resolution level to grab from.
+    *
+    *  @return The ref pointer with the image data pointer.
+    */
+   virtual ossimRefPtr<ossimImageData> getTile(const  ossimIrect& rect,
+                                               ossim_uint32 resLevel=0);
+
+   /**
+    *  Returns the number of bands in the image.
+    *  Satisfies pure virtual from ImageHandler class.
+    */
+   virtual ossim_uint32 getNumberOfInputBands() const;
+
+   /**
+    * Returns the number of bands in a tile returned from this TileSource.
+    * Note: we are supporting sources that can have multiple data objects.
+    * If you want to know the scalar type of an object you can pass in the
+    */
+   virtual ossim_uint32 getNumberOfOutputBands()const; 
+   /**
+    * Returns the tile width of the image or 0 if the image is not tiled.
+    * Note: this is not the same as the ossimImageSource::getTileWidth which
+    * returns the output tile width which can be different than the internal
+    * image tile width on disk.
+    */
+   virtual ossim_uint32 getImageTileWidth() const;
+
+   /**
+    * Returns the tile width of the image or 0 if the image is not tiled.
+    * Note: this is not the same as the ossimImageSource::getTileWidth which
+    * returns the output tile width which can be different than the internal
+    * image tile width on disk.
+    */
+   virtual ossim_uint32 getImageTileHeight() const;
+
+   /**
+    * Returns the output pixel type of the tile source.
+    */
+   virtual ossimScalarType getOutputScalarType() const;
+   
+   /**
+    * @brief Gets the decimation factor for a resLevel.
+    * @param resLevel Reduced resolution set for requested decimation.
+    * @param result ossimDpt to initialize with requested decimation.
+    */
+   virtual void getDecimationFactor(ossim_uint32 resLevel,
+                                    ossimDpt& result) const;
+
+   /**
+    * @brief Get array of decimations for all levels.
+    * @param decimations Vector to initialize with decimations.
+    */
+   virtual void getDecimationFactors(vector<ossimDpt>& decimations) const; 
+
+   /**
+    * @brief Returns the number of decimation levels.
+    * 
+    * This returns the total number of decimation levels.  It is important to
+    * note that res level 0 or full resolution is included in the list and has
+    * decimation values 1.0, 1.0
+    * 
+    * @return The number of decimation levels.
+    */
+   virtual ossim_uint32 getNumberOfDecimationLevels()const;
+
+   /**
+    * @brief Gets number of lines for res level.
+    *
+    * Overrides ossimJ2kTileSource::getNumberOfLines
+    *
+    *  @param resLevel Reduced resolution level to return lines of.
+    *  Default = 0
+    *
+    *  @return The number of lines for specified reduced resolution level.
+    */
+   virtual ossim_uint32 getNumberOfLines(ossim_uint32 resLevel = 0) const;
+
+   /**
+    *  @brief Gets the number of samples for res level.
+    *
+    *  Overrides ossimJ2kTileSource::getNumberOfSamples
+    *
+    *  @param resLevel Reduced resolution level to return samples of.
+    *  Default = 0
+    *
+    *  @return The number of samples for specified reduced resolution level.
+    */
+   virtual ossim_uint32 getNumberOfSamples(ossim_uint32 resLevel = 0) const;
+
+   /**
+    * @brief Open method.
+    * @return true on success, false on error.
+    */
+   virtual bool open();
+
+   /**
+    *  @brief Method to test for open file stream.
+    *
+    *  @return true if open, false if not.
+    */
+   virtual bool isOpen()const;
+
+   /**
+    * @brief Method to close current entry.
+    *
+    * @note There is a bool kdu_compressed_source::close() and a
+    * void ossimImageHandler::close(); hence, a new close to avoid conflicting
+    * return types.
+    */
+   virtual void closeEntry();
+
+   /**
+    * Method to the load (recreate) the state of an object from a keyword
+    * list.  Return true if ok or false on error.
+    */
+   virtual bool loadState(const ossimKeywordlist& kwl,
+                          const char* prefix=0);   
+
+protected:
+
+   /**
+   * @brief Gets an overview tile.
+   * 
+   * Overrides ossimImageHandler::getOverviewTile
+   *
+   * @param resLevel The resolution level to pull from with resLevel 0 being
+   * full res.
+   * 
+   * @param result The tile to stuff.  Note The requested rectangle in full
+   * image space and bands should be set in the result tile prior to
+   * passing.  This method will subtract the subImageOffset if needed for
+   * external overview call since they do not know about the sub image offset.
+   *
+   * @return true on success false on error.  Typically this will return false
+   * if resLevel==0 unless the overview has r0.  If return is false, result
+   * is undefined so caller should handle appropriately with makeBlank or
+   * whatever.
+   */
+  virtual bool getOverviewTile(ossim_uint32 resLevel,
+                               ossimImageData* result);   
+
+   /**
+    * @brief Gets kdu source capability.
+    *
+    * Overrides kdu_compressed_source::get_capabilities
+    *
+    * @return KDU_SOURCE_CAP_SEEKABLE
+    */
+   virtual ossim_int32 get_capabilities();
+   
+   /**
+    * @bried Read method.
+    *
+    * Implements pure virtual kdu_compressed_source::read
+    * @param buf Buffer to fill.
+    *
+    * @param num_bytes Bytes to read.
+    *
+    * @return Actual bytes read.
+    */
+   virtual ossim_int32 read(kdu_core::kdu_byte *buf, ossim_int32 num_bytes);
+
+   /**
+    * @brief Seek method.
+    *
+    * Overrides kdu_compressed_source::seek
+    *
+    * @param offset Seek position relative to the start of code stream offset.
+    *
+    * @return true on success, false on error.
+    */
+   virtual bool seek(kdu_core::kdu_long offset);
+
+   /**
+    * @brief Get file position relative to the start of code stream offset.
+    *
+    * Overrides kdu_compressed_source::get_pos
+    *
+    * @return Position in codestream.
+    */   
+   virtual kdu_core::kdu_long get_pos();
+
+private:
+
+   /** @brief Initializes data member "theTile". */
+   void initializeTile();
+
+   /**
+    * Loads a block of data to theCacheTile from the cache.
+    * 
+    * @param x Starting x position of block to load.
+    *
+    * @param y Starting y position of block to load.
+    *
+    * @param clipRect The rectangle to fill.
+    *
+    * @return true on success, false on error.
+    *
+    * @note x and y are zero based relative to the upper left corner so any
+    * sub image offset should be subtracted off.
+    */
+   bool loadTileFromCache(ossim_uint32 x, ossim_uint32 y,
+                          const ossimIrect& clipRect);
+   
+   /**
+    * Loads a block of data to theCacheTile.
+    * 
+    * @param x Starting x position of block to load.
+    *
+    * @param y Starting y position of block to load.
+    *
+    * @return true on success, false on error.
+    *
+    * @note x and y are zero based relative to the upper left corner so any
+    * sub image offset should be subtracted off.
+    */
+   bool loadTile(ossim_uint32 x, ossim_uint32 y);
+
+   kdu_core::kdu_codestream     theCodestream;
+   kdu_core::kdu_thread_env*    theThreadEnv;
+   kdu_core::kdu_thread_queue*  theOpenTileThreadQueue;
+   ossim_uint32                 theSourcePrecisionBits;
+   ossim_uint32                 theMinDwtLevels;
+   std::ifstream                theFileStr;
+   ossimJ2kSizRecord            theSizRecord;
+   ossimScalarType              theScalarType;
+   ossimIrect                   theImageRect;
+   ossimRefPtr<ossimImageData>  theTile;
+   ossimRefPtr<ossimImageData>  theCacheTile;
+   ossim_uint32                 theTileSizeX;
+   ossim_uint32                 theTileSizeY;
+   
+
+   ossimAppFixedTileCache::ossimAppFixedCacheId theCacheId;
+   
+TYPE_DATA   
+};
+
+inline ossim_int32 ossimKakaduJ2kReader::get_capabilities()
+{
+   return ( KDU_SOURCE_CAP_SEEKABLE );
+}
+
+inline ossim_int32 ossimKakaduJ2kReader::read(kdu_core::kdu_byte *buf,
+                                              ossim_int32 num_bytes)
+{
+   theFileStr.read((char*)buf, num_bytes);
+   return theFileStr.gcount();
+}
+
+inline bool ossimKakaduJ2kReader::seek(kdu_core::kdu_long offset)
+{
+   // If the last byte is read, the eofbit must be reset. 
+   if ( theFileStr.eof() )
+   {
+      theFileStr.clear();
+   }
+
+   //---
+   // All seeks are relative to the start of code stream.
+   //---
+   theFileStr.seekg(offset, ios_base::beg);
+
+   return theFileStr.good();
+}
+
+inline kdu_core::kdu_long ossimKakaduJ2kReader::get_pos()
+{
+   //---
+   // Must subtract the SOC(start of code stream) from the real file position
+   // since positions are relative to SOC.
+   //---
+   return static_cast<kdu_core::kdu_long>(theFileStr.tellg());
+}
+
+#endif /* #ifndef ossimKakaduJ2kReader_HEADER */
+
diff --git a/ossim_plugins/kakadu/ossimKakaduJp2Reader.cpp b/ossim_plugins/kakadu/ossimKakaduJp2Reader.cpp
new file mode 100644
index 0000000..68b1aea
--- /dev/null
+++ b/ossim_plugins/kakadu/ossimKakaduJp2Reader.cpp
@@ -0,0 +1,1201 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Description:  Class definition for JPEG2000 JP2 reader.
+//
+//----------------------------------------------------------------------------
+// $Id: ossimKakaduJp2Reader.cpp 23664 2015-12-14 14:17:27Z dburken $
+
+#include "ossimKakaduJp2Reader.h"
+#include "ossimKakaduCommon.h"
+#include "ossimKakaduMessaging.h"
+ 
+#include <ossim/base/ossimCommon.h>
+#include <ossim/base/ossimDpt.h>
+#include <ossim/base/ossimEndian.h>
+#include <ossim/base/ossimException.h>
+#include <ossim/base/ossimKeywordlist.h>
+#include <ossim/base/ossimNotify.h>
+#include <ossim/base/ossimPreferences.h>
+#include <ossim/base/ossimScalarTypeLut.h>
+#include <ossim/base/ossimTrace.h>
+#include <ossim/base/ossimUnitConversionTool.h>
+ 
+#include <ossim/imaging/ossimImageDataFactory.h>
+#include <ossim/imaging/ossimImageGeometryRegistry.h>
+
+#include <ossim/projection/ossimMapProjection.h>
+#include <ossim/projection/ossimProjection.h>
+#include <ossim/projection/ossimProjectionFactoryRegistry.h>
+
+#include <ossim/support_data/ossimFgdcXmlDoc.h>
+#include <ossim/support_data/ossimJ2kSizRecord.h>
+#include <ossim/support_data/ossimJ2kSotRecord.h>
+#include <ossim/support_data/ossimTiffInfo.h>
+#include <ossim/support_data/ossimTiffWorld.h>
+
+#include <kdu_compressed.h>
+#include <kdu_elementary.h>
+#include <kdu_sample_processing.h>
+#include <kdu_region_decompressor.h>
+#include <jp2.h>
+
+#include <fstream>
+#include <iostream>
+#include <string>
+
+//---
+// Kakadu code has defines that have (kdu_uint32) which should be
+// (kdu_core::kdu_uint32)
+//---
+using namespace kdu_core;
+
+#ifdef OSSIM_ID_ENABLED
+static const char OSSIM_ID[] = "$Id";
+#endif
+ 
+static const ossimTrace traceDebug( ossimString("ossimKakaduJp2Reader:debug") );
+static const ossimTrace traceDump( ossimString( "ossimKakaduJp2Reader:dump") );
+
+RTTI_DEF1_INST(ossimKakaduJp2Reader,
+               "ossimKakaduJp2Reader",
+               ossimImageHandler)
+ 
+ossimKakaduJp2Reader::ossimKakaduJp2Reader()
+   : ossimImageHandler(),
+     theJp2FamilySrc(0),
+     theJp2Source(0),
+     theChannels(0),
+     theCodestream(),
+     theThreadEnv(0),
+     theOpenTileThreadQueue(0),
+     theMinDwtLevels(0),
+     theNumberOfBands(0),
+     theCacheSize(0, 0),
+     theScalarType(OSSIM_SCALAR_UNKNOWN),
+     theImageRect(),
+     theJp2Dims(0),
+     theJp2TileDims(0),
+     theTile(),
+     theCacheTile(),
+     theCacheId(-1)
+{
+   kdu_customize_warnings(&pretty_cout); // Deliver warnings to stdout.
+   kdu_customize_errors(&pretty_cerr); // Deliver errors to stderr + throw exc
+}
+
+ossimKakaduJp2Reader::~ossimKakaduJp2Reader()
+{
+   closeEntry();
+}
+
+ossimString ossimKakaduJp2Reader::getShortName()const
+{
+   return ossimString("ossim_kakadu_jp2_reader");
+}
+
+ossimString ossimKakaduJp2Reader::getLongName()const
+{
+   return ossimString("ossim kakadu jp2 reader");
+}
+
+ossimString ossimKakaduJp2Reader::getClassName()const
+{
+   return ossimString("ossimKakaduJp2Reader");
+}
+
+ossim_uint32 ossimKakaduJp2Reader::getNumberOfDecimationLevels()const
+{
+   ossim_uint32 result = 1; // Add r0
+
+   if (theMinDwtLevels)
+   {
+      //---
+      // Add internal overviews.
+      //---
+      result += theMinDwtLevels;
+   }
+
+   if (theOverview.valid())
+   {
+      //---
+      // Add external overviews.
+      //---
+      result += theOverview->getNumberOfDecimationLevels();
+   }
+
+   return result;
+}
+
+ossim_uint32 ossimKakaduJp2Reader::getNumberOfLines(
+   ossim_uint32 resLevel) const
+{
+   ossim_uint32 result = 0;
+   if ( isValidRLevel(resLevel) )
+   {
+      if (resLevel <= theMinDwtLevels)
+      {
+         result = theJp2Dims[resLevel].height();
+      }
+      else if (theOverview.valid())
+      {
+         result = theOverview->getNumberOfLines(resLevel);
+      }
+   }
+   return result;
+}
+
+ossim_uint32 ossimKakaduJp2Reader::getNumberOfSamples(
+   ossim_uint32 resLevel) const
+{
+   ossim_uint32 result = 0;
+   if ( isValidRLevel(resLevel) )
+   {
+      if (resLevel <= theMinDwtLevels)
+      {
+         result = theJp2Dims[resLevel].width();
+      }
+      else if (theOverview.valid())
+      {
+         result = theOverview->getNumberOfSamples(resLevel);
+      }
+   }
+   return result;
+}
+
+bool ossimKakaduJp2Reader::open()
+{
+   static const char MODULE[] = "ossimKakaduJp2Reader::open";
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " entered...\n"
+         << "image: " << theImageFile << "\n";
+   }
+   
+   bool result = false;
+   
+   if(isOpen())
+   {
+      closeEntry();
+   }
+
+   if ( isJp2() )
+   {
+      result = openJp2File();
+
+      if ( !result )
+      {
+         closeEntry();
+      }
+   }
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " exit status = " << (result?"true":"false\n")
+         << std::endl;
+   }
+
+   return result;
+}
+
+bool ossimKakaduJp2Reader::isJp2()
+{
+   bool result = true;
+
+   std::ifstream str;
+   str.open(theImageFile.chars(), ios::in | ios::binary);
+
+   if ( str.is_open() )
+   {
+      const ossim_uint8 J2K_SIGNATURE_BOX[SIGNATURE_BOX_SIZE] = 
+         {0x00,0x00,0x00,0x0c,0x6a,0x50,0x20,0x20,0x0d,0x0a,0x87,0x0a};
+      
+      ossim_uint8 box[SIGNATURE_BOX_SIZE];
+      
+      // Read in the box.
+      str.read((char*)box, SIGNATURE_BOX_SIZE);
+      
+      for (ossim_uint32 i = 0; i < SIGNATURE_BOX_SIZE; ++i)
+      {
+         if (box[i] != J2K_SIGNATURE_BOX[i])
+         {
+            result = false;
+            break;
+         }
+      }
+
+      str.close();
+   }
+   else
+   {
+      result = false;
+      
+      if(traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG)
+            << "isJp2 ERROR:"
+            << "\nCannot open:  " << theImageFile.chars() << endl;
+      }
+   }
+   
+   return result;
+}
+
+bool ossimKakaduJp2Reader::openJp2File()
+{
+   static const char MODULE[] = "ossimKakaduJp2Reader::openJp2File";
+   
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " entered...\n";
+   }
+
+   bool result = false;
+   
+   theJp2FamilySrc = new kdu_supp::jp2_family_src();
+
+   theJp2FamilySrc->open(theImageFile.chars(), true);
+
+   if (theJp2FamilySrc->exists())
+   {
+      kdu_supp::jp2_source* src = new kdu_supp::jp2_source();
+      theJp2Source = src;
+      
+      src->open(theJp2FamilySrc);
+
+      src->read_header();
+
+      if (traceDebug())
+      {
+         kdu_supp::jp2_colour colour = src->access_colour();
+         if ( colour.exists() )
+         {
+            ossimNotify(ossimNotifyLevel_DEBUG)
+               << "jp2 color space: " << colour.get_space() << std::endl;
+         }
+      }
+
+      theThreadEnv = new kdu_core::kdu_thread_env();
+         
+      theThreadEnv->create(); // Creates the single "owner" thread
+
+      ossim_uint32 threads = 1;
+      
+      const char* lookup = ossimPreferences::instance()->findPreference("kakadu_threads");
+      if ( lookup )
+      {
+         threads = ossimString::toUInt32(lookup);
+         if ( threads > 1 )
+         {
+            for (ossim_uint32 nt=1; nt < threads; ++nt)
+            {
+               if ( !theThreadEnv->add_thread() )
+               {
+                  if (traceDebug())
+                  {
+                     ossimNotify(ossimNotifyLevel_WARN)
+                        << "Unable to create thread!\n";
+                  }
+               }
+            }
+         }
+      }
+
+      theOpenTileThreadQueue =
+         theThreadEnv->add_queue(NULL,NULL,"open_tile_q");
+         
+      theCodestream.create(theJp2Source, theThreadEnv);
+         
+      if ( theCodestream.exists() )
+      {
+         // This must be done before anything else...
+         theCodestream.set_persistent();
+         
+         theCodestream.enable_restart(); // ????
+         
+         // Get the image and tile dimensions.
+         if ( ossim::getCodestreamDimensions(theCodestream,
+                                             theJp2Dims,
+                                             theJp2TileDims) )
+         {
+            //---
+            // Set the image size.
+            //
+            // NOTE:
+            //
+            // The geojp2 doqq's that I have all have an offset in them.  In
+            // other words the "pos" from "get_dims" is not always 0,0.  I
+            // think this was intended for mosaicing without any projection. I
+            // do NOT think it was intended to be used as a sub image offset
+            // into the projection picked up by the geotiff_box. If this were
+            // so the current code here would not mosaic correctly.
+            //
+            // This may not be the case though with all data sets...  In which
+            // case some kind of logic would have to be added to this code.
+            //---
+            theImageRect = ossimIrect( 0,
+                                       0,
+                                       theJp2Dims[0].width() -1,
+                                       theJp2Dims[0].height()-1);
+            
+            // Number of internal dwl layers
+            theMinDwtLevels = theCodestream.get_min_dwt_levels();
+
+            // Get the number of bands.
+            theNumberOfBands =
+               static_cast<ossim_uint32>(theCodestream.
+                                         get_num_components(true));
+            
+            //---
+            // Set the cache tile size.  Use the internal j2k tile size if it's
+            // reasonable else clamp to some max.  Some j2k writer make one
+            // BIG tile so this must be done.
+            //---
+            const ossim_uint32 MAX_CACHE_TILE_DIMENSION = 1024;
+            theCacheSize.x =
+               static_cast<ossim_int32>(
+                  (theJp2TileDims[0].width() <= MAX_CACHE_TILE_DIMENSION) ?
+                  theJp2TileDims[0].width() : MAX_CACHE_TILE_DIMENSION );
+            theCacheSize.y =
+               static_cast<ossim_int32>(
+                  (theJp2TileDims[0].height() <= MAX_CACHE_TILE_DIMENSION) ?
+                  theJp2TileDims[0].height() : MAX_CACHE_TILE_DIMENSION );
+            
+            // Set the scalar:
+            int bitDepth   = theCodestream.get_bit_depth(0, true);
+            bool isSigned  = theCodestream.get_signed(0, true);
+
+            switch (bitDepth)
+            {
+               case 8:
+               {
+                  theScalarType = OSSIM_UINT8;
+                  break;
+               }
+               case 11:
+               {
+                  if (!isSigned)
+                  {
+                     theScalarType = OSSIM_USHORT11;
+                  }
+                  else
+                  {
+                     theScalarType = OSSIM_SINT16;
+                  }
+                  break;
+               }
+               case 16:
+               {
+                  if (!isSigned)
+                  {
+                     theScalarType = OSSIM_UINT16;
+                  }
+                  else
+                  {
+                     theScalarType = OSSIM_SINT16;
+                  }
+                  break;
+               }
+               default:
+               {
+                  theScalarType = OSSIM_SCALAR_UNKNOWN;
+                  break;
+               }
+            }
+            
+            if (theScalarType != OSSIM_SCALAR_UNKNOWN)
+            {
+               // Initialize the cache.
+               if (theCacheId != -1)
+               {
+                  ossimAppFixedTileCache::instance()->deleteCache(theCacheId);
+                  theCacheId = -1;
+               }
+               
+               ossimIrect fullImgRect = theImageRect;
+               fullImgRect.stretchToTileBoundary(theCacheSize);
+
+               theCacheId = ossimAppFixedTileCache::instance()->
+                  newTileCache(fullImgRect, theCacheSize);
+               
+               // Initialize the tile we will return.
+               initializeTile();
+               
+               // Call the base complete open to pick up overviews.
+               completeOpen();
+
+               // Set up channel mapping for copyRegionToTile if it makes sense.
+               configureChannelMapping();
+
+               // We should be good now so set the return result to true.
+               result = true;
+               
+               if (traceDebug())
+               {
+                  ossim::print(ossimNotify(ossimNotifyLevel_DEBUG),
+                               theCodestream);
+                  ossimNotify(ossimNotifyLevel_DEBUG)
+                     << "\ntheImageRect:      " << theImageRect
+                     << "\nFull image rect:   " << fullImgRect
+                     << "\ntheCacheSize:  " << theCacheSize
+                     << "\nscalar type:       "
+                     << ossimScalarTypeLut::instance()->
+                     getEntryString(theScalarType)
+                     << "\n";
+                  
+                  for (ossim_uint32 level=0;
+                       level < theJp2Dims.size(); ++level)
+                  {
+                     ossimNotify(ossimNotifyLevel_DEBUG)
+                        << "theJp2Dims[" << level << "]: "
+                        << theJp2Dims[level]
+                        << "\ntheJp2TileDims[" << level << "]: "
+                        << theJp2TileDims[level] << "\n";
+                  }
+                  ossimNotify(ossimNotifyLevel_DEBUG)
+                     << "threads: " << threads << endl;
+               }
+               
+            } // if (theScalarType != OSSIM_SCALAR_UNKNOWN)
+
+         } // matches: if ( ossim::getCodestreamDimensions
+            
+      } // matches: if ( theCodestream.exists() )
+         
+   } //  if (theJp2FamilySrc->exists())
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " exit status = " << (result?"true":"false\n")
+         << std::endl;
+   }
+
+   return result;      
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " exit status = " << (result?"true":"false\n")
+         << std::endl;
+   }
+
+   return result;
+}
+
+bool ossimKakaduJp2Reader::isOpen()const
+{
+   return theTile.valid();
+   
+   // return theCodestream.exists()
+   // return theFileStr.is_open();
+}
+
+void ossimKakaduJp2Reader::closeEntry()
+{
+   // Cleanup processing environment
+   if ( theThreadEnv )
+   {
+      theThreadEnv->join(NULL,true); // Wait until all internal processing is complete.
+      theThreadEnv->terminate(theOpenTileThreadQueue, true);
+      theThreadEnv->cs_terminate(theCodestream);   // Terminates background codestream processing.
+      theThreadEnv->destroy();
+      delete theThreadEnv;
+      theThreadEnv = 0;
+   }
+   
+   theTile = 0;
+   theCacheTile = 0;
+
+   if (theChannels)
+   {
+      theChannels->clear();
+      delete theChannels;
+      theChannels = 0;
+   }
+   if(theCodestream.exists())
+   {
+      theCodestream.destroy();
+   }
+   
+   if (theJp2Source)
+   {
+      delete theJp2Source;
+      theJp2Source = 0;
+   }
+
+   if (theJp2FamilySrc)
+   {
+      delete theJp2FamilySrc;
+      theJp2FamilySrc = 0;
+   }
+
+   if (theOpenTileThreadQueue)
+   {
+      theOpenTileThreadQueue = 0;
+   }
+
+   if (theCacheId != -1)
+   {
+      ossimAppFixedTileCache::instance()->deleteCache(theCacheId);
+      theCacheId = -1;
+   }
+
+   ossimImageHandler::close();
+}
+
+ossimRefPtr<ossimImageData> ossimKakaduJp2Reader::getTile(
+   const ossimIrect& rect, ossim_uint32 resLevel)
+{
+   // This tile source bypassed, or invalid res level, return null tile.
+   if(!isSourceEnabled() || !isOpen() || !isValidRLevel(resLevel))
+   {
+      return ossimRefPtr<ossimImageData>();
+   }
+
+   if (theTile.valid())
+   {
+      // Rectangle must be set prior to getOverviewTile call.
+      theTile->setImageRectangle(rect);
+
+      if (resLevel)
+      {
+         if ( getOverviewTile(resLevel, theTile.get()) == false )
+         {
+            theTile->makeBlank();
+         }
+      }
+      else // r0
+      {
+         // NOTE:  Using cache for r0 tiles.
+
+         //---
+         // See if the whole tile is going to be filled, if not, start out with
+         // a blank tile so data from a previous load gets wiped out.
+         //---
+         if ( !rect.completely_within(theImageRect) )
+         {
+            // Start with a blank tile.
+            theTile->makeBlank();
+         }
+         
+         //---
+         // See if any point of the requested tile is in the image.
+         //---
+         if ( rect.intersects(theImageRect) )
+         {
+            ossimIrect clipRect = rect.clipToRect(theImageRect);
+
+            ossimIrect expandedRect = clipRect;
+            expandedRect.stretchToTileBoundary(theCacheSize);
+
+            //---
+            // Shift the upper left corner of the "clip_rect" to the an even
+            // j2k tile boundry.  
+            //---
+            ossimIpt tileOrigin = expandedRect.ul();
+            
+            // Vertical tile loop.
+            while (tileOrigin.y < expandedRect.lr().y)
+            {
+               // Horizontal tile loop.
+               while (tileOrigin.x < expandedRect.lr().x)
+               {
+                  if ( loadTileFromCache(tileOrigin, clipRect) == false )
+                  {
+                     if ( loadTile(tileOrigin) )
+                     {
+                        //---
+                        // Note: Clip the cache tile to the image clipRect
+                        // since there are j2k tiles that go beyond the image
+                        // dimensions, i.e., edge tiles.
+                        //---    
+                        ossimIrect cr =
+                           theCacheTile->getImageRectangle().
+                           clipToRect(clipRect);
+                        
+                        theTile->loadTile(theCacheTile->getBuf(),
+                                          theCacheTile->getImageRectangle(),
+                                          cr,
+                                          OSSIM_BSQ);
+                     }
+                     
+                  }
+                  
+                  tileOrigin.x += theCacheSize.x; // Go to next tile.
+
+               } // End loop in x direction.
+               
+               // Go to next row of tiles.
+               tileOrigin.x = expandedRect.ul().x;
+               tileOrigin.y += theCacheSize.y;
+               
+            }  // End loop in y direction.
+
+            // Set the tile status.
+            theTile->validate();
+            
+         } // matches: if ( rect.intersects(theImageRect) )
+         
+      } // r0 block
+      
+   } // matches: if (theTile.valid())
+
+   return theTile;
+}
+
+bool ossimKakaduJp2Reader::getOverviewTile(ossim_uint32 resLevel,
+                                           ossimImageData* result)
+{
+   bool status = false;
+
+   if ( (resLevel < getNumberOfDecimationLevels()) && result && 
+        (result->getNumberOfBands() == getNumberOfOutputBands()) )
+   {
+      if (resLevel <= theMinDwtLevels)
+      {
+         // Using internal overviews.
+
+         //---
+         // NOTE:
+         //
+         // The geojp2 doqq's that I have all have an offset in them.  In
+         // other words the "pos" from "get_dims" is not always 0,0.  I
+         // think this was intended for mosaicing without any projection. I
+         // do NOT think it was intended to be used as a sub image offset
+         // into the projection picked up by the geotiff_box. If this were
+         // so the current code here would not mosaic correctly.
+         //
+         // This may not be the case though with all data sets...  In which
+         // case some kind of logic would have to be added to this code.
+         //---
+         ossimIrect originalTileRect = result->getImageRectangle();
+
+         ossimIrect shiftedRect = originalTileRect + theJp2Dims[resLevel].ul();
+
+         result->setImageRectangle(shiftedRect);
+         
+         try
+         {
+            if ( theChannels )
+            {
+               status = ossim::copyRegionToTile(theChannels,
+                                                theCodestream,
+                                                static_cast<int>(resLevel),
+                                                theThreadEnv,
+                                                theOpenTileThreadQueue,
+                                                result);
+            }
+            else
+            {
+               status = ossim::copyRegionToTile(theCodestream,
+                                                static_cast<int>(resLevel),
+                                                theThreadEnv,
+                                                theOpenTileThreadQueue,
+                                                result);
+            }     
+         }
+         catch(const ossimException& e)
+         {
+            ossimNotify(ossimNotifyLevel_WARN)
+               << __FILE__ << " " << __LINE__ << " caught exception\n"
+               << e.what();
+            status = false;
+         }
+         
+         // Set the rect back.
+         result->setImageRectangle(originalTileRect);
+         
+      }  // matches:  if (resLevel <= theMinDwtLevels)
+      else
+      {
+         // Using external overview.
+         status = theOverview->getTile(result, resLevel);
+      }
+   }
+
+   return status;
+}
+
+ossim_uint32 ossimKakaduJp2Reader::getNumberOfInputBands() const
+{
+   return theNumberOfBands;
+}
+
+ossim_uint32 ossimKakaduJp2Reader::getNumberOfOutputBands()const
+{
+   return theNumberOfBands;
+}
+
+ossim_uint32 ossimKakaduJp2Reader::getImageTileWidth() const
+{
+   ossim_uint32 result = 0;
+   if ( theJp2TileDims.size() )
+   {
+      if ( theJp2TileDims[0].width() != theImageRect.width() )
+      {
+         // Not a single tile.
+         result = theJp2TileDims[0].width();
+      }
+   }
+   return result;
+}
+
+ossim_uint32 ossimKakaduJp2Reader::getImageTileHeight() const
+{
+   ossim_uint32 result = 0;
+   if ( theJp2TileDims.size() )
+   {
+      if ( theJp2TileDims[0].height() != theImageRect.height() )
+      {
+         // Not a single tile.
+         result = static_cast<ossim_uint32>(theJp2TileDims[0].height());
+      }
+   }
+   return result;
+}
+
+ossimScalarType ossimKakaduJp2Reader::getOutputScalarType() const
+{
+   return theScalarType;
+}
+ 
+void ossimKakaduJp2Reader::initializeTile()
+{
+   ossim_uint32 width  = this->getImageTileWidth();
+   ossim_uint32 height = this->getImageTileHeight();
+
+   // Check for zero width, height and limit output tile sizes to 1024.
+   if ( !width || !height || ( width > 1024) || (height > 1024) )
+   {
+      ossimIpt tileSize;
+      ossim::defaultTileSize(tileSize);
+
+      width  = tileSize.x;
+      height = tileSize.y;
+   }
+   
+   theTile = ossimImageDataFactory::instance()->
+      create( this,
+              this->getOutputScalarType(),
+              this->getNumberOfOutputBands(),
+              width,
+              height);
+
+   theTile->initialize();
+
+   theCacheTile = ossimImageDataFactory::instance()->
+      create( this,
+              this->getOutputScalarType(),
+              this->getNumberOfOutputBands(),
+              theCacheSize.x,
+              theCacheSize.y );
+   
+   theCacheTile->initialize();
+}
+
+bool ossimKakaduJp2Reader::loadTileFromCache(const ossimIpt& origin,
+                                             const ossimIrect& clipRect)
+{
+   bool result = false;
+   
+   ossimRefPtr<ossimImageData> tempTile =
+      ossimAppFixedTileCache::instance()->getTile(theCacheId, origin);
+   if (tempTile.valid())
+   {
+      //---
+      // Note: Clip the cache j2k tile to the image clipRect since
+      // there are j2k tiles that go beyond the image dimensions, i.e.,
+      // edge tiles.
+      //---
+      ossimIrect cr = tempTile->getImageRectangle().clipToRect(clipRect);
+
+      theTile->loadTile(tempTile.get()->getBuf(),
+                        tempTile->getImageRectangle(),
+                        cr,
+                        OSSIM_BSQ);
+      result = true;
+   }
+
+   return result;
+}
+
+bool ossimKakaduJp2Reader::loadTile(const ossimIpt& origin)
+{
+   bool result = true;
+   
+   ossimIpt lr(origin.x + theCacheSize.x - 1,
+               origin.y + theCacheSize.y - 1);
+
+   // Set the cache rectangle to be an even j2k tile.
+   theCacheTile->setImageRectangle(ossimIrect(origin, lr));
+
+   // Let the getOverviewTile do the rest of the work.
+   if ( getOverviewTile(0, theCacheTile.get()) )
+   {
+      // Add it to the cache for the next time.
+      ossimAppFixedTileCache::instance()->addTile(theCacheId, theCacheTile);
+   }
+   else
+   {
+      ossimNotify(ossimNotifyLevel_WARN)
+         << __FILE__ << __LINE__
+         << " ossimKakaduJp2Reader::loadBlock failed!"
+         << std::endl;
+      result = false;
+   }
+   
+   return result;
+}
+
+ossimRefPtr<ossimImageGeometry> ossimKakaduJp2Reader::getImageGeometry()
+{
+   if ( !theGeometry )
+   {
+      //---
+      // Check for external geom - this is a file.geom not to be confused with
+      // geometries picked up from dot.xml, dot.prj, dot.j2w and so on.  We
+      // will check for that later if the getInternalImageGeometry fails.
+      //---
+      theGeometry = getExternalImageGeometry();
+      
+      if ( !theGeometry )
+      {
+         //---
+         // Check for external files other than .geom, i.e. file.xml & j2w:
+         //---
+         theGeometry = getMetadataImageGeometry();
+
+         if ( !theGeometry )
+         {
+            // Check the internal geometry first to avoid a factory call.
+            theGeometry = getInternalImageGeometry();
+
+            //---
+            // WARNING:
+            // Must create/set the geometry at this point or the next call to
+            // ossimImageGeometryRegistry::extendGeometry will put us in an infinite loop
+            // as it does a recursive call back to ossimImageHandler::getImageGeometry().
+            //---
+            if ( !theGeometry )
+            {
+               theGeometry = new ossimImageGeometry();
+            }
+            
+            // Check for set projection.
+            if ( !theGeometry->getProjection() )
+            {
+               // Last try factories for projection.
+               ossimImageGeometryRegistry::instance()->extendGeometry(this);
+            }
+         }
+      }
+
+      // Set image things the geometry object should know about.
+      initImageParameters( theGeometry.get() );
+   }
+   return theGeometry;
+}
+
+ossimRefPtr<ossimImageGeometry> ossimKakaduJp2Reader::getInternalImageGeometry()
+{
+   static const char MODULE[] = "ossimKakaduJp2Reader::getInternalImageGeometry";
+   ossimRefPtr<ossimImageGeometry> geom = 0;
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " entered...\n";
+   }
+   
+   kdu_supp::jp2_family_src* familySrc = new kdu_supp::jp2_family_src();
+   
+   familySrc->open(theImageFile.c_str(), true);
+   kdu_supp::jp2_input_box box;
+   box.open(familySrc);
+
+   const ossim_uint8 GEOTIFF_UUID[GEOTIFF_UUID_SIZE] = 
+   {
+      0xb1, 0x4b, 0xf8, 0xbd,
+      0x08, 0x3d, 0x4b, 0x43,
+      0xa5, 0xae, 0x8c, 0xd7,
+      0xd5, 0xa6, 0xce, 0x03
+   };
+
+   const ossim_uint8 MSIG_UUID[16] = 
+   {
+      0x96, 0xA9, 0xF1, 0xF1,
+      0xDC, 0x98, 0x40, 0x2D,
+      0xA7, 0xAE, 0xD6, 0x8E,
+      0x34, 0x45, 0x18, 0x09
+   };
+   
+   while(box.exists()&&!geom.valid())
+   {
+#if 0 // debug stuff
+      ossim_uint32 boxType =  box.get_box_type();
+      char ch[] = { (char) ( boxType >> 24 ), (char) ( boxType >> 16 ), (char) ( boxType >> 8 ) ,
+                    (char) ( boxType >> 0 ), '\0' };
+      
+      std::cout << ch << std::endl;
+      std::cout << std::hex << "BOX TYPE = " << box.get_box_type()
+                << std::dec << " bytes = " << box.get_remaining_bytes() << std::endl;
+#endif
+      
+      switch(box.get_box_type())
+      {
+         case jp2_uuid_4cc:
+         {
+            std::vector<kdu_byte> byteBuffer;
+            byteBuffer.resize(box.get_remaining_bytes());
+            box.read(&byteBuffer.front(), box.get_remaining_bytes());
+            if(memcmp((char*)&byteBuffer.front(),GEOTIFF_UUID, GEOTIFF_UUID_SIZE)==0)
+            {
+               ossimTiffInfo info;
+               std::istringstream str(ossimString((char*)&byteBuffer.front()+GEOTIFF_UUID_SIZE,
+                                                  (char*)&byteBuffer.front() + byteBuffer.size()));
+               ossim_uint32 entry = 0;
+               ossimKeywordlist kwl; // Used to capture geometry data. 
+
+               if ( info.getImageGeometry(str, kwl, entry) )
+               {
+                  //---
+                  // The tiff embedded in the geojp2 only has one line
+                  // and one sample by design so overwrite the lines and
+                  // samples with the real value.
+                  //---
+                  ossimString pfx = "image";
+                  pfx += ossimString::toString(entry);
+                  pfx += ".";
+                  
+                  // Add the lines.
+                  kwl.add(pfx.chars(), ossimKeywordNames::NUMBER_LINES_KW,
+                          getNumberOfLines(0), true);
+                  
+                  // Add the samples.
+                  kwl.add(pfx.chars(), ossimKeywordNames::NUMBER_SAMPLES_KW,
+                          getNumberOfSamples(0), true);
+                  
+                  // Create the projection.
+                  ossimRefPtr<ossimProjection> proj =
+                     ossimProjectionFactoryRegistry::instance()->createProjection(kwl, pfx);
+                  if ( proj.valid() )
+                  {
+                     // Create and assign projection to our ossimImageGeometry object.
+                     geom = new ossimImageGeometry();
+                     geom->setProjection( proj.get() );
+                     if (traceDebug())
+                     {
+                        ossimNotify(ossimNotifyLevel_DEBUG) << "Found GeoTIFF box." << std::endl;
+                     }
+                     
+                     // Get the internal raster pixel alignment type and set the base class.
+                     const char* lookup = kwl.find(pfx.chars(), ossimKeywordNames::PIXEL_TYPE_KW);
+                     if ( lookup )
+                     {
+                        ossimString type = lookup;
+                        type.downcase();
+                        if ( type == "pixel_is_area" )
+                        {
+                           thePixelType = OSSIM_PIXEL_IS_AREA;
+                        }
+                        else if ( type == "pixel_is_point" )
+                        {
+                           thePixelType = OSSIM_PIXEL_IS_POINT;
+                        }
+                     }
+                  }
+               }
+            }  
+            else if(memcmp((char*)&byteBuffer.front(),MSIG_UUID, 16)==0)
+            {
+               
+            }
+            break;
+         }
+         case jp2_xml_4cc:// gml could be here
+         {
+            break;
+         }
+         case jp2_association_4cc: // ASOC BOX GML stuff could be here
+         {
+            break;
+         }
+         default:
+         {
+            break;
+         }
+      }
+      box.close();
+      box.open_next();
+   }
+   familySrc->close();
+   delete familySrc;
+   return geom;
+}
+
+ossimRefPtr<ossimImageGeometry> ossimKakaduJp2Reader::getMetadataImageGeometry() const
+{
+   static const char M[] = "ossimKakaduJp2Reader::getMetadataImageGeometry";
+   if ( traceDebug() )
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG) << M << " entered...\n";
+   }
+   
+   ossimRefPtr<ossimImageGeometry> geom = 0;
+   ossimRefPtr<ossimProjection>    proj = 0;
+
+   // See if we can pick up the projection from the FGDC file:
+   ossimFilename fdgcFile = theImageFile;
+   
+   fdgcFile += ".xml"; // file.jp2.xml
+   if ( fdgcFile.exists() == false ) 
+   {
+      fdgcFile = theImageFile;
+      fdgcFile.setExtension(ossimString("xml")); // file.xml
+   }
+   
+   if ( fdgcFile.exists() )
+   {
+      ossimFgdcXmlDoc fgdcDoc;
+      if ( fgdcDoc.open(fdgcFile) )
+      {
+         try
+         {
+            proj = fgdcDoc.getGridCoordSysProjection();
+         }
+         catch (const ossimException& e)
+         {
+            ossimNotify(ossimNotifyLevel_WARN) << e.what() << std::endl;
+         }
+
+         if ( proj.valid() )
+         {
+            geom = new ossimImageGeometry();
+
+            ossimMapProjection* mapProj = dynamic_cast<ossimMapProjection*>(proj.get());
+            if ( mapProj )
+            {
+               // See if we have a world file.  Seems they have a more accurate tie point.
+               ossimFilename worldFile = theImageFile;
+               worldFile.setExtension(ossimString("j2w")); // file.j2w
+               if ( worldFile.exists() )
+               {
+                  //---
+                  // Note need a way to determine pixel type from fgdc doc.
+                  // This can result in a half pixel shift.
+                  //---
+                  ossimPixelType pixelType = OSSIM_PIXEL_IS_POINT;
+                  ossimUnitType  unitType  = fgdcDoc.getUnitType();
+                  
+                  ossimTiffWorld tfw;
+                  if ( tfw.open(worldFile, pixelType, unitType) )
+                  {
+                     ossimDpt gsd = tfw.getScale();
+                     gsd.y = std::fabs(gsd.y); // y positive up so negate.
+                     ossimDpt tie = tfw.getTranslation();
+                     
+                     if ( unitType != OSSIM_METERS )
+                     {
+                        ossimUnitConversionTool uct;
+                        
+                        // GSD (scale):
+                        uct.setValue(gsd.x, unitType);
+                        gsd.x = uct.getValue(OSSIM_METERS);
+                        uct.setValue(gsd.y, unitType);
+                        gsd.y = uct.getValue(OSSIM_METERS);
+                        
+                        // Tie point:
+                        uct.setValue(tie.x, unitType);
+                        tie.x = uct.getValue(OSSIM_METERS);
+                        uct.setValue(tie.y, unitType);
+                        tie.y = uct.getValue(OSSIM_METERS);
+                     }
+                     
+                     mapProj->setMetersPerPixel(gsd);
+                     mapProj->setUlTiePoints(tie);
+                  }
+                  
+                  if ( tfw.getRotation() != 0.0 )
+                  {
+                     ossimNotify(ossimNotifyLevel_WARN)
+                        << M << " Unhandled rotation in tfw file." << std::endl;
+                  }
+               }
+               
+            } // if ( worldFile.exists() )
+               
+            geom->setProjection( proj.get() );
+            
+         }  // if ( proj.valid() )
+         
+      } // if ( fgdcDoc.open(fdgcFile) )
+      
+   } // if ( fdgcFile.exists() )
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << M << " exit status = " << (geom.valid()?"true":"false\n")
+         << std::endl;
+   }   
+   
+   return geom;
+}
+
+bool ossimKakaduJp2Reader::loadState(const ossimKeywordlist& kwl,
+                                     const char* prefix)
+{
+   bool result = false;
+   if ( ossimImageHandler::loadState(kwl, prefix) )
+   {
+      result = open();
+   }
+   return result;
+}
+
+void ossimKakaduJp2Reader::configureChannelMapping()
+{
+   bool result = false;
+   
+   if ( theChannels )
+   {
+      theChannels->clear();
+   }
+   else
+   {
+      theChannels = new kdu_supp::kdu_channel_mapping;
+   }
+            
+   if ( theJp2Source )
+   {
+      // Currently ignoring alpha:
+      result = theChannels->configure(static_cast<kdu_supp::jp2_source*>(theJp2Source), false);
+   }
+   else
+   {
+      result = theChannels->configure(theCodestream);
+   }
+    
+   if ( result )
+   {
+      // If we the mapping doesn't have all our bands we don't use it.
+      if ( theChannels->get_num_colour_channels() !=  static_cast<int>(theNumberOfBands) )
+      {
+         result = false;
+      }
+   }
+
+   if ( !result )
+   {
+      theChannels->clear();
+      delete theChannels;
+      theChannels = 0;
+   }
+}
+
diff --git a/ossim_plugins/kakadu/ossimKakaduJp2Reader.h b/ossim_plugins/kakadu/ossimKakaduJp2Reader.h
new file mode 100644
index 0000000..77947af
--- /dev/null
+++ b/ossim_plugins/kakadu/ossimKakaduJp2Reader.h
@@ -0,0 +1,311 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Description:  Class declaration for JPEG2000 JP2 reader.
+//
+// Specification: ISO/IEC 15444
+//
+//----------------------------------------------------------------------------
+// $Id: ossimKakaduJp2Reader.h 23664 2015-12-14 14:17:27Z dburken $
+
+#ifndef ossimKakaduJp2Reader_HEADER
+#define ossimKakaduJp2Reader_HEADER 1
+
+
+#include "../ossimPluginConstants.h"
+#include <ossim/base/ossimIpt.h>
+#include <ossim/base/ossimIrect.h>
+#include <ossim/base/ossimRefPtr.h>
+#include <ossim/imaging/ossimAppFixedTileCache.h>
+#include <ossim/imaging/ossimImageData.h>
+#include <ossim/imaging/ossimImageHandler.h>
+#include <ossim/support_data/ossimJ2kSizRecord.h>
+
+#include <kdu_compressed.h>
+
+#include <vector>
+
+// Forward declarations:
+
+class ossimKeywordlist;
+
+class kdu_tile;
+
+namespace kdu_core
+{
+   class kdu_compressed_source;
+   class kdu_line_buf;
+   class kdu_thread_queue;
+}
+
+namespace kdu_supp
+{
+   struct kdu_channel_mapping;
+   class jp2_family_src;
+}
+
+/**
+ * @brief ossimKakaduJp2Reader class for reading images with JPEG2000
+ * (J2K) compressed blocks using kakadu library for decompression. 
+ */
+class OSSIM_PLUGINS_DLL ossimKakaduJp2Reader : public ossimImageHandler
+{
+public:
+
+   /** default construtor */
+   ossimKakaduJp2Reader();
+   
+   /** virtural destructor */
+   virtual ~ossimKakaduJp2Reader();
+
+   /**
+    * @brief Returns short name.
+    * @return "ossim_kakadu_jp2_reader"
+    */
+   virtual ossimString getShortName() const;
+   
+   /**
+    * @brief Returns long  name.
+    * @return "ossim kakadu jp2 reader"
+    */
+   virtual ossimString getLongName()  const;
+
+   /**
+    * @brief Returns class name.
+    * @return "ossimKakaduJp2Reader"
+    */
+   virtual ossimString getClassName() const;
+
+   /**
+    *  @brief Method to grab a tile(rectangle) from image.
+    *
+    *  @param rect The zero based rectangle to grab.
+    *
+    *  @param resLevel The reduced resolution level to grab from.
+    *
+    *  @return The ref pointer with the image data pointer.
+    */
+   virtual ossimRefPtr<ossimImageData> getTile(const  ossimIrect& rect,
+                                               ossim_uint32 resLevel=0);
+
+   /**
+    *  Returns the number of bands in the image.
+    *  Satisfies pure virtual from ImageHandler class.
+    */
+   virtual ossim_uint32 getNumberOfInputBands() const;
+
+   /**
+    * Returns the number of bands in a tile returned from this TileSource.
+    * Note: we are supporting sources that can have multiple data objects.
+    * If you want to know the scalar type of an object you can pass in the
+    */
+   virtual ossim_uint32 getNumberOfOutputBands()const;
+   
+   /**
+    * Returns the tile width of the image or 0 if the image is not tiled.
+    * Note: this is not the same as the ossimImageSource::getTileWidth which
+    * returns the output tile width which can be different than the internal
+    * image tile width on disk.
+    */
+   virtual ossim_uint32 getImageTileWidth() const;
+
+   /**
+    * Returns the tile width of the image or 0 if the image is not tiled.
+    * Note: this is not the same as the ossimImageSource::getTileWidth which
+    * returns the output tile width which can be different than the internal
+    * image tile width on disk.
+    */
+   virtual ossim_uint32 getImageTileHeight() const;
+
+   /**
+    * Returns the output pixel type of the tile source.
+    */
+   virtual ossimScalarType getOutputScalarType() const;
+   
+   /**
+    * @brief Returns the number of decimation levels.
+    * 
+    * This returns the total number of decimation levels.  It is important to
+    * note that res level 0 or full resolution is included in the list and has
+    * decimation values 1.0, 1.0
+    * 
+    * @return The number of decimation levels.
+    */
+   virtual ossim_uint32 getNumberOfDecimationLevels()const;
+
+   /**
+    * @brief Gets number of lines for res level.
+    *
+    * Overrides ossimJ2kTileSource::getNumberOfLines
+    *
+    *  @param resLevel Reduced resolution level to return lines of.
+    *  Default = 0
+    *
+    *  @return The number of lines for specified reduced resolution level.
+    */
+   virtual ossim_uint32 getNumberOfLines(ossim_uint32 resLevel = 0) const;
+
+   /**
+    *  @brief Gets the number of samples for res level.
+    *
+    *  Overrides ossimJ2kTileSource::getNumberOfSamples
+    *
+    *  @param resLevel Reduced resolution level to return samples of.
+    *  Default = 0
+    *
+    *  @return The number of samples for specified reduced resolution level.
+    */
+   virtual ossim_uint32 getNumberOfSamples(ossim_uint32 resLevel = 0) const;
+
+   /**
+    * @brief Open method.
+    * @return true on success, false on error.
+    */
+   virtual bool open();
+
+   /**
+    *  @brief Method to test for open file stream.
+    *
+    *  @return true if open, false if not.
+    */
+   virtual bool isOpen()const;
+
+   /**
+    * @brief Method to close current entry.
+    *
+    * @note There is a bool kdu_compressed_source::close() and a
+    * void ossimImageHandler::close(); hence, a new close to avoid conflicting
+    * return types.
+    */
+   virtual void closeEntry();
+
+   /** Anonymous enumerations: */
+   enum
+   {
+      SIGNATURE_BOX_SIZE = 12,
+      GEOTIFF_UUID_SIZE  = 16
+   };
+
+   /**
+    * Returns the image geometry object associated with this tile source or
+    * NULL if non defined.  The geometry contains full-to-local image
+    * transform as well as projection (image-to-world).
+    */
+   virtual ossimRefPtr<ossimImageGeometry> getImageGeometry();
+
+   /**
+    * @param Method to get geometry from the embedded JP2 GeoTIFF Box.
+    */
+   virtual ossimRefPtr<ossimImageGeometry> getInternalImageGeometry();
+
+   /**
+    * Method to the load (recreate) the state of an object from a keyword
+    * list.  Return true if ok or false on error.
+    */
+   virtual bool loadState(const ossimKeywordlist& kwl, const char* prefix=0);   
+   
+protected:
+
+   /**
+   * @brief Gets an overview tile.
+   * 
+   * Overrides ossimImageHandler::getOverviewTile
+   *
+   * @param resLevel The resolution level to pull from with resLevel 0 being
+   * full res.
+   * 
+   * @param result The tile to stuff.  Note The requested rectangle in full
+   * image space and bands should be set in the result tile prior to
+   * passing.  This method will subtract the subImageOffset if needed for
+   * external overview call since they do not know about the sub image offset.
+   *
+   * @return true on success false on error.  Typically this will return false
+   * if resLevel==0 unless the overview has r0.  If return is false, result
+   * is undefined so caller should handle appropriately with makeBlank or
+   * whatever.
+   */
+   virtual bool getOverviewTile(ossim_uint32 resLevel,
+                                ossimImageData* result);   
+   
+private:
+
+   /**
+    * @param Method to get geometry from the various external files like
+    * .prj, .j2w .xml and so on.
+    */
+   ossimRefPtr<ossimImageGeometry> getMetadataImageGeometry() const;
+
+   /**
+    * @brief Test first 12 bytes of file for the jp2 signature block.
+    * @return true is theImageFile is a jp2, false if not.
+    */
+   bool isJp2();
+
+   /**
+    * @brief Opens the jp2 and initializes this object.
+    * @return true on success, false on error.
+    */
+   bool openJp2File();
+   
+   /** @brief Initializes data member "theTile". */
+   void initializeTile();
+
+   /**
+    * Loads a block of data to theCacheTile from the cache.
+    * 
+    * @param origin This is the point used for the cache query.
+    *
+    * @param clipRect The rectangle to fill.
+    *
+    * @return true on success, false on error.
+    */
+   bool loadTileFromCache(const ossimIpt& origin,
+                          const ossimIrect& clipRect);
+   
+   /**
+    * Loads a block of data to theCacheTile.
+    * 
+    * @param origin Starting position of block to load.
+    *
+    * @return true on success, false on error.
+    */
+   bool loadTile(const ossimIpt& origin);
+
+   /**
+    * Initializes m_channels to be used with copyRegionToTile if it makes sense.
+    */
+   void configureChannelMapping();
+
+   kdu_supp::jp2_family_src*        theJp2FamilySrc;
+   kdu_core::kdu_compressed_source* theJp2Source;
+   kdu_supp::kdu_channel_mapping*   theChannels;
+   kdu_core::kdu_codestream         theCodestream;
+   kdu_core::kdu_thread_env*        theThreadEnv;
+   kdu_core::kdu_thread_queue*      theOpenTileThreadQueue;
+   
+   ossim_uint32                theMinDwtLevels;
+   ossim_uint32                theNumberOfBands;
+   ossimIpt                    theCacheSize;
+   ossimScalarType             theScalarType;
+   ossimIrect                  theImageRect; /** Has sub image offset. */
+
+   /** Image dimensions for each level. */
+   std::vector<ossimIrect>      theJp2Dims;
+
+   /** Tile dimensions for each level. */
+   std::vector<ossimIrect>      theJp2TileDims;
+
+   ossimRefPtr<ossimImageData>  theTile;
+   ossimRefPtr<ossimImageData>  theCacheTile;
+
+   /** Cache initialized to image rect with sub image offset */
+   ossimAppFixedTileCache::ossimAppFixedCacheId theCacheId;
+   
+TYPE_DATA   
+};
+
+#endif /* #ifndef ossimKakaduJp2Reader_HEADER */
+
diff --git a/ossim_plugins/kakadu/ossimKakaduJp2Writer.cpp b/ossim_plugins/kakadu/ossimKakaduJp2Writer.cpp
new file mode 100644
index 0000000..0f7a828
--- /dev/null
+++ b/ossim_plugins/kakadu/ossimKakaduJp2Writer.cpp
@@ -0,0 +1,448 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Description: OSSIM Kakadu based jp2 writer class definition.
+//
+//----------------------------------------------------------------------------
+// $Id: ossimKakaduJp2Writer.cpp 23664 2015-12-14 14:17:27Z dburken $
+
+#include "ossimKakaduJp2Writer.h"
+#include "ossimKakaduCommon.h"
+#include "ossimKakaduCompressor.h"
+#include "ossimKakaduMessaging.h"
+
+#include <ossim/base/ossimDate.h>
+#include <ossim/base/ossimDpt.h>
+#include <ossim/base/ossimEndian.h>
+#include <ossim/base/ossimException.h>
+#include <ossim/base/ossimKeywordlist.h>
+#include <ossim/base/ossimKeywordNames.h>
+#include <ossim/base/ossimPreferences.h>
+#include <ossim/base/ossimTrace.h>
+
+#include <ossim/projection/ossimMapProjection.h>
+
+#include <ossim/imaging/ossimImageData.h>
+#include <ossim/imaging/ossimImageGeometry.h>
+#include <ossim/imaging/ossimImageSource.h>
+
+#include <ossim/support_data/ossimGeoTiff.h>
+
+#include <jp2.h>
+#include <ostream>
+
+static const ossimIpt DEFAULT_TILE_SIZE(1024, 1024);
+
+RTTI_DEF1(ossimKakaduJp2Writer, "ossimKakaduJp2Writer", ossimImageFileWriter)
+
+//---
+// For trace debugging (to enable at runtime do:
+// your_app -T "ossimKakaduJp2Writer:debug" your_app_args
+//---
+static const ossimTrace traceDebug( ossimString("ossimKakaduJp2Writer:debug") );
+
+//---
+// For the "ident" program which will find all exanded:
+// $Id: ossimKakaduJp2Writer.cpp 23664 2015-12-14 14:17:27Z dburken $
+//---
+#if OSSIM_ID_ENABLED
+static const char OSSIM_ID[] = "$Id: ossimKakaduJp2Writer.cpp 23664 2015-12-14 14:17:27Z dburken $";
+#endif
+
+ossimKakaduJp2Writer::ossimKakaduJp2Writer()
+   : ossimImageFileWriter(),
+     m_compressor(new ossimKakaduCompressor()),
+     m_outputStream(0),
+     m_ownsStreamFlag(false)
+{
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimKakaduJp2Writer::ossimKakaduJp2Writer entered"
+         << std::endl;
+#if OSSIM_ID_ENABLED
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "OSSIM_ID:  "
+         << OSSIM_ID
+         << std::endl;
+#endif
+   }
+
+   // Set the output image type in the base class.
+   setOutputImageType(getShortName());
+}
+
+ossimKakaduJp2Writer::~ossimKakaduJp2Writer()
+{
+   // This will flush stream and delete it if we own it.
+   close();
+
+   if (m_compressor)
+   {
+      delete m_compressor;
+      m_compressor = 0;
+   }
+}
+
+ossimString ossimKakaduJp2Writer::getShortName() const
+{
+   return ossimString("ossim_kakadu_jp2");
+}
+
+ossimString ossimKakaduJp2Writer::getLongName() const
+{
+   return ossimString("ossim kakadu jp2 writer");
+}
+
+ossimString ossimKakaduJp2Writer::getClassName() const
+{
+   return ossimString("ossimKakaduJp2Writer");
+}
+
+bool ossimKakaduJp2Writer::writeFile()
+{
+   // This method is called from ossimImageFileWriter::execute().
+
+   bool result = false;
+   
+   if( theInputConnection.valid() &&
+       (getErrorStatus() == ossimErrorCodes::OSSIM_OK) )
+   {
+      // Set the tile size for all processes.
+      theInputConnection->setTileSize( DEFAULT_TILE_SIZE );
+      theInputConnection->setToStartOfSequence();
+            
+      //---
+      // Note only the master process used for writing...
+      //---
+      if(theInputConnection->isMaster())
+      {
+         if (!isOpen())
+         {
+            open();
+         }
+         
+         if ( isOpen() )
+         {
+            result = writeStream();
+         }
+      }
+      else // Slave process.
+      {
+         // This will return after all tiles for this node have been processed.
+         theInputConnection->slaveProcessTiles();
+
+         result = true;
+      }
+   }
+      
+   return result;
+}
+
+bool ossimKakaduJp2Writer::writeStream()
+{
+   static const char MODULE[] = "ossimKakaduJp2Writer::writeStream";
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " entered..." << endl;
+   }
+   
+   bool result = false;
+
+   if (theInputConnection.valid() && theInputConnection->isMaster() &&
+       m_outputStream )
+   {
+      result = true; // Assuming good at this point...
+
+      ossim_uint32 outputTilesWide =
+         theInputConnection->getNumberOfTilesHorizontal();
+      ossim_uint32 outputTilesHigh =
+         theInputConnection->getNumberOfTilesVertical();
+      ossim_uint32 numberOfTiles =
+         theInputConnection->getNumberOfTiles();
+      ossim_uint32 tileNumber = 0;
+      
+      if (traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG)
+            << MODULE << " DEBUG:"
+            << "\noutputTilesWide:  " << outputTilesWide
+            << "\noutputTilesHigh:  " << outputTilesHigh
+            << "\nnumberOfTiles:    " << numberOfTiles
+            << "\nimageRect: " << theInputConnection->getAreaOfInterest()
+            << std::endl;
+      }
+
+      ossimScalarType scalarType = theInputConnection->getOutputScalarType();
+
+      const ossim_uint32 BANDS = theInputConnection->getNumberOfOutputBands();
+
+      // Create the compressor.  Can through an exception.
+      try
+      {
+         m_compressor->create(m_outputStream,
+                              scalarType,
+                              BANDS,
+                              theInputConnection->getAreaOfInterest(),
+                              DEFAULT_TILE_SIZE,
+                              numberOfTiles,
+                              true);
+      }
+      catch (const ossimException& e)
+      {
+         ossimNotify(ossimNotifyLevel_WARN) << e.what() << std::endl;
+         return false;
+      } 
+
+      writeGeotiffBox(m_compressor);
+
+      m_compressor->openJp2Codestream();
+
+      bool needAlpha = m_compressor->getAlphaChannelFlag();
+
+      // Tile loop in the line direction.
+      for(ossim_uint32 y = 0; y < outputTilesHigh; ++y)
+      {
+         // Tile loop in the sample (width) direction.
+         for(ossim_uint32 x = 0; x < outputTilesWide; ++x)
+         {
+            // Grab the resampled tile.
+            ossimRefPtr<ossimImageData> t = theInputConnection->getNextTile();
+            if (t.valid() && ( t->getDataObjectStatus() != OSSIM_NULL ) )
+            {
+               if (needAlpha)
+               {
+                  t->computeAlphaChannel();
+               }
+               if ( ! m_compressor->writeTile( *(t.get()) ) )
+               {
+                  ossimNotify(ossimNotifyLevel_WARN)
+                     << MODULE << " ERROR:"
+                     << "Error returned writing tile:  "
+                     << tileNumber
+                     << std::endl;
+                  result = false;
+               }
+            }
+            else
+            {
+               ossimNotify(ossimNotifyLevel_WARN)
+                  << MODULE << " ERROR:"
+                  << "Error returned writing tile:  " << tileNumber
+                  << std::endl;
+               result = false;
+            }
+            if (result == false)
+            {
+               // This will bust out of both loops.
+               x = outputTilesWide;
+               y = outputTilesHigh;
+            }
+            
+            // Increment tile number for percent complete.
+            ++tileNumber;
+            
+         } // End of tile loop in the sample (width) direction.
+         
+         if (needsAborting())
+         {
+            setPercentComplete(100.0);
+            break;
+         }
+         else
+         {
+            ossim_float64 tile = tileNumber;
+            ossim_float64 numTiles = numberOfTiles;
+            setPercentComplete(tile / numTiles * 100.0);
+         }
+         
+      } // End of tile loop in the line (height) direction.
+
+      m_compressor->finish();
+
+      close();
+
+   } // matches: if (theInputConnection.valid() ...
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " exit status = " << (result?"true":"false\n")
+         << std::endl;
+   }
+   
+   return result;
+}
+
+bool ossimKakaduJp2Writer::writeGeotiffBox(ossimKakaduCompressor* compressor)
+{
+   bool result = false;
+   
+   if ( theInputConnection.valid() && compressor )
+   {
+      ossimRefPtr<ossimImageGeometry> geom = theInputConnection->getImageGeometry();
+      if ( geom.valid() )
+      {
+         //---
+         // Make a temp file.  No means currently write a tiff straight to
+         // memory.
+         //---
+         ossimFilename tmpFile = theFilename.fileNoExtension();
+         tmpFile += "-tmp.tif";
+         
+         // Output rect.
+         ossimIrect rect = theInputConnection->getBoundingRect();
+         
+         result = compressor->writeGeotiffBox(geom.get(), rect, tmpFile, getPixelType());
+      }
+   }
+
+   return result;
+   
+} // End: ossimKakaduJp2Writer::writeGeotffBox
+
+bool ossimKakaduJp2Writer::saveState(ossimKeywordlist& kwl,
+                                      const char* prefix)const
+{
+   m_compressor->saveState(kwl, prefix);
+   
+   return ossimImageFileWriter::saveState(kwl, prefix);
+}
+
+bool ossimKakaduJp2Writer::loadState(const ossimKeywordlist& kwl,
+                                      const char* prefix)
+{
+   m_compressor->loadState(kwl, prefix);
+   
+   return ossimImageFileWriter::loadState(kwl, prefix);
+}
+
+bool ossimKakaduJp2Writer::isOpen() const
+{
+   return (m_outputStream?true:false);
+}
+
+bool ossimKakaduJp2Writer::open()
+{
+   bool result = false;
+   
+   close();
+
+   // Check for empty filenames.
+   if (theFilename.size())
+   {
+      std::ofstream* os = new std::ofstream();
+      os->open(theFilename.c_str(), ios::out | ios::binary);
+      if(os->is_open())
+      {
+         m_outputStream = os;
+         m_ownsStreamFlag = true;
+         result = true;
+      }
+      else
+      {
+         delete os;
+         os = 0;
+      }
+   }
+   
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimKakaduJp2Writer::open()\n"
+         << "File " << theFilename << (result ? " opened" : " not opened")
+         << std::endl;
+   }
+
+   return result;
+}
+
+void ossimKakaduJp2Writer::close()
+{
+   if (m_outputStream)
+   {
+      m_outputStream->flush();
+      if (m_ownsStreamFlag)
+      {
+         delete m_outputStream;
+         m_outputStream = 0;
+         m_ownsStreamFlag = false;
+      }
+   }
+}
+
+void ossimKakaduJp2Writer::getImageTypeList(std::vector<ossimString>& imageTypeList)const
+{
+   imageTypeList.push_back(getShortName());
+}
+
+ossimString ossimKakaduJp2Writer::getExtension() const
+{
+   return ossimString("jp2");
+}
+
+bool ossimKakaduJp2Writer::getOutputHasInternalOverviews( void ) const
+{ 
+   return true;
+}
+
+bool ossimKakaduJp2Writer::hasImageType(const ossimString& imageType) const
+{
+   bool result = false;
+   if ( (imageType == getShortName()) ||
+        (imageType == "image/jp2") )
+   {
+      result = true;
+   }
+   return result;
+}
+
+void ossimKakaduJp2Writer::setProperty(ossimRefPtr<ossimProperty> property)
+{
+   if ( property.valid() )
+   {
+      if ( m_compressor->setProperty(property) == false )
+      {
+         // Not a compressor property.
+         ossimImageFileWriter::setProperty(property);
+      }
+   }
+}
+
+ossimRefPtr<ossimProperty> ossimKakaduJp2Writer::getProperty(
+   const ossimString& name)const
+{
+   ossimRefPtr<ossimProperty> p = m_compressor->getProperty(name);
+   
+   if ( !p )
+   {
+      p = ossimImageFileWriter::getProperty(name);
+   }
+   
+   return p;
+}
+
+void ossimKakaduJp2Writer::getPropertyNames(
+   std::vector<ossimString>& propertyNames)const
+{
+   m_compressor->getPropertyNames(propertyNames);
+   
+   ossimImageFileWriter::getPropertyNames(propertyNames);
+}
+
+bool ossimKakaduJp2Writer::setOutputStream(std::ostream& stream)
+{
+   if (m_ownsStreamFlag && m_outputStream)
+   {
+      delete m_outputStream;
+   }
+   m_outputStream = &stream;
+   m_ownsStreamFlag = false;
+   return true;
+}
+
diff --git a/ossim_plugins/kakadu/ossimKakaduJp2Writer.h b/ossim_plugins/kakadu/ossimKakaduJp2Writer.h
new file mode 100644
index 0000000..fc96096
--- /dev/null
+++ b/ossim_plugins/kakadu/ossimKakaduJp2Writer.h
@@ -0,0 +1,148 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Description: OSSIM Kakadu based jp2 writer class declaration.
+//
+//----------------------------------------------------------------------------
+// $Id: ossimKakaduJp2Writer.h 23664 2015-12-14 14:17:27Z dburken $
+
+#ifndef ossimKakaduJp2Writer_HEADER
+#define ossimKakaduJp2Writer_HEADER 1
+
+#include <ossim/imaging/ossimImageFileWriter.h>
+#include <ossim/base/ossimRefPtr.h>
+#include <ossim/base/ossimString.h>
+#include <iosfwd>
+#include <vector>
+
+class ossimKakaduCompressor;
+class ossimKeywordlist;
+
+class ossimKakaduJp2Writer : public ossimImageFileWriter
+{
+public:
+
+   /** @brief default constructor */
+   ossimKakaduJp2Writer();
+
+   /* @brief virtual destructor */
+   virtual ~ossimKakaduJp2Writer();
+
+   /** @return "ossim_kakadu_jp2_writer" */
+   virtual ossimString getShortName() const;
+
+   /** @return "ossim kakadu jp2 writer" */
+   virtual ossimString getLongName()  const;
+
+   /** @return "ossimKakaduJp2Writer" */
+   virtual ossimString getClassName()    const;
+   
+   /**
+    * @brief Appends this writer image types to list "imageTypeList".
+    * @param imageTypeList stl::vector<ossimString> list to append to.
+    */
+   virtual void getImageTypeList(std::vector<ossimString>& imageTypeList)const;
+   
+   virtual bool isOpen()const;   
+   
+   virtual bool open();
+
+   virtual void close();
+   
+   /**
+    * saves the state of the object.
+    */
+   virtual bool saveState(ossimKeywordlist& kwl,
+                          const char* prefix=0)const;
+   
+   /**
+    * Method to the load (recreate) the state of an object from a keyword
+    * list.  Return true if ok or false on error.
+    */
+   virtual bool loadState(const ossimKeywordlist& kwl,
+                          const char* prefix=0);
+
+   /**
+    * Will set the property whose name matches the argument
+    * "property->getName()".
+    *
+    * @param property Object containing property to set.
+    */
+   virtual void setProperty(ossimRefPtr<ossimProperty> property);
+
+   /**
+    * @param name Name of property to return.
+    * 
+    * @returns A pointer to a property object which matches "name".
+    */
+   virtual ossimRefPtr<ossimProperty> getProperty(
+      const ossimString& name)const;
+
+   /**
+    * Pushes this's names onto the list of property names.
+    *
+    * @param propertyNames array to add this's property names to.
+    */
+   virtual void getPropertyNames(std::vector<ossimString>& propertyNames)const;
+
+   /**
+    * Returns a 3-letter extension from the image type descriptor 
+    * (theOutputImageType) that can be used for image file extensions.
+    *
+    * @param imageType string representing image type.
+    *
+    * @return the 3-letter string extension.
+    */
+   virtual ossimString getExtension() const;
+
+   /**
+    * Examples of writers that always generate internal
+    * overviews are ossim_kakadu_jp2 and ossim_kakadu_nitf_j2k.
+    *
+    * @return true if the output of the writer will have
+    * internal overviews. The default is false. 
+    */
+   virtual bool getOutputHasInternalOverviews( void ) const;
+
+   bool hasImageType(const ossimString& imageType) const;
+
+   /**
+    * @brief Method to write the image to a stream.
+    *
+    * @return true on success, false on error.
+    */
+   virtual bool writeStream();
+
+   /**
+    * @brief Sets the output stream to write to.
+    *
+    * The stream will not be closed/deleted by this object.
+    *
+    * @param output The stream to write to.
+    */
+   virtual bool setOutputStream(std::ostream& stream);
+
+protected:
+   /**
+    * @brief Writes the file to disk or a stream.
+    * @return true on success, false on error.
+    */
+   virtual bool writeFile(); 
+
+private:
+
+   bool writeGeotiffBox(ossimKakaduCompressor* compressor);
+
+   ossimKakaduCompressor* m_compressor;
+   std::ostream*          m_outputStream;
+   bool                   m_ownsStreamFlag;
+   
+   TYPE_DATA
+
+};
+
+#endif /* #ifndef ossimKakaduJp2Writer_HEADER */
+
diff --git a/ossim_plugins/kakadu/ossimKakaduJpipHandler.cpp b/ossim_plugins/kakadu/ossimKakaduJpipHandler.cpp
new file mode 100644
index 0000000..12eacf1
--- /dev/null
+++ b/ossim_plugins/kakadu/ossimKakaduJpipHandler.cpp
@@ -0,0 +1,1219 @@
+#include "ossimKakaduJpipHandler.h"
+#include <ossim/base/ossimUrl.h>
+#include <ossim/base/ossimEndian.h>
+#include <sstream>
+//#include <ossim/base/ossimByteStreamBuffer.h>
+#include <ossim/base/ossimException.h>
+#include <ossim/base/ossimKeywordNames.h>
+#include "ossimKakaduCommon.h"
+#include <ossim/imaging/ossimImageDataFactory.h>
+#include <OpenThreads/Thread>
+#include <jpx.h>
+#include <ossim/base/ossimNumericProperty.h>
+#include <ossim/base/ossimWebRequestFactoryRegistry.h>
+#include "ossimKakaduJpipInfo.h"
+#include <ossim/imaging/ossimImageGeometryRegistry.h>
+#include <ossim/base/ossimTrace.h>
+
+using namespace kdu_core;
+using namespace kdu_supp;
+
+static const ossimTrace traceDebug( ossimString("ossimKakaduJpipHandler:debug") );
+
+RTTI_DEF1(ossimKakaduJpipHandler, "ossimKakaduJpipHandler", ossimImageHandler);
+ossimKakaduJpipHandler::ossimKakaduJpipHandler()
+:ossimImageHandler(),
+m_headerClient(0), // let's cache the header information
+m_client(0)
+{
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG) << "ossimKakaduJpipHandler::ossimKakaduJpipHandler():  entered ..................\n";
+   }
+   m_imageBounds.makeNan();
+   m_quality = 100.0;
+}
+
+ossimKakaduJpipHandler::~ossimKakaduJpipHandler()
+{
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG) << "ossimKakaduJpipHandler::~ossimKakaduJpipHandler():  entered ..................\n";
+   }
+   close();
+}
+
+void ossimKakaduJpipHandler::close()
+{
+   ossimImageHandler::close();
+
+   // Kakadu kdu_thread_entity::terminate throws exceptions...
+   try
+   {   
+      m_jp2Family.close();
+      if(m_client)
+      {
+         if(m_client->is_alive())
+         {
+            m_client->disconnect();
+         }
+         m_client->close();
+         delete m_client;
+         m_client = 0;
+      }
+      if(m_headerClient)
+      {
+         if(m_headerClient->is_alive())
+         {
+            m_headerClient->disconnect();
+         }
+         m_headerClient->close();
+         delete m_headerClient;
+         m_headerClient = 0;
+      }
+      m_request = 0;
+   }
+   catch ( kdu_core::kdu_exception exc )
+   {
+      ostringstream e;
+      e << "ossimKakaduNitfReader::~ossimKakaduNitfReader\n"
+        << "Caught exception from kdu_region_decompressor: " << exc << "\n";
+      ossimNotify(ossimNotifyLevel_WARN) << e.str() << std::endl;
+   }
+   catch ( std::bad_alloc& )
+   {
+      std::string e =
+         "Caught exception from kdu_region_decompressor: std::bad_alloc";
+      ossimNotify(ossimNotifyLevel_WARN) << e << std::endl;
+   }
+   catch( ... )
+   {
+      std::string e =
+         "Caught unhandled exception from kdu_region_decompressor";
+      ossimNotify(ossimNotifyLevel_WARN) << e << std::endl;
+   }   
+   
+   deleteRlevelCache();
+}
+
+bool ossimKakaduJpipHandler::isOpen()const
+{
+   return (m_client!=0);
+}
+
+
+int ossimKakaduJpipHandler::convertClassIdToKdu(int id)
+{
+   
+   if(id >=0 &&id<=8)
+   {
+      return (id >> 1);
+   }
+#if 0
+   switch(id)
+   {
+      case 0:
+      case 1:
+      {
+         return KDU_PRECINCT_DATABIN;
+      }
+      case 2:
+      {
+         return KDU_TILE_HEADER_DATABIN;
+      }
+      case 4:
+      case 5:
+      {
+         return KDU_TILE_DATABIN;
+      }
+      case 6:
+      {
+         return KDU_MAIN_HEADER_DATABIN;
+      }
+      case 8:
+      {
+         return KDU_META_DATABIN;
+      }
+      default:
+      {
+         break;
+      }
+   }
+#endif
+   return -1;
+}
+
+void ossimKakaduJpipHandler::showBoxes(kdu_supp::jp2_input_box* pParentBox)
+{
+   kdu_supp::jp2_input_box box;
+
+   if(!pParentBox)
+   {
+      //std::cout << "DEBUG: SHOWING HEADER BOXES FOR STREAM" << std::endl;
+      box.open(&m_jp2Family);
+   }
+   else
+   {
+      box.open(pParentBox);
+   }
+   while(box.exists())
+   {
+      kdu_uint32 boxType = box.get_box_type();
+      char ch[] = { (char) ( boxType >> 24 ), (char) ( boxType >> 16 ), (char) ( boxType >> 8 ) , (char) ( boxType >> 0 ), '\0' };
+
+      //std::cout << ch << std::endl;
+      //std::cout << "Remaining bytes = " << box.get_remaining_bytes() << "\n";
+      if ( box.get_box_type() == jp2_xml_4cc )
+      {
+         //std::cout << "XML_________________________________________________\n";
+         std::vector<kdu_byte> bytes(box.get_remaining_bytes());
+         box.read(&bytes.front(), bytes.size());
+         
+         //std::cout << ossimString((char*)&bytes.front(), ((char*)&bytes.front())+bytes.size() ) << std::endl;
+      }
+      if(box.get_box_type() == jp2_uuid_4cc)
+      {
+         std::vector<kdu_byte> bytes(box.get_remaining_bytes());
+         box.read(&bytes.front(), bytes.size());
+         ossim_uint32 idx = 0;
+         //for(idx = 0; idx < 16; ++idx)
+         //{
+            //std::cout << (int)bytes[idx]<< " ";
+         //}
+         //std::cout << "\n";
+      }
+      if ( jp2_is_superbox( box.get_box_type() ) )
+      {
+         showBoxes( &box );
+      }
+      else
+      {
+      }
+      box.close();
+      box.open_next();
+   }
+}
+void ossimKakaduJpipHandler::extractBoxes(BoxList& boxList)
+{
+   kdu_window window;
+   window.init();
+   m_headerClient->close();
+   if(loadClient(m_headerClient, window))
+   {
+      m_headerClient->set_read_scope(KDU_MAIN_HEADER_DATABIN, 0, 0);
+      kdu_codestream codestream;
+      kdu_region_decompressor decompressor;
+      codestream.create(m_headerClient);
+      codestream.set_persistent();
+      
+      kdu_channel_mapping oChannels;
+      oChannels.configure(codestream);
+      
+      kdu_coords ref_expansion(1, 1);
+      kdu_dims view_dims = decompressor.get_rendered_image_dims(codestream, &oChannels, -1, 0,
+                                                                ref_expansion, ref_expansion,
+                                                                KDU_WANT_OUTPUT_COMPONENTS);
+      siz_params* siz_in = codestream.access_siz();
+      kdu_params* cod_in = siz_in->access_cluster("COD");
+      m_jp2Family.close();
+      m_client->set_read_scope(KDU_META_DATABIN, 0, 0);
+      m_jp2Family.open(m_headerClient);
+      
+      extractBoxes(boxList, 0);
+      m_jp2Family.close();
+   }
+}
+
+void ossimKakaduJpipHandler::extractBoxes(BoxList& boxList, jp2_input_box* pParentBox)
+{
+   jp2_input_box box;
+   
+   if(!pParentBox)
+   {
+      //std::cout << "DEBUG: SHOWING HEADER BOXES FOR STREAM" << std::endl;
+      box.open(&m_jp2Family);
+   }
+   else
+   {
+      box.open(pParentBox);
+   }
+   while(box.exists())
+   {
+      ossim_uint32 idx = boxList.size();
+      boxList.push_back(Box());
+      boxList[idx].m_type = box.get_box_type();
+      if(box.get_remaining_bytes()>0)
+      {
+         boxList[idx].m_buffer.resize(box.get_remaining_bytes());
+         box.read(&boxList[idx].m_buffer.front(), boxList[idx].m_buffer.size());
+      }
+      if ( jp2_is_superbox( box.get_box_type() ) )
+      {
+         extractBoxes(boxList, &box );
+      }
+      
+      box.close();
+      box.open_next();
+   }
+}
+
+bool ossimKakaduJpipHandler::openStream()
+{
+   close();
+
+   if(!m_client)
+   {
+      m_headerClient = new kdu_client();
+      m_client       = new kdu_client();
+   }
+   bool result = false;
+   ossimString protocolString = m_baseUrl.getProtocol();
+   protocolString =  protocolString.downcase();
+   m_useOurGrab = false;
+   
+   if(protocolString == "jpip")
+   {
+      m_baseUrl.setProtocol("http");
+   }
+   else
+   {
+      if(protocolString == "jpips")
+      {
+         m_useOurGrab = true;
+         m_baseUrl.setProtocol("https");            
+      }
+      else
+      {
+         return false;
+      }
+   }
+   //std::cout << "OUR GRAB ==== " << m_useOurGrab << std::endl;
+  // m_useOurGrab = true;
+   m_imageBounds.makeNan();
+   kdu_window window;
+   window.init();
+   //std::cout << "calling loadClient " << std::endl;
+   if(loadClient(m_client, window))
+   {
+      try 
+      {
+         m_client->set_read_scope(KDU_MAIN_HEADER_DATABIN, 0, 0);
+         kdu_codestream codestream;
+         kdu_region_decompressor decompressor;
+         codestream.create(m_client);
+         codestream.set_persistent();
+         
+         kdu_channel_mapping oChannels;
+         oChannels.configure(codestream);
+         
+         
+         
+         kdu_coords ref_expansion(1, 1);
+         kdu_dims view_dims = decompressor.get_rendered_image_dims(codestream, &oChannels, -1, 0,
+                                                                   ref_expansion, ref_expansion,
+                                                                   KDU_WANT_OUTPUT_COMPONENTS);
+         siz_params* siz_in = codestream.access_siz();
+         kdu_params* cod_in = siz_in->access_cluster("COD");
+         m_jp2Family.close();
+         m_client->set_read_scope(KDU_META_DATABIN, 0, 0);
+         m_jp2Family.open(m_client);
+         //std::cout <<"SHOWING BOXES!!!!!!!!!!!" << std::endl;
+         showBoxes();
+         if(cod_in&&siz_in)
+         {
+            //std::cout << "__________________________________====\n";
+            int nResLevels = 0;
+            int nQualityLayers = 0;
+            int nTileSizeX = 0;
+            int nTileSizeY = 0;
+            
+            cod_in->get("Clevels", 0, 0, nResLevels);
+            cod_in->get("Clayers", 0, 0, nQualityLayers);
+            siz_in->get("Stiles", 0, 0, nTileSizeY);  
+            siz_in->get("Stiles", 0, 1, nTileSizeX);  
+            m_nQualityLayers = nQualityLayers;
+            m_nInputBands = codestream.get_num_components(false);
+            m_nOutputBands = codestream.get_num_components(true);
+            ossim_uint64 width =  view_dims.size.x;
+            ossim_uint64 height = view_dims.size.y;
+            //           ossim_int32 m_nQualityLayers = nQualityLayers;
+            m_bitDepth = codestream.get_bit_depth(0);
+            m_signed   = codestream.get_signed(0);
+            m_resLevels = nResLevels;
+            if(nTileSizeX&&nTileSizeY)
+            {
+               m_tileSize = ossimIpt( nTileSizeX, nTileSizeY);
+            }
+            else
+            {
+               m_tileSize = ossimIpt(2048, 128);
+            }
+            m_tileSize.x = m_tileSize.x>2048?2048:m_tileSize.x;
+            m_tileSize.y = m_tileSize.y>128?128:m_tileSize.y;
+            m_bYCC=1;
+            cod_in->get("Cycc", 0, 0, m_bYCC);
+            performRlevelSetup(codestream);
+            
+            m_jp2Family.close();
+            result = true;
+#if 0
+            std::cout << std::dec << "width = " << width << std::endl;
+            std::cout << std::dec << "height = " << height << std::endl;
+            std::cout << "m_nOutputBands = " << m_nOutputBands << std::endl;
+            std::cout << "m_nInputBands = " << m_nInputBands << std::endl;
+            std::cout << "BitDepth   = " << m_bitDepth << std::endl;
+            std::cout << "Overviews  = " << nResLevels<< std::endl;
+            std::cout << "nQualityLayers  = " << m_nQualityLayers<< std::endl;
+            std::cout << "nTileSize  = " << m_tileSize << std::endl;
+#endif       
+         }
+         
+         // walk boxes for testing
+         //
+         //               showBoxes(&box);
+         // std::cout << "BOX OPENED!!!" << std::endl;
+         //do {
+         //   std::cout << "type: " <<std::ios::hex <<  box.get_box_type() << std::endl;
+         //   std::cout << "SUPER? " << jp2_is_superbox(box.get_box_type()) << std::endl;
+         //   box.close();
+         //   box.open_next();
+         //} while (box.exists());
+         //            }
+      } 
+      catch(...)
+      {
+         result = false;
+      }
+   }
+   
+   if(result)
+   {
+      completeOpen(); 
+   }
+   else
+   {
+      close();
+   }
+   //std::cout << "RETURNING RESULT === " << result << std::endl;
+   return result;
+   
+}
+
+bool ossimKakaduJpipHandler::open()
+{
+   if(isOpen()) close();
+   bool result = false;
+   ossimFilename file = getFilename();
+   // local file and we will test for jpip extension and this
+   // will hold cached state information
+   //
+   if(file.exists())
+   {
+      if(file.ext().downcase()=="jpip")
+      {
+         ossimKeywordlist kwl;
+         if(kwl.addFile(file))
+         {
+            result = loadState(kwl);
+         }
+      }
+   }
+   else
+   {
+      m_baseUrl = ossimUrl(file);
+      result = openStream();
+   }
+   if(getOutputScalarType() == OSSIM_SCALAR_UNKNOWN)
+   {
+      result = false;
+      close();
+   }
+   return result;
+}
+
+void ossimKakaduJpipHandler::allocateSession()
+{
+   m_request = ossimWebRequestFactoryRegistry::instance()->createHttp(m_baseUrl);
+#if 0
+   if(m_request.valid())
+   {
+      m_cid = "";
+      m_path = "";
+      m_transport ="";
+      ossimString params;
+      ossimUrl imageInfoUrl = m_baseUrl;
+      params = "type=jpp-stream&stream=0&cnew=http";
+      imageInfoUrl.setParams(params);
+      std::cout << "URL------------------------- " << imageInfoUrl.toString() << std::endl;
+      m_request->set(imageInfoUrl, ossimKeywordlist());
+      m_request->addHeaderOption("HEADERS=Accept", "jpp-stream");
+      ossimRefPtr<ossimHttpResponse> response = dynamic_cast<ossimHttpResponse*>(m_request->getResponse());
+      if(response.valid()&&(response->getStatusCode()==200))
+      {
+         std::cout << "__________________________" << std::endl;
+         std::cout << response->headerKwl() << std::endl;
+         ossimString jpipCnew = response->headerKwl()["JPIP-cnew"];
+         jpipCnew = jpipCnew.trim();
+         if(!jpipCnew.empty())
+         {
+            m_cid = "";
+            m_path = "";
+            m_transport ="";
+            ossimString tempKwlString = jpipCnew.substitute(",", "\n", true);
+            std::istringstream in(tempKwlString.c_str());
+            
+            ossimKeywordlist kwl('=');
+            if(kwl.parseStream(in))
+            {
+               m_cid = kwl["cid"];
+               m_path = kwl["path"];
+               m_transport = kwl["transport"];
+               m_cid = m_cid.trim();
+               m_path = m_path.trim();
+               m_transport = m_transport.trim();
+               
+               std::cout << "PATH === " << m_path << std::endl;
+            }
+         }
+      }
+   }   
+#endif
+}
+bool ossimKakaduJpipHandler::loadClient(kdu_client* client, kdu_window& window)
+{
+   bool result =false;
+
+   if(!client) return result;
+   // we will assume that the libcurl library support ssl connections and we will use our own 
+   // urlquery instead of using kakadu's persistant code
+   // if m_ourGrab is true we currently only support stateless requests.  Kakadu
+   // interface we use if m_useOurGrab communicates through the channel session 
+   // id.
+   if(m_useOurGrab)
+   {
+      //if(!m_request.valid())
+         allocateSession();
+      
+      client->close();
+      bool needNewChannel = false;
+#if 0
+      if(!m_request.valid())
+      {
+         m_request = ossimWebRequestFactoryRegistry::instance()->createHttp(m_baseUrl);
+         needNewChannel = true;
+      }
+#endif
+      if(m_request.valid())
+      {
+         m_request->clearHeaderOptions();
+         ossimString params;
+         ossimUrl imageInfoUrl = m_baseUrl;
+         if(window.region.size.x == 0&&
+            window.region.size.y == 0)
+         {
+            
+            params = "type=jpp-stream&stream=0";
+         }
+         else
+         {
+            params = "type=jpp-stream&stream=0";
+            
+            params += ("&roff=" + ossimString::toString((ossim_int64)window.region.pos.x)+","+ossimString::toString((ossim_int64)window.region.pos.y));
+            params += ("&rsiz=" + ossimString::toString((ossim_int64)window.region.size.x)+","+ossimString::toString((ossim_int64)window.region.size.y));
+            params += ("&fsiz=" + ossimString::toString((ossim_int64)window.resolution.x)+","+ossimString::toString((ossim_int64)window.resolution.y));
+            params += ("&layers=" + ossimString::toString(window.get_max_layers()));
+            
+         }
+         if(!m_cid.empty())
+         {
+            params += ("&cid=" + m_cid); 
+           // if(!m_path.empty()) imageInfoUrl.setPath(m_path);
+         }
+         if(needNewChannel)
+         {
+            params += "&cnew=http";
+         }
+         imageInfoUrl.setParams(params);
+
+         m_request->set(imageInfoUrl, ossimKeywordlist());
+         m_request->addHeaderOption("HEADERS=Accept", "jpp-stream");
+         
+         //std::cout << "URL======================== " << imageInfoUrl.toString() << std::endl;
+         ossimRefPtr<ossimHttpResponse> response = dynamic_cast<ossimHttpResponse*>(m_request->getResponse());
+         //std::cout << "__________________________" << std::endl;
+         if(response.valid()&&(response->getStatusCode()==200))
+         {
+//            std::cout << response->headerKwl() << std::endl;
+           //std::cout << "__________________________" << std::endl;
+            //std::cout << response->headerKwl() << std::endl;
+#if 0
+            ossimString jpipCnew = response->headerKwl()["JPIP-cnew"];
+            jpipCnew = jpipCnew.trim();
+            
+            if(!jpipCnew.empty())
+            {
+               m_cid = "";
+               m_path = "";
+               m_transport ="";
+               ossimString tempKwlString = jpipCnew.substitute(",", "\n", true);
+               std::istringstream in(tempKwlString.c_str());
+               
+               ossimKeywordlist kwl('=');
+               if(kwl.parseStream(in))
+               {
+                  m_cid = kwl["cid"];
+                  m_path = kwl["path"];
+                  m_transport = kwl["transport"];
+                  m_cid = m_cid.trim();
+                  m_path = m_path.trim();
+                  m_transport = m_transport.trim();
+                  
+                  std::cout << "PATH === " << m_path << std::endl;
+               }
+            }
+#endif       
+            if(traceDebug())
+            {
+               ossimNotify(ossimNotifyLevel_DEBUG) << ossimString(response->headerBuffer().buffer(),response->headerBuffer().buffer()+response->headerBuffer().bufferSize())  << std::endl;    
+            }
+            ossimWebResponse::ByteBuffer buf;
+            response->copyAllDataFromInputStream(buf);
+            if(buf.size())
+            {
+               try 
+               {
+                  ossimRefPtr<ossimJpipMessageDecoder> decoder = new ossimJpipMessageDecoder();
+                  decoder->inputStreamBuffer().setBuf(reinterpret_cast<char*>(&buf.front()),
+                                                      buf.size(),
+                                                      true);
+                  ossimRefPtr<ossimJpipMessage> message = decoder->readMessage();
+                  ossimRefPtr<ossimJpipMessage> mainHeaderMessage;
+                  if(message.valid())
+                  {
+                     ossim_uint32 dataWritten = 0;
+                     while(message.valid()&&!message->header()->m_isEOR)
+                     {
+                        int id = convertClassIdToKdu(message->header()->m_classIdentifier);
+                        if((!message->header()->m_isEOR)&&
+                           (id >=0))
+                        {
+                           client->add_to_databin( id, 
+                                                    message->header()->m_CSn,
+                                                    message->header()->m_inClassIdentifier,
+                                                    (const kdu_byte*)&message->messageBody().front(), 
+                                                    message->header()->m_msgOffset, 
+                                                    message->messageBody().size(),
+                                                    message->header()->m_isLastByte);
+                           
+                           dataWritten+= message->messageBody().size();
+                        }
+                        message = decoder->readMessage();
+                     }
+                  }
+                  result = true;
+               } 
+               catch(...) 
+               {
+                  //std::cout << "EXCEPTION!!!!!!!!!!!!!!!!!!!\n"; 
+                  //std::cout << "-----------------------------------------------\n";
+                  result = false;
+               }
+            }
+         }
+         else if(response.valid())
+         {
+            if(traceDebug())
+            {
+               ossimNotify(ossimNotifyLevel_DEBUG) << ossimString(response->headerBuffer().buffer(),response->headerBuffer().buffer()+response->headerBuffer().bufferSize())  << std::endl;            
+            }
+            //std::cout << imageInfoUrl.toString() << std::endl;
+            //std::cout << ossimString(response->headerBuffer().buffer(),response->headerBuffer().buffer()+response->headerBuffer().bufferSize())  << std::endl;
+         }
+      }
+   }
+   else
+   {
+      //std::cout << "TRYING TO MAKE A CONNECTION" << std::endl;
+      result = makeConnectionIfNeeded(client);
+      if(result)
+      {
+         result = false;
+         if(client->post_window(&window, m_requestQueueId))
+         {
+            try 
+            {
+               //
+               while( !client->is_idle() &&client->is_alive())
+               {
+                  OpenThreads::Thread::microSleep(2000);
+               }
+
+               result = true;
+            }
+            catch(...)
+            {
+               result = false;
+            }
+         }
+      }
+   }
+   //std::cout << "RESULT? " << result << std::endl;
+  return result;
+}
+
+ossim_uint32 ossimKakaduJpipHandler::getNumberOfLines(ossim_uint32 resLevel) const
+{
+   ossim_uint32 result = 0;
+   if (resLevel < m_overviewDimensions.size())
+   {
+      result = m_overviewDimensions[resLevel].height();
+   }
+   else if (theOverview.valid())
+   {
+      result = theOverview->getNumberOfLines(resLevel);
+   }
+   return result;
+}
+
+ossim_uint32 ossimKakaduJpipHandler::getNumberOfSamples(ossim_uint32 resLevel) const
+{
+   ossim_uint32 result = 0;
+   if (resLevel < m_overviewDimensions.size())
+   {
+      result = m_overviewDimensions[resLevel].width();
+   }
+   else if (theOverview.valid())
+   {
+      result = theOverview->getNumberOfSamples(resLevel);
+   }
+   return result;
+}
+
+ossim_uint32 ossimKakaduJpipHandler::getNumberOfInputBands() const
+{
+   return m_nInputBands;
+}
+
+ossim_uint32 ossimKakaduJpipHandler::getNumberOfOutputBands() const
+{
+   return m_nOutputBands;
+}
+
+ossim_uint32 ossimKakaduJpipHandler::getImageTileWidth() const
+{
+   return m_tileSize.hasNans()?0:m_tileSize.x;
+}
+
+ossim_uint32 ossimKakaduJpipHandler::getImageTileHeight() const
+{
+   return m_tileSize.hasNans()?0:m_tileSize.y;
+}
+
+ossimScalarType ossimKakaduJpipHandler::getOutputScalarType() const
+{
+   ossimScalarType result = OSSIM_SCALAR_UNKNOWN;
+   switch(m_bitDepth)
+   {
+      case 8:
+      {
+         result = m_signed?OSSIM_SINT8:OSSIM_UINT8;
+         break;
+      }
+      case 11:
+      {
+         result = m_signed?OSSIM_SINT16:OSSIM_USHORT11;
+         break;
+      }
+      case 16:
+      {
+         result = m_signed?OSSIM_SINT16:OSSIM_UINT16;
+         break;
+      }
+   };
+   return result;
+}
+
+ossim_uint32 ossimKakaduJpipHandler::getNumberOfDecimationLevels() const
+{
+   ossim_uint32 result = m_overviewDimensions.size();
+   if (theOverview.valid())
+   {
+      result += theOverview->getNumberOfDecimationLevels();
+   }
+   return result;
+}
+
+void ossimKakaduJpipHandler::allocateTile()
+{
+   m_tile = ossimImageDataFactory::instance()->create(this, this);
+   
+   if(m_tile.valid())
+   {
+      m_tile->initialize();
+   }
+}
+#include <ossim/imaging/ossimMemoryImageSource.h>
+#include <ossim/imaging/ossimImageRenderer.h>
+#include <ossim/projection/ossimImageViewAffineTransform.h>
+
+ossim_uint64 findLevel(ossim_uint64 power2Value, ossim_uint32 maxLevel)
+{
+   ossim_uint64 test = 1<<maxLevel;
+   ossim_uint64 currentLevel = maxLevel;
+   while(currentLevel)
+   {
+      if(test&power2Value) break;
+      test >>=1;
+      --currentLevel;
+   }
+   return currentLevel;
+}
+
+ossimRefPtr<ossimImageData> ossimKakaduJpipHandler::getTile(const  ossimIrect& rect,
+                                                            ossim_uint32 resLevel)
+{
+   ossimRefPtr<ossimImageData> result;
+
+   try
+   {
+      ossim_int32 nLevels = getNumberOfDecimationLevels()-1;
+   
+      ossim_uint64 scalePower2 = 1<<nLevels;
+      ossim_int32 targetLevel = nLevels - ossim::round<ossim_uint32>(log(1.0+((scalePower2*m_quality)/100.0))/log(2.0));
+   
+      // now try log way
+      if(targetLevel > static_cast<ossim_int32>(resLevel))
+      {
+         double scale = 1.0/(1<<targetLevel);
+         ossimDrect scaledRect = rect*ossimDpt(scale, scale);
+         ossimIrect scaledRectRound = scaledRect;
+         scaledRectRound = ossimIrect(scaledRectRound.ul().x - 1,
+                                      scaledRectRound.ul().y - 1,
+                                      scaledRectRound.lr().x + 1,
+                                      scaledRectRound.lr().y + 1);
+         ossimRefPtr<ossimImageData> copy = getTileAtRes(scaledRectRound, targetLevel);
+         copy = (ossimImageData*)copy->dup();
+    
+         //result->setImageRectangle(rect);
+      
+         ossimRefPtr<ossimMemoryImageSource> memSource = new ossimMemoryImageSource();
+         ossimRefPtr<ossimImageRenderer> renderer = new ossimImageRenderer();
+         ossimRefPtr<ossimImageViewAffineTransform> transform = new ossimImageViewAffineTransform();
+         transform->scale(1<<targetLevel, 1<<targetLevel);
+         memSource->setImage(copy.get());
+         renderer->connectMyInputTo(memSource.get());
+         renderer->getResampler()->setFilterType("bilinear");
+         renderer->setImageViewTransform(transform.get());
+         result = renderer->getTile(rect);
+         renderer->disconnect();
+         memSource->disconnect();
+         renderer = 0;
+         memSource = 0;
+      }
+      else
+      {
+         // we need to apply a quality and then scale to the proper resolution.
+         // so if we want a 50% quality image and they are requesting a reslevel 0 product
+         // we need to query jpip at the next level down and not at 0 and scale the product up
+         // using a bilinear or some form of resampling
+         //
+         result = getTileAtRes(rect, resLevel);
+      }
+   }
+   catch ( kdu_exception exc )
+   {
+      ostringstream e;
+      e << "ossimKakaduNitfReader::~ossimKakaduNitfReader\n"
+        << "Caught exception from kdu_region_decompressor: " << exc << "\n";
+      ossimNotify(ossimNotifyLevel_WARN) << e.str() << std::endl;
+   }
+   catch ( std::bad_alloc& )
+   {
+      std::string e =
+         "Caught exception from kdu_region_decompressor: std::bad_alloc";
+      ossimNotify(ossimNotifyLevel_WARN) << e << std::endl;
+   }
+   catch( ... )
+   {
+      std::string e =
+         "Caught unhandled exception from kdu_region_decompressor";
+      ossimNotify(ossimNotifyLevel_WARN) << e << std::endl;
+   }   
+
+   return result.get();
+}
+
+ossimRefPtr<ossimImageData>  ossimKakaduJpipHandler::getTileAtRes(const  ossimIrect& rect,
+                                                                  ossim_uint32 resLevel)
+{
+   ossim_uint32 nLevels = getNumberOfDecimationLevels();
+   ossimRefPtr<ossimImageData> result;
+   
+   if((resLevel>=nLevels)||!isOpen()||!isSourceEnabled())
+   {
+      return result;
+   }
+   
+   if(resLevel > m_overviewDimensions.size()&&theOverview.valid())
+   {
+      return theOverview->getTile(rect, resLevel);
+   }
+   if(!m_tile.valid()) allocateTile();
+   m_tile->setImageRectangle(rect);
+   
+   if(getOverviewTile(resLevel, m_tile.get()))
+   {
+      return m_tile.get();
+   }
+   
+   ossimIrect bounds = getBoundingRect(resLevel);
+   ossimIrect clipRect = bounds.clipToRect(rect);
+   
+   kdu_dims  dims;
+   if(!bounds.intersects(rect))
+   {
+      return result;
+   }
+   
+   kdu_coords ref_expansion;
+   kdu_coords exp_numerator;
+   kdu_coords exp_denominator;
+   kdu_dims rr_win;
+   ref_expansion.x = 1;
+   ref_expansion.y = 1;
+   
+   kdu_dims view_dims;	
+   
+   ossimString comps;
+   ossim_uint32 nBands = getNumberOfInputBands();
+   ossim_uint32 idx = 0;
+   for(idx=0;idx<nBands;++idx)
+   {
+      comps+=ossimString::toString(idx);
+      if(idx+1!=nBands)
+      {
+         comps+=",";
+      }
+   }
+   ossimIpt tileSize;
+   tileSize = m_rlevelTileSize[resLevel];//m_tileSize;
+   // if(static_cast<ossim_int32>(bounds.width()) < tileSize.x) tileSize.x  = bounds.width();
+   // if(static_cast<ossim_int32>(bounds.height()) < tileSize.y) tileSize.y = bounds.height();
+   
+   ossimIrect tileBoundaryRect = clipRect;
+   tileBoundaryRect.stretchToTileBoundary(tileSize);
+   
+   
+   tileBoundaryRect.clipToRect(bounds);
+   ossim_int64 ulx = tileBoundaryRect.ul().x;
+   ossim_int64 uly = tileBoundaryRect.ul().y;
+   ossim_int64 maxx = tileBoundaryRect.lr().x;
+   ossim_int64 maxy = tileBoundaryRect.lr().y;
+   m_tile->makeBlank();
+   kdu_window window;
+   kdu_dims region;
+   for(;ulx < maxx; ulx += tileSize.x)
+   {
+      for(;uly < maxy; uly += tileSize.y)
+      {
+         ossim_int64 x = ulx;
+         ossim_int64 y = uly;
+         ossim_int64 w = tileSize.x;
+         ossim_int64 h = tileSize.y;
+         
+         if(x+w-1 > maxx) w = maxx-x;
+         if(y+h-1 > maxy) h = maxy-y;
+         
+         ossimRefPtr<ossimImageData> cacheTile =ossimAppFixedTileCache::instance()->getTile(m_rlevelBlockCache[resLevel],ossimIpt(x,y));
+         if(!cacheTile.valid())
+         {
+            double percent = (m_quality/100.0);
+            window.init();
+            region.pos.x = x;
+            region.pos.y = y;
+            region.size.x = w;
+            region.size.y = h;
+            //std::cout << "NLAYERS ================= " << m_nQualityLayers << std::endl;
+            //ossim_int32 nQualityLayers = ((m_quality/100.0)*m_nQualityLayers);
+            ossim_int32 nQualityLayers = (m_nQualityLayers);//*percent;
+            nQualityLayers = nQualityLayers<1?1:nQualityLayers;
+            // std::cout << "nquality === " << nQualityLayers << std::endl;
+            window.set_region(region);
+            
+            window.set_max_layers(nQualityLayers);
+            window.resolution.x = bounds.width();
+            window.resolution.y = bounds.height();
+            
+            try
+            {
+               if(loadClient(m_client, window))
+               {
+                  //std::cout << "WE LOADED THE CLIENT!!!!" << std::endl;
+                  bool gotRegion = true;
+                  // if we do not need to use ssl we use kakadu for the window loads
+                  if(!m_useOurGrab)
+                  {
+                     kdu_window reqWindow;
+                     m_client->get_window_in_progress(&reqWindow);
+                     gotRegion = ((reqWindow.region.size.x>0)&&
+                                  (reqWindow.region.size.y>0));
+                  }
+                  //kdu_window reqWindow = window;
+                  //m_client->get_window_in_progress(&reqWindow);
+                  // now get a codestream ready for decompressing the data
+                  //
+                  
+                  if(gotRegion)
+                  {
+                     jp2_family_src jp2FamilySource;
+                     jp2FamilySource.open(m_client);
+                     
+                     jpx_source jpxSource;
+                     if(jpxSource.open(&jp2FamilySource, true)==1)
+                     {
+                        jpx_codestream_source jpx_codestream = jpxSource.access_codestream(0);
+                        kdu_codestream codestream;
+                        jpx_input_box* inputBox = jpx_codestream.open_stream();
+                        if(inputBox)
+                        {
+                           codestream.create(inputBox);
+                           codestream.set_persistent();
+                           codestream.apply_input_restrictions(
+                              0, 0, 
+                              resLevel, nQualityLayers, &region, 
+                              KDU_WANT_CODESTREAM_COMPONENTS);
+                           if ( ossim::clipRegionToImage(codestream,
+                                                         region,
+                                                         resLevel,
+                                                         region) )
+                           {
+                              kdu_channel_mapping channels;
+                              channels.configure(codestream);
+                              cacheTile = ossimImageDataFactory::instance()->create(this, this);
+                              cacheTile->setImageRectangle(ossimIrect(region.pos.x,region.pos.y,
+                                                                      region.pos.x + region.size.x - 1, 
+                                                                      region.pos.y+region.size.y - 1));
+                              cacheTile->initialize();
+                              
+                              ossim::copyRegionToTile(&channels, codestream, resLevel, 0, 0, cacheTile.get());
+                              ossimAppFixedTileCache::instance()->addTile(m_rlevelBlockCache[resLevel], cacheTile.get(), false);
+                           }
+                        }
+                     }
+                     jpxSource.close();
+                     jp2FamilySource.close();
+                  }
+                  else
+                  {
+                     ossimNotify(ossimNotifyLevel_WARN) << "Unable to get block from server, defaulting to blank\n";
+                  }
+               }
+               else
+               {
+                  ossimNotify(ossimNotifyLevel_WARN) << "Unable to establish a connection to the server\n";
+               }
+            }
+            catch(...)
+            {
+               cacheTile = 0;
+            }
+         }
+         if(cacheTile.valid())
+         {
+            m_tile->loadTile(cacheTile->getBuf(), cacheTile->getImageRectangle(), OSSIM_BSQ);
+         }
+      }
+   }
+   m_tile->validate();
+   
+   return m_tile;
+}
+
+
+bool ossimKakaduJpipHandler::makeConnectionIfNeeded(kdu_client* client)
+{
+   if(!client->is_alive())
+   {           
+      ossimString server = m_baseUrl.getIp()+(m_baseUrl.getPort().empty()?"":":"+m_baseUrl.getPort());
+      ossimString path = m_baseUrl.getPath();
+       
+      m_requestQueueId = client->connect(server.c_str(), "",path.c_str(), "http", "", KDU_CLIENT_MODE_INTERACTIVE, "");   
+   }
+   return client->is_alive();
+   
+}
+
+void ossimKakaduJpipHandler::deleteRlevelCache()
+{
+   ossim_uint32 idx = 0;
+   for(idx = 0; idx < m_rlevelBlockCache.size();++idx)
+   {
+      ossimAppFixedTileCache::instance()->deleteCache(m_rlevelBlockCache[idx]);
+   }
+   m_rlevelBlockCache.clear();
+}
+
+void ossimKakaduJpipHandler::performRlevelSetup(kdu_codestream& codestream)
+{
+   deleteRlevelCache();
+   m_rlevelTileSize.clear();
+   
+   //Get resolution level dimensions
+   //
+   ossim_uint32 nDiscard = 0;
+   for(nDiscard = 0; nDiscard < m_resLevels; ++nDiscard)
+   {
+      kdu_dims  dims;
+      codestream.apply_input_restrictions( 0, 0, nDiscard, 0, NULL );
+      codestream.get_dims( 0, dims );
+      ossimIrect rect(0,0,dims.size.x-1, dims.size.y-1);
+      m_overviewDimensions.push_back(rect);
+      ossimIpt tileSize(m_tileSize);
+      tileSize.x = ((tileSize.x > static_cast<ossim_int32>(rect.width()))?static_cast<ossim_int32>(rect.width()):tileSize.x);
+      tileSize.y = ((tileSize.y > static_cast<ossim_int32>(rect.height()))?static_cast<ossim_int32>(rect.height()):tileSize.y);
+      m_rlevelTileSize.push_back(tileSize);
+      rect.stretchToTileBoundary(tileSize);
+      m_rlevelBlockCache.push_back(ossimAppFixedTileCache::instance()->newTileCache(rect, tileSize)); 
+   }
+}
+
+void ossimKakaduJpipHandler::initializeRlevelCache()
+{
+   deleteRlevelCache();
+   m_rlevelTileSize.clear();
+   ossim_uint32 idx = 0;
+   if(m_rlevelTileSize.size() != m_overviewDimensions.size()) return;
+   for(idx = 0; idx < m_rlevelTileSize.size(); ++idx)
+   {
+      ossimIrect rect = m_overviewDimensions[idx];
+      ossimIpt tileSize(m_rlevelTileSize[idx]);
+      rect.stretchToTileBoundary(tileSize);
+      m_rlevelBlockCache.push_back(ossimAppFixedTileCache::instance()->newTileCache(rect, tileSize)); 
+   }
+}
+
+void ossimKakaduJpipHandler::setProperty(ossimRefPtr<ossimProperty> property)
+{
+   bool refreshCache = false;
+   if(property.valid())
+   {
+      ossimString name = property->getName();
+      if(name == "quality")
+      {
+         refreshCache = !ossim::almostEqual((double)m_quality, 
+                                           property->valueToString().toDouble());
+         m_quality = property->valueToString().toDouble();
+      }
+      else
+      {
+         ossimImageHandler::setProperty(property.get());
+      }
+   }
+   
+   if(refreshCache)
+   {
+      flushCache();
+      if(m_client) m_client->close();
+   }
+}
+
+ossimRefPtr<ossimProperty> ossimKakaduJpipHandler::getProperty(const ossimString& name)const
+{
+   ossimRefPtr<ossimProperty> result;
+   if(name == "quality")
+   {
+      result = new ossimNumericProperty(name, ossimString::toString(m_quality),
+                                        0, 100);
+      result->setCacheRefreshBit();
+      result->setFullRefreshBit();
+   }
+   
+   return result.get();
+}
+
+void ossimKakaduJpipHandler::getPropertyNames(std::vector<ossimString>& propertyNames)const
+{
+   ossimImageHandler::getPropertyNames(propertyNames);
+   propertyNames.push_back(ossimKeywordNames::QUALITY_KW);
+}
+
+ ossimRefPtr<ossimImageGeometry> ossimKakaduJpipHandler::getImageGeometry()
+{
+   if(theGeometry.valid()) return theGeometry.get();
+   
+   // if base is able to create a goemetry then return it
+   theGeometry = ossimImageHandler::getImageGeometry();
+   
+   if(!theGeometry->getProjection())
+   {
+      ossimKeywordlist kwl;
+      
+      ossimRefPtr<ossimKakaduJpipInfo> info = new ossimKakaduJpipInfo();
+      info->setHandler(this);
+      info->getKeywordlist(kwl);
+      info = 0;
+      ossimString prefix = "jpip.image"+ossimString::toString(getCurrentEntry()) + ".";
+      // dump the infromation into a kwl and then pass it to the geometry resgistry
+      
+      //std::cout << kwl << std::endl;
+      //
+      theGeometry = ossimImageGeometryRegistry::instance()->createGeometry(kwl, prefix.c_str());
+      if(theGeometry.valid())
+      {
+         initImageParameters(theGeometry.get());
+      }
+   }
+   
+   return theGeometry.get();
+}
+
+bool ossimKakaduJpipHandler::loadState(const ossimKeywordlist& kwl, const char* prefix)
+{
+   close();
+   bool result = ossimImageHandler::loadState(kwl, prefix);
+   if(result)
+   {
+      m_baseUrl = ossimUrl(kwl.find(prefix, "url"));
+      ossimString qualityString = kwl.find(prefix,ossimKeywordNames::QUALITY_KW);
+      if(!qualityString.empty())
+      {
+         m_quality = qualityString.toDouble();
+      }
+      result = openStream();
+   }
+
+   
+   if(!result)
+   {
+      close();
+   }
+   return result;
+}
+
+bool ossimKakaduJpipHandler::saveState(ossimKeywordlist& kwl, const char* prefix)const
+{
+   bool result = ossimImageHandler::saveState(kwl, prefix);
+   
+   ossimUrl url = m_baseUrl;
+   ossimString protocol = m_baseUrl.getProtocol();
+   if(protocol == "http") protocol = "jpip";
+   else if(protocol == "https") protocol = "jpips";
+   url.setProtocol(protocol);
+   
+   kwl.add(prefix, "url", url.toString().c_str(), true);
+   kwl.add(prefix, ossimKeywordNames::QUALITY_KW, m_quality, true);
+   
+   return result;
+}
+
+
+void ossimKakaduJpipHandler::flushCache()
+{
+   ossim_uint32 idx = 0;
+   for(idx = 0; idx < m_rlevelBlockCache.size();++idx)
+   {
+      ossimAppFixedTileCache::instance()->flush(m_rlevelBlockCache[idx]);
+   }
+}
+
+
diff --git a/ossim_plugins/kakadu/ossimKakaduJpipHandler.h b/ossim_plugins/kakadu/ossimKakaduJpipHandler.h
new file mode 100644
index 0000000..257403d
--- /dev/null
+++ b/ossim_plugins/kakadu/ossimKakaduJpipHandler.h
@@ -0,0 +1,116 @@
+//----------------------------------------------------------------------------
+//
+// License:  See top level LICENSE.txt file
+//
+// Author: Garrett Potts
+//
+// Description: Factory for OSSIM JPIP reader using kakadu library.
+//----------------------------------------------------------------------------
+// $Id$
+#ifndef ossimJpipHandler_HEADER
+#define ossimJpipHandler_HEADER
+#include <ossim/imaging/ossimImageHandler.h>
+#include <ossim/base/ossimUrl.h>
+#include <ossim/imaging/ossimAppFixedTileCache.h>
+#include <ossim/support_data/ossimJpipMessageDecoder.h>
+#include <ossim/base/ossimHttpResponse.h>
+#include <ossim/base/ossimHttpRequest.h>
+
+#include <kdu_cache.h>
+#include <kdu_region_decompressor.h>
+#include <kdu_client.h>
+#include <kdu_compressed.h>
+
+
+class  ossimKakaduJpipHandler : public ossimImageHandler
+{
+public:
+   typedef std::vector<kdu_core::kdu_byte> ByteBuffer;
+   struct Box
+   {
+      ossim_uint32 m_type;
+      ByteBuffer m_buffer;
+   };
+   typedef std::vector<Box> BoxList;
+   typedef std::vector<ossimIrect> RectList;
+   typedef std::vector<ossimString> StringList;
+   typedef std::vector<ossimIpt> RLevelBlockSizeList;
+   typedef std::vector<ossimAppFixedTileCache::ossimAppFixedCacheId> RLevelCacheList;
+   
+   ossimKakaduJpipHandler();
+   virtual ~ossimKakaduJpipHandler();
+   virtual void close();
+   virtual bool open();
+   virtual bool isOpen()const;
+   virtual ossimRefPtr<ossimImageData> getTile(const  ossimIrect& rect,
+                                               ossim_uint32 resLevel=0);
+   
+   virtual ossim_uint32 getNumberOfLines(ossim_uint32 resLevel = 0) const;
+   virtual ossim_uint32 getNumberOfSamples(ossim_uint32 resLevel = 0) const;
+   virtual ossim_uint32 getImageTileWidth() const;
+   virtual ossim_uint32 getImageTileHeight() const;
+   
+   virtual ossim_uint32 getNumberOfInputBands() const;
+   virtual ossim_uint32 getNumberOfOutputBands() const;
+   virtual ossim_uint32 getNumberOfDecimationLevels() const;
+   virtual bool isImageTiled() const
+   {
+      return !m_tileSize.hasNans();
+   }
+   virtual ossimScalarType getOutputScalarType() const;
+   virtual void setProperty(ossimRefPtr<ossimProperty> property);
+   virtual ossimRefPtr<ossimProperty> getProperty(const ossimString& name)const;
+   virtual void getPropertyNames(std::vector<ossimString>& propertyNames)const;
+   virtual void extractBoxes(BoxList& boxList);
+   virtual ossimRefPtr<ossimImageGeometry> getImageGeometry();
+   //virtual void extractXml(ossimString& xmlBoxes);
+   virtual bool loadState(const ossimKeywordlist& kwl, const char* prefix = 0);
+   virtual bool saveState(ossimKeywordlist& kwl, const char* prefix = 0)const;
+   
+protected:
+   ossimRefPtr<ossimImageData> getTileAtRes(const  ossimIrect& rect,
+                                            ossim_uint32 resLevel=0);
+   //void extractXmlRecurse(ossimString& xmlBoxes, jp2_input_box* pParentBox=0);
+   virtual void extractBoxes(BoxList& boxList, kdu_supp::jp2_input_box* pParentBox);
+   void showBoxes(kdu_supp::jp2_input_box* pParentBox=0);
+   bool makeConnectionIfNeeded(kdu_supp::kdu_client* client);
+   //virtual bool initializeImplementation();
+   int convertClassIdToKdu(int id);
+   void allocateTile();
+   void deleteRlevelCache();
+   void performRlevelSetup(kdu_core::kdu_codestream& codestream);   
+   bool loadClient(kdu_supp::kdu_client* client, kdu_supp::kdu_window& window);
+   bool openStream();
+   void flushCache();
+   void initializeRlevelCache();
+   void allocateSession();
+   
+   bool            m_useOurGrab;
+   ossimUrl        m_baseUrl;
+   RectList        m_overviewDimensions;
+   ossim_uint32    m_nInputBands;
+   ossim_uint32    m_nOutputBands;
+   bool            m_signed;
+   ossim_uint16    m_bitDepth;
+   ossim_uint32    m_nQualityLayers;
+   ossimIpt        m_tileSize;
+   ossimIrect      m_imageBounds;
+   ossim_uint32    m_resLevels;
+   int             m_bYCC;
+   ossimRefPtr<ossimImageData> m_tile;
+   
+   ossim_float32   m_quality;
+   kdu_supp::kdu_client*     m_headerClient;
+   kdu_supp::kdu_client*     m_client;
+   kdu_supp::jp2_family_src  m_jp2Family;
+   int             m_requestQueueId;
+   RLevelBlockSizeList m_rlevelTileSize;
+   RLevelCacheList m_rlevelBlockCache;
+
+   ossimString     m_cid;
+   ossimString     m_path;
+   ossimString     m_transport;
+   ossimRefPtr<ossimHttpRequest> m_request;
+   TYPE_DATA;    
+};
+#endif
diff --git a/ossim_plugins/kakadu/ossimKakaduJpipHandlerFactory.cpp b/ossim_plugins/kakadu/ossimKakaduJpipHandlerFactory.cpp
new file mode 100644
index 0000000..986eba4
--- /dev/null
+++ b/ossim_plugins/kakadu/ossimKakaduJpipHandlerFactory.cpp
@@ -0,0 +1,225 @@
+//----------------------------------------------------------------------------
+//
+// License:  See top level LICENSE.txt file
+//
+// Author: Garrett Potts
+//
+// Description: Factory for OSSIM JPIP reader using kakadu library.
+//----------------------------------------------------------------------------
+// $Id$
+
+#include "ossimKakaduJpipHandlerFactory.h"
+#include "ossimKakaduJpipHandler.h"
+#include <ossim/base/ossimKeywordlist.h>
+#include <ossim/base/ossimKeywordNames.h>
+#include <ossim/base/ossimUrl.h>
+#include <ossim/base/ossimRefPtr.h>
+#include <ossim/base/ossimString.h>
+#include <ossim/base/ossimTrace.h>
+#include <ossim/imaging/ossimImageHandler.h>
+
+static const ossimTrace traceDebug( ossimString("ossimKakaduJpipHandlerFactory:debug") );
+
+class ossimImageHandler;
+
+RTTI_DEF1(ossimKakaduJpipHandlerFactory,
+          "ossimKakaduJpipHandlerFactory",
+          ossimImageHandlerFactoryBase);
+
+ossimKakaduJpipHandlerFactory::~ossimKakaduJpipHandlerFactory()
+{
+}
+
+ossimKakaduJpipHandlerFactory* ossimKakaduJpipHandlerFactory::instance()
+{
+   static ossimKakaduJpipHandlerFactory inst;
+   return &inst;
+}
+
+ossimImageHandler* ossimKakaduJpipHandlerFactory::open(const ossimFilename& fileName,
+                                                       bool openOverview)const
+{
+   static const char* M = "ossimKakaduJpipHandlerFactory::open(filename) -- ";
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)<<M<<"Entered with filename <"<<fileName<<">\n" ;
+   }
+   
+   ossimRefPtr<ossimImageHandler> reader = 0; 
+   
+   if (traceDebug()) ossimNotify(ossimNotifyLevel_DEBUG)<<M<< "Trying ossimKakaduJpipHandler...";
+   reader = new ossimKakaduJpipHandler();
+   reader->setOpenOverviewFlag(openOverview);
+   if(!reader->open(fileName))
+   {
+      reader = 0;
+   }
+   
+   if (traceDebug())
+   {
+      if (reader.valid())
+         ossimNotify(ossimNotifyLevel_DEBUG)<<M<< "   SUCCESS" << std::endl;
+      else
+         ossimNotify(ossimNotifyLevel_DEBUG)<<M<< "   Open FAILED" << std::endl;
+   }
+ 
+   return reader.release();
+}
+
+ossimImageHandler* ossimKakaduJpipHandlerFactory::open(const ossimKeywordlist& kwl,
+                                                  const char* prefix)const
+{
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimKakaduJpipHandlerFactory::open(kwl, prefix) DEBUG: entered..."
+         << std::endl;
+   }
+   ossimRefPtr<ossimImageHandler> reader = 0; 
+   const char* lookup = kwl.find(prefix, ossimKeywordNames::TYPE_KW);
+   const char* filenameLookup = kwl.find(prefix, ossimKeywordNames::FILENAME_KW);
+   const char* urlLookup = kwl.find(prefix, "url");
+   
+   ossimRefPtr<ossimObject> obj;
+   // first check if url is present in keywordlist
+   if(urlLookup)
+   {
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "URL lookup"
+         << std::endl;
+   }
+
+      if(lookup)
+      {
+         obj = createObject(ossimString(lookup));
+         reader = dynamic_cast<ossimImageHandler*> (obj.get());
+         obj = 0;
+         if(reader.valid())
+         {
+            if(reader->loadState(kwl, prefix) == false)
+            {
+               reader = 0;
+            }
+         }
+      }
+      if(!reader.valid())
+      {
+         if(ossimUrl(urlLookup).getProtocol().downcase().contains("jpip"))
+         {
+            reader = new ossimKakaduJpipHandler();
+            if(reader->loadState(kwl, prefix) == false)
+            {
+               reader = 0;
+            }
+         }
+      }
+   }
+   else if(filenameLookup)
+   {
+      ossimFilename local(filenameLookup);
+
+     
+      // check if the filename is a jpip url
+      if(!ossimFilename(filenameLookup).exists()&&
+         ossimUrl(filenameLookup).getProtocol().downcase().contains("jpip"))
+      {
+         reader = open(ossimFilename(filenameLookup));
+      }
+      else if(local.exists()&&(local.ext().downcase()=="jpip"))
+      {
+         // do local file keywordlist
+         //
+         ossimKeywordlist tempKwl;
+         tempKwl.add(kwl, prefix, true);
+         if(tempKwl.addFile(ossimFilename(filenameLookup)))
+         {
+            if(tempKwl.find("url"))
+            {
+               reader = open(tempKwl);
+            }
+         }
+      }
+   }
+   else if(lookup)
+   {
+      obj = createObject(ossimString(lookup));
+      reader = dynamic_cast<ossimImageHandler*> (obj.get());
+      obj = 0;
+      if(reader.valid())
+      {
+         if(reader->loadState(kwl, prefix) == false)
+         {
+            reader = 0;
+         }
+      }
+   }
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimKakaduJpipHandlerFactory::open(kwl, prefix) DEBUG: leaving..."
+         << std::endl;
+   }
+   
+   return reader.release();
+}
+
+ossimObject* ossimKakaduJpipHandlerFactory::createObject(const ossimString& typeName)const
+{
+   ossimRefPtr<ossimObject> result = 0;
+   
+   if(typeName == STATIC_TYPE_NAME(ossimKakaduJpipHandler))
+   {
+      result =  new ossimKakaduJpipHandler();
+   }
+   
+   return result.release();
+}
+
+ossimObject* ossimKakaduJpipHandlerFactory::createObject(
+   const ossimKeywordlist& kwl,
+   const char* prefix)const
+{
+   return this->open(kwl, prefix);
+}
+ 
+void ossimKakaduJpipHandlerFactory::getTypeNameList(
+   std::vector<ossimString>& typeList)const
+{
+   typeList.push_back(STATIC_TYPE_NAME(ossimKakaduJpipHandler));
+}
+
+void ossimKakaduJpipHandlerFactory::getSupportedExtensions(
+   ossimImageHandlerFactoryBase::UniqueStringList& extensionList)const
+{
+   extensionList.push_back("jp2");
+   extensionList.push_back("jpip");
+}
+
+void ossimKakaduJpipHandlerFactory::getImageHandlersBySuffix(ossimImageHandlerFactoryBase::ImageHandlerList& result,
+                                                       const ossimString& ext)const
+{
+    ossimString testExt = ext.downcase();
+   if((testExt == "jp2")||(testExt=="jp2"))
+   {
+      result.push_back(new ossimKakaduJpipHandler());
+   }
+}
+
+/**
+ *
+ * Will add to the result list and handler that supports the passed in mime type
+ *
+ */
+void ossimKakaduJpipHandlerFactory::getImageHandlersByMimeType(ossimImageHandlerFactoryBase::ImageHandlerList& result,
+                                                          const ossimString& mimeType)const
+{
+}
+
+
+ossimKakaduJpipHandlerFactory::ossimKakaduJpipHandlerFactory(){}
+
+ossimKakaduJpipHandlerFactory::ossimKakaduJpipHandlerFactory(const ossimKakaduJpipHandlerFactory&){}
+
+void ossimKakaduJpipHandlerFactory::operator=(const ossimKakaduJpipHandlerFactory&){}
diff --git a/ossim_plugins/kakadu/ossimKakaduJpipHandlerFactory.h b/ossim_plugins/kakadu/ossimKakaduJpipHandlerFactory.h
new file mode 100644
index 0000000..922aa7b
--- /dev/null
+++ b/ossim_plugins/kakadu/ossimKakaduJpipHandlerFactory.h
@@ -0,0 +1,120 @@
+//----------------------------------------------------------------------------
+//
+// License:  See top level LICENSE.txt file
+//
+// Author:  Garrett Potts
+//
+// Description: Factory for OSSIM JPIP reader using kakadu library.
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef ossimKakaduJpipHandlerFactory_HEADER
+#define ossimKakaduJpipHandlerFactory_HEADER 1
+
+#include <ossim/imaging/ossimImageHandlerFactoryBase.h>
+
+class ossimString;
+class ossimFilename;
+class ossimKeywordlist;
+
+/** @brief Factory for J2K image reader. */
+class ossimKakaduJpipHandlerFactory : public ossimImageHandlerFactoryBase
+{
+public:
+
+   /** @brief virtual destructor */
+   virtual ~ossimKakaduJpipHandlerFactory();
+
+   /**
+    * @brief static method to return instance (the only one) of this class.
+    * @return pointer to instance of this class.
+    */
+   static ossimKakaduJpipHandlerFactory* instance();
+
+   /**
+    * @brief open that takes a file name.
+    * @param file The file to open.
+    * @param openOverview If true image handler will attempt to open overview.
+    * default = true
+    * @return pointer to image handler on success, NULL on failure.
+    */
+   virtual ossimImageHandler* open(const ossimFilename& fileName,
+                                   bool openOverview=true) const;
+
+   /**
+    * @brief open that takes a keyword list and prefix.
+    * @param kwl The keyword list.
+    * @param prefix the keyword list prefix.
+    * @return pointer to image handler on success, NULL on failure.
+    */
+   virtual ossimImageHandler* open(const ossimKeywordlist& kwl,
+                                   const char* prefix=0)const;
+
+   /**
+    * @brief createObject that takes a class name (ossimKakaduReader)
+    * @param typeName Should be "ossimKakaduReader".
+    * @return pointer to image writer on success, NULL on failure.
+    */
+   virtual ossimObject* createObject(const ossimString& typeName)const;
+   
+   /**
+    * @brief Creates and object given a keyword list and prefix.
+    * @param kwl The keyword list.
+    * @param prefix the keyword list prefix.
+    * @return pointer to image handler on success, NULL on failure.
+    */
+   virtual ossimObject* createObject(const ossimKeywordlist& kwl,
+                                     const char* prefix=0)const;
+   
+   /**
+    * @brief Adds ossimKakaduWriter to the typeList.
+    * @param typeList List to add to.
+    */
+   virtual void getTypeNameList(std::vector<ossimString>& typeList)const;
+
+   /**
+    * @brief Method to add supported extension to the list, like "jp2".
+    *
+    * @param extensionList The list to add to.
+    */
+   virtual void getSupportedExtensions(
+      ossimImageHandlerFactoryBase::UniqueStringList& extensionList)const;
+  
+   /**
+    *
+    * Will add to the result list any handler that supports the passed in extensions
+    *
+    */
+   virtual void getImageHandlersBySuffix(ossimImageHandlerFactoryBase::ImageHandlerList& result,
+                                         const ossimString& ext)const;
+   /**
+    *
+    * Will add to the result list and handler that supports the passed in mime type
+    *
+    */
+   virtual void getImageHandlersByMimeType(ossimImageHandlerFactoryBase::ImageHandlerList& result,
+                                           const ossimString& mimeType)const;
+protected:
+
+   /**
+    * @brief Method to weed out extensions that this plugin knows it does
+    * not support.  This is to avoid a costly open on say a tiff or jpeg that
+    * is not handled by this plugin.
+    *
+    * @return true if extension, false if not.
+    */
+  // bool hasExcludedExtension(const ossimFilename& file) const;
+   
+   /** @brief hidden from use default constructor */
+   ossimKakaduJpipHandlerFactory();
+
+   /** @brief hidden from use copy constructor */
+   ossimKakaduJpipHandlerFactory(const ossimKakaduJpipHandlerFactory&);
+
+   /** @brief hidden from use copy constructor */
+   void operator=(const ossimKakaduJpipHandlerFactory&);
+
+TYPE_DATA
+};
+
+#endif /* end of #ifndef ossimKakaduJpipHandlerFactory_HEADER */
diff --git a/ossim_plugins/kakadu/ossimKakaduJpipImageGeometryFactory.cpp b/ossim_plugins/kakadu/ossimKakaduJpipImageGeometryFactory.cpp
new file mode 100644
index 0000000..125b4f0
--- /dev/null
+++ b/ossim_plugins/kakadu/ossimKakaduJpipImageGeometryFactory.cpp
@@ -0,0 +1,114 @@
+#include "ossimKakaduJpipImageGeometryFactory.h"
+#include "ossimKakaduJpipHandler.h"
+#include <ossim/projection/ossimProjectionFactoryRegistry.h>
+
+ossimKakaduJpipImageGeometryFactory::ossimKakaduJpipImageGeometryFactory()
+{
+}
+
+ossimKakaduJpipImageGeometryFactory* ossimKakaduJpipImageGeometryFactory::instance()
+{
+   static ossimKakaduJpipImageGeometryFactory inst;
+   return &inst;
+}
+
+ossimImageGeometry* ossimKakaduJpipImageGeometryFactory::createGeometry(const ossimString& typeName)const
+{   
+   return 0;
+}
+
+ossimImageGeometry* ossimKakaduJpipImageGeometryFactory::createGeometry(
+                                                                        const ossimKeywordlist& kwl, 
+                                                                        const char* prefix)const
+{
+   ossimRefPtr<ossimImageGeometry> result = 0;   
+   //std::cout << "ossimKakaduJpipImageGeometryFactory::createGeometry (kwl, prefix).................. entered" << std::endl;
+   
+   ossimRefPtr<ossimProjection> proj = ossimProjectionFactoryRegistry::instance()->createProjection(kwl, prefix);
+   if(proj.valid())
+   {
+      result = new ossimImageGeometry();
+      result->setProjection(proj.get());
+      
+      ossimRefPtr<ossim2dTo2dTransform> transform = createTransform(kwl, prefix);
+      result->setTransform(transform.get());
+   }
+   return result.release();
+}
+
+ossimImageGeometry* ossimKakaduJpipImageGeometryFactory::createGeometry(
+                                                              const ossimFilename& /* filename */, ossim_uint32 /* entryIdx */)const
+{
+   //std::cout << "ossimKakaduJpipImageGeometryFactory::createGeometry(filename) .................. entered" << std::endl;
+   // currently don't support this option just yet by this factory
+   return 0;
+}
+
+bool ossimKakaduJpipImageGeometryFactory::extendGeometry(ossimImageHandler* handler)const
+{
+   //std::cout << "ossimKakaduJpipImageGeometryFactory::extendGeometry(handler) .................. entered" << std::endl;
+   bool result = false;
+   if (handler)
+   {
+      bool add2D = true;
+      ossimRefPtr<ossimImageGeometry> geom = handler->getImageGeometry();
+      if(geom.valid())
+      {
+         if(!geom->getProjection())
+         {
+//            geom->setProjection(createProjection(handler));
+//            result = geom->hasProjection();
+         }
+         if(geom->getProjection())
+         {
+//            if( !(dynamic_cast<ossimSensorModel*>(geom->getProjection())))
+//            {
+//               add2D = false;
+//            }
+         }
+         if(!geom->getTransform()&&add2D)
+         {
+            geom->setTransform(createTransform(handler));
+            result |= geom->hasTransform();
+         }
+      }
+   }
+   
+   return result;
+}
+
+void ossimKakaduJpipImageGeometryFactory::getTypeNameList(
+                                                std::vector<ossimString>& typeList)const
+{
+}
+
+
+ossim2dTo2dTransform* ossimKakaduJpipImageGeometryFactory::createTransform(
+                                                                 ossimImageHandler* handler)const
+{
+   // Currently nothing to do...
+   
+   ossimRefPtr<ossim2dTo2dTransform> result = 0;
+   
+   return result.release();
+}
+
+ossim2dTo2dTransform* ossimKakaduJpipImageGeometryFactory::createTransform(const ossimKeywordlist& kwl, 
+                                                                           const char* prefix)const
+{
+   // Currently nothing to do...
+   
+   ossimRefPtr<ossim2dTo2dTransform> result = 0;
+   
+   return result.release();
+}
+
+
+ossimProjection* ossimKakaduJpipImageGeometryFactory::createProjection(
+                                                             ossimImageHandler* handler) const
+{
+   ossimRefPtr<ossimProjection> result =
+   ossimProjectionFactoryRegistry::instance()->createProjection(handler);
+   
+   return result.release();
+}
diff --git a/ossim_plugins/kakadu/ossimKakaduJpipImageGeometryFactory.h b/ossim_plugins/kakadu/ossimKakaduJpipImageGeometryFactory.h
new file mode 100644
index 0000000..9b3fc4a
--- /dev/null
+++ b/ossim_plugins/kakadu/ossimKakaduJpipImageGeometryFactory.h
@@ -0,0 +1,43 @@
+#ifndef ossimKakaduJpipImageGeometryFactory_HEADER
+#define ossimKakaduJpipImageGeometryFactory_HEADER 1
+#include <ossim/imaging/ossimImageGeometryFactoryBase.h>
+
+class ossimImageHandler;
+class ossimKakaduJpipImageGeometryFactory : public ossimImageGeometryFactoryBase
+{
+public:
+   static ossimKakaduJpipImageGeometryFactory* instance();
+   virtual ossimImageGeometry* createGeometry(const ossimString& typeName)const;
+   virtual ossimImageGeometry* createGeometry(const ossimKeywordlist& kwl,
+                                              const char* prefix=0)const;
+   virtual ossimImageGeometry* createGeometry(const ossimFilename& filename,
+                                              ossim_uint32 entryIdx)const;
+   virtual bool extendGeometry(ossimImageHandler* handler)const;
+   
+   virtual void getTypeNameList(std::vector<ossimString>& typeList)const;
+   
+   /**
+    * This is a utility method used by crateGeoemtry that takes an image handler
+    */
+   virtual ossim2dTo2dTransform* createTransform(ossimImageHandler* handler)const;
+   
+   
+   /**
+    * This is a utility method used by crateGeoemtry that takes keywordlist and prefix
+    */
+   virtual ossim2dTo2dTransform* createTransform(const ossimKeywordlist& kwl, 
+                                                 const char* prefix=0)const;
+   
+   /**
+    * @brief Utility method to create a projection from an image handler.
+    * @param handler The image handler to create projection from.
+    * @return Pointer to an ossimProjection on success, null on error.
+    */
+   virtual ossimProjection* createProjection(ossimImageHandler* handler) const;
+   
+protected:
+   ossimKakaduJpipImageGeometryFactory();
+
+};
+
+#endif
diff --git a/ossim_plugins/kakadu/ossimKakaduJpipInfo.cpp b/ossim_plugins/kakadu/ossimKakaduJpipInfo.cpp
new file mode 100644
index 0000000..c27cd66
--- /dev/null
+++ b/ossim_plugins/kakadu/ossimKakaduJpipInfo.cpp
@@ -0,0 +1,160 @@
+#include "ossimKakaduJpipInfo.h"
+#include "ossimKakaduJpipHandler.h"
+#include <ossim/base/ossimUrl.h>
+#include <ossim/base/ossimFilename.h>
+#include <ossim/base/ossimXmlDocument.h>
+#include <ossim/support_data/ossimTiffInfo.h>
+#include <ossim/projection/ossimProjectionFactoryRegistry.h>
+
+//---
+// Kakadu code has defines that have (kdu_uint32) which should be
+// (kdu_core::kdu_uint32)
+//---
+using namespace kdu_core;
+
+ossimKakaduJpipInfo::ossimKakaduJpipInfo()
+{
+   
+}
+
+ossimKakaduJpipInfo::~ossimKakaduJpipInfo()
+{
+   
+}
+
+bool ossimKakaduJpipInfo::open(const ossimFilename& file)
+{
+   m_handler = new ossimKakaduJpipHandler();
+   ossimImageHandler* handler = m_handler.get();
+   bool result = false;
+   ossimUrl url(file.c_str());
+   ossimString protocol = url.getProtocol().downcase();
+   if((protocol == "jpip")||
+      (protocol == "jpips"))
+   {
+      result = handler->open(file);
+
+   }
+   else
+   {
+      url = ossimUrl();
+      if(file.ext() == "jpip")
+      {
+         ossimKeywordlist kwl;
+         
+         if(kwl.addFile(file.c_str()))
+         {
+            result = handler->loadState(kwl);
+         }
+      }
+   }
+   if(!result) m_handler = 0;
+   
+   return result;
+}
+
+std::ostream& ossimKakaduJpipInfo::print(std::ostream& out) const
+{
+   if(m_handler.valid())
+   {
+      ossimKeywordlist kwl;
+      ossimString xml;
+      ossimKakaduJpipHandler::BoxList boxes;
+      m_handler->extractBoxes(boxes);
+      
+      ossim_uint32 idx = 0;
+      for(idx = 0; idx < boxes.size(); ++idx)
+      {
+         if(boxes[idx].m_type == jp2_xml_4cc)
+         {
+            ossimRefPtr<ossimXmlDocument> xmlDoc = new ossimXmlDocument();
+            //std::istringstream in(ossimString((char*)&boxes[idx].m_buffer.front(),
+            //                                  (char*)&boxes[idx].m_buffer.front() + boxes[idx].m_buffer.size()));
+            ossimByteStreamBuffer byteStreamBuf((char*)&boxes[idx].m_buffer.front(), boxes[idx].m_buffer.size());
+            std::iostream in(&byteStreamBuf);
+            
+        //    std::cout << "________________________________________________" << std::endl;
+        //    std::cout << ossimString((char*)&boxes[idx].m_buffer.front(),
+        //                             (char*)&boxes[idx].m_buffer.front() + boxes[idx].m_buffer.size()) << std::endl;
+        //    std::cout << "________________________________________________" << std::endl;
+            if(ossimString((char*)&boxes[idx].m_buffer.front(), (char*)&boxes[idx].m_buffer.front()+4) ==
+               "<?xm")
+            {
+               xmlDoc->read(in);
+            }
+            else
+            {
+               ossimRefPtr<ossimXmlNode> node = new ossimXmlNode();
+               if(node->read(in))
+               {
+                  xmlDoc->initRoot(node);
+               }
+            }
+            if(xmlDoc->getRoot().valid())
+            {
+               ossimRefPtr<ossimXmlNode> node = new ossimXmlNode();
+               node->setTag("jpip.image0");
+               node->addChildNode(xmlDoc->getRoot().get());
+               xmlDoc->initRoot(node.get());
+               xmlDoc->toKwl(kwl);
+               out << kwl;
+            }
+         }
+         else if(boxes[idx].m_type == jp2_uuid_4cc)
+         {
+            kdu_byte geojp2_uuid[16] = {0xB1,0x4B,0xF8,0xBD,0x08,0x3D,0x4B,0x43,
+               0xA5,0xAE,0x8C,0xD7,0xD5,0xA6,0xCE,0x03};
+            
+            if(memcmp(&boxes[idx].m_buffer.front(),geojp2_uuid, 16)==0)
+            {
+               ossimTiffInfo info;
+               
+               //---
+               // Have geotiff boxes with badly terminated geotiffs. So to keep
+               // the tag parser from walking past the first image file directory
+               // (IFD) into garbage we will set the process overview flag to false.
+               //
+               // Note if we ever get multiple entries we will need to take this out.
+               //---
+               info.setProcessOverviewFlag(false);
+               //ossimByteStreamBuffer buf((char*)&boxList[idx].m_buffer.front()+16, 
+               //                          boxList[idx].m_buffer.size()-16);
+               //std::istream str(&buf);
+               std::ofstream outStr("/tmp/dump.bin", std::ios::out|std::ios::binary);
+               outStr.write((char*)&boxes[idx].m_buffer.front(),
+                            boxes[idx].m_buffer.size());
+               outStr.close();
+               std::istringstream str(ossimString((char*)&boxes[idx].m_buffer.front()+16,
+                                                  (char*)&boxes[idx].m_buffer.front() + boxes[idx].m_buffer.size()));
+               ossim_uint32 entry = 0;
+               ossimKeywordlist kwl; // Used to capture geometry data. 
+               // std::cout << ossimString((char*)&boxList[idx].m_buffer.front() + 16,
+               //                          (char*)&boxList[idx].m_buffer.front() + boxList[idx].m_buffer.size()) << std::endl;
+               if ( info.getImageGeometry(str, kwl, entry) )
+               {
+                  kwl.stripPrefixFromAll("image0.");
+                  kwl.addPrefixToAll("jpip.image0.geojp2.");
+                  out << kwl << std::endl;
+                 // ossimRefPtr<ossimProjection> proj = ossimProjectionFactoryRegistry::instance()->createProjection(kwl, "image0.");
+                  //if(proj.valid())
+                 // {
+                 //    ossimKeywordlist projKwl;
+                 //    proj->saveState(projKwl,"jpip.image0.geojp2.");
+                 //    out << projKwl << std::endl;
+                 // }
+               }
+            }
+            else
+            {
+            }
+         }
+      }
+   }
+   return out;
+}
+
+void ossimKakaduJpipInfo::setHandler(ossimKakaduJpipHandler* handler)
+{
+   m_handler = handler;
+}
+
diff --git a/ossim_plugins/kakadu/ossimKakaduJpipInfo.h b/ossim_plugins/kakadu/ossimKakaduJpipInfo.h
new file mode 100644
index 0000000..43a8623
--- /dev/null
+++ b/ossim_plugins/kakadu/ossimKakaduJpipInfo.h
@@ -0,0 +1,66 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author:  Garrett Potts
+//
+// Description: Does an information dump of any XML JP2 boxes plus basic
+//              image information
+// 
+//----------------------------------------------------------------------------
+// $Id$
+#ifndef ossimKakduJpipInfo_HEADER
+#define ossimKakduJpipInfo_HEADER
+
+#include <iosfwd>
+#include <ossim/support_data/ossimInfoBase.h>
+#include <ossim/base/ossimConstants.h>
+#include <ossim/base/ossimReferenced.h>
+#include "ossimKakaduJpipHandler.h"
+class ossimFilename;
+class ossimKeywordlist;
+
+/**
+ * @brief Info Base.
+ *
+ * This is the base class for all info objects.  The purpose of an Info object
+ * is to dump whatever info is available for a given file name to user.
+ */
+class ossimKakaduJpipInfo : public ossimInfoBase
+{
+public:
+   
+   /** default constructor */
+   ossimKakaduJpipInfo();
+   
+   
+   /**
+    * @brief open method.
+    *
+    * @param file File name to open.
+    *
+    * @return true on success false on error.
+    */
+   virtual bool open(const ossimFilename& file);
+   
+   /**
+    * Print method.
+    *
+    * @param out Stream to print to.
+    * 
+    * @return std::ostream&
+    */
+   virtual std::ostream& print(std::ostream& out) const;
+   
+   virtual void setHandler(ossimKakaduJpipHandler* handler);
+protected:
+   /** virtual destructor */
+   virtual ~ossimKakaduJpipInfo();
+   mutable ossimRefPtr<ossimKakaduJpipHandler> m_handler;
+   
+};
+
+#endif /* End of "#ifndef ossimInfoBase_HEADER" */
+
diff --git a/ossim_plugins/kakadu/ossimKakaduJpipInfoFactory.cpp b/ossim_plugins/kakadu/ossimKakaduJpipInfoFactory.cpp
new file mode 100644
index 0000000..a017993
--- /dev/null
+++ b/ossim_plugins/kakadu/ossimKakaduJpipInfoFactory.cpp
@@ -0,0 +1,43 @@
+#include "ossimKakaduJpipInfoFactory.h"
+#include "ossimKakaduJpipInfo.h"
+#include <ossim/base/ossimRefPtr.h>
+#include <iostream>
+
+ossimKakaduJpipInfoFactory::~ossimKakaduJpipInfoFactory()
+{
+}
+
+ossimKakaduJpipInfoFactory* ossimKakaduJpipInfoFactory::instance()
+{
+   static ossimKakaduJpipInfoFactory inst;
+   return &inst;
+}
+
+ossimInfoBase* ossimKakaduJpipInfoFactory::create(const ossimFilename& file) const
+{
+
+   ossimRefPtr<ossimKakaduJpipInfo> jpipInfo = new ossimKakaduJpipInfo();
+   if(!jpipInfo->open(file))
+   {
+      jpipInfo = 0;
+   }
+   return jpipInfo.release();
+}
+
+
+/** hidden from use default constructor */
+ossimKakaduJpipInfoFactory::ossimKakaduJpipInfoFactory()
+{
+}
+
+/** hidden from use copy constructor */
+ossimKakaduJpipInfoFactory::ossimKakaduJpipInfoFactory(const ossimKakaduJpipInfoFactory& )
+{
+   
+}
+
+/** hidden from use operator = */
+const ossimKakaduJpipInfoFactory& ossimKakaduJpipInfoFactory::operator=(const ossimKakaduJpipInfoFactory& )
+{
+   return *this;
+}
diff --git a/ossim_plugins/kakadu/ossimKakaduJpipInfoFactory.h b/ossim_plugins/kakadu/ossimKakaduJpipInfoFactory.h
new file mode 100644
index 0000000..6a78942
--- /dev/null
+++ b/ossim_plugins/kakadu/ossimKakaduJpipInfoFactory.h
@@ -0,0 +1,37 @@
+#ifndef ossimKakaduJpipInfoFactory_HEADER
+#define ossimKakaduJpipInfoFactory_HEADER 1
+#include <ossim/support_data/ossimInfoFactoryInterface.h>
+
+class ossimKakaduJpipInfoFactory : public ossimInfoFactoryInterface
+{
+public:
+   
+   /** virtual destructor */
+   virtual ~ossimKakaduJpipInfoFactory();
+   
+   static ossimKakaduJpipInfoFactory* instance();
+   
+   /**
+    * @brief create method.
+    *
+    * @param file Some file you want info for.
+    *
+    * @return ossimInfoBase* on success 0 on failure.  Caller is responsible
+    * for memory.
+    */
+   virtual ossimInfoBase* create(const ossimFilename& file) const;
+   
+private:
+   
+   /** hidden from use default constructor */
+   ossimKakaduJpipInfoFactory();
+   
+   /** hidden from use copy constructor */
+   ossimKakaduJpipInfoFactory(const ossimKakaduJpipInfoFactory& obj);
+   
+   /** hidden from use operator = */
+   const ossimKakaduJpipInfoFactory& operator=(const ossimKakaduJpipInfoFactory& rhs);
+
+};
+
+#endif
diff --git a/ossim_plugins/kakadu/ossimKakaduKeywords.h b/ossim_plugins/kakadu/ossimKakaduKeywords.h
new file mode 100644
index 0000000..beb6eb3
--- /dev/null
+++ b/ossim_plugins/kakadu/ossimKakaduKeywords.h
@@ -0,0 +1,22 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Description: Header file for common keyword names.
+//
+//----------------------------------------------------------------------------
+// $Id: ossimKakaduKeywords.h 23664 2015-12-14 14:17:27Z dburken $
+
+#ifndef ossimKakaduKeywords_HEADER
+#define ossimKakaduKeywords_HEADER 1
+
+static const ossimString COMPRESSION_RATTIO_KW = "compression_ratio";
+static const ossimString LEVELS_KW = "levels";
+static const ossimString REVERSIBLE_KW = "reversible";
+static const ossimString THREADS_KW = "threads";
+static const ossimString ADD_ALPHA_CHANNEL_KW = "add_alpha_channel";
+
+#endif /* #ifndef ossimKakaduKeywords_HEADER */
+
diff --git a/ossim_plugins/kakadu/ossimKakaduMessaging.h b/ossim_plugins/kakadu/ossimKakaduMessaging.h
new file mode 100644
index 0000000..4b09c9c
--- /dev/null
+++ b/ossim_plugins/kakadu/ossimKakaduMessaging.h
@@ -0,0 +1,69 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Description: Common OSSIM Kakadu messaging definitions.
+//
+//----------------------------------------------------------------------------
+// $Id: ossimKakaduMessaging.h 23664 2015-12-14 14:17:27Z dburken $
+
+#ifndef ossimKakaduMessaging_HEADER
+#define ossimKakaduMessaging_HEADER 1
+
+#include <ossim/base/ossimNotify.h>
+#include <kdu_messaging.h>
+#include <ostream>
+#include <string>
+
+/* ========================================================================= */
+/* Set up kakadu messaging services to be sent to ossimNotify.               */
+/* ========================================================================= */
+class kdu_stream_message : public kdu_core::kdu_thread_safe_message
+{
+public: // Member classes
+   kdu_stream_message( std::ostream *stream, bool throw_exc )
+      : kdu_core::kdu_thread_safe_message(),
+        m_stream(stream),
+        m_throw_exc(throw_exc)
+   {}
+
+   virtual void put_text(const char *string)
+   {
+      (*m_stream) << string;
+   }
+
+   virtual void flush(bool end_of_message=false)
+   {
+      m_stream->flush();
+
+      // This call unlocks mutex in kakadu_thread_safe_message:
+      kdu_core::kdu_thread_safe_message::flush(end_of_message);
+
+      if (end_of_message && m_throw_exc)
+      {
+         //---
+         // Using ossimException caused hang.  From kakadu kdu_messaging.h:
+         // Unless you have good reason to do otherwise, you are strongly
+         // recommended to use the default `exception_val' of
+         // `KDU_ERROR_EXCEPTION'
+         //---
+         throw KDU_ERROR_EXCEPTION;
+      }
+   }
+   
+private: // Data
+   std::ostream* m_stream;
+   bool m_throw_exc;
+};
+
+static kdu_stream_message cout_message(&ossimNotify(ossimNotifyLevel_NOTICE),
+                                       false);
+static kdu_stream_message cerr_message(&ossimNotify(ossimNotifyLevel_WARN),
+                                       true);
+static kdu_core::kdu_message_formatter pretty_cout(&cout_message);
+static kdu_core::kdu_message_formatter pretty_cerr(&cerr_message);
+
+#endif /* #ifndef ossimKakaduMessaging_HEADER */
+
diff --git a/ossim_plugins/kakadu/ossimKakaduNitfOverviewBuilder.cpp b/ossim_plugins/kakadu/ossimKakaduNitfOverviewBuilder.cpp
new file mode 100644
index 0000000..426b422
--- /dev/null
+++ b/ossim_plugins/kakadu/ossimKakaduNitfOverviewBuilder.cpp
@@ -0,0 +1,798 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author:  David Burken
+//
+// Description:  OSSIM wrapper for building nitf, j2k compressed overviews
+// using kakadu from an ossim image source.
+//
+//----------------------------------------------------------------------------
+// $Id: ossimKakaduNitfOverviewBuilder.cpp 23664 2015-12-14 14:17:27Z dburken $
+
+#include "ossimKakaduNitfOverviewBuilder.h"
+#include "ossimKakaduCommon.h"
+#include "ossimKakaduCompressor.h"
+#include "ossimKakaduKeywords.h"
+
+#include <ossim/base/ossimDate.h>
+#include <ossim/base/ossimErrorCodes.h>
+#include <ossim/base/ossimException.h>
+#include <ossim/base/ossimFilename.h>
+#include <ossim/base/ossimKeywordlist.h>
+#include <ossim/base/ossimIpt.h>
+#include <ossim/base/ossimNotify.h>
+#include <ossim/base/ossimStdOutProgress.h>
+#include <ossim/base/ossimTrace.h>
+
+#include <ossim/imaging/ossimImageSource.h>
+#include <ossim/imaging/ossimImageHandler.h>
+#include <ossim/imaging/ossimImageSourceSequencer.h>
+
+#include <ossim/parallel/ossimMpi.h>
+#include <ossim/parallel/ossimMpiMasterOverviewSequencer.h>
+#include <ossim/parallel/ossimMpiSlaveOverviewSequencer.h>
+
+#include <ossim/support_data/ossimInfoBase.h>
+#include <ossim/support_data/ossimInfoFactoryRegistry.h>
+#include <ossim/support_data/ossimNitfCommon.h>
+#include <ossim/support_data/ossimNitfFileHeader.h>
+#include <ossim/support_data/ossimNitfFileHeaderV2_1.h>
+#include <ossim/support_data/ossimNitfImageHeader.h>
+#include <ossim/support_data/ossimNitfImageHeaderV2_1.h>
+#include <ossim/imaging/ossimBitMaskTileSource.h>
+
+#include <fstream>
+#include <sstream>
+
+static const ossimString OVERVIEW_TYPE = "ossim_kakadu_nitf_j2k";
+
+static const ossimIpt DEFAULT_TILE_SIZE(1024, 1024);
+
+RTTI_DEF1(ossimKakaduNitfOverviewBuilder,
+          "ossimKakaduNitfOverviewBuilder",
+          ossimOverviewBuilderBase);
+
+static const ossimTrace traceDebug(
+   ossimString("ossimKakaduNitfOverviewBuilder:debug"));
+
+#ifdef OSSIM_ID_ENABLED
+static const char OSSIM_ID[] = "$Id: ossimKakaduNitfOverviewBuilder.cpp 23664 2015-12-14 14:17:27Z dburken $";
+#endif
+
+ossimKakaduNitfOverviewBuilder::ossimKakaduNitfOverviewBuilder()
+   :
+   ossimOverviewBuilderBase(),
+   m_outputFile(ossimFilename::NIL),
+   m_outputFileTmp(ossimFilename::NIL),
+   m_compressor(new ossimKakaduCompressor())
+{
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimKakaduNitfOverviewBuilder::ossimKakaduNitfOverviewBuilder"
+         << " DEBUG:\n";
+#ifdef OSSIM_ID_ENABLED
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "OSSIM_ID:  "
+         << OSSIM_ID
+         << "\n";
+#endif
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "overview stop dimension: " << m_overviewStopDimension
+         << std::endl;
+   }
+}
+
+ossimKakaduNitfOverviewBuilder::~ossimKakaduNitfOverviewBuilder()
+{
+   m_imageHandler = 0;
+
+   if (m_compressor)
+   {
+      delete m_compressor;
+      m_compressor = 0;
+   }
+}
+
+void ossimKakaduNitfOverviewBuilder::setOutputFile(const ossimFilename& file)
+{
+   m_outputFile = file;
+}
+
+ossimFilename ossimKakaduNitfOverviewBuilder::getOutputFile() const
+{
+   ossimFilename result = m_outputFile;
+   if (m_outputFile == ossimFilename::NIL)
+   {
+      if ( m_imageHandler.valid() )
+      {
+         bool usePrefix = (m_imageHandler->getNumberOfEntries()>1?true:false);
+         result = m_imageHandler->
+            getFilenameWithThisExtension(ossimString("ovr"), usePrefix);
+      }
+   }
+   return result;
+}
+
+bool ossimKakaduNitfOverviewBuilder::setOverviewType(const ossimString& type)
+{
+   bool result = false;
+
+   if (type == OVERVIEW_TYPE) // Only have one type right now.
+   {
+      result = true;
+   }
+
+   return result;
+}
+
+ossimString ossimKakaduNitfOverviewBuilder::getOverviewType() const
+{
+   return OVERVIEW_TYPE;
+}
+
+void ossimKakaduNitfOverviewBuilder::getTypeNameList(
+   std::vector<ossimString>& typeList)const
+{
+   typeList.push_back(OVERVIEW_TYPE);
+}
+
+bool ossimKakaduNitfOverviewBuilder::execute()
+{
+   static const char MODULE[] = "ossimKakaduNitfOverviewBuilder::execute";
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " entered...\n";
+   }
+   
+   bool result = false;
+
+   if ( m_imageHandler.valid() ) // Make sure there is a source.
+   {
+      // Get the output filename.
+      ossimFilename outputFile = getOutputFile();
+
+      if (outputFile != m_imageHandler->getFilename())
+      {
+         //---
+         // Add .tmp in case process gets aborted to avoid leaving bad .ovr
+         // file.
+         //---
+         ossimFilename outputFileTemp = outputFile + ".tmp";
+         
+         // Required number of levels needed including r0.
+         ossim_uint32 requiedResLevels =
+            getRequiredResLevels(m_imageHandler.get());
+         
+         // Zero based starting resLevel.
+         ossim_uint32 startingResLevel =
+            m_imageHandler->getNumberOfDecimationLevels();
+         
+         if (traceDebug())
+         {
+            ossimNotify(ossimNotifyLevel_DEBUG)
+               << MODULE
+               << "\nCurrent number of reduced res sets: "
+               << m_imageHandler->getNumberOfDecimationLevels()
+               << "\nNumber of required reduced res sets:  "
+               << requiedResLevels
+               << "\nStarting reduced res set:    " << startingResLevel
+               << "\nHistogram mode: " << getHistogramMode()
+               << std::endl;
+         }
+
+         if ( startingResLevel < requiedResLevels )
+         {
+            //---
+            // If image handler is band selector, start with all bands.
+            // Some sources, e.g. ossimEnviTileSource can pick up default
+            // bands and filter out all other bands.
+            //---
+            m_imageHandler->setOutputToInputBandList();  
+            
+            // If alpha bit mask generation was requested, then need to instantiate the mask writer
+            // object.  This is simply a "transparent" tile source placed after to the right of the
+            // image handler that scans the pixels being pulled and accumulates alpha bit mask for
+            // writing at the end:
+            if (m_bitMaskSpec.getSize() > 0)
+            {
+               m_maskWriter = new ossimBitMaskWriter();
+               m_maskWriter->loadState(m_bitMaskSpec);
+               m_maskWriter->setStartingResLevel(1);
+               ossimRefPtr<ossimBitMaskTileSource> bmts = new ossimBitMaskTileSource;
+               bmts->setAssociatedMaskWriter(m_maskWriter.get());
+               m_maskFilter->connectMyInputTo(m_imageHandler.get());
+               m_maskFilter->setMaskSource((ossimImageSource*)bmts.get());
+            }
+
+            //---
+            // Set up the sequencer.  This will be one of three depending
+            // on if we're running mpi and if we are a master process or
+            // a slave process.
+            //---
+            ossimRefPtr<ossimOverviewSequencer> sequencer;
+            
+            if(ossimMpi::instance()->getNumberOfProcessors() > 1)
+            {
+               if ( ossimMpi::instance()->getRank() == 0 )
+               {
+                  sequencer = new ossimMpiMasterOverviewSequencer();
+               }
+               else
+               {
+                  sequencer = new ossimMpiSlaveOverviewSequencer();
+               }
+            }
+            else
+            {
+               sequencer = new ossimOverviewSequencer();
+            }
+
+            if( ossimMpi::instance()->getNumberOfProcessors() == 1)
+            {
+               //---
+               // Pass the histogram mode to the sequencer.
+               // Can't do with mpi/multi-process.
+               //---
+               sequencer->setHistogramMode( getHistogramMode() );
+
+               if ( getScanForMinMaxNull() == true )
+               {
+                  sequencer->setScanForMinMaxNull(true);
+               }
+               else if ( getScanForMinMax() == true )
+               {
+                  sequencer->setScanForMinMax(true);
+               }
+            }
+            
+            sequencer->setImageHandler( m_imageHandler.get() );
+            
+            ossim_uint32 sourceResLevel = 0;
+            if ( startingResLevel > 1)
+            {
+               sourceResLevel = startingResLevel - 1;
+            }
+         
+            if (traceDebug())
+            {
+               ossimNotify(ossimNotifyLevel_DEBUG)
+                  << MODULE
+                  << "\nSource starting reduced res set: " << sourceResLevel
+                  << std::endl;
+            }
+            
+            sequencer->setSourceLevel(sourceResLevel);
+
+            // Tmp hard coded to BOX:
+            sequencer->setResampleType(
+                  ossimFilterResampler::ossimFilterResampler_BOX);
+
+            sequencer->setTileSize( DEFAULT_TILE_SIZE );
+
+            sequencer->initialize();
+            
+            //---
+            // If we are a slave process start the resampling of tiles.
+            //---
+            if (ossimMpi::instance()->getRank() != 0 )
+            {
+               sequencer->slaveProcessTiles();
+               return true; // End of slave process.
+            }
+
+            ossim_uint32 outputTilesWide =
+               sequencer->getNumberOfTilesHorizontal();
+            ossim_uint32 outputTilesHigh =
+               sequencer->getNumberOfTilesVertical();
+            ossim_uint32 numberOfTiles =
+               sequencer->getNumberOfTiles();
+            ossim_uint32 tileNumber = 0;
+            ossimIrect imageRect;
+            sequencer->getOutputImageRectangle(imageRect);
+            
+            //---
+            // From here on out master process only.
+            //---
+            ossimNitfFileHeaderV2_1* fHdr = 0;
+            ossimNitfImageHeaderV2_1* iHdr = 0;
+            ossimStdOutProgress* progressListener = 0;
+            std::ofstream* os = 0;
+            std::streampos endOfFileHdrPos;
+            std::streampos endOfImgHdrPos;
+            std::streampos endOfFilePos;
+            ossimNitfImageInfoRecordV2_1 imageInfoRecord;
+            
+            // Open the output file.
+            os = new std::ofstream;
+            os->open(outputFileTemp.chars(), std::ios_base::out|std::ios_base::binary);
+            if ( os->good() )
+            {
+               result = true; // Assuming we are good from this point.
+               
+               // Get an info dump to a keyword list.
+               ossimKeywordlist kwl;
+               ossimRefPtr<ossimInfoBase> info =
+                  ossimInfoFactoryRegistry::instance()->
+                  create(m_imageHandler->getFilename());
+               if ( info.valid() )
+               {
+                  info->getKeywordlist(kwl);
+                  info = 0;
+               }
+               
+               fHdr = new ossimNitfFileHeaderV2_1();
+               
+               fHdr->addImageInfoRecord(imageInfoRecord);
+               
+               fHdr->setDate(ossimDate());
+               fHdr->setTitle(ossimString("ossim_nitf_j2k_overview"));
+               
+               const char* lookup = kwl.find("nitf.FSCLAS");
+               if (lookup)
+               {
+                  fHdr->setSecurityClassificationSys(ossimString(lookup));
+               }
+               fHdr->writeStream(*os);
+               endOfFileHdrPos = os->tellp();
+               
+               iHdr = new ossimNitfImageHeaderV2_1();
+
+               // Set the compression type:
+               iHdr->setCompression(ossimString("C8"));
+
+               // Set the Image Magnification (IMAG) field.
+               setImagField(iHdr, startingResLevel);
+
+               ossimScalarType scalarType = m_imageHandler->getOutputScalarType();
+
+               // Set the pixel type (PVTYPE field).
+               iHdr->setPixelType(
+                  ossimNitfCommon::getNitfPixelType(scalarType));
+
+               // Set the actual bits per pixel (ABPP field).
+               iHdr->setActualBitsPerPixel(
+                  ossim::getActualBitsPerPixel(scalarType));
+               iHdr->setBitsPerPixel(ossim::getBitsPerPixel(scalarType));
+               
+               const ossim_uint64 BANDS =
+                  m_imageHandler->getNumberOfOutputBands();
+
+               iHdr->setNumberOfBands(BANDS);
+               iHdr->setImageMode('B');// blocked
+               
+               if((BANDS == 3)&&
+                  (scalarType == OSSIM_UCHAR))
+               {
+                  iHdr->setRepresentation("RGB");
+                  iHdr->setCategory("VIS");
+               }
+               else if(BANDS == 1)
+               {
+                  iHdr->setRepresentation("MONO");
+                  iHdr->setCategory("MS");
+               }
+               else
+               {
+                  iHdr->setRepresentation("MULTI");
+                  iHdr->setCategory("MS");
+               }
+               
+               iHdr->setBlocksPerRow(outputTilesWide);
+               iHdr->setBlocksPerCol(outputTilesHigh);
+               iHdr->setNumberOfPixelsPerBlockRow(DEFAULT_TILE_SIZE.y);
+               iHdr->setNumberOfPixelsPerBlockCol(DEFAULT_TILE_SIZE.x);
+               iHdr->setNumberOfRows(imageRect.height());
+               iHdr->setNumberOfCols(imageRect.width());
+               
+               ossimNitfImageBandV2_1 bandInfo;
+               for(ossim_uint32 band = 0; band < BANDS; ++band)
+               {
+                  std::ostringstream out;
+                  
+                  out << std::setfill('0')
+                      << std::setw(2)
+                      << band;
+                  
+                  bandInfo.setBandRepresentation(out.str().c_str());
+                  iHdr->setBandInfo(band, bandInfo);
+               }
+               
+               iHdr->writeStream(*os);
+               endOfImgHdrPos = os->tellp();
+               
+               //---
+               // Check for a listeners.  If the list is empty, add a
+               // standard out listener so that command line apps like
+               // img2rr will get some progress.
+               //---
+               ossimStdOutProgress* progressListener = 0;
+               if (theListenerList.empty())
+               {
+                  progressListener = new ossimStdOutProgress(0, true);
+                  addListener(progressListener);
+               }
+               setProcessStatus(
+                  ossimProcessInterface::PROCESS_STATUS_EXECUTING);
+               setPercentComplete(0.0);
+               
+               if (traceDebug())
+               {
+                  ossimNotify(ossimNotifyLevel_DEBUG)
+                     << MODULE << " DEBUG:"
+                     << "\noutputTilesWide:  " << outputTilesWide
+                     << "\noutputTilesHigh:  " << outputTilesHigh
+                     << "\nnumberOfTiles:    " << numberOfTiles
+                     << "\nimageRect: " << imageRect
+                     << std::endl;
+               }
+
+               if (m_compressor->getAlphaChannelFlag())
+               {
+                  //--- 
+                  // Someone can set this through the generic setProperty
+                  // interface. Unset, currently only supported in jp2 writer.
+                  // Could be used here but I think we would have to update the
+                  // nitf tags.
+                  //---
+                  m_compressor->setAlphaChannelFlag(false);
+               }
+
+               if ( ossim::getActualBitsPerPixel(scalarType) > 31 )
+               {
+                  m_compressor->setQualityType(ossimKakaduCompressor::OKP_VISUALLY_LOSSLESS);
+               }
+
+               try
+               {
+                  // Make a compressor
+                  m_compressor->create(os,
+                                       scalarType,
+                                       BANDS,
+                                       imageRect,
+                                       DEFAULT_TILE_SIZE,
+                                       numberOfTiles,
+                                       false);
+                  
+                  ossimNotify(ossimNotifyLevel_INFO)
+                     << "Generating " << (m_compressor->getLevels()+1)
+                     << " levels..." << endl;
+               }
+               catch (const ossimException& e)
+               {
+                  setErrorStatus();
+                  ossimNotify(ossimNotifyLevel_WARN) << e.what() << std::endl;
+                  result = false;
+               }
+
+               if ( result )
+               {
+                  // Tile loop in the line direction.
+                  for(ossim_uint32 y = 0; y < outputTilesHigh; ++y)
+                  {
+                     // Tile loop in the sample (width) direction.
+                     for(ossim_uint32 x = 0; x < outputTilesWide; ++x)
+                     {
+                        // Grab the resampled tile.
+                        ossimRefPtr<ossimImageData> t = sequencer->getNextTile();
+
+                        // Check for errors reading tile:
+                        if ( sequencer->hasError() )
+                        {
+                           setErrorStatus();
+                           ossimNotify(ossimNotifyLevel_WARN)
+                              << MODULE << " ERROR: reading tile:  "
+                              << tileNumber << std::endl;
+                           result = false;
+                        }
+
+                        if ( result && t.valid() )
+                        {
+                           //---
+                           // If masking was enabled, pass the tile onto that object for
+                           // processing:
+                           //---
+                           if ( m_maskWriter.valid())
+                           {
+                              m_maskWriter->generateMask(t, 0);
+                           }
+                           
+                           if ( t->getDataObjectStatus() != OSSIM_NULL )
+                           {
+                              if ( ! m_compressor->writeTile( *(t.get()) ) )
+                              {
+                                 setErrorStatus();
+                                 ossimNotify(ossimNotifyLevel_WARN)
+                                    << MODULE << " ERROR:\nWriting tile:  "
+                                    << tileNumber << std::endl;
+                                 result = false;
+                              }
+                           }
+                           else
+                           {
+                              setErrorStatus();
+                              ossimNotify(ossimNotifyLevel_WARN)
+                                 << MODULE << " ERROR:\nNull tile returned:  " << tileNumber
+                                 << std::endl;
+                              result = false;
+                           }
+                        }
+                        
+                        if ( !result )
+                        {
+                           // Bust out of sample loop.
+                           break;
+                        }
+                        
+                        // Increment tile number for percent complete.
+                        ++tileNumber;
+                        
+                     } // End of tile loop in the sample (width) direction.
+
+                     if ( !result )
+                     {
+                        // Bust out of line loop.
+                        break;
+                     }
+                     
+                     if ( needsAborting() )
+                     {
+                        setPercentComplete(100.0);
+                        break;
+                     }
+                     else
+                     {
+                        double tile = tileNumber;
+                        double numTiles = numberOfTiles;
+                        setPercentComplete(tile / numTiles * 100.0);
+                     }
+                     
+                  } // End of tile loop in the line (height) direction.
+
+                  if ( result )
+                  {
+                     m_compressor->finish();
+                     
+                     // Get the file length.
+                     endOfFilePos = os->tellp();
+                     
+                     //---
+                     // Seek back to set some things that were not know until now and
+                     // rewrite the nitf file and image header.
+                     //---
+                     os->seekp(0, std::ios_base::beg);
+                     
+                     // Set the file length.
+                     std::streamoff length = endOfFilePos;
+                     fHdr->setFileLength(static_cast<ossim_uint64>(length));
+                     
+                     // Set the file header length.
+                     length = endOfFileHdrPos;
+                     fHdr->setHeaderLength(static_cast<ossim_uint64>(length));            
+                     // Set the image sub header length.
+                     length = endOfImgHdrPos - endOfFileHdrPos;
+                     
+                     imageInfoRecord.setSubheaderLength(
+                        static_cast<ossim_uint64>(length));
+                     
+                     // Set the image length.
+                     length = endOfFilePos - endOfImgHdrPos;
+                     imageInfoRecord.setImageLength(
+                        static_cast<ossim_uint64>(length));
+                     
+                     fHdr->replaceImageInfoRecord(0, imageInfoRecord);
+                     
+                     // Rewrite the header.
+                     fHdr->writeStream(*os);
+                     
+                     // Set the compression rate now that the image size is known.
+                     ossimString comrat = ossimNitfCommon::getCompressionRate(
+                        imageRect,
+                        BANDS,
+                        scalarType,
+                        static_cast<ossim_uint64>(length));
+                     iHdr->setCompressionRateCode(comrat);
+                     
+                     // Rewrite the image header.
+                     iHdr->writeStream(*os);
+                     
+                     if (progressListener)
+                     {
+                        removeListener(progressListener);
+                        delete progressListener;
+                        progressListener = 0;
+                     }
+                     
+                     if ( ossimMpi::instance()->getNumberOfProcessors() == 1 )
+                     {
+                        if ( getHistogramMode() != OSSIM_HISTO_MODE_UNKNOWN )
+                        {
+                           // Write the histogram.
+                           ossimFilename histoFilename = getOutputFile();
+                           histoFilename.setExtension("his");
+                           sequencer->writeHistogram(histoFilename);
+                        }
+                        
+                        if ( ( getScanForMinMaxNull() == true ) || ( getScanForMinMax() == true ) )
+                        {
+                           // Write the omd file:
+                           ossimFilename file = m_outputFile;
+                           file = file.setExtension("omd");
+                           sequencer->writeOmdFile(file);
+                        }
+                     }
+                     
+                     // If masking was enabled, then only R0 was processed, need to process
+                     // remaining levels:
+                     if (m_maskWriter.valid())
+                     {
+                        ossim_uint32 num_rlevels = m_compressor->getLevels() + 1;
+                        m_maskWriter->buildOverviews(num_rlevels);
+                        m_maskFilter->disconnectMyInput(0);
+                        m_maskWriter->disconnectAllInputs();
+                        ossimNotify(ossimNotifyLevel_INFO)
+                           << MODULE << "Writing alpha bit mask file..." << std::endl;
+                        m_maskWriter->close();
+                     }
+                     
+                  } // if ( result ) *** after end of tile loop ***
+
+               } // End: if ( result ) from m_compressor->create
+
+            } // End: if (os->good())
+            
+            if (fHdr)
+            {
+               delete fHdr;
+               fHdr = 0;
+            }
+            
+            if (iHdr)
+            {
+               delete iHdr;
+               iHdr = 0;
+            }
+
+            if (progressListener)
+            {
+               delete progressListener;
+               progressListener = 0;
+            }
+            
+            if (os->is_open())
+            {
+               os->close();
+               if ( result )
+               {
+                  outputFileTemp.rename(outputFile);
+               }
+               else
+               {
+                  ossimFilename::remove( outputFileTemp );
+               }
+            }
+            delete os;
+            os = 0;
+
+         }
+         else
+         {
+            ossimNotify(ossimNotifyLevel_INFO)<< MODULE << " NOTICE:"
+               <<"  Image has required reduced resolution data sets.\n"<< std::endl;
+         }
+      }
+      else
+      {
+         ossimNotify(ossimNotifyLevel_WARN)
+            << "Source image file and overview file cannot be the same!"
+            << std::endl;
+      }
+      
+   } // matches: if (m_imageHandler)
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " exit status = " << (result?"true":"false\n")
+         << std::endl;
+   }
+
+   finalize();  // Reset band list if a band selector.
+
+   return result;
+
+} // End: ossimKakaduNitfOverviewBuilder::execute()
+
+void ossimKakaduNitfOverviewBuilder::setProperty(
+   ossimRefPtr<ossimProperty> property)
+{
+   if ( property.valid() )
+   {
+      m_compressor->setProperty(property);
+   }
+}
+
+void ossimKakaduNitfOverviewBuilder::getPropertyNames(
+   std::vector<ossimString>& propertyNames)const
+{
+   m_compressor->getPropertyNames(propertyNames);
+}
+
+std::ostream& ossimKakaduNitfOverviewBuilder::print(std::ostream& out) const
+{
+   out << "ossimKakaduNitfOverviewBuilder::print"
+       << std::endl;
+   return out;
+}
+
+ossimObject* ossimKakaduNitfOverviewBuilder::getObject()
+{
+   return this;
+}
+
+const ossimObject* ossimKakaduNitfOverviewBuilder::getObject() const
+{
+   return this;
+}
+
+bool ossimKakaduNitfOverviewBuilder::canConnectMyInputTo(
+   ossim_int32 index,
+   const ossimConnectableObject* obj) const
+{
+   if ( (index == 0) &&
+        PTR_CAST(ossimImageHandler, obj) )
+   {
+      return true;
+   }
+
+   return false;
+}
+
+void ossimKakaduNitfOverviewBuilder::setImagField(
+   ossimNitfImageHeaderV2_1* hdr, ossim_uint32 startingResLevel) const
+{
+   //---
+   // This assumes res level 0 is 1.0 magnification.
+   //---
+   if (hdr)
+   {
+      ossimString imagString;
+      
+      if (startingResLevel == 0)
+      {
+         imagString = "1.0  ";
+      }
+      else
+      {
+         //---
+         // Assumes power of 2 decimation.
+         //---
+         ossim_uint32 decimation = 1<<startingResLevel;
+                     
+         //---
+         // Using slash '/' format.  "/2" = 1/2, /  
+         imagString = "/";
+         imagString += ossimString::toString(decimation);
+         if (imagString.size() <= 4)
+         {
+            if (imagString.size() == 2)
+            {
+               imagString += "  "; // two spaces
+            }
+            else if (imagString.size() == 3)
+            {
+               imagString += " "; // one space
+            }
+         }
+      }
+      if (imagString.size())
+      {
+         hdr->setImageMagnification(imagString);
+      }
+   }
+}
+
diff --git a/ossim_plugins/kakadu/ossimKakaduNitfOverviewBuilder.h b/ossim_plugins/kakadu/ossimKakaduNitfOverviewBuilder.h
new file mode 100644
index 0000000..a838d64
--- /dev/null
+++ b/ossim_plugins/kakadu/ossimKakaduNitfOverviewBuilder.h
@@ -0,0 +1,157 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Description:  OSSIM wrapper for building nitf, j2k compressed overviews
+// using kakadu from an ossim image source.
+//
+//----------------------------------------------------------------------------
+// $Id: ossimKakaduNitfOverviewBuilder.h 23664 2015-12-14 14:17:27Z dburken $
+
+#ifndef ossimKakaduNitfOverviewBuilder_HEADER
+#define ossimKakaduNitfOverviewBuilder_HEADER 1
+
+#include "../ossimPluginConstants.h"
+#include <ossim/base/ossimConstants.h>
+#include <ossim/base/ossimFilename.h>
+#include <ossim/base/ossimRefPtr.h>
+#include <ossim/base/ossimProperty.h>
+#include <ossim/imaging/ossimOverviewBuilderBase.h>
+#include <vector>
+
+class ossimImageHandler;
+class ossimKakaduCompressor;
+class ossimNitfImageHeaderV2_1;
+
+/**
+ * @brief ossimKakaduNitfOverviewBuilder Class to build overviews from the
+ * Kakadu library.
+ */
+class OSSIM_PLUGINS_DLL ossimKakaduNitfOverviewBuilder
+   :
+   public ossimOverviewBuilderBase
+{
+public:
+
+   /** @brief default constructor */
+   ossimKakaduNitfOverviewBuilder();
+
+   /** @brief virtual destructor */
+   virtual ~ossimKakaduNitfOverviewBuilder();
+
+   /**
+    * @brief Builds the overviews.
+    *
+    * @return true on success, false on error.
+    *
+    * @note If setOutputFile was not called the output name will be derived
+    * from the image name.  If image was "foo.tif" the overview file will
+    * be "foo.rrd" or "foo.ovr".
+    */
+   virtual bool execute();
+   
+   /**
+    * @brief Sets the output filename.
+    * Satisfies pure virtual from ossimOverviewBuilderInterface.
+    * @param file The output file name.
+    */
+   virtual void  setOutputFile(const ossimFilename& file);
+
+   /**
+    * Returns the output.  This will be derived from the input file if not
+    * explicitly set.
+    * 
+    * @return The output filename.
+    */
+   virtual ossimFilename getOutputFile() const;
+
+   /**
+    * @brief Sets the overview output type.
+    *
+    * Satisfies pure virtual from ossimOverviewBuilderInterface.
+    * 
+    * Currently handled types are:
+    * "ossim_tiff_nearest" and "ossim_tiff_box"
+    *
+    * @param type This should be the string representing the type.  This method
+    * will do nothing if type is not handled and return false.
+    *
+    * @return true if type is handled, false if not.
+    */
+   virtual bool setOverviewType(const ossimString& type);
+
+   /**
+    * @brief Gets the overview type.
+    * Satisfies pure virtual from ossimOverviewBuilderInterface.
+    * @return The overview output type as a string.
+    */
+   virtual ossimString getOverviewType() const;
+
+   /**
+    * @brief Method to populate class supported types.
+    * Satisfies pure virtual from ossimOverviewBuilderInterface.
+    * @param typeList List of ossimStrings to add to.
+    */
+   virtual void getTypeNameList(std::vector<ossimString>& typeList)const;
+
+   /**
+    * @return ossimObject* to this object. Satisfies pure virtual.
+    */
+   virtual ossimObject* getObject();
+
+   /**
+    * @return const ossimObject* to this object.  Satisfies pure virtual.
+    */
+   virtual const ossimObject* getObject() const;
+
+   /**
+    * @return true if input is an image handler.  Satisfies pure virtual.
+    */
+   virtual bool canConnectMyInputTo(ossim_int32 index,
+                                    const ossimConnectableObject* obj) const;
+
+   /**
+    * @biref Method to set properties.
+    *
+    * @param property Property to set.
+    *
+    * @note Currently supported property:
+    */
+   virtual void setProperty(ossimRefPtr<ossimProperty> property);
+
+   /**
+    * @brief Method to populate the list of property names.
+    *
+    * @param propertyNames List to populate.  This does not clear the list
+    * just adds to it.
+    */
+   virtual void getPropertyNames(std::vector<ossimString>& propertyNames)const;
+   
+   /**
+    * @brief print method.
+    * @return std::ostream&
+    */
+   virtual std::ostream& print(std::ostream& out) const;
+
+private:
+
+   /**
+    * Set the Image Magnification (IMAG) field in the form of "/2  ".
+    * @param hdr The nitf image header.
+    * @param starting resolution level.
+    */
+   void setImagField(ossimNitfImageHeaderV2_1* hdr,
+                     ossim_uint32 startingResLevel) const;
+
+   ossimFilename                  m_outputFile;
+   ossimFilename                  m_outputFileTmp;
+   ossimKakaduCompressor*         m_compressor;
+
+   /** for rtti stuff */
+   TYPE_DATA
+};
+
+#endif /* End if "#ifndef ossimKakaduNitfOverviewBuilder_HEADER" */
+
diff --git a/ossim_plugins/kakadu/ossimKakaduNitfReader.cpp b/ossim_plugins/kakadu/ossimKakaduNitfReader.cpp
new file mode 100644
index 0000000..de96c58
--- /dev/null
+++ b/ossim_plugins/kakadu/ossimKakaduNitfReader.cpp
@@ -0,0 +1,1124 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author:  David Burken
+//
+// Description:
+//
+// Class definition for reader of NITF images with JPEG2000 (J2K) compressed
+// blocks using kakadu library for decompression.  The image data segment
+// can be raw J2K or have a JP2 wrapper.
+//
+//----------------------------------------------------------------------------
+// $Id: ossimKakaduNitfReader.cpp 23664 2015-12-14 14:17:27Z dburken $
+
+#include "ossimKakaduNitfReader.h"
+#include "ossimKakaduCommon.h"
+#include "ossimKakaduMessaging.h"
+ 
+#include <ossim/base/ossimCommon.h>
+#include <ossim/base/ossimException.h>
+#include <ossim/base/ossimNotify.h>
+#include <ossim/base/ossimPreferences.h>
+#include <ossim/base/ossimScalarTypeLut.h>
+#include <ossim/base/ossimTrace.h>
+ 
+#include <ossim/imaging/ossimTiffTileSource.h>
+#include <ossim/imaging/ossimImageDataFactory.h>
+ 
+#include <ossim/support_data/ossimNitfImageHeader.h>
+#include <ossim/support_data/ossimJ2kSizRecord.h>
+#include <ossim/support_data/ossimJ2kSotRecord.h>
+
+#include <jp2.h>
+#include <kdu_sample_processing.h>
+#include <kdu_region_decompressor.h>
+ 
+#include <iostream>
+
+using namespace kdu_core;
+using namespace kdu_supp;
+
+#ifdef OSSIM_ID_ENABLED
+static const char OSSIM_ID[] = "$Id";
+#endif
+ 
+static const ossimTrace traceDebug( ossimString("ossimKakaduNitfReader:debug") );
+static const ossimTrace traceDump( ossimString("ossimKakaduNitfReader:dump") );
+ 
+RTTI_DEF1_INST(ossimKakaduNitfReader,
+               "ossimKakaduNitfReader",
+               ossimNitfTileSource)
+
+ossimKakaduNitfReader::ossimKakaduNitfReader()
+   : ossimNitfTileSource(),
+     m_startOfCodestreamOffset(0),
+     m_jp2FamilySrc(0),
+     m_jp2Source(0),
+     m_channels(0),
+     m_codestream(),
+     m_threadEnv(0),
+     m_openTileThreadQueue(0),
+     m_sourcePrecisionBits(0),
+     m_minDwtLevels(0),
+     m_imageDims(0),
+     m_minSampleValue(ossim::nan()),
+     m_maxSampleValue(ossim::nan()),
+     m_nullSampleValue(ossim::nan())
+{
+   kdu_customize_warnings(&pretty_cout); // Deliver warnings to stdout.
+   kdu_customize_errors(&pretty_cerr); // Deliver errors to stderr + throw exc
+}
+
+ossimKakaduNitfReader::~ossimKakaduNitfReader()
+{
+   // Kakadu kdu_thread_entity::terminate throws exceptions...
+   try
+   {
+      // Cleanup processing environment
+      if ( m_threadEnv )
+      {
+         m_threadEnv->terminate(m_openTileThreadQueue, true);
+
+         // Terminates background codestream processing.
+         m_threadEnv->cs_terminate(m_codestream);
+
+         m_threadEnv->destroy();
+         delete m_threadEnv;
+         m_threadEnv = 0; 
+      }
+   
+      if ( m_codestream.exists() )
+      {
+         m_codestream.destroy();
+      }
+      
+      if ( m_openTileThreadQueue )
+      {
+         m_openTileThreadQueue = 0;
+      }
+      if ( m_jp2Source )
+      {
+         delete m_jp2Source;
+         m_jp2Source = 0;
+      }
+      if ( m_jp2FamilySrc )
+      {
+         delete m_jp2FamilySrc;
+         m_jp2FamilySrc = 0;
+      }
+      if ( m_channels )
+      {
+         m_channels->clear();
+         delete m_channels;
+         m_channels = 0;
+      }
+   }
+   catch ( kdu_core::kdu_exception exc )
+   {
+      // kdu_exception is an int typedef.
+      if ( m_threadEnv != 0 )
+      {
+         m_threadEnv->handle_exception(exc);
+      }
+      ostringstream e;
+      e << "ossimKakaduNitfReader::~ossimKakaduNitfReader\n"
+        << "Caught exception from kdu_region_decompressor: " << exc << "\n";
+      ossimNotify(ossimNotifyLevel_WARN) << e.str() << std::endl;
+   }
+   catch ( std::bad_alloc& )
+   {
+      if ( m_threadEnv != 0 )
+      {
+         m_threadEnv->handle_exception(KDU_MEMORY_EXCEPTION);
+      }
+      std::string e =
+         "Caught exception from kdu_region_decompressor: std::bad_alloc";
+      ossimNotify(ossimNotifyLevel_WARN) << e << std::endl;
+   }
+   catch( ... )
+   {
+      std::string e =
+         "Caught unhandled exception from kdu_region_decompressor";
+      ossimNotify(ossimNotifyLevel_WARN) << e << std::endl;
+   }
+   
+   ossimNitfTileSource::close();
+}
+
+ossimString ossimKakaduNitfReader::getShortName()const
+{
+   return ossimString("ossim_kakadu_nitf_reader");
+}
+
+ossimString ossimKakaduNitfReader::getLongName()const
+{
+   return ossimString("ossim kakadu nitf reader");
+}
+
+ossim_uint32 ossimKakaduNitfReader::getNumberOfDecimationLevels()const
+{
+   ossim_uint32 result = 1; // Add r0
+   if ( isEntryJ2k() )
+   {
+      if (m_minDwtLevels)
+      {
+         //---
+         // Add internal overviews.
+         //---
+         result += m_minDwtLevels;
+      }
+
+      if (theOverview.valid())
+      {
+         result += theOverview->getNumberOfDecimationLevels();
+      }
+   }
+   else
+   {
+      result = ossimNitfTileSource::getNumberOfDecimationLevels();
+   }
+   return result;
+}
+
+ossim_uint32 ossimKakaduNitfReader::getNumberOfLines(
+   ossim_uint32 resLevel) const
+{
+   ossim_uint32 result = 0;
+   if ( isEntryJ2k() )
+   {
+      if ( isValidRLevel(resLevel) )
+      {
+         ossim_uint32 level = resLevel;
+         
+         if (theStartingResLevel) // This is an overview.
+         {
+            //---
+            // Adjust the level to be relative to the reader using this as
+            // overview.
+            //---
+            level = resLevel - theStartingResLevel;
+         }
+         
+         if (level <= m_minDwtLevels)
+         {
+            result = m_imageDims[level].height();
+         }
+         else if ( theOverview.valid() )
+         {
+            // Note the non-adjusted resLevel is passed to this by design.
+            result = theOverview->getNumberOfLines(resLevel);
+         }
+      }
+   }
+   else // Not our entry.
+   {
+      result = ossimNitfTileSource::getNumberOfLines(resLevel);
+   }
+   return result;
+}
+
+ossim_uint32 ossimKakaduNitfReader::getNumberOfSamples(
+   ossim_uint32 resLevel) const
+{
+   ossim_uint32 result = 0;
+   if ( isEntryJ2k() )
+   {
+      if ( isValidRLevel(resLevel) )
+      {
+         ossim_uint32 level = resLevel;
+         
+         if (theStartingResLevel) // This is an overview.
+         {
+            //---
+            // Adjust the level to be relative to the reader using this as
+            // overview.
+            //---
+            level = resLevel - theStartingResLevel;
+         }
+
+         if (level <= m_minDwtLevels)
+         {
+            result = m_imageDims[level].width();
+         }
+         else if ( theOverview.valid() )
+         {
+            // Note the non-adjusted resLevel is passed to this by design.
+            result = theOverview->getNumberOfSamples(resLevel);
+         }
+      }
+   }
+   else // Not our entry.
+   {
+      result = ossimNitfTileSource::getNumberOfSamples(resLevel);
+   }
+   return result;
+}
+
+void ossimKakaduNitfReader::setMinPixelValue(ossim_uint32 band,
+                                             const ossim_float64& pix)
+{
+   //---
+   // Store and call base ossimImageHandler::setMinPixelValue in case someone
+   // does a save state on the ossimImageHandler::theMetaData.
+   //---
+   m_minSampleValue = pix;
+   ossimImageHandler::setMinPixelValue(band, pix);
+   if ( theTile.valid() )
+   {
+      theTile->setMinPix(pix, band);
+   }
+   if ( theCacheTile.valid() )
+   {
+      theCacheTile->setMinPix(pix, band);
+   }
+}
+
+void ossimKakaduNitfReader::setMaxPixelValue(ossim_uint32 band,
+                                             const ossim_float64& pix)
+{
+   //---
+   // Store and call base ossimImageHandler::setMaxPixelValue in case someone
+   // does a save state on the ossimImageHandler::theMetaData.
+   //---
+   m_maxSampleValue  = pix;
+   ossimImageHandler::setMaxPixelValue(band, pix);
+   if ( theTile.valid() )
+   {
+      theTile->setMaxPix(pix, band);
+   }
+   if ( theCacheTile.valid() )
+   {
+      theCacheTile->setMaxPix(pix, band);
+   }   
+}
+
+void ossimKakaduNitfReader::setNullPixelValue(ossim_uint32 band,
+                                              const ossim_float64& pix)
+{
+   //---
+   // NOTES:
+   //
+   // 1) If the null pixel value has changed a makeBlank must be performed or the validate
+   // method will not work correctly.
+   // 
+   // 2) Must set the tile status to unknown prior to the makeBlank or it won't
+   // do anything.
+   //
+   // 3) It would be nice to do this after all the calls to setNullPixelValue are finished
+   // with a dirty flag or something.  In reality though the makeBlank will only be called
+   // once as this only happens(usually) with elevation data which is one band.
+   //---
+   
+   //---
+   // Store and call base ossimImageHandler::setNullPixelValue in case someone
+   // does a save state on the ossimImageHandler::theMetaData.
+   //---
+   m_nullSampleValue = pix;
+   ossimImageHandler::setNullPixelValue(band, pix);
+   if ( theTile.valid() )
+   {
+      if ( theTile->getNullPix(band) != pix )
+      {
+         theTile->setNullPix(pix, band);
+         theTile->setDataObjectStatus(OSSIM_STATUS_UNKNOWN);
+         theTile->makeBlank();
+      }
+   }
+   if ( theCacheTile.valid() )
+   {
+      if ( theCacheTile->getNullPix(band) != pix )
+      {
+         theCacheTile->setNullPix(pix, band);
+         theCacheTile->setDataObjectStatus(OSSIM_STATUS_UNKNOWN);
+         theCacheTile->makeBlank();
+      }
+   }   
+}
+
+ossim_float64 ossimKakaduNitfReader::getMinPixelValue(ossim_uint32 band)const
+{
+   if ( ossim::isnan(m_minSampleValue) )
+   {
+      return ossimImageHandler::getMinPixelValue(band);
+   }
+   return m_minSampleValue;
+}
+
+ossim_float64 ossimKakaduNitfReader::getMaxPixelValue(ossim_uint32 band)const
+{
+   if ( ossim::isnan(m_maxSampleValue) )
+   {
+      return ossimImageHandler::getMaxPixelValue(band);
+   }
+   return m_maxSampleValue;
+}
+
+ossim_float64 ossimKakaduNitfReader::getNullPixelValue(ossim_uint32 band)const
+{
+   if ( ossim::isnan(m_nullSampleValue) )
+   {
+      return ossimImageHandler::getNullPixelValue(band);
+   }
+   return m_nullSampleValue;
+}
+
+bool ossimKakaduNitfReader::getOverviewTile(ossim_uint32 resLevel,
+                                            ossimImageData* result)
+{
+   bool status = false;
+
+   // static bool traced = false;
+   
+   // Must be j2k entry, not past number of levels, bands must match.
+   if ( isEntryJ2k() )
+   {
+      if ( isValidRLevel(resLevel) && result &&
+           (result->getNumberOfBands() == getNumberOfOutputBands()) )
+      {
+         ossim_uint32 level = resLevel - theStartingResLevel;
+
+#if 0 /* please leave for debug */
+         cout << "ovr get tile res level: " << resLevel
+              << " start level: " << theStartingResLevel
+              << "\nlevel: " << level
+              << "\nrect3: " << result->getImageRectangle() << endl;
+#endif
+
+         if (level <= m_minDwtLevels)
+         {
+            // Internal overviews...
+            try
+            {
+               if ( m_channels )
+               {
+                  status = ossim::copyRegionToTile(m_channels,
+                                                   m_codestream,
+                                                   static_cast<int>(level),
+                                                   m_threadEnv,
+                                                   m_openTileThreadQueue,
+                                                   result);
+               }
+               else
+               {
+                  status = ossim::copyRegionToTile(m_codestream,
+                                                   static_cast<int>(level),
+                                                   m_threadEnv,
+                                                   m_openTileThreadQueue,
+                                                   result);
+               }
+            }
+            catch(const ossimException& e)
+            {
+               ossimNotify(ossimNotifyLevel_WARN)
+                  << __FILE__ << ":" << __LINE__ << " caught exception\n"
+                  << e.what() << std::endl;
+               status = false;
+            }
+
+         } // matches:  if (resLevel <= m_minDwtLevels)
+         else if ( theOverview.valid() )
+         {
+            //---
+            // Note: Passing non-adjusted "resLevel" to get tile by design.
+            //---
+            status = theOverview->getTile(result, resLevel);
+         }
+      }
+      else // Failed range check.
+      {
+         ossimNotify(ossimNotifyLevel_WARN)
+            << __FILE__ << " " << __LINE__
+            << "Range error." << std::endl;
+         status = false;
+      }
+         
+   } // matches:  if ( isEntryJ2k() )
+   else
+   {
+      // Not our entry, call the base.
+      status = ossimNitfTileSource::getOverviewTile(resLevel, result);
+   }
+
+   return status;
+   
+} // End:  bool ossimKakaduNitfReader::getOverviewTile( ... ) 
+
+bool ossimKakaduNitfReader::loadBlock(ossim_uint32 x, ossim_uint32 y)
+{
+   
+   bool result = true;
+
+   if ( isEntryJ2k() )
+   {
+      ossimIpt ul(x, y);
+      
+      ossimIpt lr(ul.x + theCacheSize.x - 1,
+                  ul.y + theCacheSize.y - 1);
+      
+      // Set the cache rectangle to be an even j2k tile.
+      theCacheTile->setImageRectangle(ossimIrect(ul, lr));
+      
+      // Let the getOverviewTile do the rest of the work.
+      if ( getOverviewTile(0, theCacheTile.get()) )
+      {
+         // Add it to the cache for the next time.
+         ossimAppFixedTileCache::instance()->addTile(theCacheId, theCacheTile);
+      }
+      else
+      {
+         ossimNotify(ossimNotifyLevel_WARN)
+            << __FILE__ << ":" << __LINE__
+            << "\nossimKakaduNitfReader::loadBlock failed!"
+            << std::endl;
+         result = false;
+      }
+   }
+   else
+   {
+      result = ossimNitfTileSource::loadBlock(x, y);
+   }
+   
+   return result;
+}
+
+bool ossimKakaduNitfReader::parseFile()
+{
+   static const char MODULE[] = "ossimKakaduNitfReader::parseFile";
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " entered...\n";
+   }
+
+   bool result = ossimNitfTileSource::parseFile();
+
+   if (result)
+   {
+      //---
+      // Look through the entries to see if any are j2k; if not, set result to
+      // false so the ossimNitfTileSource will pick this file up instead of
+      // ossimKakaduNitfReader.
+      //---
+
+      result = false; // Must prove we have a j2k entry.
+      
+      for (ossim_uint32 i = 0; i < theNumberOfImages; ++i)
+      {
+         if (theNitfImageHeader[i]->getCompressionCode() == "C8") // j2k
+         {
+            result = true;
+            break;
+         }
+      }
+   }
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " exit status = " << (result?"true\n":"false\n");
+   }
+
+   return result;
+}
+
+bool ossimKakaduNitfReader::allocate()
+{
+   static const char MODULE[] = "ossimKakaduNitfReader::allocate";
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " entered...\n";
+   }
+
+   bool result = ossimNitfTileSource::allocate();
+
+   if ( isEntryJ2k() && result )
+   {
+      // This only finds "Start Of Codestream" (SOC) so it's fast.
+      result = scanForJpegBlockOffsets();
+      
+      if ( result )
+      {
+         // Kakadu throws exceptions so wrap in try block.
+         try
+         {
+            // Position to start of code stream prior to create call.
+            theFileStr.seekg(m_startOfCodestreamOffset, ios_base::beg);
+            
+            //---
+            // Initialize the codestream.  The class ossimKakaduNitfReader is a
+            // kdu_compressed source so we feed ourself to the codestream.
+            //---
+            
+            // Construct multi-threaded processing environment if required.
+            if ( m_threadEnv )
+            {
+               m_threadEnv->terminate(NULL, true);
+               m_threadEnv->cs_terminate(m_codestream);
+               m_threadEnv->destroy();
+            }
+            
+            if( m_codestream.exists() )
+            {
+               m_codestream.destroy();
+            }
+            
+            if ( !m_threadEnv )
+            {
+               m_threadEnv = new kdu_thread_env();
+            }
+            
+            m_threadEnv->create(); // Creates the single "owner" thread
+            
+            // Check for threads in prefs file.
+            ossim_uint32 threads = 1;
+            const char* lookup = ossimPreferences::instance()->findPreference("kakadu_threads");
+            if ( lookup )
+            {
+               threads = ossimString::toUInt32(lookup);
+               if ( threads > 1 )
+               {
+                  for (ossim_uint32 nt=1; nt < threads; ++nt)
+                  {
+                     if ( !m_threadEnv->add_thread() )
+                     {
+                        if (traceDebug())
+                        {
+                           ossimNotify(ossimNotifyLevel_WARN) << "Unable to create thread!\n";
+                        }
+                     }
+                  }
+               }
+            }
+            
+            m_openTileThreadQueue = m_threadEnv->add_queue(NULL,NULL,"open_tile_q");
+            
+            if ( checkJp2Signature() )
+            {
+               // Note we must be at the JP2 signature block at this point for the open call.
+               m_jp2FamilySrc = new jp2_family_src();
+               m_jp2FamilySrc->open(this);
+               
+               if (m_jp2FamilySrc->exists())
+               {
+                  m_jp2Source = new kdu_supp::jp2_source();
+                  
+                  m_jp2Source->open(m_jp2FamilySrc);
+                  m_jp2Source->read_header();
+
+                  if (traceDebug())
+                  {
+                     jp2_colour colour = m_jp2Source->access_colour();
+                     if ( colour.exists() )
+                     {
+                        ossimNotify(ossimNotifyLevel_DEBUG)
+                           << "jp2 color space: " << colour.get_space() << endl;
+                     }
+                  }
+               }
+               m_codestream.create(m_jp2Source, m_threadEnv);
+            }
+            else
+            {
+               m_codestream.create(this, m_threadEnv);
+            }
+
+            if ( m_codestream.exists() )
+            {
+               //---
+               // We have to store things here in this non-const method because
+               // NONE of the kakadu methods are const.
+               //---
+               m_minDwtLevels = m_codestream.get_min_dwt_levels();
+
+               //---
+               // NOTE:  ossimNitfTileSource::allocate() calls open overview
+               // before the number of levels is known.
+               // Set the starting res level for the overview now that the levels
+               // are known.
+               //--- 
+               if ( theOverview.valid() )
+               {
+                  theOverview->setStartingResLevel(m_minDwtLevels+1);
+               }
+         
+               // ASSUMPTION:  All bands same bit depth.
+               m_sourcePrecisionBits = m_codestream.get_bit_depth(0, true);
+         
+               m_codestream.set_persistent(); // ????
+               m_codestream.enable_restart(); // ????
+
+               // Get the image and tile dimensions.
+               std::vector<ossimIrect> tileDims;
+               if ( ossim::getCodestreamDimensions(m_codestream,
+                                                   m_imageDims,
+                                                   tileDims) == false )
+               {
+                  ossimNotify(ossimNotifyLevel_WARN)
+                     << __FILE__ << " " << __LINE__ << " " << MODULE
+                     << "Could not ascertain dimensions!" << std::endl;
+                  result = false;
+               }
+
+               kdu_dims region_of_interest;
+               region_of_interest.pos.x = 0;
+               region_of_interest.pos.y = 0;
+               region_of_interest.size.x = m_imageDims[0].width();
+               region_of_interest.size.y = m_imageDims[0].height();
+         
+               m_codestream.apply_input_restrictions(
+                  0, // first_component
+                  0, // max_components (0 = all remaining will appear)
+                  0, // highest resolution level
+                  0, // max_layers (0 = all layers retained)
+                  &region_of_interest, // expanded out to block boundary.
+                  KDU_WANT_OUTPUT_COMPONENTS);
+
+               // Configure the kdu_channel_mapping if it makes sense.
+               configureChannelMapping();
+
+               if (traceDebug())
+               {
+                  ossimNotify(ossimNotifyLevel_DEBUG)
+                     << "m_codestream.get_num_components(false): "
+                     << m_codestream.get_num_components(false)
+                     << "\nm_codestream.get_num_components(true): "
+                     << m_codestream.get_num_components(true)
+                     << "\nm_codestream.get_bit_depth(0, true): "
+                     << m_codestream.get_bit_depth(0, true)
+                     << "\nm_codestream.get_signed(0, true): "
+                     << m_codestream.get_signed(0, true)
+                     << "\nm_codestream.get_min_dwt_levels(): "
+                     << m_codestream.get_min_dwt_levels()
+                     << "\ntheNumberOfInputBands: "
+                     << theNumberOfInputBands
+                     << "\ntheNumberOfOutputBands: "
+                     << theNumberOfOutputBands
+                     << "\nthreads: " << threads
+                     << "\n";
+                  for ( std::vector<ossimIrect>::size_type i = 0; i < m_imageDims.size(); ++i )
+                  {
+                     ossimNotify(ossimNotifyLevel_DEBUG)
+                        << "m_imageDims[" << i << "]: " << m_imageDims[i] << "\n";
+                  }
+               }
+            }
+            else // if ( m_codestream.exists() )
+            {
+               result = false;
+            }
+
+         } // End: try block
+         catch( const ossimException& e )
+         {
+            result = false;         
+            if (traceDebug())
+            {
+               ossimNotify(ossimNotifyLevel_WARN)
+                  << MODULE << " Caught exception: " << e.what() << std::endl;
+            }
+         }
+         catch( ... )
+         {
+            result = false;
+            if (traceDebug())
+            {
+               ossimNotify(ossimNotifyLevel_WARN)
+                  << MODULE << " Caught unknown exception!" << std::endl;
+            }
+         }
+      
+      } // Matches: if ( result )
+
+   } // Matches:    if ( isEntryJ2k() && result )
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " exit status = " << (result?"true":"false\n")
+         << std::endl;
+   }
+
+   return result;
+   
+} // End: ossimKakaduNitfReader::allocate()
+
+bool ossimKakaduNitfReader::allocateBuffers()
+{
+   bool result = ossimNitfTileSource::allocateBuffers();
+   if ( result )
+   {
+      //---
+      // The ossimImageHandler::openOverview can set our min, max and null before we
+      // have our tiles allocated.
+      // 
+      // Set the min, max, and null in case we're being used as an overview handler
+      // and it is out of sync with the base image.  Example is dted null is -32767
+      // not default -32768.
+      //---
+      const ossim_uint32 BANDS = getNumberOfOutputBands();
+      for (ossim_uint32 band = 0; band < BANDS; ++band)
+      {
+         if ( theTile.valid() )
+         {
+            if ( !ossim::isnan(m_maxSampleValue) )
+            {
+               theTile->setMaxPix(m_maxSampleValue,   band);
+            }
+            if ( !ossim::isnan(m_minSampleValue) )
+            {
+               theTile->setMinPix(m_minSampleValue,   band);
+            }
+            if ( !ossim::isnan(m_nullSampleValue) )
+            {
+               theTile->setNullPix(m_nullSampleValue, band);
+            }
+         }
+         if ( theCacheTile.valid() )
+         {
+            if ( !ossim::isnan(m_maxSampleValue) )
+            {
+               theCacheTile->setMaxPix(m_maxSampleValue,   band);
+            }
+            if ( !ossim::isnan(m_minSampleValue) )
+            {
+               theCacheTile->setMinPix(m_minSampleValue,   band);
+            }
+            if ( !ossim::isnan(m_nullSampleValue) )
+            {
+               theCacheTile->setNullPix(m_nullSampleValue, band);
+            }
+         } 
+      }
+   }
+   return result;
+   
+} // End: ossimKakaduNitfReader::allocateBuffer()
+ 
+bool ossimKakaduNitfReader::canUncompress(const ossimNitfImageHeader* hdr) const
+{
+   bool result = false;
+   if (hdr)
+   {
+      if (hdr->getCompressionCode() == "C8") // j2k
+      {
+         result = true;
+      }
+      else
+      {
+         result = ossimNitfTileSource::canUncompress(hdr);
+      }
+   }
+   return result;
+}
+ 
+void ossimKakaduNitfReader::initializeReadMode()
+{
+   theReadMode = READ_MODE_UNKNOWN;
+   const ossimNitfImageHeader* hdr = getCurrentImageHeader();
+   if (hdr)
+   {
+      if (hdr->getCompressionCode() == "C8") // j2k
+      {
+         if ( (hdr->getIMode() == "B") && (hdr->getCompressionCode()== "C8") )
+         {
+            theReadMode = READ_JPEG_BLOCK; 
+         }
+      }
+      else
+      {
+         ossimNitfTileSource::initializeReadMode();
+      }
+   }
+}
+ 
+bool ossimKakaduNitfReader::scanForJpegBlockOffsets()
+{
+   bool result = false;
+
+   const ossimNitfImageHeader* hdr = getCurrentImageHeader();
+   if( hdr )
+   {  
+      // Capture the start of data.  This is start of j2k main header.
+      m_startOfCodestreamOffset = hdr->getDataLocation();
+
+      if ( checkJp2Signature() )
+      {
+         result = true;
+      }
+      else
+      {
+         //---
+         // Kakadu library finds j2k tiles.  We only find the "Start Of Codestream"(SOC)
+         // which should be at getDataLocation() but not in all cases.
+         //---
+         
+         // Seek to the first block.
+         theFileStr.seekg(m_startOfCodestreamOffset, ios_base::beg);
+         if ( theFileStr.good() )
+         {
+            //---
+            // Read the first two bytes and test for SOC (Start Of Codestream)
+            // marker.
+            //---
+            ossim_uint8 markerField[2];
+            theFileStr.read( (char*)markerField, 2);
+         
+            if ( (markerField[0] == 0xff) && (markerField[1] == 0x4f) )
+            {
+               result = true;
+            }
+            else
+            {
+               //---
+               // Scan the file from the beginning for SOC.  This handles cases
+               // where the data does not fall on "hdr->getDataLocation()".
+               //
+               // Changed for multi-enty nitf where first entry is j2k, second is
+               // uncompressed. Need to test at site. 02 August 2013 (drb)
+               //---
+               // theFileStr.seekg(0, ios_base::beg);
+               theFileStr.seekg(m_startOfCodestreamOffset, ios_base::beg);
+               char c;
+               while ( theFileStr.get(c) )
+               {
+                  if (static_cast<ossim_uint8>(c) == 0xff)
+                  {
+                     if (  theFileStr.get(c) )
+                     {
+                        if (static_cast<ossim_uint8>(c) == 0x4f)
+                        {
+                           m_startOfCodestreamOffset = theFileStr.tellg();
+                           m_startOfCodestreamOffset -= 2;
+                           result = true;
+                           break;
+                        }
+                     }
+                  }
+               }
+            }
+            
+            if ( (result == true) && traceDump() )
+            {
+               dumpTiles(ossimNotify(ossimNotifyLevel_DEBUG));
+            }
+            
+         } // matches: if (theFileStr.good())
+         
+      }  // if ( isJp2() ) ... else {
+
+   } // matches: if (hdr)
+
+   return result;
+   
+} // End: bool ossimKakaduNitfReader::scanForJpegBlockOffsets()
+ 
+void ossimKakaduNitfReader::initializeSwapBytesFlag()
+{
+   if ( isEntryJ2k() )
+   {
+      // Kakadu library handles.
+      theSwapBytesFlag = false;
+   }
+   else
+   {
+      ossimNitfTileSource::initializeSwapBytesFlag();
+   }
+}
+
+void ossimKakaduNitfReader::initializeCacheTileInterLeaveType()
+{
+   if ( isEntryJ2k() )
+   {
+      // Always band separate here.
+      theCacheTileInterLeaveType = OSSIM_BSQ;
+   }
+   else
+   {
+      ossimNitfTileSource::initializeCacheTileInterLeaveType();
+   }
+}
+
+bool ossimKakaduNitfReader::isEntryJ2k() const
+{
+   bool result = false;
+   const ossimNitfImageHeader* hdr = getCurrentImageHeader();
+   if (hdr)
+   {
+      if (hdr->getCompressionCode() == "C8") // j2k
+      {
+         result = true;
+      }
+   }
+   return result;
+}
+
+bool ossimKakaduNitfReader::checkJp2Signature()
+{
+   bool result = false;
+   const ossimNitfImageHeader* hdr = getCurrentImageHeader();
+   if( hdr )
+   {
+      std::streamoff startOfDataPos = hdr->getDataLocation();
+
+      // Seek to the start of data.
+      theFileStr.seekg(startOfDataPos, ios_base::beg);
+      if ( theFileStr.good() )
+      {
+         const ossim_uint8 J2K_SIGNATURE_BOX[SIGNATURE_BOX_SIZE] = 
+            {0x00,0x00,0x00,0x0c,0x6a,0x50,0x20,0x20,0x0d,0x0a,0x87,0x0a};
+         
+         ossim_uint8 box[SIGNATURE_BOX_SIZE];
+         
+         // Read in the box.
+         theFileStr.read((char*)box, SIGNATURE_BOX_SIZE);
+         result = true;
+         for (ossim_uint32 i = 0; i < SIGNATURE_BOX_SIZE; ++i)
+         {
+            if (box[i] != J2K_SIGNATURE_BOX[i])
+            {
+               result = false;
+               break;
+            }
+         }
+      }
+      
+      // Seek back to the start of data.
+      theFileStr.seekg(startOfDataPos, ios_base::beg);
+   }
+   
+   return result;
+}
+
+void ossimKakaduNitfReader::configureChannelMapping()
+{
+   bool result = false;
+   
+   if ( m_channels )
+   {
+      m_channels->clear();
+   }
+   else
+   {
+      m_channels = new kdu_channel_mapping;
+   }
+            
+   if ( m_jp2Source )
+   {
+      // Currently ignoring alpha:
+      result = m_channels->configure(m_jp2Source, false);
+   }
+   else
+   {
+      result = m_channels->configure(m_codestream);
+   }
+   
+   if ( result )
+   {
+      // If we the mapping doesn't have all our bands we don't use it.
+      if ( m_channels->get_num_colour_channels() != static_cast<int>(theNumberOfOutputBands) )
+      {
+         result = false;
+      }
+   }
+
+   if ( !result )
+   {
+      m_channels->clear();
+      delete m_channels;
+      m_channels = 0;
+   }
+}
+
+std::ostream& ossimKakaduNitfReader::dumpTiles(std::ostream& out)
+{
+   //---
+   // NOTE:
+   // SOC = 0xff4f Start of Codestream
+   // SOT = 0xff90 Start of tile
+   // SOD = 0xff93 Last marker in each tile
+   // EOC = 0xffd9 End of Codestream
+   //---
+   
+   const ossimNitfImageHeader* hdr = getCurrentImageHeader();
+   if(hdr)
+   {
+      // Capture the starting position.
+      std::streampos currentPos = theFileStr.tellg();
+      
+      // Seek to the first block.
+      theFileStr.seekg(m_startOfCodestreamOffset, ios_base::beg);
+      if (theFileStr.good())
+      {
+         out << "offset to codestream: " << m_startOfCodestreamOffset << "\n";
+         
+         //---
+         // Read the first two bytes and test for SOC (Start Of Codestream)
+         // marker.
+         //---
+         ossim_uint8 markerField[2];
+         theFileStr.read( (char*)markerField, 2);
+
+         bool foundSot = false;
+         if ( (markerField[0] == 0xff) && (markerField[1] == 0x4f) )
+         {
+            // Get the SIZ marker and dump it.
+            theFileStr.read( (char*)markerField, 2);
+            if ( (markerField[0] == 0xff) && (markerField[1] == 0x51) )
+            {
+               ossimJ2kSizRecord siz;
+               siz.parseStream(theFileStr);
+               siz.print(out);
+            }
+            
+            // Find the firt tile marker.
+            char c;
+            while ( theFileStr.get(c) )
+            {
+               if (static_cast<ossim_uint8>(c) == 0xff)
+               {
+                  if (  theFileStr.get(c) )
+                  {
+                     if (static_cast<ossim_uint8>(c) == 0x90)
+                     {
+                        foundSot = true;
+                        break;
+                     }
+                  }
+               }
+            }
+         }
+
+         if (foundSot) // At SOT marker...
+         {
+            const ossim_uint32 BLOCKS =
+               hdr->getNumberOfBlocksPerRow() * hdr->getNumberOfBlocksPerCol();
+            for (ossim_uint32 i = 0; i < BLOCKS; ++i)
+            {
+               std::streamoff pos = theFileStr.tellg();
+               ossimJ2kSotRecord sotRecord;
+               sotRecord.parseStream(theFileStr);
+               pos += sotRecord.thePsot;
+               sotRecord.print(out);
+               theFileStr.seekg(pos, ios_base::beg);
+            }
+         }
+      }
+
+      // If the last byte is read, the eofbit must be reset. 
+      if ( theFileStr.eof() )
+      {
+         theFileStr.clear();
+      }
+      
+      // Put the stream back to the where it was.
+      theFileStr.seekg(currentPos);
+   }
+
+   return out;
+}
+
diff --git a/ossim_plugins/kakadu/ossimKakaduNitfReader.h b/ossim_plugins/kakadu/ossimKakaduNitfReader.h
new file mode 100644
index 0000000..57ee4c0
--- /dev/null
+++ b/ossim_plugins/kakadu/ossimKakaduNitfReader.h
@@ -0,0 +1,405 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Description:
+//
+// Class declaration for reader of NITF images with JPEG2000 (J2K) compressed
+// blocks using kakadu library for decompression.
+//
+//----------------------------------------------------------------------------
+// $Id: ossimKakaduNitfReader.h 23664 2015-12-14 14:17:27Z dburken $
+
+#ifndef ossimKakaduNitfReader_HEADER
+#define ossimKakaduNitfReader_HEADER 1
+
+#include "../ossimPluginConstants.h"
+#include <ossim/imaging/ossimNitfTileSource.h>
+#include <kdu_compressed.h>
+#include <iosfwd>
+#include <fstream>
+
+// Forward declarations:
+
+namespace kdu_core
+{
+   class kdu_thread_queue;
+}
+
+namespace kdu_supp
+{
+   class jp2_family_src;
+   class jp2_source;
+   struct kdu_channel_mapping;
+}
+
+
+
+/**
+ * @brief ossimKakaduNitfReader class for reading NITF images with JPEG2000
+ * (J2K) compressed blocks using kakadu library for decompression. 
+ */
+class OSSIM_PLUGINS_DLL ossimKakaduNitfReader :
+   public ossimNitfTileSource, public kdu_core::kdu_compressed_source
+{
+public:
+
+   /** Anonymous enumerations: */
+   enum
+   {
+      SIGNATURE_BOX_SIZE = 12
+   };
+
+   /** default construtor */
+   ossimKakaduNitfReader();
+   
+   /** virtural destructor */
+   virtual ~ossimKakaduNitfReader();
+
+   /**
+    * @brief Returns short name.
+    * @return "ossim_kakadu_nitf_reader"
+    */
+   virtual ossimString getShortName() const;
+   
+   /**
+    * @brief Returns long  name.
+    * @return "ossim kakadu nitf reader"
+    */
+   virtual ossimString getLongName()  const;
+
+   /**
+    * @brief Returns the number of decimation levels.
+    * 
+    * This returns the total number of decimation levels.  It is important to
+    * note that res level 0 or full resolution is included in the list and has
+    * decimation values 1.0, 1.0
+    * 
+    * @return The number of decimation levels.
+    */
+   virtual ossim_uint32 getNumberOfDecimationLevels()const;
+
+   /**
+    * @brief Gets number of lines for res level.
+    *
+    * Overrides ossimNitfTileSource::getNumberOfLines
+    *
+    *  @param resLevel Reduced resolution level to return lines of.
+    *  Default = 0
+    *
+    *  @return The number of lines for specified reduced resolution level.
+    */
+   virtual ossim_uint32 getNumberOfLines(ossim_uint32 resLevel = 0) const;
+
+   /**
+    *  @brief Gets the number of samples for res level.
+    *
+    *  Overrides ossimNitfTileSource::getNumberOfSamples
+    *
+    *  @param resLevel Reduced resolution level to return samples of.
+    *  Default = 0
+    *
+    *  @return The number of samples for specified reduced resolution level.
+    */
+   virtual ossim_uint32 getNumberOfSamples(ossim_uint32 resLevel = 0) const;
+
+   /**
+    * @brief convenience method to set min pixel value.
+    *
+    * Added for overview readers so that the image handler that owns the
+    * overview reader can pass on it's min value.
+    *
+    * @param band Zero based band to set.
+    *
+    * @param pix Min pixel value.
+    */
+   virtual void setMinPixelValue(ossim_uint32 band, const ossim_float64& pix);
+
+   /**
+    * @brief convenience method to set max pixel value.
+    *
+    * Added for overview readers so that the image handler that owns the
+    * overview reader can pass on it's max value.
+    *
+    * @param band Zero based band to set.
+    *
+    * @param pix Max pixel value.
+    */
+   virtual void setMaxPixelValue(ossim_uint32 band, const ossim_float64& pix);
+
+   /**
+    * @brief convenience method to set null pixel value.
+    *
+    * Added for overview readers so that the image handler that owns the
+    * overview reader can pass on it's max value.
+    *
+    * @param band Zero based band to set.
+    *
+    * @param pix Null pixel value.
+    */
+   virtual void setNullPixelValue(ossim_uint32 band, const ossim_float64& pix);
+
+   /** @return the min pixel value either from base class call or theMinPixelValue if set. */
+   virtual ossim_float64 getMinPixelValue(ossim_uint32 band=0)const;
+
+   /** @return the max pixel value either from base class call or theMaxPixelValue if set. */
+   virtual ossim_float64 getMaxPixelValue(ossim_uint32 band=0)const;
+
+   /** @return the null pixel value either from base class call or theNullPixelValue if set. */
+   virtual ossim_float64 getNullPixelValue(ossim_uint32 band=0)const;
+
+protected:
+
+   /**
+   * @brief Gets an overview tile.
+   * 
+   * Overrides ossimImageHandler::getOverviewTile
+   *
+   * @param resLevel The resolution level to pull from with resLevel 0 being
+   * full res.
+   * 
+   * @param result The tile to stuff.  Note The requested rectangle in full
+   * image space and bands should be set in the result tile prior to
+   * passing.  This method will subtract the subImageOffset if needed for
+   * external overview call since they do not know about the sub image offset.
+   *
+   * @return true on success false on error.  Typically this will return false
+   * if resLevel==0 unless the overview has r0.  If return is false, result
+   * is undefined so caller should handle appropriately with makeBlank or
+   * whatever.
+   */
+  virtual bool getOverviewTile(ossim_uint32 resLevel,
+                               ossimImageData* result); 
+
+  
+  /**
+   * Loads a block of data to theCacheTile.
+   * 
+   * @param x Starting x position of block to load.
+   *
+   * @param y Starting y position of block to load.
+   *
+   * @return true on success, false on error.
+   *
+   * @note x and y are zero based relative to the upper left corner so any
+   * sub image offset should be subtracted off.
+   */
+  virtual bool loadBlock(ossim_uint32 x, ossim_uint32 y);
+  
+   /**
+    * @brief Parses "theImageFile" and initializes all nitf headers.
+    * 
+    * Overrides ossimNitfTileSource::parseFile
+    *
+    * @return True on success, false on error.
+    */
+   virtual bool parseFile();
+
+   /**
+    * @brief Allocates everything for current entry.
+    *
+    * This is called on an open() or a entry change to an already open nitf
+    * file.
+    *
+    * This does not allocate buffers and tiles to keep open and
+    * setCurrentEntry times to a minimum.  Buffers are allocated on first
+    * grab of pixel data by allocatBuffers method.
+    *
+    * Overrides ossimNitfTileSource::allocate
+    * 
+    * @return True on success, false on error.
+    */
+   virtual bool allocate(); 
+
+   /**
+    * @brief Allocates buffers for current entry.
+    *
+    * This is called on first getTile().
+    * 
+    * Overrides ossimNitfTileSource::allocateBuffers
+    * 
+    * @return True on success, false on error.
+    */
+   virtual bool allocateBuffers();
+   
+   /**
+    * @brief Checks header to see is we can decompress entry.
+    *
+    * If compression code is not "C8" calls base canUncompress as you could
+    * have a J2k entry and a jpeg entry.
+    *
+    * Overrides ossimNitfTileSource::canUncompress
+    * 
+    * @param hdr Pointer to image header.
+    * 
+    * @return true if reader can uncompress nitf.
+    * */
+   virtual bool canUncompress(const ossimNitfImageHeader* hdr) const;
+
+   /**
+    * @brief Initializes the data member "theReadMode" from the current entry.
+    *
+    * Overrides ossimNitfTileSource::initializeReadMode
+    */
+   virtual void initializeReadMode();
+
+   /**
+    * @brief This method simply checks for Start of Codestream (SOC) marker as
+    * the Kakadu library handles finding tiles for us.
+    *
+    * Overrides ossimNitfTileSource::scanForJpegBlockOffsets
+    * 
+    * @return true on success, false on error.
+    */
+   virtual bool scanForJpegBlockOffsets();
+
+   /**
+    * @brief Sets the "theSwapBytesFlag" from the current entry.
+    *
+    * Overrides ossimNitfTileSource::initializeSwapBytesFlag
+    */
+   virtual void initializeSwapBytesFlag();
+
+   /**
+    * @brief Initializes the data member "theCacheTileInterLeaveType".
+    *
+    * Overrides ossimNitfTileSource::initializeCacheTileInterLeaveType
+    */
+   virtual void initializeCacheTileInterLeaveType();
+
+   /**
+    * @brief Gets kdu source capability.
+    *
+    * Overrides kdu_compressed_source::get_capabilities
+    *
+    * @return KDU_SOURCE_CAP_SEEKABLE
+    */
+   virtual ossim_int32 get_capabilities();
+   
+   /**
+    * @bried Read method.
+    *
+    * Implements pure virtual kdu_compressed_source::read
+    * @param buf Buffer to fill.
+    *
+    * @param num_bytes Bytes to read.
+    *
+    * @return Actual bytes read.
+    */
+   virtual ossim_int32 read(kdu_core::kdu_byte *buf, ossim_int32 num_bytes);
+
+   /**
+    * @brief Seek method.
+    *
+    * Overrides kdu_compressed_source::seek
+    *
+    * @param offset Seek position relative to the start of code stream offset.
+    *
+    * @return true on success, false on error.
+    */
+   virtual bool seek(kdu_core::kdu_long offset);
+
+   /**
+    * @brief Get file position relative to the start of code stream offset.
+    *
+    * Overrides kdu_compressed_source::get_pos
+    *
+    * @return Position in codestream.
+    */   
+   virtual kdu_core::kdu_long get_pos();
+
+private:
+
+   /**
+    * @brief Checks current entry image header to see if it is j2k.
+    * @return true if j2k, false if not.
+    */
+   bool isEntryJ2k() const;
+
+   /**
+    * @brief Checks for jp2 signature block.
+    *
+    * Note the stream is repositioned to start of data after the check so that the
+    * jp2 open code does not have to reposition.
+    * 
+    * @return true if jp2, false if not.
+    */
+   bool checkJp2Signature();
+
+   /**
+    * Initializes m_channels to be used with copyRegionToTile if it makes sense.
+    */
+   void configureChannelMapping();
+
+   
+
+   /** @brief Method to print out tile info. For debug only.  */
+   std::ostream& dumpTiles(std::ostream& out);
+
+   std::streamoff m_startOfCodestreamOffset;
+
+   kdu_supp::jp2_family_src*      m_jp2FamilySrc;
+   kdu_supp::jp2_source*          m_jp2Source;
+   kdu_supp::kdu_channel_mapping* m_channels;
+   kdu_core::kdu_codestream       m_codestream;
+   kdu_core::kdu_thread_env*      m_threadEnv;
+   kdu_core::kdu_thread_queue*    m_openTileThreadQueue;
+   
+   ossim_uint32               m_sourcePrecisionBits;
+   ossim_uint32               m_minDwtLevels;
+   
+   /** Image dimensions for each level. */
+   std::vector<ossimIrect>    m_imageDims;
+
+   /**
+    * min/max/null These are class attributes so that when behaving as an overview the owner or
+    * base image handler can pass its min/max/null to us.  For non eight bit data this is
+    * critical so that the data gets stretched exactly as the base handler.  Did NOT make
+    * these a vector the size of bands as it was not needed at time of coding.
+    */
+   ossim_float64              m_minSampleValue;
+   ossim_float64              m_maxSampleValue;
+   ossim_float64              m_nullSampleValue;
+
+TYPE_DATA   
+};
+
+inline ossim_int32 ossimKakaduNitfReader::get_capabilities()
+{
+   return ( KDU_SOURCE_CAP_SEEKABLE | KDU_SOURCE_CAP_SEQUENTIAL );
+}
+
+inline ossim_int32 ossimKakaduNitfReader::read(kdu_core::kdu_byte *buf, ossim_int32 num_bytes)
+{
+   theFileStr.read((char*)buf, num_bytes);
+   return theFileStr.gcount();
+}
+
+inline bool ossimKakaduNitfReader::seek(kdu_core::kdu_long offset)
+{
+   // If the last byte is read, the eofbit must be reset. 
+   if ( theFileStr.eof() )
+   {
+      theFileStr.clear();
+   }
+
+   //---
+   // All seeks are relative to the start of code stream.
+   //---
+   theFileStr.seekg(offset+m_startOfCodestreamOffset, ios_base::beg);
+   return theFileStr.good();
+}
+
+inline kdu_core::kdu_long ossimKakaduNitfReader::get_pos()
+{
+   //---
+   // Must subtract the SOC(start of code stream) from the real file position
+   // since positions are relative to SOC.
+   //---
+   return static_cast<kdu_core::kdu_long>(theFileStr.tellg() - m_startOfCodestreamOffset );
+}
+
+#endif /* #ifndef ossimKakaduNitfReader_HEADER */
+
diff --git a/ossim_plugins/kakadu/ossimKakaduNitfWriter.cpp b/ossim_plugins/kakadu/ossimKakaduNitfWriter.cpp
new file mode 100644
index 0000000..8957cf0
--- /dev/null
+++ b/ossim_plugins/kakadu/ossimKakaduNitfWriter.cpp
@@ -0,0 +1,554 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Description: OSSIM Kakadu based nitf writer.
+//
+//----------------------------------------------------------------------------
+// $Id: ossimKakaduNitfWriter.cpp 23664 2015-12-14 14:17:27Z dburken $
+
+#include "ossimKakaduNitfWriter.h"
+#include "ossimKakaduCommon.h"
+#include "ossimKakaduCompressor.h"
+#include "ossimKakaduKeywords.h"
+#include "ossimKakaduMessaging.h"
+
+#include <ossim/base/ossimBooleanProperty.h>
+#include <ossim/base/ossimDate.h>
+#include <ossim/base/ossimDpt.h>
+#include <ossim/base/ossimEndian.h>
+#include <ossim/base/ossimException.h>
+#include <ossim/base/ossimKeywordlist.h>
+#include <ossim/base/ossimKeywordNames.h>
+#include <ossim/base/ossimNumericProperty.h>
+#include <ossim/base/ossimTrace.h>
+
+#include <ossim/projection/ossimMapProjection.h>
+
+#include <ossim/imaging/ossimImageData.h>
+#include <ossim/imaging/ossimImageSource.h>
+
+#include <ossim/support_data/ossimNitfCommon.h>
+#include <ossim/support_data/ossimNitfFileHeader.h>
+#include <ossim/support_data/ossimNitfFileHeaderV2_1.h>
+#include <ossim/support_data/ossimNitfImageHeader.h>
+#include <ossim/support_data/ossimNitfImageHeaderV2_1.h>
+
+#include <ostream>
+
+static const ossimIpt DEFAULT_TILE_SIZE(1024, 1024);
+
+RTTI_DEF1(ossimKakaduNitfWriter, "ossimKakaduNitfWriter", ossimNitfWriterBase)
+
+//---
+// For trace debugging (to enable at runtime do:
+// your_app -T "ossimKakaduNitfWriter:debug" your_app_args
+//---
+static const ossimTrace traceDebug( ossimString("ossimKakaduNitfWriter:debug") );
+
+//---
+// For the "ident" program which will find all exanded $Id: ossimKakaduNitfWriter.cpp 23664 2015-12-14 14:17:27Z dburken $
+// them.
+//---
+#if OSSIM_ID_ENABLED
+static const char OSSIM_ID[] = "$Id: ossimKakaduNitfWriter.cpp 23664 2015-12-14 14:17:27Z dburken $";
+#endif
+
+ossimKakaduNitfWriter::ossimKakaduNitfWriter()
+   : ossimNitfWriterBase(),
+     m_compressor(new ossimKakaduCompressor()),
+     m_outputStream(0),
+     m_ownsStreamFlag(false)
+{
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimKakaduNitfWriter::ossimKakaduNitfWriter entered"
+         << std::endl;
+#if OSSIM_ID_ENABLED
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "OSSIM_ID:  "
+         << OSSIM_ID
+         << std::endl;
+#endif
+   }
+
+   //---
+   // Since the internal nitf tags are not very accurate, write an external
+   // geometry out as default behavior.  Users can disable this via the
+   // property interface or keyword list.
+   //---
+   setWriteExternalGeometryFlag(true);
+
+   // Set the output image type in the base class.
+   setOutputImageType(getShortName());
+}
+
+ossimKakaduNitfWriter::~ossimKakaduNitfWriter()
+{
+   // This will flush stream and delete it if we own it.
+   close();
+
+   if (m_compressor)
+   {
+      delete m_compressor;
+      m_compressor = 0;
+   }
+}
+
+ossimString ossimKakaduNitfWriter::getShortName() const
+{
+   return ossimString("ossim_kakadu_nitf_j2k");
+}
+
+ossimString ossimKakaduNitfWriter::getLongName() const
+{
+   return ossimString("ossim kakadu nitf j2k writer");
+}
+
+ossimString ossimKakaduNitfWriter::getClassName() const
+{
+   return ossimString("ossimKakaduNitfWriter");
+}
+
+bool ossimKakaduNitfWriter::writeFile()
+{
+   // This method is called from ossimImageFileWriter::execute().
+
+   bool result = false;
+   
+   if( theInputConnection.valid() &&
+       (getErrorStatus() == ossimErrorCodes::OSSIM_OK) )
+   {
+      // Set the tile size for all processes.
+      theInputConnection->setTileSize( DEFAULT_TILE_SIZE );
+      theInputConnection->setToStartOfSequence();
+      
+      //---
+      // Note only the master process used for writing...
+      //---
+      if(theInputConnection->isMaster())
+      {
+         if (!isOpen())
+         {
+            open();
+         }
+         
+         if ( isOpen() )
+         {
+            result = writeStream();
+         }
+      }
+      else // Slave process.
+      {
+         // This will return after all tiles for this node have been processed.
+         theInputConnection->slaveProcessTiles();
+
+         result = true;
+      }
+   }
+      
+   return result;
+}
+
+bool ossimKakaduNitfWriter::writeStream()
+{
+   static const char MODULE[] = "ossimKakaduNitfWriter::writeStream";
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " entered..." << endl;
+   }
+
+   if ( !theInputConnection || !m_outputStream || !theInputConnection->isMaster() )
+   {
+      return false;
+   }
+
+   const ossim_uint32    TILES  = theInputConnection->getNumberOfTiles();
+   const ossim_uint32    BANDS  = theInputConnection->getNumberOfOutputBands();
+   const ossimScalarType SCALAR = theInputConnection->getOutputScalarType();
+   
+   if (m_compressor->getAlphaChannelFlag())
+   {
+      //--- 
+      // Someone can set this through the generic setProperty interface.
+      // Unset, currently only supported in jp2 writer.
+      // Could be used here but I think we would have to update the
+      // nitf tags.
+      //---
+      m_compressor->setAlphaChannelFlag(false);
+   }
+
+   // Create the compressor.  Can through an exception.
+   try
+   {
+      m_compressor->create(m_outputStream,
+                           SCALAR,
+                           BANDS,
+                           theInputConnection->getAreaOfInterest(),
+                           DEFAULT_TILE_SIZE,
+                           TILES,
+                           false);
+   }
+   catch (const ossimException& e)
+   {
+      ossimNotify(ossimNotifyLevel_WARN) << e.what() << std::endl;
+      return false;
+   }
+
+   std::streampos endOfFileHdrPos;
+   std::streampos endOfImgHdrPos;
+   std::streampos endOfFilePos;
+   
+   // Container record withing NITF file header.
+   ossimNitfImageInfoRecordV2_1 imageInfoRecord;
+   
+   // NITF file header.
+   ossimRefPtr<ossimNitfFileHeaderV2_1> fHdr = new ossimNitfFileHeaderV2_1();
+   
+   // Note the sub header length and image length will be set later.      
+   fHdr->addImageInfoRecord(imageInfoRecord);
+   
+   fHdr->setDate(ossimDate());
+   fHdr->setTitle(ossimString("")); // ???
+   
+   // Write to stream capturing the stream position for later.
+   fHdr->writeStream(*m_outputStream);
+   endOfFileHdrPos = m_outputStream->tellp();
+   
+   // NITF image header.
+   ossimRefPtr<ossimNitfImageHeaderV2_1> iHdr = new ossimNitfImageHeaderV2_1();
+   
+   // Set the compression type:
+   iHdr->setCompression(ossimString("C8"));
+   
+   // Set the Image Magnification (IMAG) field.
+   iHdr->setImageMagnification(ossimString("1.0"));
+   
+   // Set the pixel type (PVTYPE) field.
+   iHdr->setPixelType(ossimNitfCommon::getNitfPixelType(SCALAR));
+   
+   // Set the actual bits per pixel (ABPP) field.
+   iHdr->setActualBitsPerPixel(ossim::getActualBitsPerPixel(SCALAR));
+   
+   // Set the bits per pixel (NBPP) field.
+   iHdr->setBitsPerPixel(ossim::getBitsPerPixel(SCALAR));
+   
+   iHdr->setNumberOfBands(BANDS);
+   iHdr->setImageMode('B'); // IMODE field to blocked.
+   
+   if( (BANDS == 3) && (SCALAR == OSSIM_UCHAR) )
+   {
+      iHdr->setRepresentation("RGB");
+      iHdr->setCategory("VIS");
+   }
+   else if(BANDS == 1)
+   {
+      iHdr->setRepresentation("MONO");
+      iHdr->setCategory("MS");
+   }
+   else
+   {
+      iHdr->setRepresentation("MULTI");
+      iHdr->setCategory("MS");
+   }
+   
+   ossimNitfImageBandV2_1 bandInfo;
+   for(ossim_uint32 band = 0; band < BANDS; ++band)
+   {
+      std::ostringstream out;
+      
+      out << std::setfill('0')
+          << std::setw(2)
+          << band;
+      
+      bandInfo.setBandRepresentation(out.str().c_str());
+      iHdr->setBandInfo(band, bandInfo);
+   }
+   
+   ossim_uint32 outputTilesWide = theInputConnection->getNumberOfTilesHorizontal();
+   ossim_uint32 outputTilesHigh = theInputConnection->getNumberOfTilesVertical();
+   
+   iHdr->setBlocksPerRow(outputTilesWide);
+   iHdr->setBlocksPerCol(outputTilesHigh);
+   iHdr->setNumberOfPixelsPerBlockRow(DEFAULT_TILE_SIZE.y);
+   iHdr->setNumberOfPixelsPerBlockCol(DEFAULT_TILE_SIZE.x);
+   iHdr->setNumberOfRows(theInputConnection->getAreaOfInterest().height());
+   iHdr->setNumberOfCols(theInputConnection->getAreaOfInterest().width());
+   
+   // Write the geometry info to the image header.
+   writeGeometry(iHdr.get(), theInputConnection.get());
+   
+   // Write the image header to stream capturing the stream position.
+   iHdr->writeStream(*m_outputStream);
+   endOfImgHdrPos = m_outputStream->tellp();
+   
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " DEBUG:"
+         << "\noutputTilesWide:  " << outputTilesWide
+         << "\noutputTilesHigh:  " << outputTilesHigh
+         << "\nnumberOfTiles:    " << TILES
+         << "\nimageRect: " << theInputConnection->getAreaOfInterest()
+         << std::endl;
+   }
+   
+   // Tile loop in the line direction.
+   ossim_uint32 tileNumber = 0;
+   bool result = true;
+   for(ossim_uint32 y = 0; y < outputTilesHigh; ++y)
+   {
+      // Tile loop in the sample (width) direction.
+      for(ossim_uint32 x = 0; x < outputTilesWide; ++x)
+      {
+         // Grab the resampled tile.
+         ossimRefPtr<ossimImageData> t = theInputConnection->getNextTile();
+         if (t.valid() && ( t->getDataObjectStatus() != OSSIM_NULL ) )
+         {
+            if ( ! m_compressor->writeTile( *(t.get()) ) )
+            {
+               ossimNotify(ossimNotifyLevel_WARN)
+                  << MODULE << " ERROR:"
+                  << "Error returned writing tile:  "
+                  << tileNumber
+                  << std::endl;
+               result = false;
+            }
+         }
+         else
+         {
+            ossimNotify(ossimNotifyLevel_WARN)
+               << MODULE << " ERROR:"
+               << "Error returned writing tile:  " << tileNumber
+               << std::endl;
+            result = false;
+         }
+         if ( !result )
+         {
+            // This will bust out of both loops.
+            x = outputTilesWide;
+            y = outputTilesHigh;
+         }
+         
+         // Increment tile number for percent complete.
+         ++tileNumber;
+         
+      } // End of tile loop in the sample (width) direction.
+      
+      if (needsAborting())
+      {
+         setPercentComplete(100.0);
+         break;
+      }
+      else
+      {
+         ossim_float64 tile = tileNumber;
+         ossim_float64 numTiles = TILES;
+         setPercentComplete(tile / numTiles * 100.0);
+      }
+      
+   } // End of tile loop in the line (height) direction.
+         
+   m_compressor->finish();
+   
+   // Get the file length.
+   endOfFilePos = m_outputStream->tellp();
+   
+   //---
+   // Seek back to set some things that were not know until now and
+   // rewrite the nitf file and image header.
+   //---
+   m_outputStream->seekp(0, std::ios_base::beg);
+   
+   // Set the file length.
+   std::streamoff length = endOfFilePos;
+   fHdr->setFileLength(static_cast<ossim_uint64>(length));
+   
+   // Set the file header length.
+   length = endOfFileHdrPos;
+   fHdr->setHeaderLength(static_cast<ossim_uint64>(length));            
+   // Set the image sub header length.
+   length = endOfImgHdrPos - endOfFileHdrPos;
+   
+   imageInfoRecord.setSubheaderLength(static_cast<ossim_uint64>(length));
+   
+   // Set the image length.
+   length = endOfFilePos - endOfImgHdrPos;
+   imageInfoRecord.setImageLength(static_cast<ossim_uint64>(length));
+   
+   fHdr->replaceImageInfoRecord(0, imageInfoRecord);
+   
+   setComplexityLevel(length, fHdr.get());
+   
+   // Rewrite the header.
+   fHdr->writeStream(*m_outputStream);
+   
+   // Set the compression rate now that the image size is known.
+   ossimString comrat = ossimNitfCommon::getCompressionRate(
+      theInputConnection->getAreaOfInterest(),
+      BANDS,
+      SCALAR,
+      static_cast<ossim_uint64>(length));
+   iHdr->setCompressionRateCode(comrat);
+   
+   // Rewrite the image header.
+   iHdr->writeStream(*m_outputStream);
+
+   close();
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " exit status = " << (result?"true":"false\n")
+         << std::endl;
+   }
+   
+   return result;
+}
+
+bool ossimKakaduNitfWriter::saveState(ossimKeywordlist& kwl,
+                                      const char* prefix)const
+{
+   m_compressor->saveState(kwl, prefix);
+   
+   return ossimNitfWriterBase::saveState(kwl, prefix);
+}
+
+bool ossimKakaduNitfWriter::loadState(const ossimKeywordlist& kwl,
+                                      const char* prefix)
+{
+   m_compressor->loadState(kwl, prefix);
+   
+   return ossimNitfWriterBase::loadState(kwl, prefix);
+}
+
+bool ossimKakaduNitfWriter::isOpen() const
+{
+   return (m_outputStream) ? true : false;
+}
+
+bool ossimKakaduNitfWriter::open()
+{
+   bool result = false;
+   
+   close();
+
+   // Check for empty filenames.
+   if (theFilename.size())
+   {
+      std::ofstream* os = new std::ofstream();
+      os->open(theFilename.c_str(), ios::out | ios::binary);
+      if(os->is_open())
+      {
+         m_outputStream = os;
+         m_ownsStreamFlag = true;
+         result = true;
+      }
+      else
+      {
+         delete os;
+         os = 0;
+      }
+   }
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimKakaduNitfWriter::open()\n"
+         << "File " << theFilename << (result ? " opened" : " not opened")
+         << std::endl;
+    }
+
+   return result;
+}
+
+void ossimKakaduNitfWriter::close()
+{
+   if (m_outputStream)      
+   {
+      m_outputStream->flush();
+
+      if (m_ownsStreamFlag)
+      {
+         delete m_outputStream;
+         m_outputStream = 0;
+         m_ownsStreamFlag = false;
+      }
+   }
+}
+
+ossimString ossimKakaduNitfWriter::getExtension() const
+{
+   return ossimString("ntf");
+}
+
+bool ossimKakaduNitfWriter::getOutputHasInternalOverviews( void ) const
+{ 
+   return true;
+}
+
+void ossimKakaduNitfWriter::getImageTypeList(std::vector<ossimString>& imageTypeList)const
+{
+   imageTypeList.push_back(getShortName());
+}
+
+bool ossimKakaduNitfWriter::hasImageType(const ossimString& imageType) const
+{
+   bool result = false;
+   if ( (imageType == getShortName()) ||
+        (imageType == "image/ntf") )
+   {
+      result = true;
+   }
+   return result;
+}
+
+void ossimKakaduNitfWriter::setProperty(ossimRefPtr<ossimProperty> property)
+{
+   if ( property.valid() )
+   {
+      if ( m_compressor->setProperty(property) == false )
+      {
+         // Not a compressor property.
+         ossimNitfWriterBase::setProperty(property);
+      }
+   }
+}
+
+ossimRefPtr<ossimProperty> ossimKakaduNitfWriter::getProperty(
+   const ossimString& name)const
+{
+   ossimRefPtr<ossimProperty> p = m_compressor->getProperty(name);
+
+   if ( !p )
+   {
+      p = ossimNitfWriterBase::getProperty(name);
+   }
+   
+   return p;
+}
+
+void ossimKakaduNitfWriter::getPropertyNames(
+   std::vector<ossimString>& propertyNames)const
+{
+   m_compressor->getPropertyNames(propertyNames);
+
+   ossimNitfWriterBase::getPropertyNames(propertyNames);
+}
+
+bool ossimKakaduNitfWriter::setOutputStream(std::ostream& stream)
+{
+   if (m_ownsStreamFlag && m_outputStream)
+   {
+      delete m_outputStream;
+   }
+   m_outputStream = &stream;
+   m_ownsStreamFlag = false;
+   return true;
+}
+
diff --git a/ossim_plugins/kakadu/ossimKakaduNitfWriter.h b/ossim_plugins/kakadu/ossimKakaduNitfWriter.h
new file mode 100644
index 0000000..be14269
--- /dev/null
+++ b/ossim_plugins/kakadu/ossimKakaduNitfWriter.h
@@ -0,0 +1,146 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author:  David Burken
+//
+// Description: OSSIM Kakadu based nitf writer.
+//
+//----------------------------------------------------------------------------
+// $Id: ossimKakaduNitfWriter.h 23664 2015-12-14 14:17:27Z dburken $
+#ifndef ossimKakaduNitfWriter_HEADER
+#define ossimKakaduNitfWriter_HEADER 1
+
+#include <ossim/imaging/ossimNitfWriterBase.h>
+#include <ossim/base/ossimRefPtr.h>
+#include <ossim/base/ossimString.h>
+
+#include <iosfwd>
+#include <vector>
+
+class ossimKakaduCompressor;
+class ossimKeywordlist;
+
+class ossimKakaduNitfWriter : public ossimNitfWriterBase
+{
+public:
+
+   /** @brief default constructor */
+   ossimKakaduNitfWriter();
+
+   /* @brief virtual destructor */
+   virtual ~ossimKakaduNitfWriter();
+
+   /** @return "ossim_kakadu_nitf_j2k_writer" */
+   virtual ossimString getShortName() const;
+
+   /** @return "ossim kakadu nitf j2k writer" */
+   virtual ossimString getLongName()  const;
+
+   /** @return "ossimKakaduNitfReader" */
+   virtual ossimString getClassName()    const;
+   
+   /**
+    * @brief Appends this writer image types to list "imageTypeList".
+    * @param imageTypeList stl::vector<ossimString> list to append to.
+    */
+   virtual void getImageTypeList(std::vector<ossimString>& imageTypeList)const;
+   
+   virtual bool isOpen()const;   
+   
+   virtual bool open();
+
+   virtual void close();
+   
+   /**
+    * saves the state of the object.
+    */
+   virtual bool saveState(ossimKeywordlist& kwl,
+                          const char* prefix=0)const;
+   
+   /**
+    * Method to the load (recreate) the state of an object from a keyword
+    * list.  Return true if ok or false on error.
+    */
+   virtual bool loadState(const ossimKeywordlist& kwl,
+                          const char* prefix=0);
+
+   /**
+    * Will set the property whose name matches the argument
+    * "property->getName()".
+    *
+    * @param property Object containing property to set.
+    */
+   virtual void setProperty(ossimRefPtr<ossimProperty> property);
+
+   /**
+    * @param name Name of property to return.
+    * 
+    * @returns A pointer to a property object which matches "name".
+    */
+   virtual ossimRefPtr<ossimProperty> getProperty(const ossimString& name)const;
+
+   /**
+    * Pushes this's names onto the list of property names.
+    *
+    * @param propertyNames array to add this's property names to.
+    */
+   virtual void getPropertyNames(std::vector<ossimString>& propertyNames)const;
+
+   bool hasImageType(const ossimString& imageType) const;
+
+   /**
+    * @brief Method to write the image to a stream.
+    *
+    * @return true on success, false on error.
+    */
+   virtual bool writeStream();
+
+   /**
+    * @brief Sets the output stream to write to.
+    *
+    * The stream will not be closed/deleted by this object.
+    *
+    * @param output The stream to write to.
+    */
+   virtual bool setOutputStream(std::ostream& stream);
+
+   /**
+    * Returns a 3-letter extension from the image type descriptor 
+    * (theOutputImageType) that can be used for image file extensions.
+    *
+    * @param imageType string representing image type.
+    *
+    * @return the 3-letter string extension.
+    */
+   virtual ossimString getExtension() const;
+
+   /**
+    * Examples of writers that always generate internal
+    * overviews are ossim_kakadu_jp2 and ossim_kakadu_nitf_j2k.
+    *
+    * @return true if the output of the writer will have
+    * internal overviews. The default is false. 
+    */
+   virtual bool getOutputHasInternalOverviews( void ) const;
+
+protected:
+   /**
+    * @brief Writes the file to disk or a stream.
+    * @return true on success, false on error.
+    */
+   virtual bool writeFile();   
+
+private:
+
+   ossimKakaduCompressor* m_compressor;
+   std::ostream*          m_outputStream;
+   bool                   m_ownsStreamFlag;
+
+   TYPE_DATA
+};
+
+#endif /* #ifndef ossimKakaduNitfVoid Writer_HEADER */
+
diff --git a/ossim_plugins/kakadu/ossimKakaduOverviewBuilderFactory.cpp b/ossim_plugins/kakadu/ossimKakaduOverviewBuilderFactory.cpp
new file mode 100644
index 0000000..fad18f5
--- /dev/null
+++ b/ossim_plugins/kakadu/ossimKakaduOverviewBuilderFactory.cpp
@@ -0,0 +1,58 @@
+//----------------------------------------------------------------------------
+// 
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Description: The ossim kakadu overview builder factory.
+//
+//----------------------------------------------------------------------------
+// $Id: ossimKakaduOverviewBuilderFactory.cpp 23664 2015-12-14 14:17:27Z dburken $
+
+#include "ossimKakaduOverviewBuilderFactory.h"
+#include "ossimKakaduNitfOverviewBuilder.h"
+
+ossimKakaduOverviewBuilderFactory* ossimKakaduOverviewBuilderFactory::instance()
+{
+   static ossimKakaduOverviewBuilderFactory inst;
+   return &inst;
+}
+
+ossimKakaduOverviewBuilderFactory::~ossimKakaduOverviewBuilderFactory()
+{
+}
+
+ossimOverviewBuilderBase* ossimKakaduOverviewBuilderFactory::createBuilder(
+   const ossimString& typeName) const
+{
+   ossimRefPtr<ossimOverviewBuilderBase> result = new  ossimKakaduNitfOverviewBuilder();
+   if ( result->hasOverviewType(typeName) == false )
+   {
+      result = 0;
+   }
+   
+   return result.release();
+}
+
+void ossimKakaduOverviewBuilderFactory::getTypeNameList(
+   std::vector<ossimString>& typeList) const
+{
+   ossimRefPtr<ossimOverviewBuilderBase> builder = new  ossimKakaduNitfOverviewBuilder();
+   builder->getTypeNameList(typeList);
+   builder = 0;
+}
+
+ossimKakaduOverviewBuilderFactory::ossimKakaduOverviewBuilderFactory()
+{
+}
+
+ossimKakaduOverviewBuilderFactory::ossimKakaduOverviewBuilderFactory(
+   const ossimKakaduOverviewBuilderFactory& /* obj */)
+{
+}
+
+void ossimKakaduOverviewBuilderFactory::operator=(
+   const ossimKakaduOverviewBuilderFactory& /* rhs */)
+{
+}
+
diff --git a/ossim_plugins/kakadu/ossimKakaduOverviewBuilderFactory.h b/ossim_plugins/kakadu/ossimKakaduOverviewBuilderFactory.h
new file mode 100644
index 0000000..cb1bd44
--- /dev/null
+++ b/ossim_plugins/kakadu/ossimKakaduOverviewBuilderFactory.h
@@ -0,0 +1,70 @@
+//----------------------------------------------------------------------------
+// 
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author:  David Burken
+//
+// Description: The ossim kakadu overview builder factory.
+//
+//----------------------------------------------------------------------------
+// $Id: ossimKakaduOverviewBuilderFactory.h 23664 2015-12-14 14:17:27Z dburken $
+
+#ifndef ossimKakaduOverviewBuilderFactory_HEADER
+#define ossimKakaduOverviewBuilderFactory_HEADER 1
+
+#include <ossim/base/ossimConstants.h>
+#include <ossim/imaging/ossimOverviewBuilderFactoryBase.h>
+
+class ossimOverviewBuilderBase;
+class ossimString;
+
+/**
+ * @class ossimKakaduOverviewBuilderFactory
+ * @brief The ossim overview builder factory.
+ */
+class ossimKakaduOverviewBuilderFactory:
+   public ossimOverviewBuilderFactoryBase
+{
+public:
+
+   /** @brief static instance method. */
+   static ossimKakaduOverviewBuilderFactory* instance();
+   
+   /** virtual destructor */
+   virtual ~ossimKakaduOverviewBuilderFactory();
+
+   /**
+    * @brief Creates a builder from a string.  This should match a string from
+    * the getTypeNameList() method.  Pure virtual.
+    * 
+    * @return Pointer to ossimOverviewBuilderInterface or NULL is not found
+    * within registered factories.
+    */
+   virtual ossimOverviewBuilderBase* createBuilder(
+      const ossimString& typeName) const;
+
+   /**
+    * @brief Method to populate a list of supported types for the factory.
+    * registered to this registry.  Pure virtual.
+    *
+    * @param typeList List of ossimStrings to add to.
+    */
+   virtual void getTypeNameList(std::vector<ossimString>& typeList)const;
+
+private:
+   /** default constructor hidden from use */
+   ossimKakaduOverviewBuilderFactory();
+
+   /** copy constructor hidden from use */
+   ossimKakaduOverviewBuilderFactory(
+      const ossimKakaduOverviewBuilderFactory& obj);
+
+   /** operator= hidden from use. */
+   void operator=(const ossimKakaduOverviewBuilderFactory& rhs);
+
+};
+
+#endif /* #ifndef ossimKakaduOverviewBuilderFactory_HEADER */
+
diff --git a/ossim_plugins/kakadu/ossimKakaduPluginInit.cpp b/ossim_plugins/kakadu/ossimKakaduPluginInit.cpp
new file mode 100644
index 0000000..de50972
--- /dev/null
+++ b/ossim_plugins/kakadu/ossimKakaduPluginInit.cpp
@@ -0,0 +1,167 @@
+//----------------------------------------------------------------------------
+//
+// License:  See top level LICENSE.txt file
+//
+// Author:  David Burken
+//
+// Description: OSSIM Kakadu plugin initialization
+// code.
+//
+//----------------------------------------------------------------------------
+// $Id: ossimKakaduPluginInit.cpp 20398 2011-12-20 16:34:24Z gpotts $
+
+#include "../ossimPluginConstants.h"
+#include "ossimKakaduOverviewBuilderFactory.h"
+#include "ossimKakaduReaderFactory.h"
+#include "ossimKakaduWriterFactory.h"
+#include <ossim/plugin/ossimSharedObjectBridge.h>
+#include <ossim/imaging/ossimImageHandlerRegistry.h>
+#include <ossim/imaging/ossimImageWriterFactoryRegistry.h>
+#include <ossim/imaging/ossimOverviewBuilderFactoryRegistry.h>
+#include "ossimKakaduJpipHandlerFactory.h"
+#include "ossimKakaduJpipInfoFactory.h"
+#include "ossimJpipProjectionFactory.h"
+#include "ossimKakaduJpipImageGeometryFactory.h"
+#include <ossim/support_data/ossimInfoFactoryRegistry.h>
+#include <ossim/projection/ossimProjectionFactoryRegistry.h>
+#include <ossim/imaging/ossimImageGeometryRegistry.h>
+
+static void setDescription(ossimString& description)
+{
+   description = "Kakadu (j2k) reader / writer plugin\n";
+   description += "Kakadu (jpip) reader plugin\n";
+   description += "\tsupports ingest via a keywordlist lr from a url of the form\n";
+   description += "\tjpip://<server>:<port>/<path>\n";
+}
+
+
+extern "C"
+{
+   ossimSharedObjectInfo  myInfo;
+   ossimString theDescription;
+   std::vector<ossimString> theObjList;
+
+   const char* getDescription()
+   {
+      return theDescription.c_str();
+   }
+
+   int getNumberOfClassNames()
+   {
+      return (int)theObjList.size();
+   }
+
+   const char* getClassName(int idx)
+   {
+      if(idx < (int)theObjList.size())
+      {
+         return theObjList[0].c_str();
+      }
+      return (const char*)0;
+   }
+
+   /* Note symbols need to be exported on windoze... */ 
+   OSSIM_PLUGINS_DLL void ossimSharedLibraryInitialize(
+                                                       ossimSharedObjectInfo** info, 
+                                                       const char* options)
+   {    
+      myInfo.getDescription = getDescription;
+      myInfo.getNumberOfClassNames = getNumberOfClassNames;
+      myInfo.getClassName = getClassName;
+      
+      *info = &myInfo;
+      ossimKeywordlist kwl;
+      kwl.parseString(ossimString(options));
+      if(ossimString(kwl.find("reader_factory.location")).downcase() == "front")
+      {
+         /* Register the readers... */
+         ossimImageHandlerRegistry::instance()->
+         registerFactoryToFront(ossimKakaduReaderFactory::instance());
+
+         ossimImageHandlerRegistry::instance()->
+         registerFactoryToFront(ossimKakaduJpipHandlerFactory::instance());
+      }
+      else
+      {
+         /* Register the readers... */
+         ossimImageHandlerRegistry::instance()->
+         registerFactory(ossimKakaduReaderFactory::instance());
+         ossimImageHandlerRegistry::instance()->
+         registerFactory(ossimKakaduJpipHandlerFactory::instance());
+      }
+
+
+      if(ossimString(kwl.find("overview_builder_factory.location")).downcase() == "front")
+      {
+         /* Register the overview buildeds. */
+         ossimOverviewBuilderFactoryRegistry::instance()->
+         registerFactoryToFront(ossimKakaduOverviewBuilderFactory::instance());
+      }
+      else 
+      {
+         /* Register the overview buildeds. */
+         ossimOverviewBuilderFactoryRegistry::instance()->
+         registerFactory(ossimKakaduOverviewBuilderFactory::instance(),
+                         false);
+      }
+      
+      if(ossimString(kwl.find("writer_factory.location")).downcase() == "front")
+      {
+         /* Register the writers... */
+         ossimImageWriterFactoryRegistry::instance()->
+         registerFactoryToFront(ossimKakaduWriterFactory::instance());
+         
+      }
+      else 
+      {
+      
+         /* Register the writers... */
+         ossimImageWriterFactoryRegistry::instance()->
+         registerFactory(ossimKakaduWriterFactory::instance());
+         
+      }
+      if(ossimString(kwl.find("projection_factory.location")).downcase() == "front")
+      {
+         ossimProjectionFactoryRegistry::instance()->registerFactoryToFront(ossimJpipProjectionFactory::instance());
+         
+      }
+      else
+      {
+         ossimProjectionFactoryRegistry::instance()->registerFactory(ossimJpipProjectionFactory::instance());
+      }
+      if(ossimString(kwl.find("info_factory.location")).downcase() == "front")
+      {
+         ossimInfoFactoryRegistry::instance()->registerFactoryToFront(ossimKakaduJpipInfoFactory::instance());
+         
+      }
+      else
+      {
+         ossimInfoFactoryRegistry::instance()->registerFactory(ossimKakaduJpipInfoFactory::instance());
+      }
+      if(ossimString(kwl.find("image_geometry_factory.location")).downcase() == "front")
+      {
+         ossimImageGeometryRegistry::instance()->registerFactoryToFront(ossimKakaduJpipImageGeometryFactory::instance());
+      }
+      else
+      {
+         ossimImageGeometryRegistry::instance()->registerFactory(ossimKakaduJpipImageGeometryFactory::instance());
+      }
+      setDescription(theDescription);
+   }
+   
+   /* Note symbols need to be exported on windoze... */ 
+   OSSIM_PLUGINS_DLL void ossimSharedLibraryFinalize()
+   {
+      ossimImageHandlerRegistry::instance()->
+         unregisterFactory(ossimKakaduReaderFactory::instance());
+      
+      ossimOverviewBuilderFactoryRegistry::instance()->
+         unregisterFactory(ossimKakaduOverviewBuilderFactory::instance());
+      
+      ossimImageWriterFactoryRegistry::instance()->
+         unregisterFactory(ossimKakaduWriterFactory::instance());
+      
+      ossimImageGeometryRegistry::instance()->unregisterFactory(ossimKakaduJpipImageGeometryFactory::instance());
+
+   }
+}
diff --git a/ossim_plugins/kakadu/ossimKakaduReaderFactory.cpp b/ossim_plugins/kakadu/ossimKakaduReaderFactory.cpp
new file mode 100644
index 0000000..2cbd0ae
--- /dev/null
+++ b/ossim_plugins/kakadu/ossimKakaduReaderFactory.cpp
@@ -0,0 +1,267 @@
+//----------------------------------------------------------------------------
+//
+// License:  See top level LICENSE.txt file
+//
+// Author:  David Burken
+//
+// Description: Factory for OSSIM JPEG 2000 (J2k) reader using kakadu library.
+//----------------------------------------------------------------------------
+// $Id: ossimKakaduReaderFactory.cpp 22884 2014-09-12 13:14:35Z dburken $
+
+#include "ossimKakaduReaderFactory.h"
+#include "ossimKakaduJp2Reader.h"
+#include "ossimKakaduJ2kReader.h"
+#include "ossimKakaduNitfReader.h"
+#include <ossim/base/ossimKeywordlist.h>
+#include <ossim/base/ossimKeywordNames.h>
+#include <ossim/base/ossimRefPtr.h>
+#include <ossim/base/ossimString.h>
+#include <ossim/base/ossimTrace.h>
+#include <ossim/imaging/ossimImageHandler.h>
+
+static const ossimTrace traceDebug( ossimString("ossimKakaduReaderFactory:debug") );
+
+class ossimImageHandler;
+
+RTTI_DEF1(ossimKakaduReaderFactory,
+          "ossimKakaduReaderFactory",
+          ossimImageHandlerFactoryBase);
+
+ossimKakaduReaderFactory::~ossimKakaduReaderFactory()
+{
+}
+
+ossimKakaduReaderFactory* ossimKakaduReaderFactory::instance()
+{
+   static ossimKakaduReaderFactory inst;
+   return &inst;
+}
+
+ossimImageHandler* ossimKakaduReaderFactory::open(const ossimFilename& fileName,
+                                                  bool openOverview)const
+{
+   static const char* M = "ossimKakaduReaderFactory::open(filename) -- ";
+   if(traceDebug())
+      ossimNotify(ossimNotifyLevel_DEBUG)<<M<<"Entered with filename <"<<fileName<<">"  ;
+
+   ossimRefPtr<ossimImageHandler> reader = 0; 
+   while (true)
+   {
+      if (hasExcludedExtension(fileName))  break;
+
+      if (traceDebug()) ossimNotify(ossimNotifyLevel_DEBUG)<<M<< "Trying ossimKakaduNitfReader...";
+      reader = new ossimKakaduNitfReader;
+      reader->setOpenOverviewFlag(openOverview);
+      if(reader->open(fileName))  break;
+
+      if (traceDebug()) ossimNotify(ossimNotifyLevel_DEBUG)<<M<< "Trying ossimKakaduJp2Reader...";
+      reader = new ossimKakaduJp2Reader;
+      reader->setOpenOverviewFlag(openOverview);
+      if(reader->open(fileName))  break;
+
+      if (traceDebug()) ossimNotify(ossimNotifyLevel_DEBUG)<<M<< "Trying ossimKakaduJ2kReader...";
+      reader = new ossimKakaduJ2kReader;
+      reader->setOpenOverviewFlag(openOverview);
+      if(reader->open(fileName))  break;
+
+      reader = 0;
+      break;
+   } 
+   
+   if (traceDebug())
+   {
+      if (reader.valid())
+         ossimNotify(ossimNotifyLevel_DEBUG)<<M<< "   SUCCESS" << std::endl;
+      else
+         ossimNotify(ossimNotifyLevel_DEBUG)<<M<< "   Open FAILED" << std::endl;
+   }
+ 
+   return reader.release();
+}
+
+ossimImageHandler* ossimKakaduReaderFactory::open(const ossimKeywordlist& kwl,
+                                                  const char* prefix)const
+{
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimKakaduReaderFactory::open(kwl, prefix) DEBUG: entered..."
+         << std::endl;
+   }
+
+   ossimRefPtr<ossimImageHandler> reader = 0; 
+
+   // To save time check the file name first.
+   const char* lookup = kwl.find(prefix, ossimKeywordNames::FILENAME_KW);
+   if (!lookup)
+   {
+      // Deprecated...
+      lookup = kwl.find(prefix, ossimKeywordNames::IMAGE_FILE_KW);
+   }
+
+   if (lookup)
+   {
+      ossimFilename f = lookup;
+      if ( hasExcludedExtension(f) == false )
+      {
+         reader = new ossimKakaduNitfReader;
+         if(reader->loadState(kwl, prefix) == false)
+         {
+            reader = 0;
+         }
+         
+         if (!reader)
+         {
+            reader = new ossimKakaduJp2Reader;
+            if(reader->loadState(kwl, prefix) == false)
+            {
+               reader = 0;
+            }
+         }
+         
+         if (!reader)
+         {
+            reader = new ossimKakaduJ2kReader;
+            if(reader->loadState(kwl, prefix) == false)
+            {
+               reader = 0;
+            }
+         }
+      }
+   }
+
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimKakaduReaderFactory::open(kwl, prefix) DEBUG: leaving..."
+         << std::endl;
+   }
+   
+   return reader.release();
+}
+
+ossimRefPtr<ossimImageHandler> ossimKakaduReaderFactory::openOverview(
+   const ossimFilename& file ) const
+{
+   ossimRefPtr<ossimImageHandler> result = 0;
+   if ( file.size() )
+   {
+      result = new ossimKakaduNitfReader;
+
+      result->setOpenOverviewFlag( false ); // Always false...
+
+      if( result->open( file ) == false )
+      {
+         result = 0;
+      }
+   }
+   return result;
+}
+
+ossimObject* ossimKakaduReaderFactory::createObject(
+   const ossimString& typeName)const
+{
+   ossimRefPtr<ossimObject> result = 0;
+   if(typeName == "ossimKakaduNitfReader")
+   {
+      result = new ossimKakaduNitfReader;
+   }
+   else if(typeName == "ossimKakaduJp2Reader")
+   {
+      result = new ossimKakaduJp2Reader;
+   }
+   else if(typeName == "ossimKakaduJ2kReader")
+   {
+      result =  new ossimKakaduJ2kReader;
+   }
+   return result.release();
+}
+
+ossimObject* ossimKakaduReaderFactory::createObject(
+   const ossimKeywordlist& kwl,
+   const char* prefix)const
+{
+   return this->open(kwl, prefix);
+}
+ 
+void ossimKakaduReaderFactory::getTypeNameList(
+   std::vector<ossimString>& typeList)const
+{
+   typeList.push_back(ossimString("ossimKakaduNitfReader"));
+   typeList.push_back(ossimString("ossimKakaduJp2Reader"));
+   typeList.push_back(ossimString("ossimKakaduJ2kReader"));
+}
+
+void ossimKakaduReaderFactory::getSupportedExtensions(
+   ossimImageHandlerFactoryBase::UniqueStringList& extensionList)const
+{
+   extensionList.push_back(ossimString("j2k"));
+   extensionList.push_back(ossimString("jp2"));   
+}
+
+bool ossimKakaduReaderFactory::hasExcludedExtension(
+   const ossimFilename& file) const
+{
+   bool result = false;
+   ossimString ext = file.ext().downcase();
+   if ( (ext == "tif")  ||
+        (ext == "tiff") ||
+        (ext == "jpg")  ||
+        (ext == "jpeg") ||
+        (ext == "png") )
+   {
+      result = true;
+   }
+   return result;
+}
+/**
+ *
+ * Will add to the result list any handler that supports the passed in extensions
+ *
+ */
+void ossimKakaduReaderFactory::getImageHandlersBySuffix(ossimImageHandlerFactoryBase::ImageHandlerList& result,
+                                                        const ossimString& ext)const
+{
+   ossimString testExt = ext.downcase();
+   if(testExt == "jp2")
+   {
+      result.push_back(new ossimKakaduJp2Reader);
+   }
+   else if(testExt == "ntf")
+   {
+      result.push_back(new ossimKakaduNitfReader);
+   }
+   else if(testExt == "nitf")
+   {
+      result.push_back(new ossimKakaduNitfReader);
+   }
+}
+/**
+ *
+ * Will add to the result list and handler that supports the passed in mime type
+ *
+ */
+void ossimKakaduReaderFactory::getImageHandlersByMimeType(ossimImageHandlerFactoryBase::ImageHandlerList& result,
+                                                          const ossimString& mimeType)const
+{
+   ossimString test(mimeType.begin(), mimeType.begin()+6);
+   if(test == "image/")
+   {
+      ossimString mimeTypeTest(mimeType.begin() + 6, mimeType.end());
+      if(mimeTypeTest == "jp2")
+      {
+         result.push_back(new ossimKakaduJp2Reader);
+      }
+      else if(mimeTypeTest == "nitf")
+      {
+         result.push_back(new ossimKakaduNitfReader);
+      }
+   }
+}
+
+
+ossimKakaduReaderFactory::ossimKakaduReaderFactory(){}
+
+ossimKakaduReaderFactory::ossimKakaduReaderFactory(const ossimKakaduReaderFactory&){}
+
+void ossimKakaduReaderFactory::operator=(const ossimKakaduReaderFactory&){}
diff --git a/ossim_plugins/kakadu/ossimKakaduReaderFactory.h b/ossim_plugins/kakadu/ossimKakaduReaderFactory.h
new file mode 100644
index 0000000..3023a37
--- /dev/null
+++ b/ossim_plugins/kakadu/ossimKakaduReaderFactory.h
@@ -0,0 +1,131 @@
+//----------------------------------------------------------------------------
+//
+// License:  See top level LICENSE.txt file
+//
+// Author:  David Burken
+//
+// Description: Factory for OSSIM JPEG 2000 (J2k) reader using kakadu library.
+//----------------------------------------------------------------------------
+// $Id: ossimKakaduReaderFactory.h 22884 2014-09-12 13:14:35Z dburken $
+
+#ifndef ossimKakaduReaderFactory_HEADER
+#define ossimKakaduReaderFactory_HEADER 1
+
+#include <ossim/imaging/ossimImageHandlerFactoryBase.h>
+
+class ossimString;
+class ossimFilename;
+class ossimKeywordlist;
+
+/** @brief Factory for J2K image reader. */
+class ossimKakaduReaderFactory : public ossimImageHandlerFactoryBase
+{
+public:
+
+   /** @brief virtual destructor */
+   virtual ~ossimKakaduReaderFactory();
+
+   /**
+    * @brief static method to return instance (the only one) of this class.
+    * @return pointer to instance of this class.
+    */
+   static ossimKakaduReaderFactory* instance();
+
+   /**
+    * @brief open that takes a file name.
+    * @param file The file to open.
+    * @param openOverview If true image handler will attempt to open overview.
+    * default = true
+    * @return pointer to image handler on success, NULL on failure.
+    */
+   virtual ossimImageHandler* open(const ossimFilename& fileName,
+                                   bool openOverview=true) const;
+
+   /**
+    * @brief Open overview that takes a file name.
+    * 
+    * @param file File to open.
+    * 
+    * @return ossimRefPtr to image handler on success or null on failure.
+    */
+   virtual ossimImageHandler* open(const ossimKeywordlist& kwl,
+                                   const char* prefix=0)const;
+   
+   /**
+    * @brief Open overview that takes a file name.
+    *
+    * @param file File to open.
+    *
+    * @return ossimRefPtr to image handler on success or null on failure.
+    */
+   virtual ossimRefPtr<ossimImageHandler> openOverview(
+      const ossimFilename& file ) const;   
+   
+   /**
+    * @brief createObject that takes a class name (ossimKakaduReader)
+    * @param typeName Should be "ossimKakaduReader".
+    * @return pointer to image writer on success, NULL on failure.
+    */
+   virtual ossimObject* createObject(const ossimString& typeName)const;
+   
+   /**
+    * @brief Creates and object given a keyword list and prefix.
+    * @param kwl The keyword list.
+    * @param prefix the keyword list prefix.
+    * @return pointer to image handler on success, NULL on failure.
+    */
+   virtual ossimObject* createObject(const ossimKeywordlist& kwl,
+                                     const char* prefix=0)const;
+   
+   /**
+    * @brief Adds ossimKakaduWriter to the typeList.
+    * @param typeList List to add to.
+    */
+   virtual void getTypeNameList(std::vector<ossimString>& typeList)const;
+
+   /**
+    * @brief Method to add supported extension to the list, like "jp2".
+    *
+    * @param extensionList The list to add to.
+    */
+   virtual void getSupportedExtensions(
+      ossimImageHandlerFactoryBase::UniqueStringList& extensionList)const;
+  
+   /**
+    *
+    * Will add to the result list any handler that supports the passed in extensions
+    *
+    */
+   virtual void getImageHandlersBySuffix(ossimImageHandlerFactoryBase::ImageHandlerList& result,
+                                         const ossimString& ext)const;
+   /**
+    *
+    * Will add to the result list and handler that supports the passed in mime type
+    *
+    */
+   virtual void getImageHandlersByMimeType(ossimImageHandlerFactoryBase::ImageHandlerList& result,
+                                           const ossimString& mimeType)const;
+protected:
+
+   /**
+    * @brief Method to weed out extensions that this plugin knows it does
+    * not support.  This is to avoid a costly open on say a tiff or jpeg that
+    * is not handled by this plugin.
+    *
+    * @return true if extension, false if not.
+    */
+   bool hasExcludedExtension(const ossimFilename& file) const;
+   
+   /** @brief hidden from use default constructor */
+   ossimKakaduReaderFactory();
+
+   /** @brief hidden from use copy constructor */
+   ossimKakaduReaderFactory(const ossimKakaduReaderFactory&);
+
+   /** @brief hidden from use copy constructor */
+   void operator=(const ossimKakaduReaderFactory&);
+
+TYPE_DATA
+};
+
+#endif /* end of #ifndef ossimKakaduReaderFactory_HEADER */
diff --git a/ossim_plugins/kakadu/ossimKakaduWriterFactory.cpp b/ossim_plugins/kakadu/ossimKakaduWriterFactory.cpp
new file mode 100644
index 0000000..5dea69c
--- /dev/null
+++ b/ossim_plugins/kakadu/ossimKakaduWriterFactory.cpp
@@ -0,0 +1,173 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author:  David Burken
+//
+// Description: Factory for OSSIM Kakadu writers.
+//----------------------------------------------------------------------------
+// $Id: ossimKakaduWriterFactory.cpp 23664 2015-12-14 14:17:27Z dburken $
+
+#include "ossimKakaduWriterFactory.h"
+#include "ossimKakaduJp2Writer.h"
+#include "ossimKakaduNitfWriter.h"
+#include <ossim/base/ossimKeywordNames.h>
+#include <ossim/base/ossimRefPtr.h>
+#include <ossim/imaging/ossimImageFileWriter.h>
+
+RTTI_DEF1(ossimKakaduWriterFactory,
+          "ossimKakaduWriterFactory",
+          ossimImageWriterFactoryBase);
+
+ossimKakaduWriterFactory::~ossimKakaduWriterFactory()
+{
+}
+
+ossimKakaduWriterFactory* ossimKakaduWriterFactory::instance()
+{
+   static ossimKakaduWriterFactory inst;
+   return &inst;
+}
+
+ossimImageFileWriter* ossimKakaduWriterFactory::createWriterFromExtension(
+   const ossimString& fileExtension)const
+{
+   ossimImageFileWriter* writer = 0;
+
+#if 0 /* Can't use as we don't know if the user wants a compressed nitf. */
+   if( (fileExtension == "ntf") || (fileExtension == "nitf") )
+   {
+      writer = new ossimKakaduNitfWriter;
+   }
+#endif
+
+   if(fileExtension == "jp2")
+   {
+      writer = new ossimKakaduJp2Writer;
+   }
+
+   return writer;
+}
+
+ossimImageFileWriter*
+ossimKakaduWriterFactory::createWriter(const ossimKeywordlist& kwl,
+                                       const char *prefix)const
+{
+   ossimRefPtr<ossimImageFileWriter> writer = 0;
+   const char* type = kwl.find(prefix, ossimKeywordNames::TYPE_KW);
+   if (type)
+   {
+      writer = createWriter(ossimString(type));
+      if (writer.valid())
+      {
+         if (writer->loadState(kwl, prefix) == false)
+         {
+            writer = 0;
+         }
+      }
+   }
+   return writer.release();
+}
+
+ossimImageFileWriter* ossimKakaduWriterFactory::createWriter(
+   const ossimString& typeName)const
+{
+   ossimRefPtr<ossimImageFileWriter> writer = 0;
+   if ( (typeName == "ossim_kakadu_nitf_j2k") ||
+        ( typeName == "ossimKakaduNitfWriter") )
+   {
+      writer = new ossimKakaduNitfWriter;
+   }
+   else if ( (typeName == "ossim_kakadu_jp2") ||
+             (typeName == "ossimKakaduJp2Writer") )
+   {
+      writer = new ossimKakaduJp2Writer;
+   }
+   else
+   {
+      // See if the type name is supported by the writer.
+
+      //---
+      // Note: Will not do ossimKakaduNitfWriter here as user may want a
+      // non-licensed solution.
+      //---
+
+      writer = new ossimKakaduJp2Writer;
+      if ( writer->hasImageType(typeName) == false )
+      {
+         writer = 0;
+      }
+   }
+   return writer.release();
+}
+
+ossimObject* ossimKakaduWriterFactory::createObject(
+   const ossimKeywordlist& kwl, const char *prefix)const
+{
+   return createWriter(kwl, prefix);
+}
+
+ossimObject* ossimKakaduWriterFactory::createObject(
+   const ossimString& typeName) const
+{
+   return createWriter(typeName);
+}
+
+void ossimKakaduWriterFactory::getExtensions(
+   std::vector<ossimString>& result)const
+{
+   result.push_back("jp2");
+   result.push_back("ntf");
+}
+
+void ossimKakaduWriterFactory::getTypeNameList(std::vector<ossimString>& typeList)const
+{
+   typeList.push_back(ossimString("ossimKakaduNitfWriter"));
+   typeList.push_back(ossimString("ossimKakaduJp2Writer"));
+}
+
+//---
+// Adds our writers to the list of writers...
+//---
+void ossimKakaduWriterFactory::getImageTypeList(std::vector<ossimString>& imageTypeList)const
+{
+   imageTypeList.push_back( ossimString("ossim_kakadu_nitf_j2k") );
+   imageTypeList.push_back( ossimString("ossim_kakadu_jp2") );
+}
+
+void ossimKakaduWriterFactory::getImageFileWritersBySuffix(
+   ossimImageWriterFactoryBase::ImageFileWriterList& result,
+   const ossimString& ext) const
+{
+   ossimString testExt = ext.downcase();
+   if(testExt == "jp2")
+   {
+      result.push_back(new ossimKakaduJp2Writer);
+   }
+   else if(testExt == "ntf")
+   {
+      result.push_back(new ossimKakaduNitfWriter);
+   }
+}
+
+void ossimKakaduWriterFactory::getImageFileWritersByMimeType(ossimImageWriterFactoryBase::ImageFileWriterList& result,
+                                           const ossimString& mimeType)const
+{
+   if(mimeType == "image/jp2")
+   {
+      result.push_back(new ossimKakaduJp2Writer);
+   }
+}
+
+ossimKakaduWriterFactory::ossimKakaduWriterFactory(){}
+
+ossimKakaduWriterFactory::ossimKakaduWriterFactory(const ossimKakaduWriterFactory&){}
+
+void ossimKakaduWriterFactory::operator=(const ossimKakaduWriterFactory&){}
+
+
+
+
+
diff --git a/ossim_plugins/kakadu/ossimKakaduWriterFactory.h b/ossim_plugins/kakadu/ossimKakaduWriterFactory.h
new file mode 100644
index 0000000..4cd550d
--- /dev/null
+++ b/ossim_plugins/kakadu/ossimKakaduWriterFactory.h
@@ -0,0 +1,113 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author:  David Burken
+//
+// Description: Factory for OSSIM Kakadu writers.
+//----------------------------------------------------------------------------
+// $Id: ossimKakaduWriterFactory.h 23664 2015-12-14 14:17:27Z dburken $
+
+#ifndef ossimKakaduWriterFactory_HEADER
+#define ossimKakaduWriterFactory_HEADER 1
+
+#include <ossim/imaging/ossimImageWriterFactoryBase.h>
+
+class ossimImageFileWriter;
+class ossimKeywordlist;
+class ossimImageWriterFactory;
+
+/** @brief Factory for Kakadu based image writers. */
+class ossimKakaduWriterFactory: public ossimImageWriterFactoryBase
+{   
+public:
+
+   /** @brief virtual destructor */
+   virtual ~ossimKakaduWriterFactory();
+
+   /**
+    * @brief static method to return instance (the only one) of this class.
+    * @return pointer to instance of this class.
+    */
+   static ossimKakaduWriterFactory* instance();
+
+   /**
+    * @brief Creates a writer from extension like "ntf".
+    * @param fileExtension "ntf"
+    */
+   virtual ossimImageFileWriter *createWriterFromExtension(
+      const ossimString& fileExtension)const;
+
+   /**
+    * @brief Create that takes a keyword list and prefix.
+    * @param kwl The keyword list.
+    * @param prefix the keyword list prefix.
+    * @return pointer to image handler on success, NULL on failure.
+    */
+   virtual ossimImageFileWriter* createWriter(const ossimKeywordlist& kwl,
+                                              const char *prefix=0)const;
+
+   /**
+    * @brief createWriter that takes a class name (ossimKakaduWriter)
+    * @param kwl The keyword list.
+    * @param prefix the keyword list prefix.
+    * @return pointer to image writer on success, NULL on failure.
+    */
+   virtual ossimImageFileWriter* createWriter(const ossimString& typeName)const;
+
+   /**
+    * @brief Creates and object given a keyword list.
+    * @param kwl The keyword list.
+    * @param prefix the keyword list prefix.
+    * @return pointer to image writer on success, NULL on failure.
+    */
+   virtual ossimObject* createObject(const ossimKeywordlist& kwl,
+                                     const char *prefix=0)const;
+
+   /**
+    * @brief createObject that takes a class name (ossimKakaduWriter)
+    * @param typeName Should be "ossimKakaduReader".
+    * @return pointer to image writer on success, NULL on failure.
+    */
+   virtual ossimObject* createObject(const ossimString& typeName)const;
+
+
+   /**
+    * @brief Adds "ntf" to list.
+    * @param extList List to add to.
+    */
+   virtual void getExtensions(std::vector<ossimString>& extList)const;
+
+   /**
+    * @brief Adds "ossimKakaduWriter" to list.
+    * @param typeList List to add to.
+    */
+   virtual void getTypeNameList(std::vector<ossimString>& typeList)const;
+   
+   /**
+    * @brief Adds "ossim_kakada_nitf_j2k" to writer list.
+    * @param imageTypeList List to append to.
+    */
+   virtual void getImageTypeList(std::vector<ossimString>& imageTypeList)const;
+   
+   virtual void getImageFileWritersBySuffix(ossimImageWriterFactoryBase::ImageFileWriterList& result,
+                                            const ossimString& ext)const;
+   virtual void getImageFileWritersByMimeType(ossimImageWriterFactoryBase::ImageFileWriterList& result,
+                                              const ossimString& mimeType)const;
+protected:
+   /** @brief hidden from use default constructor */
+   ossimKakaduWriterFactory();
+
+   /** @brief hidden from use copy constructor */
+   ossimKakaduWriterFactory(const ossimKakaduWriterFactory&);
+
+   /** @brief hidden from use copy constructor */
+   void operator=(const ossimKakaduWriterFactory&);
+
+TYPE_DATA
+};
+
+#endif /* end of #ifndef ossimKakaduWriterFactory_HEADER */
+
diff --git a/ossim_plugins/kmlsuperoverlay/CMakeLists.txt b/ossim_plugins/kmlsuperoverlay/CMakeLists.txt
new file mode 100644
index 0000000..17ebb3e
--- /dev/null
+++ b/ossim_plugins/kmlsuperoverlay/CMakeLists.txt
@@ -0,0 +1,42 @@
+set(LIB_NAME ossimkmlsuperoverlay_plugin)
+MESSAGE( "************** LIBRARY SETUP FOR ossimkmlsuperoverlay_plugin******************")
+
+# Include ossim cmake stuff:
+include(OssimVersion)
+include(OssimCommonVariables)
+include(OssimUtilities)
+
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
+
+SET(requiredLibs)
+
+find_package(MiniZip)
+if(MINIZIP_FOUND)
+   include_directories(${MINIZIP_INCLUDE_DIR})
+   set(requiredLibs ${requiredLibs} ${MINIZIP_LIBRARIES})
+else(MINIZIP_FOUND)
+   message(FATAL_ERROR "Could not find minizip")
+endif(MINIZIP_FOUND)
+
+FILE(GLOB_RECURSE OSSIMPLUGIN_SRCS *.cpp)
+FILE(GLOB_RECURSE OSSIMPLUGIN_HEADERS *.h)
+
+####
+# OSSIMPLUGINSMAKINGDLL controls dll linkage on windows.  
+# Adding this sets OSSIM_PLUGINS_DLL #define TO "__declspec(dllexport)".
+###
+add_definitions("-DOSSIMPLUGINSMAKINGDLL")
+
+# Adjust the install library path:
+if(OSSIM_INSTALL_PLUGINS_WITH_VERSION)
+   set(INSTALL_LIBRARY_DIR   "${INSTALL_LIBRARY_DIR}/ossim-${OSSIM_VERSION}/plugins")
+else(OSSIM_INSTALL_PLUGINS_WITH_VERSION)
+   set(INSTALL_LIBRARY_DIR   "${INSTALL_LIBRARY_DIR}/ossim/plugins")
+endif(OSSIM_INSTALL_PLUGINS_WITH_VERSION)
+
+OSSIM_LINK_LIBRARY(${LIB_NAME}
+                   COMPONENT_NAME ossim TYPE "${OSSIM_PLUGIN_LINK_TYPE}"
+		   LIBRARIES ${OSSIM_LIBRARY} ${requiredLibs}
+                   HEADERS "${OSSIMPLUGIN_HEADERS}"
+		   SOURCE_FILES "${OSSIMPLUGIN_SRCS}"
+                   INSTALL_LIB)
diff --git a/ossim_plugins/kmlsuperoverlay/ossimKmlSuperOverlayPluginInit.cpp b/ossim_plugins/kmlsuperoverlay/ossimKmlSuperOverlayPluginInit.cpp
new file mode 100644
index 0000000..65e33e2
--- /dev/null
+++ b/ossim_plugins/kmlsuperoverlay/ossimKmlSuperOverlayPluginInit.cpp
@@ -0,0 +1,83 @@
+//----------------------------------------------------------------------------
+//
+// License:  See top level LICENSE.txt file
+//
+// Author:  Mingjie Su
+//
+// Description: OSSIM KmlSuperOverlay plugin initialization
+// code.
+//
+//----------------------------------------------------------------------------
+// $Id: ossimKmlSuperOverlayPluginInit.cpp 2470 2011-04-26 15:32:19Z david.burken $
+
+#include <ossim/plugin/ossimSharedObjectBridge.h>
+#include "../ossimPluginConstants.h"
+// #include <ossim/imaging/ossimImageHandlerRegistry.h>
+#include <ossim/imaging/ossimImageWriterFactoryRegistry.h>
+#include <ossim/imaging/ossimOverviewBuilderFactoryRegistry.h>
+
+// #include "ossimKmlSuperOverlayReaderFactory.h"
+#include "ossimKmlSuperOverlayWriterFactory.h"
+
+static void setDescription(ossimString& description)
+{
+   description = "KmlSuperOverlay writer plugin\n\n";
+   // description = "KmlSuperOverlay reader plugin\n\n";
+}
+
+extern "C"
+{
+   ossimSharedObjectInfo  myInfo;
+   ossimString theDescription;
+   std::vector<ossimString> theObjList;
+
+   const char* getDescription()
+   {
+      return theDescription.c_str();
+   }
+
+   int getNumberOfClassNames()
+   {
+      return (int)theObjList.size();
+   }
+
+   const char* getClassName(int idx)
+   {
+      if(idx < (int)theObjList.size())
+      {
+         return theObjList[0].c_str();
+      }
+      return (const char*)0;
+   }
+
+   /* Note symbols need to be exported on windoze... */ 
+   OSSIM_PLUGINS_DLL void ossimSharedLibraryInitialize(
+      ossimSharedObjectInfo** info)
+   {    
+      myInfo.getDescription = getDescription;
+      myInfo.getNumberOfClassNames = getNumberOfClassNames;
+      myInfo.getClassName = getClassName;
+      
+      *info = &myInfo;
+
+      /* Register the readers... */
+      // ossimImageHandlerRegistry::instance()->
+      //    registerFactory(ossimKmlSuperOverlayReaderFactory::instance());
+      
+      /* Register the writers... */
+      ossimImageWriterFactoryRegistry::instance()->
+         registerFactory(ossimKmlSuperOverlayWriterFactory::instance());
+      
+      setDescription(theDescription);
+   }
+   
+   /* Note symbols need to be exported on windoze... */
+   OSSIM_PLUGINS_DLL void ossimSharedLibraryFinalize()
+   { 
+      // ossimImageHandlerRegistry::instance()->
+      //    unregisterFactory(ossimKmlSuperOverlayReaderFactory::instance());
+   
+      ossimImageWriterFactoryRegistry::instance()->
+         unregisterFactory(ossimKmlSuperOverlayWriterFactory::instance());
+   }
+}
diff --git a/ossim_plugins/kmlsuperoverlay/ossimKmlSuperOverlayReader.cpp b/ossim_plugins/kmlsuperoverlay/ossimKmlSuperOverlayReader.cpp
new file mode 100644
index 0000000..c476b69
--- /dev/null
+++ b/ossim_plugins/kmlsuperoverlay/ossimKmlSuperOverlayReader.cpp
@@ -0,0 +1,438 @@
+//*******************************************************************
+//
+// License:  See top level LICENSE.txt file.
+//
+// Author:  Mingjie Su, Harsh Govind
+//
+// Description:
+//
+// Contains class implementation for the class "ossimKmlSuperOverlayReader".
+//
+//*******************************************************************
+//  $Id: ossimKmlSuperOverlayReader.cpp 2178 2011-02-17 18:38:30Z ming.su $
+
+#include "ossimKmlSuperOverlayReader.h"
+
+//Std Includes
+#include <cstring> /* strdup */
+#include <iostream>
+#include <sstream>
+#include <string>
+
+//Minizip Includes
+#include <minizip/unzip.h>
+
+//Ossim Includes
+#include <ossim/base/ossimTrace.h>
+#include <ossim/base/ossimNotify.h>
+#include <ossim/base/ossimIpt.h>
+#include <ossim/base/ossimDpt.h>
+#include <ossim/base/ossimXmlDocument.h>
+#include <ossim/base/ossimFilename.h>
+#include <ossim/base/ossimKeywordlist.h>
+#include <ossim/base/ossimKeywordNames.h>
+#include <ossim/imaging/ossimImageGeometry.h>
+#include <ossim/projection/ossimProjectionFactoryRegistry.h>
+#include <ossim/projection/ossimEquDistCylProjection.h>
+
+RTTI_DEF1(ossimKmlSuperOverlayReader, "ossimKmlSuperOverlayReader", ossimImageHandler);
+
+static ossimTrace traceDebug("ossimKmlSuperOverlayReader:debug");
+
+//*******************************************************************
+// Public Constructor:
+//*******************************************************************
+ossimKmlSuperOverlayReader::ossimKmlSuperOverlayReader()
+   :ossimImageHandler(),
+   m_xmlDocument(0),
+   theImageBound()
+{
+}
+
+//*******************************************************************
+// Destructor:
+//*******************************************************************
+ossimKmlSuperOverlayReader::~ossimKmlSuperOverlayReader()
+{
+   close();
+}
+
+//*******************************************************************
+// Public Method:
+//*******************************************************************
+bool ossimKmlSuperOverlayReader::open()
+{
+   // const char* MODULE = "ossimKmlSuperOverlayReader::open";
+   bool result = false;
+ 
+   if(isOpen())
+   {
+      close();
+   }
+
+   if (theImageFile.ext().downcase() == "kmz")
+   {
+      result = getTopLevelKmlFileInfo();
+      if (result == false)
+      {
+         return result;
+      }
+   }
+   else
+   {
+      m_xmlDocument = new ossimXmlDocument(theImageFile);
+   }
+
+   if ( m_xmlDocument.valid() )
+   {
+      ossimRefPtr<ossimXmlNode> rootNode = m_xmlDocument->getRoot(); 
+      if (rootNode.valid())
+      {
+         std::vector<ossimRefPtr<ossimXmlNode> > nodes = rootNode->getChildNodes();
+         result = isKmlSuperOverlayFile(nodes);
+
+         if (result == false) //let gdal kml handle vector kml file
+         {
+            return result; 
+         }
+
+         ossim_float64 north = 0.0;
+         ossim_float64 south = 0.0;
+         ossim_float64 east = 0.0;
+         ossim_float64 west = 0.0;
+         result = getCoordinate(nodes, north, south, east, west);
+         
+         if (result == false)
+         {
+            return result;
+         }
+
+         if (!theImageGeometry.valid())
+         {
+            theImageGeometry = new ossimImageGeometry(0, createDefaultProj(north, south, east, west));
+            if (theImageGeometry.valid())
+            {
+               result = true;
+
+               theImageBound.makeNan();
+
+               //if the projection is default or geographic, uses the bounding of the OGR Layer
+               vector<ossimGpt> points;
+               points.push_back(ossimGpt(north, west));
+               points.push_back(ossimGpt(north, east));
+               points.push_back(ossimGpt(south, east));
+               points.push_back(ossimGpt(south, west));
+
+
+               std::vector<ossimDpt> rectTmp;
+               rectTmp.resize(points.size());
+               for(std::vector<ossimGpt>::size_type index=0; index < points.size(); ++index)
+               {
+                  theImageGeometry->worldToLocal(points[(int)index], rectTmp[(int)index]);
+               }
+
+               ossimDrect rect = ossimDrect(rectTmp[0],
+                  rectTmp[1],
+                  rectTmp[2],
+                  rectTmp[3]);
+
+               theImageBound = rect;
+            }
+            else
+            {
+               result = false;
+            }
+         }
+      }
+      else
+      {
+         result = false;
+      }
+   }
+   else
+   {
+      result = false;
+   }
+
+   return result;
+}
+
+//*******************************************************************
+// Public method:
+//*******************************************************************
+bool ossimKmlSuperOverlayReader::saveState(ossimKeywordlist& kwl,
+                                         const char* prefix) const
+{
+   return ossimImageHandler::saveState(kwl, prefix);
+}
+
+//*******************************************************************
+// Public method:
+//*******************************************************************
+bool ossimKmlSuperOverlayReader::loadState(const ossimKeywordlist& kwl, const char* prefix)
+{
+   return ossimImageHandler::loadState(kwl, prefix);
+}
+
+ossimRefPtr<ossimImageGeometry> ossimKmlSuperOverlayReader::getInternalImageGeometry() const
+{
+   return theImageGeometry;
+}
+
+void ossimKmlSuperOverlayReader::close()
+{
+   if (theImageGeometry.valid())
+   {
+      theImageGeometry = 0;
+   }
+   if (m_xmlDocument.valid())
+   {
+      m_xmlDocument = 0;
+   }
+}
+
+ossimRefPtr<ossimImageData> ossimKmlSuperOverlayReader::getTile(
+   const ossimIrect& /* tileRect */, ossim_uint32 /* resLevel */)
+{
+   return 0;
+}
+
+ossim_uint32 ossimKmlSuperOverlayReader::getNumberOfInputBands() const
+{
+   return 0;
+}
+
+ossim_uint32 ossimKmlSuperOverlayReader::getNumberOfOutputBands() const
+{
+   return 0;
+}
+
+ossim_uint32 ossimKmlSuperOverlayReader::getImageTileHeight() const
+{
+   return 0;
+}
+
+ossim_uint32 ossimKmlSuperOverlayReader::getImageTileWidth() const
+{
+   return 0;
+}
+
+ossim_uint32 ossimKmlSuperOverlayReader::getNumberOfLines(ossim_uint32 /* reduced_res_level */ ) const
+{
+   return theImageBound.height();
+}
+
+ossim_uint32 ossimKmlSuperOverlayReader::getNumberOfSamples(ossim_uint32 /* reduced_res_level */ ) const
+{ 
+   return theImageBound.width();
+}
+
+ossimIrect ossimKmlSuperOverlayReader::getImageRectangle(ossim_uint32 /* reduced_res_level */ ) const
+{
+   return theImageBound;
+}
+
+ossimRefPtr<ossimImageGeometry> ossimKmlSuperOverlayReader::getImageGeometry()
+{
+   return theImageGeometry;
+}
+
+ossimScalarType ossimKmlSuperOverlayReader::getOutputScalarType() const
+{
+   return OSSIM_SCALAR_UNKNOWN;
+}
+
+bool ossimKmlSuperOverlayReader::isOpen()const
+{
+   if (theImageFile.empty())
+   {
+      return false;
+   }
+   return true;
+}
+
+bool ossimKmlSuperOverlayReader::isKmlSuperOverlayFile(std::vector<ossimRefPtr<ossimXmlNode> > nodes)
+{
+   for (ossim_uint32 i = 0; i < nodes.size(); i++)
+   {
+      if (nodes[i]->getTag().downcase() == "placemark") //means vector kml file with point, polygon, or lines
+      {
+         return false;
+      }
+
+      if (nodes[i]->getTag().downcase() == "region" || nodes[i]->getTag().downcase() == "networkLink") //means super overlay kml file
+      {
+         return true;
+      }
+   }
+   for (ossim_uint32 i = 0; i < nodes.size(); i++)
+   {
+      return isKmlSuperOverlayFile(nodes[i]->getChildNodes());
+   }
+   return false;
+}
+
+ossimRefPtr<ossimXmlNode> ossimKmlSuperOverlayReader::findLatLonNode(std::vector<ossimRefPtr<ossimXmlNode> >nodes)
+{
+   ossimRefPtr<ossimXmlNode> latlonNode = 0;
+   for (ossim_uint32 i = 0; i < nodes.size(); i++)
+   {
+      if (nodes[i]->getTag().downcase() == "latlonaltbox")
+      {
+         return nodes[i];
+      }
+   }
+   for (ossim_uint32 j = 0; j < nodes.size(); j++)
+   {
+      latlonNode = findLatLonNode(nodes[j]->getChildNodes());
+      if (latlonNode.valid())
+      {
+         return latlonNode;
+      }
+   }
+   return latlonNode;
+}
+
+bool ossimKmlSuperOverlayReader::getCoordinate(std::vector<ossimRefPtr<ossimXmlNode> > nodes,
+                                               ossim_float64& north,
+                                               ossim_float64& south,
+                                               ossim_float64& east,
+                                               ossim_float64& west)
+{
+   ossimRefPtr<ossimXmlNode> latlonNode = findLatLonNode(nodes);
+   if (!latlonNode.valid())
+   {
+      return false;
+   }
+
+   std::vector<ossimRefPtr<ossimXmlNode> > latlonNodes = latlonNode->getChildNodes();
+   if (latlonNodes.size() != 4)
+   {
+      return false;
+   }
+   for (ossim_uint32 i = 0; i < latlonNodes.size(); i++)
+   {
+      ossimString str = latlonNodes[i]->getTag().downcase();
+      if (str == "north")
+      {
+         north = latlonNodes[i]->getText().toFloat64();
+      }
+      else if (str == "south")
+      {
+         south = latlonNodes[i]->getText().toFloat64();
+      }
+      else if (str == "east")
+      {
+         east = latlonNodes[i]->getText().toFloat64();
+      }
+      else if (str == "west")
+      {
+         west = latlonNodes[i]->getText().toFloat64();
+      }
+   }
+   return true;
+}
+
+ossimMapProjection* ossimKmlSuperOverlayReader::createDefaultProj(ossim_float64 north, 
+                                                                  ossim_float64 south, 
+                                                                  ossim_float64 east, 
+                                                                  ossim_float64 west)
+{
+   ossimEquDistCylProjection* proj = new ossimEquDistCylProjection;
+   
+   ossim_float64 centerLat = (south + north) / 2.0;
+   ossim_float64 centerLon = (west + east) / 2.0;
+   ossim_float64 deltaLat  = north - south;
+   
+   // Scale that gives 1024 pixel in the latitude direction.
+   ossim_float64 scaleLat = deltaLat / 1024.0;
+   ossim_float64 scaleLon = scaleLat*ossim::cosd(std::fabs(centerLat)); 
+   ossimGpt origin(centerLat, centerLon, 0.0);
+   ossimDpt scale(scaleLon, scaleLat);
+   
+   // Set the origin.
+   proj->setOrigin(origin);
+   
+  // Set the tie point.
+   proj->setUlGpt( ossimGpt(north, west));
+   
+   // Set the scale.  Note this will handle computing meters per pixel.
+   proj->setDecimalDegreesPerPixel(scale);
+   
+   return proj;
+}
+
+bool ossimKmlSuperOverlayReader::getTopLevelKmlFileInfo()
+{
+   theImageFile.rename(ossimString(theImageFile.noExtension() + ".zip"));
+   ossimFilename tmpZipfile = ossimString(theImageFile.noExtension() + ".zip");
+   unzFile unzipfile = unzOpen(tmpZipfile.c_str());
+   if (!unzipfile)
+   {
+      ossimSetError(getClassName(),
+         ossimErrorCodes::OSSIM_ERROR,
+         "Unable to open target zip file..");
+
+      tmpZipfile.rename(ossimString(tmpZipfile.noExtension() + ".kmz"));//if open fails, rename the file back to .kmz
+      return false;
+   }
+
+   std::string kmzStringBuffer;
+
+   if (unzGoToFirstFile(unzipfile) == UNZ_OK)
+   {
+      if (unzOpenCurrentFile(unzipfile) == UNZ_OK)
+      {
+         unsigned char buffer[4096] = {0};
+         int bytesRead = 0;
+         int read = 1;
+         while (read > 0)
+         {
+            read = unzReadCurrentFile(unzipfile, buffer, 4096);
+            bytesRead += read;
+         }
+         if ( bytesRead )
+         {
+            for (int i = 0; i < bytesRead; ++i)
+            {
+               // Copy to string casting to char.
+               kmzStringBuffer.push_back( static_cast<char>(buffer[i]) );
+            }
+         }
+      }
+      else
+      {
+         tmpZipfile.rename(ossimString(tmpZipfile.noExtension() + ".kmz"));//if read fails, rename the file back to .kmz
+         unzCloseCurrentFile(unzipfile);
+         unzClose(unzipfile);
+         return false;
+      }
+   }
+   else
+   {
+      tmpZipfile.rename(ossimString(tmpZipfile.noExtension() + ".kmz"));
+      unzClose(unzipfile);
+      return false;
+   }
+   unzCloseCurrentFile(unzipfile);
+   unzClose(unzipfile);
+
+   std::istringstream in(kmzStringBuffer);
+   if ( in.good() )
+   {
+      m_xmlDocument = new ossimXmlDocument;
+      m_xmlDocument->read( in );
+   }
+   else
+   {
+      tmpZipfile.rename(ossimString(tmpZipfile.noExtension() + ".kmz"));
+      return false;
+   }
+
+   tmpZipfile.rename(ossimString(tmpZipfile.noExtension() + ".kmz"));
+
+   return true;
+}
+
+
+
diff --git a/ossim_plugins/kmlsuperoverlay/ossimKmlSuperOverlayReader.h b/ossim_plugins/kmlsuperoverlay/ossimKmlSuperOverlayReader.h
new file mode 100644
index 0000000..6b1033e
--- /dev/null
+++ b/ossim_plugins/kmlsuperoverlay/ossimKmlSuperOverlayReader.h
@@ -0,0 +1,154 @@
+
+//*******************************************************************
+// Copyright (C) 2000 ImageLinks Inc.
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author:  Mingjie Su, Harsh Govind
+//
+// Description:
+//
+// Contains class definition for the class "ossimKmlSuperOverlayReader".
+// ossimKmlSuperOverlayReader is derived from ImageHandler which is derived from
+// TileSource. It is for displaying the information from kml super overlay.
+//
+//*******************************************************************
+//  $Id: ossimKmlSuperOverlayReader.h 2178 2011-02-17 18:38:30Z ming.su $
+
+#ifndef ossimKmlSuperOverlayReader_HEADER
+#define ossimKmlSuperOverlayReader_HEADER
+
+//Ossim Includes
+#include <ossim/imaging/ossimImageHandler.h>
+#include <ossim/base/ossimIrect.h>
+#include <ossim/base/ossimDrect.h>
+
+class ossimProjection;
+class ossimMapProjection;
+class ossimXmlDocument;
+
+class ossimKmlSuperOverlayReader : public ossimImageHandler
+{
+
+public:
+
+   ossimKmlSuperOverlayReader();
+   virtual ~ossimKmlSuperOverlayReader();
+
+   virtual void close();
+
+   /**
+    *  @return Returns true on success, false on error.
+    *
+    *  @note This method relies on the data member ossimImageData::theImageFile
+    *  being set.  Callers should do a "setFilename" prior to calling this
+    *  method or use the ossimImageHandler::open that takes a file name and an
+    *  entry index.
+    */      
+   virtual bool open();
+
+   /*!
+    *  Returns a null pointer for kml super overlay.
+    *  Satisfies pure virtual from ImageHandler class.
+    * 
+    */
+   virtual ossimRefPtr<ossimImageData> getTile(const ossimIrect& tileRect,
+                                               ossim_uint32 resLevel=0);
+
+   /*!
+    *  Returns the number 0 for bands for kml super overlay
+    *  Satisfies pure virtual from ImageHandler class.
+    */
+   virtual ossim_uint32 getNumberOfInputBands() const;
+
+   /*!
+    *  Returns the number 0 for bands for kml super overlay
+    *  Satisfies pure virtual from ImageHandler class.
+    */
+   virtual ossim_uint32 getNumberOfOutputBands() const;
+  
+   /*!
+    *  Returns the number of bands in the image.
+    *  Satisfies pure virtual from ImageHandler class.
+    */
+   virtual ossim_uint32 getNumberOfLines(ossim_uint32 reduced_res_level = 0) const;
+
+   /*!
+    *  Returns the number of bands available from an image.
+    *  Satisfies pure virtual from ImageHandler class.
+    */
+   virtual ossim_uint32 getNumberOfSamples(ossim_uint32 reduced_res_level = 0) const;
+
+   /*!
+    * Returns the zero based image rectangle for the reduced resolution data
+    * set (rrds) passed in.  Note that rrds 0 is the highest resolution rrds.
+    */
+   virtual ossimIrect getImageRectangle(ossim_uint32 reduced_res_level = 0) const;
+
+   /*!
+    * Method to save the state of an object to a keyword list.
+    * Return true if ok or false on error.
+    */
+   virtual bool saveState(ossimKeywordlist& kwl,
+                          const char* prefix=0)const;
+
+   /*!
+    * Method to the load (recreate) the state of an object from a keyword
+    * list.  Return true if ok or false on error.
+    */
+   virtual bool loadState(const ossimKeywordlist& kwl,
+                          const char* prefix=0);
+
+    /*!
+    * Returns the tile width of the image or 0 if the image is not tiled.
+    * Note: this is not the same as the ossimImageSource::getTileWidth which
+    * returns the output tile width which can be different than the internal
+    * image tile width on disk.
+    */
+   virtual ossim_uint32 getImageTileWidth() const;
+
+   /*!
+    * Returns the tile width of the image or 0 if the image is not tiled.
+    * Note: this is not the same as the ossimImageSource::getTileWidth which
+    * returns the output tile width which can be different than the internal
+    * image tile width on disk.
+    */
+   virtual ossim_uint32 getImageTileHeight() const;   
+   
+   //! Returns the image geometry object associated with this tile source or NULL if non defined.
+   //! The geometry contains full-to-local image transform as well as projection (image-to-world)
+   virtual ossimRefPtr<ossimImageGeometry> getInternalImageGeometry() const;
+
+   virtual ossimRefPtr<ossimImageGeometry> getImageGeometry();
+
+   ossimScalarType getOutputScalarType() const;
+
+   virtual bool isOpen()const;
+   
+   ossimMapProjection* createDefaultProj(ossim_float64 north, ossim_float64 south, ossim_float64 east, ossim_float64 west);
+
+private:
+
+   bool getCoordinate(std::vector<ossimRefPtr<ossimXmlNode> > nodes,
+                      ossim_float64& north,
+                      ossim_float64& south,
+                      ossim_float64& east,
+                      ossim_float64& west);
+
+   ossimRefPtr<ossimXmlNode> findLatLonNode(std::vector<ossimRefPtr<ossimXmlNode> >nodes);
+
+   bool isKmlSuperOverlayFile(std::vector<ossimRefPtr<ossimXmlNode> > nodes);
+
+   bool getTopLevelKmlFileInfo();
+
+   ossimRefPtr<ossimXmlDocument>       m_xmlDocument;
+   ossimRefPtr<ossimImageGeometry>     theImageGeometry;
+   ossimDrect                          theImageBound;
+
+TYPE_DATA
+};
+
+#endif
+
diff --git a/ossim_plugins/kmlsuperoverlay/ossimKmlSuperOverlayReaderFactory.cpp b/ossim_plugins/kmlsuperoverlay/ossimKmlSuperOverlayReaderFactory.cpp
new file mode 100644
index 0000000..2df0fc8
--- /dev/null
+++ b/ossim_plugins/kmlsuperoverlay/ossimKmlSuperOverlayReaderFactory.cpp
@@ -0,0 +1,152 @@
+//----------------------------------------------------------------------------
+//
+// License:  See top level LICENSE.txt file
+//
+// Author:  Mingjie Su, Harsh Govind
+//
+// Description: Factory for ossim KmlSuperOverlay reader using libkml library.
+//----------------------------------------------------------------------------
+// $Id: ossimKmlSuperOverlayReaderFactory.cpp 2472 2011-04-26 15:47:50Z ming.su $
+
+
+#include "ossimKmlSuperOverlayReaderFactory.h"
+#include "ossimKmlSuperOverlayReader.h"
+
+#include <ossim/base/ossimKeywordlist.h>
+#include <ossim/base/ossimRefPtr.h>
+#include <ossim/base/ossimString.h>
+#include <ossim/base/ossimTrace.h>
+#include <ossim/imaging/ossimImageHandler.h>
+
+static const ossimTrace traceDebug("ossimKmlSuperOverlayReaderFactory:debug");
+
+class ossimImageHandler;
+
+RTTI_DEF1(ossimKmlSuperOverlayReaderFactory,
+   "ossimKmlSuperOverlayReaderFactory",
+   ossimImageHandlerFactoryBase);
+
+ossimKmlSuperOverlayReaderFactory* ossimKmlSuperOverlayReaderFactory::theInstance = 0;
+
+ossimKmlSuperOverlayReaderFactory::~ossimKmlSuperOverlayReaderFactory()
+{
+   theInstance = 0;
+}
+
+ossimKmlSuperOverlayReaderFactory* ossimKmlSuperOverlayReaderFactory::instance()
+{
+   if(!theInstance)
+   {
+      theInstance = new ossimKmlSuperOverlayReaderFactory;
+   }
+   return theInstance;
+}
+
+ossimImageHandler* ossimKmlSuperOverlayReaderFactory::open(const ossimFilename& fileName,
+                                                           bool /* openOverview */ )const
+{
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimKmlSuperOverlayReaderFactory::open(filename) DEBUG: entered..."
+         << "\ntrying ossimKakaduNitfReader"
+         << std::endl;
+   }
+
+   ossimRefPtr<ossimImageHandler> reader = 0;
+
+   if ( hasExcludedExtension(fileName) == false )
+   {
+      reader = new ossimKmlSuperOverlayReader;
+      if(reader->open(fileName) == false)
+      {
+         reader = 0;
+      }
+   }
+
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimKmlSuperOverlayReaderFactory::open(filename) DEBUG: leaving..."
+         << std::endl;
+   }
+
+   return reader.release();
+}
+
+ossimImageHandler* ossimKmlSuperOverlayReaderFactory::open(const ossimKeywordlist& kwl,
+   const char* prefix)const
+{
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimKmlSuperOverlayReaderFactory::open(kwl, prefix) DEBUG: entered..."
+         << "Trying ossimKakaduNitfReader"
+         << std::endl;
+   }
+
+   ossimRefPtr<ossimImageHandler> reader = new ossimKmlSuperOverlayReader;
+   if(reader->loadState(kwl, prefix) == false)
+   {
+      reader = 0;
+   }
+
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimKmlSuperOverlayReaderFactory::open(kwl, prefix) DEBUG: leaving..."
+         << std::endl;
+   }
+
+   return reader.release();
+}
+
+ossimObject* ossimKmlSuperOverlayReaderFactory::createObject(
+   const ossimString& typeName)const
+{
+   ossimRefPtr<ossimObject> result = 0;
+   if(typeName == "ossimKmlSuperOverlayReader")
+   {
+      result = new ossimKmlSuperOverlayReader;
+   }
+
+   return result.release();
+}
+
+ossimObject* ossimKmlSuperOverlayReaderFactory::createObject(
+   const ossimKeywordlist& kwl,
+   const char* prefix)const
+{
+   return this->open(kwl, prefix);
+}
+
+void ossimKmlSuperOverlayReaderFactory::getTypeNameList(
+   std::vector<ossimString>& typeList)const
+{
+   typeList.push_back(ossimString("ossimKmlSuperOverlayReader"));
+}
+
+void ossimKmlSuperOverlayReaderFactory::getSupportedExtensions(
+   ossimImageHandlerFactoryBase::UniqueStringList& extensionList)const
+{
+   extensionList.push_back(ossimString("kml"));
+   extensionList.push_back(ossimString("kmz"));
+}
+
+bool ossimKmlSuperOverlayReaderFactory::hasExcludedExtension(
+   const ossimFilename& file) const
+{
+   bool result = true;
+   ossimString ext = file.ext().downcase();
+   if (ext == "kml" || ext == "kmz") //only include the file with .kml or .kmz extension and exclude any other files
+   {
+      result = false;
+   }
+   return result;
+}
+
+ossimKmlSuperOverlayReaderFactory::ossimKmlSuperOverlayReaderFactory(){}
+
+ossimKmlSuperOverlayReaderFactory::ossimKmlSuperOverlayReaderFactory(const ossimKmlSuperOverlayReaderFactory&){}
+
+void ossimKmlSuperOverlayReaderFactory::operator=(const ossimKmlSuperOverlayReaderFactory&){}
diff --git a/ossim_plugins/kmlsuperoverlay/ossimKmlSuperOverlayReaderFactory.h b/ossim_plugins/kmlsuperoverlay/ossimKmlSuperOverlayReaderFactory.h
new file mode 100644
index 0000000..1d3b12d
--- /dev/null
+++ b/ossim_plugins/kmlsuperoverlay/ossimKmlSuperOverlayReaderFactory.h
@@ -0,0 +1,106 @@
+//----------------------------------------------------------------------------
+//
+// License:  See top level LICENSE.txt file
+//
+// Author:  Mingjie Su, Harsh Govind
+//
+// Description: Factory for ossim KmlSuperOverlay reader using libkml library.
+//----------------------------------------------------------------------------
+// $Id: ossimKmlSuperOverlayReaderFactory.h 2472 2011-04-26 15:47:50Z ming.su $
+
+#ifndef ossimKmlSuperOverlayReaderFactory_HEADER
+#define ossimKmlSuperOverlayReaderFactory_HEADER
+
+#include <ossim/imaging/ossimImageHandlerFactoryBase.h>
+
+class ossimString;
+class ossimFilename;
+class ossimKeywordlist;
+
+/** @brief Factory for Kml SuperOverlay reader. */
+class ossimKmlSuperOverlayReaderFactory : public ossimImageHandlerFactoryBase
+{
+public:
+
+   /** @brief virtual destructor */
+   virtual ~ossimKmlSuperOverlayReaderFactory();
+
+   /**
+    * @brief static method to return instance (the only one) of this class.
+    * @return pointer to instance of this class.
+    */
+   static ossimKmlSuperOverlayReaderFactory* instance();
+
+   /**
+    * @brief open that takes a file name.
+    * @param file The file to open.
+    * @return pointer to image handler on success, NULL on failure.
+    */
+   virtual ossimImageHandler* open(const ossimFilename& fileName, bool openOverview=true) const;
+
+   /**
+    * @brief open that takes a keyword list and prefix.
+    * @param kwl The keyword list.
+    * @param prefix the keyword list prefix.
+    * @return pointer to image handler on success, NULL on failure.
+    */
+   virtual ossimImageHandler* open(const ossimKeywordlist& kwl,
+                                   const char* prefix=0)const;
+
+   /**
+    * @brief createObject that takes a class name (ossimKmlSuperOverlayReader)
+    * @param typeName Should be "ossimKmlSuperOverlayReader".
+    * @return pointer to image writer on success, NULL on failure.
+    */
+   virtual ossimObject* createObject(const ossimString& typeName)const;
+   
+   /**
+    * @brief Creates and object given a keyword list and prefix.
+    * @param kwl The keyword list.
+    * @param prefix the keyword list prefix.
+    * @return pointer to image handler on success, NULL on failure.
+    */
+   virtual ossimObject* createObject(const ossimKeywordlist& kwl,
+                                     const char* prefix=0)const;
+   
+   /**
+    * @brief Adds ossimKmlSuperOverlayReader to the typeList.
+    * @param typeList List to add to.
+    */
+   virtual void getTypeNameList(std::vector<ossimString>& typeList)const;
+
+   /**
+    * @brief Method to add supported extension to the list, like "kml" or "kmz".
+    *
+    * @param extensionList The list to add to.
+    */
+   virtual void getSupportedExtensions(
+      ossimImageHandlerFactoryBase::UniqueStringList& extensionList)const;
+  
+protected:
+
+   /**
+    * @brief Method to weed out extensions that this plugin knows it does
+    * not support.  This is to avoid a costly open on say a tiff or jpeg that
+    * is not handled by this plugin.
+    *
+    * @return true if extension, false if not.
+    */
+   bool hasExcludedExtension(const ossimFilename& file) const;
+   
+   /** @brief hidden from use default constructor */
+   ossimKmlSuperOverlayReaderFactory();
+
+   /** @brief hidden from use copy constructor */
+   ossimKmlSuperOverlayReaderFactory(const ossimKmlSuperOverlayReaderFactory&);
+
+   /** @brief hidden from use copy constructor */
+   void operator=(const ossimKmlSuperOverlayReaderFactory&);
+
+   /** static instance of this class */
+   static ossimKmlSuperOverlayReaderFactory* theInstance;
+
+TYPE_DATA
+};
+
+#endif /* end of #ifndef ossimKmlSuperOverlayReaderFactory_HEADER */
diff --git a/ossim_plugins/kmlsuperoverlay/ossimKmlSuperOverlayWriter.cpp b/ossim_plugins/kmlsuperoverlay/ossimKmlSuperOverlayWriter.cpp
new file mode 100644
index 0000000..64cc5aa
--- /dev/null
+++ b/ossim_plugins/kmlsuperoverlay/ossimKmlSuperOverlayWriter.cpp
@@ -0,0 +1,938 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author:  Mingjie Su, Harsh Govind
+//
+// Description: OSSIM KmlSuperOverlayWriter writer class definition.
+//
+//----------------------------------------------------------------------------
+// $Id: ossimKmlSuperOverlayWriter.cpp 2178 2011-02-17 18:38:30Z ming.su $
+
+#include "ossimKmlSuperOverlayWriter.h"
+
+//OSSIM Includes
+#include <ossim/base/ossimDpt.h>
+#include <ossim/base/ossimDirectory.h>
+#include <ossim/base/ossimKeywordlist.h>
+#include <ossim/base/ossimKeywordNames.h>
+#include <ossim/base/ossimTrace.h>
+#include <ossim/base/ossimVisitor.h> /* for ossimViewInterfaceVisitor */
+#include <ossim/projection/ossimMapProjection.h>
+#include <ossim/imaging/ossimImageDataFactory.h>
+#include <ossim/imaging/ossimImageGeometry.h>
+#include <ossim/imaging/ossimImageWriterFactoryRegistry.h>
+
+//STD Includes
+#include <cmath>
+#include <cstring> /* strdup */
+#include <iostream>
+#include <sstream>
+
+
+RTTI_DEF1(ossimKmlSuperOverlayWriter, "ossimKmlSuperOverlayWriter", ossimImageFileWriter)
+
+   //---
+   // For trace debugging (to enable at runtime do:
+   // your_app -T "ossimKmlSuperOverlayWriter:debug" your_app_args
+   //---
+   static ossimTrace traceDebug("ossimKmlSuperOverlayWriter:debug");
+
+ossimKmlSuperOverlayWriter::ossimKmlSuperOverlayWriter()
+   : ossimImageFileWriter(),
+   m_imageWriter(0),
+   m_mapProjection(0),
+   m_isKmz(false),
+   m_isPngFormat(false)
+{
+   // Set the output image type in the base class.
+   setOutputImageType(getShortName());
+}
+
+ossimKmlSuperOverlayWriter::~ossimKmlSuperOverlayWriter()
+{
+   close();
+}
+
+ossimString ossimKmlSuperOverlayWriter::getShortName() const
+{
+   return ossimString("ossim_kmlsuperoverlay");
+}
+
+ossimString ossimKmlSuperOverlayWriter::getLongName() const
+{
+   return ossimString("ossim kmlsuperoverlay writer");
+}
+
+ossimString ossimKmlSuperOverlayWriter::getClassName() const
+{
+   return ossimString("ossimKmlSuperOverlayWriter");
+}
+
+bool ossimKmlSuperOverlayWriter::writeFile()
+{
+   // This method is called from ossimImageFileWriter::execute().
+   bool result = false;
+
+   if( theInputConnection.valid() &&
+      (getErrorStatus() == ossimErrorCodes::OSSIM_OK) )
+   {
+      theInputConnection->setAreaOfInterest(theAreaOfInterest);
+      theInputConnection->setToStartOfSequence();
+
+      //---
+      // Note only the master process used for writing...
+      //---
+      if(theInputConnection->isMaster())
+      {
+         if (!isOpen())
+         {
+            open();
+         }
+         if ( isOpen() )
+         {
+            result = writeStream();
+         }
+      }
+      else // Slave process.
+      {
+         // This will return after all tiles for this node have been processed.
+         theInputConnection->slaveProcessTiles();
+         result = true;
+      }
+   }
+
+   return result;
+}
+
+bool ossimKmlSuperOverlayWriter::writeStream()
+{
+   static const char MODULE[] = "ossimKmlSuperOverlayWriter::writeStream";
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " entered..." << endl;
+   }
+
+   ossim_int32 bands = theInputConnection->getNumberOfOutputBands();
+   if (bands != 1 && bands != 3)
+   {
+      ossimNotify(ossimNotifyLevel_WARN)
+         << MODULE << " Range Error:"
+         << "\nInvalid number of input bands!  Must be one or three."
+         << "\nInput bands = " << bands
+         << "\nReturning from method." << endl;
+
+      return false;
+   }
+
+   if (theFilename.ext().downcase() == "kmz")
+   {
+      m_isKmz = true;
+   }
+
+   ossimString fileExt = ".jpg";
+   ossimString ext = "jpg";
+   if (m_isPngFormat)
+   {
+      fileExt = ".png";
+      ext = "png";
+   }
+   m_imageWriter = ossimImageWriterFactoryRegistry::instance()->createWriterFromExtension(ext);
+   if (!m_imageWriter.valid())
+   {
+      return false;
+   }
+   if (m_isPngFormat)//add alpha channel for png
+   {
+      ossimKeywordlist kwl;
+      kwl.add("add_alpha_channel", "true", true);
+      m_imageWriter->loadState(kwl);
+   }
+   m_imageWriter->connectMyInputTo(theInputConnection.get());
+   
+   ossimString outDir = theFilename.path();
+   if (outDir.empty())
+      outDir = ".";
+
+   if (theAreaOfInterest.hasNans())
+   {
+      return false;
+   }
+
+   ossim_int32 xsize = theAreaOfInterest.width();
+   ossim_int32 ysize = theAreaOfInterest.height();
+
+   ossimGpt ulg;
+   ossimGpt llg;
+   ossimGpt lrg;
+   ossimGpt urg;
+   ossimDpt scale;
+   ossimRefPtr<ossimImageGeometry> geom = theInputConnection->getImageGeometry();
+   ossimRefPtr<ossimMapProjection> projDup = 0; 
+   if (geom.valid())
+   {
+      geom->localToWorld(theAreaOfInterest.ul(), ulg);
+      geom->localToWorld(theAreaOfInterest.ll(), llg);
+      geom->localToWorld(theAreaOfInterest.lr(), lrg);
+      geom->localToWorld(theAreaOfInterest.ur(), urg);
+
+      ossimRefPtr<ossimProjection> proj = geom->getProjection();
+      m_mapProjection = PTR_CAST(ossimMapProjection, proj.get());
+      if (m_mapProjection.valid())
+      {
+         //make a copy of map projection for lat, lon conversion of the previous zoom in child kml since m_mapProjection set the scale 
+         //for the current zoom
+         projDup = PTR_CAST(ossimMapProjection, m_mapProjection->dup());
+
+         if (m_mapProjection->isGeographic())
+         {
+            // Get the scale.
+            scale.x =  m_mapProjection->getDecimalDegreesPerPixel().x;
+            scale.y =  m_mapProjection->getDecimalDegreesPerPixel().y;
+         }
+         else
+         {
+            // Get the scale.
+            scale.x =  m_mapProjection->getMetersPerPixel().x;
+            scale.y =  m_mapProjection->getMetersPerPixel().y;
+         }
+      }
+      else
+      {
+         return false;
+      }
+   }
+   else
+   {
+      return false;
+   }
+
+   //Zoom levels of the pyramid.
+   ossim_int32 maxzoom;
+   ossim_int32 tilexsize;
+   ossim_int32 tileysize;
+   // Let the longer side determine the max zoom level and x/y tilesizes.
+   if ( xsize >= ysize )
+   {
+      ossim_float64 dtilexsize = xsize;
+      while (dtilexsize > 400) //calculate x tile size
+      {
+         dtilexsize = dtilexsize/2;
+      }
+
+      maxzoom   = static_cast<ossim_int32>(log( (ossim_float64)xsize / dtilexsize ) / log(2.0));
+      tilexsize = (ossim_int32)dtilexsize;
+      tileysize = (ossim_int32)( (ossim_float64)(dtilexsize * ysize) / xsize );
+   }
+   else
+   {
+      ossim_float64 dtileysize = ysize;
+      while (dtileysize > 400) //calculate y tile size
+      {
+         dtileysize = dtileysize/2;
+      }
+
+      maxzoom   = static_cast<ossim_int32>(log( (ossim_float64)ysize / dtileysize ) / log(2.0));
+      tileysize = (ossim_int32)dtileysize;
+      tilexsize = (ossim_int32)( (ossim_float64)(dtileysize * xsize) / ysize );
+   }
+
+   std::vector<ossim_float64> zoomScaleX;
+   std::vector<ossim_float64> zoomScaleY;
+   for (int zoom = 0; zoom < maxzoom + 1; zoom++)
+   {
+      zoomScaleX.push_back(scale.x * pow(2.0, (maxzoom - zoom)));
+      zoomScaleY.push_back(scale.y * pow(2.0, (maxzoom - zoom)));
+   }
+
+   ossimString tmpFileName; 
+   std::vector<ossimString> dirVector;
+   std::vector<ossimString> fileVector;
+   bool isKmlGenerated = false;
+   if (m_isKmz)
+   {
+      tmpFileName = ossimString(outDir + "/" + "tmp.kml");
+      isKmlGenerated = generateRootKml(tmpFileName.c_str(), ulg.lat, lrg.lat, lrg.lon, ulg.lon, (ossim_int32)tilexsize);
+      fileVector.push_back(tmpFileName);
+   }
+   else
+   {
+      isKmlGenerated = generateRootKml(theFilename, ulg.lat, lrg.lat, lrg.lon, ulg.lon, (ossim_int32)tilexsize);
+   }
+   if (!isKmlGenerated)
+   {
+      return false;
+   }
+
+   for (ossim_int32 zoom = maxzoom; zoom >= 0; --zoom)
+   {
+      ossim_int32 rmaxxsize = static_cast<ossim_int32>(pow(2.0, (maxzoom-zoom)) * tilexsize);
+      ossim_int32 rmaxysize = static_cast<ossim_int32>(pow(2.0, (maxzoom-zoom)) * tileysize);
+
+      ossim_int32 xloop = (ossim_int32)xsize/rmaxxsize;
+      ossim_int32 yloop = (ossim_int32)ysize/rmaxysize;
+
+      xloop = xloop>0 ? xloop : 1;
+      yloop = yloop>0 ? yloop : 1;
+
+      //set scale for the current zoom
+      if (m_mapProjection.valid())
+      {
+         if (m_mapProjection->isGeographic())
+         {
+            m_mapProjection->setDecimalDegreesPerPixel(ossimDpt(zoomScaleX[zoom],zoomScaleY[zoom]));
+         }
+         else
+         {
+            m_mapProjection->setMetersPerPixel(ossimDpt(zoomScaleX[zoom],zoomScaleY[zoom]));
+         }
+      }
+
+      // Set all views and send property event out for combiner if needed.
+      propagateViewChange();
+
+      //set the scale for the previous zoom in child kml for lat, lon conversion
+      if (zoom < maxzoom)
+      {
+         if (projDup.valid())
+         {
+            if (projDup->isGeographic())
+            {
+               projDup->setDecimalDegreesPerPixel(ossimDpt(zoomScaleX[zoom+1],zoomScaleY[zoom+1]));
+            }
+            else
+            {
+               projDup->setMetersPerPixel(ossimDpt(zoomScaleX[zoom+1],zoomScaleY[zoom+1]));
+            }
+         }
+      }
+
+      for (ossim_int32 ix = 0; ix < xloop; ix++)
+      {
+         ossim_int32 rxsize = (ossim_int32)(rmaxxsize);
+         // ossim_int32 rx = (ossim_int32)(ix * rmaxxsize);
+
+         for (ossim_int32 iy = 0; iy < yloop; iy++)
+         {
+            ossim_int32 rysize = (ossim_int32)(rmaxysize);
+            // ossim_int32 ry = (ossim_int32)(ysize - (iy * rmaxysize)) - rysize;
+
+            ossim_int32 dxsize = (ossim_int32)(rxsize/rmaxxsize * tilexsize);
+            ossim_int32 dysize = (ossim_int32)(rysize/rmaxysize * tileysize);
+
+            std::stringstream zoomStr;
+            std::stringstream ixStr;
+            std::stringstream iyStr;
+
+            zoomStr << zoom;
+            ixStr << ix;
+            iyStr << iy;
+
+            ossimFilename zoomDir = ossimString(outDir + "/" + ossimString(zoomStr.str()));
+            zoomDir.createDirectory();
+
+            zoomDir = ossimString(zoomDir + "/") + ossimString::toString(ix);
+            zoomDir.createDirectory();
+
+            if (m_isKmz)
+            {
+               dirVector.push_back(zoomDir);
+            }
+
+            ossimString filename = ossimString(zoomDir + "/" + ossimString::toString(yloop-iy-1) + fileExt);
+            if (m_isKmz)
+            {
+               fileVector.push_back(filename);
+            }
+
+            generateTile(filename, ix, iy, dxsize, dysize);
+
+            ossimString childKmlfile = ossimString(zoomDir + "/" + ossimString::toString(yloop-iy-1) + ".kml");
+            if (m_isKmz)
+            {
+               fileVector.push_back(childKmlfile);
+            }
+
+            isKmlGenerated = generateChildKml(childKmlfile, zoom, yloop, ix, iy, dxsize, dysize, xsize, ysize, maxzoom, projDup, fileExt);
+            if (!isKmlGenerated)
+            {
+               return false;
+            }
+         }
+      }
+   }
+
+
+   if (m_isKmz)
+   {
+      if (zipWithMinizip(fileVector, outDir, theFilename) == false)
+      {
+         return false;
+      }
+
+      //remove sub-directories and the files under those directories
+      for (ossim_uint32 i = 0; i < dirVector.size(); ++i)
+      {
+         ossimFilename zoomDir = dirVector[i];
+
+         ossimDirectory dir;
+         std::vector<ossimFilename> filesInDir;
+         if(dir.open(zoomDir))
+         {
+            ossimFilename file;
+            //if (dir.getFirst(file, ossimDirectory::OSSIM_DIR_DEFAULT))
+            if (dir.getFirst(file, ossimDirectory::OSSIM_DIR_DEFAULT))
+            {
+               filesInDir.push_back(file);
+            }
+            do
+            {
+               filesInDir.push_back(file);
+            }while(dir.getNext(file));
+         }
+
+         for(ossim_uint32 j = 0; j < filesInDir.size(); ++j)
+         {
+            ossimFilename fi = filesInDir[j];
+            if (!fi.empty())
+            {
+               fi.remove();
+            }
+         }
+         if (zoomDir.exists())
+         {
+            ossimString cmd = "rmdir \"";
+            cmd += zoomDir + "\"";
+            std::system(cmd.c_str());
+         }
+      }
+
+      //remove the top directories
+      for (int zoom = maxzoom; zoom >= 0; --zoom)
+      {
+         std::stringstream zoomStr;
+         zoomStr << zoom;
+         ossimFilename zoomZipDir = ossimString(outDir + "/" + ossimString(zoomStr.str()));
+         if (zoomZipDir.exists())
+         {
+            ossimString cmd = "rmdir \"";
+            cmd += zoomZipDir + "\"";
+            std::system(cmd.c_str());
+         }
+      }
+      if (ossimFilename(tmpFileName).exists())
+      {
+         ossimFilename(tmpFileName).remove();
+      }
+   }
+
+   return true;
+}
+
+bool ossimKmlSuperOverlayWriter::saveState(ossimKeywordlist& kwl,
+   const char* prefix)const
+{
+   return ossimImageFileWriter::saveState(kwl, prefix);
+}
+
+bool ossimKmlSuperOverlayWriter::loadState(const ossimKeywordlist& kwl,
+   const char* prefix)
+{
+   return ossimImageFileWriter::loadState(kwl, prefix);
+}
+
+bool ossimKmlSuperOverlayWriter::isOpen() const
+{
+   if (theFilename.size() > 0)
+   {
+      return true;
+   }
+   return false;
+}
+
+bool ossimKmlSuperOverlayWriter::open()
+{
+   bool result = false;
+
+   // Check for empty filenames.
+   if (theFilename.size())
+   {
+      result = true;
+   }
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimKmlSuperOverlayWriter::open()\n"
+         << "File " << theFilename << (result ? " opened" : " not opened")
+         << std::endl;
+   }
+
+   return result;
+}
+
+void ossimKmlSuperOverlayWriter::close()
+{
+   if (m_imageWriter.valid())
+   {
+      m_imageWriter = 0;
+   }
+   if (m_mapProjection.valid())
+   {
+      m_mapProjection = 0;
+   }
+}
+
+void ossimKmlSuperOverlayWriter::getImageTypeList(std::vector<ossimString>& imageTypeList)const
+{
+   imageTypeList.push_back(getShortName());
+}
+
+ossimString ossimKmlSuperOverlayWriter::getExtension() const
+{
+   if (!theFilename.empty())
+   {
+      return theFilename.ext();
+   }
+   return ossimString("kml");
+}
+
+bool ossimKmlSuperOverlayWriter::hasImageType(const ossimString& imageType) const
+{
+   bool result = false;
+   if ( (imageType == getShortName()) ||
+      (imageType == "image/kmlsuperoverlay") )
+   {
+      result = true;
+   }
+   return result;
+}
+
+void ossimKmlSuperOverlayWriter::setProperty(ossimRefPtr<ossimProperty> property)
+{
+   if (property.get())
+   {
+      if(property->getName().downcase() == "format")
+      {
+         ossimString format = property->valueToString();
+         if (format.downcase() == "png")
+         {
+            m_isPngFormat = true;
+         }
+      }
+      ossimImageFileWriter::setProperty(property);
+   }
+}
+
+ossimRefPtr<ossimProperty> ossimKmlSuperOverlayWriter::getProperty(
+   const ossimString& name)const
+{
+   return ossimImageFileWriter::getProperty(name);
+}
+
+void ossimKmlSuperOverlayWriter::getPropertyNames(
+   std::vector<ossimString>& propertyNames)const
+{
+   ossimImageFileWriter::getPropertyNames(propertyNames);
+}
+
+void ossimKmlSuperOverlayWriter::generateTile(ossimString filename, 
+   ossim_int32 ix, 
+   ossim_int32 iy, 
+   ossim_int32 dxsize, 
+   ossim_int32 dysize)
+{
+   ossimFilename file = filename;
+   ossimIpt ul(dxsize*ix, dysize*(iy+1));
+   ossimIpt ur(dxsize*(ix+1), dysize*(iy+1));
+   ossimIpt lr(dxsize*(ix+1), dysize*iy);
+   ossimIpt ll(dxsize*ix, dysize*iy);
+   ossimIrect rect(ul, ur, lr, ll);
+
+   m_imageWriter->setFilename(file);
+   m_imageWriter->setAreaOfInterest(rect);
+   m_imageWriter->execute();
+}
+
+bool ossimKmlSuperOverlayWriter::generateRootKml(ossimString filename, 
+   ossim_float64 north, 
+   ossim_float64 south, 
+   ossim_float64 east, 
+   ossim_float64 west, 
+   ossim_int32 tilesize)
+{
+   FILE* fp = fopen(filename.c_str(), "wb");
+   if (fp == NULL)
+   {
+      return false;
+   }
+   ossim_int32 minlodpixels = tilesize/2;
+
+   ossimString tmpfilename = theFilename.fileNoExtension();
+   // If we haven't writen any features yet, output the layer's schema
+   fprintf(fp, "<kml xmlns=\"http://earth.google.com/kml/2.1\">\n");
+   fprintf(fp, "\t<Document>\n");
+   fprintf(fp, "\t\t<name>%s</name>\n", tmpfilename.c_str());
+   fprintf(fp, "\t\t<description></description>\n");
+   fprintf(fp, "\t\t<Style>\n");
+   fprintf(fp, "\t\t\t<ListStyle id=\"hideChildren\">\n");
+   fprintf(fp, "\t\t\t\t<listItemType>checkHideChildren</listItemType>\n");
+   fprintf(fp, "\t\t\t</ListStyle>\n");
+   fprintf(fp, "\t\t</Style>\n");
+   fprintf(fp, "\t\t<Region>\n \t\t<LatLonAltBox>\n");
+   fprintf(fp, "\t\t\t\t<north>%f</north>\n", north);
+   fprintf(fp, "\t\t\t\t<south>%f</south>\n", south);
+   fprintf(fp, "\t\t\t\t<east>%f</east>\n", east);
+   fprintf(fp, "\t\t\t\t<west>%f</west>\n", west);
+   fprintf(fp, "\t\t\t</LatLonAltBox>\n");
+   fprintf(fp, "\t\t</Region>\n");
+   fprintf(fp, "\t\t<NetworkLink>\n");
+   fprintf(fp, "\t\t\t<open>1</open>\n");
+   fprintf(fp, "\t\t\t<Region>\n");
+   fprintf(fp, "\t\t\t\t<Lod>\n");
+   fprintf(fp, "\t\t\t\t\t<minLodPixels>%d</minLodPixels>\n", minlodpixels);
+   fprintf(fp, "\t\t\t\t\t<maxLodPixels>-1</maxLodPixels>\n");
+   fprintf(fp, "\t\t\t\t</Lod>\n");
+   fprintf(fp, "\t\t\t\t<LatLonAltBox>\n");
+   fprintf(fp, "\t\t\t\t\t<north>%f</north>\n", north);
+   fprintf(fp, "\t\t\t\t\t<south>%f</south>\n", south);
+   fprintf(fp, "\t\t\t\t\t<east>%f</east>\n", east);
+   fprintf(fp, "\t\t\t\t\t<west>%f</west>\n", west);
+   fprintf(fp, "\t\t\t\t</LatLonAltBox>\n");
+   fprintf(fp, "\t\t\t</Region>\n");
+   fprintf(fp, "\t\t\t<Link>\n");
+   fprintf(fp, "\t\t\t\t<href>0/0/0.kml</href>\n");
+   fprintf(fp, "\t\t\t\t<viewRefreshMode>onRegion</viewRefreshMode>\n");
+   fprintf(fp, "\t\t\t</Link>\n");
+   fprintf(fp, "\t\t</NetworkLink>\n");
+   fprintf(fp, "\t</Document>\n");
+   fprintf(fp, "</kml>\n");
+
+   fclose(fp);
+   return true;
+}
+
+bool ossimKmlSuperOverlayWriter::generateChildKml(ossimString filename, 
+   ossim_int32 zoom, 
+   ossim_int32 yloop,
+   ossim_int32 ix, 
+   ossim_int32 iy, 
+   ossim_int32 dxsize, 
+   ossim_int32 dysize,
+   ossim_int32 xsize,
+   ossim_int32 ysize, 
+   ossim_int32 maxzoom,
+   ossimRefPtr<ossimMapProjection> proj,
+   ossimString fileExt)
+{
+   ossim_int32 yIndex = yloop-iy-1;
+   ossimIpt ul(dxsize*ix, dysize*(iy+1));
+   ossimIpt ur(dxsize*(ix+1), dysize*(iy+1));
+   ossimIpt lr(dxsize*(ix+1), dysize*iy);
+   ossimIpt ll(dxsize*ix, dysize*iy);
+   ossimIrect rect(ul, ur, lr, ll);
+
+   ossim_float64 tnorth = 0.0;
+   ossim_float64 tsouth = 0.0;
+   ossim_float64 teast = 0.0;
+   ossim_float64 twest = 0.0;
+
+   ossim_float64 upperleftT = 0.0;
+   ossim_float64 lowerleftT = 0.0;
+
+   ossim_float64 rightbottomT = 0.0;
+   ossim_float64 leftbottomT = 0.0;
+
+   ossim_float64 lefttopT = 0.0;
+   ossim_float64 righttopT = 0.0;
+
+   ossim_float64 lowerrightT = 0.0;
+   ossim_float64 upperrightT = 0.0;
+
+   ossimGpt ulg;
+   ossimGpt llg;
+   ossimGpt lrg;
+   ossimGpt urg;
+
+   if (m_mapProjection.valid())
+   {
+      m_mapProjection->lineSampleToWorld(rect.ul(), ulg);
+      m_mapProjection->lineSampleToWorld(rect.ll(), llg);
+      m_mapProjection->lineSampleToWorld(rect.lr(), lrg);
+      m_mapProjection->lineSampleToWorld(rect.ur(), urg);
+
+      twest = llg.lon;
+      tsouth = llg.lat;
+      teast = urg.lon;
+      tnorth = urg.lat;
+
+      upperleftT = ulg.lon;
+      lefttopT = ulg.lat;
+
+      lowerleftT = llg.lon;
+      leftbottomT = llg.lat;
+
+      lowerrightT = lrg.lon;
+      rightbottomT = lrg.lat;
+
+      upperrightT = urg.lon; 
+      righttopT = urg.lat;
+   }
+
+   std::vector<ossim_int32> xchildren;
+   std::vector<ossim_int32> ychildern;
+   std::vector<ossim_int32> ychildernIndex;
+
+   ossim_int32 maxLodPix = -1;
+   if ( zoom < maxzoom )
+   {
+      ossim_float64 zareasize = pow(2.0, (maxzoom - zoom - 1))*dxsize;
+      ossim_float64 zareasize1 = pow(2.0, (maxzoom - zoom - 1))*dysize;
+      xchildren.push_back(ix*2);
+      ossim_int32 tmp = ix*2 + 1;
+      ossim_int32 tmp1 = (ossim_int32)ceil(xsize/zareasize);
+      if (tmp < tmp1)
+      {
+         xchildren.push_back(ix*2+1);
+      }
+
+      ychildern.push_back(iy*2);
+      tmp = iy*2 + 1;
+      tmp1 = (ossim_int32)ceil(ysize/zareasize1);
+      if (tmp < tmp1)
+      {
+         ychildern.push_back(iy*2+1);
+      }    
+
+      ychildernIndex.push_back(yIndex*2);
+      tmp = yIndex*2 + 1;
+      tmp1 = (ossim_int32)ceil(ysize/zareasize1);
+      if (tmp < tmp1)
+      {
+         ychildernIndex.push_back(yIndex*2+1);
+      }    
+      maxLodPix = 2048;
+   }
+
+   FILE* fp = fopen(filename.c_str(), "wb");
+   if (fp == NULL)
+   {
+      return false;
+   }
+
+   fprintf(fp, "<kml xmlns=\"http://earth.google.com/kml/2.1\" xmlns:gx=\"http://www.google.com/kml/ext/2.2\">\n");
+   fprintf(fp, "\t<Document>\n");
+   fprintf(fp, "\t\t<name>%d/%d/%d.kml</name>\n", zoom, ix, yIndex);
+   fprintf(fp, "\t\t<Style>\n");
+   fprintf(fp, "\t\t\t<ListStyle id=\"hideChildren\">\n");
+   fprintf(fp, "\t\t\t\t<listItemType>checkHideChildren</listItemType>\n");
+   fprintf(fp, "\t\t\t</ListStyle>\n");
+   fprintf(fp, "\t\t</Style>\n");
+   fprintf(fp, "\t\t<Region>\n");
+   fprintf(fp, "\t\t\t<Lod>\n");
+   fprintf(fp, "\t\t\t\t<minLodPixels>%d</minLodPixels>\n", 128);
+   fprintf(fp, "\t\t\t\t<maxLodPixels>%d</maxLodPixels>\n", maxLodPix);
+   fprintf(fp, "\t\t\t</Lod>\n");
+   fprintf(fp, "\t\t\t<LatLonAltBox>\n");
+   fprintf(fp, "\t\t\t\t<north>%f</north>\n", tnorth);
+   fprintf(fp, "\t\t\t\t<south>%f</south>\n", tsouth);
+   fprintf(fp, "\t\t\t\t<east>%f</east>\n", teast);
+   fprintf(fp, "\t\t\t\t<west>%f</west>\n", twest);
+   fprintf(fp, "\t\t\t</LatLonAltBox>\n");
+   fprintf(fp, "\t\t</Region>\n");
+   fprintf(fp, "\t\t<GroundOverlay>\n");
+   fprintf(fp, "\t\t\t<drawOrder>%d</drawOrder>\n", zoom);
+   fprintf(fp, "\t\t\t<Icon>\n");
+   fprintf(fp, "\t\t\t\t<href>%d%s</href>\n", yIndex, fileExt.c_str());
+   fprintf(fp, "\t\t\t</Icon>\n");
+   fprintf(fp, "\t\t\t<gx:LatLonQuad>\n");
+   fprintf(fp, "\t\t\t\t<coordinates>\n");
+   fprintf(fp, "\t\t\t\t\t%f, %f, 0\n", lowerleftT, leftbottomT);
+   fprintf(fp, "\t\t\t\t\t%f, %f, 0\n", lowerrightT, rightbottomT);
+   fprintf(fp, "\t\t\t\t\t%f, %f, 0\n", upperrightT, righttopT);
+   fprintf(fp, "\t\t\t\t\t%f, %f, 0\n", upperleftT, lefttopT);
+   fprintf(fp, "\t\t\t\t</coordinates>\n");
+   fprintf(fp, "\t\t\t</gx:LatLonQuad>\n");
+   fprintf(fp, "\t\t</GroundOverlay>\n");
+
+   //generate lat, lon info and links for the previous zoom of kml
+   for (ossim_uint32 i = 0; i < xchildren.size(); i++)
+   {
+      int cx = xchildren[i];
+      for (ossim_uint32 j = 0; j < ychildern.size(); j++)
+      {
+         ossim_int32 cy = ychildern[j];
+         ossim_int32 cyIndex = ychildernIndex[ychildernIndex.size()-j-1];
+
+         ossimIpt ulc(dxsize*cx, dysize*(cy+1));
+         ossimIpt urc(dxsize*(cx+1), dysize*(cy+1));
+         ossimIpt lrc(dxsize*(cx+1), dysize*cy);
+         ossimIpt llc(dxsize*cx, dysize*cy);
+         ossimIrect rectc(ulc, urc, lrc, llc);
+
+         ossim_float64 cnorth = 0.0;
+         ossim_float64 csouth = 0.0;
+         ossim_float64 ceast = 0.0;
+         ossim_float64 cwest = 0.0;
+
+         if (proj.valid())
+         {
+            ulg.makeNan();
+            lrg.makeNan();
+            proj->lineSampleToWorld(rectc.ll(), llg);
+            proj->lineSampleToWorld(rectc.ur(), urg);
+
+            cwest = llg.lon;
+            csouth = llg.lat;
+
+            ceast = urg.lon; 
+            cnorth = urg.lat;
+         }
+
+         fprintf(fp, "\t\t<NetworkLink>\n");
+         fprintf(fp, "\t\t\t<name>%d/%d/%d%s</name>\n", zoom+1, cx, cyIndex, fileExt.c_str());
+         fprintf(fp, "\t\t\t<Region>\n");
+         fprintf(fp, "\t\t\t\t<Lod>\n");
+         fprintf(fp, "\t\t\t\t\t<minLodPixels>128</minLodPixels>\n");
+         fprintf(fp, "\t\t\t\t\t<maxLodPixels>-1</maxLodPixels>\n");
+         fprintf(fp, "\t\t\t\t</Lod>\n");
+         fprintf(fp, "\t\t\t\t<LatLonAltBox>\n");
+         fprintf(fp, "\t\t\t\t\t<north>%f</north>\n", cnorth);
+         fprintf(fp, "\t\t\t\t\t<south>%f</south>\n", csouth);
+         fprintf(fp, "\t\t\t\t\t<east>%f</east>\n", ceast);
+         fprintf(fp, "\t\t\t\t\t<west>%f</west>\n", cwest);
+         fprintf(fp, "\t\t\t\t</LatLonAltBox>\n");
+         fprintf(fp, "\t\t\t</Region>\n");
+         fprintf(fp, "\t\t\t<Link>\n");
+         fprintf(fp, "\t\t\t\t<href>../../%d/%d/%d.kml</href>\n", zoom+1, cx, cyIndex);
+         fprintf(fp, "\t\t\t\t<viewRefreshMode>onRegion</viewRefreshMode>\n");
+         fprintf(fp, "\t\t\t\t<viewFormat/>\n");
+         fprintf(fp, "\t\t\t</Link>\n");
+         fprintf(fp, "\t\t</NetworkLink>\n");
+      }
+   }
+
+   fprintf(fp, "\t</Document>\n");
+   fprintf(fp, "</kml>\n");
+   fclose(fp);
+   return true;
+}
+
+bool ossimKmlSuperOverlayWriter::zipWithMinizip(std::vector<ossimString> srcFiles, ossimString srcDirectory, ossimString targetFile)
+{
+   zipFile zipfile = zipOpen(targetFile.c_str(), 0);
+   if (!zipfile)
+   {
+      ossimSetError(getClassName(),
+         ossimErrorCodes::OSSIM_ERROR,
+         "Unable to open target zip file..");
+      return false;
+   }
+
+   std::vector<ossimString>::iterator v1_Iter;
+   for(v1_Iter = srcFiles.begin(); v1_Iter != srcFiles.end(); v1_Iter++)
+   {
+      ossimString fileRead = *v1_Iter;
+
+      // Find relative path and open new file with zip file
+      std::string relativeFileReadPath = fileRead;
+      ossim_int32 remNumChars = srcDirectory.size();
+      if(remNumChars > 0)
+      {
+         ossim_int32 f = fileRead.find(srcDirectory.string());
+         if( f >= 0 )
+         {
+            relativeFileReadPath.erase(f, remNumChars + 1); // 1 added for backslash at the end
+         }      
+      }
+
+      std::basic_string<char>::iterator iter1;
+      for (iter1 = relativeFileReadPath.begin(); iter1 != relativeFileReadPath.end(); iter1++)
+      {
+         int f = relativeFileReadPath.find("\\");
+         if (f >= 0)
+         {
+            relativeFileReadPath.replace(f, 1, "/");
+         }
+         else
+         {
+            break;
+         }
+      }
+      if (zipOpenNewFileInZip(zipfile, relativeFileReadPath.c_str(), 0, 0, 0, 0, 0, 0, Z_DEFLATED, Z_DEFAULT_COMPRESSION) != ZIP_OK)
+      {
+         ossimSetError(getClassName(),
+            ossimErrorCodes::OSSIM_ERROR,
+            "Unable to create file within the zip file..");
+         return false;
+      }
+
+      // Read source file and write to zip file
+      std::fstream inFile (fileRead.c_str(), std::ios::binary | std::ios::in);
+      if (!inFile.is_open())
+      {
+         ossimSetError(getClassName(),
+            ossimErrorCodes::OSSIM_ERROR,
+            "Could not open source file..");
+         return false;
+      }
+      if (!inFile.good())
+      {
+         ossimSetError(getClassName(),
+            ossimErrorCodes::OSSIM_ERROR,
+            "Error reading source file..");
+         return false;
+      }
+
+      // Read file in buffer
+      std::string fileData;
+      const unsigned int bufSize = 1024;
+      char buf[bufSize];
+      do 
+      {
+         inFile.read(buf, bufSize);
+         fileData.append(buf, inFile.gcount());
+      } while (!inFile.eof() && inFile.good());
+
+      if (zipWriteInFileInZip(zipfile, static_cast<const void*>(fileData.data()), static_cast<unsigned int>(fileData.size())) != ZIP_OK )
+      {
+         ossimSetError(getClassName(),
+            ossimErrorCodes::OSSIM_ERROR,
+            "Could not write to file within zip file..");
+         return false;
+      }
+
+      // Close one src file zipped completely
+      if ( zipCloseFileInZip(zipfile) != ZIP_OK )
+      {
+         ossimSetError(getClassName(),
+            ossimErrorCodes::OSSIM_ERROR,
+            "Could not close file written within zip file..");
+         return false;
+      }
+   }
+
+   zipClose(zipfile, 0);
+   return true;
+}
+
+void ossimKmlSuperOverlayWriter::propagateViewChange()
+{
+   if ( theInputConnection.valid() && m_mapProjection.valid() )
+   {
+      //---
+      // Send a view interface visitor to the input connection.  This will find all view
+      // interfaces, set the view, and send a property event to output so that the combiner,
+      // if present, can reinitialize.
+      //---
+      ossimViewInterfaceVisitor vv( m_mapProjection.get(),
+                                    (ossimViewInterfaceVisitor::VISIT_INPUTS|
+                                     ossimViewInterfaceVisitor::VISIT_CHILDREN) );
+      theInputConnection->accept(vv);
+   }
+}
+
diff --git a/ossim_plugins/kmlsuperoverlay/ossimKmlSuperOverlayWriter.h b/ossim_plugins/kmlsuperoverlay/ossimKmlSuperOverlayWriter.h
new file mode 100644
index 0000000..be50b81
--- /dev/null
+++ b/ossim_plugins/kmlsuperoverlay/ossimKmlSuperOverlayWriter.h
@@ -0,0 +1,175 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author:  Mingjie Su, Harsh Govind
+//
+// Description: OSSIM KmlSuperOverlay writer class declaration.
+//
+//----------------------------------------------------------------------------
+// $Id: ossimKmlSuperOverlayWriter.h 2178 2011-02-17 18:38:30Z ming.su $
+
+#ifndef ossimKmlSuperOverlayWriter_HEADER
+#define ossimKmlSuperOverlayWriter_HEADER 1
+
+//ossim includes
+#include <ossim/imaging/ossimImageFileWriter.h>
+#include <ossim/base/ossimRefPtr.h>
+#include <ossim/base/ossimString.h>
+
+//minizip includes
+#include <minizip/zip.h>
+
+//std includes
+#include <iosfwd>
+#include <vector>
+
+class ossimKeywordlist;
+class ossimMapProjection;
+
+class ossimKmlSuperOverlayWriter : public ossimImageFileWriter
+{
+public:
+
+   /** @brief default constructor */
+   ossimKmlSuperOverlayWriter();
+
+   /* @brief virtual destructor */
+   virtual ~ossimKmlSuperOverlayWriter();
+
+   /** @return "ossim_kmlsuperoverlay_writer" */
+   virtual ossimString getShortName() const;
+
+   /** @return "ossim kmlsuperoverlay writer" */
+   virtual ossimString getLongName()  const;
+
+   /** @return "ossimKmlSuperOverlayWriter" */
+   virtual ossimString getClassName()    const;
+   
+   /**
+    * void getImageTypeList(std::vector<ossimString>& imageTypeList)const
+    *
+    * Appends this writer image types to list "imageTypeList".
+    *
+    * This writer has type "kml" or "kmz".
+    *
+    * @param imageTypeList stl::vector<ossimString> list to append to.
+    */
+   virtual void getImageTypeList(std::vector<ossimString>& imageTypeList)const;
+   
+   virtual bool isOpen()const;   
+   
+   virtual bool open();
+
+   virtual void close();
+   
+   /**
+    * saves the state of the object.
+    */
+   virtual bool saveState(ossimKeywordlist& kwl,
+                          const char* prefix=0)const;
+   
+   /**
+    * Method to the load (recreate) the state of an object from a keyword
+    * list.  Return true if ok or false on error.
+    */
+   virtual bool loadState(const ossimKeywordlist& kwl,
+                          const char* prefix=0);
+
+   /**
+    * Will set the property whose name matches the argument
+    * "property->getName()".
+    *
+    * @param property Object containing property to set.
+    */
+   virtual void setProperty(ossimRefPtr<ossimProperty> property);
+
+   /**
+    * @param name Name of property to return.
+    * 
+    * @returns A pointer to a property object which matches "name".
+    */
+   virtual ossimRefPtr<ossimProperty> getProperty(const ossimString& name)const;
+
+   /**
+    * Pushes this's names onto the list of property names.
+    *
+    * @param propertyNames array to add this's property names to.
+    */
+   virtual void getPropertyNames(std::vector<ossimString>& propertyNames)const;
+
+   /**
+   * Returns a 3-letter extension from the image type descriptor 
+   * (theOutputImageType) that can be used for image file extensions.
+   *
+   * @param imageType string representing image type.
+   *
+   * @return the 3-letter string extension.
+   */
+   virtual ossimString getExtension() const;
+
+   bool hasImageType(const ossimString& imageType) const;
+
+   /**
+   * @brief Method to write the image to a stream.
+   *
+   * @return true on success, false on error.
+   */
+   virtual bool writeStream();
+
+protected:
+   /**
+    * @brief Writes the file to disk or a stream.
+    * @return true on success, false on error.
+    */
+   virtual bool writeFile(); 
+
+   bool generateRootKml(ossimString filename, 
+                       ossim_float64 north, 
+                       ossim_float64 south, 
+                       ossim_float64 east, 
+                       ossim_float64 west, 
+                       ossim_int32 tilesize);
+
+   bool generateChildKml(ossimString filename, 
+                         ossim_int32 zoom, 
+                         ossim_int32 yloop,
+                         ossim_int32 ix, 
+                         ossim_int32 iy, 
+                         ossim_int32 dxsize, 
+                         ossim_int32 dysize, 
+                         ossim_int32 xsize,
+                         ossim_int32 ysize, 
+                         ossim_int32 maxzoom, 
+                         ossimRefPtr<ossimMapProjection> proj,
+                         ossimString fileExt);
+
+   void generateTile(ossimString filename, 
+                     ossim_int32 ix, 
+                     ossim_int32 iy, 
+                     ossim_int32 dxsize, 
+                     ossim_int32 dysize);
+
+   bool zipWithMinizip(std::vector<ossimString> srcFiles, 
+                       ossimString srcDirectory, 
+                       ossimString targetFile);
+
+   /**
+    * @brief Sends a view interface visitor to the input connetion.  This will
+    * find all view interfaces, set the view, and send a property event to
+    * output so that the combiner, if present, can reinitialize.
+    */
+   void propagateViewChange();
+
+   ossimRefPtr<ossimImageFileWriter> m_imageWriter;
+   ossimRefPtr<ossimMapProjection>   m_mapProjection;
+   bool m_isKmz;
+   bool m_isPngFormat;
+
+ TYPE_DATA
+};
+
+#endif
+
diff --git a/ossim_plugins/kmlsuperoverlay/ossimKmlSuperOverlayWriterFactory.cpp b/ossim_plugins/kmlsuperoverlay/ossimKmlSuperOverlayWriterFactory.cpp
new file mode 100644
index 0000000..65dd918
--- /dev/null
+++ b/ossim_plugins/kmlsuperoverlay/ossimKmlSuperOverlayWriterFactory.cpp
@@ -0,0 +1,132 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author:  Mingjie Su, Harsh Govind
+//
+// Description: Factory for OSSIM KmlSuperOverlay writers.
+//----------------------------------------------------------------------------
+// $Id: ossimKmlSuperOverlayWriterFactory.cpp 2178 2011-02-17 18:38:30Z ming.su $
+
+#include <ossim/base/ossimKeywordNames.h>
+#include <ossim/base/ossimRefPtr.h>
+#include <ossim/imaging/ossimImageFileWriter.h>
+
+#include "ossimKmlSuperOverlayWriterFactory.h"
+#include "ossimKmlSuperOverlayWriter.h"
+
+ossimKmlSuperOverlayWriterFactory* ossimKmlSuperOverlayWriterFactory::theInstance = 0;
+
+RTTI_DEF1(ossimKmlSuperOverlayWriterFactory,
+          "ossimKmlSuperOverlayWriterFactory",
+          ossimImageWriterFactoryBase);
+
+ossimKmlSuperOverlayWriterFactory::~ossimKmlSuperOverlayWriterFactory()
+{
+   theInstance = 0;
+}
+
+ossimKmlSuperOverlayWriterFactory* ossimKmlSuperOverlayWriterFactory::instance()
+{
+   if(!theInstance)
+   {
+      theInstance = new ossimKmlSuperOverlayWriterFactory;
+   }
+   return theInstance;
+}
+
+ossimImageFileWriter* ossimKmlSuperOverlayWriterFactory::createWriterFromExtension(
+   const ossimString& fileExtension)const
+{
+   ossimImageFileWriter* writer = 0;
+
+   if(fileExtension == "kml" || fileExtension == "kmz")
+   {
+      writer = new ossimKmlSuperOverlayWriter;
+   }
+   return writer;
+}
+
+void ossimKmlSuperOverlayWriterFactory::getImageFileWritersBySuffix(ossimImageWriterFactoryBase::ImageFileWriterList& result,
+                                                        const ossimString& ext)const
+{
+   ossimString testExt = ext.downcase();
+   if(testExt == "kml" || testExt == "kmz")
+   {
+      result.push_back(new ossimKmlSuperOverlayWriter);
+   }
+}
+
+ossimImageFileWriter*
+ossimKmlSuperOverlayWriterFactory::createWriter(const ossimKeywordlist& kwl,
+                                       const char *prefix)const
+{
+   ossimRefPtr<ossimImageFileWriter> writer = 0;
+   const char* type = kwl.find(prefix, ossimKeywordNames::TYPE_KW);
+   if (type)
+   {
+      writer = createWriter(ossimString(type));
+      if (writer.valid())
+      {
+         if (writer->loadState(kwl, prefix) == false)
+         {
+            writer = 0;
+         }
+      }
+   }
+   return writer.release();
+}
+
+ossimImageFileWriter* ossimKmlSuperOverlayWriterFactory::createWriter(
+   const ossimString& typeName)const
+{
+   ossimRefPtr<ossimImageFileWriter> writer = 0;
+   if (typeName == "ossimKmlSuperOverlayWriter" || typeName == "ossim_kmlsuperoverlay")
+   {
+      writer = new ossimKmlSuperOverlayWriter;
+   }
+   return writer.release();
+}
+
+ossimObject* ossimKmlSuperOverlayWriterFactory::createObject(
+   const ossimKeywordlist& kwl, const char *prefix)const
+{
+   return createWriter(kwl, prefix);
+}
+
+ossimObject* ossimKmlSuperOverlayWriterFactory::createObject(
+   const ossimString& typeName) const
+{
+   return createWriter(typeName);
+}
+
+void ossimKmlSuperOverlayWriterFactory::getExtensions(
+   std::vector<ossimString>& result)const
+{
+   result.push_back("kml");
+   result.push_back("kmz");
+}
+
+void ossimKmlSuperOverlayWriterFactory::getTypeNameList(std::vector<ossimString>& typeList)const
+{
+   getImageTypeList(typeList);
+}
+
+//---
+// Adds our writers to the list of writers...
+//---
+void ossimKmlSuperOverlayWriterFactory::getImageTypeList(std::vector<ossimString>& imageTypeList)const
+{
+   ossimRefPtr<ossimImageFileWriter> writer = new ossimKmlSuperOverlayWriter;
+   writer->getImageTypeList(imageTypeList);
+}
+
+ossimKmlSuperOverlayWriterFactory::ossimKmlSuperOverlayWriterFactory(){}
+
+ossimKmlSuperOverlayWriterFactory::ossimKmlSuperOverlayWriterFactory(const ossimKmlSuperOverlayWriterFactory&){}
+
+void ossimKmlSuperOverlayWriterFactory::operator=(const ossimKmlSuperOverlayWriterFactory&){}
+
+
diff --git a/ossim_plugins/kmlsuperoverlay/ossimKmlSuperOverlayWriterFactory.h b/ossim_plugins/kmlsuperoverlay/ossimKmlSuperOverlayWriterFactory.h
new file mode 100644
index 0000000..0870122
--- /dev/null
+++ b/ossim_plugins/kmlsuperoverlay/ossimKmlSuperOverlayWriterFactory.h
@@ -0,0 +1,115 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author:  Mingjie Su, Harsh Govind
+//
+// Description: Factory for OSSIM KmlSuperOverlay writers.
+//----------------------------------------------------------------------------
+// $Id: ossimKmlSuperOverlayWriterFactory.h 2178 2011-02-17 18:38:30Z ming.su $
+
+#ifndef ossimKmlSuperOverlayWriterFactory_HEADER
+#define ossimKmlSuperOverlayWriterFactory_HEADER
+
+#include <ossim/imaging/ossimImageWriterFactoryBase.h>
+
+class ossimImageFileWriter;
+class ossimKeywordlist;
+class ossimImageWriterFactory;
+
+/** @brief Factory for kmlsuperoverlay based image writers. */
+class ossimKmlSuperOverlayWriterFactory: public ossimImageWriterFactoryBase
+{   
+public:
+
+   /** @brief virtual destructor */
+   virtual ~ossimKmlSuperOverlayWriterFactory();
+
+   /**
+    * @brief static method to return instance (the only one) of this class.
+    * @return pointer to instance of this class.
+    */
+   static ossimKmlSuperOverlayWriterFactory* instance();
+
+   /**
+    * @brief Creates a writer from extension like "sid".
+    * @param fileExtension "sid"
+    */
+   virtual ossimImageFileWriter *createWriterFromExtension(
+      const ossimString& fileExtension)const;
+
+   /**
+    * @brief Create that takes a keyword list and prefix.
+    * @param kwl The keyword list.
+    * @param prefix the keyword list prefix.
+    * @return pointer to image handler on success, NULL on failure.
+    */
+   virtual ossimImageFileWriter* createWriter(const ossimKeywordlist& kwl,
+                                              const char *prefix=0)const;
+
+   /**
+    * @brief createWriter that takes a class name (ossimKakaduWriter)
+    * @param kwl The keyword list.
+    * @param prefix the keyword list prefix.
+    * @return pointer to image writer on success, NULL on failure.
+    */
+   virtual ossimImageFileWriter* createWriter(const ossimString& typeName)const;
+
+   /**
+    * @brief Creates and object given a keyword list.
+    * @param kwl The keyword list.
+    * @param prefix the keyword list prefix.
+    * @return pointer to image writer on success, NULL on failure.
+    */
+   virtual ossimObject* createObject(const ossimKeywordlist& kwl,
+                                     const char *prefix=0)const;
+
+   /**
+    * @brief createObject that takes a class name (ossimKakaduWriter)
+    * @param typeName Should be "ossimKakaduReader".
+    * @return pointer to image writer on success, NULL on failure.
+    */
+   virtual ossimObject* createObject(const ossimString& typeName)const;
+
+
+   /**
+    * @brief Adds "ntf" to list.
+    * @param extList List to add to.
+    */
+   virtual void getExtensions(std::vector<ossimString>& extList)const;
+
+   /**
+    * @brief Adds "ossimKakaduWriter" to list.
+    * @param typeList List to add to.
+    */
+   virtual void getTypeNameList(std::vector<ossimString>& typeList)const;
+   
+   /**
+    * @brief Adds "ossim_kakada_nitf_j2k" to writer list.
+    * @param imageTypeList List to append to.
+    */
+   virtual void getImageTypeList(std::vector<ossimString>& imageTypeList)const;
+
+   virtual void getImageFileWritersBySuffix(ossimImageWriterFactoryBase::ImageFileWriterList& result,
+                                            const ossimString& ext)const;
+   
+protected:
+   /** @brief hidden from use default constructor */
+   ossimKmlSuperOverlayWriterFactory();
+
+   /** @brief hidden from use copy constructor */
+   ossimKmlSuperOverlayWriterFactory(const ossimKmlSuperOverlayWriterFactory&);
+
+   /** @brief hidden from use copy constructor */
+   void operator=(const ossimKmlSuperOverlayWriterFactory&);
+
+   /** static instance of this class */
+   static ossimKmlSuperOverlayWriterFactory* theInstance;
+
+TYPE_DATA
+};
+
+#endif /* end of #ifndef ossimKmlSuperOverlayWriterFactory_HEADER */
+
diff --git a/ossim_plugins/las/CMakeLists.txt b/ossim_plugins/las/CMakeLists.txt
new file mode 100644
index 0000000..9c25b0a
--- /dev/null
+++ b/ossim_plugins/las/CMakeLists.txt
@@ -0,0 +1,32 @@
+set(LIB_NAME ossimlas_plugin)
+MESSAGE( "************** LIBRARY SETUP FOR ossimlas_plugin******************")
+
+# Include ossim cmake stuff:
+include(OssimVersion)
+include(OssimCommonVariables)
+include(OssimUtilities)
+
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
+
+FILE(GLOB OSSIMPLUGIN_SRCS *.cpp)
+FILE(GLOB OSSIMPLUGIN_HEADERS *.h)
+
+####
+# OSSIMPLUGINSMAKINGDLL controls dll linkage on windows.  
+# Adding this sets OSSIM_PLUGINS_DLL #define TO "__declspec(dllexport)".
+###
+add_definitions("-DOSSIMPLUGINSMAKINGDLL")
+
+# Adjust the install library path:
+if(OSSIM_INSTALL_PLUGINS_WITH_VERSION)
+   set(INSTALL_LIBRARY_DIR   "${INSTALL_LIBRARY_DIR}/ossim-${OSSIM_VERSION}/plugins")
+else(OSSIM_INSTALL_PLUGINS_WITH_VERSION)
+   set(INSTALL_LIBRARY_DIR   "${INSTALL_LIBRARY_DIR}/ossim/plugins")
+endif(OSSIM_INSTALL_PLUGINS_WITH_VERSION)
+
+OSSIM_LINK_LIBRARY(${LIB_NAME}
+                   COMPONENT_NAME ossim TYPE "${OSSIM_PLUGIN_LINK_TYPE}"
+		   LIBRARIES ${OSSIM_LIBRARY}
+                   HEADERS "${OSSIMPLUGIN_HEADERS}"
+		   SOURCE_FILES "${OSSIMPLUGIN_SRCS}"
+                   INSTALL_LIB)
diff --git a/ossim_plugins/las/ossimLasPluginInit.cpp b/ossim_plugins/las/ossimLasPluginInit.cpp
new file mode 100644
index 0000000..b3e7e3b
--- /dev/null
+++ b/ossim_plugins/las/ossimLasPluginInit.cpp
@@ -0,0 +1,72 @@
+//----------------------------------------------------------------------------
+//
+// License:  See top level LICENSE.txt file
+//
+// Author:  David Burken
+//
+// Description: LAS plugin initialization code.
+//
+//----------------------------------------------------------------------------
+// $Id
+
+#include <ossim/plugin/ossimSharedObjectBridge.h>
+#include "../ossimPluginConstants.h"
+#include "ossimLasReaderFactory.h"
+#include <ossim/base/ossimString.h>
+#include <ossim/imaging/ossimImageHandlerRegistry.h>
+
+static void setDescription(ossimString& description)
+{
+   description = "LAS LIDAR reader / writer plugin\n\n";
+}
+
+
+extern "C"
+{
+   ossimSharedObjectInfo  myInfo;
+   ossimString theDescription;
+   std::vector<ossimString> theObjList;
+   
+   const char* getDescription()
+   {
+      return theDescription.c_str();
+   }
+   
+   int getNumberOfClassNames()
+   {
+      return (int)theObjList.size();
+   }
+   
+   const char* getClassName(int idx)
+   {
+      if(idx < (int)theObjList.size())
+      {
+         return theObjList[0].c_str();
+      }
+      return (const char*)0;
+   }
+   
+   /* Note symbols need to be exported on windoze... */ 
+   OSSIM_PLUGINS_DLL void ossimSharedLibraryInitialize(
+      ossimSharedObjectInfo** info)
+   {    
+      myInfo.getDescription = getDescription;
+      myInfo.getNumberOfClassNames = getNumberOfClassNames;
+      myInfo.getClassName = getClassName;
+      
+      *info = &myInfo;
+      
+      /* Register the readers... */
+      ossimImageHandlerRegistry::instance()->
+         registerFactory(ossimLasReaderFactory::instance());
+      
+      setDescription(theDescription);
+   }
+   
+   /* Note symbols need to be exported on windoze... */ 
+   OSSIM_PLUGINS_DLL void ossimSharedLibraryFinalize()
+   {
+      ossimImageHandlerRegistry::instance()->
+         unregisterFactory(ossimLasReaderFactory::instance());
+   }
+}
diff --git a/ossim_plugins/las/ossimLasPointRecord1.cpp b/ossim_plugins/las/ossimLasPointRecord1.cpp
new file mode 100644
index 0000000..b49077f
--- /dev/null
+++ b/ossim_plugins/las/ossimLasPointRecord1.cpp
@@ -0,0 +1,193 @@
+//----------------------------------------------------------------------------
+//
+// File: ossimLasPointRecord1.cpp
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author:  David Burken
+//
+// Description: Container class LAS point record type 1.
+//
+//----------------------------------------------------------------------------
+// $Id: ossimLasPointRecord1.cpp 2645 2011-05-26 15:21:34Z oscar.kramer $
+
+#include "ossimLasPointRecord1.h"
+#include <ossim/base/ossimCommon.h>
+#include <ossim/base/ossimEndian.h>
+#include <iomanip>
+#include <iostream>
+#include <istream>
+#include <ostream>
+
+ossimLasPointRecord1::ossimLasPointRecord1Data::ossimLasPointRecord1Data()
+   :
+   m_x(0),
+   m_y(0),
+   m_z(0),
+   m_intensity(0),
+   m_returnByte(0),
+   m_classification(0),
+   m_scanAngleRank(0),
+   m_userData(0),
+   m_pointSourceID(0),
+   m_gpsTime(0.0)
+{
+}
+
+ossimLasPointRecord1::ossimLasPointRecord1Data::ossimLasPointRecord1Data(
+   const ossimLasPointRecord1::ossimLasPointRecord1Data& obj)
+   :
+   m_x(obj.m_x),
+   m_y(obj.m_y),
+   m_z(obj.m_z),
+   m_intensity(obj.m_intensity),
+   m_returnByte(obj.m_returnByte),
+   m_classification(obj.m_classification),
+   m_scanAngleRank(obj.m_scanAngleRank),
+   m_userData(obj.m_userData),
+   m_pointSourceID(obj.m_pointSourceID),
+   m_gpsTime(obj.m_gpsTime)
+{
+}
+
+const ossimLasPointRecord1::ossimLasPointRecord1Data&
+ossimLasPointRecord1::ossimLasPointRecord1Data::operator=(
+   const ossimLasPointRecord1::ossimLasPointRecord1Data& obj)
+{
+   if ( this != &obj )
+   {
+      m_x = obj.m_x;
+      m_y = obj.m_y;
+      m_z = obj.m_z;
+      m_intensity      = obj.m_intensity;
+      m_returnByte     = obj.m_returnByte;
+      m_classification = obj.m_classification;
+      m_scanAngleRank  = obj.m_scanAngleRank;
+      m_userData       = obj.m_userData;
+      m_pointSourceID  = obj.m_pointSourceID;
+      m_gpsTime        = obj.m_gpsTime;
+   }
+   return *this;
+}
+
+ossimLasPointRecord1::ossimLasPointRecord1()
+   :
+   m_record()
+{
+}
+
+ossimLasPointRecord1::ossimLasPointRecord1(const ossimLasPointRecord1& obj)
+   :
+   m_record(obj.m_record)
+{
+}
+
+const ossimLasPointRecord1& ossimLasPointRecord1::operator=(const ossimLasPointRecord1& copy_this)
+{
+   if (this != &copy_this)
+   {
+      m_record = copy_this.m_record;
+   }
+   return *this;
+}
+
+ossimLasPointRecord1::~ossimLasPointRecord1()
+{
+}
+
+void ossimLasPointRecord1::readStream(std::istream& in)
+{
+   in.read((char*)&m_record, 28);
+
+   if ( ossim::byteOrder() == OSSIM_BIG_ENDIAN )
+   {
+      swap();
+   }
+}
+
+void ossimLasPointRecord1::writeStream(std::ostream& out)
+{
+   if ( ossim::byteOrder() == OSSIM_BIG_ENDIAN )
+   {
+      // Write little endian per spec:
+      swap();
+   }
+
+   out.write((char*)&m_record, 28);
+
+   if ( ossim::byteOrder() == OSSIM_BIG_ENDIAN )
+   {
+      // Swap back to native byte order if needed:
+      swap();
+   }
+}
+
+ossim_int32 ossimLasPointRecord1::getX() const
+{
+   return m_record.m_x;
+}
+
+ossim_int32 ossimLasPointRecord1::getY() const
+{
+   return m_record.m_y;
+}
+
+ossim_int32 ossimLasPointRecord1::getZ() const
+{
+   return m_record.m_z;
+}
+
+ossim_uint8 ossimLasPointRecord1::getReturnNumber() const
+{
+   return (0x07 & m_record.m_returnByte);
+}
+
+ossim_uint8 ossimLasPointRecord1::getNumberOfReturns() const
+{
+   return (0x34 & m_record.m_returnByte);
+}
+
+ossim_uint8 ossimLasPointRecord1::getEdgeFlag() const
+{
+   return (0x40 & m_record.m_returnByte);
+}
+
+std::ostream& ossimLasPointRecord1::print(std::ostream& out) const
+{
+   // Capture the original flags.
+   std::ios_base::fmtflags f = out.flags();
+
+   out << std::setiosflags(std::ios_base::fixed) << std::setprecision(8);
+
+   out << "x:                 " << m_record.m_x
+       << "\ny:                 " << m_record.m_y
+       << "\nz:                 " << m_record.m_z
+       << "\nintensity:         " << m_record.m_intensity
+       << "\nreturn:            " << int(getReturnNumber())
+       << "\nnumber_of_returns: " << int(getNumberOfReturns())
+       << "\nedge:              " << (getEdgeFlag()?"true":"false")
+       << "\nclassification:    " << m_record.m_classification
+       << "\nscan_angle_rank:   " << int(m_record.m_scanAngleRank)
+       << "\nuser_data:         " << m_record.m_userData
+       << "\npoint_source_id:   " << m_record.m_pointSourceID
+       << "\ngps_time:          " << m_record.m_gpsTime
+       << std::endl;
+
+   // Reset flags.
+   out.setf(f);
+   return out;
+}
+
+void ossimLasPointRecord1::swap()
+{
+   ossimEndian endian;
+   endian.swap(m_record.m_x);
+   endian.swap(m_record.m_y);
+   endian.swap(m_record.m_z);
+   endian.swap(m_record.m_intensity);
+   endian.swap(m_record.m_pointSourceID);
+   endian.swap(m_record.m_gpsTime);
+}
+
diff --git a/ossim_plugins/las/ossimLasPointRecord1.h b/ossim_plugins/las/ossimLasPointRecord1.h
new file mode 100644
index 0000000..2bd9b1a
--- /dev/null
+++ b/ossim_plugins/las/ossimLasPointRecord1.h
@@ -0,0 +1,91 @@
+//----------------------------------------------------------------------------
+//
+// File: ossimLasPointRecord1.h
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author:  David Burken
+//
+// Description: Container class for LAS point record type 1.
+//
+//----------------------------------------------------------------------------
+// $Id: ossimLasPointRecord1.h 2645 2011-05-26 15:21:34Z oscar.kramer $
+#ifndef ossimLasPointRecord1_HEADER
+#define ossimLasPointRecord1_HEADER 1
+
+#include "ossimLasPointRecordInterface.h"
+
+class ossimLasPointRecord1 : public ossimLasPointRecordInterface
+{
+public:
+
+   /** @brief default constructor */
+   ossimLasPointRecord1();
+
+   /* @brief copy constructor */
+   ossimLasPointRecord1(const ossimLasPointRecord1& obj);
+
+   /* @brief assignment operator= */
+   const ossimLasPointRecord1& operator=(const ossimLasPointRecord1& copy_this);
+
+   /** @brief destructor */
+   virtual ~ossimLasPointRecord1();
+
+   /** @brief Initialize record from stream. */
+   virtual void readStream(std::istream& in);
+
+   /** @brief Writes record to stream. */
+   virtual void writeStream(std::ostream& out);
+
+   /** @return x */
+   virtual ossim_int32 getX() const;
+
+   /** @return y */
+   virtual ossim_int32 getY() const;
+   
+   /** @return z */
+   virtual ossim_int32 getZ() const;
+
+   /** @return return number */
+   virtual ossim_uint8 getReturnNumber() const;
+
+   virtual ossim_uint8 getNumberOfReturns() const;
+   
+   virtual ossim_uint8 getEdgeFlag() const;
+      
+   virtual std::ostream& print(std::ostream& out) const;
+
+private:
+
+   /** @brief Performs a swap if system byte order is not little endian. */
+   void swap();
+
+   //---
+   // Private structure so we can do a single read/write in the readStream
+   // and writeStream methods.  This sped the code up 5X when doing an ossim-icp
+   // from a LAS file to a tif.
+   //---
+   struct ossimLasPointRecord1Data
+   {
+      ossimLasPointRecord1Data();
+      ossimLasPointRecord1Data(const ossimLasPointRecord1Data& obj);
+      const ossimLasPointRecord1Data& operator=(const ossimLasPointRecord1Data& obj);
+      ossim_int32   m_x;
+      ossim_int32   m_y;
+      ossim_int32   m_z;
+      ossim_uint16  m_intensity;
+      ossim_uint8   m_returnByte;
+      ossim_uint8   m_classification;
+      ossim_int8    m_scanAngleRank;
+      ossim_uint8   m_userData;
+      ossim_uint16  m_pointSourceID;
+      ossim_float64 m_gpsTime;
+   };
+   
+   ossimLasPointRecord1Data m_record;
+};
+
+#endif /* #ifndef ossimLasPointRecord1_HEADER */
+
diff --git a/ossim_plugins/las/ossimLasPointRecord2.cpp b/ossim_plugins/las/ossimLasPointRecord2.cpp
new file mode 100644
index 0000000..f00f604
--- /dev/null
+++ b/ossim_plugins/las/ossimLasPointRecord2.cpp
@@ -0,0 +1,204 @@
+//----------------------------------------------------------------------------
+//
+// File: ossimLasPointRecord2.cpp
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author:  Garrett Potts
+//
+// Description: Container class LAS point record type 2.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include "ossimLasPointRecord2.h"
+#include <ossim/base/ossimCommon.h>
+#include <ossim/base/ossimEndian.h>
+#include <iomanip>
+#include <iostream>
+#include <istream>
+#include <ostream>
+
+ossimLasPointRecord2::ossimLasPointRecord2Data::ossimLasPointRecord2Data()
+   :
+   m_x(0),
+   m_y(0),
+   m_z(0),
+   m_intensity(0),
+   m_bitFlags(0),
+   m_classification(0),
+   m_scanAngleRank(0),
+   m_userData(0),
+   m_pointSourceId(0),
+   m_red(0),
+   m_green(0),
+   m_blue(0)
+{
+}
+
+ossimLasPointRecord2::ossimLasPointRecord2Data::ossimLasPointRecord2Data(
+   const ossimLasPointRecord2::ossimLasPointRecord2Data& obj)
+   :
+   m_x(obj.m_x),
+   m_y(obj.m_y),
+   m_z(obj.m_z),
+   m_intensity(obj.m_intensity),
+   m_bitFlags(obj.m_bitFlags),
+   m_classification(obj.m_classification),
+   m_scanAngleRank(obj.m_scanAngleRank),
+   m_userData(obj.m_userData),
+   m_pointSourceId(obj.m_pointSourceId),
+   m_red(obj.m_red),
+   m_green(obj.m_green),
+   m_blue(obj.m_blue)   
+{
+}
+
+const ossimLasPointRecord2::ossimLasPointRecord2Data&
+ossimLasPointRecord2::ossimLasPointRecord2Data::operator=(
+   const ossimLasPointRecord2::ossimLasPointRecord2Data& obj)
+{
+   if ( this != &obj )
+   {
+      m_x              = obj.m_x;
+      m_y              = obj.m_y;
+      m_z              = obj.m_z;
+      m_intensity      = obj.m_intensity;
+      m_bitFlags       = obj.m_bitFlags;
+      m_classification = obj.m_classification;
+      m_scanAngleRank  = obj.m_scanAngleRank;
+      m_userData       = obj.m_userData;
+      m_pointSourceId  = obj.m_pointSourceId;
+      m_red            = obj.m_red;
+      m_green          = obj.m_green;
+      m_blue           = obj.m_blue;
+   }
+   return *this;
+}
+
+ossimLasPointRecord2::ossimLasPointRecord2()
+   :
+   m_record()
+{
+}
+
+ossimLasPointRecord2::ossimLasPointRecord2(const ossimLasPointRecord2& obj)
+   :
+   m_record(obj.m_record)
+{
+}
+
+const ossimLasPointRecord2& ossimLasPointRecord2::operator=(const ossimLasPointRecord2& copy_this)
+{
+   if (this != &copy_this)
+   {
+      m_record = copy_this.m_record;
+   }
+   return *this;
+}
+
+ossimLasPointRecord2::~ossimLasPointRecord2()
+{
+}
+
+void ossimLasPointRecord2::readStream(std::istream& in)
+{
+   in.read((char*)&m_record, sizeof(ossimLasPointRecord2Data));
+
+   if ( ossim::byteOrder() == OSSIM_BIG_ENDIAN )
+   {
+      swap();
+   }
+}
+
+void ossimLasPointRecord2::writeStream(std::ostream& out)
+{
+   if ( ossim::byteOrder() == OSSIM_BIG_ENDIAN )
+   {
+      // Write little endian per spec:
+      swap();
+   }
+
+   out.write((char*)&m_record, sizeof(ossimLasPointRecord2Data));
+
+   if ( ossim::byteOrder() == OSSIM_BIG_ENDIAN )
+   {
+      // Swap back to native byte order if needed:
+      swap();
+   }
+}
+
+ossim_int32 ossimLasPointRecord2::getX() const
+{
+   return m_record.m_x;
+}
+
+ossim_int32 ossimLasPointRecord2::getY() const
+{
+   return m_record.m_y;
+}
+
+ossim_int32 ossimLasPointRecord2::getZ() const
+{
+   return m_record.m_z;
+}
+
+ossim_uint8 ossimLasPointRecord2::getReturnNumber() const
+{
+   return (m_record.m_bitFlags.m_returnNumber);
+}
+
+ossim_uint8 ossimLasPointRecord2::getNumberOfReturns() const
+{
+   return (m_record.m_bitFlags.m_numberOfReturns);
+}
+
+ossim_uint8 ossimLasPointRecord2::getEdgeFlag() const
+{
+   return (m_record.m_bitFlags.m_edgeOfFlightLine);
+}
+
+std::ostream& ossimLasPointRecord2::print(std::ostream& out) const
+{
+   // Capture the original flags.
+   std::ios_base::fmtflags f = out.flags();
+
+   out << std::setiosflags(std::ios_base::fixed) << std::setprecision(8);
+ 
+   out << "x:                 " << m_record.m_x
+       << "\ny:                 " << m_record.m_y
+       << "\nz:                 " << m_record.m_z
+       << "\nintensity:         " << m_record.m_intensity
+       << "\nreturn:            " << int(getReturnNumber())
+       << "\nnumber_of_returns: " << int(getNumberOfReturns())
+       << "\nedge:              " << (getEdgeFlag()?"true":"false")
+       << "\nscan_direction:    " << int(m_record.m_bitFlags.m_scanDirection)
+       << "\nclassification:    " << m_record.m_classification
+       << "\nscan_angle_rank:   " << int(m_record.m_scanAngleRank)
+       << "\nuser_data:         " << m_record.m_userData
+       << "\npoint_source_id:   " << m_record.m_pointSourceId
+       << "\nred:               " << m_record.m_red
+       << "\ngreen:             " << m_record.m_green
+       << "\nblue:              " << m_record.m_blue
+       << std::endl;
+
+   // Reset flags.
+   out.setf(f);
+   return out;
+}
+
+void ossimLasPointRecord2::swap()
+{
+   ossimEndian endian;
+   endian.swap(m_record.m_x);
+   endian.swap(m_record.m_y);
+   endian.swap(m_record.m_z);
+   endian.swap(m_record.m_intensity);
+   endian.swap(m_record.m_pointSourceId);
+   endian.swap(m_record.m_red);
+   endian.swap(m_record.m_green);
+   endian.swap(m_record.m_blue);   
+}
+
diff --git a/ossim_plugins/las/ossimLasPointRecord2.h b/ossim_plugins/las/ossimLasPointRecord2.h
new file mode 100644
index 0000000..f7fd8c3
--- /dev/null
+++ b/ossim_plugins/las/ossimLasPointRecord2.h
@@ -0,0 +1,108 @@
+//----------------------------------------------------------------------------
+//
+// File: ossimLasPointRecord2.h
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author:  Garrett Potts
+//
+// Description: Container class for LAS point record type 2.
+//
+//----------------------------------------------------------------------------
+// $Id$
+#ifndef ossimLasPointRecord2_HEADER
+#define ossimLasPointRecord2_HEADER 1
+
+#include "ossimLasPointRecordInterface.h"
+
+class ossimLasPointRecord2 : public ossimLasPointRecordInterface
+{
+public:
+
+   /** @brief default constructor */
+   ossimLasPointRecord2();
+
+   /* @brief copy constructor */
+   ossimLasPointRecord2(const ossimLasPointRecord2& obj);
+
+   /* @brief assignment operator= */
+   const ossimLasPointRecord2& operator=(const ossimLasPointRecord2& copy_this);
+
+   /** @brief destructor */
+   virtual ~ossimLasPointRecord2();
+
+   /** @brief Initialize record from stream. */
+   virtual void readStream(std::istream& in);
+
+   /** @brief Writes record to stream. */
+   virtual void writeStream(std::ostream& out);
+
+   /** @return x */
+   virtual ossim_int32 getX() const;
+
+   /** @return y */
+   virtual ossim_int32 getY() const;
+   
+   /** @return z */
+   virtual ossim_int32 getZ() const;
+
+   /** @return return number */
+   virtual ossim_uint8 getReturnNumber() const;
+
+   virtual ossim_uint8 getNumberOfReturns() const;
+   
+   virtual ossim_uint8 getEdgeFlag() const;
+      
+   virtual std::ostream& print(std::ostream& out) const;
+
+private:
+
+   /** @brief Performs a swap if system byte order is not little endian. */
+   void swap();
+
+   union BitFlags
+   {
+      BitFlags(const BitFlags& obj):m_bits(obj.m_bits){}
+      BitFlags(ossim_uint8 value):m_bits((ossim_uint8)value){}
+      const BitFlags& operator =(const BitFlags& obj){m_bits = obj.m_bits;return *this;}
+      struct
+      {
+         ossim_uint8 m_returnNumber     : 3;
+         ossim_uint8 m_numberOfReturns  : 3;
+         ossim_uint8 m_scanDirection    : 1;
+         ossim_uint8 m_edgeOfFlightLine : 1;
+      };
+      ossim_uint8 m_bits;
+   };
+
+   //---
+   // Private structure so we can do a single read/write in the readStream
+   // and writeStream methods.  This sped the code up 5X when doing an ossim-icp
+   // from a LAS file to a tif.
+   //---
+   struct ossimLasPointRecord2Data
+   {
+      ossimLasPointRecord2Data();
+      ossimLasPointRecord2Data(const ossimLasPointRecord2Data& obj);
+      const ossimLasPointRecord2Data& operator=(const ossimLasPointRecord2Data& obj);
+      ossim_int32   m_x;
+      ossim_int32   m_y;
+      ossim_int32   m_z;
+      ossim_uint16  m_intensity;
+      BitFlags      m_bitFlags;
+      ossim_uint8   m_classification;
+      ossim_int8    m_scanAngleRank;
+      ossim_uint8   m_userData;
+      ossim_uint16  m_pointSourceId;
+      ossim_uint16  m_red;
+      ossim_uint16  m_green;
+      ossim_uint16  m_blue;
+   };
+   
+   ossimLasPointRecord2Data m_record;
+};
+
+#endif /* #ifndef ossimLasPointRecord2_HEADER */
+
diff --git a/ossim_plugins/las/ossimLasPointRecord3.cpp b/ossim_plugins/las/ossimLasPointRecord3.cpp
new file mode 100644
index 0000000..45764e9
--- /dev/null
+++ b/ossim_plugins/las/ossimLasPointRecord3.cpp
@@ -0,0 +1,209 @@
+//----------------------------------------------------------------------------
+//
+// File: ossimLasPointRecord3.cpp
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author:  Garrett Potts
+//
+// Description: Container class LAS point record type 3.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include "ossimLasPointRecord3.h"
+#include <ossim/base/ossimCommon.h>
+#include <ossim/base/ossimEndian.h>
+#include <iomanip>
+#include <iostream>
+#include <istream>
+#include <ostream>
+
+ossimLasPointRecord3::ossimLasPointRecord3Data::ossimLasPointRecord3Data()
+   :
+   m_x(0),
+   m_y(0),
+   m_z(0),
+   m_intensity(0),
+   m_bitFlags(0),
+   m_classification(0),
+   m_scanAngleRank(0),
+   m_userData(0),
+   m_pointSourceId(0),
+   m_gpsTime(0.0),
+   m_red(0),
+   m_green(0),
+   m_blue(0)
+{
+}
+
+ossimLasPointRecord3::ossimLasPointRecord3Data::ossimLasPointRecord3Data(
+   const ossimLasPointRecord3::ossimLasPointRecord3Data& obj)
+   :
+   m_x(obj.m_x),
+   m_y(obj.m_y),
+   m_z(obj.m_z),
+   m_intensity(obj.m_intensity),
+   m_bitFlags(obj.m_bitFlags),
+   m_classification(obj.m_classification),
+   m_scanAngleRank(obj.m_scanAngleRank),
+   m_userData(obj.m_userData),
+   m_pointSourceId(obj.m_pointSourceId),
+   m_gpsTime(obj.m_gpsTime),
+   m_red(obj.m_red),
+   m_green(obj.m_green),
+   m_blue(obj.m_blue)   
+{
+}
+
+const ossimLasPointRecord3::ossimLasPointRecord3Data&
+ossimLasPointRecord3::ossimLasPointRecord3Data::operator=(
+   const ossimLasPointRecord3::ossimLasPointRecord3Data& obj)
+{
+   if ( this != &obj )
+   {
+      m_x              = obj.m_x;
+      m_y              = obj.m_y;
+      m_z              = obj.m_z;
+      m_intensity      = obj.m_intensity;
+      m_bitFlags       = obj.m_bitFlags;
+      m_classification = obj.m_classification;
+      m_scanAngleRank  = obj.m_scanAngleRank;
+      m_userData       = obj.m_userData;
+      m_pointSourceId  = obj.m_pointSourceId;
+      m_gpsTime        = obj.m_gpsTime;
+      m_red            = obj.m_red;
+      m_green          = obj.m_green;
+      m_blue           = obj.m_blue;
+   }
+   return *this;
+}
+
+ossimLasPointRecord3::ossimLasPointRecord3()
+   :
+   m_record()
+{
+}
+
+ossimLasPointRecord3::ossimLasPointRecord3(const ossimLasPointRecord3& obj)
+   :
+   m_record(obj.m_record)
+{
+}
+
+const ossimLasPointRecord3& ossimLasPointRecord3::operator=(const ossimLasPointRecord3& copy_this)
+{
+   if (this != &copy_this)
+   {
+      m_record = copy_this.m_record;
+   }
+   return *this;
+}
+
+ossimLasPointRecord3::~ossimLasPointRecord3()
+{
+}
+
+void ossimLasPointRecord3::readStream(std::istream& in)
+{
+   in.read((char*)&m_record, sizeof(ossimLasPointRecord3Data));
+
+   if ( ossim::byteOrder() == OSSIM_BIG_ENDIAN )
+   {
+      swap();
+   }
+}
+
+void ossimLasPointRecord3::writeStream(std::ostream& out)
+{
+   if ( ossim::byteOrder() == OSSIM_BIG_ENDIAN )
+   {
+      // Write little endian per spec:
+      swap();
+   }
+
+   out.write((char*)&m_record, sizeof(ossimLasPointRecord3Data));
+
+   if ( ossim::byteOrder() == OSSIM_BIG_ENDIAN )
+   {
+      // Swap back to native byte order if needed:
+      swap();
+   }
+}
+
+ossim_int32 ossimLasPointRecord3::getX() const
+{
+   return m_record.m_x;
+}
+
+ossim_int32 ossimLasPointRecord3::getY() const
+{
+   return m_record.m_y;
+}
+
+ossim_int32 ossimLasPointRecord3::getZ() const
+{
+   return m_record.m_z;
+}
+
+ossim_uint8 ossimLasPointRecord3::getReturnNumber() const
+{
+   return (m_record.m_bitFlags.m_returnNumber);
+}
+
+ossim_uint8 ossimLasPointRecord3::getNumberOfReturns() const
+{
+   return (m_record.m_bitFlags.m_numberOfReturns);
+}
+
+ossim_uint8 ossimLasPointRecord3::getEdgeFlag() const
+{
+   return (m_record.m_bitFlags.m_edgeOfFlightLine);
+}
+
+std::ostream& ossimLasPointRecord3::print(std::ostream& out) const
+{
+   // Capture the original flags.
+   std::ios_base::fmtflags f = out.flags();
+
+   out << std::setiosflags(std::ios_base::fixed) << std::setprecision(8);
+ 
+   out << "x:                 " << m_record.m_x
+       << "\ny:                 " << m_record.m_y
+       << "\nz:                 " << m_record.m_z
+       << "\nintensity:         " << m_record.m_intensity
+       << "\nreturn:            " << int(getReturnNumber())
+       << "\nnumber_of_returns: " << int(getNumberOfReturns())
+       << "\nedge:              " << (getEdgeFlag()?"true":"false")
+       << "\nscan_direction:    " << int(m_record.m_bitFlags.m_scanDirection)
+       << "\nclassification:    " << m_record.m_classification
+       << "\nscan_angle_rank:   " << int(m_record.m_scanAngleRank)
+       << "\nuser_data:         " << m_record.m_userData
+       << "\npoint_source_id:   " << m_record.m_pointSourceId
+       << "\ngrs_time:          " << m_record.m_gpsTime
+       << "\nred:               " << m_record.m_red
+       << "\ngreen:             " << m_record.m_green
+       << "\nblue:              " << m_record.m_blue
+       << std::endl;
+
+   // Reset flags.
+   out.setf(f);
+   return out;
+}
+
+void ossimLasPointRecord3::swap()
+{
+   ossimEndian endian;
+   endian.swap(m_record.m_x);
+   endian.swap(m_record.m_y);
+   endian.swap(m_record.m_z);
+   endian.swap(m_record.m_intensity);
+   endian.swap(m_record.m_pointSourceId);
+   endian.swap(m_record.m_gpsTime);
+   endian.swap(m_record.m_red);
+   endian.swap(m_record.m_green);
+   endian.swap(m_record.m_blue);   
+}
+
diff --git a/ossim_plugins/las/ossimLasPointRecord3.h b/ossim_plugins/las/ossimLasPointRecord3.h
new file mode 100644
index 0000000..16331b9
--- /dev/null
+++ b/ossim_plugins/las/ossimLasPointRecord3.h
@@ -0,0 +1,109 @@
+//----------------------------------------------------------------------------
+//
+// File: ossimLasPointRecord3.h
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author:  Garrett Potts
+//
+// Description: Container class for LAS point record type 3.
+//
+//----------------------------------------------------------------------------
+// $Id$
+#ifndef ossimLasPointRecord3_HEADER
+#define ossimLasPointRecord3_HEADER 1
+
+#include "ossimLasPointRecordInterface.h"
+
+class ossimLasPointRecord3 : public ossimLasPointRecordInterface
+{
+public:
+
+   /** @brief default constructor */
+   ossimLasPointRecord3();
+
+   /* @brief copy constructor */
+   ossimLasPointRecord3(const ossimLasPointRecord3& obj);
+
+   /* @brief assignment operator= */
+   const ossimLasPointRecord3& operator=(const ossimLasPointRecord3& copy_this);
+
+   /** @brief destructor */
+   virtual ~ossimLasPointRecord3();
+
+   /** @brief Initialize record from stream. */
+   virtual void readStream(std::istream& in);
+
+   /** @brief Writes record to stream. */
+   virtual void writeStream(std::ostream& out);
+
+   /** @return x */
+   virtual ossim_int32 getX() const;
+
+   /** @return y */
+   virtual ossim_int32 getY() const;
+   
+   /** @return z */
+   virtual ossim_int32 getZ() const;
+
+   /** @return return number */
+   virtual ossim_uint8 getReturnNumber() const;
+
+   virtual ossim_uint8 getNumberOfReturns() const;
+   
+   virtual ossim_uint8 getEdgeFlag() const;
+      
+   virtual std::ostream& print(std::ostream& out) const;
+
+private:
+
+   /** @brief Performs a swap if system byte order is not little endian. */
+   void swap();
+
+   union BitFlags
+   {
+      BitFlags(const BitFlags& obj):m_bits(obj.m_bits){}
+      BitFlags(ossim_uint8 value):m_bits((ossim_uint8)value){}
+      const BitFlags& operator =(const BitFlags& obj){m_bits = obj.m_bits;return *this;}
+      struct
+      {
+         ossim_uint8 m_returnNumber     : 3;
+         ossim_uint8 m_numberOfReturns  : 3;
+         ossim_uint8 m_scanDirection    : 1;
+         ossim_uint8 m_edgeOfFlightLine : 1;
+      };
+      ossim_uint8 m_bits;
+   };
+
+   //---
+   // Private structure so we can do a single read/write in the readStream
+   // and writeStream methods.  This sped the code up 5X when doing an ossim-icp
+   // from a LAS file to a tif.
+   //---
+   struct ossimLasPointRecord3Data
+   {
+      ossimLasPointRecord3Data();
+      ossimLasPointRecord3Data(const ossimLasPointRecord3Data& obj);
+      const ossimLasPointRecord3Data& operator=(const ossimLasPointRecord3Data& obj);
+      ossim_int32   m_x;
+      ossim_int32   m_y;
+      ossim_int32   m_z;
+      ossim_uint16  m_intensity;
+      BitFlags      m_bitFlags;
+      ossim_uint8   m_classification;
+      ossim_int8    m_scanAngleRank;
+      ossim_uint8   m_userData;
+      ossim_uint16  m_pointSourceId;
+      ossim_float64 m_gpsTime;
+      ossim_uint16  m_red;
+      ossim_uint16  m_green;
+      ossim_uint16  m_blue;
+   };
+   
+   ossimLasPointRecord3Data m_record;
+};
+
+#endif /* #ifndef ossimLasPointRecord3_HEADER */
+
diff --git a/ossim_plugins/las/ossimLasPointRecord4.cpp b/ossim_plugins/las/ossimLasPointRecord4.cpp
new file mode 100644
index 0000000..fc4255a
--- /dev/null
+++ b/ossim_plugins/las/ossimLasPointRecord4.cpp
@@ -0,0 +1,228 @@
+//----------------------------------------------------------------------------
+//
+// File: ossimLasPointRecord4.cpp
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author:  David burken
+//
+// Description: Container class LAS point record type 4.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include "ossimLasPointRecord4.h"
+#include <ossim/base/ossimCommon.h>
+#include <ossim/base/ossimEndian.h>
+#include <iomanip>
+#include <iostream>
+#include <istream>
+#include <ostream>
+
+ossimLasPointRecord4::ossimLasPointRecord4Data::ossimLasPointRecord4Data()
+   :
+   m_x(0),
+   m_y(0),
+   m_z(0),
+   m_intensity(0),
+   m_bitFlags(0),
+   m_classification(0),
+   m_scanAngleRank(0),
+   m_userData(0),
+   m_pointSourceId(0),
+   m_gpsTime(0.0),
+   m_wavePacketDescriptorIndex(0),
+   m_byteOffsetToWaveformData(0),
+   m_waveformPacketSizeInBytes(0),
+   m_returnPointWaveformLocation(0.0),
+   m_red(0),
+   m_green(0),
+   m_blue(0)
+{
+}
+
+ossimLasPointRecord4::ossimLasPointRecord4Data::ossimLasPointRecord4Data(
+   const ossimLasPointRecord4::ossimLasPointRecord4Data& obj)
+   :
+   m_x(obj.m_x),
+   m_y(obj.m_y),
+   m_z(obj.m_z),
+   m_intensity(obj.m_intensity),
+   m_bitFlags(obj.m_bitFlags),
+   m_classification(obj.m_classification),
+   m_scanAngleRank(obj.m_scanAngleRank),
+   m_userData(obj.m_userData),
+   m_pointSourceId(obj.m_pointSourceId),
+   m_gpsTime(obj.m_gpsTime),
+   m_wavePacketDescriptorIndex(obj.m_wavePacketDescriptorIndex),
+   m_byteOffsetToWaveformData(obj.m_byteOffsetToWaveformData),
+   m_waveformPacketSizeInBytes(obj.m_waveformPacketSizeInBytes),
+   m_returnPointWaveformLocation(obj.m_returnPointWaveformLocation),
+   m_red(obj.m_red),
+   m_green(obj.m_green),
+   m_blue(obj.m_blue)   
+{
+}
+
+const ossimLasPointRecord4::ossimLasPointRecord4Data&
+ossimLasPointRecord4::ossimLasPointRecord4Data::operator=(
+   const ossimLasPointRecord4::ossimLasPointRecord4Data& obj)
+{
+   if ( this != &obj )
+   {
+      m_x              = obj.m_x;
+      m_y              = obj.m_y;
+      m_z              = obj.m_z;
+      m_intensity      = obj.m_intensity;
+      m_bitFlags       = obj.m_bitFlags;
+      m_classification = obj.m_classification;
+      m_scanAngleRank  = obj.m_scanAngleRank;
+      m_userData       = obj.m_userData;
+      m_pointSourceId  = obj.m_pointSourceId;
+      m_gpsTime        = obj.m_gpsTime;
+      m_wavePacketDescriptorIndex   = obj.m_wavePacketDescriptorIndex;
+      m_byteOffsetToWaveformData    = obj.m_byteOffsetToWaveformData;
+      m_waveformPacketSizeInBytes   = obj.m_waveformPacketSizeInBytes;
+      m_returnPointWaveformLocation = obj.m_returnPointWaveformLocation;
+      m_red            = obj.m_red;
+      m_green          = obj.m_green;
+      m_blue           = obj.m_blue;
+   }
+   return *this;
+}
+
+ossimLasPointRecord4::ossimLasPointRecord4()
+   :
+   m_record()
+{
+}
+
+ossimLasPointRecord4::ossimLasPointRecord4(const ossimLasPointRecord4& obj)
+   :
+   m_record(obj.m_record)
+{
+}
+
+const ossimLasPointRecord4& ossimLasPointRecord4::operator=(const ossimLasPointRecord4& copy_this)
+{
+   if (this != &copy_this)
+   {
+      m_record = copy_this.m_record;
+   }
+   return *this;
+}
+
+ossimLasPointRecord4::~ossimLasPointRecord4()
+{
+}
+
+void ossimLasPointRecord4::readStream(std::istream& in)
+{
+   in.read((char*)&m_record, sizeof(ossimLasPointRecord4Data));
+
+   if ( ossim::byteOrder() == OSSIM_BIG_ENDIAN )
+   {
+      swap();
+   }
+}
+
+void ossimLasPointRecord4::writeStream(std::ostream& out)
+{
+   if ( ossim::byteOrder() == OSSIM_BIG_ENDIAN )
+   {
+      // Write little endian per spec:
+      swap();
+   }
+
+   out.write((char*)&m_record, sizeof(ossimLasPointRecord4Data));
+
+   if ( ossim::byteOrder() == OSSIM_BIG_ENDIAN )
+   {
+      // Swap back to native byte order if needed:
+      swap();
+   }
+}
+
+ossim_int32 ossimLasPointRecord4::getX() const
+{
+   return m_record.m_x;
+}
+
+ossim_int32 ossimLasPointRecord4::getY() const
+{
+   return m_record.m_y;
+}
+
+ossim_int32 ossimLasPointRecord4::getZ() const
+{
+   return m_record.m_z;
+}
+
+ossim_uint8 ossimLasPointRecord4::getReturnNumber() const
+{
+   return (m_record.m_bitFlags.m_returnNumber);
+}
+
+ossim_uint8 ossimLasPointRecord4::getNumberOfReturns() const
+{
+   return (m_record.m_bitFlags.m_numberOfReturns);
+}
+
+ossim_uint8 ossimLasPointRecord4::getEdgeFlag() const
+{
+   return (m_record.m_bitFlags.m_edgeOfFlightLine);
+}
+
+std::ostream& ossimLasPointRecord4::print(std::ostream& out) const
+{
+   // Capture the original flags.
+   std::ios_base::fmtflags f = out.flags();
+
+   out << std::setiosflags(std::ios_base::fixed) << std::setprecision(8);
+ 
+   out << "x:                             " << m_record.m_x
+       << "\ny:                             " << m_record.m_y
+       << "\nz:                             " << m_record.m_z
+       << "\nintensity:                     " << m_record.m_intensity
+       << "\nreturn:                        " << int(getReturnNumber())
+       << "\nnumber_of_returns:             " << int(getNumberOfReturns())
+       << "\nedge:                          " << (getEdgeFlag()?"true":"false")
+       << "\nscan_direction:                " << int(m_record.m_bitFlags.m_scanDirection)
+       << "\nclassification:                " << m_record.m_classification
+       << "\nscan_angle_rank:               " << int(m_record.m_scanAngleRank)
+       << "\nuser_data:                     " << m_record.m_userData
+       << "\npoint_source_id:               " << m_record.m_pointSourceId
+       << "\ngrs_time:                      " << m_record.m_gpsTime
+       << "\nwave_packet_descriptor_index:  " << m_record.m_wavePacketDescriptorIndex
+       << "\nbyte_offset_to_waveform_data:  " << m_record.m_byteOffsetToWaveformData
+       << "\nwaveform_packet_size_in_bytes: " << m_record.m_waveformPacketSizeInBytes
+       << "\nm_returnPointWaveformLocation: " << m_record.m_returnPointWaveformLocation
+       << "\nred:                           " << m_record.m_red
+       << "\ngreen:                         " << m_record.m_green
+       << "\nblue:                          " << m_record.m_blue
+       << std::endl;
+
+   // Reset flags.
+   out.setf(f);
+   return out;
+}
+
+void ossimLasPointRecord4::swap()
+{
+   ossimEndian endian;
+   endian.swap(m_record.m_x);
+   endian.swap(m_record.m_y);
+   endian.swap(m_record.m_z);
+   endian.swap(m_record.m_intensity);
+   endian.swap(m_record.m_pointSourceId);
+   endian.swap(m_record.m_gpsTime);
+   endian.swap(m_record.m_byteOffsetToWaveformData);
+   endian.swap(m_record.m_waveformPacketSizeInBytes);
+   endian.swap(m_record.m_returnPointWaveformLocation);
+   endian.swap(m_record.m_red);
+   endian.swap(m_record.m_green);
+   endian.swap(m_record.m_blue);   
+}
+
diff --git a/ossim_plugins/las/ossimLasPointRecord4.h b/ossim_plugins/las/ossimLasPointRecord4.h
new file mode 100644
index 0000000..ed60987
--- /dev/null
+++ b/ossim_plugins/las/ossimLasPointRecord4.h
@@ -0,0 +1,113 @@
+//----------------------------------------------------------------------------
+//
+// File: ossimLasPointRecord4.h
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author: David Burken
+//
+// Description: Container class for LAS point record type 4.
+//
+//----------------------------------------------------------------------------
+// $Id$
+#ifndef ossimLasPointRecord4_HEADER
+#define ossimLasPointRecord4_HEADER 1
+
+#include "ossimLasPointRecordInterface.h"
+
+class ossimLasPointRecord4 : public ossimLasPointRecordInterface
+{
+public:
+
+   /** @brief default constructor */
+   ossimLasPointRecord4();
+
+   /* @brief copy constructor */
+   ossimLasPointRecord4(const ossimLasPointRecord4& obj);
+
+   /* @brief assignment operator= */
+   const ossimLasPointRecord4& operator=(const ossimLasPointRecord4& copy_this);
+
+   /** @brief destructor */
+   virtual ~ossimLasPointRecord4();
+
+   /** @brief Initialize record from stream. */
+   virtual void readStream(std::istream& in);
+
+   /** @brief Writes record to stream. */
+   virtual void writeStream(std::ostream& out);
+
+   /** @return x */
+   virtual ossim_int32 getX() const;
+
+   /** @return y */
+   virtual ossim_int32 getY() const;
+   
+   /** @return z */
+   virtual ossim_int32 getZ() const;
+
+   /** @return return number */
+   virtual ossim_uint8 getReturnNumber() const;
+
+   virtual ossim_uint8 getNumberOfReturns() const;
+   
+   virtual ossim_uint8 getEdgeFlag() const;
+      
+   virtual std::ostream& print(std::ostream& out) const;
+
+private:
+
+   /** @brief Performs a swap if system byte order is not little endian. */
+   void swap();
+
+   union BitFlags
+   {
+      BitFlags(const BitFlags& obj):m_bits(obj.m_bits){}
+      BitFlags(ossim_uint8 value):m_bits((ossim_uint8)value){}
+      const BitFlags& operator =(const BitFlags& obj){m_bits = obj.m_bits;return *this;}
+      struct
+      {
+         ossim_uint8 m_returnNumber     : 3;
+         ossim_uint8 m_numberOfReturns  : 3;
+         ossim_uint8 m_scanDirection    : 1;
+         ossim_uint8 m_edgeOfFlightLine : 1;
+      };
+      ossim_uint8 m_bits;
+   };
+
+   //---
+   // Private structure so we can do a single read/write in the readStream
+   // and writeStream methods.  This sped the code up 5X when doing an ossim-icp
+   // from a LAS file to a tif.
+   //---
+   struct ossimLasPointRecord4Data
+   {
+      ossimLasPointRecord4Data();
+      ossimLasPointRecord4Data(const ossimLasPointRecord4Data& obj);
+      const ossimLasPointRecord4Data& operator=(const ossimLasPointRecord4Data& obj);
+      ossim_int32   m_x;
+      ossim_int32   m_y;
+      ossim_int32   m_z;
+      ossim_uint16  m_intensity;
+      BitFlags      m_bitFlags;
+      ossim_uint8   m_classification;
+      ossim_int8    m_scanAngleRank;
+      ossim_uint8   m_userData;
+      ossim_uint16  m_pointSourceId;
+      ossim_float64 m_gpsTime;
+      ossim_uint8   m_wavePacketDescriptorIndex;
+      ossim_uint64  m_byteOffsetToWaveformData;
+      ossim_uint32  m_waveformPacketSizeInBytes;
+      ossim_float64 m_returnPointWaveformLocation;
+      ossim_uint16  m_red;
+      ossim_uint16  m_green;
+      ossim_uint16  m_blue;
+   };
+   
+   ossimLasPointRecord4Data m_record;
+};
+
+#endif /* #ifndef ossimLasPointRecord4_HEADER */
+
diff --git a/ossim_plugins/las/ossimLasPointRecordInterface.h b/ossim_plugins/las/ossimLasPointRecordInterface.h
new file mode 100644
index 0000000..30b3e50
--- /dev/null
+++ b/ossim_plugins/las/ossimLasPointRecordInterface.h
@@ -0,0 +1,42 @@
+//----------------------------------------------------------------------------
+//
+// File: ossimLasPointRecordInterface.h
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author:  David Burken
+//
+// Description: OSSIM Interface for LAS point record types.
+//
+//----------------------------------------------------------------------------
+// $Id: ossimLasPointRecordInterface.h 2645 2011-05-26 15:21:34Z oscar.kramer $
+#ifndef ossimLasPointRecordInterface_HEADER
+#define ossimLasPointRecordInterface_HEADER 1
+
+#include <ossim/base/ossimConstants.h>
+#include <iosfwd>
+
+class ossimLasPointRecordInterface
+{
+public:
+
+   /** @brief Virtual destructor defined to squash compiler errors. */
+   virtual ~ossimLasPointRecordInterface(){}
+   
+   virtual void readStream(std::istream& in) = 0;
+   virtual void writeStream(std::ostream& out) = 0;
+
+   virtual ossim_int32  getX() const = 0;
+   virtual ossim_int32  getY() const = 0;
+   virtual ossim_int32  getZ() const = 0;
+   virtual ossim_uint8  getReturnNumber() const = 0;
+   virtual ossim_uint8  getNumberOfReturns() const = 0;
+   virtual ossim_uint8  getEdgeFlag() const = 0;
+   
+   virtual std::ostream& print(std::ostream& out) const = 0;
+};
+
+#endif /* #ifndef ossimLasPointRecordInterface_HEADER */
+
diff --git a/ossim_plugins/las/ossimLasReader.cpp b/ossim_plugins/las/ossimLasReader.cpp
new file mode 100644
index 0000000..b4b2ebe
--- /dev/null
+++ b/ossim_plugins/las/ossimLasReader.cpp
@@ -0,0 +1,1141 @@
+//----------------------------------------------------------------------------
+//
+// File: ossimLasReader.cpp
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author:  David Burken
+//
+// Description: OSSIM LAS LIDAR reader.
+//
+//----------------------------------------------------------------------------
+// $Id: ossimLasReader.cpp 2682 2011-06-06 17:55:17Z david.burken $
+
+#include "ossimLasReader.h"
+#include "ossimLasPointRecordInterface.h"
+#include "ossimLasPointRecord1.h"
+#include "ossimLasPointRecord2.h"
+#include "ossimLasPointRecord3.h"
+#include "ossimLasPointRecord4.h"
+
+#include <ossim/base/ossimBooleanProperty.h>
+#include <ossim/base/ossimCommon.h>
+#include <ossim/base/ossimIpt.h>
+#include <ossim/base/ossimGpt.h>
+#include <ossim/base/ossimEndian.h>
+#include <ossim/base/ossimKeywordlist.h>
+#include <ossim/base/ossimProperty.h>
+#include <ossim/base/ossimString.h>
+#include <ossim/base/ossimStringProperty.h>
+#include <ossim/base/ossimTrace.h>
+#include <ossim/imaging/ossimImageGeometryRegistry.h>
+#include <ossim/projection/ossimMapProjection.h>
+#include <ossim/projection/ossimProjection.h>
+#include <ossim/projection/ossimProjectionFactoryRegistry.h>
+#include <ossim/support_data/ossimFgdcTxtDoc.h>
+#include <ossim/support_data/ossimLasHdr.h>
+#include <ossim/support_data/ossimTiffInfo.h>
+
+#include <fstream>
+#include <limits>
+#include <sstream>
+
+RTTI_DEF1(ossimLasReader, "ossimLasReader", ossimImageHandler)
+
+static ossimTrace traceDebug("ossimLasReader:debug");
+
+static const char SCALE_KW[] = "scale";
+static const char SCAN_KW[]  = "scan"; // boolean
+
+ossimLasReader::ossimLasReader()
+   : ossimImageHandler(),
+     m_str(),
+     m_hdr(0),
+     m_proj(0),
+     m_ul(),
+     m_lr(),
+     m_maxZ(0.0),
+     m_minZ(0.0),
+     m_scale(),
+     m_tile(0),
+     m_entry(0),
+     m_mutex(),
+     m_scan(false), // ???
+     m_units(OSSIM_METERS),
+     m_unitConverter(0)   
+{
+   //---
+   // Nan out as can be set in several places, i.e. setProperty,
+   // loadState and initProjection.
+   //---
+   m_scale.makeNan();
+}
+
+ossimLasReader::~ossimLasReader()
+{
+   close();
+}
+
+bool ossimLasReader::open()
+{
+   static const char M[] = "ossimLasReader::open";
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << M << " entered...\nfile: " << theImageFile << "\n";
+   }
+   
+   bool result = false;
+
+   close();
+
+   m_str.open(theImageFile.c_str(), std::ios_base::in | std::ios_base::binary);
+   if ( m_str.good() )
+   {
+      m_hdr = new ossimLasHdr();
+      if ( m_hdr->checkSignature( m_str ) )
+      {
+         m_str.seekg(0, std::ios_base::beg);
+         m_hdr->readStream(m_str);
+         ossim_uint32 dataFormatId = m_hdr->getPointDataFormatId();
+
+         if ( (dataFormatId == 1) || (dataFormatId == 2) ||
+              (dataFormatId == 3) || (dataFormatId == 4) )
+         {
+            result = init();
+            
+            if ( result )
+            {
+               establishDecimationFactors();
+               
+               if ( traceDebug() )
+               {
+                  ossimNotify(ossimNotifyLevel_DEBUG) << *m_hdr << "\n";
+               }
+            }
+         }
+         else
+         {
+            if ( traceDebug() )
+            {
+               ossimNotify(ossimNotifyLevel_DEBUG)
+                  << "Unhandled point type: " << int(m_hdr->getPointDataFormatId()) << "\n";
+            }
+         }
+      
+         if ( traceDebug() && result )
+         {
+            ossimNotify(ossimNotifyLevel_DEBUG) << *m_hdr << "\n";
+         }
+         
+      } // if ( m_hdr->checkSignature( m_str ) )
+      
+   } // if ( m_str.good() )
+
+   if ( !result ) close();
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG) << M << " exit status = " << (result?"true\n":"false\n");
+   }
+   
+   return result;
+}
+
+void ossimLasReader::completeOpen()
+{
+   establishDecimationFactors();
+}
+
+void ossimLasReader::close()
+{
+   if ( isOpen() )
+   {
+      m_str.close();
+      delete m_hdr;
+      m_hdr = 0;
+      m_entry = 0;
+      m_tile  = 0;
+      m_proj  = 0;
+      ossimImageHandler::close();
+   }
+}
+
+ossimRefPtr<ossimImageData> ossimLasReader::getTile(
+   const  ossimIrect& tile_rect, ossim_uint32 resLevel)
+{
+   if ( m_tile.valid() )
+   {
+      // Image rectangle must be set prior to calling getTile.
+      m_tile->setImageRectangle(tile_rect);
+
+      if ( getTile( m_tile.get(), resLevel ) == false )
+      {
+         if (m_tile->getDataObjectStatus() != OSSIM_NULL)
+         {
+            m_tile->makeBlank();
+         }
+      }
+   }
+
+   return m_tile;
+}
+
+bool ossimLasReader::getTile(ossimImageData* result, ossim_uint32 resLevel)
+{
+   // static const char MODULE[] = "ossimLibLasReader::getTile(ossimImageData*, level)";
+
+   bool status = false;
+
+
+   if ( m_hdr && result && (result->getScalarType() == OSSIM_FLOAT32) &&
+        (result->getDataObjectStatus() != OSSIM_NULL) &&
+        !m_ul.hasNans() && !m_scale.hasNans() )
+   {
+      status = true;
+      
+      const ossimIrect  TILE_RECT   = result->getImageRectangle();
+      const ossim_int32 TILE_HEIGHT = static_cast<ossim_int32>(TILE_RECT.height());
+      const ossim_int32 TILE_WIDTH  = static_cast<ossim_int32>(TILE_RECT.width());
+      const ossim_int32 TILE_SIZE   = static_cast<ossim_int32>(TILE_RECT.area());
+
+      const ossim_uint16 ENTRY = m_entry+1;
+
+      // Get the scale for this resLevel:
+      ossimDpt scale;
+      getScale(scale, resLevel);
+      
+      // Set the starting upper left of upper left pixel for this tile.
+      const ossimDpt UL_PROG_PT( m_ul.x - scale.x / 2.0 + TILE_RECT.ul().x * scale.x,
+                                 m_ul.y + scale.y / 2.0 - TILE_RECT.ul().y * scale.y);
+
+      //---
+      // Set the lower right to the edge of the tile boundary.  This looks like an
+      // "off by one" error but it's not.  We want the ossimDrect::pointWithin to
+      // catch any points in the last line sample.
+      //---
+      const ossimDpt LR_PROG_PT( UL_PROG_PT.x + TILE_WIDTH  * scale.x,
+                                 UL_PROG_PT.y - TILE_HEIGHT * scale.y);
+      
+      const ossimDrect PROJ_RECT(UL_PROG_PT, LR_PROG_PT, OSSIM_RIGHT_HANDED);
+
+#if 0  /* Please leave for debug. (drb) */
+      cout << "m_ul: " << m_ul
+           << "\nm_scale: " << m_scale
+           << "\nscale:   " << scale
+           << "\nresult->getScalarType(): " << result->getScalarType()
+           << "\nresult->getDataObjectStatus(): " << result->getDataObjectStatus()
+           << "\nPROJ_RECT: " << PROJ_RECT
+           << "\nTILE_RECT: " << TILE_RECT
+           << "\nUL_PROG_PT: " << UL_PROG_PT << endl;
+#endif
+
+      const ossim_float64 SCALE_X  = m_hdr->getScaleFactorX();
+      const ossim_float64 SCALE_Y  = m_hdr->getScaleFactorY();
+      const ossim_float64 SCALE_Z  = m_hdr->getScaleFactorZ();
+      const ossim_float64 OFFSET_X = m_hdr->getOffsetX();
+      const ossim_float64 OFFSET_Y = m_hdr->getOffsetY();
+      const ossim_float64 OFFSET_Z = m_hdr->getOffsetZ();
+
+      // Create array of buckets.
+      std::vector<ossimLasReader::Bucket> bucket( TILE_SIZE );
+
+      // Loop through the point data.
+      ossimLasPointRecordInterface* lasPtRec = getNewPointRecord();
+      ossimDpt lasPt;
+
+      m_str.clear();
+      m_str.seekg(m_hdr->getOffsetToPointData());
+
+      while ( m_str.good() )
+      {
+         // m_str.read((char*)lasPtRec, 28);
+         lasPtRec->readStream( m_str );
+
+         if ( lasPtRec->getReturnNumber() == ENTRY )
+         {
+            lasPt.x = lasPtRec->getX() * SCALE_X + OFFSET_X;
+            lasPt.y = lasPtRec->getY() * SCALE_Y + OFFSET_Y;
+            if ( m_unitConverter )
+            {
+               convertToMeters(lasPt.x);
+               convertToMeters(lasPt.y);
+            }
+            if ( PROJ_RECT.pointWithin( lasPt ) )
+            {
+               // Compute the bucket index:
+               ossim_int32 line = static_cast<ossim_int32>((UL_PROG_PT.y - lasPt.y) / scale.y);
+               ossim_int32 samp = static_cast<ossim_int32>((lasPt.x - UL_PROG_PT.x) / scale.x );
+               ossim_int32 bucketIndex = line * TILE_WIDTH + samp;
+               
+               // Range check and add if in there.
+               if ( ( bucketIndex >= 0 ) && ( bucketIndex < TILE_SIZE ) )
+               {
+                  ossim_float64 z = lasPtRec->getZ() * SCALE_Z + OFFSET_Z;
+                  if (  m_unitConverter ) convertToMeters(z);
+                  bucket[bucketIndex].add( z ); 
+               }
+            }
+         }
+         if ( m_str.eof() ) break;
+      }
+      delete lasPtRec;
+      lasPtRec = 0;
+
+      //---
+      // We must always blank out the tile as we may not have a point for every
+      // point.
+      //---
+      result->makeBlank();
+
+      ossim_float32* buf = result->getFloatBuf(); // Tile buffer to fill.
+      
+      // Fill the tile.  Currently no band loop:
+      for (ossim_int32 i = 0; i < TILE_SIZE; ++i)
+      {
+         buf[i] = bucket[i].getValue();
+      }
+
+      // Revalidate.
+      result->validate();
+   }
+
+   return status;
+   
+} // End: bool ossimLibLasReader::getTile(ossimImageData* result, ossim_uint32 resLevel)
+
+ossim_uint32 ossimLasReader::getNumberOfInputBands() const
+{
+   return 1; // tmp
+}
+
+ossim_uint32 ossimLasReader::getNumberOfLines(ossim_uint32 resLevel) const
+{
+   ossim_uint32 result = 0;
+   if ( isOpen() )
+   {
+      result = static_cast<ossim_uint32>(ceil(m_ul.y - m_lr.y) / m_scale.y);
+      if (resLevel) result = (result>>resLevel);
+   }
+   return result;
+}
+
+ossim_uint32 ossimLasReader::getNumberOfSamples(ossim_uint32 resLevel) const
+{
+   ossim_uint32 result = 0;
+   if ( isOpen() )
+   {
+      result = static_cast<ossim_uint32>(ceil(m_lr.x - m_ul.x) / m_scale.x);
+      if (resLevel) result = (result>>resLevel);
+   }
+   return result;
+}
+
+ossim_uint32 ossimLasReader::getImageTileWidth() const
+{
+   return 0;
+}
+
+ossim_uint32 ossimLasReader::getImageTileHeight() const
+{
+   return 0;
+}
+
+ossim_uint32 ossimLasReader::getTileWidth() const
+{
+   ossimIpt ipt;
+   ossim::defaultTileSize(ipt);
+   return ipt.x;
+}
+
+ossim_uint32 ossimLasReader::getTileHeight() const
+{
+   ossimIpt ipt;
+   ossim::defaultTileSize(ipt);
+   return ipt.y; 
+}
+
+ossimScalarType ossimLasReader::getOutputScalarType() const
+{
+   return OSSIM_FLOAT32;
+}
+
+void ossimLasReader::getEntryList(std::vector<ossim_uint32>& entryList)const
+{
+   if ( isOpen() )
+   {
+      for ( ossim_uint32 entry = 0; entry < 15; ++entry )
+      {
+         if ( m_hdr->getNumberOfPoints(entry) ) entryList.push_back(entry);
+      }
+   }
+   else
+   {
+      entryList.clear();
+   }
+}
+
+ossim_uint32 ossimLasReader::getCurrentEntry() const
+{
+   return static_cast<ossim_uint32>(m_entry);
+}
+
+bool ossimLasReader::setCurrentEntry(ossim_uint32 entryIdx)
+{
+   bool result = false;
+   if ( isOpen() )
+   {
+      std::vector<ossim_uint32> entryList;
+      getEntryList( entryList );
+      std::vector<ossim_uint32>::const_iterator i = entryList.begin();
+      while ( i != entryList.end() )
+      {
+         if ( (*i) == entryIdx )
+         {
+            m_entry = entryIdx;
+            result = true;
+         }
+         ++i;
+      }
+   }
+   return result;
+}
+
+ossimString ossimLasReader::getShortName() const
+{
+   return ossimString("las");
+}
+   
+ossimString ossimLasReader::getLongName()  const
+{
+   return ossimString("ossim las reader");
+}
+
+ossimRefPtr<ossimImageGeometry> ossimLasReader::getImageGeometry()
+{
+   if ( !theGeometry )
+   {
+      // Check for external geom:
+      theGeometry = getExternalImageGeometry();
+      
+      if ( !theGeometry )
+      {
+         theGeometry = new ossimImageGeometry();
+         if ( m_proj.valid() )
+         {
+            theGeometry->setProjection( m_proj.get() );
+         }
+         else
+         {
+            //---
+            // WARNING:
+            // Must create/set theGeometry at this point or the next call to 
+            // ossimImageGeometryRegistry::extendGeometry will put us in an infinite loop
+            // as it does a recursive call back to ossimImageHandler::getImageGeometry().
+            //---         
+
+            // Try factories for projection.
+            ossimImageGeometryRegistry::instance()->extendGeometry(this);
+         }
+      }
+      
+      // Set image things the geometry object should know about.
+      initImageParameters( theGeometry.get() );
+   }
+   
+   return theGeometry;
+}
+
+double ossimLasReader::getMinPixelValue(ossim_uint32 /* band */) const
+{
+   return m_minZ;
+}
+
+double ossimLasReader::getMaxPixelValue(ossim_uint32 /* band */) const
+{
+   return m_maxZ;
+}
+
+double ossimLasReader::getNullPixelValue(ossim_uint32 /* band */) const
+{
+   return -99999.0;
+}
+
+ossim_uint32 ossimLasReader::getNumberOfDecimationLevels() const
+{
+   // Can support any number of rlevels.
+   ossim_uint32 result = 1;
+   const ossim_uint32 STOP_DIMENSION = 16;
+   ossim_uint32 largestImageDimension = getNumberOfSamples(0) > getNumberOfLines(0) ?
+      getNumberOfSamples(0) : getNumberOfLines(0);
+   while(largestImageDimension > STOP_DIMENSION)
+   {
+      largestImageDimension /= 2;
+      ++result;
+   }
+   return result; 
+}
+
+bool ossimLasReader::saveState(ossimKeywordlist& kwl, const char* prefix)const
+{
+   kwl.add( prefix, SCALE_KW, m_scale.toString().c_str(), true );
+   kwl.add( prefix, SCAN_KW,  ossimString::toString(m_scan).c_str(), true );
+   return ossimImageHandler::saveState(kwl, prefix);
+}
+
+bool ossimLasReader::loadState(const ossimKeywordlist& kwl, const char* prefix)
+{
+   bool result = false;
+   if ( ossimImageHandler::loadState(kwl, prefix) )
+   {
+      result = open();
+      if ( result )
+      {
+         // Get our keywords:
+         const char* lookup = kwl.find(prefix, SCALE_KW);
+         if ( lookup )
+         {
+            m_scale.toPoint( ossimString(lookup) );
+         }
+         lookup = kwl.find(prefix, SCAN_KW);
+         if ( lookup )
+         {
+            ossimString s = lookup;
+            m_scan = s.toBool();
+         }
+      }
+   }
+   return result;
+}
+
+void ossimLasReader::setProperty(ossimRefPtr<ossimProperty> property)
+{
+   if ( property.valid() )
+   {
+      if ( property->getName() == SCALE_KW )
+      {
+         ossimString s;
+         property->valueToString(s);
+         ossim_float64 d = s.toFloat64();
+         if ( ossim::isnan(d) == false )
+         {
+            setScale( d );
+         }
+      }
+      else if ( property->getName() == SCAN_KW )
+      {
+         ossimString s;
+         property->valueToString(s);
+         m_scan = s.toBool();
+      }
+      else
+      {
+         ossimImageHandler::setProperty(property);
+      }
+   }
+}
+
+ossimRefPtr<ossimProperty> ossimLasReader::getProperty(const ossimString& name)const
+{
+   ossimRefPtr<ossimProperty> prop = 0;
+   if ( name == SCALE_KW )
+   {
+      ossimString value = ossimString::toString(m_scale.x);
+      prop = new ossimStringProperty(name, value);
+   }
+   else if ( name == SCAN_KW )
+   {
+      prop = new ossimBooleanProperty(name, m_scan);
+   }
+   else
+   {
+      prop = ossimImageHandler::getProperty(name);
+   }
+   return prop;
+}
+
+void ossimLasReader::getPropertyNames(std::vector<ossimString>& propertyNames)const
+{
+   propertyNames.push_back( ossimString(SCALE_KW) );
+   propertyNames.push_back( ossimString(SCAN_KW) );
+   ossimImageHandler::getPropertyNames(propertyNames);
+}
+
+bool ossimLasReader::init()
+{
+   bool result = false;
+
+   if ( isOpen() )
+   {
+      result = parseVarRecords();
+
+      if ( !result )
+      {
+         result = initFromExternalMetadata(); // Checks for external FGDC text file.
+      }
+
+      // There is nothing we can do if parseVarRecords fails.
+      if ( result )
+      {
+         initTile();
+      }
+   }
+   
+   return result;
+}
+
+bool ossimLasReader::initProjection()
+{
+   bool result = true;
+   
+   ossimMapProjection* proj = dynamic_cast<ossimMapProjection*>( m_proj.get() );
+   if ( proj )
+   {
+      //---
+      // Set the tie and scale:
+      // Note the scale can be set in other places so only set here if it
+      // has nans.
+      //---
+      if ( proj->isGeographic() )
+      {
+         ossimGpt gpt(m_ul.y, m_ul.x, 0.0, proj->getDatum() );
+         proj->setUlTiePoints( gpt );
+
+         if ( m_scale.hasNans() )
+         {
+            m_scale = proj->getDecimalDegreesPerPixel();
+            if ( m_scale.hasNans() || !m_scale.x || !m_scale.y )
+            {
+               // Set to some default:
+               m_scale.x = 0.000008983; // About 1 meter at the Equator.
+               m_scale.y = m_scale.x;
+               proj->setDecimalDegreesPerPixel( m_scale );
+            }
+            
+         }
+      }
+      else
+      {
+         proj->setUlTiePoints(m_ul);
+
+         if ( m_scale.hasNans() )
+         {
+            m_scale = proj->getMetersPerPixel();
+            if ( m_scale.hasNans() || !m_scale.x || !m_scale.y )
+            {
+               // Set to some default:
+               m_scale.x = 1.0;
+               m_scale.y = 1.0;
+               proj->setMetersPerPixel( m_scale );
+            }
+         }
+      }
+   }
+   else
+   {
+      result = false;
+      m_ul.makeNan();
+      m_lr.makeNan();
+      m_scale.makeNan();
+      
+      ossimNotify(ossimNotifyLevel_WARN)
+         << "ossimLasReader::initProjection WARN Could not cast to map projection!"
+         << std::endl;
+   }
+
+   return result;
+   
+} // bool ossimLasReader::initProjection()
+
+void ossimLasReader::initTile()
+{
+   const ossim_uint32 BANDS = getNumberOfOutputBands();
+
+   m_tile = new ossimImageData(this,
+                               getOutputScalarType(),
+                               BANDS,
+                               getTileWidth(),
+                               getTileHeight());
+
+   for(ossim_uint32 band = 0; band < BANDS; ++band)
+   {
+      m_tile->setMinPix(getMinPixelValue(band),   band);
+      m_tile->setMaxPix(getMaxPixelValue(band),   band);
+      m_tile->setNullPix(getNullPixelValue(band), band);
+   }
+
+   m_tile->initialize();
+}
+
+void ossimLasReader::initUnits(const ossimKeywordlist& geomKwl)
+{
+   ossimMapProjection* proj = dynamic_cast<ossimMapProjection*>( m_proj.get() );
+   if ( proj )
+   {
+      if ( proj->isGeographic() )
+      {
+         m_units = OSSIM_DEGREES;
+      }
+      else
+      {
+         const char* lookup = geomKwl.find("image0.linear_units");
+         if ( lookup )
+         {
+            std::string units = lookup;
+            if ( units == "meters" )
+            {
+               m_units = OSSIM_METERS;
+            }  
+            else if ( units == "feet" )
+            {
+               m_units = OSSIM_FEET;
+            }
+            else if ( units == "us_survey_feet" )
+            {
+               m_units = OSSIM_US_SURVEY_FEET;
+            }
+            else
+            {
+               ossimNotify(ossimNotifyLevel_DEBUG)
+                  << "ossimLibLasReader::initUnits WARN:\n"
+                  << "Unhandled linear units code: " << units << std::endl;
+            }
+         }
+      }
+   }
+
+   // Don't make a unit converter for decimal degrees...
+   if ( (m_units != OSSIM_DEGREES) && (m_units != OSSIM_METERS) && !m_unitConverter )
+   {
+      m_unitConverter = new ossimUnitConversionTool();
+   }
+}
+
+void ossimLasReader::initValues()
+{
+   static const char M[] = "ossimLasReader::initValues";
+
+   if ( m_scan )
+   {
+      // Set to bogus values to start.
+      m_ul.x = numeric_limits<ossim_float64>::max();
+      m_ul.y = numeric_limits<ossim_float64>::min();
+      m_lr.x = numeric_limits<ossim_float64>::min();
+      m_lr.y = numeric_limits<ossim_float64>::max();
+      m_maxZ = numeric_limits<ossim_float64>::min();
+      m_minZ = numeric_limits<ossim_float64>::max();
+      
+      const ossim_float64 SCALE_X  = m_hdr->getScaleFactorX();
+      const ossim_float64 SCALE_Y  = m_hdr->getScaleFactorY();
+      const ossim_float64 SCALE_Z  = m_hdr->getScaleFactorZ();
+      const ossim_float64 OFFSET_X = m_hdr->getOffsetX();
+      const ossim_float64 OFFSET_Y = m_hdr->getOffsetY();
+      const ossim_float64 OFFSET_Z = m_hdr->getOffsetZ();
+      
+      ossimLasPointRecordInterface* lasPtRec = getNewPointRecord();
+      
+      m_str.clear();
+      m_str.seekg(m_hdr->getOffsetToPointData());
+      
+      ossim_float64 x;
+      ossim_float64 y;
+      ossim_float64 z;
+      
+      while ( m_str.good() )
+      {
+         lasPtRec->readStream( m_str );
+         
+#if 0 /* Please leave for debug. (drb) */
+         lasPtRec->print( ossimNotify(ossimNotifyLevel_DEBUG) );
+#endif
+         
+         x = lasPtRec->getX() * SCALE_X + OFFSET_X;
+         y = lasPtRec->getY() * SCALE_Y + OFFSET_Y;
+         z = lasPtRec->getZ() * SCALE_Z + OFFSET_Z;
+         
+         if ( x < m_ul.x ) m_ul.x = x;
+         if ( x > m_lr.x ) m_lr.x = x;
+         if ( y > m_ul.y ) m_ul.y = y;
+         if ( y < m_lr.y ) m_lr.y = y;
+         if ( z > m_maxZ ) m_maxZ = z;
+         if ( z < m_minZ ) m_minZ = z;
+         
+         if ( m_str.eof() ) break;
+      }
+      delete lasPtRec;
+      lasPtRec = 0;
+   }
+   else
+   {
+      // Set the upper left (tie).
+      m_ul.x = m_hdr->getMinX();
+      m_ul.y = m_hdr->getMaxY();
+      
+      // Set the lower right.
+      m_lr.x = m_hdr->getMaxX();
+      m_lr.y = m_hdr->getMinY();
+      
+      // Set the min/max:
+      m_minZ = m_hdr->getMinZ();
+      m_maxZ = m_hdr->getMaxZ();
+   }
+
+   if ( m_unitConverter ) // Need to convert to meters.
+   {
+      convertToMeters(m_ul.x);
+      convertToMeters(m_ul.y);
+      
+      convertToMeters(m_lr.x);
+      convertToMeters(m_lr.y);
+      
+      convertToMeters(m_maxZ);
+      convertToMeters(m_minZ);
+   }
+
+   if ( traceDebug() )
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG) << M << " DEBUG:\nBounds from header:";
+      ossimDpt pt;
+      pt.x = m_hdr->getMinX();
+      pt.y = m_hdr->getMaxY();
+      if ( m_unitConverter )
+      {
+         convertToMeters(pt.x);
+         convertToMeters(pt.y);
+      }
+      ossimNotify(ossimNotifyLevel_DEBUG) << "\nul:   " << pt;
+      pt.x = m_hdr->getMaxX();
+      pt.y = m_hdr->getMinY();
+
+      if ( m_unitConverter )
+      {
+         convertToMeters(pt.x);
+         convertToMeters(pt.y); 
+      }
+      ossimNotify(ossimNotifyLevel_DEBUG) << "\nlr:   " << pt;
+      pt.x = m_hdr->getMinZ();
+      pt.y = m_hdr->getMaxZ();
+      if ( m_unitConverter )
+      {
+         convertToMeters(pt.x);
+         convertToMeters(pt.y); 
+      }
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "\nminZ: " << pt.x
+         << "\nmaxZ: " << pt.y << "\n";
+      if ( m_scan )
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG)
+            << "Bounds from scan:"
+            << "\nul:   " << m_ul
+            << "\nlr:   " << m_lr
+            << "\nminZ: " << m_minZ
+            << "\nmaxZ: " << m_maxZ << "\n";
+      }
+   }
+}
+
+bool ossimLasReader::parseVarRecords()
+{
+   static const char M[] = "ossimLasReader::parseVarRecords";
+   if (traceDebug()) ossimNotify(ossimNotifyLevel_DEBUG) << M << " entered...\n";
+   
+   bool result = false;
+
+   if ( isOpen() )
+   {
+      std::streampos origPos = m_str.tellg();
+      std::streamoff pos = static_cast<std::streamoff>(m_hdr->getHeaderSize());
+
+      m_str.clear();
+      m_str.seekg(pos, std::ios_base::beg);
+
+      ossim_uint32 vlrCount = m_hdr->getNumberOfVlrs();
+      ossim_uint16 reserved;
+      char uid[17];
+      uid[16]='\n';
+      ossim_uint16 recordId;
+      ossim_uint16 length;
+      char des[33];
+      des[32] = '\n';
+
+      //---
+      // Things we need to save for printGeoKeys:
+      //---
+      ossim_uint16*  geoKeyBlock     = 0;
+      ossim_uint64   geoKeyLength    = 0;
+      ossim_float64* geoDoubleBlock  = 0;
+      ossim_uint64   geoDoubleLength = 0;
+      ossim_int8*    geoAsciiBlock   = 0;
+      ossim_uint64   geoAsciiLength  = 0;
+     
+      ossimEndian* endian = 0;
+      // LAS LITTLE ENDIAN:
+      if ( ossim::byteOrder() == OSSIM_BIG_ENDIAN )
+      {
+         endian = new ossimEndian;
+      }
+      
+      for ( ossim_uint32 i = 0; i < vlrCount; ++i )
+      {
+         m_str.read((char*)&reserved, 2);
+         m_str.read(uid, 16);
+         m_str.read((char*)&recordId, 2);
+         m_str.read((char*)&length, 2);
+         m_str.read(des, 32);
+
+         // LAS LITTLE ENDIAN:
+         if ( endian )
+         {
+            endian->swap(recordId);
+            endian->swap(length);
+         }
+ 
+         if ( traceDebug() )
+         {
+            ossimNotify(ossimNotifyLevel_DEBUG)
+               << "uid:      " << uid
+               << "\nrecordId: " << recordId
+               << "\nlength:   " << length
+               << "\ndes:      " << des
+               << std::endl;
+         }
+         
+         if (recordId == 34735) // GeoTiff projection keys.
+         {
+            geoKeyLength = length/2;
+            if ( geoKeyBlock )
+            {
+               delete [] geoKeyBlock;
+            }
+            geoKeyBlock = new ossim_uint16[geoKeyLength];
+            m_str.read((char*)geoKeyBlock, length);
+            if ( endian )
+            {
+               endian->swap(geoKeyBlock, geoKeyLength);
+            }
+         }
+         else if (recordId == 34736) // GeoTiff double parameters.
+         {
+            geoDoubleLength = length/8;
+            if ( geoDoubleBlock )
+            {
+               delete [] geoDoubleBlock;
+            }
+            geoDoubleBlock = new ossim_float64[geoDoubleLength];
+            m_str.read((char*)geoDoubleBlock, length);
+            if ( endian )
+            {
+               endian->swap(geoDoubleBlock, geoDoubleLength);
+            }
+         }
+         else if (recordId == 34737) // GeoTiff ascii block.
+         {
+            geoAsciiLength = length;
+            if (geoAsciiBlock)
+            {
+               delete [] geoAsciiBlock;
+            }
+            geoAsciiBlock = new ossim_int8[length];
+            m_str.read((char*)geoAsciiBlock, length);
+         }
+         else
+         {
+            m_str.seekg(length, ios_base::cur);
+         }
+      }
+
+      //---
+      // Must have at mimimum the geoKeyBlock for a projection.
+      // Note the geoDoubleBlock is needed for some.
+      // Note the geoAsciiBlock is not needed, i.e. only informational.
+      //---
+      if ( geoKeyBlock )
+      {       
+         //---
+         // Give the geokeys to ossimTiffInfo to get back a keyword list that can be fed to
+         // ossimProjectionFactoryRegistry::createProjection
+         //---
+         ossimTiffInfo info;
+         ossimKeywordlist geomKwl;
+         info.getImageGeometry(geoKeyLength, geoKeyBlock,
+                               geoDoubleLength,geoDoubleBlock,
+                               geoAsciiLength,geoAsciiBlock,
+                               geomKwl);
+         
+         // Create the projection.
+         m_proj = ossimProjectionFactoryRegistry::instance()->createProjection(geomKwl);
+         if (m_proj.valid())
+         {
+            // Units must be set before initValues and initProjection.
+            initUnits(geomKwl);
+            
+            // Must be called before initProjection.
+            initValues();
+            
+            result = initProjection();  // Sets the ties and scale...
+            
+            if (traceDebug())
+            {
+               m_proj->print(ossimNotify(ossimNotifyLevel_DEBUG));
+            }
+         }
+      }
+
+      if ( geoKeyBlock )
+      {
+         delete [] geoKeyBlock;
+         geoKeyBlock = 0;
+      }
+      if (geoDoubleBlock)
+      {
+         delete [] geoDoubleBlock;
+         geoDoubleBlock = 0;
+      }
+      if (geoAsciiBlock)
+      {
+         delete [] geoAsciiBlock;
+         geoAsciiBlock = 0;
+      }
+
+      m_str.seekg(origPos);
+
+      if ( endian )
+      {
+         delete endian;
+         endian = 0;
+      }
+   }  
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG) << M << " exit status = " << (result?"true\n":"false\n");
+   }   
+   return result;
+}
+
+bool ossimLasReader::initFromExternalMetadata()
+{
+   static const char M[] = "ossimLasReader::initFromExternalMetadata";
+   if (traceDebug()) ossimNotify(ossimNotifyLevel_DEBUG) << M << " entered...\n";
+   
+   bool result = false;
+
+   ossimFilename fgdcFile = theImageFile;
+   fgdcFile.setExtension("txt");
+   if ( fgdcFile.exists() == false )
+   {
+      fgdcFile.setExtension("TXT");
+   }
+
+   if ( fgdcFile.exists() )
+   {
+      ossimRefPtr<ossimFgdcTxtDoc> fgdcDoc = new ossimFgdcTxtDoc();
+      if ( fgdcDoc->open( fgdcFile ) )
+      {
+         fgdcDoc->getProjection( m_proj );
+         if ( m_proj.valid() )
+         {
+            // Units must be set before initValues and initProjection.
+            std::string units;
+            fgdcDoc->getAltitudeDistanceUnits(units);
+            if ( ( units == "feet" ) || ( units == "international feet" ) )
+            {
+               m_units = OSSIM_FEET;
+            }
+            else if ( units == "survey feet" )
+            {
+               m_units = OSSIM_US_SURVEY_FEET;
+            }
+            else
+            {
+               m_units = OSSIM_METERS;
+            }
+            
+            // Must be called before initProjection.
+            initValues();
+            
+            result = initProjection();  // Sets the ties and scale...
+            
+            if (traceDebug())
+            {
+               m_proj->print(ossimNotify(ossimNotifyLevel_DEBUG));
+            }
+         }
+      }
+   }
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG) << M << " exit status = " << (result?"true\n":"false\n");
+   }   
+   return result;
+}
+
+ossimLasPointRecordInterface* ossimLasReader::getNewPointRecord() const
+{
+   ossimLasPointRecordInterface* result = 0;
+
+   switch(m_hdr->getPointDataFormatId())
+   {
+      case 1:
+      {
+         result = new ossimLasPointRecord1();
+         break;
+      }
+      case 2:
+      {
+         result = new ossimLasPointRecord2();
+         break;
+      }
+      case 3:
+      {
+         result = new ossimLasPointRecord3();
+         break;
+      }
+      case 4:
+      {
+         result = new ossimLasPointRecord4();
+         break;
+      }
+      default:
+      {
+         break;
+      }
+   }
+
+   return result;
+}
+
+void ossimLasReader::getScale(ossimDpt& scale, ossim_uint32 resLevel) const
+{
+   // std::pow(2.0, 0) returns 1.
+   ossim_float64 d = std::pow(2.0, static_cast<double>(resLevel));
+   scale.x = m_scale.x * d;
+   scale.y = m_scale.y * d;
+}
+
+void ossimLasReader::setScale( const ossim_float64& scale )
+{
+   m_scale.x = scale;
+   m_scale.y = m_scale.x;
+
+   if ( m_proj.valid() && ( m_scale.hasNans() == false ) )
+   {
+      ossimMapProjection* proj = dynamic_cast<ossimMapProjection*>( m_proj.get() );
+      if ( proj && ( m_scale.hasNans() == false ) )
+      {
+         if ( proj->isGeographic() )
+         {
+            proj->setDecimalDegreesPerPixel( m_scale );
+         }
+         else
+         {
+            proj->setMetersPerPixel( m_scale );
+         }
+      }
+   }
+}
+
diff --git a/ossim_plugins/las/ossimLasReader.h b/ossim_plugins/las/ossimLasReader.h
new file mode 100644
index 0000000..8858814
--- /dev/null
+++ b/ossim_plugins/las/ossimLasReader.h
@@ -0,0 +1,314 @@
+//----------------------------------------------------------------------------
+//
+// File: ossimLasReader.h
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author:  David Burken
+//
+// Description: OSSIM LAS LIDAR reader.
+//
+//----------------------------------------------------------------------------
+// $Id: ossimLasReader.h 2679 2011-06-06 16:38:44Z david.burken $
+#ifndef ossimLasReader_HEADER
+#define ossimLasReader_HEADER 1
+
+#include <ossim/imaging/ossimImageHandler.h>
+#include <ossim/base/ossimDpt.h>
+#include <ossim/base/ossimRefPtr.h>
+#include <ossim/base/ossimUnitConversionTool.h>
+#include <ossim/imaging/ossimImageData.h>
+#include <ossim/imaging/ossimImageGeometry.h>
+#include <ossim/projection/ossimProjection.h>
+
+class ossimLasHdr;
+class ossimLasPointRecordInterface;
+
+class ossimLasReader : public ossimImageHandler
+{
+public:
+
+   /** default constructor */
+   ossimLasReader();
+
+   /** virtual destructor */
+   virtual ~ossimLasReader();
+
+   /**
+    *  @brief open method.
+    *
+    *  Satisfies ossimImageHandler::open pure virtual.
+    *  
+    *  @return Returns true on success, false on error.
+    *
+    *  @note This method relies on the data member ossimImageData::theImageFile
+    *  being set.  Callers should do a "setFilename" prior to calling this
+    *  method or use the ossimImageHandler::open that takes a file name and an
+    *  entry index.
+    */
+   virtual bool open();
+
+   /**
+    *  @brief is open method.
+    *
+    *  Satisfies ossimImageHandler::isOpen pure virtual.
+    *
+    *  @return true if open, false if not.
+    */
+   virtual bool isOpen()const;
+
+   /**
+    * @brief Close method.
+    */
+   virtual void close();
+
+   /**
+    *  Returns a pointer to a tile given an origin representing the upper left
+    *  corner of the tile to grab from the image.
+    *  Satisfies pure virtual from TileSource class.
+    */
+   virtual ossimRefPtr<ossimImageData> getTile(const  ossimIrect& rect,
+                                               ossim_uint32 resLevel=0);
+   
+   /**
+    * Method to get a tile.   
+    *
+    * @param result The tile to stuff.  Note The requested rectangle in full
+    * image space and bands should be set in the result tile prior to
+    * passing.  It will be an error if:
+    * result.getNumberOfBands() != this->getNumberOfOutputBands()
+    *
+    * @return true on success false on error.  If return is false, result
+    *  is undefined so caller should handle appropriately with makeBlank or
+    * whatever.
+    */
+   virtual bool getTile(ossimImageData* result, ossim_uint32 resLevel=0);
+   
+   /**
+    * @brief Gets bands.
+    *
+    * Satisfies ossimImageSource::getNumberOfInputBands pure virtual.
+    * 
+    * @retrun Number of bands.
+    */
+   virtual ossim_uint32 getNumberOfInputBands() const;
+
+   /**
+    * @brief Gets lines.
+    *
+    * Satisfies ossimImageHandler::getNumberOfLines pure virtual.
+    *
+    * @param resLevel Reduced resolution level to return lines of.
+    * Default = 0
+    *
+    * @return The number of lines for specified reduced resolution level.
+    */
+   virtual ossim_uint32 getNumberOfLines(ossim_uint32 resLevel = 0) const;
+
+   /**
+    * @brief Gets samples.
+    *
+    * Satisfies ossimImageHandler::getNumberOfSamples
+    *
+    * @param resLevel Reduced resolution level to return samples of.
+    * Default = 0
+    *
+    * @return The number of samples for specified reduced resolution level.
+    */
+   virtual ossim_uint32 getNumberOfSamples(ossim_uint32 resLevel = 0) const;
+    
+   /**
+    * @brief Gets tile width.
+    *
+    * Satisfies ossimImageHandler::getImageTileWidth pure virtual.
+    * 
+    * @return The tile width of the image or 0 if the image is not tiled.
+    * Note: this is not the same as the ossimImageSource::getTileWidth which
+    * returns the output tile width which can be different than the internal
+    * image tile width on disk.
+    */
+   virtual ossim_uint32 getImageTileWidth() const;
+
+   /**
+    * @brief Gets tile height.
+    *
+    * Satisfies ossimImageHandler::getImageTileHeight pure virtual.
+    * 
+    * @return The tile width of the image or 0 if the image is not tiled.
+    * Note: this is not the same as the ossimImageSource::getTileWidth which
+    * returns the output tile width which can be different than the internal
+    * image tile width on disk.
+    */
+   virtual ossim_uint32 getImageTileHeight() const;
+
+   /** @return The width of the output tile. */
+   virtual ossim_uint32 getTileWidth() const;
+   
+   /** @returns The height of the output tile. */
+   virtual ossim_uint32 getTileHeight() const;
+
+   /** @return The output pixel type of the tile source. */
+   ossimScalarType getOutputScalarType() const;
+
+   /**
+    * @brief Gets entry list.
+    * @param entryList This is the list to initialize with entry indexes.
+    */
+   virtual void getEntryList(std::vector<ossim_uint32>& entryList) const;
+
+   /** @return The current entry number. */
+   virtual ossim_uint32 getCurrentEntry() const;
+
+   /**
+    * @param entryIdx Entry number to select.
+    * @return true if it was able to set the current entry and false otherwise.
+    */
+   virtual bool setCurrentEntry(ossim_uint32 entryIdx);
+
+   /** @return "las" */
+   virtual ossimString getShortName() const;
+   
+   /** @return "ossim las (liblas) reader" */
+   virtual ossimString getLongName()  const;
+
+   /**
+    * Returns the image geometry object associated with this tile source or
+    * NULL if non defined.  The geometry contains full-to-local image
+    * transform as well as projection (image-to-world).
+    */
+   virtual ossimRefPtr<ossimImageGeometry> getImageGeometry();
+
+   /** @return Min pixel value. */
+   virtual double getMinPixelValue(ossim_uint32 band=0) const;
+
+   /** @return Min pixel value. */
+   virtual double getMaxPixelValue(ossim_uint32 band=0) const;
+
+   /** @return Min pixel value. */
+   virtual double getNullPixelValue(ossim_uint32 band=0) const;
+
+   /**
+    * @brief Method to save the state of an object to a keyword list.
+    * @return true if ok or false on error.
+    */
+   virtual bool saveState(ossimKeywordlist& kwl, const char* prefix=0)const;
+  
+   /**
+    * @brief Method to the load (recreate) the state of an object from a keyword list.
+    * @return true if ok or false on error.
+    */
+   virtual bool loadState(const ossimKeywordlist& kwl, const char* prefix=0);
+
+   /**
+    * @brief Set propterty method. Overrides ossimImageHandler::setProperty.
+    *
+    * Current property name handled:
+    * "scale" One double value representing the scale in meters per pixel. It is
+    * assumed the scale is same for x and y direction.
+    * 
+    * @param property to set.
+    */
+   virtual void setProperty(ossimRefPtr<ossimProperty> property);
+
+   /**
+     * @brief Get propterty method. Overrides ossimImageHandler::getProperty.
+    * @param name Property name to get.
+    */
+   virtual ossimRefPtr<ossimProperty> getProperty(const ossimString& name) const;
+
+   /**
+    * @brief Get propterty names. Overrides ossimImageHandler::getPropertyNames.
+    * @param propertyNames Array to initialize.
+    */
+   virtual void getPropertyNames(std::vector<ossimString>& propertyNames) const;
+
+   /** @return The total number of decimation levels. */
+   virtual ossim_uint32 getNumberOfDecimationLevels() const;
+
+protected:
+   /**
+    * @brief Will complete the opening process.
+    *
+    * Overrides ossimImageHandler::completeOpen() as we do not ever have overviews.
+    */
+   virtual void completeOpen();
+   
+private:
+
+   /**
+    * @brief Container class to hold accumulated point data.  Currently single
+    * band.
+    */
+   class Bucket
+   {
+   public:
+      Bucket(): a(0.0), c(0) {}
+         
+      void add(const ossim_float64& point) { a += point; ++c; }
+      ossim_float64 getValue() const { return ( c ? a/c : -99999.0 ); }
+
+      ossim_float64 a; // accumulation
+      ossim_uint32  c; // count
+   };
+
+   bool init();
+   
+   void initValues(); // m_ul, m_lr, m_minZ
+   bool initProjection();
+   void initTile();
+   void initUnits(const ossimKeywordlist& geomKwl);
+   bool parseVarRecords();
+
+   /**
+    * @brief Looks for external FGDC text file to initialize projection from.
+    */
+   bool initFromExternalMetadata();
+   
+   /** @brief Get the scale for resLevel. */
+   void getScale(ossimDpt& scale, ossim_uint32 resLevel) const;
+
+   /** @brief Sets m_scale data member and projection if projection is set. */
+   void setScale( const ossim_float64& scale );
+
+   void convertToMeters(ossim_float64& value) const;
+
+   /**
+    * Returns a point of type.
+    */
+   ossimLasPointRecordInterface* getNewPointRecord() const;
+
+   std::ifstream                m_str;
+   ossimLasHdr*                 m_hdr;
+   ossimRefPtr<ossimProjection> m_proj;
+   ossimDpt                     m_ul;
+   ossimDpt                     m_lr;
+   ossim_float64                m_maxZ;
+   ossim_float64                m_minZ;
+   ossimDpt                     m_scale;
+   ossimRefPtr<ossimImageData>  m_tile;
+   ossim_uint8                  m_entry;
+   OpenThreads::Mutex           m_mutex;
+   bool                         m_scan;  // Scan for bounds at open.
+   ossimUnitType                m_units;
+   ossimUnitConversionTool*     m_unitConverter;
+TYPE_DATA
+};
+
+inline bool ossimLasReader::isOpen()const
+{
+   return ( m_str.is_open() && m_hdr );
+}
+
+inline void ossimLasReader::convertToMeters(ossim_float64& value) const
+{
+   if ( value )
+   {
+      m_unitConverter->setValue(value, m_units);
+      value = m_unitConverter->getMeters();
+   }
+}
+
+#endif /* #ifndef ossimLasReader_HEADER */
+
diff --git a/ossim_plugins/las/ossimLasReaderFactory.cpp b/ossim_plugins/las/ossimLasReaderFactory.cpp
new file mode 100644
index 0000000..abed8f6
--- /dev/null
+++ b/ossim_plugins/las/ossimLasReaderFactory.cpp
@@ -0,0 +1,133 @@
+//----------------------------------------------------------------------------
+//
+// File: ossimLasReaderFactory.cpp
+// 
+// License:  See top level LICENSE.txt file
+//
+// Author:  David Burken
+//
+// Description: Reader factory for OSSIM LAS plugin.
+//----------------------------------------------------------------------------
+// $Id: ossimLasReaderFactory.cpp 2645 2011-05-26 15:21:34Z oscar.kramer $
+
+#include "ossimLasReaderFactory.h"
+#include "ossimLasReader.h"
+#include <ossim/base/ossimKeywordlist.h>
+#include <ossim/base/ossimRefPtr.h>
+#include <ossim/base/ossimString.h>
+#include <ossim/imaging/ossimImageHandler.h>
+#include <ossim/base/ossimTrace.h>
+#include <ossim/base/ossimKeywordNames.h>
+
+static const ossimTrace traceDebug("ossimLasReaderFactory:debug");
+
+RTTI_DEF1(ossimLasReaderFactory,
+          "ossimLasReaderFactory",
+          ossimImageHandlerFactoryBase);
+
+ossimLasReaderFactory* ossimLasReaderFactory::theInstance = 0;
+
+ossimLasReaderFactory::~ossimLasReaderFactory()
+{
+   theInstance = 0;
+}
+
+ossimLasReaderFactory* ossimLasReaderFactory::instance()
+{
+   if(!theInstance)
+   {
+      theInstance = new ossimLasReaderFactory;
+   }
+   return theInstance;
+}
+   
+ossimImageHandler* ossimLasReaderFactory::open(
+   const ossimFilename& fileName, bool openOverview)const
+{
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimLasReaderFactory::open(filename) DEBUG: entered..."
+         << "\ntrying ossimLasReader"
+         << std::endl;
+   }
+   
+   ossimRefPtr<ossimImageHandler> reader = 0;
+
+   reader = new ossimLasReader;
+   reader->setOpenOverviewFlag(openOverview);
+   if(reader->open(fileName) == false)
+   {
+      reader = 0;
+   }
+   
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimLasReaderFactory::open(filename) DEBUG: leaving..."
+         << std::endl;
+   }
+   
+   return reader.release();
+}
+
+ossimImageHandler* ossimLasReaderFactory::open(const ossimKeywordlist& kwl,
+                                               const char* prefix)const
+{
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimLasReaderFactory::open(kwl, prefix) DEBUG: entered..."
+         << "Trying ossimLasReader"
+         << std::endl;
+   }
+
+   ossimRefPtr<ossimImageHandler> reader = new ossimLasReader;
+   if(reader->loadState(kwl, prefix) == false)
+   {
+      reader = 0;
+   }
+   
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimLasReaderFactory::open(kwl, prefix) DEBUG: leaving..."
+         << std::endl;
+   }
+   
+   return reader.release();
+}
+
+ossimObject* ossimLasReaderFactory::createObject(
+   const ossimString& typeName)const
+{
+   ossimRefPtr<ossimObject> result = 0;
+   if(typeName == "ossimLasReader")
+   {
+      result = new ossimLasReader;
+   }
+   return result.release();
+}
+
+ossimObject* ossimLasReaderFactory::createObject(const ossimKeywordlist& kwl,
+                                                 const char* prefix)const
+{
+   return this->open(kwl, prefix);
+}
+ 
+void ossimLasReaderFactory::getTypeNameList(std::vector<ossimString>& typeList)const
+{
+   typeList.push_back(ossimString("ossimLasReader"));
+}
+
+void ossimLasReaderFactory::getSupportedExtensions(
+   ossimImageHandlerFactoryBase::UniqueStringList& extensionList)const
+{
+   extensionList.push_back(ossimString("las"));
+}
+
+ossimLasReaderFactory::ossimLasReaderFactory(){}
+
+ossimLasReaderFactory::ossimLasReaderFactory(const ossimLasReaderFactory&){}
+
+void ossimLasReaderFactory::operator=(const ossimLasReaderFactory&){}
diff --git a/ossim_plugins/las/ossimLasReaderFactory.h b/ossim_plugins/las/ossimLasReaderFactory.h
new file mode 100644
index 0000000..150bf35
--- /dev/null
+++ b/ossim_plugins/las/ossimLasReaderFactory.h
@@ -0,0 +1,100 @@
+//----------------------------------------------------------------------------
+//
+// File: ossimLasReaderFactory.h
+// 
+// License:  See top level LICENSE.txt file
+//
+// Author:  David Burken
+//
+// Description: Reader factory for OSSIM LAS plugin.
+//----------------------------------------------------------------------------
+// $Id: ossimLasReaderFactory.h 2645 2011-05-26 15:21:34Z oscar.kramer $
+#ifndef ossimLasReaderFactory_HEADER
+#define ossimLasReaderFactory_HEADER 1
+
+#include <ossim/imaging/ossimImageHandlerFactoryBase.h>
+
+class ossimString;
+class ossimFilename;
+class ossimKeywordlist;
+
+/** @brief Factory for PNG image reader. */
+class ossimLasReaderFactory : public ossimImageHandlerFactoryBase
+{
+public:
+
+   /** @brief virtual destructor */
+   virtual ~ossimLasReaderFactory();
+
+   /**
+    * @brief static method to return instance (the only one) of this class.
+    * @return pointer to instance of this class.
+    */
+   static ossimLasReaderFactory* instance();
+
+   /**
+    * @brief open that takes a file name.
+    * @param file The file to open.
+    * @param openOverview If true image handler will attempt to open overview.
+    * default = true 
+    * @return pointer to image handler on success, NULL on failure.
+    */
+   virtual ossimImageHandler* open(const ossimFilename& fileName,
+                                   bool openOverview=true) const;
+
+   /**
+    * @brief open that takes a keyword list and prefix.
+    * @param kwl The keyword list.
+    * @param prefix the keyword list prefix.
+    * @return pointer to image handler on success, NULL on failure.
+    */
+   virtual ossimImageHandler* open(const ossimKeywordlist& kwl,
+                                   const char* prefix=0)const;
+
+   /**
+    * @brief createObject that takes a class name (ossimLasReader)
+    * @param typeName Should be "ossimLasReader".
+    * @return pointer to image writer on success, NULL on failure.
+    */
+   virtual ossimObject* createObject(const ossimString& typeName)const;
+   
+   /**
+    * @brief Creates and object given a keyword list and prefix.
+    * @param kwl The keyword list.
+    * @param prefix the keyword list prefix.
+    * @return pointer to image handler on success, NULL on failure.
+    */
+   virtual ossimObject* createObject(const ossimKeywordlist& kwl,
+                                     const char* prefix=0)const;
+   
+   /**
+    * @brief Adds ossimLasWriter to the typeList.
+    * @param typeList List to add to.
+    */
+   virtual void getTypeNameList(std::vector<ossimString>& typeList)const;
+
+   /**
+    * @brief Method to add supported extension to the list, like "png".
+    *
+    * @param extensionList The list to add to.
+    */
+   virtual void getSupportedExtensions(
+      ossimImageHandlerFactoryBase::UniqueStringList& extensionList)const;
+  
+protected:
+   /** @brief hidden from use default constructor */
+   ossimLasReaderFactory();
+
+   /** @brief hidden from use copy constructor */
+   ossimLasReaderFactory(const ossimLasReaderFactory&);
+
+   /** @brief hidden from use copy constructor */
+   void operator=(const ossimLasReaderFactory&);
+
+   /** static instance of this class */
+   static ossimLasReaderFactory* theInstance;
+
+TYPE_DATA
+};
+
+#endif /* end of #ifndef ossimLasReaderFactory_HEADER */
diff --git a/ossim_plugins/libraw/CMakeLists.txt b/ossim_plugins/libraw/CMakeLists.txt
new file mode 100644
index 0000000..6d377a9
--- /dev/null
+++ b/ossim_plugins/libraw/CMakeLists.txt
@@ -0,0 +1,37 @@
+set(LIB_NAME ossimlibraw_plugin)
+MESSAGE( "************** LIBRARY SETUP FOR ossimlibraw_plugin******************")
+
+# Include ossim cmake stuff:
+include(OssimVersion)
+include(OssimCommonVariables)
+include(OssimUtilities)
+
+SET(LIBRAW_SRC LibRaw-0.9.0)
+find_package(JPEG)
+find_package(TIFF)
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR} ${LIBRAW_SRC} ${JPEG_INCLUDE_DIR} ${TIFF_INCLUDE_DIR})
+
+FILE(GLOB OSSIMPLUGIN_SRCS ${LIBRAW_SRC}/internal/*.cpp ${LIBRAW_SRC}/src/*.cpp *.cpp)
+FILE(GLOB OSSIMPLUGIN_HEADERS ${LIBRAW_SRC}/internal/*.h *.h ${LIBRAW_SRC}/libraw/*.h)
+
+####
+# OSSIMPLUGINSMAKINGDLL controls dll linkage on windows.  
+# Adding this sets OSSIM_PLUGINS_DLL #define TO "__declspec(dllexport)".
+###
+add_definitions("-DOSSIMPLUGINSMAKINGDLL")
+
+# Adjust the install library path:
+if(OSSIM_INSTALL_PLUGINS_WITH_VERSION)
+   set(INSTALL_LIBRARY_DIR   "${INSTALL_LIBRARY_DIR}/ossim-${OSSIM_VERSION}/plugins")
+else(OSSIM_INSTALL_PLUGINS_WITH_VERSION)
+   set(INSTALL_LIBRARY_DIR   "${INSTALL_LIBRARY_DIR}/ossim/plugins")
+endif(OSSIM_INSTALL_PLUGINS_WITH_VERSION)
+
+OSSIM_LINK_LIBRARY(${LIB_NAME}
+                   COMPONENT_NAME ossim TYPE "${OSSIM_PLUGIN_LINK_TYPE}"
+		   LIBRARIES ${OSSIM_LIBRARIES} ${OPENTHREADS_LIBRARY} ${JPEG_LIBRARY} ${TIFF_LIBRARY}
+                   HEADERS "${OSSIMPLUGIN_HEADERS}"
+		   SOURCE_FILES "${OSSIMPLUGIN_SRCS}" ADDITIONAL_COMPILE_FLAGS "-DLIBRAW_NOTHREADS -DLIBRAW_NODLL"
+                   INSTALL_LIB)
+
+
diff --git a/ossim_plugins/libraw/LibRaw-0.9.0/dcraw/.gdbinit b/ossim_plugins/libraw/LibRaw-0.9.0/dcraw/.gdbinit
new file mode 100644
index 0000000..ac30bf5
--- /dev/null
+++ b/ossim_plugins/libraw/LibRaw-0.9.0/dcraw/.gdbinit
@@ -0,0 +1,2 @@
+set args -s 5 -v test.cine
+b main
diff --git a/ossim_plugins/libraw/LibRaw-0.9.0/dcraw/dcraw.c b/ossim_plugins/libraw/LibRaw-0.9.0/dcraw/dcraw.c
new file mode 100644
index 0000000..338d0cd
--- /dev/null
+++ b/ossim_plugins/libraw/LibRaw-0.9.0/dcraw/dcraw.c
@@ -0,0 +1,8784 @@
+/*
+   dcraw.c -- Dave Coffin's raw photo decoder
+   Copyright 1997-2009 by Dave Coffin, dcoffin a cybercom o net
+
+   This is a command-line ANSI C program to convert raw photos from
+   any digital camera on any computer running any operating system.
+
+   No license is required to download and use dcraw.c.  However,
+   to lawfully redistribute dcraw, you must either (a) offer, at
+   no extra charge, full source code* for all executable files
+   containing RESTRICTED functions, (b) distribute this code under
+   the GPL Version 2 or later, (c) remove all RESTRICTED functions,
+   re-implement them, or copy them from an earlier, unrestricted
+   Revision of dcraw.c, or (d) purchase a license from the author.
+
+   The functions that process Foveon images have been RESTRICTED
+   since Revision 1.237.  All other code remains free for all uses.
+
+   *If you have not modified dcraw.c in any way, a link to my
+   homepage qualifies as "full source code".
+
+   $Revision: 1.432 $
+   $Date: 2009/12/25 18:51:16 $
+ */
+
+#define VERSION "8.99"
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+#define _USE_MATH_DEFINES
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <float.h>
+#include <limits.h>
+#include <math.h>
+#include <setjmp.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <sys/types.h>
+/*
+   NO_JPEG disables decoding of compressed Kodak DC120 files.
+   NO_LCMS disables the "-p" option.
+ */
+#ifndef NO_JPEG
+#include <jpeglib.h>
+#endif
+#ifndef NO_LCMS
+#include <lcms.h>
+#endif
+#ifdef LOCALEDIR
+#include <libintl.h>
+#define _(String) gettext(String)
+#else
+#define _(String) (String)
+#endif
+#ifdef DJGPP
+#define fseeko fseek
+#define ftello ftell
+#else
+#define fgetc getc_unlocked
+#endif
+#ifdef __CYGWIN__
+#include <io.h>
+#endif
+#ifdef WIN32
+#include <sys/utime.h>
+#include <winsock2.h>
+#pragma comment(lib, "ws2_32.lib")
+#define snprintf _snprintf
+#define strcasecmp stricmp
+#define strncasecmp strnicmp
+typedef __int64 INT64;
+typedef unsigned __int64 UINT64;
+#else
+#include <unistd.h>
+#include <utime.h>
+#include <netinet/in.h>
+typedef long long INT64;
+typedef unsigned long long UINT64;
+#endif
+
+#ifdef LJPEG_DECODE
+#error Please compile dcraw.c by itself.
+#error Do not link it with ljpeg_decode.
+#endif
+
+#ifndef LONG_BIT
+#define LONG_BIT (8 * sizeof (long))
+#endif
+
+#define ushort UshORt
+typedef unsigned char uchar;
+typedef unsigned short ushort;
+
+/*
+   All global variables are defined here, and all functions that
+   access them are prefixed with "CLASS".  Note that a thread-safe
+   C++ class cannot have non-const static local variables.
+ */
+FILE *ifp, *ofp;
+short order;
+const char *ifname;
+char *meta_data;
+char cdesc[5], desc[512], make[64], model[64], model2[64], artist[64];
+float flash_used, canon_ev, iso_speed, shutter, aperture, focal_len;
+time_t timestamp;
+unsigned shot_order, kodak_cbpp, filters, exif_cfa, unique_id;
+off_t    strip_offset, data_offset;
+off_t    thumb_offset, meta_offset, profile_offset;
+unsigned thumb_length, meta_length, profile_length;
+unsigned thumb_misc, *oprof, fuji_layout, shot_select=0, multi_out=0;
+unsigned tiff_nifds, tiff_samples, tiff_bps, tiff_compress;
+unsigned black, maximum, mix_green, raw_color, zero_is_bad;
+unsigned zero_after_ff, is_raw, dng_version, is_foveon, data_error;
+unsigned tile_width, tile_length, gpsdata[32], load_flags;
+ushort raw_height, raw_width, height, width, top_margin, left_margin;
+ushort shrink, iheight, iwidth, fuji_width, thumb_width, thumb_height;
+int flip, tiff_flip, colors;
+double pixel_aspect, aber[4]={1,1,1,1}, gamm[6]={ 0.45,4.5,0,0,0,0 };
+ushort (*image)[4], white[8][8], curve[0x10000], cr2_slice[3], sraw_mul[4];
+float bright=1, user_mul[4]={0,0,0,0}, threshold=0;
+int half_size=0, four_color_rgb=0, document_mode=0, highlight=0;
+int verbose=0, use_auto_wb=0, use_camera_wb=0, use_camera_matrix=-1;
+int output_color=1, output_bps=8, output_tiff=0, med_passes=0;
+int no_auto_bright=0;
+unsigned greybox[4] = { 0, 0, UINT_MAX, UINT_MAX };
+float cam_mul[4], pre_mul[4], cmatrix[3][4], rgb_cam[3][4];
+const double xyz_rgb[3][3] = {			/* XYZ from RGB */
+  { 0.412453, 0.357580, 0.180423 },
+  { 0.212671, 0.715160, 0.072169 },
+  { 0.019334, 0.119193, 0.950227 } };
+const float d65_white[3] = { 0.950456, 1, 1.088754 };
+int histogram[4][0x2000];
+void (*write_thumb)(), (*write_fun)();
+void (*load_raw)(), (*thumb_load_raw)();
+jmp_buf failure;
+
+struct decode {
+  struct decode *branch[2];
+  int leaf;
+} first_decode[2048], *second_decode, *free_decode;
+
+struct tiff_ifd {
+  int width, height, bps, comp, phint, offset, flip, samples, bytes;
+} tiff_ifd[10];
+
+struct ph1 {
+  int format, key_off, black, black_off, split_col, tag_21a;
+  float tag_210;
+} ph1;
+
+#define CLASS
+
+#define FORC(cnt) for (c=0; c < cnt; c++)
+#define FORC3 FORC(3)
+#define FORC4 FORC(4)
+#define FORCC FORC(colors)
+
+#define SQR(x) ((x)*(x))
+#define ABS(x) (((int)(x) ^ ((int)(x) >> 31)) - ((int)(x) >> 31))
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+#define MAX(a,b) ((a) > (b) ? (a) : (b))
+#define LIM(x,min,max) MAX(min,MIN(x,max))
+#define ULIM(x,y,z) ((y) < (z) ? LIM(x,y,z) : LIM(x,z,y))
+#define CLIP(x) LIM(x,0,65535)
+#define SWAP(a,b) { a ^= b; a ^= (b ^= a); }
+
+/*
+   In order to inline this calculation, I make the risky
+   assumption that all filter patterns can be described
+   by a repeating pattern of eight rows and two columns
+
+   Do not use the FC or BAYER macros with the Leaf CatchLight,
+   because its pattern is 16x16, not 2x8.
+
+   Return values are either 0/1/2/3 = G/M/C/Y or 0/1/2/3 = R/G1/B/G2
+
+	PowerShot 600	PowerShot A50	PowerShot Pro70	Pro90 & G1
+	0xe1e4e1e4:	0x1b4e4b1e:	0x1e4b4e1b:	0xb4b4b4b4:
+
+	  0 1 2 3 4 5	  0 1 2 3 4 5	  0 1 2 3 4 5	  0 1 2 3 4 5
+	0 G M G M G M	0 C Y C Y C Y	0 Y C Y C Y C	0 G M G M G M
+	1 C Y C Y C Y	1 M G M G M G	1 M G M G M G	1 Y C Y C Y C
+	2 M G M G M G	2 Y C Y C Y C	2 C Y C Y C Y
+	3 C Y C Y C Y	3 G M G M G M	3 G M G M G M
+			4 C Y C Y C Y	4 Y C Y C Y C
+	PowerShot A5	5 G M G M G M	5 G M G M G M
+	0x1e4e1e4e:	6 Y C Y C Y C	6 C Y C Y C Y
+			7 M G M G M G	7 M G M G M G
+	  0 1 2 3 4 5
+	0 C Y C Y C Y
+	1 G M G M G M
+	2 C Y C Y C Y
+	3 M G M G M G
+
+   All RGB cameras use one of these Bayer grids:
+
+	0x16161616:	0x61616161:	0x49494949:	0x94949494:
+
+	  0 1 2 3 4 5	  0 1 2 3 4 5	  0 1 2 3 4 5	  0 1 2 3 4 5
+	0 B G B G B G	0 G R G R G R	0 G B G B G B	0 R G R G R G
+	1 G R G R G R	1 B G B G B G	1 R G R G R G	1 G B G B G B
+	2 B G B G B G	2 G R G R G R	2 G B G B G B	2 R G R G R G
+	3 G R G R G R	3 B G B G B G	3 R G R G R G	3 G B G B G B
+ */
+
+#define FC(row,col) \
+	(filters >> ((((row) << 1 & 14) + ((col) & 1)) << 1) & 3)
+
+#define BAYER(row,col) \
+	image[((row) >> shrink)*iwidth + ((col) >> shrink)][FC(row,col)]
+
+#define BAYER2(row,col) \
+	image[((row) >> shrink)*iwidth + ((col) >> shrink)][fc(row,col)]
+
+int CLASS fc (int row, int col)
+{
+  static const char filter[16][16] =
+  { { 2,1,1,3,2,3,2,0,3,2,3,0,1,2,1,0 },
+    { 0,3,0,2,0,1,3,1,0,1,1,2,0,3,3,2 },
+    { 2,3,3,2,3,1,1,3,3,1,2,1,2,0,0,3 },
+    { 0,1,0,1,0,2,0,2,2,0,3,0,1,3,2,1 },
+    { 3,1,1,2,0,1,0,2,1,3,1,3,0,1,3,0 },
+    { 2,0,0,3,3,2,3,1,2,0,2,0,3,2,2,1 },
+    { 2,3,3,1,2,1,2,1,2,1,1,2,3,0,0,1 },
+    { 1,0,0,2,3,0,0,3,0,3,0,3,2,1,2,3 },
+    { 2,3,3,1,1,2,1,0,3,2,3,0,2,3,1,3 },
+    { 1,0,2,0,3,0,3,2,0,1,1,2,0,1,0,2 },
+    { 0,1,1,3,3,2,2,1,1,3,3,0,2,1,3,2 },
+    { 2,3,2,0,0,1,3,0,2,0,1,2,3,0,1,0 },
+    { 1,3,1,2,3,2,3,2,0,2,0,1,1,0,3,0 },
+    { 0,2,0,3,1,0,0,1,1,3,3,2,3,2,2,1 },
+    { 2,1,3,2,3,1,2,1,0,3,0,2,0,2,0,2 },
+    { 0,3,1,0,0,2,0,3,2,1,3,1,1,3,1,3 } };
+
+  if (filters != 1) return FC(row,col);
+  return filter[(row+top_margin) & 15][(col+left_margin) & 15];
+}
+
+#ifndef __GLIBC__
+char *my_memmem (char *haystack, size_t haystacklen,
+	      char *needle, size_t needlelen)
+{
+  char *c;
+  for (c = haystack; c <= haystack + haystacklen - needlelen; c++)
+    if (!memcmp (c, needle, needlelen))
+      return c;
+  return 0;
+}
+#define memmem my_memmem
+#endif
+
+void CLASS merror (void *ptr, const char *where)
+{
+  if (ptr) return;
+  fprintf (stderr,_("%s: Out of memory in %s\n"), ifname, where);
+  longjmp (failure, 1);
+}
+
+void CLASS derror()
+{
+  if (!data_error) {
+    fprintf (stderr, "%s: ", ifname);
+    if (feof(ifp))
+      fprintf (stderr,_("Unexpected end of file\n"));
+    else
+      fprintf (stderr,_("Corrupt data near 0x%llx\n"), (INT64) ftello(ifp));
+  }
+  data_error++;
+}
+
+ushort CLASS sget2 (uchar *s)
+{
+  if (order == 0x4949)		/* "II" means little-endian */
+    return s[0] | s[1] << 8;
+  else				/* "MM" means big-endian */
+    return s[0] << 8 | s[1];
+}
+
+ushort CLASS get2()
+{
+  uchar str[2] = { 0xff,0xff };
+  fread (str, 1, 2, ifp);
+  return sget2(str);
+}
+
+unsigned CLASS sget4 (uchar *s)
+{
+  if (order == 0x4949)
+    return s[0] | s[1] << 8 | s[2] << 16 | s[3] << 24;
+  else
+    return s[0] << 24 | s[1] << 16 | s[2] << 8 | s[3];
+}
+#define sget4(s) sget4((uchar *)s)
+
+unsigned CLASS get4()
+{
+  uchar str[4] = { 0xff,0xff,0xff,0xff };
+  fread (str, 1, 4, ifp);
+  return sget4(str);
+}
+
+unsigned CLASS getint (int type)
+{
+  return type == 3 ? get2() : get4();
+}
+
+float CLASS int_to_float (int i)
+{
+  union { int i; float f; } u;
+  u.i = i;
+  return u.f;
+}
+
+double CLASS getreal (int type)
+{
+  union { char c[8]; double d; } u;
+  int i, rev;
+
+  switch (type) {
+    case 3: return (unsigned short) get2();
+    case 4: return (unsigned int) get4();
+    case 5:  u.d = (unsigned int) get4();
+      return u.d / (unsigned int) get4();
+    case 8: return (signed short) get2();
+    case 9: return (signed int) get4();
+    case 10: u.d = (signed int) get4();
+      return u.d / (signed int) get4();
+    case 11: return int_to_float (get4());
+    case 12:
+      rev = 7 * ((order == 0x4949) == (ntohs(0x1234) == 0x1234));
+      for (i=0; i < 8; i++)
+	u.c[i ^ rev] = fgetc(ifp);
+      return u.d;
+    default: return fgetc(ifp);
+  }
+}
+
+void CLASS read_shorts (ushort *pixel, int count)
+{
+  if (fread (pixel, 2, count, ifp) < count) derror();
+  if ((order == 0x4949) == (ntohs(0x1234) == 0x1234))
+    swab (pixel, pixel, count*2);
+}
+
+void CLASS canon_black (double dark[2], int nblack)
+{
+  int c, diff, row, col;
+
+  if (!nblack) return;
+  FORC(2) dark[c] /= nblack >> 1;
+  if ((diff = dark[0] - dark[1]))
+    for (row=0; row < height; row++)
+      for (col=1; col < width; col+=2)
+	BAYER(row,col) += diff;
+  dark[1] += diff;
+  black = (dark[0] + dark[1] + 1) / 2;
+}
+
+void CLASS canon_600_fixed_wb (int temp)
+{
+  static const short mul[4][5] = {
+    {  667, 358,397,565,452 },
+    {  731, 390,367,499,517 },
+    { 1119, 396,348,448,537 },
+    { 1399, 485,431,508,688 } };
+  int lo, hi, i;
+  float frac=0;
+
+  for (lo=4; --lo; )
+    if (*mul[lo] <= temp) break;
+  for (hi=0; hi < 3; hi++)
+    if (*mul[hi] >= temp) break;
+  if (lo != hi)
+    frac = (float) (temp - *mul[lo]) / (*mul[hi] - *mul[lo]);
+  for (i=1; i < 5; i++)
+    pre_mul[i-1] = 1 / (frac * mul[hi][i] + (1-frac) * mul[lo][i]);
+}
+
+/* Return values:  0 = white  1 = near white  2 = not white */
+int CLASS canon_600_color (int ratio[2], int mar)
+{
+  int clipped=0, target, miss;
+
+  if (flash_used) {
+    if (ratio[1] < -104)
+      { ratio[1] = -104; clipped = 1; }
+    if (ratio[1] >   12)
+      { ratio[1] =   12; clipped = 1; }
+  } else {
+    if (ratio[1] < -264 || ratio[1] > 461) return 2;
+    if (ratio[1] < -50)
+      { ratio[1] = -50; clipped = 1; }
+    if (ratio[1] > 307)
+      { ratio[1] = 307; clipped = 1; }
+  }
+  target = flash_used || ratio[1] < 197
+	? -38 - (398 * ratio[1] >> 10)
+	: -123 + (48 * ratio[1] >> 10);
+  if (target - mar <= ratio[0] &&
+      target + 20  >= ratio[0] && !clipped) return 0;
+  miss = target - ratio[0];
+  if (abs(miss) >= mar*4) return 2;
+  if (miss < -20) miss = -20;
+  if (miss > mar) miss = mar;
+  ratio[0] = target - miss;
+  return 1;
+}
+
+void CLASS canon_600_auto_wb()
+{
+  int mar, row, col, i, j, st, count[] = { 0,0 };
+  int test[8], total[2][8], ratio[2][2], stat[2];
+
+  memset (&total, 0, sizeof total);
+  i = canon_ev + 0.5;
+  if      (i < 10) mar = 150;
+  else if (i > 12) mar = 20;
+  else mar = 280 - 20 * i;
+  if (flash_used) mar = 80;
+  for (row=14; row < height-14; row+=4)
+    for (col=10; col < width; col+=2) {
+      for (i=0; i < 8; i++)
+	test[(i & 4) + FC(row+(i >> 1),col+(i & 1))] =
+		    BAYER(row+(i >> 1),col+(i & 1));
+      for (i=0; i < 8; i++)
+	if (test[i] < 150 || test[i] > 1500) goto next;
+      for (i=0; i < 4; i++)
+	if (abs(test[i] - test[i+4]) > 50) goto next;
+      for (i=0; i < 2; i++) {
+	for (j=0; j < 4; j+=2)
+	  ratio[i][j >> 1] = ((test[i*4+j+1]-test[i*4+j]) << 10) / test[i*4+j];
+	stat[i] = canon_600_color (ratio[i], mar);
+      }
+      if ((st = stat[0] | stat[1]) > 1) goto next;
+      for (i=0; i < 2; i++)
+	if (stat[i])
+	  for (j=0; j < 2; j++)
+	    test[i*4+j*2+1] = test[i*4+j*2] * (0x400 + ratio[i][j]) >> 10;
+      for (i=0; i < 8; i++)
+	total[st][i] += test[i];
+      count[st]++;
+next: ;
+    }
+  if (count[0] | count[1]) {
+    st = count[0]*200 < count[1];
+    for (i=0; i < 4; i++)
+      pre_mul[i] = 1.0 / (total[st][i] + total[st][i+4]);
+  }
+}
+
+void CLASS canon_600_coeff()
+{
+  static const short table[6][12] = {
+    { -190,702,-1878,2390,   1861,-1349,905,-393, -432,944,2617,-2105  },
+    { -1203,1715,-1136,1648, 1388,-876,267,245,  -1641,2153,3921,-3409 },
+    { -615,1127,-1563,2075,  1437,-925,509,3,     -756,1268,2519,-2007 },
+    { -190,702,-1886,2398,   2153,-1641,763,-251, -452,964,3040,-2528  },
+    { -190,702,-1878,2390,   1861,-1349,905,-393, -432,944,2617,-2105  },
+    { -807,1319,-1785,2297,  1388,-876,769,-257,  -230,742,2067,-1555  } };
+  int t=0, i, c;
+  float mc, yc;
+
+  mc = pre_mul[1] / pre_mul[2];
+  yc = pre_mul[3] / pre_mul[2];
+  if (mc > 1 && mc <= 1.28 && yc < 0.8789) t=1;
+  if (mc > 1.28 && mc <= 2) {
+    if  (yc < 0.8789) t=3;
+    else if (yc <= 2) t=4;
+  }
+  if (flash_used) t=5;
+  for (raw_color = i=0; i < 3; i++)
+    FORCC rgb_cam[i][c] = table[t][i*4 + c] / 1024.0;
+}
+
+void CLASS canon_600_load_raw()
+{
+  uchar  data[1120], *dp;
+  ushort pixel[896], *pix;
+  int irow, row, col, val;
+  static const short mul[4][2] =
+  { { 1141,1145 }, { 1128,1109 }, { 1178,1149 }, { 1128,1109 } };
+
+  for (irow=row=0; irow < height; irow++) {
+    if (fread (data, 1, raw_width*5/4, ifp) < raw_width*5/4) derror();
+    for (dp=data, pix=pixel; dp < data+1120; dp+=10, pix+=8) {
+      pix[0] = (dp[0] << 2) + (dp[1] >> 6    );
+      pix[1] = (dp[2] << 2) + (dp[1] >> 4 & 3);
+      pix[2] = (dp[3] << 2) + (dp[1] >> 2 & 3);
+      pix[3] = (dp[4] << 2) + (dp[1]      & 3);
+      pix[4] = (dp[5] << 2) + (dp[9]      & 3);
+      pix[5] = (dp[6] << 2) + (dp[9] >> 2 & 3);
+      pix[6] = (dp[7] << 2) + (dp[9] >> 4 & 3);
+      pix[7] = (dp[8] << 2) + (dp[9] >> 6    );
+    }
+    for (col=0; col < width; col++)
+      BAYER(row,col) = pixel[col];
+    for (col=width; col < raw_width; col++)
+      black += pixel[col];
+    if ((row+=2) > height) row = 1;
+  }
+  if (raw_width > width)
+    black = black / ((raw_width - width) * height) - 4;
+  for (row=0; row < height; row++)
+    for (col=0; col < width; col++) {
+      if ((val = BAYER(row,col) - black) < 0) val = 0;
+      val = val * mul[row & 3][col & 1] >> 9;
+      BAYER(row,col) = val;
+    }
+  canon_600_fixed_wb(1311);
+  canon_600_auto_wb();
+  canon_600_coeff();
+  maximum = (0x3ff - black) * 1109 >> 9;
+  black = 0;
+}
+
+void CLASS remove_zeroes()
+{
+  unsigned row, col, tot, n, r, c;
+
+  for (row=0; row < height; row++)
+    for (col=0; col < width; col++)
+      if (BAYER(row,col) == 0) {
+	tot = n = 0;
+	for (r = row-2; r <= row+2; r++)
+	  for (c = col-2; c <= col+2; c++)
+	    if (r < height && c < width &&
+		FC(r,c) == FC(row,col) && BAYER(r,c))
+	      tot += (n++,BAYER(r,c));
+	if (n) BAYER(row,col) = tot/n;
+      }
+}
+
+int CLASS canon_s2is()
+{
+  unsigned row;
+
+  for (row=0; row < 100; row++) {
+    fseek (ifp, row*3340 + 3284, SEEK_SET);
+    if (getc(ifp) > 15) return 1;
+  }
+  return 0;
+}
+
+/*
+   getbits(-1) initializes the buffer
+   getbits(n) where 0 <= n <= 25 returns an n-bit integer
+ */
+unsigned CLASS getbithuff (int nbits, ushort *huff)
+{
+  static unsigned bitbuf=0;
+  static int vbits=0, reset=0;
+  unsigned c;
+
+  if (nbits == -1)
+    return bitbuf = vbits = reset = 0;
+  if (nbits == 0 || vbits < 0) return 0;
+  while (!reset && vbits < nbits && (c = fgetc(ifp)) != EOF &&
+    !(reset = zero_after_ff && c == 0xff && fgetc(ifp))) {
+    bitbuf = (bitbuf << 8) + (uchar) c;
+    vbits += 8;
+  }
+  c = bitbuf << (32-vbits) >> (32-nbits);
+  if (huff) {
+    vbits -= huff[c] >> 8;
+    c = (uchar) huff[c];
+  } else
+    vbits -= nbits;
+  if (vbits < 0) derror();
+  return c;
+}
+
+#define getbits(n) getbithuff(n,0)
+#define gethuff(h) getbithuff(*h,h+1)
+
+/*
+   Construct a decode tree according the specification in *source.
+   The first 16 bytes specify how many codes should be 1-bit, 2-bit
+   3-bit, etc.  Bytes after that are the leaf values.
+
+   For example, if the source is
+
+    { 0,1,4,2,3,1,2,0,0,0,0,0,0,0,0,0,
+      0x04,0x03,0x05,0x06,0x02,0x07,0x01,0x08,0x09,0x00,0x0a,0x0b,0xff  },
+
+   then the code is
+
+	00		0x04
+	010		0x03
+	011		0x05
+	100		0x06
+	101		0x02
+	1100		0x07
+	1101		0x01
+	11100		0x08
+	11101		0x09
+	11110		0x00
+	111110		0x0a
+	1111110		0x0b
+	1111111		0xff
+ */
+ushort * CLASS make_decoder_ref (const uchar **source)
+{
+  int max, len, h, i, j;
+  const uchar *count;
+  ushort *huff;
+
+  count = (*source += 16) - 17;
+  for (max=16; max && !count[max]; max--);
+  huff = (ushort *) calloc (1 + (1 << max), sizeof *huff);
+  merror (huff, "make_decoder()");
+  huff[0] = max;
+  for (h=len=1; len <= max; len++)
+    for (i=0; i < count[len]; i++, ++*source)
+      for (j=0; j < 1 << (max-len); j++)
+	if (h <= 1 << max)
+	  huff[h++] = len << 8 | **source;
+  return huff;
+}
+
+ushort * CLASS make_decoder (const uchar *source)
+{
+  return make_decoder_ref (&source);
+}
+
+void CLASS crw_init_tables (unsigned table, ushort *huff[2])
+{
+  static const uchar first_tree[3][29] = {
+    { 0,1,4,2,3,1,2,0,0,0,0,0,0,0,0,0,
+      0x04,0x03,0x05,0x06,0x02,0x07,0x01,0x08,0x09,0x00,0x0a,0x0b,0xff  },
+    { 0,2,2,3,1,1,1,1,2,0,0,0,0,0,0,0,
+      0x03,0x02,0x04,0x01,0x05,0x00,0x06,0x07,0x09,0x08,0x0a,0x0b,0xff  },
+    { 0,0,6,3,1,1,2,0,0,0,0,0,0,0,0,0,
+      0x06,0x05,0x07,0x04,0x08,0x03,0x09,0x02,0x00,0x0a,0x01,0x0b,0xff  },
+  };
+  static const uchar second_tree[3][180] = {
+    { 0,2,2,2,1,4,2,1,2,5,1,1,0,0,0,139,
+      0x03,0x04,0x02,0x05,0x01,0x06,0x07,0x08,
+      0x12,0x13,0x11,0x14,0x09,0x15,0x22,0x00,0x21,0x16,0x0a,0xf0,
+      0x23,0x17,0x24,0x31,0x32,0x18,0x19,0x33,0x25,0x41,0x34,0x42,
+      0x35,0x51,0x36,0x37,0x38,0x29,0x79,0x26,0x1a,0x39,0x56,0x57,
+      0x28,0x27,0x52,0x55,0x58,0x43,0x76,0x59,0x77,0x54,0x61,0xf9,
+      0x71,0x78,0x75,0x96,0x97,0x49,0xb7,0x53,0xd7,0x74,0xb6,0x98,
+      0x47,0x48,0x95,0x69,0x99,0x91,0xfa,0xb8,0x68,0xb5,0xb9,0xd6,
+      0xf7,0xd8,0x67,0x46,0x45,0x94,0x89,0xf8,0x81,0xd5,0xf6,0xb4,
+      0x88,0xb1,0x2a,0x44,0x72,0xd9,0x87,0x66,0xd4,0xf5,0x3a,0xa7,
+      0x73,0xa9,0xa8,0x86,0x62,0xc7,0x65,0xc8,0xc9,0xa1,0xf4,0xd1,
+      0xe9,0x5a,0x92,0x85,0xa6,0xe7,0x93,0xe8,0xc1,0xc6,0x7a,0x64,
+      0xe1,0x4a,0x6a,0xe6,0xb3,0xf1,0xd3,0xa5,0x8a,0xb2,0x9a,0xba,
+      0x84,0xa4,0x63,0xe5,0xc5,0xf3,0xd2,0xc4,0x82,0xaa,0xda,0xe4,
+      0xf2,0xca,0x83,0xa3,0xa2,0xc3,0xea,0xc2,0xe2,0xe3,0xff,0xff  },
+    { 0,2,2,1,4,1,4,1,3,3,1,0,0,0,0,140,
+      0x02,0x03,0x01,0x04,0x05,0x12,0x11,0x06,
+      0x13,0x07,0x08,0x14,0x22,0x09,0x21,0x00,0x23,0x15,0x31,0x32,
+      0x0a,0x16,0xf0,0x24,0x33,0x41,0x42,0x19,0x17,0x25,0x18,0x51,
+      0x34,0x43,0x52,0x29,0x35,0x61,0x39,0x71,0x62,0x36,0x53,0x26,
+      0x38,0x1a,0x37,0x81,0x27,0x91,0x79,0x55,0x45,0x28,0x72,0x59,
+      0xa1,0xb1,0x44,0x69,0x54,0x58,0xd1,0xfa,0x57,0xe1,0xf1,0xb9,
+      0x49,0x47,0x63,0x6a,0xf9,0x56,0x46,0xa8,0x2a,0x4a,0x78,0x99,
+      0x3a,0x75,0x74,0x86,0x65,0xc1,0x76,0xb6,0x96,0xd6,0x89,0x85,
+      0xc9,0xf5,0x95,0xb4,0xc7,0xf7,0x8a,0x97,0xb8,0x73,0xb7,0xd8,
+      0xd9,0x87,0xa7,0x7a,0x48,0x82,0x84,0xea,0xf4,0xa6,0xc5,0x5a,
+      0x94,0xa4,0xc6,0x92,0xc3,0x68,0xb5,0xc8,0xe4,0xe5,0xe6,0xe9,
+      0xa2,0xa3,0xe3,0xc2,0x66,0x67,0x93,0xaa,0xd4,0xd5,0xe7,0xf8,
+      0x88,0x9a,0xd7,0x77,0xc4,0x64,0xe2,0x98,0xa5,0xca,0xda,0xe8,
+      0xf3,0xf6,0xa9,0xb2,0xb3,0xf2,0xd2,0x83,0xba,0xd3,0xff,0xff  },
+    { 0,0,6,2,1,3,3,2,5,1,2,2,8,10,0,117,
+      0x04,0x05,0x03,0x06,0x02,0x07,0x01,0x08,
+      0x09,0x12,0x13,0x14,0x11,0x15,0x0a,0x16,0x17,0xf0,0x00,0x22,
+      0x21,0x18,0x23,0x19,0x24,0x32,0x31,0x25,0x33,0x38,0x37,0x34,
+      0x35,0x36,0x39,0x79,0x57,0x58,0x59,0x28,0x56,0x78,0x27,0x41,
+      0x29,0x77,0x26,0x42,0x76,0x99,0x1a,0x55,0x98,0x97,0xf9,0x48,
+      0x54,0x96,0x89,0x47,0xb7,0x49,0xfa,0x75,0x68,0xb6,0x67,0x69,
+      0xb9,0xb8,0xd8,0x52,0xd7,0x88,0xb5,0x74,0x51,0x46,0xd9,0xf8,
+      0x3a,0xd6,0x87,0x45,0x7a,0x95,0xd5,0xf6,0x86,0xb4,0xa9,0x94,
+      0x53,0x2a,0xa8,0x43,0xf5,0xf7,0xd4,0x66,0xa7,0x5a,0x44,0x8a,
+      0xc9,0xe8,0xc8,0xe7,0x9a,0x6a,0x73,0x4a,0x61,0xc7,0xf4,0xc6,
+      0x65,0xe9,0x72,0xe6,0x71,0x91,0x93,0xa6,0xda,0x92,0x85,0x62,
+      0xf3,0xc5,0xb2,0xa4,0x84,0xba,0x64,0xa5,0xb3,0xd2,0x81,0xe5,
+      0xd3,0xaa,0xc4,0xca,0xf2,0xb1,0xe4,0xd1,0x83,0x63,0xea,0xc3,
+      0xe2,0x82,0xf1,0xa3,0xc2,0xa1,0xc1,0xe3,0xa2,0xe1,0xff,0xff  }
+  };
+  if (table > 2) table = 2;
+  huff[0] = make_decoder ( first_tree[table]);
+  huff[1] = make_decoder (second_tree[table]);
+}
+
+/*
+   Return 0 if the image starts with compressed data,
+   1 if it starts with uncompressed low-order bits.
+
+   In Canon compressed data, 0xff is always followed by 0x00.
+ */
+int CLASS canon_has_lowbits()
+{
+  uchar test[0x4000];
+  int ret=1, i;
+
+  fseek (ifp, 0, SEEK_SET);
+  fread (test, 1, sizeof test, ifp);
+  for (i=540; i < sizeof test - 1; i++)
+    if (test[i] == 0xff) {
+      if (test[i+1]) return 1;
+      ret=0;
+    }
+  return ret;
+}
+
+void CLASS canon_compressed_load_raw()
+{
+  ushort *pixel, *prow, *huff[2];
+  int nblocks, lowbits, i, c, row, r, col, save, val, nblack=0;
+  unsigned irow, icol;
+  int block, diffbuf[64], leaf, len, diff, carry=0, pnum=0, base[2];
+  double dark[2] = { 0,0 };
+
+  crw_init_tables (tiff_compress, huff);
+  pixel = (ushort *) calloc (raw_width*8, sizeof *pixel);
+  merror (pixel, "canon_compressed_load_raw()");
+  lowbits = canon_has_lowbits();
+  if (!lowbits) maximum = 0x3ff;
+  fseek (ifp, 540 + lowbits*raw_height*raw_width/4, SEEK_SET);
+  zero_after_ff = 1;
+  getbits(-1);
+  for (row=0; row < raw_height; row+=8) {
+    nblocks = MIN (8, raw_height-row) * raw_width >> 6;
+    for (block=0; block < nblocks; block++) {
+      memset (diffbuf, 0, sizeof diffbuf);
+      for (i=0; i < 64; i++ ) {
+	leaf = gethuff(huff[i > 0]);
+	if (leaf == 0 && i) break;
+	if (leaf == 0xff) continue;
+	i  += leaf >> 4;
+	len = leaf & 15;
+	if (len == 0) continue;
+	diff = getbits(len);
+	if ((diff & (1 << (len-1))) == 0)
+	  diff -= (1 << len) - 1;
+	if (i < 64) diffbuf[i] = diff;
+      }
+      diffbuf[0] += carry;
+      carry = diffbuf[0];
+      for (i=0; i < 64; i++ ) {
+	if (pnum++ % raw_width == 0)
+	  base[0] = base[1] = 512;
+	if ((pixel[(block << 6) + i] = base[i & 1] += diffbuf[i]) >> 10)
+	  derror();
+      }
+    }
+    if (lowbits) {
+      save = ftell(ifp);
+      fseek (ifp, 26 + row*raw_width/4, SEEK_SET);
+      for (prow=pixel, i=0; i < raw_width*2; i++) {
+	c = fgetc(ifp);
+	for (r=0; r < 8; r+=2, prow++) {
+	  val = (*prow << 2) + ((c >> r) & 3);
+	  if (raw_width == 2672 && val < 512) val += 2;
+	  *prow = val;
+	}
+      }
+      fseek (ifp, save, SEEK_SET);
+    }
+    for (r=0; r < 8; r++) {
+      irow = row - top_margin + r;
+      if (irow >= height) continue;
+      for (col=0; col < raw_width; col++) {
+	icol = col - left_margin;
+	if (icol < width)
+	  BAYER(irow,icol) = pixel[r*raw_width+col];
+	else if (col > 1 && (unsigned) (col-left_margin+2) > width+3)
+	  dark[icol & 1] += (nblack++,pixel[r*raw_width+col]);
+      }
+    }
+  }
+  free (pixel);
+  FORC(2) free (huff[c]);
+  canon_black (dark, nblack);
+}
+
+/*
+   Not a full implementation of Lossless JPEG, just
+   enough to decode Canon, Kodak and Adobe DNG images.
+ */
+struct jhead {
+  int bits, high, wide, clrs, sraw, psv, restart, vpred[6];
+  ushort *huff[6], *free[4], *row;
+};
+
+int CLASS ljpeg_start (struct jhead *jh, int info_only)
+{
+  int c, tag, len;
+  uchar data[0x10000];
+  const uchar *dp;
+
+  memset (jh, 0, sizeof *jh);
+  jh->restart = INT_MAX;
+  fread (data, 2, 1, ifp);
+  if (data[1] != 0xd8) return 0;
+  do {
+    fread (data, 2, 2, ifp);
+    tag =  data[0] << 8 | data[1];
+    len = (data[2] << 8 | data[3]) - 2;
+    if (tag <= 0xff00) return 0;
+    fread (data, 1, len, ifp);
+    switch (tag) {
+      case 0xffc3:
+	jh->sraw = ((data[7] >> 4) * (data[7] & 15) - 1) & 3;
+      case 0xffc0:
+	jh->bits = data[0];
+	jh->high = data[1] << 8 | data[2];
+	jh->wide = data[3] << 8 | data[4];
+	jh->clrs = data[5] + jh->sraw;
+	if (len == 9 && !dng_version) getc(ifp);
+	break;
+      case 0xffc4:
+	if (info_only) break;
+	for (dp = data; dp < data+len && (c = *dp++) < 4; )
+	  jh->free[c] = jh->huff[c] = make_decoder_ref (&dp);
+	break;
+      case 0xffda:
+	jh->psv = data[1+data[0]*2];
+	jh->bits -= data[3+data[0]*2] & 15;
+	break;
+      case 0xffdd:
+	jh->restart = data[0] << 8 | data[1];
+    }
+  } while (tag != 0xffda);
+  if (info_only) return 1;
+  FORC(5) if (!jh->huff[c+1]) jh->huff[c+1] = jh->huff[c];
+  if (jh->sraw) {
+    FORC(4)        jh->huff[2+c] = jh->huff[1];
+    FORC(jh->sraw) jh->huff[1+c] = jh->huff[0];
+  }
+  jh->row = (ushort *) calloc (jh->wide*jh->clrs, 4);
+  merror (jh->row, "ljpeg_start()");
+  return zero_after_ff = 1;
+}
+
+void CLASS ljpeg_end (struct jhead *jh)
+{
+  int c;
+  FORC4 if (jh->free[c]) free (jh->free[c]);
+  free (jh->row);
+}
+
+int CLASS ljpeg_diff (ushort *huff)
+{
+  int len, diff;
+
+  len = gethuff(huff);
+  if (len == 16 && (!dng_version || dng_version >= 0x1010000))
+    return -32768;
+  diff = getbits(len);
+  if ((diff & (1 << (len-1))) == 0)
+    diff -= (1 << len) - 1;
+  return diff;
+}
+
+ushort * CLASS ljpeg_row (int jrow, struct jhead *jh)
+{
+  int col, c, diff, pred, spred=0;
+  ushort mark=0, *row[3];
+
+  if (jrow * jh->wide % jh->restart == 0) {
+    FORC(6) jh->vpred[c] = 1 << (jh->bits-1);
+    if (jrow) {
+      fseek (ifp, -2, SEEK_CUR);
+      do mark = (mark << 8) + (c = fgetc(ifp));
+      while (c != EOF && mark >> 4 != 0xffd);
+    }
+    getbits(-1);
+  }
+  FORC3 row[c] = jh->row + jh->wide*jh->clrs*((jrow+c) & 1);
+  for (col=0; col < jh->wide; col++)
+    FORC(jh->clrs) {
+      diff = ljpeg_diff (jh->huff[c]);
+      if (jh->sraw && c <= jh->sraw && (col | c))
+		    pred = spred;
+      else if (col) pred = row[0][-jh->clrs];
+      else	    pred = (jh->vpred[c] += diff) - diff;
+      if (jrow && col) switch (jh->psv) {
+	case 1:	break;
+	case 2: pred = row[1][0];					break;
+	case 3: pred = row[1][-jh->clrs];				break;
+	case 4: pred = pred +   row[1][0] - row[1][-jh->clrs];		break;
+	case 5: pred = pred + ((row[1][0] - row[1][-jh->clrs]) >> 1);	break;
+	case 6: pred = row[1][0] + ((pred - row[1][-jh->clrs]) >> 1);	break;
+	case 7: pred = (pred + row[1][0]) >> 1;				break;
+	default: pred = 0;
+      }
+      if ((**row = pred + diff) >> jh->bits) derror();
+      if (c <= jh->sraw) spred = **row;
+      row[0]++; row[1]++;
+    }
+  return row[2];
+}
+
+void CLASS lossless_jpeg_load_raw()
+{
+  int jwide, jrow, jcol, val, jidx, i, j, row=0, col=0, nblack=0;
+  double dark[2] = { 0,0 };
+  struct jhead jh;
+  int min=INT_MAX;
+  ushort *rp;
+
+  if (!ljpeg_start (&jh, 0)) return;
+  jwide = jh.wide * jh.clrs;
+
+  for (jrow=0; jrow < jh.high; jrow++) {
+    rp = ljpeg_row (jrow, &jh);
+    for (jcol=0; jcol < jwide; jcol++) {
+      val = *rp++;
+      if (jh.bits <= 12)
+	val = curve[val & 0xfff];
+      if (cr2_slice[0]) {
+	jidx = jrow*jwide + jcol;
+	i = jidx / (cr2_slice[1]*jh.high);
+	if ((j = i >= cr2_slice[0]))
+		 i  = cr2_slice[0];
+	jidx -= i * (cr2_slice[1]*jh.high);
+	row = jidx / cr2_slice[1+j];
+	col = jidx % cr2_slice[1+j] + i*cr2_slice[1];
+      }
+      if (raw_width == 3984 && (col -= 2) < 0)
+	col += (row--,raw_width);
+      if ((unsigned) (row-top_margin) < height) {
+	if ((unsigned) (col-left_margin) < width) {
+	  BAYER(row-top_margin,col-left_margin) = val;
+	  if (min > val) min = val;
+	} else if (col > 1 && (unsigned) (col-left_margin+2) > width+3)
+	  dark[(col-left_margin) & 1] += (nblack++,val);
+      }
+      if (++col >= raw_width)
+	col = (row++,0);
+    }
+  }
+  ljpeg_end (&jh);
+  canon_black (dark, nblack);
+  if (!strcasecmp(make,"KODAK"))
+    black = min;
+}
+
+void CLASS canon_sraw_load_raw()
+{
+  struct jhead jh;
+  short *rp=0, (*ip)[4];
+  int jwide, slice, scol, ecol, row, col, jrow=0, jcol=0, pix[3], c;
+  int v[3]={0,0,0}, ver, hue;
+  char *cp;
+
+  if (!ljpeg_start (&jh, 0)) return;
+  jwide = (jh.wide >>= 1) * jh.clrs;
+
+  for (ecol=slice=0; slice <= cr2_slice[0]; slice++) {
+    scol = ecol;
+    ecol += cr2_slice[1] * 2 / jh.clrs;
+    if (!cr2_slice[0] || ecol > raw_width-1) ecol = raw_width & -2;
+    for (row=0; row < height; row += (jh.clrs >> 1) - 1) {
+      ip = (short (*)[4]) image + row*width;
+      for (col=scol; col < ecol; col+=2, jcol+=jh.clrs) {
+	if ((jcol %= jwide) == 0)
+	  rp = (short *) ljpeg_row (jrow++, &jh);
+	if (col >= width) continue;
+	FORC (jh.clrs-2)
+	  ip[col + (c >> 1)*width + (c & 1)][0] = rp[jcol+c];
+	ip[col][1] = rp[jcol+jh.clrs-2] - 16384;
+	ip[col][2] = rp[jcol+jh.clrs-1] - 16384;
+      }
+    }
+  }
+  for (cp=model2; *cp && !isdigit(*cp); cp++);
+  sscanf (cp, "%d.%d.%d", v, v+1, v+2);
+  ver = (v[0]*1000 + v[1])*1000 + v[2];
+  hue = (jh.sraw+1) << 2;
+  if (unique_id == 0x80000218 && ver > 1000006 && ver < 3000000)
+    hue = jh.sraw << 1;
+  ip = (short (*)[4]) image;
+  rp = ip[0];
+  for (row=0; row < height; row++, ip+=width) {
+    if (row & (jh.sraw >> 1))
+      for (col=0; col < width; col+=2)
+	for (c=1; c < 3; c++)
+	  if (row == height-1)
+	       ip[col][c] =  ip[col-width][c];
+	  else ip[col][c] = (ip[col-width][c] + ip[col+width][c] + 1) >> 1;
+    for (col=1; col < width; col+=2)
+      for (c=1; c < 3; c++)
+	if (col == width-1)
+	     ip[col][c] =  ip[col-1][c];
+	else ip[col][c] = (ip[col-1][c] + ip[col+1][c] + 1) >> 1;
+  }
+  for ( ; rp < ip[0]; rp+=4) {
+    if (unique_id < 0x80000218) {
+      pix[0] = rp[0] + rp[2] - 512;
+      pix[2] = rp[0] + rp[1] - 512;
+      pix[1] = rp[0] + ((-778*rp[1] - (rp[2] << 11)) >> 12) - 512;
+    } else {
+      rp[1] = (rp[1] << 2) + hue;
+      rp[2] = (rp[2] << 2) + hue;
+      pix[0] = rp[0] + ((  200*rp[1] + 22929*rp[2]) >> 14);
+      pix[1] = rp[0] + ((-5640*rp[1] - 11751*rp[2]) >> 14);
+      pix[2] = rp[0] + ((29040*rp[1] -   101*rp[2]) >> 14);
+    }
+    FORC3 rp[c] = CLIP(pix[c] * sraw_mul[c] >> 10);
+  }
+  ljpeg_end (&jh);
+  maximum = 0x3fff;
+}
+
+void CLASS adobe_copy_pixel (int row, int col, ushort **rp)
+{
+  unsigned r, c;
+
+  r = row -= top_margin;
+  c = col -= left_margin;
+  if (is_raw == 2 && shot_select) (*rp)++;
+  if (filters) {
+    if (fuji_width) {
+      r = row + fuji_width - 1 - (col >> 1);
+      c = row + ((col+1) >> 1);
+    }
+    if (r < height && c < width)
+      BAYER(r,c) = **rp < 0x1000 ? curve[**rp] : **rp;
+    *rp += is_raw;
+  } else {
+    if (r < height && c < width)
+      FORC(tiff_samples)
+	image[row*width+col][c] = (*rp)[c] < 0x1000 ? curve[(*rp)[c]]:(*rp)[c];
+    *rp += tiff_samples;
+  }
+  if (is_raw == 2 && shot_select) (*rp)--;
+}
+
+void CLASS adobe_dng_load_raw_lj()
+{
+  unsigned save, trow=0, tcol=0, jwide, jrow, jcol, row, col;
+  struct jhead jh;
+  ushort *rp;
+
+  while (trow < raw_height) {
+    save = ftell(ifp);
+    if (tile_length < INT_MAX)
+      fseek (ifp, get4(), SEEK_SET);
+    if (!ljpeg_start (&jh, 0)) break;
+    jwide = jh.wide;
+    if (filters) jwide *= jh.clrs;
+    jwide /= is_raw;
+    for (row=col=jrow=0; jrow < jh.high; jrow++) {
+      rp = ljpeg_row (jrow, &jh);
+      for (jcol=0; jcol < jwide; jcol++) {
+	adobe_copy_pixel (trow+row, tcol+col, &rp);
+	if (++col >= tile_width || col >= raw_width)
+	  row += 1 + (col = 0);
+      }
+    }
+    fseek (ifp, save+4, SEEK_SET);
+    if ((tcol += tile_width) >= raw_width)
+      trow += tile_length + (tcol = 0);
+    ljpeg_end (&jh);
+  }
+}
+
+void CLASS adobe_dng_load_raw_nc()
+{
+  ushort *pixel, *rp;
+  int row, col;
+
+  pixel = (ushort *) calloc (raw_width * tiff_samples, sizeof *pixel);
+  merror (pixel, "adobe_dng_load_raw_nc()");
+  for (row=0; row < raw_height; row++) {
+    if (tiff_bps == 16)
+      read_shorts (pixel, raw_width * tiff_samples);
+    else {
+      getbits(-1);
+      for (col=0; col < raw_width * tiff_samples; col++)
+	pixel[col] = getbits(tiff_bps);
+    }
+    for (rp=pixel, col=0; col < raw_width; col++)
+      adobe_copy_pixel (row, col, &rp);
+  }
+  free (pixel);
+}
+
+void CLASS pentax_load_raw()
+{
+  ushort bit[2][13], huff[4097];
+  int row, col, diff, c, i;
+  ushort vpred[2][2] = {{0,0},{0,0}}, hpred[2];
+
+  fseek (ifp, meta_offset, SEEK_SET);
+  FORC(13) bit[0][c] = get2();
+  FORC(13) bit[1][c] = fgetc(ifp);
+  FORC(13)
+    for (i=bit[0][c]; i <= ((bit[0][c]+(4096 >> bit[1][c])-1) & 4095); )
+      huff[++i] = bit[1][c] << 8 | c;
+  huff[0] = 12;
+  fseek (ifp, data_offset, SEEK_SET);
+  getbits(-1);
+  for (row=0; row < raw_height; row++)
+    for (col=0; col < raw_width; col++) {
+      diff = ljpeg_diff (huff);
+      if (col < 2) hpred[col] = vpred[row & 1][col] += diff;
+      else	   hpred[col & 1] += diff;
+      if ((unsigned) (row-top_margin) < height && col < width)
+	BAYER(row-top_margin,col) = hpred[col & 1];
+      if (hpred[col & 1] >> 12) derror();
+    }
+}
+
+void CLASS nikon_compressed_load_raw()
+{
+  static const uchar nikon_tree[][32] = {
+    { 0,1,5,1,1,1,1,1,1,2,0,0,0,0,0,0,	/* 12-bit lossy */
+      5,4,3,6,2,7,1,0,8,9,11,10,12 },
+    { 0,1,5,1,1,1,1,1,1,2,0,0,0,0,0,0,	/* 12-bit lossy after split */
+      0x39,0x5a,0x38,0x27,0x16,5,4,3,2,1,0,11,12,12 },
+    { 0,1,4,2,3,1,2,0,0,0,0,0,0,0,0,0,  /* 12-bit lossless */
+      5,4,6,3,7,2,8,1,9,0,10,11,12 },
+    { 0,1,4,3,1,1,1,1,1,2,0,0,0,0,0,0,	/* 14-bit lossy */
+      5,6,4,7,8,3,9,2,1,0,10,11,12,13,14 },
+    { 0,1,5,1,1,1,1,1,1,1,2,0,0,0,0,0,	/* 14-bit lossy after split */
+      8,0x5c,0x4b,0x3a,0x29,7,6,5,4,3,2,1,0,13,14 },
+    { 0,1,4,2,2,3,1,2,0,0,0,0,0,0,0,0,	/* 14-bit lossless */
+      7,6,8,5,9,4,10,3,11,12,2,0,1,13,14 } };
+  ushort *huff, ver0, ver1, vpred[2][2], hpred[2], csize;
+  int i, min, max, step=0, tree=0, split=0, row, col, len, shl, diff;
+
+  fseek (ifp, meta_offset, SEEK_SET);
+  ver0 = fgetc(ifp);
+  ver1 = fgetc(ifp);
+  if (ver0 == 0x49 || ver1 == 0x58)
+    fseek (ifp, 2110, SEEK_CUR);
+  if (ver0 == 0x46) tree = 2;
+  if (tiff_bps == 14) tree += 3;
+  read_shorts (vpred[0], 4);
+  max = 1 << tiff_bps & 0x7fff;
+  if ((csize = get2()) > 1)
+    step = max / (csize-1);
+  if (ver0 == 0x44 && ver1 == 0x20 && step > 0) {
+    for (i=0; i < csize; i++)
+      curve[i*step] = get2();
+    for (i=0; i < max; i++)
+      curve[i] = ( curve[i-i%step]*(step-i%step) +
+		   curve[i-i%step+step]*(i%step) ) / step;
+    fseek (ifp, meta_offset+562, SEEK_SET);
+    split = get2();
+  } else if (ver0 != 0x46 && csize <= 0x4001)
+    read_shorts (curve, max=csize);
+  while (curve[max-2] == curve[max-1]) max--;
+  huff = make_decoder (nikon_tree[tree]);
+  fseek (ifp, data_offset, SEEK_SET);
+  getbits(-1);
+  for (min=row=0; row < height; row++) {
+    if (split && row == split) {
+      free (huff);
+      huff = make_decoder (nikon_tree[tree+1]);
+      max += (min = 16) << 1;
+    }
+    for (col=0; col < raw_width; col++) {
+      i = gethuff(huff);
+      len = i & 15;
+      shl = i >> 4;
+      diff = ((getbits(len-shl) << 1) + 1) << shl >> 1;
+      if ((diff & (1 << (len-1))) == 0)
+	diff -= (1 << len) - !shl;
+      if (col < 2) hpred[col] = vpred[row & 1][col] += diff;
+      else	   hpred[col & 1] += diff;
+      if ((ushort)(hpred[col & 1] + min) >= max) derror();
+      if ((unsigned) (col-left_margin) < width)
+	BAYER(row,col-left_margin) = curve[LIM((short)hpred[col & 1],0,0x3fff)];
+    }
+  }
+  free (huff);
+}
+
+/*
+   Figure out if a NEF file is compressed.  These fancy heuristics
+   are only needed for the D100, thanks to a bug in some cameras
+   that tags all images as "compressed".
+ */
+int CLASS nikon_is_compressed()
+{
+  uchar test[256];
+  int i;
+
+  fseek (ifp, data_offset, SEEK_SET);
+  fread (test, 1, 256, ifp);
+  for (i=15; i < 256; i+=16)
+    if (test[i]) return 1;
+  return 0;
+}
+
+/*
+   Returns 1 for a Coolpix 995, 0 for anything else.
+ */
+int CLASS nikon_e995()
+{
+  int i, histo[256];
+  const uchar often[] = { 0x00, 0x55, 0xaa, 0xff };
+
+  memset (histo, 0, sizeof histo);
+  fseek (ifp, -2000, SEEK_END);
+  for (i=0; i < 2000; i++)
+    histo[fgetc(ifp)]++;
+  for (i=0; i < 4; i++)
+    if (histo[often[i]] < 200)
+      return 0;
+  return 1;
+}
+
+/*
+   Returns 1 for a Coolpix 2100, 0 for anything else.
+ */
+int CLASS nikon_e2100()
+{
+  uchar t[12];
+  int i;
+
+  fseek (ifp, 0, SEEK_SET);
+  for (i=0; i < 1024; i++) {
+    fread (t, 1, 12, ifp);
+    if (((t[2] & t[4] & t[7] & t[9]) >> 4
+	& t[1] & t[6] & t[8] & t[11] & 3) != 3)
+      return 0;
+  }
+  return 1;
+}
+
+void CLASS nikon_3700()
+{
+  int bits, i;
+  uchar dp[24];
+  static const struct {
+    int bits;
+    char make[12], model[15];
+  } table[] = {
+    { 0x00, "PENTAX",  "Optio 33WR" },
+    { 0x03, "NIKON",   "E3200" },
+    { 0x32, "NIKON",   "E3700" },
+    { 0x33, "OLYMPUS", "C740UZ" } };
+
+  fseek (ifp, 3072, SEEK_SET);
+  fread (dp, 1, 24, ifp);
+  bits = (dp[8] & 3) << 4 | (dp[20] & 3);
+  for (i=0; i < sizeof table / sizeof *table; i++)
+    if (bits == table[i].bits) {
+      strcpy (make,  table[i].make );
+      strcpy (model, table[i].model);
+    }
+}
+
+/*
+   Separates a Minolta DiMAGE Z2 from a Nikon E4300.
+ */
+int CLASS minolta_z2()
+{
+  int i, nz;
+  char tail[424];
+
+  fseek (ifp, -sizeof tail, SEEK_END);
+  fread (tail, 1, sizeof tail, ifp);
+  for (nz=i=0; i < sizeof tail; i++)
+    if (tail[i]) nz++;
+  return nz > 20;
+}
+
+/*
+   The Fuji Super CCD is just a Bayer grid rotated 45 degrees.
+ */
+void CLASS fuji_load_raw()
+{
+  ushort *pixel;
+  int wide, row, col, r, c;
+
+  fseek (ifp, (top_margin*raw_width + left_margin) * 2, SEEK_CUR);
+  wide = fuji_width << !fuji_layout;
+  pixel = (ushort *) calloc (wide, sizeof *pixel);
+  merror (pixel, "fuji_load_raw()");
+  for (row=0; row < raw_height; row++) {
+    read_shorts (pixel, wide);
+    fseek (ifp, 2*(raw_width - wide), SEEK_CUR);
+    for (col=0; col < wide; col++) {
+      if (fuji_layout) {
+	r = fuji_width - 1 - col + (row >> 1);
+	c = col + ((row+1) >> 1);
+      } else {
+	r = fuji_width - 1 + row - (col >> 1);
+	c = row + ((col+1) >> 1);
+      }
+      BAYER(r,c) = pixel[col];
+    }
+  }
+  free (pixel);
+}
+
+void CLASS jpeg_thumb();
+
+void CLASS ppm_thumb()
+{
+  char *thumb;
+  thumb_length = thumb_width*thumb_height*3;
+  thumb = (char *) malloc (thumb_length);
+  merror (thumb, "ppm_thumb()");
+  fprintf (ofp, "P6\n%d %d\n255\n", thumb_width, thumb_height);
+  fread  (thumb, 1, thumb_length, ifp);
+  fwrite (thumb, 1, thumb_length, ofp);
+  free (thumb);
+}
+
+void CLASS layer_thumb()
+{
+  int i, c;
+  char *thumb, map[][4] = { "012","102" };
+
+  colors = thumb_misc >> 5 & 7;
+  thumb_length = thumb_width*thumb_height;
+  thumb = (char *) calloc (colors, thumb_length);
+  merror (thumb, "layer_thumb()");
+  fprintf (ofp, "P%d\n%d %d\n255\n",
+	5 + (colors >> 1), thumb_width, thumb_height);
+  fread (thumb, thumb_length, colors, ifp);
+  for (i=0; i < thumb_length; i++)
+    FORCC putc (thumb[i+thumb_length*(map[thumb_misc >> 8][c]-'0')], ofp);
+  free (thumb);
+}
+
+void CLASS rollei_thumb()
+{
+  unsigned i;
+  ushort *thumb;
+
+  thumb_length = thumb_width * thumb_height;
+  thumb = (ushort *) calloc (thumb_length, 2);
+  merror (thumb, "rollei_thumb()");
+  fprintf (ofp, "P6\n%d %d\n255\n", thumb_width, thumb_height);
+  read_shorts (thumb, thumb_length);
+  for (i=0; i < thumb_length; i++) {
+    putc (thumb[i] << 3, ofp);
+    putc (thumb[i] >> 5  << 2, ofp);
+    putc (thumb[i] >> 11 << 3, ofp);
+  }
+  free (thumb);
+}
+
+void CLASS rollei_load_raw()
+{
+  uchar pixel[10];
+  unsigned iten=0, isix, i, buffer=0, row, col, todo[16];
+
+  isix = raw_width * raw_height * 5 / 8;
+  while (fread (pixel, 1, 10, ifp) == 10) {
+    for (i=0; i < 10; i+=2) {
+      todo[i]   = iten++;
+      todo[i+1] = pixel[i] << 8 | pixel[i+1];
+      buffer    = pixel[i] >> 2 | buffer << 6;
+    }
+    for (   ; i < 16; i+=2) {
+      todo[i]   = isix++;
+      todo[i+1] = buffer >> (14-i)*5;
+    }
+    for (i=0; i < 16; i+=2) {
+      row = todo[i] / raw_width - top_margin;
+      col = todo[i] % raw_width - left_margin;
+      if (row < height && col < width)
+	BAYER(row,col) = (todo[i+1] & 0x3ff);
+    }
+  }
+  maximum = 0x3ff;
+}
+
+int CLASS bayer (unsigned row, unsigned col)
+{
+  return (row < height && col < width) ? BAYER(row,col) : 0;
+}
+
+void CLASS phase_one_flat_field (int is_float, int nc)
+{
+  ushort head[8];
+  unsigned wide, y, x, c, rend, cend, row, col;
+  float *mrow, num, mult[4];
+
+  read_shorts (head, 8);
+  wide = head[2] / head[4];
+  mrow = (float *) calloc (nc*wide, sizeof *mrow);
+  merror (mrow, "phase_one_flat_field()");
+  for (y=0; y < head[3] / head[5]; y++) {
+    for (x=0; x < wide; x++)
+      for (c=0; c < nc; c+=2) {
+	num = is_float ? getreal(11) : get2()/32768.0;
+	if (y==0) mrow[c*wide+x] = num;
+	else mrow[(c+1)*wide+x] = (num - mrow[c*wide+x]) / head[5];
+      }
+    if (y==0) continue;
+    rend = head[1]-top_margin + y*head[5];
+    for (row = rend-head[5]; row < height && row < rend; row++) {
+      for (x=1; x < wide; x++) {
+	for (c=0; c < nc; c+=2) {
+	  mult[c] = mrow[c*wide+x-1];
+	  mult[c+1] = (mrow[c*wide+x] - mult[c]) / head[4];
+	}
+	cend = head[0]-left_margin + x*head[4];
+	for (col = cend-head[4]; col < width && col < cend; col++) {
+	  c = nc > 2 ? FC(row,col) : 0;
+	  if (!(c & 1)) {
+	    c = BAYER(row,col) * mult[c];
+	    BAYER(row,col) = LIM(c,0,65535);
+	  }
+	  for (c=0; c < nc; c+=2)
+	    mult[c] += mult[c+1];
+	}
+      }
+      for (x=0; x < wide; x++)
+	for (c=0; c < nc; c+=2)
+	  mrow[c*wide+x] += mrow[(c+1)*wide+x];
+    }
+  }
+  free (mrow);
+}
+
+void CLASS phase_one_correct()
+{
+  unsigned entries, tag, data, save, col, row, type;
+  int len, i, j, k, cip, val[4], dev[4], sum, max;
+  int head[9], diff, mindiff=INT_MAX, off_412=0;
+  static const signed char dir[12][2] =
+    { {-1,-1}, {-1,1}, {1,-1}, {1,1}, {-2,0}, {0,-2}, {0,2}, {2,0},
+      {-2,-2}, {-2,2}, {2,-2}, {2,2} };
+  float poly[8], num, cfrac, frac, mult[2], *yval[2];
+  ushort *xval[2];
+
+  if (half_size || !meta_length) return;
+  if (verbose) fprintf (stderr,_("Phase One correction...\n"));
+  fseek (ifp, meta_offset, SEEK_SET);
+  order = get2();
+  fseek (ifp, 6, SEEK_CUR);
+  fseek (ifp, meta_offset+get4(), SEEK_SET);
+  entries = get4();  get4();
+  while (entries--) {
+    tag  = get4();
+    len  = get4();
+    data = get4();
+    save = ftell(ifp);
+    fseek (ifp, meta_offset+data, SEEK_SET);
+    if (tag == 0x419) {				/* Polynomial curve */
+      for (get4(), i=0; i < 8; i++)
+	poly[i] = getreal(11);
+      poly[3] += (ph1.tag_210 - poly[7]) * poly[6] + 1;
+      for (i=0; i < 0x10000; i++) {
+	num = (poly[5]*i + poly[3])*i + poly[1];
+	curve[i] = LIM(num,0,65535);
+      } goto apply;				/* apply to right half */
+    } else if (tag == 0x41a) {			/* Polynomial curve */
+      for (i=0; i < 4; i++)
+	poly[i] = getreal(11);
+      for (i=0; i < 0x10000; i++) {
+	for (num=0, j=4; j--; )
+	  num = num * i + poly[j];
+	curve[i] = LIM(num+i,0,65535);
+      } apply:					/* apply to whole image */
+      for (row=0; row < height; row++)
+	for (col = (tag & 1)*ph1.split_col; col < width; col++)
+	  BAYER(row,col) = curve[BAYER(row,col)];
+    } else if (tag == 0x400) {			/* Sensor defects */
+      while ((len -= 8) >= 0) {
+	col  = get2() - left_margin;
+	row  = get2() - top_margin;
+	type = get2(); get2();
+	if (col >= width) continue;
+	if (type == 131)			/* Bad column */
+	  for (row=0; row < height; row++)
+	    if (FC(row,col) == 1) {
+	      for (sum=i=0; i < 4; i++)
+		sum += val[i] = bayer (row+dir[i][0], col+dir[i][1]);
+	      for (max=i=0; i < 4; i++) {
+		dev[i] = abs((val[i] << 2) - sum);
+		if (dev[max] < dev[i]) max = i;
+	      }
+	      BAYER(row,col) = (sum - val[max])/3.0 + 0.5;
+	    } else {
+	      for (sum=0, i=8; i < 12; i++)
+		sum += bayer (row+dir[i][0], col+dir[i][1]);
+	      BAYER(row,col) = 0.5 + sum * 0.0732233 +
+		(bayer(row,col-2) + bayer(row,col+2)) * 0.3535534;
+	    }
+	else if (type == 129) {			/* Bad pixel */
+	  if (row >= height) continue;
+	  j = (FC(row,col) != 1) * 4;
+	  for (sum=0, i=j; i < j+8; i++)
+	    sum += bayer (row+dir[i][0], col+dir[i][1]);
+	  BAYER(row,col) = (sum + 4) >> 3;
+	}
+      }
+    } else if (tag == 0x401) {			/* All-color flat fields */
+      phase_one_flat_field (1, 2);
+    } else if (tag == 0x416 || tag == 0x410) {
+      phase_one_flat_field (0, 2);
+    } else if (tag == 0x40b) {			/* Red+blue flat field */
+      phase_one_flat_field (0, 4);
+    } else if (tag == 0x412) {
+      fseek (ifp, 36, SEEK_CUR);
+      diff = abs (get2() - ph1.tag_21a);
+      if (mindiff > diff) {
+	mindiff = diff;
+	off_412 = ftell(ifp) - 38;
+      }
+    }
+    fseek (ifp, save, SEEK_SET);
+  }
+  if (off_412) {
+    fseek (ifp, off_412, SEEK_SET);
+    for (i=0; i < 9; i++) head[i] = get4() & 0x7fff;
+    yval[0] = (float *) calloc (head[1]*head[3] + head[2]*head[4], 6);
+    merror (yval[0], "phase_one_correct()");
+    yval[1] = (float  *) (yval[0] + head[1]*head[3]);
+    xval[0] = (ushort *) (yval[1] + head[2]*head[4]);
+    xval[1] = (ushort *) (xval[0] + head[1]*head[3]);
+    get2();
+    for (i=0; i < 2; i++)
+      for (j=0; j < head[i+1]*head[i+3]; j++)
+	yval[i][j] = getreal(11);
+    for (i=0; i < 2; i++)
+      for (j=0; j < head[i+1]*head[i+3]; j++)
+	xval[i][j] = get2();
+    for (row=0; row < height; row++)
+      for (col=0; col < width; col++) {
+	cfrac = (float) col * head[3] / raw_width;
+	cfrac -= cip = cfrac;
+	num = BAYER(row,col) * 0.5;
+	for (i=cip; i < cip+2; i++) {
+	  for (k=j=0; j < head[1]; j++)
+	    if (num < xval[0][k = head[1]*i+j]) break;
+	  frac = (j == 0 || j == head[1]) ? 0 :
+		(xval[0][k] - num) / (xval[0][k] - xval[0][k-1]);
+	  mult[i-cip] = yval[0][k-1] * frac + yval[0][k] * (1-frac);
+	}
+	i = ((mult[0] * (1-cfrac) + mult[1] * cfrac)
+		* (row + top_margin) + num) * 2;
+	BAYER(row,col) = LIM(i,0,65535);
+      }
+    free (yval[0]);
+  }
+}
+
+void CLASS phase_one_load_raw()
+{
+  int row, col, a, b;
+  ushort *pixel, akey, bkey, mask;
+
+  fseek (ifp, ph1.key_off, SEEK_SET);
+  akey = get2();
+  bkey = get2();
+  mask = ph1.format == 1 ? 0x5555:0x1354;
+  fseek (ifp, data_offset + top_margin*raw_width*2, SEEK_SET);
+  pixel = (ushort *) calloc (raw_width, sizeof *pixel);
+  merror (pixel, "phase_one_load_raw()");
+  for (row=0; row < height; row++) {
+    read_shorts (pixel, raw_width);
+    for (col=0; col < raw_width; col+=2) {
+      a = pixel[col+0] ^ akey;
+      b = pixel[col+1] ^ bkey;
+      pixel[col+0] = (a & mask) | (b & ~mask);
+      pixel[col+1] = (b & mask) | (a & ~mask);
+    }
+    for (col=0; col < width; col++)
+      BAYER(row,col) = pixel[col+left_margin];
+  }
+  free (pixel);
+  phase_one_correct();
+}
+
+unsigned CLASS ph1_bithuff (int nbits, ushort *huff)
+{
+  static UINT64 bitbuf=0;
+  static int vbits=0;
+  unsigned c;
+
+  if (nbits == -1)
+    return bitbuf = vbits = 0;
+  if (nbits == 0) return 0;
+  if (vbits < nbits) {
+    bitbuf = bitbuf << 32 | get4();
+    vbits += 32;
+  }
+  c = bitbuf << (64-vbits) >> (64-nbits);
+  if (huff) {
+    vbits -= huff[c] >> 8;
+    return (uchar) huff[c];
+  }
+  vbits -= nbits;
+  return c;
+}
+#define ph1_bits(n) ph1_bithuff(n,0)
+#define ph1_huff(h) ph1_bithuff(*h,h+1)
+
+void CLASS phase_one_load_raw_c()
+{
+  static const int length[] = { 8,7,6,9,11,10,5,12,14,13 };
+  int *offset, len[2], pred[2], row, col, i, j;
+  ushort *pixel;
+  short (*black)[2];
+
+  pixel = (ushort *) calloc (raw_width + raw_height*4, 2);
+  merror (pixel, "phase_one_load_raw_c()");
+  offset = (int *) (pixel + raw_width);
+  fseek (ifp, strip_offset, SEEK_SET);
+  for (row=0; row < raw_height; row++)
+    offset[row] = get4();
+  black = (short (*)[2]) offset + raw_height;
+  fseek (ifp, ph1.black_off, SEEK_SET);
+  if (ph1.black_off)
+    read_shorts ((ushort *) black[0], raw_height*2);
+  for (i=0; i < 256; i++)
+    curve[i] = i*i / 3.969 + 0.5;
+  for (row=0; row < raw_height; row++) {
+    fseek (ifp, data_offset + offset[row], SEEK_SET);
+    ph1_bits(-1);
+    pred[0] = pred[1] = 0;
+    for (col=0; col < raw_width; col++) {
+      if (col >= (raw_width & -8))
+	len[0] = len[1] = 14;
+      else if ((col & 7) == 0)
+	for (i=0; i < 2; i++) {
+	  for (j=0; j < 5 && !ph1_bits(1); j++);
+	  if (j--) len[i] = length[j*2 + ph1_bits(1)];
+	}
+      if ((i = len[col & 1]) == 14)
+	pixel[col] = pred[col & 1] = ph1_bits(16);
+      else
+	pixel[col] = pred[col & 1] += ph1_bits(i) + 1 - (1 << (i - 1));
+      if (pred[col & 1] >> 16) derror();
+      if (ph1.format == 5 && pixel[col] < 256)
+	pixel[col] = curve[pixel[col]];
+    }
+    if ((unsigned) (row-top_margin) < height)
+      for (col=0; col < width; col++) {
+	i = (pixel[col+left_margin] << 2)
+		- ph1.black + black[row][col >= ph1.split_col];
+	if (i > 0) BAYER(row-top_margin,col) = i;
+      }
+  }
+  free (pixel);
+  phase_one_correct();
+  maximum = 0xfffc - ph1.black;
+}
+
+void CLASS hasselblad_load_raw()
+{
+  struct jhead jh;
+  int row, col, pred[2], len[2], diff, c;
+
+  if (!ljpeg_start (&jh, 0)) return;
+  order = 0x4949;
+  ph1_bits(-1);
+  for (row=-top_margin; row < height; row++) {
+    pred[0] = pred[1] = 0x8000;
+    for (col=-left_margin; col < raw_width-left_margin; col+=2) {
+      FORC(2) len[c] = ph1_huff(jh.huff[0]);
+      FORC(2) {
+	diff = ph1_bits(len[c]);
+	if ((diff & (1 << (len[c]-1))) == 0)
+	  diff -= (1 << len[c]) - 1;
+	if (diff == 65535) diff = -32768;
+	pred[c] += diff;
+	if (row >= 0 && (unsigned)(col+c) < width)
+	  BAYER(row,col+c) = pred[c];
+      }
+    }
+  }
+  ljpeg_end (&jh);
+  maximum = 0xffff;
+}
+
+void CLASS leaf_hdr_load_raw()
+{
+  ushort *pixel;
+  unsigned tile=0, r, c, row, col;
+
+  pixel = (ushort *) calloc (raw_width, sizeof *pixel);
+  merror (pixel, "leaf_hdr_load_raw()");
+  FORC(tiff_samples)
+    for (r=0; r < raw_height; r++) {
+      if (r % tile_length == 0) {
+	fseek (ifp, data_offset + 4*tile++, SEEK_SET);
+	fseek (ifp, get4() + 2*left_margin, SEEK_SET);
+      }
+      if (filters && c != shot_select) continue;
+      read_shorts (pixel, raw_width);
+      if ((row = r - top_margin) >= height) continue;
+      for (col=0; col < width; col++)
+	if (filters)  BAYER(row,col) = pixel[col];
+	else image[row*width+col][c] = pixel[col];
+    }
+  free (pixel);
+  if (!filters) {
+    maximum = 0xffff;
+    raw_color = 1;
+  }
+}
+
+void CLASS unpacked_load_raw();
+
+void CLASS sinar_4shot_load_raw()
+{
+  ushort *pixel;
+  unsigned shot, row, col, r, c;
+
+  if ((shot = shot_select) || half_size) {
+    if (shot) shot--;
+    if (shot > 3) shot = 3;
+    fseek (ifp, data_offset + shot*4, SEEK_SET);
+    fseek (ifp, get4(), SEEK_SET);
+    unpacked_load_raw();
+    return;
+  }
+  free (image);
+  image = (ushort (*)[4])
+	calloc ((iheight=height)*(iwidth=width), sizeof *image);
+  merror (image, "sinar_4shot_load_raw()");
+  pixel = (ushort *) calloc (raw_width, sizeof *pixel);
+  merror (pixel, "sinar_4shot_load_raw()");
+  for (shot=0; shot < 4; shot++) {
+    fseek (ifp, data_offset + shot*4, SEEK_SET);
+    fseek (ifp, get4(), SEEK_SET);
+    for (row=0; row < raw_height; row++) {
+      read_shorts (pixel, raw_width);
+      if ((r = row-top_margin - (shot >> 1 & 1)) >= height) continue;
+      for (col=0; col < raw_width; col++) {
+	if ((c = col-left_margin - (shot & 1)) >= width) continue;
+        image[r*width+c][FC(row,col)] = pixel[col];
+      }
+    }
+  }
+  free (pixel);
+  shrink = filters = 0;
+}
+
+void CLASS imacon_full_load_raw()
+{
+  int row, col;
+
+  for (row=0; row < height; row++)
+    for (col=0; col < width; col++)
+      read_shorts (image[row*width+col], 3);
+}
+
+void CLASS packed_load_raw()
+{
+  int vbits=0, bwide, pwide, rbits, bite, half, irow, row, col, val, i;
+  UINT64 bitbuf=0;
+
+  if (raw_width * 8 >= width * tiff_bps)	/* Is raw_width in bytes? */
+       pwide = (bwide = raw_width) * 8 / tiff_bps;
+  else bwide = (pwide = raw_width) * tiff_bps / 8;
+  rbits = bwide * 8 - pwide * tiff_bps;
+  if (load_flags & 1) bwide = bwide * 16 / 15;
+  fseek (ifp, top_margin*bwide, SEEK_CUR);
+  bite = 8 + (load_flags & 24);
+  half = (height+1) >> 1;
+  for (irow=0; irow < height; irow++) {
+    row = irow;
+    if (load_flags & 2 &&
+	(row = irow % half * 2 + irow / half) == 1 &&
+	load_flags & 4) {
+      if (vbits=0, tiff_compress)
+	fseek (ifp, data_offset - (-half*bwide & -2048), SEEK_SET);
+      else {
+	fseek (ifp, 0, SEEK_END);
+	fseek (ifp, ftell(ifp) >> 3 << 2, SEEK_SET);
+      }
+    }
+    for (col=0; col < pwide; col++) {
+      for (vbits -= tiff_bps; vbits < 0; vbits += bite) {
+	bitbuf <<= bite;
+	for (i=0; i < bite; i+=8)
+	  bitbuf |= (unsigned) (fgetc(ifp) << i);
+      }
+      val = bitbuf << (64-tiff_bps-vbits) >> (64-tiff_bps);
+      i = (col ^ (bite == 24)) - left_margin;
+      if ((unsigned) i < width)
+	BAYER(row,i) = val << (load_flags >> 6);
+      else if (load_flags & 32)
+	black += val;
+      if (load_flags & 1 && (col % 10) == 9 &&
+	fgetc(ifp) && col < width+left_margin) derror();
+    }
+    vbits -= rbits;
+  }
+  if (load_flags & 32 && pwide > width)
+    black /= (pwide - width) * height;
+}
+
+void CLASS unpacked_load_raw()
+{
+  ushort *pixel;
+  int row, col, bits=0;
+
+  while (1 << ++bits < maximum);
+  fseek (ifp, (top_margin*raw_width + left_margin) * 2, SEEK_CUR);
+  pixel = (ushort *) calloc (width, sizeof *pixel);
+  merror (pixel, "unpacked_load_raw()");
+  for (row=0; row < height; row++) {
+    read_shorts (pixel, width);
+    fseek (ifp, 2*(raw_width - width), SEEK_CUR);
+    for (col=0; col < width; col++)
+      if ((BAYER2(row,col) = pixel[col]) >> bits) derror();
+  }
+  free (pixel);
+}
+
+void CLASS nokia_load_raw()
+{
+  uchar  *data,  *dp;
+  ushort *pixel, *pix;
+  int dwide, row, c;
+
+  dwide = raw_width * 5 / 4;
+  data = (uchar *) malloc (dwide + raw_width*2);
+  merror (data, "nokia_load_raw()");
+  pixel = (ushort *) (data + dwide);
+  for (row=0; row < raw_height; row++) {
+    if (fread (data, 1, dwide, ifp) < dwide) derror();
+    for (dp=data, pix=pixel; pix < pixel+raw_width; dp+=5, pix+=4)
+      FORC4 pix[c] = (dp[c] << 2) | (dp[4] >> (c << 1) & 3);
+    if (row < top_margin)
+      FORC(width) black += pixel[c];
+    else
+      FORC(width) BAYER(row-top_margin,c) = pixel[c];
+  }
+  free (data);
+  if (top_margin) black /= top_margin * width;
+  maximum = 0x3ff;
+}
+
+unsigned CLASS pana_bits (int nbits)
+{
+  static uchar buf[0x4000];
+  static int vbits;
+  int byte;
+
+  if (!nbits) return vbits=0;
+  if (!vbits) {
+    fread (buf+load_flags, 1, 0x4000-load_flags, ifp);
+    fread (buf, 1, load_flags, ifp);
+  }
+  vbits = (vbits - nbits) & 0x1ffff;
+  byte = vbits >> 3 ^ 0x3ff0;
+  return (buf[byte] | buf[byte+1] << 8) >> (vbits & 7) & ~(-1 << nbits);
+}
+
+void CLASS panasonic_load_raw()
+{
+  int row, col, i, j, sh=0, pred[2], nonz[2];
+
+  pana_bits(0);
+  for (row=0; row < height; row++)
+    for (col=0; col < raw_width; col++) {
+      if ((i = col % 14) == 0)
+	pred[0] = pred[1] = nonz[0] = nonz[1] = 0;
+      if (i % 3 == 2) sh = 4 >> (3 - pana_bits(2));
+      if (nonz[i & 1]) {
+	if ((j = pana_bits(8))) {
+	  if ((pred[i & 1] -= 0x80 << sh) < 0 || sh == 4)
+	       pred[i & 1] &= ~(-1 << sh);
+	  pred[i & 1] += j << sh;
+	}
+      } else if ((nonz[i & 1] = pana_bits(8)) || i > 11)
+	pred[i & 1] = nonz[i & 1] << 4 | pana_bits(4);
+      if (col < width)
+	if ((BAYER(row,col) = pred[col & 1]) > 4098) derror();
+    }
+}
+
+void CLASS olympus_load_raw()
+{
+  ushort huff[4096];
+  int row, col, nbits, sign, low, high, i, c, w, n, nw;
+  int acarry[2][3], *carry, pred, diff;
+
+  huff[n=0] = 0xc0c;
+  for (i=12; i--; )
+    FORC(2048 >> i) huff[++n] = (i+1) << 8 | i;
+  fseek (ifp, 7, SEEK_CUR);
+  getbits(-1);
+  for (row=0; row < height; row++) {
+    memset (acarry, 0, sizeof acarry);
+    for (col=0; col < raw_width; col++) {
+      carry = acarry[col & 1];
+      i = 2 * (carry[2] < 3);
+      for (nbits=2+i; (ushort) carry[0] >> (nbits+i); nbits++);
+      low = (sign = getbits(3)) & 3;
+      sign = sign << 29 >> 31;
+      if ((high = getbithuff(12,huff)) == 12)
+	high = getbits(16-nbits) >> 1;
+      carry[0] = (high << nbits) | getbits(nbits);
+      diff = (carry[0] ^ sign) + carry[1];
+      carry[1] = (diff*3 + carry[1]) >> 5;
+      carry[2] = carry[0] > 16 ? 0 : carry[2]+1;
+      if (col >= width) continue;
+      if (row < 2 && col < 2) pred = 0;
+      else if (row < 2) pred = BAYER(row,col-2);
+      else if (col < 2) pred = BAYER(row-2,col);
+      else {
+	w  = BAYER(row,col-2);
+	n  = BAYER(row-2,col);
+	nw = BAYER(row-2,col-2);
+	if ((w < nw && nw < n) || (n < nw && nw < w)) {
+	  if (ABS(w-nw) > 32 || ABS(n-nw) > 32)
+	    pred = w + n - nw;
+	  else pred = (w + n) >> 1;
+	} else pred = ABS(w-nw) > ABS(n-nw) ? w : n;
+      }
+      if ((BAYER(row,col) = pred + ((diff << 2) | low)) >> 12) derror();
+    }
+  }
+}
+
+void CLASS minolta_rd175_load_raw()
+{
+  uchar pixel[768];
+  unsigned irow, box, row, col;
+
+  for (irow=0; irow < 1481; irow++) {
+    if (fread (pixel, 1, 768, ifp) < 768) derror();
+    box = irow / 82;
+    row = irow % 82 * 12 + ((box < 12) ? box | 1 : (box-12)*2);
+    switch (irow) {
+      case 1477: case 1479: continue;
+      case 1476: row = 984; break;
+      case 1480: row = 985; break;
+      case 1478: row = 985; box = 1;
+    }
+    if ((box < 12) && (box & 1)) {
+      for (col=0; col < 1533; col++, row ^= 1)
+	if (col != 1) BAYER(row,col) = (col+1) & 2 ?
+		   pixel[col/2-1] + pixel[col/2+1] : pixel[col/2] << 1;
+      BAYER(row,1)    = pixel[1]   << 1;
+      BAYER(row,1533) = pixel[765] << 1;
+    } else
+      for (col=row & 1; col < 1534; col+=2)
+	BAYER(row,col) = pixel[col/2] << 1;
+  }
+  maximum = 0xff << 1;
+}
+
+void CLASS quicktake_100_load_raw()
+{
+  uchar pixel[484][644];
+  static const short gstep[16] =
+  { -89,-60,-44,-32,-22,-15,-8,-2,2,8,15,22,32,44,60,89 };
+  static const short rstep[6][4] =
+  { {  -3,-1,1,3  }, {  -5,-1,1,5  }, {  -8,-2,2,8  },
+    { -13,-3,3,13 }, { -19,-4,4,19 }, { -28,-6,6,28 } };
+  static const short curve[256] =
+  { 0,1,2,3,4,5,6,7,8,9,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,
+    28,29,30,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,53,
+    54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,74,75,76,77,78,
+    79,80,81,82,83,84,86,88,90,92,94,97,99,101,103,105,107,110,112,114,116,
+    118,120,123,125,127,129,131,134,136,138,140,142,144,147,149,151,153,155,
+    158,160,162,164,166,168,171,173,175,177,179,181,184,186,188,190,192,195,
+    197,199,201,203,205,208,210,212,214,216,218,221,223,226,230,235,239,244,
+    248,252,257,261,265,270,274,278,283,287,291,296,300,305,309,313,318,322,
+    326,331,335,339,344,348,352,357,361,365,370,374,379,383,387,392,396,400,
+    405,409,413,418,422,426,431,435,440,444,448,453,457,461,466,470,474,479,
+    483,487,492,496,500,508,519,531,542,553,564,575,587,598,609,620,631,643,
+    654,665,676,687,698,710,721,732,743,754,766,777,788,799,810,822,833,844,
+    855,866,878,889,900,911,922,933,945,956,967,978,989,1001,1012,1023 };
+  int rb, row, col, sharp, val=0;
+
+  getbits(-1);
+  memset (pixel, 0x80, sizeof pixel);
+  for (row=2; row < height+2; row++) {
+    for (col=2+(row & 1); col < width+2; col+=2) {
+      val = ((pixel[row-1][col-1] + 2*pixel[row-1][col+1] +
+		pixel[row][col-2]) >> 2) + gstep[getbits(4)];
+      pixel[row][col] = val = LIM(val,0,255);
+      if (col < 4)
+	pixel[row][col-2] = pixel[row+1][~row & 1] = val;
+      if (row == 2)
+	pixel[row-1][col+1] = pixel[row-1][col+3] = val;
+    }
+    pixel[row][col] = val;
+  }
+  for (rb=0; rb < 2; rb++)
+    for (row=2+rb; row < height+2; row+=2)
+      for (col=3-(row & 1); col < width+2; col+=2) {
+	if (row < 4 || col < 4) sharp = 2;
+	else {
+	  val = ABS(pixel[row-2][col] - pixel[row][col-2])
+	      + ABS(pixel[row-2][col] - pixel[row-2][col-2])
+	      + ABS(pixel[row][col-2] - pixel[row-2][col-2]);
+	  sharp = val <  4 ? 0 : val <  8 ? 1 : val < 16 ? 2 :
+		  val < 32 ? 3 : val < 48 ? 4 : 5;
+	}
+	val = ((pixel[row-2][col] + pixel[row][col-2]) >> 1)
+	      + rstep[sharp][getbits(2)];
+	pixel[row][col] = val = LIM(val,0,255);
+	if (row < 4) pixel[row-2][col+2] = val;
+	if (col < 4) pixel[row+2][col-2] = val;
+      }
+  for (row=2; row < height+2; row++)
+    for (col=3-(row & 1); col < width+2; col+=2) {
+      val = ((pixel[row][col-1] + (pixel[row][col] << 2) +
+	      pixel[row][col+1]) >> 1) - 0x100;
+      pixel[row][col] = LIM(val,0,255);
+    }
+  for (row=0; row < height; row++)
+    for (col=0; col < width; col++)
+      BAYER(row,col) = curve[pixel[row+2][col+2]];
+  maximum = 0x3ff;
+}
+
+#define radc_token(tree) ((signed char) getbithuff(8,huff[tree]))
+
+#define FORYX for (y=1; y < 3; y++) for (x=col+1; x >= col; x--)
+
+#define PREDICTOR (c ? (buf[c][y-1][x] + buf[c][y][x+1]) / 2 \
+: (buf[c][y-1][x+1] + 2*buf[c][y-1][x] + buf[c][y][x+1]) / 4)
+
+void CLASS kodak_radc_load_raw()
+{
+  static const char src[] = {
+    1,1, 2,3, 3,4, 4,2, 5,7, 6,5, 7,6, 7,8,
+    1,0, 2,1, 3,3, 4,4, 5,2, 6,7, 7,6, 8,5, 8,8,
+    2,1, 2,3, 3,0, 3,2, 3,4, 4,6, 5,5, 6,7, 6,8,
+    2,0, 2,1, 2,3, 3,2, 4,4, 5,6, 6,7, 7,5, 7,8,
+    2,1, 2,4, 3,0, 3,2, 3,3, 4,7, 5,5, 6,6, 6,8,
+    2,3, 3,1, 3,2, 3,4, 3,5, 3,6, 4,7, 5,0, 5,8,
+    2,3, 2,6, 3,0, 3,1, 4,4, 4,5, 4,7, 5,2, 5,8,
+    2,4, 2,7, 3,3, 3,6, 4,1, 4,2, 4,5, 5,0, 5,8,
+    2,6, 3,1, 3,3, 3,5, 3,7, 3,8, 4,0, 5,2, 5,4,
+    2,0, 2,1, 3,2, 3,3, 4,4, 4,5, 5,6, 5,7, 4,8,
+    1,0, 2,2, 2,-2,
+    1,-3, 1,3,
+    2,-17, 2,-5, 2,5, 2,17,
+    2,-7, 2,2, 2,9, 2,18,
+    2,-18, 2,-9, 2,-2, 2,7,
+    2,-28, 2,28, 3,-49, 3,-9, 3,9, 4,49, 5,-79, 5,79,
+    2,-1, 2,13, 2,26, 3,39, 4,-16, 5,55, 6,-37, 6,76,
+    2,-26, 2,-13, 2,1, 3,-39, 4,16, 5,-55, 6,-76, 6,37
+  };
+  ushort huff[19][256];
+  int row, col, tree, nreps, rep, step, i, c, s, r, x, y, val;
+  short last[3] = { 16,16,16 }, mul[3], buf[3][3][386];
+  static const ushort pt[] =
+    { 0,0, 1280,1344, 2320,3616, 3328,8000, 4095,16383, 65535,16383 };
+
+  for (i=2; i < 12; i+=2)
+    for (c=pt[i-2]; c <= pt[i]; c++)
+      curve[c] = (float)
+	(c-pt[i-2]) / (pt[i]-pt[i-2]) * (pt[i+1]-pt[i-1]) + pt[i-1] + 0.5;
+  for (s=i=0; i < sizeof src; i+=2)
+    FORC(256 >> src[i])
+      huff[0][s++] = src[i] << 8 | (uchar) src[i+1];
+  s = kodak_cbpp == 243 ? 2 : 3;
+  FORC(256) huff[18][c] = (8-s) << 8 | c >> s << s | 1 << (s-1);
+  getbits(-1);
+  for (i=0; i < sizeof(buf)/sizeof(short); i++)
+    buf[0][0][i] = 2048;
+  for (row=0; row < height; row+=4) {
+    FORC3 mul[c] = getbits(6);
+    FORC3 {
+      val = ((0x1000000/last[c] + 0x7ff) >> 12) * mul[c];
+      s = val > 65564 ? 10:12;
+      x = ~(-1 << (s-1));
+      val <<= 12-s;
+      for (i=0; i < sizeof(buf[0])/sizeof(short); i++)
+	buf[c][0][i] = (buf[c][0][i] * val + x) >> s;
+      last[c] = mul[c];
+      for (r=0; r <= !c; r++) {
+	buf[c][1][width/2] = buf[c][2][width/2] = mul[c] << 7;
+	for (tree=1, col=width/2; col > 0; ) {
+	  if ((tree = radc_token(tree))) {
+	    col -= 2;
+	    if (tree == 8)
+	      FORYX buf[c][y][x] = (uchar) radc_token(18) * mul[c];
+	    else
+	      FORYX buf[c][y][x] = radc_token(tree+10) * 16 + PREDICTOR;
+	  } else
+	    do {
+	      nreps = (col > 2) ? radc_token(9) + 1 : 1;
+	      for (rep=0; rep < 8 && rep < nreps && col > 0; rep++) {
+		col -= 2;
+		FORYX buf[c][y][x] = PREDICTOR;
+		if (rep & 1) {
+		  step = radc_token(10) << 4;
+		  FORYX buf[c][y][x] += step;
+		}
+	      }
+	    } while (nreps == 9);
+	}
+	for (y=0; y < 2; y++)
+	  for (x=0; x < width/2; x++) {
+	    val = (buf[c][y+1][x] << 4) / mul[c];
+	    if (val < 0) val = 0;
+	    if (c) BAYER(row+y*2+c-1,x*2+2-c) = val;
+	    else   BAYER(row+r*2+y,x*2+y) = val;
+	  }
+	memcpy (buf[c][0]+!c, buf[c][2], sizeof buf[c][0]-2*!c);
+      }
+    }
+    for (y=row; y < row+4; y++)
+      for (x=0; x < width; x++)
+	if ((x+y) & 1) {
+	  r = x ? x-1 : x+1;
+	  s = x+1 < width ? x+1 : x-1;
+	  val = (BAYER(y,x)-2048)*2 + (BAYER(y,r)+BAYER(y,s))/2;
+	  if (val < 0) val = 0;
+	  BAYER(y,x) = val;
+	}
+  }
+  for (i=0; i < iheight*iwidth*4; i++)
+    image[0][i] = curve[image[0][i]];
+  maximum = 0x3fff;
+}
+
+#undef FORYX
+#undef PREDICTOR
+
+#ifdef NO_JPEG
+void CLASS kodak_jpeg_load_raw() {}
+#else
+
+METHODDEF(boolean)
+fill_input_buffer (j_decompress_ptr cinfo)
+{
+  static uchar jpeg_buffer[4096];
+  size_t nbytes;
+
+  nbytes = fread (jpeg_buffer, 1, 4096, ifp);
+  swab (jpeg_buffer, jpeg_buffer, nbytes);
+  cinfo->src->next_input_byte = jpeg_buffer;
+  cinfo->src->bytes_in_buffer = nbytes;
+  return TRUE;
+}
+
+void CLASS kodak_jpeg_load_raw()
+{
+  struct jpeg_decompress_struct cinfo;
+  struct jpeg_error_mgr jerr;
+  JSAMPARRAY buf;
+  JSAMPLE (*pixel)[3];
+  int row, col;
+
+  cinfo.err = jpeg_std_error (&jerr);
+  jpeg_create_decompress (&cinfo);
+  jpeg_stdio_src (&cinfo, ifp);
+  cinfo.src->fill_input_buffer = fill_input_buffer;
+  jpeg_read_header (&cinfo, TRUE);
+  jpeg_start_decompress (&cinfo);
+  if ((cinfo.output_width      != width  ) ||
+      (cinfo.output_height*2   != height ) ||
+      (cinfo.output_components != 3      )) {
+    fprintf (stderr,_("%s: incorrect JPEG dimensions\n"), ifname);
+    jpeg_destroy_decompress (&cinfo);
+    longjmp (failure, 3);
+  }
+  buf = (*cinfo.mem->alloc_sarray)
+		((j_common_ptr) &cinfo, JPOOL_IMAGE, width*3, 1);
+
+  while (cinfo.output_scanline < cinfo.output_height) {
+    row = cinfo.output_scanline * 2;
+    jpeg_read_scanlines (&cinfo, buf, 1);
+    pixel = (JSAMPLE (*)[3]) buf[0];
+    for (col=0; col < width; col+=2) {
+      BAYER(row+0,col+0) = pixel[col+0][1] << 1;
+      BAYER(row+1,col+1) = pixel[col+1][1] << 1;
+      BAYER(row+0,col+1) = pixel[col][0] + pixel[col+1][0];
+      BAYER(row+1,col+0) = pixel[col][2] + pixel[col+1][2];
+    }
+  }
+  jpeg_finish_decompress (&cinfo);
+  jpeg_destroy_decompress (&cinfo);
+  maximum = 0xff << 1;
+}
+#endif
+
+void CLASS kodak_dc120_load_raw()
+{
+  static const int mul[4] = { 162, 192, 187,  92 };
+  static const int add[4] = {   0, 636, 424, 212 };
+  uchar pixel[848];
+  int row, shift, col;
+
+  for (row=0; row < height; row++) {
+    if (fread (pixel, 1, 848, ifp) < 848) derror();
+    shift = row * mul[row & 3] + add[row & 3];
+    for (col=0; col < width; col++)
+      BAYER(row,col) = (ushort) pixel[(col + shift) % 848];
+  }
+  maximum = 0xff;
+}
+
+void CLASS eight_bit_load_raw()
+{
+  uchar *pixel;
+  unsigned row, col, val, lblack=0;
+
+  pixel = (uchar *) calloc (raw_width, sizeof *pixel);
+  merror (pixel, "eight_bit_load_raw()");
+  fseek (ifp, top_margin*raw_width, SEEK_CUR);
+  for (row=0; row < height; row++) {
+    if (fread (pixel, 1, raw_width, ifp) < raw_width) derror();
+    for (col=0; col < raw_width; col++) {
+      val = curve[pixel[col]];
+      if ((unsigned) (col-left_margin) < width)
+        BAYER(row,col-left_margin) = val;
+      else lblack += val;
+    }
+  }
+  free (pixel);
+  if (raw_width > width+1)
+    black = lblack / ((raw_width - width) * height);
+  if (!strncmp(model,"DC2",3))
+    black = 0;
+  maximum = curve[0xff];
+}
+
+void CLASS kodak_yrgb_load_raw()
+{
+  uchar *pixel;
+  int row, col, y, cb, cr, rgb[3], c;
+
+  pixel = (uchar *) calloc (raw_width, 3*sizeof *pixel);
+  merror (pixel, "kodak_yrgb_load_raw()");
+  for (row=0; row < height; row++) {
+    if (~row & 1)
+      if (fread (pixel, raw_width, 3, ifp) < 3) derror();
+    for (col=0; col < raw_width; col++) {
+      y  = pixel[width*2*(row & 1) + col];
+      cb = pixel[width + (col & -2)]   - 128;
+      cr = pixel[width + (col & -2)+1] - 128;
+      rgb[1] = y-((cb + cr + 2) >> 2);
+      rgb[2] = rgb[1] + cb;
+      rgb[0] = rgb[1] + cr;
+      FORC3 image[row*width+col][c] = curve[LIM(rgb[c],0,255)];
+    }
+  }
+  free (pixel);
+  maximum = curve[0xff];
+}
+
+void CLASS kodak_262_load_raw()
+{
+  static const uchar kodak_tree[2][26] =
+  { { 0,1,5,1,1,2,0,0,0,0,0,0,0,0,0,0, 0,1,2,3,4,5,6,7,8,9 },
+    { 0,3,1,1,1,1,1,2,0,0,0,0,0,0,0,0, 0,1,2,3,4,5,6,7,8,9 } };
+  ushort *huff[2];
+  uchar *pixel;
+  int *strip, ns, c, row, col, chess, pi=0, pi1, pi2, pred, val;
+
+  FORC(2) huff[c] = make_decoder (kodak_tree[c]);
+  ns = (raw_height+63) >> 5;
+  pixel = (uchar *) malloc (raw_width*32 + ns*4);
+  merror (pixel, "kodak_262_load_raw()");
+  strip = (int *) (pixel + raw_width*32);
+  order = 0x4d4d;
+  FORC(ns) strip[c] = get4();
+  for (row=0; row < raw_height; row++) {
+    if ((row & 31) == 0) {
+      fseek (ifp, strip[row >> 5], SEEK_SET);
+      getbits(-1);
+      pi = 0;
+    }
+    for (col=0; col < raw_width; col++) {
+      chess = (row + col) & 1;
+      pi1 = chess ? pi-2           : pi-raw_width-1;
+      pi2 = chess ? pi-2*raw_width : pi-raw_width+1;
+      if (col <= chess) pi1 = -1;
+      if (pi1 < 0) pi1 = pi2;
+      if (pi2 < 0) pi2 = pi1;
+      if (pi1 < 0 && col > 1) pi1 = pi2 = pi-2;
+      pred = (pi1 < 0) ? 0 : (pixel[pi1] + pixel[pi2]) >> 1;
+      pixel[pi] = val = pred + ljpeg_diff (huff[chess]);
+      if (val >> 8) derror();
+      val = curve[pixel[pi++]];
+      if ((unsigned) (col-left_margin) < width)
+	BAYER(row,col-left_margin) = val;
+      else black += val;
+    }
+  }
+  free (pixel);
+  FORC(2) free (huff[c]);
+  if (raw_width > width)
+    black /= (raw_width - width) * height;
+}
+
+int CLASS kodak_65000_decode (short *out, int bsize)
+{
+  uchar c, blen[768];
+  ushort raw[6];
+  INT64 bitbuf=0;
+  int save, bits=0, i, j, len, diff;
+
+  save = ftell(ifp);
+  bsize = (bsize + 3) & -4;
+  for (i=0; i < bsize; i+=2) {
+    c = fgetc(ifp);
+    if ((blen[i  ] = c & 15) > 12 ||
+	(blen[i+1] = c >> 4) > 12 ) {
+      fseek (ifp, save, SEEK_SET);
+      for (i=0; i < bsize; i+=8) {
+	read_shorts (raw, 6);
+	out[i  ] = raw[0] >> 12 << 8 | raw[2] >> 12 << 4 | raw[4] >> 12;
+	out[i+1] = raw[1] >> 12 << 8 | raw[3] >> 12 << 4 | raw[5] >> 12;
+	for (j=0; j < 6; j++)
+	  out[i+2+j] = raw[j] & 0xfff;
+      }
+      return 1;
+    }
+  }
+  if ((bsize & 7) == 4) {
+    bitbuf  = fgetc(ifp) << 8;
+    bitbuf += fgetc(ifp);
+    bits = 16;
+  }
+  for (i=0; i < bsize; i++) {
+    len = blen[i];
+    if (bits < len) {
+      for (j=0; j < 32; j+=8)
+	bitbuf += (INT64) fgetc(ifp) << (bits+(j^8));
+      bits += 32;
+    }
+    diff = bitbuf & (0xffff >> (16-len));
+    bitbuf >>= len;
+    bits -= len;
+    if ((diff & (1 << (len-1))) == 0)
+      diff -= (1 << len) - 1;
+    out[i] = diff;
+  }
+  return 0;
+}
+
+void CLASS kodak_65000_load_raw()
+{
+  short buf[256];
+  int row, col, len, pred[2], ret, i;
+
+  for (row=0; row < height; row++)
+    for (col=0; col < width; col+=256) {
+      pred[0] = pred[1] = 0;
+      len = MIN (256, width-col);
+      ret = kodak_65000_decode (buf, len);
+      for (i=0; i < len; i++)
+	if ((BAYER(row,col+i) =	curve[ret ? buf[i] :
+		(pred[i & 1] += buf[i])]) >> 12) derror();
+    }
+}
+
+void CLASS kodak_ycbcr_load_raw()
+{
+  short buf[384], *bp;
+  int row, col, len, c, i, j, k, y[2][2], cb, cr, rgb[3];
+  ushort *ip;
+
+  for (row=0; row < height; row+=2)
+    for (col=0; col < width; col+=128) {
+      len = MIN (128, width-col);
+      kodak_65000_decode (buf, len*3);
+      y[0][1] = y[1][1] = cb = cr = 0;
+      for (bp=buf, i=0; i < len; i+=2, bp+=2) {
+	cb += bp[4];
+	cr += bp[5];
+	rgb[1] = -((cb + cr + 2) >> 2);
+	rgb[2] = rgb[1] + cb;
+	rgb[0] = rgb[1] + cr;
+	for (j=0; j < 2; j++)
+	  for (k=0; k < 2; k++) {
+	    if ((y[j][k] = y[j][k^1] + *bp++) >> 10) derror();
+	    ip = image[(row+j)*width + col+i+k];
+	    FORC3 ip[c] = curve[LIM(y[j][k]+rgb[c], 0, 0xfff)];
+	  }
+      }
+    }
+}
+
+void CLASS kodak_rgb_load_raw()
+{
+  short buf[768], *bp;
+  int row, col, len, c, i, rgb[3];
+  ushort *ip=image[0];
+
+  for (row=0; row < height; row++)
+    for (col=0; col < width; col+=256) {
+      len = MIN (256, width-col);
+      kodak_65000_decode (buf, len*3);
+      memset (rgb, 0, sizeof rgb);
+      for (bp=buf, i=0; i < len; i++, ip+=4)
+	FORC3 if ((ip[c] = rgb[c] += *bp++) >> 12) derror();
+    }
+}
+
+void CLASS kodak_thumb_load_raw()
+{
+  int row, col;
+  colors = thumb_misc >> 5;
+  for (row=0; row < height; row++)
+    for (col=0; col < width; col++)
+      read_shorts (image[row*width+col], colors);
+  maximum = (1 << (thumb_misc & 31)) - 1;
+}
+
+void CLASS sony_decrypt (unsigned *data, int len, int start, int key)
+{
+  static unsigned pad[128], p;
+
+  if (start) {
+    for (p=0; p < 4; p++)
+      pad[p] = key = key * 48828125 + 1;
+    pad[3] = pad[3] << 1 | (pad[0]^pad[2]) >> 31;
+    for (p=4; p < 127; p++)
+      pad[p] = (pad[p-4]^pad[p-2]) << 1 | (pad[p-3]^pad[p-1]) >> 31;
+    for (p=0; p < 127; p++)
+      pad[p] = htonl(pad[p]);
+  }
+  while (len--)
+    *data++ ^= pad[p++ & 127] = pad[(p+1) & 127] ^ pad[(p+65) & 127];
+}
+
+void CLASS sony_load_raw()
+{
+  uchar head[40];
+  ushort *pixel;
+  unsigned i, key, row, col;
+
+  fseek (ifp, 200896, SEEK_SET);
+  fseek (ifp, (unsigned) fgetc(ifp)*4 - 1, SEEK_CUR);
+  order = 0x4d4d;
+  key = get4();
+  fseek (ifp, 164600, SEEK_SET);
+  fread (head, 1, 40, ifp);
+  sony_decrypt ((unsigned int *) head, 10, 1, key);
+  for (i=26; i-- > 22; )
+    key = key << 8 | head[i];
+  fseek (ifp, data_offset, SEEK_SET);
+  pixel = (ushort *) calloc (raw_width, sizeof *pixel);
+  merror (pixel, "sony_load_raw()");
+  for (row=0; row < height; row++) {
+    if (fread (pixel, 2, raw_width, ifp) < raw_width) derror();
+    sony_decrypt ((unsigned int *) pixel, raw_width/2, !row, key);
+    for (col=9; col < left_margin; col++)
+      black += ntohs(pixel[col]);
+    for (col=0; col < width; col++)
+      if ((BAYER(row,col) = ntohs(pixel[col+left_margin])) >> 14)
+	derror();
+  }
+  free (pixel);
+  if (left_margin > 9)
+    black /= (left_margin-9) * height;
+  maximum = 0x3ff0;
+}
+
+void CLASS sony_arw_load_raw()
+{
+  ushort huff[32768];
+  static const ushort tab[18] =
+  { 0xf11,0xf10,0xe0f,0xd0e,0xc0d,0xb0c,0xa0b,0x90a,0x809,
+    0x708,0x607,0x506,0x405,0x304,0x303,0x300,0x202,0x201 };
+  int i, c, n, col, row, len, diff, sum=0;
+
+  for (n=i=0; i < 18; i++)
+    FORC(32768 >> (tab[i] >> 8)) huff[n++] = tab[i];
+  getbits(-1);
+  for (col = raw_width; col--; )
+    for (row=0; row < raw_height+1; row+=2) {
+      if (row == raw_height) row = 1;
+      len = getbithuff(15,huff);
+      diff = getbits(len);
+      if ((diff & (1 << (len-1))) == 0)
+	diff -= (1 << len) - 1;
+      if ((sum += diff) >> 12) derror();
+      if (row < height) BAYER(row,col) = sum;
+    }
+}
+
+void CLASS sony_arw2_load_raw()
+{
+  uchar *data, *dp;
+  ushort pix[16];
+  int row, col, val, max, min, imax, imin, sh, bit, i;
+
+  data = (uchar *) malloc (raw_width);
+  merror (data, "sony_arw2_load_raw()");
+  for (row=0; row < height; row++) {
+    fread (data, 1, raw_width, ifp);
+    for (dp=data, col=0; col < width-30; dp+=16) {
+      max = 0x7ff & (val = sget4(dp));
+      min = 0x7ff & val >> 11;
+      imax = 0x0f & val >> 22;
+      imin = 0x0f & val >> 26;
+      for (sh=0; sh < 4 && 0x80 << sh <= max-min; sh++);
+      for (bit=30, i=0; i < 16; i++)
+	if      (i == imax) pix[i] = max;
+	else if (i == imin) pix[i] = min;
+	else {
+	  pix[i] = ((sget2(dp+(bit >> 3)) >> (bit & 7) & 0x7f) << sh) + min;
+	  if (pix[i] > 0x7ff) pix[i] = 0x7ff;
+	  bit += 7;
+	}
+      for (i=0; i < 16; i++, col+=2)
+	BAYER(row,col) = curve[pix[i] << 1] >> 1;
+      col -= col & 1 ? 1:31;
+    }
+  }
+  free (data);
+}
+
+#define HOLE(row) ((holes >> (((row) - raw_height) & 7)) & 1)
+
+/* Kudos to Rich Taylor for figuring out SMaL's compression algorithm. */
+void CLASS smal_decode_segment (unsigned seg[2][2], int holes)
+{
+  uchar hist[3][13] = {
+    { 7, 7, 0, 0, 63, 55, 47, 39, 31, 23, 15, 7, 0 },
+    { 7, 7, 0, 0, 63, 55, 47, 39, 31, 23, 15, 7, 0 },
+    { 3, 3, 0, 0, 63,     47,     31,     15,    0 } };
+  int low, high=0xff, carry=0, nbits=8;
+  int s, count, bin, next, i, sym[3];
+  uchar diff, pred[]={0,0};
+  ushort data=0, range=0;
+  unsigned pix, row, col;
+
+  fseek (ifp, seg[0][1]+1, SEEK_SET);
+  getbits(-1);
+  for (pix=seg[0][0]; pix < seg[1][0]; pix++) {
+    for (s=0; s < 3; s++) {
+      data = data << nbits | getbits(nbits);
+      if (carry < 0)
+	carry = (nbits += carry+1) < 1 ? nbits-1 : 0;
+      while (--nbits >= 0)
+	if ((data >> nbits & 0xff) == 0xff) break;
+      if (nbits > 0)
+	  data = ((data & ((1 << (nbits-1)) - 1)) << 1) |
+	((data + (((data & (1 << (nbits-1)))) << 1)) & (-1 << nbits));
+      if (nbits >= 0) {
+	data += getbits(1);
+	carry = nbits - 8;
+      }
+      count = ((((data-range+1) & 0xffff) << 2) - 1) / (high >> 4);
+      for (bin=0; hist[s][bin+5] > count; bin++);
+		low = hist[s][bin+5] * (high >> 4) >> 2;
+      if (bin) high = hist[s][bin+4] * (high >> 4) >> 2;
+      high -= low;
+      for (nbits=0; high << nbits < 128; nbits++);
+      range = (range+low) << nbits;
+      high <<= nbits;
+      next = hist[s][1];
+      if (++hist[s][2] > hist[s][3]) {
+	next = (next+1) & hist[s][0];
+	hist[s][3] = (hist[s][next+4] - hist[s][next+5]) >> 2;
+	hist[s][2] = 1;
+      }
+      if (hist[s][hist[s][1]+4] - hist[s][hist[s][1]+5] > 1) {
+	if (bin < hist[s][1])
+	  for (i=bin; i < hist[s][1]; i++) hist[s][i+5]--;
+	else if (next <= bin)
+	  for (i=hist[s][1]; i < bin; i++) hist[s][i+5]++;
+      }
+      hist[s][1] = next;
+      sym[s] = bin;
+    }
+    diff = sym[2] << 5 | sym[1] << 2 | (sym[0] & 3);
+    if (sym[0] & 4)
+      diff = diff ? -diff : 0x80;
+    if (ftell(ifp) + 12 >= seg[1][1])
+      diff = 0;
+    pred[pix & 1] += diff;
+    row = pix / raw_width - top_margin;
+    col = pix % raw_width - left_margin;
+    if (row < height && col < width)
+      BAYER(row,col) = pred[pix & 1];
+    if (!(pix & 1) && HOLE(row)) pix += 2;
+  }
+  maximum = 0xff;
+}
+
+void CLASS smal_v6_load_raw()
+{
+  unsigned seg[2][2];
+
+  fseek (ifp, 16, SEEK_SET);
+  seg[0][0] = 0;
+  seg[0][1] = get2();
+  seg[1][0] = raw_width * raw_height;
+  seg[1][1] = INT_MAX;
+  smal_decode_segment (seg, 0);
+}
+
+int CLASS median4 (int *p)
+{
+  int min, max, sum, i;
+
+  min = max = sum = p[0];
+  for (i=1; i < 4; i++) {
+    sum += p[i];
+    if (min > p[i]) min = p[i];
+    if (max < p[i]) max = p[i];
+  }
+  return (sum - min - max) >> 1;
+}
+
+void CLASS fill_holes (int holes)
+{
+  int row, col, val[4];
+
+  for (row=2; row < height-2; row++) {
+    if (!HOLE(row)) continue;
+    for (col=1; col < width-1; col+=4) {
+      val[0] = BAYER(row-1,col-1);
+      val[1] = BAYER(row-1,col+1);
+      val[2] = BAYER(row+1,col-1);
+      val[3] = BAYER(row+1,col+1);
+      BAYER(row,col) = median4(val);
+    }
+    for (col=2; col < width-2; col+=4)
+      if (HOLE(row-2) || HOLE(row+2))
+	BAYER(row,col) = (BAYER(row,col-2) + BAYER(row,col+2)) >> 1;
+      else {
+	val[0] = BAYER(row,col-2);
+	val[1] = BAYER(row,col+2);
+	val[2] = BAYER(row-2,col);
+	val[3] = BAYER(row+2,col);
+	BAYER(row,col) = median4(val);
+      }
+  }
+}
+
+void CLASS smal_v9_load_raw()
+{
+  unsigned seg[256][2], offset, nseg, holes, i;
+
+  fseek (ifp, 67, SEEK_SET);
+  offset = get4();
+  nseg = fgetc(ifp);
+  fseek (ifp, offset, SEEK_SET);
+  for (i=0; i < nseg*2; i++)
+    seg[0][i] = get4() + data_offset*(i & 1);
+  fseek (ifp, 78, SEEK_SET);
+  holes = fgetc(ifp);
+  fseek (ifp, 88, SEEK_SET);
+  seg[nseg][0] = raw_height * raw_width;
+  seg[nseg][1] = get4() + data_offset;
+  for (i=0; i < nseg; i++)
+    smal_decode_segment (seg+i, holes);
+  if (holes) fill_holes (holes);
+}
+
+/* RESTRICTED code starts here */
+
+void CLASS foveon_decoder (unsigned size, unsigned code)
+{
+  static unsigned huff[1024];
+  struct decode *cur;
+  int i, len;
+
+  if (!code) {
+    for (i=0; i < size; i++)
+      huff[i] = get4();
+    memset (first_decode, 0, sizeof first_decode);
+    free_decode = first_decode;
+  }
+  cur = free_decode++;
+  if (free_decode > first_decode+2048) {
+    fprintf (stderr,_("%s: decoder table overflow\n"), ifname);
+    longjmp (failure, 2);
+  }
+  if (code)
+    for (i=0; i < size; i++)
+      if (huff[i] == code) {
+	cur->leaf = i;
+	return;
+      }
+  if ((len = code >> 27) > 26) return;
+  code = (len+1) << 27 | (code & 0x3ffffff) << 1;
+
+  cur->branch[0] = free_decode;
+  foveon_decoder (size, code);
+  cur->branch[1] = free_decode;
+  foveon_decoder (size, code+1);
+}
+
+void CLASS foveon_thumb()
+{
+  unsigned bwide, row, col, bitbuf=0, bit=1, c, i;
+  char *buf;
+  struct decode *dindex;
+  short pred[3];
+
+  bwide = get4();
+  fprintf (ofp, "P6\n%d %d\n255\n", thumb_width, thumb_height);
+  if (bwide > 0) {
+    if (bwide < thumb_width*3) return;
+    buf = (char *) malloc (bwide);
+    merror (buf, "foveon_thumb()");
+    for (row=0; row < thumb_height; row++) {
+      fread  (buf, 1, bwide, ifp);
+      fwrite (buf, 3, thumb_width, ofp);
+    }
+    free (buf);
+    return;
+  }
+  foveon_decoder (256, 0);
+
+  for (row=0; row < thumb_height; row++) {
+    memset (pred, 0, sizeof pred);
+    if (!bit) get4();
+    for (bit=col=0; col < thumb_width; col++)
+      FORC3 {
+	for (dindex=first_decode; dindex->branch[0]; ) {
+	  if ((bit = (bit-1) & 31) == 31)
+	    for (i=0; i < 4; i++)
+	      bitbuf = (bitbuf << 8) + fgetc(ifp);
+	  dindex = dindex->branch[bitbuf >> bit & 1];
+	}
+	pred[c] += dindex->leaf;
+	fputc (pred[c], ofp);
+      }
+  }
+}
+
+void CLASS foveon_load_camf()
+{
+  unsigned key, i, val;
+
+  fseek (ifp, meta_offset, SEEK_SET);
+  key = get4();
+  fread (meta_data, 1, meta_length, ifp);
+  for (i=0; i < meta_length; i++) {
+    key = (key * 1597 + 51749) % 244944;
+    val = key * (INT64) 301593171 >> 24;
+    meta_data[i] ^= ((((key << 8) - val) >> 1) + val) >> 17;
+  }
+}
+
+void CLASS foveon_load_raw()
+{
+  struct decode *dindex;
+  short diff[1024];
+  unsigned bitbuf=0;
+  int pred[3], fixed, row, col, bit=-1, c, i;
+
+  fixed = get4();
+  read_shorts ((ushort *) diff, 1024);
+  if (!fixed) foveon_decoder (1024, 0);
+
+  for (row=0; row < height; row++) {
+    memset (pred, 0, sizeof pred);
+    if (!bit && !fixed && atoi(model+2) < 14) get4();
+    for (col=bit=0; col < width; col++) {
+      if (fixed) {
+	bitbuf = get4();
+	FORC3 pred[2-c] += diff[bitbuf >> c*10 & 0x3ff];
+      }
+      else FORC3 {
+	for (dindex=first_decode; dindex->branch[0]; ) {
+	  if ((bit = (bit-1) & 31) == 31)
+	    for (i=0; i < 4; i++)
+	      bitbuf = (bitbuf << 8) + fgetc(ifp);
+	  dindex = dindex->branch[bitbuf >> bit & 1];
+	}
+	pred[c] += diff[dindex->leaf];
+	if (pred[c] >> 16 && ~pred[c] >> 16) derror();
+      }
+      FORC3 image[row*width+col][c] = pred[c];
+    }
+  }
+  if (document_mode)
+    for (i=0; i < height*width*4; i++)
+      if ((short) image[0][i] < 0) image[0][i] = 0;
+  foveon_load_camf();
+}
+
+const char * CLASS foveon_camf_param (const char *block, const char *param)
+{
+  unsigned idx, num;
+  char *pos, *cp, *dp;
+
+  for (idx=0; idx < meta_length; idx += sget4(pos+8)) {
+    pos = meta_data + idx;
+    if (strncmp (pos, "CMb", 3)) break;
+    if (pos[3] != 'P') continue;
+    if (strcmp (block, pos+sget4(pos+12))) continue;
+    cp = pos + sget4(pos+16);
+    num = sget4(cp);
+    dp = pos + sget4(cp+4);
+    while (num--) {
+      cp += 8;
+      if (!strcmp (param, dp+sget4(cp)))
+	return dp+sget4(cp+4);
+    }
+  }
+  return 0;
+}
+
+void * CLASS foveon_camf_matrix (unsigned dim[3], const char *name)
+{
+  unsigned i, idx, type, ndim, size, *mat;
+  char *pos, *cp, *dp;
+  double dsize;
+
+  for (idx=0; idx < meta_length; idx += sget4(pos+8)) {
+    pos = meta_data + idx;
+    if (strncmp (pos, "CMb", 3)) break;
+    if (pos[3] != 'M') continue;
+    if (strcmp (name, pos+sget4(pos+12))) continue;
+    dim[0] = dim[1] = dim[2] = 1;
+    cp = pos + sget4(pos+16);
+    type = sget4(cp);
+    if ((ndim = sget4(cp+4)) > 3) break;
+    dp = pos + sget4(cp+8);
+    for (i=ndim; i--; ) {
+      cp += 12;
+      dim[i] = sget4(cp);
+    }
+    if ((dsize = (double) dim[0]*dim[1]*dim[2]) > meta_length/4) break;
+    mat = (unsigned *) malloc ((size = dsize) * 4);
+    merror (mat, "foveon_camf_matrix()");
+    for (i=0; i < size; i++)
+      if (type && type != 6)
+	mat[i] = sget4(dp + i*4);
+      else
+	mat[i] = sget4(dp + i*2) & 0xffff;
+    return mat;
+  }
+  fprintf (stderr,_("%s: \"%s\" matrix not found!\n"), ifname, name);
+  return 0;
+}
+
+int CLASS foveon_fixed (void *ptr, int size, const char *name)
+{
+  void *dp;
+  unsigned dim[3];
+
+  dp = foveon_camf_matrix (dim, name);
+  if (!dp) return 0;
+  memcpy (ptr, dp, size*4);
+  free (dp);
+  return 1;
+}
+
+float CLASS foveon_avg (short *pix, int range[2], float cfilt)
+{
+  int i;
+  float val, min=FLT_MAX, max=-FLT_MAX, sum=0;
+
+  for (i=range[0]; i <= range[1]; i++) {
+    sum += val = pix[i*4] + (pix[i*4]-pix[(i-1)*4]) * cfilt;
+    if (min > val) min = val;
+    if (max < val) max = val;
+  }
+  if (range[1] - range[0] == 1) return sum/2;
+  return (sum - min - max) / (range[1] - range[0] - 1);
+}
+
+short * CLASS foveon_make_curve (double max, double mul, double filt)
+{
+  short *curve;
+  unsigned i, size;
+  double x;
+
+  if (!filt) filt = 0.8;
+  size = 4*M_PI*max / filt;
+  if (size == UINT_MAX) size--;
+  curve = (short *) calloc (size+1, sizeof *curve);
+  merror (curve, "foveon_make_curve()");
+  curve[0] = size;
+  for (i=0; i < size; i++) {
+    x = i*filt/max/4;
+    curve[i+1] = (cos(x)+1)/2 * tanh(i*filt/mul) * mul + 0.5;
+  }
+  return curve;
+}
+
+void CLASS foveon_make_curves
+	(short **curvep, float dq[3], float div[3], float filt)
+{
+  double mul[3], max=0;
+  int c;
+
+  FORC3 mul[c] = dq[c]/div[c];
+  FORC3 if (max < mul[c]) max = mul[c];
+  FORC3 curvep[c] = foveon_make_curve (max, mul[c], filt);
+}
+
+int CLASS foveon_apply_curve (short *curve, int i)
+{
+  if (abs(i) >= curve[0]) return 0;
+  return i < 0 ? -curve[1-i] : curve[1+i];
+}
+
+#define image ((short (*)[4]) image)
+
+void CLASS foveon_interpolate()
+{
+  static const short hood[] = { -1,-1, -1,0, -1,1, 0,-1, 0,1, 1,-1, 1,0, 1,1 };
+  short *pix, prev[3], *curve[8], (*shrink)[3];
+  float cfilt=0, ddft[3][3][2], ppm[3][3][3];
+  float cam_xyz[3][3], correct[3][3], last[3][3], trans[3][3];
+  float chroma_dq[3], color_dq[3], diag[3][3], div[3];
+  float (*black)[3], (*sgain)[3], (*sgrow)[3];
+  float fsum[3], val, frow, num;
+  int row, col, c, i, j, diff, sgx, irow, sum, min, max, limit;
+  int dscr[2][2], dstb[4], (*smrow[7])[3], total[4], ipix[3];
+  int work[3][3], smlast, smred, smred_p=0, dev[3];
+  int satlev[3], keep[4], active[4];
+  unsigned dim[3], *badpix;
+  double dsum=0, trsum[3];
+  char str[128];
+  const char* cp;
+
+  if (verbose)
+    fprintf (stderr,_("Foveon interpolation...\n"));
+
+  foveon_fixed (dscr, 4, "DarkShieldColRange");
+  foveon_fixed (ppm[0][0], 27, "PostPolyMatrix");
+  foveon_fixed (satlev, 3, "SaturationLevel");
+  foveon_fixed (keep, 4, "KeepImageArea");
+  foveon_fixed (active, 4, "ActiveImageArea");
+  foveon_fixed (chroma_dq, 3, "ChromaDQ");
+  foveon_fixed (color_dq, 3,
+	foveon_camf_param ("IncludeBlocks", "ColorDQ") ?
+		"ColorDQ" : "ColorDQCamRGB");
+  if (foveon_camf_param ("IncludeBlocks", "ColumnFilter"))
+  		 foveon_fixed (&cfilt, 1, "ColumnFilter");
+
+  memset (ddft, 0, sizeof ddft);
+  if (!foveon_camf_param ("IncludeBlocks", "DarkDrift")
+	 || !foveon_fixed (ddft[1][0], 12, "DarkDrift"))
+    for (i=0; i < 2; i++) {
+      foveon_fixed (dstb, 4, i ? "DarkShieldBottom":"DarkShieldTop");
+      for (row = dstb[1]; row <= dstb[3]; row++)
+	for (col = dstb[0]; col <= dstb[2]; col++)
+	  FORC3 ddft[i+1][c][1] += (short) image[row*width+col][c];
+      FORC3 ddft[i+1][c][1] /= (dstb[3]-dstb[1]+1) * (dstb[2]-dstb[0]+1);
+    }
+
+  if (!(cp = foveon_camf_param ("WhiteBalanceIlluminants", model2)))
+  { fprintf (stderr,_("%s: Invalid white balance \"%s\"\n"), ifname, model2);
+    return; }
+  foveon_fixed (cam_xyz, 9, cp);
+  foveon_fixed (correct, 9,
+	foveon_camf_param ("WhiteBalanceCorrections", model2));
+  memset (last, 0, sizeof last);
+  for (i=0; i < 3; i++)
+    for (j=0; j < 3; j++)
+      FORC3 last[i][j] += correct[i][c] * cam_xyz[c][j];
+
+  #define LAST(x,y) last[(i+x)%3][(c+y)%3]
+  for (i=0; i < 3; i++)
+    FORC3 diag[c][i] = LAST(1,1)*LAST(2,2) - LAST(1,2)*LAST(2,1);
+  #undef LAST
+  FORC3 div[c] = diag[c][0]*0.3127 + diag[c][1]*0.329 + diag[c][2]*0.3583;
+  sprintf (str, "%sRGBNeutral", model2);
+  if (foveon_camf_param ("IncludeBlocks", str))
+    foveon_fixed (div, 3, str);
+  num = 0;
+  FORC3 if (num < div[c]) num = div[c];
+  FORC3 div[c] /= num;
+
+  memset (trans, 0, sizeof trans);
+  for (i=0; i < 3; i++)
+    for (j=0; j < 3; j++)
+      FORC3 trans[i][j] += rgb_cam[i][c] * last[c][j] * div[j];
+  FORC3 trsum[c] = trans[c][0] + trans[c][1] + trans[c][2];
+  dsum = (6*trsum[0] + 11*trsum[1] + 3*trsum[2]) / 20;
+  for (i=0; i < 3; i++)
+    FORC3 last[i][c] = trans[i][c] * dsum / trsum[i];
+  memset (trans, 0, sizeof trans);
+  for (i=0; i < 3; i++)
+    for (j=0; j < 3; j++)
+      FORC3 trans[i][j] += (i==c ? 32 : -1) * last[c][j] / 30;
+
+  foveon_make_curves (curve, color_dq, div, cfilt);
+  FORC3 chroma_dq[c] /= 3;
+  foveon_make_curves (curve+3, chroma_dq, div, cfilt);
+  FORC3 dsum += chroma_dq[c] / div[c];
+  curve[6] = foveon_make_curve (dsum, dsum, cfilt);
+  curve[7] = foveon_make_curve (dsum*2, dsum*2, cfilt);
+
+  sgain = (float (*)[3]) foveon_camf_matrix (dim, "SpatialGain");
+  if (!sgain) return;
+  sgrow = (float (*)[3]) calloc (dim[1], sizeof *sgrow);
+  sgx = (width + dim[1]-2) / (dim[1]-1);
+
+  black = (float (*)[3]) calloc (height, sizeof *black);
+  for (row=0; row < height; row++) {
+    for (i=0; i < 6; i++)
+      ddft[0][0][i] = ddft[1][0][i] +
+	row / (height-1.0) * (ddft[2][0][i] - ddft[1][0][i]);
+    FORC3 black[row][c] =
+ 	( foveon_avg (image[row*width]+c, dscr[0], cfilt) +
+	  foveon_avg (image[row*width]+c, dscr[1], cfilt) * 3
+	  - ddft[0][c][0] ) / 4 - ddft[0][c][1];
+  }
+  memcpy (black, black+8, sizeof *black*8);
+  memcpy (black+height-11, black+height-22, 11*sizeof *black);
+  memcpy (last, black, sizeof last);
+
+  for (row=1; row < height-1; row++) {
+    FORC3 if (last[1][c] > last[0][c]) {
+	if (last[1][c] > last[2][c])
+	  black[row][c] = (last[0][c] > last[2][c]) ? last[0][c]:last[2][c];
+      } else
+	if (last[1][c] < last[2][c])
+	  black[row][c] = (last[0][c] < last[2][c]) ? last[0][c]:last[2][c];
+    memmove (last, last+1, 2*sizeof last[0]);
+    memcpy (last[2], black[row+1], sizeof last[2]);
+  }
+  FORC3 black[row][c] = (last[0][c] + last[1][c])/2;
+  FORC3 black[0][c] = (black[1][c] + black[3][c])/2;
+
+  val = 1 - exp(-1/24.0);
+  memcpy (fsum, black, sizeof fsum);
+  for (row=1; row < height; row++)
+    FORC3 fsum[c] += black[row][c] =
+	(black[row][c] - black[row-1][c])*val + black[row-1][c];
+  memcpy (last[0], black[height-1], sizeof last[0]);
+  FORC3 fsum[c] /= height;
+  for (row = height; row--; )
+    FORC3 last[0][c] = black[row][c] =
+	(black[row][c] - fsum[c] - last[0][c])*val + last[0][c];
+
+  memset (total, 0, sizeof total);
+  for (row=2; row < height; row+=4)
+    for (col=2; col < width; col+=4) {
+      FORC3 total[c] += (short) image[row*width+col][c];
+      total[3]++;
+    }
+  for (row=0; row < height; row++)
+    FORC3 black[row][c] += fsum[c]/2 + total[c]/(total[3]*100.0);
+
+  for (row=0; row < height; row++) {
+    for (i=0; i < 6; i++)
+      ddft[0][0][i] = ddft[1][0][i] +
+	row / (height-1.0) * (ddft[2][0][i] - ddft[1][0][i]);
+    pix = image[row*width];
+    memcpy (prev, pix, sizeof prev);
+    frow = row / (height-1.0) * (dim[2]-1);
+    if ((irow = frow) == dim[2]-1) irow--;
+    frow -= irow;
+    for (i=0; i < dim[1]; i++)
+      FORC3 sgrow[i][c] = sgain[ irow   *dim[1]+i][c] * (1-frow) +
+			  sgain[(irow+1)*dim[1]+i][c] *    frow;
+    for (col=0; col < width; col++) {
+      FORC3 {
+	diff = pix[c] - prev[c];
+	prev[c] = pix[c];
+	ipix[c] = pix[c] + floor ((diff + (diff*diff >> 14)) * cfilt
+		- ddft[0][c][1] - ddft[0][c][0] * ((float) col/width - 0.5)
+		- black[row][c] );
+      }
+      FORC3 {
+	work[0][c] = ipix[c] * ipix[c] >> 14;
+	work[2][c] = ipix[c] * work[0][c] >> 14;
+	work[1][2-c] = ipix[(c+1) % 3] * ipix[(c+2) % 3] >> 14;
+      }
+      FORC3 {
+	for (val=i=0; i < 3; i++)
+	  for (  j=0; j < 3; j++)
+	    val += ppm[c][i][j] * work[i][j];
+	ipix[c] = floor ((ipix[c] + floor(val)) *
+		( sgrow[col/sgx  ][c] * (sgx - col%sgx) +
+		  sgrow[col/sgx+1][c] * (col%sgx) ) / sgx / div[c]);
+	if (ipix[c] > 32000) ipix[c] = 32000;
+	pix[c] = ipix[c];
+      }
+      pix += 4;
+    }
+  }
+  free (black);
+  free (sgrow);
+  free (sgain);
+
+  if ((badpix = (unsigned int *) foveon_camf_matrix (dim, "BadPixels"))) {
+    for (i=0; i < dim[0]; i++) {
+      col = (badpix[i] >> 8 & 0xfff) - keep[0];
+      row = (badpix[i] >> 20       ) - keep[1];
+      if ((unsigned)(row-1) > height-3 || (unsigned)(col-1) > width-3)
+	continue;
+      memset (fsum, 0, sizeof fsum);
+      for (sum=j=0; j < 8; j++)
+	if (badpix[i] & (1 << j)) {
+	  FORC3 fsum[c] += (short)
+		image[(row+hood[j*2])*width+col+hood[j*2+1]][c];
+	  sum++;
+	}
+      if (sum) FORC3 image[row*width+col][c] = fsum[c]/sum;
+    }
+    free (badpix);
+  }
+
+  /* Array for 5x5 Gaussian averaging of red values */
+  smrow[6] = (int (*)[3]) calloc (width*5, sizeof **smrow);
+  merror (smrow[6], "foveon_interpolate()");
+  for (i=0; i < 5; i++)
+    smrow[i] = smrow[6] + i*width;
+
+  /* Sharpen the reds against these Gaussian averages */
+  for (smlast=-1, row=2; row < height-2; row++) {
+    while (smlast < row+2) {
+      for (i=0; i < 6; i++)
+	smrow[(i+5) % 6] = smrow[i];
+      pix = image[++smlast*width+2];
+      for (col=2; col < width-2; col++) {
+	smrow[4][col][0] =
+	  (pix[0]*6 + (pix[-4]+pix[4])*4 + pix[-8]+pix[8] + 8) >> 4;
+	pix += 4;
+      }
+    }
+    pix = image[row*width+2];
+    for (col=2; col < width-2; col++) {
+      smred = ( 6 *  smrow[2][col][0]
+	      + 4 * (smrow[1][col][0] + smrow[3][col][0])
+	      +      smrow[0][col][0] + smrow[4][col][0] + 8 ) >> 4;
+      if (col == 2)
+	smred_p = smred;
+      i = pix[0] + ((pix[0] - ((smred*7 + smred_p) >> 3)) >> 3);
+      if (i > 32000) i = 32000;
+      pix[0] = i;
+      smred_p = smred;
+      pix += 4;
+    }
+  }
+
+  /* Adjust the brighter pixels for better linearity */
+  min = 0xffff;
+  FORC3 {
+    i = satlev[c] / div[c];
+    if (min > i) min = i;
+  }
+  limit = min * 9 >> 4;
+  for (pix=image[0]; pix < image[height*width]; pix+=4) {
+    if (pix[0] <= limit || pix[1] <= limit || pix[2] <= limit)
+      continue;
+    min = max = pix[0];
+    for (c=1; c < 3; c++) {
+      if (min > pix[c]) min = pix[c];
+      if (max < pix[c]) max = pix[c];
+    }
+    if (min >= limit*2) {
+      pix[0] = pix[1] = pix[2] = max;
+    } else {
+      i = 0x4000 - ((min - limit) << 14) / limit;
+      i = 0x4000 - (i*i >> 14);
+      i = i*i >> 14;
+      FORC3 pix[c] += (max - pix[c]) * i >> 14;
+    }
+  }
+/*
+   Because photons that miss one detector often hit another,
+   the sum R+G+B is much less noisy than the individual colors.
+   So smooth the hues without smoothing the total.
+ */
+  for (smlast=-1, row=2; row < height-2; row++) {
+    while (smlast < row+2) {
+      for (i=0; i < 6; i++)
+	smrow[(i+5) % 6] = smrow[i];
+      pix = image[++smlast*width+2];
+      for (col=2; col < width-2; col++) {
+	FORC3 smrow[4][col][c] = (pix[c-4]+2*pix[c]+pix[c+4]+2) >> 2;
+	pix += 4;
+      }
+    }
+    pix = image[row*width+2];
+    for (col=2; col < width-2; col++) {
+      FORC3 dev[c] = -foveon_apply_curve (curve[7], pix[c] -
+	((smrow[1][col][c] + 2*smrow[2][col][c] + smrow[3][col][c]) >> 2));
+      sum = (dev[0] + dev[1] + dev[2]) >> 3;
+      FORC3 pix[c] += dev[c] - sum;
+      pix += 4;
+    }
+  }
+  for (smlast=-1, row=2; row < height-2; row++) {
+    while (smlast < row+2) {
+      for (i=0; i < 6; i++)
+	smrow[(i+5) % 6] = smrow[i];
+      pix = image[++smlast*width+2];
+      for (col=2; col < width-2; col++) {
+	FORC3 smrow[4][col][c] =
+		(pix[c-8]+pix[c-4]+pix[c]+pix[c+4]+pix[c+8]+2) >> 2;
+	pix += 4;
+      }
+    }
+    pix = image[row*width+2];
+    for (col=2; col < width-2; col++) {
+      for (total[3]=375, sum=60, c=0; c < 3; c++) {
+	for (total[c]=i=0; i < 5; i++)
+	  total[c] += smrow[i][col][c];
+	total[3] += total[c];
+	sum += pix[c];
+      }
+      if (sum < 0) sum = 0;
+      j = total[3] > 375 ? (sum << 16) / total[3] : sum * 174;
+      FORC3 pix[c] += foveon_apply_curve (curve[6],
+		((j*total[c] + 0x8000) >> 16) - pix[c]);
+      pix += 4;
+    }
+  }
+
+  /* Transform the image to a different colorspace */
+  for (pix=image[0]; pix < image[height*width]; pix+=4) {
+    FORC3 pix[c] -= foveon_apply_curve (curve[c], pix[c]);
+    sum = (pix[0]+pix[1]+pix[1]+pix[2]) >> 2;
+    FORC3 pix[c] -= foveon_apply_curve (curve[c], pix[c]-sum);
+    FORC3 {
+      for (dsum=i=0; i < 3; i++)
+	dsum += trans[c][i] * pix[i];
+      if (dsum < 0)  dsum = 0;
+      if (dsum > 24000) dsum = 24000;
+      ipix[c] = dsum + 0.5;
+    }
+    FORC3 pix[c] = ipix[c];
+  }
+
+  /* Smooth the image bottom-to-top and save at 1/4 scale */
+  shrink = (short (*)[3]) calloc ((width/4) * (height/4), sizeof *shrink);
+  merror (shrink, "foveon_interpolate()");
+  for (row = height/4; row--; )
+    for (col=0; col < width/4; col++) {
+      ipix[0] = ipix[1] = ipix[2] = 0;
+      for (i=0; i < 4; i++)
+	for (j=0; j < 4; j++)
+	  FORC3 ipix[c] += image[(row*4+i)*width+col*4+j][c];
+      FORC3
+	if (row+2 > height/4)
+	  shrink[row*(width/4)+col][c] = ipix[c] >> 4;
+	else
+	  shrink[row*(width/4)+col][c] =
+	    (shrink[(row+1)*(width/4)+col][c]*1840 + ipix[c]*141 + 2048) >> 12;
+    }
+  /* From the 1/4-scale image, smooth right-to-left */
+  for (row=0; row < (height & ~3); row++) {
+    ipix[0] = ipix[1] = ipix[2] = 0;
+    if ((row & 3) == 0)
+      for (col = width & ~3 ; col--; )
+	FORC3 smrow[0][col][c] = ipix[c] =
+	  (shrink[(row/4)*(width/4)+col/4][c]*1485 + ipix[c]*6707 + 4096) >> 13;
+
+  /* Then smooth left-to-right */
+    ipix[0] = ipix[1] = ipix[2] = 0;
+    for (col=0; col < (width & ~3); col++)
+      FORC3 smrow[1][col][c] = ipix[c] =
+	(smrow[0][col][c]*1485 + ipix[c]*6707 + 4096) >> 13;
+
+  /* Smooth top-to-bottom */
+    if (row == 0)
+      memcpy (smrow[2], smrow[1], sizeof **smrow * width);
+    else
+      for (col=0; col < (width & ~3); col++)
+	FORC3 smrow[2][col][c] =
+	  (smrow[2][col][c]*6707 + smrow[1][col][c]*1485 + 4096) >> 13;
+
+  /* Adjust the chroma toward the smooth values */
+    for (col=0; col < (width & ~3); col++) {
+      for (i=j=30, c=0; c < 3; c++) {
+	i += smrow[2][col][c];
+	j += image[row*width+col][c];
+      }
+      j = (j << 16) / i;
+      for (sum=c=0; c < 3; c++) {
+	ipix[c] = foveon_apply_curve (curve[c+3],
+	  ((smrow[2][col][c] * j + 0x8000) >> 16) - image[row*width+col][c]);
+	sum += ipix[c];
+      }
+      sum >>= 3;
+      FORC3 {
+	i = image[row*width+col][c] + ipix[c] - sum;
+	if (i < 0) i = 0;
+	image[row*width+col][c] = i;
+      }
+    }
+  }
+  free (shrink);
+  free (smrow[6]);
+  for (i=0; i < 8; i++)
+    free (curve[i]);
+
+  /* Trim off the black border */
+  active[1] -= keep[1];
+  active[3] -= 2;
+  i = active[2] - active[0];
+  for (row=0; row < active[3]-active[1]; row++)
+    memcpy (image[row*i], image[(row+active[1])*width+active[0]],
+	 i * sizeof *image);
+  width = i;
+  height = row;
+}
+#undef image
+
+/* RESTRICTED code ends here */
+
+/*
+   Seach from the current directory up to the root looking for
+   a ".badpixels" file, and fix those pixels now.
+ */
+void CLASS bad_pixels (const char *cfname)
+{
+  FILE *fp=0;
+  char *fname, *cp, line[128];
+  int len, time, row, col, r, c, rad, tot, n, fixed=0;
+
+  if (!filters) return;
+  if (cfname)
+    fp = fopen (cfname, "r");
+  else {
+    for (len=32 ; ; len *= 2) {
+      fname = (char *) malloc (len);
+      if (!fname) return;
+      if (getcwd (fname, len-16)) break;
+      free (fname);
+      if (errno != ERANGE) return;
+    }
+#if defined(WIN32) || defined(DJGPP)
+    if (fname[1] == ':')
+      memmove (fname, fname+2, len-2);
+    for (cp=fname; *cp; cp++)
+      if (*cp == '\\') *cp = '/';
+#endif
+    cp = fname + strlen(fname);
+    if (cp[-1] == '/') cp--;
+    while (*fname == '/') {
+      strcpy (cp, "/.badpixels");
+      if ((fp = fopen (fname, "r"))) break;
+      if (cp == fname) break;
+      while (*--cp != '/');
+    }
+    free (fname);
+  }
+  if (!fp) return;
+  while (fgets (line, 128, fp)) {
+    cp = strchr (line, '#');
+    if (cp) *cp = 0;
+    if (sscanf (line, "%d %d %d", &col, &row, &time) != 3) continue;
+    if ((unsigned) col >= width || (unsigned) row >= height) continue;
+    if (time > timestamp) continue;
+    for (tot=n=0, rad=1; rad < 3 && n==0; rad++)
+      for (r = row-rad; r <= row+rad; r++)
+	for (c = col-rad; c <= col+rad; c++)
+	  if ((unsigned) r < height && (unsigned) c < width &&
+		(r != row || c != col) && fc(r,c) == fc(row,col)) {
+	    tot += BAYER2(r,c);
+	    n++;
+	  }
+    BAYER2(row,col) = tot/n;
+    if (verbose) {
+      if (!fixed++)
+	fprintf (stderr,_("Fixed dead pixels at:"));
+      fprintf (stderr, " %d,%d", col, row);
+    }
+  }
+  if (fixed) fputc ('\n', stderr);
+  fclose (fp);
+}
+
+void CLASS subtract (const char *fname)
+{
+  FILE *fp;
+  int dim[3]={0,0,0}, comment=0, number=0, error=0, nd=0, c, row, col;
+  ushort *pixel;
+
+  if (!(fp = fopen (fname, "rb"))) {
+    perror (fname);  return;
+  }
+  if (fgetc(fp) != 'P' || fgetc(fp) != '5') error = 1;
+  while (!error && nd < 3 && (c = fgetc(fp)) != EOF) {
+    if (c == '#')  comment = 1;
+    if (c == '\n') comment = 0;
+    if (comment) continue;
+    if (isdigit(c)) number = 1;
+    if (number) {
+      if (isdigit(c)) dim[nd] = dim[nd]*10 + c -'0';
+      else if (isspace(c)) {
+	number = 0;  nd++;
+      } else error = 1;
+    }
+  }
+  if (error || nd < 3) {
+    fprintf (stderr,_("%s is not a valid PGM file!\n"), fname);
+    fclose (fp);  return;
+  } else if (dim[0] != width || dim[1] != height || dim[2] != 65535) {
+    fprintf (stderr,_("%s has the wrong dimensions!\n"), fname);
+    fclose (fp);  return;
+  }
+  pixel = (ushort *) calloc (width, sizeof *pixel);
+  merror (pixel, "subtract()");
+  for (row=0; row < height; row++) {
+    fread (pixel, 2, width, fp);
+    for (col=0; col < width; col++)
+      BAYER(row,col) = MAX (BAYER(row,col) - ntohs(pixel[col]), 0);
+  }
+  free (pixel);
+  black = 0;
+}
+
+void CLASS gamma_curve (double pwr, double ts, int mode, int imax)
+{
+  int i;
+  double g[6], bnd[2]={0,0}, r;
+
+  g[0] = pwr;
+  g[1] = ts;
+  g[2] = g[3] = g[4] = 0;
+  bnd[g[1] >= 1] = 1;
+  if (g[1] && (g[1]-1)*(g[0]-1) <= 0) {
+    for (i=0; i < 48; i++) {
+      g[2] = (bnd[0] + bnd[1])/2;
+      if (g[0]) bnd[(pow(g[2]/g[1],-g[0]) - 1)/g[0] - 1/g[2] > -1] = g[2];
+      else	bnd[g[2]/exp(1-1/g[2]) < g[1]] = g[2];
+    }
+    g[3] = g[2] / g[1];
+    if (g[0]) g[4] = g[2] * (1/g[0] - 1);
+  }
+  if (g[0]) g[5] = 1 / (g[1]*SQR(g[3])/2 - g[4]*(1 - g[3]) +
+		(1 - pow(g[3],1+g[0]))*(1 + g[4])/(1 + g[0])) - 1;
+  else      g[5] = 1 / (g[1]*SQR(g[3])/2 + 1
+		- g[2] - g[3] -	g[2]*g[3]*(log(g[3]) - 1)) - 1;
+  if (!mode--) {
+    memcpy (gamm, g, sizeof gamm);
+    return;
+  }
+  for (i=0; i < 0x10000; i++) {
+    curve[i] = 0xffff;
+    if ((r = (double) i / imax) < 1)
+      curve[i] = 0x10000 * ( mode
+	? (r < g[3] ? r*g[1] : (g[0] ? pow( r,g[0])*(1+g[4])-g[4]    : log(r)*g[2]+1))
+	: (r < g[2] ? r/g[1] : (g[0] ? pow((r+g[4])/(1+g[4]),1/g[0]) : exp((r-1)/g[2]))));
+  }
+}
+
+void CLASS pseudoinverse (double (*in)[3], double (*out)[3], int size)
+{
+  double work[3][6], num;
+  int i, j, k;
+
+  for (i=0; i < 3; i++) {
+    for (j=0; j < 6; j++)
+      work[i][j] = j == i+3;
+    for (j=0; j < 3; j++)
+      for (k=0; k < size; k++)
+	work[i][j] += in[k][i] * in[k][j];
+  }
+  for (i=0; i < 3; i++) {
+    num = work[i][i];
+    for (j=0; j < 6; j++)
+      work[i][j] /= num;
+    for (k=0; k < 3; k++) {
+      if (k==i) continue;
+      num = work[k][i];
+      for (j=0; j < 6; j++)
+	work[k][j] -= work[i][j] * num;
+    }
+  }
+  for (i=0; i < size; i++)
+    for (j=0; j < 3; j++)
+      for (out[i][j]=k=0; k < 3; k++)
+	out[i][j] += work[j][k+3] * in[i][k];
+}
+
+void CLASS cam_xyz_coeff (double cam_xyz[4][3])
+{
+  double cam_rgb[4][3], inverse[4][3], num;
+  int i, j, k;
+
+  for (i=0; i < colors; i++)		/* Multiply out XYZ colorspace */
+    for (j=0; j < 3; j++)
+      for (cam_rgb[i][j] = k=0; k < 3; k++)
+	cam_rgb[i][j] += cam_xyz[i][k] * xyz_rgb[k][j];
+
+  for (i=0; i < colors; i++) {		/* Normalize cam_rgb so that */
+    for (num=j=0; j < 3; j++)		/* cam_rgb * (1,1,1) is (1,1,1,1) */
+      num += cam_rgb[i][j];
+    for (j=0; j < 3; j++)
+      cam_rgb[i][j] /= num;
+    pre_mul[i] = 1 / num;
+  }
+  pseudoinverse (cam_rgb, inverse, colors);
+  for (raw_color = i=0; i < 3; i++)
+    for (j=0; j < colors; j++)
+      rgb_cam[i][j] = inverse[j][i];
+}
+
+#ifdef COLORCHECK
+void CLASS colorcheck()
+{
+#define NSQ 24
+// Coordinates of the GretagMacbeth ColorChecker squares
+// width, height, 1st_column, 1st_row
+  int cut[NSQ][4];			// you must set these
+// ColorChecker Chart under 6500-kelvin illumination
+  static const double gmb_xyY[NSQ][3] = {
+    { 0.400, 0.350, 10.1 },		// Dark Skin
+    { 0.377, 0.345, 35.8 },		// Light Skin
+    { 0.247, 0.251, 19.3 },		// Blue Sky
+    { 0.337, 0.422, 13.3 },		// Foliage
+    { 0.265, 0.240, 24.3 },		// Blue Flower
+    { 0.261, 0.343, 43.1 },		// Bluish Green
+    { 0.506, 0.407, 30.1 },		// Orange
+    { 0.211, 0.175, 12.0 },		// Purplish Blue
+    { 0.453, 0.306, 19.8 },		// Moderate Red
+    { 0.285, 0.202, 6.6 },		// Purple
+    { 0.380, 0.489, 44.3 },		// Yellow Green
+    { 0.473, 0.438, 43.1 },		// Orange Yellow
+    { 0.187, 0.129, 6.1 },		// Blue
+    { 0.305, 0.478, 23.4 },		// Green
+    { 0.539, 0.313, 12.0 },		// Red
+    { 0.448, 0.470, 59.1 },		// Yellow
+    { 0.364, 0.233, 19.8 },		// Magenta
+    { 0.196, 0.252, 19.8 },		// Cyan
+    { 0.310, 0.316, 90.0 },		// White
+    { 0.310, 0.316, 59.1 },		// Neutral 8
+    { 0.310, 0.316, 36.2 },		// Neutral 6.5
+    { 0.310, 0.316, 19.8 },		// Neutral 5
+    { 0.310, 0.316, 9.0 },		// Neutral 3.5
+    { 0.310, 0.316, 3.1 } };		// Black
+  double gmb_cam[NSQ][4], gmb_xyz[NSQ][3];
+  double inverse[NSQ][3], cam_xyz[4][3], num;
+  int c, i, j, k, sq, row, col, count[4];
+
+  memset (gmb_cam, 0, sizeof gmb_cam);
+  for (sq=0; sq < NSQ; sq++) {
+    FORCC count[c] = 0;
+    for   (row=cut[sq][3]; row < cut[sq][3]+cut[sq][1]; row++)
+      for (col=cut[sq][2]; col < cut[sq][2]+cut[sq][0]; col++) {
+	c = FC(row,col);
+	if (c >= colors) c -= 2;
+	gmb_cam[sq][c] += BAYER(row,col);
+	count[c]++;
+      }
+    FORCC gmb_cam[sq][c] = gmb_cam[sq][c]/count[c] - black;
+    gmb_xyz[sq][0] = gmb_xyY[sq][2] * gmb_xyY[sq][0] / gmb_xyY[sq][1];
+    gmb_xyz[sq][1] = gmb_xyY[sq][2];
+    gmb_xyz[sq][2] = gmb_xyY[sq][2] *
+		(1 - gmb_xyY[sq][0] - gmb_xyY[sq][1]) / gmb_xyY[sq][1];
+  }
+  pseudoinverse (gmb_xyz, inverse, NSQ);
+  for (i=0; i < colors; i++)
+    for (j=0; j < 3; j++)
+      for (cam_xyz[i][j] = k=0; k < NSQ; k++)
+	cam_xyz[i][j] += gmb_cam[k][i] * inverse[k][j];
+  cam_xyz_coeff (cam_xyz);
+  if (verbose) {
+    printf ("    { \"%s %s\", %d,\n\t{", make, model, black);
+    num = 10000 / (cam_xyz[1][0] + cam_xyz[1][1] + cam_xyz[1][2]);
+    FORCC for (j=0; j < 3; j++)
+      printf ("%c%d", (c | j) ? ',':' ', (int) (cam_xyz[c][j] * num + 0.5));
+    puts (" } },");
+  }
+#undef NSQ
+}
+#endif
+
+void CLASS hat_transform (float *temp, float *base, int st, int size, int sc)
+{
+  int i;
+  for (i=0; i < sc; i++)
+    temp[i] = 2*base[st*i] + base[st*(sc-i)] + base[st*(i+sc)];
+  for (; i+sc < size; i++)
+    temp[i] = 2*base[st*i] + base[st*(i-sc)] + base[st*(i+sc)];
+  for (; i < size; i++)
+    temp[i] = 2*base[st*i] + base[st*(i-sc)] + base[st*(2*size-2-(i+sc))];
+}
+
+void CLASS wavelet_denoise()
+{
+  float *fimg=0, *temp, thold, mul[2], avg, diff;
+  int scale=1, size, lev, hpass, lpass, row, col, nc, c, i, wlast;
+  ushort *window[4];
+  static const float noise[] =
+  { 0.8002,0.2735,0.1202,0.0585,0.0291,0.0152,0.0080,0.0044 };
+
+  if (verbose) fprintf (stderr,_("Wavelet denoising...\n"));
+
+  while (maximum << scale < 0x10000) scale++;
+  maximum <<= --scale;
+  black <<= scale;
+  if ((size = iheight*iwidth) < 0x15550000)
+    fimg = (float *) malloc ((size*3 + iheight + iwidth) * sizeof *fimg);
+  merror (fimg, "wavelet_denoise()");
+  temp = fimg + size*3;
+  if ((nc = colors) == 3 && filters) nc++;
+  FORC(nc) {			/* denoise R,G1,B,G3 individually */
+    for (i=0; i < size; i++)
+      fimg[i] = 256 * sqrt(image[i][c] << scale);
+    for (hpass=lev=0; lev < 5; lev++) {
+      lpass = size*((lev & 1)+1);
+      for (row=0; row < iheight; row++) {
+	hat_transform (temp, fimg+hpass+row*iwidth, 1, iwidth, 1 << lev);
+        for (col=0; col < iwidth; col++)
+	  fimg[lpass + row*iwidth + col] = temp[col] * 0.25;
+      }
+      for (col=0; col < iwidth; col++) {
+	hat_transform (temp, fimg+lpass+col, iwidth, iheight, 1 << lev);
+	for (row=0; row < iheight; row++)
+	  fimg[lpass + row*iwidth + col] = temp[row] * 0.25;
+      }
+      thold = threshold * noise[lev];
+      for (i=0; i < size; i++) {
+	fimg[hpass+i] -= fimg[lpass+i];
+	if	(fimg[hpass+i] < -thold) fimg[hpass+i] += thold;
+	else if (fimg[hpass+i] >  thold) fimg[hpass+i] -= thold;
+	else	 fimg[hpass+i] = 0;
+	if (hpass) fimg[i] += fimg[hpass+i];
+      }
+      hpass = lpass;
+    }
+    for (i=0; i < size; i++)
+      image[i][c] = CLIP(SQR(fimg[i]+fimg[lpass+i])/0x10000);
+  }
+  if (filters && colors == 3) {  /* pull G1 and G3 closer together */
+    for (row=0; row < 2; row++)
+      mul[row] = 0.125 * pre_mul[FC(row+1,0) | 1] / pre_mul[FC(row,0) | 1];
+    for (i=0; i < 4; i++)
+      window[i] = (ushort *) fimg + width*i;
+    for (wlast=-1, row=1; row < height-1; row++) {
+      while (wlast < row+1) {
+	for (wlast++, i=0; i < 4; i++)
+	  window[(i+3) & 3] = window[i];
+	for (col = FC(wlast,1) & 1; col < width; col+=2)
+	  window[2][col] = BAYER(wlast,col);
+      }
+      thold = threshold/512;
+      for (col = (FC(row,0) & 1)+1; col < width-1; col+=2) {
+	avg = ( window[0][col-1] + window[0][col+1] +
+		window[2][col-1] + window[2][col+1] - black*4 )
+	      * mul[row & 1] + (window[1][col] - black) * 0.5 + black;
+	avg = avg < 0 ? 0 : sqrt(avg);
+	diff = sqrt(BAYER(row,col)) - avg;
+	if      (diff < -thold) diff += thold;
+	else if (diff >  thold) diff -= thold;
+	else diff = 0;
+	BAYER(row,col) = CLIP(SQR(avg+diff) + 0.5);
+      }
+    }
+  }
+  free (fimg);
+}
+
+void CLASS scale_colors()
+{
+  unsigned bottom, right, size, row, col, ur, uc, i, x, y, c, sum[8];
+  int val, dark, sat;
+  double dsum[8], dmin, dmax;
+  float scale_mul[4], fr, fc;
+  ushort *img=0, *pix;
+
+  if (user_mul[0])
+    memcpy (pre_mul, user_mul, sizeof pre_mul);
+  if (use_auto_wb || (use_camera_wb && cam_mul[0] == -1)) {
+    memset (dsum, 0, sizeof dsum);
+    bottom = MIN (greybox[1]+greybox[3], height);
+    right  = MIN (greybox[0]+greybox[2], width);
+    for (row=greybox[1]; row < bottom; row += 8)
+      for (col=greybox[0]; col < right; col += 8) {
+	memset (sum, 0, sizeof sum);
+	for (y=row; y < row+8 && y < bottom; y++)
+	  for (x=col; x < col+8 && x < right; x++)
+	    FORC4 {
+	      if (filters) {
+		c = FC(y,x);
+		val = BAYER(y,x);
+	      } else
+		val = image[y*width+x][c];
+	      if (val > maximum-25) goto skip_block;
+	      if ((val -= black) < 0) val = 0;
+	      sum[c] += val;
+	      sum[c+4]++;
+	      if (filters) break;
+	    }
+	FORC(8) dsum[c] += sum[c];
+skip_block: ;
+      }
+    FORC4 if (dsum[c]) pre_mul[c] = dsum[c+4] / dsum[c];
+  }
+  if (use_camera_wb && cam_mul[0] != -1) {
+    memset (sum, 0, sizeof sum);
+    for (row=0; row < 8; row++)
+      for (col=0; col < 8; col++) {
+	c = FC(row,col);
+	if ((val = white[row][col] - black) > 0)
+	  sum[c] += val;
+	sum[c+4]++;
+      }
+    if (sum[0] && sum[1] && sum[2] && sum[3])
+      FORC4 pre_mul[c] = (float) sum[c+4] / sum[c];
+    else if (cam_mul[0] && cam_mul[2])
+      memcpy (pre_mul, cam_mul, sizeof pre_mul);
+    else
+      fprintf (stderr,_("%s: Cannot use camera white balance.\n"), ifname);
+  }
+  if (pre_mul[3] == 0) pre_mul[3] = colors < 4 ? pre_mul[1] : 1;
+  dark = black;
+  sat = maximum;
+  if (threshold) wavelet_denoise();
+  maximum -= black;
+  for (dmin=DBL_MAX, dmax=c=0; c < 4; c++) {
+    if (dmin > pre_mul[c])
+	dmin = pre_mul[c];
+    if (dmax < pre_mul[c])
+	dmax = pre_mul[c];
+  }
+  if (!highlight) dmax = dmin;
+  FORC4 scale_mul[c] = (pre_mul[c] /= dmax) * 65535.0 / maximum;
+  if (verbose) {
+    fprintf (stderr,
+      _("Scaling with darkness %d, saturation %d, and\nmultipliers"), dark, sat);
+    FORC4 fprintf (stderr, " %f", pre_mul[c]);
+    fputc ('\n', stderr);
+  }
+  size = iheight*iwidth;
+  for (i=0; i < size*4; i++) {
+    val = image[0][i];
+    if (!val) continue;
+    val -= black;
+    val *= scale_mul[i & 3];
+    image[0][i] = CLIP(val);
+  }
+  if ((aber[0] != 1 || aber[2] != 1) && colors == 3) {
+    if (verbose)
+      fprintf (stderr,_("Correcting chromatic aberration...\n"));
+    for (c=0; c < 4; c+=2) {
+      if (aber[c] == 1) continue;
+      img = (ushort *) malloc (size * sizeof *img);
+      merror (img, "scale_colors()");
+      for (i=0; i < size; i++)
+	img[i] = image[i][c];
+      for (row=0; row < iheight; row++) {
+	ur = fr = (row - iheight*0.5) * aber[c] + iheight*0.5;
+	if (ur > iheight-2) continue;
+	fr -= ur;
+	for (col=0; col < iwidth; col++) {
+	  uc = fc = (col - iwidth*0.5) * aber[c] + iwidth*0.5;
+	  if (uc > iwidth-2) continue;
+	  fc -= uc;
+	  pix = img + ur*iwidth + uc;
+	  image[row*iwidth+col][c] =
+	    (pix[     0]*(1-fc) + pix[       1]*fc) * (1-fr) +
+	    (pix[iwidth]*(1-fc) + pix[iwidth+1]*fc) * fr;
+	}
+      }
+      free(img);
+    }
+  }
+}
+
+void CLASS pre_interpolate()
+{
+  ushort (*img)[4];
+  int row, col, c;
+
+  if (shrink) {
+    if (half_size) {
+      height = iheight;
+      width  = iwidth;
+    } else {
+      img = (ushort (*)[4]) calloc (height*width, sizeof *img);
+      merror (img, "pre_interpolate()");
+      for (row=0; row < height; row++)
+	for (col=0; col < width; col++) {
+	  c = fc(row,col);
+	  img[row*width+col][c] = image[(row >> 1)*iwidth+(col >> 1)][c];
+	}
+      free (image);
+      image = img;
+      shrink = 0;
+    }
+  }
+  if (filters && colors == 3) {
+    if ((mix_green = four_color_rgb)) colors++;
+    else {
+      for (row = FC(1,0) >> 1; row < height; row+=2)
+	for (col = FC(row,1) & 1; col < width; col+=2)
+	  image[row*width+col][1] = image[row*width+col][3];
+      filters &= ~((filters & 0x55555555) << 1);
+    }
+  }
+  if (half_size) filters = 0;
+}
+
+void CLASS border_interpolate (int border)
+{
+  unsigned row, col, y, x, f, c, sum[8];
+
+  for (row=0; row < height; row++)
+    for (col=0; col < width; col++) {
+      if (col==border && row >= border && row < height-border)
+	col = width-border;
+      memset (sum, 0, sizeof sum);
+      for (y=row-1; y != row+2; y++)
+	for (x=col-1; x != col+2; x++)
+	  if (y < height && x < width) {
+	    f = fc(y,x);
+	    sum[f] += image[y*width+x][f];
+	    sum[f+4]++;
+	  }
+      f = fc(row,col);
+      FORCC if (c != f && sum[c+4])
+	image[row*width+col][c] = sum[c] / sum[c+4];
+    }
+}
+
+void CLASS lin_interpolate()
+{
+  int code[16][16][32], *ip, sum[4];
+  int c, i, x, y, row, col, shift, color;
+  ushort *pix;
+
+  if (verbose) fprintf (stderr,_("Bilinear interpolation...\n"));
+
+  border_interpolate(1);
+  for (row=0; row < 16; row++)
+    for (col=0; col < 16; col++) {
+      ip = code[row][col];
+      memset (sum, 0, sizeof sum);
+      for (y=-1; y <= 1; y++)
+	for (x=-1; x <= 1; x++) {
+	  shift = (y==0) + (x==0);
+	  if (shift == 2) continue;
+	  color = fc(row+y,col+x);
+	  *ip++ = (width*y + x)*4 + color;
+	  *ip++ = shift;
+	  *ip++ = color;
+	  sum[color] += 1 << shift;
+	}
+      FORCC
+	if (c != fc(row,col)) {
+	  *ip++ = c;
+	  *ip++ = 256 / sum[c];
+	}
+    }
+  for (row=1; row < height-1; row++)
+    for (col=1; col < width-1; col++) {
+      pix = image[row*width+col];
+      ip = code[row & 15][col & 15];
+      memset (sum, 0, sizeof sum);
+      for (i=8; i--; ip+=3)
+	sum[ip[2]] += pix[ip[0]] << ip[1];
+      for (i=colors; --i; ip+=2)
+	pix[ip[0]] = sum[ip[0]] * ip[1] >> 8;
+    }
+}
+
+/*
+   This algorithm is officially called:
+
+   "Interpolation using a Threshold-based variable number of gradients"
+
+   described in http://scien.stanford.edu/class/psych221/projects/99/tingchen/algodep/vargra.html
+
+   I've extended the basic idea to work with non-Bayer filter arrays.
+   Gradients are numbered clockwise from NW=0 to W=7.
+ */
+void CLASS vng_interpolate()
+{
+  static const signed char *cp, terms[] = {
+    -2,-2,+0,-1,0,0x01, -2,-2,+0,+0,1,0x01, -2,-1,-1,+0,0,0x01,
+    -2,-1,+0,-1,0,0x02, -2,-1,+0,+0,0,0x03, -2,-1,+0,+1,1,0x01,
+    -2,+0,+0,-1,0,0x06, -2,+0,+0,+0,1,0x02, -2,+0,+0,+1,0,0x03,
+    -2,+1,-1,+0,0,0x04, -2,+1,+0,-1,1,0x04, -2,+1,+0,+0,0,0x06,
+    -2,+1,+0,+1,0,0x02, -2,+2,+0,+0,1,0x04, -2,+2,+0,+1,0,0x04,
+    -1,-2,-1,+0,0,0x80, -1,-2,+0,-1,0,0x01, -1,-2,+1,-1,0,0x01,
+    -1,-2,+1,+0,1,0x01, -1,-1,-1,+1,0,0x88, -1,-1,+1,-2,0,0x40,
+    -1,-1,+1,-1,0,0x22, -1,-1,+1,+0,0,0x33, -1,-1,+1,+1,1,0x11,
+    -1,+0,-1,+2,0,0x08, -1,+0,+0,-1,0,0x44, -1,+0,+0,+1,0,0x11,
+    -1,+0,+1,-2,1,0x40, -1,+0,+1,-1,0,0x66, -1,+0,+1,+0,1,0x22,
+    -1,+0,+1,+1,0,0x33, -1,+0,+1,+2,1,0x10, -1,+1,+1,-1,1,0x44,
+    -1,+1,+1,+0,0,0x66, -1,+1,+1,+1,0,0x22, -1,+1,+1,+2,0,0x10,
+    -1,+2,+0,+1,0,0x04, -1,+2,+1,+0,1,0x04, -1,+2,+1,+1,0,0x04,
+    +0,-2,+0,+0,1,0x80, +0,-1,+0,+1,1,0x88, +0,-1,+1,-2,0,0x40,
+    +0,-1,+1,+0,0,0x11, +0,-1,+2,-2,0,0x40, +0,-1,+2,-1,0,0x20,
+    +0,-1,+2,+0,0,0x30, +0,-1,+2,+1,1,0x10, +0,+0,+0,+2,1,0x08,
+    +0,+0,+2,-2,1,0x40, +0,+0,+2,-1,0,0x60, +0,+0,+2,+0,1,0x20,
+    +0,+0,+2,+1,0,0x30, +0,+0,+2,+2,1,0x10, +0,+1,+1,+0,0,0x44,
+    +0,+1,+1,+2,0,0x10, +0,+1,+2,-1,1,0x40, +0,+1,+2,+0,0,0x60,
+    +0,+1,+2,+1,0,0x20, +0,+1,+2,+2,0,0x10, +1,-2,+1,+0,0,0x80,
+    +1,-1,+1,+1,0,0x88, +1,+0,+1,+2,0,0x08, +1,+0,+2,-1,0,0x40,
+    +1,+0,+2,+1,0,0x10
+  }, chood[] = { -1,-1, -1,0, -1,+1, 0,+1, +1,+1, +1,0, +1,-1, 0,-1 };
+  ushort (*brow[5])[4], *pix;
+  int prow=7, pcol=1, *ip, *code[16][16], gval[8], gmin, gmax, sum[4];
+  int row, col, x, y, x1, x2, y1, y2, t, weight, grads, color, diag;
+  int g, diff, thold, num, c;
+
+  lin_interpolate();
+  if (verbose) fprintf (stderr,_("VNG interpolation...\n"));
+
+  if (filters == 1) prow = pcol = 15;
+  ip = (int *) calloc ((prow+1)*(pcol+1), 1280);
+  merror (ip, "vng_interpolate()");
+  for (row=0; row <= prow; row++)		/* Precalculate for VNG */
+    for (col=0; col <= pcol; col++) {
+      code[row][col] = ip;
+      for (cp=terms, t=0; t < 64; t++) {
+	y1 = *cp++;  x1 = *cp++;
+	y2 = *cp++;  x2 = *cp++;
+	weight = *cp++;
+	grads = *cp++;
+	color = fc(row+y1,col+x1);
+	if (fc(row+y2,col+x2) != color) continue;
+	diag = (fc(row,col+1) == color && fc(row+1,col) == color) ? 2:1;
+	if (abs(y1-y2) == diag && abs(x1-x2) == diag) continue;
+	*ip++ = (y1*width + x1)*4 + color;
+	*ip++ = (y2*width + x2)*4 + color;
+	*ip++ = weight;
+	for (g=0; g < 8; g++)
+	  if (grads & 1<<g) *ip++ = g;
+	*ip++ = -1;
+      }
+      *ip++ = INT_MAX;
+      for (cp=chood, g=0; g < 8; g++) {
+	y = *cp++;  x = *cp++;
+	*ip++ = (y*width + x) * 4;
+	color = fc(row,col);
+	if (fc(row+y,col+x) != color && fc(row+y*2,col+x*2) == color)
+	  *ip++ = (y*width + x) * 8 + color;
+	else
+	  *ip++ = 0;
+      }
+    }
+  brow[4] = (ushort (*)[4]) calloc (width*3, sizeof **brow);
+  merror (brow[4], "vng_interpolate()");
+  for (row=0; row < 3; row++)
+    brow[row] = brow[4] + row*width;
+  for (row=2; row < height-2; row++) {		/* Do VNG interpolation */
+    for (col=2; col < width-2; col++) {
+      pix = image[row*width+col];
+      ip = code[row & prow][col & pcol];
+      memset (gval, 0, sizeof gval);
+      while ((g = ip[0]) != INT_MAX) {		/* Calculate gradients */
+	diff = ABS(pix[g] - pix[ip[1]]) << ip[2];
+	gval[ip[3]] += diff;
+	ip += 5;
+	if ((g = ip[-1]) == -1) continue;
+	gval[g] += diff;
+	while ((g = *ip++) != -1)
+	  gval[g] += diff;
+      }
+      ip++;
+      gmin = gmax = gval[0];			/* Choose a threshold */
+      for (g=1; g < 8; g++) {
+	if (gmin > gval[g]) gmin = gval[g];
+	if (gmax < gval[g]) gmax = gval[g];
+      }
+      if (gmax == 0) {
+	memcpy (brow[2][col], pix, sizeof *image);
+	continue;
+      }
+      thold = gmin + (gmax >> 1);
+      memset (sum, 0, sizeof sum);
+      color = fc(row,col);
+      for (num=g=0; g < 8; g++,ip+=2) {		/* Average the neighbors */
+	if (gval[g] <= thold) {
+	  FORCC
+	    if (c == color && ip[1])
+	      sum[c] += (pix[c] + pix[ip[1]]) >> 1;
+	    else
+	      sum[c] += pix[ip[0] + c];
+	  num++;
+	}
+      }
+      FORCC {					/* Save to buffer */
+	t = pix[color];
+	if (c != color)
+	  t += (sum[c] - sum[color]) / num;
+	brow[2][col][c] = CLIP(t);
+      }
+    }
+    if (row > 3)				/* Write buffer to image */
+      memcpy (image[(row-2)*width+2], brow[0]+2, (width-4)*sizeof *image);
+    for (g=0; g < 4; g++)
+      brow[(g-1) & 3] = brow[g];
+  }
+  memcpy (image[(row-2)*width+2], brow[0]+2, (width-4)*sizeof *image);
+  memcpy (image[(row-1)*width+2], brow[1]+2, (width-4)*sizeof *image);
+  free (brow[4]);
+  free (code[0][0]);
+}
+
+/*
+   Patterned Pixel Grouping Interpolation by Alain Desbiolles
+*/
+void CLASS ppg_interpolate()
+{
+  int dir[5] = { 1, width, -1, -width, 1 };
+  int row, col, diff[2], guess[2], c, d, i;
+  ushort (*pix)[4];
+
+  border_interpolate(3);
+  if (verbose) fprintf (stderr,_("PPG interpolation...\n"));
+
+/*  Fill in the green layer with gradients and pattern recognition: */
+  for (row=3; row < height-3; row++)
+    for (col=3+(FC(row,3) & 1), c=FC(row,col); col < width-3; col+=2) {
+      pix = image + row*width+col;
+      for (i=0; (d=dir[i]) > 0; i++) {
+	guess[i] = (pix[-d][1] + pix[0][c] + pix[d][1]) * 2
+		      - pix[-2*d][c] - pix[2*d][c];
+	diff[i] = ( ABS(pix[-2*d][c] - pix[ 0][c]) +
+		    ABS(pix[ 2*d][c] - pix[ 0][c]) +
+		    ABS(pix[  -d][1] - pix[ d][1]) ) * 3 +
+		  ( ABS(pix[ 3*d][1] - pix[ d][1]) +
+		    ABS(pix[-3*d][1] - pix[-d][1]) ) * 2;
+      }
+      d = dir[i = diff[0] > diff[1]];
+      pix[0][1] = ULIM(guess[i] >> 2, pix[d][1], pix[-d][1]);
+    }
+/*  Calculate red and blue for each green pixel:		*/
+  for (row=1; row < height-1; row++)
+    for (col=1+(FC(row,2) & 1), c=FC(row,col+1); col < width-1; col+=2) {
+      pix = image + row*width+col;
+      for (i=0; (d=dir[i]) > 0; c=2-c, i++)
+	pix[0][c] = CLIP((pix[-d][c] + pix[d][c] + 2*pix[0][1]
+			- pix[-d][1] - pix[d][1]) >> 1);
+    }
+/*  Calculate blue for red pixels and vice versa:		*/
+  for (row=1; row < height-1; row++)
+    for (col=1+(FC(row,1) & 1), c=2-FC(row,col); col < width-1; col+=2) {
+      pix = image + row*width+col;
+      for (i=0; (d=dir[i]+dir[i+1]) > 0; i++) {
+	diff[i] = ABS(pix[-d][c] - pix[d][c]) +
+		  ABS(pix[-d][1] - pix[0][1]) +
+		  ABS(pix[ d][1] - pix[0][1]);
+	guess[i] = pix[-d][c] + pix[d][c] + 2*pix[0][1]
+		 - pix[-d][1] - pix[d][1];
+      }
+      if (diff[0] != diff[1])
+	pix[0][c] = CLIP(guess[diff[0] > diff[1]] >> 1);
+      else
+	pix[0][c] = CLIP((guess[0]+guess[1]) >> 2);
+    }
+}
+
+/*
+   Adaptive Homogeneity-Directed interpolation is based on
+   the work of Keigo Hirakawa, Thomas Parks, and Paul Lee.
+ */
+#define TS 256		/* Tile Size */
+
+void CLASS ahd_interpolate()
+{
+  int i, j, k, top, left, row, col, tr, tc, c, d, val, hm[2];
+  ushort (*pix)[4], (*rix)[3];
+  static const int dir[4] = { -1, 1, -TS, TS };
+  unsigned ldiff[2][4], abdiff[2][4], leps, abeps;
+  float r, cbrt[0x10000], xyz[3], xyz_cam[3][4];
+  ushort (*rgb)[TS][TS][3];
+   short (*lab)[TS][TS][3], (*lix)[3];
+   char (*homo)[TS][TS], *buffer;
+
+  if (verbose) fprintf (stderr,_("AHD interpolation...\n"));
+
+  for (i=0; i < 0x10000; i++) {
+    r = i / 65535.0;
+    cbrt[i] = r > 0.008856 ? pow(r,1/3.0) : 7.787*r + 16/116.0;
+  }
+  for (i=0; i < 3; i++)
+    for (j=0; j < colors; j++)
+      for (xyz_cam[i][j] = k=0; k < 3; k++)
+	xyz_cam[i][j] += xyz_rgb[i][k] * rgb_cam[k][j] / d65_white[i];
+
+  border_interpolate(5);
+  buffer = (char *) malloc (26*TS*TS);		/* 1664 kB */
+  merror (buffer, "ahd_interpolate()");
+  rgb  = (ushort(*)[TS][TS][3]) buffer;
+  lab  = (short (*)[TS][TS][3])(buffer + 12*TS*TS);
+  homo = (char  (*)[TS][TS])   (buffer + 24*TS*TS);
+
+  for (top=2; top < height-5; top += TS-6)
+    for (left=2; left < width-5; left += TS-6) {
+
+/*  Interpolate green horizontally and vertically:		*/
+      for (row = top; row < top+TS && row < height-2; row++) {
+	col = left + (FC(row,left) & 1);
+	for (c = FC(row,col); col < left+TS && col < width-2; col+=2) {
+	  pix = image + row*width+col;
+	  val = ((pix[-1][1] + pix[0][c] + pix[1][1]) * 2
+		- pix[-2][c] - pix[2][c]) >> 2;
+	  rgb[0][row-top][col-left][1] = ULIM(val,pix[-1][1],pix[1][1]);
+	  val = ((pix[-width][1] + pix[0][c] + pix[width][1]) * 2
+		- pix[-2*width][c] - pix[2*width][c]) >> 2;
+	  rgb[1][row-top][col-left][1] = ULIM(val,pix[-width][1],pix[width][1]);
+	}
+      }
+/*  Interpolate red and blue, and convert to CIELab:		*/
+      for (d=0; d < 2; d++)
+	for (row=top+1; row < top+TS-1 && row < height-3; row++)
+	  for (col=left+1; col < left+TS-1 && col < width-3; col++) {
+	    pix = image + row*width+col;
+	    rix = &rgb[d][row-top][col-left];
+	    lix = &lab[d][row-top][col-left];
+	    if ((c = 2 - FC(row,col)) == 1) {
+	      c = FC(row+1,col);
+	      val = pix[0][1] + (( pix[-1][2-c] + pix[1][2-c]
+				 - rix[-1][1] - rix[1][1] ) >> 1);
+	      rix[0][2-c] = CLIP(val);
+	      val = pix[0][1] + (( pix[-width][c] + pix[width][c]
+				 - rix[-TS][1] - rix[TS][1] ) >> 1);
+	    } else
+	      val = rix[0][1] + (( pix[-width-1][c] + pix[-width+1][c]
+				 + pix[+width-1][c] + pix[+width+1][c]
+				 - rix[-TS-1][1] - rix[-TS+1][1]
+				 - rix[+TS-1][1] - rix[+TS+1][1] + 1) >> 2);
+	    rix[0][c] = CLIP(val);
+	    c = FC(row,col);
+	    rix[0][c] = pix[0][c];
+	    xyz[0] = xyz[1] = xyz[2] = 0.5;
+	    FORCC {
+	      xyz[0] += xyz_cam[0][c] * rix[0][c];
+	      xyz[1] += xyz_cam[1][c] * rix[0][c];
+	      xyz[2] += xyz_cam[2][c] * rix[0][c];
+	    }
+	    xyz[0] = cbrt[CLIP((int) xyz[0])];
+	    xyz[1] = cbrt[CLIP((int) xyz[1])];
+	    xyz[2] = cbrt[CLIP((int) xyz[2])];
+	    lix[0][0] = 64 * (116 * xyz[1] - 16);
+	    lix[0][1] = 64 * 500 * (xyz[0] - xyz[1]);
+	    lix[0][2] = 64 * 200 * (xyz[1] - xyz[2]);
+	  }
+/*  Build homogeneity maps from the CIELab images:		*/
+      memset (homo, 0, 2*TS*TS);
+      for (row=top+2; row < top+TS-2 && row < height-4; row++) {
+	tr = row-top;
+	for (col=left+2; col < left+TS-2 && col < width-4; col++) {
+	  tc = col-left;
+	  for (d=0; d < 2; d++) {
+	    lix = &lab[d][tr][tc];
+	    for (i=0; i < 4; i++) {
+	       ldiff[d][i] = ABS(lix[0][0]-lix[dir[i]][0]);
+	      abdiff[d][i] = SQR(lix[0][1]-lix[dir[i]][1])
+			   + SQR(lix[0][2]-lix[dir[i]][2]);
+	    }
+	  }
+	  leps = MIN(MAX(ldiff[0][0],ldiff[0][1]),
+		     MAX(ldiff[1][2],ldiff[1][3]));
+	  abeps = MIN(MAX(abdiff[0][0],abdiff[0][1]),
+		      MAX(abdiff[1][2],abdiff[1][3]));
+	  for (d=0; d < 2; d++)
+	    for (i=0; i < 4; i++)
+	      if (ldiff[d][i] <= leps && abdiff[d][i] <= abeps)
+		homo[d][tr][tc]++;
+	}
+      }
+/*  Combine the most homogenous pixels for the final result:	*/
+      for (row=top+3; row < top+TS-3 && row < height-5; row++) {
+	tr = row-top;
+	for (col=left+3; col < left+TS-3 && col < width-5; col++) {
+	  tc = col-left;
+	  for (d=0; d < 2; d++)
+	    for (hm[d]=0, i=tr-1; i <= tr+1; i++)
+	      for (j=tc-1; j <= tc+1; j++)
+		hm[d] += homo[d][i][j];
+	  if (hm[0] != hm[1])
+	    FORC3 image[row*width+col][c] = rgb[hm[1] > hm[0]][tr][tc][c];
+	  else
+	    FORC3 image[row*width+col][c] =
+		(rgb[0][tr][tc][c] + rgb[1][tr][tc][c]) >> 1;
+	}
+      }
+    }
+  free (buffer);
+}
+#undef TS
+
+void CLASS median_filter()
+{
+  ushort (*pix)[4];
+  int pass, c, i, j, k, med[9];
+  static const uchar opt[] =	/* Optimal 9-element median search */
+  { 1,2, 4,5, 7,8, 0,1, 3,4, 6,7, 1,2, 4,5, 7,8,
+    0,3, 5,8, 4,7, 3,6, 1,4, 2,5, 4,7, 4,2, 6,4, 4,2 };
+
+  for (pass=1; pass <= med_passes; pass++) {
+    if (verbose)
+      fprintf (stderr,_("Median filter pass %d...\n"), pass);
+    for (c=0; c < 3; c+=2) {
+      for (pix = image; pix < image+width*height; pix++)
+	pix[0][3] = pix[0][c];
+      for (pix = image+width; pix < image+width*(height-1); pix++) {
+	if ((pix-image+1) % width < 2) continue;
+	for (k=0, i = -width; i <= width; i += width)
+	  for (j = i-1; j <= i+1; j++)
+	    med[k++] = pix[j][3] - pix[j][1];
+	for (i=0; i < sizeof opt; i+=2)
+	  if     (med[opt[i]] > med[opt[i+1]])
+	    SWAP (med[opt[i]] , med[opt[i+1]]);
+	pix[0][c] = CLIP(med[4] + pix[0][1]);
+      }
+    }
+  }
+}
+
+void CLASS blend_highlights()
+{
+  int clip=INT_MAX, row, col, c, i, j;
+  static const float trans[2][4][4] =
+  { { { 1,1,1 }, { 1.7320508,-1.7320508,0 }, { -1,-1,2 } },
+    { { 1,1,1,1 }, { 1,-1,1,-1 }, { 1,1,-1,-1 }, { 1,-1,-1,1 } } };
+  static const float itrans[2][4][4] =
+  { { { 1,0.8660254,-0.5 }, { 1,-0.8660254,-0.5 }, { 1,0,1 } },
+    { { 1,1,1,1 }, { 1,-1,1,-1 }, { 1,1,-1,-1 }, { 1,-1,-1,1 } } };
+  float cam[2][4], lab[2][4], sum[2], chratio;
+
+  if ((unsigned) (colors-3) > 1) return;
+  if (verbose) fprintf (stderr,_("Blending highlights...\n"));
+  FORCC if (clip > (i = 65535*pre_mul[c])) clip = i;
+  for (row=0; row < height; row++)
+    for (col=0; col < width; col++) {
+      FORCC if (image[row*width+col][c] > clip) break;
+      if (c == colors) continue;
+      FORCC {
+	cam[0][c] = image[row*width+col][c];
+	cam[1][c] = MIN(cam[0][c],clip);
+      }
+      for (i=0; i < 2; i++) {
+	FORCC for (lab[i][c]=j=0; j < colors; j++)
+	  lab[i][c] += trans[colors-3][c][j] * cam[i][j];
+	for (sum[i]=0,c=1; c < colors; c++)
+	  sum[i] += SQR(lab[i][c]);
+      }
+      chratio = sqrt(sum[1]/sum[0]);
+      for (c=1; c < colors; c++)
+	lab[0][c] *= chratio;
+      FORCC for (cam[0][c]=j=0; j < colors; j++)
+	cam[0][c] += itrans[colors-3][c][j] * lab[0][j];
+      FORCC image[row*width+col][c] = cam[0][c] / colors;
+    }
+}
+
+#define SCALE (4 >> shrink)
+void CLASS recover_highlights()
+{
+  float *map, sum, wgt, grow;
+  int hsat[4], count, spread, change, val, i;
+  unsigned high, wide, mrow, mcol, row, col, kc, c, d, y, x;
+  ushort *pixel;
+  static const signed char dir[8][2] =
+    { {-1,-1}, {-1,0}, {-1,1}, {0,1}, {1,1}, {1,0}, {1,-1}, {0,-1} };
+
+  if (verbose) fprintf (stderr,_("Rebuilding highlights...\n"));
+
+  grow = pow (2, 4-highlight);
+  FORCC hsat[c] = 32000 * pre_mul[c];
+  for (kc=0, c=1; c < colors; c++)
+    if (pre_mul[kc] < pre_mul[c]) kc = c;
+  high = height / SCALE;
+  wide =  width / SCALE;
+  map = (float *) calloc (high*wide, sizeof *map);
+  merror (map, "recover_highlights()");
+  FORCC if (c != kc) {
+    memset (map, 0, high*wide*sizeof *map);
+    for (mrow=0; mrow < high; mrow++)
+      for (mcol=0; mcol < wide; mcol++) {
+	sum = wgt = count = 0;
+	for (row = mrow*SCALE; row < (mrow+1)*SCALE; row++)
+	  for (col = mcol*SCALE; col < (mcol+1)*SCALE; col++) {
+	    pixel = image[row*width+col];
+	    if (pixel[c] / hsat[c] == 1 && pixel[kc] > 24000) {
+	      sum += pixel[c];
+	      wgt += pixel[kc];
+	      count++;
+	    }
+	  }
+	if (count == SCALE*SCALE)
+	  map[mrow*wide+mcol] = sum / wgt;
+      }
+    for (spread = 32/grow; spread--; ) {
+      for (mrow=0; mrow < high; mrow++)
+	for (mcol=0; mcol < wide; mcol++) {
+	  if (map[mrow*wide+mcol]) continue;
+	  sum = count = 0;
+	  for (d=0; d < 8; d++) {
+	    y = mrow + dir[d][0];
+	    x = mcol + dir[d][1];
+	    if (y < high && x < wide && map[y*wide+x] > 0) {
+	      sum  += (1 + (d & 1)) * map[y*wide+x];
+	      count += 1 + (d & 1);
+	    }
+	  }
+	  if (count > 3)
+	    map[mrow*wide+mcol] = - (sum+grow) / (count+grow);
+	}
+      for (change=i=0; i < high*wide; i++)
+	if (map[i] < 0) {
+	  map[i] = -map[i];
+	  change = 1;
+	}
+      if (!change) break;
+    }
+    for (i=0; i < high*wide; i++)
+      if (map[i] == 0) map[i] = 1;
+    for (mrow=0; mrow < high; mrow++)
+      for (mcol=0; mcol < wide; mcol++) {
+	for (row = mrow*SCALE; row < (mrow+1)*SCALE; row++)
+	  for (col = mcol*SCALE; col < (mcol+1)*SCALE; col++) {
+	    pixel = image[row*width+col];
+	    if (pixel[c] / hsat[c] > 1) {
+	      val = pixel[kc] * map[mrow*wide+mcol];
+	      if (pixel[c] < val) pixel[c] = CLIP(val);
+	    }
+	  }
+      }
+  }
+  free (map);
+}
+#undef SCALE
+
+void CLASS tiff_get (unsigned base,
+	unsigned *tag, unsigned *type, unsigned *len, unsigned *save)
+{
+  *tag  = get2();
+  *type = get2();
+  *len  = get4();
+  *save = ftell(ifp) + 4;
+  if (*len * ("11124811248488"[*type < 14 ? *type:0]-'0') > 4)
+    fseek (ifp, get4()+base, SEEK_SET);
+}
+
+void CLASS parse_thumb_note (int base, unsigned toff, unsigned tlen)
+{
+  unsigned entries, tag, type, len, save;
+
+  entries = get2();
+  while (entries--) {
+    tiff_get (base, &tag, &type, &len, &save);
+    if (tag == toff) thumb_offset = get4()+base;
+    if (tag == tlen) thumb_length = get4();
+    fseek (ifp, save, SEEK_SET);
+  }
+}
+
+int CLASS parse_tiff_ifd (int base);
+
+void CLASS parse_makernote (int base, int uptag)
+{
+  static const uchar xlat[2][256] = {
+  { 0xc1,0xbf,0x6d,0x0d,0x59,0xc5,0x13,0x9d,0x83,0x61,0x6b,0x4f,0xc7,0x7f,0x3d,0x3d,
+    0x53,0x59,0xe3,0xc7,0xe9,0x2f,0x95,0xa7,0x95,0x1f,0xdf,0x7f,0x2b,0x29,0xc7,0x0d,
+    0xdf,0x07,0xef,0x71,0x89,0x3d,0x13,0x3d,0x3b,0x13,0xfb,0x0d,0x89,0xc1,0x65,0x1f,
+    0xb3,0x0d,0x6b,0x29,0xe3,0xfb,0xef,0xa3,0x6b,0x47,0x7f,0x95,0x35,0xa7,0x47,0x4f,
+    0xc7,0xf1,0x59,0x95,0x35,0x11,0x29,0x61,0xf1,0x3d,0xb3,0x2b,0x0d,0x43,0x89,0xc1,
+    0x9d,0x9d,0x89,0x65,0xf1,0xe9,0xdf,0xbf,0x3d,0x7f,0x53,0x97,0xe5,0xe9,0x95,0x17,
+    0x1d,0x3d,0x8b,0xfb,0xc7,0xe3,0x67,0xa7,0x07,0xf1,0x71,0xa7,0x53,0xb5,0x29,0x89,
+    0xe5,0x2b,0xa7,0x17,0x29,0xe9,0x4f,0xc5,0x65,0x6d,0x6b,0xef,0x0d,0x89,0x49,0x2f,
+    0xb3,0x43,0x53,0x65,0x1d,0x49,0xa3,0x13,0x89,0x59,0xef,0x6b,0xef,0x65,0x1d,0x0b,
+    0x59,0x13,0xe3,0x4f,0x9d,0xb3,0x29,0x43,0x2b,0x07,0x1d,0x95,0x59,0x59,0x47,0xfb,
+    0xe5,0xe9,0x61,0x47,0x2f,0x35,0x7f,0x17,0x7f,0xef,0x7f,0x95,0x95,0x71,0xd3,0xa3,
+    0x0b,0x71,0xa3,0xad,0x0b,0x3b,0xb5,0xfb,0xa3,0xbf,0x4f,0x83,0x1d,0xad,0xe9,0x2f,
+    0x71,0x65,0xa3,0xe5,0x07,0x35,0x3d,0x0d,0xb5,0xe9,0xe5,0x47,0x3b,0x9d,0xef,0x35,
+    0xa3,0xbf,0xb3,0xdf,0x53,0xd3,0x97,0x53,0x49,0x71,0x07,0x35,0x61,0x71,0x2f,0x43,
+    0x2f,0x11,0xdf,0x17,0x97,0xfb,0x95,0x3b,0x7f,0x6b,0xd3,0x25,0xbf,0xad,0xc7,0xc5,
+    0xc5,0xb5,0x8b,0xef,0x2f,0xd3,0x07,0x6b,0x25,0x49,0x95,0x25,0x49,0x6d,0x71,0xc7 },
+  { 0xa7,0xbc,0xc9,0xad,0x91,0xdf,0x85,0xe5,0xd4,0x78,0xd5,0x17,0x46,0x7c,0x29,0x4c,
+    0x4d,0x03,0xe9,0x25,0x68,0x11,0x86,0xb3,0xbd,0xf7,0x6f,0x61,0x22,0xa2,0x26,0x34,
+    0x2a,0xbe,0x1e,0x46,0x14,0x68,0x9d,0x44,0x18,0xc2,0x40,0xf4,0x7e,0x5f,0x1b,0xad,
+    0x0b,0x94,0xb6,0x67,0xb4,0x0b,0xe1,0xea,0x95,0x9c,0x66,0xdc,0xe7,0x5d,0x6c,0x05,
+    0xda,0xd5,0xdf,0x7a,0xef,0xf6,0xdb,0x1f,0x82,0x4c,0xc0,0x68,0x47,0xa1,0xbd,0xee,
+    0x39,0x50,0x56,0x4a,0xdd,0xdf,0xa5,0xf8,0xc6,0xda,0xca,0x90,0xca,0x01,0x42,0x9d,
+    0x8b,0x0c,0x73,0x43,0x75,0x05,0x94,0xde,0x24,0xb3,0x80,0x34,0xe5,0x2c,0xdc,0x9b,
+    0x3f,0xca,0x33,0x45,0xd0,0xdb,0x5f,0xf5,0x52,0xc3,0x21,0xda,0xe2,0x22,0x72,0x6b,
+    0x3e,0xd0,0x5b,0xa8,0x87,0x8c,0x06,0x5d,0x0f,0xdd,0x09,0x19,0x93,0xd0,0xb9,0xfc,
+    0x8b,0x0f,0x84,0x60,0x33,0x1c,0x9b,0x45,0xf1,0xf0,0xa3,0x94,0x3a,0x12,0x77,0x33,
+    0x4d,0x44,0x78,0x28,0x3c,0x9e,0xfd,0x65,0x57,0x16,0x94,0x6b,0xfb,0x59,0xd0,0xc8,
+    0x22,0x36,0xdb,0xd2,0x63,0x98,0x43,0xa1,0x04,0x87,0x86,0xf7,0xa6,0x26,0xbb,0xd6,
+    0x59,0x4d,0xbf,0x6a,0x2e,0xaa,0x2b,0xef,0xe6,0x78,0xb6,0x4e,0xe0,0x2f,0xdc,0x7c,
+    0xbe,0x57,0x19,0x32,0x7e,0x2a,0xd0,0xb8,0xba,0x29,0x00,0x3c,0x52,0x7d,0xa8,0x49,
+    0x3b,0x2d,0xeb,0x25,0x49,0xfa,0xa3,0xaa,0x39,0xa7,0xc5,0xa7,0x50,0x11,0x36,0xfb,
+    0xc6,0x67,0x4a,0xf5,0xa5,0x12,0x65,0x7e,0xb0,0xdf,0xaf,0x4e,0xb3,0x61,0x7f,0x2f } };
+  unsigned offset=0, entries, tag, type, len, save, c;
+  unsigned ver97=0, serial=0, i, wbi=0, wb[4]={0,0,0,0};
+  uchar buf97[324], ci, cj, ck;
+  short sorder=order;
+  char buf[10];
+/*
+   The MakerNote might have its own TIFF header (possibly with
+   its own byte-order!), or it might just be a table.
+ */
+  fread (buf, 1, 10, ifp);
+  if (!strncmp (buf,"KDK" ,3) ||	/* these aren't TIFF tables */
+      !strncmp (buf,"VER" ,3) ||
+      !strncmp (buf,"IIII",4) ||
+      !strncmp (buf,"MMMM",4)) return;
+  if (!strncmp (buf,"KC"  ,2) ||	/* Konica KD-400Z, KD-510Z */
+      !strncmp (buf,"MLY" ,3)) {	/* Minolta DiMAGE G series */
+    order = 0x4d4d;
+    while ((i=ftell(ifp)) < data_offset && i < 16384) {
+      wb[0] = wb[2];  wb[2] = wb[1];  wb[1] = wb[3];
+      wb[3] = get2();
+      if (wb[1] == 256 && wb[3] == 256 &&
+	  wb[0] > 256 && wb[0] < 640 && wb[2] > 256 && wb[2] < 640)
+	FORC4 cam_mul[c] = wb[c];
+    }
+    goto quit;
+  }
+  if (!strcmp (buf,"Nikon")) {
+    base = ftell(ifp);
+    order = get2();
+    if (get2() != 42) goto quit;
+    offset = get4();
+    fseek (ifp, offset-8, SEEK_CUR);
+  } else if (!strcmp (buf,"OLYMPUS")) {
+    base = ftell(ifp)-10;
+    fseek (ifp, -2, SEEK_CUR);
+    order = get2();  get2();
+  } else if (!strncmp (buf,"FUJIFILM",8) ||
+	     !strncmp (buf,"SONY",4) ||
+	     !strcmp  (buf,"Panasonic")) {
+    order = 0x4949;
+    fseek (ifp,  2, SEEK_CUR);
+  } else if (!strcmp (buf,"OLYMP") ||
+	     !strcmp (buf,"LEICA") ||
+	     !strcmp (buf,"Ricoh") ||
+	     !strcmp (buf,"EPSON"))
+    fseek (ifp, -2, SEEK_CUR);
+  else if (!strcmp (buf,"AOC") ||
+	   !strcmp (buf,"QVC"))
+    fseek (ifp, -4, SEEK_CUR);
+  else fseek (ifp, -10, SEEK_CUR);
+
+  entries = get2();
+  if (entries > 1000) return;
+  while (entries--) {
+    tiff_get (base, &tag, &type, &len, &save);
+    tag |= uptag << 16;
+    if (tag == 2 && strstr(make,"NIKON"))
+      iso_speed = (get2(),get2());
+    if (tag == 4 && len > 26 && len < 35) {
+      if ((i=(get4(),get2())) != 0x7fff && !iso_speed)
+	iso_speed = 50 * pow (2, i/32.0 - 4);
+      if ((i=(get2(),get2())) != 0x7fff && !aperture)
+	aperture = pow (2, i/64.0);
+      if ((i=get2()) != 0xffff && !shutter)
+	shutter = pow (2, (short) i/-32.0);
+      wbi = (get2(),get2());
+      shot_order = (get2(),get2());
+    }
+    if ((tag == 4 || tag == 0x114) && !strncmp(make,"KONICA",6)) {
+      fseek (ifp, tag == 4 ? 140:160, SEEK_CUR);
+      switch (get2()) {
+	case 72:  flip = 0;  break;
+	case 76:  flip = 6;  break;
+	case 82:  flip = 5;  break;
+      }
+    }
+    if (tag == 7 && type == 2 && len > 20)
+      fgets (model2, 64, ifp);
+    if (tag == 8 && type == 4)
+      shot_order = get4();
+    if (tag == 9 && !strcmp(make,"Canon"))
+      fread (artist, 64, 1, ifp);
+    if (tag == 0xc && len == 4) {
+      cam_mul[0] = getreal(type);
+      cam_mul[2] = getreal(type);
+    }
+    if (tag == 0x10 && type == 4)
+      unique_id = get4();
+    if (tag == 0x11 && is_raw && !strncmp(make,"NIKON",5)) {
+      fseek (ifp, get4()+base, SEEK_SET);
+      parse_tiff_ifd (base);
+    }
+    if (tag == 0x14 && len == 2560 && type == 7) {
+      fseek (ifp, 1248, SEEK_CUR);
+      goto get2_256;
+    }
+    if (tag == 0x15 && type == 2 && is_raw)
+      fread (model, 64, 1, ifp);
+    if (strstr(make,"PENTAX")) {
+      if (tag == 0x1b) tag = 0x1018;
+      if (tag == 0x1c) tag = 0x1017;
+    }
+    if (tag == 0x1d)
+      while ((c = fgetc(ifp)) && c != EOF)
+	serial = serial*10 + (isdigit(c) ? c - '0' : c % 10);
+    if (tag == 0x81 && type == 4) {
+      data_offset = get4();
+      fseek (ifp, data_offset + 41, SEEK_SET);
+      raw_height = get2() * 2;
+      raw_width  = get2();
+      filters = 0x61616161;
+    }
+    if (tag == 0x29 && type == 1) {
+      c = wbi < 18 ? "012347800000005896"[wbi]-'0' : 0;
+      fseek (ifp, 8 + c*32, SEEK_CUR);
+      FORC4 cam_mul[c ^ (c >> 1) ^ 1] = get4();
+    }
+    if ((tag == 0x81  && type == 7) ||
+	(tag == 0x100 && type == 7) ||
+	(tag == 0x280 && type == 1)) {
+      thumb_offset = ftell(ifp);
+      thumb_length = len;
+    }
+    if (tag == 0x88 && type == 4 && (thumb_offset = get4()))
+      thumb_offset += base;
+    if (tag == 0x89 && type == 4)
+      thumb_length = get4();
+    if (tag == 0x8c || tag == 0x96)
+      meta_offset = ftell(ifp);
+    if (tag == 0x97) {
+      for (i=0; i < 4; i++)
+	ver97 = ver97 * 10 + fgetc(ifp)-'0';
+      switch (ver97) {
+	case 100:
+	  fseek (ifp, 68, SEEK_CUR);
+	  FORC4 cam_mul[(c >> 1) | ((c & 1) << 1)] = get2();
+	  break;
+	case 102:
+	  fseek (ifp, 6, SEEK_CUR);
+	  goto get2_rggb;
+	case 103:
+	  fseek (ifp, 16, SEEK_CUR);
+	  FORC4 cam_mul[c] = get2();
+      }
+      if (ver97 >= 200) {
+	if (ver97 != 205) fseek (ifp, 280, SEEK_CUR);
+	fread (buf97, 324, 1, ifp);
+      }
+    }
+    if (tag == 0xa4 && type == 3) {
+      fseek (ifp, wbi*48, SEEK_CUR);
+      FORC3 cam_mul[c] = get2();
+    }
+    if (tag == 0xa7 && (unsigned) (ver97-200) < 12 && !cam_mul[0]) {
+      ci = xlat[0][serial & 0xff];
+      cj = xlat[1][fgetc(ifp)^fgetc(ifp)^fgetc(ifp)^fgetc(ifp)];
+      ck = 0x60;
+      for (i=0; i < 324; i++)
+	buf97[i] ^= (cj += ci * ck++);
+      i = "66666>666;6A"[ver97-200] - '0';
+      FORC4 cam_mul[c ^ (c >> 1) ^ (i & 1)] =
+	sget2 (buf97 + (i & -2) + c*2);
+    }
+    if (tag == 0x200 && len == 3)
+      shot_order = (get4(),get4());
+    if (tag == 0x200 && len == 4)
+      black = (get2()+get2()+get2()+get2())/4;
+    if (tag == 0x201 && len == 4)
+      goto get2_rggb;
+    if (tag == 0x220 && len == 53)
+      meta_offset = ftell(ifp) + 14;
+    if (tag == 0x401 && type == 4 && len == 4) {
+      black = (get4()+get4()+get4()+get4())/4;
+    }
+    if (tag == 0xe01) {		/* Nikon Capture Note */
+      type = order;
+      order = 0x4949;
+      fseek (ifp, 22, SEEK_CUR);
+      for (offset=22; offset+22 < len; offset += 22+i) {
+	tag = get4();
+	fseek (ifp, 14, SEEK_CUR);
+	i = get4()-4;
+	if (tag == 0x76a43207) flip = get2();
+	else fseek (ifp, i, SEEK_CUR);
+      }
+      order = type;
+    }
+    if (tag == 0xe80 && len == 256 && type == 7) {
+      fseek (ifp, 48, SEEK_CUR);
+      cam_mul[0] = get2() * 508 * 1.078 / 0x10000;
+      cam_mul[2] = get2() * 382 * 1.173 / 0x10000;
+    }
+    if (tag == 0xf00 && type == 7) {
+      if (len == 614)
+	fseek (ifp, 176, SEEK_CUR);
+      else if (len == 734 || len == 1502)
+	fseek (ifp, 148, SEEK_CUR);
+      else goto next;
+      goto get2_256;
+    }
+    if ((tag == 0x1011 && len == 9) || tag == 0x20400200)
+      for (i=0; i < 3; i++)
+	FORC3 cmatrix[i][c] = ((short) get2()) / 256.0;
+    if ((tag == 0x1012 || tag == 0x20400600) && len == 4)
+      for (black = i=0; i < 4; i++)
+	black += get2() << 2;
+    if (tag == 0x1017 || tag == 0x20400100)
+      cam_mul[0] = get2() / 256.0;
+    if (tag == 0x1018 || tag == 0x20400100)
+      cam_mul[2] = get2() / 256.0;
+    if (tag == 0x2011 && len == 2) {
+get2_256:
+      order = 0x4d4d;
+      cam_mul[0] = get2() / 256.0;
+      cam_mul[2] = get2() / 256.0;
+    }
+    if ((tag | 0x70) == 0x2070 && type == 4)
+      fseek (ifp, get4()+base, SEEK_SET);
+    if (tag == 0x2010 && type != 7)
+      load_raw = &CLASS olympus_load_raw;
+    if (tag == 0x2020)
+      parse_thumb_note (base, 257, 258);
+    if (tag == 0x2040)
+      parse_makernote (base, 0x2040);
+    if (tag == 0xb028) {
+      fseek (ifp, get4(), SEEK_SET);
+      parse_thumb_note (base, 136, 137);
+    }
+    if (tag == 0x4001 && len > 500) {
+      i = len == 582 ? 50 : len == 653 ? 68 : len == 5120 ? 142 : 126;
+      fseek (ifp, i, SEEK_CUR);
+get2_rggb:
+      FORC4 cam_mul[c ^ (c >> 1)] = get2();
+      fseek (ifp, 22, SEEK_CUR);
+      FORC4 sraw_mul[c ^ (c >> 1)] = get2();
+    }
+next:
+    fseek (ifp, save, SEEK_SET);
+  }
+quit:
+  order = sorder;
+}
+
+/*
+   Since the TIFF DateTime string has no timezone information,
+   assume that the camera's clock was set to Universal Time.
+ */
+void CLASS get_timestamp (int reversed)
+{
+  struct tm t;
+  char str[20];
+  int i;
+
+  str[19] = 0;
+  if (reversed)
+    for (i=19; i--; ) str[i] = fgetc(ifp);
+  else
+    fread (str, 19, 1, ifp);
+  memset (&t, 0, sizeof t);
+  if (sscanf (str, "%d:%d:%d %d:%d:%d", &t.tm_year, &t.tm_mon,
+	&t.tm_mday, &t.tm_hour, &t.tm_min, &t.tm_sec) != 6)
+    return;
+  t.tm_year -= 1900;
+  t.tm_mon -= 1;
+  if (mktime(&t) > 0)
+    timestamp = mktime(&t);
+}
+
+void CLASS parse_exif (int base)
+{
+  unsigned kodak, entries, tag, type, len, save, c;
+  double expo;
+
+  kodak = !strncmp(make,"EASTMAN",7);
+  entries = get2();
+  while (entries--) {
+    tiff_get (base, &tag, &type, &len, &save);
+    switch (tag) {
+      case 33434:  shutter = getreal(type);		break;
+      case 33437:  aperture = getreal(type);		break;
+      case 34855:  iso_speed = get2();			break;
+      case 36867:
+      case 36868:  get_timestamp(0);			break;
+      case 37377:  if ((expo = -getreal(type)) < 128)
+		     shutter = pow (2, expo);		break;
+      case 37378:  aperture = pow (2, getreal(type)/2);	break;
+      case 37386:  focal_len = getreal(type);		break;
+      case 37500:  parse_makernote (base, 0);		break;
+      case 40962:  if (kodak) raw_width  = get4();	break;
+      case 40963:  if (kodak) raw_height = get4();	break;
+      case 41730:
+	if (get4() == 0x20002)
+	  for (exif_cfa=c=0; c < 8; c+=2)
+	    exif_cfa |= fgetc(ifp) * 0x01010101 << c;
+    }
+    fseek (ifp, save, SEEK_SET);
+  }
+}
+
+void CLASS parse_gps (int base)
+{
+  unsigned entries, tag, type, len, save, c;
+
+  entries = get2();
+  while (entries--) {
+    tiff_get (base, &tag, &type, &len, &save);
+    switch (tag) {
+      case 1: case 3: case 5:
+	gpsdata[29+tag/2] = getc(ifp);			break;
+      case 2: case 4: case 7:
+	FORC(6) gpsdata[tag/3*6+c] = get4();		break;
+      case 6:
+	FORC(2) gpsdata[18+c] = get4();			break;
+      case 18: case 29:
+	fgets ((char *) (gpsdata+14+tag/3), MIN(len,12), ifp);
+    }
+    fseek (ifp, save, SEEK_SET);
+  }
+}
+
+void CLASS romm_coeff (float romm_cam[3][3])
+{
+  static const float rgb_romm[3][3] =	/* ROMM == Kodak ProPhoto */
+  { {  2.034193, -0.727420, -0.306766 },
+    { -0.228811,  1.231729, -0.002922 },
+    { -0.008565, -0.153273,  1.161839 } };
+  int i, j, k;
+
+  for (i=0; i < 3; i++)
+    for (j=0; j < 3; j++)
+      for (cmatrix[i][j] = k=0; k < 3; k++)
+	cmatrix[i][j] += rgb_romm[i][k] * romm_cam[k][j];
+}
+
+void CLASS parse_mos (int offset)
+{
+  char data[40];
+  int skip, from, i, c, neut[4], planes=0, frot=0;
+  static const char *mod[] =
+  { "","DCB2","Volare","Cantare","CMost","Valeo 6","Valeo 11","Valeo 22",
+    "Valeo 11p","Valeo 17","","Aptus 17","Aptus 22","Aptus 75","Aptus 65",
+    "Aptus 54S","Aptus 65S","Aptus 75S","AFi 5","AFi 6","AFi 7" };
+  float romm_cam[3][3];
+
+  fseek (ifp, offset, SEEK_SET);
+  while (1) {
+    if (get4() != 0x504b5453) break;
+    get4();
+    fread (data, 1, 40, ifp);
+    skip = get4();
+    from = ftell(ifp);
+    if (!strcmp(data,"JPEG_preview_data")) {
+      thumb_offset = from;
+      thumb_length = skip;
+    }
+    if (!strcmp(data,"icc_camera_profile")) {
+      profile_offset = from;
+      profile_length = skip;
+    }
+    if (!strcmp(data,"ShootObj_back_type")) {
+      fscanf (ifp, "%d", &i);
+      if ((unsigned) i < sizeof mod / sizeof (*mod))
+	strcpy (model, mod[i]);
+    }
+    if (!strcmp(data,"icc_camera_to_tone_matrix")) {
+      for (i=0; i < 9; i++)
+	romm_cam[0][i] = int_to_float(get4());
+      romm_coeff (romm_cam);
+    }
+    if (!strcmp(data,"CaptProf_color_matrix")) {
+      for (i=0; i < 9; i++)
+	fscanf (ifp, "%f", &romm_cam[0][i]);
+      romm_coeff (romm_cam);
+    }
+    if (!strcmp(data,"CaptProf_number_of_planes"))
+      fscanf (ifp, "%d", &planes);
+    if (!strcmp(data,"CaptProf_raw_data_rotation"))
+      fscanf (ifp, "%d", &flip);
+    if (!strcmp(data,"CaptProf_mosaic_pattern"))
+      FORC4 {
+	fscanf (ifp, "%d", &i);
+	if (i == 1) frot = c ^ (c >> 1);
+      }
+    if (!strcmp(data,"ImgProf_rotation_angle")) {
+      fscanf (ifp, "%d", &i);
+      flip = i - flip;
+    }
+    if (!strcmp(data,"NeutObj_neutrals") && !cam_mul[0]) {
+      FORC4 fscanf (ifp, "%d", neut+c);
+      FORC3 cam_mul[c] = (float) neut[0] / neut[c+1];
+    }
+    parse_mos (from);
+    fseek (ifp, skip+from, SEEK_SET);
+  }
+  if (planes)
+    filters = (planes == 1) * 0x01010101 *
+	(uchar) "\x94\x61\x16\x49"[(flip/90 + frot) & 3];
+}
+
+void CLASS linear_table (unsigned len)
+{
+  int i;
+  if (len > 0x1000) len = 0x1000;
+  read_shorts (curve, len);
+  for (i=len; i < 0x1000; i++)
+    curve[i] = curve[i-1];
+  maximum = curve[0xfff];
+}
+
+void CLASS parse_kodak_ifd (int base)
+{
+  unsigned entries, tag, type, len, save;
+  int i, c, wbi=-2, wbtemp=6500;
+  float mul[3]={1,1,1}, num;
+  static const int wbtag[]={ 0xfa25,0xfa28,0xfa27,0xfa29,-1,-1,0xfa2a };
+
+  entries = get2();
+  if (entries > 1024) return;
+  while (entries--) {
+    tiff_get (base, &tag, &type, &len, &save);
+    if (tag == 1020) wbi = getint(type);
+    if (tag == 1021 && len == 72) {		/* WB set in software */
+      fseek (ifp, 40, SEEK_CUR);
+      FORC3 cam_mul[c] = 2048.0 / get2();
+      wbi = -2;
+    }
+    if (tag == 2118) wbtemp = getint(type);
+    if (tag == 2130 + wbi)
+      FORC3 mul[c] = getreal(type);
+    if (tag == 2140 + wbi && wbi >= 0)
+      FORC3 {
+	for (num=i=0; i < 4; i++)
+	  num += getreal(type) * pow (wbtemp/100.0, i);
+	cam_mul[c] = 2048 / (num * mul[c]);
+      }
+    if (tag == 2317) linear_table (len);
+    if (tag == 6020) iso_speed = getint(type);
+    if (tag == 0xfa0d) wbi = fgetc(ifp);
+    if ((unsigned) wbi < 7 && tag == wbtag[wbi])
+      FORC3 cam_mul[c] = get4();
+    fseek (ifp, save, SEEK_SET);
+  }
+}
+
+void CLASS parse_minolta (int base);
+
+int CLASS parse_tiff_ifd (int base)
+{
+  unsigned entries, tag, type, len, plen=16, save;
+  int ifd, use_cm=0, cfa, i, j, c, ima_len=0;
+  char software[64], *cbuf, *cp;
+  uchar cfa_pat[16], cfa_pc[] = { 0,1,2,3 }, tab[256];
+  double dblack, cc[4][4], cm[4][3], cam_xyz[4][3], num;
+  double ab[]={ 1,1,1,1 }, asn[] = { 0,0,0,0 }, xyz[] = { 1,1,1 };
+  unsigned sony_curve[] = { 0,0,0,0,0,4095 };
+  unsigned *buf, sony_offset=0, sony_length=0, sony_key=0;
+  struct jhead jh;
+  FILE *sfp;
+
+  if (tiff_nifds >= sizeof tiff_ifd / sizeof tiff_ifd[0])
+    return 1;
+  ifd = tiff_nifds++;
+  for (j=0; j < 4; j++)
+    for (i=0; i < 4; i++)
+      cc[j][i] = i == j;
+  entries = get2();
+  if (entries > 512) return 1;
+  while (entries--) {
+    tiff_get (base, &tag, &type, &len, &save);
+    switch (tag) {
+      case 17: case 18:
+	if (type == 3 && len == 1)
+	  cam_mul[(tag-17)*2] = get2() / 256.0;
+	break;
+      case 23:
+	if (type == 3) iso_speed = get2();
+	break;
+      case 36: case 37: case 38:
+	cam_mul[tag-0x24] = get2();
+	break;
+      case 39:
+	if (len < 50 || cam_mul[0]) break;
+	fseek (ifp, 12, SEEK_CUR);
+	FORC3 cam_mul[c] = get2();
+	break;
+      case 46:
+	if (type != 7 || fgetc(ifp) != 0xff || fgetc(ifp) != 0xd8) break;
+	thumb_offset = ftell(ifp) - 2;
+	thumb_length = len;
+	break;
+      case 2: case 256:			/* ImageWidth */
+	tiff_ifd[ifd].width = getint(type);
+	break;
+      case 3: case 257:			/* ImageHeight */
+	tiff_ifd[ifd].height = getint(type);
+	break;
+      case 258:				/* BitsPerSample */
+	tiff_ifd[ifd].samples = len & 7;
+	tiff_ifd[ifd].bps = get2();
+	break;
+      case 259:				/* Compression */
+	tiff_ifd[ifd].comp = get2();
+	break;
+      case 262:				/* PhotometricInterpretation */
+	tiff_ifd[ifd].phint = get2();
+	break;
+      case 270:				/* ImageDescription */
+	fread (desc, 512, 1, ifp);
+	break;
+      case 271:				/* Make */
+	fgets (make, 64, ifp);
+	break;
+      case 272:				/* Model */
+	fgets (model, 64, ifp);
+	break;
+      case 280:				/* Panasonic RW2 offset */
+	if (type != 4) break;
+	load_raw = &CLASS panasonic_load_raw;
+	load_flags = 0x2008;
+      case 273:				/* StripOffset */
+      case 513:
+	tiff_ifd[ifd].offset = get4()+base;
+	if (!tiff_ifd[ifd].bps) {
+	  fseek (ifp, tiff_ifd[ifd].offset, SEEK_SET);
+	  if (ljpeg_start (&jh, 1)) {
+	    tiff_ifd[ifd].comp    = 6;
+	    tiff_ifd[ifd].width   = jh.wide << (jh.clrs == 2);
+	    tiff_ifd[ifd].height  = jh.high;
+	    tiff_ifd[ifd].bps     = jh.bits;
+	    tiff_ifd[ifd].samples = jh.clrs;
+	  }
+	}
+	break;
+      case 274:				/* Orientation */
+	tiff_ifd[ifd].flip = "50132467"[get2() & 7]-'0';
+	break;
+      case 277:				/* SamplesPerPixel */
+	tiff_ifd[ifd].samples = getint(type) & 7;
+	break;
+      case 279:				/* StripByteCounts */
+      case 514:
+	tiff_ifd[ifd].bytes = get4();
+	break;
+      case 305:  case 11:		/* Software */
+	fgets (software, 64, ifp);
+	if (!strncmp(software,"Adobe",5) ||
+	    !strncmp(software,"dcraw",5) ||
+	    !strncmp(software,"UFRaw",5) ||
+	    !strncmp(software,"Bibble",6) ||
+	    !strncmp(software,"Nikon Scan",10) ||
+	    !strcmp (software,"Digital Photo Professional"))
+	  is_raw = 0;
+	break;
+      case 306:				/* DateTime */
+	get_timestamp(0);
+	break;
+      case 315:				/* Artist */
+	fread (artist, 64, 1, ifp);
+	break;
+      case 322:				/* TileWidth */
+	tile_width = getint(type);
+	break;
+      case 323:				/* TileLength */
+	tile_length = getint(type);
+	break;
+      case 324:				/* TileOffsets */
+	tiff_ifd[ifd].offset = len > 1 ? ftell(ifp) : get4();
+	if (len == 4) {
+	  load_raw = &CLASS sinar_4shot_load_raw;
+	  is_raw = 5;
+	}
+	break;
+      case 330:				/* SubIFDs */
+	if (!strcmp(model,"DSLR-A100") && tiff_ifd[ifd].width == 3872) {
+	  load_raw = &CLASS sony_arw_load_raw;
+	  data_offset = get4()+base;
+	  ifd++;  break;
+	}
+	while (len--) {
+	  i = ftell(ifp);
+	  fseek (ifp, get4()+base, SEEK_SET);
+	  if (parse_tiff_ifd (base)) break;
+	  fseek (ifp, i+4, SEEK_SET);
+	}
+	break;
+      case 400:
+	strcpy (make, "Sarnoff");
+	maximum = 0xfff;
+	break;
+      case 28688:
+	FORC4 sony_curve[c+1] = get2() >> 2 & 0xfff;
+	for (i=0; i < 5; i++)
+	  for (j = sony_curve[i]+1; j <= sony_curve[i+1]; j++)
+	    curve[j] = curve[j-1] + (1 << i);
+	break;
+      case 29184: sony_offset = get4();  break;
+      case 29185: sony_length = get4();  break;
+      case 29217: sony_key    = get4();  break;
+      case 29264:
+	parse_minolta (ftell(ifp));
+	raw_width = 0;
+	break;
+      case 29443:
+	FORC4 cam_mul[c ^ (c < 2)] = get2();
+	break;
+      case 29459:
+	FORC4 cam_mul[c ^ (c >> 1)] = get2();
+	break;
+      case 33405:			/* Model2 */
+	fgets (model2, 64, ifp);
+	break;
+      case 33422:			/* CFAPattern */
+      case 64777:			/* Kodak P-series */
+	if ((plen=len) > 16) plen = 16;
+	fread (cfa_pat, 1, plen, ifp);
+	for (colors=cfa=i=0; i < plen; i++) {
+	  colors += !(cfa & (1 << cfa_pat[i]));
+	  cfa |= 1 << cfa_pat[i];
+	}
+	if (cfa == 070) memcpy (cfa_pc,"\003\004\005",3);	/* CMY */
+	if (cfa == 072) memcpy (cfa_pc,"\005\003\004\001",4);	/* GMCY */
+	goto guess_cfa_pc;
+      case 33424:
+      case 65024:
+	fseek (ifp, get4()+base, SEEK_SET);
+	parse_kodak_ifd (base);
+	break;
+      case 33434:			/* ExposureTime */
+	shutter = getreal(type);
+	break;
+      case 33437:			/* FNumber */
+	aperture = getreal(type);
+	break;
+      case 34306:			/* Leaf white balance */
+	FORC4 cam_mul[c ^ 1] = 4096.0 / get2();
+	break;
+      case 34307:			/* Leaf CatchLight color matrix */
+	fread (software, 1, 7, ifp);
+	if (strncmp(software,"MATRIX",6)) break;
+	colors = 4;
+	for (raw_color = i=0; i < 3; i++) {
+	  FORC4 fscanf (ifp, "%f", &rgb_cam[i][c^1]);
+	  if (!use_camera_wb) continue;
+	  num = 0;
+	  FORC4 num += rgb_cam[i][c];
+	  FORC4 rgb_cam[i][c] /= num;
+	}
+	break;
+      case 34310:			/* Leaf metadata */
+	parse_mos (ftell(ifp));
+      case 34303:
+	strcpy (make, "Leaf");
+	break;
+      case 34665:			/* EXIF tag */
+	fseek (ifp, get4()+base, SEEK_SET);
+	parse_exif (base);
+	break;
+      case 34853:			/* GPSInfo tag */
+	fseek (ifp, get4()+base, SEEK_SET);
+	parse_gps (base);
+	break;
+      case 34675:			/* InterColorProfile */
+      case 50831:			/* AsShotICCProfile */
+	profile_offset = ftell(ifp);
+	profile_length = len;
+	break;
+      case 37122:			/* CompressedBitsPerPixel */
+	kodak_cbpp = get4();
+	break;
+      case 37386:			/* FocalLength */
+	focal_len = getreal(type);
+	break;
+      case 37393:			/* ImageNumber */
+	shot_order = getint(type);
+	break;
+      case 37400:			/* old Kodak KDC tag */
+	for (raw_color = i=0; i < 3; i++) {
+	  getreal(type);
+	  FORC3 rgb_cam[i][c] = getreal(type);
+	}
+	break;
+      case 46275:			/* Imacon tags */
+	strcpy (make, "Imacon");
+	data_offset = ftell(ifp);
+	ima_len = len;
+	break;
+      case 46279:
+	if (!ima_len) break;
+	fseek (ifp, 78, SEEK_CUR);
+	raw_width  = get4();
+	raw_height = get4();
+	left_margin = get4() & 7;
+	width = raw_width - left_margin - (get4() & 7);
+	top_margin = get4() & 7;
+	height = raw_height - top_margin - (get4() & 7);
+	if (raw_width == 7262) {
+	  height = 5444;
+	  width  = 7244;
+	  left_margin = 7;
+	}
+	fseek (ifp, 52, SEEK_CUR);
+	FORC3 cam_mul[c] = getreal(11);
+	fseek (ifp, 114, SEEK_CUR);
+	flip = (get2() >> 7) * 90;
+	if (width * height * 6 == ima_len) {
+	  if (flip % 180 == 90) SWAP(width,height);
+	  filters = flip = 0;
+	}
+	sprintf (model, "Ixpress %d-Mp", height*width/1000000);
+	load_raw = &CLASS imacon_full_load_raw;
+	if (filters) {
+	  if (left_margin & 1) filters = 0x61616161;
+	  load_raw = &CLASS unpacked_load_raw;
+	}
+	maximum = 0xffff;
+	break;
+      case 50454:			/* Sinar tag */
+      case 50455:
+	if (!(cbuf = (char *) malloc(len))) break;
+	fread (cbuf, 1, len, ifp);
+	for (cp = cbuf-1; cp && cp < cbuf+len; cp = strchr(cp,'\n'))
+	  if (!strncmp (++cp,"Neutral ",8))
+	    sscanf (cp+8, "%f %f %f", cam_mul, cam_mul+1, cam_mul+2);
+	free (cbuf);
+	break;
+      case 50458:
+	if (!make[0]) strcpy (make, "Hasselblad");
+	break;
+      case 50459:			/* Hasselblad tag */
+	i = order;
+	j = ftell(ifp);
+	c = tiff_nifds;
+	order = get2();
+	fseek (ifp, j+(get2(),get4()), SEEK_SET);
+	parse_tiff_ifd (j);
+	maximum = 0xffff;
+	tiff_nifds = c;
+	order = i;
+	break;
+      case 50706:			/* DNGVersion */
+	FORC4 dng_version = (dng_version << 8) + fgetc(ifp);
+	if (!make[0]) strcpy (make, "DNG");
+	is_raw = 1;
+	break;
+      case 50710:			/* CFAPlaneColor */
+	if (len > 4) len = 4;
+	colors = len;
+	fread (cfa_pc, 1, colors, ifp);
+guess_cfa_pc:
+	FORCC tab[cfa_pc[c]] = c;
+	cdesc[c] = 0;
+	for (i=16; i--; )
+	  filters = filters << 2 | tab[cfa_pat[i % plen]];
+	break;
+      case 50711:			/* CFALayout */
+	if (get2() == 2) {
+	  fuji_width = 1;
+	  filters = 0x49494949;
+	}
+	break;
+      case 291:
+      case 50712:			/* LinearizationTable */
+	linear_table (len);
+	break;
+      case 50714:			/* BlackLevel */
+      case 50715:			/* BlackLevelDeltaH */
+      case 50716:			/* BlackLevelDeltaV */
+	for (dblack=i=0; i < len; i++)
+	  dblack += getreal(type);
+	black += dblack/len + 0.5;
+	break;
+      case 50717:			/* WhiteLevel */
+	maximum = getint(type);
+	break;
+      case 50718:			/* DefaultScale */
+	pixel_aspect  = getreal(type);
+	pixel_aspect /= getreal(type);
+	break;
+      case 50721:			/* ColorMatrix1 */
+      case 50722:			/* ColorMatrix2 */
+	FORCC for (j=0; j < 3; j++)
+	  cm[c][j] = getreal(type);
+	use_cm = 1;
+	break;
+      case 50723:			/* CameraCalibration1 */
+      case 50724:			/* CameraCalibration2 */
+	for (i=0; i < colors; i++)
+	  FORCC cc[i][c] = getreal(type);
+	break;
+      case 50727:			/* AnalogBalance */
+	FORCC ab[c] = getreal(type);
+	break;
+      case 50728:			/* AsShotNeutral */
+	FORCC asn[c] = getreal(type);
+	break;
+      case 50729:			/* AsShotWhiteXY */
+	xyz[0] = getreal(type);
+	xyz[1] = getreal(type);
+	xyz[2] = 1 - xyz[0] - xyz[1];
+	FORC3 xyz[c] /= d65_white[c];
+	break;
+      case 50740:			/* DNGPrivateData */
+	if (dng_version) break;
+	parse_minolta (j = get4()+base);
+	fseek (ifp, j, SEEK_SET);
+	parse_tiff_ifd (base);
+	break;
+      case 50752:
+	read_shorts (cr2_slice, 3);
+	break;
+      case 50829:			/* ActiveArea */
+	top_margin = getint(type);
+	left_margin = getint(type);
+	height = getint(type) - top_margin;
+	width = getint(type) - left_margin;
+	break;
+      case 64772:			/* Kodak P-series */
+	if (len < 13) break;
+	fseek (ifp, 16, SEEK_CUR);
+	data_offset = get4();
+	fseek (ifp, 28, SEEK_CUR);
+	data_offset += get4();
+	load_raw = &CLASS packed_load_raw;
+	break;
+      case 65026:
+	if (type == 2) fgets (model2, 64, ifp);
+    }
+    fseek (ifp, save, SEEK_SET);
+  }
+  if (sony_length && (buf = (unsigned *) malloc(sony_length))) {
+    fseek (ifp, sony_offset, SEEK_SET);
+    fread (buf, sony_length, 1, ifp);
+    sony_decrypt (buf, sony_length/4, 1, sony_key);
+    sfp = ifp;
+    if ((ifp = tmpfile())) {
+      fwrite (buf, sony_length, 1, ifp);
+      fseek (ifp, 0, SEEK_SET);
+      parse_tiff_ifd (-sony_offset);
+      fclose (ifp);
+    }
+    ifp = sfp;
+    free (buf);
+  }
+  for (i=0; i < colors; i++)
+    FORCC cc[i][c] *= ab[i];
+  if (use_cm) {
+    FORCC for (i=0; i < 3; i++)
+      for (cam_xyz[c][i]=j=0; j < colors; j++)
+	cam_xyz[c][i] += cc[c][j] * cm[j][i] * xyz[i];
+    cam_xyz_coeff (cam_xyz);
+  }
+  if (asn[0]) {
+    cam_mul[3] = 0;
+    FORCC cam_mul[c] = 1 / asn[c];
+  }
+  if (!use_cm)
+    FORCC pre_mul[c] /= cc[c][c];
+  return 0;
+}
+
+void CLASS parse_tiff (int base)
+{
+  int doff, max_samp=0, raw=-1, thm=-1, i;
+  struct jhead jh;
+
+  fseek (ifp, base, SEEK_SET);
+  order = get2();
+  if (order != 0x4949 && order != 0x4d4d) return;
+  get2();
+  memset (tiff_ifd, 0, sizeof tiff_ifd);
+  tiff_nifds = 0;
+  while ((doff = get4())) {
+    fseek (ifp, doff+base, SEEK_SET);
+    if (parse_tiff_ifd (base)) break;
+  }
+  thumb_misc = 16;
+  if (thumb_offset) {
+    fseek (ifp, thumb_offset, SEEK_SET);
+    if (ljpeg_start (&jh, 1)) {
+      thumb_misc   = jh.bits;
+      thumb_width  = jh.wide;
+      thumb_height = jh.high;
+    }
+  }
+  for (i=0; i < tiff_nifds; i++) {
+    if (max_samp < tiff_ifd[i].samples)
+	max_samp = tiff_ifd[i].samples;
+    if (max_samp > 3) max_samp = 3;
+    if ((tiff_ifd[i].comp != 6 || tiff_ifd[i].samples != 3) &&
+	(tiff_ifd[i].width | tiff_ifd[i].height) < 0x10000 &&
+	tiff_ifd[i].width*tiff_ifd[i].height > raw_width*raw_height) {
+      raw_width     = tiff_ifd[i].width;
+      raw_height    = tiff_ifd[i].height;
+      tiff_bps      = tiff_ifd[i].bps;
+      tiff_compress = tiff_ifd[i].comp;
+      data_offset   = tiff_ifd[i].offset;
+      tiff_flip     = tiff_ifd[i].flip;
+      tiff_samples  = tiff_ifd[i].samples;
+      raw = i;
+    }
+  }
+  fuji_width *= (raw_width+1)/2;
+  if (tiff_ifd[0].flip) tiff_flip = tiff_ifd[0].flip;
+  if (raw >= 0 && !load_raw)
+    switch (tiff_compress) {
+      case 0:  case 1:
+	switch (tiff_bps) {
+	  case  8: load_raw = &CLASS eight_bit_load_raw;	break;
+	  case 12: load_raw = &CLASS packed_load_raw;
+		   if (tiff_ifd[raw].phint == 2)
+		     load_flags = 6;
+		   if (strncmp(make,"PENTAX",6)) break;
+	  case 14:
+	  case 16: load_raw = &CLASS unpacked_load_raw;		break;
+	}
+	if (tiff_ifd[raw].bytes*5 == raw_width*raw_height*8) {
+	  tiff_bps = 12;
+	  maximum = 0xffff;
+	  load_raw = &CLASS packed_load_raw;
+	  load_flags = 273;
+	}
+	break;
+      case 6:  case 7:  case 99:
+	load_raw = &CLASS lossless_jpeg_load_raw;		break;
+      case 262:
+	load_raw = &CLASS kodak_262_load_raw;			break;
+      case 32767:
+	if (tiff_ifd[raw].bytes == raw_width*raw_height) {
+	  tiff_bps = 12;
+	  load_raw = &CLASS sony_arw2_load_raw;			break;
+	}
+	if (tiff_ifd[raw].bytes*8 != raw_width*raw_height*tiff_bps) {
+	  raw_height += 8;
+	  load_raw = &CLASS sony_arw_load_raw;			break;
+	}
+	load_flags = 79;
+      case 32769:
+	load_flags++;
+      case 32773:
+	load_raw = &CLASS packed_load_raw;			break;
+      case 34713:
+	load_raw = &CLASS nikon_compressed_load_raw;		break;
+      case 65535:
+	load_raw = &CLASS pentax_load_raw;			break;
+      case 65000:
+	switch (tiff_ifd[raw].phint) {
+	  case 2: load_raw = &CLASS kodak_rgb_load_raw;   filters = 0;  break;
+	  case 6: load_raw = &CLASS kodak_ycbcr_load_raw; filters = 0;  break;
+	  case 32803: load_raw = &CLASS kodak_65000_load_raw;
+	}
+      case 32867: break;
+      default: is_raw = 0;
+    }
+  if (!dng_version)
+    if ( (tiff_samples == 3 && tiff_ifd[raw].bytes &&
+	  tiff_bps != 14 && tiff_bps != 2048)
+      || (tiff_bps == 8 && !strstr(make,"KODAK") && !strstr(make,"Kodak") &&
+	  !strstr(model2,"DEBUG RAW")))
+      is_raw = 0;
+  for (i=0; i < tiff_nifds; i++)
+    if (i != raw && tiff_ifd[i].samples == max_samp &&
+	tiff_ifd[i].width * tiff_ifd[i].height / SQR(tiff_ifd[i].bps+1) >
+	      thumb_width *       thumb_height / SQR(thumb_misc+1)) {
+      thumb_width  = tiff_ifd[i].width;
+      thumb_height = tiff_ifd[i].height;
+      thumb_offset = tiff_ifd[i].offset;
+      thumb_length = tiff_ifd[i].bytes;
+      thumb_misc   = tiff_ifd[i].bps;
+      thm = i;
+    }
+  if (thm >= 0) {
+    thumb_misc |= tiff_ifd[thm].samples << 5;
+    switch (tiff_ifd[thm].comp) {
+      case 0:
+	write_thumb = &CLASS layer_thumb;
+	break;
+      case 1:
+	if (tiff_ifd[thm].bps > 8)
+	  thumb_load_raw = &CLASS kodak_thumb_load_raw;
+	else
+	  write_thumb = &CLASS ppm_thumb;
+	break;
+      case 65000:
+	thumb_load_raw = tiff_ifd[thm].phint == 6 ?
+		&CLASS kodak_ycbcr_load_raw : &CLASS kodak_rgb_load_raw;
+    }
+  }
+}
+
+void CLASS parse_minolta (int base)
+{
+  int save, tag, len, offset, high=0, wide=0, i, c;
+  short sorder=order;
+
+  fseek (ifp, base, SEEK_SET);
+  if (fgetc(ifp) || fgetc(ifp)-'M' || fgetc(ifp)-'R') return;
+  order = fgetc(ifp) * 0x101;
+  offset = base + get4() + 8;
+  while ((save=ftell(ifp)) < offset) {
+    for (tag=i=0; i < 4; i++)
+      tag = tag << 8 | fgetc(ifp);
+    len = get4();
+    switch (tag) {
+      case 0x505244:				/* PRD */
+	fseek (ifp, 8, SEEK_CUR);
+	high = get2();
+	wide = get2();
+	break;
+      case 0x574247:				/* WBG */
+	get4();
+	i = strcmp(model,"DiMAGE A200") ? 0:3;
+	FORC4 cam_mul[c ^ (c >> 1) ^ i] = get2();
+	break;
+      case 0x545457:				/* TTW */
+	parse_tiff (ftell(ifp));
+	data_offset = offset;
+    }
+    fseek (ifp, save+len+8, SEEK_SET);
+  }
+  raw_height = high;
+  raw_width  = wide;
+  order = sorder;
+}
+
+/*
+   Many cameras have a "debug mode" that writes JPEG and raw
+   at the same time.  The raw file has no header, so try to
+   to open the matching JPEG file and read its metadata.
+ */
+void CLASS parse_external_jpeg()
+{
+  const char *file, *ext;
+  char *jname, *jfile, *jext;
+  FILE *save=ifp;
+
+  ext  = strrchr (ifname, '.');
+  file = strrchr (ifname, '/');
+  if (!file) file = strrchr (ifname, '\\');
+  if (!file) file = ifname-1;
+  file++;
+  if (!ext || strlen(ext) != 4 || ext-file != 8) return;
+  jname = (char *) malloc (strlen(ifname) + 1);
+  merror (jname, "parse_external_jpeg()");
+  strcpy (jname, ifname);
+  jfile = file - ifname + jname;
+  jext  = ext  - ifname + jname;
+  if (strcasecmp (ext, ".jpg")) {
+    strcpy (jext, isupper(ext[1]) ? ".JPG":".jpg");
+    if (isdigit(*file)) {
+      memcpy (jfile, file+4, 4);
+      memcpy (jfile+4, file, 4);
+    }
+  } else
+    while (isdigit(*--jext)) {
+      if (*jext != '9') {
+        (*jext)++;
+	break;
+      }
+      *jext = '0';
+    }
+  if (strcmp (jname, ifname)) {
+    if ((ifp = fopen (jname, "rb"))) {
+      if (verbose)
+	fprintf (stderr,_("Reading metadata from %s ...\n"), jname);
+      parse_tiff (12);
+      thumb_offset = 0;
+      is_raw = 1;
+      fclose (ifp);
+    }
+  }
+  if (!timestamp)
+    fprintf (stderr,_("Failed to read metadata from %s\n"), jname);
+  free (jname);
+  ifp = save;
+}
+
+/*
+   CIFF block 0x1030 contains an 8x8 white sample.
+   Load this into white[][] for use in scale_colors().
+ */
+void CLASS ciff_block_1030()
+{
+  static const ushort key[] = { 0x410, 0x45f3 };
+  int i, bpp, row, col, vbits=0;
+  unsigned long bitbuf=0;
+
+  if ((get2(),get4()) != 0x80008 || !get4()) return;
+  bpp = get2();
+  if (bpp != 10 && bpp != 12) return;
+  for (i=row=0; row < 8; row++)
+    for (col=0; col < 8; col++) {
+      if (vbits < bpp) {
+	bitbuf = bitbuf << 16 | (get2() ^ key[i++ & 1]);
+	vbits += 16;
+      }
+      white[row][col] =
+	bitbuf << (LONG_BIT - vbits) >> (LONG_BIT - bpp);
+      vbits -= bpp;
+    }
+}
+
+/*
+   Parse a CIFF file, better known as Canon CRW format.
+ */
+void CLASS parse_ciff (int offset, int length)
+{
+  int tboff, nrecs, c, type, len, save, wbi=-1;
+  ushort key[] = { 0x410, 0x45f3 };
+
+  fseek (ifp, offset+length-4, SEEK_SET);
+  tboff = get4() + offset;
+  fseek (ifp, tboff, SEEK_SET);
+  nrecs = get2();
+  if (nrecs > 100) return;
+  while (nrecs--) {
+    type = get2();
+    len  = get4();
+    save = ftell(ifp) + 4;
+    fseek (ifp, offset+get4(), SEEK_SET);
+    if ((((type >> 8) + 8) | 8) == 0x38)
+      parse_ciff (ftell(ifp), len);	/* Parse a sub-table */
+
+    if (type == 0x0810)
+      fread (artist, 64, 1, ifp);
+    if (type == 0x080a) {
+      fread (make, 64, 1, ifp);
+      fseek (ifp, strlen(make) - 63, SEEK_CUR);
+      fread (model, 64, 1, ifp);
+    }
+    if (type == 0x1810) {
+      fseek (ifp, 12, SEEK_CUR);
+      flip = get4();
+    }
+    if (type == 0x1835)			/* Get the decoder table */
+      tiff_compress = get4();
+    if (type == 0x2007) {
+      thumb_offset = ftell(ifp);
+      thumb_length = len;
+    }
+    if (type == 0x1818) {
+      shutter = pow (2, -int_to_float((get4(),get4())));
+      aperture = pow (2, int_to_float(get4())/2);
+    }
+    if (type == 0x102a) {
+      iso_speed = pow (2, (get4(),get2())/32.0 - 4) * 50;
+      aperture  = pow (2, (get2(),(short)get2())/64.0);
+      shutter   = pow (2,-((short)get2())/32.0);
+      wbi = (get2(),get2());
+      if (wbi > 17) wbi = 0;
+      fseek (ifp, 32, SEEK_CUR);
+      if (shutter > 1e6) shutter = get2()/10.0;
+    }
+    if (type == 0x102c) {
+      if (get2() > 512) {		/* Pro90, G1 */
+	fseek (ifp, 118, SEEK_CUR);
+	FORC4 cam_mul[c ^ 2] = get2();
+      } else {				/* G2, S30, S40 */
+	fseek (ifp, 98, SEEK_CUR);
+	FORC4 cam_mul[c ^ (c >> 1) ^ 1] = get2();
+      }
+    }
+    if (type == 0x0032) {
+      if (len == 768) {			/* EOS D30 */
+	fseek (ifp, 72, SEEK_CUR);
+	FORC4 cam_mul[c ^ (c >> 1)] = 1024.0 / get2();
+	if (!wbi) cam_mul[0] = -1;	/* use my auto white balance */
+      } else if (!cam_mul[0]) {
+	if (get2() == key[0])		/* Pro1, G6, S60, S70 */
+	  c = (strstr(model,"Pro1") ?
+	      "012346000000000000":"01345:000000006008")[wbi]-'0'+ 2;
+	else {				/* G3, G5, S45, S50 */
+	  c = "023457000000006000"[wbi]-'0';
+	  key[0] = key[1] = 0;
+	}
+	fseek (ifp, 78 + c*8, SEEK_CUR);
+	FORC4 cam_mul[c ^ (c >> 1) ^ 1] = get2() ^ key[c & 1];
+	if (!wbi) cam_mul[0] = -1;
+      }
+    }
+    if (type == 0x10a9) {		/* D60, 10D, 300D, and clones */
+      if (len > 66) wbi = "0134567028"[wbi]-'0';
+      fseek (ifp, 2 + wbi*8, SEEK_CUR);
+      FORC4 cam_mul[c ^ (c >> 1)] = get2();
+    }
+    if (type == 0x1030 && (0x18040 >> wbi & 1))
+      ciff_block_1030();		/* all that don't have 0x10a9 */
+    if (type == 0x1031) {
+      raw_width = (get2(),get2());
+      raw_height = get2();
+    }
+    if (type == 0x5029) {
+      focal_len = len >> 16;
+      if ((len & 0xffff) == 2) focal_len /= 32;
+    }
+    if (type == 0x5813) flash_used = int_to_float(len);
+    if (type == 0x5814) canon_ev   = int_to_float(len);
+    if (type == 0x5817) shot_order = len;
+    if (type == 0x5834) unique_id  = len;
+    if (type == 0x580e) timestamp  = len;
+    if (type == 0x180e) timestamp  = get4();
+#ifdef LOCALTIME
+    if ((type | 0x4000) == 0x580e)
+      timestamp = mktime (gmtime (&timestamp));
+#endif
+    fseek (ifp, save, SEEK_SET);
+  }
+}
+
+void CLASS parse_rollei()
+{
+  char line[128], *val;
+  struct tm t;
+
+  fseek (ifp, 0, SEEK_SET);
+  memset (&t, 0, sizeof t);
+  do {
+    fgets (line, 128, ifp);
+    if ((val = strchr(line,'=')))
+      *val++ = 0;
+    else
+      val = line + strlen(line);
+    if (!strcmp(line,"DAT"))
+      sscanf (val, "%d.%d.%d", &t.tm_mday, &t.tm_mon, &t.tm_year);
+    if (!strcmp(line,"TIM"))
+      sscanf (val, "%d:%d:%d", &t.tm_hour, &t.tm_min, &t.tm_sec);
+    if (!strcmp(line,"HDR"))
+      thumb_offset = atoi(val);
+    if (!strcmp(line,"X  "))
+      raw_width = atoi(val);
+    if (!strcmp(line,"Y  "))
+      raw_height = atoi(val);
+    if (!strcmp(line,"TX "))
+      thumb_width = atoi(val);
+    if (!strcmp(line,"TY "))
+      thumb_height = atoi(val);
+  } while (strncmp(line,"EOHD",4));
+  data_offset = thumb_offset + thumb_width * thumb_height * 2;
+  t.tm_year -= 1900;
+  t.tm_mon -= 1;
+  if (mktime(&t) > 0)
+    timestamp = mktime(&t);
+  strcpy (make, "Rollei");
+  strcpy (model,"d530flex");
+  write_thumb = &CLASS rollei_thumb;
+}
+
+void CLASS parse_sinar_ia()
+{
+  int entries, off;
+  char str[8], *cp;
+
+  order = 0x4949;
+  fseek (ifp, 4, SEEK_SET);
+  entries = get4();
+  fseek (ifp, get4(), SEEK_SET);
+  while (entries--) {
+    off = get4(); get4();
+    fread (str, 8, 1, ifp);
+    if (!strcmp(str,"META"))   meta_offset = off;
+    if (!strcmp(str,"THUMB")) thumb_offset = off;
+    if (!strcmp(str,"RAW0"))   data_offset = off;
+  }
+  fseek (ifp, meta_offset+20, SEEK_SET);
+  fread (make, 64, 1, ifp);
+  make[63] = 0;
+  if ((cp = strchr(make,' '))) {
+    strcpy (model, cp+1);
+    *cp = 0;
+  }
+  raw_width  = get2();
+  raw_height = get2();
+  load_raw = &CLASS unpacked_load_raw;
+  thumb_width = (get4(),get2());
+  thumb_height = get2();
+  write_thumb = &CLASS ppm_thumb;
+  maximum = 0x3fff;
+}
+
+void CLASS parse_phase_one (int base)
+{
+  unsigned entries, tag, type, len, data, save, i, c;
+  float romm_cam[3][3];
+  char *cp;
+
+  memset (&ph1, 0, sizeof ph1);
+  fseek (ifp, base, SEEK_SET);
+  order = get4() & 0xffff;
+  if (get4() >> 8 != 0x526177) return;		/* "Raw" */
+  fseek (ifp, get4()+base, SEEK_SET);
+  entries = get4();
+  get4();
+  while (entries--) {
+    tag  = get4();
+    type = get4();
+    len  = get4();
+    data = get4();
+    save = ftell(ifp);
+    fseek (ifp, base+data, SEEK_SET);
+    switch (tag) {
+      case 0x100:  flip = "0653"[data & 3]-'0';  break;
+      case 0x106:
+	for (i=0; i < 9; i++)
+	  romm_cam[0][i] = getreal(11);
+	romm_coeff (romm_cam);
+	break;
+      case 0x107:
+	FORC3 cam_mul[c] = getreal(11);
+	break;
+      case 0x108:  raw_width     = data;	break;
+      case 0x109:  raw_height    = data;	break;
+      case 0x10a:  left_margin   = data;	break;
+      case 0x10b:  top_margin    = data;	break;
+      case 0x10c:  width         = data;	break;
+      case 0x10d:  height        = data;	break;
+      case 0x10e:  ph1.format    = data;	break;
+      case 0x10f:  data_offset   = data+base;	break;
+      case 0x110:  meta_offset   = data+base;
+		   meta_length   = len;			break;
+      case 0x112:  ph1.key_off   = save - 4;		break;
+      case 0x210:  ph1.tag_210   = int_to_float(data);	break;
+      case 0x21a:  ph1.tag_21a   = data;		break;
+      case 0x21c:  strip_offset  = data+base;		break;
+      case 0x21d:  ph1.black     = data;		break;
+      case 0x222:  ph1.split_col = data - left_margin;	break;
+      case 0x223:  ph1.black_off = data+base;		break;
+      case 0x301:
+	model[63] = 0;
+	fread (model, 1, 63, ifp);
+	if ((cp = strstr(model," camera"))) *cp = 0;
+    }
+    fseek (ifp, save, SEEK_SET);
+  }
+  load_raw = ph1.format < 3 ?
+	&CLASS phase_one_load_raw : &CLASS phase_one_load_raw_c;
+  maximum = 0xffff;
+  strcpy (make, "Phase One");
+  if (model[0]) return;
+  switch (raw_height) {
+    case 2060: strcpy (model,"LightPhase");	break;
+    case 2682: strcpy (model,"H 10");		break;
+    case 4128: strcpy (model,"H 20");		break;
+    case 5488: strcpy (model,"H 25");		break;
+  }
+}
+
+void CLASS parse_fuji (int offset)
+{
+  unsigned entries, tag, len, save, c;
+
+  fseek (ifp, offset, SEEK_SET);
+  entries = get4();
+  if (entries > 255) return;
+  while (entries--) {
+    tag = get2();
+    len = get2();
+    save = ftell(ifp);
+    if (tag == 0x100) {
+      raw_height = get2();
+      raw_width  = get2();
+    } else if (tag == 0x121) {
+      height = get2();
+      if ((width = get2()) == 4284) width += 3;
+    } else if (tag == 0x130) {
+      fuji_layout = fgetc(ifp) >> 7;
+      load_raw = fgetc(ifp) & 8 ?
+	&CLASS unpacked_load_raw : &CLASS fuji_load_raw;
+    }
+    if (tag == 0x2ff0)
+      FORC4 cam_mul[c ^ 1] = get2();
+    fseek (ifp, save+len, SEEK_SET);
+  }
+  height <<= fuji_layout;
+  width  >>= fuji_layout;
+}
+
+int CLASS parse_jpeg (int offset)
+{
+  int len, save, hlen, mark;
+
+  fseek (ifp, offset, SEEK_SET);
+  if (fgetc(ifp) != 0xff || fgetc(ifp) != 0xd8) return 0;
+
+  while (fgetc(ifp) == 0xff && (mark = fgetc(ifp)) != 0xda) {
+    order = 0x4d4d;
+    len   = get2() - 2;
+    save  = ftell(ifp);
+    if (mark == 0xc0 || mark == 0xc3) {
+      fgetc(ifp);
+      raw_height = get2();
+      raw_width  = get2();
+    }
+    order = get2();
+    hlen  = get4();
+    if (get4() == 0x48454150)		/* "HEAP" */
+      parse_ciff (save+hlen, len-hlen);
+    parse_tiff (save+6);
+    fseek (ifp, save+len, SEEK_SET);
+  }
+  return 1;
+}
+
+void CLASS parse_riff()
+{
+  unsigned i, size, end;
+  char tag[4], date[64], month[64];
+  static const char mon[12][4] =
+  { "Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec" };
+  struct tm t;
+
+  order = 0x4949;
+  fread (tag, 4, 1, ifp);
+  size = get4();
+  end = ftell(ifp) + size;
+  if (!memcmp(tag,"RIFF",4) || !memcmp(tag,"LIST",4)) {
+    get4();
+    while (ftell(ifp)+7 < end)
+      parse_riff();
+  } else if (!memcmp(tag,"nctg",4)) {
+    while (ftell(ifp)+7 < end) {
+      i = get2();
+      size = get2();
+      if ((i+1) >> 1 == 10 && size == 20)
+	get_timestamp(0);
+      else fseek (ifp, size, SEEK_CUR);
+    }
+  } else if (!memcmp(tag,"IDIT",4) && size < 64) {
+    fread (date, 64, 1, ifp);
+    date[size] = 0;
+    memset (&t, 0, sizeof t);
+    if (sscanf (date, "%*s %s %d %d:%d:%d %d", month, &t.tm_mday,
+	&t.tm_hour, &t.tm_min, &t.tm_sec, &t.tm_year) == 6) {
+      for (i=0; i < 12 && strcasecmp(mon[i],month); i++);
+      t.tm_mon = i;
+      t.tm_year -= 1900;
+      if (mktime(&t) > 0)
+	timestamp = mktime(&t);
+    }
+  } else
+    fseek (ifp, size, SEEK_CUR);
+}
+
+void CLASS parse_smal (int offset, int fsize)
+{
+  int ver;
+
+  fseek (ifp, offset+2, SEEK_SET);
+  order = 0x4949;
+  ver = fgetc(ifp);
+  if (ver == 6)
+    fseek (ifp, 5, SEEK_CUR);
+  if (get4() != fsize) return;
+  if (ver > 6) data_offset = get4();
+  raw_height = height = get2();
+  raw_width  = width  = get2();
+  strcpy (make, "SMaL");
+  sprintf (model, "v%d %dx%d", ver, width, height);
+  if (ver == 6) load_raw = &CLASS smal_v6_load_raw;
+  if (ver == 9) load_raw = &CLASS smal_v9_load_raw;
+}
+
+void CLASS parse_cine()
+{
+  unsigned off_head, off_setup, off_image, i;
+
+  order = 0x4949;
+  fseek (ifp, 4, SEEK_SET);
+  is_raw = get2() == 2;
+  fseek (ifp, 14, SEEK_CUR);
+  is_raw *= get4();
+  off_head = get4();
+  off_setup = get4();
+  off_image = get4();
+  timestamp = get4();
+  if ((i = get4())) timestamp = i;
+  fseek (ifp, off_head+4, SEEK_SET);
+  raw_width = get4();
+  raw_height = get4();
+  switch (get2(),get2()) {
+    case  8:  load_raw = &CLASS eight_bit_load_raw;  break;
+    case 16:  load_raw = &CLASS  unpacked_load_raw;
+  }
+  fseek (ifp, off_setup+792, SEEK_SET);
+  strcpy (make, "CINE");
+  sprintf (model, "%d", get4());
+  fseek (ifp, 12, SEEK_CUR);
+  switch ((i=get4()) & 0xffffff) {
+    case  3:  filters = 0x94949494;  break;
+    case  4:  filters = 0x49494949;  break;
+    default:  is_raw = 0;
+  }
+  fseek (ifp, 72, SEEK_CUR);
+  switch ((get4()+3600) % 360) {
+    case 270:  flip = 4;  break;
+    case 180:  flip = 1;  break;
+    case  90:  flip = 7;  break;
+    case   0:  flip = 2;
+  }
+  cam_mul[0] = getreal(11);
+  cam_mul[2] = getreal(11);
+  maximum = ~(-1 << get4());
+  fseek (ifp, 668, SEEK_CUR);
+  shutter = get4()/1000000000.0;
+  fseek (ifp, off_image, SEEK_SET);
+  if (shot_select < is_raw)
+    fseek (ifp, shot_select*8, SEEK_CUR);
+  data_offset  = (INT64) get4() + 8;
+  data_offset += (INT64) get4() << 32;
+}
+
+char * CLASS foveon_gets (int offset, char *str, int len)
+{
+  int i;
+  fseek (ifp, offset, SEEK_SET);
+  for (i=0; i < len-1; i++)
+    if ((str[i] = get2()) == 0) break;
+  str[i] = 0;
+  return str;
+}
+
+void CLASS parse_foveon()
+{
+  int entries, img=0, off, len, tag, save, i, wide, high, pent, poff[256][2];
+  char name[64], value[64];
+
+  order = 0x4949;			/* Little-endian */
+  fseek (ifp, 36, SEEK_SET);
+  flip = get4();
+  fseek (ifp, -4, SEEK_END);
+  fseek (ifp, get4(), SEEK_SET);
+  if (get4() != 0x64434553) return;	/* SECd */
+  entries = (get4(),get4());
+  while (entries--) {
+    off = get4();
+    len = get4();
+    tag = get4();
+    save = ftell(ifp);
+    fseek (ifp, off, SEEK_SET);
+    if (get4() != (0x20434553 | (tag << 24))) return;
+    switch (tag) {
+      case 0x47414d49:			/* IMAG */
+      case 0x32414d49:			/* IMA2 */
+	fseek (ifp, 12, SEEK_CUR);
+	wide = get4();
+	high = get4();
+	if (wide > raw_width && high > raw_height) {
+	  raw_width  = wide;
+	  raw_height = high;
+	  data_offset = off+24;
+	}
+	fseek (ifp, off+28, SEEK_SET);
+	if (fgetc(ifp) == 0xff && fgetc(ifp) == 0xd8
+		&& thumb_length < len-28) {
+	  thumb_offset = off+28;
+	  thumb_length = len-28;
+	  write_thumb = &CLASS jpeg_thumb;
+	}
+	if (++img == 2 && !thumb_length) {
+	  thumb_offset = off+24;
+	  thumb_width = wide;
+	  thumb_height = high;
+	  write_thumb = &CLASS foveon_thumb;
+	}
+	break;
+      case 0x464d4143:			/* CAMF */
+	meta_offset = off+24;
+	meta_length = len-28;
+	if (meta_length > 0x20000)
+	    meta_length = 0x20000;
+	break;
+      case 0x504f5250:			/* PROP */
+	pent = (get4(),get4());
+	fseek (ifp, 12, SEEK_CUR);
+	off += pent*8 + 24;
+	if ((unsigned) pent > 256) pent=256;
+	for (i=0; i < pent*2; i++)
+	  poff[0][i] = off + get4()*2;
+	for (i=0; i < pent; i++) {
+	  foveon_gets (poff[i][0], name, 64);
+	  foveon_gets (poff[i][1], value, 64);
+	  if (!strcmp (name, "ISO"))
+	    iso_speed = atoi(value);
+	  if (!strcmp (name, "CAMMANUF"))
+	    strcpy (make, value);
+	  if (!strcmp (name, "CAMMODEL"))
+	    strcpy (model, value);
+	  if (!strcmp (name, "WB_DESC"))
+	    strcpy (model2, value);
+	  if (!strcmp (name, "TIME"))
+	    timestamp = atoi(value);
+	  if (!strcmp (name, "EXPTIME"))
+	    shutter = atoi(value) / 1000000.0;
+	  if (!strcmp (name, "APERTURE"))
+	    aperture = atof(value);
+	  if (!strcmp (name, "FLENGTH"))
+	    focal_len = atof(value);
+	}
+#ifdef LOCALTIME
+	timestamp = mktime (gmtime (&timestamp));
+#endif
+    }
+    fseek (ifp, save, SEEK_SET);
+  }
+  is_foveon = 1;
+}
+
+/*
+   All matrices are from Adobe DNG Converter unless otherwise noted.
+ */
+void CLASS adobe_coeff (const char *make, const char *model)
+{
+  static const struct {
+    const char *prefix;
+    short black, maximum, trans[12];
+  } table[] = {
+    { "AGFAPHOTO DC-833m", 0, 0,	/* DJC */
+	{ 11438,-3762,-1115,-2409,9914,2497,-1227,2295,5300 } },
+    { "Apple QuickTake", 0, 0,		/* DJC */
+	{ 21392,-5653,-3353,2406,8010,-415,7166,1427,2078 } },
+    { "Canon EOS D2000", 0, 0,
+	{ 24542,-10860,-3401,-1490,11370,-297,2858,-605,3225 } },
+    { "Canon EOS D6000", 0, 0,
+	{ 20482,-7172,-3125,-1033,10410,-285,2542,226,3136 } },
+    { "Canon EOS D30", 0, 0,
+	{ 9805,-2689,-1312,-5803,13064,3068,-2438,3075,8775 } },
+    { "Canon EOS D60", 0, 0xfa0,
+	{ 6188,-1341,-890,-7168,14489,2937,-2640,3228,8483 } },
+    { "Canon EOS 5D Mark II", 0, 0x3cf0,
+	{ 4716,603,-830,-7798,15474,2480,-1496,1937,6651 } },
+    { "Canon EOS 5D", 0, 0xe6c,
+	{ 6347,-479,-972,-8297,15954,2480,-1968,2131,7649 } },
+    { "Canon EOS 7D", 0, 0x3510,
+	{ 6844,-996,-856,-3876,11761,2396,-593,1772,6198 } },
+    { "Canon EOS 10D", 0, 0xfa0,
+	{ 8197,-2000,-1118,-6714,14335,2592,-2536,3178,8266 } },
+    { "Canon EOS 20Da", 0, 0,
+	{ 14155,-5065,-1382,-6550,14633,2039,-1623,1824,6561 } },
+    { "Canon EOS 20D", 0, 0xfff,
+	{ 6599,-537,-891,-8071,15783,2424,-1983,2234,7462 } },
+    { "Canon EOS 30D", 0, 0,
+	{ 6257,-303,-1000,-7880,15621,2396,-1714,1904,7046 } },
+    { "Canon EOS 40D", 0, 0x3f60,
+	{ 6071,-747,-856,-7653,15365,2441,-2025,2553,7315 } },
+    { "Canon EOS 50D", 0, 0x3d93,
+	{ 4920,616,-593,-6493,13964,2784,-1774,3178,7005 } },
+    { "Canon EOS 300D", 0, 0xfa0,
+	{ 8197,-2000,-1118,-6714,14335,2592,-2536,3178,8266 } },
+    { "Canon EOS 350D", 0, 0xfff,
+	{ 6018,-617,-965,-8645,15881,2975,-1530,1719,7642 } },
+    { "Canon EOS 400D", 0, 0xe8e,
+	{ 7054,-1501,-990,-8156,15544,2812,-1278,1414,7796 } },
+    { "Canon EOS 450D", 0, 0x390d,
+	{ 5784,-262,-821,-7539,15064,2672,-1982,2681,7427 } },
+    { "Canon EOS 500D", 0, 0x3479,
+	{ 4763,712,-646,-6821,14399,2640,-1921,3276,6561 } },
+    { "Canon EOS 1000D", 0, 0xe43,
+	{ 6771,-1139,-977,-7818,15123,2928,-1244,1437,7533 } },
+    { "Canon EOS-1Ds Mark III", 0, 0x3bb0,
+	{ 5859,-211,-930,-8255,16017,2353,-1732,1887,7448 } },
+    { "Canon EOS-1Ds Mark II", 0, 0xe80,
+	{ 6517,-602,-867,-8180,15926,2378,-1618,1771,7633 } },
+    { "Canon EOS-1D Mark IV", 0, 0x3bb0,
+	{ 6014,-220,-795,-4109,12014,2361,-561,1824,5787 } },
+    { "Canon EOS-1D Mark III", 0, 0x3bb0,
+	{ 6291,-540,-976,-8350,16145,2311,-1714,1858,7326 } },
+    { "Canon EOS-1D Mark II N", 0, 0xe80,
+	{ 6240,-466,-822,-8180,15825,2500,-1801,1938,8042 } },
+    { "Canon EOS-1D Mark II", 0, 0xe80,
+	{ 6264,-582,-724,-8312,15948,2504,-1744,1919,8664 } },
+    { "Canon EOS-1DS", 0, 0xe20,
+	{ 4374,3631,-1743,-7520,15212,2472,-2892,3632,8161 } },
+    { "Canon EOS-1D", 0, 0xe20,
+	{ 6806,-179,-1020,-8097,16415,1687,-3267,4236,7690 } },
+    { "Canon EOS", 0, 0,
+	{ 8197,-2000,-1118,-6714,14335,2592,-2536,3178,8266 } },
+    { "Canon PowerShot A530", 0, 0,
+	{ 0 } },	/* don't want the A5 matrix */	
+    { "Canon PowerShot A50", 0, 0,
+	{ -5300,9846,1776,3436,684,3939,-5540,9879,6200,-1404,11175,217 } },
+    { "Canon PowerShot A5", 0, 0,
+	{ -4801,9475,1952,2926,1611,4094,-5259,10164,5947,-1554,10883,547 } },
+    { "Canon PowerShot G10", 0, 0,
+	{ 11093,-3906,-1028,-5047,12492,2879,-1003,1750,5561 } },
+    { "Canon PowerShot G11", 0, 0,
+	{ 12177,-4817,-1069,-1612,9864,2049,-98,850,4471 } },
+    { "Canon PowerShot G1", 0, 0,
+	{ -4778,9467,2172,4743,-1141,4344,-5146,9908,6077,-1566,11051,557 } },
+    { "Canon PowerShot G2", 0, 0,
+	{ 9087,-2693,-1049,-6715,14382,2537,-2291,2819,7790 } },
+    { "Canon PowerShot G3", 0, 0,
+	{ 9212,-2781,-1073,-6573,14189,2605,-2300,2844,7664 } },
+    { "Canon PowerShot G5", 0, 0,
+	{ 9757,-2872,-933,-5972,13861,2301,-1622,2328,7212 } },
+    { "Canon PowerShot G6", 0, 0,
+	{ 9877,-3775,-871,-7613,14807,3072,-1448,1305,7485 } },
+    { "Canon PowerShot G9", 0, 0,
+	{ 7368,-2141,-598,-5621,13254,2625,-1418,1696,5743 } },
+    { "Canon PowerShot Pro1", 0, 0,
+	{ 10062,-3522,-999,-7643,15117,2730,-765,817,7323 } },
+    { "Canon PowerShot Pro70", 34, 0,
+	{ -4155,9818,1529,3939,-25,4522,-5521,9870,6610,-2238,10873,1342 } },
+    { "Canon PowerShot Pro90", 0, 0,
+	{ -4963,9896,2235,4642,-987,4294,-5162,10011,5859,-1770,11230,577 } },
+    { "Canon PowerShot S30", 0, 0,
+	{ 10566,-3652,-1129,-6552,14662,2006,-2197,2581,7670 } },
+    { "Canon PowerShot S40", 0, 0,
+	{ 8510,-2487,-940,-6869,14231,2900,-2318,2829,9013 } },
+    { "Canon PowerShot S45", 0, 0,
+	{ 8163,-2333,-955,-6682,14174,2751,-2077,2597,8041 } },
+    { "Canon PowerShot S50", 0, 0,
+	{ 8882,-2571,-863,-6348,14234,2288,-1516,2172,6569 } },
+    { "Canon PowerShot S60", 0, 0,
+	{ 8795,-2482,-797,-7804,15403,2573,-1422,1996,7082 } },
+    { "Canon PowerShot S70", 0, 0,
+	{ 9976,-3810,-832,-7115,14463,2906,-901,989,7889 } },
+    { "Canon PowerShot S90", 0, 0,
+	{ 12374,-5016,-1049,-1677,9902,2078,-83,852,4683 } },
+    { "Canon PowerShot A470", 0, 0,	/* DJC */
+	{ 12513,-4407,-1242,-2680,10276,2405,-878,2215,4734 } },
+    { "Canon PowerShot A610", 0, 0,	/* DJC */
+	{ 15591,-6402,-1592,-5365,13198,2168,-1300,1824,5075 } },
+    { "Canon PowerShot A620", 0, 0,	/* DJC */
+	{ 15265,-6193,-1558,-4125,12116,2010,-888,1639,5220 } },
+    { "Canon PowerShot A630", 0, 0,	/* DJC */
+	{ 14201,-5308,-1757,-6087,14472,1617,-2191,3105,5348 } },
+    { "Canon PowerShot A640", 0, 0,	/* DJC */
+	{ 13124,-5329,-1390,-3602,11658,1944,-1612,2863,4885 } },
+    { "Canon PowerShot A650", 0, 0,	/* DJC */
+	{ 9427,-3036,-959,-2581,10671,1911,-1039,1982,4430 } },
+    { "Canon PowerShot A720", 0, 0,	/* DJC */
+	{ 14573,-5482,-1546,-1266,9799,1468,-1040,1912,3810 } },
+    { "Canon PowerShot S3 IS", 0, 0,	/* DJC */
+	{ 14062,-5199,-1446,-4712,12470,2243,-1286,2028,4836 } },
+    { "Canon PowerShot SX1 IS", 0, 0,
+	{ 6578,-259,-502,-5974,13030,3309,-308,1058,4970 } },
+    { "Canon PowerShot SX110 IS", 0, 0,	/* DJC */
+        { 14134,-5576,-1527,-1991,10719,1273,-1158,1929,3581 } },
+    { "CASIO EX-S20", 0, 0,		/* DJC */
+	{ 11634,-3924,-1128,-4968,12954,2015,-1588,2648,7206 } },
+    { "CASIO EX-Z750", 0, 0,		/* DJC */
+	{ 10819,-3873,-1099,-4903,13730,1175,-1755,3751,4632 } },
+    { "CINE 650", 0, 0,
+	{ 3390,480,-500,-800,3610,340,-550,2336,1192 } },
+    { "CINE 660", 0, 0,
+	{ 3390,480,-500,-800,3610,340,-550,2336,1192 } },
+    { "CINE", 0, 0,
+	{ 20183,-4295,-423,-3940,15330,3985,-280,4870,9800 } },
+    { "Contax N Digital", 0, 0xf1e,
+	{ 7777,1285,-1053,-9280,16543,2916,-3677,5679,7060 } },
+    { "EPSON R-D1", 0, 0,
+	{ 6827,-1878,-732,-8429,16012,2564,-704,592,7145 } },
+    { "FUJIFILM FinePix E550", 0, 0,
+	{ 11044,-3888,-1120,-7248,15168,2208,-1531,2277,8069 } },
+    { "FUJIFILM FinePix E900", 0, 0,
+	{ 9183,-2526,-1078,-7461,15071,2574,-2022,2440,8639 } },
+    { "FUJIFILM FinePix F8", 0, 0,
+	{ 11044,-3888,-1120,-7248,15168,2208,-1531,2277,8069 } },
+    { "FUJIFILM FinePix F7", 0, 0,
+	{ 10004,-3219,-1201,-7036,15047,2107,-1863,2565,7736 } },
+    { "FUJIFILM FinePix S100FS", 514, 0,
+	{ 11521,-4355,-1065,-6524,13767,3058,-1466,1984,6045 } },
+    { "FUJIFILM FinePix S20Pro", 0, 0,
+	{ 10004,-3219,-1201,-7036,15047,2107,-1863,2565,7736 } },
+    { "FUJIFILM FinePix S2Pro", 128, 0,
+	{ 12492,-4690,-1402,-7033,15423,1647,-1507,2111,7697 } },
+    { "FUJIFILM FinePix S3Pro", 0, 0,
+	{ 11807,-4612,-1294,-8927,16968,1988,-2120,2741,8006 } },
+    { "FUJIFILM FinePix S5Pro", 0, 0,
+	{ 12300,-5110,-1304,-9117,17143,1998,-1947,2448,8100 } },
+    { "FUJIFILM FinePix S5000", 0, 0,
+	{ 8754,-2732,-1019,-7204,15069,2276,-1702,2334,6982 } },
+    { "FUJIFILM FinePix S5100", 0, 0x3e00,
+	{ 11940,-4431,-1255,-6766,14428,2542,-993,1165,7421 } },
+    { "FUJIFILM FinePix S5500", 0, 0x3e00,
+	{ 11940,-4431,-1255,-6766,14428,2542,-993,1165,7421 } },
+    { "FUJIFILM FinePix S5200", 0, 0,
+	{ 9636,-2804,-988,-7442,15040,2589,-1803,2311,8621 } },
+    { "FUJIFILM FinePix S5600", 0, 0,
+	{ 9636,-2804,-988,-7442,15040,2589,-1803,2311,8621 } },
+    { "FUJIFILM FinePix S6", 0, 0,
+	{ 12628,-4887,-1401,-6861,14996,1962,-2198,2782,7091 } },
+    { "FUJIFILM FinePix S7000", 0, 0,
+	{ 10190,-3506,-1312,-7153,15051,2238,-2003,2399,7505 } },
+    { "FUJIFILM FinePix S9000", 0, 0,
+	{ 10491,-3423,-1145,-7385,15027,2538,-1809,2275,8692 } },
+    { "FUJIFILM FinePix S9500", 0, 0,
+	{ 10491,-3423,-1145,-7385,15027,2538,-1809,2275,8692 } },
+    { "FUJIFILM FinePix S9100", 0, 0,
+	{ 12343,-4515,-1285,-7165,14899,2435,-1895,2496,8800 } },
+    { "FUJIFILM FinePix S9600", 0, 0,
+	{ 12343,-4515,-1285,-7165,14899,2435,-1895,2496,8800 } },
+    { "FUJIFILM IS-1", 0, 0,
+	{ 21461,-10807,-1441,-2332,10599,1999,289,875,7703 } },
+    { "FUJIFILM IS Pro", 0, 0,
+	{ 12300,-5110,-1304,-9117,17143,1998,-1947,2448,8100 } },
+    { "Imacon Ixpress", 0, 0,		/* DJC */
+	{ 7025,-1415,-704,-5188,13765,1424,-1248,2742,6038 } },
+    { "KODAK NC2000", 0, 0,
+	{ 13891,-6055,-803,-465,9919,642,2121,82,1291 } },
+    { "Kodak DCS315C", 8, 0,
+	{ 17523,-4827,-2510,756,8546,-137,6113,1649,2250 } },
+    { "Kodak DCS330C", 8, 0,
+	{ 20620,-7572,-2801,-103,10073,-396,3551,-233,2220 } },
+    { "KODAK DCS420", 0, 0,
+	{ 10868,-1852,-644,-1537,11083,484,2343,628,2216 } },
+    { "KODAK DCS460", 0, 0,
+	{ 10592,-2206,-967,-1944,11685,230,2206,670,1273 } },
+    { "KODAK EOSDCS1", 0, 0,
+	{ 10592,-2206,-967,-1944,11685,230,2206,670,1273 } },
+    { "KODAK EOSDCS3B", 0, 0,
+	{ 9898,-2700,-940,-2478,12219,206,1985,634,1031 } },
+    { "Kodak DCS520C", 180, 0,
+	{ 24542,-10860,-3401,-1490,11370,-297,2858,-605,3225 } },
+    { "Kodak DCS560C", 188, 0,
+	{ 20482,-7172,-3125,-1033,10410,-285,2542,226,3136 } },
+    { "Kodak DCS620C", 180, 0,
+	{ 23617,-10175,-3149,-2054,11749,-272,2586,-489,3453 } },
+    { "Kodak DCS620X", 185, 0,
+	{ 13095,-6231,154,12221,-21,-2137,895,4602,2258 } },
+    { "Kodak DCS660C", 214, 0,
+	{ 18244,-6351,-2739,-791,11193,-521,3711,-129,2802 } },
+    { "Kodak DCS720X", 0, 0,
+	{ 11775,-5884,950,9556,1846,-1286,-1019,6221,2728 } },
+    { "Kodak DCS760C", 0, 0,
+	{ 16623,-6309,-1411,-4344,13923,323,2285,274,2926 } },
+    { "Kodak DCS Pro SLR", 0, 0,
+	{ 5494,2393,-232,-6427,13850,2846,-1876,3997,5445 } },
+    { "Kodak DCS Pro 14nx", 0, 0,
+	{ 5494,2393,-232,-6427,13850,2846,-1876,3997,5445 } },
+    { "Kodak DCS Pro 14", 0, 0,
+	{ 7791,3128,-776,-8588,16458,2039,-2455,4006,6198 } },
+    { "Kodak ProBack645", 0, 0,
+	{ 16414,-6060,-1470,-3555,13037,473,2545,122,4948 } },
+    { "Kodak ProBack", 0, 0,
+	{ 21179,-8316,-2918,-915,11019,-165,3477,-180,4210 } },
+    { "KODAK P712", 0, 0,
+	{ 9658,-3314,-823,-5163,12695,2768,-1342,1843,6044 } },
+    { "KODAK P850", 0, 0xf7c,
+	{ 10511,-3836,-1102,-6946,14587,2558,-1481,1792,6246 } },
+    { "KODAK P880", 0, 0xfff,
+	{ 12805,-4662,-1376,-7480,15267,2360,-1626,2194,7904 } },
+    { "KODAK EasyShare Z980", 0, 0,
+	{ 11313,-3559,-1101,-3893,11891,2257,-1214,2398,4908 } },
+    { "KODAK EASYSHARE Z1015", 0, 0xef1,
+	{ 11265,-4286,-992,-4694,12343,2647,-1090,1523,5447 } },
+    { "Leaf CMost", 0, 0,
+	{ 3952,2189,449,-6701,14585,2275,-4536,7349,6536 } },
+    { "Leaf Valeo 6", 0, 0,
+	{ 3952,2189,449,-6701,14585,2275,-4536,7349,6536 } },
+    { "Leaf Aptus 54S", 0, 0,
+	{ 8236,1746,-1314,-8251,15953,2428,-3673,5786,5771 } },
+    { "Leaf Aptus 65", 0, 0,
+	{ 7914,1414,-1190,-8777,16582,2280,-2811,4605,5562 } },
+    { "Leaf Aptus 75", 0, 0,
+	{ 7914,1414,-1190,-8777,16582,2280,-2811,4605,5562 } },
+    { "Leaf", 0, 0,
+	{ 8236,1746,-1314,-8251,15953,2428,-3673,5786,5771 } },
+    { "Mamiya ZD", 0, 0,
+	{ 7645,2579,-1363,-8689,16717,2015,-3712,5941,5961 } },
+    { "Micron 2010", 110, 0,		/* DJC */
+	{ 16695,-3761,-2151,155,9682,163,3433,951,4904 } },
+    { "Minolta DiMAGE 5", 0, 0xf7d,
+	{ 8983,-2942,-963,-6556,14476,2237,-2426,2887,8014 } },
+    { "Minolta DiMAGE 7Hi", 0, 0xf7d,
+	{ 11368,-3894,-1242,-6521,14358,2339,-2475,3056,7285 } },
+    { "Minolta DiMAGE 7", 0, 0xf7d,
+	{ 9144,-2777,-998,-6676,14556,2281,-2470,3019,7744 } },
+    { "Minolta DiMAGE A1", 0, 0xf8b,
+	{ 9274,-2547,-1167,-8220,16323,1943,-2273,2720,8340 } },
+    { "MINOLTA DiMAGE A200", 0, 0,
+	{ 8560,-2487,-986,-8112,15535,2771,-1209,1324,7743 } },
+    { "Minolta DiMAGE A2", 0, 0xf8f,
+	{ 9097,-2726,-1053,-8073,15506,2762,-966,981,7763 } },
+    { "Minolta DiMAGE Z2", 0, 0,	/* DJC */
+	{ 11280,-3564,-1370,-4655,12374,2282,-1423,2168,5396 } },
+    { "MINOLTA DYNAX 5", 0, 0xffb,
+	{ 10284,-3283,-1086,-7957,15762,2316,-829,882,6644 } },
+    { "MINOLTA DYNAX 7", 0, 0xffb,
+	{ 10239,-3104,-1099,-8037,15727,2451,-927,925,6871 } },
+    { "MOTOROLA PIXL", 0, 0,		/* DJC */
+	{ 8898,-989,-1033,-3292,11619,1674,-661,3178,5216 } },
+    { "NIKON D100", 0, 0,
+	{ 5902,-933,-782,-8983,16719,2354,-1402,1455,6464 } },
+    { "NIKON D1H", 0, 0,
+	{ 7577,-2166,-926,-7454,15592,1934,-2377,2808,8606 } },
+    { "NIKON D1X", 0, 0,
+	{ 7702,-2245,-975,-9114,17242,1875,-2679,3055,8521 } },
+    { "NIKON D1", 0, 0, /* multiplied by 2.218750, 1.0, 1.148438 */
+	{ 16772,-4726,-2141,-7611,15713,1972,-2846,3494,9521 } },
+    { "NIKON D200", 0, 0xfbc,
+	{ 8367,-2248,-763,-8758,16447,2422,-1527,1550,8053 } },
+    { "NIKON D2H", 0, 0,
+	{ 5710,-901,-615,-8594,16617,2024,-2975,4120,6830 } },
+    { "NIKON D2X", 0, 0,
+	{ 10231,-2769,-1255,-8301,15900,2552,-797,680,7148 } },
+    { "NIKON D3000", 0, 0,
+	{ 8736,-2458,-935,-9075,16894,2251,-1354,1242,8263 } },
+    { "NIKON D300", 0, 0,
+	{ 9030,-1992,-715,-8465,16302,2255,-2689,3217,8069 } },
+    { "NIKON D3X", 0, 0,
+	{ 7171,-1986,-648,-8085,15555,2718,-2170,2512,7457 } },
+    { "NIKON D3S", 0, 0,
+	{ 8828,-2406,-694,-4874,12603,2541,-660,1509,7587 } },
+    { "NIKON D3", 0, 0,
+	{ 8139,-2171,-663,-8747,16541,2295,-1925,2008,8093 } },
+    { "NIKON D40X", 0, 0,
+	{ 8819,-2543,-911,-9025,16928,2151,-1329,1213,8449 } },
+    { "NIKON D40", 0, 0,
+	{ 6992,-1668,-806,-8138,15748,2543,-874,850,7897 } },
+    { "NIKON D5000", 0, 0xf00,
+	{ 7309,-1403,-519,-8474,16008,2622,-2433,2826,8064 } },
+    { "NIKON D50", 0, 0,
+	{ 7732,-2422,-789,-8238,15884,2498,-859,783,7330 } },
+    { "NIKON D60", 0, 0,
+	{ 8736,-2458,-935,-9075,16894,2251,-1354,1242,8263 } },
+    { "NIKON D700", 0, 0,
+	{ 8139,-2171,-663,-8747,16541,2295,-1925,2008,8093 } },
+    { "NIKON D70", 0, 0,
+	{ 7732,-2422,-789,-8238,15884,2498,-859,783,7330 } },
+    { "NIKON D80", 0, 0,
+	{ 8629,-2410,-883,-9055,16940,2171,-1490,1363,8520 } },
+    { "NIKON D90", 0, 0xf00,
+	{ 7309,-1403,-519,-8474,16008,2622,-2434,2826,8064 } },
+    { "NIKON E950", 0, 0x3dd,		/* DJC */
+	{ -3746,10611,1665,9621,-1734,2114,-2389,7082,3064,3406,6116,-244 } },
+    { "NIKON E995", 0, 0,	/* copied from E5000 */
+	{ -5547,11762,2189,5814,-558,3342,-4924,9840,5949,688,9083,96 } },
+    { "NIKON E2100", 0, 0,	/* copied from Z2, new white balance */
+	{ 13142,-4152,-1596,-4655,12374,2282,-1769,2696,6711} },
+    { "NIKON E2500", 0, 0,
+	{ -5547,11762,2189,5814,-558,3342,-4924,9840,5949,688,9083,96 } },
+    { "NIKON E4300", 0, 0,	/* copied from Minolta DiMAGE Z2 */
+	{ 11280,-3564,-1370,-4655,12374,2282,-1423,2168,5396 } },
+    { "NIKON E4500", 0, 0,
+	{ -5547,11762,2189,5814,-558,3342,-4924,9840,5949,688,9083,96 } },
+    { "NIKON E5000", 0, 0,
+	{ -5547,11762,2189,5814,-558,3342,-4924,9840,5949,688,9083,96 } },
+    { "NIKON E5400", 0, 0,
+	{ 9349,-2987,-1001,-7919,15766,2266,-2098,2680,6839 } },
+    { "NIKON E5700", 0, 0,
+	{ -5368,11478,2368,5537,-113,3148,-4969,10021,5782,778,9028,211 } },
+    { "NIKON E8400", 0, 0,
+	{ 7842,-2320,-992,-8154,15718,2599,-1098,1342,7560 } },
+    { "NIKON E8700", 0, 0,
+	{ 8489,-2583,-1036,-8051,15583,2643,-1307,1407,7354 } },
+    { "NIKON E8800", 0, 0,
+	{ 7971,-2314,-913,-8451,15762,2894,-1442,1520,7610 } },
+    { "NIKON COOLPIX P6000", 0, 0,
+	{ 9698,-3367,-914,-4706,12584,2368,-837,968,5801 } },
+    { "OLYMPUS C5050", 0, 0,
+	{ 10508,-3124,-1273,-6079,14294,1901,-1653,2306,6237 } },
+    { "OLYMPUS C5060", 0, 0,
+	{ 10445,-3362,-1307,-7662,15690,2058,-1135,1176,7602 } },
+    { "OLYMPUS C7070", 0, 0,
+	{ 10252,-3531,-1095,-7114,14850,2436,-1451,1723,6365 } },
+    { "OLYMPUS C70", 0, 0,
+	{ 10793,-3791,-1146,-7498,15177,2488,-1390,1577,7321 } },
+    { "OLYMPUS C80", 0, 0,
+	{ 8606,-2509,-1014,-8238,15714,2703,-942,979,7760 } },
+    { "OLYMPUS E-10", 0, 0xffc0,
+	{ 12745,-4500,-1416,-6062,14542,1580,-1934,2256,6603 } },
+    { "OLYMPUS E-1", 0, 0xfff0,
+	{ 11846,-4767,-945,-7027,15878,1089,-2699,4122,8311 } },
+    { "OLYMPUS E-20", 0, 0xffc0,
+	{ 13173,-4732,-1499,-5807,14036,1895,-2045,2452,7142 } },
+    { "OLYMPUS E-300", 0, 0,
+	{ 7828,-1761,-348,-5788,14071,1830,-2853,4518,6557 } },
+    { "OLYMPUS E-330", 0, 0,
+	{ 8961,-2473,-1084,-7979,15990,2067,-2319,3035,8249 } },
+    { "OLYMPUS E-30", 0, 0xfbc,
+	{ 8144,-1861,-1111,-7763,15894,1929,-1865,2542,7607 } },
+    { "OLYMPUS E-3", 0, 0xf99,
+	{ 9487,-2875,-1115,-7533,15606,2010,-1618,2100,7389 } },
+    { "OLYMPUS E-400", 0, 0xfff0,
+	{ 6169,-1483,-21,-7107,14761,2536,-2904,3580,8568 } },
+    { "OLYMPUS E-410", 0, 0xf6a,
+	{ 8856,-2582,-1026,-7761,15766,2082,-2009,2575,7469 } },
+    { "OLYMPUS E-420", 0, 0xfd7,
+	{ 8746,-2425,-1095,-7594,15612,2073,-1780,2309,7416 } },
+    { "OLYMPUS E-450", 0, 0xfd2,
+	{ 8745,-2425,-1095,-7594,15613,2073,-1780,2309,7416 } },
+    { "OLYMPUS E-500", 0, 0xfff0,
+	{ 8136,-1968,-299,-5481,13742,1871,-2556,4205,6630 } },
+    { "OLYMPUS E-510", 0, 0xf6a,
+	{ 8785,-2529,-1033,-7639,15624,2112,-1783,2300,7817 } },
+    { "OLYMPUS E-520", 0, 0xfd2,
+	{ 8344,-2322,-1020,-7596,15635,2048,-1748,2269,7287 } },
+    { "OLYMPUS E-620", 0, 0xfb9,
+	{ 8453,-2198,-1092,-7609,15681,2008,-1725,2337,7824 } },
+    { "OLYMPUS E-P1", 0, 0xffd,
+	{ 8343,-2050,-1021,-7715,15705,2103,-1831,2380,8235 } },
+    { "OLYMPUS SP350", 0, 0,
+	{ 12078,-4836,-1069,-6671,14306,2578,-786,939,7418 } },
+    { "OLYMPUS SP3", 0, 0,
+	{ 11766,-4445,-1067,-6901,14421,2707,-1029,1217,7572 } },
+    { "OLYMPUS SP500UZ", 0, 0xfff,
+	{ 9493,-3415,-666,-5211,12334,3260,-1548,2262,6482 } },
+    { "OLYMPUS SP510UZ", 0, 0xffe,
+	{ 10593,-3607,-1010,-5881,13127,3084,-1200,1805,6721 } },
+    { "OLYMPUS SP550UZ", 0, 0xffe,
+	{ 11597,-4006,-1049,-5432,12799,2957,-1029,1750,6516 } },
+    { "OLYMPUS SP560UZ", 0, 0xff9,
+	{ 10915,-3677,-982,-5587,12986,2911,-1168,1968,6223 } },
+    { "OLYMPUS SP570UZ", 0, 0,
+	{ 11522,-4044,-1146,-4736,12172,2904,-988,1829,6039 } },
+    { "PENTAX *ist DL2", 0, 0,
+	{ 10504,-2438,-1189,-8603,16207,2531,-1022,863,12242 } },
+    { "PENTAX *ist DL", 0, 0,
+	{ 10829,-2838,-1115,-8339,15817,2696,-837,680,11939 } },
+    { "PENTAX *ist DS2", 0, 0,
+	{ 10504,-2438,-1189,-8603,16207,2531,-1022,863,12242 } },
+    { "PENTAX *ist DS", 0, 0,
+	{ 10371,-2333,-1206,-8688,16231,2602,-1230,1116,11282 } },
+    { "PENTAX *ist D", 0, 0,
+	{ 9651,-2059,-1189,-8881,16512,2487,-1460,1345,10687 } },
+    { "PENTAX K10D", 0, 0,
+	{ 9566,-2863,-803,-7170,15172,2112,-818,803,9705 } },
+    { "PENTAX K1", 0, 0,
+	{ 11095,-3157,-1324,-8377,15834,2720,-1108,947,11688 } },
+    { "PENTAX K20D", 0, 0,
+	{ 9427,-2714,-868,-7493,16092,1373,-2199,3264,7180 } },
+    { "PENTAX K200D", 0, 0,
+	{ 9186,-2678,-907,-8693,16517,2260,-1129,1094,8524 } },
+    { "PENTAX K2000", 0, 0,
+	{ 11057,-3604,-1155,-5152,13046,2329,-282,375,8104 } },
+    { "PENTAX K-m", 0, 0,
+	{ 11057,-3604,-1155,-5152,13046,2329,-282,375,8104 } },
+    { "PENTAX K-x", 0, 0,
+	{ 8843,-2837,-625,-5025,12644,2668,-411,1234,7410 } },
+    { "PENTAX K-7", 0, 0,
+	{ 9142,-2947,-678,-8648,16967,1663,-2224,2898,8615 } },
+    { "Panasonic DMC-FZ8", 0, 0xf7f0,
+	{ 8986,-2755,-802,-6341,13575,3077,-1476,2144,6379 } },
+    { "Panasonic DMC-FZ18", 0, 0,
+	{ 9932,-3060,-935,-5809,13331,2753,-1267,2155,5575 } },
+    { "Panasonic DMC-FZ28", 15, 0xfff,
+	{ 10109,-3488,-993,-5412,12812,2916,-1305,2140,5543 } },
+    { "Panasonic DMC-FZ30", 0, 0xf94c,
+	{ 10976,-4029,-1141,-7918,15491,2600,-1670,2071,8246 } },
+    { "Panasonic DMC-FZ35", 147, 0xfff,
+	{ 9938,-2780,-890,-4604,12393,2480,-1117,2304,4620 } },
+    { "Panasonic DMC-FZ50", 0, 0xfff0,	/* aka "LEICA V-LUX1" */
+	{ 7906,-2709,-594,-6231,13351,3220,-1922,2631,6537 } },
+    { "Panasonic DMC-L10", 15, 0xf96,
+	{ 8025,-1942,-1050,-7920,15904,2100,-2456,3005,7039 } },
+    { "Panasonic DMC-L1", 0, 0xf7fc,	/* aka "LEICA DIGILUX 3" */
+	{ 8054,-1885,-1025,-8349,16367,2040,-2805,3542,7629 } },
+    { "Panasonic DMC-LC1", 0, 0,	/* aka "LEICA DIGILUX 2" */
+	{ 11340,-4069,-1275,-7555,15266,2448,-2960,3426,7685 } },
+    { "Panasonic DMC-LX1", 0, 0xf7f0,	/* aka "LEICA D-LUX2" */
+	{ 10704,-4187,-1230,-8314,15952,2501,-920,945,8927 } },
+    { "Panasonic DMC-LX2", 0, 0,	/* aka "LEICA D-LUX3" */
+	{ 8048,-2810,-623,-6450,13519,3272,-1700,2146,7049 } },
+    { "Panasonic DMC-LX3", 15, 0xfff,	/* aka "LEICA D-LUX4" */
+	{ 8128,-2668,-655,-6134,13307,3161,-1782,2568,6083 } },
+    { "Panasonic DMC-FX150", 15, 0xfff,
+	{ 9082,-2907,-925,-6119,13377,3058,-1797,2641,5609 } },
+    { "Panasonic DMC-G1", 15, 0xfff,
+	{ 8199,-2065,-1056,-8124,16156,2033,-2458,3022,7220 } },
+    { "Panasonic DMC-GF1", 15, 0xf92,
+	{ 7888,-1902,-1011,-8106,16085,2099,-2353,2866,7330 } },
+    { "Panasonic DMC-GH1", 15, 0xf92,
+	{ 6299,-1466,-532,-6535,13852,2969,-2331,3112,5984 } },
+    { "Phase One H 20", 0, 0,		/* DJC */
+	{ 1313,1855,-109,-6715,15908,808,-327,1840,6020 } },
+    { "Phase One P 2", 0, 0,
+	{ 2905,732,-237,-8134,16626,1476,-3038,4253,7517 } },
+    { "Phase One P 30", 0, 0,
+	{ 4516,-245,-37,-7020,14976,2173,-3206,4671,7087 } },
+    { "Phase One P 45", 0, 0,
+	{ 5053,-24,-117,-5684,14076,1702,-2619,4492,5849 } },
+    { "Phase One P65", 0, 0,		/* DJC */
+	{ 8522,1268,-1916,-7706,16350,1358,-2397,4344,4923 } },
+    { "SAMSUNG GX-1", 0, 0,
+	{ 10504,-2438,-1189,-8603,16207,2531,-1022,863,12242 } },
+    { "SAMSUNG S85", 0, 0,		/* DJC */
+	{ 11885,-3968,-1473,-4214,12299,1916,-835,1655,5549 } },
+    { "Sinar", 0, 0,			/* DJC */
+	{ 16442,-2956,-2422,-2877,12128,750,-1136,6066,4559 } },
+    { "SONY DSC-F828", 491, 0,
+	{ 7924,-1910,-777,-8226,15459,2998,-1517,2199,6818,-7242,11401,3481 } },
+    { "SONY DSC-R1", 512, 0,
+	{ 8512,-2641,-694,-8042,15670,2526,-1821,2117,7414 } },
+    { "SONY DSC-V3", 0, 0,
+	{ 7511,-2571,-692,-7894,15088,3060,-948,1111,8128 } },
+    { "SONY DSLR-A100", 0, 0xfeb,
+	{ 9437,-2811,-774,-8405,16215,2290,-710,596,7181 } },
+    { "SONY DSLR-A200", 0, 0,
+	{ 9847,-3091,-928,-8485,16345,2225,-715,595,7103 } },
+    { "SONY DSLR-A230", 0, 0,	/* copied */
+	{ 9847,-3091,-928,-8485,16345,2225,-715,595,7103 } },
+    { "SONY DSLR-A300", 0, 0,
+	{ 9847,-3091,-928,-8485,16345,2225,-715,595,7103 } },
+    { "SONY DSLR-A330", 0, 0,
+	{ 9847,-3091,-929,-8485,16346,2225,-714,595,7103 } },
+    { "SONY DSLR-A350", 0, 0xffc,
+	{ 6038,-1484,-578,-9146,16746,2513,-875,746,7217 } },
+    { "SONY DSLR-A380", 0, 0,
+	{ 6038,-1484,-579,-9145,16746,2512,-875,746,7218 } },
+    { "SONY DSLR-A5", 254, 0x1ffe,
+	{ 4950,-580,-103,-5228,12542,3029,-709,1435,7371 } },
+    { "SONY DSLR-A700", 254, 0x1ffe,
+	{ 5775,-805,-359,-8574,16295,2391,-1943,2341,7249 } },
+    { "SONY DSLR-A850", 256, 0x1ffe,
+	{ 5413,-1162,-365,-5665,13098,2866,-608,1179,8440 } },
+    { "SONY DSLR-A900", 254, 0x1ffe,
+	{ 5209,-1072,-397,-8845,16120,2919,-1618,1803,8654 } }
+  };
+  double cam_xyz[4][3];
+  char name[130];
+  int i, j;
+
+  sprintf (name, "%s %s", make, model);
+  for (i=0; i < sizeof table / sizeof *table; i++)
+    if (!strncmp (name, table[i].prefix, strlen(table[i].prefix))) {
+      if (table[i].black)   black   = (ushort) table[i].black;
+      if (table[i].maximum) maximum = (ushort) table[i].maximum;
+      if (table[i].trans[0]) {
+	for (j=0; j < 12; j++)
+	  cam_xyz[0][j] = table[i].trans[j] / 10000.0;
+	cam_xyz_coeff (cam_xyz);
+      }
+      break;
+    }
+}
+
+void CLASS simple_coeff (int index)
+{
+  static const float table[][12] = {
+  /* index 0 -- all Foveon cameras */
+  { 1.4032,-0.2231,-0.1016,-0.5263,1.4816,0.017,-0.0112,0.0183,0.9113 },
+  /* index 1 -- Kodak DC20 and DC25 */
+  { 2.25,0.75,-1.75,-0.25,-0.25,0.75,0.75,-0.25,-0.25,-1.75,0.75,2.25 },
+  /* index 2 -- Logitech Fotoman Pixtura */
+  { 1.893,-0.418,-0.476,-0.495,1.773,-0.278,-1.017,-0.655,2.672 },
+  /* index 3 -- Nikon E880, E900, and E990 */
+  { -1.936280,  1.800443, -1.448486,  2.584324,
+     1.405365, -0.524955, -0.289090,  0.408680,
+    -1.204965,  1.082304,  2.941367, -1.818705 }
+  };
+  int i, c;
+
+  for (raw_color = i=0; i < 3; i++)
+    FORCC rgb_cam[i][c] = table[index][i*colors+c];
+}
+
+short CLASS guess_byte_order (int words)
+{
+  uchar test[4][2];
+  int t=2, msb;
+  double diff, sum[2] = {0,0};
+
+  fread (test[0], 2, 2, ifp);
+  for (words-=2; words--; ) {
+    fread (test[t], 2, 1, ifp);
+    for (msb=0; msb < 2; msb++) {
+      diff = (test[t^2][msb] << 8 | test[t^2][!msb])
+	   - (test[t  ][msb] << 8 | test[t  ][!msb]);
+      sum[msb] += diff*diff;
+    }
+    t = (t+1) & 3;
+  }
+  return sum[0] < sum[1] ? 0x4d4d : 0x4949;
+}
+
+float CLASS find_green (int bps, int bite, int off0, int off1)
+{
+  UINT64 bitbuf=0;
+  int vbits, col, i, c;
+  ushort img[2][2064];
+  double sum[]={0,0};
+
+  FORC(2) {
+    fseek (ifp, c ? off1:off0, SEEK_SET);
+    for (vbits=col=0; col < width; col++) {
+      for (vbits -= bps; vbits < 0; vbits += bite) {
+	bitbuf <<= bite;
+	for (i=0; i < bite; i+=8)
+	  bitbuf |= (unsigned) (fgetc(ifp) << i);
+      }
+      img[c][col] = bitbuf << (64-bps-vbits) >> (64-bps);
+    }
+  }
+  FORC(width-1) {
+    sum[ c & 1] += ABS(img[0][c]-img[1][c+1]);
+    sum[~c & 1] += ABS(img[1][c]-img[0][c+1]);
+  }
+  return 100 * log(sum[0]/sum[1]);
+}
+
+/*
+   Identify which camera created this file, and set global variables
+   accordingly.
+ */
+void CLASS identify()
+{
+  char head[32], *cp;
+  int hlen, fsize, i, c, is_canon;
+  struct jhead jh;
+  static const struct {
+    int fsize;
+    char make[12], model[19], withjpeg;
+  } table[] = {
+    {    62464, "Kodak",    "DC20"            ,0 },
+    {   124928, "Kodak",    "DC20"            ,0 },
+    {  1652736, "Kodak",    "DCS200"          ,0 },
+    {  4159302, "Kodak",    "C330"            ,0 },
+    {  4162462, "Kodak",    "C330"            ,0 },
+    {   460800, "Kodak",    "C603v"           ,0 },
+    {   614400, "Kodak",    "C603v"           ,0 },
+    {  6163328, "Kodak",    "C603"            ,0 },
+    {  6166488, "Kodak",    "C603"            ,0 },
+    {  9116448, "Kodak",    "C603y"           ,0 },
+    {   311696, "ST Micro", "STV680 VGA"      ,0 },  /* SPYz */
+    {   787456, "Creative", "PC-CAM 600"      ,0 },
+    {  1138688, "Minolta",  "RD175"           ,0 },
+    {  3840000, "Foculus",  "531C"            ,0 },
+    {   786432, "AVT",      "F-080C"          ,0 },
+    {  1447680, "AVT",      "F-145C"          ,0 },
+    {  1920000, "AVT",      "F-201C"          ,0 },
+    {  5067304, "AVT",      "F-510C"          ,0 },
+    { 10134608, "AVT",      "F-510C"          ,0 },
+    { 16157136, "AVT",      "F-810C"          ,0 },
+    {  1409024, "Sony",     "XCD-SX910CR"     ,0 },
+    {  2818048, "Sony",     "XCD-SX910CR"     ,0 },
+    {  3884928, "Micron",   "2010"            ,0 },
+    {  6624000, "Pixelink", "A782"            ,0 },
+    { 13248000, "Pixelink", "A782"            ,0 },
+    {  6291456, "RoverShot","3320AF"          ,0 },
+    {  6553440, "Canon",    "PowerShot A460"  ,0 },
+    {  6653280, "Canon",    "PowerShot A530"  ,0 },
+    {  6573120, "Canon",    "PowerShot A610"  ,0 },
+    {  9219600, "Canon",    "PowerShot A620"  ,0 },
+    {  9243240, "Canon",    "PowerShot A470"  ,0 },
+    { 10341600, "Canon",    "PowerShot A720"  ,0 },
+    { 10383120, "Canon",    "PowerShot A630"  ,0 },
+    { 12945240, "Canon",    "PowerShot A640"  ,0 },
+    { 15636240, "Canon",    "PowerShot A650"  ,0 },
+    {  5298000, "Canon",    "PowerShot SD300" ,0 },
+    {  7710960, "Canon",    "PowerShot S3 IS" ,0 },
+    { 15467760, "Canon",    "PowerShot SX110 IS",0 },
+    {  5939200, "OLYMPUS",  "C770UZ"          ,0 },
+    {  1581060, "NIKON",    "E900"            ,1 },  /* or E900s,E910 */
+    {  2465792, "NIKON",    "E950"            ,1 },  /* or E800,E700 */
+    {  2940928, "NIKON",    "E2100"           ,1 },  /* or E2500 */
+    {  4771840, "NIKON",    "E990"            ,1 },  /* or E995, Oly C3030Z */
+    {  4775936, "NIKON",    "E3700"           ,1 },  /* or Optio 33WR */
+    {  5869568, "NIKON",    "E4300"           ,1 },  /* or DiMAGE Z2 */
+    {  5865472, "NIKON",    "E4500"           ,1 },
+    {  7438336, "NIKON",    "E5000"           ,1 },  /* or E5700 */
+    {  8998912, "NIKON",    "COOLPIX S6"      ,1 },
+    {  1976352, "CASIO",    "QV-2000UX"       ,1 },
+    {  3217760, "CASIO",    "QV-3*00EX"       ,1 },
+    {  6218368, "CASIO",    "QV-5700"         ,1 },
+    {  6054400, "CASIO",    "QV-R41"          ,1 },
+    {  7530816, "CASIO",    "QV-R51"          ,1 },
+    {  7684000, "CASIO",    "QV-4000"         ,1 },
+    {  2937856, "CASIO",    "EX-S20"          ,1 },
+    {  4948608, "CASIO",    "EX-S100"         ,1 },
+    {  7542528, "CASIO",    "EX-Z50"          ,1 },
+    {  7753344, "CASIO",    "EX-Z55"          ,1 },
+    {  7816704, "CASIO",    "EX-Z60"          ,1 },
+    { 10843712, "CASIO",    "EX-Z75"          ,1 },
+    { 10834368, "CASIO",    "EX-Z750"         ,1 },
+    { 12310144, "CASIO",    "EX-Z850"         ,1 },
+    {  7426656, "CASIO",    "EX-P505"         ,1 },
+    {  9313536, "CASIO",    "EX-P600"         ,1 },
+    { 10979200, "CASIO",    "EX-P700"         ,1 },
+    {  3178560, "PENTAX",   "Optio S"         ,1 },
+    {  4841984, "PENTAX",   "Optio S"         ,1 },
+    {  6114240, "PENTAX",   "Optio S4"        ,1 },  /* or S4i, CASIO EX-Z4 */
+    { 10702848, "PENTAX",   "Optio 750Z"      ,1 },
+    { 15980544, "AGFAPHOTO","DC-833m"         ,1 },
+    { 16098048, "SAMSUNG",  "S85"             ,1 },
+    { 16215552, "SAMSUNG",  "S85"             ,1 },
+    { 12582980, "Sinar",    ""                ,0 },
+    { 33292868, "Sinar",    ""                ,0 },
+    { 44390468, "Sinar",    ""                ,0 } };
+  static const char *corp[] =
+    { "Canon", "NIKON", "EPSON", "KODAK", "Kodak", "OLYMPUS", "PENTAX",
+      "MINOLTA", "Minolta", "Konica", "CASIO", "Sinar", "Phase One",
+      "SAMSUNG", "Mamiya", "MOTOROLA" };
+
+  tiff_flip = flip = filters = -1;	/* 0 is valid, so -1 is unknown */
+  raw_height = raw_width = fuji_width = fuji_layout = cr2_slice[0] = 0;
+  maximum = height = width = top_margin = left_margin = 0;
+  cdesc[0] = desc[0] = artist[0] = make[0] = model[0] = model2[0] = 0;
+  iso_speed = shutter = aperture = focal_len = unique_id = 0;
+  memset (gpsdata, 0, sizeof gpsdata);
+  memset (white, 0, sizeof white);
+  thumb_offset = thumb_length = thumb_width = thumb_height = 0;
+  load_raw = thumb_load_raw = 0;
+  write_thumb = &CLASS jpeg_thumb;
+  data_offset = meta_length = tiff_bps = tiff_compress = 0;
+  kodak_cbpp = zero_after_ff = dng_version = load_flags = 0;
+  timestamp = shot_order = tiff_samples = black = is_foveon = 0;
+  mix_green = profile_length = data_error = zero_is_bad = 0;
+  pixel_aspect = is_raw = raw_color = 1;
+  tile_width = tile_length = INT_MAX;
+  for (i=0; i < 4; i++) {
+    cam_mul[i] = i == 1;
+    pre_mul[i] = i < 3;
+    FORC3 cmatrix[c][i] = 0;
+    FORC3 rgb_cam[c][i] = c == i;
+  }
+  colors = 3;
+  for (i=0; i < 0x4000; i++) curve[i] = i;
+
+  order = get2();
+  hlen = get4();
+  fseek (ifp, 0, SEEK_SET);
+  fread (head, 1, 32, ifp);
+  fseek (ifp, 0, SEEK_END);
+  fsize = ftell(ifp);
+  if ((cp = (char *) memmem (head, 32, "MMMM", 4)) ||
+      (cp = (char *) memmem (head, 32, "IIII", 4))) {
+    parse_phase_one (cp-head);
+    if (cp-head) parse_tiff(0);
+  } else if (order == 0x4949 || order == 0x4d4d) {
+    if (!memcmp (head+6,"HEAPCCDR",8)) {
+      data_offset = hlen;
+      parse_ciff (hlen, fsize - hlen);
+    } else {
+      parse_tiff(0);
+    }
+  } else if (!memcmp (head,"\xff\xd8\xff\xe1",4) &&
+	     !memcmp (head+6,"Exif",4)) {
+    fseek (ifp, 4, SEEK_SET);
+    data_offset = 4 + get2();
+    fseek (ifp, data_offset, SEEK_SET);
+    if (fgetc(ifp) != 0xff)
+      parse_tiff(12);
+    thumb_offset = 0;
+  } else if (!memcmp (head+25,"ARECOYK",7)) {
+    strcpy (make, "Contax");
+    strcpy (model,"N Digital");
+    fseek (ifp, 33, SEEK_SET);
+    get_timestamp(1);
+    fseek (ifp, 60, SEEK_SET);
+    FORC4 cam_mul[c ^ (c >> 1)] = get4();
+  } else if (!strcmp (head, "PXN")) {
+    strcpy (make, "Logitech");
+    strcpy (model,"Fotoman Pixtura");
+  } else if (!strcmp (head, "qktk")) {
+    strcpy (make, "Apple");
+    strcpy (model,"QuickTake 100");
+  } else if (!strcmp (head, "qktn")) {
+    strcpy (make, "Apple");
+    strcpy (model,"QuickTake 150");
+  } else if (!memcmp (head,"FUJIFILM",8)) {
+    fseek (ifp, 84, SEEK_SET);
+    thumb_offset = get4();
+    thumb_length = get4();
+    fseek (ifp, 92, SEEK_SET);
+    parse_fuji (get4());
+    if (thumb_offset > 120) {
+      fseek (ifp, 120, SEEK_SET);
+      is_raw += (i = get4()) && 1;
+      if (is_raw == 2 && shot_select)
+	parse_fuji (i);
+    }
+    fseek (ifp, 100, SEEK_SET);
+    data_offset = get4();
+    parse_tiff (thumb_offset+12);
+  } else if (!memcmp (head,"RIFF",4)) {
+    fseek (ifp, 0, SEEK_SET);
+    parse_riff();
+  } else if (!memcmp (head,"\0\001\0\001\0@",6)) {
+    fseek (ifp, 6, SEEK_SET);
+    fread (make, 1, 8, ifp);
+    fread (model, 1, 8, ifp);
+    fread (model2, 1, 16, ifp);
+    data_offset = get2();
+    get2();
+    raw_width = get2();
+    raw_height = get2();
+    load_raw = &CLASS nokia_load_raw;
+    filters = 0x61616161;
+  } else if (!memcmp (head,"DSC-Image",9))
+    parse_rollei();
+  else if (!memcmp (head,"PWAD",4))
+    parse_sinar_ia();
+  else if (!memcmp (head,"\0MRM",4))
+    parse_minolta(0);
+  else if (!memcmp (head,"FOVb",4))
+    parse_foveon();
+  else if (!memcmp (head,"CI",2))
+    parse_cine();
+  else
+    for (i=0; i < sizeof table / sizeof *table; i++)
+      if (fsize == table[i].fsize) {
+	strcpy (make,  table[i].make );
+	strcpy (model, table[i].model);
+	if (table[i].withjpeg)
+	  parse_external_jpeg();
+      }
+  if (make[0] == 0) parse_smal (0, fsize);
+  if (make[0] == 0) parse_jpeg (is_raw = 0);
+
+  for (i=0; i < sizeof corp / sizeof *corp; i++)
+    if (strstr (make, corp[i]))		/* Simplify company names */
+	strcpy (make, corp[i]);
+  if (!strncmp (make,"KODAK",5) &&
+	((cp = strstr(model," DIGITAL CAMERA")) ||
+	 (cp = strstr(model," Digital Camera")) ||
+	 (cp = strstr(model,"FILE VERSION"))))
+     *cp = 0;
+  cp = make + strlen(make);		/* Remove trailing spaces */
+  while (*--cp == ' ') *cp = 0;
+  cp = model + strlen(model);
+  while (*--cp == ' ') *cp = 0;
+  i = strlen(make);			/* Remove make from model */
+  if (!strncasecmp (model, make, i) && model[i++] == ' ')
+    memmove (model, model+i, 64-i);
+  if (!strncmp (model,"Digital Camera ",15))
+    strcpy (model, model+15);
+  desc[511] = artist[63] = make[63] = model[63] = model2[63] = 0;
+  if (!is_raw) goto notraw;
+
+  if (!height) height = raw_height;
+  if (!width)  width  = raw_width;
+  if (fuji_width) {
+    width = height + fuji_width;
+    height = width - 1;
+    pixel_aspect = 1;
+  }
+  if (height == 2624 && width == 3936)	/* Pentax K10D and Samsung GX10 */
+    { height  = 2616;   width  = 3896; }
+  if (height == 3136 && width == 4864)	/* Pentax K20D */
+    { height  = 3124;   width  = 4688; }
+  if (height == 3136 && width == 4736)	/* Pentax K-7 */
+    { height  = 3122;   width  = 4684;
+      top_margin = 2;  filters = 0x16161616; }
+  if (height == 3014 && width == 4096)	/* Ricoh GX200 */
+			width  = 4014;
+  if (dng_version) {
+    if (filters == UINT_MAX) filters = 0;
+    if (filters) is_raw = tiff_samples;
+    else	 colors = tiff_samples;
+    if (tiff_compress == 1)
+      load_raw = &CLASS adobe_dng_load_raw_nc;
+    if (tiff_compress == 7)
+      load_raw = &CLASS adobe_dng_load_raw_lj;
+    goto dng_skip;
+  }
+  if ((is_canon = !strcmp(make,"Canon")))
+    load_raw = memcmp (head+6,"HEAPCCDR",8) ?
+	&CLASS lossless_jpeg_load_raw : &CLASS canon_compressed_load_raw;
+  if (!strcmp(make,"NIKON")) {
+    if (!load_raw)
+      load_raw = &CLASS packed_load_raw;
+    if (model[0] == 'E')
+      load_flags |= !data_offset << 2 | 2;
+  }
+  if (!strcmp(make,"CASIO")) {
+    load_raw = &CLASS packed_load_raw;
+    maximum = 0xf7f;
+  }
+
+/* Set parameters based on camera name (for non-DNG files). */
+
+  if (is_foveon) {
+    if (height*2 < width) pixel_aspect = 0.5;
+    if (height   > width) pixel_aspect = 2;
+    filters = 0;
+    load_raw = &CLASS foveon_load_raw;
+    simple_coeff(0);
+  } else if (is_canon && tiff_bps == 15) {
+    switch (width) {
+      case 3344: width -= 66;
+      case 3872: width -= 6;
+    }
+    filters = 0;
+    load_raw = &CLASS canon_sraw_load_raw;
+  } else if (!strcmp(model,"PowerShot 600")) {
+    height = 613;
+    width  = 854;
+    raw_width = 896;
+    pixel_aspect = 607/628.0;
+    colors = 4;
+    filters = 0xe1e4e1e4;
+    load_raw = &CLASS canon_600_load_raw;
+  } else if (!strcmp(model,"PowerShot A5") ||
+	     !strcmp(model,"PowerShot A5 Zoom")) {
+    height = 773;
+    width  = 960;
+    raw_width = 992;
+    pixel_aspect = 256/235.0;
+    colors = 4;
+    filters = 0x1e4e1e4e;
+    goto canon_a5;
+  } else if (!strcmp(model,"PowerShot A50")) {
+    height =  968;
+    width  = 1290;
+    raw_width = 1320;
+    colors = 4;
+    filters = 0x1b4e4b1e;
+    goto canon_a5;
+  } else if (!strcmp(model,"PowerShot Pro70")) {
+    height = 1024;
+    width  = 1552;
+    colors = 4;
+    filters = 0x1e4b4e1b;
+    goto canon_a5;
+  } else if (!strcmp(model,"PowerShot SD300")) {
+    height = 1752;
+    width  = 2344;
+    raw_height = 1766;
+    raw_width  = 2400;
+    top_margin  = 12;
+    left_margin = 12;
+    goto canon_a5;
+  } else if (!strcmp(model,"PowerShot A460")) {
+    height = 1960;
+    width  = 2616;
+    raw_height = 1968;
+    raw_width  = 2664;
+    top_margin  = 4;
+    left_margin = 4;
+    goto canon_a5;
+  } else if (!strcmp(model,"PowerShot A530")) {
+    height = 1984;
+    width  = 2620;
+    raw_height = 1992;
+    raw_width  = 2672;
+    top_margin  = 6;
+    left_margin = 10;
+    goto canon_a5;
+  } else if (!strcmp(model,"PowerShot A610")) {
+    if (canon_s2is()) strcpy (model+10, "S2 IS");
+    height = 1960;
+    width  = 2616;
+    raw_height = 1968;
+    raw_width  = 2672;
+    top_margin  = 8;
+    left_margin = 12;
+    goto canon_a5;
+  } else if (!strcmp(model,"PowerShot A620")) {
+    height = 2328;
+    width  = 3112;
+    raw_height = 2340;
+    raw_width  = 3152;
+    top_margin  = 12;
+    left_margin = 36;
+    goto canon_a5;
+  } else if (!strcmp(model,"PowerShot A470")) {
+    height = 2328;
+    width  = 3096;
+    raw_height = 2346;
+    raw_width  = 3152;
+    top_margin  = 6;
+    left_margin = 12;
+    goto canon_a5;
+  } else if (!strcmp(model,"PowerShot A720")) {
+    height = 2472;
+    width  = 3298;
+    raw_height = 2480;
+    raw_width  = 3336;
+    top_margin  = 5;
+    left_margin = 6;
+    goto canon_a5;
+  } else if (!strcmp(model,"PowerShot A630")) {
+    height = 2472;
+    width  = 3288;
+    raw_height = 2484;
+    raw_width  = 3344;
+    top_margin  = 6;
+    left_margin = 12;
+    goto canon_a5;
+  } else if (!strcmp(model,"PowerShot A640")) {
+    height = 2760;
+    width  = 3672;
+    raw_height = 2772;
+    raw_width  = 3736;
+    top_margin  = 6;
+    left_margin = 12;
+    goto canon_a5;
+  } else if (!strcmp(model,"PowerShot A650")) {
+    height = 3024;
+    width  = 4032;
+    raw_height = 3048;
+    raw_width  = 4104;
+    top_margin  = 12;
+    left_margin = 48;
+    goto canon_a5;
+  } else if (!strcmp(model,"PowerShot S3 IS")) {
+    height = 2128;
+    width  = 2840;
+    raw_height = 2136;
+    raw_width  = 2888;
+    top_margin  = 8;
+    left_margin = 44;
+canon_a5:
+    tiff_bps = 10;
+    load_raw = &CLASS packed_load_raw;
+    load_flags = 40;
+    if (raw_width > 1600) zero_is_bad = 1;
+  } else if (!strcmp(model,"PowerShot SX110 IS")) {
+    height = 2760;
+    width  = 3684;
+    raw_height = 2772;
+    raw_width  = 3720;
+    top_margin  = 12;
+    left_margin = 6;
+    load_raw = &CLASS packed_load_raw;
+    load_flags = 40;
+    zero_is_bad = 1;
+  } else if (!strcmp(model,"PowerShot Pro90 IS")) {
+    width  = 1896;
+    colors = 4;
+    filters = 0xb4b4b4b4;
+  } else if (is_canon && raw_width == 2144) {
+    height = 1550;
+    width  = 2088;
+    top_margin  = 8;
+    left_margin = 4;
+    if (!strcmp(model,"PowerShot G1")) {
+      colors = 4;
+      filters = 0xb4b4b4b4;
+    }
+  } else if (is_canon && raw_width == 2224) {
+    height = 1448;
+    width  = 2176;
+    top_margin  = 6;
+    left_margin = 48;
+  } else if (is_canon && raw_width == 2376) {
+    height = 1720;
+    width  = 2312;
+    top_margin  = 6;
+    left_margin = 12;
+  } else if (is_canon && raw_width == 2672) {
+    height = 1960;
+    width  = 2616;
+    top_margin  = 6;
+    left_margin = 12;
+  } else if (is_canon && raw_width == 3152) {
+    height = 2056;
+    width  = 3088;
+    top_margin  = 12;
+    left_margin = 64;
+    if (unique_id == 0x80000170)
+      adobe_coeff ("Canon","EOS 300D");
+  } else if (is_canon && raw_width == 3160) {
+    height = 2328;
+    width  = 3112;
+    top_margin  = 12;
+    left_margin = 44;
+  } else if (is_canon && raw_width == 3344) {
+    height = 2472;
+    width  = 3288;
+    top_margin  = 6;
+    left_margin = 4;
+  } else if (!strcmp(model,"EOS D2000C")) {
+    filters = 0x61616161;
+    black = curve[200];
+  } else if (is_canon && raw_width == 3516) {
+    top_margin  = 14;
+    left_margin = 42;
+    if (unique_id == 0x80000189)
+      adobe_coeff ("Canon","EOS 350D");
+    goto canon_cr2;
+  } else if (is_canon && raw_width == 3596) {
+    top_margin  = 12;
+    left_margin = 74;
+    goto canon_cr2;
+  } else if (is_canon && raw_width == 3744) {
+    height = 2760;
+    width  = 3684;
+    top_margin  = 16;
+    left_margin = 8;
+  } else if (is_canon && raw_width == 3944) {
+    height = 2602;
+    width  = 3908;
+    top_margin  = 18;
+    left_margin = 30;
+  } else if (is_canon && raw_width == 3948) {
+    top_margin  = 18;
+    left_margin = 42;
+    height -= 2;
+    if (unique_id == 0x80000236)
+      adobe_coeff ("Canon","EOS 400D");
+    if (unique_id == 0x80000254)
+      adobe_coeff ("Canon","EOS 1000D");
+    goto canon_cr2;
+  } else if (is_canon && raw_width == 3984) {
+    top_margin  = 20;
+    left_margin = 76;
+    height -= 2;
+    goto canon_cr2;
+  } else if (is_canon && raw_width == 4104) {
+    height = 3024;
+    width  = 4032;
+    top_margin  = 12;
+    left_margin = 48;
+  } else if (is_canon && raw_width == 4152) {
+    top_margin  = 12;
+    left_margin = 192;
+    goto canon_cr2;
+  } else if (is_canon && raw_width == 4312) {
+    top_margin  = 18;
+    left_margin = 22;
+    height -= 2;
+    if (unique_id == 0x80000176)
+      adobe_coeff ("Canon","EOS 450D");
+    goto canon_cr2;
+  } else if (is_canon && raw_width == 4476) {
+    top_margin  = 34;
+    left_margin = 90;
+    goto canon_cr2;
+  } else if (is_canon && raw_width == 4480) {
+    height = 3326;
+    width  = 4432;
+    top_margin  = 10;
+    left_margin = 12;
+    filters = 0x49494949;
+  } else if (is_canon && raw_width == 1208) {
+    top_margin = unique_id == 0x80000261 ? 51:26;
+    left_margin = 62;
+    raw_width = width *= 4;
+    if (unique_id == 0x80000252)
+      adobe_coeff ("Canon","EOS 500D");
+    goto canon_cr2;
+  } else if (is_canon && raw_width == 1280) {
+    height -= top_margin = 45;
+    left_margin = 142;
+    raw_width *= 4;
+    width = 4916;
+  } else if (is_canon && raw_width == 1340) {
+    top_margin = 51;
+    left_margin = 158;
+    raw_width = width *= 4;
+    goto canon_cr2;
+  } else if (is_canon && raw_width == 1448) {
+    top_margin  = 51;
+    left_margin = 158;
+    raw_width = width *= 4;
+    goto canon_cr2;
+  } else if (is_canon && raw_width == 5108) {
+    top_margin  = 13;
+    left_margin = 98;
+canon_cr2:
+    height -= top_margin;
+    width  -= left_margin;
+  } else if (is_canon && raw_width == 5712) {
+    height = 3752;
+    width  = 5640;
+    top_margin  = 20;
+    left_margin = 62;
+  } else if (!strcmp(model,"D1")) {
+    cam_mul[0] *= 256/527.0;
+    cam_mul[2] *= 256/317.0;
+  } else if (!strcmp(model,"D1X")) {
+    width -= 4;
+    pixel_aspect = 0.5;
+  } else if (!strcmp(model,"D40X") ||
+	     !strcmp(model,"D60")  ||
+	     !strcmp(model,"D80")  ||
+	     !strcmp(model,"D3000")) {
+    height -= 3;
+    width  -= 4;
+  } else if (!strcmp(model,"D3")   ||
+	     !strcmp(model,"D3S")  ||
+	     !strcmp(model,"D700")) {
+    width -= 4;
+    left_margin = 2;
+  } else if (!strcmp(model,"D5000")) {
+    width -= 42;
+  } else if (!strncmp(model,"D40",3) ||
+	     !strncmp(model,"D50",3) ||
+	     !strncmp(model,"D70",3)) {
+    width--;
+  } else if (!strcmp(model,"D90")) {
+    width -= 42;
+  } else if (!strcmp(model,"D100")) {
+    if (tiff_compress == 34713 && !nikon_is_compressed()) {
+      load_raw = &CLASS packed_load_raw;
+      load_flags |= 1;
+      raw_width = (width += 3) + 3;
+    }
+  } else if (!strcmp(model,"D200")) {
+    left_margin = 1;
+    width -= 4;
+    filters = 0x94949494;
+  } else if (!strncmp(model,"D2H",3)) {
+    left_margin = 6;
+    width -= 14;
+  } else if (!strncmp(model,"D2X",3)) {
+    if (width == 3264) width -= 32;
+    else width -= 8;
+  } else if (!strncmp(model,"D300",4)) {
+    width -= 32;
+  } else if (!strcmp(model,"COOLPIX P6000")) {
+    load_flags = 24;
+    filters = 0x94949494;
+  } else if (fsize == 1581060) {
+    height = 963;
+    width = 1287;
+    raw_width = 1632;
+    maximum = 0x3f4;
+    colors = 4;
+    filters = 0x1e1e1e1e;
+    simple_coeff(3);
+    pre_mul[0] = 1.2085;
+    pre_mul[1] = 1.0943;
+    pre_mul[3] = 1.1103;
+    goto e900;
+  } else if (fsize == 2465792) {
+    height = 1203;
+    width  = 1616;
+    raw_width = 2048;
+    colors = 4;
+    filters = 0x4b4b4b4b;
+    adobe_coeff ("NIKON","E950");
+e900:
+    tiff_bps = 10;
+    load_raw = &CLASS packed_load_raw;
+    load_flags = 6;
+  } else if (fsize == 4771840) {
+    height = 1540;
+    width  = 2064;
+    colors = 4;
+    filters = 0xe1e1e1e1;
+    load_raw = &CLASS packed_load_raw;
+    load_flags = 6;
+    if (!timestamp && nikon_e995())
+      strcpy (model, "E995");
+    if (strcmp(model,"E995")) {
+      filters = 0xb4b4b4b4;
+      simple_coeff(3);
+      pre_mul[0] = 1.196;
+      pre_mul[1] = 1.246;
+      pre_mul[2] = 1.018;
+    }
+  } else if (!strcmp(model,"E2100")) {
+    if (!timestamp && !nikon_e2100()) goto cp_e2500;
+    height = 1206;
+    width  = 1616;
+    load_flags = 30;
+  } else if (!strcmp(model,"E2500")) {
+cp_e2500:
+    strcpy (model, "E2500");
+    height = 1204;
+    width  = 1616;
+    colors = 4;
+    filters = 0x4b4b4b4b;
+  } else if (fsize == 4775936) {
+    height = 1542;
+    width  = 2064;
+    load_raw = &CLASS packed_load_raw;
+    load_flags = 30;
+    if (!timestamp) nikon_3700();
+    if (model[0] == 'E' && atoi(model+1) < 3700)
+      filters = 0x49494949;
+    if (!strcmp(model,"Optio 33WR")) {
+      flip = 1;
+      filters = 0x16161616;
+    }
+    if (make[0] == 'O') {
+      i = find_green (12, 32, 0, fsize/2);
+      c = find_green (12, 32, 0, 3096);
+      if (abs(i) < abs(c)) {
+	SWAP(i,c);
+	load_flags = 24;
+      }
+      if (i < 0) filters = 0x61616161;
+    }
+  } else if (fsize == 5869568) {
+    height = 1710;
+    width  = 2288;
+    filters = 0x16161616;
+    if (!timestamp && minolta_z2()) {
+      strcpy (make, "Minolta");
+      strcpy (model,"DiMAGE Z2");
+    }
+    load_raw = &CLASS packed_load_raw;
+    load_flags = 6 + 24*(make[0] == 'M');
+  } else if (!strcmp(model,"E4500")) {
+    height = 1708;
+    width  = 2288;
+    colors = 4;
+    filters = 0xb4b4b4b4;
+  } else if (fsize == 7438336) {
+    height = 1924;
+    width  = 2576;
+    colors = 4;
+    filters = 0xb4b4b4b4;
+  } else if (fsize == 8998912) {
+    height = 2118;
+    width  = 2832;
+    maximum = 0xf83;
+    load_raw = &CLASS packed_load_raw;
+    load_flags = 30;
+  } else if (!strcmp(make,"FUJIFILM")) {
+    if (!strcmp(model+7,"S2Pro")) {
+      strcpy (model+7," S2Pro");
+      height = 2144;
+      width  = 2880;
+      flip = 6;
+    } else
+      maximum = 0x3e00;
+    if (is_raw == 2 && shot_select)
+      maximum = 0x2f00;
+    top_margin = (raw_height - height)/2;
+    left_margin = (raw_width - width )/2;
+    if (is_raw == 2)
+      data_offset += (shot_select > 0) * ( fuji_layout ?
+		(raw_width *= 2) : raw_height*raw_width*2 );
+    if (load_raw == &CLASS fuji_load_raw) {
+      fuji_width = width >> !fuji_layout;
+      width = (height >> fuji_layout) + fuji_width;
+      raw_height = height;
+      height = width - 1;
+      if (~fuji_width & 1) filters = 0x49494949;
+    }
+  } else if (!strcmp(model,"RD175")) {
+    height = 986;
+    width = 1534;
+    data_offset = 513;
+    filters = 0x61616161;
+    load_raw = &CLASS minolta_rd175_load_raw;
+  } else if (!strcmp(model,"KD-400Z")) {
+    height = 1712;
+    width  = 2312;
+    raw_width = 2336;
+    goto konica_400z;
+  } else if (!strcmp(model,"KD-510Z")) {
+    goto konica_510z;
+  } else if (!strcasecmp(make,"MINOLTA")) {
+    load_raw = &CLASS unpacked_load_raw;
+    maximum = 0xfff;
+    if (!strncmp(model,"DiMAGE A",8)) {
+      if (!strcmp(model,"DiMAGE A200"))
+	filters = 0x49494949;
+      tiff_bps = 12;
+      load_raw = &CLASS packed_load_raw;
+    } else if (!strncmp(model,"ALPHA",5) ||
+	       !strncmp(model,"DYNAX",5) ||
+	       !strncmp(model,"MAXXUM",6)) {
+      sprintf (model+20, "DYNAX %-10s", model+6+(model[0]=='M'));
+      adobe_coeff (make, model+20);
+      load_raw = &CLASS packed_load_raw;
+    } else if (!strncmp(model,"DiMAGE G",8)) {
+      if (model[8] == '4') {
+	height = 1716;
+	width  = 2304;
+      } else if (model[8] == '5') {
+konica_510z:
+	height = 1956;
+	width  = 2607;
+	raw_width = 2624;
+      } else if (model[8] == '6') {
+	height = 2136;
+	width  = 2848;
+      }
+      data_offset += 14;
+      filters = 0x61616161;
+konica_400z:
+      load_raw = &CLASS unpacked_load_raw;
+      maximum = 0x3df;
+      order = 0x4d4d;
+    }
+  } else if (!strcmp(model,"*ist D")) {
+    data_error = -1;
+  } else if (!strcmp(model,"*ist DS")) {
+    height -= 2;
+  } else if (!strcmp(model,"K20D")) {
+    filters = 0x16161616;
+  } else if (!strcmp(model,"K-x")) {
+    width = 4309;
+    filters = 0x16161616;
+  } else if (!strcmp(model,"Optio S")) {
+    if (fsize == 3178560) {
+      height = 1540;
+      width  = 2064;
+      load_raw = &CLASS eight_bit_load_raw;
+      cam_mul[0] *= 4;
+      cam_mul[2] *= 4;
+    } else {
+      height = 1544;
+      width  = 2068;
+      raw_width = 3136;
+      load_raw = &CLASS packed_load_raw;
+      maximum = 0xf7c;
+    }
+  } else if (fsize == 6114240) {
+    height = 1737;
+    width  = 2324;
+    raw_width = 3520;
+    load_raw = &CLASS packed_load_raw;
+    maximum = 0xf7a;
+  } else if (!strcmp(model,"Optio 750Z")) {
+    height = 2302;
+    width  = 3072;
+    load_raw = &CLASS packed_load_raw;
+    load_flags = 30;
+  } else if (!strcmp(model,"DC-833m")) {
+    height = 2448;
+    width  = 3264;
+    order = 0x4949;
+    filters = 0x61616161;
+    load_raw = &CLASS unpacked_load_raw;
+    maximum = 0xfc00;
+  } else if (!strncmp(model,"S85",3)) {
+    height = 2448;
+    width  = 3264;
+    raw_width = fsize/height/2;
+    order = 0x4d4d;
+    load_raw = &CLASS unpacked_load_raw;
+    maximum = 0xffff;
+  } else if (!strcmp(model,"STV680 VGA")) {
+    height = 484;
+    width  = 644;
+    load_raw = &CLASS eight_bit_load_raw;
+    flip = 2;
+    filters = 0x16161616;
+    black = 16;
+  } else if (!strcmp(model,"N95")) {
+    height = raw_height - (top_margin = 2);
+  } else if (!strcmp(model,"531C")) {
+    height = 1200;
+    width  = 1600;
+    load_raw = &CLASS unpacked_load_raw;
+    filters = 0x49494949;
+  } else if (!strcmp(model,"F-080C")) {
+    height = 768;
+    width  = 1024;
+    load_raw = &CLASS eight_bit_load_raw;
+  } else if (!strcmp(model,"F-145C")) {
+    height = 1040;
+    width  = 1392;
+    load_raw = &CLASS eight_bit_load_raw;
+  } else if (!strcmp(model,"F-201C")) {
+    height = 1200;
+    width  = 1600;
+    load_raw = &CLASS eight_bit_load_raw;
+  } else if (!strcmp(model,"F-510C")) {
+    height = 1958;
+    width  = 2588;
+    load_raw = fsize < 7500000 ?
+	&CLASS eight_bit_load_raw : &CLASS unpacked_load_raw;
+    maximum = 0xfff0;
+  } else if (!strcmp(model,"F-810C")) {
+    height = 2469;
+    width  = 3272;
+    load_raw = &CLASS unpacked_load_raw;
+    maximum = 0xfff0;
+  } else if (!strcmp(model,"XCD-SX910CR")) {
+    height = 1024;
+    width  = 1375;
+    raw_width = 1376;
+    filters = 0x49494949;
+    maximum = 0x3ff;
+    load_raw = fsize < 2000000 ?
+	&CLASS eight_bit_load_raw : &CLASS unpacked_load_raw;
+  } else if (!strcmp(model,"2010")) {
+    height = 1207;
+    width  = 1608;
+    order = 0x4949;
+    filters = 0x16161616;
+    data_offset = 3212;
+    maximum = 0x3ff;
+    load_raw = &CLASS unpacked_load_raw;
+  } else if (!strcmp(model,"A782")) {
+    height = 3000;
+    width  = 2208;
+    filters = 0x61616161;
+    load_raw = fsize < 10000000 ?
+	&CLASS eight_bit_load_raw : &CLASS unpacked_load_raw;
+    maximum = 0xffc0;
+  } else if (!strcmp(model,"3320AF")) {
+    height = 1536;
+    raw_width = width = 2048;
+    filters = 0x61616161;
+    load_raw = &CLASS unpacked_load_raw;
+    maximum = 0x3ff;
+    fseek (ifp, 0x300000, SEEK_SET);
+    if ((order = guess_byte_order(0x10000)) == 0x4d4d) {
+      height -= (top_margin = 16);
+      width -= (left_margin = 28);
+      maximum = 0xf5c0;
+      strcpy (make, "ISG");
+      model[0] = 0;
+    }
+  } else if (!strcmp(make,"Hasselblad")) {
+    if (load_raw == &CLASS lossless_jpeg_load_raw)
+      load_raw = &CLASS hasselblad_load_raw;
+    if (raw_width == 7262) {
+      height = 5444;
+      width  = 7248;
+      top_margin  = 4;
+      left_margin = 7;
+      filters = 0x61616161;
+    } else if (raw_width == 4090) {
+      strcpy (model, "V96C");
+      height -= (top_margin = 6);
+      width -= (left_margin = 3) + 7;
+      filters = 0x61616161;
+    }
+  } else if (!strcmp(make,"Sinar")) {
+    if (!memcmp(head,"8BPS",4)) {
+      fseek (ifp, 14, SEEK_SET);
+      height = get4();
+      width  = get4();
+      filters = 0x61616161;
+      data_offset = 68;
+    }
+    if (!load_raw) load_raw = &CLASS unpacked_load_raw;
+    maximum = 0x3fff;
+  } else if (!strcmp(make,"Leaf")) {
+    maximum = 0x3fff;
+    fseek (ifp, data_offset, SEEK_SET);
+    if (ljpeg_start (&jh, 1) && jh.bits == 15)
+      maximum = 0x1fff;
+    if (tiff_samples > 1) filters = 0;
+    if (tiff_samples > 1 || tile_length < raw_height)
+      load_raw = &CLASS leaf_hdr_load_raw;
+    if ((width | height) == 2048) {
+      if (tiff_samples == 1) {
+	filters = 1;
+	strcpy (cdesc, "RBTG");
+	strcpy (model, "CatchLight");
+	top_margin =  8; left_margin = 18; height = 2032; width = 2016;
+      } else {
+	strcpy (model, "DCB2");
+	top_margin = 10; left_margin = 16; height = 2028; width = 2022;
+      }
+    } else if (width+height == 3144+2060) {
+      if (!model[0]) strcpy (model, "Cantare");
+      if (width > height) {
+	 top_margin = 6; left_margin = 32; height = 2048;  width = 3072;
+	filters = 0x61616161;
+      } else {
+	left_margin = 6;  top_margin = 32;  width = 2048; height = 3072;
+	filters = 0x16161616;
+      }
+      if (!cam_mul[0] || model[0] == 'V') filters = 0;
+      else is_raw = tiff_samples;
+    } else if (width == 2116) {
+      strcpy (model, "Valeo 6");
+      height -= 2 * (top_margin = 30);
+      width -= 2 * (left_margin = 55);
+      filters = 0x49494949;
+    } else if (width == 3171) {
+      strcpy (model, "Valeo 6");
+      height -= 2 * (top_margin = 24);
+      width -= 2 * (left_margin = 24);
+      filters = 0x16161616;
+    }
+  } else if (!strcmp(make,"LEICA") || !strcmp(make,"Panasonic")) {
+    maximum = 0xfff0;
+    if ((fsize-data_offset) / (width*8/7) == height)
+      load_raw = &CLASS panasonic_load_raw;
+    if (!load_raw) load_raw = &CLASS unpacked_load_raw;
+    switch (width) {
+      case 2568:
+	adobe_coeff ("Panasonic","DMC-LC1");  break;
+      case 3130:
+	left_margin = -14;
+      case 3170:
+	left_margin += 18;
+	width = 3096;
+	if (height > 2326) {
+	  height = 2326;
+	  top_margin = 13;
+	  filters = 0x49494949;
+	}
+	zero_is_bad = 1;
+	adobe_coeff ("Panasonic","DMC-FZ8");  break;
+      case 3213:
+	width -= 27;
+      case 3177:
+	width -= 10;
+	filters = 0x49494949;
+	zero_is_bad = 1;
+	adobe_coeff ("Panasonic","DMC-L1");  break;
+      case 3304:
+	width -= 17;
+	zero_is_bad = 1;
+	adobe_coeff ("Panasonic","DMC-FZ30");  break;
+      case 3330:
+	width += 43;
+	left_margin = -6;
+	maximum = 0xf7f0;
+      case 3370:
+	width -= 82;
+	left_margin += 15;
+	if (height > 2480)
+	    height = 2480 - (top_margin = 10);
+	filters = 0x49494949;
+	zero_is_bad = 1;
+	adobe_coeff ("Panasonic","DMC-FZ18");  break;
+      case 3690:
+	height -= 2;
+	left_margin = -14;
+	maximum = 0xf7f0;
+      case 3770:
+	width = 3672;
+	if (--height == 2798 && (height = 2760))
+	  top_margin = 15;
+	else filters = 0x49494949;
+	left_margin += 17;
+	zero_is_bad = 1;
+	adobe_coeff ("Panasonic","DMC-FZ50");  break;
+      case 3710:
+	width = 3682;
+	filters = 0x49494949;
+	adobe_coeff ("Panasonic","DMC-L10");  break;
+      case 3724:
+	width -= 14;
+	if (height == 2450) height -= 2;
+      case 3836:
+	width -= 42;
+lx3:	filters = 0x16161616;
+	if (make[0] != 'P')
+	  adobe_coeff ("Panasonic","DMC-LX3");
+	break;
+      case 3880:
+	width -= 22;
+	left_margin = 6;
+	zero_is_bad = 1;
+	adobe_coeff ("Panasonic","DMC-LX1");  break;
+      case 4060:
+	width = 3982;
+	if (height == 2250) goto lx3;
+	width = 4018;
+	filters = 0x16161616;
+	if (!strncmp(model,"DMC-FZ3",7)) {
+	  height -= 2;
+	  adobe_coeff ("Panasonic","DMC-FZ35");  break;
+	}
+	filters = 0x49494949;
+	if (!strcmp(model,"DMC-GH1")) break;
+	zero_is_bad = 1;
+	adobe_coeff ("Panasonic","DMC-G1");  break;
+      case 4172:
+      case 4396:
+	width -= 28;
+	filters = 0x49494949;
+	adobe_coeff ("Panasonic","DMC-GH1");  break;
+      case 4290:
+	height += 38;
+	left_margin = -14;
+	filters = 0x49494949;
+      case 4330:
+	width = 4248;
+	if ((height -= 39) == 2400)
+	  top_margin = 15;
+	left_margin += 17;
+	adobe_coeff ("Panasonic","DMC-LX2");  break;
+      case 4508:
+	height -= 6;
+	width = 4429;
+	filters = 0x16161616;
+	adobe_coeff ("Panasonic","DMC-FX150");  break;
+    }
+  } else if (!strcmp(model,"C770UZ")) {
+    height = 1718;
+    width  = 2304;
+    filters = 0x16161616;
+    load_raw = &CLASS packed_load_raw;
+    load_flags = 30;
+  } else if (!strcmp(make,"OLYMPUS")) {
+    height += height & 1;
+    filters = exif_cfa;
+    if (width == 4100) width -= 4;
+    if (load_raw == &CLASS olympus_load_raw) {
+      tiff_bps = 12;
+      black >>= 4;
+    } else if (!strcmp(model,"E-10") ||
+	      !strncmp(model,"E-20",4)) {
+      black <<= 2;
+    } else if (!strcmp(model,"E-300") ||
+	       !strcmp(model,"E-500")) {
+      width -= 20;
+      if (load_raw == &CLASS unpacked_load_raw) {
+	maximum = 0xfc30;
+	black = 0;
+      }
+    } else if (!strcmp(model,"E-330")) {
+      width -= 30;
+      if (load_raw == &CLASS unpacked_load_raw)
+	maximum = 0xf790;
+    } else if (!strcmp(model,"SP550UZ")) {
+      thumb_length = fsize - (thumb_offset = 0xa39800);
+      thumb_height = 480;
+      thumb_width  = 640;
+    }
+  } else if (!strcmp(model,"N Digital")) {
+    height = 2047;
+    width  = 3072;
+    filters = 0x61616161;
+    data_offset = 0x1a00;
+    load_raw = &CLASS packed_load_raw;
+  } else if (!strcmp(model,"DSC-F828")) {
+    width = 3288;
+    left_margin = 5;
+    data_offset = 862144;
+    load_raw = &CLASS sony_load_raw;
+    filters = 0x9c9c9c9c;
+    colors = 4;
+    strcpy (cdesc, "RGBE");
+  } else if (!strcmp(model,"DSC-V3")) {
+    width = 3109;
+    left_margin = 59;
+    data_offset = 787392;
+    load_raw = &CLASS sony_load_raw;
+  } else if (!strcmp(make,"SONY") && raw_width == 3984) {
+    adobe_coeff ("SONY","DSC-R1");
+    width = 3925;
+    order = 0x4d4d;
+  } else if (!strcmp(model,"DSLR-A100")) {
+    height--;
+    width = ++raw_width;
+    filters = 0x61616161;
+  } else if (!strcmp(model,"DSLR-A350")) {
+    height -= 4;
+  } else if (!strcmp(model,"PIXL")) {
+    height -= top_margin = 4;
+    width -= left_margin = 32;
+    gamma_curve (0, 7, 1, 255);
+  } else if (!strcmp(model,"C603v")) {
+    height = 480;
+    width  = 640;
+    if (fsize < 614400 || find_green (16, 16, 3840, 5120) < 25) goto c603v;
+    strcpy (model,"KAI-0340");
+    height -= 3;
+    data_offset = 3840;
+    order = 0x4949;
+    load_raw = &CLASS unpacked_load_raw;
+  } else if (!strcmp(model,"C603y")) {
+    height = 2134;
+    width  = 2848;
+c603v:
+    filters = 0;
+    load_raw = &CLASS kodak_yrgb_load_raw;
+    gamma_curve (0, 3.875, 1, 255);
+  } else if (!strcmp(model,"C603")) {
+    raw_height = height = 2152;
+    raw_width  = width  = 2864;
+    goto c603;
+  } else if (!strcmp(model,"C330")) {
+    height = 1744;
+    width  = 2336;
+    raw_height = 1779;
+    raw_width  = 2338;
+    top_margin = 33;
+    left_margin = 1;
+c603:
+    order = 0x4949;
+    if ((data_offset = fsize - raw_height*raw_width)) {
+      fseek (ifp, 168, SEEK_SET);
+      read_shorts (curve, 256);
+    } else gamma_curve (0, 3.875, 1, 255);
+    load_raw = &CLASS eight_bit_load_raw;
+  } else if (!strcmp(model,"EASYSHARE Z1015 IS")) {
+    height = 2742;
+    width  = 3664;
+    goto ezshare;
+  } else if (!strcmp(model,"EasyShare Z980")) {
+    height = 3006;
+    width  = 4016;
+ezshare:
+    data_offset = 0x15000;
+    load_raw = &CLASS packed_load_raw;
+  } else if (!strcasecmp(make,"KODAK")) {
+    if (filters == UINT_MAX) filters = 0x61616161;
+    if (!strncmp(model,"NC2000",6)) {
+      width -= 4;
+      left_margin = 2;
+    } else if (!strcmp(model,"EOSDCS3B")) {
+      width -= 4;
+      left_margin = 2;
+    } else if (!strcmp(model,"EOSDCS1")) {
+      width -= 4;
+      left_margin = 2;
+    } else if (!strcmp(model,"DCS420")) {
+      width -= 4;
+      left_margin = 2;
+    } else if (!strncmp(model,"DCS460 ",7)) {
+      model[6] = 0;
+      width -= 4;
+      left_margin = 2;
+    } else if (!strcmp(model,"DCS460A")) {
+      width -= 4;
+      left_margin = 2;
+      colors = 1;
+      filters = 0;
+    } else if (!strcmp(model,"DCS660M")) {
+      black = 214;
+      colors = 1;
+      filters = 0;
+    } else if (!strcmp(model,"DCS760M")) {
+      colors = 1;
+      filters = 0;
+    }
+    if (!strcmp(model+4,"20X"))
+      strcpy (cdesc, "MYCY");
+    if (strstr(model,"DC25")) {
+      strcpy (model, "DC25");
+      data_offset = 15424;
+    }
+    if (!strncmp(model,"DC2",3)) {
+      height = 242;
+      if (fsize < 100000) {
+	raw_width = 256; width = 249;
+	pixel_aspect = (4.0*height) / (3.0*width);
+      } else {
+	raw_width = 512; width = 501;
+	pixel_aspect = (493.0*height) / (373.0*width);
+      }
+      data_offset += raw_width + 1;
+      colors = 4;
+      filters = 0x8d8d8d8d;
+      simple_coeff(1);
+      pre_mul[1] = 1.179;
+      pre_mul[2] = 1.209;
+      pre_mul[3] = 1.036;
+      load_raw = &CLASS eight_bit_load_raw;
+    } else if (!strcmp(model,"40")) {
+      strcpy (model, "DC40");
+      height = 512;
+      width  = 768;
+      data_offset = 1152;
+      load_raw = &CLASS kodak_radc_load_raw;
+    } else if (strstr(model,"DC50")) {
+      strcpy (model, "DC50");
+      height = 512;
+      width  = 768;
+      data_offset = 19712;
+      load_raw = &CLASS kodak_radc_load_raw;
+    } else if (strstr(model,"DC120")) {
+      strcpy (model, "DC120");
+      height = 976;
+      width  = 848;
+      pixel_aspect = height/0.75/width;
+      load_raw = tiff_compress == 7 ?
+	&CLASS kodak_jpeg_load_raw : &CLASS kodak_dc120_load_raw;
+    } else if (!strcmp(model,"DCS200")) {
+      thumb_height = 128;
+      thumb_width  = 192;
+      thumb_offset = 6144;
+      thumb_misc   = 360;
+      write_thumb = &CLASS layer_thumb;
+      height = 1024;
+      width  = 1536;
+      data_offset = 79872;
+      load_raw = &CLASS eight_bit_load_raw;
+      black = 17;
+    }
+  } else if (!strcmp(model,"Fotoman Pixtura")) {
+    height = 512;
+    width  = 768;
+    data_offset = 3632;
+    load_raw = &CLASS kodak_radc_load_raw;
+    filters = 0x61616161;
+    simple_coeff(2);
+  } else if (!strcmp(model,"QuickTake 100")) {
+    fseek (ifp, 544, SEEK_SET);
+    height = get2();
+    width  = get2();
+    data_offset = (get4(),get2()) == 30 ? 738:736;
+    if (height > width) {
+      SWAP(height,width);
+      fseek (ifp, data_offset-6, SEEK_SET);
+      flip = ~get2() & 3 ? 5:6;
+    }
+    load_raw = &CLASS quicktake_100_load_raw;
+    filters = 0x61616161;
+  } else if (!strcmp(model,"QuickTake 150")) {
+    data_offset = 738 - head[5];
+    if (head[5]) strcpy (model+10, "200");
+    load_raw = &CLASS kodak_radc_load_raw;
+    height = 480;
+    width  = 640;
+    filters = 0x61616161;
+  } else if (!strcmp(make,"Rollei") && !load_raw) {
+    switch (raw_width) {
+      case 1316:
+	height = 1030;
+	width  = 1300;
+	top_margin  = 1;
+	left_margin = 6;
+	break;
+      case 2568:
+	height = 1960;
+	width  = 2560;
+	top_margin  = 2;
+	left_margin = 8;
+    }
+    filters = 0x16161616;
+    load_raw = &CLASS rollei_load_raw;
+  } else if (!strcmp(model,"PC-CAM 600")) {
+    height = 768;
+    data_offset = width = 1024;
+    filters = 0x49494949;
+    load_raw = &CLASS eight_bit_load_raw;
+  } else if (!strcmp(model,"QV-2000UX")) {
+    height = 1208;
+    width  = 1632;
+    data_offset = width * 2;
+    load_raw = &CLASS eight_bit_load_raw;
+  } else if (fsize == 3217760) {
+    height = 1546;
+    width  = 2070;
+    raw_width = 2080;
+    load_raw = &CLASS eight_bit_load_raw;
+  } else if (!strcmp(model,"QV-4000")) {
+    height = 1700;
+    width  = 2260;
+    load_raw = &CLASS unpacked_load_raw;
+    maximum = 0xffff;
+  } else if (!strcmp(model,"QV-5700")) {
+    height = 1924;
+    width  = 2576;
+    raw_width = 3232;
+    tiff_bps = 10;
+  } else if (!strcmp(model,"QV-R41")) {
+    height = 1720;
+    width  = 2312;
+    raw_width = 3520;
+    left_margin = 2;
+  } else if (!strcmp(model,"QV-R51")) {
+    height = 1926;
+    width  = 2580;
+    raw_width = 3904;
+  } else if (!strcmp(model,"EX-S20")) {
+    height = 1208;
+    width  = 1620;
+    raw_width = 2432;
+    flip = 3;
+  } else if (!strcmp(model,"EX-S100")) {
+    height = 1544;
+    width  = 2058;
+    raw_width = 3136;
+  } else if (!strcmp(model,"EX-Z50")) {
+    height = 1931;
+    width  = 2570;
+    raw_width = 3904;
+  } else if (!strcmp(model,"EX-Z55")) {
+    height = 1960;
+    width  = 2570;
+    raw_width = 3904;
+  } else if (!strcmp(model,"EX-Z60")) {
+    height = 2145;
+    width  = 2833;
+    raw_width = 3584;
+    filters = 0x16161616;
+    tiff_bps = 10;
+  } else if (!strcmp(model,"EX-Z75")) {
+    height = 2321;
+    width  = 3089;
+    raw_width = 4672;
+    maximum = 0xfff;
+  } else if (!strcmp(model,"EX-Z750")) {
+    height = 2319;
+    width  = 3087;
+    raw_width = 4672;
+    maximum = 0xfff;
+  } else if (!strcmp(model,"EX-Z850")) {
+    height = 2468;
+    width  = 3279;
+    raw_width = 4928;
+    maximum = 0xfff;
+  } else if (!strcmp(model,"EX-P505")) {
+    height = 1928;
+    width  = 2568;
+    raw_width = 3852;
+    maximum = 0xfff;
+  } else if (fsize == 9313536) {	/* EX-P600 or QV-R61 */
+    height = 2142;
+    width  = 2844;
+    raw_width = 4288;
+  } else if (!strcmp(model,"EX-P700")) {
+    height = 2318;
+    width  = 3082;
+    raw_width = 4672;
+  }
+  if (!model[0])
+    sprintf (model, "%dx%d", width, height);
+  if (filters == UINT_MAX) filters = 0x94949494;
+  if (raw_color) adobe_coeff (make, model);
+  if (load_raw == &CLASS kodak_radc_load_raw)
+    if (raw_color) adobe_coeff ("Apple","Quicktake");
+  if (thumb_offset && !thumb_height) {
+    fseek (ifp, thumb_offset, SEEK_SET);
+    if (ljpeg_start (&jh, 1)) {
+      thumb_width  = jh.wide;
+      thumb_height = jh.high;
+    }
+  }
+dng_skip:
+  if (!tiff_bps) tiff_bps = 12;
+  if (!maximum) maximum = (1 << tiff_bps) - 1;
+  if (!load_raw || height < 22) is_raw = 0;
+#ifdef NO_JPEG
+  if (load_raw == &CLASS kodak_jpeg_load_raw) {
+    fprintf (stderr,_("%s: You must link dcraw with libjpeg!!\n"), ifname);
+    is_raw = 0;
+  }
+#endif
+  if (!cdesc[0])
+    strcpy (cdesc, colors == 3 ? "RGB":"GMCY");
+  if (!raw_height) raw_height = height;
+  if (!raw_width ) raw_width  = width;
+  if (filters && colors == 3)
+    for (i=0; i < 32; i+=4) {
+      if ((filters >> i & 15) == 9)
+	filters |= 2 << i;
+      if ((filters >> i & 15) == 6)
+	filters |= 8 << i;
+    }
+notraw:
+  if (flip == -1) flip = tiff_flip;
+  if (flip == -1) flip = 0;
+}
+
+#ifndef NO_LCMS
+void CLASS apply_profile (const char *input, const char *output)
+{
+  char *prof;
+  cmsHPROFILE hInProfile=0, hOutProfile=0;
+  cmsHTRANSFORM hTransform;
+  FILE *fp;
+  unsigned size;
+
+  cmsErrorAction (LCMS_ERROR_SHOW);
+  if (strcmp (input, "embed"))
+    hInProfile = cmsOpenProfileFromFile (input, "r");
+  else if (profile_length) {
+    prof = (char *) malloc (profile_length);
+    merror (prof, "apply_profile()");
+    fseek (ifp, profile_offset, SEEK_SET);
+    fread (prof, 1, profile_length, ifp);
+    hInProfile = cmsOpenProfileFromMem (prof, profile_length);
+    free (prof);
+  } else
+    fprintf (stderr,_("%s has no embedded profile.\n"), ifname);
+  if (!hInProfile) return;
+  if (!output)
+    hOutProfile = cmsCreate_sRGBProfile();
+  else if ((fp = fopen (output, "rb"))) {
+    fread (&size, 4, 1, fp);
+    fseek (fp, 0, SEEK_SET);
+    oprof = (unsigned *) malloc (size = ntohl(size));
+    merror (oprof, "apply_profile()");
+    fread (oprof, 1, size, fp);
+    fclose (fp);
+    if (!(hOutProfile = cmsOpenProfileFromMem (oprof, size))) {
+      free (oprof);
+      oprof = 0;
+    }
+  } else
+    fprintf (stderr,_("Cannot open file %s!\n"), output);
+  if (!hOutProfile) goto quit;
+  if (verbose)
+    fprintf (stderr,_("Applying color profile...\n"));
+  hTransform = cmsCreateTransform (hInProfile, TYPE_RGBA_16,
+	hOutProfile, TYPE_RGBA_16, INTENT_PERCEPTUAL, 0);
+  cmsDoTransform (hTransform, image, image, width*height);
+  raw_color = 1;		/* Don't use rgb_cam with a profile */
+  cmsDeleteTransform (hTransform);
+  cmsCloseProfile (hOutProfile);
+quit:
+  cmsCloseProfile (hInProfile);
+}
+#endif
+
+void CLASS convert_to_rgb()
+{
+  int row, col, c, i, j, k;
+  ushort *img;
+  float out[3], out_cam[3][4];
+  double num, inverse[3][3];
+  static const double xyzd50_srgb[3][3] =
+  { { 0.436083, 0.385083, 0.143055 },
+    { 0.222507, 0.716888, 0.060608 },
+    { 0.013930, 0.097097, 0.714022 } };
+  static const double rgb_rgb[3][3] =
+  { { 1,0,0 }, { 0,1,0 }, { 0,0,1 } };
+  static const double adobe_rgb[3][3] =
+  { { 0.715146, 0.284856, 0.000000 },
+    { 0.000000, 1.000000, 0.000000 },
+    { 0.000000, 0.041166, 0.958839 } };
+  static const double wide_rgb[3][3] =
+  { { 0.593087, 0.404710, 0.002206 },
+    { 0.095413, 0.843149, 0.061439 },
+    { 0.011621, 0.069091, 0.919288 } };
+  static const double prophoto_rgb[3][3] =
+  { { 0.529317, 0.330092, 0.140588 },
+    { 0.098368, 0.873465, 0.028169 },
+    { 0.016879, 0.117663, 0.865457 } };
+  static const double (*out_rgb[])[3] =
+  { rgb_rgb, adobe_rgb, wide_rgb, prophoto_rgb, xyz_rgb };
+  static const char *name[] =
+  { "sRGB", "Adobe RGB (1998)", "WideGamut D65", "ProPhoto D65", "XYZ" };
+  static const unsigned phead[] =
+  { 1024, 0, 0x2100000, 0x6d6e7472, 0x52474220, 0x58595a20, 0, 0, 0,
+    0x61637370, 0, 0, 0x6e6f6e65, 0, 0, 0, 0, 0xf6d6, 0x10000, 0xd32d };
+  unsigned pbody[] =
+  { 10, 0x63707274, 0, 36,	/* cprt */
+	0x64657363, 0, 40,	/* desc */
+	0x77747074, 0, 20,	/* wtpt */
+	0x626b7074, 0, 20,	/* bkpt */
+	0x72545243, 0, 14,	/* rTRC */
+	0x67545243, 0, 14,	/* gTRC */
+	0x62545243, 0, 14,	/* bTRC */
+	0x7258595a, 0, 20,	/* rXYZ */
+	0x6758595a, 0, 20,	/* gXYZ */
+	0x6258595a, 0, 20 };	/* bXYZ */
+  static const unsigned pwhite[] = { 0xf351, 0x10000, 0x116cc };
+  unsigned pcurve[] = { 0x63757276, 0, 1, 0x1000000 };
+
+  gamma_curve (gamm[0], gamm[1], 0, 0);
+  memcpy (out_cam, rgb_cam, sizeof out_cam);
+  raw_color |= colors == 1 || document_mode ||
+		output_color < 1 || output_color > 5;
+  if (!raw_color) {
+    oprof = (unsigned *) calloc (phead[0], 1);
+    merror (oprof, "convert_to_rgb()");
+    memcpy (oprof, phead, sizeof phead);
+    if (output_color == 5) oprof[4] = oprof[5];
+    oprof[0] = 132 + 12*pbody[0];
+    for (i=0; i < pbody[0]; i++) {
+      oprof[oprof[0]/4] = i ? (i > 1 ? 0x58595a20 : 0x64657363) : 0x74657874;
+      pbody[i*3+2] = oprof[0];
+      oprof[0] += (pbody[i*3+3] + 3) & -4;
+    }
+    memcpy (oprof+32, pbody, sizeof pbody);
+    oprof[pbody[5]/4+2] = strlen(name[output_color-1]) + 1;
+    memcpy ((char *)oprof+pbody[8]+8, pwhite, sizeof pwhite);
+    pcurve[3] = (short)(256/gamm[5]+0.5) << 16;
+    for (i=4; i < 7; i++)
+      memcpy ((char *)oprof+pbody[i*3+2], pcurve, sizeof pcurve);
+    pseudoinverse ((double (*)[3]) out_rgb[output_color-1], inverse, 3);
+    for (i=0; i < 3; i++)
+      for (j=0; j < 3; j++) {
+	for (num = k=0; k < 3; k++)
+	  num += xyzd50_srgb[i][k] * inverse[j][k];
+        oprof[pbody[j*3+23]/4+i+2] = num * 0x10000 + 0.5;
+      }
+    for (i=0; i < phead[0]/4; i++)
+      oprof[i] = htonl(oprof[i]);
+    strcpy ((char *)oprof+pbody[2]+8, "auto-generated by dcraw");
+    strcpy ((char *)oprof+pbody[5]+12, name[output_color-1]);
+    for (i=0; i < 3; i++)
+      for (j=0; j < colors; j++)
+	for (out_cam[i][j] = k=0; k < 3; k++)
+	  out_cam[i][j] += out_rgb[output_color-1][i][k] * rgb_cam[k][j];
+  }
+  if (verbose)
+    fprintf (stderr, raw_color ? _("Building histograms...\n") :
+	_("Converting to %s colorspace...\n"), name[output_color-1]);
+
+  memset (histogram, 0, sizeof histogram);
+  for (img=image[0], row=0; row < height; row++)
+    for (col=0; col < width; col++, img+=4) {
+      if (!raw_color) {
+	out[0] = out[1] = out[2] = 0;
+	FORCC {
+	  out[0] += out_cam[0][c] * img[c];
+	  out[1] += out_cam[1][c] * img[c];
+	  out[2] += out_cam[2][c] * img[c];
+	}
+	FORC3 img[c] = CLIP((int) out[c]);
+      }
+      else if (document_mode)
+	img[0] = img[FC(row,col)];
+      FORCC histogram[c][img[c] >> 3]++;
+    }
+  if (colors == 4 && output_color) colors = 3;
+  if (document_mode && filters) colors = 1;
+}
+
+void CLASS fuji_rotate()
+{
+  int i, row, col;
+  double step;
+  float r, c, fr, fc;
+  unsigned ur, uc;
+  ushort wide, high, (*img)[4], (*pix)[4];
+
+  if (!fuji_width) return;
+  if (verbose)
+    fprintf (stderr,_("Rotating image 45 degrees...\n"));
+  fuji_width = (fuji_width - 1 + shrink) >> shrink;
+  step = sqrt(0.5);
+  wide = fuji_width / step;
+  high = (height - fuji_width) / step;
+  img = (ushort (*)[4]) calloc (wide*high, sizeof *img);
+  merror (img, "fuji_rotate()");
+
+  for (row=0; row < high; row++)
+    for (col=0; col < wide; col++) {
+      ur = r = fuji_width + (row-col)*step;
+      uc = c = (row+col)*step;
+      if (ur > height-2 || uc > width-2) continue;
+      fr = r - ur;
+      fc = c - uc;
+      pix = image + ur*width + uc;
+      for (i=0; i < colors; i++)
+	img[row*wide+col][i] =
+	  (pix[    0][i]*(1-fc) + pix[      1][i]*fc) * (1-fr) +
+	  (pix[width][i]*(1-fc) + pix[width+1][i]*fc) * fr;
+    }
+  free (image);
+  width  = wide;
+  height = high;
+  image  = img;
+  fuji_width = 0;
+}
+
+void CLASS stretch()
+{
+  ushort newdim, (*img)[4], *pix0, *pix1;
+  int row, col, c;
+  double rc, frac;
+
+  if (pixel_aspect == 1) return;
+  if (verbose) fprintf (stderr,_("Stretching the image...\n"));
+  if (pixel_aspect < 1) {
+    newdim = height / pixel_aspect + 0.5;
+    img = (ushort (*)[4]) calloc (width*newdim, sizeof *img);
+    merror (img, "stretch()");
+    for (rc=row=0; row < newdim; row++, rc+=pixel_aspect) {
+      frac = rc - (c = rc);
+      pix0 = pix1 = image[c*width];
+      if (c+1 < height) pix1 += width*4;
+      for (col=0; col < width; col++, pix0+=4, pix1+=4)
+	FORCC img[row*width+col][c] = pix0[c]*(1-frac) + pix1[c]*frac + 0.5;
+    }
+    height = newdim;
+  } else {
+    newdim = width * pixel_aspect + 0.5;
+    img = (ushort (*)[4]) calloc (height*newdim, sizeof *img);
+    merror (img, "stretch()");
+    for (rc=col=0; col < newdim; col++, rc+=1/pixel_aspect) {
+      frac = rc - (c = rc);
+      pix0 = pix1 = image[c];
+      if (c+1 < width) pix1 += 4;
+      for (row=0; row < height; row++, pix0+=width*4, pix1+=width*4)
+	FORCC img[row*newdim+col][c] = pix0[c]*(1-frac) + pix1[c]*frac + 0.5;
+    }
+    width = newdim;
+  }
+  free (image);
+  image = img;
+}
+
+int CLASS flip_index (int row, int col)
+{
+  if (flip & 4) SWAP(row,col);
+  if (flip & 2) row = iheight - 1 - row;
+  if (flip & 1) col = iwidth  - 1 - col;
+  return row * iwidth + col;
+}
+
+struct tiff_tag {
+  ushort tag, type;
+  int count;
+  union { char c[4]; short s[2]; int i; } val;
+};
+
+struct tiff_hdr {
+  ushort order, magic;
+  int ifd;
+  ushort pad, ntag;
+  struct tiff_tag tag[23];
+  int nextifd;
+  ushort pad2, nexif;
+  struct tiff_tag exif[4];
+  ushort pad3, ngps;
+  struct tiff_tag gpst[10];
+  short bps[4];
+  int rat[10];
+  unsigned gps[26];
+  char desc[512], make[64], model[64], soft[32], date[20], artist[64];
+};
+
+void CLASS tiff_set (ushort *ntag,
+	ushort tag, ushort type, int count, int val)
+{
+  struct tiff_tag *tt;
+  int c;
+
+  tt = (struct tiff_tag *)(ntag+1) + (*ntag)++;
+  tt->tag = tag;
+  tt->type = type;
+  tt->count = count;
+  if (type < 3 && count <= 4)
+    FORC(4) tt->val.c[c] = val >> (c << 3);
+  else if (type == 3 && count <= 2)
+    FORC(2) tt->val.s[c] = val >> (c << 4);
+  else tt->val.i = val;
+}
+
+#define TOFF(ptr) ((char *)(&(ptr)) - (char *)th)
+
+void CLASS tiff_head (struct tiff_hdr *th, int full)
+{
+  int c, psize=0;
+  struct tm *t;
+
+  memset (th, 0, sizeof *th);
+  th->order = htonl(0x4d4d4949) >> 16;
+  th->magic = 42;
+  th->ifd = 10;
+  if (full) {
+    tiff_set (&th->ntag, 254, 4, 1, 0);
+    tiff_set (&th->ntag, 256, 4, 1, width);
+    tiff_set (&th->ntag, 257, 4, 1, height);
+    tiff_set (&th->ntag, 258, 3, colors, output_bps);
+    if (colors > 2)
+      th->tag[th->ntag-1].val.i = TOFF(th->bps);
+    FORC4 th->bps[c] = output_bps;
+    tiff_set (&th->ntag, 259, 3, 1, 1);
+    tiff_set (&th->ntag, 262, 3, 1, 1 + (colors > 1));
+  }
+  tiff_set (&th->ntag, 270, 2, 512, TOFF(th->desc));
+  tiff_set (&th->ntag, 271, 2, 64, TOFF(th->make));
+  tiff_set (&th->ntag, 272, 2, 64, TOFF(th->model));
+  if (full) {
+    if (oprof) psize = ntohl(oprof[0]);
+    tiff_set (&th->ntag, 273, 4, 1, sizeof *th + psize);
+    tiff_set (&th->ntag, 277, 3, 1, colors);
+    tiff_set (&th->ntag, 278, 4, 1, height);
+    tiff_set (&th->ntag, 279, 4, 1, height*width*colors*output_bps/8);
+  } else
+    tiff_set (&th->ntag, 274, 3, 1, "12435867"[flip]-'0');
+  tiff_set (&th->ntag, 282, 5, 1, TOFF(th->rat[0]));
+  tiff_set (&th->ntag, 283, 5, 1, TOFF(th->rat[2]));
+  tiff_set (&th->ntag, 284, 3, 1, 1);
+  tiff_set (&th->ntag, 296, 3, 1, 2);
+  tiff_set (&th->ntag, 305, 2, 32, TOFF(th->soft));
+  tiff_set (&th->ntag, 306, 2, 20, TOFF(th->date));
+  tiff_set (&th->ntag, 315, 2, 64, TOFF(th->artist));
+  tiff_set (&th->ntag, 34665, 4, 1, TOFF(th->nexif));
+  if (psize) tiff_set (&th->ntag, 34675, 7, psize, sizeof *th);
+  tiff_set (&th->nexif, 33434, 5, 1, TOFF(th->rat[4]));
+  tiff_set (&th->nexif, 33437, 5, 1, TOFF(th->rat[6]));
+  tiff_set (&th->nexif, 34855, 3, 1, iso_speed);
+  tiff_set (&th->nexif, 37386, 5, 1, TOFF(th->rat[8]));
+  if (gpsdata[1]) {
+    tiff_set (&th->ntag, 34853, 4, 1, TOFF(th->ngps));
+    tiff_set (&th->ngps,  0, 1,  4, 0x202);
+    tiff_set (&th->ngps,  1, 2,  2, gpsdata[29]);
+    tiff_set (&th->ngps,  2, 5,  3, TOFF(th->gps[0]));
+    tiff_set (&th->ngps,  3, 2,  2, gpsdata[30]);
+    tiff_set (&th->ngps,  4, 5,  3, TOFF(th->gps[6]));
+    tiff_set (&th->ngps,  5, 1,  1, gpsdata[31]);
+    tiff_set (&th->ngps,  6, 5,  1, TOFF(th->gps[18]));
+    tiff_set (&th->ngps,  7, 5,  3, TOFF(th->gps[12]));
+    tiff_set (&th->ngps, 18, 2, 12, TOFF(th->gps[20]));
+    tiff_set (&th->ngps, 29, 2, 12, TOFF(th->gps[23]));
+    memcpy (th->gps, gpsdata, sizeof th->gps);
+  }
+  th->rat[0] = th->rat[2] = 300;
+  th->rat[1] = th->rat[3] = 1;
+  FORC(6) th->rat[4+c] = 1000000;
+  th->rat[4] *= shutter;
+  th->rat[6] *= aperture;
+  th->rat[8] *= focal_len;
+  strncpy (th->desc, desc, 512);
+  strncpy (th->make, make, 64);
+  strncpy (th->model, model, 64);
+  strcpy (th->soft, "dcraw v"VERSION);
+  t = gmtime (&timestamp);
+  sprintf (th->date, "%04d:%02d:%02d %02d:%02d:%02d",
+      t->tm_year+1900,t->tm_mon+1,t->tm_mday,t->tm_hour,t->tm_min,t->tm_sec);
+  strncpy (th->artist, artist, 64);
+}
+
+void CLASS jpeg_thumb()
+{
+  char *thumb;
+  ushort exif[5];
+  struct tiff_hdr th;
+
+  thumb = (char *) malloc (thumb_length);
+  merror (thumb, "jpeg_thumb()");
+  fread (thumb, 1, thumb_length, ifp);
+  fputc (0xff, ofp);
+  fputc (0xd8, ofp);
+  if (strcmp (thumb+6, "Exif")) {
+    memcpy (exif, "\xff\xe1  Exif\0\0", 10);
+    exif[1] = htons (8 + sizeof th);
+    fwrite (exif, 1, sizeof exif, ofp);
+    tiff_head (&th, 0);
+    fwrite (&th, 1, sizeof th, ofp);
+  }
+  fwrite (thumb+2, 1, thumb_length-2, ofp);
+  free (thumb);
+}
+
+void CLASS write_ppm_tiff()
+{
+  struct tiff_hdr th;
+  uchar *ppm;
+  ushort *ppm2;
+  int c, row, col, soff, rstep, cstep;
+  int perc, val, total, white=0x2000;
+
+  perc = width * height * 0.01;		/* 99th percentile white level */
+  if (fuji_width) perc /= 2;
+  if (!((highlight & ~2) || no_auto_bright))
+    for (white=c=0; c < colors; c++) {
+      for (val=0x2000, total=0; --val > 32; )
+	if ((total += histogram[c][val]) > perc) break;
+      if (white < val) white = val;
+    }
+  gamma_curve (gamm[0], gamm[1], 2, (white << 3)/bright);
+  iheight = height;
+  iwidth  = width;
+  if (flip & 4) SWAP(height,width);
+  ppm = (uchar *) calloc (width, colors*output_bps/8);
+  ppm2 = (ushort *) ppm;
+  merror (ppm, "write_ppm_tiff()");
+  if (output_tiff) {
+    tiff_head (&th, 1);
+    fwrite (&th, sizeof th, 1, ofp);
+    if (oprof)
+      fwrite (oprof, ntohl(oprof[0]), 1, ofp);
+  } else if (colors > 3)
+    fprintf (ofp,
+      "P7\nWIDTH %d\nHEIGHT %d\nDEPTH %d\nMAXVAL %d\nTUPLTYPE %s\nENDHDR\n",
+	width, height, colors, (1 << output_bps)-1, cdesc);
+  else
+    fprintf (ofp, "P%d\n%d %d\n%d\n",
+	colors/2+5, width, height, (1 << output_bps)-1);
+  soff  = flip_index (0, 0);
+  cstep = flip_index (0, 1) - soff;
+  rstep = flip_index (1, 0) - flip_index (0, width);
+  for (row=0; row < height; row++, soff += rstep) {
+    for (col=0; col < width; col++, soff += cstep)
+      if (output_bps == 8)
+	   FORCC ppm [col*colors+c] = curve[image[soff][c]] >> 8;
+      else FORCC ppm2[col*colors+c] = curve[image[soff][c]];
+    if (output_bps == 16 && !output_tiff && htons(0x55aa) != 0x55aa)
+      swab (ppm2, ppm2, width*colors*2);
+    fwrite (ppm, colors*output_bps/8, width, ofp);
+  }
+  free (ppm);
+}
+
+int CLASS main (int argc, const char **argv)
+{
+  int arg, status=0;
+  int timestamp_only=0, thumbnail_only=0, identify_only=0;
+  int user_qual=-1, user_black=-1, user_sat=-1, user_flip=-1;
+  int use_fuji_rotate=1, write_to_stdout=0, quality, i, c;
+  const char *sp, *bpfile=0, *dark_frame=0, *write_ext;
+  char opm, opt, *ofname, *cp;
+  struct utimbuf ut;
+#ifndef NO_LCMS
+  const char *cam_profile=0, *out_profile=0;
+#endif
+
+#ifndef LOCALTIME
+  putenv ((char *) "TZ=UTC");
+#endif
+#ifdef LOCALEDIR
+  setlocale (LC_CTYPE, "");
+  setlocale (LC_MESSAGES, "");
+  bindtextdomain ("dcraw", LOCALEDIR);
+  textdomain ("dcraw");
+#endif
+
+  if (argc == 1) {
+    printf(_("\nRaw photo decoder \"dcraw\" v%s"), VERSION);
+    printf(_("\nby Dave Coffin, dcoffin a cybercom o net\n"));
+    printf(_("\nUsage:  %s [OPTION]... [FILE]...\n\n"), argv[0]);
+    puts(_("-v        Print verbose messages"));
+    puts(_("-c        Write image data to standard output"));
+    puts(_("-e        Extract embedded thumbnail image"));
+    puts(_("-i        Identify files without decoding them"));
+    puts(_("-i -v     Identify files and show metadata"));
+    puts(_("-z        Change file dates to camera timestamp"));
+    puts(_("-w        Use camera white balance, if possible"));
+    puts(_("-a        Average the whole image for white balance"));
+    puts(_("-A <x y w h> Average a grey box for white balance"));
+    puts(_("-r <r g b g> Set custom white balance"));
+    puts(_("+M/-M     Use/don't use an embedded color matrix"));
+    puts(_("-C <r b>  Correct chromatic aberration"));
+    puts(_("-P <file> Fix the dead pixels listed in this file"));
+    puts(_("-K <file> Subtract dark frame (16-bit raw PGM)"));
+    puts(_("-k <num>  Set the darkness level"));
+    puts(_("-S <num>  Set the saturation level"));
+    puts(_("-n <num>  Set threshold for wavelet denoising"));
+    puts(_("-H [0-9]  Highlight mode (0=clip, 1=unclip, 2=blend, 3+=rebuild)"));
+    puts(_("-t [0-7]  Flip image (0=none, 3=180, 5=90CCW, 6=90CW)"));
+    puts(_("-o [0-5]  Output colorspace (raw,sRGB,Adobe,Wide,ProPhoto,XYZ)"));
+#ifndef NO_LCMS
+    puts(_("-o <file> Apply output ICC profile from file"));
+    puts(_("-p <file> Apply camera ICC profile from file or \"embed\""));
+#endif
+    puts(_("-d        Document mode (no color, no interpolation)"));
+    puts(_("-D        Document mode without scaling (totally raw)"));
+    puts(_("-j        Don't stretch or rotate raw pixels"));
+    puts(_("-W        Don't automatically brighten the image"));
+    puts(_("-b <num>  Adjust brightness (default = 1.0)"));
+    puts(_("-g <p ts> Set custom gamma curve (default = 2.222 4.5)"));
+    puts(_("-q [0-3]  Set the interpolation quality"));
+    puts(_("-h        Half-size color image (twice as fast as \"-q 0\")"));
+    puts(_("-f        Interpolate RGGB as four colors"));
+    puts(_("-m <num>  Apply a 3x3 median filter to R-G and B-G"));
+    puts(_("-s [0..N-1] Select one raw image or \"all\" from each file"));
+    puts(_("-6        Write 16-bit instead of 8-bit"));
+    puts(_("-4        Linear 16-bit, same as \"-6 -W -g 1 1\""));
+    puts(_("-T        Write TIFF instead of PPM"));
+    puts("");
+    return 1;
+  }
+  argv[argc] = "";
+  for (arg=1; (((opm = argv[arg][0]) - 2) | 2) == '+'; ) {
+    opt = argv[arg++][1];
+    if ((cp = (char *) strchr (sp="nbrkStqmHACg", opt)))
+      for (i=0; i < "114111111422"[cp-sp]-'0'; i++)
+	if (!isdigit(argv[arg+i][0])) {
+	  fprintf (stderr,_("Non-numeric argument to \"-%c\"\n"), opt);
+	  return 1;
+	}
+    switch (opt) {
+      case 'n':  threshold   = atof(argv[arg++]);  break;
+      case 'b':  bright      = atof(argv[arg++]);  break;
+      case 'r':
+	   FORC4 user_mul[c] = atof(argv[arg++]);  break;
+      case 'C':  aber[0] = 1 / atof(argv[arg++]);
+		 aber[2] = 1 / atof(argv[arg++]);  break;
+      case 'g':  gamm[0] =     atof(argv[arg++]);
+		 gamm[1] =     atof(argv[arg++]);
+		 if (gamm[0]) gamm[0] = 1/gamm[0]; break;
+      case 'k':  user_black  = atoi(argv[arg++]);  break;
+      case 'S':  user_sat    = atoi(argv[arg++]);  break;
+      case 't':  user_flip   = atoi(argv[arg++]);  break;
+      case 'q':  user_qual   = atoi(argv[arg++]);  break;
+      case 'm':  med_passes  = atoi(argv[arg++]);  break;
+      case 'H':  highlight   = atoi(argv[arg++]);  break;
+      case 's':
+	shot_select = abs(atoi(argv[arg]));
+	multi_out = !strcmp(argv[arg++],"all");
+	break;
+      case 'o':
+	if (isdigit(argv[arg][0]) && !argv[arg][1])
+	  output_color = atoi(argv[arg++]);
+#ifndef NO_LCMS
+	else     out_profile = argv[arg++];
+	break;
+      case 'p':  cam_profile = argv[arg++];
+#endif
+	break;
+      case 'P':  bpfile     = argv[arg++];  break;
+      case 'K':  dark_frame = argv[arg++];  break;
+      case 'z':  timestamp_only    = 1;  break;
+      case 'e':  thumbnail_only    = 1;  break;
+      case 'i':  identify_only     = 1;  break;
+      case 'c':  write_to_stdout   = 1;  break;
+      case 'v':  verbose           = 1;  break;
+      case 'h':  half_size         = 1;		/* "-h" implies "-f" */
+      case 'f':  four_color_rgb    = 1;  break;
+      case 'A':  FORC4 greybox[c]  = atoi(argv[arg++]);
+      case 'a':  use_auto_wb       = 1;  break;
+      case 'w':  use_camera_wb     = 1;  break;
+      case 'M':  use_camera_matrix = (opm == '+');  break;
+      case 'D':
+      case 'd':  document_mode = 1 + (opt == 'D');
+      case 'j':  use_fuji_rotate   = 0;  break;
+      case 'W':  no_auto_bright    = 1;  break;
+      case 'T':  output_tiff       = 1;  break;
+      case '4':  gamm[0] = gamm[1] =
+		 no_auto_bright    = 1;
+      case '6':  output_bps       = 16;  break;
+      default:
+	fprintf (stderr,_("Unknown option \"-%c\".\n"), opt);
+	return 1;
+    }
+  }
+  if (use_camera_matrix < 0)
+      use_camera_matrix = use_camera_wb;
+  if (arg == argc) {
+    fprintf (stderr,_("No files to process.\n"));
+    return 1;
+  }
+  if (write_to_stdout) {
+    if (isatty(1)) {
+      fprintf (stderr,_("Will not write an image to the terminal!\n"));
+      return 1;
+    }
+#if defined(WIN32) || defined(DJGPP) || defined(__CYGWIN__)
+    if (setmode(1,O_BINARY) < 0) {
+      perror ("setmode()");
+      return 1;
+    }
+#endif
+  }
+  for ( ; arg < argc; arg++) {
+    status = 1;
+    image = 0;
+    oprof = 0;
+    meta_data = ofname = 0;
+    ofp = stdout;
+    if (setjmp (failure)) {
+      if (fileno(ifp) > 2) fclose(ifp);
+      if (fileno(ofp) > 2) fclose(ofp);
+      status = 1;
+      goto cleanup;
+    }
+    ifname = argv[arg];
+    if (!(ifp = fopen (ifname, "rb"))) {
+      perror (ifname);
+      continue;
+    }
+    status = (identify(),!is_raw);
+    if (user_flip >= 0)
+      flip = user_flip;
+    switch ((flip+3600) % 360) {
+      case 270:  flip = 5;  break;
+      case 180:  flip = 3;  break;
+      case  90:  flip = 6;
+    }
+    if (timestamp_only) {
+      if ((status = !timestamp))
+	fprintf (stderr,_("%s has no timestamp.\n"), ifname);
+      else if (identify_only)
+	printf ("%10ld%10d %s\n", (long) timestamp, shot_order, ifname);
+      else {
+	if (verbose)
+	  fprintf (stderr,_("%s time set to %d.\n"), ifname, (int) timestamp);
+	ut.actime = ut.modtime = timestamp;
+	utime (ifname, &ut);
+      }
+      goto next;
+    }
+    write_fun = &CLASS write_ppm_tiff;
+    if (thumbnail_only) {
+      if ((status = !thumb_offset)) {
+	fprintf (stderr,_("%s has no thumbnail.\n"), ifname);
+	goto next;
+      } else if (thumb_load_raw) {
+	load_raw = thumb_load_raw;
+	data_offset = thumb_offset;
+	height = thumb_height;
+	width  = thumb_width;
+	filters = 0;
+      } else {
+	fseek (ifp, thumb_offset, SEEK_SET);
+	write_fun = write_thumb;
+	goto thumbnail;
+      }
+    }
+    if (load_raw == &CLASS kodak_ycbcr_load_raw) {
+      height += height & 1;
+      width  += width  & 1;
+    }
+    if (identify_only && verbose && make[0]) {
+      printf (_("\nFilename: %s\n"), ifname);
+      printf (_("Timestamp: %s"), ctime(&timestamp));
+      printf (_("Camera: %s %s\n"), make, model);
+      if (artist[0])
+	printf (_("Owner: %s\n"), artist);
+      if (dng_version) {
+	printf (_("DNG Version: "));
+	for (i=24; i >= 0; i -= 8)
+	  printf ("%d%c", dng_version >> i & 255, i ? '.':'\n');
+      }
+      printf (_("ISO speed: %d\n"), (int) iso_speed);
+      printf (_("Shutter: "));
+      if (shutter > 0 && shutter < 1)
+	shutter = (printf ("1/"), 1 / shutter);
+      printf (_("%0.1f sec\n"), shutter);
+      printf (_("Aperture: f/%0.1f\n"), aperture);
+      printf (_("Focal length: %0.1f mm\n"), focal_len);
+      printf (_("Embedded ICC profile: %s\n"), profile_length ? _("yes"):_("no"));
+      printf (_("Number of raw images: %d\n"), is_raw);
+      if (pixel_aspect != 1)
+	printf (_("Pixel Aspect Ratio: %0.6f\n"), pixel_aspect);
+      if (thumb_offset)
+	printf (_("Thumb size:  %4d x %d\n"), thumb_width, thumb_height);
+      printf (_("Full size:   %4d x %d\n"), raw_width, raw_height);
+    } else if (!is_raw)
+      fprintf (stderr,_("Cannot decode file %s\n"), ifname);
+    if (!is_raw) goto next;
+    shrink = filters &&
+	(half_size || threshold || aber[0] != 1 || aber[2] != 1);
+    iheight = (height + shrink) >> shrink;
+    iwidth  = (width  + shrink) >> shrink;
+    if (identify_only) {
+      if (verbose) {
+	if (use_fuji_rotate) {
+	  if (fuji_width) {
+	    fuji_width = (fuji_width - 1 + shrink) >> shrink;
+	    iwidth = fuji_width / sqrt(0.5);
+	    iheight = (iheight - fuji_width) / sqrt(0.5);
+	  } else {
+	    if (pixel_aspect < 1) iheight = iheight / pixel_aspect + 0.5;
+	    if (pixel_aspect > 1) iwidth  = iwidth  * pixel_aspect + 0.5;
+	  }
+	}
+	if (flip & 4)
+	  SWAP(iheight,iwidth);
+	printf (_("Image size:  %4d x %d\n"), width, height);
+	printf (_("Output size: %4d x %d\n"), iwidth, iheight);
+	printf (_("Raw colors: %d"), colors);
+	if (filters) {
+	  printf (_("\nFilter pattern: "));
+	  if (!cdesc[3]) cdesc[3] = 'G';
+	  for (i=0; i < 16; i++)
+	    putchar (cdesc[fc(i >> 1,i & 1)]);
+	}
+	printf (_("\nDaylight multipliers:"));
+	FORCC printf (" %f", pre_mul[c]);
+	if (cam_mul[0] > 0) {
+	  printf (_("\nCamera multipliers:"));
+	  FORC4 printf (" %f", cam_mul[c]);
+	}
+	putchar ('\n');
+      } else
+	printf (_("%s is a %s %s image.\n"), ifname, make, model);
+next:
+      fclose(ifp);
+      continue;
+    }
+    if (use_camera_matrix && cmatrix[0][0] > 0.25) {
+      memcpy (rgb_cam, cmatrix, sizeof cmatrix);
+      raw_color = 0;
+    }
+    image = (ushort (*)[4]) calloc (iheight*iwidth, sizeof *image);
+    merror (image, "main()");
+    if (meta_length) {
+      meta_data = (char *) malloc (meta_length);
+      merror (meta_data, "main()");
+    }
+    if (verbose)
+      fprintf (stderr,_("Loading %s %s image from %s ...\n"),
+	make, model, ifname);
+    if (shot_select >= is_raw)
+      fprintf (stderr,_("%s: \"-s %d\" requests a nonexistent image!\n"),
+	ifname, shot_select);
+    fseeko (ifp, data_offset, SEEK_SET);
+    (*load_raw)();
+    if (zero_is_bad) remove_zeroes();
+    bad_pixels (bpfile);
+    if (dark_frame) subtract (dark_frame);
+    quality = 2 + !fuji_width;
+    if (user_qual >= 0) quality = user_qual;
+    if (user_black >= 0) black = user_black;
+    if (user_sat > 0) maximum = user_sat;
+#ifdef COLORCHECK
+    colorcheck();
+#endif
+    if (is_foveon && !document_mode) foveon_interpolate();
+    if (!is_foveon && document_mode < 2) scale_colors();
+    pre_interpolate();
+    if (filters && !document_mode) {
+      if (quality == 0)
+	lin_interpolate();
+      else if (quality == 1 || colors > 3)
+	vng_interpolate();
+      else if (quality == 2)
+	ppg_interpolate();
+      else ahd_interpolate();
+    }
+    if (mix_green)
+      for (colors=3, i=0; i < height*width; i++)
+	image[i][1] = (image[i][1] + image[i][3]) >> 1;
+    if (!is_foveon && colors == 3) median_filter();
+    if (!is_foveon && highlight == 2) blend_highlights();
+    if (!is_foveon && highlight > 2) recover_highlights();
+    if (use_fuji_rotate) fuji_rotate();
+#ifndef NO_LCMS
+    if (cam_profile) apply_profile (cam_profile, out_profile);
+#endif
+    convert_to_rgb();
+    if (use_fuji_rotate) stretch();
+thumbnail:
+    if (write_fun == &CLASS jpeg_thumb)
+      write_ext = ".jpg";
+    else if (output_tiff && write_fun == &CLASS write_ppm_tiff)
+      write_ext = ".tiff";
+    else
+      write_ext = ".pgm\0.ppm\0.ppm\0.pam" + colors*5-5;
+    ofname = (char *) malloc (strlen(ifname) + 64);
+    merror (ofname, "main()");
+    if (write_to_stdout)
+      strcpy (ofname,_("standard output"));
+    else {
+      strcpy (ofname, ifname);
+      if ((cp = strrchr (ofname, '.'))) *cp = 0;
+      if (multi_out)
+	sprintf (ofname+strlen(ofname), "_%0*d",
+		snprintf(0,0,"%d",is_raw-1), shot_select);
+      if (thumbnail_only)
+	strcat (ofname, ".thumb");
+      strcat (ofname, write_ext);
+      ofp = fopen (ofname, "wb");
+      if (!ofp) {
+	status = 1;
+	perror (ofname);
+	goto cleanup;
+      }
+    }
+    if (verbose)
+      fprintf (stderr,_("Writing data to %s ...\n"), ofname);
+    (*write_fun)();
+    fclose(ifp);
+    if (ofp != stdout) fclose(ofp);
+cleanup:
+    if (meta_data) free (meta_data);
+    if (ofname) free (ofname);
+    if (oprof) free (oprof);
+    if (image) free (image);
+    if (multi_out) {
+      if (++shot_select < is_raw) arg--;
+      else shot_select = 0;
+    }
+  }
+  return status;
+}
diff --git a/ossim_plugins/libraw/LibRaw-0.9.0/internal/dcraw_common.cpp b/ossim_plugins/libraw/LibRaw-0.9.0/internal/dcraw_common.cpp
new file mode 100644
index 0000000..252ca9e
--- /dev/null
+++ b/ossim_plugins/libraw/LibRaw-0.9.0/internal/dcraw_common.cpp
@@ -0,0 +1,8737 @@
+/* 
+   GENERATED FILE, DO NOT EDIT
+   Generated from dcraw/dcraw.c at Wed Apr 21 09:55:20 2010
+   Look into original file (probably http://cybercom.net/~dcoffin/dcraw/dcraw.c)
+   for copyright information.
+*/
+
+#line 264 "dcraw/dcraw.c"
+#define CLASS LibRaw::
+#include "libraw/libraw_types.h"
+#define LIBRAW_LIBRARY_BUILD
+#define LIBRAW_IO_REDEFINED
+#include "libraw/libraw.h"
+#include "internal/defines.h"
+#include "internal/var_defines.h"
+
+#line 274 "dcraw/dcraw.c"
+
+#ifndef __GLIBC__
+char *my_memmem (char *haystack, size_t haystacklen,
+	      char *needle, size_t needlelen)
+{
+  char *c;
+  for (c = haystack; c <= haystack + haystacklen - needlelen; c++)
+    if (!memcmp (c, needle, needlelen))
+      return c;
+  return 0;
+}
+#define memmem my_memmem
+#endif
+
+#line 308 "dcraw/dcraw.c"
+
+ushort CLASS sget2 (uchar *s)
+{
+  if (order == 0x4949)		/* "II" means little-endian */
+    return s[0] | s[1] << 8;
+  else				/* "MM" means big-endian */
+    return s[0] << 8 | s[1];
+}
+
+ushort CLASS get2()
+{
+  uchar str[2] = { 0xff,0xff };
+  fread (str, 1, 2, ifp);
+  return sget2(str);
+}
+
+unsigned CLASS sget4 (uchar *s)
+{
+  if (order == 0x4949)
+    return s[0] | s[1] << 8 | s[2] << 16 | s[3] << 24;
+  else
+    return s[0] << 24 | s[1] << 16 | s[2] << 8 | s[3];
+}
+#define sget4(s) sget4((uchar *)s)
+
+unsigned CLASS get4()
+{
+  uchar str[4] = { 0xff,0xff,0xff,0xff };
+  fread (str, 1, 4, ifp);
+  return sget4(str);
+}
+
+unsigned CLASS getint (int type)
+{
+  return type == 3 ? get2() : get4();
+}
+
+float CLASS int_to_float (int i)
+{
+  union { int i; float f; } u;
+  u.i = i;
+  return u.f;
+}
+
+double CLASS getreal (int type)
+{
+  union { char c[8]; double d; } u;
+  int i, rev;
+
+  switch (type) {
+    case 3: return (unsigned short) get2();
+    case 4: return (unsigned int) get4();
+    case 5:  u.d = (unsigned int) get4();
+      return u.d / (unsigned int) get4();
+    case 8: return (signed short) get2();
+    case 9: return (signed int) get4();
+    case 10: u.d = (signed int) get4();
+      return u.d / (signed int) get4();
+    case 11: return int_to_float (get4());
+    case 12:
+      rev = 7 * ((order == 0x4949) == (ntohs(0x1234) == 0x1234));
+      for (i=0; i < 8; i++)
+	u.c[i ^ rev] = fgetc(ifp);
+      return u.d;
+    default: return fgetc(ifp);
+  }
+}
+
+void CLASS read_shorts (ushort *pixel, int count)
+{
+  if (fread (pixel, 2, count, ifp) < count) derror();
+  if ((order == 0x4949) == (ntohs(0x1234) == 0x1234))
+      swab ((char*)pixel, (char*)pixel, count*2);
+}
+#line 385 "dcraw/dcraw.c"
+void CLASS canon_black (double dark[2], int nblack)
+{
+  int c, diff, row, col;
+
+#ifdef LIBRAW_LIBRARY_BUILD
+  if(!( filtering_mode & LIBRAW_FILTERING_NOBLACKS) )
+      {
+#endif
+  if (!nblack) return;
+  FORC(2) dark[c] /= nblack >> 1;
+  if ((diff = dark[0] - dark[1]))
+    for (row=0; row < height; row++)
+      for (col=1; col < width; col+=2)
+	BAYER(row,col) += diff;
+#ifdef LIBRAW_LIBRARY_BUILD
+      }
+#endif
+  dark[1] += diff;
+  black = (dark[0] + dark[1] + 1) / 2;
+}
+
+void CLASS canon_600_fixed_wb (int temp)
+{
+  static const short mul[4][5] = {
+    {  667, 358,397,565,452 },
+    {  731, 390,367,499,517 },
+    { 1119, 396,348,448,537 },
+    { 1399, 485,431,508,688 } };
+  int lo, hi, i;
+  float frac=0;
+
+  for (lo=4; --lo; )
+    if (*mul[lo] <= temp) break;
+  for (hi=0; hi < 3; hi++)
+    if (*mul[hi] >= temp) break;
+  if (lo != hi)
+    frac = (float) (temp - *mul[lo]) / (*mul[hi] - *mul[lo]);
+  for (i=1; i < 5; i++)
+    pre_mul[i-1] = 1 / (frac * mul[hi][i] + (1-frac) * mul[lo][i]);
+#ifdef LIBRAW_LIBRARY_BUILD
+  color_flags.pre_mul_state = LIBRAW_COLORSTATE_CONST;
+#endif
+}
+
+/* Return values:  0 = white  1 = near white  2 = not white */
+int CLASS canon_600_color (int ratio[2], int mar)
+{
+  int clipped=0, target, miss;
+
+  if (flash_used) {
+    if (ratio[1] < -104)
+      { ratio[1] = -104; clipped = 1; }
+    if (ratio[1] >   12)
+      { ratio[1] =   12; clipped = 1; }
+  } else {
+    if (ratio[1] < -264 || ratio[1] > 461) return 2;
+    if (ratio[1] < -50)
+      { ratio[1] = -50; clipped = 1; }
+    if (ratio[1] > 307)
+      { ratio[1] = 307; clipped = 1; }
+  }
+  target = flash_used || ratio[1] < 197
+	? -38 - (398 * ratio[1] >> 10)
+	: -123 + (48 * ratio[1] >> 10);
+  if (target - mar <= ratio[0] &&
+      target + 20  >= ratio[0] && !clipped) return 0;
+  miss = target - ratio[0];
+  if (abs(miss) >= mar*4) return 2;
+  if (miss < -20) miss = -20;
+  if (miss > mar) miss = mar;
+  ratio[0] = target - miss;
+  return 1;
+}
+
+void CLASS canon_600_auto_wb()
+{
+  int mar, row, col, i, j, st, count[] = { 0,0 };
+  int test[8], total[2][8], ratio[2][2], stat[2];
+
+  memset (&total, 0, sizeof total);
+  i = canon_ev + 0.5;
+  if      (i < 10) mar = 150;
+  else if (i > 12) mar = 20;
+  else mar = 280 - 20 * i;
+  if (flash_used) mar = 80;
+  for (row=14; row < height-14; row+=4)
+    for (col=10; col < width; col+=2) {
+      for (i=0; i < 8; i++)
+	test[(i & 4) + FC(row+(i >> 1),col+(i & 1))] =
+		    BAYER(row+(i >> 1),col+(i & 1));
+      for (i=0; i < 8; i++)
+	if (test[i] < 150 || test[i] > 1500) goto next;
+      for (i=0; i < 4; i++)
+	if (abs(test[i] - test[i+4]) > 50) goto next;
+      for (i=0; i < 2; i++) {
+	for (j=0; j < 4; j+=2)
+	  ratio[i][j >> 1] = ((test[i*4+j+1]-test[i*4+j]) << 10) / test[i*4+j];
+	stat[i] = canon_600_color (ratio[i], mar);
+      }
+      if ((st = stat[0] | stat[1]) > 1) goto next;
+      for (i=0; i < 2; i++)
+	if (stat[i])
+	  for (j=0; j < 2; j++)
+	    test[i*4+j*2+1] = test[i*4+j*2] * (0x400 + ratio[i][j]) >> 10;
+      for (i=0; i < 8; i++)
+	total[st][i] += test[i];
+      count[st]++;
+next: ;
+    }
+  if (count[0] | count[1]) {
+    st = count[0]*200 < count[1];
+    for (i=0; i < 4; i++)
+      pre_mul[i] = 1.0 / (total[st][i] + total[st][i+4]);
+#ifdef LIBRAW_LIBRARY_BUILD
+    color_flags.pre_mul_state = LIBRAW_COLORSTATE_CALCULATED;
+#endif
+  }
+}
+
+void CLASS canon_600_coeff()
+{
+  static const short table[6][12] = {
+    { -190,702,-1878,2390,   1861,-1349,905,-393, -432,944,2617,-2105  },
+    { -1203,1715,-1136,1648, 1388,-876,267,245,  -1641,2153,3921,-3409 },
+    { -615,1127,-1563,2075,  1437,-925,509,3,     -756,1268,2519,-2007 },
+    { -190,702,-1886,2398,   2153,-1641,763,-251, -452,964,3040,-2528  },
+    { -190,702,-1878,2390,   1861,-1349,905,-393, -432,944,2617,-2105  },
+    { -807,1319,-1785,2297,  1388,-876,769,-257,  -230,742,2067,-1555  } };
+  int t=0, i, c;
+  float mc, yc;
+
+  mc = pre_mul[1] / pre_mul[2];
+  yc = pre_mul[3] / pre_mul[2];
+  if (mc > 1 && mc <= 1.28 && yc < 0.8789) t=1;
+  if (mc > 1.28 && mc <= 2) {
+    if  (yc < 0.8789) t=3;
+    else if (yc <= 2) t=4;
+  }
+  if (flash_used) t=5;
+  for (raw_color = i=0; i < 3; i++)
+    FORCC rgb_cam[i][c] = table[t][i*4 + c] / 1024.0;
+#ifdef LIBRAW_LIBRARY_BUILD
+  color_flags.rgb_cam_state = LIBRAW_COLORSTATE_CALCULATED;
+#endif
+}
+
+void CLASS canon_600_load_raw()
+{
+  uchar  data[1120], *dp;
+  ushort pixel[896], *pix;
+  int irow, row, col, val;
+  static const short mul[4][2] =
+  { { 1141,1145 }, { 1128,1109 }, { 1178,1149 }, { 1128,1109 } };
+
+  for (irow=row=0; irow < height; irow++) {
+    if (fread (data, 1, raw_width*5/4, ifp) < raw_width*5/4) derror();
+    for (dp=data, pix=pixel; dp < data+1120; dp+=10, pix+=8) {
+      pix[0] = (dp[0] << 2) + (dp[1] >> 6    );
+      pix[1] = (dp[2] << 2) + (dp[1] >> 4 & 3);
+      pix[2] = (dp[3] << 2) + (dp[1] >> 2 & 3);
+      pix[3] = (dp[4] << 2) + (dp[1]      & 3);
+      pix[4] = (dp[5] << 2) + (dp[9]      & 3);
+      pix[5] = (dp[6] << 2) + (dp[9] >> 2 & 3);
+      pix[6] = (dp[7] << 2) + (dp[9] >> 4 & 3);
+      pix[7] = (dp[8] << 2) + (dp[9] >> 6    );
+    }
+    for (col=0; col < width; col++)
+        {
+            BAYER(row,col) = pixel[col];
+        }
+    for (col=width; col < raw_width; col++)
+        {
+            black += pixel[col];
+#ifdef LIBRAW_LIBRARY_BUILD
+            ushort *dfp = get_masked_pointer(row,col);
+            if(dfp) *dfp = pixel[col];
+#endif
+        }
+    if ((row+=2) > height) row = 1;
+  }
+  if (raw_width > width)
+    black = black / ((raw_width - width) * height) - 4;
+  for (row=0; row < height; row++)
+    for (col=0; col < width; col++) {
+#ifdef LIBRAW_LIBRARY_BUILD
+     if( filtering_mode & LIBRAW_FILTERING_NOBLACKS)  
+         val = BAYER(row,col);
+     else
+#endif
+      if ((val = BAYER(row,col) - black) < 0) val = 0;
+      val = val * mul[row & 3][col & 1] >> 9;
+      BAYER(row,col) = val;
+#ifdef LIBRAW_LIBRARY_BUILD
+      if((int)channel_maximum[FC(row,col)] < val ) channel_maximum[FC(row,col)] = val;
+#endif
+    }
+  canon_600_fixed_wb(1311);
+  canon_600_auto_wb();
+  canon_600_coeff();
+  maximum = (0x3ff - black) * 1109 >> 9;
+  black = 0;
+}
+
+void CLASS remove_zeroes()
+{
+  unsigned row, col, tot, n, r, c;
+
+#ifdef LIBRAW_LIBRARY_BUILD
+  RUN_CALLBACK(LIBRAW_PROGRESS_REMOVE_ZEROES,0,2);
+#endif
+  for (row=0; row < height; row++)
+    for (col=0; col < width; col++)
+      if (BAYER(row,col) == 0) {
+	tot = n = 0;
+	for (r = row-2; r <= row+2; r++)
+	  for (c = col-2; c <= col+2; c++)
+	    if (r < height && c < width &&
+		FC(r,c) == FC(row,col) && BAYER(r,c))
+	      tot += (n++,BAYER(r,c));
+	if (n) BAYER(row,col) = tot/n;
+      }
+#ifdef LIBRAW_LIBRARY_BUILD
+  RUN_CALLBACK(LIBRAW_PROGRESS_REMOVE_ZEROES,1,2);
+#endif
+}
+
+int CLASS canon_s2is()
+{
+  unsigned row;
+
+  for (row=0; row < 100; row++) {
+    fseek (ifp, row*3340 + 3284, SEEK_SET);
+    if (getc(ifp) > 15) return 1;
+  }
+  return 0;
+}
+
+/*
+   getbits(-1) initializes the buffer
+   getbits(n) where 0 <= n <= 25 returns an n-bit integer
+ */
+unsigned CLASS getbithuff (int nbits, ushort *huff)
+{
+#ifdef LIBRAW_NOTHREADS
+  static unsigned bitbuf=0;
+  static int vbits=0, reset=0;
+#else
+#define bitbuf tls->getbits.bitbuf
+#define vbits  tls->getbits.vbits
+#define reset  tls->getbits.reset
+#endif
+  unsigned c;
+
+  if (nbits == -1)
+    return bitbuf = vbits = reset = 0;
+  if (nbits == 0 || vbits < 0) return 0;
+  while (!reset && vbits < nbits && (c = fgetc(ifp)) != EOF &&
+    !(reset = zero_after_ff && c == 0xff && fgetc(ifp))) {
+    bitbuf = (bitbuf << 8) + (uchar) c;
+    vbits += 8;
+  }
+  c = bitbuf << (32-vbits) >> (32-nbits);
+  if (huff) {
+    vbits -= huff[c] >> 8;
+    c = (uchar) huff[c];
+  } else
+    vbits -= nbits;
+  if (vbits < 0) derror();
+  return c;
+#ifndef LIBRAW_NOTHREADS
+#undef bitbuf
+#undef vbits
+#undef reset
+#endif
+}
+
+#define getbits(n) getbithuff(n,0)
+#define gethuff(h) getbithuff(*h,h+1)
+
+/*
+   Construct a decode tree according to the specification in *source.
+   The first 16 bytes specify how many codes should be 1-bit, 2-bit
+   3-bit, etc.  Bytes after that are the leaf values.
+
+   For example, if the source is
+
+    { 0,1,4,2,3,1,2,0,0,0,0,0,0,0,0,0,
+      0x04,0x03,0x05,0x06,0x02,0x07,0x01,0x08,0x09,0x00,0x0a,0x0b,0xff  },
+
+   then the code is
+
+	00		0x04
+	010		0x03
+	011		0x05
+	100		0x06
+	101		0x02
+	1100		0x07
+	1101		0x01
+	11100		0x08
+	11101		0x09
+	11110		0x00
+	111110		0x0a
+	1111110		0x0b
+	1111111		0xff
+ */
+ushort * CLASS make_decoder_ref (const uchar **source)
+{
+  int max, len, h, i, j;
+  const uchar *count;
+  ushort *huff;
+
+  count = (*source += 16) - 17;
+  for (max=16; max && !count[max]; max--);
+  huff = (ushort *) calloc (1 + (1 << max), sizeof *huff);
+  merror (huff, "make_decoder()");
+  huff[0] = max;
+  for (h=len=1; len <= max; len++)
+    for (i=0; i < count[len]; i++, ++*source)
+      for (j=0; j < 1 << (max-len); j++)
+	if (h <= 1 << max)
+	  huff[h++] = len << 8 | **source;
+  return huff;
+}
+
+ushort * CLASS make_decoder (const uchar *source)
+{
+  return make_decoder_ref (&source);
+}
+
+void CLASS crw_init_tables (unsigned table, ushort *huff[2])
+{
+  static const uchar first_tree[3][29] = {
+    { 0,1,4,2,3,1,2,0,0,0,0,0,0,0,0,0,
+      0x04,0x03,0x05,0x06,0x02,0x07,0x01,0x08,0x09,0x00,0x0a,0x0b,0xff  },
+    { 0,2,2,3,1,1,1,1,2,0,0,0,0,0,0,0,
+      0x03,0x02,0x04,0x01,0x05,0x00,0x06,0x07,0x09,0x08,0x0a,0x0b,0xff  },
+    { 0,0,6,3,1,1,2,0,0,0,0,0,0,0,0,0,
+
+      0x06,0x05,0x07,0x04,0x08,0x03,0x09,0x02,0x00,0x0a,0x01,0x0b,0xff  },
+  };
+  static const uchar second_tree[3][180] = {
+    { 0,2,2,2,1,4,2,1,2,5,1,1,0,0,0,139,
+      0x03,0x04,0x02,0x05,0x01,0x06,0x07,0x08,
+      0x12,0x13,0x11,0x14,0x09,0x15,0x22,0x00,0x21,0x16,0x0a,0xf0,
+      0x23,0x17,0x24,0x31,0x32,0x18,0x19,0x33,0x25,0x41,0x34,0x42,
+      0x35,0x51,0x36,0x37,0x38,0x29,0x79,0x26,0x1a,0x39,0x56,0x57,
+      0x28,0x27,0x52,0x55,0x58,0x43,0x76,0x59,0x77,0x54,0x61,0xf9,
+      0x71,0x78,0x75,0x96,0x97,0x49,0xb7,0x53,0xd7,0x74,0xb6,0x98,
+      0x47,0x48,0x95,0x69,0x99,0x91,0xfa,0xb8,0x68,0xb5,0xb9,0xd6,
+      0xf7,0xd8,0x67,0x46,0x45,0x94,0x89,0xf8,0x81,0xd5,0xf6,0xb4,
+      0x88,0xb1,0x2a,0x44,0x72,0xd9,0x87,0x66,0xd4,0xf5,0x3a,0xa7,
+      0x73,0xa9,0xa8,0x86,0x62,0xc7,0x65,0xc8,0xc9,0xa1,0xf4,0xd1,
+      0xe9,0x5a,0x92,0x85,0xa6,0xe7,0x93,0xe8,0xc1,0xc6,0x7a,0x64,
+      0xe1,0x4a,0x6a,0xe6,0xb3,0xf1,0xd3,0xa5,0x8a,0xb2,0x9a,0xba,
+      0x84,0xa4,0x63,0xe5,0xc5,0xf3,0xd2,0xc4,0x82,0xaa,0xda,0xe4,
+      0xf2,0xca,0x83,0xa3,0xa2,0xc3,0xea,0xc2,0xe2,0xe3,0xff,0xff  },
+    { 0,2,2,1,4,1,4,1,3,3,1,0,0,0,0,140,
+      0x02,0x03,0x01,0x04,0x05,0x12,0x11,0x06,
+      0x13,0x07,0x08,0x14,0x22,0x09,0x21,0x00,0x23,0x15,0x31,0x32,
+      0x0a,0x16,0xf0,0x24,0x33,0x41,0x42,0x19,0x17,0x25,0x18,0x51,
+      0x34,0x43,0x52,0x29,0x35,0x61,0x39,0x71,0x62,0x36,0x53,0x26,
+      0x38,0x1a,0x37,0x81,0x27,0x91,0x79,0x55,0x45,0x28,0x72,0x59,
+      0xa1,0xb1,0x44,0x69,0x54,0x58,0xd1,0xfa,0x57,0xe1,0xf1,0xb9,
+      0x49,0x47,0x63,0x6a,0xf9,0x56,0x46,0xa8,0x2a,0x4a,0x78,0x99,
+      0x3a,0x75,0x74,0x86,0x65,0xc1,0x76,0xb6,0x96,0xd6,0x89,0x85,
+      0xc9,0xf5,0x95,0xb4,0xc7,0xf7,0x8a,0x97,0xb8,0x73,0xb7,0xd8,
+      0xd9,0x87,0xa7,0x7a,0x48,0x82,0x84,0xea,0xf4,0xa6,0xc5,0x5a,
+      0x94,0xa4,0xc6,0x92,0xc3,0x68,0xb5,0xc8,0xe4,0xe5,0xe6,0xe9,
+      0xa2,0xa3,0xe3,0xc2,0x66,0x67,0x93,0xaa,0xd4,0xd5,0xe7,0xf8,
+      0x88,0x9a,0xd7,0x77,0xc4,0x64,0xe2,0x98,0xa5,0xca,0xda,0xe8,
+      0xf3,0xf6,0xa9,0xb2,0xb3,0xf2,0xd2,0x83,0xba,0xd3,0xff,0xff  },
+    { 0,0,6,2,1,3,3,2,5,1,2,2,8,10,0,117,
+      0x04,0x05,0x03,0x06,0x02,0x07,0x01,0x08,
+      0x09,0x12,0x13,0x14,0x11,0x15,0x0a,0x16,0x17,0xf0,0x00,0x22,
+      0x21,0x18,0x23,0x19,0x24,0x32,0x31,0x25,0x33,0x38,0x37,0x34,
+      0x35,0x36,0x39,0x79,0x57,0x58,0x59,0x28,0x56,0x78,0x27,0x41,
+      0x29,0x77,0x26,0x42,0x76,0x99,0x1a,0x55,0x98,0x97,0xf9,0x48,
+      0x54,0x96,0x89,0x47,0xb7,0x49,0xfa,0x75,0x68,0xb6,0x67,0x69,
+      0xb9,0xb8,0xd8,0x52,0xd7,0x88,0xb5,0x74,0x51,0x46,0xd9,0xf8,
+      0x3a,0xd6,0x87,0x45,0x7a,0x95,0xd5,0xf6,0x86,0xb4,0xa9,0x94,
+      0x53,0x2a,0xa8,0x43,0xf5,0xf7,0xd4,0x66,0xa7,0x5a,0x44,0x8a,
+      0xc9,0xe8,0xc8,0xe7,0x9a,0x6a,0x73,0x4a,0x61,0xc7,0xf4,0xc6,
+      0x65,0xe9,0x72,0xe6,0x71,0x91,0x93,0xa6,0xda,0x92,0x85,0x62,
+      0xf3,0xc5,0xb2,0xa4,0x84,0xba,0x64,0xa5,0xb3,0xd2,0x81,0xe5,
+      0xd3,0xaa,0xc4,0xca,0xf2,0xb1,0xe4,0xd1,0x83,0x63,0xea,0xc3,
+      0xe2,0x82,0xf1,0xa3,0xc2,0xa1,0xc1,0xe3,0xa2,0xe1,0xff,0xff  }
+  };
+  if (table > 2) table = 2;
+  huff[0] = make_decoder ( first_tree[table]);
+  huff[1] = make_decoder (second_tree[table]);
+}
+
+/*
+   Return 0 if the image starts with compressed data,
+   1 if it starts with uncompressed low-order bits.
+
+   In Canon compressed data, 0xff is always followed by 0x00.
+ */
+int CLASS canon_has_lowbits()
+{
+  uchar test[0x4000];
+  int ret=1;
+  unsigned i;
+
+  fseek (ifp, 0, SEEK_SET);
+  fread (test, 1, sizeof test, ifp);
+  for (i=540; i < sizeof test - 1; i++)
+    if (test[i] == 0xff) {
+      if (test[i+1]) return 1;
+      ret=0;
+    }
+  return ret;
+}
+
+void CLASS canon_compressed_load_raw()
+{
+  ushort *pixel, *prow, *huff[2];
+  int nblocks, lowbits, i, c, row, r, col, save, val, nblack=0;
+  unsigned irow, icol;
+  int block, diffbuf[64], leaf, len, diff, carry=0, pnum=0, base[2];
+  double dark[2] = { 0,0 };
+
+  crw_init_tables (tiff_compress, huff);
+  pixel = (ushort *) calloc (raw_width*8, sizeof *pixel);
+  merror (pixel, "canon_compressed_load_raw()");
+  lowbits = canon_has_lowbits();
+  if (!lowbits) maximum = 0x3ff;
+  fseek (ifp, 540 + lowbits*raw_height*raw_width/4, SEEK_SET);
+  zero_after_ff = 1;
+  getbits(-1);
+  for (row=0; row < raw_height; row+=8) {
+    nblocks = MIN (8, raw_height-row) * raw_width >> 6;
+    for (block=0; block < nblocks; block++) {
+      memset (diffbuf, 0, sizeof diffbuf);
+      for (i=0; i < 64; i++ ) {
+	leaf = gethuff(huff[i > 0]);
+	if (leaf == 0 && i) break;
+	if (leaf == 0xff) continue;
+	i  += leaf >> 4;
+	len = leaf & 15;
+	if (len == 0) continue;
+	diff = getbits(len);
+	if ((diff & (1 << (len-1))) == 0)
+	  diff -= (1 << len) - 1;
+	if (i < 64) diffbuf[i] = diff;
+      }
+      diffbuf[0] += carry;
+      carry = diffbuf[0];
+      for (i=0; i < 64; i++ ) {
+	if (pnum++ % raw_width == 0)
+	  base[0] = base[1] = 512;
+	if ((pixel[(block << 6) + i] = base[i & 1] += diffbuf[i]) >> 10)
+	  derror();
+      }
+    }
+    if (lowbits) {
+      save = ftell(ifp);
+      fseek (ifp, 26 + row*raw_width/4, SEEK_SET);
+      for (prow=pixel, i=0; i < raw_width*2; i++) {
+	c = fgetc(ifp);
+	for (r=0; r < 8; r+=2, prow++) {
+	  val = (*prow << 2) + ((c >> r) & 3);
+	  if (raw_width == 2672 && val < 512) val += 2;
+	  *prow = val;
+	}
+      }
+      fseek (ifp, save, SEEK_SET);
+    }
+    for (r=0; r < 8; r++) {
+      irow = row - top_margin + r;
+#ifndef LIBRAW_LIBRARY_BUILD
+      if (irow >= height) continue;
+#endif
+      for (col=0; col < raw_width; col++) {
+#ifdef LIBRAW_LIBRARY_BUILD
+          ushort *dfp = get_masked_pointer(row+r,col);
+          if(dfp) *dfp = pixel[r*raw_width+col];
+          if (irow >= height) continue; // skip for top/bottom rows
+#endif
+	icol = col - left_margin;
+	if (icol < width)
+            {
+#ifdef LIBRAW_LIBRARY_BUILD
+                ushort val = pixel[r*raw_width+col];
+                ushort color = FC(irow,icol);
+                if(channel_maximum[color] < val) channel_maximum[color]=val;
+#endif
+                BAYER(irow,icol) = pixel[r*raw_width+col];
+            }
+	else if (col > 1 && (unsigned) (col-left_margin+2) > width+3)
+	  dark[icol & 1] += (nblack++,pixel[r*raw_width+col]);
+      }
+    }
+  }
+  free (pixel);
+  FORC(2) free (huff[c]);
+  canon_black (dark, nblack);
+}
+
+#line 895 "dcraw/dcraw.c"
+int CLASS ljpeg_start (struct jhead *jh, int info_only)
+{
+  int c, tag, len;
+  uchar data[0x10000];
+  const uchar *dp;
+
+  memset (jh, 0, sizeof *jh);
+  jh->restart = INT_MAX;
+  fread (data, 2, 1, ifp);
+  if (data[1] != 0xd8) return 0;
+  do {
+    fread (data, 2, 2, ifp);
+    tag =  data[0] << 8 | data[1];
+    len = (data[2] << 8 | data[3]) - 2;
+    if (tag <= 0xff00) return 0;
+    fread (data, 1, len, ifp);
+    switch (tag) {
+      case 0xffc3:
+	jh->sraw = ((data[7] >> 4) * (data[7] & 15) - 1) & 3;
+      case 0xffc0:
+	jh->bits = data[0];
+	jh->high = data[1] << 8 | data[2];
+	jh->wide = data[3] << 8 | data[4];
+	jh->clrs = data[5] + jh->sraw;
+	if (len == 9 && !dng_version) getc(ifp);
+	break;
+      case 0xffc4:
+	if (info_only) break;
+	for (dp = data; dp < data+len && (c = *dp++) < 4; )
+	  jh->free[c] = jh->huff[c] = make_decoder_ref (&dp);
+	break;
+      case 0xffda:
+	jh->psv = data[1+data[0]*2];
+	jh->bits -= data[3+data[0]*2] & 15;
+	break;
+      case 0xffdd:
+	jh->restart = data[0] << 8 | data[1];
+    }
+  } while (tag != 0xffda);
+  if (info_only) return 1;
+  FORC(5) if (!jh->huff[c+1]) jh->huff[c+1] = jh->huff[c];
+  if (jh->sraw) {
+    FORC(4)        jh->huff[2+c] = jh->huff[1];
+    FORC(jh->sraw) jh->huff[1+c] = jh->huff[0];
+  }
+  jh->row = (ushort *) calloc (jh->wide*jh->clrs, 4);
+  merror (jh->row, "ljpeg_start()");
+  return zero_after_ff = 1;
+}
+
+void CLASS ljpeg_end (struct jhead *jh)
+{
+  int c;
+  FORC4 if (jh->free[c]) free (jh->free[c]);
+  free (jh->row);
+}
+
+int CLASS ljpeg_diff (ushort *huff)
+{
+  int len, diff;
+
+  len = gethuff(huff);
+  if (len == 16 && (!dng_version || dng_version >= 0x1010000))
+    return -32768;
+  diff = getbits(len);
+  if ((diff & (1 << (len-1))) == 0)
+    diff -= (1 << len) - 1;
+  return diff;
+}
+
+ushort * CLASS ljpeg_row (int jrow, struct jhead *jh)
+{
+  int col, c, diff, pred, spred=0;
+  ushort mark=0, *row[3];
+
+  if (jrow * jh->wide % jh->restart == 0) {
+    FORC(6) jh->vpred[c] = 1 << (jh->bits-1);
+    if (jrow) {
+      fseek (ifp, -2, SEEK_CUR);
+      do mark = (mark << 8) + (c = fgetc(ifp));
+      while (c != EOF && mark >> 4 != 0xffd);
+    }
+    getbits(-1);
+  }
+  FORC3 row[c] = jh->row + jh->wide*jh->clrs*((jrow+c) & 1);
+  for (col=0; col < jh->wide; col++)
+    FORC(jh->clrs) {
+      diff = ljpeg_diff (jh->huff[c]);
+      if (jh->sraw && c <= jh->sraw && (col | c))
+		    pred = spred;
+      else if (col) pred = row[0][-jh->clrs];
+      else	    pred = (jh->vpred[c] += diff) - diff;
+      if (jrow && col) switch (jh->psv) {
+	case 1:	break;
+	case 2: pred = row[1][0];					break;
+	case 3: pred = row[1][-jh->clrs];				break;
+	case 4: pred = pred +   row[1][0] - row[1][-jh->clrs];		break;
+	case 5: pred = pred + ((row[1][0] - row[1][-jh->clrs]) >> 1);	break;
+	case 6: pred = row[1][0] + ((pred - row[1][-jh->clrs]) >> 1);	break;
+	case 7: pred = (pred + row[1][0]) >> 1;				break;
+	default: pred = 0;
+      }
+      if ((**row = pred + diff) >> jh->bits) derror();
+      if (c <= jh->sraw) spred = **row;
+      row[0]++; row[1]++;
+    }
+  return row[2];
+}
+
+void CLASS lossless_jpeg_load_raw()
+{
+  int jwide, jrow, jcol, val, jidx, i, j, row=0, col=0, nblack=0;
+  double dark[2] = { 0,0 };
+  struct jhead jh;
+  int min=INT_MAX;
+  ushort *rp;
+
+  if (!ljpeg_start (&jh, 0)) return;
+  jwide = jh.wide * jh.clrs;
+
+  for (jrow=0; jrow < jh.high; jrow++) {
+    rp = ljpeg_row (jrow, &jh);
+    for (jcol=0; jcol < jwide; jcol++) {
+      val = *rp++;
+      if (jh.bits <= 12)
+#ifdef LIBRAW_LIBRARY_BUILD
+          if( !(filtering_mode & LIBRAW_FILTERING_NORAWCURVE))
+#endif
+	val = curve[val & 0xfff];
+      if (cr2_slice[0]) {
+	jidx = jrow*jwide + jcol;
+	i = jidx / (cr2_slice[1]*jh.high);
+	if ((j = i >= cr2_slice[0]))
+		 i  = cr2_slice[0];
+	jidx -= i * (cr2_slice[1]*jh.high);
+	row = jidx / cr2_slice[1+j];
+	col = jidx % cr2_slice[1+j] + i*cr2_slice[1];
+      }
+      if (raw_width == 3984 && (col -= 2) < 0)
+	col += (row--,raw_width);
+#ifdef LIBRAW_LIBRARY_BUILD
+      ushort *dfp = get_masked_pointer(row,col);
+      if(dfp) *dfp = val;
+#endif
+      if ((unsigned) (row-top_margin) < height) {
+	if ((unsigned) (col-left_margin) < width) {
+#ifdef LIBRAW_LIBRARY_BUILD
+            ushort color = FC(row-top_margin,col-left_margin);
+            if(channel_maximum[color] < val) channel_maximum[color] = val;
+#endif
+	  BAYER(row-top_margin,col-left_margin) = val;
+	  if (min > val) min = val;
+	} else if (col > 1 && (unsigned) (col-left_margin+2) > width+3)
+	  dark[(col-left_margin) & 1] += (nblack++,val);
+      }
+      if (++col >= raw_width)
+	col = (row++,0);
+    }
+  }
+  ljpeg_end (&jh);
+  canon_black (dark, nblack);
+  if (!strcasecmp(make,"KODAK"))
+    black = min;
+}
+
+void CLASS canon_sraw_load_raw()
+{
+  struct jhead jh;
+  short *rp=0, (*ip)[4];
+  int jwide, slice, scol, ecol, row, col, jrow=0, jcol=0, pix[3], c;
+  int v[3]={0,0,0}, ver, hue;
+  char *cp;
+
+  if (!ljpeg_start (&jh, 0)) return;
+  jwide = (jh.wide >>= 1) * jh.clrs;
+
+  for (ecol=slice=0; slice <= cr2_slice[0]; slice++) {
+    scol = ecol;
+    ecol += cr2_slice[1] * 2 / jh.clrs;
+    if (!cr2_slice[0] || ecol > raw_width-1) ecol = raw_width & -2;
+    for (row=0; row < height; row += (jh.clrs >> 1) - 1) {
+      ip = (short (*)[4]) image + row*width;
+      for (col=scol; col < ecol; col+=2, jcol+=jh.clrs) {
+	if ((jcol %= jwide) == 0)
+	  rp = (short *) ljpeg_row (jrow++, &jh);
+	if (col >= width) continue;
+	FORC (jh.clrs-2)
+	  ip[col + (c >> 1)*width + (c & 1)][0] = rp[jcol+c];
+	ip[col][1] = rp[jcol+jh.clrs-2] - 16384;
+	ip[col][2] = rp[jcol+jh.clrs-1] - 16384;
+      }
+    }
+  }
+  for (cp=model2; *cp && !isdigit(*cp); cp++);
+  sscanf (cp, "%d.%d.%d", v, v+1, v+2);
+  ver = (v[0]*1000 + v[1])*1000 + v[2];
+  hue = (jh.sraw+1) << 2;
+  if (unique_id == 0x80000218 && ver > 1000006 && ver < 3000000)
+    hue = jh.sraw << 1;
+  ip = (short (*)[4]) image;
+  rp = ip[0];
+  for (row=0; row < height; row++, ip+=width) {
+    if (row & (jh.sraw >> 1))
+      for (col=0; col < width; col+=2)
+	for (c=1; c < 3; c++)
+	  if (row == height-1)
+	       ip[col][c] =  ip[col-width][c];
+	  else ip[col][c] = (ip[col-width][c] + ip[col+width][c] + 1) >> 1;
+    for (col=1; col < width; col+=2)
+      for (c=1; c < 3; c++)
+	if (col == width-1)
+	     ip[col][c] =  ip[col-1][c];
+	else ip[col][c] = (ip[col-1][c] + ip[col+1][c] + 1) >> 1;
+  }
+  for ( ; rp < ip[0]; rp+=4) {
+    if (unique_id < 0x80000218) {
+      pix[0] = rp[0] + rp[2] - 512;
+      pix[2] = rp[0] + rp[1] - 512;
+      pix[1] = rp[0] + ((-778*rp[1] - (rp[2] << 11)) >> 12) - 512;
+    } else {
+      rp[1] = (rp[1] << 2) + hue;
+      rp[2] = (rp[2] << 2) + hue;
+      pix[0] = rp[0] + ((  200*rp[1] + 22929*rp[2]) >> 14);
+      pix[1] = rp[0] + ((-5640*rp[1] - 11751*rp[2]) >> 14);
+      pix[2] = rp[0] + ((29040*rp[1] -   101*rp[2]) >> 14);
+    }
+    FORC3 { 
+#ifdef LIBRAW_LIBRARY_BUILD
+        ushort val = CLIP(pix[c] * sraw_mul[c] >> 10);
+        rp[c] = val;
+        if(channel_maximum[c] < val) channel_maximum[c] = val;
+#else
+        rp[c] = CLIP(pix[c] * sraw_mul[c] >> 10);
+#endif
+    }
+  }
+  ljpeg_end (&jh);
+  maximum = 0x3fff;
+}
+
+void CLASS adobe_copy_pixel (int row, int col, ushort **rp)
+{
+  unsigned r, c;
+
+  r = row -= top_margin;
+  c = col -= left_margin;
+  if (is_raw == 2 && shot_select) (*rp)++;
+  if (filters) {
+#ifndef LIBRAW_LIBRARY_BUILD
+    if (fuji_width) {
+      r = row + fuji_width - 1 - (col >> 1);
+      c = row + ((col+1) >> 1);
+    }
+#endif
+#ifdef LIBRAW_LIBRARY_BUILD
+    ushort val = **rp;
+    if(!(filtering_mode & LIBRAW_FILTERING_NORAWCURVE))
+        val = **rp < 0x1000 ? curve[**rp] : **rp;
+    if (r < height && c < width)
+        {
+            ushort color = COLOR(r,c);
+            image[((row) >> shrink)*iwidth + ((col) >> shrink)][color] = val;
+            if(channel_maximum[color] < val) channel_maximum[color] = val;
+        }
+    else
+        {
+            ushort *dfp = get_masked_pointer(row+top_margin,col+left_margin);
+            if(dfp) *dfp = val;
+        }
+#else
+    if (r < height && c < width)
+      BAYER(r,c) = **rp < 0x1000 ? curve[**rp] : **rp;
+#endif
+    *rp += is_raw;
+  } else {
+    if (r < height && c < width)
+      FORC(tiff_samples)
+	image[row*width+col][c] = (*rp)[c] < 0x1000 ? curve[(*rp)[c]]:(*rp)[c];
+    *rp += tiff_samples;
+  }
+  if (is_raw == 2 && shot_select) (*rp)--;
+}
+
+void CLASS adobe_dng_load_raw_lj()
+{
+  unsigned save, trow=0, tcol=0, jwide, jrow, jcol, row, col;
+  struct jhead jh;
+  ushort *rp;
+
+  while (trow < raw_height) {
+    save = ftell(ifp);
+    if (tile_length < INT_MAX)
+      fseek (ifp, get4(), SEEK_SET);
+    if (!ljpeg_start (&jh, 0)) break;
+    jwide = jh.wide;
+    if (filters) jwide *= jh.clrs;
+    jwide /= is_raw;
+    for (row=col=jrow=0; jrow < jh.high; jrow++) {
+      rp = ljpeg_row (jrow, &jh);
+      for (jcol=0; jcol < jwide; jcol++) {
+	adobe_copy_pixel (trow+row, tcol+col, &rp);
+	if (++col >= tile_width || col >= raw_width)
+	  row += 1 + (col = 0);
+      }
+    }
+    fseek (ifp, save+4, SEEK_SET);
+    if ((tcol += tile_width) >= raw_width)
+      trow += tile_length + (tcol = 0);
+    ljpeg_end (&jh);
+  }
+}
+
+void CLASS adobe_dng_load_raw_nc()
+{
+  ushort *pixel, *rp;
+  int row, col;
+
+  pixel = (ushort *) calloc (raw_width * tiff_samples, sizeof *pixel);
+  merror (pixel, "adobe_dng_load_raw_nc()");
+  for (row=0; row < raw_height; row++) {
+    if (tiff_bps == 16)
+      read_shorts (pixel, raw_width * tiff_samples);
+    else {
+      getbits(-1);
+      for (col=0; col < raw_width * tiff_samples; col++)
+	pixel[col] = getbits(tiff_bps);
+    }
+    for (rp=pixel, col=0; col < raw_width; col++)
+      adobe_copy_pixel (row, col, &rp);
+  }
+  free (pixel);
+}
+
+void CLASS pentax_load_raw()
+{
+  ushort bit[2][13], huff[4097];
+  int row, col, diff, c, i;
+  ushort vpred[2][2] = {{0,0},{0,0}}, hpred[2];
+
+  fseek (ifp, meta_offset, SEEK_SET);
+  FORC(13) bit[0][c] = get2();
+  FORC(13) bit[1][c] = fgetc(ifp);
+  FORC(13)
+    for (i=bit[0][c]; i <= ((bit[0][c]+(4096 >> bit[1][c])-1) & 4095); )
+      huff[++i] = bit[1][c] << 8 | c;
+  huff[0] = 12;
+  fseek (ifp, data_offset, SEEK_SET);
+  getbits(-1);
+  for (row=0; row < raw_height; row++)
+      {
+#ifndef LIBRAW_LIBRARY_BUILD
+          if(row >= height) break;
+#endif
+    for (col=0; col < raw_width; col++) {
+      diff = ljpeg_diff (huff);
+      if (col < 2) hpred[col] = vpred[row & 1][col] += diff;
+      else	   hpred[col & 1] += diff;
+      if ((unsigned) (row-top_margin) < height && col < width)
+          {
+#ifdef LIBRAW_LIBRARY_BUILD
+              ushort color = FC(row-top_margin,col);
+              if(channel_maximum[color] < hpred[col & 1])  channel_maximum[color] = hpred[col & 1];
+#endif
+              BAYER(row-top_margin,col) = hpred[col & 1];
+          }
+#ifdef LIBRAW_LIBRARY_BUILD
+      else
+        {
+          ushort *dfp = get_masked_pointer(row,col);
+          if(dfp) *dfp = hpred[col & 1];
+        }
+      
+      if (col < width && row < height)
+#endif
+        if (hpred[col & 1] >> 12) derror();
+    }
+      }
+}
+
+void CLASS nikon_compressed_load_raw()
+{
+  static const uchar nikon_tree[][32] = {
+    { 0,1,5,1,1,1,1,1,1,2,0,0,0,0,0,0,	/* 12-bit lossy */
+      5,4,3,6,2,7,1,0,8,9,11,10,12 },
+    { 0,1,5,1,1,1,1,1,1,2,0,0,0,0,0,0,	/* 12-bit lossy after split */
+      0x39,0x5a,0x38,0x27,0x16,5,4,3,2,1,0,11,12,12 },
+    { 0,1,4,2,3,1,2,0,0,0,0,0,0,0,0,0,  /* 12-bit lossless */
+      5,4,6,3,7,2,8,1,9,0,10,11,12 },
+    { 0,1,4,3,1,1,1,1,1,2,0,0,0,0,0,0,	/* 14-bit lossy */
+      5,6,4,7,8,3,9,2,1,0,10,11,12,13,14 },
+    { 0,1,5,1,1,1,1,1,1,1,2,0,0,0,0,0,	/* 14-bit lossy after split */
+      8,0x5c,0x4b,0x3a,0x29,7,6,5,4,3,2,1,0,13,14 },
+    { 0,1,4,2,2,3,1,2,0,0,0,0,0,0,0,0,	/* 14-bit lossless */
+      7,6,8,5,9,4,10,3,11,12,2,0,1,13,14 } };
+  ushort *huff, ver0, ver1, vpred[2][2], hpred[2], csize;
+  int i, min, max, step=0, tree=0, split=0, row, col, len, shl, diff;
+
+  fseek (ifp, meta_offset, SEEK_SET);
+  ver0 = fgetc(ifp);
+  ver1 = fgetc(ifp);
+  if (ver0 == 0x49 || ver1 == 0x58)
+    fseek (ifp, 2110, SEEK_CUR);
+  if (ver0 == 0x46) tree = 2;
+  if (tiff_bps == 14) tree += 3;
+  read_shorts (vpred[0], 4);
+  max = 1 << tiff_bps & 0x7fff;
+  if ((csize = get2()) > 1)
+    step = max / (csize-1);
+  if (ver0 == 0x44 && ver1 == 0x20 && step > 0) {
+    for (i=0; i < csize; i++)
+      curve[i*step] = get2();
+    for (i=0; i < max; i++)
+      curve[i] = ( curve[i-i%step]*(step-i%step) +
+		   curve[i-i%step+step]*(i%step) ) / step;
+#ifdef LIBRAW_LIBRARY_BUILD
+    color_flags.curve_state = LIBRAW_COLORSTATE_LOADED;
+#endif
+    fseek (ifp, meta_offset+562, SEEK_SET);
+    split = get2();
+  } else if (ver0 != 0x46 && csize <= 0x4001)
+      {
+    read_shorts (curve, max=csize);
+#ifdef LIBRAW_LIBRARY_BUILD
+    color_flags.curve_state = LIBRAW_COLORSTATE_LOADED;
+#endif
+      }
+  while (curve[max-2] == curve[max-1]) max--;
+  huff = make_decoder (nikon_tree[tree]);
+  fseek (ifp, data_offset, SEEK_SET);
+  getbits(-1);
+  for (min=row=0; row < height; row++) {
+    if (split && row == split) {
+      free (huff);
+      huff = make_decoder (nikon_tree[tree+1]);
+      max += (min = 16) << 1;
+    }
+    for (col=0; col < raw_width; col++) {
+      i = gethuff(huff);
+      len = i & 15;
+      shl = i >> 4;
+      diff = ((getbits(len-shl) << 1) + 1) << shl >> 1;
+      if ((diff & (1 << (len-1))) == 0)
+	diff -= (1 << len) - !shl;
+      if (col < 2) hpred[col] = vpred[row & 1][col] += diff;
+      else	   hpred[col & 1] += diff;
+      if ((ushort)(hpred[col & 1] + min) >= max) derror();
+#ifndef LIBRAW_LIBRARY_BUILD
+      if ((unsigned) (col-left_margin) < width)
+	BAYER(row,col-left_margin) =  curve[LIM((short)hpred[col & 1],0,0x3fff)];
+#else
+      ushort xval = hpred[col & 1];
+      if(!(filtering_mode & LIBRAW_FILTERING_NORAWCURVE))
+          xval = curve[LIM((short)xval,0,0x3fff)];
+      if ((unsigned) (col-left_margin) < width)
+          {
+              ushort color = FC(row,col-left_margin);
+              if(channel_maximum[color] < xval ) channel_maximum[color] = xval;
+              BAYER(row,col-left_margin) =  xval;
+          }
+      else
+        {
+          ushort *dfp = get_masked_pointer(row,col);
+          if(dfp) *dfp = xval;
+        }
+#endif
+
+    }
+  }
+  free (huff);
+}
+
+/*
+   Figure out if a NEF file is compressed.  These fancy heuristics
+   are only needed for the D100, thanks to a bug in some cameras
+   that tags all images as "compressed".
+ */
+int CLASS nikon_is_compressed()
+{
+  uchar test[256];
+  int i;
+
+  fseek (ifp, data_offset, SEEK_SET);
+  fread (test, 1, 256, ifp);
+  for (i=15; i < 256; i+=16)
+    if (test[i]) return 1;
+  return 0;
+}
+
+/*
+   Returns 1 for a Coolpix 995, 0 for anything else.
+ */
+int CLASS nikon_e995()
+{
+  int i, histo[256];
+  const uchar often[] = { 0x00, 0x55, 0xaa, 0xff };
+
+  memset (histo, 0, sizeof histo);
+  fseek (ifp, -2000, SEEK_END);
+  for (i=0; i < 2000; i++)
+    histo[fgetc(ifp)]++;
+  for (i=0; i < 4; i++)
+    if (histo[often[i]] < 200)
+      return 0;
+  return 1;
+}
+
+/*
+   Returns 1 for a Coolpix 2100, 0 for anything else.
+ */
+int CLASS nikon_e2100()
+{
+  uchar t[12];
+  int i;
+
+  fseek (ifp, 0, SEEK_SET);
+  for (i=0; i < 1024; i++) {
+    fread (t, 1, 12, ifp);
+    if (((t[2] & t[4] & t[7] & t[9]) >> 4
+	& t[1] & t[6] & t[8] & t[11] & 3) != 3)
+      return 0;
+  }
+  return 1;
+}
+
+void CLASS nikon_3700()
+{
+  int bits, i;
+  uchar dp[24];
+  static const struct {
+    int bits;
+    char t_make[12], t_model[15];
+  } table[] = {
+    { 0x00, "PENTAX",  "Optio 33WR" },
+    { 0x03, "NIKON",   "E3200" },
+    { 0x32, "NIKON",   "E3700" },
+    { 0x33, "OLYMPUS", "C740UZ" } };
+
+  fseek (ifp, 3072, SEEK_SET);
+  fread (dp, 1, 24, ifp);
+  bits = (dp[8] & 3) << 4 | (dp[20] & 3);
+  for (i=0; i < sizeof table / sizeof *table; i++)
+    if (bits == table[i].bits) {
+      strcpy (make,  table[i].t_make );
+      strcpy (model, table[i].t_model);
+    }
+}
+
+/*
+   Separates a Minolta DiMAGE Z2 from a Nikon E4300.
+ */
+int CLASS minolta_z2()
+{
+  int i, nz;
+  char tail[424];
+
+  fseek (ifp, -sizeof tail, SEEK_END);
+  fread (tail, 1, sizeof tail, ifp);
+  for (nz=i=0; i < sizeof tail; i++)
+    if (tail[i]) nz++;
+  return nz > 20;
+}
+
+/*
+   The Fuji Super CCD is just a Bayer grid rotated 45 degrees.
+ */
+void CLASS fuji_load_raw()
+{
+  ushort *pixel;
+#ifndef LIBRAW_LIBRARY_BUILD
+  int wide, row, col, r, c;
+
+  fseek (ifp, (top_margin*raw_width + left_margin) * 2, SEEK_CUR);
+  wide = fuji_width << !fuji_layout;
+  pixel = (ushort *) calloc (wide, sizeof *pixel);
+  merror (pixel, "fuji_load_raw()");
+  for (row=0; row < raw_height; row++) {
+    read_shorts (pixel, wide);
+    fseek (ifp, 2*(raw_width - wide), SEEK_CUR);
+    for (col=0; col < wide; col++) {
+      if (fuji_layout) {
+	r = fuji_width - 1 - col + (row >> 1);
+	c = col + ((row+1) >> 1);
+      } else {
+	r = fuji_width - 1 + row - (col >> 1);
+	c = row + ((col+1) >> 1);
+      }
+      BAYER(r,c) = pixel[col];
+    }
+  }
+  free (pixel);
+#else
+  int row,col;
+  int wide, r, c;
+  pixel = (ushort *) calloc (raw_width, sizeof *pixel);
+  merror (pixel, "fuji_load_raw()");
+  for (row=0; row < raw_height; row++) {
+    read_shorts (pixel, raw_width);
+    for (col=0; col < raw_width; col++) {
+        if(col >= left_margin && col < width+left_margin
+           && row >= top_margin && row < height+top_margin)
+            {
+                int rrow = row-top_margin;
+                int ccol = col-left_margin;
+                ushort color = FCF(rrow,ccol);
+                image[((rrow) >> shrink)*iwidth + ((ccol) >> shrink)][color] = pixel[col];
+                if(channel_maximum[color] < pixel[col] ) channel_maximum[color] = pixel[col];
+            }
+        else
+            {
+                ushort *dfp = get_masked_pointer(row,col);
+                if(dfp) *dfp = pixel[col];
+            }
+    }
+  }
+  free (pixel);
+#endif
+}
+#line 1517 "dcraw/dcraw.c"
+void CLASS ppm_thumb()
+{
+  char *thumb;
+  thumb_length = thumb_width*thumb_height*3;
+  thumb = (char *) malloc (thumb_length);
+  merror (thumb, "ppm_thumb()");
+  fprintf (ofp, "P6\n%d %d\n255\n", thumb_width, thumb_height);
+  fread  (thumb, 1, thumb_length, ifp);
+  fwrite (thumb, 1, thumb_length, ofp);
+  free (thumb);
+}
+
+void CLASS layer_thumb()
+{
+  int i, c;
+  char *thumb, map[][4] = { "012","102" };
+
+  colors = thumb_misc >> 5 & 7;
+  thumb_length = thumb_width*thumb_height;
+  thumb = (char *) calloc (colors, thumb_length);
+  merror (thumb, "layer_thumb()");
+  fprintf (ofp, "P%d\n%d %d\n255\n",
+	5 + (colors >> 1), thumb_width, thumb_height);
+  fread (thumb, thumb_length, colors, ifp);
+  for (i=0; i < thumb_length; i++)
+    FORCC putc (thumb[i+thumb_length*(map[thumb_misc >> 8][c]-'0')], ofp);
+  free (thumb);
+}
+
+void CLASS rollei_thumb()
+{
+  unsigned i;
+  ushort *thumb;
+
+  thumb_length = thumb_width * thumb_height;
+  thumb = (ushort *) calloc (thumb_length, 2);
+  merror (thumb, "rollei_thumb()");
+  fprintf (ofp, "P6\n%d %d\n255\n", thumb_width, thumb_height);
+  read_shorts (thumb, thumb_length);
+  for (i=0; i < thumb_length; i++) {
+    putc (thumb[i] << 3, ofp);
+    putc (thumb[i] >> 5  << 2, ofp);
+    putc (thumb[i] >> 11 << 3, ofp);
+  }
+  free (thumb);
+}
+
+void CLASS rollei_load_raw()
+{
+  uchar pixel[10];
+  unsigned iten=0, isix, i, buffer=0, row, col, todo[16];
+
+  isix = raw_width * raw_height * 5 / 8;
+  while (fread (pixel, 1, 10, ifp) == 10) {
+    for (i=0; i < 10; i+=2) {
+      todo[i]   = iten++;
+      todo[i+1] = pixel[i] << 8 | pixel[i+1];
+      buffer    = pixel[i] >> 2 | buffer << 6;
+    }
+    for (   ; i < 16; i+=2) {
+      todo[i]   = isix++;
+      todo[i+1] = buffer >> (14-i)*5;
+    }
+    for (i=0; i < 16; i+=2) {
+      row = todo[i] / raw_width - top_margin;
+      col = todo[i] % raw_width - left_margin;
+      if (row < height && col < width)
+          {
+#ifdef LIBRAW_LIBRARY_BUILD
+              ushort color = FC(row,col);
+              if(channel_maximum[color] < (todo[i+1] & 0x3ff))
+                  channel_maximum[color] = (todo[i+1] & 0x3ff);
+#endif
+              BAYER(row,col) = (todo[i+1] & 0x3ff);
+          }
+#ifdef LIBRAW_LIBRARY_BUILD
+      else
+          {
+              ushort *dfp = get_masked_pointer(todo[i] / raw_width,todo[i] % raw_width);
+              if(dfp) *dfp = (todo[i+1] & 0x3ff);
+          }
+#endif
+    }
+  }
+  maximum = 0x3ff;
+}
+
+int CLASS bayer (unsigned row, unsigned col)
+{
+  return (row < height && col < width) ? BAYER(row,col) : 0;
+}
+
+void CLASS phase_one_flat_field (int is_float, int nc)
+{
+  ushort head[8];
+  unsigned wide, y, x, c, rend, cend, row, col;
+  float *mrow, num, mult[4];
+
+  read_shorts (head, 8);
+  wide = head[2] / head[4];
+  mrow = (float *) calloc (nc*wide, sizeof *mrow);
+  merror (mrow, "phase_one_flat_field()");
+  for (y=0; y < head[3] / head[5]; y++) {
+    for (x=0; x < wide; x++)
+      for (c=0; c < nc; c+=2) {
+	num = is_float ? getreal(11) : get2()/32768.0;
+	if (y==0) mrow[c*wide+x] = num;
+	else mrow[(c+1)*wide+x] = (num - mrow[c*wide+x]) / head[5];
+      }
+    if (y==0) continue;
+    rend = head[1]-top_margin + y*head[5];
+    for (row = rend-head[5]; row < height && row < rend; row++) {
+      for (x=1; x < wide; x++) {
+	for (c=0; c < nc; c+=2) {
+	  mult[c] = mrow[c*wide+x-1];
+	  mult[c+1] = (mrow[c*wide+x] - mult[c]) / head[4];
+	}
+	cend = head[0]-left_margin + x*head[4];
+	for (col = cend-head[4]; col < width && col < cend; col++) {
+	  c = nc > 2 ? FC(row,col) : 0;
+	  if (!(c & 1)) {
+	    c = BAYER(row,col) * mult[c];
+	    BAYER(row,col) = LIM(c,0,65535);
+	  }
+	  for (c=0; c < nc; c+=2)
+	    mult[c] += mult[c+1];
+	}
+      }
+      for (x=0; x < wide; x++)
+	for (c=0; c < nc; c+=2)
+	  mrow[c*wide+x] += mrow[(c+1)*wide+x];
+    }
+  }
+  free (mrow);
+}
+
+void CLASS phase_one_correct()
+{
+  unsigned entries, tag, data, save, col, row, type;
+  int len, i, j, k, cip, val[4], dev[4], sum, max;
+  int head[9], diff, mindiff=INT_MAX, off_412=0;
+  static const signed char dir[12][2] =
+    { {-1,-1}, {-1,1}, {1,-1}, {1,1}, {-2,0}, {0,-2}, {0,2}, {2,0},
+      {-2,-2}, {-2,2}, {2,-2}, {2,2} };
+  float poly[8], num, cfrac, frac, mult[2], *yval[2];
+  ushort *xval[2];
+
+  if (half_size || !meta_length) return;
+#ifdef DCRAW_VERBOSE
+  if (verbose) fprintf (stderr,_("Phase One correction...\n"));
+#endif
+  fseek (ifp, meta_offset, SEEK_SET);
+  order = get2();
+  fseek (ifp, 6, SEEK_CUR);
+  fseek (ifp, meta_offset+get4(), SEEK_SET);
+  entries = get4();  get4();
+  while (entries--) {
+    tag  = get4();
+    len  = get4();
+    data = get4();
+    save = ftell(ifp);
+    fseek (ifp, meta_offset+data, SEEK_SET);
+    if (tag == 0x419) {				/* Polynomial curve */
+      for (get4(), i=0; i < 8; i++)
+	poly[i] = getreal(11);
+      poly[3] += (ph1.tag_210 - poly[7]) * poly[6] + 1;
+      for (i=0; i < 0x10000; i++) {
+	num = (poly[5]*i + poly[3])*i + poly[1];
+	curve[i] = LIM(num,0,65535);
+      } goto apply;				/* apply to right half */
+    } else if (tag == 0x41a) {			/* Polynomial curve */
+      for (i=0; i < 4; i++)
+	poly[i] = getreal(11);
+      for (i=0; i < 0x10000; i++) {
+	for (num=0, j=4; j--; )
+	  num = num * i + poly[j];
+	curve[i] = LIM(num+i,0,65535);
+      } apply:					/* apply to whole image */
+      for (row=0; row < height; row++)
+	for (col = (tag & 1)*ph1.split_col; col < width; col++)
+	  BAYER(row,col) = curve[BAYER(row,col)];
+    } else if (tag == 0x400) {			/* Sensor defects */
+      while ((len -= 8) >= 0) {
+	col  = get2() - left_margin;
+	row  = get2() - top_margin;
+	type = get2(); get2();
+	if (col >= width) continue;
+	if (type == 131)			/* Bad column */
+	  for (row=0; row < height; row++)
+	    if (FC(row,col) == 1) {
+	      for (sum=i=0; i < 4; i++)
+		sum += val[i] = bayer (row+dir[i][0], col+dir[i][1]);
+	      for (max=i=0; i < 4; i++) {
+		dev[i] = abs((val[i] << 2) - sum);
+		if (dev[max] < dev[i]) max = i;
+	      }
+	      BAYER(row,col) = (sum - val[max])/3.0 + 0.5;
+	    } else {
+	      for (sum=0, i=8; i < 12; i++)
+		sum += bayer (row+dir[i][0], col+dir[i][1]);
+	      BAYER(row,col) = 0.5 + sum * 0.0732233 +
+		(bayer(row,col-2) + bayer(row,col+2)) * 0.3535534;
+	    }
+	else if (type == 129) {			/* Bad pixel */
+	  if (row >= height) continue;
+	  j = (FC(row,col) != 1) * 4;
+	  for (sum=0, i=j; i < j+8; i++)
+	    sum += bayer (row+dir[i][0], col+dir[i][1]);
+	  BAYER(row,col) = (sum + 4) >> 3;
+	}
+      }
+    } else if (tag == 0x401) {			/* All-color flat fields */
+      phase_one_flat_field (1, 2);
+    } else if (tag == 0x416 || tag == 0x410) {
+      phase_one_flat_field (0, 2);
+    } else if (tag == 0x40b) {			/* Red+blue flat field */
+      phase_one_flat_field (0, 4);
+    } else if (tag == 0x412) {
+      fseek (ifp, 36, SEEK_CUR);
+      diff = abs (get2() - ph1.tag_21a);
+      if (mindiff > diff) {
+	mindiff = diff;
+	off_412 = ftell(ifp) - 38;
+      }
+    }
+    fseek (ifp, save, SEEK_SET);
+  }
+  if (off_412) {
+    fseek (ifp, off_412, SEEK_SET);
+    for (i=0; i < 9; i++) head[i] = get4() & 0x7fff;
+    yval[0] = (float *) calloc (head[1]*head[3] + head[2]*head[4], 6);
+    merror (yval[0], "phase_one_correct()");
+    yval[1] = (float  *) (yval[0] + head[1]*head[3]);
+    xval[0] = (ushort *) (yval[1] + head[2]*head[4]);
+    xval[1] = (ushort *) (xval[0] + head[1]*head[3]);
+    get2();
+    for (i=0; i < 2; i++)
+      for (j=0; j < head[i+1]*head[i+3]; j++)
+	yval[i][j] = getreal(11);
+    for (i=0; i < 2; i++)
+      for (j=0; j < head[i+1]*head[i+3]; j++)
+	xval[i][j] = get2();
+    for (row=0; row < height; row++)
+      for (col=0; col < width; col++) {
+	cfrac = (float) col * head[3] / raw_width;
+	cfrac -= cip = cfrac;
+	num = BAYER(row,col) * 0.5;
+	for (i=cip; i < cip+2; i++) {
+	  for (k=j=0; j < head[1]; j++)
+	    if (num < xval[0][k = head[1]*i+j]) break;
+	  frac = (j == 0 || j == head[1]) ? 0 :
+		(xval[0][k] - num) / (xval[0][k] - xval[0][k-1]);
+	  mult[i-cip] = yval[0][k-1] * frac + yval[0][k] * (1-frac);
+	}
+	i = ((mult[0] * (1-cfrac) + mult[1] * cfrac)
+		* (row + top_margin) + num) * 2;
+	BAYER(row,col) = LIM(i,0,65535);
+      }
+    free (yval[0]);
+  }
+}
+
+void CLASS phase_one_load_raw()
+{
+  int row, col, a, b;
+  ushort *pixel, akey, bkey, mask;
+
+  fseek (ifp, ph1.key_off, SEEK_SET);
+  akey = get2();
+  bkey = get2();
+  mask = ph1.format == 1 ? 0x5555:0x1354;
+#ifndef LIBRAW_LIBRARY_BUILD
+  fseek (ifp, data_offset + top_margin*raw_width*2, SEEK_SET);
+  pixel = (ushort *) calloc (raw_width, sizeof *pixel);
+  merror (pixel, "phase_one_load_raw()");
+  for (row=0; row < height; row++) {
+    read_shorts (pixel, raw_width);
+    for (col=0; col < raw_width; col+=2) {
+      a = pixel[col+0] ^ akey;
+      b = pixel[col+1] ^ bkey;
+      pixel[col+0] = (a & mask) | (b & ~mask);
+      pixel[col+1] = (b & mask) | (a & ~mask);
+    }
+    for (col=0; col < width; col++)
+      BAYER(row,col) = pixel[col+left_margin];
+  }
+  free (pixel);
+#else
+  fseek (ifp, data_offset, SEEK_SET);
+  pixel = (ushort *) calloc (raw_width, sizeof *pixel);
+  merror (pixel, "phase_one_load_raw()");
+  for (row=0; row < raw_height; row++) {
+    read_shorts (pixel, raw_width);
+    for (col=0; col < raw_width; col+=2) {
+      a = pixel[col+0] ^ akey;
+      b = pixel[col+1] ^ bkey;
+      pixel[col+0] = (a & mask) | (b & ~mask);
+      pixel[col+1] = (b & mask) | (a & ~mask);
+    }
+    for (col=0; col < raw_width; col++)
+        {
+            ushort *dfp = get_masked_pointer(row,col);
+            if(dfp)
+                *dfp = pixel[col];
+            else
+                {
+                    ushort color = FC(row-top_margin,col-left_margin);
+                    if(channel_maximum[color] < pixel[col]) channel_maximum[color] = pixel[col];
+                    BAYER(row-top_margin,col-left_margin) = pixel[col];
+                }
+        }
+  }
+  free (pixel);
+  if(!( filtering_mode & LIBRAW_FILTERING_NORAWCURVE) )
+#endif
+  phase_one_correct();
+}
+
+unsigned CLASS ph1_bithuff (int nbits, ushort *huff)
+{
+#ifndef LIBRAW_NOTHREADS
+#define bitbuf tls->ph1_bits.bitbuf
+#define vbits  tls->ph1_bits.vbits    
+#else
+  static UINT64 bitbuf=0;
+  static int vbits=0;
+#endif
+  unsigned c;
+
+  if (nbits == -1)
+    return bitbuf = vbits = 0;
+  if (nbits == 0) return 0;
+  if (vbits < nbits) {
+    bitbuf = bitbuf << 32 | get4();
+    vbits += 32;
+  }
+  c = bitbuf << (64-vbits) >> (64-nbits);
+  if (huff) {
+    vbits -= huff[c] >> 8;
+    return (uchar) huff[c];
+  }
+  vbits -= nbits;
+  return c;
+#ifndef LIBRAW_NOTHREADS
+#undef bitbuf
+#undef vbits
+#endif
+}
+#define ph1_bits(n) ph1_bithuff(n,0)
+#define ph1_huff(h) ph1_bithuff(*h,h+1)
+
+void CLASS phase_one_load_raw_c()
+{
+  static const int length[] = { 8,7,6,9,11,10,5,12,14,13 };
+  int *offset, len[2], pred[2], row, col, i, j;
+  ushort *pixel;
+  short (*t_black)[2];
+
+  pixel = (ushort *) calloc (raw_width + raw_height*4, 2);
+  merror (pixel, "phase_one_load_raw_c()");
+  offset = (int *) (pixel + raw_width);
+  fseek (ifp, strip_offset, SEEK_SET);
+  for (row=0; row < raw_height; row++)
+    offset[row] = get4();
+  t_black = (short (*)[2]) offset + raw_height;
+  fseek (ifp, ph1.black_off, SEEK_SET);
+  if (ph1.black_off)
+      {
+    read_shorts ((ushort *) t_black[0], raw_height*2);
+#ifdef LIBRAW_LIBRARY_BUILD
+    imgdata.masked_pixels.ph1_black = (ushort (*)[2])calloc(raw_height*2,sizeof(ushort));
+    merror (imgdata.masked_pixels.ph1_black, "phase_one_load_raw_c()");
+    memmove(imgdata.masked_pixels.ph1_black,(ushort *) t_black[0],raw_height*2*sizeof(ushort));
+#endif
+      }
+  for (i=0; i < 256; i++)
+    curve[i] = i*i / 3.969 + 0.5;
+#ifdef LIBRAW_LIBRARY_BUILD
+  color_flags.curve_state = LIBRAW_COLORSTATE_CALCULATED;
+#endif
+  for (row=0; row < raw_height; row++) {
+    fseek (ifp, data_offset + offset[row], SEEK_SET);
+    ph1_bits(-1);
+    pred[0] = pred[1] = 0;
+    for (col=0; col < raw_width; col++) {
+      if (col >= (raw_width & -8))
+	len[0] = len[1] = 14;
+      else if ((col & 7) == 0)
+	for (i=0; i < 2; i++) {
+	  for (j=0; j < 5 && !ph1_bits(1); j++);
+	  if (j--) len[i] = length[j*2 + ph1_bits(1)];
+	}
+      if ((i = len[col & 1]) == 14)
+	pixel[col] = pred[col & 1] = ph1_bits(16);
+      else
+	pixel[col] = pred[col & 1] += ph1_bits(i) + 1 - (1 << (i - 1));
+      if (pred[col & 1] >> 16) derror();
+#ifdef LIBRAW_LIBRARY_BUILD
+  if(!( filtering_mode & LIBRAW_FILTERING_NORAWCURVE) )
+#endif
+      if (ph1.format == 5 && pixel[col] < 256)
+	pixel[col] = curve[pixel[col]];
+    }
+    if ((unsigned) (row-top_margin) < height)
+#ifndef LIBRAW_LIBRARY_BUILD
+      for (col=0; col < width; col++) {
+	i = (pixel[col+left_margin] << 2)
+		- ph1.t_black + t_black[row][col >= ph1.split_col];
+	if (i > 0) BAYER(row-top_margin,col) = i;
+      }
+#else
+    {
+      for (col=0; col < raw_width; col++) {
+          if( filtering_mode & LIBRAW_FILTERING_NOBLACKS)  
+              i = (pixel[col] << 2);
+          else
+              i = (pixel[col] << 2)
+                  - ph1.t_black + t_black[row][(col /* - left_margin */) >= ph1.split_col]; // changed to fix Coffin's bug!
+          if(col >= left_margin && col < width+left_margin)
+              {
+                  if (i > 0){
+                      ushort color = FC(row-top_margin,col-left_margin);
+                      BAYER(row-top_margin,col-left_margin) = i;
+                      if(channel_maximum[color] < i) channel_maximum[color] = i ;
+                  }
+              }
+          else
+              {
+                  ushort *dfp = get_masked_pointer(row,col);
+                  if(i>0 && dfp) *dfp = i;
+              }
+      }
+    }
+    else
+        {
+            // top-bottom fields
+            for (col=0; col < raw_width; col++) {
+                i = (pixel[col] << 2)
+                    - ph1.t_black + t_black[row][(col+left_margin) >= ph1.split_col];
+                if (i > 0) 
+                    {
+                        ushort *dfp = get_masked_pointer(row,col);
+                        if(dfp) *dfp = i;
+                    }
+            }
+        }
+#endif
+  }
+  free (pixel);
+#ifdef LIBRAW_LIBRARY_BUILD
+  if(!( filtering_mode & LIBRAW_FILTERING_NORAWCURVE) )
+#endif
+  phase_one_correct();
+  maximum = 0xfffc - ph1.t_black;
+}
+
+void CLASS hasselblad_load_raw()
+{
+  struct jhead jh;
+  int row, col, pred[2], len[2], diff, c;
+
+  if (!ljpeg_start (&jh, 0)) return;
+  order = 0x4949;
+  ph1_bits(-1);
+  for (row=-top_margin; row < raw_height-top_margin; row++) {
+    pred[0] = pred[1] = 0x8000;
+    for (col=-left_margin; col < raw_width-left_margin; col+=2) {
+      FORC(2) len[c] = ph1_huff(jh.huff[0]);
+      FORC(2) {
+	diff = ph1_bits(len[c]);
+	if ((diff & (1 << (len[c]-1))) == 0)
+	  diff -= (1 << len[c]) - 1;
+	if (diff == 65535) diff = -32768;
+	pred[c] += diff;
+	if (row >= 0 && row < height && (unsigned)(col+c) < width)
+            {
+#ifdef LIBRAW_LIBRARY_BUILD
+                ushort color = FC(row,col+c);
+                if(channel_maximum[color] < pred[c] ) channel_maximum[color]=pred[c];
+#endif
+	  BAYER(row,col+c) = pred[c];
+            }
+#ifdef LIBRAW_LIBRARY_BUILD
+        else
+            {
+                ushort *dfp = get_masked_pointer(row+top_margin,col+left_margin+c);
+                if(dfp) *dfp = pred[c];
+            }
+#endif
+      }
+    }
+  }
+  ljpeg_end (&jh);
+  maximum = 0xffff;
+}
+
+void CLASS leaf_hdr_load_raw()
+{
+  ushort *pixel;
+  unsigned tile=0, r, c, row, col;
+
+  pixel = (ushort *) calloc (raw_width, sizeof *pixel);
+  merror (pixel, "leaf_hdr_load_raw()");
+  FORC(tiff_samples)
+    for (r=0; r < raw_height; r++) {
+      if (r % tile_length == 0) {
+	fseek (ifp, data_offset + 4*tile++, SEEK_SET);
+	fseek (ifp, get4() + 2*left_margin, SEEK_SET);
+      }
+      if (filters && c != shot_select) continue;
+      read_shorts (pixel, raw_width);
+      if ((row = r - top_margin) >= height) continue;
+      for (col=0; col < width; col++)
+          {
+              if (filters)  BAYER(row,col) = pixel[col];
+              else image[row*width+col][c] = pixel[col];
+#ifdef LIBRAW_LIBRARY_BUILD
+              if(filters)
+                  {
+                      ushort color = FC(row,col);
+                      if(channel_maximum[color] < pixel[col]) channel_maximum[color] = pixel[col];
+                  }
+              else
+                  if(channel_maximum[c] < pixel[col]) channel_maximum[c] = pixel[col];
+#endif              
+          }
+    }
+  free (pixel);
+  if (!filters) {
+    maximum = 0xffff;
+    raw_color = 1;
+  }
+}
+
+#line 2055 "dcraw/dcraw.c"
+void CLASS sinar_4shot_load_raw()
+{
+  ushort *pixel;
+  unsigned shot, row, col, r, c;
+
+  if ((shot = shot_select) || half_size) {
+    if (shot) shot--;
+    if (shot > 3) shot = 3;
+    fseek (ifp, data_offset + shot*4, SEEK_SET);
+    fseek (ifp, get4(), SEEK_SET);
+    unpacked_load_raw();
+    return;
+  }
+  free (image);
+  image = (ushort (*)[4])
+	calloc ((iheight=height)*(iwidth=width), sizeof *image);
+  merror (image, "sinar_4shot_load_raw()");
+  pixel = (ushort *) calloc (raw_width, sizeof *pixel);
+  merror (pixel, "sinar_4shot_load_raw()");
+  for (shot=0; shot < 4; shot++) {
+    fseek (ifp, data_offset + shot*4, SEEK_SET);
+    fseek (ifp, get4(), SEEK_SET);
+    for (row=0; row < raw_height; row++) {
+      read_shorts (pixel, raw_width);
+      if ((r = row-top_margin - (shot >> 1 & 1)) >= height) continue;
+      for (col=0; col < raw_width; col++) {
+	if ((c = col-left_margin - (shot & 1)) >= width) continue;
+        image[r*width+c][FC(row,col)] = pixel[col];
+      }
+    }
+  }
+  free (pixel);
+  shrink = filters = 0;
+}
+
+void CLASS imacon_full_load_raw()
+{
+  int row, col;
+
+  for (row=0; row < height; row++)
+    for (col=0; col < width; col++)
+        {
+      read_shorts (image[row*width+col], 3);
+#ifdef LIBRAW_LIBRARY_BUILD
+      for(int c=0; c<3; c++)
+          if(image[row*width+col][c] > channel_maximum[c]) channel_maximum[c] = image[row*width+col][c];
+#endif
+        }
+}
+
+void CLASS packed_load_raw()
+{
+  int vbits=0, bwide, pwide, rbits, bite, half, irow, row, col, val, i;
+  UINT64 bitbuf=0;
+
+  if (raw_width * 8 >= width * tiff_bps)	/* Is raw_width in bytes? */
+       pwide = (bwide = raw_width) * 8 / tiff_bps;
+  else bwide = (pwide = raw_width) * tiff_bps / 8;
+  rbits = bwide * 8 - pwide * tiff_bps;
+  if (load_flags & 1) bwide = bwide * 16 / 15;
+  fseek (ifp, top_margin*bwide, SEEK_CUR);
+  bite = 8 + (load_flags & 24);
+  half = (height+1) >> 1;
+  for (irow=0; irow < height; irow++) {
+    row = irow;
+    if (load_flags & 2 &&
+	(row = irow % half * 2 + irow / half) == 1 &&
+	load_flags & 4) {
+      if (vbits=0, tiff_compress)
+	fseek (ifp, data_offset - (-half*bwide & -2048), SEEK_SET);
+      else {
+	fseek (ifp, 0, SEEK_END);
+	fseek (ifp, ftell(ifp) >> 3 << 2, SEEK_SET);
+      }
+    }
+    for (col=0; col < pwide; col++) {
+      for (vbits -= tiff_bps; vbits < 0; vbits += bite) {
+	bitbuf <<= bite;
+	for (i=0; i < bite; i+=8)
+	  bitbuf |= (unsigned) (fgetc(ifp) << i);
+      }
+      val = bitbuf << (64-tiff_bps-vbits) >> (64-tiff_bps);
+      i = (col ^ (bite == 24)) - left_margin;
+      if ((unsigned) i < width)
+          {
+#ifdef LIBRAW_LIBRARY_BUILD
+              ushort color = FC(row,i);
+              ushort xval = val << (load_flags >> 6);
+              if( channel_maximum[color] < xval ) channel_maximum[color] = xval;
+              BAYER(row,i) = xval;
+#else
+	BAYER(row,i) = val << (load_flags >> 6);
+#endif
+          }
+      else if (load_flags & 32)
+#ifdef LIBRAW_LIBRARY_BUILD
+          {
+              ushort *dfp = get_masked_pointer(row,col);
+              if(dfp) *dfp = val << (load_flags >> 6);
+#endif
+	black += val;
+#ifdef LIBRAW_LIBRARY_BUILD
+          }
+#endif
+      if (load_flags & 1 && (col % 10) == 9 &&
+	fgetc(ifp) && col < width+left_margin) derror();
+    }
+    vbits -= rbits;
+  }
+  if (load_flags & 32 && pwide > width)
+    black /= (pwide - width) * height;
+}
+
+void CLASS unpacked_load_raw()
+{
+  ushort *pixel;
+  int row, col, bits=0;
+
+  while (1 << ++bits < maximum);
+#ifndef LIBRAW_LIBRARY_BUILD
+  fseek (ifp, (top_margin*raw_width + left_margin) * 2, SEEK_CUR);
+  pixel = (ushort *) calloc (width, sizeof *pixel);
+  merror (pixel, "unpacked_load_raw()");
+  for (row=0; row < height; row++) {
+    read_shorts (pixel, width);
+    fseek (ifp, 2*(raw_width - width), SEEK_CUR);
+    for (col=0; col < width; col++)
+      if ((BAYER2(row,col) = pixel[col]) >> bits) derror();
+  }
+  free (pixel);
+#else
+  // fseek (ifp, (top_margin*raw_width + left_margin) * 2, SEEK_CUR);
+  pixel = (ushort *) calloc (raw_width, sizeof *pixel);
+  merror (pixel, "unpacked_load_raw()");
+  for (row=0; row < raw_height; row++) {
+    read_shorts (pixel, raw_width);
+    //fseek (ifp, 2*(raw_width - width), SEEK_CUR);
+    for (col=0; col < raw_width; col++)
+        {
+            ushort *dfp = get_masked_pointer(row,col);
+            if(dfp) 
+                *dfp = pixel[col];
+            else
+                {
+                    ushort color = FC(row-top_margin,col-left_margin);
+                    if ((BAYER2(row-top_margin,col-left_margin) = pixel[col]) >> bits) derror();
+                    if (channel_maximum[color] < pixel[col] ) channel_maximum[color] = pixel[col];
+                }
+        }
+  }
+  free (pixel);
+#endif
+}
+
+void CLASS nokia_load_raw()
+{
+  uchar  *data,  *dp;
+  ushort *pixel, *pix;
+  int dwide, row, c;
+
+  dwide = raw_width * 5 / 4;
+  data = (uchar *) malloc (dwide + raw_width*2);
+  merror (data, "nokia_load_raw()");
+  pixel = (ushort *) (data + dwide);
+  for (row=0; row < raw_height; row++) {
+    if (fread (data, 1, dwide, ifp) < dwide) derror();
+    for (dp=data, pix=pixel; pix < pixel+raw_width; dp+=5, pix+=4)
+      FORC4 pix[c] = (dp[c] << 2) | (dp[4] >> (c << 1) & 3);
+    if (row < top_margin)
+#ifdef LIBRAW_LIBRARY_BUILD
+        {
+            int col;
+            for(col=0;col<width;col++)
+                {
+                    ushort *dfp = get_masked_pointer(row,col);
+                    if(dfp) 
+                        *dfp = pixel[col];
+                }
+            FORC(width) black += pixel[c];
+        }
+#else
+      FORC(width) black += pixel[c];
+#endif
+      else
+              FORC(width){
+#ifdef LIBRAW_LIBRARY_BUILD
+                  ushort color = FC(row-top_margin,c);
+                  if(channel_maximum[color] < pixel[c]) channel_maximum[color] = pixel[c];
+#endif
+                  BAYER(row-top_margin,c) = pixel[c];
+              }
+  }
+  free (data);
+  if (top_margin) black /= top_margin * width;
+  maximum = 0x3ff;
+}
+
+unsigned CLASS pana_bits (int nbits)
+{
+#ifndef LIBRAW_NOTHREADS
+#define buf tls->pana_bits.buf
+#define vbits tls->pana_bits.vbits   
+#else
+  static uchar buf[0x4000];
+  static int vbits;
+#endif
+  int byte;
+
+  if (!nbits) return vbits=0;
+  if (!vbits) {
+    fread (buf+load_flags, 1, 0x4000-load_flags, ifp);
+    fread (buf, 1, load_flags, ifp);
+  }
+  vbits = (vbits - nbits) & 0x1ffff;
+  byte = vbits >> 3 ^ 0x3ff0;
+  return (buf[byte] | buf[byte+1] << 8) >> (vbits & 7) & ~(-1 << nbits);
+#ifndef LIBRAW_NOTHREADS
+#undef buf
+#undef vbits
+#endif
+}
+
+void CLASS panasonic_load_raw()
+{
+  int row, col, i, j, sh=0, pred[2], nonz[2];
+
+  pana_bits(0);
+  for (row=0; row < height; row++)
+    for (col=0; col < raw_width; col++) {
+      if ((i = col % 14) == 0)
+	pred[0] = pred[1] = nonz[0] = nonz[1] = 0;
+      if (i % 3 == 2) sh = 4 >> (3 - pana_bits(2));
+      if (nonz[i & 1]) {
+	if ((j = pana_bits(8))) {
+	  if ((pred[i & 1] -= 0x80 << sh) < 0 || sh == 4)
+	       pred[i & 1] &= ~(-1 << sh);
+	  pred[i & 1] += j << sh;
+	}
+      } else if ((nonz[i & 1] = pana_bits(8)) || i > 11)
+	pred[i & 1] = nonz[i & 1] << 4 | pana_bits(4);
+      if (col < width)
+          {
+#ifdef LIBRAW_LIBRARY_BUILD
+              ushort color = FC(row,col);
+#endif
+              if ((BAYER(row,col) = pred[col & 1]) > 4098) derror();
+#ifdef LIBRAW_LIBRARY_BUILD
+              if( channel_maximum[color] < pred[col &1] ) channel_maximum[color] = pred[col &1];
+#endif
+          }
+#ifdef LIBRAW_LIBRARY_BUILD
+      if(col>=width)
+          {
+              ushort *dfp = get_masked_pointer(row,col);
+              if(dfp)*dfp = pred[col & 1];
+          }
+#endif
+    }
+}
+
+void CLASS olympus_load_raw()
+{
+  ushort huff[4096];
+  int row, col, nbits, sign, low, high, i, c, w, n, nw;
+  int acarry[2][3], *carry, pred, diff;
+
+  huff[n=0] = 0xc0c;
+  for (i=12; i--; )
+    FORC(2048 >> i) huff[++n] = (i+1) << 8 | i;
+  fseek (ifp, 7, SEEK_CUR);
+  getbits(-1);
+  for (row=0; row < height; row++) {
+    memset (acarry, 0, sizeof acarry);
+    for (col=0; col < raw_width; col++) {
+      carry = acarry[col & 1];
+      i = 2 * (carry[2] < 3);
+      for (nbits=2+i; (ushort) carry[0] >> (nbits+i); nbits++);
+      low = (sign = getbits(3)) & 3;
+      sign = sign << 29 >> 31;
+      if ((high = getbithuff(12,huff)) == 12)
+	high = getbits(16-nbits) >> 1;
+      carry[0] = (high << nbits) | getbits(nbits);
+      diff = (carry[0] ^ sign) + carry[1];
+      carry[1] = (diff*3 + carry[1]) >> 5;
+      carry[2] = carry[0] > 16 ? 0 : carry[2]+1;
+      if (col >= width) continue;
+      if (row < 2 && col < 2) pred = 0;
+      else if (row < 2) pred = BAYER(row,col-2);
+      else if (col < 2) pred = BAYER(row-2,col);
+      else {
+	w  = BAYER(row,col-2);
+	n  = BAYER(row-2,col);
+	nw = BAYER(row-2,col-2);
+	if ((w < nw && nw < n) || (n < nw && nw < w)) {
+	  if (ABS(w-nw) > 32 || ABS(n-nw) > 32)
+	    pred = w + n - nw;
+	  else pred = (w + n) >> 1;
+	} else pred = ABS(w-nw) > ABS(n-nw) ? w : n;
+      }
+#ifdef LIBRAW_LIBRARY_BUILD
+      {
+          ushort val = pred + ((diff << 2) | low);
+          ushort color = FC(row,col);
+          if(val >> 12) derror();
+          BAYER(row,col)=val;
+          if(channel_maximum[color] < val ) channel_maximum[color] = val;
+      }
+#else
+      if ((BAYER(row,col) = pred + ((diff << 2) | low)) >> 12) derror();
+#endif
+    }
+  }
+}
+
+void CLASS minolta_rd175_load_raw()
+{
+  uchar pixel[768];
+  unsigned irow, box, row, col;
+
+  for (irow=0; irow < 1481; irow++) {
+    if (fread (pixel, 1, 768, ifp) < 768) derror();
+    box = irow / 82;
+    row = irow % 82 * 12 + ((box < 12) ? box | 1 : (box-12)*2);
+    switch (irow) {
+      case 1477: case 1479: continue;
+      case 1476: row = 984; break;
+      case 1480: row = 985; break;
+      case 1478: row = 985; box = 1;
+    }
+    if ((box < 12) && (box & 1)) {
+      for (col=0; col < 1533; col++, row ^= 1)
+	if (col != 1) BAYER(row,col) = (col+1) & 2 ?
+		   pixel[col/2-1] + pixel[col/2+1] : pixel[col/2] << 1;
+      BAYER(row,1)    = pixel[1]   << 1;
+      BAYER(row,1533) = pixel[765] << 1;
+    } else
+      for (col=row & 1; col < 1534; col+=2)
+          {
+#ifdef LIBRAW_LIBRARY_BUILD
+              ushort color = FC(row,col);
+              if(channel_maximum[color] < pixel[col/2] << 1)
+                  channel_maximum[color] = pixel[col/2] << 1;
+#endif
+              BAYER(row,col) = pixel[col/2] << 1;
+          }
+  }
+  maximum = 0xff << 1;
+}
+
+void CLASS quicktake_100_load_raw()
+{
+  uchar pixel[484][644];
+  static const short gstep[16] =
+  { -89,-60,-44,-32,-22,-15,-8,-2,2,8,15,22,32,44,60,89 };
+  static const short rstep[6][4] =
+  { {  -3,-1,1,3  }, {  -5,-1,1,5  }, {  -8,-2,2,8  },
+    { -13,-3,3,13 }, { -19,-4,4,19 }, { -28,-6,6,28 } };
+  static const short t_curve[256] =
+  { 0,1,2,3,4,5,6,7,8,9,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,
+    28,29,30,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,53,
+    54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,74,75,76,77,78,
+    79,80,81,82,83,84,86,88,90,92,94,97,99,101,103,105,107,110,112,114,116,
+    118,120,123,125,127,129,131,134,136,138,140,142,144,147,149,151,153,155,
+    158,160,162,164,166,168,171,173,175,177,179,181,184,186,188,190,192,195,
+    197,199,201,203,205,208,210,212,214,216,218,221,223,226,230,235,239,244,
+    248,252,257,261,265,270,274,278,283,287,291,296,300,305,309,313,318,322,
+    326,331,335,339,344,348,352,357,361,365,370,374,379,383,387,392,396,400,
+    405,409,413,418,422,426,431,435,440,444,448,453,457,461,466,470,474,479,
+    483,487,492,496,500,508,519,531,542,553,564,575,587,598,609,620,631,643,
+    654,665,676,687,698,710,721,732,743,754,766,777,788,799,810,822,833,844,
+    855,866,878,889,900,911,922,933,945,956,967,978,989,1001,1012,1023 };
+  int rb, row, col, sharp, val=0;
+
+  getbits(-1);
+  memset (pixel, 0x80, sizeof pixel);
+  for (row=2; row < height+2; row++) {
+    for (col=2+(row & 1); col < width+2; col+=2) {
+      val = ((pixel[row-1][col-1] + 2*pixel[row-1][col+1] +
+		pixel[row][col-2]) >> 2) + gstep[getbits(4)];
+      pixel[row][col] = val = LIM(val,0,255);
+      if (col < 4)
+	pixel[row][col-2] = pixel[row+1][~row & 1] = val;
+      if (row == 2)
+	pixel[row-1][col+1] = pixel[row-1][col+3] = val;
+    }
+    pixel[row][col] = val;
+  }
+  for (rb=0; rb < 2; rb++)
+    for (row=2+rb; row < height+2; row+=2)
+      for (col=3-(row & 1); col < width+2; col+=2) {
+	if (row < 4 || col < 4) sharp = 2;
+	else {
+	  val = ABS(pixel[row-2][col] - pixel[row][col-2])
+	      + ABS(pixel[row-2][col] - pixel[row-2][col-2])
+	      + ABS(pixel[row][col-2] - pixel[row-2][col-2]);
+	  sharp = val <  4 ? 0 : val <  8 ? 1 : val < 16 ? 2 :
+		  val < 32 ? 3 : val < 48 ? 4 : 5;
+	}
+	val = ((pixel[row-2][col] + pixel[row][col-2]) >> 1)
+	      + rstep[sharp][getbits(2)];
+	pixel[row][col] = val = LIM(val,0,255);
+	if (row < 4) pixel[row-2][col+2] = val;
+	if (col < 4) pixel[row+2][col-2] = val;
+      }
+  for (row=2; row < height+2; row++)
+    for (col=3-(row & 1); col < width+2; col+=2) {
+      val = ((pixel[row][col-1] + (pixel[row][col] << 2) +
+	      pixel[row][col+1]) >> 1) - 0x100;
+      pixel[row][col] = LIM(val,0,255);
+    }
+  for (row=0; row < height; row++)
+    for (col=0; col < width; col++)
+        {
+#ifdef LIBRAW_LIBRARY_BUILD
+            ushort color = FC(row,col);
+            if(channel_maximum[color] < t_curve[pixel[row+2][col+2]])
+                channel_maximum[color] = t_curve[pixel[row+2][col+2]];
+#endif
+            BAYER(row,col) = t_curve[pixel[row+2][col+2]];
+        }
+  maximum = 0x3ff;
+}
+
+#define radc_token(tree) ((signed char) getbithuff(8,huff[tree]))
+
+#define FORYX for (y=1; y < 3; y++) for (x=col+1; x >= col; x--)
+
+#define PREDICTOR (c ? (buf[c][y-1][x] + buf[c][y][x+1]) / 2 \
+: (buf[c][y-1][x+1] + 2*buf[c][y-1][x] + buf[c][y][x+1]) / 4)
+
+void CLASS kodak_radc_load_raw()
+{
+  static const char src[] = {
+    1,1, 2,3, 3,4, 4,2, 5,7, 6,5, 7,6, 7,8,
+    1,0, 2,1, 3,3, 4,4, 5,2, 6,7, 7,6, 8,5, 8,8,
+    2,1, 2,3, 3,0, 3,2, 3,4, 4,6, 5,5, 6,7, 6,8,
+    2,0, 2,1, 2,3, 3,2, 4,4, 5,6, 6,7, 7,5, 7,8,
+    2,1, 2,4, 3,0, 3,2, 3,3, 4,7, 5,5, 6,6, 6,8,
+    2,3, 3,1, 3,2, 3,4, 3,5, 3,6, 4,7, 5,0, 5,8,
+    2,3, 2,6, 3,0, 3,1, 4,4, 4,5, 4,7, 5,2, 5,8,
+    2,4, 2,7, 3,3, 3,6, 4,1, 4,2, 4,5, 5,0, 5,8,
+    2,6, 3,1, 3,3, 3,5, 3,7, 3,8, 4,0, 5,2, 5,4,
+    2,0, 2,1, 3,2, 3,3, 4,4, 4,5, 5,6, 5,7, 4,8,
+    1,0, 2,2, 2,-2,
+    1,-3, 1,3,
+    2,-17, 2,-5, 2,5, 2,17,
+    2,-7, 2,2, 2,9, 2,18,
+    2,-18, 2,-9, 2,-2, 2,7,
+    2,-28, 2,28, 3,-49, 3,-9, 3,9, 4,49, 5,-79, 5,79,
+    2,-1, 2,13, 2,26, 3,39, 4,-16, 5,55, 6,-37, 6,76,
+    2,-26, 2,-13, 2,1, 3,-39, 4,16, 5,-55, 6,-76, 6,37
+  };
+  ushort huff[19][256];
+  int row, col, tree, nreps, rep, step, i, c, s, r, x, y, val;
+  short last[3] = { 16,16,16 }, mul[3], buf[3][3][386];
+  static const ushort pt[] =
+    { 0,0, 1280,1344, 2320,3616, 3328,8000, 4095,16383, 65535,16383 };
+
+  for (i=2; i < 12; i+=2)
+    for (c=pt[i-2]; c <= pt[i]; c++)
+      curve[c] = (float)
+	(c-pt[i-2]) / (pt[i]-pt[i-2]) * (pt[i+1]-pt[i-1]) + pt[i-1] + 0.5;
+  for (s=i=0; i < sizeof src; i+=2)
+    FORC(256 >> src[i])
+      huff[0][s++] = src[i] << 8 | (uchar) src[i+1];
+  s = kodak_cbpp == 243 ? 2 : 3;
+  FORC(256) huff[18][c] = (8-s) << 8 | c >> s << s | 1 << (s-1);
+  getbits(-1);
+  for (i=0; i < sizeof(buf)/sizeof(short); i++)
+    buf[0][0][i] = 2048;
+  for (row=0; row < height; row+=4) {
+    FORC3 mul[c] = getbits(6);
+    FORC3 {
+      val = ((0x1000000/last[c] + 0x7ff) >> 12) * mul[c];
+      s = val > 65564 ? 10:12;
+      x = ~(-1 << (s-1));
+      val <<= 12-s;
+      for (i=0; i < sizeof(buf[0])/sizeof(short); i++)
+	buf[c][0][i] = (buf[c][0][i] * val + x) >> s;
+      last[c] = mul[c];
+      for (r=0; r <= !c; r++) {
+	buf[c][1][width/2] = buf[c][2][width/2] = mul[c] << 7;
+	for (tree=1, col=width/2; col > 0; ) {
+	  if ((tree = radc_token(tree))) {
+	    col -= 2;
+	    if (tree == 8)
+	      FORYX buf[c][y][x] = (uchar) radc_token(18) * mul[c];
+	    else
+	      FORYX buf[c][y][x] = radc_token(tree+10) * 16 + PREDICTOR;
+	  } else
+	    do {
+	      nreps = (col > 2) ? radc_token(9) + 1 : 1;
+	      for (rep=0; rep < 8 && rep < nreps && col > 0; rep++) {
+		col -= 2;
+		FORYX buf[c][y][x] = PREDICTOR;
+		if (rep & 1) {
+		  step = radc_token(10) << 4;
+		  FORYX buf[c][y][x] += step;
+		}
+	      }
+	    } while (nreps == 9);
+	}
+	for (y=0; y < 2; y++)
+	  for (x=0; x < width/2; x++) {
+	    val = (buf[c][y+1][x] << 4) / mul[c];
+	    if (val < 0) val = 0;
+	    if (c) BAYER(row+y*2+c-1,x*2+2-c) = val;
+	    else   BAYER(row+r*2+y,x*2+y) = val;
+	  }
+	memcpy (buf[c][0]+!c, buf[c][2], sizeof buf[c][0]-2*!c);
+      }
+    }
+    for (y=row; y < row+4; y++)
+      for (x=0; x < width; x++)
+	if ((x+y) & 1) {
+	  r = x ? x-1 : x+1;
+	  s = x+1 < width ? x+1 : x-1;
+	  val = (BAYER(y,x)-2048)*2 + (BAYER(y,r)+BAYER(y,s))/2;
+	  if (val < 0) val = 0;
+	  BAYER(y,x) = val;
+	}
+  }
+  for (i=0; i < iheight*iwidth*4; i++)
+#ifdef LIBRAW_LIBRARY_BUILD
+      {
+          ushort c = i%4;
+          image[0][i] = curve[image[0][i]];
+          if(channel_maximum[c] < image[0][i]) channel_maximum[c] = image[0][i];
+      }
+#else
+    image[0][i] = curve[image[0][i]];
+#endif
+  maximum = 0x3fff;
+}
+
+#undef FORYX
+#undef PREDICTOR
+
+#ifdef NO_JPEG
+void CLASS kodak_jpeg_load_raw() {}
+#else
+
+METHODDEF(boolean)
+fill_input_buffer (j_decompress_ptr cinfo)
+{
+#ifndef LIBRAW_NOTHREADS
+#define jpeg_buffer tls->jpeg_buffer
+#else
+  static uchar jpeg_buffer[4096];
+#endif
+  size_t nbytes;
+
+  nbytes = fread (jpeg_buffer, 1, 4096, ifp);
+  swab (jpeg_buffer, jpeg_buffer, nbytes);
+  cinfo->src->next_input_byte = jpeg_buffer;
+  cinfo->src->bytes_in_buffer = nbytes;
+  return TRUE;
+#ifndef LIBRAW_NOTHREADS
+#undef jpeg_buffer
+#endif
+}
+
+void CLASS kodak_jpeg_load_raw()
+{
+  struct jpeg_decompress_struct cinfo;
+  struct jpeg_error_mgr jerr;
+  JSAMPARRAY buf;
+  JSAMPLE (*pixel)[3];
+  int row, col;
+
+  cinfo.err = jpeg_std_error (&jerr);
+  jpeg_create_decompress (&cinfo);
+  jpeg_stdio_src (&cinfo, ifp);
+  cinfo.src->fill_input_buffer = fill_input_buffer;
+  jpeg_read_header (&cinfo, TRUE);
+  jpeg_start_decompress (&cinfo);
+  if ((cinfo.output_width      != width  ) ||
+      (cinfo.output_height*2   != height ) ||
+      (cinfo.output_components != 3      )) {
+#ifdef DCRAW_VERBOSE
+    fprintf (stderr,_("%s: incorrect JPEG dimensions\n"), ifname);
+#endif
+    jpeg_destroy_decompress (&cinfo);
+#ifdef LIBRAW_LIBRARY_BUILD
+    throw LIBRAW_EXCEPTION_DECODE_JPEG;
+#else
+    longjmp (failure, 3);
+#endif
+  }
+  buf = (*cinfo.mem->alloc_sarray)
+		((j_common_ptr) &cinfo, JPOOL_IMAGE, width*3, 1);
+
+  while (cinfo.output_scanline < cinfo.output_height) {
+    row = cinfo.output_scanline * 2;
+    jpeg_read_scanlines (&cinfo, buf, 1);
+    pixel = (JSAMPLE (*)[3]) buf[0];
+    for (col=0; col < width; col+=2) {
+      BAYER(row+0,col+0) = pixel[col+0][1] << 1;
+      BAYER(row+1,col+1) = pixel[col+1][1] << 1;
+      BAYER(row+0,col+1) = pixel[col][0] + pixel[col+1][0];
+      BAYER(row+1,col+0) = pixel[col][2] + pixel[col+1][2];
+
+#ifdef LIBRAW_LIBRARY_BUILD
+      if(channel_maximum[FC(row+0,col+0)] < pixel[col+0][1] << 1) channel_maximum[FC(row+0,col+0)]=pixel[col+0][1]<<1;
+      if(channel_maximum[FC(row+1,col+1)] < pixel[col+1][1] << 1) channel_maximum[FC(row+1,col+1)]=pixel[col+1][1]<<1;
+      if(channel_maximum[FC(row+0,col+1)] < pixel[col][0] + pixel[col+1][0])
+          channel_maximum[FC(row+0,col+1)] = pixel[col][0] + pixel[col+1][0];
+      if(channel_maximum[FC(row+1,col+0)] < pixel[col][2] + pixel[col+1][2])
+          channel_maximum[FC(row+1,col+0)] = pixel[col][2] + pixel[col+1][2];
+#endif
+    }
+  }
+  jpeg_finish_decompress (&cinfo);
+  jpeg_destroy_decompress (&cinfo);
+  maximum = 0xff << 1;
+}
+#endif
+
+void CLASS kodak_dc120_load_raw()
+{
+  static const int mul[4] = { 162, 192, 187,  92 };
+  static const int add[4] = {   0, 636, 424, 212 };
+  uchar pixel[848];
+  int row, shift, col;
+
+  for (row=0; row < height; row++) {
+    if (fread (pixel, 1, 848, ifp) < 848) derror();
+    shift = row * mul[row & 3] + add[row & 3];
+    for (col=0; col < width; col++)
+#ifdef LIBRAW_LIBRARY_BUILD
+        {
+            ushort val = pixel[(col + shift) % 848];
+            ushort color = FC(row,col);
+            BAYER(row,col) = val;
+            if(channel_maximum[color] < val) channel_maximum[color] = val;
+        }
+#else
+      BAYER(row,col) = (ushort) pixel[(col + shift) % 848];
+#endif
+  }
+  maximum = 0xff;
+}
+
+void CLASS eight_bit_load_raw()
+{
+  uchar *pixel;
+  unsigned row, col, val, lblack=0;
+
+  pixel = (uchar *) calloc (raw_width, sizeof *pixel);
+  merror (pixel, "eight_bit_load_raw()");
+#ifndef LIBRAW_LIBRARY_BUILD
+  fseek (ifp, top_margin*raw_width, SEEK_CUR);
+  for (row=0; row < height; row++) {
+    if (fread (pixel, 1, raw_width, ifp) < raw_width) derror();
+    for (col=0; col < raw_width; col++) {
+      val = curve[pixel[col]];
+      if ((unsigned) (col-left_margin) < width)
+        BAYER(row,col-left_margin) = val;
+      else lblack += val;
+    }
+  }
+#else
+  for (row=0; row < raw_height; row++) {
+    if (fread (pixel, 1, raw_width, ifp) < raw_width) derror();
+    for (col=0; col < raw_width; col++) {
+        if(filtering_mode & LIBRAW_FILTERING_NORAWCURVE)
+            {
+                val = pixel[col];
+                if(val>maximum) maximum = val;
+            }
+        else
+            val = curve[pixel[col]];
+      if((unsigned) (row-top_margin)< height)
+          {
+              if ((unsigned) (col-left_margin) < width)
+                  {
+                      ushort color=FC(row,col);
+                      if(channel_maximum[color] < val) channel_maximum[color] = val;
+                      BAYER(row,col-left_margin) = val;
+                  }
+              else
+                  {
+                      ushort *dfp = get_masked_pointer(row,col);
+                      if(dfp) *dfp = val;
+                      lblack += val;
+                  }
+          }
+      else // top/bottom margins
+          {
+              ushort *dfp = get_masked_pointer(row,col);
+              if(dfp) *dfp = val;
+          }
+    }
+  }
+#endif
+
+  free (pixel);
+  if (raw_width > width+1)
+    black = lblack / ((raw_width - width) * height);
+  if (!strncmp(model,"DC2",3))
+    black = 0;
+#ifdef LIBRAW_LIBRARY_BUILD
+  if(!(filtering_mode & LIBRAW_FILTERING_NORAWCURVE))
+#endif
+  maximum = curve[0xff];
+}
+
+void CLASS kodak_yrgb_load_raw()
+{
+  uchar *pixel;
+  int row, col, y, cb, cr, rgb[3], c;
+
+  pixel = (uchar *) calloc (raw_width, 3*sizeof *pixel);
+  merror (pixel, "kodak_yrgb_load_raw()");
+  for (row=0; row < height; row++) {
+    if (~row & 1)
+      if (fread (pixel, raw_width, 3, ifp) < 3) derror();
+    for (col=0; col < raw_width; col++) {
+      y  = pixel[width*2*(row & 1) + col];
+      cb = pixel[width + (col & -2)]   - 128;
+      cr = pixel[width + (col & -2)+1] - 128;
+      rgb[1] = y-((cb + cr + 2) >> 2);
+      rgb[2] = rgb[1] + cb;
+      rgb[0] = rgb[1] + cr;
+      FORC3{
+          image[row*width+col][c] = curve[LIM(rgb[c],0,255)];
+#ifdef LIBRAW_LIBRARY_BUILD
+          if(channel_maximum[c] < image[row*width+col][c]) channel_maximum[c] = image[row*width+col][c];
+#endif
+      }
+    }
+  }
+  free (pixel);
+  maximum = curve[0xff];
+}
+
+void CLASS kodak_262_load_raw()
+{
+  static const uchar kodak_tree[2][26] =
+  { { 0,1,5,1,1,2,0,0,0,0,0,0,0,0,0,0, 0,1,2,3,4,5,6,7,8,9 },
+    { 0,3,1,1,1,1,1,2,0,0,0,0,0,0,0,0, 0,1,2,3,4,5,6,7,8,9 } };
+  ushort *huff[2];
+  uchar *pixel;
+  int *strip, ns, c, row, col, chess, pi=0, pi1, pi2, pred, val;
+
+  FORC(2) huff[c] = make_decoder (kodak_tree[c]);
+  ns = (raw_height+63) >> 5;
+  pixel = (uchar *) malloc (raw_width*32 + ns*4);
+  merror (pixel, "kodak_262_load_raw()");
+  strip = (int *) (pixel + raw_width*32);
+  order = 0x4d4d;
+  FORC(ns) strip[c] = get4();
+  for (row=0; row < raw_height; row++) {
+    if ((row & 31) == 0) {
+      fseek (ifp, strip[row >> 5], SEEK_SET);
+      getbits(-1);
+      pi = 0;
+    }
+    for (col=0; col < raw_width; col++) {
+      chess = (row + col) & 1;
+      pi1 = chess ? pi-2           : pi-raw_width-1;
+      pi2 = chess ? pi-2*raw_width : pi-raw_width+1;
+      if (col <= chess) pi1 = -1;
+      if (pi1 < 0) pi1 = pi2;
+      if (pi2 < 0) pi2 = pi1;
+      if (pi1 < 0 && col > 1) pi1 = pi2 = pi-2;
+      pred = (pi1 < 0) ? 0 : (pixel[pi1] + pixel[pi2]) >> 1;
+      pixel[pi] = val = pred + ljpeg_diff (huff[chess]);
+      if (val >> 8) derror();
+#ifdef LIBRAW_LIBRARY_BUILD
+      if(filtering_mode & LIBRAW_FILTERING_NORAWCURVE)
+          val = pixel[pi++];
+      else
+          val = curve[pixel[pi++]];
+#else
+      val = curve[pixel[pi++]];
+#endif
+      if ((unsigned) (col-left_margin) < width)
+          {
+#ifdef LIBRAW_LIBRARY_BUILD
+              ushort color = FC(row,col-left_margin);
+              if(channel_maximum[color] < val ) channel_maximum[color]=val;
+#endif
+	BAYER(row,col-left_margin) = val;
+          }
+      else
+#ifndef LIBRAW_LIBRARY_BUILD
+          black += val;
+#else
+      {
+          ushort *dfp = get_masked_pointer(row,col);
+          if(dfp) *dfp = val;
+          black += val;
+      }
+#endif
+    }
+  }
+  free (pixel);
+  FORC(2) free (huff[c]);
+  if (raw_width > width)
+    black /= (raw_width - width) * height;
+}
+
+int CLASS kodak_65000_decode (short *out, int bsize)
+{
+  uchar c, blen[768];
+  ushort raw[6];
+  INT64 bitbuf=0;
+  int save, bits=0, i, j, len, diff;
+
+  save = ftell(ifp);
+  bsize = (bsize + 3) & -4;
+  for (i=0; i < bsize; i+=2) {
+    c = fgetc(ifp);
+    if ((blen[i  ] = c & 15) > 12 ||
+	(blen[i+1] = c >> 4) > 12 ) {
+      fseek (ifp, save, SEEK_SET);
+      for (i=0; i < bsize; i+=8) {
+	read_shorts (raw, 6);
+	out[i  ] = raw[0] >> 12 << 8 | raw[2] >> 12 << 4 | raw[4] >> 12;
+	out[i+1] = raw[1] >> 12 << 8 | raw[3] >> 12 << 4 | raw[5] >> 12;
+	for (j=0; j < 6; j++)
+	  out[i+2+j] = raw[j] & 0xfff;
+      }
+      return 1;
+    }
+  }
+  if ((bsize & 7) == 4) {
+    bitbuf  = fgetc(ifp) << 8;
+    bitbuf += fgetc(ifp);
+    bits = 16;
+  }
+  for (i=0; i < bsize; i++) {
+    len = blen[i];
+    if (bits < len) {
+      for (j=0; j < 32; j+=8)
+	bitbuf += (INT64) fgetc(ifp) << (bits+(j^8));
+      bits += 32;
+    }
+    diff = bitbuf & (0xffff >> (16-len));
+    bitbuf >>= len;
+    bits -= len;
+    if ((diff & (1 << (len-1))) == 0)
+      diff -= (1 << len) - 1;
+    out[i] = diff;
+  }
+  return 0;
+}
+
+void CLASS kodak_65000_load_raw()
+{
+  short buf[256];
+  int row, col, len, pred[2], ret, i;
+
+  for (row=0; row < height; row++)
+    for (col=0; col < width; col+=256) {
+      pred[0] = pred[1] = 0;
+      len = MIN (256, width-col);
+      ret = kodak_65000_decode (buf, len);
+      for (i=0; i < len; i++)
+#ifndef LIBRAW_LIBRARY_BUILD
+	if ((BAYER(row,col+i) =	curve[ret ? buf[i] :
+		(pred[i & 1] += buf[i])]) >> 12) derror();
+#else
+      {
+          ushort val = ret ? buf[i] : (pred[i & 1] += buf[i]);
+          ushort color = FC(row,col);
+          if(!(filtering_mode & LIBRAW_FILTERING_NORAWCURVE))
+              val = curve[val];
+          BAYER(row,col+i)=val;
+          if(channel_maximum[color] < val ) channel_maximum[color]=val;
+          if(curve[val]>>12) derror();
+      }
+#endif
+    }
+}
+
+void CLASS kodak_ycbcr_load_raw()
+{
+  short buf[384], *bp;
+  int row, col, len, c, i, j, k, y[2][2], cb, cr, rgb[3];
+  ushort *ip;
+
+  for (row=0; row < height; row+=2)
+    for (col=0; col < width; col+=128) {
+      len = MIN (128, width-col);
+      kodak_65000_decode (buf, len*3);
+      y[0][1] = y[1][1] = cb = cr = 0;
+      for (bp=buf, i=0; i < len; i+=2, bp+=2) {
+	cb += bp[4];
+	cr += bp[5];
+	rgb[1] = -((cb + cr + 2) >> 2);
+	rgb[2] = rgb[1] + cb;
+	rgb[0] = rgb[1] + cr;
+	for (j=0; j < 2; j++)
+	  for (k=0; k < 2; k++) {
+	    if ((y[j][k] = y[j][k^1] + *bp++) >> 10) derror();
+	    ip = image[(row+j)*width + col+i+k];
+#ifndef LIBRAW_LIBRARY_BUILD
+	    FORC3 ip[c] = curve[LIM(y[j][k]+rgb[c], 0, 0xfff)];
+#else
+          if(!(filtering_mode & LIBRAW_FILTERING_NORAWCURVE))
+              FORC3 ip[c] = curve[LIM(y[j][k]+rgb[c], 0, 0xfff)];
+          else
+              FORC3 ip[c] = y[j][k]+rgb[c];;
+          FORC3
+              if(channel_maximum[c] < ip[c])
+                  channel_maximum[c] = ip[c];
+#endif
+	  }
+      }
+    }
+}
+
+void CLASS kodak_rgb_load_raw()
+{
+  short buf[768], *bp;
+  int row, col, len, c, i, rgb[3];
+  ushort *ip=image[0];
+
+  for (row=0; row < height; row++)
+    for (col=0; col < width; col+=256) {
+      len = MIN (256, width-col);
+      kodak_65000_decode (buf, len*3);
+      memset (rgb, 0, sizeof rgb);
+      for (bp=buf, i=0; i < len; i++, ip+=4)
+          FORC3{
+              if ((ip[c] = rgb[c] += *bp++) >> 12) derror();
+#ifdef LIBRAW_LIBRARY_BUILD
+              if(channel_maximum[c] < ip[c]) channel_maximum[c] = ip[c];
+#endif
+          }
+    }
+}
+
+void CLASS kodak_thumb_load_raw()
+{
+  int row, col;
+  colors = thumb_misc >> 5;
+  for (row=0; row < height; row++)
+    for (col=0; col < width; col++)
+      read_shorts (image[row*width+col], colors);
+  maximum = (1 << (thumb_misc & 31)) - 1;
+}
+
+void CLASS sony_decrypt (unsigned *data, int len, int start, int key)
+{
+#ifndef LIBRAW_NOTHREADS
+#define pad tls->sony_decrypt.pad
+#define p   tls->sony_decrypt.p
+#else
+  static unsigned pad[128], p;
+#endif
+
+  if (start) {
+    for (p=0; p < 4; p++)
+      pad[p] = key = key * 48828125 + 1;
+    pad[3] = pad[3] << 1 | (pad[0]^pad[2]) >> 31;
+    for (p=4; p < 127; p++)
+      pad[p] = (pad[p-4]^pad[p-2]) << 1 | (pad[p-3]^pad[p-1]) >> 31;
+    for (p=0; p < 127; p++)
+      pad[p] = htonl(pad[p]);
+  }
+  while (len--)
+    *data++ ^= pad[p++ & 127] = pad[(p+1) & 127] ^ pad[(p+65) & 127];
+#ifndef LIBRAW_NOTHREADS
+#undef pad
+#undef p
+#endif
+}
+
+void CLASS sony_load_raw()
+{
+  uchar head[40];
+  ushort *pixel;
+  unsigned i, key, row, col;
+
+  fseek (ifp, 200896, SEEK_SET);
+  fseek (ifp, (unsigned) fgetc(ifp)*4 - 1, SEEK_CUR);
+  order = 0x4d4d;
+  key = get4();
+  fseek (ifp, 164600, SEEK_SET);
+  fread (head, 1, 40, ifp);
+  sony_decrypt ((unsigned int *) head, 10, 1, key);
+  for (i=26; i-- > 22; )
+    key = key << 8 | head[i];
+  fseek (ifp, data_offset, SEEK_SET);
+  pixel = (ushort *) calloc (raw_width, sizeof *pixel);
+  merror (pixel, "sony_load_raw()");
+  for (row=0; row < height; row++) {
+    if (fread (pixel, 2, raw_width, ifp) < raw_width) derror();
+    sony_decrypt ((unsigned int *) pixel, raw_width/2, !row, key);
+#ifdef LIBRAW_LIBRARY_BUILD
+    for (col=0; col < left_margin; col++)
+          {
+              ushort *dfp = get_masked_pointer(row,col);
+              if(dfp) *dfp = ntohs(pixel[col]);
+          }
+    for (col=left_margin+width; col < raw_width; col++)
+          {
+              ushort *dfp = get_masked_pointer(row,col);
+              if(dfp) *dfp = ntohs(pixel[col]);
+          }
+#endif
+    for (col=9; col < left_margin; col++)
+      black += ntohs(pixel[col]);
+    for (col=0; col < width; col++)
+#ifdef LIBRAW_LIBRARY_BUILD
+        {
+            ushort color = FC(row,col);
+            ushort  val = ntohs(pixel[col+left_margin]);
+            if(val>>14)
+                derror();
+            BAYER(row,col)=val;
+            if(channel_maximum[color] < val ) channel_maximum[color] = val;
+        }
+#else
+      if ((BAYER(row,col) = ntohs(pixel[col+left_margin])) >> 14)
+	derror();
+#endif    
+  }
+  free (pixel);
+  if (left_margin > 9)
+    black /= (left_margin-9) * height;
+  maximum = 0x3ff0;
+}
+
+void CLASS sony_arw_load_raw()
+{
+  ushort huff[32768];
+  static const ushort tab[18] =
+  { 0xf11,0xf10,0xe0f,0xd0e,0xc0d,0xb0c,0xa0b,0x90a,0x809,
+    0x708,0x607,0x506,0x405,0x304,0x303,0x300,0x202,0x201 };
+  int i, c, n, col, row, len, diff, sum=0;
+
+  for (n=i=0; i < 18; i++)
+    FORC(32768 >> (tab[i] >> 8)) huff[n++] = tab[i];
+  getbits(-1);
+  for (col = raw_width; col--; )
+    for (row=0; row < raw_height+1; row+=2) {
+      if (row == raw_height) row = 1;
+      len = getbithuff(15,huff);
+      diff = getbits(len);
+      if ((diff & (1 << (len-1))) == 0)
+	diff -= (1 << len) - 1;
+      if ((sum += diff) >> 12) derror();
+      if (row < height)
+          {
+              BAYER(row,col) = sum;
+#ifdef LIBRAW_LIBRARY_BUILD
+            ushort color = FC(row,col);
+            if(channel_maximum[color] < sum ) channel_maximum[color] = sum;
+#endif
+          }
+#ifdef LIBRAW_LIBRARY_BUILD
+      else
+          {
+              ushort *dfp = get_masked_pointer(row,col);
+              if(dfp) *dfp = sum;
+          }
+#endif
+    }
+}
+
+void CLASS sony_arw2_load_raw()
+{
+  uchar *data, *dp;
+  ushort pix[16];
+  int row, col, val, max, min, imax, imin, sh, bit, i;
+
+  data = (uchar *) malloc (raw_width);
+  merror (data, "sony_arw2_load_raw()");
+  for (row=0; row < height; row++) {
+    fread (data, 1, raw_width, ifp);
+    for (dp=data, col=0; col < width-30; dp+=16) {
+      max = 0x7ff & (val = sget4(dp));
+      min = 0x7ff & val >> 11;
+      imax = 0x0f & val >> 22;
+      imin = 0x0f & val >> 26;
+      for (sh=0; sh < 4 && 0x80 << sh <= max-min; sh++);
+      for (bit=30, i=0; i < 16; i++)
+	if      (i == imax) pix[i] = max;
+	else if (i == imin) pix[i] = min;
+	else {
+	  pix[i] = ((sget2(dp+(bit >> 3)) >> (bit & 7) & 0x7f) << sh) + min;
+	  if (pix[i] > 0x7ff) pix[i] = 0x7ff;
+	  bit += 7;
+	}
+      for (i=0; i < 16; i++, col+=2)
+#ifndef LIBRAW_LIBRARY_BUILD
+	  BAYER(row,col) = curve[pix[i] << 1] >> 1;
+#else
+        {
+            ushort val = pix[i];
+            ushort color = FC(row,col);
+            if(!(filtering_mode & LIBRAW_FILTERING_NORAWCURVE))
+                val = curve[val<<1]>>1;
+            BAYER(row,col)=val;
+            if(channel_maximum[color] < val ) channel_maximum[color] = val;
+        }
+#endif
+      col -= col & 1 ? 1:31;
+    }
+  }
+  free (data);
+}
+
+#define HOLE(row) ((holes >> (((row) - raw_height) & 7)) & 1)
+
+/* Kudos to Rich Taylor for figuring out SMaL's compression algorithm. */
+void CLASS smal_decode_segment (unsigned seg[2][2], int holes)
+{
+  uchar hist[3][13] = {
+    { 7, 7, 0, 0, 63, 55, 47, 39, 31, 23, 15, 7, 0 },
+    { 7, 7, 0, 0, 63, 55, 47, 39, 31, 23, 15, 7, 0 },
+    { 3, 3, 0, 0, 63,     47,     31,     15,    0 } };
+  int low, high=0xff, carry=0, nbits=8;
+  int s, count, bin, next, i, sym[3];
+  uchar diff, pred[]={0,0};
+  ushort data=0, range=0;
+  unsigned pix, row, col;
+
+  fseek (ifp, seg[0][1]+1, SEEK_SET);
+  getbits(-1);
+  for (pix=seg[0][0]; pix < seg[1][0]; pix++) {
+    for (s=0; s < 3; s++) {
+      data = data << nbits | getbits(nbits);
+      if (carry < 0)
+	carry = (nbits += carry+1) < 1 ? nbits-1 : 0;
+      while (--nbits >= 0)
+	if ((data >> nbits & 0xff) == 0xff) break;
+      if (nbits > 0)
+	  data = ((data & ((1 << (nbits-1)) - 1)) << 1) |
+	((data + (((data & (1 << (nbits-1)))) << 1)) & (-1 << nbits));
+      if (nbits >= 0) {
+	data += getbits(1);
+	carry = nbits - 8;
+      }
+      count = ((((data-range+1) & 0xffff) << 2) - 1) / (high >> 4);
+      for (bin=0; hist[s][bin+5] > count; bin++);
+		low = hist[s][bin+5] * (high >> 4) >> 2;
+      if (bin) high = hist[s][bin+4] * (high >> 4) >> 2;
+      high -= low;
+      for (nbits=0; high << nbits < 128; nbits++);
+      range = (range+low) << nbits;
+      high <<= nbits;
+      next = hist[s][1];
+      if (++hist[s][2] > hist[s][3]) {
+	next = (next+1) & hist[s][0];
+	hist[s][3] = (hist[s][next+4] - hist[s][next+5]) >> 2;
+	hist[s][2] = 1;
+      }
+      if (hist[s][hist[s][1]+4] - hist[s][hist[s][1]+5] > 1) {
+	if (bin < hist[s][1])
+	  for (i=bin; i < hist[s][1]; i++) hist[s][i+5]--;
+	else if (next <= bin)
+	  for (i=hist[s][1]; i < bin; i++) hist[s][i+5]++;
+      }
+      hist[s][1] = next;
+      sym[s] = bin;
+    }
+    diff = sym[2] << 5 | sym[1] << 2 | (sym[0] & 3);
+    if (sym[0] & 4)
+      diff = diff ? -diff : 0x80;
+    if (ftell(ifp) + 12 >= seg[1][1])
+      diff = 0;
+    pred[pix & 1] += diff;
+    row = pix / raw_width - top_margin;
+    col = pix % raw_width - left_margin;
+    if (row < height && col < width)
+        {
+#ifdef LIBRAW_LIBRARY_BUILD
+            ushort color = FC(row,col);
+            if(channel_maximum[color] < pred[pix & 1])
+                channel_maximum[color] = pred[pix & 1];
+#endif
+            BAYER(row,col) = pred[pix & 1];
+        }
+#ifdef LIBRAW_LIBRARY_BUILD
+    else
+        {
+            ushort *dfp = get_masked_pointer(row+top_margin,col+left_margin);
+            if(dfp) *dfp = pred[pix &1];
+        }
+#endif
+    if (!(pix & 1) && HOLE(row)) pix += 2;
+  }
+  maximum = 0xff;
+}
+
+void CLASS smal_v6_load_raw()
+{
+  unsigned seg[2][2];
+
+  fseek (ifp, 16, SEEK_SET);
+  seg[0][0] = 0;
+  seg[0][1] = get2();
+  seg[1][0] = raw_width * raw_height;
+  seg[1][1] = INT_MAX;
+  smal_decode_segment (seg, 0);
+}
+
+int CLASS median4 (int *p)
+{
+  int min, max, sum, i;
+
+  min = max = sum = p[0];
+  for (i=1; i < 4; i++) {
+    sum += p[i];
+    if (min > p[i]) min = p[i];
+    if (max < p[i]) max = p[i];
+  }
+  return (sum - min - max) >> 1;
+}
+
+void CLASS fill_holes (int holes)
+{
+  int row, col, val[4];
+
+  for (row=2; row < height-2; row++) {
+    if (!HOLE(row)) continue;
+    for (col=1; col < width-1; col+=4) {
+      val[0] = BAYER(row-1,col-1);
+      val[1] = BAYER(row-1,col+1);
+      val[2] = BAYER(row+1,col-1);
+      val[3] = BAYER(row+1,col+1);
+      BAYER(row,col) = median4(val);
+    }
+    for (col=2; col < width-2; col+=4)
+      if (HOLE(row-2) || HOLE(row+2))
+	BAYER(row,col) = (BAYER(row,col-2) + BAYER(row,col+2)) >> 1;
+      else {
+	val[0] = BAYER(row,col-2);
+	val[1] = BAYER(row,col+2);
+	val[2] = BAYER(row-2,col);
+	val[3] = BAYER(row+2,col);
+	BAYER(row,col) = median4(val);
+      }
+  }
+}
+
+void CLASS smal_v9_load_raw()
+{
+  unsigned seg[256][2], offset, nseg, holes, i;
+
+  fseek (ifp, 67, SEEK_SET);
+  offset = get4();
+  nseg = fgetc(ifp);
+  fseek (ifp, offset, SEEK_SET);
+  for (i=0; i < nseg*2; i++)
+    seg[0][i] = get4() + data_offset*(i & 1);
+  fseek (ifp, 78, SEEK_SET);
+  holes = fgetc(ifp);
+  fseek (ifp, 88, SEEK_SET);
+  seg[nseg][0] = raw_height * raw_width;
+  seg[nseg][1] = get4() + data_offset;
+  for (i=0; i < nseg; i++)
+    smal_decode_segment (seg+i, holes);
+  if (holes) fill_holes (holes);
+}
+#line 4127 "dcraw/dcraw.c"
+
+void CLASS gamma_curve (double pwr, double ts, int mode, int imax)
+{
+  int i;
+  double g[6], bnd[2]={0,0}, r;
+
+  g[0] = pwr;
+  g[1] = ts;
+  g[2] = g[3] = g[4] = 0;
+  bnd[g[1] >= 1] = 1;
+  if (g[1] && (g[1]-1)*(g[0]-1) <= 0) {
+    for (i=0; i < 48; i++) {
+      g[2] = (bnd[0] + bnd[1])/2;
+      if (g[0]) bnd[(pow(g[2]/g[1],-g[0]) - 1)/g[0] - 1/g[2] > -1] = g[2];
+      else	bnd[g[2]/exp(1-1/g[2]) < g[1]] = g[2];
+    }
+    g[3] = g[2] / g[1];
+    if (g[0]) g[4] = g[2] * (1/g[0] - 1);
+  }
+  if (g[0]) g[5] = 1 / (g[1]*SQR(g[3])/2 - g[4]*(1 - g[3]) +
+		(1 - pow(g[3],1+g[0]))*(1 + g[4])/(1 + g[0])) - 1;
+  else      g[5] = 1 / (g[1]*SQR(g[3])/2 + 1
+		- g[2] - g[3] -	g[2]*g[3]*(log(g[3]) - 1)) - 1;
+  if (!mode--) {
+    memcpy (gamm, g, sizeof gamm);
+    return;
+  }
+  for (i=0; i < 0x10000; i++) {
+    curve[i] = 0xffff;
+    if ((r = (double) i / imax) < 1)
+      curve[i] = 0x10000 * ( mode
+	? (r < g[3] ? r*g[1] : (g[0] ? pow( r,g[0])*(1+g[4])-g[4]    : log(r)*g[2]+1))
+	: (r < g[2] ? r/g[1] : (g[0] ? pow((r+g[4])/(1+g[4]),1/g[0]) : exp((r-1)/g[2]))));
+  }
+}
+
+void CLASS pseudoinverse (double (*in)[3], double (*out)[3], int size)
+{
+  double work[3][6], num;
+  int i, j, k;
+
+  for (i=0; i < 3; i++) {
+    for (j=0; j < 6; j++)
+      work[i][j] = j == i+3;
+    for (j=0; j < 3; j++)
+      for (k=0; k < size; k++)
+	work[i][j] += in[k][i] * in[k][j];
+  }
+  for (i=0; i < 3; i++) {
+    num = work[i][i];
+    for (j=0; j < 6; j++)
+      work[i][j] /= num;
+    for (k=0; k < 3; k++) {
+      if (k==i) continue;
+      num = work[k][i];
+      for (j=0; j < 6; j++)
+	work[k][j] -= work[i][j] * num;
+    }
+  }
+  for (i=0; i < size; i++)
+    for (j=0; j < 3; j++)
+      for (out[i][j]=k=0; k < 3; k++)
+	out[i][j] += work[j][k+3] * in[i][k];
+}
+
+void CLASS cam_xyz_coeff (double cam_xyz[4][3])
+{
+  double cam_rgb[4][3], inverse[4][3], num;
+  int i, j, k;
+
+  for (i=0; i < colors; i++)		/* Multiply out XYZ colorspace */
+    for (j=0; j < 3; j++)
+      for (cam_rgb[i][j] = k=0; k < 3; k++)
+	cam_rgb[i][j] += cam_xyz[i][k] * xyz_rgb[k][j];
+
+  for (i=0; i < colors; i++) {		/* Normalize cam_rgb so that */
+    for (num=j=0; j < 3; j++)		/* cam_rgb * (1,1,1) is (1,1,1,1) */
+      num += cam_rgb[i][j];
+    for (j=0; j < 3; j++)
+      cam_rgb[i][j] /= num;
+    pre_mul[i] = 1 / num;
+  }
+  pseudoinverse (cam_rgb, inverse, colors);
+  for (raw_color = i=0; i < 3; i++)
+    for (j=0; j < colors; j++)
+      rgb_cam[i][j] = inverse[j][i];
+#ifdef LIBRAW_LIBRARY_BUILD
+  color_flags.pre_mul_state = LIBRAW_COLORSTATE_CONST;
+  color_flags.rgb_cam_state = LIBRAW_COLORSTATE_CONST;
+#endif
+}
+
+#ifdef COLORCHECK
+void CLASS colorcheck()
+{
+#define NSQ 24
+// Coordinates of the GretagMacbeth ColorChecker squares
+// width, height, 1st_column, 1st_row
+  int cut[NSQ][4];			// you must set these
+// ColorChecker Chart under 6500-kelvin illumination
+  static const double gmb_xyY[NSQ][3] = {
+    { 0.400, 0.350, 10.1 },		// Dark Skin
+    { 0.377, 0.345, 35.8 },		// Light Skin
+    { 0.247, 0.251, 19.3 },		// Blue Sky
+    { 0.337, 0.422, 13.3 },		// Foliage
+    { 0.265, 0.240, 24.3 },		// Blue Flower
+    { 0.261, 0.343, 43.1 },		// Bluish Green
+    { 0.506, 0.407, 30.1 },		// Orange
+    { 0.211, 0.175, 12.0 },		// Purplish Blue
+    { 0.453, 0.306, 19.8 },		// Moderate Red
+    { 0.285, 0.202, 6.6 },		// Purple
+    { 0.380, 0.489, 44.3 },		// Yellow Green
+    { 0.473, 0.438, 43.1 },		// Orange Yellow
+    { 0.187, 0.129, 6.1 },		// Blue
+    { 0.305, 0.478, 23.4 },		// Green
+    { 0.539, 0.313, 12.0 },		// Red
+    { 0.448, 0.470, 59.1 },		// Yellow
+    { 0.364, 0.233, 19.8 },		// Magenta
+    { 0.196, 0.252, 19.8 },		// Cyan
+    { 0.310, 0.316, 90.0 },		// White
+    { 0.310, 0.316, 59.1 },		// Neutral 8
+    { 0.310, 0.316, 36.2 },		// Neutral 6.5
+    { 0.310, 0.316, 19.8 },		// Neutral 5
+    { 0.310, 0.316, 9.0 },		// Neutral 3.5
+    { 0.310, 0.316, 3.1 } };		// Black
+  double gmb_cam[NSQ][4], gmb_xyz[NSQ][3];
+  double inverse[NSQ][3], cam_xyz[4][3], num;
+  int c, i, j, k, sq, row, col, count[4];
+
+  memset (gmb_cam, 0, sizeof gmb_cam);
+  for (sq=0; sq < NSQ; sq++) {
+    FORCC count[c] = 0;
+    for   (row=cut[sq][3]; row < cut[sq][3]+cut[sq][1]; row++)
+      for (col=cut[sq][2]; col < cut[sq][2]+cut[sq][0]; col++) {
+	c = FC(row,col);
+	if (c >= colors) c -= 2;
+	gmb_cam[sq][c] += BAYER(row,col);
+	count[c]++;
+      }
+    FORCC gmb_cam[sq][c] = gmb_cam[sq][c]/count[c] - black;
+    gmb_xyz[sq][0] = gmb_xyY[sq][2] * gmb_xyY[sq][0] / gmb_xyY[sq][1];
+    gmb_xyz[sq][1] = gmb_xyY[sq][2];
+    gmb_xyz[sq][2] = gmb_xyY[sq][2] *
+		(1 - gmb_xyY[sq][0] - gmb_xyY[sq][1]) / gmb_xyY[sq][1];
+  }
+  pseudoinverse (gmb_xyz, inverse, NSQ);
+  for (i=0; i < colors; i++)
+    for (j=0; j < 3; j++)
+      for (cam_xyz[i][j] = k=0; k < NSQ; k++)
+	cam_xyz[i][j] += gmb_cam[k][i] * inverse[k][j];
+  cam_xyz_coeff (cam_xyz);
+#ifdef DCRAW_VERBOSE
+  if (verbose) {
+    printf ("    { \"%s %s\", %d,\n\t{", make, model, black);
+    num = 10000 / (cam_xyz[1][0] + cam_xyz[1][1] + cam_xyz[1][2]);
+    FORCC for (j=0; j < 3; j++)
+      printf ("%c%d", (c | j) ? ',':' ', (int) (cam_xyz[c][j] * num + 0.5));
+    puts (" } },");
+  }
+#endif
+#undef NSQ
+}
+#endif
+
+void CLASS hat_transform (float *temp, float *base, int st, int size, int sc)
+{
+  int i;
+  for (i=0; i < sc; i++)
+    temp[i] = 2*base[st*i] + base[st*(sc-i)] + base[st*(i+sc)];
+  for (; i+sc < size; i++)
+    temp[i] = 2*base[st*i] + base[st*(i-sc)] + base[st*(i+sc)];
+  for (; i < size; i++)
+    temp[i] = 2*base[st*i] + base[st*(i-sc)] + base[st*(2*size-2-(i+sc))];
+}
+
+#ifndef _OPENMP
+void CLASS wavelet_denoise()
+{
+  float *fimg=0, *temp, thold, mul[2], avg, diff;
+  int scale=1, size, lev, hpass, lpass, row, col, nc, c, i, wlast;
+  ushort *window[4];
+  static const float noise[] =
+  { 0.8002,0.2735,0.1202,0.0585,0.0291,0.0152,0.0080,0.0044 };
+
+#ifdef DCRAW_VERBOSE
+  if (verbose) fprintf (stderr,_("Wavelet denoising...\n"));
+#endif
+
+  while (maximum << scale < 0x10000) scale++;
+  maximum <<= --scale;
+  black <<= scale;
+  if ((size = iheight*iwidth) < 0x15550000)
+    fimg = (float *) malloc ((size*3 + iheight + iwidth) * sizeof *fimg);
+  merror (fimg, "wavelet_denoise()");
+  temp = fimg + size*3;
+  if ((nc = colors) == 3 && filters) nc++;
+  FORC(nc) {			/* denoise R,G1,B,G3 individually */
+    for (i=0; i < size; i++)
+        fimg[i] = 256 * sqrt((double)(image[i][c] << scale));
+    for (hpass=lev=0; lev < 5; lev++) {
+      lpass = size*((lev & 1)+1);
+      for (row=0; row < iheight; row++) {
+	hat_transform (temp, fimg+hpass+row*iwidth, 1, iwidth, 1 << lev);
+        for (col=0; col < iwidth; col++)
+	  fimg[lpass + row*iwidth + col] = temp[col] * 0.25;
+      }
+      for (col=0; col < iwidth; col++) {
+	hat_transform (temp, fimg+lpass+col, iwidth, iheight, 1 << lev);
+	for (row=0; row < iheight; row++)
+	  fimg[lpass + row*iwidth + col] = temp[row] * 0.25;
+      }
+      thold = threshold * noise[lev];
+      for (i=0; i < size; i++) {
+	fimg[hpass+i] -= fimg[lpass+i];
+	if	(fimg[hpass+i] < -thold) fimg[hpass+i] += thold;
+	else if (fimg[hpass+i] >  thold) fimg[hpass+i] -= thold;
+	else	 fimg[hpass+i] = 0;
+	if (hpass) fimg[i] += fimg[hpass+i];
+      }
+      hpass = lpass;
+    }
+    for (i=0; i < size; i++)
+      image[i][c] = CLIP(SQR(fimg[i]+fimg[lpass+i])/0x10000);
+  }
+  if (filters && colors == 3) {  /* pull G1 and G3 closer together */
+    for (row=0; row < 2; row++)
+      mul[row] = 0.125 * pre_mul[FC(row+1,0) | 1] / pre_mul[FC(row,0) | 1];
+    for (i=0; i < 4; i++)
+      window[i] = (ushort *) fimg + width*i;
+    for (wlast=-1, row=1; row < height-1; row++) {
+      while (wlast < row+1) {
+	for (wlast++, i=0; i < 4; i++)
+	  window[(i+3) & 3] = window[i];
+	for (col = FC(wlast,1) & 1; col < width; col+=2)
+	  window[2][col] = BAYER(wlast,col);
+      }
+      thold = threshold/512;
+      for (col = (FC(row,0) & 1)+1; col < width-1; col+=2) {
+	avg = ( window[0][col-1] + window[0][col+1] +
+		window[2][col-1] + window[2][col+1] - black*4 )
+	      * mul[row & 1] + (window[1][col] - black) * 0.5 + black;
+	avg = avg < 0 ? 0 : sqrt(avg);
+	diff = sqrt((double)(BAYER(row,col))) - avg;
+	if      (diff < -thold) diff += thold;
+	else if (diff >  thold) diff -= thold;
+	else diff = 0;
+	BAYER(row,col) = CLIP(SQR(avg+diff) + 0.5);
+      }
+    }
+  }
+  free (fimg);
+}
+#else
+void CLASS wavelet_denoise()
+{
+  float *fimg=0, *temp, thold, mul[2], avg, diff;
+  int scale=1, size, lev, hpass, lpass, row, col, nc, c, i, wlast;
+  ushort *window[4];
+  static const float noise[] =
+  { 0.8002,0.2735,0.1202,0.0585,0.0291,0.0152,0.0080,0.0044 };
+
+#ifdef DCRAW_VERBOSE
+  if (verbose) fprintf (stderr,_("Wavelet denoising...\n"));
+#endif
+
+  while (maximum << scale < 0x10000) scale++;
+  maximum <<= --scale;
+  black <<= scale;
+  if ((size = iheight*iwidth) < 0x15550000)
+    fimg = (float *) malloc ((size*3 + iheight + iwidth) * sizeof *fimg);
+  merror (fimg, "wavelet_denoise()");
+  temp = fimg + size*3;
+  if ((nc = colors) == 3 && filters) nc++;
+#ifdef LIBRAW_LIBRARY_BUILD
+#pragma omp parallel default(shared) private(i,col,row,thold,lev,lpass,hpass,temp) firstprivate(c,scale,size) 
+#endif
+  {
+      temp = (float*)malloc( (iheight + iwidth) * sizeof *fimg);
+    FORC(nc) {			/* denoise R,G1,B,G3 individually */
+#ifdef LIBRAW_LIBRARY_BUILD
+#pragma omp for
+#endif
+      for (i=0; i < size; i++)
+        fimg[i] = 256 * sqrt((double)(image[i][c] << scale));
+      for (hpass=lev=0; lev < 5; lev++) {
+	lpass = size*((lev & 1)+1);
+#ifdef LIBRAW_LIBRARY_BUILD
+#pragma omp for
+#endif
+	for (row=0; row < iheight; row++) {
+	  hat_transform (temp, fimg+hpass+row*iwidth, 1, iwidth, 1 << lev);
+	  for (col=0; col < iwidth; col++)
+	    fimg[lpass + row*iwidth + col] = temp[col] * 0.25;
+	}
+#ifdef LIBRAW_LIBRARY_BUILD
+#pragma omp for
+#endif
+	for (col=0; col < iwidth; col++) {
+	  hat_transform (temp, fimg+lpass+col, iwidth, iheight, 1 << lev);
+	  for (row=0; row < iheight; row++)
+	    fimg[lpass + row*iwidth + col] = temp[row] * 0.25;
+	}
+	thold = threshold * noise[lev];
+#ifdef LIBRAW_LIBRARY_BUILD
+#pragma omp for
+#endif
+	for (i=0; i < size; i++) {
+	  fimg[hpass+i] -= fimg[lpass+i];
+	  if	(fimg[hpass+i] < -thold) fimg[hpass+i] += thold;
+	  else if (fimg[hpass+i] >  thold) fimg[hpass+i] -= thold;
+	  else	 fimg[hpass+i] = 0;
+	  if (hpass) fimg[i] += fimg[hpass+i];
+	}
+	hpass = lpass;
+      }
+#ifdef LIBRAW_LIBRARY_BUILD
+#pragma omp for
+#endif
+      for (i=0; i < size; i++)
+	image[i][c] = CLIP(SQR(fimg[i]+fimg[lpass+i])/0x10000);
+    }
+    free(temp);
+  } /* end omp parallel */
+/* the following loops are hard to parallize, no idea yes,
+ * problem is wlast which is carrying dependency
+ * second part should be easyer, but did not yet get it right.
+ */
+  if (filters && colors == 3) {  /* pull G1 and G3 closer together */
+    for (row=0; row < 2; row++)
+      mul[row] = 0.125 * pre_mul[FC(row+1,0) | 1] / pre_mul[FC(row,0) | 1];
+    for (i=0; i < 4; i++)
+      window[i] = (ushort *) fimg + width*i;
+    for (wlast=-1, row=1; row < height-1; row++) {
+      while (wlast < row+1) {
+	for (wlast++, i=0; i < 4; i++)
+	  window[(i+3) & 3] = window[i];
+	for (col = FC(wlast,1) & 1; col < width; col+=2)
+	  window[2][col] = BAYER(wlast,col);
+      }
+      thold = threshold/512;
+      for (col = (FC(row,0) & 1)+1; col < width-1; col+=2) {
+	avg = ( window[0][col-1] + window[0][col+1] +
+		window[2][col-1] + window[2][col+1] - black*4 )
+	      * mul[row & 1] + (window[1][col] - black) * 0.5 + black;
+	avg = avg < 0 ? 0 : sqrt(avg);
+	diff = sqrt((double)BAYER(row,col)) - avg;
+	if      (diff < -thold) diff += thold;
+	else if (diff >  thold) diff -= thold;
+	else diff = 0;
+	BAYER(row,col) = CLIP(SQR(avg+diff) + 0.5);
+      }
+    }
+  }
+  free (fimg);
+}
+
+#endif
+
+void CLASS scale_colors()
+{
+  unsigned bottom, right, size, row, col, ur, uc, i, x, y, c, sum[8];
+  int val, dark, sat;
+  double dsum[8], dmin, dmax;
+  float scale_mul[4], fr, fc;
+  ushort *img=0, *pix;
+
+#ifdef LIBRAW_LIBRARY_BUILD
+  RUN_CALLBACK(LIBRAW_PROGRESS_SCALE_COLORS,0,2);
+#endif
+
+  if (user_mul[0])
+    memcpy (pre_mul, user_mul, sizeof pre_mul);
+  if (use_auto_wb || (use_camera_wb && cam_mul[0] == -1)) {
+    memset (dsum, 0, sizeof dsum);
+    bottom = MIN (greybox[1]+greybox[3], height);
+    right  = MIN (greybox[0]+greybox[2], width);
+    for (row=greybox[1]; row < bottom; row += 8)
+      for (col=greybox[0]; col < right; col += 8) {
+	memset (sum, 0, sizeof sum);
+	for (y=row; y < row+8 && y < bottom; y++)
+	  for (x=col; x < col+8 && x < right; x++)
+	    FORC4 {
+	      if (filters) {
+		c = FC(y,x);
+		val = BAYER(y,x);
+	      } else
+		val = image[y*width+x][c];
+	      if (val > maximum-25) goto skip_block;
+	      if ((val -= black) < 0) val = 0;
+	      sum[c] += val;
+	      sum[c+4]++;
+	      if (filters) break;
+	    }
+	FORC(8) dsum[c] += sum[c];
+skip_block: ;
+      }
+    FORC4 if (dsum[c]) pre_mul[c] = dsum[c+4] / dsum[c];
+#ifdef LIBRAW_LIBRARY_BUILD
+    color_flags.pre_mul_state = LIBRAW_COLORSTATE_CALCULATED;
+#endif
+  }
+  if (use_camera_wb && cam_mul[0] != -1) {
+    memset (sum, 0, sizeof sum);
+    for (row=0; row < 8; row++)
+      for (col=0; col < 8; col++) {
+	c = FC(row,col);
+	if ((val = white[row][col] - black) > 0)
+	  sum[c] += val;
+	sum[c+4]++;
+      }
+    if (sum[0] && sum[1] && sum[2] && sum[3])
+        {
+            FORC4 pre_mul[c] = (float) sum[c+4] / sum[c];
+#ifdef LIBRAW_LIBRARY_BUILD
+            color_flags.pre_mul_state = LIBRAW_COLORSTATE_CALCULATED;
+#endif
+        }
+    else if (cam_mul[0] && cam_mul[2])
+        {
+            memcpy (pre_mul, cam_mul, sizeof pre_mul);
+#ifdef LIBRAW_LIBRARY_BUILD
+            color_flags.pre_mul_state =color_flags.pre_mul_state;
+#endif
+        }
+    else
+        {
+#ifdef LIBRAW_LIBRARY_BUILD
+            imgdata.process_warnings |= LIBRAW_WARN_BAD_CAMERA_WB;
+#endif
+#ifdef DCRAW_VERBOSE
+            fprintf (stderr,_("%s: Cannot use camera white balance.\n"), ifname);
+#endif
+        }
+  }
+  if (pre_mul[3] == 0) pre_mul[3] = colors < 4 ? pre_mul[1] : 1;
+  dark = black;
+  sat = maximum;
+  if (threshold) wavelet_denoise();
+  maximum -= black;
+#ifdef LIBRAW_LIBRARY_BUILD
+  for(i=0;i<4;i++)
+      if(channel_maximum[i]>=black)
+          channel_maximum[i]-=black;
+      else
+          channel_maximum[i] = 0;
+#endif
+  for (dmin=DBL_MAX, dmax=c=0; c < 4; c++) {
+    if (dmin > pre_mul[c])
+	dmin = pre_mul[c];
+    if (dmax < pre_mul[c])
+	dmax = pre_mul[c];
+  }
+  if (!highlight) dmax = dmin;
+  FORC4 scale_mul[c] = (pre_mul[c] /= dmax) * 65535.0 / maximum;
+#ifdef DCRAW_VERBOSE
+  if (verbose) {
+    fprintf (stderr,
+      _("Scaling with darkness %d, saturation %d, and\nmultipliers"), dark, sat);
+    FORC4 fprintf (stderr, " %f", pre_mul[c]);
+    fputc ('\n', stderr);
+  }
+#endif
+  size = iheight*iwidth;
+  for (i=0; i < size*4; i++) {
+    val = image[0][i];
+    if (!val) continue;
+    val -= black;
+    val *= scale_mul[i & 3];
+    image[0][i] = CLIP(val);
+  }
+  if ((aber[0] != 1 || aber[2] != 1) && colors == 3) {
+#ifdef DCRAW_VERBOSE
+    if (verbose)
+      fprintf (stderr,_("Correcting chromatic aberration...\n"));
+#endif
+    for (c=0; c < 4; c+=2) {
+      if (aber[c] == 1) continue;
+      img = (ushort *) malloc (size * sizeof *img);
+      merror (img, "scale_colors()");
+      for (i=0; i < size; i++)
+	img[i] = image[i][c];
+      for (row=0; row < iheight; row++) {
+	ur = fr = (row - iheight*0.5) * aber[c] + iheight*0.5;
+	if (ur > iheight-2) continue;
+	fr -= ur;
+	for (col=0; col < iwidth; col++) {
+	  uc = fc = (col - iwidth*0.5) * aber[c] + iwidth*0.5;
+	  if (uc > iwidth-2) continue;
+	  fc -= uc;
+	  pix = img + ur*iwidth + uc;
+	  image[row*iwidth+col][c] =
+	    (pix[     0]*(1-fc) + pix[       1]*fc) * (1-fr) +
+	    (pix[iwidth]*(1-fc) + pix[iwidth+1]*fc) * fr;
+	}
+      }
+      free(img);
+    }
+  }
+#ifdef LIBRAW_LIBRARY_BUILD
+  RUN_CALLBACK(LIBRAW_PROGRESS_SCALE_COLORS,1,2);
+#endif
+}
+
+void CLASS pre_interpolate()
+{
+  ushort (*img)[4];
+  int row, col, c;
+
+#ifdef LIBRAW_LIBRARY_BUILD
+  RUN_CALLBACK(LIBRAW_PROGRESS_PRE_INTERPOLATE,0,2);
+#endif
+  if (shrink) {
+    if (half_size) {
+      height = iheight;
+      width  = iwidth;
+    } else {
+      img = (ushort (*)[4]) calloc (height*width, sizeof *img);
+      merror (img, "pre_interpolate()");
+      for (row=0; row < height; row++)
+	for (col=0; col < width; col++) {
+	  c = fc(row,col);
+	  img[row*width+col][c] = image[(row >> 1)*iwidth+(col >> 1)][c];
+	}
+      free (image);
+      image = img;
+      shrink = 0;
+    }
+  }
+  if (filters && colors == 3) {
+    if ((mix_green = four_color_rgb)) colors++;
+    else {
+      for (row = FC(1,0) >> 1; row < height; row+=2)
+	for (col = FC(row,1) & 1; col < width; col+=2)
+	  image[row*width+col][1] = image[row*width+col][3];
+      filters &= ~((filters & 0x55555555) << 1);
+    }
+  }
+  if (half_size) filters = 0;
+#ifdef LIBRAW_LIBRARY_BUILD
+  RUN_CALLBACK(LIBRAW_PROGRESS_PRE_INTERPOLATE,1,2);
+#endif
+}
+
+void CLASS border_interpolate (int border)
+{
+  unsigned row, col, y, x, f, c, sum[8];
+
+  for (row=0; row < height; row++)
+    for (col=0; col < width; col++) {
+      if (col==border && row >= border && row < height-border)
+	col = width-border;
+      memset (sum, 0, sizeof sum);
+      for (y=row-1; y != row+2; y++)
+	for (x=col-1; x != col+2; x++)
+	  if (y < height && x < width) {
+	    f = fc(y,x);
+	    sum[f] += image[y*width+x][f];
+	    sum[f+4]++;
+	  }
+      f = fc(row,col);
+      FORCC if (c != f && sum[c+4])
+	image[row*width+col][c] = sum[c] / sum[c+4];
+    }
+}
+
+void CLASS lin_interpolate()
+{
+  int code[16][16][32], *ip, sum[4];
+  int c, i, x, y, row, col, shift, color;
+  ushort *pix;
+
+#ifdef DCRAW_VERBOSE
+  if (verbose) fprintf (stderr,_("Bilinear interpolation...\n"));
+#endif
+
+#ifdef LIBRAW_LIBRARY_BUILD
+  RUN_CALLBACK(LIBRAW_PROGRESS_INTERPOLATE,0,3);
+#endif
+  border_interpolate(1);
+  for (row=0; row < 16; row++)
+    for (col=0; col < 16; col++) {
+      ip = code[row][col];
+      memset (sum, 0, sizeof sum);
+      for (y=-1; y <= 1; y++)
+	for (x=-1; x <= 1; x++) {
+	  shift = (y==0) + (x==0);
+	  if (shift == 2) continue;
+	  color = fc(row+y,col+x);
+	  *ip++ = (width*y + x)*4 + color;
+	  *ip++ = shift;
+	  *ip++ = color;
+	  sum[color] += 1 << shift;
+	}
+      FORCC
+	if (c != fc(row,col)) {
+	  *ip++ = c;
+	  *ip++ = 256 / sum[c];
+	}
+    }
+#ifdef LIBRAW_LIBRARY_BUILD
+  RUN_CALLBACK(LIBRAW_PROGRESS_INTERPOLATE,1,3);
+#endif
+  for (row=1; row < height-1; row++)
+    for (col=1; col < width-1; col++) {
+      pix = image[row*width+col];
+      ip = code[row & 15][col & 15];
+      memset (sum, 0, sizeof sum);
+      for (i=8; i--; ip+=3)
+	sum[ip[2]] += pix[ip[0]] << ip[1];
+      for (i=colors; --i; ip+=2)
+	pix[ip[0]] = sum[ip[0]] * ip[1] >> 8;
+    }
+#ifdef LIBRAW_LIBRARY_BUILD
+  RUN_CALLBACK(LIBRAW_PROGRESS_INTERPOLATE,2,3);
+#endif
+}
+
+/*
+   This algorithm is officially called:
+
+   "Interpolation using a Threshold-based variable number of gradients"
+
+   described in http://scien.stanford.edu/class/psych221/projects/99/tingchen/algodep/vargra.html
+
+   I've extended the basic idea to work with non-Bayer filter arrays.
+   Gradients are numbered clockwise from NW=0 to W=7.
+ */
+void CLASS vng_interpolate()
+{
+  static const signed char *cp, terms[] = {
+    -2,-2,+0,-1,0,0x01, -2,-2,+0,+0,1,0x01, -2,-1,-1,+0,0,0x01,
+    -2,-1,+0,-1,0,0x02, -2,-1,+0,+0,0,0x03, -2,-1,+0,+1,1,0x01,
+    -2,+0,+0,-1,0,0x06, -2,+0,+0,+0,1,0x02, -2,+0,+0,+1,0,0x03,
+    -2,+1,-1,+0,0,0x04, -2,+1,+0,-1,1,0x04, -2,+1,+0,+0,0,0x06,
+    -2,+1,+0,+1,0,0x02, -2,+2,+0,+0,1,0x04, -2,+2,+0,+1,0,0x04,
+    -1,-2,-1,+0,0,0x80, -1,-2,+0,-1,0,0x01, -1,-2,+1,-1,0,0x01,
+    -1,-2,+1,+0,1,0x01, -1,-1,-1,+1,0,0x88, -1,-1,+1,-2,0,0x40,
+    -1,-1,+1,-1,0,0x22, -1,-1,+1,+0,0,0x33, -1,-1,+1,+1,1,0x11,
+    -1,+0,-1,+2,0,0x08, -1,+0,+0,-1,0,0x44, -1,+0,+0,+1,0,0x11,
+    -1,+0,+1,-2,1,0x40, -1,+0,+1,-1,0,0x66, -1,+0,+1,+0,1,0x22,
+    -1,+0,+1,+1,0,0x33, -1,+0,+1,+2,1,0x10, -1,+1,+1,-1,1,0x44,
+    -1,+1,+1,+0,0,0x66, -1,+1,+1,+1,0,0x22, -1,+1,+1,+2,0,0x10,
+    -1,+2,+0,+1,0,0x04, -1,+2,+1,+0,1,0x04, -1,+2,+1,+1,0,0x04,
+    +0,-2,+0,+0,1,0x80, +0,-1,+0,+1,1,0x88, +0,-1,+1,-2,0,0x40,
+    +0,-1,+1,+0,0,0x11, +0,-1,+2,-2,0,0x40, +0,-1,+2,-1,0,0x20,
+    +0,-1,+2,+0,0,0x30, +0,-1,+2,+1,1,0x10, +0,+0,+0,+2,1,0x08,
+    +0,+0,+2,-2,1,0x40, +0,+0,+2,-1,0,0x60, +0,+0,+2,+0,1,0x20,
+    +0,+0,+2,+1,0,0x30, +0,+0,+2,+2,1,0x10, +0,+1,+1,+0,0,0x44,
+    +0,+1,+1,+2,0,0x10, +0,+1,+2,-1,1,0x40, +0,+1,+2,+0,0,0x60,
+    +0,+1,+2,+1,0,0x20, +0,+1,+2,+2,0,0x10, +1,-2,+1,+0,0,0x80,
+    +1,-1,+1,+1,0,0x88, +1,+0,+1,+2,0,0x08, +1,+0,+2,-1,0,0x40,
+    +1,+0,+2,+1,0,0x10
+  }, chood[] = { -1,-1, -1,0, -1,+1, 0,+1, +1,+1, +1,0, +1,-1, 0,-1 };
+  ushort (*brow[5])[4], *pix;
+  int prow=7, pcol=1, *ip, *code[16][16], gval[8], gmin, gmax, sum[4];
+  int row, col, x, y, x1, x2, y1, y2, t, weight, grads, color, diag;
+  int g, diff, thold, num, c;
+  lin_interpolate();
+#ifdef DCRAW_VERBOSE
+  if (verbose) fprintf (stderr,_("VNG interpolation...\n"));
+#endif
+
+  if (filters == 1) prow = pcol = 15;
+  ip = (int *) calloc ((prow+1)*(pcol+1), 1280);
+  merror (ip, "vng_interpolate()");
+  for (row=0; row <= prow; row++)		/* Precalculate for VNG */
+    for (col=0; col <= pcol; col++) {
+      code[row][col] = ip;
+      for (cp=terms, t=0; t < 64; t++) {
+	y1 = *cp++;  x1 = *cp++;
+	y2 = *cp++;  x2 = *cp++;
+	weight = *cp++;
+	grads = *cp++;
+	color = fc(row+y1,col+x1);
+	if (fc(row+y2,col+x2) != color) continue;
+	diag = (fc(row,col+1) == color && fc(row+1,col) == color) ? 2:1;
+	if (abs(y1-y2) == diag && abs(x1-x2) == diag) continue;
+	*ip++ = (y1*width + x1)*4 + color;
+	*ip++ = (y2*width + x2)*4 + color;
+	*ip++ = weight;
+	for (g=0; g < 8; g++)
+	  if (grads & 1<<g) *ip++ = g;
+	*ip++ = -1;
+      }
+      *ip++ = INT_MAX;
+      for (cp=chood, g=0; g < 8; g++) {
+	y = *cp++;  x = *cp++;
+	*ip++ = (y*width + x) * 4;
+	color = fc(row,col);
+	if (fc(row+y,col+x) != color && fc(row+y*2,col+x*2) == color)
+	  *ip++ = (y*width + x) * 8 + color;
+	else
+	  *ip++ = 0;
+      }
+    }
+  brow[4] = (ushort (*)[4]) calloc (width*3, sizeof **brow);
+  merror (brow[4], "vng_interpolate()");
+  for (row=0; row < 3; row++)
+    brow[row] = brow[4] + row*width;
+  for (row=2; row < height-2; row++) {		/* Do VNG interpolation */
+#ifdef LIBRAW_LIBRARY_BUILD
+      if(!((row-2)%256))RUN_CALLBACK(LIBRAW_PROGRESS_INTERPOLATE,(row-2)/256+1,((height-3)/256)+1);
+#endif
+    for (col=2; col < width-2; col++) {
+      pix = image[row*width+col];
+      ip = code[row & prow][col & pcol];
+      memset (gval, 0, sizeof gval);
+      while ((g = ip[0]) != INT_MAX) {		/* Calculate gradients */
+	diff = ABS(pix[g] - pix[ip[1]]) << ip[2];
+	gval[ip[3]] += diff;
+	ip += 5;
+	if ((g = ip[-1]) == -1) continue;
+	gval[g] += diff;
+	while ((g = *ip++) != -1)
+	  gval[g] += diff;
+      }
+      ip++;
+      gmin = gmax = gval[0];			/* Choose a threshold */
+      for (g=1; g < 8; g++) {
+	if (gmin > gval[g]) gmin = gval[g];
+	if (gmax < gval[g]) gmax = gval[g];
+      }
+      if (gmax == 0) {
+	memcpy (brow[2][col], pix, sizeof *image);
+	continue;
+      }
+      thold = gmin + (gmax >> 1);
+      memset (sum, 0, sizeof sum);
+      color = fc(row,col);
+      for (num=g=0; g < 8; g++,ip+=2) {		/* Average the neighbors */
+	if (gval[g] <= thold) {
+	  FORCC
+	    if (c == color && ip[1])
+	      sum[c] += (pix[c] + pix[ip[1]]) >> 1;
+	    else
+	      sum[c] += pix[ip[0] + c];
+	  num++;
+	}
+      }
+      FORCC {					/* Save to buffer */
+	t = pix[color];
+	if (c != color)
+	  t += (sum[c] - sum[color]) / num;
+	brow[2][col][c] = CLIP(t);
+      }
+    }
+    if (row > 3)				/* Write buffer to image */
+      memcpy (image[(row-2)*width+2], brow[0]+2, (width-4)*sizeof *image);
+    for (g=0; g < 4; g++)
+      brow[(g-1) & 3] = brow[g];
+  }
+  memcpy (image[(row-2)*width+2], brow[0]+2, (width-4)*sizeof *image);
+  memcpy (image[(row-1)*width+2], brow[1]+2, (width-4)*sizeof *image);
+  free (brow[4]);
+  free (code[0][0]);
+}
+
+/*
+   Patterned Pixel Grouping Interpolation by Alain Desbiolles
+*/
+void CLASS ppg_interpolate()
+{
+  int dir[5] = { 1, width, -1, -width, 1 };
+  int row, col, diff[2], guess[2], c, d, i;
+  ushort (*pix)[4];
+
+  border_interpolate(3);
+#ifdef DCRAW_VERBOSE
+  if (verbose) fprintf (stderr,_("PPG interpolation...\n"));
+#endif
+
+/*  Fill in the green layer with gradients and pattern recognition: */
+#ifdef LIBRAW_LIBRARY_BUILD
+  RUN_CALLBACK(LIBRAW_PROGRESS_INTERPOLATE,0,3);
+#endif
+  for (row=3; row < height-3; row++)
+    for (col=3+(FC(row,3) & 1), c=FC(row,col); col < width-3; col+=2) {
+      pix = image + row*width+col;
+      for (i=0; (d=dir[i]) > 0; i++) {
+	guess[i] = (pix[-d][1] + pix[0][c] + pix[d][1]) * 2
+		      - pix[-2*d][c] - pix[2*d][c];
+	diff[i] = ( ABS(pix[-2*d][c] - pix[ 0][c]) +
+		    ABS(pix[ 2*d][c] - pix[ 0][c]) +
+		    ABS(pix[  -d][1] - pix[ d][1]) ) * 3 +
+		  ( ABS(pix[ 3*d][1] - pix[ d][1]) +
+		    ABS(pix[-3*d][1] - pix[-d][1]) ) * 2;
+      }
+      d = dir[i = diff[0] > diff[1]];
+      pix[0][1] = ULIM(guess[i] >> 2, pix[d][1], pix[-d][1]);
+    }
+/*  Calculate red and blue for each green pixel:		*/
+#ifdef LIBRAW_LIBRARY_BUILD
+  RUN_CALLBACK(LIBRAW_PROGRESS_INTERPOLATE,1,3);
+#endif
+  for (row=1; row < height-1; row++)
+    for (col=1+(FC(row,2) & 1), c=FC(row,col+1); col < width-1; col+=2) {
+      pix = image + row*width+col;
+      for (i=0; (d=dir[i]) > 0; c=2-c, i++)
+	pix[0][c] = CLIP((pix[-d][c] + pix[d][c] + 2*pix[0][1]
+			- pix[-d][1] - pix[d][1]) >> 1);
+    }
+/*  Calculate blue for red pixels and vice versa:		*/
+#ifdef LIBRAW_LIBRARY_BUILD
+  RUN_CALLBACK(LIBRAW_PROGRESS_INTERPOLATE,2,3);
+#endif
+  for (row=1; row < height-1; row++)
+    for (col=1+(FC(row,1) & 1), c=2-FC(row,col); col < width-1; col+=2) {
+      pix = image + row*width+col;
+      for (i=0; (d=dir[i]+dir[i+1]) > 0; i++) {
+	diff[i] = ABS(pix[-d][c] - pix[d][c]) +
+		  ABS(pix[-d][1] - pix[0][1]) +
+		  ABS(pix[ d][1] - pix[0][1]);
+	guess[i] = pix[-d][c] + pix[d][c] + 2*pix[0][1]
+		 - pix[-d][1] - pix[d][1];
+      }
+      if (diff[0] != diff[1])
+	pix[0][c] = CLIP(guess[diff[0] > diff[1]] >> 1);
+      else
+	pix[0][c] = CLIP((guess[0]+guess[1]) >> 2);
+    }
+}
+
+/*
+   Adaptive Homogeneity-Directed interpolation is based on
+   the work of Keigo Hirakawa, Thomas Parks, and Paul Lee.
+ */
+#define TS 256		/* Tile Size */
+#ifndef _OPENMP
+void CLASS ahd_interpolate()
+{
+  int i, j, k, top, left, row, col, tr, tc, c, d, val, hm[2];
+  ushort (*pix)[4], (*rix)[3];
+  static const int dir[4] = { -1, 1, -TS, TS };
+  unsigned ldiff[2][4], abdiff[2][4], leps, abeps;
+  float r, cbrt[0x10000], xyz[3], xyz_cam[3][4];
+  ushort (*rgb)[TS][TS][3];
+   short (*lab)[TS][TS][3], (*lix)[3];
+   char (*homo)[TS][TS], *buffer;
+
+#ifdef DCRAW_VERBOSE
+  if (verbose) fprintf (stderr,_("AHD interpolation...\n"));
+#endif
+
+  for (i=0; i < 0x10000; i++) {
+    r = i / 65535.0;
+    cbrt[i] = r > 0.008856 ? pow((double)r,1/3.0) : 7.787*r + 16/116.0;
+  }
+  for (i=0; i < 3; i++)
+    for (j=0; j < colors; j++)
+      for (xyz_cam[i][j] = k=0; k < 3; k++)
+	xyz_cam[i][j] += xyz_rgb[i][k] * rgb_cam[k][j] / d65_white[i];
+
+  border_interpolate(5);
+  buffer = (char *) malloc (26*TS*TS);		/* 1664 kB */
+  merror (buffer, "ahd_interpolate()");
+  rgb  = (ushort(*)[TS][TS][3]) buffer;
+  lab  = (short (*)[TS][TS][3])(buffer + 12*TS*TS);
+  homo = (char  (*)[TS][TS])   (buffer + 24*TS*TS);
+
+  for (top=2; top < height-5; top += TS-6)
+  {    
+      
+#ifdef LIBRAW_LIBRARY_BUILD
+      RUN_CALLBACK(LIBRAW_PROGRESS_INTERPOLATE,(top-2)/(TS-6),(height-7)/(TS-6)+1);
+#endif
+    for (left=2; left < width-5; left += TS-6) {
+
+/*  Interpolate green horizontally and vertically:		*/
+      for (row = top; row < top+TS && row < height-2; row++) {
+	col = left + (FC(row,left) & 1);
+	for (c = FC(row,col); col < left+TS && col < width-2; col+=2) {
+	  pix = image + row*width+col;
+	  val = ((pix[-1][1] + pix[0][c] + pix[1][1]) * 2
+		- pix[-2][c] - pix[2][c]) >> 2;
+	  rgb[0][row-top][col-left][1] = ULIM(val,pix[-1][1],pix[1][1]);
+	  val = ((pix[-width][1] + pix[0][c] + pix[width][1]) * 2
+		- pix[-2*width][c] - pix[2*width][c]) >> 2;
+	  rgb[1][row-top][col-left][1] = ULIM(val,pix[-width][1],pix[width][1]);
+	}
+      }
+/*  Interpolate red and blue, and convert to CIELab:		*/
+      for (d=0; d < 2; d++)
+	for (row=top+1; row < top+TS-1 && row < height-3; row++)
+	  for (col=left+1; col < left+TS-1 && col < width-3; col++) {
+	    pix = image + row*width+col;
+	    rix = &rgb[d][row-top][col-left];
+	    lix = &lab[d][row-top][col-left];
+	    if ((c = 2 - FC(row,col)) == 1) {
+	      c = FC(row+1,col);
+	      val = pix[0][1] + (( pix[-1][2-c] + pix[1][2-c]
+				 - rix[-1][1] - rix[1][1] ) >> 1);
+	      rix[0][2-c] = CLIP(val);
+	      val = pix[0][1] + (( pix[-width][c] + pix[width][c]
+				 - rix[-TS][1] - rix[TS][1] ) >> 1);
+	    } else
+	      val = rix[0][1] + (( pix[-width-1][c] + pix[-width+1][c]
+				 + pix[+width-1][c] + pix[+width+1][c]
+				 - rix[-TS-1][1] - rix[-TS+1][1]
+				 - rix[+TS-1][1] - rix[+TS+1][1] + 1) >> 2);
+	    rix[0][c] = CLIP(val);
+	    c = FC(row,col);
+	    rix[0][c] = pix[0][c];
+	    xyz[0] = xyz[1] = xyz[2] = 0.5;
+	    FORCC {
+	      xyz[0] += xyz_cam[0][c] * rix[0][c];
+	      xyz[1] += xyz_cam[1][c] * rix[0][c];
+	      xyz[2] += xyz_cam[2][c] * rix[0][c];
+	    }
+	    xyz[0] = cbrt[CLIP((int) xyz[0])];
+	    xyz[1] = cbrt[CLIP((int) xyz[1])];
+	    xyz[2] = cbrt[CLIP((int) xyz[2])];
+	    lix[0][0] = 64 * (116 * xyz[1] - 16);
+	    lix[0][1] = 64 * 500 * (xyz[0] - xyz[1]);
+	    lix[0][2] = 64 * 200 * (xyz[1] - xyz[2]);
+	  }
+/*  Build homogeneity maps from the CIELab images:		*/
+      memset (homo, 0, 2*TS*TS);
+      for (row=top+2; row < top+TS-2 && row < height-4; row++) {
+	tr = row-top;
+	for (col=left+2; col < left+TS-2 && col < width-4; col++) {
+	  tc = col-left;
+	  for (d=0; d < 2; d++) {
+	    lix = &lab[d][tr][tc];
+	    for (i=0; i < 4; i++) {
+	       ldiff[d][i] = ABS(lix[0][0]-lix[dir[i]][0]);
+	      abdiff[d][i] = SQR(lix[0][1]-lix[dir[i]][1])
+			   + SQR(lix[0][2]-lix[dir[i]][2]);
+	    }
+	  }
+	  leps = MIN(MAX(ldiff[0][0],ldiff[0][1]),
+		     MAX(ldiff[1][2],ldiff[1][3]));
+	  abeps = MIN(MAX(abdiff[0][0],abdiff[0][1]),
+		      MAX(abdiff[1][2],abdiff[1][3]));
+	  for (d=0; d < 2; d++)
+	    for (i=0; i < 4; i++)
+	      if (ldiff[d][i] <= leps && abdiff[d][i] <= abeps)
+		homo[d][tr][tc]++;
+	}
+      }
+/*  Combine the most homogenous pixels for the final result:	*/
+      for (row=top+3; row < top+TS-3 && row < height-5; row++) {
+	tr = row-top;
+	for (col=left+3; col < left+TS-3 && col < width-5; col++) {
+	  tc = col-left;
+	  for (d=0; d < 2; d++)
+	    for (hm[d]=0, i=tr-1; i <= tr+1; i++)
+	      for (j=tc-1; j <= tc+1; j++)
+		hm[d] += homo[d][i][j];
+	  if (hm[0] != hm[1])
+	    FORC3 image[row*width+col][c] = rgb[hm[1] > hm[0]][tr][tc][c];
+	  else
+	    FORC3 image[row*width+col][c] =
+		(rgb[0][tr][tc][c] + rgb[1][tr][tc][c]) >> 1;
+	}
+      }
+    }
+  }
+  free (buffer);
+}
+#else
+void CLASS ahd_interpolate()
+{
+  int i, j, k, top, left, row, col, tr, tc, c, d, val, hm[2];
+  ushort (*pix)[4], (*rix)[3];
+  static const int dir[4] = { -1, 1, -TS, TS };
+  unsigned ldiff[2][4], abdiff[2][4], leps, abeps;
+  float r, cbrt[0x10000], xyz[3], xyz_cam[3][4];
+  ushort (*rgb)[TS][TS][3];
+  short (*lab)[TS][TS][3], (*lix)[3];
+  char (*homo)[TS][TS], *buffer;
+
+#ifdef DCRAW_VERBOSE
+  if (verbose) fprintf (stderr,_("AHD interpolation...\n"));
+#endif
+
+  for (i=0; i < 0x10000; i++) {
+    r = i / 65535.0;
+    cbrt[i] = r > 0.008856 ? pow((double)r,1/3.0) : 7.787*r + 16/116.0;
+  }
+  for (i=0; i < 3; i++)
+    for (j=0; j < colors; j++)
+      for (xyz_cam[i][j] = k=0; k < 3; k++)
+	xyz_cam[i][j] += xyz_rgb[i][k] * rgb_cam[k][j] / d65_white[i];
+
+  border_interpolate(5);
+
+#ifdef LIBRAW_LIBRARY_BUILD
+#pragma omp parallel private(buffer,rgb,lab,homo,top,left,row,c,col,pix,val,d,rix,xyz,lix,tc,tr,ldiff,abdiff,leps,abeps,hm,i,j) firstprivate(cbrt) shared(xyz_cam)
+#endif
+  {
+    buffer = (char *) malloc (26*TS*TS);		/* 1664 kB */
+    merror (buffer, "ahd_interpolate()");
+    rgb  = (ushort(*)[TS][TS][3]) buffer;
+    lab  = (short (*)[TS][TS][3])(buffer + 12*TS*TS);
+    homo = (char  (*)[TS][TS])   (buffer + 24*TS*TS);
+
+#pragma omp for schedule(dynamic)
+    for (top=2; top < height-5; top += TS-6){
+#ifdef LIBRAW_LIBRARY_BUILD
+        RUN_CALLBACK(LIBRAW_PROGRESS_INTERPOLATE,(top-2)/(TS-6)+1,(height-7)/(TS-6)+1);
+#endif
+      for (left=2; left < width-5; left += TS-6) {
+
+  /*  Interpolate green horizontally and vertically:		*/
+        for (row = top; row < top+TS && row < height-2; row++) {
+          col = left + (FC(row,left) & 1);
+          for (c = FC(row,col); col < left+TS && col < width-2; col+=2) {
+            pix = image + row*width+col;
+            val = ((pix[-1][1] + pix[0][c] + pix[1][1]) * 2
+                  - pix[-2][c] - pix[2][c]) >> 2;
+            rgb[0][row-top][col-left][1] = ULIM(val,pix[-1][1],pix[1][1]);
+            val = ((pix[-width][1] + pix[0][c] + pix[width][1]) * 2
+                  - pix[-2*width][c] - pix[2*width][c]) >> 2;
+            rgb[1][row-top][col-left][1] = ULIM(val,pix[-width][1],pix[width][1]);
+          }
+        }
+  /*  Interpolate red and blue, and convert to CIELab:		*/
+        for (d=0; d < 2; d++)
+          for (row=top+1; row < top+TS-1 && row < height-3; row++)
+            for (col=left+1; col < left+TS-1 && col < width-3; col++) {
+              pix = image + row*width+col;
+              rix = &rgb[d][row-top][col-left];
+              lix = &lab[d][row-top][col-left];
+              if ((c = 2 - FC(row,col)) == 1) {
+                c = FC(row+1,col);
+                val = pix[0][1] + (( pix[-1][2-c] + pix[1][2-c]
+                                   - rix[-1][1] - rix[1][1] ) >> 1);
+                rix[0][2-c] = CLIP(val);
+                val = pix[0][1] + (( pix[-width][c] + pix[width][c]
+                                   - rix[-TS][1] - rix[TS][1] ) >> 1);
+              } else
+                val = rix[0][1] + (( pix[-width-1][c] + pix[-width+1][c]
+                                   + pix[+width-1][c] + pix[+width+1][c]
+                                   - rix[-TS-1][1] - rix[-TS+1][1]
+                                   - rix[+TS-1][1] - rix[+TS+1][1] + 1) >> 2);
+              rix[0][c] = CLIP(val);
+              c = FC(row,col);
+              rix[0][c] = pix[0][c];
+              xyz[0] = xyz[1] = xyz[2] = 0.5;
+              FORCC {
+                xyz[0] += xyz_cam[0][c] * rix[0][c];
+                xyz[1] += xyz_cam[1][c] * rix[0][c];
+                xyz[2] += xyz_cam[2][c] * rix[0][c];
+              }
+              xyz[0] = cbrt[CLIP((int) xyz[0])];
+              xyz[1] = cbrt[CLIP((int) xyz[1])];
+              xyz[2] = cbrt[CLIP((int) xyz[2])];
+              lix[0][0] = 64 * (116 * xyz[1] - 16);
+              lix[0][1] = 64 * 500 * (xyz[0] - xyz[1]);
+              lix[0][2] = 64 * 200 * (xyz[1] - xyz[2]);
+            }
+  /*  Build homogeneity maps from the CIELab images:		*/
+        memset (homo, 0, 2*TS*TS);
+        for (row=top+2; row < top+TS-2 && row < height-4; row++) {
+          tr = row-top;
+          for (col=left+2; col < left+TS-2 && col < width-4; col++) {
+            tc = col-left;
+            for (d=0; d < 2; d++) {
+              lix = &lab[d][tr][tc];
+              for (i=0; i < 4; i++) {
+                 ldiff[d][i] = ABS(lix[0][0]-lix[dir[i]][0]);
+                abdiff[d][i] = SQR(lix[0][1]-lix[dir[i]][1])
+                             + SQR(lix[0][2]-lix[dir[i]][2]);
+              }
+            }
+            leps = MIN(MAX(ldiff[0][0],ldiff[0][1]),
+                       MAX(ldiff[1][2],ldiff[1][3]));
+            abeps = MIN(MAX(abdiff[0][0],abdiff[0][1]),
+                        MAX(abdiff[1][2],abdiff[1][3]));
+            for (d=0; d < 2; d++)
+              for (i=0; i < 4; i++)
+                if (ldiff[d][i] <= leps && abdiff[d][i] <= abeps)
+                  homo[d][tr][tc]++;
+          }
+        }
+  /*  Combine the most homogenous pixels for the final result:	*/
+        for (row=top+3; row < top+TS-3 && row < height-5; row++) {
+          tr = row-top;
+          for (col=left+3; col < left+TS-3 && col < width-5; col++) {
+            tc = col-left;
+            for (d=0; d < 2; d++)
+              for (hm[d]=0, i=tr-1; i <= tr+1; i++)
+                for (j=tc-1; j <= tc+1; j++)
+                  hm[d] += homo[d][i][j];
+            if (hm[0] != hm[1])
+              FORC3 image[row*width+col][c] = rgb[hm[1] > hm[0]][tr][tc][c];
+            else
+              FORC3 image[row*width+col][c] =
+                  (rgb[0][tr][tc][c] + rgb[1][tr][tc][c]) >> 1;
+          }
+        }
+      }
+    }
+    free (buffer);
+  }
+}
+
+#endif
+#undef TS
+
+void CLASS median_filter()
+{
+  ushort (*pix)[4];
+  int pass, c, i, j, k, med[9];
+  static const uchar opt[] =	/* Optimal 9-element median search */
+  { 1,2, 4,5, 7,8, 0,1, 3,4, 6,7, 1,2, 4,5, 7,8,
+    0,3, 5,8, 4,7, 3,6, 1,4, 2,5, 4,7, 4,2, 6,4, 4,2 };
+
+  for (pass=1; pass <= med_passes; pass++) {
+#ifdef LIBRAW_LIBRARY_BUILD
+      RUN_CALLBACK(LIBRAW_PROGRESS_MEDIAN_FILTER,pass-1,med_passes);
+#endif
+#ifdef DCRAW_VERBOSE
+    if (verbose)
+      fprintf (stderr,_("Median filter pass %d...\n"), pass);
+#endif
+    for (c=0; c < 3; c+=2) {
+      for (pix = image; pix < image+width*height; pix++)
+	pix[0][3] = pix[0][c];
+      for (pix = image+width; pix < image+width*(height-1); pix++) {
+	if ((pix-image+1) % width < 2) continue;
+	for (k=0, i = -width; i <= width; i += width)
+	  for (j = i-1; j <= i+1; j++)
+	    med[k++] = pix[j][3] - pix[j][1];
+	for (i=0; i < sizeof opt; i+=2)
+	  if     (med[opt[i]] > med[opt[i+1]])
+	    SWAP (med[opt[i]] , med[opt[i+1]]);
+	pix[0][c] = CLIP(med[4] + pix[0][1]);
+      }
+    }
+  }
+}
+
+void CLASS blend_highlights()
+{
+  int clip=INT_MAX, row, col, c, i, j;
+  static const float trans[2][4][4] =
+  { { { 1,1,1 }, { 1.7320508,-1.7320508,0 }, { -1,-1,2 } },
+    { { 1,1,1,1 }, { 1,-1,1,-1 }, { 1,1,-1,-1 }, { 1,-1,-1,1 } } };
+  static const float itrans[2][4][4] =
+  { { { 1,0.8660254,-0.5 }, { 1,-0.8660254,-0.5 }, { 1,0,1 } },
+    { { 1,1,1,1 }, { 1,-1,1,-1 }, { 1,1,-1,-1 }, { 1,-1,-1,1 } } };
+  float cam[2][4], lab[2][4], sum[2], chratio;
+
+  if ((unsigned) (colors-3) > 1) return;
+#ifdef DCRAW_VERBOSE
+  if (verbose) fprintf (stderr,_("Blending highlights...\n"));
+#endif
+  FORCC if (clip > (i = 65535*pre_mul[c])) clip = i;
+#ifdef LIBRAW_LIBRARY_BUILD
+  RUN_CALLBACK(LIBRAW_PROGRESS_HIGHLIGHTS,0,2);
+#endif
+  for (row=0; row < height; row++)
+    for (col=0; col < width; col++) {
+      FORCC if (image[row*width+col][c] > clip) break;
+      if (c == colors) continue;
+      FORCC {
+	cam[0][c] = image[row*width+col][c];
+	cam[1][c] = MIN(cam[0][c],clip);
+      }
+      for (i=0; i < 2; i++) {
+	FORCC for (lab[i][c]=j=0; j < colors; j++)
+	  lab[i][c] += trans[colors-3][c][j] * cam[i][j];
+	for (sum[i]=0,c=1; c < colors; c++)
+	  sum[i] += SQR(lab[i][c]);
+      }
+      chratio = sqrt(sum[1]/sum[0]);
+      for (c=1; c < colors; c++)
+	lab[0][c] *= chratio;
+      FORCC for (cam[0][c]=j=0; j < colors; j++)
+	cam[0][c] += itrans[colors-3][c][j] * lab[0][j];
+      FORCC image[row*width+col][c] = cam[0][c] / colors;
+    }
+#ifdef LIBRAW_LIBRARY_BUILD
+  RUN_CALLBACK(LIBRAW_PROGRESS_HIGHLIGHTS,1,2);
+#endif
+}
+
+#define SCALE (4 >> shrink)
+void CLASS recover_highlights()
+{
+  float *map, sum, wgt, grow;
+  int hsat[4], count, spread, change, val, i;
+  unsigned high, wide, mrow, mcol, row, col, kc, c, d, y, x;
+  ushort *pixel;
+  static const signed char dir[8][2] =
+    { {-1,-1}, {-1,0}, {-1,1}, {0,1}, {1,1}, {1,0}, {1,-1}, {0,-1} };
+
+#ifdef DCRAW_VERBOSE
+  if (verbose) fprintf (stderr,_("Rebuilding highlights...\n"));
+#endif
+
+  grow = pow (2.0, 4.0-highlight);
+  FORCC hsat[c] = 32000 * pre_mul[c];
+  for (kc=0, c=1; c < colors; c++)
+    if (pre_mul[kc] < pre_mul[c]) kc = c;
+  high = height / SCALE;
+  wide =  width / SCALE;
+  map = (float *) calloc (high*wide, sizeof *map);
+  merror (map, "recover_highlights()");
+  FORCC if (c != kc) {
+#ifdef LIBRAW_LIBRARY_BUILD
+      RUN_CALLBACK(LIBRAW_PROGRESS_HIGHLIGHTS,c-1,colors-1);
+#endif
+    memset (map, 0, high*wide*sizeof *map);
+    for (mrow=0; mrow < high; mrow++)
+      for (mcol=0; mcol < wide; mcol++) {
+	sum = wgt = count = 0;
+	for (row = mrow*SCALE; row < (mrow+1)*SCALE; row++)
+	  for (col = mcol*SCALE; col < (mcol+1)*SCALE; col++) {
+	    pixel = image[row*width+col];
+	    if (pixel[c] / hsat[c] == 1 && pixel[kc] > 24000) {
+	      sum += pixel[c];
+	      wgt += pixel[kc];
+	      count++;
+	    }
+	  }
+	if (count == SCALE*SCALE)
+	  map[mrow*wide+mcol] = sum / wgt;
+      }
+    for (spread = 32/grow; spread--; ) {
+      for (mrow=0; mrow < high; mrow++)
+	for (mcol=0; mcol < wide; mcol++) {
+	  if (map[mrow*wide+mcol]) continue;
+	  sum = count = 0;
+	  for (d=0; d < 8; d++) {
+	    y = mrow + dir[d][0];
+	    x = mcol + dir[d][1];
+	    if (y < high && x < wide && map[y*wide+x] > 0) {
+	      sum  += (1 + (d & 1)) * map[y*wide+x];
+	      count += 1 + (d & 1);
+	    }
+	  }
+	  if (count > 3)
+	    map[mrow*wide+mcol] = - (sum+grow) / (count+grow);
+	}
+      for (change=i=0; i < high*wide; i++)
+	if (map[i] < 0) {
+	  map[i] = -map[i];
+	  change = 1;
+	}
+      if (!change) break;
+    }
+    for (i=0; i < high*wide; i++)
+      if (map[i] == 0) map[i] = 1;
+    for (mrow=0; mrow < high; mrow++)
+      for (mcol=0; mcol < wide; mcol++) {
+	for (row = mrow*SCALE; row < (mrow+1)*SCALE; row++)
+	  for (col = mcol*SCALE; col < (mcol+1)*SCALE; col++) {
+	    pixel = image[row*width+col];
+	    if (pixel[c] / hsat[c] > 1) {
+	      val = pixel[kc] * map[mrow*wide+mcol];
+	      if (pixel[c] < val) pixel[c] = CLIP(val);
+	    }
+	  }
+      }
+  }
+  free (map);
+}
+#undef SCALE
+
+void CLASS tiff_get (unsigned base,
+	unsigned *tag, unsigned *type, unsigned *len, unsigned *save)
+{
+  *tag  = get2();
+  *type = get2();
+  *len  = get4();
+  *save = ftell(ifp) + 4;
+  if (*len * ("11124811248488"[*type < 14 ? *type:0]-'0') > 4)
+    fseek (ifp, get4()+base, SEEK_SET);
+}
+
+void CLASS parse_thumb_note (int base, unsigned toff, unsigned tlen)
+{
+  unsigned entries, tag, type, len, save;
+
+  entries = get2();
+  while (entries--) {
+    tiff_get (base, &tag, &type, &len, &save);
+    if (tag == toff) thumb_offset = get4()+base;
+    if (tag == tlen) thumb_length = get4();
+    fseek (ifp, save, SEEK_SET);
+  }
+}
+
+#line 5416 "dcraw/dcraw.c"
+void CLASS parse_makernote (int base, int uptag)
+{
+  static const uchar xlat[2][256] = {
+  { 0xc1,0xbf,0x6d,0x0d,0x59,0xc5,0x13,0x9d,0x83,0x61,0x6b,0x4f,0xc7,0x7f,0x3d,0x3d,
+    0x53,0x59,0xe3,0xc7,0xe9,0x2f,0x95,0xa7,0x95,0x1f,0xdf,0x7f,0x2b,0x29,0xc7,0x0d,
+    0xdf,0x07,0xef,0x71,0x89,0x3d,0x13,0x3d,0x3b,0x13,0xfb,0x0d,0x89,0xc1,0x65,0x1f,
+    0xb3,0x0d,0x6b,0x29,0xe3,0xfb,0xef,0xa3,0x6b,0x47,0x7f,0x95,0x35,0xa7,0x47,0x4f,
+    0xc7,0xf1,0x59,0x95,0x35,0x11,0x29,0x61,0xf1,0x3d,0xb3,0x2b,0x0d,0x43,0x89,0xc1,
+    0x9d,0x9d,0x89,0x65,0xf1,0xe9,0xdf,0xbf,0x3d,0x7f,0x53,0x97,0xe5,0xe9,0x95,0x17,
+    0x1d,0x3d,0x8b,0xfb,0xc7,0xe3,0x67,0xa7,0x07,0xf1,0x71,0xa7,0x53,0xb5,0x29,0x89,
+    0xe5,0x2b,0xa7,0x17,0x29,0xe9,0x4f,0xc5,0x65,0x6d,0x6b,0xef,0x0d,0x89,0x49,0x2f,
+    0xb3,0x43,0x53,0x65,0x1d,0x49,0xa3,0x13,0x89,0x59,0xef,0x6b,0xef,0x65,0x1d,0x0b,
+    0x59,0x13,0xe3,0x4f,0x9d,0xb3,0x29,0x43,0x2b,0x07,0x1d,0x95,0x59,0x59,0x47,0xfb,
+    0xe5,0xe9,0x61,0x47,0x2f,0x35,0x7f,0x17,0x7f,0xef,0x7f,0x95,0x95,0x71,0xd3,0xa3,
+    0x0b,0x71,0xa3,0xad,0x0b,0x3b,0xb5,0xfb,0xa3,0xbf,0x4f,0x83,0x1d,0xad,0xe9,0x2f,
+    0x71,0x65,0xa3,0xe5,0x07,0x35,0x3d,0x0d,0xb5,0xe9,0xe5,0x47,0x3b,0x9d,0xef,0x35,
+    0xa3,0xbf,0xb3,0xdf,0x53,0xd3,0x97,0x53,0x49,0x71,0x07,0x35,0x61,0x71,0x2f,0x43,
+    0x2f,0x11,0xdf,0x17,0x97,0xfb,0x95,0x3b,0x7f,0x6b,0xd3,0x25,0xbf,0xad,0xc7,0xc5,
+    0xc5,0xb5,0x8b,0xef,0x2f,0xd3,0x07,0x6b,0x25,0x49,0x95,0x25,0x49,0x6d,0x71,0xc7 },
+  { 0xa7,0xbc,0xc9,0xad,0x91,0xdf,0x85,0xe5,0xd4,0x78,0xd5,0x17,0x46,0x7c,0x29,0x4c,
+    0x4d,0x03,0xe9,0x25,0x68,0x11,0x86,0xb3,0xbd,0xf7,0x6f,0x61,0x22,0xa2,0x26,0x34,
+    0x2a,0xbe,0x1e,0x46,0x14,0x68,0x9d,0x44,0x18,0xc2,0x40,0xf4,0x7e,0x5f,0x1b,0xad,
+    0x0b,0x94,0xb6,0x67,0xb4,0x0b,0xe1,0xea,0x95,0x9c,0x66,0xdc,0xe7,0x5d,0x6c,0x05,
+    0xda,0xd5,0xdf,0x7a,0xef,0xf6,0xdb,0x1f,0x82,0x4c,0xc0,0x68,0x47,0xa1,0xbd,0xee,
+    0x39,0x50,0x56,0x4a,0xdd,0xdf,0xa5,0xf8,0xc6,0xda,0xca,0x90,0xca,0x01,0x42,0x9d,
+    0x8b,0x0c,0x73,0x43,0x75,0x05,0x94,0xde,0x24,0xb3,0x80,0x34,0xe5,0x2c,0xdc,0x9b,
+    0x3f,0xca,0x33,0x45,0xd0,0xdb,0x5f,0xf5,0x52,0xc3,0x21,0xda,0xe2,0x22,0x72,0x6b,
+    0x3e,0xd0,0x5b,0xa8,0x87,0x8c,0x06,0x5d,0x0f,0xdd,0x09,0x19,0x93,0xd0,0xb9,0xfc,
+    0x8b,0x0f,0x84,0x60,0x33,0x1c,0x9b,0x45,0xf1,0xf0,0xa3,0x94,0x3a,0x12,0x77,0x33,
+    0x4d,0x44,0x78,0x28,0x3c,0x9e,0xfd,0x65,0x57,0x16,0x94,0x6b,0xfb,0x59,0xd0,0xc8,
+    0x22,0x36,0xdb,0xd2,0x63,0x98,0x43,0xa1,0x04,0x87,0x86,0xf7,0xa6,0x26,0xbb,0xd6,
+    0x59,0x4d,0xbf,0x6a,0x2e,0xaa,0x2b,0xef,0xe6,0x78,0xb6,0x4e,0xe0,0x2f,0xdc,0x7c,
+    0xbe,0x57,0x19,0x32,0x7e,0x2a,0xd0,0xb8,0xba,0x29,0x00,0x3c,0x52,0x7d,0xa8,0x49,
+    0x3b,0x2d,0xeb,0x25,0x49,0xfa,0xa3,0xaa,0x39,0xa7,0xc5,0xa7,0x50,0x11,0x36,0xfb,
+    0xc6,0x67,0x4a,0xf5,0xa5,0x12,0x65,0x7e,0xb0,0xdf,0xaf,0x4e,0xb3,0x61,0x7f,0x2f } };
+  unsigned offset=0, entries, tag, type, len, save, c;
+  unsigned ver97=0, serial=0, i, wbi=0, wb[4]={0,0,0,0};
+  uchar buf97[324], ci, cj, ck;
+  short sorder=order;
+  char buf[10];
+/*
+   The MakerNote might have its own TIFF header (possibly with
+   its own byte-order!), or it might just be a table.
+ */
+  fread (buf, 1, 10, ifp);
+  if (!strncmp (buf,"KDK" ,3) ||	/* these aren't TIFF tables */
+      !strncmp (buf,"VER" ,3) ||
+      !strncmp (buf,"IIII",4) ||
+      !strncmp (buf,"MMMM",4)) return;
+  if (!strncmp (buf,"KC"  ,2) ||	/* Konica KD-400Z, KD-510Z */
+      !strncmp (buf,"MLY" ,3)) {	/* Minolta DiMAGE G series */
+    order = 0x4d4d;
+    while ((i=ftell(ifp)) < data_offset && i < 16384) {
+      wb[0] = wb[2];  wb[2] = wb[1];  wb[1] = wb[3];
+      wb[3] = get2();
+      if (wb[1] == 256 && wb[3] == 256 &&
+	  wb[0] > 256 && wb[0] < 640 && wb[2] > 256 && wb[2] < 640)
+	FORC4 cam_mul[c] = wb[c];
+#ifdef LIBRAW_LIBRARY_BUILD
+      color_flags.cam_mul_state = LIBRAW_COLORSTATE_LOADED;
+#endif
+    }
+    goto quit;
+  }
+  if (!strcmp (buf,"Nikon")) {
+    base = ftell(ifp);
+    order = get2();
+    if (get2() != 42) goto quit;
+    offset = get4();
+    fseek (ifp, offset-8, SEEK_CUR);
+  } else if (!strcmp (buf,"OLYMPUS")) {
+    base = ftell(ifp)-10;
+    fseek (ifp, -2, SEEK_CUR);
+    order = get2();  get2();
+  } else if (!strncmp (buf,"FUJIFILM",8) ||
+	     !strncmp (buf,"SONY",4) ||
+	     !strcmp  (buf,"Panasonic")) {
+    order = 0x4949;
+    fseek (ifp,  2, SEEK_CUR);
+  } else if (!strcmp (buf,"OLYMP") ||
+	     !strcmp (buf,"LEICA") ||
+	     !strcmp (buf,"Ricoh") ||
+	     !strcmp (buf,"EPSON"))
+    fseek (ifp, -2, SEEK_CUR);
+  else if (!strcmp (buf,"AOC") ||
+	   !strcmp (buf,"QVC"))
+    fseek (ifp, -4, SEEK_CUR);
+  else fseek (ifp, -10, SEEK_CUR);
+
+  entries = get2();
+  if (entries > 1000) return;
+  while (entries--) {
+    tiff_get (base, &tag, &type, &len, &save);
+    tag |= uptag << 16;
+    if (tag == 2 && strstr(make,"NIKON"))
+      iso_speed = (get2(),get2());
+    if (tag == 4 && len > 26 && len < 35) {
+      if ((i=(get4(),get2())) != 0x7fff && !iso_speed)
+	iso_speed = 50 * pow (2, i/32.0 - 4);
+      if ((i=(get2(),get2())) != 0x7fff && !aperture)
+	aperture = pow (2, i/64.0);
+      if ((i=get2()) != 0xffff && !shutter)
+	shutter = pow (2, (short) i/-32.0);
+      wbi = (get2(),get2());
+      shot_order = (get2(),get2());
+    }
+    if ((tag == 4 || tag == 0x114) && !strncmp(make,"KONICA",6)) {
+      fseek (ifp, tag == 4 ? 140:160, SEEK_CUR);
+      switch (get2()) {
+	case 72:  flip = 0;  break;
+	case 76:  flip = 6;  break;
+	case 82:  flip = 5;  break;
+      }
+    }
+    if (tag == 7 && type == 2 && len > 20)
+      fgets (model2, 64, ifp);
+    if (tag == 8 && type == 4)
+      shot_order = get4();
+    if (tag == 9 && !strcmp(make,"Canon"))
+      fread (artist, 64, 1, ifp);
+    if (tag == 0xc && len == 4) {
+      cam_mul[0] = getreal(type);
+      cam_mul[2] = getreal(type);
+#ifdef LIBRAW_LIBRARY_BUILD
+      color_flags.cam_mul_state = LIBRAW_COLORSTATE_LOADED;
+#endif
+    }
+    if (tag == 0x10 && type == 4)
+      unique_id = get4();
+    if (tag == 0x11 && is_raw && !strncmp(make,"NIKON",5)) {
+      fseek (ifp, get4()+base, SEEK_SET);
+      parse_tiff_ifd (base);
+    }
+    if (tag == 0x14 && len == 2560 && type == 7) {
+      fseek (ifp, 1248, SEEK_CUR);
+      goto get2_256;
+    }
+    if (tag == 0x15 && type == 2 && is_raw)
+      fread (model, 64, 1, ifp);
+    if (strstr(make,"PENTAX")) {
+      if (tag == 0x1b) tag = 0x1018;
+      if (tag == 0x1c) tag = 0x1017;
+    }
+    if (tag == 0x1d)
+      while ((c = fgetc(ifp)) && c != EOF)
+	serial = serial*10 + (isdigit(c) ? c - '0' : c % 10);
+    if (tag == 0x81 && type == 4) {
+      data_offset = get4();
+      fseek (ifp, data_offset + 41, SEEK_SET);
+      raw_height = get2() * 2;
+      raw_width  = get2();
+      filters = 0x61616161;
+    }
+    if (tag == 0x29 && type == 1) {
+      c = wbi < 18 ? "012347800000005896"[wbi]-'0' : 0;
+      fseek (ifp, 8 + c*32, SEEK_CUR);
+      FORC4 cam_mul[c ^ (c >> 1) ^ 1] = get4();
+#ifdef LIBRAW_LIBRARY_BUILD
+      color_flags.cam_mul_state = LIBRAW_COLORSTATE_LOADED;
+#endif
+    }
+    if ((tag == 0x81  && type == 7) ||
+	(tag == 0x100 && type == 7) ||
+	(tag == 0x280 && type == 1)) {
+      thumb_offset = ftell(ifp);
+      thumb_length = len;
+    }
+    if (tag == 0x88 && type == 4 && (thumb_offset = get4()))
+      thumb_offset += base;
+    if (tag == 0x89 && type == 4)
+      thumb_length = get4();
+    if (tag == 0x8c || tag == 0x96)
+      meta_offset = ftell(ifp);
+    if (tag == 0x97) {
+      for (i=0; i < 4; i++)
+	ver97 = ver97 * 10 + fgetc(ifp)-'0';
+      switch (ver97) {
+	case 100:
+	  fseek (ifp, 68, SEEK_CUR);
+	  FORC4 cam_mul[(c >> 1) | ((c & 1) << 1)] = get2();
+#ifdef LIBRAW_LIBRARY_BUILD
+          color_flags.cam_mul_state = LIBRAW_COLORSTATE_LOADED;
+#endif
+	  break;
+	case 102:
+	  fseek (ifp, 6, SEEK_CUR);
+	  goto get2_rggb;
+	case 103:
+	  fseek (ifp, 16, SEEK_CUR);
+	  FORC4 cam_mul[c] = get2();
+#ifdef LIBRAW_LIBRARY_BUILD
+          color_flags.cam_mul_state = LIBRAW_COLORSTATE_LOADED;
+#endif
+      }
+      if (ver97 >= 200) {
+	if (ver97 != 205) fseek (ifp, 280, SEEK_CUR);
+	fread (buf97, 324, 1, ifp);
+      }
+    }
+    if (tag == 0xa4 && type == 3) {
+      fseek (ifp, wbi*48, SEEK_CUR);
+      FORC3 cam_mul[c] = get2();
+#ifdef LIBRAW_LIBRARY_BUILD
+      color_flags.cam_mul_state = LIBRAW_COLORSTATE_LOADED;
+#endif
+    }
+    if (tag == 0xa7 && (unsigned) (ver97-200) < 12 && !cam_mul[0]) {
+      ci = xlat[0][serial & 0xff];
+      cj = xlat[1][fgetc(ifp)^fgetc(ifp)^fgetc(ifp)^fgetc(ifp)];
+      ck = 0x60;
+      for (i=0; i < 324; i++)
+	buf97[i] ^= (cj += ci * ck++);
+      i = "66666>666;6A"[ver97-200] - '0';
+      FORC4 cam_mul[c ^ (c >> 1) ^ (i & 1)] =
+	sget2 (buf97 + (i & -2) + c*2);
+#ifdef LIBRAW_LIBRARY_BUILD
+      color_flags.cam_mul_state = LIBRAW_COLORSTATE_LOADED;
+#endif
+    }
+    if (tag == 0x200 && len == 3)
+      shot_order = (get4(),get4());
+    if (tag == 0x200 && len == 4)
+      black = (get2()+get2()+get2()+get2())/4;
+    if (tag == 0x201 && len == 4)
+      goto get2_rggb;
+    if (tag == 0x220 && len == 53)
+      meta_offset = ftell(ifp) + 14;
+    if (tag == 0x401 && type == 4 && len == 4) {
+      black = (get4()+get4()+get4()+get4())/4;
+    }
+    if (tag == 0xe01) {		/* Nikon Capture Note */
+      type = order;
+      order = 0x4949;
+      fseek (ifp, 22, SEEK_CUR);
+      for (offset=22; offset+22 < len; offset += 22+i) {
+	tag = get4();
+	fseek (ifp, 14, SEEK_CUR);
+	i = get4()-4;
+	if (tag == 0x76a43207) flip = get2();
+	else fseek (ifp, i, SEEK_CUR);
+      }
+      order = type;
+    }
+    if (tag == 0xe80 && len == 256 && type == 7) {
+      fseek (ifp, 48, SEEK_CUR);
+      cam_mul[0] = get2() * 508 * 1.078 / 0x10000;
+      cam_mul[2] = get2() * 382 * 1.173 / 0x10000;
+#ifdef LIBRAW_LIBRARY_BUILD
+      color_flags.cam_mul_state = LIBRAW_COLORSTATE_LOADED;
+#endif
+    }
+    if (tag == 0xf00 && type == 7) {
+      if (len == 614)
+	fseek (ifp, 176, SEEK_CUR);
+      else if (len == 734 || len == 1502)
+	fseek (ifp, 148, SEEK_CUR);
+      else goto next;
+      goto get2_256;
+    }
+    if ((tag == 0x1011 && len == 9) || tag == 0x20400200)
+        {
+      for (i=0; i < 3; i++)
+	FORC3 cmatrix[i][c] = ((short) get2()) / 256.0;
+#ifdef LIBRAW_LIBRARY_BUILD
+      color_flags.cmatrix_state = LIBRAW_COLORSTATE_LOADED;
+#endif
+        }
+    if ((tag == 0x1012 || tag == 0x20400600) && len == 4)
+      for (black = i=0; i < 4; i++)
+	black += get2() << 2;
+    if (tag == 0x1017 || tag == 0x20400100)
+        {
+      cam_mul[0] = get2() / 256.0;
+#ifdef LIBRAW_LIBRARY_BUILD
+      color_flags.cam_mul_state = LIBRAW_COLORSTATE_LOADED;
+#endif
+        }
+    if (tag == 0x1018 || tag == 0x20400100)
+        {
+      cam_mul[2] = get2() / 256.0;
+#ifdef LIBRAW_LIBRARY_BUILD
+      color_flags.cam_mul_state = LIBRAW_COLORSTATE_LOADED;
+#endif
+        }
+    if (tag == 0x2011 && len == 2) {
+get2_256:
+      order = 0x4d4d;
+      cam_mul[0] = get2() / 256.0;
+      cam_mul[2] = get2() / 256.0;
+#ifdef LIBRAW_LIBRARY_BUILD
+      color_flags.cam_mul_state = LIBRAW_COLORSTATE_LOADED;
+#endif
+    }
+    if ((tag | 0x70) == 0x2070 && type == 4)
+      fseek (ifp, get4()+base, SEEK_SET);
+    if (tag == 0x2010 && type != 7)
+      load_raw = &CLASS olympus_load_raw;
+    if (tag == 0x2020)
+      parse_thumb_note (base, 257, 258);
+    if (tag == 0x2040)
+      parse_makernote (base, 0x2040);
+    if (tag == 0xb028) {
+      fseek (ifp, get4(), SEEK_SET);
+      parse_thumb_note (base, 136, 137);
+    }
+    if (tag == 0x4001 && len > 500) {
+      i = len == 582 ? 50 : len == 653 ? 68 : len == 5120 ? 142 : 126;
+      fseek (ifp, i, SEEK_CUR);
+get2_rggb:
+      FORC4 cam_mul[c ^ (c >> 1)] = get2();
+#ifdef LIBRAW_LIBRARY_BUILD
+      color_flags.cam_mul_state = LIBRAW_COLORSTATE_LOADED;
+#endif
+      fseek (ifp, 22, SEEK_CUR);
+      FORC4 sraw_mul[c ^ (c >> 1)] = get2();
+    }
+next:
+    fseek (ifp, save, SEEK_SET);
+  }
+quit:
+  order = sorder;
+}
+
+/*
+   Since the TIFF DateTime string has no timezone information,
+   assume that the camera's clock was set to Universal Time.
+ */
+void CLASS get_timestamp (int reversed)
+{
+  struct tm t;
+  char str[20];
+  int i;
+
+  str[19] = 0;
+  if (reversed)
+    for (i=19; i--; ) str[i] = fgetc(ifp);
+  else
+    fread (str, 19, 1, ifp);
+  memset (&t, 0, sizeof t);
+  if (sscanf (str, "%d:%d:%d %d:%d:%d", &t.tm_year, &t.tm_mon,
+	&t.tm_mday, &t.tm_hour, &t.tm_min, &t.tm_sec) != 6)
+    return;
+  t.tm_year -= 1900;
+  t.tm_mon -= 1;
+  if (mktime(&t) > 0)
+    timestamp = mktime(&t);
+}
+
+void CLASS parse_exif (int base)
+{
+  unsigned kodak, entries, tag, type, len, save, c;
+  double expo;
+
+  kodak = !strncmp(make,"EASTMAN",7);
+  entries = get2();
+  while (entries--) {
+    tiff_get (base, &tag, &type, &len, &save);
+    switch (tag) {
+      case 33434:  shutter = getreal(type);		break;
+      case 33437:  aperture = getreal(type);		break;
+      case 34855:  iso_speed = get2();			break;
+      case 36867:
+      case 36868:  get_timestamp(0);			break;
+      case 37377:  if ((expo = -getreal(type)) < 128)
+		     shutter = pow (2, expo);		break;
+      case 37378:  aperture = pow (2, getreal(type)/2);	break;
+      case 37386:  focal_len = getreal(type);		break;
+      case 37500:  parse_makernote (base, 0);		break;
+      case 40962:  if (kodak) raw_width  = get4();	break;
+      case 40963:  if (kodak) raw_height = get4();	break;
+      case 41730:
+	if (get4() == 0x20002)
+	  for (exif_cfa=c=0; c < 8; c+=2)
+	    exif_cfa |= fgetc(ifp) * 0x01010101 << c;
+    }
+    fseek (ifp, save, SEEK_SET);
+  }
+}
+
+void CLASS parse_gps (int base)
+{
+  unsigned entries, tag, type, len, save, c;
+
+  entries = get2();
+  while (entries--) {
+    tiff_get (base, &tag, &type, &len, &save);
+    switch (tag) {
+      case 1: case 3: case 5:
+	gpsdata[29+tag/2] = getc(ifp);			break;
+      case 2: case 4: case 7:
+	FORC(6) gpsdata[tag/3*6+c] = get4();		break;
+      case 6:
+	FORC(2) gpsdata[18+c] = get4();			break;
+      case 18: case 29:
+	fgets ((char *) (gpsdata+14+tag/3), MIN(len,12), ifp);
+    }
+    fseek (ifp, save, SEEK_SET);
+  }
+}
+
+void CLASS romm_coeff (float romm_cam[3][3])
+{
+  static const float rgb_romm[3][3] =	/* ROMM == Kodak ProPhoto */
+  { {  2.034193, -0.727420, -0.306766 },
+    { -0.228811,  1.231729, -0.002922 },
+    { -0.008565, -0.153273,  1.161839 } };
+  int i, j, k;
+
+  for (i=0; i < 3; i++)
+    for (j=0; j < 3; j++)
+      for (cmatrix[i][j] = k=0; k < 3; k++)
+	cmatrix[i][j] += rgb_romm[i][k] * romm_cam[k][j];
+#ifdef LIBRAW_LIBRARY_BUILD
+  color_flags.cmatrix_state = LIBRAW_COLORSTATE_CALCULATED;
+#endif
+}
+
+void CLASS parse_mos (int offset)
+{
+  char data[40];
+  int skip, from, i, c, neut[4], planes=0, frot=0;
+  static const char *mod[] =
+  { "","DCB2","Volare","Cantare","CMost","Valeo 6","Valeo 11","Valeo 22",
+    "Valeo 11p","Valeo 17","","Aptus 17","Aptus 22","Aptus 75","Aptus 65",
+    "Aptus 54S","Aptus 65S","Aptus 75S","AFi 5","AFi 6","AFi 7" };
+  float romm_cam[3][3];
+
+  fseek (ifp, offset, SEEK_SET);
+  while (1) {
+    if (get4() != 0x504b5453) break;
+    get4();
+    fread (data, 1, 40, ifp);
+    skip = get4();
+    from = ftell(ifp);
+    if (!strcmp(data,"JPEG_preview_data")) {
+      thumb_offset = from;
+      thumb_length = skip;
+    }
+    if (!strcmp(data,"icc_camera_profile")) {
+      profile_offset = from;
+      profile_length = skip;
+    }
+    if (!strcmp(data,"ShootObj_back_type")) {
+      fscanf (ifp, "%d", &i);
+      if ((unsigned) i < sizeof mod / sizeof (*mod))
+	strcpy (model, mod[i]);
+    }
+    if (!strcmp(data,"icc_camera_to_tone_matrix")) {
+      for (i=0; i < 9; i++)
+	romm_cam[0][i] = int_to_float(get4());
+      romm_coeff (romm_cam);
+    }
+    if (!strcmp(data,"CaptProf_color_matrix")) {
+      for (i=0; i < 9; i++)
+	fscanf (ifp, "%f", &romm_cam[0][i]);
+      romm_coeff (romm_cam);
+    }
+    if (!strcmp(data,"CaptProf_number_of_planes"))
+      fscanf (ifp, "%d", &planes);
+    if (!strcmp(data,"CaptProf_raw_data_rotation"))
+      fscanf (ifp, "%d", &flip);
+    if (!strcmp(data,"CaptProf_mosaic_pattern"))
+      FORC4 {
+	fscanf (ifp, "%d", &i);
+	if (i == 1) frot = c ^ (c >> 1);
+      }
+    if (!strcmp(data,"ImgProf_rotation_angle")) {
+      fscanf (ifp, "%d", &i);
+      flip = i - flip;
+    }
+    if (!strcmp(data,"NeutObj_neutrals") && !cam_mul[0]) {
+      FORC4 fscanf (ifp, "%d", neut+c);
+      FORC3 cam_mul[c] = (float) neut[0] / neut[c+1];
+#ifdef LIBRAW_LIBRARY_BUILD
+      color_flags.cam_mul_state = LIBRAW_COLORSTATE_LOADED;
+#endif
+    }
+    parse_mos (from);
+    fseek (ifp, skip+from, SEEK_SET);
+  }
+  if (planes)
+    filters = (planes == 1) * 0x01010101 *
+	(uchar) "\x94\x61\x16\x49"[(flip/90 + frot) & 3];
+}
+
+void CLASS linear_table (unsigned len)
+{
+  int i;
+  if (len > 0x1000) len = 0x1000;
+  read_shorts (curve, len);
+#ifdef LIBRAW_LIBRARY_BUILD
+  color_flags.curve_state = LIBRAW_COLORSTATE_LOADED;
+#endif
+  for (i=len; i < 0x1000; i++)
+    curve[i] = curve[i-1];
+  maximum = curve[0xfff];
+}
+
+void CLASS parse_kodak_ifd (int base)
+{
+  unsigned entries, tag, type, len, save;
+  int i, c, wbi=-2, wbtemp=6500;
+  float mul[3]={1,1,1}, num;
+  static const int wbtag[]={ 0xfa25,0xfa28,0xfa27,0xfa29,-1,-1,0xfa2a };
+
+  entries = get2();
+  if (entries > 1024) return;
+  while (entries--) {
+    tiff_get (base, &tag, &type, &len, &save);
+    if (tag == 1020) wbi = getint(type);
+    if (tag == 1021 && len == 72) {		/* WB set in software */
+      fseek (ifp, 40, SEEK_CUR);
+      FORC3 cam_mul[c] = 2048.0 / get2();
+#ifdef LIBRAW_LIBRARY_BUILD
+      color_flags.cam_mul_state = LIBRAW_COLORSTATE_LOADED;
+#endif
+      wbi = -2;
+    }
+    if (tag == 2118) wbtemp = getint(type);
+    if (tag == 2130 + wbi)
+      FORC3 mul[c] = getreal(type);
+    if (tag == 2140 + wbi && wbi >= 0)
+        {
+      FORC3 {
+	for (num=i=0; i < 4; i++)
+	  num += getreal(type) * pow (wbtemp/100.0, i);
+	cam_mul[c] = 2048 / (num * mul[c]);
+      }
+#ifdef LIBRAW_LIBRARY_BUILD
+      color_flags.cam_mul_state = LIBRAW_COLORSTATE_LOADED;
+#endif
+        }
+    if (tag == 2317) linear_table (len);
+    if (tag == 6020) iso_speed = getint(type);
+    if (tag == 0xfa0d) wbi = fgetc(ifp);
+    if ((unsigned) wbi < 7 && tag == wbtag[wbi])
+      FORC3 cam_mul[c] = get4();
+    fseek (ifp, save, SEEK_SET);
+  }
+}
+
+#line 5961 "dcraw/dcraw.c"
+int CLASS parse_tiff_ifd (int base)
+{
+  unsigned entries, tag, type, len, plen=16, save;
+  int ifd, use_cm=0, cfa, i, j, c, ima_len=0;
+  char software[64], *cbuf, *cp;
+  uchar cfa_pat[16], cfa_pc[] = { 0,1,2,3 }, tab[256];
+  double dblack, cc[4][4], cm[4][3], cam_xyz[4][3], num;
+  double ab[]={ 1,1,1,1 }, asn[] = { 0,0,0,0 }, xyz[] = { 1,1,1 };
+  unsigned sony_curve[] = { 0,0,0,0,0,4095 };
+  unsigned *buf, sony_offset=0, sony_length=0, sony_key=0;
+  struct jhead jh;
+  FILE *sfp;
+
+  if (tiff_nifds >= sizeof tiff_ifd / sizeof tiff_ifd[0])
+    return 1;
+  ifd = tiff_nifds++;
+  for (j=0; j < 4; j++)
+    for (i=0; i < 4; i++)
+      cc[j][i] = i == j;
+  entries = get2();
+  if (entries > 512) return 1;
+  while (entries--) {
+    tiff_get (base, &tag, &type, &len, &save);
+    switch (tag) {
+      case 17: case 18:
+	if (type == 3 && len == 1)
+            {
+	  cam_mul[(tag-17)*2] = get2() / 256.0;
+#ifdef LIBRAW_LIBRARY_BUILD
+          color_flags.cam_mul_state = LIBRAW_COLORSTATE_LOADED;
+#endif
+            }
+	break;
+      case 23:
+	if (type == 3) iso_speed = get2();
+	break;
+      case 36: case 37: case 38:
+	cam_mul[tag-0x24] = get2();
+	break;
+      case 39:
+	if (len < 50 || cam_mul[0]) break;
+	fseek (ifp, 12, SEEK_CUR);
+	FORC3 cam_mul[c] = get2();
+#ifdef LIBRAW_LIBRARY_BUILD
+        color_flags.cam_mul_state = LIBRAW_COLORSTATE_LOADED;
+#endif
+	break;
+      case 46:
+	if (type != 7 || fgetc(ifp) != 0xff || fgetc(ifp) != 0xd8) break;
+	thumb_offset = ftell(ifp) - 2;
+	thumb_length = len;
+	break;
+      case 2: case 256:			/* ImageWidth */
+	tiff_ifd[ifd].t_width = getint(type);
+	break;
+      case 3: case 257:			/* ImageHeight */
+	tiff_ifd[ifd].t_height = getint(type);
+	break;
+      case 258:				/* BitsPerSample */
+	tiff_ifd[ifd].samples = len & 7;
+	tiff_ifd[ifd].bps = get2();
+	break;
+      case 259:				/* Compression */
+	tiff_ifd[ifd].comp = get2();
+	break;
+      case 262:				/* PhotometricInterpretation */
+	tiff_ifd[ifd].phint = get2();
+	break;
+      case 270:				/* ImageDescription */
+	fread (desc, 512, 1, ifp);
+	break;
+      case 271:				/* Make */
+	fgets (make, 64, ifp);
+	break;
+      case 272:				/* Model */
+	fgets (model, 64, ifp);
+	break;
+      case 280:				/* Panasonic RW2 offset */
+	if (type != 4) break;
+	load_raw = &CLASS panasonic_load_raw;
+	load_flags = 0x2008;
+      case 273:				/* StripOffset */
+      case 513:
+	tiff_ifd[ifd].offset = get4()+base;
+	if (!tiff_ifd[ifd].bps) {
+	  fseek (ifp, tiff_ifd[ifd].offset, SEEK_SET);
+	  if (ljpeg_start (&jh, 1)) {
+	    tiff_ifd[ifd].comp    = 6;
+	    tiff_ifd[ifd].t_width   = jh.wide << (jh.clrs == 2);
+	    tiff_ifd[ifd].t_height  = jh.high;
+	    tiff_ifd[ifd].bps     = jh.bits;
+	    tiff_ifd[ifd].samples = jh.clrs;
+	  }
+	}
+	break;
+      case 274:				/* Orientation */
+	tiff_ifd[ifd].t_flip = "50132467"[get2() & 7]-'0';
+	break;
+      case 277:				/* SamplesPerPixel */
+	tiff_ifd[ifd].samples = getint(type) & 7;
+	break;
+      case 279:				/* StripByteCounts */
+      case 514:
+	tiff_ifd[ifd].bytes = get4();
+	break;
+      case 305:  case 11:		/* Software */
+	fgets (software, 64, ifp);
+	if (!strncmp(software,"Adobe",5) ||
+	    !strncmp(software,"dcraw",5) ||
+	    !strncmp(software,"UFRaw",5) ||
+	    !strncmp(software,"Bibble",6) ||
+	    !strncmp(software,"Nikon Scan",10) ||
+	    !strcmp (software,"Digital Photo Professional"))
+	  is_raw = 0;
+	break;
+      case 306:				/* DateTime */
+	get_timestamp(0);
+	break;
+      case 315:				/* Artist */
+	fread (artist, 64, 1, ifp);
+	break;
+      case 322:				/* TileWidth */
+	tile_width = getint(type);
+	break;
+      case 323:				/* TileLength */
+	tile_length = getint(type);
+	break;
+      case 324:				/* TileOffsets */
+	tiff_ifd[ifd].offset = len > 1 ? ftell(ifp) : get4();
+	if (len == 4) {
+	  load_raw = &CLASS sinar_4shot_load_raw;
+	  is_raw = 5;
+	}
+	break;
+      case 330:				/* SubIFDs */
+	if (!strcmp(model,"DSLR-A100") && tiff_ifd[ifd].t_width == 3872) {
+	  load_raw = &CLASS sony_arw_load_raw;
+	  data_offset = get4()+base;
+	  ifd++;  break;
+	}
+	while (len--) {
+	  i = ftell(ifp);
+	  fseek (ifp, get4()+base, SEEK_SET);
+	  if (parse_tiff_ifd (base)) break;
+	  fseek (ifp, i+4, SEEK_SET);
+	}
+	break;
+      case 400:
+	strcpy (make, "Sarnoff");
+	maximum = 0xfff;
+	break;
+      case 28688:
+	FORC4 sony_curve[c+1] = get2() >> 2 & 0xfff;
+	for (i=0; i < 5; i++)
+	  for (j = sony_curve[i]+1; j <= sony_curve[i+1]; j++)
+	    curve[j] = curve[j-1] + (1 << i);
+#ifdef LIBRAW_LIBRARY_BUILD
+        color_flags.curve_state = LIBRAW_COLORSTATE_LOADED;
+#endif
+	break;
+      case 29184: sony_offset = get4();  break;
+      case 29185: sony_length = get4();  break;
+      case 29217: sony_key    = get4();  break;
+      case 29264:
+	parse_minolta (ftell(ifp));
+	raw_width = 0;
+	break;
+      case 29443:
+	FORC4 cam_mul[c ^ (c < 2)] = get2();
+#ifdef LIBRAW_LIBRARY_BUILD
+        color_flags.cam_mul_state = LIBRAW_COLORSTATE_LOADED;
+#endif
+	break;
+      case 29459:
+	FORC4 cam_mul[c ^ (c >> 1)] = get2();
+#ifdef LIBRAW_LIBRARY_BUILD
+        color_flags.cam_mul_state = LIBRAW_COLORSTATE_LOADED;
+#endif
+	break;
+      case 33405:			/* Model2 */
+	fgets (model2, 64, ifp);
+	break;
+      case 33422:			/* CFAPattern */
+      case 64777:			/* Kodak P-series */
+	if ((plen=len) > 16) plen = 16;
+	fread (cfa_pat, 1, plen, ifp);
+	for (colors=cfa=i=0; i < plen; i++) {
+	  colors += !(cfa & (1 << cfa_pat[i]));
+	  cfa |= 1 << cfa_pat[i];
+	}
+	if (cfa == 070) memcpy (cfa_pc,"\003\004\005",3);	/* CMY */
+	if (cfa == 072) memcpy (cfa_pc,"\005\003\004\001",4);	/* GMCY */
+	goto guess_cfa_pc;
+      case 33424:
+      case 65024:
+	fseek (ifp, get4()+base, SEEK_SET);
+	parse_kodak_ifd (base);
+	break;
+      case 33434:			/* ExposureTime */
+	shutter = getreal(type);
+	break;
+      case 33437:			/* FNumber */
+	aperture = getreal(type);
+	break;
+      case 34306:			/* Leaf white balance */
+	FORC4 cam_mul[c ^ 1] = 4096.0 / get2();
+#ifdef LIBRAW_LIBRARY_BUILD
+        color_flags.cam_mul_state = LIBRAW_COLORSTATE_LOADED;
+#endif
+	break;
+      case 34307:			/* Leaf CatchLight color matrix */
+	fread (software, 1, 7, ifp);
+	if (strncmp(software,"MATRIX",6)) break;
+	colors = 4;
+	for (raw_color = i=0; i < 3; i++) {
+	  FORC4 fscanf (ifp, "%f", &rgb_cam[i][c^1]);
+	  if (!use_camera_wb) continue;
+	  num = 0;
+	  FORC4 num += rgb_cam[i][c];
+	  FORC4 rgb_cam[i][c] /= num;
+#ifdef LIBRAW_LIBRARY_BUILD
+          color_flags.rgb_cam_state = LIBRAW_COLORSTATE_LOADED;
+#endif
+	}
+	break;
+      case 34310:			/* Leaf metadata */
+	parse_mos (ftell(ifp));
+      case 34303:
+	strcpy (make, "Leaf");
+	break;
+      case 34665:			/* EXIF tag */
+	fseek (ifp, get4()+base, SEEK_SET);
+	parse_exif (base);
+	break;
+      case 34853:			/* GPSInfo tag */
+	fseek (ifp, get4()+base, SEEK_SET);
+	parse_gps (base);
+	break;
+      case 34675:			/* InterColorProfile */
+      case 50831:			/* AsShotICCProfile */
+	profile_offset = ftell(ifp);
+	profile_length = len;
+	break;
+      case 37122:			/* CompressedBitsPerPixel */
+	kodak_cbpp = get4();
+	break;
+      case 37386:			/* FocalLength */
+	focal_len = getreal(type);
+	break;
+      case 37393:			/* ImageNumber */
+	shot_order = getint(type);
+	break;
+      case 37400:			/* old Kodak KDC tag */
+	for (raw_color = i=0; i < 3; i++) {
+	  getreal(type);
+	  FORC3 rgb_cam[i][c] = getreal(type);
+	}
+#ifdef LIBRAW_LIBRARY_BUILD
+        color_flags.rgb_cam_state = LIBRAW_COLORSTATE_LOADED;
+#endif
+	break;
+      case 46275:			/* Imacon tags */
+	strcpy (make, "Imacon");
+	data_offset = ftell(ifp);
+	ima_len = len;
+	break;
+      case 46279:
+	if (!ima_len) break;
+	fseek (ifp, 78, SEEK_CUR);
+	raw_width  = get4();
+	raw_height = get4();
+	left_margin = get4() & 7;
+	width = raw_width - left_margin - (get4() & 7);
+	top_margin = get4() & 7;
+	height = raw_height - top_margin - (get4() & 7);
+	if (raw_width == 7262) {
+	  height = 5444;
+	  width  = 7244;
+	  left_margin = 7;
+	}
+	fseek (ifp, 52, SEEK_CUR);
+	FORC3 cam_mul[c] = getreal(11);
+#ifdef LIBRAW_LIBRARY_BUILD
+        color_flags.cam_mul_state = LIBRAW_COLORSTATE_LOADED;
+#endif
+	fseek (ifp, 114, SEEK_CUR);
+	flip = (get2() >> 7) * 90;
+	if (width * height * 6 == ima_len) {
+	  if (flip % 180 == 90) SWAP(width,height);
+	  filters = flip = 0;
+	}
+	sprintf (model, "Ixpress %d-Mp", height*width/1000000);
+	load_raw = &CLASS imacon_full_load_raw;
+	if (filters) {
+	  if (left_margin & 1) filters = 0x61616161;
+	  load_raw = &CLASS unpacked_load_raw;
+	}
+	maximum = 0xffff;
+	break;
+      case 50454:			/* Sinar tag */
+      case 50455:
+	if (!(cbuf = (char *) malloc(len))) break;
+	fread (cbuf, 1, len, ifp);
+	for (cp = cbuf-1; cp && cp < cbuf+len; cp = strchr(cp,'\n'))
+	  if (!strncmp (++cp,"Neutral ",8))
+              {
+	    sscanf (cp+8, "%f %f %f", cam_mul, cam_mul+1, cam_mul+2);
+#ifdef LIBRAW_LIBRARY_BUILD
+            color_flags.cam_mul_state = LIBRAW_COLORSTATE_LOADED;
+#endif
+              }
+	free (cbuf);
+	break;
+      case 50458:
+	if (!make[0]) strcpy (make, "Hasselblad");
+	break;
+      case 50459:			/* Hasselblad tag */
+	i = order;
+	j = ftell(ifp);
+	c = tiff_nifds;
+	order = get2();
+	fseek (ifp, j+(get2(),get4()), SEEK_SET);
+	parse_tiff_ifd (j);
+	maximum = 0xffff;
+	tiff_nifds = c;
+	order = i;
+	break;
+      case 50706:			/* DNGVersion */
+	FORC4 dng_version = (dng_version << 8) + fgetc(ifp);
+	if (!make[0]) strcpy (make, "DNG");
+	is_raw = 1;
+	break;
+      case 50710:			/* CFAPlaneColor */
+	if (len > 4) len = 4;
+	colors = len;
+	fread (cfa_pc, 1, colors, ifp);
+guess_cfa_pc:
+	FORCC tab[cfa_pc[c]] = c;
+	cdesc[c] = 0;
+	for (i=16; i--; )
+	  filters = filters << 2 | tab[cfa_pat[i % plen]];
+	break;
+      case 50711:			/* CFALayout */
+	if (get2() == 2) {
+	  fuji_width = 1;
+	  filters = 0x49494949;
+	}
+	break;
+      case 291:
+      case 50712:			/* LinearizationTable */
+	linear_table (len);
+	break;
+      case 50714:			/* BlackLevel */
+      case 50715:			/* BlackLevelDeltaH */
+      case 50716:			/* BlackLevelDeltaV */
+	for (dblack=i=0; i < len; i++)
+	  dblack += getreal(type);
+	black += dblack/len + 0.5;
+	break;
+      case 50717:			/* WhiteLevel */
+	maximum = getint(type);
+	break;
+      case 50718:			/* DefaultScale */
+	pixel_aspect  = getreal(type);
+	pixel_aspect /= getreal(type);
+	break;
+      case 50721:			/* ColorMatrix1 */
+      case 50722:			/* ColorMatrix2 */
+	FORCC for (j=0; j < 3; j++)
+	  cm[c][j] = getreal(type);
+	use_cm = 1;
+	break;
+      case 50723:			/* CameraCalibration1 */
+      case 50724:			/* CameraCalibration2 */
+	for (i=0; i < colors; i++)
+	  FORCC cc[i][c] = getreal(type);
+	break;
+      case 50727:			/* AnalogBalance */
+	FORCC ab[c] = getreal(type);
+	break;
+      case 50728:			/* AsShotNeutral */
+	FORCC asn[c] = getreal(type);
+	break;
+      case 50729:			/* AsShotWhiteXY */
+	xyz[0] = getreal(type);
+	xyz[1] = getreal(type);
+	xyz[2] = 1 - xyz[0] - xyz[1];
+	FORC3 xyz[c] /= d65_white[c];
+	break;
+      case 50740:			/* DNGPrivateData */
+	if (dng_version) break;
+	parse_minolta (j = get4()+base);
+	fseek (ifp, j, SEEK_SET);
+	parse_tiff_ifd (base);
+	break;
+      case 50752:
+	read_shorts (cr2_slice, 3);
+	break;
+      case 50829:			/* ActiveArea */
+	top_margin = getint(type);
+	left_margin = getint(type);
+	height = getint(type) - top_margin;
+	width = getint(type) - left_margin;
+	break;
+      case 64772:			/* Kodak P-series */
+	if (len < 13) break;
+	fseek (ifp, 16, SEEK_CUR);
+	data_offset = get4();
+	fseek (ifp, 28, SEEK_CUR);
+	data_offset += get4();
+	load_raw = &CLASS packed_load_raw;
+	break;
+      case 65026:
+	if (type == 2) fgets (model2, 64, ifp);
+    }
+    fseek (ifp, save, SEEK_SET);
+  }
+  if (sony_length && (buf = (unsigned *) malloc(sony_length))) {
+    fseek (ifp, sony_offset, SEEK_SET);
+    fread (buf, sony_length, 1, ifp);
+    sony_decrypt (buf, sony_length/4, 1, sony_key);
+#ifndef LIBRAW_LIBRARY_BUILD
+    sfp = ifp;
+    if ((ifp = tmpfile())) {
+      fwrite (buf, sony_length, 1, ifp);
+      fseek (ifp, 0, SEEK_SET);
+      parse_tiff_ifd (-sony_offset);
+      fclose (ifp);
+    }
+    ifp = sfp;
+#else
+    if( !ifp->tempbuffer_open(buf,sony_length))
+        {
+            parse_tiff_ifd(-sony_offset);
+            ifp->tempbuffer_close();
+        }
+#endif
+    free (buf);
+  }
+  for (i=0; i < colors; i++)
+    FORCC cc[i][c] *= ab[i];
+  if (use_cm) {
+    FORCC for (i=0; i < 3; i++)
+      for (cam_xyz[c][i]=j=0; j < colors; j++)
+	cam_xyz[c][i] += cc[c][j] * cm[j][i] * xyz[i];
+    cam_xyz_coeff (cam_xyz);
+  }
+  if (asn[0]) {
+    cam_mul[3] = 0;
+    FORCC cam_mul[c] = 1 / asn[c];
+#ifdef LIBRAW_LIBRARY_BUILD
+    color_flags.cam_mul_state = LIBRAW_COLORSTATE_LOADED;
+#endif
+  }
+  if (!use_cm)
+      {
+    FORCC pre_mul[c] /= cc[c][c];
+#ifdef LIBRAW_LIBRARY_BUILD
+    color_flags.pre_mul_state = LIBRAW_COLORSTATE_LOADED;
+#endif
+      }
+
+  return 0;
+}
+
+void CLASS parse_tiff (int base)
+{
+  int doff, max_samp=0, raw=-1, thm=-1, i;
+  struct jhead jh;
+
+  fseek (ifp, base, SEEK_SET);
+  order = get2();
+  if (order != 0x4949 && order != 0x4d4d) return;
+  get2();
+  memset (tiff_ifd, 0, sizeof tiff_ifd);
+  tiff_nifds = 0;
+  while ((doff = get4())) {
+    fseek (ifp, doff+base, SEEK_SET);
+    if (parse_tiff_ifd (base)) break;
+  }
+  thumb_misc = 16;
+  if (thumb_offset) {
+    fseek (ifp, thumb_offset, SEEK_SET);
+    if (ljpeg_start (&jh, 1)) {
+      thumb_misc   = jh.bits;
+      thumb_width  = jh.wide;
+      thumb_height = jh.high;
+    }
+  }
+  for (i=0; i < tiff_nifds; i++) {
+    if (max_samp < tiff_ifd[i].samples)
+	max_samp = tiff_ifd[i].samples;
+    if (max_samp > 3) max_samp = 3;
+    if ((tiff_ifd[i].comp != 6 || tiff_ifd[i].samples != 3) &&
+	(tiff_ifd[i].t_width | tiff_ifd[i].t_height) < 0x10000 &&
+	tiff_ifd[i].t_width*tiff_ifd[i].t_height > raw_width*raw_height) {
+      raw_width     = tiff_ifd[i].t_width;
+      raw_height    = tiff_ifd[i].t_height;
+      tiff_bps      = tiff_ifd[i].bps;
+      tiff_compress = tiff_ifd[i].comp;
+      data_offset   = tiff_ifd[i].offset;
+      tiff_flip     = tiff_ifd[i].t_flip;
+      tiff_samples  = tiff_ifd[i].samples;
+      raw = i;
+    }
+  }
+  fuji_width *= (raw_width+1)/2;
+  if (tiff_ifd[0].t_flip) tiff_flip = tiff_ifd[0].t_flip;
+  if (raw >= 0 && !load_raw)
+    switch (tiff_compress) {
+      case 0:  case 1:
+	switch (tiff_bps) {
+	  case  8: load_raw = &CLASS eight_bit_load_raw;	break;
+	  case 12: load_raw = &CLASS packed_load_raw;
+		   if (tiff_ifd[raw].phint == 2)
+		     load_flags = 6;
+		   if (strncmp(make,"PENTAX",6)) break;
+	  case 14:
+	  case 16: load_raw = &CLASS unpacked_load_raw;		break;
+	}
+	if (tiff_ifd[raw].bytes*5 == raw_width*raw_height*8) {
+	  tiff_bps = 12;
+	  maximum = 0xffff;
+	  load_raw = &CLASS packed_load_raw;
+	  load_flags = 273;
+	}
+	break;
+      case 6:  case 7:  case 99:
+	load_raw = &CLASS lossless_jpeg_load_raw;		break;
+      case 262:
+	load_raw = &CLASS kodak_262_load_raw;			break;
+      case 32767:
+	if (tiff_ifd[raw].bytes == raw_width*raw_height) {
+	  tiff_bps = 12;
+	  load_raw = &CLASS sony_arw2_load_raw;			break;
+	}
+	if (tiff_ifd[raw].bytes*8 != raw_width*raw_height*tiff_bps) {
+	  raw_height += 8;
+	  load_raw = &CLASS sony_arw_load_raw;			break;
+	}
+	load_flags = 79;
+      case 32769:
+	load_flags++;
+      case 32773:
+	load_raw = &CLASS packed_load_raw;			break;
+      case 34713:
+	load_raw = &CLASS nikon_compressed_load_raw;		break;
+      case 65535:
+	load_raw = &CLASS pentax_load_raw;			break;
+      case 65000:
+	switch (tiff_ifd[raw].phint) {
+	  case 2: load_raw = &CLASS kodak_rgb_load_raw;   filters = 0;  break;
+	  case 6: load_raw = &CLASS kodak_ycbcr_load_raw; filters = 0;  break;
+	  case 32803: load_raw = &CLASS kodak_65000_load_raw;
+	}
+      case 32867: break;
+      default: is_raw = 0;
+    }
+  if (!dng_version)
+    if ( (tiff_samples == 3 && tiff_ifd[raw].bytes &&
+	  tiff_bps != 14 && tiff_bps != 2048)
+      || (tiff_bps == 8 && !strstr(make,"KODAK") && !strstr(make,"Kodak") &&
+	  !strstr(model2,"DEBUG RAW")))
+      is_raw = 0;
+  for (i=0; i < tiff_nifds; i++)
+    if (i != raw && tiff_ifd[i].samples == max_samp &&
+	tiff_ifd[i].t_width * tiff_ifd[i].t_height / SQR(tiff_ifd[i].bps+1) >
+	      thumb_width *       thumb_height / SQR(thumb_misc+1)) {
+      thumb_width  = tiff_ifd[i].t_width;
+      thumb_height = tiff_ifd[i].t_height;
+      thumb_offset = tiff_ifd[i].offset;
+      thumb_length = tiff_ifd[i].bytes;
+      thumb_misc   = tiff_ifd[i].bps;
+      thm = i;
+    }
+  if (thm >= 0) {
+    thumb_misc |= tiff_ifd[thm].samples << 5;
+    switch (tiff_ifd[thm].comp) {
+      case 0:
+	write_thumb = &CLASS layer_thumb;
+	break;
+      case 1:
+	if (tiff_ifd[thm].bps > 8)
+	  thumb_load_raw = &CLASS kodak_thumb_load_raw;
+	else
+	  write_thumb = &CLASS ppm_thumb;
+	break;
+      case 65000:
+	thumb_load_raw = tiff_ifd[thm].phint == 6 ?
+		&CLASS kodak_ycbcr_load_raw : &CLASS kodak_rgb_load_raw;
+    }
+  }
+}
+
+void CLASS parse_minolta (int base)
+{
+  int save, tag, len, offset, high=0, wide=0, i, c;
+  short sorder=order;
+
+  fseek (ifp, base, SEEK_SET);
+  if (fgetc(ifp) || fgetc(ifp)-'M' || fgetc(ifp)-'R') return;
+  order = fgetc(ifp) * 0x101;
+  offset = base + get4() + 8;
+  while ((save=ftell(ifp)) < offset) {
+    for (tag=i=0; i < 4; i++)
+      tag = tag << 8 | fgetc(ifp);
+    len = get4();
+    switch (tag) {
+      case 0x505244:				/* PRD */
+	fseek (ifp, 8, SEEK_CUR);
+	high = get2();
+	wide = get2();
+	break;
+      case 0x574247:				/* WBG */
+	get4();
+	i = strcmp(model,"DiMAGE A200") ? 0:3;
+	FORC4 cam_mul[c ^ (c >> 1) ^ i] = get2();
+#ifdef LIBRAW_LIBRARY_BUILD
+        color_flags.cam_mul_state = LIBRAW_COLORSTATE_LOADED;
+#endif
+	break;
+      case 0x545457:				/* TTW */
+	parse_tiff (ftell(ifp));
+	data_offset = offset;
+    }
+    fseek (ifp, save+len+8, SEEK_SET);
+  }
+  raw_height = high;
+  raw_width  = wide;
+  order = sorder;
+}
+
+/*
+   Many cameras have a "debug mode" that writes JPEG and raw
+   at the same time.  The raw file has no header, so try to
+   to open the matching JPEG file and read its metadata.
+ */
+void CLASS parse_external_jpeg()
+{
+  const char *file, *ext;
+  char *jname, *jfile, *jext;
+#ifndef LIBRAW_LIBRARY_BUILD
+  FILE *save=ifp;
+#else
+  if(!ifp->fname())
+      {
+          imgdata.process_warnings |= LIBRAW_WARN_NO_METADATA ;
+          return;
+      }
+#endif
+
+  ext  = strrchr (ifname, '.');
+  file = strrchr (ifname, '/');
+  if (!file) file = strrchr (ifname, '\\');
+#ifndef LIBRAW_LIBRARY_BUILD
+  if (!file) file = ifname-1;
+#else
+  if (!file) file = (char*)ifname-1;
+#endif
+  file++;
+  if (!ext || strlen(ext) != 4 || ext-file != 8) return;
+  jname = (char *) malloc (strlen(ifname) + 1);
+  merror (jname, "parse_external_jpeg()");
+  strcpy (jname, ifname);
+  jfile = file - ifname + jname;
+  jext  = ext  - ifname + jname;
+  if (strcasecmp (ext, ".jpg")) {
+    strcpy (jext, isupper(ext[1]) ? ".JPG":".jpg");
+    if (isdigit(*file)) {
+      memcpy (jfile, file+4, 4);
+      memcpy (jfile+4, file, 4);
+    }
+  } else
+    while (isdigit(*--jext)) {
+      if (*jext != '9') {
+        (*jext)++;
+	break;
+      }
+      *jext = '0';
+    }
+#ifndef LIBRAW_LIBRARY_BUILD
+  if (strcmp (jname, ifname)) {
+    if ((ifp = fopen (jname, "rb"))) {
+#ifdef DCRAW_VERBOSE
+      if (verbose)
+	fprintf (stderr,_("Reading metadata from %s ...\n"), jname);
+#endif
+      parse_tiff (12);
+      thumb_offset = 0;
+      is_raw = 1;
+      fclose (ifp);
+    }
+  }
+#else
+  if (strcmp (jname, ifname)) 
+      {
+          if(!ifp->subfile_open(jname))
+              {
+                  parse_tiff (12);
+                  thumb_offset = 0;
+                  is_raw = 1;
+                  ifp->subfile_close();
+              }
+          else
+              imgdata.process_warnings |= LIBRAW_WARN_NO_METADATA ;
+      }
+#endif
+  if (!timestamp)
+      {
+#ifdef LIBRAW_LIBRARY_BUILD
+          imgdata.process_warnings |= LIBRAW_WARN_NO_METADATA ;
+#endif
+#ifdef DCRAW_VERBOSE
+          fprintf (stderr,_("Failed to read metadata from %s\n"), jname);
+#endif
+      }
+  free (jname);
+#ifndef LIBRAW_LIBRARY_BUILD
+  ifp = save;
+#endif
+}
+
+/*
+   CIFF block 0x1030 contains an 8x8 white sample.
+   Load this into white[][] for use in scale_colors().
+ */
+void CLASS ciff_block_1030()
+{
+  static const ushort key[] = { 0x410, 0x45f3 };
+  int i, bpp, row, col, vbits=0;
+  unsigned long bitbuf=0;
+
+  if ((get2(),get4()) != 0x80008 || !get4()) return;
+  bpp = get2();
+  if (bpp != 10 && bpp != 12) return;
+  for (i=row=0; row < 8; row++)
+    for (col=0; col < 8; col++) {
+      if (vbits < bpp) {
+	bitbuf = bitbuf << 16 | (get2() ^ key[i++ & 1]);
+	vbits += 16;
+      }
+      white[row][col] =
+	bitbuf << (LONG_BIT - vbits) >> (LONG_BIT - bpp);
+      vbits -= bpp;
+    }
+}
+
+/*
+   Parse a CIFF file, better known as Canon CRW format.
+ */
+void CLASS parse_ciff (int offset, int length)
+{
+  int tboff, nrecs, c, type, len, save, wbi=-1;
+  ushort key[] = { 0x410, 0x45f3 };
+
+  fseek (ifp, offset+length-4, SEEK_SET);
+  tboff = get4() + offset;
+  fseek (ifp, tboff, SEEK_SET);
+  nrecs = get2();
+  if (nrecs > 100) return;
+  while (nrecs--) {
+    type = get2();
+    len  = get4();
+    save = ftell(ifp) + 4;
+    fseek (ifp, offset+get4(), SEEK_SET);
+    if ((((type >> 8) + 8) | 8) == 0x38)
+      parse_ciff (ftell(ifp), len);	/* Parse a sub-table */
+
+    if (type == 0x0810)
+      fread (artist, 64, 1, ifp);
+    if (type == 0x080a) {
+      fread (make, 64, 1, ifp);
+      fseek (ifp, ((INT64)strlen(make)) - 63, SEEK_CUR);
+      fread (model, 64, 1, ifp);
+    }
+    if (type == 0x1810) {
+      fseek (ifp, 12, SEEK_CUR);
+      flip = get4();
+    }
+    if (type == 0x1835)			/* Get the decoder table */
+      tiff_compress = get4();
+    if (type == 0x2007) {
+      thumb_offset = ftell(ifp);
+      thumb_length = len;
+    }
+    if (type == 0x1818) {
+      shutter = pow (2.0f, -int_to_float((get4(),get4())));
+      aperture = pow (2.0f, int_to_float(get4())/2);
+    }
+    if (type == 0x102a) {
+      iso_speed = pow (2, (get4(),get2())/32.0 - 4) * 50;
+      aperture  = pow (2, (get2(),(short)get2())/64.0);
+      shutter   = pow (2,-((short)get2())/32.0);
+      wbi = (get2(),get2());
+      if (wbi > 17) wbi = 0;
+      fseek (ifp, 32, SEEK_CUR);
+      if (shutter > 1e6) shutter = get2()/10.0;
+    }
+    if (type == 0x102c) {
+      if (get2() > 512) {		/* Pro90, G1 */
+	fseek (ifp, 118, SEEK_CUR);
+	FORC4 cam_mul[c ^ 2] = get2();
+#ifdef LIBRAW_LIBRARY_BUILD
+        color_flags.cam_mul_state = LIBRAW_COLORSTATE_LOADED;
+#endif
+      } else {				/* G2, S30, S40 */
+	fseek (ifp, 98, SEEK_CUR);
+	FORC4 cam_mul[c ^ (c >> 1) ^ 1] = get2();
+#ifdef LIBRAW_LIBRARY_BUILD
+        color_flags.cam_mul_state = LIBRAW_COLORSTATE_LOADED;
+#endif
+      }
+    }
+    if (type == 0x0032) {
+      if (len == 768) {			/* EOS D30 */
+	fseek (ifp, 72, SEEK_CUR);
+	FORC4 cam_mul[c ^ (c >> 1)] = 1024.0 / get2();
+#ifdef LIBRAW_LIBRARY_BUILD
+        color_flags.cam_mul_state = LIBRAW_COLORSTATE_LOADED;
+#endif
+	if (!wbi) cam_mul[0] = -1;	/* use my auto white balance */
+      } else if (!cam_mul[0]) {
+	if (get2() == key[0])		/* Pro1, G6, S60, S70 */
+	  c = (strstr(model,"Pro1") ?
+	      "012346000000000000":"01345:000000006008")[wbi]-'0'+ 2;
+	else {				/* G3, G5, S45, S50 */
+	  c = "023457000000006000"[wbi]-'0';
+	  key[0] = key[1] = 0;
+	}
+	fseek (ifp, 78 + c*8, SEEK_CUR);
+	FORC4 cam_mul[c ^ (c >> 1) ^ 1] = get2() ^ key[c & 1];
+#ifdef LIBRAW_LIBRARY_BUILD
+        color_flags.cam_mul_state = LIBRAW_COLORSTATE_LOADED;
+#endif
+	if (!wbi) cam_mul[0] = -1;
+      }
+    }
+    if (type == 0x10a9) {		/* D60, 10D, 300D, and clones */
+      if (len > 66) wbi = "0134567028"[wbi]-'0';
+      fseek (ifp, 2 + wbi*8, SEEK_CUR);
+      FORC4 cam_mul[c ^ (c >> 1)] = get2();
+#ifdef LIBRAW_LIBRARY_BUILD
+      color_flags.cam_mul_state = LIBRAW_COLORSTATE_LOADED;
+#endif
+    }
+    if (type == 0x1030 && (0x18040 >> wbi & 1))
+      ciff_block_1030();		/* all that don't have 0x10a9 */
+    if (type == 0x1031) {
+      raw_width = (get2(),get2());
+      raw_height = get2();
+    }
+    if (type == 0x5029) {
+      focal_len = len >> 16;
+      if ((len & 0xffff) == 2) focal_len /= 32;
+    }
+    if (type == 0x5813) flash_used = int_to_float(len);
+    if (type == 0x5814) canon_ev   = int_to_float(len);
+    if (type == 0x5817) shot_order = len;
+    if (type == 0x5834) unique_id  = len;
+    if (type == 0x580e) timestamp  = len;
+    if (type == 0x180e) timestamp  = get4();
+#ifdef LOCALTIME
+    if ((type | 0x4000) == 0x580e)
+      timestamp = mktime (gmtime (&timestamp));
+#endif
+    fseek (ifp, save, SEEK_SET);
+  }
+}
+
+void CLASS parse_rollei()
+{
+  char line[128], *val;
+  struct tm t;
+
+  fseek (ifp, 0, SEEK_SET);
+  memset (&t, 0, sizeof t);
+  do {
+    fgets (line, 128, ifp);
+    if ((val = strchr(line,'=')))
+      *val++ = 0;
+    else
+      val = line + strlen(line);
+    if (!strcmp(line,"DAT"))
+      sscanf (val, "%d.%d.%d", &t.tm_mday, &t.tm_mon, &t.tm_year);
+    if (!strcmp(line,"TIM"))
+      sscanf (val, "%d:%d:%d", &t.tm_hour, &t.tm_min, &t.tm_sec);
+    if (!strcmp(line,"HDR"))
+      thumb_offset = atoi(val);
+    if (!strcmp(line,"X  "))
+      raw_width = atoi(val);
+    if (!strcmp(line,"Y  "))
+      raw_height = atoi(val);
+    if (!strcmp(line,"TX "))
+      thumb_width = atoi(val);
+    if (!strcmp(line,"TY "))
+      thumb_height = atoi(val);
+  } while (strncmp(line,"EOHD",4));
+  data_offset = thumb_offset + thumb_width * thumb_height * 2;
+  t.tm_year -= 1900;
+  t.tm_mon -= 1;
+  if (mktime(&t) > 0)
+    timestamp = mktime(&t);
+  strcpy (make, "Rollei");
+  strcpy (model,"d530flex");
+  write_thumb = &CLASS rollei_thumb;
+}
+
+void CLASS parse_sinar_ia()
+{
+  int entries, off;
+  char str[8], *cp;
+
+  order = 0x4949;
+  fseek (ifp, 4, SEEK_SET);
+  entries = get4();
+  fseek (ifp, get4(), SEEK_SET);
+  while (entries--) {
+    off = get4(); get4();
+    fread (str, 8, 1, ifp);
+    if (!strcmp(str,"META"))   meta_offset = off;
+    if (!strcmp(str,"THUMB")) thumb_offset = off;
+    if (!strcmp(str,"RAW0"))   data_offset = off;
+  }
+  fseek (ifp, meta_offset+20, SEEK_SET);
+  fread (make, 64, 1, ifp);
+  make[63] = 0;
+  if ((cp = strchr(make,' '))) {
+    strcpy (model, cp+1);
+    *cp = 0;
+  }
+  raw_width  = get2();
+  raw_height = get2();
+  load_raw = &CLASS unpacked_load_raw;
+  thumb_width = (get4(),get2());
+  thumb_height = get2();
+  write_thumb = &CLASS ppm_thumb;
+  maximum = 0x3fff;
+}
+
+void CLASS parse_phase_one (int base)
+{
+  unsigned entries, tag, type, len, data, save, i, c;
+  float romm_cam[3][3];
+  char *cp;
+
+  memset (&ph1, 0, sizeof ph1);
+  fseek (ifp, base, SEEK_SET);
+  order = get4() & 0xffff;
+  if (get4() >> 8 != 0x526177) return;		/* "Raw" */
+  fseek (ifp, get4()+base, SEEK_SET);
+  entries = get4();
+  get4();
+  while (entries--) {
+    tag  = get4();
+    type = get4();
+    len  = get4();
+    data = get4();
+    save = ftell(ifp);
+    fseek (ifp, base+data, SEEK_SET);
+    switch (tag) {
+      case 0x100:  flip = "0653"[data & 3]-'0';  break;
+      case 0x106:
+	for (i=0; i < 9; i++)
+	  romm_cam[0][i] = getreal(11);
+	romm_coeff (romm_cam);
+	break;
+      case 0x107:
+	FORC3 cam_mul[c] = getreal(11);
+#ifdef LIBRAW_LIBRARY_BUILD
+        color_flags.cam_mul_state = LIBRAW_COLORSTATE_LOADED;
+#endif
+	break;
+      case 0x108:  raw_width     = data;	break;
+      case 0x109:  raw_height    = data;	break;
+      case 0x10a:  left_margin   = data;	break;
+      case 0x10b:  top_margin    = data;	break;
+      case 0x10c:  width         = data;	break;
+      case 0x10d:  height        = data;	break;
+      case 0x10e:  ph1.format    = data;	break;
+      case 0x10f:  data_offset   = data+base;	break;
+      case 0x110:  meta_offset   = data+base;
+		   meta_length   = len;			break;
+      case 0x112:  ph1.key_off   = save - 4;		break;
+      case 0x210:  ph1.tag_210   = int_to_float(data);	break;
+      case 0x21a:  ph1.tag_21a   = data;		break;
+      case 0x21c:  strip_offset  = data+base;		break;
+      case 0x21d:  ph1.t_black     = data;		break;
+      case 0x222:  ph1.split_col = data - left_margin;	break;
+      case 0x223:  ph1.black_off = data+base;		break;
+      case 0x301:
+	model[63] = 0;
+	fread (model, 1, 63, ifp);
+	if ((cp = strstr(model," camera"))) *cp = 0;
+    }
+    fseek (ifp, save, SEEK_SET);
+  }
+  load_raw = ph1.format < 3 ?
+	&CLASS phase_one_load_raw : &CLASS phase_one_load_raw_c;
+  maximum = 0xffff;
+  strcpy (make, "Phase One");
+  if (model[0]) return;
+  switch (raw_height) {
+    case 2060: strcpy (model,"LightPhase");	break;
+    case 2682: strcpy (model,"H 10");		break;
+    case 4128: strcpy (model,"H 20");		break;
+    case 5488: strcpy (model,"H 25");		break;
+  }
+}
+
+void CLASS parse_fuji (int offset)
+{
+  unsigned entries, tag, len, save, c;
+
+  fseek (ifp, offset, SEEK_SET);
+  entries = get4();
+  if (entries > 255) return;
+  while (entries--) {
+    tag = get2();
+    len = get2();
+    save = ftell(ifp);
+    if (tag == 0x100) {
+      raw_height = get2();
+      raw_width  = get2();
+    } else if (tag == 0x121) {
+      height = get2();
+      if ((width = get2()) == 4284) width += 3;
+    } else if (tag == 0x130) {
+      fuji_layout = fgetc(ifp) >> 7;
+      load_raw = fgetc(ifp) & 8 ?
+	&CLASS unpacked_load_raw : &CLASS fuji_load_raw;
+    }
+    if (tag == 0x2ff0)
+        {
+      FORC4 cam_mul[c ^ 1] = get2();
+#ifdef LIBRAW_LIBRARY_BUILD
+      color_flags.cam_mul_state = LIBRAW_COLORSTATE_LOADED;
+#endif
+        }
+    fseek (ifp, save+len, SEEK_SET);
+  }
+  height <<= fuji_layout;
+  width  >>= fuji_layout;
+}
+
+int CLASS parse_jpeg (int offset)
+{
+  int len, save, hlen, mark;
+
+  fseek (ifp, offset, SEEK_SET);
+  if (fgetc(ifp) != 0xff || fgetc(ifp) != 0xd8) return 0;
+
+  while (fgetc(ifp) == 0xff && (mark = fgetc(ifp)) != 0xda) {
+    order = 0x4d4d;
+    len   = get2() - 2;
+    save  = ftell(ifp);
+    if (mark == 0xc0 || mark == 0xc3) {
+      fgetc(ifp);
+      raw_height = get2();
+      raw_width  = get2();
+    }
+    order = get2();
+    hlen  = get4();
+    if (get4() == 0x48454150)		/* "HEAP" */
+      parse_ciff (save+hlen, len-hlen);
+    parse_tiff (save+6);
+    fseek (ifp, save+len, SEEK_SET);
+  }
+  return 1;
+}
+
+void CLASS parse_riff()
+{
+  unsigned i, size, end;
+  char tag[4], date[64], month[64];
+  static const char mon[12][4] =
+  { "Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec" };
+  struct tm t;
+
+  order = 0x4949;
+  fread (tag, 4, 1, ifp);
+  size = get4();
+  end = ftell(ifp) + size;
+  if (!memcmp(tag,"RIFF",4) || !memcmp(tag,"LIST",4)) {
+      int cnt=0;
+    get4();
+    while (ftell(ifp)+7 < end)
+        {
+            parse_riff();
+            if(cnt++>10000) break; // no more than 10k times
+        }
+  } else if (!memcmp(tag,"nctg",4)) {
+    while (ftell(ifp)+7 < end) {
+      i = get2();
+      size = get2();
+      if ((i+1) >> 1 == 10 && size == 20)
+	get_timestamp(0);
+      else fseek (ifp, size, SEEK_CUR);
+    }
+  } else if (!memcmp(tag,"IDIT",4) && size < 64) {
+    fread (date, 64, 1, ifp);
+    date[size] = 0;
+    memset (&t, 0, sizeof t);
+    if (sscanf (date, "%*s %s %d %d:%d:%d %d", month, &t.tm_mday,
+	&t.tm_hour, &t.tm_min, &t.tm_sec, &t.tm_year) == 6) {
+      for (i=0; i < 12 && strcasecmp(mon[i],month); i++);
+      t.tm_mon = i;
+      t.tm_year -= 1900;
+      if (mktime(&t) > 0)
+	timestamp = mktime(&t);
+    }
+  } else
+    fseek (ifp, size, SEEK_CUR);
+}
+
+void CLASS parse_smal (int offset, int fsize)
+{
+  int ver;
+
+  fseek (ifp, offset+2, SEEK_SET);
+  order = 0x4949;
+  ver = fgetc(ifp);
+  if (ver == 6)
+    fseek (ifp, 5, SEEK_CUR);
+  if (get4() != fsize) return;
+  if (ver > 6) data_offset = get4();
+  raw_height = height = get2();
+  raw_width  = width  = get2();
+  strcpy (make, "SMaL");
+  sprintf (model, "v%d %dx%d", ver, width, height);
+  if (ver == 6) load_raw = &CLASS smal_v6_load_raw;
+  if (ver == 9) load_raw = &CLASS smal_v9_load_raw;
+}
+
+void CLASS parse_cine()
+{
+  unsigned off_head, off_setup, off_image, i;
+
+  order = 0x4949;
+  fseek (ifp, 4, SEEK_SET);
+  is_raw = get2() == 2;
+  fseek (ifp, 14, SEEK_CUR);
+  is_raw *= get4();
+  off_head = get4();
+  off_setup = get4();
+  off_image = get4();
+  timestamp = get4();
+  if ((i = get4())) timestamp = i;
+  fseek (ifp, off_head+4, SEEK_SET);
+  raw_width = get4();
+  raw_height = get4();
+  switch (get2(),get2()) {
+    case  8:  load_raw = &CLASS eight_bit_load_raw;  break;
+    case 16:  load_raw = &CLASS  unpacked_load_raw;
+  }
+  fseek (ifp, off_setup+792, SEEK_SET);
+  strcpy (make, "CINE");
+  sprintf (model, "%d", get4());
+  fseek (ifp, 12, SEEK_CUR);
+  switch ((i=get4()) & 0xffffff) {
+    case  3:  filters = 0x94949494;  break;
+    case  4:  filters = 0x49494949;  break;
+    default:  is_raw = 0;
+  }
+  fseek (ifp, 72, SEEK_CUR);
+  switch ((get4()+3600) % 360) {
+    case 270:  flip = 4;  break;
+    case 180:  flip = 1;  break;
+    case  90:  flip = 7;  break;
+    case   0:  flip = 2;
+  }
+  cam_mul[0] = getreal(11);
+  cam_mul[2] = getreal(11);
+#ifdef LIBRAW_LIBRARY_BUILD
+  color_flags.cam_mul_state = LIBRAW_COLORSTATE_LOADED;
+#endif
+  maximum = ~(-1 << get4());
+  fseek (ifp, 668, SEEK_CUR);
+  shutter = get4()/1000000000.0;
+  fseek (ifp, off_image, SEEK_SET);
+  if (shot_select < is_raw)
+    fseek (ifp, shot_select*8, SEEK_CUR);
+  data_offset  = (INT64) get4() + 8;
+  data_offset += (INT64) get4() << 32;
+}
+#line 7247 "dcraw/dcraw.c"
+void CLASS adobe_coeff (const char *p_make, const char *p_model)
+{
+  static const struct {
+    const char *prefix;
+    short t_black, t_maximum, trans[12];
+  } table[] = {
+    { "AGFAPHOTO DC-833m", 0, 0,	/* DJC */
+	{ 11438,-3762,-1115,-2409,9914,2497,-1227,2295,5300 } },
+    { "Apple QuickTake", 0, 0,		/* DJC */
+	{ 21392,-5653,-3353,2406,8010,-415,7166,1427,2078 } },
+    { "Canon EOS D2000", 0, 0,
+	{ 24542,-10860,-3401,-1490,11370,-297,2858,-605,3225 } },
+    { "Canon EOS D6000", 0, 0,
+	{ 20482,-7172,-3125,-1033,10410,-285,2542,226,3136 } },
+    { "Canon EOS D30", 0, 0,
+	{ 9805,-2689,-1312,-5803,13064,3068,-2438,3075,8775 } },
+    { "Canon EOS D60", 0, 0xfa0,
+	{ 6188,-1341,-890,-7168,14489,2937,-2640,3228,8483 } },
+    { "Canon EOS 5D Mark II", 0, 0x3cf0,
+	{ 4716,603,-830,-7798,15474,2480,-1496,1937,6651 } },
+    { "Canon EOS 5D", 0, 0xe6c,
+	{ 6347,-479,-972,-8297,15954,2480,-1968,2131,7649 } },
+    { "Canon EOS 7D", 0, 0x3510,
+	{ 6844,-996,-856,-3876,11761,2396,-593,1772,6198 } },
+    { "Canon EOS 10D", 0, 0xfa0,
+	{ 8197,-2000,-1118,-6714,14335,2592,-2536,3178,8266 } },
+    { "Canon EOS 20Da", 0, 0,
+	{ 14155,-5065,-1382,-6550,14633,2039,-1623,1824,6561 } },
+    { "Canon EOS 20D", 0, 0xfff,
+	{ 6599,-537,-891,-8071,15783,2424,-1983,2234,7462 } },
+    { "Canon EOS 30D", 0, 0,
+	{ 6257,-303,-1000,-7880,15621,2396,-1714,1904,7046 } },
+    { "Canon EOS 40D", 0, 0x3f60,
+	{ 6071,-747,-856,-7653,15365,2441,-2025,2553,7315 } },
+    { "Canon EOS 50D", 0, 0x3d93,
+	{ 4920,616,-593,-6493,13964,2784,-1774,3178,7005 } },
+    { "Canon EOS 300D", 0, 0xfa0,
+	{ 8197,-2000,-1118,-6714,14335,2592,-2536,3178,8266 } },
+    { "Canon EOS 350D", 0, 0xfff,
+	{ 6018,-617,-965,-8645,15881,2975,-1530,1719,7642 } },
+    { "Canon EOS 400D", 0, 0xe8e,
+	{ 7054,-1501,-990,-8156,15544,2812,-1278,1414,7796 } },
+    { "Canon EOS 450D", 0, 0x390d,
+	{ 5784,-262,-821,-7539,15064,2672,-1982,2681,7427 } },
+    { "Canon EOS 500D", 0, 0x3479,
+	{ 4763,712,-646,-6821,14399,2640,-1921,3276,6561 } },
+    { "Canon EOS 1000D", 0, 0xe43,
+	{ 6771,-1139,-977,-7818,15123,2928,-1244,1437,7533 } },
+    { "Canon EOS-1Ds Mark III", 0, 0x3bb0,
+	{ 5859,-211,-930,-8255,16017,2353,-1732,1887,7448 } },
+    { "Canon EOS-1Ds Mark II", 0, 0xe80,
+	{ 6517,-602,-867,-8180,15926,2378,-1618,1771,7633 } },
+    { "Canon EOS-1D Mark IV", 0, 0x3bb0,
+	{ 6014,-220,-795,-4109,12014,2361,-561,1824,5787 } },
+    { "Canon EOS-1D Mark III", 0, 0x3bb0,
+	{ 6291,-540,-976,-8350,16145,2311,-1714,1858,7326 } },
+    { "Canon EOS-1D Mark II N", 0, 0xe80,
+	{ 6240,-466,-822,-8180,15825,2500,-1801,1938,8042 } },
+    { "Canon EOS-1D Mark II", 0, 0xe80,
+	{ 6264,-582,-724,-8312,15948,2504,-1744,1919,8664 } },
+    { "Canon EOS-1DS", 0, 0xe20,
+	{ 4374,3631,-1743,-7520,15212,2472,-2892,3632,8161 } },
+    { "Canon EOS-1D", 0, 0xe20,
+	{ 6806,-179,-1020,-8097,16415,1687,-3267,4236,7690 } },
+    { "Canon EOS", 0, 0,
+	{ 8197,-2000,-1118,-6714,14335,2592,-2536,3178,8266 } },
+    { "Canon PowerShot A530", 0, 0,
+	{ 0 } },	/* don't want the A5 matrix */	
+    { "Canon PowerShot A50", 0, 0,
+	{ -5300,9846,1776,3436,684,3939,-5540,9879,6200,-1404,11175,217 } },
+    { "Canon PowerShot A5", 0, 0,
+	{ -4801,9475,1952,2926,1611,4094,-5259,10164,5947,-1554,10883,547 } },
+    { "Canon PowerShot G10", 0, 0,
+	{ 11093,-3906,-1028,-5047,12492,2879,-1003,1750,5561 } },
+    { "Canon PowerShot G11", 0, 0,
+	{ 12177,-4817,-1069,-1612,9864,2049,-98,850,4471 } },
+    { "Canon PowerShot G1", 0, 0,
+	{ -4778,9467,2172,4743,-1141,4344,-5146,9908,6077,-1566,11051,557 } },
+    { "Canon PowerShot G2", 0, 0,
+	{ 9087,-2693,-1049,-6715,14382,2537,-2291,2819,7790 } },
+    { "Canon PowerShot G3", 0, 0,
+	{ 9212,-2781,-1073,-6573,14189,2605,-2300,2844,7664 } },
+    { "Canon PowerShot G5", 0, 0,
+	{ 9757,-2872,-933,-5972,13861,2301,-1622,2328,7212 } },
+    { "Canon PowerShot G6", 0, 0,
+	{ 9877,-3775,-871,-7613,14807,3072,-1448,1305,7485 } },
+    { "Canon PowerShot G9", 0, 0,
+	{ 7368,-2141,-598,-5621,13254,2625,-1418,1696,5743 } },
+    { "Canon PowerShot Pro1", 0, 0,
+	{ 10062,-3522,-999,-7643,15117,2730,-765,817,7323 } },
+    { "Canon PowerShot Pro70", 34, 0,
+	{ -4155,9818,1529,3939,-25,4522,-5521,9870,6610,-2238,10873,1342 } },
+    { "Canon PowerShot Pro90", 0, 0,
+	{ -4963,9896,2235,4642,-987,4294,-5162,10011,5859,-1770,11230,577 } },
+    { "Canon PowerShot S30", 0, 0,
+	{ 10566,-3652,-1129,-6552,14662,2006,-2197,2581,7670 } },
+    { "Canon PowerShot S40", 0, 0,
+	{ 8510,-2487,-940,-6869,14231,2900,-2318,2829,9013 } },
+    { "Canon PowerShot S45", 0, 0,
+	{ 8163,-2333,-955,-6682,14174,2751,-2077,2597,8041 } },
+    { "Canon PowerShot S50", 0, 0,
+	{ 8882,-2571,-863,-6348,14234,2288,-1516,2172,6569 } },
+    { "Canon PowerShot S60", 0, 0,
+	{ 8795,-2482,-797,-7804,15403,2573,-1422,1996,7082 } },
+    { "Canon PowerShot S70", 0, 0,
+	{ 9976,-3810,-832,-7115,14463,2906,-901,989,7889 } },
+    { "Canon PowerShot S90", 0, 0,
+	{ 12374,-5016,-1049,-1677,9902,2078,-83,852,4683 } },
+    { "Canon PowerShot A470", 0, 0,	/* DJC */
+	{ 12513,-4407,-1242,-2680,10276,2405,-878,2215,4734 } },
+    { "Canon PowerShot A610", 0, 0,	/* DJC */
+	{ 15591,-6402,-1592,-5365,13198,2168,-1300,1824,5075 } },
+    { "Canon PowerShot A620", 0, 0,	/* DJC */
+	{ 15265,-6193,-1558,-4125,12116,2010,-888,1639,5220 } },
+    { "Canon PowerShot A630", 0, 0,	/* DJC */
+	{ 14201,-5308,-1757,-6087,14472,1617,-2191,3105,5348 } },
+    { "Canon PowerShot A640", 0, 0,	/* DJC */
+	{ 13124,-5329,-1390,-3602,11658,1944,-1612,2863,4885 } },
+    { "Canon PowerShot A650", 0, 0,	/* DJC */
+	{ 9427,-3036,-959,-2581,10671,1911,-1039,1982,4430 } },
+    { "Canon PowerShot A720", 0, 0,	/* DJC */
+	{ 14573,-5482,-1546,-1266,9799,1468,-1040,1912,3810 } },
+    { "Canon PowerShot S3 IS", 0, 0,	/* DJC */
+	{ 14062,-5199,-1446,-4712,12470,2243,-1286,2028,4836 } },
+    { "Canon PowerShot SX1 IS", 0, 0,
+	{ 6578,-259,-502,-5974,13030,3309,-308,1058,4970 } },
+    { "Canon PowerShot SX110 IS", 0, 0,	/* DJC */
+        { 14134,-5576,-1527,-1991,10719,1273,-1158,1929,3581 } },
+    { "CASIO EX-S20", 0, 0,		/* DJC */
+	{ 11634,-3924,-1128,-4968,12954,2015,-1588,2648,7206 } },
+    { "CASIO EX-Z750", 0, 0,		/* DJC */
+	{ 10819,-3873,-1099,-4903,13730,1175,-1755,3751,4632 } },
+    { "CINE 650", 0, 0,
+	{ 3390,480,-500,-800,3610,340,-550,2336,1192 } },
+    { "CINE 660", 0, 0,
+	{ 3390,480,-500,-800,3610,340,-550,2336,1192 } },
+    { "CINE", 0, 0,
+	{ 20183,-4295,-423,-3940,15330,3985,-280,4870,9800 } },
+    { "Contax N Digital", 0, 0xf1e,
+	{ 7777,1285,-1053,-9280,16543,2916,-3677,5679,7060 } },
+    { "EPSON R-D1", 0, 0,
+	{ 6827,-1878,-732,-8429,16012,2564,-704,592,7145 } },
+    { "FUJIFILM FinePix E550", 0, 0,
+	{ 11044,-3888,-1120,-7248,15168,2208,-1531,2277,8069 } },
+    { "FUJIFILM FinePix E900", 0, 0,
+	{ 9183,-2526,-1078,-7461,15071,2574,-2022,2440,8639 } },
+    { "FUJIFILM FinePix F8", 0, 0,
+	{ 11044,-3888,-1120,-7248,15168,2208,-1531,2277,8069 } },
+    { "FUJIFILM FinePix F7", 0, 0,
+	{ 10004,-3219,-1201,-7036,15047,2107,-1863,2565,7736 } },
+    { "FUJIFILM FinePix S100FS", 514, 0,
+	{ 11521,-4355,-1065,-6524,13767,3058,-1466,1984,6045 } },
+    { "FUJIFILM FinePix S20Pro", 0, 0,
+	{ 10004,-3219,-1201,-7036,15047,2107,-1863,2565,7736 } },
+    { "FUJIFILM FinePix S2Pro", 128, 0,
+	{ 12492,-4690,-1402,-7033,15423,1647,-1507,2111,7697 } },
+    { "FUJIFILM FinePix S3Pro", 0, 0,
+	{ 11807,-4612,-1294,-8927,16968,1988,-2120,2741,8006 } },
+    { "FUJIFILM FinePix S5Pro", 0, 0,
+	{ 12300,-5110,-1304,-9117,17143,1998,-1947,2448,8100 } },
+    { "FUJIFILM FinePix S5000", 0, 0,
+	{ 8754,-2732,-1019,-7204,15069,2276,-1702,2334,6982 } },
+    { "FUJIFILM FinePix S5100", 0, 0x3e00,
+	{ 11940,-4431,-1255,-6766,14428,2542,-993,1165,7421 } },
+    { "FUJIFILM FinePix S5500", 0, 0x3e00,
+	{ 11940,-4431,-1255,-6766,14428,2542,-993,1165,7421 } },
+    { "FUJIFILM FinePix S5200", 0, 0,
+	{ 9636,-2804,-988,-7442,15040,2589,-1803,2311,8621 } },
+    { "FUJIFILM FinePix S5600", 0, 0,
+	{ 9636,-2804,-988,-7442,15040,2589,-1803,2311,8621 } },
+    { "FUJIFILM FinePix S6", 0, 0,
+	{ 12628,-4887,-1401,-6861,14996,1962,-2198,2782,7091 } },
+    { "FUJIFILM FinePix S7000", 0, 0,
+	{ 10190,-3506,-1312,-7153,15051,2238,-2003,2399,7505 } },
+    { "FUJIFILM FinePix S9000", 0, 0,
+	{ 10491,-3423,-1145,-7385,15027,2538,-1809,2275,8692 } },
+    { "FUJIFILM FinePix S9500", 0, 0,
+	{ 10491,-3423,-1145,-7385,15027,2538,-1809,2275,8692 } },
+    { "FUJIFILM FinePix S9100", 0, 0,
+	{ 12343,-4515,-1285,-7165,14899,2435,-1895,2496,8800 } },
+    { "FUJIFILM FinePix S9600", 0, 0,
+	{ 12343,-4515,-1285,-7165,14899,2435,-1895,2496,8800 } },
+    { "FUJIFILM IS-1", 0, 0,
+	{ 21461,-10807,-1441,-2332,10599,1999,289,875,7703 } },
+    { "FUJIFILM IS Pro", 0, 0,
+	{ 12300,-5110,-1304,-9117,17143,1998,-1947,2448,8100 } },
+    { "Imacon Ixpress", 0, 0,		/* DJC */
+	{ 7025,-1415,-704,-5188,13765,1424,-1248,2742,6038 } },
+    { "KODAK NC2000", 0, 0,
+	{ 13891,-6055,-803,-465,9919,642,2121,82,1291 } },
+    { "Kodak DCS315C", 8, 0,
+	{ 17523,-4827,-2510,756,8546,-137,6113,1649,2250 } },
+    { "Kodak DCS330C", 8, 0,
+	{ 20620,-7572,-2801,-103,10073,-396,3551,-233,2220 } },
+    { "KODAK DCS420", 0, 0,
+	{ 10868,-1852,-644,-1537,11083,484,2343,628,2216 } },
+    { "KODAK DCS460", 0, 0,
+	{ 10592,-2206,-967,-1944,11685,230,2206,670,1273 } },
+    { "KODAK EOSDCS1", 0, 0,
+	{ 10592,-2206,-967,-1944,11685,230,2206,670,1273 } },
+    { "KODAK EOSDCS3B", 0, 0,
+	{ 9898,-2700,-940,-2478,12219,206,1985,634,1031 } },
+    { "Kodak DCS520C", 180, 0,
+	{ 24542,-10860,-3401,-1490,11370,-297,2858,-605,3225 } },
+    { "Kodak DCS560C", 188, 0,
+	{ 20482,-7172,-3125,-1033,10410,-285,2542,226,3136 } },
+    { "Kodak DCS620C", 180, 0,
+	{ 23617,-10175,-3149,-2054,11749,-272,2586,-489,3453 } },
+    { "Kodak DCS620X", 185, 0,
+	{ 13095,-6231,154,12221,-21,-2137,895,4602,2258 } },
+    { "Kodak DCS660C", 214, 0,
+	{ 18244,-6351,-2739,-791,11193,-521,3711,-129,2802 } },
+    { "Kodak DCS720X", 0, 0,
+	{ 11775,-5884,950,9556,1846,-1286,-1019,6221,2728 } },
+    { "Kodak DCS760C", 0, 0,
+	{ 16623,-6309,-1411,-4344,13923,323,2285,274,2926 } },
+    { "Kodak DCS Pro SLR", 0, 0,
+	{ 5494,2393,-232,-6427,13850,2846,-1876,3997,5445 } },
+    { "Kodak DCS Pro 14nx", 0, 0,
+	{ 5494,2393,-232,-6427,13850,2846,-1876,3997,5445 } },
+    { "Kodak DCS Pro 14", 0, 0,
+	{ 7791,3128,-776,-8588,16458,2039,-2455,4006,6198 } },
+    { "Kodak ProBack645", 0, 0,
+	{ 16414,-6060,-1470,-3555,13037,473,2545,122,4948 } },
+    { "Kodak ProBack", 0, 0,
+	{ 21179,-8316,-2918,-915,11019,-165,3477,-180,4210 } },
+    { "KODAK P712", 0, 0,
+	{ 9658,-3314,-823,-5163,12695,2768,-1342,1843,6044 } },
+    { "KODAK P850", 0, 0xf7c,
+	{ 10511,-3836,-1102,-6946,14587,2558,-1481,1792,6246 } },
+    { "KODAK P880", 0, 0xfff,
+	{ 12805,-4662,-1376,-7480,15267,2360,-1626,2194,7904 } },
+    { "KODAK EasyShare Z980", 0, 0,
+	{ 11313,-3559,-1101,-3893,11891,2257,-1214,2398,4908 } },
+    { "KODAK EASYSHARE Z1015", 0, 0xef1,
+	{ 11265,-4286,-992,-4694,12343,2647,-1090,1523,5447 } },
+    { "Leaf CMost", 0, 0,
+	{ 3952,2189,449,-6701,14585,2275,-4536,7349,6536 } },
+    { "Leaf Valeo 6", 0, 0,
+	{ 3952,2189,449,-6701,14585,2275,-4536,7349,6536 } },
+    { "Leaf Aptus 54S", 0, 0,
+	{ 8236,1746,-1314,-8251,15953,2428,-3673,5786,5771 } },
+    { "Leaf Aptus 65", 0, 0,
+	{ 7914,1414,-1190,-8777,16582,2280,-2811,4605,5562 } },
+    { "Leaf Aptus 75", 0, 0,
+	{ 7914,1414,-1190,-8777,16582,2280,-2811,4605,5562 } },
+    { "Leaf", 0, 0,
+	{ 8236,1746,-1314,-8251,15953,2428,-3673,5786,5771 } },
+    { "Mamiya ZD", 0, 0,
+	{ 7645,2579,-1363,-8689,16717,2015,-3712,5941,5961 } },
+    { "Micron 2010", 110, 0,		/* DJC */
+	{ 16695,-3761,-2151,155,9682,163,3433,951,4904 } },
+    { "Minolta DiMAGE 5", 0, 0xf7d,
+	{ 8983,-2942,-963,-6556,14476,2237,-2426,2887,8014 } },
+    { "Minolta DiMAGE 7Hi", 0, 0xf7d,
+	{ 11368,-3894,-1242,-6521,14358,2339,-2475,3056,7285 } },
+    { "Minolta DiMAGE 7", 0, 0xf7d,
+	{ 9144,-2777,-998,-6676,14556,2281,-2470,3019,7744 } },
+    { "Minolta DiMAGE A1", 0, 0xf8b,
+	{ 9274,-2547,-1167,-8220,16323,1943,-2273,2720,8340 } },
+    { "MINOLTA DiMAGE A200", 0, 0,
+	{ 8560,-2487,-986,-8112,15535,2771,-1209,1324,7743 } },
+    { "Minolta DiMAGE A2", 0, 0xf8f,
+	{ 9097,-2726,-1053,-8073,15506,2762,-966,981,7763 } },
+    { "Minolta DiMAGE Z2", 0, 0,	/* DJC */
+	{ 11280,-3564,-1370,-4655,12374,2282,-1423,2168,5396 } },
+    { "MINOLTA DYNAX 5", 0, 0xffb,
+	{ 10284,-3283,-1086,-7957,15762,2316,-829,882,6644 } },
+    { "MINOLTA DYNAX 7", 0, 0xffb,
+	{ 10239,-3104,-1099,-8037,15727,2451,-927,925,6871 } },
+    { "MOTOROLA PIXL", 0, 0,		/* DJC */
+	{ 8898,-989,-1033,-3292,11619,1674,-661,3178,5216 } },
+    { "NIKON D100", 0, 0,
+	{ 5902,-933,-782,-8983,16719,2354,-1402,1455,6464 } },
+    { "NIKON D1H", 0, 0,
+	{ 7577,-2166,-926,-7454,15592,1934,-2377,2808,8606 } },
+    { "NIKON D1X", 0, 0,
+	{ 7702,-2245,-975,-9114,17242,1875,-2679,3055,8521 } },
+    { "NIKON D1", 0, 0, /* multiplied by 2.218750, 1.0, 1.148438 */
+	{ 16772,-4726,-2141,-7611,15713,1972,-2846,3494,9521 } },
+    { "NIKON D200", 0, 0xfbc,
+	{ 8367,-2248,-763,-8758,16447,2422,-1527,1550,8053 } },
+    { "NIKON D2H", 0, 0,
+	{ 5710,-901,-615,-8594,16617,2024,-2975,4120,6830 } },
+    { "NIKON D2X", 0, 0,
+	{ 10231,-2769,-1255,-8301,15900,2552,-797,680,7148 } },
+    { "NIKON D3000", 0, 0,
+	{ 8736,-2458,-935,-9075,16894,2251,-1354,1242,8263 } },
+    { "NIKON D300", 0, 0,
+	{ 9030,-1992,-715,-8465,16302,2255,-2689,3217,8069 } },
+    { "NIKON D3X", 0, 0,
+	{ 7171,-1986,-648,-8085,15555,2718,-2170,2512,7457 } },
+    { "NIKON D3S", 0, 0,
+	{ 8828,-2406,-694,-4874,12603,2541,-660,1509,7587 } },
+    { "NIKON D3", 0, 0,
+	{ 8139,-2171,-663,-8747,16541,2295,-1925,2008,8093 } },
+    { "NIKON D40X", 0, 0,
+	{ 8819,-2543,-911,-9025,16928,2151,-1329,1213,8449 } },
+    { "NIKON D40", 0, 0,
+	{ 6992,-1668,-806,-8138,15748,2543,-874,850,7897 } },
+    { "NIKON D5000", 0, 0xf00,
+	{ 7309,-1403,-519,-8474,16008,2622,-2433,2826,8064 } },
+    { "NIKON D50", 0, 0,
+	{ 7732,-2422,-789,-8238,15884,2498,-859,783,7330 } },
+    { "NIKON D60", 0, 0,
+	{ 8736,-2458,-935,-9075,16894,2251,-1354,1242,8263 } },
+    { "NIKON D700", 0, 0,
+	{ 8139,-2171,-663,-8747,16541,2295,-1925,2008,8093 } },
+    { "NIKON D70", 0, 0,
+	{ 7732,-2422,-789,-8238,15884,2498,-859,783,7330 } },
+    { "NIKON D80", 0, 0,
+	{ 8629,-2410,-883,-9055,16940,2171,-1490,1363,8520 } },
+    { "NIKON D90", 0, 0xf00,
+	{ 7309,-1403,-519,-8474,16008,2622,-2434,2826,8064 } },
+    { "NIKON E950", 0, 0x3dd,		/* DJC */
+	{ -3746,10611,1665,9621,-1734,2114,-2389,7082,3064,3406,6116,-244 } },
+    { "NIKON E995", 0, 0,	/* copied from E5000 */
+	{ -5547,11762,2189,5814,-558,3342,-4924,9840,5949,688,9083,96 } },
+    { "NIKON E2100", 0, 0,	/* copied from Z2, new white balance */
+	{ 13142,-4152,-1596,-4655,12374,2282,-1769,2696,6711} },
+    { "NIKON E2500", 0, 0,
+	{ -5547,11762,2189,5814,-558,3342,-4924,9840,5949,688,9083,96 } },
+    { "NIKON E4300", 0, 0,	/* copied from Minolta DiMAGE Z2 */
+	{ 11280,-3564,-1370,-4655,12374,2282,-1423,2168,5396 } },
+    { "NIKON E4500", 0, 0,
+	{ -5547,11762,2189,5814,-558,3342,-4924,9840,5949,688,9083,96 } },
+    { "NIKON E5000", 0, 0,
+	{ -5547,11762,2189,5814,-558,3342,-4924,9840,5949,688,9083,96 } },
+    { "NIKON E5400", 0, 0,
+	{ 9349,-2987,-1001,-7919,15766,2266,-2098,2680,6839 } },
+    { "NIKON E5700", 0, 0,
+	{ -5368,11478,2368,5537,-113,3148,-4969,10021,5782,778,9028,211 } },
+    { "NIKON E8400", 0, 0,
+	{ 7842,-2320,-992,-8154,15718,2599,-1098,1342,7560 } },
+    { "NIKON E8700", 0, 0,
+	{ 8489,-2583,-1036,-8051,15583,2643,-1307,1407,7354 } },
+    { "NIKON E8800", 0, 0,
+	{ 7971,-2314,-913,-8451,15762,2894,-1442,1520,7610 } },
+    { "NIKON COOLPIX P6000", 0, 0,
+	{ 9698,-3367,-914,-4706,12584,2368,-837,968,5801 } },
+    { "OLYMPUS C5050", 0, 0,
+	{ 10508,-3124,-1273,-6079,14294,1901,-1653,2306,6237 } },
+    { "OLYMPUS C5060", 0, 0,
+	{ 10445,-3362,-1307,-7662,15690,2058,-1135,1176,7602 } },
+    { "OLYMPUS C7070", 0, 0,
+	{ 10252,-3531,-1095,-7114,14850,2436,-1451,1723,6365 } },
+    { "OLYMPUS C70", 0, 0,
+	{ 10793,-3791,-1146,-7498,15177,2488,-1390,1577,7321 } },
+    { "OLYMPUS C80", 0, 0,
+	{ 8606,-2509,-1014,-8238,15714,2703,-942,979,7760 } },
+    { "OLYMPUS E-10", 0, 0xffc0,
+	{ 12745,-4500,-1416,-6062,14542,1580,-1934,2256,6603 } },
+    { "OLYMPUS E-1", 0, 0xfff0,
+	{ 11846,-4767,-945,-7027,15878,1089,-2699,4122,8311 } },
+    { "OLYMPUS E-20", 0, 0xffc0,
+	{ 13173,-4732,-1499,-5807,14036,1895,-2045,2452,7142 } },
+    { "OLYMPUS E-300", 0, 0,
+	{ 7828,-1761,-348,-5788,14071,1830,-2853,4518,6557 } },
+    { "OLYMPUS E-330", 0, 0,
+	{ 8961,-2473,-1084,-7979,15990,2067,-2319,3035,8249 } },
+    { "OLYMPUS E-30", 0, 0xfbc,
+	{ 8144,-1861,-1111,-7763,15894,1929,-1865,2542,7607 } },
+    { "OLYMPUS E-3", 0, 0xf99,
+	{ 9487,-2875,-1115,-7533,15606,2010,-1618,2100,7389 } },
+    { "OLYMPUS E-400", 0, 0xfff0,
+	{ 6169,-1483,-21,-7107,14761,2536,-2904,3580,8568 } },
+    { "OLYMPUS E-410", 0, 0xf6a,
+	{ 8856,-2582,-1026,-7761,15766,2082,-2009,2575,7469 } },
+    { "OLYMPUS E-420", 0, 0xfd7,
+	{ 8746,-2425,-1095,-7594,15612,2073,-1780,2309,7416 } },
+    { "OLYMPUS E-450", 0, 0xfd2,
+	{ 8745,-2425,-1095,-7594,15613,2073,-1780,2309,7416 } },
+    { "OLYMPUS E-500", 0, 0xfff0,
+	{ 8136,-1968,-299,-5481,13742,1871,-2556,4205,6630 } },
+    { "OLYMPUS E-510", 0, 0xf6a,
+	{ 8785,-2529,-1033,-7639,15624,2112,-1783,2300,7817 } },
+    { "OLYMPUS E-520", 0, 0xfd2,
+	{ 8344,-2322,-1020,-7596,15635,2048,-1748,2269,7287 } },
+    { "OLYMPUS E-620", 0, 0xfb9,
+	{ 8453,-2198,-1092,-7609,15681,2008,-1725,2337,7824 } },
+    { "OLYMPUS E-P1", 0, 0xffd,
+	{ 8343,-2050,-1021,-7715,15705,2103,-1831,2380,8235 } },
+    { "OLYMPUS SP350", 0, 0,
+	{ 12078,-4836,-1069,-6671,14306,2578,-786,939,7418 } },
+    { "OLYMPUS SP3", 0, 0,
+	{ 11766,-4445,-1067,-6901,14421,2707,-1029,1217,7572 } },
+    { "OLYMPUS SP500UZ", 0, 0xfff,
+	{ 9493,-3415,-666,-5211,12334,3260,-1548,2262,6482 } },
+    { "OLYMPUS SP510UZ", 0, 0xffe,
+	{ 10593,-3607,-1010,-5881,13127,3084,-1200,1805,6721 } },
+    { "OLYMPUS SP550UZ", 0, 0xffe,
+	{ 11597,-4006,-1049,-5432,12799,2957,-1029,1750,6516 } },
+    { "OLYMPUS SP560UZ", 0, 0xff9,
+	{ 10915,-3677,-982,-5587,12986,2911,-1168,1968,6223 } },
+    { "OLYMPUS SP570UZ", 0, 0,
+	{ 11522,-4044,-1146,-4736,12172,2904,-988,1829,6039 } },
+    { "PENTAX *ist DL2", 0, 0,
+	{ 10504,-2438,-1189,-8603,16207,2531,-1022,863,12242 } },
+    { "PENTAX *ist DL", 0, 0,
+	{ 10829,-2838,-1115,-8339,15817,2696,-837,680,11939 } },
+    { "PENTAX *ist DS2", 0, 0,
+	{ 10504,-2438,-1189,-8603,16207,2531,-1022,863,12242 } },
+    { "PENTAX *ist DS", 0, 0,
+	{ 10371,-2333,-1206,-8688,16231,2602,-1230,1116,11282 } },
+    { "PENTAX *ist D", 0, 0,
+	{ 9651,-2059,-1189,-8881,16512,2487,-1460,1345,10687 } },
+    { "PENTAX K10D", 0, 0,
+	{ 9566,-2863,-803,-7170,15172,2112,-818,803,9705 } },
+    { "PENTAX K1", 0, 0,
+	{ 11095,-3157,-1324,-8377,15834,2720,-1108,947,11688 } },
+    { "PENTAX K20D", 0, 0,
+	{ 9427,-2714,-868,-7493,16092,1373,-2199,3264,7180 } },
+    { "PENTAX K200D", 0, 0,
+	{ 9186,-2678,-907,-8693,16517,2260,-1129,1094,8524 } },
+    { "PENTAX K2000", 0, 0,
+	{ 11057,-3604,-1155,-5152,13046,2329,-282,375,8104 } },
+    { "PENTAX K-m", 0, 0,
+	{ 11057,-3604,-1155,-5152,13046,2329,-282,375,8104 } },
+    { "PENTAX K-x", 0, 0,
+	{ 8843,-2837,-625,-5025,12644,2668,-411,1234,7410 } },
+    { "PENTAX K-7", 0, 0,
+	{ 9142,-2947,-678,-8648,16967,1663,-2224,2898,8615 } },
+    { "Panasonic DMC-FZ8", 0, 0xf7f0,
+	{ 8986,-2755,-802,-6341,13575,3077,-1476,2144,6379 } },
+    { "Panasonic DMC-FZ18", 0, 0,
+	{ 9932,-3060,-935,-5809,13331,2753,-1267,2155,5575 } },
+    { "Panasonic DMC-FZ28", 15, 0xfff,
+	{ 10109,-3488,-993,-5412,12812,2916,-1305,2140,5543 } },
+    { "Panasonic DMC-FZ30", 0, 0xf94c,
+	{ 10976,-4029,-1141,-7918,15491,2600,-1670,2071,8246 } },
+    { "Panasonic DMC-FZ35", 147, 0xfff,
+	{ 9938,-2780,-890,-4604,12393,2480,-1117,2304,4620 } },
+    { "Panasonic DMC-FZ50", 0, 0xfff0,	/* aka "LEICA V-LUX1" */
+	{ 7906,-2709,-594,-6231,13351,3220,-1922,2631,6537 } },
+    { "Panasonic DMC-L10", 15, 0xf96,
+	{ 8025,-1942,-1050,-7920,15904,2100,-2456,3005,7039 } },
+    { "Panasonic DMC-L1", 0, 0xf7fc,	/* aka "LEICA DIGILUX 3" */
+	{ 8054,-1885,-1025,-8349,16367,2040,-2805,3542,7629 } },
+    { "Panasonic DMC-LC1", 0, 0,	/* aka "LEICA DIGILUX 2" */
+	{ 11340,-4069,-1275,-7555,15266,2448,-2960,3426,7685 } },
+    { "Panasonic DMC-LX1", 0, 0xf7f0,	/* aka "LEICA D-LUX2" */
+	{ 10704,-4187,-1230,-8314,15952,2501,-920,945,8927 } },
+    { "Panasonic DMC-LX2", 0, 0,	/* aka "LEICA D-LUX3" */
+	{ 8048,-2810,-623,-6450,13519,3272,-1700,2146,7049 } },
+    { "Panasonic DMC-LX3", 15, 0xfff,	/* aka "LEICA D-LUX4" */
+	{ 8128,-2668,-655,-6134,13307,3161,-1782,2568,6083 } },
+    { "Panasonic DMC-FX150", 15, 0xfff,
+	{ 9082,-2907,-925,-6119,13377,3058,-1797,2641,5609 } },
+    { "Panasonic DMC-G1", 15, 0xfff,
+	{ 8199,-2065,-1056,-8124,16156,2033,-2458,3022,7220 } },
+    { "Panasonic DMC-GF1", 15, 0xf92,
+	{ 7888,-1902,-1011,-8106,16085,2099,-2353,2866,7330 } },
+    { "Panasonic DMC-GH1", 15, 0xf92,
+	{ 6299,-1466,-532,-6535,13852,2969,-2331,3112,5984 } },
+    { "Phase One H 20", 0, 0,		/* DJC */
+	{ 1313,1855,-109,-6715,15908,808,-327,1840,6020 } },
+    { "Phase One P 2", 0, 0,
+	{ 2905,732,-237,-8134,16626,1476,-3038,4253,7517 } },
+    { "Phase One P 30", 0, 0,
+	{ 4516,-245,-37,-7020,14976,2173,-3206,4671,7087 } },
+    { "Phase One P 45", 0, 0,
+	{ 5053,-24,-117,-5684,14076,1702,-2619,4492,5849 } },
+    { "Phase One P65", 0, 0,		/* DJC */
+	{ 8522,1268,-1916,-7706,16350,1358,-2397,4344,4923 } },
+    { "SAMSUNG GX-1", 0, 0,
+	{ 10504,-2438,-1189,-8603,16207,2531,-1022,863,12242 } },
+    { "SAMSUNG S85", 0, 0,		/* DJC */
+	{ 11885,-3968,-1473,-4214,12299,1916,-835,1655,5549 } },
+    { "Sinar", 0, 0,			/* DJC */
+	{ 16442,-2956,-2422,-2877,12128,750,-1136,6066,4559 } },
+    { "SONY DSC-F828", 491, 0,
+	{ 7924,-1910,-777,-8226,15459,2998,-1517,2199,6818,-7242,11401,3481 } },
+    { "SONY DSC-R1", 512, 0,
+	{ 8512,-2641,-694,-8042,15670,2526,-1821,2117,7414 } },
+    { "SONY DSC-V3", 0, 0,
+	{ 7511,-2571,-692,-7894,15088,3060,-948,1111,8128 } },
+    { "SONY DSLR-A100", 0, 0xfeb,
+	{ 9437,-2811,-774,-8405,16215,2290,-710,596,7181 } },
+    { "SONY DSLR-A200", 0, 0,
+	{ 9847,-3091,-928,-8485,16345,2225,-715,595,7103 } },
+    { "SONY DSLR-A230", 0, 0,	/* copied */
+	{ 9847,-3091,-928,-8485,16345,2225,-715,595,7103 } },
+    { "SONY DSLR-A300", 0, 0,
+	{ 9847,-3091,-928,-8485,16345,2225,-715,595,7103 } },
+    { "SONY DSLR-A330", 0, 0,
+	{ 9847,-3091,-929,-8485,16346,2225,-714,595,7103 } },
+    { "SONY DSLR-A350", 0, 0xffc,
+	{ 6038,-1484,-578,-9146,16746,2513,-875,746,7217 } },
+    { "SONY DSLR-A380", 0, 0,
+	{ 6038,-1484,-579,-9145,16746,2512,-875,746,7218 } },
+    { "SONY DSLR-A5", 254, 0x1ffe,
+	{ 4950,-580,-103,-5228,12542,3029,-709,1435,7371 } },
+    { "SONY DSLR-A700", 254, 0x1ffe,
+	{ 5775,-805,-359,-8574,16295,2391,-1943,2341,7249 } },
+    { "SONY DSLR-A850", 256, 0x1ffe,
+	{ 5413,-1162,-365,-5665,13098,2866,-608,1179,8440 } },
+    { "SONY DSLR-A900", 254, 0x1ffe,
+	{ 5209,-1072,-397,-8845,16120,2919,-1618,1803,8654 } }
+  };
+  double cam_xyz[4][3];
+  char name[130];
+  int i, j;
+
+  sprintf (name, "%s %s", p_make, p_model);
+  for (i=0; i < sizeof table / sizeof *table; i++)
+    if (!strncmp (name, table[i].prefix, strlen(table[i].prefix))) {
+      if (table[i].t_black)   black   = (ushort) table[i].t_black;
+      if (table[i].t_maximum) maximum = (ushort) table[i].t_maximum;
+      if (table[i].trans[0]) {
+        for (j=0; j < 12; j++)
+#ifdef LIBRAW_LIBRARY_BUILD
+          imgdata.color.cam_xyz[0][j] = 
+#endif
+	  cam_xyz[0][j] = table[i].trans[j] / 10000.0;
+      cam_xyz_coeff (cam_xyz);
+      }
+      break;
+    }
+}
+
+void CLASS simple_coeff (int index)
+{
+  static const float table[][12] = {
+  /* index 0 -- all Foveon cameras */
+  { 1.4032,-0.2231,-0.1016,-0.5263,1.4816,0.017,-0.0112,0.0183,0.9113 },
+  /* index 1 -- Kodak DC20 and DC25 */
+  { 2.25,0.75,-1.75,-0.25,-0.25,0.75,0.75,-0.25,-0.25,-1.75,0.75,2.25 },
+  /* index 2 -- Logitech Fotoman Pixtura */
+  { 1.893,-0.418,-0.476,-0.495,1.773,-0.278,-1.017,-0.655,2.672 },
+  /* index 3 -- Nikon E880, E900, and E990 */
+  { -1.936280,  1.800443, -1.448486,  2.584324,
+     1.405365, -0.524955, -0.289090,  0.408680,
+    -1.204965,  1.082304,  2.941367, -1.818705 }
+  };
+  int i, c;
+
+  for (raw_color = i=0; i < 3; i++)
+    FORCC rgb_cam[i][c] = table[index][i*colors+c];
+#ifdef LIBRAW_LIBRARY_BUILD
+  color_flags.rgb_cam_state = LIBRAW_COLORSTATE_CALCULATED;
+#endif
+}
+
+short CLASS guess_byte_order (int words)
+{
+  uchar test[4][2];
+  int t=2, msb;
+  double diff, sum[2] = {0,0};
+
+  fread (test[0], 2, 2, ifp);
+  for (words-=2; words--; ) {
+    fread (test[t], 2, 1, ifp);
+    for (msb=0; msb < 2; msb++) {
+      diff = (test[t^2][msb] << 8 | test[t^2][!msb])
+	   - (test[t  ][msb] << 8 | test[t  ][!msb]);
+      sum[msb] += diff*diff;
+    }
+    t = (t+1) & 3;
+  }
+  return sum[0] < sum[1] ? 0x4d4d : 0x4949;
+}
+
+#line 7813 "dcraw/dcraw.c"
+
+float CLASS find_green (int bps, int bite, int off0, int off1)
+{
+  UINT64 bitbuf=0;
+  int vbits, col, i, c;
+  ushort img[2][2064];
+  double sum[]={0,0};
+
+  FORC(2) {
+    fseek (ifp, c ? off1:off0, SEEK_SET);
+    for (vbits=col=0; col < width; col++) {
+      for (vbits -= bps; vbits < 0; vbits += bite) {
+	bitbuf <<= bite;
+	for (i=0; i < bite; i+=8)
+	  bitbuf |= (unsigned) (fgetc(ifp) << i);
+      }
+      img[c][col] = bitbuf << (64-bps-vbits) >> (64-bps);
+    }
+  }
+  FORC(width-1) {
+    sum[ c & 1] += ABS(img[0][c]-img[1][c+1]);
+    sum[~c & 1] += ABS(img[1][c]-img[0][c+1]);
+  }
+  return 100 * log(sum[0]/sum[1]);
+}
+
+/*
+   Identify which camera created this file, and set global variables
+   accordingly.
+ */
+void CLASS identify()
+{
+  char head[32], *cp;
+  int hlen, fsize, i, c, is_canon;
+  struct jhead jh;
+  static const struct {
+    int fsize;
+    char t_make[12], t_model[19], withjpeg;
+  } table[] = {
+    {    62464, "Kodak",    "DC20"            ,0 },
+    {   124928, "Kodak",    "DC20"            ,0 },
+    {  1652736, "Kodak",    "DCS200"          ,0 },
+    {  4159302, "Kodak",    "C330"            ,0 },
+    {  4162462, "Kodak",    "C330"            ,0 },
+    {   460800, "Kodak",    "C603v"           ,0 },
+    {   614400, "Kodak",    "C603v"           ,0 },
+    {  6163328, "Kodak",    "C603"            ,0 },
+    {  6166488, "Kodak",    "C603"            ,0 },
+    {  9116448, "Kodak",    "C603y"           ,0 },
+    {   311696, "ST Micro", "STV680 VGA"      ,0 },  /* SPYz */
+    {   787456, "Creative", "PC-CAM 600"      ,0 },
+    {  1138688, "Minolta",  "RD175"           ,0 },
+    {  3840000, "Foculus",  "531C"            ,0 },
+    {   786432, "AVT",      "F-080C"          ,0 },
+    {  1447680, "AVT",      "F-145C"          ,0 },
+    {  1920000, "AVT",      "F-201C"          ,0 },
+    {  5067304, "AVT",      "F-510C"          ,0 },
+    { 10134608, "AVT",      "F-510C"          ,0 },
+    { 16157136, "AVT",      "F-810C"          ,0 },
+    {  1409024, "Sony",     "XCD-SX910CR"     ,0 },
+    {  2818048, "Sony",     "XCD-SX910CR"     ,0 },
+    {  3884928, "Micron",   "2010"            ,0 },
+    {  6624000, "Pixelink", "A782"            ,0 },
+    { 13248000, "Pixelink", "A782"            ,0 },
+    {  6291456, "RoverShot","3320AF"          ,0 },
+    {  6553440, "Canon",    "PowerShot A460"  ,0 },
+    {  6653280, "Canon",    "PowerShot A530"  ,0 },
+    {  6573120, "Canon",    "PowerShot A610"  ,0 },
+    {  9219600, "Canon",    "PowerShot A620"  ,0 },
+    {  9243240, "Canon",    "PowerShot A470"  ,0 },
+    { 10341600, "Canon",    "PowerShot A720"  ,0 },
+    { 10383120, "Canon",    "PowerShot A630"  ,0 },
+    { 12945240, "Canon",    "PowerShot A640"  ,0 },
+    { 15636240, "Canon",    "PowerShot A650"  ,0 },
+    {  5298000, "Canon",    "PowerShot SD300" ,0 },
+    {  7710960, "Canon",    "PowerShot S3 IS" ,0 },
+    { 15467760, "Canon",    "PowerShot SX110 IS",0 },
+    {  5939200, "OLYMPUS",  "C770UZ"          ,0 },
+    {  1581060, "NIKON",    "E900"            ,1 },  /* or E900s,E910 */
+    {  2465792, "NIKON",    "E950"            ,1 },  /* or E800,E700 */
+    {  2940928, "NIKON",    "E2100"           ,1 },  /* or E2500 */
+    {  4771840, "NIKON",    "E990"            ,1 },  /* or E995, Oly C3030Z */
+    {  4775936, "NIKON",    "E3700"           ,1 },  /* or Optio 33WR */
+    {  5869568, "NIKON",    "E4300"           ,1 },  /* or DiMAGE Z2 */
+    {  5865472, "NIKON",    "E4500"           ,1 },
+    {  7438336, "NIKON",    "E5000"           ,1 },  /* or E5700 */
+    {  8998912, "NIKON",    "COOLPIX S6"      ,1 },
+    {  1976352, "CASIO",    "QV-2000UX"       ,1 },
+    {  3217760, "CASIO",    "QV-3*00EX"       ,1 },
+    {  6218368, "CASIO",    "QV-5700"         ,1 },
+    {  6054400, "CASIO",    "QV-R41"          ,1 },
+    {  7530816, "CASIO",    "QV-R51"          ,1 },
+    {  7684000, "CASIO",    "QV-4000"         ,1 },
+    {  2937856, "CASIO",    "EX-S20"          ,1 },
+    {  4948608, "CASIO",    "EX-S100"         ,1 },
+    {  7542528, "CASIO",    "EX-Z50"          ,1 },
+    {  7753344, "CASIO",    "EX-Z55"          ,1 },
+    {  7816704, "CASIO",    "EX-Z60"          ,1 },
+    { 10843712, "CASIO",    "EX-Z75"          ,1 },
+    { 10834368, "CASIO",    "EX-Z750"         ,1 },
+    { 12310144, "CASIO",    "EX-Z850"         ,1 },
+    {  7426656, "CASIO",    "EX-P505"         ,1 },
+    {  9313536, "CASIO",    "EX-P600"         ,1 },
+    { 10979200, "CASIO",    "EX-P700"         ,1 },
+    {  3178560, "PENTAX",   "Optio S"         ,1 },
+    {  4841984, "PENTAX",   "Optio S"         ,1 },
+    {  6114240, "PENTAX",   "Optio S4"        ,1 },  /* or S4i, CASIO EX-Z4 */
+    { 10702848, "PENTAX",   "Optio 750Z"      ,1 },
+    { 15980544, "AGFAPHOTO","DC-833m"         ,1 },
+    { 16098048, "SAMSUNG",  "S85"             ,1 },
+    { 16215552, "SAMSUNG",  "S85"             ,1 },
+    { 12582980, "Sinar",    ""                ,0 },
+    { 33292868, "Sinar",    ""                ,0 },
+    { 44390468, "Sinar",    ""                ,0 } };
+  static const char *corp[] =
+    { "Canon", "NIKON", "EPSON", "KODAK", "Kodak", "OLYMPUS", "PENTAX",
+      "MINOLTA", "Minolta", "Konica", "CASIO", "Sinar", "Phase One",
+      "SAMSUNG", "Mamiya", "MOTOROLA" };
+
+#ifdef LIBRAW_LIBRARY_BUILD
+  RUN_CALLBACK(LIBRAW_PROGRESS_IDENTIFY,0,2);
+#endif
+
+  tiff_flip = flip = filters = -1;	/* 0 is valid, so -1 is unknown */
+  raw_height = raw_width = fuji_width = fuji_layout = cr2_slice[0] = 0;
+  maximum = height = width = top_margin = left_margin = 0;
+  cdesc[0] = desc[0] = artist[0] = make[0] = model[0] = model2[0] = 0;
+  iso_speed = shutter = aperture = focal_len = unique_id = 0;
+  memset (gpsdata, 0, sizeof gpsdata);
+  memset (white, 0, sizeof white);
+  thumb_offset = thumb_length = thumb_width = thumb_height = 0;
+  load_raw = thumb_load_raw = 0;
+  write_thumb = &CLASS jpeg_thumb;
+  data_offset = meta_length = tiff_bps = tiff_compress = 0;
+  kodak_cbpp = zero_after_ff = dng_version = load_flags = 0;
+  timestamp = shot_order = tiff_samples = black = 
+#ifndef LIBRAW_LIBRARY_BUILD
+      is_foveon = 
+#endif
+      0;
+  mix_green = profile_length = data_error = zero_is_bad = 0;
+  pixel_aspect = is_raw = raw_color = 1;
+  tile_width = tile_length = INT_MAX;
+  for (i=0; i < 4; i++) {
+    cam_mul[i] = i == 1;
+    pre_mul[i] = i < 3;
+    FORC3 cmatrix[c][i] = 0;
+    FORC3 rgb_cam[c][i] = c == i;
+  }
+#ifdef LIBRAW_LIBRARY_BUILD
+  color_flags.cmatrix_state = LIBRAW_COLORSTATE_INIT;
+  color_flags.rgb_cam_state = LIBRAW_COLORSTATE_INIT;
+  color_flags.pre_mul_state = LIBRAW_COLORSTATE_INIT;
+  color_flags.cam_mul_state = LIBRAW_COLORSTATE_INIT;
+#endif
+  colors = 3;
+  for (i=0; i < 0x4000; i++) curve[i] = i;
+#ifdef LIBRAW_LIBRARY_BUILD
+  color_flags.curve_state = LIBRAW_COLORSTATE_INIT;
+#endif
+
+  order = get2();
+  hlen = get4();
+  fseek (ifp, 0, SEEK_SET);
+  fread (head, 1, 32, ifp);
+  fseek (ifp, 0, SEEK_END);
+  fsize = ftell(ifp);
+  if ((cp = (char *) memmem (head, 32, (char*)"MMMM", 4)) ||
+      (cp = (char *) memmem (head, 32, (char*)"IIII", 4))) {
+    parse_phase_one (cp-head);
+    if (cp-head) parse_tiff(0);
+  } else if (order == 0x4949 || order == 0x4d4d) {
+    if (!memcmp (head+6,"HEAPCCDR",8)) {
+      data_offset = hlen;
+      parse_ciff (hlen, fsize - hlen);
+    } else {
+      parse_tiff(0);
+    }
+  } else if (!memcmp (head,"\xff\xd8\xff\xe1",4) &&
+	     !memcmp (head+6,"Exif",4)) {
+    fseek (ifp, 4, SEEK_SET);
+    data_offset = 4 + get2();
+    fseek (ifp, data_offset, SEEK_SET);
+    if (fgetc(ifp) != 0xff)
+      parse_tiff(12);
+    thumb_offset = 0;
+  } else if (!memcmp (head+25,"ARECOYK",7)) {
+    strcpy (make, "Contax");
+    strcpy (model,"N Digital");
+    fseek (ifp, 33, SEEK_SET);
+    get_timestamp(1);
+    fseek (ifp, 60, SEEK_SET);
+    FORC4 cam_mul[c ^ (c >> 1)] = get4();
+#ifdef LIBRAW_LIBRARY_BUILD
+    color_flags.cam_mul_state = LIBRAW_COLORSTATE_LOADED;
+#endif
+  } else if (!strcmp (head, "PXN")) {
+    strcpy (make, "Logitech");
+    strcpy (model,"Fotoman Pixtura");
+  } else if (!strcmp (head, "qktk")) {
+    strcpy (make, "Apple");
+    strcpy (model,"QuickTake 100");
+  } else if (!strcmp (head, "qktn")) {
+    strcpy (make, "Apple");
+    strcpy (model,"QuickTake 150");
+  } else if (!memcmp (head,"FUJIFILM",8)) {
+    fseek (ifp, 84, SEEK_SET);
+    thumb_offset = get4();
+    thumb_length = get4();
+    fseek (ifp, 92, SEEK_SET);
+    parse_fuji (get4());
+    if (thumb_offset > 120) {
+      fseek (ifp, 120, SEEK_SET);
+      is_raw += (i = get4()) && 1;
+      if (is_raw == 2 && shot_select)
+	parse_fuji (i);
+    }
+    fseek (ifp, 100, SEEK_SET);
+    data_offset = get4();
+    parse_tiff (thumb_offset+12);
+  } else if (!memcmp (head,"RIFF",4)) {
+    fseek (ifp, 0, SEEK_SET);
+    parse_riff();
+  } else if (!memcmp (head,"\0\001\0\001\0@",6)) {
+    fseek (ifp, 6, SEEK_SET);
+    fread (make, 1, 8, ifp);
+    fread (model, 1, 8, ifp);
+    fread (model2, 1, 16, ifp);
+    data_offset = get2();
+    get2();
+    raw_width = get2();
+    raw_height = get2();
+    load_raw = &CLASS nokia_load_raw;
+    filters = 0x61616161;
+  } else if (!memcmp (head,"DSC-Image",9))
+    parse_rollei();
+  else if (!memcmp (head,"PWAD",4))
+    parse_sinar_ia();
+  else if (!memcmp (head,"\0MRM",4))
+    parse_minolta(0);
+#ifndef LIBRAW_LIBRARY_BUILD
+  else if (!memcmp (head,"FOVb",4))
+    parse_foveon();
+#endif
+  else if (!memcmp (head,"CI",2))
+    parse_cine();
+  else
+    for (i=0; i < sizeof table / sizeof *table; i++)
+      if (fsize == table[i].fsize) {
+	strcpy (make,  table[i].t_make );
+	strcpy (model, table[i].t_model);
+	if (table[i].withjpeg)
+	  parse_external_jpeg();
+      }
+  if (make[0] == 0) parse_smal (0, fsize);
+  if (make[0] == 0) parse_jpeg (is_raw = 0);
+
+  for (i=0; i < sizeof corp / sizeof *corp; i++)
+    if (strstr (make, corp[i]))		/* Simplify company names */
+	strcpy (make, corp[i]);
+  if (!strncmp (make,"KODAK",5) &&
+	((cp = strstr(model," DIGITAL CAMERA")) ||
+	 (cp = strstr(model," Digital Camera")) ||
+	 (cp = strstr(model,"FILE VERSION"))))
+     *cp = 0;
+  cp = make + strlen(make);		/* Remove trailing spaces */
+  while (*--cp == ' ') *cp = 0;
+  cp = model + strlen(model);
+  while (*--cp == ' ') *cp = 0;
+  i = strlen(make);			/* Remove make from model */
+  if (!strncasecmp (model, make, i) && model[i++] == ' ')
+    memmove (model, model+i, 64-i);
+  if (!strncmp (model,"Digital Camera ",15))
+    strcpy (model, model+15);
+  desc[511] = artist[63] = make[63] = model[63] = model2[63] = 0;
+  if (!is_raw) goto notraw;
+
+  if (!height) height = raw_height;
+  if (!width)  width  = raw_width;
+  if (fuji_width) {
+    width = height + fuji_width;
+    height = width - 1;
+    pixel_aspect = 1;
+  }
+  if (height == 2624 && width == 3936)	/* Pentax K10D and Samsung GX10 */
+    { height  = 2616;   width  = 3896; }
+  if (height == 3136 && width == 4864)	/* Pentax K20D */
+    { height  = 3124;   width  = 4688; }
+  if (height == 3136 && width == 4736)	/* Pentax K-7 */
+    { height  = 3122;   width  = 4684;
+      top_margin = 2;  filters = 0x16161616; }
+  if (height == 3014 && width == 4096)	/* Ricoh GX200 */
+			width  = 4014;
+  if (dng_version) {
+    if (filters == UINT_MAX) filters = 0;
+    if (filters) is_raw = tiff_samples;
+    else	 colors = tiff_samples;
+    if (tiff_compress == 1)
+      load_raw = &CLASS adobe_dng_load_raw_nc;
+    if (tiff_compress == 7)
+      load_raw = &CLASS adobe_dng_load_raw_lj;
+    goto dng_skip;
+  }
+  if ((is_canon = !strcmp(make,"Canon")))
+    load_raw = memcmp (head+6,"HEAPCCDR",8) ?
+	&CLASS lossless_jpeg_load_raw : &CLASS canon_compressed_load_raw;
+  if (!strcmp(make,"NIKON")) {
+    if (!load_raw)
+      load_raw = &CLASS packed_load_raw;
+    if (model[0] == 'E')
+      load_flags |= !data_offset << 2 | 2;
+  }
+  if (!strcmp(make,"CASIO")) {
+    load_raw = &CLASS packed_load_raw;
+    maximum = 0xf7f;
+  }
+
+/* Set parameters based on camera name (for non-DNG files). */
+
+#ifndef LIBRAW_LIBRARY_BUILD
+  if (is_foveon) {
+    if (height*2 < width) pixel_aspect = 0.5;
+    if (height   > width) pixel_aspect = 2;
+    filters = 0;
+    load_raw = &CLASS foveon_load_raw;
+    simple_coeff(0);
+  } else 
+#endif
+if (is_canon && tiff_bps == 15) {
+    switch (width) {
+      case 3344: width -= 66;
+      case 3872: width -= 6;
+    }
+    filters = 0;
+    load_raw = &CLASS canon_sraw_load_raw;
+  } else if (!strcmp(model,"PowerShot 600")) {
+    height = 613;
+    width  = 854;
+    raw_width = 896;
+    pixel_aspect = 607/628.0;
+    colors = 4;
+    filters = 0xe1e4e1e4;
+    load_raw = &CLASS canon_600_load_raw;
+  } else if (!strcmp(model,"PowerShot A5") ||
+	     !strcmp(model,"PowerShot A5 Zoom")) {
+    height = 773;
+    width  = 960;
+    raw_width = 992;
+    pixel_aspect = 256/235.0;
+    colors = 4;
+    filters = 0x1e4e1e4e;
+    goto canon_a5;
+  } else if (!strcmp(model,"PowerShot A50")) {
+    height =  968;
+    width  = 1290;
+    raw_width = 1320;
+    colors = 4;
+    filters = 0x1b4e4b1e;
+    goto canon_a5;
+  } else if (!strcmp(model,"PowerShot Pro70")) {
+    height = 1024;
+    width  = 1552;
+    colors = 4;
+    filters = 0x1e4b4e1b;
+    goto canon_a5;
+  } else if (!strcmp(model,"PowerShot SD300")) {
+    height = 1752;
+    width  = 2344;
+    raw_height = 1766;
+    raw_width  = 2400;
+    top_margin  = 12;
+    left_margin = 12;
+    goto canon_a5;
+  } else if (!strcmp(model,"PowerShot A460")) {
+    height = 1960;
+    width  = 2616;
+    raw_height = 1968;
+    raw_width  = 2664;
+    top_margin  = 4;
+    left_margin = 4;
+    goto canon_a5;
+  } else if (!strcmp(model,"PowerShot A530")) {
+    height = 1984;
+    width  = 2620;
+    raw_height = 1992;
+    raw_width  = 2672;
+    top_margin  = 6;
+    left_margin = 10;
+    goto canon_a5;
+  } else if (!strcmp(model,"PowerShot A610")) {
+    if (canon_s2is()) strcpy (model+10, "S2 IS");
+    height = 1960;
+    width  = 2616;
+    raw_height = 1968;
+    raw_width  = 2672;
+    top_margin  = 8;
+    left_margin = 12;
+    goto canon_a5;
+  } else if (!strcmp(model,"PowerShot A620")) {
+    height = 2328;
+    width  = 3112;
+    raw_height = 2340;
+    raw_width  = 3152;
+    top_margin  = 12;
+    left_margin = 36;
+    goto canon_a5;
+  } else if (!strcmp(model,"PowerShot A470")) {
+    height = 2328;
+    width  = 3096;
+    raw_height = 2346;
+    raw_width  = 3152;
+    top_margin  = 6;
+    left_margin = 12;
+    goto canon_a5;
+  } else if (!strcmp(model,"PowerShot A720")) {
+    height = 2472;
+    width  = 3298;
+    raw_height = 2480;
+    raw_width  = 3336;
+    top_margin  = 5;
+    left_margin = 6;
+    goto canon_a5;
+  } else if (!strcmp(model,"PowerShot A630")) {
+    height = 2472;
+    width  = 3288;
+    raw_height = 2484;
+    raw_width  = 3344;
+    top_margin  = 6;
+    left_margin = 12;
+    goto canon_a5;
+  } else if (!strcmp(model,"PowerShot A640")) {
+    height = 2760;
+    width  = 3672;
+    raw_height = 2772;
+    raw_width  = 3736;
+    top_margin  = 6;
+    left_margin = 12;
+    goto canon_a5;
+  } else if (!strcmp(model,"PowerShot A650")) {
+    height = 3024;
+    width  = 4032;
+    raw_height = 3048;
+    raw_width  = 4104;
+    top_margin  = 12;
+    left_margin = 48;
+    goto canon_a5;
+  } else if (!strcmp(model,"PowerShot S3 IS")) {
+    height = 2128;
+    width  = 2840;
+    raw_height = 2136;
+    raw_width  = 2888;
+    top_margin  = 8;
+    left_margin = 44;
+canon_a5:
+    tiff_bps = 10;
+    load_raw = &CLASS packed_load_raw;
+    load_flags = 40;
+    if (raw_width > 1600) zero_is_bad = 1;
+  } else if (!strcmp(model,"PowerShot SX110 IS")) {
+    height = 2760;
+    width  = 3684;
+    raw_height = 2772;
+    raw_width  = 3720;
+    top_margin  = 12;
+    left_margin = 6;
+    load_raw = &CLASS packed_load_raw;
+    load_flags = 40;
+    zero_is_bad = 1;
+  } else if (!strcmp(model,"PowerShot Pro90 IS")) {
+    width  = 1896;
+    colors = 4;
+    filters = 0xb4b4b4b4;
+  } else if (is_canon && raw_width == 2144) {
+    height = 1550;
+    width  = 2088;
+    top_margin  = 8;
+    left_margin = 4;
+    if (!strcmp(model,"PowerShot G1")) {
+      colors = 4;
+      filters = 0xb4b4b4b4;
+    }
+  } else if (is_canon && raw_width == 2224) {
+    height = 1448;
+    width  = 2176;
+    top_margin  = 6;
+    left_margin = 48;
+  } else if (is_canon && raw_width == 2376) {
+    height = 1720;
+    width  = 2312;
+    top_margin  = 6;
+    left_margin = 12;
+  } else if (is_canon && raw_width == 2672) {
+    height = 1960;
+    width  = 2616;
+    top_margin  = 6;
+    left_margin = 12;
+  } else if (is_canon && raw_width == 3152) {
+    height = 2056;
+    width  = 3088;
+    top_margin  = 12;
+    left_margin = 64;
+    if (unique_id == 0x80000170)
+      adobe_coeff ("Canon","EOS 300D");
+  } else if (is_canon && raw_width == 3160) {
+    height = 2328;
+    width  = 3112;
+    top_margin  = 12;
+    left_margin = 44;
+  } else if (is_canon && raw_width == 3344) {
+    height = 2472;
+    width  = 3288;
+    top_margin  = 6;
+    left_margin = 4;
+  } else if (!strcmp(model,"EOS D2000C")) {
+    filters = 0x61616161;
+    black = curve[200];
+  } else if (is_canon && raw_width == 3516) {
+    top_margin  = 14;
+    left_margin = 42;
+    if (unique_id == 0x80000189)
+      adobe_coeff ("Canon","EOS 350D");
+    goto canon_cr2;
+  } else if (is_canon && raw_width == 3596) {
+    top_margin  = 12;
+    left_margin = 74;
+    goto canon_cr2;
+  } else if (is_canon && raw_width == 3744) {
+    height = 2760;
+    width  = 3684;
+    top_margin  = 16;
+    left_margin = 8;
+  } else if (is_canon && raw_width == 3944) {
+    height = 2602;
+    width  = 3908;
+    top_margin  = 18;
+    left_margin = 30;
+  } else if (is_canon && raw_width == 3948) {
+    top_margin  = 18;
+    left_margin = 42;
+    height -= 2;
+    if (unique_id == 0x80000236)
+      adobe_coeff ("Canon","EOS 400D");
+    if (unique_id == 0x80000254)
+      adobe_coeff ("Canon","EOS 1000D");
+    goto canon_cr2;
+  } else if (is_canon && raw_width == 3984) {
+    top_margin  = 20;
+    left_margin = 76;
+    height -= 2;
+    goto canon_cr2;
+  } else if (is_canon && raw_width == 4104) {
+    height = 3024;
+    width  = 4032;
+    top_margin  = 12;
+    left_margin = 48;
+  } else if (is_canon && raw_width == 4152) {
+    top_margin  = 12;
+    left_margin = 192;
+    goto canon_cr2;
+  } else if (is_canon && raw_width == 4312) {
+    top_margin  = 18;
+    left_margin = 22;
+    height -= 2;
+    if (unique_id == 0x80000176)
+      adobe_coeff ("Canon","EOS 450D");
+    goto canon_cr2;
+  } else if (is_canon && raw_width == 4476) {
+    top_margin  = 34;
+    left_margin = 90;
+    goto canon_cr2;
+  } else if (is_canon && raw_width == 4480) {
+    height = 3326;
+    width  = 4432;
+    top_margin  = 10;
+    left_margin = 12;
+    filters = 0x49494949;
+  } else if (is_canon && raw_width == 1208) {
+    top_margin = unique_id == 0x80000261 ? 51:26;
+    left_margin = 62;
+    raw_width = width *= 4;
+    if (unique_id == 0x80000252)
+      adobe_coeff ("Canon","EOS 500D");
+    goto canon_cr2;
+  } else if (is_canon && raw_width == 1280) {
+    height -= top_margin = 45;
+    left_margin = 142;
+    raw_width *= 4;
+    width = 4916;
+  } else if (is_canon && raw_width == 1340) {
+    top_margin = 51;
+    left_margin = 158;
+    raw_width = width *= 4;
+    goto canon_cr2;
+  } else if (is_canon && raw_width == 1448) {
+    top_margin  = 51;
+    left_margin = 158;
+    raw_width = width *= 4;
+    goto canon_cr2;
+  } else if (is_canon && raw_width == 5108) {
+    top_margin  = 13;
+    left_margin = 98;
+canon_cr2:
+    height -= top_margin;
+    width  -= left_margin;
+  } else if (is_canon && raw_width == 5712) {
+    height = 3752;
+    width  = 5640;
+    top_margin  = 20;
+    left_margin = 62;
+  } else if (!strcmp(model,"D1")) {
+    cam_mul[0] *= 256/527.0;
+    cam_mul[2] *= 256/317.0;
+  } else if (!strcmp(model,"D1X")) {
+    width -= 4;
+    pixel_aspect = 0.5;
+  } else if (!strcmp(model,"D40X") ||
+	     !strcmp(model,"D60")  ||
+	     !strcmp(model,"D80")  ||
+	     !strcmp(model,"D3000")) {
+    height -= 3;
+    width  -= 4;
+  } else if (!strcmp(model,"D3")   ||
+	     !strcmp(model,"D3S")  ||
+	     !strcmp(model,"D700")) {
+    width -= 4;
+    left_margin = 2;
+  } else if (!strcmp(model,"D5000")) {
+    width -= 42;
+  } else if (!strncmp(model,"D40",3) ||
+	     !strncmp(model,"D50",3) ||
+	     !strncmp(model,"D70",3)) {
+    width--;
+  } else if (!strcmp(model,"D90")) {
+    width -= 42;
+  } else if (!strcmp(model,"D100")) {
+    if (tiff_compress == 34713 && !nikon_is_compressed()) {
+      load_raw = &CLASS packed_load_raw;
+      load_flags |= 1;
+      raw_width = (width += 3) + 3;
+    }
+  } else if (!strcmp(model,"D200")) {
+    left_margin = 1;
+    width -= 4;
+    filters = 0x94949494;
+  } else if (!strncmp(model,"D2H",3)) {
+    left_margin = 6;
+    width -= 14;
+  } else if (!strncmp(model,"D2X",3)) {
+    if (width == 3264) width -= 32;
+    else width -= 8;
+  } else if (!strncmp(model,"D300",4)) {
+    width -= 32;
+  } else if (!strcmp(model,"COOLPIX P6000")) {
+    load_flags = 24;
+    filters = 0x94949494;
+  } else if (fsize == 1581060) {
+    height = 963;
+    width = 1287;
+    raw_width = 1632;
+    maximum = 0x3f4;
+    colors = 4;
+    filters = 0x1e1e1e1e;
+    simple_coeff(3);
+    pre_mul[0] = 1.2085;
+    pre_mul[1] = 1.0943;
+    pre_mul[3] = 1.1103;
+#ifdef LIBRAW_LIBRARY_BUILD
+    color_flags.pre_mul_state = LIBRAW_COLORSTATE_CONST;
+#endif
+    goto e900;
+  } else if (fsize == 2465792) {
+    height = 1203;
+    width  = 1616;
+    raw_width = 2048;
+    colors = 4;
+    filters = 0x4b4b4b4b;
+    adobe_coeff ("NIKON","E950");
+e900:
+    tiff_bps = 10;
+    load_raw = &CLASS packed_load_raw;
+    load_flags = 6;
+  } else if (fsize == 4771840) {
+    height = 1540;
+    width  = 2064;
+    colors = 4;
+    filters = 0xe1e1e1e1;
+    load_raw = &CLASS packed_load_raw;
+    load_flags = 6;
+    if (!timestamp && nikon_e995())
+      strcpy (model, "E995");
+    if (strcmp(model,"E995")) {
+      filters = 0xb4b4b4b4;
+      simple_coeff(3);
+      pre_mul[0] = 1.196;
+      pre_mul[1] = 1.246;
+      pre_mul[2] = 1.018;
+#ifdef LIBRAW_LIBRARY_BUILD
+      color_flags.pre_mul_state = LIBRAW_COLORSTATE_CONST;
+#endif
+    }
+  } else if (!strcmp(model,"E2100")) {
+    if (!timestamp && !nikon_e2100()) goto cp_e2500;
+    height = 1206;
+    width  = 1616;
+    load_flags = 30;
+  } else if (!strcmp(model,"E2500")) {
+cp_e2500:
+    strcpy (model, "E2500");
+    height = 1204;
+    width  = 1616;
+    colors = 4;
+    filters = 0x4b4b4b4b;
+  } else if (fsize == 4775936) {
+    height = 1542;
+    width  = 2064;
+    load_raw = &CLASS packed_load_raw;
+    load_flags = 30;
+    if (!timestamp) nikon_3700();
+    if (model[0] == 'E' && atoi(model+1) < 3700)
+      filters = 0x49494949;
+    if (!strcmp(model,"Optio 33WR")) {
+      flip = 1;
+      filters = 0x16161616;
+    }
+    if (make[0] == 'O') {
+      i = find_green (12, 32, 0, fsize/2);
+      c = find_green (12, 32, 0, 3096);
+      if (abs(i) < abs(c)) {
+	SWAP(i,c);
+	load_flags = 24;
+      }
+      if (i < 0) filters = 0x61616161;
+    }
+  } else if (fsize == 5869568) {
+    height = 1710;
+    width  = 2288;
+    filters = 0x16161616;
+    if (!timestamp && minolta_z2()) {
+      strcpy (make, "Minolta");
+      strcpy (model,"DiMAGE Z2");
+    }
+    load_raw = &CLASS packed_load_raw;
+    load_flags = 6 + 24*(make[0] == 'M');
+  } else if (!strcmp(model,"E4500")) {
+    height = 1708;
+    width  = 2288;
+    colors = 4;
+    filters = 0xb4b4b4b4;
+  } else if (fsize == 7438336) {
+    height = 1924;
+    width  = 2576;
+    colors = 4;
+    filters = 0xb4b4b4b4;
+  } else if (fsize == 8998912) {
+    height = 2118;
+    width  = 2832;
+    maximum = 0xf83;
+    load_raw = &CLASS packed_load_raw;
+    load_flags = 30;
+  } else if (!strcmp(make,"FUJIFILM")) {
+    if (!strcmp(model+7,"S2Pro")) {
+      strcpy (model+7," S2Pro");
+      height = 2144;
+      width  = 2880;
+      flip = 6;
+    } else
+      maximum = 0x3e00;
+    if (is_raw == 2 && shot_select)
+      maximum = 0x2f00;
+    top_margin = (raw_height - height)/2;
+    left_margin = (raw_width - width )/2;
+    if (is_raw == 2)
+      data_offset += (shot_select > 0) * ( fuji_layout ?
+		(raw_width *= 2) : raw_height*raw_width*2 );
+    if (load_raw == &CLASS fuji_load_raw) {
+      fuji_width = width >> !fuji_layout;
+      width = (height >> fuji_layout) + fuji_width;
+      raw_height = height;
+      height = width - 1;
+      if (~fuji_width & 1) filters = 0x49494949;
+    }
+  } else if (!strcmp(model,"RD175")) {
+    height = 986;
+    width = 1534;
+    data_offset = 513;
+    filters = 0x61616161;
+    load_raw = &CLASS minolta_rd175_load_raw;
+  } else if (!strcmp(model,"KD-400Z")) {
+    height = 1712;
+    width  = 2312;
+    raw_width = 2336;
+    goto konica_400z;
+  } else if (!strcmp(model,"KD-510Z")) {
+    goto konica_510z;
+  } else if (!strcasecmp(make,"MINOLTA")) {
+    load_raw = &CLASS unpacked_load_raw;
+    maximum = 0xfff;
+    if (!strncmp(model,"DiMAGE A",8)) {
+      if (!strcmp(model,"DiMAGE A200"))
+	filters = 0x49494949;
+      tiff_bps = 12;
+      load_raw = &CLASS packed_load_raw;
+    } else if (!strncmp(model,"ALPHA",5) ||
+	       !strncmp(model,"DYNAX",5) ||
+	       !strncmp(model,"MAXXUM",6)) {
+      sprintf (model+20, "DYNAX %-10s", model+6+(model[0]=='M'));
+      adobe_coeff (make, model+20);
+      load_raw = &CLASS packed_load_raw;
+    } else if (!strncmp(model,"DiMAGE G",8)) {
+      if (model[8] == '4') {
+	height = 1716;
+	width  = 2304;
+      } else if (model[8] == '5') {
+konica_510z:
+	height = 1956;
+	width  = 2607;
+	raw_width = 2624;
+      } else if (model[8] == '6') {
+	height = 2136;
+	width  = 2848;
+      }
+      data_offset += 14;
+      filters = 0x61616161;
+konica_400z:
+      load_raw = &CLASS unpacked_load_raw;
+      maximum = 0x3df;
+      order = 0x4d4d;
+    }
+  } else if (!strcmp(model,"*ist D")) {
+    data_error = -1;
+  } else if (!strcmp(model,"*ist DS")) {
+    height -= 2;
+  } else if (!strcmp(model,"K20D")) {
+    filters = 0x16161616;
+  } else if (!strcmp(model,"K-x")) {
+    width = 4309;
+    filters = 0x16161616;
+  } else if (!strcmp(model,"Optio S")) {
+    if (fsize == 3178560) {
+      height = 1540;
+      width  = 2064;
+      load_raw = &CLASS eight_bit_load_raw;
+      cam_mul[0] *= 4;
+      cam_mul[2] *= 4;
+    } else {
+      height = 1544;
+      width  = 2068;
+      raw_width = 3136;
+      load_raw = &CLASS packed_load_raw;
+      maximum = 0xf7c;
+    }
+  } else if (fsize == 6114240) {
+    height = 1737;
+    width  = 2324;
+    raw_width = 3520;
+    load_raw = &CLASS packed_load_raw;
+    maximum = 0xf7a;
+  } else if (!strcmp(model,"Optio 750Z")) {
+    height = 2302;
+    width  = 3072;
+    load_raw = &CLASS packed_load_raw;
+    load_flags = 30;
+  } else if (!strcmp(model,"DC-833m")) {
+    height = 2448;
+    width  = 3264;
+    order = 0x4949;
+    filters = 0x61616161;
+    load_raw = &CLASS unpacked_load_raw;
+    maximum = 0xfc00;
+  } else if (!strncmp(model,"S85",3)) {
+    height = 2448;
+    width  = 3264;
+    raw_width = fsize/height/2;
+    order = 0x4d4d;
+    load_raw = &CLASS unpacked_load_raw;
+    maximum = 0xffff;
+  } else if (!strcmp(model,"STV680 VGA")) {
+    height = 484;
+    width  = 644;
+    load_raw = &CLASS eight_bit_load_raw;
+    flip = 2;
+    filters = 0x16161616;
+    black = 16;
+  } else if (!strcmp(model,"N95")) {
+    height = raw_height - (top_margin = 2);
+  } else if (!strcmp(model,"531C")) {
+    height = 1200;
+    width  = 1600;
+    load_raw = &CLASS unpacked_load_raw;
+    filters = 0x49494949;
+  } else if (!strcmp(model,"F-080C")) {
+    height = 768;
+    width  = 1024;
+    load_raw = &CLASS eight_bit_load_raw;
+  } else if (!strcmp(model,"F-145C")) {
+    height = 1040;
+    width  = 1392;
+    load_raw = &CLASS eight_bit_load_raw;
+  } else if (!strcmp(model,"F-201C")) {
+    height = 1200;
+    width  = 1600;
+    load_raw = &CLASS eight_bit_load_raw;
+  } else if (!strcmp(model,"F-510C")) {
+    height = 1958;
+    width  = 2588;
+    load_raw = fsize < 7500000 ?
+	&CLASS eight_bit_load_raw : &CLASS unpacked_load_raw;
+    maximum = 0xfff0;
+  } else if (!strcmp(model,"F-810C")) {
+    height = 2469;
+    width  = 3272;
+    load_raw = &CLASS unpacked_load_raw;
+    maximum = 0xfff0;
+  } else if (!strcmp(model,"XCD-SX910CR")) {
+    height = 1024;
+    width  = 1375;
+    raw_width = 1376;
+    filters = 0x49494949;
+    maximum = 0x3ff;
+    load_raw = fsize < 2000000 ?
+	&CLASS eight_bit_load_raw : &CLASS unpacked_load_raw;
+  } else if (!strcmp(model,"2010")) {
+    height = 1207;
+    width  = 1608;
+    order = 0x4949;
+    filters = 0x16161616;
+    data_offset = 3212;
+    maximum = 0x3ff;
+    load_raw = &CLASS unpacked_load_raw;
+  } else if (!strcmp(model,"A782")) {
+    height = 3000;
+    width  = 2208;
+    filters = 0x61616161;
+    load_raw = fsize < 10000000 ?
+	&CLASS eight_bit_load_raw : &CLASS unpacked_load_raw;
+    maximum = 0xffc0;
+  } else if (!strcmp(model,"3320AF")) {
+    height = 1536;
+    raw_width = width = 2048;
+    filters = 0x61616161;
+    load_raw = &CLASS unpacked_load_raw;
+    maximum = 0x3ff;
+    fseek (ifp, 0x300000, SEEK_SET);
+    if ((order = guess_byte_order(0x10000)) == 0x4d4d) {
+      height -= (top_margin = 16);
+      width -= (left_margin = 28);
+      maximum = 0xf5c0;
+      strcpy (make, "ISG");
+      model[0] = 0;
+    }
+  } else if (!strcmp(make,"Hasselblad")) {
+    if (load_raw == &CLASS lossless_jpeg_load_raw)
+      load_raw = &CLASS hasselblad_load_raw;
+    if (raw_width == 7262) {
+      height = 5444;
+      width  = 7248;
+      top_margin  = 4;
+      left_margin = 7;
+      filters = 0x61616161;
+    } else if (raw_width == 4090) {
+      strcpy (model, "V96C");
+      height -= (top_margin = 6);
+      width -= (left_margin = 3) + 7;
+      filters = 0x61616161;
+    }
+  } else if (!strcmp(make,"Sinar")) {
+    if (!memcmp(head,"8BPS",4)) {
+      fseek (ifp, 14, SEEK_SET);
+      height = get4();
+      width  = get4();
+      filters = 0x61616161;
+      data_offset = 68;
+    }
+    if (!load_raw) load_raw = &CLASS unpacked_load_raw;
+    maximum = 0x3fff;
+  } else if (!strcmp(make,"Leaf")) {
+    maximum = 0x3fff;
+    fseek (ifp, data_offset, SEEK_SET);
+    if (ljpeg_start (&jh, 1) && jh.bits == 15)
+      maximum = 0x1fff;
+    if (tiff_samples > 1) filters = 0;
+    if (tiff_samples > 1 || tile_length < raw_height)
+      load_raw = &CLASS leaf_hdr_load_raw;
+    if ((width | height) == 2048) {
+      if (tiff_samples == 1) {
+	filters = 1;
+	strcpy (cdesc, "RBTG");
+	strcpy (model, "CatchLight");
+	top_margin =  8; left_margin = 18; height = 2032; width = 2016;
+      } else {
+	strcpy (model, "DCB2");
+	top_margin = 10; left_margin = 16; height = 2028; width = 2022;
+      }
+    } else if (width+height == 3144+2060) {
+      if (!model[0]) strcpy (model, "Cantare");
+      if (width > height) {
+	 top_margin = 6; left_margin = 32; height = 2048;  width = 3072;
+	filters = 0x61616161;
+      } else {
+	left_margin = 6;  top_margin = 32;  width = 2048; height = 3072;
+	filters = 0x16161616;
+      }
+      if (!cam_mul[0] || model[0] == 'V') filters = 0;
+      else is_raw = tiff_samples;
+    } else if (width == 2116) {
+      strcpy (model, "Valeo 6");
+      height -= 2 * (top_margin = 30);
+      width -= 2 * (left_margin = 55);
+      filters = 0x49494949;
+    } else if (width == 3171) {
+      strcpy (model, "Valeo 6");
+      height -= 2 * (top_margin = 24);
+      width -= 2 * (left_margin = 24);
+      filters = 0x16161616;
+    }
+  } else if (!strcmp(make,"LEICA") || !strcmp(make,"Panasonic")) {
+    maximum = 0xfff0;
+    if ((fsize-data_offset) / (width*8/7) == height)
+      load_raw = &CLASS panasonic_load_raw;
+    if (!load_raw) load_raw = &CLASS unpacked_load_raw;
+    switch (width) {
+      case 2568:
+	adobe_coeff ("Panasonic","DMC-LC1");  break;
+      case 3130:
+	left_margin = -14;
+      case 3170:
+	left_margin += 18;
+	width = 3096;
+	if (height > 2326) {
+	  height = 2326;
+	  top_margin = 13;
+	  filters = 0x49494949;
+	}
+	zero_is_bad = 1;
+	adobe_coeff ("Panasonic","DMC-FZ8");  break;
+      case 3213:
+	width -= 27;
+      case 3177:
+	width -= 10;
+	filters = 0x49494949;
+	zero_is_bad = 1;
+	adobe_coeff ("Panasonic","DMC-L1");  break;
+      case 3304:
+	width -= 17;
+	zero_is_bad = 1;
+	adobe_coeff ("Panasonic","DMC-FZ30");  break;
+      case 3330:
+	width += 43;
+	left_margin = -6;
+	maximum = 0xf7f0;
+      case 3370:
+	width -= 82;
+	left_margin += 15;
+	if (height > 2480)
+	    height = 2480 - (top_margin = 10);
+	filters = 0x49494949;
+	zero_is_bad = 1;
+	adobe_coeff ("Panasonic","DMC-FZ18");  break;
+      case 3690:
+	height -= 2;
+	left_margin = -14;
+	maximum = 0xf7f0;
+      case 3770:
+	width = 3672;
+	if (--height == 2798 && (height = 2760))
+	  top_margin = 15;
+	else filters = 0x49494949;
+	left_margin += 17;
+	zero_is_bad = 1;
+	adobe_coeff ("Panasonic","DMC-FZ50");  break;
+      case 3710:
+	width = 3682;
+	filters = 0x49494949;
+	adobe_coeff ("Panasonic","DMC-L10");  break;
+      case 3724:
+	width -= 14;
+	if (height == 2450) height -= 2;
+      case 3836:
+	width -= 42;
+lx3:	filters = 0x16161616;
+	if (make[0] != 'P')
+	  adobe_coeff ("Panasonic","DMC-LX3");
+	break;
+      case 3880:
+	width -= 22;
+	left_margin = 6;
+	zero_is_bad = 1;
+	adobe_coeff ("Panasonic","DMC-LX1");  break;
+      case 4060:
+	width = 3982;
+	if (height == 2250) goto lx3;
+	width = 4018;
+	filters = 0x16161616;
+	if (!strncmp(model,"DMC-FZ3",7)) {
+	  height -= 2;
+	  adobe_coeff ("Panasonic","DMC-FZ35");  break;
+	}
+	filters = 0x49494949;
+	if (!strcmp(model,"DMC-GH1")) break;
+	zero_is_bad = 1;
+	adobe_coeff ("Panasonic","DMC-G1");  break;
+      case 4172:
+      case 4396:
+	width -= 28;
+	filters = 0x49494949;
+	adobe_coeff ("Panasonic","DMC-GH1");  break;
+      case 4290:
+	height += 38;
+	left_margin = -14;
+	filters = 0x49494949;
+      case 4330:
+	width = 4248;
+	if ((height -= 39) == 2400)
+	  top_margin = 15;
+	left_margin += 17;
+	adobe_coeff ("Panasonic","DMC-LX2");  break;
+      case 4508:
+	height -= 6;
+	width = 4429;
+	filters = 0x16161616;
+	adobe_coeff ("Panasonic","DMC-FX150");  break;
+    }
+  } else if (!strcmp(model,"C770UZ")) {
+    height = 1718;
+    width  = 2304;
+    filters = 0x16161616;
+    load_raw = &CLASS packed_load_raw;
+    load_flags = 30;
+  } else if (!strcmp(make,"OLYMPUS")) {
+    height += height & 1;
+    filters = exif_cfa;
+    if (width == 4100) width -= 4;
+    if (load_raw == &CLASS olympus_load_raw) {
+      tiff_bps = 12;
+      black >>= 4;
+    } else if (!strcmp(model,"E-10") ||
+	      !strncmp(model,"E-20",4)) {
+      black <<= 2;
+    } else if (!strcmp(model,"E-300") ||
+	       !strcmp(model,"E-500")) {
+      width -= 20;
+      if (load_raw == &CLASS unpacked_load_raw) {
+	maximum = 0xfc30;
+	black = 0;
+      }
+    } else if (!strcmp(model,"E-330")) {
+      width -= 30;
+      if (load_raw == &CLASS unpacked_load_raw)
+	maximum = 0xf790;
+    } else if (!strcmp(model,"SP550UZ")) {
+      thumb_length = fsize - (thumb_offset = 0xa39800);
+      thumb_height = 480;
+      thumb_width  = 640;
+    }
+  } else if (!strcmp(model,"N Digital")) {
+    height = 2047;
+    width  = 3072;
+    filters = 0x61616161;
+    data_offset = 0x1a00;
+    load_raw = &CLASS packed_load_raw;
+  } else if (!strcmp(model,"DSC-F828")) {
+    width = 3288;
+    left_margin = 5;
+    data_offset = 862144;
+    load_raw = &CLASS sony_load_raw;
+    filters = 0x9c9c9c9c;
+    colors = 4;
+    strcpy (cdesc, "RGBE");
+  } else if (!strcmp(model,"DSC-V3")) {
+    width = 3109;
+    left_margin = 59;
+    data_offset = 787392;
+    load_raw = &CLASS sony_load_raw;
+  } else if (!strcmp(make,"SONY") && raw_width == 3984) {
+    adobe_coeff ("SONY","DSC-R1");
+    width = 3925;
+    order = 0x4d4d;
+  } else if (!strcmp(model,"DSLR-A100")) {
+    height--;
+    width = ++raw_width;
+    filters = 0x61616161;
+  } else if (!strcmp(model,"DSLR-A350")) {
+    height -= 4;
+  } else if (!strcmp(model,"PIXL")) {
+    height -= top_margin = 4;
+    width -= left_margin = 32;
+    gamma_curve (0, 7, 1, 255);
+  } else if (!strcmp(model,"C603v")) {
+    height = 480;
+    width  = 640;
+    if (fsize < 614400 || find_green (16, 16, 3840, 5120) < 25) goto c603v;
+    strcpy (model,"KAI-0340");
+    height -= 3;
+    data_offset = 3840;
+    order = 0x4949;
+    load_raw = &CLASS unpacked_load_raw;
+  } else if (!strcmp(model,"C603y")) {
+    height = 2134;
+    width  = 2848;
+c603v:
+    filters = 0;
+    load_raw = &CLASS kodak_yrgb_load_raw;
+    gamma_curve (0, 3.875, 1, 255);
+  } else if (!strcmp(model,"C603")) {
+    raw_height = height = 2152;
+    raw_width  = width  = 2864;
+    goto c603;
+  } else if (!strcmp(model,"C330")) {
+    height = 1744;
+    width  = 2336;
+    raw_height = 1779;
+    raw_width  = 2338;
+    top_margin = 33;
+    left_margin = 1;
+c603:
+    order = 0x4949;
+    if ((data_offset = fsize - raw_height*raw_width)) {
+      fseek (ifp, 168, SEEK_SET);
+      read_shorts (curve, 256);
+#ifdef LIBRAW_LIBRARY_BUILD
+      color_flags.curve_state = LIBRAW_COLORSTATE_LOADED;
+#endif
+    } else gamma_curve (0, 3.875, 1, 255);
+    load_raw = &CLASS eight_bit_load_raw;
+  }
+#if 1
+  else
+      identify2(fsize,head); /* Avoid MS VS 2008 bug */
+#else
+ else if (!strcmp(model,"EASYSHARE Z1015 IS")) {
+    height = 2742;
+    width  = 3664;
+    goto ezshare;
+  } else if (!strcmp(model,"EasyShare Z980")) {
+    height = 3006;
+    width  = 4016;
+ezshare:
+    data_offset = 0x15000;
+    load_raw = &CLASS packed_load_raw;
+  } else if (!strcasecmp(make,"KODAK")) {
+    if (filters == UINT_MAX) filters = 0x61616161;
+    if (!strncmp(model,"NC2000",6)) {
+      width -= 4;
+      left_margin = 2;
+    } else if (!strcmp(model,"EOSDCS3B")) {
+      width -= 4;
+      left_margin = 2;
+    } else if (!strcmp(model,"EOSDCS1")) {
+      width -= 4;
+      left_margin = 2;
+    } else if (!strcmp(model,"DCS420")) {
+      width -= 4;
+      left_margin = 2;
+    } else if (!strncmp(model,"DCS460 ",7)) {
+      model[6] = 0;
+      width -= 4;
+      left_margin = 2;
+    } else if (!strcmp(model,"DCS460A")) {
+      width -= 4;
+      left_margin = 2;
+      colors = 1;
+      filters = 0;
+    } else if (!strcmp(model,"DCS660M")) {
+      black = 214;
+      colors = 1;
+      filters = 0;
+    } else if (!strcmp(model,"DCS760M")) {
+      colors = 1;
+      filters = 0;
+    }
+    if (!strcmp(model+4,"20X"))
+      strcpy (cdesc, "MYCY");
+    if (strstr(model,"DC25")) {
+      strcpy (model, "DC25");
+      data_offset = 15424;
+    }
+    if (!strncmp(model,"DC2",3)) {
+      height = 242;
+      if (fsize < 100000) {
+	raw_width = 256; width = 249;
+	pixel_aspect = (4.0*height) / (3.0*width);
+      } else {
+	raw_width = 512; width = 501;
+	pixel_aspect = (493.0*height) / (373.0*width);
+      }
+      data_offset += raw_width + 1;
+      colors = 4;
+      filters = 0x8d8d8d8d;
+      simple_coeff(1);
+      pre_mul[1] = 1.179;
+      pre_mul[2] = 1.209;
+      pre_mul[3] = 1.036;
+#ifdef LIBRAW_LIBRARY_BUILD
+      color_flags.pre_mul_state = LIBRAW_COLORSTATE_CONST;
+#endif
+      load_raw = &CLASS eight_bit_load_raw;
+    } else if (!strcmp(model,"40")) {
+      strcpy (model, "DC40");
+      height = 512;
+      width  = 768;
+      data_offset = 1152;
+      load_raw = &CLASS kodak_radc_load_raw;
+    } else if (strstr(model,"DC50")) {
+      strcpy (model, "DC50");
+      height = 512;
+      width  = 768;
+      data_offset = 19712;
+      load_raw = &CLASS kodak_radc_load_raw;
+    } else if (strstr(model,"DC120")) {
+      strcpy (model, "DC120");
+      height = 976;
+      width  = 848;
+      pixel_aspect = height/0.75/width;
+      load_raw = tiff_compress == 7 ?
+	&CLASS kodak_jpeg_load_raw : &CLASS kodak_dc120_load_raw;
+    } else if (!strcmp(model,"DCS200")) {
+      thumb_height = 128;
+      thumb_width  = 192;
+      thumb_offset = 6144;
+      thumb_misc   = 360;
+      write_thumb = &CLASS layer_thumb;
+      height = 1024;
+      width  = 1536;
+      data_offset = 79872;
+      load_raw = &CLASS eight_bit_load_raw;
+      black = 17;
+    }
+  } else if (!strcmp(model,"Fotoman Pixtura")) {
+    height = 512;
+    width  = 768;
+    data_offset = 3632;
+    load_raw = &CLASS kodak_radc_load_raw;
+    filters = 0x61616161;
+    simple_coeff(2);
+  } else if (!strcmp(model,"QuickTake 100")) {
+    fseek (ifp, 544, SEEK_SET);
+    height = get2();
+    width  = get2();
+    data_offset = (get4(),get2()) == 30 ? 738:736;
+    if (height > width) {
+      SWAP(height,width);
+      fseek (ifp, data_offset-6, SEEK_SET);
+      flip = ~get2() & 3 ? 5:6;
+    }
+    load_raw = &CLASS quicktake_100_load_raw;
+    filters = 0x61616161;
+  } else if (!strcmp(model,"QuickTake 150")) {
+    data_offset = 738 - head[5];
+    if (head[5]) strcpy (model+10, "200");
+    load_raw = &CLASS kodak_radc_load_raw;
+    height = 480;
+    width  = 640;
+    filters = 0x61616161;
+  } else if (!strcmp(make,"Rollei") && !load_raw) {
+    switch (raw_width) {
+      case 1316:
+	height = 1030;
+	width  = 1300;
+	top_margin  = 1;
+	left_margin = 6;
+	break;
+      case 2568:
+	height = 1960;
+	width  = 2560;
+	top_margin  = 2;
+	left_margin = 8;
+    }
+    filters = 0x16161616;
+    load_raw = &CLASS rollei_load_raw;
+  } else if (!strcmp(model,"PC-CAM 600")) {
+    height = 768;
+    data_offset = width = 1024;
+    filters = 0x49494949;
+    load_raw = &CLASS eight_bit_load_raw;
+  }
+ else if (!strcmp(model,"QV-2000UX")) {
+    height = 1208;
+    width  = 1632;
+    data_offset = width * 2;
+    load_raw = &CLASS eight_bit_load_raw;
+  } else if (fsize == 3217760) {
+    height = 1546;
+    width  = 2070;
+    raw_width = 2080;
+    load_raw = &CLASS eight_bit_load_raw;
+  } else if (!strcmp(model,"QV-4000")) {
+    height = 1700;
+    width  = 2260;
+    load_raw = &CLASS unpacked_load_raw;
+    maximum = 0xffff;
+  } else if (!strcmp(model,"QV-5700")) {
+    height = 1924;
+    width  = 2576;
+    raw_width = 3232;
+    tiff_bps = 10;
+  } else if (!strcmp(model,"QV-R41")) {
+    height = 1720;
+    width  = 2312;
+    raw_width = 3520;
+    left_margin = 2;
+  } else if (!strcmp(model,"QV-R51")) {
+    height = 1926;
+    width  = 2580;
+    raw_width = 3904;
+  } else if (!strcmp(model,"EX-S20")) {
+    height = 1208;
+    width  = 1620;
+    raw_width = 2432;
+    flip = 3;
+  } else if (!strcmp(model,"EX-S100")) {
+    height = 1544;
+    width  = 2058;
+    raw_width = 3136;
+  } else if (!strcmp(model,"EX-Z50")) {
+    height = 1931;
+    width  = 2570;
+    raw_width = 3904;
+  } else if (!strcmp(model,"EX-Z55")) {
+    height = 1960;
+    width  = 2570;
+    raw_width = 3904;
+  } else if (!strcmp(model,"EX-Z60")) {
+    height = 2145;
+    width  = 2833;
+    raw_width = 3584;
+    filters = 0x16161616;
+    tiff_bps = 10;
+  } else if (!strcmp(model,"EX-Z75")) {
+    height = 2321;
+    width  = 3089;
+    raw_width = 4672;
+    maximum = 0xfff;
+  } else if (!strcmp(model,"EX-Z750")) {
+    height = 2319;
+    width  = 3087;
+    raw_width = 4672;
+    maximum = 0xfff;
+  } else if (!strcmp(model,"EX-Z850")) {
+    height = 2468;
+    width  = 3279;
+    raw_width = 4928;
+    maximum = 0xfff;
+  } else if (!strcmp(model,"EX-P505")) {
+    height = 1928;
+    width  = 2568;
+    raw_width = 3852;
+    maximum = 0xfff;
+  } else if (fsize == 9313536) {	/* EX-P600 or QV-R61 */
+    height = 2142;
+    width  = 2844;
+    raw_width = 4288;
+  } else if (!strcmp(model,"EX-P700")) {
+    height = 2318;
+    width  = 3082;
+    raw_width = 4672;
+  }
+#endif
+  if (!model[0])
+    sprintf (model, "%dx%d", width, height);
+  if (filters == UINT_MAX) filters = 0x94949494;
+  if (raw_color) adobe_coeff (make, model);
+  if (load_raw == &CLASS kodak_radc_load_raw)
+    if (raw_color) adobe_coeff ("Apple","Quicktake");
+  if (thumb_offset && !thumb_height) {
+    fseek (ifp, thumb_offset, SEEK_SET);
+    if (ljpeg_start (&jh, 1)) {
+      thumb_width  = jh.wide;
+      thumb_height = jh.high;
+    }
+  }
+dng_skip:
+  if (!tiff_bps) tiff_bps = 12;
+  if (!maximum) maximum = (1 << tiff_bps) - 1;
+  if (!load_raw || height < 22) is_raw = 0;
+#ifdef NO_JPEG
+  if (load_raw == &CLASS kodak_jpeg_load_raw) {
+#ifdef DCRAW_VERBOSE
+    fprintf (stderr,_("%s: You must link dcraw with libjpeg!!\n"), ifname);
+#endif
+    is_raw = 0;
+#ifdef LIBRAW_LIBRARY_BUILD
+    imgdata.process_warnings |= LIBRAW_WARN_NO_JPEGLIB;
+#endif
+  }
+#endif
+  if (!cdesc[0])
+    strcpy (cdesc, colors == 3 ? "RGB":"GMCY");
+  if (!raw_height) raw_height = height;
+  if (!raw_width ) raw_width  = width;
+  if (filters && colors == 3)
+    for (i=0; i < 32; i+=4) {
+      if ((filters >> i & 15) == 9)
+	filters |= 2 << i;
+      if ((filters >> i & 15) == 6)
+	filters |= 8 << i;
+    }
+notraw:
+  if (flip == -1) flip = tiff_flip;
+  if (flip == -1) flip = 0;
+#ifdef LIBRAW_LIBRARY_BUILD
+  RUN_CALLBACK(LIBRAW_PROGRESS_IDENTIFY,1,2);
+#endif
+}
+
+void CLASS identify2(unsigned fsize, char *head)
+{
+    if (!strcmp(model,"EASYSHARE Z1015 IS")) {
+    height = 2742;
+    width  = 3664;
+    goto ezshare;
+  } else if (!strcmp(model,"EasyShare Z980")) {
+    height = 3006;
+    width  = 4016;
+ezshare:
+    data_offset = 0x15000;
+    load_raw = &CLASS packed_load_raw;
+  } else if (!strcasecmp(make,"KODAK")) {
+    if (filters == UINT_MAX) filters = 0x61616161;
+    if (!strncmp(model,"NC2000",6)) {
+      width -= 4;
+      left_margin = 2;
+    } else if (!strcmp(model,"EOSDCS3B")) {
+      width -= 4;
+      left_margin = 2;
+    } else if (!strcmp(model,"EOSDCS1")) {
+      width -= 4;
+      left_margin = 2;
+    } else if (!strcmp(model,"DCS420")) {
+      width -= 4;
+      left_margin = 2;
+    } else if (!strncmp(model,"DCS460 ",7)) {
+      model[6] = 0;
+      width -= 4;
+      left_margin = 2;
+    } else if (!strcmp(model,"DCS460A")) {
+      width -= 4;
+      left_margin = 2;
+      colors = 1;
+      filters = 0;
+    } else if (!strcmp(model,"DCS660M")) {
+      black = 214;
+      colors = 1;
+      filters = 0;
+    } else if (!strcmp(model,"DCS760M")) {
+      colors = 1;
+      filters = 0;
+    }
+    if (!strcmp(model+4,"20X"))
+      strcpy (cdesc, "MYCY");
+    if (strstr(model,"DC25")) {
+      strcpy (model, "DC25");
+      data_offset = 15424;
+    }
+    if (!strncmp(model,"DC2",3)) {
+      height = 242;
+      if (fsize < 100000) {
+	raw_width = 256; width = 249;
+	pixel_aspect = (4.0*height) / (3.0*width);
+      } else {
+	raw_width = 512; width = 501;
+	pixel_aspect = (493.0*height) / (373.0*width);
+      }
+      data_offset += raw_width + 1;
+      colors = 4;
+      filters = 0x8d8d8d8d;
+      simple_coeff(1);
+      pre_mul[1] = 1.179;
+      pre_mul[2] = 1.209;
+      pre_mul[3] = 1.036;
+#ifdef LIBRAW_LIBRARY_BUILD
+      color_flags.pre_mul_state = LIBRAW_COLORSTATE_CONST;
+#endif
+      load_raw = &CLASS eight_bit_load_raw;
+    } else if (!strcmp(model,"40")) {
+      strcpy (model, "DC40");
+      height = 512;
+      width  = 768;
+      data_offset = 1152;
+      load_raw = &CLASS kodak_radc_load_raw;
+    } else if (strstr(model,"DC50")) {
+      strcpy (model, "DC50");
+      height = 512;
+      width  = 768;
+      data_offset = 19712;
+      load_raw = &CLASS kodak_radc_load_raw;
+    } else if (strstr(model,"DC120")) {
+      strcpy (model, "DC120");
+      height = 976;
+      width  = 848;
+      pixel_aspect = height/0.75/width;
+      load_raw = tiff_compress == 7 ?
+	&CLASS kodak_jpeg_load_raw : &CLASS kodak_dc120_load_raw;
+    } else if (!strcmp(model,"DCS200")) {
+      thumb_height = 128;
+      thumb_width  = 192;
+      thumb_offset = 6144;
+      thumb_misc   = 360;
+      write_thumb = &CLASS layer_thumb;
+      height = 1024;
+      width  = 1536;
+      data_offset = 79872;
+      load_raw = &CLASS eight_bit_load_raw;
+      black = 17;
+    }
+} else if (!strcmp(model,"Fotoman Pixtura")) {
+    height = 512;
+    width  = 768;
+    data_offset = 3632;
+    load_raw = &CLASS kodak_radc_load_raw;
+    filters = 0x61616161;
+    simple_coeff(2);
+  } else if (!strcmp(model,"QuickTake 100")) {
+    fseek (ifp, 544, SEEK_SET);
+    height = get2();
+    width  = get2();
+    data_offset = (get4(),get2()) == 30 ? 738:736;
+    if (height > width) {
+      SWAP(height,width);
+      fseek (ifp, data_offset-6, SEEK_SET);
+      flip = ~get2() & 3 ? 5:6;
+    }
+    load_raw = &CLASS quicktake_100_load_raw;
+    filters = 0x61616161;
+  } else if (!strcmp(model,"QuickTake 150")) {
+    data_offset = 738 - head[5];
+    if (head[5]) strcpy (model+10, "200");
+    load_raw = &CLASS kodak_radc_load_raw;
+    height = 480;
+    width  = 640;
+    filters = 0x61616161;
+  } else if (!strcmp(make,"Rollei") && !load_raw) {
+    switch (raw_width) {
+      case 1316:
+	height = 1030;
+	width  = 1300;
+	top_margin  = 1;
+	left_margin = 6;
+	break;
+      case 2568:
+	height = 1960;
+	width  = 2560;
+	top_margin  = 2;
+	left_margin = 8;
+    }
+    filters = 0x16161616;
+    load_raw = &CLASS rollei_load_raw;
+  } else if (!strcmp(model,"PC-CAM 600")) {
+    height = 768;
+    data_offset = width = 1024;
+    filters = 0x49494949;
+    load_raw = &CLASS eight_bit_load_raw;
+  }
+else if (!strcmp(model,"QV-2000UX")) {
+    height = 1208;
+    width  = 1632;
+    data_offset = width * 2;
+    load_raw = &CLASS eight_bit_load_raw;
+  } else if (fsize == 3217760) {
+    height = 1546;
+    width  = 2070;
+    raw_width = 2080;
+    load_raw = &CLASS eight_bit_load_raw;
+  } else if (!strcmp(model,"QV-4000")) {
+    height = 1700;
+    width  = 2260;
+    load_raw = &CLASS unpacked_load_raw;
+    maximum = 0xffff;
+  } else if (!strcmp(model,"QV-5700")) {
+    height = 1924;
+    width  = 2576;
+    raw_width = 3232;
+    tiff_bps = 10;
+  } else if (!strcmp(model,"QV-R41")) {
+    height = 1720;
+    width  = 2312;
+    raw_width = 3520;
+    left_margin = 2;
+  } else if (!strcmp(model,"QV-R51")) {
+    height = 1926;
+    width  = 2580;
+    raw_width = 3904;
+  } else if (!strcmp(model,"EX-S20")) {
+    height = 1208;
+    width  = 1620;
+    raw_width = 2432;
+    flip = 3;
+  } else if (!strcmp(model,"EX-S100")) {
+    height = 1544;
+    width  = 2058;
+    raw_width = 3136;
+  } else if (!strcmp(model,"EX-Z50")) {
+    height = 1931;
+    width  = 2570;
+    raw_width = 3904;
+  } else if (!strcmp(model,"EX-Z55")) {
+    height = 1960;
+    width  = 2570;
+    raw_width = 3904;
+  } else if (!strcmp(model,"EX-Z60")) {
+    height = 2145;
+    width  = 2833;
+    raw_width = 3584;
+    filters = 0x16161616;
+    tiff_bps = 10;
+  } else if (!strcmp(model,"EX-Z75")) {
+    height = 2321;
+    width  = 3089;
+    raw_width = 4672;
+  } else if (!strcmp(model,"EX-Z750")) {
+    height = 2319;
+    width  = 3087;
+    raw_width = 4672;
+    maximum = 0xfff;
+  } else if (!strcmp(model,"EX-Z850")) {
+    height = 2468;
+    width  = 3279;
+    raw_width = 4928;
+    maximum = 0xfff;
+  } else if (!strcmp(model,"EX-P505")) {
+    height = 1928;
+    width  = 2568;
+    raw_width = 3852;
+    maximum = 0xfff;
+  } else if (fsize == 9313536) {	/* EX-P600 or QV-R61 */
+    height = 2142;
+    width  = 2844;
+    raw_width = 4288;
+  } else if (!strcmp(model,"EX-P700")) {
+    height = 2318;
+    width  = 3082;
+    raw_width = 4672;
+  }
+}
+
+#line 9639 "dcraw/dcraw.c"
+void CLASS convert_to_rgb()
+{
+  int row, col, c, i, j, k;
+  ushort *img;
+  float out[3], out_cam[3][4];
+  double num, inverse[3][3];
+  static const double xyzd50_srgb[3][3] =
+  { { 0.436083, 0.385083, 0.143055 },
+    { 0.222507, 0.716888, 0.060608 },
+    { 0.013930, 0.097097, 0.714022 } };
+  static const double rgb_rgb[3][3] =
+  { { 1,0,0 }, { 0,1,0 }, { 0,0,1 } };
+  static const double adobe_rgb[3][3] =
+  { { 0.715146, 0.284856, 0.000000 },
+    { 0.000000, 1.000000, 0.000000 },
+    { 0.000000, 0.041166, 0.958839 } };
+  static const double wide_rgb[3][3] =
+  { { 0.593087, 0.404710, 0.002206 },
+    { 0.095413, 0.843149, 0.061439 },
+    { 0.011621, 0.069091, 0.919288 } };
+  static const double prophoto_rgb[3][3] =
+  { { 0.529317, 0.330092, 0.140588 },
+    { 0.098368, 0.873465, 0.028169 },
+    { 0.016879, 0.117663, 0.865457 } };
+  static const double (*out_rgb[])[3] =
+  { rgb_rgb, adobe_rgb, wide_rgb, prophoto_rgb, xyz_rgb };
+  static const char *name[] =
+  { "sRGB", "Adobe RGB (1998)", "WideGamut D65", "ProPhoto D65", "XYZ" };
+  static const unsigned phead[] =
+  { 1024, 0, 0x2100000, 0x6d6e7472, 0x52474220, 0x58595a20, 0, 0, 0,
+    0x61637370, 0, 0, 0x6e6f6e65, 0, 0, 0, 0, 0xf6d6, 0x10000, 0xd32d };
+  unsigned pbody[] =
+  { 10, 0x63707274, 0, 36,	/* cprt */
+	0x64657363, 0, 40,	/* desc */
+	0x77747074, 0, 20,	/* wtpt */
+	0x626b7074, 0, 20,	/* bkpt */
+	0x72545243, 0, 14,	/* rTRC */
+	0x67545243, 0, 14,	/* gTRC */
+	0x62545243, 0, 14,	/* bTRC */
+	0x7258595a, 0, 20,	/* rXYZ */
+	0x6758595a, 0, 20,	/* gXYZ */
+	0x6258595a, 0, 20 };	/* bXYZ */
+  static const unsigned pwhite[] = { 0xf351, 0x10000, 0x116cc };
+  unsigned pcurve[] = { 0x63757276, 0, 1, 0x1000000 };
+
+#ifdef LIBRAW_LIBRARY_BUILD
+  RUN_CALLBACK(LIBRAW_PROGRESS_CONVERT_RGB,0,2);
+#endif
+  gamma_curve (gamm[0], gamm[1], 0, 0);
+  memcpy (out_cam, rgb_cam, sizeof out_cam);
+  raw_color |= colors == 1 || document_mode ||
+		output_color < 1 || output_color > 5;
+  if (!raw_color) {
+    oprof = (unsigned *) calloc (phead[0], 1);
+    merror (oprof, "convert_to_rgb()");
+    memcpy (oprof, phead, sizeof phead);
+    if (output_color == 5) oprof[4] = oprof[5];
+    oprof[0] = 132 + 12*pbody[0];
+    for (i=0; i < pbody[0]; i++) {
+      oprof[oprof[0]/4] = i ? (i > 1 ? 0x58595a20 : 0x64657363) : 0x74657874;
+      pbody[i*3+2] = oprof[0];
+      oprof[0] += (pbody[i*3+3] + 3) & -4;
+    }
+    memcpy (oprof+32, pbody, sizeof pbody);
+    oprof[pbody[5]/4+2] = strlen(name[output_color-1]) + 1;
+    memcpy ((char *)oprof+pbody[8]+8, pwhite, sizeof pwhite);
+    pcurve[3] = (short)(256/gamm[5]+0.5) << 16;
+    for (i=4; i < 7; i++)
+      memcpy ((char *)oprof+pbody[i*3+2], pcurve, sizeof pcurve);
+    pseudoinverse ((double (*)[3]) out_rgb[output_color-1], inverse, 3);
+    for (i=0; i < 3; i++)
+      for (j=0; j < 3; j++) {
+	for (num = k=0; k < 3; k++)
+	  num += xyzd50_srgb[i][k] * inverse[j][k];
+        oprof[pbody[j*3+23]/4+i+2] = num * 0x10000 + 0.5;
+      }
+    for (i=0; i < phead[0]/4; i++)
+      oprof[i] = htonl(oprof[i]);
+    strcpy ((char *)oprof+pbody[2]+8, "auto-generated by dcraw");
+    strcpy ((char *)oprof+pbody[5]+12, name[output_color-1]);
+    for (i=0; i < 3; i++)
+      for (j=0; j < colors; j++)
+	for (out_cam[i][j] = k=0; k < 3; k++)
+	  out_cam[i][j] += out_rgb[output_color-1][i][k] * rgb_cam[k][j];
+  }
+#ifdef DCRAW_VERBOSE
+  if (verbose)
+    fprintf (stderr, raw_color ? _("Building histograms...\n") :
+	_("Converting to %s colorspace...\n"), name[output_color-1]);
+
+#endif
+#ifdef LIBRAW_LIBRARY_BUILD
+  memset(histogram,0,sizeof(int)*LIBRAW_HISTOGRAM_SIZE*4);
+#else
+  memset (histogram, 0, sizeof histogram);
+#endif
+  for (img=image[0], row=0; row < height; row++)
+    for (col=0; col < width; col++, img+=4) {
+      if (!raw_color) {
+	out[0] = out[1] = out[2] = 0;
+	FORCC {
+	  out[0] += out_cam[0][c] * img[c];
+	  out[1] += out_cam[1][c] * img[c];
+	  out[2] += out_cam[2][c] * img[c];
+	}
+	FORC3 img[c] = CLIP((int) out[c]);
+      }
+      else if (document_mode)
+	img[0] = img[FC(row,col)];
+      FORCC histogram[c][img[c] >> 3]++;
+    }
+  if (colors == 4 && output_color) colors = 3;
+  if (document_mode && filters) colors = 1;
+#ifdef LIBRAW_LIBRARY_BUILD
+  RUN_CALLBACK(LIBRAW_PROGRESS_CONVERT_RGB,1,2);
+#endif
+}
+
+void CLASS fuji_rotate()
+{
+  int i, row, col;
+  double step;
+  float r, c, fr, fc;
+  unsigned ur, uc;
+  ushort wide, high, (*img)[4], (*pix)[4];
+
+  if (!fuji_width) return;
+#ifdef DCRAW_VERBOSE
+  if (verbose)
+    fprintf (stderr,_("Rotating image 45 degrees...\n"));
+#endif
+  fuji_width = (fuji_width - 1 + shrink) >> shrink;
+  step = sqrt(0.5);
+  wide = fuji_width / step;
+  high = (height - fuji_width) / step;
+  img = (ushort (*)[4]) calloc (wide*high, sizeof *img);
+  merror (img, "fuji_rotate()");
+
+#ifdef LIBRAW_LIBRARY_BUILD
+  RUN_CALLBACK(LIBRAW_PROGRESS_FUJI_ROTATE,0,2);
+#endif
+
+  for (row=0; row < high; row++)
+    for (col=0; col < wide; col++) {
+      ur = r = fuji_width + (row-col)*step;
+      uc = c = (row+col)*step;
+      if (ur > height-2 || uc > width-2) continue;
+      fr = r - ur;
+      fc = c - uc;
+      pix = image + ur*width + uc;
+      for (i=0; i < colors; i++)
+	img[row*wide+col][i] =
+	  (pix[    0][i]*(1-fc) + pix[      1][i]*fc) * (1-fr) +
+	  (pix[width][i]*(1-fc) + pix[width+1][i]*fc) * fr;
+    }
+  free (image);
+  width  = wide;
+  height = high;
+  image  = img;
+  fuji_width = 0;
+#ifdef LIBRAW_LIBRARY_BUILD
+  RUN_CALLBACK(LIBRAW_PROGRESS_FUJI_ROTATE,1,2);
+#endif
+}
+
+void CLASS stretch()
+{
+  ushort newdim, (*img)[4], *pix0, *pix1;
+  int row, col, c;
+  double rc, frac;
+
+  if (pixel_aspect == 1) return;
+#ifdef LIBRAW_LIBRARY_BUILD
+  RUN_CALLBACK(LIBRAW_PROGRESS_STRETCH,0,2);
+#endif
+#ifdef DCRAW_VERBOSE
+  if (verbose) fprintf (stderr,_("Stretching the image...\n"));
+#endif
+  if (pixel_aspect < 1) {
+    newdim = height / pixel_aspect + 0.5;
+    img = (ushort (*)[4]) calloc (width*newdim, sizeof *img);
+    merror (img, "stretch()");
+    for (rc=row=0; row < newdim; row++, rc+=pixel_aspect) {
+      frac = rc - (c = rc);
+      pix0 = pix1 = image[c*width];
+      if (c+1 < height) pix1 += width*4;
+      for (col=0; col < width; col++, pix0+=4, pix1+=4)
+	FORCC img[row*width+col][c] = pix0[c]*(1-frac) + pix1[c]*frac + 0.5;
+    }
+    height = newdim;
+  } else {
+    newdim = width * pixel_aspect + 0.5;
+    img = (ushort (*)[4]) calloc (height*newdim, sizeof *img);
+    merror (img, "stretch()");
+    for (rc=col=0; col < newdim; col++, rc+=1/pixel_aspect) {
+      frac = rc - (c = rc);
+      pix0 = pix1 = image[c];
+      if (c+1 < width) pix1 += 4;
+      for (row=0; row < height; row++, pix0+=width*4, pix1+=width*4)
+	FORCC img[row*newdim+col][c] = pix0[c]*(1-frac) + pix1[c]*frac + 0.5;
+    }
+    width = newdim;
+  }
+  free (image);
+  image = img;
+#ifdef LIBRAW_LIBRARY_BUILD
+  RUN_CALLBACK(LIBRAW_PROGRESS_STRETCH,1,2);
+#endif
+}
+
+int CLASS flip_index (int row, int col)
+{
+  if (flip & 4) SWAP(row,col);
+  if (flip & 2) row = iheight - 1 - row;
+  if (flip & 1) col = iwidth  - 1 - col;
+  return row * iwidth + col;
+}
+
+#line 9882 "dcraw/dcraw.c"
+void CLASS tiff_set (ushort *ntag,
+	ushort tag, ushort type, int count, int val)
+{
+  struct tiff_tag *tt;
+  int c;
+
+  tt = (struct tiff_tag *)(ntag+1) + (*ntag)++;
+  tt->tag = tag;
+  tt->type = type;
+  tt->count = count;
+  if (type < 3 && count <= 4)
+    FORC(4) tt->val.c[c] = val >> (c << 3);
+  else if (type == 3 && count <= 2)
+    FORC(2) tt->val.s[c] = val >> (c << 4);
+  else tt->val.i = val;
+}
+
+#define TOFF(ptr) ((char *)(&(ptr)) - (char *)th)
+
+void CLASS tiff_head (struct tiff_hdr *th, int full)
+{
+  int c, psize=0;
+  struct tm *t;
+
+  memset (th, 0, sizeof *th);
+  th->t_order = htonl(0x4d4d4949) >> 16;
+  th->magic = 42;
+  th->ifd = 10;
+  if (full) {
+    tiff_set (&th->ntag, 254, 4, 1, 0);
+    tiff_set (&th->ntag, 256, 4, 1, width);
+    tiff_set (&th->ntag, 257, 4, 1, height);
+    tiff_set (&th->ntag, 258, 3, colors, output_bps);
+    if (colors > 2)
+      th->tag[th->ntag-1].val.i = TOFF(th->bps);
+    FORC4 th->bps[c] = output_bps;
+    tiff_set (&th->ntag, 259, 3, 1, 1);
+    tiff_set (&th->ntag, 262, 3, 1, 1 + (colors > 1));
+  }
+  tiff_set (&th->ntag, 270, 2, 512, TOFF(th->t_desc));
+  tiff_set (&th->ntag, 271, 2, 64, TOFF(th->t_make));
+  tiff_set (&th->ntag, 272, 2, 64, TOFF(th->t_model));
+  if (full) {
+    if (oprof) psize = ntohl(oprof[0]);
+    tiff_set (&th->ntag, 273, 4, 1, sizeof *th + psize);
+    tiff_set (&th->ntag, 277, 3, 1, colors);
+    tiff_set (&th->ntag, 278, 4, 1, height);
+    tiff_set (&th->ntag, 279, 4, 1, height*width*colors*output_bps/8);
+  } else
+    tiff_set (&th->ntag, 274, 3, 1, "12435867"[flip]-'0');
+  tiff_set (&th->ntag, 282, 5, 1, TOFF(th->rat[0]));
+  tiff_set (&th->ntag, 283, 5, 1, TOFF(th->rat[2]));
+  tiff_set (&th->ntag, 284, 3, 1, 1);
+  tiff_set (&th->ntag, 296, 3, 1, 2);
+  tiff_set (&th->ntag, 305, 2, 32, TOFF(th->soft));
+  tiff_set (&th->ntag, 306, 2, 20, TOFF(th->date));
+  tiff_set (&th->ntag, 315, 2, 64, TOFF(th->t_artist));
+  tiff_set (&th->ntag, 34665, 4, 1, TOFF(th->nexif));
+  if (psize) tiff_set (&th->ntag, 34675, 7, psize, sizeof *th);
+  tiff_set (&th->nexif, 33434, 5, 1, TOFF(th->rat[4]));
+  tiff_set (&th->nexif, 33437, 5, 1, TOFF(th->rat[6]));
+  tiff_set (&th->nexif, 34855, 3, 1, iso_speed);
+  tiff_set (&th->nexif, 37386, 5, 1, TOFF(th->rat[8]));
+  if (gpsdata[1]) {
+    tiff_set (&th->ntag, 34853, 4, 1, TOFF(th->ngps));
+    tiff_set (&th->ngps,  0, 1,  4, 0x202);
+    tiff_set (&th->ngps,  1, 2,  2, gpsdata[29]);
+    tiff_set (&th->ngps,  2, 5,  3, TOFF(th->gps[0]));
+    tiff_set (&th->ngps,  3, 2,  2, gpsdata[30]);
+    tiff_set (&th->ngps,  4, 5,  3, TOFF(th->gps[6]));
+    tiff_set (&th->ngps,  5, 1,  1, gpsdata[31]);
+    tiff_set (&th->ngps,  6, 5,  1, TOFF(th->gps[18]));
+    tiff_set (&th->ngps,  7, 5,  3, TOFF(th->gps[12]));
+    tiff_set (&th->ngps, 18, 2, 12, TOFF(th->gps[20]));
+    tiff_set (&th->ngps, 29, 2, 12, TOFF(th->gps[23]));
+    memcpy (th->gps, gpsdata, sizeof th->gps);
+  }
+  th->rat[0] = th->rat[2] = 300;
+  th->rat[1] = th->rat[3] = 1;
+  FORC(6) th->rat[4+c] = 1000000;
+  th->rat[4] *= shutter;
+  th->rat[6] *= aperture;
+  th->rat[8] *= focal_len;
+  strncpy (th->t_desc, desc, 512);
+  strncpy (th->t_make, make, 64);
+  strncpy (th->t_model, model, 64);
+  strcpy (th->soft, "dcraw v"VERSION);
+  t = gmtime (&timestamp);
+  sprintf (th->date, "%04d:%02d:%02d %02d:%02d:%02d",
+      t->tm_year+1900,t->tm_mon+1,t->tm_mday,t->tm_hour,t->tm_min,t->tm_sec);
+  strncpy (th->t_artist, artist, 64);
+}
+
+void CLASS jpeg_thumb_writer (FILE *tfp,char *t_humb,int t_humb_length)
+{
+  ushort exif[5];
+  struct tiff_hdr th;
+  fputc (0xff, tfp);
+  fputc (0xd8, tfp);
+  if (strcmp (t_humb+6, "Exif")) {
+    memcpy (exif, "\xff\xe1  Exif\0\0", 10);
+    exif[1] = htons (8 + sizeof th);
+    fwrite (exif, 1, sizeof exif, tfp);
+    tiff_head (&th, 0);
+    fwrite (&th, 1, sizeof th, tfp);
+  }
+  fwrite (t_humb+2, 1, t_humb_length-2, tfp);
+}
+
+
+void CLASS jpeg_thumb()
+{
+  char *thumb;
+  ushort exif[5];
+  struct tiff_hdr th;
+
+  thumb = (char *) malloc (thumb_length);
+  merror (thumb, "jpeg_thumb()");
+  fread (thumb, 1, thumb_length, ifp);
+#if 0
+  fputc (0xff, ofp);
+  fputc (0xd8, ofp);
+  if (strcmp (thumb+6, "Exif")) {
+    memcpy (exif, "\xff\xe1  Exif\0\0", 10);
+    exif[1] = htons (8 + sizeof th);
+    fwrite (exif, 1, sizeof exif, ofp);
+    tiff_head (&th, 0);
+    fwrite (&th, 1, sizeof th, ofp);
+  }
+  fwrite (thumb+2, 1, thumb_length-2, ofp);
+#else
+  jpeg_thumb_writer(ofp,thumb,thumb_length);
+#endif
+  free (thumb);
+}
+
+void CLASS write_ppm_tiff()
+{
+  struct tiff_hdr th;
+  uchar *ppm;
+  ushort *ppm2;
+  int c, row, col, soff, rstep, cstep;
+  int perc, val, total, t_white=0x2000;
+
+  perc = width * height * 0.01;		/* 99th percentile white level */
+  if (fuji_width) perc /= 2;
+  if (!((highlight & ~2) || no_auto_bright))
+    for (t_white=c=0; c < colors; c++) {
+      for (val=0x2000, total=0; --val > 32; )
+	if ((total += histogram[c][val]) > perc) break;
+      if (t_white < val) t_white = val;
+    }
+  gamma_curve (gamm[0], gamm[1], 2, (t_white << 3)/bright);
+  iheight = height;
+  iwidth  = width;
+  if (flip & 4) SWAP(height,width);
+  ppm = (uchar *) calloc (width, colors*output_bps/8);
+  ppm2 = (ushort *) ppm;
+  merror (ppm, "write_ppm_tiff()");
+  if (output_tiff) {
+    tiff_head (&th, 1);
+    fwrite (&th, sizeof th, 1, ofp);
+    if (oprof)
+      fwrite (oprof, ntohl(oprof[0]), 1, ofp);
+  } else if (colors > 3)
+    fprintf (ofp,
+      "P7\nWIDTH %d\nHEIGHT %d\nDEPTH %d\nMAXVAL %d\nTUPLTYPE %s\nENDHDR\n",
+	width, height, colors, (1 << output_bps)-1, cdesc);
+  else
+    fprintf (ofp, "P%d\n%d %d\n%d\n",
+	colors/2+5, width, height, (1 << output_bps)-1);
+
+  soff  = flip_index (0, 0);
+  cstep = flip_index (0, 1) - soff;
+  rstep = flip_index (1, 0) - flip_index (0, width);
+  for (row=0; row < height; row++, soff += rstep) {
+    for (col=0; col < width; col++, soff += cstep)
+      if (output_bps == 8)
+	   FORCC ppm [col*colors+c] = curve[image[soff][c]] >> 8;
+      else FORCC ppm2[col*colors+c] = curve[image[soff][c]];
+    if (output_bps == 16 && !output_tiff && htons(0x55aa) != 0x55aa)
+        swab ((char*)ppm2, (char*)ppm2, width*colors*2);
+    fwrite (ppm, colors*output_bps/8, width, ofp);
+  }
+  free (ppm);
+}
diff --git a/ossim_plugins/libraw/LibRaw-0.9.0/internal/dcraw_fileio.cpp b/ossim_plugins/libraw/LibRaw-0.9.0/internal/dcraw_fileio.cpp
new file mode 100644
index 0000000..dd96e24
--- /dev/null
+++ b/ossim_plugins/libraw/LibRaw-0.9.0/internal/dcraw_fileio.cpp
@@ -0,0 +1,215 @@
+/* 
+   GENERATED FILE, DO NOT EDIT
+   Generated from dcraw/dcraw.c at Wed Apr 21 09:55:26 2010
+   Look into original file (probably http://cybercom.net/~dcoffin/dcraw/dcraw.c)
+   for copyright information.
+*/
+
+#line 3976 "dcraw/dcraw.c"
+#define CLASS LibRaw::
+#include "libraw/libraw_types.h"
+#define LIBRAW_LIBRARY_BUILD
+#include "libraw/libraw.h"
+#include "internal/defines.h"
+#include "internal/var_defines.h"
+#line 3986 "dcraw/dcraw.c"
+
+/*
+   Seach from the current directory up to the root looking for
+   a ".badpixels" file, and fix those pixels now.
+ */
+void CLASS bad_pixels (const char *cfname)
+{
+  FILE *fp=0;
+  char *fname, *cp, line[128];
+  int len, time, row, col, r, c, rad, tot, n, fixed=0;
+
+  if (!filters) return;
+#ifdef LIBRAW_LIBRARY_BUILD
+  RUN_CALLBACK(LIBRAW_PROGRESS_BAD_PIXELS,0,2);
+#endif
+  if (cfname)
+    fp = fopen (cfname, "r");
+#line 4029 "dcraw/dcraw.c"
+  if (!fp) 
+      {
+#ifdef LIBRAW_LIBRARY_BUILD
+          imgdata.process_warnings |= LIBRAW_WARN_NO_BADPIXELMAP;
+#endif
+          return;
+      }
+  while (fgets (line, 128, fp)) {
+    cp = strchr (line, '#');
+    if (cp) *cp = 0;
+    if (sscanf (line, "%d %d %d", &col, &row, &time) != 3) continue;
+    if ((unsigned) col >= width || (unsigned) row >= height) continue;
+    if (time > timestamp) continue;
+    for (tot=n=0, rad=1; rad < 3 && n==0; rad++)
+      for (r = row-rad; r <= row+rad; r++)
+	for (c = col-rad; c <= col+rad; c++)
+	  if ((unsigned) r < height && (unsigned) c < width &&
+		(r != row || c != col) && fc(r,c) == fc(row,col)) {
+	    tot += BAYER2(r,c);
+	    n++;
+	  }
+    BAYER2(row,col) = tot/n;
+#ifdef DCRAW_VERBOSE
+    if (verbose) {
+      if (!fixed++)
+	fprintf (stderr,_("Fixed dead pixels at:"));
+      fprintf (stderr, " %d,%d", col, row);
+    }
+#endif
+  }
+#ifdef DCRAW_VERBOSE
+  if (fixed) fputc ('\n', stderr);
+#endif
+  fclose (fp);
+#ifdef LIBRAW_LIBRARY_BUILD
+  RUN_CALLBACK(LIBRAW_PROGRESS_BAD_PIXELS,1,2);
+#endif
+}
+
+void CLASS subtract (const char *fname)
+{
+  FILE *fp;
+  int dim[3]={0,0,0}, comment=0, number=0, error=0, nd=0, c, row, col;
+  ushort *pixel;
+#ifdef LIBRAW_LIBRARY_BUILD
+  RUN_CALLBACK(LIBRAW_PROGRESS_DARK_FRAME,0,2);
+#endif
+
+  if (!(fp = fopen (fname, "rb"))) {
+#ifdef DCRAW_VERBOSE
+    perror (fname); 
+#endif
+#ifdef LIBRAW_LIBRARY_BUILD
+    imgdata.process_warnings |= LIBRAW_WARN_BAD_DARKFRAME_FILE;
+#endif
+    return;
+  }
+  if (fgetc(fp) != 'P' || fgetc(fp) != '5') error = 1;
+  while (!error && nd < 3 && (c = fgetc(fp)) != EOF) {
+    if (c == '#')  comment = 1;
+    if (c == '\n') comment = 0;
+    if (comment) continue;
+    if (isdigit(c)) number = 1;
+    if (number) {
+      if (isdigit(c)) dim[nd] = dim[nd]*10 + c -'0';
+      else if (isspace(c)) {
+	number = 0;  nd++;
+      } else error = 1;
+    }
+  }
+  if (error || nd < 3) {
+    fprintf (stderr,_("%s is not a valid PGM file!\n"), fname);
+    fclose (fp);  return;
+  } else if (dim[0] != width || dim[1] != height || dim[2] != 65535) {
+#ifdef DCRAW_VERBOSE
+      fprintf (stderr,_("%s has the wrong dimensions!\n"), fname);
+#endif
+#ifdef LIBRAW_LIBRARY_BUILD
+      imgdata.process_warnings |= LIBRAW_WARN_BAD_DARKFRAME_DIM;
+#endif
+    fclose (fp);  return;
+  }
+  pixel = (ushort *) calloc (width, sizeof *pixel);
+  merror (pixel, "subtract()");
+  for (row=0; row < height; row++) {
+    fread (pixel, 2, width, fp);
+    for (col=0; col < width; col++)
+      BAYER(row,col) = MAX (BAYER(row,col) - ntohs(pixel[col]), 0);
+  }
+  free (pixel);
+  black = 0;
+#ifdef LIBRAW_LIBRARY_BUILD
+  RUN_CALLBACK(LIBRAW_PROGRESS_DARK_FRAME,1,2);
+#endif
+}
+#line 9550 "dcraw/dcraw.c"
+
+#ifndef NO_LCMS
+void CLASS apply_profile (const char *input, const char *output)
+{
+  char *prof;
+  cmsHPROFILE hInProfile=0, hOutProfile=0;
+  cmsHTRANSFORM hTransform;
+  FILE *fp;
+  unsigned size;
+
+  cmsErrorAction (LCMS_ERROR_SHOW);
+  if (strcmp (input, "embed"))
+    hInProfile = cmsOpenProfileFromFile (input, "r");
+  else if (profile_length) {
+#ifndef LIBRAW_LIBRARY_BUILD
+    prof = (char *) malloc (profile_length);
+    merror (prof, "apply_profile()");
+    fseek (ifp, profile_offset, SEEK_SET);
+    fread (prof, 1, profile_length, ifp);
+    hInProfile = cmsOpenProfileFromMem (prof, profile_length);
+    free (prof);
+#else
+    hInProfile = cmsOpenProfileFromMem (imgdata.color.profile, profile_length);
+#endif
+  } else
+      {
+#ifdef LIBRAW_LIBRARY_BUILD
+          imgdata.process_warnings |= LIBRAW_WARN_NO_EMBEDDED_PROFILE;
+#endif
+#ifdef DCRAW_VERBOSE
+          fprintf (stderr,_("%s has no embedded profile.\n"), ifname);
+#endif
+      }
+  if (!hInProfile)
+      {
+#ifdef LIBRAW_LIBRARY_BUILD
+          imgdata.process_warnings |= LIBRAW_WARN_NO_INPUT_PROFILE;
+#endif
+          return;
+      }
+  if (!output)
+    hOutProfile = cmsCreate_sRGBProfile();
+  else if ((fp = fopen (output, "rb"))) {
+    fread (&size, 4, 1, fp);
+    fseek (fp, 0, SEEK_SET);
+    oprof = (unsigned *) malloc (size = ntohl(size));
+    merror (oprof, "apply_profile()");
+    fread (oprof, 1, size, fp);
+    fclose (fp);
+    if (!(hOutProfile = cmsOpenProfileFromMem (oprof, size))) {
+      free (oprof);
+      oprof = 0;
+    }
+#ifdef DCRAW_VERBOSE
+  } else
+    fprintf (stderr,_("Cannot open file %s!\n"), output);
+#else
+}
+#endif
+  if (!hOutProfile)
+      {
+#ifdef LIBRAW_LIBRARY_BUILD
+          imgdata.process_warnings |= LIBRAW_WARN_BAD_OUTPUT_PROFILE;
+#endif
+          goto quit;
+      }
+#ifdef DCRAW_VERBOSE
+  if (verbose)
+    fprintf (stderr,_("Applying color profile...\n"));
+#endif
+#ifdef LIBRAW_LIBRARY_BUILD
+  RUN_CALLBACK(LIBRAW_PROGRESS_APPLY_PROFILE,0,2);
+#endif
+  hTransform = cmsCreateTransform (hInProfile, TYPE_RGBA_16,
+	hOutProfile, TYPE_RGBA_16, INTENT_PERCEPTUAL, 0);
+  cmsDoTransform (hTransform, image, image, width*height);
+  raw_color = 1;		/* Don't use rgb_cam with a profile */
+  cmsDeleteTransform (hTransform);
+  cmsCloseProfile (hOutProfile);
+quit:
+  cmsCloseProfile (hInProfile);
+#ifdef LIBRAW_LIBRARY_BUILD
+  RUN_CALLBACK(LIBRAW_PROGRESS_APPLY_PROFILE,1,2);
+#endif
+}
+#endif
diff --git a/ossim_plugins/libraw/LibRaw-0.9.0/internal/defines.h b/ossim_plugins/libraw/LibRaw-0.9.0/internal/defines.h
new file mode 100644
index 0000000..01e4434
--- /dev/null
+++ b/ossim_plugins/libraw/LibRaw-0.9.0/internal/defines.h
@@ -0,0 +1,133 @@
+/* 
+   GENERATED FILE, DO NOT EDIT
+   Generated from dcraw/dcraw.c at Wed Apr 21 09:55:20 2010
+   Look into original file (probably http://cybercom.net/~dcoffin/dcraw/dcraw.c)
+   for copyright information.
+*/
+
+#line 27 "dcraw/dcraw.c"
+#define NO_JPEG
+#line 32 "dcraw/dcraw.c"
+#define VERSION "8.99"
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+#define _USE_MATH_DEFINES
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <float.h>
+#include <limits.h>
+#include <math.h>
+#include <setjmp.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <sys/types.h>
+#ifdef _OPENMP
+#include <omp.h>
+#endif
+/*
+   NO_JPEG disables decoding of compressed Kodak DC120 files.
+   NO_LCMS disables the "-p" option.
+ */
+#ifndef NO_JPEG
+#include <jpeglib.h>
+#endif
+#ifndef NO_LCMS
+#include <lcms.h>
+#endif
+#ifdef LOCALEDIR
+#include <libintl.h>
+#define _(String) gettext(String)
+#else
+#define _(String) (String)
+#endif
+#line 77 "dcraw/dcraw.c"
+#ifdef __CYGWIN__
+#include <io.h>
+#endif
+#ifdef WIN32
+#include <sys/utime.h>
+#include <winsock2.h>
+#pragma comment(lib, "ws2_32.lib")
+#define snprintf _snprintf
+#define strcasecmp _stricmp
+#define strncasecmp strnicmp
+#line 91 "dcraw/dcraw.c"
+#else
+#include <unistd.h>
+#include <utime.h>
+#include <netinet/in.h>
+#line 99 "dcraw/dcraw.c"
+#endif
+
+#ifdef LJPEG_DECODE
+#error Please compile dcraw.c by itself.
+#error Do not link it with ljpeg_decode.
+#endif
+
+#ifndef LONG_BIT
+#define LONG_BIT (8 * sizeof (long))
+#endif
+#line 175 "dcraw/dcraw.c"
+#define FORC(cnt) for (c=0; c < cnt; c++)
+#define FORC3 FORC(3)
+#define FORC4 FORC(4)
+#define FORCC FORC(colors)
+
+#define SQR(x) ((x)*(x))
+#define ABS(x) (((int)(x) ^ ((int)(x) >> 31)) - ((int)(x) >> 31))
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+#define MAX(a,b) ((a) > (b) ? (a) : (b))
+#define LIM(x,min,max) MAX(min,MIN(x,max))
+#define ULIM(x,y,z) ((y) < (z) ? LIM(x,y,z) : LIM(x,z,y))
+#define CLIP(x) LIM(x,0,65535)
+#define SWAP(a,b) { a ^= b; a ^= (b ^= a); }
+
+/*
+   In order to inline this calculation, I make the risky
+   assumption that all filter patterns can be described
+   by a repeating pattern of eight rows and two columns
+
+   Do not use the FC or BAYER macros with the Leaf CatchLight,
+   because its pattern is 16x16, not 2x8.
+
+   Return values are either 0/1/2/3 = G/M/C/Y or 0/1/2/3 = R/G1/B/G2
+
+	PowerShot 600	PowerShot A50	PowerShot Pro70	Pro90 & G1
+	0xe1e4e1e4:	0x1b4e4b1e:	0x1e4b4e1b:	0xb4b4b4b4:
+
+	  0 1 2 3 4 5	  0 1 2 3 4 5	  0 1 2 3 4 5	  0 1 2 3 4 5
+	0 G M G M G M	0 C Y C Y C Y	0 Y C Y C Y C	0 G M G M G M
+	1 C Y C Y C Y	1 M G M G M G	1 M G M G M G	1 Y C Y C Y C
+	2 M G M G M G	2 Y C Y C Y C	2 C Y C Y C Y
+	3 C Y C Y C Y	3 G M G M G M	3 G M G M G M
+			4 C Y C Y C Y	4 Y C Y C Y C
+	PowerShot A5	5 G M G M G M	5 G M G M G M
+	0x1e4e1e4e:	6 Y C Y C Y C	6 C Y C Y C Y
+			7 M G M G M G	7 M G M G M G
+	  0 1 2 3 4 5
+	0 C Y C Y C Y
+	1 G M G M G M
+	2 C Y C Y C Y
+	3 M G M G M G
+
+   All RGB cameras use one of these Bayer grids:
+
+	0x16161616:	0x61616161:	0x49494949:	0x94949494:
+
+	  0 1 2 3 4 5	  0 1 2 3 4 5	  0 1 2 3 4 5	  0 1 2 3 4 5
+	0 B G B G B G	0 G R G R G R	0 G B G B G B	0 R G R G R G
+	1 G R G R G R	1 B G B G B G	1 R G R G R G	1 G B G B G B
+	2 B G B G B G	2 G R G R G R	2 G B G B G B	2 R G R G R G
+	3 G R G R G R	3 B G B G B G	3 R G R G R G	3 G B G B G B
+ */
+
+#line 233 "dcraw/dcraw.c"
+#define BAYER(row,col) \
+	image[((row) >> shrink)*iwidth + ((col) >> shrink)][FC(row,col)]
+#define BAYER2(row,col) \
+	image[((row) >> shrink)*iwidth + ((col) >> shrink)][fc(row,col)]
diff --git a/ossim_plugins/libraw/LibRaw-0.9.0/internal/libraw_internal_funcs.h b/ossim_plugins/libraw/LibRaw-0.9.0/internal/libraw_internal_funcs.h
new file mode 100644
index 0000000..49e772f
--- /dev/null
+++ b/ossim_plugins/libraw/LibRaw-0.9.0/internal/libraw_internal_funcs.h
@@ -0,0 +1,183 @@
+/* -*- C++ -*-
+ * File: libraw_internal_funcs.h
+ * Copyright 2008-2009 LibRaw LLC (info at libraw.org)
+ * Created: Sat Mar  14, 2008
+ *
+ * LibRaw internal data structures (not visible outside)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifndef _LIBRAW_INTERNAL_FUNCS_H
+#define _LIBRAW_INTERNAL_FUNCS_H
+
+#ifndef LIBRAW_LIBRARY_BUILD
+#error "This file should be used only for libraw library build"
+#else
+// inline functions
+    ushort      sget2 (uchar *s);
+    ushort      get2();
+    unsigned    sget4 (uchar *s);
+    unsigned    getint (int type);
+    float       int_to_float (int i);
+    double      getreal (int type);
+    void        read_shorts (ushort *pixel, int count);
+
+// Canon P&S cameras
+    void        canon_600_fixed_wb (int temp);
+    int         canon_600_color (int ratio[2], int mar);
+    void        canon_600_auto_wb();
+    void        canon_600_coeff();
+    void        canon_600_load_raw();
+    int         canon_s2is();
+    void        parse_ciff (int offset, int length);
+    void        ciff_block_1030();
+
+// LJPEG decoder
+    unsigned    getbithuff (int nbits, ushort *huff);
+    ushort*     make_decoder_ref (const uchar **source);
+    ushort*     make_decoder (const uchar *source);
+    int         ljpeg_start (struct jhead *jh, int info_only);
+    void        ljpeg_end(struct jhead *jh);
+    int         ljpeg_diff (ushort *huff);
+    ushort *    ljpeg_row (int jrow, struct jhead *jh);
+    unsigned    ph1_bithuff (int nbits, ushort *huff);
+
+// Canon DSLRs
+void        crw_init_tables (unsigned table, ushort *huff[2]);
+    int         canon_has_lowbits();
+    void        canon_compressed_load_raw();
+    void        lossless_jpeg_load_raw();
+    void        canon_sraw_load_raw();
+void        canon_black(double *, int nblack);
+// Adobe DNG
+    void        adobe_copy_pixel (int row, int col, ushort **rp);
+    void        adobe_dng_load_raw_lj();
+    void        adobe_dng_load_raw_nc();
+
+// Pentax
+    void        pentax_load_raw();
+    void        pentax_tree();
+
+// Nikon (and Minolta Z2)
+    void        nikon_compressed_load_raw();
+    void        nikon_load_raw();
+    int         nikon_is_compressed();
+    int         nikon_e995();
+    int         nikon_e2100();
+    void        nikon_3700();
+    int         minolta_z2();
+    void        nikon_e2100_load_raw();
+
+// Fuji
+    void        fuji_load_raw();
+    void        parse_fuji (int offset);
+
+
+
+
+// Rollei
+    void        rollei_load_raw();
+    void        parse_rollei();
+
+// MF backs
+    int         bayer (unsigned row, unsigned col);
+    void        phase_one_flat_field (int is_float, int nc);
+    void        phase_one_correct();
+    void        phase_one_load_raw();
+    unsigned    ph1_bits (int nbits);
+    void        phase_one_load_raw_c();
+    void        hasselblad_load_raw();
+    void        leaf_hdr_load_raw();
+    void        sinar_4shot_load_raw();
+    void        imacon_full_load_raw();
+    void        packed_load_raw();
+    float	find_green(int,int,int,int);
+    void        unpacked_load_raw();
+    void        parse_sinar_ia();
+    void        parse_phase_one (int base);
+
+// Misc P&S cameras
+    void        nokia_load_raw();
+    unsigned    pana_bits (int nbits);
+    void        panasonic_load_raw();
+    void        olympus_load_raw();
+    void        olympus_cseries_load_raw();
+    void        minolta_rd175_load_raw();
+    void        quicktake_100_load_raw();
+    const int*  make_decoder_int (const int *source, int level);
+    int         radc_token (int tree);
+    void        kodak_radc_load_raw();
+    void        kodak_jpeg_load_raw();
+    void        kodak_dc120_load_raw();
+    void        eight_bit_load_raw();
+    void        smal_decode_segment (unsigned seg[2][2], int holes);
+    void        smal_v6_load_raw();
+    int         median4 (int *p);
+    void        fill_holes (int holes);
+    void        smal_v9_load_raw();
+    void        parse_riff();
+    void        parse_cine();
+    void        parse_smal (int offset, int fsize);
+    int         parse_jpeg (int offset);
+
+// Kodak
+    void        kodak_262_load_raw();
+    int         kodak_65000_decode (short *out, int bsize);
+    void        kodak_65000_load_raw();
+    void        kodak_rgb_load_raw();
+    void        kodak_yrgb_load_raw();
+
+// It's a Sony (and K&M)
+    void        sony_decrypt (unsigned *data, int len, int start, int key);
+    void        sony_load_raw();
+    void        sony_arw_load_raw();
+    void        sony_arw2_load_raw();
+    void        parse_minolta (int base);
+
+// CAM/RGB
+    void        pseudoinverse (double (*in)[3], double (*out)[3], int size);
+    void        cam_xyz_coeff (double cam_xyz[4][3]);
+    void        adobe_coeff (const char *, const char *);
+    void        simple_coeff (int index);
+
+
+// Tiff/Exif parsers
+    void        tiff_get (unsigned base,unsigned *tag, unsigned *type, unsigned *len, unsigned *save);
+    void        parse_thumb_note (int base, unsigned toff, unsigned tlen);
+    void        parse_makernote (int base, int uptag);
+    void        parse_exif (int base);
+    void        linear_table (unsigned len);
+    void        parse_kodak_ifd (int base);
+    int         parse_tiff_ifd (int base);
+    void        parse_tiff (int base);
+    void        parse_gps (int base);
+    void        romm_coeff (float romm_cam[3][3]);
+    void        parse_mos (int offset);
+    void        get_timestamp (int reversed);
+
+// External JPEGs, what cameras uses it ?
+    void        parse_external_jpeg();
+
+// The identify
+    short       guess_byte_order (int words);
+
+// Tiff writer
+    void        tiff_set (ushort *ntag, ushort tag, ushort type, int count, int val);
+    void        tiff_head (struct tiff_hdr *th, int full);
+#endif
+
+#endif
diff --git a/ossim_plugins/libraw/LibRaw-0.9.0/internal/var_defines.h b/ossim_plugins/libraw/LibRaw-0.9.0/internal/var_defines.h
new file mode 100644
index 0000000..d26d0e8
--- /dev/null
+++ b/ossim_plugins/libraw/LibRaw-0.9.0/internal/var_defines.h
@@ -0,0 +1,185 @@
+/* -*- C++ -*-
+ * File: var_defines.h
+ * Copyright 2008-2009 LibRaw LLC (info at libraw.org)
+ * Created: Sat Mar  8, 2008
+ *
+ * LibRaw redefinitions of dcraw internal variables
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifndef VAR_DEFINES_H
+#define VAR_DEFINES_H
+
+// imgdata.idata
+#define make            (imgdata.idata.make)
+#define model           (imgdata.idata.model)
+#define is_raw          (imgdata.idata.raw_count)
+#define dng_version     (imgdata.idata.dng_version)
+#define colors          (imgdata.idata.colors)
+#define cdesc           (imgdata.idata.cdesc)
+#define filters         (imgdata.idata.filters)
+
+//imgdata image
+#define image           (imgdata.image)
+
+// imgdata.sizes
+#define raw_height      (imgdata.sizes.raw_height)
+#define raw_width       (imgdata.sizes.raw_width)
+#define height          (imgdata.sizes.height)
+#define width           (imgdata.sizes.width)
+#define top_margin      (imgdata.sizes.top_margin)
+#define left_margin     (imgdata.sizes.left_margin)
+#define bottom_margin   (imgdata.sizes.bottom_margin)
+#define right_margin    (imgdata.sizes.right_margin)
+#define iheight         (imgdata.sizes.iheight)
+#define iwidth          (imgdata.sizes.iwidth)
+#define pixel_aspect    (imgdata.sizes.pixel_aspect)
+#define flip            (imgdata.sizes.flip)
+
+//imgdata.color
+#define white           (imgdata.color.white)
+#define cam_mul         (imgdata.color.cam_mul)
+#define pre_mul         (imgdata.color.pre_mul)
+#define cmatrix         (imgdata.color.cmatrix)
+#define rgb_cam         (imgdata.color.rgb_cam)
+#ifndef SRC_USES_CURVE
+#define curve           (imgdata.color.curve)
+#endif
+#ifndef SRC_USES_BLACK
+#define black           (imgdata.color.black)
+#endif
+#define maximum         (imgdata.color.maximum)
+#define channel_maximum         (imgdata.color.channel_maximum)
+#define profile_length  (imgdata.color.profile_length)
+#define color_flags     (imgdata.color.color_flags)
+#define ph1             (imgdata.color.phase_one_data)
+#define flash_used      (imgdata.color.flash_used)
+#define canon_ev        (imgdata.color.canon_ev)
+#define model2          (imgdata.color.model2)
+
+//imgdata.thumbnail
+
+#define thumb_width     (imgdata.thumbnail.twidth)
+#define thumb_height    (imgdata.thumbnail.theight)
+#define thumb_length    (imgdata.thumbnail.tlength)
+
+
+//imgdata.others
+#define iso_speed       (imgdata.other.iso_speed)
+#define shutter         (imgdata.other.shutter)
+#define aperture        (imgdata.other.aperture)
+#define focal_len       (imgdata.other.focal_len)
+#define timestamp       (imgdata.other.timestamp)
+#define shot_order      (imgdata.other.shot_order)
+#define gpsdata         (imgdata.other.gpsdata)
+#define desc            (imgdata.other.desc)
+#define artist          (imgdata.other.artist)
+
+//imgdata.output
+#define greybox         (imgdata.params.greybox)
+#define aber            (imgdata.params.aber)
+#define gamm            (imgdata.params.gamm)
+#define user_mul        (imgdata.params.user_mul)
+#define shot_select     (imgdata.params.shot_select)
+#define bright          (imgdata.params.bright)
+#define threshold       (imgdata.params.threshold)
+#define half_size       (imgdata.params.half_size)
+#define four_color_rgb  (imgdata.params.four_color_rgb)
+#define document_mode   (imgdata.params.document_mode)
+#define highlight       (imgdata.params.highlight)
+//#define verbose         (imgdata.params.verbose)
+#define use_auto_wb     (imgdata.params.use_auto_wb)
+#define use_camera_wb   (imgdata.params.use_camera_wb)
+#define use_camera_matrix (imgdata.params.use_camera_matrix)
+#define output_color    (imgdata.params.output_color)
+#define output_bps      (imgdata.params.output_bps)
+#define gamma_16bit      (imgdata.params.gamma_16bit)
+#define output_tiff     (imgdata.params.output_tiff)
+#define med_passes      (imgdata.params.med_passes)
+#define no_auto_bright  (imgdata.params.no_auto_bright)
+#define use_fuji_rotate (imgdata.params.use_fuji_rotate)
+#define filtering_mode (imgdata.params.filtering_mode)
+
+//rgb_constants
+#define xyz_rgb         (rgb_constants.xyz_rgb)
+#define d65_white       (rgb_constants.d65_white)
+
+//libraw_internal_data.internal_data
+#define meta_data       (libraw_internal_data.internal_data.meta_data)
+#define ifp             libraw_internal_data.internal_data.input
+#define ifname          ((char*)libraw_internal_data.internal_data.input->fname())
+#define ofp             libraw_internal_data.internal_data.output
+#define profile_offset  (libraw_internal_data.internal_data.profile_offset)
+#define thumb_offset    (libraw_internal_data.internal_data.toffset)
+
+//libraw_internal_data.internal_output_params
+#define mix_green       (libraw_internal_data.internal_output_params.mix_green)
+#define raw_color       (libraw_internal_data.internal_output_params.raw_color)
+#define use_gamma       (libraw_internal_data.internal_output_params.use_gamma)
+#define zero_is_bad     (libraw_internal_data.internal_output_params.zero_is_bad)
+#ifndef SRC_USES_SHRINK
+#define shrink          (libraw_internal_data.internal_output_params.shrink)
+#endif
+#define fuji_width      (libraw_internal_data.internal_output_params.fuji_width)
+
+
+//libraw_internal_data.output_data
+#define histogram       (libraw_internal_data.output_data.histogram)
+#define oprof           (libraw_internal_data.output_data.oprof)
+
+//libraw_internal_data.identify_data
+#define exif_cfa        (libraw_internal_data.identify_data.olympus_exif_cfa)
+#define unique_id       (libraw_internal_data.identify_data.unique_id)
+#define tiff_nifds      (libraw_internal_data.identify_data.tiff_nifds)
+#define tiff_flip       (libraw_internal_data.identify_data.tiff_flip)
+
+//libraw_internal_data.unpacker_data
+#define order           (libraw_internal_data.unpacker_data.order)
+#define data_error      (libraw_internal_data.unpacker_data.data_error)
+#define cr2_slice       (libraw_internal_data.unpacker_data.cr2_slice)
+#define sraw_mul        (libraw_internal_data.unpacker_data.sraw_mul)
+#define kodak_cbpp      (libraw_internal_data.unpacker_data.kodak_cbpp)
+#define strip_offset    (libraw_internal_data.unpacker_data.strip_offset)
+#define data_offset     (libraw_internal_data.unpacker_data.data_offset)
+#define meta_offset     (libraw_internal_data.unpacker_data.meta_offset)
+#define meta_length     (libraw_internal_data.unpacker_data.meta_length)
+#define thumb_misc      (libraw_internal_data.unpacker_data.thumb_misc)
+#define fuji_layout     (libraw_internal_data.unpacker_data.fuji_layout)
+#define tiff_samples    (libraw_internal_data.unpacker_data.tiff_samples)
+#define tiff_bps        (libraw_internal_data.unpacker_data.tiff_bps)
+#define tiff_compress   (libraw_internal_data.unpacker_data.tiff_compress)
+#define zero_after_ff   (libraw_internal_data.unpacker_data.zero_after_ff)
+#define tile_width      (libraw_internal_data.unpacker_data.tile_width)
+#define tile_length     (libraw_internal_data.unpacker_data.tile_length)
+#define load_flags      (libraw_internal_data.unpacker_data.load_flags)
+
+#ifdef LIBRAW_IO_REDEFINED
+#define fread(ptr,size,n,stream) stream->read(ptr,size,n)
+#define fseek(stream,o,w)	 stream->seek(o,w)
+#define fseeko(stream,o,w)	 stream->seek(o,w)
+#define ftell(stream)		 stream->tell()
+#define ftello(stream)		 stream->tell()
+#ifdef getc
+#undef getc
+#endif
+#define getc(stream)		 stream->get_char()
+#define fgetc(stream)		 stream->get_char()
+#define fgets(str,n,stream)	 stream->gets(str,n)
+#define fscanf(stream,fmt,ptr)	 stream->scanf_one(fmt,ptr)
+#endif
+
+#endif
diff --git a/ossim_plugins/libraw/LibRaw-0.9.0/libraw/libraw.h b/ossim_plugins/libraw/LibRaw-0.9.0/libraw/libraw.h
new file mode 100644
index 0000000..e09dbdc
--- /dev/null
+++ b/ossim_plugins/libraw/LibRaw-0.9.0/libraw/libraw.h
@@ -0,0 +1,234 @@
+/* -*- C++ -*-
+ * File: libraw.h
+ * Copyright 2008-2010 LibRaw LLC (info at libraw.org)
+ * Created: Sat Mar  8, 2008 
+ *
+ * LibRaw C++ interface
+ *
+
+LibRaw is free software; you can redistribute it and/or modify
+it under the terms of the one of three licenses as you choose:
+
+1. GNU LESSER GENERAL PUBLIC LICENSE version 2.1
+   (See file LICENSE.LGPL provided in LibRaw distribution archive for details).
+
+2. COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0
+   (See file LICENSE.CDDL provided in LibRaw distribution archive for details).
+
+3. LibRaw Software License 27032010
+   (See file LICENSE.LibRaw.pdf provided in LibRaw distribution archive for details).
+
+*/
+
+#ifndef _LIBRAW_CLASS_H
+#define _LIBRAW_CLASS_H
+
+#ifdef __linux__
+#define _FILE_OFFSET_BITS 64
+#endif
+
+#include <limits.h>
+#include <memory.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+
+#include "libraw_datastream.h"
+#include "libraw_types.h"
+#include "libraw_const.h"
+#include "libraw_internal.h"
+#include "libraw_alloc.h"
+
+#ifdef __cplusplus
+extern "C" 
+{
+#endif
+DllDef    const char          *libraw_strerror(int errorcode);
+DllDef    const char          *libraw_strprogress(enum LibRaw_progress);
+    /* LibRaw C API */
+DllDef    libraw_data_t       *libraw_init(unsigned int flags);
+DllDef    int                 libraw_open_file(libraw_data_t*, const char *);
+DllDef    int                 libraw_open_buffer(libraw_data_t*, void * buffer, size_t size);
+DllDef    int                 libraw_unpack(libraw_data_t*);
+DllDef    int                 libraw_unpack_thumb(libraw_data_t*);
+DllDef    void                libraw_recycle(libraw_data_t*);
+DllDef    void                libraw_close(libraw_data_t*);
+    /* version helpers */
+DllDef    const char*               libraw_version();
+DllDef    int                 libraw_versionNumber();
+    /* Camera list */
+DllDef    const char**        libraw_cameraList();
+DllDef    int                 libraw_cameraCount();
+
+DllDef    void                libraw_set_memerror_handler(libraw_data_t*, memory_callback cb, void *datap);
+DllDef    void                libraw_set_dataerror_handler(libraw_data_t*,data_callback func,void *datap);
+DllDef    void                libraw_set_progress_handler(libraw_data_t*,progress_callback cb,void *datap);
+DllDef    int                 libraw_add_masked_borders_to_bitmap(libraw_data_t* lr);
+DllDef    const char *        libraw_unpack_function_name(libraw_data_t* lr);
+DllDef    int                 libraw_rotate_fuji_raw(libraw_data_t* lr);
+
+    /* DCRAW compatibility */
+DllDef    int                 libraw_adjust_sizes_info_only(libraw_data_t*);
+DllDef    int                 libraw_dcraw_document_mode_processing(libraw_data_t*);
+DllDef    int                 libraw_dcraw_ppm_tiff_writer(libraw_data_t* lr,const char *filename);
+DllDef    int                 libraw_dcraw_thumb_writer(libraw_data_t* lr,const char *fname);
+DllDef    int                 libraw_dcraw_process(libraw_data_t* lr);
+DllDef    libraw_processed_image_t* libraw_dcraw_make_mem_image(libraw_data_t* lr, int *errc);
+DllDef    libraw_processed_image_t* libraw_dcraw_make_mem_thumb(libraw_data_t* lr, int *errc);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#ifdef __cplusplus
+
+class DllDef LibRaw
+{
+  public:
+    libraw_data_t imgdata;
+    int verbose;
+
+    LibRaw(unsigned int flags = LIBRAW_OPTIONS_NONE);
+    
+    libraw_output_params_t*     output_params_ptr() { return &imgdata.params;}
+    int                         open_file(const char *fname);
+    int                         open_buffer(void *buffer, size_t size);
+    int                         open_datastream(LibRaw_abstract_datastream *);
+    int                         unpack(void);
+    int                         unpack_thumb(void);
+
+    int                         adjust_sizes_info_only(void);
+    int                         adjust_maximum();
+    void                        set_memerror_handler( memory_callback cb,void *data) {callbacks.memcb_data = data; callbacks.mem_cb = cb; }
+    void                        set_dataerror_handler(data_callback func, void *data) { callbacks.datacb_data = data; callbacks.data_cb = func;}
+    void                        set_progress_handler(progress_callback pcb, void *data) { callbacks.progresscb_data = data; callbacks.progress_cb = pcb;}
+
+    /* helpers */
+    static const char*          version();
+    static int                  versionNumber();
+    static const char**         cameraList();
+    static int                  cameraCount();
+    static const char*          strprogress(enum LibRaw_progress);
+    static const char*          strerror(int p);
+    /* dcraw emulation */
+    int                         dcraw_document_mode_processing();
+    int                         dcraw_ppm_tiff_writer(const char *filename);
+    int                         dcraw_thumb_writer(const char *fname);
+    int                         dcraw_process(void);
+    /* memory writers */
+    libraw_processed_image_t*   dcraw_make_mem_image(int *errcode=NULL);  
+    libraw_processed_image_t*   dcraw_make_mem_thumb(int *errcode=NULL);  
+
+    /* free all internal data structures */
+    void         recycle(); 
+    ~LibRaw(void) { recycle(); delete tls; }
+
+    int COLOR(int row, int col) { return libraw_internal_data.internal_output_params.fuji_width? FCF(row,col):FC(row,col);}
+
+    int FC(int row,int col) { return (imgdata.idata.filters >> ((((row) << 1 & 14) + ((col) & 1)) << 1) & 3);}
+    int         fc (int row, int col);
+    int add_masked_borders_to_bitmap();
+    
+    const char *unpack_function_name();
+    int         rotate_fuji_raw();
+
+  private:
+
+    int FCF(int row,int col) { 
+        int rr,cc;
+        if (libraw_internal_data.unpacker_data.fuji_layout) {
+            rr = libraw_internal_data.internal_output_params.fuji_width - 1 - col + (row >> 1);
+            cc = col + ((row+1) >> 1);
+        } else {
+            rr = libraw_internal_data.internal_output_params.fuji_width - 1 + row - (col >> 1);
+            cc = row + ((col+1) >> 1);
+        }
+        return FC(rr,cc);
+    }
+
+    void*        malloc(size_t t);
+    void*        calloc(size_t n,size_t t);
+    void        free(void *p);
+    void        merror (void *ptr, const char *where);
+    void        derror();
+
+    LibRaw_TLS  *tls;
+    libraw_internal_data_t libraw_internal_data;
+    decode      first_decode[2048], *second_decode, *free_decode;
+    tiff_ifd_t  tiff_ifd[10];
+    libraw_memmgr memmgr;
+    libraw_callbacks_t callbacks;
+
+    LibRaw_constants rgb_constants;
+    void        (LibRaw:: *write_thumb)(), 
+                (LibRaw:: *write_fun)();
+    void        (LibRaw:: *load_raw)(),
+                (LibRaw:: *thumb_load_raw)();
+
+    void        kodak_thumb_loader();
+    void        write_thumb_ppm_tiff(FILE *); 
+    
+    void init_masked_ptrs();
+    ushort *get_masked_pointer(int row, int col); 
+    
+    int         own_filtering_supported(){ return 0;}
+    void        identify();
+    void        identify2(unsigned, char*);
+    void        write_ppm_tiff ();
+    void        convert_to_rgb();
+    void        kodak_ycbcr_load_raw();
+    void        remove_zeroes();
+#ifndef NO_LCMS
+    void	apply_profile(const char*,const char*);
+#endif
+    void        pre_interpolate();
+    void        border_interpolate (int border);
+    void        lin_interpolate();
+    void        vng_interpolate();
+    void        ppg_interpolate();
+    void        ahd_interpolate();
+
+    void        bad_pixels(const char*);
+    void        subtract(const char*);
+    void        hat_transform (float *temp, float *base, int st, int size, int sc);
+    void        wavelet_denoise();
+    void        scale_colors();
+    void        median_filter ();
+    void        blend_highlights();
+    void        recover_highlights();
+
+    void        fuji_rotate();
+    void        stretch();
+
+    void        jpeg_thumb_writer (FILE *tfp,char *thumb,int thumb_length);
+    void        jpeg_thumb ();
+    void        ppm_thumb ();
+    void        layer_thumb ();
+    void        rollei_thumb ();
+    void        kodak_thumb_load_raw();
+
+    unsigned    get4();
+
+    int         flip_index (int row, int col);
+    void        gamma_curve (double pwr, double ts, int mode, int imax);
+
+
+#ifdef LIBRAW_LIBRARY_BUILD 
+#include "internal/libraw_internal_funcs.h"
+#endif
+
+};
+
+#ifdef LIBRAW_LIBRARY_BUILD 
+#define RUN_CALLBACK(stage,iter,expect)  if(callbacks.progress_cb) { \
+        int rr = (*callbacks.progress_cb)(callbacks.progresscb_data,stage,iter,expect); \
+        if(rr!=0) throw LIBRAW_EXCEPTION_CANCELLED_BY_CALLBACK; \
+    }
+#endif
+
+
+#endif /* __cplusplus */
+
+
+#endif /* _LIBRAW_CLASS_H */
diff --git a/ossim_plugins/libraw/LibRaw-0.9.0/libraw/libraw_alloc.h b/ossim_plugins/libraw/LibRaw-0.9.0/libraw/libraw_alloc.h
new file mode 100644
index 0000000..49ccac0
--- /dev/null
+++ b/ossim_plugins/libraw/LibRaw-0.9.0/libraw/libraw_alloc.h
@@ -0,0 +1,92 @@
+/* -*- C++ -*-
+ * File: libraw_alloc.h
+ * Copyright 2008-2010 LibRaw LLC (info at libraw.org)
+ * Created: Sat Mar  22, 2008 
+ *
+ * LibRaw C++ interface
+ *
+LibRaw is free software; you can redistribute it and/or modify
+it under the terms of the one of three licenses as you choose:
+
+1. GNU LESSER GENERAL PUBLIC LICENSE version 2.1
+   (See file LICENSE.LGPL provided in LibRaw distribution archive for details).
+
+2. COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0
+   (See file LICENSE.CDDL provided in LibRaw distribution archive for details).
+
+3. LibRaw Software License 27032010
+   (See file LICENSE.LibRaw.pdf provided in LibRaw distribution archive for details).
+
+ */
+
+#ifndef __LIBRAW_ALLOC_H
+#define __LIBRAW_ALLOC_H
+
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef __cplusplus
+
+#define MSIZE 32
+
+class libraw_memmgr
+{
+  public:
+    libraw_memmgr()
+        {
+            memset(mems,0,sizeof(mems));
+            calloc_cnt=0;
+        }
+    void *malloc(size_t sz)
+        {
+            void *ptr = ::malloc(sz);
+            mem_ptr(ptr);
+            return ptr;
+        }
+    void *calloc(size_t n, size_t sz)
+        {
+            void *ptr =  ::calloc(n,sz);
+            mem_ptr(ptr);
+            return ptr;
+        }
+    void  free(void *ptr)
+    {
+        ::free(ptr);
+        forget_ptr(ptr);
+    }
+    void cleanup(void)
+    {
+        for(int i = 0; i< MSIZE; i++)
+            if(mems[i])
+                {
+                    free(mems[i]);
+                    mems[i] = NULL;
+                }
+    }
+
+  private:
+    void *mems[MSIZE];
+    int calloc_cnt;
+    void mem_ptr(void *ptr)
+    {
+        if(ptr)
+            for(int i=0;i < MSIZE; i++)
+                if(!mems[i])
+                    {
+                        mems[i] = ptr;
+                        break;
+                    }
+    }
+    void forget_ptr(void *ptr)
+    {
+        if(ptr)
+            for(int i=0;i < MSIZE; i++)
+                if(mems[i] == ptr)
+                    mems[i] = NULL;
+    }
+
+};
+
+#endif /* C++ */
+
+#endif
diff --git a/ossim_plugins/libraw/LibRaw-0.9.0/libraw/libraw_const.h b/ossim_plugins/libraw/LibRaw-0.9.0/libraw/libraw_const.h
new file mode 100644
index 0000000..3d7472e
--- /dev/null
+++ b/ossim_plugins/libraw/LibRaw-0.9.0/libraw/libraw_const.h
@@ -0,0 +1,157 @@
+/* -*- C++ -*-
+ * File: libraw_const.h
+ * Copyright 2008-2010 LibRaw LLC (info at libraw.org)
+ * Created: Sat Mar  8 , 2008
+ *
+ * LibRaw error codes
+LibRaw is free software; you can redistribute it and/or modify
+it under the terms of the one of three licenses as you choose:
+
+1. GNU LESSER GENERAL PUBLIC LICENSE version 2.1
+   (See file LICENSE.LGPL provided in LibRaw distribution archive for details).
+
+2. COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0
+   (See file LICENSE.CDDL provided in LibRaw distribution archive for details).
+
+3. LibRaw Software License 27032010
+   (See file LICENSE.LibRaw.pdf provided in LibRaw distribution archive for details).
+
+ */
+
+#ifndef _LIBRAW_ERRORS_H
+#define _LIBRAW_ERRORS_H
+
+#define LIBRAW_DEFAULT_ADJUST_MAXIMUM_THRESHOLD 0.75
+#define LIBRAW_DEFAULT_AUTO_BRIGHTNESS_THRESHOLD 0.01
+
+enum LibRaw_constructor_flags
+{
+    LIBRAW_OPTIONS_NONE         =0,
+    LIBRAW_OPIONS_NO_MEMERR_CALLBACK=1,
+    LIBRAW_OPIONS_NO_DATAERR_CALLBACK=1<<1
+};
+
+enum LibRaw_warnings
+{
+    LIBRAW_WARN_NONE            =0,
+    LIBRAW_WARN_BAD_CAMERA_WB   =1<<2,
+    LIBRAW_WARN_NO_METADATA     =1<<3,
+    LIBRAW_WARN_NO_JPEGLIB     = 1<<4,
+    LIBRAW_WARN_NO_EMBEDDED_PROFILE = 1<<5,
+    LIBRAW_WARN_NO_INPUT_PROFILE = 1<<6,
+    LIBRAW_WARN_BAD_OUTPUT_PROFILE= 1<<7,
+    LIBRAW_WARN_NO_BADPIXELMAP=1<<8,
+    LIBRAW_WARN_BAD_DARKFRAME_FILE=1<<9,
+    LIBRAW_WARN_BAD_DARKFRAME_DIM=1<<10
+};
+
+enum LibRaw_exceptions
+{
+    LIBRAW_EXCEPTION_NONE       =0,
+    LIBRAW_EXCEPTION_ALLOC      =1,
+    LIBRAW_EXCEPTION_DECODE_RAW =2,
+    LIBRAW_EXCEPTION_DECODE_JPEG=3,
+    LIBRAW_EXCEPTION_IO_EOF     =4,
+    LIBRAW_EXCEPTION_IO_CORRUPT =5,
+    LIBRAW_EXCEPTION_CANCELLED_BY_CALLBACK=6
+};
+
+
+enum LibRaw_colorstate
+{
+    LIBRAW_COLORSTATE_UNKNOWN   =0,
+    LIBRAW_COLORSTATE_INIT      =1,
+    LIBRAW_COLORSTATE_CONST     =2,
+    LIBRAW_COLORSTATE_LOADED    =3,
+    LIBRAW_COLORSTATE_CALCULATED=4,
+    LIBRAW_COLORSTATE_RESERVED1 =5,
+    LIBRAW_COLORSTATE_RESERVED2 =6,
+    LIBRAW_COLORSTATE_RESERVED3 =7
+};
+
+enum LibRaw_filtering
+{
+    LIBRAW_FILTERING_DEFAULT            =0,
+    LIBRAW_FILTERING_NOZEROES           =1,  
+    LIBRAW_FILTERING_NOBLACKS           =2, 
+    LIBRAW_FILTERING_NORAWCURVE         =4,
+    LIBRAW_FILTERING_NONE               =7,
+    LIBRAW_FILTERING_LIBRAWOWN          =(8 | LIBRAW_FILTERING_NONE),
+    LIBRAW_FILTERING_AUTOMATIC_BIT      =16,
+    LIBRAW_FILTERING_AUTOMATIC          = (LIBRAW_FILTERING_LIBRAWOWN | LIBRAW_FILTERING_AUTOMATIC_BIT)
+};
+
+
+enum LibRaw_progress
+{
+    LIBRAW_PROGRESS_START               = 0,
+    LIBRAW_PROGRESS_OPEN                = 1,
+    LIBRAW_PROGRESS_IDENTIFY            = 1<<1,
+    LIBRAW_PROGRESS_SIZE_ADJUST         = 1<<2,
+    LIBRAW_PROGRESS_LOAD_RAW            = 1<<3,
+    LIBRAW_PROGRESS_REMOVE_ZEROES       = 1<<4,
+    LIBRAW_PROGRESS_BAD_PIXELS          = 1<<5,
+    LIBRAW_PROGRESS_DARK_FRAME          = 1<<6,
+    LIBRAW_PROGRESS_SCALE_COLORS        = 1<<8,
+    LIBRAW_PROGRESS_PRE_INTERPOLATE     = 1<<9,
+    LIBRAW_PROGRESS_INTERPOLATE         = 1<<10,
+    LIBRAW_PROGRESS_MIX_GREEN           = 1<<11,
+    LIBRAW_PROGRESS_MEDIAN_FILTER       = 1<<12,
+    LIBRAW_PROGRESS_HIGHLIGHTS          = 1<<13,
+    LIBRAW_PROGRESS_FUJI_ROTATE         = 1<<14,
+    LIBRAW_PROGRESS_FLIP                = 1<<15,
+    LIBRAW_PROGRESS_APPLY_PROFILE       = 1<<16,
+    LIBRAW_PROGRESS_CONVERT_RGB         = 1<<17,
+    LIBRAW_PROGRESS_STRETCH             = 1<<18,
+/* reserved */
+    LIBRAW_PROGRESS_STAGE19             = 1<<19,
+    LIBRAW_PROGRESS_STAGE20             = 1<<20,
+    LIBRAW_PROGRESS_STAGE21             = 1<<21,
+    LIBRAW_PROGRESS_STAGE22             = 1<<22,
+    LIBRAW_PROGRESS_STAGE23             = 1<<23,
+    LIBRAW_PROGRESS_STAGE24             = 1<<24,
+    LIBRAW_PROGRESS_STAGE25             = 1<<25,
+    LIBRAW_PROGRESS_STAGE26             = 1<<26,
+    LIBRAW_PROGRESS_STAGE27             = 1<<27,
+
+    LIBRAW_PROGRESS_THUMB_LOAD          = 1<<28,
+    LIBRAW_PROGRESS_TRESERVED1          = 1<<29,
+    LIBRAW_PROGRESS_TRESERVED2          = 1<<30,
+    LIBRAW_PROGRESS_TRESERVED3          = 1<<31
+};
+#define LIBRAW_PROGRESS_THUMB_MASK 0x0fffffff
+
+enum LibRaw_errors
+{
+    LIBRAW_SUCCESS = 0,
+    LIBRAW_UNSPECIFIED_ERROR=-1,
+    LIBRAW_FILE_UNSUPPORTED = -2,
+    LIBRAW_REQUEST_FOR_NONEXISTENT_IMAGE=-3,
+    LIBRAW_OUT_OF_ORDER_CALL=-4,
+    LIBRAW_NO_THUMBNAIL=-5,
+    LIBRAW_UNSUPPORTED_THUMBNAIL=-6,
+    LIBRAW_CANNOT_ADDMASK=-7,
+    LIBRAW_UNSUFFICIENT_MEMORY=-100007,
+    LIBRAW_DATA_ERROR=-100008,
+    LIBRAW_IO_ERROR=-100009,
+    LIBRAW_CANCELLED_BY_CALLBACK=-100010
+};
+
+#define LIBRAW_FATAL_ERROR(ec) ((ec)<-100000)
+
+enum LibRaw_thumbnail_formats
+{
+    LIBRAW_THUMBNAIL_UNKNOWN=0,
+    LIBRAW_THUMBNAIL_JPEG=1,
+    LIBRAW_THUMBNAIL_BITMAP=2,
+    LIBRAW_THUMBNAIL_LAYER=4,
+    LIBRAW_THUMBNAIL_ROLLEI=5
+};
+
+enum LibRaw_image_formats
+{
+    LIBRAW_IMAGE_JPEG=1,
+    LIBRAW_IMAGE_BITMAP=2
+};
+
+#endif
diff --git a/ossim_plugins/libraw/LibRaw-0.9.0/libraw/libraw_datastream.h b/ossim_plugins/libraw/LibRaw-0.9.0/libraw/libraw_datastream.h
new file mode 100644
index 0000000..e63e12c
--- /dev/null
+++ b/ossim_plugins/libraw/LibRaw-0.9.0/libraw/libraw_datastream.h
@@ -0,0 +1,316 @@
+/* -*- C -*-
+ * File: libraw_datastream.h
+ * Copyright 2008-2010 LibRaw LLC (info at libraw.org)
+ * Created: Sun Jan 18 13:07:35 2009
+ *
+ * LibRaw Data stream interface
+
+LibRaw is free software; you can redistribute it and/or modify
+it under the terms of the one of three licenses as you choose:
+
+1. GNU LESSER GENERAL PUBLIC LICENSE version 2.1
+   (See file LICENSE.LGPL provided in LibRaw distribution archive for details).
+
+2. COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0
+   (See file LICENSE.CDDL provided in LibRaw distribution archive for details).
+
+3. LibRaw Software License 27032010
+   (See file LICENSE.LibRaw.pdf provided in LibRaw distribution archive for details).
+
+ */
+
+#ifndef __LIBRAW_DATASTREAM_H
+#define __LIBRAW_DATASTREAM_H
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <string.h>
+
+#ifndef __cplusplus
+
+struct LibRaw_abstract_datastream;
+
+#else /* __cplusplus */
+
+#include "libraw_const.h"
+#include "libraw_types.h"
+
+class LibRaw_buffer_datastream;
+
+class LibRaw_abstract_datastream
+{
+  public:
+    LibRaw_abstract_datastream(){substream=0;};
+    virtual             ~LibRaw_abstract_datastream(void){if(substream) delete substream;}
+    virtual int         valid(){return 0;}
+    virtual int         read(void *,size_t, size_t ){ return -1;}
+    virtual int         seek(INT64 , int ){return -1;}
+    virtual INT64       tell(){return -1;}
+    virtual int         get_char(){return -1;}
+    virtual char*       gets(char *, int){ return NULL;}
+    virtual int         scanf_one(const char *, void *){return -1;}
+    virtual int         eof(){return -1;}
+
+    virtual const char* fname(){ return NULL;};
+    virtual int         subfile_open(const char*){ return EINVAL;}
+    virtual void        subfile_close(){}
+    virtual int		tempbuffer_open(void*, size_t);
+    virtual void	tempbuffer_close()
+    {
+        if(substream) delete substream;
+        substream = NULL;
+    }
+
+  protected:
+    LibRaw_abstract_datastream *substream;
+};
+
+
+class LibRaw_file_datastream : public LibRaw_abstract_datastream
+{
+  public:
+    LibRaw_file_datastream(const char *fname) 
+        { 
+            if(fname)
+                {filename = fname; f = fopen(fname,"rb");}
+            else 
+                {filename=0;f=0;}
+            sav=0;
+        }
+
+    virtual ~LibRaw_file_datastream() {if(f)fclose(f); if(sav)fclose(sav);}
+
+    virtual int valid() { return f?1:0;}
+
+#define CHK() do {if(!f) throw LIBRAW_EXCEPTION_IO_EOF;}while(0)
+    virtual int read(void * ptr,size_t size, size_t nmemb) 
+    { 
+        CHK(); 
+        return substream?substream->read(ptr,size,nmemb):int(fread(ptr,size,nmemb,f));
+    }
+    virtual int eof() 
+    { 
+        CHK(); 
+        return substream?substream->eof():feof(f);
+    }
+    virtual int seek(INT64 o, int whence) 
+    { 
+        CHK(); 
+#if defined (WIN32) 
+#if __MSVCRT_VERSION__ >= 0x800
+        return substream?substream->seek(o,whence):_fseeki64(f,o,whence);
+#else
+        return substream?substream->seek(o,whence):fseek(f,(size_t)o,whence);
+#endif
+#else
+        return substream?substream->seek(o,whence):fseeko(f,o,whence);
+#endif
+    }
+    virtual INT64 tell() 
+    { 
+        CHK(); 
+#if defined (WIN32)
+#if __MSVCRT_VERSION__ >= 0x800
+        return substream?substream->tell():_ftelli64(f);
+#else
+        return substream?substream->tell():ftell(f);
+#endif
+#else
+        return substream?substream->tell():ftello(f);
+#endif
+    }
+    virtual int get_char() 
+    { 
+        CHK(); 
+        return substream?substream->get_char():fgetc(f);
+    }
+    virtual char* gets(char *str, int sz) 
+    { 
+        CHK(); 
+        return substream?substream->gets(str,sz):fgets(str,sz,f);
+    }
+    virtual int scanf_one(const char *fmt, void*val) 
+    { 
+        CHK(); 
+        return substream?substream->scanf_one(fmt,val):fscanf(f,fmt,val);
+    }
+
+    virtual const char *fname() { return filename; }
+
+    virtual int subfile_open(const char *fn)
+    {
+        if(sav) return EBUSY;
+        sav = f;
+        f = fopen(fn,"rb");
+        if(!f)
+            {
+                f = sav;
+                sav = NULL;
+                return ENOENT;
+            }
+        else
+            return 0;
+    }
+    virtual void subfile_close()
+    {
+        if(!sav) return;
+        fclose(f);
+        f = sav;
+        sav = 0;
+    }
+
+  private:
+    FILE *f,*sav;
+    const char *filename;
+};
+#undef CHK
+
+class LibRaw_buffer_datastream : public LibRaw_abstract_datastream
+{
+  public:
+    LibRaw_buffer_datastream(void *buffer, size_t bsize)
+        {
+            buf = (unsigned char*)buffer; streampos = 0; streamsize = bsize;
+        }
+    virtual ~LibRaw_buffer_datastream(){}
+    virtual int valid() { return buf?1:0;}
+    virtual int read(void * ptr,size_t sz, size_t nmemb) 
+    { 
+        if(substream) return substream->read(ptr,sz,nmemb);
+        size_t to_read = sz*nmemb;
+        if(to_read > streamsize - streampos)
+            to_read = streamsize-streampos;
+        if(to_read<1) 
+            return 0;
+        memmove(ptr,buf+streampos,to_read);
+        streampos+=to_read;
+        return int((to_read+sz-1)/sz);
+    }
+
+    virtual int eof() 
+    { 
+        if(substream) return substream->eof();
+        return streampos >= streamsize;
+    }
+
+    virtual int seek(INT64 o, int whence) 
+    { 
+        if(substream) return substream->seek(o,whence);
+        switch(whence)
+            {
+            case SEEK_SET:
+                if(o<0)
+                    streampos = 0;
+                else if (size_t(o) > streamsize)
+                    streampos = streamsize;
+                else
+                    streampos = size_t(o);
+                return 0;
+            case SEEK_CUR:
+                if(o<0)
+                    {
+                        if(size_t(-o) >= streampos)
+                            streampos = 0;
+                        else
+                            streampos += (size_t)o;
+                    }
+                else if (o>0)
+                    {
+                        if(o+streampos> streamsize)
+                            streampos = streamsize;
+                        else
+                            streampos += (size_t)o;
+                    }
+                return 0;
+            case SEEK_END:
+                if(o>0)
+                    streampos = streamsize;
+                else if ( size_t(-o) > streamsize)
+                    streampos = 0;
+                else
+                    streampos = streamsize+(size_t)o;
+                return 0;
+            default:
+                return 0;
+            }
+    }
+    
+    virtual INT64 tell() 
+    { 
+        if(substream) return substream->tell();
+        return INT64(streampos);
+    }
+
+    virtual int get_char() 
+    { 
+        if(substream) return substream->get_char();
+        if(streampos>=streamsize)
+            return -1;
+        return buf[streampos++];
+    }
+    virtual char* gets(char *s, int sz) 
+    { 
+        if (substream) return substream->gets(s,sz);
+        unsigned char *psrc,*pdest,*str;
+        str = (unsigned char *)s;
+        psrc = buf+streampos;
+        pdest = str;
+        while ( (size_t(psrc - buf) < streamsize)
+               &&
+                ((pdest-str)<sz)
+		)
+	  {
+                *pdest = *psrc;
+                if(*psrc == '\n')
+                    break;
+                psrc++;
+                pdest++;
+            }
+        if(size_t(psrc-buf) < streamsize)
+            psrc++;
+        if((pdest-str)<sz)
+            *(++pdest)=0;
+        streampos = psrc - buf;
+        return s;
+    }
+    virtual int scanf_one(const char *fmt, void* val) 
+    { 
+        if(substream) return substream->scanf_one(fmt,val);
+        int scanf_res;
+        if(streampos>streamsize) return 0;
+        scanf_res = sscanf((char*)(buf+streampos),fmt,val);
+        if(scanf_res>0)
+            {
+                int xcnt=0;
+                while(streampos<streamsize)
+                    {
+                        streampos++;
+                        xcnt++;
+                        if(buf[streampos] == 0
+                           || buf[streampos]==' '
+                           || buf[streampos]=='\t'
+                           || buf[streampos]=='\n'
+                           || xcnt>24)
+                            break;
+                    }
+            }
+        return scanf_res;
+    }
+  private:
+    unsigned char *buf;
+    size_t   streampos,streamsize;
+};
+
+inline int LibRaw_abstract_datastream::tempbuffer_open(void  *buf, size_t size)
+{
+    if(substream) return EBUSY;
+    substream = new LibRaw_buffer_datastream(buf,size);
+    return substream?0:EINVAL;
+}
+
+
+#endif
+
+#endif
+
diff --git a/ossim_plugins/libraw/LibRaw-0.9.0/libraw/libraw_internal.h b/ossim_plugins/libraw/LibRaw-0.9.0/libraw/libraw_internal.h
new file mode 100644
index 0000000..fee2149
--- /dev/null
+++ b/ossim_plugins/libraw/LibRaw-0.9.0/libraw/libraw_internal.h
@@ -0,0 +1,224 @@
+/* -*- C++ -*-
+ * File: libraw_internal.h
+ * Copyright 2008-2010 LibRaw LLC (info at libraw.org)
+ * Created: Sat Mar  8 , 2008
+ *
+ * LibRaw internal data structures (not visible outside)
+
+LibRaw is free software; you can redistribute it and/or modify
+it under the terms of the one of three licenses as you choose:
+
+1. GNU LESSER GENERAL PUBLIC LICENSE version 2.1
+   (See file LICENSE.LGPL provided in LibRaw distribution archive for details).
+
+2. COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0
+   (See file LICENSE.CDDL provided in LibRaw distribution archive for details).
+
+3. LibRaw Software License 27032010
+   (See file LICENSE.LibRaw.pdf provided in LibRaw distribution archive for details).
+
+ */
+
+#ifndef _LIBRAW_INTERNAL_TYPES_H
+#define _LIBRAW_INTERNAL_TYPES_H
+
+#include <stdio.h>
+#ifdef __cplusplus
+
+
+#ifndef CLASS
+#define CLASS LibRaw::
+#endif
+
+#else
+#ifndef CLASS
+#define CLASS
+#endif
+#endif
+
+
+#ifdef __cplusplus
+
+#include "libraw_datastream.h"
+
+class LibRaw_TLS
+{
+public:
+    struct
+    {
+         unsigned bitbuf;
+         int vbits, reset;
+    }getbits;
+    struct 
+    {
+         UINT64 bitbuf;
+         int vbits;
+
+    }ph1_bits;
+    struct
+    {
+         unsigned pad[128], p;
+    }sony_decrypt;
+    uchar jpeg_buffer[4096];
+    struct
+    {
+        uchar buf[0x4000];
+        int vbits, padding;
+    }pana_bits;
+
+    void init() 
+        { 
+            getbits.bitbuf = 0; getbits.vbits = getbits.reset = 0;
+            ph1_bits.bitbuf = 0; ph1_bits.vbits = 0;
+            pana_bits.vbits = 0;
+        }
+};
+
+
+class LibRaw_constants
+{
+  public:
+    static const float d65_white[3];
+    static const double xyz_rgb[3][3];
+};
+#endif /* __cplusplus */
+
+
+typedef struct
+{
+#ifndef __cplusplus
+    struct
+#endif
+    LibRaw_abstract_datastream *input;
+    FILE        *output;
+    int         input_internal;
+    char        *meta_data;
+    INT64       profile_offset;
+    INT64       toffset;
+
+} internal_data_t;
+
+typedef struct
+{
+    unsigned    mix_green;
+    unsigned    raw_color;
+    unsigned    zero_is_bad;
+    ushort      shrink;
+    ushort      fuji_width;
+    ushort      fwidth,fheight;
+} internal_output_params_t;
+
+#define LIBRAW_HISTOGRAM_SIZE 0x2000
+typedef struct
+{
+    int         (*histogram)[LIBRAW_HISTOGRAM_SIZE];
+    unsigned    *oprof;
+} output_data_t;
+
+typedef struct
+{
+    unsigned olympus_exif_cfa;
+    unsigned     unique_id;
+    unsigned tiff_nifds;
+    int  tiff_flip;
+}identify_data_t;
+
+typedef struct
+{
+    short       order; 
+    ushort      sraw_mul[4],cr2_slice[3];
+    unsigned    kodak_cbpp;
+    INT64       strip_offset, data_offset;
+    INT64       meta_offset;
+    unsigned     meta_length;
+    unsigned    thumb_misc;
+    unsigned    fuji_layout;
+    unsigned    tiff_samples;
+    unsigned    tiff_bps;
+    unsigned    tiff_compress;
+    unsigned    zero_after_ff;
+    unsigned    tile_width, tile_length,load_flags;
+    unsigned    data_error;
+}unpacker_data_t;
+
+
+
+typedef struct
+{
+    internal_data_t internal_data;
+    internal_output_params_t internal_output_params;    
+    output_data_t output_data;
+    identify_data_t identify_data;
+    unpacker_data_t unpacker_data;
+} libraw_internal_data_t;
+
+
+struct decode 
+{
+    struct decode *branch[2];
+    int leaf;
+};
+
+struct tiff_ifd_t 
+{
+    int t_width, t_height, bps, comp, phint, offset, t_flip, samples, bytes;
+};
+
+
+struct jhead {
+  int bits, high, wide, clrs, sraw, psv, restart, vpred[6];
+    ushort *huff[6], *free[4], *row;
+};
+struct tiff_tag {
+  ushort tag, type;
+  int count;
+  union { char c[4]; short s[2]; int i; } val;
+};
+
+struct tiff_hdr {
+  ushort t_order, magic;
+  int ifd;
+  ushort pad, ntag;
+  struct tiff_tag tag[23];
+  int nextifd;
+  ushort pad2, nexif;
+  struct tiff_tag exif[4];
+  ushort pad3, ngps;
+  struct tiff_tag gpst[10];
+  short bps[4];
+  int rat[10];
+  unsigned gps[26];
+  char t_desc[512], t_make[64], t_model[64], soft[32], date[20], t_artist[64];
+};
+
+
+
+#ifdef DEBUG_STAGE_CHECKS
+#define CHECK_ORDER_HIGH(expected_stage) \
+    do { if((imgdata.progress_flags & LIBRAW_PROGRESS_THUMB_MASK) >= expected_stage) {fprintf(stderr,"CHECK_HIGH: check %d >=  %d\n",imgdata.progress_flags & LIBRAW_PROGRESS_THUMB_MASK,expected_stage);return LIBRAW_OUT_OF_ORDER_CALL;} } while(0)
+
+#define CHECK_ORDER_LOW(expected_stage) \
+    do { printf("Checking LOW %d/%d : %d\n",imgdata.progress_flags,expected_stage,imgdata.progress_flags<expected_stage); if( (imgdata.progress_flags&LIBRAW_PROGRESS_THUMB_MASK) < expected_stage ) { printf("failed!\n"); return LIBRAW_OUT_OF_ORDER_CALL;} } while(0)
+#define CHECK_ORDER_BIT(expected_stage) \
+    do { if(imgdata.progress_flags & expected_stage) return LIBRAW_OUT_OF_ORDER_CALL; } while(0)
+
+#define SET_PROC_FLAG(stage) do {imgdata.progress_flags |= stage; fprintf(stderr,"SET_FLAG: %d\n",stage); } while (0)
+
+#else
+
+#define CHECK_ORDER_HIGH(expected_stage) \
+    do { if((imgdata.progress_flags & LIBRAW_PROGRESS_THUMB_MASK) >= expected_stage) \
+            {return LIBRAW_OUT_OF_ORDER_CALL;} } while(0)
+
+#define CHECK_ORDER_LOW(expected_stage) \
+    do { if((imgdata.progress_flags&LIBRAW_PROGRESS_THUMB_MASK) < expected_stage) \
+            return LIBRAW_OUT_OF_ORDER_CALL; } while(0)
+
+#define CHECK_ORDER_BIT(expected_stage) \
+    do { if(imgdata.progress_flags & expected_stage) return LIBRAW_OUT_OF_ORDER_CALL; } while(0)
+
+#define SET_PROC_FLAG(stage) do {imgdata.progress_flags |= stage;} while (0)
+
+#endif
+
+#endif
diff --git a/ossim_plugins/libraw/LibRaw-0.9.0/libraw/libraw_types.h b/ossim_plugins/libraw/LibRaw-0.9.0/libraw/libraw_types.h
new file mode 100644
index 0000000..5800bd6
--- /dev/null
+++ b/ossim_plugins/libraw/LibRaw-0.9.0/libraw/libraw_types.h
@@ -0,0 +1,295 @@
+/* -*- C++ -*-
+ * File: libraw_types.h
+ * Copyright 2008-2010 LibRaw LLC (info at libraw.org)
+ * Created: Sat Mar  8 , 2008
+ *
+ * LibRaw C data structures
+ *
+
+LibRaw is free software; you can redistribute it and/or modify
+it under the terms of the one of three licenses as you choose:
+
+1. GNU LESSER GENERAL PUBLIC LICENSE version 2.1
+   (See file LICENSE.LGPL provided in LibRaw distribution archive for details).
+
+2. COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0
+   (See file LICENSE.CDDL provided in LibRaw distribution archive for details).
+
+3. LibRaw Software License 27032010
+   (See file LICENSE.LibRaw.pdf provided in LibRaw distribution archive for details).
+
+ */
+
+#ifndef _LIBRAW_TYPES_H
+#define _LIBRAW_TYPES_H
+
+#include <sys/types.h>
+#ifndef WIN32
+#include <sys/time.h>
+#endif
+#include <stdio.h>
+#ifdef _OPENMP
+#ifdef _MSC_VER
+#error OpenMP is not supported under MS Visual Studio
+#endif
+#include <omp.h>
+#endif
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef USE_LCMS
+#define NO_LCMS
+#endif
+
+#include "libraw_const.h"
+#include "libraw_version.h"
+
+#ifdef WIN32
+typedef __int64 INT64;
+typedef unsigned __int64 UINT64;
+#else
+typedef long long INT64;
+typedef unsigned long long UINT64;
+#endif
+
+typedef unsigned char uchar;
+typedef unsigned short ushort;
+
+#ifdef WIN32
+#ifdef LIBRAW_NODLL
+# define DllDef
+#else
+# ifdef LIBRAW_BUILDLIB
+#    define DllDef   __declspec( dllexport )
+# else
+#    define DllDef   __declspec( dllimport )
+# endif
+#endif
+#else
+#  define DllDef
+#endif
+
+
+
+typedef void (* memory_callback)(void * data, const char *file, const char *where);
+
+DllDef void default_memory_callback(void *data,const char *file, const char *where);
+
+typedef void (*data_callback)(void *data,const char *file, const int offset);
+
+DllDef void default_data_callback(void *data,const char *file, const int offset);
+
+typedef int (* progress_callback) (void *data,enum LibRaw_progress stage, int iteration,int expected);
+
+typedef struct
+{
+    memory_callback mem_cb;
+    void*  memcb_data;
+
+    data_callback data_cb;
+    void*       datacb_data;
+
+    progress_callback progress_cb;
+    void *progresscb_data;
+} libraw_callbacks_t;
+
+
+typedef struct
+{
+    enum LibRaw_image_formats type; 
+    ushort      height,
+                width,
+                colors,
+                bits;
+#ifdef LIBRAW_LIBRARY_BUILD
+#ifdef _OPENMP
+#pragma omp firstprivate(colors,height,width)
+#endif
+#endif
+    unsigned int  data_size; 
+    unsigned char data[1]; 
+}libraw_processed_image_t;
+
+
+typedef struct
+{
+    char        make[64];
+    char        model[64];
+
+    unsigned    raw_count;
+    unsigned    dng_version;
+    int         colors;
+
+    unsigned    filters; 
+    char        cdesc[5];
+
+}libraw_iparams_t;
+
+typedef struct
+{
+    ushort      raw_height, 
+                raw_width, 
+                height, 
+                width, 
+                top_margin, 
+                left_margin;
+    ushort      iheight,
+                iwidth;
+#ifdef LIBRAW_LIBRARY_BUILD
+#ifdef _OPENMP
+#pragma omp firstprivate(iheight,iwidth)
+#endif
+#endif
+    double      pixel_aspect;
+    int         flip;
+
+    ushort      right_margin,bottom_margin; 
+
+} libraw_image_sizes_t;
+
+struct ph1_t
+{
+    int format, key_off, t_black, black_off, split_col, tag_21a;
+    float tag_210;
+};
+
+
+typedef struct
+{
+    unsigned curve_state        : 3;
+    unsigned rgb_cam_state      : 3;
+    unsigned cmatrix_state      : 3;
+    unsigned pre_mul_state      : 3;
+    unsigned cam_mul_state      : 3;
+    unsigned filler             : 17;
+} color_data_state_t;
+
+typedef struct
+{
+    color_data_state_t   color_flags;
+    ushort      white[8][8];  
+    float       cam_mul[4]; 
+    float       pre_mul[4]; 
+    float       cmatrix[3][4]; 
+    float       rgb_cam[3][4]; 
+    float       cam_xyz[4][3]; 
+    ushort      curve[0x10000]; 
+    unsigned    black;
+    unsigned    maximum;
+    unsigned    channel_maximum[4];
+    struct ph1_t       phase_one_data;
+    float       flash_used; 
+    float       canon_ev; 
+    char        model2[64];
+    void        *profile;
+    unsigned    profile_length;
+}libraw_colordata_t;
+
+typedef struct
+{
+    enum LibRaw_thumbnail_formats tformat;
+    ushort      twidth, 
+                theight;
+    unsigned    tlength;
+    int         tcolors;
+    
+    char       *thumb;
+}libraw_thumbnail_t;
+
+typedef struct
+{
+    float       iso_speed; 
+    float       shutter;
+    float       aperture;
+    float       focal_len;
+    time_t      timestamp; 
+    unsigned    shot_order;
+    unsigned    gpsdata[32];
+    char        desc[512],
+                artist[64];
+} libraw_imgother_t;
+
+typedef struct
+{
+    unsigned    greybox[4];     /* -A  x1 y1 x2 y2 */
+    double      aber[4];        /* -C */
+    double      gamm[6];        /* -g */
+    float       user_mul[4];    /* -r mul0 mul1 mul2 mul3 */
+    unsigned    shot_select;    /* -s */
+    float       bright;         /* -b */
+    float       threshold;      /*  -n */
+#ifdef LIBRAW_LIBRARY_BUILD
+#ifdef _OPENMP
+#pragma omp firstprivate(threshold)
+#endif
+#endif
+    int         half_size;      /* -h */
+    int         four_color_rgb; /* -f */
+    int         document_mode;  /* -d/-D */
+    int         highlight;      /* -H */
+    int         use_auto_wb;    /* -a */
+    int         use_camera_wb;  /* -w */
+    int         use_camera_matrix; /* +M/-M */
+    int         output_color;   /* -o */
+    char        *output_profile; /* -o */
+    char        *camera_profile; /* -p */
+    char        *bad_pixels;    /* -P */
+    char        *dark_frame;    /* -K */
+    int         output_bps;     /* -4 */
+    int         output_tiff;    /* -T */
+    int         user_flip;      /* -t */
+    int         user_qual;      /* -q */
+    int         user_black;     /* -k */
+    int         user_sat;       /* -S */
+
+    int         med_passes;     /* -m */
+    float       auto_bright_thr; 
+    float       adjust_maximum_thr;
+    int         no_auto_bright; /* -W */
+    int         use_fuji_rotate;/* -j */
+    enum LibRaw_filtering    filtering_mode; 
+}libraw_output_params_t;
+
+typedef struct
+{
+    ushort  *buffer; 
+    ushort  *tl;     
+    ushort  *top;    
+    ushort  *tr;    
+    ushort  *left;  
+    ushort  *right; 
+    ushort  *bl;     
+    ushort  *bottom; 
+    ushort  *br;     
+    ushort  (*ph1_black)[2]; 
+}libraw_masked_t;
+
+typedef struct
+{
+    unsigned int                progress_flags;
+    unsigned int                process_warnings;
+    libraw_iparams_t            idata;
+    libraw_image_sizes_t        sizes;
+    libraw_colordata_t          color;
+    libraw_imgother_t           other;
+    libraw_thumbnail_t          thumbnail;
+    libraw_masked_t             masked_pixels;
+    ushort                      (*image)[4] ;
+#ifdef LIBRAW_LIBRARY_BUILD
+#ifdef _OPENMP
+#pragma omp shared(image)
+#endif
+#endif
+    libraw_output_params_t     params;
+    void                *parent_class;      
+} libraw_data_t;
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/ossim_plugins/libraw/LibRaw-0.9.0/libraw/libraw_version.h b/ossim_plugins/libraw/LibRaw-0.9.0/libraw/libraw_version.h
new file mode 100644
index 0000000..78d6b56
--- /dev/null
+++ b/ossim_plugins/libraw/LibRaw-0.9.0/libraw/libraw_version.h
@@ -0,0 +1,46 @@
+/* -*- C++ -*-
+ * File: libraw_version.h
+ * Copyright 2008-2010 LibRaw LLC (info at libraw.org)
+ * Created: Mon Sept  8, 2008 
+ *
+ * LibRaw C++ interface
+ *
+
+LibRaw is free software; you can redistribute it and/or modify
+it under the terms of the one of three licenses as you choose:
+
+1. GNU LESSER GENERAL PUBLIC LICENSE version 2.1
+   (See the file LICENSE.LGPL provided in LibRaw distribution archive for details).
+
+2. COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0
+   (See the file LICENSE.CDDL provided in LibRaw distribution archive for details).
+
+3. LibRaw Software License 27032010
+   (See the file LICENSE.LibRaw.pdf provided in LibRaw distribution archive for details).
+
+ */
+
+#ifndef __VERSION_H
+#define __VERSION_H
+
+#define LIBRAW_MAJOR_VERSION  0
+#define LIBRAW_MINOR_VERSION  9
+#define LIBRAW_PATCH_VERSION  0
+#define LIBRAW_VERSION_TAIL   Release
+
+#define _LIBRAW_VERSION_MAKE(a,b,c,d) #a"."#b"."#c"-"#d
+#define LIBRAW_VERSION_MAKE(a,b,c,d) _LIBRAW_VERSION_MAKE(a,b,c,d)
+
+#define LIBRAW_VERSION_STR LIBRAW_VERSION_MAKE(LIBRAW_MAJOR_VERSION,LIBRAW_MINOR_VERSION,LIBRAW_PATCH_VERSION,LIBRAW_VERSION_TAIL)
+
+#define LIBRAW_MAKE_VERSION(major,minor,patch) \
+    (((major) << 16) | ((minor) << 8) | (patch))
+
+#define LIBRAW_VERSION \
+    LIBRAW_MAKE_VERSION(LIBRAW_MAJOR_VERSION,LIBRAW_MINOR_VERSION,LIBRAW_PATCH_VERSION)
+
+#define LIBRAW_CHECK_VERSION(major,minor,patch) \
+    ( LibRaw::versionNumber() >= LIBRAW_MAKE_VERSION(major,minor,patch) )
+
+
+#endif
diff --git a/ossim_plugins/libraw/LibRaw-0.9.0/src/libraw_c_api.cpp b/ossim_plugins/libraw/LibRaw-0.9.0/src/libraw_c_api.cpp
new file mode 100644
index 0000000..250b6f5
--- /dev/null
+++ b/ossim_plugins/libraw/LibRaw-0.9.0/src/libraw_c_api.cpp
@@ -0,0 +1,170 @@
+/* -*- C++ -*-
+ * File: libraw_c_api.cpp
+ * Copyright 2008-2010 LibRaw LLC (info at libraw.org)
+ * Created: Sat Mar  8 , 2008
+ *
+ * LibRaw C interface 
+
+
+LibRaw is free software; you can redistribute it and/or modify
+it under the terms of the one of three licenses as you choose:
+
+1. GNU LESSER GENERAL PUBLIC LICENSE version 2.1
+   (See file LICENSE.LGPL provided in LibRaw distribution archive for details).
+
+2. COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0
+   (See file LICENSE.CDDL provided in LibRaw distribution archive for details).
+
+3. LibRaw Software License 27032010
+   (See file LICENSE.LibRaw.pdf provided in LibRaw distribution archive for details).
+
+
+
+ */
+#include <errno.h>
+#include "libraw/libraw.h"
+
+#ifdef __cplusplus
+extern "C" 
+{
+#endif
+
+    libraw_data_t *libraw_init(unsigned int flags)
+    {
+        LibRaw *ret = new LibRaw(flags);
+        return &(ret->imgdata);
+    }
+
+    const char*   libraw_version() { return LibRaw::version();}
+    const char*   libraw_strprogress(enum LibRaw_progress p) { return LibRaw::strprogress(p);}
+    int     libraw_versionNumber() { return LibRaw::versionNumber();}
+    const char**  libraw_cameraList() { return LibRaw::cameraList();}
+    int   libraw_cameraCount() { return LibRaw::cameraCount(); }
+    const char* libraw_unpack_function_name(libraw_data_t* lr)
+    {
+        if(!lr) return "NULL parameter passed";
+        LibRaw *ip = (LibRaw*) lr->parent_class;
+        return ip->unpack_function_name();
+    }
+    int libraw_rotate_fuji_raw(libraw_data_t* lr)
+    {
+        if(!lr) return EINVAL;
+        LibRaw *ip = (LibRaw*) lr->parent_class;
+        return ip->rotate_fuji_raw();
+    }
+
+    int libraw_add_masked_borders_to_bitmap(libraw_data_t* lr)
+    {
+        if(!lr) return EINVAL;
+        LibRaw *ip = (LibRaw*) lr->parent_class;
+        return ip->add_masked_borders_to_bitmap();
+    }
+
+    int libraw_open_file(libraw_data_t* lr, const char *file)
+    {
+        if(!lr) return EINVAL;
+        LibRaw *ip = (LibRaw*) lr->parent_class;
+        return ip->open_file(file);
+    }
+    int libraw_open_buffer(libraw_data_t* lr, void *buffer, size_t size)
+    {
+        if(!lr) return EINVAL;
+        LibRaw *ip = (LibRaw*) lr->parent_class;
+        return ip->open_buffer(buffer,size);
+    }
+    int libraw_unpack(libraw_data_t* lr)
+    {
+        if(!lr) return EINVAL;
+        LibRaw *ip = (LibRaw*) lr->parent_class;
+        return ip->unpack();
+    }
+    int libraw_unpack_thumb(libraw_data_t* lr)
+    {
+        if(!lr) return EINVAL;
+        LibRaw *ip = (LibRaw*) lr->parent_class;
+        return ip->unpack_thumb();
+    }
+    void libraw_recycle(libraw_data_t* lr)
+    {
+        if(!lr) return;
+        LibRaw *ip = (LibRaw*) lr->parent_class;
+        ip->recycle();
+    }
+    void libraw_close(libraw_data_t* lr)
+    {
+        if(!lr) return;
+        LibRaw *ip = (LibRaw*) lr->parent_class;
+        delete ip;
+    }
+
+    void  libraw_set_memerror_handler(libraw_data_t* lr, memory_callback cb,void *data)
+    {
+        if(!lr) return;
+        LibRaw *ip = (LibRaw*) lr->parent_class;
+        ip->set_memerror_handler(cb,data);
+
+    }
+    void libraw_set_dataerror_handler(libraw_data_t* lr,data_callback func,void *data)
+    {
+        if(!lr) return;
+        LibRaw *ip = (LibRaw*) lr->parent_class;
+        ip->set_dataerror_handler(func,data);
+
+    }
+    void  libraw_set_progress_handler(libraw_data_t* lr, progress_callback cb,void *data)
+    {
+        if(!lr) return;
+        LibRaw *ip = (LibRaw*) lr->parent_class;
+        ip->set_progress_handler(cb,data);
+
+    }
+
+    // DCRAW
+    int  libraw_adjust_sizes_info_only(libraw_data_t* lr)
+    {
+        if(!lr) return EINVAL;
+        LibRaw *ip = (LibRaw*) lr->parent_class;
+        return ip->adjust_sizes_info_only();
+    }
+    int  libraw_dcraw_document_mode_processing(libraw_data_t* lr)
+    {
+        if(!lr) return EINVAL;
+        LibRaw *ip = (LibRaw*) lr->parent_class;
+        return ip->dcraw_document_mode_processing();
+
+    }
+    int  libraw_dcraw_ppm_tiff_writer(libraw_data_t* lr,const char *filename)
+    {
+        if(!lr) return EINVAL;
+        LibRaw *ip = (LibRaw*) lr->parent_class;
+        return ip->dcraw_ppm_tiff_writer(filename);
+    }
+    int  libraw_dcraw_thumb_writer(libraw_data_t* lr,const char *fname)
+    {
+        if(!lr) return EINVAL;
+        LibRaw *ip = (LibRaw*) lr->parent_class;
+        return ip->dcraw_thumb_writer(fname);
+
+    }
+    int libraw_dcraw_process(libraw_data_t* lr)
+    {
+        if(!lr) return EINVAL;
+        LibRaw *ip = (LibRaw*) lr->parent_class;
+        return ip->dcraw_process();
+    }
+    libraw_processed_image_t *libraw_dcraw_make_mem_image(libraw_data_t* lr,int *errc)
+    {
+        if(!lr) { if(errc) *errc=EINVAL; return NULL;}
+        LibRaw *ip = (LibRaw*) lr->parent_class;
+        return ip->dcraw_make_mem_image(errc);
+    }
+    libraw_processed_image_t *libraw_dcraw_make_mem_thumb(libraw_data_t* lr,int *errc)
+    {
+        if(!lr) { if(errc) *errc=EINVAL; return NULL;}
+        LibRaw *ip = (LibRaw*) lr->parent_class;
+        return ip->dcraw_make_mem_thumb(errc);
+    }
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/ossim_plugins/libraw/LibRaw-0.9.0/src/libraw_cxx.cpp b/ossim_plugins/libraw/LibRaw-0.9.0/src/libraw_cxx.cpp
new file mode 100644
index 0000000..0192a5e
--- /dev/null
+++ b/ossim_plugins/libraw/LibRaw-0.9.0/src/libraw_cxx.cpp
@@ -0,0 +1,1956 @@
+/* -*- C++ -*-
+ * File: libraw_cxx.cpp
+ * Copyright 2008-2010 LibRaw LLC (info at libraw.org)
+ * Created: Sat Mar  8 , 2008
+ *
+ * LibRaw C++ interface (implementation)
+
+LibRaw is free software; you can redistribute it and/or modify
+it under the terms of the one of three licenses as you choose:
+
+1. GNU LESSER GENERAL PUBLIC LICENSE version 2.1
+   (See file LICENSE.LGPL provided in LibRaw distribution archive for details).
+
+2. COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0
+   (See file LICENSE.CDDL provided in LibRaw distribution archive for details).
+
+3. LibRaw Software License 27032010
+   (See file LICENSE.LibRaw.pdf provided in LibRaw distribution archive for details).
+
+ */
+
+#include <errno.h>
+#include <float.h>
+#include <math.h>
+#ifndef WIN32
+#include <netinet/in.h>
+#else
+#include <winsock2.h>
+#endif
+#define LIBRAW_LIBRARY_BUILD
+#include "libraw/libraw.h"
+
+#ifdef __cplusplus
+extern "C" 
+{
+#endif
+    void default_memory_callback(void *,const char *file,const char *where)
+    {
+        fprintf (stderr,"%s: Out of memory in %s\n", file?file:"unknown file", where);
+    }
+
+    void default_data_callback(void*,const char *file, const int offset)
+    {
+        if(offset < 0)
+            fprintf (stderr,"%s: Unexpected end of file\n", file?file:"unknown file");
+        else
+            fprintf (stderr,"%s: data corrupted at %d\n",file?file:"unknown file",offset); 
+    }
+    const char *libraw_strerror(int e)
+    {
+        enum LibRaw_errors errorcode = (LibRaw_errors)e;
+        switch(errorcode)
+            {
+            case        LIBRAW_SUCCESS:
+                return "No error";
+            case        LIBRAW_UNSPECIFIED_ERROR:
+                return "Unspecified error";
+            case        LIBRAW_FILE_UNSUPPORTED:
+                return "Unsupported file format or not RAW file";
+            case        LIBRAW_REQUEST_FOR_NONEXISTENT_IMAGE:
+                return "Request for nonexisting image number";
+            case        LIBRAW_OUT_OF_ORDER_CALL:
+                return "Out of order call of libraw function";
+            case    LIBRAW_NO_THUMBNAIL:
+                return "No thumbnail in file";
+            case    LIBRAW_UNSUPPORTED_THUMBNAIL:
+                return "Unsupported thumbnail format";
+            case LIBRAW_CANNOT_ADDMASK:
+                return "Cannot add masked pixels to resized image";
+            case    LIBRAW_UNSUFFICIENT_MEMORY:
+                return "Unsufficient memory";
+            case    LIBRAW_DATA_ERROR:
+                return "Corrupted data or unexpected EOF";
+            case    LIBRAW_IO_ERROR:
+                return "Input/output error";
+            case LIBRAW_CANCELLED_BY_CALLBACK:
+                return "Cancelled by user callback";
+            default:
+                return "Unknown error code";
+        }
+    }
+
+#ifdef __cplusplus
+}
+#endif
+
+
+const double LibRaw_constants::xyz_rgb[3][3] = 
+{
+    { 0.412453, 0.357580, 0.180423 },
+    { 0.212671, 0.715160, 0.072169 },
+    { 0.019334, 0.119193, 0.950227 } 
+};
+
+const float LibRaw_constants::d65_white[3] =  { 0.950456, 1, 1.088754 };
+
+#define P1 imgdata.idata
+#define S imgdata.sizes
+#define O imgdata.params
+#define C imgdata.color
+#define M imgdata.masked_pixels
+#define T imgdata.thumbnail
+#define IO libraw_internal_data.internal_output_params
+#define ID libraw_internal_data.internal_data
+
+#define EXCEPTION_HANDLER(e) do{                        \
+        fprintf(stderr,"Exception %d caught\n",e);      \
+        switch(e)                                       \
+            {                                           \
+            case LIBRAW_EXCEPTION_ALLOC:                \
+                recycle();                              \
+                return LIBRAW_UNSUFFICIENT_MEMORY;      \
+            case LIBRAW_EXCEPTION_DECODE_RAW:           \
+            case LIBRAW_EXCEPTION_DECODE_JPEG:          \
+                recycle();                              \
+                return LIBRAW_DATA_ERROR;               \
+            case LIBRAW_EXCEPTION_IO_EOF:               \
+            case LIBRAW_EXCEPTION_IO_CORRUPT:           \
+                recycle();                              \
+                return LIBRAW_IO_ERROR;                 \
+            case LIBRAW_EXCEPTION_CANCELLED_BY_CALLBACK:\
+                recycle();                              \
+                return LIBRAW_CANCELLED_BY_CALLBACK;    \
+            default:                                    \
+                return LIBRAW_UNSPECIFIED_ERROR;        \
+            } \
+    }while(0)
+
+const char* LibRaw::version() { return LIBRAW_VERSION_STR;}
+int LibRaw::versionNumber() { return LIBRAW_VERSION; }
+const char* LibRaw::strerror(int p) { return libraw_strerror(p);}
+
+
+void LibRaw::derror()
+{
+    if (!libraw_internal_data.unpacker_data.data_error && libraw_internal_data.internal_data.input) 
+        {
+            if (libraw_internal_data.internal_data.input->eof())
+                {
+                    if(callbacks.data_cb)(*callbacks.data_cb)(callbacks.datacb_data,
+                                                              libraw_internal_data.internal_data.input->fname(),-1);
+                    throw LIBRAW_EXCEPTION_IO_EOF;
+                }
+            else
+                {
+                    if(callbacks.data_cb)(*callbacks.data_cb)(callbacks.datacb_data,
+                                                              libraw_internal_data.internal_data.input->fname(),
+                                                              libraw_internal_data.internal_data.input->tell());
+                    throw LIBRAW_EXCEPTION_IO_CORRUPT;
+                }
+        }
+    libraw_internal_data.unpacker_data.data_error++;
+}
+
+#define ZERO(a) memset(&a,0,sizeof(a))
+
+
+LibRaw:: LibRaw(unsigned int flags)
+{
+    double aber[4] = {1,1,1,1};
+    double gamm[6] = { 0.45,4.5,0,0,0,0 };
+    unsigned greybox[4] =  { 0, 0, UINT_MAX, UINT_MAX };
+#ifdef DCRAW_VERBOSE
+    verbose = 1;
+#else
+    verbose = 0;
+#endif
+    ZERO(imgdata);
+    ZERO(libraw_internal_data);
+    ZERO(callbacks);
+    callbacks.mem_cb = (flags & LIBRAW_OPIONS_NO_MEMERR_CALLBACK) ? NULL:  &default_memory_callback;
+    callbacks.data_cb = (flags & LIBRAW_OPIONS_NO_DATAERR_CALLBACK)? NULL : &default_data_callback;
+    memmove(&imgdata.params.aber,&aber,sizeof(aber));
+    memmove(&imgdata.params.gamm,&gamm,sizeof(gamm));
+    memmove(&imgdata.params.greybox,&greybox,sizeof(greybox));
+    
+    imgdata.params.bright=1;
+    imgdata.params.use_camera_matrix=-1;
+    imgdata.params.user_flip=-1;
+    imgdata.params.user_black=-1;
+    imgdata.params.user_sat=-1;
+    imgdata.params.user_qual=-1;
+    imgdata.params.output_color=1;
+    imgdata.params.output_bps=8;
+    imgdata.params.use_fuji_rotate=1;
+    imgdata.params.auto_bright_thr = LIBRAW_DEFAULT_AUTO_BRIGHTNESS_THRESHOLD;
+    imgdata.params.adjust_maximum_thr= LIBRAW_DEFAULT_ADJUST_MAXIMUM_THRESHOLD;
+    imgdata.parent_class = this;
+    imgdata.progress_flags = 0;
+    tls = new LibRaw_TLS;
+    tls->init();
+}
+
+
+void* LibRaw:: malloc(size_t t)
+{
+    void *p = memmgr.malloc(t);
+    return p;
+}
+void* LibRaw::       calloc(size_t n,size_t t)
+{
+    void *p = memmgr.calloc(n,t);
+    return p;
+}
+void  LibRaw::      free(void *p)
+{
+    memmgr.free(p);
+}
+
+
+int LibRaw:: fc (int row, int col)
+{
+    static const char filter[16][16] =
+        { { 2,1,1,3,2,3,2,0,3,2,3,0,1,2,1,0 },
+          { 0,3,0,2,0,1,3,1,0,1,1,2,0,3,3,2 },
+          { 2,3,3,2,3,1,1,3,3,1,2,1,2,0,0,3 },
+          { 0,1,0,1,0,2,0,2,2,0,3,0,1,3,2,1 },
+          { 3,1,1,2,0,1,0,2,1,3,1,3,0,1,3,0 },
+          { 2,0,0,3,3,2,3,1,2,0,2,0,3,2,2,1 },
+          { 2,3,3,1,2,1,2,1,2,1,1,2,3,0,0,1 },
+          { 1,0,0,2,3,0,0,3,0,3,0,3,2,1,2,3 },
+          { 2,3,3,1,1,2,1,0,3,2,3,0,2,3,1,3 },
+          { 1,0,2,0,3,0,3,2,0,1,1,2,0,1,0,2 },
+          { 0,1,1,3,3,2,2,1,1,3,3,0,2,1,3,2 },
+          { 2,3,2,0,0,1,3,0,2,0,1,2,3,0,1,0 },
+          { 1,3,1,2,3,2,3,2,0,2,0,1,1,0,3,0 },
+          { 0,2,0,3,1,0,0,1,1,3,3,2,3,2,2,1 },
+          { 2,1,3,2,3,1,2,1,0,3,0,2,0,2,0,2 },
+          { 0,3,1,0,0,2,0,3,2,1,3,1,1,3,1,3 } };
+    
+    if (imgdata.idata.filters != 1) return FC(row,col);
+    return filter[(row+imgdata.sizes.top_margin) & 15][(col+imgdata.sizes.left_margin) & 15];
+}
+
+void LibRaw:: recycle() 
+{
+    if(libraw_internal_data.internal_data.input && libraw_internal_data.internal_data.input_internal) 
+        { 
+            delete libraw_internal_data.internal_data.input; 
+            libraw_internal_data.internal_data.input = NULL;
+        }
+    libraw_internal_data.internal_data.input_internal = 0;
+#define FREE(a) do { if(a) { free(a); a = NULL;} }while(0)
+            
+    FREE(imgdata.image); 
+    FREE(imgdata.thumbnail.thumb);
+    FREE(libraw_internal_data.internal_data.meta_data);
+    FREE(libraw_internal_data.output_data.histogram);
+    FREE(libraw_internal_data.output_data.oprof);
+    FREE(imgdata.color.profile);
+    FREE(imgdata.masked_pixels.buffer);
+    FREE(imgdata.masked_pixels.ph1_black);
+#undef FREE
+    ZERO(imgdata.masked_pixels);
+    ZERO(imgdata.sizes);
+    ZERO(imgdata.color);
+    ZERO(libraw_internal_data.internal_output_params);
+    memmgr.cleanup();
+    imgdata.thumbnail.tformat = LIBRAW_THUMBNAIL_UNKNOWN;
+    imgdata.progress_flags = 0;
+    
+    tls->init();
+}
+
+const char * LibRaw::unpack_function_name()
+{
+    if(!load_raw) return "Function not set";
+
+    // sorted names order
+    if (load_raw == &LibRaw::adobe_dng_load_raw_lj)     return "adobe_dng_load_raw_lj()"; //+
+    if (load_raw == &LibRaw::adobe_dng_load_raw_nc)     return "adobe_dng_load_raw_nc()"; //+
+    if (load_raw == &LibRaw::canon_600_load_raw)        return "canon_600_load_raw()";    //+
+
+    if (load_raw == &LibRaw::canon_compressed_load_raw) return "canon_compressed_load_raw()"; //+
+    if (load_raw == &LibRaw::canon_sraw_load_raw)       return "canon_sraw_load_raw()"; //+
+
+    if (load_raw == &LibRaw::eight_bit_load_raw )       return "eight_bit_load_raw()"; //+
+    if (load_raw == &LibRaw::fuji_load_raw )            return "fuji_load_raw()"; //+
+    // 10
+    if (load_raw == &LibRaw::hasselblad_load_raw )      return "hasselblad_load_raw()"; //+
+    if (load_raw == &LibRaw::imacon_full_load_raw )     return "imacon_full_load_raw()"; //+ (untested)
+    if (load_raw == &LibRaw::kodak_262_load_raw )       return "kodak_262_load_raw()"; //+
+
+    if (load_raw == &LibRaw::kodak_65000_load_raw )     return "kodak_65000_load_raw()";//+
+    if (load_raw == &LibRaw::kodak_dc120_load_raw )     return "kodak_dc120_load_raw()"; //+
+    if (load_raw == &LibRaw::kodak_jpeg_load_raw )      return "kodak_jpeg_load_raw()"; //+ (untested)
+
+    if (load_raw == &LibRaw::kodak_radc_load_raw )      return "kodak_radc_load_raw()"; //+
+    if (load_raw == &LibRaw::kodak_rgb_load_raw )       return "kodak_rgb_load_raw()"; //+ (untested)
+    if (load_raw == &LibRaw::kodak_yrgb_load_raw )      return "kodak_yrgb_load_raw()"; //+
+    if (load_raw == &LibRaw::kodak_ycbcr_load_raw )     return "kodak_ycbcr_load_raw()"; //+ (untested)
+    // 20
+    if (load_raw == &LibRaw::leaf_hdr_load_raw )        return "leaf_hdr_load_raw()"; //+
+    if (load_raw == &LibRaw::lossless_jpeg_load_raw)    return "lossless_jpeg_load_raw()"; //+
+    if (load_raw == &LibRaw::minolta_rd175_load_raw )   return "minolta_rd175_load_raw()"; //+
+
+    if (load_raw == &LibRaw::nikon_compressed_load_raw) return "nikon_compressed_load_raw()";//+
+    if (load_raw == &LibRaw::nokia_load_raw )           return "nokia_load_raw()";//+ (untested)
+
+    if (load_raw == &LibRaw::olympus_load_raw )    return "olympus_load_raw()"; //+
+    if (load_raw == &LibRaw::packed_load_raw )       return "packed_load_raw()"; //+
+    if (load_raw == &LibRaw::panasonic_load_raw )       return "panasonic_load_raw()";//+
+    // 30
+    if (load_raw == &LibRaw::pentax_load_raw )          return "pentax_load_raw()"; //+
+    if (load_raw == &LibRaw::phase_one_load_raw )       return "phase_one_load_raw()"; //+
+    if (load_raw == &LibRaw::phase_one_load_raw_c )     return "phase_one_load_raw_c()"; //+
+
+    if (load_raw == &LibRaw::quicktake_100_load_raw )   return "quicktake_100_load_raw()";//+ (untested)
+    if (load_raw == &LibRaw::rollei_load_raw )          return "rollei_load_raw()"; //+ (untested)
+    if (load_raw == &LibRaw::sinar_4shot_load_raw )     return "sinar_4shot_load_raw()";//+
+
+    if (load_raw == &LibRaw::smal_v6_load_raw )         return "smal_v6_load_raw()";//+ (untested)
+    if (load_raw == &LibRaw::smal_v9_load_raw )         return "smal_v9_load_raw()";//+ (untested)
+    if (load_raw == &LibRaw::sony_load_raw )            return "sony_load_raw()"; //+
+    if (load_raw == &LibRaw::sony_arw_load_raw )        return "sony_arw_load_raw()";//+
+    // 40
+    if (load_raw == &LibRaw::sony_arw2_load_raw )       return "sony_arw2_load_raw()";//+
+    if (load_raw == &LibRaw::unpacked_load_raw )        return "unpacked_load_raw()"; //+
+    // 42 total
+        
+    return "Unknown unpack function";
+}
+
+int LibRaw::adjust_maximum()
+{
+    int i;
+    ushort real_max;
+    float  auto_threshold;
+
+    if(O.adjust_maximum_thr < 0.00001)
+        return LIBRAW_SUCCESS;
+    else if (O.adjust_maximum_thr > 0.99999)
+        auto_threshold = LIBRAW_DEFAULT_ADJUST_MAXIMUM_THRESHOLD;
+    else
+        auto_threshold = O.adjust_maximum_thr;
+        
+    
+    real_max = C.channel_maximum[0];
+    for(i = 1; i< 4; i++)
+        if(real_max < C.channel_maximum[i])
+            real_max = C.channel_maximum[i];
+
+    if (real_max > 0 && real_max < C.maximum && real_max > C.maximum* auto_threshold)
+        {
+            C.maximum = real_max;
+        }
+    return LIBRAW_SUCCESS;
+}
+
+
+void LibRaw:: merror (void *ptr, const char *where)
+{
+    if (ptr) return;
+    if(callbacks.mem_cb)(*callbacks.mem_cb)(callbacks.memcb_data,
+                                            libraw_internal_data.internal_data.input
+                                            ?libraw_internal_data.internal_data.input->fname()
+                                            :NULL,
+                                            where);
+    throw LIBRAW_EXCEPTION_ALLOC;
+}
+
+ushort * LibRaw::get_masked_pointer(int row, int col) 
+{ 
+    if(row<0 || col < 0) return NULL;
+    if(!M.buffer) return NULL; 
+    if(row < S.top_margin)
+        {
+            // top band
+            if(col < S.left_margin)
+                {
+                    return &(M.tl[row*S.left_margin+col]);
+                }
+            else if (col < S.left_margin + S.width)
+                {
+                    int icol = col - S.left_margin;
+                    return &(M.top[row*S.width+icol]);
+                }
+            else if (col < S.raw_width)
+                {
+                    int icol = col - S.left_margin - S.width;
+                    return &(M.tr[row*S.right_margin+icol]);
+                }
+            else
+                return NULL; // out of bounds
+        }
+    else if (row < S.top_margin + S.height)
+        {
+            //normal image height
+            int irow = row - S.top_margin;
+            if(col < S.left_margin)
+                {
+                    return &M.left[irow*S.left_margin + col];
+                }
+            else if (col < S.left_margin + S.width)
+                {
+                    // central image
+                    return NULL;
+                }
+            else if (col < S.raw_width)
+                {
+                    int icol = col - S.left_margin - S.width;
+                    return &M.right[irow*S.right_margin+icol];
+                }
+            else
+                return NULL; // out of bounds
+        }
+    else if (row < S.raw_height)
+        {
+            int irow = row - S.top_margin - S.height;
+            // bottom band
+            if(col < S.left_margin)
+                {
+                    return &M.bl[irow*S.left_margin+col];
+                }
+            else if (col < S.left_margin + S.width)
+                {
+                    int icol = col - S.left_margin;
+                    return &M.bottom[irow*S.width + icol];
+                }
+            else if (col < S.raw_width)
+                {
+                    int icol = col - S.left_margin - S.width;
+                    return &M.br[irow*S.right_margin + icol];
+                }
+            else
+                return NULL; // out of bounds
+        }
+    else
+        {
+            // out of bounds
+            return NULL;
+        }
+    // fallback
+    return NULL;
+}
+
+void LibRaw:: init_masked_ptrs()
+{
+    if(!M.buffer) return;
+    
+    // top band
+    M.tl = M.buffer;
+    M.top = M.tl +(S.top_margin*S.left_margin);
+    M.tr =  M.top + (S.top_margin*S.width);
+    
+    // left-right
+    M.left = M.tr + (S.top_margin * S.right_margin);
+    M.right = M.left + (S.left_margin * S.height);
+
+    // bottom band
+    M.bl = M.right + (S.right_margin * S.height);
+    M.bottom = M.bl + (S.left_margin * S.bottom_margin);
+    M.br = M.bottom + (S.width * S.bottom_margin);
+
+}
+int LibRaw::add_masked_borders_to_bitmap()
+{
+    CHECK_ORDER_HIGH(LIBRAW_PROGRESS_PRE_INTERPOLATE);
+    CHECK_ORDER_LOW(LIBRAW_PROGRESS_LOAD_RAW);
+
+    if(S.width != S.iwidth || S.height!=S.iheight)
+        return LIBRAW_CANNOT_ADDMASK;
+
+    if(!P1.filters)
+        return LIBRAW_CANNOT_ADDMASK;
+        
+    if(!imgdata.image)
+        return LIBRAW_OUT_OF_ORDER_CALL;
+
+    if(S.raw_width < S.width || S.raw_height < S.height)
+        return LIBRAW_SUCCESS; // nothing to do or already called
+
+    if(S.width == S.raw_width && S.height == S.raw_height)
+        return LIBRAW_SUCCESS; // nothing to do or already called
+
+    ushort (*newimage)[4];
+
+    newimage = (ushort (*)[4]) calloc (S.raw_height*S.raw_width, sizeof (*newimage));
+    merror (newimage, "add_masked_borders_to_bitmap()");
+
+    int r,c;
+    // top rows
+    for (r=0; r<S.top_margin;r++)
+        for(c=0;c<S.raw_width;c++)
+            {
+                ushort *p = get_masked_pointer(r,c);
+                if(p)
+                    newimage[r*S.raw_width+c][COLOR(r,c)] = *p;
+            }
+    // middle rows
+    for (r=S.top_margin; r<S.top_margin+S.height;r++)
+        {
+            int row = r-S.top_margin;
+            for(c=0;c<S.left_margin;c++)
+                {
+                    ushort *p = get_masked_pointer(r,c);
+                    if(p)
+                        newimage[r*S.raw_width+c][COLOR(r,c)] =  *p;
+                }
+            for(c=S.left_margin; c<S.left_margin+S.iwidth;c++)
+                {
+                    int col = c - S.left_margin;
+                    newimage[r*S.raw_width+c][COLOR(r,c)] = imgdata.image[row*S.iwidth+col][COLOR(r,c)];
+//                    for(int cc=0;cc<4;cc++)
+//                        newimage[r*S.raw_width+c][cc] = imgdata.image[row*S.iwidth+col][cc];
+                }
+            for(c=S.left_margin+S.iwidth;c<S.raw_width;c++)
+                {
+                    ushort *p = get_masked_pointer(r,c);
+                    if(p)
+                        newimage[r*S.raw_width+c][COLOR(r,c)] =  *p;
+                }
+        }
+    // bottom rows
+    for (r=S.top_margin+S.height; r<S.raw_height;r++)
+        for(c=0;c<S.raw_width;c++)
+            {
+                ushort *p = get_masked_pointer(r,c);
+                if(p)
+                    newimage[r*S.raw_width+c][COLOR(r,c)] = *p;
+            }
+    free(imgdata.image);
+    imgdata.image=newimage;
+    S.iwidth = S.width = S.raw_width;
+    S.iheight = S.height = S.raw_height;
+    return LIBRAW_SUCCESS;
+}
+
+int LibRaw::open_file(const char *fname)
+{
+    // this stream will close on recycle()
+    LibRaw_file_datastream *stream = new LibRaw_file_datastream(fname);
+    if(!stream->valid())
+        {
+            delete stream;
+            return LIBRAW_IO_ERROR;
+        }
+    ID.input_internal = 0; // preserve from deletion on error
+    int ret = open_datastream(stream);
+    if (ret == LIBRAW_SUCCESS)
+        {
+            ID.input_internal =1 ; // flag to delete datastream on recycle
+        }
+    else
+        {
+            delete stream;
+            ID.input_internal = 0;
+        }
+    return ret;
+}
+
+int LibRaw::open_buffer(void *buffer, size_t size)
+{
+    // this stream will close on recycle()
+    if(!buffer  || buffer==(void*)-1)
+        return LIBRAW_IO_ERROR;
+
+    LibRaw_buffer_datastream *stream = new LibRaw_buffer_datastream(buffer,size);
+    if(!stream->valid())
+        {
+            delete stream;
+            return LIBRAW_IO_ERROR;
+        }
+    ID.input_internal = 0; // preserve from deletion on error
+    int ret = open_datastream(stream);
+    if (ret == LIBRAW_SUCCESS)
+        {
+            ID.input_internal =1 ; // flag to delete datastream on recycle
+        }
+    else
+        {
+            delete stream;
+            ID.input_internal = 0;
+        }
+    return ret;
+}
+
+
+int LibRaw::open_datastream(LibRaw_abstract_datastream *stream)
+{
+
+    if(!stream)
+        return ENOENT;
+    if(!stream->valid())
+        return LIBRAW_IO_ERROR;
+    recycle();
+
+    try {
+        ID.input = stream;
+        SET_PROC_FLAG(LIBRAW_PROGRESS_OPEN);
+
+        if (O.use_camera_matrix < 0)
+            O.use_camera_matrix = O.use_camera_wb;
+
+        identify();
+
+        if(IO.fuji_width)
+            {
+                IO.fwidth = S.width;
+                IO.fheight = S.height;
+                S.iwidth = S.width = IO.fuji_width << !libraw_internal_data.unpacker_data.fuji_layout;
+                S.iheight = S.height = S.raw_height;
+                S.raw_height += 2*S.top_margin;
+            }
+
+        int saved_raw_width = S.raw_width;
+        int saved_width = S.width;
+        // from packed_12_load_raw
+        if ((load_raw == &LibRaw:: packed_load_raw) && (S.raw_width * 8U >= S.width * libraw_internal_data.unpacker_data.tiff_bps))
+            {	
+                // raw_width is in bytes!
+                S.raw_width = S.raw_width * 8 / libraw_internal_data.unpacker_data.tiff_bps;	
+            }
+        else if (S.pixel_aspect < 0.95 || S.pixel_aspect > 1.05)
+            {
+                S.width*=S.pixel_aspect;
+            }
+
+        if(S.raw_width>S.width + S.left_margin)
+            S.right_margin = S.raw_width - S.width - S.left_margin;
+
+        if(S.raw_height > S.height + S.top_margin)
+            S.bottom_margin = S.raw_height - S.height - S.top_margin;
+
+        S.raw_width = saved_raw_width;
+        S.width = saved_width;
+
+        if(C.profile_length)
+            {
+                if(C.profile) free(C.profile);
+                C.profile = malloc(C.profile_length);
+                merror(C.profile,"LibRaw::open_file()");
+                ID.input->seek(ID.profile_offset,SEEK_SET);
+                ID.input->read(C.profile,C.profile_length,1);
+            }
+        
+        SET_PROC_FLAG(LIBRAW_PROGRESS_IDENTIFY);
+    }
+    catch ( LibRaw_exceptions err) {
+        EXCEPTION_HANDLER(err);
+    }
+
+    if(P1.raw_count < 1) 
+        return LIBRAW_FILE_UNSUPPORTED;
+
+    if (O.user_flip >= 0)
+        S.flip = O.user_flip;
+    
+    switch ((S.flip+3600) % 360) 
+        {
+        case 270:  S.flip = 5;  break;
+        case 180:  S.flip = 3;  break;
+        case  90:  S.flip = 6;  break;
+        }
+    
+    write_fun = &LibRaw::write_ppm_tiff;
+    
+    if (load_raw == &LibRaw::kodak_ycbcr_load_raw) 
+        {
+            S.height += S.height & 1;
+            S.width  += S.width  & 1;
+        }
+
+    IO.shrink = P1.filters && (O.half_size || O.threshold || O.aber[0] != 1 || O.aber[2] != 1);
+    S.iheight = (S.height + IO.shrink) >> IO.shrink;
+    S.iwidth  = (S.width  + IO.shrink) >> IO.shrink;
+    
+    SET_PROC_FLAG(LIBRAW_PROGRESS_SIZE_ADJUST);
+
+
+    return LIBRAW_SUCCESS;
+}
+
+int LibRaw::unpack(void)
+{
+    CHECK_ORDER_HIGH(LIBRAW_PROGRESS_LOAD_RAW);
+    CHECK_ORDER_LOW(LIBRAW_PROGRESS_IDENTIFY);
+    try {
+
+        RUN_CALLBACK(LIBRAW_PROGRESS_LOAD_RAW,0,2);
+        if (O.shot_select >= P1.raw_count)
+            return LIBRAW_REQUEST_FOR_NONEXISTENT_IMAGE;
+        
+        if(!load_raw)
+            return LIBRAW_UNSPECIFIED_ERROR;
+        
+        if (O.use_camera_matrix && C.cmatrix[0][0] > 0.25) 
+            {
+                memcpy (C.rgb_cam, C.cmatrix, sizeof (C.cmatrix));
+                IO.raw_color = 0;
+            }
+        // already allocated ?
+        if(imgdata.image) free(imgdata.image);
+        
+        imgdata.image = (ushort (*)[4]) calloc (S.iheight*S.iwidth, sizeof (*imgdata.image));
+        merror (imgdata.image, "unpack()");
+
+
+        if(S.top_margin || S.left_margin || S.right_margin || S.bottom_margin)
+            {
+                unsigned sz = S.raw_height*(S.left_margin+S.right_margin) 
+                    + S.width*(S.top_margin+S.bottom_margin);
+                imgdata.masked_pixels.buffer = (ushort*) calloc(sz, sizeof(ushort)); 
+                merror (imgdata.masked_pixels.buffer, "unpack()");
+                init_masked_ptrs();
+            }
+        if (libraw_internal_data.unpacker_data.meta_length) 
+            {
+                libraw_internal_data.internal_data.meta_data = 
+                    (char *) malloc (libraw_internal_data.unpacker_data.meta_length);
+                merror (libraw_internal_data.internal_data.meta_data, "LibRaw::unpack()");
+            }
+        ID.input->seek(libraw_internal_data.unpacker_data.data_offset, SEEK_SET);
+        int save_document_mode = O.document_mode;
+        O.document_mode = 0;
+
+        if(!own_filtering_supported() && (O.filtering_mode & LIBRAW_FILTERING_AUTOMATIC_BIT))
+            O.filtering_mode = LIBRAW_FILTERING_AUTOMATIC_BIT; // turn on black and zeroes filtering
+        
+        (this->*load_raw)();
+        
+        O.document_mode = save_document_mode;
+
+        if (O.filtering_mode & LIBRAW_FILTERING_AUTOMATIC_BIT)
+            O.filtering_mode = LIBRAW_FILTERING_AUTOMATIC; // restore automated mode
+        
+        SET_PROC_FLAG(LIBRAW_PROGRESS_LOAD_RAW);
+        RUN_CALLBACK(LIBRAW_PROGRESS_LOAD_RAW,1,2);
+        
+        return 0;
+    }
+    catch ( LibRaw_exceptions err) {
+        EXCEPTION_HANDLER(err);
+    }
+}
+
+int LibRaw::dcraw_document_mode_processing(void)
+{
+    CHECK_ORDER_HIGH(LIBRAW_PROGRESS_PRE_INTERPOLATE);
+    CHECK_ORDER_LOW(LIBRAW_PROGRESS_LOAD_RAW);
+
+    try {
+
+        if(IO.fwidth) 
+            rotate_fuji_raw();
+
+        if(!own_filtering_supported() && (O.filtering_mode & LIBRAW_FILTERING_AUTOMATIC_BIT))
+            O.filtering_mode = LIBRAW_FILTERING_AUTOMATIC_BIT; // turn on black and zeroes filtering
+
+        O.document_mode = 2;
+
+        O.use_fuji_rotate = 0;
+        if (!(O.filtering_mode & LIBRAW_FILTERING_NOZEROES) && IO.zero_is_bad)
+            {
+                remove_zeroes();
+                SET_PROC_FLAG(LIBRAW_PROGRESS_REMOVE_ZEROES);
+            }
+        if(O.bad_pixels) 
+            {
+                bad_pixels(O.bad_pixels);
+                SET_PROC_FLAG(LIBRAW_PROGRESS_BAD_PIXELS);
+            }
+        if (O.dark_frame)
+            {
+                subtract (O.dark_frame);
+                SET_PROC_FLAG(LIBRAW_PROGRESS_DARK_FRAME);
+            }
+        if(O.filtering_mode & LIBRAW_FILTERING_NOBLACKS)
+            C.black=0;
+
+        if (O.user_black >= 0) 
+            C.black = O.user_black;
+
+        if (O.user_sat > 0) 
+            C.maximum = O.user_sat;
+
+        pre_interpolate();
+        SET_PROC_FLAG(LIBRAW_PROGRESS_PRE_INTERPOLATE);
+
+        if (libraw_internal_data.internal_output_params.mix_green)
+            {
+                int i;
+                for (P1.colors=3, i=0; i < S.height*S.width; i++)
+                    imgdata.image[i][1] = (imgdata.image[i][1] + imgdata.image[i][3]) >> 1;
+            }
+        SET_PROC_FLAG(LIBRAW_PROGRESS_MIX_GREEN);
+
+        if ( P1.colors == 3) 
+            median_filter();
+        SET_PROC_FLAG(LIBRAW_PROGRESS_MEDIAN_FILTER);
+
+        if ( O.highlight == 2) 
+            blend_highlights();
+
+        if ( O.highlight > 2) 
+            recover_highlights();
+        SET_PROC_FLAG(LIBRAW_PROGRESS_HIGHLIGHTS);
+
+        if (O.use_fuji_rotate) 
+            fuji_rotate();
+        SET_PROC_FLAG(LIBRAW_PROGRESS_FUJI_ROTATE);
+#ifndef NO_LCMS
+	if(O.camera_profile)
+            {
+                apply_profile(O.camera_profile,O.output_profile);
+                SET_PROC_FLAG(LIBRAW_PROGRESS_APPLY_PROFILE);
+            }
+#endif
+        if(!libraw_internal_data.output_data.histogram)
+            {
+                libraw_internal_data.output_data.histogram = (int (*)[LIBRAW_HISTOGRAM_SIZE]) malloc(sizeof(*libraw_internal_data.output_data.histogram)*4);
+                merror(libraw_internal_data.output_data.histogram,"LibRaw::dcraw_document_mode_processing()");
+            }
+        convert_to_rgb();
+        SET_PROC_FLAG(LIBRAW_PROGRESS_CONVERT_RGB);
+
+        if (O.use_fuji_rotate)
+            stretch();
+        SET_PROC_FLAG(LIBRAW_PROGRESS_STRETCH);
+
+        if (O.filtering_mode & LIBRAW_FILTERING_AUTOMATIC_BIT)
+            O.filtering_mode = LIBRAW_FILTERING_AUTOMATIC; // restore automated mode
+
+        return 0;
+    }
+    catch ( LibRaw_exceptions err) {
+        EXCEPTION_HANDLER(err);
+    }
+
+}
+
+#if 1
+#define FORC(cnt) for (c=0; c < cnt; c++)
+#define FORCC FORC(ret->colors)
+#define SWAP(a,b) { a ^= b; a ^= (b ^= a); }
+
+libraw_processed_image_t * LibRaw::dcraw_make_mem_thumb(int *errcode)
+{
+    if(!T.thumb)
+        {
+            if ( !ID.toffset) 
+                {
+                    if(errcode) *errcode= LIBRAW_NO_THUMBNAIL;
+                }
+            else
+                {
+                    if(errcode) *errcode= LIBRAW_OUT_OF_ORDER_CALL;
+                }
+            return NULL;
+        }
+
+    if (T.tformat == LIBRAW_THUMBNAIL_BITMAP)
+        {
+            libraw_processed_image_t * ret = 
+                (libraw_processed_image_t *)::malloc(sizeof(libraw_processed_image_t)+T.tlength);
+
+            if(!ret)
+                {
+                    if(errcode) *errcode= ENOMEM;
+                    return NULL;
+                }
+
+            memset(ret,0,sizeof(libraw_processed_image_t));
+            ret->type   = LIBRAW_IMAGE_BITMAP;
+            ret->height = T.theight;
+            ret->width  = T.twidth;
+            ret->colors = 3; 
+            ret->bits   = 8;
+            ret->data_size = T.tlength;
+            memmove(ret->data,T.thumb,T.tlength);
+            if(errcode) *errcode= 0;
+            return ret;
+        }
+    else if (T.tformat == LIBRAW_THUMBNAIL_JPEG)
+        {
+            ushort exif[5];
+            int mk_exif = 0;
+            if(strcmp(T.thumb+6,"Exif")) mk_exif = 1;
+            
+            int dsize = T.tlength + mk_exif * (sizeof(exif)+sizeof(tiff_hdr));
+
+            libraw_processed_image_t * ret = 
+                (libraw_processed_image_t *)::malloc(sizeof(libraw_processed_image_t)+dsize);
+
+            if(!ret)
+                {
+                    if(errcode) *errcode= ENOMEM;
+                    return NULL;
+                }
+
+            memset(ret,0,sizeof(libraw_processed_image_t));
+
+            ret->type = LIBRAW_IMAGE_JPEG;
+            ret->data_size = dsize;
+            
+            ret->data[0] = 0xff;
+            ret->data[1] = 0xd8;
+            if(mk_exif)
+                {
+                    struct tiff_hdr th;
+                    memcpy (exif, "\xff\xe1  Exif\0\0", 10);
+                    exif[1] = htons (8 + sizeof th);
+                    memmove(ret->data+2,exif,sizeof(exif));
+                    tiff_head (&th, 0);
+                    memmove(ret->data+(2+sizeof(exif)),&th,sizeof(th));
+                    memmove(ret->data+(2+sizeof(exif)+sizeof(th)),T.thumb+2,T.tlength-2);
+                }
+            else
+                {
+                    memmove(ret->data+2,T.thumb+2,T.tlength-2);
+                }
+            if(errcode) *errcode= 0;
+            return ret;
+            
+        }
+    else
+        {
+            if(errcode) *errcode= LIBRAW_UNSUPPORTED_THUMBNAIL;
+            return NULL;
+
+        }
+}
+
+
+
+libraw_processed_image_t *LibRaw::dcraw_make_mem_image(int *errcode)
+{
+    if((imgdata.progress_flags & LIBRAW_PROGRESS_THUMB_MASK) < LIBRAW_PROGRESS_PRE_INTERPOLATE)
+            {
+                if(errcode) *errcode= LIBRAW_OUT_OF_ORDER_CALL;
+                return NULL;
+            }
+
+    if(libraw_internal_data.output_data.histogram)
+        {
+            int perc, val, total, t_white=0x2000,c;
+
+            perc = S.width * S.height * 0.01;		/* 99th percentile white level */
+            if (IO.fuji_width) perc /= 2;
+            if (!((O.highlight & ~2) || O.no_auto_bright))
+                for (t_white=c=0; c < P1.colors; c++) {
+                    for (val=0x2000, total=0; --val > 32; )
+                        if ((total += libraw_internal_data.output_data.histogram[c][val]) > perc) break;
+                    if (t_white < val) t_white = val;
+                }
+            gamma_curve (O.gamm[0], O.gamm[1], 2, (t_white << 3)/O.bright);
+        }
+
+    unsigned ds = S.height * S.width * (O.output_bps/8) * P1.colors;
+    libraw_processed_image_t *ret = (libraw_processed_image_t*)::malloc(sizeof(libraw_processed_image_t)+ds);
+    if(!ret)
+        {
+                if(errcode) *errcode= ENOMEM;
+                return NULL;
+        }
+    memset(ret,0,sizeof(libraw_processed_image_t));
+    // metadata init
+
+    int s_iheight = S.iheight;
+    int s_iwidth = S.iwidth;
+    int s_width = S.width;
+    int s_hwight = S.height;
+
+    S.iheight = S.height;
+    S.iwidth  = S.width;
+
+
+    if (S.flip & 4) SWAP(S.height,S.width);
+
+
+    ret->type   = LIBRAW_IMAGE_BITMAP;
+    ret->height = S.height;
+    ret->width  = S.width;
+    ret->colors = P1.colors;
+    ret->bits   = O.output_bps;
+
+    ret->data_size = ds;
+
+    // Cut'n'paste from write_tiff_ppm, should be generalized later
+    uchar *bufp = ret->data;
+    uchar *ppm;
+    ushort *ppm2;
+    int c, row, col, soff, rstep, cstep;
+
+
+    soff  = flip_index (0, 0);
+    cstep = flip_index (0, 1) - soff;
+    rstep = flip_index (1, 0) - flip_index (0, S.width);
+
+
+    for (row=0; row < ret->height; row++, soff += rstep) 
+        {
+            ppm2 = (ushort*) (ppm = bufp);
+            for (col=0; col < ret->width; col++, soff += cstep)
+                if (ret->bits == 8)
+                    FORCC ppm [col*ret->colors+c] = imgdata.color.curve[imgdata.image[soff][c]]>>8;
+                else
+                    FORCC ppm2[col*ret->colors+c] =     imgdata.color.curve[imgdata.image[soff][c]];
+            bufp+=ret->colors*(ret->bits/8)*ret->width;
+        }
+    if(errcode) *errcode= 0;
+
+    S.iheight = s_iheight;
+    S.iwidth = s_iwidth;
+    S.width = s_width;
+    S.height = s_hwight;
+
+    return ret;
+}
+
+#undef FORC
+#undef FORCC
+#undef SWAP
+#endif
+
+
+int LibRaw::dcraw_ppm_tiff_writer(const char *filename)
+{
+    CHECK_ORDER_LOW(LIBRAW_PROGRESS_LOAD_RAW);
+
+    if(!imgdata.image) 
+        return LIBRAW_OUT_OF_ORDER_CALL;
+
+    if(!filename) 
+        return ENOENT;
+    FILE *f = fopen(filename,"wb");
+
+    if(!f) 
+        return errno;
+        
+    try {
+        if(!libraw_internal_data.output_data.histogram)
+            {
+                libraw_internal_data.output_data.histogram = 
+                    (int (*)[LIBRAW_HISTOGRAM_SIZE]) malloc(sizeof(*libraw_internal_data.output_data.histogram)*4);
+                merror(libraw_internal_data.output_data.histogram,"LibRaw::dcraw_ppm_tiff_writer()");
+            }
+        libraw_internal_data.internal_data.output = f;
+        write_ppm_tiff();
+        SET_PROC_FLAG(LIBRAW_PROGRESS_FLIP);
+        libraw_internal_data.internal_data.output = NULL;
+        fclose(f);
+        return 0;
+    }
+    catch ( LibRaw_exceptions err) {
+        fclose(f);
+        EXCEPTION_HANDLER(err);
+    }
+}
+
+void LibRaw::kodak_thumb_loader()
+{
+    // some kodak cameras
+    ushort s_height = S.height, s_width = S.width,s_iwidth = S.iwidth,s_iheight=S.iheight;
+    int s_colors = P1.colors;
+    unsigned s_filters = P1.filters;
+    ushort (*s_image)[4] = imgdata.image;
+
+    
+    S.height = T.theight;
+    S.width  = T.twidth;
+    P1.filters = 0;
+
+    if (thumb_load_raw == &CLASS kodak_ycbcr_load_raw) 
+        {
+            S.height += S.height & 1;
+            S.width  += S.width  & 1;
+        }
+    
+    imgdata.image = (ushort (*)[4]) calloc (S.iheight*S.iwidth, sizeof (*imgdata.image));
+    merror (imgdata.image, "LibRaw::kodak_thumb_loader()");
+
+    ID.input->seek(ID.toffset, SEEK_SET);
+    // read kodak thumbnail into T.image[]
+    (this->*thumb_load_raw)();
+
+    // copy-n-paste from image pipe
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+#define MAX(a,b) ((a) > (b) ? (a) : (b))
+#define LIM(x,min,max) MAX(min,MIN(x,max))
+#define CLIP(x) LIM(x,0,65535)
+#define SWAP(a,b) { a ^= b; a ^= (b ^= a); }
+
+    // from scale_colors
+    {
+        double   dmax;
+        float scale_mul[4];
+        int c,val;
+        for (dmax=DBL_MAX, c=0; c < 3; c++) 
+                if (dmax > C.pre_mul[c])
+                    dmax = C.pre_mul[c];
+
+        for( c=0; c< 3; c++)
+                scale_mul[c] = (C.pre_mul[c] / dmax) * 65535.0 / C.maximum;
+        scale_mul[3] = scale_mul[1];
+
+        size_t size = S.height * S.width;
+        for (unsigned i=0; i < size*4 ; i++) 
+            {
+                val = imgdata.image[0][i];
+                if(!val) continue;
+                val *= scale_mul[i & 3];
+                imgdata.image[0][i] = CLIP(val);
+            }
+    }
+
+    // from convert_to_rgb
+    ushort *img;
+    int row,col;
+    
+    int  (*t_hist)[LIBRAW_HISTOGRAM_SIZE] =  (int (*)[LIBRAW_HISTOGRAM_SIZE]) calloc(sizeof(*t_hist),4);
+    merror (t_hist, "LibRaw::kodak_thumb_loader()");
+    
+    float out[3], 
+        out_cam[3][4] = 
+        {
+            {2.81761312, -1.98369181, 0.166078627, 0}, 
+            {-0.111855984, 1.73688626, -0.625030339, 0}, 
+            {-0.0379119813, -0.891268849, 1.92918086, 0}
+        };
+
+    for (img=imgdata.image[0], row=0; row < S.height; row++)
+        for (col=0; col < S.width; col++, img+=4)
+            {
+                out[0] = out[1] = out[2] = 0;
+                int c;
+                for(c=0;c<3;c++) 
+                    {
+                        out[0] += out_cam[0][c] * img[c];
+                        out[1] += out_cam[1][c] * img[c];
+                        out[2] += out_cam[2][c] * img[c];
+                    }
+                for(c=0; c<3; c++)
+                    img[c] = CLIP((int) out[c]);
+                for(c=0; c<P1.colors;c++)
+                    t_hist[c][img[c] >> 3]++;
+                    
+            }
+
+    // from gamma_lut
+    int  (*save_hist)[LIBRAW_HISTOGRAM_SIZE] = libraw_internal_data.output_data.histogram;
+    libraw_internal_data.output_data.histogram = t_hist;
+
+    // make curve output curve!
+    ushort (*t_curve) = (ushort*) calloc(sizeof(C.curve),1);
+    merror (t_curve, "LibRaw::kodak_thumb_loader()");
+    memmove(t_curve,C.curve,sizeof(C.curve));
+    memset(C.curve,0,sizeof(C.curve));
+        {
+            int perc, val, total, t_white=0x2000,c;
+
+            perc = S.width * S.height * 0.01;		/* 99th percentile white level */
+            if (IO.fuji_width) perc /= 2;
+            if (!((O.highlight & ~2) || O.no_auto_bright))
+                for (t_white=c=0; c < P1.colors; c++) {
+                    for (val=0x2000, total=0; --val > 32; )
+                        if ((total += libraw_internal_data.output_data.histogram[c][val]) > perc) break;
+                    if (t_white < val) t_white = val;
+                }
+            gamma_curve (O.gamm[0], O.gamm[1], 2, (t_white << 3)/O.bright);
+        }
+    
+    libraw_internal_data.output_data.histogram = save_hist;
+    free(t_hist);
+    
+    // from write_ppm_tiff - copy pixels into bitmap
+    
+    S.iheight = S.height;
+    S.iwidth  = S.width;
+    if (S.flip & 4) SWAP(S.height,S.width);
+
+    if(T.thumb) free(T.thumb);
+    T.thumb = (char*) calloc (S.width * S.height, P1.colors);
+    merror (T.thumb, "LibRaw::kodak_thumb_loader()");
+    T.tlength = S.width * S.height * P1.colors;
+
+    // from write_tiff_ppm
+    {
+        int soff  = flip_index (0, 0);
+        int cstep = flip_index (0, 1) - soff;
+        int rstep = flip_index (1, 0) - flip_index (0, S.width);
+        
+        for (int row=0; row < S.height; row++, soff += rstep) 
+            {
+                char *ppm = T.thumb + row*S.width*P1.colors;
+                for (int col=0; col < S.width; col++, soff += cstep)
+                    for(int c = 0; c < P1.colors; c++)
+                        ppm [col*P1.colors+c] = imgdata.color.curve[imgdata.image[soff][c]]>>8;
+            }
+    }
+
+    memmove(C.curve,t_curve,sizeof(C.curve));
+    free(t_curve);
+
+    // restore variables
+    free(imgdata.image);
+    imgdata.image  = s_image;
+    
+    T.twidth = S.width;
+    S.width = s_width;
+
+    S.iwidth = s_iwidth;
+    S.iheight = s_iheight;
+
+    T.theight = S.height;
+    S.height = s_height;
+
+    T.tcolors = P1.colors;
+    P1.colors = s_colors;
+
+    P1.filters = s_filters;
+}
+#undef MIN
+#undef MAX
+#undef LIM
+#undef CLIP
+#undef SWAP
+
+
+
+
+// ������� thumbnail �� �����, ������ thumb_format � ������������ � ��������
+int LibRaw::unpack_thumb(void)
+{
+    CHECK_ORDER_LOW(LIBRAW_PROGRESS_IDENTIFY);
+    CHECK_ORDER_BIT(LIBRAW_PROGRESS_THUMB_LOAD);
+
+    try {
+        if ( !ID.toffset) 
+            {
+                return LIBRAW_NO_THUMBNAIL;
+            } 
+        else if (thumb_load_raw) 
+            {
+                kodak_thumb_loader();
+                T.tformat = LIBRAW_THUMBNAIL_BITMAP;
+                SET_PROC_FLAG(LIBRAW_PROGRESS_THUMB_LOAD);
+                return 0;
+            } 
+        else 
+            {
+                ID.input->seek(ID.toffset, SEEK_SET);
+                if ( write_thumb == &LibRaw::jpeg_thumb)
+                    {
+                        if(T.thumb) free(T.thumb);
+                        T.thumb = (char *) malloc (T.tlength);
+                        merror (T.thumb, "jpeg_thumb()");
+                        ID.input->read (T.thumb, 1, T.tlength);
+                        T.tcolors = 3;
+                        T.tformat = LIBRAW_THUMBNAIL_JPEG;
+                        SET_PROC_FLAG(LIBRAW_PROGRESS_THUMB_LOAD);
+                        return 0;
+                    }
+                else if (write_thumb == &LibRaw::ppm_thumb)
+                    {
+                        T.tlength = T.twidth * T.theight*3;
+                        if(T.thumb) free(T.thumb);
+
+                        T.thumb = (char *) malloc (T.tlength);
+                        merror (T.thumb, "ppm_thumb()");
+
+                        ID.input->read(T.thumb, 1, T.tlength);
+
+                        T.tformat = LIBRAW_THUMBNAIL_BITMAP;
+                        SET_PROC_FLAG(LIBRAW_PROGRESS_THUMB_LOAD);
+                        return 0;
+
+                    }
+                // else if -- all other write_thumb cases!
+                else
+                    {
+                        return LIBRAW_UNSUPPORTED_THUMBNAIL;
+                    }
+            }
+        // last resort
+        return LIBRAW_UNSUPPORTED_THUMBNAIL;
+    }
+    catch ( LibRaw_exceptions err) {
+        EXCEPTION_HANDLER(err);
+    }
+
+}
+
+int LibRaw::dcraw_thumb_writer(const char *fname)
+{
+//    CHECK_ORDER_LOW(LIBRAW_PROGRESS_THUMB_LOAD);
+
+    if(!fname) 
+        return ENOENT;
+        
+    FILE *tfp = fopen(fname,"wb");
+    
+    if(!tfp) 
+        return errno;
+
+    if(!T.thumb)
+	{
+		fclose(tfp);
+        	return LIBRAW_OUT_OF_ORDER_CALL;
+	}
+
+    try {
+        switch (T.tformat)
+            {
+            case LIBRAW_THUMBNAIL_JPEG:
+                jpeg_thumb_writer (tfp,T.thumb,T.tlength);
+                break;
+            case LIBRAW_THUMBNAIL_BITMAP:
+                fprintf (tfp, "P6\n%d %d\n255\n", T.twidth, T.theight);
+                fwrite (T.thumb, 1, T.tlength, tfp);
+                break;
+            default:
+                fclose(tfp);
+                return LIBRAW_UNSUPPORTED_THUMBNAIL;
+           }
+        fclose(tfp);
+        return 0;
+    }
+    catch ( LibRaw_exceptions err) {
+        fclose(tfp);
+        EXCEPTION_HANDLER(err);
+    }
+}
+
+int LibRaw::adjust_sizes_info_only(void)
+{
+    CHECK_ORDER_LOW(LIBRAW_PROGRESS_IDENTIFY);
+    CHECK_ORDER_HIGH(LIBRAW_PROGRESS_FUJI_ROTATE);
+    if (O.use_fuji_rotate)
+        {
+            if (IO.fuji_width) 
+                {
+                    // restore saved values
+                    if(IO.fheight)
+                        {
+                            S.height = IO.fheight;
+                            S.width = IO.fwidth;
+                            S.iheight = (S.height + IO.shrink) >> IO.shrink;
+                            S.iwidth  = (S.width  + IO.shrink) >> IO.shrink;
+                            S.raw_height -= 2*S.top_margin;
+                            IO.fheight = IO.fwidth = 0; // prevent repeated calls
+                        }
+                    // dcraw code
+                    IO.fuji_width = (IO.fuji_width - 1 + IO.shrink) >> IO.shrink;
+                    S.iwidth = (ushort)(IO.fuji_width / sqrt(0.5));
+                    S.iheight = (ushort)( (S.iheight - IO.fuji_width) / sqrt(0.5));
+                } 
+            else 
+                {
+                    if (S.pixel_aspect < 1) S.iheight = (ushort)( S.iheight / S.pixel_aspect + 0.5);
+                    if (S.pixel_aspect > 1) S.iwidth  = (ushort) (S.iwidth  * S.pixel_aspect + 0.5);
+                }
+        }
+    SET_PROC_FLAG(LIBRAW_PROGRESS_FUJI_ROTATE);
+    if (S.flip & 4)
+        {
+            unsigned short t = S.iheight;
+            S.iheight=S.iwidth;
+            S.iwidth = t;
+            SET_PROC_FLAG(LIBRAW_PROGRESS_FLIP);
+        }
+    return 0;
+}
+
+int LibRaw::rotate_fuji_raw(void)
+{
+    CHECK_ORDER_LOW(LIBRAW_PROGRESS_LOAD_RAW);
+    CHECK_ORDER_HIGH(LIBRAW_PROGRESS_PRE_INTERPOLATE);
+
+
+    if(!IO.fwidth) return LIBRAW_SUCCESS;
+    int row,col,r,c;
+    ushort (*newimage)[4];
+    ushort fiwidth,fiheight;
+
+    fiheight = (IO.fheight + IO.shrink) >> IO.shrink;
+    fiwidth = (IO.fwidth + IO.shrink) >> IO.shrink;
+    
+    newimage = (ushort (*)[4]) calloc (fiheight*fiwidth, sizeof (*newimage));
+    merror(newimage,"rotate_fuji_raw()");
+    for(row=0;row<S.height;row++)
+        {
+            for(col=0;col<S.width;col++)
+                {
+                    if (libraw_internal_data.unpacker_data.fuji_layout) {
+                        r = IO.fuji_width - 1 - col + (row >> 1);
+                        c = col + ((row+1) >> 1);
+                    } else {
+                        r = IO.fuji_width - 1 + row - (col >> 1);
+                        c = row + ((col+1) >> 1);
+                    }
+                    newimage[((r) >> IO.shrink)*fiwidth + ((c) >> IO.shrink)][FCF(row,col)] = 
+                        imgdata.image[((row) >> IO.shrink)*S.iwidth + ((col) >> IO.shrink)][FCF(row,col)];
+                }
+        }
+    // restore fuji sizes!
+    S.height = IO.fheight;
+    S.width = IO.fwidth;
+    S.iheight = (S.height + IO.shrink) >> IO.shrink;
+    S.iwidth  = (S.width  + IO.shrink) >> IO.shrink;
+    S.raw_height -= 2*S.top_margin;
+    IO.fheight = IO.fwidth = 0; // prevent repeated calls
+
+    free(imgdata.image);
+    imgdata.image = newimage;
+    return LIBRAW_SUCCESS;
+    
+}
+
+
+int LibRaw::dcraw_process(void)
+{
+    int quality,i;
+
+
+    CHECK_ORDER_LOW(LIBRAW_PROGRESS_LOAD_RAW);
+    CHECK_ORDER_HIGH(LIBRAW_PROGRESS_PRE_INTERPOLATE);
+
+    try {
+
+        adjust_maximum();
+        if(IO.fwidth) 
+            rotate_fuji_raw();
+
+
+        if(!own_filtering_supported() && (O.filtering_mode & LIBRAW_FILTERING_AUTOMATIC_BIT))
+            O.filtering_mode = LIBRAW_FILTERING_AUTOMATIC_BIT; // turn on black and zeroes filtering
+
+        if(O.half_size) 
+            O.four_color_rgb = 1;
+
+        if (!(O.filtering_mode & LIBRAW_FILTERING_NOZEROES) && IO.zero_is_bad) 
+            {
+                remove_zeroes();
+                SET_PROC_FLAG(LIBRAW_PROGRESS_REMOVE_ZEROES);
+            }
+        if(O.bad_pixels) 
+            {
+                bad_pixels(O.bad_pixels);
+                SET_PROC_FLAG(LIBRAW_PROGRESS_BAD_PIXELS);
+            }
+        if (O.dark_frame)
+            {
+                subtract (O.dark_frame);
+                SET_PROC_FLAG(LIBRAW_PROGRESS_DARK_FRAME);
+            }
+
+        quality = 2 + !IO.fuji_width;
+
+        if(O.filtering_mode & LIBRAW_FILTERING_NOBLACKS)
+            C.black=0;
+
+        if (O.user_qual >= 0) quality = O.user_qual;
+        if (O.user_black >= 0) C.black = O.user_black;
+        if (O.user_sat > 0) C.maximum = O.user_sat;
+
+
+        if ( O.document_mode < 2)
+            {
+                scale_colors();
+                SET_PROC_FLAG(LIBRAW_PROGRESS_SCALE_COLORS);
+            }
+
+        pre_interpolate();
+        SET_PROC_FLAG(LIBRAW_PROGRESS_PRE_INTERPOLATE);
+
+        if (P1.filters && !O.document_mode) 
+            {
+                if (quality == 0)
+                    lin_interpolate();
+                else if (quality == 1 || P1.colors > 3)
+                    vng_interpolate();
+                else if (quality == 2)
+                    ppg_interpolate();
+                else 
+                    ahd_interpolate();
+                SET_PROC_FLAG(LIBRAW_PROGRESS_INTERPOLATE);
+            }
+        if (IO.mix_green)
+            {
+                for (P1.colors=3, i=0; i < S.height * S.width; i++)
+                    imgdata.image[i][1] = (imgdata.image[i][1] + imgdata.image[i][3]) >> 1;
+                SET_PROC_FLAG(LIBRAW_PROGRESS_MIX_GREEN);
+            }
+
+        if (P1.colors == 3) 
+            {
+                median_filter();
+                SET_PROC_FLAG(LIBRAW_PROGRESS_MEDIAN_FILTER);
+            }
+        
+        if (O.highlight == 2) 
+            {
+                blend_highlights();
+                SET_PROC_FLAG(LIBRAW_PROGRESS_HIGHLIGHTS);
+            }
+        
+        if (O.highlight > 2) 
+            {
+                recover_highlights();
+                SET_PROC_FLAG(LIBRAW_PROGRESS_HIGHLIGHTS);
+            }
+        
+        if (O.use_fuji_rotate) 
+            {
+                fuji_rotate();
+                SET_PROC_FLAG(LIBRAW_PROGRESS_FUJI_ROTATE);
+            }
+    
+        if(!libraw_internal_data.output_data.histogram)
+            {
+                libraw_internal_data.output_data.histogram = (int (*)[LIBRAW_HISTOGRAM_SIZE]) malloc(sizeof(*libraw_internal_data.output_data.histogram)*4);
+                merror(libraw_internal_data.output_data.histogram,"LibRaw::dcraw_process()");
+            }
+#ifndef NO_LCMS
+	if(O.camera_profile)
+            {
+                apply_profile(O.camera_profile,O.output_profile);
+                SET_PROC_FLAG(LIBRAW_PROGRESS_APPLY_PROFILE);
+            }
+#endif
+
+        convert_to_rgb();
+        SET_PROC_FLAG(LIBRAW_PROGRESS_CONVERT_RGB);
+
+        if (O.use_fuji_rotate) 
+            {
+                stretch();
+                SET_PROC_FLAG(LIBRAW_PROGRESS_STRETCH);
+            }
+        if (O.filtering_mode & LIBRAW_FILTERING_AUTOMATIC_BIT)
+            O.filtering_mode = LIBRAW_FILTERING_AUTOMATIC; // restore automated mode
+        return 0;
+    }
+    catch ( LibRaw_exceptions err) {
+        EXCEPTION_HANDLER(err);
+    }
+}
+
+// Supported cameras:
+static const char  *static_camera_list[] = 
+{
+"Adobe Digital Negative (DNG)",
+"AgfaPhoto DC-833m",
+"Apple QuickTake 100",
+"Apple QuickTake 150",
+"Apple QuickTake 200",
+"AVT F-080C",
+"AVT F-145C",
+"AVT F-201C",
+"AVT F-510C",
+"AVT F-810C",
+"Canon PowerShot 600",
+"Canon PowerShot A5",
+"Canon PowerShot A5 Zoom",
+"Canon PowerShot A50",
+"Canon PowerShot A460 (CHDK hack)",
+"Canon PowerShot A470 (CHDK hack)",
+"Canon PowerShot A530 (CHDK hack)",
+"Canon PowerShot A570 (CHDK hack)",
+"Canon PowerShot A590 (CHDK hack)",
+"Canon PowerShot A610 (CHDK hack)",
+"Canon PowerShot A620 (CHDK hack)",
+"Canon PowerShot A630 (CHDK hack)",
+"Canon PowerShot A640 (CHDK hack)",
+"Canon PowerShot A650 (CHDK hack)",
+"Canon PowerShot A710 IS (CHDK hack)",
+"Canon PowerShot A720 IS (CHDK hack)",
+"Canon PowerShot Pro70",
+"Canon PowerShot Pro90 IS",
+"Canon PowerShot Pro1",
+"Canon PowerShot G1",
+"Canon PowerShot G2",
+"Canon PowerShot G3",
+"Canon PowerShot G5",
+"Canon PowerShot G6",
+"Canon PowerShot G7 (CHDK hack)",
+"Canon PowerShot G9",
+"Canon PowerShot G10",
+"Canon PowerShot G11",
+"Canon PowerShot S2 IS (CHDK hack)",
+"Canon PowerShot S3 IS (CHDK hack)",
+"Canon PowerShot S5 IS (CHDK hack)",
+"Canon PowerShot SD300 (CHDK hack)",
+"Canon PowerShot S30",
+"Canon PowerShot S40",
+"Canon PowerShot S45",
+"Canon PowerShot S50",
+"Canon PowerShot S60",
+"Canon PowerShot S70",
+"Canon PowerShot S90",
+"Canon PowerShot SX1 IS",
+"Canon PowerShot SX110 IS (CHDK hack)",
+"Canon EOS D30",
+"Canon EOS D60",
+"Canon EOS 5D",
+"Canon EOS 5D Mark II",
+"Canon EOS 7D",
+"Canon EOS 10D",
+"Canon EOS 20D",
+"Canon EOS 30D",
+"Canon EOS 40D",
+"Canon EOS 50D",
+"Canon EOS 300D / Digital Rebel / Kiss Digital",
+"Canon EOS 350D / Digital Rebel XT / Kiss Digital N",
+"Canon EOS 400D / Digital Rebel XTi / Kiss Digital X",
+"Canon EOS 450D / Digital Rebel XSi / Kiss Digital X2",
+"Canon EOS 500D / Digital Rebel T1i / Kiss Digital X3",
+"Canon EOS 1000D / Digital Rebel XS / Kiss Digital F",
+"Canon EOS D2000C",
+"Canon EOS-1D",
+"Canon EOS-1DS",
+"Canon EOS-1D Mark II",
+"Canon EOS-1D Mark II N",
+"Canon EOS-1D Mark III",
+"Canon EOS-1D Mark IV",
+"Canon EOS-1Ds Mark II",
+"Canon EOS-1Ds Mark III",
+"Casio QV-2000UX",
+"Casio QV-3000EX",
+"Casio QV-3500EX",
+"Casio QV-4000",
+"Casio QV-5700",
+"Casio QV-R41",
+"Casio QV-R51",
+"Casio QV-R61",
+"Casio EX-S20",
+"Casio EX-S100",
+"Casio EX-Z4",
+"Casio EX-Z50",
+"Casio EX-Z55",
+"Casio EX-Z60",
+"Casio EX-Z75",
+"Casio EX-Z750",
+"Casio EX-Z850",
+"Casio Exlim Pro 505",
+"Casio Exlim Pro 600",
+"Casio Exlim Pro 700",
+"Contax N Digital",
+"Creative PC-CAM 600",
+"Epson R-D1",
+"Foculus 531C",
+"Fuji FinePix E550",
+"Fuji FinePix E900",
+"Fuji FinePix F700",
+"Fuji FinePix F710",
+"Fuji FinePix F800",
+"Fuji FinePix F810",
+"Fuji FinePix S2Pro",
+"Fuji FinePix S3Pro",
+"Fuji FinePix S5Pro",
+"Fuji FinePix S20Pro",
+"Fuji FinePix S100FS",
+"Fuji FinePix S5000",
+"Fuji FinePix S5100/S5500",
+"Fuji FinePix S5200/S5600",
+"Fuji FinePix S6000fd",
+"Fuji FinePix S7000",
+"Fuji FinePix S9000/S9500",
+"Fuji FinePix S9100/S9600",
+"Fuji FinePix S200EXR",
+"Fuji IS-1",
+"Hasselblad CFV",
+"Hasselblad H3D",
+"Hasselblad V96C",
+"Imacon Ixpress 16-megapixel",
+"Imacon Ixpress 22-megapixel",
+"Imacon Ixpress 39-megapixel",
+"ISG 2020x1520",
+"Kodak DC20 (see Oliver Hartman's page)",
+"Kodak DC25 (see Jun-ichiro Itoh's page)",
+"Kodak DC40",
+"Kodak DC50",
+"Kodak DC120 (also try kdc2tiff)",
+"Kodak DCS200",
+"Kodak DCS315C",
+"Kodak DCS330C",
+"Kodak DCS420",
+"Kodak DCS460",
+"Kodak DCS460A",
+"Kodak DCS520C",
+"Kodak DCS560C",
+"Kodak DCS620C",
+"Kodak DCS620X",
+"Kodak DCS660C",
+"Kodak DCS660M",
+"Kodak DCS720X",
+"Kodak DCS760C",
+"Kodak DCS760M",
+"Kodak EOSDCS1",
+"Kodak EOSDCS3B",
+"Kodak NC2000F",
+"Kodak ProBack",
+"Kodak PB645C",
+"Kodak PB645H",
+"Kodak PB645M",
+"Kodak DCS Pro 14n",
+"Kodak DCS Pro 14nx",
+"Kodak DCS Pro SLR/c",
+"Kodak DCS Pro SLR/n",
+"Kodak C330",
+"Kodak C603",
+"Kodak P850",
+"Kodak P880",
+"Kodak Z980",
+"Kodak Z1015",
+"Kodak KAI-0340",
+"Konica KD-400Z",
+"Konica KD-510Z",
+"Leaf AFi 7",
+"Leaf Aptus 17",
+"Leaf Aptus 22",
+"Leaf Aptus 54S",
+"Leaf Aptus 65",
+"Leaf Aptus 75",
+"Leaf Aptus 75S",
+"Leaf Cantare",
+"Leaf CatchLight",
+"Leaf CMost",
+"Leaf DCB2",
+"Leaf Valeo 6",
+"Leaf Valeo 11",
+"Leaf Valeo 17",
+"Leaf Valeo 22",
+"Leaf Volare",
+"Leica Digilux 2",
+"Leica Digilux 3",
+"Leica D-LUX2",
+"Leica D-LUX3",
+"Leica D-LUX4",
+"Leica V-LUX1",
+"Logitech Fotoman Pixtura",
+"Mamiya ZD",
+"Micron 2010",
+"Minolta RD175",
+"Minolta DiMAGE 5",
+"Minolta DiMAGE 7",
+"Minolta DiMAGE 7i",
+"Minolta DiMAGE 7Hi",
+"Minolta DiMAGE A1",
+"Minolta DiMAGE A2",
+"Minolta DiMAGE A200",
+"Minolta DiMAGE G400",
+"Minolta DiMAGE G500",
+"Minolta DiMAGE G530",
+"Minolta DiMAGE G600",
+"Minolta DiMAGE Z2",
+"Minolta Alpha/Dynax/Maxxum 5D",
+"Minolta Alpha/Dynax/Maxxum 7D",
+"Motorola PIXL",
+"Nikon D1",
+"Nikon D1H",
+"Nikon D1X",
+"Nikon D2H",
+"Nikon D2Hs",
+"Nikon D2X",
+"Nikon D2Xs",
+"Nikon D3",
+"Nikon D3X",
+"Nikon D40",
+"Nikon D40X",
+"Nikon D50",
+"Nikon D60",
+"Nikon D70",
+"Nikon D70s",
+"Nikon D80",
+"Nikon D90",
+"Nikon D100",
+"Nikon D200",
+"Nikon D300",
+"Nikon D300s",
+"Nikon D700",
+"Nikon D3000",
+"Nikon D5000",
+"Nikon E700 (\"DIAG RAW\" hack)",
+"Nikon E800 (\"DIAG RAW\" hack)",
+"Nikon E880 (\"DIAG RAW\" hack)",
+"Nikon E900 (\"DIAG RAW\" hack)",
+"Nikon E950 (\"DIAG RAW\" hack)",
+"Nikon E990 (\"DIAG RAW\" hack)",
+"Nikon E995 (\"DIAG RAW\" hack)",
+"Nikon E2100 (\"DIAG RAW\" hack)",
+"Nikon E2500 (\"DIAG RAW\" hack)",
+"Nikon E3200 (\"DIAG RAW\" hack)",
+"Nikon E3700 (\"DIAG RAW\" hack)",
+"Nikon E4300 (\"DIAG RAW\" hack)",
+"Nikon E4500 (\"DIAG RAW\" hack)",
+"Nikon E5000",
+"Nikon E5400",
+"Nikon E5700",
+"Nikon E8400",
+"Nikon E8700",
+"Nikon E8800",
+"Nikon Coolpix P6000",
+"Nikon Coolpix S6 (\"DIAG RAW\" hack)",
+"Nokia N95",
+"Olympus C3030Z",
+"Olympus C5050Z",
+"Olympus C5060WZ",
+"Olympus C7070WZ",
+"Olympus C70Z,C7000Z",
+"Olympus C740UZ",
+"Olympus C770UZ",
+"Olympus C8080WZ",
+"Olympus X200,D560Z,C350Z",
+"Olympus E-1",
+"Olympus E-3",
+"Olympus E-10",
+"Olympus E-20",
+"Olympus E-30",
+"Olympus E-300",
+"Olympus E-330",
+"Olympus E-400",
+"Olympus E-410",
+"Olympus E-420",
+"Olympus E-500",
+"Olympus E-510",
+"Olympus E-520",
+"Olympus E-620",
+"Olympus E-P1",
+"Olympus SP310",
+"Olympus SP320",
+"Olympus SP350",
+"Olympus SP500UZ",
+"Olympus SP510UZ",
+"Olympus SP550UZ",
+"Olympus SP560UZ",
+"Olympus SP570UZ",
+"Panasonic DMC-FZ8",
+"Panasonic DMC-FZ18",
+"Panasonic DMC-FZ28",
+"Panasonic DMC-FZ30",
+"Panasonic DMC-FZ35/FZ38",
+"Panasonic DMC-FZ50",
+"Panasonic DMC-FX150",
+"Panasonic DMC-G1",
+"Panasonic DMC-GH1",
+"Panasonic DMC-L1",
+"Panasonic DMC-L10",
+"Panasonic DMC-LC1",
+"Panasonic DMC-LX1",
+"Panasonic DMC-LX2",
+"Panasonic DMC-LX3",
+"Pentax *ist D",
+"Pentax *ist DL",
+"Pentax *ist DL2",
+"Pentax *ist DS",
+"Pentax *ist DS2",
+"Pentax K10D",
+"Pentax K20D",
+"Pentax K100D",
+"Pentax K100D Super",
+"Pentax K200D",
+"Pentax K2000/K-m",
+"Pentax K-x",
+"Pentax K-7",
+"Pentax Optio S",
+"Pentax Optio S4",
+"Pentax Optio 33WR",
+"Pentax Optio 750Z",
+"Phase One LightPhase",
+"Phase One H 10",
+"Phase One H 20",
+"Phase One H 25",
+"Phase One P 20",
+"Phase One P 25",
+"Phase One P 30",
+"Phase One P 45",
+"Phase One P 45+",
+"Pixelink A782",
+"Rollei d530flex",
+"RoverShot 3320af",
+"Samsung GX-1S",
+"Samsung GX-10",
+"Samsung S85 (hacked)",
+"Samsung S850 (hacked)",
+"Sarnoff 4096x5440",
+"Sinar 3072x2048",
+"Sinar 4080x4080",
+"Sinar 4080x5440",
+"Sinar STI format",
+"SMaL Ultra-Pocket 3",
+"SMaL Ultra-Pocket 4",
+"SMaL Ultra-Pocket 5",
+"Sony DSC-F828",
+"Sony DSC-R1",
+"Sony DSC-V3",
+"Sony DSLR-A100",
+"Sony DSLR-A200",
+"Sony DSLR-A300",
+"Sony DSLR-A330",
+"Sony DSLR-A350",
+"Sony DSLR-A380",
+"Sony DSLR-A500",
+"Sony DSLR-A550",
+"Sony DSLR-A700",
+"Sony DSLR-A850",
+"Sony DSLR-A900",
+"Sony XCD-SX910CR",
+"STV680 VGA",
+
+   NULL
+};
+
+const char** LibRaw::cameraList() { return static_camera_list;}
+int LibRaw::cameraCount() { return (sizeof(static_camera_list)/sizeof(static_camera_list[0]))-1; }
+
+
+const char * LibRaw::strprogress(enum LibRaw_progress p)
+{
+    switch(p)
+        {
+        case LIBRAW_PROGRESS_START:
+            return "Starting";
+        case LIBRAW_PROGRESS_OPEN :
+            return "Opening file";
+        case LIBRAW_PROGRESS_IDENTIFY :
+            return "Reading metadata";
+        case LIBRAW_PROGRESS_SIZE_ADJUST:
+            return "Adjusting size";
+        case LIBRAW_PROGRESS_LOAD_RAW:
+            return "Reading RAW data";
+        case LIBRAW_PROGRESS_REMOVE_ZEROES:
+            return "Clearing zero values";
+        case LIBRAW_PROGRESS_BAD_PIXELS :
+            return "Removing dead pixels";
+        case LIBRAW_PROGRESS_DARK_FRAME:
+            return "Subtracting dark frame data";
+        case LIBRAW_PROGRESS_SCALE_COLORS:
+            return "Scaling colors";
+        case LIBRAW_PROGRESS_PRE_INTERPOLATE:
+            return "Pre-interpolating";
+        case LIBRAW_PROGRESS_INTERPOLATE:
+            return "Interpolating";
+        case LIBRAW_PROGRESS_MIX_GREEN :
+            return "Mixing green channels";
+        case LIBRAW_PROGRESS_MEDIAN_FILTER   :
+            return "Median filter";
+        case LIBRAW_PROGRESS_HIGHLIGHTS:
+            return "Highlight recovery";
+        case LIBRAW_PROGRESS_FUJI_ROTATE :
+            return "Rotating Fuji diagonal data";
+        case LIBRAW_PROGRESS_FLIP :
+            return "Flipping image";
+        case LIBRAW_PROGRESS_APPLY_PROFILE:
+            return "ICC conversion";
+        case LIBRAW_PROGRESS_CONVERT_RGB:
+            return "Converting to RGB";
+        case LIBRAW_PROGRESS_STRETCH:
+            return "Stretching image";
+        case LIBRAW_PROGRESS_THUMB_LOAD:
+            return "Loading thumbnail";
+        default:
+            return "Some strange things";
+        }
+}
diff --git a/ossim_plugins/libraw/ossimLibRawPluginInit.cpp b/ossim_plugins/libraw/ossimLibRawPluginInit.cpp
new file mode 100644
index 0000000..a1fc1db
--- /dev/null
+++ b/ossim_plugins/libraw/ossimLibRawPluginInit.cpp
@@ -0,0 +1,89 @@
+//----------------------------------------------------------------------------
+//
+// License:  See top level LICENSE.txt file
+//
+// Author:  David Burken
+//
+// Description: OSSIM Portable Network Graphics (PNG) plugin initialization
+// code.
+//
+//----------------------------------------------------------------------------
+// $Id: ossimLibRawPluginInit.cpp 11046 2007-05-25 18:03:03Z gpotts $
+
+#include <ossim/plugin/ossimSharedObjectBridge.h>
+#include "ossimPluginConstants.h"
+#include "ossimLibRawReaderFactory.h"
+#include <ossim/imaging/ossimImageHandlerRegistry.h>
+#include <ossim/imaging/ossimImageWriterFactoryRegistry.h>
+#include <libraw/libraw.h>
+static void setDescription(ossimString& description)
+{
+   description = "LIBRAW reader plugin version: " + ossimString(libraw_version()) + "\nSupports " + ossimString::toString(libraw_cameraCount()) + " camera formats:\n\n";
+   
+   static const char**         cameraList = libraw_cameraList();
+   int                  count = libraw_cameraCount();
+   
+   int idx = 0;
+   
+   for(idx = 0; idx < count; ++idx)
+   {
+      if(cameraList[idx])
+      {
+         description += ossimString(cameraList[idx]);
+         description += "\n";
+      }
+   }
+
+}
+
+
+extern "C"
+{
+   ossimSharedObjectInfo  myInfo;
+   ossimString theDescription;
+   std::vector<ossimString> theObjList;
+
+   const char* getDescription()
+   {
+      return theDescription.c_str();
+   }
+
+   int getNumberOfClassNames()
+   {
+      return (int)theObjList.size();
+   }
+
+   const char* getClassName(int idx)
+   {
+      if(idx < (int)theObjList.size())
+      {
+         return theObjList[0].c_str();
+      }
+      return (const char*)0;
+   }
+
+   /* Note symbols need to be exported on windoze... */ 
+   OSSIM_PLUGINS_DLL void ossimSharedLibraryInitialize(
+                                                       ossimSharedObjectInfo** info, 
+                                                       const char* /*options*/)
+   {    
+      myInfo.getDescription = getDescription;
+      myInfo.getNumberOfClassNames = getNumberOfClassNames;
+      myInfo.getClassName = getClassName;
+      
+      *info = &myInfo;
+      
+      /* Register the readers... */
+      ossimImageHandlerRegistry::instance()->
+        registerFactory(ossimLibRawReaderFactory::instance());
+      
+      setDescription(theDescription);
+  }
+
+   /* Note symbols need to be exported on windoze... */ 
+  OSSIM_PLUGINS_DLL void ossimSharedLibraryFinalize()
+  {
+     ossimImageHandlerRegistry::instance()->
+        unregisterFactory(ossimLibRawReaderFactory::instance());
+  }
+}
diff --git a/ossim_plugins/libraw/ossimLibRawReader.cpp b/ossim_plugins/libraw/ossimLibRawReader.cpp
new file mode 100644
index 0000000..8ceb8cb
--- /dev/null
+++ b/ossim_plugins/libraw/ossimLibRawReader.cpp
@@ -0,0 +1,350 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author:  David Burken
+//
+// Description: OSSIM Portable Network Graphics (PNG) reader (tile source).
+//
+//----------------------------------------------------------------------------
+// $Id: ossimLibRawReader.cpp 16420 2010-01-27 15:41:52Z dburken $
+
+#include <cstdlib>
+#include <cstddef> /* for NULL */
+#include <cmath>   /* for pow */
+
+#include "ossimLibRawReader.h"
+#include <ossim/imaging/ossimImageDataFactory.h>
+#include <ossim/base/ossimConstants.h>
+#include <ossim/base/ossimIpt.h>
+#include <ossim/base/ossimDpt.h>
+#include <ossim/base/ossimEndian.h>
+#include <ossim/base/ossimIrect.h>
+#include <ossim/base/ossimFilename.h>
+#include <ossim/base/ossimKeywordlist.h>
+#include <ossim/base/ossimTrace.h>
+#include <ossim/base/ossimNotifyContext.h>
+
+
+RTTI_DEF1(ossimLibRawReader, "ossimLibRawReader", ossimImageHandler)
+
+#ifdef OSSIM_ID_ENABLED
+   static const char OSSIM_ID[] = "$Id: ossimLibRawReader.cpp 16420 2010-01-27 15:41:52Z dburken $";
+#endif
+   
+static ossimTrace traceDebug("ossimLibRawReader:degug");  
+
+ossimLibRawReader::ossimLibRawReader()
+   :
+      ossimImageHandler(),
+      theRawProcessor(0)
+{
+}
+
+ossimLibRawReader::~ossimLibRawReader()
+{
+   if (isOpen())
+   {
+      close();
+   }
+}
+
+void ossimLibRawReader::destroy()
+{
+   if(theRawProcessor)
+   {
+      delete theRawProcessor;
+      theRawProcessor = 0;
+   }
+   theTile = 0;
+   theMemoryTile = 0;
+}
+
+ossimRefPtr<ossimImageData> ossimLibRawReader::getTile(
+                                                         const  ossimIrect& tile_rect,
+                                                         ossim_uint32 resLevel)
+{
+   if(!theTile.valid()||!theMemoryTile.valid())
+   {
+      cacheImage();
+   }
+   if (theTile.valid())
+   {
+      // Image rectangle must be set prior to calling getTile.
+      theTile->setImageRectangle(tile_rect);
+      
+      if ( getTile( theTile.get(), resLevel ) == false )
+      {
+         if (theTile->getDataObjectStatus() != OSSIM_NULL)
+         {
+            theTile->makeBlank();
+         }
+      }
+   }
+   
+   return theTile;
+}
+
+bool ossimLibRawReader::getTile(ossimImageData* result,
+                                  ossim_uint32 resLevel)
+{
+   bool status = false;
+   status = getOverviewTile(resLevel, result);
+   
+   ossimIrect rect = result->getImageRectangle();
+   if (!status) // Did not get an overview tile.
+   {
+      if(!theTile.valid()||!theMemoryTile.valid())
+      {
+         cacheImage();
+      }
+      if (theTile.valid())
+      {
+         // Image rectangle must be set prior to calling getTile.
+         theTile->setImageRectangle(rect);
+         
+         theTile->makeBlank();
+         
+         ossimIrect memRect = theMemoryTile->getImageRectangle();
+         
+         if(memRect.intersects(rect))
+         {
+            ossimIrect clampRect = theMemoryTile->getImageRectangle().clipToRect(rect);
+            
+            theTile->loadTile(theMemoryTile->getBuf(),
+                              memRect,
+                              OSSIM_BSQ);
+            
+            theTile->validate();
+            status = true;
+         }
+      }
+   }
+   return status;
+}
+
+
+
+ossimIrect
+ossimLibRawReader::getImageRectangle(ossim_uint32 reduced_res_level) const
+{
+   return ossimIrect(0,
+                     0,
+                     getNumberOfSamples(reduced_res_level) - 1,
+                     getNumberOfLines(reduced_res_level)   - 1);
+}
+
+bool ossimLibRawReader::saveState(ossimKeywordlist& kwl,
+                               const char* prefix) const
+{
+   return ossimImageHandler::saveState(kwl, prefix);
+}
+
+bool ossimLibRawReader::loadState(const ossimKeywordlist& kwl,
+                               const char* prefix)
+{
+   if (ossimImageHandler::loadState(kwl, prefix))
+   {
+      return open();
+   }
+
+   return false;
+}
+
+bool ossimLibRawReader::open()
+{
+   OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theMutex);
+   int ret = 0;
+   static const char MODULE[] = "ossimLibRawReader::open";
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimLibRawReader::open entered..."
+         << "File:  " << theImageFile.c_str()
+         << std::endl;
+   }
+
+   // Start with a clean slate.
+   if (isOpen())
+   {
+      close();
+   }
+   
+   // Check for empty filename.
+   if (theImageFile.empty())
+   {
+      return false;
+   }
+   theRawProcessor = new LibRaw();
+   if( (ret = theRawProcessor->open_file(theImageFile.c_str()) != LIBRAW_SUCCESS))
+   {
+      destroy();
+      return false;
+   }
+   
+   ossimImageHandler::completeOpen();
+
+
+   return true;
+}
+
+ossim_uint32 ossimLibRawReader::getNumberOfLines(ossim_uint32 reduced_res_level) const
+{
+   cacheImage();
+   if (reduced_res_level == 0)
+   {
+      if(theMemoryTile.valid())
+      {
+         return theMemoryTile->getHeight();
+      }
+   }
+   else if ( theOverview.valid() )
+   {
+      return theOverview->getNumberOfLines(reduced_res_level);
+   }
+
+   return 0;
+}
+
+ossim_uint32 ossimLibRawReader::getNumberOfSamples(ossim_uint32 reduced_res_level) const
+{
+   cacheImage();
+   if (reduced_res_level == 0)
+   {
+      if(theMemoryTile.valid())
+      {
+         return theMemoryTile->getWidth();
+      }
+   }
+   else if ( theOverview.valid() )
+   {
+      return theOverview->getNumberOfSamples(reduced_res_level);
+   }
+
+   return 0;
+}
+
+ossim_uint32 ossimLibRawReader::getImageTileWidth() const
+{
+   return 0;
+}
+
+ossim_uint32 ossimLibRawReader::getImageTileHeight() const
+{
+   return 0;
+}
+
+ossimString ossimLibRawReader::getShortName()const
+{
+   return ossimString("ossim_libraw_reader");
+}
+   
+ossimString ossimLibRawReader::getLongName()const
+{
+   return ossimString("ossim libraw reader");
+}
+
+ossimString  ossimLibRawReader::getClassName()const
+{
+   return ossimString("ossimLibRawReader");
+}
+
+ossim_uint32 ossimLibRawReader::getNumberOfInputBands() const
+{
+   ossim_uint32 result = 0;
+   cacheImage();
+   if(theMemoryTile.valid())
+   {
+      result = theMemoryTile->getNumberOfBands();
+   }
+   return result;
+}
+
+ossim_uint32 ossimLibRawReader::getNumberOfOutputBands()const
+{
+   return getNumberOfInputBands();
+}
+
+ossimScalarType ossimLibRawReader::getOutputScalarType() const
+{
+   cacheImage();
+   if(theMemoryTile.valid())
+   {
+      return theMemoryTile->getScalarType();
+   }
+   return ossimImageHandler::getOutputScalarType();
+}
+
+bool ossimLibRawReader::isOpen()const
+{
+   return ((theRawProcessor != 0)||
+           (theMemoryTile.valid()));
+}
+
+double ossimLibRawReader::getMaxPixelValue(ossim_uint32 band)const
+{
+   cacheImage();
+   if(theMemoryTile.valid())
+   {
+      return theMemoryTile->getMaxPix(band);
+   }
+   return ossimImageHandler::getMaxPixelValue(band);
+}
+
+void ossimLibRawReader::close()
+{
+   destroy();
+   ossimImageHandler::close();
+}
+
+bool ossimLibRawReader::cacheImage()const
+{
+   OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theMutex);
+   
+   bool result = false;
+   if(theMemoryTile.valid()) return true;
+   if(!theRawProcessor) return result;
+   int ret = 0;
+   if( (ret = theRawProcessor->unpack() ) == LIBRAW_SUCCESS)
+   {
+      theRawProcessor->imgdata.params.output_bps = 16;
+      theRawProcessor->imgdata.params.output_color = 1;
+      theRawProcessor->imgdata.params.no_auto_bright = 1;
+      
+      
+      ret = theRawProcessor->dcraw_process();
+      if(LIBRAW_SUCCESS ==ret)
+      {
+         libraw_processed_image_t *image = theRawProcessor->dcraw_make_mem_image(&ret);
+         if(image)
+         {
+            theMemoryTile = 0;
+            theTile = 0;
+            ossimScalarType scalarType = OSSIM_UINT16;
+            if(image->bits == 8)
+            {
+               scalarType = OSSIM_UINT8;
+            }
+            theMemoryTile = new ossimImageData(0, scalarType, image->colors, image->width, image->height);
+            theTile       = new ossimImageData(0, scalarType, image->colors, 8,8);
+            theTile->initialize();
+            theMemoryTile->initialize();
+            theMemoryTile->loadTile(image->data, 
+                                    theMemoryTile->getImageRectangle(), 
+                                    OSSIM_BIP);
+            result = true;
+            free(image);
+            image = 0;
+         }
+      }
+   }
+   delete theRawProcessor;
+   theRawProcessor = 0;
+   
+   return result;
+}
+
+
diff --git a/ossim_plugins/libraw/ossimLibRawReader.h b/ossim_plugins/libraw/ossimLibRawReader.h
new file mode 100644
index 0000000..0374e23
--- /dev/null
+++ b/ossim_plugins/libraw/ossimLibRawReader.h
@@ -0,0 +1,151 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author:  Garrett Potts
+//
+// Description: Uses the LibRaw library for reading raw sensor images
+//
+//----------------------------------------------------------------------------
+// $Id$
+#ifndef ossimLibRawReader_HEADER
+#define ossimLibRawReader_HEADER
+
+#include <png.h>
+#include <vector>
+
+#include <ossim/imaging/ossimImageHandler.h>
+#include <ossim/imaging/ossimAppFixedTileCache.h>
+#include <libraw/libraw.h>
+
+class ossimImageData;
+
+class ossimLibRawReader : public ossimImageHandler
+{
+public:
+
+
+   /** default constructor */
+   ossimLibRawReader();
+
+   /** virtual destructor */
+   virtual ~ossimLibRawReader();
+
+   /** @return "png" */
+   virtual ossimString getShortName() const;
+
+   /** @return "ossim png" */
+   virtual ossimString getLongName()  const;
+
+   /** @return "ossimLibRawReader" */
+   virtual ossimString getClassName()    const;
+
+   /**
+    *  Returns a pointer to a tile given an origin representing the upper
+    *  left corner of the tile to grab from the image.
+    *  Satisfies pure virtual from TileSource class.
+    */
+   virtual ossimRefPtr<ossimImageData> getTile(const  ossimIrect& rect,
+                                               ossim_uint32 resLevel=0);
+   
+   bool getTile(ossimImageData* result,
+                ossim_uint32 resLevel);
+    /**
+     *  Returns the number of bands in the image.
+     *  Satisfies pure virtual from ImageHandler class.
+     */
+   virtual ossim_uint32 getNumberOfInputBands() const;
+
+   /**
+    * Returns the number of bands in a tile returned from this TileSource.
+    * Note: we are supporting sources that can have multiple data objects.
+    * If you want to know the scalar type of an object you can pass in the
+    */
+   virtual ossim_uint32 getNumberOfOutputBands()const;
+
+   /**
+     *  Returns the number of lines in the image.
+     *  Satisfies pure virtual from ImageHandler class.
+     */
+   virtual ossim_uint32 getNumberOfLines(ossim_uint32 reduced_res_level = 0) const;
+
+   /**
+    *  Returns the number of samples in the image.
+    *  Satisfies pure virtual from ImageHandler class.
+    */
+   virtual ossim_uint32 getNumberOfSamples(ossim_uint32 reduced_res_level = 0) const;
+
+   /**
+    * Returns the zero based image rectangle for the reduced resolution data
+    * set (rrds) passed in.  Note that rrds 0 is the highest resolution rrds.
+    */
+   virtual ossimIrect getImageRectangle(ossim_uint32 reduced_res_level = 0) const;
+
+   /**
+    * Method to save the state of an object to a keyword list.
+    * Return true if ok or false on error.
+    */
+   virtual bool saveState(ossimKeywordlist& kwl,
+                          const char* prefix=0)const;
+
+   /**
+    * Method to the load (recreate) the state of an object from a keyword
+    * list.  Return true if ok or false on error.
+    */
+   virtual bool loadState(const ossimKeywordlist& kwl,
+                          const char* prefix=0);
+
+   /**
+    * Returns the output pixel type of the tile source.
+    */
+   virtual ossimScalarType getOutputScalarType() const;
+
+   /**
+    * Returns the tile width of the image or 0 if the image is not tiled.
+    * Note: this is not the same as the ossimImageSource::getTileWidth which
+    * returns the output tile width which can be different than the internal
+    * image tile width on disk.
+    */
+   virtual ossim_uint32 getImageTileWidth() const;
+
+   /**
+    * Returns the tile width of the image or 0 if the image is not tiled.
+    * Note: this is not the same as the ossimImageSource::getTileWidth which
+    * returns the output tile width which can be different than the internal
+    * image tile width on disk.
+    */
+   virtual ossim_uint32 getImageTileHeight() const;
+
+   bool isOpen()const;
+
+   virtual double getMaxPixelValue(ossim_uint32 band = 0)const;
+
+   /** Close method. */
+   virtual void close();
+
+protected:
+   
+   /**
+    *  @brief open method.
+    *  @return true on success, false on error.
+    */
+   virtual bool open();
+
+   virtual bool cacheImage()const;
+   /**
+    */ 
+   void allocate();
+   void destroy();
+
+   mutable ossimRefPtr<ossimImageData>  theTile;
+   mutable ossimRefPtr<ossimImageData> theMemoryTile;
+   mutable LibRaw *theRawProcessor;
+   mutable OpenThreads::Mutex theMutex;
+   
+TYPE_DATA
+};
+
+#endif
+
diff --git a/ossim_plugins/libraw/ossimLibRawReaderFactory.cpp b/ossim_plugins/libraw/ossimLibRawReaderFactory.cpp
new file mode 100644
index 0000000..f02736a
--- /dev/null
+++ b/ossim_plugins/libraw/ossimLibRawReaderFactory.cpp
@@ -0,0 +1,129 @@
+//----------------------------------------------------------------------------
+//
+// License:  See top level LICENSE.txt file
+//
+// Author:  David Burken
+//
+// Description: Factory for OSSIM Portable Network Graphics (PNG) reader
+// (tile source).
+//----------------------------------------------------------------------------
+// $Id: ossimLibRawReaderFactory.cpp 15766 2009-10-20 12:37:09Z gpotts $
+
+#include "ossimLibRawReaderFactory.h"
+#include "ossimLibRawReader.h"
+#include <ossim/base/ossimKeywordlist.h>
+#include <ossim/base/ossimRefPtr.h>
+#include <ossim/base/ossimString.h>
+#include <ossim/imaging/ossimImageHandler.h>
+#include <ossim/base/ossimTrace.h>
+#include <ossim/base/ossimKeywordNames.h>
+
+static const ossimTrace traceDebug("ossimLibRawReaderFactory:debug");
+
+RTTI_DEF1(ossimLibRawReaderFactory,
+          "ossimLibRawReaderFactory",
+          ossimImageHandlerFactoryBase);
+
+ossimLibRawReaderFactory* ossimLibRawReaderFactory::theInstance = 0;
+
+ossimLibRawReaderFactory::~ossimLibRawReaderFactory()
+{
+   theInstance = 0;
+}
+
+ossimLibRawReaderFactory* ossimLibRawReaderFactory::instance()
+{
+   if(!theInstance)
+   {
+      theInstance = new ossimLibRawReaderFactory;
+   }
+   return theInstance;
+}
+   
+ossimImageHandler* ossimLibRawReaderFactory::open(
+   const ossimFilename& fileName, bool openOverview)const
+{
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimLibRawReaderFactory::open(filename) DEBUG: entered..."
+         << "\ntrying ossimLibRawReader"
+         << std::endl;
+   }
+   
+   ossimRefPtr<ossimImageHandler> reader = new ossimLibRawReader;
+   reader->setOpenOverviewFlag(openOverview);
+   if(reader->open(fileName) == false)
+   {
+      reader = 0;
+   }
+   
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimLibRawReaderFactory::open(filename) DEBUG: leaving..."
+         << std::endl;
+   }
+   
+   return reader.release();
+}
+
+ossimImageHandler* ossimLibRawReaderFactory::open(const ossimKeywordlist& kwl,
+                                               const char* prefix)const
+{
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimLibRawReaderFactory::open(kwl, prefix) DEBUG: entered..."
+         << "Trying ossimLibRawReader"
+         << std::endl;
+   }
+
+   ossimRefPtr<ossimImageHandler> reader = new ossimLibRawReader;
+   if(reader->loadState(kwl, prefix) == false)
+   {
+      reader = 0;
+   }
+   
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimLibRawReaderFactory::open(kwl, prefix) DEBUG: leaving..."
+         << std::endl;
+   }
+   
+   return reader.release();
+}
+
+ossimObject* ossimLibRawReaderFactory::createObject(
+   const ossimString& typeName)const
+{
+   ossimRefPtr<ossimObject> result = 0;
+   if(typeName == "ossimLibRawReader")
+   {
+      result = new ossimLibRawReader;
+   }
+   return result.release();
+}
+
+ossimObject* ossimLibRawReaderFactory::createObject(const ossimKeywordlist& kwl,
+                                                 const char* prefix)const
+{
+   return this->open(kwl, prefix);
+}
+ 
+void ossimLibRawReaderFactory::getTypeNameList(std::vector<ossimString>& typeList)const
+{
+   typeList.push_back(ossimString("ossimLibRawReader"));
+}
+
+void ossimLibRawReaderFactory::getSupportedExtensions(
+   ossimImageHandlerFactoryBase::UniqueStringList& extensionList)const
+{
+}
+
+ossimLibRawReaderFactory::ossimLibRawReaderFactory(){}
+
+ossimLibRawReaderFactory::ossimLibRawReaderFactory(const ossimLibRawReaderFactory&){}
+
+void ossimLibRawReaderFactory::operator=(const ossimLibRawReaderFactory&){}
diff --git a/ossim_plugins/libraw/ossimLibRawReaderFactory.h b/ossim_plugins/libraw/ossimLibRawReaderFactory.h
new file mode 100644
index 0000000..7f166c1
--- /dev/null
+++ b/ossim_plugins/libraw/ossimLibRawReaderFactory.h
@@ -0,0 +1,99 @@
+//----------------------------------------------------------------------------
+//
+// License:  See top level LICENSE.txt file
+//
+// Author:  David Burken
+//
+// Description: Factory for OSSIM Portable Network Graphics plugin (PNG)
+// reader.
+//----------------------------------------------------------------------------
+// $Id: ossimLibRawReaderFactory.h 10110 2006-12-14 18:20:54Z dburken $
+#ifndef ossimLibRawReaderFactory_HEADER
+#define ossimLibRawReaderFactory_HEADER
+
+#include <ossim/imaging/ossimImageHandlerFactoryBase.h>
+
+class ossimString;
+class ossimFilename;
+class ossimKeywordlist;
+
+/** @brief Factory for PNG image reader. */
+class ossimLibRawReaderFactory : public ossimImageHandlerFactoryBase
+{
+public:
+
+   /** @brief virtual destructor */
+   virtual ~ossimLibRawReaderFactory();
+
+   /**
+    * @brief static method to return instance (the only one) of this class.
+    * @return pointer to instance of this class.
+    */
+   static ossimLibRawReaderFactory* instance();
+
+   /**
+    * @brief open that takes a file name.
+    * @param file The file to open.
+    * @param openOverview If true image handler will attempt to open overview.
+    * default = true
+    * @return pointer to image handler on success, NULL on failure.
+    */
+   virtual ossimImageHandler* open(const ossimFilename& fileName,
+                                   bool openOverview=true) const;
+
+   /**
+    * @brief open that takes a keyword list and prefix.
+    * @param kwl The keyword list.
+    * @param prefix the keyword list prefix.
+    * @return pointer to image handler on success, NULL on failure.
+    */
+   virtual ossimImageHandler* open(const ossimKeywordlist& kwl,
+                                   const char* prefix=0)const;
+
+   /**
+    * @brief createObject that takes a class name (ossimLibRawReader)
+    * @param typeName Should be "ossimLibRawReader".
+    * @return pointer to image writer on success, NULL on failure.
+    */
+   virtual ossimObject* createObject(const ossimString& typeName)const;
+   
+   /**
+    * @brief Creates and object given a keyword list and prefix.
+    * @param kwl The keyword list.
+    * @param prefix the keyword list prefix.
+    * @return pointer to image handler on success, NULL on failure.
+    */
+   virtual ossimObject* createObject(const ossimKeywordlist& kwl,
+                                     const char* prefix=0)const;
+   
+   /**
+    * @brief Adds ossimLibRawWriter to the typeList.
+    * @param typeList List to add to.
+    */
+   virtual void getTypeNameList(std::vector<ossimString>& typeList)const;
+
+   /**
+    * @brief Method to add supported extension to the list, like "png".
+    *
+    * @param extensionList The list to add to.
+    */
+   virtual void getSupportedExtensions(
+      ossimImageHandlerFactoryBase::UniqueStringList& extensionList)const;
+  
+protected:
+   /** @brief hidden from use default constructor */
+   ossimLibRawReaderFactory();
+
+   /** @brief hidden from use copy constructor */
+   ossimLibRawReaderFactory(const ossimLibRawReaderFactory&);
+
+   /** @brief hidden from use copy constructor */
+   void operator=(const ossimLibRawReaderFactory&);
+
+   /** static instance of this class */
+   static ossimLibRawReaderFactory* theInstance;
+
+TYPE_DATA
+};
+
+#endif /* end of #ifndef ossimLibRawReaderFactory_HEADER */
diff --git a/ossim_plugins/make.opt.in b/ossim_plugins/make.opt.in
new file mode 100644
index 0000000..1a267e7
--- /dev/null
+++ b/ossim_plugins/make.opt.in
@@ -0,0 +1,100 @@
+###
+# $Id: make.opt.in 16956 2010-04-02 19:08:37Z gpotts $
+#
+# Edit these as required for your platform and plugins.
+###
+
+# Ossim Plugins Top
+OPT=`pwd`
+
+
+###
+# GDAL plugin specific things...
+#
+# GDAL_HOME can be:
+# - an environment variable
+# - or you can set it here, 
+# - or if your gdal is in standard place just leave this be...
+###
+
+
+# If gdal with MRSID
+# MRSID_LIBS = -L/work/drb/mrsid/Geo_ESDK-4.1.5.964/3rd-party/lib/Release -L/work/drb/mrsid/Geo_ESDK-4.1.5.964/lib/Release -lltiesdk -lltidsdk
+# else 
+MRSID_LIBS=
+
+###
+# KAKADU: Uncomment/edit as needed.
+#
+#KAKADU_VERSION=v6_2-00367C
+#KAKADU_HOME=/your/path/to/kakadu/$(KAKADU_VERSION)
+#KAKADU_INCLUDES=-I$(KAKADU_HOME)/managed/all_includes
+#KAKADU_LIBS=$(KAKADU_HOME)/apps/make/jp2.o $(KAKADU_HOME)/apps/make/kdu_region_decompressor.o $(KAKADU_HOME)/apps/make/kdu_stripe_compressor.o -L$(KAKADU_HOME)/lib/Linux-x86-64-gcc -lkdu_v62R
+###
+
+# GDAL_HOME = 
+ifeq ($(origin GDAL_HOME), undefined)
+  GDAL_INCLUDES =`gdal-config --cflags`
+  GDAL_LIBS = `gdal-config --libs`
+else
+  GDAL_INCLUDES = -I$(GDAL_HOME)/include
+  GDAL_LIBS = -L$(GDAL_HOME)/lib -lgdal
+endif
+###
+# End of gdal plugin specific things.
+###
+
+###
+# FFTW includes and libs.  Found at www.fftw.org.  
+# Should come installed Linux through rpm
+# MAC's you can use darwin ports easily
+###
+
+###
+# For MACs:
+# FFTW_HOME = /opt/local
+# FFTW_LIBS = -L$(FFTW_HOME)/lib -lfftw3
+# FFTW_INCLUDES = -I$(FFTW_HOME)/include
+###
+# OR
+###
+# Linux usually in /usr which is standard place.
+# You can get by doing:
+# sudo yum install fftw fftw-devel
+FFTW_LIBS = -lfftw3
+FFTW_INCLUDES=
+
+###
+# For png:
+###
+PNG_INCLUDES=
+PNG_LIBS=-lpng -lz
+
+###
+# For OpenJpeg:
+###
+OPEN_JPEG_INCLUDES=
+OPEN_JPEG_LIBS=-lopenjpeg
+
+###
+# for NUI Support
+#
+NUI_INCLUDES=-I/home/ldadmin/temp/nuiSDK/include/nuiSDK
+NUI_LIBS=-L/home/ldadmin/temp/nuiSDK/lib -lnuiSDK /home/ldadmin/temp/nuiSDK/lib/libkdu_a52R.a  -lkdu -lgdal
+###
+# After editing this, cd to the plugin directory you want and type "make".
+# See README.txt for more info.
+###
+
+###
+# INSTALL DIRECTORY:
+###
+PREFIX=/usr/local/ossim
+OSSIM_PLUGINS_INSTAL_LIB_DIR=$(PREFIX)/lib
+
+###
+# Nitro setup
+###
+#NITRO_INCLUDES=
+#NITRO_LIBS=
+
diff --git a/ossim_plugins/make_platform.opt.in b/ossim_plugins/make_platform.opt.in
new file mode 100644
index 0000000..2331118
--- /dev/null
+++ b/ossim_plugins/make_platform.opt.in
@@ -0,0 +1,21 @@
+###
+# $Id: make_platform.opt.in 9767 2006-10-20 20:37:20Z dburken $
+#
+# For command line gmake platform specific options.  This file should be
+# include after the Makefile.common from ossim if you are overriding 
+# something from there like the "LD_SHARED" variable.
+###
+
+
+
+# linux stuff #
+ifeq ($(HOST_RESULT),linux)
+# Override for linux to just do a straight link. 
+LD_SHARED=$(CXX) -shared 
+endif
+
+
+# darwin stuff #
+# ifeq ($(HOST_RESULT),darwin)
+# nothing to do here...
+# endif
diff --git a/ossim_plugins/makefile.inc b/ossim_plugins/makefile.inc
new file mode 100644
index 0000000..0e52348
--- /dev/null
+++ b/ossim_plugins/makefile.inc
@@ -0,0 +1,71 @@
+# $Id$
+# 
+# Include file for windows nmake for embedding manifest in dll's and 
+# executable (exe) files.
+#
+# makefile.inc -- Include this file into existing makefile at the very top.
+
+# _VC_MANIFEST_INC specifies whether build is incremental (1 - incremental).
+# _VC_MANIFEST_BASENAME specifies name of a temporary resource file.
+
+!if "$(DEBUG)" == "1"
+CPPFLAGS=$(CPPFLAGS) /MDd
+LFLAGS=$(LFLAGS) /INCREMENTAL
+_VC_MANIFEST_INC=1
+_VC_MANIFEST_BASENAME=__VC90.Debug
+
+!else
+CPPFLAGS=$(CPPFLAGS) /MD
+_VC_MANIFEST_INC=0
+_VC_MANIFEST_BASENAME=__VC90
+
+!endif
+
+####################################################
+# Specifying name of temporary resource file used only in incremental builds:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+_VC_MANIFEST_AUTO_RES=$(_VC_MANIFEST_BASENAME).auto.res
+!else
+_VC_MANIFEST_AUTO_RES=
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_EXE - command to embed manifest in EXE:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;1
+
+!endif
+
+####################################################
+# _VC_MANIFEST_CLEAN - command to clean resources files generated temporarily:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+_VC_MANIFEST_CLEAN=-del $(_VC_MANIFEST_BASENAME).auto.res \
+    $(_VC_MANIFEST_BASENAME).auto.rc \
+    $(_VC_MANIFEST_BASENAME).auto.manifest
+
+!else
+
+_VC_MANIFEST_CLEAN=
+
+!endif
+
+# End of makefile.inc 
+####################################################
diff --git a/ossim_plugins/makefile.targ.inc b/ossim_plugins/makefile.targ.inc
new file mode 100644
index 0000000..6d4beee
--- /dev/null
+++ b/ossim_plugins/makefile.targ.inc
@@ -0,0 +1,27 @@
+# $Id$
+# 
+# Include file for windows nmake for embedding manifest in dll's and 
+# executable (exe) files.
+#
+# makefile.targ.inc - include this at the very bottom of the existing makefile
+
+####################################################
+# Commands to generate initial empty manifest file and the RC file
+# that references it, and for generating the .res file:
+
+$(_VC_MANIFEST_BASENAME).auto.res : $(_VC_MANIFEST_BASENAME).auto.rc
+
+$(_VC_MANIFEST_BASENAME).auto.rc : $(_VC_MANIFEST_BASENAME).auto.manifest
+    type <<$@
+#include <winuser.h>
+1RT_MANIFEST"$(_VC_MANIFEST_BASENAME).auto.manifest"
+<< KEEP
+
+$(_VC_MANIFEST_BASENAME).auto.manifest :
+    type <<$@
+<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
+<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
+</assembly>
+<< KEEP
+
+# end of makefile.targ.inc
diff --git a/ossim_plugins/makefile.vc b/ossim_plugins/makefile.vc
new file mode 100644
index 0000000..80271bb
--- /dev/null
+++ b/ossim_plugins/makefile.vc
@@ -0,0 +1,133 @@
+###
+# $Id$
+#
+# Windows nmake make file.
+#
+# Typical usarge: nmake /f makefile.vc
+#
+# NOTE: Use a '#' in the first column to comment out directories not compiled.
+#
+###
+
+default:
+	cd contrib
+	$(MAKE) /f makefile.vc
+	cd ..
+	cd csm
+#	$(MAKE) /f makefile.vc
+	cd ..
+	cd gdal
+	$(MAKE) /f makefile.vc
+	cd ..
+	cd kakadu
+	$(MAKE) /f makefile.vc
+	cd ..
+	cd mrsid
+#	$(MAKE) /f makefile.vc
+	cd ..
+	cd ndf
+	$(MAKE) /f makefile.vc
+	cd ..
+	cd nitro
+#	$(MAKE) /f makefile.vc
+	cd ..	
+	cd nui
+#	$(MAKE) /f makefile.vc
+	cd ..
+	cd openjpeg
+#	$(MAKE) /f makefile.vc
+	cd ..
+	cd ossim
+	$(MAKE) /f makefile.vc
+	cd ..
+	cd png
+	$(MAKE) /f makefile.vc
+	cd ..
+	cd registration
+	$(MAKE) /f makefile.vc
+	cd ..
+	cd worldwind
+#	$(MAKE) /f makefile.vc
+	cd ..
+
+clean:
+	cd contrib
+	$(MAKE) /f makefile.vc clean
+	cd ..
+	cd csm
+#	$(MAKE) /f makefile.vc clean
+	cd ..
+	cd gdal
+	$(MAKE) /f makefile.vc clean
+	cd ..
+	cd kakadu
+	$(MAKE) /f makefile.vc clean
+	cd ..
+	cd mrsid
+#	$(MAKE) /f makefile.vc clean
+	cd ..
+	cd ndf
+	$(MAKE) /f makefile.vc clean
+	cd ..
+	cd nitro
+#	$(MAKE) /f makefile.vc clean
+	cd ..	
+	cd nui
+#	$(MAKE) /f makefile.vc clean
+	cd ..
+	cd openjpeg
+#	$(MAKE) /f makefile.vc clean
+	cd ..
+	cd ossim
+	$(MAKE) /f makefile.vc clean
+	cd ..
+	cd png
+	$(MAKE) /f makefile.vc clean
+	cd ..
+	cd registration
+	$(MAKE) /f makefile.vc clean
+	cd ..
+	cd worldwind
+#	$(MAKE) /f makefile.vc clean
+	cd ..
+
+install:
+	cd contrib
+	$(MAKE) /f makefile.vc install
+	cd ..
+	cd csm
+#	$(MAKE) /f makefile.vc install
+	cd ..
+	cd gdal
+	$(MAKE) /f makefile.vc install
+	cd ..
+	cd kakadu
+	$(MAKE) /f makefile.vc install
+	cd ..
+	cd mrsid
+#	$(MAKE) /f makefile.vc install
+	cd ..
+	cd ndf
+	$(MAKE) /f makefile.vc install
+	cd ..
+	cd nitro
+#	$(MAKE) /f makefile.vc install
+	cd ..	
+	cd nui
+#	$(MAKE) /f makefile.vc install
+	cd ..
+	cd openjpeg
+#	$(MAKE) /f makefile.vc install
+	cd ..
+	cd ossim
+	$(MAKE) /f makefile.vc install
+	cd ..
+	cd png
+	$(MAKE) /f makefile.vc install
+	cd ..
+	cd registration
+	$(MAKE) /f makefile.vc install
+	cd ..
+	cd worldwind
+#	$(MAKE) /f makefile.vc install
+	cd ..
diff --git a/ossim_plugins/mrsid/CMakeLists.txt b/ossim_plugins/mrsid/CMakeLists.txt
new file mode 100644
index 0000000..a135ff5
--- /dev/null
+++ b/ossim_plugins/mrsid/CMakeLists.txt
@@ -0,0 +1,63 @@
+set(LIB_NAME ossimmrsid_plugin)
+MESSAGE( "************** LIBRARY SETUP FOR ossimmrsid_plugin******************")
+
+# Include ossim cmake stuff:
+include(OssimVersion)
+include(OssimCommonVariables)
+include(OssimUtilities)
+
+set(requiredLibs)
+
+find_package(MrSid)
+if(MRSID_FOUND)
+   include_directories(${CMAKE_CURRENT_SOURCE_DIR})
+   include_directories(${MRSID_INCLUDE_DIR})
+   set( requiredLibs ${requiredLibs} ${MRSID_LIBRARIES} )
+else(MRSID_FOUND)
+   message(FATAL_ERROR "Could not find mrsid")
+endif(MRSID_FOUND)
+
+MESSAGE( STATUS "MRSID_LIBRARIES     = ${MRSID_LIBRARIES}" )
+MESSAGE( STATUS "MRSID_INCLUDE       = ${MRSID_INCLUDE_DIR}" )
+MESSAGE( STATUS "MRSID_WRITE_FOUND   = ${MRSID_WRITE_FOUND}" )
+
+find_package(GDAL)
+if(GDAL_FOUND)
+   include_directories(${GDAL_INCLUDE_DIR})
+   set( requiredLibs ${requiredLibs} ${GDAL_LIBRARY} )
+else(GDAL_FOUND)
+    message( FATAL_ERROR "Could not find gdal" )
+endif(GDAL_FOUND)
+
+# OSSIM - Required: 
+find_package(ossim)
+if(OSSIM_FOUND)
+   include_directories( ${OSSIM_INCLUDE_DIR} )
+   set( requiredLibs ${requiredLibs} ${OSSIM_LIBRARIES} )
+else(OSSIM_FOUND)
+   message(FATAL_ERROR "Could not find ossim")
+endif(OSSIM_FOUND)
+
+####
+# OSSIMPLUGINSMAKINGDLL controls dll linkage on windows.  
+# Adding this sets OSSIM_PLUGINS_DLL #define TO "__declspec(dllexport)".
+###
+add_definitions("-DOSSIMPLUGINSMAKINGDLL")
+
+FILE(GLOB_RECURSE OSSIMPLUGIN_SRCS *.cpp)
+FILE(GLOB_RECURSE OSSIMPLUGIN_HEADERS *.h)
+
+# Adjust the install library path:
+if(OSSIM_INSTALL_PLUGINS_WITH_VERSION)
+   set(INSTALL_LIBRARY_DIR   "${INSTALL_LIBRARY_DIR}/ossim-${OSSIM_VERSION}/plugins")
+else(OSSIM_INSTALL_PLUGINS_WITH_VERSION)
+   set(INSTALL_LIBRARY_DIR   "${INSTALL_LIBRARY_DIR}/ossim/plugins")
+endif(OSSIM_INSTALL_PLUGINS_WITH_VERSION)
+
+OSSIM_LINK_LIBRARY(${LIB_NAME}
+                   COMPONENT_NAME ossim TYPE "${OSSIM_PLUGIN_LINK_TYPE}"
+		   LIBRARIES ${requiredLibs} 
+                   HEADERS "${OSSIMPLUGIN_HEADERS}"
+		   SOURCE_FILES "${OSSIMPLUGIN_SRCS}"
+                   INSTALL_LIB)
+
diff --git a/ossim_plugins/mrsid/ossimMG4LidarReader.cpp b/ossim_plugins/mrsid/ossimMG4LidarReader.cpp
new file mode 100644
index 0000000..39dc020
--- /dev/null
+++ b/ossim_plugins/mrsid/ossimMG4LidarReader.cpp
@@ -0,0 +1,602 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Description:  Class definition for MRSID MG4 reader.
+//
+// Author: Mingjie Su
+//
+//----------------------------------------------------------------------------
+// $Id: ossimMG4LidarReader.cpp 2645 2011-05-26 15:21:34Z oscar.kramer $
+
+#include <fstream>
+#include <iostream>
+#include <string>
+
+//ossim includes
+#include <ossim/base/ossimCommon.h>
+#include <ossim/base/ossimDpt.h>
+#include <ossim/base/ossimEndian.h>
+#include <ossim/base/ossimException.h>
+#include <ossim/base/ossimIoStream.h>
+#include <ossim/base/ossimKeywordlist.h>
+#include <ossim/base/ossimNotify.h>
+#include <ossim/base/ossimScalarTypeLut.h>
+#include <ossim/base/ossimTrace.h>
+#include <ossim/base/ossimUnitTypeLut.h>
+
+#include <ossim/imaging/ossimImageDataFactory.h>
+#include <ossim/imaging/ossimImageGeometryRegistry.h>
+
+#include <ossim/projection/ossimProjection.h>
+#include <ossim/projection/ossimProjectionFactoryRegistry.h>
+#include <ossim/projection/ossimEpsgProjectionFactory.h>
+#include <ossim/projection/ossimUtmProjection.h>
+
+#include <ossim/support_data/ossimAuxFileHandler.h>
+#include <ogr_spatialref.h>
+
+#include "ossimMG4LidarReader.h"
+
+#ifdef OSSIM_ID_ENABLED
+static const char OSSIM_ID[] = "$Id";
+#endif
+
+// Resolution Ratio between adjacent levels.
+
+static double maxRasterSize = 2048.0;
+static double maxBlockSideSize = 1024.0;
+
+static ossimTrace traceDebug("ossimMG4LidarReader:debug");
+static ossimTrace traceDump("ossimMG4LidarReader:dump");
+//static ossimOgcWktTranslator wktTranslator;
+
+RTTI_DEF1_INST(ossimMG4LidarReader,
+   "ossimMG4LidarReader",
+   ossimImageHandler)
+
+   ossimMG4LidarReader::ossimMG4LidarReader()
+   : ossimImageHandler(),
+   m_reader(NULL),
+   m_imageRect(),
+   m_numberOfSamples(0),
+   m_numberOfLines(0),
+   m_scalarType(OSSIM_SCALAR_UNKNOWN),
+   m_tile(0)
+{
+}
+
+ossimMG4LidarReader::~ossimMG4LidarReader()
+{
+   closeEntry();
+}
+
+ossimString ossimMG4LidarReader::getShortName()const
+{
+   return ossimString("ossim_mg4_lidar_reader");
+}
+
+ossimString ossimMG4LidarReader::getLongName()const
+{
+   return ossimString("ossim mg4 lidar reader");
+}
+
+ossimString ossimMG4LidarReader::getClassName()const
+{
+   return ossimString("ossimMG4LidarReader");
+}
+
+ossim_uint32 ossimMG4LidarReader::getNumberOfDecimationLevels()const
+{
+   ossim_uint32 result = 1; // Add r0
+
+   if (theOverview.valid())
+   {
+      //---
+      // Add external overviews.
+      //---
+      result += theOverview->getNumberOfDecimationLevels();
+   }
+
+   return result;
+}
+
+ossim_uint32 ossimMG4LidarReader::getNumberOfLines(
+   ossim_uint32 resLevel) const
+{
+   if (theOverview.valid())
+   {
+      return theOverview->getNumberOfSamples(resLevel);
+   }
+   return m_numberOfLines;
+}
+
+ossim_uint32 ossimMG4LidarReader::getNumberOfSamples(
+   ossim_uint32 resLevel) const
+{
+   if (theOverview.valid())
+   {
+      return theOverview->getNumberOfSamples(resLevel);
+   }
+   return m_numberOfSamples;
+}
+
+bool ossimMG4LidarReader::open()
+{
+   static const char MODULE[] = "ossimMG4LidarReader::open";
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " entered...\n"
+         << "image: " << theImageFile << "\n";
+   }
+
+   bool result = false;
+
+   if(isOpen())
+   {
+      closeEntry();
+   }
+
+   int gen = 0;
+   bool raster = false;
+   result = Version::getMrSIDFileVersion(theImageFile.c_str(), gen, raster);
+   if (result == false)
+   {
+      return result;
+   }
+
+   m_reader = MG4PointReader::create();
+   m_reader->init(theImageFile.c_str());
+   m_bounds = m_reader->getBounds();
+
+   int numPoints = m_reader->getNumPoints();
+   m_numberOfSamples = m_bounds.x.length();
+   m_numberOfLines = m_bounds.y.length();
+
+   double pts_per_area = ((double)m_reader->getNumPoints())/(m_bounds.x.length()*m_bounds.y.length());
+   double average_pt_spacing = sqrt(1.0 / pts_per_area) ;
+   double cell_side = average_pt_spacing;
+   maxRasterSize = std::max(m_bounds.x.length()/cell_side, m_bounds.y.length()/cell_side);
+   //openZoomLevel(0);
+
+   //get data type from X channel as default
+   getDataType(0);
+
+   if (m_scalarType != OSSIM_SCALAR_UNKNOWN)
+   {
+      m_tile = ossimImageDataFactory::instance()->create(this, this);
+
+      m_tile->initialize();
+
+      // Call the base complete open to pick up overviews.
+      completeOpen();
+
+      result = true;
+   }
+
+   if (result == false)
+   {
+      closeEntry();
+   }
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " exit status = " << (result?"true":"false\n")
+         << std::endl;
+   }
+
+   return result;
+}
+
+void ossimMG4LidarReader::openZoomLevel(ossim_int32 zoom)
+{
+   // geo dimensions
+   const double gWidth = m_reader->getBounds().x.length() ;
+   const double gHeight = m_reader->getBounds().y.length() ;
+
+   // geo res
+   double xRes = pow(2.0, zoom) * gWidth / maxRasterSize ;
+   double yRes = pow(2.0, zoom) * gHeight / maxRasterSize ;
+   xRes = yRes = std::max(xRes, yRes);
+
+   // pixel dimensions
+   m_numberOfSamples  = static_cast<int>(gWidth / xRes  + 0.5);
+   m_numberOfLines  = static_cast<int>(gHeight / yRes + 0.5);
+}
+
+bool ossimMG4LidarReader::isOpen()const
+{
+   return m_tile.get();
+}
+
+void ossimMG4LidarReader::closeEntry()
+{
+   m_tile = 0;
+
+   if (m_reader)
+   {
+      RELEASE(m_reader);
+      m_reader = 0;
+   }
+   ossimImageHandler::close();
+}
+
+ossimRefPtr<ossimImageData> ossimMG4LidarReader::getTile(
+   const ossimIrect& rect, ossim_uint32 resLevel)
+{
+   // This tile source bypassed, or invalid res level, return null tile.
+   if(!isSourceEnabled() || !isOpen() || !isValidRLevel(resLevel))
+   {
+      return ossimRefPtr<ossimImageData>();
+   }
+
+   ossimIrect imageBound = getBoundingRect(resLevel);
+   if(!rect.intersects(imageBound))
+   {
+      return ossimRefPtr<ossimImageData>();
+   }
+
+   // Check for overview.
+   if( resLevel > 0 )
+   {
+      if(theOverview.valid())
+      {
+         ossimRefPtr<ossimImageData> tileData = theOverview->getTile(rect, resLevel);
+         tileData->setScalarType(getOutputScalarType());
+         return tileData;
+      }
+   }
+
+   m_tile->setImageRectangle(rect);
+
+   // Compute clip rectangle with respect to the image bounds.
+   ossimIrect clipRect   = rect.clipToRect(imageBound);
+
+   if (rect.completely_within(clipRect) == false)
+   {
+      // Not filling whole tile so blank it out first.
+      m_tile->makeBlank();
+   }
+
+   // access the point cloud with PointSource::read()
+   const ossimDpt UL_PT(m_bounds.x.min + clipRect.ul().x, m_bounds.y.min + clipRect.ul().y);
+   const ossimDpt LR_PT(m_bounds.x.min + clipRect.ul().x + clipRect.width(), m_bounds.y.min + clipRect.ul().y + clipRect.height());
+
+   Bounds bounds(UL_PT.lon, LR_PT.lon, 
+      UL_PT.lat, LR_PT.lat,
+      -HUGE_VAL, +HUGE_VAL);
+
+   ossim_float32 fraction = 1.0/pow(2.0, (double)resLevel);
+
+   PointIterator* iter = m_reader->createIterator(bounds, fraction, m_reader->getPointInfo(), NULL);
+
+   // create a buffer to store the point data
+   PointData points;
+   points.init(m_reader->getPointInfo(), clipRect.width()*clipRect.height());
+
+   size_t count = 0;
+   ossimDpt lasPt;
+   double* dataValues = new double[clipRect.width()*clipRect.height()];
+   while((count = iter->getNextPoints(points)) != 0)
+   {
+      //loop through each point
+      for(size_t i = 0; i < count; i += 1)
+      {
+         const ChannelData* channelX = points.getChannel(CHANNEL_NAME_X);
+         const ChannelData* channelY = points.getChannel(CHANNEL_NAME_Y);
+         const ChannelData* channelZ = points.getChannel(CHANNEL_NAME_Z);
+
+         const void *dataX = channelX->getData();
+         const void *dataY = channelY->getData();
+         const void *dataZ = channelZ->getData();
+
+         lasPt.x = static_cast<const double*>(dataX)[i];
+         lasPt.y = static_cast<const double*>(dataY)[i];
+
+         ossim_int32 line = static_cast<ossim_int32>(lasPt.y - UL_PT.y);
+         ossim_int32 samp = static_cast<ossim_int32>(lasPt.x - UL_PT.x);
+         ossim_int32 bufIndex = line * clipRect.width() + samp;
+
+         if (bufIndex < clipRect.width()*clipRect.height())
+         {
+            dataValues[bufIndex] = static_cast<const double*>(dataZ)[i];
+         }
+      }
+   }
+   RELEASE(iter);
+
+   m_tile->loadBand((void*)dataValues, clipRect, 0);
+   m_tile->validate();
+
+   delete[] dataValues;
+
+   return m_tile;
+}
+
+ossim_uint32 ossimMG4LidarReader::getNumberOfInputBands() const
+{
+   return 1;
+}
+
+ossim_uint32 ossimMG4LidarReader::getNumberOfOutputBands()const
+{
+   return 1;
+}
+
+ossim_uint32 ossimMG4LidarReader::getImageTileWidth() const
+{
+   return 0;
+}
+
+ossim_uint32 ossimMG4LidarReader::getImageTileHeight() const
+{
+   return 0;
+}
+
+ossimScalarType ossimMG4LidarReader::getOutputScalarType() const
+{
+   return m_scalarType;
+}
+
+ossimRefPtr<ossimImageGeometry> ossimMG4LidarReader::getImageGeometry()
+{
+   if ( !theGeometry )
+   {
+      //---
+      // Check for external geom:
+      //---
+      theGeometry = getExternalImageGeometry();
+
+      if ( !theGeometry )
+      {
+         //---
+         // Check the internal geometry first to avoid a factory call.
+         //---
+         theGeometry = getInternalImageGeometry();
+
+         // At this point it is assured theGeometry is set.
+
+         // Check for set projection.
+         if ( !theGeometry->getProjection() )
+         {
+            // Try factories for projection.
+            ossimImageGeometryRegistry::instance()->extendGeometry(this);
+         }
+      }
+
+      // Set image things the geometry object should know about.
+      initImageParameters( theGeometry.get() );
+   }
+
+   return theGeometry;
+}
+
+ossimRefPtr<ossimImageGeometry> ossimMG4LidarReader::getInternalImageGeometry() const
+{
+   static const char MODULE[] = "ossimMG4LidarReader::getInternalImageGeometry";
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " entered...\n";
+   }
+
+   ossimRefPtr<ossimImageGeometry> geom = new ossimImageGeometry();
+
+   // Must cast away constness.
+   ossimMG4LidarReader* th = const_cast<ossimMG4LidarReader*>(this);
+   ossimRefPtr<ossimProjection> proj = th->getGeoProjection();
+
+   geom->setProjection(proj.get());
+
+   return geom;
+}
+
+bool ossimMG4LidarReader::loadState(const ossimKeywordlist& kwl,
+   const char* prefix)
+{
+   bool result = false;
+
+   if ( ossimImageHandler::loadState(kwl, prefix) )
+   {
+      result = open();
+   }
+
+   return result;
+}
+
+void ossimMG4LidarReader::getDataType(ossim_int32 channelId) 
+{
+   if (m_reader)
+   {
+      DataType pixelType = m_reader->getChannel(channelId).getDataType();
+      switch (pixelType)
+      {
+      case DATATYPE_UINT8:
+         {
+            m_scalarType = OSSIM_UINT8;
+            break;
+         }
+      case DATATYPE_SINT8:
+         {
+            m_scalarType = OSSIM_SINT8;
+            break;
+         }
+      case DATATYPE_UINT16:
+         {
+            m_scalarType = OSSIM_UINT16;
+            break;
+         }
+      case DATATYPE_SINT16:
+         {
+            m_scalarType = OSSIM_SINT16;
+            break;
+         }
+      case DATATYPE_UINT32:
+         {
+            m_scalarType = OSSIM_UINT32;
+            break;
+         }
+      case DATATYPE_SINT32:
+         {
+            m_scalarType = OSSIM_SINT32;
+            break;
+         }
+      case DATATYPE_FLOAT32:
+         {
+            m_scalarType = OSSIM_FLOAT32;
+            break;
+         }
+      case DATATYPE_FLOAT64:
+         {
+            m_scalarType = OSSIM_FLOAT64;
+            break;
+         }
+      default:
+         {
+            m_scalarType = OSSIM_SCALAR_UNKNOWN;
+            break;
+         }
+      }
+   }
+}
+
+ossimProjection* ossimMG4LidarReader::getGeoProjection()
+{
+   ossimProjection* proj = NULL;
+   if (m_reader)
+   {
+      const char* wkt = m_reader->getWKT();
+      if (wkt)
+      {
+         OGRSpatialReferenceH  hSRS = NULL;
+
+         //Translate the WKT into an OGRSpatialReference. 
+         hSRS = OSRNewSpatialReference(NULL);
+         if(OSRImportFromWkt( hSRS, (char**)&wkt) != OGRERR_NONE)
+         {
+            OSRDestroySpatialReference( hSRS );
+            return NULL;
+         }
+
+         //Determine if State Plane Coordinate System
+         const char* epsg_code = OSRGetAttrValue(hSRS, "AUTHORITY", 1);
+         proj = ossimProjectionFactoryRegistry::instance()->createProjection(ossimString(epsg_code));
+
+         //get unit type
+         ossimUnitType unitType = OSSIM_METERS;
+         const char* units = OSRGetAttrValue(hSRS, "UNIT", 0);
+         bool bGeog = OSRIsGeographic(hSRS);
+         if (bGeog == false)
+         {
+            if ( units != NULL )
+            {
+               // Down case to avoid case mismatch.
+               ossimString s = units;
+               s.downcase();
+
+               if( ( s == ossimString("us survey foot") ) ||
+                  ( s == ossimString("u.s. foot") ) ||
+                  ( s == ossimString("foot_us") ) )
+               {
+                  unitType = OSSIM_US_SURVEY_FEET;
+               }
+               else if( s == ossimString("degree") )
+               {
+                  unitType = OSSIM_DEGREES;
+               }
+               else if( s == ossimString("feet") )
+               {
+                  unitType = OSSIM_FEET;
+               }
+            }
+         }
+         else
+         {
+            unitType = OSSIM_DEGREES;
+         }
+
+         //set ul tie point and gsd
+         ossimMapProjection* mapProj = dynamic_cast<ossimMapProjection*>(proj);
+         if (mapProj)
+         {
+            double xMin = m_reader->getBounds().x.min;
+            double yMax = m_reader->getBounds().y.max;
+            double xRes = m_reader->getBounds().x.length()/m_numberOfSamples;
+            double yRes = m_reader->getBounds().y.length()/m_numberOfLines;
+            ossimDpt gsd(xRes, yRes);
+            if (mapProj->isGeographic())
+            {
+               ossimGpt tie(yMax, xMin);
+               mapProj->setUlTiePoints(tie);
+               mapProj->setDecimalDegreesPerPixel(gsd);
+            }
+            else
+            {
+               ossimDpt tie(xMin, yMax);
+               if ( unitType == OSSIM_US_SURVEY_FEET)
+               {
+                  gsd = gsd * US_METERS_PER_FT;
+                  tie = tie * US_METERS_PER_FT;
+               }
+               else if ( unitType == OSSIM_FEET )
+               {
+                  gsd = gsd * MTRS_PER_FT;
+                  tie = tie * MTRS_PER_FT;
+               }
+               mapProj->setUlTiePoints(tie);
+               mapProj->setMetersPerPixel(gsd);
+            }
+         }
+         return proj;
+      }
+   }
+   return proj;
+}
+
+template<typename DTYPE>
+const DTYPE ossimMG4LidarReader::getChannelElement(const ChannelData* channel, size_t idx)
+{
+   DTYPE retval = static_cast<DTYPE>(0);
+   switch (channel->getDataType())
+   {
+   case (DATATYPE_FLOAT64):
+      retval = static_cast<DTYPE>(static_cast<const double*>(channel->getData())[idx]);
+      break;
+   case (DATATYPE_FLOAT32):
+      retval = static_cast<DTYPE>(static_cast<const float *>(channel->getData())[idx]);
+      break;
+   case (DATATYPE_SINT32):
+      retval = static_cast<DTYPE>(static_cast<const long *>(channel->getData())[idx]);
+      break;
+   case (DATATYPE_UINT32):
+      retval = static_cast<DTYPE>(static_cast<const unsigned long *>(channel->getData())[idx]);
+      break;
+   case (DATATYPE_SINT16):
+      retval = static_cast<DTYPE>(static_cast<const short *>(channel->getData())[idx]);
+      break;
+   case (DATATYPE_UINT16):
+      retval = static_cast<DTYPE>(static_cast<const unsigned short *>(channel->getData())[idx]);
+      break;
+   case (DATATYPE_SINT8):
+      retval = static_cast<DTYPE>(static_cast<const char *>(channel->getData())[idx]);
+      break;
+   case (DATATYPE_UINT8):
+      retval = static_cast<DTYPE>(static_cast<const unsigned char *>(channel->getData())[idx]);
+      break;
+   case (DATATYPE_SINT64):
+      retval = static_cast<DTYPE>(static_cast<const GIntBig *>(channel->getData())[idx]);
+      break;
+   case (DATATYPE_UINT64):
+      retval = static_cast<DTYPE>(static_cast<const GUIntBig *>(channel->getData())[idx]);
+      break;
+   default:
+      break;
+   }
+   return retval;
+}
+
+
diff --git a/ossim_plugins/mrsid/ossimMG4LidarReader.h b/ossim_plugins/mrsid/ossimMG4LidarReader.h
new file mode 100644
index 0000000..f5770e2
--- /dev/null
+++ b/ossim_plugins/mrsid/ossimMG4LidarReader.h
@@ -0,0 +1,210 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Description:  Class declaration MrSID MG4 reader.
+//
+// Author: Mingjie Su
+//
+// Specification: ISO/IEC 15444
+//
+//----------------------------------------------------------------------------
+// $Id: ossimMG4LidarReader.h 1524 2010-10-29 19:31:54Z ming.su$
+
+#ifndef ossimMG4LidarReader_HEADER
+#define ossimMG4LidarReader_HEADER 1
+
+#include <float.h>
+#include "../ossimPluginConstants.h"
+#include <ossim/base/ossimIpt.h>
+#include <ossim/base/ossimIrect.h>
+#include <ossim/imaging/ossimImageHandler.h>
+#include <ossim/support_data/ossimJ2kSizRecord.h>
+#include <ossim/imaging/ossimAppFixedTileCache.h>
+
+//LizardTech Includes
+#include <lidar/MG4PointReader.h>
+#include <lidar/Error.h>
+#include <lidar/Version.h>
+
+LT_USE_LIDAR_NAMESPACE
+
+// Forward class declarations.
+class ossimImageData;
+class ossimDpt;
+
+class OSSIM_PLUGINS_DLL ossimMG4LidarReader : public ossimImageHandler
+{
+public:
+
+   /** default construtor */
+   ossimMG4LidarReader();
+   
+   /** virtural destructor */
+   virtual ~ossimMG4LidarReader();
+
+   /**
+    * @brief Returns short name.
+    * @return "ossim_mrsid_reader"
+    */
+   virtual ossimString getShortName() const;
+   
+   /**
+    * @brief Returns long  name.
+    * @return "ossim mrsid reader"
+    */
+   virtual ossimString getLongName()  const;
+
+   /**
+    * @brief Returns class name.
+    * @return "ossimMG4LidarReader"
+    */
+   virtual ossimString getClassName() const;
+
+   /**
+    *  @brief Method to grab a tile(rectangle) from image.
+    *
+    *  @param rect The zero based rectangle to grab.
+    *
+    *  @param resLevel The reduced resolution level to grab from.
+    *
+    *  @return The ref pointer with the image data pointer.
+    */
+   virtual ossimRefPtr<ossimImageData> getTile(const  ossimIrect& rect,
+                                               ossim_uint32 resLevel=0);
+
+   /**
+    *  Returns the number of bands in the image.
+    *  Satisfies pure virtual from ImageHandler class.
+    */
+   virtual ossim_uint32 getNumberOfInputBands() const;
+
+   /**
+    * Returns the number of bands in a tile returned from this TileSource.
+    * Note: we are supporting sources that can have multiple data objects.
+    * If you want to know the scalar type of an object you can pass in the
+    */
+   virtual ossim_uint32 getNumberOfOutputBands()const; 
+   /**
+    * Returns the tile width of the image or 0 if the image is not tiled.
+    * Note: this is not the same as the ossimImageSource::getTileWidth which
+    * returns the output tile width which can be different than the internal
+    * image tile width on disk.
+    */
+   virtual ossim_uint32 getImageTileWidth() const;
+
+   /**
+    * Returns the tile width of the image or 0 if the image is not tiled.
+    * Note: this is not the same as the ossimImageSource::getTileHeight which
+    * returns the output tile height which can be different than the internal
+    * image tile height on disk.
+    */
+   virtual ossim_uint32 getImageTileHeight() const;
+
+   /**
+    * Returns the output pixel type of the tile source.
+    */
+   virtual ossimScalarType getOutputScalarType() const;
+   
+
+   /**
+    * @brief Returns the number of decimation levels.
+    * 
+    * This returns the total number of decimation levels.  It is important to
+    * note that res level 0 or full resolution is included in the list and has
+    * decimation values 1.0, 1.0
+    * 
+    * @return The number of decimation levels.
+    */
+   virtual ossim_uint32 getNumberOfDecimationLevels()const;
+
+   /**
+    * @brief Gets number of lines for res level.
+    *
+    *  @param resLevel Reduced resolution level to return lines of.
+    *  Default = 0
+    *
+    *  @return The number of lines for specified reduced resolution level.
+    */
+   virtual ossim_uint32 getNumberOfLines(ossim_uint32 resLevel = 0) const;
+
+   /**
+    *  @brief Gets the number of samples for res level.
+    *
+    *  @param resLevel Reduced resolution level to return samples of.
+    *  Default = 0
+    *
+    *  @return The number of samples for specified reduced resolution level.
+    */
+   virtual ossim_uint32 getNumberOfSamples(ossim_uint32 resLevel = 0) const;
+
+   /**
+    * @brief Open method.
+    * @return true on success, false on error.
+    */
+   virtual bool open();
+
+   /**
+    *  @brief Method to test for open file stream.
+    *
+    *  @return true if open, false if not.
+    */
+   virtual bool isOpen()const;
+
+   /**
+    * @brief Method to close current entry.
+    *
+    * @note There is a bool kdu_compressed_source::close() and a
+    * void ossimImageHandler::close(); hence, a new close to avoid conflicting
+    * return types.
+    */
+   virtual void closeEntry();
+
+   /**
+    * Returns the image geometry object associated with this tile source or
+    * NULL if non defined.  The geometry contains full-to-local image
+    * transform as well as projection (image-to-world).
+    */
+   virtual ossimRefPtr<ossimImageGeometry> getImageGeometry();
+
+   /**
+    * @param Method to get geometry.
+    */
+   virtual ossimRefPtr<ossimImageGeometry> getInternalImageGeometry() const;
+
+   /**
+    * Method to the load (recreate) the state of an object from a keyword
+    * list.  Return true if ok or false on error.
+    */
+   virtual bool loadState(const ossimKeywordlist& kwl, const char* prefix=0);   
+
+private:
+
+  ossimProjection* getGeoProjection();
+
+  void getDataType(ossim_int32 channelId);
+
+  void openZoomLevel(ossim_int32 zoom);
+
+  template<typename DTYPE>
+     const DTYPE getChannelElement(const ChannelData* channel, size_t idx);
+
+  MG4PointReader*              m_reader;
+  Bounds                       m_bounds;
+  ossimIrect                   m_imageRect; /** Has sub image offset. */
+
+  ossim_uint32                 m_numberOfSamples;
+  ossim_uint32                 m_numberOfLines;
+  ossimScalarType              m_scalarType;
+  ossimRefPtr<ossimImageData>  m_tile;
+TYPE_DATA
+};
+
+#endif /* #ifndef ossimMG4LidarReader_HEADER */
+
+
+
+
+
diff --git a/ossim_plugins/mrsid/ossimMrSidPluginInit.cpp b/ossim_plugins/mrsid/ossimMrSidPluginInit.cpp
new file mode 100644
index 0000000..5b57a89
--- /dev/null
+++ b/ossim_plugins/mrsid/ossimMrSidPluginInit.cpp
@@ -0,0 +1,90 @@
+//----------------------------------------------------------------------------
+//
+// License:  See top level LICENSE.txt file
+//
+// Author:  Mingjie Su
+//
+// Description: OSSIM MrSID plugin initialization
+// code.
+//
+//----------------------------------------------------------------------------
+// $Id: ossimMrSidPluginInit.cpp 899 2010-05-17 21:00:26Z david.burken $
+
+#include <ossim/plugin/ossimSharedObjectBridge.h>
+#include "../ossimPluginConstants.h"
+#include <ossim/imaging/ossimImageHandlerRegistry.h>
+#include <ossim/imaging/ossimImageWriterFactoryRegistry.h>
+#include <ossim/imaging/ossimOverviewBuilderFactoryRegistry.h>
+
+#include "ossimMrSidReaderFactory.h"
+#include "ossimMrSidWriterFactory.h"
+
+static void setDescription(ossimString& description)
+{
+#ifdef OSSIM_ENABLE_MRSID_WRITE 
+   description = "MrSid reader / writer plugin\n\n";
+#else
+   description = "MrSid reader plugin\n\n";
+#endif
+}
+
+extern "C"
+{
+   ossimSharedObjectInfo  myInfo;
+   ossimString theDescription;
+   std::vector<ossimString> theObjList;
+
+   const char* getDescription()
+   {
+      return theDescription.c_str();
+   }
+
+   int getNumberOfClassNames()
+   {
+      return (int)theObjList.size();
+   }
+
+   const char* getClassName(int idx)
+   {
+      if(idx < (int)theObjList.size())
+      {
+         return theObjList[0].c_str();
+      }
+      return (const char*)0;
+   }
+
+   /* Note symbols need to be exported on windoze... */ 
+   OSSIM_PLUGINS_DLL void ossimSharedLibraryInitialize(
+      ossimSharedObjectInfo** info)
+   {    
+      myInfo.getDescription = getDescription;
+      myInfo.getNumberOfClassNames = getNumberOfClassNames;
+      myInfo.getClassName = getClassName;
+      
+      *info = &myInfo;
+      
+      /* Register the readers... */
+      ossimImageHandlerRegistry::instance()->
+         registerFactory(ossimMrSidReaderFactory::instance(), false);
+
+#ifdef OSSIM_ENABLE_MRSID_WRITE
+      /* Register the writers... */
+      ossimImageWriterFactoryRegistry::instance()->
+         registerFactory(ossimMrSidWriterFactory::instance());
+#endif
+      
+      setDescription(theDescription);
+   }
+   
+   /* Note symbols need to be exported on windoze... */ 
+   OSSIM_PLUGINS_DLL void ossimSharedLibraryFinalize()
+   {
+      ossimImageHandlerRegistry::instance()->
+         unregisterFactory(ossimMrSidReaderFactory::instance());
+
+#ifdef OSSIM_ENABLE_MRSID_WRITE      
+      ossimImageWriterFactoryRegistry::instance()->
+         unregisterFactory(ossimMrSidWriterFactory::instance());
+#endif
+   }
+}
diff --git a/ossim_plugins/mrsid/ossimMrSidReader.cpp b/ossim_plugins/mrsid/ossimMrSidReader.cpp
new file mode 100644
index 0000000..4c9bfd2
--- /dev/null
+++ b/ossim_plugins/mrsid/ossimMrSidReader.cpp
@@ -0,0 +1,1002 @@
+ //----------------------------------------------------------------------------
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Description:  Class definition for MRSID reader.
+//
+//----------------------------------------------------------------------------
+// $Id: ossimMrSidReader.cpp 2645 2011-05-26 15:21:34Z oscar.kramer $
+
+
+#include "ossimMrSidReader.h"
+
+//ossim includes
+#include <ossim/base/ossimCommon.h>
+#include <ossim/base/ossimDpt.h>
+#include <ossim/base/ossimEndian.h>
+#include <ossim/base/ossimException.h>
+#include <ossim/base/ossimIoStream.h>
+#include <ossim/base/ossimKeywordlist.h>
+#include <ossim/base/ossimNotify.h>
+#include <ossim/base/ossimScalarTypeLut.h>
+#include <ossim/base/ossimTrace.h>
+#include <ossim/base/ossimUnitTypeLut.h>
+
+#include <ossim/imaging/ossimImageDataFactory.h>
+#include <ossim/imaging/ossimImageGeometryRegistry.h>
+
+#include <ossim/projection/ossimProjection.h>
+#include <ossim/projection/ossimProjectionFactoryRegistry.h>
+#include <ossim/projection/ossimEpsgProjectionFactory.h>
+#include <ossim/projection/ossimUtmProjection.h>
+
+#include <ossim/support_data/ossimAuxFileHandler.h>
+#include <ossim/support_data/ossimAuxXmlSupportData.h>
+#include <ossim/support_data/ossimWkt.h>
+
+//LizardTech Includes
+#include <lt_base.h>
+#include <lt_fileSpec.h>
+#include <lt_ioFileStream.h>
+#include <lti_imageReader.h>
+#include <lti_pixel.h>
+#include <lti_scene.h>
+#include <lti_sceneBuffer.h>
+#include <lt_fileSpec.h>
+#include <lti_geoCoord.h>
+#include <lt_ioFileStream.h>
+#include <lti_pixelLookupTable.h>
+#include <lti_utils.h>
+#include <lti_metadataDatabase.h>
+#include <lti_metadataRecord.h>
+
+// System:
+#include <fstream>
+#include <iostream>
+#include <string>
+
+#ifdef OSSIM_ID_ENABLED
+static const char OSSIM_ID[] = "$Id";
+#endif
+ 
+static ossimTrace traceDebug("ossimMrSidReader:debug");
+static ossimTrace traceDump("ossimMrSidReader:dump");
+//static ossimOgcWktTranslator wktTranslator;
+
+RTTI_DEF1_INST(ossimMrSidReader,
+               "ossimMrSidReader",
+               ossimImageHandler)
+ 
+ossimMrSidReader::ossimMrSidReader()
+   : ossimImageHandler(),
+     theReader(0),
+     theImageNavigator(0),
+     theMinDwtLevels(0),
+     theImageRect(),
+     theMrSidDims(),
+     theNumberOfBands(0),
+     theScalarType(OSSIM_SCALAR_UNKNOWN),
+     theTile(0)
+{
+}
+
+ossimMrSidReader::~ossimMrSidReader()
+{
+   closeEntry();
+
+   // Note: Not a ref ptr.  This is a  MrSIDImageReader*.
+   if ( theReader )
+   {
+      theReader->release();
+      theReader = 0;
+   }
+   if (theImageNavigator != 0)
+   {
+      delete theImageNavigator;
+      theImageNavigator = 0;
+   }
+}
+
+ossimString ossimMrSidReader::getShortName()const
+{
+   return ossimString("ossim_mrsid_reader");
+}
+
+ossimString ossimMrSidReader::getLongName()const
+{
+   return ossimString("ossim mrsid reader");
+}
+
+ossimString ossimMrSidReader::getClassName()const
+{
+   return ossimString("ossimMrSidReader");
+}
+
+void ossimMrSidReader::getDecimationFactor(ossim_uint32 resLevel,
+                                           ossimDpt& result) const
+{
+   if (theGeometry.valid())
+   {
+      theGeometry->decimationFactor(resLevel, result);
+   }
+   else
+   {
+      result.makeNan();
+   }
+}
+
+void ossimMrSidReader::getDecimationFactors(
+   vector<ossimDpt>& decimations) const
+{
+   if (theGeometry.valid())
+   {
+      if ( theGeometry->getNumberOfDecimations() )
+      {
+         theGeometry->decimationFactors(decimations);
+      }
+      else
+      {
+         // First time called...
+         if ( computeDecimationFactors(decimations) )
+         {
+            theGeometry->setDiscreteDecimation(decimations);
+         }
+         else
+         {
+            decimations.clear();
+         }
+      }
+   }
+   else
+   {
+      if ( !computeDecimationFactors(decimations) )
+      {
+         decimations.clear();
+      }
+   }
+}
+
+ossim_uint32 ossimMrSidReader::getNumberOfDecimationLevels()const
+{
+   ossim_uint32 result = 1; // Add r0
+   
+   if (theMinDwtLevels)
+   {
+      //---
+      // Add internal overviews.
+      //---
+      result += theMinDwtLevels;
+   }
+
+   if (theOverview.valid())
+   {
+      //---
+      // Add external overviews.
+      //---
+      result += theOverview->getNumberOfDecimationLevels();
+   }
+
+   return result;
+}
+
+ossim_uint32 ossimMrSidReader::getNumberOfLines(
+   ossim_uint32 resLevel) const
+{
+   ossim_uint32 result = 0;
+   if ( isValidRLevel(resLevel) )
+   {
+      if (resLevel <= theMinDwtLevels)
+      {
+         if (theMrSidDims.size() > 0)
+         {
+            result = theMrSidDims[resLevel].height();
+         }
+      }
+      else if (theOverview.valid())
+      {
+         result = theOverview->getNumberOfSamples(resLevel);
+      }
+   }
+   return result;
+}
+
+ossim_uint32 ossimMrSidReader::getNumberOfSamples(
+   ossim_uint32 resLevel) const
+{
+   ossim_uint32 result = 0;
+   if ( isValidRLevel(resLevel) )
+   {
+      if (resLevel <= theMinDwtLevels)
+      {
+         if (theMrSidDims.size() > 0)
+         {
+            result = theMrSidDims[resLevel].width();
+         }
+      }
+      else if (theOverview.valid())
+      {
+         result = theOverview->getNumberOfSamples(resLevel);
+      }
+   }
+   return result;
+}
+
+bool ossimMrSidReader::open()
+{
+   static const char MODULE[] = "ossimMrSidReader::open";
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " entered...\n"
+         << "image: " << theImageFile << "\n";
+   }
+   
+   bool result = false;
+
+   if(isOpen())
+   {
+      closeEntry();
+   }
+
+   ossimString ext = theImageFile.ext();
+   ext.downcase();
+   if ( ext != "sid" )
+   {
+      return false;
+   }
+
+   LT_STATUS sts = LT_STS_Uninit;
+
+   const LTFileSpec fileSpec(theImageFile.c_str());
+ 
+   theReader = MrSIDImageReader::create();
+   sts = theReader->initialize(fileSpec, true);
+   if (LT_SUCCESS(sts) == false)
+   {
+      return false;
+   }
+
+   theImageNavigator = new LTINavigator(*theReader);
+
+   theImageRect = ossimIrect(0, 0, theReader->getWidth()-1, theReader->getHeight()-1);
+   theNumberOfBands = theReader->getNumBands();
+   theMinDwtLevels = theReader->getNumLevels();
+
+   getDataType();
+
+   if (getImageDimensions(theMrSidDims))
+   {
+      if (theScalarType != OSSIM_SCALAR_UNKNOWN)
+      {
+         ossim_uint32 width  = theReader->getWidth();
+         ossim_uint32 height = theReader->getHeight();
+
+         // Check for zero width, height.
+         if ( !width || !height )
+         {
+            ossimIpt tileSize;
+            ossim::defaultTileSize(tileSize);
+
+            width  = tileSize.x;
+            height = tileSize.y;
+         }
+
+         theTile = ossimImageDataFactory::instance()->create(this, this);
+
+         theTile->initialize();
+
+         // Call the base complete open to pick up overviews.
+         computeMinMax();
+         completeOpen();
+
+         result = true;
+      }
+   }
+
+   if (result == false)
+   {
+      closeEntry();
+   }
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " exit status = " << (result?"true":"false\n")
+         << std::endl;
+   }
+
+   return result;
+}
+
+bool ossimMrSidReader::isOpen()const
+{
+   return theTile.get();
+}
+
+void ossimMrSidReader::closeEntry()
+{
+   theTile = 0;
+   
+   ossimImageHandler::close();
+}
+
+ossimRefPtr<ossimImageData> ossimMrSidReader::getTile(
+   const ossimIrect& rect, ossim_uint32 resLevel)
+{
+   LT_STATUS sts = LT_STS_Uninit;
+
+   // This tile source bypassed, or invalid res level, return null tile.
+   if(!isSourceEnabled() || !isOpen() || !isValidRLevel(resLevel))
+   {
+      return ossimRefPtr<ossimImageData>();
+   }
+
+   ossimIrect imageBound = getBoundingRect(resLevel);
+   if(!rect.intersects(imageBound))
+   {
+      return ossimRefPtr<ossimImageData>();
+   }
+
+   // Check for overview.
+   if( resLevel > theMinDwtLevels )
+   {
+      if(theOverview.valid())
+      {
+         ossimRefPtr<ossimImageData> tileData = theOverview->getTile(rect, resLevel);
+         tileData->setScalarType(getOutputScalarType());
+         return tileData;
+      }
+   }
+
+   theTile->setImageRectangle(rect);
+
+   // Compute clip rectangle with respect to the image bounds.
+   ossimIrect clipRect   = rect.clipToRect(imageBound);
+
+   if (rect.completely_within(clipRect) == false)
+   {
+      // Not filling whole tile so blank it out first.
+      theTile->makeBlank();
+   }
+
+   lt_uint16 anOssimBandIndex = 0;
+
+   LTIPixel pixel(theReader->getColorSpace(), theNumberOfBands, theReader->getDataType());
+   LTISceneBuffer sceneBuffer(pixel, clipRect.width(), clipRect.height(), NULL);
+
+   if (!theGeometry.valid())
+   {
+      theGeometry = getImageGeometry();
+   }
+   double mag = theGeometry->decimationFactor(resLevel).lat;
+   sts = theImageNavigator->setSceneAsULWH(clipRect.ul().x,
+                                           clipRect.ul().y,
+                                           clipRect.lr().x - clipRect.ul().x + 1,
+                                           clipRect.lr().y - clipRect.ul().y + 1, mag);
+
+   LTIScene scene = theImageNavigator->getScene();
+   sts = theReader->read(scene, sceneBuffer);
+
+   if (LT_SUCCESS(sts) == true)
+   {
+      if(clipRect == rect)
+      {
+         void *buf = theTile->getBuf();
+         sceneBuffer.exportDataBSQ(buf);
+      }
+      else
+      {
+         for(anOssimBandIndex = 0; anOssimBandIndex < theNumberOfBands; anOssimBandIndex++)
+         {
+            theTile->loadBand(sceneBuffer.getBandData(anOssimBandIndex),//sceneBuffer.getTotalBandData(anOssimBandIndex),
+                              clipRect, anOssimBandIndex);
+         }
+      }
+   }
+
+   theTile->validate();
+   return theTile;
+}
+
+ossim_uint32 ossimMrSidReader::getNumberOfInputBands() const
+{
+   return theNumberOfBands;
+}
+
+ossim_uint32 ossimMrSidReader::getNumberOfOutputBands()const
+{
+   return theNumberOfBands;
+}
+
+ossim_uint32 ossimMrSidReader::getImageTileWidth() const
+{
+   ossim_uint32 result = 0;
+   if ( theMrSidDims.size() )
+   {
+      if ( theMrSidDims[0].width() != theImageRect.width() )
+      {
+         // Not a single tile.
+         result = theMrSidDims[0].width();
+      }
+   }
+   return result;
+}
+
+ossim_uint32 ossimMrSidReader::getImageTileHeight() const
+{
+   ossim_uint32 result = 0;
+   if ( theMrSidDims.size() )
+   {
+      if ( theMrSidDims[0].height() != theImageRect.height() )
+      {
+         // Not a single tile.
+         result = theMrSidDims[0].height();
+      }
+   }
+   return result;
+}
+
+ossimScalarType ossimMrSidReader::getOutputScalarType() const
+{
+   return theScalarType;
+}
+
+ossimRefPtr<ossimImageGeometry> ossimMrSidReader::getImageGeometry()
+{
+   if ( !theGeometry )
+   {
+      //---
+      // Check for external geom:
+      //---
+      theGeometry = getExternalImageGeometry();
+      
+      if ( !theGeometry )
+      {
+         //---
+         // Check the internal geometry first to avoid a factory call.
+         //---
+         theGeometry = getInternalImageGeometry();
+
+         // At this point it is assured theGeometry is set.
+
+         // Check for set projection.
+         if ( !theGeometry->getProjection() )
+         {
+            // Try factories for projection.
+            ossimImageGeometryRegistry::instance()->extendGeometry(this);
+         }
+      }
+
+      // Set image things the geometry object should know about.
+      initImageParameters( theGeometry.get() );
+   }
+
+   return theGeometry;
+}
+
+ossimRefPtr<ossimImageGeometry> ossimMrSidReader::getExternalImageGeometry() const
+{
+   // Check for external .geom file:
+   ossimRefPtr<ossimImageGeometry> geom = ossimImageHandler::getExternalImageGeometry();
+   if ( geom.valid() == false )
+   {
+      // Check for .aux.xml file:
+      ossimFilename auxXmlFile = theImageFile;
+      auxXmlFile += ".aux.xml";
+      if  ( auxXmlFile.exists() )
+      {
+         ossimAuxXmlSupportData sd;
+         ossimRefPtr<ossimProjection> proj = sd.getProjection( auxXmlFile );
+         if ( proj.valid() )
+         {
+            geom = new ossimImageGeometry();
+            geom->setProjection( proj.get() );
+         }
+      }
+   }
+   return geom;
+}
+
+ossimRefPtr<ossimImageGeometry> ossimMrSidReader::getInternalImageGeometry() const
+{
+   static const char MODULE[] = "ossimMrSidReader::getInternalImageGeometry";
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " entered...\n";
+   }
+
+   ossimRefPtr<ossimImageGeometry> geom = new ossimImageGeometry();
+
+   // Must cast away constness.
+   ossimMrSidReader* th = const_cast<ossimMrSidReader*>(this);
+   ossimRefPtr<ossimProjection> proj = th->getGeoProjection();
+
+   geom->setProjection(proj.get());
+
+   return geom;
+}
+
+bool ossimMrSidReader::computeDecimationFactors(
+   std::vector<ossimDpt>& decimations) const
+{
+   bool result = true;
+
+   decimations.clear();
+
+   const ossim_uint32 LEVELS = getNumberOfDecimationLevels();
+
+   for (ossim_uint32 level = 0; level < LEVELS; ++level)
+   {
+      ossimDpt pt;
+
+      if (level == 0)
+      {
+         // Assuming r0 is full res for now.
+         pt.x = 1.0;
+         pt.y = 1.0;
+      }
+      else
+      {
+         // Get the sample decimation.
+         ossim_float64 r0 = getNumberOfSamples(0);
+         ossim_float64 rL = getNumberOfSamples(level);
+         if ( (r0 > 0.0) && (rL > 0.0) )
+         {
+            pt.x = rL / r0;
+         }
+         else
+         {
+            result = false;
+            break;
+         }
+
+         // Get the line decimation.
+         r0 = getNumberOfLines(0);
+         rL = getNumberOfLines(level);
+         if ( (r0 > 0.0) && (rL > 0.0) )
+         {
+            pt.y = rL / r0;
+         }
+         else
+         {
+            result = false;
+            break;
+         }
+      }
+
+      decimations.push_back(pt);
+   }
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimMrSidReader::computeDecimationFactors DEBUG\n";
+      for (ossim_uint32 i = 0; i < decimations.size(); ++i)
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG)
+            << "decimation[" << i << "]: " << decimations[i]
+            << std::endl;
+      }
+   }
+
+   return result;
+}
+
+bool ossimMrSidReader::getImageDimensions(std::vector<ossimIrect>& tileDims) const
+{
+   bool result = true;
+
+   tileDims.clear();
+
+   if (theReader != 0)
+   {
+      ossim_uint32 levels = theReader->getNumLevels();
+
+      for (ossim_uint32 level=0; level <= levels; ++level)
+      {
+         lt_uint32 width = 0;
+         lt_uint32 height = 0;
+
+         double mag = LTIUtils::levelToMag(level);
+         LTIUtils::getDimsAtMag(theImageRect.width(), theImageRect.height(), mag, width, height);
+
+         // Make the imageRect upper left relative to any sub image offset.
+         ossimIrect imageRect(0, 0, width-1, height-1);
+
+         tileDims.push_back(imageRect);
+      }
+   }
+   else
+   {
+      result = false;
+   }
+
+   return result;
+}
+
+bool ossimMrSidReader::loadState(const ossimKeywordlist& kwl,
+                                 const char* prefix)
+{
+   bool result = false;
+
+   if ( ossimImageHandler::loadState(kwl, prefix) )
+   {
+      result = open();
+   }
+
+   return result;
+}
+
+void ossimMrSidReader::getDataType() 
+{
+   if (theReader != 0)
+   {
+      LTIDataType pixelType = theReader->getPixelProps().getDataType();   
+
+      LTIPixel pixel = theReader->getPixelProps();
+
+      switch (pixelType)
+      {
+         case LTI_DATATYPE_UINT8:
+         {
+            theScalarType = OSSIM_UINT8;
+            break;
+         }
+         case LTI_DATATYPE_SINT8:
+         {
+            theScalarType = OSSIM_SINT8;
+            break;
+         }
+         case LTI_DATATYPE_UINT16:
+         {
+            theScalarType = OSSIM_UINT16;
+            break;
+         }
+         case LTI_DATATYPE_SINT16:
+         {
+            theScalarType = OSSIM_SINT16;
+            break;
+         }
+         case LTI_DATATYPE_UINT32:
+         {
+            theScalarType = OSSIM_UINT32;
+            break;
+         }
+         case LTI_DATATYPE_SINT32:
+         {
+            theScalarType = OSSIM_SINT32;
+            break;
+         }
+         case LTI_DATATYPE_FLOAT32:
+         {
+            theScalarType = OSSIM_FLOAT32;
+            break;
+         }
+         case LTI_DATATYPE_FLOAT64:
+         {
+            theScalarType = OSSIM_FLOAT64;
+            break;
+         }
+         default:
+         {
+            theScalarType = OSSIM_SCALAR_UNKNOWN;
+            break;
+         }
+      }
+   }
+}
+
+ossimProjection* ossimMrSidReader::getGeoProjection()
+{
+   if (theReader == 0)
+      return 0;
+
+   // A local KWL will be filled as items are read from the support data. At the end,
+   // the projection factory will be provided with the populated KWL to instantiate proper 
+   // map projection. No prefix needed.
+   ossimKeywordlist kwl; 
+
+   // Add the lines and samples.
+   kwl.add(ossimKeywordNames::NUMBER_LINES_KW, getNumberOfLines(0));
+   kwl.add(ossimKeywordNames::NUMBER_SAMPLES_KW, getNumberOfSamples(0));
+
+   ossimString proj_type;
+   ossimString datum_type;
+   ossimString scale_units  = "unknown";
+   ossimString tie_pt_units = "unknown";
+
+   ossim_uint32 code = 0;
+   ossim_uint32 gcsCode = 0;
+   ossim_uint32 pcsCode = 0;
+
+   const LTIGeoCoord& geo = theReader->getGeoCoord();
+   LTIMetadataDatabase metaDb = theReader->getMetadata();
+
+#if 0 /* Please keep for debug. (drb) */
+   for (ossim_uint32 i = 0; i < metaDb.getIndexCount(); ++i )
+   {
+      const LTIMetadataRecord* rec = 0;
+      metaDb.getDataByIndex(i, rec);
+      cout << "rec.getTagName(): " << rec->getTagName() << endl;
+   }
+   const char* projStr = geo.getWKT();
+   if ( projStr )
+   {
+      std::string wktStr = projStr;
+      
+      cout << "wktStr: " << wktStr << endl;
+      ossimWkt wkt;
+      if ( wkt.open( wktStr ) )
+      {
+         cout << "kwl:\n" << wkt.getKwl() << endl;
+      }
+   }
+#endif
+   
+   // Can only handle non-rotated images since only projection object returned (no 2d transform):
+   if( (geo.getXRot() != 0.0) || (geo.getYRot() != 0.0))
+      return 0;
+
+   bool gcsFound = getMetadataElement(
+      metaDb, "GEOTIFF_NUM::2048::GeographicTypeGeoKey", &gcsCode);
+   bool pcsFound = getMetadataElement(
+      metaDb, "GEOTIFF_NUM::3072::ProjectedCSTypeGeoKey", &pcsCode);
+
+   if (gcsFound && !pcsFound)
+   {
+      code = gcsCode;
+      kwl.add(ossimKeywordNames::TYPE_KW, "ossimEquDistCylProjection");
+      proj_type = "ossimEquDistCylProjection";
+      kwl.add(ossimKeywordNames::PCS_CODE_KW, code);
+      tie_pt_units = "degrees";
+
+      // Assign units if set in Metadata
+      char unitStr[200];
+      if (getMetadataElement(metaDb, "GEOTIFF_CHAR::GeogAngularUnitsGeoKey",
+                             &unitStr, sizeof(unitStr)) == true)
+      {
+         ossimString unitTag(unitStr);
+         if ( unitTag.contains("Angular_Degree") ) // decimal degrees
+            scale_units = "degrees";
+         else if ( unitTag.contains("Angular_Minute") ) // decimal minutes
+            scale_units = "minutes";
+         else if ( unitTag.contains("Angular_Second") ) // decimal seconds
+            scale_units = "seconds";
+      }
+   }
+   else 
+   {
+      if (!pcsFound)
+      {
+         pcsFound = getMetadataElement(metaDb, "GEOTIFF_NUM::3074::ProjectionGeoKey", &code);
+      }
+      else
+      {
+        code = pcsCode;
+      }
+
+      if (pcsFound)
+      {
+         kwl.add(ossimKeywordNames::PCS_CODE_KW, code);
+
+         ossimString unitTag;
+
+         char unitStr[200];
+         if (getMetadataElement(metaDb, "GEOTIFF_CHAR::ProjLinearUnitsGeoKey", &unitStr, 
+                                sizeof(unitStr)) == true )
+         {
+            unitTag = unitStr;
+         }
+         else
+         {
+            // Have data with no ProjLinearUnitsGeoKey so try WKT string.
+            const char* wktProjStr = geo.getWKT();
+            if ( wktProjStr )
+            {
+               std::string wktStr = wktProjStr;
+               ossimWkt wkt;
+               if ( wkt.parse( wktStr ) )
+               {
+                  unitTag = wkt.getKwl().findKey( std::string("PROJCS.UNIT.name") );
+               }
+            }
+         }
+
+         if ( unitTag.size() )
+         {
+            unitTag.downcase();
+            
+            if ( unitTag.contains("meter") ||  unitTag.contains("metre") )
+            {
+               scale_units = "meters";
+            }
+            else if ( unitTag.contains("linear_foot_us_survey") )
+            {
+               scale_units = "us_survey_feet";
+            }
+            else if ( unitTag.contains("linear_foot") )
+            {
+               scale_units = "feet";
+            }
+            tie_pt_units = scale_units;
+         }
+         
+      }
+      else
+      {
+         // Try with WKT:
+         const char* projStr = geo.getWKT();
+         kwl.add(ossimKeywordNames::TYPE_KW, projStr);
+      }
+   }
+
+   char rasterTypeStr[200];
+   strcpy( rasterTypeStr, "unnamed" );
+   double topLeftX = geo.getX(); // AMBIGUOUS! OLK 5/10
+   double topLeftY = geo.getY(); // AMBIGUOUS! OLK 5/10
+   if (getMetadataElement(metaDb, "GEOTIFF_CHAR::GTRasterTypeGeoKey", &rasterTypeStr, sizeof(rasterTypeStr)) == true)
+   {
+      ossimString rasterTypeTag(rasterTypeStr);
+
+      // If the raster type is pixel_is_area, shift the tie point by
+      // half a pixel to locate it at the pixel center. 
+      if ( rasterTypeTag.contains("RasterPixelIsPoint") )
+      {
+         topLeftX -= geo.getXRes() / 2.0;  // AMBIGUOUS -- DOESN'T MATCH COMMENT! OLK 5/10
+         topLeftY += geo.getYRes() / 2.0;  // AMBIGUOUS! OLK 5/10
+      }
+   }
+   ossimDpt gsd(fabs(geo.getXRes()), fabs(geo.getYRes()));
+   ossimDpt tie(topLeftX, topLeftY);
+
+   // CANNOT HANDLE 2D TRANSFORMS -- ONLY REAL PROJECTIONS. (OLK 5/10)
+   //std::stringstream mString;
+   //// store as a 4x4 matrix
+   //mString << ossimString::toString(geo.getXRes(), 20)
+   //  << " " << ossimString::toString(geo.getXRot(), 20)
+   //  << " " << 0 << " "
+   //  << ossimString::toString(geo.getX(), 20)
+   //  << " " << ossimString::toString(geo.getYRot(), 20)
+   //  << " " << ossimString::toString(geo.getYRes(), 20)
+   //  << " " << 0 << " "
+   //  << ossimString::toString(geo.getY(), 20)
+   //  << " " << 0 << " " << 0 << " " << 1 << " " << 0
+   //  << " " << 0 << " " << 0 << " " << 0 << " " << 1;
+   //kwl.add(ossimKeywordNames::IMAGE_MODEL_TRANSFORM_MATRIX_KW, mString.str().c_str());
+
+   // if meta data does not have the code info, try to read from .aux file
+   if (code == 0)
+   {
+      ossimFilename auxFile = theImageFile;
+      auxFile.setExtension("aux");
+      ossimAuxFileHandler auxHandler;
+      if (auxFile.exists() && auxHandler.open(auxFile))
+      {
+         ossimString proj_name = auxHandler.getProjectionName();
+         ossimString datum_name = auxHandler.getDatumName();
+         ossimString unitType = auxHandler.getUnitType();
+
+         // HACK: Geographic projection is specified in non-WKT format. Intercepting here. OLK 5/10
+         // TODO: Need projection factory that can handle miscellaneous non-WKT specs as they are 
+         //       encountered. 
+         if (proj_name.contains("Geographic"))
+         {
+            kwl.add(ossimKeywordNames::TYPE_KW, "ossimEquDistCylProjection", false);
+            scale_units = "degrees";
+            tie_pt_units = "degrees";
+         }
+         else
+         {
+            // pass along MrSid's projection name and pray it can be resolved:
+            kwl.add(ossimKeywordNames::PROJECTION_KW, proj_name, false);
+            if (unitType.empty())
+            {
+               if (proj_name.downcase().contains("feet"))
+               {
+                  scale_units = "feet";
+                  tie_pt_units = "feet";
+               }
+            }
+            else
+            {
+               scale_units = unitType;
+               tie_pt_units = unitType;
+            }
+         }
+
+         // HACK: WGS-84 is specified in non-WKT format. Intercepting here. OLK 5/10
+         // TODO: Need datum factory that can handle miscellaneous non-WKT specs as they are 
+         //       encountered. 
+         if (datum_name.contains("WGS") && datum_name.contains("84"))
+            kwl.add(ossimKeywordNames::DATUM_KW, "EPSG:6326");
+         else
+            kwl.add(ossimKeywordNames::DATUM_KW, datum_name, false);
+      }
+   }
+
+   if ( scale_units.empty()  || (scale_units == "unknown" ) ||
+        tie_pt_units.empty() || (tie_pt_units == "unknown" ) )
+   {
+      ossimNotify(ossimNotifyLevel_WARN)
+         << "ossimMrSidReader::getProjection WARNING: Undefined units!"
+         << "\nscale units:  " << scale_units
+         << "\ntie_pt_units: " << tie_pt_units
+         << std::endl;
+   }
+
+   kwl.add(ossimKeywordNames::PIXEL_SCALE_XY_KW, gsd.toString());
+   kwl.add(ossimKeywordNames::PIXEL_SCALE_UNITS_KW, scale_units);
+   kwl.add(ossimKeywordNames::TIE_POINT_XY_KW, tie.toString());
+   kwl.add(ossimKeywordNames::TIE_POINT_UNITS_KW, tie_pt_units);
+
+   ossimProjection* proj = 
+      ossimProjectionFactoryRegistry::instance()->createProjection(kwl);
+   return proj;
+}
+
+bool ossimMrSidReader::getMetadataElement(LTIMetadataDatabase metaDb,
+                                          const char *tagName, 
+                                          void *pValue,
+                                          int iLength)
+{
+   if (!metaDb.has(tagName))
+   {
+      return false;
+   }
+
+   const LTIMetadataRecord* metaRec = 0;
+   metaDb.get(tagName, metaRec );
+
+   if (!metaRec->isScalar())
+   {
+      return false;
+   }
+
+   // XXX: return FALSE if we have more than one element in metadata record
+   int iSize;
+   switch(metaRec->getDataType())
+   {
+      case LTI_METADATA_DATATYPE_UINT8:
+      case LTI_METADATA_DATATYPE_SINT8:
+         iSize = 1;
+         break;
+      case LTI_METADATA_DATATYPE_UINT16:
+      case LTI_METADATA_DATATYPE_SINT16:
+         iSize = 2;
+         break;
+      case LTI_METADATA_DATATYPE_UINT32:
+      case LTI_METADATA_DATATYPE_SINT32:
+      case LTI_METADATA_DATATYPE_FLOAT32:
+         iSize = 4;
+         break;
+      case LTI_METADATA_DATATYPE_FLOAT64:
+         iSize = 8;
+         break;
+      case LTI_METADATA_DATATYPE_ASCII:
+         iSize = iLength;
+         break;
+      default:
+         iSize = 0;
+         break;
+   }
+
+   if ( metaRec->getDataType() == LTI_METADATA_DATATYPE_ASCII )
+   {
+      strncpy( (char *)pValue, ((const char**)metaRec->getScalarData())[0], iSize );
+      ((char *)pValue)[iSize - 1] = '\0';
+   }
+   else
+   {
+      memcpy( pValue, metaRec->getScalarData(), iSize);
+   }
+
+   return true;
+}
+
+void ossimMrSidReader::computeMinMax()
+{
+}
+
diff --git a/ossim_plugins/mrsid/ossimMrSidReader.h b/ossim_plugins/mrsid/ossimMrSidReader.h
new file mode 100644
index 0000000..e4157b1
--- /dev/null
+++ b/ossim_plugins/mrsid/ossimMrSidReader.h
@@ -0,0 +1,236 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Description:  Class declaration MrSID reader.
+//
+// Specification: ISO/IEC 15444
+//
+//----------------------------------------------------------------------------
+// $Id: ossimMrSidReader.h 2645 2011-05-26 15:21:34Z oscar.kramer $
+
+#ifndef ossimMrSidReader_HEADER
+#define ossimMrSidReader_HEADER 1
+
+#include <iosfwd>
+#include <fstream>
+#include <vector>
+#include "../ossimPluginConstants.h"
+#include <ossim/base/ossimIpt.h>
+#include <ossim/base/ossimIrect.h>
+#include <ossim/imaging/ossimImageHandler.h>
+#include <ossim/support_data/ossimJ2kSizRecord.h>
+#include <ossim/imaging/ossimAppFixedTileCache.h>
+
+//LizardTech Includes
+#include <MrSIDImageReader.h>
+#include <lti_navigator.h>
+#include <lti_metadataTypes.h>
+
+LT_USE_NAMESPACE(LizardTech);
+
+// Forward class declarations.
+class ossimImageData;
+class ossimDpt;
+
+class OSSIM_PLUGINS_DLL ossimMrSidReader : public ossimImageHandler
+{
+public:
+
+   /** default construtor */
+   ossimMrSidReader();
+   
+   /** virtural destructor */
+   virtual ~ossimMrSidReader();
+
+   /**
+    * @brief Returns short name.
+    * @return "ossim_mrsid_reader"
+    */
+   virtual ossimString getShortName() const;
+   
+   /**
+    * @brief Returns long  name.
+    * @return "ossim mrsid reader"
+    */
+   virtual ossimString getLongName()  const;
+
+   /**
+    * @brief Returns class name.
+    * @return "ossimMrSidReader"
+    */
+   virtual ossimString getClassName() const;
+
+   /**
+    *  @brief Method to grab a tile(rectangle) from image.
+    *
+    *  @param rect The zero based rectangle to grab.
+    *
+    *  @param resLevel The reduced resolution level to grab from.
+    *
+    *  @return The ref pointer with the image data pointer.
+    */
+   virtual ossimRefPtr<ossimImageData> getTile(const  ossimIrect& rect,
+                                               ossim_uint32 resLevel=0);
+
+   /**
+    *  Returns the number of bands in the image.
+    *  Satisfies pure virtual from ImageHandler class.
+    */
+   virtual ossim_uint32 getNumberOfInputBands() const;
+
+   /**
+    * Returns the number of bands in a tile returned from this TileSource.
+    * Note: we are supporting sources that can have multiple data objects.
+    * If you want to know the scalar type of an object you can pass in the
+    */
+   virtual ossim_uint32 getNumberOfOutputBands()const; 
+   /**
+    * Returns the tile width of the image or 0 if the image is not tiled.
+    * Note: this is not the same as the ossimImageSource::getTileWidth which
+    * returns the output tile width which can be different than the internal
+    * image tile width on disk.
+    */
+   virtual ossim_uint32 getImageTileWidth() const;
+
+   /**
+    * Returns the tile width of the image or 0 if the image is not tiled.
+    * Note: this is not the same as the ossimImageSource::getTileHeight which
+    * returns the output tile height which can be different than the internal
+    * image tile height on disk.
+    */
+   virtual ossim_uint32 getImageTileHeight() const;
+
+   /**
+    * Returns the output pixel type of the tile source.
+    */
+   virtual ossimScalarType getOutputScalarType() const;
+   
+   /**
+    * @brief Gets the decimation factor for a resLevel.
+    * @param resLevel Reduced resolution set for requested decimation.
+    * @param result ossimDpt to initialize with requested decimation.
+    */
+   virtual void getDecimationFactor(ossim_uint32 resLevel,
+                                    ossimDpt& result) const;
+
+   /**
+    * @brief Get array of decimations for all levels.
+    * @param decimations Vector to initialize with decimations.
+    */
+   virtual void getDecimationFactors(vector<ossimDpt>& decimations) const; 
+
+   /**
+    * @brief Returns the number of decimation levels.
+    * 
+    * This returns the total number of decimation levels.  It is important to
+    * note that res level 0 or full resolution is included in the list and has
+    * decimation values 1.0, 1.0
+    * 
+    * @return The number of decimation levels.
+    */
+   virtual ossim_uint32 getNumberOfDecimationLevels()const;
+
+   /**
+    * @brief Gets number of lines for res level.
+    *
+    *  @param resLevel Reduced resolution level to return lines of.
+    *  Default = 0
+    *
+    *  @return The number of lines for specified reduced resolution level.
+    */
+   virtual ossim_uint32 getNumberOfLines(ossim_uint32 resLevel = 0) const;
+
+   /**
+    *  @brief Gets the number of samples for res level.
+    *
+    *  @param resLevel Reduced resolution level to return samples of.
+    *  Default = 0
+    *
+    *  @return The number of samples for specified reduced resolution level.
+    */
+   virtual ossim_uint32 getNumberOfSamples(ossim_uint32 resLevel = 0) const;
+
+   /**
+    * @brief Open method.
+    * @return true on success, false on error.
+    */
+   virtual bool open();
+
+   /**
+    *  @brief Method to test for open file stream.
+    *
+    *  @return true if open, false if not.
+    */
+   virtual bool isOpen()const;
+
+   /**
+    * @brief Method to close current entry.
+    *
+    * @note There is a bool kdu_compressed_source::close() and a
+    * void ossimImageHandler::close(); hence, a new close to avoid conflicting
+    * return types.
+    */
+   virtual void closeEntry();
+
+   /**
+    * Returns the image geometry object associated with this tile source or
+    * NULL if non defined.  The geometry contains full-to-local image
+    * transform as well as projection (image-to-world).
+    */
+   virtual ossimRefPtr<ossimImageGeometry> getImageGeometry();
+
+   /**
+    * Method to the load (recreate) the state of an object from a keyword
+    * list.  Return true if ok or false on error.
+    */
+   virtual bool loadState(const ossimKeywordlist& kwl, const char* prefix=0);   
+
+protected:
+
+   /**
+    * @brief Gets the image geometry from external ".geom" or ".aux.xml" file.
+    * @return The image geometry object associated with this mrsid image.
+    */
+   virtual ossimRefPtr<ossimImageGeometry> getExternalImageGeometry() const;
+   
+    /**
+    * @brief Method to get geometry from internal mrsid tags.
+    * @return The image geometry object associated with this mrsid image.
+    */
+   virtual ossimRefPtr<ossimImageGeometry> getInternalImageGeometry() const;
+  
+   
+private:
+
+  bool computeDecimationFactors(std::vector<ossimDpt>& decimations) const;
+
+  bool getImageDimensions(std::vector<ossimIrect>& tileDims) const;
+
+  ossimProjection* getGeoProjection();
+
+  void getDataType();
+
+  void computeMinMax();
+
+  bool getMetadataElement(LTIMetadataDatabase metaDb, const char* tagName, void *pValue, int iLength=0);
+   
+  MrSIDImageReader*            theReader;
+  LTINavigator*                theImageNavigator;
+
+  ossim_uint32                 theMinDwtLevels;
+  ossimIrect                   theImageRect; /** Has sub image offset. */
+
+  /** Image dimensions for each level. */
+  std::vector<ossimIrect>      theMrSidDims;
+  
+  ossim_uint32                 theNumberOfBands;
+  ossimScalarType              theScalarType;
+  ossimRefPtr<ossimImageData>  theTile;
+TYPE_DATA
+};
+
+#endif /* #ifndef ossimMrSidReader_HEADER */
+
diff --git a/ossim_plugins/mrsid/ossimMrSidReaderFactory.cpp b/ossim_plugins/mrsid/ossimMrSidReaderFactory.cpp
new file mode 100644
index 0000000..ec7b6cf
--- /dev/null
+++ b/ossim_plugins/mrsid/ossimMrSidReaderFactory.cpp
@@ -0,0 +1,187 @@
+//----------------------------------------------------------------------------
+//
+// License:  See top level LICENSE.txt file
+//
+// Author:  Mingjie Su
+//
+// Description: Factory for OSSIM MrSID reader using kakadu library.
+//----------------------------------------------------------------------------
+// $Id: ossimMrSidReaderFactory.cpp 469 2009-12-23 18:52:47Z ming.su $
+
+#include <ossim/base/ossimKeywordlist.h>
+#include <ossim/base/ossimRefPtr.h>
+#include <ossim/base/ossimString.h>
+#include <ossim/base/ossimTrace.h>
+#include <ossim/imaging/ossimImageHandler.h>
+
+#include "ossimMrSidReaderFactory.h"
+#include "ossimMrSidReader.h"
+#include "ossimMG4LidarReader.h"
+
+static const ossimTrace traceDebug("ossimMrSidReaderFactory:debug");
+
+class ossimImageHandler;
+
+RTTI_DEF1(ossimMrSidReaderFactory,
+          "ossimMrSidReaderFactory",
+          ossimImageHandlerFactoryBase);
+
+ossimMrSidReaderFactory* ossimMrSidReaderFactory::theInstance = 0;
+
+ossimMrSidReaderFactory::~ossimMrSidReaderFactory()
+{
+   theInstance = 0;
+}
+
+ossimMrSidReaderFactory* ossimMrSidReaderFactory::instance()
+{
+   if(!theInstance)
+   {
+      theInstance = new ossimMrSidReaderFactory;
+   }
+   return theInstance;
+}
+
+ossimImageHandler* ossimMrSidReaderFactory::open(
+   const ossimFilename& fileName, bool openOverview)const
+{
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimMrSidReaderFactory::open(filename) DEBUG: entered...\n";
+   }
+
+   ossimRefPtr<ossimImageHandler> reader = 0;
+
+   if ( hasExcludedExtension(fileName) == false )
+   {
+      if(traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG) << "\nTrying ossimMrSidReader\n";
+      }
+      reader = new ossimMrSidReader;
+      reader->setOpenOverviewFlag(openOverview);
+      if(reader->open(fileName) == false)
+      {
+         reader = 0;
+      }
+
+      if (!reader.valid())
+      {
+         reader = new ossimMG4LidarReader;
+         reader->setOpenOverviewFlag(openOverview);
+         if(reader->open(fileName) == false)
+         {
+            reader = 0;
+         }
+      }
+   }
+
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimMrSidReaderFactory::open(filename) DEBUG: leaving...\n";
+   }
+
+   return reader.release();
+}
+
+ossimImageHandler* ossimMrSidReaderFactory::open(const ossimKeywordlist& kwl,
+                                                 const char* prefix)const
+{
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimMrSidReaderFactory::open(kwl, prefix) DEBUG: entered..."
+         << "Trying ossimMrSidReader..."
+         << std::endl;
+   }
+
+   ossimRefPtr<ossimImageHandler> reader = new ossimMrSidReader;
+   if(reader->loadState(kwl, prefix) == false)
+   {
+      reader = 0;
+   }
+
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimMrSidReaderFactory::open(kwl, prefix) DEBUG: leaving..."
+         << std::endl;
+   }
+
+   return reader.release();
+}
+
+ossimObject* ossimMrSidReaderFactory::createObject(
+   const ossimString& typeName)const
+{
+   ossimRefPtr<ossimObject> result = 0;
+   if(typeName == "ossimMrSidReader")
+   {
+      result = new ossimMrSidReader;
+   }
+   else if(typeName == "ossimMG4LidarReader")
+   {
+      result = new ossimMrSidReader;
+   }
+
+   return result.release();
+}
+
+ossimObject* ossimMrSidReaderFactory::createObject(
+   const ossimKeywordlist& kwl,
+   const char* prefix)const
+{
+   return this->open(kwl, prefix);
+}
+
+void ossimMrSidReaderFactory::getTypeNameList(
+   std::vector<ossimString>& typeList)const
+{
+   typeList.push_back(ossimString("ossimMrSidReader"));
+}
+
+void ossimMrSidReaderFactory::getSupportedExtensions(
+   ossimImageHandlerFactoryBase::UniqueStringList& extensionList)const
+{
+   extensionList.push_back(ossimString("sid"));
+}
+
+void ossimMrSidReaderFactory::getImageHandlersBySuffix(
+   ossimImageHandlerFactoryBase::ImageHandlerList& result, const ossimString& ext)const
+{
+   ossimString testExt = ext.downcase();
+   if(ext == "sid")
+   {
+      result.push_back(new ossimMrSidReader);
+   }
+}
+
+void ossimMrSidReaderFactory::getImageHandlersByMimeType(
+   ossimImageHandlerFactoryBase::ImageHandlerList& result, const ossimString& mimeType)const
+{
+   ossimString testExt = mimeType.downcase();
+   if(testExt == "image/sid")
+   {
+      result.push_back(new ossimMrSidReader);
+   }
+}
+
+bool ossimMrSidReaderFactory::hasExcludedExtension(
+   const ossimFilename& file) const
+{
+   bool result = true;
+   ossimString ext = file.ext().downcase();
+   if (ext == "sid") //only include the file with .sid extension and exclude any other files
+   {
+      result = false;
+   }
+   return result;
+}
+
+ossimMrSidReaderFactory::ossimMrSidReaderFactory(){}
+
+ossimMrSidReaderFactory::ossimMrSidReaderFactory(const ossimMrSidReaderFactory&){}
+
+void ossimMrSidReaderFactory::operator=(const ossimMrSidReaderFactory&){}
diff --git a/ossim_plugins/mrsid/ossimMrSidReaderFactory.h b/ossim_plugins/mrsid/ossimMrSidReaderFactory.h
new file mode 100644
index 0000000..6cdec30
--- /dev/null
+++ b/ossim_plugins/mrsid/ossimMrSidReaderFactory.h
@@ -0,0 +1,116 @@
+//----------------------------------------------------------------------------
+//
+// License:  See top level LICENSE.txt file
+//
+// Author:  Mingjie Su
+//
+// Description: Factory for OSSIM MrSID) reader using Lizard library.
+//----------------------------------------------------------------------------
+// $Id: ossimMrSidReaderFactory.h 2997 2011-10-21 17:46:30Z ming.su $
+
+#ifndef ossimMrSidReaderFactory_HEADER
+#define ossimMrSidReaderFactory_HEADER
+
+#include <ossim/imaging/ossimImageHandlerFactoryBase.h>
+
+class ossimString;
+class ossimFilename;
+class ossimKeywordlist;
+
+/** @brief Factory for MrSid image reader. */
+class ossimMrSidReaderFactory : public ossimImageHandlerFactoryBase
+{
+public:
+
+   /** @brief virtual destructor */
+   virtual ~ossimMrSidReaderFactory();
+
+   /**
+    * @brief static method to return instance (the only one) of this class.
+    * @return pointer to instance of this class.
+    */
+   static ossimMrSidReaderFactory* instance();
+
+   /**
+    * @brief open that takes a file name.
+    * @param file The file to open.
+    * @param openOverview If true image handler will attempt to open overview.
+    * default = true 
+    * @return pointer to image handler on success, NULL on failure.
+    */
+   virtual ossimImageHandler* open(const ossimFilename& fileName,
+                                   bool openOverview=true) const;
+
+   /**
+    * @brief open that takes a keyword list and prefix.
+    * @param kwl The keyword list.
+    * @param prefix the keyword list prefix.
+    * @return pointer to image handler on success, NULL on failure.
+    */
+   virtual ossimImageHandler* open(const ossimKeywordlist& kwl,
+                                   const char* prefix=0)const;
+
+   /**
+    * @brief createObject that takes a class name (ossimMrSidReader)
+    * @param typeName Should be "ossimMrSidReader".
+    * @return pointer to image writer on success, NULL on failure.
+    */
+   virtual ossimObject* createObject(const ossimString& typeName)const;
+   
+   /**
+    * @brief Creates and object given a keyword list and prefix.
+    * @param kwl The keyword list.
+    * @param prefix the keyword list prefix.
+    * @return pointer to image handler on success, NULL on failure.
+    */
+   virtual ossimObject* createObject(const ossimKeywordlist& kwl,
+                                     const char* prefix=0)const;
+   
+   /**
+    * @brief Adds ossimMrSidWriter to the typeList.
+    * @param typeList List to add to.
+    */
+   virtual void getTypeNameList(std::vector<ossimString>& typeList)const;
+
+   /**
+    * @brief Method to add supported extension to the list, like "sid".
+    *
+    * @param extensionList The list to add to.
+    */
+   virtual void getSupportedExtensions(
+      ossimImageHandlerFactoryBase::UniqueStringList& extensionList)const;
+
+   virtual void getImageHandlersBySuffix(ImageHandlerList& result,
+      const ossimString& ext)const;
+   virtual void getImageHandlersByMimeType(ImageHandlerList& result,
+      const ossimString& mimeType)const;
+  
+protected:
+
+   /**
+    * @brief Method to weed out extensions that this plugin knows it does
+    * not support.  This is to avoid a costly open on say a tiff or jpeg that
+    * is not handled by this plugin.
+    *
+    * @return true if extension, false if not.
+    */
+   bool hasExcludedExtension(const ossimFilename& file) const;
+   
+   /** @brief hidden from use default constructor */
+   ossimMrSidReaderFactory();
+
+   /** @brief hidden from use copy constructor */
+   ossimMrSidReaderFactory(const ossimMrSidReaderFactory&);
+
+   /** @brief hidden from use copy constructor */
+   void operator=(const ossimMrSidReaderFactory&);
+
+   /** static instance of this class */
+   static ossimMrSidReaderFactory* theInstance;
+
+TYPE_DATA
+};
+
+#endif /* end of #ifndef ossimMrSidReaderFactory_HEADER */
+
+
diff --git a/ossim_plugins/mrsid/ossimMrSidWriter.cpp b/ossim_plugins/mrsid/ossimMrSidWriter.cpp
new file mode 100644
index 0000000..90ac24b
--- /dev/null
+++ b/ossim_plugins/mrsid/ossimMrSidWriter.cpp
@@ -0,0 +1,594 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Description: OSSIM MrSid writer class definition.
+//
+//----------------------------------------------------------------------------
+// $Id: ossimMrSidWriter.cpp 2645 2011-05-26 15:21:34Z oscar.kramer $
+
+#ifdef OSSIM_ENABLE_MRSID_WRITE
+
+#include <ostream>
+
+#include <ossim/base/ossimBooleanProperty.h>
+#include <ossim/base/ossimDate.h>
+#include <ossim/base/ossimDpt.h>
+#include <ossim/base/ossimEndian.h>
+#include <ossim/base/ossimKeywordlist.h>
+#include <ossim/base/ossimKeywordNames.h>
+#include <ossim/base/ossimTrace.h>
+#include <ossim/projection/ossimMapProjection.h>
+#include <ossim/projection/ossimEpsgProjectionDatabase.h>
+#include <ossim/imaging/ossimImageData.h>
+#include <ossim/imaging/ossimImageSource.h>
+#include <ossim/imaging/ossimImageDataFactory.h>
+
+//LizardTech Includes
+#include <lt_base.h>
+#include <lt_fileSpec.h>
+#include <lt_ioFileStream.h>
+#include <lti_imageReader.h>
+#include <lti_pixel.h>
+#include <lti_scene.h>
+#include <lti_sceneBuffer.h>
+#include <lt_fileSpec.h>
+#include <lti_geoCoord.h>
+#include <lt_ioFileStream.h>
+#include <lti_pixelLookupTable.h>
+#include <lti_utils.h>
+#include <lti_metadataDatabase.h>
+#include <lti_metadataRecord.h>
+#include <lt_utilStatusStrings.h>
+#include <ogr_spatialref.h>
+
+#include "ossimMrSidWriter.h"
+
+RTTI_DEF1(ossimMrSidWriter, "ossimMrSidWriter", ossimImageFileWriter)
+
+//---
+// For trace debugging (to enable at runtime do:
+// your_app -T "ossimMrSidWriter:debug" your_app_args
+//---
+static ossimTrace traceDebug("ossimMrSidWriter:debug");
+
+//---
+// For the "ident" program which will find all exanded $Id: ossimMrSidWriter.cpp 2645 2011-05-26 15:21:34Z oscar.kramer $
+// them.
+//---
+#if OSSIM_ID_ENABLED
+static const char OSSIM_ID[] = "$Id: ossimMrSidWriter.cpp 2645 2011-05-26 15:21:34Z oscar.kramer $";
+#endif
+
+template <class T>
+class LTIDLLPixel : public T
+{
+public:
+  LTIDLLPixel(LTIColorSpace colorSpace, lt_uint16 numBands,
+    LTIDataType dataType) : T(colorSpace,numBands,dataType) {}
+  virtual ~LTIDLLPixel() {};
+};
+
+ossimMrSidWriter::ossimMrSidWriter()
+: ossimImageFileWriter(),
+m_fileSize(0),
+m_makeWorldFile(false)
+{
+  // Set the output image type in the base class.
+  setOutputImageType(getShortName());
+}
+
+ossimMrSidWriter::~ossimMrSidWriter()
+{
+  close();
+}
+
+ossimString ossimMrSidWriter::getShortName() const
+{
+  return ossimString("ossim_mrsid");
+}
+
+ossimString ossimMrSidWriter::getLongName() const
+{
+  return ossimString("ossim mrsid writer");
+}
+
+ossimString ossimMrSidWriter::getClassName() const
+{
+  return ossimString("ossimMrSidWriter");
+}
+
+bool ossimMrSidWriter::writeFile()
+{
+  // This method is called from ossimImageFileWriter::execute().
+  bool result = false;
+
+  if( theInputConnection.valid() &&
+    (getErrorStatus() == ossimErrorCodes::OSSIM_OK) )
+  {
+    //---
+    // Note only the master process used for writing...
+    //---
+    if(theInputConnection->isMaster())
+    {
+      if (!isOpen())
+      {
+        open();
+      }
+      if ( isOpen() )
+      {
+        result = writeStream();
+      }
+    }
+    else // Slave process.
+    {
+      // This will return after all tiles for this node have been processed.
+      theInputConnection->slaveProcessTiles();
+      result = true;
+    }
+  }
+
+  return result;
+}
+
+bool ossimMrSidWriter::writeStream()
+{
+  static const char MODULE[] = "ossimMrSidWriter::writeStream";
+
+  if (traceDebug())
+  {
+    ossimNotify(ossimNotifyLevel_DEBUG)
+      << MODULE << " entered..." << endl;
+  }
+
+  //Since the LizardTech algorithms process an entire row at a time, 
+  //we need to set the tile width equals to the width of theAreaOfInterest
+  //set the tile height to 32, so the writer will write 32 rows at a time
+  theInputConnection->setTileSize(theAreaOfInterest.width(), 32);
+  theInputConnection->initialize();
+
+  theInputConnection->setAreaOfInterest(theAreaOfInterest);
+  theInputConnection->setToStartOfSequence();
+
+  MrSIDDummyImageReader imageReader(theInputConnection);
+  if (!LT_SUCCESS(imageReader.initialize()))
+  {
+    ossimNotify(ossimNotifyLevel_DEBUG)
+      << MODULE << ": Failed to open the input image!" << endl;
+    return false;
+  }
+  LTIMetadataDatabase& metadataDatabase = 
+    const_cast<LTIMetadataDatabase&>(imageReader.getMetadata());
+  writeMetaDatabase(metadataDatabase);
+
+  MG3ImageWriter imageWriter;
+  if (!LT_SUCCESS(imageWriter.initialize(&imageReader)))
+  {
+    return false;
+  }
+
+  // set output filename
+  if (!LT_SUCCESS(imageWriter.setOutputFileSpec(theFilename)))
+  {
+    return false;
+  }
+
+  LT_STATUS stat = imageWriter.setEncodingApplication(getShortName(), "1.0");
+
+  if ( LT_FAILURE(stat) )
+  {
+     ossimNotify(ossimNotifyLevel_FATAL)
+        << "ossimMrSidWriter::writeMetaDatabase ERROR:"
+        << "\nMG3ImageWriter.setEncodingApplication() failed. "
+        << getLastStatusString(stat)
+        << std::endl;
+     return false;
+  }
+
+  // Only allow the cartridge check disable when ossimMrSid is compiled for
+  // development mode. MRSID_DISABLE_CARTRIDGE_CHECK is defined as preprocessor 
+  // in the project with ReleaseWithSymbols
+#ifdef MRSID_DISABLE_CARTRIDGE_CHECK
+  imageWriter.setUsageMeterEnabled(false);
+#else
+  // V Important: This enables proper usage of cartridge. Changing the param
+  // to false will cause Mr. Sid writer license violation.
+  imageWriter.setUsageMeterEnabled(true); 
+#endif 
+
+  imageWriter.setStripHeight(32); //set rows offset. it's same as the tile height
+  if (!LT_SUCCESS(imageWriter.params().setBlockSize(imageWriter.params().getBlockSize())))
+  {
+    return false;
+  }
+
+  if (m_makeWorldFile)
+  {
+    imageWriter.setWorldFileSupport(m_makeWorldFile);
+  }
+
+  if (m_fileSize > 0)
+  {
+    imageWriter.params().setTargetFilesize(m_fileSize);
+  }
+
+  const LTIScene scene(0, 0, theInputConnection->getAreaOfInterest().width(), 
+    theInputConnection->getAreaOfInterest().height(), 1.0);
+  if (!LT_SUCCESS(imageWriter.write(scene)))
+  {
+    ossimNotify(ossimNotifyLevel_FATAL)
+      << "ossimMrSidWriter::writeMetaDatabase ERROR:"
+      << "\nFailed to write SID file. Is cartridge installed correctly?"
+      << std::endl;
+    return false;
+  }
+
+  return true;
+}
+
+bool ossimMrSidWriter::saveState(ossimKeywordlist& kwl,
+                                 const char* prefix)const
+{
+  return ossimImageFileWriter::saveState(kwl, prefix);
+}
+
+bool ossimMrSidWriter::loadState(const ossimKeywordlist& kwl,
+                                 const char* prefix)
+{
+  return ossimImageFileWriter::loadState(kwl, prefix);
+}
+
+bool ossimMrSidWriter::isOpen() const
+{
+  if (theFilename.size() > 0)
+  {
+    return true;
+  }
+  return false;
+}
+
+bool ossimMrSidWriter::open()
+{
+  bool result = false;
+
+  // Check for empty filenames.
+  if (theFilename.size())
+  {
+    result = true;
+  }
+
+  if (traceDebug())
+  {
+    ossimNotify(ossimNotifyLevel_DEBUG)
+      << "ossimMrSidWriter::open()\n"
+      << "File " << theFilename << (result ? " opened" : " not opened")
+      << std::endl;
+  }
+
+  return result;
+}
+
+void ossimMrSidWriter::close()
+{
+}
+
+void ossimMrSidWriter::getImageTypeList(std::vector<ossimString>& imageTypeList)const
+{
+  imageTypeList.push_back(getShortName());
+}
+
+ossimString ossimMrSidWriter::getExtension() const
+{
+  return ossimString("sid");
+}
+
+bool ossimMrSidWriter::hasImageType(const ossimString& imageType) const
+{
+  bool result = false;
+  if ( (imageType == getShortName()) ||
+    (imageType == "image/mrsid") )
+  {
+    result = true;
+  }
+  return result;
+}
+
+void ossimMrSidWriter::setProperty(ossimRefPtr<ossimProperty> property)
+{
+  if (property.get())
+  {
+    if(property->getName() == "FILESIZE")
+    {
+      m_fileSize = property->valueToString().toInt32();
+    }
+
+    if(property->getName() == "WORLDFILE")
+    {
+      if (!property->valueToString().empty())
+      {
+        m_makeWorldFile = true;
+      }
+    }
+
+    ossimImageFileWriter::setProperty(property);
+  }
+}
+
+ossimRefPtr<ossimProperty> ossimMrSidWriter::getProperty(
+  const ossimString& name)const
+{
+  // Currently no properties.
+  return ossimImageFileWriter::getProperty(name);
+}
+
+void ossimMrSidWriter::getPropertyNames(
+                                        std::vector<ossimString>& propertyNames)const
+{
+  ossimImageFileWriter::getPropertyNames(propertyNames);
+}
+
+void ossimMrSidWriter::writeMetaDatabase(LTIMetadataDatabase& metadataDatabase)
+{
+  // Get current input geometry
+  ossimRefPtr<ossimImageGeometry> image_geom = theInputConnection->getImageGeometry();
+  if (!image_geom.valid())
+  {
+    ossimNotify(ossimNotifyLevel_WARN)
+      << "ossimMrSidWriter::writeMetaDatabase WARNING:"
+      << "\ntheInputConnection->getImageGeometry returned NULL."
+      << std::endl;
+    return;
+  }
+
+  ossimProjection* proj = image_geom->getProjection();
+  if (!proj)
+  {
+    ossimNotify(ossimNotifyLevel_WARN)
+      << "ossimMrSidWriter::writeMetaDatabase WARNING:"
+      << "\nFailed to create projection!"
+      << std::endl;
+    return; 
+  }
+
+  ossimMapProjection* mapProj = PTR_CAST(ossimMapProjection, proj);
+  if (!mapProj)
+  {
+    ossimNotify(ossimNotifyLevel_WARN)
+      << "ossimMrSidWriter::writeMetaDatabase WARNING:"
+      << "\nProjection failed to cast to map projection!"
+      << std::endl;
+    return;  
+  }
+
+  ossimUnitType unitType = mapProj->getModelTransformUnitType();
+  int epsg_code = (int) mapProj->getPcsCode();
+
+  if (mapProj->getProjectionName() == "ossimEquDistCylProjection" || 
+      mapProj->getProjectionName() == "ossimLlxyProjection")
+  {
+    LTIMetadataRecord mrGeoCSType( "GEOTIFF_NUM::2048::GeographicTypeGeoKey",
+      LTI_METADATA_DATATYPE_SINT32, &epsg_code);
+    metadataDatabase.add(mrGeoCSType);
+
+    const char* angularUnit = NULL;
+    if (unitType == OSSIM_UNIT_UNKNOWN || unitType == OSSIM_DEGREES)
+    {
+      angularUnit = "Angular_Degree";
+    }
+    else if (unitType == OSSIM_MINUTES)
+    {
+      angularUnit = "Angular_Minute";
+    }
+    else if (unitType == OSSIM_SECONDS)
+    {
+      angularUnit = "Angular_Second";
+    }
+
+    LTIMetadataRecord mrGeogAngularUnitsStr( "GEOTIFF_CHAR::GeogAngularUnitsGeoKey",
+      LTI_METADATA_DATATYPE_ASCII, &angularUnit);
+    metadataDatabase.add(mrGeogAngularUnitsStr);
+  }
+  else
+  {
+    LTIMetadataRecord mrProjectedCSType("GEOTIFF_NUM::3072::ProjectedCSTypeGeoKey",
+      LTI_METADATA_DATATYPE_SINT32, &epsg_code);
+    metadataDatabase.add(mrProjectedCSType);
+
+    const char* projLinearUnitsStr = NULL;
+    if (unitType == OSSIM_UNIT_UNKNOWN || unitType == OSSIM_METERS)
+    {
+      projLinearUnitsStr = "Linear_Meter";
+    }
+    else if (unitType == OSSIM_FEET)
+    {
+      projLinearUnitsStr = "Linear_Foot";
+    }
+    else if (unitType == OSSIM_US_SURVEY_FEET)
+    {
+      projLinearUnitsStr = "Linear_Foot_US_Survey";
+    }
+    LTIMetadataRecord mrProjLinearUnitsStr( "GEOTIFF_CHAR::ProjLinearUnitsGeoKey",
+      LTI_METADATA_DATATYPE_ASCII, &projLinearUnitsStr );
+    metadataDatabase.add( mrProjLinearUnitsStr );
+  }
+
+  const char* GTRasterType = "RasterPixelIsArea";
+  LTIMetadataRecord mrGTRasterType( "GEOTIFF_CHAR::GTRasterTypeGeoKey",
+    LTI_METADATA_DATATYPE_ASCII, &GTRasterType );
+  metadataDatabase.add( mrGTRasterType );
+}
+
+MrSIDDummyImageReader::MrSIDDummyImageReader(ossimRefPtr<ossimImageSourceSequencer> theInputConnection) 
+: LTIImageReader(), 
+theInputSource(theInputConnection)
+{
+  ltiPixel = NULL;
+}
+
+MrSIDDummyImageReader::~MrSIDDummyImageReader()
+{
+  if ( ltiPixel )
+  {
+    delete ltiPixel;
+  }
+}
+
+LT_STATUS MrSIDDummyImageReader::initialize()
+{
+  if ( !LT_SUCCESS(LTIImageReader::init()) )
+    return LT_STS_Failure;
+
+  lt_uint16 numBands = (lt_uint16)theInputSource->getNumberOfOutputBands();
+  LTIColorSpace colorSpace = LTI_COLORSPACE_RGB;
+  switch ( numBands )
+  {
+  case 1:
+    colorSpace = LTI_COLORSPACE_GRAYSCALE;
+    break;
+  case 3:
+    colorSpace = LTI_COLORSPACE_RGB;
+    break;
+  default:
+    colorSpace = LTI_COLORSPACE_MULTISPECTRAL;
+    break;
+  }
+
+  ossimScalarType scalarType = theInputSource->getOutputScalarType();
+
+  switch (scalarType)
+  {
+  case OSSIM_UINT16:
+    sampleType = LTI_DATATYPE_UINT16;
+    break;
+  case OSSIM_SINT16:
+    sampleType = LTI_DATATYPE_SINT16;
+    break;
+  case OSSIM_UINT32:
+    sampleType = LTI_DATATYPE_UINT32;
+    break;
+  case OSSIM_SINT32:
+    sampleType = LTI_DATATYPE_SINT32;
+    break;
+  case OSSIM_FLOAT32:
+    sampleType = LTI_DATATYPE_FLOAT32;
+    break;
+  case OSSIM_FLOAT64:
+    sampleType = LTI_DATATYPE_FLOAT64;
+    break;
+  default:
+    sampleType = LTI_DATATYPE_UINT8;
+    break;
+  }
+
+  ltiPixel = new LTIDLLPixel<LTIPixel>( colorSpace, numBands, sampleType );
+
+  if ( !LT_SUCCESS(setPixelProps(*ltiPixel)) )
+    return LT_STS_Failure;
+
+  if ( !LT_SUCCESS(setDimensions(theInputSource->getAreaOfInterest().width()+1, theInputSource->getAreaOfInterest().height()+1)))
+  {
+    return LT_STS_Failure;
+  }
+
+  ossimRefPtr<ossimImageGeometry> image_geom = theInputSource->getImageGeometry();
+  if (!image_geom.valid())
+  {
+    return LT_STS_Failure;
+  }
+
+  ossimProjection* proj = image_geom->getProjection();
+  if (!proj)
+  {
+    return LT_STS_Failure; 
+  }
+
+  ossimMapProjection* mapProj = dynamic_cast<ossimMapProjection*>(proj);
+  if (!mapProj)
+  {
+    return LT_STS_Failure;  
+  }
+
+  double ulx = 0.0;       
+  double uly = 0.0; 
+  double perPixelX = 0.0;
+  double perPixelY = 0.0;
+
+  ossimString type(mapProj->getProjectionName());
+  if(type == "ossimLlxyProjection" || type == "ossimEquDistCylProjection")
+  {
+    perPixelX =  mapProj->getDecimalDegreesPerPixel().x;
+    perPixelY = -mapProj->getDecimalDegreesPerPixel().y;
+    ulx =  mapProj->getUlGpt().lond();
+    uly =  mapProj->getUlGpt().latd();
+  }
+  else
+  {
+    perPixelX =  mapProj->getMetersPerPixel().x;
+    perPixelY = -mapProj->getMetersPerPixel().y;
+    ulx =  mapProj->getUlEastingNorthing().u;
+    uly =  mapProj->getUlEastingNorthing().v;
+  }
+
+  LTIGeoCoord geoCoord(ulx + fabs(perPixelX)/2, 
+    uly - fabs(perPixelY)/2, perPixelX,perPixelY, 0.0, 0.0, NULL);
+
+  ossimString wkt = getWkt(mapProj);
+  if (!wkt.empty())
+  {
+    geoCoord.setWKT(wkt.c_str());
+  }
+
+  if ( !LT_SUCCESS(setGeoCoord(geoCoord)) )
+  {
+    return LT_STS_Failure;  
+  }
+
+  setDefaultDynamicRange();
+
+  return LT_STS_Success;
+}
+
+ossimString MrSIDDummyImageReader::getWkt(ossimMapProjection* map_proj)
+{
+  ossimString wktString;
+  OGRSpatialReference spatialRef;
+
+  if(map_proj == NULL)
+  {
+    return wktString;
+  }
+
+  ossim_uint32 code = map_proj->getPcsCode();
+  if (code != 0)
+  {
+     spatialRef.importFromEPSG(code);
+     
+     char* exportString = NULL;
+     spatialRef.exportToWkt(&exportString);
+     
+     if(exportString)
+     {
+        wktString = exportString;
+        delete exportString;
+     }
+  }
+
+  return wktString;
+}
+
+LT_STATUS MrSIDDummyImageReader::decodeStrip(LTISceneBuffer& stripData,
+                                             const LTIScene& stripScene)
+
+{
+  ossimRefPtr<ossimImageData> imageData = theInputSource->getNextTile();
+  if (imageData.valid() && ( imageData->getDataObjectStatus() != OSSIM_NULL ) )
+  {
+    stripData.importDataBSQ(imageData->getBuf());
+  }
+  return LT_STS_Success;
+}
+
+#endif /* #ifdef OSSIM_ENABLE_MRSID_WRITE */
+
diff --git a/ossim_plugins/mrsid/ossimMrSidWriter.h b/ossim_plugins/mrsid/ossimMrSidWriter.h
new file mode 100644
index 0000000..61f9b76
--- /dev/null
+++ b/ossim_plugins/mrsid/ossimMrSidWriter.h
@@ -0,0 +1,164 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Description: OSSIM MrSID writer class declaration.
+//
+//----------------------------------------------------------------------------
+// $Id: ossimMrSidWriter.h 1256 2010-08-09 17:11:17Z ming.su $
+
+#ifndef ossimMrSidWriter_HEADER
+#define ossimMrSidWriter_HEADER 1
+
+#ifdef OSSIM_ENABLE_MRSID_WRITE
+
+#include <iosfwd>
+#include <vector>
+
+#include <ossim/imaging/ossimImageFileWriter.h>
+#include <ossim/base/ossimRefPtr.h>
+#include <ossim/base/ossimString.h>
+
+//LizardTech Includes
+#include <lti_rawImageReader.h>
+#include <MG2ImageWriter.h>
+#include <MG3ImageWriter.h>
+
+LT_USE_NAMESPACE(LizardTech);
+
+class ossimKeywordlist;
+class ossimMapProjection;
+
+class MrSIDDummyImageReader : public LTIImageReader
+{
+public:
+
+  MrSIDDummyImageReader(ossimRefPtr<ossimImageSourceSequencer> theInputConnection);
+  ~MrSIDDummyImageReader();
+  LT_STATUS           initialize();
+  lt_int64            getPhysicalFileSize(void) const { return 0; };
+
+private:
+  ossimRefPtr<ossimImageSourceSequencer> theInputSource;
+  LTIDataType         sampleType;
+  LTIPixel*           ltiPixel;
+ 
+  virtual LT_STATUS   decodeStrip( LTISceneBuffer& stripBuffer,
+    const LTIScene& stripScene );
+  virtual LT_STATUS   decodeBegin( const LTIScene& scene )
+  { return LT_STS_Success; };
+  virtual LT_STATUS   decodeEnd() { return LT_STS_Success; };
+  ossimString getWkt(ossimMapProjection* map_proj);
+};
+
+class ossimMrSidWriter : public ossimImageFileWriter
+{
+public:
+
+   /** @brief default constructor */
+   ossimMrSidWriter();
+
+   /* @brief virtual destructor */
+   virtual ~ossimMrSidWriter();
+
+   /** @return "ossim_mrsid_writer" */
+   virtual ossimString getShortName() const;
+
+   /** @return "ossim mrsid writer" */
+   virtual ossimString getLongName()  const;
+
+   /** @return "ossimMrSidWriter" */
+   virtual ossimString getClassName()    const;
+   
+   /**
+    * void getImageTypeList(std::vector<ossimString>& imageTypeList)const
+    *
+    * Appends this writer image types to list "imageTypeList".
+    *
+    * This writer only has one type "sid".
+    *
+    * @param imageTypeList stl::vector<ossimString> list to append to.
+    */
+   virtual void getImageTypeList(std::vector<ossimString>& imageTypeList)const;
+   
+   virtual bool isOpen()const;   
+   
+   virtual bool open();
+
+   virtual void close();
+   
+   /**
+    * saves the state of the object.
+    */
+   virtual bool saveState(ossimKeywordlist& kwl,
+                          const char* prefix=0)const;
+   
+   /**
+    * Method to the load (recreate) the state of an object from a keyword
+    * list.  Return true if ok or false on error.
+    */
+   virtual bool loadState(const ossimKeywordlist& kwl,
+                          const char* prefix=0);
+
+   /**
+    * Will set the property whose name matches the argument
+    * "property->getName()".
+    *
+    * @param property Object containing property to set.
+    */
+   virtual void setProperty(ossimRefPtr<ossimProperty> property);
+
+   /**
+    * @param name Name of property to return.
+    * 
+    * @returns A pointer to a property object which matches "name".
+    */
+   virtual ossimRefPtr<ossimProperty> getProperty(const ossimString& name)const;
+
+   /**
+    * Pushes this's names onto the list of property names.
+    *
+    * @param propertyNames array to add this's property names to.
+    */
+   virtual void getPropertyNames(std::vector<ossimString>& propertyNames)const;
+
+   /**
+   * Returns a 3-letter extension from the image type descriptor 
+   * (theOutputImageType) that can be used for image file extensions.
+   *
+   * @param imageType string representing image type.
+   *
+   * @return the 3-letter string extension.
+   */
+   virtual ossimString getExtension() const;
+
+   bool hasImageType(const ossimString& imageType) const;
+
+   /**
+   * @brief Method to write the image to a stream.
+   *
+   * @return true on success, false on error.
+   */
+   virtual bool writeStream();
+
+   void writeMetaDatabase(LTIMetadataDatabase& metadataDatabase);
+
+protected:
+   /**
+    * @brief Writes the file to disk or a stream.
+    * @return true on success, false on error.
+    */
+   virtual bool writeFile(); 
+
+   ossim_int32 m_fileSize;
+   bool        m_makeWorldFile;
+
+ TYPE_DATA
+};
+
+#endif /* #ifdef OSSIM_ENABLE_MRSID_WRITE */
+
+#endif /* #ifndef ossimMrSidWriter_HEADER */
+
diff --git a/ossim_plugins/mrsid/ossimMrSidWriterFactory.cpp b/ossim_plugins/mrsid/ossimMrSidWriterFactory.cpp
new file mode 100644
index 0000000..704b2cb
--- /dev/null
+++ b/ossim_plugins/mrsid/ossimMrSidWriterFactory.cpp
@@ -0,0 +1,144 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author:  Mingjie Su
+//
+// Description: Factory for OSSIM MrSID writers.
+//----------------------------------------------------------------------------
+// $Id: ossimMrSidWriterFactory.cpp 899 2010-05-17 21:00:26Z david.burken $
+
+#ifdef OSSIM_ENABLE_MRSID_WRITE
+
+#include <ossim/base/ossimKeywordNames.h>
+#include <ossim/base/ossimRefPtr.h>
+#include <ossim/imaging/ossimImageFileWriter.h>
+
+#include "ossimMrSidWriterFactory.h"
+#include "ossimMrSidWriter.h"
+
+ossimMrSidWriterFactory* ossimMrSidWriterFactory::theInstance = 0;
+
+RTTI_DEF1(ossimMrSidWriterFactory,
+          "ossimMrSidWriterFactory",
+          ossimImageWriterFactoryBase);
+
+ossimMrSidWriterFactory::~ossimMrSidWriterFactory()
+{
+   theInstance = 0;
+}
+
+ossimMrSidWriterFactory* ossimMrSidWriterFactory::instance()
+{
+   if(!theInstance)
+   {
+      theInstance = new ossimMrSidWriterFactory;
+   }
+   return theInstance;
+}
+
+ossimImageFileWriter* ossimMrSidWriterFactory::createWriterFromExtension(
+   const ossimString& fileExtension)const
+{
+   ossimImageFileWriter* writer = 0;
+
+   if(fileExtension == "sid")
+   {
+      writer = new ossimMrSidWriter;
+   }
+   return writer;
+}
+
+ossimImageFileWriter*
+ossimMrSidWriterFactory::createWriter(const ossimKeywordlist& kwl,
+                                       const char *prefix)const
+{
+   ossimRefPtr<ossimImageFileWriter> writer = 0;
+   const char* type = kwl.find(prefix, ossimKeywordNames::TYPE_KW);
+   if (type)
+   {
+      writer = createWriter(ossimString(type));
+      if (writer.valid())
+      {
+         if (writer->loadState(kwl, prefix) == false)
+         {
+            writer = 0;
+         }
+      }
+   }
+   return writer.release();
+}
+
+ossimImageFileWriter* ossimMrSidWriterFactory::createWriter(
+   const ossimString& typeName)const
+{
+   ossimRefPtr<ossimImageFileWriter> writer = 0;
+   if (typeName == "ossimMrSidWriter" || typeName == "ossim_mrsid")
+   {
+      writer = new ossimMrSidWriter;
+   }
+   return writer.release();
+}
+
+ossimObject* ossimMrSidWriterFactory::createObject(
+   const ossimKeywordlist& kwl, const char *prefix)const
+{
+   return createWriter(kwl, prefix);
+}
+
+ossimObject* ossimMrSidWriterFactory::createObject(
+   const ossimString& typeName) const
+{
+   return createWriter(typeName);
+}
+
+void ossimMrSidWriterFactory::getExtensions(
+   std::vector<ossimString>& result)const
+{
+   result.push_back("sid");
+}
+
+void ossimMrSidWriterFactory::getTypeNameList(std::vector<ossimString>& typeList)const
+{
+   getImageTypeList(typeList);
+}
+
+//---
+// Adds our writers to the list of writers...
+//---
+void ossimMrSidWriterFactory::getImageTypeList(std::vector<ossimString>& imageTypeList)const
+{
+   ossimRefPtr<ossimImageFileWriter> writer = new ossimMrSidWriter;
+   writer->getImageTypeList(imageTypeList);
+}
+
+void ossimMrSidWriterFactory::getImageFileWritersBySuffix(
+   ossimImageWriterFactoryBase::ImageFileWriterList& result, const ossimString& ext)const
+{
+   ossimString testExt = ext.downcase();
+   if(testExt == "sid")
+   {
+      result.push_back(new ossimMrSidWriter);
+   }
+}
+
+void ossimMrSidWriterFactory::getImageFileWritersByMimeType(
+   ossimImageWriterFactoryBase::ImageFileWriterList& result, const ossimString& mimeType)const
+{
+   ossimString testMime = mimeType.downcase();
+   if(testMime == "image/sid")
+   {
+      result.push_back(new ossimMrSidWriter);
+   }
+}
+
+ossimMrSidWriterFactory::ossimMrSidWriterFactory(){}
+
+ossimMrSidWriterFactory::ossimMrSidWriterFactory(const ossimMrSidWriterFactory&){}
+
+void ossimMrSidWriterFactory::operator=(const ossimMrSidWriterFactory&){}
+
+#endif /* #if OSSIM_ENABLE_MRSID_WRITE */
+
diff --git a/ossim_plugins/mrsid/ossimMrSidWriterFactory.h b/ossim_plugins/mrsid/ossimMrSidWriterFactory.h
new file mode 100644
index 0000000..f5a925c
--- /dev/null
+++ b/ossim_plugins/mrsid/ossimMrSidWriterFactory.h
@@ -0,0 +1,124 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author:  Mingjie Su
+//
+// Description: Factory for OSSIM MrSID writers.
+//----------------------------------------------------------------------------
+// $Id: ossimMrSidWriterFactory.h 899 2010-05-17 21:00:26Z david.burken $
+
+#ifndef ossimMrSidWriterFactory_HEADER
+#define ossimMrSidWriterFactory_HEADER
+
+#ifdef OSSIM_ENABLE_MRSID_WRITE
+
+#include <ossim/imaging/ossimImageWriterFactoryBase.h>
+
+class ossimImageFileWriter;
+class ossimKeywordlist;
+class ossimImageWriterFactory;
+
+/** @brief Factory for Kakadu based image writers. */
+class ossimMrSidWriterFactory: public ossimImageWriterFactoryBase
+{   
+public:
+
+   /** @brief virtual destructor */
+   virtual ~ossimMrSidWriterFactory();
+
+   /**
+    * @brief static method to return instance (the only one) of this class.
+    * @return pointer to instance of this class.
+    */
+   static ossimMrSidWriterFactory* instance();
+
+   /**
+    * @brief Creates a writer from extension like "sid".
+    * @param fileExtension "sid"
+    */
+   virtual ossimImageFileWriter *createWriterFromExtension(
+      const ossimString& fileExtension)const;
+
+   /**
+    * @brief Create that takes a keyword list and prefix.
+    * @param kwl The keyword list.
+    * @param prefix the keyword list prefix.
+    * @return pointer to image handler on success, NULL on failure.
+    */
+   virtual ossimImageFileWriter* createWriter(const ossimKeywordlist& kwl,
+                                              const char *prefix=0)const;
+
+   /**
+    * @brief createWriter that takes a class name (ossimKakaduWriter)
+    * @param kwl The keyword list.
+    * @param prefix the keyword list prefix.
+    * @return pointer to image writer on success, NULL on failure.
+    */
+   virtual ossimImageFileWriter* createWriter(const ossimString& typeName)const;
+
+   /**
+    * @brief Creates and object given a keyword list.
+    * @param kwl The keyword list.
+    * @param prefix the keyword list prefix.
+    * @return pointer to image writer on success, NULL on failure.
+    */
+   virtual ossimObject* createObject(const ossimKeywordlist& kwl,
+                                     const char *prefix=0)const;
+
+   /**
+    * @brief createObject that takes a class name (ossimKakaduWriter)
+    * @param typeName Should be "ossimKakaduReader".
+    * @return pointer to image writer on success, NULL on failure.
+    */
+   virtual ossimObject* createObject(const ossimString& typeName)const;
+
+
+   /**
+    * @brief Adds "ntf" to list.
+    * @param extList List to add to.
+    */
+   virtual void getExtensions(std::vector<ossimString>& extList)const;
+
+   /**
+    * @brief Adds "ossimKakaduWriter" to list.
+    * @param typeList List to add to.
+    */
+   virtual void getTypeNameList(std::vector<ossimString>& typeList)const;
+   
+   /**
+    * @brief Adds "ossim_kakada_nitf_j2k" to writer list.
+    * @param imageTypeList List to append to.
+    */
+   virtual void getImageTypeList(std::vector<ossimString>& imageTypeList)const;
+
+   virtual void getImageFileWritersBySuffix(
+      ossimImageWriterFactoryBase::ImageFileWriterList& result,
+      const ossimString& ext)const;
+
+   virtual void getImageFileWritersByMimeType(
+      ossimImageWriterFactoryBase::ImageFileWriterList& result,
+      const ossimString& mimeType)const;
+   
+protected:
+   /** @brief hidden from use default constructor */
+   ossimMrSidWriterFactory();
+
+   /** @brief hidden from use copy constructor */
+   ossimMrSidWriterFactory(const ossimMrSidWriterFactory&);
+
+   /** @brief hidden from use copy constructor */
+   void operator=(const ossimMrSidWriterFactory&);
+
+   /** static instance of this class */
+   static ossimMrSidWriterFactory* theInstance;
+
+TYPE_DATA
+};
+
+#endif /* #ifdef OSSIM_ENABLE_MRSID_WRITE */
+
+#endif /* end of #ifndef ossimMrSidWriterFactory_HEADER */
+
diff --git a/ossim_plugins/ndf/CMakeLists.txt b/ossim_plugins/ndf/CMakeLists.txt
new file mode 100644
index 0000000..4bd20f0
--- /dev/null
+++ b/ossim_plugins/ndf/CMakeLists.txt
@@ -0,0 +1,38 @@
+set(LIB_NAME ossimndf_plugin)
+MESSAGE( "************** LIBRARY SETUP FOR ossimndf_plugin******************")
+
+# Include ossim cmake stuff:
+include(OssimVersion)
+include(OssimCommonVariables)
+include(OssimUtilities)
+
+find_package(ossim)
+find_package(OpenThreads)
+find_package(TIFF)
+
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
+INCLUDE_DIRECTORIES(${OPENTHREADS_INCLUDE_DIR})
+INCLUDE_DIRECTORIES(${TIFF_INCLUDE_DIR})
+
+FILE(GLOB OSSIMPLUGIN_SRCS *.cpp)
+FILE(GLOB OSSIMPLUGIN_HEADERS *.h)
+
+####
+# OSSIMPLUGINSMAKINGDLL controls dll linkage on windows.  
+# Adding this sets OSSIM_PLUGINS_DLL #define TO "__declspec(dllexport)".
+###
+add_definitions("-DOSSIMPLUGINSMAKINGDLL")
+
+# Adjust the install library path:
+if(OSSIM_INSTALL_PLUGINS_WITH_VERSION)
+   set(INSTALL_LIBRARY_DIR   "${INSTALL_LIBRARY_DIR}/ossim-${OSSIM_VERSION}/plugins")
+else(OSSIM_INSTALL_PLUGINS_WITH_VERSION)
+   set(INSTALL_LIBRARY_DIR   "${INSTALL_LIBRARY_DIR}/ossim/plugins")
+endif(OSSIM_INSTALL_PLUGINS_WITH_VERSION)
+
+OSSIM_LINK_LIBRARY(${LIB_NAME}
+                   COMPONENT_NAME ossim TYPE "${OSSIM_PLUGIN_LINK_TYPE}"
+		   LIBRARIES ${OSSIM_LIBRARIES} ${OPENTHREADS_LIBRARY} ${TIFF_LIBRARY}
+                   HEADERS "${OSSIMPLUGIN_HEADERS}"
+		   SOURCE_FILES "${OSSIMPLUGIN_SRCS}"
+                   INSTALL_LIB)
diff --git a/ossim_plugins/ndf/makefile.vc b/ossim_plugins/ndf/makefile.vc
new file mode 100644
index 0000000..319c328
--- /dev/null
+++ b/ossim_plugins/ndf/makefile.vc
@@ -0,0 +1,47 @@
+###
+#
+# Windows nmake make file.  This code should compile with the Microsoft .NET
+# compiler.
+# 
+# Currently for a typical build on windows you would do the following.
+# - cd src packages
+# - untar the gdal package
+# - cd gdal and edit the nmake.opt file appropriately.
+# - cd back to the ossim top and edit its nmake.opt file appropriately.
+# - nmake /f makefile
+# - nmake /f makefile install (if you want the apps in the bin directory.
+#
+# NOTE:  If you make shared apps it's handy to copy the ossim.dll to the bin
+#        directory. 
+###
+
+!INCLUDE ..\nmake.opt
+PLUGIN_ROOT = ossim_ndf_plugin
+
+INC	=	-I.. -I. $(3RD_PARTY_INC) -I$(OSSIM_HOME)\include
+LINK	=	link
+LFLAGS	=	/NOLOGO /SUBSYSTEM:WINDOWS /LIBPATH:"$(OSSIM_HOME)\lib\ossim" $(SHARED_OSSIM_LINK)
+
+LIBS	= "$(OSSIM_LIB)"
+
+OBJ	= ossimNdfPluginInit.obj \
+ossimNdfHeader.obj \
+ossimNdfTileSource.obj \
+ossimNdfReaderFactory.obj 
+
+default:	$(OBJ)
+	link /NOLOGO /SUBSYSTEM:WINDOWS /VERSION:$(VERSION_STRING) /DLL /OUT:"$(PLUGIN_ROOT).dll" /IMPLIB:"$(PLUGIN_ROOT).lib" $(OBJ) $(OSSIM_HOME)\lib\ossim.lib $(KAK_LIB)
+	$(OSSIM_VC_MANIFEST_EMBED_DLL)
+
+
+install:
+	$(CP) $(PLUGIN_ROOT).dll $(INSTALL_DIR)
+
+ndf:	ndf_test.cpp
+	$(CC) $(APP_CFLAGS) ndf_test.cpp $(SHARED_OSSIM_LINK) .\ossim_ndf_plugin.lib
+
+clean:
+	$(RM) *.obj
+	$(RM) $(OSSIM_PLUGIN_LIB_PATH)\$(PLUGIN_ROOT).*
+	$(OSSIM_VC_MANIFEST_CLEAN)
+
diff --git a/ossim_plugins/ndf/ndf_test.cpp b/ossim_plugins/ndf/ndf_test.cpp
new file mode 100644
index 0000000..d4c20fd
--- /dev/null
+++ b/ossim_plugins/ndf/ndf_test.cpp
@@ -0,0 +1,24 @@
+//***
+// Written by: Kenneth Melero (kmelero at sanz.com)
+// Description:  This application unit tests the nlaps plugin methods.
+// ***
+
+#include <iostream>
+
+#include <ossimNdfHeader.h>
+#include <ossim/init/ossimInit.h>
+
+using namespace std;
+
+int main(int argc, char *argv[])
+{
+	ossimInit::instance()->initialize(argc, argv);
+   
+	ossimNdfHeader lnh(argv[1]);
+	cout << lnh;
+	cout << lnh.getGeom();
+	
+	cout << "Status: " << lnh.getErrorStatus() << endl;
+
+	return lnh.getErrorStatus();
+}
diff --git a/ossim_plugins/ndf/ossimNdfHeader.cpp b/ossim_plugins/ndf/ossimNdfHeader.cpp
new file mode 100644
index 0000000..c36f0a1
--- /dev/null
+++ b/ossim_plugins/ndf/ossimNdfHeader.cpp
@@ -0,0 +1,591 @@
+//***
+// Written by: Kenneth Melero (kmelero at sanz.com)
+// Description: This class parses header files in National Land Archive Processing System 
+// Data Format (NDF). It currently supports Landsat MSS, TM, and ETM+ sensors.
+//
+// $Id$
+// ***
+
+#include <ossimNdfHeader.h>
+#include <ossim/base/ossimException.h>
+#include <ossim/base/ossimKeywordNames.h>
+#include <ossim/base/ossimNotify.h>
+#include <ossim/base/ossimTrace.h>
+
+#include <iostream>
+#include <cstdlib> /* for abs */
+
+static ossimTrace traceDebug("ossimNdfTileSource:debug");
+
+ossimNdfHeader::ossimNdfHeader(const char* file)
+   :
+   m_file(file),
+   m_kwl(),
+   m_geom(),
+   m_revision(""),
+   m_projection(""),
+   m_utmzone(-1),
+   m_datum(""),
+   m_lines(-1),
+   m_samples(-1),
+   m_ul(0.0,0.0),
+   m_ur(0.0,0.0),
+   m_lr(0.0,0.0),
+   m_ll(0.0,0.0),
+   m_gsd(-1.0),
+   m_satellite(""),
+   m_instrument(""),
+   m_dataset_type(""),
+   m_acqdate(""),
+   m_interleave(""),
+   m_proc_level(-1),
+   m_num_bands(-1),
+   m_sun_elev(-1.0),
+   m_sun_azim(-1.0),
+   m_wrs(""),
+   m_path(-1),
+   m_row(-1)
+{
+   static const char MODULE[] = "ossimNdfHeader::ossimNdfHeader";
+   
+   // Set the delimeter to '=' as the default is ':'
+   m_kwl.change_delimiter('=');
+
+   // Ensure header file exists
+   if(!m_file.exists())
+   {
+      std::string errMsg = MODULE;
+      errMsg += " ERROR: Missing Header File ";
+      errMsg += m_file.string();
+      theErrorStatus = ossimErrorCodes::OSSIM_ERROR;
+      throw ossimException(errMsg);
+   }
+   
+   // Load and parse header with a keywordlist object.
+   if ( m_kwl.addFile(m_file) == false )
+   {
+      theErrorStatus = ossimErrorCodes::OSSIM_ERROR;
+      std::string errMsg = MODULE;
+      errMsg += " keyword list error.";
+      errMsg += m_file.string();
+      throw ossimException(errMsg);
+   }
+
+   // Quickly check if file is supported.  
+   if(!isSupportedNlaps())
+   {
+      theErrorStatus = ossimErrorCodes::OSSIM_ERROR;      
+      std::string errMsg = MODULE;
+      errMsg += " unsupported";
+      errMsg += m_file.string();
+      throw ossimException(errMsg);
+   }
+   
+   // Parse NDF header and further validate.
+   parseHeader();
+}
+
+ossimNdfHeader::~ossimNdfHeader()
+{
+}
+
+void ossimNdfHeader::parseHeader()
+{
+   const char* lookup;
+   
+   // NDF Revision
+   lookup = m_kwl.find("NDF_REVISION");
+   if(lookup)
+   {
+      m_revision = lookup;
+      m_revision.trim(";");
+      
+      m_geom.add("ndf_revision", m_revision, true);
+   }
+   
+   // Projection
+   // Support: UTM
+   // Available: Data comes in as UTM, SOM, and Albers
+   lookup = m_kwl.find("MAP_PROJECTION_NAME");
+   if(lookup)
+   {
+      ossimString tmp;
+      tmp = lookup;
+      tmp.trim(";");
+      
+      if(tmp == ossimString("UTM"))
+      {
+         m_projection = "ossimUtmProjection";
+      }
+      else
+      {
+         theErrorStatus = ossimErrorCodes::OSSIM_ERROR;
+         return;
+      }
+      
+      m_geom.add(ossimKeywordNames::TYPE_KW, m_projection, true);
+   }
+   
+   // UTM Zone
+   lookup = m_kwl.find("USGS_MAP_ZONE");
+   if(lookup)
+   {
+      ossimString tmp;
+      tmp = lookup;
+      tmp.trim(";");
+      m_utmzone = tmp.toInt();
+      
+      if(m_utmzone > 0)
+      {
+         m_geom.add(ossimKeywordNames::ZONE_KW, m_utmzone, true);
+         m_geom.add(ossimKeywordNames::HEMISPHERE_KW, "N", true);
+      }
+      
+      if(m_utmzone < 0)
+      {
+         m_geom.add(ossimKeywordNames::ZONE_KW, std::abs(m_utmzone), true);
+         m_geom.add(ossimKeywordNames::HEMISPHERE_KW, "S", true);
+      }
+   }
+   
+   // Datum
+   // Support: NAD83, NAD27, WGS84
+   // Available: NAD83, NAD27, WGS84, Ellipsoid
+   lookup = m_kwl.find("HORIZONTAL_DATUM");
+   if(lookup)
+   {
+      ossimString tmp;
+      tmp = lookup;
+      tmp.trim(";");
+      
+      if(tmp == ossimString("NAD83"))
+      {
+         m_datum = "NAR-C";
+      }
+      else if(tmp == ossimString("NAD27"))
+      {
+         m_datum = "NAS-C";
+      }
+      else if(tmp == ossimString("WGS84"))
+      {
+         m_datum = "WGE";
+      }
+      else
+      {
+         theErrorStatus = ossimErrorCodes::OSSIM_ERROR;
+         return;
+      }		 
+      
+      m_geom.add(ossimKeywordNames::DATUM_KW, m_datum, true);
+   }
+   
+   // Lines
+   lookup = m_kwl.find("LINES_PER_DATA_FILE");
+   if(lookup)
+   {
+      ossimString tmp;
+      tmp = lookup;
+      tmp.trim(";");
+      m_lines = tmp.toInt64();
+      
+      m_geom.add(ossimKeywordNames::NUMBER_LINES_KW,
+                 tmp, true);
+   }
+   
+   // Samples
+   lookup = m_kwl.find("PIXELS_PER_LINE");
+   if(lookup)
+   {
+      ossimString tmp;
+      tmp = lookup;
+      tmp.trim(";");
+      m_samples = tmp.toInt64();
+      
+      m_geom.add(ossimKeywordNames::NUMBER_SAMPLES_KW,
+                 tmp, true);
+   }
+   
+   // Ground Sample Distance
+   lookup = m_kwl.find("PIXEL_SPACING");
+   if(lookup)
+   {
+      ossimString tmp;
+      tmp = lookup;
+      tmp.trim(";");
+      m_gsd = tmp.toDouble();
+      
+      m_geom.add(ossimKeywordNames::METERS_PER_PIXEL_X_KW,
+                 m_gsd, true);
+      m_geom.add(ossimKeywordNames::METERS_PER_PIXEL_Y_KW,
+                 m_gsd, true);
+   }
+   
+   // Bands
+   lookup = m_kwl.find("NUMBER_OF_BANDS_IN_VOLUME");
+   if(lookup)
+   {
+      ossimString tmp;
+      tmp = lookup;
+      tmp.trim(";");
+      m_num_bands = tmp.toInt();
+      
+      m_geom.add(ossimKeywordNames::NUMBER_BANDS_KW,
+                 m_num_bands, true);
+   }
+   
+   // Satellite
+   lookup = m_kwl.find("SATELLITE");
+   if(lookup)
+   {
+      m_satellite = lookup;
+      m_satellite.trim(";");
+      
+      m_geom.add("satellite", m_satellite, true);
+   }
+   
+   // Instrument
+   lookup = m_kwl.find("SATELLITE_INSTRUMENT");
+   if(lookup)
+   {
+      m_instrument = lookup;
+      m_instrument.trim(";");
+      
+      if(m_instrument == ossimString("MSS") || m_instrument == ossimString("TM") || m_instrument == ossimString("ETM+"))
+      {
+         // Supported instrument
+      }
+      else
+      {
+         theErrorStatus = ossimErrorCodes::OSSIM_ERROR;
+         return;
+      }
+      
+      m_geom.add("instrument", m_instrument, true);
+   }
+   
+   // Dataset Type
+   lookup = m_kwl.find("DATA_SET_TYPE");
+   if(lookup)
+   {
+      m_dataset_type = lookup;
+      m_dataset_type.trim(";");
+      
+      m_geom.add("dataset_type", m_dataset_type, true);
+   }
+   
+   // Acquisition Date
+   lookup = m_kwl.find("ACQUISITION_DATE/TIME");
+   if(lookup)
+   {
+      ossimString tmp;
+      tmp = lookup;
+      tmp.trim(";");
+      
+      if(m_instrument == ossimString("MSS"))
+      {
+         // UTC date and time of acquisition of reference point in ISO compliant format: YYYY-MM-DDThh:mm:ssZ
+         m_acqdate = tmp.beforePos(10);			
+      }
+      else if (m_instrument == ossimString("TM"))
+      {
+         m_acqdate = tmp.beforePos(6);			
+      }
+      else if (m_instrument == ossimString("ETM+"))
+      {
+         m_acqdate = tmp.beforePos(10);			
+      }
+      
+      m_geom.add("acquisition_date",
+                 m_acqdate, true);
+   }
+   
+   // Interleave
+   lookup = m_kwl.find("DATA_FILE_INTERLEAVING");
+   if(lookup)
+   {
+      m_interleave = lookup;
+      m_interleave.trim(";");
+      
+      m_geom.add(ossimKeywordNames::INTERLEAVE_TYPE_KW,
+                 m_interleave, true);
+   }
+   
+   // Processing Level
+   // Support:  8, 9, or 10
+   // Available: 
+   // - 0: Raw, Uncorrected
+   // - 1: Radiometrically Calibrated, Uncorrected
+   // - 8: Systematically Corrected, Map Projected
+   // - 9: Precision Corrected, Map Projected
+   // - 10: Terrain Corrected, Map Projected
+   lookup = m_kwl.find("PROCESSING_LEVEL");
+   if(lookup)
+   {
+      ossimString tmp;
+      tmp = lookup;
+      tmp.trim(";");
+      
+      if(tmp.contains("8") || tmp.contains("9") || tmp.contains("10"))
+      {
+         m_proc_level = tmp.toInt();
+      }
+      else
+      {
+         theErrorStatus = ossimErrorCodes::OSSIM_ERROR;
+         return;
+      }
+      
+      m_geom.add("processing_level", m_proc_level, true);
+   }
+   
+   // Sun Elevation
+   lookup = m_kwl.find("SUN_ELEVATION");
+   if(lookup)
+   {
+      ossimString tmp;
+      tmp = lookup;
+      tmp.trim(";");
+      
+      m_sun_elev = tmp.toDouble();
+      
+      m_geom.add("sun_elevation",
+                 m_sun_elev, true);
+   }
+   
+   // Sun Azimuth
+   lookup = m_kwl.find("SUN_AZIMUTH");
+   if(lookup)
+   {
+      ossimString tmp;
+      tmp = lookup;
+      tmp.trim(";");
+      
+      m_sun_azim = tmp.toDouble();
+      
+      m_geom.add("sun_azimuth",
+                 m_sun_azim, true);
+   }
+   
+   // WRS (Path and Row)
+   lookup = m_kwl.find("WRS");
+   if(lookup)
+   {
+      ossimString tmp;
+      tmp = lookup;
+      tmp.trim(";");
+      
+      m_wrs = tmp;
+      m_path = tmp.before(ossimString("/")).toInt();
+      m_row = tmp.after(ossimString("/")).toInt();
+      
+      m_geom.add("wrs", m_wrs, true);
+      m_geom.add("path", m_path, true);
+      m_geom.add("row", m_row, true);
+   }
+   
+   // Upper Left Image Footprint
+   lookup = m_kwl.find("UPPER_LEFT_CORNER");
+   if(lookup)
+   {
+      ossimString tmp;
+      tmp = lookup;
+      tmp.trim(";");
+      
+      std::vector<ossimString> tmp_vec;
+      tmp_vec = tmp.explode(ossimString(","));
+      
+      m_ul = ossimDpt(tmp_vec[2].toDouble(),
+                      tmp_vec[3].toDouble());
+      
+      m_geom.add(ossimKeywordNames::TIE_POINT_EASTING_KW,
+                 m_ul.x, true);
+      m_geom.add(ossimKeywordNames::TIE_POINT_NORTHING_KW,
+                 m_ul.y, true);
+      
+      m_geom.add("hdr_ul_easting", m_ul.x, true);
+      m_geom.add("hdr_ul_northing", m_ul.y, true);
+   }
+   
+   // Upper Right Image Footprint
+   lookup = m_kwl.find("UPPER_RIGHT_CORNER");
+   if(lookup)
+   {
+      ossimString tmp;
+      tmp = lookup;
+      tmp.trim(";");
+      
+      std::vector<ossimString> tmp_vec;
+      tmp_vec = tmp.explode(ossimString(","));
+      
+      m_ur = ossimDpt(tmp_vec[2].toDouble(),
+                      tmp_vec[3].toDouble());
+      
+      m_geom.add("hdr_ur_easting", m_ur.x, true);
+      m_geom.add("hdr_ur_northing", m_ur.y, true);
+   }
+   
+   // Lower Right Image Footprint
+   lookup = m_kwl.find("LOWER_RIGHT_CORNER");
+   if(lookup)
+   {
+      ossimString tmp;
+      tmp = lookup;
+      tmp.trim(";");
+      
+      std::vector<ossimString> tmp_vec;
+      tmp_vec = tmp.explode(ossimString(","));
+      
+      m_lr = ossimDpt(tmp_vec[2].toDouble(),
+                      tmp_vec[3].toDouble());
+      
+      m_geom.add("hdr_lr_easting", m_lr.x, true);
+      m_geom.add("hdr_lr_northing", m_lr.y, true);
+      
+   }
+   
+   // Lower Left Image Footprint
+   lookup = m_kwl.find("LOWER_LEFT_CORNER");
+   if(lookup)
+   {
+      ossimString tmp;
+      tmp = lookup;
+      tmp.trim(";");
+      
+      std::vector<ossimString> tmp_vec;
+      tmp_vec = tmp.explode(ossimString(","));
+      
+      m_ll = ossimDpt(tmp_vec[2].toDouble(),
+                      tmp_vec[3].toDouble());
+      
+      m_geom.add("hdr_ll_easting", m_ll.x, true);
+      m_geom.add("hdr_ll_northing", m_ll.y, true);
+   }
+   
+   // Band Information
+   for(ossim_uint32 i = 1; i <= m_num_bands; ++i)
+   {
+      ossimString srch;
+      
+      srch = "BAND" + ossimString::toString(i) + "_NAME";
+      lookup = m_kwl.find(srch);
+      if(lookup)
+      {
+         m_band_name.push_back(ossimString(lookup).trim(";"));
+      }
+      
+      srch = "BAND" + ossimString::toString(i) + "_FILENAME";
+      lookup = m_kwl.find(srch);
+      if(lookup)
+      {
+         ossimFilename img_file =
+            m_file.path().dirCat(ossimFilename(ossimString(lookup).trim(";")));
+         
+         if(img_file.exists())
+         {
+            m_band_filename.push_back(img_file);
+         }
+         else
+         {
+            ossimNotify(ossimNotifyLevel_WARN)
+               << "ERROR: Image File Does Not Exists or Is Missing (" 
+                 << img_file << ")" << std::endl;
+            theErrorStatus = ossimErrorCodes::OSSIM_ERROR;
+            return;
+         }
+      }
+      else
+      {
+         ossimFilename img_file = m_file.path() + "/" + m_file.fileNoExtension() + ".I" + ossimString::toString(i);
+
+         if(img_file.exists())
+         {
+            m_band_filename.push_back(img_file);
+         }
+         else
+         {
+            ossimNotify(ossimNotifyLevel_WARN)
+               << "ERROR: Image File Does Not Exists or Is Missing (" 
+                 << img_file << ")" << std::endl;
+            theErrorStatus = ossimErrorCodes::OSSIM_ERROR;
+            return;
+         }
+      }
+
+      srch = "BAND" + ossimString::toString(i) + "_WAVELENGTHS";
+      lookup = m_kwl.find(srch);
+      if(lookup)
+      {
+         m_band_wavelengths.push_back(ossimString(lookup).trim(";"));
+      }
+
+      srch = "BAND" + ossimString::toString(i) + "_RADIOMETRIC_GAINS/BIAS";
+      lookup = m_kwl.find(srch);
+      if(lookup)
+      {
+         m_band_radiom_gains_bias.push_back(ossimString(lookup).trim(";"));
+      }
+   }
+}
+
+ossimKeywordlist ossimNdfHeader::getGeom()
+{
+   return m_geom;
+}
+
+bool ossimNdfHeader::isSupportedNlaps()
+{
+   ossimString r = m_kwl.find("NDF_REVISION");
+
+   if(r.size() > 0)
+      return true;
+   else
+      return false;
+}
+
+std::ostream& operator << (std::ostream& o, const ossimNdfHeader& head)
+{
+   if(head.theErrorStatus == ossimErrorCodes::OSSIM_ERROR)
+   {
+      // Error exists parsing file
+      return o;
+   }
+   else
+   {
+      o << std::endl;
+      o << "NDF Revision: " << head.m_revision << std::endl;
+      o << "Map Projection: " << head.m_projection << std::endl;
+      o << "UTM Zone: " << head.m_utmzone << std::endl;
+      o << "Datum: " << head.m_datum << std::endl;
+      o << "Lines: " << head.m_lines << std::endl;
+      o << "Samples: " << head.m_samples << std::endl;
+	
+      o << "UL: " << head.m_ul << std::endl;
+      o << "UR: " << head.m_ur << std::endl;
+      o << "LR: " << head.m_lr << std::endl;
+      o << "LL: " << head.m_ll << std::endl;
+      o << "GSD: " << head.m_gsd << std::endl;
+
+      o << "Satellite: " << head.m_satellite << std::endl;
+      o << "Instrument: " << head.m_instrument << std::endl;
+      o << "Dataset Type: " << head.m_dataset_type << std::endl;
+      o << "Acquisition Date: " << head.m_acqdate << std::endl;
+      o << "Interleave: " << head.m_interleave << std::endl;
+      o << "Processing Level: " << head.m_proc_level << std::endl;
+      o << "Number of Bands: " << head.m_num_bands << std::endl;
+      o << "Sun Elevation: " << head.m_sun_elev << std::endl;
+      o << "Sun Azimuth: " << head.m_sun_azim << std::endl;
+      o << "WRS: " << head.m_wrs << std::endl;
+      o << "Path: " << head.m_path << std::endl;
+      o << "Row: " << head.m_row << std::endl;
+
+      for(ossim_uint32 i = 0; i < head.m_num_bands; ++i)
+      {
+         o << "Band Name: " << head.m_band_name[i] << std::endl;
+         o << "Band Wavelengths: " << head.m_band_wavelengths[i] << std::endl;
+         o << "Band Radmiometry Gains/Bias: " << head.m_band_radiom_gains_bias[i] << std::endl;
+         o << "Band Filename: " << head.m_band_filename[i] << std::endl;
+      }
+
+      return o;
+   }
+}
diff --git a/ossim_plugins/ndf/ossimNdfHeader.h b/ossim_plugins/ndf/ossimNdfHeader.h
new file mode 100644
index 0000000..c1bdef4
--- /dev/null
+++ b/ossim_plugins/ndf/ossimNdfHeader.h
@@ -0,0 +1,79 @@
+//***
+// Written by: Kenneth Melero (kmelero at sanz.com)
+// Description: This class parses header files in National Land Archive Processing System 
+//              Data Format (NDF). It currently supports Landsat MSS, TM,
+//              and ETM+ sensors.
+//              
+// ***
+// $Id$
+#ifndef ossimNdfHeader_HEADER
+#define ossimNdfHeader_HEADER 1
+
+#include "../ossimPluginConstants.h"
+#include <ossim/base/ossimErrorCodes.h>
+#include <ossim/base/ossimErrorStatusInterface.h>
+#include <ossim/base/ossimFilename.h>
+#include <ossim/base/ossimDpt.h>
+#include <ossim/base/ossimKeywordlist.h>
+
+#include <ostream>
+#include <vector>
+
+class OSSIM_PLUGINS_DLL ossimNdfHeader : public ossimErrorStatusInterface
+{
+public:
+   ossimNdfHeader(const char* file);
+   virtual ~ossimNdfHeader();
+
+   friend OSSIM_PLUGINS_DLL std::ostream& operator <<
+      (std::ostream& out, const ossimNdfHeader& head);
+   
+   ossimKeywordlist getGeom();
+   std::vector<ossimFilename> getImageFileList() { return m_band_filename; }
+   ossim_int64 getLines() { return m_lines; }
+   ossim_int64 getSamples() { return m_samples; }
+   ossim_uint32 getNumOfBands() { return m_num_bands; }
+   
+private:
+   ossimNdfHeader();  // prevent use
+   
+   bool isSupportedNlaps();
+   void parseHeader();
+   
+   ossimFilename    m_file;  // Source Filename
+   ossimKeywordlist m_kwl;   // Source Header
+   ossimKeywordlist m_geom;  // Converted Header to OSSIM Geometry
+   
+   ossimString  m_revision;
+   ossimString  m_projection;
+   ossim_sint32 m_utmzone;
+   ossimString  m_datum;
+   ossim_int64  m_lines;
+   ossim_int64  m_samples;
+   
+   ossimDpt m_ul;
+   ossimDpt m_ur;
+   ossimDpt m_lr;
+   ossimDpt m_ll;
+   ossim_float64 m_gsd;
+   
+   ossimString   m_satellite;
+   ossimString   m_instrument;
+   ossimString   m_dataset_type;
+   ossimString   m_acqdate;
+   ossimString   m_interleave;
+   ossim_uint32  m_proc_level;
+   ossim_uint32  m_num_bands;
+   ossim_float64 m_sun_elev;
+   ossim_float64 m_sun_azim;
+   ossimString   m_wrs;
+   ossim_uint32  m_path;
+   ossim_uint32  m_row;
+   
+   std::vector<ossimString>   m_band_name;
+   std::vector<ossimFilename> m_band_filename;
+   std::vector<ossimString>   m_band_wavelengths;
+   std::vector<ossimString>   m_band_radiom_gains_bias;
+};
+
+#endif 
diff --git a/ossim_plugins/ndf/ossimNdfPluginInit.cpp b/ossim_plugins/ndf/ossimNdfPluginInit.cpp
new file mode 100644
index 0000000..3a6919b
--- /dev/null
+++ b/ossim_plugins/ndf/ossimNdfPluginInit.cpp
@@ -0,0 +1,63 @@
+//***
+// Written by: Kenneth Melero (kmelero at sanz.com)
+// ***
+
+#include "../ossimPluginConstants.h"
+#include "ossimNdfReaderFactory.h"
+#include <ossim/plugin/ossimSharedObjectBridge.h>
+#include <ossim/imaging/ossimImageHandlerRegistry.h>
+
+static void setDescription(ossimString& description)
+{
+   description = "NLAPS Data Format (NDF) Reader Plugin\n\n";
+}
+
+extern "C"
+{
+   ossimSharedObjectInfo  myInfo;
+   ossimString theDescription;
+   std::vector<ossimString> theObjList;
+
+   const char* getDescription()
+   {
+      return theDescription.c_str();
+   }
+
+   int getNumberOfClassNames()
+   {
+      return (int)theObjList.size();
+   }
+
+   const char* getClassName(int idx)
+   {
+      if(idx < (int)theObjList.size())
+      {
+         return theObjList[0].c_str();
+      }
+      return (const char*)0;
+   }
+   
+   /* Note symbols need to be exported on windoze... */ 
+   OSSIM_PLUGINS_DLL void ossimSharedLibraryInitialize(ossimSharedObjectInfo** info)
+   {    
+      myInfo.getDescription = getDescription;
+      myInfo.getNumberOfClassNames = getNumberOfClassNames;
+      myInfo.getClassName = getClassName;
+      
+      *info = &myInfo;
+      
+      /**
+       * Register the reader...
+       */
+      ossimImageHandlerRegistry::instance()->
+         registerFactory(ossimNdfReaderFactory::instance(), false);
+      
+      setDescription(theDescription);
+   }
+   
+   /* Note symbols need to be exported on windoze... */ 
+   OSSIM_PLUGINS_DLL void ossimSharedLibraryFinalize()
+   {
+      ossimImageHandlerRegistry::instance()->unregisterFactory(ossimNdfReaderFactory::instance());
+   }
+}
diff --git a/ossim_plugins/ndf/ossimNdfReaderFactory.cpp b/ossim_plugins/ndf/ossimNdfReaderFactory.cpp
new file mode 100644
index 0000000..9bcca1d
--- /dev/null
+++ b/ossim_plugins/ndf/ossimNdfReaderFactory.cpp
@@ -0,0 +1,124 @@
+//***
+// Written by: Kenneth Melero (kmelero at sanz.com)
+//
+// $Id$
+// ***
+
+#include "ossimNdfReaderFactory.h"
+#include "ossimNdfTileSource.h"
+#include <ossim/base/ossimKeywordlist.h>
+#include <ossim/base/ossimString.h>
+#include <ossim/imaging/ossimImageHandler.h>
+#include <ossim/base/ossimTrace.h>
+#include <ossim/base/ossimKeywordNames.h>
+
+static const ossimTrace traceDebug("ossimNdfReaderFactory:debug");
+
+RTTI_DEF1(ossimNdfReaderFactory, "ossimNdfReaderFactory", ossimImageHandlerFactoryBase);
+
+ossimNdfReaderFactory* ossimNdfReaderFactory::theInstance = 0;
+
+ossimNdfReaderFactory::~ossimNdfReaderFactory()
+{
+   theInstance = 0;
+}
+
+ossimNdfReaderFactory* ossimNdfReaderFactory::instance()
+{
+   if(!theInstance)
+   {
+      theInstance = new ossimNdfReaderFactory;
+   }
+   return theInstance;
+}
+
+ossimImageHandler* ossimNdfReaderFactory::open(const ossimFilename& fileName,
+                                               bool openOverview) const
+{
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimNdfReaderFactory::open(filename) DEBUG: entered..."
+         << "\nTrying ossimNdfTileSource"
+         << std::endl;
+   }
+   
+   ossimRefPtr<ossimImageHandler> reader = new ossimNdfTileSource;
+   reader->setOpenOverviewFlag(openOverview);
+   if(reader->open(fileName) == false)
+   {
+      reader = 0;
+   }
+   
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimNdfReaderFactory::open(filename) DEBUG: exit status = "
+         << (reader.get()?"success":"failure")
+         << std::endl;
+   }
+   
+   return reader.release();
+}
+
+ossimImageHandler* ossimNdfReaderFactory::open(const ossimKeywordlist& kwl,
+                                               const char* prefix) const
+{
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimNdfReaderFactory::open(kwl, prefix) DEBUG: entered..."
+         << "Trying ossimNdfTileSource"
+         << std::endl;
+   }
+   
+   ossimRefPtr<ossimImageHandler> reader = new ossimNdfTileSource;
+   if(reader->loadState(kwl, prefix) == false)
+   {
+      reader = 0;
+   }
+   
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimNdfReaderFactory::open(kwl, prefix) DEBUG: leaving..."
+         << std::endl;
+   }
+   
+   return reader.release();
+}
+
+ossimObject* ossimNdfReaderFactory::createObject(const ossimString& typeName) const
+{
+   if(typeName == "ossimNdfTileSource")
+   {
+      return new ossimNdfTileSource;
+   }
+   return 0;
+}
+
+ossimObject* ossimNdfReaderFactory::createObject(const ossimKeywordlist& kwl,
+                                                 const char* prefix) const
+{
+   return this->open(kwl, prefix);
+}
+ 
+void ossimNdfReaderFactory::getTypeNameList(std::vector<ossimString>& typeList) const
+{
+   typeList.push_back(ossimString("ossimNdfTileSource"));
+}
+
+void ossimNdfReaderFactory::getSupportedExtensions(
+   ossimImageHandlerFactoryBase::UniqueStringList& extensionList) const
+{
+   extensionList.push_back(ossimString("h1"));
+   extensionList.push_back(ossimString("h2"));
+   extensionList.push_back(ossimString("h3"));
+   extensionList.push_back(ossimString("hd"));
+}
+
+ossimNdfReaderFactory::ossimNdfReaderFactory() {}
+
+ossimNdfReaderFactory::ossimNdfReaderFactory(const ossimNdfReaderFactory&) {}
+
+void ossimNdfReaderFactory::operator=(const ossimNdfReaderFactory&) {}
diff --git a/ossim_plugins/ndf/ossimNdfReaderFactory.h b/ossim_plugins/ndf/ossimNdfReaderFactory.h
new file mode 100644
index 0000000..3ec4fbd
--- /dev/null
+++ b/ossim_plugins/ndf/ossimNdfReaderFactory.h
@@ -0,0 +1,49 @@
+//***
+// Written by: Kenneth Melero (kmelero at sanz.com)
+// ***
+
+#ifndef ossimNdfReaderFactory_HEADER
+#define ossimNdfReaderFactory_HEADER
+
+#include <ossim/imaging/ossimImageHandlerFactoryBase.h>
+
+class ossimString;
+class ossimFilename;
+class ossimKeywordlist;
+
+class ossimNdfReaderFactory : public ossimImageHandlerFactoryBase
+{
+public:
+   virtual ~ossimNdfReaderFactory();
+   static ossimNdfReaderFactory* instance();
+
+   /**
+    * @brief open that takes a file name.
+    * @param file The file to open.
+    * @param openOverview If true image handler will attempt to open overview.
+    * default = true 
+    * @return pointer to image handler on success, NULL on failure.
+    */
+   virtual ossimImageHandler* open(const ossimFilename& fileName,
+                                   bool openOverview=true) const;
+
+   virtual ossimImageHandler* open(const ossimKeywordlist& kwl,
+                                   const char* prefix=0)const;
+   virtual ossimObject* createObject(const ossimString& typeName)const;
+   virtual ossimObject* createObject(const ossimKeywordlist& kwl,
+                                     const char* prefix=0)const;
+   virtual void getTypeNameList(std::vector<ossimString>& typeList)const;
+   virtual void getSupportedExtensions(
+      ossimImageHandlerFactoryBase::UniqueStringList& extensionList)const;
+  
+protected:
+   ossimNdfReaderFactory();
+
+   ossimNdfReaderFactory(const ossimNdfReaderFactory&);
+   void operator=(const ossimNdfReaderFactory&);
+   static ossimNdfReaderFactory* theInstance;
+
+TYPE_DATA
+};
+
+#endif
diff --git a/ossim_plugins/ndf/ossimNdfTileSource.cpp b/ossim_plugins/ndf/ossimNdfTileSource.cpp
new file mode 100644
index 0000000..316e524
--- /dev/null
+++ b/ossim_plugins/ndf/ossimNdfTileSource.cpp
@@ -0,0 +1,304 @@
+//***
+// Written by: Kenneth Melero (kmelero at sanz.com)
+//
+// $Id$
+// ***
+
+#include <ossimNdfHeader.h>
+#include <ossimNdfTileSource.h>
+#include <ossim/base/ossimDirectory.h>
+#include <ossim/base/ossimException.h>
+#include <ossim/base/ossimNotify.h>
+#include <ossim/base/ossimKeywordNames.h>
+#include <ossim/base/ossimTrace.h>
+#include <ossim/imaging/ossimImageGeometryRegistry.h>
+#include <ossim/projection/ossimProjection.h>
+#include <ossim/projection/ossimProjectionFactoryRegistry.h>
+
+RTTI_DEF1_INST(ossimNdfTileSource,
+               "ossimNdfTileSource",
+               ossimGeneralRasterTileSource)
+
+static ossimTrace traceDebug("ossimNdfTileSource:debug");
+
+ossimNdfTileSource::ossimNdfTileSource()
+   :
+   ossimGeneralRasterTileSource(),
+   theHeaderFile()
+{ }
+
+ossimNdfTileSource::ossimNdfTileSource(const ossimKeywordlist& kwl,
+                                       const char* prefix)
+   :
+   ossimGeneralRasterTileSource(),
+   theHeaderFile()
+{
+   if (loadState(kwl, prefix) == false)
+   {
+      theErrorStatus = ossimErrorCodes::OSSIM_ERROR;
+   }
+}
+
+ossimNdfTileSource::~ossimNdfTileSource()
+{ }
+
+bool ossimNdfTileSource::open()
+{
+   // Ensure header file exists
+   if(!theHeaderFile.exists())
+   {
+      theErrorStatus = ossimErrorCodes::OSSIM_ERROR;
+      if ( traceDebug() )
+      {
+         ossimNotify(ossimNotifyLevel_WARN)
+            << "ERROR: Missing Header File ("
+            << theHeaderFile << ")" << std::endl;
+      }
+      return false;
+   }
+
+   try
+   {
+      // Validate Header to ensure we support this data type
+      ossimNdfHeader lnh(theHeaderFile);
+      if(lnh.getErrorStatus())
+      {
+         theErrorStatus = ossimErrorCodes::OSSIM_ERROR;
+         return false;
+      }
+
+      // Use General Raster classes to build NLAPS imagery
+      ossimGeneralRasterInfo generalRasterInfo;
+      if(lnh.getNumOfBands() == 1)
+      {
+         generalRasterInfo = ossimGeneralRasterInfo(lnh.getImageFileList(),
+                                                    OSSIM_UINT8,
+                                                    OSSIM_BSQ,
+                                                    lnh.getNumOfBands(),
+                                                    lnh.getLines(),
+                                                    lnh.getSamples(),
+                                                    0,
+                                                    ossimGeneralRasterInfo::NONE,
+                                                    0);
+      }
+      else
+      {
+         generalRasterInfo = ossimGeneralRasterInfo(lnh.getImageFileList(),
+                                                    OSSIM_UINT8,
+                                                    OSSIM_BSQ_MULTI_FILE,
+                                                    lnh.getNumOfBands(),
+                                                    lnh.getLines(),
+                                                    lnh.getSamples(),
+                                                    0,
+                                                    ossimGeneralRasterInfo::NONE,
+                                                    0);
+      }
+      
+      theMetaData.clear();
+      theMetaData.setScalarType(OSSIM_UINT8);
+      theMetaData.setNumberOfBands(lnh.getNumOfBands());
+      m_rasterInfo = generalRasterInfo;
+      
+      if(initializeHandler())
+      {
+         completeOpen();
+      }
+      else
+      {
+         theErrorStatus = ossimErrorCodes::OSSIM_ERROR;
+         return false;
+      }  
+   }
+   catch (const ossimException& e)
+   {
+      if ( traceDebug() )
+      {
+         ossimNotify(ossimNotifyLevel_WARN)
+            << "ossimNdfTileSource::open caught exception:\n"
+            << e.what() << std::endl;
+      }
+      return false;
+   }
+   
+   return true;
+}
+  
+ossimRefPtr<ossimImageGeometry> ossimNdfTileSource::getImageGeometry()
+{
+   if ( !theGeometry )
+   {
+      // Check for external geom:
+      theGeometry = getExternalImageGeometry();
+      
+      if ( !theGeometry )
+      {
+         theGeometry = new ossimImageGeometry();
+         
+         // Validate Header to ensure we support this data type
+         ossimNdfHeader lnh(theHeaderFile);
+         if(lnh.getErrorStatus() == ossimErrorCodes::OSSIM_OK)
+         {
+            // Get the projection info.
+            ossimKeywordlist kwl;
+            kwl.add(lnh.getGeom());
+            
+            // Create the projection.
+            ossimRefPtr<ossimProjection> proj = ossimProjectionFactoryRegistry::instance()->
+               createProjection(kwl);
+            
+            if ( proj.valid() )
+            {
+               // Assign projection to our ossimImageGeometry object.
+               theGeometry->setProjection( proj.get() );
+            }
+         }
+         
+         // At this point it is assured theGeometry is set.
+
+         //---
+         // WARNING:
+         // Must create/set theGeometry at this point or the next call to
+         // ossimImageGeometryRegistry::extendGeometry will put us in an infinite loop
+         // as it does a recursive call back to ossimImageHandler::getImageGeometry().
+         //---         
+         
+         // Check for set projection.
+         if ( !theGeometry->getProjection() )
+         {
+            // Try factories for projection.
+            ossimImageGeometryRegistry::instance()->extendGeometry(this);
+         }
+      }
+      
+      // Set image things the geometry object should know about.
+      initImageParameters( theGeometry.get() );
+   }
+   
+   return theGeometry;
+}
+
+bool ossimNdfTileSource::saveState(ossimKeywordlist& kwl,
+                                   const char* prefix)const
+{
+   kwl.add(prefix, "header_filename", theHeaderFile.c_str(), true);
+
+   return ossimGeneralRasterTileSource::saveState(kwl, prefix);
+}
+
+bool ossimNdfTileSource::loadState(const ossimKeywordlist& kwl,
+                                   const char* prefix)
+{
+   const char* lookup = kwl.find(prefix, "header_filename");
+   if (lookup)
+   {
+      theHeaderFile = lookup;
+      return ossimGeneralRasterTileSource::loadState(kwl, prefix);
+   }
+
+   theErrorStatus = ossimErrorCodes::OSSIM_ERROR;
+
+   return false;
+
+#if 0
+   if(lookup)
+   {
+      // Validate Header to ensure we support this data type
+      ossimNdfHeader lnh(lookup);
+      if(lnh.getErrorStatus())
+      {
+         theErrorStatus = ossimErrorCodes::OSSIM_ERROR;
+         return false;
+      }
+      
+      // Use General Raster classes to build NLAPS imagery
+      ossimGeneralRasterInfo generalRasterInfo;
+      if(lnh.getNumOfBands() == 1)
+      {
+         generalRasterInfo = ossimGeneralRasterInfo(lnh.getImageFileList(),
+                                                    OSSIM_UINT8,
+                                                    OSSIM_BSQ,
+                                                    lnh.getNumOfBands(),
+                                                    lnh.getLines(),
+                                                    lnh.getSamples(),
+                                                    0,
+                                                    ossimGeneralRasterInfo::NONE,
+                                                    0);
+      }
+      else
+      {
+         generalRasterInfo = ossimGeneralRasterInfo(lnh.getImageFileList(),
+                                                    OSSIM_UINT8,
+                                                    OSSIM_BSQ_MULTI_FILE,
+                                                    lnh.getNumOfBands(),
+                                                    lnh.getLines(),
+                                                    lnh.getSamples(),
+                                                    0,
+                                                    ossimGeneralRasterInfo::NONE,
+                                                    0);
+      }
+      
+      return open(generalRasterInfo);   
+   }
+   else
+   {
+      theErrorStatus = ossimErrorCodes::OSSIM_ERROR;
+      return false;
+   }
+#endif
+}
+
+bool ossimNdfTileSource::open(const ossimGeneralRasterInfo& info)
+{
+   return ossimGeneralRasterTileSource::open(info);
+}
+
+ossimString ossimNdfTileSource::getShortName() const
+{
+   return ossimString("ossim_ndf");
+}
+
+ossimString ossimNdfTileSource::getLongName() const
+{
+   return ossimString("NLAPS Data Format Reader");
+}
+
+ossimString  ossimNdfTileSource::className() const
+{
+   return ossimString("ossimNdfTileSource");
+}
+
+double ossimNdfTileSource::getNullPixelValue(ossim_uint32) const
+{
+   return 0.0;
+}
+
+double ossimNdfTileSource::getMinPixelValue(ossim_uint32) const
+{
+   return 1.0;
+}
+
+double ossimNdfTileSource::getMaxPixelValue(ossim_uint32) const
+{
+   return 255.0;
+}
+
+ossimScalarType ossimNdfTileSource::getOutputScalarType() const
+{
+   return OSSIM_UINT8;
+}
+
+void ossimNdfTileSource::setFilename(const ossimFilename& filename)
+{
+   theHeaderFile = filename;
+   
+   //---
+   // Because all raster band files for multispectral, thermal and pan have
+   // the same filename base we must make a unique name for file like the
+   // overview, histogram, omd and such.  So is header file is
+   // "LE7116034000502150.H1" this will return
+   // "LE7116034000502150_H1" so that things like the overviews will come
+   // out LE7116034000502150_H1.ovr.
+   //---
+   theImageFile =
+      theHeaderFile.substitute(ossimString("."), ossimString("_"), false);
+}
diff --git a/ossim_plugins/ndf/ossimNdfTileSource.h b/ossim_plugins/ndf/ossimNdfTileSource.h
new file mode 100644
index 0000000..b438b3d
--- /dev/null
+++ b/ossim_plugins/ndf/ossimNdfTileSource.h
@@ -0,0 +1,76 @@
+//***
+// Written by: Kenneth Melero (kmelero at sanz.com)
+//
+// $Id$
+// ***
+#ifndef ossimNdfTileSource_HEADER
+#define ossimNdfTileSource_HEADER
+
+#include "../ossimPluginConstants.h"
+#include <ossim/imaging/ossimGeneralRasterTileSource.h>
+
+class OSSIM_PLUGINS_DLL ossimNdfTileSource : public ossimGeneralRasterTileSource
+{
+public:
+   ossimNdfTileSource();
+   ossimNdfTileSource(const ossimKeywordlist& kwl, const char* prefix=0);
+   virtual ~ossimNdfTileSource();
+   
+   virtual bool open();
+   
+   virtual ossimString getShortName() const;
+   virtual ossimString getLongName()  const;
+   virtual ossimString className()    const;
+   
+   virtual double getNullPixelValue(ossim_uint32 band=0) const;
+   virtual double getMinPixelValue(ossim_uint32 band=0) const;
+   virtual double getMaxPixelValue(ossim_uint32 band=0) const;
+   virtual ossimScalarType getOutputScalarType() const;
+
+   /**
+    * Returns the image geometry object associated with this tile source or
+    * NULL if non defined.  The geometry contains full-to-local image
+    * transform as well as projection (image-to-world).
+    */
+   virtual ossimRefPtr<ossimImageGeometry> getImageGeometry();
+
+   /**
+    * Method to save the state of an object to a keyword list.
+    * Return true if ok or false on error.
+    */
+   virtual bool saveState(ossimKeywordlist& kwl,
+                          const char* prefix=0)const;
+
+   /**
+    * Method to the load (recreate) the state of an object from a keyword
+    * list.  Return true if ok or false on error.
+    */
+   virtual bool loadState(const ossimKeywordlist& kwl, const char* prefix=0);
+
+   /**
+    * Sets the filename
+    */
+   virtual void setFilename(const ossimFilename& filename);
+
+   
+private:
+   bool open(const ossimGeneralRasterInfo& info);
+
+   /**
+    * Because all raster band files for multispectral, thermal and pan have
+    * the same filename base we must make a unique name for file like the
+    * overview, histogram, omd and such.  So is header file is
+    * "LE7116034000502150.H1" this will return
+    * "LE7116034000502150_H1" so that things like the overviews will come
+    * out LE7116034000502150_H1.ovr.
+    */
+   // virtual ossimFilename getFilenameBase() const;
+
+   ossimFilename theHeaderFile;
+
+   
+   
+   TYPE_DATA
+};
+
+#endif /* #ifndef ossimNdfTileSource_HEADER */
diff --git a/ossim_plugins/nitro/ossimNitroHandler.cpp b/ossim_plugins/nitro/ossimNitroHandler.cpp
new file mode 100644
index 0000000..ca1a632
--- /dev/null
+++ b/ossim_plugins/nitro/ossimNitroHandler.cpp
@@ -0,0 +1,1525 @@
+#include "ossimNitroHandler.h"
+#include <ossim/imaging/ossimTiffTileSource.h>
+#include <ossim/base/ossimBooleanProperty.h>
+#include <ossim/base/ossimTrace.h>
+#include <ossim/base/ossimScalarTypeLut.h>
+#include <ossim/imaging/ossimImageDataFactory.h>
+#include <ossim/base/ossimNBandLutDataObject.h>
+#include <ossim/imaging/ossimAnnotationPolyObject.h>
+#include <ossim/imaging/ossimAnnotationMultiPolyLineObject.h>
+#include <ossim/imaging/ossimAnnotationFontObject.h>
+#include <ossim/imaging/ossimAnnotationEllipseObject.h>
+
+#include <ossim/base/ossimPolyLine.h>
+
+RTTI_DEF1(ossimNitroHandler, "ossimNitroHandler", ossimImageHandler)
+static const ossimTrace traceDebug("ossimNitroHandler:debug");
+
+ossimNitroHandler::ossimNitroHandler()
+:theReader(0),
+theRecord(0),
+theIoHandle(0),
+theNumberOfImages(0),
+theCurrentImageReader(0),
+theCurrentImageSegment(0),
+theNumberOfBits(0),
+theNumberOfInputBands(0),
+theNumberOfRows(0),
+theNumberOfColumns(0),
+theSubImageSize(0),
+theCurrentImageEntry(0),
+theScalarType(OSSIM_SCALAR_UNKNOWN),
+theReadBuffer(0),
+theSubImage(0),
+theIsVqCompressedFlag(false),
+theEnableAnnotationsFlag(false),
+theAnnotationImage(new ossimRgbImage())
+{
+   nitf_Error e;
+   theSubImage = nitf_SubWindow_construct(&e);
+   
+}
+
+ossimNitroHandler::~ossimNitroHandler()
+{
+   if(theSubImage)
+   {
+      nitf_SubWindow_destruct(&theSubImage);
+      theSubImage = 0;
+   }
+   close();
+}
+
+void ossimNitroHandler::close()
+{
+   theAnnotationBounds.makeNan();
+   theAnnotations.clear();
+   if(theCurrentImageReader) 
+   {
+      nitf_ImageReader_destruct(&theCurrentImageReader);
+      theCurrentImageReader = 0;
+   }
+   if(theRecord)
+   {
+      nitf_Record_destruct(&theRecord);
+      theRecord = 0;
+   }
+   if(theReader)
+   {
+      nitf_Reader_destruct(&theReader);
+      theReader = 0;
+   }
+   if(theIoHandle)
+   {
+      nitf_IOHandle_close(theIoHandle);
+   }
+   if(theReadBuffer)
+   {
+      ossim_uint32 i=0;
+      for (i = 0; i < theNumberOfInputBands; i++)
+         NITF_FREE(theReadBuffer[i]);
+      NITF_FREE(theReadBuffer);
+   }
+   theReadBuffer = 0;
+   theCurrentImageSegment = 0;
+   theNumberOfImages = 0;
+   theNumberOfBits = 0;
+   theNumberOfInputBands = 0;
+   theNumberOfRows = 0;
+   theNumberOfColumns = 0;
+   theSubImageSize = 0;
+   theCurrentImageEntry = 0;
+   theIsVqCompressedFlag = false;
+}
+
+bool ossimNitroHandler::open()
+{
+   close();
+   nitf_Error e;
+   theReader = nitf_Reader_construct(&e);
+   if(!theReader)
+   {
+      close(); // clean up
+      return false;
+   }
+   theCurrentImageRect.makeNan();
+   theIoHandle = nitf_IOHandle_create(getFilename().c_str(),
+                                      NITF_ACCESS_READONLY,
+                                      NITF_OPEN_EXISTING, &e);
+   if (NITF_INVALID_HANDLE(theIoHandle))
+   {
+      close();
+      return false;
+   }
+   theRecord = nitf_Reader_read(theReader, theIoHandle, &e);
+   if(!theRecord)
+   {
+      close();
+      return false;
+   }
+   
+   int numImages;
+   if (!nitf_Field_get
+       (theRecord->header->numImages, &numImages, NITF_CONV_INT,
+        NITF_INT32_SZ, &e))
+   {
+      theNumberOfImages = 0;
+   }
+   else
+   {
+      theNumberOfImages = numImages;
+   }
+   
+   int numSegments;
+   /**************************************************************************/
+   /* GRAPHICS                                                               */
+   /**************************************************************************/
+   /* get the # of images from the field */
+   if (!nitf_Field_get(theRecord->header->numGraphics,
+                       &numSegments, NITF_CONV_INT, NITF_INT32_SZ, &e))
+   {
+      theNumberOfGraphicSegments = 0;
+   }
+   else
+   {
+      theNumberOfGraphicSegments = numSegments;
+   }
+   /**************************************************************************/
+   /* TEXT                                                               */
+   /**************************************************************************/
+   /* get the # of images from the field */
+   if (!nitf_Field_get(theRecord->header->numTexts,
+                       &numSegments, NITF_CONV_INT, NITF_INT32_SZ, &e))
+   {
+      theNumberOfTextSegments = 0;
+   }
+   else
+   {
+      theNumberOfTextSegments = numSegments;
+   }
+   
+   /**************************************************************************/
+   /* TEXT                                                               */
+   /**************************************************************************/
+   /* get the # of images from the field */
+   if (!nitf_Field_get(theRecord->header->numLabels,
+                       &numSegments, NITF_CONV_INT, NITF_INT32_SZ, &e))
+   {
+      theNumberOfLabelSegments = 0;
+   }
+   else
+   {
+      theNumberOfLabelSegments = numSegments;
+   }
+   
+   
+   if(theNumberOfImages > 0)
+   {
+      if(!setCurrentEntry(0)) 
+      {
+         return false;
+      }
+   }
+   loadAnnotations();
+   if(theAnnotations.size())
+   {
+      theMaxAnnotationRlevel = 0;
+      ossim_uint32 maxDimension = ossim::max(theAnnotationBounds.width(), theAnnotationBounds.height());
+      while(maxDimension > 128)
+      {
+         maxDimension <<=1;
+         ++theMaxAnnotationRlevel;
+      }
+      ossim_uint32 idx = 0;
+      for(idx=0; idx < theMaxAnnotationRlevel; ++idx)
+      {
+         getAnnotationListForRlevel(idx);
+      }
+   }
+   if(theNumberOfInputBands == 0)
+   {
+      if(theAnnotations.size() > 0)
+      {
+         theNumberOfInputBands = 3;
+         theNumberOfOutputBands = theNumberOfInputBands;
+      }
+   }
+   initializeScalarType();
+   
+   std::cout << "IMAGES === " << theNumberOfImages << std::endl
+   << "LABELS === " << theNumberOfLabelSegments << std::endl
+   << "GRAPHICS = " << theNumberOfGraphicSegments << std::endl;
+   nitf_Uint32 theNumberOfTextSegments;
+   nitf_Uint32 theNumberOfLabelSegments;
+   
+   bool result = ((theNumberOfImages>0)&&
+                  (theAnnotations.size()>0));
+   if(result)
+   {
+      completeOpen();
+   }
+   return result;
+}
+
+ossimRefPtr<ossimImageData> ossimNitroHandler::getTile(const ossimIrect& tileRect,
+                                                       ossim_uint32 resLevel)
+{
+   if(!isSourceEnabled() || !isOpen() || !isValidRLevel(resLevel))
+   {
+      return ossimRefPtr<ossimImageData>();
+   }
+   if(!theTile.valid())
+   {
+      initializeOutputTile();
+   }
+   if(!theTile.valid()) return theTile;
+   theTile->setImageRectangle(tileRect);
+   theTile->makeBlank();
+   if(resLevel > 0)
+   {
+      
+      if (theOverview)
+      {
+         if (theOverview->hasR0() || resLevel)
+         {
+            // Subtract any offsets since the overview doesn't know about them.
+            ossimIrect rr_rect = tileRect - getSubImageOffset(resLevel);
+            
+            //---
+            // If there is a sub image offset then we will not be requesting
+            // the same rectangle as was requested from us.  For this reason,
+            // we'll do a setOrigin, rather than just returning the getTile
+            // result.
+            //---
+            ossimRefPtr<ossimImageData> tileData = theOverview->getTile(rr_rect,
+                                                                        resLevel);
+            if(tileData.valid())
+            {
+               tileData->setImageRectangle(tileRect);
+               
+               if(getOutputScalarType() == OSSIM_USHORT11)
+               {
+                  //---
+                  // Temp fix:
+                  // The overview handler could return a tile of OSSIM_UINT16 if
+                  // the max sample value was not set to 2047.  
+                  //---
+                  tileData->setScalarType(OSSIM_USHORT11);
+               }
+            }
+            if((tileData->getDataObjectStatus() != OSSIM_NULL)&&
+               (tileData->getDataObjectStatus() != OSSIM_EMPTY))
+            {
+               theTile->loadTile(tileData.get());
+               theTile->validate();
+            }
+         }
+      }
+   }
+   else
+   {
+      int padded=0;
+      nitf_Error e;
+      
+      if(resLevel == 0)
+      {
+         theTile->setImageRectangle(tileRect);
+         theTile->makeBlank();
+         if(tileRect.intersects(theCurrentImageRect))
+         {
+            if(theNumberOfImages > 0)
+            {
+               ossimIrect clipRect = theCurrentImageRect.clipToRect(tileRect);
+               
+               theSubImage->startCol = clipRect.ul().x;
+               theSubImage->startRow = clipRect.ul().y;
+               theSubImage->numRows  = clipRect.height();
+               theSubImage->numCols  = clipRect.width();
+               
+               int bufSize = clipRect.width()*clipRect.height()*ossim::scalarSizeInBytes(theScalarType);
+               if(theSubImageSize!=(bufSize))
+               {
+                  ossim_uint32 i=0;
+                  if(theReadBuffer)
+                  {
+                     for (i = 0; i < theNumberOfInputBands; i++)
+                        NITF_FREE(theReadBuffer[i]);
+                     NITF_FREE(theReadBuffer);
+                  }
+                  theReadBuffer = (nitf_Uint8 **) NITF_MALLOC(theNumberOfInputBands * sizeof(nitf_Uint8*));
+                  for(i = 0; i < theNumberOfInputBands; ++i)
+                  {
+                     theReadBuffer[i] = (nitf_Uint8 *) NITF_MALLOC(bufSize);
+                  }
+                  theSubImageSize = bufSize;
+               }
+               if (nitf_ImageReader_read
+                   (theCurrentImageReader, theSubImage, theReadBuffer, &padded, &e))
+               {
+                  // now load per band
+                  //
+                  if(!theLut.valid())
+                  {
+                     ossim_uint32 idx = 0;
+                     for(idx = 0; idx < theNumberOfInputBands; ++idx)
+                     {
+                        theTile->loadBand(theReadBuffer[idx],
+                                          clipRect,
+                                          idx);
+                     }
+                  }
+                  else
+                  {
+                     theUncompressedClipTile->setImageRectangle(clipRect);
+                     lutUncompress(theUncompressedClipTile, theReadBuffer[0]);
+                     theTile->loadTile(theUncompressedClipTile.get());
+                  }
+                  theTile->validate();
+               }
+               else
+               {
+                  nitf_Error_print(&e, stderr, "image read failed");
+                  
+               }
+            }
+         }
+      }
+   }
+   
+   // now merge the annotations into the image tile
+   //
+   if(theAnnotations.size()&&theEnableAnnotationsFlag)
+   {
+      ossim_uint32 numberOfOutputBands = theTile->getNumberOfBands();
+      ossim_uint8* srcBandPtr[3];
+      theRgbAnnotationImageData->setImageRectangle(tileRect);
+      theRgbAnnotationImageData->makeBlank();
+      
+      
+      //      drawAnnotations(theTile, resLevel);
+      drawAnnotations(theRgbAnnotationImageData, resLevel);
+      
+      if((theRgbAnnotationImageData->getDataObjectStatus()!=OSSIM_EMPTY)&&
+         (theRgbAnnotationImageData->getDataObjectStatus()!=OSSIM_NULL))
+      {
+         
+         // now merge annotations to destination tile
+         srcBandPtr[0] = (ossim_uint8*)theRgbAnnotationImageData->getBuf(0);
+         srcBandPtr[1] = (ossim_uint8*)theRgbAnnotationImageData->getBuf(1);
+         srcBandPtr[2] = (ossim_uint8*)theRgbAnnotationImageData->getBuf(2);
+         
+         switch(theTile->getScalarType())
+         {
+            case OSSIM_UINT8:
+            {
+               ossim_uint8* bandBuf = 0;
+               ossim_uint8 minPix = 0.0;
+               ossim_uint8 maxPix = 0.0;
+               ossim_uint8 nullPix = 0.0;
+               ossim_uint8 deltaPix = 254;
+               ossim_uint8 color = 0;
+               ossim_uint32 bands = ossim::min((ossim_uint32)3, (ossim_uint32)numberOfOutputBands);
+               ossim_uint32 bandIdx = 0;
+               ossim_uint32 offsetBounds = theTile->getWidth()*theTile->getHeight();
+               ossim_uint32 offset = 0;
+               for(bandIdx = 0; bandIdx < bands; ++bandIdx)
+               {
+                  bandBuf = (ossim_uint8*)theTile->getBuf(bandIdx);
+                  minPix  = ossim::defaultMin(theTile->getScalarType());
+                  maxPix  = ossim::defaultMax(theTile->getScalarType());
+                  nullPix = (ossim_uint8)theTile->getNullPix(bandIdx);
+                  deltaPix = maxPix-minPix;
+                  for(offset = 0; offset < offsetBounds; ++offset)
+                  {
+                     
+                     if((srcBandPtr[0][offset] != 0)&&
+                        (srcBandPtr[1][offset] != 0)&&
+                        (srcBandPtr[2][offset] != 0))
+                     {
+                        if(bands == 1)
+                        {
+                           color = static_cast<ossim_uint8>(((float)srcBandPtr[0][offset] + 
+                                                             (float)srcBandPtr[1][offset] +
+                                                             (float)srcBandPtr[2][offset])/3.0);
+                        }
+                        else
+                        {
+                           color = static_cast<ossim_uint8>(minPix + deltaPix*((srcBandPtr[bandIdx][offset])/255.0));
+                        }
+                        *bandBuf =  color;
+                     }
+                     ++bandBuf;
+                  }
+               }
+               break;
+            }
+            case OSSIM_USHORT11:
+            case OSSIM_UINT16:
+            {
+               ossim_uint16* bandBuf = 0;
+               ossim_uint16 minPix = 0.0;
+               ossim_uint16 maxPix = 0.0;
+               ossim_uint16 nullPix = 0.0;
+               ossim_uint16 deltaPix = 254;
+               ossim_uint16 color = 0;
+               ossim_uint32 bands = ossim::min((ossim_uint32)3, (ossim_uint32)numberOfOutputBands);
+               ossim_uint32 bandIdx = 0;
+               ossim_uint32 offsetBounds = theTile->getWidth()*theTile->getHeight();
+               ossim_uint32 offset = 0;
+               for(bandIdx = 0; bandIdx < bands; ++bandIdx)
+               {
+                  bandBuf = (ossim_uint16*)theTile->getBuf(bandIdx);
+                  minPix  = ossim::defaultMin(theTile->getScalarType());
+                  maxPix  = ossim::defaultMax(theTile->getScalarType());
+                  nullPix = (ossim_uint16)theTile->getNullPix(bandIdx);
+                  deltaPix = maxPix-minPix;
+                  for(offset = 0; offset < offsetBounds; ++offset)
+                  {
+                     if((srcBandPtr[0][offset] != 0)&&
+                        (srcBandPtr[1][offset] != 0)&&
+                        (srcBandPtr[2][offset] != 0))
+                     {
+                        if(bands == 1)
+                        {
+                           color = static_cast<ossim_uint16>(((float)srcBandPtr[0][offset] + 
+                                                              (float)srcBandPtr[1][offset] +
+                                                              (float)srcBandPtr[2][offset])/3.0);
+                        }
+                        else
+                        {
+                           color = static_cast<ossim_uint16>(minPix + deltaPix*((srcBandPtr[bandIdx][offset])/255.0));
+                        }
+                        *bandBuf =  color;
+                     }
+                     ++bandBuf;
+                  }
+               }
+               break;
+            }
+            default:
+            {
+               break;
+            }
+         }
+         
+         theTile->validate();
+      }
+   }
+   return theTile;
+}
+
+void ossimNitroHandler::drawAnnotations(ossimRefPtr<ossimImageData> result, ossim_uint32 resLevel)
+{
+   if((result->getScalarType() == OSSIM_UINT8)&&
+      ((result->getNumberOfBands() == 1)||
+       (result->getNumberOfBands() == 3)))
+   {
+      ossimIrect tempRect = result->getImageRectangle();
+      result->setImageRectangle(tempRect);
+      theAnnotationImage->setCurrentImageData(result);
+      
+      std::vector<ossimRefPtr<ossimAnnotationObject> >* currentList = getAnnotationListForRlevel(resLevel);
+      
+      if(currentList)
+      {
+         ossim_uint32 idx = 0;
+         for(idx=0; idx < currentList->size(); ++idx)
+         {
+            (*currentList)[idx]->draw(*theAnnotationImage);
+         }
+         result->setImageRectangle(tempRect);
+         result->validate();
+      }
+   }
+   
+}
+
+
+ossim_uint32 ossimNitroHandler::getNumberOfInputBands() const
+{
+   return theNumberOfInputBands;
+}
+
+ossim_uint32 ossimNitroHandler::getNumberOfOutputBands() const
+{
+   return theNumberOfOutputBands;
+}
+
+ossim_uint32 ossimNitroHandler::getNumberOfLines(ossim_uint32 reduced_res_level) const
+{
+   if (reduced_res_level == 0)
+   {
+      return  theNumberOfRows;
+   }
+   else if (theOverview)
+   {
+      return theOverview->getNumberOfLines(reduced_res_level);
+   }
+   return 0;
+}
+
+ossim_uint32 ossimNitroHandler::getNumberOfSamples(ossim_uint32 reduced_res_level) const
+{
+   if (reduced_res_level == 0)
+   {
+      return  theNumberOfColumns;
+   }
+   else if (theOverview)
+   {
+      return theOverview->getNumberOfSamples(reduced_res_level);
+   }
+   return 0;
+}
+
+bool ossimNitroHandler::saveState(ossimKeywordlist& kwl,
+                                  const char* prefix)const
+{
+}
+
+bool ossimNitroHandler::loadState(const ossimKeywordlist& kwl,
+                                  const char* prefix)
+{
+   return ossimImageHandler::loadState(kwl, prefix);
+}
+
+ossimIrect ossimNitroHandler::getImageRectangle(ossim_uint32 resLevel) const
+{
+   ossimIrect rect;
+   rect.makeNan();
+   rect = theCurrentImageRect;
+   if(!theAnnotationBounds.hasNans())
+   {
+      if(rect.hasNans())
+      {
+         if(resLevel == 0)
+         {
+            rect = theAnnotationBounds;
+         }
+         else
+         {
+            ossim_uint32 idx = resLevel-1;
+            if(idx < theRlevelAnnotationBounds.size())
+            {
+               rect = theRlevelAnnotationBounds[idx];
+            }
+         }
+      }
+      else
+      {
+         if(resLevel == 0)
+         {
+            rect = rect.combine(theAnnotationBounds);
+         }
+         else
+         {
+            ossim_uint32 idx = resLevel-1;
+            if(idx < theRlevelAnnotationBounds.size())
+            {
+               rect = rect.combine(theRlevelAnnotationBounds[idx]);
+            }
+         }
+      }
+   }
+   return rect;
+}
+
+
+bool ossimNitroHandler::getImageGeometry(ossimKeywordlist& kwl,
+                                         const char* prefix)
+{
+   return ossimImageHandler::getImageGeometry(kwl, prefix);
+}
+
+ossimScalarType ossimNitroHandler::getOutputScalarType() const
+{
+   return theScalarType;
+}
+
+ossim_uint32 ossimNitroHandler::getImageTileWidth() const
+{
+   return theNumberOfPixelsPerHorizBlock;
+}
+
+ossim_uint32 ossimNitroHandler::getImageTileHeight() const
+{
+   return theNumberOfPixelsPerVertBlock;
+}
+
+ossim_uint32 ossimNitroHandler::getCurrentEntry()const
+{
+   return theCurrentImageEntry;
+}
+
+bool ossimNitroHandler::setCurrentEntry(ossim_uint32 entryIdx)
+{
+   bool result = false;
+   theTile = 0;
+   if(isOpen())
+   {
+      nitf_Error e;
+      theCurrentImageRect.makeNan();
+      
+      if(entryIdx < theNumberOfImages)
+      {
+         if(theCurrentImageReader) 
+         {
+            nitf_ImageReader_destruct(&theCurrentImageReader);
+            theCurrentImageReader = 0;
+         }
+         if(theReadBuffer)
+         {
+            ossim_uint32 i=0;
+            for (i = 0; i < theNumberOfInputBands; i++)
+               NITF_FREE(theReadBuffer[i]);
+            NITF_FREE(theReadBuffer);
+         }
+         theReadBuffer = 0;
+         theCurrentImageReader = nitf_Reader_newImageReader(theReader, entryIdx, &e);
+         theCurrentImageIterator = nitf_List_at(theRecord->images, entryIdx);
+         result = (theCurrentImageReader != 0);
+         theCurrentImageEntry = entryIdx;
+         theCurrentImageSegment = (nitf_ImageSegment *) nitf_ListIterator_get(&theCurrentImageIterator);
+         size_t subimageSize;
+         nitf_Uint32 xBands;
+         nitf_Error e;
+         nitf_Field_get(theCurrentImageSegment->subheader->numBitsPerPixel, &theNumberOfBits,
+                        NITF_CONV_UINT, NITF_INT32_SZ, &e);
+         nitf_Field_get(theCurrentImageSegment->subheader->numImageBands, &theNumberOfInputBands,
+                        NITF_CONV_UINT, NITF_INT32_SZ, &e);
+         nitf_Field_get(theCurrentImageSegment->subheader->numMultispectralImageBands,
+                        &xBands,
+                        NITF_CONV_UINT, NITF_INT32_SZ, &e);
+         theNumberOfInputBands += xBands;
+         nitf_Field_get(theCurrentImageSegment->subheader->numRows, &theNumberOfRows, 
+                        NITF_CONV_UINT, NITF_INT32_SZ, &e);
+         nitf_Field_get(theCurrentImageSegment->subheader->numCols, &theNumberOfColumns, 
+                        NITF_CONV_UINT, NITF_INT32_SZ, &e);
+         nitf_Field_get(theCurrentImageSegment->subheader->numBlocksPerRow, &theNumberOfBlocksPerRow, 
+                        NITF_CONV_UINT, NITF_INT32_SZ, &e);
+         nitf_Field_get(theCurrentImageSegment->subheader->numBlocksPerCol, &theNumberOfBlocksPerColumn, 
+                        NITF_CONV_UINT, NITF_INT32_SZ, &e);
+         nitf_Field_get(theCurrentImageSegment->subheader->numPixelsPerHorizBlock, &theNumberOfPixelsPerHorizBlock, 
+                        NITF_CONV_UINT, NITF_INT32_SZ, &e);
+         nitf_Field_get(theCurrentImageSegment->subheader->numPixelsPerVertBlock, &theNumberOfPixelsPerVertBlock, 
+                        NITF_CONV_UINT, NITF_INT32_SZ, &e);
+         theImageRepresentation = ossimString(theCurrentImageSegment->subheader->imageRepresentation->raw,
+                                              theCurrentImageSegment->subheader->imageRepresentation->raw + theCurrentImageSegment->subheader->imageRepresentation->length);
+         theCurrentImageRect = ossimIrect(0,0,theNumberOfRows-1, theNumberOfColumns-1);
+         theImageRepresentation = theImageRepresentation.upcase();
+         theSubImageSize = 0;
+         setCompressionFlags();
+         populateLut();
+         theNumberOfOutputBands = theNumberOfInputBands;
+         if(theIsVqCompressedFlag&&(theNumberOfInputBands==1))
+         {
+            theNumberOfOutputBands = 3;
+         }
+         else if(theLut.valid())
+         {
+            theNumberOfOutputBands = theLut->getNumberOfBands();
+         }
+         theBandList.resize(theNumberOfInputBands);
+         int idx = 0;
+         theReadBuffer = 0;
+         theSubImage->bandList=&theBandList.front();
+         theSubImage->numBands=theBandList.size();
+         initializeScalarType();
+      }
+   }
+   if(!result)
+   {
+      if((theAnnotations.size()>0)&&
+         (entryIdx == 0))
+      {
+         result = true;
+         theNumberOfOutputBands = 3;
+         theNumberOfInputBands = 1;
+         theScalarType=OSSIM_UINT8;
+      }
+   }
+   
+   return result;
+}
+
+void ossimNitroHandler::getEntryList(std::vector<ossim_uint32>& entryList)const
+{
+   ossim_uint32 idx = 0;
+   for(idx = 0; idx < theNumberOfImages; ++idx)
+   {
+      entryList.push_back(idx);
+   }
+   if(theNumberOfImages == 0)
+   {
+      if(theAnnotations.size())
+      {
+         entryList.push_back(0);
+      }
+   }
+}
+
+void ossimNitroHandler::getEntryNames(std::vector<ossimString>& entryStringList) const
+{
+   ossim_uint32 idx = 0;
+   for(idx = 0; idx < theNumberOfImages; ++idx)
+   {
+      entryStringList.push_back(ossimString::toString(idx));
+   }
+   if(theNumberOfImages == 0)
+   {
+      if(theAnnotations.size())
+      {
+         entryStringList.push_back("0");
+      }
+   }
+}
+
+bool ossimNitroHandler::isOpen()const
+{
+   return (theRecord!=0);
+}
+
+double ossimNitroHandler::getNullPixelValue(ossim_uint32 band)const
+{
+   double result = ossimImageHandler::getNullPixelValue(band);
+   
+   //   if(thePackedBitsFlag)
+   //   {
+   //      if((result < 0) ||
+   //         (result > getMaxPixelValue(band)))
+   //      {
+   //         result = 0.0;
+   //      }
+   //   }
+   
+   
+   return result;
+}
+
+double ossimNitroHandler::getMinPixelValue(ossim_uint32 band)const
+{
+   double result = ossimImageHandler::getMinPixelValue(band);
+   
+   //   if(thePackedBitsFlag)
+   //   {
+   //      if(result < 1.0) result = 1.0;
+   //   }
+   
+   return result;
+}
+
+double ossimNitroHandler::getMaxPixelValue(ossim_uint32 band)const
+{
+   double result = ossimImageHandler::getMaxPixelValue(band);
+   
+#if 0
+   if(thePackedBitsFlag)
+   {
+      double test = 1<<(hdr->getBitsPerPixelPerBand());
+      
+      if(result > test) result = test;
+   }
+   else
+#endif
+      switch (theNumberOfBits)
+   {
+      case 11:
+      {
+         if (result > 2047.0)
+         {
+            result = 2047.0;
+         }
+         break;
+      }
+      case 12:
+      {
+         if (result > 4095.0)
+         {
+            result = 4095.0;
+         }
+         break;
+      }
+      default:
+      {
+         if(theNumberOfBits < 16)
+         {
+            result = (2>>theNumberOfBits) - 1;
+         }
+      }
+         break;
+   }
+   
+   return result;
+}
+
+void ossimNitroHandler::setProperty(ossimRefPtr<ossimProperty> property)
+{
+   ossimString name = property->getName();
+   if(name == "enable_annotations_flag")
+   {
+      theEnableAnnotationsFlag = property->valueToString().toBool();
+   }
+   else
+   {
+      ossimImageHandler::setProperty(property);
+   }
+}
+
+ossimRefPtr<ossimProperty> ossimNitroHandler::getProperty(const ossimString& name)const
+{
+   ossimRefPtr<ossimProperty> result;
+   if(name == "enable_annotations_flag")
+   {
+      ossimBooleanProperty* prop = new ossimBooleanProperty(name,
+                                                            theEnableAnnotationsFlag);
+      prop->setFullRefreshBit();
+      
+      result = prop;
+   }
+   else
+   {
+      result = ossimImageHandler::getProperty(name);
+   }
+   
+   return result.get();
+}
+
+void ossimNitroHandler::getPropertyNames(std::vector<ossimString>& propertyNames)const
+{
+   ossimImageHandler::getPropertyNames(propertyNames);
+   propertyNames.push_back("enable_annotations_flag");
+}
+
+void ossimNitroHandler::initializeScalarType()
+{
+   theScalarType = OSSIM_SCALAR_UNKNOWN;
+   if(theCurrentImageSegment)
+   {
+      nitf_Error e;
+      nitf_Uint32 bitsPerPixel=0;
+      nitf_Field_get(theCurrentImageSegment->subheader->actualBitsPerPixel, &bitsPerPixel, 
+                     NITF_CONV_UINT, NITF_INT32_SZ, &e);
+      if (bitsPerPixel < 1)
+      {
+         nitf_Field_get(theCurrentImageSegment->subheader->numBitsPerPixel, &bitsPerPixel, 
+                        NITF_CONV_UINT, NITF_INT32_SZ, &e);
+      }
+      if(bitsPerPixel <=0) return;
+      
+      ossimString pixelValueType(theCurrentImageSegment->subheader->pixelValueType->raw, theCurrentImageSegment->subheader->pixelValueType->raw + theCurrentImageSegment->subheader->pixelValueType->length);
+      pixelValueType = pixelValueType.upcase();
+      
+      switch (bitsPerPixel)
+      {
+         case 8:
+         {
+            theScalarType = OSSIM_UINT8;
+            break;
+         }
+         case 11:
+         {
+            theScalarType = OSSIM_USHORT11;
+            break;
+         }
+         case 12:
+         {
+            theScalarType = OSSIM_UINT16;
+            break;
+         }
+         case 16:
+         {
+            if(pixelValueType == "SI")
+            {
+               theScalarType = OSSIM_SINT16;
+            }
+            else
+            {
+               theScalarType = OSSIM_UINT16;
+            }
+            break;
+         }
+         case 32:
+         {
+            if(pixelValueType == "R")
+            {
+               theScalarType = OSSIM_FLOAT32;
+            }
+            
+            break;
+         }
+         case 64:
+         {
+            if(pixelValueType == "R")
+            {
+               theScalarType = OSSIM_FLOAT64;
+            }
+            
+            break;
+         }
+         default:
+         {
+            if(bitsPerPixel <=8)
+            {
+               theScalarType = OSSIM_UINT8;
+            }
+            else if(bitsPerPixel <=16)
+            {
+               if(pixelValueType == "SI")
+               {
+                  theScalarType = OSSIM_SINT16;
+               }
+               else
+               {
+                  theScalarType = OSSIM_UINT16;
+               }
+            }
+            break;
+         }
+      }
+   }
+   
+   if(theScalarType == OSSIM_SCALAR_UNKNOWN)
+   {
+      if(theAnnotations.size() > 0)
+      {
+         theScalarType = OSSIM_UINT8;
+      }
+   }
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+      << "ossimNitroHandler::initializeScalarType DEBUG:"
+      << "\nScalar type:  "
+      << (ossimScalarTypeLut::instance()->getEntryString(theScalarType))
+      << endl;
+   }
+}
+
+void ossimNitroHandler::initializeOutputTile()
+{
+   ossimImageDataFactory* idf = ossimImageDataFactory::instance();
+   theTile = idf->create(this, this);
+   theTile->initialize();
+   theUncompressedClipTile = (ossimImageData*)theTile->dup();
+   theUncompressedClipTile->initialize();
+   theRgbAnnotationImageData = 0;
+   
+   theRgbAnnotationImageData = new ossimImageData(0,
+                                                  OSSIM_UINT8,
+                                                  3,
+                                                  64,
+                                                  64);
+   theRgbAnnotationImageData->initialize();
+}
+
+bool ossimNitroHandler::setCompressionFlags()
+{
+   ossimString compressionCode(theCurrentImageSegment->subheader->imageCompression->raw, 
+                               theCurrentImageSegment->subheader->imageCompression->raw+theCurrentImageSegment->subheader->imageCompression->length);
+   compressionCode = compressionCode.upcase();
+   theIsVqCompressedFlag = ((compressionCode == "C4")||
+                            (compressionCode == "M4"));
+}
+
+void ossimNitroHandler::populateLut()
+{
+   theLut = 0 ;
+   if(theCurrentImageSegment&&theCurrentImageSegment->subheader->bandInfo[0])
+   {
+      nitf_Error e;
+      int numLuts, numEntries;
+      int outputBands = 0;
+      nitf_Field_get(theCurrentImageSegment->subheader->bandInfo[0]->numLUTs, &numLuts,
+                     NITF_CONV_UINT, NITF_INT32_SZ, &e);
+      if(numLuts > 0)
+      {
+         nitf_Field_get(theCurrentImageSegment->subheader->bandInfo[0]->bandEntriesPerLUT, &numEntries,
+                        NITF_CONV_UINT, NITF_INT32_SZ, &e);
+         
+         outputBands = theCurrentImageSegment->subheader->bandInfo[0]->lut->tables;
+         if(numLuts = 1)
+         {
+            theLut = new ossimNBandLutDataObject(numEntries, outputBands);
+            ossim_uint32 idx = 0;
+            ossim_uint32 bandIdx = 0;
+            ossim_uint32 offset = 0;
+            for(idx = 0; idx < numEntries; ++idx)
+            {
+               for(bandIdx = 0; bandIdx < outputBands; ++bandIdx)
+               {
+                  (*theLut)[idx][bandIdx] = theCurrentImageSegment->subheader->bandInfo[0]->lut->table[offset+bandIdx];
+                  //               (*theLut)[idx][1] = theCurrentImageSegment->subheader->bandInfo[0]->lut->table[offset+1];
+                  //               (*theLut)[idx][2] = theCurrentImageSegment->subheader->bandInfo[0]->lut->table[offset+2];
+                  
+                  //               offset+=3;
+               }
+               offset+=outputBands;
+            }
+         }
+      }
+   }
+}
+
+void ossimNitroHandler::lutUncompress(ossimRefPtr<ossimImageData> destination, nitf_Uint8* source)
+{
+   if(!theLut.valid()) return;
+   if((!destination->getBuf())||
+      (destination->getScalarType()!=OSSIM_UINT8))
+   {
+      return;
+   }
+   
+   if(destination->getNumberOfBands()!=theLut->getNumberOfBands())
+   {
+      return;
+   }
+   std::vector<ossim_uint8*> bandList(destination->getNumberOfBands());
+   ossim_uint8** tempRows = &bandList.front();
+   ossim_uint32 idx = 0;
+   ossim_uint32 bands = bandList.size();
+   for(idx = 0; idx <bands; ++idx)
+   {
+      tempRows[idx] = (ossim_uint8*)(destination->getBuf(idx));
+   }   
+   ossim_uint8* srcPtr = source;
+   ossim_uint32 compressionYidx   = 0;
+   ossim_uint32 compressionXidx   = 0;
+   ossim_uint32 uncompressIdx     = 0;
+   ossim_uint32 h = destination->getHeight();
+   ossim_uint32 w = destination->getWidth();
+   
+   for(compressionYidx = 0; compressionYidx < h; ++compressionYidx)
+   {
+      for(compressionXidx = 0; compressionXidx < w; ++compressionXidx)
+      {
+         for(idx = 0; idx < bands;++idx)
+         {
+            tempRows[idx][uncompressIdx] = (*theLut)[*srcPtr][idx];
+         }
+         ++srcPtr;
+         ++uncompressIdx;
+      }
+   }
+}
+
+void printCGM(cgm_Metafile *mf, nitf_Error *error)
+{
+   nitf_ListIterator iter;
+   nitf_ListIterator end;
+   int i;
+   
+   printf("metafile:\n");
+   printf("    name        : %s\n", mf->name);
+   printf("    version     : %d\n", mf->version);
+   printf("    description : %s\n", mf->description);
+   printf("    fonts       : { ");
+   
+   iter = nitf_List_begin(mf->fontList);
+   end = nitf_List_end(mf->fontList);
+   while(nitf_ListIterator_notEqualTo(&iter, &end))
+   {
+      printf("%s, ", (char*)nitf_ListIterator_get(&iter));
+      nitf_ListIterator_increment(&iter);
+   }
+   printf("}\n");
+   
+   printf("    picture     : \n");
+   printf("        name               : %s\n", mf->picture->name);
+   printf("        colorSelectionMode : %d\n", mf->picture->colorSelectionMode);
+   printf("        edgeWidthSpec      : %d\n", mf->picture->edgeWidthSpec);
+   printf("        lineWidthSpec      : %d\n", mf->picture->lineWidthSpec);
+   printf("        vdcExtent          : \n");
+   printf("            x1 : %d\n", mf->picture->vdcExtent->x1);
+   printf("            y1 : %d\n", mf->picture->vdcExtent->y1);
+   printf("            x2 : %d\n", mf->picture->vdcExtent->x2);
+   printf("            y2 : %d\n", mf->picture->vdcExtent->y2);
+   printf("        body               :\n");
+   printf("            transparency : %d\n", mf->picture->body->transparency);
+   
+   iter = nitf_List_begin(mf->picture->body->elements);
+   end = nitf_List_end(mf->picture->body->elements);
+   while(nitf_ListIterator_notEqualTo(&iter, &end))
+   {
+      cgm_Element_print((cgm_Element*)nitf_ListIterator_get(&iter));
+      nitf_ListIterator_increment(&iter);
+   }
+}
+
+void ossimNitroHandler::addElement(cgm_Element* element)
+{   
+   //   cgm_Element_print(element);
+   nitf_ListIterator iter;
+   nitf_ListIterator end;
+   ossimDrect rect;
+   switch(element->type)
+   {
+      case CGM_TEXT_ELEMENT:
+      {
+         ossimDpt scale(1.0,1.0); 
+         ossimDpt shear(0.0,0.0); 
+         ossimIpt size(18, 18);
+         ossim_uint8 r,g,b;
+         double rotation = 0.0;
+         ossimRefPtr<ossimAnnotationFontObject> fontObject;
+         cgm_TextElement* el = (cgm_TextElement*)element->data;
+         if(el->attributes)
+         {
+            if(el->attributes->textColor)
+            {
+               r = el->attributes->textColor->r;
+               g = el->attributes->textColor->g;
+               b = el->attributes->textColor->b;
+            }
+            if(el->attributes->characterHeight > 0)
+            {
+               size.x = el->attributes->characterHeight;
+               size.y = size.x;
+            }
+         }
+         
+         fontObject = new ossimAnnotationFontObject(ossimIpt(el->text->x, el->text->y),
+                                                    ossimString(el->text->str),
+                                                    size,
+                                                    rotation,
+                                                    scale,
+                                                    shear,
+                                                    r,g,b);
+         fontObject->getBoundingRect(rect);
+         theAnnotations.push_back(fontObject.get());
+         if(!rect.hasNans())
+         {
+            addAnnotationBounds(rect);
+         }
+         break;
+      }
+      case CGM_POLYGON_ELEMENT:
+      {
+         ossimRefPtr<ossimAnnotationPolyObject> polyObject = new ossimAnnotationPolyObject;
+         cgm_PolygonElement* el = (cgm_PolygonElement*)element->data;
+         if(el->attributes)
+         {
+            if(el->attributes->edgeColor)
+            {
+               polyObject->setColor(el->attributes->edgeColor->r,
+                                    el->attributes->edgeColor->g,
+                                    el->attributes->edgeColor->b);
+            }
+            if(el->attributes->edgeWidth>0)
+            {
+               polyObject->setThickness(el->attributes->edgeWidth);
+            }
+         }
+         iter = nitf_List_begin(el->vertices);
+         end = nitf_List_end(el->vertices);
+         while(nitf_ListIterator_notEqualTo(&iter, &end))
+         {
+            cgm_Vertex* vert = (cgm_Vertex*)nitf_ListIterator_get(&iter);
+            polyObject->addPoint(ossimDpt(vert->x, vert->y));
+            nitf_ListIterator_increment(&iter);
+         }
+         polyObject->computeBoundingRect();
+         theAnnotations.push_back(polyObject.get());
+         polyObject->getBoundingRect(rect);
+         if(!rect.hasNans())
+         {
+            addAnnotationBounds(rect);
+         }
+         break;
+      }
+      case CGM_POLYLINE_ELEMENT:
+      {
+         ossimPolyLine polyLine;
+         ossimRefPtr<ossimAnnotationMultiPolyLineObject> polyLineObject = new ossimAnnotationMultiPolyLineObject();
+         cgm_PolyLineElement* el = (cgm_PolyLineElement*)element->data;
+         if(el->attributes)
+         {
+            if(el->attributes->lineColor)
+            {
+               polyLineObject->setColor(el->attributes->lineColor->r,
+                                        el->attributes->lineColor->g,
+                                        el->attributes->lineColor->b);
+            }
+            if(el->attributes->lineWidth > 0)
+            {
+               polyLineObject->setThickness(el->attributes->lineWidth);
+            }
+         }
+         iter = nitf_List_begin(el->vertices);
+         end = nitf_List_end(el->vertices);
+         while(nitf_ListIterator_notEqualTo(&iter, &end))
+         {
+            cgm_Vertex* vert = (cgm_Vertex*)nitf_ListIterator_get(&iter);
+            polyLine.addPoint(ossimDpt(vert->x, vert->y));
+            nitf_ListIterator_increment(&iter);
+         }
+         polyLineObject->addPolyLine(polyLine);
+         polyLineObject->computeBoundingRect();
+         theAnnotations.push_back(polyLineObject.get());
+         polyLineObject->getBoundingRect(rect);
+         if(!rect.hasNans())
+         {
+            addAnnotationBounds(rect);
+         }
+         break;
+      }
+      case CGM_POLYSET_ELEMENT:
+      {
+         break;
+      }
+      case CGM_ELLIPSE_ELEMENT:
+      {
+         // we still need to fix for rotation.  For now no rotation will be added
+         //
+         cgm_EllipseElement* el = (cgm_EllipseElement*)element->data;
+         double azimuthInDegrees = 0.0;
+         int lineWidth = 1;
+         ossimDpt center(el->centerX, el->centerY);
+         ossimDpt pt1(el->end1X, el->end1Y);
+         ossimDpt pt2(el->end2X, el->end2Y);
+         ossimDpt widthHeight((pt2-center).length(),
+                              (pt1-center).length());
+         ossim_uint8 lineColorR=255, lineColorG=255, lineColorB=255;
+         if(el->attributes)
+         {
+            lineWidth = el->attributes->edgeWidth;
+            if(lineWidth < 0 ) lineWidth = 1;
+            if(el->attributes->edgeColor)
+            {
+               lineColorR = el->attributes->edgeColor->r;
+               lineColorG = el->attributes->edgeColor->g;
+               lineColorB = el->attributes->edgeColor->b;
+            }
+         }
+         ossimRefPtr<ossimAnnotationEllipseObject> ellipseObject = new ossimAnnotationEllipseObject(center, widthHeight);
+         ellipseObject->setColor(lineColorR, lineColorG, lineColorB);
+         ellipseObject->computeBoundingRect();
+         //ellipseObject->setThickness(lineWidth);
+         theAnnotations.push_back(ellipseObject.get());
+         ellipseObject->getBoundingRect(rect);
+         if(!rect.hasNans())
+         {
+            addAnnotationBounds(rect);
+         }
+         break;
+      }
+      case CGM_ELLIPTICAL_ARC_CENTER_ELEMENT:
+      {
+         break;
+      }
+      case CGM_ELLIPTICAL_ARC_CENTER_CLOSE_ELEMENT:
+      {
+         break;
+      }
+      case CGM_RECTANGLE_ELEMENT:
+      {
+         ossimRefPtr<ossimAnnotationPolyObject> polyObject = new ossimAnnotationPolyObject;
+         int lineWidth = 1;
+         polyObject->setThickness(lineWidth);
+         cgm_RectangleElement* el = (cgm_RectangleElement*)element->data;
+         if(el->attributes)
+         {
+            lineWidth = el->attributes->edgeWidth;
+            if(lineWidth < 0 ) lineWidth = 1;
+            if(el->attributes->edgeColor)
+            {
+               polyObject->setColor(el->attributes->edgeColor->r,
+                                    el->attributes->edgeColor->g,
+                                    el->attributes->edgeColor->b);
+            }
+         }
+         ossimIrect tempRectangle(ossimIpt(el->rectangle->x1, el->rectangle->y1),
+                                  ossimIpt(el->rectangle->x2, el->rectangle->y2));
+         polyObject->addPoint(ossimDpt(tempRectangle.ul()));
+         polyObject->addPoint(ossimDpt(tempRectangle.ur()));
+         polyObject->addPoint(ossimDpt(tempRectangle.lr()));
+         polyObject->addPoint(ossimDpt(tempRectangle.ll()));
+         
+         polyObject->computeBoundingRect();
+         theAnnotations.push_back(polyObject.get());
+         polyObject->getBoundingRect(rect);
+         if(!rect.hasNans())
+         {
+            addAnnotationBounds(rect);
+         }
+         break;
+      }
+      case CGM_CIRCLE_ELEMENT:
+      {
+         cgm_CircleElement* el = (cgm_CircleElement*)element->data;
+         ossimDpt center(el->centerX, el->centerY);
+         ossimDpt widthHeight(el->radius, el->radius);
+         ossimRefPtr<ossimAnnotationEllipseObject> ellipseObject = new ossimAnnotationEllipseObject(center, widthHeight);
+         
+         if(el->attributes)
+         {
+            if(el->attributes->edgeColor)
+            {
+               ellipseObject->setColor(el->attributes->edgeColor->r,
+                                       el->attributes->edgeColor->g,
+                                       el->attributes->edgeColor->b);
+            }
+         }
+         ellipseObject->computeBoundingRect();
+         theAnnotations.push_back(ellipseObject.get());
+         ellipseObject->getBoundingRect(rect);
+         if(!rect.hasNans())
+         {
+            addAnnotationBounds(rect);
+         }
+         
+         break;
+      }
+      case CGM_CIRCULAR_ARC_CENTER_ELEMENT:
+      {
+         break;
+      }
+      case CGM_CIRCULAR_ARC_CENTER_CLOSE_ELEMENT:
+      {
+         break;
+      }
+   }
+}
+
+void ossimNitroHandler::loadAnnotations()
+{
+   nitf_ListIterator iter;
+   nitf_ListIterator end;
+   ossim_uint32 num = 0;
+   nitf_Error e;
+   
+   if (theRecord->graphics)
+   {
+      iter = nitf_List_begin(theRecord->graphics);
+      end = nitf_List_end(theRecord->graphics);
+      
+      num = 0;
+      while(nitf_ListIterator_notEqualTo(&iter, &end))
+      {
+         nitf_SegmentReader *segmentReader = NULL;
+         nitf_GraphicSegment *segment =
+         (nitf_GraphicSegment *) nitf_ListIterator_get(&iter);
+         
+         segmentReader = nitf_Reader_newGraphicReader(theReader, num, &e);
+         
+         // size_t bytes;
+         // bytes = (size_t)(segment->end - segment->offset);
+         cgm_MetafileReader* metafileReader = cgm_MetafileReader_construct(&e);
+         /** put yourself at the beginning of the data segment **/
+         nitf_IOHandle_seek(segmentReader->inputHandle, segmentReader->baseOffset, NITF_SEEK_SET, &e);
+         cgm_Metafile* metaFile = cgm_MetafileReader_read(metafileReader,
+                                                          segmentReader->inputHandle, 
+                                                          &e);
+         cgm_Picture* picture = 0;
+         if(metaFile)
+         {
+            nitf_ListIterator elementIter;
+            nitf_ListIterator elementIterEnd;
+            elementIter = nitf_List_begin(metaFile->picture->body->elements);
+            elementIterEnd = nitf_List_end(metaFile->picture->body->elements);
+            while(nitf_ListIterator_notEqualTo(&elementIter, &elementIterEnd))
+            {
+               //cgm_Element_print((cgm_Element*)nitf_ListIterator_get(&iter));
+               addElement((cgm_Element*)nitf_ListIterator_get(&elementIter));
+               nitf_ListIterator_increment(&elementIter);
+            }
+            //            printCGM(metaFile, &e);
+            cgm_Metafile_destruct(&metaFile);
+         }
+         cgm_MetafileReader_destruct(&metafileReader);
+         nitf_SegmentReader_destruct(&segmentReader);
+         nitf_ListIterator_increment(&iter);
+         ++num;
+      }
+   }
+   if(theRecord->labels)
+   {
+      ossimDpt scale(1.0,1.0); 
+      ossimDpt shear(0.0,0.0); 
+      double rotation = 0.0;
+      int x,y;
+      int cellHeight, cellWidth;
+      ossim_uint8 r,g,b;
+      iter = nitf_List_begin(theRecord->labels);
+      end = nitf_List_end(theRecord->labels);
+      
+      num = 0;
+      while(nitf_ListIterator_notEqualTo(&iter, &end))
+      {
+         ossimDrect rect;
+         nitf_LabelSegment *segment =
+         (nitf_LabelSegment *) nitf_ListIterator_get(&iter);
+         
+         r = (ossim_uint8)segment->subheader->textColor->raw[0];
+         g = (ossim_uint8)segment->subheader->textColor->raw[1];
+         b = (ossim_uint8)segment->subheader->textColor->raw[2];
+         nitf_Field_get(segment->subheader->locationColumn, &x, 
+                        NITF_CONV_INT, NITF_INT32_SZ, &e);
+         nitf_Field_get(segment->subheader->locationRow, &y, 
+                        NITF_CONV_INT, NITF_INT32_SZ, &e);
+         nitf_Field_get(segment->subheader->cellHeight, &cellHeight, 
+                        NITF_CONV_INT, NITF_INT32_SZ, &e);
+         if(cellHeight <=0)
+         {
+            cellHeight = 18;
+         }
+         ossimRefPtr<ossimAnnotationFontObject> fontObject = new ossimAnnotationFontObject(ossimIpt(x, y),
+                                                                                           segment->label,
+                                                                                           ossimIpt(cellHeight, cellHeight),
+                                                                                           rotation,
+                                                                                           scale,
+                                                                                           shear,
+                                                                                           r,g,b);
+         fontObject->getBoundingRect(rect);
+         theAnnotations.push_back(fontObject.get());
+         if(!rect.hasNans())
+         {
+            addAnnotationBounds(rect);
+         }
+         nitf_ListIterator_increment(&iter);
+      }
+   }
+}
+
+void ossimNitroHandler::addAnnotationBounds(const ossimDrect& rect)
+{
+   if(rect.hasNans()) return;
+   if(theAnnotationBounds.hasNans())
+   {
+      theAnnotationBounds = rect;
+   }
+   else
+   {
+      theAnnotationBounds = theAnnotationBounds.combine(ossimIrect(rect));
+   }
+}
+
+ossim_uint32 ossimNitroHandler::getNumberOfDecimationLevels()const
+{
+   if(theNumberOfImages > 0)
+   {
+      return ossimImageHandler::getNumberOfDecimationLevels();
+   }
+   
+   if(theMaxAnnotationRlevel > 0)
+   {
+      return theMaxAnnotationRlevel;
+   }
+   
+   return 0;
+}
+
+std::vector<ossimRefPtr<ossimAnnotationObject> >* ossimNitroHandler::getAnnotationListForRlevel(ossim_uint32 rlevel)
+{
+   if(rlevel == 0)
+   {
+      
+      return &theAnnotations;
+   }
+   else
+   {
+      ossim_uint32 annotationIndex = rlevel-1;
+      
+      if(rlevel <= theMaxAnnotationRlevel)
+      {
+         if(annotationIndex < theRlevelAnnotations.size())
+         {
+            return &(theRlevelAnnotations[annotationIndex]);
+         }
+         else // scale the annotations to reach the desired rlevel
+         {
+            ossimIrect rlevelBounds;
+            ossim_uint32 idx = 0;
+            ossim_uint32 currentRlevel = theRlevelAnnotations.size();
+            for(;currentRlevel<rlevel;++currentRlevel)
+            {
+               rlevelBounds.makeNan();
+               theRlevelAnnotations.push_back(std::vector<ossimRefPtr<ossimAnnotationObject> >());
+               std::vector<ossimRefPtr<ossimAnnotationObject> >& destinationList = theRlevelAnnotations[theRlevelAnnotations.size() - 1];
+               {
+                  double scale = 1.0/(double)(1<<(currentRlevel+1));
+                  ossim_uint32 annotationToScaleIndex = 0;
+                  for(annotationToScaleIndex=0; annotationToScaleIndex<theAnnotations.size();++annotationToScaleIndex)
+                  {
+                     ossimRefPtr<ossimAnnotationObject> obj =  (ossimAnnotationObject*)theAnnotations[annotationToScaleIndex]->dup();
+                     obj->applyScale(ossimDpt(scale,scale));
+                     if(rlevelBounds.hasNans())
+                     {
+                        rlevelBounds = obj->getBoundingRect();
+                     }
+                     else
+                     {
+                        rlevelBounds = rlevelBounds.combine(obj->getBoundingRect());
+                     }
+                     
+                     destinationList.push_back(obj.get());
+                  }
+               }
+               theRlevelAnnotationBounds.push_back(rlevelBounds);
+            }
+            return &(theRlevelAnnotations[rlevel-1]);
+         }
+      }
+   }
+   
+   return (std::vector<ossimRefPtr<ossimAnnotationObject> >*)0;
+}
+
diff --git a/ossim_plugins/nitro/ossimNitroHandler.h b/ossim_plugins/nitro/ossimNitroHandler.h
new file mode 100644
index 0000000..889559d
--- /dev/null
+++ b/ossim_plugins/nitro/ossimNitroHandler.h
@@ -0,0 +1,224 @@
+//*******************************************************************
+// Copyright (C) 2008 Garrett Potts.
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author:  Garrett Potts
+//
+// Description:
+//
+// Contains class definition for the class "ossimNitroHandler for NITF handling".
+//
+//*******************************************************************
+//  $Id$
+
+#ifndef ossimNitroHandler_HEADER
+#define ossimNitroHandler_HEADER
+
+#include <ossim/imaging/ossimImageHandler.h>
+#include <ossim/imaging/ossimAnnotationObject.h>
+#include <ossim/imaging/ossimRgbImage.h>
+#include <ossim/base/ossimIrect.h>
+
+#include <import/nitf.h>
+#include <import/cgm.h>
+
+class ossimImageData;
+
+class ossimNitroHandler : public ossimImageHandler
+{
+public:
+   ossimNitroHandler();
+   virtual ~ossimNitroHandler();
+
+
+   virtual void close();
+
+   /**
+    *  @return Returns true on success, false on error.
+    *
+    *  @note This method relies on the data member ossimImageData::theImageFile
+    *  being set.  Callers should do a "setFilename" prior to calling this
+    *  method or use the ossimImageHandler::open that takes a file name and an
+    *  entry index.
+    */   
+   virtual bool open();
+
+   /**
+    *  Returns a pointer to a tile given an origin representing the upper
+    *  left corner of the tile to grab from the image.
+    *  Satisfies pure virtual from TileSource class.
+    */
+   virtual ossimRefPtr<ossimImageData> getTile(const ossimIrect& tileRect,
+                                   ossim_uint32 resLevel=0);
+
+   /**
+    *  Returns the number of bands in the image.
+    *  Satisfies pure virtual from ImageHandler class.
+    */
+   virtual ossim_uint32 getNumberOfInputBands() const;
+
+    /**
+    * Returns the number of bands in a tile returned from this TileSource.
+    * Note: we are supporting sources that can have multiple data objects.
+    * If you want to know the scalar type of an object you can pass in the 
+    */
+   virtual ossim_uint32 getNumberOfOutputBands() const;
+  
+   /**
+    *  Returns the number of bands in the image.
+    *  Satisfies pure virtual from ImageHandler class.
+    */
+   virtual ossim_uint32 getNumberOfLines(ossim_uint32 reduced_res_level = 0) const;
+
+   /**
+    *  Returns the number of bands available from an image.
+    *  Satisfies pure virtual from ImageHandler class.
+    */
+   virtual ossim_uint32 getNumberOfSamples(ossim_uint32 reduced_res_level = 0) const;
+
+   /**
+    * Method to save the state of an object to a keyword list.
+    * Return true if ok or false on error.
+    */
+   virtual bool saveState(ossimKeywordlist& kwl,
+                          const char* prefix=0)const;
+
+   /**
+    * Method to the load (recreate) the state of an object from a keyword
+    * list.  Return true if ok or false on error.
+    */
+   virtual bool loadState(const ossimKeywordlist& kwl,
+                          const char* prefix=0);
+   
+   
+   virtual ossimIrect getImageRectangle(ossim_uint32 resLevel = 0) const;
+   
+   /**
+    *  Populates the keyword list with image geometry information.  This
+    *  method is used to relay projection/model information to users.
+    *  Returns true if geometry info is present, false if not.
+    */
+   virtual bool getImageGeometry(ossimKeywordlist& kwl,
+                                 const char* prefix=0);
+
+   /**
+    * Returns the output pixel type of the tile source.
+    */
+   virtual ossimScalarType getOutputScalarType() const;
+
+   /**
+    * Returns the tile width of the image or 0 if the image is not tiled.
+    * Note: this is not the same as the ossimImageSource::getTileWidth which
+    * returns the output tile width which can be different than the internal
+    * image tile width on disk.
+    */
+   virtual ossim_uint32 getImageTileWidth() const;
+   
+   /**
+    * Returns the tile width of the image or 0 if the image is not tiled.
+    * Note: this is not the same as the ossimImageSource::getTileWidth which
+    * returns the output tile width which can be different than the internal
+    * image tile width on disk.
+    */
+   virtual ossim_uint32 getImageTileHeight() const;   
+
+   /**
+    * @return The current entry number.
+    */
+   virtual ossim_uint32 getCurrentEntry()const;
+   
+   /**
+    * @param entryIdx Entry number to select.  This will set the data member
+    * "theEntryNumberToRender", then call open().
+    */
+   virtual bool setCurrentEntry(ossim_uint32 entryIdx);
+
+   /**
+    * @param entryList This is the list to initialize with entry indexes.
+    */
+   virtual void getEntryList(std::vector<ossim_uint32>& entryList)const;
+
+   /**
+    * @param entryStringList List to initialize with strings associated with
+    * entries.
+    */
+   virtual void getEntryNames(
+      std::vector<ossimString>& entryStringList) const;
+   
+   virtual bool isOpen()const;
+   
+   virtual ossim_uint32 getNumberOfDecimationLevels()const;
+   
+   virtual double getNullPixelValue(ossim_uint32 band=0)const;
+   virtual double getMinPixelValue(ossim_uint32 band=0)const;
+   virtual double getMaxPixelValue(ossim_uint32 band=0)const;
+
+   virtual void setProperty(ossimRefPtr<ossimProperty> property);
+   virtual ossimRefPtr<ossimProperty> getProperty(const ossimString& name)const;
+   virtual void getPropertyNames(std::vector<ossimString>& propertyNames)const;
+   
+private:
+   void initializeScalarType();
+   void initializeOutputTile();
+   bool setCompressionFlags();
+   void populateLut();
+   void lutUncompress(ossimRefPtr<ossimImageData> destination, nitf_Uint8* source);
+   void addElement(cgm_Element* element);
+   void loadAnnotations();
+   void addAnnotationBounds(const ossimDrect& rect);
+   void drawAnnotations(ossimRefPtr<ossimImageData>, ossim_uint32 resLevel = 0);
+   std::vector<ossimRefPtr<ossimAnnotationObject> >* getAnnotationListForRlevel(ossim_uint32 rlevel);
+   
+   ossimRefPtr<ossimImageData> theTile;
+   ossimRefPtr<ossimImageData> theUncompressedClipTile;
+  /*  This is the reader  */
+   nitf_Reader *theReader;
+   /*  This is the record of the file we are reading  */
+   nitf_Record *theRecord;
+      /*  This is the io handle we will give the reader to parse  */
+   nitf_IOHandle theIoHandle;
+   
+   ossim_uint32 theNumberOfImages;
+   nitf_ImageReader* theCurrentImageReader;
+   nitf_ListIterator theCurrentImageIterator;
+   nitf_ImageSegment* theCurrentImageSegment;
+   nitf_Uint32 theNumberOfBits;
+   nitf_Uint32 theNumberOfInputBands;
+   nitf_Uint32 theNumberOfOutputBands;
+   nitf_Uint32 theNumberOfRows; 
+   nitf_Uint32 theNumberOfColumns;
+   size_t theSubImageSize;
+   ossim_uint32 theCurrentImageEntry;
+   nitf_Uint32 theNumberOfBlocksPerRow;
+   nitf_Uint32 theNumberOfBlocksPerColumn;
+   nitf_Uint32 theNumberOfPixelsPerHorizBlock;
+   nitf_Uint32 theNumberOfPixelsPerVertBlock;
+   ossimScalarType theScalarType;
+   nitf_Uint8 **theReadBuffer;
+   std::vector<nitf_Uint32> theBandList;
+   nitf_SubWindow* theSubImage;
+   ossimString theImageRepresentation;
+   bool theIsVqCompressedFlag;
+   
+   ossimIrect theCurrentImageRect;
+   ossimIrect theAnnotationBounds;
+   /************************** Graphics and text support *********************/
+   bool                       theEnableAnnotationsFlag;
+   ossimRefPtr<ossimRgbImage> theAnnotationImage;
+   ossimRefPtr<ossimImageData> theRgbAnnotationImageData;
+   nitf_Uint32 theNumberOfGraphicSegments;
+   nitf_Uint32 theNumberOfTextSegments;
+   nitf_Uint32 theNumberOfLabelSegments;
+   ossim_uint32 theMaxAnnotationRlevel;
+   
+   std::vector<ossimRefPtr<ossimAnnotationObject> > theAnnotations;
+   std::vector<std::vector<ossimRefPtr<ossimAnnotationObject> > > theRlevelAnnotations;
+   std::vector<ossimIrect> theRlevelAnnotationBounds;
+   TYPE_DATA
+};
+
+#endif
+
diff --git a/ossim_plugins/nitro/ossimNitroImageHandlerFactory.cpp b/ossim_plugins/nitro/ossimNitroImageHandlerFactory.cpp
new file mode 100644
index 0000000..f2c118f
--- /dev/null
+++ b/ossim_plugins/nitro/ossimNitroImageHandlerFactory.cpp
@@ -0,0 +1,158 @@
+//*******************************************************************
+// Copyright (C) 2009 Garrett Potts.
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author:  Garrett Potts
+//*******************************************************************
+//  $Id$
+
+#include "ossimNitroImageHandlerFactory.h"
+#include "ossimNitroHandler.h"
+#include <ossim/base/ossimKeywordlist.h>
+#include <ossim/base/ossimString.h>
+#include <ossim/imaging/ossimImageHandler.h>
+#include <ossim/base/ossimTrace.h>
+#include <ossim/base/ossimKeywordNames.h>
+
+static const ossimTrace traceDebug("ossimNitroImageHandlerFactory:debug");
+
+RTTI_DEF1(ossimNitroImageHandlerFactory, "ossimNitroImageHandlerFactory", ossimImageHandlerFactoryBase);
+
+ossimNitroImageHandlerFactory* ossimNitroImageHandlerFactory::theInstance = 0;
+ossimNitroImageHandlerFactory::~ossimNitroImageHandlerFactory()
+{
+   theInstance = (ossimNitroImageHandlerFactory*)NULL;
+}
+
+
+ossimNitroImageHandlerFactory* ossimNitroImageHandlerFactory::instance()
+{
+   if(!theInstance)
+   {
+      theInstance = new ossimNitroImageHandlerFactory;
+   }
+
+   return theInstance;
+}
+   
+ossimImageHandler* ossimNitroImageHandlerFactory::open(const ossimFilename& fileName)const
+{
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG) << "ossimNitroImageHandlerFactory::open(filename) DEBUG: entered..." << std::endl;
+   }
+   
+   ossimImageHandler* result = NULL;
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimNitroImageHandlerFactory::open(filename) DEBUG:"
+         << "\ntrying ossimGdalTileSource"
+         << std::endl;
+   }
+   
+   // make sure you put this last
+   //
+   result = new ossimNitroHandler;
+   if(result->open(fileName))
+   {
+      return result;
+   }
+   delete result;
+   result = 0;
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimNitroImageHandlerFactory::open(filename) DEBUG: leaving..."
+         << std::endl;
+   }
+   
+   return result;
+}
+
+ossimImageHandler* ossimNitroImageHandlerFactory::open(const ossimKeywordlist& kwl,
+                                          const char* prefix)const
+{
+   ossimImageHandler* result = (ossimImageHandler*)NULL;
+   
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG) << "ossimNitroImageHandlerFactory::open(kwl, prefix) DEBUG: entered..." << std::endl;
+   }
+   
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG) << "ossimNitroImageHandlerFactory::open(kwl, prefix) DEBUG: trying ossimNitroHandler" << std::endl;
+   }
+   result = new ossimNitroHandler;
+   if(result->loadState(kwl, prefix))
+   {
+      return result;
+   }
+   delete result;
+   result = (ossimImageHandler*)NULL;
+
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG) << "ossimNitroImageHandlerFactory::open(kwl, prefix) DEBUG: leaving..." << std::endl;
+   }
+   
+   return result;
+}
+
+ossimObject* ossimNitroImageHandlerFactory::createObject(const ossimString& typeName)const
+{
+   if(STATIC_TYPE_NAME(ossimNitroHandler) == typeName)
+   {
+      return new ossimNitroHandler();
+   }
+   
+   return (ossimObject*)NULL;
+}
+
+ossimObject* ossimNitroImageHandlerFactory::createObject(const ossimKeywordlist& kwl,
+                                                    const char* prefix)const
+{
+   ossimObject* result = (ossimObject*)NULL;
+   const char* type = kwl.find(prefix, ossimKeywordNames::TYPE_KW);
+
+   if(type)
+   {
+      if (ossimString(type).trim() == STATIC_TYPE_NAME(ossimImageHandler))
+      {
+         const char* lookup = kwl.find(prefix, ossimKeywordNames::FILENAME_KW);
+         if (lookup)
+         {
+            // Call the open that takes a filename...
+            result = this->open(kwl, prefix);
+         }
+      }
+      else
+      {
+         result = createObject(ossimString(type));
+         if(result)
+         {
+            result->loadState(kwl, prefix);
+         }
+      }
+   }
+
+   return result;
+}
+ 
+void ossimNitroImageHandlerFactory::getTypeNameList(std::vector<ossimString>& typeList)const
+{
+   typeList.push_back(STATIC_TYPE_NAME(ossimNitroHandler));
+}
+
+void ossimNitroImageHandlerFactory::getSupportedExtensions(ossimImageHandlerFactoryBase::UniqueStringList& extensionList)const
+{
+   extensionList.push_back("ntf");
+   extensionList.push_back("nsf");
+   extensionList.push_back("nitf");
+}
+
diff --git a/ossim_plugins/nitro/ossimNitroImageHandlerFactory.h b/ossim_plugins/nitro/ossimNitroImageHandlerFactory.h
new file mode 100644
index 0000000..6f53f79
--- /dev/null
+++ b/ossim_plugins/nitro/ossimNitroImageHandlerFactory.h
@@ -0,0 +1,63 @@
+//*******************************************************************
+// Copyright (C) 2009 Garrett Potts.
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author:  Garrett Potts
+//*******************************************************************
+//  $Id$
+
+#ifndef ossimNitroImageHandlerFactory_HEADER
+#define ossimNitroImageHandlerFactory_HEADER
+
+#include <ossim/imaging/ossimImageHandlerFactoryBase.h>
+#include <ossim/base/ossimString.h>
+
+class ossimGdal;
+class ossimFilename;
+class ossimKeywordlist;
+
+//*******************************************************************
+// CLASS:  ossimNitroImageHandlerFactory
+//*******************************************************************
+class ossimNitroImageHandlerFactory : public ossimImageHandlerFactoryBase
+{
+public:
+   virtual ~ossimNitroImageHandlerFactory();
+   static ossimNitroImageHandlerFactory* instance();
+   
+   virtual ossimImageHandler* open(const ossimFilename& fileName)const;
+   virtual ossimImageHandler* open(const ossimKeywordlist& kwl,
+                                   const char* prefix=0)const;
+
+   
+   virtual ossimObject* createObject(const ossimString& typeName)const;
+   
+   /*!
+    * Creates and object given a keyword list.
+    */
+   virtual ossimObject* createObject(const ossimKeywordlist& kwl,
+                                     const char* prefix=0)const;
+   
+   /*!
+    * This should return the type name of all objects in all factories.
+    * This is the name used to construct the objects dynamially and this
+    * name must be unique.
+    */
+   virtual void getTypeNameList(std::vector<ossimString>& typeList)const;
+   virtual void getSupportedExtensions(ossimImageHandlerFactoryBase::UniqueStringList& extensionList)const;
+  
+protected:
+   ossimNitroImageHandlerFactory(){}
+   ossimNitroImageHandlerFactory(const ossimNitroImageHandlerFactory&){}
+   void operator = (const ossimNitroImageHandlerFactory&){}
+
+   static ossimNitroImageHandlerFactory* theInstance;
+
+TYPE_DATA
+};
+
+#endif
+
diff --git a/ossim_plugins/nitro/ossimNitroPluginInit.cpp b/ossim_plugins/nitro/ossimNitroPluginInit.cpp
new file mode 100644
index 0000000..c13cac6
--- /dev/null
+++ b/ossim_plugins/nitro/ossimNitroPluginInit.cpp
@@ -0,0 +1,102 @@
+//*******************************************************************
+// Copyright (C) 2005 David Burken, all rights reserved.
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author:  David Burken
+//*******************************************************************
+//  $Id: ossimGdalPluginInit.cpp 13341 2008-07-29 17:27:02Z dburken $
+#include <ossim/plugin/ossimSharedObjectBridge.h>
+#include <ossimPluginConstants.h>
+#include <ossim/base/ossimObjectFactoryRegistry.h>
+#include <ossim/imaging/ossimImageHandlerRegistry.h>
+#include <ossim/imaging/ossimImageWriterFactoryRegistry.h>
+#include <ossim/imaging/ossimOverviewBuilderFactoryRegistry.h>
+#include <ossim/projection/ossimProjectionFactoryRegistry.h>
+#include "ossimNitroImageHandlerFactory.h"
+
+static void setDescription(ossimString& description)
+{
+   description = "NITRO Plugin\n\n";
+}
+
+
+extern "C"
+{
+   ossimSharedObjectInfo  myInfo;
+   ossimString theDescription;
+   std::vector<ossimString> theObjList;
+   const char* getDescription()
+   {
+      return theDescription.c_str();
+   }
+   int getNumberOfClassNames()
+   {
+      return (int)theObjList.size();
+   }
+   const char* getClassName(int idx)
+   {
+      if(idx < (int)theObjList.size())
+      {
+         return theObjList[0].c_str();
+      }
+      return (const char*)0;
+   }
+
+   /* Note symbols need to be exported on windoze... */ 
+   OSSIM_PLUGINS_DLL void ossimSharedLibraryInitialize(
+      ossimSharedObjectInfo** info)
+   {    
+      myInfo.getDescription = getDescription;
+      myInfo.getNumberOfClassNames = getNumberOfClassNames;
+      myInfo.getClassName = getClassName;
+      
+      *info = &myInfo;
+
+      /* Register the readers... */
+     ossimImageHandlerRegistry::instance()->
+        registerFactory(ossimNitroImageHandlerFactory::instance(), true);
+
+#if 0
+     /* Register the writers... */
+     ossimImageWriterFactoryRegistry::instance()->
+        registerFactory(ossimGdalImageWriterFactory::instance());
+
+     /* Register the overview builder factory. */
+     ossimOverviewBuilderFactoryRegistry::instance()->
+        registerFactory(ossimGdalOverviewBuilderFactory::instance());
+
+     ossimProjectionFactoryRegistry::instance()->
+        registerFactory(ossimGdalProjectionFactory::instance());
+
+     /* Register generic objects... */
+     ossimObjectFactoryRegistry::instance()->
+        registerFactory(ossimGdalObjectFactory::instance());
+#endif
+     setDescription(theDescription);
+  }
+
+   /* Note symbols need to be exported on windoze... */ 
+  OSSIM_PLUGINS_DLL void ossimSharedLibraryFinalize()
+  {
+     ossimImageHandlerRegistry::instance()->
+        unregisterFactory(ossimNitroImageHandlerFactory::instance());
+#if 0
+
+     ossimImageWriterFactoryRegistry::instance()->
+        unregisterFactory(ossimGdalImageWriterFactory::instance());
+
+     ossimOverviewBuilderFactoryRegistry::instance()->
+        unregisterFactory(ossimGdalOverviewBuilderFactory::instance());
+
+     ossimProjectionFactoryRegistry::instance()->unregisterFactory(ossimGdalProjectionFactory::instance());
+
+     ossimObjectFactoryRegistry::instance()->
+        unregisterFactory(ossimGdalObjectFactory::instance());
+ 
+#endif
+  }
+}
+
diff --git a/ossim_plugins/nmake.opt b/ossim_plugins/nmake.opt
new file mode 100644
index 0000000..46677b9
--- /dev/null
+++ b/ossim_plugins/nmake.opt
@@ -0,0 +1,89 @@
+####
+# $Id: nmake.opt 15349 2009-09-02 16:11:06Z dburken $
+#
+# Typical build with .net compiler using nmake
+# cd to:  "ossim/src/packages"
+# unzip and untar the file gdal.tgz
+# set the environment variable OSSIM_HOME
+# cd to the top of ossim
+# nmake /f makefile.vc
+#
+# Edit this file as required.
+#
+# NOTE:  
+#
+# You should either set the environment variable "OSSIM_HOME" or uncomment and
+# set it in this file for include paths and linking.  Since external packages
+# such as ossim_qt looks for the environment variable, it is preferable to set
+# the environment variable to setting it in this file.
+#
+# See:  "Start->Control Panel->System->Advanced->Environment Variables" (XP)
+#       to set the environment variables.
+###
+
+###
+# EMBED_MANIFEST:
+# For vs7 (Visual C++ 2003) set to empty string.
+# For vs8 (Visual C++ 2005) and vs9(Visual C++ 2008) set to 1.
+###
+EMBED_MANIFEST=1
+
+###
+# 3rdparty stuff:
+###
+3RD_PARTY_HOME = E:\sw\3rdparty
+3RD_PARTY_INC = -I$(3RD_PARTY_HOME)\include
+
+FWTOOLS_HOME = "E:\sw\FWTools2.1.0"
+FWTOOLS_INC = -I$(FWTOOLS_HOME)\include
+
+OSSIM_HOME 	= E:\sw\vs9\drb\ossim
+!INCLUDE $(OSSIM_HOME)\nmake.opt
+
+CORE_DIR 	= $(OSSIM_HOME)\src\ossim_core
+BINDIR 		= $(OSSIM_HOME)\bin
+BIN_DIR 	= $(OSSIM_HOME)\bin
+
+###
+# Where the dll goes on "nmake /f makefile.vc install"
+###
+INSTALL_DIR     = E:\data\share\ossim\plugins
+
+###
+# Plugin home.
+###
+OSSIM_PLUGINS_HOME = E:\sw\vs9\drb\ossim_plugins
+OSSIM_PLUGINS_INCLUDES = -I$(OSSIM_PLUGINS_HOME)
+
+###
+# Optional png support.
+###
+PNG_DIR = E:\sw\png
+PNG_INC = -IE:\sw\png -IE:\sw\zlib
+PNG_LIB = E:\sw\png\png.lib
+ZLIB_LIB = E:\sw\zlib\zdll.lib
+
+###
+# Optional kakadu support.
+###
+KAK_INC = -ID:\vs9\kakadu\v6_2_1-00367C\managed\all_includes
+KAK_LIB = D:\vs9\kakadu\lib_x86\kdu_v62R.lib D:\vs9\kakadu\v6_generated_x86\render\release\kdu_region_decompressor.obj D:\vs9\kakadu\v6_generated_x86\server\release\jp2.obj
+
+###
+# GDAL support.
+###
+GDAL_DIR = $(FWTOOLS_HOME)
+GDAL_INC = -I$(OSSIM_PLUGINS_HOME)\gdal -I$(GDAL_DIR)\include
+GDAL_LIBS = $(GDAL_DIR)\lib\gdal_i.lib
+
+###
+# GDAL libs with odbc support
+# GDAL_LIBS = $(GDAL_DIR)\gdal.lib odbc32.lib odbccp32.lib user32.lib
+###
+
+###
+# CFLAGS We must override the core CFLAGS to use "OSSIMUSINGDLL" not
+# "OSSIMMAKINGDLL" or all the ossim symbols will be undefined!
+###
+CFLAGS = $(OPTFLAGS) /DOSSIMUSINGDLL $(INC) $(EXTRAFLAGS)
+
diff --git a/ossim_plugins/nui/ossimNuiExports.h b/ossim_plugins/nui/ossimNuiExports.h
new file mode 100644
index 0000000..0a48666
--- /dev/null
+++ b/ossim_plugins/nui/ossimNuiExports.h
@@ -0,0 +1,31 @@
+//----------------------------------------------------------------------------
+// Copyright (c) 2005, Garrett Potts, all rights reserved.
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author:  Garrett Potts
+//
+// Description: Constants file for ossim plugins.
+//
+// $Id: ossimNuiExports.h 23664 2015-12-14 14:17:27Z dburken $
+//----------------------------------------------------------------------------
+#ifndef ossimNuiExports_HEADER
+#define ossimNuiExports_HEADER
+
+#if defined(__MINGW32__) || defined(__CYGWIN__) || defined(_MSC_VER) || defined(__VISUALC__) || defined(__BORLANDC__) || defined(__WATCOMC__)
+#  define OSSIM_NUI_EXPORT __declspec(dllexport)
+#  define OSSIM_NUI_IMPORT __declspec(dllexport)
+
+#  ifdef OSSIM_NUI_MAKINGDLL
+#     define OSSIM_NUI_DLL OSSIM_NUI_EXPORT
+#  else
+#     define  OSSIM_NUI_DLL OSSIM_NUI_IMPORT
+#  endif
+#else
+# define OSSIM_NUI_DLL
+#endif
+
+#endif /* #ifndef ossimNuiExports_HEADER */
+
diff --git a/ossim_plugins/nui/ossimNuiFactory.cpp b/ossim_plugins/nui/ossimNuiFactory.cpp
new file mode 100644
index 0000000..f5efbc8
--- /dev/null
+++ b/ossim_plugins/nui/ossimNuiFactory.cpp
@@ -0,0 +1,147 @@
+//*******************************************************************
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author:  Garrett Potts
+//*******************************************************************
+//  $Id: ossimNuiFactory.cpp 23664 2015-12-14 14:17:27Z dburken $
+
+#include "ossimNuiFactory.h"
+#include "ossimNuiHandler.h"
+#include <ossim/base/ossimKeywordlist.h>
+#include <ossim/base/ossimString.h>
+#include <ossim/imaging/ossimImageHandler.h>
+#include <ossim/base/ossimTrace.h>
+#include <ossim/base/ossimKeywordNames.h>
+#include <nuiSDK.h>
+
+static const ossimTrace traceDebug("ossimNuiFactory:debug");
+
+RTTI_DEF1(ossimNuiFactory, "ossimNuiFactory", ossimImageHandlerFactoryBase);
+
+ossimNuiFactory* ossimNuiFactory::theInstance = 0;
+ossimNuiFactory::~ossimNuiFactory()
+{
+   theInstance = (ossimNuiFactory*)NULL;
+}
+
+
+ossimNuiFactory* ossimNuiFactory::instance()
+{
+   
+   if(!theInstance)
+   {
+      theInstance = new ossimNuiFactory;
+   }
+   
+   return theInstance;
+}
+   
+ossimImageHandler* ossimNuiFactory::open(const ossimFilename& fileName)const
+{
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG) << "ossimNuiFactory::open(filename) DEBUG: entered..." << std::endl;
+   }
+   
+   ossimRefPtr<ossimImageHandler> result;
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimNuiFactory::open(filename) DEBUG:"
+         << "\ntrying ossimNuiHandler"
+         << std::endl;
+   }
+   
+   // make sure you put this last
+   //
+   result = new ossimNuiHandler;
+   if(!result->open(fileName))
+   {
+      result = 0;
+   }
+   
+   return result.release();
+}
+
+ossimImageHandler* ossimNuiFactory::open(const ossimKeywordlist& kwl,
+                                          const char* prefix)const
+{
+   ossimRefPtr<ossimImageHandler> result;
+   
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG) << "ossimNuiFactory::open(kwl, prefix) DEBUG: entered..." << std::endl;
+   }
+   
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG) << "ossimNuiFactory::open(kwl, prefix) DEBUG: trying ossimNuiHandler" << std::endl;
+   }
+   result = new ossimNuiHandler;
+   if(!result->loadState(kwl, prefix))
+   {
+      result = 0;
+   }
+   
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG) << "ossimNuiFactory::open(kwl, prefix) DEBUG: leaving..." << std::endl;
+   }
+   
+   return result.release();
+}
+
+ossimObject* ossimNuiFactory::createObject(const ossimString& typeName)const
+{
+   if(STATIC_TYPE_NAME(ossimNuiHandler) == typeName)
+   {
+      return new ossimNuiHandler();
+   }
+   
+   return (ossimObject*)NULL;
+}
+
+ossimObject* ossimNuiFactory::createObject(const ossimKeywordlist& kwl,
+                                                    const char* prefix)const
+{
+   ossimObject* result = (ossimObject*)NULL;
+   const char* type = kwl.find(prefix, ossimKeywordNames::TYPE_KW);
+
+   if(type)
+   {
+      if (ossimString(type).trim() == STATIC_TYPE_NAME(ossimImageHandler))
+      {
+         const char* lookup = kwl.find(prefix, ossimKeywordNames::FILENAME_KW);
+         if (lookup)
+         {
+            // Call the open that takes a filename...
+            result = this->open(kwl, prefix);
+         }
+      }
+      else
+      {
+         result = createObject(ossimString(type));
+         if(result)
+         {
+            result->loadState(kwl, prefix);
+         }
+      }
+   }
+
+   return result;
+}
+ 
+void ossimNuiFactory::getTypeNameList(std::vector<ossimString>& typeList)const
+{
+   typeList.push_back(STATIC_TYPE_NAME(ossimNuiHandler));
+}
+
+void ossimNuiFactory::getSupportedExtensions(ossimImageHandlerFactoryBase::UniqueStringList& extensionList)const
+{
+   extensionList.push_back("nui");
+}
+
diff --git a/ossim_plugins/nui/ossimNuiFactory.h b/ossim_plugins/nui/ossimNuiFactory.h
new file mode 100644
index 0000000..0f09e39
--- /dev/null
+++ b/ossim_plugins/nui/ossimNuiFactory.h
@@ -0,0 +1,63 @@
+//*******************************************************************
+// Copyright (C) 2000 ImageLinks Inc.
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author:  Garrett Potts
+//*******************************************************************
+//  $Id: ossimNuiFactory.h 23664 2015-12-14 14:17:27Z dburken $
+
+#ifndef ossimNuiFactory_HEADER
+#define ossimNuiFactory_HEADER
+
+#include <ossim/imaging/ossimImageHandlerFactoryBase.h>
+#include <ossim/base/ossimString.h>
+
+class ossimGdal;
+class ossimFilename;
+class ossimKeywordlist;
+
+//*******************************************************************
+// CLASS:  ossimNuiFactory
+//*******************************************************************
+class ossimNuiFactory : public ossimImageHandlerFactoryBase
+{
+public:
+   virtual ~ossimNuiFactory();
+   static ossimNuiFactory* instance();
+   
+   virtual ossimImageHandler* open(const ossimFilename& fileName)const;
+   virtual ossimImageHandler* open(const ossimKeywordlist& kwl,
+                                   const char* prefix=0)const;
+
+   
+   virtual ossimObject* createObject(const ossimString& typeName)const;
+   
+   /*!
+    * Creates and object given a keyword list.
+    */
+   virtual ossimObject* createObject(const ossimKeywordlist& kwl,
+                                     const char* prefix=0)const;
+   
+   /*!
+    * This should return the type name of all objects in all factories.
+    * This is the name used to construct the objects dynamially and this
+    * name must be unique.
+    */
+   virtual void getTypeNameList(std::vector<ossimString>& typeList)const;
+   virtual void getSupportedExtensions(ossimImageHandlerFactoryBase::UniqueStringList& extensionList)const;
+
+protected:
+   ossimNuiFactory(){}
+   ossimNuiFactory(const ossimNuiFactory&){}
+   void operator = (const ossimNuiFactory&){}
+
+   static ossimNuiFactory* theInstance;
+
+TYPE_DATA
+};
+
+#endif
+
diff --git a/ossim_plugins/nui/ossimNuiHandler.cpp b/ossim_plugins/nui/ossimNuiHandler.cpp
new file mode 100644
index 0000000..508717c
--- /dev/null
+++ b/ossim_plugins/nui/ossimNuiHandler.cpp
@@ -0,0 +1,716 @@
+#include "ossimNuiHandler.h"
+#include <ossim/base/ossimTrace.h>
+#include <ossim/imaging/ossimImageDataFactory.h>
+#include <ossim/imaging/ossimFixedTileCache.h>
+#include <OpenThreads/Mutex>
+#include <OpenThreads/SCopedLock>
+#include <ossim/base/ossimKeywordNames.h>
+#include <ossim/projection/ossimProjectionFactoryRegistry.h>
+
+ossimNuiData::ossimNuiData()
+{
+   nuif              = NULL;
+   geo               = NULL;
+   tile_width        = 0;
+   tile_height       = 0;
+   tile_size         = 0;
+   image_width       = 0;
+   image_height      = 0;
+   x_pixel_size      = 0;
+   y_pixel_size      = 0;
+   channels          = 0;
+   bytes_per_channel = 0;
+   compression_ratio = 0.0;
+   total_levels      = 0;
+   top_left_x        = 0.0;
+   top_left_y        = 0.0;
+   bot_right_x       = 0.0;
+   bot_right_y       = 0.0;
+   tile_buffer       = 0;
+   decode            = 0;
+   codestream_size   = 0;
+   codestream_buffer = 0;
+   codec             = NUIF_CODEC_NONE;
+}
+
+ossimNuiData::~ossimNuiData()
+{
+//    assert(nuif == NULL);
+//    assert(geo == NULL);
+}
+
+
+static ossimTrace traceDebug("ossimNuiHandler:debug");
+
+RTTI_DEF1(ossimNuiHandler, "ossimNuiHandler", ossimImageHandler);
+
+ossimNuiHandler::ossimNuiHandler()
+{
+}
+
+ossimNuiHandler::~ossimNuiHandler()
+{
+   close();
+}
+
+void ossimNuiHandler::close()
+{
+   clearCache();
+   if (theNui.decode)
+   {
+      if (theNui.codestream_buffer)
+      {
+         NUI_SUPPORT_free(theNui.codestream_buffer);
+         theNui.codestream_buffer = 0;
+      }
+      NUI_J2K2_DECODE_destroy(theNui.decode);
+      theNui.decode = 0;
+   }
+   if (theNui.nuif) 
+   {
+      NUIF_close_file(theNui.nuif);
+      NUIF_destroy(theNui.nuif);
+   }
+   theNui.codec = NUIF_CODEC_NONE;
+   theNui.nuif = 0;
+   theNui.geo = 0;
+   theNui.tile_width = 0;
+   theNui.tile_height = 0;
+   theNui.tile_size = 0;
+   theNui.image_width = 0;
+   theNui.image_height = 0;
+   theNui.decode = 0;
+   if(theNui.tile_buffer)
+   {
+      NUI_SUPPORT_free(theNui.tile_buffer);
+      theNui.tile_buffer = 0;
+      theNui.tile_buffer_rect.makeNan();
+   }
+}
+
+bool ossimNuiHandler::open()
+{
+   static OpenThreads::Mutex openMutex;
+   
+   OpenThreads::ScopedLock<OpenThreads::Mutex> lock(openMutex);
+   
+   int ret_val = 0;
+   
+#ifdef NUI_PLATFORM_UNIX_MACOS
+   //This is a step necessary for GCC on Mac OSX which through
+   //optimizations removes nuiSDK_error and won't link.
+   (void*)nuiSDK_error_string();
+#endif
+   
+   if(isOpen())
+   {
+      close();
+   }
+   
+   theNui.nuif = NUIF_open_file((NUI_CHAR*)theImageFile.c_str(), NUIF_MODE_READONLY);
+   if (theNui.nuif == NULL) 
+   {
+//       std::cout << "ossimNuiHandler:open could not open " << theImageFile.c_str()
+// 	            << " (" << NUIF_error_string() << ")" << std::endl;
+      return false;
+   }
+//    std::cout << "KJ: ossimNuiHandler:open NUI file " << theImageFile.c_str()  << " succeeded." << std::endl;
+   theNui.tile_buffer = 0;
+   theNui.geo = NUIF_GEO_get_object(theNui.nuif);
+   if (theNui.geo == NULL)
+   {
+//       std::cout << "KJ: Unable to get GEO header from the NUI file.  Sorry." << std::endl;
+//       close();
+//       return false;   
+   }
+   
+   NUIF_get_image_parameters(theNui.nuif,
+      &theNui.image_width, 
+	  &theNui.image_height,
+	  &theNui.channels,
+	  &theNui.bits_per_channel,
+	  &theNui.type,
+	  &theNui.layout,
+	  &theNui.codec,
+	  &theNui.compression_ratio);
+   theNui.bytes_per_channel = NUIF_get_total_bytes_per_channel(theNui.nuif);
+
+   switch (theNui.bits_per_channel)
+   {
+   case NUIF_BITS_8:
+   case NUIF_BITS_16:
+   case NUIF_BITS_32:
+   case NUIF_BITS_FLOAT:
+   case NUIF_BITS_DOUBLE:
+      break;
+
+   default:
+   {
+      ossimNotify(ossimNotifyLevel_WARN) << "ossimNuiHandler::open WARNING: Type either unsupported or not sure and need to verify. Sorry." << std::endl;
+      close();
+      return false;
+   }
+   };
+   
+   NUIF_get_tile_size(theNui.nuif, &theNui.tile_width, &theNui.tile_height);
+   theNui.tile_size = theNui.tile_width * theNui.tile_height 
+                    * theNui.channels * theNui.bytes_per_channel;
+					
+   NUIF_GEO_get_basic_parameters(theNui.geo, NULL, NULL,
+	                            &theNui.x_pixel_size, &theNui.y_pixel_size);
+   theNui.total_levels = NUIF_get_total_pyramid_levels(theNui.nuif);
+   
+   theNui.top_left_x = theNui.top_left_y = theNui.bot_right_x = theNui.bot_right_y = 0;
+   ret_val = NUIF_GEO_get_projected_bounding_box(theNui.nuif, 
+                 &theNui.top_left_x,  &theNui.top_left_y,
+				 &theNui.bot_right_x, &theNui.bot_right_y);
+   if (ret_val < 0)
+   {
+      ossimNotify(ossimNotifyLevel_WARN) << "ossimNuiHandler::open WARNING: Unable to get projected bounding box from the NUI file." << std::endl;
+   }
+   if (theNui.codec == NUIF_CODEC_J2K) 
+   {
+      theNui.decode = NUI_J2K2_DECODE_create(NUI_J2K2_SDK_KAKADU);
+      if (theNui.decode == NULL)
+      {
+         close();
+         return false;
+      }
+      
+      //Create the codestream buffer.  
+      theNui.codestream_size = (NUI_UINT32) 
+         NUIF_LEVEL_get_tile_data_size_in_bytes(
+            NUIF_LEVEL_get_first(theNui.nuif));
+      theNui.codestream_buffer =  (NUI_UCHAR  *)NUI_SUPPORT_malloc(theNui.codestream_size, 0);
+      if (theNui.codestream_buffer == NULL)
+      {
+         close();
+         return false;
+      }
+      NUI_J2K2_DECODE_set_raw_image_mem_size(theNui.decode,
+                                             theNui.tile_size); 
+   }
+   else if(theNui.codec != NUIF_CODEC_NONE)
+   {
+      ossimNotify(ossimNotifyLevel_WARN) << "ossimNuiHandler::open WARNGIN: The NUI plugin to OSSIM does not handle the CODEC yet." << std::endl;
+      close();
+      return false;
+   }
+   std::vector<NUI_CHAR> coordName(1024*32);
+   std::vector<NUI_CHAR> coordUnits(1024*32);
+   NUIF_GEO_get_coordinate_system_name_and_units(theNui.nuif,
+                                                 &coordName.front(),
+                                                 coordName.size(),
+                                                 &coordUnits.front(),
+                                                 coordUnits.size());
+   ossimString units(&coordUnits.front());
+
+   theNui.coord_unit_string = "unknown";
+   theNui.coord_unit = OSSIM_UNIT_UNKNOWN;
+   if(units.size())
+   {
+      units = units.downcase();
+      if(units == ossimString("u.u. foot"))
+      {
+         theNui.coord_unit_string = "us_survey_feet";
+         theNui.coord_unit = OSSIM_US_SURVEY_FEET;
+      }
+      else if(units == ossimString("us survey foot"))
+      {
+         theNui.coord_unit_string = "us_survey_feet";
+         theNui.coord_unit = OSSIM_US_SURVEY_FEET;
+      }
+      else if(units == ossimString("degree"))
+      {
+         theNui.coord_unit_string = "degrees";
+         theNui.coord_unit = OSSIM_DEGREES;
+      }
+      else if(units == ossimString("meter"))
+      {
+         theNui.coord_unit_string = "meters";
+         theNui.coord_unit = OSSIM_METERS;
+      }
+      else if(units == ossimString("metre"))
+      {
+         theNui.coord_unit_string = "meters";
+         theNui.coord_unit = OSSIM_METERS;
+      }
+      else
+      {
+         ossimNotify(ossimNotifyLevel_WARN) << "ossimNuiHandler::open WARNING: need a translation for projection cooord units == " << std::endl;
+      }
+   }
+   std::vector<NUI_CHAR> wktString(32*1024);
+   theNui.wkt_string.resize(32*1024); // resize to 32k
+   theNui.wkt_string = "";
+   if(NUIF_GEO_get_coordinate_system_as_OpenGIS_WKT(theNui.nuif,
+                                                    NUI_OPENGIS_WKT_STANDARD,
+                                                    &wktString.front(),
+                                                    wktString.size())==0)
+   {
+      theNui.wkt_string = &wktString.front();
+   }
+
+   theNui.channelMins.clear();
+   theNui.channelMaxs.clear();
+   NUIF_CHANNEL* channel = NUIF_CHANNEL_get_first(theNui.nuif);
+   NUI_DOUBLE minValue;
+   NUI_DOUBLE maxValue;
+
+   while(channel)
+   {
+      
+      NUIF_CHANNEL_get_range(channel,
+                             &minValue,
+                             &maxValue);
+      
+      theNui.channelMins.push_back(minValue);
+      theNui.channelMaxs.push_back(maxValue);
+      channel = NUIF_CHANNEL_get_next(channel);
+   }
+   return true;
+}
+
+bool ossimNuiHandler::isOpen()const
+{
+   if (theNui.nuif != NULL)
+      return true;
+   
+   return false;
+}
+
+ossim_uint32 ossimNuiHandler::getNumberOfLines(ossim_uint32 resLevel)const
+{
+   if(isOpen())
+   {
+      // return the number of lines for a given resolution level(Height)
+      // note,  in OSSIM library it expects the level 0 to typically be the full res image and then
+      // the image get's smaller
+      
+      if (resLevel < theNui.total_levels)
+      {
+         NUIF_LEVEL *level = NUIF_LEVEL_get_by_id(theNui.nuif, resLevel);
+//         assert(level != NULL);
+         if (level != NULL) 
+         {
+            NUI_UINT32   height;
+            NUIF_LEVEL_get_size(level, NULL, &height, NULL, NULL, NULL, NULL);
+            return height;
+         }
+      }
+   }
+   
+   return 0;
+}
+
+ossim_uint32 ossimNuiHandler::getNumberOfSamples(ossim_uint32 resLevel)const
+{
+   if(isOpen())
+   {
+      // return the number of samples for a given resolution level (Width)
+      // note,  in OSSIM library it expects the level 0 to typically be the full res image and then
+      // the image get's smaller
+
+	  if (resLevel < theNui.total_levels)
+	  {
+	     NUIF_LEVEL *level = NUIF_LEVEL_get_by_id(theNui.nuif, resLevel);
+// 		 assert(level != NULL);
+		 if (level != NULL) 
+		 {
+			NUI_UINT32   width;
+			NUIF_LEVEL_get_size(level, &width, NULL, NULL, NULL, NULL, NULL);
+			return width;
+		 }
+	  }
+   }
+   return 0;
+}
+
+ossim_uint32 ossimNuiHandler::getImageTileWidth()const
+{
+   if(isOpen())
+   {
+      // if this image is tiled it will return the tiled dimensions.  This is used to create
+      // a nui tile buffer.  Typical nui files should be blocked or tiled with a width and height
+	  return theNui.tile_width;
+   }
+   return 0;
+}
+
+ossim_uint32 ossimNuiHandler::getImageTileHeight()const
+{
+   if(isOpen())
+   {
+      // if this image is tiled it will return the tiled dimensions.  This is used to create
+      // a nui tile buffer.  Typical nui files should be blocked or tiled with a width and height
+	  return theNui.tile_height;
+   }
+   
+   return 0;
+}
+
+ossim_uint32 ossimNuiHandler::getNumberOfInputBands()const
+{
+   if (isOpen())
+   {
+//       std::cout << "KJ: Garrett, please make sure Input and Output bands = number of channels for NUI." << std::endl;
+	  // return the number of bands for this handler.
+      return theNui.channels;
+   }
+   return 0;
+}
+
+ossim_uint32 ossimNuiHandler::getNumberOfOutputBands()const
+{
+   if(isOpen())
+   {
+      // return the number of bands for this handler.
+//       std::cout << "KJ: Garrett, please make sure Input and Output bands = number of channels for NUI." << std::endl;
+      return theNui.channels;
+   }
+   return 0;
+}
+
+ossimScalarType ossimNuiHandler::getOutputScalarType() const
+{
+//    std::cout << "Need to implement ossimNuiHandler::getOutputScalarType()" << std::endl;
+   // need to return the correct scalar type of the pixel data.  These are found in ossim/base/ossimConstants.h
+   //
+   //
+   
+   if (isOpen())
+   {
+      switch (theNui.bits_per_channel)
+      {
+         case NUIF_BITS_8:
+         {
+            return OSSIM_UINT8;
+         }
+         case NUIF_BITS_16:
+	 {
+            return OSSIM_SINT16;
+         }
+         case NUIF_BITS_32:
+	 {
+            return OSSIM_SINT32;
+         }
+         case NUIF_BITS_FLOAT:
+	 {
+            return OSSIM_FLOAT32;
+         }
+         case NUIF_BITS_DOUBLE:
+	 {
+            return OSSIM_FLOAT64;
+         }
+         default:
+	 {
+            return OSSIM_SCALAR_UNKNOWN;
+         }
+      }
+   }
+   
+   return OSSIM_SCALAR_UNKNOWN;
+}
+
+ossim_uint32 ossimNuiHandler::getNumberOfDecimationLevels()const
+{
+   if(isOpen())
+   {
+      // this value returned should include the full res set.  So at the minimum it
+      // should be 1
+	  return theNui.total_levels;
+   }
+   
+   return 0;
+}
+
+
+void ossimNuiHandler::initialize()
+{
+   theTile          = 0;
+   theNui.tile_buffer_rect.makeNan();
+   clearCache();
+//    theTileCache.clear();
+}
+
+void ossimNuiHandler::allocateTile()
+{
+   if(!isOpen()) return;
+   clearCache();
+//    theTileCache.clear();
+   if(theNui.tile_width&&theNui.tile_height)
+   {
+      theTile          = ossimImageDataFactory::instance()->create(this, this);
+      if(theTile.valid())
+      {
+         theNuiTileBuffer = (ossimImageData*)theTile->dup();
+         
+         theNuiTileBuffer->setWidthHeight(theNui.tile_width,
+                                          theNui.tile_height);
+         theTile->initialize();
+         theNuiTileBuffer->initialize();
+         if(theNui.tile_buffer)
+         {
+            NUI_SUPPORT_free(theNui.tile_buffer);
+            theNui.tile_buffer = 0;
+         }
+         theNui.tile_buffer = (NUI_UCHAR*)NUI_SUPPORT_malloc(theNui.tile_size,
+                                                             0);
+         theTileCache.resize(theNui.total_levels);
+         ossim_uint32 idx = 0;
+
+         for(idx = 0; idx < theTileCache.size(); ++idx)
+         {
+            theTileCache[idx] = ossimAppFixedTileCache::instance()->newTileCache();
+//              = new ossimFixedTileCache;
+            ossimAppFixedTileCache::instance()->setRect(theTileCache[idx],
+                                                        getBoundingRect(idx));
+            ossimAppFixedTileCache::instance()->setTileSize(theTileCache[idx],
+                                                            ossimIpt(theNui.tile_width,
+                                                                     theNui.tile_height));
+            
+//             theTileCache[idx]->setRect(getBoundingRect(idx),
+//                                        ossimIpt(theNui.tile_width,
+//                                                 theNui.tile_height));
+//             theTileCache[idx]->setMaxCacheSize(theNui.tile_size*4);
+         }
+      }
+   }
+}
+
+ossimRefPtr<ossimImageGeometry> ossimNuiHandler::getInternalImageGeometry() const
+{
+   ossimRefPtr<ossimImageGeometry> geom = new ossimImageGeometry();
+   
+   if( isOpen() )
+   {
+      if((theNui.wkt_string!="")&&(theNui.coord_unit!=OSSIM_UNIT_UNKNOWN))
+      {
+         ossimKeywordlist kwl;
+         kwl.add(ossimKeywordNames::TYPE_KW,
+                 theNui.wkt_string,
+                 true);
+         ossimDpt tiePoint(theNui.top_left_x,
+                           theNui.top_left_y);
+         kwl.add(ossimKeywordNames::TIE_POINT_XY_KW,
+                 tiePoint.toString(),
+                 true);
+         kwl.add(ossimKeywordNames::TIE_POINT_UNITS_KW,
+                 theNui.coord_unit_string,
+                 true);
+         kwl.add(ossimKeywordNames::PIXEL_SCALE_XY_KW,
+                 ossimDpt( theNui.x_pixel_size,
+                           theNui.y_pixel_size).toString(),
+                 true);
+         kwl.add(ossimKeywordNames::PIXEL_SCALE_UNITS_KW,
+                 theNui.coord_unit_string,
+                 true);
+         geom->setProjection(ossimProjectionFactoryRegistry::instance()->createProjection(kwl));
+      }
+   }
+   
+   return geom;
+}
+
+ossimRefPtr<ossimImageData> ossimNuiHandler::getTile(const ossimIrect& rect,
+                                                           ossim_uint32 resLevel)
+{
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG) <<  "ossimNuiHandler::getTile: entered........" << std::endl;
+   }
+   if(!isOpen())
+   {
+      if(traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG) <<  "ossimNuiHandler::getTile: leaving 1........" << std::endl;
+      }
+      return 0;
+   }
+   if(!theTile.valid()||!theNuiTileBuffer.valid())
+   {
+      allocateTile();
+   }
+   
+   if(theTile.valid())
+   {
+      theTile->setImageRectangle(rect);
+   }
+   else
+   {
+      return 0;
+   }
+   if(!theNuiTileBuffer.valid())
+   {
+      return theTile;
+   }
+   if(resLevel >= theNui.total_levels)
+   {
+      return 0;
+   }
+   theTile->makeBlank();
+   ossimInterleaveType interleaveType;
+   switch(theNui.layout)
+   {
+      case NUIF_DATA_LAYOUT_PACKED:
+      {
+         interleaveType = OSSIM_BIP;
+         break;
+      }
+      case NUIF_DATA_LAYOUT_PLANAR:
+      {
+         interleaveType = OSSIM_BSQ;
+         break;
+      }
+      default:
+      {
+         return theTile;
+      }
+   }
+
+   ossimIrect boundingRect = getBoundingRect(resLevel);
+   if(!boundingRect.intersects(rect)) return 0;
+   ossimIrect tempRect = boundingRect.clipToRect(rect);
+   tempRect.stretchToTileBoundary(ossimIpt(theNui.tile_width,
+                                           theNui.tile_height));
+   ossim_uint32 x, y;
+   ossim_uint32 h = tempRect.height();
+   ossim_uint32 w = tempRect.width();
+   ossimIpt origin;
+   ossim_uint32 row, col;
+   ossimIpt ul = tempRect.ul();
+   ossimRefPtr<ossimImageData> data = 0;
+   
+   for(y = 0; y < h; y+=theNui.tile_height)
+   {
+      for(x = 0; x < w; x+=theNui.tile_width)
+      {
+         data = 0;
+         origin = ul+ossimIpt(x, y);
+         if(resLevel < theTileCache.size())
+         {
+            data = ossimAppFixedTileCache::instance()->getTile(theTileCache[resLevel], origin);
+         }
+         if(data.valid())
+         {
+            if(data->getBuf() &&
+               (data->getDataObjectStatus()!=OSSIM_EMPTY))
+            {
+               theTile->loadTile(data->getBuf(),
+                                 data->getImageRectangle(),
+                                 OSSIM_BSQ);
+            }
+         }
+         else
+         {
+            bool decoded = true;
+            row = origin.y/theNui.tile_height;
+            col = origin.x/theNui.tile_width;
+            if(NUIF_read_packed_tile_from_level(theNui.nuif,
+                                                resLevel,
+                                                row,
+                                                col,
+                                                ((theNui.decode)?theNui.codestream_buffer:
+                                                 theNui.tile_buffer)) == 0)
+            {
+               if(theNui.decode)
+               {
+                  if(NUI_J2K2_DECODE_set_code_stream(theNui.decode,
+                                                     theNui.codestream_buffer, 
+                                                     theNui.codestream_size) < 0)
+                  {
+                     decoded = false;
+                  }
+               
+                  if(NUI_J2K2_DECODE_decompress_code_stream(theNui.decode,
+                                                            NULL, NULL, NULL, NULL, theNui.tile_buffer) < 0)
+                  {
+                     decoded = false;
+                  }
+               }
+               if(decoded)
+               {
+                  theNui.tile_buffer_rect=ossimIrect(origin.x,
+                                                     origin.y,
+                                                     origin.x + (theNui.tile_width-1),
+                                                     origin.y + (theNui.tile_height-1));
+                  
+                  if(resLevel < theTileCache.size())
+                  {
+                     ossimRefPtr<ossimImageData> dataToUse = theNuiTileBuffer;
+                     dataToUse->setImageRectangle(theNui.tile_buffer_rect);
+                     dataToUse->makeBlank();
+                     dataToUse->loadTile(theNui.tile_buffer,
+                                         theNui.tile_buffer_rect,
+                                         interleaveType);
+                     dataToUse->setDataObjectStatus(OSSIM_FULL);
+                     ossimAppFixedTileCache::instance()->addTile(theTileCache[resLevel], dataToUse);                     
+                  }
+                  theTile->loadTile(theNui.tile_buffer,
+                                    theNui.tile_buffer_rect,
+                                    interleaveType);
+               }
+            }
+         }
+      }
+   }
+   theTile->validate();
+   
+   return theTile;
+}
+
+double ossimNuiHandler::getNullPixelValue(ossim_uint32 band)const
+{
+   return ossimImageHandler::getNullPixelValue(band);
+}
+
+double ossimNuiHandler::getMinPixelValue(ossim_uint32 band)const
+{
+   if(isOpen())
+   {
+      if(band < theNui.channelMins.size())
+      {
+			if(theNui.channelMins[band] != getNullPixelValue(band))
+			{
+				return theNui.channelMins[band];
+			}
+      }
+   }
+   return ossimImageHandler::getMinPixelValue(band);
+}
+
+double ossimNuiHandler::getMaxPixelValue(ossim_uint32 band)const
+{
+   if(isOpen())
+   {
+      if(band < theNui.channelMaxs.size())
+      {
+         return theNui.channelMaxs[band];
+      }
+   }
+   return ossimImageHandler::getMaxPixelValue(band);
+}
+
+bool ossimNuiHandler::saveState(ossimKeywordlist& kwl,
+                                      const char* prefix)const
+{
+   return ossimImageHandler::saveState(kwl, prefix);
+}
+
+bool ossimNuiHandler::loadState(const ossimKeywordlist& kwl,
+                                      const char* prefix)
+{
+   ossimImageHandler::loadState(kwl, prefix);
+
+   return open();
+}
+
+void ossimNuiHandler::clearCache()
+{
+   ossim_uint32 idx = 0;
+   for(idx = 0; idx < theTileCache.size();++idx)
+   {
+      ossimAppFixedTileCache::instance()->deleteCache(theTileCache[idx]);
+   }
+   theTileCache.clear();
+}
diff --git a/ossim_plugins/nui/ossimNuiHandler.h b/ossim_plugins/nui/ossimNuiHandler.h
new file mode 100644
index 0000000..28e69f8
--- /dev/null
+++ b/ossim_plugins/nui/ossimNuiHandler.h
@@ -0,0 +1,103 @@
+#ifndef ossimNuiHandler_HEADER
+#define ossimNuiHandler_HEADER
+#include <ossim/imaging/ossimImageHandler.h>
+#include <ossim/base/ossimXmlDocument.h>
+#include <ossim/imaging/ossimAppFixedTileCache.h>
+#include <nuiSDK.h>
+
+// ossimNuiData is a normal struct holding all the information
+// about an open NUI file but benefits from C++ ctors to initialize
+// and the dtor to assert if not cleaned up.
+
+struct ossimNuiData 
+{
+   ossimNuiData();
+   ~ossimNuiData();
+   
+   NUIF             *nuif;
+   NUIF_GEO         *geo;
+   NUI_UINT32        tile_width;		//tile width
+   NUI_UINT32        tile_height;		//tile height
+   NUI_UINT32        tile_size;			//tile size in bytes
+   NUI_UINT32        image_width;		//image width of RRD 0
+   NUI_UINT32        image_height;		//image height of RRD 0
+   NUI_DOUBLE        x_pixel_size;		//size of pixels - X
+   NUI_DOUBLE        y_pixel_size;		//size of pixels - Y
+   NUI_UINT32        channels;			//# channels
+   NUI_UINT32		 bytes_per_channel;	//# bytes per channel
+   NUIF_BITS_PER_CHANNEL  bits_per_channel;	//bits per channel
+   NUIF_DATA_TYPE    type;			    //data type
+   NUIF_DATA_LAYOUT  layout;			//data layout
+   NUIF_CODEC		 codec;			    //compression codec
+   NUI_DOUBLE		 compression_ratio; //compression ratio
+   NUI_UINT32		 total_levels;		//#levels (RRDs)
+   NUI_DOUBLE		 top_left_x;        //bounding box TL-x
+   NUI_DOUBLE	     top_left_y;        //bounding box TL-y
+   NUI_DOUBLE		 bot_right_x;       //bounding box BR-x
+   NUI_DOUBLE        bot_right_y;	    //bounding box BR-y
+   ossimUnitType     coord_unit;
+   ossimString       coord_unit_string;
+   ossimString       wkt_string;
+   NUI_UCHAR*         tile_buffer;
+   ossimIrect         tile_buffer_rect;
+   std::vector<double> channelMins;
+   std::vector<double> channelMaxs;
+
+   /* COMPRESSION PARAMETERS */
+   NUI_J2K2_DECODE *decode;
+   NUI_UINT32 codestream_size;
+   NUI_UCHAR  *codestream_buffer;
+};
+     
+
+class ossimNuiHandler : public ossimImageHandler
+{
+public:
+   ossimNuiHandler();
+   virtual ~ossimNuiHandler();
+   virtual bool open();
+   virtual void close();
+   virtual bool isOpen()const;
+   virtual ossim_uint32 getNumberOfLines(ossim_uint32 resLevel)const;
+   virtual ossim_uint32 getNumberOfSamples(ossim_uint32 resLevel)const;
+   virtual ossim_uint32 getImageTileWidth()const;
+   virtual ossim_uint32 getImageTileHeight()const;
+   virtual ossim_uint32 getNumberOfInputBands()const;
+   virtual ossim_uint32 getNumberOfOutputBands()const;
+   
+   virtual ossim_uint32 getNumberOfDecimationLevels()const;
+   virtual ossimScalarType getOutputScalarType() const;
+ 
+   virtual ossimRefPtr<ossimImageGeometry> getInternalImageGeometry() const;
+   virtual double getNullPixelValue(ossim_uint32 band=0)const;
+   virtual double getMinPixelValue(ossim_uint32 band=0)const;
+   virtual double getMaxPixelValue(ossim_uint32 band=0)const;
+
+   virtual ossimRefPtr<ossimImageData> getTile(const ossimIrect& rect,
+                                               ossim_uint32 resLevel=0);
+
+   ossimIrect tileBounds(const ossimGpt& gpt,
+                         ossim_uint32 resLevel);
+
+   virtual void initialize();
+   virtual bool saveState(ossimKeywordlist& kwl,
+                          const char* prefix=0)const;
+
+   virtual bool loadState(const ossimKeywordlist& kwl,
+                          const char* prefix=0);
+    
+protected:
+   void allocateTile();
+   void clearCache();
+   ossimRefPtr<ossimImageData> theTile;
+
+   std::vector<ossimAppFixedTileCache::ossimAppFixedCacheId> theTileCache;
+/*    std::vector<ossimRefPtr<ossimFixedTileCache> > theTileCache; */
+   ossimRefPtr<ossimImageData> theNuiTileBuffer;
+   ossimNuiData                theNui;
+   
+   
+TYPE_DATA
+};
+
+#endif
diff --git a/ossim_plugins/nui/ossimNuiPluginInit.cpp b/ossim_plugins/nui/ossimNuiPluginInit.cpp
new file mode 100644
index 0000000..e10865c
--- /dev/null
+++ b/ossim_plugins/nui/ossimNuiPluginInit.cpp
@@ -0,0 +1,57 @@
+#include <ossim/plugin/ossimSharedObjectBridge.h>
+#include <ossim/base/ossimString.h>
+#include <ossim/imaging/ossimImageHandlerRegistry.h>
+#include "ossimNuiFactory.h"
+#include "ossimNuiExports.h"
+
+static void setDescription(ossimString& description)
+{
+   description = "This plugin supports loaders for Pixia's NUI file format.";
+}
+
+extern "C"
+{
+   ossimSharedObjectInfo  myInfo;
+   ossimString theDescription;
+   std::vector<ossimString> theObjList;
+   const char* getDescription()
+   {
+      return theDescription.c_str();
+   }
+   int getNumberOfClassNames()
+   {
+      return (int)theObjList.size();
+   }
+   const char* getClassName(int idx)
+   {
+      if(idx < (int)theObjList.size())
+      {
+         return theObjList[0].c_str();
+      }
+      return (const char*)0;
+   }
+
+   /* Note symbols need to be exported on windoze... */ 
+   OSSIM_NUI_DLL void ossimSharedLibraryInitialize(
+      ossimSharedObjectInfo** info)
+   {    
+      myInfo.getDescription = (ossimSharedLibraryGetDescriptionPtr)getDescription;
+      myInfo.getNumberOfClassNames = (ossimSharedLibraryGetNumberOfClassNamesPtr)getNumberOfClassNames;
+      myInfo.getClassName = (ossimSharedLibraryGetClassNamesPtr)getClassName;
+      
+      *info = &myInfo;
+
+      /* Register the readers... */
+      ossimImageHandlerRegistry::instance()->registerFactory(ossimNuiFactory::instance());
+      
+     /* Register the writers... */
+     
+     setDescription(theDescription);
+  }
+
+   /* Note symbols need to be exported on windoze... */ 
+   OSSIM_NUI_DLL void ossimSharedLibraryFinalize()
+   {
+      
+   }
+}
diff --git a/ossim_plugins/nui/ossimnui_plugin.vcproj b/ossim_plugins/nui/ossimnui_plugin.vcproj
new file mode 100644
index 0000000..1ddc127
--- /dev/null
+++ b/ossim_plugins/nui/ossimnui_plugin.vcproj
@@ -0,0 +1,207 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="9.00"
+	Name="ossimnui_plugin"
+	ProjectGUID="{AA70BAD4-84B5-4D56-975C-4EC3E035D9ED}"
+	RootNamespace="ossim_pngplugin"
+	Keyword="Win32Proj"
+	TargetFrameworkVersion="131072"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="ReleaseWithSymbols|Win32"
+			OutputDirectory="$(SolutionDir)bin\$(ConfigurationName)"
+			IntermediateDirectory="$(ConfigurationName)"
+			ConfigurationType="2"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="C:\Users\Kent\Projects\OSSIM\ossim_plugins;C:\Users\Kent\Projects\OSSIM\ossim\include;C:\Users\Kent\Projects\OSSIM\ossim_dependencies\src\3rdParty\include;"$(InputDir)""
+				PreprocessorDefinitions="_CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_WINDOWS;_USRDLL;OSSIMUSINGDLL;HAVE_CONFIG_H"
+				RuntimeLibrary="2"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="false"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="libpng.lib zlib.lib"
+				LinkIncremental="1"
+				AdditionalLibraryDirectories="$(SolutionDir)..\..\..\ossim_dependencies\src\3rdParty\lib"
+				GenerateDebugInformation="true"
+				SubSystem="0"
+				OptimizeReferences="0"
+				EnableCOMDATFolding="0"
+				RandomizedBaseAddress="1"
+				DataExecutionPrevention="0"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|Win32"
+			OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+			IntermediateDirectory="$(ConfigurationName)"
+			ConfigurationType="2"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="3"
+				AdditionalIncludeDirectories=""$(InputDir)..\..\ossim\include";"$(InputDir)..\..\ossim_dependencies\include";"$(InputDir)";"$(InputDir)..\""
+				PreprocessorDefinitions="_CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_WINDOWS;_USRDLL;OSSIM_NUI_MAKINGDLL"
+				RuntimeLibrary="2"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="false"
+				DebugInformationFormat="0"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies=""OpenThreads.lib  nuiSDK.lib"
+				OutputFile="$(OutDir)\bin\$(ProjectName).dll"
+				LinkIncremental="1"
+				AdditionalLibraryDirectories=""$(InputDir)..\..\ossim_dependencies\src\OpenSceneGraph-2.8.1\build\lib";"$(ProjectDir)..\..\ossim_dependencies\src\nuiGeoSDK\lib";"$(ProjectDir)..\..\ossim_dependencies\lib""
+				GenerateDebugInformation="false"
+				SubSystem="0"
+				OptimizeReferences="0"
+				EnableCOMDATFolding="0"
+				RandomizedBaseAddress="1"
+				DataExecutionPrevention="0"
+				ImportLibrary="$(OutDir)\lib\$(ProjectName).lib"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+				CommandLine=""
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<File
+			RelativePath=".\ossimNuiExports.h"
+			>
+		</File>
+		<File
+			RelativePath=".\ossimNuiFactory.cpp"
+			>
+		</File>
+		<File
+			RelativePath=".\ossimNuiFactory.h"
+			>
+		</File>
+		<File
+			RelativePath=".\ossimNuiHandler.cpp"
+			>
+		</File>
+		<File
+			RelativePath=".\ossimNuiHandler.h"
+			>
+		</File>
+		<File
+			RelativePath=".\ossimNuiPluginInit.cpp"
+			>
+		</File>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
diff --git a/ossim_plugins/opencv/CMakeLists.txt b/ossim_plugins/opencv/CMakeLists.txt
new file mode 100644
index 0000000..81d7749
--- /dev/null
+++ b/ossim_plugins/opencv/CMakeLists.txt
@@ -0,0 +1,46 @@
+set(LIB_NAME ossimopencv_plugin)
+MESSAGE( "************** LIBRARY SETUP FOR ossimopencv_plugin ******************")
+
+# Include ossim cmake stuff:
+include(OssimVersion)
+include(OssimCommonVariables)
+include(OssimUtilities)
+
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
+
+SET(requiredLib)
+
+find_package( OpenCV )
+if( OPENCV_FOUND )
+	include_directories( ${OPENCV_INCLUDE_DIR} )
+	set( requiredLib ${requiredLib} ${OPENCV_LIBRARIES} )
+else( OPENCV_FOUND )
+	message( FATAL_ERROR "Could not find OpenCV package!" )
+endif( OPENCV_FOUND )
+
+MESSAGE( STATUS "OPENCV_LIBRARY = ${OPENCV_LIBRARIES}" )
+MESSAGE( STATUS "OPENCV_INCLUDE = ${OPENCV_INCLUDE_DIR}" )
+
+FILE(GLOB_RECURSE OSSIMPLUGIN_SRCS *.cpp)
+FILE(GLOB_RECURSE OSSIMPLUGIN_HEADERS *.h)
+
+####
+# OSSIMPLUGINSMAKINGDLL controls dll linkage on windows.  
+# Adding this sets OSSIM_PLUGINS_DLL #define TO "__declspec(dllexport)".
+###
+add_definitions("-DOSSIMPLUGINSMAKINGDLL")
+
+# Adjust the install library path:
+if(OSSIM_INSTALL_PLUGINS_WITH_VERSION)
+   set(INSTALL_LIBRARY_DIR   "${INSTALL_LIBRARY_DIR}/ossim-${OSSIM_VERSION}/plugins")
+else(OSSIM_INSTALL_PLUGINS_WITH_VERSION)
+   set(INSTALL_LIBRARY_DIR   "${INSTALL_LIBRARY_DIR}/ossim/plugins")
+endif(OSSIM_INSTALL_PLUGINS_WITH_VERSION)
+
+OSSIM_LINK_LIBRARY(${LIB_NAME}
+                   COMPONENT_NAME ossim TYPE "${OSSIM_PLUGIN_LINK_TYPE}"
+		   LIBRARIES ${OSSIM_LIBRARIES} ${requiredLib} 
+		   HEADERS "${OSSIMPLUGIN_HEADERS}"
+		   SOURCE_FILES "${OSSIMPLUGIN_SRCS}"
+                   INSTALL_LIB)
+
diff --git a/ossim_plugins/opencv/ossimIvtGeomXform.cpp b/ossim_plugins/opencv/ossimIvtGeomXform.cpp
new file mode 100644
index 0000000..1a6802e
--- /dev/null
+++ b/ossim_plugins/opencv/ossimIvtGeomXform.cpp
@@ -0,0 +1,60 @@
+#include "ossimIvtGeomXform.h"
+
+
+void ossimIvtGeomXform::viewToImage(const ossimDpt& viewPt, ossimDpt& ipt)
+{
+  ipt.makeNan();
+  if(m_ivt.valid())
+  {
+    m_ivt->viewToImage(viewPt, ipt);
+  }
+}
+
+void ossimIvtGeomXform::imageToView(const ossimDpt& ipt, ossimDpt& viewPt)
+{
+  viewPt.makeNan();
+  if(m_ivt.valid())
+  {
+    m_ivt->imageToView(ipt, viewPt);
+  }
+}
+void ossimIvtGeomXform::imageToGround(const ossimDpt& ipt, ossimGpt& gpt)
+{
+  gpt.makeNan();
+  if(m_geom.valid())
+  {
+    m_geom->localToWorld(ipt, gpt);
+  }
+}
+void ossimIvtGeomXform::groundToImage(const ossimGpt& gpt, ossimDpt& ipt)
+{
+  ipt.makeNan();
+  if(m_geom.valid())
+  {
+    m_geom->worldToLocal(gpt, ipt);
+  }
+}
+
+void ossimIvtGeomXform::viewToGround(const ossimDpt& viewPt, ossimGpt& gpt)
+{
+  ossimDpt ipt;
+  gpt.makeNan();
+  viewToImage(viewPt, ipt);
+  if(!ipt.hasNans())
+  {
+    imageToGround(ipt, gpt);
+  }
+}
+
+void ossimIvtGeomXform::groundToView(const ossimGpt& gpt, ossimDpt& viewPt)
+{
+  ossimDpt ipt;
+  viewPt.makeNan();
+
+  groundToImage(gpt, ipt);
+  if(!ipt.hasNans())
+  {
+    imageToView(ipt, viewPt);
+  }
+}
+
diff --git a/ossim_plugins/opencv/ossimIvtGeomXform.h b/ossim_plugins/opencv/ossimIvtGeomXform.h
new file mode 100644
index 0000000..6dee7a6
--- /dev/null
+++ b/ossim_plugins/opencv/ossimIvtGeomXform.h
@@ -0,0 +1,36 @@
+#ifndef ossimIvtGeomXform_HEADER
+#define ossimIvtGeomXform_HEADER
+#include <ossim/base/ossimReferenced.h>
+#include <ossim/base/ossimIpt.h>
+#include <ossim/base/ossimDpt.h>
+#include <ossim/base/ossimGpt.h>
+#include <ossim/projection/ossimImageViewProjectionTransform.h>
+#include <ossim/projection/ossimImageViewAffineTransform.h>
+
+class ossimIvtGeomXform : public ossimReferenced
+{
+public:
+    ossimIvtGeomXform(ossimImageViewTransform* trans, 
+                           ossimImageGeometry* geom)
+    :
+    m_ivt(trans),
+    m_geom(geom)
+    {}
+
+    void viewToImage(const ossimDpt& viewPt, ossimDpt& ipt);
+    void imageToView(const ossimDpt& ipt, ossimDpt& viewPt);
+    void imageToGround(const ossimDpt& ipt, ossimGpt& gpt);
+    void groundToImage(const ossimGpt& gpt, ossimDpt& ipt);
+    void viewToGround(const ossimDpt& viewPt, ossimGpt& gpt);
+    void groundToView(const ossimGpt& gpt, ossimDpt& viewPt);
+    ossimImageViewTransform* getIvt(){return m_ivt.get();}
+    const ossimImageViewTransform* getIvt()const {return m_ivt.get();}
+    ossimImageGeometry* getGeom(){return m_geom.get();}
+    const ossimImageGeometry* getGeom()const{return m_geom.get();}
+
+protected:
+    ossimRefPtr<ossimImageViewTransform> m_ivt;
+    ossimRefPtr<ossimImageGeometry> m_geom;
+};
+
+#endif
diff --git a/ossim_plugins/opencv/ossimIvtGeomXformVisitor.cpp b/ossim_plugins/opencv/ossimIvtGeomXformVisitor.cpp
new file mode 100644
index 0000000..adb84c6
--- /dev/null
+++ b/ossim_plugins/opencv/ossimIvtGeomXformVisitor.cpp
@@ -0,0 +1,40 @@
+  #include "ossimIvtGeomXformVisitor.h"
+  #include <ossim/imaging/ossimImageRenderer.h>
+  #include <ossim/imaging/ossimImageHandler.h>
+
+
+  void ossimIvtGeomXformVisitor::visit(ossimObject* obj)
+  {
+    if(!hasVisited(obj))
+    {
+      ossimImageRenderer* renderer = dynamic_cast<ossimImageRenderer*>(obj);
+      if(renderer)
+      {
+        ossimImageViewProjectionTransform* ivpt = dynamic_cast<ossimImageViewProjectionTransform*>(renderer->getImageViewTransform());
+        if(ivpt)
+        {
+          m_transformList.push_back(new ossimIvtGeomXform(ivpt, ivpt->getImageGeometry()) );
+        }
+        else
+        {
+          ossimImageViewAffineTransform* ivat = dynamic_cast<ossimImageViewAffineTransform*>(renderer->getImageViewTransform());
+          if(ivat&&renderer->getInput())
+          {
+            ossimTypeNameVisitor v("ossimImageHandler", true);
+            renderer->accept(v);
+            
+            ossimImageHandler* handler = v.getObjectAs<ossimImageHandler>(0);
+            if(handler)
+            {
+              ossimRefPtr<ossimImageGeometry> geom = handler->getImageGeometry();
+              if(geom.valid())
+              {
+                m_transformList.push_back(new ossimIvtGeomXform(ivat, geom.get()) );
+              }
+            }
+          }
+        }
+      }
+      ossimVisitor::visit(obj);
+    }
+  }
diff --git a/ossim_plugins/opencv/ossimIvtGeomXformVisitor.h b/ossim_plugins/opencv/ossimIvtGeomXformVisitor.h
new file mode 100644
index 0000000..67002ad
--- /dev/null
+++ b/ossim_plugins/opencv/ossimIvtGeomXformVisitor.h
@@ -0,0 +1,25 @@
+#ifndef ossimIvtGeomXformVisitor_HEADER
+#define ossimIvtGeomXformVisitor_HEADER
+#include <ossim/base/ossimVisitor.h>
+#include "ossimIvtGeomXform.h"
+
+class ossimIvtGeomXformVisitor : public ossimVisitor
+{
+public:
+   typedef std::vector<ossimRefPtr<ossimIvtGeomXform> > TransformList;
+
+   ossimIvtGeomXformVisitor(int visitorType =(VISIT_INPUTS|VISIT_CHILDREN))
+   :ossimVisitor(visitorType)
+   {}
+   
+   virtual ossimRefPtr<ossimVisitor> dup()const{return new ossimIvtGeomXformVisitor(*this);}
+   virtual void visit(ossimObject* obj);
+
+   TransformList& getTransformList(){return m_transformList;}
+   const TransformList& getTransformList()const{return m_transformList;}
+
+protected:
+   TransformList m_transformList;
+};
+
+#endif
\ No newline at end of file
diff --git a/ossim_plugins/opencv/ossimOpenCvObjectFactory.cpp b/ossim_plugins/opencv/ossimOpenCvObjectFactory.cpp
new file mode 100644
index 0000000..a167502
--- /dev/null
+++ b/ossim_plugins/opencv/ossimOpenCvObjectFactory.cpp
@@ -0,0 +1,90 @@
+//----------------------------------------------------------------------------
+//
+// File: ossimOpenCvObjectFactory.cpp
+// 
+// License:  See top level LICENSE.txt file
+//
+// Author:  David Hicks
+//
+// Description: Factory for OSSIM OpenCvObject plugin.
+//----------------------------------------------------------------------------
+
+#include "ossimOpenCvObjectFactory.h"
+#include "ossimTieMeasurementGenerator.h"
+#include <ossim/base/ossimKeywordlist.h>
+#include <ossim/base/ossimRefPtr.h>
+#include <ossim/base/ossimString.h>
+#include <ossim/base/ossimTrace.h>
+#include <ossim/base/ossimKeywordNames.h>
+
+static const ossimTrace traceDebug("ossimOpenCvObjectFactory:debug");
+
+RTTI_DEF1(ossimOpenCvObjectFactory,
+          "ossimOpenCvObjectFactory",
+          ossimObjectFactory);
+
+ossimOpenCvObjectFactory* ossimOpenCvObjectFactory::theInstance = 0;
+
+ossimOpenCvObjectFactory::~ossimOpenCvObjectFactory()
+{
+   theInstance = 0;
+}
+
+ossimOpenCvObjectFactory* ossimOpenCvObjectFactory::instance()
+{
+   if(!theInstance)
+   {
+      theInstance = new ossimOpenCvObjectFactory;
+   }
+   return theInstance;
+}
+
+
+ossimObject* ossimOpenCvObjectFactory::createObject(
+   const ossimString& typeName)const
+{
+   ossimObject* result = 0;
+
+   if(typeName == "ossimTieMeasurementGenerator")
+   {
+      result = new ossimTieMeasurementGenerator;
+   }
+   return result;
+}
+
+
+ossimObject* ossimOpenCvObjectFactory::createObject(const ossimKeywordlist& kwl,
+                                                    const char* prefix)const
+{
+   ossimObject* result = 0;
+
+   const char* type = kwl.find(prefix, "type");
+   if(type)
+   {
+      result = createObject(ossimString(type));
+      if(result)
+      {
+         result->loadState(kwl, prefix);
+      }
+   }
+
+   return result; 
+}
+ 
+void ossimOpenCvObjectFactory::getTypeNameList(std::vector<ossimString>& typeList)const
+{
+   typeList.push_back(ossimString("ossimTieMeasurementGenerator"));
+}
+
+ossimOpenCvObjectFactory::ossimOpenCvObjectFactory()
+{
+}
+
+ossimOpenCvObjectFactory::ossimOpenCvObjectFactory(const ossimOpenCvObjectFactory&)
+{
+}
+
+const ossimOpenCvObjectFactory& ossimOpenCvObjectFactory::operator=(const ossimOpenCvObjectFactory&)
+{
+   return *this;
+}
diff --git a/ossim_plugins/opencv/ossimOpenCvObjectFactory.h b/ossim_plugins/opencv/ossimOpenCvObjectFactory.h
new file mode 100644
index 0000000..5480cf3
--- /dev/null
+++ b/ossim_plugins/opencv/ossimOpenCvObjectFactory.h
@@ -0,0 +1,71 @@
+//----------------------------------------------------------------------------
+//
+// File: ossimOpenCvObjectFactory.h
+// 
+// License:  See top level LICENSE.txt file
+//
+// Author:  David Hicks
+//
+// Description: Factory for OSSIM OpenCvObject plugin.
+//----------------------------------------------------------------------------
+
+#ifndef ossimOpenCvObjectFactory_HEADER
+#define ossimOpenCvObjectFactory_HEADER 1
+
+#include <ossim/base/ossimObjectFactory.h>
+
+
+class ossimString;
+class ossimKeywordlist;
+
+/** @brief Factory for ossimOpenCvObject. */
+class ossimOpenCvObjectFactory : public ossimObjectFactory
+{
+public:
+
+   /** @brief virtual destructor */
+   virtual ~ossimOpenCvObjectFactory();
+
+   /**
+    * @brief static method to return instance (the only one) of this class.
+    * @return pointer to instance of this class.
+    */
+   static ossimOpenCvObjectFactory* instance();
+
+   /**
+    * @brief createObject that takes a class name (eg. ossimTieMeasurementGenerator)
+    * @param typeName (class, eg. "ossimTieMeasurementGenerator").
+    */
+   virtual ossimObject* createObject(const ossimString& typeName)const;
+   
+   /**
+    * @brief Creates an object given a keyword list and prefix.
+    * @param kwl The keyword list.
+    * @param prefix the keyword list prefix.
+    */
+   virtual ossimObject* createObject(const ossimKeywordlist& kwl,
+                                     const char* prefix=0)const;
+   
+   /**
+    * @brief Adds ossimLasWriter to the typeList.
+    * @param typeList List to add to.
+    */
+   virtual void getTypeNameList(std::vector<ossimString>& typeList)const;
+  
+protected:
+   /** @brief hidden from use default constructor */
+   ossimOpenCvObjectFactory();
+
+   /** @brief hidden from use copy constructor */
+   ossimOpenCvObjectFactory(const ossimOpenCvObjectFactory&);
+
+   /** @brief hidden from use copy constructor */
+   const ossimOpenCvObjectFactory& operator=(const ossimOpenCvObjectFactory&);
+
+   /** static instance of this class */
+   static ossimOpenCvObjectFactory* theInstance;
+
+TYPE_DATA
+};
+
+#endif /* end of #ifndef ossimOpenCvObjectFactory_HEADER */
diff --git a/ossim_plugins/opencv/ossimOpenCvPluginInit.cpp b/ossim_plugins/opencv/ossimOpenCvPluginInit.cpp
new file mode 100644
index 0000000..d9224c3
--- /dev/null
+++ b/ossim_plugins/opencv/ossimOpenCvPluginInit.cpp
@@ -0,0 +1,72 @@
+//----------------------------------------------------------------------------
+//
+// License:  See top level LICENSE.txt file
+//
+// Author:  David Hicks
+//
+// Description: OpenCV plugin initialization code.
+//
+//----------------------------------------------------------------------------
+// $Id
+
+#include <ossim/plugin/ossimSharedObjectBridge.h>
+#include "ossimPluginConstants.h"
+#include "ossimOpenCvObjectFactory.h"
+#include <ossim/base/ossimString.h>
+#include <ossim/base/ossimObjectFactoryRegistry.h>
+
+static void setDescription(ossimString& description)
+{
+   description = "OpenCV plugin\n\n";
+}
+
+
+extern "C"
+{
+   ossimSharedObjectInfo  myInfo;
+   ossimString theDescription;
+   std::vector<ossimString> theObjList;
+   
+   const char* getDescription()
+   {
+      return theDescription.c_str();
+   }
+   
+   int getNumberOfClassNames()
+   {
+      return (int)theObjList.size();
+   }
+   
+   const char* getClassName(int idx)
+   {
+      if(idx < (int)theObjList.size())
+      {
+         return theObjList[0].c_str();
+      }
+      return (const char*)0;
+   }
+   
+   /* Note symbols need to be exported on windoze... */ 
+   OSSIM_PLUGINS_DLL void ossimSharedLibraryInitialize(
+      ossimSharedObjectInfo** info)
+   {    
+      myInfo.getDescription = getDescription;
+      myInfo.getNumberOfClassNames = getNumberOfClassNames;
+      myInfo.getClassName = getClassName;
+      
+      *info = &myInfo;
+      
+     /* Register objects... */
+     ossimObjectFactoryRegistry::instance()->
+        registerFactory(ossimOpenCvObjectFactory::instance());
+      
+      setDescription(theDescription);
+   }
+   
+   /* Note symbols need to be exported on windoze... */ 
+   OSSIM_PLUGINS_DLL void ossimSharedLibraryFinalize()
+   {
+     ossimObjectFactoryRegistry::instance()->
+        unregisterFactory(ossimOpenCvObjectFactory::instance());
+   }
+}
diff --git a/ossim_plugins/opencv/ossimTieMeasurementGenerator.cpp b/ossim_plugins/opencv/ossimTieMeasurementGenerator.cpp
new file mode 100644
index 0000000..a57b6b5
--- /dev/null
+++ b/ossim_plugins/opencv/ossimTieMeasurementGenerator.cpp
@@ -0,0 +1,728 @@
+//----------------------------------------------------------------------------
+//
+// License:  See top level LICENSE.txt file.
+//
+// Author:  David Hicks
+//
+// Description: Automatic tie measurement extraction.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include <ossim/base/ossimString.h>
+#include <ossim/base/ossimNotify.h>
+#include <ossim/base/ossimTrace.h>
+#include <ossim/base/ossimIrect.h>
+#include <ossim/base/ossimRefPtr.h>
+#include <ossim/base/ossimConstants.h>
+#include <ossim/elevation/ossimElevManager.h>
+#include <ossim/imaging/ossimImageData.h>
+#include <ossim/imaging/ossimImageSource.h>
+
+#include "ossimTieMeasurementGenerator.h"
+#include "ossimIvtGeomXformVisitor.h"
+
+#include <opencv/highgui.h>
+#include <opencv2/core/core.hpp>
+#include <opencv2/highgui/highgui.hpp>
+#include <opencv2/flann/flann.hpp>
+#include <opencv2/legacy/legacy.hpp>
+// Note: These are purposely commented out to indicate non-use.
+// #include <opencv2/nonfree/nonfree.hpp>
+// #include <opencv2/nonfree/features2d.hpp>
+// Note: These are purposely commented out to indicate non-use.
+
+#include <vector>
+#include <iostream>
+
+static ossimTrace traceExec  ("ossimTieMeasurementGenerator:exec");
+static ossimTrace traceDebug ("ossimTieMeasurementGenerator:debug");
+
+
+//*****************************************************************************
+//  METHOD: ossimTieMeasurementGenerator::ossimTieMeasurementGenerator()
+//  
+//  Constructor.
+//*****************************************************************************
+ossimTieMeasurementGenerator::ossimTieMeasurementGenerator()
+   :
+   m_src(0),
+   m_igxA(0),
+   m_igxB(0),
+   m_imgA(),
+   m_imgB(),
+   m_numMeasurements(0),
+   m_maxMatches(5),
+   m_spIndexA(0),
+   m_spIndexB(1),
+   m_patchSizeA(),
+   m_patchSizeB(),
+   m_validBox(false),   
+   m_useGrid(false),
+   m_showCvWindow(false),
+   m_patchRefA(),
+   m_patchRefB(),
+   m_measA(),
+   m_measB(),
+   m_distEditFactor(0),
+   m_detectorName("ORB"),
+   m_detector(),
+   m_extractorName("FREAK"),
+   m_extractor(),
+   m_matcherName("BruteForce-Hamming"),
+   m_matcher(),
+   m_rep(0),
+   m_maxCvWindowDim(500),
+   m_cvWindowName("Correlation Patch")
+{
+   if (traceExec())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "\nDEBUG: ...ossimTieMeasurementGenerator::constructor" << std::endl;
+   }
+}
+
+
+//*****************************************************************************
+//  METHOD: ossimTieMeasurementGenerator::ossimTieMeasurementGenerator()
+//  
+//  Initializer.
+//*****************************************************************************
+bool ossimTieMeasurementGenerator::init(std::ostream& report)
+{
+   if (traceExec())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "DEBUG: ...ossimTieMeasurementGenerator::init" << std::endl;
+   }
+
+   m_initOK = true;
+   ossimString ts;
+   ossim::getFormattedTime("%a %m.%d.%y %H:%M:%S", false, ts);
+
+   m_rep = &report;
+
+
+   // Initial report output
+   *m_rep << "\nossimTieMeasurementGenerator Report     ";
+   *m_rep << ts;
+   *m_rep << "\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~";
+   *m_rep << std::endl;
+ 
+   // Set default grid size
+   setGridSize(ossimIpt(1,1));
+
+   try{
+   // Set default detector, extractor, matcher
+      setFeatureDetector(m_detectorName);
+      setDescriptorExtractor(m_extractorName);
+      setDescriptorMatcher(m_matcherName);
+
+   }
+   catch(...)
+   {
+      m_initOK = false;
+   }
+
+   return m_initOK;
+}
+
+
+//*****************************************************************************
+//  DESTRUCTOR: ~ossimTieMeasurementGenerator()
+//  
+//*****************************************************************************
+ossimTieMeasurementGenerator::~ossimTieMeasurementGenerator()
+{
+   if (traceExec())  ossimNotify(ossimNotifyLevel_DEBUG)
+      << "DEBUG: ~ossimTieMeasurementGenerator(): returning..." << std::endl;
+}
+
+
+//*****************************************************************************
+//  METHOD: ossimTieMeasurementGenerator::refreshCollectionTraits()
+//  
+//  Collection trait initializer.
+//*****************************************************************************
+bool ossimTieMeasurementGenerator::refreshCollectionTraits()
+{
+   bool initOK = true;
+
+   if (m_useGrid)
+   {
+      int gridRows = m_gridSize.y;
+      int gridCols = m_gridSize.x;
+      cv::Ptr<cv::FeatureDetector> detector = m_detector;
+      m_detector = new cv::GridAdaptedFeatureDetector(detector, m_maxMatches, gridRows, gridCols);
+   }
+
+   return initOK;
+}
+
+
+//*****************************************************************************
+//  METHOD: ossimTieMeasurementGenerator::run()
+//  
+//  
+//*****************************************************************************
+bool ossimTieMeasurementGenerator::run()
+{
+   bool runOK = true;
+
+   // Refresh collection traits before run
+   runOK = refreshCollectionTraits();
+
+   if (runOK)
+   {
+      // ossimIrect constructor center-based constructor
+      //    -> center view coordinates: m_patchRefA,m_patchRefB
+      ossimIrect rectA(m_patchRefA, m_patchSizeA.x, m_patchSizeA.y);
+      ossimIrect rectB(m_patchRefB, m_patchSizeB.x, m_patchSizeB.y);
+      
+      if (traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG)
+            << "DEBUG: ...ossimTieMeasurementGenerator::run" << std::endl;
+         ossimNotify(ossimNotifyLevel_DEBUG)<<" m_patchRefA: "<<m_patchRefA<<" size: "<<m_patchSizeA<<std::endl; 
+         ossimNotify(ossimNotifyLevel_DEBUG)<<" m_patchRefB: "<<m_patchRefB<<" size: "<<m_patchSizeB<<std::endl; 
+         ossimNotify(ossimNotifyLevel_DEBUG)<<" rectA = "<<rectA<<endl;
+         ossimNotify(ossimNotifyLevel_DEBUG)<<" rectB = "<<rectB<<endl;
+         ossimNotify(ossimNotifyLevel_DEBUG)<<" m_src A ossimScalarType = "<<m_src[m_spIndexA]->getOutputScalarType()<<endl;
+         ossimNotify(ossimNotifyLevel_DEBUG)<<" m_src B ossimScalarType = "<<m_src[m_spIndexB]->getOutputScalarType()<<endl;
+      }
+
+      // Get the patches
+      ossimRefPtr<ossimImageData> idA = m_src[m_spIndexA]->getTile(rectA);   
+      ossimRefPtr<ossimImageData> idB = m_src[m_spIndexB]->getTile(rectB);
+
+      // Create the OpenCV images
+      m_imgA.create(cv::Size(rectA.width(), rectA.height()), CV_8UC1);
+      m_imgB.create(cv::Size(rectB.width(), rectB.height()), CV_8UC1);
+
+      memcpy(m_imgA.ptr(), (void*) idA->getBuf(), rectA.area());
+      memcpy(m_imgB.ptr(), (void*) idB->getBuf(), rectB.area());
+
+      if(m_imgA.empty())
+      {
+         *m_rep << "cv::Mat A creation failed..."<<std::endl;;
+         runOK = false;
+      }
+      else if(m_imgB.empty())
+      {
+         *m_rep << "cv::Mat B creation failed..."<<std::endl;;
+         runOK = false;
+      }
+      else
+      {
+         // Detector
+         vector<cv::KeyPoint> keypointsA;
+         vector<cv::KeyPoint> keypointsB;
+         m_detector->detect(m_imgA, keypointsA);
+         m_detector->detect(m_imgB, keypointsB);
+         
+         // Extractor
+         //    32 byte uchar arrays   CV_8U (0) ..........
+         //    cout << desc.rows << " " << desc.cols << " " << desc.type() << std::endl;
+         //    uchar d = desc.at<uchar>(row,col);
+         cv::Mat descriptorsA;
+         cv::Mat descriptorsB;
+         m_extractor->compute(m_imgA, keypointsA, descriptorsA);
+         m_extractor->compute(m_imgB, keypointsB, descriptorsB);
+         
+         // Execute matcher
+         //  TODO add cross-check process here?
+         //----------
+         // BruteForceMatcher<L2<float> > descriptorMatcher;
+         // vector<DMatch> filteredMatches12, matches12, matches21;
+         // descriptorMatcher.match( descriptors1, descriptors2, matches12 );
+         // descriptorMatcher.match( descriptors2, descriptors1, matches21 );
+         // for( size_t i = 0; i < matches12.size(); i++ )
+         // {
+         //     DMatch forward = matches12[i];
+         //     DMatch backward = matches21[forward.trainIdx];
+         //     if( backward.trainIdx == forward.queryIdx )
+         //         filteredMatches12.push_back( forward );
+         // }
+         //----------
+         std::vector<cv::DMatch> matches;
+         std::vector<cv::DMatch> matchesAB;
+         m_matcher->match(descriptorsA, descriptorsB, matchesAB);
+         
+         matches = matchesAB;
+
+         // Symmetry
+         // void symmetryTest(const std::vector<cv::DMatch> &matches1,const std::vector<cv::DMatch> &matches2,std::vector<cv::DMatch>& symMatches)
+         // {
+         //     symMatches.clear();
+         //     for (vector<DMatch>::const_iterator matchIterator1= matches1.begin();matchIterator1!= matches1.end(); ++matchIterator1)
+         //     {
+         //         for (vector<DMatch>::const_iterator matchIterator2= matches2.begin();matchIterator2!= matches2.end();++matchIterator2)
+         //         {
+         //             if ((*matchIterator1).queryIdx ==(*matchIterator2).trainIdx &&(*matchIterator2).queryIdx ==(*matchIterator1).trainIdx)
+         //             {
+         //                 symMatches.push_back(DMatch((*matchIterator1).queryIdx,(*matchIterator1).trainIdx,(*matchIterator1).distance));
+         //                 break;
+         //             }
+         //         }
+         //     }
+         // }
+
+         *m_rep<<" Match resulted in "<<descriptorsA.rows<<" points..."<<std::endl;
+
+         //-- Calculate max and min distances between keypoints
+         double maxDist = 0;
+         double minDist = 500;
+         int maxRows = matches.size();
+         if(maxRows > descriptorsA.rows) maxRows = descriptorsA.rows;
+         for( int i = 0; i < maxRows; i++ )
+         {
+            double dist = matches[i].distance;
+            if( dist < minDist ) minDist = dist;
+            if( dist > maxDist ) maxDist = dist;
+         }
+
+         //-- Check for "good" matches (i.e. whose distance is less than 2*minDist )
+         //-- TODO -> radiusMatch can also be used here?
+         m_distEditFactor = 3; //TODO
+         std::vector<cv::DMatch> goodMatches;
+         for( int i = 0; i < maxRows; i++ )
+         {
+            if( matches[i].distance < m_distEditFactor*minDist )
+            {
+               goodMatches.push_back( matches[i]);
+            }
+         }
+         *m_rep<<" Distance filter ("<<std::setw(1)<<m_distEditFactor<<"X min) resulted in "<<goodMatches.size()<<" points..."<<std::endl;
+         *m_rep<<"  -- Max dist : "<<maxDist<<std::endl;
+         *m_rep<<"  -- Min dist : "<<minDist<<std::endl;
+      
+         if (m_maxMatches<(int)goodMatches.size())
+         {
+            nth_element(goodMatches.begin(),goodMatches.begin()+m_maxMatches,goodMatches.end());
+            goodMatches.erase(goodMatches.begin()+m_maxMatches,goodMatches.end());
+         }
+         
+         // Load measurements
+         *m_rep<<"\n Selected top "<<goodMatches.size()<<"..."<<std::endl;
+         *m_rep<<"   n queryIdx trainIdx imgIdx distance            A            B"<<std::endl;
+         *m_rep<<"---- -------- -------- ------ -------- ------------ ------------"<<std::endl;
+         
+         for( ossim_uint32 i = 0; i < goodMatches.size(); ++i )
+         {
+            double xA = keypointsA[goodMatches[i].queryIdx].pt.x;
+            double yA = keypointsA[goodMatches[i].queryIdx].pt.y;
+            double xB = keypointsB[goodMatches[i].trainIdx].pt.x;
+            double yB = keypointsB[goodMatches[i].trainIdx].pt.y;
+
+            *m_rep<<std::setw(4)<<i+1<<" "
+               <<std::setw(8)<<goodMatches[i].queryIdx<<" "
+               <<std::setw(8)<<goodMatches[i].trainIdx<<" "
+               <<std::setw(6)<<goodMatches[i].imgIdx<<" "
+               <<std::fixed<<std::setprecision(1)<<std::setw(8)
+               <<goodMatches[i].distance<<" ("
+               <<std::fixed<<std::setprecision(0)
+               <<std::setw(4)<<xA << ", " 
+               <<std::setw(4)<<yA <<") ("
+               <<std::setw(4)<<xB << ", " 
+               <<std::setw(4)<<yB <<") "
+               <<std::endl;
+         
+            // View coordinates
+            ossimDpt vptA(xA, yA);
+            ossimDpt vptB(xB, yB);
+            vptA += m_patchRefA - m_patchSizeA/2;
+            vptB += m_patchRefB - m_patchSizeB/2;
+
+            // Image coordinates
+            ossimDpt iptA;
+            ossimDpt iptB;
+            m_igxA->viewToImage(vptA, iptA);
+            m_igxB->viewToImage(vptB, iptB);
+
+            m_measA.push_back(iptA);
+            m_measB.push_back(iptB);
+            ++m_numMeasurements;
+         }
+         
+
+         // Pop up the results window
+         if (m_showCvWindow)
+         {
+            showCvResultsWindow(keypointsA, keypointsB, goodMatches);
+         }
+      }
+
+   }
+   else
+   {
+      *m_rep << "An error occurred in collection trait initialization..."<<std::endl;
+      *m_rep << "Measurement collection could not be executed."<<std::endl;
+   }
+
+   summarizeRun();
+
+   return runOK;
+}
+
+
+//*****************************************************************************
+//  METHOD: ossimTieMeasurementGenerator::setFeatureDetector()
+//   Set the feature detector
+//  
+// The following detector types are supported:
+//     "FAST" – FastFeatureDetector
+//     "STAR" – StarFeatureDetector
+//     "SIFT" – SIFT (nonfree module)
+//     "SURF" – SURF (nonfree module)
+//     "ORB" – ORB
+//     "BRISK" – BRISK
+//     "MSER" – MSER
+//     "GFTT" – GoodFeaturesToTrackDetector
+//     "HARRIS" – GoodFeaturesToTrackDetector with Harris detector enabled
+//     "Dense" – DenseFeatureDetector
+//     "SimpleBlob" – SimpleBlobDetector
+// Also a combined format is supported: feature detector adapter name
+// ( "Grid" – GridAdaptedFeatureDetector, "Pyramid" – PyramidAdaptedFeatureDetector )
+//+ feature detector name (see above), for example: "GridFAST", "PyramidSTAR".
+//*****************************************************************************
+bool ossimTieMeasurementGenerator::setFeatureDetector(const ossimString& name)
+{
+   bool createOK = false;
+   m_detectorName = name;
+   m_detector  = cv::FeatureDetector::create(m_detectorName);
+
+   if( m_detector != 0 )
+   {
+      createOK = true;
+      std::vector<std::string> parameters;
+      m_detector->getParams(parameters);
+      if (traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG)
+            << "DEBUG: ...detector..." << std::endl;
+         for (int i = 0; i < (int) parameters.size(); i++)
+            ossimNotify(ossimNotifyLevel_DEBUG)<<"  "<<parameters[i]<<std::endl;
+      }
+   }
+
+   return createOK;
+}
+
+//*****************************************************************************
+//  METHOD: ossimTieMeasurementGenerator::setDescriptorExtractor()
+//   Set the descriptor-extractor
+//  
+// The current implementation supports the following types of a descriptor extractor:
+// Not Used "SIFT" – SIFT (nonfree module)
+// Not Used "SURF" – SURF (nonfree module)
+//          "ORB" – ORB
+//          "BRISK" – BRISK
+//          "BRIEF" – BriefDescriptorExtractor
+// A combined format is also supported: descriptor extractor adapter name
+//( "Opponent" – OpponentColorDescriptorExtractor ) + descriptor extractor name
+//(see above), for example: "OpponentSIFT" .
+//
+// cv::Algorithm::set, cv::Algorithm::getParams
+//featureDetector->set("someParam", someValue)
+//*****************************************************************************
+bool ossimTieMeasurementGenerator::setDescriptorExtractor(const ossimString& name)
+{
+   bool createOK = false;
+   m_extractorName = name;
+   m_extractor = cv::DescriptorExtractor::create(m_extractorName);
+
+   if( m_extractor != 0 )
+   {
+      createOK = true;
+      std::vector<std::string> parameters;
+      m_extractor->getParams(parameters);
+      if (traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG)
+            << "DEBUG: ...extractor..." << std::endl;
+         for (int i = 0; i < (int) parameters.size(); i++)
+            ossimNotify(ossimNotifyLevel_DEBUG)<<"  "<<parameters[i]<<std::endl;
+      }
+   }
+
+   return createOK;
+}
+
+//*****************************************************************************
+//  METHOD: ossimTieMeasurementGenerator::getDescriptorMatcher()
+//   Set the descriptor-matcher
+//  
+// Descriptor matcher type. Now the following matcher types are supported:
+//     BruteForce-Hamming
+//     BruteForce-HammingLUT
+//     FlannBased
+//
+//  The current decriptor-matcher compatibility table (updated for this note) is the following:
+//                 BruteForce BruteForce-L1 FlannBased BruteForce-Hamming BruteForce-HammingLUT
+//  Not Used SURF  YES        YES           YES        NO                 NO
+//  Not Used SIFT  YES        YES           YES        NO                 NO
+//           ORB   NO         NO            YES(Lsh)   YES                YES
+//           BRIEF NO         NO            YES(Lsh)   YES                YES
+//           FREAK NO         NO            YES(Lsh)   YES                YES
+// The ORB and BRIEF descriptors and BruteForce-Hamming and BruteForce-HammingLUT
+// matching schemes generate or accept binary-string descriptors (CV_8U), while
+// the other descriptors and matching schemes generate or accept vectors of floating
+// point values (CV_32F). It is possible to mix and match the descriptors more by
+// converting the data format of the descriptor matrix prior to matching, but this can
+// sometimes lead to very poor matching results, so attempt it with caution.
+//*****************************************************************************
+bool ossimTieMeasurementGenerator::setDescriptorMatcher(const ossimString& name)
+{
+   bool createOK = false;
+   m_matcherName = name;
+
+   if (m_matcherName == "FlannBased")
+   {
+      // Set LshIndexParams(int table_number, int key_size, int multi_probe_level)
+      m_matcher = new cv::FlannBasedMatcher(new cv::flann::LshIndexParams(20,10,2));
+   }
+   else
+   {
+      m_matcher = cv::DescriptorMatcher::create(m_matcherName);
+   }
+
+   if( m_matcher != 0 )
+   {
+      createOK = true;
+      std::vector<std::string> parameters;
+      m_matcher->getParams(parameters);
+      if (traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG)
+            << "DEBUG: ...matcher..." << std::endl;
+         for (int i = 0; i < (int) parameters.size(); i++)
+            ossimNotify(ossimNotifyLevel_DEBUG)<<"  "<<parameters[i]<<std::endl;
+      }
+   }
+
+   // TODO: Garrett: this was causing core dumps so I commented it out.  Also, it appears that in the docs 
+   //          the default for crossCheck argument in the base constructor is false.
+      // Set crossCheck
+      //m_matcher->set("crossCheck", false);
+
+
+   return createOK;
+}
+
+
+//*****************************************************************************
+//  METHOD: ossimTieMeasurementGenerator::setGridSize()
+//  
+//*****************************************************************************
+bool ossimTieMeasurementGenerator::setGridSize(const ossimIpt& gridDimensions)
+{
+   bool setOK = false;
+
+   if (gridDimensions.x>0 && gridDimensions.y>0)
+   {
+      m_gridSize = gridDimensions;
+      setOK = true;
+   }
+
+   return setOK;
+}
+
+
+//*****************************************************************************
+//  METHOD: ossimTieMeasurementGenerator::setBox()
+//
+//  Delineate the bounding collection boxes
+//*****************************************************************************
+bool ossimTieMeasurementGenerator::setBox(std::vector<ossimIrect> roi,
+                                          const ossim_uint32& index,
+                                          std::vector<ossimImageSource*> src)
+{
+
+   m_validBox = false;
+
+   // Load the image source pointers
+   //    Note: The source pointer vector may contain more than
+   //          two images, but only the first two are used
+   //          in the auto measurement process.
+   m_src.clear();
+   for (ossim_uint32 n=0; n<src.size(); ++n)
+      m_src.push_back(src[n]);
+
+
+   // Set the patch indices
+   if (index<2)
+   {
+      m_spIndexA = index;
+      if (m_spIndexA == 0)
+         m_spIndexB = 1;
+      else
+         m_spIndexB = 0;
+
+      // Save reference points (patch centers)
+      roi[m_spIndexA].getCenter(m_patchRefA);
+      roi[m_spIndexB].getCenter(m_patchRefB);
+
+      // Save dimensions (patch sizes)
+      m_patchSizeA.x = roi[m_spIndexA].width();
+      m_patchSizeA.y = roi[m_spIndexA].height();
+      m_patchSizeB.x = roi[m_spIndexB].width();
+      m_patchSizeB.y = roi[m_spIndexB].height();
+
+      // Set the IvtGeometryXforms
+      ossimIvtGeomXformVisitor visitorA;
+      m_src[m_spIndexA]->accept(visitorA);
+      if (visitorA.getTransformList().size() == 1)
+      {
+         m_igxA = visitorA.getTransformList()[0].get();
+      }
+      ossimIvtGeomXformVisitor visitorB;
+      m_src[m_spIndexB]->accept(visitorB);
+      if (visitorB.getTransformList().size() == 1)
+      {
+         m_igxB = visitorB.getTransformList()[0].get();
+      }
+
+      m_validBox = true;
+
+      if (traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG)
+            << "DEBUG: ...ossimTieMeasurementGenerator::setBox" << std::endl;
+         ossimNotify(ossimNotifyLevel_DEBUG)<<" m_spIndexA  = "<<m_spIndexA<<std::endl;
+         ossimNotify(ossimNotifyLevel_DEBUG)<<" m_spIndexB  = "<<m_spIndexB<<std::endl;
+         ossimNotify(ossimNotifyLevel_DEBUG)<<" m_patchRefA = "<<m_patchRefA<<std::endl;
+         ossimNotify(ossimNotifyLevel_DEBUG)<<" m_patchRefB = "<<m_patchRefB<<std::endl;
+         ossimNotify(ossimNotifyLevel_DEBUG)<<" m_patchSizeA = "<<m_patchSizeA<<std::endl;
+         ossimNotify(ossimNotifyLevel_DEBUG)<<" m_patchSizeB = "<<m_patchSizeB<<std::endl;
+      }
+   }
+
+   return m_validBox;
+}
+
+
+//*****************************************************************************
+//  METHOD: ossimTieMeasurementGenerator::setMaxMatches()
+//  
+//*****************************************************************************
+bool ossimTieMeasurementGenerator::setMaxMatches(const int& maxMatches)
+{
+   bool setOK = false;
+
+   if (maxMatches > 0)
+   {
+      m_maxMatches = maxMatches;
+      setOK = true;
+   }
+
+   return setOK;
+}
+
+
+//*****************************************************************************
+//  METHOD: ossimTieMeasurementGenerator::pointIndexedAt()
+//  
+//*****************************************************************************
+ossimDpt ossimTieMeasurementGenerator::pointIndexedAt
+   (const ossim_uint32 imgIdx, const ossim_uint32 measIdx)
+{
+   if ((int)measIdx<m_numMeasurements && imgIdx<2)
+   {
+      if (imgIdx == 0)
+      {
+         if (m_spIndexA == 0)
+            return m_measA[measIdx];
+         else
+            return m_measB[measIdx];
+      }
+      else
+      {
+         if (m_spIndexA == 1)
+            return m_measA[measIdx];
+         else
+            return m_measB[measIdx];
+      }
+   }
+   else
+   {
+      ossimDpt bad;
+      bad.makeNan();
+      return bad;
+   }
+}
+
+
+//*****************************************************************************
+//  METHOD: ossimTieMeasurementGenerator::summarizeRun()
+//  
+//*****************************************************************************
+void ossimTieMeasurementGenerator::summarizeRun() const
+{
+   *m_rep<<"\n Configuration..."<<std::endl;
+   *m_rep<<"  Detector:   "<<getFeatureDetector()<<std::endl;
+   *m_rep<<"  Descriptor: "<<getDescriptorExtractor()<<std::endl;
+   *m_rep<<"  Matcher:    "<<getDescriptorMatcher()<<std::endl;
+   *m_rep<<"  Patch size: "<<m_patchSizeA<<std::endl;
+   *m_rep<<"  Grid size:  "<<m_gridSize<<std::endl;
+
+   ossimString ts;
+   ossim::getFormattedTime("%a %m.%d.%y %H:%M:%S", false, ts);
+   *m_rep << "\n";
+   *m_rep << "\n" << ts;
+   *m_rep << "\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~";
+   *m_rep << std::endl;
+}
+
+
+//*****************************************************************************
+//  METHOD: ossimTieMeasurementGenerator::showCvResultsWindow()
+//  
+//*****************************************************************************
+void ossimTieMeasurementGenerator::showCvResultsWindow(
+   std::vector<cv::KeyPoint> keypointsA,
+   std::vector<cv::KeyPoint> keypointsB,
+   std::vector<cv::DMatch> goodMatches) 
+{
+   //-- Draw only "good" matches
+   // DEFAULT
+   // DRAW_OVER_OUTIMG
+   // NOT_DRAW_SINGLE_POINTS
+   // DRAW_RICH_KEYPOINTS
+   cv::namedWindow(m_cvWindowName);
+   cv::Mat imgMatch;
+   cv::drawMatches(m_imgA, keypointsA, m_imgB, keypointsB, goodMatches, imgMatch,
+       cv::Scalar::all(-1), cv::Scalar::all(-1), vector<char>(), cv::DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS);      
+
+   // Scale down the results window if necessary using a somewhat arbitrary factor for now
+   double rRatio = m_maxCvWindowDim / std::max(m_patchSizeA.y, m_patchSizeB.y);
+   double cRatio = m_maxCvWindowDim / std::max(m_patchSizeA.x, m_patchSizeB.x);
+   double sFac = 1.0;
+   if (rRatio <= cRatio)
+   {
+      if (rRatio < 1.0)
+         sFac = rRatio;
+   }
+   else
+   {
+      if (cRatio< 1.0)
+         sFac = cRatio;
+   }
+   cv::Mat imgMatchOut;
+   cv::resize(imgMatch, imgMatchOut, cv::Size(), sFac, sFac, cv::INTER_AREA);
+   cv::imshow(m_cvWindowName, imgMatchOut);
+}
+
+
+//*****************************************************************************
+//  METHOD: ossimTieMeasurementGenerator::closeCvWindow()
+//  
+//*****************************************************************************
+void ossimTieMeasurementGenerator::closeCvWindow(const bool waitKeyPress) 
+{
+   if (waitKeyPress)
+   {
+      cv::waitKey();
+   }
+
+   cv::destroyWindow(m_cvWindowName);
+}
diff --git a/ossim_plugins/opencv/ossimTieMeasurementGenerator.h b/ossim_plugins/opencv/ossimTieMeasurementGenerator.h
new file mode 100644
index 0000000..c5b8541
--- /dev/null
+++ b/ossim_plugins/opencv/ossimTieMeasurementGenerator.h
@@ -0,0 +1,149 @@
+//----------------------------------------------------------------------------
+//
+// License:  See top level LICENSE.txt file.
+//
+// Author:  David Hicks
+//
+//
+// Description: Automatic tie measurement extraction.
+//----------------------------------------------------------------------------
+#ifndef ossimTieMeasurementGenerator_HEADER
+#define ossimTieMeasurementGenerator_HEADER 1
+
+#include <ossim/base/ossimObject.h>
+#include <ossim/base/ossimDpt.h>
+#include <ossim/base/ossimString.h>
+#include <ossim/base/ossimTieMeasurementGeneratorInterface.h>
+#include "ossimIvtGeomXform.h"
+
+#include <opencv/cv.h>
+
+#include <ctime>
+#include <vector>
+#include <iostream>
+
+typedef std::vector<ossimDpt> DptVec_t;
+
+class ossimImageSource;
+
+
+class OSSIM_DLL ossimTieMeasurementGenerator : 
+   public ossimTieMeasurementGeneratorInterface, public ossimObject
+{
+public:
+
+   // Constructor/initializer
+   ossimTieMeasurementGenerator();
+   bool init(std::ostream& report = cout);
+
+   // Define collection ROI
+   bool setBox(std::vector<ossimIrect> roi,
+               const ossim_uint32& index,
+               std::vector<ossimImageSource*> src);
+   bool isValidCollectionBox() const {return m_validBox;}   
+
+   // Measurement collection
+   bool run();
+
+   // Report run parameters
+   void summarizeRun() const;
+
+   // Destructor
+   ~ossimTieMeasurementGenerator();
+
+   // Patch grid configuration accessors
+   void setUseGrid(const bool useGrid) {m_useGrid = useGrid;}
+   bool getUseGrid() const {return m_useGrid;}
+   bool setGridSize(const ossimIpt& gridDimensions);
+   ossimIpt getGridSize() const {return m_gridSize;}
+
+   // Max matches in patch accessors
+   bool setMaxMatches(const int& maxMatches);
+   int getMaxMatches() const {return m_maxMatches;}
+
+   // Set the feature detector
+   bool setFeatureDetector(const ossimString& name);
+   ossimString getFeatureDetector() const {return m_detectorName;}
+
+   // Set the descriptor-extractor
+   bool setDescriptorExtractor(const ossimString& name);
+   ossimString getDescriptorExtractor() const {return m_extractorName;}
+
+   // Set the matcher
+   bool setDescriptorMatcher(const ossimString& name);
+   ossimString getDescriptorMatcher() const {return m_matcherName;}
+
+   // Measured point accessors
+   int numMeasurements() const { return m_numMeasurements; }
+   ossimDpt pointIndexedAt(const ossim_uint32 imgIdx, const ossim_uint32 measIdx);
+
+   // OpenCV drawMatches window
+   void closeCvWindow(const bool waitKeyPress = false);
+   void setShowCvWindow(const bool showCvWindow) {m_showCvWindow = showCvWindow;}
+   bool getShowCvWindow() const {return m_showCvWindow;}
+
+protected:
+
+   bool m_initOK;
+
+   // Initialize patch reference positions
+   bool refreshCollectionTraits();
+
+   // Image-related members
+   std::vector<ossimImageSource*> m_src;
+   ossimRefPtr<ossimIvtGeomXform> m_igxA;
+   ossimRefPtr<ossimIvtGeomXform> m_igxB;
+   cv::Mat m_imgA;
+   cv::Mat m_imgB;
+
+   // Measurement count parameters
+   int m_numMeasurements;
+   int m_maxMatches;
+
+   // Patch traits
+   ossim_uint32 m_spIndexA;
+   ossim_uint32 m_spIndexB;
+   ossimIpt m_patchSizeA;
+   ossimIpt m_patchSizeB;
+   bool m_validBox;
+
+   // Grid size for matcher
+   bool m_useGrid;
+   ossimIpt m_gridSize;
+
+   // Patch reference point (center)
+   ossimDpt m_patchRefA;
+   ossimDpt m_patchRefB;
+
+   // Measurement containers
+   DptVec_t m_measA;
+   DptVec_t m_measB;
+
+   // Editing parameters
+   int m_distEditFactor;
+
+   // Pointer to detector
+   ossimString m_detectorName;
+   cv::Ptr<cv::FeatureDetector> m_detector;
+
+   // Pointer to descriptor extractor
+   ossimString m_extractorName;
+   cv::Ptr<cv::DescriptorExtractor> m_extractor;
+
+   // Pointer to matcher
+   ossimString m_matcherName;
+   cv::Ptr<cv::DescriptorMatcher> m_matcher;
+
+   // Measurement run report
+   std::ostream* m_rep;
+
+   // Results window
+   void showCvResultsWindow(
+      std::vector<cv::KeyPoint> keypointsA,
+      std::vector<cv::KeyPoint> keypointsB,
+      std::vector<cv::DMatch> goodMatches);
+   double m_maxCvWindowDim;
+   ossimString m_cvWindowName;
+   bool m_showCvWindow;
+};
+#endif // #ifndef ossimTieMeasurementGenerator_HEADER
diff --git a/ossim_plugins/openjpeg/CMakeLists.txt b/ossim_plugins/openjpeg/CMakeLists.txt
new file mode 100644
index 0000000..7dea61a
--- /dev/null
+++ b/ossim_plugins/openjpeg/CMakeLists.txt
@@ -0,0 +1,70 @@
+set(LIB_NAME ossimopenjpeg_plugin)
+
+message( "************** LIBRARY SETUP FOR ossimopenjpeg_plugin******************")
+
+# Include ossim cmake stuff:
+include(OssimVersion)
+include(OssimCommonVariables)
+include(OssimUtilities)
+
+set(requiredLibs)
+
+# OSSIM - Required: 
+find_package(ossim)
+if(OSSIM_FOUND)
+   include_directories( ${OSSIM_INCLUDE_DIR} )
+   set( requiredLibs ${requiredLibs} ${OSSIM_LIBRARIES} )
+else(OSSIM_FOUND)
+   message(FATAL_ERROR "Could not find ossim")
+endif(OSSIM_FOUND)
+
+# OpenJPEG required:
+find_package(OpenJPEG)
+if(OPENJPEG_FOUND)
+   include_directories( ${OPENJPEG_INCLUDE_DIR} )
+   SET(requiredLibs ${requiredLibs} ${OPENJPEG_LIBRARIES} )
+else(OPENJPEG_FOUND)
+   message(FATAL_ERROR "Could not find OpenJPEG")
+endif(OPENJPEG_FOUND)
+
+# Little CMS2 required:
+find_package(LCMS2)
+if(LCMS2_FOUND)
+   include_directories( ${LCMS2_INCLUDE_DIR} )
+   SET(requiredLibs ${requiredLibs} ${LCMS2_LIBRARIES} )
+   add_definitions("-DOPJ_HAVE_LIBLCMS2")
+   add_definitions("-DCMS_DLL")
+else(LCMS2_FOUND)
+   message(FATAL_ERROR "Could not find LCMS2")
+endif(LCMS2_FOUND)
+
+include_directories(${CMAKE_CURRENT_SOURCE_DIR})
+
+file(GLOB OSSIMPLUGIN_SRCS *.cpp)
+file(GLOB OSSIMPLUGIN_HEADERS *.h)
+
+message( STATUS "OPENJPEG_INCLUDE_DIR = ${OPENJPEG_INCLUDE_DIR}")
+message( STATUS "OPENJPEG_LIBRARIES   = ${OPENJPEG_LIBRARIES}")
+message( STATUS "LCMS2_INCLUDE_DIR = ${LCMS2_INCLUDE_DIR}")
+message( STATUS "LCMS2_LIBRARIES   = ${LCMS2_LIBRARIES}")
+message( STATUS "OPENJPEG plugin required libs = ${requiredLibs}")
+
+#---
+# OSSIMPLUGINSMAKINGDLL controls dll linkage on windows.  
+# Adding this sets OSSIM_PLUGINS_DLL #define TO "__declspec(dllexport)".
+#---
+add_definitions("-DOSSIMPLUGINSMAKINGDLL")
+
+# Adjust the install library path:
+if(OSSIM_INSTALL_PLUGINS_WITH_VERSION)
+   set(INSTALL_LIBRARY_DIR   "${INSTALL_LIBRARY_DIR}/ossim-${OSSIM_VERSION}/plugins")
+else(OSSIM_INSTALL_PLUGINS_WITH_VERSION)
+   set(INSTALL_LIBRARY_DIR   "${INSTALL_LIBRARY_DIR}/ossim/plugins")
+endif(OSSIM_INSTALL_PLUGINS_WITH_VERSION)
+
+OSSIM_LINK_LIBRARY(${LIB_NAME}
+                   COMPONENT_NAME ossim TYPE "${OSSIM_PLUGIN_LINK_TYPE}"
+		   LIBRARIES ${OSSIM_LIBRARY} ${requiredLibs}
+                   HEADERS "${OSSIMPLUGIN_HEADERS}"
+		   SOURCE_FILES "${OSSIMPLUGIN_SRCS}"
+                   INSTALL_LIB)
diff --git a/ossim_plugins/openjpeg/ossimOpjColor.cpp b/ossim_plugins/openjpeg/ossimOpjColor.cpp
new file mode 100644
index 0000000..e39e5c8
--- /dev/null
+++ b/ossim_plugins/openjpeg/ossimOpjColor.cpp
@@ -0,0 +1,544 @@
+/*
+ * The copyright in this software is being made available under the 2-clauses 
+ * BSD License, included below. This software may be subject to other third 
+ * party and contributor rights, including patent rights, and no such rights
+ * are granted under this license.
+ *
+ * Copyright (c) 2002-2014, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2014, Professor Benoit Macq
+ * Copyright (c) 2001-2003, David Janssens
+ * Copyright (c) 2002-2003, Yannick Verschueren
+ * Copyright (c) 2003-2007, Francois-Olivier Devaux 
+ * Copyright (c) 2003-2014, Antonin Descampe
+ * Copyright (c) 2005, Herve Drolon, FreeImage Team
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  24 March 2015 - D. Burken
+ *  Code from openjpeg/src/bin/color.h namespaced for ossim library.
+ */
+
+#include <ossimOpjColor.h>
+
+#include <openjpeg.h>
+
+#include <cstdio>
+#include <cstring>
+#include <cstdlib>
+#include <cmath>
+#include <cassert>
+
+#ifdef OPJ_HAVE_LIBLCMS2
+#include <lcms2.h>
+#endif
+#ifdef OPJ_HAVE_LIBLCMS1
+#include <lcms.h>
+#endif
+
+#ifdef OPJ_USE_LEGACY
+#define OPJ_CLRSPC_GRAY CLRSPC_GRAY
+#define OPJ_CLRSPC_SRGB CLRSPC_SRGB
+#endif
+
+/*--------------------------------------------------------
+Matrix for sYCC, Amendment 1 to IEC 61966-2-1
+
+Y :   0.299   0.587    0.114   :R
+Cb:  -0.1687 -0.3312   0.5     :G
+Cr:   0.5    -0.4187  -0.0812  :B
+
+Inverse:
+
+R: 1        -3.68213e-05    1.40199      :Y
+G: 1.00003  -0.344125      -0.714128     :Cb - 2^(prec - 1)
+B: 0.999823  1.77204       -8.04142e-06  :Cr - 2^(prec - 1)
+
+-----------------------------------------------------------*/
+static void sycc_to_rgb(int offset, int upb, int y, int cb, int cr,
+                        int *out_r, int *out_g, int *out_b)
+{
+   int r, g, b;
+
+   cb -= offset; cr -= offset;
+   r = y + (int)(1.402 * (float)cr);
+   if(r < 0) r = 0; else if(r > upb) r = upb; *out_r = r;
+
+   g = y - (int)(0.344 * (float)cb + 0.714 * (float)cr);
+   if(g < 0) g = 0; else if(g > upb) g = upb; *out_g = g;
+
+   b = y + (int)(1.772 * (float)cb);
+   if(b < 0) b = 0; else if(b > upb) b = upb; *out_b = b;
+}
+
+static void sycc444_to_rgb(opj_image_t *img)
+{
+   int *d0, *d1, *d2, *r, *g, *b;
+   const int *y, *cb, *cr;
+   int maxw, maxh, max, i, offset, upb;
+
+   i = (int)img->comps[0].prec;
+   offset = 1<<(i - 1); upb = (1<<i)-1;
+
+   maxw = (int)img->comps[0].w; maxh = (int)img->comps[0].h;
+   max = maxw * maxh;
+
+   y = img->comps[0].data;
+   cb = img->comps[1].data;
+   cr = img->comps[2].data;
+
+   d0 = r = (int*)malloc(sizeof(int) * (size_t)max);
+   d1 = g = (int*)malloc(sizeof(int) * (size_t)max);
+   d2 = b = (int*)malloc(sizeof(int) * (size_t)max);
+
+   for(i = 0; i < max; ++i)
+   {
+      sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b);	
+
+      ++y; ++cb; ++cr; ++r; ++g; ++b;
+   }	
+   free(img->comps[0].data); img->comps[0].data = d0;
+   free(img->comps[1].data); img->comps[1].data = d1;
+   free(img->comps[2].data); img->comps[2].data = d2;
+
+}/* sycc444_to_rgb() */
+
+static void sycc422_to_rgb(opj_image_t *img)
+{	
+   int *d0, *d1, *d2, *r, *g, *b;
+   const int *y, *cb, *cr;
+   int maxw, maxh, max, offset, upb;
+   int i, j;
+
+   i = (int)img->comps[0].prec;
+   offset = 1<<(i - 1); upb = (1<<i)-1;
+
+   maxw = (int)img->comps[0].w; maxh = (int)img->comps[0].h;
+   max = maxw * maxh;
+
+   y = img->comps[0].data;
+   cb = img->comps[1].data;
+   cr = img->comps[2].data;
+
+   d0 = r = (int*)malloc(sizeof(int) * (size_t)max);
+   d1 = g = (int*)malloc(sizeof(int) * (size_t)max);
+   d2 = b = (int*)malloc(sizeof(int) * (size_t)max);
+
+   for(i=0; i < maxh; ++i)
+   {
+      for(j=0; j < maxw; j += 2)
+      {
+         sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b);
+
+         ++y; ++r; ++g; ++b;
+
+         sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b);
+
+         ++y; ++r; ++g; ++b; ++cb; ++cr;
+      }
+   }
+   free(img->comps[0].data); img->comps[0].data = d0;
+   free(img->comps[1].data); img->comps[1].data = d1;
+   free(img->comps[2].data); img->comps[2].data = d2;
+
+#if defined(USE_JPWL) || defined(USE_MJ2)
+   img->comps[1].w = maxw; img->comps[1].h = maxh;
+   img->comps[2].w = maxw; img->comps[2].h = maxh;
+#else
+   img->comps[1].w = (OPJ_UINT32)maxw; img->comps[1].h = (OPJ_UINT32)maxh;
+   img->comps[2].w = (OPJ_UINT32)maxw; img->comps[2].h = (OPJ_UINT32)maxh;
+#endif
+   img->comps[1].dx = img->comps[0].dx;
+   img->comps[2].dx = img->comps[0].dx;
+   img->comps[1].dy = img->comps[0].dy;
+   img->comps[2].dy = img->comps[0].dy;
+
+}/* sycc422_to_rgb() */
+
+static void sycc420_to_rgb(opj_image_t *img)
+{
+   int *d0, *d1, *d2, *r, *g, *b, *nr, *ng, *nb;
+   const int *y, *cb, *cr, *ny;
+   int maxw, maxh, max, offset, upb;
+   int i, j;
+
+   i = (int)img->comps[0].prec;
+   offset = 1<<(i - 1); upb = (1<<i)-1;
+
+   maxw = (int)img->comps[0].w; maxh = (int)img->comps[0].h;
+   max = maxw * maxh;
+
+   y = img->comps[0].data;
+   cb = img->comps[1].data;
+   cr = img->comps[2].data;
+
+   d0 = r = (int*)malloc(sizeof(int) * (size_t)max);
+   d1 = g = (int*)malloc(sizeof(int) * (size_t)max);
+   d2 = b = (int*)malloc(sizeof(int) * (size_t)max);
+
+   for(i=0; i < maxh; i += 2)
+   {
+      ny = y + maxw;
+      nr = r + maxw; ng = g + maxw; nb = b + maxw;
+
+      for(j=0; j < maxw;  j += 2)
+      {
+         sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b);
+
+         ++y; ++r; ++g; ++b;
+
+         sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b);
+
+         ++y; ++r; ++g; ++b;
+
+         sycc_to_rgb(offset, upb, *ny, *cb, *cr, nr, ng, nb);
+
+         ++ny; ++nr; ++ng; ++nb;
+
+         sycc_to_rgb(offset, upb, *ny, *cb, *cr, nr, ng, nb);
+
+         ++ny; ++nr; ++ng; ++nb; ++cb; ++cr;
+      }
+      y += maxw; r += maxw; g += maxw; b += maxw;
+   }
+   free(img->comps[0].data); img->comps[0].data = d0;
+   free(img->comps[1].data); img->comps[1].data = d1;
+   free(img->comps[2].data); img->comps[2].data = d2;
+
+#if defined(USE_JPWL) || defined(USE_MJ2)
+   img->comps[1].w = maxw; img->comps[1].h = maxh;
+   img->comps[2].w = maxw; img->comps[2].h = maxh;
+#else
+   img->comps[1].w = (OPJ_UINT32)maxw; img->comps[1].h = (OPJ_UINT32)maxh;
+   img->comps[2].w = (OPJ_UINT32)maxw; img->comps[2].h = (OPJ_UINT32)maxh;
+#endif
+   img->comps[1].dx = img->comps[0].dx;
+   img->comps[2].dx = img->comps[0].dx;
+   img->comps[1].dy = img->comps[0].dy;
+   img->comps[2].dy = img->comps[0].dy;
+
+}/* sycc420_to_rgb() */
+
+void ossim::color_sycc_to_rgb(opj_image *img)
+{
+   if(img->numcomps < 3) 
+   {
+      img->color_space = OPJ_CLRSPC_GRAY;
+      return;
+   }
+
+   if((img->comps[0].dx == 1)
+      && (img->comps[1].dx == 2)
+      && (img->comps[2].dx == 2)
+      && (img->comps[0].dy == 1)
+      && (img->comps[1].dy == 2)
+      && (img->comps[2].dy == 2))/* horizontal and vertical sub-sample */
+   {
+      sycc420_to_rgb(img);
+   }
+   else
+      if((img->comps[0].dx == 1)
+         && (img->comps[1].dx == 2)
+         && (img->comps[2].dx == 2)
+         && (img->comps[0].dy == 1)
+         && (img->comps[1].dy == 1)
+         && (img->comps[2].dy == 1))/* horizontal sub-sample only */
+      {
+         sycc422_to_rgb(img);
+      }
+      else
+         if((img->comps[0].dx == 1)
+            && (img->comps[1].dx == 1)
+            && (img->comps[2].dx == 1)
+            && (img->comps[0].dy == 1)
+            && (img->comps[1].dy == 1)
+            && (img->comps[2].dy == 1))/* no sub-sample */
+         {
+            sycc444_to_rgb(img);
+         }
+         else
+         {
+            fprintf(stderr,"%s:%d:color_sycc_to_rgb\n\tCAN NOT CONVERT\n",
+                    __FILE__,__LINE__);
+            return;
+         }
+   img->color_space = OPJ_CLRSPC_SRGB;
+
+}/* color_sycc_to_rgb() */
+
+#if defined(OPJ_HAVE_LIBLCMS2) || defined(OPJ_HAVE_LIBLCMS1)
+#ifdef OPJ_HAVE_LIBLCMS1
+/* Bob Friesenhahn proposed:*/
+#define cmsSigXYZData   icSigXYZData
+#define cmsSigLabData   icSigLabData
+#define cmsSigCmykData  icSigCmykData
+#define cmsSigYCbCrData icSigYCbCrData
+#define cmsSigLuvData   icSigLuvData
+#define cmsSigGrayData  icSigGrayData
+#define cmsSigRgbData   icSigRgbData
+#define cmsUInt32Number DWORD
+
+#define cmsColorSpaceSignature icColorSpaceSignature
+#define cmsGetHeaderRenderingIntent cmsTakeRenderingIntent
+
+#endif /* OPJ_HAVE_LIBLCMS1 */
+
+/*#define DEBUG_PROFILE*/
+void ossim::color_apply_icc_profile(opj_image *image)
+{
+   cmsHPROFILE in_prof, out_prof;
+   cmsHTRANSFORM transform;
+   cmsColorSpaceSignature in_space, out_space;
+   cmsUInt32Number intent, in_type, out_type, nr_samples;
+   int *r, *g, *b;
+   int prec, i, max, max_w, max_h;
+   OPJ_COLOR_SPACE oldspace;
+
+   in_prof = 
+      cmsOpenProfileFromMem(image->icc_profile_buf, image->icc_profile_len);
+#ifdef DEBUG_PROFILE
+   FILE *icm = fopen("debug.icm","wb");
+   fwrite( image->icc_profile_buf,1, image->icc_profile_len,icm);
+   fclose(icm);
+#endif
+
+   if(in_prof == NULL) return;
+
+   in_space = cmsGetPCS(in_prof);
+   out_space = cmsGetColorSpace(in_prof);
+   intent = cmsGetHeaderRenderingIntent(in_prof);
+
+	
+   max_w = (int)image->comps[0].w;
+   max_h = (int)image->comps[0].h;
+   prec = (int)image->comps[0].prec;
+   oldspace = image->color_space;
+
+   if(out_space == cmsSigRgbData) /* enumCS 16 */
+   {
+      if( prec <= 8 )
+      {
+         in_type = TYPE_RGB_8;
+         out_type = TYPE_RGB_8;
+      }
+      else
+      {
+         in_type = TYPE_RGB_16;
+         out_type = TYPE_RGB_16;
+      }
+      out_prof = cmsCreate_sRGBProfile();
+      image->color_space = OPJ_CLRSPC_SRGB;
+   }
+   else if(out_space == cmsSigGrayData) /* enumCS 17 */
+   {
+      in_type = TYPE_GRAY_8;
+      out_type = TYPE_RGB_8;
+      out_prof = cmsCreate_sRGBProfile();
+      image->color_space = OPJ_CLRSPC_SRGB;
+   }
+   else if(out_space == cmsSigYCbCrData) /* enumCS 18 */
+   {
+      in_type = TYPE_YCbCr_16;
+      out_type = TYPE_RGB_16;
+      out_prof = cmsCreate_sRGBProfile();
+      image->color_space = OPJ_CLRSPC_SRGB;
+   }
+   else
+   {
+#ifdef DEBUG_PROFILE
+      fprintf(stderr,"%s:%d: color_apply_icc_profile\n\tICC Profile has unknown "
+              "output colorspace(%#x)(%c%c%c%c)\n\tICC Profile ignored.\n",
+              __FILE__,__LINE__,out_space,
+              (out_space>>24) & 0xff,(out_space>>16) & 0xff,
+              (out_space>>8) & 0xff, out_space & 0xff);
+#endif
+      return;
+   }
+   
+#ifdef DEBUG_PROFILE
+   fprintf(stderr,"%s:%d:color_apply_icc_profile\n\tchannels(%d) prec(%d) w(%d) h(%d)"
+           "\n\tprofile: in(%p) out(%p)\n",__FILE__,__LINE__,image->numcomps,prec,
+           max_w,max_h, (void*)in_prof,(void*)out_prof);
+
+   fprintf(stderr,"\trender_intent (%u)\n\t"
+           "color_space: in(%#x)(%c%c%c%c)   out:(%#x)(%c%c%c%c)\n\t"
+           "       type: in(%u)              out:(%u)\n",
+           intent,
+           in_space,
+           (in_space>>24) & 0xff,(in_space>>16) & 0xff,
+           (in_space>>8) & 0xff, in_space & 0xff,
+
+           out_space,
+           (out_space>>24) & 0xff,(out_space>>16) & 0xff,
+           (out_space>>8) & 0xff, out_space & 0xff,
+
+           in_type,out_type
+           );
+#else
+   (void)prec;
+   (void)in_space;
+#endif /* DEBUG_PROFILE */
+
+   transform = cmsCreateTransform(in_prof, in_type,
+                                  out_prof, out_type, intent, 0);
+
+#ifdef OPJ_HAVE_LIBLCMS2
+/* Possible for: LCMS_VERSION >= 2000 :*/
+   cmsCloseProfile(in_prof);
+   cmsCloseProfile(out_prof);
+#endif
+
+   if(transform == NULL)
+   {
+#ifdef DEBUG_PROFILE
+      fprintf(stderr,"%s:%d:color_apply_icc_profile\n\tcmsCreateTransform failed. "
+              "ICC Profile ignored.\n",__FILE__,__LINE__);
+#endif
+      image->color_space = oldspace;
+#ifdef OPJ_HAVE_LIBLCMS1
+      cmsCloseProfile(in_prof);
+      cmsCloseProfile(out_prof);
+#endif
+      return;
+   }
+
+   if(image->numcomps > 2)/* RGB, RGBA */
+   {
+      if( prec <= 8 )
+      {
+         unsigned char *inbuf, *outbuf, *in, *out;
+         max = max_w * max_h;
+         nr_samples = (cmsUInt32Number)max * 3 * (cmsUInt32Number)sizeof(unsigned char);
+         in = inbuf = (unsigned char*)malloc(nr_samples);
+         out = outbuf = (unsigned char*)malloc(nr_samples);
+
+         r = image->comps[0].data;
+         g = image->comps[1].data;
+         b = image->comps[2].data;
+
+         for(i = 0; i < max; ++i)
+         {
+            *in++ = (unsigned char)*r++;
+            *in++ = (unsigned char)*g++;
+            *in++ = (unsigned char)*b++;
+         }
+
+         cmsDoTransform(transform, inbuf, outbuf, (cmsUInt32Number)max);
+
+         r = image->comps[0].data;
+         g = image->comps[1].data;
+         b = image->comps[2].data;
+
+         for(i = 0; i < max; ++i)
+         {
+            *r++ = (int)*out++;
+            *g++ = (int)*out++;
+            *b++ = (int)*out++;
+         }
+         free(inbuf); free(outbuf);
+      }
+      else
+      {
+         unsigned short *inbuf, *outbuf, *in, *out;
+         max = max_w * max_h;
+         nr_samples = (cmsUInt32Number)max * 3 * (cmsUInt32Number)sizeof(unsigned short);
+         in = inbuf = (unsigned short*)malloc(nr_samples);
+         out = outbuf = (unsigned short*)malloc(nr_samples);
+
+         r = image->comps[0].data;
+         g = image->comps[1].data;
+         b = image->comps[2].data;
+
+         for(i = 0; i < max; ++i)
+         {
+            *in++ = (unsigned short)*r++;
+            *in++ = (unsigned short)*g++;
+            *in++ = (unsigned short)*b++;
+         }
+
+         cmsDoTransform(transform, inbuf, outbuf, (cmsUInt32Number)max);
+
+         r = image->comps[0].data;
+         g = image->comps[1].data;
+         b = image->comps[2].data;
+
+         for(i = 0; i < max; ++i)
+         {
+            *r++ = (int)*out++;
+            *g++ = (int)*out++;
+            *b++ = (int)*out++;
+         }
+         free(inbuf); free(outbuf);
+      }
+   }
+   else /* GRAY, GRAYA */
+   {
+      unsigned char *in, *inbuf, *out, *outbuf;
+      max = max_w * max_h;
+      nr_samples = (cmsUInt32Number)max * 3 * sizeof(unsigned char);
+      in = inbuf = (unsigned char*)malloc(nr_samples);
+      out = outbuf = (unsigned char*)malloc(nr_samples);
+
+      image->comps = (opj_image_comp_t*)
+	 realloc(image->comps, (image->numcomps+2)*sizeof(opj_image_comp_t));
+
+      if(image->numcomps == 2)
+	 image->comps[3] = image->comps[1];
+
+      image->comps[1] = image->comps[0];
+      image->comps[2] = image->comps[0];
+
+      image->comps[1].data = (int*)calloc((size_t)max, sizeof(int));
+      image->comps[2].data = (int*)calloc((size_t)max, sizeof(int));
+
+      image->numcomps += 2;
+
+      r = image->comps[0].data;
+
+      for(i = 0; i < max; ++i)
+      {
+         *in++ = (unsigned char)*r++;
+      }
+      cmsDoTransform(transform, inbuf, outbuf, (cmsUInt32Number)max);
+
+      r = image->comps[0].data;
+      g = image->comps[1].data;
+      b = image->comps[2].data;
+
+      for(i = 0; i < max; ++i)
+      {
+         *r++ = (int)*out++; *g++ = (int)*out++; *b++ = (int)*out++;
+      }
+      free(inbuf); free(outbuf);
+
+   }/* if(image->numcomps */
+
+   cmsDeleteTransform(transform);
+
+#ifdef OPJ_HAVE_LIBLCMS1
+   cmsCloseProfile(in_prof);
+   cmsCloseProfile(out_prof);
+#endif
+}/* color_apply_icc_profile() */
+
+#endif /* OPJ_HAVE_LIBLCMS2 || OPJ_HAVE_LIBLCMS1 */
+
diff --git a/ossim_plugins/openjpeg/ossimOpjColor.h b/ossim_plugins/openjpeg/ossimOpjColor.h
new file mode 100644
index 0000000..6dd7c2a
--- /dev/null
+++ b/ossim_plugins/openjpeg/ossimOpjColor.h
@@ -0,0 +1,53 @@
+/*
+ * The copyright in this software is being made available under the 2-clauses 
+ * BSD License, included below. This software may be subject to other third 
+ * party and contributor rights, including patent rights, and no such rights
+ * are granted under this license.
+ *
+ * Copyright (c) 2002-2014, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2014, Professor Benoit Macq
+ * Copyright (c) 2001-2003, David Janssens
+ * Copyright (c) 2002-2003, Yannick Verschueren
+ * Copyright (c) 2003-2007, Francois-Olivier Devaux 
+ * Copyright (c) 2003-2014, Antonin Descampe
+ * Copyright (c) 2005, Herve Drolon, FreeImage Team
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  24 March 2015 - D. Burken
+ *  Code from openjpeg/src/bin/color.h namespaced for ossim library.
+ */
+
+#ifndef ossimOpjColor_HEADER
+#define ossimOpjColor_HEADER 1
+
+struct opj_image;
+
+namespace ossim
+{
+   void color_sycc_to_rgb(opj_image *img);
+   void color_apply_icc_profile(opj_image *image);
+   
+} // End of namespace ossim
+
+#endif /* ossimOpjColor_HEADER */
diff --git a/ossim_plugins/openjpeg/ossimOpjCommon.cpp b/ossim_plugins/openjpeg/ossimOpjCommon.cpp
new file mode 100644
index 0000000..9c565a8
--- /dev/null
+++ b/ossim_plugins/openjpeg/ossimOpjCommon.cpp
@@ -0,0 +1,925 @@
+//----------------------------------------------------------------------------
+//
+// License:  See top level LICENSE.txt file
+//
+// Author:  David Burken
+//
+// Description:  Place for common code used by both encoders and decoders
+// using the openjpeg library.
+//
+// This code is namespaced with "ossim".
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include <ossimOpjCommon.h>
+#include <ossimOpjColor.h>
+#include <ossim/base/ossimCommon.h>
+#include <ossim/base/ossimException.h>
+#include <ossim/base/ossimIrect.h>
+#include <ossim/base/ossimNotify.h>
+#include <ossim/base/ossimString.h>
+#include <ossim/base/ossimTrace.h>
+#include <ossim/imaging/ossimImageData.h>
+
+#include <openjpeg.h>
+
+#include <cstring>
+#include <istream>
+#include <iostream>
+#include <iomanip>
+
+static ossimTrace traceDebug(ossimString("ossimOpjCommon:degug"));
+
+/** To hold stream and offset. */
+class opj_user_istream
+{
+public:
+   opj_user_istream() : m_str(0), m_offset(0), m_length(0){}
+   ~opj_user_istream(){ m_str = 0; } // We don't own stream.
+   std::istream*   m_str;
+   std::streamoff  m_offset;
+   std::streamsize m_length;
+};
+
+/** Callback method for errors. */
+void ossim::opj_error_callback(const char* msg, void* /* client_data */)
+{
+   ossimNotify(ossimNotifyLevel_WARN) << msg << std::endl;
+}
+
+/** Callback method for warnings. */
+void ossim::opj_warning_callback(const char* msg, void* /* client_data */ )
+{
+   ossimNotify(ossimNotifyLevel_WARN) << msg << std::endl;
+}
+
+/** Callback method for info. */
+void ossim::opj_info_callback(const char* /* msg */ , void* /* client_data */)
+{
+    //ossimNotify(ossimNotifyLevel_NOTICE) << msg << std::endl;
+}
+
+/** Callback function prototype for read function */ 
+static OPJ_SIZE_T ossim_opj_istream_read( void * p_buffer,
+                                          OPJ_SIZE_T p_nb_bytes,
+                                          void * p_user_data )
+{
+   OPJ_SIZE_T count = 0;
+   opj_user_istream* usrStr = static_cast<opj_user_istream*>(p_user_data);
+   if ( usrStr )
+   {
+      if ( usrStr->m_str )
+      {
+         std::streamsize bytesToRead = ossim::min<std::streamsize>(
+            (std::streamsize)p_nb_bytes,
+            (std::streamsize)(usrStr->m_length - usrStr->m_str->tellg() ) );
+         // std::streamsize left = usrStr->m_str->tellg();
+         usrStr->m_str->read( (char*) p_buffer, bytesToRead );
+         count = usrStr->m_str->gcount();
+         
+         if ( usrStr->m_str->eof() )
+         {
+            // Set back to front:
+            usrStr->m_str->clear();
+            usrStr->m_str->seekg(usrStr->m_offset, std::ios_base::beg);
+         }
+         else if ( !usrStr->m_str->good() )
+         {
+            usrStr->m_str->clear();
+            usrStr->m_str->seekg(usrStr->m_offset, std::ios_base::beg);
+            count = -1;
+         }
+      }
+   }
+   return count;
+}
+
+/** Callback function prototype for skip function */
+static OPJ_OFF_T ossim_opj_istream_skip(OPJ_OFF_T p_nb_bytes, void * p_user_data)
+{
+   OPJ_OFF_T skipped = p_nb_bytes;
+   opj_user_istream* usrStr = static_cast<opj_user_istream*>(p_user_data);
+   if ( usrStr )
+   {
+      if ( usrStr->m_str )
+      {
+         std::streampos p1 = usrStr->m_str->tellg();
+         usrStr->m_str->seekg( p_nb_bytes, std::ios_base::cur );
+         std::streampos p2 = usrStr->m_str->tellg();
+         if ( ( p2 - p1 ) !=  p_nb_bytes )
+         {
+            skipped = -1;
+         }
+      }
+   }
+   return skipped;
+}
+
+/** Callback function prototype for seek function */
+static OPJ_BOOL ossim_opj_istream_seek(OPJ_OFF_T p_nb_bytes, void * p_user_data)
+{
+   opj_user_istream* usrStr = static_cast<opj_user_istream*>(p_user_data);
+   if ( usrStr )
+   {
+      if ( usrStr->m_str )
+      {
+         usrStr->m_str->seekg( p_nb_bytes, std::ios_base::beg );
+      }
+   }
+   return OPJ_TRUE;
+}
+
+static void ossim_opj_free_user_istream_data( void * p_user_data )
+{
+   opj_user_istream* usrStr = static_cast<opj_user_istream*>(p_user_data);
+   if ( usrStr )
+   {
+      delete usrStr;
+   }
+   usrStr = 0;
+}
+
+bool ossim::opj_decode( std::ifstream* in,
+                        const ossimIrect& rect,
+                        ossim_uint32 resLevel,
+                        ossim_int32 format, // OPJ_CODEC_FORMAT
+                        std::streamoff fileOffset,
+                        ossimImageData* tile)
+{
+   static const char MODULE[] = "ossimOpjDecoder::decode";
+
+   bool status = false;
+
+   if ( traceDebug() )
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << "entered...\nrect: " << rect
+         << "\nresLevel: " << resLevel << std::endl;
+   }
+   
+   // Need to check for NAN in rect
+   if ( in && tile && !rect.hasNans())
+   {
+      in->seekg( fileOffset, std::ios_base::beg );
+
+      opj_dparameters_t param;
+      opj_codec_t*      codec = 0;
+      opj_image_t*      image = 0;;
+      opj_stream_t*     stream = 0;
+
+      opj_user_istream* userStream = new opj_user_istream();
+      userStream->m_str = in;
+      userStream->m_offset = fileOffset;
+
+      /* Set the length to avoid an assert */
+      in->seekg(0, std::ios_base::end);
+
+      // Fix: length must be passed in for nift blocks.
+      userStream->m_length = in->tellg();
+
+      // Set back to front:
+      in->clear();
+      in->seekg(fileOffset, std::ios_base::beg);
+      
+      stream = opj_stream_default_create(OPJ_TRUE);
+      if (!stream)
+      {
+         opj_stream_destroy(stream);
+         std::string errMsg = MODULE;
+         errMsg += " ERROR: opj_setup_decoder failed!";
+         throw ossimException(errMsg);
+      }
+      
+      opj_stream_set_read_function(stream, ossim_opj_istream_read);
+      opj_stream_set_skip_function(stream, ossim_opj_istream_skip);
+      opj_stream_set_seek_function(stream, ossim_opj_istream_seek);
+
+      // Fix: length must be passed in for nift blocks.
+      opj_stream_set_user_data_length(stream, userStream->m_length);
+      
+      opj_stream_set_user_data(stream, userStream,
+                               ossim_opj_free_user_istream_data);
+
+      opj_stream_set_user_data_length(stream, userStream->m_length);
+
+      
+      /* Set the default decoding parameters */
+      opj_set_default_decoder_parameters(&param);
+
+      param.decod_format = format;
+
+      /** you may here add custom decoding parameters */
+      /* do not use layer decoding limitations */
+      param.cp_layer = 0;
+
+      /* do not use resolutions reductions */
+      param.cp_reduce = resLevel;
+
+      codec = opj_create_decompress( (CODEC_FORMAT)format );
+
+      // catch events using our callbacks and give a local context
+      //opj_set_info_handler   (codec, ossim::opj_info_callback,   00);
+      opj_set_info_handler   (codec, NULL,   00);
+      opj_set_warning_handler(codec, ossim::opj_warning_callback,00);
+      opj_set_error_handler  (codec, ossim::opj_error_callback,  00);
+
+      // Setup the decoder decoding parameters using user parameters
+      if ( opj_setup_decoder(codec, &param) == false )
+      {
+         opj_stream_destroy(stream);
+         opj_destroy_codec(codec);
+         std::string errMsg = MODULE;
+         errMsg += " ERROR: opj_setup_decoder failed!";
+         throw ossimException(errMsg);
+      }
+
+      // Read the main header of the codestream and if necessary the JP2 boxes.
+      if ( opj_read_header(stream, codec, &image) == false )
+      {
+         opj_stream_destroy(stream);
+         opj_destroy_codec(codec);
+         opj_image_destroy(image);         
+         std::string errMsg = MODULE;
+         errMsg += " ERROR: opj_read_header failed!";
+         throw ossimException(errMsg);
+      }
+
+      // tmp drb:
+      // opj_stream_destroy(stream);
+      // return;
+      
+      if ( opj_set_decoded_resolution_factor(codec, resLevel) == false)
+      {
+         opj_stream_destroy(stream);
+         opj_destroy_codec(codec);
+         opj_image_destroy(image);
+         std::string errMsg = MODULE;
+         errMsg += " ERROR:  opj_set_decoded_resolution_factor failed!";
+         throw ossimException(errMsg);
+      }
+
+      //ossim_float32 res = resLevel;
+      ossimIrect resRect = rect * (1 << resLevel);
+
+      //std::cout << "resRect.ul(): " << resRect.ul()
+      //          << "\nresRect.lr(): " << resRect.lr()
+      //          << std::endl;
+
+//      if ( opj_set_decode_area(codec, image, rect.ul().x, rect.ul().y,
+//                               rect.lr().x+1, rect.lr().y+1) == false )
+      if ( opj_set_decode_area(codec, image, resRect.ul().x, resRect.ul().y,
+                               resRect.lr().x+1, resRect.lr().y+1) == false )
+      {
+         opj_stream_destroy(stream);
+         opj_destroy_codec(codec);
+         opj_image_destroy(image);
+         std::string errMsg = MODULE;
+         errMsg += " ERROR: opj_set_decode_area failed!";
+         throw ossimException(errMsg);
+      }
+
+      // Get the decoded image:
+      if ( opj_decode(codec, stream, image) == false )
+      {
+         opj_stream_destroy(stream);
+         opj_destroy_codec(codec);
+         opj_image_destroy(image);
+         std::string errMsg = MODULE;
+         errMsg += " ERROR: opj_decode failed!";
+         throw ossimException(errMsg);
+      }
+      
+      // ossim::print(std::cout, *image);
+      if(image->icc_profile_buf) {
+#if defined(OPJ_HAVE_LIBLCMS1) || defined(OPJ_HAVE_LIBLCMS2)
+          color_apply_icc_profile(image); /* FIXME */
+#endif
+          free(image->icc_profile_buf);
+          image->icc_profile_buf = NULL; image->icc_profile_len = 0;
+      }
+
+      status = ossim::copyOpjImage(image, tile);
+      
+#if 0
+      ossim_uint32 tile_index      = 0;
+      ossim_uint32 data_size       = 0;
+      ossim_int32  current_tile_x0 = 0;
+      ossim_int32  current_tile_y0 = 0;
+      ossim_int32  current_tile_x1 = 0;
+      ossim_int32  current_tile_y1 = 0;
+      ossim_uint32 nb_comps        = 0;
+      OPJ_BOOL go_on = 1;
+
+      if ( opj_read_tile_header( codec,
+                                 stream,
+                                 &tile_index,
+                                 &data_size,
+                                 &current_tile_x0,
+                                 &current_tile_y0,
+                                 &current_tile_x1,
+                                 &current_tile_y1,
+                                 &nb_comps,
+                                 &go_on) == false )
+      {
+         opj_stream_destroy(stream);
+         opj_destroy_codec(codec);
+         opj_image_destroy(image);
+         std::string errMsg = MODULE;
+         errMsg += " ERROR: opj_read_tile_header failed!";
+         throw ossimException(errMsg);
+      }
+#endif
+
+#if 0
+      std::cout << "tile_index:      " << tile_index
+                << "\ndata_size:       " << data_size
+                << "\ncurrent_tile_x0: " << current_tile_x0
+                << "\ncurrent_tile_y0: " << current_tile_y0
+                << "\ncurrent_tile_x1: " << current_tile_x1
+                << "\ncurrent_tile_y1: " << current_tile_y1
+                << "\nnb_comps:        " << nb_comps
+                << std::endl;
+#endif
+
+#if 0
+      if ( opj_decode_tile_data(codec, tile_index,l_data,l_data_size,l_stream) == false)
+      {
+         opj_stream_destroy(l_stream);
+         opj_destroy_codec(l_codec);
+         opj_image_destroy(l_image);
+         std::string errMsg = MODULE;
+         errMsg += " ERROR: opj_read_tile_header failed!";
+         throw ossimException(errMsg);
+      }
+#endif
+
+#if 0
+      
+      if (opj_end_decompress(codec,stream) == false )
+      {
+         opj_stream_destroy(stream);
+         opj_destroy_codec(codec);
+         opj_image_destroy(image);
+         std::string errMsg = MODULE;
+         errMsg += " ERROR: opj_end_decompress failed!";
+         throw ossimException(errMsg);
+      } 
+
+#endif
+      
+      /* Free memory */
+      opj_stream_destroy(stream);
+      opj_destroy_codec(codec);
+      opj_image_destroy(image);
+
+      // Tmp drb:
+      if ( in->eof() )
+      {
+         in->clear();
+      }
+      in->seekg(fileOffset, std::ios_base::beg );
+      
+   } // Matches: if ( in && tile )
+
+   return status;
+   
+} // End: ossim::opj_decode( ... )
+
+bool ossim::copyOpjImage( opj_image* image, ossimImageData* tile )
+{
+   bool status = false;
+   
+   if ( image && tile )
+   {
+      if ( image->color_space == OPJ_CLRSPC_SRGB )
+      {
+         const ossimScalarType SCALAR = tile->getScalarType();
+         if ( SCALAR == OSSIM_UINT8 )
+         {
+            status = ossim::copyOpjSrgbImage( ossim_uint8(0), image, tile );
+         }
+         else
+         {
+            ossimNotify(ossimNotifyLevel_WARN)
+               << "ossim::copyOpjImage WARNING!\nUnhandle scalar: "
+               << SCALAR << "\n";
+         }
+      }
+      else
+      {
+         ossimNotify(ossimNotifyLevel_WARN)
+            << "ossim::copyOpjImage WARNING!\nUnhandle color space: "
+            << image->color_space << "\n";
+      }
+   }
+
+   return status;
+}
+
+template <class T> bool ossim::copyOpjSrgbImage( T /* dummy */,
+                                                 opj_image* image,
+                                                 ossimImageData* tile )
+{
+   bool status = false;
+   
+   const ossim_uint32 BANDS = tile->getNumberOfBands();
+
+   if ( image->numcomps == BANDS )
+   {
+      for ( ossim_uint32 band = 0; band < BANDS; ++band )
+      {
+         T* buf = (T*)tile->getBuf(band);
+         const ossim_uint32 LINES = tile->getHeight();
+         
+         if ( image->comps[band].h == LINES )
+         {
+            ossim_uint32 offset = 0;
+            for ( ossim_uint32 line = 0; line < LINES; ++line )
+            {
+               const ossim_uint32 SAMPS = tile->getWidth();
+               if ( image->comps[band].w == SAMPS )
+               {
+                  for ( ossim_uint32 samp = 0; samp < SAMPS; ++samp )
+                  {
+                     buf[offset] = (T)(image->comps[band].data[offset]);
+                     ++offset;
+                  }
+
+                  //---
+                  // If we get here all the dimensions match and things sould
+                  // be good.
+                  //---
+                  status = true;
+               }
+               else
+               {
+                  ossimNotify(ossimNotifyLevel_WARN)
+                     << "ossim::copyOpjSrgbImage WARNING: sample mismatch!\n";
+               }
+            }
+         }
+         else
+         {
+            ossimNotify(ossimNotifyLevel_WARN)
+               << "ossim::copyOpjSrgbImage WARNING: line mismatch!\n";
+         } 
+      }
+   }
+   else
+   {
+      ossimNotify(ossimNotifyLevel_WARN)
+               << "ossim::copyOpjSrgbImage WARNING: band mismatch!\n";
+   }
+
+   return status;
+   
+} // End: ossim::copyOpjSrgbImage( ... )
+
+ossim_int32 ossim::getCodecFormat( std::istream* str )
+{
+   ossim_int32 result = OPJ_CODEC_UNKNOWN; // -1
+
+   if ( str )
+   {
+      if ( str->good() )
+      {
+         const ossim_uint8 JP2_RFC3745_MAGIC[12] = 
+            { 0x00,0x00,0x00,0x0c,0x6a,0x50,0x20,0x20,0x0d,0x0a,0x87,0x0a };
+         const ossim_uint8 JP2_MAGIC[4] = { 0x0d,0x0a,0x87,0x0a };
+         const ossim_uint8 J2K_CODESTREAM_MAGIC[4] = { 0xff,0x4f,0xff,0x51 };
+         
+         ossim_uint8 buf[12];
+         
+         // Read in the box.
+         str->read((char*)buf, 12);
+         
+         if ( ( std::memcmp(buf, JP2_RFC3745_MAGIC, 12) == 0 ) ||
+              ( std::memcmp(buf, JP2_MAGIC, 4) == 0 ) )
+         {
+            result = OPJ_CODEC_JP2;
+         }
+         else if ( std::memcmp(buf, J2K_CODESTREAM_MAGIC, 4) == 0 )
+         {
+            result = OPJ_CODEC_J2K;
+         }
+      }
+   }
+   
+   return result;
+}
+
+std::ostream& ossim::print(std::ostream& out, const opj_codestream_info& info)
+{
+   // Capture stream flags since we are going to mess with them.
+   std::ios_base::fmtflags f = out.flags();
+   
+   const int W = 20;
+   
+   out << std::setiosflags(std::ios_base::right) << std::setfill(' ')
+       << "opj_codestream_info:\n\n"
+       << std::setw(W) << "D_max: "
+       << info.D_max << "\n"
+       << std::setw(W) << "packno: "
+       << info.packno << "\n"
+       << std::setw(W) << "index_write: "
+       <<info.index_write << "\n"
+       << std::setw(W) << "image_w: "
+       << info.image_w << "\n"
+       << std::setw(W) << "image_h: "
+       << info.image_h << "\n"
+       << std::setw(W) << "proj: "
+       << info.prog << "\n"
+       << std::setw(W) << "tile_x: "
+       << info.tile_x << "\n"
+       << std::setw(W) << "tile_y: "
+       << info.tile_y << "\n"
+       << std::setw(W) << "tile_Ox: "
+       << info.tile_Ox << "\n"
+       << std::setw(W) << "tile_Oy: "
+       << info.tile_Oy << "\n"
+       << std::setw(W) << "tw: "
+       << info.tw << "\n"
+       << std::setw(W) << "th: "
+       << info.th << "\n"
+       << std::setw(W) << "numcomps: "
+       << info.numcomps << "\n"
+       << std::setw(W) << "numlayers: "
+       << info.numlayers << "\n";
+
+   for (int i = 0; i < info.numcomps; ++i)
+   {
+      std::string s = "numdecompos[";
+      s += ossimString::toString(i).string();
+      s += "]: ";
+      out << std::setw(W) << s << info.numdecompos[i] << "\n";
+   }
+
+   out << std::setw(W) << "marknum: "
+       << info.marknum << "\n"
+      // << std::setw(W) << "marker: " << info.marker << "\n"
+       << std::setw(W) << "maxmarknum: "
+       << info.maxmarknum << "\n"
+       << std::setw(W) << "main_head_start: "
+       << info.main_head_start << "\n"
+       << std::setw(W) << "main_head_end: "
+       << info.main_head_end << "\n"
+       << std::setw(W) << "codestream_size: "
+       << info.codestream_size << "\n"
+      // << "tile: " << info.tile
+       << std::endl;
+
+   // Set the flags back.
+   out.flags(f);
+
+   return out;
+}
+
+std::ostream& ossim::print(std::ostream& out, const opj_cparameters& param)
+{
+   // Capture stream flags since we are going to mess with them.
+   std::ios_base::fmtflags f = out.flags();
+
+   const int W = 24;
+   int i;
+
+   out << std::setiosflags(std::ios_base::left) << std::setfill(' ')
+       << "opj_cparameters:\n\n"
+      
+       << std::setw(W) << "tile_size_on:"
+       << param.tile_size_on << "\n"
+
+       << std::setw(W) << "cp_tx0: "
+       << param.cp_tx0 << "\n"
+
+       << std::setw(W) << "cp_ty0: "
+       << param.cp_ty0 << "\n"
+
+       << std::setw(W) << "cp_tdx: "
+       << param.cp_tdx << "\n"
+
+       << std::setw(W) << "cp_tdy: "
+       << param.cp_tdy << "\n"
+
+       << std::setw(W) << "cp_disto_alloc: "
+       << param.cp_disto_alloc << "\n"
+
+       << std::setw(W) << "cp_fixed_alloc: "
+       << param.cp_fixed_alloc << "\n"
+
+       << std::setw(W) << "cp_fixed_quality: "
+       << param.cp_fixed_quality << "\n"
+
+       << "cp_matrice:\n"
+
+       << "cp_comment:\n"
+
+       << std::setw(W) << "csty:"
+       << param.csty << "\n"
+      
+       << std::setw(W) << "prog_order: "
+       << getProgressionOrderString( (ossim_int32)param.prog_order ) << "\n"
+
+       << "POC:\n"
+      
+       << std::setw(W) << "numpocs:"
+       << param.numpocs << "\n"
+      
+       << std::setw(W) << "tcp_numlayers:"
+       << param.tcp_numlayers << "\n";
+
+   for ( i = 0; i < param.tcp_numlayers; ++i )
+   {
+      out << "tcp_rate[" << i << std::setw(14)<< "]: "<< std::setw(4) << param.tcp_rates[i] << "\n"
+          << "tcp_distoratio[" << i << std::setw(8) << "]: " << std::setw(4) << param.tcp_distoratio[i] << "\n";
+   }
+
+   out << std::setw(W) << "numresolution:"
+       << param.numresolution << "\n"
+
+       << std::setw(W) << "cblockw_init:"
+       << param.cblockw_init << "\n"
+      
+       << std::setw(W) << "cblockh_init:"
+       << param.cblockh_init << "\n"
+      
+       << std::setw(W) << "mode:"
+       << param.mode << "\n"
+      
+       << std::setw(W) << "irreversible:"
+       << param.irreversible << "\n"
+      
+       << std::setw(W) << "roi_compn:"
+       << param.roi_compno << "\n"
+      
+       << std::setw(W) << "roi_shift:"
+       << param.roi_shift << "\n"
+      
+       << std::setw(W) << "res_spec:"
+       << param.res_spec << "\n"
+      
+       << "prcw_init:\n"
+      // << param.prcw_init << "\n"
+      
+       << "prch_init:\n"
+      // << param.prcw_init << "\n"
+
+      // << std::setw(W) << "infile:"
+      //  << param.infile << "\n"
+
+       << std::setw(W) << "outfile:"
+       << param.outfile << "\n"
+
+      // << std::setw(W) << "index_on:"
+      //  << param.index_on << "\n"
+
+      // << std::setw(W) << "index:"
+      //  << param.index << "\n"
+
+       << std::setw(W) << "image_offset_x0:"
+       << param.image_offset_x0 << "\n"
+
+       << std::setw(W) << "image_offset_y0:"
+       << param.image_offset_y0 << "\n"
+      
+       << std::setw(W) << "subsampling_dx:"
+       << param.subsampling_dx << "\n"
+
+       << std::setw(W) << "image_offset_dy:"
+       << param.subsampling_dy << "\n"
+      
+       << std::setw(W) << "decod_format:"
+       << param.decod_format << "\n"
+      
+       << std::setw(W) << "cod_format:"
+       << param.cod_format << "\n"
+      
+       << std::setw(W) << "jpwl_epc_on:"
+       << param.jpwl_epc_on << "\n"
+      
+       << std::setw(W) << "jpwl_hprot_MH:"
+       << param.jpwl_hprot_MH << "\n"
+      
+       << "jpwl_hprot_TPH_tileno:\n"
+
+       << "jpwl_pprot_TPH:\n"
+
+       << "jpwl_pprot_tileno:\n"
+      
+       << "jpwl_pprot_packno:\n"
+
+       << "jpwl_pprot:\n"
+      
+       << std::setw(W) << "jpwl_sens_size:"
+       << param.jpwl_sens_size << "\n"
+
+       << std::setw(W) << "jpwl_sens_addr:"
+       << param.jpwl_sens_addr << "\n"
+     
+       << std::setw(W) << "jpwl_sens_range:"
+       << param.jpwl_sens_range << "\n"
+     
+       << std::setw(W) << "jpwl_sens_MH:"
+       << param.jpwl_sens_MH << "\n"
+     
+       << "jpwl_sens_TPH_tileno:\n"
+
+       << "jpwl_sens_TPH:\n"
+
+       << "cp_cinema:\n"
+
+       << std::setw(W) << "max_comp_size:"
+       << param.max_comp_size << "\n"
+
+       << std::setw(W) << "cp_rsiz:"
+       << param.cp_rsiz << "\n"
+
+       << std::setw(W) << "tp_on:"
+       << param.tp_on << "\n"
+
+       << std::setw(W) << "tp_flag:"
+       << param.tp_flag << "\n"
+
+       << std::setw(W) << "tcp_mct:"
+       << int(param.tcp_mct) << "\n"
+
+       << std::setw(W) << "jpip_on:"
+       << param.jpip_on << "\n"
+
+       << "mct_data:\n"
+
+       << std::setw(W) << "max_cs_size:"
+       << param.max_cs_size << "\n"
+
+       << std::setw(W) << "rsiz:"
+       << param.rsiz << "\n"
+
+       << std::endl;
+
+   // Set the flags back.
+   out.flags(f);
+
+   return out;
+}
+
+std::ostream& ossim::print(std::ostream& out, const opj_dparameters& param)
+{
+   // Capture stream flags since we are going to mess with them.
+   std::ios_base::fmtflags f = out.flags();
+
+   const int W = 20;
+
+   out << std::setiosflags(std::ios_base::right) << std::setfill(' ')
+       << "opj_dparameters:\n\n"
+       << std::setw(W) << "cp_reduce: "
+       << param.cp_reduce << "\n"
+       << std::setw(W) << "cp_layer: "
+       << param.cp_layer << "\n"
+       << std::setw(W) << "infile: "
+       << param.infile << "\n"
+       << std::setw(W) << "outfile: "
+       << param.outfile << "\n"
+       << std::setw(W) << "decod_format: "
+       << param.decod_format << "\n"
+       << std::setw(W) << "cod_format: "
+       << param.cod_format << "\n"
+       << std::setw(W) << "jpwl_correct: "
+       << param.jpwl_correct << "\n"
+       << std::setw(W) << "jpwl_exp_comps: "
+       << param.jpwl_exp_comps << "\n"
+       << std::setw(W) << "jpwl_max_tiles: "
+       << param.jpwl_max_tiles << "\n"
+       << std::setw(W) << "cp_limit_decoding: "
+      // << param.cp_limit_decoding fix (drb)
+       << std::endl;
+   // Set the flags back.
+   out.flags(f);
+
+   return out;
+}
+
+std::ostream& ossim::print(std::ostream& out, const opj_image& image)
+{
+   // Capture stream flags since we are going to mess with them.
+   std::ios_base::fmtflags f = out.flags();
+
+   const int W = 20;
+
+   out << std::setiosflags(std::ios_base::right) << std::setfill(' ')
+       << "opj_image:\n\n"
+       << std::setw(W) << "x0: "
+       << image.x0 << "\n"
+       << std::setw(W) << "y0: "
+       << image.y0 << "\n"
+       << std::setw(W) << "x1: "
+       << image.x1 << "\n"
+       << std::setw(W) << "y1: "
+       << image.y1 << "\n"
+       << std::setw(W) << "numcomps: "
+       << image.numcomps << "\n"
+       << std::setw(W) << "color_space: ";
+   if ( image.color_space == OPJ_CLRSPC_UNKNOWN ) out << "UNKNOWN\n";
+   else if (  image.color_space == OPJ_CLRSPC_UNSPECIFIED) out << "UNSPECIFIED\n";
+   else if (  image.color_space == OPJ_CLRSPC_SRGB) out << "SRGB\n";
+   else if (  image.color_space == OPJ_CLRSPC_GRAY) out << "GRAY\n";
+   else if (  image.color_space == OPJ_CLRSPC_SYCC) out << "SYCC\n";
+   else if (  image.color_space == OPJ_CLRSPC_EYCC) out << "EYCC\n";
+   else if (  image.color_space == OPJ_CLRSPC_CMYK) out << "CMYK\n";
+
+   for (ossim_uint32 i = 0; i < image.numcomps; ++i)
+   {
+      std::string s = "comps[";
+      s += ossimString::toString(i).string();
+      s += "]: ";
+      out << s << std::endl;
+         
+      print(out, (image.comps[i]));
+   }
+
+   out << std::endl;
+      
+   // Set the flags back.
+   out.flags(f);
+
+   return out;
+}
+
+std::ostream& ossim::print(std::ostream& out, const opj_image_comp& comp)
+{
+   // Capture stream flags since we are going to mess with them.
+   std::ios_base::fmtflags f = out.flags();
+
+   const int W = 20;
+
+   out << std::setiosflags(std::ios_base::right) << std::setfill(' ')
+       << "opj_image_comp:\n\n"
+       << std::setw(W) << "dx: "
+       << comp.dx << "\n"
+       << std::setw(W) << "dy: "
+       << comp.dy << "\n"
+       << std::setw(W) << "w: "
+       << comp.w << "\n"
+       << std::setw(W) << "h: "
+       << comp.h << "\n"
+       << std::setw(W) << "x0: "
+       << comp.x0 << "\n"
+       << std::setw(W) << "y0: "
+       << comp.y0 << "\n"
+       << std::setw(W) << "prec: "
+       << comp.prec << "\n"
+       << std::setw(W) << "bpp: "
+       << comp.bpp << "\n" 
+       << std::setw(W) << "sgnd: "
+       << comp.sgnd << "\n"
+       << std::setw(W) << "resno_decoded: "
+       << comp.resno_decoded << "\n"
+       << std::setw(W) << "factor: "
+       << comp.factor
+       << std::endl;
+      
+   // Set the flags back.
+   out.flags(f);
+
+   return out;
+}
+
+std::string ossim::getProgressionOrderString( int prog_order )
+{
+   std::string result = "";
+   switch (prog_order)
+   {
+      case OPJ_LRCP:
+      {
+         result = "LRCP";
+         break;
+      }
+      case OPJ_RLCP:
+      {
+         result = "RLCP";
+         break;
+      }
+      case OPJ_RPCL:
+      {
+         result = "RPCL";
+         break;
+      }
+      case OPJ_PCRL:
+      {
+         result = "PCRL";
+         break;
+      }
+      case OPJ_CPRL:
+      {
+         result = "CPRL";
+         break;
+      }
+      default:
+      {
+         result = "UNKOWN";
+         break;
+      }
+   }
+   
+   return result;
+}
+
diff --git a/ossim_plugins/openjpeg/ossimOpjCommon.h b/ossim_plugins/openjpeg/ossimOpjCommon.h
new file mode 100644
index 0000000..f9f1c89
--- /dev/null
+++ b/ossim_plugins/openjpeg/ossimOpjCommon.h
@@ -0,0 +1,101 @@
+//----------------------------------------------------------------------------
+//
+// License:  See top level LICENSE.txt file
+//
+// Author:  David Burken
+//
+// Description:  Place for common code used by both encoders and decoders
+// using the openjpeg library.
+//
+// This code is namespaced with "ossim".
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef ossimOpjCommon_HEADER
+#define ossimOpjCommon_HEADER 1
+
+#include <ossim/base/ossimConstants.h>
+#include <iosfwd>
+#include <string>
+
+// Forward declarations:
+class ossimImageData;
+class ossimIrect;
+struct opj_codestream_info;
+struct opj_cparameters;
+struct opj_dparameters;
+struct opj_image;
+struct opj_image_comp;
+
+namespace ossim
+{
+   /** @brief Callback method for errors. */
+   void opj_error_callback(const char* msg, void* /* client_data */);
+
+   /** @brief Callback method for warnings. */
+   void opj_warning_callback(const char* msg, void* /* client_data */ );
+
+   /** @brief Callback method for info. */
+   void opj_info_callback(const char* msg, void* /* client_data */);
+
+   bool opj_decode( std::ifstream* in,
+                    const ossimIrect& rect,
+                    ossim_uint32 resLevel,
+                    ossim_int32 format, // OPJ_CODEC_FORMAT
+                    std::streamoff fileOffset, // for nitf
+                    ossimImageData* tile
+                    );
+   
+   bool copyOpjImage( opj_image* image, ossimImageData* tile );
+   
+   template <class T> bool copyOpjSrgbImage( T dummy,
+                                             opj_image* image,
+                                             ossimImageData* tile );
+   
+   /**
+    * Gets codec format from magic number.
+    * @return OPJ_CODEC_J2K = 0, OPJ_CODEC_JP2 = 2, OPJ_CODEC_UNKNOWN = -1
+    */
+   ossim_int32 getCodecFormat( std::istream* str );
+
+   /**
+    * Prints codestream info from openjpeg struct opj_codestream_info.
+    * 
+    * @return std::ostream&
+    */
+   std::ostream& print(std::ostream& out, const opj_codestream_info& info);
+   
+   /**
+    * Prints compression parameters from openjpeg struct opj_cparameters.
+    * 
+    * @return std::ostream&
+    */
+   std::ostream& print(std::ostream& out, const opj_cparameters& param);
+
+   /**
+    * Prints decode parameters from openjpeg struct opj_dparameters.
+    * 
+    * @return std::ostream&
+    */
+   std::ostream& print(std::ostream& out, const opj_dparameters& param);
+
+   /**
+    * Prints opj_image structure.
+    * 
+    * @return std::ostream&
+    */
+   std::ostream& print(std::ostream& out, const opj_image& image);
+
+   /**
+    * Prints opj_image_comp structure.
+    * 
+    * @return std::ostream&
+    */
+   std::ostream& print(std::ostream& out, const opj_image_comp& comp);
+
+   std::string getProgressionOrderString( ossim_int32 prog_order );
+
+} // End of namespace ossim
+
+#endif /* ossimOpjCommon_HEADER */
diff --git a/ossim_plugins/openjpeg/ossimOpjCompressor.cpp b/ossim_plugins/openjpeg/ossimOpjCompressor.cpp
new file mode 100644
index 0000000..0f4413d
--- /dev/null
+++ b/ossim_plugins/openjpeg/ossimOpjCompressor.cpp
@@ -0,0 +1,1257 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author:  David Burken
+//
+// Description: Wrapper class to compress whole tiles using kdu_analysis
+// object.
+//
+//----------------------------------------------------------------------------
+// $Id: ossimOpjCompressor.cpp 22513 2013-12-11 21:45:51Z dburken $
+
+#include "ossimOpjCompressor.h"
+#include "ossimOpjCommon.h"
+#include "ossimOpjKeywords.h"
+
+#include <ossim/base/ossimBooleanProperty.h>
+#include <ossim/base/ossimException.h>
+#include <ossim/base/ossimIpt.h>
+#include <ossim/base/ossimKeywordlist.h>
+#include <ossim/base/ossimKeywordNames.h>
+#include <ossim/base/ossimNotify.h>
+#include <ossim/base/ossimNumericProperty.h>
+#include <ossim/base/ossimPreferences.h>
+#include <ossim/base/ossimStringProperty.h>
+#include <ossim/base/ossimTrace.h>
+
+#include <ossim/imaging/ossimImageData.h>
+#include <ossim/imaging/ossimImageGeometry.h>
+
+#include <ossim/support_data/ossimGeoTiff.h>
+#include <ossim/support_data/ossimGmlSupportData.h>
+
+#include <sstream>
+
+//---
+// For trace debugging (to enable at runtime do:
+// your_app -T "ossimOpjCompressor:debug" your_app_args
+//---
+static ossimTrace traceDebug("ossimOpjCompressor:debug");
+
+static const ossim_int32 DEFAULT_LEVELS = 5;
+
+// Callback stream function prototypes:
+static OPJ_SIZE_T ossim_opj_ostream_write( void * p_buffer,
+                                           OPJ_SIZE_T p_nb_bytes,
+                                           void * p_user_data )
+{
+   OPJ_SIZE_T count = 0;
+   if ( p_user_data )
+   {
+      ostream* str = (ostream*)p_user_data;
+      std::streamsize bytesToRead = (std::streamsize)p_nb_bytes;
+      str->write( (char*) p_buffer, bytesToRead );
+      count = p_nb_bytes;
+   }
+   return count;
+}
+
+// Callback function prototype for skip function:
+static OPJ_OFF_T ossim_opj_ostream_skip(OPJ_OFF_T p_nb_bytes, void * p_user_data)
+{
+   OPJ_OFF_T pos = 0;
+   if ( p_user_data )
+   {
+      ostream* str = (ostream*)p_user_data;
+      str->seekp( p_nb_bytes, std::ios_base::cur );
+      pos = p_nb_bytes;
+   }
+   return pos;
+}
+
+/// Callback function prototype for seek function:
+static OPJ_BOOL ossim_opj_ostream_seek(OPJ_OFF_T p_nb_bytes, void * p_user_data)
+{
+   if ( p_user_data )
+   {
+      ostream* str = (ostream*)p_user_data;
+      // str->seekp( p_nb_bytes, std::ios_base::cur );
+      str->seekp( p_nb_bytes, std::ios_base::beg );         
+   }
+   return OPJ_TRUE;
+}
+
+static void ossim_opj_free_user_ostream_data( void * p_user_data )
+{
+   if ( p_user_data )
+   {
+      ostream* str = (ostream*)p_user_data;
+      str->flush();
+   }
+}
+
+// Matches ossimOpjCompressionQuality enumeration:
+static const ossimString COMPRESSION_QUALITY[] = { "unknown",
+                                                   "user_defined",
+                                                   "numerically_lossless",
+                                                   "visually_lossless",
+                                                   "lossy" };
+
+
+ossimOpjCompressor::ossimOpjCompressor()
+   :
+   m_params(0),
+   m_codec(0),
+   m_stream(0),
+   m_image(0),
+   m_imageRect(),
+   m_reversible(true),
+   m_alpha(false),
+   m_levels(0),
+   m_threads(1),
+   m_options(),
+   m_qualityType(ossimOpjCompressor::OPJ_NUMERICALLY_LOSSLESS)
+{
+   //---
+   // Uncomment for debug mode:
+   // traceDebug.setTraceFlag(true);
+   //---
+}
+
+ossimOpjCompressor::~ossimOpjCompressor()
+{
+   finish();
+}
+
+void ossimOpjCompressor::create(std::ostream* os,
+                                ossimScalarType scalar,
+                                ossim_uint32 bands,
+                                const ossimIrect& imageRect,
+                                const ossimIpt& tileSize,
+                                bool jp2)
+{
+   static const char MODULE[] = "ossimOpjCompressor::create";
+   if ( traceDebug() )
+   {
+      ossimNotify(ossimNotifyLevel_WARN) << MODULE << " entered...\n";
+   }
+   
+#if 0 /* Please leave for debug. (drb) */
+   cout << "levels:      " << m_levels
+        << "\nreversible:  " << m_reversible
+        << "\nthreads:     " << m_threads
+        << "\nscalar:    " << scalar
+        << "\nbands:     " << bands
+        << "\nimageRect: " << imageRect
+        << "\ntileSize:  " << tileSize
+        << "\njp2:       " << jp2
+        << endl;
+#endif
+
+   // In case we were reused.
+   finish();
+
+   if ( !os )
+   {
+      std::string errMsg = MODULE;
+      errMsg += " ERROR: Null stream passed to method!";
+      throw ossimException(errMsg);
+   }
+   
+   if ( !os->good() )
+   {
+      std::string errMsg = MODULE;
+      errMsg += " ERROR: Stream state has error!";
+      throw ossimException(errMsg);
+   }
+   
+   if ( ossim::getActualBitsPerPixel(scalar) > 31 )
+   {
+      // Data is not reversible.
+      if ( m_reversible )
+      {
+         std::string errMsg = MODULE;
+         errMsg += " ERROR: Reversible processing not possible with 32 bit data!";
+         throw ossimException(errMsg);
+      }
+   }
+   
+   // Store for tile clip.
+   m_imageRect = imageRect;
+
+   m_stream = createOpjStream( os );
+   if ( !m_stream )
+   {
+      std::string errMsg = MODULE;
+      errMsg += " ERROR: OPJ stream creation failed!";
+      throw ossimException(errMsg); 
+   }
+
+   // Requests the insertion of TLM (tile-part-length) marker.
+   // setTlmTileCount(tilesToWrite);
+   
+   // Set up stream:
+   initOpjCodingParams( jp2, tileSize, imageRect );
+   if ( !m_params )
+   {
+      std::string errMsg = MODULE;
+      errMsg += " ERROR: coding parameters creation failed!";
+      throw ossimException(errMsg);
+   }
+
+   m_codec = createOpjCodec( jp2 );
+   if ( !m_codec )
+   {
+      std::string errMsg = MODULE;
+      errMsg += " ERROR: code creation failed!";
+      throw ossimException(errMsg);
+   }   
+
+   // Set rates rates/distorsion
+   // parameters->cp_disto_alloc = 1;
+
+   // ossim::print( cout, *m_params );
+   
+   if (m_alpha)
+   {
+      if ( (bands != 1) && (bands != 3) )
+      {
+         m_alpha = false;
+         if ( traceDebug() )
+         {
+            ossimNotify(ossimNotifyLevel_WARN)
+               << "Alpha channel being unset! Can only be used with "
+               << "one or three band data.\n"
+               << "Source image bands: " << bands << "\n";
+         }
+      }
+   }
+
+   // Create an image without allocating memory(for tile based).
+   m_image = createOpjImage( scalar, bands, imageRect );
+   if ( !m_image )
+   {
+      std::string errMsg = MODULE;
+      errMsg += " ERROR: Unsupported input image type!";
+      throw ossimException(errMsg);
+   }
+
+   if ( !opj_setup_encoder( m_codec, m_params, m_image) )
+   {
+      std::string errMsg = MODULE;
+      errMsg += " ERROR: opj_setup_encoder failed!";
+      throw ossimException(errMsg); 
+   }
+
+   // openJp2Codestream();
+   
+   if ( traceDebug() )
+   {
+      ossim::print( ossimNotify(ossimNotifyLevel_DEBUG), *m_params );
+      
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " exiting...\n";
+   }
+}
+
+void ossimOpjCompressor::openJp2Codestream()
+{
+   //---
+   // Start compression...
+   // Matching "opj_end_compress" is in ossimOpjCompressor::finish().
+   //---
+   if ( !opj_start_compress(m_codec, m_image, m_stream) )
+   {
+      std::string errMsg = "ossimOpjCompressor::openJp2Codestream ERROR: opj_start_compress failed!";
+      throw ossimException(errMsg);
+   }
+}
+
+bool ossimOpjCompressor::writeTile(
+   ossimImageData* srcTile, ossim_uint32 tileIndex )
+{
+   bool result = false;
+
+   if ( srcTile )
+   {
+      if (srcTile->getDataObjectStatus() != OSSIM_NULL)
+      {
+         ossimIrect tileRect = srcTile->getImageRectangle();
+
+         // Write the tile out:
+         if ( opj_write_tile( m_codec,
+                              tileIndex,
+                              srcTile->getUcharBuf(),
+                              srcTile->getDataSizeInBytes(),
+                              m_stream ) ) 
+         {
+            result = true;
+         }
+         else
+         {
+            ossimNotify(ossimNotifyLevel_WARN)
+               << "ossimOpjCompressor::writeTile ERROR on tile index: "
+               << tileIndex << std::endl;
+         }
+      }
+      else
+      {
+         ossimNotify(ossimNotifyLevel_WARN)
+            << "ossimOpjCompressor::writeTile ERROR null tile passed in!" << endl;
+      }
+   }
+   
+   return result;
+   
+} // End: ossimOpjCompressor::writeTile
+
+void ossimOpjCompressor::finish()
+{
+   if ( m_stream )
+   {
+      // Every opj_start_compress must have an end.
+      opj_end_compress( m_codec, m_stream );
+
+      opj_stream_destroy( m_stream );
+      m_stream = 0;
+   }
+   if ( m_codec )
+   {
+      opj_destroy_codec( m_codec );
+      m_codec = 0;
+   }
+   if ( m_image )
+   {
+      opj_image_destroy( m_image );
+      m_image = 0;
+   }
+}
+
+void ossimOpjCompressor::setQualityType(ossimOpjCompressionQuality type)
+{
+   m_qualityType = type;
+
+   //---
+   // Set the reversible flag for appropriate type.
+   // Not sure what to set for unknown and user defined but visually lossless
+   // and lossy need to set the reversible flag to false.
+   //---
+   if ( (type == ossimOpjCompressor::OPJ_VISUALLY_LOSSLESS) ||
+        (type == ossimOpjCompressor::OPJ_LOSSY) )
+   {
+      setReversibleFlag(false);
+   }
+   else
+   {
+      setReversibleFlag(true);
+   }
+}
+
+ossimOpjCompressor::ossimOpjCompressionQuality ossimOpjCompressor::getQualityType() const
+{
+   return m_qualityType;
+   
+}
+
+void ossimOpjCompressor::setReversibleFlag(bool reversible)
+{
+   m_reversible = reversible;
+}
+
+bool ossimOpjCompressor::getReversibleFlag() const
+{
+   return m_reversible;
+}
+
+void ossimOpjCompressor::setAlphaChannelFlag(bool flag)
+{
+   m_alpha = flag;
+}
+
+bool ossimOpjCompressor::getAlphaChannelFlag() const
+{
+   return m_alpha;
+}
+
+void ossimOpjCompressor::setLevels(ossim_int32 levels)
+{
+   if (levels)
+   {
+      m_levels = levels;
+   }
+}
+
+ossim_int32 ossimOpjCompressor::getLevels() const
+{
+   return m_levels;
+}
+
+void ossimOpjCompressor::setThreads(ossim_int32 threads)
+{
+   if (threads)
+   {
+      m_threads = threads;
+   }
+}
+
+ossim_int32 ossimOpjCompressor::getThreads() const
+{
+   return m_threads;
+}
+
+void ossimOpjCompressor::setOptions(const std::vector<ossimString>& options)
+{
+   std::vector<ossimString>::const_iterator i = options.begin();
+   while ( i != options.end() )
+   {
+      m_options.push_back( (*i) );
+      ++i;
+   }
+}
+
+bool ossimOpjCompressor::setProperty(ossimRefPtr<ossimProperty> property)
+{
+   bool consumed = false;
+   
+   if ( property.valid() )
+   {
+      ossimString key = property->getName();
+
+      if ( traceDebug() )
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG)
+            << "ossimOpjCompressor::setProperty DEBUG:"
+            << "\nkey: " << key
+            << " values: " << property->valueToString() << std::endl;
+      }
+      
+      if (key == ossimKeywordNames::COMPRESSION_QUALITY_KW)
+      {
+         setQualityTypeString(property->valueToString());
+         consumed = true;
+      }
+      else if ( (key == LEVELS_KW) || (key ==  "Clevels") )
+      {
+         m_levels = property->valueToString().toInt32();
+         consumed = true;
+      }
+      else if( (key == REVERSIBLE_KW) || (key == "Creversible") )
+      {
+         setReversibleFlag(property->valueToString().toBool());
+         consumed = true;
+      }
+      else if (key == ADD_ALPHA_CHANNEL_KW)
+      {
+         m_alpha = property->valueToString().toBool();
+         consumed = true;
+      }
+      else if ( key == THREADS_KW)
+      {
+         m_threads = property->valueToString().toInt32();
+         consumed = true;
+      }
+      else if ( (key == "Clayers") ||
+                (key == "Cprecincts") )
+      {
+         // Generic options passed through kdu_params::parse_string.
+
+         // Make in the form of "key=value" for kdu_params::parse_string.
+         ossimString option = key;
+         option += "=";
+         option += property->valueToString();
+         
+         // Add to list.
+         m_options.push_back(option);
+         
+         consumed = true;
+      } 
+   }
+
+   return consumed;
+}
+
+ossimRefPtr<ossimProperty> ossimOpjCompressor::getProperty(
+   const ossimString& name)const
+{
+   ossimRefPtr<ossimProperty> p = 0;
+
+   if (name == ossimKeywordNames::COMPRESSION_QUALITY_KW)
+   {
+      // property value
+      ossimString value = getQualityTypeString();
+
+      if ( (value == COMPRESSION_QUALITY[ossimOpjCompressor::OPJ_USER_DEFINED] ) ||
+           (value == COMPRESSION_QUALITY[ossimOpjCompressor::OPJ_UNKNOWN])
+          )
+      {
+         value = COMPRESSION_QUALITY[ossimOpjCompressor::OPJ_NUMERICALLY_LOSSLESS];
+      }
+         
+      // constraint list
+      vector<ossimString> constraintList;
+      constraintList.push_back(COMPRESSION_QUALITY[ossimOpjCompressor::
+                                                   OPJ_NUMERICALLY_LOSSLESS]);
+      constraintList.push_back(COMPRESSION_QUALITY[ossimOpjCompressor::
+                                                   OPJ_VISUALLY_LOSSLESS]);
+      constraintList.push_back(COMPRESSION_QUALITY[ossimOpjCompressor::
+                                                   OPJ_LOSSY]);
+      
+      p = new ossimStringProperty(name,
+                                  value,
+                                  false, // not editable
+                                  constraintList);
+   }
+   else if (name == LEVELS_KW)
+   {
+      p = new ossimNumericProperty(name, ossimString::toString(m_levels));
+   }
+   else if (name == REVERSIBLE_KW)
+   {
+      p = new ossimBooleanProperty(name, m_reversible);
+   }
+   else if (name == ADD_ALPHA_CHANNEL_KW)
+   {
+      p = new ossimBooleanProperty(name, m_alpha);
+   }
+   else if (name == THREADS_KW)
+   {
+      p = new ossimNumericProperty(name, ossimString::toString(m_threads));
+   }   
+   
+   return p;
+}
+
+void ossimOpjCompressor::getPropertyNames(
+   std::vector<ossimString>& propertyNames)const
+{
+   propertyNames.push_back(ossimKeywordNames::COMPRESSION_QUALITY_KW);
+   propertyNames.push_back(LEVELS_KW);
+   propertyNames.push_back(REVERSIBLE_KW);
+   propertyNames.push_back(THREADS_KW);
+}
+
+bool ossimOpjCompressor::saveState(ossimKeywordlist& kwl,
+                                      const char* prefix)const
+{
+   kwl.add( prefix,
+            ossimKeywordNames::COMPRESSION_QUALITY_KW,
+            getQualityTypeString().c_str(),
+            true );
+   
+   kwl.add( prefix,
+            LEVELS_KW,
+            ossimString::toString(m_levels),
+            true );
+   
+   kwl.add( prefix,
+            REVERSIBLE_KW,
+            ossimString::toString(m_reversible),
+            true );
+
+   kwl.add( prefix,
+            ADD_ALPHA_CHANNEL_KW,
+            ossimString::toString(m_alpha),
+            true ); 
+   
+   kwl.add( prefix,
+            THREADS_KW,
+            ossimString::toString(m_threads),
+            true );
+
+   std::vector<ossimString>::size_type size = m_options.size();
+   for (ossim_uint32 i = 0; i < size; ++i)
+   {
+      ossimString key = "option";
+      key += ossimString::toString(i);
+      
+      kwl.add( prefix,
+               key.c_str(),
+               m_options[i].c_str(),
+               true );
+   }
+   
+   return true;
+}
+
+bool ossimOpjCompressor::loadState(const ossimKeywordlist& kwl,
+                                      const char* prefix)
+{
+   const char* value = 0;
+
+   value = kwl.find(prefix, ossimKeywordNames::COMPRESSION_QUALITY_KW);
+   if(value)
+   {
+      setQualityTypeString( ossimString(value) );
+   }
+   
+   value = kwl.find(prefix, LEVELS_KW);
+   if(value)
+   {
+      m_levels = ossimString(value).toInt32();
+   }
+   
+   value = kwl.find(prefix, REVERSIBLE_KW);
+   if(value)
+   {
+      setReversibleFlag(ossimString(value).toBool());
+   }
+
+   value = kwl.find(prefix, ADD_ALPHA_CHANNEL_KW);
+   if(value)
+   {
+      m_alpha = ossimString(value).toBool();
+   }
+   
+   value = kwl.find(prefix, THREADS_KW);
+   if(value)
+   {
+      m_threads = ossimString(value).toInt32();
+   }
+
+   ossimString searchKey;
+   if (prefix)
+   {
+      searchKey = prefix;
+   }
+   searchKey += "option";
+   ossim_uint32 nOptions = kwl.numberOf(searchKey);
+   for (ossim_uint32 i = 0; i < nOptions; ++i)
+   {
+      ossimString key = searchKey;
+      key += ossimString::toString(i);
+      
+      const char* lookup = kwl.find(key.c_str());
+      if (lookup)
+      {
+         m_options.push_back(ossimString(lookup));
+      }
+   }
+   
+   return true;
+}
+
+bool ossimOpjCompressor::writeGeotiffBox(std::ostream* stream,
+                                         const ossimImageGeometry* geom,
+                                         const ossimIrect& rect,
+                                         const ossimFilename& tmpFile,
+                                         ossimPixelType pixelType)
+{
+   // cout << "ossimOpjCompressor::writeGeotiffBox entered..." << endl;
+   
+   
+   bool result = false;
+
+   if ( stream && geom )
+   {
+      ossimRefPtr<const ossimImageGeometry> imgGeom = geom;
+      ossimRefPtr<const ossimProjection> proj = imgGeom->getProjection();
+      if ( proj.valid() )
+      {
+         //---
+         // Make a temp file.  No means currently write a tiff straight to
+         // memory.
+         //---
+         
+         // Buffer to hold the tiff box.
+         std::vector<ossim_uint8> buf;
+         
+         // Write to buffer.
+         if ( ossimGeoTiff::writeJp2GeotiffBox(tmpFile,
+                                               rect,
+                                               proj.get(),
+                                               buf,
+                                               pixelType) )
+         {
+            //---
+            // JP2 box type uuid in ascii expressed as an int.
+            // "u(75), u(75), i(69), d(64)"
+            //---
+            const ossim_uint8 UUID[4] = 
+            {
+               0x75, 0x75, 0x69, 0x64
+            };
+
+            ossim_uint32 lbox = buf.size() + 8;
+
+            // cout << "gbox tellp: " << stream->tellp() << endl;
+            // cout << "lbox: " << lbox << endl;
+            
+            if (ossim::byteOrder() == OSSIM_LITTLE_ENDIAN)
+            {
+               ossimEndian endian;
+               endian.swap( lbox );
+            }
+            
+            stream->write( (char*)&lbox, 4 ); // LBox
+            
+            stream->write((const char*)UUID, 4); // TBox
+
+            // DBox: geotiff
+            stream->write((const char*)&buf.front(), (std::streamsize)buf.size());
+
+            result = true;
+
+            // cout << "wrote box!!!" << endl;
+         }
+      }
+   }
+   
+   return result;
+   
+} // End: ossimOpjCompressor::writeGeotiffBox
+
+bool ossimOpjCompressor::writeGmlBox(std::ostream* stream,
+                                     const ossimImageGeometry* geom,
+                                     const ossimIrect& /* rect */,
+                                     ossimPixelType /* pixelType */)
+{
+   // cout << "ossimOpjCompressor::writeGmlBox entered..." << endl;
+   
+   bool result = false;
+
+   if ( stream && geom )
+   {
+      ossimGmlSupportData* gml = new ossimGmlSupportData();
+
+      if ( gml->initialize( geom ) )  
+      {
+         const ossim_uint8 ASOC_BOX_ID[4] = 
+         {
+            0x61, 0x73, 0x6F, 0x63
+         };
+
+         const ossim_uint8 LBL_BOX_ID[4] = 
+         {
+             0x6C, 0x62, 0x6C, 0x20
+         };
+
+         const ossim_uint8 XML_BOX_ID[4] = 
+         {
+            0x78, 0x6D, 0x6C, 0x20
+         };
+         
+         // Write the xml to a stream.
+         ostringstream xmlStr;
+         if ( gml->write( xmlStr ) )
+         {
+             ossim_uint32 xmlDataSize = xmlStr.str().size();
+
+            // Set the 1st asoc box size and type
+            ossim_uint32 boxSize = xmlDataSize + 17 + 8 + 8 + 8 + 8 + 8 + 8;
+            if (ossim::byteOrder() == OSSIM_LITTLE_ENDIAN)
+            {
+               ossimEndian endian;
+               endian.swap( boxSize );
+            }
+            stream->write((char*)&boxSize, 4); // 1st asoc size
+            stream->write((const char*)ASOC_BOX_ID, 4); // 1st asoc type
+
+            // Set the 1st lbl box size, type, and data
+            boxSize = 8 + 8;
+            if (ossim::byteOrder() == OSSIM_LITTLE_ENDIAN)
+            {
+                ossimEndian endian;
+                endian.swap( boxSize );
+            }
+            stream->write((char*)&boxSize, 4); // 1st lbl size
+            stream->write((const char*)LBL_BOX_ID, 4); // 1st lbl type
+            stream->write("gml.data", 8); // 1st lbl data
+
+            // Set the 2nd asoc box size and type
+            boxSize = xmlDataSize + 17 + 8 + 8 + 8;
+            if (ossim::byteOrder() == OSSIM_LITTLE_ENDIAN)
+            {
+                ossimEndian endian;
+                endian.swap( boxSize );
+            }
+            stream->write((char*)&boxSize, 4); // 2nd asoc size
+            stream->write((const char*)ASOC_BOX_ID, 4); // 2nd asoc type
+
+            // Set the 2nd lbl box size, type, and data
+            boxSize = 17 + 8;
+            if (ossim::byteOrder() == OSSIM_LITTLE_ENDIAN)
+            {
+                ossimEndian endian;
+                endian.swap( boxSize );
+            }
+            stream->write((char*)&boxSize, 4); // 2nd lbl size
+            stream->write((const char*)LBL_BOX_ID, 4); // 2nd lbl type
+            stream->write("gml.root-instance", 17); // 2nd lbl data
+
+            // Set the xml box size, type, and data
+            boxSize = xmlDataSize + 8;
+            if (ossim::byteOrder() == OSSIM_LITTLE_ENDIAN)
+            {
+                ossimEndian endian;
+                endian.swap( boxSize );
+            }
+            stream->write((char*)&boxSize, 4); // xml size
+            stream->write((const char*)XML_BOX_ID, 4); // xml type
+            stream->write(xmlStr.str().data(), xmlDataSize); // xml data
+            
+            result = true;
+         
+            //cout << "wrote gml box!!!" << endl;
+         }
+      }
+
+      // cleanup:
+      delete gml;
+      gml = 0;
+   }
+   
+   return result;
+   
+} // End: ossimOpjCompressor::writeGmlBox
+
+void ossimOpjCompressor::initOpjCodingParams( bool jp2,
+                                              const ossimIpt& tileSize,
+                                              const ossimIrect& imageRect )
+{
+   static const char MODULE[] = "ossimOpjCompressor::initOpjCodingParams";
+   if ( traceDebug() )
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " entered...\n";
+   }
+
+   if ( m_params )
+   {
+      delete m_params;
+   }
+
+   m_params = new opj_cparameters_t();
+
+   // Set encoding parameters to default values.
+   opj_set_default_encoder_parameters( m_params );
+   
+   // Output format: 0: J2K, 1: JP2, 2: JPT   
+   m_params->cod_format = jp2 ? 1 : 0;
+      
+   // std::string outfile = "test.jp2";
+   // strncpy(m_params->outfile, outfile.data(), outfile.size());
+
+   //---
+   // Shall we do an Multi-component Transformation(MCT) ?
+   // 0:no_mct;1:rgb->ycc;2:custom mct
+   //---
+
+   // Set the tiles size:
+   m_params->cp_tx0 = 0;
+   m_params->cp_ty0 = 0;
+   m_params->cp_tdx = tileSize.x;
+   m_params->cp_tdy = tileSize.y;
+   m_params->tile_size_on = OPJ_TRUE;
+   
+   // No mct.
+   m_params->tcp_mct = 0;
+
+   //---
+   // Number of resolutions:
+   // This sets m_levels if not set and
+   // m_params->numresolution.
+   //---
+   initLevels( imageRect );
+      
+   // Set the block size.  Note 64x64 is the current kakadu default.
+   setCodeBlockSize( 64, 64 );
+      
+   //---
+   // Set progression order to use. Note LRCP is the current opj default.
+   // L=layer; R=resolution C=component; P=position
+   // 
+   // OPJ_LRCP, OPJ_RLCP, OPJ_RPCL, PCRL, CPRL */
+   //---
+   setProgressionOrder( OPJ_LRCP );
+      
+   // total pixels
+   const ossim_float64 TP = imageRect.area();
+      
+   if ( traceDebug() )
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "quality type: " << getQualityTypeString() << endl;
+   }
+      
+   //---
+   // Rate is a ratio of desired bytes / total bytes.  So if you
+   // want 4 bits per pixels it's total_pixels * 4 / 8 or
+   // total_pixels * 4 * 0.125.
+   //---
+      
+   // Allocation by rate/distortion.
+   m_params->cp_disto_alloc = 1;
+      
+   switch (m_qualityType)
+   {
+      case ossimOpjCompressor::OPJ_NUMERICALLY_LOSSLESS:
+      {
+         // cout << "ossimOpjCompressor::OPJ_NUMERICALLY_LOSSLESS..." << endl;
+         
+         // W5X3 Kernel
+         setReversibleFlag(true);
+
+         // Tmp drb...
+         m_params->tcp_numlayers = 1;
+         m_params->tcp_rates[0] = 1;
+
+#if 0
+            
+         m_params->tcp_numlayers = 20;
+            
+         m_params->tcp_rates[0] = std::ceil( TP * 0.03125 * 0.125 );
+         m_params->tcp_rates[1] = std::ceil( TP * 0.0625 * 0.125 );
+         m_params->tcp_rates[2] = std::ceil( TP * 0.125 * 0.125 );
+         m_params->tcp_rates[3] = std::ceil( TP * 0.25 * 0.125 );
+         m_params->tcp_rates[4] = std::ceil( TP * 0.5 * 0.125 );
+         m_params->tcp_rates[5] = std::ceil( TP * 0.6 * 0.125 );
+         m_params->tcp_rates[6] = std::ceil( TP * 0.7 * 0.125 );
+         m_params->tcp_rates[7] = std::ceil( TP * 0.8 * 0.125 );
+         m_params->tcp_rates[8] = std::ceil( TP * 0.9 * 0.125 );
+         m_params->tcp_rates[9] = std::ceil( TP * 1.0 * 0.125 );
+         m_params->tcp_rates[10] = std::ceil( TP * 1.1 * 0.125 );
+         m_params->tcp_rates[11] = std::ceil( TP * 1.2 * 0.125 );
+         m_params->tcp_rates[12] = std::ceil( TP * 1.3 * 0.125 );
+         m_params->tcp_rates[13] = std::ceil( TP * 1.5 * 0.125 );
+         m_params->tcp_rates[14] = std::ceil( TP * 1.7 * 0.125 );
+         m_params->tcp_rates[15] = std::ceil( TP * 2.0 * 0.125 );
+         m_params->tcp_rates[16] = std::ceil( TP * 2.3 * 0.125 );
+         m_params->tcp_rates[17] = std::ceil( TP * 2.8 * 0.125 );
+         m_params->tcp_rates[18] = std::ceil( TP * 3.5 * 0.125 );
+            
+         //---
+         // Indicate that the final quality layer should include all
+         // compressed bits.
+         //---
+         // m_params->tcp_rates[19] = OSSIM_DEFAULT_MAX_PIX_SINT32; // KDU_LONG_MAX;
+         m_params->tcp_rates[19] = std::ceil( TP * 4.0 * 0.125 );
+
+#endif
+         
+         break;
+      }
+      case ossimOpjCompressor::OPJ_VISUALLY_LOSSLESS:
+      {
+         // W9X7 kernel:
+         setReversibleFlag(false);
+            
+         m_params->tcp_numlayers = 19;
+            
+         m_params->tcp_rates[0] = std::ceil( TP * 0.03125 * 0.125 );
+         m_params->tcp_rates[1] = std::ceil( TP * 0.0625 * 0.125 );
+         m_params->tcp_rates[2] = std::ceil( TP * 0.125 * 0.125 );
+         m_params->tcp_rates[3] = std::ceil( TP * 0.25 * 0.125 );
+         m_params->tcp_rates[4] = std::ceil( TP * 0.5 * 0.125 );
+         m_params->tcp_rates[5] = std::ceil( TP * 0.6 * 0.125 );
+         m_params->tcp_rates[6] = std::ceil( TP * 0.7 * 0.125 );
+         m_params->tcp_rates[7] = std::ceil( TP * 0.8 * 0.125 );
+         m_params->tcp_rates[8] = std::ceil( TP * 0.9 * 0.125 );
+         m_params->tcp_rates[9] = std::ceil( TP * 1.0 * 0.125 );
+         m_params->tcp_rates[10] = std::ceil( TP * 1.1 * 0.125 );
+         m_params->tcp_rates[11] = std::ceil( TP * 1.2 * 0.125 );
+         m_params->tcp_rates[12] = std::ceil( TP * 1.3 * 0.125 );
+         m_params->tcp_rates[13] = std::ceil( TP * 1.5 * 0.125 );
+         m_params->tcp_rates[14] = std::ceil( TP * 1.7 * 0.125 );
+         m_params->tcp_rates[15] = std::ceil( TP * 2.0 * 0.125 );
+         m_params->tcp_rates[16] = std::ceil( TP * 2.3 * 0.125 );
+         m_params->tcp_rates[17] = std::ceil( TP * 2.8 * 0.125 );
+         m_params->tcp_rates[18] = std::ceil( TP * 3.5 * 0.125 );
+         break;
+      }
+      case ossimOpjCompressor::OPJ_LOSSY:
+      {
+         // W9X7 kernel:
+         setReversibleFlag(false);
+            
+         m_params->tcp_numlayers = 10;
+            
+         m_params->tcp_rates[0] = std::ceil( TP * 0.03125 * 0.125 );
+         m_params->tcp_rates[1] = std::ceil( TP * 0.0625 * 0.125 );
+         m_params->tcp_rates[2] = std::ceil( TP * 0.125 * 0.125 );
+         m_params->tcp_rates[3] = std::ceil( TP * 0.25 * 0.125 );
+         m_params->tcp_rates[4] = std::ceil( TP * 0.5 * 0.125 );
+         m_params->tcp_rates[5] = std::ceil( TP * 0.6 * 0.125 );
+         m_params->tcp_rates[6] = std::ceil( TP * 0.7 * 0.125 );
+         m_params->tcp_rates[7] = std::ceil( TP * 0.8 * 0.125 );
+         m_params->tcp_rates[8] = std::ceil( TP * 0.9 * 0.125 );
+         m_params->tcp_rates[9] = std::ceil( TP * 1.0 * 0.125 );
+         break;
+      }
+         
+      default:
+      {
+         m_params->tcp_numlayers = 1;
+         m_params->tcp_rates[0] = 1.0;
+            
+         if (traceDebug())
+         {
+            ossimNotify(ossimNotifyLevel_WARN)
+               << "unspecified quality type\n";
+         }
+      }
+         
+   } // matches: switch (m_qualityType)
+
+
+   
+   //---
+   // Set reversible flag, note, this controls the kernel.
+   // W5X3(default) if reversible = true, W9X7 if reversible is false.
+   //---
+   m_params->irreversible = !m_reversible;
+   
+   if ( traceDebug() )
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "m_reversible: " << m_reversible
+         << "\nm_levels: " << m_levels << "\n";
+
+      ossim::print( ossimNotify(ossimNotifyLevel_DEBUG), *m_params );
+   }
+      
+   if ( traceDebug() )
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " exited...\n";
+   }
+}
+
+int ossimOpjCompressor::getNumberOfLayers() const
+{
+   return m_params->tcp_numlayers;
+}
+
+ossimString ossimOpjCompressor::getQualityTypeString() const
+{
+   return COMPRESSION_QUALITY[m_qualityType];
+}
+
+void ossimOpjCompressor::setQualityTypeString(const ossimString& s)
+{
+   ossimString type = s;
+   type.downcase();
+   
+   if ( type == COMPRESSION_QUALITY[ossimOpjCompressor::OPJ_UNKNOWN] )
+   {
+      setQualityType(ossimOpjCompressor::OPJ_UNKNOWN);
+   }
+   else if ( type == COMPRESSION_QUALITY[ossimOpjCompressor::OPJ_USER_DEFINED] )
+   {
+      setQualityType(ossimOpjCompressor::OPJ_USER_DEFINED);
+   }
+   else if ( type == COMPRESSION_QUALITY[ossimOpjCompressor::OPJ_NUMERICALLY_LOSSLESS] )
+   {
+      setQualityType(ossimOpjCompressor::OPJ_NUMERICALLY_LOSSLESS);
+   }
+   else if ( type == COMPRESSION_QUALITY[ossimOpjCompressor::OPJ_VISUALLY_LOSSLESS] )
+   {
+      setQualityType(ossimOpjCompressor::OPJ_VISUALLY_LOSSLESS);
+   }
+   else if (type == "lossy")
+   {
+      setQualityType(ossimOpjCompressor::OPJ_LOSSY);
+   }
+   else
+   {
+      if ( traceDebug() )
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG)
+            << "ossimOpjCompressor::setQualityTypeString DEBUG"
+            << "\nUnhandled quality type: " << type
+            << std::endl;
+      }
+   }
+}
+
+void ossimOpjCompressor::initLevels( const ossimIrect& imageRect )
+{
+   //---
+   // Number of wavelet decomposition levels, or stages.  May not exceed 32.
+   // Default is 6 (r0 - r5)
+   //---
+   if ( m_levels == 0 )
+   {
+      m_levels = (ossim_int32)ossim::computeLevels(imageRect);
+      if (m_levels == 0)
+      {
+         m_levels = 1; // Must have at least one.
+      }
+   }
+   if ( (m_levels < 1) || (m_levels > 32) )
+   {
+      m_levels = 6;
+   }
+
+   m_params->numresolution = m_levels;
+}
+
+void ossimOpjCompressor::setCodeBlockSize( ossim_int32 xSize,
+                                           ossim_int32 ySize )
+{
+   if ( m_params )
+   {
+      //---
+      // Nominal code-block dimensions (must be powers of 2 no less than 4 and
+      // no greater than 1024).
+      // Default block dimensions are {64,64}
+      //---
+      m_params->cblockw_init = xSize;
+      m_params->cblockh_init = ySize;
+   }
+}
+
+void ossimOpjCompressor::setProgressionOrder( OPJ_PROG_ORDER progressionOrder )
+{
+   if ( m_params )
+   {
+      //---
+      // Default progression order (may be overridden by Porder).
+      // The four character identifiers have the following interpretation:
+      // L=layer; R=resolution; C=component; P=position.
+      // The first character in the identifier refers to the index which
+      // progresses most slowly, while the last refers to the index which
+      // progresses most quickly.  [Default is LRCP]
+      // Enumerations:  (LRCP=0,RLCP=1,RPCL=2,PCRL=3,CPRL=4)
+      //---
+      m_params->prog_order = progressionOrder;
+   }
+}
+ 
+void ossimOpjCompressor::setTlmTileCount(ossim_uint32 /* tilesToWrite */)
+{
+   //---
+   // Identifies the maximum number of tile-parts which will be written to the
+   // code-stream for each tile.
+   //
+   // See Opj kdu_params.h "Macro = `ORGgen_tlm'" for more.
+   //---
+   // ossimString s = "ORGgen_tlm=1";
+   // m_codestream.access_siz()->parse_string( s.c_str() );
+}
+
+opj_codec_t* ossimOpjCompressor::createOpjCodec( bool jp2 ) const
+{
+   opj_codec_t* codec = 0;
+   if ( jp2 )
+   {
+      codec = opj_create_compress(OPJ_CODEC_JP2);
+   }
+   else
+   {
+      codec = opj_create_compress(OPJ_CODEC_J2K);
+   }
+
+   if ( codec )
+   {
+      // Catch events using our callbacks and give a local context.
+      opj_set_info_handler   (codec, ossim::opj_info_callback,   00);
+      opj_set_warning_handler(codec, ossim::opj_warning_callback,00);
+      opj_set_error_handler  (codec, ossim::opj_error_callback,  00);
+   }
+   return codec;
+   
+} // End: opj_codec_t* createOpjCodec()
+
+opj_stream_t* ossimOpjCompressor::createOpjStream( std::ostream* os ) const
+{
+   opj_stream_t* stream = 0;
+   if ( os )
+   {
+      // stream = opj_stream_create_default_file_stream("test.jp2", OPJ_FALSE);
+   
+ 
+      // OPJ stream:
+      // stream = opj_stream_create(OPJ_J2K_STREAM_CHUNK_SIZE, OPJ_FALSE);
+      // stream = opj_stream_create(512, OPJ_FALSE);      
+      // stream = opj_stream_create_default_file_stream("test.jp2", OPJ_FALSE); // false = output.
+      stream = opj_stream_create(1048576, OPJ_FALSE);
+      if ( stream )
+      {
+         // cout << "stream good..." << endl;
+         
+         // Set OPJ user stream:
+         opj_stream_set_user_data(stream, os, ossim_opj_free_user_ostream_data);        
+         
+         // Set callbacks:
+         // opj_stream_set_read_function(m_stream, ossim_opj_stream_read);
+         // opj_stream_set_read_function(stream, ossim_opj_imagedata_read);
+         opj_stream_set_write_function(stream, ossim_opj_ostream_write);
+         opj_stream_set_skip_function(stream,  ossim_opj_ostream_skip);
+         opj_stream_set_seek_function(stream,  ossim_opj_ostream_seek);
+      }
+   }
+   return stream;
+
+} // End: ossimOpjCompressor::createOpjStream()
+
+opj_image_t* ossimOpjCompressor::createOpjImage( ossimScalarType scalar,
+                                                 ossim_uint32 bands,
+                                                 const ossimIrect& imageRect ) const
+{
+   opj_image_t* image = 0;
+
+   // image component definitions:
+   opj_image_cmptparm_t* imageParams = new opj_image_cmptparm_t[bands];	
+   opj_image_cmptparm_t* imageParam = imageParams;
+   for (ossim_uint32 i = 0; i < bands; ++i)
+   {
+      imageParam->dx = 1;
+      imageParam->dy = 1;
+      imageParam->h = imageRect.height();
+      imageParam->w = imageRect.width();
+      imageParam->sgnd = (OPJ_UINT32)ossim::isSigned(scalar);
+      imageParam->prec = ossim::getActualBitsPerPixel(scalar);
+      imageParam->bpp = ossim::getBitsPerPixel(scalar);
+      imageParam->x0 = 0;
+      imageParam->y0 = 0;
+      ++imageParam;
+   }
+   
+   OPJ_COLOR_SPACE clrspc;
+   if ( bands == 3 )
+   {
+      clrspc = OPJ_CLRSPC_SRGB;
+   }
+   else //  if ( bands == 1 )
+   {
+      // Anything other than 3 band.  Not sure if this is correct way yet?(drb)
+      clrspc = OPJ_CLRSPC_GRAY;
+   }
+
+   if ( clrspc != OPJ_CLRSPC_UNKNOWN )
+   {
+      image = opj_image_tile_create( bands, imageParams, clrspc );
+      if ( image )
+      {
+         image->x0 = 0;
+         image->y0 = 0;
+         image->x1 = imageRect.width();
+         image->y1 = imageRect.height();
+         image->color_space = clrspc;
+      }
+   }
+
+   delete [] imageParams;
+   imageParams = 0;
+   
+   if ( traceDebug() )
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimOpjCompressor::createOpjImage DEBUG:\n";
+      if ( image )
+      {
+         ossim::print( ossimNotify(ossimNotifyLevel_DEBUG), *image );
+      }
+      else
+      {
+         ossimNotify(ossimNotifyLevel_WARN)
+            << "ossimOpjCompressor::createOpjImage DEBUG image not created!"
+            << std::endl;
+      }
+   }
+   
+   return image;
+   
+} // End: ossimOpjCompressor::createOpjImage( ... )
+
diff --git a/ossim_plugins/openjpeg/ossimOpjCompressor.h b/ossim_plugins/openjpeg/ossimOpjCompressor.h
new file mode 100644
index 0000000..5441c20
--- /dev/null
+++ b/ossim_plugins/openjpeg/ossimOpjCompressor.h
@@ -0,0 +1,330 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Description: Wrapper class to compress whole tiles using OpenJPEG code.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef ossimOpjCompressor_HEADER
+#define ossimOpjCompressor_HEADER 1
+
+#include <ossim/base/ossimConstants.h>
+#include <ossim/base/ossimIrect.h>
+#include <ossim/base/ossimProperty.h>
+#include <ossim/base/ossimRefPtr.h>
+#include <ossim/base/ossimString.h>
+#include <opj_config.h>
+#include <openjpeg.h>
+#include <iosfwd>
+
+class ossimFilename;
+class ossimImageData;
+class ossimImageGeometry;
+class ossimIpt;
+
+class ossimOpjCompressor
+{
+public:
+
+   // Matches static "COMPRESSION_QUALITY" string array in .cpp.
+   enum ossimOpjCompressionQuality
+   {
+      OPJ_UNKNOWN              = 0,
+      OPJ_USER_DEFINED         = 1,
+      OPJ_NUMERICALLY_LOSSLESS = 2,
+      OPJ_VISUALLY_LOSSLESS    = 3,
+      OPJ_LOSSY                = 4
+   };
+   
+   /** default constructor */
+   ossimOpjCompressor();
+   
+   /** destructor */
+   ~ossimOpjCompressor();
+   
+   /**
+    * @brief Create method.
+    * @param os Stream to write to.
+    * @param scalar Scalar type of source tiles to be fed to compressor.
+    * @param bands Number of bands in source tiles to be fed to compressor.
+    * @param imageRect The image rectangle.
+    * @param tileSize The size of a tile.
+    * @param jp2 If true jp2 header and jp2 geotiff block will be written out.
+    * @note Throws ossimException on error.
+    */
+   void create(std::ostream* os,
+               ossimScalarType scalar,
+               ossim_uint32 bands,
+               const ossimIrect& imageRect,
+               const ossimIpt& tileSize,
+               bool jp2);
+   
+   /**
+    * @brief Calls "open_codestream" on the m_jp2Target.
+    *
+    * Note: Only valid if create method was called with jp2 = true.
+    */
+   void openJp2Codestream();
+   
+   /**
+    * @brief Write tile method.
+    *
+    * Writes tiles stream provided to create method.  Note that tiles should
+    * be fed to compressor in left to right, top to bottom order.
+    * 
+    * @param srcTile The source tile to write.
+    * @param tileIndex Index starting at 0.  Currently must be sequential.
+    * @return true on success, false on error.
+    */
+   bool writeTile(ossimImageData* srcTile, ossim_uint32 tileIndex);
+
+   /**
+    * @brief Finish method.  Every call to "create" should be matched by a
+    * "finish".  Note the destructor calls finish.
+    */
+   void finish();
+   
+   /**
+    * @brief Sets the quality type.
+    * @param type See enumeration for types.
+    */
+   void setQualityType(ossimOpjCompressionQuality type);
+   
+   /** @return The quality type setting. */
+   ossimOpjCompressionQuality getQualityType() const;
+   
+   /**
+    * @brief Sets the m_reversible flag.
+    *
+    * If set to true the compression will be lossless; if not, lossy.
+    * Default is lossless.
+    * 
+    * @param reversible Flag to set.
+    */
+   void setReversibleFlag(bool reversible);
+   
+   /** @return The reversible flag. */
+   bool getReversibleFlag() const;
+   
+   /**
+    * Set the writer to add an alpha channel to the output png image.
+    *
+    * @param flag true to create an alpha channel.
+    */
+   void setAlphaChannelFlag( bool flag );
+
+   /**
+    * Retrieve the writer's setting for whether or not to add an 
+    * alpha channel to the output png image.
+    *
+    * @return true if the writer is configured to create an alpha channel.
+    */
+   bool getAlphaChannelFlag() const;
+
+   /**
+    * @brief Sets the number of levels.
+    *
+    * This must be positive and at least 1.
+    * Default = 6 ( r0 - r5 )
+    *
+    * @param levels Levels to set.
+    */
+   void setLevels(ossim_int32 levels);
+
+   /** @return The number of levels. */
+   ossim_int32 getLevels() const;
+   
+    /**
+    * @brief Sets the number of threads.
+    *
+    * This must be positive and at least 1.  Default = 1 thread.
+    *
+    * @param threads The number of threads.
+    */
+   void setThreads(ossim_int32 threads);
+
+   /** @return The number of threads. */
+   ossim_int32 getThreads() const;
+
+   /**
+    * @brief Sets the options array.
+    *
+    * These get passed to the generic kdu_params::parse_string method.  Note
+    * this adds options to the list.  Does not zero out existing options.
+    *
+    * @param options Array of options to add.
+    */
+   void setOptions(const std::vector<ossimString>& options);
+   
+   /**
+    * @brief Get the array of options.
+    * @param options Array to initialize.
+    */
+   void getOptions(std::vector<ossimString>& options) const;
+  
+   /**
+    * saves the state of the object.
+    */
+   bool saveState(ossimKeywordlist& kwl, const char* prefix=0)const;
+   
+   /**
+    * Method to the load (recreate) the state of an object from a keyword
+    * list.  Return true if ok or false on error.
+    */
+   bool loadState(const ossimKeywordlist& kwl, const char* prefix=0);
+   
+   /**
+    * Will set the property whose name matches the argument
+    * "property->getName()".
+    *
+    * @param property Object containing property to set.
+    *
+    * @return true if property was consumed, false if not.
+    */
+   bool setProperty(ossimRefPtr<ossimProperty> property);
+   
+   /**
+    * @param name Name of property to return.
+    * 
+    * @returns A pointer to a property object which matches "name".
+    */
+   ossimRefPtr<ossimProperty> getProperty(const ossimString& name)const;
+   
+   /**
+    * Pushes this's names onto the list of property names.
+    *
+    * @param propertyNames array to add this's property names to.
+    */
+   void getPropertyNames(std::vector<ossimString>& propertyNames)const;
+
+   /**
+    * @brief Writes the geotiff box to the jp2
+    * @param stream The stream to write to.
+    * @param geom Output image geometry.
+    * @param rect Output rectangle (view rect).
+    * @param tmpFile Temp file written out.
+    * @param pixelType OSSIM_PIXEL_IS_POINT(0) or OSSIM_PIXEL_IS_AREA(1)
+    */
+   bool writeGeotiffBox(std::ostream* stream,
+                        const ossimImageGeometry* geom,
+                        const ossimIrect& rect,
+                        const ossimFilename& tmpFile,
+                        ossimPixelType pixelType);
+   
+   /**
+    * @brief Writes the gml box to the jp2
+    * @param stream The stream to write to.
+    * @param geom Output image geometry.
+    * @param rect Output rectangle (view rect).
+    * @param pixelType OSSIM_PIXEL_IS_POINT(0) or OSSIM_PIXEL_IS_AREA(1)
+    */
+   bool writeGmlBox(std::ostream* stream,
+                    const ossimImageGeometry* geom,
+                    const ossimIrect& rect,
+                    ossimPixelType pixelType);
+   
+private:
+
+   void initOpjCodingParams( bool jp2,
+                             const ossimIpt& tileSize,
+                             const ossimIrect& imageRect );
+   
+   int  getNumberOfLayers() const;
+
+   ossimString getQualityTypeString() const;
+   void setQualityTypeString(const ossimString& s);
+
+   /**
+    * @brief Set levels, class attribute m_levels and
+    * m_parameters->numresolution.
+    *
+    * Number of wavelet decomposition levels, or stages.  May not exceed 32.
+    * Opj Default is 6 (0 - 5)
+    *
+    * @param imageRect The image rectangle.
+    */
+   void initLevels( const ossimIrect& imageRect );
+
+   /**
+    * @brief Set code block size.
+    *
+    * Nominal code-block dimensions (must be powers of 2 no less than 4 and
+    * no greater than 1024).
+    * Opj Default block dimensions are {64,64}
+    *
+    * @param xSize
+    * @param ySize
+    */   
+   void setCodeBlockSize( ossim_int32 xSize, ossim_int32 ySize);
+
+   /**
+    * @brief Sets progression order.
+    *
+    * Default progression order (may be overridden by Porder).
+    * The four character identifiers have the following interpretation:
+    * L=layer; R=resolution; C=component; P=position.
+    * The first character in the identifier refers to the index which
+    * progresses most slowly, while the last refers to the index which
+    * progresses most quickly.  [Default is LRCP]
+    * Enumerations:  (LRCP=0,RLCP=1,RPCL=2,PCRL=3,CPRL=4) 
+    *
+    * @param corder The progression order which should be one of the above
+    * enumerations.
+    */   
+   void setProgressionOrder( OPJ_PROG_ORDER progressionOrder );
+
+   void setTlmTileCount(ossim_uint32 tilesToWrite);
+
+   opj_cparameters_t* createOpjCodingParameters(
+      bool jp2,
+      const ossimIpt& tileSize,
+      const ossimIrect& imageRect ) const;
+   
+   opj_codec_t* createOpjCodec( bool jp2 ) const;
+
+   opj_stream_t* createOpjStream( std::ostream* os ) const;
+   
+   opj_image_t* createOpjImage( ossimScalarType scalar,
+                                ossim_uint32 bands,
+                                const ossimIrect& imageRect ) const;
+
+   opj_cparameters_t* m_params;
+   opj_codec_t*       m_codec;
+   opj_stream_t*      m_stream;
+   
+   opj_image_t*       m_image;
+   
+   
+   // opj_codec* m_stream;
+   // opj_image_t* m_image = 0;
+
+   
+   /** Image rectangle.  Used for clip in writeTile. */
+   ossimIrect                   m_imageRect;
+
+   /** Lossless or lossy */
+   bool                         m_reversible;
+
+   /** If true write alpha channel. */
+   bool                         m_alpha;
+
+   /** Reduced resolution levels. */
+   ossim_int32                  m_levels;
+
+   /** Number of threads. */
+   ossim_int32                  m_threads;
+
+   /** Container for Opj options. */
+   std::vector<ossimString> m_options;
+
+   ossimOpjCompressionQuality m_qualityType;
+   
+};
+
+#endif /* matches: #ifndef ossimOpjCompressor_HEADER */
+ 
+
diff --git a/ossim_plugins/openjpeg/ossimOpjJp2Reader.cpp b/ossim_plugins/openjpeg/ossimOpjJp2Reader.cpp
new file mode 100644
index 0000000..66c0136
--- /dev/null
+++ b/ossim_plugins/openjpeg/ossimOpjJp2Reader.cpp
@@ -0,0 +1,1012 @@
+//----------------------------------------------------------------------------
+//
+// License:  See top level LICENSE.txt file
+//
+// Author:  David Burken
+//
+// Description: OSSIM Open JPEG JP2 reader (tile source).
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include <ossimOpjJp2Reader.h>
+#include <ossimOpjCommon.h>
+
+#include <ossim/base/ossimCommon.h>
+#include <ossim/base/ossimConstants.h>
+#include <ossim/base/ossimDpt.h>
+#include <ossim/base/ossimEndian.h>
+#include <ossim/base/ossimException.h>
+#include <ossim/base/ossimFilename.h>
+#include <ossim/base/ossimIpt.h>
+#include <ossim/base/ossimIrect.h>
+#include <ossim/base/ossimKeywordlist.h>
+#include <ossim/base/ossimKeywordNames.h>
+#include <ossim/base/ossimNotifyContext.h>
+#include <ossim/base/ossimTrace.h>
+#include <ossim/base/ossimUnitConversionTool.h>
+
+#include <ossim/imaging/ossimImageDataFactory.h>
+#include <ossim/imaging/ossimImageGeometryRegistry.h>
+#include <ossim/imaging/ossimTiffTileSource.h>
+#include <ossim/imaging/ossimU8ImageData.h>
+
+#include <ossim/projection/ossimMapProjection.h>
+#include <ossim/projection/ossimProjection.h>
+#include <ossim/projection/ossimProjectionFactoryRegistry.h>
+
+#include <ossim/support_data/ossimFgdcXmlDoc.h>
+#include <ossim/support_data/ossimGmlSupportData.h>
+#include <ossim/support_data/ossimJ2kCodRecord.h>
+#include <ossim/support_data/ossimJp2Info.h>
+#include <ossim/support_data/ossimTiffInfo.h>
+#include <ossim/support_data/ossimTiffWorld.h>
+
+#include <openjpeg.h>
+#include <fstream>
+
+RTTI_DEF1(ossimOpjJp2Reader, "ossimOpjJp2Reader", ossimImageHandler)
+
+#ifdef OSSIM_ID_ENABLED
+   static const char OSSIM_ID[] = "$Id: ossimOpjJp2Reader.cpp 11439 2007-07-29 17:43:24Z dburken $";
+#endif
+   
+static ossimTrace traceDebug(ossimString("ossimOpjJp2Reader:degug"));
+
+static const ossim_uint16 SOC_MARKER = 0xff4f; // start of codestream marker
+static const ossim_uint16 SIZ_MARKER = 0xff51; // size maker
+
+
+ossimOpjJp2Reader::ossimOpjJp2Reader()
+   :
+   ossimImageHandler(),
+   m_sizRecord(),
+   m_tile(0),
+   m_str(0),
+   m_minDwtLevels(0)
+{
+   // Uncomment to enable trace for debug:
+   // traceDebug.setTraceFlag(true); 
+   
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimOpjJp2Reader::ossimOpjJp2Reader entered..." << std::endl;
+#ifdef OSSIM_ID_ENABLED
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "OSSIM_ID:  " << OSSIM_ID << endl;
+#endif
+   }
+}
+
+ossimOpjJp2Reader::~ossimOpjJp2Reader()
+{
+   destroy();
+}
+
+void ossimOpjJp2Reader::destroy()
+{
+   m_tile      = 0;  // ossimRefPtr
+   m_cacheTile = 0;  // ossimRefPtr   
+   
+   if ( m_str )
+   {
+      m_str->close();
+      delete m_str;
+      m_str = 0;
+   }
+}
+
+bool ossimOpjJp2Reader::open()
+{
+   static const char MODULE[] = "ossimOpjJp2Reader::open";
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " entered..."
+         << "\nFile:  " << theImageFile.c_str()
+         << std::endl;
+   }
+
+   bool status = false;
+
+   close();
+
+   if ( theImageFile.size() )
+   {
+      m_str = new std::ifstream();
+      m_str->open( theImageFile.string().c_str(), std::ios_base::in | std::ios_base::binary);
+      
+      if ( m_str->good() )
+      {
+         m_format = ossim::getCodecFormat( m_str );
+
+         if ( m_format != OPJ_CODEC_UNKNOWN )
+         {
+            m_str->seekg(0, ios_base::beg);
+            if ( initSizRecord( m_str, m_sizRecord ) )
+            {
+               ossimJ2kCodRecord codRecord;
+               status = initCodRecord( m_str, codRecord );
+
+               if ( status )
+               {
+                  // Number of built in reduced res sets.
+                  m_minDwtLevels = codRecord.m_numberOfDecompositionLevels;
+
+                  // Put the stream back:
+                  m_str->seekg(0, ios_base::beg);
+
+                  if ( traceDebug() )
+                  {
+                     ossimNotify(ossimNotifyLevel_DEBUG)
+                        << " DEBUG: J2K COD RECORD:\n"
+                        << codRecord
+                        << "\n";
+                  }
+               }
+            }
+         }
+         
+         if ( status && traceDebug() )
+         {
+            ossimNotify(ossimNotifyLevel_DEBUG)
+               << " DEBUG: J2K SIZ RECORD:\n"
+               << m_sizRecord
+               << "\n";
+         }
+      }
+      else if ( traceDebug() )
+      {
+         ossimNotify(ossimNotifyLevel_WARN)
+            << "Cannot open:  " << theImageFile.c_str() << "\n";
+      }
+      
+   }
+
+   if ( !status )
+   {
+      m_str->close();
+      delete m_str;
+      m_str = 0;
+   }
+   
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " exit status " << (status?"true\n":"false\n");
+   }
+   return status;
+}
+
+void ossimOpjJp2Reader::close()
+{
+   destroy();
+   ossimImageHandler::close();   
+}
+
+ossimRefPtr<ossimImageData> ossimOpjJp2Reader::getTile(
+   const ossimIrect& rect, ossim_uint32 resLevel)
+{
+   ossimRefPtr<ossimImageData> result = 0;
+   
+   if( isSourceEnabled() && isOpen() && isValidRLevel(resLevel) )
+   {
+      if ( m_tile.valid() == false )
+      {
+         allocate(); // First time though.
+      }
+
+      // Rectangle must be set prior to getOverviewTile call.
+      m_tile->setImageRectangle(rect);
+
+      // tmp drb...
+      m_tile->makeBlank();
+      
+      if ( getOverviewTile( resLevel, m_tile.get() ) )
+      {
+         result = m_tile.get();
+      }
+   }
+
+   return result;
+}
+
+bool ossimOpjJp2Reader::getOverviewTile(ossim_uint32 resLevel,
+                                        ossimImageData* result)
+{
+   bool status = false;
+
+   if ( result )
+   {
+      if (resLevel <= m_minDwtLevels)
+      {
+         // Using internal overviews.
+         
+         //---
+         // NOTE:
+         //
+         // The geojp2 doqq's that I have all have an offset in them.  In
+         // other words the "pos" from "get_dims" is not always 0,0.  I
+         // think this was intended for mosaicing without any projection. I
+         // do NOT think it was intended to be used as a sub image offset
+         // into the projection picked up by the geotiff_box. If this were
+         // so the current code here would not mosaic correctly.
+         //
+         // This may not be the case though with all data sets...  In which
+         // case some kind of logic would have to be added to this code.
+         
+         ossimIrect tileRect  = result->getImageRectangle();
+         ossimIrect imageRect = getImageRectangle( resLevel );
+         ossimIrect clipRect  = tileRect.clipToRect(imageRect);
+
+         ossimIpt offset((ossim_int32)m_sizRecord.m_XOsiz,
+                         (ossim_int32)m_sizRecord.m_YOsiz);
+
+         // tmp drb...
+         // ossimIrect rect(0,0,255,255);
+
+         ossimIrect shiftedRect = clipRect + offset;
+         if ( traceDebug() )
+         {
+            ossimNotify(ossimNotifyLevel_DEBUG)
+               << "ossimOpjJp2Reader::getOverviewTile DEBUG:"
+               << "\ntile rect:   " << tileRect
+               << "\nimageRect:   " << imageRect
+               << "\nclipRect:    " << clipRect
+               << "\nshiftedRect: " << shiftedRect
+               << "\noffset:      " << offset
+               << "\nresLevel:      " << resLevel
+               << std::endl;
+         }
+
+         m_cacheTile->setImageRectangle( clipRect );
+         
+         try
+         {
+            status = ossim::opj_decode( m_str,
+                                        shiftedRect,
+                                        resLevel,
+                                        m_format,
+                                        0,
+                                        m_cacheTile.get() );
+
+            if ( status )
+            {
+               
+               result->loadTile(m_cacheTile->getBuf(), clipRect,  OSSIM_BSQ);
+               result->validate();
+            }
+         }
+         catch( const ossimException& e )
+         {
+            ossimNotify(ossimNotifyLevel_WARN)
+               << __FILE__ << " " << __LINE__ << " caught exception\n"
+               << e.what() << "\n File:" << this->theImageFile << "\n";
+            status = false;
+         }
+         catch( ... )
+         {
+            ossimNotify(ossimNotifyLevel_WARN)
+               << __FILE__ << " " << __LINE__ << " caught unknown exception\n";
+         }
+            
+         // result->setImageRectangle(originalTileRect);
+         
+         try
+         {
+#if 0
+            if ( theChannels )
+            {
+               status = ossim::copyRegionToTile(theChannels,
+                                                theCodestream,
+                                                static_cast<int>(resLevel),
+                                                theThreadEnv,
+                                                theOpenTileThreadQueue,
+                                                result);
+            }
+            else
+            {
+               status = ossim::copyRegionToTile(theCodestream,
+                                                static_cast<int>(resLevel),
+                                                theThreadEnv,
+                                                theOpenTileThreadQueue,
+                                                result);
+            }
+#endif
+         }
+         catch(const ossimException& e)
+         {
+            ossimNotify(ossimNotifyLevel_WARN)
+               << __FILE__ << " " << __LINE__ << " caught exception\n"
+               << e.what();
+            status = false;
+         }
+         
+         // Set the rect back.
+         // result->setImageRectangle(originalTileRect);
+         
+      }  // matches:  if (resLevel <= theMinDwtLevels)
+      else
+      {
+         // Using external overview.
+         status = theOverview->getTile(result, resLevel);
+      }
+   }
+
+   return status;
+}
+
+ossimIrect
+ossimOpjJp2Reader::getImageRectangle(ossim_uint32 reduced_res_level) const
+{
+   return ossimIrect(0,
+                     0,
+                     getNumberOfSamples(reduced_res_level) - 1,
+                     getNumberOfLines(reduced_res_level)   - 1);
+}
+
+bool ossimOpjJp2Reader::saveState(ossimKeywordlist& kwl,
+                                  const char* prefix) const
+{
+   return ossimImageHandler::saveState(kwl, prefix);
+}
+
+bool ossimOpjJp2Reader::loadState(const ossimKeywordlist& kwl,
+                                  const char* prefix)
+{
+   if (ossimImageHandler::loadState(kwl, prefix))
+   {
+      return open();
+   }
+
+   return false;
+}
+
+ossim_uint32 ossimOpjJp2Reader::getNumberOfDecimationLevels()const
+{
+   ossim_uint32 result = 1; // Add r0
+
+   if (m_minDwtLevels)
+   {
+      //---
+      // Add internal overviews.
+      //---
+      result += m_minDwtLevels;
+   }
+
+   if (theOverview.valid())
+   {
+      //---
+      // Add external overviews.
+      //---
+      result += theOverview->getNumberOfDecimationLevels();
+   }
+
+   return result;
+}
+
+ossim_uint32 ossimOpjJp2Reader::getNumberOfLines( ossim_uint32 resLevel ) const
+{
+   ossim_uint32 result = 0;
+   if ( isValidRLevel(resLevel) )
+   {
+      if (resLevel <= m_minDwtLevels)
+      {
+         result = m_sizRecord.m_Ysiz - m_sizRecord.m_YOsiz;
+         if ( resLevel )
+         {
+            ossim_float32 x = 2.0;
+            ossim_float32 y = resLevel;
+            result = (ossim_uint32) result / std::pow(x, y);
+         }  
+      }
+      else if (theOverview.valid())
+      {
+         result = theOverview->getNumberOfLines(resLevel);
+      }
+   }
+   return result;
+}
+
+ossim_uint32 ossimOpjJp2Reader::getNumberOfSamples( ossim_uint32 resLevel ) const
+{
+   ossim_uint32 result = 0;
+   if ( isValidRLevel(resLevel) )
+   {
+      if (resLevel <= m_minDwtLevels)
+      {
+         result = m_sizRecord.m_Xsiz - m_sizRecord.m_XOsiz;
+         if ( resLevel )
+         {
+            ossim_float32 x = 2.0;
+            ossim_float32 y = resLevel;
+            result = (ossim_uint32) result / std::pow(x, y);
+         }  
+      }
+      else if (theOverview.valid())
+      {
+         result = theOverview->getNumberOfLines(resLevel);
+      }
+   }
+   return result;
+}
+
+//---
+// Use the internal j2k tile size if it's not the same as the image(one BIG tile).
+//---
+ossim_uint32 ossimOpjJp2Reader::getImageTileWidth() const
+{
+   ossim_uint32 result = 0;
+   if ( (m_sizRecord.m_XTsiz - m_sizRecord.m_XTOsiz) < getNumberOfSamples(0) )
+   {
+      result = m_sizRecord.m_XTsiz - m_sizRecord.m_XTOsiz;
+   }
+   return result;
+}
+
+ossim_uint32 ossimOpjJp2Reader::getImageTileHeight() const
+{
+   ossim_uint32 result = 0;
+   if ( (m_sizRecord.m_YTsiz - m_sizRecord.m_YTOsiz) < getNumberOfLines(0) )
+   {
+      result = m_sizRecord.m_YTsiz - m_sizRecord.m_YTOsiz;
+   }
+   return result; 
+}
+
+ossimString ossimOpjJp2Reader::getShortName()const
+{
+   return ossimString("ossim_openjpeg_reader");
+}
+   
+ossimString ossimOpjJp2Reader::getLongName()const
+{
+   return ossimString("ossim open jpeg reader");
+}
+
+ossimString  ossimOpjJp2Reader::getClassName()const
+{
+   return ossimString("ossimOpjJp2Reader");
+}
+
+ossim_uint32 ossimOpjJp2Reader::getNumberOfInputBands() const
+{
+   return m_sizRecord.m_Csiz;
+}
+
+ossim_uint32 ossimOpjJp2Reader::getNumberOfOutputBands()const
+{
+   return m_sizRecord.m_Csiz;
+}
+
+ossimScalarType ossimOpjJp2Reader::getOutputScalarType() const
+{
+   return m_sizRecord.getScalarType();
+}
+
+bool ossimOpjJp2Reader::isOpen()const
+{
+   return m_str ? m_str->is_open() : false;
+}
+
+double ossimOpjJp2Reader::getMaxPixelValue(ossim_uint32 band)const
+{
+   
+   if (m_tile.valid())
+   {
+      return m_tile->getMaxPix(band);
+   }
+   return 255.0;
+}
+
+bool ossimOpjJp2Reader::initSizRecord( std::istream* str,
+                                       ossimJ2kSizRecord& sizRecord ) const
+{
+   bool result = false;
+   
+   if ( str )
+   {
+      if ( str->good() )
+      {
+         // Looking for SOC, SIZ markers: 0xff, 0x4f, 0xff, 0x51
+         const ossim_uint8 AFF = 0xff;
+         const ossim_uint8 A4F = 0x4f;
+         const ossim_uint8 A51 = 0x51;
+
+         union
+         {
+            char c;
+            ossim_uint8 uc;
+         } ct;
+      
+         // Read in the box.
+         while ( str->get( ct.c ) )
+         {
+            if ( ct.uc == AFF ) // Found FF byte.
+            { 
+               if ( str->get( ct.c ) )
+               {
+                  if ( ct.uc ==  A4F ) // Found 4F byte.
+                  {
+                     if ( str->get( ct.c ) )
+                     {
+                        if ( ct.uc ==  AFF ) // Found FF byte.
+                        {
+                           if ( str->get( ct.c ) )
+                           {
+                              if ( ct.uc ==  A51 ) // Found 51 byte.
+                              {
+                                 sizRecord.parseStream( *str );
+                                 result = true;
+                                 break;
+                              }
+                           }
+                        }
+                     }
+                  }
+               }
+            }
+         }
+      }
+   }
+   
+   return result;
+}
+
+bool ossimOpjJp2Reader::initCodRecord( std::istream* str,
+                                       ossimJ2kCodRecord& codRecord ) const
+{
+   bool result = false;
+
+   if ( str )
+   {
+      if ( str->good() )
+      {
+         // Looking for COD marker: 0xff, 0x51
+         const ossim_uint8 AFF = 0xff;
+         const ossim_uint8 A52 = 0x52;
+
+         union
+         {
+            char c;
+            ossim_uint8 uc;
+         } ct;
+      
+         // Read in the box.
+         while ( str->get( ct.c ) )
+         {
+            if ( ct.uc == AFF ) // Found FF byte.
+            { 
+               if ( str->get( ct.c ) )
+               {
+                  if ( ct.uc ==  A52 ) // Found 52 byte.
+                  {
+                     codRecord.parseStream( *str );
+                     result = true;
+                     break;
+                  }
+               }
+            }
+         }
+      }
+   }
+   
+   return result;
+}
+
+ossimRefPtr<ossimImageGeometry> ossimOpjJp2Reader::getImageGeometry()
+{
+   if ( !theGeometry )
+   {
+      //---
+      // Check for external geom - this is a file.geom not to be confused with
+      // geometries picked up from dot.xml, dot.prj, dot.j2w and so on.  We
+      // will check for that later if the getInternalImageGeometry fails.
+      //---
+      theGeometry = getExternalImageGeometry();
+      
+      if ( !theGeometry )
+      {
+         //---
+         // Check for external files other than .geom, i.e. file.xml & j2w:
+         //---
+         theGeometry = getMetadataImageGeometry();
+
+         if ( !theGeometry )
+         {
+            // Check the internal geometry first to avoid a factory call.
+            theGeometry = getInternalImageGeometry();
+
+            //---
+            // WARNING:
+            // Must create/set the geometry at this point or the next call to
+            // ossimImageGeometryRegistry::extendGeometry will put us in an infinite loop
+            // as it does a recursive call back to ossimImageHandler::getImageGeometry().
+            //---
+            if ( !theGeometry )
+            {
+               theGeometry = new ossimImageGeometry();
+            }
+            
+            // Check for set projection.
+            if ( !theGeometry->getProjection() )
+            {
+               // Last try factories for projection.
+               ossimImageGeometryRegistry::instance()->extendGeometry(this);
+            }
+         }
+      }
+
+      // Set image things the geometry object should know about.
+      initImageParameters( theGeometry.get() );
+   }
+   return theGeometry;
+}
+
+ossimRefPtr<ossimImageGeometry> ossimOpjJp2Reader::getInternalImageGeometry()
+{
+   static const char MODULE[] = "ossimOpjJp2Reader::getInternalImageGeometry";
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " entered...\n";
+   }
+
+   ossimRefPtr<ossimImageGeometry> geom = 0;
+
+   if ( isOpen() )
+   {
+      std::streamoff pos = m_str->tellg();
+
+      m_str->seekg(0, std::ios_base::beg );
+
+      // Straight up J2k has no boxes.
+      if ( ossim::getCodecFormat( m_str ) == OPJ_CODEC_JP2 )
+      {
+         m_str->seekg(4, std::ios_base::beg );
+
+         // Try to get geom from GML box:
+         geom = getImageGeometryFromGmlBox();
+
+         if ( geom.valid() == false )
+         {
+            // Try to get geom from geotiff box:
+            geom = getImageGeometryFromGeotiffBox();
+         }
+      }
+
+      // Seek back to original position.
+      m_str->seekg(pos, std::ios_base::beg );
+   }
+
+   return geom;
+
+} // End: ossimOpjJp2Reader::getInternalImageGeometry()
+ 
+ossimRefPtr<ossimImageGeometry> ossimOpjJp2Reader::getImageGeometryFromGeotiffBox()
+{
+   static const char MODULE[] = "ossimOpjJp2Reader::getImageGeometryFromGeotiffBox";
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " entered...\n";
+   }
+   ossimRefPtr<ossimImageGeometry> geom = 0;
+   
+   if ( isOpen() )
+   {
+      std::streamoff pos = m_str->tellg();
+      
+      m_str->seekg(0, std::ios_base::beg );
+
+      std::vector<ossim_uint8> box;
+      ossimJp2Info jp2Info;
+      
+      std::streamoff boxPos = jp2Info.getGeotiffBox( *m_str, box );
+
+      // Seek back to original position.
+      m_str->seekg(pos, std::ios_base::beg );
+      
+      if ( boxPos && box.size() )
+      {
+         if (traceDebug())
+         {
+            ossimNotify(ossimNotifyLevel_DEBUG)
+               << "Found geotiff uuid at: " << boxPos+8 << "\n";
+         }
+
+         //---
+         // Create a string stream and set the vector buffer as its source.
+         // Note: The box has the 16 GEOTIFF_UUID bytes in there so offset
+         // address and size.
+         //---
+#if 0
+         // This doesn't work with VS2010...
+         // Create a string stream and set the vector buffer as its source.
+         std::istringstream boxStream;
+         boxStream.rdbuf()->pubsetbuf( (char*)&box.front()+GEOTIFF_UUID_SIZE,
+                                 box.size()-GEOTIFF_UUID_SIZE );
+#else
+         // convert the vector into a string
+         std::string boxString( box.begin()+GEOTIFF_UUID_SIZE, box.end() );
+         std::istringstream boxStream;
+         boxStream.str( boxString );
+#endif
+
+
+         // Give the stream to tiff info to create a geometry.
+         ossimTiffInfo info;
+         ossim_uint32 entry = 0;
+         ossimKeywordlist kwl; // Used to capture geometry data. 
+         
+         if ( info.getImageGeometry(boxStream, kwl, entry) )
+         {
+            //---
+            // The tiff embedded in the geojp2 only has one line
+            // and one sample by design so overwrite the lines and
+            // samples with the real value.
+            //---
+            ossimString pfx = "image";
+            pfx += ossimString::toString(entry);
+            pfx += ".";
+            
+            // Add the lines.
+            kwl.add(pfx.chars(), ossimKeywordNames::NUMBER_LINES_KW,
+                    getNumberOfLines(0), true);
+            
+            // Add the samples.
+            kwl.add(pfx.chars(), ossimKeywordNames::NUMBER_SAMPLES_KW,
+                    getNumberOfSamples(0), true);
+            
+            // Create the projection.
+            ossimRefPtr<ossimProjection> proj =
+               ossimProjectionFactoryRegistry::instance()->createProjection(kwl, pfx);
+            if ( proj.valid() )
+            {
+               // Create and assign projection to our ossimImageGeometry object.
+               geom = new ossimImageGeometry();
+               geom->setProjection( proj.get() );
+               if (traceDebug())
+               {
+                  ossimNotify(ossimNotifyLevel_DEBUG) << "Found GeoTIFF box." << std::endl;
+               }
+               
+               // Get the internal raster pixel alignment type and set the base class.
+               const char* lookup = kwl.find(pfx.chars(), ossimKeywordNames::PIXEL_TYPE_KW);
+               if ( lookup )
+               {
+                  ossimString type = lookup;
+                  type.downcase();
+                  if ( type == "pixel_is_area" )
+                  {
+                     thePixelType = OSSIM_PIXEL_IS_AREA;
+                  }
+                  else if ( type == "pixel_is_point" )
+                  {
+                     thePixelType = OSSIM_PIXEL_IS_POINT;
+                  }
+               }
+            }
+         }
+      }
+      else // Did not find box in file.
+      {
+         m_str->clear();
+      }
+   }
+   return geom;
+   
+} // End: ossimOpjJp2Reader::getImageGeometryFromGeotiffBox
+
+
+ossimRefPtr<ossimImageGeometry> ossimOpjJp2Reader::getImageGeometryFromGmlBox()
+{
+   static const char MODULE[] = "ossimOpjJp2Reader::getImageGeometryFromGmlBox";
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " entered...\n";
+   }
+   ossimRefPtr<ossimImageGeometry> geom = 0;
+   
+   if ( isOpen() )
+   {
+      std::streamoff pos = m_str->tellg();
+      
+      m_str->seekg(0, std::ios_base::beg );
+
+      std::vector<ossim_uint8> box;
+      ossimJp2Info jp2Info;
+      
+      std::streamoff boxPos = jp2Info.getGmlBox( *m_str, box );
+
+      // Seek back to original position.
+      m_str->seekg(pos, std::ios_base::beg );
+      
+      if ( boxPos && box.size() )
+      {
+         if (traceDebug())
+         {
+            ossimNotify(ossimNotifyLevel_DEBUG)
+               << "Found gml box at: " << boxPos+8
+               << "\nbox size: " << box.size() << "\n";
+         }
+
+#if 0
+         // This doesn't work with VS2010...
+         // Create a string stream and set the vector buffer as its source.
+         std::istringstream boxStream;
+         boxStream.rdbuf()->pubsetbuf( (char*)&box.front(), box.size() );
+#else
+         // convert the vector into a string
+         std::string boxString( box.begin(), box.end() );
+         std::istringstream boxStream;
+         boxStream.str( boxString );
+#endif
+
+         ossimGmlSupportData* gml = new ossimGmlSupportData();
+
+         if ( gml->initialize( boxStream ) )
+         {
+            // Tmp drb
+            //cout << *(gml->getXmlDoc().get()) << endl;
+
+            ossimKeywordlist geomKwl;
+            if ( gml->getImageGeometry( geomKwl ) )
+            {
+               // Make projection:
+               // Create the projection.
+               ossimRefPtr<ossimProjection> proj =
+                  ossimProjectionFactoryRegistry::instance()->createProjection( geomKwl );
+               if ( proj.valid() )
+               {
+                  // Create and assign projection to our ossimImageGeometry object.
+                  geom = new ossimImageGeometry();
+                  geom->setProjection( proj.get() );
+                  if (traceDebug())
+                  {
+                     ossimNotify(ossimNotifyLevel_DEBUG) << "Found GMLJP2 box." << std::endl;
+                  }
+               }
+            }
+         }
+
+         // Cleanup:
+         delete gml;
+         gml = 0;
+      }
+      else // Did not find box in file.
+      {
+         m_str->clear();
+      }
+   }
+   return geom;
+   
+} // End: ossimOpjJp2Reader::getImageGeometryFromGmlBox
+
+ossimRefPtr<ossimImageGeometry> ossimOpjJp2Reader::getMetadataImageGeometry() const
+{
+   static const char M[] = "ossimOpjJp2Reader::getMetadataImageGeometry";
+   if ( traceDebug() )
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG) << M << " entered...\n";
+   }
+   
+   ossimRefPtr<ossimImageGeometry> geom = 0;
+   ossimRefPtr<ossimProjection>    proj = 0;
+
+   // See if we can pick up the projection from the FGDC file:
+   ossimFilename fdgcFile = theImageFile;
+   
+   fdgcFile += ".xml"; // file.jp2.xml
+   if ( fdgcFile.exists() == false ) 
+   {
+      fdgcFile = theImageFile;
+      fdgcFile.setExtension(ossimString("xml")); // file.xml
+   }
+   
+   if ( fdgcFile.exists() )
+   {
+      ossimFgdcXmlDoc fgdcDoc;
+      if ( fgdcDoc.open(fdgcFile) )
+      {
+         try
+         {
+            proj = fgdcDoc.getGridCoordSysProjection();
+         }
+         catch (const ossimException& e)
+         {
+            ossimNotify(ossimNotifyLevel_WARN) << e.what() << std::endl;
+         }
+
+         if ( proj.valid() )
+         {
+            geom = new ossimImageGeometry();
+
+            ossimMapProjection* mapProj = dynamic_cast<ossimMapProjection*>(proj.get());
+            if ( mapProj )
+            {
+               // See if we have a world file.  Seems they have a more accurate tie point.
+               ossimFilename worldFile = theImageFile;
+               worldFile.setExtension(ossimString("j2w")); // file.j2w
+               if ( worldFile.exists() )
+               {
+                  //---
+                  // Note need a way to determine pixel type from fgdc doc.
+                  // This can result in a half pixel shift.
+                  //---
+                  ossimPixelType pixelType = OSSIM_PIXEL_IS_POINT;
+                  ossimUnitType  unitType  = fgdcDoc.getUnitType();
+                  
+                  ossimTiffWorld tfw;
+                  if ( tfw.open(worldFile, pixelType, unitType) )
+                  {
+                     ossimDpt gsd = tfw.getScale();
+                     gsd.y = std::fabs(gsd.y); // y positive up so negate.
+                     ossimDpt tie = tfw.getTranslation();
+                     
+                     if ( unitType != OSSIM_METERS )
+                     {
+                        ossimUnitConversionTool uct;
+                        
+                        // GSD (scale):
+                        uct.setValue(gsd.x, unitType);
+                        gsd.x = uct.getValue(OSSIM_METERS);
+                        uct.setValue(gsd.y, unitType);
+                        gsd.y = uct.getValue(OSSIM_METERS);
+                        
+                        // Tie point:
+                        uct.setValue(tie.x, unitType);
+                        tie.x = uct.getValue(OSSIM_METERS);
+                        uct.setValue(tie.y, unitType);
+                        tie.y = uct.getValue(OSSIM_METERS);
+                     }
+                     
+                     mapProj->setMetersPerPixel(gsd);
+                     mapProj->setUlTiePoints(tie);
+                  }
+                  
+                  if ( tfw.getRotation() != 0.0 )
+                  {
+                     ossimNotify(ossimNotifyLevel_WARN)
+                        << M << " Unhandled rotation in tfw file." << std::endl;
+                  }
+               }
+               
+            } // if ( worldFile.exists() )
+               
+            geom->setProjection( proj.get() );
+            
+         }  // if ( proj.valid() )
+         
+      } // if ( fgdcDoc.open(fdgcFile) )
+      
+   } // if ( fdgcFile.exists() )
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << M << " exit status = " << (geom.valid()?"true":"false\n")
+         << std::endl;
+   }   
+   
+   return geom;
+}
+
+void ossimOpjJp2Reader::allocate()
+{
+   m_tile = ossimImageDataFactory::instance()->create(this, this);
+   m_tile->initialize();
+   m_cacheTile = ossimImageDataFactory::instance()->create(this, this);
+   m_cacheTile->initialize();
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimOpjJp2Reader::allocate DEBUG:"
+         << "\nm_tile:\n"      << *(m_tile.get())
+         << endl;
+   }
+}
diff --git a/ossim_plugins/openjpeg/ossimOpjJp2Reader.h b/ossim_plugins/openjpeg/ossimOpjJp2Reader.h
new file mode 100644
index 0000000..5da6887
--- /dev/null
+++ b/ossim_plugins/openjpeg/ossimOpjJp2Reader.h
@@ -0,0 +1,232 @@
+//----------------------------------------------------------------------------
+//
+// License:  See top level LICENSE.txt file
+//
+// Author:  David Burken
+//
+// Description: OSSIM Open JPEG JP2 reader (tile source).
+//
+// http://www.openjpeg.org/
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef ossimOpjJp2Reader_HEADER
+#define ossimOpjJp2Reader_HEADER 1
+
+#include <ossim/imaging/ossimImageHandler.h>
+#include <ossim/support_data/ossimJ2kSizRecord.h>
+#include <vector>
+
+// Forward class declarations.
+class ossimImageData;
+class ossimJ2kCodRecord;
+
+class ossimOpjJp2Reader : public ossimImageHandler
+{
+public:
+
+   /** Anonymous enumerations: */
+   enum
+   {
+      SIGNATURE_BOX_SIZE = 12,
+      GEOTIFF_UUID_SIZE  = 16
+   };
+   
+   enum ossimOpjJp2ReadMode
+   {
+      ossimOpjJp2ReadUnknown = 0
+   };
+
+   /** default constructor */
+   ossimOpjJp2Reader();
+
+   /** virtual destructor */
+   virtual ~ossimOpjJp2Reader();
+
+   /** @return "ossim_openjpeg_reader" */
+   virtual ossimString getShortName() const;
+
+   /** @return "ossim open jpeg reader" */
+   virtual ossimString getLongName()  const;
+
+   /** @return "ossimOpjJp2Reader" */
+   virtual ossimString getClassName()    const;
+
+   /**
+    *  Returns a pointer to a tile given an origin representing the upper
+    *  left corner of the tile to grab from the image.
+    *  Satisfies pure virtual from TileSource class.
+    */
+   virtual ossimRefPtr<ossimImageData> getTile(const ossimIrect& rect,
+                                               ossim_uint32 resLevel=0);
+
+    /**
+     *  Returns the number of bands in the image.
+     *  Satisfies pure virtual from ImageHandler class.
+     */
+   virtual ossim_uint32 getNumberOfInputBands() const;
+
+   /**
+    * Returns the number of bands in a tile returned from this TileSource.
+    * Note: we are supporting sources that can have multiple data objects.
+    * If you want to know the scalar type of an object you can pass in the
+    */
+   virtual ossim_uint32 getNumberOfOutputBands()const;
+
+   /**
+    * @brief Returns the number of decimation levels.
+    * 
+    * This returns the total number of decimation levels.  It is important to
+    * note that res level 0 or full resolution is included in the list and has
+    * decimation values 1.0, 1.0
+    * 
+    * @return The number of decimation levels.
+    */
+   virtual ossim_uint32 getNumberOfDecimationLevels()const;
+
+   /**
+     *  Returns the number of lines in the image.
+     *  Satisfies pure virtual from ImageHandler class.
+     */
+   virtual ossim_uint32 getNumberOfLines(ossim_uint32 reduced_res_level = 0) const;
+
+   /**
+    *  Returns the number of samples in the image.
+    *  Satisfies pure virtual from ImageHandler class.
+    */
+   virtual ossim_uint32 getNumberOfSamples(ossim_uint32 reduced_res_level = 0) const;
+
+   /**
+    * Returns the zero based image rectangle for the reduced resolution data
+    * set (rrds) passed in.  Note that rrds 0 is the highest resolution rrds.
+    */
+   virtual ossimIrect getImageRectangle(ossim_uint32 reduced_res_level = 0) const;
+
+   /**
+    * Method to save the state of an object to a keyword list.
+    * Return true if ok or false on error.
+    */
+   virtual bool saveState(ossimKeywordlist& kwl,
+                          const char* prefix=0)const;
+
+   /**
+    * Method to the load (recreate) the state of an object from a keyword
+    * list.  Return true if ok or false on error.
+    */
+   virtual bool loadState(const ossimKeywordlist& kwl,
+                          const char* prefix=0);
+
+   /**
+    * Returns the output pixel type of the tile source.
+    */
+   virtual ossimScalarType getOutputScalarType() const;
+
+   /**
+    * Returns the tile width of the image or 0 if the image is not tiled.
+    * Note: this is not the same as the ossimImageSource::getTileWidth which
+    * returns the output tile width which can be different than the internal
+    * image tile width on disk.
+    */
+   virtual ossim_uint32 getImageTileWidth() const;
+
+   /**
+    * Returns the tile width of the image or 0 if the image is not tiled.
+    * Note: this is not the same as the ossimImageSource::getTileWidth which
+    * returns the output tile width which can be different than the internal
+    * image tile width on disk.
+    */
+   virtual ossim_uint32 getImageTileHeight() const;
+
+   virtual bool isOpen()const;
+
+   virtual double getMaxPixelValue(ossim_uint32 band = 0)const;
+
+   /**
+    *  @brief open method.
+    *  @return true on success, false on error.
+    */
+   virtual bool open();
+
+   /** close method */
+   virtual void close();
+
+   /**
+    * Returns the image geometry object associated with this tile source or
+    * NULL if non defined.  The geometry contains full-to-local image
+    * transform as well as projection (image-to-world).
+    */
+   virtual ossimRefPtr<ossimImageGeometry> getImageGeometry();
+
+protected:
+   /**
+    * @brief Gets an overview tile.
+    * 
+    * Overrides ossimImageHandler::getOverviewTile
+    *
+    * @param resLevel The resolution level to pull from with resLevel 0 being
+    * full res.
+    * 
+    * @param result The tile to stuff.  Note The requested rectangle in full
+    * image space and bands should be set in the result tile prior to
+    * passing.  This method will subtract the subImageOffset if needed for
+    * external overview call since they do not know about the sub image offset.
+    *
+    * @return true on success false on error.  Typically this will return false
+    * if resLevel==0 unless the overview has r0.  If return is false, result
+    * is undefined so caller should handle appropriately with makeBlank or
+    * whatever.
+    */
+  virtual bool getOverviewTile(ossim_uint32 resLevel,
+                               ossimImageData* result);   
+      
+private:
+
+   /**
+    * @param Method to get geometry from the embedded JP2 Boxes.
+    */
+   virtual ossimRefPtr<ossimImageGeometry> getInternalImageGeometry();
+
+   /**
+    * @param Method to get geometry from the embedded JP2 GeoTIFF Box.
+    */
+   virtual ossimRefPtr<ossimImageGeometry> getImageGeometryFromGeotiffBox();
+
+   /**
+    * @param Method to get geometry from the embedded JP2 GML Box.
+    */
+   virtual ossimRefPtr<ossimImageGeometry> getImageGeometryFromGmlBox();
+   
+   /**
+    * @param Method to get geometry from the various external files like
+    * .prj, .j2w .xml and so on.
+    */
+   ossimRefPtr<ossimImageGeometry> getMetadataImageGeometry() const;
+
+   // Cleans memory.  Called on close or destruct.
+   void destroy();
+   
+
+   bool initSizRecord( std::istream* str,
+                       ossimJ2kSizRecord& sizRecord) const;
+
+   bool initCodRecord( std::istream* str,
+                       ossimJ2kCodRecord& sizRecord) const;
+
+   /**
+    * @brief Initializes tiles.  Called once on first getTile request.
+    */ 
+   void allocate();
+
+   ossimJ2kSizRecord m_sizRecord;
+   
+   ossimRefPtr<ossimImageData>  m_tile;
+   ossimRefPtr<ossimImageData>  m_cacheTile;   
+   std::ifstream*               m_str;
+   ossim_uint32                 m_minDwtLevels;
+   ossim_int32                  m_format; // OPJ_CODEC_FORMAT
+   
+TYPE_DATA
+};
+
+#endif
diff --git a/ossim_plugins/openjpeg/ossimOpjJp2Writer.cpp b/ossim_plugins/openjpeg/ossimOpjJp2Writer.cpp
new file mode 100644
index 0000000..b669620
--- /dev/null
+++ b/ossim_plugins/openjpeg/ossimOpjJp2Writer.cpp
@@ -0,0 +1,581 @@
+//----------------------------------------------------------------------------
+//
+// License:  See top level LICENSE.txt file
+//
+// Author:  David Burken
+//
+// Description: OSSIM Open JPEG writer.
+//
+//----------------------------------------------------------------------------
+// $Id: ossimOpjJp2Writer.cpp 11652 2007-08-24 17:14:15Z dburken $
+
+#include "ossimOpjJp2Writer.h"
+#include "ossimOpjCompressor.h"
+
+#include <ossim/base/ossimDpt.h>
+#include <ossim/base/ossimEndian.h>
+#include <ossim/base/ossimException.h>
+#include <ossim/base/ossimIoStream.h>
+#include <ossim/base/ossimKeywordlist.h>
+#include <ossim/base/ossimKeywordNames.h>
+#include <ossim/base/ossimNumericProperty.h>
+#include <ossim/base/ossimScalarTypeLut.h>
+#include <ossim/base/ossimStringProperty.h>
+#include <ossim/base/ossimTrace.h>
+#include <ossim/projection/ossimMapProjection.h>
+#include <ossim/imaging/ossimImageData.h>
+#include <ossim/imaging/ossimImageSource.h>
+#include <ossim/imaging/ossimScalarRemapper.h>
+#include <ossim/support_data/ossimJp2Info.h>
+
+#include <ctime>
+
+RTTI_DEF1(ossimOpjJp2Writer,
+	  "ossimOpjJp2Writer",
+	  ossimImageFileWriter)
+
+//---
+// For trace debugging (to enable at runtime do:
+// your_app -T "ossimOpjJp2Writer:debug" your_app_args
+//---
+static ossimTrace traceDebug("ossimOpjJp2Writer:debug");
+
+static const ossimIpt DEFAULT_TILE_SIZE(1024, 1024);
+
+//---
+// For the "ident" program which will find all expanded $Id$
+// them.
+//---
+#if OSSIM_ID_ENABLED
+static const char OSSIM_ID[] = "$Id$";
+#endif
+
+ossimOpjJp2Writer::ossimOpjJp2Writer()
+   : ossimImageFileWriter(),
+     m_outputStream(0),
+     m_ownsStreamFlag(false),
+     m_compressor(new ossimOpjCompressor()),
+     m_do_geojp2(true),
+     m_do_gmljp2(true)
+{
+   //---
+   // Uncomment for debug mode:
+   // traceDebug.setTraceFlag(true);
+   //---
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimOpjJp2Writer::ossimOpjJp2Writer entered" << std::endl;
+#if OSSIM_ID_ENABLED
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "OSSIM_ID:  "
+         << OSSIM_ID
+         << std::endl;
+#endif
+   }
+
+   // Since there is no internal geometry set the flag to write out one.
+   // setWriteExternalGeometryFlag(true);
+
+   // Set the output image type in the base class.
+   setOutputImageType(getShortName());
+}
+
+ossimOpjJp2Writer::ossimOpjJp2Writer( const ossimString& typeName )
+   : ossimImageFileWriter(),
+     m_outputStream(0),
+     m_ownsStreamFlag(false),
+     m_compressor(new ossimOpjCompressor()),
+     m_do_geojp2(typeName.contains("ossim_opj_geojp2")),
+     m_do_gmljp2(typeName.contains("ossim_opj_gmljp2"))
+{
+   //---
+   // Uncomment for debug mode:
+   // traceDebug.setTraceFlag(true);
+   //---
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimOpjJp2Writer::ossimOpjJp2Writer entered" << std::endl;
+#if OSSIM_ID_ENABLED
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "OSSIM_ID:  "
+         << OSSIM_ID
+         << std::endl;
+#endif
+   }
+
+   // Since there is no internal geometry set the flag to write out one.
+   // setWriteExternalGeometryFlag(true);
+
+   // Set the output image type in the base class.
+   setOutputImageType(getShortName());
+
+   // If typeName is unrecognized, write out both geotiff and gmljp2 headers
+   if ( !m_do_geojp2 && !m_do_gmljp2 )
+   {
+       m_do_geojp2 = true;
+       m_do_gmljp2 = true;
+   }
+}
+
+ossimOpjJp2Writer::~ossimOpjJp2Writer()
+{
+   // This will flush stream and delete it if we own it.
+   close();
+}
+
+ossimString ossimOpjJp2Writer::getShortName() const
+{
+   return ossimString("ossim_opj_jp2");
+}
+
+ossimString ossimOpjJp2Writer::getLongName() const
+{
+   return ossimString("ossim open jpeg writer");
+}
+
+ossimString ossimOpjJp2Writer::getClassName() const
+{
+   return ossimString("ossimOpjJp2Writer");
+}
+
+bool ossimOpjJp2Writer::writeFile()
+{
+   // This method is called from ossimImageFileWriter::execute().
+
+   bool result = false;
+   
+   if( theInputConnection.valid() &&
+       (getErrorStatus() == ossimErrorCodes::OSSIM_OK) )
+   {
+
+      // Make sure Area of Interest is an even multiple of tiles
+      ossimIrect areaOfInterest = theInputConnection->getAreaOfInterest();
+      ossimIpt imageSize(areaOfInterest.size());
+      ossimIpt imageLr(areaOfInterest.lr());
+      ossim_uint32 xBoundaryAdjustFactor = DEFAULT_TILE_SIZE.x - (imageSize.x % DEFAULT_TILE_SIZE.x);
+      ossim_uint32 yBoundaryAdjustFactor = DEFAULT_TILE_SIZE.y - (imageSize.y % DEFAULT_TILE_SIZE.y);
+      imageLr.x += xBoundaryAdjustFactor;
+      imageLr.y += yBoundaryAdjustFactor;
+      areaOfInterest.set_lr(imageLr); 
+      theInputConnection->setAreaOfInterest(areaOfInterest);
+
+      // Set the tile size for all processes.
+      theInputConnection->setTileSize( DEFAULT_TILE_SIZE );
+      theInputConnection->setToStartOfSequence();
+      
+      //---
+      // Note only the master process used for writing...
+      //---
+      if(theInputConnection->isMaster())
+      {
+         if (!isOpen())
+         {
+            open();
+         }
+         
+         if ( isOpen() )
+         {
+            result = writeStream();
+         }
+      }
+      else // Slave process.
+      {
+         // This will return after all tiles for this node have been processed.
+         theInputConnection->slaveProcessTiles();
+
+         result = true;
+      }
+   }
+      
+   return result;
+   
+} // End: ossimOpjJp2Writer::writeFile()
+
+bool ossimOpjJp2Writer::writeStream()
+{
+   static const char MODULE[] = "ossimOpjJp2Writer::write";
+   
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " entered..." << endl;
+   }
+   
+   bool result = false;
+   
+   if (theInputConnection.valid() && theInputConnection->isMaster() &&
+       m_outputStream )
+   {
+      result = true; // Assuming good at this point...
+      
+      ossim_uint32 outputTilesWide =
+         theInputConnection->getNumberOfTilesHorizontal();
+      ossim_uint32 outputTilesHigh =
+         theInputConnection->getNumberOfTilesVertical();
+      ossim_uint32 numberOfTiles =
+         theInputConnection->getNumberOfTiles();
+      ossim_uint32 tileNumber = 0;
+      
+      if (traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG)
+            << MODULE << " DEBUG:"
+            << "\noutputTilesWide:  " << outputTilesWide
+            << "\noutputTilesHigh:  " << outputTilesHigh
+            << "\nnumberOfTiles:    " << numberOfTiles
+            << "\nimageRect: " << theInputConnection->getAreaOfInterest()
+            << std::endl;
+      }
+
+      ossimScalarType scalarType = theInputConnection->getOutputScalarType();
+
+      const ossim_uint32 BANDS = theInputConnection->getNumberOfOutputBands();
+
+      // Create the compressor.  Can through an exception.
+      try
+      {
+         m_compressor->create(m_outputStream,
+                              scalarType,
+                              BANDS,
+                              theInputConnection->getAreaOfInterest(),
+                              DEFAULT_TILE_SIZE,
+                              true);
+      }
+      catch (const ossimException& e)
+      {
+         ossimNotify(ossimNotifyLevel_WARN) << e.what() << std::endl;
+         return false;
+      }
+
+      m_compressor->openJp2Codestream();
+
+      // Flush the stream since we're going to mess with it.
+      m_outputStream->flush();
+
+      // cout << "tellp 1: " << m_outputStream->tellp();
+
+      // Back up to start of jp2c lbox.
+      m_outputStream->seekp( -8, std::ios_base::cur );
+      std::streamoff origJp2cBoxPos = m_outputStream->tellp();
+
+      // cout << "origJp2cBoxPos: " << origJp2cBoxPos << endl;
+      
+      // Copy the lbox and tbox for jp2c (codestream).
+      std::vector<ossim_uint8> jp2cHdr;
+      copyData( origJp2cBoxPos, 8, jp2cHdr );
+
+      // Write the geotiff and gml boxes:
+      // Overwrite!!!  Supreme hack. (drb - 20150326)
+      if ( m_do_geojp2 == true )
+         writeGeotiffBox(m_outputStream, m_compressor);
+      if ( m_do_gmljp2 == true )
+         writeGmlBox(m_outputStream, m_compressor);
+      m_outputStream->flush();
+
+      std::streamoff newJp2cBoxPos = m_outputStream->tellp();
+      // cout << "newJp2cBoxPos: " << newJp2cBoxPos << endl;
+
+      // Write the jp2c hdr after the geotiff box:
+      m_outputStream->write( (char*)&jp2cHdr, jp2cHdr.size() );
+
+      // Copy the lbox and tbox for geotiff box
+      std::vector<ossim_uint8> geotiffHdr;
+      copyData( origJp2cBoxPos, 8, geotiffHdr );
+
+      bool needAlpha = m_compressor->getAlphaChannelFlag();
+      ossim_uint32 tileIndex = 0;
+      
+      // Tile loop in the line direction.
+      for(ossim_uint32 y = 0; y < outputTilesHigh; ++y)
+      {
+         // Tile loop in the sample (width) direction.
+         for(ossim_uint32 x = 0; x < outputTilesWide; ++x)
+         {
+            // Grab the resampled tile.
+            ossimRefPtr<ossimImageData> t = theInputConnection->getNextTile();
+            if (t.valid() && ( t->getDataObjectStatus() != OSSIM_NULL ) )
+            {
+               if (needAlpha)
+               {
+                  t->computeAlphaChannel();
+               }
+               if ( ! m_compressor->writeTile( t.get(), tileIndex++) )
+               {
+                  ossimNotify(ossimNotifyLevel_WARN)
+                     << MODULE << " ERROR:"
+                     << "Error returned writing tile:  "
+                     << tileNumber
+                     << std::endl;
+                  result = false;
+               }
+            }
+            else
+            {
+               ossimNotify(ossimNotifyLevel_WARN)
+                  << MODULE << " ERROR:"
+                  << "Error returned writing tile:  " << tileNumber
+                  << std::endl;
+               result = false;
+            }
+            if (result == false)
+            {
+               // This will bust out of both loops.
+               x = outputTilesWide;
+               y = outputTilesHigh;
+            }
+            
+            // Increment tile number for percent complete.
+            ++tileNumber;
+            
+         } // End of tile loop in the sample (width) direction.
+         
+         if (needsAborting())
+         {
+            setPercentComplete(100.0);
+            break;
+         }
+         else
+         {
+            ossim_float64 tile = tileNumber;
+            ossim_float64 numTiles = numberOfTiles;
+            setPercentComplete(tile / numTiles * 100.0);
+         }
+         
+      } // End of tile loop in the line (height) direction.
+
+      if (m_outputStream)      
+      {
+         m_outputStream->flush();
+      }
+      
+      m_compressor->finish();
+
+      // Grab the jp2c hdr again in case the lbox changes.
+      copyData( origJp2cBoxPos, 8, jp2cHdr );
+
+      // Re-write the geotiff lbox and tbox:
+      m_outputStream->seekp( origJp2cBoxPos, std::ios_base::beg );
+      m_outputStream->write( (char*)&geotiffHdr.front(), geotiffHdr.size() );
+
+      // Re-write the jp2c hdr at new position:
+      m_outputStream->seekp( newJp2cBoxPos, std::ios_base::beg );
+      m_outputStream->write( (char*)&jp2cHdr.front(), jp2cHdr.size() );
+
+      m_outputStream->flush();
+      close();
+
+   } // matches: if (theInputConnection.valid() ...
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " exit status = " << (result?"true":"false\n")
+         << std::endl;
+   }
+   
+   return result;
+}
+
+bool ossimOpjJp2Writer::isOpen() const
+{
+   if (m_outputStream)
+   {
+     return true;
+   }
+   return false;
+}
+
+bool ossimOpjJp2Writer::open()
+{
+   bool result = false;
+   
+   close();
+
+   // Check for empty filenames.
+   if ( theFilename.size() )
+   {
+      std::ofstream* os = new std::ofstream();
+      os->open(theFilename.c_str(), ios::out | ios::binary);
+      if(os->is_open())
+      {
+         // cout << "opened " << theFilename << endl;
+         m_outputStream = os;
+         m_ownsStreamFlag = true;
+         result = true;
+      }
+      else
+      {
+         delete os;
+         os = 0;
+      }
+   }
+   
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimOpjJp2Writer::open()\n"
+         << "File " << theFilename << (result ? " opened" : " not opened")
+         << std::endl;
+   }
+
+   return result;
+}
+
+void ossimOpjJp2Writer::close()
+{
+   if (m_outputStream)      
+   {
+      m_outputStream->flush();
+
+      if (m_ownsStreamFlag)
+      {
+         delete m_outputStream;
+         m_outputStream = 0;
+         m_ownsStreamFlag = false;
+      }
+   }
+}
+
+bool ossimOpjJp2Writer::saveState(ossimKeywordlist& kwl,
+                                const char* prefix)const
+{
+   return ossimImageFileWriter::saveState(kwl, prefix);
+}
+
+bool ossimOpjJp2Writer::loadState(const ossimKeywordlist& kwl,
+                                const char* prefix)
+{
+   const char* value;
+   
+   value = kwl.find(prefix, ossimKeywordNames::OVERVIEW_FILE_KW);
+   if(value)
+   {
+      m_overviewFlag = ossimString(value).toBool();
+   }
+   
+   return ossimImageFileWriter::loadState(kwl, prefix);
+}
+
+void ossimOpjJp2Writer::setProperty(ossimRefPtr<ossimProperty> property)
+{
+   if (!property)
+   {
+      return;
+   }
+}
+
+ossimRefPtr<ossimProperty> ossimOpjJp2Writer::getProperty(const ossimString& name)const
+{
+   return ossimImageFileWriter::getProperty(name);
+}
+
+void ossimOpjJp2Writer::getPropertyNames(std::vector<ossimString>& propertyNames)const
+{
+   ossimImageFileWriter::getPropertyNames(propertyNames);
+}
+
+void ossimOpjJp2Writer::getImageTypeList(std::vector<ossimString>& imageTypeList)const
+{
+   imageTypeList.push_back( getShortName() );
+   imageTypeList.push_back( "ossim_opj_geojp2" );
+   imageTypeList.push_back( "ossim_opj_gmljp2" );
+}
+
+ossimString ossimOpjJp2Writer::getExtension() const
+{
+   return ossimString("jp2");
+}
+
+bool ossimOpjJp2Writer::getOutputHasInternalOverviews( void ) const
+{ 
+   return true;
+}
+
+bool ossimOpjJp2Writer::hasImageType(const ossimString& imageType) const
+{
+   bool result = false; 
+   if ( (imageType == getShortName()) ||
+        (imageType == "image/jp2")    ||
+        (imageType == "image/j2k")    ||
+        (imageType == "ossim_opj_geojp2") ||
+        (imageType == "ossim_opj_gmljp2") )
+   {
+      result = true;
+   }
+   return result;
+}
+
+bool ossimOpjJp2Writer::setOutputStream(std::ostream& stream)
+{
+   if (m_ownsStreamFlag && m_outputStream)
+   {
+      delete m_outputStream;
+   }
+   m_outputStream = &stream;
+   m_ownsStreamFlag = false;
+   return true;
+}
+
+bool ossimOpjJp2Writer::writeGeotiffBox(std::ostream* stream, ossimOpjCompressor* compressor)
+{
+   bool result = false;
+   
+   if ( theInputConnection.valid() && stream && compressor )
+   {
+      ossimRefPtr<ossimImageGeometry> geom = theInputConnection->getImageGeometry();
+      if ( geom.valid() )
+      {
+         //---
+         // Make a temp file.  No means currently write a tiff straight to
+         // memory.
+         //---
+         ossimFilename tmpFile = theFilename.fileNoExtension();
+         tmpFile += "-tmp.tif";
+         
+         // Output rect.
+         ossimIrect rect = theInputConnection->getBoundingRect();
+         
+         result = compressor->writeGeotiffBox(stream, geom.get(), rect, tmpFile, getPixelType());
+      }
+   }
+
+   return result;
+   
+} // End: ossimKakaduJp2Writer::writeGeotffBox
+
+bool ossimOpjJp2Writer::writeGmlBox(std::ostream* stream, ossimOpjCompressor* compressor)
+{
+   bool result = false;
+   
+   if ( theInputConnection.valid() && stream && compressor )
+   {
+      ossimRefPtr<ossimImageGeometry> geom = theInputConnection->getImageGeometry();
+      if ( geom.valid() )
+      {
+         // Output rect.
+         ossimIrect rect = theInputConnection->getBoundingRect();
+         
+         result = compressor->writeGmlBox(stream, geom.get(), rect, getPixelType());
+      }
+   }
+
+   return result;
+   
+} // End: ossimKakaduJp2Writer::writeGmlBox
+
+void ossimOpjJp2Writer::copyData(
+   const std::streamoff& pos , ossim_uint32 size, std::vector<ossim_uint8>& data ) const
+{
+   std::ifstream str;
+   str.open( theFilename.c_str(), std::ios_base::in | std::ios_base::binary);
+   if ( str.is_open() )
+   {
+      data.resize(size);
+      str.seekg( pos, std::ios_base::beg );
+      str.read( (char*)&data.front(), size );
+   }
+}
diff --git a/ossim_plugins/openjpeg/ossimOpjJp2Writer.h b/ossim_plugins/openjpeg/ossimOpjJp2Writer.h
new file mode 100644
index 0000000..09e2cee
--- /dev/null
+++ b/ossim_plugins/openjpeg/ossimOpjJp2Writer.h
@@ -0,0 +1,176 @@
+//----------------------------------------------------------------------------
+//
+// License:  See top level LICENSE.txt file
+//
+// Author:  David Burken
+//
+// Description: OSSIM Open JPEG (j2k) writer.
+//
+//----------------------------------------------------------------------------
+// $Id: ossimOpjJp2Writer.h 11652 2007-08-24 17:14:15Z dburken $
+#ifndef ossimOpjJp2Writer_HEADER
+#define ossimOpjJp2Writer_HEADER 1
+
+#include <ossim/base/ossimRtti.h>
+#include <ossim/imaging/ossimImageFileWriter.h>
+#include <ossim/base/ossimKeywordlist.h>
+#include <ossim/base/ossimNBandLutDataObject.h>
+#include <ossim/base/ossimRefPtr.h>
+#include <ossim/imaging/ossimNBandToIndexFilter.h>
+#include <ossim/base/ossimIoStream.h>
+
+class ossimOpjCompressor;
+
+class ossimOpjJp2Writer : public ossimImageFileWriter
+{
+public:
+
+   /* default constructor */
+   ossimOpjJp2Writer();
+
+   /* 
+    * constructor with typeName
+    *   if typeName=="ossim_opj_geojp2", only write geotiff header
+    *   if typeName=="ossim_opj_gmljp2", only write gmljp2 header
+    *   else, write both headers
+    */
+   ossimOpjJp2Writer( const ossimString& typeName );
+
+   /* virtual destructor */
+   virtual ~ossimOpjJp2Writer();
+
+   /** @return "ossim_openjpeg_writer" */
+   virtual ossimString getShortName() const;
+
+   /** @return "ossim open jpeg writer" */
+   virtual ossimString getLongName()  const;
+
+   /** @return "ossimOpjReader" */
+   virtual ossimString getClassName()    const;
+   
+   /**
+    * void getImageTypeList(std::vector<ossimString>& imageTypeList)const
+    *
+    * Appends this writer image types to list "imageTypeList".
+    *
+    * This writer has types "ossim_opj_jp2", "ossim_opj_geojp2", and "ossim_opj_gmljp2".
+    *
+    * @param imageTypeList stl::vector<ossimString> list to append to.
+    */
+   virtual void getImageTypeList(std::vector<ossimString>& imageTypeList)const;
+   
+   virtual bool isOpen()const;   
+   
+   virtual bool open();
+
+   virtual void close();
+   
+   /**
+    * saves the state of the object.
+    */
+   virtual bool saveState(ossimKeywordlist& kwl,
+                          const char* prefix=0)const;
+   
+   /**
+    * Method to the load (recreate) the state of an object from a keyword
+    * list.  Return true if ok or false on error.
+    */
+   virtual bool loadState(const ossimKeywordlist& kwl,
+                          const char* prefix=0);
+
+   /**
+    * Will set the property whose name matches the argument
+    * "property->getName()".
+    *
+    * @param property Object containing property to set.
+    */
+   virtual void setProperty(ossimRefPtr<ossimProperty> property);
+
+   /**
+    * @param name Name of property to return.
+    * 
+    * @returns A pointer to a property object which matches "name".
+    */
+   virtual ossimRefPtr<ossimProperty> getProperty(const ossimString& name)const;
+
+   /**
+    * Pushes this's names onto the list of property names.
+    *
+    * @param propertyNames array to add this's property names to.
+    */
+   virtual void getPropertyNames(std::vector<ossimString>& propertyNames) const;
+   
+   /**
+    * Returns a 3-letter extension from the image type descriptor 
+    * (theOutputImageType) that can be used for image file extensions.
+    *
+    * @param imageType string representing image type.
+    *
+    * @return the 3-letter string extension.
+    */
+   virtual ossimString getExtension() const;
+
+   /**
+    * Examples of writers that always generate internal
+    * overviews are ossim_kakadu_jp2 and ossim_kakadu_nitf_j2k.
+    *
+    * @return true if the output of the writer will have
+    * internal overviews. The default is false. 
+    */
+   virtual bool getOutputHasInternalOverviews( void ) const;
+
+   /**
+    * @param imageType
+    * @return true if "imagetype" is one of: 
+    * "image/jp2" or "image/j2k"
+    * "ossim_opj_jp2", ossim_opj_geojp2", or "ossim_opj_gmljp2"
+    */
+   bool hasImageType(const ossimString& imageType) const;
+
+   /**
+    * @brief Method to write the image to a stream.
+    *
+    * @return true on success, false on error.
+    */
+   virtual bool writeStream();
+
+   /**
+    * @brief Sets the output stream to write to.
+    *
+    * The stream will not be closed/deleted by this object.
+    *
+    * @param output The stream to write to.
+    */
+   virtual bool setOutputStream(std::ostream& stream);
+
+private:
+
+   bool writeGeotiffBox(std::ostream* stream, ossimOpjCompressor* compressor);
+   bool writeGmlBox(std::ostream* stream, ossimOpjCompressor* compressor);
+
+   /**
+    * @brief Hack to copy bytes to vector so we can re-write them. Hack for
+    * inserting geotiff and gml boxes in front of jp2c codestream block.
+    */
+   void copyData( const std::streamoff& pos,
+                  ossim_uint32 size,
+                  std::vector<ossim_uint8>& data ) const;
+   
+   /**
+    * @brief Writes the file to disk or a stream.
+    * @return true on success, false on error.
+    */
+   virtual bool writeFile();
+
+   std::ostream*       m_outputStream;
+   bool                m_ownsStreamFlag;
+   bool                m_overviewFlag;
+   ossimOpjCompressor* m_compressor;
+   bool                m_do_geojp2;
+   bool                m_do_gmljp2;
+
+   TYPE_DATA
+
+};
+
+#endif /* #ifndef ossimOpjVoid Writer_HEADER */
diff --git a/ossim_plugins/openjpeg/ossimOpjKeywords.h b/ossim_plugins/openjpeg/ossimOpjKeywords.h
new file mode 100644
index 0000000..e2a63cf
--- /dev/null
+++ b/ossim_plugins/openjpeg/ossimOpjKeywords.h
@@ -0,0 +1,24 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Description: Header file for common keyword names.
+//
+//----------------------------------------------------------------------------
+// $Id: ossimOpjKeywords.h 19904 2011-08-05 17:50:32Z dburken $
+
+#ifndef ossimOpjKeywords_HEADER
+#define ossimOpjKeywords_HEADER 1
+
+#include <ossim/base/ossimString.h>
+
+static const ossimString COMPRESSION_RATTIO_KW = "compression_ratio";
+static const ossimString LEVELS_KW = "levels";
+static const ossimString REVERSIBLE_KW = "reversible";
+static const ossimString THREADS_KW = "threads";
+static const ossimString ADD_ALPHA_CHANNEL_KW = "add_alpha_channel";
+
+#endif /* #ifndef ossimOpjKeywords_HEADER */
+
diff --git a/ossim_plugins/openjpeg/ossimOpjNitfReader.cpp b/ossim_plugins/openjpeg/ossimOpjNitfReader.cpp
new file mode 100644
index 0000000..a6ed08a
--- /dev/null
+++ b/ossim_plugins/openjpeg/ossimOpjNitfReader.cpp
@@ -0,0 +1,283 @@
+//----------------------------------------------------------------------------
+//
+// License:  See top level LICENSE.txt file.
+//
+// Author:  David Burken
+//
+// Description:  NITF reader for j2k images using OpenJPEG library.
+//
+// $Id$
+//----------------------------------------------------------------------------
+
+
+#include <openjpeg.h>
+
+#include <ossimOpjNitfReader.h>
+#include <ossim/base/ossimCommon.h>
+#include <ossim/base/ossimException.h>
+#include <ossim/base/ossimTrace.h>
+#include <ossim/base/ossimEndian.h>
+#include <ossim/imaging/ossimTiffTileSource.h>
+#include <ossim/imaging/ossimImageDataFactory.h>
+#include <ossim/support_data/ossimNitfImageHeader.h>
+
+#ifdef OSSIM_ID_ENABLED
+static const char OSSIM_ID[] = "$Id";
+#endif
+
+static ossimTrace traceDebug("ossimOpjNitfReader:debug");
+
+
+static const ossim_uint16 SOC_MARKER = 0xff4f; // start of codestream
+static const ossim_uint16 SIZ_MARKER = 0xff51; // start of tile-part
+static const ossim_uint16 SOT_MARKER = 0xff90; // start of tile-part
+
+RTTI_DEF1_INST(ossimOpjNitfReader,
+               "ossimOpjNitfReader",
+               ossimNitfTileSource)
+
+
+
+ossimOpjNitfReader::ossimOpjNitfReader()
+   : ossimNitfTileSource()
+{
+}
+
+ossimOpjNitfReader::~ossimOpjNitfReader()
+{
+   close();
+}
+
+bool ossimOpjNitfReader::canUncompress(
+   const ossimNitfImageHeader* hdr) const
+{
+   if (!hdr)
+   {
+      return false;
+   }
+   if (hdr->getCompressionCode() == "C8") // jpeg
+   {
+      return true;
+   }
+   return false;
+}
+
+void ossimOpjNitfReader::initializeReadMode()
+{
+   // Initialize the read mode.
+   theReadMode = READ_MODE_UNKNOWN;
+   
+   const ossimNitfImageHeader* hdr = getCurrentImageHeader();
+   if (!hdr)
+   {
+      return;
+   }
+
+   if ( (hdr->getIMode() == "B") && (hdr->getCompressionCode()== "C8") )
+   {
+      theReadMode = READ_JPEG_BLOCK; 
+   }
+}
+
+void ossimOpjNitfReader::initializeCompressedBuf()
+{
+   //---
+   // If all block sizes are the same initialize theCompressedBuf; else,
+   // we will allocate on each loadBlock.
+   //---
+   if (theNitfBlockSize.size() == 0)
+   {
+      theCompressedBuf.clear();
+      return;
+   }
+   std::vector<ossim_uint32>::const_iterator i = theNitfBlockSize.begin();
+   ossim_uint32 size = (*i);
+   ++i;
+   while (i != theNitfBlockSize.end())
+   {
+      if ((*i) != size)
+      {
+         theCompressedBuf.clear();
+         return; // block sizes different
+      }
+      ++i;
+   }
+   theCompressedBuf.resize(size); // block sizes all the same.
+}
+
+bool ossimOpjNitfReader::scanForJpegBlockOffsets()
+{
+   const ossimNitfImageHeader* hdr = getCurrentImageHeader();
+   
+   if ( !hdr || (theReadMode != READ_JPEG_BLOCK) || !theFileStr )
+   {
+      return false;
+   }
+
+   theNitfBlockOffset.clear();
+   theNitfBlockSize.clear();
+
+   //---
+   // NOTE:
+   // SOC = 0xff4f Start of Codestream
+   // SOT = 0xff90 Start of tile
+   // SOD = 0xff93 Last marker in each tile
+   // EOC = 0xffd9 End of Codestream
+   //---
+   char c;
+
+   // Seek to the first block.
+   theFileStr.seekg(hdr->getDataLocation(), ios::beg);
+   if (theFileStr.fail())
+   {
+      return false;
+   }
+   
+   // Read the first two bytes and verify it is SOC; if not, get out.
+   theFileStr.get( c );
+   if (static_cast<ossim_uint8>(c) != 0xff)
+   {
+      return false;
+   }
+   theFileStr.get(c);
+   if (static_cast<ossim_uint8>(c) != 0x4f)
+   {
+      return false;
+   }
+
+   ossim_uint32 blockSize = 2;  // Read two bytes...
+
+   // Add the first offset.
+   // theNitfBlockOffset.push_back(hdr->getDataLocation());
+
+   // Find all the SOC markers.
+   while ( theFileStr.get(c) ) 
+   {
+      ++blockSize;
+      if (static_cast<ossim_uint8>(c) == 0xff)
+      {
+         if ( theFileStr.get(c) )
+         {
+            ++blockSize;
+
+            if (static_cast<ossim_uint8>(c) == 0x90) // At SOC marker...
+            {
+               std::streamoff pos = theFileStr.tellg();
+               theNitfBlockOffset.push_back(pos-2);
+            }
+            else if (static_cast<ossim_uint8>(c) == 0x93) // At EOC marker...
+            {
+               // Capture the size of this block.
+               theNitfBlockSize.push_back(blockSize);
+               blockSize = 0;
+            }
+         }
+      }
+   }
+
+   theFileStr.seekg(0, ios::beg);
+   theFileStr.clear();
+
+   // We should have the same amount of offsets as we do blocks...
+   ossim_uint32 total_blocks =
+      hdr->getNumberOfBlocksPerRow()*hdr->getNumberOfBlocksPerCol();
+   
+   if (theNitfBlockOffset.size() != total_blocks)
+   {
+      if (traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_WARN)
+            << "DEBUG:"
+            << "\nBlock offset count wrong!"
+            << "\nblocks:  " << total_blocks
+            << "\noffsets:  " << theNitfBlockOffset.size()
+            << std::endl;
+      }
+      
+      return false;
+   }
+   if (theNitfBlockSize.size() != total_blocks)
+   {
+      if (traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_WARN)
+            << "DEBUG:"
+            << "\nBlock size count wrong!"
+            << "\nblocks:  " << total_blocks
+            << "\nblock size array:  " << theNitfBlockSize.size()
+            << std::endl;
+      }
+
+      return false;
+   }
+
+   return true;
+}
+
+bool ossimOpjNitfReader::uncompressJpegBlock(ossim_uint32 x,
+                                             ossim_uint32 y)
+{
+   ossim_uint32 blockNumber = getBlockNumber(ossimIpt(x,y));
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimNitfTileSource::uncompressJpegBlock DEBUG:"
+         << "\nblockNumber:  " << blockNumber
+         << "\noffset to block: " << theNitfBlockOffset[blockNumber]
+         << "\nblock size: " << theNitfBlockSize[blockNumber]
+         << std::endl;
+   }
+   
+   // Seek to the block.
+   theFileStr.seekg(theNitfBlockOffset[blockNumber], ios::beg);
+
+   //---
+   // Get a buffer to read the compressed block into.  If all the blocks are
+   // the same size this will be theCompressedBuf; else we will make our own.
+   //---
+   ossim_uint8* compressedBuf = &theCompressedBuf.front();
+   if (!compressedBuf)
+   {
+      compressedBuf = new ossim_uint8[theNitfBlockSize[blockNumber]];
+   }
+
+
+   // Read the block into memory.  We could store this
+   if (!theFileStr.read((char*)compressedBuf, theNitfBlockSize[blockNumber]))
+   {
+      theFileStr.clear();
+      ossimNotify(ossimNotifyLevel_FATAL)
+         << "ossimNitfTileSource::loadBlock Read Error!"
+         << "\nReturning error..." << endl;
+      theErrorStatus = ossimErrorCodes::OSSIM_ERROR;
+      delete [] compressedBuf;
+      compressedBuf = 0;
+      return false;
+   }
+
+   try
+   {
+      //theCacheTile = decoder.decodeBuffer(compressedBuf,
+      //                                    theNitfBlockSize[blockNumber]);
+   }
+   catch (const ossimException& e)
+   {
+      ossimNotify(ossimNotifyLevel_FATAL)
+         << e.what() << std::endl;
+      theErrorStatus = ossimErrorCodes::OSSIM_ERROR;
+   }
+
+   // If theCompressedBuf is null that means we allocated the compressedBuf.
+   if (theCompressedBuf.size() == 0)
+   {
+      delete [] compressedBuf;
+      compressedBuf = 0;
+   }
+   
+   if (theErrorStatus == ossimErrorCodes::OSSIM_ERROR)
+   {
+      return false;
+   }
+   return true;
+}
diff --git a/ossim_plugins/openjpeg/ossimOpjNitfReader.h b/ossim_plugins/openjpeg/ossimOpjNitfReader.h
new file mode 100644
index 0000000..553bb48
--- /dev/null
+++ b/ossim_plugins/openjpeg/ossimOpjNitfReader.h
@@ -0,0 +1,69 @@
+//----------------------------------------------------------------------------
+//
+// License:  See top level LICENSE.txt file.
+//
+// Author:  David Burken
+//
+// Description:  Class declaration for NITF reader for j2k images using
+// OpenJPEG library.
+//
+// $Id$
+//----------------------------------------------------------------------------
+#ifndef ossimOpjNitfReader_HEADER
+#define ossimOpjNitfReader_HEADER 1
+
+#include <ossimPluginConstants.h>
+#include <ossim/imaging/ossimNitfTileSource.h>
+// #include <ossimJ2kSizRecord.h>
+// #include <ossimJ2kSotRecord.h>
+
+class OSSIM_PLUGINS_DLL ossimOpjNitfReader : public ossimNitfTileSource
+{
+public:
+
+   /** default construtor */
+   ossimOpjNitfReader();
+   
+   /** virtural destructor */
+   virtual ~ossimOpjNitfReader();
+
+protected:
+
+   /**
+    * @param hdr Pointer to image header.
+    * @return true if reader can uncompress nitf.
+    * */
+   virtual bool canUncompress(const ossimNitfImageHeader* hdr) const;
+
+   /**
+    * Initializes the data member "theReadMode" from the current entry.
+    */
+   virtual void initializeReadMode();
+
+   /**
+    * Initializes the data member theCompressedBuf.
+    */
+   virtual void initializeCompressedBuf();
+
+   /**
+    * @brief scans the file storing in offsets in "theNitfBlockOffset" and
+    * block sizes in "theNitfBlockSize".
+    * @return true on success, false on error.  This checks for arrays being
+    * the same size as number of blocks.
+    */
+   virtual bool scanForJpegBlockOffsets();
+
+   /**
+    * @brief Uncompresses a jpeg block using the jpeg-6b library.
+    * @param x sample location in image space.
+    * @param y line location in image space.
+    * @return true on success, false on error.
+    */
+   virtual bool uncompressJpegBlock(ossim_uint32 x, ossim_uint32 y);
+
+private:
+
+TYPE_DATA   
+};
+
+#endif /* #ifndef ossimOpjNitfReader_HEADER */
diff --git a/ossim_plugins/openjpeg/ossimOpjPluginInit.cpp b/ossim_plugins/openjpeg/ossimOpjPluginInit.cpp
new file mode 100644
index 0000000..5147e30
--- /dev/null
+++ b/ossim_plugins/openjpeg/ossimOpjPluginInit.cpp
@@ -0,0 +1,81 @@
+//----------------------------------------------------------------------------
+//
+// License:  See top level LICENSE.txt file
+//
+// Author:  David Burken
+//
+// Description: OSSIM Open JPEG plugin initialization
+// code.
+//
+//----------------------------------------------------------------------------
+// $Id: ossimOpjPluginInit.cpp 11046 2007-05-25 18:03:03Z gpotts $
+
+#include <ossim/plugin/ossimSharedObjectBridge.h>
+#include "ossimPluginConstants.h"
+#include "ossimOpjReaderFactory.h"
+#include "ossimOpjWriterFactory.h"
+#include <ossim/imaging/ossimImageHandlerRegistry.h>
+#include <ossim/imaging/ossimImageWriterFactoryRegistry.h>
+
+static void setDescription(ossimString& description)
+{
+   description = "Open JPEG (j2k) reader / writer plugin\n\n";
+}
+
+
+extern "C"
+{
+   ossimSharedObjectInfo  myInfo;
+   ossimString theDescription;
+   std::vector<ossimString> theObjList;
+
+   const char* getDescription()
+   {
+      return theDescription.c_str();
+   }
+
+   int getNumberOfClassNames()
+   {
+      return (int)theObjList.size();
+   }
+
+   const char* getClassName(int idx)
+   {
+      if(idx < (int)theObjList.size())
+      {
+         return theObjList[0].c_str();
+      }
+      return (const char*)0;
+   }
+
+   /* Note symbols need to be exported on windoze... */ 
+   OSSIM_PLUGINS_DLL void ossimSharedLibraryInitialize(
+      ossimSharedObjectInfo** info)
+   {    
+      myInfo.getDescription = getDescription;
+      myInfo.getNumberOfClassNames = getNumberOfClassNames;
+      myInfo.getClassName = getClassName;
+      
+      *info = &myInfo;
+      
+      /* Register the readers... */
+      ossimImageHandlerRegistry::instance()->
+        registerFactory(ossimOpjReaderFactory::instance());
+      
+      /* Register the writers... */
+      ossimImageWriterFactoryRegistry::instance()->
+         registerFactory(ossimOpjWriterFactory::instance());
+      
+      setDescription(theDescription);
+  }
+
+   /* Note symbols need to be exported on windoze... */ 
+  OSSIM_PLUGINS_DLL void ossimSharedLibraryFinalize()
+  {
+     ossimImageHandlerRegistry::instance()->
+        unregisterFactory(ossimOpjReaderFactory::instance());
+
+     ossimImageWriterFactoryRegistry::instance()->
+        unregisterFactory(ossimOpjWriterFactory::instance());
+  }
+}
diff --git a/ossim_plugins/openjpeg/ossimOpjReaderFactory.cpp b/ossim_plugins/openjpeg/ossimOpjReaderFactory.cpp
new file mode 100644
index 0000000..887cdfa
--- /dev/null
+++ b/ossim_plugins/openjpeg/ossimOpjReaderFactory.cpp
@@ -0,0 +1,244 @@
+//----------------------------------------------------------------------------
+//
+// License:  See top level LICENSE.txt file
+//
+// Author:  David Burken
+//
+// Description: Factory for J2k image readers OpenJPEG library.
+//----------------------------------------------------------------------------
+// $Id: ossimOpjReaderFactory.cpp 11046 2007-05-25 18:03:03Z gpotts $
+
+#include <ossimOpjReaderFactory.h>
+#include <ossimOpjJp2Reader.h>
+#include <ossimOpjNitfReader.h>
+#include <ossim/base/ossimKeywordlist.h>
+#include <ossim/base/ossimString.h>
+#include <ossim/imaging/ossimImageHandler.h>
+#include <ossim/base/ossimTrace.h>
+#include <ossim/base/ossimKeywordNames.h>
+
+static const ossimTrace traceDebug("ossimOpjReaderFactory:debug");
+
+RTTI_DEF1(ossimOpjReaderFactory,
+          "ossimOpjReaderFactory",
+          ossimImageHandlerFactoryBase);
+
+ossimOpjReaderFactory* ossimOpjReaderFactory::theInstance = 0;
+
+ossimOpjReaderFactory::~ossimOpjReaderFactory()
+{
+   theInstance = 0;
+}
+
+ossimOpjReaderFactory* ossimOpjReaderFactory::instance()
+{
+   if(!theInstance)
+   {
+      theInstance = new ossimOpjReaderFactory;
+   }
+   return theInstance;
+}
+   
+ossimImageHandler* ossimOpjReaderFactory::open(
+   const ossimFilename& fileName, bool openOverview) const
+{
+   static const char* M = "ossimOpjReaderFactory::open(filename)";
+   
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << M << " Entered with filename:" << fileName
+         << "\n";
+   }
+
+   ossimRefPtr<ossimImageHandler> reader = 0; 
+   while (true)
+   {
+      if (hasExcludedExtension(fileName))  break;
+
+      if (traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG) << M << " Trying ossimOpjJp2Reader...";
+      }
+      reader = new ossimOpjJp2Reader();
+      reader->setOpenOverviewFlag(openOverview);
+      if( reader->open(fileName) ) break;
+
+      if (traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG) << M << " Trying ossimOpjNitfReader...";
+      }      
+      reader = new ossimOpjNitfReader();
+      if( reader->open(fileName) ) break;
+
+      reader = 0;
+      break;
+   }
+   
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG) << M << " DEBUG: leaving..." << std::endl;
+   }
+   
+   return reader.release();
+}
+
+ossimImageHandler* ossimOpjReaderFactory::open(
+   const ossimKeywordlist& kwl, const char* prefix)const
+{
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimOpjReaderFactory::open(kwl, prefix) DEBUG: entered..."
+         << "Trying ossimOpjReader"
+         << std::endl;
+   }
+
+   ossimRefPtr<ossimImageHandler> reader = 0; 
+
+   // To save time check the file name first.
+   const char* lookup = kwl.find(prefix, ossimKeywordNames::FILENAME_KW);
+   if (!lookup)
+   {
+      // Deprecated...
+      lookup = kwl.find(prefix, ossimKeywordNames::IMAGE_FILE_KW);
+   }
+
+   if (lookup)
+   {
+      ossimFilename f = lookup;
+      if ( hasExcludedExtension(f) == false )
+      {
+         reader = new ossimOpjNitfReader;
+         if(reader->loadState(kwl, prefix) == false)
+         {
+            reader = 0;
+         }
+         
+         if (!reader)
+         {
+            reader = new ossimOpjJp2Reader;
+            if(reader->loadState(kwl, prefix) == false)
+            {
+               reader = 0;
+            }
+         }
+      }
+   }
+   
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimOpjReaderFactory::open(kwl, prefix) DEBUG: leaving..."
+         << std::endl;
+   }
+   
+   return reader.release();
+}
+
+ossimRefPtr<ossimImageHandler> ossimOpjReaderFactory::openOverview(
+   const ossimFilename& file ) const
+{
+   ossimRefPtr<ossimImageHandler> result = 0;
+   if ( file.size() )
+   {
+      result = new ossimOpjNitfReader();
+
+      result->setOpenOverviewFlag( false ); // Always false...
+
+      if( result->open( file ) == false )
+      {
+         result = 0;
+      }
+   }
+   return result;
+}
+
+ossimObject* ossimOpjReaderFactory::createObject(
+   const ossimString& typeName)const
+{
+   if(typeName == "ossimOpjJp2Reader")
+   {
+      return new ossimOpjJp2Reader;
+   }
+   else if(typeName == "ossimOpjNitfReader")
+   {
+      return new ossimOpjNitfReader;
+   }
+   return 0;
+}
+
+ossimObject* ossimOpjReaderFactory::createObject(
+   const ossimKeywordlist& kwl,
+   const char* prefix)const
+{
+   return this->open(kwl, prefix);
+}
+ 
+void ossimOpjReaderFactory::getTypeNameList(
+   std::vector<ossimString>& typeList)const
+{
+   typeList.push_back(ossimString("ossimOpjJp2Reader"));
+   typeList.push_back(ossimString("ossimOpjNitfReader"));
+}
+
+void ossimOpjReaderFactory::getSupportedExtensions(
+   ossimImageHandlerFactoryBase::UniqueStringList& extensionList) const
+{
+   extensionList.push_back(ossimString("jp2"));
+}
+
+void ossimOpjReaderFactory::getImageHandlersBySuffix(
+   ossimImageHandlerFactoryBase::ImageHandlerList& result,
+   const ossimString& ext)const
+{
+   ossimString testExt = ext.downcase();
+   if ( (testExt == "jp2") || (testExt == "j2k") )
+   {
+      result.push_back( new ossimOpjJp2Reader() );
+   }
+   else if( (testExt == "ntf") || (testExt == "nitf") )
+   {
+      result.push_back(new ossimOpjNitfReader() );
+   }
+}
+
+void ossimOpjReaderFactory::getImageHandlersByMimeType(
+   ossimImageHandlerFactoryBase::ImageHandlerList& result,
+   const ossimString& mimeType) const
+{
+   ossimString test(mimeType.begin(), mimeType.begin()+6);
+   if(test == "image/")
+   {
+      ossimString mimeTypeTest(mimeType.begin() + 6, mimeType.end());
+      if( (mimeTypeTest == "jp2") || (mimeTypeTest == "j2k") )
+      {
+         result.push_back(new ossimOpjJp2Reader);
+      }
+      else if(mimeTypeTest == "nitf")
+      {
+         result.push_back(new ossimOpjNitfReader);
+      }
+   }
+}
+
+bool ossimOpjReaderFactory::hasExcludedExtension( const ossimFilename& file) const
+{
+   bool result = false;
+   ossimString ext = file.ext().downcase();
+   if ( (ext == "tif")  ||
+        (ext == "tiff") ||
+        (ext == "jpg")  ||
+        (ext == "jpeg") ||
+        (ext == "png") )
+   {
+      result = true;
+   }
+   return result;
+}
+
+ossimOpjReaderFactory::ossimOpjReaderFactory(){}
+
+ossimOpjReaderFactory::ossimOpjReaderFactory(const ossimOpjReaderFactory&){}
+
+void ossimOpjReaderFactory::operator=(const ossimOpjReaderFactory&){}
diff --git a/ossim_plugins/openjpeg/ossimOpjReaderFactory.h b/ossim_plugins/openjpeg/ossimOpjReaderFactory.h
new file mode 100644
index 0000000..b4e49fe
--- /dev/null
+++ b/ossim_plugins/openjpeg/ossimOpjReaderFactory.h
@@ -0,0 +1,134 @@
+//----------------------------------------------------------------------------
+//
+// License:  See top level LICENSE.txt file
+//
+// Author:  David Burken
+//
+// Description: Factory for OSSIM Open JPEG reader.
+//----------------------------------------------------------------------------
+// $Id: ossimOpjReaderFactory.h 10110 2006-12-14 18:20:54Z dburken $
+#ifndef ossimOpjReaderFactory_HEADER
+#define ossimOpjReaderFactory_HEADER 1
+
+#include <ossim/imaging/ossimImageHandlerFactoryBase.h>
+
+class ossimString;
+class ossimFilename;
+class ossimKeywordlist;
+
+/** @brief Factory for PNG image reader. */
+class ossimOpjReaderFactory : public ossimImageHandlerFactoryBase
+{
+public:
+
+   /** @brief virtual destructor */
+   virtual ~ossimOpjReaderFactory();
+
+   /**
+    * @brief static method to return instance (the only one) of this class.
+    * @return pointer to instance of this class.
+    */
+   static ossimOpjReaderFactory* instance();
+
+   /**
+    * @brief open that takes a file name.
+    * @param file The file to open.
+    * @param openOverview If true image handler will attempt to open overview.
+    * default = true 
+    * @return pointer to image handler on success, NULL on failure.
+    */
+   virtual ossimImageHandler* open(const ossimFilename& fileName,
+                                   bool openOverview=true) const;
+
+   /**
+    * @brief open that takes a keyword list and prefix.
+    * @param kwl The keyword list.
+    * @param prefix the keyword list prefix.
+    * @return pointer to image handler on success, NULL on failure.
+    */
+   virtual ossimImageHandler* open(const ossimKeywordlist& kwl,
+                                   const char* prefix=0)const;
+
+   /**
+    * @brief Open overview that takes a file name.
+    *
+    * @param file File to open.
+    *
+    * @return ossimRefPtr to image handler on success or null on failure.
+    */
+   virtual ossimRefPtr<ossimImageHandler> openOverview(
+      const ossimFilename& file ) const;   
+
+   /**
+    * @brief createObject that takes a class name (ossimOpjReader)
+    * @param typeName Should be "ossimOpjReader".
+    * @return pointer to image writer on success, NULL on failure.
+    */
+   virtual ossimObject* createObject(const ossimString& typeName)const;
+   
+   /**
+    * @brief Creates and object given a keyword list and prefix.
+    * @param kwl The keyword list.
+    * @param prefix the keyword list prefix.
+    * @return pointer to image handler on success, NULL on failure.
+    */
+   virtual ossimObject* createObject(const ossimKeywordlist& kwl,
+                                     const char* prefix=0)const;
+   
+   /**
+    * @brief Adds ossimOpjWriter to the typeList.
+    * @param typeList List to add to.
+    */
+   virtual void getTypeNameList(std::vector<ossimString>& typeList)const;
+
+   /**
+    * @brief Method to add supported extension to the list, like "png".
+    *
+    * @param extensionList The list to add to.
+    */
+   virtual void getSupportedExtensions(
+      ossimImageHandlerFactoryBase::UniqueStringList& extensionList)const;
+
+   /**
+    * @brief Will add to the result list any handler that supports the passed in
+    * extensions.
+    */
+   virtual void getImageHandlersBySuffix(
+      ossimImageHandlerFactoryBase::ImageHandlerList& result,
+      const ossimString& ext) const;
+   
+   /**
+    * @brief Will add to the result list and handler that supports the passed
+    * in mime type.
+    */
+   virtual void getImageHandlersByMimeType(
+      ossimImageHandlerFactoryBase::ImageHandlerList& result,
+      const ossimString& mimeType) const;
+  
+protected:
+   
+   /**
+    * @brief Method to weed out extensions that this plugin knows it does
+    * not support.  This is to avoid a costly open on say a tiff or jpeg that
+    * is not handled by this plugin.
+    *
+    * @return true if extension, false if not.
+    */
+   bool hasExcludedExtension(const ossimFilename& file) const;
+   
+   /** @brief hidden from use default constructor */
+   ossimOpjReaderFactory();
+
+   /** @brief hidden from use copy constructor */
+   ossimOpjReaderFactory(const ossimOpjReaderFactory&);
+
+   /** @brief hidden from use copy constructor */
+   void operator=(const ossimOpjReaderFactory&);
+
+   /** static instance of this class */
+   static ossimOpjReaderFactory* theInstance;
+
+TYPE_DATA
+};
+
+#endif /* end of #ifndef ossimOpjReaderFactory_HEADER */
diff --git a/ossim_plugins/openjpeg/ossimOpjWriterFactory.cpp b/ossim_plugins/openjpeg/ossimOpjWriterFactory.cpp
new file mode 100644
index 0000000..6642349
--- /dev/null
+++ b/ossim_plugins/openjpeg/ossimOpjWriterFactory.cpp
@@ -0,0 +1,151 @@
+//----------------------------------------------------------------------------
+//
+// License:  See top level LICENSE.txt file
+//
+// Author:  David Burken
+//
+// Description: Factory for OSSIM Open JPEG writer.
+//----------------------------------------------------------------------------
+// $Id: ossimOpjWriterFactory.cpp 11046 2007-05-25 18:03:03Z gpotts $
+
+#include "ossimOpjWriterFactory.h"
+#include "ossimOpjJp2Writer.h"
+#include <ossim/base/ossimKeywordNames.h>
+#include <ossim/imaging/ossimImageFileWriter.h>
+
+ossimOpjWriterFactory* ossimOpjWriterFactory::theInstance = NULL;
+
+RTTI_DEF1(ossimOpjWriterFactory,
+          "ossimOpjWriterFactory",
+          ossimImageWriterFactoryBase);
+
+ossimOpjWriterFactory::~ossimOpjWriterFactory()
+{
+   theInstance = 0;
+}
+
+ossimOpjWriterFactory* ossimOpjWriterFactory::instance()
+{
+   if(!theInstance)
+   {
+      theInstance = new ossimOpjWriterFactory;
+   }
+   return theInstance;
+}
+
+ossimImageFileWriter *ossimOpjWriterFactory::createWriterFromExtension(
+   const ossimString& fileExtension)const
+{
+   ossimOpjJp2Writer* writer = 0;
+   if ( (fileExtension == "jp2") || (fileExtension == "JP2") || (fileExtension == "j2k"))
+   {
+      writer = new ossimOpjJp2Writer();
+   }
+   return writer;
+}
+
+ossimImageFileWriter* ossimOpjWriterFactory::createWriter(
+   const ossimKeywordlist& kwl, const char *prefix)const
+{
+   ossimRefPtr<ossimImageFileWriter> writer = 0;
+   const char* type = kwl.find(prefix, ossimKeywordNames::TYPE_KW);
+   if (type)
+   {
+      writer = createWriter(ossimString(type));
+      if (writer.valid())
+      {
+         if (writer->loadState(kwl, prefix) == false)
+         {
+            writer = 0;
+         }
+      }
+   }
+   return writer.release();
+}
+
+ossimImageFileWriter* ossimOpjWriterFactory::createWriter(
+   const ossimString& typeName)const
+{
+   ossimRefPtr<ossimImageFileWriter> writer = 0;
+   if (typeName == "ossimOpjJp2Writer")
+   {
+      writer = new ossimOpjJp2Writer;
+   }
+   else
+   {
+      // See if the type name is supported by the writer.
+      writer = new ossimOpjJp2Writer(typeName);
+      if ( writer->hasImageType(typeName) == false )
+      {
+         writer = 0;
+      }
+   }
+   return writer.release();
+}
+
+ossimObject* ossimOpjWriterFactory::createObject(
+   const ossimKeywordlist& kwl, const char *prefix)const
+{
+   return createWriter(kwl, prefix);
+}
+
+ossimObject* ossimOpjWriterFactory::createObject(
+   const ossimString& typeName) const
+{
+   return createWriter(typeName);
+}
+
+void ossimOpjWriterFactory::getExtensions(
+   std::vector<ossimString>& result)const
+{
+   result.push_back("jp2");
+   result.push_back("j2k");   
+}
+
+void ossimOpjWriterFactory::getTypeNameList(std::vector<ossimString>& typeList) const
+{
+   typeList.push_back(ossimString("ossimOpjJp2Writer"));
+}
+
+void ossimOpjWriterFactory::getImageTypeList(std::vector<ossimString>& imageTypeList) const
+{
+   // include both geotiff and gmljp2 headers
+   imageTypeList.push_back( ossimString("ossim_opj_jp2") );
+
+   // include only a geotiff header
+   imageTypeList.push_back( ossimString("ossim_opj_geojp2") ); 
+
+   // include only a gmljp2 header
+   imageTypeList.push_back( ossimString("ossim_opj_gmljp2") ); 
+}
+
+void ossimOpjWriterFactory::getImageFileWritersBySuffix(
+   ossimImageWriterFactoryBase::ImageFileWriterList& result,
+   const ossimString& ext) const
+{
+   ossimString testExt = ext.downcase();
+   if ( (testExt == "jp2") || (testExt == "j2k") )
+   {
+      result.push_back(new ossimOpjJp2Writer);
+   }
+}
+
+void ossimOpjWriterFactory::getImageFileWritersByMimeType(
+   ossimImageWriterFactoryBase::ImageFileWriterList& result,
+   const ossimString& mimeType)const
+{
+   if ( (mimeType == "image/jp2") || (mimeType == "image/j2k") )
+   {
+      result.push_back( new ossimOpjJp2Writer() );
+   }
+}
+
+ossimOpjWriterFactory::ossimOpjWriterFactory(){}
+
+ossimOpjWriterFactory::ossimOpjWriterFactory(const ossimOpjWriterFactory&){}
+
+void ossimOpjWriterFactory::operator=(const ossimOpjWriterFactory&){}
+
+
+
+
diff --git a/ossim_plugins/openjpeg/ossimOpjWriterFactory.h b/ossim_plugins/openjpeg/ossimOpjWriterFactory.h
new file mode 100644
index 0000000..88fdfe5
--- /dev/null
+++ b/ossim_plugins/openjpeg/ossimOpjWriterFactory.h
@@ -0,0 +1,120 @@
+//----------------------------------------------------------------------------
+//
+// License:  See top level LICENSE.txt file
+//
+// Author:  David Burken
+//
+// Description: Factory for OSSIM Open JPEG writer.
+//----------------------------------------------------------------------------
+// $Id: ossimOpjWriterFactory.h 10121 2006-12-14 22:38:33Z dburken $
+
+#ifndef ossimOpjWriterFactory_HEADER
+#define ossimOpjWriterFactory_HEADER
+#include <ossim/imaging/ossimImageWriterFactoryBase.h>
+
+class ossimImageFileWriter;
+class ossimKeywordlist;
+class ossimImageWriterFactory;
+
+/** @brief Factory for OpenJPEG image writer. */
+class ossimOpjWriterFactory: public ossimImageWriterFactoryBase
+{   
+public:
+
+   /** @brief virtual destructor */
+   virtual ~ossimOpjWriterFactory();
+
+   /**
+    * @brief static method to return instance (the only one) of this class.
+    * @return pointer to instance of this class.
+    */
+   static ossimOpjWriterFactory* instance();
+
+   /**
+    * @brief Creates a writer from extension like "jp2".
+    * @param fileExtension e.g. "jpg"
+    */
+   virtual ossimImageFileWriter *createWriterFromExtension(
+      const ossimString& fileExtension)const;
+
+   /**
+    * @brief Create that takes a keyword list and prefix.
+    * @param kwl The keyword list.
+    * @param prefix the keyword list prefix.
+    * @return pointer to image handler on success, NULL on failure.
+    */
+   virtual ossimImageFileWriter* createWriter(const ossimKeywordlist& kwl,
+                                              const char *prefix=0)const;
+
+   /**
+    * @brief createWriter that takes a class name (ossimOpjWriter)
+    * @param kwl The keyword list.
+    * @param prefix the keyword list prefix.
+    * @return pointer to image writer on success, NULL on failure.
+    */
+   virtual ossimImageFileWriter* createWriter(const ossimString& typeName)const;
+
+   /**
+    * @brief Creates and object given a keyword list.
+    * @param kwl The keyword list.
+    * @param prefix the keyword list prefix.
+    * @return pointer to image writer on success, NULL on failure.
+    */
+   virtual ossimObject* createObject(const ossimKeywordlist& kwl,
+                                     const char *prefix=0)const;
+
+   /**
+    * @brief createObject that takes a class name (ossimOpjWriter)
+    * @param typeName Should be "ossimOpjReader".
+    * @return pointer to image writer on success, NULL on failure.
+    */
+   virtual ossimObject* createObject(const ossimString& typeName)const;
+
+   /**
+    * @brief Adds "jp2" to list.
+    * @param extList List to add to.
+    */
+   virtual void getExtensions(std::vector<ossimString>& extList)const;
+
+   /**
+    * @brief Adds "ossimOpjWriter" to list.
+    * @param typeList List to add to.
+    */
+   virtual void getTypeNameList(std::vector<ossimString>& typeList)const;
+   
+   /**
+    * @brief Adds "ossim_opj_jp2", "ossim_opj_geojp2", and "ossim_opj_gmljp2" to writer list.
+    * @param imageTypeList List to append to.
+    */
+   virtual void getImageTypeList(std::vector<ossimString>& imageTypeList)const;
+
+   /**
+    * @brief Adds an ossimOpjJp2Writer instance to writer list.
+    * @param result List to append to.
+    * @param ext file extension should be either "jp2" or "j2k"
+    */
+   virtual void getImageFileWritersBySuffix(
+      ossimImageWriterFactoryBase::ImageFileWriterList& result,
+      const ossimString& ext ) const;
+
+   virtual void getImageFileWritersByMimeType(
+      ossimImageWriterFactoryBase::ImageFileWriterList& result,
+      const ossimString& mimeType ) const;
+   
+protected:
+   /** @brief hidden from use default constructor */
+   ossimOpjWriterFactory();
+
+   /** @brief hidden from use copy constructor */
+   ossimOpjWriterFactory(const ossimOpjWriterFactory&);
+
+   /** @brief hidden from use copy constructor */
+   void operator=(const ossimOpjWriterFactory&);
+
+   /** static instance of this class */
+   static ossimOpjWriterFactory* theInstance;
+
+TYPE_DATA
+};
+
+#endif /* end of #ifndef ossimOpjWriterFactory_HEADER */
diff --git a/ossim_plugins/ossim/AlosPalsar/AlosPalsarData.cpp b/ossim_plugins/ossim/AlosPalsar/AlosPalsarData.cpp
new file mode 100644
index 0000000..d67b456
--- /dev/null
+++ b/ossim_plugins/ossim/AlosPalsar/AlosPalsarData.cpp
@@ -0,0 +1,187 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+// "Copyright Centre for Remote Imaging, Sensing and Processing"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include <AlosPalsar/AlosPalsarData.h>
+#include <AlosPalsar/AlosPalsarRecordHeader.h>
+
+#include <AlosPalsar/AlosPalsarDataFileDescriptor.h>
+#include <AlosPalsar/AlosPalsarSignalData.h>
+
+#include <ossim/base/ossimTrace.h>
+#include <ossim/base/ossimKeywordlist.h>
+#include <ossim/base/ossimKeywordNames.h>
+
+// Static trace for debugging
+static ossimTrace traceDebug("ossimAlosPalsarData:debug");
+
+namespace ossimplugins
+{
+
+const int AlosPalsarData::AlosPalsarDataFileDescriptorID = 1;
+const int AlosPalsarData::AlosPalsarSignalDataID = 2;
+
+AlosPalsarData::AlosPalsarData()
+{
+
+}
+
+AlosPalsarData::~AlosPalsarData()
+{
+  ClearRecords();
+}
+
+std::ostream& operator<<(std::ostream& os, const AlosPalsarData& data)
+{
+  std::map<int, AlosPalsarRecord*>::const_iterator it = data._records.begin();
+  while (it != data._records.end())
+  {
+    (*it).second->Write(os);
+    ++it;
+  }
+  return os;
+
+}
+
+std::istream& operator>>(std::istream& is, AlosPalsarData& data)
+{
+
+  data.ClearRecords();
+
+  AlosPalsarRecordHeader header;
+
+  is >> header;
+
+  AlosPalsarRecord* record = new AlosPalsarDataFileDescriptor;
+  if (record != NULL)
+  {
+    record->Read(is);
+    data._records[header.get_rec_seq()] = record;
+  }
+  else
+  {
+    char* buff = new char[header.get_length()-12];
+    is.read(buff, header.get_length() - 12);
+    delete buff;
+  }
+
+  std::streampos filePosition;
+
+  filePosition = is.tellg();
+  is >> header;
+
+  record = new AlosPalsarSignalData;
+
+  if (record != NULL)
+  {
+    record->Read(is);
+    data._records[header.get_rec_seq()] = record;
+//    std::cout << "Record sequence number = " << header.get_rec_seq() << std::endl;
+  }
+  is.seekg(filePosition); // Rewind file pointer to start of record
+  // Then, advance pointer to next record
+  is.seekg(static_cast<std::streamoff>(header.get_length()), std::ios::cur);
+
+  return is;
+}
+
+
+AlosPalsarData::AlosPalsarData(const AlosPalsarData& rhs)
+{
+  std::map<int, AlosPalsarRecord*>::const_iterator it = rhs._records.begin();
+  while (it != rhs._records.end())
+  {
+    _records[(*it).first] = (*it).second->Clone();
+    ++it;
+  }
+}
+
+AlosPalsarData& AlosPalsarData::operator=(const AlosPalsarData& rhs)
+{
+  ClearRecords();
+  std::map<int, AlosPalsarRecord*>::const_iterator it = rhs._records.begin();
+  while (it != rhs._records.end())
+  {
+    _records[(*it).first] = (*it).second->Clone();
+    ++it;
+  }
+
+  return *this;
+}
+
+void AlosPalsarData::ClearRecords()
+{
+  std::map<int, AlosPalsarRecord*>::const_iterator it = _records.begin();
+  while (it != _records.end())
+  {
+    delete(*it).second;
+    ++it;
+  }
+  _records.clear();
+}
+
+bool AlosPalsarData::saveState(ossimKeywordlist& kwl,
+                               const char* prefix) const
+{
+
+  static const char MODULE[] = "AlosPalsarData::saveState";
+
+  if (traceDebug())
+  {
+    ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " entered...\n";
+  }
+
+  bool result = true;
+
+  /*
+   * Adding metadata necessary to the sensor model in the keywordlist
+   */
+  const AlosPalsarDataFileDescriptor *datafiledesc = get_AlosPalsarDataFileDescriptor();
+  if (datafiledesc != NULL)
+  {
+    kwl.add(prefix, "num_lines", datafiledesc->get_num_lines(), true);
+    kwl.add(prefix, "num_pix_in_line", datafiledesc->get_num_pix_in_line(), true);
+  }
+  else
+  {
+    result = false;
+  }
+
+  const AlosPalsarSignalData *signalData = get_AlosPalsarSignalData();
+  if (datafiledesc != NULL)
+  {
+    kwl.add(prefix, "pulse_repetition_frequency", signalData->get_pulse_repetition_frequency(), true);
+    // slant range to 1st data sample in metres
+    kwl.add(prefix, "slant_range_to_1st_data_sample", signalData->get_slant_range_to_1st_data_sample(), true);
+  }
+  else
+  {
+    result = false;
+  }
+
+
+  return result;
+}
+
+
+const AlosPalsarDataFileDescriptor * AlosPalsarData::get_AlosPalsarDataFileDescriptor() const
+{
+  return dynamic_cast<const AlosPalsarDataFileDescriptor*>(_records.find(AlosPalsarDataFileDescriptorID)->second);
+}
+
+const AlosPalsarSignalData * AlosPalsarData::get_AlosPalsarSignalData() const
+{
+  // TODO: Check if _records[AlosPalsarSignalDataID] works
+  return dynamic_cast<const AlosPalsarSignalData*>(_records.find(AlosPalsarSignalDataID)->second);
+}
+
+}
+
diff --git a/ossim_plugins/ossim/AlosPalsar/AlosPalsarData.h b/ossim_plugins/ossim/AlosPalsar/AlosPalsarData.h
new file mode 100644
index 0000000..29f0f65
--- /dev/null
+++ b/ossim_plugins/ossim/AlosPalsar/AlosPalsarData.h
@@ -0,0 +1,96 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+// "Copyright Centre for Remote Imaging, Sensing and Processing"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef AlosPalsarData_h
+#define AlosPalsarData_h
+
+#include <iostream>
+#include <map>
+
+class ossimKeywordlist;
+
+namespace ossimplugins
+{
+
+class AlosPalsarRecord;
+class AlosPalsarDataFileDescriptor;
+class AlosPalsarSignalData;
+
+/**
+ * @ingroup AlosPalsarDataFile
+ * @brief This class is able to read the Leader file of the AlosPalsar file structure
+ */
+class AlosPalsarData
+{
+public:
+  /**
+   * @brief Constructor
+   */
+  AlosPalsarData();
+
+  /**
+   * @brief Destructor
+   */
+  virtual ~AlosPalsarData();
+
+  /**
+   * @brief This function write the AlosPalsarData in a stream
+   */
+  friend std::ostream& operator<<(std::ostream& os, const AlosPalsarData& data);
+
+  /**
+   * @brief This function read a AlosPalsarData from a stream
+   */
+  friend std::istream& operator>>(std::istream& is, AlosPalsarData& data);
+
+  /**
+   * @brief Copy constructor
+   */
+  AlosPalsarData(const AlosPalsarData& rhs);
+
+  /**
+   * @brief Copy operator
+   */
+  AlosPalsarData& operator=(const AlosPalsarData& rhs);
+
+  /**
+   * @brief Remove all the previous records from the AlosPalsarData
+   */
+  void ClearRecords();
+
+
+  /**
+   * @brief Method to save object state to a keyword list.
+   * @param kwl Keyword list to save to.
+   * @param prefix added to keys when saved.
+   * @return true on success, false on error.
+   */
+  virtual bool saveState(ossimKeywordlist& kwl,
+                         const char* prefix = 0) const;
+
+
+  const AlosPalsarDataFileDescriptor * get_AlosPalsarDataFileDescriptor() const;
+  const AlosPalsarSignalData * get_AlosPalsarSignalData() const;
+
+protected:
+  typedef std::map<int, AlosPalsarRecord*> RecordType;
+  RecordType _records;
+
+
+  static const int AlosPalsarDataFileDescriptorID;
+  static const int AlosPalsarSignalDataID;
+private:
+
+};
+}
+#endif
+
diff --git a/ossim_plugins/ossim/AlosPalsar/AlosPalsarDataFileDescriptor.cpp b/ossim_plugins/ossim/AlosPalsar/AlosPalsarDataFileDescriptor.cpp
new file mode 100644
index 0000000..00847e4
--- /dev/null
+++ b/ossim_plugins/ossim/AlosPalsar/AlosPalsarDataFileDescriptor.cpp
@@ -0,0 +1,81 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+// "Copyright Centre for Remote Imaging, Sensing and Processing"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include <AlosPalsar/AlosPalsarDataFileDescriptor.h>
+
+
+namespace ossimplugins
+{
+
+AlosPalsarDataFileDescriptor::AlosPalsarDataFileDescriptor() : AlosPalsarRecord("sar_desc_rec")
+{
+}
+
+AlosPalsarDataFileDescriptor::~AlosPalsarDataFileDescriptor()
+{
+}
+
+std::ostream& operator<<(std::ostream& os, const AlosPalsarDataFileDescriptor& data)
+{
+  os << "_num_lines:" << data._num_lines << std::endl;
+  os << "_num_pix_in_line:" << data._num_pix_in_line << std::endl;
+  return os;
+}
+
+std::istream& operator>>(std::istream& is, AlosPalsarDataFileDescriptor& data)
+{
+  char buf6[7];
+  buf6[6] = '\0';
+
+  char buf168[169];
+  buf168[168] = '\0';
+
+  char buf94[95];
+  buf94[94] = '\0';
+
+  char buf8[9];
+  buf8[8] = '\0';
+
+  is.read(buf168, 168);
+
+  is.read(buf6, 6);
+  data._num_lines = atoi(buf6);
+
+  is.read(buf94, 94);
+
+  int tmpval;
+  is.read(buf8, 8);
+  tmpval = atoi(buf8);
+  data._num_pix_in_line = tmpval / 8; // Assume data always in 8-byte complex format
+
+  char buf432[433];
+  buf432[432] = '\0';
+
+  is.read(buf432, 432);
+  return is;
+}
+
+AlosPalsarDataFileDescriptor::AlosPalsarDataFileDescriptor(const AlosPalsarDataFileDescriptor& rhs):
+    AlosPalsarRecord(rhs),
+    _num_pix_in_line(rhs._num_pix_in_line),
+    _num_lines(rhs._num_lines)
+{
+}
+
+AlosPalsarDataFileDescriptor& AlosPalsarDataFileDescriptor::operator=(const AlosPalsarDataFileDescriptor& rhs)
+{
+  _num_lines = rhs._num_lines;
+  _num_pix_in_line = rhs._num_pix_in_line;
+  return *this;
+}
+}
+
diff --git a/ossim_plugins/ossim/AlosPalsar/AlosPalsarDataFileDescriptor.h b/ossim_plugins/ossim/AlosPalsar/AlosPalsarDataFileDescriptor.h
new file mode 100644
index 0000000..25846d1
--- /dev/null
+++ b/ossim_plugins/ossim/AlosPalsar/AlosPalsarDataFileDescriptor.h
@@ -0,0 +1,119 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+// "Copyright Centre for Remote Imaging, Sensing and Processing"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef AlosPalsarDataFileDescriptor_h
+#define AlosPalsarDataFileDescriptor_h
+
+
+#include<iostream>
+#include <cstdlib>
+#include <AlosPalsar/AlosPalsarRecordHeader.h>
+#include <AlosPalsar/AlosPalsarRecord.h>
+
+namespace ossimplugins
+{
+
+/**
+ * @ingroup SARLeaderAlosPalsarDataFileDescriptorRecord
+ * @brief This class is able to read the SAR leader file descriptor record of the leader file
+ */
+class AlosPalsarDataFileDescriptor : public AlosPalsarRecord
+{
+public:
+  /**
+   * @brief Constructor
+   */
+  AlosPalsarDataFileDescriptor();
+  /**
+   * @brief Destructor
+   */
+  ~AlosPalsarDataFileDescriptor();
+
+  /**
+   * @brief This function write the AlosPalsarDataFileDescriptor in a stream
+   */
+  friend std::ostream& operator<<(std::ostream& os, const AlosPalsarDataFileDescriptor& data);
+
+  /**
+   * @brief This function read a AlosPalsarDataFileDescriptor from a stream
+   */
+  friend std::istream& operator>>(std::istream& is, AlosPalsarDataFileDescriptor& data);
+
+  /**
+   * @brief Copy constructor
+   */
+  AlosPalsarDataFileDescriptor(const AlosPalsarDataFileDescriptor& rhs);
+
+  /**
+   * @brief Copy operator
+   */
+  AlosPalsarDataFileDescriptor& operator=(const AlosPalsarDataFileDescriptor& rhs);
+
+  /**
+   * @brief This function is able to create a new instance of the class
+   */
+  AlosPalsarRecord* Instanciate()
+  {
+    return new AlosPalsarDataFileDescriptor();
+  };
+
+  /**
+   * @brief This function is able to create a new instance of the class initialised with the data of the calling instance
+   */
+  AlosPalsarRecord* Clone()
+  {
+    return new AlosPalsarDataFileDescriptor(*this);
+  };
+
+  /**
+   * @brief Read the class data from a stream
+   */
+  void Read(std::istream& is)
+  {
+    is >> *this;
+  };
+
+  /**
+   * @brief Write the class to a stream
+   */
+  void Write(std::ostream& os)
+  {
+    os << *this;
+  };
+
+
+  int get_num_pix_in_line() const
+  {
+    return _num_pix_in_line;
+  };
+
+  int get_num_lines() const
+  {
+    return _num_lines;
+  };
+
+protected:
+  /**
+  * @brief num_pix_in_line
+  */
+  int   _num_pix_in_line;
+  /**
+  * @brief num_lines
+  */
+  int   _num_lines;
+
+
+private:
+};
+}
+#endif
+
diff --git a/ossim_plugins/ossim/AlosPalsar/AlosPalsarDataSetSummary.cpp b/ossim_plugins/ossim/AlosPalsar/AlosPalsarDataSetSummary.cpp
new file mode 100644
index 0000000..a4a8e51
--- /dev/null
+++ b/ossim_plugins/ossim/AlosPalsar/AlosPalsarDataSetSummary.cpp
@@ -0,0 +1,763 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+// "Copyright Centre for Remote Imaging, Sensing and Processing"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include <AlosPalsar/AlosPalsarDataSetSummary.h>
+
+namespace ossimplugins
+{
+
+AlosPalsarDataSetSummary::AlosPalsarDataSetSummary() : AlosPalsarRecord("dataset_sum_rec")
+{
+}
+
+AlosPalsarDataSetSummary::~AlosPalsarDataSetSummary()
+{
+}
+
+std::ostream& operator<<(std::ostream& os, const AlosPalsarDataSetSummary& data)
+{
+  os << "seq_num:" << data._seq_num << std::endl;
+
+  os << "sar_chn:" << data._sar_chn << std::endl;
+
+  os << "scene_id:" << data._scene_id.c_str() << std::endl;
+
+  os << "scene_des:" << data._scene_des.c_str() << std::endl;
+
+  os << "inp_sctim:" << data._inp_sctim.c_str() << std::endl;
+
+  os << "asc_des:" << data._asc_des.c_str() << std::endl;
+
+  os << "pro_lat:" << data._pro_lat << std::endl;
+
+  os << "pro_long:" << data._pro_long << std::endl;
+
+  os << "pro_head:" << data._pro_head << std::endl;
+
+  os << "ellip_des:" << data._ellip_des.c_str() << std::endl;
+
+  os << "ellip_maj:" << data._ellip_maj << std::endl;
+
+  os << "ellip_min:" << data._ellip_min << std::endl;
+  os << "earth_mass:" << data._earth_mass << std::endl;
+  os << "grav_const:" << data._grav_const << std::endl;
+  os << "ellip_j[0]:" << data._ellip_j[0] << std::endl;
+  os << "ellip_j[1]:" << data._ellip_j[1] << std::endl;
+  os << "ellip_j[2]:" << data._ellip_j[2] << std::endl;
+  os << "terrain_h:" << data._terrain_h << std::endl;
+  os << "sc_lin:" << data._sc_lin << std::endl;
+  os << "sc_pix:" << data._sc_pix << std::endl;
+  os << "scene_len:" << data._scene_len << std::endl;
+  os << "scene_wid:" << data._scene_wid << std::endl;
+  os << "nchn:" << data._nchn << std::endl;
+  os << "mission_id:" << data._mission_id.c_str() << std::endl;
+  os << "sensor_id:" << data._sensor_id.c_str() << std::endl;
+  os << "orbit_num:" << data._orbit_num.c_str() << std::endl;
+
+  os << "plat_lat:" << data._plat_lat << std::endl;
+
+  os << "plat_long:" << data._plat_long << std::endl;
+
+  os << "plat_head:" << data._plat_head << std::endl;
+
+  os << "clock_ang:" << data._clock_ang << std::endl;
+
+  os << "incident_ang:" << data._incident_ang << std::endl;
+
+
+  os << "wave_length:" << data._wave_length << std::endl;
+
+  os << "motion_comp:" << data._motion_comp.c_str() << std::endl;
+
+  os << "pulse_code:" << data._pulse_code.c_str() << std::endl;
+
+  for (int i = 0; i < 5; i++)
+  {
+    os << "ampl_coef[" << i << "]:" << data._ampl_coef[i] << std::endl;
+  }
+
+  for (int i = 0; i < 5; i++)
+  {
+    os << "phas_coef[" << i << "]:" << data._phas_coef[i] << std::endl;
+  }
+
+  os << "chirp_ext_ind:" << data._chirp_ext_ind << std::endl;
+
+  os << "fr:" << data._fr << std::endl;
+
+  os << "rng_gate:" << data._rng_gate << std::endl;
+
+  os << "rng_length:" << data._rng_length << std::endl;
+
+  os << "baseband_f:" << data._baseband_f.c_str() << std::endl;
+
+  os << "rngcmp_f:" << data._rngcmp_f.c_str() << std::endl;
+
+  os << "gn_polar:" << data._gn_polar << std::endl;
+
+  os << "gn_cross:" << data._gn_cross << std::endl;
+
+  os << "chn_bits:" << data._chn_bits << std::endl;
+
+  os << "quant_desc:" << data._quant_desc.c_str() << std::endl;
+
+  os << "i_bias:" << data._i_bias << std::endl;
+
+  os << "q_bias:" << data._q_bias << std::endl;
+
+  os << "iq_ratio:" << data._iq_ratio << std::endl;
+
+  os << "mech_sight:" << data._mech_sight << std::endl;
+
+  os << "fa:" << data._fa << std::endl;
+
+  os << "sat_bintim:" << data._sat_bintim.c_str() << std::endl;
+
+  os << "sat_clktim:" << data._sat_clktim.c_str() << std::endl;
+
+  os << "sat_clkinc:" << data._sat_clkinc.c_str() << std::endl;
+
+  os << "fac_id:" << data._fac_id.c_str() << std::endl;
+
+  os << "sys_id:" << data._sys_id.c_str() << std::endl;
+
+  os << "ver_id:" << data._ver_id.c_str() << std::endl;
+
+  os << "prod_type:" << data._prod_type.c_str() << std::endl;
+
+  os << "algor_id:" << data._algor_id.c_str() << std::endl;
+
+  os << "n_azilok:" << data._n_azilok << std::endl;
+
+  os << "n_rnglok:" << data._n_rnglok << std::endl;
+
+  os << "bnd_azilok:" << data._bnd_azilok << std::endl;
+
+  os << "bnd_rnglok:" << data._bnd_rnglok << std::endl;
+
+  os << "bnd_azi:" << data._bnd_azi << std::endl;
+
+  os << "bnd_rng:" << data._bnd_rng << std::endl;
+
+  os << "azi_weight:" << data._azi_weight.c_str() << std::endl;
+
+  os << "rng_weight:" << data._rng_weight.c_str() << std::endl;
+
+  os << "data_inpsrc:" << data._data_inpsrc.c_str() << std::endl;
+
+  os << "rng_res:" << data._rng_res << std::endl;
+
+  os << "azi_res:" << data._azi_res << std::endl;
+
+  os << "alt_dopcen[0]:" << data._alt_dopcen[0] << std::endl;
+  os << "alt_dopcen[1]:" << data._alt_dopcen[1] << std::endl;
+  os << "alt_dopcen[2]:" << data._alt_dopcen[2] << std::endl;
+
+  os << "crt_dopcen[0]:" << data._crt_dopcen[0] << std::endl;
+  os << "crt_dopcen[1]:" << data._crt_dopcen[1] << std::endl;
+  os << "crt_dopcen[2]:" << data._crt_dopcen[2] << std::endl;
+
+  os << "time_dir_pix:" << data._time_dir_pix.c_str() << std::endl;
+
+  os << "time_dir_lin:" << data._time_dir_lin.c_str() << std::endl;
+
+  os << "alt_rate[0]:" << data._alt_rate[0] << std::endl;
+  os << "alt_rate[1]:" << data._alt_rate[1] << std::endl;
+  os << "alt_rate[2]:" << data._alt_rate[2] << std::endl;
+
+  os << "crt_rate[0]:" << data._crt_rate[0] << std::endl;
+  os << "crt_rate[1]:" << data._crt_rate[1] << std::endl;
+  os << "crt_rate[2]:" << data._crt_rate[2] << std::endl;
+
+  os << "clutter_lock:" << data._line_cont.c_str() << std::endl;
+
+  os << "clutter_lock:" << data._clutter_lock.c_str() << std::endl;
+
+  os << "auto_focus:" << data._auto_focus.c_str() << std::endl;
+
+  os << "line_spacing:" << data._line_spacing << std::endl;
+
+  os << "pix_spacing:" << data._pix_spacing << std::endl;
+
+  os << "rngcmp_desg:" << data._rngcmp_desg.c_str() << std::endl;
+
+
+  os << "dopcen_range[0]:" << data._dopcen_range[0] << std::endl;
+  os << "dopcen_range[1]:" << data._dopcen_range[1] << std::endl;
+  /**
+  * @Data from 1767 to 4096 to be added
+  */
+
+  return os;
+
+}
+
+std::istream& operator>>(std::istream& is, AlosPalsarDataSetSummary& data)
+{
+  char buf16[17];
+  buf16[16] = '\0';
+  char buf32[33];
+  buf32[32] = '\0';
+  char buf8[9];
+  buf8[8] = '\0';
+  char buf4[5];
+  buf4[4] = '\0';
+  char buf2330[2331];  //data skip from  1767 to 4096//
+  buf2330[2330] = '\0';   //data skip from  1767 to 4096//
+
+  is.read(buf4, 4);
+  data._seq_num = atoi(buf4);
+
+  is.read(buf4, 4);
+  data._sar_chn = atoi(buf4);
+
+  is.read(buf16, 16);
+  data._scene_id = buf16;
+
+  is.read(buf32, 32);
+  data._scene_des = buf32;
+
+  is.read(buf32, 32);
+  data._inp_sctim = buf32;
+
+  is.read(buf16, 16);
+  data._asc_des = buf16;
+
+  is.read(buf16, 16);
+  data._pro_lat = atof(buf16);
+
+  is.read(buf16, 16);
+  data._pro_long = atof(buf16);
+
+  is.read(buf16, 16);
+  data._pro_head = atof(buf16);
+
+  is.read(buf16, 16);
+  data._ellip_des = buf16;
+
+  is.read(buf16, 16);
+  data._ellip_maj = atof(buf16);
+
+  is.read(buf16, 16);
+  data._ellip_min = atof(buf16);
+
+  is.read(buf16, 16);
+  data._earth_mass = atof(buf16);
+
+  is.read(buf16, 16);
+  data._grav_const = atof(buf16);
+
+  is.read(buf16, 16);
+  data._ellip_j[0] = atof(buf16);
+  is.read(buf16, 16);
+  data._ellip_j[1] = atof(buf16);
+  is.read(buf16, 16);
+  data._ellip_j[2] = atof(buf16);
+
+  is.read(buf16, 16);
+
+  is.read(buf16, 16);
+  data._terrain_h = atof(buf16);
+
+  is.read(buf8, 8);
+  data._sc_lin = atoi(buf8);
+
+  is.read(buf8, 8);
+  data._sc_pix = atoi(buf8);
+
+  is.read(buf16, 16);
+  data._scene_len = atof(buf16);
+
+  is.read(buf16, 16);
+  data._scene_wid = atof(buf16);
+
+  is.read(buf16, 16);
+
+  is.read(buf4, 4);
+  data._nchn = atoi(buf4);
+
+  is.read(buf4, 4);
+
+  is.read(buf16, 16);
+  data._mission_id = buf16;
+
+  is.read(buf32, 32);
+  data._sensor_id = buf32;
+
+  is.read(buf8, 8);
+  data._orbit_num = buf8;
+
+  is.read(buf8, 8);
+  data._plat_lat = atof(buf8);
+
+  is.read(buf8, 8);
+  data._plat_long = atof(buf8);
+
+  is.read(buf8, 8);
+  data._plat_head = atof(buf8);
+
+  is.read(buf8, 8);
+  data._clock_ang = atof(buf8);
+
+  is.read(buf8, 8);
+  data._incident_ang = atof(buf8);
+
+  is.read(buf8, 8);
+
+  is.read(buf16, 16);
+  data._wave_length = atof(buf16);
+
+  is.read(buf8, 2);
+  buf8[2] = '\0';
+  data._motion_comp = buf8;
+
+  is.read(buf16, 16);
+  data._pulse_code = buf16;
+
+  for (int i = 0; i < 5; i++)
+  {
+    is.read(buf16, 16);
+    data._ampl_coef[i] = atof(buf16);
+  }
+
+  for (int i = 0; i < 5; i++)
+  {
+    is.read(buf16, 16);
+    data._phas_coef[i] = atof(buf16);
+  }
+
+  is.read(buf8, 8);
+  data._chirp_ext_ind = atoi(buf8);
+
+  is.read(buf8, 8);
+
+  is.read(buf16, 16);
+  data._fr = atof(buf16);
+
+  is.read(buf16, 16);
+  data._rng_gate = atof(buf16);
+
+  is.read(buf16, 16);
+  data._rng_length = atof(buf16);
+
+  is.read(buf8, 4);
+  buf8[4] = '\0';
+  data._baseband_f = buf8;
+
+  is.read(buf8, 4);
+  buf8[4] = '\0';
+  data._rngcmp_f = buf8;
+
+  is.read(buf16, 16);
+  data._gn_polar = atof(buf16);
+
+  is.read(buf16, 16);
+  data._gn_cross = atof(buf16);
+
+  is.read(buf8, 8);
+  data._chn_bits = atoi(buf8);
+
+  is.read(buf16, 12);
+  buf16[12] = '\0';
+  data._quant_desc = buf16;
+
+  is.read(buf16, 16);
+  data._i_bias = atof(buf16);
+
+  is.read(buf16, 16);
+  data._q_bias = atof(buf16);
+
+  is.read(buf16, 16);
+  data._iq_ratio = atof(buf16);
+
+  is.read(buf32, 32);
+
+  is.read(buf16, 16);
+
+  is.read(buf16, 16);
+  data._mech_sight = atof(buf16);
+
+  is.read(buf4, 4);
+
+  is.read(buf16, 16);
+  data._fa = atof(buf16);
+
+  is.read(buf16, 16);
+
+  is.read(buf16, 16);
+
+  is.read(buf16, 16);
+  data._sat_bintim = buf16;
+
+  is.read(buf32, 32);
+  data._sat_clktim = buf32;
+
+  is.read(buf8, 8);
+  data._sat_clkinc = buf8;
+
+  is.read(buf8, 8);
+
+  is.read(buf16, 16);
+  data._fac_id = buf16;
+
+  is.read(buf8, 8);
+  data._sys_id = buf8;
+
+  is.read(buf8, 8);
+  data._ver_id = buf8;
+
+  is.read(buf32, 32);
+
+  is.read(buf32, 32);
+  data._prod_type = buf32;
+
+  is.read(buf32, 32);
+  data._algor_id = buf32;
+
+  is.read(buf16, 16);
+  data._n_azilok = atof(buf16);
+
+  is.read(buf16, 16);
+  data._n_rnglok = atof(buf16);
+
+  is.read(buf16, 16);
+  data._bnd_azilok = atof(buf16);
+
+  is.read(buf16, 16);
+  data._bnd_rnglok = atof(buf16);
+
+  is.read(buf16, 16);
+  data._bnd_azi = atof(buf16);
+
+  is.read(buf16, 16);
+  data._bnd_rng = atof(buf16);
+
+  is.read(buf32, 32);
+  data._azi_weight = buf32;
+
+  is.read(buf32, 32);
+  data._rng_weight = buf32;
+
+  is.read(buf16, 16);
+  data._data_inpsrc = buf16;
+
+  is.read(buf16, 16);
+  data._rng_res = atof(buf16);
+
+  is.read(buf16, 16);
+  data._azi_res = atof(buf16);
+
+  is.read(buf32, 32);
+
+  is.read(buf16, 16);
+  data._alt_dopcen[0] = atof(buf16);
+  is.read(buf16, 16);
+  data._alt_dopcen[1] = atof(buf16);
+  is.read(buf16, 16);
+  data._alt_dopcen[2] = atof(buf16);
+
+  is.read(buf16, 16);
+
+  is.read(buf16, 16);
+  data._crt_dopcen[0] = atof(buf16);
+  is.read(buf16, 16);
+  data._crt_dopcen[1] = atof(buf16);
+  is.read(buf16, 16);
+  data._crt_dopcen[2] = atof(buf16);
+
+  is.read(buf8, 8);
+  data._time_dir_pix = buf8;
+
+  is.read(buf8, 8);
+  data._time_dir_lin = buf8;
+
+  is.read(buf16, 16);
+  data._alt_rate[0] = atof(buf16);
+  is.read(buf16, 16);
+  data._alt_rate[1] = atof(buf16);
+  is.read(buf16, 16);
+  data._alt_rate[2] = atof(buf16);
+
+  is.read(buf16, 16);
+
+  is.read(buf16, 16);
+  data._crt_rate[0] = atof(buf16);
+  is.read(buf16, 16);
+  data._crt_rate[1] = atof(buf16);
+  is.read(buf16, 16);
+  data._crt_rate[2] = atof(buf16);
+
+  is.read(buf16, 16);
+
+  is.read(buf8, 8);
+  data._line_cont = buf8;
+
+  is.read(buf4, 4);
+  data._clutter_lock = buf4;
+
+  is.read(buf4, 4);
+  data._auto_focus = buf4;
+
+  is.read(buf16, 16);
+  data._line_spacing = atof(buf16);
+
+  is.read(buf16, 16);
+  data._pix_spacing = atof(buf16);
+
+  is.read(buf16, 16);
+  data._rngcmp_desg = buf16;
+
+  is.read(buf16, 16);
+  data._dopcen_range[0] = atof(buf16);
+
+  is.read(buf16, 16);
+  data._dopcen_range[1] = atof(buf16);
+
+  /**
+  * @Data from 1767 to 4096 to be added
+  */
+
+  is.read(buf2330, 2330);
+
+  return is;
+}
+
+
+AlosPalsarDataSetSummary::AlosPalsarDataSetSummary(const AlosPalsarDataSetSummary& rhs):
+    AlosPalsarRecord(rhs),
+    _seq_num(rhs._seq_num),
+    _sar_chn(rhs._sar_chn),
+    _scene_id(rhs._scene_id),
+    _scene_des(rhs._scene_des),
+    _inp_sctim(rhs._inp_sctim),
+    _asc_des(rhs._asc_des),
+    _pro_lat(rhs._pro_lat),
+    _pro_long(rhs._pro_long),
+    _pro_head(rhs._pro_head),
+    _ellip_des(rhs._ellip_des),
+    _ellip_maj(rhs._ellip_maj),
+    _ellip_min(rhs._ellip_min),
+    _earth_mass(rhs._earth_mass),
+    _grav_const(rhs._grav_const),
+    _terrain_h(rhs._terrain_h),
+    _sc_lin(rhs._sc_lin),
+    _sc_pix(rhs._sc_pix),
+    _scene_len(rhs._scene_len),
+    _scene_wid(rhs._scene_wid),
+    _nchn(rhs._nchn),
+    _mission_id(rhs._mission_id),
+    _sensor_id(rhs._sensor_id),
+    _orbit_num(rhs._orbit_num),
+    _plat_lat(rhs._plat_lat),
+    _plat_long(rhs._plat_long),
+    _plat_head(rhs._plat_head),
+    _clock_ang(rhs._clock_ang),
+    _incident_ang(rhs._incident_ang),
+    _wave_length(rhs._wave_length),
+    _motion_comp(rhs._motion_comp),
+    _pulse_code(rhs._pulse_code),
+    _chirp_ext_ind(rhs._chirp_ext_ind),
+    _fr(rhs._fr),
+    _rng_gate(rhs._rng_gate),
+    _rng_length(rhs._rng_length),
+    _baseband_f(rhs._baseband_f),
+    _rngcmp_f(rhs._rngcmp_f),
+    _gn_polar(rhs._gn_polar),
+    _gn_cross(rhs._gn_cross),
+    _chn_bits(rhs._chn_bits),
+    _quant_desc(rhs._quant_desc),
+    _i_bias(rhs._i_bias),
+    _q_bias(rhs._q_bias),
+    _iq_ratio(rhs._iq_ratio),
+    _mech_sight(rhs._mech_sight),
+    _fa(rhs._fa),
+    _sat_bintim(rhs._sat_bintim),
+    _sat_clktim(rhs._sat_clktim),
+    _sat_clkinc(rhs._sat_clkinc),
+    _fac_id(rhs._fac_id),
+    _sys_id(rhs._sys_id),
+    _ver_id(rhs._ver_id),
+    _prod_type(rhs._prod_type),
+    _algor_id(rhs._algor_id),
+    _n_azilok(rhs._n_azilok),
+    _n_rnglok(rhs._n_rnglok),
+    _bnd_azilok(rhs._bnd_azilok),
+    _bnd_rnglok(rhs._bnd_rnglok),
+    _bnd_azi(rhs._bnd_azi),
+    _bnd_rng(rhs._bnd_rng),
+    _azi_weight(rhs._azi_weight),
+    _rng_weight(rhs._rng_weight),
+    _data_inpsrc(rhs._data_inpsrc),
+    _rng_res(rhs._rng_res),
+    _azi_res(rhs._azi_res),
+    _time_dir_pix(rhs._time_dir_pix),
+    _time_dir_lin(rhs._time_dir_lin),
+    _line_cont(rhs._line_cont),
+    _clutter_lock(rhs._clutter_lock),
+    _auto_focus(rhs._auto_focus),
+    _line_spacing(rhs._line_spacing),
+    _pix_spacing(rhs._pix_spacing),
+    _rngcmp_desg(rhs._rngcmp_desg)
+
+
+//to be added//
+
+{
+  _ellip_j[0] = rhs._ellip_j[0];
+  _ellip_j[1] = rhs._ellip_j[1];
+  _ellip_j[2] = rhs._ellip_j[2];
+  _ampl_coef[0] = rhs._ampl_coef[0];
+  _ampl_coef[1] = rhs._ampl_coef[1];
+  _ampl_coef[2] = rhs._ampl_coef[2];
+  _ampl_coef[3] = rhs._ampl_coef[3];
+  _ampl_coef[4] = rhs._ampl_coef[4];
+  _phas_coef[0] = rhs._phas_coef[0];
+  _phas_coef[1] = rhs._phas_coef[1];
+  _phas_coef[2] = rhs._phas_coef[2];
+  _phas_coef[3] = rhs._phas_coef[3];
+  _phas_coef[4] = rhs._phas_coef[4];
+
+  _alt_dopcen[0] = rhs._alt_dopcen[0];
+  _alt_dopcen[1] = rhs._alt_dopcen[1];
+  _alt_dopcen[2] = rhs._alt_dopcen[2];
+
+  _crt_dopcen[0] = rhs._crt_dopcen[0];
+  _crt_dopcen[1] = rhs._crt_dopcen[1];
+  _crt_dopcen[2] = rhs._crt_dopcen[2];
+
+  _alt_rate[0] = rhs._alt_rate[0];
+  _alt_rate[1] = rhs._alt_rate[1];
+  _alt_rate[2] = rhs._alt_rate[2];
+  _crt_rate[0] = rhs._crt_rate[0];
+  _crt_rate[1] = rhs._crt_rate[1];
+  _crt_rate[2] = rhs._crt_rate[2];
+
+  _dopcen_range[0] = rhs._dopcen_range[0];
+  _dopcen_range[1] = rhs._dopcen_range[1];
+
+}
+
+AlosPalsarDataSetSummary& AlosPalsarDataSetSummary::operator=(const AlosPalsarDataSetSummary& rhs)
+{
+  _seq_num = rhs._seq_num;
+  _sar_chn = rhs._sar_chn;
+  _scene_id = rhs._scene_id;
+  _scene_des = rhs._scene_des;
+  _inp_sctim = rhs._inp_sctim;
+  _asc_des = rhs._asc_des;
+  _pro_lat = rhs._pro_lat;
+  _pro_long = rhs._pro_long;
+  _pro_head = rhs._pro_head;
+  _ellip_des = rhs._ellip_des;
+  _ellip_maj = rhs._ellip_maj;
+  _ellip_min = rhs._ellip_min;
+  _earth_mass = rhs._earth_mass;
+  _grav_const = rhs._grav_const;
+  _terrain_h = rhs._terrain_h;
+  _sc_lin = rhs._sc_lin;
+  _sc_pix = rhs._sc_pix;
+  _scene_len = rhs._scene_len;
+  _scene_wid = rhs._scene_wid;
+  _nchn = rhs._nchn;
+  _mission_id = rhs._mission_id;
+  _sensor_id = rhs._sensor_id;
+  _orbit_num = rhs._orbit_num;
+  _plat_lat = rhs._plat_lat;
+  _plat_long = rhs._plat_long;
+  _plat_head = rhs._plat_head;
+  _clock_ang = rhs._clock_ang;
+  _incident_ang = rhs._incident_ang;
+  _wave_length = rhs._wave_length;
+  _motion_comp = rhs._motion_comp;
+  _pulse_code = rhs._pulse_code;
+  _chirp_ext_ind = rhs._chirp_ext_ind;
+  _fr = rhs._fr;
+  _rng_gate = rhs._rng_gate;
+  _rng_length = rhs._rng_length;
+  _baseband_f = rhs._baseband_f;
+  _rngcmp_f = rhs._rngcmp_f;
+  _gn_polar = rhs._gn_polar;
+  _gn_cross = rhs._gn_cross;
+  _chn_bits = rhs._chn_bits;
+  _quant_desc = rhs._quant_desc;
+  _i_bias = rhs._i_bias;
+  _q_bias = rhs._q_bias;
+  _iq_ratio = rhs._iq_ratio;
+  _mech_sight = rhs._mech_sight;
+  _fa = rhs._fa;
+  _sat_bintim = rhs._sat_bintim;
+  _sat_clktim = rhs._sat_clktim;
+  _sat_clkinc = rhs._sat_clkinc;
+  _fac_id = rhs._fac_id;
+  _sys_id = rhs._sys_id;
+  _ver_id = rhs._ver_id;
+  _prod_type = rhs._prod_type;
+  _algor_id = rhs._algor_id;
+  _n_azilok = rhs._n_azilok;
+  _n_rnglok = rhs._n_rnglok;
+  _bnd_azilok = rhs._bnd_azilok;
+  _bnd_rnglok = rhs._bnd_rnglok;
+  _bnd_azi = rhs._bnd_azi;
+  _bnd_rng = rhs._bnd_rng;
+  _azi_weight = rhs._azi_weight;
+  _rng_weight = rhs._rng_weight;
+  _data_inpsrc = rhs._data_inpsrc;
+  _rng_res = rhs._rng_res;
+  _azi_res = rhs._azi_res;
+  _time_dir_pix = rhs._time_dir_pix;
+  _time_dir_lin = rhs._time_dir_lin;
+  _line_cont = rhs._line_cont;
+  _clutter_lock = rhs._clutter_lock;
+  _auto_focus = rhs._auto_focus;
+  _line_spacing = rhs._line_spacing;
+  _pix_spacing = rhs._pix_spacing;
+  _rngcmp_desg = rhs._rngcmp_desg;
+
+  _ellip_j[0] = rhs._ellip_j[0];
+  _ellip_j[1] = rhs._ellip_j[1];
+  _ellip_j[2] = rhs._ellip_j[2];
+  _ampl_coef[0] = rhs._ampl_coef[0];
+  _ampl_coef[1] = rhs._ampl_coef[1];
+  _ampl_coef[2] = rhs._ampl_coef[2];
+  _ampl_coef[3] = rhs._ampl_coef[3];
+  _ampl_coef[4] = rhs._ampl_coef[4];
+  _phas_coef[0] = rhs._phas_coef[0];
+  _phas_coef[1] = rhs._phas_coef[1];
+  _phas_coef[2] = rhs._phas_coef[2];
+  _phas_coef[3] = rhs._phas_coef[3];
+  _phas_coef[4] = rhs._phas_coef[4];
+
+  _alt_dopcen[0] = rhs._alt_dopcen[0];
+  _alt_dopcen[1] = rhs._alt_dopcen[1];
+  _alt_dopcen[2] = rhs._alt_dopcen[2];
+
+  _crt_dopcen[0] = rhs._crt_dopcen[0];
+  _crt_dopcen[1] = rhs._crt_dopcen[1];
+  _crt_dopcen[2] = rhs._crt_dopcen[2];
+
+  _alt_rate[0] = rhs._alt_rate[0];
+  _alt_rate[1] = rhs._alt_rate[1];
+  _alt_rate[2] = rhs._alt_rate[2];
+  _crt_rate[0] = rhs._crt_rate[0];
+  _crt_rate[1] = rhs._crt_rate[1];
+  _crt_rate[2] = rhs._crt_rate[2];
+
+  _dopcen_range[0] = rhs._dopcen_range[0];
+  _dopcen_range[1] = rhs._dopcen_range[1];
+
+//to be added//
+
+
+  return *this;
+}
+}
+
diff --git a/ossim_plugins/ossim/AlosPalsar/AlosPalsarDataSetSummary.h b/ossim_plugins/ossim/AlosPalsar/AlosPalsarDataSetSummary.h
new file mode 100644
index 0000000..2c66ee2
--- /dev/null
+++ b/ossim_plugins/ossim/AlosPalsar/AlosPalsarDataSetSummary.h
@@ -0,0 +1,1025 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+// "Copyright Centre for Remote Imaging, Sensing and Processing"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef AlosPalsarDataSetSummary_h
+#define AlosPalsarDataSetSummary_h
+
+#include <iostream>
+#include <cstdlib>
+#include <AlosPalsar/AlosPalsarRecordHeader.h>
+#include <AlosPalsar/AlosPalsarRecord.h>
+
+namespace ossimplugins
+{
+
+/**
+ * @ingroup AlosPalsarDataSetSummaryRecord
+ * @brief This class is able to read the SAR leader data set summary record of the leader file
+ */
+class AlosPalsarDataSetSummary : public AlosPalsarRecord
+{
+public:
+  /**
+   * @brief Constructor
+   */
+  AlosPalsarDataSetSummary();
+
+  /**
+   * @brief Destructor
+   */
+  virtual ~AlosPalsarDataSetSummary();
+
+  /**
+   * @brief This function write the AlosPalsarDataSetSummary in a stream
+   */
+  friend std::ostream& operator<<(std::ostream& os, const AlosPalsarDataSetSummary& data);
+
+  /**
+   * @brief This function read a AlosPalsarDataSetSummary from a stream
+   */
+  friend std::istream& operator>>(std::istream& is, AlosPalsarDataSetSummary& data);
+
+  /**
+   * @brief Copy constructor
+   */
+  AlosPalsarDataSetSummary(const AlosPalsarDataSetSummary& rhs);
+
+  /**
+   * @brief Copy operator
+   */
+  AlosPalsarDataSetSummary& operator=(const AlosPalsarDataSetSummary& rhs);
+
+  /**
+   * @brief This function is able to create a new instance of the class
+   */
+  AlosPalsarRecord* Instanciate()
+  {
+    return new AlosPalsarDataSetSummary();
+  };
+
+  /**
+   * @brief This function is able to create a new instance of the class initialised with the data of the calling instance
+   */
+  AlosPalsarRecord* Clone()
+  {
+    return new AlosPalsarDataSetSummary(*this);
+  };
+
+  /**
+   * @brief Read the class data from a stream
+   */
+  void Read(std::istream& is)
+  {
+    is >> *this;
+  };
+
+  /**
+   * @brief Write the class to a stream
+   */
+  void Write(std::ostream& os)
+  {
+    os << *this;
+  };
+
+  /**
+   * @brief Sequence number
+   */
+  int   get_seq_num() const
+  {
+    return _seq_num;
+  };
+  /**
+  * @brief SAR channel indicator
+  */
+  int   get_sar_chn() const
+  {
+    return _sar_chn;
+  };
+  /**
+   * @brief Scene identifier
+   */
+  std::string   get_scene_id() const
+  {
+    return _scene_id;
+  };
+  /**
+   * @brief Scene designator
+   */
+  std::string   get_scene_des() const
+  {
+    return _scene_des;
+  };
+  /**
+   * @brief Input scene centre time
+   */
+  std::string   get_inp_sctim() const
+  {
+    return _inp_sctim;
+  };
+  /**
+   * @brief Ascending/descending
+   */
+  std::string   get_asc_des() const
+  {
+    return _asc_des;
+  };
+  /**
+  * @brief Processed scene centre latitude
+  */
+  double   get_pro_lat() const
+  {
+    return _pro_lat;
+  };
+  /**
+  * @brief Processed scene centre longitude
+  */
+  double   get_pro_long() const
+  {
+    return _pro_long;
+  };
+  /**
+  * @brief Processed scene centre headng
+  */
+  double   get_pro_head() const
+  {
+    return _pro_head;
+  };
+  /**
+   * @brief Ellipsoid designator
+   */
+  std::string   get_ellip_des() const
+  {
+    return _ellip_des;
+  };
+  /**
+  * @brief Ellipsoid semi-major axis, km
+  */
+  double   get_ellip_maj() const
+  {
+    return _ellip_maj;
+  };
+  /**
+  * @brief Ellipsoid semi_minor axis, km
+  */
+  double  get_ellip_min() const
+  {
+    return _ellip_min;
+  };
+  /**
+   * @brief Earth's mass
+   */
+  double   get_earth_mass() const
+  {
+    return _earth_mass;
+  };
+  /**
+  * @brief Gravitational constant
+  */
+  double   get_grav_const() const
+  {
+    return _grav_const;
+  };
+  /**
+  * @brief Ellipsoid J2-4 parameters
+  */
+  const double*   get_ellip_j() const
+  {
+    return _ellip_j;
+  };
+
+  /**
+  * @brief Average terrain height, km
+  */
+  double   get_terrain_h() const
+  {
+    return _terrain_h;
+  };
+  /**
+  * @brief Scene centre line number
+  */
+  int   get_sc_lin() const
+  {
+    return _sc_lin;
+  };
+  /**
+  * @brief Scene centre pixel number
+  */
+  int   get_sc_pix() const
+  {
+    return _sc_pix;
+  };
+  /**
+  * @brief Scene length, km
+  */
+  double   get_scene_len() const
+  {
+    return _scene_len;
+  };
+  /**
+  * @brief Scene width, km
+  */
+  double   get_scene_wid() const
+  {
+    return _scene_wid;
+  };
+
+  /**
+  * @brief Number of SAR channels
+  */
+  double   get_nchn() const
+  {
+    return _nchn;
+  };
+
+  /**
+  * @brief Mission identifier
+  */
+  std::string   get_mission_id() const
+  {
+    return _mission_id;
+  };
+  /**
+  * @brief Sensor identifier
+  */
+  std::string   get_sensor_id() const
+  {
+    return _sensor_id;
+  };
+  /**
+  * @brief Orbit number
+  */
+  std::string   get_orbit_num() const
+  {
+    return _orbit_num;
+  };
+  /**
+  * @brief Platform geodetic latitude
+  */
+  double   get_plat_lat() const
+  {
+    return _plat_lat;
+  };
+  /**
+  * @brief Platform geodetic longitude
+  */
+  double   get_plat_long() const
+  {
+    return _plat_long;
+  };
+  /**
+  * @brief Platform heading
+  */
+  double   get_plat_head() const
+  {
+    return _plat_head;
+  };
+  /**
+  * @brief Sensor clock angle
+  */
+  double   get_clock_ang() const
+  {
+    return _clock_ang;
+  };
+  /**
+  * @brief Incidence angle
+  */
+  double   get_incident_ang() const
+  {
+    return _incident_ang;
+  };
+
+  /**
+  * @brief Radar wave length
+  */
+  double   get_wave_length() const
+  {
+    return _wave_length;
+  };
+  /**
+  * @brief Motion compensation indicator
+  */
+  std::string   get_motion_comp() const
+  {
+    return _motion_comp;
+  };
+  /**
+  * @brief Range pulse code specifier
+  */
+  std::string   get_pulse_code() const
+  {
+    return _pulse_code;
+  };
+  /**
+  * @brief Range chirp coefficients
+  */
+  const double*   get_ampl_coef() const
+  {
+    return _ampl_coef;
+  };
+  /**
+  * @brief Range phase coefficients
+  */
+  const double*   get_phas_coef() const
+  {
+    return _phas_coef;
+  };
+  /**
+  * @brief Chirp extraction index
+  */
+  int   get_chirp_ext_ind() const
+  {
+    return _chirp_ext_ind;
+  };
+
+  /**
+  * @brief Range sampling rate
+  */
+  double   get_fr() const
+  {
+    return _fr;
+  };
+  /**
+  * @brief Range gate start time
+  */
+  double   get_rng_gate() const
+  {
+    return _rng_gate;
+  };
+  /**
+  * @brief Range pulse length
+  */
+  double   get_rng_length() const
+  {
+    return _rng_length;
+  };
+  /**
+  * @brief Baseband conversion flag
+  */
+  std::string   get_baseband_f() const
+  {
+    return _baseband_f;
+  };
+  /**
+  * @brief Range compressed flag
+  */
+  std::string   get_rngcmp_f() const
+  {
+    return _rngcmp_f;
+  };
+  /**
+  * @brief Like polarized gain
+  */
+  double   get_gn_polar() const
+  {
+    return _gn_polar;
+  };
+  /**
+  * @brief Cross polarized gain
+  */
+  double   get_gn_cross() const
+  {
+    return _gn_cross;
+  };
+  /**
+  * @brief Number of bits per channel
+  */
+  int   get_chn_bits() const
+  {
+    return _chn_bits;
+  };
+  /**
+  * @brief Quantization descriptor
+  */
+  std::string   get_quant_desc() const
+  {
+    return _quant_desc;
+  };
+  /**
+  * @brief I channel DC bias
+  */
+  double   get_i_bias() const
+  {
+    return _i_bias;
+  };
+  /**
+  * @brief Q channel DC bias
+  */
+  double   get_q_bias() const
+  {
+    return _q_bias;
+  };
+  /**
+  * @brief I/Q channel ratio
+  */
+  double   get_iq_ratio() const
+  {
+    return _iq_ratio;
+  };
+
+
+  /**
+  * @brief Mechanical boresight
+  */
+  double   get_mech_sight() const
+  {
+    return _mech_sight;
+  };
+
+  /**
+  * @brief Nominal PRF, Hz
+  */
+  double   get_fa() const
+  {
+    return _fa;
+  };
+
+  /**
+  * @brief Satellite binary time
+  */
+  std::string    get_sat_bintim() const
+  {
+    return _sat_bintim;
+  };
+  /**
+  * @brief Satellite clock time
+  */
+  std::string    get_sat_clktim() const
+  {
+    return _sat_clktim;
+  };
+  /**
+  * @brief Satellite clock increment
+  */
+  std::string    get_sat_clkinc() const
+  {
+    return _sat_clkinc;
+  };
+
+  /**
+  * @brief Processing facility identifier
+  */
+  std::string   get_fac_id() const
+  {
+    return _fac_id;
+  };
+  /**
+  * @brief Processing system identifier
+  */
+  std::string   get_sys_id() const
+  {
+    return _sys_id;
+  };
+  /**
+  * @brief Processing version identifier
+  */
+  std::string   get_ver_id() const
+  {
+    return _ver_id;
+  };
+
+  /**
+  * @brief Product type specifier
+  */
+  std::string   get_prod_type() const
+  {
+    return _prod_type;
+  };
+  /**
+  * @brief Processing algorithm identifier
+  */
+  std::string   get_algor_id() const
+  {
+    return _algor_id;
+  };
+  /**
+  * @brief Number of azimuth looks
+  */
+  double   get_n_azilok() const
+  {
+    return _n_azilok;
+  };
+  /**
+  * @brief Number of range looks
+  */
+  double   get_n_rnglok() const
+  {
+    return _n_rnglok;
+  };
+  /**
+  * @brief Bandwidth per look in azimuth,Hz
+  */
+  double   get_bnd_azilok() const
+  {
+    return _bnd_azilok;
+  };
+  /**
+  * @brief Bandwidth per look in range,Hz
+  */
+  double   get_bnd_rnglok() const
+  {
+    return _bnd_rnglok;
+  };
+  /**
+  * @brief Total azimuth look bandwidth
+  */
+  double   get_bnd_azi() const
+  {
+    return _bnd_azi;
+  };
+  /**
+  * @brief Total range look bandwidth
+  */
+  double   get_bnd_rng() const
+  {
+    return _bnd_rng;
+  };
+  /**
+  * @brief Azimuth weighting designator
+  */
+  std::string   get_azi_weight() const
+  {
+    return _azi_weight;
+  };
+  /**
+  * @brief Range weighting designator
+  */
+  std::string   get_rng_weight() const
+  {
+    return _rng_weight;
+  };
+  /**
+  * @brief Data input source
+  */
+  std::string   get_data_inpsrc() const
+  {
+    return _data_inpsrc;
+  };
+  /**
+  * @brief Range resolution, meter
+  */
+  double   get_rng_res() const
+  {
+    return _rng_res;
+  };
+  /**
+  * @brief Azimuth resolution, meter
+  */
+  double   get_azi_res() const
+  {
+    return _azi_res;
+  };
+  /**
+  * @brief Along track Doppler frequency terms
+  */
+  const double*   get_alt_dopcen() const
+  {
+    return _alt_dopcen;
+  };
+
+  /**
+  * @brief Cross track Doppler frequency terms
+  */
+  const double*   get_crt_dopcen() const
+  {
+    return _crt_dopcen;
+  };
+  /**
+  * @brief Pixel time direction indicator
+  */
+  std::string   get_time_dir_pix() const
+  {
+    return _time_dir_pix;
+  };
+  /**
+  * @brief Line time direction indicator
+  */
+  std::string   get_time_dir_lin() const
+  {
+    return _time_dir_lin;
+  };
+  /**
+  * @brief Along track Doppler rate term
+  */
+  const  double*   get_alt_rate() const
+  {
+    return _alt_rate;
+  };
+
+  /**
+  * @brief Cross track Doppler rate term
+  */
+  const  double*   get_crt_rate() const
+  {
+    return _crt_rate;
+  };
+
+  /**
+  * @brief Line content indicator
+  */
+  std::string   get_line_cont() const
+  {
+    return _line_cont;
+  };
+  /**
+  * @brief Clutter lock applied flag
+  */
+  std::string   get_clutter_lock() const
+  {
+    return _clutter_lock;
+  };
+  /**
+  * @brief Auto-focus applied flag
+  */
+  std::string   get_auto_focus() const
+  {
+    return _auto_focus;
+  };
+  /**
+  * @brief Line spacing, meters
+  */
+  double   get_line_spacing() const
+  {
+    return _line_spacing;
+  };
+  /**
+  * @brief Pixel spacing, meters
+  */
+  double   get_pix_spacing() const
+  {
+    return _pix_spacing;
+  };
+  /**
+  * @brief Range compression designator
+  */
+  std::string   get_rngcmp_desg() const
+  {
+    return _rngcmp_desg;
+  };
+
+  /**
+  * @brief Along track Doppler frequency terms (in range unit: km)
+  */
+  const double*   get_dopcen_range() const
+  {
+    return _dopcen_range;
+  };
+
+  /**
+  * @Data from 1767 to 4096 to be added
+  */
+
+
+protected:
+  /**
+   * @brief Sequence number
+   */
+  int   _seq_num;
+  /**
+  * @brief SAR channel indicator
+  */
+  int   _sar_chn;
+  /**
+   * @brief Scene identifier
+   */
+  std::string   _scene_id;
+  /**
+   * @brief Scene designator
+   */
+  std::string   _scene_des;
+  /**
+   * @brief Input scene centre time
+   */
+  std::string   _inp_sctim;
+  /**
+   * @brief Ascending/descending
+   */
+  std::string   _asc_des;
+  /**
+  * @brief Processed scene centre latitude
+  */
+  double   _pro_lat;
+  /**
+  * @brief Processed scene centre longitude
+  */
+  double   _pro_long;
+  /**
+  * @brief Processed scene centre headng
+  */
+  double   _pro_head;
+  /**
+   * @brief Ellipsoid designator
+   */
+  std::string   _ellip_des;
+  /**
+  * @brief Ellipsoid semi-major axis, km
+  */
+  double   _ellip_maj;
+  /**
+  * @brief Ellipsoid semi_minor axis, km
+  */
+  double  _ellip_min;
+  /**
+   * @brief Earth's mass
+   */
+  double   _earth_mass;
+  /**
+  * @brief Gravitational constant
+  */
+  double   _grav_const;
+  /**
+  * @brief Ellipsoid J2-4 parameters
+  */
+  double   _ellip_j[3];
+
+  /**
+  * @brief Average terrain height, km
+  */
+  double   _terrain_h;
+  /**
+  * @brief Scene centre line number
+  */
+  int   _sc_lin;
+  /**
+  * @brief Scene centre pixel number
+  */
+  int   _sc_pix;
+  /**
+  * @brief Scene length, km
+  */
+  double   _scene_len;
+  /**
+  * @brief Scene width, km
+  */
+  double   _scene_wid;
+
+  /**
+  * @brief Number of SAR channels
+  */
+  double   _nchn;
+
+  /**
+  * @brief Mission identifier
+  */
+  std::string   _mission_id;
+  /**
+  * @brief Sensor identifier
+  */
+  std::string   _sensor_id;
+  /**
+  * @brief Orbit number
+  */
+  std::string   _orbit_num;
+  /**
+  * @brief Platform geodetic latitude
+  */
+  double   _plat_lat;
+  /**
+  * @brief Platform geodetic longitude
+  */
+  double   _plat_long;
+  /**
+  * @brief Platform heading
+  */
+  double   _plat_head;
+  /**
+  * @brief Sensor clock angle
+  */
+  double   _clock_ang;
+  /**
+  * @brief Incidence angle
+  */
+  double   _incident_ang;
+
+  /**
+  * @brief Radar wave length
+  */
+  double   _wave_length;
+  /**
+  * @brief Motion compensation indicator
+  */
+  std::string   _motion_comp;
+  /**
+  * @brief Range pulse code specifier
+  */
+  std::string   _pulse_code;
+  /**
+  * @brief Range chirp coefficients
+  */
+  double   _ampl_coef[5];
+  /**
+  * @brief Range phase coefficients
+  */
+  double   _phas_coef[5];
+  /**
+  * @brief Chirp extraction index
+  */
+  int   _chirp_ext_ind;
+
+  /**
+  * @brief Range sampling rate
+  */
+  double   _fr;
+  /**
+  * @brief Range gate start time
+  */
+  double   _rng_gate;
+  /**
+  * @brief Range pulse length
+  */
+  double   _rng_length;
+  /**
+  * @brief Baseband conversion flag
+  */
+  std::string   _baseband_f;
+  /**
+  * @brief Range compressed flag
+  */
+  std::string   _rngcmp_f;
+  /**
+  * @brief Like polarized gain
+  */
+  double   _gn_polar;
+  /**
+  * @brief Cross polarized gain
+  */
+  double   _gn_cross;
+  /**
+  * @brief Number of bits per channel
+  */
+  int   _chn_bits;
+  /**
+  * @brief Quantization descriptor
+  */
+  std::string   _quant_desc;
+  /**
+  * @brief I channel DC bias
+  */
+  double   _i_bias;
+  /**
+  * @brief Q channel DC bias
+  */
+  double   _q_bias;
+  /**
+  * @brief I/Q channel ratio
+  */
+  double   _iq_ratio;
+  /**
+  * @brief Mechanical boresight
+  */
+  double   _mech_sight;
+  /**
+  * @brief Nominal PRF, Hz
+  */
+  double   _fa;
+  /**
+  * @brief Satellite binary time
+  */
+  std::string    _sat_bintim;
+  /**
+  * @brief Satellite clock time
+  */
+  std::string    _sat_clktim;
+  /**
+  * @brief Satellite clock increment
+  */
+  std::string    _sat_clkinc;
+
+  /**
+  * @brief Processing facility identifier
+  */
+  std::string   _fac_id;
+  /**
+  * @brief Processing system identifier
+  */
+  std::string   _sys_id;
+  /**
+  * @brief Processing version identifier
+  */
+  std::string   _ver_id;
+  /**
+  * @brief Product type specifier
+  */
+  std::string   _prod_type;
+  /**
+  * @brief Processing algorithm identifier
+  */
+  std::string   _algor_id;
+  /**
+  * @brief Number of azimuth looks
+  */
+  double   _n_azilok;
+  /**
+  * @brief Number of range looks
+  */
+  double   _n_rnglok;
+  /**
+  * @brief Bandwidth per look in azimuth,Hz
+  */
+  double   _bnd_azilok;
+  /**
+  * @brief Bandwidth per look in range,Hz
+  */
+  double   _bnd_rnglok;
+  /**
+  * @brief Total azimuth look bandwidth
+  */
+  double   _bnd_azi;
+  /**
+  * @brief Total range look bandwidth
+  */
+  double   _bnd_rng;
+  /**
+  * @brief Azimuth weighting designator
+  */
+  std::string   _azi_weight;
+  /**
+  * @brief Range weighting designator
+  */
+  std::string   _rng_weight;
+  /**
+  * @brief Data input source
+  */
+  std::string   _data_inpsrc;
+  /**
+  * @brief Range resolution, meter
+  */
+  double   _rng_res;
+  /**
+  * @brief Azimuth resolution, meter
+  */
+  double   _azi_res;
+  /**
+  * @brief Along track Doppler frequency terms
+  */
+  double   _alt_dopcen[3];
+  /**
+  * @brief Cross track Doppler frequency terms
+  */
+  double   _crt_dopcen[3];
+  /**
+  * @brief Pixel time direction indicator
+  */
+  std::string   _time_dir_pix;
+  /**
+  * @brief Line time direction indicator
+  */
+  std::string   _time_dir_lin;
+  /**
+  * @brief Along track Doppler rate term
+  */
+  double   _alt_rate[3];
+
+  /**
+  * @brief Cross track Doppler rate term
+  */
+  double   _crt_rate[3];
+
+  /**
+  * @brief Line content indicator
+  */
+  std::string   _line_cont;
+  /**
+  * @brief Clutter lock applied flag
+  */
+  std::string   _clutter_lock;
+  /**
+  * @brief Auto-focus applied flag
+  */
+  std::string   _auto_focus;
+  /**
+  * @brief Line spacing, meters
+  */
+  double   _line_spacing;
+  /**
+  * @brief Pixel spacing, meters
+  */
+  double   _pix_spacing;
+  /**
+  * @brief Range compression designator
+  */
+  std::string   _rngcmp_desg;
+
+  /**
+  * @brief Cross track Doppler frequency terms (in range unit: km)
+  */
+  double   _dopcen_range[2];
+
+  /**
+  * @Data from 1767 to 4096 to be added
+  */
+
+private:
+
+};
+}
+#endif
+
diff --git a/ossim_plugins/ossim/AlosPalsar/AlosPalsarFacilityData.cpp b/ossim_plugins/ossim/AlosPalsar/AlosPalsarFacilityData.cpp
new file mode 100644
index 0000000..77bd78d
--- /dev/null
+++ b/ossim_plugins/ossim/AlosPalsar/AlosPalsarFacilityData.cpp
@@ -0,0 +1,1168 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+// "Copyright Centre for Remote Imaging, Sensing and Processing"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include <AlosPalsar/AlosPalsarFacilityData.h>
+
+namespace ossimplugins
+{
+
+   AlosPalsarFacilityData::AlosPalsarFacilityData() : AlosPalsarRecord("facility_data_rec")
+   {
+   }
+
+   AlosPalsarFacilityData::~AlosPalsarFacilityData()
+   {
+   }
+
+   std::ostream& operator<<(std::ostream& os, const AlosPalsarFacilityData& data)
+   {
+      os << "last_release_qc_date:" << data._last_release_qc_date.c_str() << std::endl;
+
+      os << "last_release_cal_date:" << data._last_release_cal_date.c_str() << std::endl;
+
+      os << "qa_summary_flag:" << data._qa_summary_flag << std::endl;
+
+      os << "prf_code_change_flag:" << data._prf_code_change_flag << std::endl;
+
+      os << "sampling_win_change_flag:" << data._sampling_win_change_flag << std::endl;
+
+      os << "cal_gain_change_flag:" << data._cal_gain_change_flag << std::endl;
+
+      os << "quirp_qu_flag:" << data._quirp_qu_flag << std::endl;
+
+      os << "inp_data_stat_flag:" << data._inp_data_stat_flag << std::endl;
+
+      os << "dopp_cent_conf_meas_flag:" << data._dopp_cent_conf_meas_flag << std::endl;
+
+      os << "dopp_cent_val_flag:" << data._dopp_cent_val_flag << std::endl;
+
+      os << "dopp_ambig_conf_meas_flag:" << data._dopp_ambig_conf_meas_flag << std::endl;
+
+      os << "outp_data_mean_flag:" << data._outp_data_mean_flag << std::endl;
+
+      os << "OGOB_flag:" << data._OGOB_flag << std::endl;
+
+      os << "PRF_changes:" << data._PRF_changes << std::endl;
+
+      os << "sampling_win_changes:" << data._sampling_win_changes << std::endl;
+
+      os << "cal_gain_changes:" << data._cal_gain_changes << std::endl;
+
+      os << "missing_lines:" << data._missing_lines << std::endl;
+
+      os << "rec_gain_changes:" << data._rec_gain_changes << std::endl;
+
+      os << "pulse_width_of_ACF_3db:" << data._pulse_width_of_ACF_3db << std::endl;
+
+      os << "first_side_lobe_lev_of_ACF:" << data._first_side_lobe_lev_of_ACF << std::endl;
+
+      os << "ISLR_of_ACF:" << data._ISLR_of_ACF << std::endl;
+
+      os << "dopp_cent_conf_meas:" << data._dopp_cent_conf_meas << std::endl;
+
+      os << "dopp_ambig_conf_meas:" << data._dopp_ambig_conf_meas << std::endl;
+
+      os << "inp_data_I_mean:" << data._inp_data_I_mean << std::endl;
+
+      os << "inp_data_Q_mean:" << data._inp_data_Q_mean << std::endl;
+
+      os << "inp_data_I_stddev:" << data._inp_data_I_stddev << std::endl;
+
+      os << "inp_data_Q_stddev:" << data._inp_data_Q_stddev << std::endl;
+
+      os << "cal_sys_gain:" << data._cal_sys_gain << std::endl;
+
+      os << "first_rec_gain_read:" << data._first_rec_gain_read << std::endl;
+
+      os << "dopp_ambig_num:" << data._dopp_ambig_num << std::endl;
+
+      os << "I_channel_bias_correction:" << data._I_channel_bias_correction << std::endl;
+
+      os << "Q_channel_bias_correction:" << data._Q_channel_bias_correction << std::endl;
+
+      os << "I_channel_gain_correction:" << data._I_channel_gain_correction << std::endl;
+
+      os << "Q_channel_gain_correction:" << data._Q_channel_gain_correction << std::endl;
+
+      os << "Q_channel_I_Q_correction:" << data._Q_channel_I_Q_correction << std::endl;
+
+      os << "noise_power:" << data._noise_power << std::endl;
+
+      os << "int_cal_utc:" << data._int_cal_utc << std::endl;
+
+      os << "num_valid_cal_pulses:" << data._num_valid_cal_pulses << std::endl;
+
+      os << "num_valid_noise_pulses:" << data._num_valid_noise_pulses << std::endl;
+
+      os << "num_valid_replicas:" << data._num_valid_replicas << std::endl;
+
+      os << "first_replica_sample:" << data._first_replica_sample << std::endl;
+
+      os << "mean_cal_pulse_power:" << data._mean_cal_pulse_power << std::endl;
+
+      os << "mean_noise_power:" << data._mean_noise_power << std::endl;
+
+      os << "range_comp_norm_fact:" << data._range_comp_norm_fact << std::endl;
+
+      os << "replica_power:" << data._replica_power << std::endl;
+
+      os << "first_range_pixel_mid_az_inc:" << data._first_range_pixel_mid_az_inc << std::endl;
+
+      os << "center_range_pix_mid_az_inc:" << data._center_range_pix_mid_az_inc << std::endl;
+
+      os << "last_range_pix_mid_az_inc:" << data._last_range_pix_mid_az_inc << std::endl;
+
+      os << "norm_ref_range_ro:" << data._norm_ref_range_ro << std::endl;
+
+      os << "antenna_elev_flag:" << data._antenna_elev_flag << std::endl;
+
+      os << "abs_cal_const_K:" << data._abs_cal_const_K << std::endl;
+
+      os << "upp_bound_K:" << data._upp_bound_K << std::endl;
+
+      os << "low_bound_K:" << data._low_bound_K << std::endl;
+
+      os << "proc_noise_scale_fact:" << data._proc_noise_scale_fact << std::endl;
+
+      os << "K_gen_date:" << data._K_gen_date.c_str() << std::endl;
+
+      os << "K_vers_num:" << data._K_vers_num.c_str() << std::endl;
+
+      os << "num_duplic_input_lines:" << data._num_duplic_input_lines << std::endl;
+
+      os << "estim_bit_error_rate:" << data._estim_bit_error_rate << std::endl;
+
+      os << "out_image_mean:" << data._out_image_mean << std::endl;
+
+      os << "out_image_std_dev:" << data._out_image_std_dev << std::endl;
+
+      os << "out_image_max_value:" << data._out_image_max_value << std::endl;
+
+      os << "time_raw_data_first_input:" << data._time_raw_data_first_input.c_str() << std::endl;
+
+      os << "time_asc_node_state_vectors:" << data._time_asc_node_state_vectors.c_str() << std::endl;
+
+      os << "asc_node_pos_X_comp:" << data._asc_node_pos_X_comp.c_str() << std::endl;
+
+      os << "asc_node_pos_Y_comp:" << data._asc_node_pos_Y_comp.c_str() << std::endl;
+
+      os << "asc_node_pos_Z_comp:" << data._asc_node_pos_Z_comp.c_str() << std::endl;
+
+      os << "asc_node_vel_X_comp:" << data._asc_node_vel_X_comp.c_str() << std::endl;
+
+      os << "asc_node_vel_Y_comp:" << data._asc_node_vel_Y_comp.c_str() << std::endl;
+
+      os << "asc_node_vel_Z_comp:" << data._asc_node_vel_Z_comp.c_str() << std::endl;
+
+      os << "out_pixel_bit_length:" << data._out_pixel_bit_length << std::endl;
+
+      os << "proc_gain_param_1:" << data._proc_gain_param_1 << std::endl;
+
+      os << "proc_gain_param_2:" << data._proc_gain_param_2 << std::endl;
+
+      os << "proc_gain_param_3:" << data._proc_gain_param_3 << std::endl;
+
+      os << "peak_loc_cross_correl_fun:" << data._peak_loc_cross_correl_fun << std::endl;
+
+      os << "3_dB_width_CCF:" << data._3_dB_width_CCF << std::endl;
+
+      os << "first_side_lobe_level:" << data._first_side_lobe_level << std::endl;
+
+      os << "ISLR_CCF_between_last:" << data._ISLR_CCF_between_last << std::endl;
+
+      os << "peak_loc_CCF_betw_last:" << data._peak_loc_CCF_betw_last << std::endl;
+
+      os << "Roll_Tilt_Mode_flag:" << data._Roll_Tilt_Mode_flag << std::endl;
+
+      os << "raw_data_correction_flag:" << data._raw_data_correction_flag << std::endl;
+
+      os << "look_detecion_flag:" << data._look_detecion_flag << std::endl;
+
+      os << "doppler_ambiguity_estimat_flag:" << data._doppler_ambiguity_estimat_flag << std::endl;
+
+      os << "azimuth_baseband_convers_flag:" << data._azimuth_baseband_convers_flag << std::endl;
+
+      os << "samples_per_line_used:" << data._samples_per_line_used << std::endl;
+
+      os << "range_lines_skip_factor:" << data._range_lines_skip_factor << std::endl;
+
+      os << "time_of_inp_state_vectors:" << data._time_of_inp_state_vectors.c_str() << std::endl;
+
+      os << "inp_state_vect_pos_X_comp:" << data._inp_state_vect_pos_X_comp.c_str() << std::endl;
+
+      os << "inp_state_vect_pos_Y_comp:" << data._inp_state_vect_pos_Y_comp.c_str() << std::endl;
+
+      os << "inp_state_vect_pos_Z_comp:" << data._inp_state_vect_pos_Z_comp.c_str() << std::endl;
+
+      os << "inp_state_vect_vel_Vx_comp:" << data._inp_state_vect_vel_Vx_comp.c_str() << std::endl;
+
+      os << "inp_state_vect_vel_Vy_comp:" << data._inp_state_vect_vel_Vy_comp.c_str() << std::endl;
+
+      os << "inp_state_vect_vel_Vz_comp:" << data._inp_state_vect_vel_Vz_comp.c_str() << std::endl;
+
+      os << "inp_state_vector_type_flag:" << data._inp_state_vector_type_flag << std::endl;
+
+      os << "win_coeff_for_range_match:" << data._win_coeff_for_range_match << std::endl;
+
+      os << "win_coeff_for_azi_match:" << data._win_coeff_for_azi_match << std::endl;
+
+      os << "update_period_range_match:" << data._update_period_range_match << std::endl;
+
+      os << "look_scalar_gain_1:" << data._look_scalar_gain_1 << std::endl;
+
+      os << "look_scalar_gain_2:" << data._look_scalar_gain_2 << std::endl;
+
+      os << "look_scalar_gain_3:" << data._look_scalar_gain_3 << std::endl;
+
+      os << "look_scalar_gain_4:" << data._look_scalar_gain_4 << std::endl;
+
+      os << "look_scalar_gain_5:" << data._look_scalar_gain_5 << std::endl;
+
+      os << "look_scalar_gain_6:" << data._look_scalar_gain_6 << std::endl;
+
+      os << "look_scalar_gain_7:" << data._look_scalar_gain_7 << std::endl;
+
+      os << "look_scalar_gain_8:" << data._look_scalar_gain_8 << std::endl;
+
+      os << "samp_window_start_time_bias:" << data._samp_window_start_time_bias << std::endl;
+
+      os << "doppler_centroid_cubic_coeff:" << data._doppler_centroid_cubic_coeff << std::endl;
+
+      os << "PRF_code_first_range_line:" << data._PRF_code_first_range_line << std::endl;
+
+      os << "PRF_code_last_range_line:" << data._PRF_code_last_range_line << std::endl;
+
+      os << "samp_win_start_first:" << data._samp_win_start_first << std::endl;
+
+      os << "samp_win_start_last:" << data._samp_win_start_last << std::endl;
+
+      os << "cal_syst_gain_last_proc:" << data._cal_syst_gain_last_proc << std::endl;
+
+      os << "receiver_gain_last_proc:" << data._receiver_gain_last_proc << std::endl;
+
+      os << "first_processed_range_sample:" << data._first_processed_range_sample << std::endl;
+
+      os << "azimuth_FFT_IFFT_ratio:" << data._azimuth_FFT_IFFT_ratio << std::endl;
+
+      os << "num_azimuth_blocks_proc:" << data._num_azimuth_blocks_proc << std::endl;
+
+      os << "num_input_raw_data_lines:" << data._num_input_raw_data_lines << std::endl;
+
+      os << "initial_doppler_ambiguity_num:" << data._initial_doppler_ambiguity_num << std::endl;
+
+      os << "thresh_no_1_flag:" << data._thresh_no_1_flag << std::endl;
+
+      os << "thresh_no_2_flag:" << data._thresh_no_2_flag << std::endl;
+
+      os << "thresh_no_3_flag:" << data._thresh_no_3_flag << std::endl;
+
+      os << "thresh_no_4_flag:" << data._thresh_no_4_flag << std::endl;
+
+      os << "thresh_no_5_flag:" << data._thresh_no_5_flag << std::endl;
+
+      os << "thresh_no_6_flag:" << data._thresh_no_6_flag << std::endl;
+
+      os << "thresh_no_7_flag:" << data._thresh_no_7_flag << std::endl;
+
+      os << "thresh_no_8_flag:" << data._thresh_no_8_flag << std::endl;
+
+      os << "thresh_no_9_flag:" << data._thresh_no_9_flag << std::endl;
+
+      os << "thresh_no_10_flag:" << data._thresh_no_10_flag << std::endl;
+
+      os << "thresh_no_11_flag:" << data._thresh_no_11_flag << std::endl;
+
+      os << "sat_binary_time_of_first:" << data._sat_binary_time_of_first << std::endl;
+
+      os << "num_valid_pixels_per_range:" << data._num_valid_pixels_per_range << std::endl;
+
+      os << "num_range_samp_discarded:" << data._num_range_samp_discarded << std::endl;
+
+      os << "I_gain_imb_lower_bound:" << data._I_gain_imb_lower_bound << std::endl;
+
+      os << "I_gain_imb_upper_bound:" << data._I_gain_imb_upper_bound << std::endl;
+
+      os << "I_Q_quad_depar_lower_bound:" << data._I_Q_quad_depar_lower_bound << std::endl;
+
+      os << "I_Q_quad_depar_upper_bound:" << data._I_Q_quad_depar_upper_bound << std::endl;
+
+      os << "3_dB_look_bandwidth:" << data._3_dB_look_bandwidth << std::endl;
+
+      os << "3_dB_look_proc_dopp_bandw:" << data._3_dB_look_proc_dopp_bandw << std::endl;
+
+      os << "range_spread_loss_comp_flag:" << data._range_spread_loss_comp_flag << std::endl;
+
+      os << "datation_flag:" << data._datation_flag << std::endl;
+
+      os << "max_error_range_line_timing:" << data._max_error_range_line_timing << std::endl;
+
+      os << "form_num_range_line_used:" << data._form_num_range_line_used << std::endl;
+
+      os << "autom_look_scal_gain_flag:" << data._autom_look_scal_gain_flag << std::endl;
+
+      os << "max_value_look_scalar_gain:" << data._max_value_look_scalar_gain << std::endl;
+
+      os << "replica_norm_method_flag:" << data._replica_norm_method_flag << std::endl;
+
+      os << "coef_ground_range_1:" << data._coef_ground_range_1 << std::endl;
+
+      os << "coef_ground_range_2:" << data._coef_ground_range_2 << std::endl;
+
+      os << "coef_ground_range_3:" << data._coef_ground_range_3 << std::endl;
+
+      os << "coef_ground_range_4:" << data._coef_ground_range_4 << std::endl;
+
+      os << "coef_ant_elev_1:" << data._coef_ant_elev_1 << std::endl;
+
+      os << "coef_ant_elev_2:" << data._coef_ant_elev_2 << std::endl;
+
+      os << "coef_ant_elev_3:" << data._coef_ant_elev_3 << std::endl;
+
+      os << "coef_ant_elev_4:" << data._coef_ant_elev_4 << std::endl;
+
+      os << "coef_ant_elev_5:" << data._coef_ant_elev_5 << std::endl;
+
+      os << "range_time_origin_ant:" << data._range_time_origin_ant << std::endl;
+
+      return os;
+
+   }
+
+   std::istream& operator>>(std::istream& is, AlosPalsarFacilityData& data)
+   {
+      char buf64[65];
+      buf64[64] = '\0';
+      char buf32[33];
+      buf32[32] = '\0';
+      char buf24[25];
+      buf24[24] = '\0';
+      char buf22[23];
+      buf22[22] = '\0';
+      char buf20[21];
+      buf20[20] = '\0';
+      char buf16[17];
+      buf16[16] = '\0';
+      char buf12[13];
+      buf12[12] = '\0';
+      char buf7[8];
+      buf7[7] = '\0';
+      char buf8[9];
+      buf8[8] = '\0';
+      char buf6[7];
+      buf6[6] = '\0';
+      char buf4[5];
+      buf4[4] = '\0';
+      char buf2[3];
+      buf2[2] = '\0';
+      char buf1[2];
+      buf1[1] = '\0';
+
+      is.read(buf64, 64);
+      data._name_of_facil_rec = buf64;
+
+      is.read(buf6, 6);
+      data._last_release_qc_date = buf6;
+
+      is.read(buf2, 2);
+
+      is.read(buf6, 6);
+      data._last_release_cal_date = buf6;
+
+      is.read(buf4, 4);
+      data._qa_summary_flag = atoi(buf4);
+
+      is.read(buf4, 4);
+      data._prf_code_change_flag = atoi(buf4);
+
+      is.read(buf4, 4);
+      data._sampling_win_change_flag = atoi(buf4);
+
+      is.read(buf4, 4);
+      data._cal_gain_change_flag = atoi(buf4);
+
+      is.read(buf4, 4);
+      data._quirp_qu_flag = atoi(buf4);
+
+      is.read(buf4, 4);
+      data._inp_data_stat_flag = atoi(buf4);
+
+      is.read(buf4, 4);
+      data._dopp_cent_conf_meas_flag = atoi(buf4);
+
+      is.read(buf4, 4);
+      data._dopp_cent_val_flag = atoi(buf4);
+
+      is.read(buf4, 4);
+      data._dopp_ambig_conf_meas_flag = atoi(buf4);
+
+      is.read(buf4, 4);
+      data._outp_data_mean_flag = atoi(buf4);
+
+      is.read(buf4, 4);
+      data._OGOB_flag = atoi(buf4);
+
+      is.read(buf4, 4);
+      data._PRF_changes = atoi(buf4);
+
+      is.read(buf4, 4);
+      data._sampling_win_changes = atoi(buf4);
+
+      is.read(buf4, 4);
+      data._cal_gain_changes = atoi(buf4);
+
+      is.read(buf4, 4);
+      data._missing_lines = atoi(buf4);
+
+      is.read(buf4, 4);
+      data._rec_gain_changes = atoi(buf4);
+
+      is.read(buf16, 16);
+      data._pulse_width_of_ACF_3db = atof(buf16);
+
+      is.read(buf16, 16);
+      data._first_side_lobe_lev_of_ACF = atof(buf16);
+
+      is.read(buf16, 16);
+      data._ISLR_of_ACF = atof(buf16);
+
+      is.read(buf16, 16);
+      data._dopp_cent_conf_meas = atof(buf16);
+
+      is.read(buf16, 16);
+      data._dopp_ambig_conf_meas = atof(buf16);
+
+      is.read(buf16, 16);
+      data._inp_data_I_mean = atof(buf16);
+
+      is.read(buf16, 16);
+      data._inp_data_Q_mean = atof(buf16);
+
+      is.read(buf16, 16);
+      data._inp_data_I_stddev = atof(buf16);
+
+      is.read(buf16, 16);
+      data._inp_data_Q_stddev = atof(buf16);
+
+      is.read(buf16, 16);
+      data._cal_sys_gain = atof(buf16);
+
+      is.read(buf16, 16);
+      data._first_rec_gain_read = atof(buf16);
+
+      is.read(buf16, 16);
+      data._dopp_ambig_num = atof(buf16);
+
+      is.read(buf16, 16);
+
+      is.read(buf16, 16);
+      data._I_channel_bias_correction = atof(buf16);
+
+      is.read(buf16, 16);
+      data._Q_channel_bias_correction = atof(buf16);
+
+      is.read(buf16, 16);
+      data._I_channel_gain_correction = atof(buf16);
+
+      is.read(buf16, 16);
+      data._Q_channel_gain_correction = atof(buf16);
+
+      is.read(buf16, 16);
+      data._Q_channel_I_Q_correction = atof(buf16);
+
+      is.read(buf16, 16);
+
+      is.read(buf16, 16);
+      data._noise_power = atof(buf16);
+
+      is.read(buf16, 16);
+      data._int_cal_utc = atoi(buf16);
+
+      is.read(buf4, 4);
+      data._num_valid_cal_pulses = atoi(buf4);
+
+      is.read(buf4, 4);
+      data._num_valid_noise_pulses = atoi(buf4);
+
+      is.read(buf4, 4);
+      data._num_valid_replicas = atoi(buf4);
+
+      is.read(buf16, 16);
+      data._first_replica_sample = atof(buf16);
+
+      is.read(buf16, 16);
+      data._mean_cal_pulse_power = atof(buf16);
+
+      is.read(buf16, 16);
+      data._mean_noise_power = atof(buf16);
+
+      is.read(buf16, 16);
+      data._range_comp_norm_fact = atof(buf16);
+
+      is.read(buf16, 16);
+      data._replica_power = atof(buf16);
+
+      is.read(buf16, 16);
+      data._first_range_pixel_mid_az_inc = atof(buf16);
+
+      is.read(buf16, 16);
+      data._center_range_pix_mid_az_inc = atof(buf16);
+
+      is.read(buf16, 16);
+      data._last_range_pix_mid_az_inc = atof(buf16);
+
+      is.read(buf16, 16);
+      data._norm_ref_range_ro = atof(buf16);
+
+      is.read(buf12, 12);
+
+      is.read(buf4, 4);
+      data._antenna_elev_flag = atoi(buf4);
+
+      is.read(buf16, 16);
+      data._abs_cal_const_K = atof(buf16);
+
+      is.read(buf16, 16);
+      data._upp_bound_K = atof(buf16);
+
+      is.read(buf16, 16);
+      data._low_bound_K = atof(buf16);
+
+      is.read(buf16, 16);
+      data._proc_noise_scale_fact = atof(buf16);
+
+      is.read(buf6, 6);
+      data._K_gen_date = buf6;
+
+      is.read(buf4, 4);
+      data._K_vers_num = buf4;
+
+      is.read(buf4, 4);
+      data._num_duplic_input_lines = atoi(buf4);
+
+      is.read(buf16, 16);
+      data._estim_bit_error_rate = atof(buf16);
+
+      is.read(buf12, 12);
+
+      is.read(buf16, 16);
+      data._out_image_mean = atof(buf16);
+
+      is.read(buf16, 16);
+      data._out_image_std_dev = atof(buf16);
+
+      is.read(buf16, 16);
+      data._out_image_max_value = atof(buf16);
+
+      is.read(buf24, 24);
+      data._time_raw_data_first_input = buf24;
+
+      is.read(buf24, 24);
+      data._time_asc_node_state_vectors = buf24;
+
+      is.read(buf22, 22);
+      data._asc_node_pos_X_comp = buf22;
+
+      is.read(buf22, 22);
+      data._asc_node_pos_Y_comp = buf22;
+
+      is.read(buf22, 22);
+      data._asc_node_pos_Z_comp = buf22;
+
+      is.read(buf22, 22);
+      data._asc_node_vel_X_comp = buf22;
+
+      is.read(buf22, 22);
+      data._asc_node_vel_Y_comp = buf22;
+
+      is.read(buf22, 22);
+      data._asc_node_vel_Z_comp = buf22;
+
+      is.read(buf4, 4);
+      data._out_pixel_bit_length = atoi(buf4);
+
+      is.read(buf16, 16);
+      data._proc_gain_param_1 = atof(buf16);
+
+      is.read(buf16, 16);
+      data._proc_gain_param_2 = atof(buf16);
+
+      is.read(buf16, 16);
+      data._proc_gain_param_3 = atof(buf16);
+
+      is.read(buf4, 4);
+      data._peak_loc_cross_correl_fun = atoi(buf4);
+
+      is.read(buf16, 16);
+      data._3_dB_width_CCF = atof(buf16);
+
+      is.read(buf16, 16);
+      data._first_side_lobe_level = atof(buf16);
+
+      is.read(buf16, 16);
+      data._ISLR_CCF_between_last = atof(buf16);
+
+      is.read(buf4, 4);
+      data._peak_loc_CCF_betw_last = atoi(buf4);
+
+      is.read(buf4, 4);
+      data._Roll_Tilt_Mode_flag = atoi(buf4);
+
+      is.read(buf4, 4);
+      data._raw_data_correction_flag = atoi(buf4);
+
+      is.read(buf4, 4);
+      data._look_detecion_flag = atoi(buf4);
+
+      is.read(buf4, 4);
+      data._doppler_ambiguity_estimat_flag = atoi(buf4);
+
+      is.read(buf4, 4);
+      data._azimuth_baseband_convers_flag = atoi(buf4);
+
+      is.read(buf4, 4);
+      data._samples_per_line_used = atoi(buf4);
+
+      is.read(buf4, 4);
+      data._range_lines_skip_factor = atoi(buf4);
+
+      is.read(buf24, 24);
+      data._time_of_inp_state_vectors = buf24;
+
+      is.read(buf22, 22);
+      data._inp_state_vect_pos_X_comp = buf22;
+
+      is.read(buf22, 22);
+      data._inp_state_vect_pos_Y_comp = buf22;
+
+      is.read(buf22, 22);
+      data._inp_state_vect_pos_Z_comp = buf22;
+
+      is.read(buf22, 22);
+      data._inp_state_vect_vel_Vx_comp = buf22;
+
+      is.read(buf22, 22);
+      data._inp_state_vect_vel_Vy_comp = buf22;
+
+      is.read(buf22, 22);
+      data._inp_state_vect_vel_Vz_comp = buf22;
+
+      is.read(buf4, 4);
+      data._inp_state_vector_type_flag = atoi(buf4);
+
+      is.read(buf16, 16);
+      data._win_coeff_for_range_match = atof(buf16);
+
+      is.read(buf16, 16);
+      data._win_coeff_for_azi_match = atof(buf16);
+
+      is.read(buf4, 4);
+      data._update_period_range_match = atoi(buf4);
+
+      is.read(buf16, 16);
+      data._look_scalar_gain_1 = atof(buf16);
+
+      is.read(buf16, 16);
+      data._look_scalar_gain_2 = atof(buf16);
+
+      is.read(buf16, 16);
+      data._look_scalar_gain_3 = atof(buf16);
+
+      is.read(buf16, 16);
+      data._look_scalar_gain_4 = atof(buf16);
+
+      is.read(buf16, 16);
+      data._look_scalar_gain_5 = atof(buf16);
+
+      is.read(buf16, 16);
+      data._look_scalar_gain_6 = atof(buf16);
+
+      is.read(buf16, 16);
+      data._look_scalar_gain_7 = atof(buf16);
+
+      is.read(buf16, 16);
+      data._look_scalar_gain_8 = atof(buf16);
+
+      is.read(buf4, 4);
+      data._samp_window_start_time_bias = atoi(buf4);
+
+      is.read(buf22, 22);
+      data._doppler_centroid_cubic_coeff = atof(buf22);
+
+      is.read(buf4, 4);
+      data._PRF_code_first_range_line = atoi(buf4);
+
+      is.read(buf4, 4);
+      data._PRF_code_last_range_line = atoi(buf4);
+
+      is.read(buf4, 4);
+      data._samp_win_start_first = atoi(buf4);
+
+      is.read(buf4, 4);
+      data._samp_win_start_last = atoi(buf4);
+
+      is.read(buf4, 4);
+      data._cal_syst_gain_last_proc = atoi(buf4);
+
+      is.read(buf4, 4);
+      data._receiver_gain_last_proc = atoi(buf4);
+
+      is.read(buf4, 4);
+      data._first_processed_range_sample = atoi(buf4);
+
+      is.read(buf4, 4);
+      data._azimuth_FFT_IFFT_ratio = atoi(buf4);
+
+      is.read(buf4, 4);
+      data._num_azimuth_blocks_proc = atoi(buf4);
+
+      is.read(buf8, 8);
+      data._num_input_raw_data_lines = atol(buf8);
+
+      is.read(buf4, 4);
+      data._initial_doppler_ambiguity_num = atoi(buf4);
+
+      is.read(buf16, 16);
+      data._thresh_no_1_flag = atof(buf16);
+
+      is.read(buf16, 16);
+      data._thresh_no_2_flag = atof(buf16);
+
+      is.read(buf16, 16);
+      data._thresh_no_3_flag = atof(buf16);
+
+      is.read(buf16, 16);
+      data._thresh_no_4_flag = atof(buf16);
+
+      is.read(buf16, 16);
+      data._thresh_no_5_flag = atof(buf16);
+
+      is.read(buf16, 16);
+      data._thresh_no_6_flag = atof(buf16);
+
+      is.read(buf16, 16);
+      data._thresh_no_7_flag = atof(buf16);
+
+      is.read(buf16, 16);
+      data._thresh_no_8_flag = atof(buf16);
+
+      is.read(buf16, 16);
+      data._thresh_no_9_flag = atof(buf16);
+
+      is.read(buf16, 16);
+      data._thresh_no_10_flag = atof(buf16);
+
+      is.read(buf16, 16);
+      data._thresh_no_11_flag = atof(buf16);
+
+      is.read(buf16, 16);
+      data._sat_binary_time_of_first = atol(buf16);
+
+      is.read(buf4, 4);
+      data._num_valid_pixels_per_range = atoi(buf4);
+
+      is.read(buf4, 4);
+      data._num_range_samp_discarded = atoi(buf4);
+
+      is.read(buf16, 16);
+      data._I_gain_imb_lower_bound = atof(buf16);
+
+      is.read(buf16, 16);
+      data._I_gain_imb_upper_bound = atof(buf16);
+
+      is.read(buf16, 16);
+      data._I_Q_quad_depar_lower_bound = atof(buf16);
+
+      is.read(buf16, 16);
+      data._I_Q_quad_depar_upper_bound = atof(buf16);
+
+      is.read(buf16, 16);
+      data._3_dB_look_bandwidth = atof(buf16);
+
+      is.read(buf16, 16);
+      data._3_dB_look_proc_dopp_bandw = atof(buf16);
+
+      is.read(buf4, 4);
+      data._range_spread_loss_comp_flag = atoi(buf4);
+
+      is.read(buf1, 1);
+      data._datation_flag = atoi(buf1) != 0;
+
+      is.read(buf7, 7);
+      data._max_error_range_line_timing = atoi(buf7);
+
+      is.read(buf7, 7);
+      data._form_num_range_line_used = atoi(buf7);
+
+      is.read(buf1, 1);
+      data._autom_look_scal_gain_flag = atoi(buf1) != 0;
+
+      is.read(buf4, 4);
+      data._max_value_look_scalar_gain = atoi(buf4);
+
+      is.read(buf4, 4);
+      data._replica_norm_method_flag = atoi(buf4);
+
+      is.read(buf20, 20);
+      data._coef_ground_range_1 = atof(buf20);
+
+      is.read(buf20, 20);
+      data._coef_ground_range_2 = atof(buf20);
+
+      is.read(buf20, 20);
+      data._coef_ground_range_3 = atof(buf20);
+
+      is.read(buf20, 20);
+      data._coef_ground_range_4 = atof(buf20);
+
+      is.read(buf20, 20);
+      data._coef_ant_elev_1 = atof(buf20);
+
+      is.read(buf20, 20);
+      data._coef_ant_elev_2 = atof(buf20);
+
+      is.read(buf20, 20);
+      data._coef_ant_elev_3 = atof(buf20);
+
+      is.read(buf20, 20);
+      data._coef_ant_elev_4 = atof(buf20);
+
+      is.read(buf20, 20);
+      data._coef_ant_elev_5 = atof(buf20);
+
+      is.read(buf16, 16);
+      data._range_time_origin_ant = atof(buf16);
+
+      char buf10238[10238];
+      is.read(buf10238, 10238);
+      return is;
+   }
+
+
+   AlosPalsarFacilityData::AlosPalsarFacilityData(const AlosPalsarFacilityData& rhs):
+      AlosPalsarRecord(rhs),
+      _last_release_qc_date(rhs._last_release_qc_date),
+      _last_release_cal_date(rhs._last_release_cal_date),
+      _qa_summary_flag(rhs._qa_summary_flag),
+      _prf_code_change_flag(rhs._prf_code_change_flag),
+      _sampling_win_change_flag(rhs._sampling_win_change_flag),
+      _cal_gain_change_flag(rhs._cal_gain_change_flag),
+      _quirp_qu_flag(rhs._quirp_qu_flag),
+      _inp_data_stat_flag(rhs._inp_data_stat_flag),
+      _dopp_cent_conf_meas_flag(rhs._dopp_cent_conf_meas_flag),
+      _dopp_cent_val_flag(rhs._dopp_cent_val_flag),
+      _dopp_ambig_conf_meas_flag(rhs._dopp_ambig_conf_meas_flag),
+      _outp_data_mean_flag(rhs._outp_data_mean_flag),
+      _OGOB_flag(rhs._OGOB_flag),
+      _PRF_changes(rhs._PRF_changes),
+      _sampling_win_changes(rhs._sampling_win_changes),
+      _cal_gain_changes(rhs._cal_gain_changes),
+      _missing_lines(rhs._missing_lines),
+      _rec_gain_changes(rhs._rec_gain_changes),
+      _pulse_width_of_ACF_3db(rhs._pulse_width_of_ACF_3db),
+      _first_side_lobe_lev_of_ACF(rhs._first_side_lobe_lev_of_ACF),
+      _ISLR_of_ACF(rhs._ISLR_of_ACF),
+      _dopp_cent_conf_meas(rhs._dopp_cent_conf_meas),
+      _dopp_ambig_conf_meas(rhs._dopp_ambig_conf_meas),
+      _inp_data_I_mean(rhs._inp_data_I_mean),
+      _inp_data_Q_mean(rhs._inp_data_Q_mean),
+      _inp_data_I_stddev(rhs._inp_data_I_stddev),
+      _inp_data_Q_stddev(rhs._inp_data_Q_stddev),
+      _cal_sys_gain(rhs._cal_sys_gain),
+      _first_rec_gain_read(rhs._first_rec_gain_read),
+      _dopp_ambig_num(rhs._dopp_ambig_num),
+      _I_channel_bias_correction(rhs._I_channel_bias_correction),
+      _Q_channel_bias_correction(rhs._Q_channel_bias_correction),
+      _I_channel_gain_correction(rhs._I_channel_gain_correction),
+      _Q_channel_gain_correction(rhs._Q_channel_gain_correction),
+      _Q_channel_I_Q_correction(rhs._Q_channel_I_Q_correction),
+      _noise_power(rhs._noise_power),
+      _int_cal_utc(rhs._int_cal_utc),
+      _num_valid_cal_pulses(rhs._num_valid_cal_pulses),
+      _num_valid_noise_pulses(rhs._num_valid_noise_pulses),
+      _num_valid_replicas(rhs._num_valid_replicas),
+      _first_replica_sample(rhs._first_replica_sample),
+      _mean_cal_pulse_power(rhs._mean_cal_pulse_power),
+      _mean_noise_power(rhs._mean_noise_power),
+      _range_comp_norm_fact(rhs._range_comp_norm_fact),
+      _replica_power(rhs._replica_power),
+      _first_range_pixel_mid_az_inc(rhs._first_range_pixel_mid_az_inc),
+      _center_range_pix_mid_az_inc(rhs._center_range_pix_mid_az_inc),
+      _last_range_pix_mid_az_inc(rhs._last_range_pix_mid_az_inc),
+      _norm_ref_range_ro(rhs._norm_ref_range_ro),
+      _antenna_elev_flag(rhs._antenna_elev_flag),
+      _abs_cal_const_K(rhs._abs_cal_const_K),
+      _upp_bound_K(rhs._upp_bound_K),
+      _low_bound_K(rhs._low_bound_K),
+      _proc_noise_scale_fact(rhs._proc_noise_scale_fact),
+      _K_gen_date(rhs._K_gen_date),
+      _K_vers_num(rhs._K_vers_num),
+      _num_duplic_input_lines(rhs._num_duplic_input_lines),
+      _estim_bit_error_rate(rhs._estim_bit_error_rate),
+      _out_image_mean(rhs._out_image_mean),
+      _out_image_std_dev(rhs._out_image_std_dev),
+      _out_image_max_value(rhs._out_image_max_value),
+      _time_raw_data_first_input(rhs._time_raw_data_first_input),
+      _time_asc_node_state_vectors(rhs._time_asc_node_state_vectors),
+      _asc_node_pos_X_comp(rhs._asc_node_pos_X_comp),
+      _asc_node_pos_Y_comp(rhs._asc_node_pos_Y_comp),
+      _asc_node_pos_Z_comp(rhs._asc_node_pos_Z_comp),
+      _asc_node_vel_X_comp(rhs._asc_node_vel_X_comp),
+      _asc_node_vel_Y_comp(rhs._asc_node_vel_Y_comp),
+      _asc_node_vel_Z_comp(rhs._asc_node_vel_Z_comp),
+      _out_pixel_bit_length(rhs._out_pixel_bit_length),
+      _proc_gain_param_1(rhs._proc_gain_param_1),
+      _proc_gain_param_2(rhs._proc_gain_param_2),
+      _proc_gain_param_3(rhs._proc_gain_param_3),
+      _peak_loc_cross_correl_fun(rhs._peak_loc_cross_correl_fun),
+      _3_dB_width_CCF(rhs._3_dB_width_CCF),
+      _first_side_lobe_level(rhs._first_side_lobe_level),
+      _ISLR_CCF_between_last(rhs._ISLR_CCF_between_last),
+      _peak_loc_CCF_betw_last(rhs._peak_loc_CCF_betw_last),
+      _Roll_Tilt_Mode_flag(rhs._Roll_Tilt_Mode_flag),
+      _raw_data_correction_flag(rhs._raw_data_correction_flag),
+      _look_detecion_flag(rhs._look_detecion_flag),
+      _doppler_ambiguity_estimat_flag(rhs._doppler_ambiguity_estimat_flag),
+      _azimuth_baseband_convers_flag(rhs._azimuth_baseband_convers_flag),
+      _samples_per_line_used(rhs._samples_per_line_used),
+      _range_lines_skip_factor(rhs._range_lines_skip_factor),
+      _time_of_inp_state_vectors(rhs._time_of_inp_state_vectors),
+      _inp_state_vect_pos_X_comp(rhs._inp_state_vect_pos_X_comp),
+      _inp_state_vect_pos_Y_comp(rhs._inp_state_vect_pos_Y_comp),
+      _inp_state_vect_pos_Z_comp(rhs._inp_state_vect_pos_Z_comp),
+      _inp_state_vect_vel_Vx_comp(rhs._inp_state_vect_vel_Vx_comp),
+      _inp_state_vect_vel_Vy_comp(rhs._inp_state_vect_vel_Vy_comp),
+      _inp_state_vect_vel_Vz_comp(rhs._inp_state_vect_vel_Vz_comp),
+      _inp_state_vector_type_flag(rhs._inp_state_vector_type_flag),
+      _win_coeff_for_range_match(rhs._win_coeff_for_range_match),
+      _win_coeff_for_azi_match(rhs._win_coeff_for_azi_match),
+      _update_period_range_match(rhs._update_period_range_match),
+      _look_scalar_gain_1(rhs._look_scalar_gain_1),
+      _look_scalar_gain_2(rhs._look_scalar_gain_2),
+      _look_scalar_gain_3(rhs._look_scalar_gain_3),
+      _look_scalar_gain_4(rhs._look_scalar_gain_4),
+      _look_scalar_gain_5(rhs._look_scalar_gain_5),
+      _look_scalar_gain_6(rhs._look_scalar_gain_6),
+      _look_scalar_gain_7(rhs._look_scalar_gain_7),
+      _look_scalar_gain_8(rhs._look_scalar_gain_8),
+      _samp_window_start_time_bias(rhs._samp_window_start_time_bias),
+      _doppler_centroid_cubic_coeff(rhs._doppler_centroid_cubic_coeff),
+      _PRF_code_first_range_line(rhs._PRF_code_first_range_line),
+      _PRF_code_last_range_line(rhs._PRF_code_last_range_line),
+      _samp_win_start_first(rhs._samp_win_start_first),
+      _samp_win_start_last(rhs._samp_win_start_last),
+      _cal_syst_gain_last_proc(rhs._cal_syst_gain_last_proc),
+      _receiver_gain_last_proc(rhs._receiver_gain_last_proc),
+      _first_processed_range_sample(rhs._first_processed_range_sample),
+      _azimuth_FFT_IFFT_ratio(rhs._azimuth_FFT_IFFT_ratio),
+      _num_azimuth_blocks_proc(rhs._num_azimuth_blocks_proc),
+      _num_input_raw_data_lines(rhs._num_input_raw_data_lines),
+      _initial_doppler_ambiguity_num(rhs._initial_doppler_ambiguity_num),
+      _thresh_no_1_flag(rhs._thresh_no_1_flag),
+      _thresh_no_2_flag(rhs._thresh_no_2_flag),
+      _thresh_no_3_flag(rhs._thresh_no_3_flag),
+      _thresh_no_4_flag(rhs._thresh_no_4_flag),
+      _thresh_no_5_flag(rhs._thresh_no_5_flag),
+      _thresh_no_6_flag(rhs._thresh_no_6_flag),
+      _thresh_no_7_flag(rhs._thresh_no_7_flag),
+      _thresh_no_8_flag(rhs._thresh_no_8_flag),
+      _thresh_no_9_flag(rhs._thresh_no_9_flag),
+      _thresh_no_10_flag(rhs._thresh_no_10_flag),
+      _thresh_no_11_flag(rhs._thresh_no_11_flag),
+      _sat_binary_time_of_first(rhs._sat_binary_time_of_first),
+      _num_valid_pixels_per_range(rhs._num_valid_pixels_per_range),
+      _num_range_samp_discarded(rhs._num_range_samp_discarded),
+      _I_gain_imb_lower_bound(rhs._I_gain_imb_lower_bound),
+      _I_gain_imb_upper_bound(rhs._I_gain_imb_upper_bound),
+      _I_Q_quad_depar_lower_bound(rhs._I_Q_quad_depar_lower_bound),
+      _I_Q_quad_depar_upper_bound(rhs._I_Q_quad_depar_upper_bound),
+      _3_dB_look_bandwidth(rhs._3_dB_look_bandwidth),
+      _3_dB_look_proc_dopp_bandw(rhs._3_dB_look_proc_dopp_bandw),
+      _range_spread_loss_comp_flag(rhs._range_spread_loss_comp_flag),
+      _datation_flag(rhs._datation_flag),
+      _max_error_range_line_timing(rhs._max_error_range_line_timing),
+      _form_num_range_line_used(rhs._form_num_range_line_used),
+      _autom_look_scal_gain_flag(rhs._autom_look_scal_gain_flag),
+      _max_value_look_scalar_gain(rhs._max_value_look_scalar_gain),
+      _replica_norm_method_flag(rhs._replica_norm_method_flag),
+      _coef_ground_range_1(rhs._coef_ground_range_1),
+      _coef_ground_range_2(rhs._coef_ground_range_2),
+      _coef_ground_range_3(rhs._coef_ground_range_3),
+      _coef_ground_range_4(rhs._coef_ground_range_4),
+      _coef_ant_elev_1(rhs._coef_ant_elev_1),
+      _coef_ant_elev_2(rhs._coef_ant_elev_2),
+      _coef_ant_elev_3(rhs._coef_ant_elev_3),
+      _coef_ant_elev_4(rhs._coef_ant_elev_4),
+      _coef_ant_elev_5(rhs._coef_ant_elev_5),
+      _range_time_origin_ant(rhs._range_time_origin_ant)
+   {}
+
+   AlosPalsarFacilityData& AlosPalsarFacilityData::operator=(const AlosPalsarFacilityData& rhs)
+   {
+      _last_release_qc_date = rhs._last_release_qc_date;
+      _last_release_cal_date = rhs._last_release_cal_date;
+      _qa_summary_flag = rhs._qa_summary_flag;
+      _prf_code_change_flag = rhs._prf_code_change_flag;
+      _sampling_win_change_flag = rhs._sampling_win_change_flag;
+      _cal_gain_change_flag = rhs._cal_gain_change_flag;
+      _quirp_qu_flag = rhs._quirp_qu_flag;
+      _inp_data_stat_flag = rhs._inp_data_stat_flag;
+      _dopp_cent_conf_meas_flag = rhs._dopp_cent_conf_meas_flag;
+      _dopp_cent_val_flag = rhs._dopp_cent_val_flag;
+      _dopp_ambig_conf_meas_flag = rhs._dopp_ambig_conf_meas_flag;
+      _outp_data_mean_flag = rhs._outp_data_mean_flag;
+      _OGOB_flag = rhs._OGOB_flag;
+      _PRF_changes = rhs._PRF_changes;
+      _sampling_win_changes = rhs._sampling_win_changes;
+      _cal_gain_changes = rhs._cal_gain_changes;
+      _missing_lines = rhs._missing_lines;
+      _rec_gain_changes = rhs._rec_gain_changes;
+      _pulse_width_of_ACF_3db = rhs._pulse_width_of_ACF_3db;
+      _first_side_lobe_lev_of_ACF = rhs._first_side_lobe_lev_of_ACF;
+      _ISLR_of_ACF = rhs._ISLR_of_ACF;
+      _dopp_cent_conf_meas = rhs._dopp_cent_conf_meas;
+      _dopp_ambig_conf_meas = rhs._dopp_ambig_conf_meas;
+      _inp_data_I_mean = rhs._inp_data_I_mean;
+      _inp_data_Q_mean = rhs._inp_data_Q_mean;
+      _inp_data_I_stddev = rhs._inp_data_I_stddev;
+      _inp_data_Q_stddev = rhs._inp_data_Q_stddev;
+      _cal_sys_gain = rhs._cal_sys_gain;
+      _first_rec_gain_read = rhs._first_rec_gain_read;
+      _dopp_ambig_num = rhs._dopp_ambig_num;
+      _I_channel_bias_correction = rhs._I_channel_bias_correction;
+      _Q_channel_bias_correction = rhs._Q_channel_bias_correction;
+      _I_channel_gain_correction = rhs._I_channel_gain_correction;
+      _Q_channel_gain_correction = rhs._Q_channel_gain_correction;
+      _Q_channel_I_Q_correction = rhs._Q_channel_I_Q_correction;
+      _noise_power = rhs._noise_power;
+      _int_cal_utc = rhs._int_cal_utc;
+      _num_valid_cal_pulses = rhs._num_valid_cal_pulses;
+      _num_valid_noise_pulses = rhs._num_valid_noise_pulses;
+      _num_valid_replicas = rhs._num_valid_replicas;
+      _first_replica_sample = rhs._first_replica_sample;
+      _mean_cal_pulse_power = rhs._mean_cal_pulse_power;
+      _mean_noise_power = rhs._mean_noise_power;
+      _range_comp_norm_fact = rhs._range_comp_norm_fact;
+      _replica_power = rhs._replica_power;
+      _first_range_pixel_mid_az_inc = rhs._first_range_pixel_mid_az_inc;
+      _center_range_pix_mid_az_inc = rhs._center_range_pix_mid_az_inc;
+      _last_range_pix_mid_az_inc = rhs._last_range_pix_mid_az_inc;
+      _norm_ref_range_ro = rhs._norm_ref_range_ro;
+      _antenna_elev_flag = rhs._antenna_elev_flag;
+      _abs_cal_const_K = rhs._abs_cal_const_K;
+      _upp_bound_K = rhs._upp_bound_K;
+      _low_bound_K = rhs._low_bound_K;
+      _proc_noise_scale_fact = rhs._proc_noise_scale_fact;
+      _K_gen_date = rhs._K_gen_date;
+      _K_vers_num = rhs._K_vers_num;
+      _num_duplic_input_lines = rhs._num_duplic_input_lines;
+      _estim_bit_error_rate = rhs._estim_bit_error_rate;
+      _out_image_mean = rhs._out_image_mean;
+      _out_image_std_dev = rhs._out_image_std_dev;
+      _out_image_max_value = rhs._out_image_max_value;
+      _time_raw_data_first_input = rhs._time_raw_data_first_input;
+      _time_asc_node_state_vectors = rhs._time_asc_node_state_vectors;
+      _asc_node_pos_X_comp = rhs._asc_node_pos_X_comp;
+      _asc_node_pos_Y_comp = rhs._asc_node_pos_Y_comp;
+      _asc_node_pos_Z_comp = rhs._asc_node_pos_Z_comp;
+      _asc_node_vel_X_comp = rhs._asc_node_vel_X_comp;
+      _asc_node_vel_Y_comp = rhs._asc_node_vel_Y_comp;
+      _asc_node_vel_Z_comp = rhs._asc_node_vel_Z_comp;
+      _out_pixel_bit_length = rhs._out_pixel_bit_length;
+      _proc_gain_param_1 = rhs._proc_gain_param_1;
+      _proc_gain_param_2 = rhs._proc_gain_param_2;
+      _proc_gain_param_3 = rhs._proc_gain_param_3;
+      _peak_loc_cross_correl_fun = rhs._peak_loc_cross_correl_fun;
+      _3_dB_width_CCF = rhs._3_dB_width_CCF;
+      _first_side_lobe_level = rhs._first_side_lobe_level;
+      _ISLR_CCF_between_last = rhs._ISLR_CCF_between_last;
+      _peak_loc_CCF_betw_last = rhs._peak_loc_CCF_betw_last;
+      _Roll_Tilt_Mode_flag = rhs._Roll_Tilt_Mode_flag;
+      _raw_data_correction_flag = rhs._raw_data_correction_flag;
+      _look_detecion_flag = rhs._look_detecion_flag;
+      _doppler_ambiguity_estimat_flag = rhs._doppler_ambiguity_estimat_flag;
+      _azimuth_baseband_convers_flag = rhs._azimuth_baseband_convers_flag;
+      _samples_per_line_used = rhs._samples_per_line_used;
+      _range_lines_skip_factor = rhs._range_lines_skip_factor;
+      _time_of_inp_state_vectors = rhs._time_of_inp_state_vectors;
+      _inp_state_vect_pos_X_comp = rhs._inp_state_vect_pos_X_comp;
+      _inp_state_vect_pos_Y_comp = rhs._inp_state_vect_pos_Y_comp;
+      _inp_state_vect_pos_Z_comp = rhs._inp_state_vect_pos_Z_comp;
+      _inp_state_vect_vel_Vx_comp = rhs._inp_state_vect_vel_Vx_comp;
+      _inp_state_vect_vel_Vy_comp = rhs._inp_state_vect_vel_Vy_comp;
+      _inp_state_vect_vel_Vz_comp = rhs._inp_state_vect_vel_Vz_comp;
+      _inp_state_vector_type_flag = rhs._inp_state_vector_type_flag;
+      _win_coeff_for_range_match = rhs._win_coeff_for_range_match;
+      _win_coeff_for_azi_match = rhs._win_coeff_for_azi_match;
+      _update_period_range_match = rhs._update_period_range_match;
+      _look_scalar_gain_1 = rhs._look_scalar_gain_1;
+      _look_scalar_gain_2 = rhs._look_scalar_gain_2;
+      _look_scalar_gain_3 = rhs._look_scalar_gain_3;
+      _look_scalar_gain_4 = rhs._look_scalar_gain_4;
+      _look_scalar_gain_5 = rhs._look_scalar_gain_5;
+      _look_scalar_gain_6 = rhs._look_scalar_gain_6;
+      _look_scalar_gain_7 = rhs._look_scalar_gain_7;
+      _look_scalar_gain_8 = rhs._look_scalar_gain_8;
+      _samp_window_start_time_bias = rhs._samp_window_start_time_bias;
+      _doppler_centroid_cubic_coeff = rhs._doppler_centroid_cubic_coeff;
+      _PRF_code_first_range_line = rhs._PRF_code_first_range_line;
+      _PRF_code_last_range_line = rhs._PRF_code_last_range_line;
+      _samp_win_start_first = rhs._samp_win_start_first;
+      _samp_win_start_last = rhs._samp_win_start_last;
+      _cal_syst_gain_last_proc = rhs._cal_syst_gain_last_proc;
+      _receiver_gain_last_proc = rhs._receiver_gain_last_proc;
+      _first_processed_range_sample = rhs._first_processed_range_sample;
+      _azimuth_FFT_IFFT_ratio = rhs._azimuth_FFT_IFFT_ratio;
+      _num_azimuth_blocks_proc = rhs._num_azimuth_blocks_proc;
+      _num_input_raw_data_lines = rhs._num_input_raw_data_lines;
+      _initial_doppler_ambiguity_num = rhs._initial_doppler_ambiguity_num;
+      _thresh_no_1_flag = rhs._thresh_no_1_flag;
+      _thresh_no_2_flag = rhs._thresh_no_2_flag;
+      _thresh_no_3_flag = rhs._thresh_no_3_flag;
+      _thresh_no_4_flag = rhs._thresh_no_4_flag;
+      _thresh_no_5_flag = rhs._thresh_no_5_flag;
+      _thresh_no_6_flag = rhs._thresh_no_6_flag;
+      _thresh_no_7_flag = rhs._thresh_no_7_flag;
+      _thresh_no_8_flag = rhs._thresh_no_8_flag;
+      _thresh_no_9_flag = rhs._thresh_no_9_flag;
+      _thresh_no_10_flag = rhs._thresh_no_10_flag;
+      _thresh_no_11_flag = rhs._thresh_no_11_flag;
+      _sat_binary_time_of_first = rhs._sat_binary_time_of_first;
+      _num_valid_pixels_per_range = rhs._num_valid_pixels_per_range;
+      _num_range_samp_discarded = rhs._num_range_samp_discarded;
+      _I_gain_imb_lower_bound = rhs._I_gain_imb_lower_bound;
+      _I_gain_imb_upper_bound = rhs._I_gain_imb_upper_bound;
+      _I_Q_quad_depar_lower_bound = rhs._I_Q_quad_depar_lower_bound;
+      _I_Q_quad_depar_upper_bound = rhs._I_Q_quad_depar_upper_bound;
+      _3_dB_look_bandwidth = rhs._3_dB_look_bandwidth;
+      _3_dB_look_proc_dopp_bandw = rhs._3_dB_look_proc_dopp_bandw;
+      _range_spread_loss_comp_flag = rhs._range_spread_loss_comp_flag;
+      _datation_flag = rhs._datation_flag;
+      _max_error_range_line_timing = rhs._max_error_range_line_timing;
+      _form_num_range_line_used = rhs._form_num_range_line_used;
+      _autom_look_scal_gain_flag = rhs._autom_look_scal_gain_flag;
+      _max_value_look_scalar_gain = rhs._max_value_look_scalar_gain;
+      _replica_norm_method_flag = rhs._replica_norm_method_flag;
+      _coef_ground_range_1 = rhs._coef_ground_range_1;
+      _coef_ground_range_2 = rhs._coef_ground_range_2;
+      _coef_ground_range_3 = rhs._coef_ground_range_3;
+      _coef_ground_range_4 = rhs._coef_ground_range_4;
+      _coef_ant_elev_1 = rhs._coef_ant_elev_1;
+      _coef_ant_elev_2 = rhs._coef_ant_elev_2;
+      _coef_ant_elev_3 = rhs._coef_ant_elev_3;
+      _coef_ant_elev_4 = rhs._coef_ant_elev_4;
+      _coef_ant_elev_5 = rhs._coef_ant_elev_5;
+      _range_time_origin_ant = rhs._range_time_origin_ant;
+
+      return *this;
+   }
+}
+
diff --git a/ossim_plugins/ossim/AlosPalsar/AlosPalsarFacilityData.h b/ossim_plugins/ossim/AlosPalsar/AlosPalsarFacilityData.h
new file mode 100644
index 0000000..15e6558
--- /dev/null
+++ b/ossim_plugins/ossim/AlosPalsar/AlosPalsarFacilityData.h
@@ -0,0 +1,1809 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+// "Copyright Centre for Remote Imaging, Sensing and Processing"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef AlosPalsarFacilityData_h
+#define AlosPalsarFacilityData_h
+
+#include <iostream>
+#include <cstdlib>
+#include <AlosPalsar/AlosPalsarRecordHeader.h>
+#include <AlosPalsar/AlosPalsarRecord.h>
+
+namespace ossimplugins
+{
+
+/**
+ * @ingroup AlosPalsarFacilityDataRecord
+ * @brief This class is able to read the SAR leader data set summary record of the leader file
+ */
+class AlosPalsarFacilityData : public AlosPalsarRecord
+{
+public:
+  /**
+   * @brief Constructor
+   */
+  AlosPalsarFacilityData();
+
+  /**
+   * @brief Destructor
+   */
+  virtual ~AlosPalsarFacilityData();
+
+  /**
+   * @brief This function write the AlosPalsarFacilityData in a stream
+   */
+  friend std::ostream& operator<<(std::ostream& os, const AlosPalsarFacilityData& data);
+
+  /**
+   * @brief This function read a AlosPalsarFacilityData from a stream
+   */
+  friend std::istream& operator>>(std::istream& is, AlosPalsarFacilityData& data);
+
+  /**
+   * @brief Copy constructor
+   */
+  AlosPalsarFacilityData(const AlosPalsarFacilityData& rhs);
+
+  /**
+   * @brief Copy operator
+   */
+  AlosPalsarFacilityData& operator=(const AlosPalsarFacilityData& rhs);
+
+  /**
+   * @brief This function is able to create a new instance of the class
+   */
+  AlosPalsarRecord* Instanciate()
+  {
+    return new AlosPalsarFacilityData();
+  };
+
+  /**
+   * @brief This function is able to create a new instance of the class initialised with the data of the calling instance
+   */
+  AlosPalsarRecord* Clone()
+  {
+    return new AlosPalsarFacilityData(*this);
+  };
+
+  /**
+   * @brief Read the class data from a stream
+   */
+  void Read(std::istream& is)
+  {
+    is >> *this;
+  };
+
+  /**
+   * @brief Write the class to a stream
+   */
+  void Write(std::ostream& os)
+  {
+    os << *this;
+  };
+
+  /**
+  * @brief name_of_facil_rec
+  */
+  std::string   get_name_of_facil_rec() const
+  {
+    return _name_of_facil_rec;
+  };
+
+  /**
+  * @brief last_release_qc_date
+  */
+  std::string   get_last_release_qc_date() const
+  {
+    return _last_release_qc_date;
+  };
+  /**
+  * @brief last_release_cal_date
+  */
+  std::string   get_last_release_cal_date() const
+  {
+    return _last_release_cal_date;
+  };
+  /**
+  * @brief qa_summary_flag
+  */
+  int   get_qa_summary_flag() const
+  {
+    return _qa_summary_flag;
+  };
+  /**
+  * @brief prf_code_change_flag
+  */
+  int   get_prf_code_change_flag() const
+  {
+    return _prf_code_change_flag;
+  };
+  /**
+  * @brief sampling_win_change_flag
+  */
+  int   get_sampling_win_change_flag() const
+  {
+    return _sampling_win_change_flag;
+  };
+  /**
+  * @brief cal_gain_change_flag
+  */
+  int   get_cal_gain_change_flag() const
+  {
+    return _cal_gain_change_flag;
+  };
+  /**
+  * @brief quirp_qu_flag
+  */
+  int   get_quirp_qu_flag() const
+  {
+    return _quirp_qu_flag;
+  };
+  /**
+  * @brief inp_data_stat_flag
+  */
+  int   get_inp_data_stat_flag() const
+  {
+    return _inp_data_stat_flag;
+  };
+  /**
+  * @brief dopp_cent_conf_meas_flag
+  */
+  int   get_dopp_cent_conf_meas_flag() const
+  {
+    return _dopp_cent_conf_meas_flag;
+  };
+  /**
+  * @brief dopp_cent_val_flag
+  */
+  int   get_dopp_cent_val_flag() const
+  {
+    return _dopp_cent_val_flag;
+  };
+  /**
+  * @brief dopp_ambig_conf_meas_flag
+  */
+  int   get_dopp_ambig_conf_meas_flag() const
+  {
+    return _dopp_ambig_conf_meas_flag;
+  };
+  /**
+  * @brief outp_data_mean_flag
+  */
+  int   get_outp_data_mean_flag() const
+  {
+    return _outp_data_mean_flag;
+  };
+  /**
+  * @brief OGOB_flag
+  */
+  int   get_OGOB_flag()
+  {
+    return _OGOB_flag;
+  };
+  /**
+  * @brief PRF_changes
+  */
+  int   get_PRF_changes()
+  {
+    return _PRF_changes;
+  };
+  /**
+  * @brief sampling_win_changes
+  */
+  int   get_sampling_win_changes() const
+  {
+    return _sampling_win_changes;
+  };
+  /**
+  * @brief cal_gain_changes
+  */
+  int   get_cal_gain_changes() const
+  {
+    return _cal_gain_changes;
+  };
+  /**
+  * @brief missing_lines
+  */
+  int   get_missing_lines() const
+  {
+    return _missing_lines;
+  };
+  /**
+  * @brief rec_gain_changes
+  */
+  int   get_rec_gain_changes() const
+  {
+    return _rec_gain_changes;
+  };
+  /**
+  * @brief pulse_width_of_ACF_3db
+  */
+  double   get_pulse_width_of_ACF_3db()
+  {
+    return _pulse_width_of_ACF_3db;
+  };
+  /**
+  * @brief first_side_lobe_lev_of_ACF
+  */
+  double   get_first_side_lobe_lev_of_ACF()
+  {
+    return _first_side_lobe_lev_of_ACF;
+  };
+  /**
+  * @brief ISLR_of_ACF
+  */
+  double   get_ISLR_of_ACF()
+  {
+    return _ISLR_of_ACF;
+  };
+  /**
+  * @brief dopp_cent_conf_meas
+  */
+  double   get_dopp_cent_conf_meas() const
+  {
+    return _dopp_cent_conf_meas;
+  };
+  /**
+  * @brief dopp_ambig_conf_meas
+  */
+  double   get_dopp_ambig_conf_meas() const
+  {
+    return _dopp_ambig_conf_meas;
+  };
+  /**
+  * @brief inp_data_I_mean
+  */
+  double   get_inp_data_I_mean()
+  {
+    return _inp_data_I_mean;
+  };
+  /**
+  * @brief inp_data_Q_mean
+  */
+  double   get_inp_data_Q_mean()
+  {
+    return _inp_data_Q_mean;
+  };
+  /**
+  * @brief inp_data_I_stddev
+  */
+  double   get_inp_data_I_stddev()
+  {
+    return _inp_data_I_stddev;
+  };
+  /**
+  * @brief inp_data_Q_stddev
+  */
+  double   get_inp_data_Q_stddev()
+  {
+    return _inp_data_Q_stddev;
+  };
+  /**
+  * @brief cal_sys_gain
+  */
+  double   get_cal_sys_gain() const
+  {
+    return _cal_sys_gain;
+  };
+  /**
+  * @brief first_rec_gain_read
+  */
+  double   get_first_rec_gain_read() const
+  {
+    return _first_rec_gain_read;
+  };
+  /**
+  * @brief dopp_ambig_num
+  */
+  double   get_dopp_ambig_num() const
+  {
+    return _dopp_ambig_num;
+  };
+  /**
+  * @brief I_channel_bias_correction
+  */
+  double   get_I_channel_bias_correction()
+  {
+    return _I_channel_bias_correction;
+  };
+  /**
+  * @brief Q_channel_bias_correction
+  */
+  double   get_Q_channel_bias_correction()
+  {
+    return _Q_channel_bias_correction;
+  };
+  /**
+  * @brief I_channel_gain_correction
+  */
+  double   get_I_channel_gain_correction()
+  {
+    return _I_channel_gain_correction;
+  };
+  /**
+  * @brief Q_channel_gain_correction
+  */
+  double   get_Q_channel_gain_correction()
+  {
+    return _Q_channel_gain_correction;
+  };
+  /**
+  * @brief Q_channel_I_Q_correction
+  */
+  double   get_Q_channel_I_Q_correction()
+  {
+    return _Q_channel_I_Q_correction;
+  };
+  /**
+  * @brief noise_power
+  */
+  double   get_noise_power() const
+  {
+    return _noise_power;
+  };
+  /**
+  * @brief int_cal_utc
+  */
+  int   get_int_cal_utc() const
+  {
+    return _int_cal_utc;
+  };
+  /**
+  * @brief num_valid_cal_pulses
+  */
+  int   get_num_valid_cal_pulses() const
+  {
+    return _num_valid_cal_pulses;
+  };
+  /**
+  * @brief num_valid_noise_pulses
+  */
+  int   get_num_valid_noise_pulses() const
+  {
+    return _num_valid_noise_pulses;
+  };
+  /**
+  * @brief num_valid_replicas
+  */
+  int   get_num_valid_replicas() const
+  {
+    return _num_valid_replicas;
+  };
+  /**
+  * @brief first_replica_sample
+  */
+  double   get_first_replica_sample() const
+  {
+    return _first_replica_sample;
+  };
+  /**
+  * @brief mean_cal_pulse_power
+  */
+  double   get_mean_cal_pulse_power() const
+  {
+    return _mean_cal_pulse_power;
+  };
+  /**
+  * @brief mean_noise_power
+  */
+  double   get_mean_noise_power() const
+  {
+    return _mean_noise_power;
+  };
+  /**
+  * @brief range_comp_norm_fact
+  */
+  double   get_range_comp_norm_fact() const
+  {
+    return _range_comp_norm_fact;
+  };
+  /**
+  * @brief replica_power
+  */
+  double   get_replica_power() const
+  {
+    return _replica_power;
+  };
+  /**
+  * @brief first_range_pixel_mid_az_inc
+  */
+  double   get_first_range_pixel_mid_az_inc() const
+  {
+    return _first_range_pixel_mid_az_inc;
+  };
+  /**
+  * @brief center_range_pix_mid_az_inc
+  */
+  double   get_center_range_pix_mid_az_inc() const
+  {
+    return _center_range_pix_mid_az_inc;
+  };
+  /**
+  * @brief last_range_pix_mid_az_inc
+  */
+  double   get_last_range_pix_mid_az_inc() const
+  {
+    return _last_range_pix_mid_az_inc;
+  };
+  /**
+  * @brief norm_ref_range_ro
+  */
+  double   get_norm_ref_range_ro() const
+  {
+    return _norm_ref_range_ro;
+  };
+  /**
+  * @brief antenna_elev_flag
+  */
+  int   get_antenna_elev_flag() const
+  {
+    return _antenna_elev_flag;
+  };
+  /**
+  * @brief abs_cal_const_K
+  */
+  double   get_abs_cal_const_K()
+  {
+    return _abs_cal_const_K;
+  };
+  /**
+  * @brief upp_bound_K
+  */
+  double   get_upp_bound_K()
+  {
+    return _upp_bound_K;
+  };
+  /**
+  * @brief low_bound_K
+  */
+  double   get_low_bound_K()
+  {
+    return _low_bound_K;
+  };
+  /**
+  * @brief proc_noise_scale_fact
+  */
+  double   get_proc_noise_scale_fact() const
+  {
+    return _proc_noise_scale_fact;
+  };
+  /**
+  * @brief K_gen_date
+  */
+  std::string   get_K_gen_date()
+  {
+    return _K_gen_date;
+  };
+  /**
+  * @brief K_vers_num
+  */
+  std::string   get_K_vers_num()
+  {
+    return _K_vers_num;
+  };
+  /**
+  * @brief num_duplic_input_lines
+  */
+  int   get_num_duplic_input_lines() const
+  {
+    return _num_duplic_input_lines;
+  };
+  /**
+  * @brief estim_bit_error_rate
+  */
+  double   get_estim_bit_error_rate() const
+  {
+    return _estim_bit_error_rate;
+  };
+  /**
+  * @brief out_image_mean
+  */
+  double   get_out_image_mean() const
+  {
+    return _out_image_mean;
+  };
+  /**
+  * @brief out_image_std_dev
+  */
+  double   get_out_image_std_dev() const
+  {
+    return _out_image_std_dev;
+  };
+  /**
+  * @brief out_image_max_value
+  */
+  double   get_out_image_max_value() const
+  {
+    return _out_image_max_value;
+  };
+  /**
+  * @brief time_raw_data_first_input
+  */
+  std::string   get_time_raw_data_first_input() const
+  {
+    return _time_raw_data_first_input;
+  };
+  /**
+  * @brief time_asc_node_state_vectors
+  */
+  std::string   get_time_asc_node_state_vectors() const
+  {
+    return _time_asc_node_state_vectors;
+  };
+  /**
+  * @brief asc_node_pos_X_comp
+  */
+  std::string   get_asc_node_pos_X_comp()
+  {
+    return _asc_node_pos_X_comp;
+  };
+  /**
+  * @brief asc_node_pos_Y_comp
+  */
+  std::string   get_asc_node_pos_Y_comp()
+  {
+    return _asc_node_pos_Y_comp;
+  };
+  /**
+  * @brief asc_node_pos_Z_comp
+  */
+  std::string   get_asc_node_pos_Z_comp()
+  {
+    return _asc_node_pos_Z_comp;
+  };
+  /**
+  * @brief asc_node_vel_X_comp
+  */
+  std::string   get_asc_node_vel_X_comp()
+  {
+    return _asc_node_vel_X_comp;
+  };
+  /**
+  * @brief asc_node_vel_Y_comp
+  */
+  std::string   get_asc_node_vel_Y_comp()
+  {
+    return _asc_node_vel_Y_comp;
+  };
+  /**
+  * @brief asc_node_vel_Z_comp
+  */
+  std::string   get_asc_node_vel_Z_comp()
+  {
+    return _asc_node_vel_Z_comp;
+  };
+  /**
+  * @brief out_pixel_bit_length
+  */
+  int   get_out_pixel_bit_length() const
+  {
+    return _out_pixel_bit_length;
+  };
+  /**
+  * @brief proc_gain_param_1
+  */
+  double   get_proc_gain_param_1()
+  {
+    return _proc_gain_param_1;
+  };
+  /**
+  * @brief proc_gain_param_2
+  */
+  double   get_proc_gain_param_2()
+  {
+    return _proc_gain_param_2;
+  };
+  /**
+  * @brief proc_gain_param_3
+  */
+  double   get_proc_gain_param_3()
+  {
+    return _proc_gain_param_3;
+  };
+  /**
+  * @brief peak_loc_cross_correl_fun
+  */
+  int   get_peak_loc_cross_correl_fun() const
+  {
+    return _peak_loc_cross_correl_fun;
+  };
+  /**
+  * @brief 3_dB_width_CCF
+  */
+  double   get_3_dB_width_CCF()
+  {
+    return _3_dB_width_CCF;
+  };
+  /**
+  * @brief first_side_lobe_level
+  */
+  double   get_first_side_lobe_level() const
+  {
+    return _first_side_lobe_level;
+  };
+  /**
+  * @brief ISLR_CCF_between_last
+  */
+  double   get_ISLR_CCF_between_last()
+  {
+    return _ISLR_CCF_between_last;
+  };
+  /**
+  * @brief peak_loc_CCF_betw_last
+  */
+  int   get_peak_loc_CCF_betw_last()
+  {
+    return _peak_loc_CCF_betw_last;
+  };
+  /**
+  * @brief Roll_Tilt_Mode_flag
+  */
+  int   get_Roll_Tilt_Mode_flag()
+  {
+    return _Roll_Tilt_Mode_flag;
+  };
+  /**
+  * @brief raw_data_correction_flag
+  */
+  int   get_raw_data_correction_flag() const
+  {
+    return _raw_data_correction_flag;
+  };
+  /**
+  * @brief look_detecion_flag
+  */
+  int   get_look_detecion_flag() const
+  {
+    return _look_detecion_flag;
+  };
+  /**
+  * @brief doppler_ambiguity_estimat_flag
+  */
+  int   get_doppler_ambiguity_estimat_flag() const
+  {
+    return _doppler_ambiguity_estimat_flag;
+  };
+  /**
+  * @brief azimuth_baseband_convers_flag
+  */
+  int   get_azimuth_baseband_convers_flag() const
+  {
+    return _azimuth_baseband_convers_flag;
+  };
+  /**
+  * @brief samples_per_line_used
+  */
+  int   get_samples_per_line_used() const
+  {
+    return _samples_per_line_used;
+  };
+  /**
+  * @brief range_lines_skip_factor
+  */
+  int   get_range_lines_skip_factor() const
+  {
+    return _range_lines_skip_factor;
+  };
+  /**
+  * @brief time_of_inp_state_vectors
+  */
+  std::string   get_time_of_inp_state_vectors() const
+  {
+    return _time_of_inp_state_vectors;
+  };
+  /**
+  * @brief inp_state_vect_pos_X_comp
+  */
+  std::string   get_inp_state_vect_pos_X_comp()
+  {
+    return _inp_state_vect_pos_X_comp;
+  };
+  /**
+  * @brief inp_state_vect_pos_Y_comp
+  */
+  std::string   get_inp_state_vect_pos_Y_comp()
+  {
+    return _inp_state_vect_pos_Y_comp;
+  };
+  /**
+  * @brief inp_state_vect_pos_Z_comp
+  */
+  std::string   get_inp_state_vect_pos_Z_comp()
+  {
+    return _inp_state_vect_pos_Z_comp;
+  };
+  /**
+  * @brief inp_state_vect_vel_Vx_comp
+  */
+  std::string   get_inp_state_vect_vel_Vx_comp()
+  {
+    return _inp_state_vect_vel_Vx_comp;
+  };
+  /**
+  * @brief inp_state_vect_vel_Vy_comp
+  */
+  std::string   get_inp_state_vect_vel_Vy_comp()
+  {
+    return _inp_state_vect_vel_Vy_comp;
+  };
+  /**
+  * @brief inp_state_vect_vel_Vz_comp
+  */
+  std::string   get_inp_state_vect_vel_Vz_comp()
+  {
+    return _inp_state_vect_vel_Vz_comp;
+  };
+  /**
+  * @brief inp_state_vector_type_flag
+  */
+  int   get_inp_state_vector_type_flag() const
+  {
+    return _inp_state_vector_type_flag;
+  };
+  /**
+  * @brief win_coeff_for_range_match
+  */
+  double   get_win_coeff_for_range_match() const
+  {
+    return _win_coeff_for_range_match;
+  };
+  /**
+  * @brief win_coeff_for_azi_match
+  */
+  double   get_win_coeff_for_azi_match() const
+  {
+    return _win_coeff_for_azi_match;
+  };
+  /**
+  * @brief update_period_range_match
+  */
+  int   get_update_period_range_match() const
+  {
+    return _update_period_range_match;
+  };
+  /**
+  * @brief look_scalar_gain_1
+  */
+  double   get_look_scalar_gain_1()
+  {
+    return _look_scalar_gain_1;
+  };
+  /**
+  * @brief look_scalar_gain_2
+  */
+  double   get_look_scalar_gain_2()
+  {
+    return _look_scalar_gain_2;
+  };
+  /**
+  * @brief look_scalar_gain_3
+  */
+  double   get_look_scalar_gain_3()
+  {
+    return _look_scalar_gain_3;
+  };
+  /**
+  * @brief look_scalar_gain_4
+  */
+  double   get_look_scalar_gain_4()
+  {
+    return _look_scalar_gain_4;
+  };
+  /**
+  * @brief look_scalar_gain_5
+  */
+  double   get_look_scalar_gain_5()
+  {
+    return _look_scalar_gain_5;
+  };
+  /**
+  * @brief look_scalar_gain_6
+  */
+  double   get_look_scalar_gain_6()
+  {
+    return _look_scalar_gain_6;
+  };
+  /**
+  * @brief look_scalar_gain_7
+  */
+  double   get_look_scalar_gain_7()
+  {
+    return _look_scalar_gain_7;
+  };
+  /**
+  * @brief look_scalar_gain_8
+  */
+  double   get_look_scalar_gain_8()
+  {
+    return _look_scalar_gain_8;
+  };
+  /**
+  * @brief samp_window_start_time_bias
+  */
+  int   get_samp_window_start_time_bias() const
+  {
+    return _samp_window_start_time_bias;
+  };
+  /**
+  * @brief doppler_centroid_cubic_coeff
+  */
+  double   get_doppler_centroid_cubic_coeff() const
+  {
+    return _doppler_centroid_cubic_coeff;
+  };
+  /**
+  * @brief PRF_code_first_range_line
+  */
+  int   get_PRF_code_first_range_line()
+  {
+    return _PRF_code_first_range_line;
+  };
+  /**
+  * @brief PRF_code_last_range_line
+  */
+  int   get_PRF_code_last_range_line()
+  {
+    return _PRF_code_last_range_line;
+  };
+  /**
+  * @brief samp_win_start_first
+  */
+  int   get_samp_win_start_first() const
+  {
+    return _samp_win_start_first;
+  };
+  /**
+  * @brief samp_win_start_last
+  */
+  int   get_samp_win_start_last() const
+  {
+    return _samp_win_start_last;
+  };
+  /**
+  * @brief cal_syst_gain_last_proc
+  */
+  int   get_cal_syst_gain_last_proc() const
+  {
+    return _cal_syst_gain_last_proc;
+  };
+  /**
+  * @brief receiver_gain_last_proc
+  */
+  int   get_receiver_gain_last_proc() const
+  {
+    return _receiver_gain_last_proc;
+  };
+  /**
+  * @brief first_processed_range_sample
+  */
+  int   get_first_processed_range_sample() const
+  {
+    return _first_processed_range_sample;
+  };
+  /**
+  * @brief azimuth_FFT_IFFT_ratio
+  */
+  int   get_azimuth_FFT_IFFT_ratio()
+  {
+    return _azimuth_FFT_IFFT_ratio;
+  };
+  /**
+  * @brief num_azimuth_blocks_proc
+  */
+  int   get_num_azimuth_blocks_proc() const
+  {
+    return _num_azimuth_blocks_proc;
+  };
+  /**
+  * @brief num_input_raw_data_lines
+  */
+  int   get_num_input_raw_data_lines() const
+  {
+    return _num_input_raw_data_lines;
+  };
+  /**
+  * @brief initial_doppler_ambiguity_num
+  */
+  int   get_initial_doppler_ambiguity_num() const
+  {
+    return _initial_doppler_ambiguity_num;
+  };
+  /**
+  * @brief thresh_no_1_flag
+  */
+  double   get_thresh_no_1_flag()
+  {
+    return _thresh_no_1_flag;
+  };
+  /**
+  * @brief thresh_no_2_flag
+  */
+  double   get_thresh_no_2_flag()
+  {
+    return _thresh_no_2_flag;
+  };
+  /**
+  * @brief thresh_no_3_flag
+  */
+  double   get_thresh_no_3_flag()
+  {
+    return _thresh_no_3_flag;
+  };
+  /**
+  * @brief thresh_no_4_flag
+  */
+  double   get_thresh_no_4_flag()
+  {
+    return _thresh_no_4_flag;
+  };
+  /**
+  * @brief thresh_no_5_flag
+  */
+  double   get_thresh_no_5_flag()
+  {
+    return _thresh_no_5_flag;
+  };
+  /**
+  * @brief thresh_no_6_flag
+  */
+  double   get_thresh_no_6_flag()
+  {
+    return _thresh_no_6_flag;
+  };
+  /**
+  * @brief thresh_no_7_flag
+  */
+  double   get_thresh_no_7_flag()
+  {
+    return _thresh_no_7_flag;
+  };
+  /**
+  * @brief thresh_no_8_flag
+  */
+  double   get_thresh_no_8_flag()
+  {
+    return _thresh_no_8_flag;
+  };
+  /**
+  * @brief thresh_no_9_flag
+  */
+  double   get_thresh_no_9_flag()
+  {
+    return _thresh_no_9_flag;
+  };
+  /**
+  * @brief thresh_no_10_flag
+  */
+  double   get_thresh_no_10_flag()
+  {
+    return _thresh_no_10_flag;
+  };
+  /**
+  * @brief thresh_no_11_flag
+  */
+  double   get_thresh_no_11_flag()
+  {
+    return _thresh_no_11_flag;
+  };
+  /**
+  * @brief sat_binary_time_of_first
+  */
+  int   get_sat_binary_time_of_first() const
+  {
+    return _sat_binary_time_of_first;
+  };
+  /**
+  * @brief num_valid_pixels_per_range
+  */
+  int   get_num_valid_pixels_per_range() const
+  {
+    return _num_valid_pixels_per_range;
+  };
+  /**
+  * @brief num_range_samp_discarded
+  */
+  int   get_num_range_samp_discarded() const
+  {
+    return _num_range_samp_discarded;
+  };
+  /**
+  * @brief I_gain_imb_lower_bound
+  */
+  double   get_I_gain_imb_lower_bound()
+  {
+    return _I_gain_imb_lower_bound;
+  };
+  /**
+  * @brief I_gain_imb_upper_bound
+  */
+  double   get_I_gain_imb_upper_bound()
+  {
+    return _I_gain_imb_upper_bound;
+  };
+  /**
+  * @brief I_Q_quad_depar_lower_bound
+  */
+  double   get_I_Q_quad_depar_lower_bound()
+  {
+    return _I_Q_quad_depar_lower_bound;
+  };
+  /**
+  * @brief I_Q_quad_depar_upper_bound
+  */
+  double   get_I_Q_quad_depar_upper_bound()
+  {
+    return _I_Q_quad_depar_upper_bound;
+  };
+  /**
+  * @brief 3_dB_look_bandwidth
+  */
+  double   get_3_dB_look_bandwidth()
+  {
+    return _3_dB_look_bandwidth;
+  };
+  /**
+  * @brief 3_dB_look_proc_dopp_bandw
+  */
+  double   get_3_dB_look_proc_dopp_bandw()
+  {
+    return _3_dB_look_proc_dopp_bandw;
+  };
+  /**
+  * @brief range_spread_loss_comp_flag
+  */
+  int   get_range_spread_loss_comp_flag() const
+  {
+    return _range_spread_loss_comp_flag;
+  };
+  /**
+  * @brief datation_flag
+  */
+  bool   get_datation_flag() const
+  {
+    return _datation_flag;
+  };
+  /**
+  * @brief max_error_range_line_timing
+  */
+  int   get_max_error_range_line_timing() const
+  {
+    return _max_error_range_line_timing;
+  };
+  /**
+  * @brief form_num_range_line_used
+  */
+  int   get_form_num_range_line_used() const
+  {
+    return _form_num_range_line_used;
+  };
+  /**
+  * @brief autom_look_scal_gain_flag
+  */
+  bool   get_autom_look_scal_gain_flag() const
+  {
+    return _autom_look_scal_gain_flag;
+  };
+  /**
+  * @brief max_value_look_scalar_gain
+  */
+  int   get_max_value_look_scalar_gain() const
+  {
+    return _max_value_look_scalar_gain;
+  };
+  /**
+  * @brief replica_norm_method_flag
+  */
+  int   get_replica_norm_method_flag() const
+  {
+    return _replica_norm_method_flag;
+  };
+  /**
+  * @brief coef_ground_range_1
+  */
+  double   get_coef_ground_range_1() const
+  {
+    return _coef_ground_range_1;
+  };
+  /**
+  * @brief coef_ground_range_2
+  */
+  double   get_coef_ground_range_2() const
+  {
+    return _coef_ground_range_2;
+  };
+  /**
+  * @brief coef_ground_range_3
+  */
+  double   get_coef_ground_range_3() const
+  {
+    return _coef_ground_range_3;
+  };
+  /**
+  * @brief coef_ground_range_4
+  */
+  double   get_coef_ground_range_4() const
+  {
+    return _coef_ground_range_4;
+  };
+  /**
+  * @brief coef_ant_elev_1
+  */
+  double   get_coef_ant_elev_1() const
+  {
+    return _coef_ant_elev_1;
+  };
+  /**
+  * @brief coef_ant_elev_2
+  */
+  double   get_coef_ant_elev_2() const
+  {
+    return _coef_ant_elev_2;
+  };
+  /**
+  * @brief coef_ant_elev_3
+  */
+  double   get_coef_ant_elev_3() const
+  {
+    return _coef_ant_elev_3;
+  };
+  /**
+  * @brief coef_ant_elev_4
+  */
+  double   get_coef_ant_elev_4() const
+  {
+    return _coef_ant_elev_4;
+  };
+  /**
+  * @brief coef_ant_elev_5
+  */
+  double   get_coef_ant_elev_5() const
+  {
+    return _coef_ant_elev_5;
+  };
+  /**
+  * @brief range_time_origin_ant
+  */
+  double   get_range_time_origin_ant() const
+  {
+    return _range_time_origin_ant;
+  };
+
+
+protected:
+
+  /**
+  * @brief last_release_qc_date
+  */
+  std::string  _name_of_facil_rec;
+  /**
+  * @brief last_release_qc_date
+  */
+  std::string  _last_release_qc_date;
+  /**
+  * @brief last_release_cal_date
+  */
+  std::string   _last_release_cal_date;
+  /**
+  * @brief qa_summary_flag
+  */
+  int   _qa_summary_flag;
+  /**
+  * @brief prf_code_change_flag
+  */
+  int   _prf_code_change_flag;
+  /**
+  * @brief sampling_win_change_flag
+  */
+  int   _sampling_win_change_flag;
+  /**
+  * @brief cal_gain_change_flag
+  */
+  int   _cal_gain_change_flag;
+  /**
+  * @brief quirp_qu_flag
+  */
+  int   _quirp_qu_flag;
+  /**
+  * @brief inp_data_stat_flag
+  */
+  int   _inp_data_stat_flag;
+  /**
+  * @brief dopp_cent_conf_meas_flag
+  */
+  int   _dopp_cent_conf_meas_flag;
+  /**
+  * @brief dopp_cent_val_flag
+  */
+  int   _dopp_cent_val_flag;
+  /**
+  * @brief dopp_ambig_conf_meas_flag
+  */
+  int   _dopp_ambig_conf_meas_flag;
+  /**
+  * @brief outp_data_mean_flag
+  */
+  int   _outp_data_mean_flag;
+  /**
+  * @brief OGOB_flag
+  */
+  int   _OGOB_flag;
+  /**
+  * @brief PRF_changes
+  */
+  int   _PRF_changes;
+  /**
+  * @brief sampling_win_changes
+  */
+  int   _sampling_win_changes;
+  /**
+  * @brief cal_gain_changes
+  */
+  int   _cal_gain_changes;
+  /**
+  * @brief missing_lines
+  */
+  int   _missing_lines;
+  /**
+  * @brief rec_gain_changes
+  */
+  int   _rec_gain_changes;
+  /**
+  * @brief pulse_width_of_ACF_3db
+  */
+  double   _pulse_width_of_ACF_3db;
+  /**
+  * @brief first_side_lobe_lev_of_ACF
+  */
+  double   _first_side_lobe_lev_of_ACF;
+  /**
+  * @brief ISLR_of_ACF
+  */
+  double   _ISLR_of_ACF;
+  /**
+  * @brief dopp_cent_conf_meas
+  */
+  double   _dopp_cent_conf_meas;
+  /**
+  * @brief dopp_ambig_conf_meas
+  */
+  double   _dopp_ambig_conf_meas;
+  /**
+  * @brief inp_data_I_mean
+  */
+  double   _inp_data_I_mean;
+  /**
+  * @brief inp_data_Q_mean
+  */
+  double   _inp_data_Q_mean;
+  /**
+  * @brief inp_data_I_stddev
+  */
+  double   _inp_data_I_stddev;
+  /**
+  * @brief inp_data_Q_stddev
+  */
+  double   _inp_data_Q_stddev;
+  /**
+  * @brief cal_sys_gain
+  */
+  double   _cal_sys_gain;
+  /**
+  * @brief first_rec_gain_read
+  */
+  double   _first_rec_gain_read;
+  /**
+  * @brief dopp_ambig_num
+  */
+  double   _dopp_ambig_num;
+  /**
+  * @brief I_channel_bias_correction
+  */
+  double   _I_channel_bias_correction;
+  /**
+  * @brief Q_channel_bias_correction
+  */
+  double   _Q_channel_bias_correction;
+  /**
+  * @brief I_channel_gain_correction
+  */
+  double   _I_channel_gain_correction;
+  /**
+  * @brief Q_channel_gain_correction
+  */
+  double   _Q_channel_gain_correction;
+  /**
+  * @brief Q_channel_I_Q_correction
+  */
+  double   _Q_channel_I_Q_correction;
+  /**
+  * @brief noise_power
+  */
+  double   _noise_power;
+  /**
+  * @brief int_cal_utc
+  */
+  int   _int_cal_utc;
+  /**
+  * @brief num_valid_cal_pulses
+  */
+  int   _num_valid_cal_pulses;
+  /**
+  * @brief num_valid_noise_pulses
+  */
+  int   _num_valid_noise_pulses;
+  /**
+  * @brief num_valid_replicas
+  */
+  int   _num_valid_replicas;
+  /**
+  * @brief first_replica_sample
+  */
+  double   _first_replica_sample;
+  /**
+  * @brief mean_cal_pulse_power
+  */
+  double   _mean_cal_pulse_power;
+  /**
+  * @brief mean_noise_power
+  */
+  double   _mean_noise_power;
+  /**
+  * @brief range_comp_norm_fact
+  */
+  double   _range_comp_norm_fact;
+  /**
+  * @brief replica_power
+  */
+  double   _replica_power;
+  /**
+  * @brief first_range_pixel_mid_az_inc
+  */
+  double   _first_range_pixel_mid_az_inc;
+  /**
+  * @brief center_range_pix_mid_az_inc
+  */
+  double   _center_range_pix_mid_az_inc;
+  /**
+  * @brief last_range_pix_mid_az_inc
+  */
+  double   _last_range_pix_mid_az_inc;
+  /**
+  * @brief norm_ref_range_ro
+  */
+  double   _norm_ref_range_ro;
+  /**
+  * @brief antenna_elev_flag
+  */
+  int   _antenna_elev_flag;
+  /**
+  * @brief abs_cal_const_K
+  */
+  double   _abs_cal_const_K;
+  /**
+  * @brief upp_bound_K
+  */
+  double   _upp_bound_K;
+  /**
+  * @brief low_bound_K
+  */
+  double   _low_bound_K;
+  /**
+  * @brief proc_noise_scale_fact
+  */
+  double   _proc_noise_scale_fact;
+  /**
+  * @brief K_gen_date
+  */
+  std::string   _K_gen_date;
+  /**
+  * @brief K_vers_num
+  */
+  std::string   _K_vers_num;
+  /**
+  * @brief num_duplic_input_lines
+  */
+  int   _num_duplic_input_lines;
+  /**
+  * @brief estim_bit_error_rate
+  */
+  double   _estim_bit_error_rate;
+  /**
+  * @brief out_image_mean
+  */
+  double   _out_image_mean;
+  /**
+  * @brief out_image_std_dev
+  */
+  double   _out_image_std_dev;
+  /**
+  * @brief out_image_max_value
+  */
+  double   _out_image_max_value;
+  /**
+  * @brief time_raw_data_first_input
+  */
+  std::string   _time_raw_data_first_input;
+  /**
+  * @brief time_asc_node_state_vectors
+  */
+  std::string   _time_asc_node_state_vectors;
+  /**
+  * @brief asc_node_pos_X_comp
+  */
+  std::string   _asc_node_pos_X_comp;
+  /**
+  * @brief asc_node_pos_Y_comp
+  */
+  std::string   _asc_node_pos_Y_comp;
+  /**
+  * @brief asc_node_pos_Z_comp
+  */
+  std::string   _asc_node_pos_Z_comp;
+  /**
+  * @brief asc_node_vel_X_comp
+  */
+  std::string   _asc_node_vel_X_comp;
+  /**
+  * @brief asc_node_vel_Y_comp
+  */
+  std::string   _asc_node_vel_Y_comp;
+  /**
+  * @brief asc_node_vel_Z_comp
+  */
+  std::string   _asc_node_vel_Z_comp;
+  /**
+  * @brief out_pixel_bit_length
+  */
+  int   _out_pixel_bit_length;
+  /**
+  * @brief proc_gain_param_1
+  */
+  double   _proc_gain_param_1;
+  /**
+  * @brief proc_gain_param_2
+  */
+  double   _proc_gain_param_2;
+  /**
+  * @brief proc_gain_param_3
+  */
+  double   _proc_gain_param_3;
+  /**
+  * @brief peak_loc_cross_correl_fun
+  */
+  int   _peak_loc_cross_correl_fun;
+  /**
+  * @brief 3_dB_width_CCF
+  */
+  double   _3_dB_width_CCF;
+  /**
+  * @brief first_side_lobe_level
+  */
+  double   _first_side_lobe_level;
+  /**
+  * @brief ISLR_CCF_between_last
+  */
+  double   _ISLR_CCF_between_last;
+  /**
+  * @brief peak_loc_CCF_betw_last
+  */
+  int   _peak_loc_CCF_betw_last;
+  /**
+  * @brief Roll_Tilt_Mode_flag
+  */
+  int   _Roll_Tilt_Mode_flag;
+  /**
+  * @brief raw_data_correction_flag
+  */
+  int   _raw_data_correction_flag;
+  /**
+  * @brief look_detecion_flag
+  */
+  int   _look_detecion_flag;
+  /**
+  * @brief doppler_ambiguity_estimat_flag
+  */
+  int   _doppler_ambiguity_estimat_flag;
+  /**
+  * @brief azimuth_baseband_convers_flag
+  */
+  int   _azimuth_baseband_convers_flag;
+  /**
+  * @brief samples_per_line_used
+  */
+  int   _samples_per_line_used;
+  /**
+  * @brief range_lines_skip_factor
+  */
+  int   _range_lines_skip_factor;
+  /**
+  * @brief time_of_inp_state_vectors
+  */
+  std::string   _time_of_inp_state_vectors;
+  /**
+  * @brief inp_state_vect_pos_X_comp
+  */
+  std::string   _inp_state_vect_pos_X_comp;
+  /**
+  * @brief inp_state_vect_pos_Y_comp
+  */
+  std::string   _inp_state_vect_pos_Y_comp;
+  /**
+  * @brief inp_state_vect_pos_Z_comp
+  */
+  std::string   _inp_state_vect_pos_Z_comp;
+  /**
+  * @brief inp_state_vect_vel_Vx_comp
+  */
+  std::string   _inp_state_vect_vel_Vx_comp;
+  /**
+  * @brief inp_state_vect_vel_Vy_comp
+  */
+  std::string   _inp_state_vect_vel_Vy_comp;
+  /**
+  * @brief inp_state_vect_vel_Vz_comp
+  */
+  std::string   _inp_state_vect_vel_Vz_comp;
+  /**
+  * @brief inp_state_vector_type_flag
+  */
+  int   _inp_state_vector_type_flag;
+  /**
+  * @brief win_coeff_for_range_match
+  */
+  double   _win_coeff_for_range_match;
+  /**
+  * @brief win_coeff_for_azi_match
+  */
+  double   _win_coeff_for_azi_match;
+  /**
+  * @brief update_period_range_match
+  */
+  int   _update_period_range_match;
+  /**
+  * @brief look_scalar_gain_1
+  */
+  double   _look_scalar_gain_1;
+  /**
+  * @brief look_scalar_gain_2
+  */
+  double   _look_scalar_gain_2;
+  /**
+  * @brief look_scalar_gain_3
+  */
+  double   _look_scalar_gain_3;
+  /**
+  * @brief look_scalar_gain_4
+  */
+  double   _look_scalar_gain_4;
+  /**
+  * @brief look_scalar_gain_5
+  */
+  double   _look_scalar_gain_5;
+  /**
+  * @brief look_scalar_gain_6
+  */
+  double   _look_scalar_gain_6;
+  /**
+  * @brief look_scalar_gain_7
+  */
+  double   _look_scalar_gain_7;
+  /**
+  * @brief look_scalar_gain_8
+  */
+  double   _look_scalar_gain_8;
+  /**
+  * @brief samp_window_start_time_bias
+  */
+  int   _samp_window_start_time_bias;
+  /**
+  * @brief doppler_centroid_cubic_coeff
+  */
+  double   _doppler_centroid_cubic_coeff;
+  /**
+  * @brief PRF_code_first_range_line
+  */
+  int   _PRF_code_first_range_line;
+  /**
+  * @brief PRF_code_last_range_line
+  */
+  int   _PRF_code_last_range_line;
+  /**
+  * @brief samp_win_start_first
+  */
+  int   _samp_win_start_first;
+  /**
+  * @brief samp_win_start_last
+  */
+  int   _samp_win_start_last;
+  /**
+  * @brief cal_syst_gain_last_proc
+  */
+  int   _cal_syst_gain_last_proc;
+  /**
+  * @brief receiver_gain_last_proc
+  */
+  int   _receiver_gain_last_proc;
+  /**
+  * @brief first_processed_range_sample
+  */
+  int   _first_processed_range_sample;
+  /**
+  * @brief azimuth_FFT_IFFT_ratio
+  */
+  int   _azimuth_FFT_IFFT_ratio;
+  /**
+  * @brief num_azimuth_blocks_proc
+  */
+  int   _num_azimuth_blocks_proc;
+  /**
+  * @brief num_input_raw_data_lines
+  */
+  int   _num_input_raw_data_lines;
+  /**
+  * @brief initial_doppler_ambiguity_num
+  */
+  int   _initial_doppler_ambiguity_num;
+  /**
+  * @brief thresh_no_1_flag
+  */
+  double   _thresh_no_1_flag;
+  /**
+  * @brief thresh_no_2_flag
+  */
+  double   _thresh_no_2_flag;
+  /**
+  * @brief thresh_no_3_flag
+  */
+  double   _thresh_no_3_flag;
+  /**
+  * @brief thresh_no_4_flag
+  */
+  double   _thresh_no_4_flag;
+  /**
+  * @brief thresh_no_5_flag
+  */
+  double   _thresh_no_5_flag;
+  /**
+  * @brief thresh_no_6_flag
+  */
+  double   _thresh_no_6_flag;
+  /**
+  * @brief thresh_no_7_flag
+  */
+  double   _thresh_no_7_flag;
+  /**
+  * @brief thresh_no_8_flag
+  */
+  double   _thresh_no_8_flag;
+  /**
+  * @brief thresh_no_9_flag
+  */
+  double   _thresh_no_9_flag;
+  /**
+  * @brief thresh_no_10_flag
+  */
+  double   _thresh_no_10_flag;
+  /**
+  * @brief thresh_no_11_flag
+  */
+  double   _thresh_no_11_flag;
+  /**
+  * @brief sat_binary_time_of_first
+  */
+  int   _sat_binary_time_of_first;
+  /**
+  * @brief num_valid_pixels_per_range
+  */
+  int   _num_valid_pixels_per_range;
+  /**
+  * @brief num_range_samp_discarded
+  */
+  int   _num_range_samp_discarded;
+  /**
+  * @brief I_gain_imb_lower_bound
+  */
+  double   _I_gain_imb_lower_bound;
+  /**
+  * @brief I_gain_imb_upper_bound
+  */
+  double   _I_gain_imb_upper_bound;
+  /**
+  * @brief I_Q_quad_depar_lower_bound
+  */
+  double   _I_Q_quad_depar_lower_bound;
+  /**
+  * @brief I_Q_quad_depar_upper_bound
+  */
+  double   _I_Q_quad_depar_upper_bound;
+  /**
+  * @brief 3_dB_look_bandwidth
+  */
+  double   _3_dB_look_bandwidth;
+  /**
+  * @brief 3_dB_look_proc_dopp_bandw
+  */
+  double   _3_dB_look_proc_dopp_bandw;
+  /**
+  * @brief range_spread_loss_comp_flag
+  */
+  int   _range_spread_loss_comp_flag;
+  /**
+  * @brief datation_flag
+  */
+  bool   _datation_flag;
+  /**
+  * @brief max_error_range_line_timing
+  */
+  int   _max_error_range_line_timing;
+  /**
+  * @brief form_num_range_line_used
+  */
+  int   _form_num_range_line_used;
+  /**
+  * @brief autom_look_scal_gain_flag
+  */
+  bool   _autom_look_scal_gain_flag;
+  /**
+  * @brief max_value_look_scalar_gain
+  */
+  int   _max_value_look_scalar_gain;
+  /**
+  * @brief replica_norm_method_flag
+  */
+  int   _replica_norm_method_flag;
+  /**
+  * @brief coef_ground_range_1
+  */
+  double   _coef_ground_range_1;
+  /**
+  * @brief coef_ground_range_2
+  */
+  double   _coef_ground_range_2;
+  /**
+  * @brief coef_ground_range_3
+  */
+  double   _coef_ground_range_3;
+  /**
+  * @brief coef_ground_range_4
+  */
+  double   _coef_ground_range_4;
+  /**
+  * @brief coef_ant_elev_1
+  */
+  double   _coef_ant_elev_1;
+  /**
+  * @brief coef_ant_elev_2
+  */
+  double   _coef_ant_elev_2;
+  /**
+  * @brief coef_ant_elev_3
+  */
+  double   _coef_ant_elev_3;
+  /**
+  * @brief coef_ant_elev_4
+  */
+  double   _coef_ant_elev_4;
+  /**
+  * @brief coef_ant_elev_5
+  */
+  double   _coef_ant_elev_5;
+  /**
+  * @brief range_time_origin_ant
+  */
+  double   _range_time_origin_ant;
+
+private:
+
+};
+}
+#endif
+
diff --git a/ossim_plugins/ossim/AlosPalsar/AlosPalsarFileDescriptor.cpp b/ossim_plugins/ossim/AlosPalsar/AlosPalsarFileDescriptor.cpp
new file mode 100644
index 0000000..e9319ab
--- /dev/null
+++ b/ossim_plugins/ossim/AlosPalsar/AlosPalsarFileDescriptor.cpp
@@ -0,0 +1,445 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+// "Copyright Centre for Remote Imaging, Sensing and Processing"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include <AlosPalsar/AlosPalsarFileDescriptor.h>
+
+
+namespace ossimplugins
+{
+
+AlosPalsarFileDescriptor::AlosPalsarFileDescriptor() : AlosPalsarRecord("sar_desc_rec")
+{
+}
+
+AlosPalsarFileDescriptor::~AlosPalsarFileDescriptor()
+{
+}
+
+std::ostream& operator<<(std::ostream& os, const AlosPalsarFileDescriptor& data)
+{
+  os << "ascii_flag:" << data._ascii_flag.c_str() << std::endl;
+  os << "continuation_flag:" << data._continuation_flag.c_str() << std::endl;
+  os << "format_doc:" << data._format_doc.c_str() << std::endl;
+  os << "format_ver:" << data._format_ver.c_str() << std::endl;
+  os << "design_rev:" << data._design_rev.c_str() << std::endl;
+  os << "software_id:" << data._software_id.c_str() << std::endl;
+  os << "file_num:" << data._file_num << std::endl;
+  os << "file_name:" << data._file_name.c_str() << std::endl;
+  os << "rec_seq:" << data._rec_seq.c_str() << std::endl;
+  os << "seq_loc:" << data._seq_loc << std::endl;
+  os << "seq_len:" << data._seq_len << std::endl;
+  os << "rec_code:" << data._rec_code.c_str() << std::endl;
+  os << "code_loc:" << data._code_loc << std::endl;
+  os << "code_len:" << data._code_len << std::endl;
+  os << "rec_len:" << data._rec_len.c_str() << std::endl;
+  os << "rlen_loc:" << data._rlen_loc << std::endl;
+  os << "rlen_len:" << data._rlen_len << std::endl;
+  os << "n_dataset:" << data._n_dataset << std::endl;
+  os << "l_dataset:" << data._l_dataset << std::endl;
+  os << "n_map_proj:" << data._n_map_proj << std::endl;
+  os << "l_map_proj:" << data._l_map_proj << std::endl;
+  os << "n_plat_pos:" << data._n_plat_pos << std::endl;
+  os << "l_plat_pos:" << data._l_plat_pos << std::endl;
+  os << "n_att_data:" << data._n_att_data << std::endl;
+  os << "l_att_data:" << data._l_att_data << std::endl;
+  os << "n_radi_data:" << data._n_radi_data << std::endl;
+  os << "l_radi_data:" << data._l_radi_data << std::endl;
+  os << "n_radi_comp:" << data._n_radi_comp << std::endl;
+  os << "l_radi_comp:" << data._l_radi_comp << std::endl;
+  os << "n_qual_sum:" << data._n_qual_sum << std::endl;
+  os << "l_qual_sum:" << data._l_qual_sum << std::endl;
+  os << "n_data_his:" << data._n_data_his << std::endl;
+  os << "l_data_his:" << data._l_data_his << std::endl;
+  os << "n_rang_spec:" << data._n_rang_spec << std::endl;
+  os << "l_rang_spec:" << data._l_rang_spec << std::endl;
+  os << "n_dem_desc:" << data._n_dem_desc << std::endl;
+  os << "l_dem_desc:" << data._l_dem_desc << std::endl;
+  os << "n_radar_par:" << data._n_radar_par << std::endl;
+  os << "l_radar_par:" << data._l_radar_par << std::endl;
+  os << "n_anno_data:" << data._n_anno_data << std::endl;
+  os << "l_anno_data:" << data._l_anno_data << std::endl;
+  os << "n_det_proc:" << data._n_det_proc << std::endl;
+  os << "l_det_proc:" << data._l_det_proc << std::endl;
+  os << "n_cal:" << data._n_cal << std::endl;
+  os << "l_cal:" << data._l_cal << std::endl;
+  os << "n_gcp:" << data._n_gcp << std::endl;
+  os << "l_gcp:" << data._l_gcp << std::endl;
+  os << "n_fac_data:" << data._n_fac_data << std::endl;
+  os << "l_fac_data:" << data._l_fac_data << std::endl;
+  os << "n_fac_data2:" << data._n_fac_data2 << std::endl;
+  os << "l_fac_data2:" << data._l_fac_data2 << std::endl;
+  os << "n_fac_data3:" << data._n_fac_data3 << std::endl;
+  os << "l_fac_data3:" << data._l_fac_data3 << std::endl;
+  os << "n_fac_data4:" << data._n_fac_data4 << std::endl;
+  os << "l_fac_data4:" << data._l_fac_data4 << std::endl;
+  os << "n_fac_data5:" << data._n_fac_data5 << std::endl;
+  os << "l_fac_data5:" << data._l_fac_data5 << std::endl;
+  os << "n_fac_data6:" << data._n_fac_data6 << std::endl;
+  os << "l_fac_data6:" << data._l_fac_data6 << std::endl;
+  os << "n_fac_data7:" << data._n_fac_data7 << std::endl;
+  os << "l_fac_data7:" << data._l_fac_data7 << std::endl;
+  os << "n_fac_data8:" << data._n_fac_data8 << std::endl;
+  os << "l_fac_data8:" << data._l_fac_data8 << std::endl;
+  os << "n_fac_data9:" << data._n_fac_data9 << std::endl;
+  os << "l_fac_data9:" << data._l_fac_data9 << std::endl;
+  os << "n_fac_data10:" << data._n_fac_data10 << std::endl;
+  os << "l_fac_data10:" << data._l_fac_data10 << std::endl;
+  os << "n_fac_data11:" << data._n_fac_data11 << std::endl;
+  os << "l_fac_data11:" << data._l_fac_data11 << std::endl;
+  return os;
+}
+
+std::istream& operator>>(std::istream& is, AlosPalsarFileDescriptor& data)
+{
+  char buf2[3];
+  buf2[2] = '\0';
+  char buf12[13];
+  buf12[12] = '\0';
+  char buf16[17];
+  buf16[16] = '\0';
+  char buf4[5];
+  buf4[4] = '\0';
+  char buf6[7];
+  buf6[6] = '\0';
+  char buf8[9];
+  buf8[8] = '\0';
+  char buf64[65];
+  buf64[64] = '\0';
+
+  char buf60[61];
+  buf60[60] = '\0';
+
+  char buf146[147];
+  buf146[146] = '\0';
+
+  is.read(buf2, 2);
+  data._ascii_flag = buf2;
+
+  is.read(buf2, 2);
+  data._continuation_flag = buf2;
+
+  is.read(buf12, 12);
+  data._format_doc = buf12;
+
+  is.read(buf2, 2);
+  data._format_ver = buf2;
+
+  is.read(buf2, 2);
+  data._design_rev = buf2;
+
+  is.read(buf12, 12);
+  data._software_id = buf12;
+
+  is.read(buf4, 4);
+  data._file_num = atoi(buf4);
+
+  is.read(buf16, 16);
+  data._file_name = buf16;
+
+  is.read(buf4, 4);
+  data._rec_seq = buf4;
+
+  is.read(buf8, 8);
+  data._seq_loc = atoi(buf8);
+
+  is.read(buf4, 4);
+  data._seq_len = atoi(buf4);
+
+  is.read(buf4, 4);
+  data._rec_code = buf4;
+
+  is.read(buf8, 8);
+  data._code_loc = atoi(buf8);
+
+  is.read(buf4, 4);
+  data._code_len = atoi(buf4);
+
+  is.read(buf4, 4);
+  data._rec_len = buf4;
+
+  is.read(buf8, 8);
+  data._rlen_loc = atoi(buf8);
+
+  is.read(buf4, 4);
+  data._rlen_len = atoi(buf4);
+
+  is.read(buf4, 4);
+
+  is.read(buf64, 64);
+
+  is.read(buf6, 6);
+  data._n_dataset = atoi(buf6);
+
+  is.read(buf6, 6);
+  data._l_dataset = atoi(buf6);
+
+  is.read(buf6, 6);
+  data._n_map_proj = atoi(buf6);
+
+  is.read(buf6, 6);
+  data._l_map_proj = atoi(buf6);
+
+  is.read(buf6, 6);
+  data._n_plat_pos = atoi(buf6);
+  is.read(buf6, 6);
+  data._l_plat_pos = atoi(buf6);
+  is.read(buf6, 6);
+  data._n_att_data = atoi(buf6);
+  is.read(buf6, 6);
+  data._l_att_data = atoi(buf6);
+  is.read(buf6, 6);
+  data._n_radi_data = atoi(buf6);
+  is.read(buf6, 6);
+  data._l_radi_data = atoi(buf6);
+  is.read(buf6, 6);
+  data._n_radi_comp = atoi(buf6);
+  is.read(buf6, 6);
+  data._l_radi_comp = atoi(buf6);
+  is.read(buf6, 6);
+  data._n_qual_sum = atoi(buf6);
+  is.read(buf6, 6);
+  data._l_qual_sum = atoi(buf6);
+  is.read(buf6, 6);
+  data._n_data_his = atoi(buf6);
+  is.read(buf6, 6);
+  data._l_data_his = atoi(buf6);
+
+
+
+  is.read(buf6, 6);
+  data._n_rang_spec = atoi(buf6);
+  is.read(buf6, 6);
+  data._l_rang_spec = atoi(buf6);
+  is.read(buf6, 6);
+  data._n_dem_desc = atoi(buf6);
+  is.read(buf6, 6);
+  data._l_dem_desc = atoi(buf6);
+  is.read(buf6, 6);
+  data._n_radar_par = atoi(buf6);
+  is.read(buf6, 6);
+  data._l_radar_par = atoi(buf6);
+  is.read(buf6, 6);
+  data._n_anno_data = atoi(buf6);
+  is.read(buf6, 6);
+  data._l_anno_data = atoi(buf6);
+  is.read(buf6, 6);
+  data._n_det_proc = atoi(buf6);
+  is.read(buf6, 6);
+  data._l_det_proc = atoi(buf6);
+  is.read(buf6, 6);
+  data._n_cal = atoi(buf6);
+  is.read(buf6, 6);
+  data._l_cal = atoi(buf6);
+  is.read(buf6, 6);
+  data._n_gcp = atoi(buf6);
+  is.read(buf6, 6);
+  data._l_gcp = atoi(buf6);
+  is.read(buf60, 60);
+  is.read(buf6, 6);
+  data._n_fac_data = atoi(buf6);
+  is.read(buf8, 8);
+  data._l_fac_data = atoi(buf8);
+  is.read(buf6, 6);
+  data._n_fac_data2 = atoi(buf6);
+  is.read(buf8, 8);
+  data._l_fac_data2 = atoi(buf8);
+  is.read(buf6, 6);
+  data._n_fac_data3 = atoi(buf6);
+  is.read(buf8, 8);
+  data._l_fac_data3 = atoi(buf8);
+  is.read(buf6, 6);
+  data._n_fac_data4 = atoi(buf6);
+  is.read(buf8, 8);
+  data._l_fac_data4 = atoi(buf8);
+  is.read(buf6, 6);
+  data._n_fac_data5 = atoi(buf6);
+  is.read(buf8, 8);
+  data._l_fac_data5 = atoi(buf8);
+  is.read(buf6, 6);
+  data._n_fac_data6 = atoi(buf6);
+  is.read(buf8, 8);
+  data._l_fac_data6 = atoi(buf8);
+  is.read(buf6, 6);
+  data._n_fac_data7 = atoi(buf6);
+  is.read(buf8, 8);
+  data._l_fac_data7 = atoi(buf8);
+  is.read(buf6, 6);
+  data._n_fac_data8 = atoi(buf6);
+  is.read(buf8, 8);
+  data._l_fac_data8 = atoi(buf8);
+  is.read(buf6, 6);
+  data._n_fac_data9 = atoi(buf6);
+  is.read(buf8, 8);
+  data._l_fac_data9 = atoi(buf8);
+  is.read(buf6, 6);
+  data._n_fac_data10 = atoi(buf6);
+  is.read(buf8, 8);
+  data._l_fac_data10 = atoi(buf8);
+  is.read(buf6, 6);
+  data._n_fac_data11 = atoi(buf6);
+  is.read(buf8, 8);
+  data._l_fac_data11 = atoi(buf8);
+
+  is.read(buf146, 146);
+  return is;
+}
+
+AlosPalsarFileDescriptor::AlosPalsarFileDescriptor(const AlosPalsarFileDescriptor& rhs):
+    AlosPalsarRecord(rhs),
+    _ascii_flag(rhs._ascii_flag),
+    _continuation_flag(rhs._continuation_flag),
+    _format_doc(rhs._format_doc),
+    _format_ver(rhs._format_ver),
+    _design_rev(rhs._design_rev),
+    _software_id(rhs._software_id),
+    _file_num(rhs._file_num),
+    _file_name(rhs._file_name),
+    _rec_seq(rhs._rec_seq),
+    _seq_loc(rhs._seq_loc),
+    _seq_len(rhs._seq_len),
+    _rec_code(rhs._rec_code),
+    _code_loc(rhs._code_loc),
+    _code_len(rhs._code_len),
+    _rec_len(rhs._rec_len),
+    _rlen_loc(rhs._rlen_loc),
+    _rlen_len(rhs._rlen_len),
+    _n_dataset(rhs._n_dataset),
+    _l_dataset(rhs._l_dataset),
+    _n_map_proj(rhs._n_map_proj),
+    _l_map_proj(rhs._l_map_proj),
+    _n_plat_pos(rhs._n_plat_pos),
+    _l_plat_pos(rhs._l_plat_pos),
+    _n_att_data(rhs._n_att_data),
+    _l_att_data(rhs._l_att_data),
+    _n_radi_data(rhs._n_radi_data),
+    _l_radi_data(rhs._l_radi_data),
+    _n_radi_comp(rhs._n_radi_comp),
+    _l_radi_comp(rhs._l_radi_comp),
+    _n_qual_sum(rhs._n_qual_sum),
+    _l_qual_sum(rhs._l_qual_sum),
+    _n_data_his(rhs._n_data_his),
+    _l_data_his(rhs._l_data_his),
+    _n_rang_spec(rhs._n_rang_spec),
+    _l_rang_spec(rhs._l_rang_spec),
+    _n_dem_desc(rhs._n_dem_desc),
+    _l_dem_desc(rhs._l_dem_desc),
+    _n_radar_par(rhs._n_radar_par),
+    _l_radar_par(rhs._l_radar_par),
+    _n_anno_data(rhs._n_anno_data),
+    _l_anno_data(rhs._l_anno_data),
+    _n_det_proc(rhs._n_det_proc),
+    _l_det_proc(rhs._l_det_proc),
+    _n_cal(rhs._n_cal),
+    _l_cal(rhs._l_cal),
+    _n_gcp(rhs._n_gcp),
+    _l_gcp(rhs._l_gcp),
+    _n_fac_data(rhs._n_fac_data),
+    _l_fac_data(rhs._l_fac_data),
+    _n_fac_data2(rhs._n_fac_data2),
+    _l_fac_data2(rhs._l_fac_data2),
+    _n_fac_data3(rhs._n_fac_data3),
+    _l_fac_data3(rhs._l_fac_data3),
+    _n_fac_data4(rhs._n_fac_data4),
+    _l_fac_data4(rhs._l_fac_data4),
+    _n_fac_data5(rhs._n_fac_data5),
+    _l_fac_data5(rhs._l_fac_data5),
+    _n_fac_data6(rhs._n_fac_data6),
+    _l_fac_data6(rhs._l_fac_data6),
+    _n_fac_data7(rhs._n_fac_data7),
+    _l_fac_data7(rhs._l_fac_data7),
+    _n_fac_data8(rhs._n_fac_data8),
+    _l_fac_data8(rhs._l_fac_data8),
+    _n_fac_data9(rhs._n_fac_data9),
+    _l_fac_data9(rhs._l_fac_data9),
+    _n_fac_data10(rhs._n_fac_data10),
+    _l_fac_data10(rhs._l_fac_data10),
+    _n_fac_data11(rhs._n_fac_data11),
+    _l_fac_data11(rhs._l_fac_data11)
+
+{
+}
+
+AlosPalsarFileDescriptor& AlosPalsarFileDescriptor::operator=(const AlosPalsarFileDescriptor& rhs)
+{
+  _ascii_flag = rhs._ascii_flag;
+  _continuation_flag = rhs._continuation_flag;
+  _format_doc = rhs._format_doc;
+  _format_ver = rhs._format_ver;
+  _design_rev = rhs._design_rev;
+  _software_id = rhs._software_id;
+  _file_num = rhs._file_num;
+  _file_name = rhs._file_name;
+  _rec_seq = rhs._rec_seq;
+  _seq_loc = rhs._seq_loc;
+  _seq_len = rhs._seq_len;
+  _rec_code = rhs._rec_code;
+  _code_loc = rhs._code_loc;
+  _code_len = rhs._code_len;
+  _rec_len = rhs._rec_len;
+  _rlen_loc = rhs._rlen_loc;
+  _rlen_len = rhs._rlen_len;
+  _n_dataset = rhs._n_dataset;
+  _l_dataset = rhs._l_dataset;
+  _n_map_proj = rhs._n_map_proj;
+  _l_map_proj = rhs._l_map_proj;
+  _n_plat_pos = rhs._n_plat_pos;
+  _l_plat_pos = rhs._l_plat_pos;
+  _n_att_data = rhs._n_att_data;
+  _l_att_data = rhs._l_att_data;
+  _n_radi_data = rhs._n_radi_data;
+  _l_radi_data = rhs._l_radi_data;
+  _n_radi_comp = rhs._n_radi_comp;
+  _l_radi_comp = rhs._l_radi_comp;
+  _n_qual_sum = rhs._n_qual_sum ;
+  _l_qual_sum = rhs._l_qual_sum;
+  _n_data_his = rhs._n_data_his;
+  _l_data_his = rhs._l_data_his;
+  _n_rang_spec = rhs._n_rang_spec;
+  _l_rang_spec = rhs._l_rang_spec;
+  _n_dem_desc = rhs._n_dem_desc;
+  _l_dem_desc = rhs._l_dem_desc;
+  _n_radar_par = rhs._n_radar_par;
+  _l_radar_par = rhs._l_radar_par;
+  _n_anno_data = rhs._n_anno_data;
+  _l_anno_data = rhs._l_anno_data;
+  _n_det_proc = rhs._n_det_proc;
+  _l_det_proc = rhs._l_det_proc;
+  _n_cal = rhs._n_cal;
+  _l_cal = rhs._l_cal;
+  _n_gcp = rhs._n_gcp;
+  _l_gcp = rhs._l_gcp;
+  _n_fac_data = rhs._n_fac_data;
+  _l_fac_data = rhs._l_fac_data;
+  _n_fac_data2 = rhs._n_fac_data2;
+  _l_fac_data2 = rhs._l_fac_data2;
+  _n_fac_data3 = rhs._n_fac_data3;
+  _l_fac_data3 = rhs._l_fac_data3;
+  _n_fac_data4 = rhs._n_fac_data4;
+  _l_fac_data4 = rhs._l_fac_data4;
+  _n_fac_data5 = rhs._n_fac_data5;
+  _l_fac_data5 = rhs._l_fac_data5;
+  _n_fac_data6 = rhs._n_fac_data6;
+  _l_fac_data6 = rhs._l_fac_data6;
+  _n_fac_data7 = rhs._n_fac_data7;
+  _l_fac_data7 = rhs._l_fac_data7;
+  _n_fac_data8 = rhs._n_fac_data8;
+  _l_fac_data8 = rhs._l_fac_data8;
+  _n_fac_data9 = rhs._n_fac_data9;
+  _l_fac_data9 = rhs._l_fac_data9;
+  _n_fac_data10 = rhs._n_fac_data10;
+  _l_fac_data10 = rhs._l_fac_data10;
+  _n_fac_data11 = rhs._n_fac_data11;
+  _l_fac_data11 = rhs._l_fac_data11;
+  return *this;
+}
+}
+
diff --git a/ossim_plugins/ossim/AlosPalsar/AlosPalsarFileDescriptor.h b/ossim_plugins/ossim/AlosPalsar/AlosPalsarFileDescriptor.h
new file mode 100644
index 0000000..8ee3c99
--- /dev/null
+++ b/ossim_plugins/ossim/AlosPalsar/AlosPalsarFileDescriptor.h
@@ -0,0 +1,879 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+// "Copyright Centre for Remote Imaging, Sensing and Processing"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef AlosPalsarFileDescriptor_h
+#define AlosPalsarFileDescriptor_h
+
+// TODO Rename to AlosPalsarLeaderFileDescriptor
+
+#include<iostream>
+#include <cstdlib>
+#include <AlosPalsar/AlosPalsarRecordHeader.h>
+#include <AlosPalsar/AlosPalsarRecord.h>
+
+namespace ossimplugins
+{
+
+/**
+ * @ingroup SARLeaderAlosPalsarFileDescriptorRecord
+ * @brief This class is able to read the SAR leader file descriptor record of the leader file
+ */
+class AlosPalsarFileDescriptor : public AlosPalsarRecord
+{
+public:
+  /**
+   * @brief Constructor
+   */
+  AlosPalsarFileDescriptor();
+  /**
+   * @brief Destructor
+   */
+  virtual ~AlosPalsarFileDescriptor();
+
+  /**
+   * @brief This function write the AlosPalsarFileDescriptor in a stream
+   */
+  friend std::ostream& operator<<(std::ostream& os, const AlosPalsarFileDescriptor& data);
+
+  /**
+   * @brief This function read a AlosPalsarFileDescriptor from a stream
+   */
+  friend std::istream& operator>>(std::istream& is, AlosPalsarFileDescriptor& data);
+
+  /**
+   * @brief Copy constructor
+   */
+  AlosPalsarFileDescriptor(const AlosPalsarFileDescriptor& rhs);
+
+  /**
+   * @brief Copy operator
+   */
+  AlosPalsarFileDescriptor& operator=(const AlosPalsarFileDescriptor& rhs);
+
+  /**
+   * @brief This function is able to create a new instance of the class
+   */
+  AlosPalsarRecord* Instanciate()
+  {
+    return new AlosPalsarFileDescriptor();
+  };
+
+  /**
+   * @brief This function is able to create a new instance of the class initialised with the data of the calling instance
+   */
+  AlosPalsarRecord* Clone()
+  {
+    return new AlosPalsarFileDescriptor(*this);
+  };
+
+  /**
+   * @brief Read the class data from a stream
+   */
+  void Read(std::istream& is)
+  {
+    is >> *this;
+  };
+
+  /**
+   * @brief Write the class to a stream
+   */
+  void Write(std::ostream& os)
+  {
+    os << *this;
+  };
+
+  /**
+   * @brief ASCII flag
+   */
+  std::string get_ascii_flag() const
+  {
+    return _ascii_flag;
+  };
+
+  /**
+   * @brief Continuation flag
+   */
+  std::string get_continuation_flag() const
+  {
+    return _continuation_flag;
+  };
+
+
+  /**
+   * @brief Format control documentation
+   */
+  std::string get_format_doc() const
+  {
+    return _format_doc;
+  };
+  /**
+   * @brief Format doc version
+   */
+  std::string   get_format_ver() const
+  {
+    return _format_ver;
+  };
+  /**
+   * @brief Format doc revision
+   */
+  std::string   get_design_rev() const
+  {
+    return _design_rev;
+  };
+  /**
+   * @brief Software identifier
+   */
+  std::string   get_software_id() const
+  {
+    return _software_id;
+  };
+  /**
+   * @brief File number
+   */
+  int   get_file_num() const
+  {
+    return _file_num ;
+  };
+  /**
+   * @brief File name
+   */
+  std::string   get_file_name() const
+  {
+    return _file_name;
+  };
+  /**
+   * @brief Record sequence/location flag
+   */
+  std::string   get_rec_seq() const
+  {
+    return _rec_seq;
+  };
+  /**
+   * @brief Sequence number location
+   */
+  int   get_seq_loc() const
+  {
+    return _seq_loc;
+  };
+  /**
+   * @brief Sequence number lenght
+   */
+  int   get_seq_len() const
+  {
+    return _seq_len;
+  };
+  /**
+   * @brief Record code/location flag
+   */
+  std::string   get_rec_code() const
+  {
+    return _rec_code;
+  };
+  /**
+   * @brief Record code location
+   */
+  int   get_code_loc() const
+  {
+    return _code_loc;
+  };
+  /**
+   * @brief Record code length
+   */
+  int   get_code_len() const
+  {
+    return _code_len;
+  };
+  /**
+   * @brief Record length/location flag
+   */
+  std::string get_rec_len() const
+  {
+    return _rec_len;
+  };
+  /**
+   * @brief Record lenght location
+   */
+  int get_rlen_loc() const
+  {
+    return _rlen_loc;
+  };
+  /**
+   * @brief Record length, bytes
+   */
+  int get_rlen_len() const
+  {
+    return _rlen_len;
+  };
+  /**
+   * @brief Number of dataset summ records
+   */
+  int get_n_dataset() const
+  {
+    return _n_dataset;
+  };
+  /**
+   * @brief Data set summary record length, bytes
+   */
+  int get_l_dataset() const
+  {
+    return _l_dataset;
+  };
+  /**
+   * @brief Number of map proj records
+   */
+  int get_n_map_proj() const
+  {
+    return _n_map_proj;
+  };
+  /**
+   * @brief Map projection record length, bytes
+   */
+  int get_l_map_proj() const
+  {
+    return _l_map_proj;
+  };
+  /**
+   * @brief Number of platform position records
+   */
+  int get_n_plat_pos() const
+  {
+    return _n_plat_pos;
+  };
+  /**
+   * @brief Platform position record length, bytes
+   */
+  int get_l_plat_pos() const
+  {
+    return _l_plat_pos;
+  };
+  /**
+   * @brief Number of attitude data records
+   */
+  int get_n_att_data() const
+  {
+    return _n_att_data;
+  };
+  /**
+   * @brief Attitude data record length, bytes
+   */
+  int get_l_att_data() const
+  {
+    return _l_att_data;
+  };
+  /**
+   * @brief Number of radiometric data records
+   */
+  int get_n_radi_data() const
+  {
+    return _n_radi_data;
+  };
+  /**
+   * @brief Radiometric data record length, bytes
+   */
+  int get_l_radi_data() const
+  {
+    return _l_radi_data;
+  };
+  /**
+   * @brief Number of radiometric compensation records
+   */
+  int get_n_radi_comp() const
+  {
+    return _n_radi_comp;
+  };
+  /**
+   *  @brief Radiometric compensation record length, bytes
+   */
+  int get_l_radi_comp() const
+  {
+    return _l_radi_comp;
+  };
+  /**
+   * @brief Number of data quality summary records
+   */
+  int get_n_qual_sum() const
+  {
+    return _n_qual_sum;
+  };
+  /**
+   * @brief Data quality summary record length, bytes
+   */
+  int get_l_qual_sum() const
+  {
+    return _l_qual_sum;
+  };
+  /**
+   * @brief Number of data histogram records
+   */
+  int get_n_data_his() const
+  {
+    return _n_data_his;
+  };
+  /**
+   * @brief Data histogram record length, bytes
+   */
+  int get_l_data_his() const
+  {
+    return _l_data_his;
+  };
+  /**
+   * @brief Number of range spectra records
+   */
+  int get_n_rang_spec() const
+  {
+    return _n_rang_spec ;
+  };
+  /**
+   * @brief Range spectra record length, bytes
+   */
+  int get_l_rang_spec() const
+  {
+    return _l_rang_spec;
+  };
+  /**
+   * @brief Number of DEM descriptor records
+   */
+  int get_n_dem_desc() const
+  {
+    return _n_dem_desc;
+  };
+  /**
+   * @brief DEM desc record length, bytes
+   */
+  int get_l_dem_desc() const
+  {
+    return _l_dem_desc;
+  };
+  /**
+   * @brief Number of RADAR par records
+   */
+  int get_n_radar_par() const
+  {
+    return _n_radar_par;
+  };
+  /**
+   * @brief RADAR par record length, bytes
+   */
+  int get_l_radar_par() const
+  {
+    return _l_radar_par;
+  };
+  /**
+   * @brief Number of annotation data records
+   */
+  int get_n_anno_data() const
+  {
+    return _n_anno_data;
+  };
+  /**
+   * @brief Annotation data record length, bytes
+   */
+  int get_l_anno_data() const
+  {
+    return _l_anno_data;
+  };
+  /**
+   * @brief Number of processing parameter records
+   */
+  int get_n_det_proc() const
+  {
+    return _n_det_proc;
+  };
+  /**
+   * @brief Processing parameter record length, bytes
+   */
+  int get_l_det_proc() const
+  {
+    return _l_det_proc;
+  };
+  /**
+   * @brief Number of calibration records
+   */
+  int get_n_cal() const
+  {
+    return _n_cal;
+  };
+  /**
+   * @brief Calibration record length, bytes
+   */
+  int get_l_cal() const
+  {
+    return _l_cal;
+  };
+  /**
+   * @brief Number of GCP records
+   */
+  int get_n_gcp() const
+  {
+    return _n_gcp;
+  };
+  /**
+   * @brief GCP record length, bytes
+   */
+  int get_l_gcp() const
+  {
+    return _l_gcp;
+  };
+  /**
+   * @brief Number of facility data records
+   */
+  int get_n_fac_data() const
+  {
+    return _n_fac_data;
+  };
+  /**
+   * @brief Fac data record length, bytes
+   */
+  int get_l_fac_data() const
+  {
+    return _l_fac_data;
+  };
+
+  /**
+   * @brief Number of facility data records
+   */
+  int get_n_fac_data2()
+  {
+    return _n_fac_data;
+  };
+  /**
+   * @brief Fac data record length, bytes
+   */
+  int get_l_fac_data2()
+  {
+    return _l_fac_data;
+  };
+  /**
+   * @brief Number of facility data records
+   */
+  int get_n_fac_data3()
+  {
+    return _n_fac_data;
+  };
+  /**
+   * @brief Fac data record length, bytes
+   */
+  int get_l_fac_data3()
+  {
+    return _l_fac_data;
+  };
+  /**
+   * @brief Number of facility data records
+   */
+  int get_n_fac_data4()
+  {
+    return _n_fac_data;
+  };
+  /**
+   * @brief Fac data record length, bytes
+   */
+  int get_l_fac_data4()
+  {
+    return _l_fac_data;
+  };
+  /**
+   * @brief Number of facility data records
+   */
+  int get_n_fac_data5()
+  {
+    return _n_fac_data;
+  };
+  /**
+   * @brief Fac data record length, bytes
+   */
+  int get_l_fac_data5()
+  {
+    return _l_fac_data;
+  };
+  /**
+   * @brief Number of facility data records
+   */
+  int get_n_fac_data6()
+  {
+    return _n_fac_data;
+  };
+  /**
+   * @brief Fac data record length, bytes
+   */
+  int get_l_fac_data6()
+  {
+    return _l_fac_data;
+  };
+  /**
+   * @brief Number of facility data records
+   */
+  int get_n_fac_data7()
+  {
+    return _n_fac_data;
+  };
+  /**
+   * @brief Fac data record length, bytes
+   */
+  int get_l_fac_data7()
+  {
+    return _l_fac_data;
+  };
+  /**
+   * @brief Number of facility data records
+   */
+  int get_n_fac_data8()
+  {
+    return _n_fac_data;
+  };
+  /**
+   * @brief Fac data record length, bytes
+   */
+  int get_l_fac_data8()
+  {
+    return _l_fac_data;
+  };
+  /**
+   * @brief Number of facility data records
+   */
+  int get_n_fac_data9()
+  {
+    return _n_fac_data;
+  };
+  /**
+   * @brief Fac data record length, bytes
+   */
+  int get_l_fac_data9()
+  {
+    return _l_fac_data;
+  };
+  /**
+   * @brief Number of facility data records
+   */
+  int get_n_fac_data10()
+  {
+    return _n_fac_data;
+  };
+  /**
+   * @brief Fac data record length, bytes
+   */
+  int get_l_fac_data10()
+  {
+    return _l_fac_data;
+  };
+  /**
+   * @brief Number of facility data records
+   */
+  int get_n_fac_data11()
+  {
+    return _n_fac_data;
+  };
+  /**
+   * @brief Fac data record length, bytes
+   */
+  int get_l_fac_data11()
+  {
+    return _l_fac_data;
+  };
+
+protected:
+  /**
+   * @brief ASCII flag
+   */
+  std::string _ascii_flag;
+
+  /**
+   * @brief Continuation flag
+   */
+  std::string _continuation_flag;
+
+  /**
+   * @brief Format control documentation
+   */
+  std::string _format_doc;
+  /**
+   * @brief Format doc version
+   */
+  std::string   _format_ver;
+  /**
+   * @brief Format doc revision
+   */
+  std::string   _design_rev;
+  /**
+   * @brief Software identifier
+   */
+  std::string   _software_id;
+  /**
+   * @brief File number
+   */
+  int   _file_num;
+  /**
+   * @brief File name
+   */
+  std::string   _file_name;
+  /**
+   * @brief Record sequence/location flag
+   */
+  std::string   _rec_seq;
+  /**
+   * @brief Sequence number location
+   */
+  int   _seq_loc;
+  /**
+   * @brief Sequence number lenght
+   */
+  int   _seq_len;
+  /**
+   * @brief Record code/location flag
+   */
+  std::string   _rec_code;
+  /**
+   * @brief Record code location
+   */
+  int   _code_loc;
+  /**
+   * @brief Record code length
+   */
+  int   _code_len;
+  /**
+   * @brief Record length/location flag
+   */
+  std::string _rec_len;
+  /**
+   * @brief Record lenght location
+   */
+  int _rlen_loc;
+  /**
+   * @brief Record length, bytes
+   */
+  int _rlen_len;
+
+
+  /**
+   * @brief Number of dataset summ records
+   */
+  int _n_dataset;
+  /**
+   * @brief Data set summary record length, bytes
+   */
+  int _l_dataset;
+  /**
+   * @brief Number of map proj records
+   */
+  int _n_map_proj;
+  /**
+   * @brief Map projection record length, bytes
+   */
+  int _l_map_proj;
+  /**
+   * @brief Number of platform position records
+   */
+  int _n_plat_pos;
+  /**
+   * @brief Platform position record length, bytes
+   */
+  int _l_plat_pos;
+  /**
+   * @brief Number of attitude data records
+   */
+  int _n_att_data;
+  /**
+   * @brief Attitude data record length, bytes
+   */
+  int _l_att_data;
+  /**
+   * @brief Number of radiometric data records
+   */
+  int _n_radi_data;
+  /**
+   * @brief Radiometric data record length, bytes
+   */
+  int _l_radi_data;
+  /**
+   * @brief Number of radiometric compensation records
+   */
+  int _n_radi_comp;
+  /**
+   *  @brief Radiometric compensation record length, bytes
+   */
+  int _l_radi_comp;
+  /**
+   * @brief Number of data quality summary records
+   */
+  int _n_qual_sum;
+  /**
+   * @brief Data quality summary record length, bytes
+   */
+  int _l_qual_sum;
+  /**
+   * @brief Number of data histogram records
+   */
+  int _n_data_his;
+  /**
+   * @brief Data histogram record length, bytes
+   */
+  int _l_data_his;
+  /**
+   * @brief Number of range spectra records
+   */
+  int _n_rang_spec;
+  /**
+   * @brief Range spectra record length, bytes
+   */
+  int _l_rang_spec;
+  /**
+   * @brief Number of DEM descriptor records
+   */
+  int _n_dem_desc;
+  /**
+   * @brief DEM desc record length, bytes
+   */
+  int _l_dem_desc;
+  /**
+   * @brief Number of RADAR par records
+   */
+  int _n_radar_par;
+  /**
+   * @brief RADAR par record length, bytes
+   */
+  int _l_radar_par;
+  /**
+   * @brief Number of annotation data records
+   */
+  int _n_anno_data;
+  /**
+   * @brief Annotation data record length, bytes
+   */
+  int _l_anno_data;
+  /**
+   * @brief Number of processing parameter records
+   */
+  int _n_det_proc;
+  /**
+   * @brief Processing parameter record length, bytes
+   */
+  int _l_det_proc;
+  /**
+   * @brief Number of calibration records
+   */
+  int _n_cal;
+  /**
+   * @brief Calibration record length, bytes
+   */
+  int _l_cal;
+  /**
+   * @brief Number of GCP records
+   */
+  int _n_gcp;
+  /**
+   * @brief GCP record length, bytes
+   */
+  int _l_gcp;
+
+  /**
+   * @brief Number of facility data records
+   */
+  int _n_fac_data;
+  /**
+   * @brief Fac data record length, bytes
+   */
+  int _l_fac_data;
+
+  /**
+   * @brief Number of facility data records
+   */
+  int _n_fac_data2;
+  /**
+   * @brief Fac data record length, bytes
+   */
+  int _l_fac_data2;
+
+  /**
+   * @brief Number of facility data records
+   */
+  int _n_fac_data3;
+  /**
+   * @brief Fac data record length, bytes
+   */
+  int _l_fac_data3;
+
+  /**
+   * @brief Number of facility data records
+   */
+  int _n_fac_data4;
+  /**
+   * @brief Fac data record length, bytes
+   */
+  int _l_fac_data4;
+
+  /**
+   * @brief Number of facility data records
+   */
+  int _n_fac_data5;
+  /**
+   * @brief Fac data record length, bytes
+   */
+  int _l_fac_data5;
+
+  /**
+   * @brief Number of facility data records
+   */
+  int _n_fac_data6;
+  /**
+   * @brief Fac data record length, bytes
+   */
+  int _l_fac_data6;
+
+  /**
+   * @brief Number of facility data records
+   */
+  int _n_fac_data7;
+  /**
+   * @brief Fac data record length, bytes
+   */
+  int _l_fac_data7;
+
+  /**
+   * @brief Number of facility data records
+   */
+  int _n_fac_data8;
+  /**
+   * @brief Fac data record length, bytes
+   */
+  int _l_fac_data8;
+
+  /**
+   * @brief Number of facility data records
+   */
+  int _n_fac_data9;
+  /**
+   * @brief Fac data record length, bytes
+   */
+  int _l_fac_data9;
+
+  /**
+   * @brief Number of facility data records
+   */
+  int _n_fac_data10;
+  /**
+   * @brief Fac data record length, bytes
+   */
+  int _l_fac_data10;
+
+  /**
+   * @brief Number of facility data records
+   */
+  int _n_fac_data11;
+  /**
+   * @brief Fac data record length, bytes
+   */
+  int _l_fac_data11;
+
+private:
+};
+}
+#endif
+
diff --git a/ossim_plugins/ossim/AlosPalsar/AlosPalsarLeader.cpp b/ossim_plugins/ossim/AlosPalsar/AlosPalsarLeader.cpp
new file mode 100644
index 0000000..8f8883d
--- /dev/null
+++ b/ossim_plugins/ossim/AlosPalsar/AlosPalsarLeader.cpp
@@ -0,0 +1,327 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+// "Copyright Centre for Remote Imaging, Sensing and Processing"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include <AlosPalsar/AlosPalsarLeader.h>
+#include <AlosPalsar/AlosPalsarLeaderFactory.h>
+#include <AlosPalsar/AlosPalsarRecordHeader.h>
+
+#include <AlosPalsar/AlosPalsarFileDescriptor.h>
+#include <AlosPalsar/AlosPalsarDataSetSummary.h>
+#include <AlosPalsar/AlosPalsarFacilityData.h>
+
+#include <ossim/base/ossimTrace.h>
+#include <ossim/base/ossimKeywordlist.h>
+#include <ossim/base/ossimKeywordNames.h>
+
+// Static trace for debugging
+static ossimTrace traceDebug("ossimAlosPalsarLeader:debug");
+
+namespace ossimplugins
+{
+
+const int AlosPalsarLeader::AlosPalsarFacilityDataID = 17;
+const int AlosPalsarLeader::AlosPalsarRadiometricDataID = 5;
+const int AlosPalsarLeader::AlosPalsarPlatformPositionDataID = 3;
+// const int AlosPalsarLeader::AlosPalsarMapProjectionDataID = 3; //
+const int AlosPalsarLeader::AlosPalsarDataSetSummaryID = 2;
+const int AlosPalsarLeader::AlosPalsarFileDescriptorID = 1;
+
+AlosPalsarLeader::AlosPalsarLeader()
+{
+}
+
+AlosPalsarLeader::~AlosPalsarLeader()
+{
+  ClearRecords();
+}
+
+std::ostream& operator<<(std::ostream& os, const AlosPalsarLeader& data)
+{
+  std::map<int, AlosPalsarRecord*>::const_iterator it = data._records.begin();
+  while (it != data._records.end())
+  {
+    (*it).second->Write(os);
+    ++it;
+  }
+  return os;
+
+}
+
+std::istream& operator>>(std::istream& is, AlosPalsarLeader& data)
+{
+  AlosPalsarLeaderFactory factory;
+
+  data.ClearRecords();
+
+  AlosPalsarRecordHeader header;
+  bool eof = false;
+  while (!eof)
+  {
+    is >> header;
+    if (is.eof())
+    {
+      eof = true;
+    }
+    else
+    {
+      AlosPalsarRecord* record = factory.Instanciate(header.get_rec_seq());
+      if (record != NULL)
+      {
+        record->Read(is);
+        data._records[header.get_rec_seq()] = record;
+      }
+      else
+      {
+        if (header.get_length() > 12)
+          {
+          char* buff = new char[header.get_length()-12];
+          is.read(buff, header.get_length() - 12);
+          delete [] buff;
+          }
+      }
+    }
+  }
+  return is;
+}
+
+
+AlosPalsarLeader::AlosPalsarLeader(const AlosPalsarLeader& rhs)
+{
+  std::map<int, AlosPalsarRecord*>::const_iterator it = rhs._records.begin();
+  while (it != rhs._records.end())
+  {
+    _records[(*it).first] = (*it).second->Clone();
+    ++it;
+  }
+}
+
+AlosPalsarLeader& AlosPalsarLeader::operator=(const AlosPalsarLeader& rhs)
+{
+  ClearRecords();
+  std::map<int, AlosPalsarRecord*>::const_iterator it = rhs._records.begin();
+  while (it != rhs._records.end())
+  {
+    _records[(*it).first] = (*it).second->Clone();
+    ++it;
+  }
+
+  return *this;
+}
+
+void AlosPalsarLeader::ClearRecords()
+{
+  std::map<int, AlosPalsarRecord*>::const_iterator it = _records.begin();
+  while (it != _records.end())
+  {
+    delete(*it).second;
+    ++it;
+  }
+  _records.clear();
+}
+
+bool AlosPalsarLeader::saveState(ossimKeywordlist& kwl,
+                                 const char* prefix) const
+{
+
+  static const char MODULE[] = "AlosPalsarLeader::saveState";
+
+  if (traceDebug())
+  {
+    ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " entered...\n";
+  }
+
+  bool result = true;
+
+  char name[64];
+
+  //kwl.add(prefix, ossimKeywordNames::TYPE_KW, "ossimAlosPalsarModel", true);
+  /*
+   * Adding metadata necessary to the sensor model in the keywordlist
+   */
+  const AlosPalsarFileDescriptor *leaderfiledesc = get_AlosPalsarFileDescriptor();
+  if (leaderfiledesc != NULL)
+  {
+    kwl.add(prefix, "filename", leaderfiledesc->get_file_name().c_str(), true);
+  }
+  else
+  {
+    result = false;
+  }
+
+  /*
+   * Adding metadata necessary to the sensor model in the keywordlist
+   */
+  const AlosPalsarDataSetSummary *datasetSummary = get_AlosPalsarDataSetSummary();
+  if ((datasetSummary != NULL) && (result == true))
+  {
+    kwl.add(prefix, "inp_sctim", (datasetSummary->get_inp_sctim()).c_str(), true);
+    kwl.add(prefix, "ellip_maj", datasetSummary->get_ellip_maj(), true);
+    kwl.add(prefix, "ellip_min", datasetSummary->get_ellip_min(), true);
+    kwl.add(prefix, "sc_lin", datasetSummary->get_sc_lin(), true);
+    kwl.add(prefix, "sc_pix", datasetSummary->get_sc_pix(), true);
+    kwl.add(prefix, "wave_length", datasetSummary->get_wave_length(), true);
+    kwl.add(prefix, "fr", datasetSummary->get_fr(), true);
+    kwl.add(prefix, "fa", datasetSummary->get_fa(), true);
+    kwl.add(prefix, "time_dir_pix", (datasetSummary->get_time_dir_pix()).c_str(), true);
+    kwl.add(prefix, "time_dir_lin", (datasetSummary->get_time_dir_lin()).c_str(), true);
+    kwl.add(prefix, "line_spacing", datasetSummary->get_line_spacing(), true);
+    kwl.add(prefix, "pix_spacing", datasetSummary->get_pix_spacing(), true);
+    kwl.add(prefix, "nlooks_az", datasetSummary->get_n_azilok(), true);
+    kwl.add(prefix, "n_rnglok", datasetSummary->get_n_rnglok(), true);
+    kwl.add(prefix, "alt_dopcen[0]", datasetSummary->get_alt_dopcen()[0], true);
+    kwl.add(prefix, "crt_dopcen[0]", datasetSummary->get_crt_dopcen()[0], true);
+    kwl.add(prefix, "crt_dopcen[1]", datasetSummary->get_crt_dopcen()[1], true);
+    kwl.add(prefix, "dopcen_range[0]", datasetSummary->get_dopcen_range()[0], true);
+    kwl.add(prefix, "dopcen_range[1]", datasetSummary->get_dopcen_range()[1], true);
+    //FIXME check if those data are available
+//     kwl.add(prefix, "zero_dop_range_time_f_pixel", datasetSummary->get_zero_dop_range_time_f_pixel(),true);
+//     kwl.add(prefix, "zero_dop_range_time_c_pixel", datasetSummary->get_zero_dop_range_time_c_pixel(),true);
+//     kwl.add(prefix, "zero_dop_range_time_l_pixel", datasetSummary->get_zero_dop_range_time_l_pixel(),true);
+  }
+  else
+  {
+    result = false;
+  }
+
+  // FIXME do not handle Alos map projection information for now...
+//   const AlosPalsarMapProjectionData *mapprojectiondata = get_AlosPalsarMapProjectionData();
+//   if ( (mapprojectiondata != NULL) && (result == true) )
+//   {
+//     kwl.add(prefix, "map_proj_des",(mapprojectiondata->get_map_proj_des()).c_str(),true);
+//     kwl.add(prefix, "num_lines",(double) mapprojectiondata->get_num_lines(),true);
+//     kwl.add(prefix, "num_pix",(double) mapprojectiondata->get_num_pix_in_line(),true);
+//     kwl.add(prefix, "first_line_first_pixel_lat",mapprojectiondata->get_first_line_first_pixel_lat(), true);
+//     kwl.add(prefix, "first_line_first_pixel_lon",mapprojectiondata->get_first_line_first_pixel_lon(), true);
+//     kwl.add(prefix, "first_line_last_pixel_lat",mapprojectiondata->get_first_line_last_pixel_lat(), true);
+//     kwl.add(prefix, "first_line_last_pixel_lon",mapprojectiondata->get_first_line_last_pixel_lon(), true);
+//     kwl.add(prefix, "last_line_first_pixel_lat",mapprojectiondata->get_last_line_first_pixel_lat(), true);
+//     kwl.add(prefix, "last_line_first_pixel_lon",mapprojectiondata->get_last_line_first_pixel_lon(), true);
+//     kwl.add(prefix, "last_line_last_pixel_lat",mapprojectiondata->get_last_line_last_pixel_lat(), true);
+//     kwl.add(prefix, "last_line_last_pixel_lon",mapprojectiondata->get_last_line_last_pixel_lon(), true);
+//   }
+//   else
+//   {
+//     result = false;
+//   }
+
+  const AlosPalsarPlatformPositionData *platformposition = get_AlosPalsarPlatformPositionData();
+  if ((platformposition != NULL) && (result == true))
+  {
+    kwl.add(prefix, "neph", platformposition->get_ndata(), true);
+    kwl.add(prefix, "eph_year", platformposition->get_year(), true);
+    kwl.add(prefix, "eph_month", platformposition->get_month(), true);
+    kwl.add(prefix, "eph_day", platformposition->get_day(), true);
+    kwl.add(prefix, "eph_gmt_day", platformposition->get_gmt_day(), true);
+    kwl.add(prefix, "eph_sec", platformposition->get_gmt_sec(), true);
+    kwl.add(prefix, "eph_hr_angle", platformposition->get_hr_angle(), true);
+    kwl.add(prefix, "eph_int", platformposition->get_data_int(), true);
+
+    for (int i = 0; i < platformposition->get_ndata(); i++)
+    {
+      sprintf(name, "eph%i_posX", i);
+      kwl.add(prefix, name, (platformposition->get_pos_vect()[i]).get_pos()[0], true);
+      sprintf(name, "eph%i_posY", i);
+      kwl.add(prefix, name, (platformposition->get_pos_vect()[i]).get_pos()[1], true);
+      sprintf(name, "eph%i_posZ", i);
+      kwl.add(prefix, name, (platformposition->get_pos_vect()[i]).get_pos()[2], true);
+
+      sprintf(name, "eph%i_velX", i);
+      kwl.add(prefix, name, (platformposition->get_pos_vect()[i]).get_vel()[0], true);
+      sprintf(name, "eph%i_velY", i);
+      kwl.add(prefix, name, (platformposition->get_pos_vect()[i]).get_vel()[1], true);
+      sprintf(name, "eph%i_velZ", i);
+      kwl.add(prefix, name, (platformposition->get_pos_vect()[i]).get_vel()[2], true);
+    }
+  }
+  else
+  {
+    result = false;
+  }
+
+  const AlosPalsarRadiometricData *radiometricdata = get_AlosPalsarRadiometricData();
+  if ((radiometricdata != NULL) && (result == true))
+  {
+    kwl.add(prefix, "calibration_factor", radiometricdata->get_calibration_factor(), true);
+  }
+  else
+  {
+    result = false;
+  }
+
+  // FIXME  Do not handle Palsar facility-related data for now...
+  // The current code corresponds to the ERS facility-related data
+  // which is completely different from that for PALSAR
+  /*
+  const AlosPalsarFacilityData *facilitydata = get_AlosPalsarFacilityData();
+  if ((facilitydata != NULL) && (result == true))
+  {
+    kwl.add(prefix, "coef_ground_range_1", facilitydata->get_coef_ground_range_1(), true);
+    kwl.add(prefix, "coef_ground_range_2", facilitydata->get_coef_ground_range_2(), true);
+    kwl.add(prefix, "coef_ground_range_3", facilitydata->get_coef_ground_range_3(), true);
+    kwl.add(prefix, "coef_ground_range_4", facilitydata->get_coef_ground_range_4(), true);
+  }
+  else
+  {
+    result = false;
+  }
+  */
+
+  if (traceDebug())
+  {
+    ossimNotify(ossimNotifyLevel_DEBUG)
+    << MODULE << " exit status = " << (result ? "true" : "false\n")
+    << std::endl;
+  }
+
+
+  return result;
+}
+
+const AlosPalsarFacilityData * AlosPalsarLeader::get_AlosPalsarFacilityData() const
+{
+//   return const_cast<const AlosPalsarFacilityData*>(dynamic_cast<AlosPalsarFacilityData*>(_records[AlosPalsarFacilityDataID]));
+//   RecordType::const_iterator it = _records.find(AlosPalsarFacilityDataID)->second;
+//   return dynamic_cast<const AlosPalsarFacilityData*>(it.find(AlosPalsarFacilityDataID));
+  return dynamic_cast<const AlosPalsarFacilityData*>(_records.find(AlosPalsarFacilityDataID)->second);
+}
+
+const AlosPalsarRadiometricData * AlosPalsarLeader::get_AlosPalsarRadiometricData() const
+{
+  return dynamic_cast<const AlosPalsarRadiometricData*>(_records.find(AlosPalsarRadiometricDataID)->second);
+}
+
+const AlosPalsarPlatformPositionData * AlosPalsarLeader::get_AlosPalsarPlatformPositionData() const
+{
+  return dynamic_cast<const AlosPalsarPlatformPositionData*>(_records.find(AlosPalsarPlatformPositionDataID)->second);
+}
+
+/*
+const AlosPalsarMapProjectionData * AlosPalsarLeader::get_AlosPalsarMapProjectionData() const
+{
+//   return (AlosPalsarMapProjectionData*)_records[AlosPalsarMapProjectionDataID];
+  return dynamic_cast<const AlosPalsarMapProjectionData*>(_records.find(AlosPalsarMapProjectionDataID)->second);
+}
+*/
+// no map projection data for level 1.1
+
+const AlosPalsarDataSetSummary * AlosPalsarLeader::get_AlosPalsarDataSetSummary() const
+{
+  return dynamic_cast<const AlosPalsarDataSetSummary*>(_records.find(AlosPalsarDataSetSummaryID)->second);
+}
+
+const AlosPalsarFileDescriptor * AlosPalsarLeader::get_AlosPalsarFileDescriptor() const
+{
+  return dynamic_cast<const AlosPalsarFileDescriptor*>(_records.find(AlosPalsarFileDescriptorID)->second);
+}
+
+}
+
diff --git a/ossim_plugins/ossim/AlosPalsar/AlosPalsarLeader.h b/ossim_plugins/ossim/AlosPalsar/AlosPalsarLeader.h
new file mode 100644
index 0000000..62a412b
--- /dev/null
+++ b/ossim_plugins/ossim/AlosPalsar/AlosPalsarLeader.h
@@ -0,0 +1,112 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+// "Copyright Centre for Remote Imaging, Sensing and Processing"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef AlosPalsarLeader_h
+#define AlosPalsarLeader_h
+
+#include <iostream>
+#include "AlosPalsar/AlosPalsarFileDescriptor.h"
+#include "AlosPalsar/AlosPalsarDataSetSummary.h"
+#include "AlosPalsar/AlosPalsarMapProjectionData.h"
+#include "AlosPalsar/AlosPalsarPlatformPositionData.h"
+#include "AlosPalsar/AlosPalsarRadiometricData.h"
+#include "AlosPalsar/AlosPalsarFacilityData.h"
+#include <map>
+
+class ossimKeywordlist;
+
+namespace ossimplugins
+{
+
+class AlosPalsarPlatformPositionData;
+class AlosPalsarMapProjectionData;
+class AlosPalsarDataSetSummary;
+class AlosPalsarFileDescriptor;
+class AlosPalsarFacilityData;
+class AlosPalsarRadiometricData;
+
+/**
+ * @ingroup AlosPalsarLeaderFile
+ * @brief This class is able to read the Leader file of the AlosPalsar file structure
+ */
+class AlosPalsarLeader
+{
+public:
+  /**
+   * @brief Constructor
+   */
+  AlosPalsarLeader();
+
+  /**
+   * @brief Destructor
+   */
+  virtual ~AlosPalsarLeader();
+
+  /**
+   * @brief This function write the AlosPalsarLeader in a stream
+   */
+  friend std::ostream& operator<<(std::ostream& os, const AlosPalsarLeader& data);
+
+  /**
+   * @brief This function read a AlosPalsarLeader from a stream
+   */
+  friend std::istream& operator>>(std::istream& is, AlosPalsarLeader& data);
+
+  /**
+   * @brief Copy constructor
+   */
+  AlosPalsarLeader(const AlosPalsarLeader& rhs);
+
+  /**
+   * @brief Copy operator
+   */
+  AlosPalsarLeader& operator=(const AlosPalsarLeader& rhs);
+
+  /**
+   * @brief Remove all the previous records from the AlosPalsarLeader
+   */
+  void ClearRecords();
+
+
+  /**
+   * @brief Method to save object state to a keyword list.
+   * @param kwl Keyword list to save to.
+   * @param prefix added to keys when saved.
+   * @return true on success, false on error.
+   */
+  virtual bool saveState(ossimKeywordlist& kwl,
+                         const char* prefix = 0) const;
+
+
+  const AlosPalsarFacilityData * get_AlosPalsarFacilityData() const;
+  const AlosPalsarRadiometricData * get_AlosPalsarRadiometricData() const;
+  const AlosPalsarPlatformPositionData * get_AlosPalsarPlatformPositionData() const;
+//  const AlosPalsarMapProjectionData * get_AlosPalsarMapProjectionData() const;
+  const AlosPalsarDataSetSummary * get_AlosPalsarDataSetSummary() const;
+  const AlosPalsarFileDescriptor * get_AlosPalsarFileDescriptor() const;
+
+protected:
+  typedef std::map<int, AlosPalsarRecord*> RecordType;
+  RecordType _records;
+
+  static const int AlosPalsarFacilityDataID;
+  static const int AlosPalsarRadiometricDataID;
+  static const int AlosPalsarPlatformPositionDataID;
+//  static const int AlosPalsarMapProjectionDataID;
+  static const int AlosPalsarDataSetSummaryID;
+  static const int AlosPalsarFileDescriptorID;
+private:
+
+};
+}
+#endif
+
diff --git a/ossim_plugins/ossim/AlosPalsar/AlosPalsarLeaderFactory.cpp b/ossim_plugins/ossim/AlosPalsar/AlosPalsarLeaderFactory.cpp
new file mode 100644
index 0000000..b1d22d3
--- /dev/null
+++ b/ossim_plugins/ossim/AlosPalsar/AlosPalsarLeaderFactory.cpp
@@ -0,0 +1,40 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+// "Copyright Centre for Remote Imaging, Sensing and Processing"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include <AlosPalsar/AlosPalsarLeaderFactory.h>
+
+#include <AlosPalsar/AlosPalsarDataSetSummary.h>
+#include <AlosPalsar/AlosPalsarFileDescriptor.h>
+#include <AlosPalsar/AlosPalsarPlatformPositionData.h>
+#include <AlosPalsar/AlosPalsarRadiometricData.h>
+#include <AlosPalsar/AlosPalsarFacilityData.h>
+
+namespace ossimplugins
+{
+
+AlosPalsarLeaderFactory::AlosPalsarLeaderFactory()
+{
+  RegisterRecord(17, new AlosPalsarFacilityData());
+  RegisterRecord(5, new AlosPalsarRadiometricData());
+  RegisterRecord(3, new AlosPalsarPlatformPositionData());
+//  RegisterRecord(3, new AlosPalsarMapProjectionData());//
+  RegisterRecord(2, new AlosPalsarDataSetSummary());
+  RegisterRecord(1, new AlosPalsarFileDescriptor());
+}
+
+AlosPalsarLeaderFactory::~AlosPalsarLeaderFactory()
+{
+
+}
+
+}
+
diff --git a/ossim_plugins/ossim/AlosPalsar/AlosPalsarLeaderFactory.h b/ossim_plugins/ossim/AlosPalsar/AlosPalsarLeaderFactory.h
new file mode 100644
index 0000000..9abda79
--- /dev/null
+++ b/ossim_plugins/ossim/AlosPalsar/AlosPalsarLeaderFactory.h
@@ -0,0 +1,47 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+// "Copyright Centre for Remote Imaging, Sensing and Processing"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef AlosPalsarLeaderFactory_h
+#define AlosPalsarLeaderFactory_h
+
+
+#include <AlosPalsar/AlosPalsarRecordFactory.h>
+#include <map>
+
+namespace ossimplugins
+{
+
+/**
+ * @ingroup AlosPalsarLeaderFile
+ * @brief This class is a facory able to construct Record base classes
+ */
+class AlosPalsarLeaderFactory : public AlosPalsarRecordFactory
+{
+public:
+  /**
+   * @brief Contstructor
+   */
+  AlosPalsarLeaderFactory();
+  /**
+   * @brief Destructor
+   */
+  ~AlosPalsarLeaderFactory();
+
+
+protected:
+
+
+private:
+};
+}
+#endif
+
diff --git a/ossim_plugins/ossim/AlosPalsar/AlosPalsarMapProjectionData.cpp b/ossim_plugins/ossim/AlosPalsar/AlosPalsarMapProjectionData.cpp
new file mode 100644
index 0000000..990096d
--- /dev/null
+++ b/ossim_plugins/ossim/AlosPalsar/AlosPalsarMapProjectionData.cpp
@@ -0,0 +1,211 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+// "Copyright Centre for Remote Imaging, Sensing and Processing"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include <AlosPalsar/AlosPalsarMapProjectionData.h>
+
+namespace ossimplugins
+{
+
+   AlosPalsarMapProjectionData::AlosPalsarMapProjectionData() : AlosPalsarRecord("map_proj_data_rec")
+   {
+   }
+
+   AlosPalsarMapProjectionData::~AlosPalsarMapProjectionData()
+   {
+   }
+
+   std::ostream& operator<<(std::ostream& os, const AlosPalsarMapProjectionData& data)
+   {
+      os << "map_proj_des:" << data._map_proj_des.c_str() << std::endl;
+
+      os << "num_pix_in_line:" << data._num_pix_in_line << std::endl;
+
+      os << "num_lines:" << data._num_lines << std::endl;
+
+      os << "nom_interpixel_dist:" << data._nom_interpixel_dist << std::endl;
+
+      os << "nom_interline_dist:" << data._nom_interline_dist << std::endl;
+
+      os << "orientation_at_center:" << data._orientation_at_center << std::endl;
+
+      os << "orbit_incl:" << data._orbit_incl << std::endl;
+
+      os << "asc_node_long:" << data._asc_node_long << std::endl;
+
+      os << "platform_heading:" << data._platform_heading << std::endl;
+
+      os << "name_of_ref_ellipsoid:" << data._name_of_ref_ellipsoid.c_str() << std::endl;
+
+      os << "semi_maj_axis:" << data._semi_maj_axis << std::endl;
+
+      os << "semi_min_axis:" << data._semi_min_axis << std::endl;
+
+      os << "first_line_first_pixel_lat:" << data._first_line_first_pixel_lat << std::endl;
+
+      os << "first_line_first_pixel_lon:" << data._first_line_first_pixel_lon << std::endl;
+
+      os << "first_line_last_pixel_lat:" << data._first_line_last_pixel_lat << std::endl;
+
+      os << "first_line_last_pixel_lon:" << data._first_line_last_pixel_lon << std::endl;
+
+      os << "last_line_last_pixel_lat:" << data._last_line_last_pixel_lat << std::endl;
+
+      os << "last_line_last_pixel_lon:" << data._last_line_last_pixel_lon << std::endl;
+
+      os << "last_line_first_pixel_lat:" << data._last_line_first_pixel_lat << std::endl;
+
+      os << "last_line_first_pixel_lon:" << data._last_line_first_pixel_lon << std::endl;
+
+      return os;
+
+   }
+
+   std::istream& operator>>(std::istream& is, AlosPalsarMapProjectionData& data)
+   {
+      char buf16[17];
+      buf16[16] = '\0';
+      char buf32[33];
+      buf32[32] = '\0';
+      // char buf8[9];
+      // buf8[8] = '\0';
+      // char buf4[5];
+      // buf4[4] = '\0';
+
+      is.read(buf16, 16);
+
+      is.read(buf32, 32);
+      data._map_proj_des = buf32;
+
+      is.read(buf16, 16);
+      data._num_pix_in_line = atoi(buf16);
+
+      is.read(buf16, 16);
+      data._num_lines = atoi(buf16);
+
+      is.read(buf16, 16);
+      data._nom_interpixel_dist = atof(buf16);
+
+      is.read(buf16, 16);
+      data._nom_interline_dist = atof(buf16);
+
+      is.read(buf16, 16);
+      data._orientation_at_center = atof(buf16);
+
+      is.read(buf16, 16);
+      data._orbit_incl = atof(buf16);
+
+      is.read(buf16, 16);
+      data._asc_node_long = atof(buf16);
+
+      is.read(buf16, 16);
+
+      is.read(buf16, 16);
+
+      is.read(buf16, 16);
+
+      is.read(buf16, 16);
+      data._platform_heading = atof(buf16);
+
+      is.read(buf32, 32);
+      data._name_of_ref_ellipsoid = buf32;
+
+      is.read(buf16, 16);
+      data._semi_maj_axis = atof(buf16);
+
+      is.read(buf16, 16);
+      data._semi_min_axis = atof(buf16);
+
+      char buf772[772];
+      is.read(buf772, 772);
+
+      is.read(buf16, 16);
+      data._first_line_first_pixel_lat = atof(buf16);
+
+      is.read(buf16, 16);
+      data._first_line_first_pixel_lon = atof(buf16);
+
+      is.read(buf16, 16);
+      data._first_line_last_pixel_lat = atof(buf16);
+
+      is.read(buf16, 16);
+      data._first_line_last_pixel_lon = atof(buf16);
+
+      is.read(buf16, 16);
+      data._last_line_last_pixel_lat = atof(buf16);
+
+      is.read(buf16, 16);
+      data._last_line_last_pixel_lon = atof(buf16);
+
+      is.read(buf16, 16);
+      data._last_line_first_pixel_lat = atof(buf16);
+
+      is.read(buf16, 16);
+      data._last_line_first_pixel_lon = atof(buf16);
+
+      char buf420[420];
+      is.read(buf420, 420);
+
+      return is;
+   }
+
+
+   AlosPalsarMapProjectionData::AlosPalsarMapProjectionData(const AlosPalsarMapProjectionData& rhs):
+      AlosPalsarRecord(rhs),
+      _map_proj_des(rhs._map_proj_des),
+      _num_pix_in_line(rhs._num_pix_in_line),
+      _num_lines(rhs._num_lines),
+      _nom_interpixel_dist(rhs._nom_interpixel_dist),
+      _nom_interline_dist(rhs._nom_interline_dist),
+      _orientation_at_center(rhs._orientation_at_center),
+      _orbit_incl(rhs._orbit_incl),
+      _asc_node_long(rhs._asc_node_long),
+      _platform_heading(rhs._platform_heading),
+      _name_of_ref_ellipsoid(rhs._name_of_ref_ellipsoid),
+      _semi_maj_axis(rhs._semi_maj_axis),
+      _semi_min_axis(rhs._semi_min_axis),
+      _first_line_first_pixel_lat(rhs._first_line_first_pixel_lat),
+      _first_line_first_pixel_lon(rhs._first_line_first_pixel_lon),
+      _first_line_last_pixel_lat(rhs._first_line_last_pixel_lat),
+      _first_line_last_pixel_lon(rhs._first_line_last_pixel_lon),
+      _last_line_last_pixel_lat(rhs._last_line_last_pixel_lat),
+      _last_line_last_pixel_lon(rhs._last_line_last_pixel_lon),
+      _last_line_first_pixel_lat(rhs._last_line_first_pixel_lat),
+      _last_line_first_pixel_lon(rhs._last_line_first_pixel_lon)
+   {}
+
+   AlosPalsarMapProjectionData& AlosPalsarMapProjectionData::operator=(const AlosPalsarMapProjectionData& rhs)
+   {
+      _map_proj_des = rhs._map_proj_des;
+      _num_pix_in_line = rhs._num_pix_in_line;
+      _num_lines = rhs._num_lines;
+      _nom_interpixel_dist = rhs._nom_interpixel_dist;
+      _nom_interline_dist = rhs._nom_interline_dist;
+      _orientation_at_center = rhs._orientation_at_center;
+      _orbit_incl = rhs._orbit_incl;
+      _asc_node_long = rhs._asc_node_long;
+      _platform_heading = rhs._platform_heading;
+      _name_of_ref_ellipsoid = rhs._name_of_ref_ellipsoid;
+      _semi_maj_axis = rhs._semi_maj_axis;
+      _semi_min_axis = rhs._semi_min_axis;
+      _first_line_first_pixel_lat = rhs._first_line_first_pixel_lat;
+      _first_line_first_pixel_lon = rhs._first_line_first_pixel_lon;
+      _first_line_last_pixel_lat = rhs._first_line_last_pixel_lat;
+      _first_line_last_pixel_lon = rhs._first_line_last_pixel_lon;
+      _last_line_last_pixel_lat = rhs._last_line_last_pixel_lat;
+      _last_line_last_pixel_lon = rhs._last_line_last_pixel_lon;
+      _last_line_first_pixel_lat = rhs._last_line_first_pixel_lat;
+      _last_line_first_pixel_lon = rhs._last_line_first_pixel_lon;
+
+      return *this;
+   }
+}
+
diff --git a/ossim_plugins/ossim/AlosPalsar/AlosPalsarMapProjectionData.h b/ossim_plugins/ossim/AlosPalsar/AlosPalsarMapProjectionData.h
new file mode 100644
index 0000000..2943505
--- /dev/null
+++ b/ossim_plugins/ossim/AlosPalsar/AlosPalsarMapProjectionData.h
@@ -0,0 +1,322 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+// "Copyright Centre for Remote Imaging, Sensing and Processing"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef AlosPalsarMapProjectionData_h
+#define AlosPalsarMapProjectionData_h
+
+#include <iostream>
+#include <cstdlib>
+#include <AlosPalsar/AlosPalsarRecordHeader.h>
+#include <AlosPalsar/AlosPalsarRecord.h>
+
+namespace ossimplugins
+{
+
+/**
+ * @ingroup AlosPalsarMapProjectionDataRecord
+ * @brief This class is able to read the SAR leader data set summary record of the leader file
+ */
+class AlosPalsarMapProjectionData : public AlosPalsarRecord
+{
+public:
+  /**
+   * @brief Constructor
+   */
+  AlosPalsarMapProjectionData();
+
+  /**
+   * @brief Destructor
+   */
+  virtual ~AlosPalsarMapProjectionData();
+
+  /**
+   * @brief This function write the AlosPalsarMapProjectionData in a stream
+   */
+  friend std::ostream& operator<<(std::ostream& os, const AlosPalsarMapProjectionData& data);
+
+  /**
+   * @brief This function read a AlosPalsarMapProjectionData from a stream
+   */
+  friend std::istream& operator>>(std::istream& is, AlosPalsarMapProjectionData& data);
+
+  /**
+   * @brief Copy constructor
+   */
+  AlosPalsarMapProjectionData(const AlosPalsarMapProjectionData& rhs);
+
+  /**
+   * @brief Copy operator
+   */
+  AlosPalsarMapProjectionData& operator=(const AlosPalsarMapProjectionData& rhs);
+
+  /**
+   * @brief This function is able to create a new instance of the class
+   */
+  AlosPalsarRecord* Instanciate()
+  {
+    return new AlosPalsarMapProjectionData();
+  };
+
+  /**
+   * @brief This function is able to create a new instance of the class initialised with the data of the calling instance
+   */
+  AlosPalsarRecord* Clone()
+  {
+    return new AlosPalsarMapProjectionData(*this);
+  };
+
+  /**
+   * @brief Read the class data from a stream
+   */
+  void Read(std::istream& is)
+  {
+    is >> *this;
+  };
+
+  /**
+   * @brief Write the class to a stream
+   */
+  void Write(std::ostream& os)
+  {
+    os << *this;
+  };
+
+  /**
+  * @brief map_proj_des
+  */
+  std::string   get_map_proj_des() const
+  {
+    return _map_proj_des;
+  };
+  /**
+  * @brief num_pix_in_line
+  */
+  int   get_num_pix_in_line() const
+  {
+    return _num_pix_in_line;
+  };
+  /**
+  * @brief num_lines
+  */
+  int   get_num_lines() const
+  {
+    return _num_lines;
+  };
+  /**
+  * @brief nom_interpixel_dist
+  */
+  double   get_nom_interpixel_dist() const
+  {
+    return _nom_interpixel_dist;
+  };
+  /**
+  * @brief nom_interline_dist
+  */
+  double   get_nom_interline_dist() const
+  {
+    return _nom_interline_dist;
+  };
+  /**
+  * @brief orientation_at_center
+  */
+  double   get_orientation_at_center() const
+  {
+    return _orientation_at_center;
+  };
+  /**
+  * @brief orbit_incl
+  */
+  double   get_orbit_incl() const
+  {
+    return _orbit_incl;
+  };
+  /**
+  * @brief asc_node_long
+  */
+  double   get_asc_node_long() const
+  {
+    return _asc_node_long;
+  };
+  /**
+  * @brief platform_heading
+  */
+  double   get_platform_heading() const
+  {
+    return _platform_heading;
+  };
+  /**
+  * @brief name_of_ref_ellipsoid
+  */
+  std::string   get_name_of_ref_ellipsoid() const
+  {
+    return _name_of_ref_ellipsoid;
+  };
+  /**
+  * @brief semi_maj_axis
+  */
+  double   get_semi_maj_axis() const
+  {
+    return _semi_maj_axis;
+  };
+  /**
+  * @brief semi_min_axis
+  */
+  double   get_semi_min_axis() const
+  {
+    return _semi_min_axis;
+  };
+  /**
+  * @brief first_line_first_pixel  _lat
+  */
+  double   get_first_line_first_pixel_lat() const
+  {
+    return _first_line_first_pixel_lat;
+  };
+  /**
+  * @brief first_line_first_pixel_lon
+  */
+  double   get_first_line_first_pixel_lon() const
+  {
+    return _first_line_first_pixel_lon;
+  };
+  /**
+  * @brief first_line_last_pixel  _lat
+  */
+  double   get_first_line_last_pixel_lat() const
+  {
+    return _first_line_last_pixel_lat;
+  };
+  /**
+  * @brief first_line_last_pixel_lon
+  */
+  double   get_first_line_last_pixel_lon() const
+  {
+    return _first_line_last_pixel_lon;
+  };
+  /**
+  * @brief last_line_last_pixel_lat
+  */
+  double   get_last_line_last_pixel_lat() const
+  {
+    return _last_line_last_pixel_lat;
+  };
+  /**
+  * @brief last_line_last_pixel_lon
+  */
+  double   get_last_line_last_pixel_lon() const
+  {
+    return _last_line_last_pixel_lon;
+  };
+  /**
+  * @brief last_line_first_pixel_lat
+  */
+  double   get_last_line_first_pixel_lat() const
+  {
+    return _last_line_first_pixel_lat;
+  };
+  /**
+  * @brief last_line_first_pixel_lon
+  */
+  double   get_last_line_first_pixel_lon() const
+  {
+    return _last_line_first_pixel_lon;
+  };
+
+protected:
+  /**
+  * @brief map_proj_des
+  */
+  std::string   _map_proj_des;
+  /**
+  * @brief num_pix_in_line
+  */
+  int   _num_pix_in_line;
+  /**
+  * @brief num_lines
+  */
+  int   _num_lines;
+  /**
+  * @brief nom_interpixel_dist
+  */
+  double   _nom_interpixel_dist;
+  /**
+  * @brief nom_interline_dist
+  */
+  double   _nom_interline_dist;
+  /**
+  * @brief orientation_at_center
+  */
+  double   _orientation_at_center;
+  /**
+  * @brief orbit_incl
+  */
+  double   _orbit_incl;
+  /**
+  * @brief asc_node_long
+  */
+  double   _asc_node_long;
+  /**
+  * @brief platform_heading
+  */
+  double   _platform_heading;
+  /**
+  * @brief name_of_ref_ellipsoid
+  */
+  std::string   _name_of_ref_ellipsoid;
+  /**
+  * @brief semi_maj_axis
+  */
+  double   _semi_maj_axis;
+  /**
+  * @brief semi_min_axis
+  */
+  double   _semi_min_axis;
+  /**
+  * @brief first_line_first_pixel_lat
+  */
+  double   _first_line_first_pixel_lat;
+  /**
+  * @brief first_line_first_pixel_lon
+  */
+  double   _first_line_first_pixel_lon;
+  /**
+  * @brief first_line_last_pixel_lat
+  */
+  double   _first_line_last_pixel_lat;
+  /**
+  * @brief first_line_last_pixel_lon
+  */
+  double   _first_line_last_pixel_lon;
+  /**
+  * @brief last_line_last_pixel_lat
+  */
+  double   _last_line_last_pixel_lat;
+  /**
+  * @brief last_line_last_pixel_lon
+  */
+  double   _last_line_last_pixel_lon;
+  /**
+  * @brief last_line_first_pixel_lat
+  */
+  double   _last_line_first_pixel_lat;
+  /**
+  * @brief last_line_first_pixel_lon
+  */
+  double   _last_line_first_pixel_lon;
+
+
+private:
+
+};
+}
+#endif
+
diff --git a/ossim_plugins/ossim/AlosPalsar/AlosPalsarPlatformPositionData.cpp b/ossim_plugins/ossim/AlosPalsar/AlosPalsarPlatformPositionData.cpp
new file mode 100644
index 0000000..111276b
--- /dev/null
+++ b/ossim_plugins/ossim/AlosPalsar/AlosPalsarPlatformPositionData.cpp
@@ -0,0 +1,256 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+// "Copyright Centre for Remote Imaging, Sensing and Processing"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include <AlosPalsar/AlosPalsarPlatformPositionData.h>
+
+namespace ossimplugins
+{
+
+
+AlosPalsarPlatformPositionData::AlosPalsarPlatformPositionData() : AlosPalsarRecord("pos_data_rec")
+{
+}
+
+AlosPalsarPlatformPositionData::~AlosPalsarPlatformPositionData()
+{
+}
+
+std::ostream& operator<<(std::ostream& os, const AlosPalsarPlatformPositionData& data)
+{
+  os << "orbit_ele_desg:" << data._orbit_ele_desg.c_str() << std::endl;
+
+  for (int i = 0; i < 6; i++)
+  {
+    os << "orbit_ele[" << i << "]:" << data._orbit_ele[i] << std::endl;
+  }
+
+  os << "ndata:" << data._ndata << std::endl;
+
+  os << "year:" << data._year << std::endl;
+
+  os << "month:" << data._month << std::endl;
+
+  os << "day:" << data._day << std::endl;
+
+  os << "gmt_day:" << data._gmt_day << std::endl;
+
+  os << "gmt_sec:" << data._gmt_sec << std::endl;
+
+  os << "data_int:" << data._data_int << std::endl;
+
+  os << "ref_coord:" << data._ref_coord.c_str() << std::endl;
+
+  os << "hr_angle:" << data._hr_angle << std::endl;
+
+  os << "alt_poserr:" << data._alt_poserr << std::endl;
+
+  os << "crt_poserr:" << data._crt_poserr << std::endl;
+
+  os << "rad_poserr:" << data._rad_poserr << std::endl;
+
+  os << "alt_velerr:" << data._alt_velerr << std::endl;
+
+  os << "crt_velerr:" << data._crt_velerr << std::endl;
+
+  os << "rad_velerr:" << data._rad_velerr << std::endl;
+
+  for (int i = 0; i < 64; i++)
+  {
+    os << "pos_vect[" << i << "]:" << data._pos_vect[i] << std::endl;
+  }
+
+  return os;
+}
+
+std::istream& operator>>(std::istream& is, AlosPalsarPlatformPositionData& data)
+{
+  char buf[1207];
+  buf[1206] = '\0';
+
+  is.read(buf, 32);
+  buf[32] = '\0';
+  data._orbit_ele_desg = buf;
+
+  for (int i = 0; i < 6; i++)
+  {
+    is.read(buf, 16);
+    buf[16] = '\0';
+    data._orbit_ele[i] = atof(buf);
+  }
+
+  is.read(buf, 4);
+  buf[4] = '\0';
+  data._ndata = atoi(buf);
+
+  is.read(buf, 4);
+  buf[4] = '\0';
+  data._year = atoi(buf);
+
+  is.read(buf, 4);
+  buf[4] = '\0';
+  data._month = atoi(buf);
+
+  is.read(buf, 4);
+  buf[4] = '\0';
+  data._day = atoi(buf);
+
+  is.read(buf, 4);
+  buf[4] = '\0';
+  data._gmt_day = atoi(buf);
+
+  is.read(buf, 22);
+  buf[22] = '\0';
+  data._gmt_sec = atof(buf);
+
+  is.read(buf, 22);
+  buf[22] = '\0';
+  data._data_int = atof(buf);
+
+  is.read(buf, 64);
+  buf[64] = '\0';
+  data._ref_coord = buf;
+
+  is.read(buf, 22);
+  buf[22] = '\0';
+  data._hr_angle = atof(buf);
+
+  is.read(buf, 16);
+  buf[16] = '\0';
+  data._alt_poserr = atof(buf);
+
+  is.read(buf, 16);
+  buf[16] = '\0';
+  data._crt_poserr = atof(buf);
+
+  is.read(buf, 16);
+  buf[16] = '\0';
+  data._rad_poserr = atof(buf);
+
+  is.read(buf, 16);
+  buf[16] = '\0';
+  data._alt_velerr = atof(buf);
+
+  is.read(buf, 16);
+  buf[16] = '\0';
+  data._crt_velerr = atof(buf);
+
+  is.read(buf, 16);
+  buf[16] = '\0';
+  data._rad_velerr = atof(buf);
+
+  for (int i = 0; i < data._ndata; i++)
+  {
+    is >> data._pos_vect[i];
+  }
+
+  is.seekg(598, std::ios::cur);				//skip the rest of the platform position data record
+  is.seekg(8192, std::ios::cur);			//skip to the radiometric data record
+  //is.seekg(12495744, std::ios::cur);		//skip to the 11th facility-related data record
+
+  return is;
+}
+
+AlosPalsarPlatformPositionData::AlosPalsarPlatformPositionData(const AlosPalsarPlatformPositionData& rhs):
+    AlosPalsarRecord(rhs)
+{
+  _orbit_ele_desg = rhs._orbit_ele_desg;
+
+  for (int i = 0; i < 6; i++)
+  {
+    _orbit_ele[i] = rhs._orbit_ele[i];
+  }
+
+  _ndata = rhs._ndata;
+
+  _year = rhs._year;
+
+  _month = rhs._month;
+
+  _day = rhs._day;
+
+  _gmt_day = rhs._gmt_day;
+
+  _gmt_sec = rhs._gmt_sec;
+
+  _data_int = rhs._data_int;
+
+  _ref_coord = rhs._ref_coord;
+
+  _hr_angle = rhs._hr_angle;
+
+  _alt_poserr = rhs._alt_poserr;
+
+  _crt_poserr = rhs._crt_poserr;
+
+  _rad_poserr = rhs._rad_poserr;
+
+  _alt_velerr = rhs._alt_velerr;
+
+  _crt_velerr = rhs._crt_velerr;
+
+  _rad_velerr = rhs._rad_velerr;
+
+  for (int i = 0; i < 64; i++)
+  {
+    _pos_vect[i] = rhs._pos_vect[i];
+  }
+
+}
+
+AlosPalsarPlatformPositionData& AlosPalsarPlatformPositionData::operator=(const AlosPalsarPlatformPositionData& rhs)
+{
+  _orbit_ele_desg = rhs._orbit_ele_desg;
+
+  for (int i = 0; i < 6; i++)
+  {
+    _orbit_ele[i] = rhs._orbit_ele[i];
+  }
+
+  _ndata = rhs._ndata;
+
+  _year = rhs._year;
+
+  _month = rhs._month;
+
+  _day = rhs._day;
+
+  _gmt_day = rhs._gmt_day;
+
+  _gmt_sec = rhs._gmt_sec;
+
+  _data_int = rhs._data_int;
+
+  _ref_coord = rhs._ref_coord;
+
+  _hr_angle = rhs._hr_angle;
+
+  _alt_poserr = rhs._alt_poserr;
+
+  _crt_poserr = rhs._crt_poserr;
+
+  _rad_poserr = rhs._rad_poserr;
+
+  _alt_velerr = rhs._alt_velerr;
+
+  _crt_velerr = rhs._crt_velerr;
+
+  _rad_velerr = rhs._rad_velerr;
+
+  for (int i = 0; i < 64; i++)
+  {
+    _pos_vect[i] = rhs._pos_vect[i];
+  }
+
+  return *this;
+}
+}
+
diff --git a/ossim_plugins/ossim/AlosPalsar/AlosPalsarPlatformPositionData.h b/ossim_plugins/ossim/AlosPalsar/AlosPalsarPlatformPositionData.h
new file mode 100644
index 0000000..d40ecef
--- /dev/null
+++ b/ossim_plugins/ossim/AlosPalsar/AlosPalsarPlatformPositionData.h
@@ -0,0 +1,299 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+// "Copyright Centre for Remote Imaging, Sensing and Processing"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef AlosPalsarPlatformPositionData_h
+#define AlosPalsarPlatformPositionData_h
+
+#include <iostream>
+#include <cstdlib>
+#include <AlosPalsar/AlosPalsarRecord.h>
+#include <AlosPalsar/AlosPalsarRecordHeader.h>
+
+#include <AlosPalsar/AlosPalsarPositionVectorRecord.h>
+
+namespace ossimplugins
+{
+
+/**
+ * @ingroup PlatformPositionDataRecord
+ * @brief This class is able to read a Platform position data record
+ */
+class AlosPalsarPlatformPositionData : public AlosPalsarRecord
+{
+public:
+  /**
+   * @brief Constructor
+   */
+  AlosPalsarPlatformPositionData();
+
+  /**
+   * @brief Destructor
+   */
+  virtual ~AlosPalsarPlatformPositionData();
+
+  /**
+   * @brief Copy constructor
+   */
+  AlosPalsarPlatformPositionData(const AlosPalsarPlatformPositionData& rhs);
+
+  /**
+   * @brief Copy operator
+   */
+  AlosPalsarPlatformPositionData& operator=(const AlosPalsarPlatformPositionData& rhs);
+  /**
+   * @brief This function write the AlosPalsar PlatformPositionData in a stream
+   */
+  friend std::ostream& operator<<(std::ostream& os, const AlosPalsarPlatformPositionData& data);
+
+  /**
+   * @brief This function read a AlosPalsar PlatformPositionData from a stream
+   */
+  friend std::istream& operator>>(std::istream& is, AlosPalsarPlatformPositionData& data);
+
+  /**
+   * @brief This function is able to create a new instance of the class
+   */
+  AlosPalsarRecord* Instanciate()
+  {
+    return new AlosPalsarPlatformPositionData();
+  };
+
+  /**
+   * @brief This function is able to create a new instance of the class initialised with the data of the calling instance
+   */
+  AlosPalsarRecord* Clone()
+  {
+    return new AlosPalsarPlatformPositionData(*this);
+  };
+
+  /**
+   * @brief Read the class data from a stream
+   */
+  void Read(std::istream& is)
+  {
+    is >> *this;
+  };
+
+  /**
+   * @brief Write the class to a stream
+   */
+  void Write(std::ostream& os)
+  {
+    os << *this;
+  };
+
+  /**
+   * @brief Orbital elements designator
+   */
+  std::string   get_orbit_ele_desg() const
+  {
+    return _orbit_ele_desg;
+  };
+  /**
+  * @brief Orbital elements
+  */
+  const double*   get_orbit_ele() const
+  {
+    return _orbit_ele;
+  };
+  /**
+  * @brief Number of data points
+  */
+  int  get_ndata() const
+  {
+    return _ndata;
+  };
+  /**
+  * @brief Year of data point
+  */
+  int   get_year() const
+  {
+    return _year;
+  };
+  /**
+  * @brief Month of data point
+  */
+  int   get_month() const
+  {
+    return _month;
+  };
+  /**
+  * @brief Day of data point
+  */
+  int   get_day() const
+  {
+    return _day;
+  };
+  /**
+  * @brief Day of year
+  */
+  int   get_gmt_day() const
+  {
+    return _gmt_day;
+  };
+  /**
+  * @brief Seconds of day
+  */
+  double   get_gmt_sec() const
+  {
+    return _gmt_sec;
+  };
+  /**
+  * @brief Data sampling interval
+  */
+  double   get_data_int() const
+  {
+    return _data_int;
+  };
+  /**
+  * @brief Reference coordinate system
+  */
+  std::string   get_ref_coord() const
+  {
+    return _ref_coord;
+  };
+  /**
+  * @brief Greenwich mean hour angle
+  */
+  double   get_hr_angle() const
+  {
+    return _hr_angle;
+  };
+  /**
+  * @brief Along track position error
+  */
+  double   get_alt_poserr() const
+  {
+    return _alt_poserr;
+  };
+  /**
+  * @brief Cross track position error
+  */
+  double   get_crt_poserr() const
+  {
+    return _crt_poserr;
+  };
+  /**
+  * @brief Radial position error
+  */
+  double   get_rad_poserr() const
+  {
+    return _rad_poserr;
+  };
+  /**
+  * @brief Along track velocity error
+  */
+  double   get_alt_velerr() const
+  {
+    return _alt_velerr;
+  };
+  /**
+  * @brief Cross track velocity error
+  */
+  double  get_crt_velerr() const
+  {
+    return _crt_velerr;
+  };
+  /**
+  * @brief Radial velocity error
+  */
+  double  get_rad_velerr() const
+  {
+    return _rad_velerr;
+  };
+  /**
+  * @brief Data point position/velocity
+  */
+  const AlosPalsarPositionVectorRecord* get_pos_vect() const
+  {
+    return _pos_vect;
+  };
+
+protected:
+  /**
+   * @brief Orbital elements designator
+   */
+  std::string   _orbit_ele_desg;
+  /**
+  * @brief Orbital elements
+  */
+  double   _orbit_ele[6];
+  /**
+  * @brief Number of data points
+  */
+  int   _ndata;
+  /**
+  * @brief Year of data point
+  */
+  int   _year;
+  /**
+  * @brief Month of data point
+  */
+  int   _month;
+  /**
+  * @brief Day of data point
+  */
+  int   _day;
+  /**
+  * @brief Day of year
+  */
+  int   _gmt_day;
+  /**
+  * @brief Seconds of day
+  */
+  double   _gmt_sec;
+  /**
+  * @brief Data sampling interval
+  */
+  double   _data_int;
+  /**
+  * @brief Reference coordinate system
+  */
+  std::string   _ref_coord;
+  /**
+  * @brief Greenwich mean hour angle
+  */
+  double   _hr_angle;
+  /**
+  * @brief Along track position error
+  */
+  double   _alt_poserr;
+  /**
+  * @brief Cross track position error
+  */
+  double   _crt_poserr;
+  /**
+  * @brief Radial position error
+  */
+  double   _rad_poserr;
+  /**
+  * @brief Along track velocity error
+  */
+  double   _alt_velerr;
+  /**
+  * @brief Cross track velocity error
+  */
+  double   _crt_velerr;
+  /**
+  * @brief Radial velocity error
+  */
+  double   _rad_velerr;
+  /**
+  * @brief Data point position/velocity
+  */
+  AlosPalsarPositionVectorRecord _pos_vect[64];
+
+private:
+};
+}
+#endif
+
diff --git a/ossim_plugins/ossim/AlosPalsar/AlosPalsarPositionVectorRecord.cpp b/ossim_plugins/ossim/AlosPalsar/AlosPalsarPositionVectorRecord.cpp
new file mode 100644
index 0000000..1779e49
--- /dev/null
+++ b/ossim_plugins/ossim/AlosPalsar/AlosPalsarPositionVectorRecord.cpp
@@ -0,0 +1,88 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+// "Copyright Centre for Remote Imaging, Sensing and Processing"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include <AlosPalsar/AlosPalsarPositionVectorRecord.h>
+
+namespace ossimplugins
+{
+
+
+AlosPalsarPositionVectorRecord::AlosPalsarPositionVectorRecord()
+{
+}
+
+AlosPalsarPositionVectorRecord::~AlosPalsarPositionVectorRecord()
+{
+}
+
+std::ostream& operator<<(std::ostream& os, const AlosPalsarPositionVectorRecord& data)
+{
+  for (int i = 0; i < 3; i++)
+  {
+    os << "pos[" << i << "]:" << data._pos[i] << std::endl;
+  }
+
+  for (int i = 0; i < 3; i++)
+  {
+    os << "vel[" << i << "]:" << data._vel[i] << std::endl;
+  }
+  return os;
+}
+
+std::istream& operator>>(std::istream& is, AlosPalsarPositionVectorRecord& data)
+{
+  char buf[23];
+  buf[22] = '\0';
+
+  for (int i = 0; i < 3; i++)
+  {
+    is.read(buf, 22);
+    data._pos[i] = atof(buf);
+  }
+
+  for (int i = 0; i < 3; i++)
+  {
+    is.read(buf, 22);
+    data._vel[i] = atof(buf);
+  }
+  return is;
+}
+
+AlosPalsarPositionVectorRecord::AlosPalsarPositionVectorRecord(const AlosPalsarPositionVectorRecord& rhs)
+{
+  for (int i = 0; i < 3; i++)
+  {
+    _pos[i] = rhs._pos[i];
+  }
+
+  for (int i = 0; i < 3; i++)
+  {
+    _vel[i] = rhs._vel[i];
+  }
+}
+
+AlosPalsarPositionVectorRecord& AlosPalsarPositionVectorRecord::operator=(const AlosPalsarPositionVectorRecord& rhs)
+{
+  for (int i = 0; i < 3; i++)
+  {
+    _pos[i] = rhs._pos[i];
+  }
+
+  for (int i = 0; i < 3; i++)
+  {
+    _vel[i] = rhs._vel[i];
+  }
+  return *this;
+}
+
+}
+
diff --git a/ossim_plugins/ossim/AlosPalsar/AlosPalsarPositionVectorRecord.h b/ossim_plugins/ossim/AlosPalsar/AlosPalsarPositionVectorRecord.h
new file mode 100644
index 0000000..be079e6
--- /dev/null
+++ b/ossim_plugins/ossim/AlosPalsar/AlosPalsarPositionVectorRecord.h
@@ -0,0 +1,90 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+// "Copyright Centre for Remote Imaging, Sensing and Processing"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef AlosPalsarPositionVectorRecord_h
+#define AlosPalsarPositionVectorRecord_h
+
+#include <iostream>
+#include <cstdlib>
+#include <AlosPalsar/AlosPalsarRecord.h>
+
+namespace ossimplugins
+{
+
+/**
+ * @ingroup PlatformPositionDataRecord
+ * @brief This class is able to read a position vector record
+ */
+class AlosPalsarPositionVectorRecord
+{
+public:
+  /**
+   * @brief Constructor
+   */
+  AlosPalsarPositionVectorRecord();
+
+  /**
+   * @brief Destructor
+   */
+  ~AlosPalsarPositionVectorRecord();
+
+  /**
+   * @brief Copy constructor
+   */
+  AlosPalsarPositionVectorRecord(const AlosPalsarPositionVectorRecord& rhs);
+
+  /**
+   * @brief Copy operator
+   */
+  AlosPalsarPositionVectorRecord& operator=(const AlosPalsarPositionVectorRecord& rhs);
+  /**
+   * @brief This function write the AlosPalsar PositionVectorRecord in a stream
+   */
+  friend std::ostream& operator<<(std::ostream& os, const AlosPalsarPositionVectorRecord& data);
+
+  /**
+   * @brief This function read a AlosPalsar PositionVectorRecord from a stream
+   */
+  friend std::istream& operator>>(std::istream& is, AlosPalsarPositionVectorRecord& data);
+
+  /**
+   * @brief Data point position (m)
+   */
+  const double* get_pos() const
+  {
+    return _pos;
+  };
+
+  /**
+   * @brief Data point velocity (mm/s)
+   */
+  const double* get_vel() const
+  {
+    return _vel;
+  };
+
+protected:
+  /**
+   * @brief Data point position (m)
+   */
+  double _pos[3];
+  /**
+   * @brief Data point velocity (mm/s)
+   */
+  double _vel[3];
+private:
+
+
+};
+}
+#endif
+
diff --git a/ossim_plugins/ossim/AlosPalsar/AlosPalsarRadiometricData.cpp b/ossim_plugins/ossim/AlosPalsar/AlosPalsarRadiometricData.cpp
new file mode 100644
index 0000000..4aa5adf
--- /dev/null
+++ b/ossim_plugins/ossim/AlosPalsar/AlosPalsarRadiometricData.cpp
@@ -0,0 +1,64 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+// "Copyright Centre for Remote Imaging, Sensing and Processing"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include <AlosPalsar/AlosPalsarRadiometricData.h>
+
+namespace ossimplugins
+{
+
+
+AlosPalsarRadiometricData::AlosPalsarRadiometricData() : AlosPalsarRecord("radio_data_rec")
+{
+}
+
+AlosPalsarRadiometricData::~AlosPalsarRadiometricData()
+{
+}
+
+std::ostream& operator<<(std::ostream& os, const AlosPalsarRadiometricData& data)
+{
+  os << "calibration_factor:" << data._calibration_factor << std::endl;
+
+  return os;
+}
+
+std::istream& operator>>(std::istream& is, AlosPalsarRadiometricData& data)
+{
+  char buf[9];
+
+  is.seekg(8, std::ios::cur);
+
+  is.read(buf, 8);
+  buf[8] = '\0';
+  data._calibration_factor = atof(buf);
+
+  is.seekg(9824, std::ios::cur);			//skip the rest of the radiometric data record
+  is.seekg(12477692, std::ios::cur);		//skip to the 11th facility-related data record
+
+  return is;
+}
+
+AlosPalsarRadiometricData::AlosPalsarRadiometricData(const AlosPalsarRadiometricData& rhs):
+    AlosPalsarRecord(rhs)
+{
+  _calibration_factor = rhs._calibration_factor;
+}
+
+AlosPalsarRadiometricData& AlosPalsarRadiometricData::operator=(const AlosPalsarRadiometricData& rhs)
+{
+  _calibration_factor = rhs._calibration_factor;
+
+  return *this;
+}
+
+}
+
diff --git a/ossim_plugins/ossim/AlosPalsar/AlosPalsarRadiometricData.h b/ossim_plugins/ossim/AlosPalsar/AlosPalsarRadiometricData.h
new file mode 100644
index 0000000..cedd797
--- /dev/null
+++ b/ossim_plugins/ossim/AlosPalsar/AlosPalsarRadiometricData.h
@@ -0,0 +1,111 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+// "Copyright Centre for Remote Imaging, Sensing and Processing"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef AlosPalsarRadiometricData_h
+#define AlosPalsarRadiometricData_h
+
+#include <iostream>
+#include <cstdlib>
+#include <AlosPalsar/AlosPalsarRecord.h>
+#include <AlosPalsar/AlosPalsarRecordHeader.h>
+
+
+namespace ossimplugins
+{
+
+/**
+ * @ingroup RadiometricDataRecord
+ * @brief This class is able to read a radiometric data record
+ */
+class AlosPalsarRadiometricData : public AlosPalsarRecord
+{
+public:
+  /**
+   * @brief Constructor
+   */
+  AlosPalsarRadiometricData();
+
+  /**
+   * @brief Destructor
+   */
+  virtual ~AlosPalsarRadiometricData();
+
+  /**
+   * @brief Copy constructor
+   */
+  AlosPalsarRadiometricData(const AlosPalsarRadiometricData& rhs);
+
+  /**
+   * @brief Copy operator
+   */
+  AlosPalsarRadiometricData& operator=(const AlosPalsarRadiometricData& rhs);
+  /**
+   * @brief This function writes the Alos Palsar radiometric data in a stream
+   */
+  friend std::ostream& operator<<(std::ostream& os, const AlosPalsarRadiometricData& data);
+
+  /**
+   * @brief This function reads Alos Palsar radiometric data from a stream
+   */
+  friend std::istream& operator>>(std::istream& is, AlosPalsarRadiometricData& data);
+
+  /**
+   * @brief This function is able to create a new instance of the class
+   */
+  AlosPalsarRecord* Instanciate()
+  {
+    return new AlosPalsarRadiometricData();
+  };
+
+  /**
+   * @brief This function is able to create a new instance of the class initialised with the data of the calling instance
+   */
+  AlosPalsarRecord* Clone()
+  {
+    return new AlosPalsarRadiometricData(*this);
+  };
+
+  /**
+   * @brief Read the class data from a stream
+   */
+  void Read(std::istream& is)
+  {
+    is >> *this;
+  };
+
+  /**
+   * @brief Write the class to a stream
+   */
+  void Write(std::ostream& os)
+  {
+    os << *this;
+  };
+
+  /**
+   * @brief Calibration factor
+   */
+  double   get_calibration_factor() const
+  {
+    return _calibration_factor;
+  };
+
+protected:
+  /**
+  * @brief Data sampling interval
+  */
+  double   _calibration_factor;
+
+private:
+};
+}
+#endif
+
diff --git a/ossim_plugins/ossim/AlosPalsar/AlosPalsarRecord.cpp b/ossim_plugins/ossim/AlosPalsar/AlosPalsarRecord.cpp
new file mode 100644
index 0000000..5a511ad
--- /dev/null
+++ b/ossim_plugins/ossim/AlosPalsar/AlosPalsarRecord.cpp
@@ -0,0 +1,34 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+// "Copyright Centre for Remote Imaging, Sensing and Processing"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include <AlosPalsar/AlosPalsarRecord.h>
+#include <memory.h>
+
+namespace ossimplugins
+{
+
+AlosPalsarRecord::AlosPalsarRecord(std::string mnemonic):
+    _mnemonic(mnemonic)
+{
+}
+
+AlosPalsarRecord::~AlosPalsarRecord()
+{
+}
+
+AlosPalsarRecord::AlosPalsarRecord(const AlosPalsarRecord& rhs):
+    _mnemonic(rhs._mnemonic)
+{
+}
+
+}
+
diff --git a/ossim_plugins/ossim/AlosPalsar/AlosPalsarRecord.h b/ossim_plugins/ossim/AlosPalsar/AlosPalsarRecord.h
new file mode 100644
index 0000000..260455d
--- /dev/null
+++ b/ossim_plugins/ossim/AlosPalsar/AlosPalsarRecord.h
@@ -0,0 +1,78 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+// "Copyright Centre for Remote Imaging, Sensing and Processing"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef AlosPalsarRecord_h
+#define AlosPalsarRecord_h
+
+
+#include <AlosPalsar/AlosPalsarRecordHeader.h>
+#include <iostream>
+
+namespace ossimplugins
+{
+
+/**
+ * @ingroup AlosPalsar
+ * @brief This class is the base class of all the record classes
+ */
+class AlosPalsarRecord
+{
+public:
+  /**
+   * @brief Constructor
+   * @param mnemonic Name of the record
+   */
+  AlosPalsarRecord(std::string mnemonic);
+  /**
+   * @brief Destructor
+   */
+  virtual ~AlosPalsarRecord();
+
+  /**
+   * @brief Copy constructor
+   */
+  AlosPalsarRecord(const AlosPalsarRecord& rhs);
+
+  /**
+   * @brief This function is able to create a new instance of the class
+   */
+  virtual AlosPalsarRecord* Instanciate() = 0;
+
+  /**
+   * @brief This function is able to create a new instance of the class initialised with the data of the calling instance
+   */
+  virtual AlosPalsarRecord* Clone() = 0;
+
+  /**
+   * @brief Read the class data from a stream
+   */
+  virtual void Read(std::istream& is) = 0;
+
+  /**
+   * @brief Write the class to a stream
+   */
+  virtual void Write(std::ostream& os) = 0;
+
+  std::string get_mnemonic()
+  {
+    return _mnemonic;
+  };
+
+protected:
+
+  std::string _mnemonic;
+
+private:
+};
+}
+#endif
+
diff --git a/ossim_plugins/ossim/AlosPalsar/AlosPalsarRecordFactory.cpp b/ossim_plugins/ossim/AlosPalsar/AlosPalsarRecordFactory.cpp
new file mode 100644
index 0000000..574f7d7
--- /dev/null
+++ b/ossim_plugins/ossim/AlosPalsar/AlosPalsarRecordFactory.cpp
@@ -0,0 +1,53 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+// "Copyright Centre for Remote Imaging, Sensing and Processing"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include <AlosPalsar/AlosPalsarRecordFactory.h>
+#include <ossim/base/ossimTrace.h>
+
+// Static trace for debugging
+static ossimTrace traceDebug("AlosPalsarRecordFactory:debug");
+
+namespace ossimplugins
+{
+
+AlosPalsarRecordFactory::AlosPalsarRecordFactory()
+{
+}
+
+AlosPalsarRecordFactory::~AlosPalsarRecordFactory()
+{
+}
+
+AlosPalsarRecord* AlosPalsarRecordFactory::Instanciate(int id)
+{
+  if (traceDebug())
+  {
+    ossimNotify(ossimNotifyLevel_DEBUG) << "Intanciate AlosPalsar record:" << id << "\n";
+  }
+  AlosPalsarRecord* record = _availableRecords[id];
+  if (record == NULL)
+  {
+    return NULL;
+  }
+  else
+  {
+    return record->Instanciate();
+  }
+}
+
+void AlosPalsarRecordFactory::RegisterRecord(int id, AlosPalsarRecord * record)
+{
+  _availableRecords[id] = record;
+}
+
+}
+
diff --git a/ossim_plugins/ossim/AlosPalsar/AlosPalsarRecordFactory.h b/ossim_plugins/ossim/AlosPalsar/AlosPalsarRecordFactory.h
new file mode 100644
index 0000000..fc51653
--- /dev/null
+++ b/ossim_plugins/ossim/AlosPalsar/AlosPalsarRecordFactory.h
@@ -0,0 +1,63 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+// "Copyright Centre for Remote Imaging, Sensing and Processing"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef AlosPalsarRecordFactory_h
+#define AlosPalsarRecordFactory_h
+
+
+#include <AlosPalsar/AlosPalsarRecordHeader.h>
+#include <AlosPalsar/AlosPalsarRecord.h>
+#include <map>
+
+namespace ossimplugins
+{
+
+/**
+ * @ingroup AlosPalsar
+ * @brief This class is a facory able to construct Record base classes given the id of the record wanted
+ */
+class AlosPalsarRecordFactory
+{
+public:
+  /**
+   * @brief Constructor
+   */
+  AlosPalsarRecordFactory();
+  /**
+   * @brief Destructor
+   */
+  ~AlosPalsarRecordFactory();
+
+  /**
+   * @brief Add a new Record type available in this factory
+   * @param record Record to add in the factory
+   * @param id Id of the new avalaible Record
+   */
+  void RegisterRecord(int id, AlosPalsarRecord * record);
+
+  /**
+   * @brief Instanciate a new Record
+   * @param id Id of the Record we want to instanciate
+   */
+  AlosPalsarRecord* Instanciate(int id) ;
+protected:
+
+  /**
+   * @brief Contain all the available Records for the factory
+   */
+  std::map<int, AlosPalsarRecord*> _availableRecords;
+
+private:
+};
+}
+#endif
+
diff --git a/ossim_plugins/ossim/AlosPalsar/AlosPalsarRecordHeader.cpp b/ossim_plugins/ossim/AlosPalsar/AlosPalsarRecordHeader.cpp
new file mode 100644
index 0000000..b6074da
--- /dev/null
+++ b/ossim_plugins/ossim/AlosPalsar/AlosPalsarRecordHeader.cpp
@@ -0,0 +1,84 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+// "Copyright Centre for Remote Imaging, Sensing and Processing"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include <AlosPalsar/AlosPalsarRecordHeader.h>
+
+namespace ossimplugins
+{
+
+
+AlosPalsarRecordHeader::AlosPalsarRecordHeader()
+{
+}
+
+AlosPalsarRecordHeader::~AlosPalsarRecordHeader()
+{
+}
+
+std::ostream& operator<<(std::ostream& os, const AlosPalsarRecordHeader& data)
+{
+  os << "record_sequence_number:" << data._rec_seq << std::endl;
+  os << "first_record_sub-type:" << (int)data._rec_sub1 << std::endl;
+  os << "record_type_code:" << (int)data._rec_type << std::endl;
+  os << "second_record_sub-type:" << (int)data._rec_sub2 << std::endl;
+  os << "third_record_sub-type:" << (int)data._rec_sub3 << std::endl;
+  os << "length:" << data._length << std::endl;
+  return os;
+}
+
+std::istream& operator>>(std::istream& is, AlosPalsarRecordHeader& data)
+{
+  is.read((char*)&(data._rec_seq), 4); // TODO Change dangerous C-style cast to static cast.
+  data.SwitchEndian(data._rec_seq);
+  is.read((char*)&(data._rec_sub1), 1);
+  is.read((char*)&(data._rec_type), 1);
+  is.read((char*)&(data._rec_sub2), 1);
+  is.read((char*)&(data._rec_sub3), 1);
+  is.read((char*)&(data._length), 4);
+  data.SwitchEndian(data._length);
+  return is;
+}
+
+AlosPalsarRecordHeader::AlosPalsarRecordHeader(const AlosPalsarRecordHeader& rhs):
+    _rec_seq(rhs._rec_seq),
+    _rec_sub1(rhs._rec_sub1),
+    _rec_type(rhs._rec_type),
+    _rec_sub2(rhs._rec_sub2),
+    _rec_sub3(rhs._rec_sub3)
+{
+}
+
+AlosPalsarRecordHeader& AlosPalsarRecordHeader::operator=(const AlosPalsarRecordHeader& rhs)
+{
+  _rec_seq = rhs._rec_seq;
+  _rec_sub1 = rhs._rec_sub1;
+  _rec_type = rhs._rec_type;
+  _rec_sub2 = rhs._rec_sub2;
+  _rec_sub3 = rhs._rec_sub3;
+  return *this;
+}
+
+void AlosPalsarRecordHeader::SwitchEndian(unsigned int& value)
+{
+  char buffer[4];
+  char res[4];
+
+  memcpy(buffer, &value, 4);
+  res[0] = buffer[3];
+  res[1] = buffer[2];
+  res[2] = buffer[1];
+  res[3] = buffer[0];
+
+  memcpy(&value, res, 4);
+}
+}
+
diff --git a/ossim_plugins/ossim/AlosPalsar/AlosPalsarRecordHeader.h b/ossim_plugins/ossim/AlosPalsar/AlosPalsarRecordHeader.h
new file mode 100644
index 0000000..f912443
--- /dev/null
+++ b/ossim_plugins/ossim/AlosPalsar/AlosPalsarRecordHeader.h
@@ -0,0 +1,142 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+// "Copyright Centre for Remote Imaging, Sensing and Processing"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef AlosPalsarRecordHeader_h
+#define AlosPalsarRecordHeader_h
+
+#include<iostream>
+#include<cstring>
+
+namespace ossimplugins
+{
+
+/**
+ * @ingroup AlosPalsar
+ * @brief This class is able to read a record header
+ */
+class AlosPalsarRecordHeader
+{
+public:
+  /**
+   * @brief Constructor
+   */
+  AlosPalsarRecordHeader();
+
+  /**
+   * @brief Destructor
+   */
+  ~AlosPalsarRecordHeader();
+
+  /**
+   * @brief Copy constructor
+   */
+  AlosPalsarRecordHeader(const AlosPalsarRecordHeader& rhs);
+
+  /**
+   * @brief Copy operator
+   */
+  AlosPalsarRecordHeader& operator=(const AlosPalsarRecordHeader& rhs);
+  /**
+   * @brief This function write the RecordHeader in a stream
+   */
+  friend std::ostream& operator<<(std::ostream& os, const AlosPalsarRecordHeader& data);
+
+  /**
+   * @brief This function read a RecordHeader from a stream
+   */
+  friend std::istream& operator>>(std::istream& is, AlosPalsarRecordHeader& data);
+
+  /**
+   * @brief Record sequence number
+   */
+  unsigned int  get_rec_seq()
+  {
+    return _rec_seq;
+  };
+
+  /**
+   * @brief First record sub-type code
+   */
+  unsigned char   get_rec_sub1()
+  {
+    return _rec_sub1;
+  };
+
+  /**
+   * @brief Record type code
+   */
+  unsigned char   get_rec_type()
+  {
+    return _rec_type;
+  };
+
+  /**
+   * @brief Second record sub-type code
+   */
+  unsigned char   get_rec_sub2()
+  {
+    return _rec_sub2;
+  };
+
+  /**
+   * @brief Third record sub-type code
+   */
+  unsigned char   get_rec_sub3()
+  {
+    return _rec_sub3;
+  };
+
+  /**
+   * @brief Length of this record (in bytes)
+   */
+  unsigned int get_length()
+  {
+    return _length;
+  };
+protected:
+
+  /**
+   * @brief This function switch the LSB value and the MSB value of the parameter
+   */
+  void SwitchEndian(unsigned int& value);
+
+  /**
+   * @brief Record sequence number
+   */
+  unsigned int  _rec_seq;
+  /**
+   * @brief First record sub-type code
+   */
+  unsigned char   _rec_sub1;
+  /**
+   * @brief Record type code
+   */
+  unsigned char   _rec_type;
+  /**
+   * @brief Second record sub-type code
+   */
+  unsigned char   _rec_sub2;
+  /**
+   * @brief Third record sub-type code
+   */
+  unsigned char   _rec_sub3;
+  /**
+   * @brief Length of this record (in bytes)
+   */
+  unsigned int  _length;
+private:
+
+
+};
+}
+#endif
+
diff --git a/ossim_plugins/ossim/AlosPalsar/AlosPalsarSignalData.cpp b/ossim_plugins/ossim/AlosPalsar/AlosPalsarSignalData.cpp
new file mode 100644
index 0000000..4546ee6
--- /dev/null
+++ b/ossim_plugins/ossim/AlosPalsar/AlosPalsarSignalData.cpp
@@ -0,0 +1,195 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+// "Copyright Centre for Remote Imaging, Sensing and Processing"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include <AlosPalsar/AlosPalsarSignalData.h>
+#include <ossim/base/ossimConstants.h>
+#include <ossim/base/ossimEndian.h>
+
+
+namespace ossimplugins
+{
+
+AlosPalsarSignalData::AlosPalsarSignalData() : AlosPalsarRecord("sar_sig_dat_rec")
+{
+}
+
+AlosPalsarSignalData::~AlosPalsarSignalData()
+{
+}
+
+std::ostream& operator<<(std::ostream& os, const AlosPalsarSignalData& data)
+{
+  os << "_pulse_repetition_frequency:"
+  << data._pulse_repetition_frequency << std::endl;
+  os << "_slant_range_to_1st_data_sample:"
+  << data._slant_range_to_1st_data_sample << std::endl;
+
+  return os;
+}
+
+std::istream& operator>>(std::istream& is, AlosPalsarSignalData& data)
+{
+  ossim_uint16 tmpuint16;
+  ossim_uint32 tmpuint32;
+  ossimEndian oe;
+
+  is.read(reinterpret_cast<char*>(&tmpuint32), 4);
+  if (oe.getSystemEndianType() == OSSIM_LITTLE_ENDIAN)
+  {
+    oe.swap(tmpuint32);
+  }
+//  std::cout << "Data line number = " << tmpuint32 << std::endl;
+
+  is.read(reinterpret_cast<char*>(&tmpuint32), 4);
+  if (oe.getSystemEndianType() == OSSIM_LITTLE_ENDIAN)
+  {
+    oe.swap(tmpuint32);
+  }
+//  std::cout << "Data record index = " << tmpuint32 << std::endl;
+
+  is.read(reinterpret_cast<char*>(&tmpuint32), 4);
+  if (oe.getSystemEndianType() == OSSIM_LITTLE_ENDIAN)
+  {
+    oe.swap(tmpuint32);
+  }
+//  std::cout << "Actual count of left-fill pixels = " << tmpuint32 << std::endl;
+
+  is.read(reinterpret_cast<char*>(&tmpuint32), 4);
+  if (oe.getSystemEndianType() == OSSIM_LITTLE_ENDIAN)
+  {
+    oe.swap(tmpuint32);
+  }
+//  std::cout << "Actual count of data pixels = " << tmpuint32 << std::endl;
+
+  is.read(reinterpret_cast<char*>(&tmpuint32), 4);
+  if (oe.getSystemEndianType() == OSSIM_LITTLE_ENDIAN)
+  {
+    oe.swap(tmpuint32);
+  }
+//  std::cout << "Actual count of right-fill pixels = " << tmpuint32 << std::endl;
+
+  is.read(reinterpret_cast<char*>(&tmpuint32), 4);
+  if (oe.getSystemEndianType() == OSSIM_LITTLE_ENDIAN)
+  {
+    oe.swap(tmpuint32);
+  }
+//  std::cout << "Sensor parameters update flag = " << tmpuint32 << std::endl;
+
+  is.read(reinterpret_cast<char*>(&tmpuint32), 4);
+  if (oe.getSystemEndianType() == OSSIM_LITTLE_ENDIAN)
+  {
+    oe.swap(tmpuint32);
+  }
+//  std::cout << "Scene start year = " << tmpuint32 << std::endl;
+
+  is.read(reinterpret_cast<char*>(&tmpuint32), 4);
+  if (oe.getSystemEndianType() == OSSIM_LITTLE_ENDIAN)
+  {
+    oe.swap(tmpuint32);
+  }
+//  std::cout << "Scene start day of year = " << tmpuint32 << std::endl;
+
+  is.read(reinterpret_cast<char*>(&tmpuint32), 4);
+  if (oe.getSystemEndianType() == OSSIM_LITTLE_ENDIAN)
+  {
+    oe.swap(tmpuint32);
+  }
+//  std::cout << "Sensor acquisition milliseconds of day = " << tmpuint32 << std::endl;
+
+  is.read(reinterpret_cast<char*>(&tmpuint16), 2);
+  if (oe.getSystemEndianType() == OSSIM_LITTLE_ENDIAN)
+  {
+    oe.swap(tmpuint16);
+  }
+//  std::cout << "SAR channel indicator = " << tmpuint16 << std::endl;
+
+  is.read(reinterpret_cast<char*>(&tmpuint16), 2);
+  if (oe.getSystemEndianType() == OSSIM_LITTLE_ENDIAN)
+  {
+    oe.swap(tmpuint16);
+  }
+//  std::cout << "SAR channel code = " << tmpuint16 << std::endl;
+
+  is.read(reinterpret_cast<char*>(&tmpuint16), 2);
+  if (oe.getSystemEndianType() == OSSIM_LITTLE_ENDIAN)
+  {
+    oe.swap(tmpuint16);
+  }
+//  std::cout << "Transmitted polarization = " << tmpuint16 << std::endl;
+
+  is.read(reinterpret_cast<char*>(&tmpuint16), 2);
+  if (oe.getSystemEndianType() == OSSIM_LITTLE_ENDIAN)
+  {
+    oe.swap(tmpuint16);
+  }
+//  std::cout << "Received polarization = " << tmpuint16 << std::endl;
+
+  is.read(reinterpret_cast<char*>(&tmpuint32), 4);
+  if (oe.getSystemEndianType() == OSSIM_LITTLE_ENDIAN)
+  {
+    oe.swap(tmpuint32);
+  }
+//  std::cout << "PRF (mHz) = " << tmpuint32 << std::endl;
+  data._pulse_repetition_frequency = static_cast<int>(tmpuint32);
+
+  is.read(reinterpret_cast<char*>(&tmpuint32), 4);
+  if (oe.getSystemEndianType() == OSSIM_LITTLE_ENDIAN)
+  {
+    oe.swap(tmpuint32);
+  }
+//  std::cout << "Scan ID for SCAN SAR mode = " << tmpuint32 << std::endl;
+
+  is.read(reinterpret_cast<char*>(&tmpuint16), 2);
+  if (oe.getSystemEndianType() == OSSIM_LITTLE_ENDIAN)
+  {
+    oe.swap(tmpuint16);
+  }
+//  std::cout << "Onboard range compressed flag = " << tmpuint16 << std::endl;
+
+  is.seekg(50, std::ios_base::cur);
+
+  is.read(reinterpret_cast<char*>(&tmpuint32), 4);
+  if (oe.getSystemEndianType() == OSSIM_LITTLE_ENDIAN)
+  {
+    oe.swap(tmpuint32);
+  }
+//  std::cout << "Slant range to 1st data sample (m) = " << tmpuint32 << std::endl;
+  data._slant_range_to_1st_data_sample = static_cast<int>(tmpuint32);
+
+  is.read(reinterpret_cast<char*>(&tmpuint32), 4);
+  if (oe.getSystemEndianType() == OSSIM_LITTLE_ENDIAN)
+  {
+    oe.swap(tmpuint32);
+  }
+//  std::cout << "Data record window position = " << tmpuint32 << std::endl;
+
+//  std::cout << std::endl << "File pointer location = " << is.tellg() << std::endl;
+//  std::cout << std::endl;
+
+  return is;
+}
+
+AlosPalsarSignalData::AlosPalsarSignalData(const AlosPalsarSignalData& rhs):
+    AlosPalsarRecord(rhs),
+    _pulse_repetition_frequency(rhs._pulse_repetition_frequency),
+    _slant_range_to_1st_data_sample(rhs._slant_range_to_1st_data_sample)
+{
+}
+
+AlosPalsarSignalData& AlosPalsarSignalData::operator=(const AlosPalsarSignalData& rhs)
+{
+  _pulse_repetition_frequency = rhs._pulse_repetition_frequency;
+  _slant_range_to_1st_data_sample = rhs._slant_range_to_1st_data_sample;
+  return *this;
+}
+}
+
diff --git a/ossim_plugins/ossim/AlosPalsar/AlosPalsarSignalData.h b/ossim_plugins/ossim/AlosPalsar/AlosPalsarSignalData.h
new file mode 100644
index 0000000..ba9a93a
--- /dev/null
+++ b/ossim_plugins/ossim/AlosPalsar/AlosPalsarSignalData.h
@@ -0,0 +1,122 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+// "Copyright Centre for Remote Imaging, Sensing and Processing"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef AlosPalsarSignalData_h
+#define AlosPalsarSignalData_h
+
+
+#include <iostream>
+#include <cstdlib>
+#include <AlosPalsar/AlosPalsarRecordHeader.h>
+#include <AlosPalsar/AlosPalsarRecord.h>
+
+namespace ossimplugins
+{
+
+/**
+ * @ingroup SARDataAlosPalsarSignalDataRecord
+ * @brief This class is able to read the header of the Signal Data Records of the image file
+ */
+class AlosPalsarSignalData : public AlosPalsarRecord
+{
+public:
+  /**
+   * @brief Constructor
+   */
+  AlosPalsarSignalData();
+  /**
+   * @brief Destructor
+   */
+  virtual ~AlosPalsarSignalData();
+
+  /**
+   * @brief This function writes AlosPalsarSignalData to a stream
+   */
+  friend std::ostream& operator<<(std::ostream& os, const AlosPalsarSignalData& data);
+
+  /**
+   * @brief This function reads to AlosPalsarSignalData from a stream
+   */
+  friend std::istream& operator>>(std::istream& is, AlosPalsarSignalData& data);
+
+  /**
+   * @brief Copy constructor
+   */
+  AlosPalsarSignalData(const AlosPalsarSignalData& rhs);
+
+  /**
+   * @brief Copy operator
+   */
+  AlosPalsarSignalData& operator=(const AlosPalsarSignalData& rhs);
+
+  /**
+   * @brief This function is able to create a new instance of the class
+   */
+  AlosPalsarRecord* Instanciate()
+  {
+    return new AlosPalsarSignalData();
+  };
+
+  /**
+   * @brief This function is able to create a new instance of the class initialised with the data of the calling instance
+   */
+  AlosPalsarRecord* Clone()
+  {
+    return new AlosPalsarSignalData(*this);
+  };
+
+  /**
+   * @brief Read the class data from a stream
+   */
+  void Read(std::istream& is)
+  {
+    is >> *this;
+  };
+
+  /**
+   * @brief Write the class to a stream
+   */
+  void Write(std::ostream& os)
+  {
+    os << *this;
+  };
+
+
+  int get_pulse_repetition_frequency() const
+  {
+    return _pulse_repetition_frequency;
+  };
+
+  int get_slant_range_to_1st_data_sample() const
+  {
+    return _slant_range_to_1st_data_sample;
+  };
+
+
+protected:
+
+  /**
+  * @brief pulse_repetition_frequency
+  */
+  int _pulse_repetition_frequency;
+
+  /**
+  * @brief slant_range_to_1st_data_sample
+  */
+  int _slant_range_to_1st_data_sample;
+
+private:
+};
+
+}
+#endif
+
diff --git a/ossim_plugins/ossim/CMakeLists.txt b/ossim_plugins/ossim/CMakeLists.txt
new file mode 100644
index 0000000..5dbb97f
--- /dev/null
+++ b/ossim_plugins/ossim/CMakeLists.txt
@@ -0,0 +1,38 @@
+set(LIB_NAME ossim_plugin)
+MESSAGE( "************** LIBRARY SETUP FOR ossim_plugin******************")
+
+# Include ossim cmake stuff:
+include(OssimVersion)
+include(OssimCommonVariables)
+include(OssimUtilities)
+
+find_package(TIFF)
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
+INCLUDE_DIRECTORIES(${OPENTHREADS_INCLUDE_DIR})
+INCLUDE_DIRECTORIES(${TIFF_INCLUDE_DIR})
+INCLUDE_DIRECTORIES(${GEOTIFF_INCLUDE_DIR})
+
+FILE(GLOB_RECURSE OSSIMPLUGIN_SRCS *.cpp)
+FILE(GLOB_RECURSE OSSIMPLUGIN_HEADERS *.h)
+
+####
+# OSSIMPLUGINSMAKINGDLL controls dll linkage on windows.  
+# Adding this sets OSSIM_PLUGINS_DLL #define TO "__declspec(dllexport)".
+###
+add_definitions("-DOSSIMPLUGINSMAKINGDLL")
+
+# Adjust the install library path:
+if(OSSIM_INSTALL_PLUGINS_WITH_VERSION)
+   set(INSTALL_LIBRARY_DIR   "${INSTALL_LIBRARY_DIR}/ossim-${OSSIM_VERSION}/plugins")
+else(OSSIM_INSTALL_PLUGINS_WITH_VERSION)
+   set(INSTALL_LIBRARY_DIR   "${INSTALL_LIBRARY_DIR}/ossim/plugins")
+endif(OSSIM_INSTALL_PLUGINS_WITH_VERSION)
+
+OSSIM_LINK_LIBRARY(${LIB_NAME}
+                   COMPONENT_NAME ossim TYPE "${OSSIM_PLUGIN_LINK_TYPE}"
+		   LIBRARIES ${OSSIM_LIBRARY} ${GEOTIFF_LIBRARY} ${TIFF_LIBARY}
+                   HEADERS "${OSSIMPLUGIN_HEADERS}"
+		   SOURCE_FILES "${OSSIMPLUGIN_SRCS}"
+                   INSTALL_LIB)
+
+
diff --git a/ossim_plugins/ossim/EnvisatAsar/AntennaElevationPatterns.cpp b/ossim_plugins/ossim/EnvisatAsar/AntennaElevationPatterns.cpp
new file mode 100644
index 0000000..9b975e5
--- /dev/null
+++ b/ossim_plugins/ossim/EnvisatAsar/AntennaElevationPatterns.cpp
@@ -0,0 +1,97 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include <EnvisatAsar/AntennaElevationPatterns.h>
+
+namespace ossimplugins
+{
+   AntennaElevationPatterns::AntennaElevationPatterns() : EnvisatAsarRecord("AntennaElevationPatterns_rec")
+   {
+   }
+
+   AntennaElevationPatterns::~AntennaElevationPatterns()
+   {
+   }
+
+
+   std::ostream& operator<<(std::ostream& os, const AntennaElevationPatterns& data)
+   {
+      os<<"zero_doppler_time:"<<data._zero_doppler_time.c_str()<<std::endl;
+
+      os<<"attach_flag:"<<data._attach_flag<<std::endl;
+
+      os<<"swath:"<<data._swath.c_str()<<std::endl;
+
+      for (int i = 0; i<33; i++) {
+         os<<"elevation pattern:"<<data._elevation_pattern[i]<<std::endl;
+      }
+
+      return os;
+
+   }
+
+   std::istream& operator>>(std::istream& is, AntennaElevationPatterns& data)
+   {
+      char buf16[17];
+      buf16[16]='\0';
+      char buf12[13];
+      buf12[12] = '\0';
+      char buf3[4];
+      buf3[3] = '\0';
+      // char buf2[3];
+      // buf2[2] = '\0';
+//	char buf1[1]; // avoid not used warning
+
+      is.read(buf12,12);
+      data._zero_doppler_time = buf12;
+
+      is.read((char*)&(data._attach_flag),1);
+
+      is.read(buf3,3);
+      data._swath = buf3;
+
+      for (int i = 0; i<33; i++) {
+         is.read((char*)&(data._elevation_pattern[i]),4);
+         data.SwitchEndian(data._elevation_pattern[i]);
+      }
+
+      is.read(buf16,14);
+
+      return is;
+
+   }
+
+   AntennaElevationPatterns::AntennaElevationPatterns(const AntennaElevationPatterns& rhs):
+      EnvisatAsarRecord(rhs),
+      _zero_doppler_time(rhs._zero_doppler_time),
+      _attach_flag(rhs._attach_flag),
+      _swath(rhs._swath)
+   {
+      for (int i = 0; i<33; i++) {
+         _elevation_pattern[i] = rhs._elevation_pattern[i];
+      }
+   }
+
+
+   AntennaElevationPatterns& AntennaElevationPatterns::operator=(const AntennaElevationPatterns& rhs)
+   {
+      _zero_doppler_time = rhs._zero_doppler_time;
+      _attach_flag = rhs._attach_flag;
+      _swath = rhs._swath;
+
+      for (int i = 0; i<33; i++) {
+         _elevation_pattern[i] = rhs._elevation_pattern[i];
+      }
+
+      return *this;
+   }
+}
+
diff --git a/ossim_plugins/ossim/EnvisatAsar/AntennaElevationPatterns.h b/ossim_plugins/ossim/EnvisatAsar/AntennaElevationPatterns.h
new file mode 100644
index 0000000..982302c
--- /dev/null
+++ b/ossim_plugins/ossim/EnvisatAsar/AntennaElevationPatterns.h
@@ -0,0 +1,146 @@
+
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef AntennaElevationPatterns_h
+#define AntennaElevationPatterns_h
+
+#include <iostream>
+#include <EnvisatAsar/EnvisatAsarRecord.h>
+
+namespace ossimplugins
+{
+/**
+ * @ingroup AntennaElevationPatternsRecord
+ * @brief This class is able to read the ASAR AntennaElevationPatterns record
+ */
+class AntennaElevationPatterns : public EnvisatAsarRecord
+{
+public:
+  /**
+   * @brief Constructor
+   */
+  AntennaElevationPatterns();
+
+  /**
+   * @brief Destructor
+   */
+  virtual ~AntennaElevationPatterns();
+
+  /**
+   * @brief This function writes the AntennaElevationPatterns in a stream
+   */
+  friend std::ostream& operator<<(std::ostream& os, const AntennaElevationPatterns& data);
+
+  /**
+   * @brief This function reads a AntennaElevationPatterns from a stream
+   */
+  friend std::istream& operator>>(std::istream& is, AntennaElevationPatterns& data);
+
+  /**
+   * @brief Copy constructor
+   */
+  AntennaElevationPatterns(const AntennaElevationPatterns& rhs);
+
+  /**
+   * @brief Copy operator
+   */
+  AntennaElevationPatterns& operator=(const AntennaElevationPatterns& rhs);
+
+  /**
+   * @brief This function is able to create a new instance of the class
+   */
+  EnvisatAsarRecord* Instanciate()
+  {
+    return new AntennaElevationPatterns();
+  };
+
+  /**
+   * @brief This function is able to create a new instance of the class initialised with the data of the calling instance
+   */
+  EnvisatAsarRecord* Clone()
+  {
+    return new AntennaElevationPatterns(*this);
+  };
+
+  /**
+   * @brief Reads the class data from a stream
+   */
+  void Read(std::istream& is)
+  {
+    is>>*this;
+  };
+
+  /**
+   * @brief Writes the class to a stream
+   */
+  void Write(std::ostream& os)
+  {
+    os<<*this;
+  };
+
+
+  /**
+  * @brief zero_doppler_time
+  */
+  std::string   get_zero_doppler_time()
+  {
+    return _zero_doppler_time;
+  };
+  /**
+  * @brief attach_flag
+  */
+  bool   get_attach_flag()
+  {
+    return _attach_flag;
+  };
+  /**
+  * @brief swath
+  */
+  std::string    get_swath()
+  {
+    return _swath;
+  };
+  /**
+  * @brief Elevation Pattern
+  */
+  float *    get_elevation_pattern()
+  {
+    return _elevation_pattern;
+  };
+
+
+  /**
+  * @brief zero_doppler_time
+  */
+  std::string   _zero_doppler_time;
+  /**
+  * @brief attach_flag
+  */
+  bool   _attach_flag;
+  /**
+  * @brief swath
+  */
+  std::string   _swath;
+  /**
+  * @brief Elevation Pattern
+  */
+  float  _elevation_pattern[33];
+
+
+private:
+
+};
+}
+#endif
+
+
+
diff --git a/ossim_plugins/ossim/EnvisatAsar/ChirpParameters.cpp b/ossim_plugins/ossim/EnvisatAsar/ChirpParameters.cpp
new file mode 100644
index 0000000..f1b728f
--- /dev/null
+++ b/ossim_plugins/ossim/EnvisatAsar/ChirpParameters.cpp
@@ -0,0 +1,200 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include <EnvisatAsar/ChirpParameters.h>
+
+namespace ossimplugins
+{
+   ChirpParameters::ChirpParameters() : EnvisatAsarRecord("ChirpParameters_rec")
+   {
+   }
+
+   ChirpParameters::~ChirpParameters()
+   {
+   }
+
+
+   std::ostream& operator<<(std::ostream& os, const ChirpParameters& data)
+   {
+      os<<"zero_doppler_time:"<<data._zero_doppler_time.c_str()<<std::endl;
+
+      os<<"attach_flag:"<<data._attach_flag<<std::endl;
+
+      os<<"swath:"<<data._swath.c_str()<<std::endl;
+
+      os<<"polar:"<<data._polar.c_str()<<std::endl;
+
+      os<<"chirp_width:"<<data._chirp_width<<std::endl;
+
+      os<<"chirp_sidelobe:"<<data._chirp_sidelobe<<std::endl;
+
+      os<<"chirp_islr:"<<data._chirp_islr<<std::endl;
+
+      os<<"chirp_peak_loc:"<<data._chirp_peak_loc<<std::endl;
+
+      os<<"re_chirp_power:"<<data._re_chirp_power<<std::endl;
+
+      os<<"elev_chirp_power:"<<data._elev_chirp_power<<std::endl;
+
+      os<<"chirp_quality_flag:"<<data._chirp_quality_flag<<std::endl;
+
+      os<<"ref_chirp_power:"<<data._ref_chirp_power<<std::endl;
+
+      os<<"normalisation_source:"<<data._normalisation_source.c_str()<<std::endl;
+
+      for (int i = 0 ; i<352; i++) {
+         os<<"cal_pulse_info["<<i<<"]:"<<data._cal_pulse_info[i]<<std::endl;
+      }
+
+      return os;
+
+   }
+
+   std::istream& operator>>(std::istream& is, ChirpParameters& data)
+   {
+      // char buf64[65];
+      // buf64[64] = '\0';
+      // char buf32[33];
+      // buf32[32] = '\0';
+      // char buf27[28];
+      // buf27[27] = '\0';
+      // char buf20[21];
+      // buf20[20] = '\0';
+      char buf16[17];
+      buf16[16]='\0';
+      // char buf15[16];
+      // buf15[15] = '\0';
+      // char buf14[15];
+      // buf14[14] = '\0';
+      // char buf13[14];
+      // buf13[13] = '\0';
+      char buf12[13];
+      buf12[12] = '\0';
+      // char buf11[12];
+      // buf11[11] = '\0';
+      // char buf10[11];
+      // buf10[10] = '\0';
+      // char buf9[10];
+      // buf9[9] = '\0';
+      // char buf8[9];
+      // buf8[8] = '\0';
+      char buf7[8];
+      buf7[7] = '\0';
+      // char buf6[7];
+      // buf6[6] = '\0';
+      // char buf5[6];
+      // buf5[5] = '\0';
+      char buf4[5];
+      buf4[4] = '\0';
+      char buf3[4];
+      buf3[3] = '\0';
+      // char buf2[3];
+      // buf2[2] = '\0';
+//	char buf1[1]; // not used avoid warning
+
+      is.read(buf12,12);
+      data._zero_doppler_time = buf12;
+
+      is.read((char*)&(data._attach_flag),1);
+
+      is.read(buf3,3);
+      data._swath = buf3;
+
+      is.read(buf3,3);
+      data._polar = buf3;
+
+      is.read((char*)&(data._chirp_width),4);
+      data.SwitchEndian(data._chirp_width);
+
+      is.read((char*)&(data._chirp_sidelobe),4);
+      data.SwitchEndian(data._chirp_sidelobe);
+
+      is.read((char*)&(data._chirp_islr),4);
+      data.SwitchEndian(data._chirp_islr);
+
+      is.read((char*)&(data._chirp_peak_loc),4);
+      data.SwitchEndian(data._chirp_peak_loc);
+
+      is.read((char*)&(data._re_chirp_power),4);
+      data.SwitchEndian(data._re_chirp_power);
+
+      is.read((char*)&(data._elev_chirp_power),4);
+      data.SwitchEndian(data._elev_chirp_power);
+
+      is.read((char*)&(data._chirp_quality_flag),1);
+      data.SwitchEndian(data._chirp_quality_flag);
+
+      is.read((char*)&(data._ref_chirp_power),4);
+      data.SwitchEndian(data._ref_chirp_power);
+
+      is.read(buf7,7);
+      data._normalisation_source = buf7;
+
+      is.read(buf4,4);
+
+      for (int i = 0; i<352; i++) {
+         is.read((char*)&(data._cal_pulse_info[i]),4);
+         data.SwitchEndian(data._cal_pulse_info[i]);
+      }
+
+      is.read(buf16,16);
+
+      return is;
+
+   }
+
+   ChirpParameters::ChirpParameters(const ChirpParameters& rhs):
+      EnvisatAsarRecord(rhs),
+      _zero_doppler_time(rhs._zero_doppler_time),
+      _attach_flag(rhs._attach_flag),
+      _swath(rhs._swath),
+      _polar(rhs._polar),
+      _chirp_width(rhs._chirp_width),
+      _chirp_sidelobe(rhs._chirp_sidelobe),
+      _chirp_islr(rhs._chirp_islr),
+      _chirp_peak_loc(rhs._chirp_peak_loc),
+      _re_chirp_power(rhs._re_chirp_power),
+      _elev_chirp_power(rhs._elev_chirp_power),
+      _chirp_quality_flag(rhs._chirp_quality_flag),
+      _ref_chirp_power(rhs._ref_chirp_power),
+      _normalisation_source(rhs._normalisation_source)
+   {
+      for (int i = 0; i<352; i++) {
+         _cal_pulse_info[i] = rhs._cal_pulse_info[i];
+      }
+   }
+
+
+   ChirpParameters& ChirpParameters::operator=(const ChirpParameters& rhs)
+   {
+      _zero_doppler_time = rhs._zero_doppler_time;
+      _attach_flag = rhs._attach_flag;
+      _swath = rhs._swath;
+      _polar = rhs._polar;
+      _chirp_width = rhs._chirp_width;
+      _chirp_sidelobe = rhs._chirp_sidelobe;
+      _chirp_islr = rhs._chirp_islr;
+      _chirp_peak_loc = rhs._chirp_peak_loc;
+      _re_chirp_power = rhs._re_chirp_power;
+      _elev_chirp_power = rhs._elev_chirp_power;
+      _chirp_quality_flag = rhs._chirp_quality_flag;
+      _ref_chirp_power = rhs._ref_chirp_power;
+      _normalisation_source = rhs._normalisation_source;
+
+      for (int i = 0; i<352; i++) {
+         _cal_pulse_info[i] = rhs._cal_pulse_info[i];
+      }
+
+      return *this;
+   }
+}
+
+
diff --git a/ossim_plugins/ossim/EnvisatAsar/ChirpParameters.h b/ossim_plugins/ossim/EnvisatAsar/ChirpParameters.h
new file mode 100644
index 0000000..df02840
--- /dev/null
+++ b/ossim_plugins/ossim/EnvisatAsar/ChirpParameters.h
@@ -0,0 +1,254 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef ChirpParameters_h
+#define ChirpParameters_h
+
+#include <iostream>
+#include <EnvisatAsar/EnvisatAsarRecord.h>
+
+namespace ossimplugins
+{
+/**
+ * @ingroup ChirpParametersRecord
+ * @brief This class is able to read the ASAR ChirpParameters record
+ */
+class ChirpParameters : public EnvisatAsarRecord
+{
+public:
+  /**
+   * @brief Constructor
+   */
+  ChirpParameters();
+
+  /**
+   * @brief Destructor
+   */
+  virtual ~ChirpParameters();
+
+  /**
+   * @brief This function writes the ChirpParameters in a stream
+   */
+  friend std::ostream& operator<<(std::ostream& os, const ChirpParameters& data);
+
+  /**
+   * @brief This function reads a ChirpParameters from a stream
+   */
+  friend std::istream& operator>>(std::istream& is, ChirpParameters& data);
+
+  /**
+   * @brief Copy constructor
+   */
+  ChirpParameters(const ChirpParameters& rhs);
+
+  /**
+   * @brief Copy operator
+   */
+  ChirpParameters& operator=(const ChirpParameters& rhs);
+
+  /**
+   * @brief This function is able to create a new instance of the class
+   */
+  EnvisatAsarRecord* Instanciate()
+  {
+    return new ChirpParameters();
+  };
+
+  /**
+   * @brief This function is able to create a new instance of the class initialised with the data of the calling instance
+   */
+  EnvisatAsarRecord* Clone()
+  {
+    return new ChirpParameters(*this);
+  };
+
+  /**
+   * @brief Reads the class data from a stream
+   */
+  void Read(std::istream& is)
+  {
+    is>>*this;
+  };
+
+  /**
+   * @brief Writes the class to a stream
+   */
+  void Write(std::ostream& os)
+  {
+    os<<*this;
+  };
+
+
+  /**
+  * @brief zero_doppler_time
+  */
+  std::string   get_zero_doppler_time()
+  {
+    return _zero_doppler_time;
+  };
+  /**
+  * @brief attach_flag
+  */
+  bool   get_attach_flag()
+  {
+    return _attach_flag;
+  };
+  /**
+  * @brief swath
+  */
+  std::string   get_swath()
+  {
+    return _swath;
+  };
+  /**
+  * @brief polar
+  */
+  std::string   get_polar()
+  {
+    return _polar;
+  };
+  /**
+  * @brief chirp_width
+  */
+  float   get_chirp_width()
+  {
+    return _chirp_width;
+  };
+  /**
+  * @brief chirp_sidelobe
+  */
+  float   get_chirp_sidelobe()
+  {
+    return _chirp_sidelobe;
+  };
+  /**
+  * @brief chirp_islr
+  */
+  float   get_chirp_islr()
+  {
+    return _chirp_islr;
+  };
+  /**
+  * @brief chirp_peak_loc
+  */
+  float   get_chirp_peak_loc()
+  {
+    return _chirp_peak_loc;
+  };
+  /**
+  * @brief re_chirp_power
+  */
+  float   get_re_chirp_power()
+  {
+    return _re_chirp_power;
+  };
+  /**
+  * @brief elev_chirp_power
+  */
+  float   get_elev_chirp_power()
+  {
+    return _elev_chirp_power;
+  };
+  /**
+  * @brief chirp_quality_flag
+  */
+  bool   get_chirp_quality_flag()
+  {
+    return _chirp_quality_flag;
+  };
+  /**
+  * @brief ref_chirp_power
+  */
+  float   get_ref_chirp_power()
+  {
+    return _ref_chirp_power;
+  };
+  /**
+  * @brief normalisation_source
+  */
+  std::string   get_normalisation_source()
+  {
+    return _normalisation_source;
+  };
+  /**
+  * @brief cal_pulse_info[352]
+  */
+  float*   get_cal_pulse_info()
+  {
+    return _cal_pulse_info;
+  };
+
+
+  /**
+  * @brief zero_doppler_time
+  */
+  std::string   _zero_doppler_time;
+  /**
+  * @brief attach_flag
+  */
+  bool   _attach_flag;
+  /**
+  * @brief swath
+  */
+  std::string   _swath;
+  /**
+  * @brief polar
+  */
+  std::string   _polar;
+  /**
+  * @brief chirp_width
+  */
+  float   _chirp_width;
+  /**
+  * @brief chirp_sidelobe
+  */
+  float   _chirp_sidelobe;
+  /**
+  * @brief chirp_islr
+  */
+  float   _chirp_islr;
+  /**
+  * @brief chirp_peak_loc
+  */
+  float   _chirp_peak_loc;
+  /**
+  * @brief re_chirp_power
+  */
+  float   _re_chirp_power;
+  /**
+  * @brief elev_chirp_power
+  */
+  float   _elev_chirp_power;
+  /**
+  * @brief chirp_quality_flag
+  */
+  bool   _chirp_quality_flag;
+  /**
+  * @brief ref_chirp_power
+  */
+  float   _ref_chirp_power;
+  /**
+  * @brief normalisation_source
+  */
+  std::string   _normalisation_source;
+  /**
+  * @brief cal_pulse_info[352]
+  */
+  float   _cal_pulse_info[352];
+
+private:
+
+};
+}
+#endif
+
+
+
diff --git a/ossim_plugins/ossim/EnvisatAsar/DopplerCentroidParameters.cpp b/ossim_plugins/ossim/EnvisatAsar/DopplerCentroidParameters.cpp
new file mode 100644
index 0000000..5c9e8ac
--- /dev/null
+++ b/ossim_plugins/ossim/EnvisatAsar/DopplerCentroidParameters.cpp
@@ -0,0 +1,159 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include <EnvisatAsar/DopplerCentroidParameters.h>
+
+namespace ossimplugins
+{
+   DopplerCentroidParameters::DopplerCentroidParameters() : EnvisatAsarRecord("DopplerCentroidParameters_rec")
+   {
+   }
+
+   DopplerCentroidParameters::~DopplerCentroidParameters()
+   {
+   }
+
+
+   std::ostream& operator<<(std::ostream& os, const DopplerCentroidParameters& data)
+   {
+      os<<"zero_doppler_time:"<<data._zero_doppler_time.c_str()<<std::endl;
+
+      os<<"attach_flag:"<<data._attach_flag<<std::endl;
+
+      os<<"slant_range_time:"<<data._slant_range_time<<std::endl;
+
+      os<<"dop_coef[0]:"<<data._dop_coef[0]<<std::endl;
+      os<<"dop_coef[1]:"<<data._dop_coef[1]<<std::endl;
+      os<<"dop_coef[2]:"<<data._dop_coef[2]<<std::endl;
+      os<<"dop_coef[3]:"<<data._dop_coef[3]<<std::endl;
+      os<<"dop_coef[4]:"<<data._dop_coef[4]<<std::endl;
+
+      os<<"dop_conf:"<<data._dop_conf<<std::endl;
+
+      os<<"dop_conf_below_thresh_flag:"<<data._dop_conf_below_thresh_flag<<std::endl;
+
+      os<<"delta_dopp_coeff[0]:"<<data._delta_dopp_coeff[0]<<std::endl;
+      os<<"delta_dopp_coeff[1]:"<<data._delta_dopp_coeff[1]<<std::endl;
+      os<<"delta_dopp_coeff[2]:"<<data._delta_dopp_coeff[2]<<std::endl;
+      os<<"delta_dopp_coeff[3]:"<<data._delta_dopp_coeff[3]<<std::endl;
+      os<<"delta_dopp_coeff[4]:"<<data._delta_dopp_coeff[4]<<std::endl;
+
+      return os;
+
+   }
+
+   std::istream& operator>>(std::istream& is, DopplerCentroidParameters& data)
+   {
+      // char buf64[65];
+      // buf64[64] = '\0';
+      // char buf32[33];
+      // buf32[32] = '\0';
+      // char buf27[28];
+      // buf27[27] = '\0';
+      // char buf20[21];
+      // buf20[20] = '\0';
+      // char buf16[17];
+      // buf16[16]='\0';
+      // char buf15[16];
+      // buf15[15] = '\0';
+      // char buf14[15];
+      // buf14[14] = '\0';
+      // char buf13[14];
+      // buf13[13] = '\0';
+      char buf12[13];
+      buf12[12] = '\0';
+      // char buf11[12];
+      // buf11[11] = '\0';
+      // char buf10[11];
+      // buf10[10] = '\0';
+      // char buf9[10];
+      // buf9[9] = '\0';
+      // char buf8[9];
+      // buf8[8] = '\0';
+      // char buf7[8];
+      // buf7[7] = '\0';
+      // char buf6[7];
+      // buf6[6] = '\0';
+      // char buf5[6];
+      // buf5[5] = '\0';
+      // char buf4[5];
+      // buf4[4] = '\0';
+      char buf3[4];
+      buf3[3] = '\0';
+      // char buf2[3];
+      // buf2[2] = '\0';
+//	char buf1[1];  // Not used avoid warning
+
+      is.read(buf12,12);
+      data._zero_doppler_time = buf12;
+
+      is.read((char*)&(data._attach_flag),1);
+
+      is.read((char*)&(data._slant_range_time),4);
+      data.SwitchEndian(data._slant_range_time);
+
+      for (int i = 0; i <5; i++) {
+         is.read((char*)&(data._dop_coef[i]),4);
+         data.SwitchEndian(data._dop_coef[i]);
+      }
+
+      is.read((char*)&(data._dop_conf),4);
+      data.SwitchEndian(data._dop_conf);
+
+      is.read((char*)&(data._dop_conf_below_thresh_flag),1);
+
+      for (int i = 0; i <5; i++) {
+         is.read((char*)&(data._delta_dopp_coeff[i]),2);
+         data.SwitchEndian(data._delta_dopp_coeff[i]);
+      }
+
+      is.read(buf3,3);
+
+      return is;
+
+   }
+
+   DopplerCentroidParameters::DopplerCentroidParameters(const DopplerCentroidParameters& rhs):
+      EnvisatAsarRecord(rhs),
+      _zero_doppler_time(rhs._zero_doppler_time),
+      _attach_flag(rhs._attach_flag),
+      _slant_range_time(rhs._slant_range_time),
+      _dop_conf(rhs._dop_conf),
+      _dop_conf_below_thresh_flag(rhs._dop_conf_below_thresh_flag)
+   {
+      for (int i = 0; i <5; i++) {
+         _dop_coef[i] = rhs._dop_coef[i];
+      }
+      for (int i = 0; i <5; i++) {
+         _delta_dopp_coeff[i] = rhs._delta_dopp_coeff[i];
+      }
+   }
+
+
+   DopplerCentroidParameters& DopplerCentroidParameters::operator=(const DopplerCentroidParameters& rhs)
+   {
+      _zero_doppler_time = rhs._zero_doppler_time;
+      _attach_flag = rhs._attach_flag;
+      _slant_range_time = rhs._slant_range_time;
+      _dop_conf = rhs._dop_conf;
+      _dop_conf_below_thresh_flag = rhs._dop_conf_below_thresh_flag;
+
+      for (int i = 0; i <5; i++) {
+         _dop_coef[i] = rhs._dop_coef[i];
+      }
+      for (int i = 0; i <5; i++) {
+         _delta_dopp_coeff[i] = rhs._delta_dopp_coeff[i];
+      }
+
+      return *this;
+   }
+}
+
diff --git a/ossim_plugins/ossim/EnvisatAsar/DopplerCentroidParameters.h b/ossim_plugins/ossim/EnvisatAsar/DopplerCentroidParameters.h
new file mode 100644
index 0000000..c3de748
--- /dev/null
+++ b/ossim_plugins/ossim/EnvisatAsar/DopplerCentroidParameters.h
@@ -0,0 +1,176 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef DopplerCentroidParameters_h
+#define DopplerCentroidParameters_h
+
+#include <iostream>
+#include <EnvisatAsar/EnvisatAsarRecord.h>
+
+namespace ossimplugins
+{
+/**
+ * @ingroup DopplerCentroidParametersRecord
+ * @brief This class is able to read the ASAR DopplerCentroidParameters record
+ */
+class DopplerCentroidParameters : public EnvisatAsarRecord
+{
+public:
+  /**
+   * @brief Constructor
+   */
+  DopplerCentroidParameters();
+
+  /**
+   * @brief Destructor
+   */
+  virtual ~DopplerCentroidParameters();
+
+  /**
+   * @brief This function writes the DopplerCentroidParameters in a stream
+   */
+  friend std::ostream& operator<<(std::ostream& os, const DopplerCentroidParameters& data);
+
+  /**
+   * @brief This function reads a DopplerCentroidParameters from a stream
+   */
+  friend std::istream& operator>>(std::istream& is, DopplerCentroidParameters& data);
+
+  /**
+   * @brief Copy constructor
+   */
+  DopplerCentroidParameters(const DopplerCentroidParameters& rhs);
+
+  /**
+   * @brief Copy operator
+   */
+  DopplerCentroidParameters& operator=(const DopplerCentroidParameters& rhs);
+
+  /**
+   * @brief This function is able to create a new instance of the class
+   */
+  EnvisatAsarRecord* Instanciate()
+  {
+    return new DopplerCentroidParameters();
+  };
+
+  /**
+   * @brief This function is able to create a new instance of the class initialised with the data of the calling instance
+   */
+  EnvisatAsarRecord* Clone()
+  {
+    return new DopplerCentroidParameters(*this);
+  };
+
+  /**
+   * @brief Reads the class data from a stream
+   */
+  void Read(std::istream& is)
+  {
+    is>>*this;
+  };
+
+  /**
+   * @brief Writes the class to a stream
+   */
+  void Write(std::ostream& os)
+  {
+    os<<*this;
+  };
+
+
+  /**
+  * @brief zero_doppler_time
+  */
+  std::string   get_zero_doppler_time()
+  {
+    return _zero_doppler_time;
+  };
+  /**
+  * @brief attach_flag
+  */
+  bool   get_attach_flag()
+  {
+    return _attach_flag;
+  };
+  /**
+  * @brief slant_range_time
+  */
+  float   get_slant_range_time()
+  {
+    return _slant_range_time;
+  };
+  /**
+  * @brief dop_coef[5]
+  */
+  float*   get_dop_coef()
+  {
+    return _dop_coef;
+  };
+  /**
+  * @brief dop_conf
+  */
+  float   get_dop_conf()
+  {
+    return _dop_conf;
+  };
+  /**
+  * @brief dop_conf_below_thresh_flag
+  */
+  bool   get_dop_conf_below_thresh_flag()
+  {
+    return _dop_conf_below_thresh_flag;
+  };
+  /**
+  * @brief delta_dopp_coeff[5]
+  */
+  signed short  * get_delta_dopp_coeff()
+  {
+    return _delta_dopp_coeff;
+  };
+
+  /**
+  * @brief zero_doppler_time
+  */
+  std::string   _zero_doppler_time;
+  /**
+  * @brief attach_flag
+  */
+  bool   _attach_flag;
+  /**
+  * @brief slant_range_time
+  */
+  float   _slant_range_time;
+  /**
+  * @brief dop_coef[5]
+  */
+  float   _dop_coef[5];
+  /**
+  * @brief dop_conf
+  */
+  float   _dop_conf;
+  /**
+  * @brief dop_conf_below_thresh_flag
+  */
+  bool   _dop_conf_below_thresh_flag;
+  /**
+  * @brief delta_dopp_coeff[5]
+  */
+  signed short   _delta_dopp_coeff[5];
+
+private:
+
+};
+}
+#endif
+
+
+
diff --git a/ossim_plugins/ossim/EnvisatAsar/EnvisatAsarData.cpp b/ossim_plugins/ossim/EnvisatAsar/EnvisatAsarData.cpp
new file mode 100644
index 0000000..45b3bd2
--- /dev/null
+++ b/ossim_plugins/ossim/EnvisatAsar/EnvisatAsarData.cpp
@@ -0,0 +1,284 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include <EnvisatAsar/EnvisatAsarData.h>
+#include <EnvisatAsar/EnvisatAsarDataFactory.h>
+
+#include <EnvisatAsar/sph.h>
+#include <EnvisatAsar/mph.h>
+#include <EnvisatAsar/SQ_ADSR.h>
+#include <EnvisatAsar/MainProcessingParameters.h>
+#include <EnvisatAsar/SRGRConversionParameters.h>
+#include <EnvisatAsar/DopplerCentroidParameters.h>
+#include <EnvisatAsar/ChirpParameters.h>
+#include <EnvisatAsar/AntennaElevationPatterns.h>
+#include <EnvisatAsar/GeolocationGrid.h>
+
+namespace ossimplugins
+{
+
+EnvisatAsarData::EnvisatAsarData()
+{
+}
+
+EnvisatAsarData::~EnvisatAsarData()
+{
+	ClearRecords();
+}
+
+std::ostream& operator<<(std::ostream& os, const EnvisatAsarData& data)
+{
+	std::list<EnvisatAsarRecord*>::const_iterator it = data._records.begin();
+	while(it != data._records.end())
+	{
+		(*it)->Write(os);
+		++it;
+	}
+	return os;
+
+}
+
+std::istream& operator>>(std::istream& is, EnvisatAsarData& data)
+{
+	EnvisatAsarDataFactory factory;
+
+	if (sizeof(int)!=4) std::cout << "EnvisatAsarData WARNING : (int) not coded over 32 bits, metadata might not be byte swapped correctly"<< std::endl ;
+	if (sizeof(float)!=4) std::cout << "EnvisatAsarData WARNING : (float) not coded over 32 bits, metadata might not be byte swapped correctly"<< std::endl ;
+	if (sizeof(double)!=8) std::cout << "EnvisatAsarData WARNING : (double) not coded over 64 bits, metadata might not be byte swapped correctly"<< std::endl ;
+
+	data.ClearRecords();
+
+	// read the first record (MPH)
+	EnvisatAsarRecord* mph_record = factory.Instanciate("MPH");
+	mph_record->Read(is);
+	data._records.push_back(mph_record);
+
+	// read the second record (sph) and update it with the mph (number of dsd)
+	EnvisatAsarRecord* sph_record = factory.Instanciate("SPH");
+	((sph*)sph_record)->update_sph_from_mph(*((mph *)mph_record));
+	sph_record->Read(is);
+	data._records.push_back(sph_record);
+
+	std::vector<dsd> dsd_vector = ((sph*)sph_record)->get_dsd_vector();
+
+	// For each dsd, check if present in the file and in the record factory.
+	// If true, instanciate it and add to the EnvisatAsarRecord list.
+	std::vector<dsd>::iterator it = dsd_vector.begin();
+	while(it != dsd_vector.end())
+	{
+		std::string str = (it->get_ds_name());
+
+		if ( (it->get_ds_size()) != 0)
+		{
+			for (int i = 0; i<(it->get_num_dsr()); i++)
+			{
+				EnvisatAsarRecord* record = factory.Instanciate(str);
+				if (record != NULL)
+				{
+					is.seekg((std::streampos)(it->get_ds_offset())+ (std::streampos)(i*(it->get_dsr_size())));
+					record->Read(is);
+					data._records.push_back(record);
+				}
+			}
+		}
+		++it;
+	}
+
+	return is;
+}
+
+
+EnvisatAsarData::EnvisatAsarData(const EnvisatAsarData& rhs)
+{
+	std::list<EnvisatAsarRecord*>::const_iterator it = rhs._records.begin();
+	while(it != rhs._records.end())
+	{
+		_records.push_back((*it)->Clone());
+		++it;
+	}
+}
+
+EnvisatAsarData& EnvisatAsarData::operator=(const EnvisatAsarData& rhs)
+{
+	ClearRecords();
+	std::list<EnvisatAsarRecord*>::const_iterator it = rhs._records.begin();
+	while(it != rhs._records.end())
+	{
+		_records.push_back((*it)->Clone());
+		++it;
+	}
+
+	return *this;
+}
+
+void EnvisatAsarData::ClearRecords()
+{
+	std::list<EnvisatAsarRecord*>::const_iterator it = _records.begin();
+	while(it != _records.end())
+	{
+		delete (*it);
+		++it;
+	}
+	_records.clear();
+}
+mph * EnvisatAsarData::get_mph()
+{
+	std::list<EnvisatAsarRecord*>::const_iterator it = _records.begin();
+	while(it != _records.end())
+	{
+		if ((*it)->get_mnemonic().compare("mph_rec") == 0)	return (mph*)(*it);
+		++it;
+	}
+	return NULL;
+}
+sph * EnvisatAsarData::get_sph()
+{
+	std::list<EnvisatAsarRecord*>::const_iterator it = _records.begin();
+	while(it != _records.end())
+	{
+		if ((*it)->get_mnemonic().compare("sph_rec") == 0)	return (sph*)(*it);
+		++it;
+	}
+	return NULL;
+}
+
+SQ_ADSR * EnvisatAsarData::get_SQ_ADSR()
+{
+	std::list<EnvisatAsarRecord*>::const_iterator it = _records.begin();
+	while(it != _records.end())
+	{
+		if ((*it)->get_mnemonic().compare("SQ_ADSR_rec") == 0)	return (SQ_ADSR*)(*it);
+		++it;
+	}
+	return NULL;
+}
+MainProcessingParameters * EnvisatAsarData::get_MainProcessingParameters()
+{
+	std::list<EnvisatAsarRecord*>::const_iterator it = _records.begin();
+	while(it != _records.end())
+	{
+		if ((*it)->get_mnemonic().compare("MainProcessingParameters_rec") == 0)	return (MainProcessingParameters*)(*it);
+		++it;
+	}
+	return NULL;
+}
+DopplerCentroidParameters * EnvisatAsarData::get_DopplerCentroidParameters()
+{
+	std::list<EnvisatAsarRecord*>::const_iterator it = _records.begin();
+	while(it != _records.end())
+	{
+		if ((*it)->get_mnemonic().compare("DopplerCentroidParameters_rec") == 0)	return (DopplerCentroidParameters*)(*it);
+		++it;
+	}
+	return NULL;
+}
+SRGRConversionParameters * EnvisatAsarData::get_SRGRConversionParameters(int pos)
+{
+	std::list<EnvisatAsarRecord*>::const_iterator it = _records.begin();
+	int cpt = 0;
+	while(it != _records.end())
+	{
+		if ((*it)->get_mnemonic().compare("SRGRConversionParameters_rec") == 0)
+		{
+			if (cpt == pos) {
+				return (SRGRConversionParameters*)(*it);
+			}
+			else cpt++;
+		}
+		++it;
+	}
+	return NULL;
+}
+ChirpParameters * EnvisatAsarData::get_ChirpParameters()
+{
+	std::list<EnvisatAsarRecord*>::const_iterator it = _records.begin();
+	while(it != _records.end())
+	{
+		if ((*it)->get_mnemonic().compare("ChirpParameters_rec") == 0)	return (ChirpParameters*)(*it);
+		++it;
+	}
+	return NULL;
+}
+AntennaElevationPatterns * EnvisatAsarData::get_AntennaElevationPatterns()
+{
+	std::list<EnvisatAsarRecord*>::const_iterator it = _records.begin();
+	while(it != _records.end())
+	{
+		if ((*it)->get_mnemonic().compare("AntennaElevationPatterns_rec") == 0)	return (AntennaElevationPatterns*)(*it);
+		++it;
+	}
+	return NULL;
+}
+
+// Return the first Geolocation Grid Record
+//GeolocationGrid * EnvisatAsarData::get_GeolocationGrid()
+//{
+//	std::list<EnvisatAsarRecord*>::const_iterator it = _records.begin();
+//	while(it != _records.end())
+//	{
+//		std::string str = (*it)->get_mnemonic();
+//		if ((*it)->get_mnemonic().compare("GeolocationGrid_rec") == 0)
+//		{
+//			return (GeolocationGrid*)(*it);
+//		}
+//		++it;
+//	}
+//	return NULL;
+//}
+
+// Return the num_ds Geolocation Grid Record
+GeolocationGrid * EnvisatAsarData::get_GeolocationGrid(int num_ds)
+{
+	std::list<EnvisatAsarRecord*>::const_iterator it = _records.begin();
+
+	int total_num_ds = 0;
+	while(it != _records.end())
+	{
+		std::string str = (*it)->get_mnemonic();
+		if ((*it)->get_mnemonic().compare("GeolocationGrid_rec") == 0)	total_num_ds += 1;
+		++it;
+	}
+
+	int cpt = 0;
+	it = _records.begin();
+	while(it != _records.end())
+	{
+		std::string str = (*it)->get_mnemonic();
+		if ((*it)->get_mnemonic().compare("GeolocationGrid_rec") == 0)
+		{
+			if ((cpt == num_ds) || (cpt == total_num_ds-1))	return (GeolocationGrid*)(*it);
+			cpt +=1;
+
+		}
+		++it;
+	}
+	return NULL;
+}
+
+
+int EnvisatAsarData::get_num_ds(EnvisatAsarRecord * record)
+{
+	if (record == NULL) return 0;
+	std::list<EnvisatAsarRecord*>::const_iterator it = _records.begin();
+	int cpt = 0;
+	while(it != _records.end())
+	{
+		std::string str = (*it)->get_mnemonic();
+		if ((*it)->get_mnemonic().compare(record->get_mnemonic()) == 0)
+		{
+			cpt++;
+		}
+		++it;
+	}
+	return cpt;
+}
+}
+
diff --git a/ossim_plugins/ossim/EnvisatAsar/EnvisatAsarData.h b/ossim_plugins/ossim/EnvisatAsar/EnvisatAsarData.h
new file mode 100644
index 0000000..7bba480
--- /dev/null
+++ b/ossim_plugins/ossim/EnvisatAsar/EnvisatAsarData.h
@@ -0,0 +1,93 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef EnvisatAsarData_h
+#define EnvisatAsarData_h
+
+#include <iostream>
+#include "sph.h"
+#include "mph.h"
+#include "SQ_ADSR.h"
+#include "MainProcessingParameters.h"
+#include "AntennaElevationPatterns.h"
+#include "DopplerCentroidParameters.h"
+#include "SRGRConversionParameters.h"
+#include "ChirpParameters.h"
+#include "GeolocationGrid.h"
+#include <map>
+#include <list>
+#include <vector>
+
+namespace ossimplugins
+{
+/**
+ * @ingroup EnvisatAsarDataFile
+ * @brief This class is able to read the Envisat file structure
+ */
+class EnvisatAsarData
+{
+public:
+  /**
+   * @brief Constructor
+   */
+  EnvisatAsarData();
+
+  /**
+   * @brief Destructor
+   */
+  ~EnvisatAsarData();
+
+  /**
+   * @brief This function writes the EnvisatAsarData in a stream
+   */
+  friend std::ostream& operator<<(std::ostream& os, const EnvisatAsarData& data);
+
+  /**
+   * @brief This function reads a EnvisatAsarData from a stream
+   */
+  friend std::istream& operator>>(std::istream& is, EnvisatAsarData& data);
+
+  /**
+   * @brief Copy constructor
+   */
+  EnvisatAsarData(const EnvisatAsarData& rhs);
+
+  /**
+   * @brief Copy operator
+   */
+  EnvisatAsarData& operator=(const EnvisatAsarData& rhs);
+
+  /**
+   * @brief Removes all the previous records from the EnvisatAsarData
+   */
+  void ClearRecords();
+
+  mph * get_mph();
+  sph * get_sph();
+  SQ_ADSR * get_SQ_ADSR();
+  MainProcessingParameters * get_MainProcessingParameters();
+  AntennaElevationPatterns * get_AntennaElevationPatterns();
+  DopplerCentroidParameters * get_DopplerCentroidParameters();
+  SRGRConversionParameters * get_SRGRConversionParameters(int pos = 0);
+  ChirpParameters * get_ChirpParameters();
+  GeolocationGrid * get_GeolocationGrid(int num_ds = 0);
+
+  int get_num_ds(EnvisatAsarRecord * record);
+
+protected:
+  std::list<EnvisatAsarRecord*> _records;
+
+private:
+
+};
+}
+#endif
+
diff --git a/ossim_plugins/ossim/EnvisatAsar/EnvisatAsarDataFactory.cpp b/ossim_plugins/ossim/EnvisatAsar/EnvisatAsarDataFactory.cpp
new file mode 100644
index 0000000..6be888f
--- /dev/null
+++ b/ossim_plugins/ossim/EnvisatAsar/EnvisatAsarDataFactory.cpp
@@ -0,0 +1,50 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include <EnvisatAsar/EnvisatAsarDataFactory.h>
+#include <EnvisatAsar/EnvisatAsarData.h>
+
+#include <EnvisatAsar/sph.h>
+#include <EnvisatAsar/mph.h>
+#include <EnvisatAsar/SQ_ADSR.h>
+#include <EnvisatAsar/MainProcessingParameters.h>
+#include <EnvisatAsar/SRGRConversionParameters.h>
+#include <EnvisatAsar/DopplerCentroidParameters.h>
+#include <EnvisatAsar/ChirpParameters.h>
+#include <EnvisatAsar/AntennaElevationPatterns.h>
+#include <EnvisatAsar/GeolocationGrid.h>
+
+namespace ossimplugins
+{
+
+EnvisatAsarDataFactory::EnvisatAsarDataFactory()
+{
+	RegisterRecord("MPH"							, new mph());
+	RegisterRecord("SPH"							, new sph());
+	RegisterRecord("MDS1 SQ ADS                 "	, new SQ_ADSR());
+	RegisterRecord("MDS2 SQ ADS                 "	, new SQ_ADSR());
+	RegisterRecord("MAIN PROCESSING PARAMS ADS  "	, new MainProcessingParameters());
+	RegisterRecord("DOP CENTROID COEFFS ADS     "	, new DopplerCentroidParameters());
+	RegisterRecord("SR GR ADS                   "	, new SRGRConversionParameters());
+	RegisterRecord("CHIRP PARAMS ADS            "	, new ChirpParameters());
+	RegisterRecord("MDS1 ANTENNA ELEV PATT ADS  "	, new AntennaElevationPatterns());
+	RegisterRecord("MDS2 ANTENNA ELEV PATT ADS  "	, new AntennaElevationPatterns());
+	RegisterRecord("GEOLOCATION GRID ADS        "	, new GeolocationGrid());
+}
+
+EnvisatAsarDataFactory::~EnvisatAsarDataFactory()
+{
+
+}
+
+}
+
+
diff --git a/ossim_plugins/ossim/EnvisatAsar/EnvisatAsarDataFactory.h b/ossim_plugins/ossim/EnvisatAsar/EnvisatAsarDataFactory.h
new file mode 100644
index 0000000..4bebc98
--- /dev/null
+++ b/ossim_plugins/ossim/EnvisatAsar/EnvisatAsarDataFactory.h
@@ -0,0 +1,45 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef EnvisatAsarDataFactory_h
+#define EnvisatAsarDataFactory_h
+
+
+#include <EnvisatAsar/EnvisatAsarRecordFactory.h>
+#include <map>
+
+namespace ossimplugins
+{
+/**
+ * @ingroup EnvisatAsarDataFile
+ * @brief This class is a factory able to construct Record base classes
+ */
+class EnvisatAsarDataFactory : public EnvisatAsarRecordFactory
+{
+public:
+  /**
+   * @brief Constructor
+   */
+  EnvisatAsarDataFactory();
+  /**
+   * @brief Destructor
+   */
+  ~EnvisatAsarDataFactory();
+
+
+protected:
+
+
+private:
+};
+}
+#endif
+
diff --git a/ossim_plugins/ossim/EnvisatAsar/EnvisatAsarRecord.cpp b/ossim_plugins/ossim/EnvisatAsar/EnvisatAsarRecord.cpp
new file mode 100644
index 0000000..48593c9
--- /dev/null
+++ b/ossim_plugins/ossim/EnvisatAsar/EnvisatAsarRecord.cpp
@@ -0,0 +1,31 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include <EnvisatAsar/EnvisatAsarRecord.h>
+#include <memory.h>
+
+namespace ossimplugins
+{
+EnvisatAsarRecord::EnvisatAsarRecord(std::string mnemonic):
+	_mnemonic(mnemonic)
+{
+}
+
+EnvisatAsarRecord::~EnvisatAsarRecord()
+{
+}
+
+EnvisatAsarRecord::EnvisatAsarRecord(const EnvisatAsarRecord& rhs):
+	_mnemonic(rhs._mnemonic)
+{
+}
+}
+
diff --git a/ossim_plugins/ossim/EnvisatAsar/EnvisatAsarRecord.h b/ossim_plugins/ossim/EnvisatAsar/EnvisatAsarRecord.h
new file mode 100644
index 0000000..978a46a
--- /dev/null
+++ b/ossim_plugins/ossim/EnvisatAsar/EnvisatAsarRecord.h
@@ -0,0 +1,113 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef EnvisatAsarRecord_h
+#define EnvisatAsarRecord_h
+
+#include <iostream>
+#include <cstdlib>
+#include <cstring>
+#include <ossim/base/ossimCommon.h>
+
+namespace ossimplugins
+{
+/**
+ * @ingroup EnvisatAsar
+ * @brief This class is the base class of all the Envisat ASAR record classes
+ */
+
+
+
+
+class EnvisatAsarRecord
+{
+public:
+  /**
+   * @brief Constructor
+   * @param mnemonic Name of the record
+   */
+  EnvisatAsarRecord(std::string mnemonic);
+  /**
+   * @brief Destructor
+   */
+  virtual ~EnvisatAsarRecord();
+
+  /**
+   * @brief Copy constructor
+   */
+  EnvisatAsarRecord(const EnvisatAsarRecord& rhs);
+
+  /**
+   * @brief This function is able to create a new instance of the class
+   */
+  virtual EnvisatAsarRecord* Instanciate() =0;
+
+  /**
+   * @brief This function is able to create a new instance of the class initialised with the data of the calling instance
+   */
+  virtual EnvisatAsarRecord* Clone()=0;
+
+  /**
+   * @brief Reads the class data from a stream
+   */
+  virtual void Read(std::istream& is) =0;
+
+  /**
+   * @brief Writes the class to a stream
+   */
+  virtual void Write(std::ostream& os)=0;
+
+  /**
+   * @brief Returns the mnemonic of the record
+   */
+  std::string get_mnemonic()
+  {
+    return _mnemonic;
+  };
+
+
+
+protected:
+  /**
+   * @brief This function switches the LSB value and the MSB value of the parameter
+   */
+  template<typename T>
+  void SwitchEndian(T &value) {
+
+    char *buffer;
+    char *res;
+    int nb_octets = sizeof(T);
+
+    if (ossim::byteOrder() == OSSIM_LITTLE_ENDIAN) {
+      buffer = (char* )malloc(nb_octets);
+      res = (char* )malloc(nb_octets);
+
+      memcpy(buffer,&value,nb_octets);
+
+      for (int i=0; i<nb_octets/2; i++) {
+        res[i] = buffer[nb_octets-1-i];
+        res[nb_octets-1-i] = buffer[i];
+      }
+      memcpy(&value,res,nb_octets);
+
+      free(buffer);
+      free(res);
+    }
+  }
+
+
+  std::string _mnemonic;
+
+private:
+};
+}
+#endif
+
diff --git a/ossim_plugins/ossim/EnvisatAsar/EnvisatAsarRecordFactory.cpp b/ossim_plugins/ossim/EnvisatAsar/EnvisatAsarRecordFactory.cpp
new file mode 100644
index 0000000..dce4851
--- /dev/null
+++ b/ossim_plugins/ossim/EnvisatAsar/EnvisatAsarRecordFactory.cpp
@@ -0,0 +1,42 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include <EnvisatAsar/EnvisatAsarRecordFactory.h>
+
+namespace ossimplugins
+{
+EnvisatAsarRecordFactory::EnvisatAsarRecordFactory()
+{
+}
+
+EnvisatAsarRecordFactory::~EnvisatAsarRecordFactory()
+{
+}
+
+EnvisatAsarRecord* EnvisatAsarRecordFactory::Instanciate(std::string id)
+{
+	EnvisatAsarRecord* record = _availableRecords[id];
+	if(record == NULL)
+	{
+		return NULL;
+	}
+	else
+	{
+		return record->Instanciate();
+	}
+}
+
+void EnvisatAsarRecordFactory::RegisterRecord(std::string id, EnvisatAsarRecord * record)
+{
+	_availableRecords[id] = record;
+}
+}
+
diff --git a/ossim_plugins/ossim/EnvisatAsar/EnvisatAsarRecordFactory.h b/ossim_plugins/ossim/EnvisatAsar/EnvisatAsarRecordFactory.h
new file mode 100644
index 0000000..f2f67a4
--- /dev/null
+++ b/ossim_plugins/ossim/EnvisatAsar/EnvisatAsarRecordFactory.h
@@ -0,0 +1,61 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef EnvisatAsarRecordFactory_h
+#define EnvisatAsarRecordFactory_h
+
+#include <EnvisatAsar/EnvisatAsarRecord.h>
+#include <map>
+#include <string>
+
+namespace ossimplugins
+{
+
+/**
+ * @ingroup EnvisatAsar
+ * @brief This class is a factory able to construct Record base classes given the id of the record wanted
+ */
+class EnvisatAsarRecordFactory
+{
+public:
+  /**
+   * @brief Constructor
+   */
+  EnvisatAsarRecordFactory();
+  /**
+   * @brief Destructor
+   */
+  ~EnvisatAsarRecordFactory();
+
+  /**
+   * @brief Adds a new Record type available in this factory
+   * @param record Record to add in the factory
+   * @param id Id of the new avalaible Record
+   */
+  void RegisterRecord(std::string id, EnvisatAsarRecord * record);
+
+  /**
+   * @brief Instanciatse a new Record
+   * @param id Id of the Record we want to instanciate
+   */
+  EnvisatAsarRecord* Instanciate(std::string id);
+
+protected:
+  /**
+   * @brief Contains all the available Records for the factory
+   */
+  std::map<std::string, EnvisatAsarRecord*> _availableRecords;
+
+private:
+};
+}
+#endif
+
diff --git a/ossim_plugins/ossim/EnvisatAsar/GeolocationGrid.cpp b/ossim_plugins/ossim/EnvisatAsar/GeolocationGrid.cpp
new file mode 100644
index 0000000..1c33d5a
--- /dev/null
+++ b/ossim_plugins/ossim/EnvisatAsar/GeolocationGrid.cpp
@@ -0,0 +1,218 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include <EnvisatAsar/GeolocationGrid.h>
+
+namespace ossimplugins
+{
+   GeolocationGrid::GeolocationGrid() : EnvisatAsarRecord("GeolocationGrid_rec")
+   {
+   }
+
+   GeolocationGrid::~GeolocationGrid()
+   {
+   }
+
+
+   std::ostream& operator<<(std::ostream& os, const GeolocationGrid& data)
+   {
+      os<<"first_zero_doppler_time_day:"<<data._first_zero_doppler_time_day<<std::endl;
+
+      os<<"first_zero_doppler_time_sec:"<<data._first_zero_doppler_time_sec<<std::endl;
+
+      os<<"first_zero_doppler_time_microsec:"<<data._first_zero_doppler_time_microsec<<std::endl;
+
+      os<<"attach_flag:"<<data._attach_flag<<std::endl;
+
+      os<<"line_num:"<<data._line_num<<std::endl;
+
+      os<<"num_lines:"<<data._num_lines<<std::endl;
+
+      os<<"sub_sat_track:"<<data._sub_sat_track<<std::endl;
+
+      for (int i = 0; i<11; i++) {
+         os<<"samp_numbers["<<i<<"]:"<<data._samp_numbers[i]<<std::endl;
+      }
+
+      for (int i = 0; i<11; i++) {
+         os<<"slant_range_times["<<i<<"]:"<<data._slant_range_times[i]<<std::endl;
+      }
+
+      for (int i = 0; i<11; i++) {
+         os<<"angles["<<i<<"]:"<<data._angles[i]<<std::endl;
+      }
+
+      for (int i = 0; i<11; i++) {
+         os<<"lats["<<i<<"]:"<<data._lats[i]<<std::endl;
+      }
+
+      for (int i = 0; i<11; i++) {
+         os<<"longs["<<i<<"]:"<<data._longs[i]<<std::endl;
+      }
+
+      os<<"last_zero_doppler_time:"<<data._last_zero_doppler_time.c_str()<<std::endl;
+
+      os<<"last_line_tie_points:"<<data._last_line_tie_points.c_str()<<std::endl;
+
+      return os;
+
+   }
+
+   std::istream& operator>>(std::istream& is, GeolocationGrid& data)
+   {
+      char buf220[221];
+      buf220[220] = '\0';
+      char buf32[33];
+      buf32[32] = '\0';
+      // char buf27[28];
+      // buf27[27] = '\0';
+      // char buf20[21];
+      // buf20[20] = '\0';
+      // char buf16[17];
+      // buf16[16]='\0';
+      // char buf15[16];
+      // buf15[15] = '\0';
+      // char buf14[15];
+      // buf14[14] = '\0';
+      // char buf13[14];
+      // buf13[13] = '\0';
+      char buf12[13];
+      buf12[12] = '\0';
+      // char buf11[12];
+      // buf11[11] = '\0';
+      // char buf10[11];
+      // buf10[10] = '\0';
+      // char buf9[10];
+      // buf9[9] = '\0';
+      // char buf8[9];
+      // buf8[8] = '\0';
+      // char buf7[8];
+      // buf7[7] = '\0';
+      // char buf6[7];
+      // buf6[6] = '\0';
+      // char buf5[6];
+      // buf5[5] = '\0';
+      // char buf4[5];
+      // buf4[4] = '\0';
+      // char buf3[4];
+      // buf3[3] = '\0';
+      // char buf2[3];
+      // buf2[2] = '\0';
+//	char buf1[1]; // not used avoid warning
+
+      is.read((char*)&(data._first_zero_doppler_time_day),4);
+      data.SwitchEndian(data._first_zero_doppler_time_day);
+
+      is.read((char*)&(data._first_zero_doppler_time_sec),4);
+      data.SwitchEndian(data._first_zero_doppler_time_sec);
+
+      is.read((char*)&(data._first_zero_doppler_time_microsec),4);
+      data.SwitchEndian(data._first_zero_doppler_time_microsec);
+
+      is.read((char*)&(data._attach_flag),1);
+
+      is.read((char*)&(data._line_num),4);
+      data.SwitchEndian(data._line_num);
+
+      is.read((char*)&(data._num_lines),4);
+      data.SwitchEndian(data._num_lines);
+
+      is.read((char*)&(data._sub_sat_track),4);
+      data.SwitchEndian(data._sub_sat_track);
+
+      for (int i = 0; i<11; i++) {
+         is.read((char*)&(data._samp_numbers[i]),4);
+         data.SwitchEndian(data._samp_numbers[i]);
+      }
+
+      for (int i = 0; i<11; i++) {
+         is.read((char*)&(data._slant_range_times[i]),4);
+         data.SwitchEndian(data._slant_range_times[i]);
+      }
+
+      for (int i = 0; i<11; i++) {
+         is.read((char*)&(data._angles[i]),4);
+         data.SwitchEndian(data._angles[i]);
+      }
+
+      for (int i = 0; i<11; i++) {
+         is.read((char*)&(data._lats[i]),4);
+         data.SwitchEndian(data._lats[i]);
+      }
+
+      for (int i = 0; i<11; i++) {
+         is.read((char*)&(data._longs[i]),4);
+         data.SwitchEndian(data._longs[i]);
+      }
+
+      is.read(buf32,22);
+
+      is.read(buf12,12);
+      data._last_zero_doppler_time = buf12;
+
+      is.read(buf220,220);
+      data._last_line_tie_points = buf220;
+
+      is.read(buf32,22);
+
+      return is;
+
+   }
+
+   GeolocationGrid::GeolocationGrid(const GeolocationGrid& rhs):
+      EnvisatAsarRecord(rhs),
+      _first_zero_doppler_time_day(rhs._first_zero_doppler_time_day),
+      _first_zero_doppler_time_sec(rhs._first_zero_doppler_time_sec),
+      _first_zero_doppler_time_microsec(rhs._first_zero_doppler_time_microsec),
+      _attach_flag(rhs._attach_flag),
+      _line_num(rhs._line_num),
+      _num_lines(rhs._num_lines),
+      _sub_sat_track(rhs._sub_sat_track),
+      _last_zero_doppler_time(rhs._last_zero_doppler_time),
+      _last_line_tie_points(rhs._last_line_tie_points)
+   {
+
+      for (int i = 0; i<11; i++) {
+         _samp_numbers[i] = rhs._samp_numbers[i];
+         _slant_range_times[i] = rhs._slant_range_times[i];
+         _angles[i] = rhs._angles[i];
+         _lats[i] = rhs._lats[i];
+         _longs[i] = rhs._longs[i];
+      }
+
+
+   }
+
+
+   GeolocationGrid& GeolocationGrid::operator=(const GeolocationGrid& rhs)
+   {
+      _first_zero_doppler_time_day = rhs._first_zero_doppler_time_day;
+      _first_zero_doppler_time_sec = rhs._first_zero_doppler_time_sec;
+      _first_zero_doppler_time_microsec = rhs._first_zero_doppler_time_microsec;
+      _attach_flag = rhs._attach_flag;
+      _line_num = rhs._line_num;
+      _num_lines = rhs._num_lines;
+      _sub_sat_track = rhs._sub_sat_track;
+      _last_zero_doppler_time = rhs._last_zero_doppler_time;
+      _last_line_tie_points = rhs._last_line_tie_points;
+
+      for (int i = 0; i<11; i++) {
+         _samp_numbers[i] = rhs._samp_numbers[i];
+         _slant_range_times[i] = rhs._slant_range_times[i];
+         _angles[i] = rhs._angles[i];
+         _lats[i] = rhs._lats[i];
+         _longs[i] = rhs._longs[i];
+      }
+
+      return *this;
+   }
+}
+
diff --git a/ossim_plugins/ossim/EnvisatAsar/GeolocationGrid.h b/ossim_plugins/ossim/EnvisatAsar/GeolocationGrid.h
new file mode 100644
index 0000000..9d90291
--- /dev/null
+++ b/ossim_plugins/ossim/EnvisatAsar/GeolocationGrid.h
@@ -0,0 +1,254 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef GeolocationGrid_h
+#define GeolocationGrid_h
+
+#include <iostream>
+#include <EnvisatAsar/EnvisatAsarRecord.h>
+
+namespace ossimplugins
+{
+/**
+ * @ingroup GeolocationGridRecord
+ * @brief This class is able to read the ASAR GeolocationGrid record
+ */
+class GeolocationGrid : public EnvisatAsarRecord
+{
+public:
+  /**
+   * @brief Constructor
+   */
+  GeolocationGrid();
+
+  /**
+   * @brief Destructor
+   */
+  virtual ~GeolocationGrid();
+
+  /**
+   * @brief This function writes the GeolocationGrid in a stream
+   */
+  friend std::ostream& operator<<(std::ostream& os, const GeolocationGrid& data);
+
+  /**
+   * @brief This function reads a GeolocationGrid from a stream
+   */
+  friend std::istream& operator>>(std::istream& is, GeolocationGrid& data);
+
+  /**
+   * @brief Copy constructor
+   */
+  GeolocationGrid(const GeolocationGrid& rhs);
+
+  /**
+   * @brief Copy operator
+   */
+  GeolocationGrid& operator=(const GeolocationGrid& rhs);
+
+  /**
+   * @brief This function is able to create a new instance of the class
+   */
+  EnvisatAsarRecord* Instanciate()
+  {
+    return new GeolocationGrid();
+  };
+
+  /**
+   * @brief This function is able to create a new instance of the class initialised with the data of the calling instance
+   */
+  EnvisatAsarRecord* Clone()
+  {
+    return new GeolocationGrid(*this);
+  };
+
+  /**
+   * @brief Reads the class data from a stream
+   */
+  void Read(std::istream& is)
+  {
+    is>>*this;
+  };
+
+  /**
+   * @brief Writes the class to a stream
+   */
+  void Write(std::ostream& os)
+  {
+    os<<*this;
+  };
+
+  /**
+  * @brief first_zero_doppler_time day
+  */
+  int  get_first_zero_doppler_time_day()
+  {
+    return _first_zero_doppler_time_day;
+  };
+  /**
+  * @brief first_zero_doppler_time second
+  */
+  unsigned int  get_first_zero_doppler_time_sec()
+  {
+    return _first_zero_doppler_time_sec;
+  };
+  /**
+  * @brief first_zero_doppler_time micro sec
+  */
+  unsigned int  get_first_zero_doppler_time_microsec()
+  {
+    return _first_zero_doppler_time_microsec;
+  };
+  /**
+  * @brief attach_flag
+  */
+  bool   get_attach_flag()
+  {
+    return _attach_flag;
+  };
+  /**
+  * @brief line_num
+  */
+  unsigned int   get_line_num()
+  {
+    return _line_num;
+  };
+  /**
+  * @brief num_lines
+  */
+  unsigned int   get_num_lines()
+  {
+    return _num_lines;
+  };
+  /**
+  * @brief sub_sat_track
+  */
+  float   get_sub_sat_track()
+  {
+    return _sub_sat_track;
+  };
+  /**
+  * @brief samp_numbvers
+  */
+  unsigned int *  get_samp_numbers()
+  {
+    return _samp_numbers;
+  };
+  /**
+  * @brief slant_range_times
+  */
+  float *  get_slant_range_times()
+  {
+    return _slant_range_times;
+  };
+  /**
+  * @brief angles
+  */
+  float *  get_angles()
+  {
+    return _angles;
+  };
+  /**
+  * @brief lats
+  */
+  int *  get_lats()
+  {
+    return _lats;
+  };
+  /**
+  * @brief longs
+  */
+  int *  get_longs()
+  {
+    return _longs;
+  };
+  /**
+  * @brief last_zero_doppler_time
+  */
+  std::string   get_last_zero_doppler_time()
+  {
+    return _last_zero_doppler_time;
+  };
+  /**
+  * @brief last_line_tie_points
+  */
+  std::string   get_last_line_tie_points()
+  {
+    return _last_line_tie_points;
+  };
+
+
+  /**
+  * @brief first_zero_doppler_time day
+  */
+  int   _first_zero_doppler_time_day;
+  /**
+  * @brief first_zero_doppler_time sec
+  */
+  unsigned int   _first_zero_doppler_time_sec;
+  /**
+  * @brief first_zero_doppler_time microsec
+  */
+  unsigned int   _first_zero_doppler_time_microsec;
+  /**
+  * @brief attach_flag
+  */
+  bool   _attach_flag;
+  /**
+  * @brief line_num
+  */
+  unsigned int   _line_num;
+  /**
+  * @brief num_lines
+  */
+  unsigned int   _num_lines;
+  /**
+  * @brief sub_sat_track
+  */
+  float   _sub_sat_track;
+  /**
+  * @brief samp_numbers
+  */
+  unsigned int  _samp_numbers[11];
+  /**
+  * @brief slant_range_times[11]
+  */
+  float  _slant_range_times[11];
+  /**
+  * @brief angles[11]
+  */
+  float  _angles[11];
+  /**
+  * @brief lats[11]
+  */
+  int  _lats[11];
+  /**
+  * @brief longs[11]
+  */
+  int  _longs[11];
+  /**
+  * @brief last_zero_doppler_time
+  */
+  std::string   _last_zero_doppler_time;
+  /**
+  * @brief last_line_tie_points
+  */
+  std::string   _last_line_tie_points;
+
+
+private:
+
+};
+}
+#endif
+
+
+
diff --git a/ossim_plugins/ossim/EnvisatAsar/MainProcessingParameters.cpp b/ossim_plugins/ossim/EnvisatAsar/MainProcessingParameters.cpp
new file mode 100644
index 0000000..e4dc4a6
--- /dev/null
+++ b/ossim_plugins/ossim/EnvisatAsar/MainProcessingParameters.cpp
@@ -0,0 +1,990 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include <EnvisatAsar/MainProcessingParameters.h>
+
+namespace ossimplugins
+{
+
+   MainProcessingParameters::MainProcessingParameters() : EnvisatAsarRecord("MainProcessingParameters_rec")
+   {
+   }
+
+   MainProcessingParameters::~MainProcessingParameters()
+   {
+   }
+
+   std::ostream& operator<<(std::ostream& os, const MainProcessingParameters& data)
+   {
+      os<<"first_zero_doppler_time:"<<data._first_zero_doppler_time.c_str()<<std::endl;
+
+      os<<"attach_flag:"<<data._attach_flag<<std::endl;
+
+      os<<"last_zero_doppler_time:"<<data._last_zero_doppler_time.c_str()<<std::endl;
+
+      os<<"work_order_id:"<<data._work_order_id.c_str()<<std::endl;
+
+      os<<"time_diff:"<<data._time_diff<<std::endl;
+
+      os<<"swath_num:"<<data._swath_num.c_str()<<std::endl;
+
+      os<<"range_spacing:"<<data._range_spacing<<std::endl;
+
+      os<<"azimut_spacing:"<<data._azimut_spacing<<std::endl;
+
+      os<<"line_time_interval:"<<data._line_time_interval<<std::endl;
+
+      os<<"num_output_lines:"<<data._num_output_lines<<std::endl;
+
+      os<<"num_samples_per_line:"<<data._num_samples_per_line<<std::endl;
+
+      os<<"data_type:"<<data._data_type.c_str()<<std::endl;
+
+      os<<"num_range_lines_per_burst:"<<data._num_range_lines_per_burst<<std::endl;
+
+      os<<"time_diff_zero_doppler:"<<data._time_diff_zero_doppler<<std::endl;
+
+      os<<"data_analysis_flag:"<<data._data_analysis_flag<<std::endl;
+
+      os<<"ant_elev_coor_flag:"<<data._ant_elev_coor_flag<<std::endl;
+
+      os<<"chirp_extract_flag:"<<data._chirp_extract_flag<<std::endl;
+
+      os<<"srgr_flag:"<<data._srgr_flag<<std::endl;
+
+      os<<"dop_cen_flag:"<<data._dop_cen_flag<<std::endl;
+
+      os<<"dop_amb_flag:"<<data._dop_amb_flag<<std::endl;
+
+      os<<"range_spread_comp_flag:"<<data._range_spread_comp_flag<<std::endl;
+
+      os<<"detected_flag:"<<data._detected_flag<<std::endl;
+
+      os<<"look_sum_flag:"<<data._look_sum_flag<<std::endl;
+
+      os<<"rms_equal_flag:"<<data._rms_equal_flag<<std::endl;
+
+      os<<"ant_scal_flag:"<<data._ant_scal_flag<<std::endl;
+
+      os<<"vga_com_echo_flag:"<<data._vga_com_echo_flag<<std::endl;
+
+      os<<"vga_com_cal_flag:"<<data._vga_com_cal_flag<<std::endl;
+
+      os<<"vga_com_nom_time_flag:"<<data._vga_com_nom_time_flag<<std::endl;
+
+      os<<"gm_rng_comp_inv_filter_flag:"<<data._gm_rng_comp_inv_filter_flag<<std::endl;
+
+      os<<"raw_data_analysis:"<<data._raw_data_analysis.c_str()<<std::endl;
+
+      os<<"start_time_mds1:"<<data._start_time_mds1.c_str()<<std::endl;
+
+      os<<"start_time_mds2:"<<data._start_time_mds2.c_str()<<std::endl;
+
+      os<<"parameter_code:"<<data._parameter_code.c_str()<<std::endl;
+
+      os<<"errors_counters:"<<data._errors_counters.c_str()<<std::endl;
+
+      os<<"image_parameters 1:"<<data._image_parameters1.c_str()<<std::endl;
+
+      os<<"prf_values[0]:"<<data._prf_values[0]<<std::endl;
+
+      os<<"image_parameters 1:"<<data._image_parameters2.c_str()<<std::endl;
+
+      os<<"first_proc_range_samp:"<<data._first_proc_range_samp<<std::endl;
+
+      os<<"range_ref:"<<data._range_ref<<std::endl;
+
+      os<<"range_samp_rate:"<<data._range_samp_rate<<std::endl;
+
+      os<<"radar_freq:"<<data._radar_freq<<std::endl;
+
+      os<<"num_looks_range:"<<data._num_looks_range<<std::endl;
+
+      os<<"filter_range:"<<data._filter_range.c_str()<<std::endl;
+
+      os<<"filter_coef_range:"<<data._filter_coef_range<<std::endl;
+
+      os<<"bandwidth:"<<data._bandwidth.c_str()<<std::endl;
+
+      os<<"nominal_chirp:"<<data._nominal_chirp.c_str()<<std::endl;
+
+      os<<"num_lines_proc:"<<data._num_lines_proc<<std::endl;
+
+      os<<"num_look_az:"<<data._num_look_az<<std::endl;
+
+      os<<"look_bw_az:"<<data._look_bw_az<<std::endl;
+
+      os<<"to_bw_az:"<<data._to_bw_az<<std::endl;
+
+      os<<"filter_az:"<<data._filter_az.c_str()<<std::endl;
+
+      os<<"filter_coef_az:"<<data._filter_coef_az<<std::endl;
+
+      os<<"az_fm_rate[0]:"<<data._az_fm_rate[0]<<std::endl;
+      os<<"az_fm_rate[1]:"<<data._az_fm_rate[1]<<std::endl;
+      os<<"az_fm_rate[2]:"<<data._az_fm_rate[2]<<std::endl;
+
+      os<<"ax_fm_origin:"<<data._ax_fm_origin<<std::endl;
+
+      os<<"dop_amb_coef:"<<data._dop_amb_coef<<std::endl;
+
+      os<<"calibration_factors:"<<data._calibration_factors.c_str()<<std::endl;
+
+      os<<"noise_estimation:"<<data._noise_estimation.c_str()<<std::endl;
+
+      os<<"output_statistics:"<<data._output_statistics.c_str()<<std::endl;
+
+      os<<"avg_scene_height_ellpsoid:"<<data._avg_scene_height_ellpsoid<<std::endl;
+
+      os<<"echo_comp:"<<data._echo_comp.c_str()<<std::endl;
+
+      os<<"echo_comp_ratio:"<<data._echo_comp_ratio.c_str()<<std::endl;
+
+      os<<"init_cal_comp:"<<data._init_cal_comp.c_str()<<std::endl;
+
+      os<<"init_cal_ratio:"<<data._init_cal_ratio.c_str()<<std::endl;
+
+      os<<"per_cal_comp:"<<data._per_cal_comp.c_str()<<std::endl;
+
+      os<<"per_cal_ratio:"<<data._per_cal_ratio.c_str()<<std::endl;
+
+      os<<"noise_comp:"<<data._noise_comp.c_str()<<std::endl;
+
+      os<<"noise_comp_ratio:"<<data._noise_comp_ratio.c_str()<<std::endl;
+
+      os<<"beam_overlap[0]:"<<data._beam_overlap[0]<<std::endl;
+      os<<"beam_overlap[1]:"<<data._beam_overlap[1]<<std::endl;
+      os<<"beam_overlap[2]:"<<data._beam_overlap[2]<<std::endl;
+      os<<"beam_overlap[3]:"<<data._beam_overlap[3]<<std::endl;
+
+      os<<"lines_per_burst[0]:"<<data._lines_per_burst[0]<<std::endl;
+      os<<"lines_per_burst[1]:"<<data._lines_per_burst[1]<<std::endl;
+      os<<"lines_per_burst[2]:"<<data._lines_per_burst[2]<<std::endl;
+      os<<"lines_per_burst[3]:"<<data._lines_per_burst[3]<<std::endl;
+      os<<"lines_per_burst[4]:"<<data._lines_per_burst[4]<<std::endl;
+
+      os<<"time_first_SS1_echo:"<<data._time_first_SS1_echo.c_str()<<std::endl;
+
+      os<<"state_vector_time_1:"<<data._state_vector_time_1_day<<std::endl;
+
+      os<<"state_vector_time_1:"<<data._state_vector_time_1_sec<<std::endl;
+
+      os<<"state_vector_time_1:"<<data._state_vector_time_1_microsec<<std::endl;
+
+      os<<"x_pos_1:"<<data._x_pos_1<<std::endl;
+
+      os<<"y_pos_1:"<<data._y_pos_1<<std::endl;
+
+      os<<"z_pos_1:"<<data._z_pos_1<<std::endl;
+
+      os<<"x_vel_1:"<<data._x_vel_1<<std::endl;
+
+      os<<"y_vel_1:"<<data._y_vel_1<<std::endl;
+
+      os<<"z_vel_1:"<<data._z_vel_1<<std::endl;
+
+      os<<"state_vector_time_2:"<<data._state_vector_time_2_day<<std::endl;
+
+      os<<"state_vector_time_2:"<<data._state_vector_time_2_sec<<std::endl;
+
+      os<<"state_vector_time_2:"<<data._state_vector_time_2_microsec<<std::endl;
+
+      os<<"x_pos_2:"<<data._x_pos_2<<std::endl;
+
+      os<<"y_pos_2:"<<data._y_pos_2<<std::endl;
+
+      os<<"z_pos_2:"<<data._z_pos_2<<std::endl;
+
+      os<<"x_vel_2:"<<data._x_vel_2<<std::endl;
+
+      os<<"y_vel_2:"<<data._y_vel_2<<std::endl;
+
+      os<<"z_vel_2:"<<data._z_vel_2<<std::endl;
+
+      os<<"state_vector_time_3:"<<data._state_vector_time_3_day<<std::endl;
+
+      os<<"state_vector_time_3:"<<data._state_vector_time_3_sec<<std::endl;
+
+      os<<"state_vector_time_3:"<<data._state_vector_time_3_microsec<<std::endl;
+
+      os<<"x_pos_3:"<<data._x_pos_3<<std::endl;
+
+      os<<"y_pos_3:"<<data._y_pos_3<<std::endl;
+
+      os<<"z_pos_3:"<<data._z_pos_3<<std::endl;
+
+      os<<"x_vel_3:"<<data._x_vel_3<<std::endl;
+
+      os<<"y_vel_3:"<<data._y_vel_3<<std::endl;
+
+      os<<"z_vel_3:"<<data._z_vel_3<<std::endl;
+
+      os<<"state_vector_time_4:"<<data._state_vector_time_4_day<<std::endl;
+
+      os<<"state_vector_time_4:"<<data._state_vector_time_4_sec<<std::endl;
+
+      os<<"state_vector_time_4:"<<data._state_vector_time_4_microsec<<std::endl;
+
+      os<<"x_pos_4:"<<data._x_pos_4<<std::endl;
+
+      os<<"y_pos_4:"<<data._y_pos_4<<std::endl;
+
+      os<<"z_pos_4:"<<data._z_pos_4<<std::endl;
+
+      os<<"x_vel_4:"<<data._x_vel_4<<std::endl;
+
+      os<<"y_vel_4:"<<data._y_vel_4<<std::endl;
+
+      os<<"z_vel_4:"<<data._z_vel_4<<std::endl;
+
+      os<<"state_vector_time_5:"<<data._state_vector_time_5_day<<std::endl;
+
+      os<<"state_vector_time_5:"<<data._state_vector_time_5_sec<<std::endl;
+
+      os<<"state_vector_time_5:"<<data._state_vector_time_5_microsec<<std::endl;
+
+      os<<"x_pos_5:"<<data._x_pos_5<<std::endl;
+
+      os<<"y_pos_5:"<<data._y_pos_5<<std::endl;
+
+      os<<"z_pos_5:"<<data._z_pos_5<<std::endl;
+
+      os<<"x_vel_5:"<<data._x_vel_5<<std::endl;
+
+      os<<"y_vel_5:"<<data._y_vel_5<<std::endl;
+
+      os<<"z_vel_5:"<<data._z_vel_5<<std::endl;
+
+      return os;
+
+   }
+
+   std::istream& operator>>(std::istream& is, MainProcessingParameters& data)
+   {
+      char buf64[65];
+      buf64[64] = '\0';
+      char buf32[33];
+      buf32[32] = '\0';
+      // char buf27[28];
+      // buf27[27] = '\0';
+      char buf20[21];
+      buf20[20] = '\0';
+      char buf16[17];
+      buf16[16]='\0';
+      // char buf15[16];
+      // buf15[15] = '\0';
+      // char buf14[15];
+      // buf14[14] = '\0';
+      // char buf13[14];
+      // buf13[13] = '\0';
+      char buf12[13];
+      buf12[12] = '\0';
+      // char buf11[12];
+      // buf11[11] = '\0';
+      // char buf10[11];
+      // buf10[10] = '\0';
+      // char buf9[10];
+      // buf9[9] = '\0';
+      // char buf8[9];
+      // buf8[8] = '\0';
+      char buf7[8];
+      buf7[7] = '\0';
+      char buf6[7];
+      buf6[6] = '\0';
+      char buf5[6];
+      buf5[5] = '\0';
+      char buf4[5];
+      buf4[4] = '\0';
+      char buf3[4];
+      buf3[3] = '\0';
+      // char buf2[3];
+      // buf2[2] = '\0';
+//	char buf1[1]; // not used avoid warning
+
+//	int * var_long; // not used avoid warning
+
+      is.read(buf12,12);
+      data._first_zero_doppler_time = buf12;
+
+      is.read((char*)&(data._attach_flag),1);
+
+      is.read(buf12,12);
+      data._last_zero_doppler_time = buf12;
+
+      is.read(buf12,12);
+      data._work_order_id = buf12;
+
+      is.read((char*)&(data._time_diff),4);
+      data.SwitchEndian(data._time_diff);
+
+      is.read(buf3,3);
+      data._swath_num = buf3;
+
+      is.read((char*)&(data._range_spacing),4);
+      data.SwitchEndian(data._range_spacing);
+
+      is.read((char*)&(data._azimut_spacing),4);
+      data.SwitchEndian(data._azimut_spacing);
+
+      is.read((char*)&(data._line_time_interval),4);
+      data.SwitchEndian(data._line_time_interval);
+
+      is.read((char*)&(data._num_output_lines),4);
+      data.SwitchEndian(data._num_output_lines);
+
+      is.read((char*)&(data._num_samples_per_line),4);
+      data.SwitchEndian(data._num_samples_per_line);
+
+      is.read(buf5,5);
+      data._data_type = buf5;
+
+      is.read((char*)&(data._num_range_lines_per_burst),4);
+      data.SwitchEndian(data._num_range_lines_per_burst);
+
+      is.read((char*)&(data._time_diff_zero_doppler),4);
+      data.SwitchEndian(data._time_diff_zero_doppler);
+
+      is.read(buf64,43);
+
+      is.read((char*)&(data._data_analysis_flag),1);
+
+      is.read((char*)&(data._ant_elev_coor_flag),1);
+
+      is.read((char*)&(data._chirp_extract_flag),1);
+
+      is.read((char*)&(data._srgr_flag),1);
+
+      is.read((char*)&(data._dop_cen_flag),1);
+
+      is.read((char*)&(data._dop_amb_flag),1);
+
+      is.read((char*)&(data._range_spread_comp_flag),1);
+
+      is.read((char*)&(data._detected_flag),1);
+
+      is.read((char*)&(data._look_sum_flag),1);
+
+      is.read((char*)&(data._rms_equal_flag),1);
+
+      is.read((char*)&(data._ant_scal_flag),1);
+
+      is.read((char*)&(data._vga_com_echo_flag),1);
+
+      is.read((char*)&(data._vga_com_cal_flag),1);
+
+      is.read((char*)&(data._vga_com_nom_time_flag),1);
+
+      is.read((char*)&(data._gm_rng_comp_inv_filter_flag),1);
+
+      is.read(buf6,6);
+
+      char buf184[185];
+      buf184[184] = '\0';
+      is.read(buf184,184);
+      data._raw_data_analysis = buf184;
+
+      is.read(buf32,32);
+
+      is.read(buf20,20);
+      data._start_time_mds1 = buf20;
+
+      is.read(buf20,20);
+      data._start_time_mds2 = buf20;
+
+      char buf120[121];
+      buf120[120] = '\0';
+      is.read(buf120,120);
+      data._parameter_code = buf120;
+
+      is.read(buf64,60);
+
+      is.read(buf64,40);
+      buf64[40] = '\0';
+      data._errors_counters = buf64;
+
+      is.read(buf32,26);
+
+      is.read(buf64,60);
+      buf64[60] = '\0';
+      data._image_parameters1 = buf64;
+
+      for (int i = 0; i<5; i++)
+      {
+         is.read((char*)&(data._prf_values[i]),4);
+         data.SwitchEndian(data._prf_values[i]);
+      }
+
+      char buf190[191];
+      buf190[190] = '\0';
+      is.read(buf190,190);
+      data._image_parameters2 = buf190;
+
+      is.read(buf64,62);
+
+      is.read((char*)&(data._first_proc_range_samp),4);
+      data.SwitchEndian(data._first_proc_range_samp);
+
+      is.read((char*)&(data._range_ref),4);
+      data.SwitchEndian(data._range_ref);
+
+      is.read((char*)&(data._range_samp_rate),4);
+      data.SwitchEndian(data._range_samp_rate);
+
+      is.read((char*)&(data._radar_freq),4);
+      data.SwitchEndian(data._radar_freq);
+
+      is.read((char*)&(data._num_looks_range),2);
+      data.SwitchEndian(data._num_looks_range);
+
+      is.read(buf7,7);
+      data._filter_range = buf7;
+
+      is.read((char*)&(data._filter_coef_range),4);
+      data.SwitchEndian(data._filter_coef_range);
+
+      is.read(buf64,40);
+      buf64[40] = '\0';
+      data._bandwidth = buf64;
+
+      char buf160[161];
+      buf160[160] = '\0';
+      is.read(buf160,160);
+      data._nominal_chirp = buf160;
+
+      is.read(buf64,60);
+
+      is.read((char*)&(data._num_lines_proc),4);
+      data.SwitchEndian(data._num_lines_proc);
+
+      is.read((char*)&(data._num_look_az),2);
+      data.SwitchEndian(data._num_look_az);
+
+      is.read((char*)&(data._look_bw_az),4);
+      data.SwitchEndian(data._look_bw_az);
+
+      is.read((char*)&(data._to_bw_az),4);
+      data.SwitchEndian(data._to_bw_az);
+
+      is.read(buf7,7);
+      data._filter_az = buf7;
+
+      is.read((char*)&(data._filter_coef_az),4);
+      data.SwitchEndian(data._filter_coef_az);
+
+      for (int i = 0; i <3; i++) {
+         is.read((char*)&(data._az_fm_rate[i]),4);
+         data.SwitchEndian(data._az_fm_rate[i]);
+      }
+
+      is.read((char*)&(data._ax_fm_origin),4);
+      data.SwitchEndian(data._ax_fm_origin);
+
+      is.read((char*)&(data._dop_amb_coef),4);
+      data.SwitchEndian(data._dop_amb_coef);
+
+      char buf128[129];
+      buf128[128] = '\0';
+      is.read(buf128,68);
+
+      is.read(buf16,16);
+      data._calibration_factors = buf16;
+
+      is.read(buf64,40);
+      buf64[40]='\0';
+      data._noise_estimation = buf64;
+
+      is.read(buf64,64);
+
+      is.read(buf12,12);
+
+      is.read(buf32,32);
+      data._output_statistics = buf32;
+
+      is.read((char*)&(data._avg_scene_height_ellpsoid),4);
+      data.SwitchEndian(data._avg_scene_height_ellpsoid);
+
+      is.read(buf64,48);
+
+      is.read(buf4,4);
+      data._echo_comp = buf4;
+
+      is.read(buf3,3);
+      data._echo_comp_ratio = buf3;
+
+      is.read(buf4,4);
+      data._init_cal_comp = buf4;
+
+      is.read(buf3,3);
+      data._init_cal_ratio = buf3;
+
+      is.read(buf4,4);
+      data._per_cal_comp = buf4;
+
+      is.read(buf3,3);
+      data._per_cal_ratio = buf3;
+
+      is.read(buf4,4);
+      data._noise_comp = buf4;
+
+      is.read(buf3,3);
+      data._noise_comp_ratio = buf3;
+
+      is.read(buf64,64);
+
+      for (int i=0;i<4;i++)
+      {
+         is.read((char*)&(data._beam_overlap[i]),4);
+         data.SwitchEndian(data._beam_overlap[i]);
+      }
+      for (int i=0;i<4;i++)
+      {
+         is.read((char*)&(data._beam_param[i]),4);
+         data.SwitchEndian(data._beam_param[i]);
+      }
+      for (int i=0;i<5;i++)
+      {
+         is.read((char*)&(data._lines_per_burst[i]),4);
+         data.SwitchEndian(data._lines_per_burst[i]);
+      }
+
+      is.read(buf12,12);
+      data._time_first_SS1_echo = buf12;
+
+      is.read(buf16,16);
+
+      is.read((char*)&(data._state_vector_time_1_day),4);
+      data.SwitchEndian(data._state_vector_time_1_day);
+
+      is.read((char*)&(data._state_vector_time_1_sec),4);
+      data.SwitchEndian(data._state_vector_time_1_sec);
+
+      is.read((char*)&(data._state_vector_time_1_microsec),4);
+      data.SwitchEndian(data._state_vector_time_1_microsec);
+
+      is.read((char*)&(data._x_pos_1),4);
+      data.SwitchEndian(data._x_pos_1);
+
+      is.read((char*)&(data._y_pos_1),4);
+      data.SwitchEndian(data._y_pos_1);
+
+      is.read((char*)&(data._z_pos_1),4);
+      data.SwitchEndian(data._z_pos_1);
+
+      is.read((char*)&(data._x_vel_1),4);
+      data.SwitchEndian(data._x_vel_1);
+
+      is.read((char*)&(data._y_vel_1),4);
+      data.SwitchEndian(data._y_vel_1);
+
+      is.read((char*)&(data._z_vel_1),4);
+      data.SwitchEndian(data._z_vel_1);
+
+      is.read((char*)&(data._state_vector_time_2_day),4);
+      data.SwitchEndian(data._state_vector_time_2_day);
+
+      is.read((char*)&(data._state_vector_time_2_sec),4);
+      data.SwitchEndian(data._state_vector_time_2_sec);
+
+      is.read((char*)&(data._state_vector_time_2_microsec),4);
+      data.SwitchEndian(data._state_vector_time_2_microsec);
+
+      is.read((char*)&(data._x_pos_2),4);
+      data.SwitchEndian(data._x_pos_2);
+
+      is.read((char*)&(data._y_pos_2),4);
+      data.SwitchEndian(data._y_pos_2);
+
+      is.read((char*)&(data._z_pos_2),4);
+      data.SwitchEndian(data._z_pos_2);
+
+      is.read((char*)&(data._x_vel_2),4);
+      data.SwitchEndian(data._x_vel_2);
+
+      is.read((char*)&(data._y_vel_2),4);
+      data.SwitchEndian(data._y_vel_2);
+
+      is.read((char*)&(data._z_vel_2),4);
+      data.SwitchEndian(data._z_vel_2);
+
+      is.read((char*)&(data._state_vector_time_3_day),4);
+      data.SwitchEndian(data._state_vector_time_3_day);
+
+      is.read((char*)&(data._state_vector_time_3_sec),4);
+      data.SwitchEndian(data._state_vector_time_3_sec);
+
+      is.read((char*)&(data._state_vector_time_3_microsec),4);
+      data.SwitchEndian(data._state_vector_time_3_microsec);
+
+      is.read((char*)&(data._x_pos_3),4);
+      data.SwitchEndian(data._x_pos_3);
+
+      is.read((char*)&(data._y_pos_3),4);
+      data.SwitchEndian(data._y_pos_3);
+
+      is.read((char*)&(data._z_pos_3),4);
+      data.SwitchEndian(data._z_pos_3);
+
+      is.read((char*)&(data._x_vel_3),4);
+      data.SwitchEndian(data._x_vel_3);
+
+      is.read((char*)&(data._y_vel_3),4);
+      data.SwitchEndian(data._y_vel_3);
+
+      is.read((char*)&(data._z_vel_3),4);
+      data.SwitchEndian(data._z_vel_3);
+
+      is.read((char*)&(data._state_vector_time_4_day),4);
+      data.SwitchEndian(data._state_vector_time_4_day);
+
+      is.read((char*)&(data._state_vector_time_4_sec),4);
+      data.SwitchEndian(data._state_vector_time_4_sec);
+
+      is.read((char*)&(data._state_vector_time_4_microsec),4);
+      data.SwitchEndian(data._state_vector_time_4_microsec);
+
+      is.read((char*)&(data._x_pos_4),4);
+      data.SwitchEndian(data._x_pos_4);
+
+      is.read((char*)&(data._y_pos_4),4);
+      data.SwitchEndian(data._y_pos_4);
+
+      is.read((char*)&(data._z_pos_4),4);
+      data.SwitchEndian(data._z_pos_4);
+
+      is.read((char*)&(data._x_vel_4),4);
+      data.SwitchEndian(data._x_vel_4);
+
+      is.read((char*)&(data._y_vel_4),4);
+      data.SwitchEndian(data._y_vel_4);
+
+      is.read((char*)&(data._z_vel_4),4);
+      data.SwitchEndian(data._z_vel_4);
+
+      is.read((char*)&(data._state_vector_time_5_day),4);
+      data.SwitchEndian(data._state_vector_time_5_day);
+
+      is.read((char*)&(data._state_vector_time_5_sec),4);
+      data.SwitchEndian(data._state_vector_time_5_sec);
+
+      is.read((char*)&(data._state_vector_time_5_microsec),4);
+      data.SwitchEndian(data._state_vector_time_5_microsec);
+
+      is.read((char*)&(data._x_pos_5),4);
+      data.SwitchEndian(data._x_pos_5);
+
+      is.read((char*)&(data._y_pos_5),4);
+      data.SwitchEndian(data._y_pos_5);
+
+      is.read((char*)&(data._z_pos_5),4);
+      data.SwitchEndian(data._z_pos_5);
+
+      is.read((char*)&(data._x_vel_5),4);
+      data.SwitchEndian(data._x_vel_5);
+
+      is.read((char*)&(data._y_vel_5),4);
+      data.SwitchEndian(data._y_vel_5);
+
+      is.read((char*)&(data._z_vel_5),4);
+      data.SwitchEndian(data._z_vel_5);
+
+      is.read(buf64,64);
+
+      return is;
+
+   }
+
+   MainProcessingParameters::MainProcessingParameters(const MainProcessingParameters& rhs):
+      EnvisatAsarRecord(rhs),
+      _first_zero_doppler_time(rhs._first_zero_doppler_time),
+      _attach_flag(rhs._attach_flag),
+      _last_zero_doppler_time(rhs._last_zero_doppler_time),
+      _work_order_id(rhs._work_order_id),
+      _time_diff(rhs._time_diff),
+      _swath_num(rhs._swath_num),
+      _range_spacing(rhs._range_spacing),
+      _azimut_spacing(rhs._azimut_spacing),
+      _line_time_interval(rhs._line_time_interval),
+      _num_output_lines(rhs._num_output_lines),
+      _num_samples_per_line(rhs._num_samples_per_line),
+      _data_type(rhs._data_type),
+      _num_range_lines_per_burst(rhs._num_range_lines_per_burst),
+      _time_diff_zero_doppler(rhs._time_diff_zero_doppler),
+      _data_analysis_flag(rhs._data_analysis_flag),
+      _ant_elev_coor_flag(rhs._ant_elev_coor_flag),
+      _chirp_extract_flag(rhs._chirp_extract_flag),
+      _srgr_flag(rhs._srgr_flag),
+      _dop_cen_flag(rhs._dop_cen_flag),
+      _dop_amb_flag(rhs._dop_amb_flag),
+      _range_spread_comp_flag(rhs._range_spread_comp_flag),
+      _detected_flag(rhs._detected_flag),
+      _look_sum_flag(rhs._look_sum_flag),
+      _rms_equal_flag(rhs._rms_equal_flag),
+      _ant_scal_flag(rhs._ant_scal_flag),
+      _vga_com_echo_flag(rhs._vga_com_echo_flag),
+      _vga_com_cal_flag(rhs._vga_com_cal_flag),
+      _vga_com_nom_time_flag(rhs._vga_com_nom_time_flag),
+      _gm_rng_comp_inv_filter_flag(rhs._gm_rng_comp_inv_filter_flag),
+      _raw_data_analysis(rhs._raw_data_analysis),
+      _start_time_mds1(rhs._start_time_mds1),
+      _start_time_mds2(rhs._start_time_mds2),
+      _parameter_code(rhs._parameter_code),
+      _errors_counters(rhs._errors_counters),
+      _image_parameters1(rhs._image_parameters1),
+      _image_parameters2(rhs._image_parameters2),
+      _first_proc_range_samp(rhs._first_proc_range_samp),
+      _range_ref(rhs._range_ref),
+      _range_samp_rate(rhs._range_samp_rate),
+      _radar_freq(rhs._radar_freq),
+      _num_looks_range(rhs._num_looks_range),
+      _filter_range(rhs._filter_range),
+      _filter_coef_range(rhs._filter_coef_range),
+      _bandwidth(rhs._bandwidth),
+      _nominal_chirp(rhs._nominal_chirp),
+      _num_lines_proc(rhs._num_lines_proc),
+      _num_look_az(rhs._num_look_az),
+      _look_bw_az(rhs._look_bw_az),
+      _to_bw_az(rhs._to_bw_az),
+      _filter_az(rhs._filter_az),
+      _filter_coef_az(rhs._filter_coef_az),
+      _ax_fm_origin(rhs._ax_fm_origin),
+      _dop_amb_coef(rhs._dop_amb_coef),
+      _calibration_factors(rhs._calibration_factors),
+      _noise_estimation(rhs._noise_estimation),
+      _output_statistics(rhs._output_statistics),
+      _avg_scene_height_ellpsoid(rhs._avg_scene_height_ellpsoid),
+      _echo_comp(rhs._echo_comp),
+      _echo_comp_ratio(rhs._echo_comp_ratio),
+      _init_cal_comp(rhs._init_cal_comp),
+      _init_cal_ratio(rhs._init_cal_ratio),
+      _per_cal_comp(rhs._per_cal_comp),
+      _per_cal_ratio(rhs._per_cal_ratio),
+      _noise_comp(rhs._noise_comp),
+      _noise_comp_ratio(rhs._noise_comp_ratio),
+      _time_first_SS1_echo(rhs._time_first_SS1_echo),
+      _state_vector_time_1_day(rhs._state_vector_time_1_day),
+      _state_vector_time_1_sec(rhs._state_vector_time_1_sec),
+      _state_vector_time_1_microsec(rhs._state_vector_time_1_microsec),
+      _x_pos_1(rhs._x_pos_1),
+      _y_pos_1(rhs._y_pos_1),
+      _z_pos_1(rhs._z_pos_1),
+      _x_vel_1(rhs._x_vel_1),
+      _y_vel_1(rhs._y_vel_1),
+      _z_vel_1(rhs._z_vel_1),
+      _state_vector_time_2_day(rhs._state_vector_time_2_day),
+      _state_vector_time_2_sec(rhs._state_vector_time_2_sec),
+      _state_vector_time_2_microsec(rhs._state_vector_time_2_microsec),
+      _x_pos_2(rhs._x_pos_2),
+      _y_pos_2(rhs._y_pos_2),
+      _z_pos_2(rhs._z_pos_2),
+      _x_vel_2(rhs._x_vel_2),
+      _y_vel_2(rhs._y_vel_2),
+      _z_vel_2(rhs._z_vel_2),
+      _state_vector_time_3_day(rhs._state_vector_time_3_day),
+      _state_vector_time_3_sec(rhs._state_vector_time_3_sec),
+      _state_vector_time_3_microsec(rhs._state_vector_time_3_microsec),
+      _x_pos_3(rhs._x_pos_3),
+      _y_pos_3(rhs._y_pos_3),
+      _z_pos_3(rhs._z_pos_3),
+      _x_vel_3(rhs._x_vel_3),
+      _y_vel_3(rhs._y_vel_3),
+      _z_vel_3(rhs._z_vel_3),
+      _state_vector_time_4_day(rhs._state_vector_time_4_day),
+      _state_vector_time_4_sec(rhs._state_vector_time_4_sec),
+      _state_vector_time_4_microsec(rhs._state_vector_time_4_microsec),
+      _x_pos_4(rhs._x_pos_4),
+      _y_pos_4(rhs._y_pos_4),
+      _z_pos_4(rhs._z_pos_4),
+      _x_vel_4(rhs._x_vel_4),
+      _y_vel_4(rhs._y_vel_4),
+      _z_vel_4(rhs._z_vel_4),
+      _state_vector_time_5_day(rhs._state_vector_time_5_day),
+      _state_vector_time_5_sec(rhs._state_vector_time_5_sec),
+      _state_vector_time_5_microsec(rhs._state_vector_time_5_microsec),
+      _x_pos_5(rhs._x_pos_5),
+      _y_pos_5(rhs._y_pos_5),
+      _z_pos_5(rhs._z_pos_5),
+      _x_vel_5(rhs._x_vel_5),
+      _y_vel_5(rhs._y_vel_5),
+      _z_vel_5(rhs._z_vel_5)
+   {
+      _az_fm_rate[0] = rhs._az_fm_rate[0];
+      _az_fm_rate[1] = rhs._az_fm_rate[1];
+      _az_fm_rate[2] = rhs._az_fm_rate[2];
+
+      _prf_values[0] = rhs._prf_values[0];
+      _prf_values[1] = rhs._prf_values[1];
+      _prf_values[2] = rhs._prf_values[2];
+      _prf_values[3] = rhs._prf_values[3];
+      _prf_values[4] = rhs._prf_values[4];
+
+      _beam_overlap[0]= rhs._beam_overlap[0];
+      _beam_overlap[1]= rhs._beam_overlap[1];
+      _beam_overlap[2]= rhs._beam_overlap[2];
+      _beam_overlap[3]= rhs._beam_overlap[3];
+
+      _beam_param[0]= rhs._beam_param[0];
+      _beam_param[1]= rhs._beam_param[1];
+      _beam_param[2]= rhs._beam_param[2];
+      _beam_param[3]= rhs._beam_param[3];
+
+      _lines_per_burst[0] =rhs._lines_per_burst[0];
+      _lines_per_burst[1] =rhs._lines_per_burst[1];
+      _lines_per_burst[2] =rhs._lines_per_burst[2];
+      _lines_per_burst[3] =rhs._lines_per_burst[3];
+      _lines_per_burst[4] =rhs._lines_per_burst[4];
+   }
+
+
+   MainProcessingParameters& MainProcessingParameters::operator=(const MainProcessingParameters& rhs)
+   {
+      _first_zero_doppler_time = rhs._first_zero_doppler_time;
+      _attach_flag = rhs._attach_flag;
+      _last_zero_doppler_time = rhs._last_zero_doppler_time;
+      _work_order_id = rhs._work_order_id;
+      _time_diff = rhs._time_diff;
+      _swath_num = rhs._swath_num;
+      _range_spacing = rhs._range_spacing;
+      _azimut_spacing = rhs._azimut_spacing;
+      _line_time_interval = rhs._line_time_interval;
+      _num_output_lines = rhs._num_output_lines;
+      _num_samples_per_line = rhs._num_samples_per_line;
+      _data_type = rhs._data_type;
+      _num_range_lines_per_burst = rhs._num_range_lines_per_burst;
+      _time_diff_zero_doppler = rhs._time_diff_zero_doppler;
+      _data_analysis_flag = rhs._data_analysis_flag;
+      _ant_elev_coor_flag = rhs._ant_elev_coor_flag;
+      _chirp_extract_flag = rhs._chirp_extract_flag;
+      _srgr_flag = rhs._srgr_flag;
+      _dop_cen_flag = rhs._dop_cen_flag;
+      _dop_amb_flag = rhs._dop_amb_flag;
+      _range_spread_comp_flag = rhs._range_spread_comp_flag;
+      _detected_flag = rhs._detected_flag;
+      _look_sum_flag = rhs._look_sum_flag;
+      _rms_equal_flag = rhs._rms_equal_flag;
+      _ant_scal_flag = rhs._ant_scal_flag;
+      _vga_com_echo_flag = rhs._vga_com_echo_flag;
+      _vga_com_cal_flag = rhs._vga_com_cal_flag;
+      _vga_com_nom_time_flag = rhs._vga_com_nom_time_flag;
+      _gm_rng_comp_inv_filter_flag = rhs._gm_rng_comp_inv_filter_flag;
+      _raw_data_analysis = rhs._raw_data_analysis;
+      _start_time_mds1 = rhs._start_time_mds1;
+      _start_time_mds2 = rhs._start_time_mds2;
+      _parameter_code = rhs._parameter_code;
+      _errors_counters = rhs._errors_counters;
+      _image_parameters1 = rhs._image_parameters1;
+      _image_parameters2 = rhs._image_parameters2;
+      _first_proc_range_samp = rhs._first_proc_range_samp;
+      _range_ref = rhs._range_ref;
+      _range_samp_rate = rhs._range_samp_rate;
+      _radar_freq = rhs._radar_freq;
+      _num_looks_range = rhs._num_looks_range;
+      _filter_range = rhs._filter_range;
+      _filter_coef_range = rhs._filter_coef_range;
+      _bandwidth = rhs._bandwidth;
+      _nominal_chirp = rhs._nominal_chirp;
+      _num_lines_proc = rhs._num_lines_proc;
+      _num_look_az = rhs._num_look_az;
+      _look_bw_az = rhs._look_bw_az;
+      _to_bw_az = rhs._to_bw_az;
+      _filter_az = rhs._filter_az;
+      _filter_coef_az = rhs._filter_coef_az;
+      _ax_fm_origin = rhs._ax_fm_origin;
+      _dop_amb_coef = rhs._dop_amb_coef;
+      _calibration_factors = rhs._calibration_factors;
+      _noise_estimation = rhs._noise_estimation;
+      _output_statistics = rhs._output_statistics;
+      _avg_scene_height_ellpsoid = rhs._avg_scene_height_ellpsoid;
+      _echo_comp = rhs._echo_comp;
+      _echo_comp_ratio = rhs._echo_comp_ratio;
+      _init_cal_comp = rhs._init_cal_comp;
+      _init_cal_ratio = rhs._init_cal_ratio;
+      _per_cal_comp = rhs._per_cal_comp;
+      _per_cal_ratio = rhs._per_cal_ratio;
+      _noise_comp = rhs._noise_comp;
+      _noise_comp_ratio = rhs._noise_comp_ratio;
+      _time_first_SS1_echo = rhs._time_first_SS1_echo;
+      _state_vector_time_1_day = rhs._state_vector_time_1_day;
+      _state_vector_time_1_sec = rhs._state_vector_time_1_sec;
+      _state_vector_time_1_microsec = rhs._state_vector_time_1_microsec;
+      _x_pos_1 = rhs._x_pos_1;
+      _y_pos_1 = rhs._y_pos_1;
+      _z_pos_1 = rhs._z_pos_1;
+      _x_vel_1 = rhs._x_vel_1;
+      _y_vel_1 = rhs._y_vel_1;
+      _z_vel_1 = rhs._z_vel_1;
+      _state_vector_time_2_day = rhs._state_vector_time_2_day;
+      _state_vector_time_2_sec = rhs._state_vector_time_2_sec;
+      _state_vector_time_2_microsec = rhs._state_vector_time_2_microsec;
+      _x_pos_2 = rhs._x_pos_2;
+      _y_pos_2 = rhs._y_pos_2;
+      _z_pos_2 = rhs._z_pos_2;
+      _x_vel_2 = rhs._x_vel_2;
+      _y_vel_2 = rhs._y_vel_2;
+      _z_vel_2 = rhs._z_vel_2;
+      _state_vector_time_3_day = rhs._state_vector_time_3_day;
+      _state_vector_time_3_sec = rhs._state_vector_time_3_sec;
+      _state_vector_time_3_microsec = rhs._state_vector_time_3_microsec;
+      _x_pos_3 = rhs._x_pos_3;
+      _y_pos_3 = rhs._y_pos_3;
+      _z_pos_3 = rhs._z_pos_3;
+      _x_vel_3 = rhs._x_vel_3;
+      _y_vel_3 = rhs._y_vel_3;
+      _z_vel_3 = rhs._z_vel_3;
+      _state_vector_time_4_day = rhs._state_vector_time_4_day;
+      _state_vector_time_4_sec = rhs._state_vector_time_4_sec;
+      _state_vector_time_4_microsec = rhs._state_vector_time_4_microsec;
+      _x_pos_4 = rhs._x_pos_4;
+      _y_pos_4 = rhs._y_pos_4;
+      _z_pos_4 = rhs._z_pos_4;
+      _x_vel_4 = rhs._x_vel_4;
+      _y_vel_4 = rhs._y_vel_4;
+      _z_vel_4 = rhs._z_vel_4;
+      _state_vector_time_5_day = rhs._state_vector_time_5_day;
+      _state_vector_time_5_sec = rhs._state_vector_time_5_sec;
+      _state_vector_time_5_microsec = rhs._state_vector_time_5_microsec;
+      _x_pos_5 = rhs._x_pos_5;
+      _y_pos_5 = rhs._y_pos_5;
+      _z_pos_5 = rhs._z_pos_5;
+      _x_vel_5 = rhs._x_vel_5;
+      _y_vel_5 = rhs._y_vel_5;
+      _z_vel_5 = rhs._z_vel_5;
+
+      _az_fm_rate[0] = rhs._az_fm_rate[0];
+      _az_fm_rate[1] = rhs._az_fm_rate[1];
+      _az_fm_rate[2] = rhs._az_fm_rate[2];
+
+      _prf_values[0] = rhs._prf_values[0];
+      _prf_values[1] = rhs._prf_values[1];
+      _prf_values[2] = rhs._prf_values[2];
+      _prf_values[3] = rhs._prf_values[3];
+      _prf_values[4] = rhs._prf_values[4];
+
+      _beam_overlap[0]= rhs._beam_overlap[0];
+      _beam_overlap[1]= rhs._beam_overlap[1];
+      _beam_overlap[2]= rhs._beam_overlap[2];
+      _beam_overlap[3]= rhs._beam_overlap[3];
+
+      _beam_param[0]= rhs._beam_param[0];
+      _beam_param[1]= rhs._beam_param[1];
+      _beam_param[2]= rhs._beam_param[2];
+      _beam_param[3]= rhs._beam_param[3];
+
+      _lines_per_burst[0] =rhs._lines_per_burst[0];
+      _lines_per_burst[1] =rhs._lines_per_burst[1];
+      _lines_per_burst[2] =rhs._lines_per_burst[2];
+      _lines_per_burst[3] =rhs._lines_per_burst[3];
+      _lines_per_burst[4] =rhs._lines_per_burst[4];
+
+      return *this;
+   }
+
+}
+
diff --git a/ossim_plugins/ossim/EnvisatAsar/MainProcessingParameters.h b/ossim_plugins/ossim/EnvisatAsar/MainProcessingParameters.h
new file mode 100644
index 0000000..fc21e90
--- /dev/null
+++ b/ossim_plugins/ossim/EnvisatAsar/MainProcessingParameters.h
@@ -0,0 +1,1384 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef MainProcessingParameters_h
+#define MainProcessingParameters_h
+
+#include <iostream>
+#include <sstream>
+#include <EnvisatAsar/EnvisatAsarRecord.h>
+
+namespace ossimplugins
+{
+/**
+ * @ingroup MainProcessingParametersRecord
+ * @brief This class is able to read the ASAR MainProcessingParameters record
+ */
+class MainProcessingParameters : public EnvisatAsarRecord
+{
+public:
+  /**
+   * @brief Constructor
+   */
+  MainProcessingParameters();
+
+  /**
+   * @brief Destructor
+   */
+  virtual ~MainProcessingParameters();
+
+  /**
+   * @brief This function writes the MainProcessingParameters in a stream
+   */
+  friend std::ostream& operator<<(std::ostream& os, const MainProcessingParameters& data);
+
+  /**
+   * @brief This function reads a MainProcessingParameters from a stream
+   */
+  friend std::istream& operator>>(std::istream& is, MainProcessingParameters& data);
+
+  /**
+   * @brief Copy constructor
+   */
+  MainProcessingParameters(const MainProcessingParameters& rhs);
+
+  /**
+   * @brief Copy operator
+   */
+  MainProcessingParameters& operator=(const MainProcessingParameters& rhs);
+
+  /**
+   * @brief This function is able to create a new instance of the class
+   */
+  EnvisatAsarRecord* Instanciate()
+  {
+    return new MainProcessingParameters();
+  };
+
+  /**
+   * @brief This function is able to create a new instance of the class initialised with the data of the calling instance
+   */
+  EnvisatAsarRecord* Clone()
+  {
+    return new MainProcessingParameters(*this);
+  };
+
+  /**
+   * @brief Reads the class data from a stream
+   */
+  void Read(std::istream& is)
+  {
+    is>>*this;
+  };
+
+  /**
+   * @brief Writes the class to a stream
+   */
+  void Write(std::ostream& os)
+  {
+    os<<*this;
+  };
+
+
+  /**
+  * @brief first_zero_doppler_time
+  */
+  std::string   get_first_zero_doppler_time()
+  {
+    return _first_zero_doppler_time;
+  };
+  /**
+  * @brief attach_flag
+  */
+  bool   get_attach_flag()
+  {
+    return _attach_flag;
+  };
+  /**
+  * @brief last_zero_doppler_time
+  */
+  std::string   get_last_zero_doppler_time()
+  {
+    return _last_zero_doppler_time;
+  };
+  /**
+  * @brief work_order_id
+  */
+  std::string   get_work_order_id()
+  {
+    return _work_order_id;
+  };
+  /**
+  * @brief time_diff
+  */
+  float  get_time_diff()
+  {
+    return _time_diff;
+  };
+  /**
+  * @brief swath_num
+  */
+  std::string   get_swath_num()
+  {
+    return _swath_num;
+  };
+  /**
+  * @brief range_spacing
+  */
+  float  get_range_spacing()
+  {
+    return _range_spacing;
+  };
+  /**
+  * @brief azimut_spacing
+  */
+  float  get_azimut_spacing()
+  {
+    return _azimut_spacing;
+  };
+  /**
+  * @brief line_time_interval
+  */
+  float  get_line_time_interval()
+  {
+    return _line_time_interval;
+  };
+  /**
+  * @brief num_output_lines
+  */
+  unsigned int  get_num_output_lines()
+  {
+    return _num_output_lines;
+  };
+  /**
+  * @brief num_samples_per_line
+  */
+  unsigned int  get_num_samples_per_line()
+  {
+    return _num_samples_per_line;
+  };
+  /**
+  * @brief data_type
+  */
+  std::string   get_data_type()
+  {
+    return _data_type;
+  };
+  /**
+  * @brief num_range_lines_per_burst
+  */
+  unsigned int  get_num_range_lines_per_burst()
+  {
+    return _num_range_lines_per_burst;
+  };
+  /**
+  * @brief time_diff_zero_doppler
+  */
+  float  get_time_diff_zero_doppler()
+  {
+    return _time_diff_zero_doppler;
+  };
+  /**
+  * @brief data_analysis_flag
+  */
+  bool   get_data_analysis_flag()
+  {
+    return _data_analysis_flag;
+  };
+  /**
+  * @brief ant_elev_coor_flag
+  */
+  bool   get_ant_elev_coor_flag()
+  {
+    return _ant_elev_coor_flag;
+  };
+  /**
+  * @brief chirp_extract_flag
+  */
+  bool   get_chirp_extract_flag()
+  {
+    return _chirp_extract_flag;
+  };
+  /**
+  * @brief srgr_flag
+  */
+  bool   get_srgr_flag()
+  {
+    return _srgr_flag;
+  };
+  /**
+  * @brief dop_cen_flag
+  */
+  bool   get_dop_cen_flag()
+  {
+    return _dop_cen_flag;
+  };
+  /**
+  * @brief dop_amb_flag
+  */
+  bool   get_dop_amb_flag()
+  {
+    return _dop_amb_flag;
+  };
+  /**
+  * @brief range_spread_comp_flag
+  */
+  bool   get_range_spread_comp_flag()
+  {
+    return _range_spread_comp_flag;
+  };
+  /**
+  * @brief detected_flag
+  */
+  bool   get_detected_flag()
+  {
+    return _detected_flag;
+  };
+  /**
+  * @brief look_sum_flag
+  */
+  bool   get_look_sum_flag()
+  {
+    return _look_sum_flag;
+  };
+  /**
+  * @brief rms_equal_flag
+  */
+  bool   get_rms_equal_flag()
+  {
+    return _rms_equal_flag;
+  };
+  /**
+  * @brief ant_scal_flag
+  */
+  bool   get_ant_scal_flag()
+  {
+    return _ant_scal_flag;
+  };
+  /**
+  * @brief vga_com_echo_flag
+  */
+  bool   get_vga_com_echo_flag()
+  {
+    return _vga_com_echo_flag;
+  };
+  /**
+  * @brief vga_com_cal_flag
+  */
+  bool   get_vga_com_cal_flag()
+  {
+    return _vga_com_cal_flag;
+  };
+  /**
+  * @brief vga_com_nom_time_flag
+  */
+  bool   get_vga_com_nom_time_flag()
+  {
+    return _vga_com_nom_time_flag;
+  };
+  /**
+  * @brief gm_rng_comp_inv_filter_flag
+  */
+  bool   get_gm_rng_comp_inv_filter_flag()
+  {
+    return _gm_rng_comp_inv_filter_flag;
+  };
+  /**
+  * @brief raw_data_analysis
+  */
+  std::string   get_raw_data_analysis()
+  {
+    return _raw_data_analysis;
+  };
+  /**
+  * @brief start_time_mds1
+  */
+  std::string   get_start_time_mds1()
+  {
+    return _start_time_mds1;
+  };
+  /**
+  * @brief start_time_mds2
+  */
+  std::string   get_start_time_mds2()
+  {
+    return _start_time_mds2;
+  };
+  /**
+  * @brief parameter_code
+  */
+  std::string   get_parameter_code()
+  {
+    return _parameter_code;
+  };
+  /**
+  * @brief errors_counters
+  */
+  std::string   get_errors_counters()
+  {
+    return _errors_counters;
+  };
+  /**
+  * @brief image_parameters  block1
+  */
+  std::string   get_image_parameters1()
+  {
+    return _image_parameters1;
+  };
+  /**
+  * @brief prf_values[5]
+  */
+  float*   get_prf_values()
+  {
+    return _prf_values;
+  };
+  /**
+  * @brief prf (i.e prf_values[0])
+  */
+  float   get_prf()
+  {
+    return _prf_values[0];
+  };
+  /**
+  * @brief image_parameters  block2
+  */
+  std::string   get_image_parameters2()
+  {
+    return _image_parameters2;
+  };
+  /**
+  * @brief first_proc_range_samp
+  */
+  unsigned int  get_first_proc_range_samp()
+  {
+    return _first_proc_range_samp;
+  };
+  /**
+  * @brief range_ref
+  */
+  float  get_range_ref()
+  {
+    return _range_ref;
+  };
+  /**
+  * @brief range_samp_rate
+  */
+  float  get_range_samp_rate()
+  {
+    return _range_samp_rate;
+  };
+  /**
+  * @brief radar_freq
+  */
+  float  get_radar_freq()
+  {
+    return _radar_freq;
+  };
+  /**
+  * @brief num_looks_range
+  */
+  unsigned short   get_num_looks_range()
+  {
+    return _num_looks_range;
+  };
+  /**
+  * @brief filter_range
+  */
+  std::string   get_filter_range()
+  {
+    return _filter_range;
+  };
+  /**
+  * @brief filter_coef_range
+  */
+  float  get_filter_coef_range()
+  {
+    return _filter_coef_range;
+  };
+  /**
+  * @brief bandwidth
+  */
+  std::string   get_bandwidth()
+  {
+    return _bandwidth;
+  };
+  /**
+  * @brief nominal_chirp
+  */
+  std::string   get_nominal_chirp()
+  {
+    return _nominal_chirp;
+  };
+  /**
+  * @brief num_lines_proc
+  */
+  unsigned int  get_num_lines_proc()
+  {
+    return _num_lines_proc;
+  };
+  /**
+  * @brief num_look_az
+  */
+  unsigned short   get_num_look_az()
+  {
+    return _num_look_az;
+  };
+  /**
+  * @brief look_bw_az
+  */
+  float  get_look_bw_az()
+  {
+    return _look_bw_az;
+  };
+  /**
+  * @brief to_bw_az
+  */
+  float  get_to_bw_az()
+  {
+    return _to_bw_az;
+  };
+  /**
+  * @brief filter_az
+  */
+  std::string   get_filter_az()
+  {
+    return _filter_az;
+  };
+  /**
+  * @brief filter_coef_az
+  */
+  float  get_filter_coef_az()
+  {
+    return _filter_coef_az;
+  };
+  /**
+  * @brief az_fm_rate[3]
+  */
+  float*  get_az_fm_rate()
+  {
+    return _az_fm_rate;
+  };
+  /**
+  * @brief ax_fm_origin
+  */
+  float  get_ax_fm_origin()
+  {
+    return _ax_fm_origin;
+  };
+  /**
+  * @brief dop_amb_coef
+  */
+  float  get_dop_amb_coef()
+  {
+    return _dop_amb_coef;
+  };
+  /**
+  * @brief calibration_factors
+  */
+  std::string   get_calibration_factors()
+  {
+    return _calibration_factors;
+  };
+  /**
+  * @brief noise_estimation
+  */
+  std::string   get_noise_estimation()
+  {
+    return _noise_estimation;
+  };
+  /**
+  * @brief output_statistics
+  */
+  std::string   get_output_statistics()
+  {
+    return _output_statistics;
+  };
+  /**
+  * @brief avg_scene_height_ellpsoid
+  */
+  float  get_avg_scene_height_ellpsoid()
+  {
+    return _avg_scene_height_ellpsoid;
+  };
+  /**
+  * @brief echo_comp
+  */
+  std::string   get_echo_comp()
+  {
+    return _echo_comp;
+  };
+  /**
+  * @brief echo_comp_ratio
+  */
+  std::string   get_echo_comp_ratio()
+  {
+    return _echo_comp_ratio;
+  };
+  /**
+  * @brief init_cal_comp
+  */
+  std::string   get_init_cal_comp()
+  {
+    return _init_cal_comp;
+  };
+  /**
+  * @brief init_cal_ratio
+  */
+  std::string   get_init_cal_ratio()
+  {
+    return _init_cal_ratio;
+  };
+  /**
+  * @brief per_cal_comp
+  */
+  std::string   get_per_cal_comp()
+  {
+    return _per_cal_comp;
+  };
+  /**
+  * @brief per_cal_ratio
+  */
+  std::string   get_per_cal_ratio()
+  {
+    return _per_cal_ratio;
+  };
+  /**
+  * @brief noise_comp
+  */
+  std::string   get_noise_comp()
+  {
+    return _noise_comp;
+  };
+  /**
+  * @brief noise_comp_ratio
+  */
+  std::string   get_noise_comp_ratio()
+  {
+    return _noise_comp_ratio;
+  };
+  /**
+  * @brief beam_overlap[4]
+  */
+  unsigned int* get_beam_overlap()
+  {
+    return _beam_overlap;
+  };
+  /**
+  * @brief beam_param[4]
+  */
+  float* get_beam_param()
+  {
+    return _beam_param;
+  };
+  /**
+  * @brief lines_per_burst[5]
+  */
+  unsigned int*  get_lines_per_burst()
+  {
+    return _lines_per_burst;
+  };
+  /**
+  * @brief time_first_SS1_echo
+  */
+  std::string   get_time_first_SS1_echo()
+  {
+    return _time_first_SS1_echo;
+  };
+  /**
+  * @brief state_vector_time_1 day
+  */
+  int get_state_vector_time_1_day()
+  {
+    return _state_vector_time_1_day;
+  };
+  /**
+  * @brief state_vector_time_1 sec
+  */
+  unsigned int get_state_vector_time_1_sec()
+  {
+    return _state_vector_time_1_sec;
+  };
+  /**
+  * @brief state_vector_time_1 microsec
+  */
+  unsigned int get_state_vector_time_1_microsec()
+  {
+    return _state_vector_time_1_microsec;
+  };
+  /**
+  * @brief x_pos_1
+  */
+  int   get_x_pos_1()
+  {
+    return _x_pos_1;
+  };
+  /**
+  * @brief y_pos_1
+  */
+  int   get_y_pos_1()
+  {
+    return _y_pos_1;
+  };
+  /**
+  * @brief z_pos_1
+  */
+  int   get_z_pos_1()
+  {
+    return _z_pos_1;
+  };
+  /**
+  * @brief x_vel_1
+  */
+  int   get_x_vel_1()
+  {
+    return _x_vel_1;
+  };
+  /**
+  * @brief y_vel_1
+  */
+  int   get_y_vel_1()
+  {
+    return _y_vel_1;
+  };
+  /**
+  * @brief z_vel_1
+  */
+  int   get_z_vel_1()
+  {
+    return _z_vel_1;
+  };
+  /**
+  * @brief state_vector_time_2 day
+  */
+  int get_state_vector_time_2_day()
+  {
+    return _state_vector_time_2_day;
+  };
+  /**
+  * @brief state_vector_time_2 sec
+  */
+  unsigned int get_state_vector_time_2_sec()
+  {
+    return _state_vector_time_2_sec;
+  };
+  /**
+  * @brief state_vector_time_1 microsec
+  */
+  unsigned int get_state_vector_time_2_microsec()
+  {
+    return _state_vector_time_2_microsec;
+  };
+  /**
+  * @brief x_pos_2
+  */
+  int   get_x_pos_2()
+  {
+    return _x_pos_2;
+  };
+  /**
+  * @brief y_pos_2
+  */
+  int   get_y_pos_2()
+  {
+    return _y_pos_2;
+  };
+  /**
+  * @brief z_pos_2
+  */
+  int   get_z_pos_2()
+  {
+    return _z_pos_2;
+  };
+  /**
+  * @brief x_vel_2
+  */
+  int   get_x_vel_2()
+  {
+    return _x_vel_2;
+  };
+  /**
+  * @brief y_vel_2
+  */
+  int   get_y_vel_2()
+  {
+    return _y_vel_2;
+  };
+  /**
+  * @brief z_vel_2
+  */
+  int   get_z_vel_2()
+  {
+    return _z_vel_2;
+  };
+  /**
+  * @brief state_vector_time_3 day
+  */
+  int get_state_vector_time_3_day()
+  {
+    return _state_vector_time_3_day;
+  };
+  /**
+  * @brief state_vector_time_3 sec
+  */
+  unsigned int get_state_vector_time_3_sec()
+  {
+    return _state_vector_time_3_sec;
+  };
+  /**
+  * @brief state_vector_time_3 microsec
+  */
+  unsigned int get_state_vector_time_3_microsec()
+  {
+    return _state_vector_time_3_microsec;
+  };
+  /**
+  * @brief x_pos_3
+  */
+  int   get_x_pos_3()
+  {
+    return _x_pos_3;
+  };
+  /**
+  * @brief y_pos_3
+  */
+  int   get_y_pos_3()
+  {
+    return _y_pos_3;
+  };
+  /**
+  * @brief z_pos_3
+  */
+  int   get_z_pos_3()
+  {
+    return _z_pos_3;
+  };
+  /**
+  * @brief x_vel_3
+  */
+  int   get_x_vel_3()
+  {
+    return _x_vel_3;
+  };
+  /**
+  * @brief y_vel_3
+  */
+  int   get_y_vel_3()
+  {
+    return _y_vel_3;
+  };
+  /**
+  * @brief z_vel_3
+  */
+  int   get_z_vel_3()
+  {
+    return _z_vel_3;
+  };
+  /**
+  * @brief state_vector_time_4 day
+  */
+  int get_state_vector_time_4_day()
+  {
+    return _state_vector_time_4_day;
+  };
+  /**
+  * @brief state_vector_time_1 sec
+  */
+  unsigned int get_state_vector_time_4_sec()
+  {
+    return _state_vector_time_4_sec;
+  };
+  /**
+  * @brief state_vector_time_4 microsec
+  */
+  unsigned int get_state_vector_time_4_microsec()
+  {
+    return _state_vector_time_4_microsec;
+  };
+  /**
+  * @brief x_pos_4
+  */
+  int   get_x_pos_4()
+  {
+    return _x_pos_4;
+  };
+  /**
+  * @brief y_pos_4
+  */
+  int   get_y_pos_4()
+  {
+    return _y_pos_4;
+  };
+  /**
+  * @brief z_pos_4
+  */
+  int   get_z_pos_4()
+  {
+    return _z_pos_4;
+  };
+  /**
+  * @brief x_vel_4
+  */
+  int   get_x_vel_4()
+  {
+    return _x_vel_4;
+  };
+  /**
+  * @brief y_vel_4
+  */
+  int   get_y_vel_4()
+  {
+    return _y_vel_4;
+  };
+  /**
+  * @brief z_vel_4
+  */
+  int   get_z_vel_4()
+  {
+    return _z_vel_4;
+  };
+  /**
+  * @brief state_vector_time_5 day
+  */
+  int get_state_vector_time_5_day()
+  {
+    return _state_vector_time_5_day;
+  };
+  /**
+  * @brief state_vector_time_5 sec
+  */
+  unsigned int get_state_vector_time_5_sec()
+  {
+    return _state_vector_time_5_sec;
+  };
+  /**
+  * @brief state_vector_time_5 microsec
+  */
+  unsigned int get_state_vector_time_5_microsec()
+  {
+    return _state_vector_time_5_microsec;
+  };
+  /**
+  * @brief x_pos_5
+  */
+  int   get_x_pos_5()
+  {
+    return _x_pos_5;
+  };
+  /**
+  * @brief y_pos_5
+  */
+  int   get_y_pos_5()
+  {
+    return _y_pos_5;
+  };
+  /**
+  * @brief z_pos_5
+  */
+  int   get_z_pos_5()
+  {
+    return _z_pos_5;
+  };
+  /**
+  * @brief x_vel_5
+  */
+  int   get_x_vel_5()
+  {
+    return _x_vel_5;
+  };
+  /**
+  * @brief y_vel_5
+  */
+  int   get_y_vel_5()
+  {
+    return _y_vel_5;
+  };
+  /**
+  * @brief z_vel_5
+  */
+  int   get_z_vel_5()
+  {
+    return _z_vel_5;
+  };
+
+  /**
+  * @brief first_zero_doppler_time
+  */
+  std::string   _first_zero_doppler_time;
+  /**
+  * @brief attach_flag
+  */
+  bool   _attach_flag;
+  /**
+  * @brief last_zero_doppler_time
+  */
+  std::string   _last_zero_doppler_time;
+  /**
+  * @brief work_order_id
+  */
+  std::string   _work_order_id;
+  /**
+  * @brief time_diff
+  */
+  float  _time_diff;
+  /**
+  * @brief swath_num
+  */
+  std::string   _swath_num;
+  /**
+  * @brief range_spacing
+  */
+  float  _range_spacing;
+  /**
+  * @brief azimut_spacing
+  */
+  float  _azimut_spacing;
+  /**
+  * @brief line_time_interval
+  */
+  float  _line_time_interval;
+  /**
+  * @brief num_output_lines
+  */
+  unsigned int   _num_output_lines;
+  /**
+  * @brief num_samples_per_line
+  */
+  unsigned int   _num_samples_per_line;
+  /**
+  * @brief data_type
+  */
+  std::string   _data_type;
+  /**
+  * @brief num_range_lines_per_burst
+  */
+  unsigned int   _num_range_lines_per_burst;
+  /**
+  * @brief time_diff_zero_doppler
+  */
+  float  _time_diff_zero_doppler;
+  /**
+  * @brief data_analysis_flag
+  */
+  bool   _data_analysis_flag;
+  /**
+  * @brief ant_elev_coor_flag
+  */
+  bool   _ant_elev_coor_flag;
+  /**
+  * @brief chirp_extract_flag
+  */
+  bool   _chirp_extract_flag;
+  /**
+  * @brief srgr_flag
+  */
+  bool   _srgr_flag;
+  /**
+  * @brief dop_cen_flag
+  */
+  bool   _dop_cen_flag;
+  /**
+  * @brief dop_amb_flag
+  */
+  bool   _dop_amb_flag;
+  /**
+  * @brief range_spread_comp_flag
+  */
+  bool   _range_spread_comp_flag;
+  /**
+  * @brief detected_flag
+  */
+  bool   _detected_flag;
+  /**
+  * @brief look_sum_flag
+  */
+  bool   _look_sum_flag;
+  /**
+  * @brief rms_equal_flag
+  */
+  bool   _rms_equal_flag;
+  /**
+  * @brief ant_scal_flag
+  */
+  bool   _ant_scal_flag;
+  /**
+  * @brief vga_com_echo_flag
+  */
+  bool   _vga_com_echo_flag;
+  /**
+  * @brief vga_com_cal_flag
+  */
+  bool   _vga_com_cal_flag;
+  /**
+  * @brief vga_com_nom_time_flag
+  */
+  bool   _vga_com_nom_time_flag;
+  /**
+  * @brief gm_rng_comp_inv_filter_flag
+  */
+  bool   _gm_rng_comp_inv_filter_flag;
+  /**
+  * @brief raw_data_analysis
+  */
+  std::string   _raw_data_analysis;
+  /**
+  * @brief start_time_mds1
+  */
+  std::string   _start_time_mds1;
+  /**
+  * @brief start_time_mds2
+  */
+  std::string   _start_time_mds2;
+  /**
+  * @brief parameter_code
+  */
+  std::string   _parameter_code;
+  /**
+  * @brief errors_counters
+  */
+  std::string   _errors_counters;
+  /**
+  * @brief image_parameters block 1
+  */
+  std::string   _image_parameters1;
+  /**
+  * @brief PRF
+  */
+  float  _prf_values[5];
+  /**
+  * @brief image_parameters block 2
+  */
+  std::string   _image_parameters2;
+  /**
+  * @brief first_proc_range_samp
+  */
+  unsigned int   _first_proc_range_samp;
+  /**
+  * @brief range_ref
+  */
+  float  _range_ref;
+  /**
+  * @brief range_samp_rate
+  */
+  float  _range_samp_rate;
+  /**
+  * @brief radar_freq
+  */
+  float  _radar_freq;
+  /**
+  * @brief num_looks_range
+  */
+  unsigned short   _num_looks_range;
+  /**
+  * @brief filter_range
+  */
+  std::string   _filter_range;
+  /**
+  * @brief filter_coef_range
+  */
+  float  _filter_coef_range;
+  /**
+  * @brief bandwidth
+  */
+  std::string   _bandwidth;
+  /**
+  * @brief nominal_chirp
+  */
+  std::string   _nominal_chirp;
+  /**
+  * @brief num_lines_proc
+  */
+  unsigned int   _num_lines_proc;
+  /**
+  * @brief num_look_az
+  */
+  unsigned short   _num_look_az;
+  /**
+  * @brief look_bw_az
+  */
+  float  _look_bw_az;
+  /**
+  * @brief to_bw_az
+  */
+  float  _to_bw_az;
+  /**
+  * @brief filter_az
+  */
+  std::string   _filter_az;
+  /**
+  * @brief filter_coef_az
+  */
+  float  _filter_coef_az;
+  /**
+  * @brief az_fm_rate[3]
+  */
+  float  _az_fm_rate[3];
+  /**
+  * @brief ax_fm_origin
+  */
+  float  _ax_fm_origin;
+  /**
+  * @brief dop_amb_coef
+  */
+  float  _dop_amb_coef;
+  /**
+  * @brief calibration_factors
+  */
+  std::string   _calibration_factors;
+  /**
+  * @brief noise_estimation
+  */
+  std::string   _noise_estimation;
+  /**
+  * @brief output_statistics
+  */
+  std::string   _output_statistics;
+  /**
+  * @brief avg_scene_height_ellpsoid
+  */
+  float  _avg_scene_height_ellpsoid;
+  /**
+  * @brief echo_comp
+  */
+  std::string   _echo_comp;
+  /**
+  * @brief echo_comp_ratio
+  */
+  std::string   _echo_comp_ratio;
+  /**
+  * @brief init_cal_comp
+  */
+  std::string   _init_cal_comp;
+  /**
+  * @brief init_cal_ratio
+  */
+  std::string   _init_cal_ratio;
+  /**
+  * @brief per_cal_comp
+  */
+  std::string   _per_cal_comp;
+  /**
+  * @brief per_cal_ratio
+  */
+  std::string   _per_cal_ratio;
+  /**
+  * @brief noise_comp
+  */
+  std::string   _noise_comp;
+  /**
+  * @brief noise_comp_ratio
+  */
+  std::string   _noise_comp_ratio;
+  /**
+  * @brief beam_overlap[4]
+  */
+  unsigned int   _beam_overlap[4];
+  /**
+  * @brief beam_overlap[4]
+  */
+  float   _beam_param[4];
+  /**
+  * @brief lines_per_burst[5]
+  */
+  unsigned int   _lines_per_burst[5];
+  /**
+  * @brief time_first_SS1_echo
+  */
+  std::string   _time_first_SS1_echo;
+  /**
+  * @brief state_vector_time_1_day
+  */
+  int   _state_vector_time_1_day;
+  /**
+  * @brief state_vector_time_1_sec
+  */
+  unsigned int   _state_vector_time_1_sec;
+  /**
+  * @brief state_vector_time_1_microsec
+  */
+  unsigned int   _state_vector_time_1_microsec;
+  /**
+  * @brief x_pos_1
+  */
+  int   _x_pos_1;
+  /**
+  * @brief y_pos_1
+  */
+  int   _y_pos_1;
+  /**
+  * @brief z_pos_1
+  */
+  int   _z_pos_1;
+  /**
+  * @brief x_vel_1
+  */
+  int   _x_vel_1;
+  /**
+  * @brief y_vel_1
+  */
+  int   _y_vel_1;
+  /**
+  * @brief z_vel_1
+  */
+  int   _z_vel_1;
+  /**
+  * @brief state_vector_time_2_day
+  */
+  int   _state_vector_time_2_day;
+  /**
+  * @brief state_vector_time_2_sec
+  */
+  unsigned int   _state_vector_time_2_sec;
+  /**
+  * @brief state_vector_time_2_microsec
+  */
+  unsigned int   _state_vector_time_2_microsec;
+  /**
+  * @brief x_pos_2
+  */
+  int   _x_pos_2;
+  /**
+  * @brief y_pos_2
+  */
+  int   _y_pos_2;
+  /**
+  * @brief z_pos_2
+  */
+  int   _z_pos_2;
+  /**
+  * @brief x_vel_2
+  */
+  int   _x_vel_2;
+  /**
+  * @brief y_vel_2
+  */
+  int   _y_vel_2;
+  /**
+  * @brief z_vel_2
+  */
+  int   _z_vel_2;
+  /**
+  * @brief state_vector_time_3_day
+  */
+  int   _state_vector_time_3_day;
+  /**
+  * @brief state_vector_time_3_sec
+  */
+  unsigned int   _state_vector_time_3_sec;
+  /**
+  * @brief state_vector_time_3_microsec
+  */
+  unsigned int   _state_vector_time_3_microsec;
+  /**
+  * @brief x_pos_3
+  */
+  int   _x_pos_3;
+  /**
+  * @brief y_pos_3
+  */
+  int   _y_pos_3;
+  /**
+  * @brief z_pos_3
+  */
+  int   _z_pos_3;
+  /**
+  * @brief x_vel_3
+  */
+  int   _x_vel_3;
+  /**
+  * @brief y_vel_3
+  */
+  int   _y_vel_3;
+  /**
+  * @brief z_vel_3
+  */
+  int   _z_vel_3;
+  /**
+  * @brief state_vector_time_4_day
+  */
+  int   _state_vector_time_4_day;
+  /**
+  * @brief state_vector_time_4_sec
+  */
+  unsigned int   _state_vector_time_4_sec;
+  /**
+  * @brief state_vector_time_4_microsec
+  */
+  unsigned int   _state_vector_time_4_microsec;
+  /**
+  * @brief x_pos_4
+  */
+  int   _x_pos_4;
+  /**
+  * @brief y_pos_4
+  */
+  int   _y_pos_4;
+  /**
+  * @brief z_pos_4
+  */
+  int   _z_pos_4;
+  /**
+  * @brief x_vel_4
+  */
+  int   _x_vel_4;
+  /**
+  * @brief y_vel_4
+  */
+  int   _y_vel_4;
+  /**
+  * @brief z_vel_4
+  */
+  int   _z_vel_4;
+  /**
+  * @brief state_vector_time_5_day
+  */
+  int   _state_vector_time_5_day;
+  /**
+  * @brief state_vector_time_5_sec
+  */
+  unsigned int   _state_vector_time_5_sec;
+  /**
+  * @brief state_vector_time_5_microsec
+  */
+  unsigned int   _state_vector_time_5_microsec;
+  /**
+  * @brief x_pos_5
+  */
+  int   _x_pos_5;
+  /**
+  * @brief y_pos_5
+  */
+  int   _y_pos_5;
+  /**
+  * @brief z_pos_5
+  */
+  int   _z_pos_5;
+  /**
+  * @brief x_vel_5
+  */
+  int   _x_vel_5;
+  /**
+  * @brief y_vel_5
+  */
+  int   _y_vel_5;
+  /**
+  * @brief z_vel_5
+  */
+  int   _z_vel_5;
+
+
+private:
+
+};
+}
+#endif
+
+
+
diff --git a/ossim_plugins/ossim/EnvisatAsar/SQ_ADSR.cpp b/ossim_plugins/ossim/EnvisatAsar/SQ_ADSR.cpp
new file mode 100644
index 0000000..8bd4cc7
--- /dev/null
+++ b/ossim_plugins/ossim/EnvisatAsar/SQ_ADSR.cpp
@@ -0,0 +1,365 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include <EnvisatAsar/SQ_ADSR.h>
+
+namespace ossimplugins
+{
+   SQ_ADSR::SQ_ADSR() : EnvisatAsarRecord("sq_adsr_rec")
+   {
+   }
+
+   SQ_ADSR::~SQ_ADSR()
+   {
+   }
+
+
+
+   std::ostream& operator<<(std::ostream& os, const SQ_ADSR& data)
+   {
+      os<<"zero_doppler_time:"<<data._zero_doppler_time.c_str()<<std::endl;
+
+      os<<"attach_flag:"<<data._attach_flag<<std::endl;
+
+      os<<"input_mean_flag:"<<data._input_mean_flag<<std::endl;
+
+      os<<"input_std_dev_flag:"<<data._input_std_dev_flag<<std::endl;
+
+      os<<"input_gaps_flag:"<<data._input_gaps_flag<<std::endl;
+
+      os<<"input_missing_lines_flag:"<<data._input_missing_lines_flag<<std::endl;
+
+      os<<"dop_cen_flag:"<<data._dop_cen_flag<<std::endl;
+
+      os<<"dop_amb_flag:"<<data._dop_amb_flag<<std::endl;
+
+      os<<"output_mean_flag:"<<data._output_mean_flag<<std::endl;
+
+      os<<"output_std_dev_flag:"<<data._output_std_dev_flag<<std::endl;
+
+      os<<"chirp_flag:"<<data._chirp_flag<<std::endl;
+
+      os<<"missing_data_set_flag:"<<data._missing_data_set_flag<<std::endl;
+
+      os<<"invalid_downlink_flag:"<<data._invalid_downlink_flag<<std::endl;
+
+      os<<"thres_chirp_broadening:"<<data._thres_chirp_broadening<<std::endl;
+
+      os<<"thresh_chirp_sidelobe:"<<data._thresh_chirp_sidelobe<<std::endl;
+
+      os<<"thresh_chirp_islr:"<<data._thresh_chirp_islr<<std::endl;
+
+      os<<"thresh_input_mean:"<<data._thresh_input_mean<<std::endl;
+
+      os<<"exp_input_mean:"<<data._exp_input_mean<<std::endl;
+
+      os<<"thresh_input_std_dev:"<<data._thresh_input_std_dev<<std::endl;
+
+      os<<"exp_input_std_dev:"<<data._exp_input_std_dev<<std::endl;
+
+      os<<"thresh_dop_cen:"<<data._thresh_dop_cen<<std::endl;
+
+      os<<"thresh_dop_amb:"<<data._thresh_dop_amb<<std::endl;
+
+      os<<"thresh_output_mean:"<<data._thresh_output_mean<<std::endl;
+
+      os<<"exp_output_mean:"<<data._exp_output_mean<<std::endl;
+
+      os<<"thresh_output_std_dev:"<<data._thresh_output_std_dev<<std::endl;
+
+      os<<"exp_output_std_dev:"<<data._exp_output_std_dev<<std::endl;
+
+      os<<"thresh_input_missing_lines:"<<data._thresh_input_missing_lines<<std::endl;
+
+      os<<"thresh_input_gaps:"<<data._thresh_input_gaps<<std::endl;
+
+      os<<"lines_per_gaps:"<<data._lines_per_gaps<<std::endl;
+
+      os<<"input_mean[0]:"<<data._input_mean[0]<<std::endl;
+      os<<"input_mean[1]:"<<data._input_mean[1]<<std::endl;
+
+      os<<"input_std_dev[0]:"<<data._input_std_dev[0]<<std::endl;
+      os<<"input_std_dev[1]:"<<data._input_std_dev[1]<<std::endl;
+
+      os<<"num_gaps:"<<data._num_gaps<<std::endl;
+
+      os<<"num_missing_lines:"<<data._num_missing_lines<<std::endl;
+
+      os<<"output_mean[0]:"<<data._output_mean[0]<<std::endl;
+      os<<"output_mean[1]:"<<data._output_mean[1]<<std::endl;
+
+      os<<"output_std_dev[0]:"<<data._output_std_dev[0]<<std::endl;
+      os<<"output_std_dev[1]:"<<data._output_std_dev[1]<<std::endl;
+
+      os<<"tot_errors:"<<data._tot_errors<<std::endl;
+
+      return os;
+
+   }
+
+   std::istream& operator>>(std::istream& is, SQ_ADSR& data)
+   {
+      // char buf64[65];
+      // buf64[64] = '\0';
+      // char buf32[33];
+      // buf32[32] = '\0';
+      // char buf27[28];
+      // buf27[27] = '\0';
+      // char buf20[21];
+      // buf20[20] = '\0';
+      char buf16[17];
+      buf16[16]='\0';
+      char buf15[16];
+      buf15[15] = '\0';
+      // char buf14[15];
+      // buf14[14] = '\0';
+      // char buf13[14];
+      // buf13[13] = '\0';
+      char buf12[13];
+      buf12[12] = '\0';
+      // char buf11[12];
+      // buf11[11] = '\0';
+      // char buf10[11];
+      // buf10[10] = '\0';
+      // char buf9[10];
+      // buf9[9] = '\0';
+      // char buf8[9];
+      // buf8[8] = '\0';
+      char buf7[8];
+      buf7[7] = '\0';
+      // char buf6[7];
+      // buf6[6] = '\0';
+      // char buf5[6];
+      // buf5[5] = '\0';
+      // char buf4[5];
+      // buf4[4] = '\0';
+      // char buf3[4];
+      // buf3[3] = '\0';
+      // char buf2[3];
+      // buf2[2] = '\0';
+//	char buf1[1]; // not used avoid warning
+
+      is.read(buf12,12);
+      data._zero_doppler_time = buf12;
+
+      is.read((char*)&(data._attach_flag),1);
+
+      is.read((char*)&(data._input_mean_flag),1);
+
+      is.read((char*)&(data._input_std_dev_flag),1);
+
+      is.read((char*)&(data._input_gaps_flag),1);
+
+      is.read((char*)&(data._input_missing_lines_flag),1);
+
+      is.read((char*)&(data._dop_cen_flag),1);
+
+      is.read((char*)&(data._dop_amb_flag),1);
+
+      is.read((char*)&(data._output_mean_flag),1);
+
+      is.read((char*)&(data._output_std_dev_flag),1);
+
+      is.read((char*)&(data._chirp_flag),1);
+
+      is.read((char*)&(data._missing_data_set_flag),1);
+
+      is.read((char*)&(data._invalid_downlink_flag),1);
+
+      is.read(buf7,7);
+
+      is.read((char*)&(data._thres_chirp_broadening),4);
+      data.SwitchEndian(data._thres_chirp_broadening);
+
+      is.read((char*)&(data._thresh_chirp_sidelobe),4);
+      data.SwitchEndian(data._thresh_chirp_sidelobe);
+
+      is.read((char*)&(data._thresh_chirp_islr),4);
+      data.SwitchEndian(data._thresh_chirp_islr);
+
+      is.read((char*)&(data._thresh_input_mean),4);
+      data.SwitchEndian(data._thresh_input_mean);
+
+      is.read((char*)&(data._exp_input_mean),4);
+      data.SwitchEndian(data._exp_input_mean);
+
+      is.read((char*)&(data._thresh_input_std_dev),4);
+      data.SwitchEndian(data._thresh_input_std_dev);
+
+      is.read((char*)&(data._exp_input_std_dev),4);
+      data.SwitchEndian(data._exp_input_std_dev);
+
+      is.read((char*)&(data._thresh_dop_cen),4);
+      data.SwitchEndian(data._thresh_dop_cen);
+
+      is.read((char*)&(data._thresh_dop_amb),4);
+      data.SwitchEndian(data._thresh_dop_amb);
+
+      is.read((char*)&(data._thresh_output_mean),4);
+      data.SwitchEndian(data._thresh_output_mean);
+
+      is.read((char*)&(data._exp_output_mean),4);
+      data.SwitchEndian(data._exp_output_mean);
+
+      is.read((char*)&(data._thresh_output_std_dev),4);
+      data.SwitchEndian(data._thresh_output_std_dev);
+
+      is.read((char*)&(data._exp_output_std_dev),4);
+      data.SwitchEndian(data._exp_output_std_dev);
+
+      is.read((char*)&(data._thresh_input_missing_lines),4);
+      data.SwitchEndian(data._thresh_input_missing_lines);
+
+      is.read((char*)&(data._thresh_input_gaps),4);
+      data.SwitchEndian(data._thresh_input_gaps);
+
+      is.read((char*)&(data._lines_per_gaps),4);
+      data.SwitchEndian(data._lines_per_gaps);
+
+      is.read(buf15,15);
+
+      is.read((char*)&(data._input_mean[0]),4);
+      data.SwitchEndian(data._input_mean[0]);
+
+      is.read((char*)&(data._input_mean[1]),4);
+      data.SwitchEndian(data._input_mean[1]);
+
+      is.read((char*)&(data._input_std_dev[0]),4);
+      data.SwitchEndian(data._input_std_dev[0]);
+      is.read((char*)&(data._input_std_dev[1]),4);
+      data.SwitchEndian(data._input_std_dev[1]);
+
+      is.read((char*)&(data._num_gaps),4);
+      data.SwitchEndian(data._num_gaps);
+
+      is.read((char*)&(data._num_missing_lines),4);
+      data.SwitchEndian(data._num_missing_lines);
+
+      is.read((char*)&(data._output_mean[0]),4);
+      data.SwitchEndian(data._output_mean[0]);
+      is.read((char*)&(data._output_mean[1]),4);
+      data.SwitchEndian(data._output_mean[1]);
+
+      is.read((char*)&(data._output_std_dev[0]),4);
+      data.SwitchEndian(data._output_std_dev[0]);
+
+      is.read((char*)&(data._output_std_dev[1]),4);
+      data.SwitchEndian(data._output_std_dev[1]);
+
+      is.read((char*)&(data._tot_errors),4);
+      data.SwitchEndian(data._tot_errors);
+
+      is.read(buf16,16);
+
+      return is;
+
+   }
+
+   SQ_ADSR::SQ_ADSR(const SQ_ADSR& rhs):
+      EnvisatAsarRecord(rhs),
+      _zero_doppler_time(rhs._zero_doppler_time),
+      _attach_flag(rhs._attach_flag),
+      _input_mean_flag(rhs._input_mean_flag),
+      _input_std_dev_flag(rhs._input_std_dev_flag),
+      _input_gaps_flag(rhs._input_gaps_flag),
+      _input_missing_lines_flag(rhs._input_missing_lines_flag),
+      _dop_cen_flag(rhs._dop_cen_flag),
+      _dop_amb_flag(rhs._dop_amb_flag),
+      _output_mean_flag(rhs._output_mean_flag),
+      _output_std_dev_flag(rhs._output_std_dev_flag),
+      _chirp_flag(rhs._chirp_flag),
+      _missing_data_set_flag(rhs._missing_data_set_flag),
+      _invalid_downlink_flag(rhs._invalid_downlink_flag),
+      _thres_chirp_broadening(rhs._thres_chirp_broadening),
+      _thresh_chirp_sidelobe(rhs._thresh_chirp_sidelobe),
+      _thresh_chirp_islr(rhs._thresh_chirp_islr),
+      _thresh_input_mean(rhs._thresh_input_mean),
+      _exp_input_mean(rhs._exp_input_mean),
+      _thresh_input_std_dev(rhs._thresh_input_std_dev),
+      _exp_input_std_dev(rhs._exp_input_std_dev),
+      _thresh_dop_cen(rhs._thresh_dop_cen),
+      _thresh_dop_amb(rhs._thresh_dop_amb),
+      _thresh_output_mean(rhs._thresh_output_mean),
+      _exp_output_mean(rhs._exp_output_mean),
+      _thresh_output_std_dev(rhs._thresh_output_std_dev),
+      _exp_output_std_dev(rhs._exp_output_std_dev),
+      _thresh_input_missing_lines(rhs._thresh_input_missing_lines),
+      _thresh_input_gaps(rhs._thresh_input_gaps),
+      _lines_per_gaps(rhs._lines_per_gaps),
+      _num_gaps(rhs._num_gaps),
+      _num_missing_lines(rhs._num_missing_lines),
+      _tot_errors(rhs._tot_errors)
+   {
+      _input_mean[0] = rhs._input_mean[0];
+      _input_mean[1] = rhs._input_mean[1];
+
+      _input_std_dev[0] = rhs._input_std_dev[0];
+      _input_std_dev[1] = rhs._input_std_dev[1];
+
+      _output_mean[0] = rhs._output_mean[0];
+      _output_mean[1] = rhs._output_mean[1];
+
+      _output_std_dev[0] = rhs._output_std_dev[0];
+      _output_std_dev[1] = rhs._output_std_dev[1];
+
+   }
+
+   SQ_ADSR& SQ_ADSR::operator=(const SQ_ADSR& rhs)
+   {
+      _zero_doppler_time = rhs._zero_doppler_time;
+      _attach_flag = rhs._attach_flag;
+      _input_mean_flag = rhs._input_mean_flag;
+      _input_std_dev_flag = rhs._input_std_dev_flag;
+      _input_gaps_flag = rhs._input_gaps_flag;
+      _input_missing_lines_flag = rhs._input_missing_lines_flag;
+      _dop_cen_flag = rhs._dop_cen_flag;
+      _dop_amb_flag = rhs._dop_amb_flag;
+      _output_mean_flag = rhs._output_mean_flag;
+      _output_std_dev_flag = rhs._output_std_dev_flag;
+      _chirp_flag = rhs._chirp_flag;
+      _missing_data_set_flag = rhs._missing_data_set_flag;
+      _invalid_downlink_flag = rhs._invalid_downlink_flag;
+      _thres_chirp_broadening = rhs._thres_chirp_broadening;
+      _thresh_chirp_sidelobe = rhs._thresh_chirp_sidelobe;
+      _thresh_chirp_islr = rhs._thresh_chirp_islr;
+      _thresh_input_mean = rhs._thresh_input_mean;
+      _exp_input_mean = rhs._exp_input_mean;
+      _thresh_input_std_dev = rhs._thresh_input_std_dev;
+      _exp_input_std_dev = rhs._exp_input_std_dev;
+      _thresh_dop_cen = rhs._thresh_dop_cen;
+      _thresh_dop_amb = rhs._thresh_dop_amb;
+      _thresh_output_mean = rhs._thresh_output_mean;
+      _exp_output_mean = rhs._exp_output_mean;
+      _thresh_output_std_dev = rhs._thresh_output_std_dev;
+      _exp_output_std_dev = rhs._exp_output_std_dev;
+      _thresh_input_missing_lines = rhs._thresh_input_missing_lines;
+      _thresh_input_gaps = rhs._thresh_input_gaps;
+      _lines_per_gaps = rhs._lines_per_gaps;
+      _num_gaps = rhs._num_gaps;
+      _num_missing_lines = rhs._num_missing_lines;
+      _tot_errors = rhs._tot_errors;
+
+      _input_mean[0] = rhs._input_mean[0];
+      _input_mean[1] = rhs._input_mean[1];
+
+      _input_std_dev[0] = rhs._input_std_dev[0];
+      _input_std_dev[1] = rhs._input_std_dev[1];
+
+      _output_mean[0] = rhs._output_mean[0];
+      _output_mean[1] = rhs._output_mean[1];
+
+      _output_std_dev[0] = rhs._output_std_dev[0];
+      _output_std_dev[1] = rhs._output_std_dev[1];
+
+      return *this;
+   }
+}
+
diff --git a/ossim_plugins/ossim/EnvisatAsar/SQ_ADSR.h b/ossim_plugins/ossim/EnvisatAsar/SQ_ADSR.h
new file mode 100644
index 0000000..a766b5e
--- /dev/null
+++ b/ossim_plugins/ossim/EnvisatAsar/SQ_ADSR.h
@@ -0,0 +1,497 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef SQ_ADSR_h
+#define SQ_ADSR_h
+
+#include <iostream>
+#include <EnvisatAsar/EnvisatAsarRecord.h>
+
+namespace ossimplugins
+{
+/**
+ * @ingroup SQ_ADSRRecord
+ * @brief This class is able to read the ASAR SQ_ADSR record
+ */
+class SQ_ADSR : public EnvisatAsarRecord
+{
+public:
+  /**
+   * @brief Constructor
+   */
+  SQ_ADSR();
+
+  /**
+   * @brief Destructor
+   */
+  virtual ~SQ_ADSR();
+
+  /**
+   * @brief This function write the SQ_ADSR in a stream
+   */
+  friend std::ostream& operator<<(std::ostream& os, const SQ_ADSR& data);
+
+  /**
+   * @brief This function read a SQ_ADSR from a stream
+   */
+  friend std::istream& operator>>(std::istream& is, SQ_ADSR& data);
+
+  /**
+   * @brief Copy constructor
+   */
+  SQ_ADSR(const SQ_ADSR& rhs);
+
+  /**
+   * @brief Copy operator
+   */
+  SQ_ADSR& operator=(const SQ_ADSR& rhs);
+
+  /**
+   * @brief This function is able to create a new instance of the class
+   */
+  EnvisatAsarRecord* Instanciate()
+  {
+    return new SQ_ADSR();
+  };
+
+  /**
+   * @brief This function is able to create a new instance of the class initialised with the data of the calling instance
+   */
+  EnvisatAsarRecord* Clone()
+  {
+    return new SQ_ADSR(*this);
+  };
+
+  /**
+   * @brief Reads the class data from a stream
+   */
+  void Read(std::istream& is)
+  {
+    is>>*this;
+  };
+
+  /**
+   * @brief Writes the class to a stream
+   */
+  void Write(std::ostream& os)
+  {
+    os<<*this;
+  };
+
+
+  /**
+  * @brief zero_doppler_time
+  */
+  std::string   get_zero_doppler_time()
+  {
+    return _zero_doppler_time;
+  };
+  /**
+  * @brief attach_flag
+  */
+  bool   get_attach_flag()
+  {
+    return _attach_flag;
+  };
+  /**
+  * @brief input_mean_flag
+  */
+  bool   get_input_mean_flag()
+  {
+    return _input_mean_flag;
+  };
+  /**
+  * @brief input_std_dev_flag
+  */
+  bool   get_input_std_dev_flag()
+  {
+    return _input_std_dev_flag;
+  };
+  /**
+  * @brief input_gaps_flag
+  */
+  bool   get_input_gaps_flag()
+  {
+    return _input_gaps_flag;
+  };
+  /**
+  * @brief input_missing_lines_flag
+  */
+  bool   get_input_missing_lines_flag()
+  {
+    return _input_missing_lines_flag;
+  };
+  /**
+  * @brief dop_cen_flag
+  */
+  bool   get_dop_cen_flag()
+  {
+    return _dop_cen_flag;
+  };
+  /**
+  * @brief dop_amb_flag
+  */
+  bool   get_dop_amb_flag()
+  {
+    return _dop_amb_flag;
+  };
+  /**
+  * @brief output_mean_flag
+  */
+  bool   get_output_mean_flag()
+  {
+    return _output_mean_flag;
+  };
+  /**
+  * @brief output_std_dev_flag
+  */
+  bool   get_output_std_dev_flag()
+  {
+    return _output_std_dev_flag;
+  };
+  /**
+  * @brief chirp_flag
+  */
+  bool   get_chirp_flag()
+  {
+    return _chirp_flag;
+  };
+  /**
+  * @brief missing_data_set_flag
+  */
+  bool   get_missing_data_set_flag()
+  {
+    return _missing_data_set_flag;
+  };
+  /**
+  * @brief invalid_downlink_flag
+  */
+  bool   get_invalid_downlink_flag()
+  {
+    return _invalid_downlink_flag;
+  };
+  /**
+  * @brief thres_chirp_broadening
+  */
+  float   get_thres_chirp_broadening()
+  {
+    return _thres_chirp_broadening;
+  };
+  /**
+  * @brief thresh_chirp_sidelobe
+  */
+  float   get_thresh_chirp_sidelobe()
+  {
+    return _thresh_chirp_sidelobe;
+  };
+  /**
+  * @brief thresh_chirp_islr
+  */
+  float   get_thresh_chirp_islr()
+  {
+    return _thresh_chirp_islr;
+  };
+  /**
+  * @brief thresh_input_mean
+  */
+  float   get_thresh_input_mean()
+  {
+    return _thresh_input_mean;
+  };
+  /**
+  * @brief exp_input_mean
+  */
+  float   get_exp_input_mean()
+  {
+    return _exp_input_mean;
+  };
+  /**
+  * @brief thresh_input_std_dev
+  */
+  float   get_thresh_input_std_dev()
+  {
+    return _thresh_input_std_dev;
+  };
+  /**
+  * @brief exp_input_std_dev
+  */
+  float   get_exp_input_std_dev()
+  {
+    return _exp_input_std_dev;
+  };
+  /**
+  * @brief thresh_dop_cen
+  */
+  float   get_thresh_dop_cen()
+  {
+    return _thresh_dop_cen;
+  };
+  /**
+  * @brief thresh_dop_amb
+  */
+  float   get_thresh_dop_amb()
+  {
+    return _thresh_dop_amb;
+  };
+  /**
+  * @brief thresh_output_mean
+  */
+  float   get_thresh_output_mean()
+  {
+    return _thresh_output_mean;
+  };
+  /**
+  * @brief exp_output_mean
+  */
+  float   get_exp_output_mean()
+  {
+    return _exp_output_mean;
+  };
+  /**
+  * @brief thresh_output_std_dev
+  */
+  float   get_thresh_output_std_dev()
+  {
+    return _thresh_output_std_dev;
+  };
+  /**
+  * @brief exp_output_std_dev
+  */
+  float   get_exp_output_std_dev()
+  {
+    return _exp_output_std_dev;
+  };
+  /**
+  * @brief thresh_input_missing_lines
+  */
+  float   get_thresh_input_missing_lines()
+  {
+    return _thresh_input_missing_lines;
+  };
+  /**
+  * @brief thresh_input_gaps
+  */
+  float   get_thresh_input_gaps()
+  {
+    return _thresh_input_gaps;
+  };
+  /**
+  * @brief lines_per_gaps
+  */
+  unsigned int   get_lines_per_gaps()
+  {
+    return _lines_per_gaps;
+  };
+  /**
+  * @brief input_mean[2]
+  */
+  float*   get_input_mean()
+  {
+    return _input_mean;
+  };
+  /**
+  * @brief input_std_dev[2]
+  */
+  float*   get_input_std_dev()
+  {
+    return _input_std_dev;
+  };
+  /**
+  * @brief num_gaps
+  */
+  float   get_num_gaps()
+  {
+    return _num_gaps;
+  };
+  /**
+  * @brief num_missing_lines
+  */
+  float   get_num_missing_lines()
+  {
+    return _num_missing_lines;
+  };
+  /**
+  * @brief output_mean[2]
+  */
+  float*   get_output_mean()
+  {
+    return _output_mean;
+  };
+  /**
+  * @brief output_std_dev[2]
+  */
+  float*   get_output_std_dev()
+  {
+    return _output_std_dev;
+  };
+  /**
+  * @brief tot_errors
+  */
+  unsigned int   get_tot_errors()
+  {
+    return _tot_errors;
+  };
+
+
+  /**
+   * @brief zero_doppler_time
+   */
+  std::string   _zero_doppler_time;
+  /**
+   * @brief attach_flag
+   */
+  bool   _attach_flag;
+  /**
+   * @brief input_mean_flag
+   */
+  bool   _input_mean_flag;
+  /**
+   * @brief input_std_dev_flag
+   */
+  bool   _input_std_dev_flag;
+  /**
+   * @brief input_gaps_flag
+   */
+  bool   _input_gaps_flag;
+  /**
+   * @brief input_missing_lines_flag
+   */
+  bool   _input_missing_lines_flag;
+  /**
+   * @brief dop_cen_flag
+   */
+  bool   _dop_cen_flag;
+  /**
+   * @brief dop_amb_flag
+   */
+  bool   _dop_amb_flag;
+  /**
+   * @brief output_mean_flag
+   */
+  bool   _output_mean_flag;
+  /**
+   * @brief output_std_dev_flag
+   */
+  bool   _output_std_dev_flag;
+  /**
+   * @brief chirp_flag
+   */
+  bool   _chirp_flag;
+  /**
+   * @brief missing_data_set_flag
+   */
+  bool   _missing_data_set_flag;
+  /**
+   * @brief invalid_downlink_flag
+   */
+  bool   _invalid_downlink_flag;
+  /**
+   * @brief thres_chirp_broadening
+   */
+  float   _thres_chirp_broadening;
+  /**
+   * @brief thresh_chirp_sidelobe
+   */
+  float   _thresh_chirp_sidelobe;
+  /**
+   * @brief thresh_chirp_islr
+   */
+  float   _thresh_chirp_islr;
+  /**
+   * @brief thresh_input_mean
+   */
+  float   _thresh_input_mean;
+  /**
+   * @brief exp_input_mean
+   */
+  float   _exp_input_mean;
+  /**
+   * @brief thresh_input_std_dev
+   */
+  float   _thresh_input_std_dev;
+  /**
+   * @brief exp_input_std_dev
+   */
+  float   _exp_input_std_dev;
+  /**
+   * @brief thresh_dop_cen
+   */
+  float   _thresh_dop_cen;
+  /**
+   * @brief thresh_dop_amb
+   */
+  float   _thresh_dop_amb;
+  /**
+   * @brief thresh_output_mean
+   */
+  float   _thresh_output_mean;
+  /**
+   * @brief exp_output_mean
+   */
+  float   _exp_output_mean;
+  /**
+   * @brief thresh_output_std_dev
+   */
+  float   _thresh_output_std_dev;
+  /**
+   * @brief exp_output_std_dev
+   */
+  float   _exp_output_std_dev;
+  /**
+   * @brief thresh_input_missing_lines
+   */
+  float   _thresh_input_missing_lines;
+  /**
+   * @brief thresh_input_gaps
+   */
+  float   _thresh_input_gaps;
+  /**
+   * @brief lines_per_gaps
+   */
+  unsigned int   _lines_per_gaps;
+  /**
+   * @brief input_mean[2]
+   */
+  float   _input_mean[2];
+  /**
+   * @brief input_std_dev[2]
+   */
+  float   _input_std_dev[2];
+  /**
+   * @brief num_gaps
+   */
+  float   _num_gaps;
+  /**
+   * @brief num_missing_lines
+   */
+  float   _num_missing_lines;
+  /**
+   * @brief output_mean[2]
+   */
+  float   _output_mean[2];
+  /**
+   * @brief output_std_dev[2]
+   */
+  float   _output_std_dev[2];
+  /**
+   * @brief tot_errors
+   */
+  unsigned int   _tot_errors;
+
+
+private:
+
+};
+}
+#endif
+
+
+
diff --git a/ossim_plugins/ossim/EnvisatAsar/SRGRConversionParameters.cpp b/ossim_plugins/ossim/EnvisatAsar/SRGRConversionParameters.cpp
new file mode 100644
index 0000000..a409e7e
--- /dev/null
+++ b/ossim_plugins/ossim/EnvisatAsar/SRGRConversionParameters.cpp
@@ -0,0 +1,111 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+#include <EnvisatAsar/SRGRConversionParameters.h>
+
+namespace ossimplugins
+{
+
+   SRGRConversionParameters::SRGRConversionParameters() : EnvisatAsarRecord("SRGRConversionParameters_rec")
+   {
+   }
+
+   SRGRConversionParameters::~SRGRConversionParameters()
+   {
+   }
+
+   std::ostream& operator<<(std::ostream& os, const SRGRConversionParameters& data)
+   {
+      os<<"first_zero_doppler_time_day:"<<data._first_zero_doppler_time_day<<std::endl;
+
+      os<<"first_zero_doppler_time_sec:"<<data._first_zero_doppler_time_sec<<std::endl;
+
+      os<<"first_zero_doppler_time_microsec:"<<data._first_zero_doppler_time_microsec<<std::endl;
+
+      os<<"attach_flag:"<<data._attach_flag<<std::endl;
+
+      os<<"_slant_range_time:"<<data._slant_range_time<<std::endl;
+
+      os<<"_ground_range_origin:"<<data._ground_range_origin<<std::endl;
+
+      for (int i = 0; i<5; i++) {
+         os<<"_srgr_coef[i]:"<<data._srgr_coef[i]<<std::endl;
+      }
+
+      return os;
+
+   }
+
+   std::istream& operator>>(std::istream& is, SRGRConversionParameters& data)
+   {
+      char buf14[15];
+      buf14[14] = '\0';
+      // char buf12[13];
+      // buf12[12] = '\0';
+
+
+      is.read((char*)&(data._first_zero_doppler_time_day),4);
+      data.SwitchEndian(data._first_zero_doppler_time_day);
+
+      is.read((char*)&(data._first_zero_doppler_time_sec),4);
+      data.SwitchEndian(data._first_zero_doppler_time_sec);
+
+      is.read((char*)&(data._first_zero_doppler_time_microsec),4);
+      data.SwitchEndian(data._first_zero_doppler_time_microsec);
+
+      is.read((char*)&(data._attach_flag),1);
+
+      is.read((char*)&(data._slant_range_time),4);
+      data.SwitchEndian(data._slant_range_time);
+
+      is.read((char*)&(data._ground_range_origin),4);
+      data.SwitchEndian(data._ground_range_origin);
+
+      for (int i = 0; i<5; i++) {
+         is.read((char*)&(data._srgr_coef[i]),4);
+         data.SwitchEndian(data._srgr_coef[i]);
+      }
+
+      is.read(buf14,14);
+
+      return is;
+   }
+
+
+   SRGRConversionParameters::SRGRConversionParameters(const SRGRConversionParameters& rhs):
+      EnvisatAsarRecord(rhs),
+      _first_zero_doppler_time_day(rhs._first_zero_doppler_time_day),
+      _first_zero_doppler_time_sec(rhs._first_zero_doppler_time_sec),
+      _first_zero_doppler_time_microsec(rhs._first_zero_doppler_time_microsec),
+      _attach_flag(rhs._attach_flag),
+      _slant_range_time(rhs._slant_range_time),
+      _ground_range_origin(rhs._ground_range_origin)
+   {
+      for (int i = 0; i<5; i++) {
+         _srgr_coef[i] = rhs._srgr_coef[i];
+      }
+   }
+
+   SRGRConversionParameters& SRGRConversionParameters::operator=(const SRGRConversionParameters& rhs)
+   {
+      _first_zero_doppler_time_day = rhs._first_zero_doppler_time_day;
+      _first_zero_doppler_time_sec = rhs._first_zero_doppler_time_sec;
+      _first_zero_doppler_time_microsec = rhs._first_zero_doppler_time_microsec;
+      _attach_flag = rhs._attach_flag;
+      _slant_range_time = rhs._slant_range_time;
+
+      for (int i = 0; i<5; i++) {
+         _srgr_coef[i] = rhs._srgr_coef[i];
+      }
+
+      return *this;
+   }
+}
+
diff --git a/ossim_plugins/ossim/EnvisatAsar/SRGRConversionParameters.h b/ossim_plugins/ossim/EnvisatAsar/SRGRConversionParameters.h
new file mode 100644
index 0000000..dd1133e
--- /dev/null
+++ b/ossim_plugins/ossim/EnvisatAsar/SRGRConversionParameters.h
@@ -0,0 +1,178 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef SRGRConversionParameters_h
+#define SRGRConversionParameters_h
+
+#include <iostream>
+#include <EnvisatAsar/EnvisatAsarRecord.h>
+
+namespace ossimplugins
+{
+
+/**
+ * @ingroup SRGRConversionParametersRecord
+ * @brief This class is able to read the ASAR SRGRConversionParameters record
+ */
+class SRGRConversionParameters : public EnvisatAsarRecord
+{
+public:
+  /**
+   * @brief Constructor
+   */
+  SRGRConversionParameters();
+
+  /**
+   * @brief Destructor
+   */
+  virtual ~SRGRConversionParameters();
+
+  /**
+   * @brief This function writes the SRGRConversionParameters in a stream
+   */
+  friend std::ostream& operator<<(std::ostream& os, const SRGRConversionParameters& data);
+
+  /**
+   * @brief This function reads a SRGRConversionParameters from a stream
+   */
+  friend std::istream& operator>>(std::istream& is, SRGRConversionParameters& data);
+
+  /**
+   * @brief Copy constructor
+   */
+  SRGRConversionParameters(const SRGRConversionParameters& rhs);
+
+  /**
+   * @brief Copy operator
+   */
+  SRGRConversionParameters& operator=(const SRGRConversionParameters& rhs);
+
+  /**
+   * @brief This function is able to create a new instance of the class
+   */
+  EnvisatAsarRecord* Instanciate()
+  {
+    return new SRGRConversionParameters();
+  };
+
+  /**
+   * @brief This function is able to create a new instance of the class initialised with the data of the calling instance
+   */
+  EnvisatAsarRecord* Clone()
+  {
+    return new SRGRConversionParameters(*this);
+  };
+
+  /**
+   * @brief Reads the class data from a stream
+   */
+  void Read(std::istream& is)
+  {
+    is>>*this;
+  };
+
+  /**
+   * @brief Writes the class to a stream
+   */
+  void Write(std::ostream& os)
+  {
+    os<<*this;
+  };
+
+
+  /**
+  * @brief first_zero_doppler_time day
+  */
+  int  get_first_zero_doppler_time_day()
+  {
+    return _first_zero_doppler_time_day;
+  };
+  /**
+  * @brief first_zero_doppler_time second
+  */
+  unsigned int  get_first_zero_doppler_time_sec()
+  {
+    return _first_zero_doppler_time_sec;
+  };
+  /**
+  * @brief first_zero_doppler_time micro sec
+  */
+  unsigned int  get_first_zero_doppler_time_microsec()
+  {
+    return _first_zero_doppler_time_microsec;
+  };
+  /**
+  * @brief attach_flag
+  */
+  bool   get_attach_flag()
+  {
+    return _attach_flag;
+  };
+  /**
+  * @brief input_mean_flag
+  */
+  float   get_slant_range_time()
+  {
+    return _slant_range_time;
+  };
+  /**
+  * @brief input_std_dev_flag
+  */
+  float  get_ground_range_origin()
+  {
+    return _ground_range_origin;
+  };
+  /**
+  * @brief input_gaps_flag
+  */
+  float*  get_srgr_coef()
+  {
+    return _srgr_coef;
+  };
+
+  /**
+  * @brief first_zero_doppler_time day
+  */
+  int   _first_zero_doppler_time_day;
+  /**
+  * @brief first_zero_doppler_time sec
+  */
+  unsigned int   _first_zero_doppler_time_sec;
+  /**
+  * @brief first_zero_doppler_time microsec
+  */
+  unsigned int   _first_zero_doppler_time_microsec;
+  /**
+   * @brief attach_flag
+   */
+  bool   _attach_flag;
+  /**
+   * @brief input_mean_flag
+   */
+  float   _slant_range_time;
+  /**
+   * @brief input_std_dev_flag
+   */
+  float   _ground_range_origin;
+  /**
+   * @brief input_gaps_flag
+   */
+  float   _srgr_coef[5];
+
+
+private:
+
+};
+}
+#endif
+
+
+
diff --git a/ossim_plugins/ossim/EnvisatAsar/dsd.cpp b/ossim_plugins/ossim/EnvisatAsar/dsd.cpp
new file mode 100644
index 0000000..7f54005
--- /dev/null
+++ b/ossim_plugins/ossim/EnvisatAsar/dsd.cpp
@@ -0,0 +1,158 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include <EnvisatAsar/dsd.h>
+
+namespace ossimplugins
+{
+   dsd::dsd() : EnvisatAsarRecord("dsd_rec")
+   {
+   }
+
+   dsd::~dsd()
+   {
+   }
+
+   std::ostream& operator<<(std::ostream& os, const dsd& data)
+   {
+      os<<"ds_name:"<<data._ds_name.c_str()<<std::endl;
+      os<<"ds_type:"<<data._ds_type.c_str()<<std::endl;
+      os<<"filename:"<<data._filename.c_str()<<std::endl;
+      os<<"ds_offset:"<<data._ds_offset<<std::endl;
+      os<<"ds_size:"<<data._ds_size<<std::endl;
+      os<<"num_dsr:"<<data._num_dsr<<std::endl;
+      os<<"dsr_size:"<<data._dsr_size<<std::endl;
+
+      return os;
+   }
+
+   std::istream& operator>>(std::istream& is, dsd& data)
+   {
+      char buf64[65];
+      buf64[64] = '\0';
+      // char buf32[33];
+      // buf32[32] = '\0';
+      char buf28[29];
+      buf28[28] = '\0';
+      char buf27[28];
+      buf27[27] = '\0';
+      // char buf20[21];
+      // buf20[20] = '\0';
+      char buf16[17];
+      buf16[16]='\0';
+      // char buf15[16];
+      // buf15[15] = '\0';
+      // char buf14[15];
+      // buf14[14] = '\0';
+      // char buf13[14];
+      // buf13[13] = '\0';
+      char buf12[13];
+      buf12[12] = '\0';
+      char buf11[12];
+      buf11[11] = '\0';
+      char buf10[11];
+      buf10[10] = '\0';
+      char buf9[10];
+      buf9[9] = '\0';
+      // char buf8[9];
+      // buf8[8] = '\0';
+      // char buf7[8];
+      // buf7[7] = '\0';
+      // char buf6[7];
+      // buf6[6] = '\0';
+      // char buf5[6];
+      // buf5[5] = '\0';
+      // char buf4[5];
+      // buf4[4] = '\0';
+      // char buf3[4];
+      // buf3[3] = '\0';
+      // char buf2[3];
+      // buf2[2] = '\0';
+      char buf1[1];
+
+      is.read(buf9,9);
+
+      is.read(buf28,28);
+      data._ds_name = buf28;
+
+      is.read(buf10,10);
+
+      is.read(buf1,1);
+      data._ds_type = buf1;
+
+      is.read(buf11,11);
+
+      is.read(buf64,62);
+      buf64[62] = '\0';
+      data._filename = buf64;
+
+      is.read(buf12,12);
+
+      is.read(buf27,21);
+      buf27[21] = '\0';
+      data._ds_offset = atof(buf27);
+
+      is.read(buf16,16);
+
+      is.read(buf27,21);
+      buf27[21] = '\0';
+      data._ds_size = atof(buf27);
+
+      is.read(buf16,16);
+
+      is.read(buf11,11);
+      data._num_dsr = atol(buf11);
+
+      is.read(buf10,10);
+
+      is.read(buf11,11);
+      data._dsr_size = atol(buf11);
+
+      is.read(buf64,41);
+
+      return is;
+
+   }
+   std::string   _ds_name;
+   std::string   _ds_type;
+   std::string   _filename;
+   double	_ds_offset;
+   double	_ds_size;
+   int	_num_dsr;
+   int	_dsr_size;
+
+   dsd::dsd(const dsd& rhs):
+      EnvisatAsarRecord(rhs),
+      _ds_name(rhs._ds_name),
+      _ds_type(rhs._ds_type),
+      _filename(rhs._filename),
+      _ds_offset(rhs._ds_offset),
+      _ds_size(rhs._ds_size),
+      _num_dsr(rhs._num_dsr),
+      _dsr_size(rhs._dsr_size)
+   {
+   }
+
+
+   dsd& dsd::operator=(const dsd& rhs)
+   {
+      _ds_name = rhs._ds_name;
+      _ds_type = rhs._ds_type;
+      _filename = rhs._filename;
+      _ds_offset = rhs._ds_offset;
+      _ds_size = rhs._ds_size;
+      _num_dsr = rhs._num_dsr;
+      _dsr_size = rhs._dsr_size;
+
+      return *this;
+   }
+}
+
diff --git a/ossim_plugins/ossim/EnvisatAsar/dsd.h b/ossim_plugins/ossim/EnvisatAsar/dsd.h
new file mode 100644
index 0000000..b822ffd
--- /dev/null
+++ b/ossim_plugins/ossim/EnvisatAsar/dsd.h
@@ -0,0 +1,176 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef dsd_h
+#define dsd_h
+
+#include <iostream>
+#include <EnvisatAsar/EnvisatAsarRecord.h>
+
+namespace ossimplugins
+{
+/**
+ * @ingroup dsdRecord
+ * @brief This class is able to read the ASAR dsd record
+ */
+class dsd : public EnvisatAsarRecord
+{
+public:
+  /**
+   * @brief Constructor
+   */
+  dsd();
+
+  /**
+   * @brief Destructor
+   */
+  virtual ~dsd();
+
+  /**
+   * @brief This function write the dsd in a stream
+   */
+  friend std::ostream& operator<<(std::ostream& os, const dsd& data);
+
+  /**
+   * @brief This function read a dsd from a stream
+   */
+  friend std::istream& operator>>(std::istream& is, dsd& data);
+
+  /**
+   * @brief Copy constructor
+   */
+  dsd(const dsd& rhs);
+
+  /**
+   * @brief Copy operator
+   */
+  dsd& operator=(const dsd& rhs);
+
+  /**
+   * @brief This function is able to create a new instance of the class
+   */
+  EnvisatAsarRecord* Instanciate()
+  {
+    return new dsd();
+  };
+
+  /**
+   * @brief This function is able to create a new instance of the class initialised with the data of the calling instance
+   */
+  EnvisatAsarRecord* Clone()
+  {
+    return new dsd(*this);
+  };
+
+  /**
+   * @brief Read the class data from a stream
+   */
+  void Read(std::istream& is)
+  {
+    is>>*this;
+  };
+
+  /**
+   * @brief Write the class to a stream
+   */
+  void Write(std::ostream& os)
+  {
+    os<<*this;
+  };
+
+
+  /**
+  * @brief Data set Name
+  */
+  std::string   get_ds_name()
+  {
+    return _ds_name;
+  }
+  /**
+  * @brief Data set Type
+  */
+  std::string   get_ds_type()
+  {
+    return _ds_type;
+  }
+  /**
+  * @brief Data set Filename
+  */
+  std::string   get_filename()
+  {
+    return _filename;
+  }
+  /**
+  * @brief Data set Offset
+  */
+  double   get_ds_offset()
+  {
+    return _ds_offset;
+  }
+  /**
+  * @brief Data set Size
+  */
+  double   get_ds_size()
+  {
+    return _ds_size;
+  }
+  /**
+  * @brief Number of data set record
+  */
+  int   get_num_dsr()
+  {
+    return _num_dsr;
+  }
+  /**
+  * @brief Data set record size
+  */
+  int   get_dsr_size()
+  {
+    return _dsr_size;
+  }
+
+  /**
+  * @brief Data set Name
+  */
+  std::string   _ds_name;
+  /**
+  * @brief Data set Type
+  */
+  std::string   _ds_type;
+  /**
+  * @brief Data set Filename
+  */
+  std::string   _filename;
+  /**
+  * @brief Data set Offset
+  */
+  double  _ds_offset;
+  /**
+  * @brief Data set Size
+  */
+  double  _ds_size;
+  /**
+  * @brief Number of data set record
+  */
+  int  _num_dsr;
+  /**
+  * @brief Data set record size
+  */
+  int  _dsr_size;
+
+private:
+
+};
+}
+#endif
+
+
+
diff --git a/ossim_plugins/ossim/EnvisatAsar/mph.cpp b/ossim_plugins/ossim/EnvisatAsar/mph.cpp
new file mode 100644
index 0000000..9cab20e
--- /dev/null
+++ b/ossim_plugins/ossim/EnvisatAsar/mph.cpp
@@ -0,0 +1,820 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include <EnvisatAsar/mph.h>
+
+namespace ossimplugins
+{
+   mph::mph() : EnvisatAsarRecord("mph_rec")
+   {
+   }
+
+   mph::~mph()
+   {
+   }
+
+   std::ostream& operator<<(std::ostream& os, const mph& data)
+   {
+      os<<"product_name:"<<data._product_name.c_str()<<std::endl;
+
+      os<<"product:"<<data._product.c_str()<<std::endl;
+
+      os<<"proc_stage_title:"<<data._proc_stage_title.c_str()<<std::endl;
+
+      os<<"proc_stage:"<<data._proc_stage.c_str()<<std::endl;
+
+      os<<"ref_doc_title:"<<data._ref_doc_title.c_str()<<std::endl;
+
+      os<<"ref_doc:"<<data._ref_doc.c_str()<<std::endl;
+
+      os<<"acq_stat_id_title:"<<data._acq_stat_id_title.c_str()<<std::endl;
+
+      os<<"acq_station:"<<data._acq_station.c_str()<<std::endl;
+
+      os<<"proc_center_title:"<<data._proc_center_title.c_str()<<std::endl;
+
+      os<<"proc_center:"<<data._proc_center.c_str()<<std::endl;
+
+      os<<"proc_time_title:"<<data._proc_time_title.c_str()<<std::endl;
+
+      os<<"proc_time:"<<data._proc_time.c_str()<<std::endl;
+
+      os<<"soft_version_title:"<<data._soft_version_title.c_str()<<std::endl;
+
+      os<<"soft_version:"<<data._soft_version.c_str()<<std::endl;
+
+      os<<"sensing_start_title:"<<data._sensing_start_title.c_str()<<std::endl;
+
+      os<<"sensing_start:"<<data._sensing_start.c_str()<<std::endl;
+
+      os<<"sensing_stop_title:"<<data._sensing_stop_title.c_str()<<std::endl;
+
+      os<<"sensing_stop:"<<data._sensing_stop.c_str()<<std::endl;
+
+      os<<"phase_title:"<<data._phase_title.c_str()<<std::endl;
+
+      os<<"phase:"<<data._phase.c_str()<<std::endl;
+
+      os<<"cycle_title:"<<data._cycle_title.c_str()<<std::endl;
+
+      os<<"cycle:"<<data._cycle.c_str()<<std::endl;
+
+      os<<"relative_orbit_title:"<<data._relative_orbit_title.c_str()<<std::endl;
+
+      os<<"rel_orbit:"<<data._rel_orbit.c_str()<<std::endl;
+
+      os<<"absolute_orbit_title:"<<data._absolute_orbit_title.c_str()<<std::endl;
+
+      os<<"abs_orbit:"<<data._abs_orbit.c_str()<<std::endl;
+
+      os<<"state_vector_time_title:"<<data._state_vector_time_title.c_str()<<std::endl;
+
+      os<<"state_vector_time:"<<data._state_vector_time.c_str()<<std::endl;
+
+      os<<"delta_ut1_title:"<<data._delta_ut1_title.c_str()<<std::endl;
+
+      os<<"delta_ut1:"<<data._delta_ut1.c_str()<<std::endl;
+
+      os<<"delta_ut1_units:"<<data._delta_ut1_units.c_str()<<std::endl;
+
+      os<<"x_position_title:"<<data._x_position_title.c_str()<<std::endl;
+
+      os<<"x_position:"<<data._x_position.c_str()<<std::endl;
+
+      os<<"x_position_units:"<<data._x_position_units.c_str()<<std::endl;
+
+      os<<"y_position_title:"<<data._y_position_title.c_str()<<std::endl;
+
+      os<<"y_position:"<<data._y_position.c_str()<<std::endl;
+
+      os<<"y_position_units:"<<data._y_position_units.c_str()<<std::endl;
+
+      os<<"z_position_title:"<<data._z_position_title.c_str()<<std::endl;
+
+      os<<"z_position:"<<data._z_position.c_str()<<std::endl;
+
+      os<<"z_position_units:"<<data._z_position_units.c_str()<<std::endl;
+
+      os<<"x_velocity_title:"<<data._x_velocity_title.c_str()<<std::endl;
+
+      os<<"x_velocity:"<<data._x_velocity.c_str()<<std::endl;
+
+      os<<"x_velocity_units:"<<data._x_velocity_units.c_str()<<std::endl;
+
+      os<<"y_velocity_title:"<<data._y_velocity_title.c_str()<<std::endl;
+
+      os<<"y_velocity:"<<data._y_velocity.c_str()<<std::endl;
+
+      os<<"y_velocity_units:"<<data._y_velocity_units.c_str()<<std::endl;
+
+      os<<"z_velocity_title:"<<data._z_velocity_title.c_str()<<std::endl;
+
+      os<<"z_velocity:"<<data._z_velocity.c_str()<<std::endl;
+
+      os<<"z_velocity_units:"<<data._z_velocity_units.c_str()<<std::endl;
+
+      os<<"vector_source_title:"<<data._vector_source_title.c_str()<<std::endl;
+
+      os<<"vector_source:"<<data._vector_source.c_str()<<std::endl;
+
+      os<<"spare_4:"<<data._spare_4.c_str()<<std::endl;
+
+      os<<"utc_sbt_time_title:"<<data._utc_sbt_time_title.c_str()<<std::endl;
+
+      os<<"utc_sbt_time:"<<data._utc_sbt_time.c_str()<<std::endl;
+
+      os<<"sat_binary_time_title:"<<data._sat_binary_time_title.c_str()<<std::endl;
+
+      os<<"sat_binary_time:"<<data._sat_binary_time.c_str()<<std::endl;
+
+      os<<"clock_step_title:"<<data._clock_step_title.c_str()<<std::endl;
+
+      os<<"clock_step:"<<data._clock_step.c_str()<<std::endl;
+
+      os<<"clock_step_units:"<<data._clock_step_units.c_str()<<std::endl;
+
+      os<<"leap_utc_title:"<<data._leap_utc_title.c_str()<<std::endl;
+
+      os<<"leap_utc:"<<data._leap_utc.c_str()<<std::endl;
+
+      os<<"leap_sign_title:"<<data._leap_sign_title.c_str()<<std::endl;
+
+      os<<"leap_sign:"<<data._leap_sign.c_str()<<std::endl;
+
+      os<<"leap_err_title:"<<data._leap_err_title.c_str()<<std::endl;
+
+      os<<"leap_err:"<<data._leap_err.c_str()<<std::endl;
+
+      os<<"product_err_title:"<<data._product_err_title.c_str()<<std::endl;
+
+      os<<"product_err:"<<data._product_err.c_str()<<std::endl;
+
+      os<<"total_size_title:"<<data._total_size_title.c_str()<<std::endl;
+
+      os<<"tot_size:"<<data._tot_size.c_str()<<std::endl;
+
+      os<<"total_size_units:"<<data._total_size_units.c_str()<<std::endl;
+
+      os<<"sph_size_title:"<<data._sph_size_title.c_str()<<std::endl;
+
+      os<<"sph_size:"<<data._sph_size.c_str()<<std::endl;
+
+      os<<"sph_size_units:"<<data._sph_size_units.c_str()<<std::endl;
+
+      os<<"number_of_dsd_title:"<<data._number_of_dsd_title.c_str()<<std::endl;
+
+      os<<"num_dsd:"<<data._num_dsd<<std::endl;
+
+      os<<"size_of_dsd_title:"<<data._size_of_dsd_title.c_str()<<std::endl;
+
+      os<<"dsd_size:"<<data._dsd_size<<std::endl;
+
+      os<<"size_of_dsd_units:"<<data._size_of_dsd_units.c_str()<<std::endl;
+
+      os<<"number_of_ds_att_title:"<<data._number_of_ds_att_title.c_str()<<std::endl;
+
+      os<<"num_data_sets:"<<data._num_data_sets<<std::endl;
+
+      return os;
+
+   }
+
+   std::istream& operator>>(std::istream& is, mph& data)
+   {
+      char buf64[65];
+      buf64[64] = '\0';
+      char buf32[33];
+      buf32[32] = '\0';
+      char buf27[28];
+      buf27[27]='\0';
+      char buf16[17];
+      buf16[16]='\0';
+      // char buf15[16];
+      // buf15[15] = '\0';
+      // char buf14[15];
+      // buf14[14] = '\0';
+      // char buf13[14];
+      // buf13[13] = '\0';
+      char buf12[13];
+      buf12[12] = '\0';
+      char buf11[12];
+      buf11[11] = '\0';
+      char buf10[11];
+      buf10[10] = '\0';
+      // char buf9[10];
+      // buf9[9] = '\0';
+      char buf8[9];
+      buf8[8] = '\0';
+      char buf7[8];
+      buf7[7] = '\0';
+      char buf6[7];
+      buf6[6] = '\0';
+      // char buf5[6];
+      // buf5[5] = '\0';
+      char buf4[5];
+      buf4[4] = '\0';
+      char buf3[4];
+      buf3[3] = '\0';
+      char buf2[3];
+      buf2[2] = '\0';
+      char buf1[1];
+      buf1[0] = '\0';
+
+      is.read(buf8,8);
+      data._product_name = buf8;
+
+      is.read(buf1,1);
+
+      is.read(buf64,62);
+      buf64[62]='\0';
+      data._product = buf64;
+
+      is.read(buf1,1);
+
+      is.read(buf1,1);
+
+      is.read(buf16,11);
+      buf16[11]='\0';
+      data._proc_stage_title = buf16;
+
+      is.read(buf1,1);
+      data._proc_stage = buf1;
+
+      is.read(buf1,1);
+
+      is.read(buf8,8);
+      data._ref_doc_title = buf8;
+
+      is.read(buf1,1);
+
+      is.read(buf32,23);
+      buf32[23]='\0';
+      data._ref_doc = buf32;
+
+      is.read(buf1,1);
+
+      is.read(buf1,1);
+
+      is.read(buf64,40);
+
+      is.read(buf1,1);
+
+      is.read(buf32,20);
+      buf32[20]='\0';
+      data._acq_stat_id_title = buf32;
+
+      is.read(buf1,1);
+
+      is.read(buf32,20);
+      buf32[20]='\0';
+      data._acq_station = buf32;
+
+      is.read(buf1,1);
+
+      is.read(buf1,1);
+
+      is.read(buf16,12);
+      buf16[12]='\0';
+      data._proc_center_title = buf16;
+
+      is.read(buf1,1);
+
+      is.read(buf8,6);
+      buf8[6]='\0';
+      data._proc_center = buf8;
+
+      is.read(buf1,1);
+
+      is.read(buf1,1);
+
+      is.read(buf16,10);
+      buf16[10]='\0';
+      data._proc_time_title = buf16;
+
+      is.read(buf1,1);
+
+      is.read(buf32,27);
+      buf32[27]='\0';
+      data._proc_time = buf32;
+
+      is.read(buf1,1);
+
+      is.read(buf1,1);
+
+      is.read(buf16,13);
+      buf16[13]='\0';
+      data._soft_version_title = buf16;
+
+      is.read(buf1,1);
+
+      is.read(buf16,14);
+      buf16[14]='\0';
+      data._soft_version = buf16;
+
+      is.read(buf1,1);
+
+      is.read(buf1,1);
+
+      is.read(buf64,40);
+
+      is.read(buf1,1);
+
+      is.read(buf16,14);
+      buf16[14]='\0';
+      data._sensing_start_title = buf16;
+
+      is.read(buf1,1);
+
+      is.read(buf32,27);
+      buf32[27]='\0';
+      data._sensing_start = buf32;
+
+      is.read(buf1,1);
+
+      is.read(buf1,1);
+
+      is.read(buf16,13);
+      buf16[13]='\0';
+      data._sensing_stop_title = buf16;
+
+      is.read(buf1,1);
+
+      is.read(buf32,27);
+      buf32[27]='\0';
+      data._sensing_stop = buf32;
+
+      is.read(buf1,1);
+
+      is.read(buf1,1);
+
+      is.read(buf64,40);
+
+      is.read(buf1,1);
+
+      is.read(buf6,6);
+      data._phase_title = buf6;
+
+      is.read(buf1,1);
+      data._phase = buf1;
+
+      is.read(buf1,1);
+
+      is.read(buf6,6);
+      data._cycle_title = buf6;
+
+      is.read(buf4,4);
+      data._cycle = buf4;
+
+      is.read(buf1,1);
+
+      is.read(buf10,10);
+      data._relative_orbit_title = buf10;
+
+      is.read(buf6,6);
+      data._rel_orbit = buf6;
+
+      is.read(buf1,1);
+
+      is.read(buf10,10);
+      data._absolute_orbit_title = buf10;
+
+      is.read(buf6,6);
+      data._abs_orbit = buf6;
+
+      is.read(buf1,1);
+
+      is.read(buf32,18);
+      buf32[18]='\0';
+      data._state_vector_time_title = buf32;
+
+      is.read(buf1,1);
+
+      is.read(buf27,27);
+      data._state_vector_time = buf27;
+
+      is.read(buf1,1);
+
+      is.read(buf1,1);
+
+      is.read(buf10,10);
+      data._delta_ut1_title = buf10;
+
+      is.read(buf8,8);
+      data._delta_ut1 = buf8;
+
+      is.read(buf4,3);
+      buf4[3]='\0';
+      data._delta_ut1_units = buf4;
+
+      is.read(buf1,1);
+
+      is.read(buf11,11);
+      data._x_position_title = buf11;
+
+      is.read(buf12,12);
+      data._x_position = buf12;
+
+      is.read(buf3,3);
+      data._x_position_units = buf3;
+
+      is.read(buf1,1);
+
+      is.read(buf11,11);
+      data._y_position_title = buf11;
+
+      is.read(buf12,12);
+      data._y_position = buf12;
+
+      is.read(buf3,3);
+      data._y_position_units = buf3;
+
+      is.read(buf1,1);
+
+      is.read(buf11,11);
+      data._z_position_title = buf11;
+
+      is.read(buf12,12);
+      data._z_position = buf12;
+
+      is.read(buf3,3);
+      data._z_position_units = buf3;
+
+      is.read(buf1,1);
+
+      is.read(buf11,11);
+      data._x_velocity_title = buf11;
+
+      is.read(buf12,12);
+      data._x_velocity = buf12;
+
+      is.read(buf8,5);
+      buf8[5] = '\0';
+      data._x_velocity_units = buf8;
+
+      is.read(buf1,1);
+
+      is.read(buf11,11);
+      data._y_velocity_title = buf11;
+
+      is.read(buf12,12);
+      data._y_velocity = buf12;
+
+      is.read(buf8,5);
+      buf8[5] = '\0';
+      data._y_velocity_units = buf8;
+
+      is.read(buf1,1);
+
+      is.read(buf11,11);
+      data._z_velocity_title = buf11;
+
+      is.read(buf12,12);
+      data._z_velocity = buf12;
+
+      is.read(buf8,5);
+      buf8[5] = '\0';
+      data._z_velocity_units = buf8;
+
+      is.read(buf1,1);
+
+      is.read(buf16,14);
+      buf16[14] = '\0';
+      data._vector_source_title = buf16;
+
+      is.read(buf1,1);
+
+      is.read(buf2,2);
+      data._vector_source = buf2;
+
+      is.read(buf1,1);
+
+      is.read(buf1,1);
+
+      is.read(buf64,40);
+      buf64[40] = '\0';
+      data._spare_4 = buf64;
+
+      is.read(buf1,1);
+
+      is.read(buf16,13);
+      buf16[13] = '\0';
+      data._utc_sbt_time_title = buf16;
+
+      is.read(buf1,1);
+
+      is.read(buf27,27);
+      data._utc_sbt_time = buf27;
+
+      is.read(buf1,1);
+
+      is.read(buf1,1);
+
+      is.read(buf16,16);
+      data._sat_binary_time_title = buf16;
+
+      is.read(buf11,11);
+      data._sat_binary_time = buf11;
+
+      is.read(buf1,1);
+
+      is.read(buf11,11);
+      data._clock_step_title = buf11;
+
+      is.read(buf11,11);
+      data._clock_step = buf11;
+
+      is.read(buf4,4);
+      data._clock_step_units = buf4;
+
+      is.read(buf1,1);
+
+      is.read(buf32,32);
+
+      is.read(buf1,1);
+
+      is.read(buf10,9);
+      buf10[9] = '\0';
+      data._leap_utc_title = buf10;
+
+      is.read(buf1,1);
+
+      is.read(buf27,27);
+      data._leap_utc = buf27;
+
+      is.read(buf1,1);
+
+      is.read(buf1,1);
+
+      is.read(buf10,10);
+      data._leap_sign_title = buf10;
+
+      is.read(buf4,4);
+      data._leap_sign = buf4;
+
+      is.read(buf1,1);
+
+      is.read(buf10,9);
+      buf10[9] = '\0';
+      data._leap_err_title = buf10;
+
+      is.read(buf1,1);
+      data._leap_err = buf1;
+
+      is.read(buf1,1);
+
+      is.read(buf64,40);
+
+      is.read(buf1,1);
+
+      is.read(buf12,12);
+      data._product_err_title = buf12;
+
+      is.read(buf1,1);
+      data._product_err = buf1;
+
+      is.read(buf1,1);
+
+      is.read(buf10,9);
+      buf10[9] = '\0';
+      data._total_size_title = buf10;
+
+      is.read(buf32,21);
+      buf32[21] = '\0';
+      data._tot_size = buf32;
+
+      is.read(buf7,7);
+      data._total_size_units = buf7;
+
+      is.read(buf1,1);
+
+      is.read(buf10,9);
+      buf10[9] = '\0';
+      data._sph_size_title = buf10;
+
+      is.read(buf11,11);
+      data._sph_size = buf11;
+
+      is.read(buf8,7);
+      buf8[7] = '\0';
+      data._sph_size_units = buf8;
+
+      is.read(buf1,1);
+
+      is.read(buf8,8);
+      data._number_of_dsd_title = buf8;
+
+      is.read(buf11,11);
+      data._num_dsd = atoi(buf11);
+
+      is.read(buf1,1);
+
+      is.read(buf10,9);
+      buf10[9] = '\0';
+      data._size_of_dsd_title = buf10;
+
+      is.read(buf11,11);
+      data._dsd_size = atoi(buf11);
+
+      is.read(buf8,7);
+      buf8[7] = '\0';
+      data._size_of_dsd_units = buf8;
+
+      is.read(buf1,1);
+
+      is.read(buf16,14);
+      buf16[14] = '\0';
+      data._number_of_ds_att_title = buf16;
+
+      is.read(buf11,11);
+      data._num_data_sets = atoi(buf11);
+
+      is.read(buf1,1);
+
+      is.read(buf64,40);
+
+      is.read(buf1,1);
+
+      return is;
+   }
+
+
+   mph::mph(const mph& rhs):
+      EnvisatAsarRecord(rhs),
+      _product_name(rhs._product_name),
+      _product(rhs._product),
+      _proc_stage_title(rhs._proc_stage_title),
+      _proc_stage(rhs._proc_stage),
+      _ref_doc_title(rhs._ref_doc_title),
+      _ref_doc(rhs._ref_doc),
+      _acq_stat_id_title(rhs._acq_stat_id_title),
+      _acq_station(rhs._acq_station),
+      _proc_center_title(rhs._proc_center_title),
+      _proc_center(rhs._proc_center),
+      _proc_time_title(rhs._proc_time_title),
+      _proc_time(rhs._proc_time),
+      _soft_version_title(rhs._soft_version_title),
+      _soft_version(rhs._soft_version),
+      _sensing_start_title(rhs._sensing_start_title),
+      _sensing_start(rhs._sensing_start),
+      _sensing_stop_title(rhs._sensing_stop_title),
+      _sensing_stop(rhs._sensing_stop),
+      _phase_title(rhs._phase_title),
+      _phase(rhs._phase),
+      _cycle_title(rhs._cycle_title),
+      _cycle(rhs._cycle),
+      _relative_orbit_title(rhs._relative_orbit_title),
+      _rel_orbit(rhs._rel_orbit),
+      _absolute_orbit_title(rhs._absolute_orbit_title),
+      _abs_orbit(rhs._abs_orbit),
+      _state_vector_time_title(rhs._state_vector_time_title),
+      _state_vector_time(rhs._state_vector_time),
+      _delta_ut1_title(rhs._delta_ut1_title),
+      _delta_ut1(rhs._delta_ut1),
+      _delta_ut1_units(rhs._delta_ut1_units),
+      _x_position_title(rhs._x_position_title),
+      _x_position(rhs._x_position),
+      _x_position_units(rhs._x_position_units),
+      _y_position_title(rhs._y_position_title),
+      _y_position(rhs._y_position),
+      _y_position_units(rhs._y_position_units),
+      _z_position_title(rhs._z_position_title),
+      _z_position(rhs._z_position),
+      _z_position_units(rhs._z_position_units),
+      _x_velocity_title(rhs._x_velocity_title),
+      _x_velocity(rhs._x_velocity),
+      _x_velocity_units(rhs._x_velocity_units),
+      _y_velocity_title(rhs._y_velocity_title),
+      _y_velocity(rhs._y_velocity),
+      _y_velocity_units(rhs._y_velocity_units),
+      _z_velocity_title(rhs._z_velocity_title),
+      _z_velocity(rhs._z_velocity),
+      _z_velocity_units(rhs._z_velocity_units),
+      _vector_source_title(rhs._vector_source_title),
+      _vector_source(rhs._vector_source),
+      _spare_4(rhs._spare_4),
+      _utc_sbt_time_title(rhs._utc_sbt_time_title),
+      _utc_sbt_time(rhs._utc_sbt_time),
+      _sat_binary_time_title(rhs._sat_binary_time_title),
+      _sat_binary_time(rhs._sat_binary_time),
+      _clock_step_title(rhs._clock_step_title),
+      _clock_step(rhs._clock_step),
+      _clock_step_units(rhs._clock_step_units),
+      _leap_utc_title(rhs._leap_utc_title),
+      _leap_utc(rhs._leap_utc),
+      _leap_sign_title(rhs._leap_sign_title),
+      _leap_sign(rhs._leap_sign),
+      _leap_err_title(rhs._leap_err_title),
+      _leap_err(rhs._leap_err),
+      _product_err_title(rhs._product_err_title),
+      _product_err(rhs._product_err),
+      _total_size_title(rhs._total_size_title),
+      _tot_size(rhs._tot_size),
+      _total_size_units(rhs._total_size_units),
+      _sph_size_title(rhs._sph_size_title),
+      _sph_size(rhs._sph_size),
+      _sph_size_units(rhs._sph_size_units),
+      _number_of_dsd_title(rhs._number_of_dsd_title),
+      _num_dsd(rhs._num_dsd),
+      _size_of_dsd_title(rhs._size_of_dsd_title),
+      _dsd_size(rhs._dsd_size),
+      _size_of_dsd_units(rhs._size_of_dsd_units),
+      _number_of_ds_att_title(rhs._number_of_ds_att_title),
+      _num_data_sets(rhs._num_data_sets)
+   {}
+
+
+   mph& mph::operator=(const mph& rhs)
+   {
+      _product_name = rhs._product_name;
+      _product = rhs._product;
+      _proc_stage_title = rhs._proc_stage_title;
+      _proc_stage = rhs._proc_stage;
+      _ref_doc_title = rhs._ref_doc_title;
+      _ref_doc = rhs._ref_doc;
+      _acq_stat_id_title = rhs._acq_stat_id_title;
+      _acq_station = rhs._acq_station;
+      _proc_center_title = rhs._proc_center_title;
+      _proc_center = rhs._proc_center;
+      _proc_time_title = rhs._proc_time_title;
+      _proc_time = rhs._proc_time;
+      _soft_version_title = rhs._soft_version_title;
+      _soft_version = rhs._soft_version;
+      _sensing_start_title = rhs._sensing_start_title;
+      _sensing_start = rhs._sensing_start;
+      _sensing_stop_title = rhs._sensing_stop_title;
+      _sensing_stop = rhs._sensing_stop;
+      _phase_title = rhs._phase_title;
+      _phase = rhs._phase;
+      _cycle_title = rhs._cycle_title;
+      _cycle = rhs._cycle;
+      _relative_orbit_title = rhs._relative_orbit_title;
+      _rel_orbit = rhs._rel_orbit;
+      _absolute_orbit_title = rhs._absolute_orbit_title;
+      _abs_orbit = rhs._abs_orbit;
+      _state_vector_time_title = rhs._state_vector_time_title;
+      _state_vector_time = rhs._state_vector_time;
+      _delta_ut1_title = rhs._delta_ut1_title;
+      _delta_ut1 = rhs._delta_ut1;
+      _delta_ut1_units = rhs._delta_ut1_units;
+      _x_position_title = rhs._x_position_title;
+      _x_position = rhs._x_position;
+      _x_position_units = rhs._x_position_units;
+      _y_position_title = rhs._y_position_title;
+      _y_position = rhs._y_position;
+      _y_position_units = rhs._y_position_units;
+      _z_position_title = rhs._z_position_title;
+      _z_position = rhs._z_position;
+      _z_position_units = rhs._z_position_units;
+      _x_velocity_title = rhs._x_velocity_title;
+      _x_velocity = rhs._x_velocity;
+      _x_velocity_units = rhs._x_velocity_units;
+      _y_velocity_title = rhs._y_velocity_title;
+      _y_velocity = rhs._y_velocity;
+      _y_velocity_units = rhs._y_velocity_units;
+      _z_velocity_title = rhs._z_velocity_title;
+      _z_velocity = rhs._z_velocity;
+      _z_velocity_units = rhs._z_velocity_units;
+      _vector_source_title = rhs._vector_source_title;
+      _vector_source = rhs._vector_source;
+      _spare_4 = rhs._spare_4;
+      _utc_sbt_time_title = rhs._utc_sbt_time_title;
+      _utc_sbt_time = rhs._utc_sbt_time;
+      _sat_binary_time_title = rhs._sat_binary_time_title;
+      _sat_binary_time = rhs._sat_binary_time;
+      _clock_step_title = rhs._clock_step_title;
+      _clock_step = rhs._clock_step;
+      _clock_step_units = rhs._clock_step_units;
+      _leap_utc_title = rhs._leap_utc_title;
+      _leap_utc = rhs._leap_utc;
+      _leap_sign_title = rhs._leap_sign_title;
+      _leap_sign = rhs._leap_sign;
+      _leap_err_title = rhs._leap_err_title;
+      _leap_err = rhs._leap_err;
+      _product_err_title = rhs._product_err_title;
+      _product_err = rhs._product_err;
+      _total_size_title = rhs._total_size_title;
+      _tot_size = rhs._tot_size;
+      _total_size_units = rhs._total_size_units;
+      _sph_size_title = rhs._sph_size_title;
+      _sph_size = rhs._sph_size;
+      _sph_size_units = rhs._sph_size_units;
+      _number_of_dsd_title = rhs._number_of_dsd_title;
+      _num_dsd = rhs._num_dsd;
+      _size_of_dsd_title = rhs._size_of_dsd_title;
+      _dsd_size = rhs._dsd_size;
+      _size_of_dsd_units = rhs._size_of_dsd_units;
+      _number_of_ds_att_title = rhs._number_of_ds_att_title;
+      _num_data_sets = rhs._num_data_sets;
+
+      return *this;
+   }
+}
+
diff --git a/ossim_plugins/ossim/EnvisatAsar/mph.h b/ossim_plugins/ossim/EnvisatAsar/mph.h
new file mode 100644
index 0000000..5a4c9b0
--- /dev/null
+++ b/ossim_plugins/ossim/EnvisatAsar/mph.h
@@ -0,0 +1,990 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef mph_h
+#define mph_h
+
+#include <iostream>
+#include <EnvisatAsar/EnvisatAsarRecord.h>
+
+namespace ossimplugins
+{
+
+/**
+ * @ingroup mphRecord
+ * @brief This class is able to read the ASAR mph record of the leader file
+ */
+class mph : public EnvisatAsarRecord
+{
+public:
+  /**
+   * @brief Constructor
+   */
+  mph();
+
+  /**
+   * @brief Destructor
+   */
+  virtual ~mph();
+
+  /**
+   * @brief This function write the mph in a stream
+   */
+  friend std::ostream& operator<<(std::ostream& os, const mph& data);
+
+  /**
+   * @brief This function read a mph from a stream
+   */
+  friend std::istream& operator>>(std::istream& is, mph& data);
+
+  /**
+   * @brief Copy constructor
+   */
+  mph(const mph& rhs);
+
+  /**
+   * @brief Copy operator
+   */
+  mph& operator=(const mph& rhs);
+
+  /**
+   * @brief This function is able to create a new instance of the class
+   */
+  EnvisatAsarRecord* Instanciate()
+  {
+    return new mph();
+  };
+
+  /**
+   * @brief This function is able to create a new instance of the class initialised with the data of the calling instance
+   */
+  EnvisatAsarRecord* Clone()
+  {
+    return new mph(*this);
+  };
+
+  /**
+   * @brief Read the class data from a stream
+   */
+  void Read(std::istream& is)
+  {
+    is>>*this;
+  };
+
+  /**
+   * @brief Write the class to a stream
+   */
+  void Write(std::ostream& os)
+  {
+    os<<*this;
+  };
+
+  /**
+  * @brief product_name
+  */
+  std::string   get_product_name()
+  {
+    return _product_name;
+  };
+  /**
+  * @brief product
+  */
+  std::string   get_product()
+  {
+    return _product;
+  };
+  /**
+  * @brief proc_stage_title
+  */
+  std::string   get_proc_stage_title()
+  {
+    return _proc_stage_title;
+  };
+  /**
+  * @brief proc_stage
+  */
+  std::string   get_proc_stage()
+  {
+    return _proc_stage;
+  };
+  /**
+  * @brief ref_doc_title
+  */
+  std::string   get_ref_doc_title()
+  {
+    return _ref_doc_title;
+  };
+  /**
+  * @brief ref_doc
+  */
+  std::string   get_ref_doc()
+  {
+    return _ref_doc;
+  };
+  /**
+  * @brief acq_stat_id_title
+  */
+  std::string   get_acq_stat_id_title()
+  {
+    return _acq_stat_id_title;
+  };
+  /**
+  * @brief acq_station
+  */
+  std::string   get_acq_station()
+  {
+    return _acq_station;
+  };
+  /**
+  * @brief proc_center_title
+  */
+  std::string   get_proc_center_title()
+  {
+    return _proc_center_title;
+  };
+  /**
+  * @brief proc_center
+  */
+  std::string   get_proc_center()
+  {
+    return _proc_center;
+  };
+  /**
+  * @brief proc_time_title
+  */
+  std::string   get_proc_time_title()
+  {
+    return _proc_time_title;
+  };
+  /**
+  * @brief proc_time
+  */
+  std::string   get_proc_time()
+  {
+    return _proc_time;
+  };
+  /**
+  * @brief soft_version_title
+  */
+  std::string   get_soft_version_title()
+  {
+    return _soft_version_title;
+  };
+  /**
+  * @brief soft_version
+  */
+  std::string   get_soft_version()
+  {
+    return _soft_version;
+  };
+  /**
+  * @brief sensing_start_title
+  */
+  std::string   get_sensing_start_title()
+  {
+    return _sensing_start_title;
+  };
+  /**
+  * @brief sensing_start
+  */
+  std::string   get_sensing_start()
+  {
+    return _sensing_start;
+  };
+  /**
+  * @brief sensing_stop_title
+  */
+  std::string   get_sensing_stop_title()
+  {
+    return _sensing_stop_title;
+  };
+  /**
+  * @brief sensing_stop
+  */
+  std::string   get_sensing_stop()
+  {
+    return _sensing_stop;
+  };
+  /**
+  * @brief phase_title
+  */
+  std::string   get_phase_title()
+  {
+    return _phase_title;
+  };
+  /**
+  * @brief phase
+  */
+  std::string   get_phase()
+  {
+    return _phase;
+  };
+  /**
+  * @brief cycle_title
+  */
+  std::string   get_cycle_title()
+  {
+    return _cycle_title;
+  };
+  /**
+  * @brief cycle
+  */
+  std::string   get_cycle()
+  {
+    return _cycle;
+  };
+  /**
+  * @brief relative_orbit_title
+  */
+  std::string   get_relative_orbit_title()
+  {
+    return _relative_orbit_title;
+  };
+  /**
+  * @brief rel_orbit
+  */
+  std::string   get_rel_orbit()
+  {
+    return _rel_orbit;
+  };
+  /**
+  * @brief absolute_orbit_title
+  */
+  std::string   get_absolute_orbit_title()
+  {
+    return _absolute_orbit_title;
+  };
+  /**
+  * @brief abs_orbit
+  */
+  std::string   get_abs_orbit()
+  {
+    return _abs_orbit;
+  };
+  /**
+  * @brief state_vector_time_title
+  */
+  std::string   get_state_vector_time_title()
+  {
+    return _state_vector_time_title;
+  };
+  /**
+  * @brief state_vector_time
+  */
+  std::string   get_state_vector_time()
+  {
+    return _state_vector_time;
+  };
+  /**
+  * @brief delta_ut1_title
+  */
+  std::string   get_delta_ut1_title()
+  {
+    return _delta_ut1_title;
+  };
+  /**
+  * @brief delta_ut1
+  */
+  std::string   get_delta_ut1()
+  {
+    return _delta_ut1;
+  };
+  /**
+  * @brief delta_ut1_units
+  */
+  std::string   get_delta_ut1_units()
+  {
+    return _delta_ut1_units;
+  };
+  /**
+  * @brief x_position_title
+  */
+  std::string   get_x_position_title()
+  {
+    return _x_position_title;
+  };
+  /**
+  * @brief x_position
+  */
+  std::string   get_x_position()
+  {
+    return _x_position;
+  };
+  /**
+  * @brief x_position_units
+  */
+  std::string   get_x_position_units()
+  {
+    return _x_position_units;
+  };
+  /**
+  * @brief y_position_title
+  */
+  std::string   get_y_position_title()
+  {
+    return _y_position_title;
+  };
+  /**
+  * @brief y_position
+  */
+  std::string   get_y_position()
+  {
+    return _y_position;
+  };
+  /**
+  * @brief y_position_units
+  */
+  std::string   get_y_position_units()
+  {
+    return _y_position_units;
+  };
+  /**
+  * @brief z_position_title
+  */
+  std::string   get_z_position_title()
+  {
+    return _z_position_title;
+  };
+  /**
+  * @brief z_position
+  */
+  std::string   get_z_position()
+  {
+    return _z_position;
+  };
+  /**
+  * @brief z_position_units
+  */
+  std::string   get_z_position_units()
+  {
+    return _z_position_units;
+  };
+  /**
+  * @brief x_velocity_title
+  */
+  std::string   get_x_velocity_title()
+  {
+    return _x_velocity_title;
+  };
+  /**
+  * @brief x_velocity
+  */
+  std::string   get_x_velocity()
+  {
+    return _x_velocity;
+  };
+  /**
+  * @brief x_velocity_units
+  */
+  std::string   get_x_velocity_units()
+  {
+    return _x_velocity_units;
+  };
+  /**
+  * @brief y_velocity_title
+  */
+  std::string   get_y_velocity_title()
+  {
+    return _y_velocity_title;
+  };
+  /**
+  * @brief y_velocity
+  */
+  std::string   get_y_velocity()
+  {
+    return _y_velocity;
+  };
+  /**
+  * @brief y_velocity_units
+  */
+  std::string   get_y_velocity_units()
+  {
+    return _y_velocity_units;
+  };
+  /**
+  * @brief z_velocity_title
+  */
+  std::string   get_z_velocity_title()
+  {
+    return _z_velocity_title;
+  };
+  /**
+  * @brief z_velocity
+  */
+  std::string   get_z_velocity()
+  {
+    return _z_velocity;
+  };
+  /**
+  * @brief z_velocity_units
+  */
+  std::string   get_z_velocity_units()
+  {
+    return _z_velocity_units;
+  };
+  /**
+  * @brief vector_source_title
+  */
+  std::string   get_vector_source_title()
+  {
+    return _vector_source_title;
+  };
+  /**
+  * @brief vector_source
+  */
+  std::string   get_vector_source()
+  {
+    return _vector_source;
+  };
+  /**
+  * @brief spare_4
+  */
+  std::string   get_spare_4()
+  {
+    return _spare_4;
+  };
+  /**
+  * @brief utc_sbt_time_title
+  */
+  std::string   get_utc_sbt_time_title()
+  {
+    return _utc_sbt_time_title;
+  };
+  /**
+  * @brief utc_sbt_time
+  */
+  std::string   get_utc_sbt_time()
+  {
+    return _utc_sbt_time;
+  };
+  /**
+  * @brief sat_binary_time_title
+  */
+  std::string   get_sat_binary_time_title()
+  {
+    return _sat_binary_time_title;
+  };
+  /**
+  * @brief sat_binary_time
+  */
+  std::string   get_sat_binary_time()
+  {
+    return _sat_binary_time;
+  };
+  /**
+  * @brief clock_step_title
+  */
+  std::string   get_clock_step_title()
+  {
+    return _clock_step_title;
+  };
+  /**
+  * @brief clock_step
+  */
+  std::string   get_clock_step()
+  {
+    return _clock_step;
+  };
+  /**
+  * @brief clock_step_units
+  */
+  std::string   get_clock_step_units()
+  {
+    return _clock_step_units;
+  };
+  /**
+  * @brief leap_utc_title
+  */
+  std::string   get_leap_utc_title()
+  {
+    return _leap_utc_title;
+  };
+  /**
+  * @brief leap_utc
+  */
+  std::string   get_leap_utc()
+  {
+    return _leap_utc;
+  };
+  /**
+  * @brief leap_sign_title
+  */
+  std::string   get_leap_sign_title()
+  {
+    return _leap_sign_title;
+  };
+  /**
+  * @brief leap_sign
+  */
+  std::string   get_leap_sign()
+  {
+    return _leap_sign;
+  };
+  /**
+  * @brief leap_err_title
+  */
+  std::string   get_leap_err_title()
+  {
+    return _leap_err_title;
+  };
+  /**
+  * @brief leap_err
+  */
+  std::string   get_leap_err()
+  {
+    return _leap_err;
+  };
+  /**
+  * @brief product_err_title
+  */
+  std::string   get_product_err_title()
+  {
+    return _product_err_title;
+  };
+  /**
+  * @brief product_err
+  */
+  std::string   get_product_err()
+  {
+    return _product_err;
+  };
+  /**
+  * @brief total_size_title
+  */
+  std::string   get_total_size_title()
+  {
+    return _total_size_title;
+  };
+  /**
+  * @brief tot_size
+  */
+  std::string   get_tot_size()
+  {
+    return _tot_size;
+  };
+  /**
+  * @brief total_size_units
+  */
+  std::string   get_total_size_units()
+  {
+    return _total_size_units;
+  };
+  /**
+  * @brief sph_size_title
+  */
+  std::string   get_sph_size_title()
+  {
+    return _sph_size_title;
+  };
+  /**
+  * @brief sph_size
+  */
+  std::string   get_sph_size()
+  {
+    return _sph_size;
+  };
+  /**
+  * @brief sph_size_units
+  */
+  std::string   get_sph_size_units()
+  {
+    return _sph_size_units;
+  };
+  /**
+  * @brief number_of_dsd_title
+  */
+  std::string   get_number_of_dsd_title()
+  {
+    return _number_of_dsd_title;
+  };
+  /**
+  * @brief num_dsd
+  */
+  int   get_num_dsd()
+  {
+    return _num_dsd;
+  };
+  /**
+  * @brief size_of_dsd_title
+  */
+  std::string   get_size_of_dsd_title()
+  {
+    return _size_of_dsd_title;
+  };
+  /**
+  * @brief dsd_size
+  */
+  int   get_dsd_size()
+  {
+    return _dsd_size;
+  };
+  /**
+  * @brief size_of_dsd_units
+  */
+  std::string   get_size_of_dsd_units()
+  {
+    return _size_of_dsd_units;
+  };
+  /**
+  * @brief number_of_ds_att_title
+  */
+  std::string   get_number_of_ds_att_title()
+  {
+    return _number_of_ds_att_title;
+  };
+  /**
+  * @brief num_data_sets
+  */
+  int   get_num_data_sets()
+  {
+    return _num_data_sets;
+  };
+  /**
+  * @brief Check mph validity
+  */
+  bool is_valid()
+  {
+    if ((_product_name.compare("PRODUCT=") == 0) && (_number_of_dsd_title.compare("NUM_DSD=") == 0))
+    {
+      return true;
+    } else return false;
+  };
+
+
+  /**
+  * @brief product_name
+  */
+  std::string   _product_name;
+  /**
+  * @brief product
+  */
+  std::string   _product;
+  /**
+  * @brief proc_stage_title
+  */
+  std::string   _proc_stage_title;
+  /**
+  * @brief proc_stage
+  */
+  std::string   _proc_stage;
+  /**
+  * @brief ref_doc_title
+  */
+  std::string   _ref_doc_title;
+  /**
+  * @brief ref_doc
+  */
+  std::string   _ref_doc;
+  /**
+  * @brief acq_stat_id_title
+  */
+  std::string   _acq_stat_id_title;
+  /**
+  * @brief acq_station
+  */
+  std::string   _acq_station;
+  /**
+  * @brief proc_center_title
+  */
+  std::string   _proc_center_title;
+  /**
+  * @brief proc_center
+  */
+  std::string   _proc_center;
+  /**
+  * @brief proc_time_title
+  */
+  std::string   _proc_time_title;
+  /**
+  * @brief proc_time
+  */
+  std::string   _proc_time;
+  /**
+  * @brief soft_version_title
+  */
+  std::string   _soft_version_title;
+  /**
+  * @brief soft_version
+  */
+  std::string   _soft_version;
+  /**
+  * @brief sensing_start_title
+  */
+  std::string   _sensing_start_title;
+  /**
+  * @brief sensing_start
+  */
+  std::string   _sensing_start;
+  /**
+  * @brief sensing_stop_title
+  */
+  std::string   _sensing_stop_title;
+  /**
+  * @brief sensing_stop
+  */
+  std::string   _sensing_stop;
+  /**
+  * @brief phase_title
+  */
+  std::string   _phase_title;
+  /**
+  * @brief phase
+  */
+  std::string   _phase;
+  /**
+  * @brief cycle_title
+  */
+  std::string   _cycle_title;
+  /**
+  * @brief cycle
+  */
+  std::string   _cycle;
+  /**
+  * @brief relative_orbit_title
+  */
+  std::string   _relative_orbit_title;
+  /**
+  * @brief rel_orbit
+  */
+  std::string   _rel_orbit;
+  /**
+  * @brief absolute_orbit_title
+  */
+  std::string   _absolute_orbit_title;
+  /**
+  * @brief abs_orbit
+  */
+  std::string   _abs_orbit;
+  /**
+  * @brief state_vector_time_title
+  */
+  std::string   _state_vector_time_title;
+  /**
+  * @brief state_vector_time
+  */
+  std::string   _state_vector_time;
+  /**
+  * @brief delta_ut1_title
+  */
+  std::string   _delta_ut1_title;
+  /**
+  * @brief delta_ut1
+  */
+  std::string   _delta_ut1;
+  /**
+  * @brief delta_ut1_units
+  */
+  std::string   _delta_ut1_units;
+  /**
+  * @brief x_position_title
+  */
+  std::string   _x_position_title;
+  /**
+  * @brief x_position
+  */
+  std::string   _x_position;
+  /**
+  * @brief x_position_units
+  */
+  std::string   _x_position_units;
+  /**
+  * @brief y_position_title
+  */
+  std::string   _y_position_title;
+  /**
+  * @brief y_position
+  */
+  std::string   _y_position;
+  /**
+  * @brief y_position_units
+  */
+  std::string   _y_position_units;
+  /**
+  * @brief z_position_title
+  */
+  std::string   _z_position_title;
+  /**
+  * @brief z_position
+  */
+  std::string   _z_position;
+  /**
+  * @brief z_position_units
+  */
+  std::string   _z_position_units;
+  /**
+  * @brief x_velocity_title
+  */
+  std::string   _x_velocity_title;
+  /**
+  * @brief x_velocity
+  */
+  std::string   _x_velocity;
+  /**
+  * @brief x_velocity_units
+  */
+  std::string   _x_velocity_units;
+  /**
+  * @brief y_velocity_title
+  */
+  std::string   _y_velocity_title;
+  /**
+  * @brief y_velocity
+  */
+  std::string   _y_velocity;
+  /**
+  * @brief y_velocity_units
+  */
+  std::string   _y_velocity_units;
+  /**
+  * @brief z_velocity_title
+  */
+  std::string   _z_velocity_title;
+  /**
+  * @brief z_velocity
+  */
+  std::string   _z_velocity;
+  /**
+  * @brief z_velocity_units
+  */
+  std::string   _z_velocity_units;
+  /**
+  * @brief vector_source_title
+  */
+  std::string   _vector_source_title;
+  /**
+  * @brief vector_source
+  */
+  std::string   _vector_source;
+  /**
+  * @brief spare_4
+  */
+  std::string   _spare_4;
+  /**
+  * @brief utc_sbt_time_title
+  */
+  std::string   _utc_sbt_time_title;
+  /**
+  * @brief utc_sbt_time
+  */
+  std::string   _utc_sbt_time;
+  /**
+  * @brief sat_binary_time_title
+  */
+  std::string   _sat_binary_time_title;
+  /**
+  * @brief sat_binary_time
+  */
+  std::string   _sat_binary_time;
+  /**
+  * @brief clock_step_title
+  */
+  std::string   _clock_step_title;
+  /**
+  * @brief clock_step
+  */
+  std::string   _clock_step;
+  /**
+  * @brief clock_step_units
+  */
+  std::string   _clock_step_units;
+  /**
+  * @brief leap_utc_title
+  */
+  std::string   _leap_utc_title;
+  /**
+  * @brief leap_utc
+  */
+  std::string   _leap_utc;
+  /**
+  * @brief leap_sign_title
+  */
+  std::string   _leap_sign_title;
+  /**
+  * @brief leap_sign
+  */
+  std::string   _leap_sign;
+  /**
+  * @brief leap_err_title
+  */
+  std::string   _leap_err_title;
+  /**
+  * @brief leap_err
+  */
+  std::string   _leap_err;
+  /**
+  * @brief product_err_title
+  */
+  std::string   _product_err_title;
+  /**
+  * @brief product_err
+  */
+  std::string   _product_err;
+  /**
+  * @brief total_size_title
+  */
+  std::string   _total_size_title;
+  /**
+  * @brief tot_size
+  */
+  std::string   _tot_size;
+  /**
+  * @brief total_size_units
+  */
+  std::string   _total_size_units;
+  /**
+  * @brief sph_size_title
+  */
+  std::string   _sph_size_title;
+  /**
+  * @brief sph_size
+  */
+  std::string   _sph_size;
+  /**
+  * @brief sph_size_units
+  */
+  std::string   _sph_size_units;
+  /**
+  * @brief number_of_dsd_title
+  */
+  std::string   _number_of_dsd_title;
+  /**
+  * @brief num_dsd
+  */
+  int   _num_dsd;
+  /**
+  * @brief size_of_dsd_title
+  */
+  std::string   _size_of_dsd_title;
+  /**
+  * @brief dsd_size
+  */
+  int  _dsd_size;
+  /**
+  * @brief size_of_dsd_units
+  */
+  std::string   _size_of_dsd_units;
+  /**
+  * @brief number_of_ds_att_title
+  */
+  std::string   _number_of_ds_att_title;
+  /**
+  * @brief num_data_sets
+  */
+  int   _num_data_sets;
+
+private:
+
+};
+}
+#endif
+
+
+
diff --git a/ossim_plugins/ossim/EnvisatAsar/sph.cpp b/ossim_plugins/ossim/EnvisatAsar/sph.cpp
new file mode 100644
index 0000000..c9ad332
--- /dev/null
+++ b/ossim_plugins/ossim/EnvisatAsar/sph.cpp
@@ -0,0 +1,787 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include <EnvisatAsar/sph.h>
+#include <EnvisatAsar/mph.h>
+
+namespace ossimplugins
+{
+   sph::sph() : EnvisatAsarRecord("sph_rec")
+   {
+      this->_num_dsd = 18;
+      this->_size_dsd = 280;
+   }
+
+   sph::sph(const mph& data) : EnvisatAsarRecord("sph_rec")
+   {
+      this->_num_dsd = data._num_dsd ;
+      this->_size_dsd = data._dsd_size;
+   }
+
+   sph::~sph()
+   {
+   }
+
+
+   std::ostream& operator<<(std::ostream& os, const sph& data)
+   {
+      os<<"sph_desc_title:"<<data._sph_desc_title.c_str()<<std::endl;
+
+      os<<"sph_desc:"<<data._sph_desc.c_str()<<std::endl;
+
+      os<<"strip_cont_ind_title:"<<data._strip_cont_ind_title.c_str()<<std::endl;
+
+      os<<"strip_cont_ind	std::string:"<<data._strip_cont_ind.c_str()<<std::endl;
+
+      os<<"slice_pos_title:"<<data._slice_pos_title.c_str()<<std::endl;
+
+      os<<"slice_position:"<<data._slice_position.c_str()<<std::endl;
+
+      os<<"num_slices_title:"<<data._num_slices_title.c_str()<<std::endl;
+
+      os<<"num_slices:"<<data._num_slices.c_str()<<std::endl;
+
+      os<<"first_line_time_title:"<<data._first_line_time_title.c_str()<<std::endl;
+
+      os<<"first_line_time:"<<data._first_line_time.c_str()<<std::endl;
+
+      os<<"last_line_time_title:"<<data._last_line_time_title.c_str()<<std::endl;
+
+      os<<"last_line_time:"<<data._last_line_time.c_str()<<std::endl;
+
+      os<<"first_near_lat_title:"<<data._first_near_lat_title.c_str()<<std::endl;
+
+      os<<"first_near_lat:"<<data._first_near_lat.c_str()<<std::endl;
+
+      os<<"first_near_lat_units:"<<data._first_near_lat_units.c_str()<<std::endl;
+
+      os<<"first_near_long_title:"<<data._first_near_long_title.c_str()<<std::endl;
+
+      os<<"first_near_long:"<<data._first_near_long.c_str()<<std::endl;
+
+      os<<"first_near_long_units:"<<data._first_near_long_units.c_str()<<std::endl;
+
+      os<<"first_mid_lat_title:"<<data._first_mid_lat_title.c_str()<<std::endl;
+
+      os<<"first_mid_lat:"<<data._first_mid_lat.c_str()<<std::endl;
+
+      os<<"first_mid_lat_units:"<<data._first_mid_lat_units.c_str()<<std::endl;
+
+      os<<"first_mid_long_title:"<<data._first_mid_long_title.c_str()<<std::endl;
+
+      os<<"first_mid_long:"<<data._first_mid_long.c_str()<<std::endl;
+
+      os<<"first_mid_long_units:"<<data._first_mid_long_units.c_str()<<std::endl;
+
+      os<<"first_far_lat_title:"<<data._first_far_lat_title.c_str()<<std::endl;
+
+      os<<"first_far_lat:"<<data._first_far_lat.c_str()<<std::endl;
+
+      os<<"first_far_lat_units:"<<data._first_far_lat_units.c_str()<<std::endl;
+
+      os<<"first_far_long_title:"<<data._first_far_long_title.c_str()<<std::endl;
+
+      os<<"first_far_long:"<<data._first_far_long.c_str()<<std::endl;
+
+      os<<"first_far_long_units:"<<data._first_far_long_units.c_str()<<std::endl;
+
+      os<<"last_near_lat_title:"<<data._last_near_lat_title.c_str()<<std::endl;
+
+      os<<"last_near_lat:"<<data._last_near_lat.c_str()<<std::endl;
+
+      os<<"last_near_lat_units:"<<data._last_near_lat_units.c_str()<<std::endl;
+
+      os<<"last_near_long_title:"<<data._last_near_long_title.c_str()<<std::endl;
+
+      os<<"last_near_long:"<<data._last_near_long.c_str()<<std::endl;
+
+      os<<"last_near_long_units:"<<data._last_near_long_units.c_str()<<std::endl;
+
+      os<<"last_mid_lat_title:"<<data._last_mid_lat_title.c_str()<<std::endl;
+
+      os<<"last_mid_lat:"<<data._last_mid_lat.c_str()<<std::endl;
+
+      os<<"last_mid_lat_units:"<<data._last_mid_lat_units.c_str()<<std::endl;
+
+      os<<"last_mid_long_title:"<<data._last_mid_long_title.c_str()<<std::endl;
+
+      os<<"last_mid_long:"<<data._last_mid_long.c_str()<<std::endl;
+
+      os<<"last_mid_long_units:"<<data._last_mid_long_units.c_str()<<std::endl;
+
+      os<<"last_far_lat_title:"<<data._last_far_lat_title.c_str()<<std::endl;
+
+      os<<"last_far_lat:"<<data._last_far_lat.c_str()<<std::endl;
+
+      os<<"last_far_lat_units:"<<data._last_far_lat_units.c_str()<<std::endl;
+
+      os<<"last_far_long_title:"<<data._last_far_long_title.c_str()<<std::endl;
+
+      os<<"last_far_long:"<<data._last_far_long.c_str()<<std::endl;
+
+      os<<"last_far_long_units:"<<data._last_far_long_units.c_str()<<std::endl;
+
+      os<<"swath_title:"<<data._swath_title.c_str()<<std::endl;
+
+      os<<"swath:"<<data._swath.c_str()<<std::endl;
+
+      os<<"pass_title:"<<data._pass_title.c_str()<<std::endl;
+
+      os<<"pass:"<<data._pass.c_str()<<std::endl;
+
+      os<<"sample_type_title:"<<data._sample_type_title.c_str()<<std::endl;
+
+      os<<"sample_type:"<<data._sample_type.c_str()<<std::endl;
+
+      os<<"algo_title:"<<data._algo_title.c_str()<<std::endl;
+
+      os<<"algorithm:"<<data._algorithm.c_str()<<std::endl;
+
+      os<<"mds1_tx_rx_polar_title:"<<data._mds1_tx_rx_polar_title.c_str()<<std::endl;
+
+      os<<"mds1_tx_rx_polar:"<<data._mds1_tx_rx_polar.c_str()<<std::endl;
+
+      os<<"mds2_tx_rx_polar_title:"<<data._mds2_tx_rx_polar_title.c_str()<<std::endl;
+
+      os<<"mds2_tx_rx_polar:"<<data._mds2_tx_rx_polar.c_str()<<std::endl;
+
+      os<<"compression_title:"<<data._compression_title.c_str()<<std::endl;
+
+      os<<"compression:"<<data._compression.c_str()<<std::endl;
+
+      os<<"azimut_looks_title:"<<data._azimut_looks_title.c_str()<<std::endl;
+
+      os<<"azimut_looks:"<<data._azimut_looks.c_str()<<std::endl;
+
+      os<<"range_looks_title:"<<data._range_looks_title.c_str()<<std::endl;
+
+      os<<"range_looks:"<<data._range_looks.c_str()<<std::endl;
+
+      os<<"range_spacing_title:"<<data._range_spacing_title.c_str()<<std::endl;
+
+      os<<"range_spacing:"<<data._range_spacing.c_str()<<std::endl;
+
+      os<<"range_spacing_unit:"<<data._range_spacing_unit.c_str()<<std::endl;
+
+      os<<"azimut_spacing_title:"<<data._azimut_spacing_title.c_str()<<std::endl;
+
+      os<<"azimut_spacing:"<<data._azimut_spacing.c_str()<<std::endl;
+
+      os<<"azimut_spacing_unit:"<<data._azimut_spacing_unit.c_str()<<std::endl;
+
+      os<<"line_time_interval_title:"<<data._line_time_interval_title.c_str()<<std::endl;
+
+      os<<"line_time_interval:"<<data._line_time_interval.c_str()<<std::endl;
+
+      os<<"line_time_interv_units:"<<data._line_time_interv_units.c_str()<<std::endl;
+
+      os<<"line_length_title:"<<data._line_length_title.c_str()<<std::endl;
+
+      os<<"line_length:"<<data._line_length.c_str()<<std::endl;
+
+      os<<"line_length_units:"<<data._line_length_units.c_str()<<std::endl;
+
+      os<<"data_type_title:"<<data._data_type_title.c_str()<<std::endl;
+
+      os<<"data_type:"<<data._data_type.c_str()<<std::endl;
+
+      return os;
+
+   }
+
+   std::istream& operator>>(std::istream& is, sph& data)
+   {
+      char buf64[65];
+      buf64[64] = '\0';
+      char buf32[33];
+      buf32[32] = '\0';
+      char buf27[28];
+      buf27[27] = '\0';
+      char buf16[17];
+      buf16[16]='\0';
+      char buf15[16];
+      buf15[15] = '\0';
+      char buf14[15];
+      buf14[14] = '\0';
+      char buf13[14];
+      buf13[13] = '\0';
+      char buf12[13];
+      buf12[12] = '\0';
+      char buf11[12];
+      buf11[11] = '\0';
+      char buf10[11];
+      buf10[10] = '\0';
+      char buf9[10];
+      buf9[9] = '\0';
+      char buf8[9];
+      buf8[8] = '\0';
+      char buf7[8];
+      buf7[7] = '\0';
+      char buf6[7];
+      buf6[6] = '\0';
+      char buf5[6];
+      buf5[5] = '\0';
+      char buf4[5];
+      buf4[4] = '\0';
+      char buf3[4];
+      buf3[3] = '\0';
+      // char buf2[3];
+      // buf2[2] = '\0';
+      char buf1[1];
+
+
+      is.read(buf15,15);
+      data._sph_desc_title = buf15;
+
+      is.read(buf1,1);
+
+      is.read(buf32,28);
+      buf32[28] = '\0';
+      data._sph_desc = buf32;
+
+      is.read(buf1,1);
+
+      is.read(buf1,1);
+
+      is.read(buf32,31);
+      buf32[31] = '\0';
+      data._strip_cont_ind_title = buf32;
+
+      is.read(buf4,4);
+      data._strip_cont_ind =  buf4;
+
+      is.read(buf1,1);
+
+      is.read(buf15,15);
+      data._slice_pos_title = buf15;
+
+      is.read(buf4,4);
+      data._slice_position = buf4;
+
+      is.read(buf1,1);
+
+      is.read(buf11,11);
+      data._num_slices_title = buf11;
+
+      is.read(buf4,4);
+      data._num_slices = buf4;
+
+      is.read(buf1,1);
+
+      is.read(buf16,16);
+      data._first_line_time_title = buf16;
+
+      is.read(buf1,1);
+
+      is.read(buf27,27);
+      data._first_line_time = buf27;
+
+      is.read(buf1,1);
+
+      is.read(buf1,1);
+
+      is.read(buf15,15);
+      data._last_line_time_title = buf15;
+
+      is.read(buf1,1);
+
+      is.read(buf27,27);
+      data._last_line_time = buf27;
+
+      is.read(buf1,1);
+
+      is.read(buf1,1);
+
+      is.read(buf15,15);
+      data._first_near_lat_title = buf15;
+
+      is.read(buf11,11);
+      data._first_near_lat = buf11;
+
+      is.read(buf10,10);
+      data._first_near_lat_units = buf10;
+
+      is.read(buf1,1);
+
+      is.read(buf16,16);
+      data._first_near_long_title = buf16;
+
+      is.read(buf11,11);
+      data._first_near_long = buf11;
+
+      is.read(buf10,10);
+      data._first_near_long_units = buf10;
+
+      is.read(buf1,1);
+
+      is.read(buf14,14);
+      data._first_mid_lat_title = buf14;
+
+      is.read(buf11,11);
+      data._first_mid_lat = buf11;
+
+      is.read(buf10,10);
+      data._first_mid_lat_units = buf10;
+
+      is.read(buf1,1);
+
+      is.read(buf15,15);
+      data._first_mid_long_title = buf15;
+
+      is.read(buf11,11);
+      data._first_mid_long = buf11;
+
+      is.read(buf10,10);
+      data._first_mid_long_units = buf10;
+
+      is.read(buf1,1);
+
+      is.read(buf14,14);
+      data._first_far_lat_title = buf14;
+
+      is.read(buf11,11);
+      data._first_far_lat = buf11;
+
+      is.read(buf10,10);
+      data._first_far_lat_units = buf10;
+
+      is.read(buf1,1);
+
+      is.read(buf15,15);
+      data._first_far_long_title = buf15;
+
+      is.read(buf11,11);
+      data._first_far_long = buf11;
+
+      is.read(buf10,10);
+      data._first_far_long_units = buf10;
+
+      is.read(buf1,1);
+
+      is.read(buf14,14);
+      data._last_near_lat_title = buf14;
+
+      is.read(buf11,11);
+      data._last_near_lat = buf11;
+
+      is.read(buf10,10);
+      data._last_near_lat_units = buf10;
+
+      is.read(buf1,1);
+
+      is.read(buf15,15);
+      data._last_near_long_title = buf15;
+
+      is.read(buf11,11);
+      data._last_near_long = buf11;
+
+      is.read(buf10,10);
+      data._last_near_long_units = buf10;
+
+      is.read(buf1,1);
+
+      is.read(buf13,13);
+      data._last_mid_lat_title = buf13;
+
+      is.read(buf11,11);
+      data._last_mid_lat = buf11;
+
+      is.read(buf10,10);
+      data._last_mid_lat_units = buf10;
+
+      is.read(buf1,1);
+
+      is.read(buf14,14);
+      data._last_mid_long_title = buf14;
+
+      is.read(buf11,11);
+      data._last_mid_long = buf11;
+
+      is.read(buf10,10);
+      data._last_mid_long_units = buf10;
+
+      is.read(buf1,1);
+
+      is.read(buf13,13);
+      data._last_far_lat_title = buf13;
+
+      is.read(buf11,11);
+      data._last_far_lat = buf11;
+
+      is.read(buf10,10);
+      data._last_far_lat_units = buf10;
+
+      is.read(buf1,1);
+
+      is.read(buf14,14);
+      data._last_far_long_title = buf14;
+
+      is.read(buf11,11);
+      data._last_far_long = buf11;
+
+      is.read(buf10,10);
+      data._last_far_long_units = buf10;
+
+      is.read(buf1,1);
+
+      is.read(buf64,35);
+
+      is.read(buf1,1);
+
+      is.read(buf6,6);
+      data._swath_title = buf6;
+
+      is.read(buf1,1);
+
+      is.read(buf3,3);
+      data._swath = buf3;
+
+      is.read(buf1,1);
+
+      is.read(buf1,1);
+
+      is.read(buf5,5);
+      data._pass_title = buf5;
+
+      is.read(buf1,1);
+
+      is.read(buf10,10);
+      data._pass = buf10;
+
+      is.read(buf1,1);
+
+      is.read(buf1,1);
+
+      is.read(buf12,12);
+      data._sample_type_title = buf12;
+
+      is.read(buf1,1);
+
+      is.read(buf8,8);
+      data._sample_type = buf8;
+
+      is.read(buf1,1);
+
+      is.read(buf1,1);
+
+      is.read(buf10,10);
+      data._algo_title = buf10;
+
+      is.read(buf1,1);
+
+      is.read(buf7,7);
+      data._algorithm = buf7;
+
+      is.read(buf1,1);
+
+      is.read(buf1,1);
+
+      is.read(buf32,17);
+      buf32[17] = '\0';
+      data._mds1_tx_rx_polar_title = buf32;
+
+      is.read(buf1,1);
+
+      is.read(buf3,3);
+      data._mds1_tx_rx_polar = buf3;
+
+      is.read(buf1,1);
+
+      is.read(buf1,1);
+
+      is.read(buf32,17);
+      buf32[17] = '\0';
+      data._mds2_tx_rx_polar_title = buf32;
+
+      is.read(buf1,1);
+
+      is.read(buf3,3);
+      data._mds2_tx_rx_polar = buf3;
+
+      is.read(buf1,1);
+
+      is.read(buf1,1);
+
+      is.read(buf12,12);
+      data._compression_title = buf12;
+
+      is.read(buf1,1);
+
+      is.read(buf5,5);
+      data._compression = buf5;
+
+      is.read(buf1,1);
+
+      is.read(buf1,1);
+
+      is.read(buf14,14);
+      data._azimut_looks_title = buf14;
+
+      is.read(buf4,4);
+      data._azimut_looks = buf4;
+
+      is.read(buf1,1);
+
+      is.read(buf12,12);
+      data._range_looks_title = buf12;
+
+      is.read(buf4,4);
+      data._range_looks = buf4;
+
+      is.read(buf1,1);
+
+      is.read(buf14,14);
+      data._range_spacing_title = buf14;
+
+      is.read(buf15,15);
+      data._range_spacing = buf15;
+
+      is.read(buf3,3);
+      data._range_spacing_unit = buf3;
+
+      is.read(buf1,1);
+
+      is.read(buf16,16);
+      data._azimut_spacing_title = buf16;
+
+      is.read(buf15,15);
+      data._azimut_spacing = buf15;
+
+      is.read(buf3,3);
+      data._azimut_spacing_unit = buf3;
+
+      is.read(buf1,1);
+
+      is.read(buf32,19);
+      buf32[19] = '\0';
+      data._line_time_interval_title = buf32;
+
+      is.read(buf15,15);
+      data._line_time_interval = buf15;
+
+      is.read(buf3,3);
+      data._line_time_interv_units = buf3;
+
+      is.read(buf1,1);
+
+      is.read(buf12,12);
+      data._line_length_title = buf12;
+
+      is.read(buf6,6);
+      data._line_length = buf6;
+
+      is.read(buf9,9);
+      data._line_length_units = buf9;
+
+      is.read(buf1,1);
+
+      is.read(buf10,10);
+      data._data_type_title = buf10;
+
+      is.read(buf1,1);
+
+      is.read(buf5,5);
+      data._data_type = buf5;
+
+      is.read(buf1,1);
+
+      is.read(buf1,1);
+
+      is.read(buf64,50);
+
+      is.read(buf1,1);
+
+      for (int i = 0; i<data._num_dsd; i++)
+      {
+         dsd dsd_rec;
+         is>>dsd_rec;
+         data._dsd_vector.push_back(dsd_rec);
+      }
+
+      //char *buffer = (char* )malloc(data._num_dsd*data._size_dsd);
+      //is.read(buffer, data._num_dsd*data._size_dsd);
+
+      return is;
+   }
+
+
+   sph::sph(const sph& rhs):
+      EnvisatAsarRecord(rhs),
+      _sph_desc_title(rhs._sph_desc_title),
+      _sph_desc(rhs._sph_desc),
+      _strip_cont_ind_title(rhs._strip_cont_ind_title),
+      _strip_cont_ind(rhs._strip_cont_ind),
+      _slice_pos_title(rhs._slice_pos_title),
+      _slice_position(rhs._slice_position),
+      _num_slices_title(rhs._num_slices_title),
+      _num_slices(rhs._num_slices),
+      _first_line_time_title(rhs._first_line_time_title),
+      _first_line_time(rhs._first_line_time),
+      _last_line_time_title(rhs._last_line_time_title),
+      _last_line_time(rhs._last_line_time),
+      _first_near_lat_title(rhs._first_near_lat_title),
+      _first_near_lat(rhs._first_near_lat),
+      _first_near_lat_units(rhs._first_near_lat_units),
+      _first_near_long_title(rhs._first_near_long_title),
+      _first_near_long(rhs._first_near_long),
+      _first_near_long_units(rhs._first_near_long_units),
+      _first_mid_lat_title(rhs._first_mid_lat_title),
+      _first_mid_lat(rhs._first_mid_lat),
+      _first_mid_lat_units(rhs._first_mid_lat_units),
+      _first_mid_long_title(rhs._first_mid_long_title),
+      _first_mid_long(rhs._first_mid_long),
+      _first_mid_long_units(rhs._first_mid_long_units),
+      _first_far_lat_title(rhs._first_far_lat_title),
+      _first_far_lat(rhs._first_far_lat),
+      _first_far_lat_units(rhs._first_far_lat_units),
+      _first_far_long_title(rhs._first_far_long_title),
+      _first_far_long(rhs._first_far_long),
+      _first_far_long_units(rhs._first_far_long_units),
+      _last_near_lat_title(rhs._last_near_lat_title),
+      _last_near_lat(rhs._last_near_lat),
+      _last_near_lat_units(rhs._last_near_lat_units),
+      _last_near_long_title(rhs._last_near_long_title),
+      _last_near_long(rhs._last_near_long),
+      _last_near_long_units(rhs._last_near_long_units),
+      _last_mid_lat_title(rhs._last_mid_lat_title),
+      _last_mid_lat(rhs._last_mid_lat),
+      _last_mid_lat_units(rhs._last_mid_lat_units),
+      _last_mid_long_title(rhs._last_mid_long_title),
+      _last_mid_long(rhs._last_mid_long),
+      _last_mid_long_units(rhs._last_mid_long_units),
+      _last_far_lat_title(rhs._last_far_lat_title),
+      _last_far_lat(rhs._last_far_lat),
+      _last_far_lat_units(rhs._last_far_lat_units),
+      _last_far_long_title(rhs._last_far_long_title),
+      _last_far_long(rhs._last_far_long),
+      _last_far_long_units(rhs._last_far_long_units),
+      _swath_title(rhs._swath_title),
+      _swath(rhs._swath),
+      _pass_title(rhs._pass_title),
+      _pass(rhs._pass),
+      _sample_type_title(rhs._sample_type_title),
+      _sample_type(rhs._sample_type),
+      _algo_title(rhs._algo_title),
+      _algorithm(rhs._algorithm),
+      _mds1_tx_rx_polar_title(rhs._mds1_tx_rx_polar_title),
+      _mds1_tx_rx_polar(rhs._mds1_tx_rx_polar),
+      _mds2_tx_rx_polar_title(rhs._mds2_tx_rx_polar_title),
+      _mds2_tx_rx_polar(rhs._mds2_tx_rx_polar),
+      _compression_title(rhs._compression_title),
+      _compression(rhs._compression),
+      _azimut_looks_title(rhs._azimut_looks_title),
+      _azimut_looks(rhs._azimut_looks),
+      _range_looks_title(rhs._range_looks_title),
+      _range_looks(rhs._range_looks),
+      _range_spacing_title(rhs._range_spacing_title),
+      _range_spacing(rhs._range_spacing),
+      _range_spacing_unit(rhs._range_spacing_unit),
+      _azimut_spacing_title(rhs._azimut_spacing_title),
+      _azimut_spacing(rhs._azimut_spacing),
+      _azimut_spacing_unit(rhs._azimut_spacing_unit),
+      _line_time_interval_title(rhs._line_time_interval_title),
+      _line_time_interval(rhs._line_time_interval),
+      _line_time_interv_units(rhs._line_time_interv_units),
+      _line_length_title(rhs._line_length_title),
+      _line_length(rhs._line_length),
+      _line_length_units(rhs._line_length_units),
+      _data_type_title(rhs._data_type_title),
+      _data_type(rhs._data_type)
+   {}
+
+
+   sph& sph::operator=(const sph& rhs)
+   {
+      _sph_desc_title = rhs._sph_desc_title;
+      _sph_desc = rhs._sph_desc;
+      _strip_cont_ind_title = rhs._strip_cont_ind_title;
+      _strip_cont_ind	= rhs._strip_cont_ind;
+      _slice_pos_title = rhs._slice_pos_title;
+      _slice_position = rhs._slice_position;
+      _num_slices_title = rhs._num_slices_title;
+      _num_slices = rhs._num_slices;
+      _first_line_time_title = rhs._first_line_time_title;
+      _first_line_time = rhs._first_line_time;
+      _last_line_time_title = rhs._last_line_time_title;
+      _last_line_time = rhs._last_line_time;
+      _first_near_lat_title = rhs._first_near_lat_title;
+      _first_near_lat = rhs._first_near_lat;
+      _first_near_lat_units = rhs._first_near_lat_units;
+      _first_near_long_title = rhs._first_near_long_title;
+      _first_near_long = rhs._first_near_long;
+      _first_near_long_units = rhs._first_near_long_units;
+      _first_mid_lat_title = rhs._first_mid_lat_title;
+      _first_mid_lat = rhs._first_mid_lat;
+      _first_mid_lat_units = rhs._first_mid_lat_units;
+      _first_mid_long_title = rhs._first_mid_long_title;
+      _first_mid_long = rhs._first_mid_long;
+      _first_mid_long_units = rhs._first_mid_long_units;
+      _first_far_lat_title = rhs._first_far_lat_title;
+      _first_far_lat = rhs._first_far_lat;
+      _first_far_lat_units = rhs._first_far_lat_units;
+      _first_far_long_title = rhs._first_far_long_title;
+      _first_far_long = rhs._first_far_long;
+      _first_far_long_units = rhs._first_far_long_units;
+      _last_near_lat_title = rhs._last_near_lat_title;
+      _last_near_lat = rhs._last_near_lat;
+      _last_near_lat_units = rhs._last_near_lat_units;
+      _last_near_long_title = rhs._last_near_long_title;
+      _last_near_long = rhs._last_near_long;
+      _last_near_long_units = rhs._last_near_long_units;
+      _last_mid_lat_title = rhs._last_mid_lat_title;
+      _last_mid_lat = rhs._last_mid_lat;
+      _last_mid_lat_units = rhs._last_mid_lat_units;
+      _last_mid_long_title = rhs._last_mid_long_title;
+      _last_mid_long = rhs._last_mid_long;
+      _last_mid_long_units = rhs._last_mid_long_units;
+      _last_far_lat_title = rhs._last_far_lat_title;
+      _last_far_lat = rhs._last_far_lat;
+      _last_far_lat_units = rhs._last_far_lat_units;
+      _last_far_long_title = rhs._last_far_long_title;
+      _last_far_long = rhs._last_far_long;
+      _last_far_long_units = rhs._last_far_long_units;
+      _swath_title = rhs._swath_title;
+      _swath = rhs._swath;
+      _pass_title = rhs._pass_title;
+      _pass = rhs._pass;
+      _sample_type_title = rhs._sample_type_title;
+      _sample_type = rhs._sample_type;
+      _algo_title = rhs._algo_title;
+      _algorithm = rhs._algorithm;
+      _mds1_tx_rx_polar_title = rhs._mds1_tx_rx_polar_title;
+      _mds1_tx_rx_polar = rhs._mds1_tx_rx_polar;
+      _mds2_tx_rx_polar_title = rhs._mds2_tx_rx_polar_title;
+      _mds2_tx_rx_polar = rhs._mds2_tx_rx_polar;
+      _compression_title = rhs._compression_title;
+      _compression = rhs._compression;
+      _azimut_looks_title = rhs._azimut_looks_title;
+      _azimut_looks = rhs._azimut_looks;
+      _range_looks_title = rhs._range_looks_title;
+      _range_looks = rhs._range_looks;
+      _range_spacing_title = rhs._range_spacing_title;
+      _range_spacing = rhs._range_spacing;
+      _range_spacing_unit = rhs._range_spacing_unit;
+      _azimut_spacing_title = rhs._azimut_spacing_title;
+      _azimut_spacing = rhs._azimut_spacing;
+      _azimut_spacing_unit = rhs._azimut_spacing_unit;
+      _line_time_interval_title = rhs._line_time_interval_title;
+      _line_time_interval = rhs._line_time_interval;
+      _line_time_interv_units = rhs._line_time_interv_units;
+      _line_length_title = rhs._line_length_title;
+      _line_length = rhs._line_length;
+      _line_length_units = rhs._line_length_units;
+      _data_type_title = rhs._data_type_title;
+      _data_type = rhs._data_type;
+
+      return *this;
+   }
+}
+
diff --git a/ossim_plugins/ossim/EnvisatAsar/sph.h b/ossim_plugins/ossim/EnvisatAsar/sph.h
new file mode 100644
index 0000000..5e8df26
--- /dev/null
+++ b/ossim_plugins/ossim/EnvisatAsar/sph.h
@@ -0,0 +1,1017 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef sph_h
+#define sph_h
+
+#include <iostream>
+#include <vector>
+#include <EnvisatAsar/EnvisatAsarRecord.h>
+#include <EnvisatAsar/mph.h>
+#include <EnvisatAsar/dsd.h>
+
+namespace ossimplugins
+{
+/**
+ * @ingroup sphRecord
+ * @brief This class is able to read the SAR sph record of the ASAR file
+ */
+class sph : public EnvisatAsarRecord
+{
+public:
+  /**
+   * @brief Constructor
+   */
+  sph();
+
+  /**
+   * @brief Constructor Using an mph record to initialize num_dsd and dsd_size
+   */
+  sph(const mph& data);
+  /**
+   * @brief Destructor
+   */
+  virtual ~sph();
+
+  /**
+   * @brief This function write the sph in a stream
+   */
+  friend std::ostream& operator<<(std::ostream& os, const sph& data);
+
+  /**
+   * @brief This function read a sph from a stream
+   */
+  friend std::istream& operator>>(std::istream& is, sph& data);
+
+  /**
+   * @brief Copy constructor
+   */
+  sph(const sph& rhs);
+
+  /**
+   * @brief Copy operator
+   */
+  sph& operator=(const sph& rhs);
+
+  /**
+   * @brief This function is able to create a new instance of the class
+   */
+  EnvisatAsarRecord* Instanciate()
+  {
+    return new sph();
+  };
+
+  /**
+   * @brief This function is able to create a new instance of the class initialised with the data of the calling instance
+   */
+  EnvisatAsarRecord* Clone()
+  {
+    return new sph(*this);
+  };
+
+  /**
+   * @brief Read the class data from a stream
+   */
+  void Read(std::istream& is)
+  {
+    is>>*this;
+  };
+
+  /**
+   * @brief Write the class to a stream
+   */
+  void Write(std::ostream& os)
+  {
+    os<<*this;
+  };
+
+  /**
+  * @brief sph_desc_title
+  */
+  std::string   get_sph_desc_title()
+  {
+    return _sph_desc_title;
+  };
+  /**
+  * @brief sph_desc
+  */
+  std::string   get_sph_desc()
+  {
+    return _sph_desc;
+  };
+  /**
+  * @brief strip_cont_ind_title
+  */
+  std::string   get_strip_cont_ind_title()
+  {
+    return _strip_cont_ind_title;
+  };
+  /**
+  * @brief strip_cont_ind
+  */
+  std::string   get_strip_cont_ind()
+  {
+    return _strip_cont_ind;
+  };
+  /**
+  * @brief slice_pos_title
+  */
+  std::string   get_slice_pos_title()
+  {
+    return _slice_pos_title;
+  };
+  /**
+  * @brief slice_position
+  */
+  std::string   get_slice_position()
+  {
+    return _slice_position;
+  };
+  /**
+  * @brief num_slices_title
+  */
+  std::string   get_num_slices_title()
+  {
+    return _num_slices_title;
+  };
+  /**
+  * @brief num_slices
+  */
+  std::string   get_num_slices()
+  {
+    return _num_slices;
+  };
+  /**
+  * @brief first_line_time_title
+  */
+  std::string   get_first_line_time_title()
+  {
+    return _first_line_time_title;
+  };
+  /**
+  * @brief first_line_time
+  */
+  std::string   get_first_line_time()
+  {
+    return _first_line_time;
+  };
+  /**
+  * @brief last_line_time_title
+  */
+  std::string   get_last_line_time_title()
+  {
+    return _last_line_time_title;
+  };
+  /**
+  * @brief last_line_time
+  */
+  std::string   get_last_line_time()
+  {
+    return _last_line_time;
+  };
+  /**
+  * @brief first_near_lat_title
+  */
+  std::string   get_first_near_lat_title()
+  {
+    return _first_near_lat_title;
+  };
+  /**
+  * @brief first_near_lat
+  */
+  std::string   get_first_near_lat()
+  {
+    return _first_near_lat;
+  };
+  /**
+  * @brief first_near_lat_units
+  */
+  std::string   get_first_near_lat_units()
+  {
+    return _first_near_lat_units;
+  };
+  /**
+  * @brief first_near_long_title
+  */
+  std::string   get_first_near_long_title()
+  {
+    return _first_near_long_title;
+  };
+  /**
+  * @brief first_near_long
+  */
+  std::string   get_first_near_long()
+  {
+    return _first_near_long;
+  };
+  /**
+  * @brief first_near_long_units
+  */
+  std::string   get_first_near_long_units()
+  {
+    return _first_near_long_units;
+  };
+  /**
+  * @brief first_mid_lat_title
+  */
+  std::string   get_first_mid_lat_title()
+  {
+    return _first_mid_lat_title;
+  };
+  /**
+  * @brief first_mid_lat
+  */
+  std::string   get_first_mid_lat()
+  {
+    return _first_mid_lat;
+  };
+  /**
+  * @brief first_mid_lat_units
+  */
+  std::string   get_first_mid_lat_units()
+  {
+    return _first_mid_lat_units;
+  };
+  /**
+  * @brief first_mid_long_title
+  */
+  std::string   get_first_mid_long_title()
+  {
+    return _first_mid_long_title;
+  };
+  /**
+  * @brief first_mid_long
+  */
+  std::string   get_first_mid_long()
+  {
+    return _first_mid_long;
+  };
+  /**
+  * @brief first_mid_long_units
+  */
+  std::string   get_first_mid_long_units()
+  {
+    return _first_mid_long_units;
+  };
+  /**
+  * @brief first_far_lat_title
+  */
+  std::string   get_first_far_lat_title()
+  {
+    return _first_far_lat_title;
+  };
+  /**
+  * @brief first_far_lat
+  */
+  std::string   get_first_far_lat()
+  {
+    return _first_far_lat;
+  };
+  /**
+  * @brief first_far_lat_units
+  */
+  std::string   get_first_far_lat_units()
+  {
+    return _first_far_lat_units;
+  };
+  /**
+  * @brief first_far_long_title
+  */
+  std::string   get_first_far_long_title()
+  {
+    return _first_far_long_title;
+  };
+  /**
+  * @brief first_far_long
+  */
+  std::string   get_first_far_long()
+  {
+    return _first_far_long;
+  };
+  /**
+  * @brief first_far_long_units
+  */
+  std::string   get_first_far_long_units()
+  {
+    return _first_far_long_units;
+  };
+  /**
+  * @brief last_near_lat_title
+  */
+  std::string   get_last_near_lat_title()
+  {
+    return _last_near_lat_title;
+  };
+  /**
+  * @brief last_near_lat
+  */
+  std::string   get_last_near_lat()
+  {
+    return _last_near_lat;
+  };
+  /**
+  * @brief last_near_lat_units
+  */
+  std::string   get_last_near_lat_units()
+  {
+    return _last_near_lat_units;
+  };
+  /**
+  * @brief last_near_long_title
+  */
+  std::string   get_last_near_long_title()
+  {
+    return _last_near_long_title;
+  };
+  /**
+  * @brief last_near_long
+  */
+  std::string   get_last_near_long()
+  {
+    return _last_near_long;
+  };
+  /**
+  * @brief last_near_long_units
+  */
+  std::string   get_last_near_long_units()
+  {
+    return _last_near_long_units;
+  };
+  /**
+  * @brief last_mid_lat_title
+  */
+  std::string   get_last_mid_lat_title()
+  {
+    return _last_mid_lat_title;
+  };
+  /**
+  * @brief last_mid_lat
+  */
+  std::string   get_last_mid_lat()
+  {
+    return _last_mid_lat;
+  };
+  /**
+  * @brief last_mid_lat_units
+  */
+  std::string   get_last_mid_lat_units()
+  {
+    return _last_mid_lat_units;
+  };
+  /**
+  * @brief last_mid_long_title
+  */
+  std::string   get_last_mid_long_title()
+  {
+    return _last_mid_long_title;
+  };
+  /**
+  * @brief last_mid_long
+  */
+  std::string   get_last_mid_long()
+  {
+    return _last_mid_long;
+  };
+  /**
+  * @brief last_mid_long_units
+  */
+  std::string   get_last_mid_long_units()
+  {
+    return _last_mid_long_units;
+  };
+  /**
+  * @brief last_far_lat_title
+  */
+  std::string   get_last_far_lat_title()
+  {
+    return _last_far_lat_title;
+  };
+  /**
+  * @brief last_far_lat
+  */
+  std::string   get_last_far_lat()
+  {
+    return _last_far_lat;
+  };
+  /**
+  * @brief last_far_lat_units
+  */
+  std::string   get_last_far_lat_units()
+  {
+    return _last_far_lat_units;
+  };
+  /**
+  * @brief last_far_long_title
+  */
+  std::string   get_last_far_long_title()
+  {
+    return _last_far_long_title;
+  };
+  /**
+  * @brief last_far_long
+  */
+  std::string   get_last_far_long()
+  {
+    return _last_far_long;
+  };
+  /**
+  * @brief last_far_long_units
+  */
+  std::string   get_last_far_long_units()
+  {
+    return _last_far_long_units;
+  };
+  /**
+  * @brief swath_title
+  */
+  std::string   get_swath_title()
+  {
+    return _swath_title;
+  };
+  /**
+  * @brief swath
+  */
+  std::string   get_swath()
+  {
+    return _swath;
+  };
+  /**
+  * @brief pass_title
+  */
+  std::string   get_pass_title()
+  {
+    return _pass_title;
+  };
+  /**
+  * @brief pass
+  */
+  std::string   get_pass()
+  {
+    return _pass;
+  };
+  /**
+  * @brief sample_type_title
+  */
+  std::string   get_sample_type_title()
+  {
+    return _sample_type_title;
+  };
+  /**
+  * @brief sample_type
+  */
+  std::string   get_sample_type()
+  {
+    return _sample_type;
+  };
+  /**
+  * @brief algo_title
+  */
+  std::string   get_algo_title()
+  {
+    return _algo_title;
+  };
+  /**
+  * @brief algorithm
+  */
+  std::string   get_algorithm()
+  {
+    return _algorithm;
+  };
+  /**
+  * @brief mds1_tx_rx_polar_title
+  */
+  std::string   get_mds1_tx_rx_polar_title()
+  {
+    return _mds1_tx_rx_polar_title;
+  };
+  /**
+  * @brief mds1_tx_rx_polar
+  */
+  std::string   get_mds1_tx_rx_polar()
+  {
+    return _mds1_tx_rx_polar;
+  };
+  /**
+  * @brief mds2_tx_rx_polar_title
+  */
+  std::string   get_mds2_tx_rx_polar_title()
+  {
+    return _mds2_tx_rx_polar_title;
+  };
+  /**
+  * @brief mds2_tx_rx_polar
+  */
+  std::string   get_mds2_tx_rx_polar()
+  {
+    return _mds2_tx_rx_polar;
+  };
+  /**
+  * @brief compression_title
+  */
+  std::string   get_compression_title()
+  {
+    return _compression_title;
+  };
+  /**
+  * @brief compression
+  */
+  std::string   get_compression()
+  {
+    return _compression;
+  };
+  /**
+  * @brief azimut_looks_title
+  */
+  std::string   get_azimut_looks_title()
+  {
+    return _azimut_looks_title;
+  };
+  /**
+  * @brief azimut_looks
+  */
+  std::string   get_azimut_looks()
+  {
+    return _azimut_looks;
+  };
+  /**
+  * @brief range_looks_title
+  */
+  std::string   get_range_looks_title()
+  {
+    return _range_looks_title;
+  };
+  /**
+  * @brief range_looks
+  */
+  std::string   get_range_looks()
+  {
+    return _range_looks;
+  };
+  /**
+  * @brief range_spacing_title
+  */
+  std::string   get_range_spacing_title()
+  {
+    return _range_spacing_title;
+  };
+  /**
+  * @brief range_spacing
+  */
+  std::string   get_range_spacing()
+  {
+    return _range_spacing;
+  };
+  /**
+  * @brief range_spacing_unit
+  */
+  std::string   get_range_spacing_unit()
+  {
+    return _range_spacing_unit;
+  };
+  /**
+  * @brief azimut_spacing_title
+  */
+  std::string   get_azimut_spacing_title()
+  {
+    return _azimut_spacing_title;
+  };
+  /**
+  * @brief azimut_spacing
+  */
+  std::string   get_azimut_spacing()
+  {
+    return _azimut_spacing;
+  };
+  /**
+  * @brief azimut_spacing_unit
+  */
+  std::string   get_azimut_spacing_unit()
+  {
+    return _azimut_spacing_unit;
+  };
+  /**
+  * @brief line_time_interval_title
+  */
+  std::string   get_line_time_interval_title()
+  {
+    return _line_time_interval_title;
+  };
+  /**
+  * @brief line_time_interval
+  */
+  std::string   get_line_time_interval()
+  {
+    return _line_time_interval;
+  };
+  /**
+  * @brief line_time_interv_units
+  */
+  std::string   get_line_time_interv_units()
+  {
+    return _line_time_interv_units;
+  };
+  /**
+  * @brief line_length_title
+  */
+  std::string   get_line_length_title()
+  {
+    return _line_length_title;
+  };
+  /**
+  * @brief line_length
+  */
+  std::string   get_line_length()
+  {
+    return _line_length;
+  };
+  /**
+  * @brief line_length_units
+  */
+  std::string   get_line_length_units()
+  {
+    return _line_length_units;
+  };
+  /**
+  * @brief data_type_title
+  */
+  std::string   get_data_type_title()
+  {
+    return _data_type_title;
+  };
+  /**
+  * @brief data_type
+  */
+  std::string   get_data_type()
+  {
+    return _data_type;
+  };
+  /**
+  * @brief data_type
+  */
+  std::vector<dsd>  get_dsd_vector()
+  {
+    return _dsd_vector;
+  }
+
+    /**
+  * @brief update DSD number and dsd size from a mph record
+  */
+  bool  update_sph_from_mph( mph& mph_rec)
+  {
+    _num_dsd = mph_rec._num_dsd;
+    _size_dsd = mph_rec._dsd_size;
+
+    return 1;
+  };
+
+
+protected:
+  /**
+  * @brief Number of Data Set Descriptors (DSD)
+  */
+  long   _num_dsd;
+
+  /**
+  * @brief Size of each Data Set Descriptors (DSD)
+  */
+  long   _size_dsd;
+
+  /**
+  * @brief sph_desc_title
+  */
+  std::string   _sph_desc_title;
+  /**
+  * @brief sph_desc
+  */
+  std::string   _sph_desc;
+  /**
+  * @brief strip_cont_ind_title
+  */
+  std::string   _strip_cont_ind_title;
+  /**
+  * @brief strip_cont_ind
+  */
+  std::string   _strip_cont_ind;
+  /**
+  * @brief slice_pos_title
+  */
+  std::string   _slice_pos_title;
+  /**
+  * @brief slice_position
+  */
+  std::string   _slice_position;
+  /**
+  * @brief num_slices_title
+  */
+  std::string   _num_slices_title;
+  /**
+  * @brief num_slices
+  */
+  std::string   _num_slices;
+  /**
+  * @brief first_line_time_title
+  */
+  std::string   _first_line_time_title;
+  /**
+  * @brief first_line_time
+  */
+  std::string   _first_line_time;
+  /**
+  * @brief last_line_time_title
+  */
+  std::string   _last_line_time_title;
+  /**
+  * @brief last_line_time
+  */
+  std::string   _last_line_time;
+  /**
+  * @brief first_near_lat_title
+  */
+  std::string   _first_near_lat_title;
+  /**
+  * @brief first_near_lat
+  */
+  std::string   _first_near_lat;
+  /**
+  * @brief first_near_lat_units
+  */
+  std::string   _first_near_lat_units;
+  /**
+  * @brief first_near_long_title
+  */
+  std::string   _first_near_long_title;
+  /**
+  * @brief first_near_long
+  */
+  std::string   _first_near_long;
+  /**
+  * @brief first_near_long_units
+  */
+  std::string   _first_near_long_units;
+  /**
+  * @brief first_mid_lat_title
+  */
+  std::string   _first_mid_lat_title;
+  /**
+  * @brief first_mid_lat
+  */
+  std::string   _first_mid_lat;
+  /**
+  * @brief first_mid_lat_units
+  */
+  std::string   _first_mid_lat_units;
+  /**
+  * @brief first_mid_long_title
+  */
+  std::string   _first_mid_long_title;
+  /**
+  * @brief first_mid_long
+  */
+  std::string   _first_mid_long;
+  /**
+  * @brief first_mid_long_units
+  */
+  std::string   _first_mid_long_units;
+  /**
+  * @brief first_far_lat_title
+  */
+  std::string   _first_far_lat_title;
+  /**
+  * @brief first_far_lat
+  */
+  std::string   _first_far_lat;
+  /**
+  * @brief first_far_lat_units
+  */
+  std::string   _first_far_lat_units;
+  /**
+  * @brief first_far_long_title
+  */
+  std::string   _first_far_long_title;
+  /**
+  * @brief first_far_long
+  */
+  std::string   _first_far_long;
+  /**
+  * @brief first_far_long_units
+  */
+  std::string   _first_far_long_units;
+  /**
+  * @brief last_near_lat_title
+  */
+  std::string   _last_near_lat_title;
+  /**
+  * @brief last_near_lat
+  */
+  std::string   _last_near_lat;
+  /**
+  * @brief last_near_lat_units
+  */
+  std::string   _last_near_lat_units;
+  /**
+  * @brief last_near_long_title
+  */
+  std::string   _last_near_long_title;
+  /**
+  * @brief last_near_long
+  */
+  std::string   _last_near_long;
+  /**
+  * @brief last_near_long_units
+  */
+  std::string   _last_near_long_units;
+  /**
+  * @brief last_mid_lat_title
+  */
+  std::string   _last_mid_lat_title;
+  /**
+  * @brief last_mid_lat
+  */
+  std::string   _last_mid_lat;
+  /**
+  * @brief last_mid_lat_units
+  */
+  std::string   _last_mid_lat_units;
+  /**
+  * @brief last_mid_long_title
+  */
+  std::string   _last_mid_long_title;
+  /**
+  * @brief last_mid_long
+  */
+  std::string   _last_mid_long;
+  /**
+  * @brief last_mid_long_units
+  */
+  std::string   _last_mid_long_units;
+  /**
+  * @brief last_far_lat_title
+  */
+  std::string   _last_far_lat_title;
+  /**
+  * @brief last_far_lat
+  */
+  std::string   _last_far_lat;
+  /**
+  * @brief last_far_lat_units
+  */
+  std::string   _last_far_lat_units;
+  /**
+  * @brief last_far_long_title
+  */
+  std::string   _last_far_long_title;
+  /**
+  * @brief last_far_long
+  */
+  std::string   _last_far_long;
+  /**
+  * @brief last_far_long_units
+  */
+  std::string   _last_far_long_units;
+  /**
+  * @brief swath_title
+  */
+  std::string   _swath_title;
+  /**
+  * @brief swath
+  */
+  std::string   _swath;
+  /**
+  * @brief pass_title
+  */
+  std::string   _pass_title;
+  /**
+  * @brief pass
+  */
+  std::string   _pass;
+  /**
+  * @brief sample_type_title
+  */
+  std::string   _sample_type_title;
+  /**
+  * @brief sample_type
+  */
+  std::string   _sample_type;
+  /**
+  * @brief algo_title
+  */
+  std::string   _algo_title;
+  /**
+  * @brief algorithm
+  */
+  std::string   _algorithm;
+  /**
+  * @brief mds1_tx_rx_polar_title
+  */
+  std::string   _mds1_tx_rx_polar_title;
+  /**
+  * @brief mds1_tx_rx_polar
+  */
+  std::string   _mds1_tx_rx_polar;
+  /**
+  * @brief mds2_tx_rx_polar_title
+  */
+  std::string   _mds2_tx_rx_polar_title;
+  /**
+  * @brief mds2_tx_rx_polar
+  */
+  std::string   _mds2_tx_rx_polar;
+  /**
+  * @brief compression_title
+  */
+  std::string   _compression_title;
+  /**
+  * @brief compression
+  */
+  std::string   _compression;
+  /**
+  * @brief azimut_looks_title
+  */
+  std::string   _azimut_looks_title;
+  /**
+  * @brief azimut_looks
+  */
+  std::string   _azimut_looks;
+  /**
+  * @brief range_looks_title
+  */
+  std::string   _range_looks_title;
+  /**
+  * @brief range_looks
+  */
+  std::string   _range_looks;
+  /**
+  * @brief range_spacing_title
+  */
+  std::string   _range_spacing_title;
+  /**
+  * @brief range_spacing
+  */
+  std::string   _range_spacing;
+  /**
+  * @brief range_spacing_unit
+  */
+  std::string   _range_spacing_unit;
+  /**
+  * @brief azimut_spacing_title
+  */
+  std::string   _azimut_spacing_title;
+  /**
+  * @brief azimut_spacing
+  */
+  std::string   _azimut_spacing;
+  /**
+  * @brief azimut_spacing_unit
+  */
+  std::string   _azimut_spacing_unit;
+  /**
+  * @brief line_time_interval_title
+  */
+  std::string   _line_time_interval_title;
+  /**
+  * @brief line_time_interval
+  */
+  std::string   _line_time_interval;
+  /**
+  * @brief line_time_interv_units
+  */
+  std::string   _line_time_interv_units;
+  /**
+  * @brief line_length_title
+  */
+  std::string   _line_length_title;
+  /**
+  * @brief line_length
+  */
+  std::string   _line_length;
+  /**
+  * @brief line_length_units
+  */
+  std::string   _line_length_units;
+  /**
+  * @brief data_type_title
+  */
+  std::string   _data_type_title;
+  /**
+  * @brief data_type
+  */
+  std::string   _data_type;
+    /**
+  * @brief DSD records
+  */
+  std::vector<dsd>  _dsd_vector;
+
+private:
+
+};
+}
+#endif
+
diff --git a/ossim_plugins/ossim/RadarSat/CommonRecord/AttitudeData.cpp b/ossim_plugins/ossim/RadarSat/CommonRecord/AttitudeData.cpp
new file mode 100755
index 0000000..1e26ec7
--- /dev/null
+++ b/ossim_plugins/ossim/RadarSat/CommonRecord/AttitudeData.cpp
@@ -0,0 +1,95 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+
+#include "AttitudeData.h"
+
+namespace ossimplugins
+{
+
+AttitudeData::AttitudeData() : RadarSatRecord("att_data_rec")
+{
+}
+
+AttitudeData::~AttitudeData()
+{
+}
+
+std::ostream& operator<<(std::ostream& os, const AttitudeData& data)
+{
+	os<<"npoint:"<<data._npoint<<std::endl;
+	for (int i=0;i<20;i++)
+	{
+		os<<"att_vect["<<i<<"]:"<<data._att_vect[i]<<std::endl;
+	}
+    os<<"pitch_bias:"<<data._pitch_bias<<std::endl;
+    os<<"roll_bias:"<<data._roll_bias<<std::endl;
+    os<<"yaw_bias:"<<data._yaw_bias<<std::endl;
+	return os;
+}
+
+std::istream& operator>>(std::istream& is, AttitudeData& data)
+{
+	char buf[6503];
+	buf[6502] = '\0';
+
+	is.read(buf,4);
+	buf[4] = '\0';
+	data._npoint = atoi(buf);
+
+	for (int i=0;i<20;i++)
+	{
+		is>>data._att_vect[i];
+	}
+    is.read(buf,14);
+	buf[14] = '\0';
+	data._pitch_bias = atof(buf);
+
+    is.read(buf,14);
+	buf[14] = '\0';
+	data._roll_bias = atof(buf);
+
+    is.read(buf,14);
+	buf[14] = '\0';
+	data._yaw_bias = atof(buf);
+
+	is.read(buf,6502);
+
+	return is;
+}
+
+AttitudeData::AttitudeData(const AttitudeData& rhs):
+	RadarSatRecord(rhs)
+{
+	_npoint = rhs._npoint;
+	for (int i=0;i<20;i++)
+	{
+		_att_vect[i] = rhs._att_vect[i];
+	}
+    _pitch_bias = rhs._pitch_bias;
+    _roll_bias = rhs._roll_bias;
+    _yaw_bias = rhs._yaw_bias;
+}
+
+AttitudeData& AttitudeData::operator=(const AttitudeData& rhs)
+{
+	_npoint = rhs._npoint;
+	for (int i=0;i<20;i++)
+	{
+		_att_vect[i] = rhs._att_vect[i];
+	}
+    _pitch_bias = rhs._pitch_bias;
+    _roll_bias = rhs._roll_bias;
+    _yaw_bias = rhs._yaw_bias;
+	return *this;
+}
+}
+
diff --git a/ossim_plugins/ossim/RadarSat/CommonRecord/AttitudeData.h b/ossim_plugins/ossim/RadarSat/CommonRecord/AttitudeData.h
new file mode 100755
index 0000000..2f00a59
--- /dev/null
+++ b/ossim_plugins/ossim/RadarSat/CommonRecord/AttitudeData.h
@@ -0,0 +1,156 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef AttitudeData_h
+#define AttitudeData_h
+
+#include <iostream>
+
+#include <RadarSat/RadarSatRecord.h>
+#include <RadarSat/RadarSatRecordHeader.h>
+
+#include "DataPointDataRecord.h"
+
+namespace ossimplugins
+{
+/**
+ * @ingroup AttitudeDataRecord
+ * @brief This class is able to read a Attitude data record
+ */
+class AttitudeData : public RadarSatRecord
+{
+public:
+  /**
+   * @brief Constructor
+   */
+  AttitudeData();
+
+  /**
+   * @brief Destructor
+   */
+  ~AttitudeData();
+
+  /**
+   * @brief Copy constructor
+   */
+  AttitudeData(const AttitudeData& rhs);
+
+  /**
+   * @brief Copy operator
+   */
+  AttitudeData& operator=(const AttitudeData& rhs);
+  /**
+   * @brief This function writes the AttitudeData in a stream
+   */
+  friend std::ostream& operator<<(std::ostream& os, const AttitudeData& data);
+
+  /**
+   * @brief This function reads a AttitudeData from a stream
+   */
+  friend std::istream& operator>>(std::istream& is, AttitudeData& data);
+
+  /**
+   * @brief This function is able to create a new instance of the class
+   */
+  RadarSatRecord* Instanciate()
+  {
+    return new AttitudeData();
+  };
+
+  /**
+   * @brief This function is able to create a new instance of the class initialised with the data of the calling instance
+   */
+  RadarSatRecord* Clone()
+  {
+    return new AttitudeData(*this);
+  };
+
+  /**
+   * @brief Reads the class data from a stream
+   */
+  void Read(std::istream& is)
+  {
+    is>>*this;
+  };
+
+  /**
+   * @brief Writes the class to a stream
+   */
+  void Write(std::ostream& os)
+  {
+    os<<*this;
+  };
+
+  /**
+   * @brief Number of data points
+   */
+  int   get_npoint()
+  {
+    return _npoint;
+  };
+    /**
+   * @brief Data points
+   */
+  DataPointDataRecord* get_att_vect()
+  {
+    return _att_vect;
+  };
+    /**
+   * @brief Pitch bias (degrees)
+   */
+  double   get_pitch_bias()
+  {
+    return _pitch_bias;
+  };
+    /**
+   * @brief Roll bias (degrees)
+   */
+  double   get_roll_bias()
+  {
+    return _roll_bias;
+  };
+    /**
+   * @brief Yaw bias (degrees)
+   */
+  double   get_yaw_bias()
+  {
+    return _yaw_bias;
+  };
+
+
+protected:
+  /**
+   * @brief Number of data points
+   */
+  int   _npoint;
+    /**
+   * @brief Data points
+   */
+  DataPointDataRecord _att_vect[20];
+    /**
+   * @brief Pitch bias (degrees)
+   */
+  double   _pitch_bias;
+    /**
+   * @brief Roll bias (degrees)
+   */
+  double   _roll_bias;
+    /**
+   * @brief Yaw bias (degrees)
+   */
+  double   _yaw_bias;
+
+
+private:
+};
+}
+#endif
+
diff --git a/ossim_plugins/ossim/RadarSat/CommonRecord/BeamInformationRecord.cpp b/ossim_plugins/ossim/RadarSat/CommonRecord/BeamInformationRecord.cpp
new file mode 100755
index 0000000..d2feee2
--- /dev/null
+++ b/ossim_plugins/ossim/RadarSat/CommonRecord/BeamInformationRecord.cpp
@@ -0,0 +1,79 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include "BeamInformationRecord.h"
+
+namespace ossimplugins
+{
+BeamInformationRecord::BeamInformationRecord()
+{
+}
+
+BeamInformationRecord::~BeamInformationRecord()
+{
+}
+
+std::ostream& operator<<(std::ostream& os, const BeamInformationRecord& data)
+{
+	os<<"beam_type:"<<data._beam_type.c_str()<<std::endl;
+
+	os<<"beam_look_src:"<<data._beam_look_src.c_str()<<std::endl;
+
+    os<<"beam_look_ang:"<<data._beam_look_ang<<std::endl;
+
+	os<<"prf:"<<data._prf<<std::endl;
+
+	return os;
+}
+
+std::istream& operator>>(std::istream& is, BeamInformationRecord& data)
+{
+	char buf[17];
+	buf[16] = '\0';
+
+	is.read(buf,3);
+	buf[3] = '\0';
+	data._beam_type = buf;
+
+	is.read(buf,9);
+	buf[9] = '\0';
+	data._beam_look_src = buf;
+
+    is.read(buf,16);
+	buf[16] = '\0';
+	data._beam_look_ang = atof(buf);
+
+	is.read(buf,16);
+	buf[16] = '\0';
+	data._prf = atof(buf);
+
+	return is;
+}
+
+BeamInformationRecord::BeamInformationRecord(const BeamInformationRecord& rhs):
+	_beam_type(rhs._beam_type),
+	_beam_look_src(rhs._beam_look_src),
+	_beam_look_ang(rhs._beam_look_ang),
+	_prf(rhs._prf)
+{
+
+}
+
+BeamInformationRecord& BeamInformationRecord::operator=(const BeamInformationRecord& rhs)
+{
+	_beam_type = rhs._beam_type;
+	_beam_look_src = rhs._beam_look_src;
+	_beam_look_ang = rhs._beam_look_ang;
+	_prf = rhs._prf;
+	return *this;
+}
+}
+
diff --git a/ossim_plugins/ossim/RadarSat/CommonRecord/BeamInformationRecord.h b/ossim_plugins/ossim/RadarSat/CommonRecord/BeamInformationRecord.h
new file mode 100755
index 0000000..52adf79
--- /dev/null
+++ b/ossim_plugins/ossim/RadarSat/CommonRecord/BeamInformationRecord.h
@@ -0,0 +1,115 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef BeamInformationRecord_h
+#define BeamInformationRecord_h
+
+#include <iostream>
+
+#include <RadarSat/RadarSatRecord.h>
+
+namespace ossimplugins
+{
+/**
+ * @ingroup ProcessingParametersRecord
+ * @brief This class is able to read a Beam information record
+ */
+class BeamInformationRecord
+{
+public:
+  /**
+   * @brief Constructor
+   */
+  BeamInformationRecord();
+
+  /**
+   * @brief Destructor
+   */
+  ~BeamInformationRecord();
+
+  /**
+   * @brief Copy constructor
+   */
+  BeamInformationRecord(const BeamInformationRecord& rhs);
+
+  /**
+   * @brief Copy operator
+   */
+  BeamInformationRecord& operator=(const BeamInformationRecord& rhs);
+
+  /**
+   * @brief This function writes the BeamInformationRecord in a stream
+   */
+  friend std::ostream& operator<<(std::ostream& os, const BeamInformationRecord& data);
+
+  /**
+   * @brief This function reads a BeamInformationRecord from a stream
+   */
+  friend std::istream& operator>>(std::istream& is, BeamInformationRecord& data);
+
+  /**
+   * @brief Beam type
+   */
+  std::string   get_beam_type()
+  {
+    return _beam_type;
+  };
+
+  /**
+   * @brief Elevation beam look angle source
+   */
+  std::string   get_beam_look_src()
+  {
+    return _beam_look_src;
+  };
+
+    /**
+   * @brief Applied elevation beam look angle (deg)
+   */
+  double   get_beam_look_ang()
+  {
+    return _beam_look_ang;
+  };
+
+  /**
+   * @brief Actual PRF (Hz)
+   */
+  double   get_prf()
+  {
+    return _prf;
+  };
+protected:
+
+  /**
+   * @brief Beam type
+   */
+  std::string  _beam_type;
+
+  /**
+   * @brief Elevation beam look angle source
+   */
+  std::string  _beam_look_src;
+
+    /**
+   * @brief Applied elevation beam look angle (deg)
+   */
+  double   _beam_look_ang;
+
+  /**
+   * @brief Actual PRF (Hz)
+   */
+  double   _prf;
+private:
+
+};
+}
+#endif
+
diff --git a/ossim_plugins/ossim/RadarSat/CommonRecord/BeamPixelCountRecord.cpp b/ossim_plugins/ossim/RadarSat/CommonRecord/BeamPixelCountRecord.cpp
new file mode 100755
index 0000000..af16d89
--- /dev/null
+++ b/ossim_plugins/ossim/RadarSat/CommonRecord/BeamPixelCountRecord.cpp
@@ -0,0 +1,71 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include "BeamPixelCountRecord.h"
+
+namespace ossimplugins
+{
+BeamPixelCountRecord::BeamPixelCountRecord()
+{
+}
+
+BeamPixelCountRecord::~BeamPixelCountRecord()
+{
+}
+
+std::ostream& operator<<(std::ostream& os, const BeamPixelCountRecord& data)
+{
+	os<<"pix_update:"<<data._pix_update.c_str()<<std::endl;
+
+	for (int i=0;i<4;i++)
+	{
+		os<<"crt_m["<<i<<":"<<data._n_pix[i]<<std::endl;
+	}
+	return os;
+}
+
+std::istream& operator>>(std::istream& is, BeamPixelCountRecord& data)
+{
+	char buf[23];
+	buf[22] = '\0';
+
+	is.read(buf,21);
+	data._pix_update = buf;
+
+	for (int i=0;i<4;i++)
+	{
+		is.read(buf,8);
+		buf[8] = '\0';
+		data._n_pix[i] = atoi(buf);
+	}
+	return is;
+}
+
+BeamPixelCountRecord::BeamPixelCountRecord(const BeamPixelCountRecord& rhs):
+	_pix_update(rhs._pix_update)
+{
+	for (int i=0;i<4;i++)
+	{
+		_n_pix[i] = rhs._n_pix[i];
+	}
+}
+
+BeamPixelCountRecord& BeamPixelCountRecord::operator=(const BeamPixelCountRecord& rhs)
+{
+	_pix_update = rhs._pix_update;
+	for (int i=0;i<4;i++)
+	{
+		_n_pix[i] = rhs._n_pix[i];
+	}
+	return *this;
+}
+}
+
diff --git a/ossim_plugins/ossim/RadarSat/CommonRecord/BeamPixelCountRecord.h b/ossim_plugins/ossim/RadarSat/CommonRecord/BeamPixelCountRecord.h
new file mode 100755
index 0000000..2f9e34a
--- /dev/null
+++ b/ossim_plugins/ossim/RadarSat/CommonRecord/BeamPixelCountRecord.h
@@ -0,0 +1,88 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef BeamPixelCountRecord_h
+#define BeamPixelCountRecord_h
+
+#include <iostream>
+
+#include <RadarSat/RadarSatRecord.h>
+
+namespace ossimplugins
+{
+/**
+ * @ingroup ProcessingParametersRecord
+ * @brief This class is able to read a Beam pixel count record
+ */
+class BeamPixelCountRecord
+{
+public:
+  /**
+   * @brief Constructor
+   */
+  BeamPixelCountRecord();
+
+  /**
+   * @brief Destructor
+   */
+  ~BeamPixelCountRecord();
+
+  /**
+   * @brief Copy constructor
+   */
+  BeamPixelCountRecord(const BeamPixelCountRecord& rhs);
+
+  /**
+   * @brief Copy operator
+   */
+  BeamPixelCountRecord& operator=(const BeamPixelCountRecord& rhs);
+
+  /**
+   * @brief This function writes the BeamPixelCountRecord in a stream
+   */
+  friend std::ostream& operator<<(std::ostream& os, const BeamPixelCountRecord& data);
+
+  /**
+   * @brief This function reads a BeamPixelCountRecord from a stream
+   */
+  friend std::istream& operator>>(std::istream& is, BeamPixelCountRecord& data);
+
+  /**
+   * @brief Pixel count update date/time
+   */
+  std::string   get_pix_update()
+  {
+    return _pix_update;
+  };
+
+    /**
+   * @brief Count of image pixels in beams
+   */
+  int*   get_n_pix()
+  {
+    return _n_pix;
+  };
+protected:
+
+  /**
+   * @brief Pixel count update date/time
+   */
+  std::string  _pix_update;
+    /**
+   * @brief Count of image pixels in beams
+   */
+  int   _n_pix[4];
+private:
+
+};
+}
+#endif
+
diff --git a/ossim_plugins/ossim/RadarSat/CommonRecord/CompensationDataRecord.cpp b/ossim_plugins/ossim/RadarSat/CommonRecord/CompensationDataRecord.cpp
new file mode 100755
index 0000000..37ef2b2
--- /dev/null
+++ b/ossim_plugins/ossim/RadarSat/CommonRecord/CompensationDataRecord.cpp
@@ -0,0 +1,147 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include "CompensationDataRecord.h"
+
+namespace ossimplugins
+{
+CompensationDataRecord::CompensationDataRecord()
+{
+}
+
+CompensationDataRecord::~CompensationDataRecord()
+{
+}
+
+std::ostream& operator<<(std::ostream& os, const CompensationDataRecord& data)
+{
+	os<<"comp_desig:"<<data._comp_desig.c_str()<<std::endl;
+
+	os<<"comp_descr:"<<data._comp_descr.c_str()<<std::endl;
+
+    os<<"n_comp_rec:"<<data._n_comp_rec<<std::endl;
+
+    os<<"comp_seq_no:"<<data._comp_seq_no<<std::endl;
+
+    os<<"beam_tab_size:"<<data._beam_tab_size<<std::endl;
+
+	for (int i=0;i<256;i++)
+	{
+		os<<"beam_tab["<<i<<"]:"<<data._beam_tab[i]<<std::endl;
+	}
+
+    os<<"beam_type:"<<data._beam_type.c_str()<<std::endl;
+
+    os<<"look_angle:"<<data._look_angle<<std::endl;
+
+    os<<"beam_tab_inc:"<<data._beam_tab_inc<<std::endl;
+	return os;
+}
+
+std::istream& operator>>(std::istream& is, CompensationDataRecord& data)
+{
+	char buf[33];
+	buf[32] = '\0';
+
+
+	is.read(buf,8);
+	buf[8] = '\0';
+	data._comp_desig = buf;
+
+	is.read(buf,32);
+	buf[32] = '\0';
+	data._comp_descr = buf;
+
+    is.read(buf,4);
+	buf[4] = '\0';
+	data._n_comp_rec = atoi(buf);
+
+    is.read(buf,4);
+	buf[4] = '\0';
+	data._comp_seq_no = atoi(buf);
+
+    is.read(buf,8);
+	buf[8] = '\0';
+	data._beam_tab_size = atoi(buf);
+
+	for (int i=0;i<256;i++)
+	{
+		is.read(buf,16);
+		buf[16] = '\0';
+		data._beam_tab[i] = atof(buf);
+	}
+
+    is.read(buf,16);
+	buf[16] = '\0';
+	data._beam_type = buf;
+
+    is.read(buf,16);
+	buf[16] = '\0';
+	data._look_angle = atof(buf);
+
+    is.read(buf,16);
+	buf[16] = '\0';
+	data._beam_tab_inc = atof(buf);
+
+	return is;
+}
+
+CompensationDataRecord::CompensationDataRecord(const CompensationDataRecord& rhs)
+{
+	_comp_desig = rhs._comp_desig;
+
+	_comp_descr = rhs._comp_descr;
+
+    _n_comp_rec = rhs._n_comp_rec;
+
+    _comp_seq_no = rhs._comp_seq_no;
+
+    _beam_tab_size = rhs._beam_tab_size;
+
+	for (int i=0;i<256;i++)
+	{
+		_beam_tab[i] = rhs._beam_tab[i];
+	}
+
+    _beam_type = rhs._beam_type;
+
+    _look_angle = rhs._look_angle;
+
+    _beam_tab_inc = rhs._beam_tab_inc;
+}
+
+CompensationDataRecord& CompensationDataRecord::operator=(const CompensationDataRecord& rhs)
+{
+	_comp_desig = rhs._comp_desig;
+
+	_comp_descr = rhs._comp_descr;
+
+    _n_comp_rec = rhs._n_comp_rec;
+
+    _comp_seq_no = rhs._comp_seq_no;
+
+    _beam_tab_size = rhs._beam_tab_size;
+
+	for (int i=0;i<256;i++)
+	{
+		_beam_tab[i] = rhs._beam_tab[i];
+	}
+
+    _beam_type = rhs._beam_type;
+
+    _look_angle = rhs._look_angle;
+
+    _beam_tab_inc = rhs._beam_tab_inc;
+
+	return *this;
+}
+}
+
diff --git a/ossim_plugins/ossim/RadarSat/CommonRecord/CompensationDataRecord.h b/ossim_plugins/ossim/RadarSat/CommonRecord/CompensationDataRecord.h
new file mode 100755
index 0000000..a33b9dd
--- /dev/null
+++ b/ossim_plugins/ossim/RadarSat/CommonRecord/CompensationDataRecord.h
@@ -0,0 +1,163 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef CompensationDataRecord_h
+#define CompensationDataRecord_h
+
+#include <iostream>
+
+#include <RadarSat/RadarSatRecord.h>
+#include <RadarSat/RadarSatRecordHeader.h>
+
+namespace ossimplugins
+{
+/**
+ * @ingroup RadiometricCompensationDataRecord
+ * @brief This class is able to read a Compensation data record
+ */
+class CompensationDataRecord
+{
+public:
+  /**
+   * @brief Constructor
+   */
+  CompensationDataRecord();
+
+  /**
+   * @brief Destructor
+   */
+  ~CompensationDataRecord();
+
+  /**
+   * @brief Copy constructor
+   */
+  CompensationDataRecord(const CompensationDataRecord& rhs);
+
+  /**
+   * @brief Copy operator
+   */
+  CompensationDataRecord& operator=(const CompensationDataRecord& rhs);
+  /**
+   * @brief This function writes the CompensationDataRecord in a stream
+   */
+  friend std::ostream& operator<<(std::ostream& os, const CompensationDataRecord& data);
+
+  /**
+   * @brief This function reads a CompensationDataRecord from a stream
+   */
+  friend std::istream& operator>>(std::istream& is, CompensationDataRecord& data);
+
+  /**
+   * @brief Compensation data designator
+   */
+  std::string   get_comp_desig()
+  {
+    return _comp_desig;
+  };
+    /**
+   * @brief Compensation data descriptor
+   */
+  std::string   get_comp_descr()
+  {
+    return _comp_descr;
+  };
+    /**
+   * @brief Number of compensation records
+   */
+  int   get_n_comp_rec()
+  {
+    return _n_comp_rec;
+  };
+    /**
+   * @brief Compensation record sequence number
+   */
+  int   get_comp_seq_no()
+  {
+    return _comp_seq_no;
+  };
+    /**
+   * @brief Number of beam table entries
+   */
+  int   get_beam_tab_size()
+  {
+    return _beam_tab_size;
+  };
+    /**
+   * @brief Elevation gain beam profile
+   */
+  double*  get_beam_tab()
+  {
+    return _beam_tab;
+  };
+    /**
+   * @brief Beam type
+   */
+  std::string   get_beam_type()
+  {
+    return _beam_type;
+  };
+    /**
+   * @brief Look angle of beam table centre
+   */
+  double   get_look_angle()
+  {
+    return _look_angle;
+  };
+    /**
+   * @brief Increment between beam table entries
+   */
+  double   get_beam_tab_inc()
+  {
+    return _beam_tab_inc;
+  };
+
+protected:
+  /**
+   * @brief Compensation data designator
+   */
+  std::string   _comp_desig;
+    /**
+   * @brief Compensation data descriptor
+   */
+  std::string   _comp_descr;
+    /**
+   * @brief Number of compensation records
+   */
+  int   _n_comp_rec;
+    /**
+   * @brief Compensation record sequence number
+   */
+  int   _comp_seq_no;
+    /**
+   * @brief Number of beam table entries
+   */
+  int   _beam_tab_size;
+    /**
+   * @brief Elevation gain beam profile
+   */
+  double  _beam_tab[256];
+    /**
+   * @brief Beam type
+   */
+  std::string   _beam_type;
+    /**
+   * @brief Look angle of beam table centre
+   */
+  double   _look_angle;
+    /**
+   * @brief Increment between beam table entries
+   */
+  double   _beam_tab_inc;
+private:
+};
+}
+#endif
+
diff --git a/ossim_plugins/ossim/RadarSat/CommonRecord/DataHistogramRecord.cpp b/ossim_plugins/ossim/RadarSat/CommonRecord/DataHistogramRecord.cpp
new file mode 100755
index 0000000..d93a4e6
--- /dev/null
+++ b/ossim_plugins/ossim/RadarSat/CommonRecord/DataHistogramRecord.cpp
@@ -0,0 +1,237 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include "DataHistogramRecord.h"
+
+namespace ossimplugins
+{
+
+DataHistogramRecord::DataHistogramRecord():
+	_hist(NULL)
+{
+}
+
+DataHistogramRecord::~DataHistogramRecord()
+{
+	if (_hist != NULL)
+		delete[] _hist;
+}
+
+DataHistogramRecord::DataHistogramRecord(const DataHistogramRecord& rhs):
+	_hist_desc(rhs._hist_desc),
+	_nrec(rhs._nrec),
+	_tab_seq(rhs._tab_seq),
+	_nbin(rhs._nbin),
+	_ns_lin(rhs._ns_lin),
+	_ns_pix(rhs._ns_pix),
+	_ngrp_lin(rhs._ngrp_lin),
+	_ngrp_pix(rhs._ngrp_pix),
+	_nsamp_lin(rhs._nsamp_lin),
+	_nsamp_pix(rhs._nsamp_pix),
+	_min_smp(rhs._min_smp),
+	_max_smp(rhs._max_smp),
+	_mean_smp(rhs._mean_smp),
+	_std_smp(rhs._std_smp),
+	_smp_inc(rhs._smp_inc),
+	_min_hist(rhs._min_hist),
+	_max_hist(rhs._max_hist),
+	_mean_hist(rhs._mean_hist),
+	_std_hist(rhs._std_hist),
+	_nhist(rhs._nhist)
+{
+	_hist = new int[rhs._nhist];
+	for (int i=0;i<rhs._nhist;i++)
+	{
+		_hist[i] = rhs._hist[i];
+	}
+}
+
+DataHistogramRecord& DataHistogramRecord::operator=(const DataHistogramRecord& rhs)
+{
+	_hist_desc = rhs._hist_desc;
+	_nrec = rhs._nrec;
+	_tab_seq = rhs._tab_seq;
+	_nbin = rhs._nbin;
+	_ns_lin = rhs._ns_lin;
+	_ns_pix = rhs._ns_pix;
+	_ngrp_lin = rhs._ngrp_lin;
+	_ngrp_pix = rhs._ngrp_pix;
+	_nsamp_lin = rhs._nsamp_lin;
+	_nsamp_pix = rhs._nsamp_pix;
+	_min_smp = rhs._min_smp;
+	_max_smp = rhs._max_smp;
+	_mean_smp = rhs._mean_smp;
+	_std_smp = rhs._std_smp;
+	_smp_inc = rhs._smp_inc;
+	_min_hist = rhs._min_hist;
+	_max_hist = rhs._max_hist;
+	_mean_hist = rhs._mean_hist;
+	_std_hist = rhs._std_hist;
+	_nhist = rhs._nhist;
+	return *this;
+}
+
+std::ostream& operator<<(std::ostream& os, const DataHistogramRecord& data)
+{
+	os<<"hist_desc:"<<data._hist_desc.c_str()<<std::endl;
+
+    os<<"nrec:"<<data._nrec<<std::endl;
+
+    os<<"tab_seq:"<<data._tab_seq<<std::endl;
+
+    os<<"nbin:"<<data._nbin<<std::endl;
+
+    os<<"ns_lin:"<<data._ns_lin<<std::endl;
+
+    os<<"ns_pix:"<<data._ns_pix<<std::endl;
+
+    os<<"ngrp_lin:"<<data._ngrp_lin<<std::endl;
+
+    os<<"ngrp_pix:"<<data._ngrp_pix<<std::endl;
+
+    os<<"nsamp_lin:"<<data._nsamp_lin<<std::endl;
+
+    os<<"nsamp_pix:"<<data._nsamp_pix<<std::endl;
+
+    os<<"min_smp:"<<data._min_smp<<std::endl;
+
+    os<<"max_smp:"<<data._max_smp<<std::endl;
+
+    os<<"mean_smp:"<<data._mean_smp<<std::endl;
+
+    os<<"std_smp:"<<data._std_smp<<std::endl;
+
+    os<<"smp_inc:"<<data._smp_inc<<std::endl;
+
+    os<<"min_hist:"<<data._min_hist<<std::endl;
+
+    os<<"max_histd:"<<data._max_hist<<std::endl;
+
+    os<<"mean_hist:"<<data._mean_hist<<std::endl;
+
+    os<<"std_hist:"<<data._std_hist<<std::endl;
+
+    os<<"nhist:"<<data._nhist<<std::endl;
+
+	for(int i=0;i<data._nhist;i++)
+	{
+		os<<"his["<<i<<"]:"<<data._hist[i]<<std::endl;
+	}
+	return os;
+}
+
+std::istream& operator>>(std::istream& is, DataHistogramRecord& data)
+{
+	char buff[33];
+	buff[32] = '\0';
+
+	is.read(buff,32);
+	data._hist_desc = buff;
+
+    is.read(buff,4);
+	buff[4] = '\0';
+	data._nrec = atoi(buff);
+
+    is.read(buff,4);
+	buff[4] = '\0';
+	data._tab_seq = atoi(buff);
+
+    is.read(buff,8);
+	buff[8] = '\0';
+	data._nbin = atoi(buff);
+
+    is.read(buff,8);
+	buff[8] = '\0';
+	data._ns_lin = atoi(buff);
+
+    is.read(buff,8);
+	buff[8] = '\0';
+	data._ns_pix = atoi(buff);
+
+    is.read(buff,8);
+	buff[8] = '\0';
+	data._ngrp_lin = atoi(buff);
+
+    is.read(buff,8);
+	buff[8] = '\0';
+	data._ngrp_pix = atoi(buff);
+
+    is.read(buff,8);
+	buff[8] = '\0';
+	data._nsamp_lin = atoi(buff);
+
+    is.read(buff,8);
+	buff[8] = '\0';
+	data._nsamp_pix = atoi(buff);
+
+    is.read(buff,16);
+	buff[16] = '\0';
+	data._min_smp = atof(buff);
+
+    is.read(buff,16);
+	buff[16] = '\0';
+	data._max_smp = atof(buff);
+
+    is.read(buff,16);
+	buff[16] = '\0';
+	data._mean_smp = atof(buff);
+
+    is.read(buff,16);
+	buff[16] = '\0';
+	data._std_smp = atof(buff);
+
+    is.read(buff,16);
+	buff[16] = '\0';
+	data._smp_inc = atof(buff);
+
+    is.read(buff,16);
+	buff[16] = '\0';
+	data._min_hist = atof(buff);
+
+    is.read(buff,16);
+	buff[16] = '\0';
+	data._max_hist = atof(buff);
+
+    is.read(buff,16);
+	buff[16] = '\0';
+	data._mean_hist = atof(buff);
+
+    is.read(buff,16);
+	buff[16] = '\0';
+	data._std_hist = atof(buff);
+
+    is.read(buff,8);
+	buff[8] = '\0';
+	data._nhist = atoi(buff);
+
+	if(data._hist != NULL)
+	{
+		delete[] data._hist;
+	}
+
+	//for (int i=0;i<data._nhist;i++)
+	int nhist ;
+	if (data._nhist == 256)
+		{  nhist = 256 ; } // Signal Data
+	else {nhist = 1024 ; } // Processed Data
+
+	data._hist = new int[nhist];
+	for (int i=0;i<nhist;i++)
+	{
+		is.read(buff,8);
+		buff[8] = '\0';
+		data._hist[i] = atoi(buff);
+	}
+
+	return is;
+}
+}
+
diff --git a/ossim_plugins/ossim/RadarSat/CommonRecord/DataHistogramRecord.h b/ossim_plugins/ossim/RadarSat/CommonRecord/DataHistogramRecord.h
new file mode 100755
index 0000000..385112e
--- /dev/null
+++ b/ossim_plugins/ossim/RadarSat/CommonRecord/DataHistogramRecord.h
@@ -0,0 +1,303 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef DataHistogramRecord_h
+#define DataHistogramRecord_h
+
+#include<iostream>
+
+#include <RadarSat/RadarSatRecord.h>
+#include <RadarSat/RadarSatRecordHeader.h>
+
+namespace ossimplugins
+{
+/**
+ * @ingroup ProcessedData16bitHistogramRecord
+ * @ingroup SignalDataHistogramRecord
+ * @brief This class is able to read a data histogram record
+ */
+class DataHistogramRecord
+{
+public:
+  /**
+   * @brief Constructor
+   */
+  DataHistogramRecord();
+
+  /**
+   * @brief Destructor
+   */
+  ~DataHistogramRecord();
+
+  /**
+   * @brief Copy constructor
+   */
+  DataHistogramRecord(const DataHistogramRecord& rhs);
+
+  /**
+   * @brief Copy operator
+   */
+  DataHistogramRecord& operator=(const DataHistogramRecord& rhs);
+
+  /**
+   * @brief This function writes the DataHistogramRecord in a stream
+   */
+  friend std::ostream& operator<<(std::ostream& os, const DataHistogramRecord& data);
+
+  /**
+   * @brief This function reads a DataHistogramRecord from a stream
+   */
+  friend std::istream& operator>>(std::istream& is, DataHistogramRecord& data);
+
+
+
+  /**
+   * @brief Histogram descriptor
+   */
+  std::string   get_hist_desc()
+  {
+    return _hist_desc;
+  };
+    /**
+   * @brief Records per table
+   */
+  int   get_nrec()
+  {
+    return _nrec;
+  };
+    /**
+   * @brief Table sequence number
+   */
+  int   get_tab_seq()
+  {
+    return _tab_seq;
+  };
+    /**
+   * @brief Total number of table bins
+   */
+  int   get_nbin()
+  {
+    return _nbin;
+  };
+    /**
+   * @brief Total number of lines
+   */
+  int   get_ns_lin()
+  {
+    return _ns_lin;
+  };
+    /**
+   * @brief Total number of pixels per line
+   */
+  int   get_ns_pix()
+  {
+    return _ns_pix;
+  };
+    /**
+   * @brief Group size along line axis
+   */
+  int   get_ngrp_lin()
+  {
+    return _ngrp_lin;
+  };
+    /**
+   * @brief Group size along pixel axis
+   */
+  int   get_ngrp_pix()
+  {
+    return _ngrp_pix;
+  };
+    /**
+   * @brief Number of samples used per group along line axis
+   */
+  int   get_nsamp_lin()
+  {
+    return _nsamp_lin;
+  };
+    /**
+   * @brief Number of samples used per group along pixel
+   */
+  int   get_nsamp_pix()
+  {
+    return _nsamp_pix;
+  };
+    /**
+   * @brief Minimum first bin
+   */
+  double   get_min_smp()
+  {
+    return _min_smp;
+  };
+    /**
+   * @brief Maximum last bin
+   */
+  double   get_max_smp()
+  {
+    return _max_smp;
+  };
+    /**
+   * @brief Mean sample value
+   */
+  double   get_mean_smp()
+  {
+    return _mean_smp;
+  };
+    /**
+   * @brief Sample standard deviation
+   */
+  double   get_std_smp()
+  {
+    return _std_smp;
+  };
+    /**
+   * @brief Sample value increment
+   */
+  double   get_smp_inc()
+  {
+    return _smp_inc;
+  };
+    /**
+   * @brief Minimum histogram value
+   */
+  double   get_min_hist()
+  {
+    return _min_hist;
+  };
+    /**
+   * @brief Maximum histogram value
+   */
+  double   get_max_hist()
+  {
+    return _max_hist;
+  };
+    /**
+   * @brief Histogram mean value
+   */
+  double   get_mean_hist()
+  {
+    return _mean_hist;
+  };
+    /**
+   * @brief Histogram standard deviation
+   */
+  double   get_std_hist()
+  {
+    return _std_hist;
+  };
+    /**
+   * @brief Histogram table size
+   */
+  int   get_nhist()
+  {
+    return _nhist;
+  };
+
+  /**
+   * @brief Histogram table values of 16 bins for Ix16 bins for Q
+   */
+  int* get_hist()
+  {
+    return _hist;
+  };
+protected:
+
+
+  /**
+   * @brief Histogram descriptor
+   */
+  std::string   _hist_desc;
+    /**
+   * @brief Records per table
+   */
+  int   _nrec;
+    /**
+   * @brief Table sequence number
+   */
+  int   _tab_seq;
+    /**
+   * @brief Total number of table bins
+   */
+  int   _nbin;
+    /**
+   * @brief Total number of lines
+   */
+  int   _ns_lin;
+    /**
+   * @brief Total number of pixels per line
+   */
+  int   _ns_pix;
+    /**
+   * @brief Group size along line axis
+   */
+  int   _ngrp_lin;
+    /**
+   * @brief Group size along pixel axis
+   */
+  int   _ngrp_pix;
+    /**
+   * @brief Number of samples used per group along line axis
+   */
+  int   _nsamp_lin;
+    /**
+   * @brief Number of samples used per group along pixel
+   */
+  int   _nsamp_pix;
+    /**
+   * @brief Minimum first bin
+   */
+  double   _min_smp;
+    /**
+   * @brief Maximum last bin
+   */
+  double   _max_smp;
+    /**
+   * @brief Mean sample value
+   */
+  double   _mean_smp;
+    /**
+   * @brief Sample standard deviation
+   */
+  double   _std_smp;
+    /**
+   * @brief Sample value increment
+   */
+  double   _smp_inc;
+    /**
+   * @brief Minimum histogram value
+   */
+  double   _min_hist;
+    /**
+   * @brief Maximum histogram value
+   */
+  double   _max_hist;
+    /**
+   * @brief Histogram mean value
+   */
+  double   _mean_hist;
+    /**
+   * @brief Histogram standard deviation
+   */
+  double   _std_hist;
+    /**
+   * @brief Histogram table size
+   */
+  int   _nhist;
+  /**
+   * @brief Histogram table values
+   */
+  int* _hist;
+private:
+
+
+};
+}
+#endif
+
diff --git a/ossim_plugins/ossim/RadarSat/CommonRecord/DataHistogramSignalData.cpp b/ossim_plugins/ossim/RadarSat/CommonRecord/DataHistogramSignalData.cpp
new file mode 100755
index 0000000..6edadbd
--- /dev/null
+++ b/ossim_plugins/ossim/RadarSat/CommonRecord/DataHistogramSignalData.cpp
@@ -0,0 +1,94 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include "DataHistogramSignalData.h"
+
+namespace ossimplugins
+{
+
+DataHistogramSignalData::DataHistogramSignalData() : RadarSatRecord("sdr_hist_rec")
+{
+}
+
+DataHistogramSignalData::~DataHistogramSignalData()
+{
+}
+
+std::ostream& operator<<(std::ostream& os, const DataHistogramSignalData& data)
+{
+
+	os<<"rec_seq:"<<data._rec_seq<<std::endl;
+
+    os<<"sar_chn:"<<data._sar_chn<<std::endl;
+
+	os<<"ntab:"<<data._ntab<<std::endl;
+
+	os<<"ltab:"<<data._ltab<<std::endl;
+
+	os<<data._histogram<<std::endl;
+
+	return os;
+}
+
+std::istream& operator>>(std::istream& is, DataHistogramSignalData& data)
+{
+	char buff[33];
+	buff[32] = '\0';
+
+
+	is.read(buff,4);
+	buff[4] = '\0';
+	data._rec_seq = atoi(buff);
+
+    is.read(buff,4);
+	buff[4] = '\0';
+	data._sar_chn = atoi(buff);
+
+	is.read(buff,8);
+	buff[8] = '\0';
+	data._ntab = atoi(buff);
+
+	is.read(buff,8);
+	buff[8] = '\0';
+	data._ltab = atoi(buff);
+
+	is>>data._histogram;
+
+	char tmp[14589];
+	tmp[14588] = '\0';
+	is.read(tmp, 14588);
+
+	return is;
+}
+
+DataHistogramSignalData::DataHistogramSignalData(const DataHistogramSignalData& rhs) :
+	RadarSatRecord(rhs),
+	_rec_seq(rhs._rec_seq),
+	_sar_chn(rhs._sar_chn),
+	_ntab(rhs._ntab),
+	_ltab(rhs._ltab),
+	_histogram(rhs._histogram)
+{
+
+}
+
+DataHistogramSignalData& DataHistogramSignalData::operator=(const DataHistogramSignalData& rhs)
+{
+	_histogram = rhs._histogram;
+	_sar_chn = rhs._sar_chn;
+	_rec_seq = rhs._rec_seq;
+	_ntab = rhs._ntab;
+	_ltab = rhs._ltab;
+
+	return *this;
+}
+}
+
diff --git a/ossim_plugins/ossim/RadarSat/CommonRecord/DataHistogramSignalData.h b/ossim_plugins/ossim/RadarSat/CommonRecord/DataHistogramSignalData.h
new file mode 100755
index 0000000..601b63b
--- /dev/null
+++ b/ossim_plugins/ossim/RadarSat/CommonRecord/DataHistogramSignalData.h
@@ -0,0 +1,161 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef DataHistogramSignalData_h
+#define DataHistogramSignalData_h
+
+#include <iostream>
+
+#include <RadarSat/RadarSatRecord.h>
+#include <RadarSat/RadarSatRecordHeader.h>
+#include "DataHistogramRecord.h"
+
+namespace ossimplugins
+{
+/**
+ * @ingroup SignalDataHistogramRecord
+ * @brief This class is able to read a data histogram record - Signal data
+ */
+class DataHistogramSignalData : public RadarSatRecord
+{
+public:
+  /**
+   * @brief Constructor
+   */
+  DataHistogramSignalData();
+
+  /**
+   * @brief Destructor
+   */
+  virtual ~DataHistogramSignalData();
+
+  /**
+   * @brief Copy constructor
+   */
+  DataHistogramSignalData(const DataHistogramSignalData& rhs);
+
+  /**
+   * @brief Copy operator
+   */
+  DataHistogramSignalData& operator=(const DataHistogramSignalData& rhs);
+  /**
+   * @brief This function writes the DataHistogramSignalData in a stream
+   */
+  friend std::ostream& operator<<(std::ostream& os, const DataHistogramSignalData& data);
+
+  /**
+   * @brief This function reads a DataHistogramSignalData from a stream
+   */
+  friend std::istream& operator>>(std::istream& is, DataHistogramSignalData& data);
+
+  /**
+   * @brief This function is able to create a new instance of the class
+   */
+  RadarSatRecord* Instanciate()
+  {
+    return new DataHistogramSignalData();
+  };
+
+  /**
+   * @brief This function is able to create a new instance of the class initialised with the data of the calling instance
+   */
+  RadarSatRecord* Clone()
+  {
+    return new DataHistogramSignalData(*this);
+  };
+
+  /**
+   * @brief Reads the class data from a stream
+   */
+  void Read(std::istream& is)
+  {
+    is>>*this;
+  };
+
+  /**
+   * @brief Writes the class to a stream
+   */
+  void Write(std::ostream& os)
+  {
+    os<<*this;
+  };
+
+  /**
+   * @brief Record sequence number
+   */
+  int   get_rec_seq()
+  {
+    return _rec_seq;
+  };
+  /**
+   * @brief SAR channel indicator
+   */
+  int   get_sar_chn()
+  {
+    return _sar_chn;
+  };
+
+  /**
+   * @brief Number of histogram table data sets in this record
+   */
+  int   get_ntab()
+  {
+    return _ntab;
+  };
+
+  /**
+   * @brief Histogram table data set size
+   */
+  int   get_ltab()
+  {
+    return _ltab;
+  };
+
+  /**
+   * @brief Histogram data record
+   */
+  DataHistogramRecord get_histogram()
+  {
+    return _histogram;
+  };
+
+protected:
+  /**
+   * @brief Record sequence number
+   */
+  int   _rec_seq;
+  /**
+   * @brief SAR channel indicator
+   */
+  int   _sar_chn;
+
+  /**
+   * @brief Number of histogram table data sets in this record
+   */
+  int   _ntab;
+  /**
+   * @brief Histogram table data set size
+   */
+  int   _ltab;
+  /**
+   * @brief Histogram data record
+   */
+  DataHistogramRecord _histogram;
+
+private:
+
+
+};
+
+typedef DataHistogramSignalData DataHistogramProcessedData8;
+}
+#endif
+
diff --git a/ossim_plugins/ossim/RadarSat/CommonRecord/DataPointDataRecord.cpp b/ossim_plugins/ossim/RadarSat/CommonRecord/DataPointDataRecord.cpp
new file mode 100755
index 0000000..adb98ce
--- /dev/null
+++ b/ossim_plugins/ossim/RadarSat/CommonRecord/DataPointDataRecord.cpp
@@ -0,0 +1,144 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include "DataPointDataRecord.h"
+
+namespace ossimplugins
+{
+DataPointDataRecord::DataPointDataRecord()
+{
+}
+
+DataPointDataRecord::~DataPointDataRecord()
+{
+}
+
+std::ostream& operator<<(std::ostream& os, const DataPointDataRecord& data)
+{
+	os<<"gmt_day:"<<data._gmt_day<<std::endl;
+    os<<"gmt_sec:"<<data._gmt_sec<<std::endl;
+    os<<"pitch_flag:"<<data._pitch_flag<<std::endl;
+    os<<"roll_flag:"<<data._roll_flag<<std::endl;
+    os<<"yaw_flag:"<<data._yaw_flag<<std::endl;
+    os<<"pitch:"<<data._pitch<<std::endl;
+    os<<"roll:"<<data._roll<<std::endl;
+    os<<"yaw:"<<data._yaw<<std::endl;
+    os<<"pitch_rate_flag:"<<data._pitch_rate_flag<<std::endl;
+    os<<"roll_rate_flag:"<<data._roll_rate_flag<<std::endl;
+    os<<"yaw_rate_flag:"<<data._yaw_rate_flag<<std::endl;
+    os<<"pitch_rate:"<<data._pitch_rate<<std::endl;
+    os<<"roll_rate:"<<data._roll_rate<<std::endl;
+	os<<"yaw_rate:"<<data._yaw_rate<<std::endl;
+	return os;
+}
+
+std::istream& operator>>(std::istream& is, DataPointDataRecord& data)
+{
+	char buf[15];
+	buf[14] = '\0';
+
+	is.read(buf,4);
+	buf[4] = '\0';
+	data._gmt_day = atoi(buf);
+
+	is.read(buf,8);
+	buf[8] = '\0';
+	data._gmt_sec = atoi(buf);
+
+    is.read(buf,4);
+	buf[4] = '\0';
+	data._pitch_flag = atoi(buf);
+
+    is.read(buf,4);
+	buf[4] = '\0';
+	data._roll_flag = atoi(buf);
+
+    is.read(buf,4);
+	buf[4] = '\0';
+	data._yaw_flag = atoi(buf);
+
+    is.read(buf,14);
+	buf[14] = '\0';
+	data._pitch = atof(buf);
+
+    is.read(buf,14);
+	buf[14] = '\0';
+	data._roll = atof(buf);
+
+    is.read(buf,14);
+	buf[14] = '\0';
+	data._yaw = atof(buf);
+
+    is.read(buf,4);
+	buf[4] = '\0';
+	data._pitch_rate_flag = atoi(buf);
+
+    is.read(buf,4);
+	buf[4] = '\0';
+	data._roll_rate_flag = atoi(buf);
+
+    is.read(buf,4);
+	buf[4] = '\0';
+	data._yaw_rate_flag = atoi(buf);
+
+    is.read(buf,14);
+	buf[14] = '\0';
+	data._pitch_rate = atof(buf);
+
+    is.read(buf,14);
+	buf[14] = '\0';
+	data._roll_rate = atof(buf);
+
+    is.read(buf,14);
+	buf[14] = '\0';
+	data._yaw_rate = atof(buf);
+
+	return is;
+}
+
+DataPointDataRecord::DataPointDataRecord(const DataPointDataRecord& rhs)
+{
+	_gmt_day = rhs._gmt_day;
+    _gmt_sec = rhs._gmt_sec;
+    _pitch_flag = rhs._pitch_flag;
+    _roll_flag = rhs._roll_flag;
+    _yaw_flag = rhs._yaw_flag;
+    _pitch = rhs._pitch;
+    _roll = rhs._roll;
+    _yaw = rhs._yaw;
+    _pitch_rate_flag = rhs._pitch_rate_flag;
+    _roll_rate_flag = rhs._roll_rate_flag;
+    _yaw_rate_flag = rhs._yaw_rate_flag;
+    _pitch_rate = rhs._pitch_rate;
+    _roll_rate = rhs._roll_rate;
+	_yaw_rate = rhs._yaw_rate;
+}
+
+DataPointDataRecord& DataPointDataRecord::operator=(const DataPointDataRecord& rhs)
+{
+	_gmt_day = rhs._gmt_day;
+    _gmt_sec = rhs._gmt_sec;
+    _pitch_flag = rhs._pitch_flag;
+    _roll_flag = rhs._roll_flag;
+    _yaw_flag = rhs._yaw_flag;
+    _pitch = rhs._pitch;
+    _roll = rhs._roll;
+    _yaw = rhs._yaw;
+    _pitch_rate_flag = rhs._pitch_rate_flag;
+    _roll_rate_flag = rhs._roll_rate_flag;
+    _yaw_rate_flag = rhs._yaw_rate_flag;
+    _pitch_rate = rhs._pitch_rate;
+    _roll_rate = rhs._roll_rate;
+	_yaw_rate = rhs._yaw_rate;
+	return *this;
+}
+}
+
diff --git a/ossim_plugins/ossim/RadarSat/CommonRecord/DataPointDataRecord.h b/ossim_plugins/ossim/RadarSat/CommonRecord/DataPointDataRecord.h
new file mode 100755
index 0000000..9717633
--- /dev/null
+++ b/ossim_plugins/ossim/RadarSat/CommonRecord/DataPointDataRecord.h
@@ -0,0 +1,218 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef DataPointDataRecord_h
+#define DataPointDataRecord_h
+
+#include <iostream>
+
+#include <RadarSat/RadarSatRecord.h>
+#include <RadarSat/RadarSatRecordHeader.h>
+
+namespace ossimplugins
+{
+/**
+ * @ingroup AttitudeDataRecord
+ * @brief This class is able to read a Data point data record
+ */
+class DataPointDataRecord
+{
+public:
+  /**
+   * @brief Constructor
+   */
+  DataPointDataRecord();
+
+  /**
+   * @brief Destructor
+   */
+  ~DataPointDataRecord();
+
+  /**
+   * @brief Copy constructor
+   */
+  DataPointDataRecord(const DataPointDataRecord& rhs);
+
+  /**
+   * @brief Copy operator
+   */
+  DataPointDataRecord& operator=(const DataPointDataRecord& rhs);
+  /**
+   * @brief This function writes the DataPointDataRecord in a stream
+   */
+  friend std::ostream& operator<<(std::ostream& os, const DataPointDataRecord& data);
+
+  /**
+   * @brief This function reads a DataPointDataRecord from a stream
+   */
+  friend std::istream& operator>>(std::istream& is, DataPointDataRecord& data);
+
+  /**
+   * @brief Day of the year, GMT
+   */
+  int   get_gmt_day()
+  {
+    return _gmt_day;
+  };
+    /**
+   * @brief Milliseconds of day, GMT
+   */
+  int  get_gmt_sec()
+  {
+    return _gmt_sec;
+  };
+    /**
+   * @brief Pitch data quality flag
+   */
+  int   get_pitch_flag()
+  {
+    return _pitch_flag;
+  };
+    /**
+   * @brief Roll data quality flag
+   */
+  int   get_roll_flag()
+  {
+    return _roll_flag;
+  };
+    /**
+   * @brief Yaw data quality flag
+   */
+  int   get_yaw_flag()
+  {
+    return _yaw_flag;
+  };
+    /**
+   * @brief Pitch error, degrees
+   */
+  double   get_pitch()
+  {
+    return _pitch;
+  };
+    /**
+   * @brief Roll error, degrees
+   */
+  double   get_roll()
+  {
+    return _roll;
+  };
+    /**
+   * @brief Yaw error, degrees
+   */
+  double   get_yaw()
+  {
+    return _yaw;
+  };
+    /**
+   * @brief Pitch rate data quality flag
+   */
+  int   get_pitch_rate_flag()
+  {
+    return _pitch_rate_flag;
+  };
+    /**
+   * @brief Roll rate data quality fla
+   */
+  int   get_roll_rate_flag()
+  {
+    return _roll_rate_flag;
+  };
+    /**
+   * @brief Yaw rate data quality flag
+   */
+  int   get_yaw_rate_flag()
+  {
+    return _yaw_rate_flag;
+  };
+    /**
+   * @brief Pitch rate, degrees/sec
+   */
+  double   get_pitch_rate()
+  {
+    return _pitch_rate;
+  };
+    /**
+   * @brief Roll rate, degrees/sec
+   */
+  double   get_roll_rate()
+  {
+    return _roll_rate;
+  };
+    /**
+   * @brief Yaw rate, degrees/sec
+   */
+  double   get_yaw_rate()
+  {
+    return _yaw_rate;
+  };
+
+protected:
+  /**
+   * @brief Day of the year, GMT
+   */
+  int   _gmt_day;
+    /**
+   * @brief Milliseconds of day, GMT
+   */
+  int   _gmt_sec;
+    /**
+   * @brief Pitch data quality flag
+   */
+  int   _pitch_flag;
+    /**
+   * @brief Roll data quality flag
+   */
+  int   _roll_flag;
+    /**
+   * @brief Yaw data quality flag
+   */
+  int   _yaw_flag;
+    /**
+   * @brief Pitch error, degrees
+   */
+  double   _pitch;
+    /**
+   * @brief Roll error, degrees
+   */
+  double   _roll;
+    /**
+   * @brief Yaw error, degrees
+   */
+  double   _yaw;
+    /**
+   * @brief Pitch rate data quality flag
+   */
+  int   _pitch_rate_flag;
+    /**
+   * @brief Roll rate data quality fla
+   */
+  int   _roll_rate_flag;
+    /**
+   * @brief Yaw rate data quality flag
+   */
+  int   _yaw_rate_flag;
+    /**
+   * @brief Pitch rate, degrees/sec
+   */
+  double   _pitch_rate;
+    /**
+   * @brief Roll rate, degrees/sec
+   */
+  double   _roll_rate;
+    /**
+   * @brief Yaw rate, degrees/sec
+   */
+  double   _yaw_rate;
+private:
+};
+}
+#endif
+
diff --git a/ossim_plugins/ossim/RadarSat/CommonRecord/DataQuality.cpp b/ossim_plugins/ossim/RadarSat/CommonRecord/DataQuality.cpp
new file mode 100755
index 0000000..026c337
--- /dev/null
+++ b/ossim_plugins/ossim/RadarSat/CommonRecord/DataQuality.cpp
@@ -0,0 +1,294 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include "DataQuality.h"
+
+namespace ossimplugins
+{
+DataQuality::DataQuality() : RadarSatRecord("qual_sum_rec")
+{
+}
+
+DataQuality::~DataQuality()
+{
+}
+
+std::ostream& operator<<(std::ostream& os, const DataQuality& data)
+{
+
+	os<<"rec_seq:"<<data._rec_seq<<std::endl;
+
+	os<<"sar_chn:"<<data._sar_chn.c_str()<<std::endl;
+
+    os<<"cali_date:"<<data._cali_date.c_str()<<std::endl;
+
+    os<<"nchn:"<<data._nchn<<std::endl;
+
+    os<<"islr:"<<data._islr<<std::endl;
+
+    os<<"pslr:"<<data._pslr<<std::endl;
+
+    os<<"azi_ambig:"<<data._azi_ambig<<std::endl;
+
+    os<<"rng_ambig:"<<data._rng_ambig<<std::endl;
+
+    os<<"snr:"<<data._snr<<std::endl;
+
+    os<<"ber:"<<data._ber<<std::endl;
+
+    os<<"rng_res:"<<data._rng_res<<std::endl;
+
+    os<<"azi_res:"<<data._azi_res<<std::endl;
+
+    os<<"rad_res:"<<data._rad_res<<std::endl;
+
+    os<<"dyn_rng:"<<data._dyn_rng<<std::endl;
+
+    os<<"rad_unc_db:"<<data._rad_unc_db<<std::endl;
+
+    os<<"rad_unc_deg:"<<data._rad_unc_deg<<std::endl;
+
+	for (int i=0;i<16;i++)
+	{
+		os<<"rad_unc:"<<data._rad_unc[i]<<std::endl;
+	}
+
+    os<<"alt_locerr:"<<data._alt_locerr<<std::endl;
+
+    os<<"crt_locerr:"<<data._crt_locerr<<std::endl;
+
+    os<<"alt_scale:"<<data._alt_scale<<std::endl;
+
+    os<<"crt_scale:"<<data._crt_scale<<std::endl;
+
+    os<<"dis_skew:"<<data._dis_skew<<std::endl;
+
+    os<<"ori_err:"<<data._ori_err<<std::endl;
+
+	for (int i=0;i<16;i++)
+	{
+		os<<"misreg:"<<data._misreg[i]<<std::endl;
+	}
+
+	os<<"nesz:"<<data._nesz<<std::endl;
+
+    os<<"enl:"<<data._enl<<std::endl;
+
+    os<<"tb_update:"<<data._tb_update.c_str()<<std::endl;
+
+
+	return os;
+}
+
+std::istream& operator>>(std::istream& is, DataQuality& data)
+{
+	char buf[2149];
+	buf[2148] = '\0';
+
+
+	is.read(buf,4);
+	buf[4] = '\0';
+	data._rec_seq = atoi(buf);
+
+	is.read(buf,4);
+	buf[4] = '\0';
+	data._sar_chn = buf;
+
+    is.read(buf,6);
+	buf[6] = '\0';
+	data._cali_date = buf;
+
+    is.read(buf,4);
+	buf[4] = '\0';
+	data._nchn = atoi(buf);
+
+    is.read(buf,16);
+	buf[16] = '\0';
+	data._islr = atof(buf);
+
+    is.read(buf,16);
+	buf[16] = '\0';
+	data._pslr = atof(buf);
+
+    is.read(buf,16);
+	buf[16] = '\0';
+	data._azi_ambig = atof(buf);
+
+    is.read(buf,16);
+	buf[16] = '\0';
+	data._rng_ambig = atof(buf);
+
+    is.read(buf,16);
+	buf[16] = '\0';
+	data._snr = atof(buf);
+
+    is.read(buf,16);
+	buf[16] = '\0';
+	data._ber = atof(buf);
+
+    is.read(buf,16);
+	buf[16] = '\0';
+	data._rng_res = atof(buf);
+
+    is.read(buf,16);
+	buf[16] = '\0';
+	data._azi_res = atof(buf);
+
+    is.read(buf,16);
+	buf[16] = '\0';
+	data._rad_res = atof(buf);
+
+    is.read(buf,16);
+	buf[16] = '\0';
+	data._dyn_rng = atof(buf);
+
+    is.read(buf,16);
+	buf[16] = '\0';
+	data._rad_unc_db = atof(buf);
+
+    is.read(buf,16);
+	buf[16] = '\0';
+	data._rad_unc_deg = atof(buf);
+
+	for (int i=0;i<16;i++)
+	{
+		is>>data._rad_unc[i];
+	}
+
+    is.read(buf,16);
+	buf[16] = '\0';
+	data._alt_locerr = atof(buf);
+
+    is.read(buf,16);
+	buf[16] = '\0';
+	data._crt_locerr = atof(buf);
+
+    is.read(buf,16);
+	buf[16] = '\0';
+	data._alt_scale = atof(buf);
+
+    is.read(buf,16);
+	buf[16] = '\0';
+	data._crt_scale = atof(buf);
+
+    is.read(buf,16);
+	buf[16] = '\0';
+	data._dis_skew = atof(buf);
+
+    is.read(buf,16);
+	buf[16] = '\0';
+	data._ori_err = atof(buf);
+
+	for (int i=0;i<16;i++)
+	{
+		is>>data._misreg[i];
+	}
+
+	is.read(buf,16);
+	buf[16] = '\0';
+	data._nesz = atof(buf);
+
+    is.read(buf,16);
+	buf[16] = '\0';
+	data._enl = atof(buf);
+
+    is.read(buf,8);
+	buf[8] = '\0';
+	data._tb_update = buf;
+
+    is.read(buf,238);
+
+
+	return is;
+}
+
+DataQuality::DataQuality(const DataQuality& rhs):
+	RadarSatRecord(rhs),
+	_rec_seq(rhs._rec_seq),
+	_sar_chn(rhs._sar_chn),
+    _cali_date(rhs._cali_date),
+    _nchn(rhs._nchn),
+    _islr(rhs._islr),
+    _pslr(rhs._pslr),
+    _azi_ambig(rhs._azi_ambig),
+    _rng_ambig(rhs._rng_ambig),
+    _snr(rhs._snr),
+    _ber(rhs._ber),
+    _rng_res(rhs._rng_res),
+    _azi_res(rhs._azi_res),
+    _rad_res(rhs._rad_res),
+    _dyn_rng(rhs._dyn_rng),
+    _rad_unc_db(rhs._rad_unc_db),
+    _rad_unc_deg(rhs._rad_unc_deg),
+    _alt_locerr(rhs._alt_locerr),
+    _crt_locerr(rhs._crt_locerr),
+    _alt_scale(rhs._alt_scale),
+    _crt_scale(rhs._crt_scale),
+    _dis_skew(rhs._dis_skew),
+    _ori_err(rhs._ori_err),
+	_nesz(rhs._nesz),
+    _enl(rhs._enl),
+    _tb_update(rhs._tb_update)
+{
+	for (int i=0;i<16;i++)
+	{
+		_rad_unc[i] = rhs._rad_unc[i];
+	}
+	for (int i=0;i<16;i++)
+	{
+		_misreg[i] = rhs._misreg[i];
+	}
+}
+
+DataQuality& DataQuality::operator=(const DataQuality& rhs)
+{
+	_rec_seq = rhs._rec_seq;
+	_sar_chn = rhs._sar_chn;
+    _cali_date = rhs._cali_date;
+    _nchn = rhs._nchn;
+    _islr = rhs._islr;
+    _pslr = rhs._pslr;
+    _azi_ambig = rhs._azi_ambig;
+    _rng_ambig = rhs._rng_ambig;
+    _snr = rhs._snr;
+    _ber = rhs._ber;
+    _rng_res = rhs._rng_res;
+    _azi_res = rhs._azi_res;
+    _rad_res = rhs._rad_res;
+    _dyn_rng = rhs._dyn_rng;
+    _rad_unc_db = rhs._rad_unc_db;
+    _rad_unc_deg = rhs._rad_unc_deg;
+
+	for (int i=0;i<16;i++)
+	{
+		_rad_unc[i] = rhs._rad_unc[i];
+	}
+
+    _alt_locerr = rhs._alt_locerr;
+    _crt_locerr = rhs._crt_locerr;
+    _alt_scale = rhs._alt_scale;
+    _crt_scale = rhs._crt_scale;
+    _dis_skew = rhs._dis_skew;
+    _ori_err = rhs._ori_err;
+
+	for (int i=0;i<16;i++)
+	{
+		_misreg[i] = rhs._misreg[i];
+	}
+
+	_nesz = rhs._nesz;
+    _enl = rhs._enl;
+    _tb_update = rhs._tb_update;
+
+	return *this;
+}
+}
+
diff --git a/ossim_plugins/ossim/RadarSat/CommonRecord/DataQuality.h b/ossim_plugins/ossim/RadarSat/CommonRecord/DataQuality.h
new file mode 100755
index 0000000..d813290
--- /dev/null
+++ b/ossim_plugins/ossim/RadarSat/CommonRecord/DataQuality.h
@@ -0,0 +1,401 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef DataQuality_h
+#define DataQuality_h
+
+#include <iostream>
+
+#include <RadarSat/RadarSatRecord.h>
+#include <RadarSat/RadarSatRecordHeader.h>
+
+#include "RadiometryUncertaintyRecord.h"
+#include "MisregistrationRecord.h"
+
+namespace ossimplugins
+{
+/**
+ * @ingroup DataQualitySummaryRecord
+ * @brief This class is able to read a data quality record
+ */
+class DataQuality : public RadarSatRecord
+{
+public:
+  /**
+   * @brief Constructor
+   */
+  DataQuality();
+
+  /**
+   * @brief Destructor
+   */
+  virtual ~DataQuality();
+
+  /**
+   * @brief Copy constructor
+   */
+  DataQuality(const DataQuality& rhs);
+
+  /**
+   * @brief Copy operator
+   */
+  DataQuality& operator=(const DataQuality& rhs);
+  /**
+   * @brief This function writes the DataQuality in a stream
+   */
+  friend std::ostream& operator<<(std::ostream& os, const DataQuality& data);
+
+  /**
+   * @brief This function reads a DataQuality from a stream
+   */
+  friend std::istream& operator>>(std::istream& is, DataQuality& data);
+
+  /**
+   * @brief This function is able to create a new instance of the class
+   */
+  RadarSatRecord* Instanciate()
+  {
+    return new DataQuality();
+  };
+
+  /**
+   * @brief This function is able to create a new instance of the class initialised with the data of the calling instance
+   */
+  RadarSatRecord* Clone()
+  {
+    return new DataQuality(*this);
+  };
+
+  /**
+   * @brief Reads the class data from a stream
+   */
+  void Read(std::istream& is)
+  {
+    is>>*this;
+  };
+
+  /**
+   * @brief Writes the class to a stream
+   */
+  void Write(std::ostream& os)
+  {
+    os<<*this;
+  };
+
+  /**
+   * @brief Record sequence number
+   */
+  int   get_rec_seq()
+  {
+    return _rec_seq;
+  };
+  /**
+   * @brief SAR channel indicator
+   */
+  std::string   get_sar_chn()
+  {
+    return _sar_chn;
+  };
+    /**
+   * @brief Calibration update date
+   */
+  std::string   get_cali_date()
+  {
+    return _cali_date;
+  };
+    /**
+   * @brief Number of channels
+   */
+  int   get_nchn()
+  {
+    return _nchn;
+  };
+    /**
+   * @brief Nominal integrated side lobe ratio
+   */
+  double   get_islr()
+  {
+    return _islr;
+  };
+    /**
+   * @brief Nominal peak side lobe ratio
+   */
+  double   get_pslr()
+  {
+    return _pslr;
+  };
+    /**
+   * @brief Nominal azimuth ambiguity
+   */
+  double   get_azi_ambig()
+  {
+    return _azi_ambig;
+  };
+    /**
+   * @brief Nominal range ambiguity
+   */
+  double   get_rng_ambig()
+  {
+    return _rng_ambig;
+  };
+    /**
+   * @brief Nominal signal to noise ratio
+   */
+  double   get_snr()
+  {
+    return _snr;
+  };
+    /**
+   * @brief Nominal bit error rate
+   */
+  double   get_ber()
+  {
+    return _ber;
+  };
+    /**
+   * @brief Nominal slant range resolution
+   */
+  double   get_rng_res()
+  {
+    return _rng_res;
+  };
+    /**
+   * @brief Nominal azimuth resolution,meter
+   */
+  double   get_azi_res()
+  {
+    return _azi_res;
+  };
+    /**
+   * @brief Nominal radiometric resolution,dB
+   */
+  double   get_rad_res()
+  {
+    return _rad_res;
+  };
+    /**
+   * @brief Instantaneous dynamic range
+   */
+  double   get_dyn_rng()
+  {
+    return _dyn_rng;
+  };
+    /**
+   * @brief Nominal radiometric uncertainty,dB
+   */
+  double   get_rad_unc_db()
+  {
+    return _rad_unc_db;
+  };
+    /**
+   * @brief Nominal Radiometric uncertainty,deg
+   */
+  double   get_rad_unc_deg()
+  {
+    return _rad_unc_deg;
+  };
+  /**
+   * @brief Radiometric data quality
+   */
+  RadiometryUncertaintyRecord* get_rad_unc()
+  {
+    return _rad_unc;
+  };
+    /**
+   * @brief Nominal along track location error
+   */
+  double   get_alt_locerr()
+  {
+    return _alt_locerr;
+  };
+    /**
+   * @brief Nominal cross track location error
+   */
+  double   get_crt_locerr()
+  {
+    return _crt_locerr;
+  };
+    /**
+   * @brief Nominal along track distortion scale
+   */
+  double   get_alt_scale()
+  {
+    return _alt_scale;
+  };
+    /**
+   * @brief Nominal cross track distortion scale
+   */
+  double   get_crt_scale()
+  {
+    return _crt_scale;
+  };
+    /**
+   * @brief Nominal distortion skew
+   */
+  double   get_dis_skew()
+  {
+    return _dis_skew;
+  };
+    /**
+   * @brief Nominal Scene orientation error
+   */
+  double   get_ori_err()
+  {
+    return _ori_err;
+  };
+  /**
+   * @brief Misregistration error
+   */
+  MisregistrationRecord* get_misreg()
+  {
+    return _misreg;
+  };
+    /**
+   * @brief Nominal noise equivalent sigma zero
+   */
+  double   get_nesz()
+  {
+    return _nesz;
+  };
+    /**
+   * @brief Nominal equivalent number of looks
+   */
+  double   get_enl()
+  {
+    return _enl;
+  };
+    /**
+   * @brief Default parameters table update date
+   */
+  std::string   get_tb_update()
+  {
+    return _tb_update;
+  };
+
+
+protected:
+
+  /**
+   * @brief Record sequence number
+   */
+  int   _rec_seq;
+  /**
+   * @brief SAR channel indicator
+   */
+  std::string   _sar_chn;
+    /**
+   * @brief Calibration update date
+   */
+  std::string   _cali_date;
+    /**
+   * @brief Number of channels
+   */
+  int   _nchn;
+    /**
+   * @brief Nominal integrated side lobe ratio
+   */
+  double   _islr;
+    /**
+   * @brief Nominal peak side lobe ratio
+   */
+  double   _pslr;
+    /**
+   * @brief Nominal azimuth ambiguity
+   */
+  double   _azi_ambig;
+    /**
+   * @brief Nominal range ambiguity
+   */
+  double   _rng_ambig;
+    /**
+   * @brief Nominal signal to noise ratio
+   */
+  double   _snr;
+    /**
+   * @brief Nominal bit error rate
+   */
+  double   _ber;
+    /**
+   * @brief Nominal slant range resolution
+   */
+  double   _rng_res;
+    /**
+   * @brief Nominal azimuth resolution,meter
+   */
+  double   _azi_res;
+    /**
+   * @brief Nominal radiometric resolution,dB
+   */
+  double   _rad_res;
+    /**
+   * @brief Instantaneous dynamic range
+   */
+  double   _dyn_rng;
+    /**
+   * @brief Nominal radiometric uncertainty,dB
+   */
+  double   _rad_unc_db;
+    /**
+   * @brief Nominal Radiometric uncertainty,deg
+   */
+  double   _rad_unc_deg;
+  /**
+   * @brief Radiometric data quality
+   */
+  RadiometryUncertaintyRecord _rad_unc[16];
+    /**
+   * @brief Nominal along track location error
+   */
+  double   _alt_locerr;
+    /**
+   * @brief Nominal cross track location error
+   */
+  double   _crt_locerr;
+    /**
+   * @brief Nominal along track distortion scale
+   */
+  double   _alt_scale;
+    /**
+   * @brief Nominal cross track distortion scale
+   */
+  double   _crt_scale;
+    /**
+   * @brief Nominal distortion skew
+   */
+  double   _dis_skew;
+    /**
+   * @brief Nominal Scene orientation error
+   */
+  double   _ori_err;
+  /**
+   * @brief Misregistration error
+   */
+  MisregistrationRecord _misreg[16];
+    /**
+   * @brief Nominal noise equivalent sigma zero
+   */
+  double   _nesz;
+    /**
+   * @brief Nominal equivalent number of looks
+   */
+  double   _enl;
+    /**
+   * @brief Default parameters table update date
+   */
+  std::string   _tb_update;
+
+private:
+
+
+};
+}
+#endif
+
diff --git a/ossim_plugins/ossim/RadarSat/CommonRecord/DataSetSummary.cpp b/ossim_plugins/ossim/RadarSat/CommonRecord/DataSetSummary.cpp
new file mode 100755
index 0000000..2f5bc30
--- /dev/null
+++ b/ossim_plugins/ossim/RadarSat/CommonRecord/DataSetSummary.cpp
@@ -0,0 +1,775 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include "DataSetSummary.h"
+
+namespace ossimplugins
+{
+DataSetSummary::DataSetSummary() : RadarSatRecord("dataset_sum_rec")
+{
+}
+
+DataSetSummary::~DataSetSummary()
+{
+}
+
+std::ostream& operator<<(std::ostream& os, const DataSetSummary& data)
+{
+	os<<"seq_num:"<<data._seq_num<<std::endl;
+
+	os<<"sar_chn:"<<data._sar_chn<<std::endl;
+
+	os<<"scene_id:"<<data._scene_id.c_str()<<std::endl;
+
+	os<<"scene_des:"<<data._scene_des.c_str()<<std::endl;
+
+	os<<"inp_sctim:"<<data._inp_sctim.c_str()<<std::endl;
+
+	os<<"asc_des:"<<data._asc_des.c_str()<<std::endl;
+
+	os<<"pro_lat:"<<data._pro_lat<<std::endl;
+
+    os<<"pro_long:"<<data._pro_long<<std::endl;
+
+    os<<"pro_head:"<<data._pro_head<<std::endl;
+
+	os<<"ellip_des:"<<data._ellip_des.c_str()<<std::endl;
+
+	os<<"ellip_maj:"<<data._ellip_maj<<std::endl;
+
+	os<<"ellip_min:"<<data._ellip_min<<std::endl;
+	os<<"earth_mass:"<<data._earth_mass<<std::endl;
+    os<<"grav_const:"<<data._grav_const<<std::endl;
+    os<<"ellip_j[0]:"<<data._ellip_j[0]<<std::endl;
+	os<<"ellip_j[1]:"<<data._ellip_j[1]<<std::endl;
+	os<<"ellip_j[2]:"<<data._ellip_j[2]<<std::endl;
+    os<<"terrain_h:"<<data._terrain_h<<std::endl;
+    os<<"sc_lin:"<<data._sc_lin<<std::endl;
+    os<<"sc_pix:"<<data._sc_pix<<std::endl;
+    os<<"scene_len:"<<data._scene_len<<std::endl;
+    os<<"scene_wid:"<<data._scene_wid<<std::endl;
+    os<<"nchn:"<<data._nchn<<std::endl;
+    os<<"mission_id:"<<data._mission_id.c_str()<<std::endl;
+    os<<"sensor_id:"<<data._sensor_id.c_str()<<std::endl;
+    os<<"orbit_num:"<<data._orbit_num.c_str()<<std::endl;
+
+	os<<"plat_lat:"<<data._plat_lat<<std::endl;
+
+    os<<"plat_long:"<<data._plat_long<<std::endl;
+
+    os<<"plat_head:"<<data._plat_head<<std::endl;
+
+    os<<"clock_ang:"<<data._clock_ang<<std::endl;
+
+    os<<"incident_ang:"<<data._incident_ang<<std::endl;
+
+
+    os<<"wave_length:"<<data._wave_length<<std::endl;
+
+	os<<"motion_comp:"<<data._motion_comp.c_str()<<std::endl;
+
+	os<<"pulse_code:"<<data._pulse_code.c_str()<<std::endl;
+
+	for (int i=0;i<5;i++)
+	{
+		os<<"ampl_coef["<<i<<"]:"<<data._ampl_coef[i]<<std::endl;
+	}
+
+    for (int i=0;i<5;i++)
+	{
+		os<<"phas_coef["<<i<<"]:"<<data._phas_coef[i]<<std::endl;
+	}
+
+	os<<"chirp_ext_ind:"<<data._chirp_ext_ind<<std::endl;
+
+	os<<"fr:"<<data._fr<<std::endl;
+
+    os<<"rng_gate:"<<data._rng_gate<<std::endl;
+
+    os<<"rng_length:"<<data._rng_length<<std::endl;
+
+    os<<"baseband_f:"<<data._baseband_f.c_str()<<std::endl;
+
+    os<<"rngcmp_f:"<<data._rngcmp_f.c_str()<<std::endl;
+
+	os<<"gn_polar:"<<data._gn_polar <<std::endl;
+
+    os<<"gn_cross:"<<data._gn_cross <<std::endl;
+
+    os<<"chn_bits:"<<data._chn_bits<<std::endl;
+
+    os<<"quant_desc:"<<data._quant_desc.c_str()<<std::endl;
+
+    os<<"i_bias:"<<data._i_bias<<std::endl;
+
+    os<<"q_bias:"<<data._q_bias<<std::endl;
+
+    os<<"iq_ratio:"<<data._iq_ratio<<std::endl;
+
+    os<<"ele_sight:"<<data._ele_sight<<std::endl;
+
+    os<<"mech_sight:"<<data._mech_sight<<std::endl;
+
+    os<<"echo_track:"<<data._echo_track.c_str()<<std::endl;
+
+    os<<"fa:"<<data._fa<<std::endl;
+
+    os<<"elev_beam:"<<data._elev_beam<<std::endl;
+
+    os<<"azim_beam:"<<data._azim_beam<<std::endl;
+
+    os<<"sat_bintim:"<<data._sat_bintim<<std::endl;
+
+    os<<"sat_clktim:"<<data._sat_clktim<<std::endl;
+
+    os<<"sat_clkinc:"<<data._sat_clkinc<<std::endl;
+
+    os<<"fac_id:"<<data._fac_id.c_str()<<std::endl;
+
+    os<<"sys_id:"<<data._sys_id.c_str()<<std::endl;
+
+    os<<"ver_id:"<<data._ver_id.c_str()<<std::endl;
+
+    os<<"fac_code:"<<data._fac_code.c_str()<<std::endl;
+
+    os<<"lev_code:"<<data._lev_code.c_str()<<std::endl;
+
+    os<<"prod_type:"<<data._prod_type.c_str()<<std::endl;
+
+    os<<"algor_id:"<<data._algor_id.c_str()<<std::endl;
+
+    os<<"n_azilok:"<<data._n_azilok<<std::endl;
+
+    os<<"n_rnglok:"<<data._n_rnglok<<std::endl;
+
+    os<<"bnd_azilok:"<<data._bnd_azilok<<std::endl;
+
+    os<<"bnd_rnglok:"<<data._bnd_rnglok<<std::endl;
+
+    os<<"bnd_azi:"<<data._bnd_azi<<std::endl;
+
+    os<<"bnd_rng:"<<data._bnd_rng<<std::endl;
+
+    os<<"azi_weight:"<<data._azi_weight.c_str()<<std::endl;
+
+    os<<"rng_weight:"<<data._rng_weight.c_str()<<std::endl;
+
+    os<<"data_inpsrc:"<<data._data_inpsrc.c_str()<<std::endl;
+
+    os<<"rng_res:"<<data._rng_res<<std::endl;
+
+    os<<"azi_res:"<<data._azi_res<<std::endl;
+
+	os<<"radi_stretch[0]:"<<data._radi_stretch[0]<<std::endl;
+	os<<"radi_stretch[1]:"<<data._radi_stretch[1]<<std::endl;
+
+	os<<"alt_dopcen[0]:"<<data._alt_dopcen[0]<<std::endl;
+	os<<"alt_dopcen[1]:"<<data._alt_dopcen[1]<<std::endl;
+	os<<"alt_dopcen[2]:"<<data._alt_dopcen[2]<<std::endl;
+
+    os<<"crt_dopcen[0]:"<<data._crt_dopcen[0]<<std::endl;
+	os<<"crt_dopcen[1]:"<<data._crt_dopcen[1]<<std::endl;
+	os<<"crt_dopcen[2]:"<<data._crt_dopcen[2]<<std::endl;
+
+    os<<"time_dir_pix:"<<data._time_dir_pix.c_str()<<std::endl;
+
+	os<<"time_dir_lin:"<<data._time_dir_lin.c_str()<<std::endl;
+
+    os<<"alt_rate[0]:"<<data._alt_rate[0]<<std::endl;
+	os<<"alt_rate[1]:"<<data._alt_rate[1]<<std::endl;
+	os<<"alt_rate[2]:"<<data._alt_rate[2]<<std::endl;
+
+    os<<"crt_rate[0]:"<<data._crt_rate[0]<<std::endl;
+	os<<"crt_rate[1]:"<<data._crt_rate[1]<<std::endl;
+	os<<"crt_rate[2]:"<<data._crt_rate[2]<<std::endl;
+
+    os<<"clutter_lock:"<<data._line_cont.c_str()<<std::endl;
+
+    os<<"clutter_lock:"<<data._clutter_lock.c_str()<<std::endl;
+
+    os<<"auto_focus:"<<data._auto_focus.c_str()<<std::endl;
+
+    os<<"line_spacing:"<<data._line_spacing<<std::endl;
+
+    os<<"pix_spacing:"<<data._pix_spacing<<std::endl;
+
+    os<<"rngcmp_desg:"<<data._rngcmp_desg.c_str()<<std::endl;
+
+	return os;
+
+}
+
+std::istream& operator>>(std::istream& is, DataSetSummary& data)
+{
+	char buf16[17];
+	buf16[16]='\0';
+	char buf32[33];
+	buf32[32] = '\0';
+	char buf8[9];
+	buf8[8] = '\0';
+	char buf4[5];
+	buf4[4] = '\0';
+
+	is.read(buf4,4);
+	data._seq_num = atoi(buf4);
+
+	is.read(buf4,4);
+	data._sar_chn = atoi(buf4);
+
+	is.read(buf16,16);
+	data._scene_id = buf16;
+
+	is.read(buf32,32);
+	data._scene_des = buf32;
+
+	is.read(buf32,32);
+	data._inp_sctim = buf32;
+
+	is.read(buf16,16);
+	data._asc_des = buf16;
+
+	is.read(buf16,16);
+	data._pro_lat = atof(buf16);
+
+    is.read(buf16,16);
+	data._pro_long = atof(buf16);
+
+    is.read(buf16,16);
+	data._pro_head = atof(buf16);
+
+	is.read(buf16,16);
+	data._ellip_des = buf16;
+
+	is.read(buf16,16);
+	data._ellip_maj = atof(buf16);
+
+	is.read(buf16,16);
+	data._ellip_min = atof(buf16);
+
+	is.read(buf16,16);
+	data._earth_mass = atof(buf16);
+
+    is.read(buf16,16);
+	data._grav_const = atof(buf16);
+
+	is.read(buf16,16);
+	data._ellip_j[0] = atof(buf16);
+	is.read(buf16,16);
+	data._ellip_j[1] = atof(buf16);
+	is.read(buf16,16);
+	data._ellip_j[2] = atof(buf16);
+
+    is.read(buf16,16);
+
+    is.read(buf16,16);
+	data._terrain_h = atof(buf16);
+
+	is.read(buf8,8);
+	data._sc_lin = atoi(buf8);
+
+	is.read(buf8,8);
+	data._sc_pix = atoi(buf8);
+
+	is.read(buf16,16);
+	data._scene_len = atof(buf16);
+
+	is.read(buf16,16);
+	data._scene_wid = atof(buf16);
+
+	is.read(buf16,16);
+
+	is.read(buf4,4);
+	data._nchn = atoi(buf4);
+
+	is.read(buf4,4);
+
+	is.read(buf16,16);
+	data._mission_id = buf16;
+
+	is.read(buf32,32);
+	data._sensor_id = buf32;
+
+	is.read(buf8,8);
+	data._orbit_num = buf8;
+
+	is.read(buf8,8);
+	data._plat_lat = atof(buf8);
+
+    is.read(buf8,8);
+	data._plat_long = atof(buf8);
+
+    is.read(buf8,8);
+	data._plat_head = atof(buf8);
+
+    is.read(buf8,8);
+	data._clock_ang = atof(buf8);
+
+    is.read(buf8,8);
+	data._incident_ang = atof(buf8);
+
+    is.read(buf8,8);
+
+	is.read(buf16,16);
+	data._wave_length = atof(buf16);
+
+	is.read(buf8,2);
+	buf8[2] = '\0';
+	data._motion_comp = buf8;
+
+	is.read(buf16,16);
+	data._pulse_code = buf16;
+
+	for (int i=0;i<5;i++)
+	{
+		is.read(buf16,16);
+		data._ampl_coef[i] = atof(buf16);
+	}
+
+    for (int i=0;i<5;i++)
+	{
+		is.read(buf16,16);
+		data._phas_coef[i] = atof(buf16);
+	}
+
+    is.read(buf8,8);
+	data._chirp_ext_ind = atoi(buf8);
+
+    is.read(buf8,8);
+
+    is.read(buf16,16);
+	data._fr = atof(buf16);
+
+    is.read(buf16,16);
+	data._rng_gate = atof(buf16);
+
+    is.read(buf16,16);
+	data._rng_length = atof(buf16);
+
+    is.read(buf8,4);
+	buf8[4] = '\0';
+	data._baseband_f = buf8;
+
+    is.read(buf8,4);
+	buf8[4] = '\0';
+	data._rngcmp_f = buf8;
+
+	is.read(buf16,16);
+	data._gn_polar = atof(buf16);
+
+    is.read(buf16,16);
+	data._gn_cross = atof(buf16);
+
+    is.read(buf8,8);
+	data._chn_bits = atoi(buf8);
+
+    is.read(buf16,12);
+	buf16[12] = '\0';
+	data._quant_desc = buf16;
+
+    is.read(buf16,16);
+	data._i_bias = atof(buf16);
+
+    is.read(buf16,16);
+	data._q_bias = atof(buf16);
+
+    is.read(buf16,16);
+	data._iq_ratio = atof(buf16);
+
+    is.read(buf16,16);
+
+    is.read(buf16,16);
+
+    is.read(buf16,16);
+	data._ele_sight = atof(buf16);
+
+    is.read(buf16,16);
+	data._mech_sight = atof(buf16);
+
+    is.read(buf4,4);
+	data._echo_track = buf4;
+
+    is.read(buf16,16);
+	data._fa = atof(buf16);
+
+    is.read(buf16,16);
+	data._elev_beam = atof(buf16);
+
+    is.read(buf16,16);
+	data._azim_beam = atof(buf16);
+
+    is.read(buf16,16);
+	data._sat_bintim = atoi(buf16);
+
+    is.read(buf32,32);
+	data._sat_clktim = atoi(buf32);
+
+    is.read(buf8,8);
+	data._sat_clkinc = atoi(buf8);
+
+    is.read(buf8,8);
+
+    is.read(buf16,16);
+	data._fac_id = buf16;
+
+    is.read(buf8,8);
+	data._sys_id = buf8;
+
+    is.read(buf8,8);
+	data._ver_id = buf8;
+
+    is.read(buf16,16);
+	data._fac_code = buf16;
+
+    is.read(buf16,16);
+	data._lev_code = buf16;
+
+    is.read(buf32,32);
+	data._prod_type = buf32;
+
+    is.read(buf32,32);
+	data._algor_id = buf32;
+
+    is.read(buf16,16);
+	data._n_azilok = atof(buf16);
+
+    is.read(buf16,16);
+	data._n_rnglok = atof(buf16);
+
+    is.read(buf16,16);
+	data._bnd_azilok = atof(buf16);
+
+    is.read(buf16,16);
+	data._bnd_rnglok = atof(buf16);
+
+    is.read(buf16,16);
+	data._bnd_azi = atof(buf16);
+
+    is.read(buf16,16);
+	data._bnd_rng = atof(buf16);
+
+    is.read(buf32,32);
+	data._azi_weight = buf32;
+
+    is.read(buf32,32);
+	data._rng_weight = buf32;
+
+    is.read(buf16,16);
+	data._data_inpsrc = buf16;
+
+    is.read(buf16,16);
+	data._rng_res = atof(buf16);
+
+    is.read(buf16,16);
+	data._azi_res = atof(buf16);
+
+	is.read(buf16,16);
+	data._radi_stretch[0] = atof(buf16);
+	is.read(buf16,16);
+	data._radi_stretch[1] = atof(buf16);
+
+	is.read(buf16,16);
+	data._alt_dopcen[0] = atof(buf16);
+	is.read(buf16,16);
+	data._alt_dopcen[1] = atof(buf16);
+	is.read(buf16,16);
+	data._alt_dopcen[2] = atof(buf16);
+
+    is.read(buf16,16);
+
+    is.read(buf16,16);
+	data._crt_dopcen[0] = atof(buf16);
+	is.read(buf16,16);
+	data._crt_dopcen[1] = atof(buf16);
+	is.read(buf16,16);
+	data._crt_dopcen[2] = atof(buf16);
+
+    is.read(buf8,8);
+	data._time_dir_pix = buf8;
+
+	is.read(buf8,8);
+	data._time_dir_lin = buf8;
+
+    is.read(buf16,16);
+	data._alt_rate[0] = atof(buf16);
+	is.read(buf16,16);
+	data._alt_rate[1] = atof(buf16);
+	is.read(buf16,16);
+	data._alt_rate[2] = atof(buf16);
+
+    is.read(buf16,16);
+
+    is.read(buf16,16);
+	data._crt_rate[0] = atof(buf16);
+	is.read(buf16,16);
+	data._crt_rate[1] = atof(buf16);
+	is.read(buf16,16);
+	data._crt_rate[2] = atof(buf16);
+
+    is.read(buf16,16);
+
+    is.read(buf8,8);
+	data._line_cont = buf8;
+
+    is.read(buf4,4);
+	data._clutter_lock = buf4;
+
+    is.read(buf4,4);
+	data._auto_focus = buf4;
+
+    is.read(buf16,16);
+	data._line_spacing = atof(buf16);
+
+    is.read(buf16,16);
+	data._pix_spacing = atof(buf16);
+
+    is.read(buf16,16);
+	data._rngcmp_desg = buf16;
+
+    char buf[2363];
+	buf[2362] = '\0';
+
+	is.read(buf,2362);
+
+	return is;
+}
+
+
+DataSetSummary::DataSetSummary(const DataSetSummary& rhs):
+	RadarSatRecord(rhs),
+	_seq_num(rhs._seq_num),
+    _sar_chn(rhs._sar_chn),
+	_scene_id(rhs._scene_id),
+	_scene_des(rhs._scene_des),
+	_inp_sctim(rhs._inp_sctim),
+	_asc_des(rhs._asc_des),
+    _pro_lat(rhs._pro_lat),
+    _pro_long(rhs._pro_long),
+    _pro_head(rhs._pro_head),
+	_ellip_des(rhs._ellip_des),
+    _ellip_maj(rhs._ellip_maj),
+    _ellip_min(rhs._ellip_min),
+	_earth_mass(rhs._earth_mass),
+    _grav_const(rhs._grav_const),
+    _terrain_h(rhs._terrain_h),
+    _sc_lin(rhs._sc_lin),
+    _sc_pix(rhs._sc_pix),
+    _scene_len(rhs._scene_len),
+    _scene_wid(rhs._scene_wid),
+    _nchn(rhs._nchn),
+    _mission_id(rhs._mission_id),
+    _sensor_id(rhs._sensor_id),
+    _orbit_num(rhs._orbit_num),
+    _plat_lat(rhs._plat_lat),
+    _plat_long(rhs._plat_long),
+    _plat_head(rhs._plat_head),
+    _clock_ang(rhs._clock_ang),
+    _incident_ang(rhs._incident_ang),
+    _wave_length(rhs._wave_length),
+    _motion_comp(rhs._motion_comp),
+    _pulse_code(rhs._pulse_code),
+    _chirp_ext_ind(rhs._chirp_ext_ind),
+    _fr(rhs._fr),
+    _rng_gate(rhs._rng_gate),
+    _rng_length(rhs._rng_length),
+    _baseband_f(rhs._baseband_f),
+    _rngcmp_f(rhs._rngcmp_f),
+    _gn_polar(rhs._gn_polar),
+    _gn_cross(rhs._gn_cross),
+    _chn_bits(rhs._chn_bits),
+    _quant_desc(rhs._quant_desc),
+    _i_bias(rhs._i_bias),
+    _q_bias(rhs._q_bias),
+    _iq_ratio(rhs._iq_ratio),
+    _ele_sight(rhs._ele_sight),
+    _mech_sight(rhs._mech_sight),
+    _echo_track(rhs._echo_track),
+    _fa(rhs._fa),
+    _elev_beam(rhs._elev_beam),
+    _azim_beam(rhs._azim_beam),
+    _sat_bintim(rhs._sat_bintim),
+    _sat_clktim(rhs._sat_clktim),
+    _sat_clkinc(rhs._sat_clkinc),
+    _fac_id(rhs._fac_id),
+    _sys_id(rhs._sys_id),
+    _ver_id(rhs._ver_id),
+    _fac_code(rhs._fac_code),
+    _lev_code(rhs._lev_code),
+    _prod_type(rhs._prod_type),
+    _algor_id(rhs._algor_id),
+    _n_azilok(rhs._n_azilok),
+    _n_rnglok(rhs._n_rnglok),
+    _bnd_azilok(rhs._bnd_azilok),
+    _bnd_rnglok(rhs._bnd_rnglok),
+    _bnd_azi(rhs._bnd_azi),
+    _bnd_rng(rhs._bnd_rng),
+    _azi_weight(rhs._azi_weight),
+    _rng_weight(rhs._rng_weight),
+    _data_inpsrc(rhs._data_inpsrc),
+    _rng_res(rhs._rng_res),
+    _azi_res(rhs._azi_res),
+    _time_dir_pix(rhs._time_dir_pix),
+    _time_dir_lin(rhs._time_dir_lin),
+    _line_cont(rhs._line_cont),
+    _clutter_lock(rhs._clutter_lock),
+    _auto_focus(rhs._auto_focus),
+    _line_spacing(rhs._line_spacing),
+    _pix_spacing(rhs._pix_spacing),
+    _rngcmp_desg(rhs._rngcmp_desg)
+{
+	_ellip_j[0] = rhs._ellip_j[0];
+	_ellip_j[1] = rhs._ellip_j[1];
+	_ellip_j[2] = rhs._ellip_j[2];
+	_ampl_coef[0] = rhs._ampl_coef[0];
+	_ampl_coef[1] = rhs._ampl_coef[1];
+	_ampl_coef[2] = rhs._ampl_coef[2];
+	_ampl_coef[3] = rhs._ampl_coef[3];
+	_ampl_coef[4] = rhs._ampl_coef[4];
+    _phas_coef[0] = rhs._phas_coef[0];
+	_phas_coef[1] = rhs._phas_coef[1];
+	_phas_coef[2] = rhs._phas_coef[2];
+	_phas_coef[3] = rhs._phas_coef[3];
+	_phas_coef[4] = rhs._phas_coef[4];
+
+	_radi_stretch[0] = rhs._radi_stretch[0];
+	_radi_stretch[1] = rhs._radi_stretch[1];
+    _alt_dopcen[0] = rhs._alt_dopcen[0];
+	_alt_dopcen[1] = rhs._alt_dopcen[1];
+	_alt_dopcen[2] = rhs._alt_dopcen[2];
+
+	_crt_dopcen[0] = rhs._crt_dopcen[0];
+	_crt_dopcen[1] = rhs._crt_dopcen[1];
+	_crt_dopcen[2] = rhs._crt_dopcen[2];
+
+	_alt_rate[0] = rhs._alt_rate[0];
+	_alt_rate[1] = rhs._alt_rate[1];
+	_alt_rate[2] = rhs._alt_rate[2];
+	_crt_rate[0] = rhs._crt_rate[0];
+	_crt_rate[1] = rhs._crt_rate[1];
+	_crt_rate[2] = rhs._crt_rate[2];
+}
+
+DataSetSummary& DataSetSummary::operator=(const DataSetSummary& rhs)
+{
+	_seq_num = rhs._seq_num;
+    _sar_chn = rhs._sar_chn;
+	_scene_id = rhs._scene_id;
+	_scene_des = rhs._scene_des;
+	_inp_sctim = rhs._inp_sctim;
+	_asc_des = rhs._asc_des;
+    _pro_lat = rhs._pro_lat;
+    _pro_long = rhs._pro_long;
+    _pro_head = rhs._pro_head;
+	_ellip_des = rhs._ellip_des;
+    _ellip_maj = rhs._ellip_maj;
+    _ellip_min = rhs._ellip_min;
+	_earth_mass = rhs._earth_mass;
+    _grav_const = rhs._grav_const;
+    _terrain_h = rhs._terrain_h;
+    _sc_lin = rhs._sc_lin;
+    _sc_pix = rhs._sc_pix;
+    _scene_len = rhs._scene_len;
+    _scene_wid = rhs._scene_wid;
+    _nchn = rhs._nchn;
+    _mission_id = rhs._mission_id;
+    _sensor_id = rhs._sensor_id;
+    _orbit_num = rhs._orbit_num;
+    _plat_lat = rhs._plat_lat;
+    _plat_long = rhs._plat_long;
+    _plat_head = rhs._plat_head;
+    _clock_ang = rhs._clock_ang;
+    _incident_ang = rhs._incident_ang;
+    _wave_length = rhs._wave_length;
+    _motion_comp = rhs._motion_comp;
+    _pulse_code = rhs._pulse_code;
+    _chirp_ext_ind = rhs._chirp_ext_ind;
+    _fr = rhs._fr;
+    _rng_gate = rhs._rng_gate;
+    _rng_length = rhs._rng_length;
+    _baseband_f = rhs._baseband_f;
+    _rngcmp_f = rhs._rngcmp_f;
+    _gn_polar = rhs._gn_polar;
+    _gn_cross = rhs._gn_cross;
+    _chn_bits = rhs._chn_bits;
+    _quant_desc = rhs._quant_desc;
+    _i_bias = rhs._i_bias;
+    _q_bias = rhs._q_bias;
+    _iq_ratio = rhs._iq_ratio;
+    _ele_sight = rhs._ele_sight;
+    _mech_sight = rhs._mech_sight;
+    _echo_track = rhs._echo_track;
+    _fa = rhs._fa;
+    _elev_beam = rhs._elev_beam;
+    _azim_beam = rhs._azim_beam;
+    _sat_bintim = rhs._sat_bintim;
+    _sat_clktim = rhs._sat_clktim;
+    _sat_clkinc = rhs._sat_clkinc;
+    _fac_id = rhs._fac_id;
+    _sys_id = rhs._sys_id;
+    _ver_id = rhs._ver_id;
+    _fac_code = rhs._fac_code;
+    _lev_code = rhs._lev_code;
+    _prod_type = rhs._prod_type;
+    _algor_id = rhs._algor_id;
+    _n_azilok = rhs._n_azilok;
+    _n_rnglok = rhs._n_rnglok;
+    _bnd_azilok = rhs._bnd_azilok;
+    _bnd_rnglok = rhs._bnd_rnglok;
+    _bnd_azi = rhs._bnd_azi;
+    _bnd_rng = rhs._bnd_rng;
+    _azi_weight = rhs._azi_weight;
+    _rng_weight = rhs._rng_weight;
+    _data_inpsrc = rhs._data_inpsrc;
+    _rng_res = rhs._rng_res;
+    _azi_res = rhs._azi_res;
+    _time_dir_pix = rhs._time_dir_pix;
+    _time_dir_lin = rhs._time_dir_lin;
+    _line_cont = rhs._line_cont;
+    _clutter_lock = rhs._clutter_lock;
+    _auto_focus = rhs._auto_focus;
+    _line_spacing = rhs._line_spacing;
+    _pix_spacing = rhs._pix_spacing;
+    _rngcmp_desg = rhs._rngcmp_desg;
+
+	_ellip_j[0] = rhs._ellip_j[0];
+	_ellip_j[1] = rhs._ellip_j[1];
+	_ellip_j[2] = rhs._ellip_j[2];
+	_ampl_coef[0] = rhs._ampl_coef[0];
+	_ampl_coef[1] = rhs._ampl_coef[1];
+	_ampl_coef[2] = rhs._ampl_coef[2];
+	_ampl_coef[3] = rhs._ampl_coef[3];
+	_ampl_coef[4] = rhs._ampl_coef[4];
+    _phas_coef[0] = rhs._phas_coef[0];
+	_phas_coef[1] = rhs._phas_coef[1];
+	_phas_coef[2] = rhs._phas_coef[2];
+	_phas_coef[3] = rhs._phas_coef[3];
+	_phas_coef[4] = rhs._phas_coef[4];
+
+	_radi_stretch[0] = rhs._radi_stretch[0];
+	_radi_stretch[1] = rhs._radi_stretch[1];
+    _alt_dopcen[0] = rhs._alt_dopcen[0];
+	_alt_dopcen[1] = rhs._alt_dopcen[1];
+	_alt_dopcen[2] = rhs._alt_dopcen[2];
+
+	_crt_dopcen[0] = rhs._crt_dopcen[0];
+	_crt_dopcen[1] = rhs._crt_dopcen[1];
+	_crt_dopcen[2] = rhs._crt_dopcen[2];
+
+	_alt_rate[0] = rhs._alt_rate[0];
+	_alt_rate[1] = rhs._alt_rate[1];
+	_alt_rate[2] = rhs._alt_rate[2];
+	_crt_rate[0] = rhs._crt_rate[0];
+	_crt_rate[1] = rhs._crt_rate[1];
+	_crt_rate[2] = rhs._crt_rate[2];
+	return *this;
+}
+}
+
+
diff --git a/ossim_plugins/ossim/RadarSat/CommonRecord/DataSetSummary.h b/ossim_plugins/ossim/RadarSat/CommonRecord/DataSetSummary.h
new file mode 100755
index 0000000..3da07aa
--- /dev/null
+++ b/ossim_plugins/ossim/RadarSat/CommonRecord/DataSetSummary.h
@@ -0,0 +1,1076 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef DataSetSummary_h
+#define DataSetSummary_h
+
+#include <iostream>
+#include <RadarSat/RadarSatRecordHeader.h>
+#include <RadarSat/RadarSatRecord.h>
+
+namespace ossimplugins
+{
+/**
+ * @ingroup DataSetSummaryRecord
+ * @brief This class is able to read the SAR leader data set summary record of the leader file
+ */
+class DataSetSummary : public RadarSatRecord
+{
+public:
+  /**
+   * @brief Constructor
+   */
+  DataSetSummary();
+
+  /**
+   * @brief Destructor
+   */
+  virtual ~DataSetSummary();
+
+  /**
+   * @brief This function write the DataSetSummary in a stream
+   */
+  friend std::ostream& operator<<(std::ostream& os, const DataSetSummary& data);
+
+  /**
+   * @brief This function read a DataSetSummary from a stream
+   */
+  friend std::istream& operator>>(std::istream& is, DataSetSummary& data);
+
+  /**
+   * @brief Copy constructor
+   */
+  DataSetSummary(const DataSetSummary& rhs);
+
+  /**
+   * @brief Copy operator
+   */
+  DataSetSummary& operator=(const DataSetSummary& rhs);
+
+  /**
+   * @brief This function is able to create a new instance of the class
+   */
+  RadarSatRecord* Instanciate()
+  {
+    return new DataSetSummary();
+  };
+
+  /**
+   * @brief This function is able to create a new instance of the class initialised with the data of the calling instance
+   */
+  RadarSatRecord* Clone()
+  {
+    return new DataSetSummary(*this);
+  };
+
+  /**
+   * @brief Reads the class data from a stream
+   */
+  void Read(std::istream& is)
+  {
+    is>>*this;
+  };
+
+  /**
+   * @brief Writes the class to a stream
+   */
+  void Write(std::ostream& os)
+  {
+    os<<*this;
+  };
+
+  /**
+   * @brief Sequence number
+   */
+  int   get_seq_num()
+  {
+    return _seq_num;
+  };
+    /**
+   * @brief SAR channel indicator
+   */
+  int   get_sar_chn()
+  {
+    return _sar_chn;
+  };
+  /**
+   * @brief Scene identifier
+   */
+  std::string   get_scene_id()
+  {
+    return _scene_id;
+  };
+  /**
+   * @brief Scene designator
+   */
+  std::string   get_scene_des()
+  {
+    return _scene_des;
+  };
+  /**
+   * @brief Input scene centre time
+   */
+  std::string   get_inp_sctim()
+  {
+    return _inp_sctim;
+  };
+  /**
+   * @brief Ascending/descending
+   */
+  std::string   get_asc_des()
+  {
+    return _asc_des;
+  };
+    /**
+   * @brief Processed scene centre latitude
+   */
+  double   get_pro_lat()
+  {
+    return _pro_lat;
+  };
+    /**
+   * @brief Processed scene centre longitude
+   */
+  double   get_pro_long()
+  {
+    return _pro_long;
+  };
+    /**
+   * @brief Processed scene centre headng
+   */
+  double   get_pro_head()
+  {
+    return _pro_head;
+  };
+  /**
+   * @brief Ellipsoid designator
+   */
+  std::string   get_ellip_des()
+  {
+    return _ellip_des;
+  };
+    /**
+   * @brief Ellipsoid semi-major axis, km
+   */
+  double   get_ellip_maj()
+  {
+    return _ellip_maj;
+  };
+    /**
+   * @brief Ellipsoid semi_minor axis, km
+   */
+  double  get_ellip_min()
+  {
+    return _ellip_min;
+  };
+  /**
+   * @brief Earth's mass
+   */
+    double   get_earth_mass()
+  {
+    return _earth_mass;
+  };
+    /**
+   * @brief Gravitational constant
+   */
+    double   get_grav_const()
+  {
+    return _grav_const;
+  };
+    /**
+   * @brief Ellipsoid J2-4 parameters
+   */
+    double*   get_ellip_j()
+  {
+    return _ellip_j;
+  };
+
+    /**
+   * @brief Average terrain height, km
+   */
+    double   get_terrain_h()
+  {
+    return _terrain_h;
+  };
+    /**
+   * @brief Scene centre line number
+   */
+    int   get_sc_lin()
+  {
+    return _sc_lin;
+  };
+    /**
+   * @brief Scene centre pixel number
+   */
+    int   get_sc_pix()
+  {
+    return _sc_pix;
+  };
+    /**
+   * @brief Scene length, km
+   */
+    double   get_scene_len()
+  {
+    return _scene_len;
+  };
+    /**
+   * @brief Scene width, km
+   */
+    double   get_scene_wid()
+  {
+    return _scene_wid;
+  };
+
+    /**
+   * @brief Number of SAR channels
+   */
+    double   get_nchn()
+  {
+    return _nchn;
+  };
+
+    /**
+   * @brief Mission identifier
+   */
+  std::string   get_mission_id()
+  {
+    return _mission_id;
+  };
+    /**
+   * @brief Sensor identifier
+   */
+  std::string   get_sensor_id()
+  {
+    return _sensor_id;
+  };
+    /**
+   * @brief Orbit number
+   */
+  std::string   get_orbit_num()
+  {
+    return _orbit_num;
+  };
+    /**
+   * @brief Platform geodetic latitude
+   */
+    double   get_plat_lat()
+  {
+    return _plat_lat;
+  };
+    /**
+   * @brief Platform geodetic longitude
+   */
+    double   get_plat_long()
+  {
+    return _plat_long;
+  };
+    /**
+   * @brief Platform heading
+   */
+    double   get_plat_head()
+  {
+    return _plat_head;
+  };
+    /**
+   * @brief Sensor clock angle
+   */
+    double   get_clock_ang()
+  {
+    return _clock_ang;
+  };
+    /**
+   * @brief Incidence angle
+   */
+    double   get_incident_ang()
+  {
+    return _incident_ang;
+  };
+
+    /**
+   * @brief Radar wave length
+   */
+    double   get_wave_length()
+  {
+    return _wave_length;
+  };
+    /**
+   * @brief Motion compensation indicator
+   */
+  std::string   get_motion_comp()
+  {
+    return _motion_comp;
+  };
+    /**
+   * @brief Range pulse code specifier
+   */
+    std::string   get_pulse_code()
+  {
+    return _pulse_code;
+  };
+    /**
+   * @brief Range chirp coefficients
+   */
+    double*   get_ampl_coef()
+  {
+    return _ampl_coef;
+  };
+    /**
+   * @brief Range phase coefficients
+   */
+    double*   get_phas_coef()
+  {
+    return _phas_coef;
+  };
+    /**
+   * @brief Chirp extraction index
+   */
+    int   get_chirp_ext_ind()
+  {
+    return _chirp_ext_ind;
+  };
+
+    /**
+   * @brief Range sampling rate
+   */
+    double   get_fr()
+  {
+    return _fr;
+  };
+    /**
+   * @brief Range gate start time
+   */
+    double   get_rng_gate()
+  {
+    return _rng_gate;
+  };
+    /**
+   * @brief Range pulse length
+   */
+    double   get_rng_length()
+  {
+    return _rng_length;
+  };
+    /**
+   * @brief Baseband conversion flag
+   */
+  std::string   get_baseband_f()
+  {
+    return _baseband_f;
+  };
+    /**
+   * @brief Range compressed flag
+   */
+    std::string   get_rngcmp_f()
+  {
+    return _rngcmp_f;
+  };
+    /**
+   * @brief Like polarized gain
+   */
+    double   get_gn_polar()
+  {
+    return _gn_polar;
+  };
+    /**
+   * @brief Cross polarized gain
+   */
+    double   get_gn_cross()
+  {
+    return _gn_cross;
+  };
+    /**
+   * @brief Number of bits per channel
+   */
+    int   get_chn_bits()
+  {
+    return _chn_bits;
+  };
+    /**
+   * @brief Quantization descriptor
+   */
+    std::string   get_quant_desc()
+  {
+    return _quant_desc;
+  };
+    /**
+   * @brief I channel DC bias
+   */
+    double   get_i_bias()
+  {
+    return _i_bias;
+  };
+    /**
+   * @brief Q channel DC bias
+   */
+    double   get_q_bias()
+  {
+    return _q_bias;
+  };
+    /**
+   * @brief I/Q channel ratio
+   */
+    double   get_iq_ratio()
+  {
+    return _iq_ratio;
+  };
+
+
+    /**
+   * @brief Electronic boresight
+   */
+    double   get_ele_sight()
+  {
+    return _ele_sight;
+  };
+    /**
+   * @brief Mechanical boresight
+   */
+    double   get_mech_sight()
+  {
+    return _mech_sight;
+  };
+    /**
+   * @brief Echo tracker on/off flag
+   */
+  std::string   get_echo_track()
+  {
+    return _echo_track;
+  };
+    /**
+   * @brief Nominal PRF, Hz
+   */
+    double   get_fa()
+  {
+    return _fa;
+  };
+    /**
+   * @brief Elevation beamwidth
+   */
+    double   get_elev_beam()
+  {
+    return _elev_beam;
+  };
+    /**
+   * @brief Azimuth beamwidth
+   */
+    double   get_azim_beam()
+  {
+    return _azim_beam;
+  };
+    /**
+   * @brief Satellite binary time
+   */
+    int   get_sat_bintim()
+  {
+    return _sat_bintim;
+  };
+    /**
+   * @brief Satellite clock time
+   */
+    int   get_sat_clktim()
+  {
+    return _sat_clktim;
+  };
+    /**
+   * @brief Satellite clock increment
+   */
+    int   get_sat_clkinc()
+  {
+    return _sat_clkinc;
+  };
+
+    /**
+   * @brief Processing facility identifier
+   */
+    std::string   get_fac_id()
+  {
+    return _fac_id;
+  };
+    /**
+   * @brief Processing system identifier
+   */
+    std::string   get_sys_id()
+  {
+    return _sys_id;
+  };
+    /**
+   * @brief Processing version identifier
+   */
+    std::string   get_ver_id()
+  {
+    return _ver_id;
+  };
+    /**
+   * @brief Facility process code
+   */
+    std::string   get_fac_code()
+  {
+    return _fac_code;
+  };
+    /**
+   * @brief Product level code
+   */
+    std::string   get_lev_code()
+  {
+    return _lev_code;
+  };
+    /**
+   * @brief Product type specifier
+   */
+    std::string   get_prod_type()
+  {
+    return _prod_type;
+  };
+    /**
+   * @brief Processing algorithm identifier
+   */
+    std::string   get_algor_id()
+  {
+    return _algor_id;
+  };
+    /**
+   * @brief Number of azimuth looks
+   */
+    double   get_n_azilok()
+  {
+    return _n_azilok;
+  };
+    /**
+   * @brief Number of range looks
+   */
+    double   get_n_rnglok()
+  {
+    return _n_rnglok;
+  };
+    /**
+   * @brief Bandwidth per look in azimuth,Hz
+   */
+    double   get_bnd_azilok()
+  {
+    return _bnd_azilok;
+  };
+    /**
+   * @brief Bandwidth per look in range,Hz
+   */
+    double   get_bnd_rnglok()
+  {
+    return _bnd_rnglok;
+  };
+    /**
+   * @brief Total azimuth look bandwidth
+   */
+    double   get_bnd_azi()
+  {
+    return _bnd_azi;
+  };
+    /**
+   * @brief Total range look bandwidth
+   */
+    double   get_bnd_rng()
+  {
+    return _bnd_rng;
+  };
+    /**
+   * @brief Azimuth weighting designator
+   */
+    std::string   get_azi_weight()
+  {
+    return _azi_weight;
+  };
+    /**
+   * @brief Range weighting designator
+   */
+    std::string   get_rng_weight()
+  {
+    return _rng_weight;
+  };
+    /**
+   * @brief Data input source
+   */
+    std::string   get_data_inpsrc()
+  {
+    return _data_inpsrc;
+  };
+    /**
+   * @brief Range resolution, meter
+   */
+    double   get_rng_res()
+  {
+    return _rng_res;
+  };
+    /**
+   * @brief Azimuth resolution, meter
+   */
+    double   get_azi_res()
+  {
+    return _azi_res;
+  };
+    /**
+   * @brief Radiometric stretch terms
+   */
+    double*   get_radi_stretch()
+  {
+    return _radi_stretch;
+  };
+    /**
+   * @brief Along track Doppler frequency terms
+   */
+    double*   get_alt_dopcen()
+  {
+    return _alt_dopcen;
+  };
+
+    /**
+   * @brief Cross track Doppler frequency terms
+   */
+    double*   get_crt_dopcen()
+  {
+    return _crt_dopcen;
+  };
+    /**
+   * @brief Pixel time direction indicator
+   */
+    std::string   get_time_dir_pix()
+  {
+    return _time_dir_pix;
+  };
+    /**
+   * @brief Line time direction indicator
+   */
+    std::string   get_time_dir_lin()
+  {
+    return _time_dir_lin;
+  };
+    /**
+   * @brief Along track Doppler rate term
+   */
+    double*   get_alt_rate()
+  {
+    return _alt_rate;
+  };
+
+    /**
+   * @brief Cross track Doppler rate term
+   */
+    double*   get_crt_rate()
+  {
+    return _crt_rate;
+  };
+
+    /**
+   * @brief Line content indicator
+   */
+    std::string   get_line_cont()
+  {
+    return _line_cont;
+  };
+    /**
+   * @brief Clutter lock applied flag
+   */
+    std::string   get_clutter_lock()
+  {
+    return _clutter_lock;
+  };
+    /**
+   * @brief Auto-focus applied flag
+   */
+    std::string   get_auto_focus()
+  {
+    return _auto_focus;
+  };
+    /**
+   * @brief Line spacing, meters
+   */
+    double   get_line_spacing()
+  {
+    return _line_spacing;
+  };
+    /**
+   * @brief Pixel spacing, meters
+   */
+    double   get_pix_spacing()
+  {
+    return _pix_spacing;
+  };
+    /**
+   * @brief Range compression designator
+   */
+    std::string   get_rngcmp_desg()
+  {
+    return _rngcmp_desg;
+  };
+
+protected:
+  /**
+   * @brief Sequence number
+   */
+  int   _seq_num;
+    /**
+   * @brief SAR channel indicator
+   */
+  int   _sar_chn;
+  /**
+   * @brief Scene identifier
+   */
+  std::string   _scene_id;
+  /**
+   * @brief Scene designator
+   */
+  std::string   _scene_des;
+  /**
+   * @brief Input scene centre time
+   */
+  std::string   _inp_sctim;
+  /**
+   * @brief Ascending/descending
+   */
+  std::string   _asc_des;
+    /**
+   * @brief Processed scene centre latitude
+   */
+  double   _pro_lat;
+    /**
+   * @brief Processed scene centre longitude
+   */
+  double   _pro_long;
+    /**
+   * @brief Processed scene centre headng
+   */
+  double   _pro_head;
+  /**
+   * @brief Ellipsoid designator
+   */
+  std::string   _ellip_des;
+    /**
+   * @brief Ellipsoid semi-major axis, km
+   */
+  double   _ellip_maj;
+    /**
+   * @brief Ellipsoid semi_minor axis, km
+   */
+  double  _ellip_min;
+  /**
+   * @brief Earth's mass
+   */
+    double   _earth_mass;
+    /**
+   * @brief Gravitational constant
+   */
+    double   _grav_const;
+    /**
+   * @brief Ellipsoid J2-4 parameters
+   */
+    double   _ellip_j[3];
+
+    /**
+   * @brief Average terrain height, km
+   */
+    double   _terrain_h;
+    /**
+   * @brief Scene centre line number
+   */
+    int   _sc_lin;
+    /**
+   * @brief Scene centre pixel number
+   */
+    int   _sc_pix;
+    /**
+   * @brief Scene length, km
+   */
+    double   _scene_len;
+    /**
+   * @brief Scene width, km
+   */
+    double   _scene_wid;
+
+    /**
+   * @brief Number of SAR channels
+   */
+    double   _nchn;
+
+    /**
+   * @brief Mission identifier
+   */
+  std::string   _mission_id;
+    /**
+   * @brief Sensor identifier
+   */
+  std::string   _sensor_id;
+    /**
+   * @brief Orbit number
+   */
+  std::string   _orbit_num;
+    /**
+   * @brief Platform geodetic latitude
+   */
+    double   _plat_lat;
+    /**
+   * @brief Platform geodetic longitude
+   */
+    double   _plat_long;
+    /**
+   * @brief Platform heading
+   */
+    double   _plat_head;
+    /**
+   * @brief Sensor clock angle
+   */
+    double   _clock_ang;
+    /**
+   * @brief Incidence angle
+   */
+    double   _incident_ang;
+
+    /**
+   * @brief Radar wave length
+   */
+    double   _wave_length;
+    /**
+   * @brief Motion compensation indicator
+   */
+  std::string   _motion_comp;
+    /**
+   * @brief Range pulse code specifier
+   */
+    std::string   _pulse_code;
+    /**
+   * @brief Range chirp coefficients
+   */
+    double   _ampl_coef[5];
+    /**
+   * @brief Range phase coefficients
+   */
+    double   _phas_coef[5];
+    /**
+   * @brief Chirp extraction index
+   */
+    int   _chirp_ext_ind;
+
+    /**
+   * @brief Range sampling rate
+   */
+    double   _fr;
+    /**
+   * @brief Range gate start time
+   */
+    double   _rng_gate;
+    /**
+   * @brief Range pulse length
+   */
+    double   _rng_length;
+    /**
+   * @brief Baseband conversion flag
+   */
+  std::string   _baseband_f;
+    /**
+   * @brief Range compressed flag
+   */
+    std::string   _rngcmp_f;
+    /**
+   * @brief Like polarized gain
+   */
+    double   _gn_polar;
+    /**
+   * @brief Cross polarized gain
+   */
+    double   _gn_cross;
+    /**
+   * @brief Number of bits per channel
+   */
+    int   _chn_bits;
+    /**
+   * @brief Quantization descriptor
+   */
+    std::string   _quant_desc;
+    /**
+   * @brief I channel DC bias
+   */
+    double   _i_bias;
+    /**
+   * @brief Q channel DC bias
+   */
+    double   _q_bias;
+    /**
+   * @brief I/Q channel ratio
+   */
+    double   _iq_ratio;
+
+    /**
+   * @brief Electronic boresight
+   */
+    double   _ele_sight;
+    /**
+   * @brief Mechanical boresight
+   */
+    double   _mech_sight;
+    /**
+   * @brief Echo tracker on/off flag
+   */
+  std::string   _echo_track;
+    /**
+   * @brief Nominal PRF, Hz
+   */
+    double   _fa;
+    /**
+   * @brief Elevation beamwidth
+   */
+    double   _elev_beam;
+    /**
+   * @brief Azimuth beamwidth
+   */
+    double   _azim_beam;
+    /**
+   * @brief Satellite binary time
+   */
+    int   _sat_bintim;
+    /**
+   * @brief Satellite clock time
+   */
+    int   _sat_clktim;
+    /**
+   * @brief Satellite clock increment
+   */
+    int   _sat_clkinc;
+
+    /**
+   * @brief Processing facility identifier
+   */
+    std::string   _fac_id;
+    /**
+   * @brief Processing system identifier
+   */
+    std::string   _sys_id;
+    /**
+   * @brief Processing version identifier
+   */
+    std::string   _ver_id;
+    /**
+   * @brief Facility process code
+   */
+    std::string   _fac_code;
+    /**
+   * @brief Product level code
+   */
+    std::string   _lev_code;
+    /**
+   * @brief Product type specifier
+   */
+    std::string   _prod_type;
+    /**
+   * @brief Processing algorithm identifier
+   */
+    std::string   _algor_id;
+    /**
+   * @brief Number of azimuth looks
+   */
+    double   _n_azilok;
+    /**
+   * @brief Number of range looks
+   */
+    double   _n_rnglok;
+    /**
+   * @brief Bandwidth per look in azimuth,Hz
+   */
+    double   _bnd_azilok;
+    /**
+   * @brief Bandwidth per look in range,Hz
+   */
+    double   _bnd_rnglok;
+    /**
+   * @brief Total azimuth look bandwidth
+   */
+    double   _bnd_azi;
+    /**
+   * @brief Total range look bandwidth
+   */
+    double   _bnd_rng;
+    /**
+   * @brief Azimuth weighting designator
+   */
+    std::string   _azi_weight;
+    /**
+   * @brief Range weighting designator
+   */
+    std::string   _rng_weight;
+    /**
+   * @brief Data input source
+   */
+    std::string   _data_inpsrc;
+    /**
+   * @brief Range resolution, meter
+   */
+    double   _rng_res;
+    /**
+   * @brief Azimuth resolution, meter
+   */
+    double   _azi_res;
+    /**
+   * @brief Radiometric stretch terms
+   */
+    double   _radi_stretch[2];
+    /**
+   * @brief Along track Doppler frequency terms
+   */
+    double   _alt_dopcen[3];
+
+    /**
+   * @brief Cross track Doppler frequency terms
+   */
+    double   _crt_dopcen[3];
+    /**
+   * @brief Pixel time direction indicator
+   */
+    std::string   _time_dir_pix;
+    /**
+   * @brief Line time direction indicator
+   */
+    std::string   _time_dir_lin;
+    /**
+   * @brief Along track Doppler rate term
+   */
+    double   _alt_rate[3];
+
+    /**
+   * @brief Cross track Doppler rate term
+   */
+    double   _crt_rate[3];
+
+    /**
+   * @brief Line content indicator
+   */
+    std::string   _line_cont;
+    /**
+   * @brief Clutter lock applied flag
+   */
+    std::string   _clutter_lock;
+    /**
+   * @brief Auto-focus applied flag
+   */
+    std::string   _auto_focus;
+    /**
+   * @brief Line spacing, meters
+   */
+    double   _line_spacing;
+    /**
+   * @brief Pixel spacing, meters
+   */
+    double   _pix_spacing;
+    /**
+   * @brief Range compression designator
+   */
+    std::string   _rngcmp_desg;
+
+private:
+
+};
+}
+#endif
+
diff --git a/ossim_plugins/ossim/RadarSat/CommonRecord/DopplerCentroidEstimateRecord.cpp b/ossim_plugins/ossim/RadarSat/CommonRecord/DopplerCentroidEstimateRecord.cpp
new file mode 100755
index 0000000..09572b5
--- /dev/null
+++ b/ossim_plugins/ossim/RadarSat/CommonRecord/DopplerCentroidEstimateRecord.cpp
@@ -0,0 +1,79 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include "DopplerCentroidEstimateRecord.h"
+
+namespace ossimplugins
+{
+DopplerCentroidEstimateRecord::DopplerCentroidEstimateRecord()
+{
+}
+
+DopplerCentroidEstimateRecord::~DopplerCentroidEstimateRecord()
+{
+}
+
+std::ostream& operator<<(std::ostream& os, const DopplerCentroidEstimateRecord& data)
+{
+	os<<"dopcen_conf:"<<data._dopcen_conf<<std::endl;
+	os<<"dopcen_ref_tim:"<<data._dopcen_ref_tim<<std::endl;
+	for (int i=0;i<4;i++)
+	{
+		os<<"dopcen_coef["<<i<<"]:"<<data._dopcen_coef[i]<<std::endl;
+	}
+
+	return os;
+}
+
+std::istream& operator>>(std::istream& is, DopplerCentroidEstimateRecord& data)
+{
+	char buf[17];
+	buf[16] = '\0';
+
+	is.read(buf,16);
+	buf[16] = '\0';
+	data._dopcen_conf = atof(buf);
+
+	is.read(buf,16);
+	buf[16] = '\0';
+	data._dopcen_ref_tim = atof(buf);
+
+	for (int i=0;i<4;i++)
+	{
+		is.read(buf,16);
+		buf[16] = '\0';
+		data._dopcen_coef[i] = atof(buf);
+	}
+	return is;
+}
+
+DopplerCentroidEstimateRecord::DopplerCentroidEstimateRecord(const DopplerCentroidEstimateRecord& rhs):
+	_dopcen_conf(rhs._dopcen_conf),
+	_dopcen_ref_tim(rhs._dopcen_ref_tim)
+{
+	for (int i=0;i<4;i++)
+	{
+		_dopcen_coef[i] = rhs._dopcen_coef[i];
+	}
+}
+
+DopplerCentroidEstimateRecord& DopplerCentroidEstimateRecord::operator=(const DopplerCentroidEstimateRecord& rhs)
+{
+	_dopcen_conf = rhs._dopcen_conf;
+	_dopcen_ref_tim = rhs._dopcen_ref_tim;
+	for (int i=0;i<4;i++)
+	{
+		_dopcen_coef[i] = rhs._dopcen_coef[i];
+	}
+	return *this;
+}
+}
+
diff --git a/ossim_plugins/ossim/RadarSat/CommonRecord/DopplerCentroidEstimateRecord.h b/ossim_plugins/ossim/RadarSat/CommonRecord/DopplerCentroidEstimateRecord.h
new file mode 100755
index 0000000..d962aaa
--- /dev/null
+++ b/ossim_plugins/ossim/RadarSat/CommonRecord/DopplerCentroidEstimateRecord.h
@@ -0,0 +1,98 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef DopplerCentroidEstimateRecord_h
+#define DopplerCentroidEstimateRecord_h
+
+#include <iostream>
+
+#include <RadarSat/RadarSatRecord.h>
+
+namespace ossimplugins
+{
+/**
+ * @ingroup ProcessingParametersRecord
+ * @brief This class is able to read a Doppler centroid estimates record
+ */
+class DopplerCentroidEstimateRecord
+{
+public:
+  /**
+   * @brief Constructor
+   */
+  DopplerCentroidEstimateRecord();
+
+  /**
+   * @brief Destructor
+   */
+  ~DopplerCentroidEstimateRecord();
+
+  /**
+   * @brief Copy constructor
+   */
+  DopplerCentroidEstimateRecord(const DopplerCentroidEstimateRecord& rhs);
+
+  /**
+   * @brief Copy operator
+   */
+  DopplerCentroidEstimateRecord& operator=(const DopplerCentroidEstimateRecord& rhs);
+
+  /**
+   * @brief This function writes the DopplerCentroidEstimateRecord in a stream
+   */
+  friend std::ostream& operator<<(std::ostream& os, const DopplerCentroidEstimateRecord& data);
+
+  /**
+   * @brief This function reads a DopplerCentroidEstimateRecord from a stream
+   */
+  friend std::istream& operator>>(std::istream& is, DopplerCentroidEstimateRecord& data);
+
+  /**
+   * @brief Doppler centroid confidence measure
+   */
+  double   get_dopcen_conf()
+  {
+    return _dopcen_conf;
+  }
+    /**
+   * @brief Doppler centroid reference time (sec)
+   */
+  double   get_dopcen_ref_tim()
+  {
+    return _dopcen_ref_tim;
+  }
+    /**
+   * @brief Doppler centroid coefficients
+   */
+  double*   get_dopcen_coef()
+  {
+    return _dopcen_coef;
+  }
+
+protected:
+  /**
+   * @brief Doppler centroid confidence measure
+   */
+  double   _dopcen_conf;
+    /**
+   * @brief Doppler centroid reference time (sec)
+   */
+  double   _dopcen_ref_tim;
+    /**
+   * @brief Doppler centroid coefficients
+   */
+  double   _dopcen_coef[4];
+private:
+
+};
+}
+#endif
+
diff --git a/ossim_plugins/ossim/RadarSat/CommonRecord/FileDescriptor.cpp b/ossim_plugins/ossim/RadarSat/CommonRecord/FileDescriptor.cpp
new file mode 100755
index 0000000..650a149
--- /dev/null
+++ b/ossim_plugins/ossim/RadarSat/CommonRecord/FileDescriptor.cpp
@@ -0,0 +1,336 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include "FileDescriptor.h"
+
+namespace ossimplugins
+{
+FileDescriptor::FileDescriptor() : RadarSatRecord("sar_desc_rec")
+{
+}
+
+FileDescriptor::~FileDescriptor()
+{
+}
+
+std::ostream& operator<<(std::ostream& os, const FileDescriptor& data)
+{
+	os<<"ascii_flag:"<<data._ascii_flag.c_str()<<std::endl;
+	os<<"format_doc:"<<data._format_doc.c_str()<<std::endl;
+	os<<"format_ver:"<<data._format_ver.c_str()<<std::endl;
+	os<<"design_rev:"<<data._design_rev.c_str()<<std::endl;
+	os<<"software_id:"<<data._software_id.c_str()<<std::endl;
+	os<<"file_num:"<<data._file_num<<std::endl;
+	os<<"file_name:"<<data._file_name.c_str()<<std::endl;
+	os<<"rec_seq:"<<data._rec_seq.c_str()<<std::endl;
+	os<<"seq_loc:"<<data._seq_loc<<std::endl;
+	os<<"seq_len:"<<data._seq_len<<std::endl;
+	os<<"rec_code:"<<data._rec_code.c_str()<<std::endl;
+	os<<"code_loc:"<<data._code_loc<<std::endl;
+	os<<"code_len:"<<data._code_len<<std::endl;
+	os<<"rec_len:"<<data._rec_len.c_str()<<std::endl;
+	os<<"rlen_loc:"<<data._rlen_loc<<std::endl;
+	os<<"rlen_len:"<<data._rlen_len<<std::endl;
+	os<<"n_dataset:"<<data._n_dataset<<std::endl;
+	os<<"l_dataset:"<<data._l_dataset<<std::endl;
+	os<<"n_map_proj:"<<data._n_map_proj<<std::endl;
+	os<<"l_map_proj:"<<data._l_map_proj<<std::endl;
+	os<<"n_plat_pos:"<<data._n_plat_pos<<std::endl;
+	os<<"l_plat_pos:"<<data._l_plat_pos<<std::endl;
+	os<<"n_att_data:"<<data._n_att_data<<std::endl;
+	os<<"l_att_data:"<<data._l_att_data<<std::endl;
+	os<<"n_radi_data:"<<data._n_radi_data<<std::endl;
+	os<<"l_radi_data:"<<data._l_radi_data<<std::endl;
+	os<<"n_radi_comp:"<<data._n_radi_comp<<std::endl;
+	os<<"l_radi_comp:"<<data._l_radi_comp<<std::endl;
+	os<<"n_qual_sum:"<<data._n_qual_sum<<std::endl;
+	os<<"l_qual_sum:"<<data._l_qual_sum<<std::endl;
+	os<<"n_data_his:"<<data._n_data_his<<std::endl;
+	os<<"l_data_his:"<<data._l_data_his<<std::endl;
+	os<<"n_rang_spec:"<<data._n_rang_spec<<std::endl;
+	os<<"l_rang_spec:"<<data._l_rang_spec<<std::endl;
+	os<<"n_dem_desc:"<<data._n_dem_desc<<std::endl;
+	os<<"l_dem_desc:"<<data._l_dem_desc<<std::endl;
+	os<<"n_radar_par:"<<data._n_radar_par<<std::endl;
+	os<<"l_radar_par:"<<data._l_radar_par<<std::endl;
+	os<<"n_anno_data:"<<data._n_anno_data<<std::endl;
+	os<<"l_anno_data:"<<data._l_anno_data<<std::endl;
+	os<<"n_det_proc:"<<data._n_det_proc<<std::endl;
+	os<<"l_det_proc:"<<data._l_det_proc<<std::endl;
+	os<<"n_cal:"<<data._n_cal<<std::endl;
+	os<<"l_cal:"<<data._l_cal<<std::endl;
+	os<<"n_gcp:"<<data._n_gcp<<std::endl;
+	os<<"l_gcp:"<<data._l_gcp<<std::endl;
+	os<<"n_fac_data:"<<data._n_fac_data<<std::endl;
+	os<<"l_fac_data:"<<data._l_fac_data<<std::endl;
+	return os;
+}
+
+std::istream& operator>>(std::istream& is, FileDescriptor& data)
+{
+	char buf2[3];
+	buf2[2] = '\0';
+	char buf12[13];
+	buf12[12] = '\0';
+	char buf16[17];
+	buf16[16] = '\0';
+	char buf4[5];
+	buf4[4] = '\0';
+	char buf6[7];
+	buf6[6] = '\0';
+	char buf8[9];
+	buf8[8] = '\0';
+	char buf64[65];
+	buf64[64] = '\0';
+
+	char buf60[61];
+	buf60[60] = '\0';
+
+	char buf288[289];
+	buf288[288] = '\0';
+
+	is.read(buf2,2);
+	data._ascii_flag = buf2;
+
+	is.read(buf2,2);
+
+	is.read(buf12,12);
+	data._format_doc = buf12;
+
+	is.read(buf2,2);
+	data._format_ver = buf2;
+
+	is.read(buf2,2);
+	data._design_rev = buf2;
+
+	is.read(buf12,12);
+	data._software_id = buf12;
+
+	is.read(buf4,4);
+	data._file_num = atoi(buf4);
+
+	is.read(buf16,16);
+	data._file_name = buf16;
+
+	is.read(buf4,4);
+	data._rec_seq = buf4;
+
+	is.read(buf8,8);
+	data._seq_loc = atoi(buf8);
+
+	is.read(buf4,4);
+	data._seq_len = atoi(buf4);
+
+	is.read(buf4,4);
+	data._rec_code = buf4;
+
+	is.read(buf8,8);
+	data._code_loc = atoi(buf8);
+
+	is.read(buf4,4);
+	data._code_len = atoi(buf4);
+
+	is.read(buf4,4);
+	data._rec_len = buf4;
+
+	is.read(buf8,8);
+	data._rlen_loc = atoi(buf8);
+
+	is.read(buf4,4);
+	data._rlen_len = atoi(buf4);
+
+	is.read(buf4,4);
+
+	is.read(buf64,64);
+
+	is.read(buf6,6);
+	data._n_dataset = atoi(buf6);
+
+	is.read(buf6,6);
+	data._l_dataset = atoi(buf6);
+
+	is.read(buf6,6);
+	data._n_map_proj = atoi(buf6);
+
+	is.read(buf6,6);
+	data._l_map_proj = atoi(buf6);
+
+	is.read(buf6,6);
+	data._n_plat_pos = atoi(buf6);
+	is.read(buf6,6);
+	data._l_plat_pos = atoi(buf6);
+	is.read(buf6,6);
+	data._n_att_data = atoi(buf6);
+	is.read(buf6,6);
+	data._l_att_data = atoi(buf6);
+	is.read(buf6,6);
+	data._n_radi_data = atoi(buf6);
+	is.read(buf6,6);
+	data._l_radi_data = atoi(buf6);
+	is.read(buf6,6);
+	data._n_radi_comp = atoi(buf6);
+	is.read(buf6,6);
+	data._l_radi_comp = atoi(buf6);
+	is.read(buf6,6);
+	data._n_qual_sum = atoi(buf6);
+	is.read(buf6,6);
+	data._l_qual_sum = atoi(buf6);
+	is.read(buf6,6);
+	data._n_data_his = atoi(buf6);
+	is.read(buf6,6);
+	data._l_data_his = atoi(buf6);
+
+
+
+	is.read(buf6,6);
+	data._n_rang_spec = atoi(buf6);
+	is.read(buf6,6);
+	data._l_rang_spec = atoi(buf6);
+	is.read(buf6,6);
+	data._n_dem_desc = atoi(buf6);
+	is.read(buf6,6);
+	data._l_dem_desc = atoi(buf6);
+	is.read(buf6,6);
+	data._n_radar_par = atoi(buf6);
+	is.read(buf6,6);
+	data._l_radar_par = atoi(buf6);
+	is.read(buf6,6);
+	data._n_anno_data = atoi(buf6);
+	is.read(buf6,6);
+	data._l_anno_data = atoi(buf6);
+	is.read(buf6,6);
+	data._n_det_proc = atoi(buf6);
+	is.read(buf6,6);
+	data._l_det_proc = atoi(buf6);
+	is.read(buf6,6);
+	data._n_cal = atoi(buf6);
+	is.read(buf6,6);
+	data._l_cal = atoi(buf6);
+	is.read(buf6,6);
+	data._n_gcp = atoi(buf6);
+	is.read(buf6,6);
+	data._l_gcp = atoi(buf6);
+	is.read(buf60,60);
+	is.read(buf6,6);
+	data._n_fac_data = atoi(buf6);
+	is.read(buf6,6);
+	data._l_fac_data = atoi(buf6);
+	is.read(buf288,288);
+	return is;
+}
+
+FileDescriptor::FileDescriptor(const FileDescriptor& rhs):
+	RadarSatRecord(rhs),
+	_ascii_flag(rhs._ascii_flag),
+	_format_doc(rhs._format_doc),
+	_format_ver(rhs._format_ver),
+	_design_rev(rhs._design_rev),
+	_software_id(rhs._software_id),
+	_file_num(rhs._file_num),
+	_file_name(rhs._file_name),
+	_rec_seq(rhs._rec_seq),
+	_seq_loc(rhs._seq_loc),
+	_seq_len(rhs._seq_len),
+	_rec_code(rhs._rec_code),
+	_code_loc(rhs._code_loc),
+	_code_len(rhs._code_len),
+	_rec_len(rhs._rec_len),
+	_rlen_loc(rhs._rlen_loc),
+	_rlen_len(rhs._rlen_len),
+	_n_dataset(rhs._n_dataset),
+	_l_dataset(rhs._l_dataset),
+	_n_map_proj(rhs._n_map_proj),
+	_l_map_proj(rhs._l_map_proj),
+	_n_plat_pos(rhs._n_plat_pos),
+	_l_plat_pos(rhs._l_plat_pos),
+	_n_att_data(rhs._n_att_data),
+	_l_att_data(rhs._l_att_data),
+	_n_radi_data(rhs._n_radi_data),
+	_l_radi_data(rhs._l_radi_data),
+	_n_radi_comp(rhs._n_radi_comp),
+	_l_radi_comp(rhs._l_radi_comp),
+	_n_qual_sum(rhs._n_qual_sum),
+	_l_qual_sum(rhs._l_qual_sum),
+	_n_data_his(rhs._n_data_his),
+	_l_data_his(rhs._l_data_his),
+	_n_rang_spec(rhs._n_rang_spec),
+	_l_rang_spec(rhs._l_rang_spec),
+	_n_dem_desc(rhs._n_dem_desc),
+	_l_dem_desc(rhs._l_dem_desc),
+	_n_radar_par(rhs._n_radar_par),
+	_l_radar_par(rhs._l_radar_par),
+	_n_anno_data(rhs._n_anno_data),
+	_l_anno_data(rhs._l_anno_data),
+	_n_det_proc(rhs._n_det_proc),
+	_l_det_proc(rhs._l_det_proc),
+	_n_cal(rhs._n_cal),
+	_l_cal(rhs._l_cal),
+	_n_gcp(rhs._n_gcp),
+	_l_gcp(rhs._l_gcp),
+	_n_fac_data(rhs._n_fac_data),
+	_l_fac_data(rhs._l_fac_data)
+{
+}
+
+FileDescriptor& FileDescriptor::operator=(const FileDescriptor& rhs)
+{
+	_ascii_flag = rhs._ascii_flag;
+	_format_doc = rhs._format_doc;
+	_format_ver = rhs._format_ver;
+	_design_rev = rhs._design_rev;
+	_software_id = rhs._software_id;
+	_file_num = rhs._file_num;
+	_file_name = rhs._file_name;
+	_rec_seq = rhs._rec_seq;
+	_seq_loc = rhs._seq_loc;
+	_seq_len = rhs._seq_len;
+	_rec_code = rhs._rec_code;
+	_code_loc = rhs._code_loc;
+	_code_len = rhs._code_len;
+	_rec_len = rhs._rec_len;
+	_rlen_loc = rhs._rlen_loc;
+	_rlen_len = rhs._rlen_len;
+	_n_dataset = rhs._n_dataset;
+	_l_dataset = rhs._l_dataset;
+	_n_map_proj = rhs._n_map_proj;
+	_l_map_proj = rhs._l_map_proj;
+	_n_plat_pos = rhs._n_plat_pos;
+	_l_plat_pos = rhs._l_plat_pos;
+	_n_att_data = rhs._n_att_data;
+	_l_att_data = rhs._l_att_data;
+	_n_radi_data = rhs._n_radi_data;
+	_l_radi_data = rhs._l_radi_data;
+	_n_radi_comp = rhs._n_radi_comp;
+	_l_radi_comp = rhs._l_radi_comp;
+	_n_qual_sum = rhs._n_qual_sum ;
+	_l_qual_sum = rhs._l_qual_sum;
+	_n_data_his = rhs._n_data_his;
+	_l_data_his = rhs._l_data_his;
+	_n_rang_spec = rhs._n_rang_spec;
+	_l_rang_spec = rhs._l_rang_spec;
+	_n_dem_desc = rhs._n_dem_desc;
+	_l_dem_desc = rhs._l_dem_desc;
+	_n_radar_par = rhs._n_radar_par;
+	_l_radar_par = rhs._l_radar_par;
+	_n_anno_data = rhs._n_anno_data;
+	_l_anno_data = rhs._l_anno_data;
+	_n_det_proc = rhs._n_det_proc;
+	_l_det_proc = rhs._l_det_proc;
+	_n_cal = rhs._n_cal;
+	_l_cal = rhs._l_cal;
+	_n_gcp = rhs._n_gcp;
+	_l_gcp = rhs._l_gcp;
+	_n_fac_data = rhs._n_fac_data;
+	_l_fac_data = rhs._l_fac_data;
+	return *this;
+}
+}
+
diff --git a/ossim_plugins/ossim/RadarSat/CommonRecord/FileDescriptor.h b/ossim_plugins/ossim/RadarSat/CommonRecord/FileDescriptor.h
new file mode 100755
index 0000000..885f03c
--- /dev/null
+++ b/ossim_plugins/ossim/RadarSat/CommonRecord/FileDescriptor.h
@@ -0,0 +1,630 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef FileDescriptor_h
+#define FileDescriptor_h
+
+
+#include<iostream>
+#include <RadarSat/RadarSatRecordHeader.h>
+#include <RadarSat/RadarSatRecord.h>
+
+namespace ossimplugins
+{
+/**
+ * @ingroup SARLeaderFileDescriptorRecord
+ * @brief This class is able to read the SAR leader file descriptor record of the leader file
+ */
+class FileDescriptor : public RadarSatRecord
+{
+public:
+  /**
+   * @brief Constructor
+   */
+  FileDescriptor();
+  /**
+   * @brief Destructor
+   */
+  virtual ~FileDescriptor();
+
+  /**
+   * @brief This function writes the FileDescriptor in a stream
+   */
+  friend std::ostream& operator<<(std::ostream& os, const FileDescriptor& data);
+
+  /**
+   * @brief This function reads a FileDescriptor from a stream
+   */
+  friend std::istream& operator>>(std::istream& is, FileDescriptor& data);
+
+  /**
+   * @brief Copy constructor
+   */
+  FileDescriptor(const FileDescriptor& rhs);
+
+  /**
+   * @brief Copy operator
+   */
+  FileDescriptor& operator=(const FileDescriptor& rhs);
+
+  /**
+   * @brief This function is able to create a new instance of the class
+   */
+  RadarSatRecord* Instanciate()
+  {
+    return new FileDescriptor();
+  };
+
+  /**
+   * @brief This function is able to create a new instance of the class initialised with the data of the calling instance
+   */
+  RadarSatRecord* Clone()
+  {
+    return new FileDescriptor(*this);
+  };
+
+  /**
+   * @brief Reads the class data from a stream
+   */
+  void Read(std::istream& is)
+  {
+    is>>*this;
+  };
+
+  /**
+   * @brief Writes the class to a stream
+   */
+  void Write(std::ostream& os)
+  {
+    os<<*this;
+  };
+
+  /**
+   * @brief ASCII flag
+   */
+  std::string get_ascii_flag()
+  {
+    return _ascii_flag;
+  };
+
+  /**
+   * @brief Format control documentation
+   */
+  std::string get_format_doc()
+  {
+    return _format_doc;
+  };
+  /**
+   * @brief Format doc version
+   */
+  std::string   get_format_ver()
+  {
+    return _format_ver;
+  };
+  /**
+   * @brief Format doc revision
+   */
+    std::string   get_design_rev()
+  {
+    return _design_rev;
+  };
+  /**
+   * @brief Software identifier
+   */
+    std::string   get_software_id()
+  {
+    return _software_id;
+  };
+  /**
+   * @brief File number
+   */
+  int   get_file_num()
+  {
+    return _file_num ;
+  };
+  /**
+   * @brief File name
+   */
+    std::string   get_file_name()
+  {
+    return _file_name;
+  };
+  /**
+   * @brief Record sequence/location flag
+   */
+    std::string   get_rec_seq()
+  {
+    return _rec_seq;
+  };
+  /**
+   * @brief Sequence number location
+   */
+  int   get_seq_loc()
+  {
+    return _seq_loc;
+  };
+  /**
+   * @brief Sequence number lenght
+   */
+  int   get_seq_len()
+  {
+    return _seq_len;
+  };
+  /**
+   * @brief Record code/location flag
+   */
+  std::string   get_rec_code()
+  {
+    return _rec_code;
+  };
+  /**
+   * @brief Record code location
+   */
+  int   get_code_loc()
+  {
+    return _code_loc;
+  };
+  /**
+   * @brief Record code length
+   */
+    int   get_code_len()
+  {
+    return _code_len;
+  };
+  /**
+   * @brief Record length/location flag
+   */
+  std::string get_rec_len()
+  {
+    return _rec_len;
+  };
+  /**
+   * @brief Record lenght location
+   */
+  int get_rlen_loc()
+  {
+    return _rlen_loc;
+  };
+  /**
+   * @brief Record length, bytes
+   */
+  int get_rlen_len()
+  {
+    return _rlen_len;
+  };
+  /**
+   * @brief Number of dataset summ records
+   */
+  int get_n_dataset()
+  {
+    return _n_dataset;
+  };
+  /**
+   * @brief Data set summary record length, bytes
+   */
+  int get_l_dataset()
+  {
+    return _l_dataset;
+  };
+  /**
+   * @brief Number of map proj records
+   */
+  int get_n_map_proj()
+  {
+    return _n_map_proj;
+  };
+  /**
+   * @brief Map projection record length, bytes
+   */
+  int get_l_map_proj()
+  {
+    return _l_map_proj;
+  };
+  /**
+   * @brief Number of platform position records
+   */
+  int get_n_plat_pos()
+  {
+    return _n_plat_pos;
+  };
+  /**
+   * @brief Platform position record length, bytes
+   */
+  int get_l_plat_pos()
+  {
+    return _l_plat_pos;
+  };
+  /**
+   * @brief Number of attitude data records
+   */
+  int get_n_att_data()
+  {
+    return _n_att_data;
+  };
+  /**
+   * @brief Attitude data record length, bytes
+   */
+  int get_l_att_data()
+  {
+    return _l_att_data;
+  };
+  /**
+   * @brief Number of radiometric data records
+   */
+  int get_n_radi_data()
+  {
+    return _n_radi_data;
+  };
+  /**
+   * @brief Radiometric data record length, bytes
+   */
+  int get_l_radi_data()
+  {
+    return _l_radi_data;
+  };
+  /**
+   * @brief Number of radiometric compensation records
+   */
+  int get_n_radi_comp()
+  {
+    return _n_radi_comp;
+  };
+  /**
+   *  @brief Radiometric compensation record length, bytes
+   */
+  int get_l_radi_comp()
+  {
+    return _l_radi_comp;
+  };
+  /**
+   * @brief Number of data quality summary records
+   */
+  int get_n_qual_sum()
+  {
+    return _n_qual_sum;
+  };
+  /**
+   * @brief Data quality summary record length, bytes
+   */
+  int get_l_qual_sum()
+  {
+    return _l_qual_sum;
+  };
+  /**
+   * @brief Number of data histogram records
+   */
+  int get_n_data_his()
+  {
+    return _n_data_his;
+  };
+  /**
+   * @brief Data histogram record length, bytes
+   */
+  int get_l_data_his()
+  {
+    return _l_data_his;
+  };
+  /**
+   * @brief Number of range spectra records
+   */
+  int get_n_rang_spec()
+  {
+    return _n_rang_spec ;
+  };
+  /**
+   * @brief Range spectra record length, bytes
+   */
+  int get_l_rang_spec()
+  {
+    return _l_rang_spec;
+  };
+  /**
+   * @brief Number of DEM descriptor records
+   */
+  int get_n_dem_desc()
+  {
+    return _n_dem_desc;
+  };
+  /**
+   * @brief DEM desc record length, bytes
+   */
+  int get_l_dem_desc()
+  {
+    return _l_dem_desc;
+  };
+  /**
+   * @brief Number of RADAR par records
+   */
+  int get_n_radar_par()
+  {
+    return _n_radar_par;
+  };
+  /**
+   * @brief RADAR par record length, bytes
+   */
+  int get_l_radar_par()
+  {
+    return _l_radar_par;
+  };
+  /**
+   * @brief Number of annotation data records
+   */
+  int get_n_anno_data()
+  {
+    return _n_anno_data;
+  };
+  /**
+   * @brief Annotation data record length, bytes
+   */
+  int get_l_anno_data()
+  {
+    return _l_anno_data;
+  };
+  /**
+   * @brief Number of processing parameter records
+   */
+  int get_n_det_proc()
+  {
+    return _n_det_proc;
+  };
+  /**
+   * @brief Processing parameter record length, bytes
+   */
+  int get_l_det_proc()
+  {
+    return _l_det_proc;
+  };
+  /**
+   * @brief Number of calibration records
+   */
+  int get_n_cal()
+  {
+    return _n_cal;
+  };
+  /**
+   * @brief Calibration record length, bytes
+   */
+  int get_l_cal()
+  {
+    return _l_cal;
+  };
+  /**
+   * @brief Number of GCP records
+   */
+  int get_n_gcp()
+  {
+    return _n_gcp;
+  };
+  /**
+   * @brief GCP record length, bytes
+   */
+  int get_l_gcp()
+  {
+    return _l_gcp;
+  };
+  /**
+   * @brief Number of facility data records
+   */
+  int get_n_fac_data()
+  {
+    return _n_fac_data;
+  };
+  /**
+   * @brief Fac data record length, bytes
+   */
+  int get_l_fac_data()
+  {
+    return _l_fac_data;
+  };
+
+protected:
+  /**
+   * @brief ASCII flag
+   */
+  std::string _ascii_flag;
+
+  /**
+   * @brief Format control documentation
+   */
+  std::string _format_doc;
+  /**
+   * @brief Format doc version
+   */
+  std::string   _format_ver;
+  /**
+   * @brief Format doc revision
+   */
+    std::string   _design_rev;
+  /**
+   * @brief Software identifier
+   */
+    std::string   _software_id;
+  /**
+   * @brief File number
+   */
+  int   _file_num;
+  /**
+   * @brief File name
+   */
+    std::string   _file_name;
+  /**
+   * @brief Record sequence/location flag
+   */
+    std::string   _rec_seq;
+  /**
+   * @brief Sequence number location
+   */
+  int   _seq_loc;
+  /**
+   * @brief Sequence number lenght
+   */
+  int   _seq_len;
+  /**
+   * @brief Record code/location flag
+   */
+  std::string   _rec_code;
+  /**
+   * @brief Record code location
+   */
+  int   _code_loc;
+  /**
+   * @brief Record code length
+   */
+    int   _code_len;
+  /**
+   * @brief Record length/location flag
+   */
+  std::string _rec_len;
+  /**
+   * @brief Record lenght location
+   */
+  int _rlen_loc;
+  /**
+   * @brief Record length, bytes
+   */
+  int _rlen_len;
+
+
+  /**
+   * @brief Number of dataset summ records
+   */
+  int _n_dataset;
+  /**
+   * @brief Data set summary record length, bytes
+   */
+  int _l_dataset;
+  /**
+   * @brief Number of map proj records
+   */
+  int _n_map_proj;
+  /**
+   * @brief Map projection record length, bytes
+   */
+  int _l_map_proj;
+  /**
+   * @brief Number of platform position records
+   */
+  int _n_plat_pos;
+  /**
+   * @brief Platform position record length, bytes
+   */
+  int _l_plat_pos;
+  /**
+   * @brief Number of attitude data records
+   */
+  int _n_att_data;
+  /**
+   * @brief Attitude data record length, bytes
+   */
+  int _l_att_data;
+  /**
+   * @brief Number of radiometric data records
+   */
+  int _n_radi_data;
+  /**
+   * @brief Radiometric data record length, bytes
+   */
+  int _l_radi_data;
+  /**
+   * @brief Number of radiometric compensation records
+   */
+  int _n_radi_comp;
+  /**
+   *  @brief Radiometric compensation record length, bytes
+   */
+  int _l_radi_comp;
+  /**
+   * @brief Number of data quality summary records
+   */
+  int _n_qual_sum;
+  /**
+   * @brief Data quality summary record length, bytes
+   */
+  int _l_qual_sum;
+  /**
+   * @brief Number of data histogram records
+   */
+  int _n_data_his;
+  /**
+   * @brief Data histogram record length, bytes
+   */
+  int _l_data_his;
+  /**
+   * @brief Number of range spectra records
+   */
+  int _n_rang_spec;
+  /**
+   * @brief Range spectra record length, bytes
+   */
+  int _l_rang_spec;
+  /**
+   * @brief Number of DEM descriptor records
+   */
+  int _n_dem_desc;
+  /**
+   * @brief DEM desc record length, bytes
+   */
+  int _l_dem_desc;
+  /**
+   * @brief Number of RADAR par records
+   */
+  int _n_radar_par;
+  /**
+   * @brief RADAR par record length, bytes
+   */
+  int _l_radar_par;
+  /**
+   * @brief Number of annotation data records
+   */
+  int _n_anno_data;
+  /**
+   * @brief Annotation data record length, bytes
+   */
+  int _l_anno_data;
+  /**
+   * @brief Number of processing parameter records
+   */
+  int _n_det_proc;
+  /**
+   * @brief Processing parameter record length, bytes
+   */
+  int _l_det_proc;
+  /**
+   * @brief Number of calibration records
+   */
+  int _n_cal;
+  /**
+   * @brief Calibration record length, bytes
+   */
+  int _l_cal;
+  /**
+   * @brief Number of GCP records
+   */
+  int _n_gcp;
+  /**
+   * @brief GCP record length, bytes
+   */
+  int _l_gcp;
+
+  /**
+   * @brief Number of facility data records
+   */
+  int _n_fac_data;
+  /**
+   * @brief Fac data record length, bytes
+   */
+  int _l_fac_data;
+
+private:
+};
+}
+#endif
+
diff --git a/ossim_plugins/ossim/RadarSat/CommonRecord/MisregistrationRecord.cpp b/ossim_plugins/ossim/RadarSat/CommonRecord/MisregistrationRecord.cpp
new file mode 100755
index 0000000..1704b84
--- /dev/null
+++ b/ossim_plugins/ossim/RadarSat/CommonRecord/MisregistrationRecord.cpp
@@ -0,0 +1,57 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include "MisregistrationRecord.h"
+
+namespace ossimplugins
+{
+MisregistrationRecord::MisregistrationRecord()
+{
+}
+
+MisregistrationRecord::~MisregistrationRecord()
+{
+}
+
+std::ostream& operator<<(std::ostream& os, const MisregistrationRecord& data)
+{
+	os<<"alt_m:"<<data._alt_m<<std::endl;
+    os<<"crt_m:"<<data._crt_m<<std::endl;
+	return os;
+}
+
+std::istream& operator>>(std::istream& is, MisregistrationRecord& data)
+{
+	char buf16[17];
+	buf16[16] = '\0';
+
+	is.read(buf16,16);
+	data._alt_m = atof(buf16);
+
+	is.read(buf16,16);
+	data._crt_m = atof(buf16);
+	return is;
+}
+
+MisregistrationRecord::MisregistrationRecord(const MisregistrationRecord& rhs):
+	_alt_m(rhs._alt_m),
+	_crt_m(rhs._crt_m)
+{
+}
+
+MisregistrationRecord& MisregistrationRecord::operator=(const MisregistrationRecord& rhs)
+{
+	_alt_m = rhs._alt_m;
+	_crt_m = rhs._crt_m;
+	return *this;
+}
+}
+
diff --git a/ossim_plugins/ossim/RadarSat/CommonRecord/MisregistrationRecord.h b/ossim_plugins/ossim/RadarSat/CommonRecord/MisregistrationRecord.h
new file mode 100755
index 0000000..24faaff
--- /dev/null
+++ b/ossim_plugins/ossim/RadarSat/CommonRecord/MisregistrationRecord.h
@@ -0,0 +1,87 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef MisregistrationRecord_h
+#define MisregistrationRecord_h
+
+#include <iostream>
+
+#include <RadarSat/RadarSatRecord.h>
+
+namespace ossimplugins
+{
+/**
+ * @ingroup DataQualitySummaryRecord
+ * @brief This class is able to read a misregistration record
+ */
+class MisregistrationRecord
+{
+public:
+  /**
+   * @brief Constructor
+   */
+  MisregistrationRecord();
+
+  /**
+   * @brief Destructor
+   */
+  ~MisregistrationRecord();
+
+  /**
+   * @brief Copy constructor
+   */
+  MisregistrationRecord(const MisregistrationRecord& rhs);
+
+  /**
+   * @brief Copy operator
+   */
+  MisregistrationRecord& operator=(const MisregistrationRecord& rhs);
+  /**
+   * @brief This function writes the MisregistrationRecord in a stream
+   */
+  friend std::ostream& operator<<(std::ostream& os, const MisregistrationRecord& data);
+
+  /**
+   * @brief This function reads a MisregistrationRecord from a stream
+   */
+  friend std::istream& operator>>(std::istream& is, MisregistrationRecord& data);
+
+  /**
+   * @brief Nominal along track misregistration
+   */
+  double   get_alt_m()
+  {
+    return _alt_m;
+  };
+    /**
+   * @brief Nominal cross track misregistration
+   */
+  double   get_crt_m()
+  {
+    return _crt_m;
+  };
+protected:
+
+  /**
+   * @brief Nominal along track misregistration
+   */
+  double   _alt_m;
+    /**
+   * @brief Nominal cross track misregistration
+   */
+  double   _crt_m;
+private:
+
+
+};
+}
+#endif
+
diff --git a/ossim_plugins/ossim/RadarSat/CommonRecord/ProcessingParameters.cpp b/ossim_plugins/ossim/RadarSat/CommonRecord/ProcessingParameters.cpp
new file mode 100755
index 0000000..5ac4956
--- /dev/null
+++ b/ossim_plugins/ossim/RadarSat/CommonRecord/ProcessingParameters.cpp
@@ -0,0 +1,902 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include "ProcessingParameters.h"
+
+namespace ossimplugins
+{
+   ProcessingParameters::ProcessingParameters() : RadarSatRecord("proc_param_rec")
+   {
+   }
+
+   ProcessingParameters::~ProcessingParameters()
+   {
+   }
+
+   std::ostream& operator<<(std::ostream& os, const ProcessingParameters& data)
+   {
+      os<<"rec_seq:"<<data._rec_seq<<std::endl;
+
+      os<<"inp_media:"<<data._inp_media.c_str()<<std::endl;
+
+      os<<"n_tape_id:"<<data._n_tape_id<<std::endl;
+
+      for (int i=0;i<10;i++)
+      {
+         os<<"tape_id["<<i<<"]:"<<data._tape_id[i].c_str()<<std::endl;
+      }
+
+      os<<"exp_ing_start:"<<data._exp_ing_start.c_str()<<std::endl;
+
+      os<<"exp_ing_stop:"<<data._exp_ing_stop.c_str()<<std::endl;
+
+      os<<"act_ing_start:"<<data._act_ing_start.c_str()<<std::endl;
+
+      os<<"act_ing_stop:"<<data._act_ing_stop.c_str()<<std::endl;
+
+      os<<"proc_start:"<<data._proc_start.c_str()<<std::endl;
+
+      os<<"proc_stop:"<<data._proc_stop.c_str()<<std::endl;
+
+      for (int i=0;i<10;i++)
+      {
+         os<<"mn_sig_lev["<<i<<"]:"<<data._mn_sig_lev[i]<<std::endl;
+      }
+
+      os<<"scr_data_ind:"<<data._scr_data_ind<<std::endl;
+
+      os<<"miss_ln:"<<data._miss_ln<<std::endl;
+
+      os<<"rej_ln:"<<data._rej_ln<<std::endl;
+
+      os<<"large_gap:"<<data._large_gap<<std::endl;
+
+      os<<"bit_err_rate:"<<data._bit_err_rate<<std::endl;
+
+      os<<"fm_crc_err:"<<data._fm_crc_err<<std::endl;
+
+      os<<"date_incons:"<<data._date_incons<<std::endl;
+
+      os<<"prf_changes:"<<data._prf_changes<<std::endl;
+
+      os<<"delay_changes:"<<data._delay_changes<<std::endl;
+
+      os<<"skipd_frams:"<<data._skipd_frams<<std::endl;
+
+      os<<"rej_bf_start:"<<data._rej_bf_start<<std::endl;
+
+      os<<"rej_few_fram:"<<data._rej_few_fram<<std::endl;
+
+      os<<"rej_many_fram:"<<data._rej_many_fram<<std::endl;
+
+      os<<"rej_mchn_err:"<<data._rej_mchn_err<<std::endl;
+
+      os<<"rej_vchn_err:"<<data._rej_vchn_err<<std::endl;
+
+      os<<"rej_rec_type:"<<data._rej_rec_type<<std::endl;
+
+      os<<"sens_config:"<<data._sens_config.c_str()<<std::endl;
+
+      os<<"sens_orient:"<<data._sens_orient.c_str()<<std::endl;
+
+      os<<"sych_marker:"<<data._sych_marker.c_str()<<std::endl;
+
+      os<<"rng_ref_src:"<<data._rng_ref_src.c_str()<<std::endl;
+
+      for (int i=0;i<4;i++)
+      {
+         os<<"rng_amp_coef["<<i<<"]:"<<data._rng_amp_coef[i]<<std::endl;
+      }
+
+      for (int i=0;i<4;i++)
+      {
+         os<<"rng_phas_coef["<<i<<"]:"<<data._rng_phas_coef[i]<<std::endl;
+      }
+
+      for (int i=0;i<4;i++)
+      {
+         os<<"err_amp_coef["<<i<<"]:"<<data._err_amp_coef[i]<<std::endl;
+      }
+
+      for (int i=0;i<4;i++)
+      {
+         os<<"err_phas_coef["<<i<<"]:"<<data._err_phas_coef[i]<<std::endl;
+      }
+
+      os<<"pulse_bandw:"<<data._pulse_bandw<<std::endl;
+
+
+      os<<"adc_samp_rate:"<<data._adc_samp_rate.c_str()<<std::endl;
+
+      os<<"rep_agc_attn:"<<data._rep_agc_attn<<std::endl;
+
+      os<<"gn_corctn_fctr:"<<data._gn_corctn_fctr<<std::endl;
+
+      os<<"rep_energy_gn:"<<data._rep_energy_gn<<std::endl;
+
+      os<<"orb_data_src:"<<data._orb_data_src.c_str()<<std::endl;
+
+      os<<"pulse_cnt_1:"<<data._pulse_cnt_1<<std::endl;
+
+      os<<"pulse_cnt_2:"<<data._pulse_cnt_2<<std::endl;
+
+      os<<"beam_edge_rqd:"<<data._beam_edge_rqd.c_str()<<std::endl;
+
+      os<<"beam_edge_conf:"<<data._beam_edge_conf<<std::endl;
+
+      os<<"pix_overlap:"<<data._pix_overlap<<std::endl;
+
+      os<<"n_beams:"<<data._n_beams<<std::endl;
+
+      for (int i=0;i<4;i++)
+      {
+         os<<"beam_info["<<i<<"]:"<<data._beam_info[i]<<std::endl;
+      }
+
+      os<<"n_pix_updates:"<<data._n_pix_updates<<std::endl;
+
+      for (int i=0;i<4;i++)
+      {
+         os<<"pix_count["<<i<<"]:"<<data._pix_count[i]<<std::endl;
+      }
+
+      os<<"pwin_start:"<<data._pwin_start<<std::endl;
+
+      os<<"pwin_end:"<<data._pwin_end<<std::endl;
+
+      os<<"recd_type:"<<data._recd_type.c_str()<<std::endl;
+
+      os<<"temp_set_inc:"<<data._temp_set_inc<<std::endl;
+
+      os<<"n_temp_set:"<<data._n_temp_set<<std::endl;
+
+      for (int i=0;i<20;i++)
+      {
+         os<<"temp["<<i<<"]:"<<data._temp[i]<<std::endl;
+      }
+
+      os<<"n_image_pix:"<<data._n_image_pix<<std::endl;
+
+      os<<"prc_zero_pix:"<<data._prc_zero_pix<<std::endl;
+
+      os<<"prc_satur_pix:"<<data._prc_satur_pix<<std::endl;
+
+      os<<"img_hist_mean:"<<data._img_hist_mean<<std::endl;
+
+      for (int i=0;i<3;i++)
+      {
+         os<<"img_cumu_dist["<<i<<"]:"<<data._img_cumu_dist[i]<<std::endl;
+      }
+
+      os<<"pre_img_gn:"<<data._pre_img_gn<<std::endl;
+
+      os<<"post_img_gn:"<<data._post_img_gn<<std::endl;
+
+      os<<"dopcen_inc:"<<data._dopcen_inc<<std::endl;
+
+      os<<"n_dopcen:"<<data._n_dopcen<<std::endl;
+
+      for (int i=0;i<20;i++)
+      {
+         os<<"dopcen_est["<<i<<"]:"<<data._dopcen_est[i]<<std::endl;
+      }
+
+      os<<"dop_amb_err:"<<data._dop_amb_err<<std::endl;
+
+      os<<"dopamb_conf:"<<data._dopamb_conf<<std::endl;
+
+      for (int i=0;i<7;i++)
+      {
+         os<<"eph_orb_data["<<i<<"]:"<<data._eph_orb_data[i]<<std::endl;
+      }
+
+      os<<"appl_type:"<<data._appl_type.c_str()<<std::endl;
+
+      for (int i=0;i<5;i++)
+      {
+         os<<"slow_time_coef["<<i<<"]:"<<data._slow_time_coef[i]<<std::endl;
+      }
+
+      os<<"n_srgr:"<<data._n_srgr<<std::endl;
+
+      for (int i=0;i<20;i++)
+      {
+         os<<"srgr_coefset["<<i<<"]:"<<data._srgr_coefset[i]<<std::endl;
+      }
+
+      os<<"pixel_spacing:"<<data._pixel_spacing<<std::endl;
+
+      os<<"gics_reqd:"<<data._gics_reqd.c_str()<<std::endl;
+
+      os<<"wo_number:"<<data._wo_number.c_str()<<std::endl;
+
+      os<<"wo_date:"<<data._wo_date.c_str()<<std::endl;
+
+      os<<"satellite_id:"<<data._satellite_id.c_str()<<std::endl;
+
+      os<<"user_id:"<<data._user_id.c_str()<<std::endl;
+
+      os<<"complete_msg:"<<data._complete_msg.c_str()<<std::endl;
+
+      os<<"scene_id:"<<data._scene_id.c_str()<<std::endl;
+
+      os<<"density_in:"<<data._density_in.c_str()<<std::endl;
+
+      os<<"media_id:"<<data._media_id.c_str()<<std::endl;
+
+      os<<"angle_first:"<<data._angle_first<<std::endl;
+
+      os<<"angle_last:"<<data._angle_last<<std::endl;
+
+      os<<"prod_type:"<<data._prod_type.c_str()<<std::endl;
+
+      os<<"map_system:"<<data._map_system.c_str()<<std::endl;
+
+      os<<"centre_lat:"<<data._centre_lat<<std::endl;
+
+      os<<"centre_long:"<<data._centre_long<<std::endl;
+
+      os<<"span_x:"<<data._span_x<<std::endl;
+
+      os<<"span_y:"<<data._span_y<<std::endl;
+
+      os<<"apply_dtm:"<<data._apply_dtm.c_str()<<std::endl;
+
+      os<<"density_out:"<<data._density_out.c_str()<<std::endl;
+
+      os<<"state_time:"<<data._state_time.c_str()<<std::endl;
+
+      os<<"num_state_vectors:"<<data._num_state_vectors<<std::endl;
+
+      os<<"state_time_inc:"<<data._state_time_inc<<std::endl;
+
+      return os;
+   }
+
+   std::istream& operator>>(std::istream& is, ProcessingParameters& data)
+   {
+      char buf[2407];
+      buf[2406] = '\0';
+
+      is.read(buf,4);
+      buf[4] = '\0';
+      data._rec_seq = atoi(buf);
+
+      is.read(buf,4);
+      buf[4] = '\0';
+
+      is.read(buf,3);
+      buf[3] = '\0';
+      data._inp_media = buf;
+
+      is.read(buf,4);
+      buf[4] = '\0';
+      data._n_tape_id = atoi(buf);
+
+      for (int i=0;i<10;i++)
+      {
+         is.read(buf,8);
+         buf[8] = '\0';
+         data._tape_id[i] = buf;
+      }
+
+      is.read(buf,21);
+      buf[21] = '\0';
+      data._exp_ing_start = buf;
+
+      is.read(buf,21);
+      buf[21] = '\0';
+      data._exp_ing_stop = buf;
+
+      is.read(buf,21);
+      buf[21] = '\0';
+      data._act_ing_start = buf;
+
+      is.read(buf,21);
+      buf[21] = '\0';
+      data._act_ing_stop = buf;
+
+      is.read(buf,21);
+      buf[21] = '\0';
+      data._proc_start = buf;
+
+      is.read(buf,21);
+      buf[21] = '\0';
+      data._proc_stop = buf;
+
+      for (int i=0;i<10;i++)
+      {
+         is.read(buf,16);
+         buf[16] = '\0';
+         data._mn_sig_lev[i] = atof(buf);
+      }
+
+      is.read(buf,4);
+      buf[4] = '\0';
+      data._scr_data_ind = atoi(buf);
+
+      is.read(buf,8);
+      buf[8] = '\0';
+      data._miss_ln = atoi(buf);
+
+      is.read(buf,8);
+      buf[8] = '\0';
+      data._rej_ln = atoi(buf);
+
+      is.read(buf,8);
+      buf[8] = '\0';
+      data._large_gap = atoi(buf);
+
+      is.read(buf,16);
+      buf[16] = '\0';
+      data._bit_err_rate = atof(buf);
+
+      is.read(buf,16);
+      buf[16] = '\0';
+      data._fm_crc_err = atof(buf);
+
+      is.read(buf,8);
+      buf[8] = '\0';
+      data._date_incons = atoi(buf);
+
+      is.read(buf,8);
+      buf[8] = '\0';
+      data._prf_changes = atoi(buf);
+
+      is.read(buf,8);
+      buf[8] = '\0';
+      data._delay_changes = atoi(buf);
+
+      is.read(buf,8);
+      buf[8] = '\0';
+      data._skipd_frams = atoi(buf);
+
+      is.read(buf,8);
+      buf[8] = '\0';
+      data._rej_bf_start = atoi(buf);
+
+      is.read(buf,8);
+      buf[8] = '\0';
+      data._rej_few_fram = atoi(buf);
+
+      is.read(buf,8);
+      buf[8] = '\0';
+      data._rej_many_fram = atoi(buf);
+
+      is.read(buf,8);
+      buf[8] = '\0';
+      data._rej_mchn_err = atoi(buf);
+
+      is.read(buf,8);
+      buf[8] = '\0';
+      data._rej_vchn_err = atoi(buf);
+
+      is.read(buf,8);
+      buf[8] = '\0';
+      data._rej_rec_type = atoi(buf);
+
+      is.read(buf,10);
+      buf[10] = '\0';
+      data._sens_config = buf;
+
+      is.read(buf,9);
+      buf[9] = '\0';
+      data._sens_orient = buf;
+
+      is.read(buf,8);
+      buf[8] = '\0';
+      data._sych_marker = buf;
+
+      is.read(buf,12);
+      buf[12] = '\0';
+      data._rng_ref_src = buf;
+
+      for (int i=0;i<4;i++)
+      {
+         is.read(buf,16);
+         buf[16] = '\0';
+         data._rng_amp_coef[i] = atof(buf);
+      }
+
+      for (int i=0;i<4;i++)
+      {
+         is.read(buf,16);
+         buf[16] = '\0';
+         data._rng_phas_coef[i] = atof(buf);
+      }
+
+      for (int i=0;i<4;i++)
+      {
+         is.read(buf,16);
+         buf[16] = '\0';
+         data._err_amp_coef[i] = atof(buf);
+      }
+
+      for (int i=0;i<4;i++)
+      {
+         is.read(buf,16);
+         buf[16] = '\0';
+         data._err_phas_coef[i] = atof(buf);
+      }
+
+      is.read(buf,4);
+      buf[4] = '\0';
+      data._pulse_bandw = atoi(buf);
+
+
+      is.read(buf,5);
+      buf[5] = '\0';
+      data._adc_samp_rate = buf;
+
+      is.read(buf,16);
+      buf[16] = '\0';
+      data._rep_agc_attn = atof(buf);
+
+      is.read(buf,16);
+      buf[16] = '\0';
+      data._gn_corctn_fctr = atof(buf);
+
+      is.read(buf,16);
+      buf[16] = '\0';
+      data._rep_energy_gn = atof(buf);
+
+      is.read(buf,11);
+      buf[11] = '\0';
+      data._orb_data_src = buf;
+
+      is.read(buf,4);
+      buf[4] = '\0';
+      data._pulse_cnt_1 = atoi(buf);
+
+      is.read(buf,4);
+      buf[4] = '\0';
+      data._pulse_cnt_2 = atoi(buf);
+
+      is.read(buf,3);
+      buf[3] = '\0';
+      data._beam_edge_rqd = buf;
+
+      is.read(buf,16);
+      buf[16] = '\0';
+      data._beam_edge_conf = atof(buf);
+
+      is.read(buf,4);
+      buf[4] = '\0';
+      data._pix_overlap = atoi(buf);
+
+      is.read(buf,4);
+      buf[4] = '\0';
+      data._n_beams = atoi(buf);
+
+      for (int i=0;i<4;i++)
+      {
+         is>>data._beam_info[i];
+      }
+
+      is.read(buf,4);
+      buf[4] = '\0';
+      data._n_pix_updates = atoi(buf);
+
+      for (int i=0;i<20;i++)
+      {
+         is>>data._pix_count[i];
+      }
+
+      is.read(buf,16);
+      buf[16] = '\0';
+      data._pwin_start = atof(buf);
+
+      is.read(buf,16);
+      buf[16] = '\0';
+      data._pwin_end = atof(buf);
+
+      is.read(buf,9);
+      buf[9] = '\0';
+      data._recd_type = buf;
+
+      is.read(buf,16);
+      buf[16] = '\0';
+      data._temp_set_inc = atof(buf);
+
+      is.read(buf,4);
+      buf[4] = '\0';
+      data._n_temp_set = atoi(buf);
+
+      for (int i=0;i<20;i++)
+      {
+         is>>data._temp[i];
+      }
+
+      is.read(buf,8);
+      buf[8] = '\0';
+      data._n_image_pix = atoi(buf);
+
+      is.read(buf,16);
+      buf[16] = '\0';
+      data._prc_zero_pix = atof(buf);
+
+      is.read(buf,16);
+      buf[16] = '\0';
+      data._prc_satur_pix = atof(buf);
+
+      is.read(buf,16);
+      buf[16] = '\0';
+      data._img_hist_mean = atof(buf);
+
+      for (int i=0;i<3;i++)
+      {
+         is.read(buf,16);
+         buf[16] = '\0';
+         data._img_cumu_dist[i] = atof(buf);
+      }
+
+      is.read(buf,16);
+      buf[16] = '\0';
+      data._pre_img_gn = atof(buf);
+
+      is.read(buf,16);
+      buf[16] = '\0';
+      data._post_img_gn = atof(buf);
+
+      is.read(buf,16);
+      buf[16] = '\0';
+      data._dopcen_inc = atof(buf);
+
+      is.read(buf,4);
+      buf[4] = '\0';
+      data._n_dopcen = atoi(buf);
+
+      for (int i=0;i<20;i++)
+      {
+         is>>data._dopcen_est[i];
+      }
+
+      is.read(buf,4);
+      buf[4] = '\0';
+      data._dop_amb_err = atoi(buf);
+
+      is.read(buf,16);
+      buf[16] = '\0';
+      data._dopamb_conf = atof(buf);
+
+      for (int i=0;i<7;i++)
+      {
+         is.read(buf,16);
+         buf[16] = '\0';
+         data._eph_orb_data[i] = atof(buf);
+      }
+
+      is.read(buf,12);
+      buf[12] = '\0';
+      data._appl_type = buf;
+
+      for (int i=0;i<5;i++)
+      {
+         is.read(buf,22);
+         buf[22] = '\0';
+         data._slow_time_coef[i] = atof(buf);
+      }
+
+      is.read(buf,4);
+      buf[4] = '\0';
+      data._n_srgr = atoi(buf);
+
+      for (int i=0;i<20;i++)
+      {
+         is>>data._srgr_coefset[i];
+      }
+
+      is.read(buf,16);
+      buf[16] = '\0';
+      data._pixel_spacing = atof(buf);
+
+      is.read(buf,3);
+      buf[3] = '\0';
+      data._gics_reqd = buf;
+
+      is.read(buf,8);
+      buf[8] = '\0';
+      data._wo_number = buf;
+
+      is.read(buf,20);
+      buf[20] = '\0';
+      data._wo_date = buf;
+
+      is.read(buf,10);
+      buf[10] = '\0';
+      data._satellite_id = buf;
+
+      is.read(buf,20);
+      buf[20] = '\0';
+      data._user_id = buf;
+
+      is.read(buf,3);
+      buf[3] = '\0';
+      data._complete_msg = buf;
+
+      is.read(buf,15);
+      buf[15] = '\0';
+      data._scene_id = buf;
+
+      is.read(buf,4);
+      buf[4] = '\0';
+      data._density_in = buf;
+
+      is.read(buf,8);
+      buf[8] = '\0';
+      data._media_id = buf;
+
+      is.read(buf,16);
+      buf[16] = '\0';
+      data._angle_first = atof(buf);
+
+      is.read(buf,16);
+      buf[16] = '\0';
+      data._angle_last = atof(buf);
+
+      is.read(buf,3);
+      buf[3] = '\0';
+      data._prod_type = buf;
+
+      is.read(buf,16);
+      buf[16] = '\0';
+      data._map_system = buf;
+
+      is.read(buf,22);
+      buf[22] = '\0';
+      data._centre_lat = atof(buf);
+
+      is.read(buf,22);
+      buf[22] = '\0';
+      data._centre_long = atof(buf);
+
+      is.read(buf,22);
+      buf[22] = '\0';
+      data._span_x = atof(buf);
+
+      is.read(buf,22);
+      buf[22] = '\0';
+      data._span_y = atof(buf);
+
+      is.read(buf,3);
+      buf[3] = '\0';
+      data._apply_dtm = buf;
+
+      is.read(buf,4);
+      buf[4] = '\0';
+      data._density_out = buf;
+
+      is.read(buf,21);
+      buf[21] = '\0';
+      data._state_time = buf;
+
+      is.read(buf,4);
+      buf[4] = '\0';
+      data._num_state_vectors = atoi(buf);
+
+      is.read(buf,16);
+      buf[16] = '\0';
+      data._state_time_inc = atof(buf);
+
+      is.read(buf,206);
+      buf[206] = '\0';
+
+      return is;
+   }
+
+   ProcessingParameters::ProcessingParameters(const ProcessingParameters& rhs):
+      RadarSatRecord(rhs)
+   {
+
+   }
+
+   ProcessingParameters& ProcessingParameters::operator=(const ProcessingParameters& /* rhs */)
+   {
+      /*
+	int   _rec_seq
+
+	std::string   _spare1
+
+	std::string  _inp_media
+
+	int   _n_tape_id
+
+	std::string   _tape_id
+
+	std::string   _exp_ing_start
+
+	std::string   _exp_ing_stop
+
+	std::string   _act_ing_start
+
+	std::string   _act_ing_stop
+
+	std::string   _proc_start
+
+	std::string   _proc_stop
+
+	double*   _mn_sig_lev
+
+	int   _scr_data_ind
+
+	int   _miss_ln
+
+	int   _rej_ln
+
+	int   _large_gap
+
+	double   _bit_err_rate
+
+	double   _fm_crc_err
+
+	int   _date_incons
+
+	int   _prf_changes
+
+	int   _delay_changes
+
+	int   _skipd_frams
+
+	int   _rej_bf_start
+
+	int   _rej_few_fram
+
+	int   _rej_many_fram
+
+	int   _rej_mchn_err
+
+	int   _rej_vchn_err
+
+	int   _rej_rec_type
+
+	std::string   _sens_config
+
+	std::string   _sens_orient
+
+	int   _sych_marker
+
+	std::string   _rng_ref_src
+
+	double*   _rng_amp_coef
+
+	double*   _rng_phas_coef
+
+	double*   _err_amp_coef
+
+	double*   _err_phas_coef
+
+	int   _pulse_bandw
+
+	int   _adc_samp_rate
+
+	double   _rep_agc_attn
+
+	double   _gn_corctn_fctr
+
+	double   _rep_energy_gn
+
+	std::string   _orb_data_src
+
+	int   _pulse_cnt_1
+
+	int   _pulse_cnt_2
+
+	std::string    _beam_edge_rqd
+
+	double   _beam_edge_conf
+
+	int   _pix_overlap
+
+	int   _n_beams
+
+	BeamInformationRecord* _beam_info
+
+	int   _n_pix_updates
+
+	BeamPixelCountRecord* _pix_count
+
+	double   _pwin_start
+
+	double   _pwin_end
+
+	std::string   _recd_type
+
+	double   _temp_set_inc
+
+	int*   _n_temp_set
+
+	TemperatureSettingsRecord* _temp
+
+	int   _n_image_pix
+
+	double   _prc_zero_pix
+
+	double   _prc_satur_pix
+
+	double   _img_hist_mean
+
+	double*   _img_cumu_dist
+
+	double   _pre_img_gn
+
+	double   _post_img_gn
+
+	double   _dopcen_inc
+
+	int   _n_dopcen
+
+	DopplerCentroidEstimateRecord* _dopcen_est
+
+	int   _dop_amb_err
+
+	double   _dopamb_conf
+
+	double*   _eph_orb_data
+
+	std::string   _appl_type
+
+	double*   _slow_time_coef
+
+	int   _n_srgr
+
+	SRGRCoefficientSetRecord* _srgr_coefset
+
+	double   _pixel_spacing
+
+	std::string   _gics_reqd
+
+	std::string   _wo_number
+
+	std::string   _wo_date
+
+	std::string   _satellite_id
+
+	std::string   _user_id
+
+	std::string   _complete_msg
+
+	std::string   _scene_id
+
+	std::string   _density_in
+
+	std::string   _media_id
+
+	double   _angle_first
+
+	double   _angle_last
+
+	std::string   _prod_type
+
+	std::string   _map_system
+
+	double   _centre_lat
+
+	double   _centre_long
+
+	double   _span_x
+
+	double   _span_y
+
+	std::string   _apply_dtm
+
+	std::string   _density_out
+
+	std::string   _state_time
+
+	int   _num_state_vectors
+
+	double   _state_time_inc
+
+	std::string   _spare2*/
+      return *this;
+   }
+}
+
diff --git a/ossim_plugins/ossim/RadarSat/CommonRecord/ProcessingParameters.h b/ossim_plugins/ossim/RadarSat/CommonRecord/ProcessingParameters.h
new file mode 100755
index 0000000..76c2dd8
--- /dev/null
+++ b/ossim_plugins/ossim/RadarSat/CommonRecord/ProcessingParameters.h
@@ -0,0 +1,1162 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef ProcessingParameters_h
+#define ProcessingParameters_h
+
+#include <iostream>
+#include <RadarSat/RadarSatRecord.h>
+#include <RadarSat/RadarSatRecordHeader.h>
+
+#include "BeamInformationRecord.h"
+#include "DopplerCentroidEstimateRecord.h"
+#include "BeamPixelCountRecord.h"
+#include "SRGRCoefficientSetRecord.h"
+#include "TemperatureSettingsRecord.h"
+
+namespace ossimplugins
+{
+/**
+ * @ingroup ProcessingParametersRecord
+ * @brief This class is able to read a Detailed processing parameters record
+ */
+class ProcessingParameters : public RadarSatRecord
+{
+public:
+  /**
+   * @brief Constructor
+   */
+  ProcessingParameters();
+
+  /**
+   * @brief Destructor
+   */
+  ~ProcessingParameters();
+
+  /**
+   * @brief Copy constructor
+   */
+  ProcessingParameters(const ProcessingParameters& rhs);
+
+  /**
+   * @brief Copy operator
+   */
+  ProcessingParameters& operator=(const ProcessingParameters& rhs);
+  /**
+   * @brief This function writes the ProcessingParameters in a stream
+   */
+  friend std::ostream& operator<<(std::ostream& os, const ProcessingParameters& data);
+
+  /**
+   * @brief This function reads a ProcessingParameters from a stream
+   */
+  friend std::istream& operator>>(std::istream& is, ProcessingParameters& data);
+
+  /**
+   * @brief This function is able to create a new instance of the class
+   */
+  RadarSatRecord* Instanciate()
+  {
+    return new ProcessingParameters();
+  };
+
+  /**
+   * @brief This function is able to create a new instance of the class initialised with the data of the calling instance
+   */
+  RadarSatRecord* Clone()
+  {
+    return new ProcessingParameters(*this);
+  };
+
+  /**
+   * @brief Reads the class data from a stream
+   */
+  void Read(std::istream& is)
+  {
+    is>>*this;
+  };
+
+  /**
+   * @brief Writes the class to a stream
+   */
+  void Write(std::ostream& os)
+  {
+    os<<*this;
+  };
+
+  /**
+   * @brief Record sequence number
+   */
+  int   get_rec_seq()
+  {
+    return _rec_seq;
+  };
+
+    /**
+   * @brief Input media
+   */
+  std::string  get_inp_media()
+  {
+    return  _inp_media;
+  };
+    /**
+   * @brief Number of tape input ids
+   */
+  int   get_n_tape_id()
+  {
+    return _n_tape_id;
+  };
+    /**
+   * @brief Tape identifiers
+   */
+  std::string*   get_tape_id()
+  {
+    return _tape_id;
+  };
+    /**
+   * @brief Expected ingest start time
+   */
+  std::string   get_exp_ing_start()
+  {
+    return _exp_ing_start;
+  };
+    /**
+   * @brief Expected ingest stop time
+   */
+  std::string   get_exp_ing_stop()
+  {
+    return _exp_ing_stop;
+  };
+    /**
+   * @brief Actual ingest start time
+   */
+  std::string   get_act_ing_start()
+  {
+    return _act_ing_start;
+  };
+    /**
+   * @brief Actual ingest stop time
+   */
+  std::string   get_act_ing_stop()
+  {
+    return _act_ing_stop;
+  };
+    /**
+   * @brief Processing start time
+   */
+  std::string   get_proc_start()
+  {
+    return _proc_start;
+  };
+    /**
+   * @brief Processing stop time
+   */
+  std::string   get_proc_stop()
+  {
+    return _proc_stop;
+  };
+    /**
+   * @brief Mean signal levels across range
+   */
+  double*   get_mn_sig_lev()
+  {
+    return _mn_sig_lev;
+  };
+    /**
+   * @brief Source data quality indicator
+   */
+  int   get_scr_data_ind()
+  {
+    return _scr_data_ind;
+  };
+    /**
+   * @brief Number of missing lines
+   */
+  int   get_miss_ln()
+  {
+    return _miss_ln;
+  };
+    /**
+   * @brief Number of rejected lines
+   */
+  int   get_rej_ln()
+  {
+    return _rej_ln;
+  };
+    /**
+   * @brief Number of time inconsistencies (large gaps)
+   */
+  int   get_large_gap()
+  {
+    return _large_gap;
+  };
+    /**
+   * @brief Measured bit error rate
+   */
+  double   get_bit_err_rate()
+  {
+    return _bit_err_rate;
+  };
+    /**
+   * @brief Percent of frames with CRC errors
+   */
+  double   get_fm_crc_err()
+  {
+    return _fm_crc_err;
+  };
+    /**
+   * @brief Number of date inconsistencies
+   */
+  int   get_date_incons()
+  {
+    return _date_incons;
+  };
+    /**
+   * @brief Number of unexpected PRF changes
+   */
+  int   get_prf_changes()
+  {
+    return _prf_changes;
+  };
+    /**
+   * @brief Number of delay changes
+   */
+  int   get_delay_changes()
+  {
+    return _delay_changes;
+  };
+    /**
+   * @brief Number of skipped frames
+   */
+  int   get_skipd_frams()
+  {
+    return _skipd_frams;
+  };
+    /**
+   * @brief Range lines rejected before start time
+   */
+  int   get_rej_bf_start()
+  {
+    return _rej_bf_start;
+  };
+    /**
+   * @brief Range lines rejected due to too few frames
+   */
+  int   get_rej_few_fram()
+  {
+    return _rej_few_fram;
+  };
+    /**
+   * @brief Range lines rejected due to too many frames
+   */
+  int   get_rej_many_fram()
+  {
+    return _rej_many_fram;
+  };
+    /**
+   * @brief Frames rejected due to master channel error
+   */
+  int   get_rej_mchn_err()
+  {
+    return _rej_mchn_err;
+  };
+    /**
+   * @brief Frames rejected due to virtual channel error
+   */
+  int   get_rej_vchn_err()
+  {
+    return _rej_vchn_err;
+  };
+    /**
+   * @brief Frames rejected due to incorrect recording type
+   */
+  int   get_rej_rec_type()
+  {
+    return _rej_rec_type;
+  };
+    /**
+   * @brief Sensor configuration
+   */
+  std::string   get_sens_config()
+  {
+    return _sens_config;
+  };
+    /**
+   * @brief Sensor orientation
+   */
+  std::string   get_sens_orient()
+  {
+    return _sens_orient;
+  };
+    /**
+   * @brief Frame synch marker
+   */
+  std::string   get_sych_marker()
+  {
+    return _sych_marker;
+  };
+    /**
+   * @brief Range reference function source
+   */
+  std::string   get_rng_ref_src()
+  {
+    return _rng_ref_src;
+  };
+    /**
+   * @brief Range reference amplitude coefficients
+   */
+  double*   get_rng_amp_coef()
+  {
+    return _rng_amp_coef;
+  };
+    /**
+   * @brief Range reference phase coefficients
+   */
+  double*   get_rng_phas_coef()
+  {
+    return _rng_phas_coef;
+  };
+    /**
+   * @brief Error function amplitude coefficients
+   */
+  double*   get_err_amp_coef()
+  {
+    return _err_amp_coef;
+  };
+    /**
+   * @brief Error function phase coefficients
+   */
+  double*   get_err_phas_coef()
+  {
+    return _err_phas_coef;
+  };
+    /**
+   * @brief Pulse bandwidth code
+   */
+  int   get_pulse_bandw()
+  {
+    return _pulse_bandw;
+  };
+    /**
+   * @brief ADC sampling rate
+   */
+  std::string   get_adc_samp_rate()
+  {
+    return _adc_samp_rate;
+  };
+    /**
+   * @brief Replica AGC attenuation
+   */
+  double   get_rep_agc_attn()
+  {
+    return _rep_agc_attn;
+  };
+    /**
+   * @brief Gain correction factor (dB)
+   */
+  double   get_gn_corctn_fctr()
+  {
+    return _gn_corctn_fctr;
+  };
+    /**
+   * @brief Replica energy gain correction
+   */
+  double   get_rep_energy_gn()
+  {
+    return _rep_energy_gn;
+  };
+    /**
+   * @brief Orbit data source
+   */
+  std::string   get_orb_data_src()
+  {
+    return _orb_data_src;
+  };
+    /**
+   * @brief Pulse count 1
+   */
+  int   get_pulse_cnt_1()
+  {
+    return _pulse_cnt_1;
+  };
+    /**
+   * @brief Pulse count 2
+   */
+  int   get_pulse_cnt_2()
+  {
+    return _pulse_cnt_2;
+  };
+    /**
+   * @brief Beam edge detection requested
+   */
+  std::string    get_beam_edge_rqd()
+  {
+    return _beam_edge_rqd;
+  };
+    /**
+   * @brief Beam edge confidence measure
+   */
+  double   get_beam_edge_conf()
+  {
+    return _beam_edge_conf;
+  };
+    /**
+   * @brief Number of pixels in beam overlap
+   */
+  int   get_pix_overlap()
+  {
+    return _pix_overlap;
+  };
+    /**
+   * @brief Number of beams
+   */
+  int   get_n_beams()
+  {
+    return _n_beams;
+  };
+    /**
+   * @brief Beam info
+   */
+  BeamInformationRecord* get_beam_info()
+  {
+    return _beam_info;
+  };
+    /**
+   * @brief Number of pixel count updates
+   */
+  int   get_n_pix_updates()
+  {
+    return _n_pix_updates;
+  };
+  /**
+   * @brief Beam pixel counts
+   */
+  BeamPixelCountRecord* get_pix_count()
+  {
+    return _pix_count;
+  };
+    /**
+   * @brief Processing window start time (sec)
+   */
+  double   get_pwin_start()
+  {
+    return _pwin_start;
+  };
+    /**
+   * @brief Processing window end time (sec)
+   */
+  double   get_pwin_end()
+  {
+    return _pwin_end;
+  };
+    /**
+   * @brief Recording type
+   */
+  std::string   get_recd_type()
+  {
+    return _recd_type;
+  };
+    /**
+   * @brief Time increment between temperature settings (sec)
+   */
+  double   get_temp_set_inc()
+  {
+    return _temp_set_inc;
+  };
+    /**
+   * @brief Number of temperature settings
+   */
+  int   get_n_temp_set()
+  {
+    return _n_temp_set;
+  };
+  /**
+   * @brief Temperature settings
+   */
+  TemperatureSettingsRecord* get_temp()
+  {
+    return _temp;
+  };
+    /**
+   * @brief Number of image pixels
+   */
+  int   get_n_image_pix()
+  {
+    return _n_image_pix;
+  };
+    /**
+   * @brief Percent zero pixels
+   */
+  double   get_prc_zero_pix()
+  {
+    return _prc_zero_pix;
+  };
+    /**
+   * @brief Percent saturated pixels
+   */
+  double   get_prc_satur_pix()
+  {
+    return _prc_satur_pix;
+  };
+    /**
+   * @brief Image histogram mean intensity
+   */
+  double   get_img_hist_mean()
+  {
+    return _img_hist_mean;
+  };
+    /**
+   * @brief Image cumulative distribution
+   */
+  double*   get_img_cumu_dist()
+  {
+    return _img_cumu_dist;
+  };
+    /**
+   * @brief Pre-image calibration gain factor
+   */
+  double   get_pre_img_gn()
+  {
+    return _pre_img_gn;
+  };
+    /**
+   * @brief Post-image calibration gain factor
+   */
+  double   get_post_img_gn()
+  {
+    return _post_img_gn;
+  };
+    /**
+   * @brief Time increment between Dopcen estimates (sec)
+   */
+  double   get_dopcen_inc()
+  {
+    return _dopcen_inc;
+  };
+    /**
+   * @brief Number of Doppler centroid estimates
+   */
+  int   get_n_dopcen()
+  {
+    return _n_dopcen;
+  };
+  /**
+   * @brief Doppler centroid estimates
+   */
+  DopplerCentroidEstimateRecord* get_dopcen_est()
+  {
+    return _dopcen_est;
+  };
+    /**
+   * @brief Doppler ambiguity error
+   */
+  int   get_dop_amb_err()
+  {
+    return _dop_amb_err;
+  };
+    /**
+   * @brief Doppler ambiguity confidence measure
+   */
+  double   get_dopamb_conf()
+  {
+    return _dopamb_conf;
+  };
+    /**
+   * @brief Ephemeris orbit data
+   */
+  double*   get_eph_orb_data()
+  {
+    return _eph_orb_data;
+  };
+    /**
+   * @brief Application type
+   */
+  std::string   get_appl_type()
+  {
+    return _appl_type;
+  };
+    /**
+   * @brief  Slow time coefficients
+   * @todo Verifier le type de la variable lors de la lecture de la donnee
+   */
+  double*   get_slow_time_coef()
+  {
+    return _slow_time_coef;
+  };
+    /**
+   * @brief Number of SRGR coefficient sets
+   */
+  int   get_n_srgr()
+  {
+    return _n_srgr;
+  };
+  /**
+   * @brief SRGR coefficient sets
+   */
+  SRGRCoefficientSetRecord* get_srgr_coefset()
+  {
+    return _srgr_coefset;
+  };
+    /**
+   * @brief SGF product pixel spacing
+   */
+  double   get_pixel_spacing()
+  {
+    return _pixel_spacing;
+  };
+    /**
+   * @brief GICS product required
+   */
+  std::string   get_gics_reqd()
+  {
+    return _gics_reqd;
+  };
+    /**
+   * @brief Work order identifier
+   */
+  std::string   get_wo_number()
+  {
+    return _wo_number;
+  };
+    /**
+   * @brief Work order entry date
+   */
+  std::string   get_wo_date()
+  {
+    return _wo_date;
+  };
+    /**
+   * @brief Satellite identifier
+   */
+  std::string   get_satellite_id()
+  {
+    return _satellite_id;
+  };
+    /**
+   * @brief User id
+   */
+  std::string   get_user_id()
+  {
+    return _user_id;
+  };
+    /**
+   * @brief Completion message required flag
+   */
+  std::string   get_complete_msg()
+  {
+    return _complete_msg;
+  };
+    /**
+   * @brief SGF product scene identifier
+   */
+  std::string   get_scene_id()
+  {
+    return _scene_id;
+  };
+    /**
+   * @brief Density of SGF product media
+   */
+  std::string   get_density_in()
+  {
+    return _density_in;
+  };
+    /**
+   * @brief SGF product identifier
+   */
+  std::string   get_media_id()
+  {
+    return _media_id;
+  };
+    /**
+   * @brief Incidence angle of first pixel in SGF product line
+   */
+  double   get_angle_first()
+  {
+    return _angle_first;
+  };
+    /**
+   * @brief Incidence angle of last pixel in SGF product line
+   */
+  double   get_angle_last()
+  {
+    return _angle_last;
+  };
+    /**
+   * @brief GICS output product type
+   */
+  std::string   get_prod_type()
+  {
+    return _prod_type;
+  };
+    /**
+   * @brief Map system identifier
+   */
+  std::string   get_map_system()
+  {
+    return _map_system;
+  };
+    /**
+   * @brief GICS output product scene centre latitude
+   */
+  double   get_centre_lat()
+  {
+    return _centre_lat;
+  };
+    /**
+   * @brief GICS output product scene centre longitude
+   */
+  double   get_centre_long()
+  {
+    return _centre_long;
+  };
+    /**
+   * @brief GICS output product size - map eastings (km)
+   */
+  double   get_span_x()
+  {
+    return _span_x;
+  };
+    /**
+   * @brief GICS output product size - map northings (km)
+   */
+  double   get_span_y()
+  {
+    return _span_y;
+  };
+    /**
+   * @brief DTM correction to be applied flag
+   */
+  std::string   get_apply_dtm()
+  {
+    return _apply_dtm;
+  };
+    /**
+   * @brief GICS output product density
+   */
+  std::string   get_density_out()
+  {
+    return _density_out;
+  };
+    /**
+   * @brief Time of the first state vector
+   */
+  std::string   get_state_time()
+  {
+    return _state_time;
+  };
+    /**
+   * @brief Number of state vectors
+   */
+  int   get_num_state_vectors()
+  {
+    return _num_state_vectors;
+  };
+    /**
+   * @brief Time increment between state vectors
+   */
+  double   get_state_time_inc()
+  {
+    return _state_time_inc;
+  };
+
+protected:
+  /**
+   * @brief Record sequence number
+   */
+  int   _rec_seq;
+
+    /**
+   * @brief Input media
+   */
+  std::string   _inp_media;
+    /**
+   * @brief Number of tape input ids
+   */
+  int   _n_tape_id;
+    /**
+   * @brief Tape identifiers
+   */
+  std::string   _tape_id[10];
+    /**
+   * @brief Expected ingest start time
+   */
+  std::string   _exp_ing_start;
+    /**
+   * @brief Expected ingest stop time
+   */
+  std::string   _exp_ing_stop;
+    /**
+   * @brief Actual ingest start time
+   */
+  std::string   _act_ing_start;
+    /**
+   * @brief Actual ingest stop time
+   */
+  std::string   _act_ing_stop;
+    /**
+   * @brief Processing start time
+   */
+  std::string   _proc_start;
+    /**
+   * @brief Processing stop time
+   */
+  std::string   _proc_stop;
+    /**
+   * @brief Mean signal levels across range
+   */
+  double   _mn_sig_lev[10];
+    /**
+   * @brief Source data quality indicator
+   */
+  int   _scr_data_ind;
+    /**
+   * @brief Number of missing lines
+   */
+  int   _miss_ln;
+    /**
+   * @brief Number of rejected lines
+   */
+  int   _rej_ln;
+    /**
+   * @brief Number of time inconsistencies (large gaps)
+   */
+  int   _large_gap;
+    /**
+   * @brief Measured bit error rate
+   */
+  double   _bit_err_rate;
+    /**
+   * @brief Percent of frames with CRC errors
+   */
+  double   _fm_crc_err;
+    /**
+   * @brief Number of date inconsistencies
+   */
+  int   _date_incons;
+    /**
+   * @brief Number of unexpected PRF changes
+   */
+  int   _prf_changes;
+    /**
+   * @brief Number of delay changes
+   */
+  int   _delay_changes;
+    /**
+   * @brief Number of skipped frames
+   */
+  int   _skipd_frams;
+    /**
+   * @brief Range lines rejected before start time
+   */
+  int   _rej_bf_start;
+    /**
+   * @brief Range lines rejected due to too few frames
+   */
+  int   _rej_few_fram;
+    /**
+   * @brief Range lines rejected due to too many frames
+   */
+  int   _rej_many_fram;
+    /**
+   * @brief Frames rejected due to master channel error
+   */
+  int   _rej_mchn_err;
+    /**
+   * @brief Frames rejected due to virtual channel error
+   */
+  int   _rej_vchn_err;
+    /**
+   * @brief Frames rejected due to incorrect recording type
+   */
+  int   _rej_rec_type;
+    /**
+   * @brief Sensor configuration
+   */
+  std::string   _sens_config;
+    /**
+   * @brief Sensor orientation
+   */
+  std::string   _sens_orient;
+    /**
+   * @brief Frame synch marker
+   */
+  std::string   _sych_marker;
+    /**
+   * @brief Range reference function source
+   */
+  std::string   _rng_ref_src;
+    /**
+   * @brief Range reference amplitude coefficients
+   */
+  double   _rng_amp_coef[4];
+    /**
+   * @brief Range reference phase coefficients
+   */
+  double   _rng_phas_coef[4];
+    /**
+   * @brief Error function amplitude coefficients
+   */
+  double   _err_amp_coef[16];
+    /**
+   * @brief Error function phase coefficients
+   */
+  double   _err_phas_coef[4];
+    /**
+   * @brief Pulse bandwidth code
+   */
+  int   _pulse_bandw;
+    /**
+   * @brief ADC sampling rate
+   */
+  std::string   _adc_samp_rate;
+    /**
+   * @brief Replica AGC attenuation
+   */
+  double   _rep_agc_attn;
+    /**
+   * @brief Gain correction factor (dB)
+   */
+  double   _gn_corctn_fctr;
+    /**
+   * @brief Replica energy gain correction
+   */
+  double   _rep_energy_gn;
+    /**
+   * @brief Orbit data source
+   */
+  std::string   _orb_data_src;
+    /**
+   * @brief Pulse count 1
+   */
+  int   _pulse_cnt_1;
+    /**
+   * @brief Pulse count 2
+   */
+  int   _pulse_cnt_2;
+    /**
+   * @brief Beam edge detection requested
+   */
+  std::string    _beam_edge_rqd;
+    /**
+   * @brief Beam edge confidence measure
+   */
+  double   _beam_edge_conf;
+    /**
+   * @brief Number of pixels in beam overlap
+   */
+  int   _pix_overlap;
+    /**
+   * @brief Number of beams
+   */
+  int   _n_beams;
+    /**
+   * @brief Beam info
+   */
+  BeamInformationRecord _beam_info[4];
+    /**
+   * @brief Number of pixel count updates
+   */
+  int   _n_pix_updates;
+  /**
+   * @brief Beam pixel counts
+   */
+  BeamPixelCountRecord _pix_count[20];
+    /**
+   * @brief Processing window start time (sec)
+   */
+  double   _pwin_start;
+    /**
+   * @brief Processing window end time (sec)
+   */
+  double   _pwin_end;
+    /**
+   * @brief Recording type
+   */
+  std::string   _recd_type;
+    /**
+   * @brief Time increment between temperature settings (sec)
+   */
+  double   _temp_set_inc;
+    /**
+   * @brief Number of temperature settings
+   */
+  int   _n_temp_set;
+  /**
+   * @brief Temperature settings
+   */
+  TemperatureSettingsRecord _temp[20];
+    /**
+   * @brief Number of image pixels
+   */
+  int   _n_image_pix;
+    /**
+   * @brief Percent zero pixels
+   */
+  double   _prc_zero_pix;
+    /**
+   * @brief Percent saturated pixels
+   */
+  double   _prc_satur_pix;
+    /**
+   * @brief Image histogram mean intensity
+   */
+  double   _img_hist_mean;
+    /**
+   * @brief Image cumulative distribution
+   */
+  double   _img_cumu_dist[3];
+    /**
+   * @brief Pre-image calibration gain factor
+   */
+  double   _pre_img_gn;
+    /**
+   * @brief Post-image calibration gain factor
+   */
+  double   _post_img_gn;
+    /**
+   * @brief Time increment between Dopcen estimates (sec)
+   */
+  double   _dopcen_inc;
+    /**
+   * @brief Number of Doppler centroid estimates
+   */
+  int   _n_dopcen;
+  /**
+   * @brief Doppler centroid estimates
+   */
+  DopplerCentroidEstimateRecord _dopcen_est[20];
+    /**
+   * @brief Doppler ambiguity error
+   */
+  int   _dop_amb_err;
+    /**
+   * @brief Doppler ambiguity confidence measure
+   */
+  double   _dopamb_conf;
+    /**
+   * @brief Ephemeris orbit data
+   */
+  double   _eph_orb_data[7];
+    /**
+   * @brief Application type
+   */
+  std::string   _appl_type;
+    /**
+   * @brief  Slow time coefficients
+   * @todo Verifier le type de la variable lors de la lecture de la donnee
+   */
+  double   _slow_time_coef[5];
+    /**
+   * @brief Number of SRGR coefficient sets
+   */
+  int   _n_srgr;
+  /**
+   * @brief SRGR coefficient sets
+   */
+  SRGRCoefficientSetRecord _srgr_coefset[20];
+    /**
+   * @brief SGF product pixel spacing
+   */
+  double   _pixel_spacing;
+    /**
+   * @brief GICS product required
+   */
+  std::string   _gics_reqd;
+    /**
+   * @brief Work order identifier
+   */
+  std::string   _wo_number;
+    /**
+   * @brief Work order entry date
+   */
+  std::string   _wo_date;
+    /**
+   * @brief Satellite identifier
+   */
+  std::string   _satellite_id;
+    /**
+   * @brief User id
+   */
+  std::string   _user_id;
+    /**
+   * @brief Completion message required flag
+   */
+  std::string   _complete_msg;
+    /**
+   * @brief SGF product scene identifier
+   */
+  std::string   _scene_id;
+    /**
+   * @brief Density of SGF product media
+   */
+  std::string   _density_in;
+    /**
+   * @brief SGF product identifier
+   */
+  std::string   _media_id;
+    /**
+   * @brief Incidence angle of first pixel in SGF product line
+   */
+  double   _angle_first;
+    /**
+   * @brief Incidence angle of last pixel in SGF product line
+   */
+  double   _angle_last;
+    /**
+   * @brief GICS output product type
+   */
+  std::string   _prod_type;
+    /**
+   * @brief Map system identifier
+   */
+  std::string   _map_system;
+    /**
+   * @brief GICS output product scene centre latitude
+   */
+  double   _centre_lat;
+    /**
+   * @brief GICS output product scene centre longitude
+   */
+  double   _centre_long;
+    /**
+   * @brief GICS output product size - map eastings (km)
+   */
+  double   _span_x;
+    /**
+   * @brief GICS output product size - map northings (km)
+   */
+  double   _span_y;
+    /**
+   * @brief DTM correction to be applied flag
+   */
+  std::string   _apply_dtm;
+    /**
+   * @brief GICS output product density
+   */
+  std::string   _density_out;
+    /**
+   * @brief Time of the first state vector
+   */
+  std::string   _state_time;
+    /**
+   * @brief Number of state vectors
+   */
+  int   _num_state_vectors;
+    /**
+   * @brief Time increment between state vectors
+   */
+  double   _state_time_inc;
+
+private:
+};
+}
+#endif
+
diff --git a/ossim_plugins/ossim/RadarSat/CommonRecord/RadiometricCompensationData.cpp b/ossim_plugins/ossim/RadarSat/CommonRecord/RadiometricCompensationData.cpp
new file mode 100755
index 0000000..ea9dc03
--- /dev/null
+++ b/ossim_plugins/ossim/RadarSat/CommonRecord/RadiometricCompensationData.cpp
@@ -0,0 +1,92 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include "RadiometricCompensationData.h"
+
+namespace ossimplugins
+{
+   RadiometricCompensationData::RadiometricCompensationData() : RadarSatRecord("radi_comp_rec")
+   {
+   }
+
+   RadiometricCompensationData::~RadiometricCompensationData()
+   {
+   }
+
+   std::ostream& operator<<(std::ostream& os, const RadiometricCompensationData& data)
+   {
+      os<<"seq_num:"<<data._seq_num<<std::endl;
+
+      os<<"chan_ind:"<<data._chan_ind<<std::endl;
+
+      os<<"n_dset:"<<data._n_dset<<std::endl;
+
+      os<<"dset_size:"<<data._dset_size<<std::endl;
+
+      for (int i=0;i<4;i++)
+      {
+         os<<"dset["<<i<<"]:"<<data._dset[i]<<std::endl;
+      }
+      return os;
+   }
+
+   std::istream& operator>>(std::istream& is, RadiometricCompensationData& data)
+   {
+      char buf[9];
+      buf[8] = '\0';
+
+      is.read(buf,4);
+      buf[4] = '\0';
+      data._seq_num = atoi(buf);
+
+      is.read(buf,4);
+      buf[4] = '\0';
+      data._chan_ind = atoi(buf);
+
+      is.read(buf,8);
+      buf[8] = '\0';
+      data._n_dset = atoi(buf);
+
+      is.read(buf,8);
+      buf[8] = '\0';
+      data._dset_size = atoi(buf);
+
+      for (int i=0;i<4;i++)
+      {
+         is>> data._dset[i];
+      }
+
+      return is;
+   }
+
+   RadiometricCompensationData::RadiometricCompensationData(const RadiometricCompensationData& rhs):
+      RadarSatRecord(rhs)
+   {
+      _seq_num = rhs._seq_num;
+
+      _chan_ind = rhs._chan_ind;
+
+      _n_dset = rhs._n_dset;
+
+      _dset_size = rhs._dset_size;
+
+      for (int i=0;i<4;i++)
+      {
+         _dset[i] = rhs._dset[i];
+      }
+   }
+
+   RadiometricCompensationData& RadiometricCompensationData::operator=(const RadiometricCompensationData& /* rhs */)
+   {
+      return *this;
+   }
+}
+
diff --git a/ossim_plugins/ossim/RadarSat/CommonRecord/RadiometricCompensationData.h b/ossim_plugins/ossim/RadarSat/CommonRecord/RadiometricCompensationData.h
new file mode 100755
index 0000000..9d52e47
--- /dev/null
+++ b/ossim_plugins/ossim/RadarSat/CommonRecord/RadiometricCompensationData.h
@@ -0,0 +1,153 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef RadiometricCompensationData_h
+#define RadiometricCompensationData_h
+
+#include <iostream>
+
+#include <RadarSat/RadarSatRecord.h>
+#include <RadarSat/RadarSatRecordHeader.h>
+
+#include "CompensationDataRecord.h"
+
+namespace ossimplugins
+{
+/**
+ * @ingroup RadiometricCompensationDataRecord
+ * @brief This class is able to read a Radiometric Compensation data record
+ */
+class RadiometricCompensationData : public RadarSatRecord
+{
+public:
+  /**
+   * @brief Constructor
+   */
+  RadiometricCompensationData();
+
+  /**
+   * @brief Destructor
+   */
+  ~RadiometricCompensationData();
+
+  /**
+   * @brief Copy constructor
+   */
+  RadiometricCompensationData(const RadiometricCompensationData& rhs);
+
+  /**
+   * @brief Copy operator
+   */
+  RadiometricCompensationData& operator=(const RadiometricCompensationData& rhs);
+  /**
+   * @brief This function writes the RadiometricCompensationData in a stream
+   */
+  friend std::ostream& operator<<(std::ostream& os, const RadiometricCompensationData& data);
+
+  /**
+   * @brief This function reads a RadiometricCompensationData from a stream
+   */
+  friend std::istream& operator>>(std::istream& is, RadiometricCompensationData& data);
+
+  /**
+   * @brief This function is able to create a new instance of the class
+   */
+  RadarSatRecord* Instanciate()
+  {
+    return new RadiometricCompensationData();
+  };
+
+  /**
+   * @brief This function is able to create a new instance of the class initialised with the data of the calling instance
+   */
+  RadarSatRecord* Clone()
+  {
+    return new RadiometricCompensationData(*this);
+  };
+
+  /**
+   * @brief Reads the class data from a stream
+   */
+  void Read(std::istream& is)
+  {
+    is>>*this;
+  };
+
+  /**
+   * @brief Writes the class to a stream
+   */
+  void Write(std::ostream& os)
+  {
+    os<<*this;
+  };
+
+  /**
+   * @brief Record sequence number
+   */
+  int  get_seq_num()
+  {
+    return _seq_num;
+  };
+  /**
+   * @brief SAR channel indicator
+   */
+  int   get_chan_ind()
+  {
+    return _chan_ind;
+  };
+    /**
+   * @brief Number of data sets in record
+   */
+  int   get_n_dset()
+  {
+    return _n_dset;
+  };
+    /**
+   * @brief Compensation data set size
+   */
+  int   get_dset_size()
+  {
+    return _dset_size;
+  };
+  /**
+   * @brief Compensation data set records
+   */
+  CompensationDataRecord* get_dset()
+  {
+    return _dset;
+  };
+
+protected:
+  /**
+   * @brief Record sequence number
+   */
+  int   _seq_num;
+  /**
+   * @brief SAR channel indicator
+   */
+  int   _chan_ind;
+    /**
+   * @brief Number of data sets in record
+   */
+  int   _n_dset;
+    /**
+   * @brief Compensation data set size
+   */
+  int   _dset_size;
+  /**
+   * @brief Compensation data set records
+   */
+  CompensationDataRecord _dset[4];
+private:
+};
+}
+#endif
+
diff --git a/ossim_plugins/ossim/RadarSat/CommonRecord/RadiometricData.cpp b/ossim_plugins/ossim/RadarSat/CommonRecord/RadiometricData.cpp
new file mode 100755
index 0000000..b3240d8
--- /dev/null
+++ b/ossim_plugins/ossim/RadarSat/CommonRecord/RadiometricData.cpp
@@ -0,0 +1,189 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include "RadiometricData.h"
+
+namespace ossimplugins
+{
+
+RadiometricData::RadiometricData() : RadarSatRecord("radi_data_rec")
+{
+}
+
+RadiometricData::~RadiometricData()
+{
+}
+
+std::ostream& operator<<(std::ostream& os, const RadiometricData& data)
+{
+	os<<"seq_num:"<<data._seq_num<<std::endl;
+
+    os<<"n_data:"<<data._n_data<<std::endl;
+
+    os<<"field_size:"<<data._field_size<<std::endl;
+
+	os<<"chan_ind:"<<data._chan_ind.c_str()<<std::endl;
+
+    os<<"table_desig:"<<data._table_desig.c_str()<<std::endl;
+
+    os<<"n_samp:"<<data._n_samp<<std::endl;
+
+    os<<"samp_type:"<<data._samp_type.c_str()<<std::endl;
+
+    os<<"samp_inc:"<<data._samp_inc<<std::endl;
+
+	for (int i=0;i<512;i++)
+	{
+		os<<"lookup_tab["<<i<<"]:"<<data._lookup_tab[i]<<std::endl;
+	}
+
+    os<<"noise_scale:"<<data._noise_scale<<std::endl;
+
+    os<<"offset:"<<data._offset<<std::endl;
+
+    os<<"calib_const:"<<data._calib_const<<std::endl;
+
+	return os;
+}
+
+std::istream& operator>>(std::istream& is, RadiometricData& data)
+{
+	char buf[1513];
+	buf[1512] = '\0';
+
+
+	is.read(buf,4);
+	buf[4] = '\0';
+	data._seq_num = atoi(buf);
+
+    is.read(buf,4);
+	buf[4] = '\0';
+	data._n_data = atoi(buf);
+
+    is.read(buf,8);
+	buf[8] = '\0';
+	data._field_size = atoi(buf);
+
+	is.read(buf,4);
+	buf[4] = '\0';
+	data._chan_ind = buf;
+
+    is.read(buf,4);
+
+    is.read(buf,24);
+	buf[24] = '\0';
+	data._table_desig = buf;
+
+    is.read(buf,8);
+	buf[8] = '\0';
+	data._n_samp = atoi(buf);
+
+    is.read(buf,16);
+	buf[16] = '\0';
+	data._samp_type = buf;
+
+    is.read(buf,4);
+	buf[4] = '\0';
+	data._samp_inc = atoi(buf);
+
+	for (int i=0;i<512;i++)
+	{
+		is.read(buf,16);
+		buf[16] = '\0';
+		data._lookup_tab[i] = atof(buf);
+	}
+
+    is.read(buf,4);
+
+    is.read(buf,16);
+	buf[16] = '\0';
+	data._noise_scale = atof(buf);
+
+    is.read(buf,16);
+
+    is.read(buf,16);
+	buf[16] = '\0';
+	data._offset = atof(buf);
+
+    is.read(buf,16);
+	buf[16] = '\0';
+	data._calib_const = atof(buf);
+
+	is.read(buf,1512);
+
+	return is;
+}
+
+RadiometricData::RadiometricData(const RadiometricData& rhs):
+	RadarSatRecord(rhs)
+{
+
+	_seq_num = rhs._seq_num;
+
+    _n_data = rhs._n_data;
+
+    _field_size = rhs._field_size;
+
+	_chan_ind = rhs._chan_ind;
+
+    _table_desig = rhs._table_desig;
+
+    _n_samp = rhs._n_samp;
+
+    _samp_type = rhs._samp_type;
+
+    _samp_inc = rhs._samp_inc;
+
+	for (int i=0;i<512;i++)
+	{
+		_lookup_tab[i] = rhs._lookup_tab[i];
+	}
+
+    _noise_scale = rhs._noise_scale;
+
+    _offset = rhs._offset;
+
+    _calib_const = rhs._calib_const;
+}
+
+RadiometricData& RadiometricData::operator=(const RadiometricData& rhs)
+{
+	_seq_num = rhs._seq_num;
+
+    _n_data = rhs._n_data;
+
+    _field_size = rhs._field_size;
+
+	_chan_ind = rhs._chan_ind;
+
+    _table_desig = rhs._table_desig;
+
+    _n_samp = rhs._n_samp;
+
+    _samp_type = rhs._samp_type;
+
+    _samp_inc = rhs._samp_inc;
+
+	for (int i=0;i<512;i++)
+	{
+		_lookup_tab[i] = rhs._lookup_tab[i];
+	}
+
+    _noise_scale = rhs._noise_scale;
+
+    _offset = rhs._offset;
+
+    _calib_const = rhs._calib_const;
+
+	return *this;
+}
+}
+
diff --git a/ossim_plugins/ossim/RadarSat/CommonRecord/RadiometricData.h b/ossim_plugins/ossim/RadarSat/CommonRecord/RadiometricData.h
new file mode 100755
index 0000000..e58ca99
--- /dev/null
+++ b/ossim_plugins/ossim/RadarSat/CommonRecord/RadiometricData.h
@@ -0,0 +1,237 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef RadiometricData_h
+#define RadiometricData_h
+
+#include <iostream>
+#include <RadarSat/RadarSatRecord.h>
+#include <RadarSat/RadarSatRecordHeader.h>
+
+namespace ossimplugins
+{
+/**
+ * @ingroup RadiometricDataRecord
+ * @brief This class is able to read a radiometric data record
+ */
+class RadiometricData : public RadarSatRecord
+{
+public:
+  /**
+   * @brief Constructor
+   */
+  RadiometricData();
+
+  /**
+   * @brief Destructor
+   */
+  ~RadiometricData();
+
+  /**
+   * @brief Copy constructor
+   */
+  RadiometricData(const RadiometricData& rhs);
+
+  /**
+   * @brief Copy operator
+   */
+  RadiometricData& operator=(const RadiometricData& rhs);
+  /**
+   * @brief This function writes the RadiometricData in a stream
+   */
+  friend std::ostream& operator<<(std::ostream& os, const RadiometricData& data);
+
+  /**
+   * @brief This function reads a RadiometricData from a stream
+   */
+  friend std::istream& operator>>(std::istream& is, RadiometricData& data);
+
+  /**
+   * @brief This function is able to create a new instance of the class
+   */
+  RadarSatRecord* Instanciate()
+  {
+    return new RadiometricData();
+  };
+
+  /**
+   * @brief This function is able to create a new instance of the class initialised with the data of the calling instance
+   */
+  RadarSatRecord* Clone()
+  {
+    return new RadiometricData(*this);
+  };
+
+  /**
+   * @brief Reads the class data from a stream
+   */
+  void Read(std::istream& is)
+  {
+    is>>*this;
+  };
+
+  /**
+   * @brief Writes the class to a stream
+   */
+  void Write(std::ostream& os)
+  {
+    os<<*this;
+  };
+
+  /**
+   * @brief Record sequence number
+   */
+  int   get_seq_num()
+  {
+    return _seq_num;
+  };
+    /**
+   * @brief Number of data fields
+   */
+  int   get_n_data()
+  {
+    return _n_data;
+  };
+    /**
+   * @brief Field size in bytes
+   */
+  int   get_field_size()
+  {
+    return _field_size;
+  };
+
+  /**
+   * @brief SAR channel indicator
+   */
+  std::string   get_chan_ind()
+  {
+    return _chan_ind;
+  };
+
+    /**
+   * @brief Table designator
+   */
+  std::string   get_table_desig()
+  {
+    return _table_desig;
+  };
+    /**
+   * @brief Number of lookup table samples
+   */
+  int   get_n_samp()
+  {
+    return _n_samp;
+  };
+    /**
+   * @brief Sample type designator
+   */
+  std::string   get_samp_type()
+  {
+    return _samp_type;
+  };
+    /**
+   * @brief Increment between table entries, range samples
+   */
+  int   get_samp_inc()
+  {
+    return _samp_inc;
+  };
+    /**
+   * @brief Output scaling gain table
+   */
+  double*   get_lookup_tab()
+  {
+    return _lookup_tab;
+  };
+
+    /**
+   * @brief Thermal noise reference level
+   */
+  double   get_noise_scale()
+  {
+    return _noise_scale;
+  };
+
+    /**
+   * @brief Scaling offset
+   */
+  double   get_offset()
+  {
+    return _offset;
+  };
+    /**
+   * @brief Calibration constant
+   */
+  double   get_calib_const()
+  {
+    return _calib_const;
+  };
+
+
+protected:
+  /**
+   * @brief Record sequence number
+   */
+  int   _seq_num;
+    /**
+   * @brief Number of data fields
+   */
+  int   _n_data;
+    /**
+   * @brief Field size in bytes
+   */
+  int   _field_size;
+
+  /**
+   * @brief SAR channel indicator
+   */
+  std::string   _chan_ind;
+
+    /**
+   * @brief Table designator
+   */
+  std::string   _table_desig;
+    /**
+   * @brief Number of lookup table samples
+   */
+  int   _n_samp;
+    /**
+   * @brief Sample type designator
+   */
+  std::string   _samp_type;
+    /**
+   * @brief Increment between table entries, range samples
+   */
+  int   _samp_inc;
+    /**
+   * @brief Output scaling gain table
+   */
+  double   _lookup_tab[512];
+
+    /**
+   * @brief Thermal noise reference level
+   */
+  double   _noise_scale;
+
+    /**
+   * @brief Scaling offset
+   */
+  double   _offset;
+    /**
+   * @brief Calibration constant
+   */
+  double   _calib_const;
+
+private:
+};
+}
+#endif
+
diff --git a/ossim_plugins/ossim/RadarSat/CommonRecord/RadiometryUncertaintyRecord.cpp b/ossim_plugins/ossim/RadarSat/CommonRecord/RadiometryUncertaintyRecord.cpp
new file mode 100755
index 0000000..5d2648e
--- /dev/null
+++ b/ossim_plugins/ossim/RadarSat/CommonRecord/RadiometryUncertaintyRecord.cpp
@@ -0,0 +1,57 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include "RadiometryUncertaintyRecord.h"
+
+namespace ossimplugins
+{
+RadiometryUncertaintyRecord::RadiometryUncertaintyRecord()
+{
+}
+
+RadiometryUncertaintyRecord::~RadiometryUncertaintyRecord()
+{
+}
+
+std::ostream& operator<<(std::ostream& os, const RadiometryUncertaintyRecord& data)
+{
+	os<<"db:"<<data._db<<std::endl;
+    os<<"deg:"<<data._deg<<std::endl;
+	return os;
+}
+
+std::istream& operator>>(std::istream& is, RadiometryUncertaintyRecord& data)
+{
+	char buf16[17];
+	buf16[16] = '\0';
+
+	is.read(buf16,16);
+	data._db = atof(buf16);
+
+	is.read(buf16,16);
+	data._deg = atof(buf16);
+	return is;
+}
+
+RadiometryUncertaintyRecord::RadiometryUncertaintyRecord(const RadiometryUncertaintyRecord& rhs):
+	_db(rhs._db),
+	_deg(rhs._deg)
+{
+}
+
+RadiometryUncertaintyRecord& RadiometryUncertaintyRecord::operator=(const RadiometryUncertaintyRecord& rhs)
+{
+	_db = rhs._db;
+	_deg = rhs._deg;
+	return *this;
+}
+}
+
diff --git a/ossim_plugins/ossim/RadarSat/CommonRecord/RadiometryUncertaintyRecord.h b/ossim_plugins/ossim/RadarSat/CommonRecord/RadiometryUncertaintyRecord.h
new file mode 100755
index 0000000..0ac151e
--- /dev/null
+++ b/ossim_plugins/ossim/RadarSat/CommonRecord/RadiometryUncertaintyRecord.h
@@ -0,0 +1,86 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef RadiometryUncertaintyRecord_h
+#define RadiometryUncertaintyRecord_h
+
+#include<iostream>
+#include <RadarSat/RadarSatRecord.h>
+
+namespace ossimplugins
+{
+/**
+ * @ingroup DataQualitySummaryRecord
+ * @brief This class is able to read a radiometry uncertainty record
+ */
+class RadiometryUncertaintyRecord
+{
+public:
+  /**
+   * @brief Constructor
+   */
+  RadiometryUncertaintyRecord();
+
+  /**
+   * @brief Destructor
+   */
+  ~RadiometryUncertaintyRecord();
+
+  /**
+   * @brief Copy constructor
+   */
+  RadiometryUncertaintyRecord(const RadiometryUncertaintyRecord& rhs);
+
+  /**
+   * @brief Copy operator
+   */
+  RadiometryUncertaintyRecord& operator=(const RadiometryUncertaintyRecord& rhs);
+  /**
+   * @brief This function writes the RadiometryUncertaintyRecord in a stream
+   */
+  friend std::ostream& operator<<(std::ostream& os, const RadiometryUncertaintyRecord& data);
+
+  /**
+   * @brief This function reads a RadiometryUncertaintyRecord from a stream
+   */
+  friend std::istream& operator>>(std::istream& is, RadiometryUncertaintyRecord& data);
+
+  /**
+   * @brief Units of db
+   */
+  double   get_db()
+  {
+    return _db;
+  };
+    /**
+   * @brief Units of deg
+   */
+  double   get_deg()
+  {
+    return _deg;
+  };
+protected:
+
+  /**
+   * @brief Units of db
+   */
+  double   _db;
+    /**
+   * @brief Units of deg
+   */
+  double   _deg;
+private:
+
+
+};
+}
+#endif
+
diff --git a/ossim_plugins/ossim/RadarSat/CommonRecord/SRGRCoefficientSetRecord.cpp b/ossim_plugins/ossim/RadarSat/CommonRecord/SRGRCoefficientSetRecord.cpp
new file mode 100755
index 0000000..c90b1b8
--- /dev/null
+++ b/ossim_plugins/ossim/RadarSat/CommonRecord/SRGRCoefficientSetRecord.cpp
@@ -0,0 +1,72 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include "SRGRCoefficientSetRecord.h"
+
+namespace ossimplugins
+{
+SRGRCoefficientSetRecord::SRGRCoefficientSetRecord()
+{
+}
+
+SRGRCoefficientSetRecord::~SRGRCoefficientSetRecord()
+{
+}
+
+std::ostream& operator<<(std::ostream& os, const SRGRCoefficientSetRecord& data)
+{
+	os<<"srgr_update:"<<data._srgr_update.c_str()<<std::endl;
+	for (int i=0;i<6;i++)
+	{
+		os<<"srgr_coef["<<i<<"]:"<<data._srgr_coef[i]<<std::endl;
+	}
+
+	return os;
+}
+
+std::istream& operator>>(std::istream& is, SRGRCoefficientSetRecord& data)
+{
+	char buf[22];
+	buf[21] = '\0';
+
+	is.read(buf,21);
+	buf[21] = '\0';
+	data._srgr_update = buf;
+
+	for (int i=0;i<6;i++)
+	{
+		is.read(buf,16);
+		buf[16] = '\0';
+		data._srgr_coef[i] = atof(buf);
+	}
+	return is;
+}
+
+SRGRCoefficientSetRecord::SRGRCoefficientSetRecord(const SRGRCoefficientSetRecord& rhs):
+	_srgr_update(rhs._srgr_update)
+{
+	for (int i=0;i<6;i++)
+	{
+		_srgr_coef[i] = rhs._srgr_coef[i];
+	}
+}
+
+SRGRCoefficientSetRecord& SRGRCoefficientSetRecord::operator=(const SRGRCoefficientSetRecord& rhs)
+{
+	_srgr_update = rhs._srgr_update;
+	for (int i=0;i<6;i++)
+	{
+		_srgr_coef[i] = rhs._srgr_coef[i];
+	}
+	return *this;
+}
+}
+
diff --git a/ossim_plugins/ossim/RadarSat/CommonRecord/SRGRCoefficientSetRecord.h b/ossim_plugins/ossim/RadarSat/CommonRecord/SRGRCoefficientSetRecord.h
new file mode 100755
index 0000000..0fcb848
--- /dev/null
+++ b/ossim_plugins/ossim/RadarSat/CommonRecord/SRGRCoefficientSetRecord.h
@@ -0,0 +1,88 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef SRGRCoefficientSetRecord_h
+#define SRGRCoefficientSetRecord_h
+
+#include <iostream>
+#include <RadarSat/RadarSatRecord.h>
+
+namespace ossimplugins
+{
+/**
+ * @ingroup ProcessingParametersRecord
+ * @brief This class is able to read a SRGR coefficients set record
+ */
+class SRGRCoefficientSetRecord
+{
+public:
+  /**
+   * @brief Constructor
+   */
+  SRGRCoefficientSetRecord();
+
+  /**
+   * @brief Destructor
+   */
+  ~SRGRCoefficientSetRecord();
+
+  /**
+   * @brief Copy constructor
+   */
+  SRGRCoefficientSetRecord(const SRGRCoefficientSetRecord& rhs);
+
+  /**
+   * @brief Copy operator
+   */
+  SRGRCoefficientSetRecord& operator=(const SRGRCoefficientSetRecord& rhs);
+
+  /**
+   * @brief This function writes the SRGRCoefficientSetRecord in a stream
+   */
+  friend std::ostream& operator<<(std::ostream& os, const SRGRCoefficientSetRecord& data);
+
+  /**
+   * @brief This function reads a SRGRCoefficientSetRecord from a stream
+   */
+  friend std::istream& operator>>(std::istream& is, SRGRCoefficientSetRecord& data);
+
+  /**
+   * @brief SRGR update date/time
+   */
+  std::string   get_srgr_update()
+  {
+    return _srgr_update;
+  }
+
+    /**
+   * @brief SRGR coefficients
+   */
+  double*   get_srgr_coef()
+  {
+    return _srgr_coef;
+  }
+
+protected:
+  /**
+   * @brief SRGR update date/time
+   */
+  std::string   _srgr_update;
+
+    /**
+   * @brief SRGR coefficients
+   */
+  double   _srgr_coef[6];
+private:
+
+};
+}
+#endif
+
diff --git a/ossim_plugins/ossim/RadarSat/CommonRecord/TemperatureSettingsRecord.cpp b/ossim_plugins/ossim/RadarSat/CommonRecord/TemperatureSettingsRecord.cpp
new file mode 100755
index 0000000..c10ec19
--- /dev/null
+++ b/ossim_plugins/ossim/RadarSat/CommonRecord/TemperatureSettingsRecord.cpp
@@ -0,0 +1,65 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include "TemperatureSettingsRecord.h"
+
+namespace ossimplugins
+{
+TemperatureSettingsRecord::TemperatureSettingsRecord()
+{
+}
+
+TemperatureSettingsRecord::~TemperatureSettingsRecord()
+{
+}
+
+std::ostream& operator<<(std::ostream& os, const TemperatureSettingsRecord& data)
+{
+	for (int i=0;i<4;i++)
+	{
+		os<<"temp_set["<<i<<"]:"<<data._temp_set[i]<<std::endl;
+	}
+
+	return os;
+}
+
+std::istream& operator>>(std::istream& is, TemperatureSettingsRecord& data)
+{
+	char buf[5];
+	buf[4] = '\0';
+
+	for (int i=0;i<4;i++)
+	{
+		is.read(buf,4);
+		buf[4] = '\0';
+		data._temp_set[i] = atoi(buf);
+	}
+	return is;
+}
+
+TemperatureSettingsRecord::TemperatureSettingsRecord(const TemperatureSettingsRecord& rhs)
+{
+	for (int i=0;i<4;i++)
+	{
+		_temp_set[i] = rhs._temp_set[i];
+	}
+}
+
+TemperatureSettingsRecord& TemperatureSettingsRecord::operator=(const TemperatureSettingsRecord& rhs)
+{
+	for (int i=0;i<4;i++)
+	{
+		_temp_set[i] = rhs._temp_set[i];
+	}
+	return *this;
+}
+}
+
diff --git a/ossim_plugins/ossim/RadarSat/CommonRecord/TemperatureSettingsRecord.h b/ossim_plugins/ossim/RadarSat/CommonRecord/TemperatureSettingsRecord.h
new file mode 100755
index 0000000..8dfddd0
--- /dev/null
+++ b/ossim_plugins/ossim/RadarSat/CommonRecord/TemperatureSettingsRecord.h
@@ -0,0 +1,76 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef TemperatureSettingsRecord_h
+#define TemperatureSettingsRecord_h
+
+#include <iostream>
+#include <RadarSat/RadarSatRecord.h>
+
+namespace ossimplugins
+{
+/**
+ * @ingroup ProcessingParametersRecord
+ * @brief This class is able to read a Temperature Settings record
+ */
+class TemperatureSettingsRecord
+{
+public:
+  /**
+   * @brief Constructor
+   */
+  TemperatureSettingsRecord();
+
+  /**
+   * @brief Destructor
+   */
+  ~TemperatureSettingsRecord();
+
+  /**
+   * @brief Copy constructor
+   */
+  TemperatureSettingsRecord(const TemperatureSettingsRecord& rhs);
+
+  /**
+   * @brief Copy operator
+   */
+  TemperatureSettingsRecord& operator=(const TemperatureSettingsRecord& rhs);
+
+  /**
+   * @brief This function writes the TemperatureSettingsRecord in a stream
+   */
+  friend std::ostream& operator<<(std::ostream& os, const TemperatureSettingsRecord& data);
+
+  /**
+   * @brief This function reads a TemperatureSettingsRecord from a stream
+   */
+  friend std::istream& operator>>(std::istream& is, TemperatureSettingsRecord& data);
+
+  /**
+   * @brief Temperature settings
+   */
+  int*   get_temp_set()
+  {
+    return _temp_set;
+  };
+
+protected:
+
+  /**
+   * @brief Temperature settings
+   */
+  int _temp_set[4];
+private:
+
+};
+}
+#endif
+
diff --git a/ossim_plugins/ossim/RadarSat/Data/Data.cpp b/ossim_plugins/ossim/RadarSat/Data/Data.cpp
new file mode 100644
index 0000000..b2d2cf4
--- /dev/null
+++ b/ossim_plugins/ossim/RadarSat/Data/Data.cpp
@@ -0,0 +1,236 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include <RadarSat/Data/Data.h>
+#include <RadarSat/Data/DataFactory.h>
+#include <RadarSat/RadarSatRecordHeader.h>
+#include <RadarSat/Data/ImageOptionsFileDescriptor.h>
+
+#include <ossim/base/ossimTrace.h>
+
+namespace ossimplugins
+{
+// Static trace for debugging
+static ossimTrace traceDebug("Data:debug");
+
+const int Data::ImageOptionsFileDescriptorID = 1;
+const int Data::FirstProcessedDataRecordID = 2;
+const int Data::LastProcessedDataRecordID = 3;
+
+Data::Data()
+{
+}
+
+Data::~Data()
+{
+	ClearRecords();
+}
+
+std::ostream& operator<<(std::ostream& os, const Data& data)
+{
+	std::map<int, RadarSatRecord*>::const_iterator it = data._records.begin();
+	while(it != data._records.end())
+	{
+		(*it).second->Write(os);
+		++it;
+	}
+	return os;
+
+}
+
+std::istream& operator>>(std::istream& is, Data& data)
+{
+	DataFactory factory;
+
+	data.ClearRecords();
+
+	if (sizeof(int)!=4) ossimNotify(ossimNotifyLevel_WARN)  << "RadarSat Data WARNING : (int) not coded over 32 bits, metadata might not be byte swapped correctly"<< std::endl ;
+	if (sizeof(float)!=4) ossimNotify(ossimNotifyLevel_WARN)  << "RadarSat Data WARNING : (float) not coded over 32 bits, metadata might not be byte swapped correctly"<< std::endl ;
+	if (sizeof(double)!=8) ossimNotify(ossimNotifyLevel_WARN)  << "RadarSat Data WARNING : (double) not coded over 64 bits, metadata might not be byte swapped correctly"<< std::endl ;
+
+	RadarSatRecordHeader header;
+	bool eof = false;
+
+	int nbLin = 0 ; // number of image lines
+	int lineLength = 0 ; // size of any ProcessedDataRecord
+
+  is.seekg(0, std::ios::end) ;
+  int lengthOfFile = is.tellg(); // total length of file
+  is.seekg(0, std::ios::beg);
+	while(!eof)
+	  {
+	  is>>header;
+		if(is.eof())
+		  {
+		  eof = true;
+		  }
+		else
+		  {
+			if (header.get_rec_seq() == 1)
+			  { // ImageOptionsFileDescriptor
+			  RadarSatRecord* record = factory.Instanciate(header.get_rec_seq());
+			  if (record != NULL)
+				  {
+			    record->Read(is);
+					data._records[Data::ImageOptionsFileDescriptorID] = record;
+
+					nbLin  = ((ImageOptionsFileDescriptor *) record)->get_nlin() ;
+					if (nbLin == -1)
+					  {
+					  ossimNotify(ossimNotifyLevel_DEBUG) << "WARNING: nbLin is not read in the file !" << std::endl;
+					  }
+				  }
+				else
+				  {
+					char* buff = new char[header.get_length()-12];
+					is.read(buff, header.get_length()-12);
+					delete[] buff;
+				  }
+			  }
+			else if ((header.get_rec_seq() == 2))
+			  { // First line ProcessedDataRecord
+				lineLength = header.get_length() ;
+				RadarSatRecord* record = factory.Instanciate(2);
+				if (record != NULL)
+			  	{
+				  record->Read(is);
+					data._records[Data::FirstProcessedDataRecordID] = record;
+
+					char* buff = new char[header.get_length()-192];
+					is.read(buff, header.get_length()-192);	// Reads the rest of the line
+					delete[] buff;
+				  }
+				else
+				  {
+				  char* buff = new char[header.get_length()-12];
+					is.read(buff, header.get_length()-12);
+					delete[] buff;
+				  }
+			  }
+			else if ((header.get_rec_seq() == (1+nbLin)))
+			  { // Last line ProcessedDataRecord
+			  RadarSatRecord* record = factory.Instanciate(2);
+				if (record != NULL)
+				  {
+				  record->Read(is);
+					data._records[Data::LastProcessedDataRecordID] = record;
+
+					char* buff = new char[header.get_length()-192];
+					is.read(buff, header.get_length()-192);	// Reads the rest of the line
+					delete[] buff;
+				  }
+				else
+				  {
+				  char* buff = new char[header.get_length()-12];
+					is.read(buff, header.get_length()-12);
+					delete[] buff;
+				  }
+			  }
+			else
+			  {
+				// all lines between the first and last ones are skipped
+				if (lineLength != 0)
+				  {
+				  if (nbLin == -1)
+				    {
+				    // Compute the number of line per dataset from the size of file and current position
+				    int nbLines = ( ( lengthOfFile - is.tellg() ) / lineLength ) + 2;
+				    ossimNotify(ossimNotifyLevel_DEBUG) << "To move in the dat file we compute the nb of lines = " << nbLines << std::endl;
+
+				    // We move in the file to the last line
+				    is.seekg((nbLines - 2) * lineLength - 12, std::ios::cur);
+
+				    // We save the nbLines computed in data
+				    nbLin = nbLines;
+				    ImageOptionsFileDescriptor* record = data.get_ImageOptionsFileDescriptor();
+				    record->set_nlin(nbLin);
+				    data._records[Data::ImageOptionsFileDescriptorID] = record;
+				    }
+				  else
+            {
+            // We move in the file
+            is.seekg((nbLin - 2) * lineLength - 12, std::ios::cur);
+            }
+				  }
+				else
+				  {
+				  // We move to the end of the file
+					is.seekg(0, std::ios::end) ;
+				  }
+			  }
+		  }
+  	}
+	return is;
+}
+
+
+Data::Data(const Data& rhs)
+{
+	std::map<int, RadarSatRecord*>::const_iterator it = rhs._records.begin();
+	while(it != rhs._records.end())
+	{
+		_records[(*it).first] = (*it).second->Clone();
+		++it;
+	}
+}
+
+Data& Data::operator=(const Data& rhs)
+{
+	std::map<int, RadarSatRecord*>::const_iterator it = _records.begin();
+	while(it != _records.end())
+	{
+		delete (*it).second;
+		++it;
+	}
+	_records.clear();
+
+	it = rhs._records.begin();
+	while(it != rhs._records.end())
+	{
+		_records[(*it).first] = (*it).second->Clone();
+		++it;
+	}
+
+	return *this;
+}
+
+void Data::ClearRecords()
+{
+	std::map<int, RadarSatRecord*>::const_iterator it = _records.begin();
+	while(it != _records.end())
+	{
+		delete (*it).second;
+		++it;
+	}
+	_records.clear();
+}
+
+void Data::InsertRecord(int id, RadarSatRecord* record)
+{
+	_records[id] = record;
+}
+
+ImageOptionsFileDescriptor* Data::get_ImageOptionsFileDescriptor()
+{
+	return (ImageOptionsFileDescriptor*)_records[ImageOptionsFileDescriptorID];
+}
+
+ProcessedDataRecord* Data::get_FirstProcessedDataRecord()
+{
+	return (ProcessedDataRecord*)_records[FirstProcessedDataRecordID];
+}
+
+ProcessedDataRecord* Data::get_LastProcessedDataRecord()
+{
+	return (ProcessedDataRecord*)_records[LastProcessedDataRecordID];
+}
+}
+
diff --git a/ossim_plugins/ossim/RadarSat/Data/Data.h b/ossim_plugins/ossim/RadarSat/Data/Data.h
new file mode 100644
index 0000000..d097fb4
--- /dev/null
+++ b/ossim_plugins/ossim/RadarSat/Data/Data.h
@@ -0,0 +1,87 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef Data_h
+#define Data_h
+
+#include <iostream>
+#include <map>
+#include <RadarSat/RadarSatRecord.h>
+
+namespace ossimplugins
+{
+class ImageOptionsFileDescriptor;
+class ProcessedDataRecord;
+
+/**
+ * @ingroup DataFile
+ * @brief This class is able to read the data file of the RadarSat file structure
+ * @author Magellium, Pacome Dentraygues
+ * @version 1.0
+ * @date 23-11-07
+ */
+class Data
+{
+public:
+  /**
+   * @brief Constructor
+   */
+  Data();
+
+  /**
+   * @brief Destructor
+   */
+  ~Data();
+
+  /**
+   * @brief This function writes the Data in a stream
+   */
+  friend std::ostream& operator<<(std::ostream& os, const Data& data);
+
+  /**
+   * @brief This function reads a Data from a stream
+   */
+  friend std::istream& operator>>(std::istream& is, Data& data);
+
+  /**
+   * @brief Copy constructor
+   */
+  Data(const Data& rhs);
+
+  /**
+   * @brief Copy operator
+   */
+  Data& operator=(const Data& rhs);
+
+  /**
+   * @brief Removes all the previous records from the Data
+   */
+  void ClearRecords();
+
+  /**
+   * @brief Inserts an existing record in the Data
+   */
+  void InsertRecord(int id, RadarSatRecord* record);
+
+  ImageOptionsFileDescriptor* get_ImageOptionsFileDescriptor();
+  ProcessedDataRecord* get_FirstProcessedDataRecord();
+  ProcessedDataRecord* get_LastProcessedDataRecord();
+protected:
+  std::map<int, RadarSatRecord*> _records;
+  static const int ImageOptionsFileDescriptorID;
+  static const int FirstProcessedDataRecordID;
+  static const int LastProcessedDataRecordID;
+private:
+
+};
+}
+#endif
+
diff --git a/ossim_plugins/ossim/RadarSat/Data/DataFactory.cpp b/ossim_plugins/ossim/RadarSat/Data/DataFactory.cpp
new file mode 100644
index 0000000..6971ec6
--- /dev/null
+++ b/ossim_plugins/ossim/RadarSat/Data/DataFactory.cpp
@@ -0,0 +1,42 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include <RadarSat/Data/DataFactory.h>
+
+#include <RadarSat/Data/ImageOptionsFileDescriptor.h>
+#include <RadarSat/Data/ProcessedDataRecord.h>
+
+namespace ossimplugins
+{
+
+DataFactory::DataFactory()
+{
+	RegisterRecord(1, new ImageOptionsFileDescriptor());
+	RegisterRecord(2, new ProcessedDataRecord());
+}
+
+DataFactory::~DataFactory()
+{
+  std::map<int, RadarSatRecord*>::iterator i = _availableRecords.begin();
+
+  while (i != _availableRecords.end())
+  {
+     if ( (*i).second )
+     {
+        delete (*i).second;
+        (*i).second = 0;
+     }
+     ++i;
+  }
+  _availableRecords.clear();
+}
+}
+
diff --git a/ossim_plugins/ossim/RadarSat/Data/DataFactory.h b/ossim_plugins/ossim/RadarSat/Data/DataFactory.h
new file mode 100644
index 0000000..01fb854
--- /dev/null
+++ b/ossim_plugins/ossim/RadarSat/Data/DataFactory.h
@@ -0,0 +1,42 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef DataFactory_h
+#define DataFactory_h
+
+#include <RadarSat/RadarSatRecordFactory.h>
+#include <map>
+
+namespace ossimplugins
+{
+
+/**
+ * @ingroup DataFile
+ * @brief This class is a factory able to construct Record base classes
+ */
+class DataFactory : public RadarSatRecordFactory
+{
+public:
+  /**
+   * @brief Contstructor
+   */
+  DataFactory();
+  /**
+   * @brief Destructor
+   */
+  ~DataFactory();
+
+protected:
+private:
+};
+}
+#endif
+
diff --git a/ossim_plugins/ossim/RadarSat/Data/ImageOptionsFileDescriptor.cpp b/ossim_plugins/ossim/RadarSat/Data/ImageOptionsFileDescriptor.cpp
new file mode 100644
index 0000000..c4a5c89
--- /dev/null
+++ b/ossim_plugins/ossim/RadarSat/Data/ImageOptionsFileDescriptor.cpp
@@ -0,0 +1,386 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include <RadarSat/Data/ImageOptionsFileDescriptor.h>
+#include <ossim/base/ossimNotify.h>
+#include <ossim/base/ossimTrace.h>
+
+namespace ossimplugins
+{
+   static ossimTrace traceDebug("ImageOptionsFileDescriptor:debug");
+
+   ImageOptionsFileDescriptor::ImageOptionsFileDescriptor() : RadarSatRecord("imop_desc_rec")
+   {
+   }
+
+   ImageOptionsFileDescriptor::~ImageOptionsFileDescriptor()
+   {
+   }
+
+   std::ostream& operator<<(std::ostream& os, const ImageOptionsFileDescriptor& data)
+   {
+      os<<"ascii_flag:"<<data._ascii_flag.c_str()<<std::endl;
+
+      os<<"format_doc:"<<data._format_doc.c_str()<<std::endl;
+
+      os<<"format_rev:"<<data._format_rev.c_str()<<std::endl;
+
+      os<<"design_rev:"<<data._design_rev.c_str()<<std::endl;
+
+      os<<"software_id:"<<data._software_id.c_str()<<std::endl;
+
+      os<<"file_num:"<<data._file_num<<std::endl;
+
+      os<<"file_name:"<<data._file_name.c_str()<<std::endl;
+
+      os<<"rec_seq:"<<data._rec_seq.c_str()<<std::endl;
+
+      os<<"seq_loc:"<<data._seq_loc<<std::endl;
+
+      os<<"seq_len:"<<data._seq_len<<std::endl;
+
+      os<<"rec_code:"<<data._rec_code.c_str()<<std::endl;
+
+      os<<"code_loc:"<<data._code_loc<<std::endl;
+
+      os<<"code_len:"<<data._code_len<<std::endl;
+
+      os<<"rec_len:"<<data._rec_len.c_str()<<std::endl;
+
+      os<<"rlen_loc:"<<data._rlen_loc<<std::endl;
+
+      os<<"rlen_len:"<<data._rlen_len<<std::endl;
+
+      os<<"n_dataset:"<<data._n_dataset<<std::endl;
+
+      os<<"l_dataset:"<<data._l_dataset<<std::endl;
+
+      os<<"nbit:"<<data._nbit<<std::endl;
+
+      os<<"nsamp:"<<data._nsamp<<std::endl;
+
+      os<<"nbyte:"<<data._nbyte<<std::endl;
+
+      os<<"justify:"<<data._justify.c_str()<<std::endl;
+
+      os<<"nchn:"<<data._nchn<<std::endl;
+
+      os<<"nlin:"<<data._nlin<<std::endl;
+
+      os<<"nleft:"<<data._nleft<<std::endl;
+
+      os<<"ngrp:"<<data._ngrp<<std::endl;
+
+      os<<"nright:"<<data._nright<<std::endl;
+
+      os<<"ntop:"<<data._ntop<<std::endl;
+
+      os<<"nbott:"<<data._nbott<<std::endl;
+
+      os<<"intleav:"<<data._intleav.c_str()<<std::endl;
+
+      os<<"nrec_lin:"<<data._nrec_lin<<std::endl;
+
+      os<<"nrec_chn:"<<data._nrec_chn<<std::endl;
+
+      os<<"n_prefix:"<<data._n_prefix<<std::endl;
+
+      os<<"n_sar:"<<data._n_sar<<std::endl;
+
+      os<<"n_suffix:"<<data._n_suffix<<std::endl;
+
+      os<<"lin_loc:"<<data._lin_loc.c_str()<<std::endl;
+
+      os<<"chn_loc:"<<data._chn_loc.c_str()<<std::endl;
+
+      os<<"tim_loc:"<<data._tim_loc.c_str()<<std::endl;
+
+      os<<"left_loc:"<<data._left_loc.c_str()<<std::endl;
+
+      os<<"right_loc:"<<data._right_loc.c_str()<<std::endl;
+
+      os<<"pad_ind:"<<data._pad_ind.c_str()<<std::endl;
+
+      os<<"qual_loc:"<<data._qual_loc.c_str()<<std::endl;
+
+      os<<"cali_loc:"<<data._cali_loc.c_str()<<std::endl;
+
+      os<<"gain_loc:"<<data._gain_loc.c_str()<<std::endl;
+
+      os<<"bias_loc:"<<data._bias_loc.c_str()<<std::endl;
+
+      os<<"type_id:"<<data._type_id.c_str()<<std::endl;
+
+      os<<"type_code:"<<data._type_code.c_str()<<std::endl;
+
+      os<<"left_fill:"<<data._left_fill<<std::endl;
+
+      os<<"right_fill:"<<data._right_fill<<std::endl;
+
+      os<<"pix_rng:"<<data._pix_rng<<std::endl;
+
+      return os;
+   }
+
+   std::istream& operator>>(std::istream& is, ImageOptionsFileDescriptor& data)
+   {
+      char buf[15805];
+      buf[15804] = '\0';
+
+      is.read(buf,2);
+      buf[2] = '\0';
+      data._ascii_flag = buf;
+
+      is.read(buf,2);
+
+      is.read(buf,12);
+      buf[12] = '\0';
+      data._format_doc = buf;
+
+      is.read(buf,2);
+      buf[2] = '\0';
+      data._format_rev = buf;
+
+      is.read(buf,2);
+      buf[2] = '\0';
+      data._design_rev = buf;
+
+      is.read(buf,12);
+      buf[12] = '\0';
+      data._software_id = buf;
+
+      is.read(buf,4);
+      buf[4] = '\0';
+      data._file_num = atoi(buf);
+
+      is.read(buf,16);
+      buf[16] = '\0';
+      data._file_name = buf;
+
+      is.read(buf,4);
+      buf[4] = '\0';
+      data._rec_seq = buf;
+
+      is.read(buf,8);
+      buf[8] = '\0';
+      data._seq_loc = atoi(buf);
+
+      is.read(buf,4);
+      buf[4] = '\0';
+      data._seq_len = atoi(buf);
+
+      is.read(buf,4);
+      buf[4] = '\0';
+      data._rec_code = buf;
+
+      is.read(buf,8);
+      buf[8] = '\0';
+      data._code_loc = atoi(buf);
+
+      is.read(buf,4);
+      buf[4] = '\0';
+      data._code_len = atoi(buf);
+
+      is.read(buf,4);
+      buf[4] = '\0';
+      data._rec_len = buf;
+
+      is.read(buf,8);
+      buf[8] = '\0';
+      data._rlen_loc = atoi(buf);
+
+      is.read(buf,4);
+      buf[4] = '\0';
+      data._rlen_len = atoi(buf);
+
+      for (int i=0;i<4;i++)
+      {
+         is.read(buf,1);
+      }
+
+      is.read(buf,64);
+
+      is.read(buf,6);
+      buf[6] = '\0';
+      data._n_dataset = atoi(buf);
+
+      is.read(buf,6);
+      buf[6] = '\0';
+      data._l_dataset = atoi(buf);
+
+      is.read(buf,24);
+
+      is.read(buf,4);
+      buf[4] = '\0';
+      data._nbit = atoi(buf);
+
+      is.read(buf,4);
+      buf[4] = '\0';
+      data._nsamp = atoi(buf);
+
+      is.read(buf,4);
+      buf[4] = '\0';
+      data._nbyte = atoi(buf);
+
+      is.read(buf,4);
+      buf[4] = '\0';
+      data._justify = buf;
+
+      is.read(buf,4);
+      buf[4] = '\0';
+      data._nchn = atoi(buf);
+
+      is.read(buf,8);
+      buf[8] = '\0';
+
+      // We should use strtol() to avoid wrong conversion with atoi()
+      char* p;
+      int result = strtol(buf, &p, 10);
+      if ( *p != 0 || p == buf)
+      {
+         if(traceDebug())
+         {
+            ossimNotify(ossimNotifyLevel_DEBUG) << "WARNING: strtol() try to convert an empty tab of characters. It may be possible in case of SCN and SCW format" << buf << "!" << std::endl;
+            ossimNotify(ossimNotifyLevel_DEBUG) << "=> _nlin = -1" << std::endl;
+         }
+         data._nlin = -1;
+      }
+      else
+      {
+         data._nlin = result;
+      };
+
+      is.read(buf,4);
+      buf[4] = '\0';
+      data._nleft = atoi(buf);
+
+      is.read(buf,8);
+      buf[8] = '\0';
+      data._ngrp = atoi(buf);
+
+      is.read(buf,4);
+      buf[4] = '\0';
+      data._nright = atoi(buf);
+
+      is.read(buf,4);
+      buf[4] = '\0';
+      data._ntop = atoi(buf);
+
+      is.read(buf,4);
+      buf[4] = '\0';
+      data._nbott = atoi(buf);
+
+      is.read(buf,4);
+      buf[4] = '\0';
+      data._intleav = buf;
+
+      is.read(buf,2);
+      buf[2] = '\0';
+      data._nrec_lin = atoi(buf);
+
+      is.read(buf,2);
+      buf[2] = '\0';
+      data._nrec_chn = atoi(buf);
+
+      is.read(buf,4);
+      buf[4] = '\0';
+      data._n_prefix = atoi(buf);
+
+      is.read(buf,8);
+      buf[8] = '\0';
+      data._n_sar = atoi(buf);
+
+      is.read(buf,4);
+      buf[4] = '\0';
+      data._n_suffix = atoi(buf);
+
+      is.read(buf,4);
+
+      is.read(buf,8);
+      buf[8] = '\0';
+      data._lin_loc = buf;
+
+      is.read(buf,8);
+      buf[8] = '\0';
+      data._chn_loc = buf;
+
+      is.read(buf,8);
+      buf[8] = '\0';
+      data._tim_loc = buf;
+
+      is.read(buf,8);
+      buf[8] = '\0';
+      data._left_loc = buf;
+
+      is.read(buf,8);
+      buf[8] = '\0';
+      data._right_loc = buf;
+
+      is.read(buf,4);
+      buf[4] = '\0';
+      data._pad_ind = buf;
+
+      is.read(buf,28);
+
+      is.read(buf,8);
+      buf[8] = '\0';
+      data._qual_loc = buf;
+
+      is.read(buf,8);
+      buf[8] = '\0';
+      data._cali_loc = buf;
+
+      is.read(buf,8);
+      buf[8] = '\0';
+      data._gain_loc = buf;
+
+      is.read(buf,8);
+      buf[8] = '\0';
+      data._bias_loc = buf;
+
+      is.read(buf,28);
+      buf[28] = '\0';
+      data._type_id = buf;
+
+      is.read(buf,4);
+      buf[4] = '\0';
+      data._type_code = buf;
+
+      is.read(buf,4);
+      buf[4] = '\0';
+      data._left_fill = atoi(buf);
+
+      is.read(buf,4);
+      buf[4] = '\0';
+      data._right_fill = atoi(buf);
+
+      is.read(buf,8);
+      buf[8] = '\0';
+      data._pix_rng = atoi(buf);
+
+      is.read(buf,15804);
+
+      return is;
+   }
+
+   ImageOptionsFileDescriptor::ImageOptionsFileDescriptor(const ImageOptionsFileDescriptor& rhs):
+      RadarSatRecord(rhs)
+   {
+
+
+   }
+
+   ImageOptionsFileDescriptor& ImageOptionsFileDescriptor::operator=(const ImageOptionsFileDescriptor& /* rhs */)
+   {
+      return *this;
+   }
+}
+
diff --git a/ossim_plugins/ossim/RadarSat/Data/ImageOptionsFileDescriptor.h b/ossim_plugins/ossim/RadarSat/Data/ImageOptionsFileDescriptor.h
new file mode 100644
index 0000000..74342df
--- /dev/null
+++ b/ossim_plugins/ossim/RadarSat/Data/ImageOptionsFileDescriptor.h
@@ -0,0 +1,668 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef ImageOptionsFileDescriptor_h
+#define ImageOptionsFileDescriptor_h
+
+#include <iostream>
+
+#include <RadarSat/RadarSatRecord.h>
+#include <RadarSat/RadarSatRecordHeader.h>
+
+namespace ossimplugins
+{
+/**
+ * @ingroup ImageOptionsFileDescriptionRecord
+ * @brief This class is able to read an Image options file descriptor record
+ * @author Magellium, Pacome Dentraygues
+ * @version 1.0
+ * @date 03-12-07
+ */
+class ImageOptionsFileDescriptor : public RadarSatRecord
+{
+public:
+  /**
+   * @brief Constructor
+   */
+  ImageOptionsFileDescriptor();
+
+  /**
+   * @brief Destructor
+   */
+  ~ImageOptionsFileDescriptor();
+
+  /**
+   * @brief Copy constructor
+   */
+  ImageOptionsFileDescriptor(const ImageOptionsFileDescriptor& rhs);
+
+  /**
+   * @brief Copy operator
+   */
+  ImageOptionsFileDescriptor& operator=(const ImageOptionsFileDescriptor& rhs);
+  /**
+   * @brief This function writes the ImageOptionsFileDescriptor in a stream
+   */
+  friend std::ostream& operator<<(std::ostream& os, const ImageOptionsFileDescriptor& data);
+
+  /**
+   * @brief This function reads a ImageOptionsFileDescriptor from a stream
+   */
+  friend std::istream& operator>>(std::istream& is, ImageOptionsFileDescriptor& data);
+
+  /**
+   * @brief This function is able to create a new instance of the class
+   */
+  RadarSatRecord* Instanciate()
+  {
+    return new ImageOptionsFileDescriptor();
+  };
+
+  /**
+   * @brief This function is able to create a new instance of the class initialised with the data of the calling instance
+   */
+  RadarSatRecord* Clone()
+  {
+    return new ImageOptionsFileDescriptor(*this);
+  };
+
+  /**
+   * @brief Reads the class data from a stream
+   */
+  void Read(std::istream& is)
+  {
+    is>>*this;
+  };
+
+  /**
+   * @brief Writes the class to a stream
+   */
+  void Write(std::ostream& os)
+  {
+    os<<*this;
+  };
+
+  /**
+   * @brief Set the number of lines per data set
+   */
+  void set_nlin(int inNbLines)
+  {
+    _nlin = inNbLines;
+  };
+  /**
+   * @brief ASCII flag
+   */
+  std::string   get_ascii_flag()
+  {
+    return _ascii_flag;
+  };
+
+    /**
+   * @brief Format control document
+   */
+  std::string   get_format_doc()
+  {
+    return _format_doc;
+  };
+    /**
+   * @brief Format document revision
+   */
+  std::string   get_format_rev()
+  {
+    return _format_rev;
+  };
+    /**
+   * @brief File design revision
+   */
+  std::string   get_design_rev()
+  {
+    return _design_rev;
+  };
+    /**
+   * @brief Software identifier
+   */
+  std::string   get_software_id()
+  {
+    return _software_id;
+  };
+    /**
+   * @brief File number
+   */
+  int   get_file_num()
+  {
+    return _file_num;
+  };
+    /**
+   * @brief File name
+   */
+  std::string   get_file_name()
+  {
+    return _file_name;
+  };
+    /**
+   * @brief Record sequence/location flag
+   */
+  std::string   get_rec_seq()
+  {
+    return _rec_seq;
+  };
+    /**
+   * @brief Sequence number location
+   */
+  int   get_seq_loc()
+  {
+    return _seq_loc;
+  };
+    /**
+   * @brief Sequence number length
+   */
+  int   get_seq_len()
+  {
+    return _seq_len;
+  };
+    /**
+   * @brief Record code/location flag
+   */
+  std::string   get_rec_code()
+  {
+    return _rec_code;
+  };
+    /**
+   * @brief Record code location
+   */
+  int   get_code_loc()
+  {
+    return _code_loc;
+  };
+    /**
+   * @brief Record code length
+   */
+  int   get_code_len()
+  {
+    return _code_len;
+  };
+    /**
+   * @brief Record length/location flag
+   */
+  std::string   get_rec_len()
+  {
+    return _rec_len;
+  };
+    /**
+   * @brief Record length location
+   */
+  int   get_rlen_loc()
+  {
+    return _rlen_loc;
+  };
+    /**
+   * @brief Record length length
+   */
+  int   get_rlen_len()
+  {
+    return _rlen_len;
+  };
+
+    /**
+   * @brief Number of SAR data records
+   */
+  int   get_n_dataset()
+  {
+    return _n_dataset;
+  };
+    /**
+   * @brief SAR data record length
+   */
+  int   get_l_dataset()
+  {
+    return _l_dataset;
+  };
+
+    /**
+   * @brief Number of bits per sample
+   */
+  int   get_nbit()
+  {
+    return _nbit;
+  };
+    /**
+   * @brief Samples per data group
+   */
+  int   get_nsamp()
+  {
+    return _nsamp;
+  };
+    /**
+   * @brief Bytes per data group
+   */
+  int   get_nbyte()
+  {
+    return _nbyte;
+  };
+    /**
+   * @brief Sample justification and order
+   */
+  std::string   get_justify()
+  {
+    return _justify;
+  };
+    /**
+   * @brief Number of SAR channels
+   */
+  int   get_nchn()
+  {
+    return _nchn;
+  };
+    /**
+   * @brief Lines per data set
+   */
+  int   get_nlin()
+  {
+    return _nlin;
+  };
+    /**
+   * @brief Left border pixels per line
+   */
+  int   get_nleft()
+  {
+    return _nleft;
+  };
+    /**
+   * @brief Groups per line per channel
+   */
+  int   get_ngrp()
+  {
+    return _ngrp;
+  };
+    /**
+   * @brief Right border pixels per line
+   */
+  int   get_nright()
+  {
+    return _nright;
+  };
+    /**
+   * @brief Top border lines
+   */
+  int   get_ntop()
+  {
+    return _ntop;
+  };
+    /**
+   * @brief Bottom border lines
+   */
+  int   get_nbott()
+  {
+    return _nbott;
+  };
+    /**
+   * @brief Interleave indicator
+   */
+  std::string   get_intleav()
+  {
+    return _intleav;
+  };
+    /**
+   * @brief Number of physical records per line
+   */
+  int   get_nrec_lin()
+  {
+    return _nrec_lin;
+  };
+    /**
+   * @brief Number of physical records per multi-channel line in this file
+   */
+  int   get_nrec_chn()
+  {
+    return _nrec_chn;
+  };
+    /**
+   * @brief Number of bytes of prefix data per record
+   */
+  int   get_n_prefix()
+  {
+    return _n_prefix;
+  };
+    /**
+   * @brief Number of bytes of SAR data (or pixel data) per record
+   */
+  int   get_n_sar()
+  {
+    return _n_sar;
+  };
+    /**
+   * @brief Number of bytes of suffix data per record
+   */
+  int   get_n_suffix()
+  {
+    return _n_suffix;
+  };
+
+    /**
+   * @brief Line number locator
+   */
+  std::string   get_lin_loc()
+  {
+    return _lin_loc;
+  };
+    /**
+   * @brief Channel number locator
+   */
+  std::string   get_chn_loc()
+  {
+    return _chn_loc;
+  };
+    /**
+   * @brief Time locator
+   */
+  std::string   get_tim_loc()
+  {
+    return _tim_loc;
+  };
+    /**
+   * @brief Left fill locator
+   */
+  std::string   get_left_loc()
+  {
+    return _left_loc;
+  };
+    /**
+   * @brief Right fill locator
+   */
+  std::string   get_right_loc()
+  {
+    return _right_loc;
+  };
+    /**
+   * @brief Pad pixel indicator
+   */
+  std::string   get_pad_ind()
+  {
+    return _pad_ind;
+  };
+
+    /**
+   * @brief Quality code locator
+   */
+  std::string   get_qual_loc()
+  {
+    return _qual_loc;
+  };
+    /**
+   * @brief Calibration info locator
+   */
+  std::string   get_cali_loc()
+  {
+    return _cali_loc;
+  };
+    /**
+   * @brief Gain value locator
+   */
+  std::string   get_gain_loc()
+  {
+    return _gain_loc;
+  };
+    /**
+   * @brief Bias value locator
+   */
+  std::string   get_bias_loc()
+  {
+    return _bias_loc;
+  };
+    /**
+   * @brief Data type identifier
+   */
+  std::string   get_type_id()
+  {
+    return _type_id;
+  };
+  /**
+   * @brief Data type code
+   */
+  std::string   get_type_code()
+  {
+    return _type_code;
+  };
+    /**
+   * @brief Number of left fill bits
+   */
+  int   get_left_fill()
+  {
+    return _left_fill;
+  };
+    /**
+   * @brief Number of right fill bits
+   */
+  int   get_right_fill()
+  {
+    return _right_fill;
+  };
+    /**
+   * @brief Maximum data range of pixel
+   */
+  int   get_pix_rng()
+  {
+    return _pix_rng;
+  };
+
+protected:
+  /**
+   * @brief ASCII flag
+   */
+  std::string   _ascii_flag;
+
+    /**
+   * @brief Format control document
+   */
+  std::string   _format_doc;
+    /**
+   * @brief Format document revision
+   */
+  std::string   _format_rev;
+    /**
+   * @brief File design revision
+   */
+  std::string   _design_rev;
+    /**
+   * @brief Software identifier
+   */
+  std::string   _software_id;
+    /**
+   * @brief File number
+   */
+  int   _file_num;
+    /**
+   * @brief File name
+   */
+  std::string   _file_name;
+    /**
+   * @brief Record sequence/location flag
+   */
+  std::string   _rec_seq;
+    /**
+   * @brief Sequence number location
+   */
+  int   _seq_loc;
+    /**
+   * @brief Sequence number length
+   */
+  int   _seq_len;
+    /**
+   * @brief Record code/location flag
+   */
+  std::string   _rec_code;
+    /**
+   * @brief Record code location
+   */
+  int   _code_loc;
+    /**
+   * @brief Record code length
+   */
+  int   _code_len;
+    /**
+   * @brief Record length/location flag
+   */
+  std::string   _rec_len;
+    /**
+   * @brief Record length location
+   */
+  int   _rlen_loc;
+    /**
+   * @brief Record length length
+   */
+  int   _rlen_len;
+
+
+    /**
+   * @brief Number of SAR data records
+   */
+  int   _n_dataset;
+    /**
+   * @brief SAR data record length
+   */
+  int   _l_dataset;
+
+    /**
+   * @brief Number of bits per sample
+   */
+  int   _nbit;
+    /**
+   * @brief Samples per data group
+   */
+  int   _nsamp;
+    /**
+   * @brief Bytes per data group
+   */
+  int   _nbyte;
+    /**
+   * @brief Sample justification and order
+   */
+  std::string   _justify;
+    /**
+   * @brief Number of SAR channels
+   */
+  int   _nchn;
+    /**
+   * @brief Lines per data set
+   */
+  int   _nlin;
+    /**
+   * @brief Left border pixels per line
+   */
+  int   _nleft;
+    /**
+   * @brief Groups per line per channel
+   */
+  int   _ngrp;
+    /**
+   * @brief Right border pixels per line
+   */
+  int   _nright;
+    /**
+   * @brief Top border lines
+   */
+  int   _ntop;
+    /**
+   * @brief Bottom border lines
+   */
+  int   _nbott;
+    /**
+   * @brief Interleave indicator
+   */
+  std::string   _intleav;
+    /**
+   * @brief Number of physical records per line
+   */
+  int   _nrec_lin;
+    /**
+   * @brief Number of physical records per multi-channel line in this file
+   */
+  int   _nrec_chn;
+    /**
+   * @brief Number of bytes of prefix data per record
+   */
+  int   _n_prefix;
+    /**
+   * @brief Number of bytes of SAR data (or pixel data) per record
+   */
+  int   _n_sar;
+    /**
+   * @brief Number of bytes of suffix data per record
+   */
+  int   _n_suffix;
+
+    /**
+   * @brief Line number locator
+   */
+  std::string   _lin_loc;
+    /**
+   * @brief Channel number locator
+   */
+  std::string   _chn_loc;
+    /**
+   * @brief Time locator
+   */
+  std::string   _tim_loc;
+    /**
+   * @brief Left fill locator
+   */
+  std::string   _left_loc;
+    /**
+   * @brief Right fill locator
+   */
+  std::string   _right_loc;
+    /**
+   * @brief Pad pixel indicator
+   */
+  std::string   _pad_ind;
+
+    /**
+   * @brief Quality code locator
+   */
+  std::string   _qual_loc;
+    /**
+   * @brief Calibration info locator
+   */
+  std::string   _cali_loc;
+    /**
+   * @brief Gain value locator
+   */
+  std::string   _gain_loc;
+    /**
+   * @brief Bias value locator
+   */
+  std::string   _bias_loc;
+    /**
+   * @brief Data type identifier
+   */
+  std::string   _type_id;
+  /**
+   * @brief Data type code
+   */
+  std::string   _type_code;
+    /**
+   * @brief Number of left fill bits
+   */
+  int   _left_fill;
+    /**
+   * @brief Number of right fill bits
+   */
+  int   _right_fill;
+    /**
+   * @brief Maximum data range of pixel
+   */
+  int   _pix_rng;
+
+private:
+};
+}
+#endif
+
diff --git a/ossim_plugins/ossim/RadarSat/Data/ProcessedDataRecord.cpp b/ossim_plugins/ossim/RadarSat/Data/ProcessedDataRecord.cpp
new file mode 100644
index 0000000..cd3cf62
--- /dev/null
+++ b/ossim_plugins/ossim/RadarSat/Data/ProcessedDataRecord.cpp
@@ -0,0 +1,223 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include <RadarSat/Data/ProcessedDataRecord.h>
+
+namespace ossimplugins
+{
+
+   ProcessedDataRecord::ProcessedDataRecord() : RadarSatRecord("proc_data_rec")
+   {
+   }
+
+   ProcessedDataRecord::~ProcessedDataRecord()
+   {
+   }
+
+   std::ostream& operator<<(std::ostream& os, const ProcessedDataRecord& data)
+   {
+      os<<"line_num:"<<data._line_num<<std::endl;
+      os<<"rec_num:"<<data._rec_num<<std::endl;
+      os<<"n_left_pixel:"<<data._n_left_pixel<<std::endl;
+      os<<"n_data_pixel:"<<data._n_data_pixel<<std::endl;
+      os<<"n_right_pixel:"<<data._n_right_pixel<<std::endl;
+      os<<"sensor_updf:"<<data._sensor_updf<<std::endl;
+      os<<"acq_year:"<<data._acq_year<<std::endl;
+      os<<"acq_day:"<<data._acq_day<<std::endl;
+      os<<"acq_msec:"<<data._acq_msec<<std::endl;
+      os<<"sar_chan_ind:"<<data._sar_chan_ind<<std::endl;
+      os<<"sar_chan_code:"<<data._sar_chan_code<<std::endl;
+      os<<"tran_polar:"<<data._tran_polar<<std::endl;
+      os<<"recv_polar:"<<data._recv_polar<<std::endl;
+      os<<"prf:"<<data._prf<<std::endl;
+      os<<"sr_first:"<<data._sr_first<<std::endl;
+      os<<"sr_last:"<<data._sr_last<<std::endl;
+      os<<"fdc_first:"<<data._fdc_first<<std::endl;
+      os<<"fdc_mid:"<<data._fdc_mid<<std::endl;
+      os<<"fdc_last:"<<data._fdc_last<<std::endl;
+      os<<"ka_first:"<<data._ka_first<<std::endl;
+      os<<"ka_mid:"<<data._ka_mid<<std::endl;
+      os<<"ka_last:"<<data._ka_last<<std::endl;
+      os<<"nadir_ang:"<<data._nadir_ang<<std::endl;
+      os<<"squint_ang:"<<data._squint_ang<<std::endl;
+      os<<"geo_updf:"<<data._geo_updf<<std::endl;
+      os<<"lat_first:"<<data._lat_first<<std::endl;
+      os<<"lat_mid:"<<data._lat_mid<<std::endl;
+      os<<"lat_last:"<<data._lat_last<<std::endl;
+      os<<"lon_first:"<<data._lon_first<<std::endl;
+      os<<"lon_mid:"<<data._lon_mid<<std::endl;
+      os<<"lon_last:"<<data._lon_last<<std::endl;
+      os<<"north_first:"<<data._north_first<<std::endl;
+      os<<"north_last:"<<data._north_last<<std::endl;
+      os<<"east_first:"<<data._east_first<<std::endl;
+      os<<"east_last:"<<data._east_last<<std::endl;
+      os<<"heading:"<<data._heading<<std::endl;
+
+      return os;
+   }
+
+   void SwitchEndian(int& value)
+   {
+      char buffer[4];
+      char res[4];
+
+      memcpy(buffer,&value,4);
+      res[0] = buffer[3];
+      res[1] = buffer[2];
+      res[2] = buffer[1];
+      res[3] = buffer[0];
+
+      memcpy(&value,res,4);
+   }
+
+   std::istream& operator>>(std::istream& is, ProcessedDataRecord& data)
+   {
+      char buf[193];
+      buf[192] = '\0';
+
+      is.read((char*)&(data._line_num),4);
+      data.SwitchEndian(data._line_num);
+
+      is.read((char*)&(data._rec_num),4);
+      data.SwitchEndian(data._rec_num);
+
+      is.read((char*)&(data._n_left_pixel),4);
+      data.SwitchEndian(data._n_left_pixel);
+
+      is.read((char*)&(data._n_data_pixel),4);
+      data.SwitchEndian(data._n_data_pixel);
+
+      is.read((char*)&(data._n_right_pixel),4);
+      data.SwitchEndian(data._n_right_pixel);
+
+      is.read((char*)&(data._sensor_updf),4);
+      data.SwitchEndian(data._sensor_updf);
+
+      is.read((char*)&(data._acq_year),4);
+      data.SwitchEndian(data._acq_year);
+
+      is.read((char*)&(data._acq_day),4);
+      data.SwitchEndian(data._acq_day);
+
+      is.read((char*)&(data._acq_msec),4);
+      data.SwitchEndian(data._acq_msec);
+
+      is.read((char*)&(data._sar_chan_ind),2);
+      data.SwitchEndian(data._sar_chan_ind);
+
+      is.read((char*)&(data._sar_chan_code),2);
+      data.SwitchEndian(data._sar_chan_code);
+
+      is.read((char*)&(data._tran_polar),2);
+      data.SwitchEndian(data._tran_polar );
+
+      is.read((char*)&(data._recv_polar),2);
+      data.SwitchEndian(data._recv_polar);
+
+      is.read((char*)&(data._prf),4);
+      data.SwitchEndian(data._prf );
+
+      is.read(buf,4);
+
+      is.read((char*)&(data._sr_first),4);
+      data.SwitchEndian(data._sr_first);
+
+      is.read((char*)&(data._sr_mid),4);
+      data.SwitchEndian(data._sr_mid);
+
+      is.read((char*)&(data._sr_last),4);
+      data.SwitchEndian(data._sr_last);
+
+      is.read((char*)&(data._fdc_first),4);
+      data.SwitchEndian(data._fdc_first);
+
+      is.read((char*)&(data._fdc_mid),4);
+      data.SwitchEndian(data._fdc_mid);
+
+      is.read((char*)&(data._fdc_last),4);
+      data.SwitchEndian(data._fdc_last);
+
+      is.read((char*)&(data._ka_first),4);
+      data.SwitchEndian(data._ka_first);
+
+      is.read((char*)&(data._ka_mid),4);
+      data.SwitchEndian(data._ka_mid);
+
+      is.read((char*)&(data._ka_last),4);
+      data.SwitchEndian(data._ka_last);
+
+      is.read((char*)&(data._nadir_ang),4);
+      data.SwitchEndian(data._nadir_ang);
+
+      is.read((char*)&(data._squint_ang),4);
+      data.SwitchEndian(data._squint_ang);
+
+      is.read(buf,4);
+      is.read(buf,16);
+
+      is.read((char*)&(data._geo_updf),4);
+      data.SwitchEndian(data._geo_updf);
+
+      is.read((char*)&(data._lat_first),4);
+      data.SwitchEndian(data._lat_first);
+
+      is.read((char*)&(data._lat_mid),4);
+      data.SwitchEndian(data._lat_mid);
+
+      is.read((char*)&(data._lat_last),4);
+      data.SwitchEndian(data._lat_last);
+
+      is.read((char*)&(data._lon_first),4);
+      data.SwitchEndian(data._lon_first);
+
+      is.read((char*)&(data._lon_mid),4);
+      data.SwitchEndian(data._lon_mid);
+
+      is.read((char*)&(data._lon_last),4);
+      data.SwitchEndian(data._lon_last);
+
+      is.read((char*)&(data._north_first),4);
+      data.SwitchEndian(data._north_first);
+
+      is.read(buf,4);
+
+      is.read((char*)&(data._north_last),4);
+      data.SwitchEndian(data._north_last);
+
+      is.read((char*)&(data._east_first),4);
+      data.SwitchEndian(data._east_first);
+
+      is.read(buf,4);
+
+      is.read((char*)&(data._east_last),4);
+      data.SwitchEndian(data._east_last);
+
+      is.read((char*)&(data._heading),4);
+      data.SwitchEndian(data._heading);
+
+      is.read(buf,8);
+
+      return is;
+   }
+
+   ProcessedDataRecord::ProcessedDataRecord(const ProcessedDataRecord& rhs):
+      RadarSatRecord(rhs)
+   {
+
+
+   }
+
+   ProcessedDataRecord& ProcessedDataRecord::operator=(const ProcessedDataRecord& /* rhs */)
+   {
+      return *this;
+   }
+}
+
diff --git a/ossim_plugins/ossim/RadarSat/Data/ProcessedDataRecord.h b/ossim_plugins/ossim/RadarSat/Data/ProcessedDataRecord.h
new file mode 100644
index 0000000..80cbb98
--- /dev/null
+++ b/ossim_plugins/ossim/RadarSat/Data/ProcessedDataRecord.h
@@ -0,0 +1,423 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef ProcessedDataRecord_h
+#define ProcessedDataRecord_h
+
+#include <iostream>
+
+#include <RadarSat/RadarSatRecord.h>
+#include <RadarSat/RadarSatRecordHeader.h>
+#include <ossim/base/ossimCommon.h>
+
+namespace ossimplugins
+{
+/**
+ * @ingroup ProcessedDataRecord
+ * @brief This class is able to read an Processed Data Record
+ */
+class ProcessedDataRecord : public RadarSatRecord
+{
+public:
+  /**
+   * @brief Constructor
+   */
+  ProcessedDataRecord();
+
+  /**
+   * @brief Destructor
+   */
+  ~ProcessedDataRecord();
+
+  /**
+   * @brief Copy constructor
+   */
+  ProcessedDataRecord(const ProcessedDataRecord& rhs);
+
+  /**
+   * @brief Copy operator
+   */
+  ProcessedDataRecord& operator=(const ProcessedDataRecord& rhs);
+  /**
+   * @brief This function writes the ProcessedDataRecord in a stream
+   */
+  friend std::ostream& operator<<(std::ostream& os, const ProcessedDataRecord& data);
+
+  /**
+   * @brief This function reads a ProcessedDataRecord from a stream
+   */
+  friend std::istream& operator>>(std::istream& is, ProcessedDataRecord& data);
+
+  /**
+   * @brief This function is able to create a new instance of the class
+   */
+  RadarSatRecord* Instanciate()
+  {
+    return new ProcessedDataRecord();
+  };
+
+  /**
+   * @brief This function is able to create a new instance of the class initialised with the data of the calling instance
+   */
+  RadarSatRecord* Clone()
+  {
+    return new ProcessedDataRecord(*this);
+  };
+
+  /**
+   * @brief Reads the class data from a stream
+   */
+  void Read(std::istream& is)
+  {
+    is>>*this;
+  };
+
+  /**
+   * @brief Writes the class to a stream
+   */
+  void Write(std::ostream& os)
+  {
+    os<<*this;
+  };
+  /**
+   * @brief Image data line number
+   */
+  int get_line_num() {return _line_num;};
+
+    /**
+   * @brief Image data record index
+   */
+  int get_rec_num() {return _rec_num;};
+    /**
+   * @brief Left fill pixel count
+   */
+  int get_n_left_pixel() {return _n_left_pixel;};
+    /**
+   * @brief Data pixel count
+   */
+  int get_n_data_pixel() {return _n_data_pixel;};
+    /**
+   * @brief Right fill pixel count
+   */
+  int get_n_right_pixel() {return _n_right_pixel;};
+    /**
+   * @brief Sensor parameter update flag
+   */
+  int get_sensor_updf() {return _sensor_updf;};
+    /**
+   * @brief Acquisition year
+   */
+  int   get_acq_year() {return _acq_year;};
+    /**
+   * @brief Acquisition day
+   */
+  int   get_acq_day() {return _acq_day;};
+    /**
+   * @brief Acquisition msecs
+   */
+  int   get_acq_msec() {return _acq_msec;};
+    /**
+   * @brief SAR channel indicator
+   */
+  int   get_sar_chan_ind() {return _sar_chan_ind;};
+    /**
+   * @brief SAR channel code
+   */
+  int   get_sar_chan_code() {return _sar_chan_code;};
+    /**
+   * @brief Transmitted polarization
+   */
+  int   get_tran_polar() {return _tran_polar;};
+    /**
+   * @brief Received polarization
+   */
+  int   get_recv_polar() {return _recv_polar;};
+    /**
+   * @brief PRF
+   */
+  int  get_prf() {return _prf;};
+    /**
+   * @brief Slant range to first pixel, m
+   */
+  int   get_sr_first() {return _sr_first;};
+    /**
+   * @brief Slant range to mid-pixel, m
+   */
+  int get_sr_mid() {return _sr_mid;};
+    /**
+   * @brief Slant range to last pixel, m
+   */
+  int get_sr_last() {return _sr_last;};
+    /**
+   * @brief First pixel Doppler centroid, Hz
+   */
+  int get_fdc_first() {return _fdc_first;};
+    /**
+   * @brief Mid pixel Doppler centroid, Hz
+   */
+  int   get_fdc_mid() {return _fdc_mid;};
+    /**
+   * @brief Last pixel Doppler centroid, Hz
+   */
+  int   get_fdc_last() {return _fdc_last;};
+    /**
+   * @brief First pixel azimuth FM rate, Hz
+   */
+  int get_ka_first() {return _ka_first;};
+     /**
+   * @brief Mid pixel azimuth FM rate, Hz
+   */
+  int get_ka_mid() {return _ka_mid;};
+   /**
+   * @brief Last pixel azimuth FM rate, Hz
+   */
+  int get_ka_last() {return _ka_last;};
+    /**
+   * @brief Nadir look angle, 10e-6 deg
+   */
+  int get_nadir_ang() {return _nadir_ang;};
+    /**
+   * @brief Azimuth squint angle, 10e-6 deg
+   */
+  int get_squint_ang() {return _squint_ang;};
+    /**
+   * @brief Geographic ref parameter update flag
+   */
+  int get_geo_updf() {return _geo_updf;};
+    /**
+   * @brief First pixel latitude, 10e-6 deg
+   */
+  int get_lat_first() {return _lat_first;};
+    /**
+   * @brief Mid-pixel latitude, 10e-6 deg
+   */
+  int get_lat_mid() {return _lat_mid;};
+   /**
+   * @brief Last-pixel latitude, 10e-6 deg
+   */
+  int get_lat_last() {return _lat_last;};
+  /**
+   * @brief First pixel longitude, 10e-6 deg
+   */
+  int get_lon_first() {return _lon_first;};
+    /**
+   * @brief Mid-pixel longitude, 10e-6 deg
+   */
+  int get_lon_mid() {return _lon_mid;};
+   /**
+   * @brief Last-pixel longitude, 10e-6 deg
+   */
+  int get_lon_last() {return _lon_last;};
+    /**
+   * @brief Northing of first pixel, m
+   */
+  int get_north_first() {return _north_first;};
+   /**
+   * @brief Northing of last pixel, m
+   */
+  int get_north_last() {return _north_last;};
+  /**
+   * @brief Easting of first pixel, m
+   */
+  int get_east_first() {return _east_first;};
+   /**
+   * @brief Easting of last pixel, m
+   */
+  int get_east_last() {return _east_last;};
+   /**
+   * @brief Line heading, 10e-6 deg
+   */
+  int get_heading() {return _heading;};
+
+protected:
+  /**
+   * @brief Image data line number
+   */
+  int _line_num;
+
+    /**
+   * @brief Image data record index
+   */
+  int _rec_num;
+    /**
+   * @brief Left fill pixel count
+   */
+  int _n_left_pixel;
+    /**
+   * @brief Data pixel count
+   */
+  int _n_data_pixel;
+    /**
+   * @brief Right fill pixel count
+   */
+  int _n_right_pixel;
+    /**
+   * @brief Sensor parameter update flag
+   */
+  int _sensor_updf;
+    /**
+   * @brief Acquisition year
+   */
+  int   _acq_year;
+    /**
+   * @brief Acquisition day
+   */
+  int   _acq_day;
+    /**
+   * @brief Acquisition msecs
+   */
+  int   _acq_msec;
+    /**
+   * @brief SAR channel indicator
+   */
+  int   _sar_chan_ind;
+    /**
+   * @brief SAR channel code
+   */
+  int   _sar_chan_code;
+    /**
+   * @brief Transmitted polarization
+   */
+  int   _tran_polar;
+    /**
+   * @brief Received polarization
+   */
+  int   _recv_polar;
+    /**
+   * @brief PRF
+   */
+  int   _prf;
+    /**
+   * @brief Slant range to first pixel, m
+   */
+  int   _sr_first;
+    /**
+   * @brief Slant range to mid-pixel, m
+   */
+  int _sr_mid;
+
+    /**
+   * @brief Slant range to last pixel, m
+   */
+  int _sr_last;
+    /**
+   * @brief First pixel Doppler centroid, Hz
+   */
+  int _fdc_first;
+
+    /**
+   * @brief Mid pixel Doppler centroid, Hz
+   */
+  int   _fdc_mid;
+    /**
+   * @brief Last pixel Doppler centroid, Hz
+   */
+  int   _fdc_last;
+    /**
+   * @brief First pixel azimuth FM rate, Hz
+   */
+  int _ka_first;
+     /**
+   * @brief Mid pixel azimuth FM rate, Hz
+   */
+  int _ka_mid;
+   /**
+   * @brief Last pixel azimuth FM rate, Hz
+   */
+  int _ka_last;
+    /**
+   * @brief Nadir look angle, 10e-6 deg
+   */
+  int _nadir_ang;
+    /**
+   * @brief Azimuth squint angle, 10e-6 deg
+   */
+  int _squint_ang;
+    /**
+   * @brief Geographic ref parameter update flag
+   */
+  int _geo_updf;
+    /**
+   * @brief First pixel latitude, 10e-6 deg
+   */
+  int _lat_first;
+    /**
+   * @brief Mid-pixel latitude, 10e-6 deg
+   */
+  int _lat_mid;
+   /**
+   * @brief Last-pixel latitude, 10e-6 deg
+   */
+  int _lat_last;
+  /**
+   * @brief First pixel longitude, 10e-6 deg
+   */
+  int _lon_first;
+    /**
+   * @brief Mid-pixel longitude, 10e-6 deg
+   */
+  int _lon_mid;
+   /**
+   * @brief Last-pixel longitude, 10e-6 deg
+   */
+  int _lon_last;
+    /**
+   * @brief Northing of first pixel, m
+   */
+  int _north_first;
+   /**
+   * @brief Northing of last pixel, m
+   */
+  int _north_last;
+  /**
+   * @brief Easting of first pixel, m
+   */
+  int _east_first;
+   /**
+   * @brief Easting of last pixel, m
+   */
+  int _east_last;
+   /**
+   * @brief Line heading, 10e-6 deg
+   */
+  int _heading;
+
+private:
+  /**
+   * @brief This function switches the LSB value and the MSB value of the parameter
+   */
+  template<typename T>
+  void SwitchEndian(T &value) {
+
+    char *buffer;
+    char *res;
+    int nb_octets = sizeof(T);
+
+    if (ossim::byteOrder() == OSSIM_LITTLE_ENDIAN) {
+      buffer = (char* )malloc(nb_octets);
+      res = (char* )malloc(nb_octets);
+
+      memcpy(buffer,&value,nb_octets);
+
+      for (int i=0; i<nb_octets/2; i++) {
+        res[i] = buffer[nb_octets-1-i];
+        res[nb_octets-1-i] = buffer[i];
+      }
+      memcpy(&value,res,nb_octets);
+
+      free(buffer);
+      free(res);
+    }
+  }
+};
+}
+#endif
+
diff --git a/ossim_plugins/ossim/RadarSat/Leader/DataHistogramProcessedData.cpp b/ossim_plugins/ossim/RadarSat/Leader/DataHistogramProcessedData.cpp
new file mode 100644
index 0000000..3f59369
--- /dev/null
+++ b/ossim_plugins/ossim/RadarSat/Leader/DataHistogramProcessedData.cpp
@@ -0,0 +1,95 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include <RadarSat/Leader/DataHistogramProcessedData.h>
+
+namespace ossimplugins
+{
+DataHistogramProcessedData::DataHistogramProcessedData() : RadarSatRecord("pdr16_hist_rec")
+{
+}
+
+DataHistogramProcessedData::~DataHistogramProcessedData()
+{
+}
+
+std::ostream& operator<<(std::ostream& os, const DataHistogramProcessedData& data)
+{
+	os<<"rec_seq:"<<data._rec_seq<<std::endl;
+
+    os<<"sar_chn:"<<data._sar_chn<<std::endl;
+
+	os<<"ntab:"<<data._ntab<<std::endl;
+
+	os<<"ltab:"<<data._ltab<<std::endl;
+
+	os<<data._histogram1<<std::endl;
+
+	os<<data._histogram2<<std::endl;
+
+	return os;
+}
+
+std::istream& operator>>(std::istream& is, DataHistogramProcessedData& data)
+{
+	char buff[33];
+	buff[32] = '\0';
+
+	is.read(buff,4);
+	buff[4] = '\0';
+	data._rec_seq = atoi(buff);
+
+    is.read(buff,4);
+	buff[4] = '\0';
+	data._sar_chn = atoi(buff);
+
+	is.read(buff,8);
+	buff[8] = '\0';
+	data._ntab = atoi(buff);
+
+	is.read(buff,8);
+	buff[8] = '\0';
+	data._ltab = atoi(buff);
+
+	is>>data._histogram1;
+
+	is>>data._histogram2;
+
+	char tmp[5];
+	tmp[4] = '\0';
+	is.read(tmp, 4);
+	return is;
+}
+
+DataHistogramProcessedData::DataHistogramProcessedData(const DataHistogramProcessedData& rhs) :
+		RadarSatRecord(rhs),
+		_rec_seq(rhs._rec_seq),
+		_sar_chn(rhs._sar_chn),
+		_ntab(rhs._ntab),
+		_ltab(rhs._ltab),
+		_histogram1(rhs._histogram1),
+		_histogram2(rhs._histogram2)
+{
+
+}
+
+DataHistogramProcessedData& DataHistogramProcessedData::operator=(const DataHistogramProcessedData& rhs)
+{
+	_histogram1 = rhs._histogram1;
+	_histogram2 = rhs._histogram2;
+	_sar_chn = rhs._sar_chn;
+	_rec_seq = rhs._rec_seq;
+	_ntab = rhs._ntab;
+	_ltab = rhs._ltab;
+	return *this;
+}
+}
+
diff --git a/ossim_plugins/ossim/RadarSat/Leader/DataHistogramProcessedData.h b/ossim_plugins/ossim/RadarSat/Leader/DataHistogramProcessedData.h
new file mode 100644
index 0000000..b710b18
--- /dev/null
+++ b/ossim_plugins/ossim/RadarSat/Leader/DataHistogramProcessedData.h
@@ -0,0 +1,173 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef DataHistogramProcessedData_h
+#define DataHistogramProcessedData_h
+
+#include<iostream>
+
+#include <RadarSat/RadarSatRecord.h>
+#include <RadarSat/RadarSatRecordHeader.h>
+#include <RadarSat/CommonRecord/DataHistogramRecord.h>
+
+namespace ossimplugins
+{
+/**
+ * @ingroup ProcessedData16bitHistogramRecord
+ * @brief This class is able to read a data histogram record - Processed data
+ * @warning There is an error in the documentation for the spare at the end of the record.
+ *      They say 3 bytes (A3) but they also say that the spare is on the bytes 16917, 16918, 16919 and 16920.
+ *      In the data files I have, I need to use a spare of 4 bytes.
+ */
+class DataHistogramProcessedData : public RadarSatRecord
+{
+public:
+  /**
+   * @brief Constructor
+   */
+  DataHistogramProcessedData();
+
+  /**
+   * @brief Destructor
+   */
+  virtual ~DataHistogramProcessedData();
+
+  /**
+   * @brief Copy constructor
+   */
+  DataHistogramProcessedData(const DataHistogramProcessedData& rhs);
+
+  /**
+   * @brief Copy operator
+   */
+  DataHistogramProcessedData& operator=(const DataHistogramProcessedData& rhs);
+  /**
+   * @brief This function writes the DataHistogramProcessedData in a stream
+   */
+  friend std::ostream& operator<<(std::ostream& os, const DataHistogramProcessedData& data);
+
+  /**
+   * @brief This function reads a DataHistogramProcessedData from a stream
+   */
+  friend std::istream& operator>>(std::istream& is, DataHistogramProcessedData& data);
+
+  /**
+   * @brief This function is able to create a new instance of the class
+   */
+  RadarSatRecord* Instanciate()
+  {
+    return new DataHistogramProcessedData();
+  };
+
+  /**
+   * @brief This function is able to create a new instance of the class initialised with the data of the calling instance
+   */
+  RadarSatRecord* Clone()
+  {
+    return new DataHistogramProcessedData(*this);
+  };
+
+  /**
+   * @brief Reads the class data from a stream
+   */
+  void Read(std::istream& is)
+  {
+    is>>*this;
+  };
+
+  /**
+   * @brief Writes the class to a stream
+   */
+  void Write(std::ostream& os)
+  {
+    os<<*this;
+  };
+
+  /**
+   * @brief Record sequence number
+   */
+  int   get_rec_seq()
+  {
+    return _rec_seq;
+  };
+  /**
+   * @brief SAR channel indicator
+   */
+  int   get_sar_chn()
+  {
+    return _sar_chn;
+  };
+
+  /**
+   * @brief Number of histogram table data sets in this record
+   */
+  int   get_ntab()
+  {
+    return _ntab;
+  };
+
+  /**
+   * @brief Histogram table data set size
+   */
+  int   get_ltab()
+  {
+    return _ltab;
+  };
+
+  /**
+   * @brief Histogram data record #1
+   */
+  DataHistogramRecord get_histogram1()
+  {
+    return _histogram1;
+  };
+
+  /**
+   * @brief Histogram data record #2
+   */
+  DataHistogramRecord get_histogram2()
+  {
+    return _histogram2;
+  };
+protected:
+  /**
+   * @brief Record sequence number
+   */
+  int   _rec_seq;
+  /**
+   * @brief SAR channel indicator
+   */
+  int   _sar_chn;
+
+  /**
+   * @brief Number of histogram table data sets in this record
+   */
+  int   _ntab;
+  /**
+   * @brief Histogram table data set size
+   */
+  int   _ltab;
+  /**
+   * @brief Histogram data record #1
+   */
+  DataHistogramRecord _histogram1;
+  /**
+   * @brief Histogram data record #2
+   */
+  DataHistogramRecord _histogram2;
+
+private:
+
+
+};
+}
+#endif
+
diff --git a/ossim_plugins/ossim/RadarSat/Leader/Leader.cpp b/ossim_plugins/ossim/RadarSat/Leader/Leader.cpp
new file mode 100644
index 0000000..bbacab9
--- /dev/null
+++ b/ossim_plugins/ossim/RadarSat/Leader/Leader.cpp
@@ -0,0 +1,201 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include <RadarSat/Leader/Leader.h>
+#include <RadarSat/Leader/LeaderFactory.h>
+#include <RadarSat/RadarSatRecordHeader.h>
+
+#include <RadarSat/Leader/DataHistogramProcessedData.h>
+#include <RadarSat/Leader/PlatformPositionData.h>
+
+#include <RadarSat/CommonRecord/DataHistogramSignalData.h>
+#include <RadarSat/CommonRecord/DataQuality.h>
+#include <RadarSat/CommonRecord/DataSetSummary.h>
+#include <RadarSat/CommonRecord/FileDescriptor.h>
+#include <RadarSat/CommonRecord/ProcessingParameters.h>
+#include <RadarSat/CommonRecord/AttitudeData.h>
+#include <RadarSat/CommonRecord/RadiometricData.h>
+#include <RadarSat/CommonRecord/RadiometricCompensationData.h>
+
+
+namespace ossimplugins
+{
+
+const int Leader::RadiometricDataID = 9;
+const int Leader::RadiometricCompensationDataID = 10;
+const int Leader::AttitudeDataID = 8;
+const int Leader::PlatformPositionDataID = 7;
+const int Leader::ProcessingParametersID = 6;
+const int Leader::DataHistogramProcessedDataID = 5;
+const int Leader::DataHistogramSignalDataID = 4;
+const int Leader::DataQualityID = 3;
+const int Leader::DataSetSummaryID = 2;
+const int Leader::FileDescriptorID = 1;
+
+Leader::Leader()
+{
+}
+
+Leader::~Leader()
+{
+	ClearRecords();
+}
+
+std::ostream& operator<<(std::ostream& os, const Leader& data)
+{
+	std::map<int, RadarSatRecord*>::const_iterator it = data._records.begin();
+	while(it != data._records.end())
+	{
+		(*it).second->Write(os);
+		++it;
+	}
+	return os;
+
+}
+
+std::istream& operator>>(std::istream& is, Leader& data)
+{
+	LeaderFactory factory;
+
+	data.ClearRecords();
+
+	RadarSatRecordHeader header;
+	bool eof = false;
+	while(!eof)
+	  {
+		is>>header;
+		if(is.eof())
+		  {
+			eof = true;
+		  }
+		else
+		  {
+		  RadarSatRecord* record;
+		  if ( (header.get_rec_seq() == 2) && (header.get_length() == 8960) )
+		    {
+		    record = factory.Instanciate(header.get_rec_seq() + 5); // case of SCN, SCW
+        if (record != NULL)
+          {
+          record->Read(is);
+          data._records[header.get_rec_seq() + 5] = record;
+          }
+        else
+          {
+          char* buff = new char[header.get_length()-12];
+          is.read(buff, header.get_length()-12);
+          delete[] buff;
+          }
+		    }
+		  else
+		    {
+        record = factory.Instanciate(header.get_rec_seq());
+        if (record != NULL)
+          {
+          record->Read(is);
+          data._records[header.get_rec_seq()] = record;
+          }
+        else
+          {
+          char* buff = new char[header.get_length()-12];
+          is.read(buff, header.get_length()-12);
+          delete[] buff;
+          }
+		    }
+		  }
+	  }
+	return is;
+}
+
+Leader::Leader(const Leader& rhs)
+{
+	std::map<int, RadarSatRecord*>::const_iterator it = rhs._records.begin();
+	while(it != rhs._records.end())
+	{
+		_records[(*it).first] = (*it).second->Clone();
+		++it;
+	}
+}
+
+Leader& Leader::operator=(const Leader& rhs)
+{
+	ClearRecords();
+	std::map<int, RadarSatRecord*>::const_iterator it = rhs._records.begin();
+	while(it != rhs._records.end())
+	{
+		_records[(*it).first] = (*it).second->Clone();
+		++it;
+	}
+
+	return *this;
+}
+
+void Leader::ClearRecords()
+{
+	std::map<int, RadarSatRecord*>::const_iterator it = _records.begin();
+	while(it != _records.end())
+	{
+		delete (*it).second;
+		++it;
+	}
+	_records.clear();
+}
+
+RadiometricData * Leader::get_RadiometricData()
+{
+	return (RadiometricData*)_records[RadiometricDataID];
+}
+
+RadiometricCompensationData * Leader::get_RadiometricCompensationData()
+{
+	return (RadiometricCompensationData*)_records[RadiometricCompensationDataID];
+}
+
+AttitudeData * Leader::get_AttitudeData()
+{
+	return (AttitudeData*)_records[AttitudeDataID];
+}
+
+PlatformPositionData * Leader::get_PlatformPositionData()
+{
+	return (PlatformPositionData*)_records[PlatformPositionDataID];
+}
+
+ProcessingParameters * Leader::get_ProcessingParameters()
+{
+	return (ProcessingParameters*)_records[ProcessingParametersID];
+}
+
+DataHistogramProcessedData * Leader::get_DataHistogramProcessedData()
+{
+	return (DataHistogramProcessedData*)_records[DataHistogramProcessedDataID];
+}
+
+DataHistogramSignalData * Leader::get_DataHistogramSignalData()
+{
+	return (DataHistogramSignalData*)_records[DataHistogramSignalDataID];
+}
+
+DataQuality * Leader::get_DataQuality()
+{
+	return (DataQuality*)_records[DataQualityID];
+}
+
+DataSetSummary * Leader::get_DataSetSummary()
+{
+	return (DataSetSummary*)_records[DataSetSummaryID];
+}
+
+FileDescriptor * Leader::get_FileDescriptor()
+{
+	return (FileDescriptor*)_records[FileDescriptorID];
+}
+}
+
diff --git a/ossim_plugins/ossim/RadarSat/Leader/Leader.h b/ossim_plugins/ossim/RadarSat/Leader/Leader.h
new file mode 100644
index 0000000..83bfdb4
--- /dev/null
+++ b/ossim_plugins/ossim/RadarSat/Leader/Leader.h
@@ -0,0 +1,109 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef Leader_h
+#define Leader_h
+
+#include <iostream>
+#include <RadarSat/CommonRecord/FileDescriptor.h>
+#include <RadarSat/CommonRecord/DataSetSummary.h>
+#include <RadarSat/CommonRecord/DataQuality.h>
+#include <RadarSat/CommonRecord/DataHistogramSignalData.h>
+#include "DataHistogramProcessedData.h"
+#include <map>
+
+namespace ossimplugins
+{
+class RadiometricData;
+class RadiometricCompensationData;
+class AttitudeData;
+class PlatformPositionData;
+class ProcessingParameters;
+class DataHistogramProcessedData;
+class DataHistogramSignalData;
+class DataQuality;
+class DataSetSummary;
+class FileDescriptor;
+
+/**
+ * @ingroup LeaderFile
+ * @brief This class is able to read the leader file of the RadarSat file structure
+ * @author Magellium, Pacome Dentraygues
+ * @version 1.0
+ * @date 23-11-07
+ */
+class Leader
+{
+public:
+  /**
+   * @brief Constructor
+   */
+  Leader();
+
+  /**
+   * @brief Destructor
+   */
+  ~Leader();
+
+  /**
+   * @brief This function writes the Leader in a stream
+   */
+  friend std::ostream& operator<<(std::ostream& os, const Leader& data);
+
+  /**
+   * @brief This function reads a Leader from a stream
+   */
+  friend std::istream& operator>>(std::istream& is, Leader& data);
+
+  /**
+   * @brief Copy constructor
+   */
+  Leader(const Leader& rhs);
+
+  /**
+   * @brief Copy operator
+   */
+  Leader& operator=(const Leader& rhs);
+
+  /**
+   * @brief Removes all the previous records from the Leader
+   */
+  void ClearRecords();
+
+  RadiometricData * get_RadiometricData();
+  RadiometricCompensationData * get_RadiometricCompensationData();
+  AttitudeData * get_AttitudeData();
+  PlatformPositionData * get_PlatformPositionData();
+  ProcessingParameters * get_ProcessingParameters();
+  DataHistogramProcessedData * get_DataHistogramProcessedData();
+  DataHistogramSignalData * get_DataHistogramSignalData();
+  DataQuality * get_DataQuality();
+  DataSetSummary * get_DataSetSummary();
+  FileDescriptor * get_FileDescriptor();
+protected:
+  std::map<int, RadarSatRecord*> _records;
+
+  static const int RadiometricDataID;
+  static const int RadiometricCompensationDataID;
+  static const int AttitudeDataID;
+  static const int PlatformPositionDataID;
+  static const int ProcessingParametersID;
+  static const int DataHistogramProcessedDataID;
+  static const int DataHistogramSignalDataID;
+  static const int DataQualityID;
+  static const int DataSetSummaryID;
+  static const int FileDescriptorID;
+private:
+
+};
+}
+#endif
+
diff --git a/ossim_plugins/ossim/RadarSat/Leader/LeaderFactory.cpp b/ossim_plugins/ossim/RadarSat/Leader/LeaderFactory.cpp
new file mode 100644
index 0000000..e95aed8
--- /dev/null
+++ b/ossim_plugins/ossim/RadarSat/Leader/LeaderFactory.cpp
@@ -0,0 +1,59 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include <RadarSat/Leader/LeaderFactory.h>
+
+#include <RadarSat/CommonRecord/DataHistogramSignalData.h>
+#include <RadarSat/CommonRecord/DataQuality.h>
+#include <RadarSat/CommonRecord/DataSetSummary.h>
+#include <RadarSat/CommonRecord/FileDescriptor.h>
+#include <RadarSat/Leader/DataHistogramProcessedData.h>
+#include <RadarSat/CommonRecord/ProcessingParameters.h>
+#include <RadarSat/Leader/PlatformPositionData.h>
+#include <RadarSat/CommonRecord/AttitudeData.h>
+#include <RadarSat/CommonRecord/RadiometricData.h>
+#include <RadarSat/CommonRecord/RadiometricCompensationData.h>
+
+namespace ossimplugins
+{
+LeaderFactory::LeaderFactory()
+{
+	RegisterRecord(9, new RadiometricData());
+	RegisterRecord(10, new RadiometricCompensationData());
+	RegisterRecord(8, new AttitudeData());
+	RegisterRecord(7, new PlatformPositionData());
+	RegisterRecord(6, new ProcessingParameters());
+	RegisterRecord(5, new DataHistogramProcessedData());
+	RegisterRecord(4, new DataHistogramSignalData());
+	RegisterRecord(3, new DataQuality());
+	RegisterRecord(2, new DataSetSummary());
+	RegisterRecord(1, new FileDescriptor());
+}
+
+LeaderFactory::~LeaderFactory()
+{
+
+  std::map<int, RadarSatRecord*>::iterator i = _availableRecords.begin();
+
+  while (i != _availableRecords.end())
+  {
+     if ( (*i).second )
+     {
+        delete (*i).second;
+        (*i).second = 0;
+     }
+     ++i;
+  }
+  _availableRecords.clear();
+
+}
+}
+
diff --git a/ossim_plugins/ossim/RadarSat/Leader/LeaderFactory.h b/ossim_plugins/ossim/RadarSat/Leader/LeaderFactory.h
new file mode 100644
index 0000000..6507a4d
--- /dev/null
+++ b/ossim_plugins/ossim/RadarSat/Leader/LeaderFactory.h
@@ -0,0 +1,45 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef LeaderFactory_h
+#define LeaderFactory_h
+
+
+#include <RadarSat/RadarSatRecordFactory.h>
+#include <map>
+
+namespace ossimplugins
+{
+/**
+ * @ingroup LeaderFile
+ * @brief This class is a factory able to construct Record base classes
+ */
+class LeaderFactory : public RadarSatRecordFactory
+{
+public:
+  /**
+   * @brief Contstructor
+   */
+  LeaderFactory();
+  /**
+   * @brief Destructor
+   */
+  ~LeaderFactory();
+
+
+protected:
+
+
+private:
+};
+}
+#endif
+
diff --git a/ossim_plugins/ossim/RadarSat/Leader/PlatformPositionData.cpp b/ossim_plugins/ossim/RadarSat/Leader/PlatformPositionData.cpp
new file mode 100644
index 0000000..f685302
--- /dev/null
+++ b/ossim_plugins/ossim/RadarSat/Leader/PlatformPositionData.cpp
@@ -0,0 +1,252 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include <RadarSat/Leader/PlatformPositionData.h>
+
+namespace ossimplugins
+{
+PlatformPositionData::PlatformPositionData() : RadarSatRecord("pos_data_rec")
+{
+}
+
+PlatformPositionData::~PlatformPositionData()
+{
+}
+
+std::ostream& operator<<(std::ostream& os, const PlatformPositionData& data)
+{
+	os<<"orbit_ele_desg:"<<data._orbit_ele_desg.c_str()<<std::endl;
+
+	for(int i=0;i<6;i++)
+	{
+		os<<"orbit_ele["<<i<<"]:"<<data._orbit_ele[i]<<std::endl;
+	}
+
+	os<<"ndata:"<<data._ndata<<std::endl;
+
+    os<<"year:"<<data._year<<std::endl;
+
+    os<<"month:"<<data._month<<std::endl;
+
+    os<<"day:"<<data._day<<std::endl;
+
+    os<<"gmt_day:"<<data._gmt_day<<std::endl;
+
+    os<<"gmt_sec:"<<data._gmt_sec<<std::endl;
+
+    os<<"data_int:"<<data._data_int<<std::endl;
+
+    os<<"ref_coord:"<<data._ref_coord.c_str()<<std::endl;
+
+    os<<"hr_angle:"<<data._hr_angle<<std::endl;
+
+    os<<"alt_poserr:"<<data._alt_poserr<<std::endl;
+
+    os<<"crt_poserr:"<<data._crt_poserr<<std::endl;
+
+    os<<"rad_poserr:"<<data._rad_poserr<<std::endl;
+
+	os<<"alt_velerr:"<<data._alt_velerr<<std::endl;
+
+    os<<"crt_velerr:"<<data._crt_velerr<<std::endl;
+
+    os<<"rad_velerr:"<<data._rad_velerr<<std::endl;
+
+	for (int i=0;i<64;i++)
+	{
+		os<<"pos_vect["<<i<<"]:"<<data._pos_vect[i]<<std::endl;
+	}
+
+	return os;
+}
+
+std::istream& operator>>(std::istream& is, PlatformPositionData& data)
+{
+	char buf[1207];
+	buf[1206] = '\0';
+
+	is.read(buf,32);
+	buf[32] = '\0';
+	data._orbit_ele_desg = buf;
+
+	for(int i=0;i<6;i++)
+	{
+		is.read(buf,16);
+		buf[16] = '\0';
+		data._orbit_ele[i] = atof(buf);
+	}
+
+	is.read(buf,4);
+	buf[4] = '\0';
+	data._ndata = atoi(buf);
+
+    is.read(buf,4);
+	buf[4] = '\0';
+	data._year = atoi(buf);
+
+    is.read(buf,4);
+	buf[4] = '\0';
+	data._month = atoi(buf);
+
+    is.read(buf,4);
+	buf[4] = '\0';
+	data._day = atoi(buf);
+
+    is.read(buf,4);
+	buf[4] = '\0';
+	data._gmt_day = atoi(buf);
+
+    is.read(buf,22);
+	buf[22] = '\0';
+	data._gmt_sec = atof(buf);
+
+    is.read(buf,22);
+	buf[22] = '\0';
+	data._data_int = atof(buf);
+
+    is.read(buf,64);
+	buf[64] = '\0';
+	data._ref_coord = buf;
+
+    is.read(buf,22);
+	buf[22] = '\0';
+	data._hr_angle = atof(buf);
+
+    is.read(buf,16);
+	buf[16] = '\0';
+	data._alt_poserr = atof(buf);
+
+    is.read(buf,16);
+	buf[16] = '\0';
+	data._crt_poserr = atof(buf);
+
+    is.read(buf,16);
+	buf[16] = '\0';
+	data._rad_poserr = atof(buf);
+
+    is.read(buf,16);
+	buf[16] = '\0';
+	data._alt_velerr = atof(buf);
+
+    is.read(buf,16);
+	buf[16] = '\0';
+	data._crt_velerr = atof(buf);
+
+    is.read(buf,16);
+	buf[16] = '\0';
+	data._rad_velerr = atof(buf);
+
+	for (int i=0;i<64;i++)
+	{
+		is>>data._pos_vect[i];
+	}
+
+    is.read(buf,126);
+
+
+	return is;
+}
+
+PlatformPositionData::PlatformPositionData(const PlatformPositionData& rhs):
+	RadarSatRecord(rhs)
+{
+	_orbit_ele_desg = rhs._orbit_ele_desg;
+
+	for(int i=0;i<6;i++)
+	{
+		_orbit_ele[i] = rhs._orbit_ele[i];
+	}
+
+	_ndata = rhs._ndata;
+
+    _year = rhs._year;
+
+    _month = rhs._month;
+
+    _day = rhs._day;
+
+    _gmt_day = rhs._gmt_day;
+
+    _gmt_sec = rhs._gmt_sec;
+
+    _data_int = rhs._data_int;
+
+    _ref_coord = rhs._ref_coord;
+
+    _hr_angle = rhs._hr_angle;
+
+    _alt_poserr = rhs._alt_poserr;
+
+    _crt_poserr = rhs._crt_poserr;
+
+    _rad_poserr = rhs._rad_poserr;
+
+	_alt_velerr = rhs._alt_velerr;
+
+    _crt_velerr = rhs._crt_velerr;
+
+    _rad_velerr = rhs._rad_velerr;
+
+	for (int i=0;i<64;i++)
+	{
+		_pos_vect[i] = rhs._pos_vect[i];
+	}
+
+}
+
+PlatformPositionData& PlatformPositionData::operator=(const PlatformPositionData& rhs)
+{
+		_orbit_ele_desg = rhs._orbit_ele_desg;
+
+	for(int i=0;i<6;i++)
+	{
+		_orbit_ele[i] = rhs._orbit_ele[i];
+	}
+
+	_ndata = rhs._ndata;
+
+    _year = rhs._year;
+
+    _month = rhs._month;
+
+    _day = rhs._day;
+
+    _gmt_day = rhs._gmt_day;
+
+    _gmt_sec = rhs._gmt_sec;
+
+    _data_int = rhs._data_int;
+
+    _ref_coord = rhs._ref_coord;
+
+    _hr_angle = rhs._hr_angle;
+
+    _alt_poserr = rhs._alt_poserr;
+
+    _crt_poserr = rhs._crt_poserr;
+
+    _rad_poserr = rhs._rad_poserr;
+
+	_alt_velerr = rhs._alt_velerr;
+
+    _crt_velerr = rhs._crt_velerr;
+
+    _rad_velerr = rhs._rad_velerr;
+
+	for (int i=0;i<64;i++)
+	{
+		_pos_vect[i] = rhs._pos_vect[i];
+	}
+
+	return *this;
+}
+}
+
diff --git a/ossim_plugins/ossim/RadarSat/Leader/PlatformPositionData.h b/ossim_plugins/ossim/RadarSat/Leader/PlatformPositionData.h
new file mode 100644
index 0000000..56a3fa5
--- /dev/null
+++ b/ossim_plugins/ossim/RadarSat/Leader/PlatformPositionData.h
@@ -0,0 +1,296 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef PlatformPositionData_h
+#define PlatformPositionData_h
+
+#include <iostream>
+#include <RadarSat/RadarSatRecord.h>
+#include <RadarSat/RadarSatRecordHeader.h>
+
+#include <RadarSat/Leader/PositionVectorRecord.h>
+
+namespace ossimplugins
+{
+/**
+ * @ingroup PlatformPositionDataRecord
+ * @brief This class is able to read a Platform position data record
+ */
+class PlatformPositionData : public RadarSatRecord
+{
+public:
+  /**
+   * @brief Constructor
+   */
+  PlatformPositionData();
+
+  /**
+   * @brief Destructor
+   */
+  ~PlatformPositionData();
+
+  /**
+   * @brief Copy constructor
+   */
+  PlatformPositionData(const PlatformPositionData& rhs);
+
+  /**
+   * @brief Copy operator
+   */
+  PlatformPositionData& operator=(const PlatformPositionData& rhs);
+  /**
+   * @brief This function writes the PlatformPositionData in a stream
+   */
+  friend std::ostream& operator<<(std::ostream& os, const PlatformPositionData& data);
+
+  /**
+   * @brief This function reads a PlatformPositionData from a stream
+   */
+  friend std::istream& operator>>(std::istream& is, PlatformPositionData& data);
+
+  /**
+   * @brief This function is able to create a new instance of the class
+   */
+  RadarSatRecord* Instanciate()
+  {
+    return new PlatformPositionData();
+  };
+
+  /**
+   * @brief This function is able to create a new instance of the class initialised with the data of the calling instance
+   */
+  RadarSatRecord* Clone()
+  {
+    return new PlatformPositionData(*this);
+  };
+
+  /**
+   * @brief Reads the class data from a stream
+   */
+  void Read(std::istream& is)
+  {
+    is>>*this;
+  };
+
+  /**
+   * @brief Writes the class to a stream
+   */
+  void Write(std::ostream& os)
+  {
+    os<<*this;
+  };
+
+  /**
+   * @brief Orbital elements designator
+   */
+  std::string   get_orbit_ele_desg()
+  {
+    return _orbit_ele_desg;
+  };
+    /**
+   * @brief Orbital elements
+   */
+  double*   get_orbit_ele()
+  {
+    return _orbit_ele;
+  };
+    /**
+   * @brief Number of data points
+   */
+  int  get_ndata()
+  {
+    return _ndata;
+  };
+    /**
+   * @brief Year of data point
+   */
+  int   get_year()
+  {
+    return _year;
+  };
+    /**
+   * @brief Month of data point
+   */
+  int   get_month()
+  {
+    return _month;
+  };
+    /**
+   * @brief Day of data point
+   */
+  int   get_day()
+  {
+    return _day;
+  };
+    /**
+   * @brief Day of year
+   */
+  int   get_gmt_day()
+  {
+    return _gmt_day;
+  };
+    /**
+   * @brief Seconds of day
+   */
+  double   get_gmt_sec()
+  {
+    return _gmt_sec;
+  };
+    /**
+   * @brief Data sampling interval
+   */
+  double   get_data_int()
+  {
+    return _data_int;
+  };
+    /**
+   * @brief Reference coordinate system
+   */
+  std::string   get_ref_coord()
+  {
+    return _ref_coord;
+  };
+    /**
+   * @brief Greenwich mean hour angle
+   */
+  double   get_hr_angle()
+  {
+    return _hr_angle;
+  };
+    /**
+   * @brief Along track position error
+   */
+  double   get_alt_poserr()
+  {
+    return _alt_poserr;
+  };
+    /**
+   * @brief Cross track position error
+   */
+  double   get_crt_poserr()
+  {
+    return _crt_poserr;
+  };
+    /**
+   * @brief Radial position error
+   */
+  double   get_rad_poserr()
+  {
+    return _rad_poserr;
+  };
+    /**
+   * @brief Along track velocity error
+   */
+  double   get_alt_velerr()
+  {
+    return _alt_velerr;
+  };
+    /**
+   * @brief Cross track velocity error
+   */
+  double  get_crt_velerr()
+  {
+    return _crt_velerr;
+  };
+    /**
+   * @brief Radial velocity error
+   */
+  double  get_rad_velerr()
+  {
+    return _rad_velerr;
+  };
+    /**
+   * @brief Data point position/velocity
+   */
+  PositionVectorRecord* get_pos_vect()
+  {
+    return _pos_vect;
+  };
+
+protected:
+  /**
+   * @brief Orbital elements designator
+   */
+  std::string   _orbit_ele_desg;
+    /**
+   * @brief Orbital elements
+   */
+  double   _orbit_ele[6];
+    /**
+   * @brief Number of data points
+   */
+  int   _ndata;
+    /**
+   * @brief Year of data point
+   */
+  int   _year;
+    /**
+   * @brief Month of data point
+   */
+  int   _month;
+    /**
+   * @brief Day of data point
+   */
+  int   _day;
+    /**
+   * @brief Day of year
+   */
+  int   _gmt_day;
+    /**
+   * @brief Seconds of day
+   */
+  double   _gmt_sec;
+    /**
+   * @brief Data sampling interval
+   */
+  double   _data_int;
+    /**
+   * @brief Reference coordinate system
+   */
+  std::string   _ref_coord;
+    /**
+   * @brief Greenwich mean hour angle
+   */
+  double   _hr_angle;
+    /**
+   * @brief Along track position error
+   */
+  double   _alt_poserr;
+    /**
+   * @brief Cross track position error
+   */
+  double   _crt_poserr;
+    /**
+   * @brief Radial position error
+   */
+  double   _rad_poserr;
+    /**
+   * @brief Along track velocity error
+   */
+  double   _alt_velerr;
+    /**
+   * @brief Cross track velocity error
+   */
+  double   _crt_velerr;
+    /**
+   * @brief Radial velocity error
+   */
+  double   _rad_velerr;
+    /**
+   * @brief Data point position/velocity
+   */
+  PositionVectorRecord _pos_vect[64];
+
+private:
+};
+}
+#endif
+
diff --git a/ossim_plugins/ossim/RadarSat/Leader/PositionVectorRecord.cpp b/ossim_plugins/ossim/RadarSat/Leader/PositionVectorRecord.cpp
new file mode 100644
index 0000000..c00b62f
--- /dev/null
+++ b/ossim_plugins/ossim/RadarSat/Leader/PositionVectorRecord.cpp
@@ -0,0 +1,84 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include <RadarSat/Leader/PositionVectorRecord.h>
+
+namespace ossimplugins
+{
+PositionVectorRecord::PositionVectorRecord()
+{
+}
+
+PositionVectorRecord::~PositionVectorRecord()
+{
+}
+
+std::ostream& operator<<(std::ostream& os, const PositionVectorRecord& data)
+{
+	for (int i=0;i<3;i++)
+	{
+		os<<"pos["<<i<<"]:"<<data._pos[i]<<std::endl;
+	}
+
+	for (int i=0;i<3;i++)
+	{
+		os<<"vel["<<i<<"]:"<<data._vel[i]<<std::endl;
+	}
+	return os;
+}
+
+std::istream& operator>>(std::istream& is, PositionVectorRecord& data)
+{
+	char buf[23];
+	buf[22] = '\0';
+
+	for (int i=0;i<3;i++)
+	{
+		is.read(buf,22);
+		data._pos[i] = atof(buf);
+	}
+
+	for (int i=0;i<3;i++)
+	{
+		is.read(buf,22);
+		data._vel[i] = atof(buf);
+	}
+	return is;
+}
+
+PositionVectorRecord::PositionVectorRecord(const PositionVectorRecord& rhs)
+{
+	for (int i=0;i<3;i++)
+	{
+		_pos[i] = rhs._pos[i];
+	}
+
+	for (int i=0;i<3;i++)
+	{
+		_vel[i] = rhs._vel[i];
+	}
+}
+
+PositionVectorRecord& PositionVectorRecord::operator=(const PositionVectorRecord& rhs)
+{
+	for (int i=0;i<3;i++)
+	{
+		_pos[i] = rhs._pos[i];
+	}
+
+	for (int i=0;i<3;i++)
+	{
+		_vel[i] = rhs._vel[i];
+	}
+	return *this;
+}
+}
+
diff --git a/ossim_plugins/ossim/RadarSat/Leader/PositionVectorRecord.h b/ossim_plugins/ossim/RadarSat/Leader/PositionVectorRecord.h
new file mode 100644
index 0000000..a44e85e
--- /dev/null
+++ b/ossim_plugins/ossim/RadarSat/Leader/PositionVectorRecord.h
@@ -0,0 +1,86 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef PositionVectorRecord_h
+#define PositionVectorRecord_h
+
+#include <iostream>
+#include <RadarSat/RadarSatRecord.h>
+
+namespace ossimplugins
+{
+/**
+ * @ingroup PlatformPositionDataRecord
+ * @brief This class is able to read a position vector record
+ */
+class PositionVectorRecord
+{
+public:
+  /**
+   * @brief Constructor
+   */
+  PositionVectorRecord();
+
+  /**
+   * @brief Destructor
+   */
+  ~PositionVectorRecord();
+
+  /**
+   * @brief Copy constructor
+   */
+  PositionVectorRecord(const PositionVectorRecord& rhs);
+
+  /**
+   * @brief Copy operator
+   */
+  PositionVectorRecord& operator=(const PositionVectorRecord& rhs);
+  /**
+   * @brief This function writes the PositionVectorRecord in a stream
+   */
+  friend std::ostream& operator<<(std::ostream& os, const PositionVectorRecord& data);
+
+  /**
+   * @brief This function reads a PositionVectorRecord from a stream
+   */
+  friend std::istream& operator>>(std::istream& is, PositionVectorRecord& data);
+
+  /**
+   * @brief Data point position (m)
+   */
+  double* get_pos()
+  {
+    return _pos;
+  };
+
+  /**
+   * @brief Data point velocity (mm/s)
+   */
+  double* get_vel()
+  {
+    return _vel;
+  };
+
+protected:
+  /**
+   * @brief Data point position (m)
+   */
+  double _pos[3];
+  /**
+   * @brief Data point velocity (mm/s)
+   */
+  double _vel[3];
+private:
+
+};
+}
+#endif
+
diff --git a/ossim_plugins/ossim/RadarSat/RadarSatRecord.cpp b/ossim_plugins/ossim/RadarSat/RadarSatRecord.cpp
new file mode 100644
index 0000000..8195c5d
--- /dev/null
+++ b/ossim_plugins/ossim/RadarSat/RadarSatRecord.cpp
@@ -0,0 +1,31 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include <RadarSat/RadarSatRecord.h>
+#include <memory.h>
+
+namespace ossimplugins
+{
+RadarSatRecord::RadarSatRecord(std::string mnemonic):
+	_mnemonic(mnemonic)
+{
+}
+
+RadarSatRecord::~RadarSatRecord()
+{
+}
+
+RadarSatRecord::RadarSatRecord(const RadarSatRecord& rhs):
+	_mnemonic(rhs._mnemonic)
+{
+}
+}
+
diff --git a/ossim_plugins/ossim/RadarSat/RadarSatRecord.h b/ossim_plugins/ossim/RadarSat/RadarSatRecord.h
new file mode 100644
index 0000000..17f5ba5
--- /dev/null
+++ b/ossim_plugins/ossim/RadarSat/RadarSatRecord.h
@@ -0,0 +1,77 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef RadarSatRecord_h
+#define RadarSatRecord_h
+
+
+#include <RadarSat/RadarSatRecordHeader.h>
+#include <iostream>
+#include <cstdlib>
+
+namespace ossimplugins
+{
+/**
+ * @ingroup RadarSat
+ * @brief This class is the base class of all the record classes
+ */
+class RadarSatRecord
+{
+public:
+  /**
+   * @brief Constructor
+   * @param mnemonic Name of the record
+   */
+  RadarSatRecord(std::string mnemonic);
+  /**
+   * @brief Destructor
+   */
+  virtual ~RadarSatRecord();
+
+  /**
+   * @brief Copy constructor
+   */
+  RadarSatRecord(const RadarSatRecord& rhs);
+
+  /**
+   * @brief This function is able to create a new instance of the class
+   */
+  virtual RadarSatRecord* Instanciate() =0;
+
+  /**
+   * @brief This function is able to create a new instance of the class initialised with the data of the calling instance
+   */
+  virtual RadarSatRecord* Clone()=0;
+
+  /**
+   * @brief Reads the class data from a stream
+   */
+  virtual void Read(std::istream& is) =0;
+
+  /**
+   * @brief Writes the class to a stream
+   */
+  virtual void Write(std::ostream& os)=0;
+
+  std::string get_mnemonic()
+  {
+    return _mnemonic;
+  };
+
+protected:
+
+  std::string _mnemonic;
+
+private:
+};
+}
+#endif
+
diff --git a/ossim_plugins/ossim/RadarSat/RadarSatRecordFactory.cpp b/ossim_plugins/ossim/RadarSat/RadarSatRecordFactory.cpp
new file mode 100644
index 0000000..6f67c55
--- /dev/null
+++ b/ossim_plugins/ossim/RadarSat/RadarSatRecordFactory.cpp
@@ -0,0 +1,42 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include <RadarSat/RadarSatRecordFactory.h>
+
+namespace ossimplugins
+{
+RadarSatRecordFactory::RadarSatRecordFactory()
+{
+}
+
+RadarSatRecordFactory::~RadarSatRecordFactory()
+{
+}
+
+RadarSatRecord* RadarSatRecordFactory::Instanciate(int id)
+{
+	RadarSatRecord* record = _availableRecords[id];
+	if(record == NULL)
+	{
+		return NULL;
+	}
+	else
+	{
+		return record->Instanciate();
+	}
+}
+
+void RadarSatRecordFactory::RegisterRecord(int id, RadarSatRecord * record)
+{
+	_availableRecords[id] = record;
+}
+}
+
diff --git a/ossim_plugins/ossim/RadarSat/RadarSatRecordFactory.h b/ossim_plugins/ossim/RadarSat/RadarSatRecordFactory.h
new file mode 100644
index 0000000..7169a8d
--- /dev/null
+++ b/ossim_plugins/ossim/RadarSat/RadarSatRecordFactory.h
@@ -0,0 +1,61 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef RadarSatRecordFactory_h
+#define RadarSatRecordFactory_h
+
+
+#include <RadarSat/RadarSatRecordHeader.h>
+#include <RadarSat/RadarSatRecord.h>
+#include <map>
+
+namespace ossimplugins
+{
+/**
+ * @ingroup RadarSat
+ * @brief This class is a factory able to construct Record base classes given the id of the wanted record
+ */
+class RadarSatRecordFactory
+{
+public:
+  /**
+   * @brief Constructor
+   */
+  RadarSatRecordFactory();
+  /**
+   * @brief Destructor
+   */
+  ~RadarSatRecordFactory();
+
+  /**
+   * @brief Add a new Record type available in this factory
+   * @param record Record to add in the factory
+   * @param id Id of the new available Record
+   */
+  void RegisterRecord(int id, RadarSatRecord * record);
+
+  /**
+   * @brief Instanciates a new Record
+   * @param id Id of the Record we want to instanciate
+   */
+  RadarSatRecord* Instanciate(int id) ;
+protected:
+
+  /**
+   * @brief Contains all the available Records for the factory
+   */
+  std::map<int, RadarSatRecord*> _availableRecords;
+
+private:
+};
+}
+#endif
+
diff --git a/ossim_plugins/ossim/RadarSat/RadarSatRecordHeader.cpp b/ossim_plugins/ossim/RadarSat/RadarSatRecordHeader.cpp
new file mode 100644
index 0000000..ecd5fb1
--- /dev/null
+++ b/ossim_plugins/ossim/RadarSat/RadarSatRecordHeader.cpp
@@ -0,0 +1,81 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include <RadarSat/RadarSatRecordHeader.h>
+
+namespace ossimplugins
+{
+RadarSatRecordHeader::RadarSatRecordHeader()
+{
+}
+
+RadarSatRecordHeader::~RadarSatRecordHeader()
+{
+}
+
+std::ostream& operator<<(std::ostream& os, const RadarSatRecordHeader& data)
+{
+	os<<"record_sequence_number:"<<data._rec_seq<<std::endl;
+	os<<"first_record_sub-type:"<<(int)data._rec_sub1<<std::endl;
+	os<<"record_type_code:"<<(int)data._rec_type<<std::endl;
+	os<<"second_record_sub-type:"<<(int)data._rec_sub2<<std::endl;
+	os<<"third_record_sub-type:"<<(int)data._rec_sub3<<std::endl;
+	os<<"length:"<<data._length<<std::endl;
+	return os;
+}
+
+std::istream& operator>>(std::istream& is, RadarSatRecordHeader& data)
+{
+	is.read((char*)&(data._rec_seq),4);
+	data.SwitchEndian(data._rec_seq);
+	is.read((char*)&(data._rec_sub1),1);
+	is.read((char*)&(data._rec_type),1);
+	is.read((char*)&(data._rec_sub2),1);
+	is.read((char*)&(data._rec_sub3),1);
+	is.read((char*)&(data._length),4);
+	data.SwitchEndian(data._length);
+	return is;
+}
+
+RadarSatRecordHeader::RadarSatRecordHeader(const RadarSatRecordHeader& rhs):
+	_rec_seq(rhs._rec_seq),
+	_rec_sub1(rhs._rec_sub1),
+	_rec_type(rhs._rec_type),
+	_rec_sub2(rhs._rec_sub2),
+	_rec_sub3(rhs._rec_sub3)
+{
+}
+
+RadarSatRecordHeader& RadarSatRecordHeader::operator=(const RadarSatRecordHeader& rhs)
+{
+	_rec_seq=rhs._rec_seq;
+	_rec_sub1=rhs._rec_sub1;
+	_rec_type=rhs._rec_type;
+	_rec_sub2=rhs._rec_sub2;
+	_rec_sub3=rhs._rec_sub3;
+	return *this;
+}
+
+void RadarSatRecordHeader::SwitchEndian(int& value)
+{
+	char buffer[4];
+	char res[4];
+
+	memcpy(buffer,&value,4);
+	res[0] = buffer[3];
+	res[1] = buffer[2];
+	res[2] = buffer[1];
+	res[3] = buffer[0];
+
+	memcpy(&value,res,4);
+}
+}
+
diff --git a/ossim_plugins/ossim/RadarSat/RadarSatRecordHeader.h b/ossim_plugins/ossim/RadarSat/RadarSatRecordHeader.h
new file mode 100644
index 0000000..45a4cc0
--- /dev/null
+++ b/ossim_plugins/ossim/RadarSat/RadarSatRecordHeader.h
@@ -0,0 +1,140 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef RadarSatRecordHeader_h
+#define RadarSatRecordHeader_h
+
+#include<iostream>
+#include<cstring>
+
+namespace ossimplugins
+{
+/**
+ * @ingroup RadarSat
+ * @brief This class is able to read a record header
+ */
+class RadarSatRecordHeader
+{
+public:
+  /**
+   * @brief Constructor
+   */
+  RadarSatRecordHeader();
+
+  /**
+   * @brief Destructor
+   */
+  ~RadarSatRecordHeader();
+
+  /**
+   * @brief Copy constructor
+   */
+  RadarSatRecordHeader(const RadarSatRecordHeader& rhs);
+
+  /**
+   * @brief Copy operator
+   */
+  RadarSatRecordHeader& operator=(const RadarSatRecordHeader& rhs);
+  /**
+   * @brief This function writes the RecordHeader in a stream
+   */
+  friend std::ostream& operator<<(std::ostream& os, const RadarSatRecordHeader& data);
+
+  /**
+   * @brief This function reads a RecordHeader from a stream
+   */
+  friend std::istream& operator>>(std::istream& is, RadarSatRecordHeader& data);
+
+  /**
+   * @brief Record sequence number
+   */
+  int  get_rec_seq()
+  {
+    return _rec_seq;
+  };
+
+  /**
+   * @brief First record sub-type code
+   */
+    unsigned char   get_rec_sub1()
+  {
+    return _rec_sub1;
+  };
+
+  /**
+   * @brief Record type code
+   */
+    unsigned char   get_rec_type()
+  {
+    return _rec_type;
+  };
+
+  /**
+   * @brief Second record sub-type code
+   */
+    unsigned char   get_rec_sub2()
+  {
+    return _rec_sub2;
+  };
+
+  /**
+   * @brief Third record sub-type code
+   */
+    unsigned char   get_rec_sub3()
+  {
+    return _rec_sub3;
+  };
+
+  /**
+   * @brief Length of this record (in bytes)
+   */
+    int  get_length()
+  {
+    return _length;
+  };
+protected:
+
+  /**
+   * @brief This function switches the LSB value and the MSB value of the parameter
+   */
+  void SwitchEndian(int& value);
+
+  /**
+   * @brief Record sequence number
+   */
+  int  _rec_seq;
+  /**
+   * @brief First record sub-type code
+   */
+    unsigned char   _rec_sub1;
+  /**
+   * @brief Record type code
+   */
+    unsigned char   _rec_type;
+  /**
+   * @brief Second record sub-type code
+   */
+    unsigned char   _rec_sub2;
+  /**
+   * @brief Third record sub-type code
+   */
+    unsigned char   _rec_sub3;
+  /**
+   * @brief Length of this record (in bytes)
+   */
+    int  _length;
+private:
+
+
+};
+}
+#endif
+
diff --git a/ossim_plugins/ossim/RadarSat/Trailer/Trailer.cpp b/ossim_plugins/ossim/RadarSat/Trailer/Trailer.cpp
new file mode 100755
index 0000000..90d9c2b
--- /dev/null
+++ b/ossim_plugins/ossim/RadarSat/Trailer/Trailer.cpp
@@ -0,0 +1,173 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include <RadarSat/Trailer/Trailer.h>
+#include <RadarSat/Trailer/TrailerFactory.h>
+#include <RadarSat/RadarSatRecordHeader.h>
+
+#include <RadarSat/CommonRecord/DataHistogramSignalData.h>
+#include <RadarSat/CommonRecord/DataQuality.h>
+#include <RadarSat/CommonRecord/DataSetSummary.h>
+#include <RadarSat/CommonRecord/FileDescriptor.h>
+#include <RadarSat/CommonRecord/ProcessingParameters.h>
+#include <RadarSat/CommonRecord/AttitudeData.h>
+#include <RadarSat/CommonRecord/RadiometricData.h>
+#include <RadarSat/CommonRecord/RadiometricCompensationData.h>
+
+namespace ossimplugins
+{
+
+const int Trailer::RadiometricDataID = 8;
+const int Trailer::RadiometricCompensationDataID = 9;
+const int Trailer::AttitudeDataID = 7;
+const int Trailer::ProcessingParametersID = 6;
+const int Trailer::DataHistogramProcessedData8ID = 5;
+const int Trailer::DataHistogramSignalDataID = 4;
+const int Trailer::DataQualityID = 3;
+const int Trailer::DataSetSummaryID = 2;
+const int Trailer::FileDescriptorID = 1;
+
+Trailer::Trailer()
+{
+}
+
+Trailer::~Trailer()
+{
+  ClearRecords();
+}
+
+std::ostream& operator<<(std::ostream& os, const Trailer& data)
+{
+  std::map<int, RadarSatRecord*>::const_iterator it = data._records.begin();
+  while(it != data._records.end())
+  {
+    (*it).second->Write(os);
+    ++it;
+  }
+  return os;
+
+}
+
+std::istream& operator>>(std::istream& is, Trailer& data)
+{
+  TrailerFactory factory;
+
+  data.ClearRecords();
+
+  RadarSatRecordHeader header;
+  bool eof = false;
+  while(!eof)
+  {
+    is>>header;
+    if(is.eof())
+    {
+      eof = true;
+    }
+    else
+    {
+      RadarSatRecord* record = factory.Instanciate(header.get_rec_seq());
+      if (record != NULL)
+      {
+        record->Read(is);
+        data._records[header.get_rec_seq()] = record;
+      }
+      else
+      {
+        char* buff = new char[header.get_length()-12];
+        is.read(buff, header.get_length()-12);
+        delete[] buff;
+      }
+    }
+  }
+  return is;
+}
+
+
+Trailer::Trailer(const Trailer& rhs)
+{
+  std::map<int, RadarSatRecord*>::const_iterator it = rhs._records.begin();
+  while(it != rhs._records.end())
+  {
+    _records[(*it).first] = (*it).second->Clone();
+    ++it;
+  }
+}
+
+Trailer& Trailer::operator=(const Trailer& rhs)
+{
+  ClearRecords();
+  std::map<int, RadarSatRecord*>::const_iterator it = rhs._records.begin();
+  while(it != rhs._records.end())
+  {
+    _records[(*it).first] = (*it).second->Clone();
+    ++it;
+  }
+
+  return *this;
+}
+
+void Trailer::ClearRecords()
+{
+  std::map<int, RadarSatRecord*>::const_iterator it = _records.begin();
+  while(it != _records.end())
+  {
+    delete (*it).second;
+    ++it;
+  }
+  _records.clear();
+}
+
+RadiometricData * Trailer::get_RadiometricData()
+{
+  return (RadiometricData*)_records[RadiometricDataID];
+}
+
+RadiometricCompensationData * Trailer::get_RadiometricCompensationData()
+{
+  return (RadiometricCompensationData*)_records[RadiometricCompensationDataID];
+}
+
+AttitudeData * Trailer::get_AttitudeData()
+{
+  return (AttitudeData*)_records[AttitudeDataID];
+}
+
+ProcessingParameters * Trailer::get_ProcessingParameters()
+{
+  return (ProcessingParameters*)_records[ProcessingParametersID];
+}
+
+DataHistogramProcessedData8 * Trailer::get_DataHistogramProcessedData8()
+{
+  return (DataHistogramProcessedData8*)_records[DataHistogramProcessedData8ID];
+}
+
+DataHistogramSignalData * Trailer::get_DataHistogramSignalData()
+{
+  return (DataHistogramSignalData*)_records[DataHistogramSignalDataID];
+}
+
+DataQuality * Trailer::get_DataQuality()
+{
+  return (DataQuality*)_records[DataQualityID];
+}
+
+DataSetSummary * Trailer::get_DataSetSummary()
+{
+  return (DataSetSummary*)_records[DataSetSummaryID];
+}
+
+FileDescriptor * Trailer::get_FileDescriptor()
+{
+  return (FileDescriptor*)_records[FileDescriptorID];
+}
+}
+
diff --git a/ossim_plugins/ossim/RadarSat/Trailer/Trailer.h b/ossim_plugins/ossim/RadarSat/Trailer/Trailer.h
new file mode 100755
index 0000000..81a6f8f
--- /dev/null
+++ b/ossim_plugins/ossim/RadarSat/Trailer/Trailer.h
@@ -0,0 +1,104 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef Trailer_h
+#define Trailer_h
+
+#include <iostream>
+#include <RadarSat/CommonRecord/FileDescriptor.h>
+#include <RadarSat/CommonRecord/DataSetSummary.h>
+#include <RadarSat/CommonRecord/DataQuality.h>
+#include <RadarSat/CommonRecord/DataHistogramSignalData.h>
+#include <map>
+
+namespace ossimplugins
+{
+class RadiometricData;
+class RadiometricCompensationData;
+class AttitudeData;
+class ProcessingParameters;
+class DataHistogramSignalData;
+class DataQuality;
+class DataSetSummary;
+class FileDescriptor;
+
+/**
+ * @ingroup TrailerFile
+ * @brief This class is able to read the trailer file of the RadarSat file structure
+ * @author CS, Mickaël Savinaud
+ * @version 1.0
+ * @date 25-02-2011
+ */
+class Trailer
+{
+public:
+  /**
+   * @brief Constructor
+   */
+  Trailer();
+
+  /**
+   * @brief Destructor
+   */
+  ~Trailer();
+
+  /**
+   * @brief This function writes the Trailer in a stream
+   */
+  friend std::ostream& operator<<(std::ostream& os, const Trailer& data);
+
+  /**
+   * @brief This function reads a Trailer from a stream
+   */
+  friend std::istream& operator>>(std::istream& is, Trailer& data);
+
+  /**
+   * @brief Copy constructor
+   */
+  Trailer(const Trailer& rhs);
+
+  /**
+   * @brief Copy operator
+   */
+  Trailer& operator=(const Trailer& rhs);
+
+  /**
+   * @brief Removes all the previous records from the Trailer
+   */
+  void ClearRecords();
+
+  RadiometricData * get_RadiometricData();
+  RadiometricCompensationData * get_RadiometricCompensationData();
+  AttitudeData * get_AttitudeData();
+  ProcessingParameters * get_ProcessingParameters();
+  DataHistogramProcessedData8 * get_DataHistogramProcessedData8();
+  DataHistogramSignalData * get_DataHistogramSignalData();
+  DataQuality * get_DataQuality();
+  DataSetSummary * get_DataSetSummary();
+  FileDescriptor * get_FileDescriptor();
+protected:
+  std::map<int, RadarSatRecord*> _records;
+
+  static const int RadiometricDataID;
+  static const int RadiometricCompensationDataID;
+  static const int AttitudeDataID;
+  static const int ProcessingParametersID;
+  static const int DataHistogramProcessedData8ID;
+  static const int DataHistogramSignalDataID;
+  static const int DataQualityID;
+  static const int DataSetSummaryID;
+  static const int FileDescriptorID;
+private:
+
+};
+}
+#endif
+
diff --git a/ossim_plugins/ossim/RadarSat/Trailer/TrailerFactory.cpp b/ossim_plugins/ossim/RadarSat/Trailer/TrailerFactory.cpp
new file mode 100755
index 0000000..28029b7
--- /dev/null
+++ b/ossim_plugins/ossim/RadarSat/Trailer/TrailerFactory.cpp
@@ -0,0 +1,57 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include <RadarSat/Trailer/TrailerFactory.h>
+
+#include <RadarSat/CommonRecord/DataHistogramSignalData.h>
+#include <RadarSat/CommonRecord/DataQuality.h>
+#include <RadarSat/CommonRecord/DataSetSummary.h>
+#include <RadarSat/CommonRecord/FileDescriptor.h>
+#include <RadarSat/Leader/DataHistogramProcessedData.h>
+#include <RadarSat/CommonRecord/ProcessingParameters.h>
+#include <RadarSat/CommonRecord/AttitudeData.h>
+#include <RadarSat/CommonRecord/RadiometricData.h>
+#include <RadarSat/CommonRecord/RadiometricCompensationData.h>
+
+namespace ossimplugins
+{
+TrailerFactory::TrailerFactory()
+{
+  RegisterRecord(8, new RadiometricData());
+  RegisterRecord(9, new RadiometricCompensationData());
+  RegisterRecord(7, new AttitudeData());
+  RegisterRecord(6, new ProcessingParameters());
+  RegisterRecord(5, new DataHistogramProcessedData8());
+  RegisterRecord(4, new DataHistogramSignalData());
+  RegisterRecord(3, new DataQuality());
+  RegisterRecord(2, new DataSetSummary());
+  RegisterRecord(1, new FileDescriptor());
+}
+
+TrailerFactory::~TrailerFactory()
+{
+
+  std::map<int, RadarSatRecord*>::iterator i = _availableRecords.begin();
+
+  while (i != _availableRecords.end())
+  {
+     if ( (*i).second )
+     {
+        delete (*i).second;
+        (*i).second = 0;
+     }
+     ++i;
+  }
+  _availableRecords.clear();
+
+}
+}
+
diff --git a/ossim_plugins/ossim/RadarSat/Trailer/TrailerFactory.h b/ossim_plugins/ossim/RadarSat/Trailer/TrailerFactory.h
new file mode 100755
index 0000000..52c1237
--- /dev/null
+++ b/ossim_plugins/ossim/RadarSat/Trailer/TrailerFactory.h
@@ -0,0 +1,45 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef TrailerFactory_h
+#define TrailerFactory_h
+
+
+#include <RadarSat/RadarSatRecordFactory.h>
+#include <map>
+
+namespace ossimplugins
+{
+/**
+ * @ingroup TrailerFile
+ * @brief This class is a factory able to construct Record base classes
+ */
+class TrailerFactory : public RadarSatRecordFactory
+{
+public:
+  /**
+   * @brief Contstructor
+   */
+  TrailerFactory();
+  /**
+   * @brief Destructor
+   */
+  ~TrailerFactory();
+
+
+protected:
+
+
+private:
+};
+}
+#endif
+
diff --git a/ossim_plugins/ossim/RadarSat/VolumeDir/FilePointerRecord.cpp b/ossim_plugins/ossim/RadarSat/VolumeDir/FilePointerRecord.cpp
new file mode 100755
index 0000000..f10888c
--- /dev/null
+++ b/ossim_plugins/ossim/RadarSat/VolumeDir/FilePointerRecord.cpp
@@ -0,0 +1,164 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include "FilePointerRecord.h"
+
+namespace ossimplugins
+{
+FilePointerRecord::FilePointerRecord() : RadarSatRecord("file_pntr_rec")
+{
+}
+
+FilePointerRecord::~FilePointerRecord()
+{
+}
+
+std::ostream& operator<<(std::ostream& os, const FilePointerRecord& data)
+{
+  os<<"ascii_flag:"<<data._ascii_flag.c_str()<<std::endl;
+  os<<"file_num:"<<data._file_num<<std::endl;
+  os<<"file_name:"<<data._file_name.c_str()<<std::endl;
+  os<<"file_class:"<<data._file_class.c_str()<<std::endl;
+  os<<"file_code:"<<data._file_code.c_str()<<std::endl;
+  os<<"data_type:"<<data._data_type.c_str()<<std::endl;
+  os<<"data_code:"<<data._data_code.c_str()<<std::endl;
+  os<<"nrec:"<<data._nrec<<std::endl;
+  os<<"first_len:"<<data._first_len<<std::endl;
+  os<<"max_len:"<<data._max_len<<std::endl;
+  os<<"len_type:"<<data._len_type.c_str()<<std::endl;
+  os<<"len_code:"<<data._len_code.c_str()<<std::endl;
+  os<<"first_phyvol:"<<data._first_phyvol<<std::endl;
+  os<<"last_phyvol:"<<data._last_phyvol<<std::endl;
+  os<<"first_rec:"<<data._first_rec<<std::endl;
+  os<<"last_rec:"<<data._last_rec<<std::endl;
+  return os;
+}
+
+std::istream& operator>>(std::istream& is, FilePointerRecord& data)
+{
+  char buf[349]; // 361-12 (size of header)
+  buf[348] = '\0';
+
+  is.read(buf, 2);
+  buf[2] = '\0';
+  data._ascii_flag = buf;
+
+  is.read(buf, 2); // spare1
+
+  is.read(buf, 4);
+  buf[4] = '\0';
+  data._file_num = atoi(buf);
+
+  is.read(buf, 16);
+  buf[16] = '\0';
+  data._file_name = buf;
+
+  is.read(buf, 28);
+  buf[28] = '\0';
+  data._file_class = buf;
+
+  is.read(buf, 4);
+  buf[4] = '\0';
+  data._file_code = buf;
+
+  is.read(buf, 28);
+  buf[28] = '\0';
+  data._data_type = buf;
+
+  is.read(buf, 4);
+  buf[4] = '\0';
+  data._data_code = buf;
+
+  is.read(buf, 8);
+  buf[8] = '\0';
+  data._nrec = atoi(buf);
+
+  is.read(buf, 8);
+  buf[8] = '\0';
+  data._first_len = atoi(buf);
+
+  is.read(buf, 8);
+  buf[8] = '\0';
+  data._max_len = atoi(buf);
+
+  is.read(buf, 12);
+  buf[12] = '\0';
+  data._len_type = buf;
+
+  is.read(buf, 4);
+  buf[4] = '\0';
+  data._len_code = buf;
+
+  is.read(buf, 2);
+  buf[2] = '\0';
+  data._first_phyvol = atoi(buf);
+
+  is.read(buf, 2);
+  buf[2] = '\0';
+  data._last_phyvol = atoi(buf);
+
+  is.read(buf, 8);
+  buf[8] = '\0';
+  data._first_rec = atoi(buf);
+
+  is.read(buf, 8);
+  buf[8] = '\0';
+  data._last_rec = atoi(buf);
+
+  is.read(buf, 100); // spare2
+
+  is.read(buf, 100); // spare3
+  return is;
+}
+
+FilePointerRecord::FilePointerRecord(const FilePointerRecord& rhs):
+  RadarSatRecord(rhs),
+  _ascii_flag(rhs._ascii_flag),
+  _file_num(rhs._file_num),
+  _file_name(rhs._file_name),
+  _file_class(rhs._file_class),
+  _file_code(rhs._file_code),
+  _data_type(rhs._data_type),
+  _data_code(rhs._data_code),
+  _nrec(rhs._nrec),
+  _first_len(rhs._first_len),
+  _max_len(rhs._max_len),
+  _len_type(rhs._len_type),
+  _len_code(rhs._len_code),
+  _first_phyvol(rhs._first_phyvol),
+  _last_phyvol(rhs._last_phyvol),
+  _first_rec(rhs._first_rec),
+  _last_rec(rhs._last_rec)
+{
+}
+
+FilePointerRecord& FilePointerRecord::operator=(const FilePointerRecord& rhs)
+{
+  _ascii_flag = rhs._ascii_flag;
+  _file_num = rhs._file_num;
+  _file_name = rhs._file_name;
+  _file_class = rhs._file_class;
+  _file_code = rhs._file_code;
+  _data_type = rhs._data_type;
+  _data_code = rhs._data_code;
+  _nrec = rhs._nrec;
+  _first_len = rhs._first_len;
+  _max_len = rhs._max_len;
+  _len_type = rhs._len_type;
+  _len_code = rhs._len_code;
+  _first_phyvol = rhs._first_phyvol;
+  _last_phyvol = rhs._last_phyvol;
+  _first_rec = rhs._first_rec;
+  _last_rec = rhs._last_rec;
+  return *this;
+}
+}
+
diff --git a/ossim_plugins/ossim/RadarSat/VolumeDir/FilePointerRecord.h b/ossim_plugins/ossim/RadarSat/VolumeDir/FilePointerRecord.h
new file mode 100755
index 0000000..950e57a
--- /dev/null
+++ b/ossim_plugins/ossim/RadarSat/VolumeDir/FilePointerRecord.h
@@ -0,0 +1,306 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef FilePointerRecord_h
+#define FilePointerRecord_h
+
+
+#include<iostream>
+#include <RadarSat/RadarSatRecordHeader.h>
+#include <RadarSat/RadarSatRecord.h>
+
+namespace ossimplugins
+{
+/**
+ * @ingroup SARLeaderFilePointerRecordRecord
+ * @brief This class is able to read the SAR leader file descriptor record of the leader file
+ */
+class FilePointerRecord : public RadarSatRecord
+{
+public:
+  /**
+   * @brief Constructor
+   */
+  FilePointerRecord();
+  /**
+   * @brief Destructor
+   */
+  virtual ~FilePointerRecord();
+
+  /**
+   * @brief This function writes the FilePointerRecord in a stream
+   */
+  friend std::ostream& operator<<(std::ostream& os, const FilePointerRecord& data);
+
+  /**
+   * @brief This function reads a FilePointerRecord from a stream
+   */
+  friend std::istream& operator>>(std::istream& is, FilePointerRecord& data);
+
+  /**
+   * @brief Copy constructor
+   */
+  FilePointerRecord(const FilePointerRecord& rhs);
+
+  /**
+   * @brief Copy operator
+   */
+  FilePointerRecord& operator=(const FilePointerRecord& rhs);
+
+  /**
+   * @brief This function is able to create a new instance of the class
+   */
+  RadarSatRecord* Instanciate()
+  {
+    return new FilePointerRecord();
+  };
+
+  /**
+   * @brief This function is able to create a new instance of the class initialised with the data of the calling instance
+   */
+  RadarSatRecord* Clone()
+  {
+    return new FilePointerRecord(*this);
+  };
+
+  /**
+   * @brief Reads the class data from a stream
+   */
+  void Read(std::istream& is)
+  {
+    is>>*this;
+  };
+
+  /**
+   * @brief Writes the class to a stream
+   */
+  void Write(std::ostream& os)
+  {
+    os<<*this;
+  };
+
+  /**
+   * @brief ASCII flag
+   */
+  std::string get_ascii_flag()
+  {
+    return _ascii_flag;
+  };
+
+  /**
+   * @brief Referenced file number
+   */
+  int get_file_num()
+  {
+    return _file_num;
+  };
+
+  /**
+   * @brief   Referenced file name
+   */
+  std::string get_file_name()
+  {
+    return _file_name;
+  };
+
+  /**
+   * @brief   Referenced file class
+   */
+  std::string get_file_class()
+  {
+    return _file_class;
+  };
+
+  /**
+   * @brief   Referenced file class code
+   */
+  std::string get_file_code()
+  {
+    return _file_code;
+  };
+
+  /**
+   * @brief   Referenced file data type
+   */
+  std::string get_data_type()
+  {
+    return _data_type;
+  };
+
+  /**
+   * @brief   Referenced file data type code
+   */
+  std::string get_data_code()
+  {
+    return _data_code;
+  };
+
+  /**
+   * @brief   Referenced file record count
+   */
+  int get_nrec()
+  {
+    return _nrec;
+  };
+
+  /**
+   * @brief  First record length, bytes
+   */
+  int get_first_len()
+  {
+    return _first_len;
+  };
+
+  /**
+   * @brief   Maximum record length, bytes
+   */
+  int get_max_len()
+  {
+    return _max_len;
+  };
+
+  /**
+   * @brief   Record length type
+   */
+  std::string get_len_type()
+  {
+    return _len_type;
+  };
+
+  /**
+   * @brief   Record length type code
+   */
+  std::string get_len_code()
+  {
+    return _len_code;
+  };
+
+  /**
+   * @brief   First physical volume
+   */
+  int get_first_phyvol()
+  {
+    return _first_phyvol;
+  };
+
+  /**
+   * @brief   Last physical volume
+   */
+  int get_last_phyvol()
+  {
+    return _last_phyvol;
+  };
+
+  /**
+   * @brief   First physical volume record
+   */
+  int get_first_rec()
+  {
+    return _first_rec;
+  };
+
+  /**
+   * @brief   Last physical volume record
+   */
+  int get_last_rec()
+  {
+    return _last_rec;
+  };
+
+protected:
+  /**
+   * @brief ASCII flag
+   */
+  std::string _ascii_flag;
+
+  /**
+   * @brief Referenced file number
+   */
+  int _file_num;
+
+  /**
+   * @brief   Referenced file name
+   */
+  std::string _file_name;
+
+  /**
+   * @brief   Referenced file class
+   */
+  std::string _file_class;
+
+  /**
+   * @brief   Referenced file class code
+   */
+  std::string _file_code;
+
+  /**
+   * @brief   Referenced file data type
+   */
+  std::string _data_type;
+
+  /**
+   * @brief   Referenced file data type code
+   */
+  std::string _data_code;
+
+  /**
+   * @brief   Referenced file record count
+   */
+  int _nrec;
+
+  /**
+   * @brief  First record length, bytes
+   */
+  int _first_len;
+
+  /**
+   * @brief   Maximum record length, bytes
+   */
+  int _max_len;
+
+  /**
+   * @brief   Record length type
+   */
+  std::string _len_type;
+
+  /**
+   * @brief   Record length type code
+   */
+  std::string _len_code;
+
+  /**
+   * @brief   First physical volume
+   */
+  int _first_phyvol;
+
+  /**
+   * @brief   Last physical volume
+   */
+  int _last_phyvol;
+
+  /**
+   * @brief   First physical volume record
+   */
+  int _first_rec;
+
+  /**
+   * @brief   Last physical volume record
+   */
+  int _last_rec;
+
+private:
+};
+typedef FilePointerRecord SARLeaderFilePointerRecord;
+typedef FilePointerRecord ImageOptionsFilePointerRecord;
+typedef FilePointerRecord SARTrailerFilePointerRecord;
+}
+#endif
+
diff --git a/ossim_plugins/ossim/RadarSat/VolumeDir/TextRecord.cpp b/ossim_plugins/ossim/RadarSat/VolumeDir/TextRecord.cpp
new file mode 100755
index 0000000..1446930
--- /dev/null
+++ b/ossim_plugins/ossim/RadarSat/VolumeDir/TextRecord.cpp
@@ -0,0 +1,105 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include "TextRecord.h"
+
+namespace ossimplugins
+{
+TextRecord::TextRecord() : RadarSatRecord("text_rec")
+{
+}
+
+TextRecord::~TextRecord()
+{
+}
+
+std::ostream& operator<<(std::ostream& os, const TextRecord& data)
+{
+  os<<"ascii_flag:"<<data._ascii_flag.c_str()<<std::endl;
+  os<<"cont_flag:"<<data._cont_flag.c_str()<<std::endl;
+  os<<"product_type:"<<data._product_type.c_str()<<std::endl;
+  os<<"product_create:"<<data._product_create.c_str()<<std::endl;
+  os<<"phyvol_id:"<<data._phyvol_id.c_str()<<std::endl;
+  os<<"scene_id:"<<data._scene_id.c_str()<<std::endl;
+  os<<"scene_loc:"<<data._scene_loc.c_str()<<std::endl;
+  os<<"copyright_info:"<<data._copyright_info.c_str()<<std::endl;
+  return os;
+}
+
+std::istream& operator>>(std::istream& is, TextRecord& data)
+{
+  char buf[349]; // 361-12
+  buf[348] = '\0';
+
+  is.read(buf, 2);
+  buf[2] = '\0';
+  data._ascii_flag = buf;
+
+  is.read(buf, 2);
+  buf[2] = '\0';
+  data._cont_flag = buf;
+
+  is.read(buf, 40);
+  buf[40] = '\0';
+  data._product_type = buf;
+
+  is.read(buf, 60);
+  buf[60] = '\0';
+  data._product_create = buf;
+
+  is.read(buf, 40);
+  buf[40] = '\0';
+  data._phyvol_id = buf;
+
+  is.read(buf, 40);
+  buf[40] = '\0';
+  data._scene_id = buf;
+
+  is.read(buf, 40);
+  buf[40] = '\0';
+  data._scene_loc = buf;
+
+  is.read(buf, 20);
+  buf[20] = '\0';
+  data._copyright_info = buf;
+
+  is.read(buf, 104); // spare1
+
+  return is;
+}
+
+TextRecord::TextRecord(const TextRecord& rhs):
+  RadarSatRecord(rhs),
+  _ascii_flag(rhs._ascii_flag),
+  _cont_flag(rhs._cont_flag),
+  _product_type(rhs._product_type),
+  _product_create(rhs._product_create),
+  _phyvol_id(rhs._phyvol_id),
+  _scene_id(rhs._scene_id),
+  _scene_loc(rhs._scene_loc),
+  _copyright_info(rhs._copyright_info)
+{
+}
+
+TextRecord& TextRecord::operator=(const TextRecord& rhs)
+{
+  _ascii_flag = rhs._ascii_flag;
+  _cont_flag = rhs._cont_flag;
+  _product_type = rhs._product_type;
+  _product_create = rhs._product_create;
+  _phyvol_id = rhs._phyvol_id;
+  _scene_id = rhs._scene_id;
+  _scene_loc = rhs._scene_loc;
+  _copyright_info = rhs._copyright_info;
+  return *this;
+}
+}
+
diff --git a/ossim_plugins/ossim/RadarSat/VolumeDir/TextRecord.h b/ossim_plugins/ossim/RadarSat/VolumeDir/TextRecord.h
new file mode 100755
index 0000000..cdf8b3a
--- /dev/null
+++ b/ossim_plugins/ossim/RadarSat/VolumeDir/TextRecord.h
@@ -0,0 +1,200 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef TextRecord_h
+#define TextRecord_h
+
+
+#include<iostream>
+#include <RadarSat/RadarSatRecordHeader.h>
+#include <RadarSat/RadarSatRecord.h>
+
+namespace ossimplugins
+{
+/**
+ * @ingroup TextRecordRecord
+ * @brief This class is able to read the Text record of the volume directory file
+ */
+class TextRecord : public RadarSatRecord
+{
+public:
+  /**
+   * @brief Constructor
+   */
+  TextRecord();
+  /**
+   * @brief Destructor
+   */
+  virtual ~TextRecord();
+
+  /**
+   * @brief This function writes the TextRecord in a stream
+   */
+  friend std::ostream& operator<<(std::ostream& os, const TextRecord& data);
+
+  /**
+   * @brief This function reads a TextRecord from a stream
+   */
+  friend std::istream& operator>>(std::istream& is, TextRecord& data);
+
+  /**
+   * @brief Copy constructor
+   */
+  TextRecord(const TextRecord& rhs);
+
+  /**
+   * @brief Copy operator
+   */
+  TextRecord& operator=(const TextRecord& rhs);
+
+  /**
+   * @brief This function is able to create a new instance of the class
+   */
+  RadarSatRecord* Instanciate()
+  {
+    return new TextRecord();
+  };
+
+  /**
+   * @brief This function is able to create a new instance of the class initialised with the data of the calling instance
+   */
+  RadarSatRecord* Clone()
+  {
+    return new TextRecord(*this);
+  };
+
+  /**
+   * @brief Reads the class data from a stream
+   */
+  void Read(std::istream& is)
+  {
+    is>>*this;
+  };
+
+  /**
+   * @brief Writes the class to a stream
+   */
+  void Write(std::ostream& os)
+  {
+    os<<*this;
+  };
+
+  /**
+   * @brief ASCII flag
+   */
+  std::string get_ascii_flag()
+  {
+    return _ascii_flag;
+  };
+
+  /**
+   * @brief Continuation flag
+   */
+  std::string get_cont_flag()
+  {
+    return _cont_flag;
+  };
+
+  /**
+   * @brief   Product type specifier
+   */
+  std::string get_product_type()
+  {
+    return _product_type;
+  };
+
+  /**
+   * @brief Product creation info
+   */
+  std::string get_product_create()
+  {
+    return _product_create;
+  };
+
+  /**
+   * @brief Volume Description Record
+   */
+  std::string get_phyvol_id()
+  {
+    return _phyvol_id;
+  };
+
+  /**
+   * @brief Scene identifier
+   */
+  std::string get_scene_id()
+  {
+    return _scene_id;
+  };
+
+  /**
+   * @brief Scene location
+   */
+  std::string get_scene_loc()
+  {
+    return _scene_loc;
+  };
+
+  /**
+   * @brief Copyright
+   */
+  std::string get_copyright_info()
+  {
+    return _copyright_info;
+  };
+
+
+protected:
+  /**
+   * @brief ASCII flag
+   */
+  std::string _ascii_flag;
+
+  /**
+   * @brief Continuation flag
+   */
+  std::string _cont_flag;
+
+  /**
+   * @brief   Product type specifier
+   */
+  std::string _product_type;
+
+  /**
+   * @brief Product creation info
+   */
+  std::string _product_create ;
+
+  /**
+   * @brief Volume Description Record
+   */
+  std::string _phyvol_id;
+
+  /**
+   * @brief Scene identifier
+   */
+  std::string _scene_id;
+
+  /**
+   * @brief Scene location
+   */
+  std::string _scene_loc;
+
+  /**
+   * @brief Copyright
+   */
+  std::string _copyright_info;
+
+private:
+};
+}
+#endif
+
diff --git a/ossim_plugins/ossim/RadarSat/VolumeDir/VolumeDescriptorRecord.cpp b/ossim_plugins/ossim/RadarSat/VolumeDir/VolumeDescriptorRecord.cpp
new file mode 100755
index 0000000..42b0574
--- /dev/null
+++ b/ossim_plugins/ossim/RadarSat/VolumeDir/VolumeDescriptorRecord.cpp
@@ -0,0 +1,215 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include "VolumeDescriptorRecord.h"
+
+namespace ossimplugins
+{
+VolumeDescriptorRecord::VolumeDescriptorRecord() : RadarSatRecord("vol_desc_rec")
+{
+}
+
+VolumeDescriptorRecord::~VolumeDescriptorRecord()
+{
+}
+
+std::ostream& operator<<(std::ostream& os, const VolumeDescriptorRecord& data)
+{
+  os<<"ascii_flag:"<<data._ascii_flag.c_str()<<std::endl;
+  os<<"format_doc:"<<data._format_doc.c_str()<<std::endl;
+  os<<"format_ver:"<<data._format_ver.c_str()<<std::endl;
+  os<<"format_rev:"<<data._format_rev.c_str()<<std::endl;
+  os<<"software_id:"<<data._software_id.c_str()<<std::endl;
+  os<<"phyvol_id:"<<data._phyvol_id.c_str()<<std::endl;
+  os<<"logvol_id:"<<data._logvol_id.c_str()<<std::endl;
+  os<<"volset_id:"<<data._volset_id.c_str()<<std::endl;
+  os<<"phyvol_cnt:"<<data._phyvol_cnt<<std::endl;
+  os<<"first_phyvol:"<<data._first_phyvol<<std::endl;
+  os<<"last_phyvol:"<<data._last_phyvol<<std::endl;
+  os<<"curr_phyvol:"<<data._curr_phyvol<<std::endl;
+  os<<"first_file:"<<data._first_file<<std::endl;
+  os<<"volset_log:"<<data._volset_log<<std::endl;
+  os<<"phyvol_log:"<<data._phyvol_log<<std::endl;
+  os<<"logvol_date:"<<data._logvol_date.c_str()<<std::endl;
+  os<<"logvol_time:"<<data._logvol_time.c_str()<<std::endl;
+  os<<"logvol_country:"<<data._logvol_country.c_str()<<std::endl;
+  os<<"logvol_agency:"<<data._logvol_agency.c_str()<<std::endl;
+  os<<"logvol_facility:"<<data._logvol_facility.c_str()<<std::endl;
+  os<<"n_filepoint:"<<data._n_filepoint<<std::endl;
+  os<<"n_voldir:"<<data._n_voldir<<std::endl;
+  os<<"product_id:"<<data._product_id.c_str()<<std::endl;
+
+
+  return os;
+}
+
+std::istream& operator>>(std::istream& is, VolumeDescriptorRecord& data)
+{
+  char buf[349]; // 361-12
+    buf[348] = '\0';
+
+    is.read(buf,2);
+    buf[2] = '\0';
+    data._ascii_flag = buf;
+
+    is.read(buf,2); // spare1
+
+    is.read(buf,12);
+    buf[12] = '\0';
+    data._format_doc = buf;
+
+    is.read(buf,2);
+    buf[2] = '\0';
+    data._format_ver = buf;
+
+    is.read(buf,2);
+    buf[2] = '\0';
+    data._format_rev = buf;
+
+    is.read(buf,12);
+    buf[12] = '\0';
+    data._software_id = buf;
+
+    is.read(buf,16);
+    buf[16] = '\0';
+    data._phyvol_id = buf;
+
+    is.read(buf,16);
+    buf[16] = '\0';
+    data._logvol_id = buf;
+
+    is.read(buf,16);
+    buf[16] = '\0';
+    data._volset_id = buf;
+
+    is.read(buf,2);
+    buf[2] = '\0';
+    data._phyvol_cnt = atoi(buf);
+
+    is.read(buf,2);
+    buf[2] = '\0';
+    data._first_phyvol = atoi(buf);
+
+    is.read(buf,2);
+    buf[2] = '\0';
+    data._last_phyvol = atoi(buf);
+
+    is.read(buf,2);
+    buf[2] = '\0';
+    data._curr_phyvol = atoi(buf);
+
+    is.read(buf,4);
+    buf[4] = '\0';
+    data._first_file = atoi(buf);
+
+    is.read(buf,4);
+    buf[4] = '\0';
+    data._volset_log = atoi(buf);
+
+    is.read(buf,4);
+    buf[4] = '\0';
+    data._phyvol_log = atoi(buf);
+
+    is.read(buf,8);
+    buf[8] = '\0';
+    data._logvol_date = buf;
+
+    is.read(buf,8);
+    buf[8] = '\0';
+    data._logvol_time = buf;
+
+    is.read(buf,12);
+    buf[12] = '\0';
+    data._logvol_country = buf;
+
+
+    is.read(buf,8);
+    buf[8] = '\0';
+    data._logvol_agency = buf;
+
+    is.read(buf,12);
+    buf[12] = '\0';
+    data._logvol_facility = buf;
+
+    is.read(buf,4);
+    buf[4] = '\0';
+    data._n_filepoint = atoi(buf);
+
+    is.read(buf,4);
+    buf[4] = '\0';
+    data._n_voldir = atoi(buf);
+
+    is.read(buf,92); // spare2
+
+    is.read(buf,8);
+    buf[8] = '\0';
+    data._product_id = buf;
+
+    is.read(buf,92); // spare3
+
+  return is;
+}
+
+VolumeDescriptorRecord::VolumeDescriptorRecord(const VolumeDescriptorRecord& rhs):
+  RadarSatRecord(rhs),
+  _ascii_flag(rhs._ascii_flag),
+  _format_doc(rhs._format_doc),
+  _format_ver(rhs._format_ver),
+  _format_rev(rhs._format_rev),
+  _software_id(rhs._software_id),
+  _phyvol_id(rhs._phyvol_id),
+  _logvol_id(rhs._logvol_id),
+  _volset_id(rhs._volset_id),
+  _phyvol_cnt(rhs._phyvol_cnt),
+  _first_phyvol(rhs._first_phyvol),
+  _last_phyvol(rhs._last_phyvol),
+  _curr_phyvol(rhs._curr_phyvol),
+  _first_file(rhs._first_file),
+  _volset_log(rhs._volset_log),
+  _logvol_date(rhs._logvol_date),
+  _logvol_time(rhs._logvol_time),
+  _logvol_country(rhs._logvol_country),
+  _logvol_agency(rhs._logvol_agency),
+  _logvol_facility(rhs._logvol_facility),
+  _n_filepoint(rhs._n_filepoint),
+  _n_voldir(rhs._n_voldir),
+  _product_id(rhs._product_id)
+{
+}
+
+VolumeDescriptorRecord& VolumeDescriptorRecord::operator=(const VolumeDescriptorRecord& rhs)
+{
+  _ascii_flag = rhs._ascii_flag;
+  _format_doc = rhs._format_doc;
+  _format_ver = rhs._format_ver;
+  _format_rev = rhs._format_rev;
+  _software_id = rhs._software_id;
+  _phyvol_id = rhs._phyvol_id;
+  _logvol_id = rhs._logvol_id;
+  _volset_id = rhs._volset_id;
+  _phyvol_cnt = rhs._phyvol_cnt;
+  _first_phyvol = rhs._first_phyvol;
+  _last_phyvol = rhs._last_phyvol;
+  _curr_phyvol = rhs._curr_phyvol;
+  _first_file = rhs._first_file;
+  _volset_log = rhs._volset_log;
+  _logvol_date = rhs._logvol_date;
+  _logvol_time = rhs._logvol_time;
+  _logvol_country = rhs._logvol_country;
+  _logvol_agency = rhs._logvol_agency;
+  _logvol_facility = rhs._logvol_facility;
+  _n_filepoint = rhs._n_filepoint;
+  _n_voldir = rhs._n_voldir;
+  _product_id = rhs._product_id;
+  return *this;
+}
+}
+
diff --git a/ossim_plugins/ossim/RadarSat/VolumeDir/VolumeDescriptorRecord.h b/ossim_plugins/ossim/RadarSat/VolumeDir/VolumeDescriptorRecord.h
new file mode 100755
index 0000000..fac877c
--- /dev/null
+++ b/ossim_plugins/ossim/RadarSat/VolumeDir/VolumeDescriptorRecord.h
@@ -0,0 +1,394 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef VolumeDescriptorRecord_h
+#define VolumeDescriptorRecord_h
+
+
+#include<iostream>
+#include <RadarSat/RadarSatRecordHeader.h>
+#include <RadarSat/RadarSatRecord.h>
+
+namespace ossimplugins
+{
+/**
+ * @ingroup SARLeaderVolumeDescriptorRecordRecord
+ * @brief This class is able to read the SAR leader file descriptor record of the leader file
+ */
+class VolumeDescriptorRecord : public RadarSatRecord
+{
+public:
+  /**
+   * @brief Constructor
+   */
+  VolumeDescriptorRecord();
+  /**
+   * @brief Destructor
+   */
+  virtual ~VolumeDescriptorRecord();
+
+  /**
+   * @brief This function writes the VolumeDescriptorRecord in a stream
+   */
+  friend std::ostream& operator<<(std::ostream& os, const VolumeDescriptorRecord& data);
+
+  /**
+   * @brief This function reads a VolumeDescriptorRecord from a stream
+   */
+  friend std::istream& operator>>(std::istream& is, VolumeDescriptorRecord& data);
+
+  /**
+   * @brief Copy constructor
+   */
+  VolumeDescriptorRecord(const VolumeDescriptorRecord& rhs);
+
+  /**
+   * @brief Copy operator
+   */
+  VolumeDescriptorRecord& operator=(const VolumeDescriptorRecord& rhs);
+
+  /**
+   * @brief This function is able to create a new instance of the class
+   */
+  RadarSatRecord* Instanciate()
+  {
+    return new VolumeDescriptorRecord();
+  };
+
+  /**
+   * @brief This function is able to create a new instance of the class initialised with the data of the calling instance
+   */
+  RadarSatRecord* Clone()
+  {
+    return new VolumeDescriptorRecord(*this);
+  };
+
+  /**
+   * @brief Reads the class data from a stream
+   */
+  void Read(std::istream& is)
+  {
+    is>>*this;
+  };
+
+  /**
+   * @brief Writes the class to a stream
+   */
+  void Write(std::ostream& os)
+  {
+    os<<*this;
+  };
+
+  /**
+   * @brief ASCII flag
+   */
+  std::string get_ascii_flag()
+  {
+    return _ascii_flag;
+  };
+  /**
+   * @brief Format control documentation
+   */
+  std::string get_format_doc()
+  {
+    return _format_doc;
+  };
+
+  /**
+   * @brief Format doc version
+   */
+  std::string get_format_ver()
+  {
+    return _format_ver;
+  };
+
+  /**
+   * @brief Format doc revision
+   */
+  std::string getget_format_rev()
+  {
+    return _format_rev;
+  };
+
+  /**
+   * @brief Software identifier
+   */
+  std::string get_software_id()
+  {
+    return _software_id;
+  };
+
+  /**
+   * @brief Physical volume identifier
+   */
+  std::string get_phyvol_id()
+  {
+    return _phyvol_id;
+  };
+
+  /**
+   * @brief Logical volume identifier
+   */
+  std::string get_logvol_id()
+  {
+    return _logvol_id;
+  };
+
+  /**
+   * @brief Volume set identifier
+   */
+  std::string get_volset_id()
+  {
+    return _volset_id;
+  };
+
+  /**
+   * @brief Total physical volume count
+   */
+  int get_phyvol_cnt()
+  {
+    return _phyvol_cnt;
+  };
+
+  /**
+   * @brief Physical volume of first tape
+   */
+  int get_first_phyvol()
+  {
+    return _first_phyvol;
+  };
+
+  /**
+   * @brief Physical volume of last tape
+   */
+  int get_last_phyvol()
+  {
+    return _last_phyvol;
+  };
+
+  /**
+   * @brief Physical volume of current tape
+   */
+  int get_curr_phyvol()
+  {
+    return _curr_phyvol;
+  };
+
+  /**
+   * @brief First file number in physical volume
+   */
+  int get_first_file()
+  {
+    return _first_file;
+  };
+
+  /**
+   * @brief Logical volume within set
+   */
+  int get_volset_log()
+  {
+    return _volset_log;
+  };
+
+  /**
+   * @brief Logical volume within phyvol
+   */
+  int get_phyvol_log()
+  {
+    return _phyvol_log;
+  };
+
+  /**
+   * @brief Logvol creation date
+   */
+  std::string get_logvol_date()
+  {
+    return _logvol_date;
+  };
+
+  /**
+   * @brief Logvol creation time
+   */
+  std::string get_logvol_time()
+  {
+    return _logvol_time;
+  };
+
+  /**
+   * @brief Logvol generation country
+   */
+  std::string get_logvol_country()
+  {
+    return _logvol_country;
+  };
+
+  /**
+   * @brief Logvol generation agency
+   */
+  std::string get_logvol_agency()
+  {
+    return _logvol_agency;
+  };
+
+  /**
+   * @brief Logvol generation facility
+   */
+  std::string get_logvol_facility()
+  {
+    return _logvol_facility;
+  };
+
+  /**
+   * @brief Number of file pointer records
+   */
+  int get_n_filepoint()
+  {
+    return _n_filepoint;
+  };
+
+  /**
+   * @brief Number of records in volume directory file
+   */
+  int get_n_voldir()
+  {
+    return _n_voldir;
+  };
+
+  /**
+   * @brief Product identifier
+   */
+  std::string get_product_id()
+  {
+    return _product_id;
+  };
+
+protected:
+  /**
+   * @brief ASCII flag
+   */
+  std::string _ascii_flag;
+
+  /**
+   * @brief Format control documentation
+   */
+  std::string _format_doc;
+
+  /**
+   * @brief Format doc version
+   */
+  std::string _format_ver;
+
+  /**
+   * @brief Format doc revision
+   */
+  std::string _format_rev;
+
+  /**
+   * @brief Software identifier
+   */
+  std::string _software_id;
+
+  /**
+   * @brief Physical volume identifier
+   */
+  std::string _phyvol_id;
+
+  /**
+   * @brief Logical volume identifier
+   */
+  std::string _logvol_id;
+
+  /**
+   * @brief Volume set identifier
+   */
+  std::string _volset_id;
+
+  /**
+   * @brief Total physical volume count
+   */
+  int _phyvol_cnt;
+
+  /**
+   * @brief Physical volume of first tape
+   */
+  int _first_phyvol;
+
+  /**
+   * @brief Physical volume of last tape
+   */
+  int _last_phyvol;
+
+  /**
+   * @brief Physical volume of current tape
+   */
+  int _curr_phyvol;
+
+  /**
+   * @brief First file number in physical volume
+   */
+  int _first_file;
+
+  /**
+   * @brief Logical volume within set
+   */
+  int _volset_log;
+
+  /**
+   * @brief Logical volume within phyvol
+   */
+  int _phyvol_log;
+
+  /**
+   * @brief Logvol creation date
+   */
+  std::string _logvol_date;
+
+  /**
+   * @brief Logvol creation time
+   */
+  std::string _logvol_time;
+
+  /**
+   * @brief Logvol generation country
+   */
+  std::string _logvol_country;
+
+  /**
+   * @brief Logvol generation agency
+   */
+  std::string _logvol_agency;
+
+  /**
+   * @brief Logvol generation facility
+   */
+  std::string _logvol_facility;
+
+  /**
+   * @brief Number of file pointer records
+   */
+  int _n_filepoint;
+
+  /**
+   * @brief Number of records in volume directory file
+   */
+  int _n_voldir;
+
+  /**
+   * @brief Product identifier
+   */
+    std::string _product_id;
+
+
+private:
+};
+}
+#endif
+
diff --git a/ossim_plugins/ossim/RadarSat/VolumeDir/VolumeDir.cpp b/ossim_plugins/ossim/RadarSat/VolumeDir/VolumeDir.cpp
new file mode 100755
index 0000000..925d90f
--- /dev/null
+++ b/ossim_plugins/ossim/RadarSat/VolumeDir/VolumeDir.cpp
@@ -0,0 +1,140 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include <RadarSat/VolumeDir/VolumeDir.h>
+#include <RadarSat/VolumeDir/VolumeDirFactory.h>
+#include <RadarSat/RadarSatRecordHeader.h>
+
+
+namespace ossimplugins
+{
+const int VolumeDir::TextRecordID = 1;
+const int VolumeDir::SARLeaderFilePointerRecordID = 2;
+const int VolumeDir::ImageOptionsFilePointerRecordID = 3;
+const int VolumeDir::SARTrailerFilePointerRecordID = 4;
+const int VolumeDir::VolumeDescriptorRecordID = 5;
+
+VolumeDir::VolumeDir()
+{
+}
+
+VolumeDir::~VolumeDir()
+{
+  ClearRecords();
+}
+
+std::ostream& operator<<(std::ostream& os, const VolumeDir& data)
+{
+  std::map<int, RadarSatRecord*>::const_iterator it = data._records.begin();
+  while(it != data._records.end())
+  {
+    (*it).second->Write(os);
+    ++it;
+  }
+  return os;
+
+}
+
+std::istream& operator>>(std::istream& is, VolumeDir& data)
+{
+  VolumeDirFactory factory;
+
+  data.ClearRecords();
+
+  RadarSatRecordHeader header;
+  bool eof = false;
+  while(!eof)
+  {
+    is>>header;
+    if(is.eof())
+    {
+      eof = true;
+    }
+    else
+    {
+      RadarSatRecord* record = factory.Instanciate(header.get_rec_seq());
+      if (record != NULL)
+      {
+        record->Read(is);
+        data._records[header.get_rec_seq()] = record;
+      }
+      else
+      {
+        char* buff = new char[header.get_length()-12];
+        is.read(buff, header.get_length()-12);
+        delete[] buff;
+      }
+    }
+  }
+  return is;
+}
+
+
+VolumeDir::VolumeDir(const VolumeDir& rhs)
+{
+  std::map<int, RadarSatRecord*>::const_iterator it = rhs._records.begin();
+  while(it != rhs._records.end())
+  {
+    _records[(*it).first] = (*it).second->Clone();
+    ++it;
+  }
+}
+
+VolumeDir& VolumeDir::operator=(const VolumeDir& rhs)
+{
+  ClearRecords();
+  std::map<int, RadarSatRecord*>::const_iterator it = rhs._records.begin();
+  while(it != rhs._records.end())
+  {
+    _records[(*it).first] = (*it).second->Clone();
+    ++it;
+  }
+
+  return *this;
+}
+
+void VolumeDir::ClearRecords()
+{
+  std::map<int, RadarSatRecord*>::const_iterator it = _records.begin();
+  while(it != _records.end())
+  {
+    delete (*it).second;
+    ++it;
+  }
+  _records.clear();
+}
+
+SARLeaderFilePointerRecord * VolumeDir::get_SARLeaderFilePointerRecord()
+{
+  return (SARLeaderFilePointerRecord*)_records[SARLeaderFilePointerRecordID];
+}
+
+ImageOptionsFilePointerRecord * VolumeDir::get_ImageOptionsFilePointerRecord()
+{
+  return (ImageOptionsFilePointerRecord*)_records[ImageOptionsFilePointerRecordID];
+}
+
+SARTrailerFilePointerRecord * VolumeDir::get_SARTrailerFilePointerRecord()
+{
+  return (SARTrailerFilePointerRecord*)_records[SARTrailerFilePointerRecordID];
+}
+
+TextRecord * VolumeDir::get_TextRecord()
+{
+  return (TextRecord*)_records[TextRecordID];
+}
+
+VolumeDescriptorRecord * VolumeDir::get_VolumeDescriptorRecord()
+{
+  return (VolumeDescriptorRecord*)_records[VolumeDescriptorRecordID];
+}
+}
+
diff --git a/ossim_plugins/ossim/RadarSat/VolumeDir/VolumeDir.h b/ossim_plugins/ossim/RadarSat/VolumeDir/VolumeDir.h
new file mode 100755
index 0000000..f49195c
--- /dev/null
+++ b/ossim_plugins/ossim/RadarSat/VolumeDir/VolumeDir.h
@@ -0,0 +1,92 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef VolumeDir_h
+#define VolumeDir_h
+
+#include <iostream>
+#include <RadarSat/VolumeDir/FilePointerRecord.h>
+#include <RadarSat/VolumeDir/VolumeDescriptorRecord.h>
+#include <RadarSat/VolumeDir/TextRecord.h>
+#include <map>
+
+namespace ossimplugins
+{
+class FilePointerRecord;
+class TextRecord;
+class VolumeDescriptorRecord;
+
+/**
+ * @ingroup VolumeDirFile
+ * @brief This class is able to read the volume directory file of the RadarSat file structure
+ * @author CS, Mickaël Savinaud
+ * @version 1.0
+ * @date 25-02-2011
+ */
+class VolumeDir
+{
+public:
+  /**
+   * @brief Constructor
+   */
+  VolumeDir();
+
+  /**
+   * @brief Destructor
+   */
+  ~VolumeDir();
+
+  /**
+   * @brief This function writes the VolumeDir in a stream
+   */
+  friend std::ostream& operator<<(std::ostream& os, const VolumeDir& data);
+
+  /**
+   * @brief This function reads a VolumeDir from a stream
+   */
+  friend std::istream& operator>>(std::istream& is, VolumeDir& data);
+
+  /**
+   * @brief Copy constructor
+   */
+  VolumeDir(const VolumeDir& rhs);
+
+  /**
+   * @brief Copy operator
+   */
+  VolumeDir& operator=(const VolumeDir& rhs);
+
+  /**
+   * @brief Removes all the previous records from the VolumeDir
+   */
+  void ClearRecords();
+
+  VolumeDescriptorRecord * get_VolumeDescriptorRecord();
+  SARLeaderFilePointerRecord * get_SARLeaderFilePointerRecord();
+  ImageOptionsFilePointerRecord * get_ImageOptionsFilePointerRecord();
+  SARTrailerFilePointerRecord * get_SARTrailerFilePointerRecord();
+  TextRecord * get_TextRecord();
+
+protected:
+  std::map<int, RadarSatRecord*> _records;
+
+  static const int VolumeDescriptorRecordID;
+  static const int SARLeaderFilePointerRecordID;
+  static const int ImageOptionsFilePointerRecordID;
+  static const int SARTrailerFilePointerRecordID;
+  static const int TextRecordID;
+
+private:
+
+};
+}
+#endif
+
diff --git a/ossim_plugins/ossim/RadarSat/VolumeDir/VolumeDirFactory.cpp b/ossim_plugins/ossim/RadarSat/VolumeDir/VolumeDirFactory.cpp
new file mode 100755
index 0000000..f47cb62
--- /dev/null
+++ b/ossim_plugins/ossim/RadarSat/VolumeDir/VolumeDirFactory.cpp
@@ -0,0 +1,48 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include <RadarSat/VolumeDir/VolumeDirFactory.h>
+
+#include <RadarSat/VolumeDir/FilePointerRecord.h>
+#include <RadarSat/VolumeDir/VolumeDescriptorRecord.h>
+#include <RadarSat/VolumeDir/TextRecord.h>
+
+
+namespace ossimplugins
+{
+VolumeDirFactory::VolumeDirFactory()
+{
+  RegisterRecord(1, new VolumeDescriptorRecord());
+  RegisterRecord(2, new SARLeaderFilePointerRecord());
+  RegisterRecord(3, new ImageOptionsFilePointerRecord());
+  RegisterRecord(4, new SARTrailerFilePointerRecord());
+  RegisterRecord(5, new TextRecord());
+}
+
+VolumeDirFactory::~VolumeDirFactory()
+{
+
+  std::map<int, RadarSatRecord*>::iterator i = _availableRecords.begin();
+
+  while (i != _availableRecords.end())
+  {
+     if ( (*i).second )
+     {
+        delete (*i).second;
+        (*i).second = 0;
+     }
+     ++i;
+  }
+  _availableRecords.clear();
+
+}
+}
+
diff --git a/ossim_plugins/ossim/RadarSat/VolumeDir/VolumeDirFactory.h b/ossim_plugins/ossim/RadarSat/VolumeDir/VolumeDirFactory.h
new file mode 100755
index 0000000..05a2911
--- /dev/null
+++ b/ossim_plugins/ossim/RadarSat/VolumeDir/VolumeDirFactory.h
@@ -0,0 +1,45 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef VolumeDirFactory_h
+#define VolumeDirFactory_h
+
+
+#include <RadarSat/RadarSatRecordFactory.h>
+#include <map>
+
+namespace ossimplugins
+{
+/**
+ * @ingroup VolumeDirFile
+ * @brief This class is a factory able to construct Record base classes
+ */
+class VolumeDirFactory : public RadarSatRecordFactory
+{
+public:
+  /**
+   * @brief Contstructor
+   */
+  VolumeDirFactory();
+  /**
+   * @brief Destructor
+   */
+  ~VolumeDirFactory();
+
+
+protected:
+
+
+private:
+};
+}
+#endif
+
diff --git a/ossim_plugins/ossim/erssar/ErsSarDataSetSummary.cpp b/ossim_plugins/ossim/erssar/ErsSarDataSetSummary.cpp
new file mode 100644
index 0000000..3968032
--- /dev/null
+++ b/ossim_plugins/ossim/erssar/ErsSarDataSetSummary.cpp
@@ -0,0 +1,776 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include "erssar/ErsSarDataSetSummary.h"
+
+namespace ossimplugins
+{
+
+ErsSarDataSetSummary::ErsSarDataSetSummary() : ErsSarRecord("dataset_sum_rec")
+{
+}
+
+ErsSarDataSetSummary::~ErsSarDataSetSummary()
+{
+}
+
+std::ostream& operator<<(std::ostream& os, const ErsSarDataSetSummary& data)
+{
+  os << "seq_num:" << data._seq_num << std::endl;
+
+  os << "sar_chn:" << data._sar_chn << std::endl;
+
+  os << "scene_id:" << data._scene_id.c_str() << std::endl;
+
+  os << "scene_des:" << data._scene_des.c_str() << std::endl;
+
+  os << "inp_sctim:" << data._inp_sctim.c_str() << std::endl;
+
+  os << "asc_des:" << data._asc_des.c_str() << std::endl;
+
+  os << "pro_lat:" << data._pro_lat << std::endl;
+
+  os << "pro_long:" << data._pro_long << std::endl;
+
+  os << "pro_head:" << data._pro_head << std::endl;
+
+  os << "ellip_des:" << data._ellip_des.c_str() << std::endl;
+
+  os << "ellip_maj:" << data._ellip_maj << std::endl;
+
+  os << "ellip_min:" << data._ellip_min << std::endl;
+  os << "earth_mass:" << data._earth_mass << std::endl;
+  os << "grav_const:" << data._grav_const << std::endl;
+  os << "ellip_j[0]:" << data._ellip_j[0] << std::endl;
+  os << "ellip_j[1]:" << data._ellip_j[1] << std::endl;
+  os << "ellip_j[2]:" << data._ellip_j[2] << std::endl;
+  os << "terrain_h:" << data._terrain_h << std::endl;
+  os << "sc_lin:" << data._sc_lin << std::endl;
+  os << "sc_pix:" << data._sc_pix << std::endl;
+  os << "scene_len:" << data._scene_len << std::endl;
+  os << "scene_wid:" << data._scene_wid << std::endl;
+  os << "nchn:" << data._nchn << std::endl;
+  os << "mission_id:" << data._mission_id.c_str() << std::endl;
+  os << "sensor_id:" << data._sensor_id.c_str() << std::endl;
+  os << "orbit_num:" << data._orbit_num.c_str() << std::endl;
+
+  os << "plat_lat:" << data._plat_lat << std::endl;
+
+  os << "plat_long:" << data._plat_long << std::endl;
+
+  os << "plat_head:" << data._plat_head << std::endl;
+
+  os << "clock_ang:" << data._clock_ang << std::endl;
+
+  os << "incident_ang:" << data._incident_ang << std::endl;
+
+
+  os << "wave_length:" << data._wave_length << std::endl;
+
+  os << "motion_comp:" << data._motion_comp.c_str() << std::endl;
+
+  os << "pulse_code:" << data._pulse_code.c_str() << std::endl;
+
+  for (int i = 0; i < 5; i++)
+  {
+    os << "ampl_coef[" << i << "]:" << data._ampl_coef[i] << std::endl;
+  }
+
+  for (int i = 0; i < 5; i++)
+  {
+    os << "phas_coef[" << i << "]:" << data._phas_coef[i] << std::endl;
+  }
+
+  os << "chirp_ext_ind:" << data._chirp_ext_ind << std::endl;
+
+  os << "fr:" << data._fr << std::endl;
+
+  os << "rng_gate:" << data._rng_gate << std::endl;
+
+  os << "rng_length:" << data._rng_length << std::endl;
+
+  os << "baseband_f:" << data._baseband_f.c_str() << std::endl;
+
+  os << "rngcmp_f:" << data._rngcmp_f.c_str() << std::endl;
+
+  os << "gn_polar:" << data._gn_polar << std::endl;
+
+  os << "gn_cross:" << data._gn_cross << std::endl;
+
+  os << "chn_bits:" << data._chn_bits << std::endl;
+
+  os << "quant_desc:" << data._quant_desc.c_str() << std::endl;
+
+  os << "i_bias:" << data._i_bias << std::endl;
+
+  os << "q_bias:" << data._q_bias << std::endl;
+
+  os << "iq_ratio:" << data._iq_ratio << std::endl;
+
+  os << "mech_sight:" << data._mech_sight << std::endl;
+
+  os << "fa:" << data._fa << std::endl;
+
+  os << "sat_bintim:" << data._sat_bintim.c_str() << std::endl;
+
+  os << "sat_clktim:" << data._sat_clktim.c_str() << std::endl;
+
+  os << "sat_clkinc:" << data._sat_clkinc.c_str() << std::endl;
+
+  os << "fac_id:" << data._fac_id.c_str() << std::endl;
+
+  os << "sys_id:" << data._sys_id.c_str() << std::endl;
+
+  os << "ver_id:" << data._ver_id.c_str() << std::endl;
+
+  os << "prod_type:" << data._prod_type.c_str() << std::endl;
+
+  os << "algor_id:" << data._algor_id.c_str() << std::endl;
+
+  os << "n_azilok:" << data._n_azilok << std::endl;
+
+  os << "n_rnglok:" << data._n_rnglok << std::endl;
+
+  os << "bnd_azilok:" << data._bnd_azilok << std::endl;
+
+  os << "bnd_rnglok:" << data._bnd_rnglok << std::endl;
+
+  os << "bnd_azi:" << data._bnd_azi << std::endl;
+
+  os << "bnd_rng:" << data._bnd_rng << std::endl;
+
+  os << "azi_weight:" << data._azi_weight.c_str() << std::endl;
+
+  os << "rng_weight:" << data._rng_weight.c_str() << std::endl;
+
+  os << "data_inpsrc:" << data._data_inpsrc.c_str() << std::endl;
+
+  os << "rng_res:" << data._rng_res << std::endl;
+
+  os << "azi_res:" << data._azi_res << std::endl;
+
+  os << "alt_dopcen[0]:" << data._alt_dopcen[0] << std::endl;
+  os << "alt_dopcen[1]:" << data._alt_dopcen[1] << std::endl;
+  os << "alt_dopcen[2]:" << data._alt_dopcen[2] << std::endl;
+
+  os << "crt_dopcen[0]:" << data._crt_dopcen[0] << std::endl;
+  os << "crt_dopcen[1]:" << data._crt_dopcen[1] << std::endl;
+  os << "crt_dopcen[2]:" << data._crt_dopcen[2] << std::endl;
+
+  os << "time_dir_pix:" << data._time_dir_pix.c_str() << std::endl;
+
+  os << "time_dir_lin:" << data._time_dir_lin.c_str() << std::endl;
+
+  os << "alt_rate[0]:" << data._alt_rate[0] << std::endl;
+  os << "alt_rate[1]:" << data._alt_rate[1] << std::endl;
+  os << "alt_rate[2]:" << data._alt_rate[2] << std::endl;
+
+  os << "crt_rate[0]:" << data._crt_rate[0] << std::endl;
+  os << "crt_rate[1]:" << data._crt_rate[1] << std::endl;
+  os << "crt_rate[2]:" << data._crt_rate[2] << std::endl;
+
+  os << "clutter_lock:" << data._line_cont.c_str() << std::endl;
+
+  os << "clutter_lock:" << data._clutter_lock.c_str() << std::endl;
+
+  os << "auto_focus:" << data._auto_focus.c_str() << std::endl;
+
+  os << "line_spacing:" << data._line_spacing << std::endl;
+
+  os << "pix_spacing:" << data._pix_spacing << std::endl;
+
+  os << "rngcmp_desg:" << data._rngcmp_desg.c_str() << std::endl;
+
+  os << "zero_dop_range_time_f_pixel:" << data._zero_dop_range_time_f_pixel << std::endl;
+
+  os << "zero_dop_range_time_c_pixel:" << data._zero_dop_range_time_c_pixel << std::endl;
+
+  os << "zero_dop_range_time_l_pixel:" << data._zero_dop_range_time_l_pixel << std::endl;
+
+  os << "zero_dop_az_time_f_pixel :" << data._zero_dop_az_time_f_pixel.c_str() << std::endl;
+
+  os << " zero_dop_az_time_c_pixel:" << data._zero_dop_az_time_c_pixel.c_str() << std::endl;
+
+  os << " zero_dop_az_time_l_pixel:" << data._zero_dop_az_time_l_pixel.c_str() << std::endl;
+
+  return os;
+
+}
+
+std::istream& operator>>(std::istream& is, ErsSarDataSetSummary& data)
+{
+  char buf16[17];
+  buf16[16] = '\0';
+  char buf32[33];
+  buf32[32] = '\0';
+  char buf8[9];
+  buf8[8] = '\0';
+  char buf4[5];
+  buf4[4] = '\0';
+
+  is.read(buf4, 4);
+  data._seq_num = atoi(buf4);
+
+  is.read(buf4, 4);
+  data._sar_chn = atoi(buf4);
+
+  is.read(buf16, 16);
+  data._scene_id = buf16;
+
+  is.read(buf32, 32);
+  data._scene_des = buf32;
+
+  is.read(buf32, 32);
+  data._inp_sctim = buf32;
+
+  is.read(buf16, 16);
+  data._asc_des = buf16;
+
+  is.read(buf16, 16);
+  data._pro_lat = atof(buf16);
+
+  is.read(buf16, 16);
+  data._pro_long = atof(buf16);
+
+  is.read(buf16, 16);
+  data._pro_head = atof(buf16);
+
+  is.read(buf16, 16);
+  data._ellip_des = buf16;
+
+  is.read(buf16, 16);
+  data._ellip_maj = atof(buf16);
+
+  is.read(buf16, 16);
+  data._ellip_min = atof(buf16);
+
+  is.read(buf16, 16);
+  data._earth_mass = atof(buf16);
+
+  is.read(buf16, 16);
+  data._grav_const = atof(buf16);
+
+  is.read(buf16, 16);
+  data._ellip_j[0] = atof(buf16);
+  is.read(buf16, 16);
+  data._ellip_j[1] = atof(buf16);
+  is.read(buf16, 16);
+  data._ellip_j[2] = atof(buf16);
+
+  is.read(buf16, 16);
+
+  is.read(buf16, 16);
+  data._terrain_h = atof(buf16);
+
+  is.read(buf8, 8);
+  data._sc_lin = atoi(buf8);
+
+  is.read(buf8, 8);
+  data._sc_pix = atoi(buf8);
+
+  is.read(buf16, 16);
+  data._scene_len = atof(buf16);
+
+  is.read(buf16, 16);
+  data._scene_wid = atof(buf16);
+
+  is.read(buf16, 16);
+
+  is.read(buf4, 4);
+  data._nchn = atoi(buf4);
+
+  is.read(buf4, 4);
+
+  is.read(buf16, 16);
+  data._mission_id = buf16;
+
+  is.read(buf32, 32);
+  data._sensor_id = buf32;
+
+  is.read(buf8, 8);
+  data._orbit_num = buf8;
+
+  is.read(buf8, 8);
+  data._plat_lat = atof(buf8);
+
+  is.read(buf8, 8);
+  data._plat_long = atof(buf8);
+
+  is.read(buf8, 8);
+  data._plat_head = atof(buf8);
+
+  is.read(buf8, 8);
+  data._clock_ang = atof(buf8);
+
+  is.read(buf8, 8);
+  data._incident_ang = atof(buf8);
+
+  is.read(buf8, 8);
+
+  is.read(buf16, 16);
+  data._wave_length = atof(buf16);
+
+  is.read(buf8, 2);
+  buf8[2] = '\0';
+  data._motion_comp = buf8;
+
+  is.read(buf16, 16);
+  data._pulse_code = buf16;
+
+  for (int i = 0; i < 5; i++)
+  {
+    is.read(buf16, 16);
+    data._ampl_coef[i] = atof(buf16);
+  }
+
+  for (int i = 0; i < 5; i++)
+  {
+    is.read(buf16, 16);
+    data._phas_coef[i] = atof(buf16);
+  }
+
+  is.read(buf8, 8);
+  data._chirp_ext_ind = atoi(buf8);
+
+  is.read(buf8, 8);
+
+  is.read(buf16, 16);
+  data._fr = atof(buf16);
+
+  is.read(buf16, 16);
+  data._rng_gate = atof(buf16);
+
+  is.read(buf16, 16);
+  data._rng_length = atof(buf16);
+
+  is.read(buf8, 4);
+  buf8[4] = '\0';
+  data._baseband_f = buf8;
+
+  is.read(buf8, 4);
+  buf8[4] = '\0';
+  data._rngcmp_f = buf8;
+
+  is.read(buf16, 16);
+  data._gn_polar = atof(buf16);
+
+  is.read(buf16, 16);
+  data._gn_cross = atof(buf16);
+
+  is.read(buf8, 8);
+  data._chn_bits = atoi(buf8);
+
+  is.read(buf16, 12);
+  buf16[12] = '\0';
+  data._quant_desc = buf16;
+
+  is.read(buf16, 16);
+  data._i_bias = atof(buf16);
+
+  is.read(buf16, 16);
+  data._q_bias = atof(buf16);
+
+  is.read(buf16, 16);
+  data._iq_ratio = atof(buf16);
+
+  is.read(buf32, 32);
+
+  is.read(buf16, 16);
+
+  is.read(buf16, 16);
+  data._mech_sight = atof(buf16);
+
+  is.read(buf4, 4);
+
+  is.read(buf16, 16);
+  data._fa = atof(buf16);
+
+  is.read(buf16, 16);
+
+  is.read(buf16, 16);
+
+  is.read(buf16, 16);
+  data._sat_bintim = buf16;
+
+  is.read(buf32, 32);
+  data._sat_clktim = buf32;
+
+  is.read(buf8, 8);
+  data._sat_clkinc = buf8;
+
+  is.read(buf8, 8);
+
+  is.read(buf16, 16);
+  data._fac_id = buf16;
+
+  is.read(buf8, 8);
+  data._sys_id = buf8;
+
+  is.read(buf8, 8);
+  data._ver_id = buf8;
+
+  is.read(buf32, 32);
+
+  is.read(buf32, 32);
+  data._prod_type = buf32;
+
+  is.read(buf32, 32);
+  data._algor_id = buf32;
+
+  is.read(buf16, 16);
+  data._n_azilok = atof(buf16);
+
+  is.read(buf16, 16);
+  data._n_rnglok = atof(buf16);
+
+  is.read(buf16, 16);
+  data._bnd_azilok = atof(buf16);
+
+  is.read(buf16, 16);
+  data._bnd_rnglok = atof(buf16);
+
+  is.read(buf16, 16);
+  data._bnd_azi = atof(buf16);
+
+  is.read(buf16, 16);
+  data._bnd_rng = atof(buf16);
+
+  is.read(buf32, 32);
+  data._azi_weight = buf32;
+
+  is.read(buf32, 32);
+  data._rng_weight = buf32;
+
+  is.read(buf16, 16);
+  data._data_inpsrc = buf16;
+
+  is.read(buf16, 16);
+  data._rng_res = atof(buf16);
+
+  is.read(buf16, 16);
+  data._azi_res = atof(buf16);
+
+  is.read(buf32, 32);
+
+  is.read(buf16, 16);
+  data._alt_dopcen[0] = atof(buf16);
+  is.read(buf16, 16);
+  data._alt_dopcen[1] = atof(buf16);
+  is.read(buf16, 16);
+  data._alt_dopcen[2] = atof(buf16);
+
+  is.read(buf16, 16);
+
+  is.read(buf16, 16);
+  data._crt_dopcen[0] = atof(buf16);
+  is.read(buf16, 16);
+  data._crt_dopcen[1] = atof(buf16);
+  is.read(buf16, 16);
+  data._crt_dopcen[2] = atof(buf16);
+
+  is.read(buf8, 8);
+  data._time_dir_pix = buf8;
+
+  is.read(buf8, 8);
+  data._time_dir_lin = buf8;
+
+  is.read(buf16, 16);
+  data._alt_rate[0] = atof(buf16);
+  is.read(buf16, 16);
+  data._alt_rate[1] = atof(buf16);
+  is.read(buf16, 16);
+  data._alt_rate[2] = atof(buf16);
+
+  is.read(buf16, 16);
+
+  is.read(buf16, 16);
+  data._crt_rate[0] = atof(buf16);
+  is.read(buf16, 16);
+  data._crt_rate[1] = atof(buf16);
+  is.read(buf16, 16);
+  data._crt_rate[2] = atof(buf16);
+
+  is.read(buf16, 16);
+
+  is.read(buf8, 8);
+  data._line_cont = buf8;
+
+  is.read(buf4, 4);
+  data._clutter_lock = buf4;
+
+  is.read(buf4, 4);
+  data._auto_focus = buf4;
+
+  is.read(buf16, 16);
+  data._line_spacing = atof(buf16);
+
+  is.read(buf16, 16);
+  data._pix_spacing = atof(buf16);
+
+  is.read(buf16, 16);
+  data._rngcmp_desg = buf16;
+
+  is.read(buf32, 32);
+
+  is.read(buf16, 16);
+  data._zero_dop_range_time_f_pixel = atof(buf16);
+
+  is.read(buf16, 16);
+  data._zero_dop_range_time_c_pixel = atof(buf16);
+
+  is.read(buf16, 16);
+  data._zero_dop_range_time_l_pixel  = atof(buf16);
+
+  is.read(buf32, 24);
+  buf32[24] = '\0';
+  data._zero_dop_az_time_f_pixel = buf32;
+
+  is.read(buf32, 24);
+  buf32[24] = '\0';
+  data._zero_dop_az_time_c_pixel = buf32;
+
+  is.read(buf32, 24);
+  buf32[24] = '\0';
+  data._zero_dop_az_time_l_pixel = buf32;
+
+  return is;
+}
+
+
+ErsSarDataSetSummary::ErsSarDataSetSummary(const ErsSarDataSetSummary& rhs):
+    ErsSarRecord(rhs),
+    _seq_num(rhs._seq_num),
+    _sar_chn(rhs._sar_chn),
+    _scene_id(rhs._scene_id),
+    _scene_des(rhs._scene_des),
+    _inp_sctim(rhs._inp_sctim),
+    _asc_des(rhs._asc_des),
+    _pro_lat(rhs._pro_lat),
+    _pro_long(rhs._pro_long),
+    _pro_head(rhs._pro_head),
+    _ellip_des(rhs._ellip_des),
+    _ellip_maj(rhs._ellip_maj),
+    _ellip_min(rhs._ellip_min),
+    _earth_mass(rhs._earth_mass),
+    _grav_const(rhs._grav_const),
+    _terrain_h(rhs._terrain_h),
+    _sc_lin(rhs._sc_lin),
+    _sc_pix(rhs._sc_pix),
+    _scene_len(rhs._scene_len),
+    _scene_wid(rhs._scene_wid),
+    _nchn(rhs._nchn),
+    _mission_id(rhs._mission_id),
+    _sensor_id(rhs._sensor_id),
+    _orbit_num(rhs._orbit_num),
+    _plat_lat(rhs._plat_lat),
+    _plat_long(rhs._plat_long),
+    _plat_head(rhs._plat_head),
+    _clock_ang(rhs._clock_ang),
+    _incident_ang(rhs._incident_ang),
+    _wave_length(rhs._wave_length),
+    _motion_comp(rhs._motion_comp),
+    _pulse_code(rhs._pulse_code),
+    _chirp_ext_ind(rhs._chirp_ext_ind),
+    _fr(rhs._fr),
+    _rng_gate(rhs._rng_gate),
+    _rng_length(rhs._rng_length),
+    _baseband_f(rhs._baseband_f),
+    _rngcmp_f(rhs._rngcmp_f),
+    _gn_polar(rhs._gn_polar),
+    _gn_cross(rhs._gn_cross),
+    _chn_bits(rhs._chn_bits),
+    _quant_desc(rhs._quant_desc),
+    _i_bias(rhs._i_bias),
+    _q_bias(rhs._q_bias),
+    _iq_ratio(rhs._iq_ratio),
+    _mech_sight(rhs._mech_sight),
+    _fa(rhs._fa),
+    _sat_bintim(rhs._sat_bintim),
+    _sat_clktim(rhs._sat_clktim),
+    _sat_clkinc(rhs._sat_clkinc),
+    _fac_id(rhs._fac_id),
+    _sys_id(rhs._sys_id),
+    _ver_id(rhs._ver_id),
+    _prod_type(rhs._prod_type),
+    _algor_id(rhs._algor_id),
+    _n_azilok(rhs._n_azilok),
+    _n_rnglok(rhs._n_rnglok),
+    _bnd_azilok(rhs._bnd_azilok),
+    _bnd_rnglok(rhs._bnd_rnglok),
+    _bnd_azi(rhs._bnd_azi),
+    _bnd_rng(rhs._bnd_rng),
+    _azi_weight(rhs._azi_weight),
+    _rng_weight(rhs._rng_weight),
+    _data_inpsrc(rhs._data_inpsrc),
+    _rng_res(rhs._rng_res),
+    _azi_res(rhs._azi_res),
+    _time_dir_pix(rhs._time_dir_pix),
+    _time_dir_lin(rhs._time_dir_lin),
+    _line_cont(rhs._line_cont),
+    _clutter_lock(rhs._clutter_lock),
+    _auto_focus(rhs._auto_focus),
+    _line_spacing(rhs._line_spacing),
+    _pix_spacing(rhs._pix_spacing),
+    _rngcmp_desg(rhs._rngcmp_desg),
+    _zero_dop_range_time_f_pixel(rhs._zero_dop_range_time_f_pixel),
+    _zero_dop_range_time_c_pixel(rhs._zero_dop_range_time_c_pixel),
+    _zero_dop_range_time_l_pixel(rhs._zero_dop_range_time_l_pixel),
+    _zero_dop_az_time_f_pixel(rhs._zero_dop_az_time_f_pixel),
+    _zero_dop_az_time_c_pixel(rhs._zero_dop_az_time_c_pixel),
+    _zero_dop_az_time_l_pixel(rhs._zero_dop_az_time_l_pixel)
+{
+  _ellip_j[0] = rhs._ellip_j[0];
+  _ellip_j[1] = rhs._ellip_j[1];
+  _ellip_j[2] = rhs._ellip_j[2];
+  _ampl_coef[0] = rhs._ampl_coef[0];
+  _ampl_coef[1] = rhs._ampl_coef[1];
+  _ampl_coef[2] = rhs._ampl_coef[2];
+  _ampl_coef[3] = rhs._ampl_coef[3];
+  _ampl_coef[4] = rhs._ampl_coef[4];
+  _phas_coef[0] = rhs._phas_coef[0];
+  _phas_coef[1] = rhs._phas_coef[1];
+  _phas_coef[2] = rhs._phas_coef[2];
+  _phas_coef[3] = rhs._phas_coef[3];
+  _phas_coef[4] = rhs._phas_coef[4];
+
+  _alt_dopcen[0] = rhs._alt_dopcen[0];
+  _alt_dopcen[1] = rhs._alt_dopcen[1];
+  _alt_dopcen[2] = rhs._alt_dopcen[2];
+
+  _crt_dopcen[0] = rhs._crt_dopcen[0];
+  _crt_dopcen[1] = rhs._crt_dopcen[1];
+  _crt_dopcen[2] = rhs._crt_dopcen[2];
+
+  _alt_rate[0] = rhs._alt_rate[0];
+  _alt_rate[1] = rhs._alt_rate[1];
+  _alt_rate[2] = rhs._alt_rate[2];
+  _crt_rate[0] = rhs._crt_rate[0];
+  _crt_rate[1] = rhs._crt_rate[1];
+  _crt_rate[2] = rhs._crt_rate[2];
+}
+
+ErsSarDataSetSummary& ErsSarDataSetSummary::operator=(const ErsSarDataSetSummary& rhs)
+{
+  _seq_num = rhs._seq_num;
+  _sar_chn = rhs._sar_chn;
+  _scene_id = rhs._scene_id;
+  _scene_des = rhs._scene_des;
+  _inp_sctim = rhs._inp_sctim;
+  _asc_des = rhs._asc_des;
+  _pro_lat = rhs._pro_lat;
+  _pro_long = rhs._pro_long;
+  _pro_head = rhs._pro_head;
+  _ellip_des = rhs._ellip_des;
+  _ellip_maj = rhs._ellip_maj;
+  _ellip_min = rhs._ellip_min;
+  _earth_mass = rhs._earth_mass;
+  _grav_const = rhs._grav_const;
+  _terrain_h = rhs._terrain_h;
+  _sc_lin = rhs._sc_lin;
+  _sc_pix = rhs._sc_pix;
+  _scene_len = rhs._scene_len;
+  _scene_wid = rhs._scene_wid;
+  _nchn = rhs._nchn;
+  _mission_id = rhs._mission_id;
+  _sensor_id = rhs._sensor_id;
+  _orbit_num = rhs._orbit_num;
+  _plat_lat = rhs._plat_lat;
+  _plat_long = rhs._plat_long;
+  _plat_head = rhs._plat_head;
+  _clock_ang = rhs._clock_ang;
+  _incident_ang = rhs._incident_ang;
+  _wave_length = rhs._wave_length;
+  _motion_comp = rhs._motion_comp;
+  _pulse_code = rhs._pulse_code;
+  _chirp_ext_ind = rhs._chirp_ext_ind;
+  _fr = rhs._fr;
+  _rng_gate = rhs._rng_gate;
+  _rng_length = rhs._rng_length;
+  _baseband_f = rhs._baseband_f;
+  _rngcmp_f = rhs._rngcmp_f;
+  _gn_polar = rhs._gn_polar;
+  _gn_cross = rhs._gn_cross;
+  _chn_bits = rhs._chn_bits;
+  _quant_desc = rhs._quant_desc;
+  _i_bias = rhs._i_bias;
+  _q_bias = rhs._q_bias;
+  _iq_ratio = rhs._iq_ratio;
+  _mech_sight = rhs._mech_sight;
+  _fa = rhs._fa;
+  _sat_bintim = rhs._sat_bintim;
+  _sat_clktim = rhs._sat_clktim;
+  _sat_clkinc = rhs._sat_clkinc;
+  _fac_id = rhs._fac_id;
+  _sys_id = rhs._sys_id;
+  _ver_id = rhs._ver_id;
+  _prod_type = rhs._prod_type;
+  _algor_id = rhs._algor_id;
+  _n_azilok = rhs._n_azilok;
+  _n_rnglok = rhs._n_rnglok;
+  _bnd_azilok = rhs._bnd_azilok;
+  _bnd_rnglok = rhs._bnd_rnglok;
+  _bnd_azi = rhs._bnd_azi;
+  _bnd_rng = rhs._bnd_rng;
+  _azi_weight = rhs._azi_weight;
+  _rng_weight = rhs._rng_weight;
+  _data_inpsrc = rhs._data_inpsrc;
+  _rng_res = rhs._rng_res;
+  _azi_res = rhs._azi_res;
+  _time_dir_pix = rhs._time_dir_pix;
+  _time_dir_lin = rhs._time_dir_lin;
+  _line_cont = rhs._line_cont;
+  _clutter_lock = rhs._clutter_lock;
+  _auto_focus = rhs._auto_focus;
+  _line_spacing = rhs._line_spacing;
+  _pix_spacing = rhs._pix_spacing;
+  _rngcmp_desg = rhs._rngcmp_desg;
+
+  _ellip_j[0] = rhs._ellip_j[0];
+  _ellip_j[1] = rhs._ellip_j[1];
+  _ellip_j[2] = rhs._ellip_j[2];
+  _ampl_coef[0] = rhs._ampl_coef[0];
+  _ampl_coef[1] = rhs._ampl_coef[1];
+  _ampl_coef[2] = rhs._ampl_coef[2];
+  _ampl_coef[3] = rhs._ampl_coef[3];
+  _ampl_coef[4] = rhs._ampl_coef[4];
+  _phas_coef[0] = rhs._phas_coef[0];
+  _phas_coef[1] = rhs._phas_coef[1];
+  _phas_coef[2] = rhs._phas_coef[2];
+  _phas_coef[3] = rhs._phas_coef[3];
+  _phas_coef[4] = rhs._phas_coef[4];
+
+  _alt_dopcen[0] = rhs._alt_dopcen[0];
+  _alt_dopcen[1] = rhs._alt_dopcen[1];
+  _alt_dopcen[2] = rhs._alt_dopcen[2];
+
+  _crt_dopcen[0] = rhs._crt_dopcen[0];
+  _crt_dopcen[1] = rhs._crt_dopcen[1];
+  _crt_dopcen[2] = rhs._crt_dopcen[2];
+
+  _alt_rate[0] = rhs._alt_rate[0];
+  _alt_rate[1] = rhs._alt_rate[1];
+  _alt_rate[2] = rhs._alt_rate[2];
+  _crt_rate[0] = rhs._crt_rate[0];
+  _crt_rate[1] = rhs._crt_rate[1];
+  _crt_rate[2] = rhs._crt_rate[2];
+
+  _zero_dop_range_time_f_pixel = rhs._zero_dop_range_time_f_pixel;
+  _zero_dop_range_time_c_pixel = rhs._zero_dop_range_time_c_pixel;
+  _zero_dop_range_time_l_pixel = rhs._zero_dop_range_time_l_pixel;
+  _zero_dop_az_time_f_pixel = rhs._zero_dop_az_time_f_pixel;
+  _zero_dop_az_time_c_pixel = rhs._zero_dop_az_time_c_pixel;
+  _zero_dop_az_time_l_pixel = rhs._zero_dop_az_time_l_pixel;
+
+
+  return *this;
+}
+}
+
diff --git a/ossim_plugins/ossim/erssar/ErsSarDataSetSummary.h b/ossim_plugins/ossim/erssar/ErsSarDataSetSummary.h
new file mode 100644
index 0000000..53334fd
--- /dev/null
+++ b/ossim_plugins/ossim/erssar/ErsSarDataSetSummary.h
@@ -0,0 +1,1071 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef ErsSarDataSetSummary_h
+#define ErsSarDataSetSummary_h
+
+#include <iostream>
+#include <cstdlib>
+#include "erssar/ErsSarRecordHeader.h"
+#include "erssar/ErsSarRecord.h"
+
+namespace ossimplugins
+{
+
+/**
+ * @ingroup ErsSarDataSetSummaryRecord
+ * @brief This class is able to read the SAR leader data set summary record of the leader file
+ *
+ */
+class ErsSarDataSetSummary : public ErsSarRecord
+{
+public:
+  /**
+   * @brief Constructor
+   */
+  ErsSarDataSetSummary();
+
+  /**
+   * @brief Destructor
+   */
+  virtual ~ErsSarDataSetSummary();
+
+  /**
+   * @brief This function write the ErsSarDataSetSummary in a stream
+   */
+  friend std::ostream& operator<<(std::ostream& os, const ErsSarDataSetSummary& data);
+
+  /**
+   * @brief This function read a ErsSarDataSetSummary from a stream
+   */
+  friend std::istream& operator>>(std::istream& is, ErsSarDataSetSummary& data);
+
+  /**
+   * @brief Copy constructor
+   */
+  ErsSarDataSetSummary(const ErsSarDataSetSummary& rhs);
+
+  /**
+   * @brief Copy operator
+   */
+  ErsSarDataSetSummary& operator=(const ErsSarDataSetSummary& rhs);
+
+  /**
+   * @brief This function is able to create a new instance of the class
+   */
+  ErsSarRecord* Instanciate()
+  {
+    return new ErsSarDataSetSummary();
+  };
+
+  /**
+   * @brief This function is able to create a new instance of the class initialised with the data of the calling instance
+   */
+  ErsSarRecord* Clone()
+  {
+    return new ErsSarDataSetSummary(*this);
+  };
+
+  /**
+   * @brief Read the class data from a stream
+   */
+  void Read(std::istream& is)
+  {
+    is >> *this;
+  };
+
+  /**
+   * @brief Write the class to a stream
+   */
+  void Write(std::ostream& os)
+  {
+    os << *this;
+  };
+
+  /**
+   * @brief Sequence number
+   */
+  int   get_seq_num() const
+  {
+    return _seq_num;
+  };
+  /**
+  * @brief SAR channel indicator
+  */
+  int   get_sar_chn() const
+  {
+    return _sar_chn;
+  };
+  /**
+   * @brief Scene identifier
+   */
+  std::string   get_scene_id() const
+  {
+    return _scene_id;
+  };
+  /**
+   * @brief Scene designator
+   */
+  std::string   get_scene_des() const
+  {
+    return _scene_des;
+  };
+  /**
+   * @brief Input scene centre time
+   */
+  std::string   get_inp_sctim() const
+  {
+    return _inp_sctim;
+  };
+  /**
+   * @brief Ascending/descending
+   */
+  std::string   get_asc_des() const
+  {
+    return _asc_des;
+  };
+  /**
+  * @brief Processed scene centre latitude
+  */
+  double   get_pro_lat() const
+  {
+    return _pro_lat;
+  };
+  /**
+  * @brief Processed scene centre longitude
+  */
+  double   get_pro_long() const
+  {
+    return _pro_long;
+  };
+  /**
+  * @brief Processed scene centre headng
+  */
+  double   get_pro_head() const
+  {
+    return _pro_head;
+  };
+  /**
+   * @brief Ellipsoid designator
+   */
+  std::string   get_ellip_des() const
+  {
+    return _ellip_des;
+  };
+  /**
+  * @brief Ellipsoid semi-major axis, km
+  */
+  double   get_ellip_maj() const
+  {
+    return _ellip_maj;
+  };
+  /**
+  * @brief Ellipsoid semi_minor axis, km
+  */
+  double  get_ellip_min() const
+  {
+    return _ellip_min;
+  };
+  /**
+   * @brief Earth's mass
+   */
+  double   get_earth_mass() const
+  {
+    return _earth_mass;
+  };
+  /**
+  * @brief Gravitational constant
+  */
+  double   get_grav_const() const
+  {
+    return _grav_const;
+  };
+  /**
+  * @brief Ellipsoid J2-4 parameters
+  */
+  const double*   get_ellip_j() const
+  {
+    return _ellip_j;
+  };
+
+  /**
+  * @brief Average terrain height, km
+  */
+  double   get_terrain_h() const
+  {
+    return _terrain_h;
+  };
+  /**
+  * @brief Scene centre line number
+  */
+  int   get_sc_lin() const
+  {
+    return _sc_lin;
+  };
+  /**
+  * @brief Scene centre pixel number
+  */
+  int   get_sc_pix() const
+  {
+    return _sc_pix;
+  };
+  /**
+  * @brief Scene length, km
+  */
+  double   get_scene_len() const
+  {
+    return _scene_len;
+  };
+  /**
+  * @brief Scene width, km
+  */
+  double   get_scene_wid() const
+  {
+    return _scene_wid;
+  };
+
+  /**
+  * @brief Number of SAR channels
+  */
+  double   get_nchn() const
+  {
+    return _nchn;
+  };
+
+  /**
+  * @brief Mission identifier
+  */
+  std::string   get_mission_id() const
+  {
+    return _mission_id;
+  };
+  /**
+  * @brief Sensor identifier
+  */
+  std::string   get_sensor_id() const
+  {
+    return _sensor_id;
+  };
+  /**
+  * @brief Orbit number
+  */
+  std::string   get_orbit_num() const
+  {
+    return _orbit_num;
+  };
+  /**
+  * @brief Platform geodetic latitude
+  */
+  double   get_plat_lat() const
+  {
+    return _plat_lat;
+  };
+  /**
+  * @brief Platform geodetic longitude
+  */
+  double   get_plat_long() const
+  {
+    return _plat_long;
+  };
+  /**
+  * @brief Platform heading
+  */
+  double   get_plat_head() const
+  {
+    return _plat_head;
+  };
+  /**
+  * @brief Sensor clock angle
+  */
+  double   get_clock_ang() const
+  {
+    return _clock_ang;
+  };
+  /**
+  * @brief Incidence angle
+  */
+  double   get_incident_ang() const
+  {
+    return _incident_ang;
+  };
+
+  /**
+  * @brief Radar wave length
+  */
+  double   get_wave_length() const
+  {
+    return _wave_length;
+  };
+  /**
+  * @brief Motion compensation indicator
+  */
+  std::string   get_motion_comp() const
+  {
+    return _motion_comp;
+  };
+  /**
+  * @brief Range pulse code specifier
+  */
+  std::string   get_pulse_code() const
+  {
+    return _pulse_code;
+  };
+  /**
+  * @brief Range chirp coefficients
+  */
+  const double*   get_ampl_coef() const
+  {
+    return _ampl_coef;
+  };
+  /**
+  * @brief Range phase coefficients
+  */
+  const double*   get_phas_coef() const
+  {
+    return _phas_coef;
+  };
+  /**
+  * @brief Chirp extraction index
+  */
+  int   get_chirp_ext_ind() const
+  {
+    return _chirp_ext_ind;
+  };
+
+  /**
+  * @brief Range sampling rate
+  */
+  double   get_fr() const
+  {
+    return _fr;
+  };
+  /**
+  * @brief Range gate start time
+  */
+  double   get_rng_gate() const
+  {
+    return _rng_gate;
+  };
+  /**
+  * @brief Range pulse length
+  */
+  double   get_rng_length() const
+  {
+    return _rng_length;
+  };
+  /**
+  * @brief Baseband conversion flag
+  */
+  std::string   get_baseband_f() const
+  {
+    return _baseband_f;
+  };
+  /**
+  * @brief Range compressed flag
+  */
+  std::string   get_rngcmp_f() const
+  {
+    return _rngcmp_f;
+  };
+  /**
+  * @brief Like polarized gain
+  */
+  double   get_gn_polar() const
+  {
+    return _gn_polar;
+  };
+  /**
+  * @brief Cross polarized gain
+  */
+  double   get_gn_cross() const
+  {
+    return _gn_cross;
+  };
+  /**
+  * @brief Number of bits per channel
+  */
+  int   get_chn_bits() const
+  {
+    return _chn_bits;
+  };
+  /**
+  * @brief Quantization descriptor
+  */
+  std::string   get_quant_desc() const
+  {
+    return _quant_desc;
+  };
+  /**
+  * @brief I channel DC bias
+  */
+  double   get_i_bias() const
+  {
+    return _i_bias;
+  };
+  /**
+  * @brief Q channel DC bias
+  */
+  double   get_q_bias() const
+  {
+    return _q_bias;
+  };
+  /**
+  * @brief I/Q channel ratio
+  */
+  double   get_iq_ratio() const
+  {
+    return _iq_ratio;
+  };
+
+
+  /**
+  * @brief Mechanical boresight
+  */
+  double   get_mech_sight() const
+  {
+    return _mech_sight;
+  };
+
+  /**
+  * @brief Nominal PRF, Hz
+  */
+  double   get_fa() const
+  {
+    return _fa;
+  };
+
+  /**
+  * @brief Satellite binary time
+  */
+  std::string    get_sat_bintim() const
+  {
+    return _sat_bintim;
+  };
+  /**
+  * @brief Satellite clock time
+  */
+  std::string    get_sat_clktim() const
+  {
+    return _sat_clktim;
+  };
+  /**
+  * @brief Satellite clock increment
+  */
+  std::string    get_sat_clkinc() const
+  {
+    return _sat_clkinc;
+  };
+
+  /**
+  * @brief Processing facility identifier
+  */
+  std::string   get_fac_id() const
+  {
+    return _fac_id;
+  };
+  /**
+  * @brief Processing system identifier
+  */
+  std::string   get_sys_id() const
+  {
+    return _sys_id;
+  };
+  /**
+  * @brief Processing version identifier
+  */
+  std::string   get_ver_id() const
+  {
+    return _ver_id;
+  };
+
+  /**
+  * @brief Product type specifier
+  */
+  std::string   get_prod_type() const
+  {
+    return _prod_type;
+  };
+  /**
+  * @brief Processing algorithm identifier
+  */
+  std::string   get_algor_id() const
+  {
+    return _algor_id;
+  };
+  /**
+  * @brief Number of azimuth looks
+  */
+  double   get_n_azilok() const
+  {
+    return _n_azilok;
+  };
+  /**
+  * @brief Number of range looks
+  */
+  double   get_n_rnglok() const
+  {
+    return _n_rnglok;
+  };
+  /**
+  * @brief Bandwidth per look in azimuth,Hz
+  */
+  double   get_bnd_azilok() const
+  {
+    return _bnd_azilok;
+  };
+  /**
+  * @brief Bandwidth per look in range,Hz
+  */
+  double   get_bnd_rnglok() const
+  {
+    return _bnd_rnglok;
+  };
+  /**
+  * @brief Total azimuth look bandwidth
+  */
+  double   get_bnd_azi() const
+  {
+    return _bnd_azi;
+  };
+  /**
+  * @brief Total range look bandwidth
+  */
+  double   get_bnd_rng() const
+  {
+    return _bnd_rng;
+  };
+  /**
+  * @brief Azimuth weighting designator
+  */
+  std::string   get_azi_weight() const
+  {
+    return _azi_weight;
+  };
+  /**
+  * @brief Range weighting designator
+  */
+  std::string   get_rng_weight() const
+  {
+    return _rng_weight;
+  };
+  /**
+  * @brief Data input source
+  */
+  std::string   get_data_inpsrc() const
+  {
+    return _data_inpsrc;
+  };
+  /**
+  * @brief Range resolution, meter
+  */
+  double   get_rng_res() const
+  {
+    return _rng_res;
+  };
+  /**
+  * @brief Azimuth resolution, meter
+  */
+  double   get_azi_res() const
+  {
+    return _azi_res;
+  };
+  /**
+  * @brief Along track Doppler frequency terms
+  */
+  const double*   get_alt_dopcen() const
+  {
+    return _alt_dopcen;
+  };
+
+  /**
+  * @brief Cross track Doppler frequency terms
+  */
+  const double*   get_crt_dopcen() const
+  {
+    return _crt_dopcen;
+  };
+  /**
+  * @brief Pixel time direction indicator
+  */
+  std::string   get_time_dir_pix() const
+  {
+    return _time_dir_pix;
+  };
+  /**
+  * @brief Line time direction indicator
+  */
+  std::string   get_time_dir_lin() const
+  {
+    return _time_dir_lin;
+  };
+  /**
+  * @brief Along track Doppler rate term
+  */
+  const double*   get_alt_rate() const
+  {
+    return _alt_rate;
+  };
+
+  /**
+  * @brief Cross track Doppler rate term
+  */
+  const double*   get_crt_rate() const
+  {
+    return _crt_rate;
+  };
+
+  /**
+  * @brief Line content indicator
+  */
+  std::string   get_line_cont() const
+  {
+    return _line_cont;
+  };
+  /**
+  * @brief Clutter lock applied flag
+  */
+  std::string   get_clutter_lock() const
+  {
+    return _clutter_lock;
+  };
+  /**
+  * @brief Auto-focus applied flag
+  */
+  std::string   get_auto_focus() const
+  {
+    return _auto_focus;
+  };
+  /**
+  * @brief Line spacing, meters
+  */
+  double   get_line_spacing() const
+  {
+    return _line_spacing;
+  };
+  /**
+  * @brief Pixel spacing, meters
+  */
+  double   get_pix_spacing() const
+  {
+    return _pix_spacing;
+  };
+  /**
+  * @brief Range compression designator
+  */
+  std::string   get_rngcmp_desg() const
+  {
+    return _rngcmp_desg;
+  };
+  /**
+  * @brief zero doppler range time (two way) of first pixel
+  */
+  double  get_zero_dop_range_time_f_pixel() const
+  {
+    return _zero_dop_range_time_f_pixel;
+  }
+  /**
+  * @brief zero doppler range time (two way) of mid pixel
+  */
+  double  get_zero_dop_range_time_c_pixel() const
+  {
+    return _zero_dop_range_time_c_pixel;
+  }
+  /**
+   * @brief zero doppler range time (two way) of last pixel
+   */
+  double  get_zero_dop_range_time_l_pixel() const
+  {
+    return _zero_dop_range_time_l_pixel;
+  }
+  /**
+   * @brief zero doppler azimut time (UTC) of first pixel
+   */
+  std::string    get_zero_dop_az_time_f_pixel() const
+  {
+    return _zero_dop_az_time_f_pixel;
+  }
+  /**
+   * @brief zero doppler azimut time (UTC) of mid pixel
+   */
+  std::string    get_zero_dop_az_time_c_pixel() const
+  {
+    return _zero_dop_az_time_c_pixel;
+  }
+  /**
+   * @brief zero doppler azimut time (UTC) of last pixel
+   */
+  std::string  get_zero_dop_az_time_l_pixel() const
+  {
+    return _zero_dop_az_time_l_pixel;
+  }
+
+
+protected:
+  /**
+   * @brief Sequence number
+   */
+  int   _seq_num;
+  /**
+  * @brief SAR channel indicator
+  */
+  int   _sar_chn;
+  /**
+   * @brief Scene identifier
+   */
+  std::string   _scene_id;
+  /**
+   * @brief Scene designator
+   */
+  std::string   _scene_des;
+  /**
+   * @brief Input scene centre time
+   */
+  std::string   _inp_sctim;
+  /**
+   * @brief Ascending/descending
+   */
+  std::string   _asc_des;
+  /**
+  * @brief Processed scene centre latitude
+  */
+  double   _pro_lat;
+  /**
+  * @brief Processed scene centre longitude
+  */
+  double   _pro_long;
+  /**
+  * @brief Processed scene centre headng
+  */
+  double   _pro_head;
+  /**
+   * @brief Ellipsoid designator
+   */
+  std::string   _ellip_des;
+  /**
+  * @brief Ellipsoid semi-major axis, km
+  */
+  double   _ellip_maj;
+  /**
+  * @brief Ellipsoid semi_minor axis, km
+  */
+  double  _ellip_min;
+  /**
+   * @brief Earth's mass
+   */
+  double   _earth_mass;
+  /**
+  * @brief Gravitational constant
+  */
+  double   _grav_const;
+  /**
+  * @brief Ellipsoid J2-4 parameters
+  */
+  double   _ellip_j[3];
+
+  /**
+  * @brief Average terrain height, km
+  */
+  double   _terrain_h;
+  /**
+  * @brief Scene centre line number
+  */
+  int   _sc_lin;
+  /**
+  * @brief Scene centre pixel number
+  */
+  int   _sc_pix;
+  /**
+  * @brief Scene length, km
+  */
+  double   _scene_len;
+  /**
+  * @brief Scene width, km
+  */
+  double   _scene_wid;
+
+  /**
+  * @brief Number of SAR channels
+  */
+  double   _nchn;
+
+  /**
+  * @brief Mission identifier
+  */
+  std::string   _mission_id;
+  /**
+  * @brief Sensor identifier
+  */
+  std::string   _sensor_id;
+  /**
+  * @brief Orbit number
+  */
+  std::string   _orbit_num;
+  /**
+  * @brief Platform geodetic latitude
+  */
+  double   _plat_lat;
+  /**
+  * @brief Platform geodetic longitude
+  */
+  double   _plat_long;
+  /**
+  * @brief Platform heading
+  */
+  double   _plat_head;
+  /**
+  * @brief Sensor clock angle
+  */
+  double   _clock_ang;
+  /**
+  * @brief Incidence angle
+  */
+  double   _incident_ang;
+
+  /**
+  * @brief Radar wave length
+  */
+  double   _wave_length;
+  /**
+  * @brief Motion compensation indicator
+  */
+  std::string   _motion_comp;
+  /**
+  * @brief Range pulse code specifier
+  */
+  std::string   _pulse_code;
+  /**
+  * @brief Range chirp coefficients
+  */
+  double   _ampl_coef[5];
+  /**
+  * @brief Range phase coefficients
+  */
+  double   _phas_coef[5];
+  /**
+  * @brief Chirp extraction index
+  */
+  int   _chirp_ext_ind;
+
+  /**
+  * @brief Range sampling rate
+  */
+  double   _fr;
+  /**
+  * @brief Range gate start time
+  */
+  double   _rng_gate;
+  /**
+  * @brief Range pulse length
+  */
+  double   _rng_length;
+  /**
+  * @brief Baseband conversion flag
+  */
+  std::string   _baseband_f;
+  /**
+  * @brief Range compressed flag
+  */
+  std::string   _rngcmp_f;
+  /**
+  * @brief Like polarized gain
+  */
+  double   _gn_polar;
+  /**
+  * @brief Cross polarized gain
+  */
+  double   _gn_cross;
+  /**
+  * @brief Number of bits per channel
+  */
+  int   _chn_bits;
+  /**
+  * @brief Quantization descriptor
+  */
+  std::string   _quant_desc;
+  /**
+  * @brief I channel DC bias
+  */
+  double   _i_bias;
+  /**
+  * @brief Q channel DC bias
+  */
+  double   _q_bias;
+  /**
+  * @brief I/Q channel ratio
+  */
+  double   _iq_ratio;
+  /**
+  * @brief Mechanical boresight
+  */
+  double   _mech_sight;
+  /**
+  * @brief Nominal PRF, Hz
+  */
+  double   _fa;
+  /**
+  * @brief Satellite binary time
+  */
+  std::string    _sat_bintim;
+  /**
+  * @brief Satellite clock time
+  */
+  std::string    _sat_clktim;
+  /**
+  * @brief Satellite clock increment
+  */
+  std::string    _sat_clkinc;
+
+  /**
+  * @brief Processing facility identifier
+  */
+  std::string   _fac_id;
+  /**
+  * @brief Processing system identifier
+  */
+  std::string   _sys_id;
+  /**
+  * @brief Processing version identifier
+  */
+  std::string   _ver_id;
+  /**
+  * @brief Product type specifier
+  */
+  std::string   _prod_type;
+  /**
+  * @brief Processing algorithm identifier
+  */
+  std::string   _algor_id;
+  /**
+  * @brief Number of azimuth looks
+  */
+  double   _n_azilok;
+  /**
+  * @brief Number of range looks
+  */
+  double   _n_rnglok;
+  /**
+  * @brief Bandwidth per look in azimuth,Hz
+  */
+  double   _bnd_azilok;
+  /**
+  * @brief Bandwidth per look in range,Hz
+  */
+  double   _bnd_rnglok;
+  /**
+  * @brief Total azimuth look bandwidth
+  */
+  double   _bnd_azi;
+  /**
+  * @brief Total range look bandwidth
+  */
+  double   _bnd_rng;
+  /**
+  * @brief Azimuth weighting designator
+  */
+  std::string   _azi_weight;
+  /**
+  * @brief Range weighting designator
+  */
+  std::string   _rng_weight;
+  /**
+  * @brief Data input source
+  */
+  std::string   _data_inpsrc;
+  /**
+  * @brief Range resolution, meter
+  */
+  double   _rng_res;
+  /**
+  * @brief Azimuth resolution, meter
+  */
+  double   _azi_res;
+  /**
+  * @brief Along track Doppler frequency terms
+  */
+  double   _alt_dopcen[3];
+  /**
+  * @brief Cross track Doppler frequency terms
+  */
+  double   _crt_dopcen[3];
+  /**
+  * @brief Pixel time direction indicator
+  */
+  std::string   _time_dir_pix;
+  /**
+  * @brief Line time direction indicator
+  */
+  std::string   _time_dir_lin;
+  /**
+  * @brief Along track Doppler rate term
+  */
+  double   _alt_rate[3];
+
+  /**
+  * @brief Cross track Doppler rate term
+  */
+  double   _crt_rate[3];
+
+  /**
+  * @brief Line content indicator
+  */
+  std::string   _line_cont;
+  /**
+  * @brief Clutter lock applied flag
+  */
+  std::string   _clutter_lock;
+  /**
+  * @brief Auto-focus applied flag
+  */
+  std::string   _auto_focus;
+  /**
+  * @brief Line spacing, meters
+  */
+  double   _line_spacing;
+  /**
+  * @brief Pixel spacing, meters
+  */
+  double   _pix_spacing;
+  /**
+  * @brief Range compression designator
+  */
+  std::string   _rngcmp_desg;
+  /**
+   * @brief zero doppler range time (two way) of first pixel
+   */
+  double  _zero_dop_range_time_f_pixel;
+  /**
+  * @brief zero doppler range time (two way) of mid pixel
+  */
+  double  _zero_dop_range_time_c_pixel;
+  /**
+   * @brief zero doppler range time (two way) of last pixel
+   */
+  double  _zero_dop_range_time_l_pixel ;
+  /**
+   * @brief zero doppler azimut time (UTC) of first pixel
+   */
+  std::string  _zero_dop_az_time_f_pixel ;
+  /**
+   * @brief zero doppler azimut time (UTC) of mid pixel
+   */
+  std::string  _zero_dop_az_time_c_pixel;
+  /**
+   * @brief zero doppler azimut time (UTC) of last pixel
+   */
+  std::string _zero_dop_az_time_l_pixel;
+
+private:
+
+};
+}
+
+#endif
+
diff --git a/ossim_plugins/ossim/erssar/ErsSarFacilityData.cpp b/ossim_plugins/ossim/erssar/ErsSarFacilityData.cpp
new file mode 100644
index 0000000..662da56
--- /dev/null
+++ b/ossim_plugins/ossim/erssar/ErsSarFacilityData.cpp
@@ -0,0 +1,1167 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include "erssar/ErsSarFacilityData.h"
+
+namespace ossimplugins
+{
+
+   ErsSarFacilityData::ErsSarFacilityData() : ErsSarRecord("facility_data_rec")
+   {
+   }
+
+   ErsSarFacilityData::~ErsSarFacilityData()
+   {
+   }
+
+   std::ostream& operator<<(std::ostream& os, const ErsSarFacilityData& data)
+   {
+      os << "last_release_qc_date:" << data._last_release_qc_date.c_str() << std::endl;
+
+      os << "last_release_cal_date:" << data._last_release_cal_date.c_str() << std::endl;
+
+      os << "qa_summary_flag:" << data._qa_summary_flag << std::endl;
+
+      os << "prf_code_change_flag:" << data._prf_code_change_flag << std::endl;
+
+      os << "sampling_win_change_flag:" << data._sampling_win_change_flag << std::endl;
+
+      os << "cal_gain_change_flag:" << data._cal_gain_change_flag << std::endl;
+
+      os << "quirp_qu_flag:" << data._quirp_qu_flag << std::endl;
+
+      os << "inp_data_stat_flag:" << data._inp_data_stat_flag << std::endl;
+
+      os << "dopp_cent_conf_meas_flag:" << data._dopp_cent_conf_meas_flag << std::endl;
+
+      os << "dopp_cent_val_flag:" << data._dopp_cent_val_flag << std::endl;
+
+      os << "dopp_ambig_conf_meas_flag:" << data._dopp_ambig_conf_meas_flag << std::endl;
+
+      os << "outp_data_mean_flag:" << data._outp_data_mean_flag << std::endl;
+
+      os << "OGOB_flag:" << data._OGOB_flag << std::endl;
+
+      os << "PRF_changes:" << data._PRF_changes << std::endl;
+
+      os << "sampling_win_changes:" << data._sampling_win_changes << std::endl;
+
+      os << "cal_gain_changes:" << data._cal_gain_changes << std::endl;
+
+      os << "missing_lines:" << data._missing_lines << std::endl;
+
+      os << "rec_gain_changes:" << data._rec_gain_changes << std::endl;
+
+      os << "pulse_width_of_ACF_3db:" << data._pulse_width_of_ACF_3db << std::endl;
+
+      os << "first_side_lobe_lev_of_ACF:" << data._first_side_lobe_lev_of_ACF << std::endl;
+
+      os << "ISLR_of_ACF:" << data._ISLR_of_ACF << std::endl;
+
+      os << "dopp_cent_conf_meas:" << data._dopp_cent_conf_meas << std::endl;
+
+      os << "dopp_ambig_conf_meas:" << data._dopp_ambig_conf_meas << std::endl;
+
+      os << "inp_data_I_mean:" << data._inp_data_I_mean << std::endl;
+
+      os << "inp_data_Q_mean:" << data._inp_data_Q_mean << std::endl;
+
+      os << "inp_data_I_stddev:" << data._inp_data_I_stddev << std::endl;
+
+      os << "inp_data_Q_stddev:" << data._inp_data_Q_stddev << std::endl;
+
+      os << "cal_sys_gain:" << data._cal_sys_gain << std::endl;
+
+      os << "first_rec_gain_read:" << data._first_rec_gain_read << std::endl;
+
+      os << "dopp_ambig_num:" << data._dopp_ambig_num << std::endl;
+
+      os << "I_channel_bias_correction:" << data._I_channel_bias_correction << std::endl;
+
+      os << "Q_channel_bias_correction:" << data._Q_channel_bias_correction << std::endl;
+
+      os << "I_channel_gain_correction:" << data._I_channel_gain_correction << std::endl;
+
+      os << "Q_channel_gain_correction:" << data._Q_channel_gain_correction << std::endl;
+
+      os << "Q_channel_I_Q_correction:" << data._Q_channel_I_Q_correction << std::endl;
+
+      os << "noise_power:" << data._noise_power << std::endl;
+
+      os << "int_cal_utc:" << data._int_cal_utc << std::endl;
+
+      os << "num_valid_cal_pulses:" << data._num_valid_cal_pulses << std::endl;
+
+      os << "num_valid_noise_pulses:" << data._num_valid_noise_pulses << std::endl;
+
+      os << "num_valid_replicas:" << data._num_valid_replicas << std::endl;
+
+      os << "first_replica_sample:" << data._first_replica_sample << std::endl;
+
+      os << "mean_cal_pulse_power:" << data._mean_cal_pulse_power << std::endl;
+
+      os << "mean_noise_power:" << data._mean_noise_power << std::endl;
+
+      os << "range_comp_norm_fact:" << data._range_comp_norm_fact << std::endl;
+
+      os << "replica_power:" << data._replica_power << std::endl;
+
+      os << "first_range_pixel_mid_az_inc:" << data._first_range_pixel_mid_az_inc << std::endl;
+
+      os << "center_range_pix_mid_az_inc:" << data._center_range_pix_mid_az_inc << std::endl;
+
+      os << "last_range_pix_mid_az_inc:" << data._last_range_pix_mid_az_inc << std::endl;
+
+      os << "norm_ref_range_ro:" << data._norm_ref_range_ro << std::endl;
+
+      os << "antenna_elev_flag:" << data._antenna_elev_flag << std::endl;
+
+      os << "abs_cal_const_K:" << data._abs_cal_const_K << std::endl;
+
+      os << "upp_bound_K:" << data._upp_bound_K << std::endl;
+
+      os << "low_bound_K:" << data._low_bound_K << std::endl;
+
+      os << "proc_noise_scale_fact:" << data._proc_noise_scale_fact << std::endl;
+
+      os << "K_gen_date:" << data._K_gen_date.c_str() << std::endl;
+
+      os << "K_vers_num:" << data._K_vers_num.c_str() << std::endl;
+
+      os << "num_duplic_input_lines:" << data._num_duplic_input_lines << std::endl;
+
+      os << "estim_bit_error_rate:" << data._estim_bit_error_rate << std::endl;
+
+      os << "out_image_mean:" << data._out_image_mean << std::endl;
+
+      os << "out_image_std_dev:" << data._out_image_std_dev << std::endl;
+
+      os << "out_image_max_value:" << data._out_image_max_value << std::endl;
+
+      os << "time_raw_data_first_input:" << data._time_raw_data_first_input.c_str() << std::endl;
+
+      os << "time_asc_node_state_vectors:" << data._time_asc_node_state_vectors.c_str() << std::endl;
+
+      os << "asc_node_pos_X_comp:" << data._asc_node_pos_X_comp.c_str() << std::endl;
+
+      os << "asc_node_pos_Y_comp:" << data._asc_node_pos_Y_comp.c_str() << std::endl;
+
+      os << "asc_node_pos_Z_comp:" << data._asc_node_pos_Z_comp.c_str() << std::endl;
+
+      os << "asc_node_vel_X_comp:" << data._asc_node_vel_X_comp.c_str() << std::endl;
+
+      os << "asc_node_vel_Y_comp:" << data._asc_node_vel_Y_comp.c_str() << std::endl;
+
+      os << "asc_node_vel_Z_comp:" << data._asc_node_vel_Z_comp.c_str() << std::endl;
+
+      os << "out_pixel_bit_length:" << data._out_pixel_bit_length << std::endl;
+
+      os << "proc_gain_param_1:" << data._proc_gain_param_1 << std::endl;
+
+      os << "proc_gain_param_2:" << data._proc_gain_param_2 << std::endl;
+
+      os << "proc_gain_param_3:" << data._proc_gain_param_3 << std::endl;
+
+      os << "peak_loc_cross_correl_fun:" << data._peak_loc_cross_correl_fun << std::endl;
+
+      os << "3_dB_width_CCF:" << data._3_dB_width_CCF << std::endl;
+
+      os << "first_side_lobe_level:" << data._first_side_lobe_level << std::endl;
+
+      os << "ISLR_CCF_between_last:" << data._ISLR_CCF_between_last << std::endl;
+
+      os << "peak_loc_CCF_betw_last:" << data._peak_loc_CCF_betw_last << std::endl;
+
+      os << "Roll_Tilt_Mode_flag:" << data._Roll_Tilt_Mode_flag << std::endl;
+
+      os << "raw_data_correction_flag:" << data._raw_data_correction_flag << std::endl;
+
+      os << "look_detecion_flag:" << data._look_detecion_flag << std::endl;
+
+      os << "doppler_ambiguity_estimat_flag:" << data._doppler_ambiguity_estimat_flag << std::endl;
+
+      os << "azimuth_baseband_convers_flag:" << data._azimuth_baseband_convers_flag << std::endl;
+
+      os << "samples_per_line_used:" << data._samples_per_line_used << std::endl;
+
+      os << "range_lines_skip_factor:" << data._range_lines_skip_factor << std::endl;
+
+      os << "time_of_inp_state_vectors:" << data._time_of_inp_state_vectors.c_str() << std::endl;
+
+      os << "inp_state_vect_pos_X_comp:" << data._inp_state_vect_pos_X_comp.c_str() << std::endl;
+
+      os << "inp_state_vect_pos_Y_comp:" << data._inp_state_vect_pos_Y_comp.c_str() << std::endl;
+
+      os << "inp_state_vect_pos_Z_comp:" << data._inp_state_vect_pos_Z_comp.c_str() << std::endl;
+
+      os << "inp_state_vect_vel_Vx_comp:" << data._inp_state_vect_vel_Vx_comp.c_str() << std::endl;
+
+      os << "inp_state_vect_vel_Vy_comp:" << data._inp_state_vect_vel_Vy_comp.c_str() << std::endl;
+
+      os << "inp_state_vect_vel_Vz_comp:" << data._inp_state_vect_vel_Vz_comp.c_str() << std::endl;
+
+      os << "inp_state_vector_type_flag:" << data._inp_state_vector_type_flag << std::endl;
+
+      os << "win_coeff_for_range_match:" << data._win_coeff_for_range_match << std::endl;
+
+      os << "win_coeff_for_azi_match:" << data._win_coeff_for_azi_match << std::endl;
+
+      os << "update_period_range_match:" << data._update_period_range_match << std::endl;
+
+      os << "look_scalar_gain_1:" << data._look_scalar_gain_1 << std::endl;
+
+      os << "look_scalar_gain_2:" << data._look_scalar_gain_2 << std::endl;
+
+      os << "look_scalar_gain_3:" << data._look_scalar_gain_3 << std::endl;
+
+      os << "look_scalar_gain_4:" << data._look_scalar_gain_4 << std::endl;
+
+      os << "look_scalar_gain_5:" << data._look_scalar_gain_5 << std::endl;
+
+      os << "look_scalar_gain_6:" << data._look_scalar_gain_6 << std::endl;
+
+      os << "look_scalar_gain_7:" << data._look_scalar_gain_7 << std::endl;
+
+      os << "look_scalar_gain_8:" << data._look_scalar_gain_8 << std::endl;
+
+      os << "samp_window_start_time_bias:" << data._samp_window_start_time_bias << std::endl;
+
+      os << "doppler_centroid_cubic_coeff:" << data._doppler_centroid_cubic_coeff << std::endl;
+
+      os << "PRF_code_first_range_line:" << data._PRF_code_first_range_line << std::endl;
+
+      os << "PRF_code_last_range_line:" << data._PRF_code_last_range_line << std::endl;
+
+      os << "samp_win_start_first:" << data._samp_win_start_first << std::endl;
+
+      os << "samp_win_start_last:" << data._samp_win_start_last << std::endl;
+
+      os << "cal_syst_gain_last_proc:" << data._cal_syst_gain_last_proc << std::endl;
+
+      os << "receiver_gain_last_proc:" << data._receiver_gain_last_proc << std::endl;
+
+      os << "first_processed_range_sample:" << data._first_processed_range_sample << std::endl;
+
+      os << "azimuth_FFT_IFFT_ratio:" << data._azimuth_FFT_IFFT_ratio << std::endl;
+
+      os << "num_azimuth_blocks_proc:" << data._num_azimuth_blocks_proc << std::endl;
+
+      os << "num_input_raw_data_lines:" << data._num_input_raw_data_lines << std::endl;
+
+      os << "initial_doppler_ambiguity_num:" << data._initial_doppler_ambiguity_num << std::endl;
+
+      os << "thresh_no_1_flag:" << data._thresh_no_1_flag << std::endl;
+
+      os << "thresh_no_2_flag:" << data._thresh_no_2_flag << std::endl;
+
+      os << "thresh_no_3_flag:" << data._thresh_no_3_flag << std::endl;
+
+      os << "thresh_no_4_flag:" << data._thresh_no_4_flag << std::endl;
+
+      os << "thresh_no_5_flag:" << data._thresh_no_5_flag << std::endl;
+
+      os << "thresh_no_6_flag:" << data._thresh_no_6_flag << std::endl;
+
+      os << "thresh_no_7_flag:" << data._thresh_no_7_flag << std::endl;
+
+      os << "thresh_no_8_flag:" << data._thresh_no_8_flag << std::endl;
+
+      os << "thresh_no_9_flag:" << data._thresh_no_9_flag << std::endl;
+
+      os << "thresh_no_10_flag:" << data._thresh_no_10_flag << std::endl;
+
+      os << "thresh_no_11_flag:" << data._thresh_no_11_flag << std::endl;
+
+      os << "sat_binary_time_of_first:" << data._sat_binary_time_of_first << std::endl;
+
+      os << "num_valid_pixels_per_range:" << data._num_valid_pixels_per_range << std::endl;
+
+      os << "num_range_samp_discarded:" << data._num_range_samp_discarded << std::endl;
+
+      os << "I_gain_imb_lower_bound:" << data._I_gain_imb_lower_bound << std::endl;
+
+      os << "I_gain_imb_upper_bound:" << data._I_gain_imb_upper_bound << std::endl;
+
+      os << "I_Q_quad_depar_lower_bound:" << data._I_Q_quad_depar_lower_bound << std::endl;
+
+      os << "I_Q_quad_depar_upper_bound:" << data._I_Q_quad_depar_upper_bound << std::endl;
+
+      os << "3_dB_look_bandwidth:" << data._3_dB_look_bandwidth << std::endl;
+
+      os << "3_dB_look_proc_dopp_bandw:" << data._3_dB_look_proc_dopp_bandw << std::endl;
+
+      os << "range_spread_loss_comp_flag:" << data._range_spread_loss_comp_flag << std::endl;
+
+      os << "datation_flag:" << data._datation_flag << std::endl;
+
+      os << "max_error_range_line_timing:" << data._max_error_range_line_timing << std::endl;
+
+      os << "form_num_range_line_used:" << data._form_num_range_line_used << std::endl;
+
+      os << "autom_look_scal_gain_flag:" << data._autom_look_scal_gain_flag << std::endl;
+
+      os << "max_value_look_scalar_gain:" << data._max_value_look_scalar_gain << std::endl;
+
+      os << "replica_norm_method_flag:" << data._replica_norm_method_flag << std::endl;
+
+      os << "coef_ground_range_1:" << data._coef_ground_range_1 << std::endl;
+
+      os << "coef_ground_range_2:" << data._coef_ground_range_2 << std::endl;
+
+      os << "coef_ground_range_3:" << data._coef_ground_range_3 << std::endl;
+
+      os << "coef_ground_range_4:" << data._coef_ground_range_4 << std::endl;
+
+      os << "coef_ant_elev_1:" << data._coef_ant_elev_1 << std::endl;
+
+      os << "coef_ant_elev_2:" << data._coef_ant_elev_2 << std::endl;
+
+      os << "coef_ant_elev_3:" << data._coef_ant_elev_3 << std::endl;
+
+      os << "coef_ant_elev_4:" << data._coef_ant_elev_4 << std::endl;
+
+      os << "coef_ant_elev_5:" << data._coef_ant_elev_5 << std::endl;
+
+      os << "range_time_origin_ant:" << data._range_time_origin_ant << std::endl;
+
+      return os;
+
+   }
+
+   std::istream& operator>>(std::istream& is, ErsSarFacilityData& data)
+   {
+      char buf64[65];
+      buf64[64] = '\0';
+      // char buf32[33];
+      // buf32[32] = '\0';
+      char buf24[25];
+      buf24[24] = '\0';
+      char buf22[23];
+      buf22[22] = '\0';
+      char buf20[21];
+      buf20[20] = '\0';
+      char buf16[17];
+      buf16[16] = '\0';
+      char buf12[13];
+      buf12[12] = '\0';
+      char buf7[8];
+      buf7[7] = '\0';
+      char buf8[9];
+      buf8[8] = '\0';
+      char buf6[7];
+      buf6[6] = '\0';
+      char buf4[5];
+      buf4[4] = '\0';
+      char buf2[3];
+      buf2[2] = '\0';
+      char buf1[2];
+      buf1[1] = '\0';
+
+      is.read(buf64, 64);
+      data._name_of_facil_rec = buf64;
+
+      is.read(buf6, 6);
+      data._last_release_qc_date = buf6;
+
+      is.read(buf2, 2);
+
+      is.read(buf6, 6);
+      data._last_release_cal_date = buf6;
+
+      is.read(buf4, 4);
+      data._qa_summary_flag = atoi(buf4);
+
+      is.read(buf4, 4);
+      data._prf_code_change_flag = atoi(buf4);
+
+      is.read(buf4, 4);
+      data._sampling_win_change_flag = atoi(buf4);
+
+      is.read(buf4, 4);
+      data._cal_gain_change_flag = atoi(buf4);
+
+      is.read(buf4, 4);
+      data._quirp_qu_flag = atoi(buf4);
+
+      is.read(buf4, 4);
+      data._inp_data_stat_flag = atoi(buf4);
+
+      is.read(buf4, 4);
+      data._dopp_cent_conf_meas_flag = atoi(buf4);
+
+      is.read(buf4, 4);
+      data._dopp_cent_val_flag = atoi(buf4);
+
+      is.read(buf4, 4);
+      data._dopp_ambig_conf_meas_flag = atoi(buf4);
+
+      is.read(buf4, 4);
+      data._outp_data_mean_flag = atoi(buf4);
+
+      is.read(buf4, 4);
+      data._OGOB_flag = atoi(buf4);
+
+      is.read(buf4, 4);
+      data._PRF_changes = atoi(buf4);
+
+      is.read(buf4, 4);
+      data._sampling_win_changes = atoi(buf4);
+
+      is.read(buf4, 4);
+      data._cal_gain_changes = atoi(buf4);
+
+      is.read(buf4, 4);
+      data._missing_lines = atoi(buf4);
+
+      is.read(buf4, 4);
+      data._rec_gain_changes = atoi(buf4);
+
+      is.read(buf16, 16);
+      data._pulse_width_of_ACF_3db = atof(buf16);
+
+      is.read(buf16, 16);
+      data._first_side_lobe_lev_of_ACF = atof(buf16);
+
+      is.read(buf16, 16);
+      data._ISLR_of_ACF = atof(buf16);
+
+      is.read(buf16, 16);
+      data._dopp_cent_conf_meas = atof(buf16);
+
+      is.read(buf16, 16);
+      data._dopp_ambig_conf_meas = atof(buf16);
+
+      is.read(buf16, 16);
+      data._inp_data_I_mean = atof(buf16);
+
+      is.read(buf16, 16);
+      data._inp_data_Q_mean = atof(buf16);
+
+      is.read(buf16, 16);
+      data._inp_data_I_stddev = atof(buf16);
+
+      is.read(buf16, 16);
+      data._inp_data_Q_stddev = atof(buf16);
+
+      is.read(buf16, 16);
+      data._cal_sys_gain = atof(buf16);
+
+      is.read(buf16, 16);
+      data._first_rec_gain_read = atof(buf16);
+
+      is.read(buf16, 16);
+      data._dopp_ambig_num = atof(buf16);
+
+      is.read(buf16, 16);
+
+      is.read(buf16, 16);
+      data._I_channel_bias_correction = atof(buf16);
+
+      is.read(buf16, 16);
+      data._Q_channel_bias_correction = atof(buf16);
+
+      is.read(buf16, 16);
+      data._I_channel_gain_correction = atof(buf16);
+
+      is.read(buf16, 16);
+      data._Q_channel_gain_correction = atof(buf16);
+
+      is.read(buf16, 16);
+      data._Q_channel_I_Q_correction = atof(buf16);
+
+      is.read(buf16, 16);
+
+      is.read(buf16, 16);
+      data._noise_power = atof(buf16);
+
+      is.read(buf16, 16);
+      data._int_cal_utc = atoi(buf16);
+
+      is.read(buf4, 4);
+      data._num_valid_cal_pulses = atoi(buf4);
+
+      is.read(buf4, 4);
+      data._num_valid_noise_pulses = atoi(buf4);
+
+      is.read(buf4, 4);
+      data._num_valid_replicas = atoi(buf4);
+
+      is.read(buf16, 16);
+      data._first_replica_sample = atof(buf16);
+
+      is.read(buf16, 16);
+      data._mean_cal_pulse_power = atof(buf16);
+
+      is.read(buf16, 16);
+      data._mean_noise_power = atof(buf16);
+
+      is.read(buf16, 16);
+      data._range_comp_norm_fact = atof(buf16);
+
+      is.read(buf16, 16);
+      data._replica_power = atof(buf16);
+
+      is.read(buf16, 16);
+      data._first_range_pixel_mid_az_inc = atof(buf16);
+
+      is.read(buf16, 16);
+      data._center_range_pix_mid_az_inc = atof(buf16);
+
+      is.read(buf16, 16);
+      data._last_range_pix_mid_az_inc = atof(buf16);
+
+      is.read(buf16, 16);
+      data._norm_ref_range_ro = atof(buf16);
+
+      is.read(buf12, 12);
+
+      is.read(buf4, 4);
+      data._antenna_elev_flag = atoi(buf4);
+
+      is.read(buf16, 16);
+      data._abs_cal_const_K = atof(buf16);
+
+      is.read(buf16, 16);
+      data._upp_bound_K = atof(buf16);
+
+      is.read(buf16, 16);
+      data._low_bound_K = atof(buf16);
+
+      is.read(buf16, 16);
+      data._proc_noise_scale_fact = atof(buf16);
+
+      is.read(buf6, 6);
+      data._K_gen_date = buf6;
+
+      is.read(buf4, 4);
+      data._K_vers_num = buf4;
+
+      is.read(buf4, 4);
+      data._num_duplic_input_lines = atoi(buf4);
+
+      is.read(buf16, 16);
+      data._estim_bit_error_rate = atof(buf16);
+
+      is.read(buf12, 12);
+
+      is.read(buf16, 16);
+      data._out_image_mean = atof(buf16);
+
+      is.read(buf16, 16);
+      data._out_image_std_dev = atof(buf16);
+
+      is.read(buf16, 16);
+      data._out_image_max_value = atof(buf16);
+
+      is.read(buf24, 24);
+      data._time_raw_data_first_input = buf24;
+
+      is.read(buf24, 24);
+      data._time_asc_node_state_vectors = buf24;
+
+      is.read(buf22, 22);
+      data._asc_node_pos_X_comp = buf22;
+
+      is.read(buf22, 22);
+      data._asc_node_pos_Y_comp = buf22;
+
+      is.read(buf22, 22);
+      data._asc_node_pos_Z_comp = buf22;
+
+      is.read(buf22, 22);
+      data._asc_node_vel_X_comp = buf22;
+
+      is.read(buf22, 22);
+      data._asc_node_vel_Y_comp = buf22;
+
+      is.read(buf22, 22);
+      data._asc_node_vel_Z_comp = buf22;
+
+      is.read(buf4, 4);
+      data._out_pixel_bit_length = atoi(buf4);
+
+      is.read(buf16, 16);
+      data._proc_gain_param_1 = atof(buf16);
+
+      is.read(buf16, 16);
+      data._proc_gain_param_2 = atof(buf16);
+
+      is.read(buf16, 16);
+      data._proc_gain_param_3 = atof(buf16);
+
+      is.read(buf4, 4);
+      data._peak_loc_cross_correl_fun = atoi(buf4);
+
+      is.read(buf16, 16);
+      data._3_dB_width_CCF = atof(buf16);
+
+      is.read(buf16, 16);
+      data._first_side_lobe_level = atof(buf16);
+
+      is.read(buf16, 16);
+      data._ISLR_CCF_between_last = atof(buf16);
+
+      is.read(buf4, 4);
+      data._peak_loc_CCF_betw_last = atoi(buf4);
+
+      is.read(buf4, 4);
+      data._Roll_Tilt_Mode_flag = atoi(buf4);
+
+      is.read(buf4, 4);
+      data._raw_data_correction_flag = atoi(buf4);
+
+      is.read(buf4, 4);
+      data._look_detecion_flag = atoi(buf4);
+
+      is.read(buf4, 4);
+      data._doppler_ambiguity_estimat_flag = atoi(buf4);
+
+      is.read(buf4, 4);
+      data._azimuth_baseband_convers_flag = atoi(buf4);
+
+      is.read(buf4, 4);
+      data._samples_per_line_used = atoi(buf4);
+
+      is.read(buf4, 4);
+      data._range_lines_skip_factor = atoi(buf4);
+
+      is.read(buf24, 24);
+      data._time_of_inp_state_vectors = buf24;
+
+      is.read(buf22, 22);
+      data._inp_state_vect_pos_X_comp = buf22;
+
+      is.read(buf22, 22);
+      data._inp_state_vect_pos_Y_comp = buf22;
+
+      is.read(buf22, 22);
+      data._inp_state_vect_pos_Z_comp = buf22;
+
+      is.read(buf22, 22);
+      data._inp_state_vect_vel_Vx_comp = buf22;
+
+      is.read(buf22, 22);
+      data._inp_state_vect_vel_Vy_comp = buf22;
+
+      is.read(buf22, 22);
+      data._inp_state_vect_vel_Vz_comp = buf22;
+
+      is.read(buf4, 4);
+      data._inp_state_vector_type_flag = atoi(buf4);
+
+      is.read(buf16, 16);
+      data._win_coeff_for_range_match = atof(buf16);
+
+      is.read(buf16, 16);
+      data._win_coeff_for_azi_match = atof(buf16);
+
+      is.read(buf4, 4);
+      data._update_period_range_match = atoi(buf4);
+
+      is.read(buf16, 16);
+      data._look_scalar_gain_1 = atof(buf16);
+
+      is.read(buf16, 16);
+      data._look_scalar_gain_2 = atof(buf16);
+
+      is.read(buf16, 16);
+      data._look_scalar_gain_3 = atof(buf16);
+
+      is.read(buf16, 16);
+      data._look_scalar_gain_4 = atof(buf16);
+
+      is.read(buf16, 16);
+      data._look_scalar_gain_5 = atof(buf16);
+
+      is.read(buf16, 16);
+      data._look_scalar_gain_6 = atof(buf16);
+
+      is.read(buf16, 16);
+      data._look_scalar_gain_7 = atof(buf16);
+
+      is.read(buf16, 16);
+      data._look_scalar_gain_8 = atof(buf16);
+
+      is.read(buf4, 4);
+      data._samp_window_start_time_bias = atoi(buf4);
+
+      is.read(buf22, 22);
+      data._doppler_centroid_cubic_coeff = atof(buf22);
+
+      is.read(buf4, 4);
+      data._PRF_code_first_range_line = atoi(buf4);
+
+      is.read(buf4, 4);
+      data._PRF_code_last_range_line = atoi(buf4);
+
+      is.read(buf4, 4);
+      data._samp_win_start_first = atoi(buf4);
+
+      is.read(buf4, 4);
+      data._samp_win_start_last = atoi(buf4);
+
+      is.read(buf4, 4);
+      data._cal_syst_gain_last_proc = atoi(buf4);
+
+      is.read(buf4, 4);
+      data._receiver_gain_last_proc = atoi(buf4);
+
+      is.read(buf4, 4);
+      data._first_processed_range_sample = atoi(buf4);
+
+      is.read(buf4, 4);
+      data._azimuth_FFT_IFFT_ratio = atoi(buf4);
+
+      is.read(buf4, 4);
+      data._num_azimuth_blocks_proc = atoi(buf4);
+
+      is.read(buf8, 8);
+      data._num_input_raw_data_lines = atol(buf8);
+
+      is.read(buf4, 4);
+      data._initial_doppler_ambiguity_num = atoi(buf4);
+
+      is.read(buf16, 16);
+      data._thresh_no_1_flag = atof(buf16);
+
+      is.read(buf16, 16);
+      data._thresh_no_2_flag = atof(buf16);
+
+      is.read(buf16, 16);
+      data._thresh_no_3_flag = atof(buf16);
+
+      is.read(buf16, 16);
+      data._thresh_no_4_flag = atof(buf16);
+
+      is.read(buf16, 16);
+      data._thresh_no_5_flag = atof(buf16);
+
+      is.read(buf16, 16);
+      data._thresh_no_6_flag = atof(buf16);
+
+      is.read(buf16, 16);
+      data._thresh_no_7_flag = atof(buf16);
+
+      is.read(buf16, 16);
+      data._thresh_no_8_flag = atof(buf16);
+
+      is.read(buf16, 16);
+      data._thresh_no_9_flag = atof(buf16);
+
+      is.read(buf16, 16);
+      data._thresh_no_10_flag = atof(buf16);
+
+      is.read(buf16, 16);
+      data._thresh_no_11_flag = atof(buf16);
+
+      is.read(buf16, 16);
+      data._sat_binary_time_of_first = atol(buf16);
+
+      is.read(buf4, 4);
+      data._num_valid_pixels_per_range = atoi(buf4);
+
+      is.read(buf4, 4);
+      data._num_range_samp_discarded = atoi(buf4);
+
+      is.read(buf16, 16);
+      data._I_gain_imb_lower_bound = atof(buf16);
+
+      is.read(buf16, 16);
+      data._I_gain_imb_upper_bound = atof(buf16);
+
+      is.read(buf16, 16);
+      data._I_Q_quad_depar_lower_bound = atof(buf16);
+
+      is.read(buf16, 16);
+      data._I_Q_quad_depar_upper_bound = atof(buf16);
+
+      is.read(buf16, 16);
+      data._3_dB_look_bandwidth = atof(buf16);
+
+      is.read(buf16, 16);
+      data._3_dB_look_proc_dopp_bandw = atof(buf16);
+
+      is.read(buf4, 4);
+      data._range_spread_loss_comp_flag = atoi(buf4);
+
+      is.read(buf1, 1);
+      data._datation_flag = (atoi(buf1) == 0) ? false : true;
+
+      is.read(buf7, 7);
+      data._max_error_range_line_timing = atoi(buf7);
+
+      is.read(buf7, 7);
+      data._form_num_range_line_used = atoi(buf7);
+
+      is.read(buf1, 1);
+      data._autom_look_scal_gain_flag = (atoi(buf1) == 0) ? false : true;
+
+      is.read(buf4, 4);
+      data._max_value_look_scalar_gain = atoi(buf4);
+
+      is.read(buf4, 4);
+      data._replica_norm_method_flag = atoi(buf4);
+
+      is.read(buf20, 20);
+      data._coef_ground_range_1 = atof(buf20);
+
+      is.read(buf20, 20);
+      data._coef_ground_range_2 = atof(buf20);
+
+      is.read(buf20, 20);
+      data._coef_ground_range_3 = atof(buf20);
+
+      is.read(buf20, 20);
+      data._coef_ground_range_4 = atof(buf20);
+
+      is.read(buf20, 20);
+      data._coef_ant_elev_1 = atof(buf20);
+
+      is.read(buf20, 20);
+      data._coef_ant_elev_2 = atof(buf20);
+
+      is.read(buf20, 20);
+      data._coef_ant_elev_3 = atof(buf20);
+
+      is.read(buf20, 20);
+      data._coef_ant_elev_4 = atof(buf20);
+
+      is.read(buf20, 20);
+      data._coef_ant_elev_5 = atof(buf20);
+
+      is.read(buf16, 16);
+      data._range_time_origin_ant = atof(buf16);
+
+      char buf10238[10238];
+      is.read(buf10238, 10238);
+      return is;
+   }
+
+
+   ErsSarFacilityData::ErsSarFacilityData(const ErsSarFacilityData& rhs):
+      ErsSarRecord(rhs),
+      _last_release_qc_date(rhs._last_release_qc_date),
+      _last_release_cal_date(rhs._last_release_cal_date),
+      _qa_summary_flag(rhs._qa_summary_flag),
+      _prf_code_change_flag(rhs._prf_code_change_flag),
+      _sampling_win_change_flag(rhs._sampling_win_change_flag),
+      _cal_gain_change_flag(rhs._cal_gain_change_flag),
+      _quirp_qu_flag(rhs._quirp_qu_flag),
+      _inp_data_stat_flag(rhs._inp_data_stat_flag),
+      _dopp_cent_conf_meas_flag(rhs._dopp_cent_conf_meas_flag),
+      _dopp_cent_val_flag(rhs._dopp_cent_val_flag),
+      _dopp_ambig_conf_meas_flag(rhs._dopp_ambig_conf_meas_flag),
+      _outp_data_mean_flag(rhs._outp_data_mean_flag),
+      _OGOB_flag(rhs._OGOB_flag),
+      _PRF_changes(rhs._PRF_changes),
+      _sampling_win_changes(rhs._sampling_win_changes),
+      _cal_gain_changes(rhs._cal_gain_changes),
+      _missing_lines(rhs._missing_lines),
+      _rec_gain_changes(rhs._rec_gain_changes),
+      _pulse_width_of_ACF_3db(rhs._pulse_width_of_ACF_3db),
+      _first_side_lobe_lev_of_ACF(rhs._first_side_lobe_lev_of_ACF),
+      _ISLR_of_ACF(rhs._ISLR_of_ACF),
+      _dopp_cent_conf_meas(rhs._dopp_cent_conf_meas),
+      _dopp_ambig_conf_meas(rhs._dopp_ambig_conf_meas),
+      _inp_data_I_mean(rhs._inp_data_I_mean),
+      _inp_data_Q_mean(rhs._inp_data_Q_mean),
+      _inp_data_I_stddev(rhs._inp_data_I_stddev),
+      _inp_data_Q_stddev(rhs._inp_data_Q_stddev),
+      _cal_sys_gain(rhs._cal_sys_gain),
+      _first_rec_gain_read(rhs._first_rec_gain_read),
+      _dopp_ambig_num(rhs._dopp_ambig_num),
+      _I_channel_bias_correction(rhs._I_channel_bias_correction),
+      _Q_channel_bias_correction(rhs._Q_channel_bias_correction),
+      _I_channel_gain_correction(rhs._I_channel_gain_correction),
+      _Q_channel_gain_correction(rhs._Q_channel_gain_correction),
+      _Q_channel_I_Q_correction(rhs._Q_channel_I_Q_correction),
+      _noise_power(rhs._noise_power),
+      _int_cal_utc(rhs._int_cal_utc),
+      _num_valid_cal_pulses(rhs._num_valid_cal_pulses),
+      _num_valid_noise_pulses(rhs._num_valid_noise_pulses),
+      _num_valid_replicas(rhs._num_valid_replicas),
+      _first_replica_sample(rhs._first_replica_sample),
+      _mean_cal_pulse_power(rhs._mean_cal_pulse_power),
+      _mean_noise_power(rhs._mean_noise_power),
+      _range_comp_norm_fact(rhs._range_comp_norm_fact),
+      _replica_power(rhs._replica_power),
+      _first_range_pixel_mid_az_inc(rhs._first_range_pixel_mid_az_inc),
+      _center_range_pix_mid_az_inc(rhs._center_range_pix_mid_az_inc),
+      _last_range_pix_mid_az_inc(rhs._last_range_pix_mid_az_inc),
+      _norm_ref_range_ro(rhs._norm_ref_range_ro),
+      _antenna_elev_flag(rhs._antenna_elev_flag),
+      _abs_cal_const_K(rhs._abs_cal_const_K),
+      _upp_bound_K(rhs._upp_bound_K),
+      _low_bound_K(rhs._low_bound_K),
+      _proc_noise_scale_fact(rhs._proc_noise_scale_fact),
+      _K_gen_date(rhs._K_gen_date),
+      _K_vers_num(rhs._K_vers_num),
+      _num_duplic_input_lines(rhs._num_duplic_input_lines),
+      _estim_bit_error_rate(rhs._estim_bit_error_rate),
+      _out_image_mean(rhs._out_image_mean),
+      _out_image_std_dev(rhs._out_image_std_dev),
+      _out_image_max_value(rhs._out_image_max_value),
+      _time_raw_data_first_input(rhs._time_raw_data_first_input),
+      _time_asc_node_state_vectors(rhs._time_asc_node_state_vectors),
+      _asc_node_pos_X_comp(rhs._asc_node_pos_X_comp),
+      _asc_node_pos_Y_comp(rhs._asc_node_pos_Y_comp),
+      _asc_node_pos_Z_comp(rhs._asc_node_pos_Z_comp),
+      _asc_node_vel_X_comp(rhs._asc_node_vel_X_comp),
+      _asc_node_vel_Y_comp(rhs._asc_node_vel_Y_comp),
+      _asc_node_vel_Z_comp(rhs._asc_node_vel_Z_comp),
+      _out_pixel_bit_length(rhs._out_pixel_bit_length),
+      _proc_gain_param_1(rhs._proc_gain_param_1),
+      _proc_gain_param_2(rhs._proc_gain_param_2),
+      _proc_gain_param_3(rhs._proc_gain_param_3),
+      _peak_loc_cross_correl_fun(rhs._peak_loc_cross_correl_fun),
+      _3_dB_width_CCF(rhs._3_dB_width_CCF),
+      _first_side_lobe_level(rhs._first_side_lobe_level),
+      _ISLR_CCF_between_last(rhs._ISLR_CCF_between_last),
+      _peak_loc_CCF_betw_last(rhs._peak_loc_CCF_betw_last),
+      _Roll_Tilt_Mode_flag(rhs._Roll_Tilt_Mode_flag),
+      _raw_data_correction_flag(rhs._raw_data_correction_flag),
+      _look_detecion_flag(rhs._look_detecion_flag),
+      _doppler_ambiguity_estimat_flag(rhs._doppler_ambiguity_estimat_flag),
+      _azimuth_baseband_convers_flag(rhs._azimuth_baseband_convers_flag),
+      _samples_per_line_used(rhs._samples_per_line_used),
+      _range_lines_skip_factor(rhs._range_lines_skip_factor),
+      _time_of_inp_state_vectors(rhs._time_of_inp_state_vectors),
+      _inp_state_vect_pos_X_comp(rhs._inp_state_vect_pos_X_comp),
+      _inp_state_vect_pos_Y_comp(rhs._inp_state_vect_pos_Y_comp),
+      _inp_state_vect_pos_Z_comp(rhs._inp_state_vect_pos_Z_comp),
+      _inp_state_vect_vel_Vx_comp(rhs._inp_state_vect_vel_Vx_comp),
+      _inp_state_vect_vel_Vy_comp(rhs._inp_state_vect_vel_Vy_comp),
+      _inp_state_vect_vel_Vz_comp(rhs._inp_state_vect_vel_Vz_comp),
+      _inp_state_vector_type_flag(rhs._inp_state_vector_type_flag),
+      _win_coeff_for_range_match(rhs._win_coeff_for_range_match),
+      _win_coeff_for_azi_match(rhs._win_coeff_for_azi_match),
+      _update_period_range_match(rhs._update_period_range_match),
+      _look_scalar_gain_1(rhs._look_scalar_gain_1),
+      _look_scalar_gain_2(rhs._look_scalar_gain_2),
+      _look_scalar_gain_3(rhs._look_scalar_gain_3),
+      _look_scalar_gain_4(rhs._look_scalar_gain_4),
+      _look_scalar_gain_5(rhs._look_scalar_gain_5),
+      _look_scalar_gain_6(rhs._look_scalar_gain_6),
+      _look_scalar_gain_7(rhs._look_scalar_gain_7),
+      _look_scalar_gain_8(rhs._look_scalar_gain_8),
+      _samp_window_start_time_bias(rhs._samp_window_start_time_bias),
+      _doppler_centroid_cubic_coeff(rhs._doppler_centroid_cubic_coeff),
+      _PRF_code_first_range_line(rhs._PRF_code_first_range_line),
+      _PRF_code_last_range_line(rhs._PRF_code_last_range_line),
+      _samp_win_start_first(rhs._samp_win_start_first),
+      _samp_win_start_last(rhs._samp_win_start_last),
+      _cal_syst_gain_last_proc(rhs._cal_syst_gain_last_proc),
+      _receiver_gain_last_proc(rhs._receiver_gain_last_proc),
+      _first_processed_range_sample(rhs._first_processed_range_sample),
+      _azimuth_FFT_IFFT_ratio(rhs._azimuth_FFT_IFFT_ratio),
+      _num_azimuth_blocks_proc(rhs._num_azimuth_blocks_proc),
+      _num_input_raw_data_lines(rhs._num_input_raw_data_lines),
+      _initial_doppler_ambiguity_num(rhs._initial_doppler_ambiguity_num),
+      _thresh_no_1_flag(rhs._thresh_no_1_flag),
+      _thresh_no_2_flag(rhs._thresh_no_2_flag),
+      _thresh_no_3_flag(rhs._thresh_no_3_flag),
+      _thresh_no_4_flag(rhs._thresh_no_4_flag),
+      _thresh_no_5_flag(rhs._thresh_no_5_flag),
+      _thresh_no_6_flag(rhs._thresh_no_6_flag),
+      _thresh_no_7_flag(rhs._thresh_no_7_flag),
+      _thresh_no_8_flag(rhs._thresh_no_8_flag),
+      _thresh_no_9_flag(rhs._thresh_no_9_flag),
+      _thresh_no_10_flag(rhs._thresh_no_10_flag),
+      _thresh_no_11_flag(rhs._thresh_no_11_flag),
+      _sat_binary_time_of_first(rhs._sat_binary_time_of_first),
+      _num_valid_pixels_per_range(rhs._num_valid_pixels_per_range),
+      _num_range_samp_discarded(rhs._num_range_samp_discarded),
+      _I_gain_imb_lower_bound(rhs._I_gain_imb_lower_bound),
+      _I_gain_imb_upper_bound(rhs._I_gain_imb_upper_bound),
+      _I_Q_quad_depar_lower_bound(rhs._I_Q_quad_depar_lower_bound),
+      _I_Q_quad_depar_upper_bound(rhs._I_Q_quad_depar_upper_bound),
+      _3_dB_look_bandwidth(rhs._3_dB_look_bandwidth),
+      _3_dB_look_proc_dopp_bandw(rhs._3_dB_look_proc_dopp_bandw),
+      _range_spread_loss_comp_flag(rhs._range_spread_loss_comp_flag),
+      _datation_flag(rhs._datation_flag),
+      _max_error_range_line_timing(rhs._max_error_range_line_timing),
+      _form_num_range_line_used(rhs._form_num_range_line_used),
+      _autom_look_scal_gain_flag(rhs._autom_look_scal_gain_flag),
+      _max_value_look_scalar_gain(rhs._max_value_look_scalar_gain),
+      _replica_norm_method_flag(rhs._replica_norm_method_flag),
+      _coef_ground_range_1(rhs._coef_ground_range_1),
+      _coef_ground_range_2(rhs._coef_ground_range_2),
+      _coef_ground_range_3(rhs._coef_ground_range_3),
+      _coef_ground_range_4(rhs._coef_ground_range_4),
+      _coef_ant_elev_1(rhs._coef_ant_elev_1),
+      _coef_ant_elev_2(rhs._coef_ant_elev_2),
+      _coef_ant_elev_3(rhs._coef_ant_elev_3),
+      _coef_ant_elev_4(rhs._coef_ant_elev_4),
+      _coef_ant_elev_5(rhs._coef_ant_elev_5),
+      _range_time_origin_ant(rhs._range_time_origin_ant)
+   {}
+
+   ErsSarFacilityData& ErsSarFacilityData::operator=(const ErsSarFacilityData& rhs)
+   {
+      _last_release_qc_date = rhs._last_release_qc_date;
+      _last_release_cal_date = rhs._last_release_cal_date;
+      _qa_summary_flag = rhs._qa_summary_flag;
+      _prf_code_change_flag = rhs._prf_code_change_flag;
+      _sampling_win_change_flag = rhs._sampling_win_change_flag;
+      _cal_gain_change_flag = rhs._cal_gain_change_flag;
+      _quirp_qu_flag = rhs._quirp_qu_flag;
+      _inp_data_stat_flag = rhs._inp_data_stat_flag;
+      _dopp_cent_conf_meas_flag = rhs._dopp_cent_conf_meas_flag;
+      _dopp_cent_val_flag = rhs._dopp_cent_val_flag;
+      _dopp_ambig_conf_meas_flag = rhs._dopp_ambig_conf_meas_flag;
+      _outp_data_mean_flag = rhs._outp_data_mean_flag;
+      _OGOB_flag = rhs._OGOB_flag;
+      _PRF_changes = rhs._PRF_changes;
+      _sampling_win_changes = rhs._sampling_win_changes;
+      _cal_gain_changes = rhs._cal_gain_changes;
+      _missing_lines = rhs._missing_lines;
+      _rec_gain_changes = rhs._rec_gain_changes;
+      _pulse_width_of_ACF_3db = rhs._pulse_width_of_ACF_3db;
+      _first_side_lobe_lev_of_ACF = rhs._first_side_lobe_lev_of_ACF;
+      _ISLR_of_ACF = rhs._ISLR_of_ACF;
+      _dopp_cent_conf_meas = rhs._dopp_cent_conf_meas;
+      _dopp_ambig_conf_meas = rhs._dopp_ambig_conf_meas;
+      _inp_data_I_mean = rhs._inp_data_I_mean;
+      _inp_data_Q_mean = rhs._inp_data_Q_mean;
+      _inp_data_I_stddev = rhs._inp_data_I_stddev;
+      _inp_data_Q_stddev = rhs._inp_data_Q_stddev;
+      _cal_sys_gain = rhs._cal_sys_gain;
+      _first_rec_gain_read = rhs._first_rec_gain_read;
+      _dopp_ambig_num = rhs._dopp_ambig_num;
+      _I_channel_bias_correction = rhs._I_channel_bias_correction;
+      _Q_channel_bias_correction = rhs._Q_channel_bias_correction;
+      _I_channel_gain_correction = rhs._I_channel_gain_correction;
+      _Q_channel_gain_correction = rhs._Q_channel_gain_correction;
+      _Q_channel_I_Q_correction = rhs._Q_channel_I_Q_correction;
+      _noise_power = rhs._noise_power;
+      _int_cal_utc = rhs._int_cal_utc;
+      _num_valid_cal_pulses = rhs._num_valid_cal_pulses;
+      _num_valid_noise_pulses = rhs._num_valid_noise_pulses;
+      _num_valid_replicas = rhs._num_valid_replicas;
+      _first_replica_sample = rhs._first_replica_sample;
+      _mean_cal_pulse_power = rhs._mean_cal_pulse_power;
+      _mean_noise_power = rhs._mean_noise_power;
+      _range_comp_norm_fact = rhs._range_comp_norm_fact;
+      _replica_power = rhs._replica_power;
+      _first_range_pixel_mid_az_inc = rhs._first_range_pixel_mid_az_inc;
+      _center_range_pix_mid_az_inc = rhs._center_range_pix_mid_az_inc;
+      _last_range_pix_mid_az_inc = rhs._last_range_pix_mid_az_inc;
+      _norm_ref_range_ro = rhs._norm_ref_range_ro;
+      _antenna_elev_flag = rhs._antenna_elev_flag;
+      _abs_cal_const_K = rhs._abs_cal_const_K;
+      _upp_bound_K = rhs._upp_bound_K;
+      _low_bound_K = rhs._low_bound_K;
+      _proc_noise_scale_fact = rhs._proc_noise_scale_fact;
+      _K_gen_date = rhs._K_gen_date;
+      _K_vers_num = rhs._K_vers_num;
+      _num_duplic_input_lines = rhs._num_duplic_input_lines;
+      _estim_bit_error_rate = rhs._estim_bit_error_rate;
+      _out_image_mean = rhs._out_image_mean;
+      _out_image_std_dev = rhs._out_image_std_dev;
+      _out_image_max_value = rhs._out_image_max_value;
+      _time_raw_data_first_input = rhs._time_raw_data_first_input;
+      _time_asc_node_state_vectors = rhs._time_asc_node_state_vectors;
+      _asc_node_pos_X_comp = rhs._asc_node_pos_X_comp;
+      _asc_node_pos_Y_comp = rhs._asc_node_pos_Y_comp;
+      _asc_node_pos_Z_comp = rhs._asc_node_pos_Z_comp;
+      _asc_node_vel_X_comp = rhs._asc_node_vel_X_comp;
+      _asc_node_vel_Y_comp = rhs._asc_node_vel_Y_comp;
+      _asc_node_vel_Z_comp = rhs._asc_node_vel_Z_comp;
+      _out_pixel_bit_length = rhs._out_pixel_bit_length;
+      _proc_gain_param_1 = rhs._proc_gain_param_1;
+      _proc_gain_param_2 = rhs._proc_gain_param_2;
+      _proc_gain_param_3 = rhs._proc_gain_param_3;
+      _peak_loc_cross_correl_fun = rhs._peak_loc_cross_correl_fun;
+      _3_dB_width_CCF = rhs._3_dB_width_CCF;
+      _first_side_lobe_level = rhs._first_side_lobe_level;
+      _ISLR_CCF_between_last = rhs._ISLR_CCF_between_last;
+      _peak_loc_CCF_betw_last = rhs._peak_loc_CCF_betw_last;
+      _Roll_Tilt_Mode_flag = rhs._Roll_Tilt_Mode_flag;
+      _raw_data_correction_flag = rhs._raw_data_correction_flag;
+      _look_detecion_flag = rhs._look_detecion_flag;
+      _doppler_ambiguity_estimat_flag = rhs._doppler_ambiguity_estimat_flag;
+      _azimuth_baseband_convers_flag = rhs._azimuth_baseband_convers_flag;
+      _samples_per_line_used = rhs._samples_per_line_used;
+      _range_lines_skip_factor = rhs._range_lines_skip_factor;
+      _time_of_inp_state_vectors = rhs._time_of_inp_state_vectors;
+      _inp_state_vect_pos_X_comp = rhs._inp_state_vect_pos_X_comp;
+      _inp_state_vect_pos_Y_comp = rhs._inp_state_vect_pos_Y_comp;
+      _inp_state_vect_pos_Z_comp = rhs._inp_state_vect_pos_Z_comp;
+      _inp_state_vect_vel_Vx_comp = rhs._inp_state_vect_vel_Vx_comp;
+      _inp_state_vect_vel_Vy_comp = rhs._inp_state_vect_vel_Vy_comp;
+      _inp_state_vect_vel_Vz_comp = rhs._inp_state_vect_vel_Vz_comp;
+      _inp_state_vector_type_flag = rhs._inp_state_vector_type_flag;
+      _win_coeff_for_range_match = rhs._win_coeff_for_range_match;
+      _win_coeff_for_azi_match = rhs._win_coeff_for_azi_match;
+      _update_period_range_match = rhs._update_period_range_match;
+      _look_scalar_gain_1 = rhs._look_scalar_gain_1;
+      _look_scalar_gain_2 = rhs._look_scalar_gain_2;
+      _look_scalar_gain_3 = rhs._look_scalar_gain_3;
+      _look_scalar_gain_4 = rhs._look_scalar_gain_4;
+      _look_scalar_gain_5 = rhs._look_scalar_gain_5;
+      _look_scalar_gain_6 = rhs._look_scalar_gain_6;
+      _look_scalar_gain_7 = rhs._look_scalar_gain_7;
+      _look_scalar_gain_8 = rhs._look_scalar_gain_8;
+      _samp_window_start_time_bias = rhs._samp_window_start_time_bias;
+      _doppler_centroid_cubic_coeff = rhs._doppler_centroid_cubic_coeff;
+      _PRF_code_first_range_line = rhs._PRF_code_first_range_line;
+      _PRF_code_last_range_line = rhs._PRF_code_last_range_line;
+      _samp_win_start_first = rhs._samp_win_start_first;
+      _samp_win_start_last = rhs._samp_win_start_last;
+      _cal_syst_gain_last_proc = rhs._cal_syst_gain_last_proc;
+      _receiver_gain_last_proc = rhs._receiver_gain_last_proc;
+      _first_processed_range_sample = rhs._first_processed_range_sample;
+      _azimuth_FFT_IFFT_ratio = rhs._azimuth_FFT_IFFT_ratio;
+      _num_azimuth_blocks_proc = rhs._num_azimuth_blocks_proc;
+      _num_input_raw_data_lines = rhs._num_input_raw_data_lines;
+      _initial_doppler_ambiguity_num = rhs._initial_doppler_ambiguity_num;
+      _thresh_no_1_flag = rhs._thresh_no_1_flag;
+      _thresh_no_2_flag = rhs._thresh_no_2_flag;
+      _thresh_no_3_flag = rhs._thresh_no_3_flag;
+      _thresh_no_4_flag = rhs._thresh_no_4_flag;
+      _thresh_no_5_flag = rhs._thresh_no_5_flag;
+      _thresh_no_6_flag = rhs._thresh_no_6_flag;
+      _thresh_no_7_flag = rhs._thresh_no_7_flag;
+      _thresh_no_8_flag = rhs._thresh_no_8_flag;
+      _thresh_no_9_flag = rhs._thresh_no_9_flag;
+      _thresh_no_10_flag = rhs._thresh_no_10_flag;
+      _thresh_no_11_flag = rhs._thresh_no_11_flag;
+      _sat_binary_time_of_first = rhs._sat_binary_time_of_first;
+      _num_valid_pixels_per_range = rhs._num_valid_pixels_per_range;
+      _num_range_samp_discarded = rhs._num_range_samp_discarded;
+      _I_gain_imb_lower_bound = rhs._I_gain_imb_lower_bound;
+      _I_gain_imb_upper_bound = rhs._I_gain_imb_upper_bound;
+      _I_Q_quad_depar_lower_bound = rhs._I_Q_quad_depar_lower_bound;
+      _I_Q_quad_depar_upper_bound = rhs._I_Q_quad_depar_upper_bound;
+      _3_dB_look_bandwidth = rhs._3_dB_look_bandwidth;
+      _3_dB_look_proc_dopp_bandw = rhs._3_dB_look_proc_dopp_bandw;
+      _range_spread_loss_comp_flag = rhs._range_spread_loss_comp_flag;
+      _datation_flag = rhs._datation_flag;
+      _max_error_range_line_timing = rhs._max_error_range_line_timing;
+      _form_num_range_line_used = rhs._form_num_range_line_used;
+      _autom_look_scal_gain_flag = rhs._autom_look_scal_gain_flag;
+      _max_value_look_scalar_gain = rhs._max_value_look_scalar_gain;
+      _replica_norm_method_flag = rhs._replica_norm_method_flag;
+      _coef_ground_range_1 = rhs._coef_ground_range_1;
+      _coef_ground_range_2 = rhs._coef_ground_range_2;
+      _coef_ground_range_3 = rhs._coef_ground_range_3;
+      _coef_ground_range_4 = rhs._coef_ground_range_4;
+      _coef_ant_elev_1 = rhs._coef_ant_elev_1;
+      _coef_ant_elev_2 = rhs._coef_ant_elev_2;
+      _coef_ant_elev_3 = rhs._coef_ant_elev_3;
+      _coef_ant_elev_4 = rhs._coef_ant_elev_4;
+      _coef_ant_elev_5 = rhs._coef_ant_elev_5;
+      _range_time_origin_ant = rhs._range_time_origin_ant;
+
+      return *this;
+   }
+}
+
diff --git a/ossim_plugins/ossim/erssar/ErsSarFacilityData.h b/ossim_plugins/ossim/erssar/ErsSarFacilityData.h
new file mode 100644
index 0000000..1e9444f
--- /dev/null
+++ b/ossim_plugins/ossim/erssar/ErsSarFacilityData.h
@@ -0,0 +1,1810 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef ErsSarFacilityData_h
+#define ErsSarFacilityData_h
+
+#include <iostream>
+#include <cstdlib>
+#include "erssar/ErsSarRecordHeader.h"
+#include "erssar/ErsSarRecord.h"
+
+namespace ossimplugins
+{
+
+/**
+ * @ingroup ErsSarFacilityDataRecord
+ * @brief This class is able to read the SAR leader data set summary record of the leader file
+ *
+ */
+class ErsSarFacilityData : public ErsSarRecord
+{
+public:
+  /**
+   * @brief Constructor
+   */
+  ErsSarFacilityData();
+
+  /**
+   * @brief Destructor
+   */
+  virtual ~ErsSarFacilityData();
+
+  /**
+   * @brief This function write the ErsSarFacilityData in a stream
+   */
+  friend std::ostream& operator<<(std::ostream& os, const ErsSarFacilityData& data);
+
+  /**
+   * @brief This function read a ErsSarFacilityData from a stream
+   */
+  friend std::istream& operator>>(std::istream& is, ErsSarFacilityData& data);
+
+  /**
+   * @brief Copy constructor
+   */
+  ErsSarFacilityData(const ErsSarFacilityData& rhs);
+
+  /**
+   * @brief Copy operator
+   */
+  ErsSarFacilityData& operator=(const ErsSarFacilityData& rhs);
+
+  /**
+   * @brief This function is able to create a new instance of the class
+   */
+  ErsSarRecord* Instanciate()
+  {
+    return new ErsSarFacilityData();
+  };
+
+  /**
+   * @brief This function is able to create a new instance of the class initialised with the data of the calling instance
+   */
+  ErsSarRecord* Clone()
+  {
+    return new ErsSarFacilityData(*this);
+  };
+
+  /**
+   * @brief Read the class data from a stream
+   */
+  void Read(std::istream& is)
+  {
+    is >> *this;
+  };
+
+  /**
+   * @brief Write the class to a stream
+   */
+  void Write(std::ostream& os)
+  {
+    os << *this;
+  };
+
+  /**
+  * @brief name_of_facil_rec
+  */
+  std::string   get_name_of_facil_rec() const
+  {
+    return _name_of_facil_rec;
+  };
+
+  /**
+  * @brief last_release_qc_date
+  */
+  std::string   get_last_release_qc_date() const
+  {
+    return _last_release_qc_date;
+  };
+  /**
+  * @brief last_release_cal_date
+  */
+  std::string   get_last_release_cal_date() const
+  {
+    return _last_release_cal_date;
+  };
+  /**
+  * @brief qa_summary_flag
+  */
+  int   get_qa_summary_flag() const
+  {
+    return _qa_summary_flag;
+  };
+  /**
+  * @brief prf_code_change_flag
+  */
+  int   get_prf_code_change_flag() const
+  {
+    return _prf_code_change_flag;
+  };
+  /**
+  * @brief sampling_win_change_flag
+  */
+  int   get_sampling_win_change_flag() const
+  {
+    return _sampling_win_change_flag;
+  };
+  /**
+  * @brief cal_gain_change_flag
+  */
+  int   get_cal_gain_change_flag() const
+  {
+    return _cal_gain_change_flag;
+  };
+  /**
+  * @brief quirp_qu_flag
+  */
+  int   get_quirp_qu_flag() const
+  {
+    return _quirp_qu_flag;
+  };
+  /**
+  * @brief inp_data_stat_flag
+  */
+  int   get_inp_data_stat_flag() const
+  {
+    return _inp_data_stat_flag;
+  };
+  /**
+  * @brief dopp_cent_conf_meas_flag
+  */
+  int   get_dopp_cent_conf_meas_flag() const
+  {
+    return _dopp_cent_conf_meas_flag;
+  };
+  /**
+  * @brief dopp_cent_val_flag
+  */
+  int   get_dopp_cent_val_flag() const
+  {
+    return _dopp_cent_val_flag;
+  };
+  /**
+  * @brief dopp_ambig_conf_meas_flag
+  */
+  int   get_dopp_ambig_conf_meas_flag() const
+  {
+    return _dopp_ambig_conf_meas_flag;
+  };
+  /**
+  * @brief outp_data_mean_flag
+  */
+  int   get_outp_data_mean_flag() const
+  {
+    return _outp_data_mean_flag;
+  };
+  /**
+  * @brief OGOB_flag
+  */
+  int   get_OGOB_flag() const
+  {
+    return _OGOB_flag;
+  };
+  /**
+  * @brief PRF_changes
+  */
+  int   get_PRF_changes() const
+  {
+    return _PRF_changes;
+  };
+  /**
+  * @brief sampling_win_changes
+  */
+  int   get_sampling_win_changes() const
+  {
+    return _sampling_win_changes;
+  };
+  /**
+  * @brief cal_gain_changes
+  */
+  int   get_cal_gain_changes() const
+  {
+    return _cal_gain_changes;
+  };
+  /**
+  * @brief missing_lines
+  */
+  int   get_missing_lines() const
+  {
+    return _missing_lines;
+  };
+  /**
+  * @brief rec_gain_changes
+  */
+  int   get_rec_gain_changes() const
+  {
+    return _rec_gain_changes;
+  };
+  /**
+  * @brief pulse_width_of_ACF_3db
+  */
+  double   get_pulse_width_of_ACF_3db() const
+  {
+    return _pulse_width_of_ACF_3db;
+  };
+  /**
+  * @brief first_side_lobe_lev_of_ACF
+  */
+  double   get_first_side_lobe_lev_of_ACF() const
+  {
+    return _first_side_lobe_lev_of_ACF;
+  };
+  /**
+  * @brief ISLR_of_ACF
+  */
+  double   get_ISLR_of_ACF() const
+  {
+    return _ISLR_of_ACF;
+  };
+  /**
+  * @brief dopp_cent_conf_meas
+  */
+  double   get_dopp_cent_conf_meas() const
+  {
+    return _dopp_cent_conf_meas;
+  };
+  /**
+  * @brief dopp_ambig_conf_meas
+  */
+  double   get_dopp_ambig_conf_meas() const
+  {
+    return _dopp_ambig_conf_meas;
+  };
+  /**
+  * @brief inp_data_I_mean
+  */
+  double   get_inp_data_I_mean() const
+  {
+    return _inp_data_I_mean;
+  };
+  /**
+  * @brief inp_data_Q_mean
+  */
+  double   get_inp_data_Q_mean() const
+  {
+    return _inp_data_Q_mean;
+  };
+  /**
+  * @brief inp_data_I_stddev
+  */
+  double   get_inp_data_I_stddev() const
+  {
+    return _inp_data_I_stddev;
+  };
+  /**
+  * @brief inp_data_Q_stddev
+  */
+  double   get_inp_data_Q_stddev() const
+  {
+    return _inp_data_Q_stddev;
+  };
+  /**
+  * @brief cal_sys_gain
+  */
+  double   get_cal_sys_gain() const
+  {
+    return _cal_sys_gain;
+  };
+  /**
+  * @brief first_rec_gain_read
+  */
+  double   get_first_rec_gain_read() const
+  {
+    return _first_rec_gain_read;
+  };
+  /**
+  * @brief dopp_ambig_num
+  */
+  double   get_dopp_ambig_num() const
+  {
+    return _dopp_ambig_num;
+  };
+  /**
+  * @brief I_channel_bias_correction
+  */
+  double   get_I_channel_bias_correction() const
+  {
+    return _I_channel_bias_correction;
+  };
+  /**
+  * @brief Q_channel_bias_correction
+  */
+  double   get_Q_channel_bias_correction() const
+  {
+    return _Q_channel_bias_correction;
+  };
+  /**
+  * @brief I_channel_gain_correction
+  */
+  double   get_I_channel_gain_correction() const
+  {
+    return _I_channel_gain_correction;
+  };
+  /**
+  * @brief Q_channel_gain_correction
+  */
+  double   get_Q_channel_gain_correction() const
+  {
+    return _Q_channel_gain_correction;
+  };
+  /**
+  * @brief Q_channel_I_Q_correction
+  */
+  double   get_Q_channel_I_Q_correction() const
+  {
+    return _Q_channel_I_Q_correction;
+  };
+  /**
+  * @brief noise_power
+  */
+  double   get_noise_power() const
+  {
+    return _noise_power;
+  };
+  /**
+  * @brief int_cal_utc
+  */
+  int   get_int_cal_utc() const
+  {
+    return _int_cal_utc;
+  };
+  /**
+  * @brief num_valid_cal_pulses
+  */
+  int   get_num_valid_cal_pulses() const
+  {
+    return _num_valid_cal_pulses;
+  };
+  /**
+  * @brief num_valid_noise_pulses
+  */
+  int   get_num_valid_noise_pulses() const
+  {
+    return _num_valid_noise_pulses;
+  };
+  /**
+  * @brief num_valid_replicas
+  */
+  int   get_num_valid_replicas() const
+  {
+    return _num_valid_replicas;
+  };
+  /**
+  * @brief first_replica_sample
+  */
+  double   get_first_replica_sample() const
+  {
+    return _first_replica_sample;
+  };
+  /**
+  * @brief mean_cal_pulse_power
+  */
+  double   get_mean_cal_pulse_power() const
+  {
+    return _mean_cal_pulse_power;
+  };
+  /**
+  * @brief mean_noise_power
+  */
+  double   get_mean_noise_power() const
+  {
+    return _mean_noise_power;
+  };
+  /**
+  * @brief range_comp_norm_fact
+  */
+  double   get_range_comp_norm_fact() const
+  {
+    return _range_comp_norm_fact;
+  };
+  /**
+  * @brief replica_power
+  */
+  double   get_replica_power() const
+  {
+    return _replica_power;
+  };
+  /**
+  * @brief first_range_pixel_mid_az_inc
+  */
+  double   get_first_range_pixel_mid_az_inc() const
+  {
+    return _first_range_pixel_mid_az_inc;
+  };
+  /**
+  * @brief center_range_pix_mid_az_inc
+  */
+  double   get_center_range_pix_mid_az_inc() const
+  {
+    return _center_range_pix_mid_az_inc;
+  };
+  /**
+  * @brief last_range_pix_mid_az_inc
+  */
+  double   get_last_range_pix_mid_az_inc() const
+  {
+    return _last_range_pix_mid_az_inc;
+  };
+  /**
+  * @brief norm_ref_range_ro
+  */
+  double   get_norm_ref_range_ro() const
+  {
+    return _norm_ref_range_ro;
+  };
+  /**
+  * @brief antenna_elev_flag
+  */
+  int   get_antenna_elev_flag() const
+  {
+    return _antenna_elev_flag;
+  };
+  /**
+  * @brief abs_cal_const_K
+  */
+  double   get_abs_cal_const_K() const
+  {
+    return _abs_cal_const_K;
+  };
+  /**
+  * @brief upp_bound_K
+  */
+  double   get_upp_bound_K() const
+  {
+    return _upp_bound_K;
+  };
+  /**
+  * @brief low_bound_K
+  */
+  double   get_low_bound_K() const
+  {
+    return _low_bound_K;
+  };
+  /**
+  * @brief proc_noise_scale_fact
+  */
+  double   get_proc_noise_scale_fact() const
+  {
+    return _proc_noise_scale_fact;
+  };
+  /**
+  * @brief K_gen_date
+  */
+  std::string   get_K_gen_date() const
+  {
+    return _K_gen_date;
+  };
+  /**
+  * @brief K_vers_num
+  */
+  std::string   get_K_vers_num() const
+  {
+    return _K_vers_num;
+  };
+  /**
+  * @brief num_duplic_input_lines
+  */
+  int   get_num_duplic_input_lines() const
+  {
+    return _num_duplic_input_lines;
+  };
+  /**
+  * @brief estim_bit_error_rate
+  */
+  double   get_estim_bit_error_rate() const
+  {
+    return _estim_bit_error_rate;
+  };
+  /**
+  * @brief out_image_mean
+  */
+  double   get_out_image_mean() const
+  {
+    return _out_image_mean;
+  };
+  /**
+  * @brief out_image_std_dev
+  */
+  double   get_out_image_std_dev() const
+  {
+    return _out_image_std_dev;
+  };
+  /**
+  * @brief out_image_max_value
+  */
+  double   get_out_image_max_value() const
+  {
+    return _out_image_max_value;
+  };
+  /**
+  * @brief time_raw_data_first_input
+  */
+  std::string   get_time_raw_data_first_input() const
+  {
+    return _time_raw_data_first_input;
+  };
+  /**
+  * @brief time_asc_node_state_vectors
+  */
+  std::string   get_time_asc_node_state_vectors() const
+  {
+    return _time_asc_node_state_vectors;
+  };
+  /**
+  * @brief asc_node_pos_X_comp
+  */
+  std::string   get_asc_node_pos_X_comp() const
+  {
+    return _asc_node_pos_X_comp;
+  };
+  /**
+  * @brief asc_node_pos_Y_comp
+  */
+  std::string   get_asc_node_pos_Y_comp() const
+  {
+    return _asc_node_pos_Y_comp;
+  };
+  /**
+  * @brief asc_node_pos_Z_comp
+  */
+  std::string   get_asc_node_pos_Z_comp() const
+  {
+    return _asc_node_pos_Z_comp;
+  };
+  /**
+  * @brief asc_node_vel_X_comp
+  */
+  std::string   get_asc_node_vel_X_comp() const
+  {
+    return _asc_node_vel_X_comp;
+  };
+  /**
+  * @brief asc_node_vel_Y_comp
+  */
+  std::string   get_asc_node_vel_Y_comp() const
+  {
+    return _asc_node_vel_Y_comp;
+  };
+  /**
+  * @brief asc_node_vel_Z_comp
+  */
+  std::string   get_asc_node_vel_Z_comp() const
+  {
+    return _asc_node_vel_Z_comp;
+  };
+  /**
+  * @brief out_pixel_bit_length
+  */
+  int   get_out_pixel_bit_length() const
+  {
+    return _out_pixel_bit_length;
+  };
+  /**
+  * @brief proc_gain_param_1
+  */
+  double   get_proc_gain_param_1() const
+  {
+    return _proc_gain_param_1;
+  };
+  /**
+  * @brief proc_gain_param_2
+  */
+  double   get_proc_gain_param_2() const
+  {
+    return _proc_gain_param_2;
+  };
+  /**
+  * @brief proc_gain_param_3
+  */
+  double   get_proc_gain_param_3() const
+  {
+    return _proc_gain_param_3;
+  };
+  /**
+  * @brief peak_loc_cross_correl_fun
+  */
+  int   get_peak_loc_cross_correl_fun() const
+  {
+    return _peak_loc_cross_correl_fun;
+  };
+  /**
+  * @brief 3_dB_width_CCF
+  */
+  double   get_3_dB_width_CCF() const
+  {
+    return _3_dB_width_CCF;
+  };
+  /**
+  * @brief first_side_lobe_level
+  */
+  double   get_first_side_lobe_level() const
+  {
+    return _first_side_lobe_level;
+  };
+  /**
+  * @brief ISLR_CCF_between_last
+  */
+  double   get_ISLR_CCF_between_last() const
+  {
+    return _ISLR_CCF_between_last;
+  };
+  /**
+  * @brief peak_loc_CCF_betw_last
+  */
+  int   get_peak_loc_CCF_betw_last() const
+  {
+    return _peak_loc_CCF_betw_last;
+  };
+  /**
+  * @brief Roll_Tilt_Mode_flag
+  */
+  int   get_Roll_Tilt_Mode_flag() const
+  {
+    return _Roll_Tilt_Mode_flag;
+  };
+  /**
+  * @brief raw_data_correction_flag
+  */
+  int   get_raw_data_correction_flag() const
+  {
+    return _raw_data_correction_flag;
+  };
+  /**
+  * @brief look_detecion_flag
+  */
+  int   get_look_detecion_flag() const
+  {
+    return _look_detecion_flag;
+  };
+  /**
+  * @brief doppler_ambiguity_estimat_flag
+  */
+  int   get_doppler_ambiguity_estimat_flag() const
+  {
+    return _doppler_ambiguity_estimat_flag;
+  };
+  /**
+  * @brief azimuth_baseband_convers_flag
+  */
+  int   get_azimuth_baseband_convers_flag() const
+  {
+    return _azimuth_baseband_convers_flag;
+  };
+  /**
+  * @brief samples_per_line_used
+  */
+  int   get_samples_per_line_used() const
+  {
+    return _samples_per_line_used;
+  };
+  /**
+  * @brief range_lines_skip_factor
+  */
+  int   get_range_lines_skip_factor() const
+  {
+    return _range_lines_skip_factor;
+  };
+  /**
+  * @brief time_of_inp_state_vectors
+  */
+  std::string   get_time_of_inp_state_vectors() const
+  {
+    return _time_of_inp_state_vectors;
+  };
+  /**
+  * @brief inp_state_vect_pos_X_comp
+  */
+  std::string   get_inp_state_vect_pos_X_comp() const
+  {
+    return _inp_state_vect_pos_X_comp;
+  };
+  /**
+  * @brief inp_state_vect_pos_Y_comp
+  */
+  std::string   get_inp_state_vect_pos_Y_comp() const
+  {
+    return _inp_state_vect_pos_Y_comp;
+  };
+  /**
+  * @brief inp_state_vect_pos_Z_comp
+  */
+  std::string   get_inp_state_vect_pos_Z_comp() const
+  {
+    return _inp_state_vect_pos_Z_comp;
+  };
+  /**
+  * @brief inp_state_vect_vel_Vx_comp
+  */
+  std::string   get_inp_state_vect_vel_Vx_comp() const
+  {
+    return _inp_state_vect_vel_Vx_comp;
+  };
+  /**
+  * @brief inp_state_vect_vel_Vy_comp
+  */
+  std::string   get_inp_state_vect_vel_Vy_comp() const
+  {
+    return _inp_state_vect_vel_Vy_comp;
+  };
+  /**
+  * @brief inp_state_vect_vel_Vz_comp
+  */
+  std::string   get_inp_state_vect_vel_Vz_comp() const
+  {
+    return _inp_state_vect_vel_Vz_comp;
+  };
+  /**
+  * @brief inp_state_vector_type_flag
+  */
+  int   get_inp_state_vector_type_flag() const
+  {
+    return _inp_state_vector_type_flag;
+  };
+  /**
+  * @brief win_coeff_for_range_match
+  */
+  double   get_win_coeff_for_range_match() const
+  {
+    return _win_coeff_for_range_match;
+  };
+  /**
+  * @brief win_coeff_for_azi_match
+  */
+  double   get_win_coeff_for_azi_match() const
+  {
+    return _win_coeff_for_azi_match;
+  };
+  /**
+  * @brief update_period_range_match
+  */
+  int   get_update_period_range_match() const
+  {
+    return _update_period_range_match;
+  };
+  /**
+  * @brief look_scalar_gain_1
+  */
+  double   get_look_scalar_gain_1() const
+  {
+    return _look_scalar_gain_1;
+  };
+  /**
+  * @brief look_scalar_gain_2
+  */
+  double   get_look_scalar_gain_2() const
+  {
+    return _look_scalar_gain_2;
+  };
+  /**
+  * @brief look_scalar_gain_3
+  */
+  double   get_look_scalar_gain_3() const
+  {
+    return _look_scalar_gain_3;
+  };
+  /**
+  * @brief look_scalar_gain_4
+  */
+  double   get_look_scalar_gain_4() const
+  {
+    return _look_scalar_gain_4;
+  };
+  /**
+  * @brief look_scalar_gain_5
+  */
+  double   get_look_scalar_gain_5() const
+  {
+    return _look_scalar_gain_5;
+  };
+  /**
+  * @brief look_scalar_gain_6
+  */
+  double   get_look_scalar_gain_6() const
+  {
+    return _look_scalar_gain_6;
+  };
+  /**
+  * @brief look_scalar_gain_7
+  */
+  double   get_look_scalar_gain_7() const
+  {
+    return _look_scalar_gain_7;
+  };
+  /**
+  * @brief look_scalar_gain_8
+  */
+  double   get_look_scalar_gain_8() const
+  {
+    return _look_scalar_gain_8;
+  };
+  /**
+  * @brief samp_window_start_time_bias
+  */
+  int   get_samp_window_start_time_bias() const
+  {
+    return _samp_window_start_time_bias;
+  };
+  /**
+  * @brief doppler_centroid_cubic_coeff
+  */
+  double   get_doppler_centroid_cubic_coeff() const
+  {
+    return _doppler_centroid_cubic_coeff;
+  };
+  /**
+  * @brief PRF_code_first_range_line
+  */
+  int   get_PRF_code_first_range_line() const
+  {
+    return _PRF_code_first_range_line;
+  };
+  /**
+  * @brief PRF_code_last_range_line
+  */
+  int   get_PRF_code_last_range_line() const
+  {
+    return _PRF_code_last_range_line;
+  };
+  /**
+  * @brief samp_win_start_first
+  */
+  int   get_samp_win_start_first() const
+  {
+    return _samp_win_start_first;
+  };
+  /**
+  * @brief samp_win_start_last
+  */
+  int   get_samp_win_start_last() const
+  {
+    return _samp_win_start_last;
+  };
+  /**
+  * @brief cal_syst_gain_last_proc
+  */
+  int   get_cal_syst_gain_last_proc() const
+  {
+    return _cal_syst_gain_last_proc;
+  };
+  /**
+  * @brief receiver_gain_last_proc
+  */
+  int   get_receiver_gain_last_proc() const
+  {
+    return _receiver_gain_last_proc;
+  };
+  /**
+  * @brief first_processed_range_sample
+  */
+  int   get_first_processed_range_sample() const
+  {
+    return _first_processed_range_sample;
+  };
+  /**
+  * @brief azimuth_FFT_IFFT_ratio
+  */
+  int   get_azimuth_FFT_IFFT_ratio() const
+  {
+    return _azimuth_FFT_IFFT_ratio;
+  };
+  /**
+  * @brief num_azimuth_blocks_proc
+  */
+  int   get_num_azimuth_blocks_proc() const
+  {
+    return _num_azimuth_blocks_proc;
+  };
+  /**
+  * @brief num_input_raw_data_lines
+  */
+  int   get_num_input_raw_data_lines() const
+  {
+    return _num_input_raw_data_lines;
+  };
+  /**
+  * @brief initial_doppler_ambiguity_num
+  */
+  int   get_initial_doppler_ambiguity_num() const
+  {
+    return _initial_doppler_ambiguity_num;
+  };
+  /**
+  * @brief thresh_no_1_flag
+  */
+  double   get_thresh_no_1_flag() const
+  {
+    return _thresh_no_1_flag;
+  };
+  /**
+  * @brief thresh_no_2_flag
+  */
+  double   get_thresh_no_2_flag() const
+  {
+    return _thresh_no_2_flag;
+  };
+  /**
+  * @brief thresh_no_3_flag
+  */
+  double   get_thresh_no_3_flag() const
+  {
+    return _thresh_no_3_flag;
+  };
+  /**
+  * @brief thresh_no_4_flag
+  */
+  double   get_thresh_no_4_flag() const
+  {
+    return _thresh_no_4_flag;
+  };
+  /**
+  * @brief thresh_no_5_flag
+  */
+  double   get_thresh_no_5_flag() const
+  {
+    return _thresh_no_5_flag;
+  };
+  /**
+  * @brief thresh_no_6_flag
+  */
+  double   get_thresh_no_6_flag() const
+  {
+    return _thresh_no_6_flag;
+  };
+  /**
+  * @brief thresh_no_7_flag
+  */
+  double   get_thresh_no_7_flag() const
+  {
+    return _thresh_no_7_flag;
+  };
+  /**
+  * @brief thresh_no_8_flag
+  */
+  double   get_thresh_no_8_flag() const
+  {
+    return _thresh_no_8_flag;
+  };
+  /**
+  * @brief thresh_no_9_flag
+  */
+  double   get_thresh_no_9_flag() const
+  {
+    return _thresh_no_9_flag;
+  };
+  /**
+  * @brief thresh_no_10_flag
+  */
+  double   get_thresh_no_10_flag() const
+  {
+    return _thresh_no_10_flag;
+  };
+  /**
+  * @brief thresh_no_11_flag
+  */
+  double   get_thresh_no_11_flag() const
+  {
+    return _thresh_no_11_flag;
+  };
+  /**
+  * @brief sat_binary_time_of_first
+  */
+  int   get_sat_binary_time_of_first() const
+  {
+    return _sat_binary_time_of_first;
+  };
+  /**
+  * @brief num_valid_pixels_per_range
+  */
+  int   get_num_valid_pixels_per_range() const
+  {
+    return _num_valid_pixels_per_range;
+  };
+  /**
+  * @brief num_range_samp_discarded
+  */
+  int   get_num_range_samp_discarded() const
+  {
+    return _num_range_samp_discarded;
+  };
+  /**
+  * @brief I_gain_imb_lower_bound
+  */
+  double   get_I_gain_imb_lower_bound() const
+  {
+    return _I_gain_imb_lower_bound;
+  };
+  /**
+  * @brief I_gain_imb_upper_bound
+  */
+  double   get_I_gain_imb_upper_bound() const
+  {
+    return _I_gain_imb_upper_bound;
+  };
+  /**
+  * @brief I_Q_quad_depar_lower_bound
+  */
+  double   get_I_Q_quad_depar_lower_bound() const
+  {
+    return _I_Q_quad_depar_lower_bound;
+  };
+  /**
+  * @brief I_Q_quad_depar_upper_bound
+  */
+  double   get_I_Q_quad_depar_upper_bound() const
+  {
+    return _I_Q_quad_depar_upper_bound;
+  };
+  /**
+  * @brief 3_dB_look_bandwidth
+  */
+  double   get_3_dB_look_bandwidth() const
+  {
+    return _3_dB_look_bandwidth;
+  };
+  /**
+  * @brief 3_dB_look_proc_dopp_bandw
+  */
+  double   get_3_dB_look_proc_dopp_bandw() const
+  {
+    return _3_dB_look_proc_dopp_bandw;
+  };
+  /**
+  * @brief range_spread_loss_comp_flag
+  */
+  int   get_range_spread_loss_comp_flag() const
+  {
+    return _range_spread_loss_comp_flag;
+  };
+  /**
+  * @brief datation_flag
+  */
+  bool   get_datation_flag() const
+  {
+    return _datation_flag;
+  };
+  /**
+  * @brief max_error_range_line_timing
+  */
+  int   get_max_error_range_line_timing() const
+  {
+    return _max_error_range_line_timing;
+  };
+  /**
+  * @brief form_num_range_line_used
+  */
+  int   get_form_num_range_line_used() const
+  {
+    return _form_num_range_line_used;
+  };
+  /**
+  * @brief autom_look_scal_gain_flag
+  */
+  bool   get_autom_look_scal_gain_flag() const
+  {
+    return _autom_look_scal_gain_flag;
+  };
+  /**
+  * @brief max_value_look_scalar_gain
+  */
+  int   get_max_value_look_scalar_gain() const
+  {
+    return _max_value_look_scalar_gain;
+  };
+  /**
+  * @brief replica_norm_method_flag
+  */
+  int   get_replica_norm_method_flag() const
+  {
+    return _replica_norm_method_flag;
+  };
+  /**
+  * @brief coef_ground_range_1
+  */
+  double   get_coef_ground_range_1() const
+  {
+    return _coef_ground_range_1;
+  };
+  /**
+  * @brief coef_ground_range_2
+  */
+  double   get_coef_ground_range_2() const
+  {
+    return _coef_ground_range_2;
+  };
+  /**
+  * @brief coef_ground_range_3
+  */
+  double   get_coef_ground_range_3() const
+  {
+    return _coef_ground_range_3;
+  };
+  /**
+  * @brief coef_ground_range_4
+  */
+  double   get_coef_ground_range_4() const
+  {
+    return _coef_ground_range_4;
+  };
+  /**
+  * @brief coef_ant_elev_1
+  */
+  double   get_coef_ant_elev_1() const
+  {
+    return _coef_ant_elev_1;
+  };
+  /**
+  * @brief coef_ant_elev_2
+  */
+  double   get_coef_ant_elev_2() const
+  {
+    return _coef_ant_elev_2;
+  };
+  /**
+  * @brief coef_ant_elev_3
+  */
+  double   get_coef_ant_elev_3() const
+  {
+    return _coef_ant_elev_3;
+  };
+  /**
+  * @brief coef_ant_elev_4
+  */
+  double   get_coef_ant_elev_4() const
+  {
+    return _coef_ant_elev_4;
+  };
+  /**
+  * @brief coef_ant_elev_5
+  */
+  double   get_coef_ant_elev_5() const
+  {
+    return _coef_ant_elev_5;
+  };
+  /**
+  * @brief range_time_origin_ant
+  */
+  double   get_range_time_origin_ant() const
+  {
+    return _range_time_origin_ant;
+  };
+
+
+protected:
+
+  /**
+  * @brief last_release_qc_date
+  */
+  std::string  _name_of_facil_rec;
+  /**
+  * @brief last_release_qc_date
+  */
+  std::string  _last_release_qc_date;
+  /**
+  * @brief last_release_cal_date
+  */
+  std::string   _last_release_cal_date;
+  /**
+  * @brief qa_summary_flag
+  */
+  int   _qa_summary_flag;
+  /**
+  * @brief prf_code_change_flag
+  */
+  int   _prf_code_change_flag;
+  /**
+  * @brief sampling_win_change_flag
+  */
+  int   _sampling_win_change_flag;
+  /**
+  * @brief cal_gain_change_flag
+  */
+  int   _cal_gain_change_flag;
+  /**
+  * @brief quirp_qu_flag
+  */
+  int   _quirp_qu_flag;
+  /**
+  * @brief inp_data_stat_flag
+  */
+  int   _inp_data_stat_flag;
+  /**
+  * @brief dopp_cent_conf_meas_flag
+  */
+  int   _dopp_cent_conf_meas_flag;
+  /**
+  * @brief dopp_cent_val_flag
+  */
+  int   _dopp_cent_val_flag;
+  /**
+  * @brief dopp_ambig_conf_meas_flag
+  */
+  int   _dopp_ambig_conf_meas_flag;
+  /**
+  * @brief outp_data_mean_flag
+  */
+  int   _outp_data_mean_flag;
+  /**
+  * @brief OGOB_flag
+  */
+  int   _OGOB_flag;
+  /**
+  * @brief PRF_changes
+  */
+  int   _PRF_changes;
+  /**
+  * @brief sampling_win_changes
+  */
+  int   _sampling_win_changes;
+  /**
+  * @brief cal_gain_changes
+  */
+  int   _cal_gain_changes;
+  /**
+  * @brief missing_lines
+  */
+  int   _missing_lines;
+  /**
+  * @brief rec_gain_changes
+  */
+  int   _rec_gain_changes;
+  /**
+  * @brief pulse_width_of_ACF_3db
+  */
+  double   _pulse_width_of_ACF_3db;
+  /**
+  * @brief first_side_lobe_lev_of_ACF
+  */
+  double   _first_side_lobe_lev_of_ACF;
+  /**
+  * @brief ISLR_of_ACF
+  */
+  double   _ISLR_of_ACF;
+  /**
+  * @brief dopp_cent_conf_meas
+  */
+  double   _dopp_cent_conf_meas;
+  /**
+  * @brief dopp_ambig_conf_meas
+  */
+  double   _dopp_ambig_conf_meas;
+  /**
+  * @brief inp_data_I_mean
+  */
+  double   _inp_data_I_mean;
+  /**
+  * @brief inp_data_Q_mean
+  */
+  double   _inp_data_Q_mean;
+  /**
+  * @brief inp_data_I_stddev
+  */
+  double   _inp_data_I_stddev;
+  /**
+  * @brief inp_data_Q_stddev
+  */
+  double   _inp_data_Q_stddev;
+  /**
+  * @brief cal_sys_gain
+  */
+  double   _cal_sys_gain;
+  /**
+  * @brief first_rec_gain_read
+  */
+  double   _first_rec_gain_read;
+  /**
+  * @brief dopp_ambig_num
+  */
+  double   _dopp_ambig_num;
+  /**
+  * @brief I_channel_bias_correction
+  */
+  double   _I_channel_bias_correction;
+  /**
+  * @brief Q_channel_bias_correction
+  */
+  double   _Q_channel_bias_correction;
+  /**
+  * @brief I_channel_gain_correction
+  */
+  double   _I_channel_gain_correction;
+  /**
+  * @brief Q_channel_gain_correction
+  */
+  double   _Q_channel_gain_correction;
+  /**
+  * @brief Q_channel_I_Q_correction
+  */
+  double   _Q_channel_I_Q_correction;
+  /**
+  * @brief noise_power
+  */
+  double   _noise_power;
+  /**
+  * @brief int_cal_utc
+  */
+  int   _int_cal_utc;
+  /**
+  * @brief num_valid_cal_pulses
+  */
+  int   _num_valid_cal_pulses;
+  /**
+  * @brief num_valid_noise_pulses
+  */
+  int   _num_valid_noise_pulses;
+  /**
+  * @brief num_valid_replicas
+  */
+  int   _num_valid_replicas;
+  /**
+  * @brief first_replica_sample
+  */
+  double   _first_replica_sample;
+  /**
+  * @brief mean_cal_pulse_power
+  */
+  double   _mean_cal_pulse_power;
+  /**
+  * @brief mean_noise_power
+  */
+  double   _mean_noise_power;
+  /**
+  * @brief range_comp_norm_fact
+  */
+  double   _range_comp_norm_fact;
+  /**
+  * @brief replica_power
+  */
+  double   _replica_power;
+  /**
+  * @brief first_range_pixel_mid_az_inc
+  */
+  double   _first_range_pixel_mid_az_inc;
+  /**
+  * @brief center_range_pix_mid_az_inc
+  */
+  double   _center_range_pix_mid_az_inc;
+  /**
+  * @brief last_range_pix_mid_az_inc
+  */
+  double   _last_range_pix_mid_az_inc;
+  /**
+  * @brief norm_ref_range_ro
+  */
+  double   _norm_ref_range_ro;
+  /**
+  * @brief antenna_elev_flag
+  */
+  int   _antenna_elev_flag;
+  /**
+  * @brief abs_cal_const_K
+  */
+  double   _abs_cal_const_K;
+  /**
+  * @brief upp_bound_K
+  */
+  double   _upp_bound_K;
+  /**
+  * @brief low_bound_K
+  */
+  double   _low_bound_K;
+  /**
+  * @brief proc_noise_scale_fact
+  */
+  double   _proc_noise_scale_fact;
+  /**
+  * @brief K_gen_date
+  */
+  std::string   _K_gen_date;
+  /**
+  * @brief K_vers_num
+  */
+  std::string   _K_vers_num;
+  /**
+  * @brief num_duplic_input_lines
+  */
+  int   _num_duplic_input_lines;
+  /**
+  * @brief estim_bit_error_rate
+  */
+  double   _estim_bit_error_rate;
+  /**
+  * @brief out_image_mean
+  */
+  double   _out_image_mean;
+  /**
+  * @brief out_image_std_dev
+  */
+  double   _out_image_std_dev;
+  /**
+  * @brief out_image_max_value
+  */
+  double   _out_image_max_value;
+  /**
+  * @brief time_raw_data_first_input
+  */
+  std::string   _time_raw_data_first_input;
+  /**
+  * @brief time_asc_node_state_vectors
+  */
+  std::string   _time_asc_node_state_vectors;
+  /**
+  * @brief asc_node_pos_X_comp
+  */
+  std::string   _asc_node_pos_X_comp;
+  /**
+  * @brief asc_node_pos_Y_comp
+  */
+  std::string   _asc_node_pos_Y_comp;
+  /**
+  * @brief asc_node_pos_Z_comp
+  */
+  std::string   _asc_node_pos_Z_comp;
+  /**
+  * @brief asc_node_vel_X_comp
+  */
+  std::string   _asc_node_vel_X_comp;
+  /**
+  * @brief asc_node_vel_Y_comp
+  */
+  std::string   _asc_node_vel_Y_comp;
+  /**
+  * @brief asc_node_vel_Z_comp
+  */
+  std::string   _asc_node_vel_Z_comp;
+  /**
+  * @brief out_pixel_bit_length
+  */
+  int   _out_pixel_bit_length;
+  /**
+  * @brief proc_gain_param_1
+  */
+  double   _proc_gain_param_1;
+  /**
+  * @brief proc_gain_param_2
+  */
+  double   _proc_gain_param_2;
+  /**
+  * @brief proc_gain_param_3
+  */
+  double   _proc_gain_param_3;
+  /**
+  * @brief peak_loc_cross_correl_fun
+  */
+  int   _peak_loc_cross_correl_fun;
+  /**
+  * @brief 3_dB_width_CCF
+  */
+  double   _3_dB_width_CCF;
+  /**
+  * @brief first_side_lobe_level
+  */
+  double   _first_side_lobe_level;
+  /**
+  * @brief ISLR_CCF_between_last
+  */
+  double   _ISLR_CCF_between_last;
+  /**
+  * @brief peak_loc_CCF_betw_last
+  */
+  int   _peak_loc_CCF_betw_last;
+  /**
+  * @brief Roll_Tilt_Mode_flag
+  */
+  int   _Roll_Tilt_Mode_flag;
+  /**
+  * @brief raw_data_correction_flag
+  */
+  int   _raw_data_correction_flag;
+  /**
+  * @brief look_detecion_flag
+  */
+  int   _look_detecion_flag;
+  /**
+  * @brief doppler_ambiguity_estimat_flag
+  */
+  int   _doppler_ambiguity_estimat_flag;
+  /**
+  * @brief azimuth_baseband_convers_flag
+  */
+  int   _azimuth_baseband_convers_flag;
+  /**
+  * @brief samples_per_line_used
+  */
+  int   _samples_per_line_used;
+  /**
+  * @brief range_lines_skip_factor
+  */
+  int   _range_lines_skip_factor;
+  /**
+  * @brief time_of_inp_state_vectors
+  */
+  std::string   _time_of_inp_state_vectors;
+  /**
+  * @brief inp_state_vect_pos_X_comp
+  */
+  std::string   _inp_state_vect_pos_X_comp;
+  /**
+  * @brief inp_state_vect_pos_Y_comp
+  */
+  std::string   _inp_state_vect_pos_Y_comp;
+  /**
+  * @brief inp_state_vect_pos_Z_comp
+  */
+  std::string   _inp_state_vect_pos_Z_comp;
+  /**
+  * @brief inp_state_vect_vel_Vx_comp
+  */
+  std::string   _inp_state_vect_vel_Vx_comp;
+  /**
+  * @brief inp_state_vect_vel_Vy_comp
+  */
+  std::string   _inp_state_vect_vel_Vy_comp;
+  /**
+  * @brief inp_state_vect_vel_Vz_comp
+  */
+  std::string   _inp_state_vect_vel_Vz_comp;
+  /**
+  * @brief inp_state_vector_type_flag
+  */
+  int   _inp_state_vector_type_flag;
+  /**
+  * @brief win_coeff_for_range_match
+  */
+  double   _win_coeff_for_range_match;
+  /**
+  * @brief win_coeff_for_azi_match
+  */
+  double   _win_coeff_for_azi_match;
+  /**
+  * @brief update_period_range_match
+  */
+  int   _update_period_range_match;
+  /**
+  * @brief look_scalar_gain_1
+  */
+  double   _look_scalar_gain_1;
+  /**
+  * @brief look_scalar_gain_2
+  */
+  double   _look_scalar_gain_2;
+  /**
+  * @brief look_scalar_gain_3
+  */
+  double   _look_scalar_gain_3;
+  /**
+  * @brief look_scalar_gain_4
+  */
+  double   _look_scalar_gain_4;
+  /**
+  * @brief look_scalar_gain_5
+  */
+  double   _look_scalar_gain_5;
+  /**
+  * @brief look_scalar_gain_6
+  */
+  double   _look_scalar_gain_6;
+  /**
+  * @brief look_scalar_gain_7
+  */
+  double   _look_scalar_gain_7;
+  /**
+  * @brief look_scalar_gain_8
+  */
+  double   _look_scalar_gain_8;
+  /**
+  * @brief samp_window_start_time_bias
+  */
+  int   _samp_window_start_time_bias;
+  /**
+  * @brief doppler_centroid_cubic_coeff
+  */
+  double   _doppler_centroid_cubic_coeff;
+  /**
+  * @brief PRF_code_first_range_line
+  */
+  int   _PRF_code_first_range_line;
+  /**
+  * @brief PRF_code_last_range_line
+  */
+  int   _PRF_code_last_range_line;
+  /**
+  * @brief samp_win_start_first
+  */
+  int   _samp_win_start_first;
+  /**
+  * @brief samp_win_start_last
+  */
+  int   _samp_win_start_last;
+  /**
+  * @brief cal_syst_gain_last_proc
+  */
+  int   _cal_syst_gain_last_proc;
+  /**
+  * @brief receiver_gain_last_proc
+  */
+  int   _receiver_gain_last_proc;
+  /**
+  * @brief first_processed_range_sample
+  */
+  int   _first_processed_range_sample;
+  /**
+  * @brief azimuth_FFT_IFFT_ratio
+  */
+  int   _azimuth_FFT_IFFT_ratio;
+  /**
+  * @brief num_azimuth_blocks_proc
+  */
+  int   _num_azimuth_blocks_proc;
+  /**
+  * @brief num_input_raw_data_lines
+  */
+  int   _num_input_raw_data_lines;
+  /**
+  * @brief initial_doppler_ambiguity_num
+  */
+  int   _initial_doppler_ambiguity_num;
+  /**
+  * @brief thresh_no_1_flag
+  */
+  double   _thresh_no_1_flag;
+  /**
+  * @brief thresh_no_2_flag
+  */
+  double   _thresh_no_2_flag;
+  /**
+  * @brief thresh_no_3_flag
+  */
+  double   _thresh_no_3_flag;
+  /**
+  * @brief thresh_no_4_flag
+  */
+  double   _thresh_no_4_flag;
+  /**
+  * @brief thresh_no_5_flag
+  */
+  double   _thresh_no_5_flag;
+  /**
+  * @brief thresh_no_6_flag
+  */
+  double   _thresh_no_6_flag;
+  /**
+  * @brief thresh_no_7_flag
+  */
+  double   _thresh_no_7_flag;
+  /**
+  * @brief thresh_no_8_flag
+  */
+  double   _thresh_no_8_flag;
+  /**
+  * @brief thresh_no_9_flag
+  */
+  double   _thresh_no_9_flag;
+  /**
+  * @brief thresh_no_10_flag
+  */
+  double   _thresh_no_10_flag;
+  /**
+  * @brief thresh_no_11_flag
+  */
+  double   _thresh_no_11_flag;
+  /**
+  * @brief sat_binary_time_of_first
+  */
+  int   _sat_binary_time_of_first;
+  /**
+  * @brief num_valid_pixels_per_range
+  */
+  int   _num_valid_pixels_per_range;
+  /**
+  * @brief num_range_samp_discarded
+  */
+  int   _num_range_samp_discarded;
+  /**
+  * @brief I_gain_imb_lower_bound
+  */
+  double   _I_gain_imb_lower_bound;
+  /**
+  * @brief I_gain_imb_upper_bound
+  */
+  double   _I_gain_imb_upper_bound;
+  /**
+  * @brief I_Q_quad_depar_lower_bound
+  */
+  double   _I_Q_quad_depar_lower_bound;
+  /**
+  * @brief I_Q_quad_depar_upper_bound
+  */
+  double   _I_Q_quad_depar_upper_bound;
+  /**
+  * @brief 3_dB_look_bandwidth
+  */
+  double   _3_dB_look_bandwidth;
+  /**
+  * @brief 3_dB_look_proc_dopp_bandw
+  */
+  double   _3_dB_look_proc_dopp_bandw;
+  /**
+  * @brief range_spread_loss_comp_flag
+  */
+  int   _range_spread_loss_comp_flag;
+  /**
+  * @brief datation_flag
+  */
+  bool   _datation_flag;
+  /**
+  * @brief max_error_range_line_timing
+  */
+  int   _max_error_range_line_timing;
+  /**
+  * @brief form_num_range_line_used
+  */
+  int   _form_num_range_line_used;
+  /**
+  * @brief autom_look_scal_gain_flag
+  */
+  bool   _autom_look_scal_gain_flag;
+  /**
+  * @brief max_value_look_scalar_gain
+  */
+  int   _max_value_look_scalar_gain;
+  /**
+  * @brief replica_norm_method_flag
+  */
+  int   _replica_norm_method_flag;
+  /**
+  * @brief coef_ground_range_1
+  */
+  double   _coef_ground_range_1;
+  /**
+  * @brief coef_ground_range_2
+  */
+  double   _coef_ground_range_2;
+  /**
+  * @brief coef_ground_range_3
+  */
+  double   _coef_ground_range_3;
+  /**
+  * @brief coef_ground_range_4
+  */
+  double   _coef_ground_range_4;
+  /**
+  * @brief coef_ant_elev_1
+  */
+  double   _coef_ant_elev_1;
+  /**
+  * @brief coef_ant_elev_2
+  */
+  double   _coef_ant_elev_2;
+  /**
+  * @brief coef_ant_elev_3
+  */
+  double   _coef_ant_elev_3;
+  /**
+  * @brief coef_ant_elev_4
+  */
+  double   _coef_ant_elev_4;
+  /**
+  * @brief coef_ant_elev_5
+  */
+  double   _coef_ant_elev_5;
+  /**
+  * @brief range_time_origin_ant
+  */
+  double   _range_time_origin_ant;
+
+private:
+
+};
+}
+
+#endif
+
diff --git a/ossim_plugins/ossim/erssar/ErsSarFileDescriptor.cpp b/ossim_plugins/ossim/erssar/ErsSarFileDescriptor.cpp
new file mode 100644
index 0000000..e2bdb28
--- /dev/null
+++ b/ossim_plugins/ossim/erssar/ErsSarFileDescriptor.cpp
@@ -0,0 +1,338 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include "erssar/ErsSarFileDescriptor.h"
+
+
+namespace ossimplugins
+{
+
+ErsSarFileDescriptor::ErsSarFileDescriptor() : ErsSarRecord("sar_desc_rec")
+{
+}
+
+ErsSarFileDescriptor::~ErsSarFileDescriptor()
+{
+}
+
+std::ostream& operator<<(std::ostream& os, const ErsSarFileDescriptor& data)
+{
+  os << "ascii_flag:" << data._ascii_flag.c_str() << std::endl;
+  os << "format_doc:" << data._format_doc.c_str() << std::endl;
+  os << "format_ver:" << data._format_ver.c_str() << std::endl;
+  os << "design_rev:" << data._design_rev.c_str() << std::endl;
+  os << "software_id:" << data._software_id.c_str() << std::endl;
+  os << "file_num:" << data._file_num << std::endl;
+  os << "file_name:" << data._file_name.c_str() << std::endl;
+  os << "rec_seq:" << data._rec_seq.c_str() << std::endl;
+  os << "seq_loc:" << data._seq_loc << std::endl;
+  os << "seq_len:" << data._seq_len << std::endl;
+  os << "rec_code:" << data._rec_code.c_str() << std::endl;
+  os << "code_loc:" << data._code_loc << std::endl;
+  os << "code_len:" << data._code_len << std::endl;
+  os << "rec_len:" << data._rec_len.c_str() << std::endl;
+  os << "rlen_loc:" << data._rlen_loc << std::endl;
+  os << "rlen_len:" << data._rlen_len << std::endl;
+  os << "n_dataset:" << data._n_dataset << std::endl;
+  os << "l_dataset:" << data._l_dataset << std::endl;
+  os << "n_map_proj:" << data._n_map_proj << std::endl;
+  os << "l_map_proj:" << data._l_map_proj << std::endl;
+  os << "n_plat_pos:" << data._n_plat_pos << std::endl;
+  os << "l_plat_pos:" << data._l_plat_pos << std::endl;
+  os << "n_att_data:" << data._n_att_data << std::endl;
+  os << "l_att_data:" << data._l_att_data << std::endl;
+  os << "n_radi_data:" << data._n_radi_data << std::endl;
+  os << "l_radi_data:" << data._l_radi_data << std::endl;
+  os << "n_radi_comp:" << data._n_radi_comp << std::endl;
+  os << "l_radi_comp:" << data._l_radi_comp << std::endl;
+  os << "n_qual_sum:" << data._n_qual_sum << std::endl;
+  os << "l_qual_sum:" << data._l_qual_sum << std::endl;
+  os << "n_data_his:" << data._n_data_his << std::endl;
+  os << "l_data_his:" << data._l_data_his << std::endl;
+  os << "n_rang_spec:" << data._n_rang_spec << std::endl;
+  os << "l_rang_spec:" << data._l_rang_spec << std::endl;
+  os << "n_dem_desc:" << data._n_dem_desc << std::endl;
+  os << "l_dem_desc:" << data._l_dem_desc << std::endl;
+  os << "n_radar_par:" << data._n_radar_par << std::endl;
+  os << "l_radar_par:" << data._l_radar_par << std::endl;
+  os << "n_anno_data:" << data._n_anno_data << std::endl;
+  os << "l_anno_data:" << data._l_anno_data << std::endl;
+  os << "n_det_proc:" << data._n_det_proc << std::endl;
+  os << "l_det_proc:" << data._l_det_proc << std::endl;
+  os << "n_cal:" << data._n_cal << std::endl;
+  os << "l_cal:" << data._l_cal << std::endl;
+  os << "n_gcp:" << data._n_gcp << std::endl;
+  os << "l_gcp:" << data._l_gcp << std::endl;
+  os << "n_fac_data:" << data._n_fac_data << std::endl;
+  os << "l_fac_data:" << data._l_fac_data << std::endl;
+  return os;
+}
+
+std::istream& operator>>(std::istream& is, ErsSarFileDescriptor& data)
+{
+  char buf2[3];
+  buf2[2] = '\0';
+  char buf12[13];
+  buf12[12] = '\0';
+  char buf16[17];
+  buf16[16] = '\0';
+  char buf4[5];
+  buf4[4] = '\0';
+  char buf6[7];
+  buf6[6] = '\0';
+  char buf8[9];
+  buf8[8] = '\0';
+  char buf64[65];
+  buf64[64] = '\0';
+
+  char buf60[61];
+  buf60[60] = '\0';
+
+  char buf288[289];
+  buf288[288] = '\0';
+
+  is.read(buf2, 2);
+  data._ascii_flag = buf2;
+
+  is.read(buf2, 2);
+
+  is.read(buf12, 12);
+  data._format_doc = buf12;
+
+  is.read(buf2, 2);
+  data._format_ver = buf2;
+
+  is.read(buf2, 2);
+  data._design_rev = buf2;
+
+  is.read(buf12, 12);
+  data._software_id = buf12;
+
+  is.read(buf4, 4);
+  data._file_num = atoi(buf4);
+
+  is.read(buf16, 16);
+  data._file_name = buf16;
+
+  is.read(buf4, 4);
+  data._rec_seq = buf4;
+
+  is.read(buf8, 8);
+  data._seq_loc = atoi(buf8);
+
+  is.read(buf4, 4);
+  data._seq_len = atoi(buf4);
+
+  is.read(buf4, 4);
+  data._rec_code = buf4;
+
+  is.read(buf8, 8);
+  data._code_loc = atoi(buf8);
+
+  is.read(buf4, 4);
+  data._code_len = atoi(buf4);
+
+  is.read(buf4, 4);
+  data._rec_len = buf4;
+
+  is.read(buf8, 8);
+  data._rlen_loc = atoi(buf8);
+
+  is.read(buf4, 4);
+  data._rlen_len = atoi(buf4);
+
+  is.read(buf4, 4);
+
+  is.read(buf64, 64);
+
+  is.read(buf6, 6);
+  data._n_dataset = atoi(buf6);
+
+  is.read(buf6, 6);
+  data._l_dataset = atoi(buf6);
+
+  is.read(buf6, 6);
+  data._n_map_proj = atoi(buf6);
+
+  is.read(buf6, 6);
+  data._l_map_proj = atoi(buf6);
+
+  is.read(buf6, 6);
+  data._n_plat_pos = atoi(buf6);
+  is.read(buf6, 6);
+  data._l_plat_pos = atoi(buf6);
+  is.read(buf6, 6);
+  data._n_att_data = atoi(buf6);
+  is.read(buf6, 6);
+  data._l_att_data = atoi(buf6);
+  is.read(buf6, 6);
+  data._n_radi_data = atoi(buf6);
+  is.read(buf6, 6);
+  data._l_radi_data = atoi(buf6);
+  is.read(buf6, 6);
+  data._n_radi_comp = atoi(buf6);
+  is.read(buf6, 6);
+  data._l_radi_comp = atoi(buf6);
+  is.read(buf6, 6);
+  data._n_qual_sum = atoi(buf6);
+  is.read(buf6, 6);
+  data._l_qual_sum = atoi(buf6);
+  is.read(buf6, 6);
+  data._n_data_his = atoi(buf6);
+  is.read(buf6, 6);
+  data._l_data_his = atoi(buf6);
+
+
+
+  is.read(buf6, 6);
+  data._n_rang_spec = atoi(buf6);
+  is.read(buf6, 6);
+  data._l_rang_spec = atoi(buf6);
+  is.read(buf6, 6);
+  data._n_dem_desc = atoi(buf6);
+  is.read(buf6, 6);
+  data._l_dem_desc = atoi(buf6);
+  is.read(buf6, 6);
+  data._n_radar_par = atoi(buf6);
+  is.read(buf6, 6);
+  data._l_radar_par = atoi(buf6);
+  is.read(buf6, 6);
+  data._n_anno_data = atoi(buf6);
+  is.read(buf6, 6);
+  data._l_anno_data = atoi(buf6);
+  is.read(buf6, 6);
+  data._n_det_proc = atoi(buf6);
+  is.read(buf6, 6);
+  data._l_det_proc = atoi(buf6);
+  is.read(buf6, 6);
+  data._n_cal = atoi(buf6);
+  is.read(buf6, 6);
+  data._l_cal = atoi(buf6);
+  is.read(buf6, 6);
+  data._n_gcp = atoi(buf6);
+  is.read(buf6, 6);
+  data._l_gcp = atoi(buf6);
+  is.read(buf60, 60);
+  is.read(buf6, 6);
+  data._n_fac_data = atoi(buf6);
+  is.read(buf6, 6);
+  data._l_fac_data = atoi(buf6);
+  is.read(buf288, 288);
+  return is;
+}
+
+ErsSarFileDescriptor::ErsSarFileDescriptor(const ErsSarFileDescriptor& rhs):
+    ErsSarRecord(rhs),
+    _ascii_flag(rhs._ascii_flag),
+    _format_doc(rhs._format_doc),
+    _format_ver(rhs._format_ver),
+    _design_rev(rhs._design_rev),
+    _software_id(rhs._software_id),
+    _file_num(rhs._file_num),
+    _file_name(rhs._file_name),
+    _rec_seq(rhs._rec_seq),
+    _seq_loc(rhs._seq_loc),
+    _seq_len(rhs._seq_len),
+    _rec_code(rhs._rec_code),
+    _code_loc(rhs._code_loc),
+    _code_len(rhs._code_len),
+    _rec_len(rhs._rec_len),
+    _rlen_loc(rhs._rlen_loc),
+    _rlen_len(rhs._rlen_len),
+    _n_dataset(rhs._n_dataset),
+    _l_dataset(rhs._l_dataset),
+    _n_map_proj(rhs._n_map_proj),
+    _l_map_proj(rhs._l_map_proj),
+    _n_plat_pos(rhs._n_plat_pos),
+    _l_plat_pos(rhs._l_plat_pos),
+    _n_att_data(rhs._n_att_data),
+    _l_att_data(rhs._l_att_data),
+    _n_radi_data(rhs._n_radi_data),
+    _l_radi_data(rhs._l_radi_data),
+    _n_radi_comp(rhs._n_radi_comp),
+    _l_radi_comp(rhs._l_radi_comp),
+    _n_qual_sum(rhs._n_qual_sum),
+    _l_qual_sum(rhs._l_qual_sum),
+    _n_data_his(rhs._n_data_his),
+    _l_data_his(rhs._l_data_his),
+    _n_rang_spec(rhs._n_rang_spec),
+    _l_rang_spec(rhs._l_rang_spec),
+    _n_dem_desc(rhs._n_dem_desc),
+    _l_dem_desc(rhs._l_dem_desc),
+    _n_radar_par(rhs._n_radar_par),
+    _l_radar_par(rhs._l_radar_par),
+    _n_anno_data(rhs._n_anno_data),
+    _l_anno_data(rhs._l_anno_data),
+    _n_det_proc(rhs._n_det_proc),
+    _l_det_proc(rhs._l_det_proc),
+    _n_cal(rhs._n_cal),
+    _l_cal(rhs._l_cal),
+    _n_gcp(rhs._n_gcp),
+    _l_gcp(rhs._l_gcp),
+    _n_fac_data(rhs._n_fac_data),
+    _l_fac_data(rhs._l_fac_data)
+{
+}
+
+ErsSarFileDescriptor& ErsSarFileDescriptor::operator=(const ErsSarFileDescriptor& rhs)
+{
+  _ascii_flag = rhs._ascii_flag;
+  _format_doc = rhs._format_doc;
+  _format_ver = rhs._format_ver;
+  _design_rev = rhs._design_rev;
+  _software_id = rhs._software_id;
+  _file_num = rhs._file_num;
+  _file_name = rhs._file_name;
+  _rec_seq = rhs._rec_seq;
+  _seq_loc = rhs._seq_loc;
+  _seq_len = rhs._seq_len;
+  _rec_code = rhs._rec_code;
+  _code_loc = rhs._code_loc;
+  _code_len = rhs._code_len;
+  _rec_len = rhs._rec_len;
+  _rlen_loc = rhs._rlen_loc;
+  _rlen_len = rhs._rlen_len;
+  _n_dataset = rhs._n_dataset;
+  _l_dataset = rhs._l_dataset;
+  _n_map_proj = rhs._n_map_proj;
+  _l_map_proj = rhs._l_map_proj;
+  _n_plat_pos = rhs._n_plat_pos;
+  _l_plat_pos = rhs._l_plat_pos;
+  _n_att_data = rhs._n_att_data;
+  _l_att_data = rhs._l_att_data;
+  _n_radi_data = rhs._n_radi_data;
+  _l_radi_data = rhs._l_radi_data;
+  _n_radi_comp = rhs._n_radi_comp;
+  _l_radi_comp = rhs._l_radi_comp;
+  _n_qual_sum = rhs._n_qual_sum ;
+  _l_qual_sum = rhs._l_qual_sum;
+  _n_data_his = rhs._n_data_his;
+  _l_data_his = rhs._l_data_his;
+  _n_rang_spec = rhs._n_rang_spec;
+  _l_rang_spec = rhs._l_rang_spec;
+  _n_dem_desc = rhs._n_dem_desc;
+  _l_dem_desc = rhs._l_dem_desc;
+  _n_radar_par = rhs._n_radar_par;
+  _l_radar_par = rhs._l_radar_par;
+  _n_anno_data = rhs._n_anno_data;
+  _l_anno_data = rhs._l_anno_data;
+  _n_det_proc = rhs._n_det_proc;
+  _l_det_proc = rhs._l_det_proc;
+  _n_cal = rhs._n_cal;
+  _l_cal = rhs._l_cal;
+  _n_gcp = rhs._n_gcp;
+  _l_gcp = rhs._l_gcp;
+  _n_fac_data = rhs._n_fac_data;
+  _l_fac_data = rhs._l_fac_data;
+  return *this;
+}
+}
+
diff --git a/ossim_plugins/ossim/erssar/ErsSarFileDescriptor.h b/ossim_plugins/ossim/erssar/ErsSarFileDescriptor.h
new file mode 100644
index 0000000..56caad2
--- /dev/null
+++ b/ossim_plugins/ossim/erssar/ErsSarFileDescriptor.h
@@ -0,0 +1,635 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef ErsSarFileDescriptor_h
+#define ErsSarFileDescriptor_h
+
+
+#include<iostream>
+#include <cstdlib>
+#include "erssar/ErsSarRecordHeader.h"
+#include "erssar/ErsSarRecord.h"
+
+
+namespace ossimplugins
+{
+
+/**
+ * @ingroup SARLeaderErsSarFileDescriptorRecord
+ * @brief This class is able to read the SAR leader file descriptor record of the leader file
+ *
+ */
+class ErsSarFileDescriptor : public ErsSarRecord
+{
+public:
+  /**
+   * @brief Constructor
+   */
+  ErsSarFileDescriptor();
+  /**
+   * @brief Destructor
+   */
+  virtual ~ErsSarFileDescriptor();
+
+  /**
+   * @brief This function write the ErsSarFileDescriptor in a stream
+   */
+  friend std::ostream& operator<<(std::ostream& os, const ErsSarFileDescriptor& data);
+
+  /**
+   * @brief This function read a ErsSarFileDescriptor from a stream
+   */
+  friend std::istream& operator>>(std::istream& is, ErsSarFileDescriptor& data);
+
+  /**
+   * @brief Copy constructor
+   */
+  ErsSarFileDescriptor(const ErsSarFileDescriptor& rhs);
+
+  /**
+   * @brief Copy operator
+   */
+  ErsSarFileDescriptor& operator=(const ErsSarFileDescriptor& rhs);
+
+  /**
+   * @brief This function is able to create a new instance of the class
+   */
+  ErsSarRecord* Instanciate()
+  {
+    return new ErsSarFileDescriptor();
+  };
+
+  /**
+   * @brief This function is able to create a new instance of the class initialised with the data of the calling instance
+   */
+  ErsSarRecord* Clone()
+  {
+    return new ErsSarFileDescriptor(*this);
+  };
+
+  /**
+   * @brief Read the class data from a stream
+   */
+  void Read(std::istream& is)
+  {
+    is >> *this;
+  };
+
+  /**
+   * @brief Write the class to a stream
+   */
+  void Write(std::ostream& os)
+  {
+    os << *this;
+  };
+
+  /**
+   * @brief ASCII flag
+   */
+  std::string get_ascii_flag() const
+  {
+    return _ascii_flag;
+  };
+
+  /**
+   * @brief Format control documentation
+   */
+  std::string get_format_doc() const
+  {
+    return _format_doc;
+  };
+  /**
+   * @brief Format doc version
+   */
+  std::string   get_format_ver() const
+  {
+    return _format_ver;
+  };
+  /**
+   * @brief Format doc revision
+   */
+  std::string   get_design_rev() const
+  {
+    return _design_rev;
+  };
+  /**
+   * @brief Software identifier
+   */
+  std::string   get_software_id() const
+  {
+    return _software_id;
+  };
+  /**
+   * @brief File number
+   */
+  int   get_file_num() const
+  {
+    return _file_num ;
+  };
+  /**
+   * @brief File name
+   */
+  std::string   get_file_name() const
+  {
+    return _file_name;
+  };
+  /**
+   * @brief Record sequence/location flag
+   */
+  std::string   get_rec_seq() const
+  {
+    return _rec_seq;
+  };
+  /**
+   * @brief Sequence number location
+   */
+  int   get_seq_loc() const
+  {
+    return _seq_loc;
+  };
+  /**
+   * @brief Sequence number lenght
+   */
+  int   get_seq_len() const
+  {
+    return _seq_len;
+  };
+  /**
+   * @brief Record code/location flag
+   */
+  std::string   get_rec_code() const
+  {
+    return _rec_code;
+  };
+  /**
+   * @brief Record code location
+   */
+  int   get_code_loc() const
+  {
+    return _code_loc;
+  };
+  /**
+   * @brief Record code length
+   */
+  int   get_code_len() const
+  {
+    return _code_len;
+  };
+  /**
+   * @brief Record length/location flag
+   */
+  std::string get_rec_len() const
+  {
+    return _rec_len;
+  };
+  /**
+   * @brief Record lenght location
+   */
+  int get_rlen_loc() const
+  {
+    return _rlen_loc;
+  };
+  /**
+   * @brief Record length, bytes
+   */
+  int get_rlen_len() const
+  {
+    return _rlen_len;
+  };
+  /**
+   * @brief Number of dataset summ records
+   */
+  int get_n_dataset() const
+  {
+    return _n_dataset;
+  };
+  /**
+   * @brief Data set summary record length, bytes
+   */
+  int get_l_dataset() const
+  {
+    return _l_dataset;
+  };
+  /**
+   * @brief Number of map proj records
+   */
+  int get_n_map_proj() const
+  {
+    return _n_map_proj;
+  };
+  /**
+   * @brief Map projection record length, bytes
+   */
+  int get_l_map_proj() const
+  {
+    return _l_map_proj;
+  };
+  /**
+   * @brief Number of platform position records
+   */
+  int get_n_plat_pos() const
+  {
+    return _n_plat_pos;
+  };
+  /**
+   * @brief Platform position record length, bytes
+   */
+  int get_l_plat_pos() const
+  {
+    return _l_plat_pos;
+  };
+  /**
+   * @brief Number of attitude data records
+   */
+  int get_n_att_data() const
+  {
+    return _n_att_data;
+  };
+  /**
+   * @brief Attitude data record length, bytes
+   */
+  int get_l_att_data() const
+  {
+    return _l_att_data;
+  };
+  /**
+   * @brief Number of radiometric data records
+   */
+  int get_n_radi_data() const
+  {
+    return _n_radi_data;
+  };
+  /**
+   * @brief Radiometric data record length, bytes
+   */
+  int get_l_radi_data() const
+  {
+    return _l_radi_data;
+  };
+  /**
+   * @brief Number of radiometric compensation records
+   */
+  int get_n_radi_comp() const
+  {
+    return _n_radi_comp;
+  };
+  /**
+   *  @brief Radiometric compensation record length, bytes
+   */
+  int get_l_radi_comp() const
+  {
+    return _l_radi_comp;
+  };
+  /**
+   * @brief Number of data quality summary records
+   */
+  int get_n_qual_sum() const
+  {
+    return _n_qual_sum;
+  };
+  /**
+   * @brief Data quality summary record length, bytes
+   */
+  int get_l_qual_sum() const
+  {
+    return _l_qual_sum;
+  };
+  /**
+   * @brief Number of data histogram records
+   */
+  int get_n_data_his() const
+  {
+    return _n_data_his;
+  };
+  /**
+   * @brief Data histogram record length, bytes
+   */
+  int get_l_data_his() const
+  {
+    return _l_data_his;
+  };
+  /**
+   * @brief Number of range spectra records
+   */
+  int get_n_rang_spec() const
+  {
+    return _n_rang_spec ;
+  };
+  /**
+   * @brief Range spectra record length, bytes
+   */
+  int get_l_rang_spec() const
+  {
+    return _l_rang_spec;
+  };
+  /**
+   * @brief Number of DEM descriptor records
+   */
+  int get_n_dem_desc() const
+  {
+    return _n_dem_desc;
+  };
+  /**
+   * @brief DEM desc record length, bytes
+   */
+  int get_l_dem_desc() const
+  {
+    return _l_dem_desc;
+  };
+  /**
+   * @brief Number of RADAR par records
+   */
+  int get_n_radar_par() const
+  {
+    return _n_radar_par;
+  };
+  /**
+   * @brief RADAR par record length, bytes
+   */
+  int get_l_radar_par() const
+  {
+    return _l_radar_par;
+  };
+  /**
+   * @brief Number of annotation data records
+   */
+  int get_n_anno_data() const
+  {
+    return _n_anno_data;
+  };
+  /**
+   * @brief Annotation data record length, bytes
+   */
+  int get_l_anno_data() const
+  {
+    return _l_anno_data;
+  };
+  /**
+   * @brief Number of processing parameter records
+   */
+  int get_n_det_proc() const
+  {
+    return _n_det_proc;
+  };
+  /**
+   * @brief Processing parameter record length, bytes
+   */
+  int get_l_det_proc() const
+  {
+    return _l_det_proc;
+  };
+  /**
+   * @brief Number of calibration records
+   */
+  int get_n_cal() const
+  {
+    return _n_cal;
+  };
+  /**
+   * @brief Calibration record length, bytes
+   */
+  int get_l_cal() const
+  {
+    return _l_cal;
+  };
+  /**
+   * @brief Number of GCP records
+   */
+  int get_n_gcp() const
+  {
+    return _n_gcp;
+  };
+  /**
+   * @brief GCP record length, bytes
+   */
+  int get_l_gcp() const
+  {
+    return _l_gcp;
+  };
+  /**
+   * @brief Number of facility data records
+   */
+  int get_n_fac_data() const
+  {
+    return _n_fac_data;
+  };
+  /**
+   * @brief Fac data record length, bytes
+   */
+  int get_l_fac_data() const
+  {
+    return _l_fac_data;
+  };
+
+protected:
+  /**
+   * @brief ASCII flag
+   */
+  std::string _ascii_flag;
+
+  /**
+   * @brief Format control documentation
+   */
+  std::string _format_doc;
+  /**
+   * @brief Format doc version
+   */
+  std::string   _format_ver;
+  /**
+   * @brief Format doc revision
+   */
+  std::string   _design_rev;
+  /**
+   * @brief Software identifier
+   */
+  std::string   _software_id;
+  /**
+   * @brief File number
+   */
+  int   _file_num;
+  /**
+   * @brief File name
+   */
+  std::string   _file_name;
+  /**
+   * @brief Record sequence/location flag
+   */
+  std::string   _rec_seq;
+  /**
+   * @brief Sequence number location
+   */
+  int   _seq_loc;
+  /**
+   * @brief Sequence number lenght
+   */
+  int   _seq_len;
+  /**
+   * @brief Record code/location flag
+   */
+  std::string   _rec_code;
+  /**
+   * @brief Record code location
+   */
+  int   _code_loc;
+  /**
+   * @brief Record code length
+   */
+  int   _code_len;
+  /**
+   * @brief Record length/location flag
+   */
+  std::string _rec_len;
+  /**
+   * @brief Record lenght location
+   */
+  int _rlen_loc;
+  /**
+   * @brief Record length, bytes
+   */
+  int _rlen_len;
+
+
+  /**
+   * @brief Number of dataset summ records
+   */
+  int _n_dataset;
+  /**
+   * @brief Data set summary record length, bytes
+   */
+  int _l_dataset;
+  /**
+   * @brief Number of map proj records
+   */
+  int _n_map_proj;
+  /**
+   * @brief Map projection record length, bytes
+   */
+  int _l_map_proj;
+  /**
+   * @brief Number of platform position records
+   */
+  int _n_plat_pos;
+  /**
+   * @brief Platform position record length, bytes
+   */
+  int _l_plat_pos;
+  /**
+   * @brief Number of attitude data records
+   */
+  int _n_att_data;
+  /**
+   * @brief Attitude data record length, bytes
+   */
+  int _l_att_data;
+  /**
+   * @brief Number of radiometric data records
+   */
+  int _n_radi_data;
+  /**
+   * @brief Radiometric data record length, bytes
+   */
+  int _l_radi_data;
+  /**
+   * @brief Number of radiometric compensation records
+   */
+  int _n_radi_comp;
+  /**
+   *  @brief Radiometric compensation record length, bytes
+   */
+  int _l_radi_comp;
+  /**
+   * @brief Number of data quality summary records
+   */
+  int _n_qual_sum;
+  /**
+   * @brief Data quality summary record length, bytes
+   */
+  int _l_qual_sum;
+  /**
+   * @brief Number of data histogram records
+   */
+  int _n_data_his;
+  /**
+   * @brief Data histogram record length, bytes
+   */
+  int _l_data_his;
+  /**
+   * @brief Number of range spectra records
+   */
+  int _n_rang_spec;
+  /**
+   * @brief Range spectra record length, bytes
+   */
+  int _l_rang_spec;
+  /**
+   * @brief Number of DEM descriptor records
+   */
+  int _n_dem_desc;
+  /**
+   * @brief DEM desc record length, bytes
+   */
+  int _l_dem_desc;
+  /**
+   * @brief Number of RADAR par records
+   */
+  int _n_radar_par;
+  /**
+   * @brief RADAR par record length, bytes
+   */
+  int _l_radar_par;
+  /**
+   * @brief Number of annotation data records
+   */
+  int _n_anno_data;
+  /**
+   * @brief Annotation data record length, bytes
+   */
+  int _l_anno_data;
+  /**
+   * @brief Number of processing parameter records
+   */
+  int _n_det_proc;
+  /**
+   * @brief Processing parameter record length, bytes
+   */
+  int _l_det_proc;
+  /**
+   * @brief Number of calibration records
+   */
+  int _n_cal;
+  /**
+   * @brief Calibration record length, bytes
+   */
+  int _l_cal;
+  /**
+   * @brief Number of GCP records
+   */
+  int _n_gcp;
+  /**
+   * @brief GCP record length, bytes
+   */
+  int _l_gcp;
+
+  /**
+   * @brief Number of facility data records
+   */
+  int _n_fac_data;
+  /**
+   * @brief Fac data record length, bytes
+   */
+  int _l_fac_data;
+
+private:
+};
+}
+
+#endif
+
diff --git a/ossim_plugins/ossim/erssar/ErsSarLeader.cpp b/ossim_plugins/ossim/erssar/ErsSarLeader.cpp
new file mode 100644
index 0000000..1e70eb9
--- /dev/null
+++ b/ossim_plugins/ossim/erssar/ErsSarLeader.cpp
@@ -0,0 +1,291 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include <cstdio>
+
+#include "erssar/ErsSarLeader.h"
+#include "erssar/ErsSarLeaderFactory.h"
+#include "erssar/ErsSarRecordHeader.h"
+
+#include "erssar/ErsSarFileDescriptor.h"
+#include "erssar/ErsSarDataSetSummary.h"
+#include "erssar/ErsSarMapProjectionData.h"
+#include "erssar/ErsSarFacilityData.h"
+
+#include <ossim/base/ossimTrace.h>
+#include <ossim/base/ossimKeywordlist.h>
+#include <ossim/base/ossimKeywordNames.h>
+
+// Static trace for debugging
+static ossimTrace traceDebug("ossimErsSarLeader:debug");
+
+namespace ossimplugins
+{
+
+const int ErsSarLeader::ErsSarFacilityDataID = 5;
+const int ErsSarLeader::ErsSarPlatformPositionDataID = 4;
+const int ErsSarLeader::ErsSarMapProjectionDataID = 3;
+const int ErsSarLeader::ErsSarDataSetSummaryID = 2;
+const int ErsSarLeader::ErsSarFileDescriptorID = 1;
+
+ErsSarLeader::ErsSarLeader()
+{
+}
+
+ErsSarLeader::~ErsSarLeader()
+{
+  ClearRecords();
+}
+
+std::ostream& operator<<(std::ostream& os, const ErsSarLeader& data)
+{
+  std::map<int, ErsSarRecord*>::const_iterator it = data.theRecords.begin();
+  while (it != data.theRecords.end())
+  {
+    (*it).second->Write(os);
+    ++it;
+  }
+  return os;
+
+}
+
+std::istream& operator>>(std::istream& is, ErsSarLeader& data)
+{
+  ErsSarLeaderFactory factory;
+
+  data.ClearRecords();
+
+  ErsSarRecordHeader header;
+  bool eof = false;
+  while (!eof)
+  {
+    is >> header;
+    if (is.eof())
+    {
+      eof = true;
+    }
+    else
+    {
+      ErsSarRecord* record = factory.Instanciate(header.get_rec_seq());
+      if (record != NULL)
+      {
+        record->Read(is);
+        data.theRecords[header.get_rec_seq()] = record;
+      }
+      else
+      {
+        char* buff = new char[header.get_length()-12];
+        is.read(buff, header.get_length() - 12);
+        delete [] buff;
+      }
+    }
+  }
+  return is;
+}
+
+
+ErsSarLeader::ErsSarLeader(const ErsSarLeader& rhs)
+{
+  std::map<int, ErsSarRecord*>::const_iterator it = rhs.theRecords.begin();
+  while (it != rhs.theRecords.end())
+  {
+    theRecords[(*it).first] = (*it).second->Clone();
+    ++it;
+  }
+}
+
+ErsSarLeader& ErsSarLeader::operator=(const ErsSarLeader& rhs)
+{
+  ClearRecords();
+  std::map<int, ErsSarRecord*>::const_iterator it = rhs.theRecords.begin();
+  while (it != rhs.theRecords.end())
+  {
+    theRecords[(*it).first] = (*it).second->Clone();
+    ++it;
+  }
+
+  return *this;
+}
+
+void ErsSarLeader::ClearRecords()
+{
+  std::map<int, ErsSarRecord*>::const_iterator it = theRecords.begin();
+  while (it != theRecords.end())
+  {
+    delete(*it).second;
+    ++it;
+  }
+  theRecords.clear();
+}
+
+bool ErsSarLeader::saveState(ossimKeywordlist& kwl,
+                             const char* prefix) const
+{
+
+  static const char MODULE[] = "ErsSarLeader::saveState";
+
+  if (traceDebug())
+  {
+    ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " entered...\n";
+  }
+
+  bool result = true;
+
+  char name[64];
+
+  kwl.add(prefix, ossimKeywordNames::TYPE_KW, "ossimErsSarModel", true);
+  /*
+   * Adding metadata necessary to the sensor model in the keywordlist
+   */
+  const ErsSarFileDescriptor *leaderfiledesc = get_ErsSarFileDescriptor();
+  if (leaderfiledesc != NULL)
+  {
+    kwl.add(prefix, "filename", leaderfiledesc->get_file_name().c_str(), true);
+  }
+  else
+  {
+    result = false;
+  }
+
+  /*
+   * Adding metadata necessary to the sensor model in the keywordlist
+   */
+  const ErsSarDataSetSummary *datasetSummary = get_ErsSarDataSetSummary();
+  if ((datasetSummary != NULL) && (result == true))
+  {
+    kwl.add(prefix, "inp_sctim", (datasetSummary->get_inp_sctim()).c_str(), true);
+    kwl.add(prefix, "ellip_maj", datasetSummary->get_ellip_maj(), true);
+    kwl.add(prefix, "ellip_min", datasetSummary->get_ellip_min(), true);
+    kwl.add(prefix, "sc_lin", datasetSummary->get_sc_lin(), true);
+    kwl.add(prefix, "sc_pix", datasetSummary->get_sc_pix(), true);
+    kwl.add(prefix, "wave_length", datasetSummary->get_wave_length(), true);
+    kwl.add(prefix, "fr", datasetSummary->get_fr(), true);
+    kwl.add(prefix, "fa", datasetSummary->get_fa(), true);
+    kwl.add(prefix, "time_dir_pix", (datasetSummary->get_time_dir_pix()).c_str(), true);
+    kwl.add(prefix, "time_dir_lin", (datasetSummary->get_time_dir_lin()).c_str(), true);
+    kwl.add(prefix, "line_spacing", datasetSummary->get_line_spacing(), true);
+    kwl.add(prefix, "pix_spacing", datasetSummary->get_pix_spacing(), true);
+    kwl.add(prefix, "nlooks_az", datasetSummary->get_n_azilok(), true);
+    kwl.add(prefix, "n_rnglok", datasetSummary->get_n_rnglok(), true);
+    kwl.add(prefix, "zero_dop_range_time_f_pixel", datasetSummary->get_zero_dop_range_time_f_pixel(), true);
+    kwl.add(prefix, "zero_dop_range_time_c_pixel", datasetSummary->get_zero_dop_range_time_c_pixel(), true);
+    kwl.add(prefix, "zero_dop_range_time_l_pixel", datasetSummary->get_zero_dop_range_time_l_pixel(), true);
+  }
+  else
+  {
+    result = false;
+  }
+
+  const ErsSarMapProjectionData *mapprojectiondata = get_ErsSarMapProjectionData();
+  if ((mapprojectiondata != NULL) && (result == true))
+  {
+    kwl.add(prefix, "map_proj_des", (mapprojectiondata->get_map_proj_des()).c_str(), true);
+    kwl.add(prefix, "num_lines", (double) mapprojectiondata->get_num_lines(), true);
+    kwl.add(prefix, "num_pix", (double) mapprojectiondata->get_num_pix_in_line(), true);
+    kwl.add(prefix, "first_line_first_pixel_lat", mapprojectiondata->get_first_line_first_pixel_lat(), true);
+    kwl.add(prefix, "first_line_first_pixel_lon", mapprojectiondata->get_first_line_first_pixel_lon(), true);
+    kwl.add(prefix, "first_line_last_pixel_lat", mapprojectiondata->get_first_line_last_pixel_lat(), true);
+    kwl.add(prefix, "first_line_last_pixel_lon", mapprojectiondata->get_first_line_last_pixel_lon(), true);
+    kwl.add(prefix, "last_line_first_pixel_lat", mapprojectiondata->get_last_line_first_pixel_lat(), true);
+    kwl.add(prefix, "last_line_first_pixel_lon", mapprojectiondata->get_last_line_first_pixel_lon(), true);
+    kwl.add(prefix, "last_line_last_pixel_lat", mapprojectiondata->get_last_line_last_pixel_lat(), true);
+    kwl.add(prefix, "last_line_last_pixel_lon", mapprojectiondata->get_last_line_last_pixel_lon(), true);
+  }
+  else
+  {
+    result = false;
+  }
+
+  const ErsSarPlatformPositionData *platformposition = get_ErsSarPlatformPositionData();
+  if ((platformposition != NULL) && (result == true))
+  {
+    kwl.add(prefix, "neph", platformposition->get_ndata(), true);
+    kwl.add(prefix, "eph_year", platformposition->get_year(), true);
+    kwl.add(prefix, "eph_month", platformposition->get_month(), true);
+    kwl.add(prefix, "eph_day", platformposition->get_day(), true);
+    kwl.add(prefix, "eph_gmt_day", platformposition->get_gmt_day(), true);
+    kwl.add(prefix, "eph_sec", platformposition->get_gmt_sec(), true);
+    kwl.add(prefix, "eph_hr_angle", platformposition->get_hr_angle(), true);
+    kwl.add(prefix, "eph_int", platformposition->get_data_int(), true);
+
+    for (int i = 0; i < platformposition->get_ndata(); i++)
+    {
+      sprintf(name, "eph%i_posX", i);
+      kwl.add(prefix, name, (platformposition->get_pos_vect()[i]).get_pos()[0], true);
+      sprintf(name, "eph%i_posY", i);
+      kwl.add(prefix, name, (platformposition->get_pos_vect()[i]).get_pos()[1], true);
+      sprintf(name, "eph%i_posZ", i);
+      kwl.add(prefix, name, (platformposition->get_pos_vect()[i]).get_pos()[2], true);
+
+      sprintf(name, "eph%i_velX", i);
+      kwl.add(prefix, name, (platformposition->get_pos_vect()[i]).get_vel()[0], true);
+      sprintf(name, "eph%i_velY", i);
+      kwl.add(prefix, name, (platformposition->get_pos_vect()[i]).get_vel()[1], true);
+      sprintf(name, "eph%i_velZ", i);
+      kwl.add(prefix, name, (platformposition->get_pos_vect()[i]).get_vel()[2], true);
+    }
+  }
+  else
+  {
+    result = false;
+  }
+  /*
+   * Adding metadata necessary to the sensor model in the keywordlist
+   */
+  const ErsSarFacilityData *facilitydata = get_ErsSarFacilityData();
+  if ((facilitydata != NULL) && (result == true))
+  {
+    kwl.add(prefix, "coef_ground_range_1", facilitydata->get_coef_ground_range_1(), true);
+    kwl.add(prefix, "coef_ground_range_2", facilitydata->get_coef_ground_range_2(), true);
+    kwl.add(prefix, "coef_ground_range_3", facilitydata->get_coef_ground_range_3(), true);
+    kwl.add(prefix, "coef_ground_range_4", facilitydata->get_coef_ground_range_4(), true);
+  }
+  else
+  {
+    result = false;
+  }
+
+
+  if (traceDebug())
+  {
+    ossimNotify(ossimNotifyLevel_DEBUG)
+    << MODULE << " exit status = " << (result ? "true" : "false\n")
+    << std::endl;
+  }
+
+
+  return result;
+}
+
+const ErsSarFacilityData * ErsSarLeader::get_ErsSarFacilityData() const
+{
+  return dynamic_cast<const ErsSarFacilityData*>(theRecords.find(ErsSarFacilityDataID)->second);
+}
+const ErsSarPlatformPositionData * ErsSarLeader::get_ErsSarPlatformPositionData() const
+{
+  return dynamic_cast<const ErsSarPlatformPositionData*>(theRecords.find(ErsSarPlatformPositionDataID)->second);
+}
+const ErsSarMapProjectionData * ErsSarLeader::get_ErsSarMapProjectionData() const
+{
+  return dynamic_cast<const ErsSarMapProjectionData*>(theRecords.find(ErsSarMapProjectionDataID)->second);
+}
+
+const ErsSarDataSetSummary * ErsSarLeader::get_ErsSarDataSetSummary() const
+{
+  return dynamic_cast<const ErsSarDataSetSummary*>(theRecords.find(ErsSarDataSetSummaryID)->second);
+}
+
+const ErsSarFileDescriptor * ErsSarLeader::get_ErsSarFileDescriptor() const
+{
+  return dynamic_cast<const ErsSarFileDescriptor*>(theRecords.find(ErsSarFileDescriptorID)->second);
+}
+}
+
diff --git a/ossim_plugins/ossim/erssar/ErsSarLeader.h b/ossim_plugins/ossim/erssar/ErsSarLeader.h
new file mode 100644
index 0000000..b7c1e16
--- /dev/null
+++ b/ossim_plugins/ossim/erssar/ErsSarLeader.h
@@ -0,0 +1,109 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef ErsSarLeader_h
+#define ErsSarLeader_h
+
+#include <iostream>
+#include "ErsSarFileDescriptor.h"
+#include "ErsSarDataSetSummary.h"
+#include "ErsSarMapProjectionData.h"
+#include "ErsSarPlatformPositionData.h"
+#include "ErsSarFacilityData.h"
+#include <map>
+
+class ossimKeywordlist;
+
+
+namespace ossimplugins
+{
+
+class ErsSarPlatformPositionData;
+class ErsSarMapProjectionData;
+class ErsSarDataSetSummary;
+class ErsSarFileDescriptor;
+class ErsSarFacilityData;
+
+/**
+ * @ingroup ErsSarLeaderFile
+ * @brief This class is able to read the Leader file of the ErsSar file structure
+ *
+ */
+class ErsSarLeader
+{
+public:
+  /**
+   * @brief Constructor
+   */
+  ErsSarLeader();
+
+  /**
+   * @brief Destructor
+   */
+  virtual ~ErsSarLeader();
+
+  /**
+   * @brief This function write the ErsSarLeader in a stream
+   */
+  friend std::ostream& operator<<(std::ostream& os, const ErsSarLeader& data);
+
+  /**
+   * @brief This function read a ErsSarLeader from a stream
+   */
+  friend std::istream& operator>>(std::istream& is, ErsSarLeader& data);
+
+  /**
+   * @brief Copy constructor
+   */
+  ErsSarLeader(const ErsSarLeader& rhs);
+
+  /**
+   * @brief Copy operator
+   */
+  ErsSarLeader& operator=(const ErsSarLeader& rhs);
+
+  /**
+   * @brief Remove all the previous records from the ErsSarLeader
+   */
+  void ClearRecords();
+
+  /**
+   * @brief Method to save object state to a keyword list.
+   * @param kwl Keyword list to save to.
+   * @param prefix added to keys when saved.
+   * @return true on success, false on error.
+   */
+  virtual bool saveState(ossimKeywordlist& kwl,
+                         const char* prefix = 0) const;
+
+  const ErsSarFacilityData * get_ErsSarFacilityData() const;
+  const ErsSarPlatformPositionData * get_ErsSarPlatformPositionData() const;
+  const ErsSarMapProjectionData * get_ErsSarMapProjectionData() const;
+  const ErsSarDataSetSummary * get_ErsSarDataSetSummary() const;
+  const ErsSarFileDescriptor * get_ErsSarFileDescriptor() const;
+
+protected:
+  // Made mutable because the get_* methods need to access it.
+  // (modifying the definition of the map might be another solution)
+  mutable std::map<int, ErsSarRecord*> theRecords;
+
+  static const int ErsSarFacilityDataID;
+  static const int ErsSarPlatformPositionDataID;
+  static const int ErsSarMapProjectionDataID;
+  static const int ErsSarDataSetSummaryID;
+  static const int ErsSarFileDescriptorID;
+private:
+
+};
+}
+
+#endif
+
diff --git a/ossim_plugins/ossim/erssar/ErsSarLeaderFactory.cpp b/ossim_plugins/ossim/erssar/ErsSarLeaderFactory.cpp
new file mode 100644
index 0000000..3b6c236
--- /dev/null
+++ b/ossim_plugins/ossim/erssar/ErsSarLeaderFactory.cpp
@@ -0,0 +1,48 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include "erssar/ErsSarLeaderFactory.h"
+
+#include "erssar/ErsSarDataSetSummary.h"
+#include "erssar/ErsSarFileDescriptor.h"
+#include "erssar/ErsSarMapProjectionData.h"
+#include "erssar/ErsSarPlatformPositionData.h"
+#include "erssar/ErsSarFacilityData.h"
+
+namespace ossimplugins
+{
+
+ErsSarLeaderFactory::ErsSarLeaderFactory()
+{
+  RegisterRecord(5, new ErsSarFacilityData());
+  RegisterRecord(4, new ErsSarPlatformPositionData());
+  RegisterRecord(3, new ErsSarMapProjectionData());
+  RegisterRecord(2, new ErsSarDataSetSummary());
+  RegisterRecord(1, new ErsSarFileDescriptor());
+}
+
+ErsSarLeaderFactory::~ErsSarLeaderFactory()
+{
+  std::map<int, ErsSarRecord*>::iterator i = _availableRecords.begin();
+
+  while (i != _availableRecords.end())
+  {
+    if ((*i).second)
+    {
+      delete(*i).second;
+      (*i).second = 0;
+    }
+    ++i;
+  }
+  _availableRecords.clear();
+}
+}
+
diff --git a/ossim_plugins/ossim/erssar/ErsSarLeaderFactory.h b/ossim_plugins/ossim/erssar/ErsSarLeaderFactory.h
new file mode 100644
index 0000000..d395056
--- /dev/null
+++ b/ossim_plugins/ossim/erssar/ErsSarLeaderFactory.h
@@ -0,0 +1,49 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef ErsSarLeaderFactory_h
+#define ErsSarLeaderFactory_h
+
+
+#include "erssar/ErsSarRecordFactory.h"
+#include <map>
+
+
+namespace ossimplugins
+{
+
+/**
+ * @ingroup ErsSarLeaderFile
+ * @brief This class is a facory able to construct Record base classes
+ *
+ */
+class ErsSarLeaderFactory : public ErsSarRecordFactory
+{
+public:
+  /**
+   * @brief Contstructor
+   */
+  ErsSarLeaderFactory();
+  /**
+   * @brief Destructor
+   */
+  virtual ~ErsSarLeaderFactory();
+
+
+protected:
+
+
+private:
+};
+}
+
+#endif
+
diff --git a/ossim_plugins/ossim/erssar/ErsSarMapProjectionData.cpp b/ossim_plugins/ossim/erssar/ErsSarMapProjectionData.cpp
new file mode 100644
index 0000000..9cc112a
--- /dev/null
+++ b/ossim_plugins/ossim/erssar/ErsSarMapProjectionData.cpp
@@ -0,0 +1,210 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include "erssar/ErsSarMapProjectionData.h"
+
+namespace ossimplugins
+{
+
+   ErsSarMapProjectionData::ErsSarMapProjectionData() : ErsSarRecord("map_proj_data_rec")
+   {
+   }
+
+   ErsSarMapProjectionData::~ErsSarMapProjectionData()
+   {
+   }
+
+   std::ostream& operator<<(std::ostream& os, const ErsSarMapProjectionData& data)
+   {
+      os << "map_proj_des:" << data._map_proj_des.c_str() << std::endl;
+
+      os << "num_pix_in_line:" << data._num_pix_in_line << std::endl;
+
+      os << "num_lines:" << data._num_lines << std::endl;
+
+      os << "nom_interpixel_dist:" << data._nom_interpixel_dist << std::endl;
+
+      os << "nom_interline_dist:" << data._nom_interline_dist << std::endl;
+
+      os << "orientation_at_center:" << data._orientation_at_center << std::endl;
+
+      os << "orbit_incl:" << data._orbit_incl << std::endl;
+
+      os << "asc_node_long:" << data._asc_node_long << std::endl;
+
+      os << "platform_heading:" << data._platform_heading << std::endl;
+
+      os << "name_of_ref_ellipsoid:" << data._name_of_ref_ellipsoid.c_str() << std::endl;
+
+      os << "semi_maj_axis:" << data._semi_maj_axis << std::endl;
+
+      os << "semi_min_axis:" << data._semi_min_axis << std::endl;
+
+      os << "first_line_first_pixel_lat:" << data._first_line_first_pixel_lat << std::endl;
+
+      os << "first_line_first_pixel_lon:" << data._first_line_first_pixel_lon << std::endl;
+
+      os << "first_line_last_pixel_lat:" << data._first_line_last_pixel_lat << std::endl;
+
+      os << "first_line_last_pixel_lon:" << data._first_line_last_pixel_lon << std::endl;
+
+      os << "last_line_last_pixel_lat:" << data._last_line_last_pixel_lat << std::endl;
+
+      os << "last_line_last_pixel_lon:" << data._last_line_last_pixel_lon << std::endl;
+
+      os << "last_line_first_pixel_lat:" << data._last_line_first_pixel_lat << std::endl;
+
+      os << "last_line_first_pixel_lon:" << data._last_line_first_pixel_lon << std::endl;
+
+      return os;
+
+   }
+
+   std::istream& operator>>(std::istream& is, ErsSarMapProjectionData& data)
+   {
+      char buf16[17];
+      buf16[16] = '\0';
+      char buf32[33];
+      buf32[32] = '\0';
+      // char buf8[9];
+      // buf8[8] = '\0';
+      // char buf4[5];
+      // buf4[4] = '\0';
+
+      is.read(buf16, 16);
+
+      is.read(buf32, 32);
+      data._map_proj_des = buf32;
+
+      is.read(buf16, 16);
+      data._num_pix_in_line = atoi(buf16);
+
+      is.read(buf16, 16);
+      data._num_lines = atoi(buf16);
+
+      is.read(buf16, 16);
+      data._nom_interpixel_dist = atof(buf16);
+
+      is.read(buf16, 16);
+      data._nom_interline_dist = atof(buf16);
+
+      is.read(buf16, 16);
+      data._orientation_at_center = atof(buf16);
+
+      is.read(buf16, 16);
+      data._orbit_incl = atof(buf16);
+
+      is.read(buf16, 16);
+      data._asc_node_long = atof(buf16);
+
+      is.read(buf16, 16);
+
+      is.read(buf16, 16);
+
+      is.read(buf16, 16);
+
+      is.read(buf16, 16);
+      data._platform_heading = atof(buf16);
+
+      is.read(buf32, 32);
+      data._name_of_ref_ellipsoid = buf32;
+
+      is.read(buf16, 16);
+      data._semi_maj_axis = atof(buf16);
+
+      is.read(buf16, 16);
+      data._semi_min_axis = atof(buf16);
+
+      char buf772[772];
+      is.read(buf772, 772);
+
+      is.read(buf16, 16);
+      data._first_line_first_pixel_lat = atof(buf16);
+
+      is.read(buf16, 16);
+      data._first_line_first_pixel_lon = atof(buf16);
+
+      is.read(buf16, 16);
+      data._first_line_last_pixel_lat = atof(buf16);
+
+      is.read(buf16, 16);
+      data._first_line_last_pixel_lon = atof(buf16);
+
+      is.read(buf16, 16);
+      data._last_line_last_pixel_lat = atof(buf16);
+
+      is.read(buf16, 16);
+      data._last_line_last_pixel_lon = atof(buf16);
+
+      is.read(buf16, 16);
+      data._last_line_first_pixel_lat = atof(buf16);
+
+      is.read(buf16, 16);
+      data._last_line_first_pixel_lon = atof(buf16);
+
+      char buf420[420];
+      is.read(buf420, 420);
+
+      return is;
+   }
+
+
+   ErsSarMapProjectionData::ErsSarMapProjectionData(const ErsSarMapProjectionData& rhs):
+      ErsSarRecord(rhs),
+      _map_proj_des(rhs._map_proj_des),
+      _num_pix_in_line(rhs._num_pix_in_line),
+      _num_lines(rhs._num_lines),
+      _nom_interpixel_dist(rhs._nom_interpixel_dist),
+      _nom_interline_dist(rhs._nom_interline_dist),
+      _orientation_at_center(rhs._orientation_at_center),
+      _orbit_incl(rhs._orbit_incl),
+      _asc_node_long(rhs._asc_node_long),
+      _platform_heading(rhs._platform_heading),
+      _name_of_ref_ellipsoid(rhs._name_of_ref_ellipsoid),
+      _semi_maj_axis(rhs._semi_maj_axis),
+      _semi_min_axis(rhs._semi_min_axis),
+      _first_line_first_pixel_lat(rhs._first_line_first_pixel_lat),
+      _first_line_first_pixel_lon(rhs._first_line_first_pixel_lon),
+      _first_line_last_pixel_lat(rhs._first_line_last_pixel_lat),
+      _first_line_last_pixel_lon(rhs._first_line_last_pixel_lon),
+      _last_line_last_pixel_lat(rhs._last_line_last_pixel_lat),
+      _last_line_last_pixel_lon(rhs._last_line_last_pixel_lon),
+      _last_line_first_pixel_lat(rhs._last_line_first_pixel_lat),
+      _last_line_first_pixel_lon(rhs._last_line_first_pixel_lon)
+   {}
+
+   ErsSarMapProjectionData& ErsSarMapProjectionData::operator=(const ErsSarMapProjectionData& rhs)
+   {
+      _map_proj_des = rhs._map_proj_des;
+      _num_pix_in_line = rhs._num_pix_in_line;
+      _num_lines = rhs._num_lines;
+      _nom_interpixel_dist = rhs._nom_interpixel_dist;
+      _nom_interline_dist = rhs._nom_interline_dist;
+      _orientation_at_center = rhs._orientation_at_center;
+      _orbit_incl = rhs._orbit_incl;
+      _asc_node_long = rhs._asc_node_long;
+      _platform_heading = rhs._platform_heading;
+      _name_of_ref_ellipsoid = rhs._name_of_ref_ellipsoid;
+      _semi_maj_axis = rhs._semi_maj_axis;
+      _semi_min_axis = rhs._semi_min_axis;
+      _first_line_first_pixel_lat = rhs._first_line_first_pixel_lat;
+      _first_line_first_pixel_lon = rhs._first_line_first_pixel_lon;
+      _first_line_last_pixel_lat = rhs._first_line_last_pixel_lat;
+      _first_line_last_pixel_lon = rhs._first_line_last_pixel_lon;
+      _last_line_last_pixel_lat = rhs._last_line_last_pixel_lat;
+      _last_line_last_pixel_lon = rhs._last_line_last_pixel_lon;
+      _last_line_first_pixel_lat = rhs._last_line_first_pixel_lat;
+      _last_line_first_pixel_lon = rhs._last_line_first_pixel_lon;
+
+      return *this;
+   }
+}
+
diff --git a/ossim_plugins/ossim/erssar/ErsSarMapProjectionData.h b/ossim_plugins/ossim/erssar/ErsSarMapProjectionData.h
new file mode 100644
index 0000000..39af641
--- /dev/null
+++ b/ossim_plugins/ossim/erssar/ErsSarMapProjectionData.h
@@ -0,0 +1,324 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef ErsSarMapProjectionData_h
+#define ErsSarMapProjectionData_h
+
+#include <iostream>
+#include <cstdlib>
+#include "erssar/ErsSarRecordHeader.h"
+#include "erssar/ErsSarRecord.h"
+
+namespace ossimplugins
+{
+
+
+/**
+ * @ingroup ErsSarMapProjectionDataRecord
+ * @brief This class is able to read the SAR leader data set summary record of the leader file
+ *
+ */
+class ErsSarMapProjectionData : public ErsSarRecord
+{
+public:
+  /**
+   * @brief Constructor
+   */
+  ErsSarMapProjectionData();
+
+  /**
+   * @brief Destructor
+   */
+  virtual ~ErsSarMapProjectionData();
+
+  /**
+   * @brief This function write the ErsSarMapProjectionData in a stream
+   */
+  friend std::ostream& operator<<(std::ostream& os, const ErsSarMapProjectionData& data);
+
+  /**
+   * @brief This function read a ErsSarMapProjectionData from a stream
+   */
+  friend std::istream& operator>>(std::istream& is, ErsSarMapProjectionData& data);
+
+  /**
+   * @brief Copy constructor
+   */
+  ErsSarMapProjectionData(const ErsSarMapProjectionData& rhs);
+
+  /**
+   * @brief Copy operator
+   */
+  ErsSarMapProjectionData& operator=(const ErsSarMapProjectionData& rhs);
+
+  /**
+   * @brief This function is able to create a new instance of the class
+   */
+  ErsSarRecord* Instanciate()
+  {
+    return new ErsSarMapProjectionData();
+  };
+
+  /**
+   * @brief This function is able to create a new instance of the class initialised with the data of the calling instance
+   */
+  ErsSarRecord* Clone()
+  {
+    return new ErsSarMapProjectionData(*this);
+  };
+
+  /**
+   * @brief Read the class data from a stream
+   */
+  void Read(std::istream& is)
+  {
+    is >> *this;
+  };
+
+  /**
+   * @brief Write the class to a stream
+   */
+  void Write(std::ostream& os)
+  {
+    os << *this;
+  };
+
+  /**
+  * @brief map_proj_des
+  */
+  std::string   get_map_proj_des() const
+  {
+    return _map_proj_des;
+  };
+  /**
+  * @brief num_pix_in_line
+  */
+  int   get_num_pix_in_line() const
+  {
+    return _num_pix_in_line;
+  };
+  /**
+  * @brief num_lines
+  */
+  int   get_num_lines() const
+  {
+    return _num_lines;
+  };
+  /**
+  * @brief nom_interpixel_dist
+  */
+  double   get_nom_interpixel_dist() const
+  {
+    return _nom_interpixel_dist;
+  };
+  /**
+  * @brief nom_interline_dist
+  */
+  double   get_nom_interline_dist() const
+  {
+    return _nom_interline_dist;
+  };
+  /**
+  * @brief orientation_at_center
+  */
+  double   get_orientation_at_center() const
+  {
+    return _orientation_at_center;
+  };
+  /**
+  * @brief orbit_incl
+  */
+  double   get_orbit_incl() const
+  {
+    return _orbit_incl;
+  };
+  /**
+  * @brief asc_node_long
+  */
+  double   get_asc_node_long() const
+  {
+    return _asc_node_long;
+  };
+  /**
+  * @brief platform_heading
+  */
+  double   get_platform_heading() const
+  {
+    return _platform_heading;
+  };
+  /**
+  * @brief name_of_ref_ellipsoid
+  */
+  std::string   get_name_of_ref_ellipsoid() const
+  {
+    return _name_of_ref_ellipsoid;
+  };
+  /**
+  * @brief semi_maj_axis
+  */
+  double   get_semi_maj_axis() const
+  {
+    return _semi_maj_axis;
+  };
+  /**
+  * @brief semi_min_axis
+  */
+  double   get_semi_min_axis() const
+  {
+    return _semi_min_axis;
+  };
+  /**
+  * @brief first_line_first_pixel  _lat
+  */
+  double   get_first_line_first_pixel_lat() const
+  {
+    return _first_line_first_pixel_lat;
+  };
+  /**
+  * @brief first_line_first_pixel_lon
+  */
+  double   get_first_line_first_pixel_lon() const
+  {
+    return _first_line_first_pixel_lon;
+  };
+  /**
+  * @brief first_line_last_pixel  _lat
+  */
+  double   get_first_line_last_pixel_lat() const
+  {
+    return _first_line_last_pixel_lat;
+  };
+  /**
+  * @brief first_line_last_pixel_lon
+  */
+  double   get_first_line_last_pixel_lon() const
+  {
+    return _first_line_last_pixel_lon;
+  };
+  /**
+  * @brief last_line_last_pixel_lat
+  */
+  double   get_last_line_last_pixel_lat() const
+  {
+    return _last_line_last_pixel_lat;
+  };
+  /**
+  * @brief last_line_last_pixel_lon
+  */
+  double   get_last_line_last_pixel_lon() const
+  {
+    return _last_line_last_pixel_lon;
+  };
+  /**
+  * @brief last_line_first_pixel_lat
+  */
+  double   get_last_line_first_pixel_lat() const
+  {
+    return _last_line_first_pixel_lat;
+  };
+  /**
+  * @brief last_line_first_pixel_lon
+  */
+  double   get_last_line_first_pixel_lon() const
+  {
+    return _last_line_first_pixel_lon;
+  };
+
+protected:
+  /**
+  * @brief map_proj_des
+  */
+  std::string   _map_proj_des;
+  /**
+  * @brief num_pix_in_line
+  */
+  int   _num_pix_in_line;
+  /**
+  * @brief num_lines
+  */
+  int   _num_lines;
+  /**
+  * @brief nom_interpixel_dist
+  */
+  double   _nom_interpixel_dist;
+  /**
+  * @brief nom_interline_dist
+  */
+  double   _nom_interline_dist;
+  /**
+  * @brief orientation_at_center
+  */
+  double   _orientation_at_center;
+  /**
+  * @brief orbit_incl
+  */
+  double   _orbit_incl;
+  /**
+  * @brief asc_node_long
+  */
+  double   _asc_node_long;
+  /**
+  * @brief platform_heading
+  */
+  double   _platform_heading;
+  /**
+  * @brief name_of_ref_ellipsoid
+  */
+  std::string   _name_of_ref_ellipsoid;
+  /**
+  * @brief semi_maj_axis
+  */
+  double   _semi_maj_axis;
+  /**
+  * @brief semi_min_axis
+  */
+  double   _semi_min_axis;
+  /**
+  * @brief first_line_first_pixel_lat
+  */
+  double   _first_line_first_pixel_lat;
+  /**
+  * @brief first_line_first_pixel_lon
+  */
+  double   _first_line_first_pixel_lon;
+  /**
+  * @brief first_line_last_pixel_lat
+  */
+  double   _first_line_last_pixel_lat;
+  /**
+  * @brief first_line_last_pixel_lon
+  */
+  double   _first_line_last_pixel_lon;
+  /**
+  * @brief last_line_last_pixel_lat
+  */
+  double   _last_line_last_pixel_lat;
+  /**
+  * @brief last_line_last_pixel_lon
+  */
+  double   _last_line_last_pixel_lon;
+  /**
+  * @brief last_line_first_pixel_lat
+  */
+  double   _last_line_first_pixel_lat;
+  /**
+  * @brief last_line_first_pixel_lon
+  */
+  double   _last_line_first_pixel_lon;
+
+
+private:
+
+};
+}
+
+#endif
+
diff --git a/ossim_plugins/ossim/erssar/ErsSarPlatformPositionData.cpp b/ossim_plugins/ossim/erssar/ErsSarPlatformPositionData.cpp
new file mode 100644
index 0000000..ae1b7eb
--- /dev/null
+++ b/ossim_plugins/ossim/erssar/ErsSarPlatformPositionData.cpp
@@ -0,0 +1,251 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include "erssar/ErsSarPlatformPositionData.h"
+
+
+namespace ossimplugins
+{
+
+ErsSarPlatformPositionData::ErsSarPlatformPositionData() : ErsSarRecord("pos_data_rec")
+{
+}
+
+ErsSarPlatformPositionData::~ErsSarPlatformPositionData()
+{
+}
+
+std::ostream& operator<<(std::ostream& os, const ErsSarPlatformPositionData& data)
+{
+  os << "orbit_ele_desg:" << data._orbit_ele_desg.c_str() << std::endl;
+
+  for (int i = 0; i < 6; i++)
+  {
+    os << "orbit_ele[" << i << "]:" << data._orbit_ele[i] << std::endl;
+  }
+
+  os << "ndata:" << data._ndata << std::endl;
+
+  os << "year:" << data._year << std::endl;
+
+  os << "month:" << data._month << std::endl;
+
+  os << "day:" << data._day << std::endl;
+
+  os << "gmt_day:" << data._gmt_day << std::endl;
+
+  os << "gmt_sec:" << data._gmt_sec << std::endl;
+
+  os << "data_int:" << data._data_int << std::endl;
+
+  os << "ref_coord:" << data._ref_coord.c_str() << std::endl;
+
+  os << "hr_angle:" << data._hr_angle << std::endl;
+
+  os << "alt_poserr:" << data._alt_poserr << std::endl;
+
+  os << "crt_poserr:" << data._crt_poserr << std::endl;
+
+  os << "rad_poserr:" << data._rad_poserr << std::endl;
+
+  os << "alt_velerr:" << data._alt_velerr << std::endl;
+
+  os << "crt_velerr:" << data._crt_velerr << std::endl;
+
+  os << "rad_velerr:" << data._rad_velerr << std::endl;
+
+  for (int i = 0; i < 64; i++)
+  {
+    os << "pos_vect[" << i << "]:" << data._pos_vect[i] << std::endl;
+  }
+
+  return os;
+}
+
+std::istream& operator>>(std::istream& is, ErsSarPlatformPositionData& data)
+{
+  char buf[1207];
+  buf[1206] = '\0';
+
+  is.read(buf, 32);
+  buf[32] = '\0';
+  data._orbit_ele_desg = buf;
+
+  for (int i = 0; i < 6; i++)
+  {
+    is.read(buf, 16);
+    buf[16] = '\0';
+    data._orbit_ele[i] = atof(buf);
+  }
+
+  is.read(buf, 4);
+  buf[4] = '\0';
+  data._ndata = atoi(buf);
+
+  is.read(buf, 4);
+  buf[4] = '\0';
+  data._year = atoi(buf);
+
+  is.read(buf, 4);
+  buf[4] = '\0';
+  data._month = atoi(buf);
+
+  is.read(buf, 4);
+  buf[4] = '\0';
+  data._day = atoi(buf);
+
+  is.read(buf, 4);
+  buf[4] = '\0';
+  data._gmt_day = atoi(buf);
+
+  is.read(buf, 22);
+  buf[22] = '\0';
+  data._gmt_sec = atof(buf);
+
+  is.read(buf, 22);
+  buf[22] = '\0';
+  data._data_int = atof(buf);
+
+  is.read(buf, 64);
+  buf[64] = '\0';
+  data._ref_coord = buf;
+
+  is.read(buf, 22);
+  buf[22] = '\0';
+  data._hr_angle = atof(buf);
+
+  is.read(buf, 16);
+  buf[16] = '\0';
+  data._alt_poserr = atof(buf);
+
+  is.read(buf, 16);
+  buf[16] = '\0';
+  data._crt_poserr = atof(buf);
+
+  is.read(buf, 16);
+  buf[16] = '\0';
+  data._rad_poserr = atof(buf);
+
+  is.read(buf, 16);
+  buf[16] = '\0';
+  data._alt_velerr = atof(buf);
+
+  is.read(buf, 16);
+  buf[16] = '\0';
+  data._crt_velerr = atof(buf);
+
+  is.read(buf, 16);
+  buf[16] = '\0';
+  data._rad_velerr = atof(buf);
+
+  for (int i = 0; i < data._ndata; i++)
+  {
+    is >> data._pos_vect[i];
+  }
+
+  return is;
+}
+
+ErsSarPlatformPositionData::ErsSarPlatformPositionData(const ErsSarPlatformPositionData& rhs):
+    ErsSarRecord(rhs)
+{
+  _orbit_ele_desg = rhs._orbit_ele_desg;
+
+  for (int i = 0; i < 6; i++)
+  {
+    _orbit_ele[i] = rhs._orbit_ele[i];
+  }
+
+  _ndata = rhs._ndata;
+
+  _year = rhs._year;
+
+  _month = rhs._month;
+
+  _day = rhs._day;
+
+  _gmt_day = rhs._gmt_day;
+
+  _gmt_sec = rhs._gmt_sec;
+
+  _data_int = rhs._data_int;
+
+  _ref_coord = rhs._ref_coord;
+
+  _hr_angle = rhs._hr_angle;
+
+  _alt_poserr = rhs._alt_poserr;
+
+  _crt_poserr = rhs._crt_poserr;
+
+  _rad_poserr = rhs._rad_poserr;
+
+  _alt_velerr = rhs._alt_velerr;
+
+  _crt_velerr = rhs._crt_velerr;
+
+  _rad_velerr = rhs._rad_velerr;
+
+  for (int i = 0; i < 64; i++)
+  {
+    _pos_vect[i] = rhs._pos_vect[i];
+  }
+
+}
+
+ErsSarPlatformPositionData& ErsSarPlatformPositionData::operator=(const ErsSarPlatformPositionData& rhs)
+{
+  _orbit_ele_desg = rhs._orbit_ele_desg;
+
+  for (int i = 0; i < 6; i++)
+  {
+    _orbit_ele[i] = rhs._orbit_ele[i];
+  }
+
+  _ndata = rhs._ndata;
+
+  _year = rhs._year;
+
+  _month = rhs._month;
+
+  _day = rhs._day;
+
+  _gmt_day = rhs._gmt_day;
+
+  _gmt_sec = rhs._gmt_sec;
+
+  _data_int = rhs._data_int;
+
+  _ref_coord = rhs._ref_coord;
+
+  _hr_angle = rhs._hr_angle;
+
+  _alt_poserr = rhs._alt_poserr;
+
+  _crt_poserr = rhs._crt_poserr;
+
+  _rad_poserr = rhs._rad_poserr;
+
+  _alt_velerr = rhs._alt_velerr;
+
+  _crt_velerr = rhs._crt_velerr;
+
+  _rad_velerr = rhs._rad_velerr;
+
+  for (int i = 0; i < 64; i++)
+  {
+    _pos_vect[i] = rhs._pos_vect[i];
+  }
+
+  return *this;
+}
+}
+
diff --git a/ossim_plugins/ossim/erssar/ErsSarPlatformPositionData.h b/ossim_plugins/ossim/erssar/ErsSarPlatformPositionData.h
new file mode 100644
index 0000000..a0aaa6d
--- /dev/null
+++ b/ossim_plugins/ossim/erssar/ErsSarPlatformPositionData.h
@@ -0,0 +1,299 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef ErsSarPlatformPositionData_h
+#define ErsSarPlatformPositionData_h
+
+#include <iostream>
+#include "erssar/ErsSarRecord.h"
+#include "erssar/ErsSarRecordHeader.h"
+
+#include "erssar/ErsSarPositionVectorRecord.h"
+
+
+namespace ossimplugins
+{
+
+/**
+ * @ingroup PlatformPositionDataRecord
+ * @brief This class is able to read a Platform position data record
+ *
+ */
+class ErsSarPlatformPositionData : public ErsSarRecord
+{
+public:
+  /**
+   * @brief Constructor
+   */
+  ErsSarPlatformPositionData();
+
+  /**
+   * @brief Destructor
+   */
+  virtual ~ErsSarPlatformPositionData();
+
+  /**
+   * @brief Copy constructor
+   */
+  ErsSarPlatformPositionData(const ErsSarPlatformPositionData& rhs);
+
+  /**
+   * @brief Copy operator
+   */
+  ErsSarPlatformPositionData& operator=(const ErsSarPlatformPositionData& rhs);
+  /**
+   * @brief This function write the ErsSar PlatformPositionData in a stream
+   */
+  friend std::ostream& operator<<(std::ostream& os, const ErsSarPlatformPositionData& data);
+
+  /**
+   * @brief This function read a ErsSar PlatformPositionData from a stream
+   */
+  friend std::istream& operator>>(std::istream& is, ErsSarPlatformPositionData& data);
+
+  /**
+   * @brief This function is able to create a new instance of the class
+   */
+  ErsSarRecord* Instanciate()
+  {
+    return new ErsSarPlatformPositionData();
+  };
+
+  /**
+   * @brief This function is able to create a new instance of the class initialised with the data of the calling instance
+   */
+  ErsSarRecord* Clone()
+  {
+    return new ErsSarPlatformPositionData(*this);
+  };
+
+  /**
+   * @brief Read the class data from a stream
+   */
+  void Read(std::istream& is)
+  {
+    is >> *this;
+  };
+
+  /**
+   * @brief Write the class to a stream
+   */
+  void Write(std::ostream& os)
+  {
+    os << *this;
+  };
+
+  /**
+   * @brief Orbital elements designator
+   */
+  std::string   get_orbit_ele_desg() const
+  {
+    return _orbit_ele_desg;
+  };
+  /**
+  * @brief Orbital elements
+  */
+  const double*   get_orbit_ele() const
+  {
+    return _orbit_ele;
+  };
+  /**
+  * @brief Number of data points
+  */
+  int  get_ndata() const
+  {
+    return _ndata;
+  };
+  /**
+  * @brief Year of data point
+  */
+  int   get_year() const
+  {
+    return _year;
+  };
+  /**
+  * @brief Month of data point
+  */
+  int   get_month() const
+  {
+    return _month;
+  };
+  /**
+  * @brief Day of data point
+  */
+  int   get_day() const
+  {
+    return _day;
+  };
+  /**
+  * @brief Day of year
+  */
+  int   get_gmt_day() const
+  {
+    return _gmt_day;
+  };
+  /**
+  * @brief Seconds of day
+  */
+  double   get_gmt_sec() const
+  {
+    return _gmt_sec;
+  };
+  /**
+  * @brief Data sampling interval
+  */
+  double   get_data_int() const
+  {
+    return _data_int;
+  };
+  /**
+  * @brief Reference coordinate system
+  */
+  std::string   get_ref_coord() const
+  {
+    return _ref_coord;
+  };
+  /**
+  * @brief Greenwich mean hour angle
+  */
+  double   get_hr_angle() const
+  {
+    return _hr_angle;
+  };
+  /**
+  * @brief Along track position error
+  */
+  double   get_alt_poserr() const
+  {
+    return _alt_poserr;
+  };
+  /**
+  * @brief Cross track position error
+  */
+  double   get_crt_poserr() const
+  {
+    return _crt_poserr;
+  };
+  /**
+  * @brief Radial position error
+  */
+  double   get_rad_poserr() const
+  {
+    return _rad_poserr;
+  };
+  /**
+  * @brief Along track velocity error
+  */
+  double   get_alt_velerr() const
+  {
+    return _alt_velerr;
+  };
+  /**
+  * @brief Cross track velocity error
+  */
+  double  get_crt_velerr() const
+  {
+    return _crt_velerr;
+  };
+  /**
+  * @brief Radial velocity error
+  */
+  double  get_rad_velerr() const
+  {
+    return _rad_velerr;
+  };
+  /**
+  * @brief Data point position/velocity
+  */
+  const ErsSarPositionVectorRecord* get_pos_vect() const
+  {
+    return _pos_vect;
+  };
+
+protected:
+  /**
+   * @brief Orbital elements designator
+   */
+  std::string   _orbit_ele_desg;
+  /**
+  * @brief Orbital elements
+  */
+  double   _orbit_ele[6];
+  /**
+  * @brief Number of data points
+  */
+  int   _ndata;
+  /**
+  * @brief Year of data point
+  */
+  int   _year;
+  /**
+  * @brief Month of data point
+  */
+  int   _month;
+  /**
+  * @brief Day of data point
+  */
+  int   _day;
+  /**
+  * @brief Day of year
+  */
+  int   _gmt_day;
+  /**
+  * @brief Seconds of day
+  */
+  double   _gmt_sec;
+  /**
+  * @brief Data sampling interval
+  */
+  double   _data_int;
+  /**
+  * @brief Reference coordinate system
+  */
+  std::string   _ref_coord;
+  /**
+  * @brief Greenwich mean hour angle
+  */
+  double   _hr_angle;
+  /**
+  * @brief Along track position error
+  */
+  double   _alt_poserr;
+  /**
+  * @brief Cross track position error
+  */
+  double   _crt_poserr;
+  /**
+  * @brief Radial position error
+  */
+  double   _rad_poserr;
+  /**
+  * @brief Along track velocity error
+  */
+  double   _alt_velerr;
+  /**
+  * @brief Cross track velocity error
+  */
+  double   _crt_velerr;
+  /**
+  * @brief Radial velocity error
+  */
+  double   _rad_velerr;
+  /**
+  * @brief Data point position/velocity
+  */
+  ErsSarPositionVectorRecord _pos_vect[64];
+
+private:
+};
+}
+#endif
+
diff --git a/ossim_plugins/ossim/erssar/ErsSarPositionVectorRecord.cpp b/ossim_plugins/ossim/erssar/ErsSarPositionVectorRecord.cpp
new file mode 100644
index 0000000..d2598cb
--- /dev/null
+++ b/ossim_plugins/ossim/erssar/ErsSarPositionVectorRecord.cpp
@@ -0,0 +1,86 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include "erssar/ErsSarPositionVectorRecord.h"
+
+
+namespace ossimplugins
+{
+
+ErsSarPositionVectorRecord::ErsSarPositionVectorRecord()
+{
+}
+
+ErsSarPositionVectorRecord::~ErsSarPositionVectorRecord()
+{
+}
+
+std::ostream& operator<<(std::ostream& os, const ErsSarPositionVectorRecord& data)
+{
+  for (int i = 0; i < 3; i++)
+  {
+    os << "pos[" << i << "]:" << data._pos[i] << std::endl;
+  }
+
+  for (int i = 0; i < 3; i++)
+  {
+    os << "vel[" << i << "]:" << data._vel[i] << std::endl;
+  }
+  return os;
+}
+
+std::istream& operator>>(std::istream& is, ErsSarPositionVectorRecord& data)
+{
+  char buf[23];
+  buf[22] = '\0';
+
+  for (int i = 0; i < 3; i++)
+  {
+    is.read(buf, 22);
+    data._pos[i] = atof(buf);
+  }
+
+  for (int i = 0; i < 3; i++)
+  {
+    is.read(buf, 22);
+    data._vel[i] = atof(buf);
+  }
+  return is;
+}
+
+ErsSarPositionVectorRecord::ErsSarPositionVectorRecord(const ErsSarPositionVectorRecord& rhs)
+{
+  for (int i = 0; i < 3; i++)
+  {
+    _pos[i] = rhs._pos[i];
+  }
+
+  for (int i = 0; i < 3; i++)
+  {
+    _vel[i] = rhs._vel[i];
+  }
+}
+
+ErsSarPositionVectorRecord& ErsSarPositionVectorRecord::operator=(const ErsSarPositionVectorRecord& rhs)
+{
+  for (int i = 0; i < 3; i++)
+  {
+    _pos[i] = rhs._pos[i];
+  }
+
+  for (int i = 0; i < 3; i++)
+  {
+    _vel[i] = rhs._vel[i];
+  }
+  return *this;
+}
+}
+
diff --git a/ossim_plugins/ossim/erssar/ErsSarPositionVectorRecord.h b/ossim_plugins/ossim/erssar/ErsSarPositionVectorRecord.h
new file mode 100644
index 0000000..072bc87
--- /dev/null
+++ b/ossim_plugins/ossim/erssar/ErsSarPositionVectorRecord.h
@@ -0,0 +1,90 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef ErsSarPositionVectorRecord_h
+#define ErsSarPositionVectorRecord_h
+
+#include <iostream>
+#include <cstdlib>
+#include "erssar/ErsSarRecord.h"
+
+namespace ossimplugins
+{
+
+/**
+ * @ingroup PlatformPositionDataRecord
+ * @brief This class is able to read a position vector record
+ *
+ */
+class ErsSarPositionVectorRecord
+{
+public:
+  /**
+   * @brief Constructor
+   */
+  ErsSarPositionVectorRecord();
+
+  /**
+   * @brief Destructor
+   */
+  virtual ~ErsSarPositionVectorRecord();
+
+  /**
+   * @brief Copy constructor
+   */
+  ErsSarPositionVectorRecord(const ErsSarPositionVectorRecord& rhs);
+
+  /**
+   * @brief Copy operator
+   */
+  ErsSarPositionVectorRecord& operator=(const ErsSarPositionVectorRecord& rhs);
+  /**
+   * @brief This function write the ErsSar PositionVectorRecord in a stream
+   */
+  friend std::ostream& operator<<(std::ostream& os, const ErsSarPositionVectorRecord& data);
+
+  /**
+   * @brief This function read a ErsSar PositionVectorRecord from a stream
+   */
+  friend std::istream& operator>>(std::istream& is, ErsSarPositionVectorRecord& data);
+
+  /**
+   * @brief Data point position (m)
+   */
+  const double* get_pos() const
+  {
+    return _pos;
+  };
+
+  /**
+   * @brief Data point velocity (mm/s)
+   */
+  const double* get_vel() const
+  {
+    return _vel;
+  };
+
+protected:
+  /**
+   * @brief Data point position (m)
+   */
+  double _pos[3];
+  /**
+   * @brief Data point velocity (mm/s)
+   */
+  double _vel[3];
+private:
+
+
+};
+}
+#endif
+
diff --git a/ossim_plugins/ossim/erssar/ErsSarRecord.cpp b/ossim_plugins/ossim/erssar/ErsSarRecord.cpp
new file mode 100644
index 0000000..ece2f80
--- /dev/null
+++ b/ossim_plugins/ossim/erssar/ErsSarRecord.cpp
@@ -0,0 +1,32 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include "erssar/ErsSarRecord.h"
+#include <memory.h>
+
+namespace ossimplugins
+{
+
+ErsSarRecord::ErsSarRecord(std::string mnemonic):
+    _mnemonic(mnemonic)
+{
+}
+
+ErsSarRecord::~ErsSarRecord()
+{
+}
+
+ErsSarRecord::ErsSarRecord(const ErsSarRecord& rhs):
+    _mnemonic(rhs._mnemonic)
+{
+}
+}
+
diff --git a/ossim_plugins/ossim/erssar/ErsSarRecord.h b/ossim_plugins/ossim/erssar/ErsSarRecord.h
new file mode 100644
index 0000000..8e9db67
--- /dev/null
+++ b/ossim_plugins/ossim/erssar/ErsSarRecord.h
@@ -0,0 +1,79 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef ErsSarRecord_h
+#define ErsSarRecord_h
+
+
+#include "erssar/ErsSarRecordHeader.h"
+#include <iostream>
+
+namespace ossimplugins
+{
+
+/**
+ * @ingroup ErsSar
+ * @brief This class is the base class of all the record classes
+ *
+ */
+class ErsSarRecord
+{
+public:
+  /**
+   * @brief Constructor
+   * @param mnemonic Name of the record
+   */
+  ErsSarRecord(std::string mnemonic);
+  /**
+   * @brief Destructor
+   */
+  virtual ~ErsSarRecord();
+
+  /**
+   * @brief Copy constructor
+   */
+  ErsSarRecord(const ErsSarRecord& rhs);
+
+  /**
+   * @brief This function is able to create a new instance of the class
+   */
+  virtual ErsSarRecord* Instanciate() = 0;
+
+  /**
+   * @brief This function is able to create a new instance of the class initialised with the data of the calling instance
+   */
+  virtual ErsSarRecord* Clone() = 0;
+
+  /**
+   * @brief Read the class data from a stream
+   */
+  virtual void Read(std::istream& is) = 0;
+
+  /**
+   * @brief Write the class to a stream
+   */
+  virtual void Write(std::ostream& os) = 0;
+
+  std::string get_mnemonic()
+  {
+    return _mnemonic;
+  };
+
+protected:
+
+  std::string _mnemonic;
+
+private:
+};
+}
+
+#endif
+
diff --git a/ossim_plugins/ossim/erssar/ErsSarRecordFactory.cpp b/ossim_plugins/ossim/erssar/ErsSarRecordFactory.cpp
new file mode 100644
index 0000000..353dcd2
--- /dev/null
+++ b/ossim_plugins/ossim/erssar/ErsSarRecordFactory.cpp
@@ -0,0 +1,43 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include "erssar/ErsSarRecordFactory.h"
+
+namespace ossimplugins
+{
+
+ErsSarRecordFactory::ErsSarRecordFactory()
+{
+}
+
+ErsSarRecordFactory::~ErsSarRecordFactory()
+{
+}
+
+ErsSarRecord* ErsSarRecordFactory::Instanciate(int id)
+{
+  ErsSarRecord* record = _availableRecords[id];
+  if (record == NULL)
+  {
+    return NULL;
+  }
+  else
+  {
+    return record->Instanciate();
+  }
+}
+
+void ErsSarRecordFactory::RegisterRecord(int id, ErsSarRecord * record)
+{
+  _availableRecords[id] = record;
+}
+}
+
diff --git a/ossim_plugins/ossim/erssar/ErsSarRecordFactory.h b/ossim_plugins/ossim/erssar/ErsSarRecordFactory.h
new file mode 100644
index 0000000..082465d
--- /dev/null
+++ b/ossim_plugins/ossim/erssar/ErsSarRecordFactory.h
@@ -0,0 +1,67 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef ErsSarRecordFactory_h
+#define ErsSarRecordFactory_h
+
+
+#include "erssar/ErsSarRecordHeader.h"
+#include "erssar/ErsSarRecord.h"
+
+#include <map>
+
+
+namespace ossimplugins
+{
+
+
+/**
+ * @ingroup ErsSar
+ * @brief This class is a facory able to construct Record base classes given the id of the record wanted
+ *
+ */
+class ErsSarRecordFactory
+{
+public:
+  /**
+   * @brief Constructor
+   */
+  ErsSarRecordFactory();
+  /**
+   * @brief Destructor
+   */
+  virtual ~ErsSarRecordFactory();
+
+  /**
+   * @brief Add a new Record type available in this factory
+   * @param record Record to add in the factory
+   * @param id Id of the new avalaible Record
+   */
+  void RegisterRecord(int id, ErsSarRecord * record);
+
+  /**
+   * @brief Instanciate a new Record
+   * @param id Id of the Record we want to instanciate
+   */
+  ErsSarRecord* Instanciate(int id) ;
+protected:
+
+  /**
+   * @brief Contain all the available Records for the factory
+   */
+  std::map<int, ErsSarRecord*> _availableRecords;
+
+private:
+};
+}
+
+#endif
+
diff --git a/ossim_plugins/ossim/erssar/ErsSarRecordHeader.cpp b/ossim_plugins/ossim/erssar/ErsSarRecordHeader.cpp
new file mode 100644
index 0000000..c0009d8
--- /dev/null
+++ b/ossim_plugins/ossim/erssar/ErsSarRecordHeader.cpp
@@ -0,0 +1,83 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include "erssar/ErsSarRecordHeader.h"
+
+
+namespace ossimplugins
+{
+
+ErsSarRecordHeader::ErsSarRecordHeader()
+{
+}
+
+ErsSarRecordHeader::~ErsSarRecordHeader()
+{
+}
+
+std::ostream& operator<<(std::ostream& os, const ErsSarRecordHeader& data)
+{
+  os << "record_sequence_number:" << data._rec_seq << std::endl;
+  os << "first_record_sub-type:" << (int)data._rec_sub1 << std::endl;
+  os << "record_type_code:" << (int)data._rec_type << std::endl;
+  os << "second_record_sub-type:" << (int)data._rec_sub2 << std::endl;
+  os << "third_record_sub-type:" << (int)data._rec_sub3 << std::endl;
+  os << "length:" << data._length << std::endl;
+  return os;
+}
+
+std::istream& operator>>(std::istream& is, ErsSarRecordHeader& data)
+{
+  is.read((char*)&(data._rec_seq), 4);
+  data.SwitchEndian(data._rec_seq);
+  is.read((char*)&(data._rec_sub1), 1);
+  is.read((char*)&(data._rec_type), 1);
+  is.read((char*)&(data._rec_sub2), 1);
+  is.read((char*)&(data._rec_sub3), 1);
+  is.read((char*)&(data._length), 4);
+  data.SwitchEndian(data._length);
+  return is;
+}
+
+ErsSarRecordHeader::ErsSarRecordHeader(const ErsSarRecordHeader& rhs):
+    _rec_seq(rhs._rec_seq),
+    _rec_sub1(rhs._rec_sub1),
+    _rec_type(rhs._rec_type),
+    _rec_sub2(rhs._rec_sub2),
+    _rec_sub3(rhs._rec_sub3)
+{
+}
+
+ErsSarRecordHeader& ErsSarRecordHeader::operator=(const ErsSarRecordHeader& rhs)
+{
+  _rec_seq = rhs._rec_seq;
+  _rec_sub1 = rhs._rec_sub1;
+  _rec_type = rhs._rec_type;
+  _rec_sub2 = rhs._rec_sub2;
+  _rec_sub3 = rhs._rec_sub3;
+  return *this;
+}
+
+void ErsSarRecordHeader::SwitchEndian(unsigned int& value)
+{
+  char buffer[4];
+  char res[4];
+
+  memcpy(buffer, &value, 4);
+  res[0] = buffer[3];
+  res[1] = buffer[2];
+  res[2] = buffer[1];
+  res[3] = buffer[0];
+
+  memcpy(&value, res, 4);
+}
+}
+
diff --git a/ossim_plugins/ossim/erssar/ErsSarRecordHeader.h b/ossim_plugins/ossim/erssar/ErsSarRecordHeader.h
new file mode 100644
index 0000000..7d6ce9d
--- /dev/null
+++ b/ossim_plugins/ossim/erssar/ErsSarRecordHeader.h
@@ -0,0 +1,143 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef ErsSarRecordHeader_h
+#define ErsSarRecordHeader_h
+
+#include<iostream>
+#include<cstring>
+
+namespace ossimplugins
+{
+
+/**
+ * @ingroup ErsSar
+ * @brief This class is able to read a record header
+ *
+ */
+class ErsSarRecordHeader
+{
+public:
+  /**
+   * @brief Constructor
+   */
+  ErsSarRecordHeader();
+
+  /**
+   * @brief Destructor
+   */
+  virtual ~ErsSarRecordHeader();
+
+  /**
+   * @brief Copy constructor
+   */
+  ErsSarRecordHeader(const ErsSarRecordHeader& rhs);
+
+  /**
+   * @brief Copy operator
+   */
+  ErsSarRecordHeader& operator=(const ErsSarRecordHeader& rhs);
+  /**
+   * @brief This function write the RecordHeader in a stream
+   */
+  friend std::ostream& operator<<(std::ostream& os, const ErsSarRecordHeader& data);
+
+  /**
+   * @brief This function read a RecordHeader from a stream
+   */
+  friend std::istream& operator>>(std::istream& is, ErsSarRecordHeader& data);
+
+  /**
+   * @brief Record sequence number
+   */
+  unsigned int  get_rec_seq()
+  {
+    return _rec_seq;
+  };
+
+  /**
+   * @brief First record sub-type code
+   */
+  unsigned char   get_rec_sub1()
+  {
+    return _rec_sub1;
+  };
+
+  /**
+   * @brief Record type code
+   */
+  unsigned char   get_rec_type()
+  {
+    return _rec_type;
+  };
+
+  /**
+   * @brief Second record sub-type code
+   */
+  unsigned char   get_rec_sub2()
+  {
+    return _rec_sub2;
+  };
+
+  /**
+   * @brief Third record sub-type code
+   */
+  unsigned char   get_rec_sub3()
+  {
+    return _rec_sub3;
+  };
+
+  /**
+   * @brief Length of this record (in bytes)
+   */
+  unsigned int get_length()
+  {
+    return _length;
+  };
+protected:
+
+  /**
+   * @brief This function switch the LSB value and the MSB value of the parameter
+   */
+  void SwitchEndian(unsigned int& value);
+
+  /**
+   * @brief Record sequence number
+   */
+  unsigned int  _rec_seq;
+  /**
+   * @brief First record sub-type code
+   */
+  unsigned char   _rec_sub1;
+  /**
+   * @brief Record type code
+   */
+  unsigned char   _rec_type;
+  /**
+   * @brief Second record sub-type code
+   */
+  unsigned char   _rec_sub2;
+  /**
+   * @brief Third record sub-type code
+   */
+  unsigned char   _rec_sub3;
+  /**
+   * @brief Length of this record (in bytes)
+   */
+  unsigned int  _length;
+private:
+
+
+};
+}
+
+#endif
+
diff --git a/ossim_plugins/ossim/ossimAlosPalsarModel.cpp b/ossim_plugins/ossim/ossimAlosPalsarModel.cpp
new file mode 100644
index 0000000..13a7e6d
--- /dev/null
+++ b/ossim_plugins/ossim/ossimAlosPalsarModel.cpp
@@ -0,0 +1,794 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+// "Copyright Centre for Remote Imaging, Sensing and Processing"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include <ossimAlosPalsarModel.h>
+#include <otb/GalileanEphemeris.h>
+#include <otb/GeographicEphemeris.h>
+
+#include <otb/JSDDateTime.h>
+#include <otb/GMSTDateTime.h>
+#include <otb/CivilDateTime.h>
+
+#include <ossim/base/ossimTrace.h>
+#include <otb/RefPoint.h>
+#include <AlosPalsar/AlosPalsarLeader.h>
+#include <AlosPalsar/AlosPalsarData.h>
+#include <otb/SensorParams.h>
+#include <otb/PlatformPosition.h>
+#include <ossim/base/ossimKeywordNames.h>
+
+
+// Static trace for debugging
+static ossimTrace traceDebug("ossimAlosPalsarModel:debug");
+
+#include <string>
+#include <algorithm>
+
+namespace ossimplugins
+{
+
+   RTTI_DEF1(ossimAlosPalsarModel, "ossimAlosPalsarModel", ossimGeometricSarSensorModel);
+
+   ossimAlosPalsarModel::ossimAlosPalsarModel():
+      thePixelSpacing(0),
+      theAlosPalsarLeader(NULL),
+      theAlosPalsarData(NULL)
+   {
+   }
+
+   ossimAlosPalsarModel::~ossimAlosPalsarModel()
+   {
+      if (theAlosPalsarLeader != NULL)
+      {
+         delete theAlosPalsarLeader;
+         theAlosPalsarLeader = NULL;
+      }
+      if (theAlosPalsarData != NULL)
+      {
+         delete theAlosPalsarData;
+         theAlosPalsarData = NULL;
+      }
+   }
+
+   ossimString ossimAlosPalsarModel::getClassName() const
+   {
+      return ossimString("ossimAlosPalsarModel");
+   }
+
+   ossimObject* ossimAlosPalsarModel::dup() const
+   {
+      return new ossimAlosPalsarModel(*this);
+   }
+
+   double ossimAlosPalsarModel::getSlantRangeFromGeoreferenced(double /* col */) const
+   {
+      std::cout << "WARNING: getSlantRangeFromGeoreferenced not implemented for AlosPalsar" << std::endl;
+      return 0.0;
+   }
+
+   bool ossimAlosPalsarModel::InitSensorParams(const ossimKeywordlist &kwl, const char *prefix)
+   {
+      const char* wave_length_str = kwl.find(prefix, "wave_length");
+      double wave_length = atof(wave_length_str);
+      const char* fr_str = kwl.find(prefix, "fr");
+      double fr = atof(fr_str) * 1e6;
+      const char* fa_str = kwl.find(prefix, "fa");
+      double fa = atof(fa_str);
+
+      ossimString time_dir_pix = kwl.find(prefix, "time_dir_pix");
+      time_dir_pix.upcase();
+      //std::transform(time_dir_pix.begin(), time_dir_pix.end(), time_dir_pix.begin(), toupper);
+      ossimString time_dir_lin = kwl.find(prefix, "time_dir_lin");
+      time_dir_lin.upcase();
+      //std::transform(time_dir_lin.begin(), time_dir_lin.end(), time_dir_lin.begin(), toupper);
+
+      //ellipsoid parameters
+      const char* ellip_maj_str = kwl.find(prefix, "ellip_maj");
+      double ellip_maj = atof(ellip_maj_str) * 1000.0;  // km -> m
+      const char* ellip_min_str = kwl.find(prefix, "ellip_min");
+      double ellip_min = atof(ellip_min_str) * 1000.0;  // km -> m
+
+      const char* dopcen_str = kwl.find(prefix, "dopcen_range[0]");
+      double dopcen = atof(dopcen_str);
+      const char* dopcenLinear_str = kwl.find(prefix, "dopcen_range[1]");
+      double dopcenLinear = atof(dopcenLinear_str);
+
+      if (_sensor != NULL)
+      {
+         delete _sensor;
+      }
+
+      _sensor = new SensorParams();
+
+      /*
+        if(strcmp(time_dir_pix.c_str(), "INCREASE") == 0)
+        {
+        _sensor->set_col_direction(1);
+        }
+        else
+        {
+        _sensor->set_col_direction(-1);
+        }
+      */
+      // WARNING: _col_direction hard-coded to 1, as level 1.0 image is not flipped.
+      _sensor->set_col_direction(1);
+
+      // TODO: Have to verify whether the time direction indicator should be always positive
+      /*
+        if(strcmp(time_dir_lin.c_str(), "INCREASE") == 0)
+        {
+        _sensor->set_lin_direction(1);
+        }
+        else
+        {
+        _sensor->set_lin_direction(-1);
+        }
+      */
+      _sensor->set_lin_direction(1);
+
+      _sensor->set_sightDirection(SensorParams::Right) ;
+
+      double nlooks_az = atof(kwl.find(prefix, "nlooks_az"));
+      _sensor->set_nAzimuthLook(nlooks_az);
+      double n_rnglok = atof(kwl.find(prefix, "n_rnglok"));
+      _sensor->set_nRangeLook(n_rnglok);
+
+      _sensor->set_prf(fa / 1000.); // For ALOS, the fa value in the leader file is in units of mHz
+      _sensor->set_sf(fr);
+      _sensor->set_rwl(wave_length);
+
+      _sensor->set_semiMajorAxis(ellip_maj) ;
+      _sensor->set_semiMinorAxis(ellip_min) ;
+
+      _sensor->set_dopcen(dopcen);
+      _sensor->set_dopcenLinear(dopcenLinear);
+
+      return true;
+   }
+
+   bool ossimAlosPalsarModel::open(const ossimFilename& file)
+   {
+      static const char MODULE[] = "ossimAlosPalsarModel::open";
+
+      if (traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG)
+            << MODULE << " entered...\n"
+            << "file: " << file << "\n";
+      }
+
+      bool result = false;
+      ossimFilename leaFilename = file;
+      ossimFilename datFilename;
+
+      /*
+       * Creation of the class allowing to store Leader file metadata
+       */
+      if (theAlosPalsarLeader != NULL)
+      {
+         delete theAlosPalsarLeader;
+         theAlosPalsarLeader = NULL;
+      }
+
+      theAlosPalsarLeader = new AlosPalsarLeader();
+      theAlosPalsarData = new AlosPalsarData();
+
+      if (leaFilename.exists())
+      {
+         result = isAlosPalsarLeader(leaFilename);
+         if (result == false)
+         {
+            leaFilename = findAlosPalsarLeader(file);
+         }
+         result = isAlosPalsarLeader(leaFilename);
+
+         if (result == true)
+         {
+            if (traceDebug())
+            {
+               ossimNotify(ossimNotifyLevel_DEBUG)
+                  << leaFilename << " is AlosPalsar leader file..."
+                  << std::endl
+                  << "Begin reading Leader file" << std::endl;
+            }
+            /*
+             * Leader file data reading
+             */
+            std::ifstream leaderFile(leaFilename.c_str(), ios::in | ios::binary);
+            leaderFile >> *theAlosPalsarLeader;
+            leaderFile.close();
+
+            if (traceDebug())
+            {
+               ossimNotify(ossimNotifyLevel_DEBUG)
+                  << "End reading Leader file" << std::endl;
+            }
+
+            datFilename = findAlosPalsarData(leaFilename);
+            result = isAlosPalsarData(datFilename);
+            if (result == true)
+            {
+               if (traceDebug())
+               {
+                  ossimNotify(ossimNotifyLevel_DEBUG)
+                     << datFilename << " is AlosPalsar data file..."
+                     << std::endl
+                     << "Begin reading Data file header" << std::endl;
+               }
+               /*
+                * Read header of data file for image size info
+                */
+               std::ifstream dataFile(datFilename.c_str(), ios::in | ios::binary);
+               dataFile >> *theAlosPalsarData;
+               dataFile.close();
+
+               if (traceDebug())
+               {
+                  ossimNotify(ossimNotifyLevel_DEBUG)
+                     << "End reading Data file header" << std::endl;
+               }
+            } // matches: if ( result=isAlosPalsarData(datFilename) == true )
+
+            //To initialize the whole state, reusing saveState/loadState
+            //FIXME: This could be at the superclass level instead
+            ossimKeywordlist kwl;
+            saveState(kwl);
+            loadState(kwl);
+
+         } // matches: if ( result=isAlosPalsarLeader(file) == True )
+
+      } // matches: if ( file.exists() )
+
+      if (traceDebug())
+      {
+         this->print(ossimNotify(ossimNotifyLevel_DEBUG));
+
+         ossimNotify(ossimNotifyLevel_DEBUG)
+            << MODULE << " exit status = " << (result ? "true" : "false\n")
+            << std::endl;
+      }
+
+      return result;
+
+   }
+
+
+   bool ossimAlosPalsarModel::saveState(ossimKeywordlist& kwl,
+                                        const char* prefix) const
+   {
+      static const char MODULE[] = "ossimAlosPalsarModel::saveState";
+
+      if (traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " entered...\n";
+      }
+
+      bool result;
+
+      kwl.add(prefix, ossimKeywordNames::TYPE_KW, "ossimAlosPalsarModel", true);
+
+      if (theAlosPalsarLeader == NULL)
+      {
+         std::cout << "Error: AlosPalsarLeader is NULL" << std::endl;
+         return false;
+      }
+
+      result = theAlosPalsarLeader->saveState(kwl);
+
+      if (result == true)
+      {
+         if (theAlosPalsarData == NULL)
+         {
+            std::cout << "Error: AlosPalsarData is NULL" << std::endl;
+            return false;
+         }
+         result = theAlosPalsarData->saveState(kwl);
+      }
+
+      if (traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG)
+            << MODULE << " exit status = " << (result ? "true" : "false\n")
+            << std::endl;
+      }
+
+      return result;
+   }
+
+   bool ossimAlosPalsarModel::loadState(const ossimKeywordlist &kwl, const char *prefix)
+   {
+      static const char MODULE[] = "ossimAlosPalsarModel::loadState";
+
+      if (traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " entered...\n";
+      }
+
+      const char* lookup = 0;
+      ossimString s;
+
+      // Check the type first.
+      lookup = kwl.find(prefix, ossimKeywordNames::TYPE_KW);
+      if (lookup)
+      {
+         s = lookup;
+         if (s != getClassName())
+         {
+            return false;
+         }
+      }
+
+      // Load the base class.
+//    bool result = ossimGeometricSarSensorModel::loadState(kwl, prefix);
+      bool result = false;
+      result = InitPlatformPosition(kwl, prefix);
+      if (!result)
+      {
+         if (traceDebug())
+         {
+            ossimNotify(ossimNotifyLevel_WARN)
+               << MODULE
+               << "\nCan't init platform position \n";
+         }
+      }
+
+      if (result)
+      {
+         result = InitSensorParams(kwl, prefix);
+         if (!result)
+         {
+            if (traceDebug())
+            {
+               ossimNotify(ossimNotifyLevel_WARN)
+                  << MODULE
+                  << "\nCan't init sensor parameters \n";
+            }
+         }
+      }
+
+      if (result)
+      {
+         result = InitRefPoint(kwl, prefix);
+         if (!result)
+         {
+            if (traceDebug())
+            {
+               ossimNotify(ossimNotifyLevel_WARN)
+                  << MODULE
+                  << "\nCan't init ref point \n";
+            }
+         }
+      }
+
+// Products georeferenced to ground range are not handled in AlosPalsarModel
+      _isProductGeoreferenced = false;
+      /*
+        if (result)
+        {
+        result = InitSRGR(kwl, prefix);
+        if (!result)
+        {
+        if (traceDebug())
+        {
+        ossimNotify(ossimNotifyLevel_WARN)
+        << MODULE
+        << "\nCan't init ref point \n";
+        }
+        }
+        }
+      */
+
+      return result;
+   }
+
+   bool ossimAlosPalsarModel::InitPlatformPosition(const ossimKeywordlist &kwl, const char *prefix)
+   {
+      // const double PI          = 3.14159265358979323846 ;
+      CivilDateTime ref_civil_date;
+      /*
+       * Ephemerisis reference date retrieval
+       */
+      const char* eph_year_str = kwl.find(prefix, "eph_year");
+      int eph_year = atoi(eph_year_str);
+      const char* eph_month_str = kwl.find(prefix, "eph_month");
+      int eph_month = atoi(eph_month_str);
+      const char* eph_day_str = kwl.find(prefix, "eph_day");
+      int eph_day = atoi(eph_day_str);
+      const char* eph_sec_str = kwl.find(prefix, "eph_sec");
+      double eph_sec = atof(eph_sec_str);
+
+
+      ref_civil_date.set_year(eph_year);
+      ref_civil_date.set_month(eph_month);
+      ref_civil_date.set_day(eph_day);
+      ref_civil_date.set_second((int)eph_sec);
+      ref_civil_date.set_decimal(eph_sec - (double)((int)eph_sec));
+
+      JSDDateTime ref_jsd_date(ref_civil_date);
+
+      /*
+       * Ephemerisis time interval retrieval
+       */
+      const char* eph_int_str = kwl.find(prefix, "eph_int");
+      double eph_int = atof(eph_int_str);
+      /*
+       * Ephemerisis number retrieval
+       */
+      const char* neph_str = kwl.find(prefix, "neph");
+      int neph = atoi(neph_str);
+
+      Ephemeris** ephemeris = new Ephemeris*[neph];
+
+      /*
+       * Ephemerisis retrieval
+       */
+      for (int i = 0; i < neph; i++)
+      {
+         double pos[3];
+         double vit[3];
+         char name[64];
+
+
+         sprintf(name, "eph%i_posX", i);
+         const char* px_str = kwl.find(prefix, name);
+         pos[0] = atof(px_str);
+
+         sprintf(name, "eph%i_posY", i);
+         const char* py_str = kwl.find(prefix, name);
+         pos[1] = atof(py_str);
+
+         sprintf(name, "eph%i_posZ", i);
+         const char* pz_str = kwl.find(prefix, name);
+         pos[2] = atof(pz_str);
+
+
+         sprintf(name, "eph%i_velX", i);
+         const char* vx_str = kwl.find(prefix, name);
+         vit[0] = atof(vx_str);
+
+         sprintf(name, "eph%i_velY", i);
+         const char* vy_str = kwl.find(prefix, name);
+         vit[1] = atof(vy_str);
+
+         sprintf(name, "eph%i_velZ", i);
+         const char* vz_str = kwl.find(prefix, name);
+         vit[2] = atof(vz_str);
+
+         /*
+          * Ephemerisis date
+          */
+         JSDDateTime date(ref_jsd_date);
+         date.set_second(date.get_second() + i * eph_int);
+         date.NormDate();
+
+         GeographicEphemeris* eph = new GeographicEphemeris(date, pos, vit);
+
+         ephemeris[i] = eph;
+      }
+
+      /*
+       * Antenna position interpolator creation
+       */
+      if (_platformPosition != NULL)
+      {
+         delete _platformPosition;
+      }
+      _platformPosition = new PlatformPosition(ephemeris, neph);
+
+      /*
+       * Free of memory used by the ephemerisis list
+       */
+      for (int i = 0; i < neph; i++)
+      {
+         delete ephemeris[i];
+      }
+      delete[] ephemeris;
+
+      return true;
+   }
+
+   bool ossimAlosPalsarModel::InitRefPoint(const ossimKeywordlist &kwl, const char *prefix)
+   {
+      const char* sc_lin_str = kwl.find(prefix, "sc_lin");
+      double sc_lin = atof(sc_lin_str);
+
+      const char* sc_pix_str = kwl.find(prefix, "sc_pix");
+      double sc_pix = atof(sc_pix_str);
+
+      const char* inp_sctim_str = kwl.find(prefix, "inp_sctim");
+
+      // Not available for ALOS
+      //const char* rng_gate_str = kwl.find(prefix,"zero_dop_range_time_f_pixel");
+      //double rng_gate = atof(rng_gate_str);
+
+      if (_refPoint == NULL)
+      {
+         _refPoint = new RefPoint();
+      }
+
+      _refPoint->set_pix_col(sc_pix);
+      _refPoint->set_pix_line(sc_lin);
+
+      char year_str[5];
+      for (int i = 0; i < 4; i++)
+      {
+         year_str[i] = inp_sctim_str[i];
+      }
+      year_str[4] = '\0';
+
+      char month_str[3];
+      for (int i = 4; i < 6; i++)
+      {
+         month_str[i-4] = inp_sctim_str[i];
+      }
+      month_str[2] = '\0';
+
+      char day_str[3];
+      for (int i = 6; i < 8; i++)
+      {
+         day_str[i-6] = inp_sctim_str[i];
+      }
+      day_str[2] = '\0';
+
+      char hour_str[3];
+      for (int i = 8; i < 10; i++)
+      {
+         hour_str[i-8] = inp_sctim_str[i];
+      }
+      hour_str[2] = '\0';
+
+      char min_str[3];
+      for (int i = 10; i < 12; i++)
+      {
+         min_str[i-10] = inp_sctim_str[i];
+      }
+      min_str[2] = '\0';
+
+      char sec_str[3];
+      for (int i = 12; i < 14; i++)
+      {
+         sec_str[i-12] = inp_sctim_str[i];
+      }
+      sec_str[2] = '\0';
+
+      char mili_str[4];
+      for (int i = 14; i < 17; i++)
+      {
+         mili_str[i-14] = inp_sctim_str[i];
+      }
+      mili_str[3] = '\0';
+
+      int year = atoi(year_str);
+      int month = atoi(month_str);
+      int day = atoi(day_str);
+      int hour = atoi(hour_str);
+      int min = atoi(min_str);
+      int sec = atoi(sec_str);
+      double mili = atof(mili_str);
+
+
+      CivilDateTime date(year, month, day, hour * 3600 + min * 60 + sec, mili / 1000.0);
+
+      if (_platformPosition != NULL)
+      {
+         Ephemeris * ephemeris = _platformPosition->Interpolate((JSDDateTime)date);
+         if (ephemeris == NULL) return false ;
+         _refPoint->set_ephemeris(ephemeris);
+
+         delete ephemeris;
+      }
+      else
+      {
+         return false;
+      }
+
+      const double c = 2.99792458e+8;
+
+      const char* slantRange = kwl.find(prefix, "slant_range_to_1st_data_sample");
+      double distance = atof(slantRange) + static_cast<double>(sc_pix) * _sensor->get_nRangeLook() / _sensor->get_sf() * c / 2.0;
+
+      _refPoint->set_distance(distance);
+
+      // in order to use ossimSensorModel::lineSampleToWorld
+      const char* nbCol_str = kwl.find(prefix, "num_pix_in_line");
+      const char* nbLin_str = kwl.find(prefix, "num_lines");
+      theImageSize.x      = atoi(nbCol_str);
+      theImageSize.y      = atoi(nbLin_str);
+      theImageClipRect    = ossimDrect(0, 0, theImageSize.x - 1, theImageSize.y - 1);
+
+// AlosPalsarModel currently does not handle GCPs
+      /* Do not use GCPs for now
+      // Ground Control Points extracted from the model : corner points
+      std::list<ossimGpt> groundGcpCoordinates ;
+      std::list<ossimDpt> imageGcpCoordinates ;
+      // first line first pix
+      const char* lon_str = kwl.find("first_line_first_pixel_lon");
+      double lon = atof(lon_str);
+      const char* lat_str = kwl.find("first_line_first_pixel_lat");
+      double lat = atof(lat_str);
+      if (lon > 180.0) lon -= 360.0;
+      ossimDpt imageGCP1(0,0);
+      ossimGpt groundGCP1(lat, lon, 0.0);
+      groundGcpCoordinates.push_back(groundGCP1) ;
+      imageGcpCoordinates.push_back(imageGCP1) ;
+      // first line last pix
+      lon_str = kwl.find("first_line_last_pixel_lon");
+      lon = atof(lon_str);
+      lat_str = kwl.find("first_line_last_pixel_lat");
+      lat = atof(lat_str);
+      if (lon > 180.0) lon -= 360.0;
+      ossimDpt imageGCP2(theImageSize.x-1, 0);
+      ossimGpt groundGCP2(lat, lon, 0.0);
+      groundGcpCoordinates.push_back(groundGCP2) ;
+      imageGcpCoordinates.push_back(imageGCP2) ;
+      // last line last pix
+      lon_str = kwl.find("last_line_last_pixel_lon");
+      lon = atof(lon_str);
+      lat_str = kwl.find("last_line_last_pixel_lat");
+      lat = atof(lat_str);
+      if (lon > 180.0) lon -= 360.0;
+      ossimDpt imageGCP3(theImageSize.x-1,theImageSize.y-1);
+      ossimGpt groundGCP3(lat, lon, 0.0);
+      groundGcpCoordinates.push_back(groundGCP3) ;
+      imageGcpCoordinates.push_back(imageGCP3) ;
+      // last line first pix
+      lon_str = kwl.find("last_line_first_pixel_lon");
+      lon = atof(lon_str);
+      lat_str = kwl.find("last_line_first_pixel_lat");
+      lat = atof(lat_str);
+      if (lon > 180.0) lon -= 360.0;
+      ossimDpt imageGCP4(0,theImageSize.y-1);
+      ossimGpt groundGCP4(lat, lon, 0.0);
+      groundGcpCoordinates.push_back(groundGCP4) ;
+      imageGcpCoordinates.push_back(imageGCP4) ;
+
+      // Default optimization
+      optimizeModel(groundGcpCoordinates, imageGcpCoordinates) ;
+      */
+
+      return true;
+   }
+
+// Note: Products georeferenced to ground range are not handled in AlosPalsarModel
+//  therefore the following method will not be used
+   bool ossimAlosPalsarModel::InitSRGR(const ossimKeywordlist& /* kwl */, const char* /* prefix */)
+   {
+      // TODO Add user warning and reference to ERS Model
+      return false;
+   }
+
+   bool ossimAlosPalsarModel::isAlosPalsarLeader(const ossimFilename& file) const
+   {
+      std::ifstream candidate(file.c_str(), ios::in | ios::binary);
+      char alosFileName[16];
+
+      candidate.seekg(48);
+      if (candidate.bad() || candidate.eof())
+      {
+         return false;
+      }
+      candidate.read(alosFileName, 16);
+      if (candidate.bad() || candidate.eof())
+      {
+         return false;
+      }
+      candidate.close();
+
+      ossimString ersString(alosFileName);
+
+      if ((ersString.find("AL1 ") == 0) &&
+          (ersString.find("PSR") == 4)  &&
+          (ersString.find("SARL") == 8))
+      {
+         return true;
+      }
+      else
+      {
+         return false;
+      }
+
+      return true;
+
+   }
+
+   ossimFilename ossimAlosPalsarModel::findAlosPalsarLeader(const ossimFilename& file) const
+   {
+      ossimFilename leaFile = file;
+      ossimString imgPrefix("IMG");
+      ossimString trlPrefix("TRL");
+      ossimString volPrefix("VOL");
+      ossimString leaPrefix("LED");
+
+      ossimString filename = file.fileNoExtension();
+      ossimString prefix = filename.substr(0, 3);
+
+      if ((prefix == imgPrefix) ||
+          (prefix == trlPrefix) ||
+          (prefix == volPrefix))
+      {
+         // Find the 2nd dash from the end of the string
+         // since ALOS files are of the form
+         // <prefix>-ALPSRP<identifier>-H<n.n>__A
+         filename.replace(0, prefix.size(), leaPrefix);
+
+         leaFile.setFile(filename);
+         if (leaFile.exists())
+         {
+            return leaFile;
+         }
+      }
+      return file;
+   }
+
+   bool ossimAlosPalsarModel::isAlosPalsarData(const ossimFilename& file) const
+   {
+      std::ifstream candidate(file.c_str(), ios::in | ios::binary);
+      char alosFileName[16];
+
+      candidate.seekg(48);
+      if (candidate.bad() || candidate.eof())
+      {
+         return false;
+      }
+      candidate.read(alosFileName, 16);
+      if (candidate.bad() || candidate.eof())
+      {
+         return false;
+      }
+      candidate.close();
+
+      ossimString ersString(alosFileName);
+
+      if ((ersString.find("AL1 ") == 0) &&
+          (ersString.find("PSR") == 4)  &&
+          (ersString.find("IMOP") == 8))
+      {
+         return true;
+      }
+      else
+      {
+         return false;
+      }
+
+      return true;
+   }
+
+   ossimFilename ossimAlosPalsarModel::findAlosPalsarData(const ossimFilename& file) const
+   {
+      ossimFilename dataFile = file;
+      ossimString imgPrefix("IMG-HH"); // Assume the ALOS data always has at least the HH
+      ossimString trlPrefix("TRL");
+      ossimString volPrefix("VOL");
+      ossimString leaPrefix("LED");
+
+      ossimString filename = file.fileNoExtension();
+      ossimString prefix = filename.substr(0, 3);
+      if ((prefix == leaPrefix) ||
+          (prefix == trlPrefix) ||
+          (prefix == volPrefix))
+      {
+         // Find the 2nd dash from the end of the string
+         // since ALOS files are of the form
+         // <prefix>-ALPSRP<identifier>-H<n.n>__A
+         filename.replace(0, prefix.size(), imgPrefix);
+
+         dataFile.setFile(filename);
+         if (dataFile.exists())
+         {
+            return dataFile;
+         }
+      }
+      return file;
+   }
+
+} // namespace ossimplugins
+
diff --git a/ossim_plugins/ossim/ossimAlosPalsarModel.h b/ossim_plugins/ossim/ossimAlosPalsarModel.h
new file mode 100644
index 0000000..f2364f9
--- /dev/null
+++ b/ossim_plugins/ossim/ossimAlosPalsarModel.h
@@ -0,0 +1,132 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+// "Copyright Centre for Remote Imaging, Sensing and Processing"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef ossimAlosPalsarModel_H
+#define ossimAlosPalsarModel_H 1
+
+#include <otb/JSDDateTime.h>
+#include <ossimGeometricSarSensorModel.h>
+
+#include <ossim/projection/ossimMapProjection.h>
+#include <ossim/base/ossimIpt.h>
+#include <ossim/base/ossimFilename.h>
+#include <ossim/base/ossimGpt.h>
+#include <ossim/base/ossimDpt.h>
+
+#include <iostream>
+
+namespace ossimplugins
+{
+
+class PlatformPosition;
+class SensorParams;
+class RefPoint;
+class AlosPalsarLeader;
+class AlosPalsarData;
+
+/**
+ * @brief This class is able to direct localisation and indirect
+ * localisation using the AlosPalsar sensor model. It support at least
+ * level 1.1 data (SLC).
+ *
+ */
+class OSSIM_PLUGINS_DLL ossimAlosPalsarModel : public ossimGeometricSarSensorModel
+{
+public:
+  /**
+   * @brief Constructor
+   */
+  ossimAlosPalsarModel();
+
+  /**
+   * @brief Destructor
+   */
+  virtual ~ossimAlosPalsarModel();
+
+  /**
+   * @brief Method to return the class name.
+   * @return The name of this class.
+   */
+  virtual ossimString getClassName() const;
+
+  /**
+   * @brief Returns pointer to a new instance, copy of this.
+   */
+  virtual ossimObject* dup() const;
+
+  /**
+   * @brief This function associates an image column number to a slant range when the image is georeferenced (ground projected)
+   * @param col Column coordinate of the image point
+   */
+  virtual double getSlantRangeFromGeoreferenced(double col) const;
+
+  /**
+  * @brief Method to instantiate model from the leader file.
+  * @param file
+  * @return true on success, false on error.
+  */
+  bool open(const ossimFilename& file);
+
+  /**
+   * @brief Method to save object state to a keyword list.
+   * @param kwl Keyword list to save to.
+   * @param prefix added to keys when saved.
+   * @return true on success, false on error.
+   */
+  virtual bool saveState(ossimKeywordlist& kwl,
+                         const char* prefix = 0) const;
+
+  /**
+   * @brief Method to the load (recreate) the state of the object from a
+   * keyword list. Return true if ok or false on error.
+   * @return true if load OK, false on error
+   */
+  virtual bool loadState(const ossimKeywordlist &kwl, const char *prefix = 0);
+
+protected:
+  virtual bool InitPlatformPosition(const ossimKeywordlist &kwl, const char *prefix);
+  virtual bool InitSensorParams(const ossimKeywordlist &kwl, const char *prefix);
+  virtual bool InitRefPoint(const ossimKeywordlist &kwl, const char *prefix);
+  /**
+  * @brief Initializes the Slant Range for each Ground Range data sets : theNumberSRGR,theSRGRCoeffset,_srgr_update,thePixelSpacing,_isProductGeoreferenced
+  */
+  virtual bool InitSRGR(const ossimKeywordlist &kwl, const char *prefix);
+
+private:
+  /**
+   * @brief Pixel spacing
+   */
+  double thePixelSpacing;
+
+  /**
+   * @brief List of metadata contained in the Leader file
+   */
+  AlosPalsarLeader *theAlosPalsarLeader;
+
+  /**
+   * @brief List of metadata contained in the Data file
+   */
+  AlosPalsarData *theAlosPalsarData;
+
+  virtual bool isAlosPalsarLeader(const ossimFilename& file) const;
+  virtual ossimFilename findAlosPalsarLeader(const ossimFilename& file) const;
+
+  virtual bool isAlosPalsarData(const ossimFilename& file) const;
+  virtual ossimFilename findAlosPalsarData(const ossimFilename& file) const;
+
+  TYPE_DATA
+
+};
+
+}
+#endif
+
diff --git a/ossim_plugins/ossim/ossimCosmoSkymedModel.cpp b/ossim_plugins/ossim/ossimCosmoSkymedModel.cpp
new file mode 100644
index 0000000..86e57e8
--- /dev/null
+++ b/ossim_plugins/ossim/ossimCosmoSkymedModel.cpp
@@ -0,0 +1,398 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include <cmath>
+#include <cstdio>
+
+#include <ossimCosmoSkymedModel.h>
+
+#include <otb/GalileanEphemeris.h>
+#include <otb/GeographicEphemeris.h>
+#include <otb/GMSTDateTime.h>
+
+#include <otb/PlatformPosition.h>
+#include <otb/SensorParams.h>
+#include <otb/RefPoint.h>
+#include <otb/SarSensor.h>
+
+namespace ossimplugins
+{
+
+RTTI_DEF1(ossimCosmoSkymedModel, "ossimCosmoSkymedModel", ossimGeometricSarSensorModel);
+
+ossimCosmoSkymedModel::ossimCosmoSkymedModel():
+  _nbCol(0),
+  _SrGr_R0(0),
+  _sceneCenterRangeTime(0),
+  _pixel_spacing(0)
+{
+}
+
+ossimCosmoSkymedModel::~ossimCosmoSkymedModel()
+{
+}
+
+double ossimCosmoSkymedModel::getSlantRangeFromGeoreferenced(double col) const
+{
+  // in the case of Georeferenced images, _refPoint->get_distance() contains the ground range
+  double relativeGroundRange = _refPoint->get_distance() + _sensor->get_col_direction() * (col-_refPoint->get_pix_col())* _pixel_spacing ;
+
+  double slantRange = _SrGr_coeffs[0]
+              + _SrGr_coeffs[1]*(relativeGroundRange-_SrGr_R0)
+              + _SrGr_coeffs[2]*(pow(relativeGroundRange,2)-_SrGr_R0)
+              + _SrGr_coeffs[3]*(pow(relativeGroundRange,3)-_SrGr_R0)
+              + _SrGr_coeffs[4]*(pow(relativeGroundRange,4)-_SrGr_R0)
+              + _SrGr_coeffs[5]*(pow(relativeGroundRange,5)-_SrGr_R0);
+
+  return  slantRange ;
+}
+
+bool ossimCosmoSkymedModel::InitSensorParams(const ossimKeywordlist &kwl, const char *prefix)
+{
+  const char* central_freq_str = kwl.find(prefix,"central_freq");
+  double central_freq = atof(central_freq_str);
+  const char* fr_str = kwl.find(prefix,"fr");
+  double fr = atof(fr_str);
+  const char* fa_str = kwl.find(prefix,"fa");
+  double fa = atof(fa_str);
+
+  //number of different looks
+  const char* n_azilok_str = kwl.find(prefix,"n_azilok");
+  double n_azilok = atof(n_azilok_str);
+  const char* n_rnglok_str = kwl.find(prefix,"n_rnglok");
+  double n_rnglok = atof(n_rnglok_str);
+
+  //ellipsoid parameters
+  const char* ellip_maj_str = kwl.find(prefix,"ellip_maj");
+  double ellip_maj = atof(ellip_maj_str) * 1000.0;  // km -> m
+  const char* ellip_min_str = kwl.find(prefix,"ellip_min");
+  double ellip_min = atof(ellip_min_str) * 1000.0;  // km -> m
+
+  if(_sensor != NULL)
+  {
+    delete _sensor;
+  }
+
+  _sensor = new SensorParams();
+
+
+  /**
+  * @todo : � voir sur de vrais produits (exemples de DESCENDING et ASCENDING)
+  */
+  const char* orbitDirection_str = kwl.find(prefix,"orbitDirection");
+  std::string orbitDirection(orbitDirection_str) ;
+  int orbitDirectionSign ;
+  if (orbitDirection=="DESCENDING") orbitDirectionSign = 1 ;
+  else orbitDirectionSign = - 1 ;
+
+  const char* lookDirection_str = kwl.find(prefix,"lookDirection");
+  std::string lookDirection(lookDirection_str) ;
+  if ((lookDirection == "Right")||(lookDirection == "RIGHT")) _sensor->set_sightDirection(SensorParams::Right) ;
+  else _sensor->set_sightDirection(SensorParams::Left) ;
+
+  const char* colsOrder_str = kwl.find(prefix,"colsOrder");
+  std::string colsOrder(colsOrder_str) ;
+  const char* linsOrder_str = kwl.find(prefix,"linsOrder");
+  std::string linsOrder(linsOrder_str) ;
+  if (colsOrder=="NEAR-FAR")
+    _sensor->set_col_direction(orbitDirectionSign);
+  else _sensor->set_col_direction(-orbitDirectionSign);
+  if (linsOrder=="NEAR-FAR")
+    _sensor->set_lin_direction(orbitDirectionSign);
+  else _sensor->set_lin_direction(-orbitDirectionSign);
+
+  _sensor->set_sf(fr);
+  const double CLUM        = 2.99792458e+8 ;
+  double wave_length = CLUM / central_freq ;
+  _sensor->set_rwl(wave_length);
+  _sensor->set_nAzimuthLook(n_azilok);
+  _sensor->set_nRangeLook(n_rnglok);
+
+  // fa is the processing PRF
+  _sensor->set_prf(fa * n_azilok);
+
+  _sensor->set_semiMajorAxis(ellip_maj) ;
+  _sensor->set_semiMinorAxis(ellip_min) ;
+
+  return true;
+}
+
+bool ossimCosmoSkymedModel::InitPlatformPosition(const ossimKeywordlist &kwl, const char *prefix)
+{
+  /*
+   * Retrieval of ephemerisis number
+   */
+  const char* neph_str = kwl.find(prefix,"neph");
+  int neph = atoi(neph_str);
+
+  /*
+   * Retrieval of reference date
+   */
+  const char* referenceUTC_str = kwl.find(prefix,"referenceUTC");
+  std::string referenceUTC(referenceUTC_str) ;
+  CivilDateTime ref_civil_date;
+  if (! UtcDateTimeStringToCivilDate(referenceUTC, ref_civil_date)) return false;
+
+  /*
+   * Retrieval of ephemerisis
+   */
+  Ephemeris** ephemeris = new Ephemeris*[neph];
+  for (int i = 0; i < neph; ++i)
+  {
+    double pos[3];
+    double vit[3];
+    char name[64];
+
+    sprintf(name,"eph%i_date",i);
+    const char* date_str = kwl.find(prefix,name);
+    float relative_date = atof(date_str);
+
+    sprintf(name,"eph%i_posX",i);
+    const char* px_str = kwl.find(prefix,name);
+    pos[0] = atof(px_str);
+
+    sprintf(name,"eph%i_posY",i);
+    const char* py_str = kwl.find(prefix,name);
+    pos[1] = atof(py_str);
+
+    sprintf(name,"eph%i_posZ",i);
+    const char* pz_str = kwl.find(prefix,name);
+    pos[2] = atof(pz_str);
+
+    sprintf(name,"eph%i_velX",i);
+    const char* vx_str = kwl.find(prefix,name);
+    vit[0] = atof(vx_str) ;
+
+    sprintf(name,"eph%i_velY",i);
+    const char* vy_str = kwl.find(prefix,name);
+    vit[1] = atof(vy_str) ;
+
+    sprintf(name,"eph%i_velZ",i);
+    const char* vz_str = kwl.find(prefix,name);
+    vit[2] = atof(vz_str) ;
+    /*
+     * Conversion to JSD Date
+     */
+    int second = (int) relative_date ;
+    double decimal = relative_date - second ;
+    CivilDateTime eph_civil_date(ref_civil_date.get_year(), ref_civil_date.get_month(), ref_civil_date.get_day(), second, decimal);
+    JSDDateTime eph_jsd_date(eph_civil_date);
+
+    GeographicEphemeris* eph = new GeographicEphemeris(eph_jsd_date,pos,vit);
+
+    ephemeris[i] = eph;
+  }
+
+  /*
+   * Creation of the platform position interpolator
+   */
+  if (_platformPosition != NULL)
+  {
+    delete _platformPosition;
+  }
+  _platformPosition = new PlatformPosition(ephemeris,neph);
+
+  /*
+   * Free of memory used by ephemerisis list : the constructor copies the ephemerisis
+   */
+  for (int i=0;i<neph;i++)
+  {
+    delete ephemeris[i];
+  }
+  delete[] ephemeris;
+
+  return true;
+}
+
+bool ossimCosmoSkymedModel::InitRefPoint(const ossimKeywordlist &kwl, const char *prefix)
+{
+   const char* sc_lin_str = kwl.find(prefix,"sc_lin");
+   double sc_lin = atof(sc_lin_str);
+
+   const char* sc_pix_str = kwl.find(prefix,"sc_pix");
+   double sc_pix = atof(sc_pix_str);
+
+   // const char* pixel_spacing_str = kwl.find(prefix,"pixel_spacing");
+   // double pixel_spacing = atof(pixel_spacing_str);
+
+   const char* azimuthStartTime_str = kwl.find(prefix,"azimuthStartTime");
+   double azimuthStartTime = atof(azimuthStartTime_str);
+
+   const char* rng_gate_str = kwl.find(prefix,"rng_gate");
+   double rng_gate = atof(rng_gate_str);
+
+   const char* referenceUTC_str = kwl.find(prefix,"referenceUTC");
+   std::string referenceUTC(referenceUTC_str) ;
+   CivilDateTime ref_civil_date;
+   if (! UtcDateTimeStringToCivilDate(referenceUTC, ref_civil_date)) return false;
+
+   if(_refPoint == NULL)
+   {
+      _refPoint = new RefPoint();
+   }
+
+   _refPoint->set_pix_col(sc_pix);
+   _refPoint->set_pix_line(sc_lin);
+
+   double relative_date = (azimuthStartTime + sc_lin/_sensor->get_prf());
+   int second = (int) relative_date ;
+   double decimal = relative_date - second ;
+
+   if(_platformPosition != NULL)
+   {
+      CivilDateTime * date = new CivilDateTime(
+         ref_civil_date.get_year(), ref_civil_date.get_month(),
+         ref_civil_date.get_day(), second, decimal);
+      
+      Ephemeris * ephemeris = _platformPosition->Interpolate((JSDDateTime)*date);
+      if (ephemeris == NULL) return false ;
+
+      _refPoint->set_ephemeris(ephemeris);
+
+      delete date;
+      date = 0;
+      delete ephemeris;
+      ephemeris = 0;
+   }
+   else
+   {
+      return false;
+   }
+
+   double c = 2.99792458e+8;
+   double distance = (rng_gate + sc_pix*_sensor->get_nRangeLook()/_sensor->get_sf()) * (c/2.0);
+
+   // in the case of Georeferenced images, the "relative" ground range is stored in place of the slant range
+   // (used for SlantRange computation relative to reference point, necessary for optimization)
+   // here, the pixelDirection is ignored since the CSKS reference point is always at the scene centre
+   if (_isProductGeoreferenced) {
+      distance = _refPoint->get_pix_col() * _pixel_spacing ;
+   }
+
+   _refPoint->set_distance(distance);
+
+
+   // in order to use ossimSensorModel::lineSampleToWorld
+   const char* nbCol_str = kwl.find(prefix,"nbCol");
+   const char* nbLin_str = kwl.find(prefix,"nbLin");
+   theImageSize.x      = atoi(nbCol_str);
+   theImageSize.y      = atoi(nbLin_str);
+   theImageClipRect    = ossimDrect(0, 0, theImageSize.x-1, theImageSize.y-1);
+
+
+   // Ground Control Points extracted from the model : scene center and corners
+   std::list<ossimGpt> groundGcpCoordinates ;
+   std::list<ossimDpt> imageGcpCoordinates ;
+   char name[64];
+   for (int k=0 ; k<5 ; k++) {
+      sprintf(name,"cornersCol%i",k);
+      const char* i_str = kwl.find(name);
+      int i = atoi(i_str);
+      sprintf(name,"cornersLin%i",k);
+      const char* j_str = kwl.find(name);
+      int j = atoi(j_str);
+      sprintf(name,"cornersLon%i",k);
+      const char* lon_str = kwl.find(name);
+      double lon = atof(lon_str);
+      sprintf(name,"cornersLat%i",k);
+      const char* lat_str = kwl.find(name);
+      double lat = atof(lat_str);
+      sprintf(name,"cornersHeight%i",k);
+      const char* height_str = kwl.find(name);
+      double height = atof(height_str) ;
+
+      ossimDpt imageGCP(i,j);
+      ossimGpt groundGCP(lat, lon, height);
+      groundGcpCoordinates.push_back(groundGCP) ;
+      imageGcpCoordinates.push_back(imageGCP) ;
+   }
+
+   // Default optimization
+   optimizeModel(groundGcpCoordinates, imageGcpCoordinates) ;
+
+  return true;
+}
+
+bool ossimCosmoSkymedModel::InitSRGR(const ossimKeywordlist &kwl, const char *prefix)
+{
+  const char* rangeProjectionType_str = kwl.find(prefix,"rangeProjectionType");
+  std::string rangeProjectionType(rangeProjectionType_str);
+
+  const char* pixel_spacing_str = kwl.find(prefix,"pixel_spacing");
+  _pixel_spacing= atof(pixel_spacing_str);
+
+  _isProductGeoreferenced = (rangeProjectionType=="GROUNDRANGE") ;
+
+  // Number of columns
+  const char* nbCol_str = kwl.find(prefix,"nbCol");
+  _nbCol = atoi(nbCol_str);
+
+  // SRGR polynomial reference
+  const char* SrGr_R0_str = kwl.find(prefix,"SrGr_R0");
+  _SrGr_R0 = atof(SrGr_R0_str);
+
+  // SRGR coefficients
+  char name[64];
+  double coeff ;
+  for(int i=0;i<6;i++)
+  {
+    sprintf(name,"SrToGr_coeffs_%i",i);
+    const char* coeff_str = kwl.find(prefix,name);
+    coeff = atof(coeff_str);
+    _SrGr_coeffs.push_back(coeff);
+  }
+
+  return true;
+}
+
+
+bool ossimCosmoSkymedModel::UtcDateTimeStringToCivilDate(const std::string &utcString, CivilDateTime &outputDate) {
+  // conversion :
+  // try with date format yyyymmdd
+
+  if (utcString.size() < 8) return false ;
+  const char* stringUTCDate =  utcString.c_str() ;
+
+   char year_str[5];
+  for (int i=0;i<4;i++)
+  {
+    year_str[i] = stringUTCDate[i];
+  }
+  year_str[4] = '\0';
+
+  char month_str[3];
+  for (int i=4;i<6;i++)
+  {
+    month_str[i-4] = stringUTCDate[i];
+  }
+  month_str[2] = '\0';
+
+  char day_str[3];
+  for (int i=6;i<8;i++)
+  {
+    day_str[i-6] = stringUTCDate[i];
+  }
+  day_str[2] = '\0';
+
+  outputDate.set_year(atoi(year_str));
+  outputDate.set_month(atoi(month_str));
+  outputDate.set_day(atoi(day_str));
+  outputDate.set_second(0);
+  outputDate.set_decimal(0.0);
+
+  return true ;
+}
+
+
+}
+
+
+
diff --git a/ossim_plugins/ossim/ossimCosmoSkymedModel.h b/ossim_plugins/ossim/ossimCosmoSkymedModel.h
new file mode 100644
index 0000000..08c4cba
--- /dev/null
+++ b/ossim_plugins/ossim/ossimCosmoSkymedModel.h
@@ -0,0 +1,96 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef ossimCosmoSkymedModel_H
+#define ossimCosmoSkymedModel_H
+
+#include <ossimGeometricSarSensorModel.h>
+#include <ossim/projection/ossimMapProjection.h>
+#include <ossim/base/ossimIpt.h>
+#include <ossim/base/ossimFilename.h>
+#include <ossim/base/ossimGpt.h>
+#include <ossim/base/ossimDpt.h>
+
+#include <otb/CivilDateTime.h>
+
+#include <iostream>
+#include <list>
+
+namespace ossimplugins
+{
+
+class PlatformPosition;
+class SensorParams;
+class RefPoint;
+/**
+ * @brief This class allows for direct localisation and indirect localisation
+ * using the CosmoSkymed sensor model
+ */
+class ossimCosmoSkymedModel : public ossimGeometricSarSensorModel
+{
+public:
+  /**
+   * @brief Constructor
+   */
+  ossimCosmoSkymedModel();
+
+  /**
+   * @brief Destructor
+   */
+  ~ossimCosmoSkymedModel();
+
+  /**
+   * @brief This function associates an image column number to a slant range when the image is georeferenced (ground projected)
+   * @param col Column coordinate of the image point
+   */
+  virtual double getSlantRangeFromGeoreferenced(double col) const;
+
+protected:
+
+  /**
+   * @brief Number of columns
+   */
+  double _nbCol;
+  /**
+  * @brief Slant Range for each Ground Range Projection reference point
+  */
+  double _SrGr_R0 ;
+  /**
+  * @brief Slant Range for each Ground Range Projection coefficients
+  */
+  std::vector<double> _SrGr_coeffs ;
+  /**
+   * @brief Scene Center range time
+   */
+  double _sceneCenterRangeTime;
+  /**
+   * @brief Pixel spacing
+   */
+  double _pixel_spacing ;
+
+private:
+  virtual bool InitPlatformPosition(const ossimKeywordlist &kwl, const char *prefix);
+  virtual bool InitSensorParams(const ossimKeywordlist &kwl, const char *prefix);
+  virtual bool InitRefPoint(const ossimKeywordlist &kwl, const char *prefix);
+  /**
+   * @brief Initializes the Slant Range to Ground Range data sets :
+   *        _SrToGr_R0,_SrToGr_coeffs_number,_SrToGr_exponent,_SrToGr_coeffs,_nbCol
+   */
+  virtual bool InitSRGR(const ossimKeywordlist &kwl, const char *prefix);
+
+  bool UtcDateTimeStringToCivilDate(const std::string &utcString, CivilDateTime &outputDate);
+
+  TYPE_DATA
+};
+}
+
+#endif
+
diff --git a/ossim_plugins/ossim/ossimEnvisatAsarModel.cpp b/ossim_plugins/ossim/ossimEnvisatAsarModel.cpp
new file mode 100644
index 0000000..edd2c89
--- /dev/null
+++ b/ossim_plugins/ossim/ossimEnvisatAsarModel.cpp
@@ -0,0 +1,678 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include <cmath>
+#include <cstdio>
+
+#include <ossim/base/ossimTrace.h>
+#include <ossim/base/ossimKeywordNames.h>
+
+#include <ossimEnvisatAsarModel.h>
+#include <otb/GalileanEphemeris.h>
+#include <otb/GeographicEphemeris.h>
+
+#include <otb/GMSTDateTime.h>
+#include <otb/CivilDateTime.h>
+#include <otb/MJDDateTime.h>
+
+#include <otb/PlatformPosition.h>
+#include <otb/SensorParams.h>
+#include <otb/RefPoint.h>
+#include <otb/SarSensor.h>
+
+namespace ossimplugins
+{
+
+
+   RTTI_DEF1(ossimEnvisatAsarModel, "ossimEnvisatAsarModel", ossimGeometricSarSensorModel);
+
+// Static trace for debugging
+   static ossimTrace traceDebug("ossimEnvisatAsarModel:debug");
+
+   ossimEnvisatAsarModel::ossimEnvisatAsarModel():
+      _n_srgr(0),
+      _pixel_spacing(0),
+      _EnvisatAsarData(NULL)
+   {
+   }
+
+
+
+   ossimEnvisatAsarModel::~ossimEnvisatAsarModel()
+   {
+      if(_EnvisatAsarData != NULL)
+      {
+         delete _EnvisatAsarData;
+      }
+   }
+
+   ossimString ossimEnvisatAsarModel::getClassName() const
+   {
+      return ossimString("ossimEnvisatAsarModel");
+   }
+
+   ossimObject* ossimEnvisatAsarModel::dup() const
+   {
+      return new ossimEnvisatAsarModel(*this);
+   }
+
+   double ossimEnvisatAsarModel::getSlantRangeFromGeoreferenced(double col) const
+   {
+      // const double CLUM        = 2.99792458e+8 ;
+
+      double GR, GR0, relativeGroundRange, slantRange; // , slantrangetime;
+
+      if (_n_srgr==0) return(-1) ;
+
+      std::vector<double> coefset = FindSRGRSetNumber((_refPoint->get_ephemeris())->get_date()) ;
+
+      GR = _sensor->get_col_direction() * (col)* _pixel_spacing ;
+      GR0 = coefset[0];
+      relativeGroundRange = GR-GR0;
+      slantRange = coefset[1]
+         + coefset[2]*relativeGroundRange
+         + coefset[3]*pow(relativeGroundRange,2)
+         + coefset[4]*pow(relativeGroundRange,3)
+         + coefset[5]*pow(relativeGroundRange,4);
+
+      // slantrangetime = 2.0*slantRange / (CLUM);
+      return  slantRange ;
+   }
+
+
+   bool ossimEnvisatAsarModel::open(const ossimFilename& file)
+   {
+      bool retValue = true;
+
+      if (traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG) << "ossimEnvisatAsarTileSource::open(filename) DEBUG: entered..." << std::endl
+                                             << "Attempting to open file " << file << std::endl;
+      }
+
+      /*
+       * Creation of the class allowing to store EnvisatAsarData file metadata
+       */
+      if (_EnvisatAsarData != NULL)
+      {
+         delete _EnvisatAsarData;
+         _EnvisatAsarData = NULL;
+      }
+
+      /*
+       * Opening and test of the file
+       */
+      ossimFilename Filename = file;
+      ifstream dataFile(Filename.c_str(), ios::in | ios::binary);
+      if (dataFile.eof())
+      {
+         dataFile.close();
+         retValue = false;
+      }
+      else
+      {
+         mph mph_rec;
+         dataFile >> mph_rec;
+
+         // test if it is an ENVISAT Data file
+         if (mph_rec.is_valid())
+         {
+            if (traceDebug())
+            {
+               ossimNotify(ossimNotifyLevel_DEBUG) << "Begin reading EnvisatAsar file" << std::endl;
+            }
+            /*
+             * Reading EnvisatAsarData file data
+             */
+            dataFile.seekg(0);
+            _EnvisatAsarData = new EnvisatAsarData();
+            dataFile >> *_EnvisatAsarData;
+            dataFile.close();
+            if (traceDebug())
+            {
+               ossimNotify(ossimNotifyLevel_DEBUG) << "End reading EnvisatAsar file" << std::endl;
+            }
+         }
+         else
+         {
+            dataFile.close();
+            retValue = false;
+         }
+      }
+
+      if (traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG) << "ossimEnvisatAsarTileSource::open() DEBUG: returning..." << std::endl;
+      }
+
+      return retValue;
+   }
+
+
+   bool ossimEnvisatAsarModel::saveState(ossimKeywordlist& kwl,
+                                         const char* prefix) const
+   {
+      char name[64];
+
+      kwl.add(prefix, ossimKeywordNames::TYPE_KW, "ossimEnvisatAsarModel", true);
+
+      /*
+       * Adding metadata necessary to the sensor model into the keywordlist
+       * Data derived from the SPH record
+       */
+      sph* sph_rec = _EnvisatAsarData->get_sph();
+      if(sph_rec != NULL)
+      {
+         kwl.add(prefix, "pixel_spacing", sph_rec->get_range_spacing().c_str(), true );
+         kwl.add(prefix, "line_time_interval", sph_rec->get_line_time_interval().c_str(), true );
+      }
+      else
+      {
+         return false;
+      }
+      /*
+       * Adding metadata necessary to the sensor model into the keywordlist
+       * Data derived from the Main Processing Parameters record
+       */
+      MainProcessingParameters* MPP_rec = _EnvisatAsarData->get_MainProcessingParameters();
+      if(MPP_rec != NULL)
+      {
+         kwl.add(prefix, "num_pix", (double)MPP_rec->get_num_samples_per_line(), true );
+         kwl.add(prefix, "num_lines", (double)MPP_rec->get_num_output_lines(), true );
+         kwl.add(prefix, "wave_length", MPP_rec->get_radar_freq(), true );
+         kwl.add(prefix, "range_sampling_rate", MPP_rec->get_range_samp_rate(), true );
+         kwl.add(prefix, "prf", MPP_rec->get_prf(), true );
+         kwl.add(prefix, "avg_scene_height", MPP_rec->get_avg_scene_height_ellpsoid(), true );
+         kwl.add(prefix, "is_groundrange", MPP_rec->get_srgr_flag(), true );
+         kwl.add(prefix, "state_vector_time_1_day", (double)MPP_rec->get_state_vector_time_1_day(), true );
+         kwl.add(prefix, "state_vector_time_1_sec", (double)MPP_rec->get_state_vector_time_1_sec(), true );
+         kwl.add(prefix, "state_vector_time_1_microsec", (double)MPP_rec->get_state_vector_time_1_microsec(), true );
+         kwl.add(prefix, "x_pos_1", (double)MPP_rec->get_x_pos_1(), true );
+         kwl.add(prefix, "y_pos_1", (double)MPP_rec->get_y_pos_1(), true );
+         kwl.add(prefix, "z_pos_1", (double)MPP_rec->get_z_pos_1(), true );
+         kwl.add(prefix, "x_vel_1", (double)MPP_rec->get_x_vel_1(), true );
+         kwl.add(prefix, "y_vel_1", (double)MPP_rec->get_y_vel_1(), true );
+         kwl.add(prefix, "z_vel_1", (double)MPP_rec->get_z_vel_1(), true );
+         kwl.add(prefix, "state_vector_time_2_day",(double) MPP_rec->get_state_vector_time_2_day(), true );
+         kwl.add(prefix, "state_vector_time_2_sec", (double)MPP_rec->get_state_vector_time_2_sec(), true );
+         kwl.add(prefix, "state_vector_time_2_microsec", (double)MPP_rec->get_state_vector_time_2_microsec(), true );
+         kwl.add(prefix, "x_pos_2", (double)MPP_rec->get_x_pos_2(), true );
+         kwl.add(prefix, "y_pos_2", (double)MPP_rec->get_y_pos_2(), true );
+         kwl.add(prefix, "z_pos_2", (double)MPP_rec->get_z_pos_2(), true );
+         kwl.add(prefix, "x_vel_2", (double)MPP_rec->get_x_vel_2(), true );
+         kwl.add(prefix, "y_vel_2", (double)MPP_rec->get_y_vel_2(), true );
+         kwl.add(prefix, "z_vel_2", (double)MPP_rec->get_z_vel_2(), true );
+         kwl.add(prefix, "state_vector_time_3_day", (double)MPP_rec->get_state_vector_time_3_day(), true );
+         kwl.add(prefix, "state_vector_time_3_sec", (double)MPP_rec->get_state_vector_time_3_sec(), true );
+         kwl.add(prefix, "state_vector_time_3_microsec", (double)MPP_rec->get_state_vector_time_3_microsec(), true );
+         kwl.add(prefix, "x_pos_3", (double)MPP_rec->get_x_pos_3(), true );
+         kwl.add(prefix, "y_pos_3", (double)MPP_rec->get_y_pos_3(), true );
+         kwl.add(prefix, "z_pos_3", (double)MPP_rec->get_z_pos_3(), true );
+         kwl.add(prefix, "x_vel_3", (double)MPP_rec->get_x_vel_3(), true );
+         kwl.add(prefix, "y_vel_3", (double)MPP_rec->get_y_vel_3(), true );
+         kwl.add(prefix, "z_vel_3", (double)MPP_rec->get_z_vel_3(), true );
+         kwl.add(prefix, "state_vector_time_4_day", (double)MPP_rec->get_state_vector_time_4_day(), true );
+         kwl.add(prefix, "state_vector_time_4_sec", (double)MPP_rec->get_state_vector_time_4_sec(), true );
+         kwl.add(prefix, "state_vector_time_4_microsec", (double)MPP_rec->get_state_vector_time_4_microsec(), true );
+         kwl.add(prefix, "x_pos_4", (double)MPP_rec->get_x_pos_4(), true );
+         kwl.add(prefix, "y_pos_4", (double)MPP_rec->get_y_pos_4(), true );
+         kwl.add(prefix, "z_pos_4", (double)MPP_rec->get_z_pos_4(), true );
+         kwl.add(prefix, "x_vel_4", (double)MPP_rec->get_x_vel_4(), true );
+         kwl.add(prefix, "y_vel_4", (double)MPP_rec->get_y_vel_4(), true );
+         kwl.add(prefix, "z_vel_4", (double)MPP_rec->get_z_vel_4(), true );
+         kwl.add(prefix, "state_vector_time_5_day", (double)MPP_rec->get_state_vector_time_5_day(), true );
+         kwl.add(prefix, "state_vector_time_5_sec", (double)MPP_rec->get_state_vector_time_5_sec(), true );
+         kwl.add(prefix, "state_vector_time_5_microsec", (double)MPP_rec->get_state_vector_time_5_microsec(), true );
+         kwl.add(prefix, "x_pos_5", (double)MPP_rec->get_x_pos_5(), true );
+         kwl.add(prefix, "y_pos_5",(double) MPP_rec->get_y_pos_5(), true );
+         kwl.add(prefix, "z_pos_5", (double)MPP_rec->get_z_pos_5(), true );
+         kwl.add(prefix, "x_vel_5", (double)MPP_rec->get_x_vel_5(), true );
+         kwl.add(prefix, "y_vel_5", (double)MPP_rec->get_y_vel_5(), true );
+         kwl.add(prefix, "z_vel_5", (double)MPP_rec->get_z_vel_5(), true );
+      }
+      else
+      {
+         return false;
+      }
+      /*
+       * Adding metadata necessary to the sensor model into the keywordlist
+       * Data derived from the Geolocation Grid record - Reference Point
+       */
+      GeolocationGrid* GG_rec = _EnvisatAsarData->get_GeolocationGrid(0);
+      if(GG_rec != NULL)
+      {
+         kwl.add(prefix, "first_zero_doppler_time_day", (double)GG_rec->get_first_zero_doppler_time_day(), true );
+         kwl.add(prefix, "first_zero_doppler_time_sec", (double)GG_rec->get_first_zero_doppler_time_sec(), true );
+         kwl.add(prefix, "first_zero_doppler_time_microsec", (double)GG_rec->get_first_zero_doppler_time_microsec(), true );
+         kwl.add(prefix, "line_num", (double)GG_rec->get_line_num(), true );
+         kwl.add(prefix, "samp_num", (double)(GG_rec->get_samp_numbers())[0], true );
+         kwl.add(prefix, "slant_range_time", (double)(GG_rec->get_slant_range_times())[0], true );
+      }
+      else
+      {
+         return false;
+      }
+      /*
+       * Adding metadata necessary to the sensor model into the keywordlist
+       * Data derived from the Geolocation Grid record - Corners
+       */
+      GG_rec = _EnvisatAsarData->get_GeolocationGrid(0);
+      if(GG_rec != NULL)
+      {
+         kwl.add(prefix, "UL_line", (double)GG_rec->get_line_num(), true );
+         kwl.add(prefix, "UL_col", (double)(GG_rec->get_samp_numbers())[0], true );
+         kwl.add(prefix, "UL_lat", (double)(GG_rec->get_lats())[0], true );
+         kwl.add(prefix, "UL_lon", (double)(GG_rec->get_longs())[0], true );
+         kwl.add(prefix, "UR_line", (double)GG_rec->get_line_num(), true );
+         kwl.add(prefix, "UR_col", (double)(GG_rec->get_samp_numbers())[10], true );
+         kwl.add(prefix, "UR_lat", (double)(GG_rec->get_lats())[10], true );
+         kwl.add(prefix, "UR_lon", (double)(GG_rec->get_longs())[10], true );
+      }
+      else
+      {
+         return false;
+      }
+      GG_rec = _EnvisatAsarData->get_GeolocationGrid(10);
+      if(GG_rec != NULL)
+      {
+         kwl.add(prefix, "LL_line", (double)GG_rec->get_line_num(), true );
+         kwl.add(prefix, "LL_col", (double)(GG_rec->get_samp_numbers())[0], true );
+         kwl.add(prefix, "LL_lat", (double)(GG_rec->get_lats())[0], true );
+         kwl.add(prefix, "LL_lon", (double)(GG_rec->get_longs())[0], true );
+         kwl.add(prefix, "LR_line", (double)GG_rec->get_line_num(), true );
+         kwl.add(prefix, "LR_col", (double)(GG_rec->get_samp_numbers())[10], true );
+         kwl.add(prefix, "LR_lat", (double)(GG_rec->get_lats())[10], true );
+         kwl.add(prefix, "LR_lon", (double)(GG_rec->get_longs())[10], true );
+      }
+      else
+      {
+         return false;
+      }
+
+      /*
+       * Adding metadata necessary to the sensor model into the keywordlist
+       */
+      int n_srgr = 0;
+      SRGRConversionParameters * SRGRParameters = _EnvisatAsarData->get_SRGRConversionParameters(0);
+      if(SRGRParameters != NULL)
+      {
+         n_srgr = _EnvisatAsarData->get_num_ds(SRGRParameters);
+
+         for (int i=0;i<n_srgr;i++)
+         {
+            SRGRConversionParameters * SRGR = _EnvisatAsarData->get_SRGRConversionParameters(i);
+
+            sprintf(name,"srgr_update_day%i",i);
+            kwl.add(prefix, name, (double)SRGR->get_first_zero_doppler_time_day(),true);
+
+            sprintf(name,"srgr_update_sec%i",i);
+            kwl.add(prefix, name, (double)SRGR->get_first_zero_doppler_time_sec(),true);
+
+            sprintf(name,"srgr_update_microsec%i",i);
+            kwl.add(prefix, name, (double)SRGR->get_first_zero_doppler_time_microsec(),true);
+
+            sprintf(name,"srgr_coef%iA",i);
+            kwl.add(prefix, name,(double)SRGR->get_ground_range_origin(),true);
+
+            sprintf(name,"srgr_coef%iB",i);
+            kwl.add(prefix, name,(double)SRGR->get_srgr_coef()[0],true);
+            sprintf(name,"srgr_coef%iC",i);
+            kwl.add(prefix, name,(double)SRGR->get_srgr_coef()[1],true);
+            sprintf(name,"srgr_coef%iD",i);
+            kwl.add(prefix, name,(double)SRGR->get_srgr_coef()[2],true);
+            sprintf(name,"srgr_coef%iE",i);
+            kwl.add(prefix, name,(double)SRGR->get_srgr_coef()[3]*1e10,true);
+            sprintf(name,"srgr_coef%iF",i);
+            kwl.add(prefix, name,(double)SRGR->get_srgr_coef()[4]*1e10,true);
+         }
+      }
+
+      kwl.add(prefix, "n_srgr" , n_srgr,true);
+
+      return true;
+   }
+
+   bool ossimEnvisatAsarModel::loadState (const ossimKeywordlist &kwl,
+                                          const char *prefix)
+   {
+      InitSensorParams(kwl, prefix);
+      InitPlatformPosition(kwl, prefix);
+      InitRefPoint(kwl, prefix);
+      InitSRGR(kwl, prefix);
+      return true;
+   }
+
+   std::ostream& ossimEnvisatAsarModel::print(std::ostream& out) const
+   {
+      // Capture the original flags.
+      std::ios_base::fmtflags f = out.flags();
+
+      out << setprecision(15) << setiosflags(ios::fixed)
+          << "\nossimEnvisatAsarModel data members:\n"
+          << "_pixel_spacing: " << _pixel_spacing << "\n"
+          << "_n_srgr: " << _n_srgr << "\n";
+
+      ossimGeometricSarSensorModel::print(out);
+
+      // Reset flags.
+      out.setf(f);
+
+
+      return out;
+   }
+
+   bool ossimEnvisatAsarModel::InitSensorParams(const ossimKeywordlist &kwl, const char *prefix)
+   {
+      const double CLUM = 2.99792458e+8;
+      const char* wave_length_str = kwl.find(prefix,"wave_length");
+      double wave_length = CLUM / atof(wave_length_str);
+      const char* fr_str = kwl.find(prefix,"range_sampling_rate");
+      double fr = atof(fr_str);
+
+      // product type : Slant Range or Ground Range
+      _isProductGeoreferenced = atoi(kwl.find(prefix,"is_groundrange"));
+      double fa;
+      if (!_isProductGeoreferenced)
+      {
+         const char* fa_str = kwl.find(prefix,"prf");
+         fa = atof(fa_str);
+      }
+      else
+      {
+         const char* fa_str = kwl.find(prefix,"line_time_interval");
+         fa = 1.0/atof(fa_str);
+      }
+
+      // TODO : v�rifier que ceci est ok pour les produits IMP
+      const char* time_dir_pix = "INCREASE";
+      const char* time_dir_lin = "INCREASE";
+
+      if(_sensor != NULL)
+      {
+         delete _sensor;
+      }
+
+      _sensor = new SensorParams();
+
+      if(strcmp(time_dir_pix, "INCREASE") == 0)
+      {
+         _sensor->set_col_direction(1);
+      }
+      else
+      {
+         _sensor->set_col_direction(-1);
+      }
+
+      if(strcmp(time_dir_lin, "INCREASE") == 0)
+      {
+         _sensor->set_lin_direction(1);
+      }
+      else
+      {
+         _sensor->set_lin_direction(-1);
+      }
+
+      _sensor->set_prf(fa);
+      _sensor->set_sf(fr);
+      _sensor->set_rwl(wave_length);
+
+      return true;
+   }
+
+   bool ossimEnvisatAsarModel::InitPlatformPosition(const ossimKeywordlist &kwl, const char *prefix)
+   {
+      const int neph    = 5;
+      // long val_long;
+      // unsigned long val_ulong1;
+      // unsigned long val_ulong2;
+      CivilDateTime ref_civil_date;
+
+      Ephemeris** ephemeris = new Ephemeris*[neph];
+
+      for (int i=1;i<=neph;i++)
+      {
+         double pos[3];
+         double vel[3];
+         char name[64];
+
+         /*
+          * Date de l'ephemeride
+          */
+         sprintf(name,"state_vector_time_%i_day",i);
+         long day = (long) atof(kwl.find(prefix,name));
+         sprintf(name,"state_vector_time_%i_sec",i);
+         unsigned long sec = (unsigned long) atof(kwl.find(prefix,name));
+         sprintf(name,"state_vector_time_%i_microsec",i);
+         unsigned long microsec = (unsigned long) atof(kwl.find(prefix,name));
+         MJDDateTime mjdDate(day, sec, microsec);
+         JSDDateTime jsd_date(mjdDate);
+         /*
+          * Position de l'ephemeride
+          */
+         sprintf(name,"x_pos_%i",i);
+         pos[0] = (double) atoi(kwl.find(prefix,name)) * 1.0e-2;
+         sprintf(name,"y_pos_%i",i);
+         pos[1] = (double) atoi(kwl.find(prefix,name)) * 1.0e-2;
+         sprintf(name,"z_pos_%i",i);
+         pos[2] = (double) atoi(kwl.find(prefix,name)) * 1.0e-2;
+         /*
+          * Vitesse de l'ephemeride
+          */
+         sprintf(name,"x_vel_%i",i);
+         vel[0] = (double) atoi(kwl.find(prefix,name)) * 1.0e-5;
+         sprintf(name,"y_vel_%i",i);
+         vel[1] = (double) atoi(kwl.find(prefix,name)) * 1.0e-5;
+         sprintf(name,"z_vel_%i",i);
+         vel[2] = (double) atoi(kwl.find(prefix,name)) * 1.0e-5;
+
+         GeographicEphemeris* eph = new GeographicEphemeris(jsd_date, pos, vel);
+
+         ephemeris[i-1] = eph;
+      }
+
+      if (_platformPosition != NULL)
+      {
+         delete _platformPosition;
+      }
+      _platformPosition = new PlatformPosition(ephemeris,neph);
+
+      /*
+       * Liberation de la memoire utilis�e par la liste des ephemerides
+       * ->Le constructeur effectue une copie des ephemerides
+       */
+      for (int i=0;i<neph;i++)
+      {
+         delete ephemeris[i];
+      }
+      delete[] ephemeris;
+
+      return true;
+   }
+
+
+
+   bool ossimEnvisatAsarModel::InitRefPoint(const ossimKeywordlist &kwl, const char *prefix)
+   {
+
+      // Reference image position
+      if(_refPoint == NULL)
+      {
+         _refPoint = new RefPoint();
+      }
+      double sc_pix = atof(kwl.find(prefix,"samp_num")) - 1.0;
+      _refPoint->set_pix_col(sc_pix);
+      double sc_lin = atof(kwl.find(prefix,"line_num")) - 1.0;
+      _refPoint->set_pix_line(sc_lin);
+
+      // Reference Point distance
+      double c = 2.99792458e+8;
+      double distance = atof(kwl.find(prefix,"slant_range_time")) * (c/2.0) * 1.0e-9;
+      _refPoint->set_distance(distance);
+
+
+      // Reference Point Ephemeris
+      long day_ref = (long)atof(kwl.find(prefix,"first_zero_doppler_time_day"));
+      unsigned long sec_ref = (unsigned long)atof(kwl.find(prefix,"first_zero_doppler_time_sec"));
+      unsigned long microsec_ref = (unsigned long)atof(kwl.find(prefix,"first_zero_doppler_time_microsec"));
+
+      MJDDateTime mjdDate_ref(day_ref, sec_ref, microsec_ref);
+      JSDDateTime jsd_date_ref(mjdDate_ref);
+
+      if(_platformPosition != NULL)
+      {
+         Ephemeris * ephemeris = _platformPosition->Interpolate(jsd_date_ref);
+         if (ephemeris == NULL) return false ;
+         _refPoint->set_ephemeris(ephemeris);
+         delete ephemeris;
+      }
+      else return false;
+
+      // Adjustement of the model using the four corner points
+      // in order to use ossimSensorModel::lineSampleToWorld
+      const char* nbCol_str = kwl.find(prefix,"num_pix");
+      const char* nbLin_str = kwl.find(prefix,"num_lines");
+      theImageSize.x      = atoi(nbCol_str);
+      theImageSize.y      = atoi(nbLin_str);
+      theImageClipRect    = ossimDrect(0, 0, theImageSize.x-1, theImageSize.y-1);
+
+      // Ground Control Points extracted from the model : corner points
+      std::list<ossimGpt> groundGcpCoordinates ;
+      std::list<ossimDpt> imageGcpCoordinates ;
+      double h = atof(kwl.find("avg_scene_height"));
+
+      // first line first pix
+      double line = atof(kwl.find("UL_line")) - 1;
+      double col  = atof(kwl.find("UL_col"))  - 1;
+      double lon  = atof(kwl.find("UL_lon")) * 1e-6;
+      double lat  = atof(kwl.find("UL_lat")) * 1e-6;
+      if (lon > 180.0) lon -= 360.0;
+      ossimDpt imageGCP1(col,line);
+      ossimGpt groundGCP1(lat, lon, h);
+      groundGcpCoordinates.push_back(groundGCP1) ;
+      imageGcpCoordinates.push_back(imageGCP1) ;
+      // first line last pix
+      line = atof(kwl.find("UR_line")) - 1;
+      col  = atof(kwl.find("UR_col"))  - 1;
+      lon  = atof(kwl.find("UR_lon")) * 1e-6;
+      lat  = atof(kwl.find("UR_lat")) * 1e-6;
+      if (lon > 180.0) lon -= 360.0;
+      ossimDpt imageGCP2(col,line);
+      ossimGpt groundGCP2(lat, lon, h);
+      groundGcpCoordinates.push_back(groundGCP2) ;
+      imageGcpCoordinates.push_back(imageGCP2) ;
+      // last line last pix
+      line = atof(kwl.find("LR_line")) - 1;
+      col  = atof(kwl.find("LR_col"))  - 1;
+      lon  = atof(kwl.find("LR_lon")) * 1e-6;
+      lat  = atof(kwl.find("LR_lat")) * 1e-6;
+      if (lon > 180.0) lon -= 360.0;
+      ossimDpt imageGCP3(col,line);
+      ossimGpt groundGCP3(lat, lon, h);
+      groundGcpCoordinates.push_back(groundGCP3) ;
+      imageGcpCoordinates.push_back(imageGCP3) ;
+      // last line first pix
+      line = atof(kwl.find("LL_line")) - 1;
+      col  = atof(kwl.find("LL_col"))  - 1;
+      lon  = atof(kwl.find("LL_lon")) * 1e-6;
+      lat  = atof(kwl.find("LL_lat")) * 1e-6;
+      if (lon > 180.0) lon -= 360.0;
+      ossimDpt imageGCP4(col,line);
+      ossimGpt groundGCP4(lat, lon, h);
+      groundGcpCoordinates.push_back(groundGCP4) ;
+      imageGcpCoordinates.push_back(imageGCP4) ;
+
+      // Default optimization
+      optimizeModel(groundGcpCoordinates, imageGcpCoordinates) ;
+
+      return true;
+   }
+   bool ossimEnvisatAsarModel::InitSRGR(const ossimKeywordlist &kwl, const char *prefix)
+   {
+      // product type : Slant Range or Ground Range
+      _isProductGeoreferenced = atoi(kwl.find(prefix,"is_groundrange"));
+
+      // pixel spacing
+      _pixel_spacing = atof(kwl.find(prefix,"pixel_spacing"));
+
+      // number of SRGR sets
+      _n_srgr = atoi(kwl.find(prefix,"n_srgr"));
+
+
+      char name[64];
+      for (int i=0;i<_n_srgr;i++)
+      {
+         // SRGR update time
+         sprintf(name,"srgr_update_day%i",i);
+         long day_ref = (long)atof(kwl.find(prefix,name));
+         sprintf(name,"srgr_update_sec%i",i);
+         unsigned long sec_ref = (unsigned long)atof(kwl.find(prefix,name));
+         sprintf(name,"srgr_update_microsec%i",i);
+         unsigned long microsec_ref = (unsigned long)atof(kwl.find(prefix,name));
+         MJDDateTime mjdDate_ref(day_ref, sec_ref, microsec_ref);
+         JSDDateTime jsd_date_ref(mjdDate_ref);
+         _srgr_update.push_back(jsd_date_ref);
+
+         std::vector<double> srgr_set;
+         // SRGR coefficients
+         sprintf(name,"srgr_coef%iA",i);
+         const char* srgr_coef_strA = kwl.find(prefix,name);
+         srgr_set.push_back(atof(srgr_coef_strA));
+         sprintf(name,"srgr_coef%iB",i);
+         const char* srgr_coef_strB = kwl.find(prefix,name);
+         srgr_set.push_back(atof(srgr_coef_strB));
+         sprintf(name,"srgr_coef%iC",i);
+         const char* srgr_coef_strC = kwl.find(prefix,name);
+         srgr_set.push_back(atof(srgr_coef_strC));
+         sprintf(name,"srgr_coef%iD",i);
+         const char* srgr_coef_strD = kwl.find(prefix,name);
+         srgr_set.push_back(atof(srgr_coef_strD));
+         sprintf(name,"srgr_coef%iE",i);
+         const char* srgr_coef_strE = kwl.find(prefix,name);
+         srgr_set.push_back(atof(srgr_coef_strE)*1e-10);
+         sprintf(name,"srgr_coef%iF",i);
+         const char* srgr_coef_strF = kwl.find(prefix,name);
+         srgr_set.push_back(atof(srgr_coef_strF)*1e-10);
+
+         _srgr_coefset.push_back(srgr_set);
+      }
+
+
+      return true;
+   }
+
+
+   std::vector<double> ossimEnvisatAsarModel::FindSRGRSetNumber(JSDDateTime date) const
+   {
+      //if (_n_srgr==0) return NULL ;
+
+      std::vector<double> delays;
+      double delay;
+      for (int i=0;i<_n_srgr;i++)
+      {
+         JSDDateTime datetmp(_srgr_update.at(i));
+         delay = date.get_second()+date.get_decimal() - (datetmp.get_second() + datetmp.get_decimal());
+         delays.push_back( fabs(delay) );
+      }
+
+      int setNumber = 0 ;
+      double min_delay = delays[0] ;
+      for (int i=1;i<_n_srgr;i++)
+      {
+         if (delays[i]<min_delay) {
+            setNumber = i ;
+            min_delay = delays[i] ;
+         }
+      }
+
+      return _srgr_coefset[setNumber];
+   }
+}
+
diff --git a/ossim_plugins/ossim/ossimEnvisatAsarModel.h b/ossim_plugins/ossim/ossimEnvisatAsarModel.h
new file mode 100644
index 0000000..43c6fcb
--- /dev/null
+++ b/ossim_plugins/ossim/ossimEnvisatAsarModel.h
@@ -0,0 +1,140 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef ossimEnvisatAsarModel_H
+#define ossimEnvisatAsarModel_H
+
+#include <otb/JSDDateTime.h>
+#include <ossimGeometricSarSensorModel.h>
+#include <ossim/projection/ossimMapProjection.h>
+#include <ossim/base/ossimIpt.h>
+#include <ossim/base/ossimFilename.h>
+#include <ossim/base/ossimGpt.h>
+#include <ossim/base/ossimDpt.h>
+#include <EnvisatAsar/EnvisatAsarData.h>
+
+#include <iostream>
+
+namespace ossimplugins
+{
+
+
+class PlatformPosition;
+class SensorParams;
+class RefPoint;
+/**
+ * @brief This class is able to direct localisation and indirect localisation
+ * using the EnvisatAsar sensor model
+ */
+class ossimEnvisatAsarModel : public ossimGeometricSarSensorModel
+{
+public:
+  /**
+   * @brief Constructor
+   */
+  ossimEnvisatAsarModel();
+
+  /**
+   * @brief Destructor
+   */
+  virtual ~ossimEnvisatAsarModel();
+
+  /**
+   * @brief Method to return the class name.
+   * @return The name of this class.
+   */
+  virtual ossimString getClassName()   const;
+
+  /**
+   * @brief Returns pointer to a new instance, copy of this.
+   */
+  virtual ossimObject* dup() const;
+
+  /**
+   * @brief This function associates an image column number to a slant range when the image is georeferenced (ground projected)
+   * @param col Column coordinate of the image point
+   */
+  virtual double getSlantRangeFromGeoreferenced(double col) const;
+
+  /**
+   * @brief Method to intantial model from a file.
+   *
+   * @param file
+   *
+   * @return true on success, false on error.
+   */
+  bool open(const ossimFilename& file);
+
+  /**
+   * @brief Method to save object state to a keyword list.
+   * @param kwl Keyword list to save to.
+   * @param prefix added to keys when saved.
+   * @return true on success, false on error.
+   */
+  virtual bool saveState(ossimKeywordlist& kwl,
+                         const char* prefix=0) const;
+
+  /**
+   * @brief Method to the load (recreate) the state of the object from a
+   * keyword list. Return true if ok or false on error.
+   * @return true if load OK, false on error
+   */
+  virtual bool loadState (const ossimKeywordlist &kwl, const char *prefix=0);
+
+  /*!
+   * METHOD: print()
+   * Fulfills base-class pure virtual. Dumps contents of object to ostream.
+   */
+  virtual std::ostream& print(std::ostream& out) const;
+
+protected:
+
+  /**
+   *  @brief Slant Range to Ground Range (SRGR) number of coefficients sets
+   */
+  int  _n_srgr;
+  /**
+   * @brief SRGR coefficient sets
+   */
+  std::vector< std::vector<double> > _srgr_coefset;
+  /**
+   * @brief SRGR coefficient sets update times
+   */
+  std::vector<JSDDateTime> _srgr_update;
+  /**
+   * @brief Pixel spacing
+   */
+  double _pixel_spacing;
+
+private:
+  virtual bool InitPlatformPosition(const ossimKeywordlist &kwl, const char *prefix);
+  virtual bool InitSensorParams(const ossimKeywordlist &kwl, const char *prefix);
+  virtual bool InitRefPoint(const ossimKeywordlist &kwl, const char *prefix);
+  /**
+   * @brief Initializes the Slant Range for each Ground Range data sets : _n_srgr,_srgr_coefset,_srgr_update,_pixel_spacing,_isProductGeoreferenced
+   */
+  virtual bool InitSRGR(const ossimKeywordlist &kwl, const char *prefix);
+  /**
+   * @brief Finds the SRGR data set which update time is the closest to the center scene time
+   */
+  std::vector<double> FindSRGRSetNumber(JSDDateTime date)  const;
+  TYPE_DATA
+
+  /**
+   * @brief List of metadata contained in the Data file
+   */
+  EnvisatAsarData * _EnvisatAsarData;
+
+};
+}
+
+#endif
+
diff --git a/ossim_plugins/ossim/ossimErsSarModel.cpp b/ossim_plugins/ossim/ossimErsSarModel.cpp
new file mode 100644
index 0000000..61ada9e
--- /dev/null
+++ b/ossim_plugins/ossim/ossimErsSarModel.cpp
@@ -0,0 +1,687 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include <ossimErsSarModel.h>
+#include <otb/GalileanEphemeris.h>
+#include <otb/GeographicEphemeris.h>
+
+#include <otb/JSDDateTime.h>
+#include <otb/GMSTDateTime.h>
+#include <otb/CivilDateTime.h>
+
+#include <ossim/base/ossimTrace.h>
+#include <otb/RefPoint.h>
+#include <erssar/ErsSarLeader.h>
+#include <otb/SensorParams.h>
+#include <otb/PlatformPosition.h>
+#include <ossim/base/ossimKeywordNames.h>
+
+
+// Static trace for debugging
+static ossimTrace traceDebug("ossimErsSarModel:debug");
+
+#include <string>
+#include <algorithm>
+
+namespace ossimplugins
+{
+
+
+   RTTI_DEF1(ossimErsSarModel, "ossimErsSarModel", ossimGeometricSarSensorModel);
+
+   ossimErsSarModel::ossimErsSarModel():
+      theNumberSRGR(0),
+      thePixelSpacing(0),
+      theErsSarleader(NULL)
+   {
+      theSRGRCoeffset[0][0] = 0.0;
+      theSRGRCoeffset[0][1] = 0.0;
+      theSRGRCoeffset[0][2] = 0.0;
+   }
+
+   ossimErsSarModel::~ossimErsSarModel()
+   {
+      if (theErsSarleader != NULL)
+      {
+         delete theErsSarleader;
+         theErsSarleader = NULL;
+      }
+   }
+
+   ossimString ossimErsSarModel::getClassName() const
+   {
+      return ossimString("ossimErsSarModel");
+   }
+
+   ossimObject* ossimErsSarModel::dup() const
+   {
+      return new ossimErsSarModel(*this);
+   }
+
+   double ossimErsSarModel::getSlantRangeFromGeoreferenced(double col) const
+   {
+      const double c =  2.99792458e+8;
+      double tn = theSRGRCoeffset[0][0] + theSRGRCoeffset[0][1] * col + theSRGRCoeffset[0][2] * col * col ;
+      return tn *(c / 2.0);
+   }
+
+   bool ossimErsSarModel::InitSensorParams(const ossimKeywordlist &kwl, const char *prefix)
+   {
+      const char* wave_length_str = kwl.find(prefix, "wave_length");
+      double wave_length = atof(wave_length_str);
+      const char* fr_str = kwl.find(prefix, "fr");
+      double fr = atof(fr_str) * 1e6;
+      const char* fa_str = kwl.find(prefix, "fa");
+      double fa = atof(fa_str);
+
+      ossimString time_dir_pix = kwl.find(prefix, "time_dir_pix");
+      time_dir_pix.upcase();
+      //std::transform(time_dir_pix.begin(), time_dir_pix.end(), time_dir_pix.begin(), toupper);
+      ossimString time_dir_lin = kwl.find(prefix, "time_dir_lin");
+      time_dir_lin.upcase();
+      //std::transform(time_dir_lin.begin(), time_dir_lin.end(), time_dir_lin.begin(), toupper);
+
+      //ellipsoid parameters
+      const char* ellip_maj_str = kwl.find(prefix, "ellip_maj");
+      double ellip_maj = atof(ellip_maj_str) * 1000.0;  // km -> m
+      const char* ellip_min_str = kwl.find(prefix, "ellip_min");
+      double ellip_min = atof(ellip_min_str) * 1000.0;  // km -> m
+
+      if (_sensor != NULL)
+      {
+         delete _sensor;
+      }
+
+      _sensor = new SensorParams();
+
+      if (strcmp(time_dir_pix.c_str(), "INCREASE") == 0)
+      {
+         _sensor->set_col_direction(1);
+      }
+      else
+      {
+         _sensor->set_col_direction(-1);
+      }
+
+      if (strcmp(time_dir_lin.c_str(), "INCREASE") == 0)
+      {
+         _sensor->set_lin_direction(1);
+      }
+      else
+      {
+         _sensor->set_lin_direction(-1);
+      }
+
+      _sensor->set_sightDirection(SensorParams::Right) ;
+
+      double nlooks_az = atof(kwl.find(prefix, "nlooks_az"));
+      _sensor->set_nAzimuthLook(nlooks_az);
+      double n_rnglok = atof(kwl.find(prefix, "n_rnglok"));
+      _sensor->set_nRangeLook(n_rnglok);
+
+      _sensor->set_prf(fa);
+      _sensor->set_sf(fr);
+      _sensor->set_rwl(wave_length);
+
+      _sensor->set_semiMajorAxis(ellip_maj) ;
+      _sensor->set_semiMinorAxis(ellip_min) ;
+
+      return true;
+   }
+
+   bool ossimErsSarModel::open(const ossimFilename& file)
+   {
+      static const char MODULE[] = "ossimErsSarModel::open";
+
+      if (traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG)
+            << MODULE << " entered...\n"
+            << "file: " << file << "\n";
+      }
+
+      bool result = false;
+      ossimFilename leaFilename = file;
+
+      /*
+       * Creation of the class allowing to store Leader file metadata
+       */
+      if (theErsSarleader != NULL)
+      {
+         delete theErsSarleader;
+         theErsSarleader = NULL;
+      }
+
+      theErsSarleader = new ErsSarLeader();
+
+      if (leaFilename.exists())
+      {
+         result = isErsLeader(leaFilename);
+         if (result == false)
+         {
+            leaFilename = findErsLeader(file);
+         }
+         result = isErsLeader(leaFilename);
+
+         if (result == true)
+         {
+            if (traceDebug())
+            {
+               ossimNotify(ossimNotifyLevel_DEBUG) << "is ERS leader file..."
+                                                   << "Begin reading Leader file" << std::endl;
+            }
+            /*
+             * Leader file data reading
+             */
+            std::ifstream leaderFile(leaFilename.c_str(), ios::in | ios::binary);
+            leaderFile >> *theErsSarleader;
+            leaderFile.close();
+
+            if (traceDebug())
+            {
+               ossimNotify(ossimNotifyLevel_DEBUG)
+                  << "End reading Leader file" << std::endl;
+            }
+
+            //To initialize the whole state, reusing saveState/loadState
+            //FIXME: This could be at the superclass level instead
+            ossimKeywordlist kwl;
+            saveState(kwl);
+            loadState(kwl);
+
+         } // matches: if ( result=isErsLeader(file) == True )
+
+      } // matches: if ( file.exists() )
+
+      if (traceDebug())
+      {
+         this->print(ossimNotify(ossimNotifyLevel_DEBUG));
+
+         ossimNotify(ossimNotifyLevel_DEBUG)
+            << MODULE << " exit status = " << (result ? "true" : "false\n")
+            << std::endl;
+      }
+
+
+
+      return result;
+
+   }
+
+
+   bool ossimErsSarModel::saveState(ossimKeywordlist& kwl,
+                                    const char* /* prefix */) const
+   {
+      static const char MODULE[] = "ossimErsSarModel::saveState";
+
+      if (traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " entered...\n";
+      }
+
+      bool result(false);
+
+      //kwl.add(prefix, ossimKeywordNames::TYPE_KW, "ossimErsSarModel", true);
+
+      if (theErsSarleader == NULL)
+      {
+         std::cout << "Error: ErsSarleader is NULL" << std::endl;
+         return false;
+      }
+
+      result = theErsSarleader->saveState(kwl);
+
+      if (traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG)
+            << MODULE << " exit status = " << (result ? "true" : "false\n")
+            << std::endl;
+      }
+
+      return result;
+   }
+
+   bool ossimErsSarModel::loadState(const ossimKeywordlist &kwl, const char *prefix)
+   {
+      static const char MODULE[] = "ossimErsSarModel::loadState";
+
+      if (traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " entered...\n";
+      }
+
+      const char* lookup = 0;
+      ossimString s;
+
+      // Check the type first.
+      lookup = kwl.find(prefix, ossimKeywordNames::TYPE_KW);
+      if (lookup)
+      {
+         s = lookup;
+         if (s != getClassName())
+         {
+            return false;
+         }
+      }
+
+      // Load the base class.
+//    bool result = ossimGeometricSarSensorModel::loadState(kwl, prefix);
+      bool result = false;
+      result = InitPlatformPosition(kwl, prefix);
+      if (!result)
+      {
+         if (traceDebug())
+         {
+            ossimNotify(ossimNotifyLevel_WARN)
+               << MODULE
+               << "\nCan't init platform position \n";
+         }
+      }
+
+      if (result)
+      {
+         result = InitSensorParams(kwl, prefix);
+         if (!result)
+         {
+            if (traceDebug())
+            {
+               ossimNotify(ossimNotifyLevel_WARN)
+                  << MODULE
+                  << "\nCan't init sensor parameters \n";
+            }
+         }
+      }
+
+      if (result)
+      {
+         result = InitRefPoint(kwl, prefix);
+         if (!result)
+         {
+            if (traceDebug())
+            {
+               ossimNotify(ossimNotifyLevel_WARN)
+                  << MODULE
+                  << "\nCan't init ref point \n";
+            }
+         }
+      }
+
+      if (result)
+      {
+         result = InitSRGR(kwl, prefix);
+         if (!result)
+         {
+            if (traceDebug())
+            {
+               ossimNotify(ossimNotifyLevel_WARN)
+                  << MODULE
+                  << "\nCan't init ref point \n";
+            }
+         }
+      }
+
+      return result;
+   }
+
+   bool ossimErsSarModel::InitPlatformPosition(const ossimKeywordlist &kwl, const char *prefix)
+   {
+      // const double PI          = 3.14159265358979323846 ;
+      CivilDateTime ref_civil_date;
+      /*
+       * Ephemerisis reference date retrieval
+       */
+      const char* eph_year_str = kwl.find(prefix, "eph_year");
+      int eph_year = atoi(eph_year_str);
+      const char* eph_month_str = kwl.find(prefix, "eph_month");
+      int eph_month = atoi(eph_month_str);
+      const char* eph_day_str = kwl.find(prefix, "eph_day");
+      int eph_day = atoi(eph_day_str);
+      const char* eph_sec_str = kwl.find(prefix, "eph_sec");
+      double eph_sec = atof(eph_sec_str);
+
+      ref_civil_date.set_year(eph_year);
+      ref_civil_date.set_month(eph_month);
+      ref_civil_date.set_day(eph_day);
+      ref_civil_date.set_second((int)eph_sec);
+      ref_civil_date.set_decimal(eph_sec - (double)((int)eph_sec));
+
+      JSDDateTime ref_jsd_date(ref_civil_date);
+
+      /*
+       * Ephemerisis time interval retrieval
+       */
+      const char* eph_int_str = kwl.find(prefix, "eph_int");
+      double eph_int = atof(eph_int_str);
+      /*
+       * Ephemerisis number retrieval
+       */
+      const char* neph_str = kwl.find(prefix, "neph");
+      int neph = atoi(neph_str);
+
+      Ephemeris** ephemeris = new Ephemeris*[neph];
+
+      /*
+       * Ephemerisis retrieval
+       */
+      for (int i = 0; i < neph; i++)
+      {
+         double pos[3];
+         double vit[3];
+         char name[64];
+
+
+         sprintf(name, "eph%i_posX", i);
+         const char* px_str = kwl.find(prefix, name);
+         pos[0] = atof(px_str);
+
+         sprintf(name, "eph%i_posY", i);
+         const char* py_str = kwl.find(prefix, name);
+         pos[1] = atof(py_str);
+
+         sprintf(name, "eph%i_posZ", i);
+         const char* pz_str = kwl.find(prefix, name);
+         pos[2] = atof(pz_str);
+
+
+         sprintf(name, "eph%i_velX", i);
+         const char* vx_str = kwl.find(prefix, name);
+         vit[0] = atof(vx_str);
+
+         sprintf(name, "eph%i_velY", i);
+         const char* vy_str = kwl.find(prefix, name);
+         vit[1] = atof(vy_str);
+
+         sprintf(name, "eph%i_velZ", i);
+         const char* vz_str = kwl.find(prefix, name);
+         vit[2] = atof(vz_str);
+
+         /*
+          * Ephemerisis date
+          */
+         JSDDateTime date(ref_jsd_date);
+         date.set_second(date.get_second() + i * eph_int);
+         date.NormDate();
+
+         GeographicEphemeris* eph = new GeographicEphemeris(date, pos, vit);
+
+         ephemeris[i] = eph;
+      }
+
+      /*
+       * Antenna position interpolator creation
+       */
+      if (_platformPosition != NULL)
+      {
+         delete _platformPosition;
+      }
+      _platformPosition = new PlatformPosition(ephemeris, neph);
+
+      /*
+       * Free of memory used by the ephemerisis list
+       */
+      for (int i = 0; i < neph; i++)
+      {
+         delete ephemeris[i];
+      }
+      delete[] ephemeris;
+
+      return true;
+   }
+
+   bool ossimErsSarModel::InitRefPoint(const ossimKeywordlist &kwl, const char *prefix)
+   {
+      const char* sc_lin_str = kwl.find(prefix, "sc_lin");
+      double sc_lin = atof(sc_lin_str);
+
+      const char* sc_pix_str = kwl.find(prefix, "sc_pix");
+      double sc_pix = atof(sc_pix_str);
+
+      const char* inp_sctim_str = kwl.find(prefix, "inp_sctim");
+
+      const char* rng_gate_str = kwl.find(prefix, "zero_dop_range_time_f_pixel");
+      double rng_gate = atof(rng_gate_str);
+
+      if (_refPoint == NULL)
+      {
+         _refPoint = new RefPoint();
+      }
+
+      _refPoint->set_pix_col(sc_pix);
+      _refPoint->set_pix_line(sc_lin);
+
+      char year_str[5];
+      for (int i = 0; i < 4; i++)
+      {
+         year_str[i] = inp_sctim_str[i];
+      }
+      year_str[4] = '\0';
+
+      char month_str[3];
+      for (int i = 4; i < 6; i++)
+      {
+         month_str[i-4] = inp_sctim_str[i];
+      }
+      month_str[2] = '\0';
+
+      char day_str[3];
+      for (int i = 6; i < 8; i++)
+      {
+         day_str[i-6] = inp_sctim_str[i];
+      }
+      day_str[2] = '\0';
+
+      char hour_str[3];
+      for (int i = 8; i < 10; i++)
+      {
+         hour_str[i-8] = inp_sctim_str[i];
+      }
+      hour_str[2] = '\0';
+
+      char min_str[3];
+      for (int i = 10; i < 12; i++)
+      {
+         min_str[i-10] = inp_sctim_str[i];
+      }
+      min_str[2] = '\0';
+
+      char sec_str[3];
+      for (int i = 12; i < 14; i++)
+      {
+         sec_str[i-12] = inp_sctim_str[i];
+      }
+      sec_str[2] = '\0';
+
+      char mili_str[4];
+      for (int i = 14; i < 17; i++)
+      {
+         mili_str[i-14] = inp_sctim_str[i];
+      }
+      mili_str[3] = '\0';
+
+      int year = atoi(year_str);
+      int month = atoi(month_str);
+      int day = atoi(day_str);
+      int hour = atoi(hour_str);
+      int min = atoi(min_str);
+      int sec = atoi(sec_str);
+      double mili = atof(mili_str);
+
+
+      CivilDateTime date(year, month, day, hour * 3600 + min * 60 + sec, mili / 1000.0);
+
+      if (_platformPosition != NULL)
+      {
+         Ephemeris * ephemeris = _platformPosition->Interpolate((JSDDateTime)date);
+         if (ephemeris == NULL) return false ;
+         _refPoint->set_ephemeris(ephemeris);
+
+         delete ephemeris;
+      }
+      else
+      {
+         return false;
+      }
+
+      double c = 2.99792458e+8;
+
+      double distance = (rng_gate * 1e-3 + ((double)sc_pix) * _sensor->get_nRangeLook() / _sensor->get_sf()) * (c / 2.0);
+
+      _refPoint->set_distance(distance);
+
+      // in order to use ossimSensorModel::lineSampleToWorld
+      const char* nbCol_str = kwl.find(prefix, "num_pix");
+      const char* nbLin_str = kwl.find(prefix, "num_lines");
+      theImageSize.x      = atoi(nbCol_str);
+      theImageSize.y      = atoi(nbLin_str);
+      theImageClipRect    = ossimDrect(0, 0, theImageSize.x - 1, theImageSize.y - 1);
+
+      // Ground Control Points extracted from the model : corner points
+      std::list<ossimGpt> groundGcpCoordinates ;
+      std::list<ossimDpt> imageGcpCoordinates ;
+      // first line first pix
+      const char* lon_str = kwl.find("first_line_first_pixel_lon");
+      double lon = atof(lon_str);
+      const char* lat_str = kwl.find("first_line_first_pixel_lat");
+      double lat = atof(lat_str);
+      if (lon > 180.0) lon -= 360.0;
+      ossimDpt imageGCP1(0, 0);
+      ossimGpt groundGCP1(lat, lon, 0.0);
+      groundGcpCoordinates.push_back(groundGCP1) ;
+      imageGcpCoordinates.push_back(imageGCP1) ;
+      // first line last pix
+      lon_str = kwl.find("first_line_last_pixel_lon");
+      lon = atof(lon_str);
+      lat_str = kwl.find("first_line_last_pixel_lat");
+      lat = atof(lat_str);
+      if (lon > 180.0) lon -= 360.0;
+      ossimDpt imageGCP2(theImageSize.x - 1, 0);
+      ossimGpt groundGCP2(lat, lon, 0.0);
+      groundGcpCoordinates.push_back(groundGCP2) ;
+      imageGcpCoordinates.push_back(imageGCP2) ;
+      // last line last pix
+      lon_str = kwl.find("last_line_last_pixel_lon");
+      lon = atof(lon_str);
+      lat_str = kwl.find("last_line_last_pixel_lat");
+      lat = atof(lat_str);
+      if (lon > 180.0) lon -= 360.0;
+      ossimDpt imageGCP3(theImageSize.x - 1, theImageSize.y - 1);
+      ossimGpt groundGCP3(lat, lon, 0.0);
+      groundGcpCoordinates.push_back(groundGCP3) ;
+      imageGcpCoordinates.push_back(imageGCP3) ;
+      // last line first pix
+      lon_str = kwl.find("last_line_first_pixel_lon");
+      lon = atof(lon_str);
+      lat_str = kwl.find("last_line_first_pixel_lat");
+      lat = atof(lat_str);
+      if (lon > 180.0) lon -= 360.0;
+      ossimDpt imageGCP4(0, theImageSize.y - 1);
+      ossimGpt groundGCP4(lat, lon, 0.0);
+      groundGcpCoordinates.push_back(groundGCP4) ;
+      imageGcpCoordinates.push_back(imageGCP4) ;
+
+      // Default optimization
+      optimizeModel(groundGcpCoordinates, imageGcpCoordinates) ;
+
+      return true;
+   }
+
+   bool ossimErsSarModel::InitSRGR(const ossimKeywordlist &kwl, const char* /* prefix */)
+   {
+      // Product type = PRI
+      ossimString filename(kwl.find("filename"));
+      filename.upcase();
+      //std::transform(filename.begin(), filename.end(), filename.begin(), toupper);
+      string::size_type loc = filename.find("PRI");
+      if (loc != string::npos)
+      {
+         _isProductGeoreferenced = true;
+      }
+      else
+      {
+         _isProductGeoreferenced = false;
+      }
+
+      // Number of SRGR Coef
+      theNumberSRGR = 3;
+
+      // Range time for first mid and last pixel
+      double t1 = atof(kwl.find("zero_dop_range_time_f_pixel")) * 1e-3;
+      double t2 = atof(kwl.find("zero_dop_range_time_c_pixel")) * 1e-3;
+      double t3 = atof(kwl.find("zero_dop_range_time_l_pixel")) * 1e-3;
+
+      // Range pixels numbers corresponding
+      // Todo : check if it works with "DECREASING LINE TIME"
+      // double x1 = 0.0;
+      double x2 = atof(kwl.find("sc_pix")) - 1.0;
+      double x3 = 2.0 * (x2 + 1.0) - 1.0 ;
+
+      theSRGRCoeffset[0][0] = t1;
+      theSRGRCoeffset[0][1] = ((t2 - t1) / (x2 * x2) + (t1 - t3) / (x3 * x3)) / ((1.0 / x2) - (1.0 / x3));
+      theSRGRCoeffset[0][2] = ((t2 - t1) / x2 + (t1 - t3) / x3) / (x2 - x3);
+
+      return true;
+   }
+
+   bool ossimErsSarModel::isErsLeader(const ossimFilename& file) const
+   {
+      std::ifstream candidate(file.c_str(), ios::in | ios::binary);
+      char ersFileName[16];
+
+      candidate.seekg(48);
+      if (candidate.bad() || candidate.eof())
+      {
+         return false;
+      }
+      candidate.read(ersFileName, 16);
+      if (candidate.bad() || candidate.eof())
+      {
+         return false;
+      }
+      candidate.close();
+
+      ossimString ersString(ersFileName);
+
+      if ((ersString.find("ERS") == 0)   &&
+          (ersString.find(".SAR.") == 4) &&
+          (ersString.find("LEAD") == 12))
+      {
+         return true;
+      }
+      else
+      {
+         return false;
+      }
+
+   }
+
+   ossimFilename ossimErsSarModel::findErsLeader(const ossimFilename& file) const
+   {
+      ossimFilename leaFile = file;
+      ossimString datString("DAT_01");
+      ossimString nulString("NUL_DAT");
+      ossimString vdfString("VDF_DAT");
+      ossimString leaString("LEA_01");
+      if ((file.fileNoExtension() == datString)
+          || (file.fileNoExtension() == nulString)
+          || (file.fileNoExtension() == leaString))
+      {
+         leaFile.setFile(leaString);
+         if (leaFile.exists())
+         {
+            return leaFile;
+         }
+      }
+      return file;
+   }
+
+}
+
+
diff --git a/ossim_plugins/ossim/ossimErsSarModel.h b/ossim_plugins/ossim/ossimErsSarModel.h
new file mode 100644
index 0000000..48981d5
--- /dev/null
+++ b/ossim_plugins/ossim/ossimErsSarModel.h
@@ -0,0 +1,129 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef ossimErsSarModel_H
+#define ossimErsSarModel_H 1
+
+#include <otb/JSDDateTime.h>
+#include <ossimGeometricSarSensorModel.h>
+
+#include <ossim/projection/ossimMapProjection.h>
+#include <ossim/base/ossimIpt.h>
+#include <ossim/base/ossimFilename.h>
+#include <ossim/base/ossimGpt.h>
+#include <ossim/base/ossimDpt.h>
+
+#include <iostream>
+
+namespace ossimplugins
+{
+
+class PlatformPosition;
+class SensorParams;
+class RefPoint;
+class ErsSarLeader;
+/**
+ * @brief This class is able to direct localisation and indirect localisation using the ErsSar sensor model
+ *
+ */
+class OSSIM_PLUGINS_DLL ossimErsSarModel : public ossimGeometricSarSensorModel
+{
+public:
+  /**
+   * @brief Constructor
+   */
+  ossimErsSarModel();
+
+  /**
+   * @brief Destructor
+   */
+  virtual ~ossimErsSarModel();
+
+  /**
+   * @brief Method to return the class name.
+   * @return The name of this class.
+   */
+  virtual ossimString getClassName() const;
+
+  /**
+   * @brief Returns pointer to a new instance, copy of this.
+   */
+  virtual ossimObject* dup() const;
+
+  /**
+   * @brief This function associates an image column number to a slant range when the image is georeferenced (ground projected)
+   * @param col Column coordinate of the image point
+   */
+  virtual double getSlantRangeFromGeoreferenced(double col) const;
+
+  /**
+  * @brief Method to instantiate model from the leader file.
+  * @param file
+  * @return true on success, false on error.
+  */
+  bool open(const ossimFilename& file);
+
+  /**
+   * @brief Method to save object state to a keyword list.
+   * @param kwl Keyword list to save to.
+   * @param prefix added to keys when saved.
+   * @return true on success, false on error.
+   */
+  virtual bool saveState(ossimKeywordlist& kwl,
+                         const char* prefix = 0) const;
+
+  /**
+   * @brief Method to the load (recreate) the state of the object from a
+   * keyword list. Return true if ok or false on error.
+   * @return true if load OK, false on error
+   */
+  virtual bool loadState(const ossimKeywordlist &kwl, const char *prefix = 0);
+
+protected:
+  virtual bool InitPlatformPosition(const ossimKeywordlist &kwl, const char *prefix);
+  virtual bool InitSensorParams(const ossimKeywordlist &kwl, const char *prefix);
+  virtual bool InitRefPoint(const ossimKeywordlist &kwl, const char *prefix);
+  /**
+  * @brief Initializes the Slant Range for each Ground Range data sets : theNumberSRGR,theSRGRCoeffset,_srgr_update,thePixelSpacing,_isProductGeoreferenced
+  */
+  virtual bool InitSRGR(const ossimKeywordlist &kwl, const char *prefix);
+
+private:
+  /**
+   *  @brief Slant Range for each Ground Range (SRGR) number of coefficients sets
+   */
+  int   theNumberSRGR;
+  /**
+   * @brief SRGR coefficient sets
+   */
+  double theSRGRCoeffset[1][3];
+  /**
+   * @brief Pixel spacing
+   */
+  double thePixelSpacing;
+
+  /**
+   * @brief List of metadata contained in the Leader file
+   */
+  ErsSarLeader *theErsSarleader;
+
+
+
+  virtual bool isErsLeader(const ossimFilename& file) const;
+  virtual ossimFilename findErsLeader(const ossimFilename& file) const;
+
+  TYPE_DATA
+
+};
+
+}
+#endif
+
diff --git a/ossim_plugins/ossim/ossimFormosatDimapSupportData.cpp b/ossim_plugins/ossim/ossimFormosatDimapSupportData.cpp
new file mode 100644
index 0000000..d502f5d
--- /dev/null
+++ b/ossim_plugins/ossim/ossimFormosatDimapSupportData.cpp
@@ -0,0 +1,2693 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+
+#include <iostream>
+#include <cstdlib>
+#include <iterator>
+#include <ossimFormosatDimapSupportData.h>
+#include <ossim/base/ossimFilename.h>
+#include <ossim/base/ossimXmlDocument.h>
+#include <ossim/base/ossimXmlAttribute.h>
+#include <ossim/base/ossimXmlNode.h>
+#include <ossim/base/ossimKeywordlist.h>
+#include <ossim/base/ossimDatum.h>
+#include <ossim/base/ossimKeywordNames.h>
+#include <ossim/base/ossimTrace.h>
+#include <ossim/base/ossimNotifyContext.h>
+#include <sstream>
+
+// Define Trace flags for use within this file:
+static ossimTrace traceDebug ("ossimFormosatDimapSupportData:debug");
+
+static const ossim_uint32  LAGRANGE_FILTER_SIZE = 8; // num samples considered
+
+ossimFormosatDimapSupportData::ossimFormosatDimapSupportData ()
+   :
+   ossimErrorStatusInterface(),
+   theMetadataVersion(OSSIM_FORMOSAT_METADATA_VERSION_UNKNOWN),
+   theImageID(),
+   theMetadataFile(),
+   theProductionDate(),
+   theSoftwareVersion(),
+   theInstrument(),
+   theInstrumentIndex(0), 
+   theSunAzimuth(0.0),
+   theSunElevation(0.0),
+   theSatAzimuth(0.0),
+   theIncidenceAngle(0.0),
+   theViewingAngle(0.0),
+   theViewingAngleAlongTrack(0.0),
+   theViewingAngleAcrossTrack(0.0),
+   theSceneOrientation(0.0),
+   theImageSize(0.0, 0.0),
+   theRefGroundPoint(0.0, 0.0, 0.0),
+   theRefImagePoint(0.0, 0.0),
+   theSubImageOffset(0.0, 0.0),
+   theRefLineTime(0.0),
+   theRefLineTimeLine(0.0),
+   theLineSamplingPeriod(0.0),
+   thePolynomialLookAngleX(),
+   thePolynomialLookAngleY(),
+   theAttitudeSamples(),
+   theAttSampTimes(),
+   thePosEcfSamples(),
+   theVelEcfSamples(),
+   theEphSampTimes(),
+   theStarTrackerUsed(false),
+   theNumBands(0),
+   theAcquisitionDate(),
+   theFrameVertexPosImagePoints(),
+   theFrameVertexPosGroundPoints(),
+   theGeoPosImagePoints(),
+   theGeoPosGroundPoints()
+{
+}
+ossimFormosatDimapSupportData::ossimFormosatDimapSupportData(const ossimFormosatDimapSupportData& rhs)
+   :ossimErrorStatusInterface(rhs),
+    theMetadataVersion(rhs.theMetadataVersion),
+    theImageID(rhs.theImageID),
+    theMetadataFile (rhs.theMetadataFile),
+    theProductionDate(rhs.theProductionDate),
+    theSoftwareVersion(rhs.theSoftwareVersion),
+    theInstrument(rhs.theInstrument),
+    theInstrumentIndex(rhs.theInstrumentIndex),
+    theSunAzimuth(rhs.theSunAzimuth),
+    theSunElevation(rhs.theSunElevation), 
+    theSatAzimuth(rhs.theSatAzimuth),
+    theIncidenceAngle(rhs.theIncidenceAngle),
+    theViewingAngle(rhs.theViewingAngle),
+    theViewingAngleAlongTrack(rhs.theViewingAngle),
+    theViewingAngleAcrossTrack(rhs.theViewingAngle),
+    theSceneOrientation(rhs.theSceneOrientation),
+    theImageSize(rhs.theImageSize),
+    theRefGroundPoint(rhs.theRefGroundPoint),
+    theRefImagePoint(rhs.theRefImagePoint),
+    theSubImageOffset(rhs.theSubImageOffset),
+    theRefLineTime(rhs.theRefLineTime),
+    theRefLineTimeLine(rhs.theRefLineTimeLine),
+    theLineSamplingPeriod(rhs.theLineSamplingPeriod),
+    thePolynomialLookAngleX(rhs.thePolynomialLookAngleX),
+    thePolynomialLookAngleY(rhs.thePolynomialLookAngleY),
+    theAttitudeSamples(rhs.theAttitudeSamples),
+    theAttSampTimes(rhs.theAttSampTimes),
+    thePosEcfSamples(rhs.thePosEcfSamples),
+    theVelEcfSamples(rhs.theVelEcfSamples),
+    theEphSampTimes(rhs.theEphSampTimes),
+    theStarTrackerUsed(rhs.theStarTrackerUsed),
+    theNumBands(rhs.theNumBands),
+    theAcquisitionDate(rhs.theAcquisitionDate),
+    theFrameVertexPosImagePoints(rhs.theFrameVertexPosImagePoints),
+    theFrameVertexPosGroundPoints(rhs.theFrameVertexPosGroundPoints),
+    theGeoPosImagePoints(rhs.theGeoPosImagePoints),
+    theGeoPosGroundPoints(rhs.theGeoPosGroundPoints)
+{
+}
+
+ossimFormosatDimapSupportData::ossimFormosatDimapSupportData (const ossimFilename& dimapFile)
+   :
+   ossimErrorStatusInterface(),
+   theMetadataVersion(OSSIM_FORMOSAT_METADATA_VERSION_UNKNOWN),
+   theImageID(),
+   theMetadataFile (dimapFile),
+   theProductionDate(),
+   theSoftwareVersion(),
+   theInstrument(),
+   theInstrumentIndex(0),
+   theSunAzimuth(0.0),
+   theSunElevation(0.0),
+   theSatAzimuth(0.0),
+   theIncidenceAngle(0.0),
+   theViewingAngle(0.0),
+   theViewingAngleAlongTrack(0.0),
+   theViewingAngleAcrossTrack(0.0),
+   theSceneOrientation(0.0),
+   theImageSize(0.0, 0.0),
+   theRefGroundPoint(0.0, 0.0, 0.0),
+   theRefImagePoint(0.0, 0.0),
+   theSubImageOffset(0.0, 0.0),
+   theRefLineTime(0.0),
+   theRefLineTimeLine(0.0),
+   theLineSamplingPeriod(0.0),
+   thePolynomialLookAngleX(),
+   thePolynomialLookAngleY(),
+   theAttitudeSamples(),
+   theAttSampTimes(),
+   thePosEcfSamples(),
+   theVelEcfSamples(),
+   theEphSampTimes(),
+   theStarTrackerUsed(false),
+   theNumBands(0),
+   theAcquisitionDate(),
+   theFrameVertexPosImagePoints(),
+   theFrameVertexPosGroundPoints(),
+   theGeoPosImagePoints(),
+   theGeoPosGroundPoints()
+{
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimFormosatDimapSupportData::ossimFormosatDimapSupportData: entering..."
+         << std::endl;
+   }
+
+   loadXmlFile(dimapFile);
+
+   // Finished successful parse:
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimFormosatDimapSupportData::ossimFormosatDimapSupportData: leaving..."
+         << std::endl;
+   }
+}
+
+ossimFormosatDimapSupportData::~ossimFormosatDimapSupportData ()
+{
+}
+
+ossimObject* ossimFormosatDimapSupportData::dup()const
+{
+   return new ossimFormosatDimapSupportData(*this);
+}
+
+void ossimFormosatDimapSupportData::clearFields()
+{
+   clearErrorStatus();
+   theSensorID="";
+   theMetadataVersion = OSSIM_FORMOSAT_METADATA_VERSION_UNKNOWN;
+   theImageID = "";
+   theMetadataFile = "";
+   theProductionDate = "";
+   theSoftwareVersion = "";
+   theInstrument = "";
+   theInstrumentIndex = 0;
+   theSunAzimuth = 0.0;
+   theSunElevation = 0.0;
+   theSatAzimuth = 0.0;
+   theIncidenceAngle = 0.0;
+   theViewingAngle = 0.0;
+   theViewingAngleAlongTrack = 0.0;
+   theViewingAngleAcrossTrack = 0.0;
+   theSceneOrientation = 0.0;
+   theImageSize.makeNan();
+   theRefGroundPoint.makeNan();
+   theRefImagePoint.makeNan();
+   theSubImageOffset.makeNan();
+   theRefLineTime = ossim::nan();
+   theRefLineTimeLine = ossim::nan();
+   theLineSamplingPeriod = ossim::nan();
+   thePolynomialLookAngleX.clear();
+   thePolynomialLookAngleY.clear();
+   theAttitudeSamples.clear(); // x=pitch, y=roll, z=yaw
+   theAttSampTimes.clear();
+   thePosEcfSamples.clear();
+   theVelEcfSamples.clear();
+   theEphSampTimes.clear();
+   theStarTrackerUsed = false;
+   theNumBands = 0;
+   theAcquisitionDate = "";
+
+   //---
+   // Corner points:
+   //---
+   theFrameVertexPosImagePoints.clear();
+   theFrameVertexPosGroundPoints.clear();
+
+   
+   //---
+   // Geoposition Points:
+   //---
+   theGeoPosImagePoints.clear();
+   theGeoPosGroundPoints.clear();
+
+}
+
+
+
+bool ossimFormosatDimapSupportData::loadXmlFile(const ossimFilename& file)
+{
+   static const char MODULE[] = "ossimFormosatDimapSupportData::loadXmlFile";
+
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " DEBUG:Entering ..."
+         << "\nFile: " << file << std::endl;
+   }
+   clearFields();
+   theMetadataFile = file;
+ 
+   ossim_int64 fileSize = file.fileSize();
+   std::ifstream in(file.c_str(), std::ios::binary|std::ios::in);
+   std::vector<char> fullBuffer;
+   ossimString bufferedIo;
+   if(in.good()&&(fileSize > 0))
+   {
+      char buf[100];
+	  fullBuffer.resize(fileSize);
+      in.read(buf, ossim::min((ossim_int64)100, fileSize));
+      if(!in.fail())
+      {
+         ossimString testString = ossimString(buf,
+                                  buf + in.gcount());
+         if(testString.contains("xml"))
+         {
+            in.seekg(0);
+            in.read(&fullBuffer.front(), (std::streamsize)fullBuffer.size());
+            if(!in.fail())
+            {
+               bufferedIo = ossimString(fullBuffer.begin(),
+                                        fullBuffer.begin()+in.gcount());
+            }
+         }
+      }
+   }
+   else
+   {
+      return false;
+   }
+   //---
+   // Instantiate the XML parser:
+   //---
+   ossimRefPtr<ossimXmlDocument> xmlDocument;
+
+   if(bufferedIo.empty())
+   {
+      xmlDocument = new ossimXmlDocument(file);
+   }
+   else
+   {
+
+      xmlDocument = new ossimXmlDocument;
+      std::istringstream inStringStream(bufferedIo);
+      if(!xmlDocument->read(inStringStream))
+      {
+         return false;
+      }
+   }
+ 
+   if (xmlDocument->getErrorStatus())
+   {
+      if(traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_FATAL)
+            << MODULE << " DEBUG:"
+            << "ossimFormosatDimapSupportData::loadXmlFile:"
+            << "\nUnable to parse xml file" << std::endl;
+      }
+      setErrorStatus();
+      return false;
+   }
+
+   //---
+   // Check that it is a FORMOSAT DIMAP file format
+   //---
+   vector<ossimRefPtr<ossimXmlNode> > xml_nodes;
+   xml_nodes.clear();
+   ossimString xpath = "/Dimap_Document/Dataset_Sources/Source_Information/Scene_Source/MISSION";
+   xmlDocument->findNodes(xpath, xml_nodes);
+   if (xml_nodes.size() == 0)
+   {
+     setErrorStatus();
+     if(traceDebug())
+       {
+	 ossimNotify(ossimNotifyLevel_DEBUG)
+	   << "DEBUG:\n Not a FORMOSAT DIMAP file format."<< std::endl;
+       }
+     return false;
+   }
+
+   if ( xml_nodes[0]->getText() != "FORMOSAT" && xml_nodes[0]->getText() != "Formosat" && xml_nodes[0]->getText() != "formosat" )
+     {
+       if(traceDebug())
+	 {
+	   ossimNotify(ossimNotifyLevel_DEBUG)
+	     << "DEBUG:\n Not a FORMOSAT DIMAP file format."<< std::endl;
+	 }
+       return false;
+   }
+
+   //---
+   // Get the version string.  This must be performed first as it is used
+   // as a key for parsing different versions.
+   //---
+   if (initMetadataVersion(xmlDocument) == false)
+   {
+      if(traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_FATAL)
+            << MODULE << " DEBUG:"
+            << "ossimFormosatDimapSupportData::loadXmlFile:"
+            << "\nMetadata initialization failed.  Returning false"
+            << std::endl;
+      }
+      return false;
+   }
+
+   // Get the image id.
+   if (initImageId(xmlDocument) == false)
+   {
+      if(traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_FATAL)
+            << MODULE << " DEBUG:"
+            << "ossimFormosatDimapSupportData::loadXmlFile:"
+            << "\nImageId initialization failed.  Returning false"
+            << std::endl;
+      }
+      return false;
+   }
+
+   // Get data from "Scene_Source" section.
+   if (initSceneSource(xmlDocument)  == false)
+   {
+      ossimNotify(ossimNotifyLevel_FATAL)
+         << MODULE << " DEBUG:"
+         << "ossimFormosatDimapSupportData::loadXmlFile:"
+         << "\nScene source initialization failed.  Returning false"
+         << std::endl;
+
+      return false;
+   }
+
+   if (initFramePoints(xmlDocument)  == false)
+   {
+      ossimNotify(ossimNotifyLevel_FATAL)
+         << MODULE << " DEBUG:"
+         << "ossimFormosatDimapSupportData::loadXmlFile:"
+         << "\nFrame point initialization failed.  Returning false"
+         << std::endl;
+      return false;
+   }
+ 
+   if (parsePart1(xmlDocument) == false)
+   {
+      ossimNotify(ossimNotifyLevel_FATAL)
+         << MODULE << " DEBUG:"
+         << "ossimFormosatDimapSupportData::loadXmlFile:"
+         << "\nPart 1 initialization failed.  Returning false"
+         << std::endl;
+      return false;
+   }
+
+   if (parsePart2(xmlDocument) == false)
+   {
+      ossimNotify(ossimNotifyLevel_FATAL)
+         << MODULE << " DEBUG:"
+         << "ossimFormosatDimapSupportData::loadXmlFile:"
+         << "\nPart 2 initialization failed.  Returning false"
+         << std::endl;
+      return false;
+   }
+
+   if (parsePart3(xmlDocument) == false)
+   {
+      ossimNotify(ossimNotifyLevel_FATAL)
+         << MODULE << " DEBUG:"
+         << "ossimFormosatDimapSupportData::loadXmlFile:"
+         << "\nPart 3 initialization failed.  Returning false"
+         << std::endl;
+      return false;
+   }
+
+   if (parsePart4(xmlDocument) == false)
+   {
+     ossimNotify(ossimNotifyLevel_FATAL)
+         << MODULE << " DEBUG:"
+         << "ossimFormosatDimapSupportData::loadXmlFile:"
+         << "\nPart 4 initialization failed.  Returning false"
+         << std::endl;
+     return false;
+   }
+
+   if (traceDebug())
+   {
+      printInfo(ossimNotify(ossimNotifyLevel_DEBUG));
+
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " DEBUG: leaving..."
+         << std::endl;
+   }
+
+   return true;
+}
+
+void ossimFormosatDimapSupportData::getPositionEcf(ossim_uint32 sample,
+                                               ossimEcefPoint& pe)  const
+{
+   pe.makeNan();
+   pe = ossimEcefPoint(thePosEcfSamples[sample].x,
+	                   thePosEcfSamples[sample].y,
+                       thePosEcfSamples[sample].z);
+
+}
+
+void ossimFormosatDimapSupportData::getPositionEcf(const ossim_float64& time,
+                                               ossimEcefPoint& pe)  const
+{
+   ossimDpt3d tempPt;
+
+   if((thePosEcfSamples.size() < 8)||
+      (theEphSampTimes.size() < 8))
+   {
+      getBilinearInterpolation(time, thePosEcfSamples, theEphSampTimes, tempPt);
+   }
+   else
+   {
+      getLagrangeInterpolation(time, thePosEcfSamples, theEphSampTimes, tempPt);
+   }
+
+   pe = ossimEcefPoint(tempPt.x,
+                       tempPt.y,
+                       tempPt.z);
+}
+
+void ossimFormosatDimapSupportData::getVelocityEcf(ossim_uint32 sample, ossimEcefPoint& ve)  const
+{
+   ve.makeNan();
+   ve = ossimEcefPoint(theVelEcfSamples[sample].x,
+                       theVelEcfSamples[sample].y,
+                       theVelEcfSamples[sample].z);
+}
+
+void ossimFormosatDimapSupportData::getVelocityEcf(const ossim_float64& time,
+                                               ossimEcefPoint& ve)  const
+{
+   ossimDpt3d tempPt;
+
+   if((theVelEcfSamples.size() < 8) ||
+      (theEphSampTimes.size() < 8))
+   {
+      getBilinearInterpolation (time, theVelEcfSamples, theEphSampTimes, tempPt);
+   }
+   else
+   {
+      getLagrangeInterpolation (time, theVelEcfSamples, theEphSampTimes, tempPt);
+   }
+
+   ve = ossimEcefPoint(tempPt.x,
+                       tempPt.y,
+                       tempPt.z);
+}
+
+void ossimFormosatDimapSupportData::getEphSampTime(ossim_uint32 sample,
+                                               ossim_float64& et)  const
+{
+   et = ossim::nan();
+   if(theEphSampTimes.size() < theImageSize.samp)
+   {
+      if(theImageSize.samp > 0)
+      {
+         double t = 0.0;
+         double tempIdx = 0.0;
+         double tempIdxFraction = 0.0;
+         t = (double)sample/(double)(theImageSize.samp-1);
+         tempIdx = (theEphSampTimes.size()-1)*t;
+         tempIdxFraction = tempIdx - (ossim_int32)tempIdx;
+         ossim_uint32 idxStart = (ossim_uint32)tempIdx;
+         ossim_uint32 idxEnd = (ossim_uint32)ceil(tempIdx);
+         if(idxEnd >= theEphSampTimes.size())
+         {
+            idxEnd = (ossim_uint32)theEphSampTimes.size()-1;
+         }
+         if(idxStart > idxEnd)
+         {
+            idxStart = idxEnd;
+         }
+         et = (theEphSampTimes[idxStart] +tempIdxFraction*(theEphSampTimes[idxEnd] -
+                                                           theEphSampTimes[idxStart]));
+      }
+   }
+   else if(theEphSampTimes.size() == theImageSize.samp)
+   {
+      et = theEphSampTimes[sample];
+   }
+}
+
+void ossimFormosatDimapSupportData::getAttitude(ossim_uint32 sample,
+                                            ossimDpt3d& at)  const
+{
+   if (sample >= theAttitudeSamples.size())
+   {
+      at.makeNan();
+      return;
+   }
+
+   at = theAttitudeSamples[sample];
+}
+
+void ossimFormosatDimapSupportData::getAttitude(const ossim_float64& time,
+                                            ossimDpt3d& at)  const
+{
+   if (theAttSampTimes.empty())
+   {
+     at.makeNan();
+     return;
+   }
+
+   if ((time <  theAttSampTimes.front()) ||
+       (time >= theAttSampTimes.back() ))
+   {
+      at.makeNan();
+      return;
+   }
+
+   //***
+   // Search the attitude sampling time array for surrounding samples:
+   //***
+   int i=0;
+   while ((i < (int)theAttSampTimes.size()) &&
+          (theAttSampTimes[i] < time)) ++i;
+   --i;
+
+   //***
+   // Linearly interpolate attitudes angles:
+   //***
+   ossim_float64 dt1   = time - theAttSampTimes[i];
+   ossim_float64 dt0   = theAttSampTimes[i+1] - time;
+   ossim_float64 dt    = theAttSampTimes[i+1] - theAttSampTimes[i];
+
+   at = (theAttitudeSamples[i+1]*dt1 + theAttitudeSamples[i]*dt0)/dt;
+}
+
+void ossimFormosatDimapSupportData::getAttSampTime(ossim_uint32 sample, ossim_float64& at)  const
+{
+   if (sample >= theAttSampTimes.size())
+   {
+      at = ossim::nan();
+      return;
+   }
+
+   at = theAttSampTimes[sample];
+}
+
+void ossimFormosatDimapSupportData::getPixelLookAngleX(ossim_uint32 sample,
+                                                 	  		  ossim_float64& pa) const
+{
+   getInterpolatedLookAngle(sample, thePolynomialLookAngleX, pa);
+}
+
+void ossimFormosatDimapSupportData::getPixelLookAngleX(const ossim_float64& sample,
+                                                   			  ossim_float64& pa) const
+{
+   ossim_uint32 s = static_cast<ossim_uint32>(sample);
+   getInterpolatedLookAngle(s, thePolynomialLookAngleX, pa);
+}
+
+void ossimFormosatDimapSupportData::getPixelLookAngleY(ossim_uint32 sample,
+                                                     		  ossim_float64& pa) const
+{
+   getInterpolatedLookAngle(sample, thePolynomialLookAngleY, pa);
+}
+
+void ossimFormosatDimapSupportData::getPixelLookAngleY(const ossim_float64& sample,
+                                                   			  ossim_float64& pa) const
+{
+   ossim_uint32 s = static_cast<ossim_uint32>(sample);
+   getInterpolatedLookAngle(s, thePolynomialLookAngleY, pa);
+}
+
+void ossimFormosatDimapSupportData::getInterpolatedLookAngle(
+   const ossim_float64& p,
+   const std::vector<ossim_float64>& angles,
+   ossim_float64& la) const
+{
+   la = ossim::nan();
+
+   if (angles.size() != 4 )
+   {
+      setErrorStatus();
+      return;
+   }
+
+   la = angles[0] + angles[1] * p + angles[2] * p * p +  angles[3] * p * p * p ;
+}
+
+void ossimFormosatDimapSupportData::getBilinearInterpolation(
+   const ossim_float64& time,
+   const std::vector<ossimDpt3d>& V,
+   const std::vector<ossim_float64>& T,
+   ossimDpt3d& li) const
+{
+   ossim_uint32 samp0 = 0;
+   while ((samp0 < T.size()) && (T[samp0] < time)) ++samp0;
+
+   if(samp0==0)
+   {
+      li = V[0];
+   }
+   else if(samp0 == T.size())
+   {
+      li = V[1];
+   }
+   else
+   {
+      double t = (T[samp0-1]-time)/(T[samp0-1] - T[samp0]);
+
+      li = V[samp0-1] + (V[samp0]-V[samp0-1])*t;
+   }
+}
+
+void ossimFormosatDimapSupportData::getLagrangeInterpolation(
+   const ossim_float64& time,
+   const std::vector<ossimDpt3d>& V,
+   const std::vector<ossim_float64>& T,
+   ossimDpt3d& li) const
+
+{
+//    std::cout << "V size = " << V.size() << std::endl
+//              << "T size = " << T.size() << std::endl;
+
+   ossim_uint32 filter_size = 8;
+   //
+   // Verify that t is within allowable range:
+   //
+   ossim_uint32 lagrange_half_filter = 4;
+
+   if(T.size() <= filter_size)
+   {
+      filter_size = (ossim_uint32)T.size()/2;
+      lagrange_half_filter = filter_size/2;
+   }
+   if ((time <  T[lagrange_half_filter]) ||
+       (time >= T[T.size()-lagrange_half_filter] ))
+   {
+      setErrorStatus();
+      li.makeNan();
+
+      return;
+   }
+
+   //***
+   // Search the sampling time array for surrounding samples:
+   //***
+   ossim_uint32 samp0 = lagrange_half_filter;
+   while ((samp0 < T.size()) && (T[samp0] < time)) ++samp0;
+
+   //***
+   // Do not use sample if it falls in neighborhood of desired time:
+   //***
+   ossim_uint32 bump = 0;
+   if (fabs(T[samp0] - time) < theLineSamplingPeriod/2.0)
+      bump = 1;
+
+   samp0 -= lagrange_half_filter; // adjust to first sample in window
+
+   //***
+   // Outer summation loop:
+   //***
+   ossimDpt3d S (0, 0, 0);
+   for (ossim_uint32 j=samp0; j<(samp0+filter_size+bump); ++j)
+   {
+      ossim_float64 numerator   = 1.0;
+      ossim_float64 denominator = 1.0;
+
+      //***
+      // Skip this sample if too close to desired time:
+      //***
+      if (bump && (j == (samp0+lagrange_half_filter) ))
+         ++j;
+
+      //***
+      // Inner loop for product series:
+      //***
+      for (ossim_uint32 i=samp0; i<(samp0+filter_size+bump); ++i)
+      {
+         //***
+         // Skip this sample if too close to desired time:
+         //***
+         if (bump && (i == (samp0+lagrange_half_filter) ))
+            ++i;
+
+         if (i != j)
+         {
+            numerator   *= time - T[i];
+            denominator *= T[j] - T[i];
+         }
+      }
+
+      ossimDpt3d p = V[j];
+      p = p * numerator;
+      p = p / denominator;
+      S += p;
+   }
+
+   li = S;
+}
+
+ossim_float64 ossimFormosatDimapSupportData::convertTimeStamp(const ossimString& time_stamp) const
+{
+   double ti;
+   convertTimeStamp(time_stamp, ti);
+   return ti;
+}
+
+void ossimFormosatDimapSupportData::convertTimeStamp(const ossimString& time_stamp,
+                                                 ossim_float64& ti) const
+{
+   int    year, month, day, hour, minute;
+   double second;
+
+   //***
+   // Time stamps are in the format: "yyyy-mm-ddThh:mm:ss.ssssss"
+   //***	
+   int converted = sscanf(time_stamp,
+                          "%4d-%2d-%2d %2d:%2d:%9lf",
+                          &year, &month, &day,
+                          &hour, &minute, &second);
+   
+   if (converted != 6)
+   {
+      setErrorStatus();
+      ti = ossim::nan();
+   }
+   else
+   {
+      ti = (((((year-2002.0)*12.0 + month - 1.0)*365.0 + day - 1.0)*24.0
+             + hour)*60.0 + minute)*60.0 + second;
+   }
+}
+
+void ossimFormosatDimapSupportData::getGeoPosPoint (ossim_uint32 point,
+                                                ossimDpt& ip,
+                                                ossimGpt& gp) const
+{
+   if (point < theGeoPosImagePoints.size())
+   {
+      ip = theGeoPosImagePoints [point];
+      gp = theGeoPosGroundPoints[point];
+   }
+}
+
+void ossimFormosatDimapSupportData::printInfo(ostream& os) const
+{
+   ossimString corr_att = "NO";
+   if (theStarTrackerUsed)
+      corr_att = "YES";
+
+   os << "\n----------------- Info on Formosat Image -------------------"
+      << "\n  "
+      << "\n  Job Number (ID):           	  " << theImageID
+      << "\n  Acquisition Date:          	  " << theAcquisitionDate
+      << "\n  Instrument:                	  " << theInstrument
+      << "\n  Instrument Index:          	  " << theInstrumentIndex
+      << "\n  Production Date:           	  " << theProductionDate
+      << "\n  Production Softwrae version:     	  " << theSoftwareVersion
+      << "\n  Number of Bands:           	  " << theNumBands
+      << "\n  Geo Center Point:         	  " << theRefGroundPoint
+      << "\n  Image Size:                	  " << theImageSize
+      << "\n  Incidence Angle:           	  " << theIncidenceAngle
+      << "\n  Viewing Angle:             	  " << theViewingAngle
+      << "\n  Viewing Angle Along Track:       	  " << theViewingAngleAlongTrack
+      << "\n  Viewing Angle Across Track:      	  " << theViewingAngleAcrossTrack
+      << "\n  Scene Orientation:                  " << theSceneOrientation 
+      << "\n  Corrected Attitude:                 " << corr_att
+      << "\n  Sun Azimuth:                        " << theSunAzimuth
+      << "\n  Sun Elevation:                      " << theSunElevation
+      << "\n  Sat Azimuth:                        " << theSatAzimuth
+      << "\n  Sub image offset:                   " << theSubImageOffset
+      << "\n  PolynomialLookAngleX size:          " << thePolynomialLookAngleX.size()
+      << "\n  thePosEcfSamples size:              " << thePosEcfSamples.size()
+      << "\n  theFrameVertexPosImagePoints size : " << theFrameVertexPosImagePoints.size()
+      << "\n"
+      << "\n---------------------------------------------------------"
+      << "\n  " << std::endl;
+}
+
+ossimString ossimFormosatDimapSupportData::getSensorID() const
+{
+  return theSensorID;
+}
+
+ossimString   ossimFormosatDimapSupportData::getMetadataVersionString() const
+{
+   if (theMetadataVersion == OSSIM_FORMOSAT_METADATA_VERSION_1_1)
+   {
+      return ossimString("1.1");
+   }
+   else if (theMetadataVersion == OSSIM_FORMOSAT_METADATA_VERSION_1_0)
+   {
+      return ossimString("1.0");
+   }
+   return ossimString("unknown");
+}
+
+ossimString ossimFormosatDimapSupportData::getAcquisitionDate() const
+{
+   return theAcquisitionDate;
+}
+
+ossimString ossimFormosatDimapSupportData::getProductionDate() const
+{
+   return theProductionDate;
+}
+
+ossimString ossimFormosatDimapSupportData::getSoftwareVersion() const
+{
+   return theSoftwareVersion;
+}
+
+ossimString ossimFormosatDimapSupportData::getImageID() const
+{
+   return theImageID;
+}
+
+ossimFilename ossimFormosatDimapSupportData::getMetadataFile() const
+{
+   return theMetadataFile;
+}
+
+ossimString ossimFormosatDimapSupportData::getInstrument() const
+{
+   return theInstrument;
+}
+
+ossim_uint32 ossimFormosatDimapSupportData::getInstrumentIndex() const
+{
+   return theInstrumentIndex;
+}
+
+void ossimFormosatDimapSupportData::getSunAzimuth(ossim_float64& az) const
+{
+   az = theSunAzimuth;
+}
+
+void ossimFormosatDimapSupportData::getSunElevation(ossim_float64& el) const
+{
+   el = theSunElevation;
+}
+
+void ossimFormosatDimapSupportData::getSatAzimuth(ossim_float64& az) const
+{
+   az = theSatAzimuth;
+}
+
+void ossimFormosatDimapSupportData::getImageSize(ossimDpt& sz) const
+{
+   sz = theImageSize;
+}
+
+void ossimFormosatDimapSupportData::getLineSamplingPeriod(ossim_float64& pe) const
+{
+   pe = theLineSamplingPeriod;
+}
+
+bool ossimFormosatDimapSupportData::isStarTrackerUsed() const
+{
+   return theStarTrackerUsed;
+}
+
+ossim_uint32 ossimFormosatDimapSupportData::getNumberOfBands() const
+{
+   return theNumBands;
+}
+
+
+void ossimFormosatDimapSupportData::getIncidenceAngle(ossim_float64& ia) const
+{
+   ia = theIncidenceAngle;
+}
+
+void ossimFormosatDimapSupportData::getViewingAngle(ossim_float64& va) const
+{
+   va = theViewingAngle;
+}
+
+void ossimFormosatDimapSupportData::getViewingAngleAlongTrack(ossim_float64& va) const
+{
+   va = theViewingAngleAlongTrack;
+}
+
+void ossimFormosatDimapSupportData::getViewingAngleAcrossTrack(ossim_float64& va) const
+{
+   va = theViewingAngleAcrossTrack;
+}
+
+void ossimFormosatDimapSupportData::getSceneOrientation(ossim_float64& so) const
+{
+   so = theSceneOrientation;
+}
+
+void ossimFormosatDimapSupportData::getRefGroundPoint(ossimGpt& gp) const
+{
+   gp = theRefGroundPoint;
+}
+
+void ossimFormosatDimapSupportData::getRefImagePoint(ossimDpt& rp) const
+{
+   rp = theRefImagePoint;
+}
+
+void ossimFormosatDimapSupportData::getRefLineTime(ossim_float64& rt) const
+{
+   rt = theRefLineTime;
+}
+
+void ossimFormosatDimapSupportData::getRefLineTimeLine(ossim_float64& rtl) const
+{
+   rtl = theRefLineTimeLine;
+}
+
+ossim_uint32 ossimFormosatDimapSupportData::getNumEphSamples() const
+{
+   return (ossim_uint32)theEphSampTimes.size();
+}
+
+ossim_uint32 ossimFormosatDimapSupportData::getNumAttSamples() const
+{
+   return (ossim_uint32)theAttSampTimes.size();
+}
+
+ossim_uint32 ossimFormosatDimapSupportData::getNumGeoPosPoints() const
+{
+   return (ossim_uint32)theGeoPosImagePoints.size();
+}
+
+void ossimFormosatDimapSupportData::getImageRect(ossimDrect& rect)const
+{
+   rect = ossimDrect(0.0, 0.0, theImageSize.x-1.0, theImageSize.y-1.0);
+}
+
+void ossimFormosatDimapSupportData::getSubImageOffset(ossimDpt& offset) const
+{
+   offset = theSubImageOffset;
+}
+
+bool ossimFormosatDimapSupportData::saveState(ossimKeywordlist& kwl,
+                                          const char* prefix)const
+{
+   kwl.add(prefix,
+           ossimKeywordNames::TYPE_KW,
+           "ossimFormosatDimapSupportData",
+           true);
+
+   kwl.add(prefix,
+           "metadata_file",
+           theMetadataFile,
+           true);
+
+   kwl.add(prefix,
+           ossimKeywordNames::AZIMUTH_ANGLE_KW,
+           theSunAzimuth,
+           true);
+
+   kwl.add(prefix,
+           ossimKeywordNames::ELEVATION_ANGLE_KW,
+           theSunElevation,
+           true);
+
+   kwl.add(prefix,
+           "sat_azimuth_angle",
+           theSatAzimuth,
+           true);
+
+   //---
+   // Note: since this is a new keyword, use the point.toString as there is
+   // no backwards compatibility issues.
+   //---
+
+   kwl.add(prefix,
+           "image_size",
+           ossimString::toString(theImageSize.x) + " " +
+           ossimString::toString(theImageSize.y),
+           true);
+
+   kwl.add(prefix,
+           "reference_ground_point",
+           ossimString::toString(theRefGroundPoint.latd()) + " " +
+           ossimString::toString(theRefGroundPoint.lond()) + " " +
+           ossimString::toString(theRefGroundPoint.height()) + " " +
+           theRefGroundPoint.datum()->code(),
+           true);
+
+   kwl.add(prefix,
+           "reference_image_point",
+           ossimString::toString(theRefImagePoint.x) + " " +
+           ossimString::toString(theRefImagePoint.y),
+           true);
+
+   kwl.add(prefix,
+           "sub_image_offset",
+           ossimString::toString(theSubImageOffset.x) + " " +
+           ossimString::toString(theSubImageOffset.y),
+           true);
+
+   kwl.add(prefix,
+           "reference_line_time",
+           theRefLineTime,
+           true);
+
+   kwl.add(prefix,
+           "reference_line_time_line",
+           theRefLineTimeLine,
+           true);
+
+   kwl.add(prefix,
+           "line_sampling_period",
+           theLineSamplingPeriod,
+           true);
+
+   ossimString tempString;
+   ossim_uint32 idx = 0;
+
+   tempString = "";
+   for(idx = 0; idx < thePolynomialLookAngleX.size(); ++idx)
+   {
+      tempString += (ossimString::toString(thePolynomialLookAngleX[idx]) + " ");
+   }
+
+   kwl.add(prefix,
+           "pixel_lookat_angle_x",
+           tempString,
+           true);
+
+   kwl.add(prefix,
+           "number_of_pixel_lookat_angle_x",
+           static_cast<ossim_uint32>(thePolynomialLookAngleX.size()),
+           true);
+
+   tempString = "";
+   for(idx = 0; idx < thePolynomialLookAngleY.size(); ++idx)
+   {
+      tempString += (ossimString::toString(thePolynomialLookAngleY[idx]) + " ");
+   }
+   kwl.add(prefix,
+           "pixel_lookat_angle_y",
+           tempString,
+           true);
+   kwl.add(prefix,
+           "number_of_pixel_lookat_angle_y",
+           static_cast<ossim_uint32>(thePolynomialLookAngleY.size()),
+           true);
+
+
+   tempString = "";
+   for(idx = 0; idx < theAttitudeSamples.size(); ++idx)
+   {
+      tempString += (ossimString::toString(theAttitudeSamples[idx].x) + " " +
+                     ossimString::toString(theAttitudeSamples[idx].y) + " " +
+                     ossimString::toString(theAttitudeSamples[idx].z) + " ");
+   }
+   kwl.add(prefix,
+           "attitude_samples",
+           tempString,
+           true);
+   kwl.add(prefix,
+           "number_of_attitude_samples",
+           static_cast<ossim_uint32>(theAttitudeSamples.size()),
+           true);
+
+   tempString = "";
+   for(idx = 0; idx < theAttSampTimes.size(); ++idx)
+   {
+      tempString += (ossimString::toString(theAttSampTimes[idx]) + " ");
+   }
+   kwl.add(prefix,
+           "attitude_sample_times",
+           tempString,
+           true);
+   kwl.add(prefix,
+           "number_of_attitude_sample_times",
+           static_cast<ossim_uint32>(theAttSampTimes.size()),
+           true);
+
+   tempString = "";
+   for(idx = 0; idx < thePosEcfSamples.size(); ++idx)
+   {
+      tempString += (ossimString::toString(thePosEcfSamples[idx].x) + " " +
+                     ossimString::toString(thePosEcfSamples[idx].y) + " " +
+                     ossimString::toString(thePosEcfSamples[idx].z) + " ");
+   }
+   kwl.add(prefix,
+           "position_ecf_samples",
+           tempString,
+           true);
+   kwl.add(prefix,
+           "number_of_position_ecf_samples",
+           static_cast<ossim_uint32>(thePosEcfSamples.size()),
+           true);
+
+   tempString = "";
+   for(idx = 0; idx < theVelEcfSamples.size(); ++idx)
+   {
+      tempString += (ossimString::toString(theVelEcfSamples[idx].x) + " " +
+                     ossimString::toString(theVelEcfSamples[idx].y) + " " +
+                     ossimString::toString(theVelEcfSamples[idx].z) + " ");
+   }
+   kwl.add(prefix,
+           "velocity_ecf_samples",
+           tempString,
+           true);
+   kwl.add(prefix,
+           "number_of_velocity_ecf_samples",
+           static_cast<ossim_uint32>(thePosEcfSamples.size()),
+           true);
+
+   tempString = "";
+   for(idx = 0; idx < theEphSampTimes.size(); ++idx)
+   {
+      tempString += (ossimString::toString(theEphSampTimes[idx]) + " ");
+   }
+
+   kwl.add(prefix,
+           "ephemeris_sample_times",
+           tempString,
+           true);
+   kwl.add(prefix,
+           "number_of_ephemeris_sample_times",
+           static_cast<ossim_uint32>(theEphSampTimes.size()),
+           true);
+
+   kwl.add(prefix,
+           "star_tracker_used_flag",
+           static_cast<ossim_uint32>(theStarTrackerUsed),
+           true);
+
+   kwl.add(prefix,
+           ossimKeywordNames::NUMBER_BANDS_KW,
+           theNumBands,
+           true);
+
+   kwl.add(prefix,
+           "image_id",
+           theImageID,
+           true);
+
+   kwl.add(prefix,
+           "instrument",
+           theInstrument,
+           true);
+
+   kwl.add(prefix,
+           "instrument_index",
+           theInstrumentIndex,
+           true);
+
+   kwl.add(prefix,
+           ossimKeywordNames::IMAGE_DATE_KW,
+           theAcquisitionDate,
+           true);
+
+   kwl.add(prefix,
+           "production_date",
+           theProductionDate,
+           true);
+
+   kwl.add(prefix,
+           "software_version",
+           theSoftwareVersion,
+           true);
+
+   kwl.add(prefix,
+           "incident_angle",
+           theIncidenceAngle,
+           true);
+
+   kwl.add(prefix,
+           "viewing_angle",
+           theViewingAngle,
+           true);
+
+   kwl.add(prefix,
+           "viewing_angle_along_track",
+           theViewingAngleAlongTrack,
+           true);
+   
+   kwl.add(prefix,
+           "viewing_angle_across_track",
+           theViewingAngleAcrossTrack,
+           true);
+
+   kwl.add(prefix,
+           "scene_orientation",
+           theSceneOrientation,
+           true);
+
+   kwl.add(prefix,
+           "sensorID",
+           theSensorID,
+           true);
+
+
+   tempString = "";
+   for(idx = 0; idx < thePhysicalBias.size(); ++idx)
+   {
+     tempString += (ossimString::toString(thePhysicalBias[idx]) + " ");
+   }
+   kwl.add(prefix,
+           "physical_bias",
+           tempString,
+           true);
+
+   tempString = "";
+   for(idx = 0; idx < thePhysicalGain.size(); ++idx)
+   {
+     tempString += (ossimString::toString(thePhysicalGain[idx]) + " ");
+   }
+   kwl.add(prefix,
+           "physical_gain",
+           tempString,
+           true);
+
+   tempString = "";
+   for(idx = 0; idx < theSolarIrradiance.size(); ++idx)
+   {
+     tempString += (ossimString::toString(theSolarIrradiance[idx]) + " ");
+   }
+
+   kwl.add(prefix,
+           "solar_irradiance",
+           tempString,
+           true);
+
+   return true;
+}
+
+bool ossimFormosatDimapSupportData::loadState(const ossimKeywordlist& kwl,
+                                          const char* prefix)
+{
+   clearFields();
+
+   ossimString type = kwl.find(prefix, ossimKeywordNames::TYPE_KW);
+
+   if(type != "ossimFormosatDimapSupportData")
+   {
+      return false;
+   }
+   theMetadataFile = kwl.find(prefix, "metadata_file");
+
+   theSunAzimuth   = ossimString(kwl.find(prefix, ossimKeywordNames::AZIMUTH_ANGLE_KW)).toDouble();
+   theSunElevation = ossimString(kwl.find(prefix, ossimKeywordNames::ELEVATION_ANGLE_KW)).toDouble();
+   theSatAzimuth   = ossimString(kwl.find(prefix, "sat_azimuth_angle")).toDouble();
+
+   theImageSize      = createDpt(kwl.find(prefix, "image_size"));
+   theRefGroundPoint = createGround(kwl.find(prefix, "reference_ground_point"));
+   theRefImagePoint  = createDpt(kwl.find(prefix, "reference_image_point"));
+   theSubImageOffset = createDpt(kwl.find(prefix, "sub_image_offset"));
+
+   theRefLineTime    = ossimString(kwl.find(prefix, "reference_line_time")).toDouble();
+
+   const char* lookup = kwl.find(prefix, "reference_line_time_line");
+   if (lookup)
+   {
+      theRefLineTimeLine = ossimString(lookup).toDouble();
+   }
+
+   theLineSamplingPeriod = ossimString(kwl.find(prefix, "line_sampling_period")).toDouble();
+
+
+   ossim_uint32 idx = 0;
+   ossim_uint32 total =  ossimString(kwl.find(prefix,"number_of_pixel_lookat_angle_x")).toUInt32();
+   ossimString tempString;
+
+   thePolynomialLookAngleX.resize(total);
+   tempString = kwl.find(prefix,"pixel_lookat_angle_x");
+   if(tempString != "")
+   {
+      std::istringstream in(tempString);
+      ossimString tempValue;
+      for(idx = 0; idx < thePolynomialLookAngleX.size();++idx)
+      {
+         in >> tempValue;
+         thePolynomialLookAngleX[idx] = tempValue.toDouble();
+      }
+   }
+
+   total =  ossimString(kwl.find(prefix,"number_of_pixel_lookat_angle_y")).toUInt32();
+   thePolynomialLookAngleY.resize(total);
+   tempString = kwl.find(prefix,"pixel_lookat_angle_y");
+   if(tempString != "")
+   {
+      std::istringstream in(tempString);
+      ossimString tempValue;
+      for(idx = 0; idx < thePolynomialLookAngleY.size();++idx)
+      {
+         in >> tempValue;
+         thePolynomialLookAngleY[idx] = tempValue.toDouble();
+      }
+   }
+
+
+   total =  ossimString(kwl.find(prefix,"number_of_attitude_samples")).toUInt32();
+   theAttitudeSamples.resize(total);
+   tempString = kwl.find(prefix,"attitude_samples");
+   if(tempString != "")
+   {
+      std::istringstream in(tempString);
+      ossimString x, y, z;
+      for(idx = 0; idx < theAttitudeSamples.size();++idx)
+      {
+         in >> x >> y >> z;
+         theAttitudeSamples[idx] =ossimDpt3d(x.toDouble(), y.toDouble(), z.toDouble());
+      }
+   }
+
+   total =  ossimString(kwl.find(prefix,"number_of_attitude_sample_times")).toUInt32();
+   theAttSampTimes.resize(total);
+   tempString = kwl.find(prefix,"attitude_sample_times");
+   if(tempString != "")
+   {
+      std::istringstream in(tempString);
+      ossimString tempValue;
+      for(idx = 0; idx < theAttSampTimes.size();++idx)
+      {
+         in >> tempValue;
+         theAttSampTimes[idx] = tempValue.toDouble();
+      }
+   }
+
+   total =  ossimString(kwl.find(prefix,"number_of_position_ecf_samples")).toUInt32();
+   thePosEcfSamples.resize(total);
+   tempString = kwl.find(prefix,"position_ecf_samples");
+   if(tempString != "")
+   {
+      std::istringstream in(tempString);
+      ossimString x, y, z;
+      for(idx = 0; idx < thePosEcfSamples.size();++idx)
+      {
+         in >> x >> y >> z;
+         thePosEcfSamples[idx] = ossimDpt3d(x.toDouble(), y.toDouble(), z.toDouble());
+      }
+   }
+
+   total =  ossimString(kwl.find(prefix,"number_of_velocity_ecf_samples")).toUInt32();
+   theVelEcfSamples.resize(total);
+   tempString = kwl.find(prefix,"velocity_ecf_samples");
+   if(tempString != "")
+   {
+      std::istringstream in(tempString);
+      ossimString x, y, z;
+      for(idx = 0; idx < theVelEcfSamples.size();++idx)
+      {
+         in >> x >> y >> z;
+         theVelEcfSamples[idx] = ossimDpt3d(x.toDouble(), y.toDouble(), z.toDouble());
+      }
+   }
+
+   total =  ossimString(kwl.find(prefix,"number_of_ephemeris_sample_times")).toUInt32();
+   theEphSampTimes.resize(total);
+   tempString = kwl.find(prefix,"ephemeris_sample_times");
+   if(tempString != "")
+   {
+      std::istringstream in(tempString);
+      ossimString tempValue;
+      for(idx = 0; idx < theEphSampTimes.size();++idx)
+      {
+         in >> tempValue;
+         theEphSampTimes[idx] = tempValue.toDouble();
+      }
+   }
+
+   tempString = "";
+   for(idx = 0; idx < theEphSampTimes.size(); ++idx)
+   {
+      tempString += (ossimString::toString(theEphSampTimes[idx]) + " ");
+   }
+
+   theStarTrackerUsed = ossimString(kwl.find(prefix, "star_tracker_used_flag")).toBool();
+   theNumBands        = ossimString(kwl.find(prefix, ossimKeywordNames::NUMBER_BANDS_KW)).toUInt32();
+   theAcquisitionDate = kwl.find(prefix, ossimKeywordNames::IMAGE_DATE_KW);
+   theProductionDate  = kwl.find(prefix, "production_date");
+   theSoftwareVersion = kwl.find(prefix, "software_version");
+   theImageID         = kwl.find(prefix, "image_id");
+   theInstrument      = kwl.find(prefix, "instrument");
+   theInstrumentIndex = ossimString(kwl.find(prefix, "instrument_index")).toUInt32();
+   
+   theIncidenceAngle          = ossimString(kwl.find(prefix, "incident_angle")).toDouble();
+   theViewingAngle            = ossimString(kwl.find(prefix, "viewing_angle")).toDouble();
+   theViewingAngleAlongTrack  = ossimString(kwl.find(prefix, "viewing_angle_along_track")).toDouble();
+   theViewingAngleAcrossTrack = ossimString(kwl.find(prefix, "viewing_angle_across_track")).toDouble();
+   theSceneOrientation        = ossimString(kwl.find(prefix, "scene_orientation")).toDouble();
+   
+	/* TODO add reading FrameVertex point */
+
+   theSensorID = ossimString(kwl.find(prefix, "sensorID"));
+
+   thePhysicalBias.resize(theNumBands);
+   tempString = kwl.find(prefix,"physical_bias");
+   if(tempString != "")
+   {
+     std::istringstream in(tempString);
+     ossimString tempValue;
+     for(idx = 0; idx < thePhysicalBias.size();++idx)
+     {
+       in >> tempValue;
+       thePhysicalBias[idx] = tempValue.toDouble();
+     }
+   }
+
+   thePhysicalGain.resize(theNumBands);
+   tempString = kwl.find(prefix,"physical_gain");
+   if(tempString != "")
+   {
+     std::istringstream in(tempString);
+     ossimString tempValue;
+     for(idx = 0; idx < thePhysicalGain.size();++idx)
+     {
+       in >> tempValue;
+       thePhysicalGain[idx] = tempValue.toDouble();
+     }
+   }
+
+   theSolarIrradiance.resize(theNumBands);
+   tempString = kwl.find(prefix,"solar_irradiance");
+   if(tempString != "")
+   {
+     std::istringstream in(tempString);
+     ossimString tempValue;
+     for(idx = 0; idx < theSolarIrradiance.size();++idx)
+     {
+       in >> tempValue;
+       theSolarIrradiance[idx] = tempValue.toDouble();
+     }
+   }
+
+   return true;
+}
+
+ossimGpt ossimFormosatDimapSupportData::createGround(const ossimString& s)const
+{
+   std::istringstream in(s);
+   ossimString lat, lon, height;
+   ossimString code;
+
+   in >> lat >> lon >> height >> code;
+
+   return ossimGpt(lat.toDouble(),
+                   lon.toDouble(),
+                   height.toDouble(),
+                   ossimDatumFactory::instance()->create(code));
+
+}
+
+ossimDpt ossimFormosatDimapSupportData::createDpt(const ossimString& s)const
+{
+   std::istringstream in(s);
+   ossimString x, y;
+   ossimString code;
+
+   in >> x >> y;
+
+   return ossimDpt(x.toDouble(), y.toDouble());
+
+}
+
+bool ossimFormosatDimapSupportData::parsePart1(
+   ossimRefPtr<ossimXmlDocument> xmlDocument)
+{
+   static const char MODULE[] = "ossimFormosatDimapSupportData::parsePart1";
+
+   ossimString xpath;
+   vector<ossimRefPtr<ossimXmlNode> > xml_nodes;
+
+   //---
+   // Fetch the ImageSize:
+   //---
+   xml_nodes.clear();
+   xpath = "/Dimap_Document/Raster_Dimensions/NCOLS";
+   xmlDocument->findNodes(xpath, xml_nodes);
+   if (xml_nodes.size() == 0)
+   {
+      setErrorStatus();
+      if(traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG)
+            << MODULE << " DEBUG:"
+            << "\nCould not find: " << xpath
+            << std::endl;
+      }
+      return false;
+   }
+   theImageSize.samp = xml_nodes[0]->getText().toDouble();
+
+   xml_nodes.clear();
+   xpath = "/Dimap_Document/Raster_Dimensions/NROWS";
+   xmlDocument->findNodes(xpath, xml_nodes);
+   if (xml_nodes.size() == 0)
+   {
+      setErrorStatus();
+      if(traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG)
+            << MODULE << " DEBUG:"
+            << "\nCould not find: " << xpath
+            << std::endl;
+      }
+      return false;
+   }
+   theImageSize.line = xml_nodes[0]->getText().toDouble();
+
+
+   //---
+   // We will make the RefImagePoint the zero base center of the image.  This
+   // is used by the ossimSensorModel::worldToLineSample iterative loop as
+   // the starting point.  Since the ossimSensorModel does not know of the
+   // sub image we make it zero base.
+   //---
+   theRefImagePoint.line = theImageSize.line / 2.0;
+   theRefImagePoint.samp = theImageSize.samp / 2.0;
+
+   xml_nodes.clear();
+   xpath = "/Dimap_Document/Data_Strip/Time_Stamp/REFERENCE_LINE";
+   xmlDocument->findNodes(xpath, xml_nodes);
+   if (xml_nodes.size() == 0)
+   {
+      setErrorStatus();
+      if(traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG)
+            << MODULE << " DEBUG:"
+            << "\nCould not find: " << xpath
+            << std::endl;
+      }
+      return false;
+   }
+
+   // Relative to full image frame.
+   theRefLineTimeLine = xml_nodes[0]->getText().toDouble() - 1.0;
+
+   // See if there's a sub image offset...
+   xml_nodes.clear();
+   xpath = "/Dimap_Document/Data_Processing/Regions_Of_Interest/Region_Of_Interest/COL_MIN";
+   xmlDocument->findNodes(xpath, xml_nodes);
+   if (xml_nodes.size() == 0)
+   {
+      theSubImageOffset.samp = 0.0;
+   }
+   else
+   {
+      theSubImageOffset.samp = xml_nodes[0]->getText().toDouble() - 1.0;
+   }
+
+   xml_nodes.clear();
+   xpath = "/Dimap_Document/Data_Processing/Regions_Of_Interest/Region_Of_Interest/ROW_MIN";
+   xmlDocument->findNodes(xpath, xml_nodes);
+   if (xml_nodes.size() == 0)
+   {
+      theSubImageOffset.line = 0.0;
+   }
+   else
+   {
+      theSubImageOffset.line = xml_nodes[0]->getText().toDouble() - 1.0;
+   }
+
+   //---
+   // Fetch the RefLineTime:
+   //---
+   xml_nodes.clear();
+   xpath = "/Dimap_Document/Data_Strip/Time_Stamp/REFERENCE_TIME";
+   xmlDocument->findNodes(xpath, xml_nodes);
+   if (xml_nodes.size() == 0)
+   {
+      setErrorStatus();
+      if(traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG)
+            << MODULE << " DEBUG:"
+            << "\nCould not find: " << xpath
+            << std::endl;
+      }
+      return false;
+   }
+   theAcquisitionDate = xml_nodes[0]->getText();
+   convertTimeStamp(theAcquisitionDate, theRefLineTime);
+
+   //---
+   // Fetch the ProductionDate:
+   //---
+   xml_nodes.clear();
+   xpath = "/Dimap_Document/Production/DATASET_PRODUCTION_DATE";
+   xmlDocument->findNodes(xpath, xml_nodes);
+   if (xml_nodes.size() == 0)
+   {
+      setErrorStatus();
+      if(traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG)
+            << MODULE << " DEBUG:"
+            << "\nCould not find: " << xpath
+            << std::endl;
+      }
+      return false;
+   }
+   theProductionDate = xml_nodes[0]->getText();
+
+   //---
+   // Fetch the SoftwareVersion:
+   //---
+   xml_nodes.clear();
+   xpath = "/Dimap_Document/Production/Production_Facility/SOFTWARE_VERSION";
+   xmlDocument->findNodes(xpath, xml_nodes);
+   if (xml_nodes.size() == 0)
+   {
+      setErrorStatus();
+      if(traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG)
+            << MODULE << " DEBUG:"
+            << "\nCould not find: " << xpath
+            << std::endl;
+      }
+      return false;
+   }
+   theSoftwareVersion = xml_nodes[0]->getText();
+   //---
+   // Fetch the Instrument:
+   //---
+   xml_nodes.clear();
+   xpath = "/Dimap_Document/Dataset_Sources/Source_Information/Scene_Source/INSTRUMENT";
+   xmlDocument->findNodes(xpath, xml_nodes);
+   if (xml_nodes.size() == 0)
+   {
+      setErrorStatus();
+      if(traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG)
+            << MODULE << " DEBUG:"
+            << "\nCould not find: " << xpath
+            << std::endl;
+      }
+      return false;
+   }
+   theInstrument = xml_nodes[0]->getText();
+
+   //---
+   // Fetch the Instrument Index:
+   //---
+   xml_nodes.clear();
+   xpath = "/Dimap_Document/Dataset_Sources/Source_Information/Scene_Source/INSTRUMENT_INDEX";
+   xmlDocument->findNodes(xpath, xml_nodes);
+   if (xml_nodes.size() == 0)
+   {
+      setErrorStatus();
+      if(traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG)
+            << MODULE << " DEBUG:"
+            << "\nCould not find: " << xpath
+            << std::endl;
+      }
+      return false;
+   }
+   theInstrumentIndex = xml_nodes[0]->getText().toUInt32();
+
+   return true;
+}
+
+bool ossimFormosatDimapSupportData::parsePart2(
+   ossimRefPtr<ossimXmlDocument> xmlDocument)
+{
+   static const char MODULE[] = "ossimFormosatDimapSupportData::parsePart2";
+
+   ossimString xpath;
+   std::vector<ossimRefPtr<ossimXmlNode> > xml_nodes;
+   std::vector<ossimRefPtr<ossimXmlNode> > sub_nodes;
+   std::vector<ossimRefPtr<ossimXmlNode> >::iterator node;
+   ossim_int32 band_index;
+
+   //---
+   // Fetch the LineSamplingPeriod:
+   //---
+   xml_nodes.clear();
+   xpath = "/Dimap_Document/Data_Strip/Time_Stamp/LINE_PERIOD";
+
+   xmlDocument->findNodes(xpath, xml_nodes);
+   if (xml_nodes.size() == 0)
+   {
+      setErrorStatus();
+      if(traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG)
+            << MODULE << " DEBUG:"
+            << "\nCould not find: " << xpath
+            << std::endl;
+      }
+      return false;
+   }
+   theLineSamplingPeriod = xml_nodes[0]->getText().toDouble();
+
+
+   //---
+   // Fetch number of bands
+   //---
+   xml_nodes.clear();
+   xpath = "/Dimap_Document/Raster_Dimensions/NBANDS";
+   xmlDocument->findNodes(xpath, xml_nodes);
+   if (xml_nodes.size() == 0)
+   {
+      setErrorStatus();
+      if(traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG)
+            << MODULE << " DEBUG:"
+            << "\nCould not find: " << xpath
+            << std::endl;
+      }
+      return false;
+   }
+   theNumBands = atoi(xml_nodes[0]->getText());
+
+
+   if (theNumBands == 1)
+   {
+      band_index = 0;
+   }
+   else if (theNumBands == 4)
+   {
+         band_index = 1; // using green band for Polynomial Look angles
+   }
+   else
+   {
+      setErrorStatus();
+      if(traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG)
+            << MODULE << " DEBUG:"
+            << "\nBand ERROR!"
+            << std::endl;
+      }
+      return false;
+   }
+
+   //---
+   // Fetch the PolynomialLookAngleX and PolynomialLookAngleY arrays. 
+   //---
+
+   thePolynomialLookAngleX.clear();
+   thePolynomialLookAngleY.clear();
+
+   xml_nodes.clear();
+   xpath = "/Dimap_Document/Data_Strip/Sensor_Configuration/"
+      "Instrument_Look_Angles_List/Instrument_Look_Angles/";
+   xmlDocument->findNodes(xpath, xml_nodes);
+//   if (xml_nodes.size() != theNumBands)
+//   {
+      if(xml_nodes.size() == 0)
+      {
+         setErrorStatus();
+         if(traceDebug())
+         {
+            ossimNotify(ossimNotifyLevel_DEBUG)
+               << MODULE << " DEBUG:"
+               << "\nCould not find: " << xpath
+               << std::endl;
+         }
+         return false;
+      }
+
+  node = xml_nodes.begin();
+  while (node != xml_nodes.end())
+  {
+    sub_nodes.clear();
+    xpath = "BAND_INDEX";
+    (*node)->findChildNodes(xpath, sub_nodes);
+    if (sub_nodes.size() == 0)
+    {
+      	setErrorStatus();
+         if(traceDebug())
+         {
+            ossimNotify(ossimNotifyLevel_DEBUG)
+               << MODULE << " DEBUG:"
+               << "\nCould not find: " << xpath
+               << std::endl;
+         }
+      	return false;
+    }
+
+    ossim_int32 bandIndex = sub_nodes[0]->getText().toInt32() - 1;
+
+    if( (bandIndex >= static_cast<int>(theNumBands) ) || (bandIndex<0) )
+    {
+       ossimNotify(ossimNotifyLevel_WARN) << "ossimFormosatDimapSupportData: ERROR: Band index outside of range\n";
+       return false;
+    }
+
+	if(bandIndex == band_index)
+	{
+  		sub_nodes.clear();
+    	xpath = "Polynomial_Look_Angles/XLOS_0";
+    	(*node)->findChildNodes(xpath, sub_nodes);
+    	if (sub_nodes.size() == 0)
+    	{
+      		setErrorStatus();
+      		return false;
+    	}
+    	thePolynomialLookAngleX.push_back(sub_nodes[0]->getText().toDouble());
+
+      sub_nodes.clear();
+    	xpath = "Polynomial_Look_Angles/XLOS_1";
+    	(*node)->findChildNodes(xpath, sub_nodes);
+    	if (sub_nodes.size() == 0)
+    	{
+      		setErrorStatus();
+      		return false;
+    	}
+    	thePolynomialLookAngleX.push_back(sub_nodes[0]->getText().toDouble());
+
+      sub_nodes.clear();
+    	xpath = "Polynomial_Look_Angles/XLOS_2";
+    	(*node)->findChildNodes(xpath, sub_nodes);
+    	if (sub_nodes.size() == 0)
+    	{
+      		setErrorStatus();
+      		return false;
+    	}
+    	thePolynomialLookAngleX.push_back(sub_nodes[0]->getText().toDouble());
+
+      sub_nodes.clear();
+    	xpath = "Polynomial_Look_Angles/XLOS_3";
+    	(*node)->findChildNodes(xpath, sub_nodes);
+    	if (sub_nodes.size() == 0)
+    	{
+      		setErrorStatus();
+      		return false;
+    	}
+    	thePolynomialLookAngleX.push_back(sub_nodes[0]->getText().toDouble());
+
+      sub_nodes.clear();
+    	xpath = "Polynomial_Look_Angles/YLOS_0";
+    	(*node)->findChildNodes(xpath, sub_nodes);
+    	if (sub_nodes.size() == 0)
+    	{
+      		setErrorStatus();
+      		return false;
+    	}
+    	thePolynomialLookAngleY.push_back(sub_nodes[0]->getText().toDouble());
+
+      sub_nodes.clear();
+    	xpath = "Polynomial_Look_Angles/YLOS_1";
+    	(*node)->findChildNodes(xpath, sub_nodes);
+    	if (sub_nodes.size() == 0)
+    	{
+      		setErrorStatus();
+      		return false;
+    	}
+    	thePolynomialLookAngleY.push_back(sub_nodes[0]->getText().toDouble());
+
+      sub_nodes.clear();
+    	xpath = "Polynomial_Look_Angles/YLOS_2";
+    	(*node)->findChildNodes(xpath, sub_nodes);
+    	if (sub_nodes.size() == 0)
+    	{
+      		setErrorStatus();
+      		return false;
+    	}
+    	thePolynomialLookAngleY.push_back(sub_nodes[0]->getText().toDouble());
+
+      sub_nodes.clear();
+    	xpath = "Polynomial_Look_Angles/YLOS_3";
+    	(*node)->findChildNodes(xpath, sub_nodes);
+    	if (sub_nodes.size() == 0)
+    	{
+      		setErrorStatus();
+      		return false;
+    	}
+    	thePolynomialLookAngleY.push_back(sub_nodes[0]->getText().toDouble());
+	}
+    ++node;
+  }
+
+
+   //---
+   // Fetch the Attitude Samples:
+   //---
+   theAttitudeSamples.clear();
+   theAttSampTimes.clear();
+   xml_nodes.clear();
+   xpath = "/Dimap_Document/Data_Strip/Attitudes/Corrected_Attitudes/ECF_Attitude/Angle_List/Angle";
+   xmlDocument->findNodes(xpath, xml_nodes);
+   if (xml_nodes.size() == 0)
+   {
+		setErrorStatus();
+        if(traceDebug())
+        {
+            ossimNotify(ossimNotifyLevel_DEBUG)
+               << MODULE << " DEBUG:"
+               << "\nCould not find: " << xpath
+               << std::endl;
+        }
+        return false;
+   }
+
+   node = xml_nodes.begin();
+   while (node != xml_nodes.end())
+   {
+      ossimDpt3d V;
+
+      sub_nodes.clear();
+      xpath = "PITCH";
+      (*node)->findChildNodes(xpath, sub_nodes);
+      if (sub_nodes.size() == 0)
+      {
+         setErrorStatus();
+         return false;
+      }
+      V.x = sub_nodes[0]->getText().toDouble();
+
+      sub_nodes.clear();
+      xpath = "ROLL";
+      (*node)->findChildNodes(xpath, sub_nodes);
+      if (sub_nodes.size() == 0)
+      {
+         setErrorStatus();
+         return false;
+      }
+      V.y = sub_nodes[0]->getText().toDouble();
+
+      sub_nodes.clear();
+      xpath = "YAW";
+      (*node)->findChildNodes(xpath, sub_nodes);
+      if (sub_nodes.size() == 0)
+      {
+         setErrorStatus();
+         return false;
+      }
+      V.z = sub_nodes[0]->getText().toDouble();
+
+      theAttitudeSamples.push_back(V);
+
+      sub_nodes.clear();
+      xpath = "TIME";
+      (*node)->findChildNodes(xpath, sub_nodes);
+      if (sub_nodes.size() == 0)
+      {
+         setErrorStatus();
+         return false;
+      }
+      theAttSampTimes.push_back(convertTimeStamp(sub_nodes[0]->getText()));
+
+      ++node;
+   }
+
+   return true;
+}
+
+bool ossimFormosatDimapSupportData::parsePart3(
+   ossimRefPtr<ossimXmlDocument> xmlDocument)
+{
+   ossimString xpath;
+   std::vector<ossimRefPtr<ossimXmlNode> > xml_nodes;
+   std::vector<ossimRefPtr<ossimXmlNode> > sub_nodes;
+   std::vector<ossimRefPtr<ossimXmlNode> >::iterator node;
+
+   static const char MODULE[] = "ossimFormosatDimapSupportData::parsePart3";
+
+
+   //---
+   // Fetch the ephemeris samples:
+   //---
+   thePosEcfSamples.clear();
+   theVelEcfSamples.clear();
+   theEphSampTimes.clear();
+   xml_nodes.clear();
+   xpath = "/Dimap_Document/Data_Strip/Ephemeris/Raw_Ephemeris/Point_List/Point";
+   xmlDocument->findNodes(xpath, xml_nodes);
+   if (xml_nodes.size() == 0)
+   {
+      	setErrorStatus();
+        if(traceDebug())
+        {
+            ossimNotify(ossimNotifyLevel_DEBUG)
+               << MODULE << " DEBUG:"
+               << "\nCould not find: " << xpath
+               << std::endl;
+        }
+      	return false;
+   }
+   node = xml_nodes.begin();
+
+   while (node != xml_nodes.end())
+   {
+      ossimDpt3d VP;
+      sub_nodes.clear();
+      xpath  = "Location/X";
+      (*node)->findChildNodes(xpath, sub_nodes);
+      if (sub_nodes.size() == 0)
+      {
+         setErrorStatus();
+         return false;
+      }
+      VP.x = sub_nodes[0]->getText().toDouble();
+
+      sub_nodes.clear();
+      xpath  = "Location/Y";
+      (*node)->findChildNodes(xpath, sub_nodes);
+      if (sub_nodes.size() == 0)
+      {
+         setErrorStatus();
+         return false;
+      }
+      VP.y = sub_nodes[0]->getText().toDouble();
+
+      sub_nodes.clear();
+      xpath  = "Location/Z";
+      (*node)->findChildNodes(xpath, sub_nodes);
+      if (sub_nodes.size() == 0)
+      {
+         setErrorStatus();
+         return false;
+      }
+      VP.z = sub_nodes[0]->getText().toDouble();
+
+      thePosEcfSamples.push_back(VP);
+
+      ossimDpt3d VV;
+      sub_nodes.clear();
+      xpath = "Velocity/X";
+      (*node)->findChildNodes(xpath, sub_nodes);
+      if (sub_nodes.size() == 0)
+      {
+         setErrorStatus();
+         return false;
+      }
+      VV.x = sub_nodes[0]->getText().toDouble();
+
+      sub_nodes.clear();
+      xpath = "Velocity/Y";
+      (*node)->findChildNodes(xpath, sub_nodes);
+      if (sub_nodes.size() == 0)
+      {
+         setErrorStatus();
+         return false;
+      }
+      VV.y = sub_nodes[0]->getText().toDouble();
+
+      sub_nodes.clear();
+      xpath = "Velocity/Z";
+      (*node)->findChildNodes(xpath, sub_nodes);
+      if (sub_nodes.size() == 0)
+      {
+         setErrorStatus();
+         return false;
+      }
+      VV.z = sub_nodes[0]->getText().toDouble();
+
+      theVelEcfSamples.push_back(VV);
+
+      sub_nodes.clear();
+      xpath  = "TIME";
+      (*node)->findChildNodes(xpath, sub_nodes);
+      if (sub_nodes.size() == 0)
+      {
+         setErrorStatus();
+         return false;
+      }
+      theEphSampTimes.push_back(convertTimeStamp(sub_nodes[0]->getText()));
+
+      ++node;
+   }
+
+   //---
+   // Fetch the star tracker flag:
+   //---
+   xml_nodes.clear();
+   xpath = "/Dimap_Document/Data_Strip/Satellite_Attitudes/Corrected_Attitudes/"
+      "STAR_TRACKER_USED";
+   xmlDocument->findNodes(xpath, xml_nodes);
+   if (xml_nodes.size() == 0)
+   {
+         theStarTrackerUsed = false;
+//       setErrorStatus();
+//       return false;
+   }
+   else
+   {
+      if (xml_nodes[0]->getText() == "Y")
+         theStarTrackerUsed = true;
+      else
+         theStarTrackerUsed = false;
+   }
+
+   //---
+   // Geoposition points:
+   //---
+   xml_nodes.clear();
+   xpath = "/Dimap_Document/Geoposition/Geoposition_Points/Tie_Point";
+   xmlDocument->findNodes(xpath, xml_nodes);
+   node = xml_nodes.begin();
+   while (node != xml_nodes.end())
+   {
+      ossimGpt gpt;
+      ossimDpt  ipt;
+
+      sub_nodes.clear();
+      xpath = "TIE_POINT_DATA_Y";
+      (*node)->findChildNodes(xpath, sub_nodes);
+      if (sub_nodes.size() == 0)
+      {
+         setErrorStatus();
+         return false;
+      }
+      ipt.line = sub_nodes[0]->getText().toDouble() - 1.0;
+
+      sub_nodes.clear();
+      xpath = "TIE_POINT_DATA_X";
+      (*node)->findChildNodes(xpath, sub_nodes);
+      if (sub_nodes.size() == 0)
+      {
+         setErrorStatus();
+         return false;
+      }
+      ipt.samp = sub_nodes[0]->getText().toDouble() - 1.0;
+
+      sub_nodes.clear();
+      xpath = "TIE_POINT_CRS_Y";
+      (*node)->findChildNodes(xpath, sub_nodes);
+      if (sub_nodes.size() == 0)
+      {
+         setErrorStatus();
+         return false;
+      }
+      gpt.lat = sub_nodes[0]->getText().toDouble();
+
+      sub_nodes.clear();
+      xpath = "TIE_POINT_CRS_X";
+      (*node)->findChildNodes(xpath, sub_nodes);
+      if (sub_nodes.size() == 0)
+      {
+         setErrorStatus();
+         return false;
+      }
+      gpt.lon = sub_nodes[0]->getText().toDouble();
+
+      sub_nodes.clear();
+      xpath = "TIE_POINT_CRS_Z";
+      (*node)->findChildNodes(xpath, sub_nodes);
+      if (sub_nodes.size() != 0)
+      {
+          gpt.hgt = sub_nodes[0]->getText().toDouble();
+      }
+
+      theGeoPosImagePoints.push_back(ipt);
+      theGeoPosGroundPoints.push_back(gpt);
+
+      ++node;
+   }
+
+   return true;
+}
+bool ossimFormosatDimapSupportData::parsePart4(
+                                           ossimRefPtr<ossimXmlDocument> xmlDocument)
+{
+  ossimString xpath;
+  std::vector<ossimRefPtr<ossimXmlNode> > xml_nodes;
+  std::vector<ossimRefPtr<ossimXmlNode> > sub_nodes;
+  std::vector<ossimRefPtr<ossimXmlNode> >::iterator node;
+
+  static const char MODULE[] = "ossimFormosatDimapSupportData::parsePart4";
+
+  //---
+  // Fetch the gain and bias for each spectral band:
+  //---
+
+  thePhysicalGain.assign(theNumBands, 1.000);
+  thePhysicalBias.assign(theNumBands, 0.000);
+  xml_nodes.clear();
+  xpath = "/Dimap_Document/Data_Strip/Sensor_Calibration/Calibration/Band_Parameters/";
+  	 
+  xmlDocument->findNodes(xpath, xml_nodes);
+  if(xml_nodes.size() == 0)
+  {
+     setErrorStatus();
+     if(traceDebug())
+     {
+  	    ossimNotify(ossimNotifyLevel_DEBUG)
+    		      	<< MODULE << " DEBUG:"
+            	  	<< "\nCould not find: " << xpath
+               		<< std::endl;
+      }
+      return false;
+  }
+
+  node = xml_nodes.begin();
+  while (node != xml_nodes.end())
+  {
+    sub_nodes.clear();
+    xpath = "BAND_INDEX";
+    (*node)->findChildNodes(xpath, sub_nodes);
+    if (sub_nodes.size() == 0)
+    {
+      	setErrorStatus();
+         if(traceDebug())
+         {
+            ossimNotify(ossimNotifyLevel_DEBUG)
+               << MODULE << " DEBUG:"
+               << "\nCould not find: " << xpath
+               << std::endl;
+         }
+      	return false;
+    }
+
+    ossim_int32 bandIndex = sub_nodes[0]->getText().toInt32() - 1;
+	
+
+    if( (bandIndex >= static_cast<int>(theNumBands) ) || (bandIndex<0) )
+    {
+       ossimNotify(ossimNotifyLevel_WARN) << "ossimFormosatDimapSupportData: ERROR: Band index outside of range\n";
+       return false;
+    }
+
+	sub_nodes.clear();
+    xpath = "Gain_Section_List/Gain_Section/PHYSICAL_BIAS";
+    (*node)->findChildNodes(xpath, sub_nodes);
+    if (sub_nodes.size() == 0)
+    {
+    	setErrorStatus();
+    	return false;
+    }
+    thePhysicalBias[bandIndex] = sub_nodes[0]->getText().toDouble();
+    	
+	sub_nodes.clear();
+    xpath = "Gain_Section_List/Gain_Section/PHYSICAL_GAIN";
+    (*node)->findChildNodes(xpath, sub_nodes);
+    if (sub_nodes.size() == 0)
+    {
+    	setErrorStatus();
+    	return false;
+    }
+    thePhysicalGain[bandIndex] = sub_nodes[0]->getText().toDouble();
+	
+    ++node;
+  }
+
+  theSolarIrradiance.assign(theNumBands, 0.000);
+  xml_nodes.clear();
+  xpath = "/Dimap_Document/Data_Strip/Sensor_Calibration/Solar_Irradiance/Band_Solar_Irradiance";
+  xmlDocument->findNodes(xpath, xml_nodes);
+  node = xml_nodes.begin();
+  while (node != xml_nodes.end())
+  {
+    sub_nodes.clear();
+    xpath = "BAND_INDEX";
+    (*node)->findChildNodes(xpath, sub_nodes);
+    if (sub_nodes.size() == 0)
+    {
+      setErrorStatus();
+      return false;
+    }
+
+    ossim_int32 bandIndex = sub_nodes[0]->getText().toInt32() - 1;
+    
+    if((bandIndex >= static_cast<ossim_int32>(theNumBands) ) || (bandIndex<0))
+    {
+       ossimNotify(ossimNotifyLevel_WARN) << "ossimFormosatDimapSupportData::parsePart4 ERROR: Band index outside of range\n";
+       return false;
+    }
+    
+    sub_nodes.clear();
+    xpath = "SOLAR_IRRADIANCE_VALUE";
+    (*node)->findChildNodes(xpath, sub_nodes);
+    if (sub_nodes.size() == 0)
+    {
+      setErrorStatus();
+      return false;
+    }
+    theSolarIrradiance[bandIndex] = sub_nodes[0]->getText().toDouble();
+
+    ++node;
+  }
+
+  return true;
+}
+
+bool ossimFormosatDimapSupportData::initMetadataVersion(ossimRefPtr<ossimXmlDocument> xmlDocument)
+{
+   ossimString xpath;
+   std::vector<ossimRefPtr<ossimXmlNode> > xml_nodes;
+
+   //---
+   // Get the version string which can be used as a key for parsing.
+   //---
+   xpath = "/Dimap_Document/Metadata_Id/METADATA_FORMAT";
+   xmlDocument->findNodes(xpath, xml_nodes);
+   if (xml_nodes.size() == 0)
+   {
+      setErrorStatus();
+      if(traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG)
+            << "DEBUG:\nCould not find: " << xpath
+            << endl;
+      }
+      return false;
+   }
+
+   ossimString attribute = "version";
+   ossimString value;
+   xml_nodes[0]->getAttributeValue(value, attribute);
+   if (value == "1.0")
+   {
+      theMetadataVersion = OSSIM_FORMOSAT_METADATA_VERSION_1_0;
+   }
+   else if (value == "1.1")
+   {
+      theMetadataVersion = OSSIM_FORMOSAT_METADATA_VERSION_1_1;
+   }
+
+   if (theMetadataVersion == OSSIM_FORMOSAT_METADATA_VERSION_UNKNOWN)
+   {
+      setErrorStatus();
+      if (traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_WARN)
+            << "WARNING:  metadata version not found!"
+            << std::endl;
+      }
+      return false;
+   }
+   return true;
+}
+
+bool ossimFormosatDimapSupportData::initImageId(
+   ossimRefPtr<ossimXmlDocument> xmlDocument)
+{
+   ossimString xpath;
+   vector<ossimRefPtr<ossimXmlNode> > xml_nodes;
+
+   //---
+   // Fetch the Image ID:
+   //---
+   xpath = "/Dimap_Document/Production/JOB_ID";
+   xmlDocument->findNodes(xpath, xml_nodes);
+   if (xml_nodes.size() == 0)
+   {
+      setErrorStatus();
+      if(traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG)
+            << "DEBUG:\nCould not find: " << xpath
+            << endl;
+      }
+      return false;
+   }
+   theImageID = xml_nodes[0]->getText();
+   return true;
+}
+
+bool ossimFormosatDimapSupportData::initSceneSource(
+   ossimRefPtr<ossimXmlDocument> xmlDocument)
+{
+   ossimString xpath;
+   vector<ossimRefPtr<ossimXmlNode> > xml_nodes;
+
+  //---
+  // Fetch the mission index (Formosat 1 or 2):
+  // and generate theSensorID
+  //---
+   xml_nodes.clear();
+   xpath = "/Dimap_Document/Dataset_Sources/Source_Information/Scene_Source/MISSION_INDEX";
+   xmlDocument->findNodes(xpath, xml_nodes);
+   if (xml_nodes.size() == 0)
+   {
+     setErrorStatus();
+     if(traceDebug())
+       {
+	 		ossimNotify(ossimNotifyLevel_DEBUG)
+	   				<< "DEBUG:\nCould not find: " << xpath
+	   				<< std::endl;
+       }
+     return false;
+   }
+   if (xml_nodes[0]->getText() == "1")
+     theSensorID = "Formosat 1";
+   if (xml_nodes[0]->getText() == "2")
+     theSensorID = "Formosat 2";
+
+   //---
+   // Fetch the Viewing Angle Along Track:
+   //---
+   xml_nodes.clear();
+   xpath = "/Dimap_Document/Dataset_Sources/Source_Information/Scene_Source/SUN_AZIMUTH";
+   xmlDocument->findNodes(xpath, xml_nodes);
+   if (xml_nodes.size() == 0)
+   {
+      setErrorStatus();
+      if(traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG)
+            << "DEBUG:\nCould not find: " << xpath
+            << std::endl;
+      }
+      return false;
+   }
+   theSunAzimuth = xml_nodes[0]->getText().toDouble();
+
+   //---
+   // Fetch the Viewing Angle Across Track:
+   //---
+   xml_nodes.clear();
+   xpath = "/Dimap_Document/Dataset_Sources/Source_Information/Scene_Source/VIEWING_ANGLE_ALONG_TRACK";
+   xmlDocument->findNodes(xpath, xml_nodes);
+   if (xml_nodes.size() == 0)
+   {
+      setErrorStatus();
+      if(traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG)
+            << "DEBUG:\nCould not find: " << xpath
+            << std::endl;
+      }
+      return false;
+   }
+   theViewingAngleAlongTrack = xml_nodes[0]->getText().toDouble();
+ 
+   //---
+   // Fetch the Sun Azimuth:
+   //---
+   xml_nodes.clear();
+   xpath = "/Dimap_Document/Dataset_Sources/Source_Information/Scene_Source/VIEWING_ANGLE_ACROSS_TRACK";
+   xmlDocument->findNodes(xpath, xml_nodes);
+   if (xml_nodes.size() == 0)
+   {
+      setErrorStatus();
+      if(traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG)
+            << "DEBUG:\nCould not find: " << xpath
+            << std::endl;
+      }
+      return false;
+   }
+   theViewingAngleAcrossTrack = xml_nodes[0]->getText().toDouble();
+ 
+   //---
+   // Fetch the Sun Elevation:
+   //---
+   xml_nodes.clear();
+   xpath = "/Dimap_Document/Dataset_Sources/Source_Information/Scene_Source/SUN_ELEVATION";
+   xmlDocument->findNodes(xpath, xml_nodes);
+   if (xml_nodes.size() == 0)
+   {
+      setErrorStatus();
+      if(traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG)
+            << "DEBUG:\nCould not find: " << xpath
+            << std::endl;
+      }
+      return false;
+   }
+   theSunElevation = xml_nodes[0]->getText().toDouble();
+
+   //---
+   // Fetch incidence angle:
+   //---
+   xml_nodes.clear();
+   xpath = "/Dimap_Document/Dataset_Sources/Source_Information/Scene_Source/SATELLITE_INCIDENCE_ANGLE";
+   xmlDocument->findNodes(xpath, xml_nodes);
+   if (xml_nodes.size() == 0)
+   {
+      setErrorStatus();
+      if(traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG)
+            << "DEBUG:\nCould not find: " << xpath
+            << std::endl;
+      }
+      return false;
+   }
+   theIncidenceAngle = xml_nodes[0]->getText().toDouble();
+
+   //---
+   // Fetch incidence angle:
+   //---
+   xml_nodes.clear();
+   xpath = "/Dimap_Document/Dataset_Sources/Source_Information/Scene_Source/SATELLITE_AZIMUTH_ANGLE";
+   xmlDocument->findNodes(xpath, xml_nodes);
+   if (xml_nodes.size() == 0)
+   {
+      setErrorStatus();
+      if(traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG)
+            << "DEBUG:\nCould not find: " << xpath
+            << std::endl;
+      }
+      return false;
+   }
+   theSatAzimuth = xml_nodes[0]->getText().toDouble();
+
+   //---
+   // Fetch viewing angle:
+   /*
+    * FROM FORMOSAT: You can use use incidence angle to calculate viewing angle
+    * (called look direction as well).
+    * FIX (see below): need theSatelliteAltitude and theIncidenceAngle. The
+    * equation is shown below where RT is the mean value of WGS84 ellipsoid 
+    * semi-axis.
+    *
+    * */
+   //---
+  
+   xml_nodes.clear();
+   xpath = "/Dimap_Document/Data_Strip/Ephemeris/SATELLITE_ALTITUDE";
+
+   theViewingAngle = -1.0;
+   xmlDocument->findNodes(xpath, xml_nodes);
+   if (xml_nodes.size() == 0)
+   {
+      setErrorStatus();
+      if(traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG)
+            << "DEBUG:\nCould not find: " << xpath
+            << std::endl;
+      }
+      return false;
+   }
+   //compute VIEWING_ANGLE
+   double theSatelliteAltitude =  xml_nodes[0]->getText().toDouble();
+   double RT = 63710087714.0;
+   theViewingAngle = asin((RT/(RT+theSatelliteAltitude))*sin(theIncidenceAngle));
+
+   return true;
+}
+
+bool ossimFormosatDimapSupportData::initFramePoints(
+   ossimRefPtr<ossimXmlDocument> xmlDocument)
+{
+   ossimString xpath;
+   vector<ossimRefPtr<ossimXmlNode> > xml_nodes;
+
+   //---
+   // Corner points:
+   //---
+   xml_nodes.clear();
+   xpath = "/Dimap_Document/Dataset_Frame/Vertex";
+   xmlDocument->findNodes(xpath, xml_nodes);
+   if (xml_nodes.size() != 4)
+   {
+      setErrorStatus();
+      return false;
+   }
+   std::vector<ossimRefPtr<ossimXmlNode> >::iterator node = xml_nodes.begin();
+   while (node != xml_nodes.end())
+   {
+      ossimGpt gpt;
+      ossimDpt ipt;
+
+      std::vector<ossimRefPtr<ossimXmlNode> > sub_nodes;
+      xpath = "FRAME_LAT";
+      (*node)->findChildNodes(xpath, sub_nodes);
+      if (sub_nodes.size() == 0)
+      {
+         setErrorStatus();
+         return false;
+      }
+      gpt.lat = sub_nodes[0]->getText().toDouble();
+
+      sub_nodes.clear();
+      xpath = "FRAME_LON";
+      (*node)->findChildNodes(xpath, sub_nodes);
+      if (sub_nodes.size() == 0)
+      {
+         setErrorStatus();
+         return false;
+      }
+      gpt.lon = sub_nodes[0]->getText().toDouble();
+      gpt.hgt = 0.0; // assumed
+
+      sub_nodes.clear();
+      xpath = "FRAME_ROW";
+      (*node)->findChildNodes(xpath, sub_nodes);
+      if (sub_nodes.size() == 0)
+      {
+         setErrorStatus();
+         return false;
+      }
+      ipt.line = sub_nodes[0]->getText().toDouble() - 1.0;
+
+      sub_nodes.clear();
+      xpath = "FRAME_COL";
+      (*node)->findChildNodes(xpath, sub_nodes);
+      if (sub_nodes.size() == 0)
+      {
+         setErrorStatus();
+         return false;
+      }
+      ipt.samp = sub_nodes[0]->getText().toDouble() - 1.0;
+
+	  theFrameVertexPosImagePoints.push_back(ipt);
+      theFrameVertexPosGroundPoints.push_back(gpt);
+
+      ++node;
+   }
+
+   //---
+   // Center of frame.
+   //---
+   theRefGroundPoint.hgt = 0.0; // needs to be looked up
+
+   xml_nodes.clear();
+   xpath = "/Dimap_Document/Dataset_Frame/Scene_Center/FRAME_LON";
+   xmlDocument->findNodes(xpath, xml_nodes);
+   if (xml_nodes.size() != 1)
+   {
+      setErrorStatus();
+      return false;
+   }
+   theRefGroundPoint.lon = xml_nodes[0]->getText().toDouble();
+
+   xml_nodes.clear();
+   xpath = "/Dimap_Document/Dataset_Frame/Scene_Center/FRAME_LAT";
+   xmlDocument->findNodes(xpath, xml_nodes);
+   if (xml_nodes.size() != 1)
+   {
+      setErrorStatus();
+      return false;
+   }
+   theRefGroundPoint.lat = xml_nodes[0]->getText().toDouble();
+
+  
+   //---
+   // Fetch scene orientation:
+   //---
+   xml_nodes.clear();
+   xpath = "/Dimap_Document/Dataset_Frame/SCENE_ORIENTATION";
+   xmlDocument->findNodes(xpath, xml_nodes);
+   if (xml_nodes.size() == 0)
+   {
+      setErrorStatus();
+      if(traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG)
+            << "DEBUG:\nCould not find: " << xpath
+            << std::endl;
+      }
+      return false;
+   }
+   theSceneOrientation = xml_nodes[0]->getText().toDouble();  
+
+   return true;
+}
+
+
diff --git a/ossim_plugins/ossim/ossimFormosatDimapSupportData.h b/ossim_plugins/ossim/ossimFormosatDimapSupportData.h
new file mode 100644
index 0000000..19ff3d6
--- /dev/null
+++ b/ossim_plugins/ossim/ossimFormosatDimapSupportData.h
@@ -0,0 +1,322 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef ossimFormosatDimapSupportData_HEADER
+#define ossimFormosatDimapSupportData_HEADER 1
+
+#include <ossimPluginConstants.h>
+
+#include <ossim/base/ossimConstants.h>
+#include <ossim/base/ossimObject.h>
+#include <ossim/base/ossimRefPtr.h>
+#include <ossim/base/ossimErrorStatusInterface.h>
+#include <ossim/base/ossimString.h>
+#include <ossim/base/ossimFilename.h>
+#include <ossim/base/ossimDpt.h>
+#include <ossim/base/ossimDpt3d.h>
+#include <ossim/base/ossimDrect.h>
+#include <ossim/base/ossimGpt.h>
+#include <ossim/base/ossimEcefPoint.h>
+
+#include <vector>
+#include <iostream>
+
+class ossimKeywordlist;
+// class ossimRefPtr;
+class ossimXmlDocument;
+
+class OSSIM_PLUGINS_DLL ossimFormosatDimapSupportData :
+   public ossimObject, public ossimErrorStatusInterface
+{
+public:
+
+   /** metadata.dim format version */
+   enum ossimFormosatMetadataVersion
+   {
+      OSSIM_FORMOSAT_METADATA_VERSION_UNKNOWN = 0,
+      OSSIM_FORMOSAT_METADATA_VERSION_1_0 = 1,
+      OSSIM_FORMOSAT_METADATA_VERSION_1_1 = 2
+   };
+
+   ossimFormosatDimapSupportData();
+
+
+   ossimFormosatDimapSupportData(const ossimFormosatDimapSupportData& rhs);
+   ossimFormosatDimapSupportData(const ossimFilename& dimapFile);
+
+   virtual ossimObject* dup()const;
+
+   void clearFields();
+   bool loadXmlFile(const ossimFilename& file);
+
+   ossimString   getSensorID()                                 const;
+   ossimString   getMetadataVersionString()                    const;
+   ossimString   getAcquisitionDate()                          const;
+   ossimString   getProductionDate()                           const;
+   ossimString   getSoftwareVersion()                          const;
+   ossimString   getImageID()                                  const;
+   ossimString   getInstrument()                               const;
+   ossim_uint32  getInstrumentIndex()                          const;
+   ossimFilename getMetadataFile()                             const;
+   void          getSunAzimuth(ossim_float64& az)              const;
+   void          getSunElevation(ossim_float64& el)            const;
+   void          getSatAzimuth(ossim_float64& az)              const;
+   void          getImageSize(ossimDpt& sz)                    const;
+   void          getLineSamplingPeriod(ossim_float64& pe)      const;
+   void          getIncidenceAngle(ossim_float64& ia)          const;
+   void          getViewingAngle(ossim_float64& va)            const;
+   void          getViewingAngleAlongTrack(ossim_float64& va)  const;
+   void          getViewingAngleAcrossTrack(ossim_float64& va) const;
+   void          getSceneOrientation(ossim_float64& so)        const;
+   ossim_uint32  getNumberOfBands()                            const;
+   bool          isStarTrackerUsed()                           const;
+   bool          isSwirDataUsed()                              const;
+
+   //---
+   // Image center point:
+   //---
+
+   /** Center of frame, sub image if there is one. */
+   void getRefGroundPoint(ossimGpt& gp)         const;
+
+   /** zero base center point */
+   void getRefImagePoint(ossimDpt& rp)          const;
+
+   void getRefLineTime(ossim_float64& rt)       const;
+
+   /** relative to full frame. */
+   void getRefLineTimeLine(ossim_float64& rtl)  const;
+
+   /** Zero based image rectangle, sub image if there is one. */
+   void getImageRect(ossimDrect& rect)const;
+
+   //---
+   // Sub image offset:
+   //---
+   void getSubImageOffset(ossimDpt& offset) const;
+
+   //---
+   // Ephemeris (m & m/s):
+   //---
+   void getPositionEcf(ossim_uint32 sample, ossimEcefPoint& pe) const;
+   void getPositionEcf(const ossim_float64& time, ossimEcefPoint& pe) const;
+   void getVelocityEcf(ossim_uint32 sample, ossimEcefPoint& ve) const;
+   void getVelocityEcf(const ossim_float64& time, ossimEcefPoint& ve) const;
+   void getEphSampTime(ossim_uint32 sample, ossim_float64& et) const;
+
+   ossim_uint32 getNumEphSamples() const;
+
+   //---
+   // Attitude Angles in RADIANS:
+   //---
+   void getAttitude(ossim_uint32 sample, ossimDpt3d& at)  const;
+   void getAttitude(const ossim_float64& time, ossimDpt3d& at) const;
+   void getAttSampTime(ossim_uint32 sample, ossim_float64& at)  const;
+   ossim_uint32 getNumAttSamples() const;
+
+   //---
+   // Polynomial instrument look angle in RADIANS:
+   //---
+   void getPixelLookAngleX (ossim_uint32 sample, ossim_float64& pa) const;
+   void getPixelLookAngleX (const ossim_float64& sample,
+                        	    ossim_float64& pa) const;
+   void getPixelLookAngleY (ossim_uint32 sample, ossim_float64& pa) const;
+   void getPixelLookAngleY (const ossim_float64& sample,
+                     	       ossim_float64& pa) const;
+
+   //---
+   // Geoposition points provided in the file (most likely just corner points):
+   //---
+   ossim_uint32 getNumGeoPosPoints() const;
+   void getGeoPosPoint (ossim_uint32 point, ossimDpt& ip, ossimGpt& gp) const;
+
+   //---
+   // Corner points:
+   //---
+   void getUlCorner(ossimGpt& pt) const;
+   void getUrCorner(ossimGpt& pt) const;
+   void getLrCorner(ossimGpt& pt) const;
+   void getLlCorner(ossimGpt& pt) const;
+
+   //---
+   // Convenient method to print important image info:
+   //---
+   void  printInfo (ostream& os) const;
+
+   virtual bool saveState(ossimKeywordlist& kwl,
+                          const char* prefix = 0)const;
+   virtual bool loadState(const ossimKeywordlist& kwl,
+                          const char* prefix = 0);
+protected:
+   virtual ~ossimFormosatDimapSupportData();
+
+private:
+   void getLagrangeInterpolation(const ossim_float64& t,
+                                 const std::vector<ossimDpt3d>& V,
+                                 const std::vector<ossim_float64>& T,
+                                 ossimDpt3d& li )const;
+
+   void getBilinearInterpolation(const ossim_float64& t,
+                                 const std::vector<ossimDpt3d>& V,
+                                 const std::vector<ossim_float64>& T,
+                                 ossimDpt3d& li )const;
+
+   void getInterpolatedLookAngle(const ossim_float64& p,
+                                 const std::vector<ossim_float64>& angles,
+                                 ossim_float64& la) const;
+
+   ossim_float64 convertTimeStamp(const ossimString& time_stamp) const;
+
+   void convertTimeStamp(const ossimString& time_stamp,
+                         ossim_float64& ti) const;
+
+   /**
+    * Initializes theMetadataVersion.
+    * @return true on success, false if not found.
+    */
+   bool initMetadataVersion(ossimRefPtr<ossimXmlDocument> xmlDocument);
+
+   /**
+    * Initializes theImageId.
+    * @return true on success, false if not found.
+    */
+   bool initImageId(ossimRefPtr<ossimXmlDocument> xmlDocument);
+
+   /**
+    * From xml section:
+    * /Dimap_Document/Dataset_Sources/Source_Information/Scene_Source
+    *
+    * Initializes:
+    * theSunAzimuth
+    * theSunElevation
+    * theSatAzimuth;
+    * theIncidenceAngle
+    * @return true on success, false if not found.
+    */
+   bool initSceneSource(ossimRefPtr<ossimXmlDocument> xmlDocument);
+
+   /**
+    * Frame points:
+    *
+    * From xml section:
+    * /Dimap_Document/Dataset_Frame/
+    *
+    * Initializes:
+    * theRefGroundPoint
+    * theViewingAngle
+    * theViewingAngleAlongTrack
+    * theViewingAngleAcrossTrack
+    *
+    * Note that the theRefImagePoint will be the zero based center of the
+    * frame.
+    * @return true on success, false if not found.
+    */
+   bool initFramePoints(ossimRefPtr<ossimXmlDocument> xmlDocument);
+
+   ossimString                 theSensorID;
+   ossimFormosatMetadataVersion    theMetadataVersion;
+   ossimString                 theImageID;
+   ossimFilename               theMetadataFile;
+   ossimString                 theProductionDate;
+   ossimString                 theSoftwareVersion;
+   ossimString                 theInstrument;
+   ossim_uint32                theInstrumentIndex;
+
+   /*
+    * From xml section:
+    * /Dimap_Document/Dataset_Sources/Source_Information/
+    * Scene_Source
+    */
+   ossim_float64               theSunAzimuth;
+   ossim_float64               theSunElevation;
+   ossim_float64               theSatAzimuth;
+   ossim_float64               theIncidenceAngle;
+   ossim_float64               theViewingAngle;
+   ossim_float64               theViewingAngleAlongTrack;
+   ossim_float64               theViewingAngleAcrossTrack;
+   ossim_float64               theSceneOrientation;   
+   
+   ossimDpt                    theImageSize;
+
+   /** Center of frame on ground, if sub image it's the center of that. */
+   ossimGpt                    theRefGroundPoint;
+
+   /** Zero based center of frame. */
+   ossimDpt                    theRefImagePoint;
+
+   ossimDpt                    theSubImageOffset;
+
+   /** relative to full image */
+   ossim_float64               theRefLineTime;
+
+   /** relative to full image */
+   ossim_float64               theRefLineTimeLine;
+
+   ossim_float64               theLineSamplingPeriod;
+
+   /** holds the size of thePixelLookAngleX/Y */
+   std::vector<ossim_float64>  thePolynomialLookAngleX;
+   std::vector<ossim_float64>  thePolynomialLookAngleY;
+   std::vector<ossimDpt3d>     theAttitudeSamples; // x=pitch, y=roll, z=yaw
+   std::vector<ossim_float64>  theAttSampTimes;
+   std::vector<ossimDpt3d>     thePosEcfSamples;
+   std::vector<ossimDpt3d>     theVelEcfSamples;
+   std::vector<ossim_float64>  theEphSampTimes;
+   bool                        theStarTrackerUsed;
+   ossim_uint32                theNumBands;
+   ossimString                 theAcquisitionDate;
+   
+
+   //---
+   // Corner points:
+   //---
+   //ossimGpt theUlCorner;
+   //ossimGpt theUrCorner;
+   //ossimGpt theLrCorner;
+   //ossimGpt theLlCorner;
+   std::vector <ossimDpt> theFrameVertexPosImagePoints;
+   std::vector <ossimGpt> theFrameVertexPosGroundPoints;
+
+
+   //---
+   // Geoposition Points:
+   //---
+   std::vector <ossimDpt> theGeoPosImagePoints;
+   std::vector <ossimGpt> theGeoPosGroundPoints;
+
+   ossimGpt createGround(const ossimString& s)const;
+   ossimDpt createDpt(const ossimString& s)const;
+
+   /** callibration information for radiometric corrections*/
+
+   std::vector<ossim_float64> thePhysicalBias;
+   std::vector<ossim_float64> thePhysicalGain;
+
+   std::vector<ossim_float64> theSolarIrradiance;
+
+   /**
+    * Private parse methods called by loadXml.
+    *
+    * These "parse" methods were made simply to split the loadXmlMethod
+    * into pieces.  This was an attempt to troubleshoot what was thought to
+    * be a compiler issue, which turned out to be changed metadata and bad
+    * error handling within this code.  Since there were lots of debug
+    * statements added I am committing this to cvs.
+    * DRB 16 Oct. 2005
+    */
+   bool parsePart1(ossimRefPtr<ossimXmlDocument> xmlDocument);
+   bool parsePart2(ossimRefPtr<ossimXmlDocument> xmlDocument);
+   bool parsePart3(ossimRefPtr<ossimXmlDocument> xmlDocument);
+   bool parsePart4(ossimRefPtr<ossimXmlDocument> xmlDocument);
+};
+
+#endif /* #ifndef ossimFormosatDimapSupportData_HEADER */
+
diff --git a/ossim_plugins/ossim/ossimFormosatModel.cpp b/ossim_plugins/ossim/ossimFormosatModel.cpp
new file mode 100644
index 0000000..53f01c5
--- /dev/null
+++ b/ossim_plugins/ossim/ossimFormosatModel.cpp
@@ -0,0 +1,798 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+
+#include <iostream>
+#include <iomanip>
+#include <fstream>
+using namespace std;
+
+#include <ossimFormosatModel.h>
+#include <ossim/base/ossimKeywordNames.h>
+#include <ossim/base/ossimKeywordlist.h>
+#include <ossim/projection/ossimMapProjection.h>
+#include <ossim/base/ossimLsrPoint.h>
+#include <ossim/base/ossimEcefRay.h>
+#include <ossim/base/ossimLsrRay.h>
+#include <ossim/base/ossimLsrSpace.h>
+#include <ossim/base/ossimDpt3d.h>
+#include <ossim/base/ossimColumnVector3d.h>
+#include <ossim/base/ossimNotifyContext.h>
+
+#include <ossimFormosatDimapSupportData.h>
+
+namespace ossimplugins
+{
+RTTI_DEF1(ossimFormosatModel, "ossimFormosatModel", ossimSensorModel);
+}
+
+//---
+// Define Trace flags for use within this file:
+//---
+#include <ossim/base/ossimTrace.h>
+static ossimTrace traceExec  ("ossimFormosatModel:exec");
+static ossimTrace traceDebug ("ossimFormosatModel:debug");
+
+static const ossim_int32 MODEL_VERSION_NUMBER = 1;
+
+static const char* PARAM_NAMES[] = { "roll_offset",
+                                     "pitch_offset",
+                                     "yaw_offset",
+                                     "roll_rate",
+                                     "pitch_rate",
+                                     "yaw_rate",
+                                     "focal_length_offset" };
+
+static const char* PARAM_UNITS[] = { "degrees",   // degrees
+                                     "degrees",   // degrees
+                                     "degrees",   // degrees
+                                     "degrees",   // degrees/sec
+                                     "degrees",   // degrees/sec
+                                     "degrees",   // degrees/sec
+                                     "unknown" }; // percent deviation from nominal
+
+static const ossim_float64 SIGMA[] = { 0.0001,   // degrees
+                                       0.0001,   // degrees
+                                       0.0003,   // degrees
+                                       0.00002,  // delta degrees
+                                       0.00002,  // delta degrees
+                                       0.00005,  // delta degrees
+                                       0.0001 }; // percent
+
+ossimplugins::ossimFormosatModel::ossimFormosatModel()
+   :
+   ossimSensorModel      (),
+   theSupportData        (NULL),
+   theMetaDataFile       ("NOT ASSIGNED"),
+   theIllumAzimuth       (0.0),
+   theIllumElevation     (0.0),
+   theSatAzimuth         (0.0),
+   thePositionError      (0.0),
+   theRefImagingTime     (0.0),
+   theRefImagingTimeLine (0.0),
+   theLineSamplingPeriod (0.0),
+//   theSatToOrbRotation   (3, 3),
+//   theOrbToEcfRotation   (3, 3),
+   theRollOffset         (0.0),
+   thePitchOffset        (0.0),
+   theYawOffset          (0.0),
+   theRollRate           (0.0),
+   thePitchRate          (0.0),
+   theYawRate            (0.0),
+   theFocalLenOffset     (0.0)
+{
+   initAdjustableParameters();
+}
+
+ossimplugins::ossimFormosatModel::ossimFormosatModel(ossimFormosatDimapSupportData* sd)
+   :
+   ossimSensorModel      (),
+   theSupportData        (sd),
+   theMetaDataFile       ("NOT ASSIGNED"),
+   theIllumAzimuth       (0.0),
+   theIllumElevation     (0.0),
+   theSatAzimuth         (0.0),
+   thePositionError      (0.0),
+   theRefImagingTime     (0.0),
+   theRefImagingTimeLine (0.0),
+   theLineSamplingPeriod (0.0),
+//   theSatToOrbRotation   (3, 3),
+//   theOrbToEcfRotation   (3, 3),
+   theRollOffset         (0.0),
+   thePitchOffset        (0.0),
+   theYawOffset          (0.0),
+   theRollRate           (0.0),
+   thePitchRate          (0.0),
+   theYawRate            (0.0),
+   theFocalLenOffset     (0.0)
+{
+   if (traceExec())  ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimFormosatModel(dimap_file) Constructor: entering..." << std::endl;
+
+   //---
+   // Instantiate the support data classes after establishing the filenames:
+   //---
+   loadSupportData();
+   
+   if (getErrorStatus() != ossimErrorCodes::OSSIM_OK)
+   {
+      if (traceExec())  ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimFormosatModel(dimap_file) Constructor: returning with error..." << std::endl;
+      return;
+   }
+
+   //---
+   // initialize remaining data members:
+   //---
+   initAdjustableParameters();
+   updateModel();
+
+   if (traceExec())  ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimFormosatModel(dimap_file) Constructor: returning..." << std::endl;
+}
+
+//*****************************************************************************
+//  DESTRUCTOR: ~ossimFormosatModel()
+//
+//*****************************************************************************
+ossimplugins::ossimFormosatModel::~ossimFormosatModel()
+{
+   if (traceExec())  ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG DESTRUCTOR: ~ossimFormosatModel(): entering..." << std::endl;
+
+   theSupportData = 0;
+   
+   if (traceExec())  ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG DESTRUCTOR: ~ossimFormosatModel(): returning..." << std::endl;
+}
+
+ossimplugins::ossimFormosatModel::ossimFormosatModel(const ossimFormosatModel& rhs)
+   :ossimSensorModel(rhs)
+{
+   if(rhs.theSupportData.valid())
+   {
+      theSupportData = (ossimFormosatDimapSupportData*)rhs.theSupportData->dup();
+   }
+   loadSupportData();
+   updateModel();
+}
+
+
+void ossimplugins::ossimFormosatModel::computeSatToOrbRotation(NEWMAT::Matrix& result, ossim_float64 t)const
+{
+   if (traceExec())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+      << "DEBUG ossimFormosatModel::computeSatToOrbRotation(): entering..."
+      << std::endl;
+   }
+   //---
+   // Linearly interpolate attitudes angles:
+   //---
+   ossimDpt3d att;
+   theSupportData->getAttitude(t, att);
+
+   //---
+   // Apply the attitude adjustable parameters:
+   //---
+   double dt = theRefImagingTime - t;
+   att.x     += thePitchOffset + dt*thePitchRate;
+   att.y     += theRollOffset  + dt*theRollRate;
+   att.z     += theYawOffset   + dt*theYawRate;
+
+   //---
+   // Compute trig functions to populate rotation matrices: ANGLES IN RADIANS
+   //---
+   double cp = cos(att.x);
+   double sp = sin(att.x);
+   double cr = cos(att.y);
+   double sr = sin(att.y);
+   double cy = cos(att.z);
+   double sy = sin(att.z);
+
+   //---
+   // Populate rotation matrix:
+   //---
+   result = NEWMAT::Matrix(3,3);
+   result << (cr*cy) << (-cr*sy) << (-sr)
+   << (cp*sy+sp*sr*cy) << (cp*cy-sp*sr*sy) << (sp*cr)
+   << (-sp*sy+cp*sr*cy) << (-sp*cy-cp*sr*sy) <<  cp*cr;
+
+
+   if (traceExec())  ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimFormosatModel::computeSatToOrbRotation(): returning..." << std::endl;
+}
+
+#if 0
+//*****************************************************************************
+//  METHOD
+//*****************************************************************************
+void ossimplugins::ossimFormosatModel::computeSatToOrbRotation(ossim_float64 t)const
+{
+   if (traceExec())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "DEBUG ossimFormosatModel::computeSatToOrbRotation(): entering..."
+         << std::endl;
+   }
+
+   //---
+   // Linearly interpolate attitudes angles:
+   //---
+   ossimDpt3d att;
+   theSupportData->getAttitude(t, att);
+
+   //---
+   // Apply the attitude adjustable parameters:
+   //---
+   double dt = theRefImagingTime - t;
+   att.x     += thePitchOffset + dt*thePitchRate;
+   att.y     += theRollOffset  + dt*theRollRate;
+   att.z     += theYawOffset   + dt*theYawRate;
+
+   //---
+   // Compute trig functions to populate rotation matrices: ANGLES IN RADIANS
+   //---
+    double cp = cos(att.x);
+    double sp = sin(att.x);
+    double cr = cos(att.y);
+    double sr = sin(att.y);
+    double cy = cos(att.z);
+    double sy = sin(att.z);
+
+   //---
+   // Populate rotation matrix:
+   //---
+    theSatToOrbRotation = NEWMAT::Matrix(3,3);
+    theSatToOrbRotation << (cr*cy) << (-cr*sy) << (-sr)
+                        << (cp*sy+sp*sr*cy) << (cp*cy-sp*sr*sy) << (sp*cr)
+                        << (-sp*sy+cp*sr*cy) << (-sp*cy-cp*sr*sy) <<  cp*cr;
+
+
+    if (traceExec())  ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimFormosatModel::computeSatToOrbRotation(): returning..." << std::endl;
+}
+#endif
+//*****************************************************************************
+// PUBLIC METHOD: ossimFormosatModel::updateModel()
+//
+//  Updates the model parameters given the normalized adjustable parameter
+//  array.
+//
+//*****************************************************************************
+void ossimplugins::ossimFormosatModel::updateModel()
+{
+   clearErrorStatus();
+
+   try
+   {
+      if (traceExec())  ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimFormosatModel::updateModel(): entering..." << std::endl;
+
+      if(getNumberOfAdjustableParameters() < 1)
+      {
+         theRollOffset     = 0;
+         thePitchOffset    = 0;
+         theYawOffset      = 0;
+         theRollRate       = 0;
+         thePitchRate      = 0;
+         theYawRate        = 0;
+         theFocalLenOffset = 0;
+      }
+      else
+      {
+         theRollOffset     = computeParameterOffset(0);
+         thePitchOffset    = computeParameterOffset(1);
+         theYawOffset      = computeParameterOffset(2);
+         theRollRate       = computeParameterOffset(3);
+         thePitchRate      = computeParameterOffset(4);
+         theYawRate        = computeParameterOffset(5);
+         theFocalLenOffset = computeParameterOffset(6);
+      }
+      theSeedFunction = 0;
+      ossimGpt ulg, urg, lrg, llg;
+      lineSampleToWorld(theImageClipRect.ul(), ulg);
+      lineSampleToWorld(theImageClipRect.ur(), urg);
+      lineSampleToWorld(theImageClipRect.lr(), lrg);
+      lineSampleToWorld(theImageClipRect.ll(), llg);
+      theSeedFunction = new ossimBilinearProjection(theImageClipRect.ul(),
+                                                    theImageClipRect.ur(),
+                                                    theImageClipRect.lr(),
+                                                    theImageClipRect.ll(),
+                                                    ulg,
+                                                    urg,
+                                                    lrg,
+                                                    llg);
+
+      if (traceExec())  ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimFormosatModel::updateModel(): returning..." << std::endl;
+   }
+   catch(...)
+   {
+      setErrorStatus(ossimErrorCodes::OSSIM_ERROR);
+   }
+}
+
+void ossimplugins::ossimFormosatModel::initAdjustableParameters()
+{
+   if (traceExec())  ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimFormosatModel::initAdjustableParameters(): entering..." << std::endl;
+
+   //---
+   // Allocate storage for adjustables and assign their names and units
+   // strings.
+   //---
+   resizeAdjustableParameterArray(7);
+   ossim_uint32 numParams = getNumberOfAdjustableParameters();
+
+   //---
+   // Initialize base-class adjustable parameter array:
+   //---
+   for (ossim_uint32 i=0; i<numParams; ++i)
+   {
+      setAdjustableParameter(i, 0.0);
+      setParameterDescription(i, PARAM_NAMES[i]);
+      setParameterUnit(i,PARAM_UNITS[i]);
+      setParameterSigma(i, SIGMA[i]);
+   }
+
+   if (traceExec())  ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimFormosatModel::initAdjustableParameters(): returning..." << std::endl;
+}
+
+void ossimplugins::ossimFormosatModel::loadSupportData()
+{
+   if (traceExec())  ossimNotify(ossimNotifyLevel_DEBUG) << "ossimFormosatModel::loadSupportData(): entering..." << std::endl;
+
+   //---
+   // Check for good support data:
+   //---
+   if (!theSupportData)
+   {
+      setErrorStatus();
+      ossimNotify(ossimNotifyLevel_FATAL) << "FATAL ossimFormosatModel::loadSupportData(): Null FormosatDimapSupportData pointer passed to"
+                                          << " constructor! Aborting..." << std::endl;
+      if (traceExec())  ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimFormosatModel::loadSupportData(): returning..." << std::endl;
+      return;
+   }
+
+   if (traceExec())
+     {
+   ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimFormosatModel::loadSupportData(): theSupportData->getErrorStatus(): " 
+                << theSupportData->getErrorStatus() <<std::endl;
+     }
+
+   if (theSupportData->getErrorStatus() != ossimErrorCodes::OSSIM_OK)
+   {
+      setErrorStatus();
+      ossimNotify(ossimNotifyLevel_FATAL) << "FATAL ossimFormosatModel::loadSupportData(): Bad FormosatDimapSupportData detected. Aborting..."
+                                          << std::endl;
+      if (traceExec()) ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimFormosatModel::loadSupportData(): returning..." << std::endl;
+      return;
+   }
+
+   //---
+   // Initialize some member variables from the support data:
+   //---
+   theSensorID     = theSupportData->getSensorID();
+   theImageID      = theSupportData->getImageID();
+   theMetaDataFile = theSupportData->getMetadataFile();
+
+   // Center of frame, sub image if we have one.
+   theSupportData->getRefGroundPoint(theRefGndPt);
+
+   theSupportData->getSunAzimuth(theIllumAzimuth);
+   theSupportData->getSunElevation(theIllumElevation);
+   theSupportData->getSatAzimuth(theSatAzimuth);
+
+   ossimDpt sz;
+   theSupportData->getImageSize(sz);
+   theImageSize = sz;
+   theSupportData->getRefLineTime(theRefImagingTime);
+   theSupportData->getRefLineTimeLine(theRefImagingTimeLine);
+
+   theSupportData->getLineSamplingPeriod(theLineSamplingPeriod);
+   theSupportData->getSubImageOffset(theSpotSubImageOffset);
+
+   //---
+   // We make this zero base as the base ossimSensorModel does not know about
+   // any sub image we have.
+   //---
+   theSupportData->getImageRect(theImageClipRect);
+   theSupportData->getRefImagePoint(theRefImgPt);
+
+   ossimGpt p1;
+   ossimGpt p2;
+   ossimGpt p3;
+   ossimGpt p4;
+
+
+   // I need to find the nominal scale of the spot 5 dataset
+
+   //---
+   // Position error is a function of whether star tracker information was
+   // available:
+   //---
+   if (theSupportData->isStarTrackerUsed())
+   {
+      thePositionError = 50.0;
+   }
+   else
+   {
+      thePositionError = 200.0; // meters
+   }
+   updateModel();
+   lineSampleToWorld(theImageClipRect.ul(), p1);
+   lineSampleToWorld(theImageClipRect.ur(), p2);
+   lineSampleToWorld(theImageClipRect.lr(), p3);
+   lineSampleToWorld(theImageClipRect.ll(), p4);
+
+   ossimDpt v[4]; // temporarily holds vertices for ground polygon
+   v[0] = p1;
+   v[1] = p2;
+   v[2] = p3;
+   v[3] = p4;
+   theBoundGndPolygon = ossimPolygon(4, v);
+
+
+   ossimGpt cgpt, hgpt, vgpt;
+   // ossimEcefPoint hVector, vVector;
+   ossimDpt midpt = theImageClipRect.midPoint();
+
+   lineSampleToWorld(midpt, cgpt);
+   lineSampleToWorld(midpt + ossimDpt(1,0), hgpt);
+   lineSampleToWorld(midpt + ossimDpt(0,1), vgpt);
+
+   theGSD     = ossimDpt((ossimEcefPoint(cgpt) - ossimEcefPoint(hgpt)).magnitude(),
+			 (ossimEcefPoint(cgpt) - ossimEcefPoint(vgpt)).magnitude());
+
+   theMeanGSD = (theGSD.x+theGSD.y)/2.0;
+
+   if (traceExec())  ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimFormosatModel::loadSupportData(): returning..." << std::endl;
+}
+
+ossimObject* ossimplugins::ossimFormosatModel::dup() const
+{
+   return new ossimFormosatModel(*this);
+}
+
+std::ostream& ossimplugins::ossimFormosatModel::print(std::ostream& out) const
+{
+   // Capture stream flags since we are going to mess with them.
+   std::ios_base::fmtflags f = out.flags();
+
+   out << "\nDump of ossimFormosatModel at address " << (hex) << this
+       << (dec)
+       << "\n------------------------------------------------"
+       << "\n  theImageID            = " << theImageID
+       << "\n  theMetadataFile       = " << theMetaDataFile
+       << "\n  theIllumAzimuth       = " << theIllumAzimuth
+       << "\n  theIllumElevation     = " << theIllumElevation
+       << "\n  theSatAzimuth         = " << theSatAzimuth
+       << "\n  thePositionError      = " << thePositionError
+       << "\n  theImageSize          = " << theImageSize
+       << "\n  theRefGndPt           = " << theRefGndPt
+       << "\n  theRefImgPt           = " << theRefImgPt
+       << "\n  theRefImagingTime     = " << theRefImagingTime
+       << "\n  theRefImagingTimeLine = " << theRefImagingTimeLine
+       << "\n  theLineSamplingPeriod = " << theLineSamplingPeriod
+       << "\n  theRollOffset         = " << theRollOffset
+       << "\n  thePitchOffset        = " << thePitchOffset
+       << "\n  theYawOffset          = " << theYawOffset
+       << "\n  theRollRate           = " << theRollRate
+       << "\n  thePitchRate          = " << thePitchRate
+       << "\n  theYawRate            = " << theYawRate
+       << "\n  theFocalLenOffset     = " << theFocalLenOffset
+       << "\n------------------------------------------------"
+       << "\n  " << endl;
+
+   // Set the flags back.
+   out.flags(f);
+
+   return ossimSensorModel::print(out);
+}
+
+bool ossimplugins::ossimFormosatModel::saveState(ossimKeywordlist& kwl,
+                          const char* prefix) const
+{
+  if(theSupportData.valid())
+  {
+     ossimString supportPrefix = ossimString(prefix) + "support_data.";
+     theSupportData->saveState(kwl, supportPrefix);
+  }
+  else
+  {
+     return false;
+  }
+
+   return ossimSensorModel::saveState(kwl, prefix);
+}
+
+bool ossimplugins::ossimFormosatModel::loadState(const ossimKeywordlist& kwl,
+                                const char* prefix)
+{
+   ossimString supportPrefix = ossimString(prefix) + "support_data.";
+
+   if(!theSupportData)
+   {
+      theSupportData = new ossimFormosatDimapSupportData;
+   }
+
+   if(theSupportData->loadState(kwl, supportPrefix))
+   {
+      if(!ossimSensorModel::loadState(kwl, prefix))
+      {
+         return false;
+      }
+   }
+   else
+   {
+      return false;
+   }
+
+   loadSupportData();
+   updateModel();
+
+   return (getErrorStatus()==ossimErrorCodes::OSSIM_OK);
+}
+
+void ossimplugins::ossimFormosatModel::imagingRay(const ossimDpt& image_point,
+                                 ossimEcefRay&   image_ray) const
+{
+   bool runtime_dbflag = 0;
+   NEWMAT::Matrix satToOrbit;
+   ossimDpt iPt = image_point;
+   iPt.samp += theSpotSubImageOffset.samp;
+   iPt.line += theSpotSubImageOffset.line;
+
+   //
+   // 1. Establish time of line imaging:
+   //
+   double t_line = theRefImagingTime +
+                   theLineSamplingPeriod*(iPt.line - theRefImagingTimeLine);
+   if (traceDebug() || runtime_dbflag)
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG FormosatModel::imagingRay():------------ BEGIN DEBUG PASS ---------------" << std::endl;
+      ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG FormosatModel::imagingRay(): t_line = " << t_line << std::endl;
+   }
+
+   //
+   // 2. Interpolate ephemeris position and velocity (in ECF):
+   //
+   ossimEcefPoint  tempEcefPoint;
+   ossimEcefPoint  P_ecf;
+   theSupportData->getPositionEcf(t_line, P_ecf);
+   theSupportData->getVelocityEcf(t_line, tempEcefPoint);
+   ossimEcefVector V_ecf(tempEcefPoint.x(),
+                         tempEcefPoint.y(),
+                         tempEcefPoint.z());
+   if (traceDebug() || runtime_dbflag)
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "DEBUG:\n\tP_ecf = " << P_ecf
+         << "\n\t V_ecf = " << V_ecf << std::endl;
+   }
+
+   //
+   // 3. Establish the look direction in Vehicle LSR space (S_sat).
+   //    ANGLES IN RADIANS
+   //
+    ossim_float64 Psi_x;
+    theSupportData->getPixelLookAngleX(iPt.samp, Psi_x);
+    ossim_float64 Psi_y;
+    theSupportData->getPixelLookAngleY(iPt.samp, Psi_y);
+    if (traceDebug() || runtime_dbflag)
+    {
+       ossimNotify(ossimNotifyLevel_DEBUG)
+          << "DEBUG:\n\t Psi_x = " << Psi_x
+          << "\n\t Psi_y = " << Psi_y << endl;
+    }
+
+    ossimColumnVector3d u_sat (-tan(Psi_y), tan(Psi_x), -(1.0 + theFocalLenOffset));
+    if (traceDebug() || runtime_dbflag)
+    {
+       ossimNotify(ossimNotifyLevel_DEBUG)
+          << "DEBUG \n\t u_sat = " << u_sat << endl;
+    }
+
+   //
+   // 4. Transform vehicle LSR space look direction vector to orbital LSR space
+   //    (S_orb):
+   //
+    computeSatToOrbRotation(satToOrbit, t_line);
+
+    ossimColumnVector3d u_orb = (satToOrbit*u_sat).unit();
+    if (traceDebug() || runtime_dbflag)
+    {
+       ossimNotify(ossimNotifyLevel_DEBUG)
+          << "DEBUG:\n\t theSatToOrbRotation = " << satToOrbit
+          << "\n\t u_orb = " << u_orb << endl;
+    }
+
+   //
+   // 5. Transform orbital LSR space look direction vector to ECF.
+   //
+   //   a. S_orb space Z-axis (Z_orb) is || to the ECF radial vector (P_ecf),
+   //   b. X_orb axis is computed as cross-product between velocity and radial,
+   //   c. Y_orb completes the orthogonal S_orb coordinate system.
+   //
+    ossimColumnVector3d Z_orb (P_ecf.x(),
+                               P_ecf.y(),
+                               P_ecf.z());
+    Z_orb = Z_orb.unit();
+
+    ossimColumnVector3d X_orb = ossimColumnVector3d(V_ecf.x(),
+                                                    V_ecf.y(),
+                                                    V_ecf.z()).cross(Z_orb).unit();
+    ossimColumnVector3d Y_orb = Z_orb.cross(X_orb);
+
+    NEWMAT::Matrix orbToEcfRotation = NEWMAT::Matrix(3, 3);
+    orbToEcfRotation << X_orb[0] << Y_orb[0] << Z_orb[0]
+                        << X_orb[1] << Y_orb[1] << Z_orb[1]
+                        << X_orb[2] << Y_orb[2] << Z_orb[2];
+
+
+   ossimColumnVector3d u_ecf  = (orbToEcfRotation*u_orb);
+    if (traceDebug() || runtime_dbflag)
+    {
+       ossimNotify(ossimNotifyLevel_DEBUG)
+          << "DEBUG:\n\t orbToEcfRotation = " << orbToEcfRotation
+          << "\n\t u_ecf = " << u_ecf << endl;
+    }
+
+   //
+   // Establish the imaging ray given direction and origin:
+   //
+    image_ray = ossimEcefRay(P_ecf, ossimEcefVector(u_ecf[0], u_ecf[1], u_ecf[2]));
+
+    if (traceExec())
+    {
+       ossimNotify(ossimNotifyLevel_DEBUG)
+          << "DEBUG FormosatModel::imagingRay(): returning..." << std::endl;
+    }
+}
+
+void ossimplugins::ossimFormosatModel::lineSampleHeightToWorld(const ossimDpt& image_point,
+                                              const ossim_float64& heightEllipsoid,
+                                              ossimGpt& worldPoint) const
+{
+   if (!insideImage(image_point))
+   {
+      if(theSeedFunction.valid())
+      {
+         theSeedFunction->lineSampleToWorld(image_point, worldPoint);
+      }
+      else
+      {
+         worldPoint = extrapolate(image_point, heightEllipsoid);
+      }
+      if (traceExec())  ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimFormosatModel::lineSampleHeightToWorld(): returning..." << std::endl;
+      return;
+   }
+
+   //***
+   // First establish imaging ray from image point:
+   //***
+   ossimEcefRay imaging_ray;
+   imagingRay(image_point, imaging_ray);
+   ossimEcefPoint Pecf (imaging_ray.intersectAboveEarthEllipsoid(heightEllipsoid));
+   worldPoint = ossimGpt(Pecf);
+}
+
+// ossimDpt ossimplugins::ossimFormosatModel::extrapolate (const ossimGpt& gp) const
+// {
+//     ossimDpt temp;
+
+//     temp.makeNan();
+
+//     return temp;
+
+//   ossimDpt tempGpt = gp;
+//   ossimDpt dest;
+//   theGroundToImageMap.map(tempGpt, dest);
+
+//  return dest;
+
+// }
+
+// ossimGpt ossimplugins::ossimFormosatModel::extrapolate (const ossimDpt& ip,
+// 				       const double& height) const
+// {
+//   return ossimGpt(ossim::nan(), ossim::nan(), ossim::nan(), 0);
+
+//    ossimDpt dest;
+
+//    theImageToGroundMap.map(ip, dest);
+
+
+//    return ossimGpt(dest.lat, dest.lon, ossim::nan(), origin().datum());
+// }
+
+bool
+ossimplugins::ossimFormosatModel::setupOptimizer(const ossimString& init_file)
+{
+   ossimFilename FormosatTest = init_file;
+   ossimFilename geomFile = init_file;
+   geomFile = geomFile.setExtension("geom");
+   bool tryKwl = false;
+
+   if(!FormosatTest.exists())
+   {
+      FormosatTest = geomFile.path();
+      FormosatTest = FormosatTest.dirCat(ossimFilename("METADATA.DIM"));
+      if(FormosatTest.exists() == false)
+      {
+         FormosatTest = geomFile.path();
+         FormosatTest = FormosatTest.dirCat(ossimFilename("metadata.dim"));
+      }
+   }
+   if(FormosatTest.exists())
+   {
+      ossimRefPtr<ossimFormosatDimapSupportData> meta = new ossimFormosatDimapSupportData;
+      if(meta->loadXmlFile(FormosatTest))
+      {
+         initFromMetadata(meta.get());
+         if (getErrorStatus())
+         {
+            tryKwl = true;
+            meta=0;
+         }
+         else
+         {
+            return true;
+         }
+      }
+      else
+      {
+         meta=0;
+         tryKwl = true;
+      }
+   }
+   if(tryKwl)
+   {
+      ossimKeywordlist kwl;
+      if(kwl.addFile(init_file.c_str()))
+      {
+         return loadState(kwl);
+      }
+   }
+   return false;
+}
+
+bool
+ossimplugins::ossimFormosatModel::initFromMetadata(ossimFormosatDimapSupportData* sd)
+{
+   // init parms
+   theSupportData        = sd;
+   theMetaDataFile       = "NOT ASSIGNED";
+   theIllumAzimuth       = 0.0;
+   theIllumElevation     = 0.0;
+   theSatAzimuth         = 0.0;
+   thePositionError      = 0.0;
+   theRefImagingTime     = 0.0;
+   theLineSamplingPeriod = 0.0;
+//   theSatToOrbRotation   = 0.0; //matrix
+//   theOrbToEcfRotation   = 0.0; //matrix
+   theRollOffset         = 0.0;
+   thePitchOffset        = 0.0;
+   theYawOffset          = 0.0;
+   theRollRate           = 0.0;
+   thePitchRate          = 0.0;
+   theYawRate            = 0.0;
+   theFocalLenOffset     = 0.0;
+
+   //---
+   // Instantiate the support data classes after establishing the filenames:
+   //---
+   loadSupportData();
+   if (getErrorStatus() != ossimErrorCodes::OSSIM_OK)
+   {
+      if (traceExec())  ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimplugins::ossimFormosatModel::initFromMetadata(dimap_file): returning with error..." << std::endl;
+      return false;
+   }
+
+   //---
+   // initialize remaining data members:
+   //---
+   initAdjustableParameters();
+   updateModel();
+   return true;
+}
+
diff --git a/ossim_plugins/ossim/ossimFormosatModel.h b/ossim_plugins/ossim/ossimFormosatModel.h
new file mode 100644
index 0000000..92340ea
--- /dev/null
+++ b/ossim_plugins/ossim/ossimFormosatModel.h
@@ -0,0 +1,167 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+
+
+#ifndef ossimFormosatModel_HEADER
+#define ossimFormosatModel_HEADER
+
+#include <iostream>
+using namespace std;
+
+#include <ossimPluginConstants.h>
+#include <ossim/projection/ossimSensorModel.h>
+#include <ossim/base/ossimIpt.h>
+#include <ossim/base/ossimFilename.h>
+#include <ossim/base/ossimGpt.h>
+#include <ossim/base/ossimDpt.h>
+#include <ossim/base/ossimEcefRay.h>
+#include <ossim/base/ossimEcefPoint.h>
+#include <ossim/base/ossimMatrix3x3.h>
+
+class ossimFormosatDimapSupportData;
+
+namespace ossimplugins
+{
+class OSSIM_PLUGINS_DLL ossimFormosatModel : public ossimSensorModel
+{
+public:
+   /*!
+    * CONSTRUCTORS:
+    */
+   ossimFormosatModel();
+   ossimFormosatModel(ossimFormosatDimapSupportData* sd);
+   ossimFormosatModel(const ossimFilename& init_file);
+   ossimFormosatModel(const ossimKeywordlist& geom_kwl);
+   ossimFormosatModel(const ossimFormosatModel& rhs);
+
+   virtual ~ossimFormosatModel();
+
+   enum AdjustParamIndex
+   {
+      ROLL_OFFSET = 0,
+      PITCH_OFFSET,
+      YAW_OFFSET,
+      ROLL_RATE,
+      PITCH_RATE,
+      YAW_RATE,
+      FOCAL_LEN_OFFSET,
+      NUM_ADJUSTABLE_PARAMS // not an index
+   };   
+
+   /*!
+    * Returns pointer to a new instance, copy of this.
+    * Not implemented yet!  Returns NULL...
+    */
+   virtual ossimObject* dup() const;
+
+   /*!
+    * Extends base-class implementation. Dumps contents of object to ostream.
+    */
+   virtual std::ostream& print(std::ostream& out) const;
+
+   /*!
+    * Fulfills ossimObject base-class pure virtuals. Loads and saves geometry
+    * KWL files. Returns true if successful.
+    */
+   virtual bool saveState(ossimKeywordlist& kwl,
+                          const char* prefix=NULL) const;
+   
+   virtual bool loadState(const ossimKeywordlist& kwl,
+                          const char* prefix=NULL);
+
+   /*!
+    * Writes a template of geom keywords processed by loadState and saveState
+    * to output stream.
+    */
+   static void writeGeomTemplate(ostream& os);
+
+   /*!
+    * Given an image point and height, initializes worldPoint.
+    */
+   virtual void lineSampleHeightToWorld(const ossimDpt& image_point,
+                                        const ossim_float64& heightEllipsoid,
+                                        ossimGpt& worldPoint) const;
+   
+   /*!
+    * Given an image point, returns a ray originating at some arbitrarily high
+    * point (ideally at the sensor position) and pointing towards the target.
+    */
+   virtual void imagingRay(const ossimDpt& image_point,
+                           ossimEcefRay&   image_ray) const;
+
+   /*!
+    * Following a change to the adjustable parameter set, this virtual
+    * is called to permit instances to compute derived quantities after
+    * parameter change.
+    */
+   virtual void updateModel();
+
+   /*!
+    * ossimOptimizableProjection
+    */
+   inline virtual bool useForward()const {return false;} //!image to ground faster
+   virtual bool setupOptimizer(const ossimString& init_file); //!uses file path to init model
+
+   bool initFromMetadata(ossimFormosatDimapSupportData* sd);
+protected:
+
+   /*!
+    * Sets adjustables to default values.
+    */
+   void initAdjustableParameters();
+   
+   void loadGeometry(FILE*);
+   void loadSupportData();
+   //void computeSatToOrbRotation(ossim_float64 t)const;
+   void computeSatToOrbRotation(NEWMAT::Matrix& result, ossim_float64 t)const;
+
+/*    virtual ossimDpt extrapolate (const ossimGpt& gp) const; */
+/*    virtual ossimGpt extrapolate (const ossimDpt& ip, */
+/* 				 const double& height=ossim::nan()) const; */
+
+   ossimRefPtr<ossimFormosatDimapSupportData> theSupportData;
+
+   //---
+   // Image constant parameters:
+   //---
+   ossimFilename  theMetaDataFile;
+   ossim_float64  theIllumAzimuth;  
+   ossim_float64  theIllumElevation;
+   ossim_float64  theSatAzimuth;
+   ossim_float64  thePositionError;
+   ossim_float64  theRefImagingTime;
+
+   /** relative to full image */
+   ossim_float64  theRefImagingTimeLine;
+   
+   ossim_float64  theLineSamplingPeriod;
+   ossimDpt       theSpotSubImageOffset;
+//   mutable NEWMAT::Matrix theSatToOrbRotation;
+//   mutable NEWMAT::Matrix theOrbToEcfRotation;
+
+   //---
+   // Adjustable parameters:
+   //---
+   ossim_float64  theRollOffset;      // degrees
+   ossim_float64  thePitchOffset;     // degrees
+   ossim_float64  theYawOffset;       // degrees
+   ossim_float64  theRollRate;        // degrees/sec
+   ossim_float64  thePitchRate;       // degrees/sec
+   ossim_float64  theYawRate;         // degrees/sec
+   ossim_float64  theFocalLenOffset;  // percent deviation from nominal
+
+
+TYPE_DATA
+};
+}
+#endif /* #ifndef ossimFormosatModel_HEADER */
+
diff --git a/ossim_plugins/ossim/ossimGeometricSarSensorModel.cpp b/ossim_plugins/ossim/ossimGeometricSarSensorModel.cpp
new file mode 100644
index 0000000..b879d4f
--- /dev/null
+++ b/ossim_plugins/ossim/ossimGeometricSarSensorModel.cpp
@@ -0,0 +1,811 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include <ossimGeometricSarSensorModel.h>
+
+#include <otb/Ephemeris.h>
+#include <otb/PlatformPosition.h>
+#include <otb/SensorParams.h>
+#include <otb/RefPoint.h>
+#include <otb/SarSensor.h>
+#include <ossim/base/ossimTrace.h>
+#include <ossim/base/ossimPreferences.h>
+#include <ossim/projection/ossimCoarseGridModel.h>
+#include <ossim/elevation/ossimElevManager.h>
+#include <cmath>
+#include <string>
+
+namespace ossimplugins
+{
+
+
+   static const char PRODUCT_GEOREFERENCED_FLAG_KW[] = "product_georeferenced_flag";
+   static const char OPTIMIZATION_FACTOR_X_KW[] = "optimization_factor_x";
+   static const char OPTIMIZATION_FACTOR_Y_KW[] = "optimization_factor_y";
+   static const char OPTIMIZATION_BIAS_X_KW[] = "optimization_bias_x";
+   static const char OPTIMIZATION_BIAS_Y_KW[] = "optimization_bias_y";
+
+   const char* ossimGeometricSarSensorModel::CREATE_OCG_PREF_KW = "geometric_sar_sensor_model.create_ocg";
+
+   RTTI_DEF1(ossimGeometricSarSensorModel, "ossimGeometricSarSensorModel", ossimSensorModel);
+
+   static ossimTrace traceDebug("ossimGeometricSarSensorModel:debug");
+
+   ossimGeometricSarSensorModel::ossimGeometricSarSensorModel()
+      :
+      ossimSensorModel(),
+      _platformPosition(0),
+      _sensor(0),
+      _refPoint(0),
+      _sarSensor(0),
+      _isProductGeoreferenced(false),
+      _optimizationFactorX(0.0),
+      _optimizationFactorY(0.0),
+      _optimizationBiasX(0.0),
+      _optimizationBiasY(0.0)
+   {
+   }
+
+   ossimGeometricSarSensorModel::ossimGeometricSarSensorModel(
+      const ossimGeometricSarSensorModel& rhs)
+      :
+      ossimSensorModel(rhs),
+      _platformPosition(rhs._platformPosition?rhs._platformPosition->Clone():(PlatformPosition*)0),
+      _sensor(rhs._sensor?rhs._sensor->Clone():(SensorParams*)0),
+      _refPoint(rhs._refPoint?rhs._refPoint->Clone():( RefPoint *)0),
+      _isProductGeoreferenced(rhs._isProductGeoreferenced),
+      _optimizationFactorX(rhs._optimizationFactorX),
+      _optimizationFactorY(rhs._optimizationFactorY),
+      _optimizationBiasX(rhs._optimizationBiasX),
+      _optimizationBiasY(rhs._optimizationBiasY),
+      _imageFilename(rhs._imageFilename),
+      _productXmlFile(rhs._productXmlFile)
+   {
+      _sarSensor = new SarSensor(_sensor,_platformPosition);
+   }
+
+   ossimGeometricSarSensorModel::~ossimGeometricSarSensorModel()
+   {
+      if (_platformPosition != 0)
+      {
+         delete _platformPosition;
+         _platformPosition = 0;
+      }
+
+      if(_sensor != 0)
+      {
+         delete _sensor;
+         _sensor = 0;
+      }
+
+      if (_sarSensor != 0)
+      {
+         delete _sarSensor;
+         _sarSensor = 0;
+      }
+
+      if(_refPoint != 0)
+      {
+         delete _refPoint;
+         _refPoint = 0;
+      }
+   }
+
+   double ossimGeometricSarSensorModel::getSlantRange(double col) const
+   {
+      const double CLUM        = 2.99792458e+8 ;
+
+      double dist = _refPoint->get_distance()
+         + _sensor->get_col_direction() * (col - (_refPoint->get_pix_col())) * ((CLUM / 2.0) * _sensor->get_nRangeLook() / _sensor->get_sf()) ;
+
+      return  dist;
+   }
+
+   JSDDateTime ossimGeometricSarSensorModel::getTime(double line) const
+   {
+      double dt =  _sensor->get_lin_direction() * (line - _refPoint->get_pix_line()) * _sensor->get_nAzimuthLook() / _sensor->get_prf() ;
+      JSDDateTime time = _refPoint->get_ephemeris()->get_date();
+      time.set_second(time.get_second() + dt);
+      time.NormDate();
+
+      return time;
+   }
+
+   bool ossimGeometricSarSensorModel::getPlatformPositionAtLine(double line, vector<double>& position, vector<double>& speed)
+   {
+      JSDDateTime time = getTime(line);
+      return _platformPosition->getPlatformPositionAtTime(time,position,speed);
+   }
+
+   void ossimGeometricSarSensorModel::lineSampleHeightToWorld(
+      const ossimDpt& image_point,
+      const double&   heightEllipsoid,
+      ossimGpt&       worldPoint) const
+   {
+
+      if (!_sarSensor)
+      {
+         // bad design consequence, should be fixed.
+         _sarSensor = new SarSensor(_sensor, _platformPosition);
+      }
+      double lon, lat;
+      // const double CLUM        = 2.99792458e+8 ;
+   
+      // optimization
+      double col = image_point.x - (image_point.x * _optimizationFactorX + _optimizationBiasX) ;
+      double line = image_point.y - (image_point.y * _optimizationFactorY + _optimizationBiasY) ;
+
+      JSDDateTime azimuthTime = getTime(line) ;
+
+      // Slant range computation, depending on the product type
+      double slantRange;
+      if (_isProductGeoreferenced)
+      {
+         slantRange = getSlantRangeFromGeoreferenced(col) ;
+      }
+      else
+      {
+         slantRange = getSlantRange(col) ;
+      }
+   
+      int etatLoc = _sarSensor->ImageToWorld(slantRange, azimuthTime, heightEllipsoid, lon, lat);
+
+      if(traceDebug())
+      {
+         switch (etatLoc)
+         {
+            case 0:
+               ossimNotify(ossimNotifyLevel_DEBUG) << "successful call to lineSampleHeightToWorld" << std::endl;
+               break;
+            case 1:
+               ossimNotify(ossimNotifyLevel_DEBUG) << "lineSampleHeightToWorld : no real root to the equation belongs to the imaging ray" << std::endl;
+               break;
+            case 2:
+               ossimNotify(ossimNotifyLevel_DEBUG) << "lineSampleHeightToWorld : no real root to the equation" << std::endl;
+               break;
+            default :
+               ossimNotify(ossimNotifyLevel_DEBUG) << "lineSampleHeightToWorld : unknown error case" << std::endl;
+               break;
+         }
+      }
+
+      worldPoint.lat = lat;
+      worldPoint.lon = lon;
+      worldPoint.hgt = heightEllipsoid ;
+   }
+
+   void ossimGeometricSarSensorModel::clearGCPlist() {
+      _optimizationGCPsGroundCoordinates.clear();
+      _optimizationGCPsImageCoordinates.clear();
+
+      // optimization model update
+      optimizeModel(_optimizationGCPsGroundCoordinates, _optimizationGCPsImageCoordinates) ;
+   }
+
+   void ossimGeometricSarSensorModel::getGCPlist(std::list<ossimGpt> & groundCoordinates, std::list<ossimDpt> & imageCoordinates) {
+      groundCoordinates = _optimizationGCPsGroundCoordinates ;
+      imageCoordinates = _optimizationGCPsImageCoordinates ;
+   }
+
+   bool ossimGeometricSarSensorModel::optimizeModel(const std::list<ossimGpt> & groundCoordinates, const std::list<ossimDpt> & imageCoordinates)
+   {
+      if (groundCoordinates.size() != imageCoordinates.size()) return false ;
+
+      // no optimization is used during the GCP localization error computation
+      _optimizationFactorX = 0.0 ;
+      _optimizationFactorY = 0.0 ;
+      _optimizationBiasX = 0.0 ;
+      _optimizationBiasY = 0.0 ;
+
+      // appends the user input GCPs to the GCPs already present
+      _optimizationGCPsGroundCoordinates.insert(_optimizationGCPsGroundCoordinates.end(), groundCoordinates.begin(), groundCoordinates.end()) ;
+      _optimizationGCPsImageCoordinates.insert(_optimizationGCPsImageCoordinates.end(), imageCoordinates.begin(), imageCoordinates.end()) ;
+
+      // no GCP : no optimization
+      if (groundCoordinates.size() == 0) return true ;
+
+      // Inverse projection of each Ground Control Point
+      std::list<ossimGpt>::iterator itGround = _optimizationGCPsGroundCoordinates.begin() ;
+      std::list<ossimDpt> inverseLocResults ;
+      while (itGround != _optimizationGCPsGroundCoordinates.end())
+      {
+         ossimDpt itLoc ;
+         this->worldToLineSample(*itGround,itLoc);
+         inverseLocResults.push_back(itLoc) ;
+         itGround++;
+      }
+
+      // error computation
+      int nbPoints = _optimizationGCPsGroundCoordinates.size() ;
+      double xErrorMean = 0.0, yErrorMean = 0.0, xActualPow = 0.0, yActualPow = 0.0, xActualMean = 0.0, yActualMean = 0.0,
+         xErrorByActualMean = 0.0, yErrorByActualMean = 0.0 ;
+      double xLocalError, yLocalError ;
+
+      std::list<ossimDpt>::iterator itActualCoords = _optimizationGCPsImageCoordinates.begin() ;
+      std::list<ossimDpt>::iterator itEstimatedCoords = inverseLocResults.begin() ;
+      while ((itActualCoords != _optimizationGCPsImageCoordinates.end())&&(itEstimatedCoords != inverseLocResults.end())) {
+         xLocalError = itActualCoords->x - itEstimatedCoords->x ;
+         yLocalError = itActualCoords->y - itEstimatedCoords->y ;
+
+         xErrorMean += xLocalError ;
+         yErrorMean += yLocalError ;
+         xActualMean += itActualCoords->x ;
+         yActualMean += itActualCoords->y ;
+         xActualPow += itActualCoords->x * itActualCoords->x ;
+         yActualPow += itActualCoords->y * itActualCoords->y ;
+         xErrorByActualMean += xLocalError * itActualCoords->x ;
+         yErrorByActualMean += yLocalError * itActualCoords->y ;
+
+         ++itActualCoords;
+         ++itEstimatedCoords;
+      }
+
+      xErrorMean /= nbPoints ;
+      yErrorMean /= nbPoints ;
+      xActualMean /= nbPoints ;
+      yActualMean /= nbPoints ;
+      xActualPow /= nbPoints ;
+      yActualPow /= nbPoints ;
+      xErrorByActualMean /= nbPoints ;
+      yErrorByActualMean /= nbPoints ;
+
+      // linear regression
+      if (fabs(xActualPow - xActualMean*xActualMean) > FLT_EPSILON)
+         _optimizationFactorX = (xErrorByActualMean - xErrorMean * xActualMean) / (xActualPow - xActualMean*xActualMean) ;
+      if (fabs(yActualPow - yActualMean*yActualMean) > FLT_EPSILON)
+         _optimizationFactorY = (yErrorByActualMean - yErrorMean * yActualMean) / (yActualPow - yActualMean*yActualMean) ;
+      _optimizationBiasX = xErrorMean - _optimizationFactorX * xActualMean ;
+      _optimizationBiasY = yErrorMean - _optimizationFactorY * yActualMean ;
+
+      //// Comparison between the estimated image coordinates of each GCP and its actual image coordinates
+      //double lineBias = 0.0, columnBias = 0.0 ;
+      //int nbPtsUsed = 0;
+
+      //std::list<ossimDpt>::iterator itActualCoords = imageCoordinates.begin() ;
+      //std::list<ossimDpt>::iterator itEstimatedCoords = inverseLocResults.begin() ;
+      //while ((itActualCoords != imageCoordinates.end())&&(itEstimatedCoords != inverseLocResults.end())) {
+      //
+      //  columnBias += (itActualCoords->x - itEstimatedCoords->x ) ;
+      //  lineBias += (itActualCoords->y - itEstimatedCoords->y ) ;
+      //
+      //  nbPtsUsed++;
+      //  itActualCoords++;
+      //  itEstimatedCoords++;
+      //}
+
+      //// Computation of bias in line and column : mean deviations
+      //lineBias /= nbPtsUsed ;
+      //columnBias /= nbPtsUsed ;
+
+      //// Update of the model Reference Point
+      //_refPoint->set_pix_col(_refPoint->get_pix_col() - columnBias);
+      //_refPoint->set_pix_line(_refPoint->get_pix_line() - lineBias);
+
+      return true ;
+   }
+
+   bool ossimGeometricSarSensorModel::saveState(ossimKeywordlist& kwl,
+                                                const char* prefix) const
+
+   {
+      static const char MODULE[] = "ossimGeometricSarSensorModel::saveState";
+
+      bool result = false;
+
+      if (traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG)<< MODULE << " entered...\n";
+      }
+
+      if (_platformPosition && _sensor && _refPoint)
+      {
+         if ( _platformPosition->saveState(kwl, prefix) )
+         {
+            if ( _sensor->saveState(kwl, prefix) )
+            {
+               result = _refPoint->saveState(kwl, prefix);
+
+               if (result)
+               {
+                  kwl.add(prefix,
+                          PRODUCT_GEOREFERENCED_FLAG_KW,
+                          (_isProductGeoreferenced?"true":"false"));
+                  kwl.add(prefix,
+                          OPTIMIZATION_FACTOR_X_KW,
+                          _optimizationFactorX);
+                  kwl.add(prefix,
+                          OPTIMIZATION_FACTOR_Y_KW,
+                          _optimizationFactorY);
+                  kwl.add(prefix,
+                          OPTIMIZATION_BIAS_X_KW,
+                          _optimizationBiasX);
+                  kwl.add(prefix,
+                          OPTIMIZATION_BIAS_Y_KW,
+                          _optimizationBiasY);
+
+                  result = ossimSensorModel::saveState(kwl, prefix);
+               }
+            }
+         }
+      }
+
+      if (traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG)
+            << MODULE << " exit status = " << (result?"true":"false\n")
+            << std::endl;
+      }
+
+      return result;
+   }
+
+   bool ossimGeometricSarSensorModel::loadState(const ossimKeywordlist &kwl,
+                                                const char *prefix)
+   {
+      static const char MODULE[] = "ossimGeometricSarSensorModel::loadState";
+
+      if (traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " entered...\n";
+      }
+
+      bool result = true;
+
+      // Load the base class;
+      if ( ossimSensorModel::loadState(kwl, prefix) == false )
+      {
+         if (traceDebug())
+         {
+            ossimNotify(ossimNotifyLevel_WARN)
+               << MODULE
+               << "\nossimSensorModel::loadState failed!\n";
+         }
+         result = false;
+      }
+
+      // Load the platform position state.
+      if ( !_platformPosition)
+      {
+         _platformPosition = new PlatformPosition();
+      }
+      if ( _platformPosition->loadState(kwl, prefix) == false )
+      {
+         if (traceDebug())
+         {
+            ossimNotify(ossimNotifyLevel_WARN)
+               << MODULE
+               << "\n_platformPosition->loadState failed!\n";
+         }
+         result = false;
+      }
+
+      // Load the sensor position state.
+      if ( !_sensor)
+      {
+         _sensor = new SensorParams();
+      }
+      if ( _sensor->loadState(kwl, prefix) == false )
+      {
+         if (traceDebug())
+         {
+            ossimNotify(ossimNotifyLevel_WARN)
+               << MODULE
+               << "\n_sensor->loadState failed!\n";
+         }
+         result = false;
+      }
+
+      _sarSensor = new SarSensor(_sensor, _platformPosition);
+
+      // Load the ref point.
+      if ( !_refPoint)
+      {
+         _refPoint = new RefPoint();
+      }
+      if ( _refPoint->loadState(kwl, prefix) == false )
+      {
+         if (traceDebug())
+         {
+            ossimNotify(ossimNotifyLevel_WARN)
+               << MODULE
+               << "\n_refPoint->loadState failed!\n";
+         }
+         result = false;
+      }
+
+      const char* lookup = 0;
+      ossimString s;
+
+      lookup = kwl.find(prefix, PRODUCT_GEOREFERENCED_FLAG_KW);
+      if (lookup)
+      {
+         s = lookup;
+         _isProductGeoreferenced = s.toBool();
+      }
+      else
+      {
+         if (traceDebug())
+         {
+            ossimNotify(ossimNotifyLevel_WARN)
+               << MODULE
+               << "\nRequired keyword not found: "
+               << PRODUCT_GEOREFERENCED_FLAG_KW << "\n";
+         }
+         result = false;
+      }
+
+      lookup = kwl.find(prefix, OPTIMIZATION_FACTOR_X_KW);
+      if (lookup)
+      {
+         s = lookup;
+         _optimizationFactorX = s.toDouble();
+      }
+      else
+      {
+         if (traceDebug())
+         {
+            ossimNotify(ossimNotifyLevel_WARN)
+               << MODULE
+               << "\nRequired keyword not found: "
+               << OPTIMIZATION_FACTOR_X_KW << "\n";
+         }
+         result = false;
+      }
+
+      lookup = kwl.find(prefix, OPTIMIZATION_FACTOR_Y_KW);
+      if (lookup)
+      {
+         s = lookup;
+         _optimizationFactorY = s.toDouble();
+      }
+      else
+      {
+         if (traceDebug())
+         {
+            ossimNotify(ossimNotifyLevel_WARN)
+               << MODULE
+               << "\nRequired keyword not found: "
+               << OPTIMIZATION_FACTOR_Y_KW << "\n";
+         }
+         result = false;
+      }
+
+      lookup = kwl.find(prefix,OPTIMIZATION_BIAS_X_KW);
+      if (lookup)
+      {
+         s = lookup;
+         _optimizationBiasX= s.toDouble();
+      }
+      else
+      {
+         if (traceDebug())
+         {
+            ossimNotify(ossimNotifyLevel_WARN)
+               << MODULE
+               << "\nRequired keyword not found: "
+               << OPTIMIZATION_BIAS_X_KW << "\n";
+         }
+         result = false;
+      }
+
+      lookup = kwl.find(prefix,OPTIMIZATION_BIAS_Y_KW);
+      if (lookup)
+      {
+         s = lookup;
+         _optimizationBiasY = s.toDouble();
+      }
+      else
+      {
+         if (traceDebug())
+         {
+            ossimNotify(ossimNotifyLevel_WARN)
+               << MODULE
+               << "\nRequired keyword not found: "
+               << OPTIMIZATION_BIAS_X_KW << "\n";
+         }
+         result = false;
+      }
+
+      // if (result && traceDebug())
+//    if (result)
+//    {
+//       ossimNotify(ossimNotifyLevel_DEBUG)
+//          << "calling saveState to verify loadState..." << endl;
+
+//       ossimKeywordlist kwl2;
+//       saveState(kwl2, 0);
+
+//       ossimNotify(ossimNotifyLevel_DEBUG)
+//          << "saveState result after loadState:"  << kwl2 << endl;
+//    }
+
+      if (traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG)
+            << MODULE << " exit status = " << (result?"true":"false\n")
+            << std::endl;
+      }
+
+      return result;
+   }
+
+#if 0
+   if(!InitSRGR(kwl, prefix))
+   {
+      return false;
+   }
+   if(!InitPlatformPosition(kwl, prefix))
+   {
+      return false;
+   }
+   if(!InitSensorParams(kwl, prefix))
+   {
+      return false;
+   }
+   if(!InitRefPoint(kwl, prefix))
+   {
+      return false;
+   }
+   return true;
+}
+#endif
+
+std::ostream& ossimGeometricSarSensorModel::print(std::ostream& out) const
+{
+   out << setprecision(15) << setiosflags(ios::fixed)
+       << "\nossimGeometricSarSensorModel class data members:\n";
+
+   const char* prefix = 0;
+   ossimKeywordlist kwl;
+   if (_platformPosition)
+   {
+      _platformPosition->saveState(kwl, prefix);
+   }
+   if (_sensor)
+   {
+      _sensor->saveState(kwl, prefix);
+   }
+   if (_refPoint)
+   {
+      _refPoint->saveState(kwl, prefix);
+   }
+
+   kwl.add(prefix,
+           PRODUCT_GEOREFERENCED_FLAG_KW,
+           (_isProductGeoreferenced?"true":"false"));
+   kwl.add(prefix,
+           OPTIMIZATION_FACTOR_X_KW,
+           _optimizationFactorX);
+   kwl.add(prefix,
+           OPTIMIZATION_FACTOR_Y_KW,
+           _optimizationFactorY);
+   kwl.add(prefix,
+           OPTIMIZATION_BIAS_X_KW,
+           _optimizationBiasX);
+   kwl.add(prefix,
+           OPTIMIZATION_BIAS_Y_KW,
+           _optimizationBiasY);
+
+   out << kwl;
+
+   return ossimSensorModel::print(out);
+}
+
+//*************************************************************************************************
+// Creates replacement coarse grid model if user requested via ossim preferences keyword.
+// Returns true if load OK, false on error
+//*************************************************************************************************
+bool ossimGeometricSarSensorModel::createReplacementOCG()
+{
+   // Read the preferences to determine if we need to do this:
+   ossimString str (ossimPreferences::instance()->findPreference(CREATE_OCG_PREF_KW));
+   if (!str.toBool())
+      return true; // this is not an error condition
+
+   // Compute the coarse grid:
+   _replacementOcgModel = new ossimCoarseGridModel;
+   _replacementOcgModel->setInterpolationError(0.1);
+   _replacementOcgModel->setMinGridSpacing(50);
+   
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_NOTICE)<<"\nComputing coarse grid..."<<endl;
+   }
+   _replacementOcgModel->buildGrid(theImageClipRect, this, 500.00, true, false);
+
+   // Save the coarse grid to appropriate location given image filename:
+   bool status = _replacementOcgModel->saveCoarseGrid(_imageFilename); // this saves geom file as well
+
+   return status;
+}
+
+//*****************************************************************************
+//  METHOD: ossimGeometricSarSensorModel::lineSampleToWorld(image_pt, &gpt)
+//
+//  Intersects the ray associated with image_pt with the available elevation
+//  model. Returns ground point
+//
+//*****************************************************************************
+void ossimGeometricSarSensorModel::lineSampleToWorld(const ossimDpt& image_point,
+                                                     ossimGpt&       gpt) const
+{
+   bool debug = false;  // setable via interactive debugger
+   if (traceDebug() || debug)  ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimSensorModel::lineSampleToWorld:entering..." << std::endl;
+
+   if(image_point.hasNans())
+   {
+      gpt.makeNan();
+      return;
+   }
+   //***
+   // Extrapolate if image point is outside image:
+   //***
+   if (!insideImage(image_point)&&(!theExtrapolateImageFlag))
+   {
+      gpt = extrapolate(image_point);
+      return;
+   }
+
+   //***
+   // Determine imaging ray and invoke elevation source object's services to
+   // intersect ray with terrain model:
+   //***
+   //    ossimEcefRay ray;    In the case of SAR sensors, ray intersection does not have meaning anymore...
+   //    imagingRay(image_point, ray);
+   //    ossimElevManager::instance()->intersectRay(ray, gpt);
+
+   static const double LON_LAT_THRESHOLD  = .00001; // acceptable lon lat error (degrees)
+   static const int    MAX_NUM_ITERATIONS = 30;
+   static const double LON_LAT_STEP       = .00001;
+   int iters = 0;
+
+   //
+   // Utilize iterative scheme for arriving at ground point. Begin with guess
+   // at RefGndPt:
+   //
+   gpt.lond(theRefGndPt.lond());
+   gpt.latd(theRefGndPt.latd());
+   gpt.height(ossimElevManager::instance()->getHeightAboveEllipsoid(gpt));
+
+   ossimGpt gpt_dlat;
+   ossimGpt gpt_dlon;
+
+   ossimDpt ip, ip_dlat, ip_dlon;
+   double du_dlat, du_dlon, dv_dlat, dv_dlon;
+   double delta_lat, delta_lon, delta_u, delta_v;
+   double inverse_norm;
+   bool done = false;
+
+   //***
+   // Begin iterations:
+   //***
+   do
+   {
+      //***
+      // establish perturbed ground points about the guessed point:
+      //***
+      gpt_dlat.latd(gpt.latd() + LON_LAT_STEP);
+      gpt_dlat.lond(gpt.lond());
+      gpt_dlat.height(ossimElevManager::instance()->getHeightAboveEllipsoid(gpt_dlat));
+      gpt_dlon.latd(gpt.latd());
+      gpt_dlon.lond(gpt.lond() + LON_LAT_STEP);
+      gpt_dlon.height(ossimElevManager::instance()->getHeightAboveEllipsoid(gpt_dlon));
+
+      //***
+      // Compute numerical partials at current guessed point:
+      //***
+      worldToLineSample(gpt, ip);
+      worldToLineSample(gpt_dlat, ip_dlat);
+      worldToLineSample(gpt_dlon, ip_dlon);
+
+      if(ip.hasNans() || ip_dlat.hasNans() || ip_dlon.hasNans())
+      {
+         gpt.makeNan();
+         return;
+      }
+
+      du_dlat = (ip_dlat.u - ip.u) / LON_LAT_STEP;
+      du_dlon = (ip_dlon.u - ip.u) / LON_LAT_STEP;
+      dv_dlat = (ip_dlat.v - ip.v) / LON_LAT_STEP;
+      dv_dlon = (ip_dlon.v - ip.v) / LON_LAT_STEP;
+
+      //
+      // Test for convergence:
+      //
+      delta_u = image_point.u - ip.u;
+      delta_v = image_point.v - ip.v;
+
+      //
+      // Compute linearized estimate of ground point given ip delta:
+      //
+      inverse_norm = du_dlon*dv_dlat - dv_dlon*du_dlat; // fg-eh
+
+      if (!ossim::almostEqual(inverse_norm, 0.0, DBL_EPSILON))
+      {
+         delta_lon = (delta_u*dv_dlat - delta_v*du_dlat)/inverse_norm;
+         delta_lat = (delta_v*du_dlon - delta_u*dv_dlon)/inverse_norm;
+         gpt.latd(gpt.latd() + delta_lat);
+         gpt.lond(gpt.lond() + delta_lon);
+         gpt.height(ossimElevManager::instance()->getHeightAboveEllipsoid(gpt));
+      }
+      else
+      {
+         delta_lon = 0;
+         delta_lat = 0;
+      }
+      done = ((fabs(delta_lon) < LON_LAT_THRESHOLD) && (fabs(delta_lat) < LON_LAT_THRESHOLD));
+      iters++;
+   } while ((!done) && (iters < MAX_NUM_ITERATIONS));
+
+   if (traceDebug() || debug)
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG) << "image_point = " << image_point << std::endl;
+      //       ossimNotify(ossimNotifyLevel_DEBUG) << "ray = " << ray << std::endl;
+      ossimNotify(ossimNotifyLevel_DEBUG) << "gpt = " << gpt << std::endl;
+   }
+
+   if (traceDebug() || debug)  ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimSensorModel::lineSampleToWorld: returning..." << std::endl;
+   return;
+}
+
+
+void ossimGeometricSarSensorModel::set_platformPosition(PlatformPosition* platformPosition)
+{
+   if(_platformPosition != 0)
+   {
+      delete _platformPosition;
+      _platformPosition = 0;
+   }
+   _platformPosition = platformPosition->Clone();
+}
+
+void ossimGeometricSarSensorModel::set_sensorParams(SensorParams* sensorParams)
+{
+   if(_sensor != 0)
+   {
+      delete _sensor;
+      _sensor = 0;
+   }
+   _sensor = sensorParams->Clone();
+}
+
+void ossimGeometricSarSensorModel::set_refPoint(RefPoint* refPoint)
+{
+   if(_refPoint != 0)
+   {
+      delete _refPoint;
+      _refPoint = 0;
+   }
+   _refPoint = refPoint->Clone();
+}
+
+
+PlatformPosition* ossimGeometricSarSensorModel::get_platformPosition() const
+{
+   return _platformPosition;
+}
+
+
+SensorParams* ossimGeometricSarSensorModel::get_sensorParams() const
+{
+   return _sensor;
+}
+
+
+RefPoint* ossimGeometricSarSensorModel::get_refPoint() const
+{
+   return _refPoint;
+}
+
+
+
+}
+
diff --git a/ossim_plugins/ossim/ossimGeometricSarSensorModel.h b/ossim_plugins/ossim/ossimGeometricSarSensorModel.h
new file mode 100644
index 0000000..59bff33
--- /dev/null
+++ b/ossim_plugins/ossim/ossimGeometricSarSensorModel.h
@@ -0,0 +1,248 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef ossimGeometricSarSensorModel_H
+#define ossimGeometricSarSensorModel_H 1
+
+#include <ossimPluginConstants.h>
+#include <ossim/projection/ossimSensorModel.h>
+#include <ossim/projection/ossimCoarseGridModel.h>
+
+#include <list>
+#include <vector>
+
+namespace ossimplugins
+{
+
+class PlatformPosition;
+class SensorParams;
+class RefPoint;
+class SarSensor;
+class JSDDateTime;
+
+/**
+ * @brief This class allows for direct localisation and indirect localisation
+ * using the geometric model of SAR sensors.
+ * This class must be specified for each sensor.
+ */
+class OSSIM_PLUGINS_DLL ossimGeometricSarSensorModel : public ossimSensorModel
+{
+public:
+   static const char* CREATE_OCG_PREF_KW;
+
+   /** @brief default constructor */
+   ossimGeometricSarSensorModel();
+
+   /** @brief copy constructor */
+   ossimGeometricSarSensorModel(const ossimGeometricSarSensorModel& rhs);
+
+   /** @brief Destructor */
+   virtual ~ossimGeometricSarSensorModel();
+
+   /**
+    * @brief This function associates an image column number to a slant range when the image is georeferenced (ground projected)
+    * @param col Column coordinate of the image point
+    */
+   virtual double getSlantRangeFromGeoreferenced(double col) const=0;
+
+   /**
+    * @brief This function associates an image column number to a slant range
+    * @param col Column coordinate of the image point
+    */
+   virtual double getSlantRange(double col) const;
+
+   /**
+    * @brief This function associates an image line number to an azimuth time
+    * @param line Line coordinate of the image point
+    */
+   virtual JSDDateTime getTime(double line) const;
+ 
+   /**
+    * @brief This function associates an image line number to a platform position and speed
+    * @param line Line coordinate of the image point
+    * @param position Position of the sensor at line line
+    * @param speed Speed of the sensor at line line
+    */
+  virtual bool getPlatformPositionAtLine(double line, vector<double>& position, vector<double>& speed);
+
+   /**
+    * @brief This function is able to convert image coordinates into world
+    * coordinates the geometric model of SAR sensors.
+    * @param image_point Coordinates of the image point
+    * @param heightEllipsoid Altitude of the world point
+    * @param worldPoint Coordinates of the world point (OUT)
+    */
+   virtual void lineSampleHeightToWorld(const ossimDpt& image_point,
+                                        const double&   heightEllipsoid,
+                                        ossimGpt&       worldPoint) const;
+
+
+   /**
+    * @brief This function optimizes the model according to a list of Ground
+    * Control Points.
+    *
+    * The input list of GCPs is appended to the one present in memory.
+    * An inverse localization of each ground GCP is performed.
+    * The error between localized GCPs and actual image coordinates is then
+    * computed and modeled by a linear model on each dimension.
+    * The time and range estimations are updated accordingly.
+    *
+    * @param groundCoordinates : input GCP ground coordinates
+    * @param imageCoordinates : actual image coordinates corresponding to
+    * input groundCoordinates
+    *
+    */
+   virtual bool optimizeModel(const std::list<ossimGpt> & groundCoordinates,
+                              const std::list<ossimDpt> & imageCoordinates) ;
+
+   /**
+    * @brief Clears _optimizationGCPsGroundCoordinates and
+    * _optimizationGCPsImageCoordinates attributes
+    * Updates the optimisation factors and bias
+    */
+   virtual void clearGCPlist() ;
+
+   /**
+    * @brief Returns _optimizationGCPsGroundCoordinates and
+    * _optimizationGCPsImageCoordinates attributes
+    *
+    * @retval groundCoordinates : GCP ground coordinates
+    * @retval imageCoordinates : actual image coordinates corresponding to
+    * groundCoordinates
+    */
+   virtual void getGCPlist(std::list<ossimGpt> &groundCoordinates,
+                           std::list<ossimDpt> & imageCoordinates) ;
+
+
+
+   /**
+    * @brief
+    * @return true when it's better (more accurate / fast) to use forward
+    * (from ground to image) than inverse(from image to ground)
+    * @remark This function always return false
+    */
+   inline virtual bool useForward() const {return false;}
+
+   /**
+    * @brief Method to save object state to a keyword list.
+    * @param kwl Keyword list to save to.
+    * @param prefix added to keys when saved.
+    * @return true on success, false on error.
+    */
+   virtual bool saveState(ossimKeywordlist& kwl,
+                          const char* prefix=0) const;
+
+   /**
+    * @brief Method to the load (recreate) the state of the object from a
+    * keyword list. Return true if ok or false on error.
+    * @return true if load OK, false on error
+    */
+   virtual bool loadState (const ossimKeywordlist &kwl, const char *prefix=0);
+
+   /*!
+    * METHOD: print()
+    * Fulfills base-class pure virtual. Dumps contents of object to ostream.
+    */
+   virtual std::ostream& print(std::ostream& out) const;
+
+   /**
+    * @brief Accessors to the optimization parameters.
+    */
+   double get_optimizationFactorX() const { return _optimizationFactorX; }
+   double get_optimizationFactorY() const { return _optimizationFactorY; }
+   double get_optimizationBiasX()   const { return _optimizationBiasX; }
+   double get_optimizationBiasY()   const { return _optimizationBiasY; }
+
+   ossimRefPtr<ossimCoarseGridModel> getReplacementOcgModel() { return _replacementOcgModel; }
+
+   virtual void lineSampleToWorld(const ossimDpt& image_point,
+                                  ossimGpt&       gpt) const;
+
+   /**
+    * @brief Accessors to the plateform, sensor parameters and reference point.
+    */
+   void set_platformPosition(PlatformPosition* platformPosition);
+   void set_sensorParams(SensorParams* sensorParams);
+   void set_refPoint(RefPoint* refPoint);
+   PlatformPosition* get_platformPosition() const;
+   SensorParams* get_sensorParams() const;
+   RefPoint* get_refPoint()  const;
+
+protected:
+   /**
+    * @brief Creates replacement coarse grid model if user requested via ossim preferences 
+    * keyword "geometric_sar_sensor_model.create_ocg: <bool>"
+    * @return true if load OK, false on error
+    */
+   bool createReplacementOCG();
+
+   /**
+    * @brief Handle the position of the platform
+    */
+   PlatformPosition *_platformPosition;
+   SensorParams * _sensor;
+   RefPoint * _refPoint;
+   // Note that this is only mutable because of bad design of the
+   // classes, with a bunch of classes initializing the variables of
+   // the base class directly, the 3 variable above must be made
+   // private.
+   mutable SarSensor* _sarSensor;
+
+   /**
+    * @brief True iff the product is ground range
+    */
+   bool _isProductGeoreferenced ;
+
+   /**
+    * @brief List Ground Control Points used by the optimization
+    */
+   std::list<ossimGpt> _optimizationGCPsGroundCoordinates ;
+   std::list<ossimDpt> _optimizationGCPsImageCoordinates  ;
+
+   /**
+    * @brief Optimization result : linear error correction in both dimensions
+    */
+   double _optimizationFactorX ;
+   double _optimizationFactorY ;
+   double _optimizationBiasX ;
+   double _optimizationBiasY ;
+
+   ossimFilename _imageFilename;
+   ossimFilename _productXmlFile;
+
+   ossimRefPtr<ossimCoarseGridModel> _replacementOcgModel;
+
+private:
+   /**
+    * @brief Initializes the Platform Position from a projection keywordlist
+    */
+   virtual bool InitPlatformPosition(const ossimKeywordlist &kwl, const char *prefix)=0;
+   /**
+    * @brief Initializes the Sensor Params from a projection keywordlist
+    */
+   virtual bool InitSensorParams(const ossimKeywordlist &kwl, const char *prefix)=0;
+   /**
+    * @brief Initializes the Reference Point from a projection keywordlist
+    */
+   virtual bool InitRefPoint(const ossimKeywordlist &kwl, const char *prefix)=0;
+   /**
+    * @brief Initializes the Slant Range to/for each Ground Range data sets from a projection keywordlist
+    */
+   virtual bool InitSRGR(const ossimKeywordlist &kwl, const char *prefix)=0;
+
+
+TYPE_DATA
+
+};
+}
+
+#endif
+
diff --git a/ossim_plugins/ossim/ossimPleiadesDimapSupportData.cpp b/ossim_plugins/ossim/ossimPleiadesDimapSupportData.cpp
new file mode 100644
index 0000000..a4424c3
--- /dev/null
+++ b/ossim_plugins/ossim/ossimPleiadesDimapSupportData.cpp
@@ -0,0 +1,2905 @@
+//*******************************************************************
+// Copyright (C) 2012  Centre National Etudes Spatiales
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 3 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+//
+// Author : Mickael Savinaud (mickael.savinaud at c-s.fr)
+//
+// Description:
+//
+// Contains declaration of class ossimPleiadesDimapSupportData
+//
+//*****************************************************************************
+
+#include <ossimPleiadesDimapSupportData.h>
+#include <ossim/base/ossimKeywordlist.h>
+#include <ossim/base/ossimNotify.h>
+#include <ossim/base/ossimKeywordNames.h>
+#include <ossim/base/ossimTrace.h>
+
+#include <ossim/base/ossimFilename.h>
+#include <ossim/base/ossimXmlDocument.h>
+#include <ossim/base/ossimXmlAttribute.h>
+#include <ossim/base/ossimXmlNode.h>
+
+#include <ossimPluginCommon.h>
+#include <ossim/base/ossimCommon.h>
+
+#include <ossim/base/ossimDatum.h>
+#include <ossim/base/ossimNotifyContext.h>
+
+#include <cstdio>
+#include <cstdlib>
+#include <iostream>
+#include <iterator>
+#include <sstream>
+
+
+// Define Trace flags for use within this file:
+static ossimTrace traceExec  ("ossimPleiadesDimapSupportData:exec");
+static ossimTrace traceDebug ("ossimPleiadesDimapSupportData:debug");
+
+static std::string getVectorFloat64AsString(std::vector<ossim_float64> in)
+{
+   std::vector<ossim_float64>::iterator it;
+   std::stringstream strTmp;
+
+   for ( it=in.begin() ; it < in.end(); it++ )
+   {
+      strTmp << " " << (*it);
+   }
+
+   return strTmp.str();
+}
+
+static std::string getVectorDoubleAsString(std::vector<double> in)
+{
+   std::vector<double>::iterator it;
+   std::stringstream strTmp;
+
+   for ( it=in.begin() ; it < in.end(); it++ )
+   {
+      strTmp << " " << (*it);
+   }
+
+   return strTmp.str();
+}
+
+static std::string getVectorStringAsString(std::vector<ossimString> in)
+{
+   std::vector<ossimString>::iterator it;
+   std::stringstream strTmp;
+
+   for ( it=in.begin() ; it < in.end(); it++ )
+   {
+      strTmp << " " << (*it);
+   }
+
+   return strTmp.str();
+}
+
+
+
+namespace ossimplugins
+{
+
+   static bool readOneXmlNode(ossimRefPtr<ossimXmlDocument> xmlDocument,
+                              ossimString xpath,
+                              ossimString& nodeValue)
+   {
+      vector<ossimRefPtr<ossimXmlNode> > xml_nodes;
+
+      xmlDocument->findNodes(xpath, xml_nodes);
+      if (xml_nodes.size() == 0)
+      {
+         if(traceDebug())
+         {
+            ossimNotify(ossimNotifyLevel_DEBUG) << " DEBUG:"
+                                                << "\nCould not find: " << xpath << std::endl;
+         }
+         return false;
+      }
+      if (xml_nodes.size() != 1)
+      {
+         if(traceDebug())
+         {
+            ossimNotify(ossimNotifyLevel_DEBUG) << " DEBUG:"
+                                                << "\nMore than one node value with " << xpath << std::endl;
+         }
+         return false;
+      }
+      nodeValue = xml_nodes[0]->getText();
+      return true;
+   }
+
+   ossimPleiadesDimapSupportData::ossimPleiadesDimapSupportData ()
+      :ossimErrorStatusInterface(),
+       theDIMAPVersion(OSSIM_PLEIADES_UNKNOWN),
+       theMetadataSubProfile(OSSIM_PLEIADES_METADATA_SUBPROFILE_UNKNOWN),
+       theProductIsOk(false),
+       theRpcIsOk(false),
+       theXmlDocumentRoot(),
+
+       theSensorID(),
+       theImageID(),
+       theProductionDate(),
+       theAcquisitionDate(),
+       theInstrument(),
+       theInstrumentIndex(),
+       theProcessingLevelString(),
+       theSpectralProcessingString(),
+
+       theSunAzimuth(),
+       theSunElevation(),
+       theIncidenceAngle(),
+       theViewingAngle(),
+       theAzimuthAngle(),
+       theAlongTrackIncidenceAngle(),
+       theAcrossTrackIncidenceAngle(),                                          
+
+       theImageSize(0, 0),
+       theTileSize(0, 0),
+       theNumberOfMegaTilesInRow(0),
+       theNumberOfMegaTilesInCol(0),
+       theNumberOfMegaTiles(0),
+       theMultiDataFile(),
+
+       theNumBands(0),
+       theBandOrder(),
+
+       thePhysicalBias(),
+       thePhysicalGain(),
+       theSolarIrradiance(),
+
+       theUlCorner(),
+       theUrCorner(),
+       theLrCorner(),
+       theLlCorner(),
+
+       theSpecId(),
+       theErrBias(0),
+       theErrBiasX(0),
+       theErrBiasY(0),
+       theErrRand(0),
+       theLineOffset(0),
+       theSampOffset(0),
+       theLatOffset(0),
+       theLonOffset(0),
+       theHeightOffset(0),
+       theLineScale(0),
+       theSampScale(0),
+       theLatScale(0),
+       theLonScale(0),
+       theHeightScale(0),
+       theLineNumCoeff(),
+       theLineDenCoeff(),
+       theSampNumCoeff(),
+       theSampDenCoeff(),
+       
+       theTimeRangeStart(),
+       theTimeRangeEnd(),
+       theLinePeriod(0.0),
+       theSwathFirstCol(0),
+       theSwathLastCol(0),
+
+       theRefGroundPoint(0.0, 0.0, 0.0),
+       theRefImagePoint(0.0, 0.0)
+   {
+   }
+
+   ossimPleiadesDimapSupportData::~ossimPleiadesDimapSupportData ()
+   {
+   }
+
+
+   void ossimPleiadesDimapSupportData::clearFields()
+   {
+      clearErrorStatus();
+      theDIMAPVersion = OSSIM_PLEIADES_UNKNOWN;
+      theMetadataSubProfile = OSSIM_PLEIADES_METADATA_SUBPROFILE_UNKNOWN;
+      theProductIsOk = false;
+      theRpcIsOk = false;
+      theXmlDocumentRoot = "";
+      theImageID = "";
+      theSensorID="";
+      theProductionDate = "";
+      theAcquisitionDate = "";
+      theInstrument = "";
+      theInstrumentIndex = "";
+      theProcessingLevelString = "";
+      theSpectralProcessingString = "";
+
+      theSunAzimuth.clear();
+      theSunElevation.clear();
+      theIncidenceAngle.clear();
+      theViewingAngle.clear();
+      theAzimuthAngle.clear();
+
+      theAlongTrackIncidenceAngle.clear();
+      theAcrossTrackIncidenceAngle.clear();
+
+      theImageSize.makeNan();
+      theTileSize.makeNan();
+      theNumberOfMegaTilesInRow = 0;
+      theNumberOfMegaTilesInCol = 0;
+      theNumberOfMegaTiles = 0;
+      ossimString msg = "";
+      theMultiDataFile.setBooleanValue(false, msg);
+
+      theNumBands = 0;
+      theBandOrder.clear();
+
+      thePhysicalBias.clear();
+      thePhysicalGain.clear();
+      theSolarIrradiance.clear();
+
+      //---
+      // Corner points:
+      //---
+      theUlCorner.makeNan();
+      theUrCorner.makeNan();
+      theLrCorner.makeNan();
+      theLlCorner.makeNan();
+
+      theRefGroundPoint.makeNan();
+      theRefImagePoint.makeNan();
+
+      //---
+      // RPC model parameters
+      //---
+      theErrBias = 0.0;
+      theErrBiasX = 0.0;
+      theErrBiasY = 0.0;
+      theErrRand = 0.0;
+      theLineOffset = 0.0;
+      theSampOffset = 0.0;
+      theLatOffset = 0.0;
+      theLonOffset = 0.0;
+      theHeightOffset = 0.0;
+      theLineScale = 0.0;
+      theSampScale = 0.0;
+      theLatScale = 0.0;
+      theLonScale = 0.0;
+      theHeightScale = 0.0;
+      theLineNumCoeff.clear();
+      theLineDenCoeff.clear();
+      theSampNumCoeff.clear();
+      theSampDenCoeff.clear();
+      theSpecId = "";
+      
+      theTimeRangeStart = "";
+      theTimeRangeEnd = "";
+      theLinePeriod = 0.0;
+      theSwathFirstCol = 0;
+      theSwathLastCol = 0;
+   }
+
+   void ossimPleiadesDimapSupportData::printInfo(ostream& os) const
+   {
+
+      os << "\n----------------- Info on Pleiades Image -------------------"
+         << "\n  "
+         << "\n  Job Number (ID):      " << theImageID
+         << "\n  Acquisition Date:     " << theAcquisitionDate
+         << "\n  Instrument:           " << theInstrument
+         << "\n  Instrument Index:     " << theInstrumentIndex
+         << "\n  Production Date:      " << theProductionDate
+         << "\n  Processing Level:     " << theProcessingLevelString
+         << "\n  Spectral Processing:  " << theSpectralProcessingString
+
+         << "\n  Number of Bands:      " << theNumBands
+         << "\n  Bands Display Order:  " << getVectorStringAsString(theBandOrder)
+
+         << "\n  Image Size:           " << theImageSize
+         << "\n  Tile Size:            " << theTileSize
+         << "\n  Number Of Tiles (Row, Col): " << theNumberOfMegaTiles << " ("
+         << theNumberOfMegaTilesInRow << ", "
+         << theNumberOfMegaTilesInCol << ")"
+
+         << "\n  Incidence Angle (TopCenter, Center, BottomCenter):   " << getVectorFloat64AsString(theIncidenceAngle)
+         << "\n  Viewing Angle (TopCenter, Center, BottomCenter):     " << getVectorFloat64AsString(theViewingAngle)
+         << "\n  Azimuth Angle (TopCenter, Center, BottomCenter):     " << getVectorFloat64AsString(theAzimuthAngle)
+         << "\n  Along track incidence angle (TopCenter, Center, BottomCenter):     " << getVectorFloat64AsString(theAlongTrackIncidenceAngle)
+         << "\n  Across track incidence angle (TopCenter, Center, BottomCenter):     " << getVectorFloat64AsString(theAcrossTrackIncidenceAngle)
+         << "\n  Sun Azimuth (TopCenter, Center, BottomCenter):       " << getVectorFloat64AsString(theSunAzimuth)
+         << "\n  Sun Elevation (TopCenter, Center, BottomCenter):     " << getVectorFloat64AsString(theSunElevation)
+
+         << "\n  Physical Bias (for each band):     " << getVectorFloat64AsString(thePhysicalBias)
+         << "\n  Physical Gain (for each band):     " << getVectorFloat64AsString(thePhysicalGain)
+         << "\n  Solar Irradiance (for each band):  " << getVectorFloat64AsString(theSolarIrradiance)
+
+         << "\n  Geo Center Point:     " << theRefGroundPoint
+         // TODO add RefImagePoint if necessary
+
+         << "\n  Corner Points:"
+         << "\n     UL: " << theUlCorner
+         << "\n     UR: " << theUrCorner
+         << "\n     LR: " << theLrCorner
+         << "\n     LL: " << theLlCorner
+         << "\n"
+
+         << "\n  RPC model parameters:"
+         << "\n     RPC ID: " << theSpecId
+         << "\n     SampNumCoeff: " << getVectorDoubleAsString(theSampNumCoeff)
+         << "\n     SampDenCoeff: " << getVectorDoubleAsString(theSampDenCoeff)
+         << "\n     LineNumCoeff: " << getVectorDoubleAsString(theLineNumCoeff)
+         << "\n     LineDenCoeff: " << getVectorDoubleAsString(theLineDenCoeff)
+         << "\n     LonScale: " << theLonScale
+         << "\n     LonOffset: " << theLonOffset
+         << "\n     LatScale: " << theLatScale
+         << "\n     LonScale: " << theLonScale
+         << "\n     HeightScale: " << theHeightScale
+         << "\n     HeightOffset: " << theHeightOffset
+         << "\n     SampScale: " << theSampScale
+         << "\n     SampOffset: " << theSampOffset
+         << "\n     LineScale: " << theLineScale
+         << "\n     LineOffset: " << theLineOffset
+         << "\n     theErrBias: " << theErrBias
+         << "\n     theErrBiasX: " << theErrBiasX
+         << "\n     theErrBiasY: " << theErrBiasY
+         << "\n     theErrRand: " << theErrRand
+         << "\n"
+         
+         << "\n  Acquisition time parameters (only valid for SENSOR product):"
+         << "\n     TimeRangeStart: "<< theTimeRangeStart
+         << "\n     TimeRangeEnd: "<< theTimeRangeEnd
+         << "\n     LinePeriod: "<< theLinePeriod
+         << "\n     SwathFirstCol: "<< theSwathFirstCol
+         << "\n     SwathLastCol: "<< theSwathLastCol
+         << "\n"
+         << "\n---------------------------------------------------------"
+         << "\n  " << std::endl;
+   }
+
+   bool ossimPleiadesDimapSupportData::parseXmlFile(const ossimFilename& file)
+   {
+      static const char MODULE[] = "ossimPleiadesDimapSupportData::parseXmlFile";
+      //traceDebug.setTraceFlag(true);
+
+      if(traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " DEBUG:" << "\nFile: " << file << std::endl;
+      }
+
+      if (allMetadataRead())
+         clearFields();
+
+      //---
+      // Instantiate the file reading:
+      //---
+      ossim_int64 fileSize = file.fileSize();
+      std::ifstream in(file.c_str(), std::ios::binary|std::ios::in);
+      std::vector<char> fullBuffer;
+      ossimString bufferedIo;
+      if(in.good()&&(fileSize > 0))
+      {
+         char buf[100];
+         fullBuffer.resize(fileSize);
+         in.read(buf, std::min((ossim_int64)100, fileSize));
+         if(!in.fail())
+         {
+            ossimString testString = ossimString(buf,
+                                                 buf + in.gcount());
+            if(testString.contains("xml"))
+            {
+               in.seekg(0);
+               in.read(&fullBuffer.front(), (std::streamsize)fullBuffer.size());
+               if(!in.fail())
+               {
+                  bufferedIo = ossimString(fullBuffer.begin(),
+                                           fullBuffer.begin()+in.gcount());
+               }
+            }
+         }
+      }
+      else
+      {
+         return false;
+      }
+      //---
+      // Instantiate the XML parser:
+      //---
+      ossimRefPtr<ossimXmlDocument> xmlDocument;
+
+      if(bufferedIo.empty())
+      {
+         xmlDocument = new ossimXmlDocument(file);
+      }
+      else
+      {
+         xmlDocument = new ossimXmlDocument;
+         std::istringstream inStringStream(bufferedIo.string());
+         if(!xmlDocument->read(inStringStream))
+         {
+            return false;
+         }
+      }
+      if (xmlDocument->getErrorStatus())
+      {
+         if(traceDebug())
+         {
+            ossimNotify(ossimNotifyLevel_FATAL)
+               << MODULE << " DEBUG:" << "ossimPleiadesDimapSupportData::parseXmlFile:"
+               << "\nUnable to parse xml file" << std::endl;
+         }
+         setErrorStatus();
+         return false;
+      }
+
+      if (!parseMetadataIdentificationDIMAPv2(xmlDocument)
+          && !parseMetadataIdentificationDIMAPv1(xmlDocument))
+      {
+         if (traceDebug())
+         {
+            ossimNotify(ossimNotifyLevel_FATAL)
+               << MODULE << " DEBUG:" << "ossimPleiadesDimapSupportData::parseXmlFile:"
+               << "\nparseMetadataIdentification failed.  Returning false"
+               << std::endl;
+         }
+         return false;
+      }
+
+      if (theDIMAPVersion == OSSIM_PLEIADES_DIMAPv1
+          || theMetadataSubProfile == OSSIM_PLEIADES_METADATA_SUBPROFILE_PRODUCT)
+      {
+         if (theProductIsOk)
+            clearFields();
+
+         if (!parseDatasetIdentification(xmlDocument))
+         {
+            if (traceDebug())
+            {
+               ossimNotify(ossimNotifyLevel_FATAL)
+                  << MODULE << " DEBUG:" << "ossimPleiadesDimapSupportData::parseXmlFile:"
+                  << "\nparseDatasetdentification failed.  Returning false" << std::endl;
+            }
+            return false;
+         }
+
+         if (!parseDatasetContent(xmlDocument))
+         {
+            ossimNotify(ossimNotifyLevel_FATAL)
+               << MODULE << " DEBUG:" << "ossimPleiadesDimapSupportData::parseXmlFile:"
+               << "\nparseDatasetContent failed.  Returning false" << std::endl;
+            return false;
+         }
+
+         if (!parseProductInformation(xmlDocument))
+         {
+            if (traceDebug())
+            {
+               ossimNotify(ossimNotifyLevel_FATAL)
+                  << MODULE << " DEBUG:" << "ossimPleiadesDimapSupportData::parseXmlFile:"
+                  << "\nparseProductInformation failed.  Returning false" << std::endl;
+            }
+            return false;
+         }
+
+         if (!parseCoordinateReferenceSystem(xmlDocument))
+         {
+            if (traceDebug())
+            {
+               ossimNotify(ossimNotifyLevel_FATAL)
+                  << MODULE << " DEBUG:" << "ossimPleiadesDimapSupportData::parseXmlFile:"
+                  << "\nparseCoordinateReferenceSystem failed.  Returning false" << std::endl;
+            }
+            return false;
+         }
+
+         if (!parseGeoposition(xmlDocument))
+         {
+            if (traceDebug())
+            {
+               ossimNotify(ossimNotifyLevel_FATAL)
+                  << MODULE << " DEBUG:" << "ossimPleiadesDimapSupportData::parseXmlFile:"
+                  << "\nparseGeoposition failed.  Returning false" << std::endl;
+            }
+            return false;
+         }
+
+         if (!parseProcessingInformation(xmlDocument))
+         {
+            if (traceDebug())
+            {
+               ossimNotify(ossimNotifyLevel_FATAL)
+                  << MODULE << " DEBUG:" << "ossimPleiadesDimapSupportData::parseXmlFile:"
+                  << "\nparseProcessingInformation failed.  Returning false" << std::endl;
+            }
+            return false;
+         }
+
+         if (!parseRasterData(xmlDocument))
+         {
+            if (traceDebug())
+            {
+               ossimNotify(ossimNotifyLevel_FATAL)
+                  << MODULE << " DEBUG:" << "ossimPleiadesDimapSupportData::parseXmlFile:"
+                  << "\nparseRasterData failed.  Returning false" << std::endl;
+            }
+            return false;
+         }
+
+         if (!parseRadiometricData(xmlDocument))
+         {
+            ossimNotify(ossimNotifyLevel_FATAL)
+               << MODULE << " DEBUG:" << "ossimPleiadesDimapSupportData::parseXmlFile:"
+               << "\nparseRadiometricData failed.  Returning false" << std::endl;
+            return false;
+         }
+
+         if (!parseGeometricData(xmlDocument))
+         {
+            ossimNotify(ossimNotifyLevel_FATAL)
+               << MODULE << " DEBUG:" << "ossimPleiadesDimapSupportData::parseXmlFile:"
+               << "\nparseGeometricData failed.  Returning false" << std::endl;
+            return false;
+         }
+
+         if (!parseQualityAssessment(xmlDocument))
+         {
+            ossimNotify(ossimNotifyLevel_FATAL)
+               << MODULE << " DEBUG:" << "ossimPleiadesDimapSupportData::parseXmlFile:"
+               << "\nparseQualityAssessment failed.  Returning false" << std::endl;
+            return false;
+         }
+
+         if (!parseDatasetSources(xmlDocument))
+         {
+            ossimNotify(ossimNotifyLevel_FATAL)
+               << MODULE << " DEBUG:" << "ossimPleiadesDimapSupportData::parseXmlFile:"
+               << "\nparseDatasetSources failed.  Returning false" << std::endl;
+            return false;
+         }
+
+         theProductIsOk = true;
+      }
+
+      if (theDIMAPVersion == OSSIM_PLEIADES_DIMAPv1
+          || theMetadataSubProfile == OSSIM_PLEIADES_METADATA_SUBPROFILE_RPC)
+      {
+         // Parse RPC file
+         if (theProcessingLevelString == "SENSOR")
+         {
+            if (parseRPCMetadata(xmlDocument) == false)
+            {
+               ossimNotify(ossimNotifyLevel_FATAL)
+                  << MODULE << " DEBUG:" << "ossimPleiadesDimapSupportData::parseXmlFile:"
+                  << "\nparseRPCMetadata initialization failed.  Returning false" << std::endl;
+               return false;
+            }
+            theRpcIsOk = true;
+         }
+         else
+            theRpcIsOk = true;
+      }
+
+      if (theProcessingLevelString != "SENSOR")
+         theRpcIsOk = true;
+
+      if (traceDebug() && allMetadataRead())
+      {
+         printInfo(ossimNotify(ossimNotifyLevel_DEBUG));
+         ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " DEBUG: exited..." << std::endl;
+      }
+
+      return true;
+   }
+
+   ossimString ossimPleiadesDimapSupportData::getProcessingLevel() const
+   {
+      return theProcessingLevelString;
+   }
+
+   ossimString ossimPleiadesDimapSupportData::getSensorID() const
+   {
+      return theSensorID;
+   }
+
+   ossimString ossimPleiadesDimapSupportData::getAcquisitionDate() const
+   {
+      return theAcquisitionDate;
+   }
+
+   ossimString ossimPleiadesDimapSupportData::getProductionDate() const
+   {
+      return theProductionDate;
+   }
+
+   ossimString ossimPleiadesDimapSupportData::getImageID() const
+   {
+      return theImageID;
+   }
+
+   ossimString ossimPleiadesDimapSupportData::getInstrument() const
+   {
+      return theInstrument;
+   }
+
+   ossimString ossimPleiadesDimapSupportData::getInstrumentIndex() const
+   {
+      return theInstrumentIndex;
+   }
+
+   void ossimPleiadesDimapSupportData::getSunAzimuth(std::vector<ossim_float64>& az) const
+   {
+      az = theSunAzimuth;
+   }
+
+   void ossimPleiadesDimapSupportData::getSunElevation(std::vector<ossim_float64>& el) const
+   {
+      el = theSunElevation;
+   }
+
+   void ossimPleiadesDimapSupportData::getImageSize(ossimIpt& sz) const
+   {
+      sz = theImageSize;
+   }
+
+   ossim_uint32 ossimPleiadesDimapSupportData::getNumberOfBands() const
+   {
+      return theNumBands;
+   }
+
+   void ossimPleiadesDimapSupportData::getIncidenceAngle(std::vector<ossim_float64>& ia) const
+   {
+      ia = theIncidenceAngle;
+   }
+
+   void ossimPleiadesDimapSupportData::getViewingAngle(std::vector<ossim_float64>& va) const
+   {
+      va = theViewingAngle;
+   }
+
+  void ossimPleiadesDimapSupportData::getAcrossTrackIncidenceAngle(std::vector<ossim_float64>& act) const
+   {
+      act = theAcrossTrackIncidenceAngle;
+   }
+
+  void ossimPleiadesDimapSupportData::getAlongTrackIncidenceAngle(std::vector<ossim_float64>& alt) const
+   {
+      alt = theAlongTrackIncidenceAngle;
+   }
+
+
+   void ossimPleiadesDimapSupportData::getRefGroundPoint(ossimGpt& gp) const
+   {
+      gp = theRefGroundPoint;
+   }
+
+   void ossimPleiadesDimapSupportData::getRefImagePoint(ossimDpt& rp) const
+   {
+      rp = theRefImagePoint;
+   }
+
+   void ossimPleiadesDimapSupportData::getUlCorner(ossimGpt& pt) const
+   {
+      pt = theUlCorner;
+   }
+
+   void ossimPleiadesDimapSupportData::getUrCorner(ossimGpt& pt) const
+   {
+      pt = theUrCorner;
+   }
+
+   void ossimPleiadesDimapSupportData::getLrCorner(ossimGpt& pt) const
+   {
+      pt = theLrCorner;
+   }
+
+   void ossimPleiadesDimapSupportData::getLlCorner(ossimGpt& pt) const
+   {
+      pt = theLlCorner;
+   }
+
+   void ossimPleiadesDimapSupportData::getImageRect(ossimDrect& rect)const
+   {
+      rect = ossimDrect(0.0, 0.0, theImageSize.x-1.0, theImageSize.y-1.0);
+   }
+
+
+   bool ossimPleiadesDimapSupportData::saveState(ossimKeywordlist& kwl,
+                                                 const char* prefix)const
+   {
+      ossimString tempString;
+      ossim_uint32 idx = 0;
+
+      kwl.add(prefix,
+              ossimKeywordNames::TYPE_KW,
+              "ossimPleiadesDimapSupportData",
+              true);
+
+      tempString = "";
+      for(idx = 0; idx < theSunAzimuth.size(); ++idx)
+      {
+         tempString += (ossimString::toString(theSunAzimuth[idx]) + " ");
+      }
+
+      kwl.add(prefix,
+              ossimKeywordNames::AZIMUTH_ANGLE_KW,
+              tempString,
+              true);
+
+      kwl.add(prefix,
+              "number_of_azimuth_angle",
+              static_cast<ossim_uint32>(theSunAzimuth.size()),
+              true);
+
+      tempString = "";
+      for(idx = 0; idx <  theSunElevation.size(); ++idx)
+      {
+         tempString += (ossimString::toString(theSunElevation[idx]) + " ");
+      }
+
+      kwl.add(prefix,
+              ossimKeywordNames::ELEVATION_ANGLE_KW,
+              tempString,
+              true);
+
+      kwl.add(prefix,
+              "number_of_elevation_angle",
+              static_cast<ossim_uint32>(theSunElevation.size()),
+              true);
+
+      //---
+      // Note: since this is a new keyword, use the point.toString as there is
+      // no backwards compatibility issues.
+      //---
+
+      kwl.add(prefix,
+              "image_size",
+              ossimString::toString(theImageSize.x) + " " +
+              ossimString::toString(theImageSize.y),
+              true);
+
+      kwl.add(prefix,
+              "reference_ground_point",
+              ossimString::toString(theRefGroundPoint.latd()) + " " +
+              ossimString::toString(theRefGroundPoint.lond()) + " " +
+              ossimString::toString(theRefGroundPoint.height()) + " " +
+              theRefGroundPoint.datum()->code(),
+              true);
+
+      kwl.add(prefix,
+              "reference_image_point",
+              ossimString::toString(theRefImagePoint.x) + " " +
+              ossimString::toString(theRefImagePoint.y),
+              true);
+
+      kwl.add(prefix,
+              ossimKeywordNames::NUMBER_BANDS_KW,
+              theNumBands,
+              true);
+
+      tempString = "";
+      for(idx = 0; idx <  theBandOrder.size(); ++idx)
+      {
+         tempString += (theBandOrder[idx] + " ");
+      }
+
+      kwl.add(prefix,
+              "band_name_list",
+              tempString,
+              true);
+
+      kwl.add(prefix,
+              "image_id",
+              theImageID,
+              true);
+
+      kwl.add(prefix,
+              "processing_level",
+              theProcessingLevelString,
+              true);
+
+      kwl.add(prefix,
+              "instrument",
+              theInstrument,
+              true);
+
+      kwl.add(prefix,
+              "instrument_index",
+              theInstrumentIndex,
+              true);
+
+      kwl.add(prefix,
+              ossimKeywordNames::IMAGE_DATE_KW,
+              theAcquisitionDate,
+              true);
+
+      kwl.add(prefix,
+              "production_date",
+              theProductionDate,
+              true);
+
+      tempString = "";
+      for(idx = 0; idx <  theIncidenceAngle.size(); ++idx)
+      {
+         tempString += (ossimString::toString(theIncidenceAngle[idx]) + " ");
+      }
+
+      kwl.add(prefix,
+              "incident_angle",
+              tempString,
+              true);
+
+      kwl.add(prefix,
+              "number_of_incident_angle",
+              static_cast<ossim_uint32>(theIncidenceAngle.size()),
+              true);
+
+      tempString = "";
+      for(idx = 0; idx <  theViewingAngle.size(); ++idx)
+      {
+         tempString += (ossimString::toString(theViewingAngle[idx]) + " ");
+      }
+
+      kwl.add(prefix,
+              "viewing_angle",
+              tempString,
+              true);
+
+      kwl.add(prefix,
+              "number_of_viewing_angle",
+              static_cast<ossim_uint32>(theViewingAngle.size()),
+              true);
+
+      tempString = "";
+      for(idx = 0; idx <  theAzimuthAngle.size(); ++idx)
+      {
+         tempString += (ossimString::toString(theAzimuthAngle[idx]) + " ");
+      }
+
+      kwl.add(prefix,
+              "scene_orientation",
+              tempString,
+              true);
+
+      kwl.add(prefix,
+              "number_of_scene_orientation",
+              static_cast<ossim_uint32>(theAzimuthAngle.size()),
+              true);
+
+
+      tempString = "";
+      for(idx = 0; idx <  theAlongTrackIncidenceAngle.size(); ++idx)
+      {
+         tempString += (ossimString::toString(theAlongTrackIncidenceAngle[idx]) + " ");
+      }
+      kwl.add(prefix,
+              "along_track_incidence_angle",
+              tempString,
+              true);
+
+       kwl.add(prefix,
+              "number_of_along_track_incidence_angle",
+              static_cast<ossim_uint32>(theAlongTrackIncidenceAngle.size()),
+              true);
+
+
+      tempString = "";
+      for(idx = 0; idx <  theAcrossTrackIncidenceAngle.size(); ++idx)
+      {
+         tempString += (ossimString::toString(theAcrossTrackIncidenceAngle[idx]) + " ");
+      }
+      kwl.add(prefix,
+              "across_track_incidence_angle",
+              tempString,
+              true);
+
+       kwl.add(prefix,
+              "number_of_across_track_incidence_angle",
+              static_cast<ossim_uint32>(theAcrossTrackIncidenceAngle.size()),
+              true);
+
+      kwl.add(prefix,
+              "ul_ground_point",
+              ossimString::toString(theUlCorner.latd()) + " " +
+              ossimString::toString(theUlCorner.lond()) + " " +
+              ossimString::toString(theUlCorner.height()) + " " +
+              theUlCorner.datum()->code(),
+              true);
+
+      kwl.add(prefix,
+              "ur_ground_point",
+              ossimString::toString(theUrCorner.latd()) + " " +
+              ossimString::toString(theUrCorner.lond()) + " " +
+              ossimString::toString(theUrCorner.height()) + " " +
+              theUrCorner.datum()->code(),
+              true);
+
+      kwl.add(prefix,
+              "lr_ground_point",
+              ossimString::toString(theLrCorner.latd()) + " " +
+              ossimString::toString(theLrCorner.lond()) + " " +
+              ossimString::toString(theLrCorner.height()) + " " +
+              theLrCorner.datum()->code(),
+              true);
+
+      kwl.add(prefix,
+              "ll_ground_point",
+              ossimString::toString(theLlCorner.latd()) + " " +
+              ossimString::toString(theLlCorner.lond()) + " " +
+              ossimString::toString(theLlCorner.height()) + " " +
+              theLlCorner.datum()->code(),
+              true);
+
+      kwl.add(prefix,
+              "sensorID",
+              theSensorID,
+              true);
+
+
+      tempString = "";
+      for(idx = 0; idx < thePhysicalBias.size(); ++idx)
+      {
+         tempString += (ossimString::toString(thePhysicalBias[idx]) + " ");
+      }
+      kwl.add(prefix,
+              "physical_bias",
+              tempString,
+              true);
+
+      tempString = "";
+      for(idx = 0; idx < thePhysicalGain.size(); ++idx)
+      {
+         tempString += (ossimString::toString(thePhysicalGain[idx]) + " ");
+      }
+      kwl.add(prefix,
+              "physical_gain",
+              tempString,
+              true);
+
+      tempString = "";
+      for(idx = 0; idx < theSolarIrradiance.size(); ++idx)
+      {
+         tempString += (ossimString::toString(theSolarIrradiance[idx]) + " ");
+      }
+
+      kwl.add(prefix,
+              "solar_irradiance",
+              tempString,
+              true);
+      
+      // Some geometric parameters exist only in the case of a SENSOR image
+      if (theProcessingLevelString == "SENSOR")
+      {
+        kwl.add(prefix,
+                "time_range_start",
+                theTimeRangeStart,
+                true);
+
+        kwl.add(prefix,
+                "time_range_end",
+                theTimeRangeEnd,
+                true);
+        
+        kwl.add(prefix,
+                "line_period",
+                ossimString::toString(theLinePeriod),
+                true);
+        
+        kwl.add(prefix,
+                "swath_first_col",
+                theSwathFirstCol,
+                true);
+        kwl.add(prefix,
+                "swath_last_col",
+                theSwathLastCol,
+                true);
+      }
+      
+      return true;
+   }
+
+   bool ossimPleiadesDimapSupportData::loadState(const ossimKeywordlist& kwl,
+                                                 const char* prefix)
+   {
+      ossim_uint32 idx = 0;
+      ossim_uint32 total;
+      ossimString tempString;
+
+      clearFields();
+
+
+      ossimString type = kwl.find(prefix, ossimKeywordNames::TYPE_KW);
+
+      if(type != "ossimPleiadesDimapSupportData")
+      {
+         return false;
+      }
+
+      total =  ossimString(kwl.find(prefix,"number_of_azimuth_angle")).toUInt32();
+      theSunAzimuth.resize(total);
+      tempString = kwl.find(prefix,ossimKeywordNames::AZIMUTH_ANGLE_KW);
+      if(tempString != "")
+      {
+         std::istringstream in(tempString.string());
+         ossimString tempValue;
+         for(idx = 0; idx < theSunAzimuth.size();++idx)
+         {
+            in >> tempValue.string();
+            theSunAzimuth[idx] = tempValue.toDouble();
+         }
+      }
+
+      total =  ossimString(kwl.find(prefix,"number_of_elevation_angle")).toUInt32();
+      theSunElevation.resize(total);
+      tempString = kwl.find(prefix,ossimKeywordNames::ELEVATION_ANGLE_KW);
+      if(tempString != "")
+      {
+         std::istringstream in(tempString.string());
+         ossimString tempValue;
+         for(idx = 0; idx < theSunElevation.size();++idx)
+         {
+            in >> tempValue.string();
+            theSunElevation[idx] = tempValue.toDouble();
+         }
+      }
+
+      // const char* lookup;
+
+      theImageSize      = createIpt(kwl.find(prefix, "image_size"));
+      theRefGroundPoint = createGround(kwl.find(prefix, "reference_ground_point"));
+      theRefImagePoint  = createDpt(kwl.find(prefix, "reference_image_point"));
+
+      theNumBands        = ossimString(kwl.find(prefix, ossimKeywordNames::NUMBER_BANDS_KW)).toUInt32();
+
+      theBandOrder.resize(theNumBands);
+      tempString = kwl.find(prefix,"band_name_list");
+      if(tempString != "")
+      {
+         std::istringstream in(tempString.string());
+         ossimString tempValue;
+         for(idx = 0; idx < theBandOrder.size();++idx)
+         {
+            in >> tempValue.string();
+            theBandOrder[idx] = tempValue;
+         }
+      }
+
+      theAcquisitionDate = kwl.find(prefix, ossimKeywordNames::IMAGE_DATE_KW);
+      theProductionDate  = kwl.find(prefix, "production_date");
+      theImageID         = kwl.find(prefix, "image_id");
+      theInstrument      = kwl.find(prefix, "instrument");
+      theInstrumentIndex = kwl.find(prefix, "instrument_index");
+   
+      total =  ossimString(kwl.find(prefix,"number_of_incident_angle")).toUInt32();
+      theIncidenceAngle.resize(total);
+      tempString = kwl.find(prefix,"incident_angle");
+      if(tempString != "")
+      {
+         std::istringstream in(tempString.string());
+         ossimString tempValue;
+         for(idx = 0; idx < theIncidenceAngle.size();++idx)
+         {
+            in >> tempValue.string();
+            theIncidenceAngle[idx] = tempValue.toDouble();
+         }
+      }
+
+      total =  ossimString(kwl.find(prefix,"number_of_viewing_angle")).toUInt32();
+      theViewingAngle.resize(total);
+      tempString = kwl.find(prefix,"viewing_angle");
+      if(tempString != "")
+      {
+         std::istringstream in(tempString.string());
+         ossimString tempValue;
+         for(idx = 0; idx < theViewingAngle.size();++idx)
+         {
+            in >> tempValue.string();
+            theViewingAngle[idx] = tempValue.toDouble();
+         }
+      }
+
+      total =  ossimString(kwl.find(prefix,"number_of_scene_orientation")).toUInt32();
+      theAzimuthAngle.resize(total);
+      tempString = kwl.find(prefix,"scene_orientation");
+      if(tempString != "")
+      {
+         std::istringstream in(tempString.string());
+         ossimString tempValue;
+         for(idx = 0; idx < theAzimuthAngle.size();++idx)
+         {
+            in >> tempValue.string();
+            theAzimuthAngle[idx] = tempValue.toDouble();
+         }
+      }
+
+      total =  ossimString(kwl.find(prefix,"number_of_along_track_incidence_angle")).toUInt32();
+      theAlongTrackIncidenceAngle.resize(total);
+      tempString = kwl.find(prefix,"along_track_incidence_angle");
+      if(tempString != "")
+      {
+         std::istringstream in(tempString.string());
+         ossimString tempValue;
+         for(idx = 0; idx < theAlongTrackIncidenceAngle.size();++idx)
+         {
+            in >> tempValue.string();
+            theAlongTrackIncidenceAngle[idx] = tempValue.toDouble();
+         }
+      }
+
+      total =  ossimString(kwl.find(prefix,"number_of_across_track_incidence_angle")).toUInt32();
+      theAcrossTrackIncidenceAngle.resize(total);
+      tempString = kwl.find(prefix,"across_track_incidence_angle");
+      if(tempString != "")
+      {
+         std::istringstream in(tempString.string());
+         ossimString tempValue;
+         for(idx = 0; idx < theAcrossTrackIncidenceAngle.size();++idx)
+         {
+            in >> tempValue.string();
+            theAcrossTrackIncidenceAngle[idx] = tempValue.toDouble();
+         }
+      }
+
+      theUlCorner =createGround( kwl.find(prefix, "ul_ground_point"));
+      theUrCorner =createGround( kwl.find(prefix, "ur_ground_point"));
+      theLrCorner =createGround( kwl.find(prefix, "lr_ground_point"));
+      theLlCorner =createGround( kwl.find(prefix, "ll_ground_point"));
+
+      theSensorID = ossimString(kwl.find(prefix, "sensorID"));
+
+      theProcessingLevelString = ossimString(kwl.find(prefix, "processing_level"));
+
+      thePhysicalBias.resize(theNumBands);
+      tempString = kwl.find(prefix,"physical_bias");
+      if(tempString != "")
+      {
+         std::istringstream in(tempString.string());
+         ossimString tempValue;
+         for(idx = 0; idx < thePhysicalBias.size();++idx)
+         {
+            in >> tempValue.string();
+            thePhysicalBias[idx] = tempValue.toDouble();
+         }
+      }
+
+      thePhysicalGain.resize(theNumBands);
+      tempString = kwl.find(prefix,"physical_gain");
+      if(tempString != "")
+      {
+         std::istringstream in(tempString.string());
+         ossimString tempValue;
+         for(idx = 0; idx < thePhysicalGain.size();++idx)
+         {
+            in >> tempValue.string();
+            thePhysicalGain[idx] = tempValue.toDouble();
+         }
+      }
+
+      theSolarIrradiance.resize(theNumBands);
+      tempString = kwl.find(prefix,"solar_irradiance");
+      if(tempString != "")
+      {
+         std::istringstream in(tempString.string());
+         ossimString tempValue;
+         for(idx = 0; idx < theSolarIrradiance.size();++idx)
+         {
+            in >> tempValue.string();
+            theSolarIrradiance[idx] = tempValue.toDouble();
+         }
+      }
+      
+      // Some geometric parameters exist only in the case of a SENSOR image
+      if (theProcessingLevelString == "SENSOR")
+      {
+        theTimeRangeStart = ossimString(kwl.find(prefix,"time_range_start"));
+        theTimeRangeEnd   = ossimString(kwl.find(prefix,"time_range_end"));
+        theLinePeriod     = ossimString(kwl.find(prefix,"line_period")).toDouble();
+        theSwathFirstCol  = ossimString(kwl.find(prefix,"swath_first_col")).toInt32();
+        theSwathLastCol   = ossimString(kwl.find(prefix,"swath_last_col")).toInt32();
+      }
+
+      return true;
+   }
+
+   ossimGpt ossimPleiadesDimapSupportData::createGround(const ossimString& s)const
+   {
+      std::istringstream in(s.string());
+      ossimString lat, lon, height;
+      ossimString code;
+
+      in >> lat.string() >> lon.string() >> height.string() >> code.string();
+
+      return ossimGpt(lat.toDouble(),
+                      lon.toDouble(),
+                      height.toDouble(),
+                      ossimDatumFactory::instance()->create(code));
+
+   }
+
+   ossimDpt ossimPleiadesDimapSupportData::createDpt(const ossimString& s)const
+   {
+      std::istringstream in(s.string());
+      ossimString x, y;
+      ossimString code;
+
+      in >> x.string() >> y.string();
+
+      return ossimDpt(x.toDouble(), y.toDouble());
+
+   }
+
+   ossimIpt ossimPleiadesDimapSupportData::createIpt(const ossimString& s)const
+   {
+      std::istringstream in(s.string());
+      ossimString x, y;
+      ossimString code;
+
+      in >> x.string() >> y.string();
+
+      return ossimIpt(x.toInt(), y.toInt());
+
+   }
+
+   bool ossimPleiadesDimapSupportData::parseProductInformation(
+      ossimRefPtr<ossimXmlDocument> xmlDocument)
+   {
+      ossimString xpath;
+      vector<ossimRefPtr<ossimXmlNode> > xml_nodes;
+
+      //---
+      // Fetch the Image ID:
+      //---
+      if (theDIMAPVersion == OSSIM_PLEIADES_DIMAPv1)
+      {
+         xpath = "/Production/JOB_ID";
+      }
+      else
+      {
+         xpath = "/Product_Information/Delivery_Identification/JOB_ID";
+      }
+      xpath = theXmlDocumentRoot + xpath;
+      if (!readOneXmlNode(xmlDocument, xpath, theImageID))
+      {
+         return false;
+      }
+
+      //---
+      // Fetch the ProductionDate:
+      //---
+      if (theDIMAPVersion == OSSIM_PLEIADES_DIMAPv1)
+      {
+         xpath = "/Production/DATASET_PRODUCTION_DATE";
+      }
+      else
+      {
+         xpath = "/Product_Information/Delivery_Identification/PRODUCTION_DATE";
+      }
+      xpath = theXmlDocumentRoot + xpath;
+      if (!readOneXmlNode(xmlDocument, xpath, theProductionDate))
+      {
+         return false;
+      }
+
+      return true;
+   }
+
+   bool ossimPleiadesDimapSupportData::parseDatasetContent(
+      ossimRefPtr<ossimXmlDocument> xmlDocument)
+   {
+      ossimString xpath, nodeValue;
+      vector<ossimRefPtr<ossimXmlNode> > xml_nodes;
+
+      //---
+      // Corner points:
+      //---
+      xml_nodes.clear();
+      if (theDIMAPVersion == OSSIM_PLEIADES_DIMAPv1)
+      {
+         xpath = "/Product_Frame/Dataset_Frame/Vertex";
+      }
+      else
+      {
+         xpath = "/Dataset_Content/Dataset_Extent/Vertex";
+      }
+
+      xpath = theXmlDocumentRoot + xpath;
+      xmlDocument->findNodes(xpath, xml_nodes);
+      if (xml_nodes.size() != 4)
+      {
+         setErrorStatus();
+         return false;
+      }
+      std::vector<ossimRefPtr<ossimXmlNode> >::iterator node = xml_nodes.begin();
+      while (node != xml_nodes.end())
+      {
+         ossimGpt gpt;
+         ossimDpt ipt;
+
+         std::vector<ossimRefPtr<ossimXmlNode> > sub_nodes;
+         xpath = "LAT";
+         (*node)->findChildNodes(xpath, sub_nodes);
+         if (sub_nodes.size() == 0)
+         {
+            setErrorStatus();
+            return false;
+         }
+         gpt.lat = sub_nodes[0]->getText().toDouble();
+
+         sub_nodes.clear();
+         xpath = "LON";
+         (*node)->findChildNodes(xpath, sub_nodes);
+         if (sub_nodes.size() == 0)
+         {
+            setErrorStatus();
+            return false;
+         }
+         gpt.lon = sub_nodes[0]->getText().toDouble();
+         gpt.hgt = 0.0; // assumed
+
+         sub_nodes.clear();
+         xpath = "ROW";
+         (*node)->findChildNodes(xpath, sub_nodes);
+         if (sub_nodes.size() == 0)
+         {
+            setErrorStatus();
+            return false;
+         }
+         ipt.line = sub_nodes[0]->getText().toDouble() - 1.0;
+
+         sub_nodes.clear();
+         xpath = "COL";
+         (*node)->findChildNodes(xpath, sub_nodes);
+         if (sub_nodes.size() == 0)
+         {
+            setErrorStatus();
+            return false;
+         }
+         ipt.samp = sub_nodes[0]->getText().toDouble() - 1.0;
+
+         if (ipt.line < 1.0)
+            if (ipt.samp < 1.0)
+               theUlCorner = gpt;
+            else
+               theUrCorner = gpt;
+         else
+            if (ipt.samp < 1.0)
+               theLlCorner = gpt;
+            else
+               theLrCorner = gpt;
+
+         ++node;
+      }
+
+
+
+      //---
+      // Center of frame.
+      //---
+      theRefGroundPoint.hgt = 0.0; // TODO needs to be looked up
+
+      if (!readOneXmlNode(xmlDocument,
+                          theXmlDocumentRoot + "/Product_Frame/Dataset_Frame/Center/LON", // DIMAPv1
+                          nodeValue))
+      {
+         if (!readOneXmlNode(xmlDocument,
+                             theXmlDocumentRoot + "/Dataset_Content/Dataset_Extent/Center/LON", // DIMAPv2
+                             nodeValue))
+         {
+            return false;
+         }
+      }
+      theRefGroundPoint.lon = nodeValue.toDouble();
+
+      if (!readOneXmlNode(xmlDocument, theXmlDocumentRoot + "/Dataset_Content/Dataset_Extent/Center/LAT", nodeValue))
+      {
+         if (!readOneXmlNode(xmlDocument, theXmlDocumentRoot + "/Product_Frame/Dataset_Frame/Center/LAT", nodeValue))
+         {
+            return false;
+         }
+      }
+      theRefGroundPoint.lat = nodeValue.toDouble();
+
+      return true;
+   }
+
+   bool ossimPleiadesDimapSupportData::parseRadiometricData(
+      ossimRefPtr<ossimXmlDocument> xmlDocument)
+   {
+      ossimString xpath;
+      std::vector<ossimRefPtr<ossimXmlNode> > xml_nodes;
+      std::vector<ossimRefPtr<ossimXmlNode> > sub_nodes;
+      std::vector<ossimRefPtr<ossimXmlNode> >::iterator node;
+
+      //---
+      // Fetch the gain and bias for each spectral band:
+      //---
+      thePhysicalGain.assign(theNumBands, 1.000);
+      thePhysicalBias.assign(theNumBands, 0.000);
+
+      xml_nodes.clear();
+      if (theDIMAPVersion == OSSIM_PLEIADES_DIMAPv1)
+      {
+         xpath = "/Image_Interpretation/Spectral_Band_Info";
+      }
+      else
+      {
+         xpath = "/Radiometric_Data/Radiometric_Calibration/Instrument_Calibration/Band_Measurement_List/Band_Radiance";
+      }
+      xpath = theXmlDocumentRoot + xpath;
+      xmlDocument->findNodes(xpath, xml_nodes);
+
+      node = xml_nodes.begin();
+      while (node != xml_nodes.end())
+      {
+         sub_nodes.clear();
+         xpath = "BAND_ID";
+         (*node)->findChildNodes(xpath, sub_nodes);
+         if (sub_nodes.size() == 0)
+         {
+            setErrorStatus();
+            return false;
+         }
+
+         ossimString bandName = sub_nodes[0]->getText();
+         ossim_uint32 bandIndex = 99999; // Bogus index...
+         if ( (bandName == "B0") || (bandName == "P") ||
+              (bandName == "PA") || (theNumBands == 1) )
+         {
+            bandIndex = 0;
+         }
+         else if ( (bandName == "B1") && (theNumBands > 1) )
+         {
+            bandIndex = 1;
+         }
+         else if ( (bandName == "B2") && (theNumBands > 2) )
+         {
+            bandIndex = 2;
+         }
+         else if ( (bandName == "B3") && (theNumBands > 3) )
+         {
+            bandIndex = 3;
+         }         
+         else
+         {
+            ossimNotify(ossimNotifyLevel_WARN)
+               << "ossimPleiadesDimapSupportData::parseRadiometricMetadata ERROR: Band ID is incorrect\n";
+         }
+         
+         if (bandIndex >= theNumBands )
+         {
+            ossimNotify(ossimNotifyLevel_WARN)
+               << "ossimPleiadesDimapSupportData::parseRadiometricMetadata ERROR: Band index outside of range\n";
+            return false;
+         }
+
+         sub_nodes.clear();
+         xpath = (theDIMAPVersion == OSSIM_PLEIADES_DIMAPv1 ? "PHYSICAL_BIAS" : "BIAS");
+         (*node)->findChildNodes(xpath, sub_nodes);
+         if (sub_nodes.size() == 0)
+         {
+            setErrorStatus();
+            return false;
+         }
+         thePhysicalBias[bandIndex] = sub_nodes[0]->getText().toDouble();
+
+         sub_nodes.clear();
+         xpath = (theDIMAPVersion == OSSIM_PLEIADES_DIMAPv1 ? "PHYSICAL_GAIN" : "GAIN");
+         (*node)->findChildNodes(xpath, sub_nodes);
+         if (sub_nodes.size() == 0)
+         {
+            setErrorStatus();
+            return false;
+         }
+         thePhysicalGain[bandIndex] = sub_nodes[0]->getText().toDouble();
+
+         ++node;
+      }
+
+      // Initialize to 999 : we find this value in some DIMAPv2 file
+      // and there is no such tag in DIMAPv1 file
+      theSolarIrradiance.assign(theNumBands, 999.000);
+
+      xml_nodes.clear();
+      xpath = "/Radiometric_Data/Radiometric_Calibration/Instrument_Calibration/Band_Measurement_List/Band_Solar_Irradiance";
+      xpath = theXmlDocumentRoot + xpath;
+      xmlDocument->findNodes(xpath, xml_nodes);
+
+      node = xml_nodes.begin();
+      while (node != xml_nodes.end())
+      {
+         sub_nodes.clear();
+         xpath = "BAND_ID";
+         (*node)->findChildNodes(xpath, sub_nodes);
+         if (sub_nodes.size() == 0)
+         {
+            setErrorStatus();
+            return false;
+         }
+
+         ossimString bandName = sub_nodes[0]->getText();
+         ossim_uint32 bandIndex = 99999; // Bogus index...
+         if ( (bandName == "B0") || (bandName == "P") ||
+              (bandName == "PA") || (theNumBands == 1) )
+         {
+            bandIndex = 0;
+         }
+         else if ( (bandName == "B1") && (theNumBands > 1) )
+         {
+            bandIndex = 1;
+         }
+         else if ( (bandName == "B2") && (theNumBands > 2) )
+         {
+            bandIndex = 2;
+         }
+         else if ( (bandName == "B3") && (theNumBands > 3) )
+         {
+            bandIndex = 3;
+         }
+         else
+         {
+            ossimNotify(ossimNotifyLevel_WARN)
+               << "ossimPleiadesDimapSupportData::parseRadiometricMetadata ERROR: Band ID is incorrect\n";
+         }
+         
+         if ((bandIndex >= theNumBands))
+         {
+            ossimNotify(ossimNotifyLevel_WARN)
+               << "ossimPleiadesDimapSupportData::parseRadiometricMetadata ERROR: Band index outside of range 2\n";
+            return false;
+         }
+
+         sub_nodes.clear();
+         xpath = "VALUE";
+         (*node)->findChildNodes(xpath, sub_nodes);
+         if (sub_nodes.size() == 0)
+         {
+            setErrorStatus();
+            return false;
+         }
+         theSolarIrradiance[bandIndex] = sub_nodes[0]->getText().toDouble();
+
+         ++node;
+      }
+
+      return true;
+   }
+
+   bool ossimPleiadesDimapSupportData::parseRPCMetadata(
+      ossimRefPtr<ossimXmlDocument> xmlDocument)
+   {
+      static const char MODULE[] = "ossimPleiadesDimapSupportData::parseRPCMetadata";
+      ossimString xpath, nodeValue;
+      vector<ossimRefPtr<ossimXmlNode> > xml_nodes;
+
+      //---
+      // Fetch the Global RFM - Direct Model - Bias:
+      //---
+
+      // RESOURCE_ID does not exists in DIMAPv1 file
+      if (theDIMAPVersion == OSSIM_PLEIADES_DIMAPv2)
+      {
+         xpath = "/Rational_Function_Model/Resource_Reference/RESOURCE_ID";
+         xpath = theXmlDocumentRoot + xpath;
+         if (!readOneXmlNode(xmlDocument, xpath, nodeValue))
+         {
+           ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " DEBUG: Could not find: " << xpath << std::endl;
+           return false;
+         }
+         theSpecId = nodeValue;
+      }
+
+      //---
+      // Fetch the Global RFM - Inverse Model:
+      //---
+      xml_nodes.clear();
+      if (theDIMAPVersion == OSSIM_PLEIADES_DIMAPv1)
+      {
+         xpath = "/Geoposition/Rational_Sensor_Model/Global_RFM/Inverse_Model";
+      }
+      else
+      {
+        xpath = "/Rational_Function_Model/Global_RFM/Inverse_Model";
+      }
+      xpath = theXmlDocumentRoot + xpath;
+      xmlDocument->findNodes(xpath, xml_nodes);
+      if (xml_nodes.empty())
+      {
+        setErrorStatus();
+        if(traceDebug())
+        {
+           ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " DEBUG: Could not find: " << xpath << std::endl;
+        }
+        return false;
+      }
+
+      if (theDIMAPVersion == OSSIM_PLEIADES_DIMAPv1)
+      {
+         std::vector<ossimString> coeffs;
+
+         xml_nodes.clear();
+         xpath = "/Geoposition/Rational_Sensor_Model/Global_RFM/Inverse_Model/F_ROW";
+         xpath = theXmlDocumentRoot + xpath;
+         xmlDocument->findNodes(xpath, xml_nodes);
+         coeffs = xml_nodes[0]->getText().split(" ", true);
+
+         const size_t nRow = coeffs.size() / 2;
+         for (size_t i = 0; i < nRow; i++)
+           {
+           theLineNumCoeff.push_back(coeffs[i].toDouble());
+           theLineDenCoeff.push_back(coeffs[i + nRow].toDouble());
+           }
+
+         xml_nodes.clear();
+         xpath = "/Geoposition/Rational_Sensor_Model/Global_RFM/Inverse_Model/F_COL";
+         xpath = theXmlDocumentRoot + xpath;
+         xmlDocument->findNodes(xpath, xml_nodes);
+         coeffs = xml_nodes[0]->getText().split(" ", true);
+
+         const size_t nCol = coeffs.size() / 2;
+         for (size_t i = 0; i < nCol; i++)
+           {
+           theSampNumCoeff.push_back(coeffs[i].toDouble());
+           theSampDenCoeff.push_back(coeffs[i + nCol].toDouble());
+           }
+
+      }
+      else
+      {
+        for (ossim_uint32 it = 1; it < 21; it ++)
+        {
+           std::ostringstream valueStr;
+           valueStr << it;
+
+           xml_nodes.clear();
+           xpath = "/Rational_Function_Model/Global_RFM/Inverse_Model/LINE_NUM_COEFF_";
+           xpath = theXmlDocumentRoot + xpath;
+           xpath = xpath + valueStr.str();
+           xmlDocument->findNodes(xpath, xml_nodes);
+           if (xml_nodes.size() == 0)
+           {
+              setErrorStatus();
+              if(traceDebug())
+              {
+                 ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " DEBUG:" << "\nCould not find: " << xpath << std::endl;
+              }
+              return false;
+           }
+           theLineNumCoeff.push_back(xml_nodes[0]->getText().toDouble());
+
+           xml_nodes.clear();
+           xpath = "/Rational_Function_Model/Global_RFM/Inverse_Model/LINE_DEN_COEFF_";
+           xpath = theXmlDocumentRoot + xpath;
+           xpath = xpath + valueStr.str();
+           xmlDocument->findNodes(xpath, xml_nodes);
+           if (xml_nodes.size() == 0)
+           {
+              setErrorStatus();
+              if(traceDebug())
+              {
+                 ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " DEBUG:" << "\nCould not find: " << xpath << std::endl;
+              }
+              return false;
+           }
+           theLineDenCoeff.push_back(xml_nodes[0]->getText().toDouble());
+
+           xml_nodes.clear();
+           xpath = "/Rational_Function_Model/Global_RFM/Inverse_Model/SAMP_NUM_COEFF_";
+           xpath = theXmlDocumentRoot + xpath;
+           xpath = xpath + valueStr.str();
+           xmlDocument->findNodes(xpath, xml_nodes);
+           if (xml_nodes.size() == 0)
+           {
+              setErrorStatus();
+              if(traceDebug())
+              {
+                 ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " DEBUG:" << "\nCould not find: " << xpath << std::endl;
+              }
+              return false;
+           }
+           theSampNumCoeff.push_back(xml_nodes[0]->getText().toDouble());
+
+           xml_nodes.clear();
+           xpath = "/Rational_Function_Model/Global_RFM/Inverse_Model/SAMP_DEN_COEFF_";
+           xpath = theXmlDocumentRoot + xpath;
+           xpath = xpath + valueStr.str();
+           xmlDocument->findNodes(xpath, xml_nodes);
+           if (xml_nodes.size() == 0)
+           {
+              setErrorStatus();
+              if(traceDebug())
+              {
+                 ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " DEBUG:" << "\nCould not find: " << xpath << std::endl;
+              }
+              return false;
+           }
+           theSampDenCoeff.push_back(xml_nodes[0]->getText().toDouble());
+        }
+      }
+      //---
+      // Fetch the Global RFM - Inverse Model - Bias:
+      //---
+      if (theDIMAPVersion == OSSIM_PLEIADES_DIMAPv1)
+      {
+         xpath = "/Geoposition/Rational_Sensor_Model/Global_RFM/Inverse_Model/MODEL_PRECISION_ROW";
+      }
+      else
+      {
+         xpath = "/Rational_Function_Model/Global_RFM/Inverse_Model/ERR_BIAS_ROW";
+      }
+      xpath = theXmlDocumentRoot + xpath;
+      if (!readOneXmlNode(xmlDocument, xpath, nodeValue))
+      {
+         return false;
+      }
+      theErrBiasX = nodeValue.toDouble();
+
+      if (theDIMAPVersion == OSSIM_PLEIADES_DIMAPv1)
+      {
+         xpath = "/Geoposition/Rational_Sensor_Model/Global_RFM/Inverse_Model/MODEL_PRECISION_COL";
+      }
+      else
+      {
+         xpath = "/Rational_Function_Model/Global_RFM/Inverse_Model/ERR_BIAS_COL";
+      }
+      xpath = theXmlDocumentRoot + xpath;
+      if (!readOneXmlNode(xmlDocument, xpath, nodeValue))
+      {
+         return false;
+      }
+      theErrBiasY = nodeValue.toDouble();
+
+      //---
+      // Fetch the Global RFM validity parameters :
+      //---
+      if (theDIMAPVersion == OSSIM_PLEIADES_DIMAPv1)
+      {
+         xpath = "/Geoposition/Rational_Sensor_Model/Global_RFM/RFM_Validity/Lon/A";
+      }
+      else
+      {
+         xpath = "/Rational_Function_Model/Global_RFM/RFM_Validity/LONG_SCALE";
+      }
+      xpath = theXmlDocumentRoot + xpath;
+      if (!readOneXmlNode(xmlDocument, xpath, nodeValue))
+      {
+         return false;
+      }
+      theLonScale = nodeValue.toDouble();
+
+      if (theDIMAPVersion == OSSIM_PLEIADES_DIMAPv1)
+      {
+         xpath = "/Geoposition/Rational_Sensor_Model/Global_RFM/RFM_Validity/Lon/B";
+      }
+      else
+      {
+         xpath = "/Rational_Function_Model/Global_RFM/RFM_Validity/LONG_OFF";
+      }
+      xpath = theXmlDocumentRoot + xpath;
+      if (!readOneXmlNode(xmlDocument, xpath, nodeValue))
+      {
+         return false;
+      }
+      theLonOffset = nodeValue.toDouble();
+
+      if (theDIMAPVersion == OSSIM_PLEIADES_DIMAPv1)
+      {
+         xpath = "/Geoposition/Rational_Sensor_Model/Global_RFM/RFM_Validity/Lat/A";
+      }
+      else
+      {
+         xpath = "/Rational_Function_Model/Global_RFM/RFM_Validity/LAT_SCALE";
+      }
+      xpath = theXmlDocumentRoot + xpath;
+      if (!readOneXmlNode(xmlDocument, xpath, nodeValue))
+      {
+         return false;
+      }
+      theLatScale = nodeValue.toDouble();
+
+      if (theDIMAPVersion == OSSIM_PLEIADES_DIMAPv1)
+      {
+         xpath = "/Geoposition/Rational_Sensor_Model/Global_RFM/RFM_Validity/Lat/B";
+      }
+      else
+      {
+         xpath = "/Rational_Function_Model/Global_RFM/RFM_Validity/LAT_OFF";
+      }
+      xpath = theXmlDocumentRoot + xpath;
+      if (!readOneXmlNode(xmlDocument, xpath, nodeValue))
+      {
+         return false;
+      }
+      theLatOffset = nodeValue.toDouble();
+
+      if (theDIMAPVersion == OSSIM_PLEIADES_DIMAPv1)
+      {
+         xpath = "/Geoposition/Rational_Sensor_Model/Global_RFM/RFM_Validity/Alt/A";
+      }
+      else
+      {
+         xpath = "/Rational_Function_Model/Global_RFM/RFM_Validity/HEIGHT_SCALE";
+      }
+      xpath = theXmlDocumentRoot + xpath;
+      if (!readOneXmlNode(xmlDocument, xpath, nodeValue))
+      {
+         return false;
+      }
+      theHeightScale = nodeValue.toDouble();
+
+      if (theDIMAPVersion == OSSIM_PLEIADES_DIMAPv1)
+      {
+         xpath = "/Geoposition/Rational_Sensor_Model/Global_RFM/RFM_Validity/Alt/B";
+      }
+      else
+      {
+         xpath = "/Rational_Function_Model/Global_RFM/RFM_Validity/HEIGHT_OFF";
+      }
+      xpath = theXmlDocumentRoot + xpath;
+      if (!readOneXmlNode(xmlDocument, xpath, nodeValue))
+      {
+         return false;
+      }
+      theHeightOffset = nodeValue.toDouble();
+
+      if (theDIMAPVersion == OSSIM_PLEIADES_DIMAPv1)
+      {
+         xpath = "/Geoposition/Rational_Sensor_Model/Global_RFM/RFM_Validity/Col/A";
+      }
+      else
+      {
+         xpath = "/Rational_Function_Model/Global_RFM/RFM_Validity/SAMP_SCALE";
+      }
+      xpath = theXmlDocumentRoot + xpath;
+      if (!readOneXmlNode(xmlDocument, xpath, nodeValue))
+      {
+         return false;
+      }
+      theSampScale = nodeValue.toDouble();
+
+      if (theDIMAPVersion == OSSIM_PLEIADES_DIMAPv1)
+      {
+         xpath = "/Geoposition/Rational_Sensor_Model/Global_RFM/RFM_Validity/Col/B";
+      }
+      else
+      {
+         xpath = "/Rational_Function_Model/Global_RFM/RFM_Validity/SAMP_OFF";
+      }
+      xpath = theXmlDocumentRoot + xpath;
+      if (!readOneXmlNode(xmlDocument, xpath, nodeValue))
+      {
+         return false;
+      }
+      // Pleiades metadata assume that the coordinate of the center of
+      // the upper-left pixel is (1,1), so we remove 1 to get back to
+      // OSSIM convention.
+      theSampOffset = nodeValue.toDouble()-1;
+
+      if (theDIMAPVersion == OSSIM_PLEIADES_DIMAPv1)
+      {
+         xpath = "/Geoposition/Rational_Sensor_Model/Global_RFM/RFM_Validity/Row/A";
+      }
+      else
+      {
+         xpath = "/Rational_Function_Model/Global_RFM/RFM_Validity/LINE_SCALE";
+      }
+      xpath = theXmlDocumentRoot + xpath;
+      if (!readOneXmlNode(xmlDocument, xpath, nodeValue))
+      {
+         return false;
+      }
+      theLineScale = nodeValue.toDouble();
+
+      if (theDIMAPVersion == OSSIM_PLEIADES_DIMAPv1)
+      {
+         xpath = "/Geoposition/Rational_Sensor_Model/Global_RFM/RFM_Validity/Row/B";
+      }
+      else
+      {
+         xpath = "/Rational_Function_Model/Global_RFM/RFM_Validity/LINE_OFF";
+      }
+      xpath = theXmlDocumentRoot + xpath;
+      if (!readOneXmlNode(xmlDocument, xpath, nodeValue))
+      {
+         return false;
+      }
+      // Pleiades metadata assume that the coordinate of the center of
+      // the upper-left pixel is (1,1), so we remove 1 to get back to
+      // OSSIM convention.
+      theLineOffset = nodeValue.toDouble()-1;
+
+      return true;
+   }
+
+   bool ossimPleiadesDimapSupportData::parseMetadataIdentificationDIMAPv1(ossimRefPtr<ossimXmlDocument> xmlDocument)
+   {
+      // static const char MODULE[] = "ossimPleiadesDimapSupportData::parseMetadataIdentification";
+
+      vector<ossimRefPtr<ossimXmlNode> > xml_nodes;
+      ossimString xpath, nodeValue;
+      theXmlDocumentRoot = "/PHR_Dimap_Document";
+
+      //---
+      // Get the version string which can be used as a key for parsing.
+      //---
+      xml_nodes.clear();
+      xpath = "/Metadata_Identification/METADATA_FORMAT";
+      xpath = theXmlDocumentRoot + xpath;
+
+      if (!readOneXmlNode(xmlDocument, xpath, nodeValue))
+        {
+        return false;
+        }
+      if (nodeValue != "DIMAP_PHR")
+        {
+        return false;
+        }
+
+      //---
+      // Check that it is a valid PHR DIMAPv2 file
+      //---
+      xpath = "/Metadata_Identification/METADATA_PROFILE";
+      xpath = theXmlDocumentRoot + xpath;
+      if (!readOneXmlNode(xmlDocument, xpath, nodeValue))
+      {
+         return false;
+      }
+
+      ossimString metadataProfile;
+      if ( nodeValue != "PHR_SYSTEM_RECTIFIED_PRODUCT" )
+        {
+        if (traceDebug())
+        {
+           ossimNotify(ossimNotifyLevel_DEBUG)
+              << "DEBUG:\n Not a PLEIADES DIMAPv1 file: METADATA_PROFILE is incorrect!" << std::endl;
+        }
+        return false;
+        }
+
+      // DIMAPv1 -> no subprofile
+      theMetadataSubProfile = OSSIM_PLEIADES_METADATA_SUBPROFILE_UNKNOWN;
+
+      theDIMAPVersion = OSSIM_PLEIADES_DIMAPv1;
+
+      return true;
+   }
+   bool ossimPleiadesDimapSupportData::parseMetadataIdentificationDIMAPv2(ossimRefPtr<ossimXmlDocument> xmlDocument)
+   {
+      // static const char MODULE[] = "ossimPleiadesDimapSupportData::parseMetadataIdentification";
+
+      vector<ossimRefPtr<ossimXmlNode> > xml_nodes;
+      ossimString xpath, nodeValue;
+      theXmlDocumentRoot = "/DIMAP_Document";
+
+      //---
+      // Get the version string which can be used as a key for parsing.
+      //---
+      xml_nodes.clear();
+      xpath = "/Metadata_Identification/METADATA_FORMAT";
+      xpath = theXmlDocumentRoot + xpath;
+      xmlDocument->findNodes(xpath, xml_nodes);
+      if (xml_nodes.size() == 0)
+      {
+         // FIXME MSD: used to support Pleiades samples from SPOT-IMAGES website which are not coherent
+         // with the specification (28/09/2012). Should be remove when first data will be available and sample
+         // replaced.
+         theXmlDocumentRoot = "/PHR_DIMAP_Document";
+         if (traceDebug())
+         {
+            ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG:\nTry to use the old root: " << theXmlDocumentRoot << endl;
+         }
+
+         xml_nodes.clear();
+         xpath = "/Metadata_Identification/METADATA_FORMAT";
+         xpath = theXmlDocumentRoot + xpath;
+         xmlDocument->findNodes(xpath, xml_nodes);
+         if (xml_nodes.size() == 0)
+         {
+            // FIXME MSD: used to support peiades samples from SPOT-IMAGES website which are not coherent
+            // with the specification (28/09/2012). Should be remove when first data will be available and sample
+            // replaced.
+            theXmlDocumentRoot = "/Dimap_Document";
+            if (traceDebug())
+            {
+               ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG:\nTry to use the new root: " << theXmlDocumentRoot << endl;
+            }
+
+            xml_nodes.clear();
+            xpath = "/Metadata_Identification/METADATA_FORMAT";
+            xpath = theXmlDocumentRoot + xpath;
+            xmlDocument->findNodes(xpath, xml_nodes);
+            if (xml_nodes.size() == 0)
+            {
+               setErrorStatus();
+               if (traceDebug())
+               {
+                  ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG:\nCould not find: " << xpath << endl;
+               }
+               return false;
+            }
+         }
+      }
+
+      ossimString attribute = "version";
+      ossimString value;
+      xml_nodes[0]->getAttributeValue(value, attribute);
+      if (value != "2.0")
+      {
+         setErrorStatus();
+         if (traceDebug())
+         {
+            ossimNotify(ossimNotifyLevel_WARN)
+               << "WARNING: DIMAP metadata version is not correct!" << std::endl;
+         }
+         return false;
+      }
+
+      //---
+      // Check that it is a valid PHR DIMAPv2 file
+      //---
+      xpath = "/Metadata_Identification/METADATA_PROFILE";
+      xpath = theXmlDocumentRoot + xpath;
+      if (!readOneXmlNode(xmlDocument, xpath, nodeValue))
+      {
+         return false;
+      }
+
+      ossimString metadataProfile;
+      if (  (nodeValue != "PHR_SENSOR")
+            && (nodeValue != "PHR_ORTHO")
+            && (nodeValue != "PHR_MOSAIC") )
+      {
+         if (traceDebug())
+         {
+            ossimNotify(ossimNotifyLevel_DEBUG)
+               << "DEBUG:\n Not a PLEIADES DIMAPv2 file: metadata profile is incorrect!" << std::endl;
+         }
+         return false;
+      }
+      else
+         metadataProfile = nodeValue;
+
+      //---
+      // Get the subprofile
+      //---
+      xpath = "/Metadata_Identification/METADATA_SUBPROFILE";
+      xpath = theXmlDocumentRoot + xpath;
+      if (!readOneXmlNode(xmlDocument, xpath, nodeValue))
+      {
+         return false;
+      }
+
+      if ((nodeValue == "PRODUCT"))
+         theMetadataSubProfile = OSSIM_PLEIADES_METADATA_SUBPROFILE_PRODUCT;
+      else if ( (nodeValue == "RPC") && (metadataProfile == "PHR_SENSOR") )
+         theMetadataSubProfile = OSSIM_PLEIADES_METADATA_SUBPROFILE_RPC;
+      else
+      {
+         theMetadataSubProfile = OSSIM_PLEIADES_METADATA_SUBPROFILE_UNKNOWN;
+         if (traceDebug())
+         {
+            ossimNotify(ossimNotifyLevel_DEBUG)
+               << "DEBUG:\n Not a PLEIADES DIMAPv2 file: metadata subprofile is incorrect !" << std::endl;
+         }
+         return false;
+      }
+
+      theDIMAPVersion = OSSIM_PLEIADES_DIMAPv2;
+
+      return true;
+   }
+
+   bool ossimPleiadesDimapSupportData::parseDatasetIdentification(ossimRefPtr<ossimXmlDocument> /* xmlDocument */ )
+   {
+      return true;
+   }
+
+   bool ossimPleiadesDimapSupportData::parseCoordinateReferenceSystem(ossimRefPtr<ossimXmlDocument> /* xmlDocument */ )
+   {
+      return true;
+   }
+
+   bool ossimPleiadesDimapSupportData::parseGeoposition(ossimRefPtr<ossimXmlDocument> /* xmlDocument */ )
+   {
+      return true;
+   }
+
+   bool ossimPleiadesDimapSupportData::parseProcessingInformation(ossimRefPtr<ossimXmlDocument> xmlDocument)
+   {
+      // static const char MODULE[] = "ossimPleiadesDimapSupportData::parseProcessingInformation";
+
+      vector<ossimRefPtr<ossimXmlNode> > xml_nodes;
+      ossimString xpath, nodeValue;
+
+      //---
+      // Fetch the Processing Level:
+      //---
+      if (theDIMAPVersion == OSSIM_PLEIADES_DIMAPv1)
+      {
+         xpath = "/Product_Characteristics/PROCESSING_LEVEL";
+      }
+      else
+      {
+         xpath = "/Processing_Information/Product_Settings/PROCESSING_LEVEL";
+      }
+      xpath = theXmlDocumentRoot + xpath;
+      if (!readOneXmlNode(xmlDocument, xpath, theProcessingLevelString))
+      {
+         return false;
+      }
+
+      //---
+      // Fetch the Spectral Processing:
+      //---
+      if (theDIMAPVersion == OSSIM_PLEIADES_DIMAPv1)
+      {
+         xpath = "/Product_Characteristics/Product_Image_Characteristics/SPECTRAL_PROCESSING";
+      }
+      else
+      {
+         xpath = "/Processing_Information/Product_Settings/SPECTRAL_PROCESSING";
+      }
+      xpath = theXmlDocumentRoot + xpath;
+      if (!readOneXmlNode(xmlDocument, xpath, theSpectralProcessingString))
+      {
+         return false;
+      }
+
+      return true;
+   }
+
+   bool  ossimPleiadesDimapSupportData::parseRasterData(ossimRefPtr<ossimXmlDocument> xmlDocument)
+   {
+      static const char MODULE[] = "ossimPleiadesDimapSupportData::parseRasterData";
+      vector<ossimRefPtr<ossimXmlNode> > xml_nodes;
+      ossimString xpath, nodeValue;
+      //---
+      // Fetch if the product file is linked to one or many JP2 files:
+      //---
+      if (theDIMAPVersion == OSSIM_PLEIADES_DIMAPv1)
+      {
+         xpath = "/Product_Characteristics/Product_Image_Characteristics/Data_Access/Data_File/DATA_FILE_PATH";
+         xpath = theXmlDocumentRoot + xpath;
+         xmlDocument->findNodes(xpath, xml_nodes);
+
+         if (xml_nodes.size() > 1)
+         {
+            theMultiDataFile.setValue(true);
+         }
+      }
+      else
+      {
+         xpath = "/Raster_Data/Data_Access/DATA_FILE_TILES";
+         xpath = theXmlDocumentRoot + xpath;
+         if (!readOneXmlNode(xmlDocument, xpath, nodeValue))
+         {
+            return false;
+         }
+         theMultiDataFile.setValue(nodeValue);
+      }
+
+      //---
+      // Fetch the MegaImageSize:
+      //---
+      if (theDIMAPVersion == OSSIM_PLEIADES_DIMAPv1)
+      {
+         xpath = "/Raster_Dimensions/NCOLS";
+      }
+      else
+      {
+         xpath = "/Raster_Data/Raster_Dimensions/NCOLS";
+      }
+      xpath = theXmlDocumentRoot + xpath;
+      if (!readOneXmlNode(xmlDocument, xpath, nodeValue))
+      {
+         return false;
+      }
+      theImageSize.samp = nodeValue.toInt();
+
+      if (theDIMAPVersion == OSSIM_PLEIADES_DIMAPv1)
+      {
+         xpath = "/Raster_Dimensions/NROWS";
+      }
+      else
+      {
+         xpath = "/Raster_Data/Raster_Dimensions/NROWS";
+      }
+      xpath = theXmlDocumentRoot + xpath;
+      if (!readOneXmlNode(xmlDocument, xpath, nodeValue))
+      {
+         return false;
+      }
+      theImageSize.line = nodeValue.toInt();
+
+      if (theMultiDataFile.getBoolean())
+      {
+         //---
+         // Fetch the Number of MegaTiles:
+         //---
+         if (theDIMAPVersion == OSSIM_PLEIADES_DIMAPv1)
+         {
+            xpath = "/Raster_Dimensions/Raster_Tiles/NTILES";
+         }
+         else
+         {
+            xpath = "/Raster_Data/Raster_Dimensions/Tile_Set/NTILES";
+         }
+         xpath = theXmlDocumentRoot + xpath;
+         if (!readOneXmlNode(xmlDocument, xpath, nodeValue))
+         {
+            return false;
+         }
+         theNumberOfMegaTiles = nodeValue.toUInt32();
+
+         //---
+         // Fetch the Number of MegaTiles in X and Y:
+         //---
+         if (theDIMAPVersion == OSSIM_PLEIADES_DIMAPv1)
+         {
+            xpath = "/Raster_Dimensions/Raster_Tiles/RX_NB_OF_TILES";
+            xpath = theXmlDocumentRoot + xpath;
+            if (!readOneXmlNode(xmlDocument, xpath, nodeValue))
+            {
+               return false;
+            }
+            theNumberOfMegaTilesInRow = nodeValue.toUInt32();
+
+            xpath = "/Raster_Dimensions/Raster_Tiles/CY_NB_OF_TILES";
+            xpath = theXmlDocumentRoot + xpath;
+            if (!readOneXmlNode(xmlDocument, xpath, nodeValue))
+            {
+               return false;
+            }
+            theNumberOfMegaTilesInCol = nodeValue.toUInt32();
+         }
+         else
+         {
+           xml_nodes.clear();
+           xpath = "/Raster_Data/Raster_Dimensions/Tile_Set/Regular_Tiling/NTILES_COUNT";
+           xpath = theXmlDocumentRoot + xpath;
+           xmlDocument->findNodes(xpath, xml_nodes);
+           if (xml_nodes.size() == 0)
+           {
+              setErrorStatus();
+              if (traceDebug())
+              {
+                 ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " DEBUG: \nCould not find: " << xpath << std::endl;
+              }
+              return false;
+           }
+
+           ossimString value;
+           ossimString attribute = "ntiles_x";
+           if (!xml_nodes[0]->getAttributeValue(value, attribute))
+           {
+             attribute = "ntiles_R";
+             xml_nodes[0]->getAttributeValue(value, attribute);
+           }
+           theNumberOfMegaTilesInRow = value.toUInt32();
+
+           attribute = "ntiles_y";
+           if (!xml_nodes[0]->getAttributeValue(value, attribute))
+           {
+             attribute = "ntiles_C";
+             xml_nodes[0]->getAttributeValue(value, attribute);
+           }
+           theNumberOfMegaTilesInCol = value.toUInt32();
+         }
+
+         if (theNumberOfMegaTilesInRow * theNumberOfMegaTilesInCol != theNumberOfMegaTiles)
+         {
+            setErrorStatus();
+            if (traceDebug())
+            {
+               ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " DEBUG: \nIncoherent number of tiles: " << xpath << std::endl;
+            }
+            return false;
+         }
+
+         if (theDIMAPVersion == OSSIM_PLEIADES_DIMAPv2)
+         {
+           //---
+           // Fetch the size of MegaTiles:
+           //---
+           xml_nodes.clear();
+           xpath = "/Raster_Data/Raster_Dimensions/Tile_Set/Regular_Tiling/NTILES_SIZE";
+           xpath = theXmlDocumentRoot + xpath;
+           xmlDocument->findNodes(xpath, xml_nodes);
+           if (xml_nodes.size() == 0)
+           {
+              setErrorStatus();
+              if (traceDebug())
+              {
+                 ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " DEBUG:" << "\nCould not find: " << xpath << std::endl;
+              }
+              return false;
+           }
+
+           ossimString attribute;
+           ossimString value;
+
+           attribute = "nrows";
+           xml_nodes[0]->getAttributeValue(value, attribute);
+           theTileSize.line = value.toUInt32();
+
+           attribute = "ncols";
+           xml_nodes[0]->getAttributeValue(value, attribute);
+           theTileSize.samp = value.toUInt32();
+         }
+
+      }
+
+      //--- TODO_MSD is it useful in the case of RPC model ???
+      // We will make the RefImagePoint the zero base center of the image.  This
+      // is used by the ossimSensorModel::worldToLineSample iterative loop as
+      // the starting point.  Since the ossimSensorModel does not know of the
+      // sub image we make it zero base. (comments from spot)
+      //---
+      theRefImagePoint.line = theImageSize.line / 2.0;
+      theRefImagePoint.samp = theImageSize.samp / 2.0;
+
+      //---
+      // Fetch number of bands
+      //---
+
+      if (theDIMAPVersion == OSSIM_PLEIADES_DIMAPv1)
+      {
+         xpath = "/Raster_Dimensions/NBANDS";
+      }
+      else
+      {
+         xpath = "/Raster_Data/Raster_Dimensions/NBANDS";
+      }
+      xpath = theXmlDocumentRoot + xpath;
+      if (!readOneXmlNode(xmlDocument, xpath, nodeValue))
+      {
+         return false;
+      }
+      theNumBands = nodeValue.toUInt32();
+
+      if (traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " DEBUG:" << "\nNumber of bands: " << theNumBands << std::endl;
+      }
+
+      //---
+      // Fetch Band Display Order
+      //---
+      xml_nodes.clear();
+      if (theDIMAPVersion == OSSIM_PLEIADES_DIMAPv1)
+      {
+         xpath = "/Product_Characteristics/Product_Image_Characteristics/Image_Display_Order/RED_CHANNEL";
+      }
+      else
+      {
+         xpath = "/Raster_Data/Raster_Display/Band_Display_Order/RED_CHANNEL";
+      }
+      xpath = theXmlDocumentRoot + xpath;
+      xmlDocument->findNodes(xpath, xml_nodes);
+      if (xml_nodes.size() == 0)
+      {
+         setErrorStatus();
+         if (traceDebug())
+         {
+            ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " DEBUG:" << "\nCould not find: " << xpath << std::endl;
+         }
+         return false;
+      }
+      theBandOrder.push_back(xml_nodes[0]->getText());
+
+      if (theNumBands > 1)
+      {
+         xml_nodes.clear();
+         if (theDIMAPVersion == OSSIM_PLEIADES_DIMAPv1)
+         {
+            xpath = "/Product_Characteristics/Product_Image_Characteristics/Image_Display_Order/GREEN_CHANNEL";
+         }
+         else
+         {
+            xpath = "/Raster_Data/Raster_Display/Band_Display_Order/GREEN_CHANNEL";
+         }
+         xpath = theXmlDocumentRoot + xpath;
+         xmlDocument->findNodes(xpath, xml_nodes);
+         if (xml_nodes.size() == 0)
+         {
+            setErrorStatus();
+            if (traceDebug())
+            {
+               ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " DEBUG:" << "\nCould not find: " << xpath << std::endl;
+            }
+            return false;
+         }
+         theBandOrder.push_back(xml_nodes[0]->getText());
+
+         xml_nodes.clear();
+         if (theDIMAPVersion == OSSIM_PLEIADES_DIMAPv1)
+         {
+            xpath = "/Product_Characteristics/Product_Image_Characteristics/Image_Display_Order/BLUE_CHANNEL";
+         }
+         else
+         {
+            xpath = "/Raster_Data/Raster_Display/Band_Display_Order/BLUE_CHANNEL";
+         }
+         xpath = theXmlDocumentRoot + xpath;
+         xmlDocument->findNodes(xpath, xml_nodes);
+         if (xml_nodes.size() == 0)
+         {
+            setErrorStatus();
+            if (traceDebug())
+            {
+               ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " DEBUG:" << "\nCould not find: " << xpath << std::endl;
+            }
+            return false;
+         }
+         theBandOrder.push_back(xml_nodes[0]->getText());
+
+         if (theNumBands > 3)
+         {
+            xml_nodes.clear();
+            if (theDIMAPVersion == OSSIM_PLEIADES_DIMAPv1)
+            {
+               xpath = "/Product_Characteristics/Product_Image_Characteristics/Image_Display_Order/ALPHA_CHANNEL";
+            }
+            else
+            {
+               xpath = "/Raster_Data/Raster_Display/Band_Display_Order/ALPHA_CHANNEL";
+            }
+            xpath = theXmlDocumentRoot + xpath;
+            xmlDocument->findNodes(xpath, xml_nodes);
+            if (xml_nodes.size() == 0)
+            {
+               setErrorStatus();
+               if (traceDebug())
+               {
+                  ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " DEBUG:" << "\nCould not find: " << xpath << std::endl;
+               }
+               return false;
+            }
+
+            theBandOrder.push_back(xml_nodes[0]->getText());
+         }
+      }
+
+      return true;
+   }
+
+   bool  ossimPleiadesDimapSupportData::parseGeometricData(ossimRefPtr<ossimXmlDocument> xmlDocument)
+   {
+      ossimString xpath, nodeValue;
+      vector<ossimRefPtr<ossimXmlNode> > xml_nodes;
+
+      xml_nodes.clear();
+      if (theDIMAPVersion == OSSIM_PLEIADES_DIMAPv1)
+      {
+         xpath = "/Data_Strip/Geometric_Header_List/Located_Geometric_Header";
+      }
+      else
+      {
+         xpath = "/Geometric_Data/Use_Area/Located_Geometric_Values";
+      }
+      xpath = theXmlDocumentRoot + xpath;
+      xmlDocument->findNodes(xpath, xml_nodes);
+      if (xml_nodes.size() != 3 )
+      {
+         setErrorStatus();
+         if(traceDebug())
+         {
+            ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG:\nCould not find: " << xpath << std::endl;
+         }
+         return false;
+      }
+
+      std::vector<ossimRefPtr<ossimXmlNode> >::iterator node = xml_nodes.begin();
+      while (node != xml_nodes.end())
+      {
+         std::vector<ossimRefPtr<ossimXmlNode> > sub_nodes;
+
+         //---
+         // Fetch the Sun Azimuth:
+         //---
+         xpath = "Solar_Incidences/SUN_AZIMUTH";
+         (*node)->findChildNodes(xpath, sub_nodes);
+         if (sub_nodes.size() == 0)
+         {
+            setErrorStatus();
+            if(traceDebug())
+            {
+               ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG:\nCould not find: " << xpath << std::endl;
+            }
+            return false;
+         }
+         theSunAzimuth.push_back(sub_nodes[0]->getText().toDouble());
+
+         //---
+         // Fetch the Sun Elevation:
+         //---
+         sub_nodes.clear();
+         xpath = "Solar_Incidences/SUN_ELEVATION";
+         (*node)->findChildNodes(xpath, sub_nodes);
+         if (sub_nodes.size() == 0)
+         {
+            setErrorStatus();
+            if(traceDebug())
+            {
+               ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG:\nCould not find: " << xpath << std::endl;
+            }
+            return false;
+         }
+         theSunElevation.push_back(sub_nodes[0]->getText().toDouble());
+
+         //---
+         // Fetch the Incidence Angle:
+         //---
+         sub_nodes.clear();
+
+         if (theDIMAPVersion == OSSIM_PLEIADES_DIMAPv1)
+         {
+            xpath = "Incidences/GLOBAL_INCIDENCE";
+         }
+         else
+         {
+            xpath = "Acquisition_Angles/INCIDENCE_ANGLE";
+         }
+         (*node)->findChildNodes(xpath, sub_nodes);
+         if (sub_nodes.size() == 0)
+         {
+            setErrorStatus();
+            if(traceDebug())
+            {
+               ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG:\nCould not find: " << xpath << std::endl;
+            }
+            return false;
+         }
+         theIncidenceAngle.push_back(sub_nodes[0]->getText().toDouble());
+
+         //---
+         // Fetch the Viewing Angle:
+         //---
+         sub_nodes.clear();
+         if (theDIMAPVersion == OSSIM_PLEIADES_DIMAPv1)
+         {
+            xpath = "Pointing_Angles/PSI_XY";
+         }
+         else
+         {
+            xpath = "Acquisition_Angles/VIEWING_ANGLE";
+         }
+         (*node)->findChildNodes(xpath, sub_nodes);
+         if (sub_nodes.size() == 0)
+         {
+            setErrorStatus();
+            if(traceDebug())
+            {
+               ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG:\nCould not find: " << xpath << std::endl;
+            }
+            return false;
+         }
+         theViewingAngle.push_back(sub_nodes[0]->getText().toDouble());
+
+         //---
+         // Fetch the Azimuth Angle:
+         //---
+         sub_nodes.clear();
+         if (theDIMAPVersion == OSSIM_PLEIADES_DIMAPv1)
+         {
+            xpath = "ORIENTATION";
+         }
+         else
+         {
+            xpath = "Acquisition_Angles/AZIMUTH_ANGLE";
+         }
+         (*node)->findChildNodes(xpath, sub_nodes);
+         if (sub_nodes.size() == 0)
+         {
+            setErrorStatus();
+            if(traceDebug())
+            {
+               ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG:\nCould not find: " << xpath << std::endl;
+            }
+            return false;
+         }
+         theAzimuthAngle.push_back(sub_nodes[0]->getText().toDouble());
+
+         //---
+         // Fetch the along track incidence angle :
+         //---
+         sub_nodes.clear();
+         if (theDIMAPVersion == OSSIM_PLEIADES_DIMAPv1)
+         {
+            xpath = "Incidences/ALONG_TRACK_INCIDENCE";
+         }
+         else
+         {
+            xpath = "Acquisition_Angles/INCIDENCE_ANGLE_ALONG_TRACK";
+         }
+         (*node)->findChildNodes(xpath, sub_nodes);
+         if (sub_nodes.size() == 0)
+         {
+            setErrorStatus();
+            if(traceDebug())
+            {
+               ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG:\nCould not find: " << xpath << std::endl;
+            }
+            return false;
+         }
+         theAlongTrackIncidenceAngle.push_back(sub_nodes[0]->getText().toDouble());
+
+         //---
+         // Fetch the across track incidence angle :
+         //---
+         sub_nodes.clear();
+         if (theDIMAPVersion == OSSIM_PLEIADES_DIMAPv1)
+         {
+            xpath = "Incidences/ORTHO_TRACK_INCIDENCE";
+         }
+         else
+         {
+            xpath = "Acquisition_Angles/INCIDENCE_ANGLE_ACROSS_TRACK";
+         }
+         (*node)->findChildNodes(xpath, sub_nodes);
+         if (sub_nodes.size() == 0)
+         {
+            setErrorStatus();
+            if(traceDebug())
+            {
+               ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG:\nCould not find: " << xpath << std::endl;
+            }
+            return false;
+         }
+         theAcrossTrackIncidenceAngle.push_back(sub_nodes[0]->getText().toDouble());
+
+         ++node;
+      }
+      
+      if (theProcessingLevelString == "SENSOR")
+      {
+        // check that this product is SENSOR (some tags are not present in ORTHO)
+        //---
+        // Fetch the time stamp of the first line:
+        //---
+        if (theDIMAPVersion == OSSIM_PLEIADES_DIMAPv1)
+        {
+          xpath = "/Geometric_Data/Sensor_Model_Characteristics/UTC_Sensor_Model_Range/START";
+        }
+        else
+        {
+          xpath = "/Geometric_Data/Refined_Model/Time/Time_Range/START";
+        }
+        xpath = theXmlDocumentRoot + xpath;
+        if (!readOneXmlNode(xmlDocument, xpath, theTimeRangeStart))
+        {
+            return false;
+        }
+        
+        //---
+        // Fetch the time stamp of the last line:
+        //---
+        if (theDIMAPVersion == OSSIM_PLEIADES_DIMAPv1)
+        {
+          xpath = "/Geometric_Data/Sensor_Model_Characteristics/UTC_Sensor_Model_Range/END";
+        }
+        else
+        {
+          xpath = "/Geometric_Data/Refined_Model/Time/Time_Range/END";
+        }
+        xpath = theXmlDocumentRoot + xpath;
+        if (!readOneXmlNode(xmlDocument, xpath, theTimeRangeEnd))
+        {
+            return false;
+        }
+        
+        //---
+        // Fetch the line period:
+        //---
+        if (theDIMAPVersion == OSSIM_PLEIADES_DIMAPv1)
+        {
+          xpath = "/Geometric_Data/Sensor_Model_Characteristics/SENSOR_LINE_PERIOD";
+        }
+        else
+        {
+          xpath = "/Geometric_Data/Refined_Model/Time/Time_Stamp/LINE_PERIOD";
+        }
+        xpath = theXmlDocumentRoot + xpath;
+        if (!readOneXmlNode(xmlDocument, xpath, nodeValue))
+        {
+            return false;
+        }
+        theLinePeriod = nodeValue.toDouble();
+        
+        //---
+        // Fetch the swath first col:
+        //---
+        if (theDIMAPVersion == OSSIM_PLEIADES_DIMAPv1)
+        {
+          xpath = "/Geometric_Data/Sensor_Model_Characteristics/Sensor_Viewing_Model/Position_In_Retina/FIRST_COL";
+        }
+        else
+        {
+          xpath = "/Geometric_Data/Refined_Model/Geometric_Calibration/Instrument_Calibration/Swath_Range/FIRST_COL";
+        }
+        xpath = theXmlDocumentRoot + xpath;
+        if (!readOneXmlNode(xmlDocument, xpath, nodeValue))
+        {
+            return false;
+        }
+        theSwathFirstCol = nodeValue.toInt32();
+        
+        //---
+        // Fetch the swath last col:
+        //---
+        if (theDIMAPVersion == OSSIM_PLEIADES_DIMAPv1)
+        {
+          xpath = "/Geometric_Data/Sensor_Model_Characteristics/Sensor_Viewing_Model/Position_In_Retina/LAST_COL";
+        }
+        else
+        {
+          xpath = "/Geometric_Data/Refined_Model/Geometric_Calibration/Instrument_Calibration/Swath_Range/LAST_COL";
+        }
+        xpath = theXmlDocumentRoot + xpath;
+        if (!readOneXmlNode(xmlDocument, xpath, nodeValue))
+        {
+            return false;
+        }
+        theSwathLastCol = nodeValue.toInt32();
+      }
+      
+      return true;
+   }
+
+   bool ossimPleiadesDimapSupportData::parseQualityAssessment(ossimRefPtr<ossimXmlDocument> /* xmlDocument */ )
+   {
+      return true;
+   }
+
+   bool ossimPleiadesDimapSupportData::parseDatasetSources(ossimRefPtr<ossimXmlDocument> xmlDocument)
+   {
+      // static const char MODULE[] = "ossimPleiadesDimapSupportData::parseDatasetSources";
+      ossimString xpath, nodeValue;
+      vector<ossimRefPtr<ossimXmlNode> > xml_nodes;
+
+      //---
+      // Fetch the mission index (1A ou 1B) ?
+      // and generate theSensorID
+      //---
+      if (theDIMAPVersion == OSSIM_PLEIADES_DIMAPv1)
+      {
+         xpath = "/Data_Strip/Data_Strip_Identification/PLATFORM_NAME";
+      }
+      else
+      {
+         xpath = "/Dataset_Sources/Source_Identification/Strip_Source/MISSION";
+      }
+      xpath = theXmlDocumentRoot + xpath;
+      if (!readOneXmlNode(xmlDocument, xpath, nodeValue))
+      {
+         return false;
+      }
+
+      if (nodeValue != "PHR")
+      {
+         setErrorStatus();
+         if (traceDebug())
+         {
+            ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG:\nNot a PHR mission!"<< std::endl;
+         }
+         return false;
+      }
+
+      //---
+      // Fetch the mission index (1A ou 1B) ?
+      // and generate theSensorID
+      //---
+      if (theDIMAPVersion == OSSIM_PLEIADES_DIMAPv1)
+      {
+         xpath = "/Data_Strip/Data_Strip_Identification/PLATFORM_SERIAL_NUMBER";
+      }
+      else
+      {
+         xpath = "/Dataset_Sources/Source_Identification/Strip_Source/MISSION_INDEX";
+      }
+      xpath = theXmlDocumentRoot + xpath;
+      if (!readOneXmlNode(xmlDocument, xpath, nodeValue))
+      {
+         return false;
+      }
+
+      if (nodeValue == "1A")
+         theSensorID = "PHR 1A";
+      else if (nodeValue == "1B")
+         theSensorID = "PHR 1B";
+      else
+      {
+         setErrorStatus();
+         if (traceDebug())
+         {
+            ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG:\nNot a valid sensorID!"<< std::endl;
+         }
+         return false;
+      }
+
+      //---
+      // Fetch the Instrument:
+      //---
+      if (theDIMAPVersion == OSSIM_PLEIADES_DIMAPv1)
+      {
+         xpath = "/Data_Strip/Data_Strip_Identification/PLATFORM_NAME";
+      }
+      else
+      {
+         xpath = "/Dataset_Sources/Source_Identification/Strip_Source/INSTRUMENT";
+      }
+      xpath = theXmlDocumentRoot + xpath;
+      if (!readOneXmlNode(xmlDocument, xpath, theInstrument))
+      {
+         return false;
+      }
+
+      //---
+      // Fetch the Instrument Index:
+      //---
+      if (theDIMAPVersion == OSSIM_PLEIADES_DIMAPv1)
+      {
+         xpath = "/Data_Strip/Data_Strip_Identification/PLATFORM_SERIAL_NUMBER";
+      }
+      else
+      {
+         xpath = "/Dataset_Sources/Source_Identification/Strip_Source/INSTRUMENT_INDEX";
+      }
+      xpath = theXmlDocumentRoot + xpath;
+      if (!readOneXmlNode(xmlDocument, xpath, theInstrumentIndex))
+      {
+         return false;
+      }
+
+      if (theDIMAPVersion == OSSIM_PLEIADES_DIMAPv1)
+      {
+        //---
+        // Fetch the Imaging Date:
+        //---
+        xpath = "/Data_Strip/UTC_Acquisition_Range/START";
+        xpath = theXmlDocumentRoot + xpath;
+        if (!readOneXmlNode(xmlDocument, xpath, theAcquisitionDate))
+        {
+           return false;
+        }
+        
+        // TODO : fetch (if any in v1) the other acquisition time parameters
+        
+      }
+      else
+      {
+        //---
+        // Fetch the Imaging Date:
+        //---
+        ossimString firstLineImagingDate;
+        xpath = "/Dataset_Sources/Source_Identification/Strip_Source/IMAGING_DATE";
+        xpath = theXmlDocumentRoot + xpath;
+        if (!readOneXmlNode(xmlDocument, xpath, firstLineImagingDate))
+        {
+           return false;
+        }
+
+        //---
+        // Fetch the Imaging Time:
+        //---
+        ossimString firstLineImagingTime;
+        xpath = "/Dataset_Sources/Source_Identification/Strip_Source/IMAGING_TIME";
+        xpath = theXmlDocumentRoot + xpath;
+        if (!readOneXmlNode(xmlDocument, xpath, firstLineImagingTime))
+        {
+           return false;
+        }
+
+        theAcquisitionDate = firstLineImagingDate + "T" + firstLineImagingTime;
+        
+      }
+
+      return true;
+   }
+
+}
+
diff --git a/ossim_plugins/ossim/ossimPleiadesDimapSupportData.h b/ossim_plugins/ossim/ossimPleiadesDimapSupportData.h
new file mode 100644
index 0000000..c3965a9
--- /dev/null
+++ b/ossim_plugins/ossim/ossimPleiadesDimapSupportData.h
@@ -0,0 +1,374 @@
+//*******************************************************************
+// Copyright (C) 2012  Centre National Etudes Spatiales
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 3 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+//
+// Author : Mickael Savinaud (mickael.savinaud at c-s.fr)
+//
+// Description:
+//
+// Contains declaration of class ossimPleiadesDimapSupportData
+//
+//*****************************************************************************
+#ifndef ossimPleiadesDimapSupportData_HEADER
+#define ossimPleiadesDimapSupportData_HEADER
+
+#include <ossimPluginConstants.h>
+
+#include <ossim/base/ossimConstants.h>
+#include <ossim/base/ossimIpt.h>
+#include <ossim/base/ossimObject.h>
+#include <ossim/base/ossimString.h>
+
+#include <ossim/base/ossimErrorStatusInterface.h>
+
+#include <ossim/base/ossimBooleanProperty.h>
+#include <ossim/base/ossimFilename.h>
+
+#include <ossim/base/ossimRefPtr.h>
+#include <ossim/base/ossimDpt.h>
+#include <ossim/base/ossimDpt3d.h>
+#include <ossim/base/ossimDrect.h>
+#include <ossim/base/ossimGpt.h>
+
+
+#include <vector>
+#include <iostream>
+
+
+class ossimKeywordlist;
+class ossimXmlDocument;
+
+namespace ossimplugins
+{
+   class OSSIM_PLUGINS_DLL ossimPleiadesDimapSupportData : public ossimObject,
+      public ossimErrorStatusInterface
+      {
+      public:
+         enum ossimPleiadesDIMAPVersion
+         {
+            OSSIM_PLEIADES_UNKNOWN,
+            OSSIM_PLEIADES_DIMAPv1,
+            OSSIM_PLEIADES_DIMAPv2
+         };
+
+         /** metadata subprofile type */
+         enum ossimPleiadesMetadataSubProfile
+         {
+            OSSIM_PLEIADES_METADATA_SUBPROFILE_UNKNOWN = 0,
+            OSSIM_PLEIADES_METADATA_SUBPROFILE_PRODUCT = 1,
+            OSSIM_PLEIADES_METADATA_SUBPROFILE_RPC = 2
+         };
+
+         ossimPleiadesDimapSupportData();
+
+         virtual ~ossimPleiadesDimapSupportData();
+
+         void clearFields();
+
+         bool parseXmlFile(const ossimFilename& file);
+
+         //---
+         // Convenient method to print important image info:
+         //---
+         void  printInfo (ostream& os) const;
+
+         /**
+          * Method to save the state of the object to a keyword list.
+          * Return true if ok or false on error.
+          */
+         virtual bool saveState(ossimKeywordlist& kwl,
+                                const char* prefix = 0)const;
+         /**
+          * Method to the load (recreate) the state of the object from a keyword
+          * list.  Return true if ok or false on error.
+          */
+         virtual bool loadState(const ossimKeywordlist& kwl,
+                                const char* prefix = 0);
+
+         ossimString   getSensorID()                            const;
+         ossimString   getProcessingLevel()                     const;
+         ossimString   getAcquisitionDate()                     const;
+         ossimString   getProductionDate()                      const;
+         ossimString   getImageID()                             const;
+         ossimString   getInstrument()                          const;
+         ossimString   getInstrumentIndex()                     const;
+
+         ossim_uint32  getNumberOfBands()                       const;
+         void          getSunAzimuth(std::vector<ossim_float64>& az)         const;
+         void          getSunElevation(std::vector<ossim_float64>& el)       const;
+         void          getImageSize(ossimIpt& sz)               const;
+
+         void          getIncidenceAngle(std::vector<ossim_float64>& ia)     const;
+         void          getViewingAngle(std::vector<ossim_float64>& va)       const;
+
+         //Along and across track incidence angle
+         void getAcrossTrackIncidenceAngle(std::vector<ossim_float64>& act) const;
+         void getAlongTrackIncidenceAngle(std::vector<ossim_float64>& alt) const;
+
+         //---
+         // Corner points:
+         //---
+         void getUlCorner(ossimGpt& pt) const;
+         void getUrCorner(ossimGpt& pt) const;
+         void getLrCorner(ossimGpt& pt) const;
+         void getLlCorner(ossimGpt& pt) const;
+
+         //---
+         // Image center point:
+         //---
+
+         /** Center of frame, sub image if there is one. */
+         void getRefGroundPoint(ossimGpt& gp)         const;
+
+         /** zero base center point */
+         void getRefImagePoint(ossimDpt& rp)          const;
+
+         /** Zero based image rectangle, sub image if there is one. */
+         void getImageRect(ossimDrect& rect)const;
+
+         bool allMetadataRead(){return (theProductIsOk && theRpcIsOk);};
+
+         std::vector<double> getLineNumCoeff() const {return theLineNumCoeff;};
+         std::vector<double> getLineDenCoeff() const {return theLineDenCoeff;};
+         std::vector<double> getSampNumCoeff() const {return theSampNumCoeff;};
+         std::vector<double> getSampDenCoeff() const {return theSampDenCoeff;};
+
+         ossim_int32 getLineOffset() const {return theLineOffset;};
+         ossim_int32 getSampOffset() const {return theSampOffset;};
+         double getLatOffset()       const {return theLatOffset;};
+         double getLonOffset()       const {return theLonOffset;};
+         double getHeightOffset()    const {return theHeightOffset;};
+         double getLineScale()       const {return theLineScale;};
+         double getSampScale()       const {return theSampScale;};
+         double getLatScale()        const {return theLatScale;};
+         double getLonScale()        const {return theLonScale;};
+         double getHeightScale()     const {return theHeightScale;};
+         
+         
+         ossimString    getTimeRangeStart() const {return theTimeRangeStart;};
+         ossimString    getTimeRangeEnd()   const {return theTimeRangeEnd;};
+         ossim_float64  getLinePeriod()     const {return theLinePeriod;};
+         ossim_int32    getSwathFirstCol()  const {return theSwathFirstCol;};
+         ossim_int32    getSwathLastCol()   const {return theSwathLastCol;}; 
+
+
+      private:
+         ossimPleiadesDIMAPVersion theDIMAPVersion;
+         ossimPleiadesMetadataSubProfile theMetadataSubProfile; // only for DIMAPv2
+         bool theProductIsOk;
+         bool theRpcIsOk;
+         ossimString theXmlDocumentRoot;
+
+         ossimString                 theSensorID;
+         ossimString                 theImageID;
+         ossimString                 theProductionDate;
+         ossimString                 theAcquisitionDate;
+         ossimString                 theInstrument;
+         ossimString                 theInstrumentIndex;
+         ossimString                 theProcessingLevelString;
+         ossimString                 theSpectralProcessingString;
+
+         std::vector<ossim_float64>  theSunAzimuth;
+         std::vector<ossim_float64>  theSunElevation;
+         std::vector<ossim_float64>  theIncidenceAngle;
+         std::vector<ossim_float64>  theViewingAngle;
+         std::vector<ossim_float64>  theAzimuthAngle;
+
+         std::vector<ossim_float64> theAlongTrackIncidenceAngle;
+         std::vector<ossim_float64> theAcrossTrackIncidenceAngle;
+   
+         ossimIpt                    theImageSize;
+         ossimIpt                    theTileSize;
+         ossim_uint32                theNumberOfMegaTilesInRow;
+         ossim_uint32                theNumberOfMegaTilesInCol;
+         ossim_uint32                theNumberOfMegaTiles;
+         ossimBooleanProperty        theMultiDataFile;
+
+         ossim_uint32                theNumBands;
+         std::vector<ossimString>    theBandOrder;
+
+         /** Calibration information for radiometric corrections*/
+         std::vector<ossim_float64> thePhysicalBias;
+         std::vector<ossim_float64> thePhysicalGain;
+         std::vector<ossim_float64> theSolarIrradiance;
+
+         //---
+         // Corner points:
+         //---
+         ossimGpt theUlCorner;
+         ossimGpt theUrCorner;
+         ossimGpt theLrCorner;
+         ossimGpt theLlCorner;
+
+         // RPC parameters
+         ossimString theSpecId;
+         double    theErrBias;
+         double    theErrBiasX;
+         double    theErrBiasY;
+         double    theErrRand;
+         double    theLineOffset;
+         double    theSampOffset;
+         double    theLatOffset;
+         double    theLonOffset;
+         double    theHeightOffset;
+         double    theLineScale;
+         double    theSampScale;
+         double    theLatScale;
+         double    theLonScale;
+         double    theHeightScale;
+
+         std::vector<double> theLineNumCoeff;
+         std::vector<double> theLineDenCoeff;
+         std::vector<double> theSampNumCoeff;
+         std::vector<double> theSampDenCoeff;
+         
+         // Additional metadata used to enhance pansharpening
+         ossimString    theTimeRangeStart;
+         ossimString    theTimeRangeEnd;
+         ossim_float64  theLinePeriod;
+         ossim_int32    theSwathFirstCol;
+         ossim_int32    theSwathLastCol;
+         
+
+
+         //--- TODO MSD Check if it is necessary to keep that
+         /** Center of frame on ground, if sub image it's the center of that. */
+         ossimGpt                    theRefGroundPoint;
+
+         /** Zero based center of frame. */
+         ossimDpt                    theRefImagePoint;
+
+
+         ossimGpt createGround(const ossimString& s)const;
+         ossimDpt createDpt(const ossimString& s)const;
+         ossimIpt createIpt(const ossimString& s)const;
+         //---
+
+         bool parseRPCMetadata(ossimRefPtr<ossimXmlDocument> xmlDocument);
+
+         bool parseMetadataIdentificationDIMAPv1(ossimRefPtr<ossimXmlDocument> xmlDocument);
+         bool parseMetadataIdentificationDIMAPv2(ossimRefPtr<ossimXmlDocument> xmlDocument);
+
+         /**
+          * Dataset Identification:
+          *
+          * From xml section:
+          * /Dimap_Document/Dataset_Identification/
+          *
+          * NOT YET USED
+          *
+          * @return true.
+          */
+         bool parseDatasetIdentification(ossimRefPtr<ossimXmlDocument> xmlDocument);
+
+         /**
+          * Dataset Content:
+          *
+          * From xml section:
+          * /Dimap_Document/Dataset_Content/
+          *
+          * Initializes:
+          * theRefGroundPoint
+          * theUlCorner
+          * theUrCorner
+          * theLrCorner
+          * theLlCorner
+          *
+          * Note that the theRefGroundPoint will be the zero based center of
+          * the whole mega image.
+          * Note that the corners will be the corners of the whole mega image.
+          * @return true on success, false if not found.
+          */
+         bool parseDatasetContent(ossimRefPtr<ossimXmlDocument> xmlDocument);
+
+         /**
+          * Product Information:
+          *
+          * From xml section:
+          * /Dimap_Document/Product_Information/
+          *
+          * Initializes:
+          * theImageID
+          * theProductionDate
+          *
+          * @return true on success, false if not found.
+          */
+         bool parseProductInformation(ossimRefPtr<ossimXmlDocument> xmlDocument);
+
+         /**
+          * Coordinate Reference System:
+          *
+          * From xml section:
+          * /Dimap_Document/Coordinate_Reference_System/
+          *
+          * NOT YET USED
+          *
+          * @return true.
+          */
+         bool parseCoordinateReferenceSystem(ossimRefPtr<ossimXmlDocument> xmlDocument);
+
+         /**
+          * Geoposition:
+          *
+          * From xml section:
+          * /Dimap_Document/Geoposition/
+          *
+          * NOT YET USED
+          *
+          * @return true.
+          */
+         bool parseGeoposition(ossimRefPtr<ossimXmlDocument> xmlDocument);
+
+         /**
+          * Processing Information:
+          *
+          * From xml section:
+          * /Dimap_Document/Processing_Information/
+          *
+          * Initializes:
+          * theProcessingLevel
+          * theSpectralProcessing
+          *
+          * @return true on success, false if not found.
+          */
+         bool parseProcessingInformation(ossimRefPtr<ossimXmlDocument> xmlDocument);
+
+         bool parseRasterData(ossimRefPtr<ossimXmlDocument> xmlDocument);
+
+         bool parseRadiometricData(ossimRefPtr<ossimXmlDocument> xmlDocument);
+
+         bool parseGeometricData(ossimRefPtr<ossimXmlDocument> xmlDocument);
+
+         /**
+          * QualityAssessment:
+          *
+          * From xml section:
+          * /Dimap_Document/Quality_Assessment/
+          *
+          * NOT YET USED
+          *
+          * @return true.
+          */
+         bool parseQualityAssessment(ossimRefPtr<ossimXmlDocument> xmlDocument);
+
+         bool parseDatasetSources(ossimRefPtr<ossimXmlDocument> xmlDocument);
+
+
+
+      };
+}
+#endif /* #ifndef ossimPleiadesDimapSupportData_HEADER */
+
diff --git a/ossim_plugins/ossim/ossimPleiadesModel.cpp b/ossim_plugins/ossim/ossimPleiadesModel.cpp
new file mode 100644
index 0000000..5613391
--- /dev/null
+++ b/ossim_plugins/ossim/ossimPleiadesModel.cpp
@@ -0,0 +1,385 @@
+//*******************************************************************
+// Copyright (C) 2012  Centre National Etudes Spatiales
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 3 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+//
+// Author : Mickael Savinaud (mickael.savinaud at c-s.fr)
+//
+// Description:
+//
+// Contains definition of class ossimPleiadesModel
+//
+//*****************************************************************************
+
+#include "ossimPleiadesModel.h"
+
+#include <cmath>
+#include <cstdio>
+
+#include <ossimPleiadesModel.h>
+#include <ossimPleiadesDimapSupportData.h>
+
+#include <ossimPluginCommon.h>
+
+#include <ossim/base/ossimCommon.h>
+#include <ossim/base/ossimFilename.h>
+#include <ossim/base/ossimKeywordNames.h>
+#include <ossim/base/ossimNotify.h>
+#include <ossim/base/ossimRefPtr.h>
+#include <ossim/base/ossimString.h>
+#include <ossim/base/ossimTrace.h>
+#include <ossim/base/ossimXmlDocument.h>
+#include <ossim/base/ossimXmlNode.h>
+#include <ossim/support_data/ossimSupportFilesList.h>
+
+
+namespace ossimplugins
+{
+
+// Define Trace flags for use within this file:
+   static ossimTrace traceExec  ("ossimPleiadesModel:exec");
+   static ossimTrace traceDebug ("ossimPleiadesModel:debug");
+
+
+   RTTI_DEF1(ossimPleiadesModel, "ossimPleiadesModel", ossimRpcModel);
+
+//*************************************************************************************************
+// Constructor
+//*************************************************************************************************
+   ossimPleiadesModel::ossimPleiadesModel()
+      :ossimRpcModel      (),
+       theSupportData        (0)
+   {
+      for (unsigned int i = 0; i < 20; i++)
+      {
+         theLineDenCoef[i] = 0.0;
+         theLineNumCoef[i] = 0.0;
+         theSampNumCoef[i] = 0.0;
+         theSampDenCoef[i] = 0.0;
+      }
+   }
+
+//*************************************************************************************************
+// Constructor
+//*************************************************************************************************
+   ossimPleiadesModel::ossimPleiadesModel(const ossimPleiadesModel& rhs)
+      :ossimRpcModel      (rhs),
+       theSupportData        (0)
+   {
+   }
+
+//*************************************************************************************************
+// Destructor
+//*************************************************************************************************
+   ossimPleiadesModel::~ossimPleiadesModel()
+   {
+      if (traceExec())  ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG DESTRUCTOR: ~ossimPleiadesModel(): entering..." << std::endl;
+
+      theSupportData = 0;
+
+      if (traceExec())  ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG DESTRUCTOR: ~ossimPleiadesModel(): returning..." << std::endl;
+   }
+//*************************************************************************************************
+// Infamous DUP
+//*************************************************************************************************
+   ossimObject* ossimPleiadesModel::dup() const
+   {
+      return new ossimPleiadesModel(*this);
+   }
+
+//*************************************************************************************************
+// Print
+//*************************************************************************************************
+   std::ostream& ossimPleiadesModel::print(std::ostream& out) const
+   {
+      // Capture stream flags since we are going to mess with them.
+      std::ios_base::fmtflags f = out.flags();
+
+      out << "\nDump of ossimPleiadesModel at address " << (hex) << this
+          << (dec)
+          << "\n------------------------------------------------"
+          << "\n  theImageID            = " << theImageID
+          << "\n  theImageSize          = " << theImageSize
+          << "\n  theRefGndPt           = " << theRefGndPt
+          << "\n  theRefImgPt           = " << theRefImgPt
+          << "\n  theProcessingLevel    = " << theSupportData->getProcessingLevel()
+          << "\n------------------------------------------------"
+          << "\n  " << endl;
+
+      // Set the flags back.
+      out.flags(f);
+
+      if (theSupportData->getProcessingLevel() == "SENSOR")
+         return ossimRpcModel::print(out);
+      else
+         return out;
+   }
+
+//*************************************************************************************************
+// Save State
+//*************************************************************************************************
+   bool ossimPleiadesModel::saveState(ossimKeywordlist& kwl,
+                                      const char* prefix) const
+   {
+      if(theSupportData.valid())
+      {
+         ossimString supportPrefix = ossimString(prefix) + "support_data.";
+         theSupportData->saveState(kwl, supportPrefix);
+      }
+
+      // If only it is a sensor product we save parameters from RPC model, its avoid to
+      // propagate a empty RPC model
+      if (theSupportData->getProcessingLevel() == "SENSOR")
+      {
+         ossimRpcModel::saveState(kwl, prefix);
+         return true;
+      }
+      else
+      {
+         kwl.add(prefix, "sensor", theSensorID, true);
+         return true;
+      }
+   }
+
+//*************************************************************************************************
+// Load State
+//*************************************************************************************************
+   bool ossimPleiadesModel::loadState(const ossimKeywordlist& kwl,
+                                      const char* prefix)
+   {
+      if(!theSupportData)
+      {
+         theSupportData = new ossimPleiadesDimapSupportData;
+      }
+
+      ossimString supportPrefix = ossimString(prefix) + "support_data.";
+      theSupportData->loadState(kwl, supportPrefix);
+
+      // If only it is a sensor product we load parameters from RPC model only, its avoid to
+      // add a empty RPC model
+      if (theSupportData->getProcessingLevel() == "SENSOR")
+      {
+         ossimRpcModel::loadState(kwl, prefix);
+         return true;
+      }
+      else
+      {
+         return true;
+      }
+   }
+
+
+
+   bool
+   ossimPleiadesModel::open(const ossimFilename& file)
+   {
+      static const char MODULE[] = "ossimPleiadesModel::open";
+      //traceDebug.setTraceFlag(true);
+
+      if (traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " entered...\n";
+      }
+
+      // Make the gsd nan so it gets computed.
+      theGSD.makeNan();
+
+      bool result = false;
+
+      // Filename used.
+      ossimFilename DIMxmlFile;
+      ossimFilename RPCxmlFile;
+
+      // Generate metadata and rpc filename
+      if ( (file.ext().downcase() != "jp2" && file.ext().downcase() != "tif")
+          || !file.exists())
+      {
+         //not a valid file
+         return false;
+      }
+      else
+      {
+        // DIMAPv1
+        ossimFilename DIMv1xmlFileTmp = file;
+        DIMv1xmlFileTmp.setFile("PHRDIMAP");
+        DIMv1xmlFileTmp.setExtension("XML");
+
+        if (DIMv1xmlFileTmp.exists())
+          {
+          DIMxmlFile = DIMv1xmlFileTmp;
+          RPCxmlFile = DIMv1xmlFileTmp;
+          }
+        else
+          {
+          // DIMAPv2
+          DIMxmlFile = file.path();
+          RPCxmlFile = file.path();
+          ossimFilename DIMxmlFileTmp = file.file();
+          ossimFilename RPCxmlFileTmp;
+
+          DIMxmlFileTmp = DIMxmlFileTmp.file().replaceStrThatMatch("^IMG_", "DIM_");
+          DIMxmlFileTmp = DIMxmlFileTmp.replaceStrThatMatch("_R[0-9]+C[0-9]+\\.(JP2|TIF)$", ".XML");
+          // Check if it is an XML extension
+          if( DIMxmlFileTmp.ext() != "XML")
+            return false;
+
+          RPCxmlFileTmp = DIMxmlFileTmp.file().replaceStrThatMatch("^DIM_", "RPC_");
+
+          DIMxmlFile = DIMxmlFile.dirCat(DIMxmlFileTmp);
+          RPCxmlFile = RPCxmlFile.dirCat(RPCxmlFileTmp);
+          }
+
+        if (!DIMxmlFile.exists())
+        {
+          if (traceDebug())
+          {
+            ossimNotify(ossimNotifyLevel_DEBUG) << "PHR main DIMAP file " << DIMxmlFile << " doesn't exist ...\n";
+          }
+          return false;
+        }
+      }
+
+      if (traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG) << "Metadata xml file: " << DIMxmlFile << "\n";
+         ossimNotify(ossimNotifyLevel_DEBUG) << "RPC xml file: " << RPCxmlFile << "\n";
+      }
+
+      ossimString processingLevel;
+      // Parse the metadata xml file
+      if ( !theSupportData.valid() )
+         theSupportData = new ossimPleiadesDimapSupportData();
+
+      if(!theSupportData->parseXmlFile(DIMxmlFile))
+      {
+         theSupportData = 0; // ossimRefPtr
+         if (traceDebug())
+         {
+           ossimNotify(ossimNotifyLevel_DEBUG) << "ossimPleiadesModel::open DEBUG:"
+                                               << "\nCould not open correctly DIMAP file" << std::endl;
+         }
+         return false;
+      }
+
+      theSensorID = theSupportData->getSensorID();
+      theImageID = theSupportData->getImageID();
+      // Get the processing level (ORTHO or SENSOR or perhaps MOSAIC ?)
+      processingLevel = theSupportData->getProcessingLevel();
+
+      // Parse the RPC xml file if necessary
+      if (RPCxmlFile.exists() && processingLevel == "SENSOR")
+      {
+         if (!theSupportData->parseXmlFile(RPCxmlFile))
+         {
+            theSupportData = 0; // ossimRefPtr
+            ossimNotify(ossimNotifyLevel_WARN) << "ossimPleiadesModel::open WARNING:"
+                                               << "\nCould not open correctly RPC file" << std::endl;
+            return false;
+         }
+
+         thePolyType = B;
+
+         for (unsigned int i = 0 ; i < 20; i++ )
+         {
+            theLineNumCoef[i] = theSupportData->getLineNumCoeff()[i];
+            theLineDenCoef[i] = theSupportData->getLineDenCoeff()[i];
+            theSampNumCoef[i] = theSupportData->getSampNumCoeff()[i];
+            theSampDenCoef[i] = theSupportData->getSampDenCoeff()[i];
+         }
+
+         theLineScale  = theSupportData->getLineScale();
+         theSampScale  = theSupportData->getSampScale();
+         theLatScale   = theSupportData->getLatScale();
+         theLonScale   = theSupportData->getLonScale();
+         theHgtScale   = theSupportData->getHeightScale();
+         theLineOffset = theSupportData->getLineOffset();
+         theSampOffset = theSupportData->getSampOffset();
+         theLatOffset  = theSupportData->getLatOffset();
+         theLonOffset  = theSupportData->getLonOffset();
+         theHgtOffset  = theSupportData->getHeightOffset();
+      }
+
+      // TODO MSD Check if this part is necessary
+      _productXmlFile = DIMxmlFile;
+      ossimSupportFilesList::instance()->add(_productXmlFile);
+
+      // TODO MSD WARNING File with multi tiles are not well managed
+      theSupportData->getImageRect(theImageClipRect);
+      theSupportData->getImageSize(theImageSize);
+
+      finishConstruction();
+      clearErrorStatus();
+
+      result = true;
+      if (traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " exit status = " << (result ? "true" : "false\n") << std::endl;
+      }
+
+      /*std::cout << "---------------------------" << std::endl;
+        print(std::cout);
+        std::cout << "---------------------------" << std::endl;*/
+      return result;
+   }
+
+//*************************************************************************************************
+//! Collects common code among all parsers
+//*************************************************************************************************
+   void ossimPleiadesModel::finishConstruction()
+   {
+      theImageSize.line = theImageClipRect.height();
+      theImageSize.samp = theImageClipRect.width();
+      theRefImgPt.line = theImageClipRect.midPoint().y;
+      theRefImgPt.samp = theImageClipRect.midPoint().x;
+      theRefGndPt.lat = theLatOffset;
+      theRefGndPt.lon = theLonOffset;
+      theRefGndPt.hgt = theHgtOffset;
+
+      //---
+      // NOTE:  We must call "updateModel()" to set parameter used by base
+      // ossimRpcModel prior to calling lineSampleHeightToWorld or all
+      // the world points will be same.
+      //---
+      updateModel();
+
+      ossimGpt v0, v1, v2, v3;
+      lineSampleHeightToWorld(theImageClipRect.ul(), theHgtOffset, v0);
+      lineSampleHeightToWorld(theImageClipRect.ur(), theHgtOffset, v1);
+      lineSampleHeightToWorld(theImageClipRect.lr(), theHgtOffset, v2);
+      lineSampleHeightToWorld(theImageClipRect.ll(), theHgtOffset, v3);
+
+      theBoundGndPolygon = ossimPolygon (ossimDpt(v0), ossimDpt(v1), ossimDpt(v2), ossimDpt(v3));
+
+      // Set the ground reference point using the model.
+      lineSampleHeightToWorld(theRefImgPt, theHgtOffset, theRefGndPt);
+
+      if( theGSD.hasNans() )
+      {
+         try
+         {
+            // This will set theGSD and theMeanGSD. Method throws ossimException.
+            computeGsd();
+         }
+         catch (const ossimException& e)
+         {
+            ossimNotify(ossimNotifyLevel_WARN)
+               << "ossimPleiadesModel::finishConstruction -- caught exception:\n"
+               << e.what() << std::endl;
+         }
+      }
+   }
+
+}
+
diff --git a/ossim_plugins/ossim/ossimPleiadesModel.h b/ossim_plugins/ossim/ossimPleiadesModel.h
new file mode 100644
index 0000000..fde3f44
--- /dev/null
+++ b/ossim_plugins/ossim/ossimPleiadesModel.h
@@ -0,0 +1,114 @@
+//*******************************************************************
+// Copyright (C) 2012  Centre National Etudes Spatiales
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 3 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+//
+// Author : Mickael Savinaud (mickael.savinaud at c-s.fr)
+//
+// Description:
+//
+// Contains declaration of class ossimPleiadesModel.
+//
+//*****************************************************************************
+// FIXME $Id: ossimSpot5Model.h 15766 2009-10-20 12:37:09Z gpotts $
+#ifndef ossimPleiadesModel_HEADER
+#define ossimPleiadesModel_HEADER
+
+#include <ossimPluginConstants.h>
+
+#include <ossim/projection/ossimRpcModel.h>
+#include "ossimPleiadesDimapSupportData.h"
+
+#include <ossim/base/ossimFilename.h>
+
+#include <iostream>
+
+
+namespace ossimplugins
+{
+   class ossimPleiadesDimapSupportData;
+
+   class OSSIM_PLUGINS_DLL ossimPleiadesModel : public ossimRpcModel
+   {
+   public:
+      /*!
+       * CONSTRUCTORS:
+       */
+      /** @brief default constructor */
+      ossimPleiadesModel();
+
+      /** @brief copy constructor */
+      ossimPleiadesModel(const ossimPleiadesModel& rhs);
+
+      /** @brief Destructor */
+      virtual ~ossimPleiadesModel();
+
+      bool open(const ossimFilename& file);
+
+      /*!
+       * Returns pointer to a new instance, copy of this.
+       * Not implemented yet!  Returns NULL...
+       */
+      virtual ossimObject* dup() const;
+
+      /*!
+       * Extends base-class implementation. Dumps contents of object to ostream.
+       */
+      virtual std::ostream& print(std::ostream& out) const;
+
+      /*!
+       * Fulfills ossimObject base-class pure virtuals. Loads and saves geometry
+       * KWL files. Returns true if successful.
+       */
+      virtual bool saveState(ossimKeywordlist& kwl,
+                             const char* prefix=NULL) const;
+
+      virtual bool loadState(const ossimKeywordlist& kwl,
+                             const char* prefix=NULL);
+
+      void setSupportData(ossimPleiadesDimapSupportData* supportData)
+      {
+         theSupportData = supportData;
+      }
+      ossimPleiadesDimapSupportData* getSupportData()
+      {
+         return theSupportData.get();
+      }
+      const ossimPleiadesDimapSupportData* getSupportData()const
+      {
+         return theSupportData.get();
+      }
+
+   protected:
+
+      bool parseMetaData(const ossimFilename& file);
+
+      bool parseRpcData (const ossimFilename& file);
+
+      // In the future
+      //bool parseJP2File (const ossimFilename& file);
+
+      void finishConstruction();
+
+      ossimRefPtr<ossimPleiadesDimapSupportData> theSupportData;
+
+      ossimFilename _productXmlFile;
+
+
+      TYPE_DATA
+         };
+}
+#endif /* #ifndef ossimPleiadesModel_HEADER */
+
diff --git a/ossim_plugins/ossim/ossimPluginCommon.cpp b/ossim_plugins/ossim/ossimPluginCommon.cpp
new file mode 100644
index 0000000..188a585
--- /dev/null
+++ b/ossim_plugins/ossim/ossimPluginCommon.cpp
@@ -0,0 +1,190 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author:  David Burken
+//
+// Description: Common code for this plugin.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include <cstdlib>
+
+#include <ossimPluginCommon.h>
+#include <ossim/base/ossimDate.h>
+#include <ossim/base/ossimNotify.h>
+#include <ossim/base/ossimString.h>
+#include <ossim/base/ossimXmlDocument.h>
+#include <ossim/base/ossimXmlNode.h>
+#include <otb/CivilDateTime.h>
+#include <ossim/base/ossimTrace.h>
+static ossimTrace traceDebug("ossimPluginCommon:debug");
+namespace ossimplugins
+{
+
+
+bool ossim::iso8601TimeStringToCivilDate(const std::string& dateString,
+                                         CivilDateTime& outputDate)
+{
+   bool result = true;
+
+   ossimLocalTm otm;
+   if ( otm.setIso8601(dateString) )
+   {
+      outputDate.set_year( otm.getYear() );
+      outputDate.set_month( otm.getMonth() );
+      outputDate.set_day( otm.getDay() );
+
+      int second = otm.tm_hour * 3600 + otm.tm_min * 60 + otm.tm_sec;
+      outputDate.set_second( second );
+      outputDate.set_decimal( otm.getFractionalSecond() );
+
+   }
+   else
+   {
+      result = false;
+   }
+
+   return result;
+}
+
+
+bool ossim::getPath(const ossimString& path,
+                    const ossimXmlDocument* xdoc,
+                    ossimString& s)
+{
+   bool result = false;
+   if (xdoc)
+   {
+      std::vector<ossimRefPtr<ossimXmlNode> > xnodes;
+      xdoc->findNodes(path, xnodes);
+      if ( xnodes.size() == 1 ) // Error if more than one.
+      {
+         if ( xnodes[0].valid() )
+         {
+            s = xnodes[0]->getText();
+            result = true;
+         }
+         else
+         {
+            if(traceDebug())
+            {
+               
+               ossimNotify(ossimNotifyLevel_WARN)
+               << "ossim::getPath ERROR:\n"
+               << "Node not found: " << path
+               << std::endl;
+            }
+         }
+      }
+      else if ( xnodes.size() == 0 )
+      {
+         if(traceDebug())
+         {
+           ossimNotify(ossimNotifyLevel_WARN)
+               << "ossim::getPath ERROR:\n"
+               << "Node not found: " << path
+            << std::endl;
+         }
+      }
+      else
+      {
+         if(traceDebug())
+         {
+
+            ossimNotify(ossimNotifyLevel_WARN)
+               << "ossim::getPath ERROR:\n"
+               << "Multiple nodes found: " << path
+               << std::endl;
+         }
+      }
+   }
+   if (!result)
+   {
+      s.clear();
+   }
+   return result;
+}
+
+bool ossim::getPath(const ossimString& path,
+                    const ossimXmlDocument* xdoc,
+                    std::vector<ossimString>& v)
+{
+   bool result = false;
+   if (xdoc)
+   {
+      std::vector<ossimRefPtr<ossimXmlNode> > xnodes;
+      xdoc->findNodes(path, xnodes);
+      if ( xnodes.size() )
+      {
+         std::vector<ossimRefPtr<ossimXmlNode> >::const_iterator i =
+            xnodes.begin();
+         while ( i != xnodes.end() )
+         {
+            v.push_back( (*i)->getText() );
+            ++i;
+         }
+         result = true;
+      }
+      else
+      {
+         if(traceDebug())
+         {
+            ossimNotify(ossimNotifyLevel_WARN)
+            << "ossim::getPath ERROR:\n"
+            << "Nodes not found: " << path
+            << std::endl;
+         }
+      }
+   }
+   if (!result)
+   {
+      v.clear();
+   }
+   return result;
+}
+
+bool ossim::findFirstNode(const ossimString& path,
+                          ossimRefPtr<ossimXmlNode> node,
+                          ossimString& s)
+{
+   bool result = false;
+   if ( node.valid() )
+   {
+      ossimRefPtr<ossimXmlNode> n = node->findFirstNode(path);
+      if ( n.valid() )
+      {
+         s = n->getText();
+         if ( s.size() )
+         {
+            result = true;
+         }
+         else
+         {
+            if(!traceDebug())
+            {
+               ossimNotify(ossimNotifyLevel_WARN)
+               << "ossim::findFirstNode ERROR:\n"
+               << "Node empty: " << path
+               << std::endl;
+            }
+         }
+      }
+      else
+      {
+         if(!traceDebug())
+         {
+            ossimNotify(ossimNotifyLevel_WARN)
+               << "ossim::findFirstNode ERROR:\n"
+               << "Node not found: " << path
+               << std::endl;
+         }
+      }
+   }
+   return result;
+}
+}
+
diff --git a/ossim_plugins/ossim/ossimPluginCommon.h b/ossim_plugins/ossim/ossimPluginCommon.h
new file mode 100644
index 0000000..7aaf616
--- /dev/null
+++ b/ossim_plugins/ossim/ossimPluginCommon.h
@@ -0,0 +1,93 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author:  David Burken
+//
+// Description: Common code for this plugin.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef ossimPluginCommon_HEADER
+#define ossimPluginCommon_HEADER 1
+
+#include <string>
+#include <vector>
+#include <ossim/base/ossimRefPtr.h>
+
+class ossimString;
+class ossimXmlDocument;
+class ossimXmlNode;
+
+namespace ossimplugins
+{
+
+
+class CivilDateTime;
+
+
+namespace ossim
+{
+   /**
+    * @note This code was moved out of ossimRadarSat2Model.
+    *
+    * @brief Converts date string from ISO 8601 format to CivilDateTime.
+    *
+    * @param dateString Input date string.
+    *
+    * @param outputDate Output date object to initialize.
+    *
+    * @return true on success false on error.
+    */
+   bool iso8601TimeStringToCivilDate(const std::string& dataString,
+                                     CivilDateTime& outputDate);
+
+   /**
+    * @brief Gets path from doc and initializes string.
+    * @param path Xml path to look for.
+    * @param xdoc Xml doc to look in.
+    * @param s String to initialize.
+    * @return true on success and false if path is not found or if there
+    * are more than one of path.
+    * @note You should call getPath that takes a vector for things that are
+    * repetitive.
+    */
+   bool getPath(const ossimString& path,
+                const ossimXmlDocument* xdoc,
+                ossimString& s);
+
+   /**
+    * @brief Gets path from doc and initializes string.
+    * @param path Xml path to look for.
+    * @param xdoc Xml doc to look in.
+    * @param v Vector to initialize.
+    * @return true on success and false if path is not found.
+    */
+   bool getPath(const ossimString& path,
+                const ossimXmlDocument* xdoc,
+                std::vector<ossimString>& v);
+
+   /**
+    * @brief Finds from node with path from node and initializes string.
+    *
+    * @param path Xml path to look for.
+    *
+    * @param node Xml node to look in.
+    *
+    * @param s String to initialize.
+    *
+    * @return true on success and false if path is not found or if text is
+    * empty from found node..
+    */
+   bool findFirstNode(const ossimString& path,
+                      ossimRefPtr<ossimXmlNode> node,
+                      ossimString& s);
+
+} // matches: namespace ossim
+}
+
+#endif /* matches: #ifndef ossimPluginCommon_HEADER */
+
diff --git a/ossim_plugins/ossim/ossimPluginInit.cpp b/ossim_plugins/ossim/ossimPluginInit.cpp
new file mode 100644
index 0000000..d7a0d41
--- /dev/null
+++ b/ossim_plugins/ossim/ossimPluginInit.cpp
@@ -0,0 +1,97 @@
+//*******************************************************************
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author: Garrett Potts
+//*******************************************************************
+//  $Id$
+#include <ossim/plugin/ossimSharedObjectBridge.h>
+#include <ossimPluginConstants.h>
+#include <ossim/base/ossimObjectFactoryRegistry.h>
+#include <ossim/imaging/ossimImageHandlerRegistry.h>
+#include <ossim/projection/ossimProjectionFactoryRegistry.h>
+#include <ossimPluginProjectionFactory.h>
+#include <ossimPluginReaderFactory.h>
+
+
+namespace ossimplugins
+{
+
+
+   static void setDescription(ossimString& description)
+   {
+      description = "OSSIM Plugin\n\n";
+      std::vector<ossimString> projectionTypes;
+
+      ossimPluginProjectionFactory::instance()->getTypeNameList(projectionTypes);
+      ossim_uint32 idx = 0;
+      description = "Projecitons Supported:\n\n";
+      for(idx = 0; idx < projectionTypes.size();++idx)
+      {
+         description += projectionTypes[idx] + "\n";
+      }
+   }
+
+
+   extern "C"
+   {
+      ossimSharedObjectInfo  myInfo;
+      ossimString theDescription;
+      std::vector<ossimString> theObjList;
+      const char* getDescription()
+      {
+         return theDescription.c_str();
+      }
+      int getNumberOfClassNames()
+      {
+         return (int)theObjList.size();
+      }
+      const char* getClassName(int idx)
+      {
+         if(idx < (int)theObjList.size())
+         {
+            return theObjList[0].c_str();
+         }
+         return (const char*)0;
+      }
+
+      /* Note symbols need to be exported on windoze... */
+      OSSIM_PLUGINS_DLL void ossimSharedLibraryInitialize(
+         ossimSharedObjectInfo** info)
+      {
+         myInfo.getDescription = getDescription;
+         myInfo.getNumberOfClassNames = getNumberOfClassNames;
+         myInfo.getClassName = getClassName;
+
+         *info = &myInfo;
+
+         /** Register the readers... */
+         ossimImageHandlerRegistry::instance()->
+            registerFactory(ossimPluginReaderFactory::instance());
+
+         /**
+          * Register the projection factory.
+          * Note that this must be pushed to the front of the factory or bilinear
+          * projection will be picked up.
+          */
+         ossimProjectionFactoryRegistry::instance()->
+            registerFactoryToFront(ossimPluginProjectionFactory::instance());
+
+         setDescription(theDescription);
+      }
+
+      /* Note symbols need to be exported on windoze... */
+      OSSIM_PLUGINS_DLL void ossimSharedLibraryFinalize()
+      {
+         ossimImageHandlerRegistry::instance()->
+            unregisterFactory(ossimPluginReaderFactory::instance());
+
+         ossimProjectionFactoryRegistry::instance()->
+            unregisterFactory(ossimPluginProjectionFactory::instance());
+      }
+
+   }
+}
+
diff --git a/ossim_plugins/ossim/ossimPluginProjectionFactory.cpp b/ossim_plugins/ossim/ossimPluginProjectionFactory.cpp
new file mode 100644
index 0000000..5769363
--- /dev/null
+++ b/ossim_plugins/ossim/ossimPluginProjectionFactory.cpp
@@ -0,0 +1,563 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+//***
+// Note to programmer: To add a new model, search this file for "ADD_MODEL"
+// to locate places requiring editing. Functional example below...
+//
+// ADD_MODEL: Include all sensor model headers here:
+//***
+#include "ossimPluginProjectionFactory.h"
+#include <ossim/base/ossimKeywordNames.h>
+#include <ossim/base/ossimRefPtr.h>
+#include <ossim/projection/ossimProjection.h>
+#include "ossimRadarSatModel.h"
+#include "ossimEnvisatAsarModel.h"
+#include "ossimTerraSarModel.h"
+//#include <ossim/projection/ossimCosmoSkymedModel.h>
+#include "ossimRadarSat2Model.h"
+#include "ossimErsSarModel.h"
+#include "ossimAlosPalsarModel.h"
+#include "ossimPleiadesModel.h"
+#include <ossim/base/ossimNotifyContext.h>
+#include "ossimTileMapModel.h"
+#include "ossimSpot6Model.h"
+
+//***
+// Define Trace flags for use within this file:
+//***
+#include <ossim/base/ossimTrace.h>
+static ossimTrace traceExec  = ossimTrace("ossimPluginProjectionFactory:exec");
+static ossimTrace traceDebug = ossimTrace("ossimPluginProjectionFactory:debug");
+
+
+#include <ossimFormosatModel.h>
+#include <ossimFormosatDimapSupportData.h>
+
+namespace ossimplugins
+{
+
+
+ossimPluginProjectionFactory* ossimPluginProjectionFactory::instance()
+{
+   static ossimPluginProjectionFactory* factoryInstance =
+      new ossimPluginProjectionFactory();
+
+   return factoryInstance;
+}
+   
+ossimProjection* ossimPluginProjectionFactory::createProjection(
+   const ossimFilename& filename, ossim_uint32 /*entryIdx*/)const
+{
+   static const char MODULE[] = "ossimPluginProjectionFactory::createProjection(ossimFilename& filename)";
+   ossimRefPtr<ossimProjection> projection = 0;
+   //traceDebug.setTraceFlag(true);
+
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " DEBUG: testing ossimRadarSat2Model" << std::endl;
+   }
+
+   if ( !projection )
+   {
+      ossimRefPtr<ossimRadarSat2Model> model = new ossimRadarSat2Model();
+      if ( model->open(filename) )
+      {
+         // Check if a coarse grid was generated, and use it instead:
+         projection = model->getReplacementOcgModel().get();
+         if (projection.valid())
+            model = 0; // Have OCG, don't need this one anymore
+         else
+            projection = model.get();
+      }
+      else
+      {
+         model = 0;
+      }
+   }
+   
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " DEBUG: testing ossimPleiadesModel" << std::endl;
+   }
+
+   // Pleiades
+   if ( !projection )
+   {
+      ossimRefPtr<ossimPleiadesModel> model = new ossimPleiadesModel();
+      if ( model->open(filename) )
+      {
+         projection = model.get();
+      }
+      else
+      {
+         model = 0;
+      }
+   }
+
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " DEBUG: testing ossimTerraSarModel" << std::endl;
+   }
+
+   if ( !projection )
+   {
+      ossimRefPtr<ossimTerraSarModel> model = new ossimTerraSarModel();
+
+      if ( model->open(filename) )
+      {
+         // Check if a coarse grid was generated, and use it instead:
+         projection = model->getReplacementOcgModel().get();
+         if (projection.valid())
+            model = 0; // Have OCG, don't need this one anymore
+         else
+            projection = model.get();
+      }
+      else
+      {
+         model = 0;
+      }
+   }
+
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " DEBUG: testing ossimErsSarModel" << std::endl;
+   }
+
+   if ( !projection )
+   {
+      ossimRefPtr<ossimErsSarModel> model = new ossimErsSarModel();
+      if ( model->open(filename) )
+      {
+         projection = model.get();
+      }
+      else
+      {
+         model = 0;
+      }
+   }
+
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " DEBUG: testing ossimEnvisatSarModel" << std::endl;
+   }
+
+   if (!projection)
+   {
+      ossimRefPtr<ossimEnvisatAsarModel> model = new ossimEnvisatAsarModel();
+      if (model->open(filename))
+      {
+         projection = model.get();
+      }
+      else
+      {
+         model = 0;
+      }
+   }
+
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " DEBUG: testing ossimRadarSatModel" << std::endl;
+   }
+
+   if (!projection)
+   {
+      ossimRefPtr<ossimRadarSatModel> model = new ossimRadarSatModel();
+      if (model->open(filename))
+      {
+         projection = model.get();
+      }
+      else
+      {
+         model = 0;
+      }
+   }
+
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " DEBUG: testing ossimAlosPalsarModel" << std::endl;
+   }
+
+   if (!projection)
+   {
+      ossimRefPtr<ossimAlosPalsarModel> model = new ossimAlosPalsarModel();
+      if (model->open(filename))
+      {
+         projection = model.get();
+      }
+      else
+      {
+         model = 0;
+      }
+   }
+
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " DEBUG: testing ossimFormosatModel" << std::endl;
+   }
+   
+   ossimFilename formosatTest = filename;
+   formosatTest = formosatTest.setExtension("geom");
+   if(!formosatTest.exists())
+   {
+      formosatTest = filename.path();
+      formosatTest = formosatTest.dirCat(ossimFilename("METADATA.DIM"));
+      if (formosatTest.exists() == false)
+      {
+         formosatTest = filename.path();
+         formosatTest = formosatTest.dirCat(ossimFilename("metadata.dim"));
+      }
+   }
+   if(formosatTest.exists())
+   {
+      //---
+      // Check the basename of the input file. So we don't create a projection
+      // for ancillary files, icon.jpg amd preview.jpg.
+      //---
+      ossimFilename baseName = filename.file();
+      baseName.downcase();
+      
+      if ( (baseName != "icon.jpg" ) && ( baseName != "preview.jpg" ) )
+      {
+         ossimRefPtr<ossimFormosatDimapSupportData> meta =
+            new ossimFormosatDimapSupportData;
+         if(meta->loadXmlFile(formosatTest))
+         {
+            ossimRefPtr<ossimFormosatModel> model = new ossimFormosatModel(meta.get());
+            if(!model->getErrorStatus())
+            {
+               projection = model.get();
+               
+            }
+            model = 0;
+         }
+      }
+   }
+
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " DEBUG: testing ossimTileMapModel" << std::endl;
+   }
+
+   if (!projection)
+   {
+      ossimRefPtr<ossimTileMapModel> model = new ossimTileMapModel();
+      if (model->open(filename))
+      {
+         projection = model.get();
+      }
+      else
+      {
+         model = 0;
+      }
+   }
+
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " DEBUG: testing ossimSpot6Model" << std::endl;
+   }
+
+   // Spot6
+   if ( !projection )
+   {
+      ossimRefPtr<ossimSpot6Model> model = new ossimSpot6Model();
+      if ( model->open(filename) )
+      {
+         projection = model.get(); 
+      }
+      else
+      {
+         model = 0;
+      }
+   }
+
+   //***
+   // ADD_MODEL: (Please leave this comment for the next programmer)
+   //***
+   //if(traceDebug())
+   //{
+    //  ossimNotify(ossimNotifyLevel_DEBUG)
+     //        << MODULE << " DEBUG: testing MY_NEW_MODEL" << std::endl;
+   //}
+
+   // MY_NEW_MODEL
+   //if ( !projection )
+   //{
+    //  ossimRefPtr<MY_NEW_MODEL> model = new MY_NEW_MODEL();
+     // if ( model->open(filename) )
+      //{
+       //  projection = model.get();
+      //}
+   //   else
+   //   {
+  //       model = 0;
+  //    }
+   //}
+
+   return projection.release();
+}
+
+ossimProjection* ossimPluginProjectionFactory::createProjection(
+   const ossimString& name)const
+{
+   static const char MODULE[] = "ossimPluginProjectionFactory::createProjection(ossimString& name)";
+
+   if(traceDebug())
+   {
+    	ossimNotify(ossimNotifyLevel_DEBUG)
+           << MODULE << " DEBUG: Entering ...." << std::endl;
+   }
+
+   //   else if (name == STATIC_TYPE_NAME(ossimCosmoSkymedModel))
+   //    {
+   //      return new ossimCosmoSkymedModel;
+   //   }
+   if (name == STATIC_TYPE_NAME(ossimRadarSat2Model))
+   {
+      return new ossimRadarSat2Model();
+   }
+   else if (name == STATIC_TYPE_NAME(ossimTerraSarModel))
+   {
+      return new ossimTerraSarModel();
+   }
+   else if (name == STATIC_TYPE_NAME(ossimErsSarModel))
+   {
+     return new ossimErsSarModel;
+   }
+   else if (name == STATIC_TYPE_NAME(ossimEnvisatAsarModel))
+   {
+     return new ossimEnvisatAsarModel;
+   }
+   else if (name == STATIC_TYPE_NAME(ossimRadarSatModel))
+   {
+     return new ossimRadarSatModel;
+   }
+   else if (name == STATIC_TYPE_NAME(ossimAlosPalsarModel))
+   {
+     return new ossimAlosPalsarModel;
+   }
+   else if (name == STATIC_TYPE_NAME(ossimFormosatModel))
+   {
+     return new ossimFormosatModel;
+   }
+   else if (name == STATIC_TYPE_NAME(ossimTileMapModel))
+   {
+     return new ossimTileMapModel;
+   }
+   else if (name == STATIC_TYPE_NAME(ossimPleiadesModel))
+   {
+     return new ossimPleiadesModel;
+   }
+   else if (name == STATIC_TYPE_NAME(ossimSpot6Model))
+   {
+     return new ossimSpot6Model;
+   }
+
+   //***
+   // ADD_MODEL: (Please leave this comment for the next programmer)
+   //***
+//   if(name == MY_NEW_MODEL)
+//      return new myNewModel;
+
+
+   if(traceDebug())
+   {
+    	ossimNotify(ossimNotifyLevel_DEBUG)
+        	   << MODULE << " DEBUG: Leaving ...." << std::endl;
+   }
+
+   return 0;
+}
+
+ossimProjection* ossimPluginProjectionFactory::createProjection(
+   const ossimKeywordlist& kwl, const char* prefix)const
+{
+   ossimRefPtr<ossimProjection> result = 0;
+   static const char MODULE[] = "ossimPluginProjectionFactory::createProjection(ossimKeywordlist& kwl)";
+
+   if(traceDebug())
+   {
+    	ossimNotify(ossimNotifyLevel_DEBUG)
+        	   << MODULE << " DEBUG: Start ...." << std::endl;
+   }
+
+   const char* lookup = kwl.find(prefix, ossimKeywordNames::TYPE_KW);
+   if (lookup)
+   {
+      ossimString type = lookup;
+
+      if (type == "ossimRadarSat2Model")
+      {
+         result = new ossimRadarSat2Model();
+         if ( !result->loadState(kwl, prefix) )
+         {
+            result = 0;
+         }
+      }
+      else if (type == "ossimTerraSarModel")
+      {
+         result = new ossimTerraSarModel();
+         if ( !result->loadState(kwl, prefix) )
+         {
+            result = 0;
+         }
+      }
+      else if (type == "ossimErsSarModel")
+      {
+         result = new ossimErsSarModel();
+         if ( !result->loadState(kwl, prefix) )
+         {
+            result = 0;
+         }
+      }
+      else if (type == "ossimEnvisatAsarModel")
+      {
+         result = new ossimEnvisatAsarModel();
+         if ( !result->loadState(kwl, prefix) )
+         {
+            result = 0;
+         }
+      }
+      else if (type == "ossimRadarSatModel")
+      {
+         result = new ossimRadarSatModel();
+         if ( !result->loadState(kwl, prefix) )
+         {
+            result = 0;
+         }
+      }
+      else if (type == "ossimAlosPalsarModel")
+      {
+         result = new ossimAlosPalsarModel();
+         if ( !result->loadState(kwl, prefix) )
+         {
+            result = 0;
+         }
+      }
+      else if (type == "ossimFormosatModel")
+      {
+         result = new ossimFormosatModel();
+         if ( !result->loadState(kwl, prefix) )
+         {
+            result = 0;
+         }
+      }
+      else if (type == "ossimTileMapModel")
+      {
+         result = new ossimTileMapModel();
+         if ( !result->loadState(kwl, prefix) )
+         {
+            result = 0;
+         }
+      }
+      else if (type == "ossimPleiadesModel")
+      {
+         result = new ossimPleiadesModel();
+         if ( !result->loadState(kwl, prefix) )
+         {
+            result = 0;
+         }
+      }
+      else if (type == "ossimSpot6Model")
+      {
+         result = new ossimSpot6Model();
+         if ( !result->loadState(kwl, prefix) )
+         {
+            result = 0;
+         }
+      }
+
+   //***
+   // ADD_MODEL: (Please leave this comment for the next programmer)
+   //***
+//      else if (type == "ossimSpot6Model")
+//      {
+//         result = new ossimSpot6Model();
+//         if ( !result->loadState(kwl, prefix) )
+//         {
+//            result = 0;
+//         }
+//      }
+
+   }
+
+   if(traceDebug())
+   {
+    	ossimNotify(ossimNotifyLevel_DEBUG)
+        	   << MODULE << " DEBUG: End ...." << std::endl;
+   }
+   
+   return result.release();
+}
+
+ossimObject* ossimPluginProjectionFactory::createObject(
+   const ossimString& typeName)const
+{
+   return createProjection(typeName);
+}
+
+ossimObject* ossimPluginProjectionFactory::createObject(
+   const ossimKeywordlist& kwl, const char* prefix)const
+{
+   return createProjection(kwl, prefix);
+}
+
+
+void ossimPluginProjectionFactory::getTypeNameList(std::vector<ossimString>& typeList)const
+{
+   typeList.push_back(STATIC_TYPE_NAME(ossimRadarSatModel));
+   typeList.push_back(STATIC_TYPE_NAME(ossimRadarSat2Model));
+   typeList.push_back(STATIC_TYPE_NAME(ossimTerraSarModel));
+   //   result.push_back(STATIC_TYPE_NAME(ossimCosmoSkymedModel));
+   typeList.push_back(STATIC_TYPE_NAME(ossimEnvisatAsarModel));
+   typeList.push_back(STATIC_TYPE_NAME(ossimErsSarModel));
+   typeList.push_back(STATIC_TYPE_NAME(ossimAlosPalsarModel));
+   typeList.push_back(STATIC_TYPE_NAME(ossimFormosatModel));
+   typeList.push_back(STATIC_TYPE_NAME(ossimTileMapModel));
+   typeList.push_back(STATIC_TYPE_NAME(ossimPleiadesModel));
+   typeList.push_back(STATIC_TYPE_NAME(ossimSpot6Model));
+
+   //***
+   // ADD_MODEL: Please leave this comment for the next programmer. Add above.
+   //***
+   //typeList.push_back(STATIC_TYPE_NAME(MY_NEW_MODEL));
+}
+
+bool ossimPluginProjectionFactory::isTileMap(const ossimFilename& filename)const
+{
+   ossimFilename temp(filename);
+   temp.downcase();
+  
+   ossimString os = temp.beforePos(4);
+  
+   if(temp.ext()=="otb")
+   {
+      return true;
+   }
+   else if(os == "http")
+   {
+      return true;
+   }
+   return false;
+}
+
+} // End: namespace ossimplugins
+
diff --git a/ossim_plugins/ossim/ossimPluginProjectionFactory.h b/ossim_plugins/ossim/ossimPluginProjectionFactory.h
new file mode 100644
index 0000000..5460174
--- /dev/null
+++ b/ossim_plugins/ossim/ossimPluginProjectionFactory.h
@@ -0,0 +1,61 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef ossimPluginProjectionFactory_HEADER
+#define ossimPluginProjectionFactory_HEADER
+#include <ossimPluginConstants.h>
+#include <ossim/projection/ossimProjectionFactoryBase.h>
+
+namespace ossimplugins
+{
+
+
+class OSSIM_PLUGINS_DLL ossimPluginProjectionFactory : public ossimProjectionFactoryBase
+{
+public:
+
+   static ossimPluginProjectionFactory* instance();
+   /**
+    * takes a filename. This filename can be an image file or
+    * it can also be a ossim .geom file.  It could be other
+    * forms of geom files as well.  The factories job will be to
+    * determine what parser to use and return a projection if
+    * successful.
+    */
+   virtual ossimProjection* createProjection(const ossimFilename& filename,
+                                             ossim_uint32 entryIdx)const;
+
+   /**
+    * Take a projection type name.
+    */
+   virtual ossimProjection* createProjection(const ossimString& name)const;
+
+   /**
+    * Take a keywordlist.
+    */
+   virtual ossimProjection* createProjection(const ossimKeywordlist& kwl,
+                                             const char* prefix=0)const;
+
+   virtual ossimObject* createObject(const ossimString& typeName)const;
+
+   /*!
+    * Creates and object given a keyword list.
+    */
+   virtual ossimObject* createObject(const ossimKeywordlist& kwl,
+                                     const char* prefix=0)const;
+
+   virtual void getTypeNameList(std::vector<ossimString>& typeList)const;
+protected:
+   ossimPluginProjectionFactory(){}
+   bool isTileMap(const ossimFilename& filename) const;
+};
+}
+
+#endif
+
diff --git a/ossim_plugins/ossim/ossimPluginReaderFactory.cpp b/ossim_plugins/ossim/ossimPluginReaderFactory.cpp
new file mode 100644
index 0000000..9805a6f
--- /dev/null
+++ b/ossim_plugins/ossim/ossimPluginReaderFactory.cpp
@@ -0,0 +1,179 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author:  David Burken
+//
+// Description: Image handler factory for ossim plugins plugin.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include <ossimPluginReaderFactory.h>
+#include <ossimRadarSat2TiffReader.h>
+#include <ossimTerraSarTiffReader.h>
+#include <ossim/base/ossimKeywordlist.h>
+#include <ossim/base/ossimRefPtr.h>
+#include <ossim/base/ossimString.h>
+#include <ossim/imaging/ossimImageHandler.h>
+#include <ossim/base/ossimTrace.h>
+#include <ossim/base/ossimKeywordNames.h>
+
+namespace ossimplugins
+{
+
+
+   static const ossimTrace traceDebug("ossimPluginReaderFactory:debug");
+
+   RTTI_DEF1(ossimPluginReaderFactory,
+             "ossimPluginReaderFactory",
+             ossimImageHandlerFactoryBase);
+
+   ossimPluginReaderFactory* ossimPluginReaderFactory::theInstance = 0;
+
+   ossimPluginReaderFactory::~ossimPluginReaderFactory()
+   {
+      theInstance = 0;
+   }
+
+   ossimPluginReaderFactory* ossimPluginReaderFactory::instance()
+   {
+      if(!theInstance)
+      {
+         theInstance = new ossimPluginReaderFactory;
+      }
+      return theInstance;
+   }
+
+   ossimImageHandler* ossimPluginReaderFactory::open(
+      const ossimFilename& fileName, bool openOverview)const
+   {
+      if(traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG)
+            << "ossimPluginReaderFactory::open(filename) DEBUG: entered..."
+            << "\ntrying ossimRadarSat2TiffReader"
+            << std::endl;
+      }
+
+      ossimRefPtr<ossimImageHandler> reader = new ossimRadarSat2TiffReader();
+      reader->setOpenOverviewFlag(openOverview);
+      if(reader->open(fileName) == false)
+      {
+         reader = 0;
+      }
+
+      if ( !reader.valid() )
+      {
+         if(traceDebug())
+         {
+            ossimNotify(ossimNotifyLevel_DEBUG)
+               << "\ntrying ossimTerraSarTiffReader"
+               << std::endl;
+         }
+      
+         reader = new ossimTerraSarTiffReader();
+         reader->setOpenOverviewFlag(openOverview);
+         if(reader->open(fileName) == false)
+         {
+            reader = 0;
+         }
+      }
+
+      if(traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG)
+            << "ossimPluginReaderFactory::open(filename) DEBUG: leaving..."
+            << std::endl;
+      }
+
+      return reader.release();
+   }
+
+   ossimImageHandler* ossimPluginReaderFactory::open(const ossimKeywordlist& kwl,
+                                                     const char* prefix)const
+   {
+      if(traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG)
+            << "ossimPluginReaderFactory::open(kwl, prefix) DEBUG: entered..."
+            << "Trying ossimRadarSat2TiffReader"
+            << std::endl;
+      }
+
+      ossimRefPtr<ossimImageHandler> reader = new ossimRadarSat2TiffReader;
+      if(reader->loadState(kwl, prefix) == false)
+      {
+         reader = 0;
+      }
+
+      if ( !reader.valid() )
+      {
+         if(traceDebug())
+         {
+            ossimNotify(ossimNotifyLevel_DEBUG)
+               << "ossimPluginReaderFactory::open(kwl, prefix) DEBUG: entered..."
+               << "Trying ossimTerraSarTiffReader"
+               << std::endl;
+         }
+         reader = new ossimTerraSarTiffReader;
+         if(reader->loadState(kwl, prefix) == false)
+         {
+            reader = 0;
+         }
+      }
+
+      if(traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG)
+            << "ossimPluginReaderFactory::open(kwl, prefix) DEBUG: leaving..."
+            << std::endl;
+      }
+
+      return reader.release();
+   }
+
+   ossimObject* ossimPluginReaderFactory::createObject(
+      const ossimString& typeName)const
+   {
+      ossimRefPtr<ossimObject> result = 0;
+      if(typeName == "ossimRadarSat2TiffReader")
+      {
+         result = new ossimRadarSat2TiffReader;
+      }
+      else if(typeName == "ossimTerraSarTiffReader")
+      {
+         result = new ossimTerraSarTiffReader;
+      }
+
+      return result.release();
+   }
+
+   ossimObject* ossimPluginReaderFactory::createObject(
+      const ossimKeywordlist& kwl, const char* prefix)const
+   {
+      return this->open(kwl, prefix);
+   }
+
+   void ossimPluginReaderFactory::getTypeNameList(
+      std::vector<ossimString>& typeList)const
+   {
+      typeList.push_back(ossimString("ossimRadarSat2TiffReader"));
+      typeList.push_back(ossimString("ossimTerraSarTiffReader"));
+   }
+
+   void ossimPluginReaderFactory::getSupportedExtensions(
+      ossimImageHandlerFactoryBase::UniqueStringList& extensionList)const
+   {
+      extensionList.push_back(ossimString("xml"));
+   }
+
+   ossimPluginReaderFactory::ossimPluginReaderFactory(){}
+
+   ossimPluginReaderFactory::ossimPluginReaderFactory(const ossimPluginReaderFactory&){}
+
+   void ossimPluginReaderFactory::operator=(const ossimPluginReaderFactory&){}
+}
+
diff --git a/ossim_plugins/ossim/ossimPluginReaderFactory.h b/ossim_plugins/ossim/ossimPluginReaderFactory.h
new file mode 100644
index 0000000..66feb1b
--- /dev/null
+++ b/ossim_plugins/ossim/ossimPluginReaderFactory.h
@@ -0,0 +1,105 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author:  David Burken
+//
+// Description: Image handler factory for ossim plugins plugin.
+//----------------------------------------------------------------------------
+// $Id$
+#ifndef ossimPluginReaderFactory_HEADER
+#define ossimPluginReaderFactory_HEADER 1
+
+#include <ossimPluginConstants.h>
+#include <ossim/imaging/ossimImageHandlerFactoryBase.h>
+
+class ossimString;
+class ossimFilename;
+class ossimKeywordlist;
+
+namespace ossimplugins
+{
+
+
+/** @brief Image handler factory for ossim plugins plugin. */
+   class OSSIM_PLUGINS_DLL ossimPluginReaderFactory : public ossimImageHandlerFactoryBase
+   {
+   public:
+
+      /** @brief virtual destructor */
+      virtual ~ossimPluginReaderFactory();
+
+      /**
+       * @brief static method to return instance (the only one) of this class.
+       * @return pointer to instance of this class.
+       */
+      static ossimPluginReaderFactory* instance();
+
+      /**
+       * @brief open that takes a file name.
+       * @param file The file to open.
+       * @return pointer to image handler on success, 0 on failure.
+       */
+      virtual ossimImageHandler* open(const ossimFilename& fileName,
+                                      bool openOverview=true) const;
+
+      /**
+       * @brief open that takes a keyword list and prefix.
+       * @param kwl The keyword list.
+       * @param prefix the keyword list prefix.
+       * @return pointer to image handler on success, 0 on failure.
+       */
+      virtual ossimImageHandler* open(const ossimKeywordlist& kwl,
+                                      const char* prefix=0)const;
+
+      /**
+       * @brief createObject that takes a class name.
+       * @param typeName The name of the class..
+       * @return pointer to image writer on success, 0 on failure.
+       */
+      virtual ossimObject* createObject(const ossimString& typeName)const;
+
+      /**
+       * @brief Creates and object given a keyword list and prefix.
+       * @param kwl The keyword list.
+       * @param prefix the keyword list prefix.
+       * @return pointer to image handler on success, 0 on failure.
+       */
+      virtual ossimObject* createObject(const ossimKeywordlist& kwl,
+                                        const char* prefix=0)const;
+
+      /**
+       * @brief Adds ossimTerraSarTiffReader to the typeList.
+       * @param typeList List to add to.
+       */
+      virtual void getTypeNameList(std::vector<ossimString>& typeList)const;
+
+      /**
+       * @brief Method to add supported extension to the list, like "png".
+       *
+       * @param extensionList The list to add to.
+       */
+      virtual void getSupportedExtensions(
+         ossimImageHandlerFactoryBase::UniqueStringList& extensionList)const;
+
+   protected:
+      /** @brief hidden from use default constructor */
+      ossimPluginReaderFactory();
+
+      /** @brief hidden from use copy constructor */
+      ossimPluginReaderFactory(const ossimPluginReaderFactory&);
+
+      /** @brief hidden from use copy constructor */
+      void operator=(const ossimPluginReaderFactory&);
+
+      /** static instance of this class */
+      static ossimPluginReaderFactory* theInstance;
+
+      TYPE_DATA
+         };
+}
+
+#endif /* end of #ifndef ossimPluginReaderFactory_HEADER */
+
diff --git a/ossim_plugins/ossim/ossimRadarSat2Model.cpp b/ossim_plugins/ossim/ossimRadarSat2Model.cpp
new file mode 100644
index 0000000..ef882a7
--- /dev/null
+++ b/ossim_plugins/ossim/ossimRadarSat2Model.cpp
@@ -0,0 +1,1595 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include <cmath>
+#include <cstdio>
+
+#include <ossimRadarSat2Model.h>
+#include <ossimPluginCommon.h>
+#include <ossimRadarSat2ProductDoc.h>
+#include <ossim/base/ossimCommon.h>
+#include <ossim/base/ossimFilename.h>
+#include <ossim/base/ossimKeywordNames.h>
+#include <ossim/base/ossimNotify.h>
+#include <ossim/base/ossimRefPtr.h>
+#include <ossim/base/ossimString.h>
+#include <ossim/base/ossimTrace.h>
+#include <ossim/base/ossimXmlDocument.h>
+#include <ossim/base/ossimXmlNode.h>
+#include <ossim/support_data/ossimSupportFilesList.h>
+#include <otb/GalileanEphemeris.h>
+#include <otb/GeographicEphemeris.h>
+#include <otb/GMSTDateTime.h>
+#include <otb/PlatformPosition.h>
+#include <otb/SensorParams.h>
+#include <otb/RefPoint.h>
+#include <otb/SarSensor.h>
+
+namespace ossimplugins
+{
+// Keyword constants:
+static const char NUMBER_SRGR_COEFFICIENTS_KW[] = "sr_gr_coeffs_count";
+static const char LOAD_FROM_PRODUCT_FILE_KW[] = "load_from_product_file_flag";
+static const char PRODUCT_XML_FILE_KW[] = "product_xml_filename";
+
+// Static trace for debugging
+static ossimTrace traceDebug("ossimRadarSat2Model:debug");
+
+RTTI_DEF1(ossimRadarSat2Model, "ossimRadarSat2Model", ossimGeometricSarSensorModel);
+
+
+ossimRadarSat2Model::ossimRadarSat2Model()
+   :
+   ossimGeometricSarSensorModel(),
+   _n_srgr(0),
+   _srgr_update(),
+   _SrGr_R0()
+{
+}
+
+ossimRadarSat2Model::ossimRadarSat2Model(const ossimRadarSat2Model& rhs)
+   :
+   ossimGeometricSarSensorModel(rhs),
+   _n_srgr(rhs._n_srgr),
+   _srgr_update(rhs._srgr_update),
+   _SrGr_R0(rhs._SrGr_R0)
+{
+}
+
+ossimRadarSat2Model::~ossimRadarSat2Model()
+{
+}
+
+ossimString ossimRadarSat2Model::getClassName() const
+{
+   return ossimString("ossimRadarSat2Model");
+}
+
+ossimObject* ossimRadarSat2Model::dup() const
+{
+   return new ossimRadarSat2Model(*this);
+}
+
+double ossimRadarSat2Model::getSlantRangeFromGeoreferenced(double col) const
+{
+   if (_n_srgr==0) return(-1) ;
+   
+   double relativeGroundRange, slantRange = 0.0 ;
+   
+   // in the case of Georeferenced images, _refPoint->get_distance()
+   // contains the ground range
+   relativeGroundRange = _refPoint->get_distance() + _sensor->get_col_direction() * (col-_refPoint->get_pix_col())* theGSD.x;
+   //relativeGroundRange = 1 + _sensor->get_col_direction() * (col-_refPoint->get_pix_col())* theGSD.x;
+   //relativeGroundRange = (8.78400000e+03)*theGSD.x;
+   
+   if ( traceDebug() )
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "_refPoint->get_distance(): " << _refPoint->get_distance()
+         << "\n_sensor->get_col_direction() " << _sensor->get_col_direction()
+         << "\n(col-_refPoint->get_pix_col()) "
+         << (col-_refPoint->get_pix_col())
+         << "\n_refPoint->get_pix_col() : " << _refPoint->get_pix_col()
+         << "\n relativeGroundRange : " << relativeGroundRange << endl;
+   }
+   
+   int numSet = FindSRGRSetNumber((_refPoint->get_ephemeris())->get_date()) ;
+   /**
+    * @todo : could be improved (date choice)
+    */
+   
+   for (int i=0 ; i < static_cast<int>(_SrGr_coeffs[numSet].size()); i++)
+   {
+      
+      slantRange += _SrGr_coeffs[numSet][i]*pow(relativeGroundRange,i) ;
+   }
+
+   return  slantRange ;
+}
+
+bool ossimRadarSat2Model::open(const ossimFilename& file)
+{
+   static const char MODULE[] = "ossimRadarSat2Model::open";
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)<< MODULE << " entered...\n";
+   }
+
+   bool result = false;
+
+   // Get the xml file.
+   ossimFilename xmlFile;
+   _imageFilename = file.expand();
+
+   if (file.ext().downcase() == "xml")
+   {
+      xmlFile = file;
+   }
+   else if (file.isFile())
+   {
+      xmlFile = file.expand().path().dirCat("product.xml");
+   }
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "product xml file: " << xmlFile << "\n";
+   }
+
+   if ( xmlFile.exists() )
+   {
+
+      //---
+      // Instantiate the XML parser:
+      //---
+      ossimXmlDocument* xdoc = new ossimXmlDocument();
+      if ( xdoc->openFile(xmlFile) )
+      {
+         ossimRadarSat2ProductDoc rsDoc;
+
+         result = rsDoc.isRadarSat2(xdoc);
+
+         if (result)
+         {
+            if (traceDebug())
+            {
+               ossimNotify(ossimNotifyLevel_DEBUG)
+                  << "isRadarSat2...\n";
+               ossimString s;
+               if ( rsDoc.getBeamModeMnemonic(xdoc, s) )
+               {
+                  ossimNotify(ossimNotifyLevel_DEBUG)
+                     << "beam_mode_mnemonic: " << s << "\n";
+               }
+               if ( rsDoc.getAcquisitionType(xdoc, s) )
+               {
+                  ossimNotify(ossimNotifyLevel_DEBUG)
+                     << "acquisition_type: " << s << "\n";
+               }
+            }
+
+            // Set the base class number of lines and samples
+            result = rsDoc.initImageSize(xdoc, theImageSize);
+
+            if (result)
+            {
+               // Set the base class clip rect.
+               theImageClipRect = ossimDrect(
+                  0, 0,
+                  theImageSize.x-1, theImageSize.y-1);
+            }
+
+            // Set the sub image offset. tmp hard coded (drb).
+            theSubImageOffset.x = 0.0;
+            theSubImageOffset.y = 0.0;
+
+            // Set the image id.
+            if (result)
+            {
+               result = rsDoc.getImageId(xdoc, theImageID);
+            }
+
+            // Set the sensor ID.
+            if (result)
+            {
+               result = rsDoc.getSatellite(xdoc, theSensorID);
+            }
+
+            // Set the base class gsd:
+            result = rsDoc.initGsd(xdoc, theGSD);
+            if (result)
+            {
+               theMeanGSD = (theGSD.x + theGSD.y)/2.0;
+            }
+
+            if (result)
+            {
+               result = initSRGR(xdoc, rsDoc);
+
+               if (result)
+               {
+                  result = initPlatformPosition(xdoc, rsDoc);
+
+                  if (result)
+                  {
+                     result = initSensorParams(xdoc, rsDoc);
+
+                     if (result)
+                     {
+                        result = initRefPoint(xdoc, rsDoc);
+                     
+                     	  if (result)
+                        {
+                        result = InitRefNoiseLevel(xdoc);
+                        }
+                     }
+                  }
+               }
+            }
+         }
+
+      } // matches: if ( xdoc->openFile(xmlFile) )
+
+      delete xdoc;
+      xdoc = 0;
+
+   } // matches: if ( xmlFile.exists() )
+
+   if (result)
+   {
+      _productXmlFile = xmlFile;
+      ossimSupportFilesList::instance()->add(_productXmlFile);
+   }
+   else
+   {
+      _productXmlFile = ossimFilename::NIL;
+   }
+
+   if (result)
+   {
+      // Assign the ossimSensorModel::theBoundGndPolygon
+      ossimGpt ul;
+      ossimGpt ur;
+      ossimGpt lr;
+      ossimGpt ll;
+      lineSampleToWorld(theImageClipRect.ul(), ul);
+      lineSampleToWorld(theImageClipRect.ur(), ur);
+      lineSampleToWorld(theImageClipRect.lr(), lr);
+      lineSampleToWorld(theImageClipRect.ll(), ll);
+
+      if (traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG)
+            << "theImageClipRect : " << theImageClipRect
+            << "ul, ur, lr, ll " << ul << ", " << ur
+            << ", " << lr << " , " << ll << endl;
+      }
+      
+      setGroundRect(ul, ur, lr, ll);  // ossimSensorModel method.
+
+      // OSSIM preferences specifies whether a coarse grid needs to be generated:
+      if (!createReplacementOCG())
+         result = false;
+   }
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " exit status = " << (result?"true":"false\n")
+         << std::endl;
+   }
+
+   return result;
+}
+
+std::ostream& ossimRadarSat2Model::print(std::ostream& out) const
+{
+   // Capture the original flags.
+   std::ios_base::fmtflags f = out.flags();
+
+   out << setprecision(15) << setiosflags(ios::fixed)
+       << "\nossimRadarSat2Model class data members:\n"
+       << "_n_srgr: " << _n_srgr << "\n";
+
+   ossim_uint32 idx = 0;
+   std::vector<double>::const_iterator i = _srgr_update.begin();
+   while ( i !=  _srgr_update.end() )
+   {
+      out << "sr_gr_update_" << idx << ": " << (*i) << "\n";
+      ++i;
+      ++idx;
+   }
+
+   idx = 0;
+   i = _SrGr_R0.begin();
+   while ( i !=  _SrGr_R0.end() )
+   {
+      out << "sr_gr_r0_" << idx << ": " << (*i) << "\n";
+      ++i;
+      ++idx;
+   }
+
+   idx = 0;
+   std::vector< std::vector<double> >::const_iterator i2 =
+      _SrGr_coeffs.begin();
+   while ( i2 !=  _SrGr_coeffs.end() )
+   {
+      ossim_uint32 idx2 = 0;
+      i = (*i2).begin();
+      while ( i != (*i2).end() )
+      {
+         out << "sr_gr_coeffs_" << idx << "_" << idx2 << ": " << (*i) << "\n";
+         ++i;
+         ++idx2;
+      }
+      ++i2;
+      ++idx;
+   }
+
+   ossimGeometricSarSensorModel::print(out);
+   
+
+   // Reset flags.
+   out.setf(f);
+
+   return out;
+}
+
+bool ossimRadarSat2Model::InitSensorParams(const ossimKeywordlist &kwl,
+                                           const char *prefix)
+{
+
+   // sensor frequencies
+   const char* central_freq_str = kwl.find(prefix,"central_freq");
+   double central_freq = atof(central_freq_str);
+   const char* fr_str = kwl.find(prefix,"fr");
+   double fr = atof(fr_str);
+   const char* fa_str = kwl.find(prefix,"fa");
+   double fa = atof(fa_str);
+
+   //number of different looks
+   const char* n_azilok_str = kwl.find(prefix,"n_azilok");
+   double n_azilok = atof(n_azilok_str);
+   const char* n_rnglok_str = kwl.find(prefix,"n_rnglok");
+   double n_rnglok = atof(n_rnglok_str);
+
+   //ellipsoid parameters
+   const char* ellip_maj_str = kwl.find(prefix,"ellip_maj");
+   double ellip_maj = atof(ellip_maj_str) * 1000.0;  // km -> m
+   const char* ellip_min_str = kwl.find(prefix,"ellip_min");
+   double ellip_min = atof(ellip_min_str) * 1000.0;  // km -> m
+
+   if(_sensor != 0)
+   {
+      delete _sensor;
+   }
+
+   _sensor = new SensorParams();
+
+   const char* lineTimeOrdering_str = kwl.find(prefix,"lineTimeOrdering");
+   std::string lineTimeOrdering(lineTimeOrdering_str) ;
+   const char* pixelTimeOrdering_str = kwl.find(prefix,"pixelTimeOrdering");
+   std::string pixelTimeOrdering(pixelTimeOrdering_str) ;
+   if (pixelTimeOrdering == "Increasing") _sensor->set_col_direction(1);
+   else _sensor->set_col_direction(- 1);
+   if (lineTimeOrdering == "Increasing") _sensor->set_lin_direction(1);
+   else _sensor->set_lin_direction(- 1);
+
+   const char* lookDirection_str = kwl.find(prefix,"lookDirection");
+   std::string lookDirection(lookDirection_str) ;
+   if ((lookDirection == "Right")||(lookDirection == "RIGHT")) _sensor->set_sightDirection(SensorParams::Right) ;
+   else _sensor->set_sightDirection(SensorParams::Left) ;
+
+   _sensor->set_sf(fr);
+   const double CLUM        = 2.99792458e+8 ;
+   double wave_length = CLUM / central_freq ;
+   _sensor->set_rwl(wave_length);
+   _sensor->set_nAzimuthLook(n_azilok);
+   _sensor->set_nRangeLook(n_rnglok);
+
+   // fa is the processing PRF
+   _sensor->set_prf(fa * n_azilok);
+
+   _sensor->set_semiMajorAxis(ellip_maj) ;
+   _sensor->set_semiMinorAxis(ellip_min) ;
+
+   return true;
+}
+
+bool ossimRadarSat2Model::InitPlatformPosition(const ossimKeywordlist &kwl, const char *prefix)
+{
+   /*
+    * Retrieval of ephemerisis number
+    */
+   const char* neph_str = kwl.find(prefix,"neph");
+   int neph = atoi(neph_str);
+
+   Ephemeris** ephemeris = new Ephemeris*[neph];
+   for (int i = 0; i < neph; ++i)
+   {
+      ephemeris[i] = 0; // In case of early termination, for delete block.
+   }
+
+   /*
+    * Retrieval of ephemerisis
+    */
+   for (int i=0;i<neph;i++)
+   {
+      double pos[3];
+      double vit[3];
+      char name[64];
+
+
+      sprintf(name,"eph%i_date",i);
+      const char* date_str = kwl.find(prefix,name);
+
+      sprintf(name,"eph%i_posX",i);
+      const char* px_str = kwl.find(prefix,name);
+      pos[0] = atof(px_str);
+
+      sprintf(name,"eph%i_posY",i);
+      const char* py_str = kwl.find(prefix,name);
+      pos[1] = atof(py_str);
+
+      sprintf(name,"eph%i_posZ",i);
+      const char* pz_str = kwl.find(prefix,name);
+      pos[2] = atof(pz_str);
+
+
+      sprintf(name,"eph%i_velX",i);
+      const char* vx_str = kwl.find(prefix,name);
+      vit[0] = atof(vx_str) ;
+
+      sprintf(name,"eph%i_velY",i);
+      const char* vy_str = kwl.find(prefix,name);
+      vit[1] = atof(vy_str) ;
+
+      sprintf(name,"eph%i_velZ",i);
+      const char* vz_str = kwl.find(prefix,name);
+      vit[2] = atof(vz_str) ;
+
+      /*
+       * Conversion to JSD Date
+       */
+      std::string utcString(date_str);
+      CivilDateTime eph_civil_date;
+
+      if (! ossim::iso8601TimeStringToCivilDate(utcString, eph_civil_date))
+      {
+         for (i=0;i<neph;++i)
+         {
+            delete ephemeris[i];
+         }
+         delete[] ephemeris;
+         ephemeris = 0;
+         
+         return false;
+      }
+
+      JSDDateTime eph_jsd_date(eph_civil_date);
+
+      GeographicEphemeris* eph = new GeographicEphemeris(eph_jsd_date,pos,vit);
+
+      ephemeris[i] = eph;
+   }
+
+   /*
+    * Creation of the platform position interpolator
+    */
+   if (_platformPosition != 0)
+   {
+      delete _platformPosition;
+   }
+   _platformPosition = new PlatformPosition(ephemeris,neph);
+
+   /*
+    * Free of memory used by ephemerisis list : the constructor copies the ephemerisis
+    */
+   for (int i=0;i<neph;i++)
+   {
+      delete ephemeris[i];
+   }
+   delete[] ephemeris;
+   ephemeris = 0;
+
+   return true;
+}
+
+bool ossimRadarSat2Model::InitRefPoint(const ossimKeywordlist &kwl,
+                                       const char *prefix)
+{
+   // in order to use ossimSensorModel::lineSampleToWorld
+   const char* nbCol_str = kwl.find(prefix,"nbCol");
+   const char* nbLin_str = kwl.find(prefix,"nbLin");
+   theImageSize.x      = atoi(nbCol_str);
+   theImageSize.y      = atoi(nbLin_str);
+   theImageClipRect    = ossimDrect(0, 0, theImageSize.x-1, theImageSize.y-1);
+
+   // no reference point (e.g. scene center) is given in the annotation file
+   // we choose to use the upper left corner as reference point
+   if(_refPoint == 0)
+   {
+      _refPoint = new RefPoint();
+   }
+
+   _refPoint->set_pix_col(0);    // upper left corner
+   _refPoint->set_pix_line(0);  // upper left corner
+
+   const char* zeroDopplerTimeFirstLine_str = kwl.find(prefix,"zeroDopplerTimeFirstLine");
+   std::string zeroDopplerTimeFirstLine(zeroDopplerTimeFirstLine_str);
+  
+   if(_platformPosition != 0)
+   {
+      CivilDateTime * date = new CivilDateTime() ;
+      if (! ossim::iso8601TimeStringToCivilDate(zeroDopplerTimeFirstLine, *date)) return false ;
+      
+      if (_sensor->get_lin_direction() == -1) {
+         double time = (double) date->get_second() + date->get_decimal() ;  // upper left corner
+         time += theImageSize.y / _sensor->get_prf() ;
+         date->set_second((int) floor(time)) ;
+         date->set_decimal(time - floor(time)) ;
+      }
+
+      Ephemeris* ephemeris = _platformPosition->Interpolate((JSDDateTime)*date);
+      if (ephemeris == 0) return false ;
+      _refPoint->set_ephemeris(ephemeris);
+
+      delete ephemeris;
+      ephemeris = 0;
+      delete date;
+      date = 0;
+   }
+   else
+   {
+      return false;
+   }
+
+   const char* slantRangeNearEdge_str = kwl.find(prefix,"slantRangeNearEdge");
+   double distance = atof(slantRangeNearEdge_str);
+
+   //---
+   // NOTE:  initSRGR method must be called before this method.
+   // in the case of Georeferenced images, the ground range is stored in
+   // place of the slant range
+   // (used for SlantRange computation relative to reference point, necessary
+   // for optimization)
+   //---
+   if (_isProductGeoreferenced)
+   {
+      if (_sensor->get_col_direction() == 1)
+      {
+         distance += 0.0; // upper left corner
+      }
+      else
+      {
+         distance += theImageSize.x * theGSD.x;
+      }
+   }
+
+   _refPoint->set_distance(distance);
+
+   // Ground Control Points extracted from the model
+   std::list<ossimGpt> groundGcpCoordinates ;
+   std::list<ossimDpt> imageGcpCoordinates ;
+   const char* nTiePoints_str = kwl.find(prefix,"nTiePoints");
+   int nTiePoints = atoi(nTiePoints_str);
+   char name[64];
+   for (int k=0 ; k<nTiePoints ; k++) {
+      sprintf(name,"cornersCol%i",k);
+      const char* i_str = kwl.find(name);
+      int i = atoi(i_str);
+      sprintf(name,"cornersLin%i",k);
+      const char* j_str = kwl.find(name);
+      int j = atoi(j_str);
+      sprintf(name,"cornersLon%i",k);
+      const char* lon_str = kwl.find(name);
+      double lon = atof(lon_str);
+      sprintf(name,"cornersLat%i",k);
+      const char* lat_str = kwl.find(name);
+      double lat = atof(lat_str);
+      sprintf(name,"cornersHeight%i",k);
+      const char* height_str = kwl.find(name);
+      double height = atof(height_str);
+
+      ossimDpt imageGCP(i,j);
+      ossimGpt groundGCP(lat ,lon , height);
+      groundGcpCoordinates.push_back(groundGCP) ;
+      imageGcpCoordinates.push_back(imageGCP) ;
+   }
+
+   // Default optimization
+   optimizeModel(groundGcpCoordinates, imageGcpCoordinates) ;
+
+   return true;
+}
+
+bool ossimRadarSat2Model::InitSRGR(const ossimKeywordlist &kwl,
+                                   const char *prefix)
+{
+   const char* productType_str = kwl.find(prefix,"productType");
+   ossimString productType(productType_str);
+
+   _isProductGeoreferenced = (productType != "SLC") ;
+
+//    // Pixel spacing
+//    const char* pixel_spacing_str = kwl.find(prefix,"pixel_spacing_mean");
+//    _pixel_spacing = atof(pixel_spacing_str);
+
+//    // Number of columns
+//    const char* nbCol_str = kwl.find(prefix,"nbCol");
+//    _nbCol = atoi(nbCol_str);
+
+   // number of SRGR coefficient sets
+   const char* SrGr_coeffs_number_str = kwl.find(prefix,"SrGr_coeffs_number");
+   _n_srgr = atoi(SrGr_coeffs_number_str);
+
+   // SRGR coefficients and exponents
+   char name[64];
+   for(int i=0;i<_n_srgr;i++)
+   {
+      std::vector<double> srgr_set ;
+      for(int j=0;j<4;j++)
+      {
+         sprintf(name,"SrGr_coeffs_%i_%i",i,j);
+         const char* coeff_str = kwl.find(prefix,name);
+         double coeff = atof(coeff_str);
+         srgr_set.push_back(coeff);
+      }
+      _SrGr_coeffs.push_back(srgr_set);
+      // SRGR polynomial reference
+      sprintf(name,"SrGr_R0_%i",i);
+      const char* SrGr_R0_str = kwl.find(prefix,name);
+      _SrGr_R0.push_back(atof(SrGr_R0_str));
+      // SRGR update time
+      sprintf(name,"SrGr_update_%i",i);
+      const char* SrGr_update_str = kwl.find(prefix,name);
+      CivilDateTime SrGr_update_date ;
+      ossim::iso8601TimeStringToCivilDate(std::string(SrGr_update_str), SrGr_update_date) ;
+      _srgr_update.push_back((double) SrGr_update_date.get_second()+ SrGr_update_date.get_decimal());
+   }
+
+   return true;
+}
+
+int ossimRadarSat2Model::FindSRGRSetNumber(JSDDateTime date) const
+{
+   if (_n_srgr==0) return(-1) ;
+
+   double delays[20];
+   for (int i=0;i<_n_srgr;i++)
+   {
+      delays[i] = fabs(date.get_second()+date.get_decimal()-_srgr_update[i]) ;
+   }
+
+   int setNumber = 0 ;
+   double min_delay = delays[0] ;
+   for (int i=1;i<_n_srgr;i++)
+   {
+      if (delays[i]<min_delay) {
+         setNumber = i ;
+         min_delay = delays[i] ;
+      }
+   }
+   return setNumber ;
+}
+
+bool ossimRadarSat2Model::initSRGR(const ossimXmlDocument* xdoc,
+                                   const ossimRadarSat2ProductDoc& rsDoc)
+{
+   static const char MODULE[] = "ossimRadarSat2Model::initSRGR";
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)<< MODULE << " entered...\n";
+   }
+
+   bool result = true;
+
+   ossimString s;
+
+   // Get the product type.
+   if ( rsDoc.getProductType(xdoc, s) )
+   {
+      _isProductGeoreferenced = (s != "SLC");
+   }
+   else
+   {
+      result = false;
+   }
+
+   ossimString path =
+      "/product/imageGenerationParameters/slantRangeToGroundRange";
+   std::vector<ossimRefPtr<ossimXmlNode> > xnodes;
+   xdoc->findNodes(path, xnodes);
+   if ( xnodes.size() )
+   {
+      //---
+      // Set the number of slant range for each ground range (srgs)
+      // coefficients.
+      //---
+      _n_srgr = static_cast<int>(xnodes.size());
+
+      for (ossim_uint32 i = 0; i < xnodes.size(); ++i)
+      {
+         if (xnodes[i].valid())
+         {
+            ossimRefPtr<ossimXmlNode> node = 0;
+            node = xnodes[i]->findFirstNode(
+               ossimString("zeroDopplerAzimuthTime"));
+            if (node.valid())
+            {
+               CivilDateTime date;
+               ossim::iso8601TimeStringToCivilDate(node->getText(), date);
+               _srgr_update.push_back((double) date.get_second()+
+                                      date.get_decimal());
+            }
+
+            node = xnodes[i]->findFirstNode(
+               ossimString("groundRangeOrigin"));
+            if (node.valid())
+            {
+               _SrGr_R0.push_back(node->getText().toDouble());
+            }
+
+            node = xnodes[i]->findFirstNode(
+               ossimString("groundToSlantRangeCoefficients"));
+            if (node.valid())
+            {
+               std::vector<ossimString> vs;
+               node->getText().split(vs, ' ');
+               std::vector<double> vd;
+               for (ossim_uint32 idx = 0; idx < vs.size(); ++idx)
+               {
+                  vd.push_back(vs[idx].toDouble());
+               }
+               _SrGr_coeffs.push_back(vd);
+            }
+         }
+      }
+   }
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " exit status = " << (result?"true":"false\n")
+         << std::endl;
+   }
+
+   return result;
+}
+
+bool ossimRadarSat2Model::initPlatformPosition(
+   const ossimXmlDocument* xdoc, const ossimRadarSat2ProductDoc& rsDoc)
+{
+   static const char MODULE[] = "ossimRadarSat2Model::initPlatformPosition";
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)<< MODULE << " entered...\n";
+   }
+
+   // Initialize the platform position interpolator.
+   if (_platformPosition)
+   {
+      delete _platformPosition;
+   }
+
+   _platformPosition = new PlatformPosition();
+
+   bool result = rsDoc.initPlatformPosition(xdoc, _platformPosition);
+
+   if (!result)
+   {
+      delete _platformPosition;
+      _platformPosition = 0;
+   }
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " exit status = " << (result?"true":"false\n")
+         << std::endl;
+   }
+
+   return result;
+}
+
+bool ossimRadarSat2Model::initSensorParams(
+   const ossimXmlDocument* xdoc, const ossimRadarSat2ProductDoc& rsDoc)
+{
+   static const char MODULE[] = "ossimRadarSat2Model::initSensorParams";
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)<< MODULE << " entered...\n";
+   }
+
+   if (_sensor )
+   {
+      delete _sensor;
+   }
+   _sensor =  new SensorParams();
+
+   bool result = rsDoc.initSensorParams(xdoc, _sensor);
+
+   if (!result)
+   {
+      delete _sensor;
+      _sensor = 0;
+   }
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " exit status = " << (result?"true":"false\n")
+         << std::endl;
+   }
+
+   return result;
+}
+
+
+bool ossimRadarSat2Model::initRefPoint(const ossimXmlDocument* xdoc,
+                                       const ossimRadarSat2ProductDoc& rsDoc)
+{
+   static const char MODULE[] = "ossimRadarSat2Model::initRefPoint";
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)<< MODULE << " entered...\n";
+   }
+
+   if ( !_sensor || !_platformPosition )
+   {
+      if (traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG)
+            << MODULE << "null pointer error! exiting\n";
+      }
+      return false;
+   }
+
+   // Reference point.
+   if (_refPoint)
+   {
+      delete _refPoint;
+   }
+   _refPoint = new RefPoint();
+
+   // Ground Control Points extracted from the model.
+   std::list<ossimGpt> groundGcpCoordinates;
+   std::list<ossimDpt> imageGcpCoordinates;
+   if ( rsDoc.initTiePoints(xdoc,
+                            groundGcpCoordinates,
+                            imageGcpCoordinates) == false )
+   {
+      if (traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG)
+            << MODULE << "initTiePoint error! exiting\n";
+      }
+      return false;
+   }
+
+   if ( setModelRefPoint(groundGcpCoordinates, imageGcpCoordinates) )
+   {
+      _refPoint->set_pix_col(theRefImgPt.x);
+      _refPoint->set_pix_line(theRefImgPt.y);
+   }
+   else
+   {
+      // no reference point (e.g. scene center) is given in the annotation file
+      // we choose to use the upper left corner as reference point
+      _refPoint->set_pix_col(0);   // upper left corner
+      _refPoint->set_pix_line(0);  // upper left corner
+   }
+
+   ossimString s;
+   CivilDateTime date;
+   if ( rsDoc.getZeroDopplerTimeFirstLine(xdoc, s) )
+   {
+      if (! ossim::iso8601TimeStringToCivilDate(s, date))
+      {
+         if (traceDebug())
+         {
+            ossimNotify(ossimNotifyLevel_DEBUG)
+               << MODULE << "getZeroDopplerTimeFirstLine error! exiting\n";
+         }
+         return false;
+      }
+   }
+
+   if (_sensor->get_lin_direction() == -1)
+   {
+      // upper left corner
+      double time = (double) date.get_second() + date.get_decimal();
+      time += theImageSize.y / _sensor->get_prf() ;
+      date.set_second((int) floor(time)) ;
+      date.set_decimal(time - floor(time));
+   }
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "date:\n"
+         << date
+         << "\n";
+   }
+
+   JSDDateTime jsdate(date);
+
+   // Ephemeris * ephemeris = _platformPosition->Interpolate((JSDDateTime)date);
+   Ephemeris * ephemeris = _platformPosition->Interpolate(jsdate);
+   if (ephemeris == 0)
+   {
+      if (traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG)
+            << MODULE << " Interpolate error! exiting\n";
+      }
+      return false;
+   }
+   _refPoint->set_ephemeris(ephemeris);
+   delete ephemeris;
+   ephemeris = 0;
+
+   double distance = 1;
+
+   // Only set distance to 
+   if (!_isProductGeoreferenced)
+   {
+	   if ( !rsDoc.getSlantRangeNearEdge(xdoc, s) )
+	   {
+		   if (traceDebug())
+		   {
+			   ossimNotify(ossimNotifyLevel_DEBUG)
+    
+				   << MODULE << "getSlantRangeNearEdge error! exiting\n";
+		   }      
+		   return false;
+	   }
+	   distance = s.toDouble();
+   }
+
+   //---
+   // in the case of Georeferenced images, the ground range is stored in
+   // place of the slant range
+   // (used for SlantRange computation relative to reference point,
+   // necessary for optimization)
+   //---
+   if (_isProductGeoreferenced)
+   {
+      if (_sensor->get_col_direction() == 1)
+      {
+         distance += 0 ; // upper left corner
+      }
+      else
+      {
+         distance += theImageSize.x * theGSD.x;
+      }
+   }
+
+
+   _refPoint->set_distance(distance);
+
+   // Default optimization
+   optimizeModel(groundGcpCoordinates, imageGcpCoordinates) ;
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " exit status = true\n";
+   }
+
+   return true;
+}
+
+
+bool ossimRadarSat2Model::InitLut( const ossimXmlDocument* xmlDocument,
+   			RadarSat2NoiseLevel& noise)
+{
+   static const char MODULE[] = "ossimRadarSat2Model::initLut";
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)<< MODULE << " entered...\n";
+   }
+
+   ossimString xpath;
+   ossimString incidenceAngleCorrectionName;
+   std::vector<ossimRefPtr<ossimXmlNode> > xml_nodes;
+   std::vector<ossimRefPtr<ossimXmlNode> >::iterator node;
+   ossimFilename  lutXmlFile;
+      
+   incidenceAngleCorrectionName = noise.get_incidenceAngleCorrectionName();     
+
+   xpath = "/product/imageAttributes/lookupTable";
+   xml_nodes.clear();
+   xmlDocument->findNodes(xpath, xml_nodes);
+   if(xml_nodes.size() == 0)
+   {
+     setErrorStatus();
+     if(traceDebug())
+     {
+  	    ossimNotify(ossimNotifyLevel_DEBUG)
+    		      	<< MODULE << " DEBUG:"
+            	  	<< "\nCould not find: " << xpath
+               		<< std::endl;
+      }
+      return false;
+   }  
+        
+   node = xml_nodes.begin();
+   while (node != xml_nodes.end())
+   {
+		if( (*node)->getAttributeValue("incidenceAngleCorrection") == incidenceAngleCorrectionName )
+		{
+			// Get the xml file.
+			lutXmlFile = _productXmlFile.expand().path().dirCat((*node)->getText());
+
+   			if ( lutXmlFile.exists() )
+   			{
+      			//---
+      			// Instantiate the XML parser:
+      			//---
+      			ossimXmlDocument* xmlLutDocument = new ossimXmlDocument();
+      			if ( xmlLutDocument->openFile(lutXmlFile) )
+      			{
+   					std::vector<ossimRefPtr<ossimXmlNode> > xml_lutNodes;
+   					ossimString s;
+   					
+   					xpath = "/lut/offset";
+   					xml_lutNodes.clear();
+   					xmlLutDocument->findNodes(xpath, xml_lutNodes);   					
+   					if(xml_lutNodes.size() == 0)
+   					{
+     					setErrorStatus();
+     					if(traceDebug())
+     					{
+  	    					ossimNotify(ossimNotifyLevel_DEBUG)
+    		      					<< MODULE << " DEBUG:"
+            	  					<< "\nCould not find: " << xpath
+               						<< std::endl;
+      					}
+      					return false;
+   					}
+   					ossim_float64 offset = xml_lutNodes[0]->getText().toFloat64();  
+					noise.set_offset(offset);				
+								
+   					xpath = "/lut/gains";
+   					xml_lutNodes.clear();
+   					xmlLutDocument->findNodes(xpath, xml_lutNodes);   					
+   					if(xml_lutNodes.size() == 0)
+   					{
+     					setErrorStatus();
+     					if(traceDebug())
+     					{
+  	    					ossimNotify(ossimNotifyLevel_DEBUG)
+    		      					<< MODULE << " DEBUG:"
+            	  					<< "\nCould not find: " << xpath
+               						<< std::endl;
+      					}
+      					return false;
+   					}  
+					noise.set_gain(xml_lutNodes[0]->getText());	
+				}
+   			}
+		}
+    	++node;	
+   }
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)<< MODULE << " leaving...\n";
+   }   
+
+   return true;
+}
+
+bool ossimRadarSat2Model::InitRefNoiseLevel(
+   const ossimXmlDocument* xmlDocument)
+{
+   static const char MODULE[] = "ossimRadarSat2Model::initRefNoiseLevel";
+
+   ossimString xpath;
+   std::vector<ossimRefPtr<ossimXmlNode> > xml_nodes;
+   std::vector<ossimRefPtr<ossimXmlNode> > sub_nodes;
+   std::vector<ossimRefPtr<ossimXmlNode> >::iterator node;
+   RadarSat2NoiseLevel ev;
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)<< MODULE << " entered...\n";
+   }
+
+   _noiseLevel.clear();
+   
+   
+   xpath = "/product/sourceAttributes/radarParameters/referenceNoiseLevel";
+   xml_nodes.clear();
+   xmlDocument->findNodes(xpath, xml_nodes);
+   if(xml_nodes.size() == 0)
+   {
+     setErrorStatus();
+     if(traceDebug())
+     {
+  	    ossimNotify(ossimNotifyLevel_DEBUG)
+    		      	<< MODULE << " DEBUG:"
+            	  	<< "\nCould not find: " << xpath
+               		<< std::endl;
+      }
+      return false;
+   }  
+        
+   node = xml_nodes.begin();
+   while (node != xml_nodes.end())
+   {
+   	
+   	ev.set_incidenceAngleCorrectionName( (*node)->getAttributeValue("incidenceAngleCorrection") ); 
+   	
+    sub_nodes.clear();
+    xpath = "pixelFirstNoiseValue";
+    (*node)->findChildNodes(xpath, sub_nodes);
+    if (sub_nodes.size() == 0)
+    {
+      	setErrorStatus();
+         if(traceDebug())
+         {
+            ossimNotify(ossimNotifyLevel_DEBUG)
+               << MODULE << " DEBUG:"
+               << "\nCould not find: " << xpath
+               << std::endl;
+         }
+      	return false;
+    }
+    ev.set_pixelFirstNoiseValue(sub_nodes[0]->getText().toUInt32());
+
+    sub_nodes.clear();
+    xpath = "stepSize";
+    (*node)->findChildNodes(xpath, sub_nodes);
+    if (sub_nodes.size() == 0)
+    {
+      	setErrorStatus();
+         if(traceDebug())
+         {
+            ossimNotify(ossimNotifyLevel_DEBUG)
+               << MODULE << " DEBUG:"
+               << "\nCould not find: " << xpath
+               << std::endl;
+         }
+      	return false;
+    }
+    ev.set_stepSize(sub_nodes[0]->getText().toUInt32());
+
+    sub_nodes.clear();
+    xpath = "numberOfNoiseLevelValues";
+    (*node)->findChildNodes(xpath, sub_nodes);
+    if (sub_nodes.size() == 0)
+    {
+      	setErrorStatus();
+         if(traceDebug())
+         {
+            ossimNotify(ossimNotifyLevel_DEBUG)
+               << MODULE << " DEBUG:"
+               << "\nCould not find: " << xpath
+               << std::endl;
+         }
+      	return false;
+    }
+    ev.set_numberOfNoiseLevelValues(sub_nodes[0]->getText().toUInt32());
+
+    sub_nodes.clear();
+    xpath = "noiseLevelValues";
+    (*node)->findChildNodes(xpath, sub_nodes);
+    if (sub_nodes.size() == 0)
+    {
+      	setErrorStatus();
+         if(traceDebug())
+         {
+            ossimNotify(ossimNotifyLevel_DEBUG)
+               << MODULE << " DEBUG:"
+               << "\nCould not find: " << xpath
+               << std::endl;
+         }
+      	return false;
+    }
+   	ev.set_units( sub_nodes[0]->getAttributeValue("units") ); 
+
+
+    std::vector<ossimString> s2;      
+    std::vector<ossim_float64> noiseLevelValues;
+    s2.clear();
+    noiseLevelValues.clear();
+    s2 = sub_nodes[0]->getText().split(" ");
+	for(ossim_uint32 i = 0; i < s2.size(); ++i)
+	{
+		noiseLevelValues.push_back( s2[i].toFloat64() );
+	}
+   	ev.set_noiseLevelValues( noiseLevelValues ); 
+
+	InitLut(xmlDocument, ev);
+
+
+    _noiseLevel.push_back(ev);
+
+    ++node;
+   }
+ 
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)<< MODULE << " leaving...\n";
+   }   
+
+   return true;
+}
+
+
+
+
+bool ossimRadarSat2Model::saveState(ossimKeywordlist& kwl,
+                                    const char* prefix) const
+{
+   static const char MODULE[] = "ossimRadarSat2Model::saveState";
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)<< MODULE << " entered...\n";
+   }
+
+   bool result = true;
+
+   // Save our state:
+   kwl.add(prefix, PRODUCT_XML_FILE_KW, _productXmlFile.c_str());
+   kwl.add(prefix, NUMBER_SRGR_COEFFICIENTS_KW, _n_srgr);
+
+   // Make sure all the arrays are equal in size.
+   const ossim_uint32 COUNT = static_cast<ossim_uint32>(_n_srgr);
+
+   if ( (_srgr_update.size() == COUNT) &&
+        (_SrGr_R0.size()     == COUNT) &&
+        (_SrGr_coeffs.size() == COUNT) )
+   {
+      ossimString kw1 = "sr_gr_update_";
+      ossimString kw2 = "sr_gr_r0_";
+      ossimString kw3 = "sr_gr_coeffs_";
+
+      for(ossim_uint32 i = 0; i < COUNT; ++i)
+      {
+         ossimString iStr = ossimString::toString(i);
+
+         ossimString kw = kw1;
+         kw += iStr;
+         kwl.add(prefix, kw, _srgr_update[i]);
+
+         kw = kw2;
+         kw += iStr;
+         kwl.add(prefix, kw, _SrGr_R0[i]);
+
+         for (ossim_uint32 j = 0; j < _SrGr_coeffs[i].size(); ++j)
+         {
+            ossimString jStr = ossimString::toString(j);
+            kw = kw3;
+            kw += iStr;
+            kw += "_";
+            kw += jStr;
+            kwl.add(prefix, kw,_SrGr_coeffs[i][j]);
+         }
+      }
+   }
+   else
+   {
+      result = false;
+   }
+
+   if (result)
+   {
+      // Call base save state:
+      result = ossimGeometricSarSensorModel::saveState(kwl, prefix);
+   }
+
+   if (result)
+   {
+      	for(ossim_uint32 i = 0; i < _noiseLevel.size(); ++i)
+   		{	
+   				_noiseLevel[i].saveState(kwl, prefix);
+   		}
+       
+   }
+
+   //---
+   // Uncomment to force load from product file instead of loadState.
+   //---
+   //if (result)
+   //{
+   // kwl.add(prefix, LOAD_FROM_PRODUCT_FILE_KW, "true");
+   //}
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " exit status = " << (result?"true":"false\n")
+         << std::endl;
+   }
+
+   return result;
+}
+
+bool ossimRadarSat2Model::loadState (const ossimKeywordlist &kwl,
+                                     const char *prefix)
+{
+   static const char MODULE[] = "ossimRadarSat2Model::loadState";
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " entered...\n";
+   }
+
+   const char* lookup = 0;
+   ossimString s;
+
+   // Check the type first.
+   lookup = kwl.find(prefix, ossimKeywordNames::TYPE_KW);
+   if (lookup)
+   {
+      s = lookup;
+      if (s != getClassName())
+      {
+         return false;
+      }
+   }
+
+   // Get the product.xml file name.
+   lookup = kwl.find(prefix, PRODUCT_XML_FILE_KW);
+   if (lookup)
+   {
+      _productXmlFile = lookup;
+
+      // See if caller wants to load from xml vice keyword list.
+      lookup = kwl.find(prefix, LOAD_FROM_PRODUCT_FILE_KW);
+      if (lookup)
+      {
+         s = lookup;
+         if ( s.toBool() )
+         {
+            // Loading from product.xml file.
+            return open(_productXmlFile);
+         }
+      }
+   }
+
+   //---
+   // Temp:  This must be cleared or you end up with a bounding rect of all
+   // zero's.
+   //---
+   theBoundGndPolygon.clear();
+
+   // Load the base class.
+   bool result = ossimGeometricSarSensorModel::loadState(kwl, prefix);
+
+
+   if (result)
+   {
+      lookup = kwl.find(prefix, NUMBER_SRGR_COEFFICIENTS_KW);
+      if (lookup)
+      {
+         s = lookup;
+         _n_srgr = s.toInt();
+      }
+      else
+      {
+         if (traceDebug())
+         {
+            ossimNotify(ossimNotifyLevel_WARN)
+               << MODULE
+               << "\nRequired keyword not found: "
+               << NUMBER_SRGR_COEFFICIENTS_KW << "\n";
+         }
+         result = false;
+      }
+
+      if (result && _n_srgr)
+      {
+         const ossim_uint32 COUNT = static_cast<ossim_uint32>(_n_srgr);
+
+         _srgr_update.resize(COUNT);
+         _SrGr_R0.resize(COUNT);
+         _SrGr_coeffs.resize(COUNT);
+
+         ossimString kw1 = "sr_gr_update_";
+         ossimString kw2 = "sr_gr_r0_";
+         ossimString kw3 = "sr_gr_coeffs_";
+
+         for(ossim_uint32 i = 0; i < COUNT; ++i)
+         {
+            ossimString kw;
+            ossimString iStr = ossimString::toString(i);
+
+            // Get the _srgr_update's.
+            kw = kw1;
+            kw += iStr;
+
+            lookup = kwl.find(prefix, kw);
+            if (lookup)
+            {
+               s = lookup;
+               _srgr_update[i] = s.toDouble();
+            }
+            else
+            {
+               if (traceDebug())
+               {
+                  ossimNotify(ossimNotifyLevel_WARN)
+                     << MODULE
+                     << "\nRequired keyword not found: "
+                     << kw << "\n";
+               }
+               result = false;
+            }
+
+            // Get the sr_gr_r0_'s.
+            kw = kw2;
+            kw += iStr;
+            lookup = kwl.find(prefix, kw);
+            if (lookup)
+            {
+               s = lookup;
+               _SrGr_R0[i] = s.toDouble();
+            }
+            else
+            {
+               if (traceDebug())
+               {
+                  ossimNotify(ossimNotifyLevel_WARN)
+                     << MODULE
+                     << "\nRequired keyword not found: "
+                     << kw << "\n";
+               }
+               result = false;
+            }
+
+            //---
+            // Get the _SrGr_coeffs.
+            // Note we are assuming a count of 6.
+            //---
+            const ossim_uint32 COEFFS_COUNT = 6;
+            _SrGr_coeffs[i].resize(COEFFS_COUNT);
+
+            for (ossim_uint32 j = 0; j < COEFFS_COUNT; ++j)
+            {
+               ossimString jStr = ossimString::toString(j);
+               kw = kw3;
+               kw += iStr;
+               kw += "_";
+               kw += jStr;
+               lookup = kwl.find(prefix, kw);
+               if (lookup)
+               {
+                  s = lookup;
+                  _SrGr_coeffs[i][j] = s.toDouble();
+               }
+               else
+               {
+                  if (traceDebug())
+                  {
+                     ossimNotify(ossimNotifyLevel_WARN)
+                        << MODULE
+                        << "\nRequired keyword not found: "
+                        << kw << "\n";
+                  }
+                  result = false;
+               }
+            }
+
+         } // matches: for(ossim_uint32 i = 0; i < COUNT; ++i)
+
+      } // matches:  if (_n_srgr)
+      else
+      {
+         result = false;
+      }
+
+   } // matches: if (result)
+
+	if(result)
+	{
+      	for(ossim_uint32 i = 0; i < _noiseLevel.size(); ++i)
+   		{	
+   				_noiseLevel[i].loadState(kwl, prefix);
+   		}		
+	}
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " exit status = " << (result?"true":"false\n")
+         << std::endl;
+   }
+
+   return result;
+}
+
+bool ossimRadarSat2Model::setModelRefPoint(
+   const std::list<ossimGpt>& groundGcpCoordinates,
+   const std::list<ossimDpt>& imageGcpCoordinates)
+{
+   static const char MODULE[] = "ossimRadarSat2Model::setModelRefPoint";
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)<< MODULE << " entered...\n";
+   }
+
+   bool result = false;
+
+   if ( !theImageSize.hasNans() &&
+        (groundGcpCoordinates.size() == imageGcpCoordinates.size()) )
+   {
+      const ossim_float64 THRESHOLD = 1.0;
+      ossimDpt center;
+      center.x = theImageSize.x / 2.0;
+      center.y = theImageSize.y / 2.0;
+      std::list<ossimGpt>::const_iterator gi = groundGcpCoordinates.begin();
+      std::list<ossimDpt>::const_iterator di = imageGcpCoordinates.begin();
+
+      result = true;
+
+      // Set the first point to reference for starters:
+      theRefImgPt = (*di);
+      theRefGndPt = (*gi);
+      ++gi;
+      ++di;
+         
+      // Loop to find the image point closest to center.
+      while( gi != groundGcpCoordinates.end() )
+      {
+         ossim_float64 deltaX  = std::fabs( (*di).x - center.x);
+         ossim_float64 deltaY  = std::fabs( (*di).y - center.y);
+         ossim_float64 deltaX2 = std::fabs( theRefImgPt.x - center.x);
+         ossim_float64 deltaY2 = std::fabs( theRefImgPt.y - center.y);
+
+         if ( (deltaX <= deltaX2) && (deltaY <= deltaY2) )
+         {
+            // Closer to center than previous:
+            theRefImgPt = (*di);
+            theRefGndPt = (*gi);
+
+            // If threshold is met get out of loop:
+            if ( (deltaX <= THRESHOLD) && (deltaY <= THRESHOLD) )
+            {
+               break;
+            }
+         }
+
+         ++gi;
+         ++di;
+
+      } // matches: while( gi != groundGcpCoordinates.end() )
+   }
+
+   if (traceDebug())
+   {
+      if ( result )
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG)
+            << "image reference point: " << theRefImgPt
+            << "\nground reference point: " << theRefGndPt
+            << "\n";
+      }
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " exit status = " << (result?"true":"false\n")
+         << std::endl;
+   }
+
+   return result;
+
+} // End: bool ossimRadarSat2Model::setModelRefPoint( ... )
+   
+} // End: namespace ossimplugins
+
diff --git a/ossim_plugins/ossim/ossimRadarSat2Model.h b/ossim_plugins/ossim/ossimRadarSat2Model.h
new file mode 100644
index 0000000..3be7d19
--- /dev/null
+++ b/ossim_plugins/ossim/ossimRadarSat2Model.h
@@ -0,0 +1,199 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef ossimRadarSat2Model_H
+#define ossimRadarSat2Model_H 1
+
+#include <ossimPluginConstants.h>
+#include <ossimGeometricSarSensorModel.h>
+#include <ossim/projection/ossimMapProjection.h>
+#include <ossim/base/ossimIpt.h>
+#include <ossim/base/ossimFilename.h>
+#include <ossim/base/ossimGpt.h>
+#include <ossim/base/ossimDpt.h>
+#include <iostream>
+#include <list>
+
+#include <otb/CivilDateTime.h>
+#include <otb/RadarSat2NoiseLevel.h>
+
+class ossimFilename;
+class ossimString;
+class ossimXmlDocument;
+
+namespace ossimplugins
+{
+
+  class ossimRadarSat2ProductDoc;
+
+class PlatformPosition;
+class SensorParams;
+class RefPoint;
+
+/**
+ * @brief This class allows for direct localisation and indirect localisation
+ * using the RadarSat2 sensor model
+ */
+class OSSIM_PLUGINS_DLL ossimRadarSat2Model : public ossimGeometricSarSensorModel
+{
+public:
+   /** @brief default constructor */
+   ossimRadarSat2Model();
+
+   /** @brief copy constructor */
+   ossimRadarSat2Model(const ossimRadarSat2Model& rhs);
+
+   /** @brief Destructor */
+   virtual ~ossimRadarSat2Model();
+
+   /**
+    * @brief Method to return the class name.
+    * @return The name of this class.
+    */
+   virtual ossimString getClassName()   const;
+
+   /**
+    * @brief Returns pointer to a new instance, copy of this.
+    */
+   virtual ossimObject* dup() const;
+
+   /**
+    * @brief This function associates an image column number to a slant range
+    * when the image is georeferenced (ground projected)
+    * @param col Column coordinate of the image point
+    */
+   virtual double getSlantRangeFromGeoreferenced(double col) const;
+
+   /**
+    * @brief Method to intantial model from a file.  Attempts to find the
+    * required xml file.
+    *
+    * @param file
+    *
+    * @return true on success, false on error.
+    */
+   bool open(const ossimFilename& file);
+
+   /**
+    * @brief Method to save object state to a keyword list.
+    * @param kwl Keyword list to save to.
+    * @param prefix added to keys when saved.
+    * @return true on success, false on error.
+    */
+   virtual bool saveState(ossimKeywordlist& kwl,
+                          const char* prefix=0) const;
+
+   /**
+    * @brief Method to the load (recreate) the state of the object from a
+    * keyword list. Return true if ok or false on error.
+    * @return true if load OK, false on error
+    */
+   virtual bool loadState (const ossimKeywordlist &kwl, const char *prefix=0);
+
+   /*!
+    * METHOD: print()
+    * Fulfills base-class pure virtual. Dumps contents of object to ostream.
+    */
+   virtual std::ostream& print(std::ostream& out) const;
+
+private:
+
+   virtual bool InitPlatformPosition(const ossimKeywordlist &kwl,
+                                     const char *prefix);
+
+   virtual bool InitSensorParams(const ossimKeywordlist &kwl,
+                                 const char *prefix);
+
+   virtual bool InitRefPoint(const ossimKeywordlist &kwl,
+                             const char *prefix);
+
+   virtual bool InitRefNoiseLevel(const ossimXmlDocument* xmlDocument);
+   virtual bool InitLut( const ossimXmlDocument* xmlDocument,
+   						 RadarSat2NoiseLevel& noise);
+
+   /**
+    * @brief Initializes the Slant Range to Ground Range data sets :
+    * _srgr_update,_SrGr_R0,_SrGr_coeffs_number,_SrGr_coeffs,_nbCol,
+    * _pixel_spacing
+    */
+   virtual bool InitSRGR(const ossimKeywordlist &kwl, const char *prefix);
+
+   /**
+    * @brief Finds the SRGR data set which update time is the closest
+    * to the center scene time
+    */
+   int FindSRGRSetNumber(JSDDateTime date)  const;
+
+   /**
+    * @note This method must be called before initRefPoint.
+    */
+   bool initSRGR(const ossimXmlDocument* xdoc,
+                 const ossimRadarSat2ProductDoc& rsDoc);
+
+   bool initPlatformPosition(const ossimXmlDocument* xdoc,
+                             const ossimRadarSat2ProductDoc& rsDoc);
+
+   bool initSensorParams(const ossimXmlDocument* xdoc,
+                         const ossimRadarSat2ProductDoc& rsDoc);
+
+   /**
+    * @brief Method to initialize RefPoint object from
+    * RadarSat "product.xml" file.
+    * @param xdoc Opened product.xml file.
+    * @return true on success, false on error.
+    */
+   bool initRefPoint(const ossimXmlDocument* xdoc,
+                     const ossimRadarSat2ProductDoc& rsDoc);
+
+   /**
+    * @brief Sets ossimSensorModel members theRefImgPt and theRefGndPt from
+    * tie points.
+    * @param groundGcpCoordinates Ground tie points.
+    * @param imageGcpCoordinates Image tie points.
+    * @return true on success, false on error.
+    */
+   bool setModelRefPoint(const std::list<ossimGpt>& groundGcpCoordinates,
+                         const std::list<ossimDpt>& imageGcpCoordinates);
+
+   /**
+    * @brief Slant Range FOR EACH Ground Range (SRGR) number of coefficients
+    * sets
+    */
+   int   _n_srgr;
+
+   /**
+    * @brief Slant Range FOR EACH Ground Range coefficient sets update times
+    */
+
+   std::vector<double> _srgr_update;
+   /**
+    * @brief Slant Range FOR EACH Ground Range Projection reference point
+    */
+   std::vector<double> _SrGr_R0 ;
+
+   /**
+    * @brief Slant Range FOR EACH Ground Range Projection coefficients
+    */
+   std::vector< std::vector<double> > _SrGr_coeffs ;
+
+   /**
+    * @brief noise level values
+    */
+   std::vector< RadarSat2NoiseLevel > _noiseLevel ;
+
+
+TYPE_DATA
+
+};
+}
+
+#endif
+
diff --git a/ossim_plugins/ossim/ossimRadarSat2ProductDoc.cpp b/ossim_plugins/ossim/ossimRadarSat2ProductDoc.cpp
new file mode 100644
index 0000000..cacbb87
--- /dev/null
+++ b/ossim_plugins/ossim/ossimRadarSat2ProductDoc.cpp
@@ -0,0 +1,1153 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Description: Utility class to encapsulate parsing RadarSat2 product.xml
+// file.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include <ossimRadarSat2ProductDoc.h>
+#include <ossimPluginCommon.h>
+#include <otb/CivilDateTime.h>
+#include <otb/Ephemeris.h>
+#include <otb/GeographicEphemeris.h>
+#include <otb/JSDDateTime.h>
+#include <otb/PlatformPosition.h>
+#include <otb/SarSensor.h>
+#include <otb/SensorParams.h>
+#include <otb/RefPoint.h>
+#include <ossim/base/ossimDpt.h>
+#include <ossim/base/ossimFilename.h>
+#include <ossim/base/ossimGpt.h>
+#include <ossim/base/ossimIpt.h>
+#include <ossim/base/ossimNotify.h>
+#include <ossim/base/ossimRefPtr.h>
+#include <ossim/base/ossimString.h>
+#include <ossim/base/ossimTrace.h>
+#include <ossim/base/ossimXmlDocument.h>
+#include <ossim/base/ossimXmlNode.h>
+
+#include <sstream>
+#include <vector>
+
+using namespace std;
+
+
+namespace ossimplugins
+{
+
+
+// Static trace for debugging
+static ossimTrace traceDebug("ossimRadarSat2ProductDoc:debug");
+
+
+ossimRadarSat2ProductDoc::ossimRadarSat2ProductDoc()
+{
+}
+
+ossimRadarSat2ProductDoc::~ossimRadarSat2ProductDoc()
+{
+}
+
+bool ossimRadarSat2ProductDoc::isRadarSat2(const ossimXmlDocument* xdoc) const
+{
+   bool result = false;
+   if (xdoc)
+   {
+      ossimString s;
+      getSatellite(xdoc, s);
+      if (s.upcase() == "RADARSAT-2")
+      {
+         result = true;
+      }
+   }
+   return result;
+}
+
+bool ossimRadarSat2ProductDoc::initPlatformPosition(
+   const ossimXmlDocument* xdoc, PlatformPosition* pos) const
+{
+   static const char MODULE[] =
+      "ossimRadarSat2ProductDoc::initPlatformPosition";
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)<< MODULE << " entered...\n";
+   }
+
+   bool result = true;
+
+   if ( xdoc && pos )
+   {
+      // Get all the stateVector nodes.
+      ossimString path =
+         "/product/sourceAttributes/orbitAndAttitude/orbitInformation/stateVector";
+      std::vector<ossimRefPtr<ossimXmlNode> > xnodes;
+      xdoc->findNodes(path, xnodes);
+      if ( xnodes.size() )
+      {
+         const std::vector<ossimRefPtr<ossimXmlNode> >::size_type COUNT =
+            xnodes.size();
+
+         Ephemeris** ephemeris = new Ephemeris*[COUNT];
+         for (ossim_uint32 idx = 0; idx < COUNT; ++idx)
+         {
+            ephemeris[idx] = 0;
+         }
+
+         int nbrData = 0; // to keep track of good stateVector count.
+
+         ossimRefPtr<ossimXmlNode> svNode = 0; // stateVector node
+
+         for (ossim_uint32 i = 0 ; i < COUNT; ++i)
+         {
+            svNode = xnodes[i];
+            if ( !svNode )
+            {
+               result = false;
+               break;
+            }
+
+            double pos[3];
+            double vit[3];
+            CivilDateTime eph_civil_date;
+            ossimString s;
+
+            path = "timeStamp";
+            result = ossim::findFirstNode(path, svNode, s);
+            if (result)
+            {
+               ossim::iso8601TimeStringToCivilDate(s, eph_civil_date);
+            }
+            else
+            {
+               result = false;
+               ossimNotify(ossimNotifyLevel_WARN)
+                  << MODULE << " ERROR:\nNode not found: " << path
+                  << std::endl;
+               break;
+            }
+
+            path = "xPosition";
+            result = ossim::findFirstNode(path, svNode, s);
+            if (result)
+            {
+               pos[0] = s.toDouble();
+            }
+            else
+            {
+               result = false;
+               ossimNotify(ossimNotifyLevel_WARN)
+                  << MODULE << " ERROR:\nNode not found: " << path
+                  << std::endl;
+               break;
+            }
+
+            path = "yPosition";
+            result = ossim::findFirstNode(path, svNode, s);
+            if (result)
+            {
+               pos[1] = s.toDouble();
+            }
+            else
+            {
+               result = false;
+               ossimNotify(ossimNotifyLevel_WARN)
+                  << MODULE << " ERROR:\nNode not found: " << path
+                  << std::endl;
+               break;
+            }
+
+            path = "zPosition";
+            result = ossim::findFirstNode(path, svNode, s);
+            if (result)
+            {
+               pos[2] = s.toDouble();
+            }
+            else
+            {
+               result = false;
+               ossimNotify(ossimNotifyLevel_WARN)
+                  << MODULE << " ERROR:\nNode not found: " << path
+                  << std::endl;
+               break;
+            }
+
+            path = "xVelocity";
+            result = ossim::findFirstNode(path, svNode, s);
+            if (result)
+            {
+               vit[0] = s.toDouble();
+            }
+            else
+            {
+               result = false;
+               ossimNotify(ossimNotifyLevel_WARN)
+                  << MODULE << " ERROR:\nNode not found: " << path
+                  << std::endl;
+               break;
+            }
+
+            path = "yVelocity";
+            result = ossim::findFirstNode(path, svNode, s);
+            if (result)
+            {
+               vit[1] = s.toDouble();
+            }
+            else
+            {
+               result = false;
+               ossimNotify(ossimNotifyLevel_WARN)
+                  << MODULE << " ERROR:\nNode not found: " << path
+                  << std::endl;
+               break;
+            }
+
+            path = "zVelocity";
+            result = ossim::findFirstNode(path, svNode, s);
+            if (result)
+            {
+               vit[2] = s.toDouble();
+            }
+            else
+            {
+               result = false;
+               ossimNotify(ossimNotifyLevel_WARN)
+                  << MODULE << " ERROR:\nNode not found: " << path
+                  << std::endl;
+               break;
+            }
+
+            JSDDateTime eph_jsd_date(eph_civil_date);
+            GeographicEphemeris* eph =
+               new GeographicEphemeris(eph_jsd_date, pos, vit);
+            ephemeris[i] = eph;
+            ++nbrData;
+
+         } // matches:  for (int i = 0 ; i < nbrData; ++i)
+
+         if (result)
+         {
+            if (traceDebug())
+            {
+               ossimNotify(ossimNotifyLevel_DEBUG)
+                  << " DEBUG\nnbrData:  " << nbrData << "\n";
+            }
+            pos->setData(ephemeris, nbrData);
+         }
+
+         // Clean up.  Note: PlatformPosition::setData clones the ephemeris stuff.
+         for (int idx = 0; idx < nbrData; ++idx)
+         {
+            delete ephemeris[idx];
+         }
+         delete [] ephemeris;
+         ephemeris = 0;
+
+      } // matches: if ( xnodes.size() )
+      else
+      {
+         result = false;
+         ossimNotify(ossimNotifyLevel_WARN)
+            << MODULE << " ERROR:\nNodes not found: " << path << std::endl;
+      }
+
+   } // matches: if (xdoc && pos)
+   else
+   {
+      result = false;
+   }
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " exit status = " << (result?"true\n":"false\n");
+   }
+
+   return result;
+}
+
+bool ossimRadarSat2ProductDoc::initSensorParams(const ossimXmlDocument* xdoc,
+                                                SensorParams* sp) const
+{
+   bool result = true;
+
+   if (xdoc && sp)
+   {
+      ossimString s;
+
+      // Get the number of azimuth looks.
+      if ( getNumberOfAzimuthLooks(xdoc, s) )
+      {
+         sp->set_nAzimuthLook(s.toDouble());
+      }
+      else
+      {
+         result = false;
+      }
+
+      //---
+      // drb ???
+      // Get the nominal PRF
+      //---
+      double prf;
+      if ( getNominalPrf(xdoc, prf) )
+      {
+         //sp->set_prf(prf * sp->get_nAzimuthLook() );
+         sp->set_prf(prf);
+      }
+      else
+      {
+         result = false;
+      }
+
+      // Get the Sampling frequency.
+      if ( getAdcSamplingRate(xdoc, s) )
+      {
+         sp->set_sf(s.toDouble());
+      }
+      else
+      {
+         result = false;
+      }
+
+      // Get the radar wave length.
+      if ( getRadarCenterFrequency(xdoc, s) )
+      {
+         const double CLUM = 2.99792458e+8 ;
+         double waveLength = CLUM / s.toDouble();
+         sp->set_rwl(waveLength);
+      }
+      else
+      {
+         result = false;
+      }
+
+      // Get columns direction (1=increasing, -1=decreasing).
+      if ( getLineTimeOrdering(xdoc, s) )
+      {
+         if (s.downcase() == "increasing")
+         {
+            sp->set_col_direction(1);
+         }
+         else
+         {
+            sp->set_col_direction(-1);
+         }
+      }
+      else
+      {
+         result = false;
+      }
+
+      // Get lines direction (1=increasing, -1=decreasing).
+      if ( getPixelTimeOrdering(xdoc, s) )
+      {
+         if (s.downcase() == "increasing")
+         {
+            sp->set_lin_direction(1);
+         }
+         else
+         {
+            sp->set_lin_direction(-1);
+         }
+      }
+      else
+      {
+         result = false;
+      }
+
+      // Get the antenna pointing direction.
+      if ( getAntennaPointing(xdoc, s) )
+      {
+         if ( s.downcase() == "right")
+         {
+            sp->set_sightDirection(SensorParams::Right);
+         }
+         else
+         {
+            sp->set_sightDirection(SensorParams::Left);
+         }
+      }
+      else
+      {
+         result = false;
+      }
+
+      // Get the ellipsoid semi_major axis, m, Default : WGS84
+      if ( getSemiMajorAxis(xdoc, s) )
+      {
+         sp->set_semiMajorAxis(s.toDouble());
+      }
+      else
+      {
+         result = false;
+      }
+
+      //  Get the ellipsoid semi_minor axis, m, Default : WGS84
+      if ( getSemiMinorAxis(xdoc, s) )
+      {
+         sp->set_semiMinorAxis(s.toDouble());
+      }
+      else
+      {
+         result = false;
+      }
+
+
+      // Get the number of range looks.
+      if ( getNumberOfRangeLooks(xdoc, s) )
+      {
+         sp->set_nRangeLook(s.toDouble());
+      }
+      else
+      {
+         result = false;
+      }
+
+   } // matches: if (xdoc && sp)
+   else
+   {
+      result = false;
+   }
+
+   return result;
+}
+
+bool ossimRadarSat2ProductDoc::initImageSize(const ossimXmlDocument* xdoc,
+                                             ossimIpt& imageSize) const
+{
+   bool result = true;
+
+   if (xdoc)
+   {
+      ossimString s;
+      if ( getNumberOfSamplesPerLine(xdoc, s) )
+      {
+         imageSize.x = static_cast<ossim_int32>(s.toFloat64());
+      }
+      else
+      {
+         result = false;
+      }
+      if ( getNumberOfLines(xdoc, s) )
+      {
+         imageSize.y = static_cast<ossim_int32>(s.toFloat64());
+      }
+      else
+      {
+         result = false;
+      }
+   }
+   else
+   {
+      result = false;
+   }
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimRadarSat2ProductDoc::initImageSize DEBUG:\nimage size: "
+         << imageSize
+         << "\nexit status = " << (result?"true":"false")
+         << std::endl;
+   }
+
+   return result;
+}
+
+bool ossimRadarSat2ProductDoc::initGsd(const ossimXmlDocument* xdoc,
+                                       ossimDpt& gsd) const
+{
+   bool result = true;
+
+   if (xdoc)
+   {
+      ossimString s;
+      if ( getSampledPixelSpacing(xdoc, s) )
+      {
+         gsd.x = s.toFloat64();
+      }
+      else
+      {
+         result = false;
+      }
+      if ( getSampledLineSpacing(xdoc, s) )
+      {
+         gsd.y = s.toFloat64(s);
+      }
+      else
+      {
+         result = false;
+      }
+   }
+   else
+   {
+      result = false;
+   }
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimRadarSat2ProductDoc::initGsd DEBUG:\ngsd: " << gsd
+         << "\nexit status = " << (result?"true":"false")
+         << std::endl;
+   }
+
+   return result;
+}
+
+bool ossimRadarSat2ProductDoc::initTiePoints(const ossimXmlDocument* xdoc,
+                                             std::list<ossimGpt>& gcp,
+                                             std::list<ossimDpt>& icp) const
+{
+   static const char MODULE[] = "ossimRadarSat2ProductDoc::initTiePoints";
+
+   bool result = true;
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " DEBUG:\n";
+   }
+
+   if (xdoc)
+   {
+      ossimString path = "/product/imageAttributes/geographicInformation/geolocationGrid/imageTiePoint";
+      std::vector<ossimRefPtr<ossimXmlNode> > xnodes;
+      xdoc->findNodes(path, xnodes);
+      if ( xnodes.size() )
+      {
+         for (ossim_uint32 i = 0; i < xnodes.size(); ++i)
+         {
+            if (xnodes[i].valid())
+            {
+               ossimRefPtr<ossimXmlNode> icNode = 0; // imageCoordinate
+               icNode =
+                  xnodes[i]->findFirstNode(ossimString("imageCoordinate"));
+               if (icNode.valid())
+               {
+                  ossimString s;
+                  ossimDpt dpt;
+                  result = ossim::findFirstNode(ossimString("line"),
+                                                icNode, s);
+                  if (result)
+                  {
+                     dpt.y = s.toDouble();
+                  }
+                  result = ossim::findFirstNode(ossimString("pixel"),
+                                                icNode, s);
+                  if (result)
+                  {
+                     dpt.x = s.toDouble();
+                  }
+                  icp.push_back(dpt);
+
+                  if (traceDebug())
+                  {
+                     ossimNotify(ossimNotifyLevel_DEBUG)
+                        << "dpt" << i << ": " << dpt
+                        << "\n";
+                  }
+               }
+               else
+               {
+                  result = false;
+               }
+
+               ossimRefPtr<ossimXmlNode> gcNode = 0; // geodeticCoordinate
+               gcNode = xnodes[i]->findFirstNode(
+                  ossimString("geodeticCoordinate"));
+               if (gcNode.valid())
+               {
+                  ossimString s;
+                  ossimGpt gpt;
+                  result = ossim::findFirstNode(ossimString("latitude"),
+                                                gcNode, s);
+                  if (result)
+                  {
+                     gpt.lat = s.toDouble();
+                  }
+                  result = ossim::findFirstNode(ossimString("longitude"),
+                                                gcNode, s);
+                  if (result)
+                  {
+                     gpt.lon = s.toDouble();
+                  }
+                  result = ossim::findFirstNode(ossimString("height"),
+                                                gcNode, s);
+                  if (result)
+                  {
+                     gpt.hgt = s.toDouble();
+                  }
+                  gcp.push_back(gpt);
+
+                  if (traceDebug())
+                  {
+                     ossimNotify(ossimNotifyLevel_DEBUG)
+                        << "gpt" << i << ": " << gpt
+                        << "\n";
+                  }
+
+               } // matches: if (gcNode.valid())
+               else
+               {
+                  result = false;
+               }
+
+            } // if (xnodes[i].valid())
+
+         } // mathches: for (ossim_uint32 i = 0; i < xnodes.size(); ++i)
+
+      } // matches: if ( xnodes.size() )
+      else
+      {
+         result = false;  // No nodes found.
+      }
+   } // matches: if (xdoc)
+   else
+   {
+      result = false; // Null pointer passed in.
+   }
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " DEBUG: exit status = " << (result?"true":"false")
+         << std::endl;
+   }
+
+   return result;
+}
+
+
+RPCModel ossimRadarSat2ProductDoc::getRpcData(const ossimXmlDocument* xdoc) const
+{
+   ossimString path = "/product/imageAttributes/geographicInformation/rationalFunctions/satellite";
+
+   RPCModel model;
+
+   ossimString searchbiasError = "/product/imageAttributes/geographicInformation/rationalFunctions/biasError";				//the line (y-coordinate)
+   ossimString searchrandomError = "/product/imageAttributes/geographicInformation/rationalFunctions/randomError";			//the line (y-coordinate)
+   ossimString searchlineFitQuality = "/product/imageAttributes/geographicInformation/rationalFunctions/lineFitQuality";				//the line (y-coordinate)
+   ossimString searchpixelFitQuality = "/product/imageAttributes/geographicInformation/rationalFunctions/pixelFitQuality";				//the line (y-coordinate)
+   ossimString searchlineOffset = "/product/imageAttributes/geographicInformation/rationalFunctions/lineOffset";						//the line (y-coordinate)
+   ossimString searchpixelOffset = "/product/imageAttributes/geographicInformation/rationalFunctions/pixelOffset";						//the line (y-coordinate)
+   ossimString searchlatitudeOffset = "/product/imageAttributes/geographicInformation/rationalFunctions/latitudeOffset";				//the line (y-coordinate)
+   ossimString searchlongitudeOffset = "/product/imageAttributes/geographicInformation/rationalFunctions/longitudeOffset";				//the line (y-coordinate)
+   ossimString searchheightOffset = "/product/imageAttributes/geographicInformation/rationalFunctions/heightOffset";						//the line (y-coordinate)
+   ossimString searchlineScale = "/product/imageAttributes/geographicInformation/rationalFunctions/lineScale";						//the line (y-coordinate)
+   ossimString searchpixelScale = "/product/imageAttributes/geographicInformation/rationalFunctions/pixelScale";						//the line (y-coordinate)
+   ossimString searchlatitudeScale = "/product/imageAttributes/geographicInformation/rationalFunctions/latitudeScale";						//the line (y-coordinate)
+   ossimString searchlongitudeScale = "/product/imageAttributes/geographicInformation/rationalFunctions/longitudeScale";						//the line (y-coordinate)
+   ossimString searchheightScale = "/product/imageAttributes/geographicInformation/rationalFunctions/heightScale";						//the line (y-coordinate)
+
+   ossimString searchlineNumeratorCoefficients = "/product/imageAttributes/geographicInformation/rationalFunctions/lineNumeratorCoefficients";						//the line (y-coordinate)
+   ossimString searchlineDenominatorCoefficients = "/product/imageAttributes/geographicInformation/rationalFunctions/lineDenominatorCoefficients";						//the line (y-coordinate)
+   ossimString searchpixelNumeratorCoefficients = "/product/imageAttributes/geographicInformation/rationalFunctions/pixelNumeratorCoefficients";						//the line (y-coordinate)
+   ossimString searchpixelDenominatorCoefficients = "/product/imageAttributes/geographicInformation/rationalFunctions/pixelDenominatorCoefficients";						//the line (y-coordinate)
+
+
+   // strings to hold values found
+   ossimString biasErrorStr;;
+   ossimString randomErrorStr;
+   ossimString lineFitQualityStr;
+   ossimString pixelFitQualityStr;
+   ossimString lineOffsetStr;
+   ossimString pixelOffsetStr;
+   ossimString latitudeOffsetStr;
+   ossimString longitudeOffsetStr;
+   ossimString heightOffsetStr;
+   ossimString lineScaleStr;
+   ossimString pixelScaleStr;
+   ossimString latitudeScaleStr;
+   ossimString longitudeScaleStr;
+   ossimString heightScaleStr;
+
+   std::vector<ossimString> lineNumeratorCoefficientsStr;
+   std::vector<ossimString> lineDenominatorCoefficientsStr;
+   std::vector<ossimString> pixelNumeratorCoefficientsStr;
+   std::vector<ossimString> pixelDenominatorCoefficientsStr;
+
+
+   // doubles to hold values found
+   double biasError = 0;
+   double randomError = 0;
+   double lineFitQuality = 0;
+   double pixelFitQuality = 0;
+   double lineOffset = 0;
+   double pixelOffset = 0;
+   double latitudeOffset = 0;
+   double longitudeOffset = 0;
+   double heightOffset = 0;
+   double lineScale = 0;
+   double pixelScale = 0;
+   double latitudeScale = 0;
+   double longitudeScale = 0;
+   double heightScale = 0;
+
+   vector<double> lineNumeratorCoefficients = vector<double>(20,0);
+   vector<double> lineDenominatorCoefficients = vector<double>(20,0);
+   vector<double> pixelNumeratorCoefficients = vector<double>(20,0);
+   vector<double> pixelDenominatorCoefficients = vector<double>(20,0);
+
+   //the final string outputs to the text file
+
+   //check if this function is being called on the correct SAR data type
+   //function is only applicable for RS2 product.xml files
+   bool rs2Check = isRadarSat2(xdoc);
+   if (rs2Check)
+   {
+      if (!ossim::getPath(searchbiasError, xdoc, biasErrorStr))
+         ossimNotify(ossimNotifyLevel_WARN) << "ERROR: UNABLE TO FIND RS2 RPC COEFFICIENT INFORMATION" << endl;
+      biasError = biasErrorStr.toDouble();
+
+      if (!ossim::getPath(searchrandomError, xdoc, randomErrorStr))
+         ossimNotify(ossimNotifyLevel_WARN) << "ERROR: UNABLE TO FIND RS2 RPC COEFFICIENT INFORMATION" << endl;
+      randomError = randomErrorStr.toDouble();
+
+      if (!ossim::getPath(searchlineFitQuality, xdoc, lineFitQualityStr))
+         ossimNotify(ossimNotifyLevel_WARN) << "ERROR: UNABLE TO FIND RS2 RPC COEFFICIENT INFORMATION" << endl;
+      lineFitQuality = lineFitQualityStr.toDouble();
+
+      if (!ossim::getPath(searchpixelFitQuality, xdoc, pixelFitQualityStr))
+         ossimNotify(ossimNotifyLevel_WARN) << "ERROR: UNABLE TO FIND RS2 RPC COEFFICIENT INFORMATION" << endl;
+      pixelFitQuality = pixelFitQualityStr.toDouble();
+
+      if (!ossim::getPath(searchlineOffset, xdoc, lineOffsetStr))
+         ossimNotify(ossimNotifyLevel_WARN) << "ERROR: UNABLE TO FIND RS2 RPC COEFFICIENT INFORMATION" << endl;
+      lineOffset = lineOffsetStr.toDouble();
+
+      if (!ossim::getPath(searchpixelOffset, xdoc, pixelOffsetStr))
+         ossimNotify(ossimNotifyLevel_WARN) << "ERROR: UNABLE TO FIND RS2 RPC COEFFICIENT INFORMATION" << endl;
+      pixelOffset = pixelOffsetStr.toDouble();
+
+      if (!ossim::getPath(searchlatitudeOffset, xdoc, latitudeOffsetStr))
+         ossimNotify(ossimNotifyLevel_WARN) << "ERROR: UNABLE TO FIND RS2 RPC COEFFICIENT INFORMATION" << endl;
+      latitudeOffset = latitudeOffsetStr.toDouble();
+
+      if (!ossim::getPath(searchlongitudeOffset, xdoc, longitudeOffsetStr))
+         ossimNotify(ossimNotifyLevel_WARN) << "ERROR: UNABLE TO FIND RS2 RPC COEFFICIENT INFORMATION" << endl;
+      longitudeOffset = longitudeOffsetStr.toDouble();
+
+      if (!ossim::getPath(searchheightOffset, xdoc, heightOffsetStr))
+         ossimNotify(ossimNotifyLevel_WARN) << "ERROR: UNABLE TO FIND RS2 RPC COEFFICIENT INFORMATION" << endl;
+      heightOffset = heightOffsetStr.toDouble();
+
+      // --------------
+
+      if (!ossim::getPath(searchlineScale, xdoc, lineScaleStr))
+         ossimNotify(ossimNotifyLevel_WARN) << "ERROR: UNABLE TO FIND RS2 RPC COEFFICIENT INFORMATION" << endl;
+      lineScale = lineScaleStr.toDouble();
+
+
+      if (!ossim::getPath(searchpixelScale, xdoc, pixelScaleStr))
+         ossimNotify(ossimNotifyLevel_WARN) << "ERROR: UNABLE TO FIND RS2 RPC COEFFICIENT INFORMATION" << endl;
+      pixelScale = pixelScaleStr.toDouble();
+
+
+      if (!ossim::getPath(searchlatitudeScale, xdoc, latitudeScaleStr))
+         ossimNotify(ossimNotifyLevel_WARN) << "ERROR: UNABLE TO FIND RS2 RPC COEFFICIENT INFORMATION" << endl;
+      latitudeScale = latitudeScaleStr.toDouble();
+
+      // -----------------------
+
+      if (!ossim::getPath(searchlongitudeScale, xdoc, longitudeScaleStr))
+         ossimNotify(ossimNotifyLevel_WARN) << "ERROR: UNABLE TO FIND RS2 RPC COEFFICIENT INFORMATION" << endl;
+      longitudeScale = longitudeScaleStr.toDouble();
+
+
+      if (!ossim::getPath(searchheightScale, xdoc, heightScaleStr))
+         ossimNotify(ossimNotifyLevel_WARN) << "ERROR: UNABLE TO FIND RS2 RPC COEFFICIENT INFORMATION" << endl;
+      heightScale = heightScaleStr.toDouble();
+
+      // ---- parameters for reading in coeefs ------------
+
+      double val=0;
+
+      // -------------------------------------
+
+
+      if (!ossim::getPath(searchlineNumeratorCoefficients, xdoc, lineNumeratorCoefficientsStr))
+         ossimNotify(ossimNotifyLevel_WARN) << "ERROR: UNABLE TO FIND RS2 RPC COEFFICIENT INFORMATION" << endl;
+
+
+      string lineNumeratorCoefficientsStr_N = lineNumeratorCoefficientsStr[0];
+      // place into a stream
+      std::stringstream LNstream(lineNumeratorCoefficientsStr_N);
+
+      for (int i=0; i < 20; i ++)
+      {
+         LNstream >> val;
+         lineNumeratorCoefficients[i] = val;
+      }
+
+      // ------------------
+
+      if (!ossim::getPath(searchlineDenominatorCoefficients, xdoc, lineDenominatorCoefficientsStr))
+         ossimNotify(ossimNotifyLevel_WARN) << "ERROR: UNABLE TO FIND RS2 RPC COEFFICIENT INFORMATION" << endl;
+
+
+      string lineDenominatorCoefficientsStr_N = lineDenominatorCoefficientsStr[0];
+
+      // place into a stream
+      std::stringstream LDstream(lineDenominatorCoefficientsStr_N);
+
+      for (int i=0; i < 20; i ++)
+      {
+         LDstream >> val;
+         lineDenominatorCoefficients[i] = val;
+      }
+
+      // ------------------
+
+      if (!ossim::getPath(searchpixelNumeratorCoefficients, xdoc, pixelNumeratorCoefficientsStr))
+         ossimNotify(ossimNotifyLevel_WARN) << "ERROR: UNABLE TO FIND RS2 RPC COEFFICIENT INFORMATION" << endl;
+
+      string pixelNumeratorCoefficientsStr_N = pixelNumeratorCoefficientsStr[0];
+
+      // place into a stream
+      std::stringstream PNstream(pixelNumeratorCoefficientsStr_N);
+
+      for (int i=0; i < 20; i ++)
+      {
+         PNstream >> val;
+         pixelNumeratorCoefficients[i] = val;
+      }
+
+      // ------------------
+
+      if (!ossim::getPath(searchpixelDenominatorCoefficients, xdoc, pixelDenominatorCoefficientsStr))
+         ossimNotify(ossimNotifyLevel_WARN) << "ERROR: UNABLE TO FIND RS2 RPC COEFFICIENT INFORMATION" << endl;
+
+      string pixelDenominatorCoefficientsStr_N = pixelDenominatorCoefficientsStr[0];
+
+      // place into a stream
+      std::stringstream PDstream(pixelDenominatorCoefficientsStr_N);
+
+      for (int i=0; i < 20; i ++)
+      {
+         PDstream >> val;
+         pixelDenominatorCoefficients[i] = val;
+      }
+
+      // end character search term
+
+      model.biasError = biasError;
+      model.randomError = randomError;
+      model.lineFitQuality = lineFitQuality;
+      model.pixelFitQuality = pixelFitQuality;
+      model.lineOffset = lineOffset;
+      model.pixelOffset = pixelOffset;
+      model.latitudeOffset = latitudeOffset;
+      model.longitudeOffset = longitudeOffset;
+      model.heightOffset = heightOffset;
+      model.lineScale = lineScale;
+      model.pixelScale = pixelScale;
+      model.latitudeScale = latitudeScale;
+      model.longitudeScale = longitudeScale;
+      model.heightScale = heightScale;
+      model.lineNumeratorCoefficients = lineNumeratorCoefficients;
+      model.lineDenominatorCoefficients = lineDenominatorCoefficients;
+      model.pixelNumeratorCoefficients = pixelNumeratorCoefficients;
+      model.pixelDenominatorCoefficients = pixelDenominatorCoefficients;
+   }
+
+   return model;
+}
+
+bool ossimRadarSat2ProductDoc::getSatellite(const ossimXmlDocument* xdoc,
+                                            ossimString& s) const
+{
+   ossimString path = "/product/sourceAttributes/satellite";
+   // The saved File is an ossimKeywordlist
+
+   return ossim::getPath(path, xdoc, s);
+}
+
+bool ossimRadarSat2ProductDoc::getSensor(const ossimXmlDocument* xdoc,
+                                         ossimString& s) const
+{
+   ossimString path = "/product/sourceAttributes/sensor";
+   return ossim::getPath(path, xdoc, s);
+}
+
+bool ossimRadarSat2ProductDoc::getBeamModeMnemonic(
+   const ossimXmlDocument* xdoc, ossimString& s) const
+{
+   ossimString path = "/product/sourceAttributes/beamModeMnemonic";
+   return ossim::getPath(path, xdoc, s);
+}
+
+bool ossimRadarSat2ProductDoc::getImageId(const ossimXmlDocument* xdoc,
+                                          ossimString& s) const
+{
+   ossimString path = "/product/sourceAttributes/imageId";
+   return ossim::getPath(path, xdoc, s);
+}
+
+bool ossimRadarSat2ProductDoc::getImageFile(const ossimXmlDocument* xdoc,
+                                            ossimString& s) const
+{
+   bool result = false;
+   ossimString fileName;
+   
+   ossimString path = "/product/imageAttributes/fullResolutionImageData";
+   
+   if ( ossim::getPath(path, xdoc, fileName) )
+   {
+      result = true;
+      s = fileName;
+   }
+   
+   return result;
+}
+
+bool ossimRadarSat2ProductDoc::getAcquisitionType(
+   const ossimXmlDocument* xdoc, ossimString& s) const
+{
+   ossimString path =
+      "/product/sourceAttributes/radarParameters/acquisitionType";
+   return ossim::getPath(path, xdoc, s);
+}
+
+bool ossimRadarSat2ProductDoc::getRadarCenterFrequency(
+   const ossimXmlDocument* xdoc, ossimString& s) const
+{
+   ossimString path =
+      "/product/sourceAttributes/radarParameters/radarCenterFrequency";
+   return ossim::getPath(path, xdoc, s);
+}
+
+//---
+// drb ???
+//
+// Temporary until we decide how to get nominal prf from multiple nodes.
+// drb - 15 April 2009
+//---
+bool ossimRadarSat2ProductDoc::getNominalPrf(const ossimXmlDocument* xdoc,
+                                             double& prf) const
+{
+   bool result = false;
+   std::vector<ossimString> v;
+   if ( getPulseRepetitionFrequency(xdoc, v) )
+   {
+      if (v.size())
+      {
+         double d = 0;
+         std::vector<ossimString>::const_iterator i = v.begin();
+         while (i < v.end())
+         {
+            d += (*i).toDouble();
+            ++i;
+         }
+         prf = d / v.size();
+         result = true;
+      }
+   }
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimRadarSat2ProductDoc::getNominalPrf DEBUG:\nprf = "
+         << prf << "\nexit status = " << (result?"true":"false")
+         << std::endl;
+   }
+   return result;
+}
+
+bool ossimRadarSat2ProductDoc::getPulseRepetitionFrequency(
+   const ossimXmlDocument* xdoc, std::vector<ossimString>& v) const
+{
+   ossimString path =
+      "/product/sourceAttributes/radarParameters/pulseRepetitionFrequency";
+   return ossim::getPath(path, xdoc, v);
+}
+
+bool ossimRadarSat2ProductDoc::getAntennaPointing(
+   const ossimXmlDocument* xdoc, ossimString& s) const
+{
+   ossimString path =
+      "/product/sourceAttributes/radarParameters/antennaPointing";
+   return ossim::getPath(path, xdoc, s);
+}
+
+bool ossimRadarSat2ProductDoc::getAdcSamplingRate(
+   const ossimXmlDocument* xdoc, ossimString& s) const
+{
+   ossimString path =
+      "/product/sourceAttributes/radarParameters/adcSamplingRate";
+   return ossim::getPath(path, xdoc, s);
+}
+
+bool ossimRadarSat2ProductDoc::getPassDirection(
+   const ossimXmlDocument* xdoc, ossimString& s) const
+{
+   ossimString path =
+      "/product/sourceAttributes/orbitAndAttitude/orbitInformation/passDirection";
+   return ossim::getPath(path, xdoc, s);
+}
+
+bool ossimRadarSat2ProductDoc::getProductType(
+   const ossimXmlDocument* xdoc, ossimString& s) const
+{
+   ossimString path =
+      "/product/imageGenerationParameters/generalProcessingInformation/productType";
+   return ossim::getPath(path, xdoc, s);
+}
+
+bool ossimRadarSat2ProductDoc::getZeroDopplerTimeFirstLine(
+   const ossimXmlDocument* xdoc, ossimString& s) const
+{
+   ossimString path =
+      "/product/imageGenerationParameters/sarProcessingInformation/zeroDopplerTimeFirstLine";
+   return ossim::getPath(path, xdoc, s);
+}
+
+bool ossimRadarSat2ProductDoc::getNumberOfRangeLooks(
+   const ossimXmlDocument* xdoc, ossimString& s) const
+{
+   ossimString path =
+      "/product/imageGenerationParameters/sarProcessingInformation/numberOfRangeLooks";
+   return ossim::getPath(path, xdoc, s);
+}
+
+bool ossimRadarSat2ProductDoc::getNumberOfAzimuthLooks(
+   const ossimXmlDocument* xdoc, ossimString& s) const
+{
+   ossimString path =
+      "/product/imageGenerationParameters/sarProcessingInformation/numberOfAzimuthLooks";
+   return ossim::getPath(path, xdoc, s);
+}
+
+bool ossimRadarSat2ProductDoc::getSlantRangeNearEdge(
+   const ossimXmlDocument* xdoc, ossimString& s) const
+{
+   ossimString path =
+      "/product/imageGenerationParameters/sarProcessingInformation/slantRangeNearEdge";
+   return ossim::getPath(path, xdoc, s);
+}
+
+bool ossimRadarSat2ProductDoc::getZeroDopplerAzimuthTime(
+   const ossimXmlDocument* xdoc, std::vector<ossimString>& v) const
+{
+   ossimString path =
+      "/product/imageGenerationParameters/slantRangeToGroundRange/zeroDopplerAzimuthTime";
+   return ossim::getPath(path, xdoc, v);
+}
+
+bool ossimRadarSat2ProductDoc::getGroundRangeOrigin(
+   const ossimXmlDocument* xdoc, std::vector<ossimString>& v) const
+{
+   ossimString path =
+      "/product/imageGenerationParameters/slantRangeToGroundRange/groundRangeOrigin";
+   return ossim::getPath(path, xdoc, v);
+}
+
+bool ossimRadarSat2ProductDoc::getGroundToSlantRangeCoefficients(
+   const ossimXmlDocument* xdoc, std::vector<ossimString>& v) const
+{
+   ossimString path =
+      "/product/imageGenerationParameters/slantRangeToGroundRange/groundToSlantRangeCoefficients";
+   return ossim::getPath(path, xdoc, v);
+}
+
+bool ossimRadarSat2ProductDoc::getSemiMajorAxis(
+   const ossimXmlDocument* xdoc, ossimString& s) const
+{
+   ossimString path =
+      "/product/imageAttributes/geographicInformation/referenceEllipsoidParameters/semiMajorAxis";
+   return ossim::getPath(path, xdoc, s);
+}
+
+bool ossimRadarSat2ProductDoc::getSemiMinorAxis(
+   const ossimXmlDocument* xdoc, ossimString& s) const
+{
+   ossimString path =
+      "/product/imageAttributes/geographicInformation/referenceEllipsoidParameters/semiMinorAxis";
+   return ossim::getPath(path, xdoc, s);
+}
+
+bool ossimRadarSat2ProductDoc::getNumberOfSamplesPerLine(
+   const ossimXmlDocument* xdoc, ossimString& s) const
+{
+   ossimString path =
+      "/product/imageAttributes/rasterAttributes/numberOfSamplesPerLine";
+   return ossim::getPath(path, xdoc, s);
+}
+
+bool ossimRadarSat2ProductDoc::getNumberOfLines(
+   const ossimXmlDocument* xdoc, ossimString& s) const
+{
+   ossimString path =
+      "/product/imageAttributes/rasterAttributes/numberOfLines";
+   return ossim::getPath(path, xdoc, s);
+}
+
+bool ossimRadarSat2ProductDoc::getSampledPixelSpacing(
+   const ossimXmlDocument* xdoc, ossimString& s) const
+{
+   ossimString path =
+      "/product/imageAttributes/rasterAttributes/sampledPixelSpacing";
+   return ossim::getPath(path, xdoc, s);
+}
+
+bool ossimRadarSat2ProductDoc::getSampledLineSpacing(
+   const ossimXmlDocument* xdoc, ossimString& s) const
+{
+   ossimString path =
+      "/product/imageAttributes/rasterAttributes/sampledLineSpacing";
+   return ossim::getPath(path, xdoc, s);
+}
+
+bool ossimRadarSat2ProductDoc::getLineTimeOrdering(
+   const ossimXmlDocument* xdoc, ossimString& s) const
+{
+   ossimString path =
+      "/product/imageAttributes/rasterAttributes/lineTimeOrdering";
+   return ossim::getPath(path, xdoc, s);
+}
+
+bool ossimRadarSat2ProductDoc::getPixelTimeOrdering(
+   const ossimXmlDocument* xdoc, ossimString& s) const
+{
+   ossimString path =
+      "/product/imageAttributes/rasterAttributes/pixelTimeOrdering";
+   return ossim::getPath(path, xdoc, s);
+}
+
+bool ossimRadarSat2ProductDoc::getIncidenceAngleNearRange(
+   const ossimXmlDocument* xdoc, ossimString& s) const
+{
+   ossimString path =
+      "/product/imageGenerationParameters/sarProcessingInformation/incidenceAngleNearRange";
+   return ossim::getPath(path, xdoc, s);
+}
+
+bool ossimRadarSat2ProductDoc::getIncidenceAngleFarRange(
+   const ossimXmlDocument* xdoc, ossimString& s) const
+{
+   ossimString path =
+      "/product/imageGenerationParameters/sarProcessingInformation/incidenceAngleFarRange ";
+   return ossim::getPath(path, xdoc, s);
+}
+
+bool ossimRadarSat2ProductDoc::getSatelliteHeight(
+   const ossimXmlDocument* xdoc, ossimString& s) const
+{
+   ossimString path =
+      "/product/imageGenerationParameters/sarProcessingInformation/satelliteHeight";
+   return ossim::getPath(path, xdoc, s);
+}
+
+bool ossimRadarSat2ProductDoc::getGeodeticTerrainHeight(
+   const ossimXmlDocument* xdoc, ossimString& s) const
+{
+   ossimString path =
+      "/product/imageAttributes/geographicInformation/referenceEllipsoidParameters/geodeticTerrainHeight";
+   return ossim::getPath(path, xdoc, s);
+}
+
+} // matches: namespace ossimplugins
+
diff --git a/ossim_plugins/ossim/ossimRadarSat2ProductDoc.h b/ossim_plugins/ossim/ossimRadarSat2ProductDoc.h
new file mode 100644
index 0000000..9bb7ce4
--- /dev/null
+++ b/ossim_plugins/ossim/ossimRadarSat2ProductDoc.h
@@ -0,0 +1,232 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Description: Utility class to encapsulate parsing RadarSat2 product.xml
+// file.
+//
+//----------------------------------------------------------------------------
+// $Id$
+#ifndef ossimRadarSat2ProductDoc_HEADER
+#define ossimRadarSat2ProductDoc_HEADER 1
+
+#include <ossimPluginConstants.h>
+#include <ossim/base/ossimConstants.h>
+#include <ossim/base/ossimRefPtr.h>
+
+#include <list>
+#include <vector>
+#include <sstream>
+#include <vector>
+
+class ossimDpt;
+class ossimGpt;
+class ossimIpt;
+class ossimXmlDocument;
+class ossimXmlNode;
+class ossimString;
+
+
+using namespace std;
+
+typedef struct
+{
+   double biasError;
+   double randomError;
+   double lineFitQuality;
+   double pixelFitQuality;
+   double lineOffset;
+   double pixelOffset;
+   double latitudeOffset;
+   double longitudeOffset;
+   double heightOffset;
+   double lineScale;
+   double pixelScale;
+   double latitudeScale;
+   double longitudeScale;
+   double heightScale;
+   vector<double> lineNumeratorCoefficients;
+   vector<double> lineDenominatorCoefficients;
+   vector<double> pixelNumeratorCoefficients;
+   vector<double> pixelDenominatorCoefficients;
+   
+}RPCModel;
+
+namespace ossimplugins
+{
+class PlatformPosition;
+class RefPoint;
+class SensorParams;
+   
+/** @brief Class to encapsulate parsing RadarSat2 product.xml file. */
+class OSSIM_PLUGINS_DLL ossimRadarSat2ProductDoc
+{
+public:
+   /** @brief default constructor */
+   ossimRadarSat2ProductDoc();
+      
+   /** @brief destructor */
+   ~ossimRadarSat2ProductDoc();
+      
+   /**
+    * @brief Checks for node /product/sourceAttributes/satellite containing
+    * RADARSAT-2.
+    *
+    * @return true if present, false if not.
+    */
+   bool isRadarSat2(const ossimXmlDocument* xdoc) const;
+      
+   RPCModel getRpcData(const ossimXmlDocument* xdoc) const;
+      
+   /**
+    * @brief Method to initialize PlatformPosition object from
+    * RadarSat "product.xml" file.
+    * @param xdoc Opened product.xml file.
+    * @param pos Pointer to PlatformPosition object.
+    * @return true on success, false on error.
+    */
+   bool initPlatformPosition(const ossimXmlDocument* xdoc,
+                             PlatformPosition* pos) const;
+      
+   /**
+    * @brief Method to initialize SensorParams object from
+    * RadarSat "product.xml" file.
+    * @param xdoc Opened product.xml file.
+    * @param sp Pointer to SensorParams object.
+    * @return true on success, false on error.
+    */
+   bool initSensorParams(const ossimXmlDocument* xdoc,
+                         SensorParams* sp) const;
+      
+   /**
+    * @brief Method to initialize image size from
+    * RadarSat "product.xml" file.
+    * @param xdoc Opened product.xml file.
+    * @param imageSize The point to initialize.
+    * @return true on success, false on error.
+    */
+   bool initImageSize(const ossimXmlDocument* xdoc,
+                      ossimIpt& imageSize) const;
+      
+   /**
+    * @brief Method to initialize gsd from
+    * RadarSat "product.xml" file.
+    * @param xdoc Opened product.xml file.
+    * @param gsd The point to initialize.
+    * @return true on success, false on error.
+    */
+   bool initGsd(const ossimXmlDocument* xdoc,
+                ossimDpt& gsd) const;
+      
+   /**
+    * @brief Method to initialize image tie points from
+    * RadarSat "product.xml" file.
+    * @param xdoc Opened product.xml file.
+    * @param imageSize The point to initialize.
+    * @return true on success, false on error.
+    */
+   bool initTiePoints(const ossimXmlDocument* xdoc,
+                      std::list<ossimGpt>& gcp,
+                      std::list<ossimDpt>& icp) const;
+   bool getSatellite(const ossimXmlDocument* xdoc,
+                     ossimString& s) const;
+      
+   bool getSensor(const ossimXmlDocument* xdoc,
+                  ossimString& s) const;
+
+   /** /product/sourceAttributes/beamModeMnemonic */
+   bool getBeamModeMnemonic(const ossimXmlDocument* xdoc,
+                            ossimString& s) const;
+
+   bool getImageId(const ossimXmlDocument* xdoc,
+                   ossimString& s) const;
+
+   bool getImageFile(const ossimXmlDocument* xdoc, ossimString& s) const;
+
+   /** /product/sourceAttributes/radarParameters/acquisitionType */
+   bool getAcquisitionType(const ossimXmlDocument* xdoc,
+                           ossimString& s) const;
+
+   bool getRadarCenterFrequency(const ossimXmlDocument* xdoc,
+                                ossimString& s) const;
+
+   bool getNominalPrf(const ossimXmlDocument* xdoc, double& prf) const;
+
+   bool getPulseRepetitionFrequency(const ossimXmlDocument* xdoc,
+                                    std::vector<ossimString>& v) const;
+
+   bool getAntennaPointing(const ossimXmlDocument* xdoc,
+                           ossimString& s) const;
+
+   bool getAdcSamplingRate(const ossimXmlDocument* xdoc,
+                           ossimString& s) const;
+
+   bool getPassDirection(const ossimXmlDocument* xdoc,
+                         ossimString& s) const;
+
+   bool getProductType(const ossimXmlDocument* xdoc,
+                       ossimString& s) const;
+
+   bool getZeroDopplerTimeFirstLine(const ossimXmlDocument* xdoc,
+                                    ossimString& s) const;
+
+   bool getNumberOfRangeLooks(const ossimXmlDocument* xdoc,
+                              ossimString& s) const;
+
+   bool getNumberOfAzimuthLooks(const ossimXmlDocument* xdoc,
+                                ossimString& s) const;
+
+   bool getSlantRangeNearEdge(const ossimXmlDocument* xdoc,
+                              ossimString& s) const;
+
+   bool getZeroDopplerAzimuthTime(const ossimXmlDocument* xdoc,
+                                  std::vector<ossimString>& v) const;
+
+   bool getGroundRangeOrigin(const ossimXmlDocument* xdoc,
+                             std::vector<ossimString>& v) const;
+
+   bool getGroundToSlantRangeCoefficients(const ossimXmlDocument* xdoc,
+                                          std::vector<ossimString>& v) const;
+
+   bool getSemiMajorAxis(const ossimXmlDocument* xdoc,
+                         ossimString& s) const;
+
+   bool getSemiMinorAxis(const ossimXmlDocument* xdoc,
+                         ossimString& s) const;
+
+   bool getNumberOfSamplesPerLine(const ossimXmlDocument* xdoc,
+                                  ossimString& s) const;
+
+   bool getNumberOfLines(const ossimXmlDocument* xdoc,
+                         ossimString& s) const;
+
+   bool getSampledPixelSpacing(const ossimXmlDocument* xdoc,
+                               ossimString& s) const;
+
+   bool getSampledLineSpacing(const ossimXmlDocument* xdoc,
+                              ossimString& s) const;
+
+   bool getLineTimeOrdering(const ossimXmlDocument* xdoc,
+                            ossimString& s) const;
+
+   bool getPixelTimeOrdering(const ossimXmlDocument* xdoc,
+                             ossimString& s) const;
+
+   bool getGeodeticTerrainHeight(const ossimXmlDocument* xdoc,
+                                 ossimString& s) const;
+
+   bool getIncidenceAngleNearRange(const ossimXmlDocument* xdoc,
+                                 ossimString& s) const;
+
+   bool getIncidenceAngleFarRange(const ossimXmlDocument* xdoc,
+                                  ossimString& s) const;
+   
+   bool getSatelliteHeight(const ossimXmlDocument* xdoc,
+                           ossimString& s) const;
+};
+}
+
+#endif /* matches: #ifndef ossimRadarSat2ProductDoc_HEADER */
+
diff --git a/ossim_plugins/ossim/ossimRadarSat2RPCModel.cpp b/ossim_plugins/ossim/ossimRadarSat2RPCModel.cpp
new file mode 100644
index 0000000..40d2d90
--- /dev/null
+++ b/ossim_plugins/ossim/ossimRadarSat2RPCModel.cpp
@@ -0,0 +1,666 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include <cmath>
+
+#include <ossimRadarSat2RPCModel.h>
+#include <ossimPluginCommon.h>
+#include <ossimRadarSat2ProductDoc.h>
+#include <ossim/base/ossimCommon.h>
+#include <ossim/base/ossimFilename.h>
+#include <ossim/base/ossimKeywordNames.h>
+#include <ossim/base/ossimNotify.h>
+#include <ossim/base/ossimRefPtr.h>
+#include <ossim/base/ossimString.h>
+#include <ossim/base/ossimTrace.h>
+#include <ossim/base/ossimXmlDocument.h>
+#include <ossim/base/ossimXmlNode.h>
+
+#include <ossim/base/ossimException.h>
+#include <ossim/base/ossimKeywordlist.h>
+#include <ossim/base/ossimNotifyContext.h>
+
+#include <otb/GalileanEphemeris.h>
+#include <otb/GeographicEphemeris.h>
+#include <otb/GMSTDateTime.h>
+
+#include <otb/SensorParams.h>
+#include <otb/SarSensor.h>
+
+namespace ossimplugins
+{
+
+// Keyword constants:
+static const char LOAD_FROM_PRODUCT_FILE_KW[] = "load_from_product_file_flag";
+static const char PRODUCT_XML_FILE_KW[] = "product_xml_filename";
+
+// Static trace for debugging
+static ossimTrace traceDebug("ossimRadarSat2RPCModel:debug");
+
+
+RTTI_DEF1(ossimRadarSat2RPCModel, "ossimRadarSat2RPCModel", ossimRpcModel);
+
+ossimRadarSat2RPCModel::ossimRadarSat2RPCModel()
+   :
+   ossimRpcModel(),
+   theDecimation(1.0),
+   theProductXmlFile(ossimFilename::NIL)
+{
+}
+   
+ossimRadarSat2RPCModel::ossimRadarSat2RPCModel(const ossimRadarSat2RPCModel& rhs)
+   :
+   ossimRpcModel(rhs),
+   theDecimation(1.0),
+   theProductXmlFile(rhs.theProductXmlFile)
+{
+   
+}
+
+
+//*****************************************************************************
+//  CONSTRUCTOR: ossimRadarSat2RPCModel
+//  
+//  Constructs given filename for RS2 product.xml file
+//  
+//*****************************************************************************
+
+ossimRadarSat2RPCModel::ossimRadarSat2RPCModel(const ossimFilename& RS2File)
+   :ossimRpcModel(), theDecimation(1.0)
+{
+   
+   // Open the XML file, and read the RPC values in.
+   if (!open(RS2File))
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "DEBUG ossimRadarSat2RPCModel::ossimRadarSat2RPCModel(RS2File): Unable to parse file " << RS2File
+           << std::endl;
+   }
+
+}
+   
+ossimRadarSat2RPCModel::~ossimRadarSat2RPCModel()
+{
+}
+
+ossimString ossimRadarSat2RPCModel::getClassName() const
+{
+   return ossimString("ossimRadarSat2RPCModel");
+}
+   
+// ------ DUPLICATE RS2 MODEL OBJECT ----------
+   
+ossimObject* ossimRadarSat2RPCModel::dup() const
+{
+   return new ossimRadarSat2RPCModel(*this);
+}
+
+bool ossimRadarSat2RPCModel::open(const ossimFilename& file)
+{
+   static const char MODULE[] = "ossimRadarSat2RPCModel::open";
+   
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)<< MODULE << " entered...\n";
+   }
+   
+   bool result = false;
+   
+   // Get the xml file.
+   ossimFilename xmlFile;
+   
+   if (file.ext().downcase() == "xml")
+   {
+      xmlFile = file;
+   }
+   else if (file.isFile())
+   {
+      xmlFile = file.expand().path().dirCat("product.xml");
+   }
+   
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "product xml file: " << xmlFile << "\n";
+   }
+   
+   if ( xmlFile.exists() )
+   {
+      //---
+      // Instantiate the XML parser:
+      //---
+      ossimXmlDocument* xdoc = new ossimXmlDocument();
+      if ( xdoc->openFile(xmlFile) )
+      {
+         ossimRadarSat2ProductDoc rsDoc;
+         
+         result = rsDoc.isRadarSat2(xdoc);
+         
+         if (result)
+         {
+            if (traceDebug())
+            {
+               ossimNotify(ossimNotifyLevel_DEBUG)
+                  << "isRadarSat2...\n";
+               ossimString s;
+               if ( rsDoc.getBeamModeMnemonic(xdoc, s) )
+               {
+                  ossimNotify(ossimNotifyLevel_DEBUG)
+                     << "beam_mode_mnemonic: " << s << "\n";
+               }
+               if ( rsDoc.getAcquisitionType(xdoc, s) )
+               {
+                  ossimNotify(ossimNotifyLevel_DEBUG)
+                     << "acquisition_type: " << s << "\n";
+               }
+            }
+            
+            // Set the base class number of lines and samples
+            result = rsDoc.initImageSize(xdoc, theImageSize);
+            
+            
+            //---
+            // Fetch Image Size:
+            //---
+
+            theImageSize.line = theImageSize.x;
+            theImageSize.samp =theImageSize.y;
+
+
+            //***
+                 // Assign the bounding image space rectangle:
+                 //***
+
+                      if (result)
+                   {
+                      // Set the base class clip rect.
+                      theImageClipRect = ossimDrect(
+                         0, 0,
+                         theImageSize.x-1, theImageSize.y-1);
+                   }
+
+            // Set the sub image offset. tmp hard coded (drb).
+            theSubImageOffset.x = 0.0;
+            theSubImageOffset.y = 0.0;
+
+            // Set the image id.
+            if (result)
+            {
+               result = rsDoc.getImageId(xdoc, theImageID);
+            }
+
+            // Set the sensor ID.
+            if (result)
+            {
+               result = rsDoc.getSatellite(xdoc, theSensorID);
+            }
+
+            // Set the base class gsd:
+            result = rsDoc.initGsd(xdoc, theGSD);
+            if (result)
+            {
+               theMeanGSD = (theGSD.x + theGSD.y)/2.0;
+            }
+
+
+         }
+
+         thePolyType = B;
+
+
+         RPCModel model;
+         model = rsDoc.getRpcData(xdoc);
+
+
+         theBiasError  = model.biasError;
+         theRandError  = model.randomError;
+         theLineOffset = model.lineOffset;
+         theSampOffset = model.pixelOffset;
+         theLatOffset  = model.latitudeOffset;
+         theLonOffset  = model.longitudeOffset;
+         theHgtOffset  = model.heightOffset;
+         theLineScale  = model.lineScale;
+         theSampScale  = model.pixelScale;
+         theLatScale   = model.latitudeScale;
+         theLonScale   = model.longitudeScale;
+         theHgtScale   = model.heightScale;
+
+
+         if (traceDebug())
+         {
+            ossimNotify(ossimNotifyLevel_DEBUG)
+               << "All parameters RPC : "
+               << theBiasError << ", "
+               << theRandError << ", "
+               << theLineOffset << ", "
+               << theSampOffset << ", "
+               << theLatOffset << ", "
+               << theLonOffset << ", "
+               << theHgtOffset << ", "
+               << theLineScale << ", "
+               << theSampScale << ", "
+               << theLatScale << ", "
+               << theLonScale << ", "
+               << theHgtScale << ", " << std::endl;
+         }
+
+         // Parse coefficients:
+         ossim_uint32 i;
+
+         for (i=0; i<20; ++i)
+         {
+
+            theLineNumCoef[i] = model.lineNumeratorCoefficients[i];
+            theLineDenCoef[i] = model.lineDenominatorCoefficients[i];
+            theSampNumCoef[i] = model.pixelNumeratorCoefficients[i];
+            theSampDenCoef[i] = model.pixelDenominatorCoefficients[i];
+         }
+
+         // Assign other data members to default values:
+         theNominalPosError = sqrt(theBiasError*theBiasError +
+                                   theRandError*theRandError); // meters
+
+
+
+
+      } // matches: if ( xdoc->openFile(xmlFile) )
+
+      delete xdoc;
+      xdoc = 0;
+
+   } // matches: if ( xmlFile.exists() )
+
+   if (result)
+   {
+      theProductXmlFile = xmlFile;
+   }
+   else
+   {
+      theProductXmlFile = ossimFilename::NIL;
+   }
+
+   if (result)
+   {
+      theProductXmlFile = xmlFile;
+   }
+   else
+   {
+      theProductXmlFile = ossimFilename::NIL;
+   }
+
+   if (result)
+   {
+      // Assign the ossimSensorModel::theBoundGndPolygon
+      ossimGpt ul;
+      ossimGpt ur;
+      ossimGpt lr;
+      ossimGpt ll;
+      lineSampleToWorld(theImageClipRect.ul(), ul);
+      lineSampleToWorld(theImageClipRect.ur(), ur);
+      lineSampleToWorld(theImageClipRect.lr(), lr);
+      lineSampleToWorld(theImageClipRect.ll(), ll);
+      setGroundRect(ul, ur, lr, ll);  // ossimSensorModel method.
+   }
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " exit status = " << (result?"true":"false\n")
+         << std::endl;
+   }
+
+
+
+   //---
+   // Get the decimation if any from the header "IMAG" field.
+   //
+   // Look for string like:
+   // "/2" = 1/2
+   // "/4  = 1/4
+   // ...
+   // "/16 = 1/16
+   // If it is full resolution it should be "1.0"
+   //---
+
+   theDecimation = 1.0;
+
+
+
+   //***
+        // Assign other data members:
+        //***
+             thePolyType = B; 					// This may not be true for early RPC imagery
+   theRefImgPt.line = theImageSize.line/2.0;
+   theRefImgPt.samp = theImageSize.samp/2.0;
+   theRefGndPt.lat  = theLatOffset;
+   theRefGndPt.lon  = theLonOffset;
+   theRefGndPt.hgt  = theHgtOffset;
+
+
+   //---
+   // Assign the bounding ground polygon:
+   //
+   // NOTE:  We will use the base ossimRpcModel for transformation since all
+   // of our calls are in full image space (not decimated).
+   //---
+
+   ossimGpt v0, v1, v2, v3;
+   ossimDpt ip0 (0.0, 0.0);
+   ossimRpcModel::lineSampleHeightToWorld(ip0, theHgtOffset, v0);
+   ossimDpt ip1 (theImageSize.samp-1.0, 0.0);
+   ossimRpcModel::lineSampleHeightToWorld(ip1, theHgtOffset, v1);
+   ossimDpt ip2 (theImageSize.samp-1.0, theImageSize.line-1.0);
+   ossimRpcModel::lineSampleHeightToWorld(ip2, theHgtOffset, v2);
+   ossimDpt ip3 (0.0, theImageSize.line-1.0);
+   ossimRpcModel::lineSampleHeightToWorld(ip3, theHgtOffset, v3);
+
+   theBoundGndPolygon
+      = ossimPolygon (ossimDpt(v0), ossimDpt(v1), ossimDpt(v2), ossimDpt(v3));
+
+   updateModel();
+
+   // Set the ground reference point.
+   ossimRpcModel::lineSampleHeightToWorld(theRefImgPt,
+                                          theHgtOffset,
+                                          theRefGndPt);
+
+   if ( theRefGndPt.isLatNan() || theRefGndPt.isLonNan() )
+   {
+      if (traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG)
+            << "ossimNitfRpcModel::ossimNitfRpcModel DEBUG:"
+            << "\nGround Reference Point not valid."
+            << " Aborting with error..."
+            << std::endl;
+      }
+      setErrorStatus();
+      return false;
+   }
+
+
+   return true;
+}
+
+   
+void ossimRadarSat2RPCModel::worldToLineSample(const ossimGpt& world_point,
+                                               ossimDpt&       image_point) const
+{
+   // Get the full res (not decimated) point.
+   ossimRpcModel::worldToLineSample(world_point, image_point);
+   
+   // Apply decimation.
+   image_point.x = image_point.x * theDecimation;
+   image_point.y = image_point.y * theDecimation;
+}
+   
+void ossimRadarSat2RPCModel::lineSampleHeightToWorld(
+   const ossimDpt& image_point,
+   const double&   heightEllipsoid,
+   ossimGpt&       worldPoint) const
+{
+   
+   // Convert image point to full res (not decimated) point.
+   ossimDpt pt;
+   pt.x = image_point.x / theDecimation;
+   pt.y = image_point.y / theDecimation;
+   
+   // Call base...
+   ossimRpcModel::lineSampleHeightToWorld(pt, heightEllipsoid, worldPoint);
+}
+
+std::ostream& ossimRadarSat2RPCModel::print(std::ostream& out) const
+{
+   // Capture the original flags.
+   std::ios_base::fmtflags f = out.flags();
+   
+   ossimRpcModel::print(out);
+   
+   // Reset flags.
+   out.setf(f);
+   
+   return out;
+}
+   
+bool ossimRadarSat2RPCModel::InitSensorParams(const ossimKeywordlist &kwl,
+                                              const char *prefix)
+{
+   
+   // sensor frequencies
+   const char* central_freq_str = kwl.find(prefix,"central_freq");
+   double central_freq = 0.0;
+   if (central_freq_str)
+   {
+      central_freq = ossimString::toDouble(central_freq_str);
+   }
+   const char* fr_str = kwl.find(prefix,"fr");
+   double fr = 0.0;
+   if (fr_str)
+   {
+      fr = ossimString::toDouble(fr_str);
+   }
+   const char* fa_str = kwl.find(prefix,"fa");
+   double fa = 0.0;
+   if (fa_str)
+   {
+      fa = ossimString::toDouble(fa_str);
+   }
+   
+   //number of different looks
+   const char* n_azilok_str = kwl.find(prefix,"n_azilok");
+   double n_azilok = 0.0;
+   if (n_azilok_str)
+   {
+      n_azilok = ossimString::toDouble(n_azilok_str);
+   }
+   const char* n_rnglok_str = kwl.find(prefix,"n_rnglok");
+   double n_rnglok = 0.0;
+   if (n_rnglok_str)
+   {
+      n_rnglok = ossimString::toDouble(n_rnglok_str);
+   }
+   
+   //ellipsoid parameters
+   const char* ellip_maj_str = kwl.find(prefix,"ellip_maj");
+   double ellip_maj = 0.0;
+   if (ellip_maj_str)
+   {
+      ellip_maj = ossimString::toDouble(ellip_maj_str) * 1000.0;// km -> m
+   }
+   const char* ellip_min_str = kwl.find(prefix,"ellip_min");
+   double ellip_min = 0.0;
+   if (ellip_min_str)
+   {
+      ellip_min = ossimString::toDouble(ellip_min_str) * 1000.0;// km -> m
+   }
+   
+   if(_sensor != 0)
+   {
+      delete _sensor;
+   }
+   
+   _sensor = new SensorParams();
+   
+   const char* lineTimeOrdering_str = kwl.find(prefix,"lineTimeOrdering");
+   std::string lineTimeOrdering(lineTimeOrdering_str) ;
+   const char* pixelTimeOrdering_str = kwl.find(prefix,"pixelTimeOrdering");
+   std::string pixelTimeOrdering(pixelTimeOrdering_str) ;
+   if (pixelTimeOrdering == "Increasing") _sensor->set_col_direction(1);
+   else _sensor->set_col_direction(- 1);
+   if (lineTimeOrdering == "Increasing") _sensor->set_lin_direction(1);
+   else _sensor->set_lin_direction(- 1);
+   
+   const char* lookDirection_str = kwl.find(prefix,"lookDirection");
+   std::string lookDirection(lookDirection_str) ;
+   if ((lookDirection == "Right")||(lookDirection == "RIGHT")) _sensor->set_sightDirection(SensorParams::Right) ;
+   else _sensor->set_sightDirection(SensorParams::Left) ;
+   
+   _sensor->set_sf(fr);
+   const double CLUM        = 2.99792458e+8 ;
+   double wave_length = CLUM / central_freq ;
+   _sensor->set_rwl(wave_length);
+   _sensor->set_nAzimuthLook(n_azilok);
+   _sensor->set_nRangeLook(n_rnglok);
+   
+   // fa is the processing PRF
+   _sensor->set_prf(fa * n_azilok);
+   
+   _sensor->set_semiMajorAxis(ellip_maj) ;
+   _sensor->set_semiMinorAxis(ellip_min) ;
+   
+   return true;
+}
+   
+bool ossimRadarSat2RPCModel::initSensorParams(
+   const ossimXmlDocument* xdoc, const ossimRadarSat2ProductDoc& rsDoc)
+{
+   static const char MODULE[] = "ossimRadarSat2RPCModel::initSensorParams";
+   
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)<< MODULE << " entered...\n";
+   }
+   
+   if (_sensor )
+   {
+      delete _sensor;
+   }
+   _sensor =  new SensorParams();
+   
+   bool result = rsDoc.initSensorParams(xdoc, _sensor);
+   
+   if (!result)
+   {
+      delete _sensor;
+      _sensor = 0;
+   }
+   
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " exit status = " << (result?"true":"false\n")
+         << std::endl;
+   }
+   
+   return result;
+}
+
+bool ossimRadarSat2RPCModel::saveState(ossimKeywordlist& kwl,
+                                       const char* prefix) const
+{
+   static const char MODULE[] = "ossimRadarSat2RPCModel::saveState";
+   
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)<< MODULE << " entered...\n";
+   }
+   
+   bool result = true;
+   
+   kwl.add(prefix, "decimation", theDecimation);
+   
+   // Save our state:
+   kwl.add(prefix, PRODUCT_XML_FILE_KW, theProductXmlFile.c_str());
+   
+   if (result)
+   {
+      // Call base save state:
+      result = ossimRpcModel::saveState(kwl, prefix);
+   }
+   
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " exit status = " << (result?"true":"false\n")
+         << std::endl;
+   }
+   
+   return result;
+}
+
+
+bool ossimRadarSat2RPCModel::loadState (const ossimKeywordlist &kwl,
+                                        const char *prefix)
+{
+   static const char MODULE[] = "ossimRadarSat2RPCModel::loadState";
+   
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " entered...\n";
+   }
+   
+   const char* lookup = 0;
+   ossimString s;
+   
+   // Check the type first.
+   lookup = kwl.find(prefix, ossimKeywordNames::TYPE_KW);
+   if (lookup)
+   {
+      s = lookup;
+      if (s != getClassName())
+      {
+         return false;
+      }
+   }
+   
+   // Get the product.xml file name.
+   lookup = kwl.find(prefix, PRODUCT_XML_FILE_KW);
+   if (lookup)
+   {
+      theProductXmlFile = lookup;
+      
+      // See if caller wants to load from xml vice keyword list.
+      lookup = kwl.find(prefix, LOAD_FROM_PRODUCT_FILE_KW);
+      if (lookup)
+      {
+         s = lookup;
+         if ( s.toBool() )
+         {
+            // Loading from product.xml file.
+            return open(theProductXmlFile);
+         }
+      }
+   }
+   
+   
+   // Call base.
+   bool result = ossimRpcModel::loadState(kwl, prefix);
+
+   // Lookup decimation.
+   const char* value = kwl.find(prefix, "decimation");
+   if (value)
+   {
+      theDecimation = ossimString(value).toFloat64();
+      if (theDecimation <= 0.0)
+      {
+         // Do not allow negative or "0.0"(divide by zero).
+         theDecimation = 1.0;
+      }
+   }
+   
+   
+   //---
+   // Temp:  This must be cleared or you end up with a bounding rect of all
+   // zero's.
+   //---
+   theBoundGndPolygon.clear();
+   
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " exit status = " << (result?"true":"false\n")
+         << std::endl;
+   }
+   
+   return result;
+}
+}
+
diff --git a/ossim_plugins/ossim/ossimRadarSat2RPCModel.h b/ossim_plugins/ossim/ossimRadarSat2RPCModel.h
new file mode 100644
index 0000000..03047d3
--- /dev/null
+++ b/ossim_plugins/ossim/ossimRadarSat2RPCModel.h
@@ -0,0 +1,153 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef ossimRadarSat2RPCModel_H
+#define ossimRadarSat2RPCModel_H 1
+
+#include <ossim/base/ossimConstants.h>
+#include <ossim/projection/ossimRpcModel.h>
+#include <ossim/projection/ossimMapProjection.h>
+#include <ossim/base/ossimIpt.h>
+#include <ossim/base/ossimFilename.h>
+#include <ossim/base/ossimGpt.h>
+#include <ossim/base/ossimDpt.h>
+#include <iostream>
+#include <list>
+#include <otb/PlatformPosition.h>
+#include <otb/SensorParams.h>
+#include <otb/RefPoint.h>
+#include <otb/SarSensor.h>
+
+#include <otb/CivilDateTime.h>
+
+class ossimFilename;
+class ossimString;
+class ossimXmlDocument;
+
+namespace ossimplugins
+{
+
+class ossimRadarSat2ProductDoc;
+class SensorParams;
+
+/**
+ * @brief This class allows for direct localisation and indirect localisation
+ * using the RadarSat2 sensor model
+ */
+class OSSIM_PLUGINS_DLL ossimRadarSat2RPCModel : public ossimRpcModel
+{
+public:
+   /** @brief default constructor */
+   ossimRadarSat2RPCModel();
+
+   /** @brief copy constructor */
+   ossimRadarSat2RPCModel(const ossimRadarSat2RPCModel& rhs);
+
+    ossimRadarSat2RPCModel(const ossimFilename& RS2File);
+
+
+   /** @brief Destructor */
+   virtual ~ossimRadarSat2RPCModel();
+
+   /**
+    * @brief Method to return the class name.
+    * @return The name of this class.
+    */
+   virtual ossimString getClassName()   const;
+
+   /**
+    * @brief Returns pointer to a new instance, copy of this.
+    */
+   virtual ossimObject* dup() const;
+
+
+	   /**
+    * @brief Method to parse an nitf file and initialize model.
+    * @param entryIndex The entry to get model for.  Note the nitf's can have
+    * multiple entries; each with a different projection.
+    * @return true on success, false on error.
+    */
+    bool open(const ossimFilename& file);
+
+
+   /**
+    * @brief Method to save object state to a keyword list.
+    * @param kwl Keyword list to save to.
+    * @param prefix added to keys when saved.
+    * @return true on success, false on error.
+    */
+   virtual bool saveState(ossimKeywordlist& kwl,
+                          const char* prefix=0) const;
+
+   /**
+    * @brief Method to the load (recreate) the state of the object from a
+    * keyword list. Return true if ok or false on error.
+    * @return true if load OK, false on error
+    */
+   virtual bool loadState (const ossimKeywordlist &kwl, const char *prefix=0);
+
+   /*!
+    * METHOD: print()
+    * Fulfills base-class pure virtual. Dumps contents of object to ostream.
+    */
+   virtual std::ostream& print(std::ostream& out) const;
+
+
+   /**
+    * @brief worldToLineSample()
+    * Calls ossimRpcModel::worldToLineSample(), then applies (if needed)
+    * decimation.
+    * This is a temp work around for decimation RPC NITFs.
+    */
+   virtual void  worldToLineSample(const ossimGpt& world_point,
+                                   ossimDpt&       image_point) const;
+
+   /**
+    * @brief lineSampleHeightToWorld()
+    * Backs out decimation of image_point (if needed) then calls:
+    * ossimRpcModel::lineSampleHeightToWorld
+    * This is a temp work around for decimation RPC NITFs.
+    */
+   virtual void lineSampleHeightToWorld(const ossimDpt& image_point,
+                                        const double&   heightEllipsoid,
+                                        ossimGpt&       worldPoint) const;
+
+
+private:
+
+
+   bool InitSensorParams(const ossimKeywordlist &kwl,
+                                 const char *prefix);
+
+
+   bool initSensorParams(const ossimXmlDocument* xdoc,
+                         const ossimRadarSat2ProductDoc& rsDoc);
+
+
+   /**
+    * Stored from header field "IMAG".  This is a temp work around to handle
+    * decimated rpc nitf's.
+    */
+   ossim_float64 theDecimation;
+
+   SensorParams * _sensor;
+
+
+
+   ossimFilename theProductXmlFile;
+
+TYPE_DATA
+
+};
+}
+
+#endif
+
diff --git a/ossim_plugins/ossim/ossimRadarSat2TiffReader.cpp b/ossim_plugins/ossim/ossimRadarSat2TiffReader.cpp
new file mode 100644
index 0000000..1db14de
--- /dev/null
+++ b/ossim_plugins/ossim/ossimRadarSat2TiffReader.cpp
@@ -0,0 +1,316 @@
+//----------------------------------------------------------------------------
+//
+// License:  See top level LICENSE.txt file
+//
+// Author:  John Stastny
+//
+// Description: Image handelr for RadarSAT-2 data that is TIFF based.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include <cstdlib>
+
+#include <ossimRadarSat2TiffReader.h>
+#include <ossimRadarSat2ProductDoc.h>
+#include <ossimRadarSat2Model.h>
+#include <ossim/base/ossimConstants.h>
+#include <ossim/base/ossimFilename.h>
+#include <ossim/base/ossimKeywordlist.h>
+#include <ossim/base/ossimKeywordNames.h>
+#include <ossim/base/ossimTrace.h>
+#include <ossim/base/ossimNotify.h>
+#include <ossim/base/ossimXmlDocument.h>
+#include <ossim/imaging/ossimImageGeometryRegistry.h>
+#include <ossim/projection/ossimProjection.h>
+#include <ossim/projection/ossimProjectionFactoryRegistry.h>
+
+// Keyword constants:
+static const char PRODUCT_XML_FILE_KW[] = "product_xml_filename";
+
+namespace ossimplugins
+{
+RTTI_DEF1(ossimRadarSat2TiffReader,
+          "ossimRadarSat2TiffReader",
+          ossimTiffTileSource)
+}
+
+#ifdef OSSIM_ID_ENABLED
+   static const char OSSIM_ID[] = "$Id$";
+#endif
+   
+static ossimTrace traceDebug("ossimRadarSat2TiffReader:degug");  
+
+ossimplugins::ossimRadarSat2TiffReader::ossimRadarSat2TiffReader()
+   :
+   ossimTiffTileSource()
+{
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimplugins::ossimRadarSat2TiffReader::ossimRadarSat2TiffReader entered...\n";
+#ifdef OSSIM_ID_ENABLED
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "OSSIM_ID:  " << OSSIM_ID << std::endl;
+#endif
+   }
+}
+
+ossimplugins::ossimRadarSat2TiffReader::~ossimRadarSat2TiffReader()
+{
+}
+
+bool ossimplugins::ossimRadarSat2TiffReader::saveState(
+   ossimKeywordlist& kwl, const char* prefix) const
+{
+   static const char MODULE[] = "ossimplugins::ossimRadarSat2TiffReader::saveState";
+   
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " entered...\n";
+   }
+
+   // Save our state:
+   kwl.add(prefix, PRODUCT_XML_FILE_KW, theProductXmlFile.c_str());
+
+   // Save the base:
+   return ossimTiffTileSource::saveState(kwl, prefix);
+}
+
+bool ossimplugins::ossimRadarSat2TiffReader::loadState(
+   const ossimKeywordlist& kwl, const char* prefix)
+{
+   static const char MODULE[] = "ossimplugins::ossimRadarSat2TiffReader::loadState";
+   
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " entered...\n";
+   }
+
+   bool result = false;
+
+   // Get the product.xml file name.
+   const char* lookup = kwl.find(prefix, PRODUCT_XML_FILE_KW);
+   if (lookup)
+   {
+      theProductXmlFile = lookup;
+      if ( isRadarSat2ProductFile(theProductXmlFile) )
+      {
+         //---
+         // Although we can open any tiff here we only do if we have matching
+         // RS2 product.xml.
+         //---
+         result = ossimTiffTileSource::loadState(kwl, prefix);
+      }
+   }
+
+   if (!result)
+   {
+      theProductXmlFile.clear();
+   }
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " exit status = " << (result?"true":"false\n")
+         << std::endl;
+   }
+
+   return result;
+}
+
+ossimString ossimplugins::ossimRadarSat2TiffReader::getShortName()const
+{
+   return ossimString("ossim_radarsat2_tiff_reader");
+}
+   
+ossimString ossimplugins::ossimRadarSat2TiffReader::getLongName()const
+{
+   return ossimString("ossim RadarSAT-2 tiff reader");
+}
+
+bool ossimplugins::ossimRadarSat2TiffReader::open(const ossimFilename& file)
+{
+   static const char MODULE[] = "ossimplugins::ossimRadarSat2TiffReader::open";
+   
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " entered...\n"
+         << "file: " << file << "\n";
+   }
+
+   bool result = false;
+   
+   if ( isOpen() )
+   {
+      close();
+   }
+
+   // Check extension to see if it's xml.
+   if ( file.ext().downcase() == "xml" )
+   {
+      ossimXmlDocument* xdoc = new ossimXmlDocument();
+      if ( xdoc->openFile(file) )
+      {
+         // See if it's a TerraSAR-X product xml file.
+         if ( isRadarSat2ProductFile(xdoc) )
+         {
+            ossimString s;
+            ossimRadarSat2ProductDoc helper;
+            
+            if ( helper.getImageFile(xdoc, s) )
+            {
+               ossimFilename imageFile = file.expand().path();
+               imageFile = imageFile.dirCat(s);
+
+               setFilename(imageFile);
+
+               result = ossimTiffTileSource::open();
+               if (result)
+               {
+                  theProductXmlFile = file;
+                  completeOpen();
+               }
+            }
+         }
+      }
+      delete xdoc;
+      xdoc = 0;
+      
+   } // matches: if ( file.ext().downcase() == "xml" )
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " exit status = " << (result?"true":"false\n")
+         << std::endl;
+   }
+
+   return result;
+}
+
+void ossimplugins::ossimRadarSat2TiffReader::close()
+{
+   theProductXmlFile.clear();
+   ossimTiffTileSource::close();
+}
+
+ossimRefPtr<ossimImageGeometry> ossimplugins::ossimRadarSat2TiffReader::getImageGeometry()
+{
+   if ( !theGeometry )
+   {
+      //---
+      // Check for external geom:
+      //---
+      theGeometry = getExternalImageGeometry();
+      
+      if ( !theGeometry )
+      {
+         // Check the internal geometry first to avoid a factory call.
+         theGeometry = getInternalImageGeometry();
+
+         // At this point it is assured theGeometry is set.
+         
+         //---
+         // WARNING:
+         // Must create/set theGeometry at this point or the next call to
+         // ossimImageGeometryRegistry::extendGeometry will put us in an infinite loop
+         // as it does a recursive call back to ossimImageHandler::getImageGeometry().
+         //---         
+
+         // Check for set projection.
+         if ( !theGeometry->getProjection() )
+         {
+            // Try factories for projection.
+            ossimImageGeometryRegistry::instance()->extendGeometry(this);
+         }
+      }
+
+      // Set image things the geometry object should know about.
+      initImageParameters( theGeometry.get() );
+   }
+
+   return theGeometry;
+}
+
+ossimRefPtr<ossimImageGeometry>
+ossimplugins::ossimRadarSat2TiffReader::getInternalImageGeometry() const
+{
+   static const char MODULE[] = "ossimplugins::ossimRadarSat2TiffReader::getInternalImageGeometry";
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " entered...\n";
+   }
+
+   ossimRefPtr<ossimImageGeometry> geom = new ossimImageGeometry();
+   
+   ossimXmlDocument* xdoc = new ossimXmlDocument();
+   if ( xdoc->openFile(theProductXmlFile) )
+   {
+      ossimRefPtr<ossimRadarSat2Model> model = new ossimRadarSat2Model();
+            
+      if ( model->open(theProductXmlFile) )
+      {     
+         // Assign the model to our ossimImageGeometry object.        
+         geom->setProjection( model.get() );      
+      } 
+      else    
+      {       
+         if (traceDebug())    
+         {
+            ossimNotify(ossimNotifyLevel_DEBUG) << "WARNING: Unhandled projection: " << std::endl;
+         }
+      }
+   } // matches: if ( xdoc->openFile(theProductXmlFile) )
+   
+   delete xdoc;
+   xdoc = 0;
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " exited..." << std::endl;
+   }
+   
+   return geom;
+}
+
+bool ossimplugins::ossimRadarSat2TiffReader::isRadarSat2ProductFile(
+   const ossimFilename& file) const
+{
+   bool result = false;
+   
+   // Check extension to see if it's xml.
+   if ( file.ext().downcase() == "xml" )
+   {
+      ossimXmlDocument* xdoc = new ossimXmlDocument();
+
+      if ( xdoc->openFile(file) )
+      {
+         result = isRadarSat2ProductFile(xdoc);
+      }
+
+      delete xdoc;
+      xdoc = 0;
+   }
+   
+   return result;
+}
+
+bool ossimplugins::ossimRadarSat2TiffReader::isRadarSat2ProductFile(
+   const ossimXmlDocument* xdoc) const
+{
+   bool result = false;
+
+   if (xdoc)
+   {
+      ossimRadarSat2ProductDoc helper;
+      
+      // See if it's a TerraSAR-X product xml file.
+      result = helper.isRadarSat2(xdoc);
+   }
+   
+   return result;
+}
diff --git a/ossim_plugins/ossim/ossimRadarSat2TiffReader.h b/ossim_plugins/ossim/ossimRadarSat2TiffReader.h
new file mode 100644
index 0000000..e6667cf
--- /dev/null
+++ b/ossim_plugins/ossim/ossimRadarSat2TiffReader.h
@@ -0,0 +1,107 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author:  John Stastny
+//
+// Description: Image handelr for RadarSAT-2 data that is TIFF based.
+//
+//----------------------------------------------------------------------------
+// $Id$
+#ifndef ossimRadarSat2TiffReader_HEADER
+#define ossimRadarSat2TiffReader_HEADER 1
+
+#include <ossim/imaging/ossimTiffTileSource.h>
+#include <ossim/base/ossimFilename.h>
+
+// Forward class declarations outside of namespace ossimplugins.
+class ossimXmlDocument;
+
+namespace ossimplugins
+{
+   class ossimRadarSat2TiffReader : public ossimTiffTileSource
+   {
+   public:
+      
+      /** default constructor */
+      ossimRadarSat2TiffReader();
+      
+      /** virtual destructor */
+      virtual ~ossimRadarSat2TiffReader();
+      
+      /** @return "ossim_radarsat2_tiff_reader" */
+      virtual ossimString getShortName() const;
+      
+      /** @return "ossim RadarSAT-2 tiff reader" */
+      virtual ossimString getLongName()  const;
+      
+      /**
+       *  This open take the product xml file.
+       *  
+       *  @param file File to open.
+       *
+       *  @return true on success, false on error.
+       */
+      virtual bool open(const ossimFilename& file);
+      
+      /**
+       * Method to save the state of an object to a keyword list.
+       * Return true if ok or false on error.
+       */
+      virtual bool saveState(ossimKeywordlist& kwl,
+                             const char* prefix=0)const;
+      
+      /**
+       * Method to the load (recreate) the state of an object from a keyword
+       * list.  Return true if ok or false on error.
+       */
+      virtual bool loadState(const ossimKeywordlist& kwl,
+                             const char* prefix=0);
+      
+      /** Close method. */
+      virtual void close();
+      
+      /**
+       * Returns the image geometry object associated with this tile source or
+       * NULL if non defined.  The geometry contains full-to-local image
+       * transform as well as projection (image-to-world).
+       */
+      virtual ossimRefPtr<ossimImageGeometry> getImageGeometry();
+
+      /**
+       * @param Method to get geometry from the xml file or internal geotiff
+       * tags.
+       */
+      virtual ossimRefPtr<ossimImageGeometry> getInternalImageGeometry() const;
+      
+   private:
+      
+      /**
+       * @brief Method to check file to see if it's a RS2 product
+       * xml file.
+       * @param file The file to check.
+       * @return true on success, false on error.
+       */
+      bool isRadarSat2ProductFile(const ossimFilename& file) const;
+      
+      /**
+       * @brief Method to check file to see if it's a RS2 product
+       * xml file.
+       * @param xdoc XML document opened up to product.xml file.
+       * @return true on success, false on error.
+       */
+      bool isRadarSat2ProductFile(const ossimXmlDocument* xdoc) const;
+      
+      
+      ossimFilename theProductXmlFile;
+
+      TYPE_DATA
+   };
+
+} // End: namespace ossimplugins
+
+#endif /* #ifndef ossimRadarSat2TiffReader_HEADER */
+
+
diff --git a/ossim_plugins/ossim/ossimRadarSatModel.cpp b/ossim_plugins/ossim/ossimRadarSatModel.cpp
new file mode 100644
index 0000000..7623ecc
--- /dev/null
+++ b/ossim_plugins/ossim/ossimRadarSatModel.cpp
@@ -0,0 +1,1232 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include <cmath>
+#include <cstdio>
+
+#include <ossim/base/ossimTrace.h>
+#include <ossim/base/ossimKeywordNames.h>
+
+#include <ossimRadarSatModel.h>
+#include <otb/GalileanEphemeris.h>
+#include <otb/GeographicEphemeris.h>
+
+#include <otb/JSDDateTime.h>
+#include <otb/GMSTDateTime.h>
+#include <otb/CivilDateTime.h>
+
+#include <otb/PlatformPosition.h>
+#include <otb/SensorParams.h>
+#include <otb/RefPoint.h>
+#include <otb/SarSensor.h>
+
+#include <RadarSat/Data/DataFactory.h>
+#include <RadarSat/Data/ImageOptionsFileDescriptor.h>
+
+#include <RadarSat/VolumeDir/VolumeDescriptorRecord.h>
+#include <RadarSat/VolumeDir/VolumeDirFactory.h>
+
+#include <RadarSat/Data/ProcessedDataRecord.h>
+#include <RadarSat/CommonRecord/ProcessingParameters.h>
+#include <RadarSat/Leader/PlatformPositionData.h>
+
+namespace ossimplugins
+{
+RTTI_DEF1(ossimRadarSatModel, "ossimRadarSatModel", ossimGeometricSarSensorModel);
+
+// Static trace for debugging
+static ossimTrace traceDebug("ossimRadarSatModel:debug");
+
+ossimRadarSatModel::ossimRadarSatModel():
+  ossimGeometricSarSensorModel(),
+  _n_srgr(0),
+  _pixel_spacing(0),
+  _data(NULL),
+  _leader(NULL),
+  _trailer(NULL),
+  _volumeDir(NULL)
+{
+}
+
+ossimRadarSatModel::ossimRadarSatModel(const ossimRadarSatModel& rhs):
+  ossimGeometricSarSensorModel(rhs),
+  _n_srgr(rhs._n_srgr),
+  _pixel_spacing(rhs._pixel_spacing),
+  _data(new Data(*(rhs._data))),
+  _leader(new Leader(*(rhs._leader))),
+  _trailer(new Trailer(*(rhs._trailer))),
+  _volumeDir(new VolumeDir(*(rhs._volumeDir)))
+{
+}
+
+ossimRadarSatModel::~ossimRadarSatModel()
+{
+  if (_data != 0)
+  {
+    delete _data;
+  }
+
+  if (_leader != 0)
+  {
+    delete _leader;
+  }
+  
+  if (_trailer != 0)
+  {
+    delete _trailer;
+  }
+
+  if (_volumeDir != 0)
+  {
+    delete _volumeDir;
+  }
+}
+
+ossimObject* ossimRadarSatModel::dup() const
+{
+   return new ossimRadarSatModel(*this);
+}
+
+ossimString ossimRadarSatModel::getClassName() const
+{
+   return ossimString("ossimRadarSatModel");
+}
+
+double ossimRadarSatModel::getSlantRangeFromGeoreferenced(double col) const
+{
+  if (_n_srgr==0) return(-1) ;
+
+  double relativeGroundRange ;
+
+  // in the case of Georeferenced images, _refPoint->get_distance() contains the ground range
+  relativeGroundRange = _refPoint->get_distance() + _sensor->get_col_direction() * (col-_refPoint->get_pix_col())* _pixel_spacing ;
+
+  int numSet = FindSRGRSetNumber((_refPoint->get_ephemeris())->get_date()) ;
+  /**
+   * @todo : could be improved (date choice)
+   */
+
+  double slantRange = _srgr_coefset[numSet][0]
+              + _srgr_coefset[numSet][1]*relativeGroundRange
+              + _srgr_coefset[numSet][2]*pow(relativeGroundRange,2)
+              + _srgr_coefset[numSet][3]*pow(relativeGroundRange,3)
+              + _srgr_coefset[numSet][4]*pow(relativeGroundRange,4)
+              + _srgr_coefset[numSet][5]*pow(relativeGroundRange,5);
+
+  return  slantRange ;
+}
+
+bool ossimRadarSatModel::open(const ossimFilename& file)
+{
+  //traceDebug.setTraceFlag(true);
+  if(traceDebug())
+    {
+    ossimNotify(ossimNotifyLevel_DEBUG)
+      << "ossimRadarSatTileSource::open(filename) DEBUG: entered..."
+      << std::endl
+      << "Attempting to open file " << file << std::endl;
+    }
+
+  bool retValue = true;
+  ossimFilename tempFilename = file;
+
+  /*
+   * Detect if we use vdf file or dat file
+   */
+  ossimFilename dataFilePath;
+  ossimFilename volumeDirectoryFilePath;
+  std::string input_file = file;
+  string::size_type loc_DAT = input_file.find( "DAT_01", 0 );
+  string::size_type loc_dat = input_file.find( "dat_01", 0 );
+  if ( (loc_DAT != string::npos ) || ( loc_dat != string::npos ) )
+    {
+    dataFilePath = input_file.c_str();
+    if (loc_DAT != string::npos ) input_file.replace(loc_DAT, 6, "VDF_DAT");
+    if (loc_dat != string::npos ) input_file.replace(loc_dat, 6, "vdf_dat");
+    volumeDirectoryFilePath = input_file.c_str();
+    }
+  else
+    {
+    string::size_type loc_VDF = input_file.find( "VDF_DAT", 0 );
+    string::size_type loc_vdf = input_file.find( "vdf_dat", 0 );
+    if ( (loc_VDF != string::npos ) || ( loc_vdf != string::npos ) )
+      {
+      volumeDirectoryFilePath = input_file.c_str();
+      if (loc_VDF != string::npos ) input_file.replace(loc_VDF, 7, "DAT_01");
+      if (loc_vdf != string::npos ) input_file.replace(loc_vdf, 7, "dat_01");
+      dataFilePath = input_file.c_str();
+      }
+    else
+      {
+      if(traceDebug())
+        {
+        ossimNotify(ossimNotifyLevel_DEBUG)
+             << "File Name not coherent (searching for *DAT_01* or *dat_01* or *vdf_dat* or *VDF_DAT* )  : " << file << std::endl;
+        }
+      return false;
+      }
+    }
+
+   //Creation of the class allowing to store the metadata from the Volume Directory File
+  if (_volumeDir != NULL)
+    {
+    delete _volumeDir;
+    _volumeDir = NULL;
+    }
+  _volumeDir = new VolumeDir();
+
+  //Creation of the class allowing to store the metadata from the Data file
+  if (_data != NULL)
+    {
+    delete _data;
+    _data = NULL;
+    }
+  _data = new Data();
+
+  //Creation of the class allowing to store the metadata from the Leader file
+  if(_leader != NULL)
+    {
+    delete _leader;
+    _leader = NULL;
+    }
+  _leader = new Leader();
+
+  // Creation of the class allowing to store the metadata from the Trailer file
+  if(_trailer != NULL)
+    {
+    delete _trailer;
+    _trailer = NULL;
+    }
+  _trailer = new Trailer();
+
+
+  RadarSatRecordHeader headerVDF;
+  VolumeDirFactory factoryVDF;
+  ifstream volumeDirFile (volumeDirectoryFilePath.c_str(), ios::in|ios::binary);
+  volumeDirFile>>headerVDF;
+  if(volumeDirFile.eof())
+    {
+    volumeDirFile.close();
+    retValue =  false;
+    }
+  else
+    {
+    if(traceDebug())
+      {
+      ossimNotify(ossimNotifyLevel_DEBUG) << "Begin reading VDF file" << std::endl;
+      }
+
+    RadarSatRecord* recordVDF = factoryVDF.Instanciate(headerVDF.get_rec_seq());
+    if (recordVDF != NULL && headerVDF.get_rec_seq() == 1)
+      {
+      recordVDF->Read(volumeDirFile);
+
+      //Test if the input File is a valid Radarsat VDF file
+      if ((((VolumeDescriptorRecord*) recordVDF)->get_logvol_id()).substr(0, 10) == "RSAT-1-SAR")
+        {
+        std::string subProduct = (((VolumeDescriptorRecord*) recordVDF)->get_logvol_id()).substr(11, 3);
+        if  ( (subProduct == "RAW") || (subProduct == "SPG") || (subProduct == "SSG") )
+          {
+          if(traceDebug())
+            ossimNotify(ossimNotifyLevel_DEBUG) << "RAW, SPG and SSG format are not supported" <<std::endl;
+
+          volumeDirFile.close();
+          return false;
+          }
+        else if ( (subProduct == "SCN") || (subProduct == "SGX") || (subProduct == "SLC") )
+          {
+          if(traceDebug())
+            ossimNotify(ossimNotifyLevel_DEBUG) << "SCN, SGX and SLC format are supported but not tested" <<std::endl;
+          }
+        else if ( (subProduct ==  "SCW") || (subProduct == "SGF") )
+          {
+          if(traceDebug())
+            ossimNotify(ossimNotifyLevel_DEBUG) << "SCW and SGF format are supported and tested" <<std::endl;
+          }
+
+        //Reading of the remaining of the volume directory file
+
+        volumeDirFile.close();
+        volumeDirFile.open(volumeDirectoryFilePath.c_str(), ios::in | ios::binary);
+        volumeDirFile >> *_volumeDir;
+        volumeDirFile.close();
+
+        if (traceDebug())
+          {
+          ossimNotify(ossimNotifyLevel_DEBUG) << "End reading VDF file" << std::endl;
+          }
+
+        RadarSatRecordHeader headerDAT;
+        DataFactory factoryDAT;
+        ifstream dataFile (dataFilePath.c_str(), ios::in|ios::binary);
+        dataFile>>headerDAT;
+        if(dataFile.eof())
+          {
+          dataFile.close();
+          retValue =  false;
+          }
+        else
+          {
+          if(traceDebug())
+            {
+            ossimNotify(ossimNotifyLevel_DEBUG)<< "Begin reading DAT file" << std::endl;
+            }
+
+          RadarSatRecord* recordDAT = factoryDAT.Instanciate(headerDAT.get_rec_seq());
+          if (recordDAT != NULL && headerDAT.get_rec_seq() == 1)
+            {
+            recordDAT->Read(dataFile);
+            dataFile.close();
+            /*
+             * Reading the remaining of the data file
+             */
+            dataFile.open(dataFilePath.c_str(), ios::in|ios::binary);
+            dataFile>>*_data;
+            dataFile.close();
+
+            /*
+             * Commenting this line :
+             * With SARDEGNA file (a corrupted file without number of lines)
+             * this line makes disappear the auto-computation of number of lines
+             * by file seeking.
+             * It does not seem to add any information either (same keywordlist)
+             *
+             * TODO : investigate : what is it supposed to do ?
+             */
+            //_data->InsertRecord(headerDAT.get_rec_seq(), recordDAT);
+
+            if(traceDebug())
+              {
+              ossimNotify(ossimNotifyLevel_DEBUG) << "End reading DAT file" << std::endl;
+              }
+            } // TODO move to end
+          }// TODO move to end
+
+        /*
+         * Leader file path construction from the DAT file path
+         * Warning : the filename case has to be homogenous
+         */
+        std::string leader_file = dataFilePath;
+        string::size_type loc = leader_file.find( "DAT_01", 0 );
+        if( loc != string::npos ) leader_file.replace(loc, 6, "LEA_01" ); // upper case test
+        else
+          {
+          loc = leader_file.find( "dat_01", 0 );
+          if( loc != string::npos ) leader_file.replace(loc, 6, "lea_01" ); // lower case test
+          else
+            {
+            ossimNotify(ossimNotifyLevel_DEBUG) << "File Name not coherent (searching for *DAT_01* or *dat_01*)  : " << file << std::endl;
+            }
+          }
+        ossimFilename leaderFilePath(leader_file);
+        if (!leaderFilePath.exists())
+          {
+          ossimNotify(ossimNotifyLevel_DEBUG) << "Leader file not found (searching for *lea_01* coherent with *dat_01*)  : " << file << std::endl;
+          retValue = false;
+          }
+        else
+          {
+          if(traceDebug())
+            {
+            ossimNotify(ossimNotifyLevel_DEBUG) << "Begin reading Leader file" << std::endl;
+            }
+          /*
+           * Leader file data reading
+           */
+          ifstream leaderFile (leaderFilePath.c_str(), ios::in|ios::binary);
+          leaderFile>>*_leader;
+          leaderFile.close();
+          if(traceDebug())
+            {
+            ossimNotify(ossimNotifyLevel_DEBUG) << "End reading Leader file" << std::endl;
+            }
+          }
+
+        /*
+         * Trailer file path construction from the DAT file path
+         * Warning : the filename case has to be homogenous
+         */
+        std::string trailer_file = dataFilePath;
+        loc = trailer_file.find( "DAT_01", 0 );
+        if( loc != string::npos ) trailer_file.replace(loc, 6, "TRA_01" ); // upper case test
+        else
+          {
+          loc = trailer_file.find( "dat_01", 0 );
+          if( loc != string::npos ) trailer_file.replace(loc, 6, "tra_01" ); // lower case test
+          else
+            {
+            ossimNotify(ossimNotifyLevel_DEBUG) << "File Name not coherent (searching for *DAT_01* or *dat_01*)  : " << file << std::endl;
+            }
+          }
+        ossimFilename trailerFilePath(trailer_file);
+        if (!trailerFilePath.exists())
+          {
+          ossimNotify(ossimNotifyLevel_DEBUG) << "Trailer file not found (searching for *tra_01* coherent with *dat_01*)  : " << file << std::endl;
+          retValue = false;
+          }
+        else
+          {
+          if(traceDebug())
+            {
+            ossimNotify(ossimNotifyLevel_DEBUG) << "Begin reading Trailer file" << std::endl;
+            }
+          /*
+           * Trailer file data reading
+           */
+          ifstream trailerFile (trailerFilePath.c_str(), ios::in|ios::binary);
+          trailerFile>>*_trailer;
+          trailerFile.close();
+          if(traceDebug())
+            {
+            ossimNotify(ossimNotifyLevel_DEBUG) << "End reading Trailer file" << std::endl;
+            }
+          }
+        }
+      else
+        {
+        volumeDirFile.close();
+        retValue = false;
+        }
+      }
+    else
+      {
+      volumeDirFile.close();
+      retValue = false;
+      }
+    }
+
+  ossimKeywordlist geom_kwl;
+  this->internalSaveState(geom_kwl);
+  this->internalLoadState(geom_kwl);
+
+  // Assign the ossimSensorModel::theBoundGndPolygon
+  ossimGpt ul;
+  ossimGpt ur;
+  ossimGpt lr;
+  ossimGpt ll;
+  lineSampleToWorld(theImageClipRect.ul(), ul);
+  lineSampleToWorld(theImageClipRect.ur(), ur);
+  lineSampleToWorld(theImageClipRect.lr(), lr);
+  lineSampleToWorld(theImageClipRect.ll(), ll);
+  setGroundRect(ul, ur, lr, ll);  // ossimSensorModel method.
+
+  if(traceDebug())
+    {
+    ossimNotify(ossimNotifyLevel_DEBUG) << "ossimRadarSatModel::open() DEBUG: returning..." << std::endl;
+    }
+
+  return retValue;
+}
+
+
+bool ossimRadarSatModel::internalSaveState(ossimKeywordlist& kwl,
+                                           const char* prefix) const
+{
+  static const char MODULE[] = "ossimRadarSatModel::internalSaveState";
+
+  if (traceDebug())
+  {
+     ossimNotify(ossimNotifyLevel_DEBUG)<< MODULE << " entered...\n";
+  }
+
+  char name[64];
+
+    kwl.add(prefix, ossimKeywordNames::TYPE_KW, "ossimRadarSatModel", true);
+
+    FileDescriptor * fileDescriptor = _leader->get_FileDescriptor() ;
+    if(fileDescriptor != NULL)
+    {
+      kwl.add(prefix, "file_name",fileDescriptor->get_file_name().c_str(),true);
+    }
+    else
+    {
+      return false;
+    }
+
+    DataSetSummary * datasetSummary = _leader->get_DataSetSummary();
+    if(datasetSummary == NULL)
+      {
+      delete datasetSummary;
+      datasetSummary = _trailer->get_DataSetSummary();
+      }
+
+    if(datasetSummary != NULL)
+    {
+      kwl.add(prefix, "inp_sctim",datasetSummary->get_inp_sctim().c_str(),true);
+
+      kwl.add(prefix, "asc_des",datasetSummary->get_asc_des().c_str(),true);
+
+      kwl.add(prefix, "pro_lat",datasetSummary->get_pro_lat(),true);
+      kwl.add(prefix, "pro_long",datasetSummary->get_pro_long(),true);
+      kwl.add(prefix, "pro_head",datasetSummary->get_pro_head(),true);
+
+      kwl.add(prefix, "ellip_des",datasetSummary->get_ellip_des().c_str(),true);
+      kwl.add(prefix, "ellip_maj",datasetSummary->get_ellip_maj(),true);
+      kwl.add(prefix, "ellip_min",datasetSummary->get_ellip_min(),true);
+
+      kwl.add(prefix, "sc_lin",datasetSummary->get_sc_lin(),true);
+      kwl.add(prefix, "sc_pix",datasetSummary->get_sc_pix(),true);
+
+      kwl.add(prefix, "plat_lat",datasetSummary->get_plat_lat(),true);
+      kwl.add(prefix, "plat_long",datasetSummary->get_plat_long(),true);
+      kwl.add(prefix, "plat_head",datasetSummary->get_plat_head(),true);
+
+      kwl.add(prefix, "wave_length",datasetSummary->get_wave_length(),true);
+
+      kwl.add(prefix, "fr",datasetSummary->get_fr(),true);
+
+      kwl.add(prefix, "rng_gate",datasetSummary->get_rng_gate(),true);
+
+      kwl.add(prefix, "fa",datasetSummary->get_fa(),true);
+
+      kwl.add(prefix, "n_azilok",datasetSummary->get_n_azilok(),true);
+      kwl.add(prefix, "n_rnglok",datasetSummary->get_n_rnglok(),true);
+      kwl.add(prefix, "bnd_azilok",datasetSummary->get_bnd_azilok(),true);
+      kwl.add(prefix, "bnd_rnglok",datasetSummary->get_bnd_rnglok(),true);
+      kwl.add(prefix, "bnd_azi",datasetSummary->get_bnd_azi(),true);
+      kwl.add(prefix, "bnd_rng",datasetSummary->get_bnd_rng(),true);
+
+      kwl.add(prefix, "alt_dopcen0",datasetSummary->get_alt_dopcen()[0],true);
+      kwl.add(prefix, "alt_dopcen1",datasetSummary->get_alt_dopcen()[1],true);
+      kwl.add(prefix, "alt_dopcen2",datasetSummary->get_alt_dopcen()[2],true);
+
+      kwl.add(prefix, "crt_dopcen0",datasetSummary->get_crt_dopcen()[0],true);
+      kwl.add(prefix, "crt_dopcen1",datasetSummary->get_crt_dopcen()[1],true);
+      kwl.add(prefix, "crt_dopcen2",datasetSummary->get_crt_dopcen()[2],true);
+
+      kwl.add(prefix, "time_dir_pix",datasetSummary->get_time_dir_pix().c_str(),true);
+      kwl.add(prefix, "time_dir_lin",datasetSummary->get_time_dir_lin().c_str(),true);
+
+      kwl.add(prefix, "terrain_height",datasetSummary->get_terrain_h(),true);
+
+      kwl.add(prefix, "line_spacing",datasetSummary->get_line_spacing(),true);
+    }
+    else
+    {
+      ossimNotify(ossimNotifyLevel_DEBUG) << "It is not possible to add dataSetSummary from _leader or _trailer file" <<std::endl;
+      return false;
+    }
+
+    ProcessingParameters * processingParameters = _leader->get_ProcessingParameters();
+    if(processingParameters == NULL)
+      {
+      delete processingParameters;
+      processingParameters = _trailer->get_ProcessingParameters();
+      }
+
+    if(processingParameters != NULL)
+    {
+      kwl.add(prefix, "n_srgr",processingParameters->get_n_srgr(),true);
+
+      for (int i=0;i<processingParameters->get_n_srgr();i++)
+      {
+        sprintf(name,"srgr_update%i",i);
+        kwl.add(prefix, name,((processingParameters->get_srgr_coefset()[i]).get_srgr_update()).c_str(),true);
+
+        sprintf(name,"srgr_coef%iA",i);
+        kwl.add(prefix, name,(processingParameters->get_srgr_coefset()[i]).get_srgr_coef()[0],true);
+        sprintf(name,"srgr_coef%iB",i);
+        kwl.add(prefix, name,(processingParameters->get_srgr_coefset()[i]).get_srgr_coef()[1],true);
+        sprintf(name,"srgr_coef%iC",i);
+        kwl.add(prefix, name,(processingParameters->get_srgr_coefset()[i]).get_srgr_coef()[2],true);
+        sprintf(name,"srgr_coef%iD",i);
+        kwl.add(prefix, name,(processingParameters->get_srgr_coefset()[i]).get_srgr_coef()[3],true);
+        sprintf(name,"srgr_coef%iE",i);
+        kwl.add(prefix, name,(processingParameters->get_srgr_coefset()[i]).get_srgr_coef()[4],true);
+        sprintf(name,"srgr_coef%iF",i);
+        kwl.add(prefix, name,(processingParameters->get_srgr_coefset()[i]).get_srgr_coef()[5],true);
+      }
+
+      kwl.add(prefix, "pixel_spacing",processingParameters->get_pixel_spacing(),true);
+
+      kwl.add(prefix, "lookDirection",(processingParameters->get_sens_orient()).c_str(),true);
+    }
+    else
+    {
+      ossimNotify(ossimNotifyLevel_DEBUG) << "It is not possible to add processingParameters from _leader or _trailer file" <<std::endl;
+      return false;
+    }
+
+    PlatformPositionData * platformPositionData = _leader->get_PlatformPositionData();
+    if(platformPositionData != NULL)
+    {
+      kwl.add(prefix, "neph",platformPositionData->get_ndata(),true);
+      kwl.add(prefix, "eph_int",platformPositionData->get_data_int(),true);
+
+      kwl.add(prefix, "eph_year",platformPositionData->get_year(),true);
+      kwl.add(prefix, "eph_month",platformPositionData->get_month(),true);
+      kwl.add(prefix, "eph_day",platformPositionData->get_day(),true);
+      kwl.add(prefix, "eph_sec",platformPositionData->get_gmt_sec(),true);
+      kwl.add(prefix, "hr_angle",platformPositionData->get_hr_angle(),true);
+
+      for(int i=0;i<platformPositionData->get_ndata();i++)
+      {
+        sprintf(name,"eph%i_posX",i);
+        kwl.add(prefix, name,(platformPositionData->get_pos_vect()[i]).get_pos()[0],true);
+        sprintf(name,"eph%i_posY",i);
+        kwl.add(prefix, name,(platformPositionData->get_pos_vect()[i]).get_pos()[1],true);
+        sprintf(name,"eph%i_posZ",i);
+        kwl.add(prefix, name,(platformPositionData->get_pos_vect()[i]).get_pos()[2],true);
+
+        sprintf(name,"eph%i_velX",i);
+        kwl.add(prefix, name,(platformPositionData->get_pos_vect()[i]).get_vel()[0],true);
+        sprintf(name,"eph%i_velY",i);
+        kwl.add(prefix, name,(platformPositionData->get_pos_vect()[i]).get_vel()[1],true);
+        sprintf(name,"eph%i_velZ",i);
+        kwl.add(prefix, name,(platformPositionData->get_pos_vect()[i]).get_vel()[2],true);
+      }
+    }
+    else
+    {
+      ossimNotify(ossimNotifyLevel_DEBUG) << "It is not possible to add platformPositionData from _leader file" <<std::endl;
+      return false;
+    }
+
+    ImageOptionsFileDescriptor * imageOptionsFileDescriptor = _data->get_ImageOptionsFileDescriptor();
+    if(imageOptionsFileDescriptor != NULL)
+    {
+      kwl.add(prefix, "nbLin",imageOptionsFileDescriptor->get_nlin(),true);
+      kwl.add(prefix, "nbCol",imageOptionsFileDescriptor->get_ngrp(),true);
+    }
+    else
+    {
+      ossimNotify(ossimNotifyLevel_DEBUG) << "It is not possible to add imageOptionsFileDescriptor from _data file" <<std::endl;
+      return false;
+    }
+
+    ProcessedDataRecord * firstProcessedDataRecord = _data->get_FirstProcessedDataRecord();
+    if(firstProcessedDataRecord != NULL)
+    {
+      sprintf(name,"cornersLon%i",0);
+      kwl.add(prefix, name,((float) (firstProcessedDataRecord->get_lon_first()))/1000000.0,true);
+      sprintf(name,"cornersLat%i",0);
+      kwl.add(prefix, name,((float) (firstProcessedDataRecord->get_lat_first()))/1000000.0,true);
+      sprintf(name,"cornersLon%i",1);
+      kwl.add(prefix, name,((float) (firstProcessedDataRecord->get_lon_last()))/1000000.0,true);
+      sprintf(name,"cornersLat%i",1);
+      kwl.add(prefix, name,((float) (firstProcessedDataRecord->get_lat_last()))/1000000.0,true);
+      kwl.add(prefix, "acq_msec_first",firstProcessedDataRecord->get_acq_msec(),true);
+    }
+    else
+    {
+      ossimNotify(ossimNotifyLevel_DEBUG) << "It is not possible to add firstProcessedDataRecord from _data file" <<std::endl;
+      return false;
+    }
+
+    ProcessedDataRecord * lastProcessedDataRecord = _data->get_LastProcessedDataRecord();
+    if(lastProcessedDataRecord != NULL)
+    {
+      sprintf(name,"cornersLon%i",2);
+      kwl.add(prefix, name,((float) (lastProcessedDataRecord->get_lon_first()))/1000000.0,true);
+      sprintf(name,"cornersLat%i",2);
+      kwl.add(prefix, name,((float) (lastProcessedDataRecord->get_lat_first()))/1000000.0,true);
+      sprintf(name,"cornersLon%i",3);
+      kwl.add(prefix, name,(((float) lastProcessedDataRecord->get_lon_last()))/1000000.0,true);
+      sprintf(name,"cornersLat%i",3);
+      kwl.add(prefix, name,((float) (lastProcessedDataRecord->get_lat_last()))/1000000.0,true);
+      kwl.add(prefix, "acq_msec_last",lastProcessedDataRecord->get_acq_msec(),true);
+    }
+    else
+    {
+      ossimNotify(ossimNotifyLevel_DEBUG) << "It is not possible to add lastProcessedDataRecord from _data file" <<std::endl;
+      return false;
+    }
+
+    return true;
+}
+
+bool ossimRadarSatModel::saveState(ossimKeywordlist& kwl,
+                                                 const char* prefix) const
+{
+  bool result = this->internalSaveState(kwl, prefix);
+
+  if (result)
+  {
+    result = ossimGeometricSarSensorModel::saveState(kwl, prefix);
+  }
+
+  return result;
+}
+
+bool ossimRadarSatModel::internalLoadState (const ossimKeywordlist &kwl,
+                                            const char *prefix)
+{
+  static const char MODULE[] = "ossimRadarSatModel::internalLoadState";
+  if (traceDebug())
+  {
+     ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " entered...\n";
+  }
+
+  this->InitSRGR(kwl, prefix);
+  this->InitSensorParams(kwl, prefix);
+  this->InitPlatformPosition(kwl, prefix);
+  this->InitRefPoint(kwl, prefix);
+
+  if (traceDebug())
+  {
+     ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " exit...\n";
+  }
+  return true;
+}
+
+bool ossimRadarSatModel::loadState (const ossimKeywordlist &kwl,
+                                    const char *prefix)
+{
+  static const char MODULE[] = "ossimRadarSatModel::loadState";
+  if (traceDebug())
+  {
+     ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " entered...\n";
+  }
+
+  const char* lookup = 0;
+  ossimString s;
+
+  // Check the type first.
+  lookup = kwl.find(prefix, ossimKeywordNames::TYPE_KW);
+  if (lookup)
+  {
+     s = lookup;
+     if (s != getClassName())
+     {
+        return false;
+     }
+  }
+
+  //bool result = ossimGeometricSarSensorModel::loadState(kwl, prefix);
+
+  bool result = true;
+  if (result)
+    {
+    result = this->internalLoadState(kwl, prefix);
+    }
+
+  if (traceDebug())
+  {
+     ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " exit...\n";
+  }
+  return result;
+}
+
+bool ossimRadarSatModel::InitSensorParams(const ossimKeywordlist &kwl, const char *prefix)
+{
+  const char* wave_length_str = kwl.find(prefix,"wave_length");
+  double wave_length = atof(wave_length_str);
+  const char* fr_str = kwl.find(prefix,"fr");
+  double fr = atof(fr_str);
+  const char* fa_str = kwl.find(prefix,"fa");
+  double fa = atof(fa_str);
+
+  /* //number of different looks
+  const char* n_azilok_str = kwl.find(prefix,"n_azilok");
+  double n_azilok = atof(n_azilok_str);
+  const char* n_rnglok_str = kwl.find(prefix,"n_rnglok");
+  double n_rnglok = atof(n_rnglok_str);
+  */
+
+  // look bandwidth rate (for localisation purpose)
+  const char* bnd_azilok_str = kwl.find(prefix,"bnd_azilok");
+  double bnd_azilok = atof(bnd_azilok_str);
+  const char* bnd_rnglok_str = kwl.find(prefix,"bnd_rnglok");
+  double bnd_rnglok = atof(bnd_rnglok_str);
+  const char* bnd_azi_str = kwl.find(prefix,"bnd_azi");
+  double bnd_azi = atof(bnd_azi_str);
+  const char* bnd_rng_str = kwl.find(prefix,"bnd_rng");
+  double bnd_rng = atof(bnd_rng_str);
+
+  double n_azilok = bnd_azi/bnd_azilok;
+  double n_rnglok = bnd_rng/bnd_rnglok;
+
+  const char* time_dir_pix = kwl.find(prefix,"time_dir_pix");
+  const char* time_dir_lin = kwl.find(prefix,"time_dir_lin");
+
+  //ellipsoid parameters
+  const char* ellip_maj_str = kwl.find(prefix,"ellip_maj");
+  double ellip_maj = atof(ellip_maj_str) * 1000.0;  // km -> m
+  const char* ellip_min_str = kwl.find(prefix,"ellip_min");
+  double ellip_min = atof(ellip_min_str) * 1000.0;  // km -> m
+
+  if(_sensor != NULL)
+  {
+    delete _sensor;
+  }
+
+  _sensor = new SensorParams();
+
+  if(strcmp(time_dir_pix, "INCREASE") == 0)
+  {
+    _sensor->set_col_direction(1);
+  }
+  else
+  {
+    _sensor->set_col_direction(-1);
+  }
+
+  if(strcmp(time_dir_lin, "INCREASE") == 0)
+  {
+    _sensor->set_lin_direction(1);
+  }
+  else
+  {
+    _sensor->set_lin_direction(-1);
+  }
+
+  const char* lookDirection_str = kwl.find(prefix,"lookDirection");
+  ossimString lookDirection(lookDirection_str) ;
+  lookDirection.trim(" ") ; // eliminates trailing blanks
+  if (lookDirection == "NORMAL") _sensor->set_sightDirection(SensorParams::Right) ;
+  else _sensor->set_sightDirection(SensorParams::Left) ;
+
+  _sensor->set_prf(fa);
+  _sensor->set_sf(fr);
+  _sensor->set_rwl(wave_length);
+  _sensor->set_nAzimuthLook(n_azilok);
+  _sensor->set_nRangeLook(n_rnglok);
+
+  _sensor->set_semiMajorAxis(ellip_maj) ;
+  _sensor->set_semiMinorAxis(ellip_min) ;
+
+  return true;
+}
+
+bool ossimRadarSatModel::InitPlatformPosition(const ossimKeywordlist &kwl, const char *prefix)
+{
+  const double _PI          = 3.14159265358979323846 ;
+  CivilDateTime ref_civil_date;
+  /*
+   * Ephemerisis reference date retrieval
+   */
+  const char* eph_year_str = kwl.find(prefix,"eph_year");
+  int eph_year = atoi(eph_year_str);
+  const char* eph_month_str = kwl.find(prefix,"eph_month");
+  int eph_month = atoi(eph_month_str);
+  const char* eph_day_str = kwl.find(prefix,"eph_day");
+  int eph_day = atoi(eph_day_str);
+  const char* eph_sec_str = kwl.find(prefix,"eph_sec");
+  double eph_sec = atof(eph_sec_str);
+
+  ref_civil_date.set_year(eph_year);
+  ref_civil_date.set_month(eph_month);
+  ref_civil_date.set_day(eph_day);
+  ref_civil_date.set_second((int)eph_sec);
+  ref_civil_date.set_decimal( eph_sec-(double)((int)eph_sec));
+
+
+  JSDDateTime ref_jsd_date(ref_civil_date);
+
+  const char* eph_int_str = kwl.find(prefix, "eph_int");
+  double eph_int = atof(eph_int_str);
+  /*
+   * Ephemerisis number retrieval
+   */
+  const char* neph_str = kwl.find(prefix,"neph");
+  int neph = atoi(neph_str);
+
+  Ephemeris** ephemeris = new Ephemeris*[neph];
+
+  const char* hr_angle_str = kwl.find(prefix,"hr_angle");
+  double greenwich_mha_ref = atof(hr_angle_str);
+
+  GMSTDateTime * greenwich_mha_ref2000 = new GMSTDateTime();
+  greenwich_mha_ref2000->set_origine(GMSTDateTime::AN2000);
+  ref_civil_date.AsGMSTDateTime(greenwich_mha_ref2000);
+
+  /*
+   * Ephemerisis retrieval
+   */
+  for (int i=0;i<neph;i++)
+  {
+    double pos[3];
+    double vit[3];
+    char name[64];
+
+
+    sprintf(name,"eph%i_posX",i);
+    const char* px_str = kwl.find(prefix,name);
+    pos[0] = atof(px_str);
+
+    sprintf(name,"eph%i_posY",i);
+    const char* py_str = kwl.find(prefix,name);
+    pos[1] = atof(py_str);
+
+    sprintf(name,"eph%i_posZ",i);
+    const char* pz_str = kwl.find(prefix,name);
+    pos[2] = atof(pz_str);
+
+
+    sprintf(name,"eph%i_velX",i);
+    const char* vx_str = kwl.find(prefix,name);
+    vit[0] = atof(vx_str) * 1.0e-3;;
+
+    sprintf(name,"eph%i_velY",i);
+    const char* vy_str = kwl.find(prefix,name);
+    vit[1] = atof(vy_str) * 1.0e-3;;
+
+    sprintf(name,"eph%i_velZ",i);
+    const char* vz_str = kwl.find(prefix,name);
+    vit[2] = atof(vz_str) * 1.0e-3;;
+
+    /*
+     * Ephemerisis date
+     */
+    JSDDateTime date(ref_jsd_date);
+    date.set_second(date.get_second() + i * eph_int);
+    date.NormDate();
+
+    /*
+     * Date creation for referential change
+     */
+    GMSTDateTime * greenwich_mha = new GMSTDateTime();
+    greenwich_mha->set_origine(GMSTDateTime::AN2000);
+    date.AsGMSTDateTime(greenwich_mha);
+
+    double angle = greenwich_mha_ref+(greenwich_mha->get_tms()-greenwich_mha_ref2000->get_tms())*180.0/_PI;
+    angle = fmod(angle,360.0);
+
+    /*
+     * Referential change
+     */
+    GalileanEphemeris * tmpEphemeris = new GalileanEphemeris(date,pos,vit);
+    GeographicEphemeris* eph = new GeographicEphemeris();
+
+    tmpEphemeris->ToGeographic(angle,eph);
+    ephemeris[i] = eph;
+
+    delete tmpEphemeris;
+    delete greenwich_mha;
+
+  }
+
+  delete greenwich_mha_ref2000;
+
+  /*
+   * Antenna position interpolator creation
+   */
+  if (_platformPosition != NULL)
+  {
+    delete _platformPosition;
+  }
+  _platformPosition = new PlatformPosition(ephemeris,neph);
+
+  /*
+   * Free of memory used by the ephemerisis list
+   */
+  for (int i=0;i<neph;i++)
+  {
+    delete ephemeris[i];
+  }
+  delete[] ephemeris;
+
+  return true;
+}
+
+bool ossimRadarSatModel::InitRefPoint(const ossimKeywordlist &kwl, const char *prefix)
+{
+  const char* sc_lin_str = kwl.find(prefix,"sc_lin");
+  double sc_lin = atof(sc_lin_str);
+
+  const char* sc_pix_str = kwl.find(prefix,"sc_pix");
+  double sc_pix = atof(sc_pix_str);
+
+  const char* inp_sctim_str = kwl.find(prefix,"inp_sctim");
+
+  const char* rng_gate_str = kwl.find(prefix,"rng_gate");
+  double rng_gate = atof(rng_gate_str);
+
+  if(_refPoint == NULL)
+  {
+    _refPoint = new RefPoint();
+  }
+
+  _refPoint->set_pix_col(sc_pix);
+  _refPoint->set_pix_line(sc_lin);
+
+  char year_str[5];
+  for (int i=0;i<4;i++)
+  {
+    year_str[i] = inp_sctim_str[i];
+  }
+  year_str[4] = '\0';
+
+  char month_str[3];
+  for (int i=4;i<6;i++)
+  {
+    month_str[i-4] = inp_sctim_str[i];
+  }
+  month_str[2] = '\0';
+
+  char day_str[3];
+  for (int i=6;i<8;i++)
+  {
+    day_str[i-6] = inp_sctim_str[i];
+  }
+  day_str[2] = '\0';
+
+  char hour_str[3];
+  for (int i=8;i<10;i++)
+  {
+    hour_str[i-8] = inp_sctim_str[i];
+  }
+  hour_str[2] = '\0';
+
+  char min_str[3];
+  for (int i=10;i<12;i++)
+  {
+    min_str[i-10] = inp_sctim_str[i];
+  }
+  min_str[2] = '\0';
+
+  char sec_str[3];
+  for (int i=12;i<14;i++)
+  {
+    sec_str[i-12] = inp_sctim_str[i];
+  }
+  sec_str[2] = '\0';
+
+  char mili_str[4];
+  for (int i=14;i<17;i++)
+  {
+    mili_str[i-14] = inp_sctim_str[i];
+  }
+  mili_str[3] = '\0';
+
+  int year = atoi(year_str);
+  int month = atoi(month_str);
+  int day = atoi(day_str);
+  int hour = atoi(hour_str);
+  int min = atoi(min_str);
+  int sec = atoi(sec_str);
+  double mili = atof(mili_str);
+
+
+  CivilDateTime date(year, month, day, hour * 3600 + min * 60 + sec, mili/1000.0);
+
+  if(_platformPosition != NULL)
+  {
+    Ephemeris * ephemeris = _platformPosition->Interpolate((JSDDateTime)date);
+    if (ephemeris == NULL) return false ;
+
+    _refPoint->set_ephemeris(ephemeris);
+
+    delete ephemeris;
+  }
+  else
+  {
+    return false;
+  }
+
+  double c = 2.99792458e+8;
+
+  double distance = (rng_gate + ((double)sc_pix)*_sensor->get_nRangeLook()/_sensor->get_sf()) * (c/2.0);
+
+  // in the case of Georeferenced images, the "relative" ground range is stored in place of the slant range
+  // (used for SlantRange computation relative to reference point, necessary for optimization)
+  // here, the pixelDirection is ignored since the RDS reference point is always at the scene centre
+  if (_isProductGeoreferenced) {
+    distance = _refPoint->get_pix_col() * _pixel_spacing ;
+  }
+
+  _refPoint->set_distance(distance);
+
+
+//// essai : line spacing et speed satellite
+//  const char* line_spacing_str = kwl.find(prefix,"line_spacing");
+//  double line_spacing = atof(line_spacing_str);
+//  Ephemeris * ephemeris = _refPoint->get_ephemeris() ;
+//  double velSat = sqrt(pow(ephemeris->get_speed()[0], 2)+ pow(ephemeris->get_speed()[1], 2)+ pow(ephemeris->get_speed()[2], 2));
+//  double prfeq = velSat / line_spacing ;
+//  _sensor->set_prf(prfeq);
+//  _sensor->set_nAzimuthLook(1.0);
+///**
+// * @todo : effacer
+// */
+
+  // in order to use ossimSensorModel::lineSampleToWorld
+  const char* nbCol_str = kwl.find(prefix,"nbCol");
+  const char* nbLin_str = kwl.find(prefix,"nbLin");
+
+  theImageSize.x      = atoi(nbCol_str);
+  theImageSize.y      = atoi(nbLin_str);
+  theImageClipRect    = ossimDrect(0, 0, theImageSize.x-1, theImageSize.y-1);
+
+  // sensor PRF update in the case of ground projected products
+  if (_isProductGeoreferenced) {
+    const char* acq_msec_first_str = kwl.find("acq_msec_first");
+    double acq_msec_first = atof(acq_msec_first_str);
+    const char* acq_msec_last_str = kwl.find("acq_msec_last");
+    double acq_msec_last = atof(acq_msec_last_str);
+
+    double actualPRF = 1000.0*theImageSize.y/(acq_msec_last-acq_msec_first) ;
+    _sensor->set_nAzimuthLook(_sensor->get_prf()/actualPRF);
+  }
+
+  // Ground Control Points extracted from the model : scene center
+  std::list<ossimGpt> groundGcpCoordinates ;
+  std::list<ossimDpt> imageGcpCoordinates ;
+  const char* lon_str = kwl.find("pro_long");
+  double lon = atof(lon_str);
+  const char* lat_str = kwl.find("pro_lat");
+  double lat = atof(lat_str);
+  //const char* height_str = kwl.find("terrain_height");
+  double height = 0 ; //atof(height_str) ;
+
+  ossimDpt imageGCP(sc_pix,sc_lin);
+  ossimGpt groundGCP(lat, lon, height);
+  groundGcpCoordinates.push_back(groundGCP) ;
+  imageGcpCoordinates.push_back(imageGCP) ;
+
+  // Ground Control Points extracted from the model : scene corners
+  // upper left corner
+  lon = atof(kwl.find("cornersLon0"));
+  lat = atof(kwl.find("cornersLat0"));
+  ossimDpt imageGCP0(0,0);
+  ossimGpt groundGCP0(lat, lon, height);
+  groundGcpCoordinates.push_back(groundGCP0) ;
+  imageGcpCoordinates.push_back(imageGCP0) ;
+  // upper right corner
+  lon = atof(kwl.find("cornersLon1"));
+  lat = atof(kwl.find("cornersLat1"));
+  ossimDpt imageGCP1(theImageSize.x-1,0);
+  ossimGpt groundGCP1(lat, lon, height);
+  groundGcpCoordinates.push_back(groundGCP1) ;
+  imageGcpCoordinates.push_back(imageGCP1) ;
+  // lower left corner
+  lon = atof(kwl.find("cornersLon2"));
+  lat = atof(kwl.find("cornersLat2"));
+  ossimDpt imageGCP2(0,theImageSize.y-1);
+  ossimGpt groundGCP2(lat, lon, height);
+  groundGcpCoordinates.push_back(groundGCP2) ;
+  imageGcpCoordinates.push_back(imageGCP2) ;
+  // lower right corner
+  lon = atof(kwl.find("cornersLon3"));
+  lat = atof(kwl.find("cornersLat3"));
+  ossimDpt imageGCP3(theImageSize.x-1,theImageSize.y-1);
+  ossimGpt groundGCP3(lat, lon, height);
+  groundGcpCoordinates.push_back(groundGCP3) ;
+  imageGcpCoordinates.push_back(imageGCP3) ;
+
+  // Default optimization
+  optimizeModel(groundGcpCoordinates, imageGcpCoordinates) ;
+
+  return true;
+}
+
+bool ossimRadarSatModel::InitSRGR(const ossimKeywordlist &kwl, const char *prefix)
+{
+  // product type : format "RSAT-1-SAR-{SLC,SGG,SGC,...}-..."
+  const char* file_name_str = kwl.find(prefix,"file_name");
+  char format[4] ;
+  // product type (SLC,SGG,SGC,...) extraction
+  for (int j=11;j<14;j++)
+  {
+    format[j-11] = file_name_str[j];
+  }
+  format[3] = '\0';
+  std::string format_str(format);
+
+  _isProductGeoreferenced = (format_str=="SGX") || (format_str=="SGF") || (format_str=="SCW");
+
+  // pixel spacing
+  const char* pixel_spacing_str = kwl.find(prefix,"pixel_spacing");
+  _pixel_spacing = atof(pixel_spacing_str);
+
+  // number of SRGR sets
+  const char* n_srgr_str = kwl.find(prefix,"n_srgr");
+  _n_srgr = atoi(n_srgr_str);
+
+  char name[64];
+  for (int i=0;i<_n_srgr;i++)
+  {
+    // SRGR update time, format : YYYY-DDD-HH:MM:SS.SSS
+    sprintf(name,"srgr_update%i",i);
+    const char* srgr_update_str = kwl.find(prefix,name);
+
+    // years and days are ignored in the following (conversion from CivilDate to JSDDate requires a YYYY-MM-DD format)
+    // could be improved
+    char hour_str[3];
+    for (int j=9;j<11;j++)
+    {
+      hour_str[j-9] = srgr_update_str[j];
+    }
+    hour_str[2] = '\0';
+
+    char min_str[3];
+    for (int j=12;j<14;j++)
+    {
+      min_str[j-12] = srgr_update_str[j];
+    }
+    min_str[2] = '\0';
+
+    char sec_str[3];
+    for (int j=15;j<17;j++)
+    {
+      sec_str[j-15] = srgr_update_str[j];
+    }
+    sec_str[2] = '\0';
+
+    char mili_str[4];
+    for (int j=18;j<21;j++)
+    {
+      mili_str[j-18] = srgr_update_str[j];
+    }
+    mili_str[3] = '\0';
+
+    int hour = atoi(hour_str);
+    int min = atoi(min_str);
+    int sec = atoi(sec_str);
+    double mili = atof(mili_str);
+    _srgr_update[i] = hour * 3600 + min * 60 + sec + mili/1000.0 ;
+
+    // SRGR coefficients
+    sprintf(name,"srgr_coef%iA",i);
+    const char* srgr_coef_strA = kwl.find(prefix,name);
+    _srgr_coefset[i][0] = atof(srgr_coef_strA);
+    sprintf(name,"srgr_coef%iB",i);
+    const char* srgr_coef_strB = kwl.find(prefix,name);
+    _srgr_coefset[i][1] = atof(srgr_coef_strB);
+    sprintf(name,"srgr_coef%iC",i);
+    const char* srgr_coef_strC = kwl.find(prefix,name);
+    _srgr_coefset[i][2] = atof(srgr_coef_strC);
+    sprintf(name,"srgr_coef%iD",i);
+    const char* srgr_coef_strD = kwl.find(prefix,name);
+    _srgr_coefset[i][3] = atof(srgr_coef_strD);
+    sprintf(name,"srgr_coef%iE",i);
+    const char* srgr_coef_strE = kwl.find(prefix,name);
+    _srgr_coefset[i][4] = atof(srgr_coef_strE);
+    sprintf(name,"srgr_coef%iF",i);
+    const char* srgr_coef_strF = kwl.find(prefix,name);
+    _srgr_coefset[i][5] = atof(srgr_coef_strF);
+  }
+  return true;
+}
+
+int ossimRadarSatModel::FindSRGRSetNumber(JSDDateTime date) const
+{
+  if (_n_srgr==0) return(-1) ;
+
+  double delays[20];
+  for (int i=0;i<_n_srgr;i++)
+  {
+    delays[i] = fabs(date.get_second()+date.get_decimal()-_srgr_update[i]) ;
+  }
+
+  int setNumber = 0 ;
+  double min_delay = delays[0] ;
+  for (int i=1;i<_n_srgr;i++)
+  {
+    if (delays[i]<min_delay) {
+      setNumber = i ;
+      min_delay = delays[i] ;
+    }
+  }
+  return setNumber ;
+}
+}
+
diff --git a/ossim_plugins/ossim/ossimRadarSatModel.h b/ossim_plugins/ossim/ossimRadarSatModel.h
new file mode 100644
index 0000000..72b0a2f
--- /dev/null
+++ b/ossim_plugins/ossim/ossimRadarSatModel.h
@@ -0,0 +1,169 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef ossimRadarSatModel_H
+#define ossimRadarSatModel_H
+
+#include <otb/JSDDateTime.h>
+
+#include <ossimGeometricSarSensorModel.h>
+#include <ossim/projection/ossimMapProjection.h>
+#include <ossim/base/ossimIpt.h>
+#include <ossim/base/ossimFilename.h>
+#include <ossim/base/ossimGpt.h>
+#include <ossim/base/ossimDpt.h>
+#include <RadarSat/Data/Data.h>
+#include <RadarSat/Leader/Leader.h>
+#include <RadarSat/Trailer/Trailer.h>
+#include <RadarSat/VolumeDir/VolumeDir.h>
+
+#include <iostream>
+
+namespace ossimplugins
+{
+
+
+class PlatformPosition;
+class SensorParams;
+class RefPoint;
+/**
+ * @brief This class is able to direct localisation and indirect localisation using the RadarSat sensor model
+ */
+class ossimRadarSatModel : public ossimGeometricSarSensorModel
+{
+public:
+  /** @brief Constructor */
+  ossimRadarSatModel();
+
+  /** @brief copy constructor */
+  ossimRadarSatModel(const ossimRadarSatModel& rhs);
+
+  /** @brief Destructor */
+  virtual ~ossimRadarSatModel();
+
+  /**
+   * @brief Method to return the class name.
+   * @return The name of this class.
+   */
+
+  virtual ossimString getClassName() const;
+  /**
+   * @brief Returns pointer to a new instance, copy of this.
+   */
+
+  virtual ossimObject* dup() const;
+  /**
+   * @brief This function associates an image column number to a slant range when the image is georeferenced (ground projected)
+   * @param col Column coordinate of the image point
+   */
+  virtual double getSlantRangeFromGeoreferenced(double col) const;
+
+  /**
+     * @brief Method to intantial model from a file.
+     *
+     * @param file
+     *
+     * @return true on success, false on error.
+     */
+    bool open(const ossimFilename& file);
+
+    /**
+     * @brief Method to save object state to a keyword list.
+     * @param kwl Keyword list to save to.
+     * @param prefix added to keys when saved.
+     * @return true on success, false on error.
+     */
+    virtual bool saveState(ossimKeywordlist& kwl,
+                           const char* prefix=0) const;
+
+    /**
+     * @brief Method to the load (recreate) the state of the object from a
+     * keyword list. Return true if ok or false on error.
+     * @return true if load OK, false on error
+     */
+    virtual bool loadState (const ossimKeywordlist &kwl, const char *prefix=0);
+
+protected:
+
+  /**
+   *  @brief Slant Range for each Ground Range (SRGR) number of coefficients sets
+   */
+  int   _n_srgr;
+  /**
+   * @brief SRGR coefficient sets
+   */
+  double _srgr_coefset[20][6];
+  /**
+   * @brief SRGR coefficient sets update times
+   */
+  double _srgr_update[20];
+  /**
+   * @brief Pixel spacing
+   */
+  double _pixel_spacing;
+
+  /**
+   * @brief List of metadata contained in the Data file
+   */
+  Data * _data;
+
+  /**
+   * @brief List of metadata contained in the Leader file
+   */
+  Leader * _leader;
+
+  /**
+   * @brief List of metadata contained in the Trailer file
+   */
+  Trailer * _trailer;
+
+  /**
+   * @brief List of metadata contained in the Volume Directory file
+   */
+  VolumeDir * _volumeDir;
+
+private:
+  virtual bool InitPlatformPosition(const ossimKeywordlist &kwl, const char *prefix);
+  virtual bool InitSensorParams(const ossimKeywordlist &kwl, const char *prefix);
+  virtual bool InitRefPoint(const ossimKeywordlist &kwl, const char *prefix);
+  /**
+   * @brief Initializes the Slant Range for each Ground Range data sets : _n_srgr,_srgr_coefset,_srgr_update,_pixel_spacing,_isProductGeoreferenced
+   */
+  virtual bool InitSRGR(const ossimKeywordlist &kwl, const char *prefix);
+
+  /**
+   * @brief Method to save object state to a keyword list.
+   * @param kwl Keyword list to save to.
+   * @param prefix added to keys when saved.
+   * @return true on success, false on error.
+   */
+  virtual bool internalSaveState(ossimKeywordlist& kwl,
+                         const char* prefix=0) const;
+
+  /**
+   * @brief Method to the load (recreate) the state of the object from a
+   * keyword list. Return true if ok or false on error.
+   * @return true if load OK, false on error
+   */
+  virtual bool internalLoadState (const ossimKeywordlist &kwl, const char *prefix=0);
+
+
+  /**
+   * @brief Finds the SRGR data set which update time is the closest to the center scene time
+   */
+  int FindSRGRSetNumber(JSDDateTime date)  const;
+  TYPE_DATA
+
+};
+}
+
+#endif
+
diff --git a/ossim_plugins/ossim/ossimSpot6DimapSupportData.cpp b/ossim_plugins/ossim/ossimSpot6DimapSupportData.cpp
new file mode 100644
index 0000000..6856715
--- /dev/null
+++ b/ossim_plugins/ossim/ossimSpot6DimapSupportData.cpp
@@ -0,0 +1,2217 @@
+//*******************************************************************
+// Copyright (C) 2014  Centre National Etudes Spatiales
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 3 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+//
+// Author : Christophe Palmann (christophe.palmann at c-s.fr)
+//
+// Description:
+//
+// Contains declaration of class ossimSpot6DimapSupportData
+//
+//*****************************************************************************
+
+#include <ossimSpot6DimapSupportData.h>
+#include <ossim/base/ossimKeywordlist.h>
+#include <ossim/base/ossimNotify.h>
+#include <ossim/base/ossimKeywordNames.h>
+#include <ossim/base/ossimTrace.h>
+
+#include <ossim/base/ossimFilename.h>
+#include <ossim/base/ossimXmlDocument.h>
+#include <ossim/base/ossimXmlAttribute.h>
+#include <ossim/base/ossimXmlNode.h>
+
+#include <ossimPluginCommon.h>
+#include <ossim/base/ossimCommon.h>
+
+#include <ossim/base/ossimDatum.h>
+#include <ossim/base/ossimNotifyContext.h>
+
+#include <cstdio>
+#include <cstdlib>
+#include <iostream>
+#include <iterator>
+#include <sstream>
+
+
+// Define Trace flags for use within this file:
+static ossimTrace traceExec  ("ossimSpot6DimapSupportData:exec");
+static ossimTrace traceDebug ("ossimSpot6DimapSupportData:debug");
+
+static std::string getVectorFloat64AsString(std::vector<ossim_float64> in)
+{
+   std::vector<ossim_float64>::iterator it;
+   std::stringstream strTmp;
+
+   for ( it=in.begin() ; it < in.end(); it++ )
+   {
+      strTmp << " " << (*it);
+   }
+
+   return strTmp.str();
+}
+
+static std::string getVectorDoubleAsString(std::vector<double> in)
+{
+   std::vector<double>::iterator it;
+   std::stringstream strTmp;
+
+   for ( it=in.begin() ; it < in.end(); it++ )
+   {
+      strTmp << " " << (*it);
+   }
+
+   return strTmp.str();
+}
+
+static std::string getVectorStringAsString(std::vector<ossimString> in)
+{
+   std::vector<ossimString>::iterator it;
+   std::stringstream strTmp;
+
+   for ( it=in.begin() ; it < in.end(); it++ )
+   {
+      strTmp << " " << (*it);
+   }
+
+   return strTmp.str();
+}
+
+
+
+namespace ossimplugins
+{
+
+   static bool readOneXmlNode(ossimRefPtr<ossimXmlDocument> xmlDocument,
+                              ossimString xpath,
+                              ossimString& nodeValue)
+   {
+      vector<ossimRefPtr<ossimXmlNode> > xml_nodes;
+
+      xmlDocument->findNodes(xpath, xml_nodes);
+      if (xml_nodes.size() == 0)
+      {
+         if(traceDebug())
+         {
+            ossimNotify(ossimNotifyLevel_DEBUG) << " DEBUG:"
+                                                << "\nCould not find: " << xpath << std::endl;
+         }
+         return false;
+      }
+      if (xml_nodes.size() != 1)
+      {
+         if(traceDebug())
+         {
+            ossimNotify(ossimNotifyLevel_DEBUG) << " DEBUG:"
+                                                << "\nMore than one node value with " << xpath << std::endl;
+         }
+         return false;
+      }
+      nodeValue = xml_nodes[0]->getText();
+      return true;
+   }
+
+   ossimSpot6DimapSupportData::ossimSpot6DimapSupportData ()
+      :ossimErrorStatusInterface(),
+       theDIMAPVersion(OSSIM_Spot6_UNKNOWN),
+       theMetadataSubProfile(OSSIM_Spot6_METADATA_SUBPROFILE_UNKNOWN),
+       theProductIsOk(false),
+       theRpcIsOk(false),
+       theXmlDocumentRoot(),
+
+       theSensorID(),
+       theImageID(),
+       theProductionDate(),
+       theAcquisitionDate(),
+       theInstrument(),
+       theInstrumentIndex(),
+       theProcessingLevelString(),
+       theSpectralProcessingString(),
+
+       theSunAzimuth(),
+       theSunElevation(),
+       theIncidenceAngle(),
+       theViewingAngle(),
+       theAzimuthAngle(),
+
+       theImageSize(0, 0),
+       theTileSize(0, 0),
+       theNumberOfMegaTilesInRow(0),
+       theNumberOfMegaTilesInCol(0),
+       theNumberOfMegaTiles(0),
+       theMultiDataFile(),
+
+       theNumBands(0),
+       theBandOrder(),
+
+       thePhysicalBias(),
+       thePhysicalGain(),
+       theSolarIrradiance(),
+
+       theUlCorner(),
+       theUrCorner(),
+       theLrCorner(),
+       theLlCorner(),
+
+       theSpecId(),
+       theErrBias(0),
+       theErrBiasX(0),
+       theErrBiasY(0),
+       theErrRand(0),
+       theLineOffset(0),
+       theSampOffset(0),
+       theLatOffset(0),
+       theLonOffset(0),
+       theHeightOffset(0),
+       theLineScale(0),
+       theSampScale(0),
+       theLatScale(0),
+       theLonScale(0),
+       theHeightScale(0),
+       theLineNumCoeff(),
+       theLineDenCoeff(),
+       theSampNumCoeff(),
+       theSampDenCoeff(),
+
+       theRefGroundPoint(0.0, 0.0, 0.0),
+       theRefImagePoint(0.0, 0.0)
+   {
+   }
+
+   ossimSpot6DimapSupportData::~ossimSpot6DimapSupportData ()
+   {
+   }
+
+
+   void ossimSpot6DimapSupportData::clearFields()
+   {
+      clearErrorStatus();
+      theDIMAPVersion = OSSIM_Spot6_UNKNOWN;
+      theMetadataSubProfile = OSSIM_Spot6_METADATA_SUBPROFILE_UNKNOWN;
+      theProductIsOk = false;
+      theRpcIsOk = false;
+      theXmlDocumentRoot = "";
+      theImageID = "";
+      theSensorID="";
+      theProductionDate = "";
+      theAcquisitionDate = "";
+      theInstrument = "";
+      theInstrumentIndex = "";
+      theProcessingLevelString = "";
+      theSpectralProcessingString = "";
+
+      theSunAzimuth.clear();
+      theSunElevation.clear();
+      theIncidenceAngle.clear();
+      theViewingAngle.clear();
+      theAzimuthAngle.clear();
+
+      theImageSize.makeNan();
+      theTileSize.makeNan();
+      theNumberOfMegaTilesInRow = 0;
+      theNumberOfMegaTilesInCol = 0;
+      theNumberOfMegaTiles = 0;
+      ossimString msg = "";
+      theMultiDataFile.setBooleanValue(false, msg);
+
+      theNumBands = 0;
+      theBandOrder.clear();
+
+      thePhysicalBias.clear();
+      thePhysicalGain.clear();
+      theSolarIrradiance.clear();
+
+      //---
+      // Corner points:
+      //---
+      theUlCorner.makeNan();
+      theUrCorner.makeNan();
+      theLrCorner.makeNan();
+      theLlCorner.makeNan();
+
+      theRefGroundPoint.makeNan();
+      theRefImagePoint.makeNan();
+
+      //---
+      // RPC model parameters
+      //---
+      theErrBias = 0.0;
+      theErrBiasX = 0.0;
+      theErrBiasY = 0.0;
+      theErrRand = 0.0;
+      theLineOffset = 0;
+      theSampOffset = 0;
+      theLatOffset = 0.0;
+      theLonOffset = 0.0;
+      theHeightOffset = 0.0;
+      theLineScale = 0.0;
+      theSampScale = 0.0;
+      theLatScale = 0.0;
+      theLonScale = 0.0;
+      theHeightScale = 0.0;
+      theLineNumCoeff.clear();
+      theLineDenCoeff.clear();
+      theSampNumCoeff.clear();
+      theSampDenCoeff.clear();
+      theSpecId = "";
+   }
+
+   void ossimSpot6DimapSupportData::printInfo(ostream& os) const
+   {
+
+      os << "\n----------------- Info on Spot6 Image -------------------"
+         << "\n  "
+         << "\n  Job Number (ID):      " << theImageID
+         << "\n  Acquisition Date:     " << theAcquisitionDate
+         << "\n  Instrument:           " << theInstrument
+         << "\n  Instrument Index:     " << theInstrumentIndex
+         << "\n  Production Date:      " << theProductionDate
+         << "\n  Processing Level:     " << theProcessingLevelString
+         << "\n  Spectral Processing:  " << theSpectralProcessingString
+
+         << "\n  Number of Bands:      " << theNumBands
+         << "\n  Bands Display Order:  " << getVectorStringAsString(theBandOrder)
+
+         << "\n  Image Size:           " << theImageSize
+         << "\n  Tile Size:            " << theTileSize
+         << "\n  Number Of Tiles (Row, Col): " << theNumberOfMegaTiles << " ("
+         << theNumberOfMegaTilesInRow << ", "
+         << theNumberOfMegaTilesInCol << ")"
+
+         << "\n  Incidence Angle (TopCenter, Center, BottomCenter):   " << getVectorFloat64AsString(theIncidenceAngle)
+         << "\n  Viewing Angle (TopCenter, Center, BottomCenter):     " << getVectorFloat64AsString(theViewingAngle)
+         << "\n  Azimuth Angle (TopCenter, Center, BottomCenter):     " << getVectorFloat64AsString(theAzimuthAngle)
+         << "\n  Sun Azimuth (TopCenter, Center, BottomCenter):       " << getVectorFloat64AsString(theSunAzimuth)
+         << "\n  Sun Elevation (TopCenter, Center, BottomCenter):     " << getVectorFloat64AsString(theSunElevation)
+
+         << "\n  Physical Bias (for each band):     " << getVectorFloat64AsString(thePhysicalBias)
+         << "\n  Physical Gain (for each band):     " << getVectorFloat64AsString(thePhysicalGain)
+         << "\n  Solar Irradiance (for each band):  " << getVectorFloat64AsString(theSolarIrradiance)
+
+         << "\n  Geo Center Point:     " << theRefGroundPoint
+         // TODO add RefImagePoint if necessary
+
+         << "\n  Corner Points:"
+         << "\n     UL: " << theUlCorner
+         << "\n     UR: " << theUrCorner
+         << "\n     LR: " << theLrCorner
+         << "\n     LL: " << theLlCorner
+         << "\n"
+
+         << "\n  RPC model parameters:"
+         << "\n     RPC ID: " << theSpecId
+         << "\n     SampNumCoeff: " << getVectorDoubleAsString(theSampNumCoeff)
+         << "\n     SampDenCoeff: " << getVectorDoubleAsString(theSampDenCoeff)
+         << "\n     LineNumCoeff: " << getVectorDoubleAsString(theLineNumCoeff)
+         << "\n     LineDenCoeff: " << getVectorDoubleAsString(theLineDenCoeff)
+         << "\n     LonScale: " << theLonScale
+         << "\n     LonOffset: " << theLonOffset
+         << "\n     LatScale: " << theLatScale
+         << "\n     LonScale: " << theLonScale
+         << "\n     HeightScale: " << theHeightScale
+         << "\n     HeightOffset: " << theHeightOffset
+         << "\n     SampScale: " << theSampScale
+         << "\n     SampOffset: " << theSampOffset
+         << "\n     LineScale: " << theLineScale
+         << "\n     LineOffset: " << theLineOffset
+         << "\n     theErrBias: " << theErrBias
+         << "\n     theErrBiasX: " << theErrBiasX
+         << "\n     theErrBiasY: " << theErrBiasY
+         << "\n     theErrRand: " << theErrRand
+         << "\n"
+         << "\n---------------------------------------------------------"
+         << "\n  " << std::endl;
+   }
+
+   bool ossimSpot6DimapSupportData::parseXmlFile(const ossimFilename& file)
+   {
+      static const char MODULE[] = "ossimSpot6DimapSupportData::parseXmlFile";
+      //traceDebug.setTraceFlag(true);
+
+      if(traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " DEBUG:" << "\nFile: " << file << std::endl;
+      }
+
+      if (allMetadataRead())
+         clearFields();
+
+      //---
+      // Instantiate the file reading:
+      //---
+      ossim_int64 fileSize = file.fileSize();
+      std::ifstream in(file.c_str(), std::ios::binary|std::ios::in);
+      std::vector<char> fullBuffer;
+      ossimString bufferedIo;
+      if(in.good()&&(fileSize > 0))
+      {
+         char buf[100];
+         fullBuffer.resize(fileSize);
+         in.read(buf, std::min((ossim_int64)100, fileSize));
+         if(!in.fail())
+         {
+            ossimString testString = ossimString(buf,
+                                                 buf + in.gcount());
+            if(testString.contains("xml"))
+            {
+               in.seekg(0);
+               in.read(&fullBuffer.front(), (std::streamsize)fullBuffer.size());
+               if(!in.fail())
+               {
+                  bufferedIo = ossimString(fullBuffer.begin(),
+                                           fullBuffer.begin()+in.gcount());
+               }
+            }
+         }
+      }
+      else
+      {
+         return false;
+      }
+      //---
+      // Instantiate the XML parser:
+      //---
+      ossimRefPtr<ossimXmlDocument> xmlDocument;
+
+      if(bufferedIo.empty())
+      {
+         xmlDocument = new ossimXmlDocument(file);
+      }
+      else
+      {
+         xmlDocument = new ossimXmlDocument;
+         std::istringstream inStringStream(bufferedIo.string());
+         if(!xmlDocument->read(inStringStream))
+         {
+            return false;
+         }
+      }
+      if (xmlDocument->getErrorStatus())
+      {
+         if(traceDebug())
+         {
+            ossimNotify(ossimNotifyLevel_FATAL)
+               << MODULE << " DEBUG:" << "ossimSpot6DimapSupportData::parseXmlFile:"
+               << "\nUnable to parse xml file" << std::endl;
+         }
+         setErrorStatus();
+         return false;
+      }
+
+      if (!parseMetadataIdentificationDIMAPv2(xmlDocument) )
+      {
+         if (traceDebug())
+         {
+            ossimNotify(ossimNotifyLevel_FATAL)
+               << MODULE << " DEBUG:" << "ossimSpot6DimapSupportData::parseXmlFile:"
+               << "\nparseMetadataIdentification failed.  Returning false"
+               << std::endl;
+         }
+         return false;
+      }
+
+
+      if (theMetadataSubProfile == OSSIM_Spot6_METADATA_SUBPROFILE_PRODUCT)
+      {
+         if (theProductIsOk)
+            clearFields();
+
+         if (!parseDatasetIdentification(xmlDocument))
+         {
+            if (traceDebug())
+            {
+               ossimNotify(ossimNotifyLevel_FATAL)
+                  << MODULE << " DEBUG:" << "ossimSpot6DimapSupportData::parseXmlFile:"
+                  << "\nparseDatasetdentification failed.  Returning false" << std::endl;
+            }
+            return false;
+         }
+
+         if (!parseDatasetContent(xmlDocument))
+         {
+            ossimNotify(ossimNotifyLevel_FATAL)
+               << MODULE << " DEBUG:" << "ossimSpot6DimapSupportData::parseXmlFile:"
+               << "\nparseDatasetContent failed.  Returning false" << std::endl;
+            return false;
+         }
+
+         if (!parseProductInformation(xmlDocument))
+         {
+            if (traceDebug())
+            {
+               ossimNotify(ossimNotifyLevel_FATAL)
+                  << MODULE << " DEBUG:" << "ossimSpot6DimapSupportData::parseXmlFile:"
+                  << "\nparseProductInformation failed.  Returning false" << std::endl;
+            }
+            return false;
+         }
+
+         if (!parseCoordinateReferenceSystem(xmlDocument))
+         {
+            if (traceDebug())
+            {
+               ossimNotify(ossimNotifyLevel_FATAL)
+                  << MODULE << " DEBUG:" << "ossimSpot6DimapSupportData::parseXmlFile:"
+                  << "\nparseCoordinateReferenceSystem failed.  Returning false" << std::endl;
+            }
+            return false;
+         }
+
+         if (!parseGeoposition(xmlDocument))
+         {
+            if (traceDebug())
+            {
+               ossimNotify(ossimNotifyLevel_FATAL)
+                  << MODULE << " DEBUG:" << "ossimSpot6DimapSupportData::parseXmlFile:"
+                  << "\nparseGeoposition failed.  Returning false" << std::endl;
+            }
+            return false;
+         }
+
+         if (!parseProcessingInformation(xmlDocument))
+         {
+            if (traceDebug())
+            {
+               ossimNotify(ossimNotifyLevel_FATAL)
+                  << MODULE << " DEBUG:" << "ossimSpot6DimapSupportData::parseXmlFile:"
+                  << "\nparseProcessingInformation failed.  Returning false" << std::endl;
+            }
+            return false;
+         }
+
+         if (!parseRasterData(xmlDocument))
+         {
+            if (traceDebug())
+            {
+               ossimNotify(ossimNotifyLevel_FATAL)
+                  << MODULE << " DEBUG:" << "ossimSpot6DimapSupportData::parseXmlFile:"
+                  << "\nparseRasterData failed.  Returning false" << std::endl;
+            }
+            return false;
+         }
+
+         if (!parseRadiometricData(xmlDocument))
+         {
+            ossimNotify(ossimNotifyLevel_FATAL)
+               << MODULE << " DEBUG:" << "ossimSpot6DimapSupportData::parseXmlFile:"
+               << "\nparseRadiometricData failed.  Returning false" << std::endl;
+            return false;
+         }
+
+         if (!parseGeometricData(xmlDocument))
+         {
+            ossimNotify(ossimNotifyLevel_FATAL)
+               << MODULE << " DEBUG:" << "ossimSpot6DimapSupportData::parseXmlFile:"
+               << "\nparseGeometricData failed.  Returning false" << std::endl;
+            return false;
+         }
+
+         if (!parseQualityAssessment(xmlDocument))
+         {
+            ossimNotify(ossimNotifyLevel_FATAL)
+               << MODULE << " DEBUG:" << "ossimSpot6DimapSupportData::parseXmlFile:"
+               << "\nparseQualityAssessment failed.  Returning false" << std::endl;
+            return false;
+         }
+
+         if (!parseDatasetSources(xmlDocument))
+         {
+            ossimNotify(ossimNotifyLevel_FATAL)
+               << MODULE << " DEBUG:" << "ossimSpot6DimapSupportData::parseXmlFile:"
+               << "\nparseDatasetSources failed.  Returning false" << std::endl;
+            return false;
+         }
+
+         theProductIsOk = true;
+      }
+
+      if (theMetadataSubProfile == OSSIM_Spot6_METADATA_SUBPROFILE_RPC)
+      {
+         // Parse RPC file
+         if (theProcessingLevelString == "SENSOR")
+         {
+            if (parseRPCMetadata(xmlDocument) == false)
+            {
+               ossimNotify(ossimNotifyLevel_FATAL)
+                  << MODULE << " DEBUG:" << "ossimSpot6DimapSupportData::parseXmlFile:"
+                  << "\nparseRPCMetadata initialization failed.  Returning false" << std::endl;
+               return false;
+            }
+            theRpcIsOk = true;
+         }
+         else
+            theRpcIsOk = true;
+      }
+
+      if (theProcessingLevelString != "SENSOR")
+         theRpcIsOk = true;
+
+      if (traceDebug() && allMetadataRead())
+      {
+         printInfo(ossimNotify(ossimNotifyLevel_DEBUG));
+         ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " DEBUG: exited..." << std::endl;
+      }
+
+      return true;
+   }
+
+   ossimString ossimSpot6DimapSupportData::getProcessingLevel() const
+   {
+      return theProcessingLevelString;
+   }
+
+   ossimString ossimSpot6DimapSupportData::getSensorID() const
+   {
+      return theSensorID;
+   }
+
+   ossimString ossimSpot6DimapSupportData::getAcquisitionDate() const
+   {
+      return theAcquisitionDate;
+   }
+
+   ossimString ossimSpot6DimapSupportData::getProductionDate() const
+   {
+      return theProductionDate;
+   }
+
+   ossimString ossimSpot6DimapSupportData::getImageID() const
+   {
+      return theImageID;
+   }
+
+   ossimString ossimSpot6DimapSupportData::getInstrument() const
+   {
+      return theInstrument;
+   }
+
+   ossimString ossimSpot6DimapSupportData::getInstrumentIndex() const
+   {
+      return theInstrumentIndex;
+   }
+
+   void ossimSpot6DimapSupportData::getSunAzimuth(std::vector<ossim_float64>& az) const
+   {
+      az = theSunAzimuth;
+   }
+
+   void ossimSpot6DimapSupportData::getSunElevation(std::vector<ossim_float64>& el) const
+   {
+      el = theSunElevation;
+   }
+
+   void ossimSpot6DimapSupportData::getImageSize(ossimIpt& sz) const
+   {
+      sz = theImageSize;
+   }
+
+   ossim_uint32 ossimSpot6DimapSupportData::getNumberOfBands() const
+   {
+      return theNumBands;
+   }
+
+   void ossimSpot6DimapSupportData::getIncidenceAngle(std::vector<ossim_float64>& ia) const
+   {
+      ia = theIncidenceAngle;
+   }
+
+   void ossimSpot6DimapSupportData::getViewingAngle(std::vector<ossim_float64>& va) const
+   {
+      va = theViewingAngle;
+   }
+
+   void ossimSpot6DimapSupportData::getRefGroundPoint(ossimGpt& gp) const
+   {
+      gp = theRefGroundPoint;
+   }
+
+   void ossimSpot6DimapSupportData::getRefImagePoint(ossimDpt& rp) const
+   {
+      rp = theRefImagePoint;
+   }
+
+   void ossimSpot6DimapSupportData::getUlCorner(ossimGpt& pt) const
+   {
+      pt = theUlCorner;
+   }
+
+   void ossimSpot6DimapSupportData::getUrCorner(ossimGpt& pt) const
+   {
+      pt = theUrCorner;
+   }
+
+   void ossimSpot6DimapSupportData::getLrCorner(ossimGpt& pt) const
+   {
+      pt = theLrCorner;
+   }
+
+   void ossimSpot6DimapSupportData::getLlCorner(ossimGpt& pt) const
+   {
+      pt = theLlCorner;
+   }
+
+   void ossimSpot6DimapSupportData::getImageRect(ossimDrect& rect)const
+   {
+      rect = ossimDrect(0.0, 0.0, theImageSize.x-1.0, theImageSize.y-1.0);
+   }
+
+
+   bool ossimSpot6DimapSupportData::saveState(ossimKeywordlist& kwl,
+                                                 const char* prefix)const
+   {
+      ossimString tempString;
+      ossim_uint32 idx = 0;
+
+      kwl.add(prefix,
+              ossimKeywordNames::TYPE_KW,
+              "ossimSpot6DimapSupportData",
+              true);
+
+      tempString = "";
+      for(idx = 0; idx < theSunAzimuth.size(); ++idx)
+      {
+         tempString += (ossimString::toString(theSunAzimuth[idx]) + " ");
+      }
+
+      kwl.add(prefix,
+              ossimKeywordNames::AZIMUTH_ANGLE_KW,
+              tempString,
+              true);
+
+      kwl.add(prefix,
+              "number_of_azimuth_angle",
+              static_cast<ossim_uint32>(theSunAzimuth.size()),
+              true);
+
+      tempString = "";
+      for(idx = 0; idx <  theSunElevation.size(); ++idx)
+      {
+         tempString += (ossimString::toString(theSunElevation[idx]) + " ");
+      }
+
+      kwl.add(prefix,
+              ossimKeywordNames::ELEVATION_ANGLE_KW,
+              tempString,
+              true);
+
+      kwl.add(prefix,
+              "number_of_elevation_angle",
+              static_cast<ossim_uint32>(theSunElevation.size()),
+              true);
+
+      //---
+      // Note: since this is a new keyword, use the point.toString as there is
+      // no backwards compatibility issues.
+      //---
+
+      kwl.add(prefix,
+              "image_size",
+              ossimString::toString(theImageSize.x) + " " +
+              ossimString::toString(theImageSize.y),
+              true);
+
+      kwl.add(prefix,
+              "reference_ground_point",
+              ossimString::toString(theRefGroundPoint.latd()) + " " +
+              ossimString::toString(theRefGroundPoint.lond()) + " " +
+              ossimString::toString(theRefGroundPoint.height()) + " " +
+              theRefGroundPoint.datum()->code(),
+              true);
+
+      kwl.add(prefix,
+              "reference_image_point",
+              ossimString::toString(theRefImagePoint.x) + " " +
+              ossimString::toString(theRefImagePoint.y),
+              true);
+
+      kwl.add(prefix,
+              ossimKeywordNames::NUMBER_BANDS_KW,
+              theNumBands,
+              true);
+
+      tempString = "";
+      for(idx = 0; idx <  theBandOrder.size(); ++idx)
+      {
+         tempString += (theBandOrder[idx] + " ");
+      }
+
+      kwl.add(prefix,
+              "band_name_list",
+              tempString,
+              true);
+
+      kwl.add(prefix,
+              "image_id",
+              theImageID,
+              true);
+
+      kwl.add(prefix,
+              "processing_level",
+              theProcessingLevelString,
+              true);
+
+      kwl.add(prefix,
+              "instrument",
+              theInstrument,
+              true);
+
+      kwl.add(prefix,
+              "instrument_index",
+              theInstrumentIndex,
+              true);
+
+      kwl.add(prefix,
+              ossimKeywordNames::IMAGE_DATE_KW,
+              theAcquisitionDate,
+              true);
+
+      kwl.add(prefix,
+              "production_date",
+              theProductionDate,
+              true);
+
+      tempString = "";
+      for(idx = 0; idx <  theIncidenceAngle.size(); ++idx)
+      {
+         tempString += (ossimString::toString(theIncidenceAngle[idx]) + " ");
+      }
+
+      kwl.add(prefix,
+              "incident_angle",
+              tempString,
+              true);
+
+      kwl.add(prefix,
+              "number_of_incident_angle",
+              static_cast<ossim_uint32>(theIncidenceAngle.size()),
+              true);
+
+      tempString = "";
+      for(idx = 0; idx <  theViewingAngle.size(); ++idx)
+      {
+         tempString += (ossimString::toString(theViewingAngle[idx]) + " ");
+      }
+
+      kwl.add(prefix,
+              "viewing_angle",
+              tempString,
+              true);
+
+      kwl.add(prefix,
+              "number_of_viewing_angle",
+              static_cast<ossim_uint32>(theViewingAngle.size()),
+              true);
+
+      tempString = "";
+      for(idx = 0; idx <  theAzimuthAngle.size(); ++idx)
+      {
+         tempString += (ossimString::toString(theAzimuthAngle[idx]) + " ");
+      }
+
+      kwl.add(prefix,
+              "scene_orientation",
+              tempString,
+              true);
+
+      kwl.add(prefix,
+              "number_of_scene_orientation",
+              static_cast<ossim_uint32>(theAzimuthAngle.size()),
+              true);
+
+      kwl.add(prefix,
+              "ul_ground_point",
+              ossimString::toString(theUlCorner.latd()) + " " +
+              ossimString::toString(theUlCorner.lond()) + " " +
+              ossimString::toString(theUlCorner.height()) + " " +
+              theUlCorner.datum()->code(),
+              true);
+
+      kwl.add(prefix,
+              "ur_ground_point",
+              ossimString::toString(theUrCorner.latd()) + " " +
+              ossimString::toString(theUrCorner.lond()) + " " +
+              ossimString::toString(theUrCorner.height()) + " " +
+              theUrCorner.datum()->code(),
+              true);
+
+      kwl.add(prefix,
+              "lr_ground_point",
+              ossimString::toString(theLrCorner.latd()) + " " +
+              ossimString::toString(theLrCorner.lond()) + " " +
+              ossimString::toString(theLrCorner.height()) + " " +
+              theLrCorner.datum()->code(),
+              true);
+
+      kwl.add(prefix,
+              "ll_ground_point",
+              ossimString::toString(theLlCorner.latd()) + " " +
+              ossimString::toString(theLlCorner.lond()) + " " +
+              ossimString::toString(theLlCorner.height()) + " " +
+              theLlCorner.datum()->code(),
+              true);
+
+      kwl.add(prefix,
+              "sensorID",
+              theSensorID,
+              true);
+
+
+      tempString = "";
+      for(idx = 0; idx < thePhysicalBias.size(); ++idx)
+      {
+         tempString += (ossimString::toString(thePhysicalBias[idx]) + " ");
+      }
+      kwl.add(prefix,
+              "physical_bias",
+              tempString,
+              true);
+
+      tempString = "";
+      for(idx = 0; idx < thePhysicalGain.size(); ++idx)
+      {
+         tempString += (ossimString::toString(thePhysicalGain[idx]) + " ");
+      }
+      kwl.add(prefix,
+              "physical_gain",
+              tempString,
+              true);
+
+      tempString = "";
+      for(idx = 0; idx < theSolarIrradiance.size(); ++idx)
+      {
+         tempString += (ossimString::toString(theSolarIrradiance[idx]) + " ");
+      }
+
+      kwl.add(prefix,
+              "solar_irradiance",
+              tempString,
+              true);
+
+      return true;
+   }
+
+   bool ossimSpot6DimapSupportData::loadState(const ossimKeywordlist& kwl,
+                                                 const char* prefix)
+   {
+      ossim_uint32 idx = 0;
+      ossim_uint32 total;
+      ossimString tempString;
+
+      clearFields();
+
+
+      ossimString type = kwl.find(prefix, ossimKeywordNames::TYPE_KW);
+
+      if(type != "ossimSpot6DimapSupportData")
+      {
+         return false;
+      }
+
+      total =  ossimString(kwl.find(prefix,"number_of_azimuth_angle")).toUInt32();
+      theSunAzimuth.resize(total);
+      tempString = kwl.find(prefix,ossimKeywordNames::AZIMUTH_ANGLE_KW);
+      if(tempString != "")
+      {
+         std::istringstream in(tempString.string());
+         ossimString tempValue;
+         for(idx = 0; idx < theSunAzimuth.size();++idx)
+         {
+            in >> tempValue.string();
+            theSunAzimuth[idx] = tempValue.toDouble();
+         }
+      }
+
+      total =  ossimString(kwl.find(prefix,"number_of_elevation_angle")).toUInt32();
+      theSunElevation.resize(total);
+      tempString = kwl.find(prefix,ossimKeywordNames::ELEVATION_ANGLE_KW);
+      if(tempString != "")
+      {
+         std::istringstream in(tempString.string());
+         ossimString tempValue;
+         for(idx = 0; idx < theSunElevation.size();++idx)
+         {
+            in >> tempValue.string();
+            theSunElevation[idx] = tempValue.toDouble();
+         }
+      }
+
+      theImageSize      = createIpt(kwl.find(prefix, "image_size"));
+      theRefGroundPoint = createGround(kwl.find(prefix, "reference_ground_point"));
+      theRefImagePoint  = createDpt(kwl.find(prefix, "reference_image_point"));
+
+      theNumBands        = ossimString(kwl.find(prefix, ossimKeywordNames::NUMBER_BANDS_KW)).toUInt32();
+
+      theBandOrder.resize(theNumBands);
+      tempString = kwl.find(prefix,"band_name_list");
+      if(tempString != "")
+      {
+         std::istringstream in(tempString.string());
+         ossimString tempValue;
+         for(idx = 0; idx < theBandOrder.size();++idx)
+         {
+            in >> tempValue.string();
+            theBandOrder[idx] = tempValue;
+         }
+      }
+
+      theAcquisitionDate = kwl.find(prefix, ossimKeywordNames::IMAGE_DATE_KW);
+      theProductionDate  = kwl.find(prefix, "production_date");
+      theImageID         = kwl.find(prefix, "image_id");
+      theInstrument      = kwl.find(prefix, "instrument");
+      theInstrumentIndex = kwl.find(prefix, "instrument_index");
+   
+      total =  ossimString(kwl.find(prefix,"number_of_incident_angle")).toUInt32();
+      theIncidenceAngle.resize(total);
+      tempString = kwl.find(prefix,"incident_angle");
+      if(tempString != "")
+      {
+         std::istringstream in(tempString.string());
+         ossimString tempValue;
+         for(idx = 0; idx < theIncidenceAngle.size();++idx)
+         {
+            in >> tempValue.string();
+            theIncidenceAngle[idx] = tempValue.toDouble();
+         }
+      }
+
+      total =  ossimString(kwl.find(prefix,"number_of_viewing_angle")).toUInt32();
+      theViewingAngle.resize(total);
+      tempString = kwl.find(prefix,"viewing_angle");
+      if(tempString != "")
+      {
+         std::istringstream in(tempString.string());
+         ossimString tempValue;
+         for(idx = 0; idx < theViewingAngle.size();++idx)
+         {
+            in >> tempValue.string();
+            theViewingAngle[idx] = tempValue.toDouble();
+         }
+      }
+
+      total =  ossimString(kwl.find(prefix,"number_of_scene_orientation")).toUInt32();
+      theAzimuthAngle.resize(total);
+      tempString = kwl.find(prefix,"scene_orientation");
+      if(tempString != "")
+      {
+         std::istringstream in(tempString.string());
+         ossimString tempValue;
+         for(idx = 0; idx < theAzimuthAngle.size();++idx)
+         {
+            in >> tempValue.string();
+            theAzimuthAngle[idx] = tempValue.toDouble();
+         }
+      }
+
+
+      theUlCorner =createGround( kwl.find(prefix, "ul_ground_point"));
+      theUrCorner =createGround( kwl.find(prefix, "ur_ground_point"));
+      theLrCorner =createGround( kwl.find(prefix, "lr_ground_point"));
+      theLlCorner =createGround( kwl.find(prefix, "ll_ground_point"));
+
+      theSensorID = ossimString(kwl.find(prefix, "sensorID"));
+
+      theProcessingLevelString = ossimString(kwl.find(prefix, "processing_level"));
+
+      thePhysicalBias.resize(theNumBands);
+      tempString = kwl.find(prefix,"physical_bias");
+      if(tempString != "")
+      {
+         std::istringstream in(tempString.string());
+         ossimString tempValue;
+         for(idx = 0; idx < thePhysicalBias.size();++idx)
+         {
+            in >> tempValue.string();
+            thePhysicalBias[idx] = tempValue.toDouble();
+         }
+      }
+
+      thePhysicalGain.resize(theNumBands);
+      tempString = kwl.find(prefix,"physical_gain");
+      if(tempString != "")
+      {
+         std::istringstream in(tempString.string());
+         ossimString tempValue;
+         for(idx = 0; idx < thePhysicalGain.size();++idx)
+         {
+            in >> tempValue.string();
+            thePhysicalGain[idx] = tempValue.toDouble();
+         }
+      }
+
+      theSolarIrradiance.resize(theNumBands);
+      tempString = kwl.find(prefix,"solar_irradiance");
+      if(tempString != "")
+      {
+         std::istringstream in(tempString.string());
+         ossimString tempValue;
+         for(idx = 0; idx < theSolarIrradiance.size();++idx)
+         {
+            in >> tempValue.string();
+            theSolarIrradiance[idx] = tempValue.toDouble();
+         }
+      }
+
+      return true;
+   }
+
+   ossimGpt ossimSpot6DimapSupportData::createGround(const ossimString& s)const
+   {
+      std::istringstream in(s.string());
+      ossimString lat, lon, height;
+      ossimString code;
+
+      in >> lat.string() >> lon.string() >> height.string() >> code.string();
+
+      return ossimGpt(lat.toDouble(),
+                      lon.toDouble(),
+                      height.toDouble(),
+                      ossimDatumFactory::instance()->create(code));
+
+   }
+
+   ossimDpt ossimSpot6DimapSupportData::createDpt(const ossimString& s)const
+   {
+      std::istringstream in(s.string());
+      ossimString x, y;
+      ossimString code;
+
+      in >> x.string() >> y.string();
+
+      return ossimDpt(x.toDouble(), y.toDouble());
+
+   }
+
+   ossimIpt ossimSpot6DimapSupportData::createIpt(const ossimString& s)const
+   {
+      std::istringstream in(s.string());
+      ossimString x, y;
+      ossimString code;
+
+      in >> x.string() >> y.string();
+
+      return ossimIpt(x.toInt(), y.toInt());
+
+   }
+
+   bool ossimSpot6DimapSupportData::parseProductInformation(
+      ossimRefPtr<ossimXmlDocument> xmlDocument)
+   {
+      ossimString xpath;
+      vector<ossimRefPtr<ossimXmlNode> > xml_nodes;
+
+      //---
+      // Fetch the Image ID:
+      //---
+      xpath = "/Product_Information/Delivery_Identification/JOB_ID";  //DIMAPv2
+      xpath = theXmlDocumentRoot + xpath;
+      if (!readOneXmlNode(xmlDocument, xpath, theImageID))
+      {
+         return false;
+      }
+
+      //---
+      // Fetch the ProductionDate:
+      //---
+      xpath = "/Product_Information/Delivery_Identification/PRODUCTION_DATE"; //DIMAPv2
+      xpath = theXmlDocumentRoot + xpath;
+      if (!readOneXmlNode(xmlDocument, xpath, theProductionDate))
+      {
+         return false;
+      }
+
+      return true;
+   }
+
+   bool ossimSpot6DimapSupportData::parseDatasetContent(
+      ossimRefPtr<ossimXmlDocument> xmlDocument)
+   {
+      ossimString xpath, nodeValue;
+      vector<ossimRefPtr<ossimXmlNode> > xml_nodes;
+
+      //---
+      // Corner points:
+      //---
+      xml_nodes.clear();
+      xpath = "/Dataset_Content/Dataset_Extent/Vertex";
+      xpath = theXmlDocumentRoot + xpath;
+      xmlDocument->findNodes(xpath, xml_nodes);
+      if (xml_nodes.size() != 4)
+      {
+         setErrorStatus();
+         return false;
+      }
+      std::vector<ossimRefPtr<ossimXmlNode> >::iterator node = xml_nodes.begin();
+      while (node != xml_nodes.end())
+      {
+         ossimGpt gpt;
+         ossimDpt ipt;
+
+         std::vector<ossimRefPtr<ossimXmlNode> > sub_nodes;
+         xpath = "LAT";
+         (*node)->findChildNodes(xpath, sub_nodes);
+         if (sub_nodes.size() == 0)
+         {
+            setErrorStatus();
+            return false;
+         }
+         gpt.lat = sub_nodes[0]->getText().toDouble();
+
+         sub_nodes.clear();
+         xpath = "LON";
+         (*node)->findChildNodes(xpath, sub_nodes);
+         if (sub_nodes.size() == 0)
+         {
+            setErrorStatus();
+            return false;
+         }
+         gpt.lon = sub_nodes[0]->getText().toDouble();
+         gpt.hgt = 0.0; // assumed
+
+         sub_nodes.clear();
+         xpath = "ROW";
+         (*node)->findChildNodes(xpath, sub_nodes);
+         if (sub_nodes.size() == 0)
+         {
+            setErrorStatus();
+            return false;
+         }
+         ipt.line = sub_nodes[0]->getText().toDouble() - 1.0;
+
+         sub_nodes.clear();
+         xpath = "COL";
+         (*node)->findChildNodes(xpath, sub_nodes);
+         if (sub_nodes.size() == 0)
+         {
+            setErrorStatus();
+            return false;
+         }
+         ipt.samp = sub_nodes[0]->getText().toDouble() - 1.0;
+
+         if (ipt.line < 1.0)
+            if (ipt.samp < 1.0)
+               theUlCorner = gpt;
+            else
+               theUrCorner = gpt;
+         else
+            if (ipt.samp < 1.0)
+               theLlCorner = gpt;
+            else
+               theLrCorner = gpt;
+
+         ++node;
+      }
+
+
+
+      //---
+      // Center of frame.
+      //---
+      theRefGroundPoint.hgt = 0.0; // TODO needs to be looked up
+
+      if (!readOneXmlNode(xmlDocument,
+                             theXmlDocumentRoot + "/Dataset_Content/Dataset_Extent/Center/LON", // DIMAPv2
+                             nodeValue))
+      {
+            return false;
+      }
+      theRefGroundPoint.lon = nodeValue.toDouble();
+
+      if (!readOneXmlNode(xmlDocument, theXmlDocumentRoot + "/Dataset_Content/Dataset_Extent/Center/LAT", nodeValue)) // DIMAPv2
+         {
+            return false;
+         }
+      theRefGroundPoint.lat = nodeValue.toDouble();
+
+      return true;
+   }
+
+   bool ossimSpot6DimapSupportData::parseRadiometricData(
+      ossimRefPtr<ossimXmlDocument> xmlDocument)
+   {
+      ossimString xpath;
+      std::vector<ossimRefPtr<ossimXmlNode> > xml_nodes;
+      std::vector<ossimRefPtr<ossimXmlNode> > sub_nodes;
+      std::vector<ossimRefPtr<ossimXmlNode> >::iterator node;
+
+      //---
+      // Fetch the gain and bias for each spectral band:
+      //---
+      thePhysicalGain.assign(theNumBands, 1.000);
+      thePhysicalBias.assign(theNumBands, 0.000);
+
+      xml_nodes.clear();
+      xpath = "/Radiometric_Data/Radiometric_Calibration/Instrument_Calibration/Band_Measurement_List/Band_Radiance";  //DIMAPv2
+      xpath = theXmlDocumentRoot + xpath;
+      xmlDocument->findNodes(xpath, xml_nodes);
+
+      node = xml_nodes.begin();
+      while (node != xml_nodes.end())
+      {
+         sub_nodes.clear();
+         xpath = "BAND_ID";
+         (*node)->findChildNodes(xpath, sub_nodes);
+         if (sub_nodes.size() == 0)
+         {
+            setErrorStatus();
+            return false;
+         }
+
+         ossimString bandName = sub_nodes[0]->getText();
+         ossim_uint32 bandIndex = 0;
+         if ( (theNumBands == 1) || (bandName == "B0") || (bandName == "P") )
+         {
+            bandIndex = 0;
+         }
+         else if (bandName == "B1")
+         { 
+            bandIndex = 1;
+         }
+         else if (bandName == "B2")
+         {
+            bandIndex = 2;
+         }
+         else if (bandName == "B3")
+         {
+            bandIndex = 3;
+         }
+         else
+         {
+            ossimNotify(ossimNotifyLevel_WARN)
+               << "ossimSpot6DimapSupportData::parseRadiometricMetadata ERROR: Band ID is incorrect\n";
+         }
+         
+         if ((bandIndex >= theNumBands ) )
+         {
+            ossimNotify(ossimNotifyLevel_WARN)
+               << "ossimSpot6DimapSupportData::parseRadiometricMetadata ERROR: Band index outside of range\n";
+            return false;
+         }
+
+         sub_nodes.clear();
+	 xpath = "BIAS"; //DIMAPv2
+         (*node)->findChildNodes(xpath, sub_nodes);
+         if (sub_nodes.size() == 0)
+         {
+            setErrorStatus();
+            return false;
+         }
+         thePhysicalBias[bandIndex] = sub_nodes[0]->getText().toDouble();
+
+         sub_nodes.clear();
+	 xpath = "GAIN"; //DIMAPv2
+         (*node)->findChildNodes(xpath, sub_nodes);
+         if (sub_nodes.size() == 0)
+         {
+            setErrorStatus();
+            return false;
+         }
+         thePhysicalGain[bandIndex] = sub_nodes[0]->getText().toDouble();
+
+         ++node;
+      }
+
+      // Initialize to 999 : we find this value in some DIMAPv2 file
+      // and there is no such tag in DIMAPv1 file
+      theSolarIrradiance.assign(theNumBands, 999.000);
+
+      xml_nodes.clear();
+      xpath = "/Radiometric_Data/Radiometric_Calibration/Instrument_Calibration/Band_Measurement_List/Band_Solar_Irradiance";
+      xpath = theXmlDocumentRoot + xpath;
+      xmlDocument->findNodes(xpath, xml_nodes);
+
+      node = xml_nodes.begin();
+      while (node != xml_nodes.end())
+      {
+         sub_nodes.clear();
+         xpath = "BAND_ID";
+         (*node)->findChildNodes(xpath, sub_nodes);
+         if (sub_nodes.size() == 0)
+         {
+            setErrorStatus();
+            return false;
+         }
+
+         ossimString bandName = sub_nodes[0]->getText();
+         ossim_uint32 bandIndex = 0;
+         if ( (theNumBands == 1) || (bandName == "B0") || (bandName == "P") )
+         {
+            bandIndex = 0;
+         }
+         else if (bandName == "B1")
+         {
+            bandIndex = 1;
+         }
+         else if (bandName == "B2")
+         {
+            bandIndex = 2;
+         }
+         else if (bandName == "B3")
+         {
+            bandIndex = 3;
+         }
+         else
+         {
+            ossimNotify(ossimNotifyLevel_WARN)
+               << "ossimSpot6DimapSupportData::parseRadiometricMetadata ERROR: Band ID is incorrect\n";
+         }
+         
+         if ((bandIndex >= theNumBands))
+         {
+            ossimNotify(ossimNotifyLevel_WARN)
+               << "ossimSpot6DimapSupportData::parseRadiometricMetadata ERROR: Band index outside of range 2\n";
+            return false;
+         }
+
+         sub_nodes.clear();
+         xpath = "VALUE";
+         (*node)->findChildNodes(xpath, sub_nodes);
+         if (sub_nodes.size() == 0)
+         {
+            setErrorStatus();
+            return false;
+         }
+         theSolarIrradiance[bandIndex] = sub_nodes[0]->getText().toDouble();
+
+         ++node;
+      }
+
+      return true;
+   }
+
+
+   bool ossimSpot6DimapSupportData::parseRPCMetadata(
+      ossimRefPtr<ossimXmlDocument> xmlDocument)
+   {
+      static const char MODULE[] = "ossimSpot6DimapSupportData::parseRPCMetadata";
+      ossimString xpath, nodeValue;
+      vector<ossimRefPtr<ossimXmlNode> > xml_nodes;
+
+      //---
+      // Fetch the Global RFM - Direct Model - Bias:
+      //---
+      xpath = "/Rational_Function_Model/Resource_Reference/RESOURCE_ID"; //DIMAPv2
+      xpath = theXmlDocumentRoot + xpath;
+      if (!readOneXmlNode(xmlDocument, xpath, nodeValue))
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " DEBUG: Could not find: " << xpath << std::endl;
+         return false;
+      }
+      theSpecId = nodeValue;
+
+      //---
+      // Fetch the Global RFM - Inverse Model:
+      //---
+      xml_nodes.clear();
+      xpath = "/Rational_Function_Model/Global_RFM/Inverse_Model"; //DIMAPv2
+      xpath = theXmlDocumentRoot + xpath;
+      xmlDocument->findNodes(xpath, xml_nodes);
+      if (xml_nodes.empty())
+      {
+        setErrorStatus();
+        if(traceDebug())
+        {
+           ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " DEBUG: Could not find: " << xpath << std::endl;
+        }
+        return false;
+      }
+
+      for (ossim_uint32 it = 1; it < 21; it ++)
+        {
+           std::ostringstream valueStr;
+           valueStr << it;
+
+           xml_nodes.clear();
+           xpath = "/Rational_Function_Model/Global_RFM/Inverse_Model/LINE_NUM_COEFF_"; //DIMAPv2
+           xpath = theXmlDocumentRoot + xpath;
+           xpath = xpath + valueStr.str();
+           xmlDocument->findNodes(xpath, xml_nodes);
+           if (xml_nodes.size() == 0)
+           {
+              setErrorStatus();
+              if(traceDebug())
+              {
+                 ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " DEBUG:" << "\nCould not find: " << xpath << std::endl;
+              }
+              return false;
+           }
+           theLineNumCoeff.push_back(xml_nodes[0]->getText().toDouble());
+
+           xml_nodes.clear();
+           xpath = "/Rational_Function_Model/Global_RFM/Inverse_Model/LINE_DEN_COEFF_"; //DIMAPv2
+           xpath = theXmlDocumentRoot + xpath;
+           xpath = xpath + valueStr.str();
+           xmlDocument->findNodes(xpath, xml_nodes);
+           if (xml_nodes.size() == 0)
+           {
+              setErrorStatus();
+              if(traceDebug())
+              {
+                 ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " DEBUG:" << "\nCould not find: " << xpath << std::endl;
+              }
+              return false;
+           }
+           theLineDenCoeff.push_back(xml_nodes[0]->getText().toDouble());
+
+           xml_nodes.clear();
+           xpath = "/Rational_Function_Model/Global_RFM/Inverse_Model/SAMP_NUM_COEFF_"; //DIMAPv2
+           xpath = theXmlDocumentRoot + xpath;
+           xpath = xpath + valueStr.str();
+           xmlDocument->findNodes(xpath, xml_nodes);
+           if (xml_nodes.size() == 0)
+           {
+              setErrorStatus();
+              if(traceDebug())
+              {
+                 ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " DEBUG:" << "\nCould not find: " << xpath << std::endl;
+              }
+              return false;
+           }
+           theSampNumCoeff.push_back(xml_nodes[0]->getText().toDouble());
+
+           xml_nodes.clear();
+           xpath = "/Rational_Function_Model/Global_RFM/Inverse_Model/SAMP_DEN_COEFF_"; //DIMAPv2
+           xpath = theXmlDocumentRoot + xpath;
+           xpath = xpath + valueStr.str();
+           xmlDocument->findNodes(xpath, xml_nodes);
+           if (xml_nodes.size() == 0)
+           {
+              setErrorStatus();
+              if(traceDebug())
+              {
+                 ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " DEBUG:" << "\nCould not find: " << xpath << std::endl;
+              }
+              return false;
+           }
+           theSampDenCoeff.push_back(xml_nodes[0]->getText().toDouble());
+        }
+
+
+      //---
+      // Fetch the Global RFM - Inverse Model - Bias:
+      //---
+      xpath = "/Rational_Function_Model/Global_RFM/Inverse_Model/ERR_BIAS_ROW"; //DIMAPv2
+      xpath = theXmlDocumentRoot + xpath;
+      if (!readOneXmlNode(xmlDocument, xpath, nodeValue))
+      {
+         return false;
+      }
+      theErrBiasX = nodeValue.toDouble();
+      xpath = "/Rational_Function_Model/Global_RFM/Inverse_Model/ERR_BIAS_COL"; //DIMAPv2
+      xpath = theXmlDocumentRoot + xpath;
+      if (!readOneXmlNode(xmlDocument, xpath, nodeValue))
+      {
+         return false;
+      }
+      theErrBiasY = nodeValue.toDouble();
+
+      //---
+      // Fetch the Global RFM validity parameters :
+      //---
+
+      xpath = "/Rational_Function_Model/Global_RFM/RFM_Validity/LONG_SCALE"; //DIMAPv2
+      xpath = theXmlDocumentRoot + xpath;
+      if (!readOneXmlNode(xmlDocument, xpath, nodeValue))
+      {
+         return false;
+      }
+      theLonScale = nodeValue.toDouble();
+
+      xpath = "/Rational_Function_Model/Global_RFM/RFM_Validity/LONG_OFF"; //DIMAPv2
+      xpath = theXmlDocumentRoot + xpath;
+      if (!readOneXmlNode(xmlDocument, xpath, nodeValue))
+      {
+         return false;
+      }
+      theLonOffset = nodeValue.toDouble();
+
+      xpath = "/Rational_Function_Model/Global_RFM/RFM_Validity/LAT_SCALE"; //DIMAPv2
+      xpath = theXmlDocumentRoot + xpath;
+      if (!readOneXmlNode(xmlDocument, xpath, nodeValue))
+      {
+         return false;
+      }
+      theLatScale = nodeValue.toDouble();
+
+      xpath = "/Rational_Function_Model/Global_RFM/RFM_Validity/LAT_OFF"; //DIMAPv2
+      xpath = theXmlDocumentRoot + xpath;
+      if (!readOneXmlNode(xmlDocument, xpath, nodeValue))
+      {
+         return false;
+      }
+      theLatOffset = nodeValue.toDouble();
+	
+      xpath = "/Rational_Function_Model/Global_RFM/RFM_Validity/HEIGHT_SCALE";
+      xpath = theXmlDocumentRoot + xpath;
+      if (!readOneXmlNode(xmlDocument, xpath, nodeValue))
+      {
+         return false;
+      }
+      theHeightScale = nodeValue.toDouble();
+
+      xpath = "/Rational_Function_Model/Global_RFM/RFM_Validity/HEIGHT_OFF"; //DIMAPv2
+      xpath = theXmlDocumentRoot + xpath;
+      if (!readOneXmlNode(xmlDocument, xpath, nodeValue))
+      {
+         return false;
+      }
+      theHeightOffset = nodeValue.toDouble();
+
+      xpath = "/Rational_Function_Model/Global_RFM/RFM_Validity/SAMP_SCALE"; //DIMAPv2
+      xpath = theXmlDocumentRoot + xpath;
+      if (!readOneXmlNode(xmlDocument, xpath, nodeValue))
+      {
+         return false;
+      }
+      theSampScale = nodeValue.toDouble();
+
+      xpath = "/Rational_Function_Model/Global_RFM/RFM_Validity/SAMP_OFF"; //DIMAPv2
+      xpath = theXmlDocumentRoot + xpath;
+      if (!readOneXmlNode(xmlDocument, xpath, nodeValue))
+      {
+         return false;
+      }
+      theSampOffset = nodeValue.toInt32();
+
+      xpath = "/Rational_Function_Model/Global_RFM/RFM_Validity/LINE_SCALE"; //DIMAPv2
+      xpath = theXmlDocumentRoot + xpath;
+      if (!readOneXmlNode(xmlDocument, xpath, nodeValue))
+      {
+         return false;
+      }
+      theLineScale = nodeValue.toDouble();
+
+      xpath = "/Rational_Function_Model/Global_RFM/RFM_Validity/LINE_OFF"; //DIMAPv2
+      xpath = theXmlDocumentRoot + xpath;
+      if (!readOneXmlNode(xmlDocument, xpath, nodeValue))
+      {
+         return false;
+      }
+      theLineOffset = nodeValue.toInt32();
+
+      return true;
+   }
+
+   bool ossimSpot6DimapSupportData::parseMetadataIdentificationDIMAPv2(ossimRefPtr<ossimXmlDocument> xmlDocument)
+   {
+      // static const char MODULE[] = "ossimSpot6DimapSupportData::parseMetadataIdentification";
+
+      vector<ossimRefPtr<ossimXmlNode> > xml_nodes;
+      ossimString xpath, nodeValue;
+      theXmlDocumentRoot = "/DIMAP_Document";
+
+      //---
+      // Get the version string which can be used as a key for parsing.
+      //---
+      xml_nodes.clear();
+      xpath = "/Metadata_Identification/METADATA_FORMAT";
+      xpath = theXmlDocumentRoot + xpath;
+      xmlDocument->findNodes(xpath, xml_nodes);
+      if (xml_nodes.size() == 0)
+      {
+
+         // FIXME MSD: used to support Spot6/Pleiades samples from SPOT-IMAGES website which are not coherent
+         // with the specification (28/09/2012). Should be remove when first data will be available and sample
+         // replaced.
+         theXmlDocumentRoot = "/SPOT_DIMAP_Document";
+         if (traceDebug())
+         {
+            ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG:\nTry to use the old root: " << theXmlDocumentRoot << endl;
+         }
+
+         xml_nodes.clear();
+         xpath = "/Metadata_Identification/METADATA_FORMAT";
+         xpath = theXmlDocumentRoot + xpath;
+         xmlDocument->findNodes(xpath, xml_nodes);
+         if (xml_nodes.size() == 0)
+         {
+            // FIXME MSD: used to support spot6/peiades samples from SPOT-IMAGES website which are not coherent
+            // with the specification (28/09/2012). Should be remove when first data will be available and sample
+            // replaced.
+            theXmlDocumentRoot = "/Dimap_Document";
+            if (traceDebug())
+            {
+               ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG:\nTry to use the new root: " << theXmlDocumentRoot << endl;
+            }
+
+            xml_nodes.clear();
+            xpath = "/Metadata_Identification/METADATA_FORMAT";
+            xpath = theXmlDocumentRoot + xpath;
+            xmlDocument->findNodes(xpath, xml_nodes);
+            if (xml_nodes.size() == 0)
+            {
+               setErrorStatus();
+               if (traceDebug())
+               {
+                  ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG:\nCould not find: " << xpath << endl;
+               }
+               return false;
+            }
+         }
+      }
+
+      ossimString attribute = "version";
+      ossimString value;
+      xml_nodes[0]->getAttributeValue(value, attribute);
+      if (value != "2.0")
+      {
+         setErrorStatus();
+         if (traceDebug())
+         {
+            ossimNotify(ossimNotifyLevel_WARN)
+               << "WARNING: DIMAP metadata version is not correct!" << std::endl;
+         }
+         return false;
+      }
+
+      //---
+      // Check that it is a valid SPOT DIMAPv2 file
+      //---
+      xpath = "/Metadata_Identification/METADATA_PROFILE";
+      xpath = theXmlDocumentRoot + xpath;
+      if (!readOneXmlNode(xmlDocument, xpath, nodeValue))
+      {
+         return false;
+      }
+
+      ossimString metadataProfile;
+      if (  (nodeValue != "S6_SENSOR") 
+            && (nodeValue != "S6_ORTHO") 
+            && (nodeValue != "S6_MOSAIC") ) 
+      {
+         if (traceDebug())
+         {
+            ossimNotify(ossimNotifyLevel_DEBUG)
+               << "DEBUG:\n Not a Spot6 DIMAPv2 file: metadata profile is incorrect!" << std::endl;
+         }
+         return false;
+      }
+      else
+         metadataProfile = nodeValue;
+
+      //---
+      // Get the subprofile
+      //---
+      xpath = "/Metadata_Identification/METADATA_SUBPROFILE";
+      xpath = theXmlDocumentRoot + xpath;
+      if (!readOneXmlNode(xmlDocument, xpath, nodeValue))
+      {
+         return false;
+      }
+
+      if ((nodeValue == "PRODUCT")) 
+         theMetadataSubProfile = OSSIM_Spot6_METADATA_SUBPROFILE_PRODUCT;
+      else if ( (nodeValue == "RPC") && (metadataProfile == "S6_SENSOR") ) 
+         theMetadataSubProfile = OSSIM_Spot6_METADATA_SUBPROFILE_RPC;
+      else
+      {
+         theMetadataSubProfile = OSSIM_Spot6_METADATA_SUBPROFILE_UNKNOWN;
+         if (traceDebug())
+         {
+            ossimNotify(ossimNotifyLevel_DEBUG)
+               << "DEBUG:\n Not a Spot6 DIMAPv2 file: metadata subprofile is incorrect !" << std::endl;
+         }
+         return false;
+      }
+
+      theDIMAPVersion = OSSIM_Spot6_DIMAPv2;
+
+      return true;
+   }
+
+   bool ossimSpot6DimapSupportData::parseDatasetIdentification(
+      ossimRefPtr<ossimXmlDocument> /* xmlDocument */ )
+   {
+      return true;
+   }
+
+   bool ossimSpot6DimapSupportData::parseCoordinateReferenceSystem(
+      ossimRefPtr<ossimXmlDocument> /* xmlDocument */ )
+   {
+      return true;
+   }
+
+   bool ossimSpot6DimapSupportData::parseGeoposition(
+      ossimRefPtr<ossimXmlDocument> /* xmlDocument */ )
+   {
+      return true;
+   }
+
+   bool ossimSpot6DimapSupportData::parseProcessingInformation(ossimRefPtr<ossimXmlDocument> xmlDocument)
+   {
+      // static const char MODULE[] = "ossimSpot6DimapSupportData::parseProcessingInformation";
+
+      vector<ossimRefPtr<ossimXmlNode> > xml_nodes;
+      ossimString xpath, nodeValue;
+
+      //---
+      // Fetch the Processing Level:
+      //---
+      xpath = "/Processing_Information/Product_Settings/PROCESSING_LEVEL"; //DIMAPv2
+      xpath = theXmlDocumentRoot + xpath;
+      if (!readOneXmlNode(xmlDocument, xpath, theProcessingLevelString))
+      {
+         return false;
+      }
+
+      //---
+      // Fetch the Spectral Processing:
+      //---
+      xpath = "/Processing_Information/Product_Settings/PROCESSING_LEVEL"; //DIMAPv2
+      xpath = theXmlDocumentRoot + xpath;
+      if (!readOneXmlNode(xmlDocument, xpath, theSpectralProcessingString))
+      {
+         return false;
+      }
+
+      return true;
+   }
+
+   bool  ossimSpot6DimapSupportData::parseRasterData(ossimRefPtr<ossimXmlDocument> xmlDocument)
+   {
+      static const char MODULE[] = "ossimSpot6DimapSupportData::parseRasterData";
+      vector<ossimRefPtr<ossimXmlNode> > xml_nodes;
+      ossimString xpath, nodeValue;
+      //---
+      // Fetch if the product file is linked to one or many JP2 files:
+      //---
+      xpath = "/Raster_Data/Data_Access/DATA_FILE_TILES"; //DIMAPv2
+      xpath = theXmlDocumentRoot + xpath;
+      if (!readOneXmlNode(xmlDocument, xpath, nodeValue))
+      {
+            return false;
+      }
+      theMultiDataFile.setValue(nodeValue);
+
+      //---
+      // Fetch the MegaImageSize:
+      //---
+      xpath = "/Raster_Data/Raster_Dimensions/NCOLS";  //DIMAPv2
+      xpath = theXmlDocumentRoot + xpath;
+      if (!readOneXmlNode(xmlDocument, xpath, nodeValue))
+      {
+         return false;
+      }
+      theImageSize.samp = nodeValue.toInt();
+
+      xpath = "/Raster_Data/Raster_Dimensions/NROWS"; //DIMAPv2
+      xpath = theXmlDocumentRoot + xpath;
+      if (!readOneXmlNode(xmlDocument, xpath, nodeValue))
+      {
+         return false;
+      }
+      theImageSize.line = nodeValue.toInt();
+
+      if (theMultiDataFile.getBoolean())
+      {
+         //---
+         // Fetch the Number of MegaTiles:
+         //---
+	 xpath = "/Raster_Data/Raster_Dimensions/Tile_Set/NTILES"; //DIMAPv2
+         xpath = theXmlDocumentRoot + xpath;
+         if (!readOneXmlNode(xmlDocument, xpath, nodeValue))
+         {
+            return false;
+         }
+         theNumberOfMegaTiles = nodeValue.toUInt32();
+
+         //---
+         // Fetch the Number of MegaTiles in X and Y:
+         //---
+
+           xml_nodes.clear();
+           xpath = "/Raster_Data/Raster_Dimensions/Tile_Set/Regular_Tiling/NTILES_COUNT"; //DIMAPv2
+           xpath = theXmlDocumentRoot + xpath;
+           xmlDocument->findNodes(xpath, xml_nodes);
+           if (xml_nodes.size() == 0)
+           {
+              setErrorStatus();
+              if (traceDebug())
+              {
+                 ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " DEBUG: \nCould not find: " << xpath << std::endl;
+              }
+              return false;
+           }
+
+           ossimString value;
+           ossimString attribute = "ntiles_x";  
+           if (!xml_nodes[0]->getAttributeValue(value, attribute))
+           {
+             attribute = "ntiles_R";
+             xml_nodes[0]->getAttributeValue(value, attribute);
+           }
+           theNumberOfMegaTilesInRow = value.toUInt32();
+
+           attribute = "ntiles_y";
+           if (!xml_nodes[0]->getAttributeValue(value, attribute))
+           {
+             attribute = "ntiles_C";
+             xml_nodes[0]->getAttributeValue(value, attribute);
+           }
+           theNumberOfMegaTilesInCol = value.toUInt32();
+
+         if (theNumberOfMegaTilesInRow * theNumberOfMegaTilesInCol != theNumberOfMegaTiles)
+         {
+            setErrorStatus();
+            if (traceDebug())
+            {
+               ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " DEBUG: \nIncoherent number of tiles: " << xpath << std::endl;
+            }
+            return false;
+         }
+
+         //---
+         // Fetch the size of MegaTiles:
+         //---
+         xml_nodes.clear();
+         xpath = "/Raster_Data/Raster_Dimensions/Tile_Set/Regular_Tiling/NTILES_SIZE";
+         xpath = theXmlDocumentRoot + xpath;
+         xmlDocument->findNodes(xpath, xml_nodes);
+         if (xml_nodes.size() == 0)
+           {
+              setErrorStatus();
+              if (traceDebug())
+              {
+                 ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " DEBUG:" << "\nCould not find: " << xpath << std::endl;
+              }
+              return false;
+           }
+
+  
+         attribute = "nrows";
+         xml_nodes[0]->getAttributeValue(value, attribute);
+         theTileSize.line = value.toUInt32();
+
+         attribute = "ncols";
+         xml_nodes[0]->getAttributeValue(value, attribute);
+         theTileSize.samp = value.toUInt32();
+      }
+
+      //--- TODO_MSD is it useful in the case of RPC model ???
+      // We will make the RefImagePoint the zero base center of the image.  This
+      // is used by the ossimSensorModel::worldToLineSample iterative loop as
+      // the starting point.  Since the ossimSensorModel does not know of the
+      // sub image we make it zero base. (comments from spot)
+      //---
+      theRefImagePoint.line = theImageSize.line / 2.0;
+      theRefImagePoint.samp = theImageSize.samp / 2.0;
+
+      //---
+      // Fetch number of bands
+      //---
+      xpath = "/Raster_Data/Raster_Dimensions/NBANDS"; //DIMAPv2
+      xpath = theXmlDocumentRoot + xpath;
+      if (!readOneXmlNode(xmlDocument, xpath, nodeValue))
+      {
+         return false;
+      }
+      theNumBands = nodeValue.toUInt32();
+
+      if (traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " DEBUG:" << "\nNumber of bands: " << theNumBands << std::endl;
+      }
+
+      //---
+      // Fetch Band Display Order
+      //---
+      xml_nodes.clear();
+      xpath = "/Raster_Data/Raster_Display/Band_Display_Order/RED_CHANNEL"; //DIMAPv2
+      xpath = theXmlDocumentRoot + xpath;
+      xmlDocument->findNodes(xpath, xml_nodes);
+      if (xml_nodes.size() == 0)
+      {
+         setErrorStatus();
+         if (traceDebug())
+         {
+            ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " DEBUG:" << "\nCould not find: " << xpath << std::endl;
+         }
+         return false;
+      }
+      theBandOrder.push_back(xml_nodes[0]->getText());
+
+      if (theNumBands > 1)
+      {
+         xml_nodes.clear();
+	 xpath = "/Raster_Data/Raster_Display/Band_Display_Order/GREEN_CHANNEL"; //DIMAPv2
+         xpath = theXmlDocumentRoot + xpath;
+         xmlDocument->findNodes(xpath, xml_nodes);
+         if (xml_nodes.size() == 0)
+         {
+            setErrorStatus();
+            if (traceDebug())
+            {
+               ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " DEBUG:" << "\nCould not find: " << xpath << std::endl;
+            }
+            return false;
+         }
+         theBandOrder.push_back(xml_nodes[0]->getText());
+
+         xml_nodes.clear();
+	 xpath = "/Raster_Data/Raster_Display/Band_Display_Order/BLUE_CHANNEL"; //DIMAPv2
+         xpath = theXmlDocumentRoot + xpath;
+         xmlDocument->findNodes(xpath, xml_nodes);
+         if (xml_nodes.size() == 0)
+         {
+            setErrorStatus();
+            if (traceDebug())
+            {
+               ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " DEBUG:" << "\nCould not find: " << xpath << std::endl;
+            }
+            return false;
+         }
+         theBandOrder.push_back(xml_nodes[0]->getText());
+
+         if (theNumBands > 3)
+         {
+            xml_nodes.clear();
+	    xpath = "/Raster_Data/Raster_Display/Band_Display_Order/ALPHA_CHANNEL"; //DIMAPv2
+            xpath = theXmlDocumentRoot + xpath;
+            xmlDocument->findNodes(xpath, xml_nodes);
+            if (xml_nodes.size() == 0)
+            {
+               setErrorStatus();
+               if (traceDebug())
+               {
+                  ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " DEBUG:" << "\nCould not find: " << xpath << std::endl;
+               }
+               return false;
+            }
+
+            theBandOrder.push_back(xml_nodes[0]->getText());
+         }
+      }
+
+      return true;
+   }
+
+   bool  ossimSpot6DimapSupportData::parseGeometricData(ossimRefPtr<ossimXmlDocument> xmlDocument)
+   {
+      ossimString xpath;
+      vector<ossimRefPtr<ossimXmlNode> > xml_nodes;
+
+      xml_nodes.clear();
+      xpath = "/Geometric_Data/Use_Area/Located_Geometric_Values"; //DIMAPv2
+      xpath = theXmlDocumentRoot + xpath;
+      xmlDocument->findNodes(xpath, xml_nodes);
+      if (xml_nodes.size() != 9 )
+      {
+         setErrorStatus();
+         if(traceDebug())
+         {
+            ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG:\nCould not find: " << xpath << std::endl;
+         }
+         return false;
+      }
+
+      std::vector<ossimRefPtr<ossimXmlNode> >::iterator node = xml_nodes.begin();
+      while (node != xml_nodes.end())
+      {
+         std::vector<ossimRefPtr<ossimXmlNode> > sub_nodes;
+
+         //---
+         // Fetch the Sun Azimuth:
+         //---
+         xpath = "Solar_Incidences/SUN_AZIMUTH";
+         (*node)->findChildNodes(xpath, sub_nodes);
+         if (sub_nodes.size() == 0)
+         {
+            setErrorStatus();
+            if(traceDebug())
+            {
+               ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG:\nCould not find: " << xpath << std::endl;
+            }
+            return false;
+         }
+         theSunAzimuth.push_back(sub_nodes[0]->getText().toDouble());
+
+         //---
+         // Fetch the Sun Elevation:
+         //---
+         sub_nodes.clear();
+         xpath = "Solar_Incidences/SUN_ELEVATION";
+         (*node)->findChildNodes(xpath, sub_nodes);
+         if (sub_nodes.size() == 0)
+         {
+            setErrorStatus();
+            if(traceDebug())
+            {
+               ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG:\nCould not find: " << xpath << std::endl;
+            }
+            return false;
+         }
+         theSunElevation.push_back(sub_nodes[0]->getText().toDouble());
+
+         //---
+         // Fetch the Incidence Angle:
+         //---
+         sub_nodes.clear();
+	 xpath = "Acquisition_Angles/INCIDENCE_ANGLE";  //DIMAPv2
+         (*node)->findChildNodes(xpath, sub_nodes);
+         if (sub_nodes.size() == 0)
+         {
+            setErrorStatus();
+            if(traceDebug())
+            {
+               ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG:\nCould not find: " << xpath << std::endl;
+            }
+            return false;
+         }
+         theIncidenceAngle.push_back(sub_nodes[0]->getText().toDouble());
+
+         //---
+         // Fetch the Viewing Angle:
+         //---
+         sub_nodes.clear();	 
+         xpath = "Acquisition_Angles/VIEWING_ANGLE"; //DIMAPv2
+         (*node)->findChildNodes(xpath, sub_nodes);
+         if (sub_nodes.size() == 0)
+         {
+            setErrorStatus();
+            if(traceDebug())
+            {
+               ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG:\nCould not find: " << xpath << std::endl;
+            }
+            return false;
+         }
+         theViewingAngle.push_back(sub_nodes[0]->getText().toDouble());
+
+         //---
+         // Fetch the Azimuth Angle:
+         //---
+         sub_nodes.clear();	
+	 xpath = "Acquisition_Angles/AZIMUTH_ANGLE"; //DIMAPv2
+         (*node)->findChildNodes(xpath, sub_nodes);
+         if (sub_nodes.size() == 0)
+         {
+            setErrorStatus();
+            if(traceDebug())
+            {
+               ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG:\nCould not find: " << xpath << std::endl;
+            }
+            return false;
+         }
+         theAzimuthAngle.push_back(sub_nodes[0]->getText().toDouble());
+
+         ++node;
+      }
+
+      return true;
+   }
+
+   bool ossimSpot6DimapSupportData::parseQualityAssessment(
+      ossimRefPtr<ossimXmlDocument> /* xmlDocument */)
+   {
+      return true;
+   }
+
+   bool ossimSpot6DimapSupportData::parseDatasetSources(ossimRefPtr<ossimXmlDocument> xmlDocument)
+   {
+      // static const char MODULE[] = "ossimSpot6DimapSupportData::parseDatasetSources";
+      ossimString xpath, nodeValue;
+      vector<ossimRefPtr<ossimXmlNode> > xml_nodes;
+
+      //---
+      // Fetch the mission index (1A ou 1B) ?
+      // and generate theSensorID
+      //---
+      xpath = "/Dataset_Sources/Source_Identification/Strip_Source/MISSION";
+      xpath = theXmlDocumentRoot + xpath;
+      if (!readOneXmlNode(xmlDocument, xpath, nodeValue))
+      {
+         return false;
+      }
+
+      if (nodeValue != "SPOT") 
+      {
+         setErrorStatus();
+         if (traceDebug())
+         {
+            ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG:\nNot a SPOT mission!"<< std::endl; 
+         }
+         return false;
+      }
+
+      //---
+      // Fetch the mission index (1A ou 1B) ?
+      // and generate theSensorID
+      //---
+      xpath = "/Dataset_Sources/Source_Identification/Strip_Source/MISSION_INDEX"; //DIMAPv2
+      xpath = theXmlDocumentRoot + xpath;
+      if (!readOneXmlNode(xmlDocument, xpath, nodeValue))
+      {
+         return false;
+      }
+
+      if (nodeValue == "6")        
+         theSensorID = "SPOT 6";    
+      else
+      {
+         setErrorStatus();
+         if (traceDebug())
+         {
+            ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG:\nNot a valid sensorID!"<< std::endl;
+         }
+         return false;
+      }
+
+      //---
+      // Fetch the Instrument:
+      //---
+      xpath = "/Dataset_Sources/Source_Identification/Strip_Source/INSTRUMENT";	
+      xpath = theXmlDocumentRoot + xpath;
+      if (!readOneXmlNode(xmlDocument, xpath, theInstrument))
+      {
+         return false;
+      }
+
+      //---
+      // Fetch the Instrument Index:
+      //---
+      xpath = "/Dataset_Sources/Source_Identification/Strip_Source/INSTRUMENT_INDEX"; //DIMAPv2
+      xpath = theXmlDocumentRoot + xpath;
+      if (!readOneXmlNode(xmlDocument, xpath, theInstrumentIndex))
+      {
+         return false;
+      }
+
+      //---
+      // Fetch the Imaging Date:
+      //---
+      ossimString firstLineImagingDate;
+      xpath = "/Dataset_Sources/Source_Identification/Strip_Source/IMAGING_DATE"; //DIMAPv2
+      xpath = theXmlDocumentRoot + xpath;
+      if (!readOneXmlNode(xmlDocument, xpath, firstLineImagingDate))
+        {
+           return false;
+        }
+
+      //---
+      // Fetch the Imaging Time:
+      //---
+      ossimString firstLineImagingTime;
+      xpath = "/Dataset_Sources/Source_Identification/Strip_Source/IMAGING_TIME"; //DIMAPv2
+      xpath = theXmlDocumentRoot + xpath;
+      if (!readOneXmlNode(xmlDocument, xpath, firstLineImagingTime))
+        {
+           return false;
+        }
+
+      theAcquisitionDate = firstLineImagingDate + "T" + firstLineImagingTime;
+
+      return true;
+   }
+
+}
diff --git a/ossim_plugins/ossim/ossimSpot6DimapSupportData.h b/ossim_plugins/ossim/ossimSpot6DimapSupportData.h
new file mode 100644
index 0000000..a10512f
--- /dev/null
+++ b/ossim_plugins/ossim/ossimSpot6DimapSupportData.h
@@ -0,0 +1,348 @@
+//*******************************************************************
+// Copyright (C) 2014  Centre National Etudes Spatiales
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 3 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+//
+// Author : Christophe Palmann (christophe.palmann at c-s.fr)
+//
+// Description:
+//
+// Contains declaration of class ossimSpot6DimapSupportData
+//
+//*****************************************************************************
+#ifndef ossimSpot6DimapSupportData_HEADER
+#define ossimSpot6DimapSupportData_HEADER 1
+
+#include <ossimPluginConstants.h>
+
+#include <ossim/base/ossimConstants.h>
+#include <ossim/base/ossimIpt.h>
+#include <ossim/base/ossimObject.h>
+#include <ossim/base/ossimString.h>
+
+#include <ossim/base/ossimErrorStatusInterface.h>
+
+#include <ossim/base/ossimBooleanProperty.h>
+#include <ossim/base/ossimFilename.h>
+
+#include <ossim/base/ossimRefPtr.h>
+#include <ossim/base/ossimDpt.h>
+#include <ossim/base/ossimDpt3d.h>
+#include <ossim/base/ossimDrect.h>
+#include <ossim/base/ossimGpt.h>
+
+
+#include <vector>
+#include <iostream>
+
+
+class ossimKeywordlist;
+class ossimXmlDocument;
+
+namespace ossimplugins
+{
+   class OSSIM_PLUGINS_DLL ossimSpot6DimapSupportData : public ossimObject,
+      public ossimErrorStatusInterface
+   {
+   public:
+      enum ossimSpot6DIMAPVersion
+      {
+         OSSIM_Spot6_UNKNOWN,
+         OSSIM_Spot6_DIMAPv2
+      };
+      
+      /** metadata subprofile type */
+      enum ossimSpot6MetadataSubProfile
+      {
+         OSSIM_Spot6_METADATA_SUBPROFILE_UNKNOWN = 0,
+         OSSIM_Spot6_METADATA_SUBPROFILE_PRODUCT = 1,
+         OSSIM_Spot6_METADATA_SUBPROFILE_RPC = 2
+      };
+      
+      ossimSpot6DimapSupportData();
+      
+      virtual ~ossimSpot6DimapSupportData();
+      
+      void clearFields();
+
+      bool parseXmlFile(const ossimFilename& file);
+
+      //---
+      // Convenient method to print important image info:
+      //---
+      void  printInfo (ostream& os) const;
+
+      /**
+       * Method to save the state of the object to a keyword list.
+       * Return true if ok or false on error.
+       */
+      virtual bool saveState(ossimKeywordlist& kwl,
+                             const char* prefix = 0)const;
+      /**
+       * Method to the load (recreate) the state of the object from a keyword
+       * list.  Return true if ok or false on error.
+       */
+      virtual bool loadState(const ossimKeywordlist& kwl,
+                             const char* prefix = 0);
+
+      ossimString   getSensorID()                            const;
+      ossimString   getProcessingLevel()                     const;
+      ossimString   getAcquisitionDate()                     const;
+      ossimString   getProductionDate()                      const;
+      ossimString   getImageID()                             const;
+      ossimString   getInstrument()                          const;
+      ossimString   getInstrumentIndex()                     const;
+
+      ossim_uint32  getNumberOfBands()                       const;
+      void          getSunAzimuth(std::vector<ossim_float64>& az)         const;
+      void          getSunElevation(std::vector<ossim_float64>& el)       const;
+      void          getImageSize(ossimIpt& sz)               const;
+
+      void          getIncidenceAngle(std::vector<ossim_float64>& ia)     const;
+      void          getViewingAngle(std::vector<ossim_float64>& va)       const;
+
+      //---
+      // Corner points:
+      //---
+      void getUlCorner(ossimGpt& pt) const;
+      void getUrCorner(ossimGpt& pt) const;
+      void getLrCorner(ossimGpt& pt) const;
+      void getLlCorner(ossimGpt& pt) const;
+
+      //---
+      // Image center point:
+      //---
+
+      /** Center of frame, sub image if there is one. */
+      void getRefGroundPoint(ossimGpt& gp)         const;
+
+      /** zero base center point */
+      void getRefImagePoint(ossimDpt& rp)          const;
+
+      /** Zero based image rectangle, sub image if there is one. */
+      void getImageRect(ossimDrect& rect)const;
+
+      bool allMetadataRead(){return (theProductIsOk && theRpcIsOk);};
+
+      std::vector<double> getLineNumCoeff() const {return theLineNumCoeff;};
+      std::vector<double> getLineDenCoeff() const {return theLineDenCoeff;};
+      std::vector<double> getSampNumCoeff() const {return theSampNumCoeff;};
+      std::vector<double> getSampDenCoeff() const {return theSampDenCoeff;};
+
+      ossim_int32 getLineOffset() const {return theLineOffset;};
+      ossim_int32 getSampOffset() const {return theSampOffset;};
+      double getLatOffset()       const {return theLatOffset;};
+      double getLonOffset()       const {return theLonOffset;};
+      double getHeightOffset()    const {return theHeightOffset;};
+      double getLineScale()       const {return theLineScale;};
+      double getSampScale()       const {return theSampScale;};
+      double getLatScale()        const {return theLatScale;};
+      double getLonScale()        const {return theLonScale;};
+      double getHeightScale()     const {return theHeightScale;};
+
+
+
+   private:
+      ossimSpot6DIMAPVersion theDIMAPVersion;
+      ossimSpot6MetadataSubProfile theMetadataSubProfile; // only for DIMAPv2
+      bool theProductIsOk;
+      bool theRpcIsOk;
+      ossimString theXmlDocumentRoot;
+
+      ossimString                 theSensorID;
+      ossimString                 theImageID;
+      ossimString                 theProductionDate;
+      ossimString                 theAcquisitionDate;
+      ossimString                 theInstrument;
+      ossimString                 theInstrumentIndex;
+      ossimString                 theProcessingLevelString;
+      ossimString                 theSpectralProcessingString;
+
+      std::vector<ossim_float64>  theSunAzimuth;
+      std::vector<ossim_float64>  theSunElevation;
+      std::vector<ossim_float64>  theIncidenceAngle;
+      std::vector<ossim_float64>  theViewingAngle;
+      std::vector<ossim_float64>  theAzimuthAngle;
+   
+      ossimIpt                    theImageSize;
+      ossimIpt                    theTileSize;
+      ossim_uint32                theNumberOfMegaTilesInRow;
+      ossim_uint32                theNumberOfMegaTilesInCol;
+      ossim_uint32                theNumberOfMegaTiles;
+      ossimBooleanProperty        theMultiDataFile;
+
+      ossim_uint32                theNumBands;
+      std::vector<ossimString>    theBandOrder;
+
+      /** Calibration information for radiometric corrections*/
+      std::vector<ossim_float64> thePhysicalBias;
+      std::vector<ossim_float64> thePhysicalGain;
+      std::vector<ossim_float64> theSolarIrradiance;
+
+      //---
+      // Corner points:
+      //---
+      ossimGpt theUlCorner;
+      ossimGpt theUrCorner;
+      ossimGpt theLrCorner;
+      ossimGpt theLlCorner;
+
+      // RPC parameters
+      ossimString theSpecId;
+      double    theErrBias;
+      double    theErrBiasX;
+      double    theErrBiasY;
+      double    theErrRand;
+      ossim_int32 theLineOffset;
+      ossim_int32 theSampOffset;
+      double    theLatOffset;
+      double    theLonOffset;
+      double    theHeightOffset;
+      double    theLineScale;
+      double    theSampScale;
+      double    theLatScale;
+      double    theLonScale;
+      double    theHeightScale;
+
+      std::vector<double> theLineNumCoeff;
+      std::vector<double> theLineDenCoeff;
+      std::vector<double> theSampNumCoeff;
+      std::vector<double> theSampDenCoeff;
+
+
+      //--- TODO MSD Check if it is necessary to keep that
+      /** Center of frame on ground, if sub image it's the center of that. */
+      ossimGpt                    theRefGroundPoint;
+
+      /** Zero based center of frame. */
+      ossimDpt                    theRefImagePoint;
+
+
+      ossimGpt createGround(const ossimString& s)const;
+      ossimDpt createDpt(const ossimString& s)const;
+      ossimIpt createIpt(const ossimString& s)const;
+      //---
+
+      bool parseRPCMetadata(ossimRefPtr<ossimXmlDocument> xmlDocument);
+
+      bool parseMetadataIdentificationDIMAPv2(ossimRefPtr<ossimXmlDocument> xmlDocument);
+
+      /**
+       * Dataset Identification:
+       *
+       * From xml section:
+       * /Dimap_Document/Dataset_Identification/
+       *
+       * NOT YET USED
+       *
+       * @return true.
+       */
+      bool parseDatasetIdentification(ossimRefPtr<ossimXmlDocument> xmlDocument);
+
+      /**
+       * Dataset Content:
+       *
+       * From xml section:
+       * /Dimap_Document/Dataset_Content/
+       *
+       * Initializes:
+       * theRefGroundPoint
+       * theUlCorner
+       * theUrCorner
+       * theLrCorner
+       * theLlCorner
+       *
+       * Note that the theRefGroundPoint will be the zero based center of
+       * the whole mega image.
+       * Note that the corners will be the corners of the whole mega image.
+       * @return true on success, false if not found.
+       */
+      bool parseDatasetContent(ossimRefPtr<ossimXmlDocument> xmlDocument);
+
+      /**
+       * Product Information:
+       *
+       * From xml section:
+       * /Dimap_Document/Product_Information/
+       *
+       * Initializes:
+       * theImageID
+       * theProductionDate
+       *
+       * @return true on success, false if not found.
+       */
+      bool parseProductInformation(ossimRefPtr<ossimXmlDocument> xmlDocument);
+
+      /**
+       * Coordinate Reference System:
+       *
+       * From xml section:
+       * /Dimap_Document/Coordinate_Reference_System/
+       *
+       * NOT YET USED
+       *
+       * @return true.
+       */
+      bool parseCoordinateReferenceSystem(ossimRefPtr<ossimXmlDocument> xmlDocument);
+
+      /**
+       * Geoposition:
+       *
+       * From xml section:
+       * /Dimap_Document/Geoposition/
+       *
+       * NOT YET USED
+       *
+       * @return true.
+       */
+      bool parseGeoposition(ossimRefPtr<ossimXmlDocument> xmlDocument);
+
+      /**
+       * Processing Information:
+       *
+       * From xml section:
+       * /Dimap_Document/Processing_Information/
+       *
+       * Initializes:
+       * theProcessingLevel
+       * theSpectralProcessing
+       *
+       * @return true on success, false if not found.
+       */
+      bool parseProcessingInformation(ossimRefPtr<ossimXmlDocument> xmlDocument);
+
+      bool parseRasterData(ossimRefPtr<ossimXmlDocument> xmlDocument);
+
+      bool parseRadiometricData(ossimRefPtr<ossimXmlDocument> xmlDocument);
+
+      bool parseGeometricData(ossimRefPtr<ossimXmlDocument> xmlDocument);
+
+      /**
+       * QualityAssessment:
+       *
+       * From xml section:
+       * /Dimap_Document/Quality_Assessment/
+       *
+       * NOT YET USED
+       *
+       * @return true.
+       */
+      bool parseQualityAssessment(ossimRefPtr<ossimXmlDocument> xmlDocument);
+
+      bool parseDatasetSources(ossimRefPtr<ossimXmlDocument> xmlDocument);
+
+   };
+}
+#endif /* #ifndef ossimSpot6DimapSupportData_HEADER */
diff --git a/ossim_plugins/ossim/ossimSpot6Model.cpp b/ossim_plugins/ossim/ossimSpot6Model.cpp
new file mode 100644
index 0000000..2210b71
--- /dev/null
+++ b/ossim_plugins/ossim/ossimSpot6Model.cpp
@@ -0,0 +1,372 @@
+//*******************************************************************
+// Copyright (C) 2014  Centre National Etudes Spatiales
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 3 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+//
+// Author : Christophe Palmann (christophe.palmann at c-s.fr)
+//
+// Description:
+//
+// Contains definition of class ossimSpot6Model
+//
+//*****************************************************************************
+
+#include "ossimSpot6Model.h"
+
+#include <cmath>
+#include <cstdio>
+
+#include <ossimSpot6Model.h>
+#include <ossimSpot6DimapSupportData.h>
+
+#include <ossimPluginCommon.h>
+
+#include <ossim/base/ossimCommon.h>
+#include <ossim/base/ossimFilename.h>
+#include <ossim/base/ossimKeywordNames.h>
+#include <ossim/base/ossimNotify.h>
+#include <ossim/base/ossimRefPtr.h>
+#include <ossim/base/ossimString.h>
+#include <ossim/base/ossimTrace.h>
+#include <ossim/base/ossimXmlDocument.h>
+#include <ossim/base/ossimXmlNode.h>
+#include <ossim/support_data/ossimSupportFilesList.h>
+
+
+namespace ossimplugins
+{
+
+// Define Trace flags for use within this file:
+   static ossimTrace traceExec  ("ossimSpot6Model:exec");
+   static ossimTrace traceDebug ("ossimSpot6Model:debug");
+
+
+   RTTI_DEF1(ossimSpot6Model, "ossimSpot6Model", ossimRpcModel);
+
+//*************************************************************************************************
+// Constructor
+//*************************************************************************************************
+   ossimSpot6Model::ossimSpot6Model()
+      :ossimRpcModel      (),
+       theSupportData        (0)
+   {
+      for (unsigned int i = 0; i < 20; i++)
+      {
+         theLineDenCoef[i] = 0.0;
+         theLineNumCoef[i] = 0.0;
+         theSampNumCoef[i] = 0.0;
+         theSampDenCoef[i] = 0.0;
+      }
+   }
+
+//*************************************************************************************************
+// Constructor
+//*************************************************************************************************
+   ossimSpot6Model::ossimSpot6Model(const ossimSpot6Model& rhs)
+      :ossimRpcModel      (rhs),
+       theSupportData        (0)
+   {
+   }
+
+//*************************************************************************************************
+// Destructor
+//*************************************************************************************************
+   ossimSpot6Model::~ossimSpot6Model()
+   {
+      if (traceExec())  ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG DESTRUCTOR: ~ossimSpot6Model(): entering..." << std::endl;
+
+      theSupportData = 0;
+
+      if (traceExec())  ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG DESTRUCTOR: ~ossimSpot6Model(): returning..." << std::endl;
+   }
+//*************************************************************************************************
+// Infamous DUP
+//*************************************************************************************************
+   ossimObject* ossimSpot6Model::dup() const
+   {
+      return new ossimSpot6Model(*this);
+   }
+
+//*************************************************************************************************
+// Print
+//*************************************************************************************************
+   std::ostream& ossimSpot6Model::print(std::ostream& out) const
+   {
+      // Capture stream flags since we are going to mess with them.
+      std::ios_base::fmtflags f = out.flags();
+
+      out << "\nDump of ossimSpot6Model at address " << (hex) << this
+          << (dec)
+          << "\n------------------------------------------------"
+          << "\n  theImageID            = " << theImageID
+          << "\n  theImageSize          = " << theImageSize
+          << "\n  theRefGndPt           = " << theRefGndPt
+          << "\n  theRefImgPt           = " << theRefImgPt
+          << "\n  theProcessingLevel    = " << theSupportData->getProcessingLevel()
+          << "\n------------------------------------------------"
+          << "\n  " << endl;
+
+      // Set the flags back.
+      out.flags(f);
+
+      if (theSupportData->getProcessingLevel() == "SENSOR")
+         return ossimRpcModel::print(out);
+      else
+         return out;
+   }
+
+//*************************************************************************************************
+// Save State
+//*************************************************************************************************
+   bool ossimSpot6Model::saveState(ossimKeywordlist& kwl,
+                                      const char* prefix) const
+   {
+      if(theSupportData.valid())
+      {
+         ossimString supportPrefix = ossimString(prefix) + "support_data.";
+         theSupportData->saveState(kwl, supportPrefix);
+      }
+
+      // If only it is a sensor product we save parameters from RPC model, its avoid to
+      // propagate a empty RPC model
+      if (theSupportData->getProcessingLevel() == "SENSOR")
+      {
+         ossimRpcModel::saveState(kwl, prefix);
+         return true;
+      }
+      else
+      {
+         kwl.add(prefix, "sensor", theSensorID, true);
+         return true;
+      }
+   }
+
+//*************************************************************************************************
+// Load State
+//*************************************************************************************************
+   bool ossimSpot6Model::loadState(const ossimKeywordlist& kwl,
+                                      const char* prefix)
+   {
+      if(!theSupportData)
+      {
+         theSupportData = new ossimSpot6DimapSupportData;
+      }
+
+      ossimString supportPrefix = ossimString(prefix) + "support_data.";
+      theSupportData->loadState(kwl, supportPrefix);
+
+      // If only it is a sensor product we load parameters from RPC model only, its avoid to
+      // add a empty RPC model
+      if (theSupportData->getProcessingLevel() == "SENSOR")
+      {
+         ossimRpcModel::loadState(kwl, prefix);
+         return true;
+      }
+      else
+      {
+         return true;
+      }
+   }
+
+
+
+   bool
+   ossimSpot6Model::open(const ossimFilename& file)
+   {
+      static const char MODULE[] = "ossimSpot6Model::open";
+      //traceDebug.setTraceFlag(true);
+
+      if (traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " entered...\n";
+      }
+
+      // Make the gsd nan so it gets computed.
+      theGSD.makeNan();
+
+      bool result = false;
+
+      // Filename used.
+      ossimFilename DIMxmlFile;
+      ossimFilename RPCxmlFile;
+
+      // Generate metadata and rpc filename
+      if ( (file.ext().downcase() != "jp2" && file.ext().downcase() != "tif")
+          || !file.exists())
+      {
+         //not a valid file
+         return false;
+      }
+      else
+      {
+        // DIMAPv2
+        DIMxmlFile = file.path();
+        RPCxmlFile = file.path();
+        ossimFilename DIMxmlFileTmp = file.file();
+        ossimFilename RPCxmlFileTmp;
+
+        DIMxmlFileTmp = DIMxmlFileTmp.file().replaceStrThatMatch("^IMG_", "DIM_");
+        DIMxmlFileTmp = DIMxmlFileTmp.replaceStrThatMatch("_R[0-9]+C[0-9]+\\.(JP2|TIF)$", ".XML");
+        // Check if it is an XML extension
+        if( DIMxmlFileTmp.ext() != "XML")
+          return false;
+
+        RPCxmlFileTmp = DIMxmlFileTmp.file().replaceStrThatMatch("^DIM_", "RPC_");
+
+        DIMxmlFile = DIMxmlFile.dirCat(DIMxmlFileTmp);
+        RPCxmlFile = RPCxmlFile.dirCat(RPCxmlFileTmp);
+
+        if (!DIMxmlFile.exists())
+        {
+          if (traceDebug())
+          {
+            ossimNotify(ossimNotifyLevel_DEBUG) << "SPOT main DIMAP file " << DIMxmlFile << " doesn't exist ...\n";
+          }
+          return false;
+        }
+      }
+
+      if (traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG) << "Metadata xml file: " << DIMxmlFile << "\n";
+         ossimNotify(ossimNotifyLevel_DEBUG) << "RPC xml file: " << RPCxmlFile << "\n";
+      }
+
+      ossimString processingLevel;
+      // Parse the metadata xml file
+      if ( !theSupportData.valid() )
+         theSupportData = new ossimSpot6DimapSupportData();
+
+      if(!theSupportData->parseXmlFile(DIMxmlFile))
+      {
+         theSupportData = 0; // ossimRefPtr
+         if (traceDebug())
+         {
+           ossimNotify(ossimNotifyLevel_DEBUG) << "ossimSpot6Model::open DEBUG:"
+                                               << "\nCould not open correctly DIMAP file" << std::endl;
+         }
+         return false;
+      }
+
+      theSensorID = theSupportData->getSensorID();
+      theImageID = theSupportData->getImageID();
+      // Get the processing level (ORTHO or SENSOR or perhaps MOSAIC ?)
+      processingLevel = theSupportData->getProcessingLevel();
+
+      // Parse the RPC xml file if necessary
+      if (RPCxmlFile.exists() && processingLevel == "SENSOR")
+      {
+         if (!theSupportData->parseXmlFile(RPCxmlFile))
+         {
+            theSupportData = 0; // ossimRefPtr
+            ossimNotify(ossimNotifyLevel_WARN) << "ossimSpot6Model::open WARNING:"
+                                               << "\nCould not open correctly RPC file" << std::endl;
+            return false;
+         }
+
+         thePolyType = B;
+
+         for (unsigned int i = 0 ; i < 20; i++ )
+         {
+            theLineNumCoef[i] = theSupportData->getLineNumCoeff()[i];
+            theLineDenCoef[i] = theSupportData->getLineDenCoeff()[i];
+            theSampNumCoef[i] = theSupportData->getSampNumCoeff()[i];
+            theSampDenCoef[i] = theSupportData->getSampDenCoeff()[i];
+         }
+
+         theLineScale  = theSupportData->getLineScale();
+         theSampScale  = theSupportData->getSampScale();
+         theLatScale   = theSupportData->getLatScale();
+         theLonScale   = theSupportData->getLonScale();
+         theHgtScale   = theSupportData->getHeightScale();
+         theLineOffset = theSupportData->getLineOffset();
+         theSampOffset = theSupportData->getSampOffset();
+         theLatOffset  = theSupportData->getLatOffset();
+         theLonOffset  = theSupportData->getLonOffset();
+         theHgtOffset  = theSupportData->getHeightOffset();
+      }
+
+      // TODO MSD Check if this part is necessary
+      _productXmlFile = DIMxmlFile;
+      ossimSupportFilesList::instance()->add(_productXmlFile);
+
+      // TODO MSD WARNING File with multi tiles are not well managed
+      theSupportData->getImageRect(theImageClipRect);
+      theSupportData->getImageSize(theImageSize);
+
+      finishConstruction();
+      clearErrorStatus();
+
+      result = true;
+      if (traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " exit status = " << (result ? "true" : "false\n") << std::endl;
+      }
+
+      /*std::cout << "---------------------------" << std::endl;
+        print(std::cout);
+        std::cout << "---------------------------" << std::endl;*/
+      return result;
+   }
+
+//*************************************************************************************************
+//! Collects common code among all parsers
+//*************************************************************************************************
+   void ossimSpot6Model::finishConstruction()
+   {
+      theImageSize.line = theImageClipRect.height();
+      theImageSize.samp = theImageClipRect.width();
+      theRefImgPt.line = theImageClipRect.midPoint().y;
+      theRefImgPt.samp = theImageClipRect.midPoint().x;
+      theRefGndPt.lat = theLatOffset;
+      theRefGndPt.lon = theLonOffset;
+      theRefGndPt.hgt = theHgtOffset;
+
+      //---
+      // NOTE:  We must call "updateModel()" to set parameter used by base
+      // ossimRpcModel prior to calling lineSampleHeightToWorld or all
+      // the world points will be same.
+      //---
+      updateModel();
+
+      ossimGpt v0, v1, v2, v3;
+      lineSampleHeightToWorld(theImageClipRect.ul(), theHgtOffset, v0);
+      lineSampleHeightToWorld(theImageClipRect.ur(), theHgtOffset, v1);
+      lineSampleHeightToWorld(theImageClipRect.lr(), theHgtOffset, v2);
+      lineSampleHeightToWorld(theImageClipRect.ll(), theHgtOffset, v3);
+
+      theBoundGndPolygon = ossimPolygon (ossimDpt(v0), ossimDpt(v1), ossimDpt(v2), ossimDpt(v3));
+
+      // Set the ground reference point using the model.
+      lineSampleHeightToWorld(theRefImgPt, theHgtOffset, theRefGndPt);
+
+      if( theGSD.hasNans() )
+      {
+         try
+         {
+            // This will set theGSD and theMeanGSD. Method throws ossimException.
+            computeGsd();
+         }
+         catch (const ossimException& e)
+         {
+            ossimNotify(ossimNotifyLevel_WARN)
+               << "ossimSpot6Model::finishConstruction -- caught exception:\n"
+               << e.what() << std::endl;
+         }
+      }
+   }
+
+}
+
diff --git a/ossim_plugins/ossim/ossimSpot6Model.h b/ossim_plugins/ossim/ossimSpot6Model.h
new file mode 100644
index 0000000..c296901
--- /dev/null
+++ b/ossim_plugins/ossim/ossimSpot6Model.h
@@ -0,0 +1,114 @@
+//*******************************************************************
+// Copyright (C) 2014  Centre National Etudes Spatiales
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 3 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+//
+// Author : Christophe Palmann (christophe.palmann at c-s.fr)
+//
+// Description:
+//
+// Contains declaration of class ossimSpot6Model.
+//
+//*****************************************************************************
+// FIXME $Id: ossimSpot5Model.h 15766 2009-10-20 12:37:09Z gpotts $
+#ifndef ossimSpot6Model_HEADER
+#define ossimSpot6Model_HEADER 1
+
+#include <ossimPluginConstants.h>
+
+#include <ossim/projection/ossimRpcModel.h>
+#include "ossimSpot6DimapSupportData.h"
+
+#include <ossim/base/ossimFilename.h>
+
+#include <iostream>
+
+
+namespace ossimplugins
+{
+   class ossimSpot6DimapSupportData;
+
+   class OSSIM_PLUGINS_DLL ossimSpot6Model : public ossimRpcModel
+   {
+   public:
+      /*!
+       * CONSTRUCTORS:
+       */
+      /** @brief default constructor */
+      ossimSpot6Model();
+
+      /** @brief copy constructor */
+      ossimSpot6Model(const ossimSpot6Model& rhs);
+
+      /** @brief Destructor */
+      virtual ~ossimSpot6Model();
+
+      bool open(const ossimFilename& file);
+
+      /*!
+       * Returns pointer to a new instance, copy of this.
+       * Not implemented yet!  Returns NULL...
+       */
+      virtual ossimObject* dup() const;
+
+      /*!
+       * Extends base-class implementation. Dumps contents of object to ostream.
+       */
+      virtual std::ostream& print(std::ostream& out) const;
+
+      /*!
+       * Fulfills ossimObject base-class pure virtuals. Loads and saves geometry
+       * KWL files. Returns true if successful.
+       */
+      virtual bool saveState(ossimKeywordlist& kwl,
+                             const char* prefix=NULL) const;
+
+      virtual bool loadState(const ossimKeywordlist& kwl,
+                             const char* prefix=NULL);
+
+      void setSupportData(ossimSpot6DimapSupportData* supportData)
+      {
+         theSupportData = supportData;
+      }
+      ossimSpot6DimapSupportData* getSupportData()
+      {
+         return theSupportData.get();
+      }
+      const ossimSpot6DimapSupportData* getSupportData()const
+      {
+         return theSupportData.get();
+      }
+
+   protected:
+
+      bool parseMetaData(const ossimFilename& file);
+
+      bool parseRpcData (const ossimFilename& file);
+
+      // In the future
+      //bool parseJP2File (const ossimFilename& file);
+
+      void finishConstruction();
+
+      ossimRefPtr<ossimSpot6DimapSupportData> theSupportData;
+
+      ossimFilename _productXmlFile;
+
+
+      TYPE_DATA
+   };
+}
+#endif /* #ifndef ossimSpot6Model_HEADER */
+
diff --git a/ossim_plugins/ossim/ossimTerraSarModel.cpp b/ossim_plugins/ossim/ossimTerraSarModel.cpp
new file mode 100644
index 0000000..0c31028
--- /dev/null
+++ b/ossim_plugins/ossim/ossimTerraSarModel.cpp
@@ -0,0 +1,2468 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+// 
+//----------------------------------------------------------------------------
+// $Id$
+
+#include <ossimTerraSarModel.h>
+#include <ossimPluginCommon.h>
+#include <ossimTerraSarProductDoc.h>
+#include <ossim/base/ossimEnvironmentUtility.h>
+#include <ossim/base/ossimKeywordNames.h>
+#include <ossim/base/ossimDirectory.h>
+#include <ossim/base/ossimRefPtr.h>
+#include <ossim/base/ossimTrace.h>
+#include <ossim/base/ossimXmlDocument.h>
+#include <ossim/base/ossimXmlNode.h>
+#include <ossim/base/ossimNotifyContext.h>
+#include <ossim/base/ossimTrace.h>
+#include <ossim/support_data/ossimSupportFilesList.h>
+#include <otb/GalileanEphemeris.h>
+#include <otb/GeographicEphemeris.h>
+#include <otb/GMSTDateTime.h>
+#include <otb/PlatformPosition.h>
+#include <otb/SensorParams.h>
+#include <otb/RefPoint.h>
+#include <otb/SarSensor.h>
+#include <cmath>
+#include <iostream>
+#include <sstream>
+
+
+// Keyword constants:
+static const char NUMBER_SRGR_COEFFICIENTS_KW[] = "sr_gr_coeffs_count";
+static const char LOAD_FROM_PRODUCT_FILE_KW[] = "load_from_product_file_flag";
+static const char PRODUCT_XML_FILE_KW[] = "product_xml_filename";
+static const char SR_GR_R0_KW[] = "sr_gr_r0";
+static const char SC_RT_KW[] = "sc_rt";
+static const char SR_GR_SF_KW[] = "sc_gr_sf";
+static const char ALT_SR_GR_COEFFICIENT0_KW[] = "alt_sr_gr_coeff0";
+static const char ALT_SR_GR_COEFFICIENT1_KW[] = "alt_sr_gr_coeff1";
+static const char ALT_SR_GR_COEFFICIENT2_KW[] = "alt_sr_gr_coeff2";
+static const char PRODUCT_TYPE[] = "product_type";
+static const char RADIOMETRIC_CORRECTION[] = "radiometricCorrection";
+static const char AZ_START_TIME[] = "azimuth_start_time";
+static const char AZ_STOP_TIME[] = "azimuth_stop_time";
+static const char RG_FIRST_TIME[] = "range_first_time";
+static const char RG_LAST_TIME[] = "range_last_time";
+static const char GENERATION_TIME[] = "generation_time";
+static const char ACQUISITION_INFO[] = "acquisitionInfo.";
+static const char IMAGING_MODE[] = "imagingMode";
+static const char SENSOR[] = "sensor";
+static const char LOOK_DIRECTION[] = "lookDirection";
+static const char POLARISATION_MODE[] = "polarisationMode";
+static const char POLARISATION_LIST[] = "polarisationList";
+static const char NUMBER_LAYERS[] = "numberOfLayers";
+static const char CALIBRATION_CALFACTOR[] = "calibration.calibrationConstant.calFactor";
+static const char RADAR_FREQUENCY[] = "radarFrequency";
+
+// Static trace for debugging
+static ossimTrace traceDebug("ossimTerraSarModel:debug");
+
+namespace ossimplugins
+{
+   RTTI_DEF1(ossimTerraSarModel,
+             "ossimTerraSarModel",
+             ossimGeometricSarSensorModel);
+}
+
+ossimplugins::ossimTerraSarModel::ossimTerraSarModel()
+   : ossimGeometricSarSensorModel(),
+     _SrToGr_R0(0.0),
+     _SrToGr_exponent(),
+     _SrToGr_coeffs(),
+     _sceneCenterRangeTime(0.0),
+     _SrToGr_scaling_factor(0.0),
+     _alt_srgr_coefset(3),
+     _productType(),
+     _radiometricCorrection(),
+     _imagingMode(),
+     _acquisitionSensor(),
+     _lookDirection(),
+     _polarisationMode(),
+     _polLayer("UNDEFINED"),
+     _polLayerList(),
+     _noise(0),
+     _sceneCoord(0),
+     _calFactor(0.),
+     _radarFrequency(0.),
+     _numberOfLayers(0),
+     _azStartTime(),
+     _azStopTime(),
+     _rgFirstPixelTime(),
+     _rgLastPixelTime(),
+     _generationTime()
+{
+}
+
+ossimplugins::ossimTerraSarModel::ossimTerraSarModel(
+   const ossimTerraSarModel& rhs)
+   : ossimGeometricSarSensorModel(rhs),
+     _SrToGr_R0(rhs._SrToGr_R0),
+     _SrToGr_exponent(rhs._SrToGr_exponent),
+     _SrToGr_coeffs(rhs._SrToGr_coeffs),
+     _sceneCenterRangeTime(rhs._sceneCenterRangeTime),
+     _SrToGr_scaling_factor(rhs._SrToGr_scaling_factor),
+     _alt_srgr_coefset(rhs._alt_srgr_coefset),
+     _productType(rhs._productType),
+     _radiometricCorrection(rhs._radiometricCorrection),
+     _imagingMode(rhs._imagingMode),
+     _acquisitionSensor(rhs._acquisitionSensor),
+     _lookDirection(rhs._lookDirection),
+     _polarisationMode(rhs._polarisationMode),
+     _polLayer(rhs._polLayer),
+     _polLayerList(rhs._polLayerList),
+     _noise(rhs._noise),
+     _sceneCoord( 0 ),
+     _calFactor(rhs._calFactor),
+     _radarFrequency(rhs._radarFrequency),
+     _numberOfLayers(rhs._numberOfLayers),
+     _azStartTime(rhs._azStartTime),
+     _azStopTime(rhs._azStopTime),
+     _rgFirstPixelTime(rhs._rgFirstPixelTime),
+     _rgLastPixelTime(rhs._rgLastPixelTime),
+     _generationTime(rhs._generationTime)
+{
+   if ( rhs._sceneCoord )
+   {
+      _sceneCoord = new SceneCoord( *(rhs._sceneCoord) );
+   }  
+}
+
+ossimplugins::ossimTerraSarModel::~ossimTerraSarModel()
+{
+   _noise.clear();
+   
+/*
+ *    if (_noise != 0)
+ {
+ delete _noise;
+ }
+*/
+   if (_sceneCoord)
+   {
+      delete _sceneCoord;
+      _sceneCoord = 0;
+   }
+}
+
+ossimString ossimplugins::ossimTerraSarModel::getClassName() const
+{
+   return ossimString("ossimTerraSarModel");
+}
+
+ossimObject* ossimplugins::ossimTerraSarModel::dup() const
+{
+   return new ossimTerraSarModel(*this);   
+}
+
+// Note : ground range to slant range coputation could be performed in three ways : 
+//    (1) Slant Range to Ground Range polynomial inversion (coefficients given at mid-scene)
+//    (2) use of a parabolic model from three geolocated points
+//    (3) interpolation from the geolocation grid (separate file, most precise technique) 
+// In this version, (1) and (2) were implemented but (1) is imprecise on the test products. 
+double ossimplugins::ossimTerraSarModel::getSlantRangeFromGeoreferenced(double col) const
+{
+   const double c =  2.99792458e+8;
+   double tn = _alt_srgr_coefset[0] + _alt_srgr_coefset[1] * col + _alt_srgr_coefset[2] * col*col ;
+   return tn * (c/2.0);
+}
+
+bool ossimplugins::ossimTerraSarModel::open(const ossimFilename& file)
+{
+   static const char MODULE[] = "ossimplugins::ossimTerraSarModel::open() -- ";
+  
+   _imageFilename = file.expand();
+   _productXmlFile = ossimFilename::NIL;
+   ossimFilename xmlfile;
+   bool foundMetadataFile = findTSXLeader(file, xmlfile);
+   while (foundMetadataFile) // use of while allows use of "break"
+   {
+      //---
+      // Instantiate the XML parser:
+      //---
+      ossimRefPtr<ossimXmlDocument> xdoc = new ossimXmlDocument();
+      if ( !xdoc->openFile(xmlfile) ) break;
+
+      ossimTerraSarProductDoc tsDoc;
+      if (!tsDoc.isTerraSarX(xdoc.get())) break;
+
+      ossimString s;
+      if ( tsDoc.getProjection(xdoc.get(), s) )
+      {
+         if ( s.upcase() == "MAP" ) break;
+      }
+
+      // Set the base class number of lines and samples
+      // Set the base class clip rect.
+      // Set the sub image offset. tmp hard coded (drb).
+      if (!tsDoc.initImageSize(xdoc.get(), theImageSize)) break;
+      theImageClipRect = ossimDrect(0, 0, theImageSize.x-1, theImageSize.y-1);
+      theSubImageOffset.x = 0.0;
+      theSubImageOffset.y = 0.0;
+
+      // Set the image ID to the scene ID.
+      if (!tsDoc.getSceneId(xdoc.get(), theImageID)) break;
+
+      // Set the sensor ID to the mission ID.
+      if (!tsDoc.getMission(xdoc.get(), theSensorID)) break;
+
+      // Set the base class gsd:
+      if (!tsDoc.initGsd(xdoc.get(), theGSD)) break;
+      theMeanGSD = (theGSD.x + theGSD.y)/2.0;
+
+      initSRGR(xdoc.get(), tsDoc);
+
+      if (!initPlatformPosition(xdoc.get(), tsDoc)) break;
+      if (!initSensorParams(xdoc.get(), tsDoc)) break;
+      if (!initRefPoint(xdoc.get(), tsDoc)) break;
+      if (!tsDoc.getProductType(xdoc.get(), _productType)) break;
+      if (!tsDoc.getRadiometricCorrection(xdoc.get(), _radiometricCorrection)) break;
+      if (!initAcquisitionInfo(xdoc.get(), tsDoc)) break;
+      if (!initNoise(xdoc.get(), tsDoc)) break;
+      if (!getPolLayerFromImageFile(xdoc.get(), file)) break;
+      if (!initCalibration(xdoc.get(), tsDoc)) break;
+
+//      replaced by OTB by the initCalibration above
+//      if (!tsDoc.getCalFactor(xdoc.get(), s)) break;
+//      _calFactor = s.toFloat64();
+
+      if (!tsDoc.getRadarFrequency(xdoc.get(), s)) break;
+      _radarFrequency= s.toFloat64();
+
+      if (!tsDoc.getAzimuthStartTime(xdoc.get(), _azStartTime)) break;
+      if (!tsDoc.getAzimuthStopTime(xdoc.get(), _azStopTime)) break;
+      if (!tsDoc.getRangeFirstPixelTime(xdoc.get(), _rgFirstPixelTime)) break;
+      if (!tsDoc.getRangeLastPixelTime(xdoc.get(), _rgLastPixelTime)) break;
+      if (!tsDoc.getGenerationTime(xdoc.get(), _generationTime)) break;
+//      removed by OTB
+//      if (!initIncidenceAngles(xdoc.get(), tsDoc)) break;
+      if (!initSceneCoord(xdoc.get(), tsDoc)) break;
+
+      xdoc = 0;
+
+      _productXmlFile = xmlfile;
+      ossimSupportFilesList::instance()->add(_productXmlFile);
+
+      // Assign the ossimSensorModel::theBoundGndPolygon
+      ossimGpt ul;
+      ossimGpt ur;
+      ossimGpt lr;
+      ossimGpt ll;
+      lineSampleToWorld(theImageClipRect.ul(), ul);
+      lineSampleToWorld(theImageClipRect.ur(), ur);
+      lineSampleToWorld(theImageClipRect.lr(), lr);
+      lineSampleToWorld(theImageClipRect.ll(), ll);
+      setGroundRect(ul, ur, lr, ll);  // ossimSensorModel method.
+      if (traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_NOTICE) << MODULE << "Loaded support data file <"<<xmlfile
+                                              <<"> for image <"<<file<<">."<<std::endl;
+
+         ossimNotify(ossimNotifyLevel_DEBUG) <<MODULE
+                                             << "4 corners from Projection: " << "\n"
+                                             << ul << ", " << ur << ", " << lr << ", " << ll << "\n";
+      }
+
+      // OSSIM preferences specifies whether a coarse grid needs to be generated:
+      if (!createReplacementOCG()) break;
+      return true;
+   }
+   
+   // If we broke out of the while, something happened...
+   return false;
+
+} // End of: bool ossimTerraSarModel::open(const ossimFilename& file)
+
+bool ossimplugins::ossimTerraSarModel::saveState(ossimKeywordlist& kwl,
+                                                 const char* prefix) const
+{
+   static const char MODULE[] = "ossimplugins::ossimTerraSarModel::saveState";
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)<< MODULE << " entered...\n";
+   }
+
+   bool result = false;
+
+   if ( (_alt_srgr_coefset.size() == 3) &&
+        ( _SrToGr_exponent.size() == _SrToGr_coeffs.size()) )
+   {
+      // Save our state:
+      kwl.add(prefix, SR_GR_R0_KW, _SrToGr_R0);
+      
+      ossimString kw1 = "sr_gr_exponent_";
+      ossimString kw2 = "sr_gr_coeffs_";
+
+      const ossim_uint32 COUNT = _SrToGr_exponent.size();
+
+      kwl.add(prefix, NUMBER_SRGR_COEFFICIENTS_KW, COUNT);
+      
+      for(ossim_uint32 i = 0; i < COUNT; ++i)
+      {
+         ossimString iStr = ossimString::toString(i);
+         ossimString kw = kw1;
+         kw += iStr;
+         kwl.add(prefix, kw, _SrToGr_exponent[i]);
+         kw = kw2;
+         kw += iStr;
+         kwl.add(prefix, kw, _SrToGr_coeffs[i]);
+      }
+      kwl.add(prefix, SC_RT_KW, _sceneCenterRangeTime);
+      kwl.add(prefix, SR_GR_SF_KW, _SrToGr_scaling_factor);
+      kwl.add(prefix, ALT_SR_GR_COEFFICIENT0_KW,  _alt_srgr_coefset[0]);
+      kwl.add(prefix, ALT_SR_GR_COEFFICIENT1_KW,  _alt_srgr_coefset[1]);
+      kwl.add(prefix, ALT_SR_GR_COEFFICIENT2_KW,  _alt_srgr_coefset[2]);
+      kwl.add(prefix, PRODUCT_XML_FILE_KW, _productXmlFile.c_str());   
+
+      // Call base save state:
+      result = ossimGeometricSarSensorModel::saveState(kwl, prefix);
+   }
+
+   //---
+   // Uncomment to force load from product file instead of loadState.
+   //---
+   if (result)
+   {
+      // kwl.add(prefix, LOAD_FROM_PRODUCT_FILE_KW, "true");
+   }
+
+   kwl.add(prefix, PRODUCT_TYPE, _productType.c_str());
+
+   kwl.add(prefix, RADIOMETRIC_CORRECTION, _radiometricCorrection.c_str());
+
+   ossimString kw = ACQUISITION_INFO;
+   ossimString kw2 = kw + IMAGING_MODE;
+   kwl.add(prefix, kw2, _imagingMode.c_str());
+   kw2 = kw + SENSOR;
+   kwl.add(prefix, kw2, _acquisitionSensor.c_str());
+   kw2 = kw + LOOK_DIRECTION;
+   kwl.add(prefix, kw2, _lookDirection.c_str());
+   kw2 = kw + POLARISATION_MODE;
+   kwl.add(prefix, kw2, _polarisationMode.c_str());
+   kw2 = kw + POLARISATION_LIST;
+   for(ossim_uint32 i = 0; i < _numberOfLayers; ++i)
+   {	
+      ossimString iStr = ossimString::toString(i)+"]";
+      ossimString kw3 = kw2+"[";
+      kw3 += iStr;  		
+      kwl.add(prefix, kw3, _polLayerList[i].c_str());
+   }
+
+   if( _polLayer !="UNDEFINED")
+   {
+      ossim_uint32 polLayerIdx = 0;
+      for(ossim_uint32 idx = 0 ; idx < _polLayerList.size(); ++idx)
+      {
+         if(_polLayerList[idx] == _polLayer)
+         {
+            polLayerIdx = idx;
+         }    
+      }  
+      _noise[polLayerIdx].saveState(kwl,prefix);
+   }
+   else
+   {
+      for(ossim_uint32 i = 0; i < _numberOfLayers; ++i)
+      {	
+         _noise[i].saveState(kwl,prefix);
+      }
+   }		
+   _sceneCoord->saveState(kwl,prefix);
+   
+   for(ossim_uint32 i = 0; i < _numberOfLayers; ++i)
+   {	
+      kwl.add(prefix, CALIBRATION_CALFACTOR, ossimString::toString(_calFactor[i]).c_str());
+   }
+   kwl.add(prefix, RADAR_FREQUENCY, ossimString::toString(_radarFrequency).c_str());
+   kwl.add(prefix, AZ_START_TIME, _azStartTime.c_str());
+   kwl.add(prefix, AZ_STOP_TIME, _azStopTime.c_str());
+   kwl.add(prefix, RG_FIRST_TIME, _rgFirstPixelTime.c_str());
+   kwl.add(prefix, RG_LAST_TIME, _rgLastPixelTime.c_str());
+
+   kwl.add(prefix, GENERATION_TIME, _generationTime.c_str());
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " exit status = " << (result?"true":"false\n")
+         << std::endl;
+   }
+   
+   return result;
+}
+
+bool ossimplugins::ossimTerraSarModel::loadState (const ossimKeywordlist &kwl,
+                                                  const char *prefix)
+{
+   static const char MODULE[] = "ossimplugins::ossimTerraSarModel::loadState";
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " entered...\n";
+   }
+
+   const char* lookup = 0;
+   ossimString s;
+
+   // Check the type first.
+   lookup = kwl.find(prefix, ossimKeywordNames::TYPE_KW);
+   if (lookup)
+   {
+      s = lookup;
+      if (s != getClassName())
+      {
+         return false;
+      }
+   }
+
+   // Get the product.xml file name.
+   lookup = kwl.find(prefix, PRODUCT_XML_FILE_KW);
+
+   if (lookup)
+   {
+      _productXmlFile = lookup;
+
+      // See if caller wants to load from xml vice keyword list.
+      lookup = kwl.find(prefix, LOAD_FROM_PRODUCT_FILE_KW);
+      if (lookup)
+      {
+         s = lookup;
+         if ( s.toBool() )
+         {
+            // Loading from product.xml file.
+            return open(_productXmlFile);
+         }
+      }
+   }
+   
+
+   //---
+   // Temp:  This must be cleared or you end up with a bounding rect of all
+   // zero's.
+   //---
+   theBoundGndPolygon.clear();
+
+   // Load the base class.
+   bool result = ossimGeometricSarSensorModel::loadState(kwl, prefix);
+
+   if (result)
+   {
+      lookup = kwl.find(prefix,SR_GR_R0_KW);
+      if (lookup)
+      {
+         s = lookup;
+         _SrToGr_R0 = s.toDouble();
+      }
+      else
+      {
+         if (traceDebug())
+         {
+            ossimNotify(ossimNotifyLevel_WARN)
+               << MODULE
+               << "\nRequired keyword not found: "
+               <<  SR_GR_R0_KW << "\n";
+         } 
+         result = false;
+      }
+      
+      ossim_uint32 count = 0;      
+      lookup = kwl.find(prefix, NUMBER_SRGR_COEFFICIENTS_KW);
+      if (lookup)
+      {
+         s = lookup;
+         count = s.toUInt32();
+      }
+      else
+      {
+         if (traceDebug())
+         {
+            ossimNotify(ossimNotifyLevel_WARN)
+               << MODULE
+               << "\nRequired keyword not found: "
+               << NUMBER_SRGR_COEFFICIENTS_KW << "\n";
+         } 
+         result = false;
+      }
+      
+      ////////////////////////////////////////////////////
+
+      if (result && count)
+      {
+         _SrToGr_exponent.resize(count);
+         _SrToGr_coeffs.resize(count);
+
+         ossimString kw1 = "sr_gr_exponent_";
+         ossimString kw2 = "sr_gr_coeffs_";
+          
+         for(ossim_uint32 i = 0; i < count; ++i)
+         {
+            ossimString kw;
+            ossimString iStr = ossimString::toString(i);
+            
+            // sr_gr_exponents
+            kw = kw1;
+            kw += iStr;
+            
+            lookup = kwl.find(prefix, kw);
+            if (lookup)
+            {
+               s = lookup;
+               _SrToGr_exponent[i] = s.toInt();
+            }
+            else
+            {
+               if (traceDebug())
+               {
+                  ossimNotify(ossimNotifyLevel_WARN)
+                     << MODULE
+                     << "\nRequired keyword not found: "
+                     << kw << "\n";
+               } 
+               result = false;
+            }
+            
+            // _SrToGr_coeffs
+            kw = kw2;
+            kw += iStr;
+            lookup = kwl.find(prefix, kw);
+            if (lookup)
+            {
+               s = lookup;
+               _SrToGr_coeffs[i] = s.toDouble();
+            }
+            else
+            {
+               if (traceDebug())
+               {
+                  ossimNotify(ossimNotifyLevel_WARN)
+                     << MODULE
+                     << "\nRequired keyword not found: "
+                     << kw << "\n";
+               } 
+               result = false;
+            }
+         }
+
+      } // matches:  if (result && count)
+  
+      lookup = kwl.find(prefix, SC_RT_KW);
+      if (lookup)
+      {
+         s = lookup;
+         _sceneCenterRangeTime = s.toDouble();
+      }
+      else
+      {
+         if (traceDebug())
+         {
+            ossimNotify(ossimNotifyLevel_WARN)
+               << MODULE
+               << "\nRequired keyword not found: "
+               << SC_RT_KW << "\n";
+         } 
+         result = false;
+      }
+
+      lookup = kwl.find(prefix, SR_GR_SF_KW);
+      if (lookup)
+      {
+         s = lookup;
+         _SrToGr_scaling_factor = s.toDouble();
+      }
+      else
+      {
+         if (traceDebug())
+         {
+            ossimNotify(ossimNotifyLevel_WARN)
+               << MODULE
+               << "\nRequired keyword not found: "
+               << SR_GR_SF_KW << "\n";
+         } 
+         result = false;
+      }
+      
+      lookup = kwl.find(prefix, ALT_SR_GR_COEFFICIENT0_KW);
+      if (lookup)
+      {
+         s = lookup;
+         _alt_srgr_coefset[0] = s.toDouble();
+      }
+      else
+      {
+         if (traceDebug())
+         {
+            ossimNotify(ossimNotifyLevel_WARN)
+               << MODULE
+               << "\nRequired keyword not found: "
+               << ALT_SR_GR_COEFFICIENT0_KW << "\n";
+         } 
+         result = false;
+      }
+      lookup = kwl.find(prefix, ALT_SR_GR_COEFFICIENT1_KW);
+      if (lookup)
+      {
+         s = lookup;
+         _alt_srgr_coefset[1] = s.toDouble();
+      }
+      else
+      {
+         if (traceDebug())
+         {
+            ossimNotify(ossimNotifyLevel_WARN)
+               << MODULE
+               << "\nRequired keyword not found: "
+               << ALT_SR_GR_COEFFICIENT1_KW << "\n";
+         } 
+         result = false;
+      }
+      lookup = kwl.find(prefix, ALT_SR_GR_COEFFICIENT2_KW);
+      if (lookup)
+      {
+         s = lookup;
+         _alt_srgr_coefset[2] = s.toDouble();
+      }
+      else
+      {
+         if (traceDebug())
+         {
+            ossimNotify(ossimNotifyLevel_WARN)
+               << MODULE
+               << "\nRequired keyword not found: "
+               << ALT_SR_GR_COEFFICIENT2_KW << "\n";
+         } 
+         result = false;
+      }
+
+      lookup = kwl.find(prefix, PRODUCT_XML_FILE_KW);
+      if (lookup)
+      {
+         _productXmlFile = lookup;
+      }
+      else
+      {
+         if (traceDebug())
+         {
+            ossimNotify(ossimNotifyLevel_WARN)
+               << MODULE
+               << "\nRequired keyword not found: "
+               << PRODUCT_XML_FILE_KW << "\n";
+         } 
+         result = false;
+      }
+      
+   } // matches: if (result)
+
+   // Load the base class.
+   /*
+    * TODO correct loadState
+    */
+#if 0
+   if ( !_noise)
+   {
+      _noise = new Noise();
+   }
+   if ( _noise->loadState(kwl, prefix) == false )
+   {
+      if (traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_WARN)
+            << MODULE
+            << "\n_noise->loadState failed!\n";
+      }
+      result = false;
+   }
+#endif
+
+
+   // Load the base class.
+   if ( !_sceneCoord)
+   {
+      _sceneCoord = new SceneCoord();
+   }
+
+   if ( _sceneCoord->loadState(kwl,prefix) == false )
+   {
+      if (traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_WARN)
+            << MODULE
+            << "\n__sceneCoord->loadState failed!\n";
+      }
+      result = false;
+   }
+     
+   lookup = kwl.find(prefix, CALIBRATION_CALFACTOR);
+   if (lookup)
+   {
+      std::istringstream in(lookup);
+      ossimString tempValue;
+      for(ossim_uint32 idx = 0; idx < _numberOfLayers; ++idx)
+      {
+         in >> tempValue;
+         _calFactor[idx] = tempValue.toDouble();
+      		
+      }
+   }
+   else
+   {
+      if (traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_WARN)
+            << MODULE
+            << "\nRequired keyword not found: "
+            << CALIBRATION_CALFACTOR << "\n";
+      } 
+      result = false;
+   }
+
+   lookup = kwl.find(prefix, RADAR_FREQUENCY);
+   if (lookup)
+   {
+      s = lookup;
+      _radarFrequency= s.toDouble();
+   }
+   else
+   {
+      if (traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_WARN)
+            << MODULE
+            << "\nRequired keyword not found: "
+            << RADAR_FREQUENCY << "\n";
+      } 
+      result = false;
+   }
+
+   lookup = kwl.find(prefix, AZ_START_TIME);
+   if (lookup)
+   {
+      _azStartTime = lookup;
+   }
+   else
+   {
+      if (traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_WARN)
+            << MODULE
+            << "\nRequired keyword not found: "
+            << AZ_START_TIME << "\n";
+      } 
+      result = false;
+   }
+
+   lookup = kwl.find(prefix, AZ_STOP_TIME);
+   if (lookup)
+   {
+      _azStopTime = lookup;
+   }
+   else
+   {
+      if (traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_WARN)
+            << MODULE
+            << "\nRequired keyword not found: "
+            << AZ_STOP_TIME << "\n";
+      } 
+      result = false;
+   }
+
+   lookup = kwl.find(prefix, RG_FIRST_TIME);
+   if (lookup)
+   {
+      _rgFirstPixelTime = lookup;
+   }
+   else
+   {
+      if (traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_WARN)
+            << MODULE
+            << "\nRequired keyword not found: "
+            << RG_FIRST_TIME << "\n";
+      }
+      result = false;
+   }
+
+   lookup = kwl.find(prefix, RG_LAST_TIME);
+   if (lookup)
+   {
+      _rgLastPixelTime = lookup;
+   }
+   else
+   {
+      if (traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_WARN)
+            << MODULE
+            << "\nRequired keyword not found: "
+            << RG_LAST_TIME << "\n";
+      }
+      result = false;
+   }
+
+
+   lookup = kwl.find(prefix, GENERATION_TIME);
+   if (lookup)
+   {
+      _generationTime = lookup;
+   }
+   else
+   {
+      if (traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_WARN)
+            << MODULE
+            << "\nRequired keyword not found: "
+            << GENERATION_TIME << "\n";
+      } 
+      result = false;
+   }
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " exit status = " << (result?"true":"false\n")
+         << std::endl;
+   }
+   
+   return result;
+}
+
+std::ostream& ossimplugins::ossimTerraSarModel::print(std::ostream& out) const
+{
+   static const char MODULE[] = "ossimplugins::ossimTerraSarModel::print";
+   // Capture the original flags.
+   std::ios_base::fmtflags f = out.flags();
+   
+   out << setprecision(15) << setiosflags(ios::fixed)
+       << "\nossimTerraSarModelclass data members:\n"
+       << SR_GR_R0_KW << _SrToGr_R0 << "\n";
+
+   ossim_uint32 i;
+   
+   ossimString kw1 = "sr_gr_exponent_";
+   for(i = 0; i < _SrToGr_exponent.size(); ++i)
+   {
+      ossimString iStr = ossimString::toString(i);
+      ossimString kw = kw1;
+      kw += iStr;
+      kw += ": ";
+      out << kw << _SrToGr_exponent[i] << "\n";
+   }
+
+   kw1 = "sr_gr_coeffs_";
+   for(i = 0; i < _SrToGr_coeffs.size(); ++i)
+   {
+      ossimString iStr = ossimString::toString(i);
+      ossimString kw = kw1;
+      kw += iStr;
+      kw += ": ";
+      out << kw << _SrToGr_coeffs[i] << "\n";
+   }   
+
+   out << SC_RT_KW << ": " << _sceneCenterRangeTime << "\n"
+       << SR_GR_SF_KW << ": " << _SrToGr_scaling_factor << "\n"
+       << ALT_SR_GR_COEFFICIENT0_KW << ": " << _alt_srgr_coefset[0] << "\n"
+       << ALT_SR_GR_COEFFICIENT1_KW << ": " <<_alt_srgr_coefset[1] << "\n"
+       << ALT_SR_GR_COEFFICIENT2_KW << ": " <<_alt_srgr_coefset[2] << "\n"
+       << PRODUCT_XML_FILE_KW << ": " << _productXmlFile.c_str() << "\n";
+   
+   ossimGeometricSarSensorModel::print(out);
+   for(ossim_uint32 i = 0; i < _numberOfLayers; ++i)
+   {
+      if ( !_noise[i].print(out) )
+      {
+         if (traceDebug())
+         {
+            ossimNotify(ossimNotifyLevel_WARN)
+               << MODULE
+               << "\n_noise->print failed!\n";
+         }
+      }
+   }
+
+   if ( !_sceneCoord->print(out) )
+   {
+      if (traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_WARN)
+            << MODULE
+            << "\n_sceneCoord->print failed!\n";
+      }
+   }
+
+   out << NUMBER_LAYERS <<  ": " << _numberOfLayers << "\n";
+   for(ossim_uint32 idx = 0; idx < _numberOfLayers; ++idx)
+   {
+      out << CALIBRATION_CALFACTOR << "["<< idx << "]: " << _calFactor[idx] << "\n";
+   }
+   out << RADAR_FREQUENCY <<  ": " << _radarFrequency<< "\n";
+   out << AZ_START_TIME <<  ": " << _azStartTime << "\n";
+   out << AZ_STOP_TIME <<  ": " << _azStopTime << "\n";
+   out << RG_FIRST_TIME <<  ": " << _rgFirstPixelTime << "\n";
+   out << RG_LAST_TIME <<  ": " << _rgLastPixelTime << "\n";
+   out << GENERATION_TIME <<  ": " << _generationTime << "\n";
+
+   // Reset flags.
+
+   ossimString kw = ACQUISITION_INFO;
+   ossimString kw2 = kw + IMAGING_MODE;
+   out << kw2 <<  ": " << _imagingMode.c_str()<< "\n";
+   kw2 = kw + SENSOR;
+   out << kw2<<  ": " <<  _acquisitionSensor.c_str()<< "\n";
+   kw2 = kw + LOOK_DIRECTION;
+   out << kw2<<  ": " <<  _lookDirection.c_str()<< "\n";
+   kw2 = kw + POLARISATION_MODE;
+   out << kw2<<  ": " <<  _polarisationMode.c_str()<< "\n";
+/*   kw2 = kw + POLARISATION_LIST;
+     for(ossim_uint32 i = 0; i < _numberOfLayers; ++i)
+     {	
+     out << kw2 <<  "["<< i <<"] : " <<  _polLayer[i].c_str()<< "\n";
+     if ( _noise[i]->print(out) == false )
+     {
+     if (traceDebug())
+     {
+     ossimNotify(ossimNotifyLevel_WARN)
+     << MODULE
+     << "\n_noise->print failed!\n";
+     }
+     }
+     }
+*/
+
+
+   out.setf(f);
+
+   return out;
+}
+
+/* 
+//  Version (1)
+double ossimplugins::ossimTerraSarModel::getSlantRangeFromGeoreferenced(double col) const
+{
+// iterative polynomial inversion
+const double CLUM        = 2.99792458e+8 ;
+double EPSILON = 0.0000001 ;
+double iterError = 1.0 ; 
+int maxIter = 50, nIter=0 ;
+double estimatedGroundRange, estimatedSlantRangeTime, actualGroundRange, estimatedSlantRange ; 
+
+
+// actual ground range computation relative to the image near side
+// in the case of Georeferenced images, _refPoint->get_distance() contains the ground range
+actualGroundRange = _refPoint->get_distance() - _sensor->get_col_direction() * (col-_refPoint->get_pix_col()) * _SrToGr_scaling_factor ; 
+
+estimatedSlantRangeTime = _sceneCenterRangeTime ;
+while ((fabs(iterError)>EPSILON)&& (nIter<maxIter)) {
+// estimated ground range computation from SrToGr
+estimatedGroundRange = 0.0 ; 
+for (int i=0; i<_SrToGr_coeffs.size(); i++) {
+estimatedGroundRange += _SrToGr_coeffs[i]*pow(estimatedSlantRangeTime-_SrToGr_R0,_SrToGr_exponent[i]);
+}
+
+// comparison between the estimated ground range and the actual ground range
+iterError = actualGroundRange - estimatedGroundRange ;
+
+// estimated slant range update
+estimatedSlantRangeTime += iterError * 2.0 / CLUM ; 
+
+nIter++;
+}
+
+estimatedSlantRange = estimatedSlantRangeTime* CLUM / 2.0 ;
+
+return  estimatedSlantRange  ;
+}
+*/
+
+bool ossimplugins::ossimTerraSarModel::InitSensorParams(
+   const ossimKeywordlist &kwl, const char *prefix)
+{
+
+
+
+
+   const char* central_freq_str = kwl.find(prefix,"central_freq");
+   double central_freq = atof(central_freq_str);
+   const char* fr_str = kwl.find(prefix,"fr");
+   double fr = atof(fr_str);
+   const char* fa_str = kwl.find(prefix,"fa");
+   double fa = atof(fa_str);
+
+
+
+
+   //number of different looks
+   // const char* n_azilok_str = kwl.find(prefix,"n_azilok");
+   // double n_azilok = atof(n_azilok_str);
+   const char* n_rnglok_str = kwl.find(prefix,"n_rnglok");
+   double n_rnglok = atof(n_rnglok_str);
+   
+   //ellipsoid parameters
+   const char* ellip_maj_str = kwl.find(prefix,"ellip_maj");
+   double ellip_maj = atof(ellip_maj_str) * 1000.0;  // km -> m
+   const char* ellip_min_str = kwl.find(prefix,"ellip_min");
+   double ellip_min = atof(ellip_min_str) * 1000.0;  // km -> m
+   
+   
+   if(_sensor != NULL)
+   {
+      delete _sensor;
+   }
+   
+   _sensor = new SensorParams();
+   
+   
+   if (_isProductGeoreferenced)
+   {
+      const char* orbitDirection_str = kwl.find(prefix,"orbitDirection");
+      std::string orbitDirection(orbitDirection_str) ;
+      int orbitDirectionSign ; 
+      if (orbitDirection=="DESCENDING") orbitDirectionSign = 1 ;
+      else orbitDirectionSign = - 1 ;
+      
+      const char* imageDataStartWith_str = kwl.find(prefix,"imageDataStartWith");
+      std::string imageDataStartWith(imageDataStartWith_str) ;
+      if (imageDataStartWith=="EARLYAZNEARRG") {
+         _sensor->set_col_direction(orbitDirectionSign); 
+         _sensor->set_lin_direction(orbitDirectionSign);
+      } else if (imageDataStartWith=="EARLYAZFARRG") {
+         _sensor->set_col_direction(-orbitDirectionSign);
+         _sensor->set_lin_direction(orbitDirectionSign);
+      } else if (imageDataStartWith=="LATEAZNEARRG") {
+         _sensor->set_col_direction(orbitDirectionSign);
+         _sensor->set_lin_direction(-orbitDirectionSign);
+      } else if (imageDataStartWith=="LATEAZFARRG") {
+         _sensor->set_col_direction(-orbitDirectionSign);
+         _sensor->set_lin_direction(-orbitDirectionSign);
+      } else {
+         // COSAR Files are stored starting with early azimuth, near range
+         _sensor->set_col_direction(orbitDirectionSign);
+         _sensor->set_lin_direction(orbitDirectionSign);
+      }
+   }
+   else
+   {
+      _sensor->set_col_direction(1);
+      _sensor->set_lin_direction(1);
+   }
+   
+   const char* lookDirection_str = kwl.find(prefix,"lookDirection");
+   std::string lookDirection(lookDirection_str) ;
+   if ((lookDirection == "Right")||(lookDirection == "RIGHT")) _sensor->set_sightDirection(SensorParams::Right) ;
+   else _sensor->set_sightDirection(SensorParams::Left) ;
+   
+   _sensor->set_sf(fr);
+   const double CLUM        = 2.99792458e+8 ;
+   double wave_length = CLUM / central_freq ;
+   _sensor->set_rwl(wave_length);
+   _sensor->set_nRangeLook(n_rnglok);
+   _sensor->set_prf(fa) ; 
+   // fa is the processing PRF 
+   //_sensor->set_prf(fa * n_azilok); // number of looks disabled
+   
+   _sensor->set_semiMajorAxis(ellip_maj) ; 
+   _sensor->set_semiMinorAxis(ellip_min) ; 
+   
+   return true;
+}
+
+bool ossimplugins::ossimTerraSarModel::InitPlatformPosition(
+   const ossimKeywordlist &kwl, const char *prefix)
+{
+   /*
+    * Retrieval of ephemerisis number
+    */
+   const char* neph_str = kwl.find(prefix,"neph");
+   int neph = atoi(neph_str);
+   
+   Ephemeris** ephemeris = new Ephemeris*[neph];
+   
+   /* 
+    * Retrieval of ephemerisis
+    */
+   for (int i=0;i<neph;i++)
+   {
+      double pos[3];
+      double vit[3];
+      char name[64];
+      
+      
+      sprintf(name,"eph%i_date",i);
+      const char* date_str = kwl.find(prefix,name);
+      
+      sprintf(name,"eph%i_posX",i);
+      const char* px_str = kwl.find(prefix,name);
+      pos[0] = atof(px_str);
+      
+      sprintf(name,"eph%i_posY",i);
+      const char* py_str = kwl.find(prefix,name);
+      pos[1] = atof(py_str);
+      
+      sprintf(name,"eph%i_posZ",i);
+      const char* pz_str = kwl.find(prefix,name);
+      pos[2] = atof(pz_str);
+      
+      
+      sprintf(name,"eph%i_velX",i);
+      const char* vx_str = kwl.find(prefix,name);
+      vit[0] = atof(vx_str) ;
+      
+      sprintf(name,"eph%i_velY",i);
+      const char* vy_str = kwl.find(prefix,name);
+      vit[1] = atof(vy_str) ;
+      
+      sprintf(name,"eph%i_velZ",i);
+      const char* vz_str = kwl.find(prefix,name);
+      vit[2] = atof(vz_str) ;
+
+      /*
+       * Conversion to JSD Date
+       */
+      std::string utcString(date_str);
+      CivilDateTime eph_civil_date;
+      if (! ossim::iso8601TimeStringToCivilDate(utcString, eph_civil_date)) return false;
+
+      JSDDateTime eph_jsd_date(eph_civil_date);
+
+      GeographicEphemeris* eph = new GeographicEphemeris(eph_jsd_date,pos,vit);
+
+      ephemeris[i] = eph;
+   }
+  
+   /*
+    * Creation of the platform position interpolator
+    */
+   if (_platformPosition != NULL)
+   {
+      delete _platformPosition;
+   }
+   _platformPosition = new PlatformPosition(ephemeris,neph);
+
+   /*
+    * Free of memory used by ephemerisis list : the constructor copies the ephemerisis
+    */
+   for (int i=0;i<neph;i++)
+   {
+      delete ephemeris[i];
+   }
+   delete[] ephemeris;
+
+   return true;
+}
+
+bool ossimplugins::ossimTerraSarModel::InitRefPoint(const ossimKeywordlist &kwl, const char *prefix)
+{
+   const char* sc_lin_str = kwl.find(prefix,"sc_lin");
+   double sc_lin = atof(sc_lin_str);
+
+   const char* sc_pix_str = kwl.find(prefix,"sc_pix");
+   double sc_pix = atof(sc_pix_str);
+
+   const char* inp_sctim_str = kwl.find(prefix,"inp_sctim");
+   std::string inp_sctim_string(inp_sctim_str) ;
+
+   const char* sceneCenterRangeTime_str = kwl.find(prefix,"sc_rng");
+   _sceneCenterRangeTime = atof(sceneCenterRangeTime_str);
+
+   if(_refPoint == NULL)
+   {
+      _refPoint = new RefPoint();
+   }
+
+   _refPoint->set_pix_col(sc_pix);
+   _refPoint->set_pix_line(sc_lin);
+
+   CivilDateTime * date = new CivilDateTime() ;
+   if (! ossim::iso8601TimeStringToCivilDate(inp_sctim_string, *date)) return false ;
+
+   if(_platformPosition != NULL)
+   {
+      Ephemeris * ephemeris = _platformPosition->Interpolate((JSDDateTime)*date);
+      if (ephemeris == NULL) return false ; 
+
+      _refPoint->set_ephemeris(ephemeris);
+
+      delete ephemeris;
+   }
+   else
+   {
+      return false;
+   }
+
+   const double CLUM        = 2.99792458e+8 ;
+   double sceneCenterSlantRange = _sceneCenterRangeTime * CLUM / 2.0 ;
+
+   _refPoint->set_distance(sceneCenterSlantRange);
+
+   // in the case of Georeferenced images, the ground range is stored in place of the slant range
+   // (used for SlantRange computation relative to reference point, necessary for optimization)
+   if (_isProductGeoreferenced) {
+      double estimatedGroundRange = 0.0 ; 
+      for (int i=0; i<static_cast<int>(_SrToGr_coeffs.size()); i++)
+      {
+         estimatedGroundRange += _SrToGr_coeffs[i]*pow(_sceneCenterRangeTime-_SrToGr_R0,_SrToGr_exponent[i]);
+      }
+      // SrToGr update : estimatedGroundRange  = sc_pix * scaling_factor
+      _SrToGr_scaling_factor = estimatedGroundRange / sc_pix ;
+      _refPoint->set_distance(estimatedGroundRange);
+   }
+
+   // in order to use ossimSensorModel::lineSampleToWorld
+   const char* nbCol_str = kwl.find(prefix,"nbCol");
+   const char* nbLin_str = kwl.find(prefix,"nbLin");
+   theImageSize.x      = atoi(nbCol_str);
+   theImageSize.y      = atoi(nbLin_str);
+   theImageClipRect    = ossimDrect(0, 0, theImageSize.x-1, theImageSize.y-1);
+
+   if (_isProductGeoreferenced) {
+      std::string azimuthStartTime(kwl.find("azimuthStartTime"));
+      std::string azimuthStopTime(kwl.find("azimuthStopTime"));
+      CivilDateTime * dateStart = new CivilDateTime() ;
+      if (! ossim::iso8601TimeStringToCivilDate(azimuthStartTime, *dateStart)) return false ;
+      CivilDateTime * dateStop = new CivilDateTime() ;
+      if (! ossim::iso8601TimeStringToCivilDate(azimuthStopTime, *dateStop)) return false ;
+      double acq_msec_first = (double) dateStart->get_second()+dateStart->get_decimal();
+      double acq_msec_last = (double) dateStop->get_second()+dateStop->get_decimal();
+
+      double actualPRF = theImageSize.y/(acq_msec_last-acq_msec_first) ;
+      _sensor->set_nAzimuthLook(_sensor->get_prf()/actualPRF); 
+   }
+   else   
+      _sensor->set_nAzimuthLook(1.0);
+
+   // Ground Control Points extracted from the model : scene center and corners
+   std::list<ossimGpt> groundGcpCoordinates ; 
+   std::list<ossimDpt> imageGcpCoordinates ; 
+   char name[64];
+   for (int k=0 ; k<5 ; k++) {
+      sprintf(name,"cornersCol%i",k);
+      const char* i_str = kwl.find(name);
+      int i = atoi(i_str);
+      sprintf(name,"cornersLin%i",k);
+      const char* j_str = kwl.find(name);
+      int j = atoi(j_str);
+      sprintf(name,"cornersLon%i",k);
+      const char* lon_str = kwl.find(name);
+      double lon = atof(lon_str);
+      sprintf(name,"cornersLat%i",k);
+      const char* lat_str = kwl.find(name);
+      double lat = atof(lat_str);
+      const char* height_str = kwl.find("terrain_h");
+      double height = atof(height_str) ;
+
+      ossimDpt imageGCP(i,j);
+      ossimGpt groundGCP(lat ,lon , height);
+      groundGcpCoordinates.push_back(groundGCP) ; 
+      imageGcpCoordinates.push_back(imageGCP) ;
+   }
+
+   // Default optimization 
+   optimizeModel(groundGcpCoordinates, imageGcpCoordinates) ;
+
+   return true;
+}
+
+bool ossimplugins::ossimTerraSarModel::InitSRGR(const ossimKeywordlist &kwl, const char *prefix)
+{
+   const char* rangeProjectionType_str = kwl.find(prefix,"rangeProjectionType");
+   std::string rangeProjectionType(rangeProjectionType_str);
+
+   _isProductGeoreferenced = (rangeProjectionType=="GROUNDRANGE") ;
+
+   // SRtoGR polynomial reference
+   const char* SrToGr_R0_str = kwl.find(prefix,"SrToGr_R0");
+   _SrToGr_R0 = atof(SrToGr_R0_str);
+
+   // number of SRtoGR coefficients
+   const char* SrToGr_coeffs_number_str = kwl.find(prefix,"SrToGr_coeffs_number");
+   int srToGr_coeffs_number = atoi(SrToGr_coeffs_number_str);
+
+   // SRtoGR coefficients and exponents
+   char name[64];
+   double coeff ; 
+   int exponent ; 
+   for(int i=0;i<srToGr_coeffs_number;i++)
+   {
+      sprintf(name,"SrToGr_coeffs_%i",i);
+      const char* coeff_str = kwl.find(prefix,name);
+      coeff = atof(coeff_str);
+      _SrToGr_coeffs.push_back(coeff);
+      sprintf(name,"SrToGr_exps_%i",i);
+      const char* exp_str = kwl.find(prefix,name);
+      exponent = atoi(exp_str);
+      _SrToGr_exponent.push_back(exponent);
+   }
+
+   // ALTERNATIVE to provided coefficients
+
+   // Range time for first mid and last pixel
+   std::string orbitDirection(kwl.find(prefix,"orbitDirection")) ;
+   double t1, t2, t3 ; 
+   if (orbitDirection=="DESCENDING") {
+      t3 = atof(kwl.find("start_rng"));
+      t2 = atof(kwl.find("sc_rng"));
+      t1 = atof(kwl.find("end_rng"));
+   }
+   else {
+      t1 = atof(kwl.find("start_rng"));
+      t2 = atof(kwl.find("sc_rng"));
+      t3 = atof(kwl.find("end_rng"));
+   }
+
+   // Range pixels numbers corresponding
+   // double x1 = 0.0;
+   double x2 = atof(kwl.find("sc_pix")); 
+   double x3 = 2.0*(x2+1.0) -1.0 ; 
+
+   _alt_srgr_coefset[0] = t1;
+   _alt_srgr_coefset[1] = ((t2-t1)/(x2*x2)+(t1-t3)/(x3*x3))/((1.0/x2)-(1.0/x3));
+   _alt_srgr_coefset[2] = ((t2-t1)/x2 + (t1-t3)/x3)/(x2-x3);
+  
+   return true;
+}
+
+bool ossimplugins::ossimTerraSarModel::initSRGR(const ossimXmlDocument* xdoc,
+                                                const ossimTerraSarProductDoc& tsDoc)
+{
+   static const char MODULE[] = "ossimplugins::ossimTerraSarModel::initSRGR";
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)<< MODULE << " entered...\n";
+   }
+   
+   bool result = true;
+   
+   ossimString s;
+
+   _isProductGeoreferenced = tsDoc.isProductGeoreferenced(xdoc);
+
+   // SRtoGR polynomial reference
+   if ( tsDoc.getReferencePoint(xdoc, s) )
+   {
+      _SrToGr_R0 = s.toDouble();
+   }
+   else
+   {
+      //---
+      // This value is only used if product is geo referenced,
+      // (projection == GROUNDRANGE) so we won't error out if not.
+      //---
+      if (_isProductGeoreferenced)
+      {
+         result = false;
+      }
+      _SrToGr_R0 = 0.0;
+   }
+
+   // number of SRtoGR coefficients
+   ossimRefPtr<ossimXmlNode> nodes;
+   ossimString path =
+      "/level1Product/productSpecific/projectedImageInfo/slantToGroundRangeProjection/coefficient";
+   std::vector<ossimRefPtr<ossimXmlNode> > xnodes;
+   const ossimString EXP = "exponent";
+   xdoc->findNodes(path, xnodes);
+   if ( xnodes.size() )
+   {
+      for (ossim_uint32 i = 0; i < xnodes.size(); ++i)
+      {
+         if (xnodes[i].valid())
+         {
+            xnodes[i]->getAttributeValue(s, EXP);
+            _SrToGr_exponent.push_back(s.toInt32());
+            _SrToGr_coeffs.push_back(xnodes[i]->getText().toDouble());
+         }
+      }
+   }
+   else
+   {
+      result = false;
+   }
+
+   // Range time for first mid and last pixel
+
+   if ( tsDoc.getOrbitDirection(xdoc, s) )
+   {
+      bool desendingFlag = (s == "DESCENDING");
+      double startRng = 0.0;
+      double endRng   = 0.0;
+      double scRng    = 0.0;
+      double t1 = 0.0;
+      double t2 = 0.0;
+      double t3 = 0.0;
+      double x2 = 0.0;
+
+      if ( tsDoc.getRangeGateFirstPixel(xdoc, s) )
+      {
+         startRng = s.toDouble();
+      }
+      else
+      {
+         result = false;
+      }
+      
+      if ( tsDoc.getRangeGateLastPixel(xdoc, s) )
+      {
+         endRng = s.toDouble();
+      }
+      else
+      {
+         result = false;
+      }
+      
+      if ( tsDoc.getSceneCenterRangeTime(xdoc, s) )
+      {
+         scRng = s.toDouble();
+      }
+      else
+      {
+         result = false;
+      }         
+      
+      t2 = scRng;
+      
+      if (desendingFlag)
+      {
+         t3 = startRng;
+         t1 = endRng;
+      }
+      else
+      {
+         t1 = startRng;
+         t3 = endRng;
+      }
+      
+      // Range pixels numbers corresponding
+      if ( tsDoc.getSceneCenterRefColumn(xdoc, s) )
+      {
+         //---
+         // TSX image coordinates start at (1,1),
+         // while OSSIM image coordinates start at (0,0)
+         //---
+         x2 = s.toDouble() - 1.0;
+      }
+      else
+      {
+         result = false;
+      }
+      
+      if (traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG)
+            << "startRng: " << startRng
+            << "\nscRng:    " << scRng
+            << "\nendRng:   " << endRng
+            << "\nx2:       " << x2
+            << "\n";
+      }
+      
+      double x3 = 2.0*(x2+1.0) -1.0 ;
+      
+      _alt_srgr_coefset[0] = t1;
+      _alt_srgr_coefset[1] =
+         ((t2-t1)/(x2*x2)+(t1-t3)/(x3*x3))/((1.0/x2)-(1.0/x3));
+      _alt_srgr_coefset[2] = ((t2-t1)/x2 + (t1-t3)/x3)/(x2-x3);
+   }
+   else
+   {
+      result = false;
+   }
+
+   return result;
+}
+   
+bool ossimplugins::ossimTerraSarModel::initPlatformPosition(const ossimXmlDocument* xdoc,
+                                                            const ossimTerraSarProductDoc& tsDoc)
+{
+   static const char MODULE[] = "ossimplugins::ossimTerraSarModel::initPlatformPosition";
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)<< MODULE << " entered...\n";
+   }   
+   
+   // Initialize the platform position interpolator.
+   if (_platformPosition)
+   {
+      delete _platformPosition;
+   }
+   
+   _platformPosition = new PlatformPosition();
+   
+   bool result = tsDoc.initPlatformPosition(xdoc, _platformPosition);
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " exit status = " << (result?"true":"false\n")
+         << std::endl;
+   }
+
+   return result;
+}
+
+bool ossimplugins::ossimTerraSarModel::initSensorParams(const ossimXmlDocument* xdoc,
+                                                        const ossimTerraSarProductDoc& tsDoc)
+{
+   static const char MODULE[] = "ossimplugins::ossimTerraSarModel::initSensorParams";
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " entered...\n";
+   }
+
+   if (_sensor )
+   {
+      delete _sensor;
+   }
+   _sensor =  new SensorParams();
+
+
+   bool result = tsDoc.initSensorParams(xdoc, _sensor);
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "result for  tsDoc.initSensorParams " << result << endl;
+   }
+
+   if (!result)
+   {
+      delete _sensor;
+      _sensor = 0;
+   }
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " exit status = " << (result?"true":"false\n")
+         << std::endl;
+   }
+
+   return result;
+}
+
+bool ossimplugins::ossimTerraSarModel::initRefPoint(
+   const ossimXmlDocument* xdoc, const ossimTerraSarProductDoc& tsDoc)
+{
+   static const char MODULE[] = "ossimplugins::ossimTerraSarModel::initRefPoint";
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)<< MODULE << " entered...\n";
+   }
+
+   if ( !_platformPosition )
+   {
+      return false;
+   }
+
+   bool result = true;
+
+   ossimString s; // used throughout
+
+   //---
+   // Set the base class reference points.
+   // Note the "ONE BASED" image points from xml doc.
+   //---
+   
+   // Get the center sample.
+   if ( tsDoc.getSceneCenterRefColumn(xdoc, s) )
+   {
+      theRefImgPt.x = s.toFloat64() - 1.0;
+   }
+   else
+   {
+      result = false;
+   }
+
+   // Get the center line.
+   if ( tsDoc.getSceneCenterRefRow(xdoc, s) )
+   {
+      theRefImgPt.y = s.toFloat64() - 1.0;
+   }
+   else
+   {
+      result = false;
+   }
+
+   // Get the center latitude.
+   if ( tsDoc.getSceneCenterLat(xdoc, s) )
+   {
+      theRefGndPt.lat = s.toFloat64();
+   }
+   else
+   {
+      result = false;
+   }
+
+   // Get the center longitude.
+   if ( tsDoc.getSceneCenterLon(xdoc, s) )
+   {
+      theRefGndPt.lon = s.toFloat64();
+   }
+   else
+   {
+      result = false;
+   }
+
+   // Reference point.
+   if (_refPoint)
+   {
+      delete _refPoint;
+   }
+   _refPoint = new RefPoint();
+
+   _refPoint->set_pix_col(theRefImgPt.x);
+   _refPoint->set_pix_line(theRefImgPt.y);
+
+   if ( tsDoc.getSceneCenterAzimuthTime(xdoc, s) )
+   {
+      CivilDateTime date;
+      if ( ossim::iso8601TimeStringToCivilDate(s, date) )
+      {
+         JSDDateTime jdate(date);
+         Ephemeris * ephemeris = _platformPosition->Interpolate(jdate);
+         if (ephemeris)
+         {
+            _refPoint->set_ephemeris(ephemeris);
+            delete ephemeris;
+         }
+         else
+         {
+            result = false;
+         }
+      }
+      else
+      {
+         result = false;
+      }
+   }
+   else
+   {
+      result = false;
+   }
+
+   if ( tsDoc.getSceneCenterRangeTime(xdoc, s) )
+   {
+      _sceneCenterRangeTime = s.toDouble();
+      
+      const double CLUM = 2.99792458e+8;
+      double sceneCenterSlantRange = _sceneCenterRangeTime * CLUM / 2.0;
+      _refPoint->set_distance(sceneCenterSlantRange);
+   }
+   else
+   {
+      result = false;
+   }
+
+   //---
+   // In the case of Georeferenced images, the ground range is stored in
+   // place of the slant range
+   // (used for SlantRange computation relative to reference point, necessary
+   // for optimization)
+   //---
+   if (_isProductGeoreferenced)
+   {
+      double estimatedGroundRange = 0.0 ; 
+      for (int i=0; i<static_cast<int>(_SrToGr_coeffs.size()); i++)
+      {
+         estimatedGroundRange += _SrToGr_coeffs[i]*
+            pow(_sceneCenterRangeTime - _SrToGr_R0, _SrToGr_exponent[i]);
+      }
+
+      // SrToGr update : estimatedGroundRange  = sc_pix * scaling_factor
+      _SrToGr_scaling_factor = estimatedGroundRange / theRefImgPt.x;
+      _refPoint->set_distance(estimatedGroundRange);
+
+      CivilDateTime dateStart;
+      CivilDateTime dateStop;
+      
+      if (tsDoc.getAzimuthStartTime(xdoc, s) )
+      {
+         if (! ossim::iso8601TimeStringToCivilDate(s, dateStart) )
+         {
+            result = false;
+         }
+      }
+      else
+      {
+         result = false;
+      }
+
+      if (tsDoc.getAzimuthStopTime(xdoc, s) )
+      {
+         if (! ossim::iso8601TimeStringToCivilDate(s, dateStop) )
+         {
+            result = false;
+         }
+      }
+      else
+      {
+         result = false;
+      }
+
+      double acq_msec_first = (double) dateStart.get_second() +
+         dateStart.get_decimal();
+      double acq_msec_last = (double) dateStop.get_second() +
+         dateStop.get_decimal();
+      
+      double actualPRF = theImageSize.y/(acq_msec_last - acq_msec_first) ;
+      _sensor->set_nAzimuthLook(_sensor->get_prf()/actualPRF); 
+      
+   }
+   else
+   {
+      _sensor->set_nAzimuthLook(1.0);
+   }
+   
+   // Ground Control Points extracted from the model.
+   std::list<ossimGpt> groundGcpCoordinates; 
+   std::list<ossimDpt> imageGcpCoordinates;
+   if ( tsDoc.initTiePoints(xdoc,
+                            groundGcpCoordinates,
+                            imageGcpCoordinates) == false )
+   {
+      if (traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG)
+            << MODULE << "initTiePoint error! exiting\n";
+      }
+      return false;
+   }
+
+   if (result)
+   {
+      // Default optimization 
+      optimizeModel(groundGcpCoordinates, imageGcpCoordinates);
+   }
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " exit status = true\n";
+   } 
+
+   return true;
+}
+
+bool ossimplugins::ossimTerraSarModel::initAcquisitionInfo(
+   const ossimXmlDocument* xdoc, const ossimTerraSarProductDoc& tsDoc)
+{
+   static const char MODULE[] = "ossimplugins::ossimTerraSarModel::initAcquisitionInfo";
+   bool result;
+   ossimString     s;
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)<< MODULE << " entering...\n";
+   }   
+   
+   result = tsDoc.geNumberOfLayers(xdoc, s);
+   if ( result == false )
+   {
+      if (traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG)
+            << "unable to get Number Of Layers \n";
+      }   
+      setErrorStatus();
+      return false;
+   }
+   _numberOfLayers = ossimString(s).toUInt32();
+
+   result = tsDoc.getMission(xdoc, theSensorID);
+   if ( result == false )
+   {
+      if (traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG)
+            << "unable to get theSensorID \n";
+      }   
+      setErrorStatus();
+      return false;
+   }
+   
+   result = tsDoc.getImagingMode(xdoc, _imagingMode);
+   if ( result == false )
+   {
+      if (traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG)
+            << "unable to get Imaging Mode \n";
+      }   
+      setErrorStatus();
+      return false;
+   }
+
+   result = tsDoc.getAcquisitionSensor(xdoc, _acquisitionSensor);
+   if ( result == false )
+   {
+      if (traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG)
+            << "unable to get Acquisition Sensor \n";
+      }   
+      setErrorStatus();
+      return false;
+   }
+   result = tsDoc.getLookDirection(xdoc, _lookDirection);
+   if ( result == false )
+   {
+      if (traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG)
+            << "unable to get Look direction \n";
+      }   
+      setErrorStatus();
+      return false;
+   }
+   result = tsDoc.getPolarisationMode(xdoc, _polarisationMode);
+   if ( result == false )
+   {
+      if (traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG)
+            << "unable to get Polarisation Mode \n";
+      }   
+      setErrorStatus();
+      return false;
+   }
+   result = tsDoc.getPolLayerList(xdoc, _polLayerList);
+   if ( result == false )
+   {
+      if (traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG)
+            << "unable to get Polarisation Layer list \n";
+      }   
+      setErrorStatus();
+      return false;
+   }
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)<< MODULE << " leaving...\n";
+   }   
+
+   return result;
+}
+
+bool ossimplugins::ossimTerraSarModel::initSceneCoord(
+   const ossimXmlDocument* xdoc, const ossimTerraSarProductDoc& tsDoc)
+{
+   static const char MODULE[] = "ossimplugins::ossimTerraSarModel::initSceneCoord";
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)<< MODULE << " entered...\n";
+   }   
+   
+   if (_sceneCoord)
+   {
+      delete _sceneCoord;
+   }
+   
+   _sceneCoord = new SceneCoord();
+   
+   bool result = tsDoc.initSceneCoord(xdoc, _sceneCoord);
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " exit status = " << (result?"true":"false\n")
+         << std::endl;
+   }
+
+   return result;
+}
+
+bool ossimplugins::ossimTerraSarModel::getNoiseAtGivenNode(
+   const ossimRefPtr<ossimXmlNode> xmlDocument, ossimplugins::Noise& noise)
+{
+   ossimString xpath;
+   std::vector<ossimRefPtr<ossimXmlNode> > xml_nodes;
+   std::vector<ossimRefPtr<ossimXmlNode> > sub_nodes;
+   std::vector<ossimRefPtr<ossimXmlNode> >::iterator node;
+
+   std::vector<ImageNoise> tabImageNoise;
+   ImageNoise              ev;
+   tabImageNoise.clear();
+ 
+   static const char MODULE[] = "ossimplugins::ossimTerraSarModel::getNoise";
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)<< MODULE << " entered...\n";
+   }  
+
+   if ( !xmlDocument )
+   {
+      setErrorStatus();
+      if(traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG)
+            << MODULE << " DEBUG: one of the getNoise parameter of the method is NULL" << std::endl;
+      }
+      return false;	
+   }
+
+   xml_nodes.clear();
+   xpath = "numberOfNoiseRecords";
+   xmlDocument->findChildNodes(xpath, xml_nodes);
+   if(xml_nodes.size() == 0)
+   {
+      setErrorStatus();
+      if(traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG)
+            << MODULE << " DEBUG:"
+            << "\nCould not find: " << xpath
+            << std::endl;
+      }
+      return false;
+   }
+    
+   noise.set_numberOfNoiseRecords( xml_nodes[0]->getText().toInt32() );
+
+
+   xml_nodes.clear();
+   xpath = "imageNoise";
+   xmlDocument->findChildNodes(xpath, xml_nodes);
+   if(xml_nodes.size() == 0)
+   {
+      setErrorStatus();
+      if(traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG)
+            << MODULE << " DEBUG:"
+            << "\nCould not find: " << xpath
+            << std::endl;
+      }
+      return false;
+   }
+
+   node = xml_nodes.begin();
+   while (node != xml_nodes.end())
+   {
+      sub_nodes.clear();
+      xpath = "timeUTC";
+      (*node)->findChildNodes(xpath, sub_nodes);
+      if (sub_nodes.size() == 0)
+      {
+         setErrorStatus();
+         if(traceDebug())
+         {
+            ossimNotify(ossimNotifyLevel_DEBUG)
+               << MODULE << " DEBUG:"
+               << "\nCould not find: " << xpath
+               << std::endl;
+         }
+         return false;
+      }
+      ev.set_timeUTC(sub_nodes[0]->getText());
+    
+      sub_nodes.clear();
+      xpath = "noiseEstimate/validityRangeMin";
+      (*node)->findChildNodes(xpath, sub_nodes);
+      if (sub_nodes.size() == 0)
+      {
+         setErrorStatus();
+         if(traceDebug())
+         {
+            ossimNotify(ossimNotifyLevel_DEBUG)
+               << MODULE << " DEBUG:"
+               << "\nCould not find: " << xpath
+               << std::endl;
+         }
+         return false;
+      }
+      ev.set_validityRangeMin( sub_nodes[0]->getText().toDouble() );
+
+      sub_nodes.clear();
+      xpath = "noiseEstimate/validityRangeMax";
+      (*node)->findChildNodes(xpath, sub_nodes);
+      if (sub_nodes.size() == 0)
+      {
+         setErrorStatus();
+         if(traceDebug())
+         {
+            ossimNotify(ossimNotifyLevel_DEBUG)
+               << MODULE << " DEBUG:"
+               << "\nCould not find: " << xpath
+               << std::endl;
+         }
+         return false;
+      }
+      ev.set_validityRangeMax( sub_nodes[0]->getText().toDouble() );
+
+      sub_nodes.clear();
+      xpath = "noiseEstimate/referencePoint";
+      (*node)->findChildNodes(xpath, sub_nodes);
+      if (sub_nodes.size() == 0)
+      {
+         setErrorStatus();
+         if(traceDebug())
+         {
+            ossimNotify(ossimNotifyLevel_DEBUG)
+               << MODULE << " DEBUG:"
+               << "\nCould not find: " << xpath
+               << std::endl;
+         }
+         return false;
+      }
+      ev.set_referencePoint( sub_nodes[0]->getText().toDouble() );
+
+      sub_nodes.clear();
+      xpath = "noiseEstimate/polynomialDegree";
+      (*node)->findChildNodes(xpath, sub_nodes);
+      if (sub_nodes.size() == 0)
+      {
+         setErrorStatus();
+         if(traceDebug())
+         {
+            ossimNotify(ossimNotifyLevel_DEBUG)
+               << MODULE << " DEBUG:"
+               << "\nCould not find: " << xpath
+               << std::endl;
+         }
+         return false;
+      }
+      ev.set_polynomialDegree( sub_nodes[0]->getText().toInt32() );
+
+      sub_nodes.clear();
+      ossimXmlNode::ChildListType nodelist;
+      (*node)->findChildNodes("noiseEstimate/coefficient",nodelist);
+      ossimXmlNode::ChildListType::const_iterator child_iter = nodelist.begin();
+      std::vector<double> polynomialCoefficients;
+      while(child_iter != nodelist.end())
+      {
+         double coefficient = ((*child_iter)->getText()).toDouble() ;
+         polynomialCoefficients.push_back(coefficient);
+         ++child_iter;
+      }                  
+      ev.set_polynomialCoefficients( polynomialCoefficients );
+ 
+      tabImageNoise.push_back(ev);
+
+      ++node;
+   }
+
+   noise.set_imageNoise(tabImageNoise);
+ 
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)<< MODULE << " leaving...\n";
+   }   
+
+   return true;
+}
+
+
+bool ossimplugins::ossimTerraSarModel::initNoise(
+   const ossimXmlDocument* xmlDocument, const ossimTerraSarProductDoc& /* tsDoc */ )
+{
+   ossimString xpath;
+   ossimString polLayerName;
+   std::vector<ossimRefPtr<ossimXmlNode> > xml_nodes;
+   std::vector<ossimRefPtr<ossimXmlNode> > sub_nodes;
+   std::vector<ossimRefPtr<ossimXmlNode> >::iterator node;
+   bool result;
+
+   static const char MODULE[] = "ossimplugins::ossimTerraSarModel::initNoise";
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)<< MODULE << " entering...\n";
+   }   
+
+   _noise.resize(_numberOfLayers);
+      
+   xml_nodes.clear();
+   xpath = "/level1Product/noise";
+
+   xmlDocument->findNodes(xpath, xml_nodes);
+   if(xml_nodes.size() == 0)
+   {
+      setErrorStatus();
+      if(traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG)
+            << MODULE << " DEBUG:"
+            << "\nCould not find: " << xpath
+            << std::endl;
+      }
+      return false;
+   }
+
+   node = xml_nodes.begin();
+   while (node != xml_nodes.end())
+   {
+      sub_nodes.clear();
+      xpath = "polLayer";
+      (*node)->findChildNodes(xpath, sub_nodes);
+      if (sub_nodes.size() == 0)
+      {
+         setErrorStatus();
+         if(traceDebug())
+         {
+            ossimNotify(ossimNotifyLevel_DEBUG)
+               << MODULE << " DEBUG:"
+               << "\nCould not find: " << xpath
+               << std::endl;
+         }
+         return false;
+      }
+    
+      polLayerName = sub_nodes[0]->getText();
+
+      ossim_uint32 polLayerIdx = 0;
+      bool polLayerIdxFound = false;
+    
+      for(ossim_uint32 idx = 0 ; idx < _polLayerList.size(); ++idx)
+      {
+         if(_polLayerList[idx] == polLayerName)
+         {
+            polLayerIdx = idx;
+            polLayerIdxFound = true;
+         }    
+      }  
+
+      if (!polLayerIdxFound)
+      {
+         setErrorStatus();
+         if (traceDebug())
+         {
+            ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " DEBUG: Unable to find polLayer in polLayer List"
+                                                << std::endl;
+         }
+         return false;
+      }
+	
+      sub_nodes.clear();
+
+      //_noise[polLayerIdx] = new Noise();
+      _noise[polLayerIdx].set_imagePolarisation(polLayerName);
+   
+      result = getNoiseAtGivenNode( (*node),_noise[polLayerIdx]);
+      if(!result)
+      {
+         setErrorStatus();
+         if (traceDebug())
+         {
+            ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " DEBUG: Unable to getNoise for the " << polLayerName
+                                                << " layer image" << std::endl;
+         }
+         return false;
+      }
+
+      ++node;
+   }
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)<< MODULE << " leaving...\n";
+   }   
+
+   return true;
+}
+
+
+bool ossimplugins::ossimTerraSarModel::getPolLayerFromImageFile(
+   const ossimXmlDocument* xmlDocument, const ossimFilename& imageFilename)
+{
+   ossimString xpath;
+   ossimString polLayerName;
+   ossimString polLayerFileName;
+   std::vector<ossimRefPtr<ossimXmlNode> > xml_nodes;
+   std::vector<ossimRefPtr<ossimXmlNode> > sub_nodes;
+   std::vector<ossimRefPtr<ossimXmlNode> >::iterator node;
+
+   static const char MODULE[] = "ossimplugins::ossimTerraSarModel::getPolLayerFromImageFile";
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)<< MODULE << " entering...\n";
+   }   
+   
+   xml_nodes.clear();
+   xpath = "/level1Product/productComponents/imageData";
+
+   xmlDocument->findNodes(xpath, xml_nodes);
+   if(xml_nodes.size() == 0)
+   {
+      setErrorStatus();
+      if(traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG)
+            << MODULE << " DEBUG:"
+            << "\nCould not find: " << xpath
+            << std::endl;
+      }
+      return false;
+   }
+
+   node = xml_nodes.begin();
+   while (node != xml_nodes.end())
+   {
+      sub_nodes.clear();
+      xpath = "polLayer";
+      (*node)->findChildNodes(xpath, sub_nodes);
+      if (sub_nodes.size() == 0)
+      {
+         setErrorStatus();
+         if(traceDebug())
+         {
+            ossimNotify(ossimNotifyLevel_DEBUG)
+               << MODULE << " DEBUG:"
+               << "\nCould not find: " << xpath
+               << std::endl;
+         }
+         return false;
+      }
+      polLayerName = sub_nodes[0]->getText();
+	
+      sub_nodes.clear();
+      xpath = "file/location/filename";
+      (*node)->findChildNodes(xpath, sub_nodes);
+      if (sub_nodes.size() == 0)
+      {
+         setErrorStatus();
+         if(traceDebug())
+         {
+            ossimNotify(ossimNotifyLevel_DEBUG)
+               << MODULE << " DEBUG:"
+               << "\nCould not find: " << xpath
+               << std::endl;
+         }
+         return false;
+      }
+      polLayerFileName = sub_nodes[0]->getText();
+
+      if (polLayerFileName == imageFilename.file())
+      {
+         _polLayer = polLayerName;
+      }
+      ++node;
+   }
+   
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)<< MODULE << " leaving...\n";
+   }   
+   return true;
+}
+
+
+bool ossimplugins::ossimTerraSarModel::initCalibration(
+   const ossimXmlDocument* xmlDocument, const ossimTerraSarProductDoc& /* tsDoc */ )
+{
+   ossimString xpath;
+   ossimString polLayerName;
+   std::vector<ossimRefPtr<ossimXmlNode> > xml_nodes;
+   std::vector<ossimRefPtr<ossimXmlNode> > sub_nodes;
+   std::vector<ossimRefPtr<ossimXmlNode> >::iterator node;
+
+   static const char MODULE[] = "ossimplugins::ossimTerraSarModel::initCalibration";
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)<< MODULE << " entering...\n";
+   }   
+
+   _calFactor.resize(_numberOfLayers);
+      
+   xml_nodes.clear();
+   xpath = "/level1Product/calibration/calibrationConstant";
+
+   xmlDocument->findNodes(xpath, xml_nodes);
+   if(xml_nodes.size() == 0)
+   {
+      setErrorStatus();
+      if(traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG)
+            << MODULE << " DEBUG:"
+            << "\nCould not find: " << xpath
+            << std::endl;
+      }
+      return false;
+   }
+
+   node = xml_nodes.begin();
+   while (node != xml_nodes.end())
+   {
+      sub_nodes.clear();
+      xpath = "polLayer";
+      (*node)->findChildNodes(xpath, sub_nodes);
+      if (sub_nodes.size() == 0)
+      {
+         setErrorStatus();
+         if(traceDebug())
+         {
+            ossimNotify(ossimNotifyLevel_DEBUG)
+               << MODULE << " DEBUG:"
+               << "\nCould not find: " << xpath
+               << std::endl;
+         }
+         return false;
+      }
+    
+      polLayerName = sub_nodes[0]->getText();
+
+      ossim_uint32 polLayerIdx = 0;
+      bool polLayerIdxFound = false;
+    
+      for(ossim_uint32 idx = 0 ; idx < _polLayerList.size(); ++idx)
+      {
+         if(_polLayerList[idx] == polLayerName)
+         {
+            polLayerIdx = idx;
+            polLayerIdxFound = true;
+         }    
+      }  
+
+      if(!polLayerIdxFound)
+      {
+         setErrorStatus();
+         if(traceDebug())
+         {
+            ossimNotify(ossimNotifyLevel_DEBUG)
+               << MODULE << " DEBUG: Unable to found polLayer in polLayer List" << std::endl;
+         }
+         return false;	
+      }
+	
+      sub_nodes.clear();
+      xpath = "calFactor";
+      (*node)->findChildNodes(xpath, sub_nodes);
+      if (sub_nodes.size() == 0)
+      {
+    	 setErrorStatus();
+         if(traceDebug())
+         {
+            ossimNotify(ossimNotifyLevel_DEBUG)
+               << MODULE << " DEBUG:"
+               << "\nCould not find: " << xpath
+               << std::endl;
+         }
+         return false;
+      }
+      _calFactor[polLayerIdx] = sub_nodes[0]->getText().toDouble();
+      ++node;
+   }
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)<< MODULE << " leaving...\n";
+   }   
+
+   return true;
+}
+
+
+bool ossimplugins::ossimTerraSarModel::findTSXLeader(const ossimFilename& file,
+                                                     ossimFilename& metadataFile)
+{
+   bool res = false;
+
+   if ( file.exists() && (file.ext().downcase() == "xml") )
+   {
+      metadataFile = file;
+      res = true;
+   }
+   else if (!file.exists())
+   {
+      res = false;
+   }
+   else
+   {
+      if (traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG)
+            << "ossimplugins::ossimTerraSarModel::findTSXLeader "
+            << " directory scan turned off.  This is killing the factory open."
+            << " We should never scan a directory.  Need to resolve. "
+            << std::endl;
+      }
+
+#if 0
+      ossimFilename imagePath = file.path();
+      if (imagePath.empty())
+         imagePath = ossimEnvironmentUtility::instance()->getCurrentWorkingDir();
+
+      ossimDirectory directory = ossimDirectory(imagePath.path());
+      std::vector<ossimFilename> vectName;
+      ossimString reg = ".xml";
+      directory.findAllFilesThatMatch( vectName, reg, 1 );
+
+      bool goodFileFound = false;
+      unsigned int loop = 0;
+      while(loop<vectName.size() && !goodFileFound)
+      {
+         ossimFilename curFile = vectName[loop];
+         if(curFile.file().beforePos(3) == ossimString("TSX"))
+            goodFileFound = true;
+         else
+            loop++;
+      }
+      if(goodFileFound)
+      {
+         metadataFile = vectName[loop];
+         res = true;
+      }
+      else
+      {
+         if (traceDebug())
+         {
+            if (res)
+            {
+               this->print(ossimNotify(ossimNotifyLevel_DEBUG));
+            }
+            
+            ossimNotify(ossimNotifyLevel_DEBUG)
+               << "ossimplugins::ossimTerraSarModel::findTSXLeader "
+               << " exit status = " << (res?"true":"false\n")
+               << std::endl;
+         }
+      }
+#endif	  
+   }
+
+   return res;
+}
+
+
+void ossimplugins::ossimTerraSarModel::printInfo(ostream& os) const
+{
+   os << "\n----------------- General Info on TSX-1 Image -------------------"
+      << "\n  "
+      << "\n  Sensor ID :               			" << theSensorID
+      << "\n  Imaging Mode :               			" << _imagingMode
+      << "\n  Acquisition Sensor :        			" << _acquisitionSensor
+      << "\n  Look direction :          			" << _lookDirection
+      << "\n  Polarisation Mode :          			" << _polarisationMode
+      << "\n  Number of Layers :           			" << _numberOfLayers
+      << "\n  Polarisation List Size :     			" << _polLayerList.size()
+      << "\n"
+      << "\n------------------------------------------------------------------";
+   for(ossim_uint32 idx = 0 ; idx < _polLayerList.size(); ++idx)
+   {
+      os << "\n----------------- Info on " << _polLayerList[idx] <<" Layer Image -------------------"
+         << "\n calFactor :                                  " << _calFactor[idx]
+//               << "\n Image Noise  size :                          " << _noise[idx].get_imageNoise().size()
+         << "\n------------------------------------------------------------";
+   }  
+   os << std::endl;	
+}
+
+
diff --git a/ossim_plugins/ossim/ossimTerraSarModel.h b/ossim_plugins/ossim/ossimTerraSarModel.h
new file mode 100644
index 0000000..cb58aeb
--- /dev/null
+++ b/ossim_plugins/ossim/ossimTerraSarModel.h
@@ -0,0 +1,330 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+// 
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef ossimTerraSarModel_H
+#define ossimTerraSarModel_H
+
+#include <ossimPluginConstants.h>
+#include <ossimGeometricSarSensorModel.h>
+#include <ossim/projection/ossimMapProjection.h>
+#include <ossim/base/ossimIpt.h>
+#include <ossim/base/ossimFilename.h>
+#include <ossim/base/ossimGpt.h>
+#include <ossim/base/ossimDpt.h>
+#include <ossim/base/ossimString.h>
+#include <iostream>
+#include <list>
+
+#include <otb/CivilDateTime.h>
+#include <otb/Noise.h>
+#include <otb/SceneCoord.h>
+
+// Forward class declarations outside of namespace ossimplugins.
+class ossimXmlDocument;
+
+namespace ossimplugins
+{
+   // Forward class declarations inside of namespace ossimplugins.
+   class ossimTerraSarProductDoc;
+   
+   /**
+    * @brief This class allows for direct localisation and indirect localisation
+    * using the TerraSar sensor model
+    */
+   class OSSIM_PLUGINS_DLL ossimTerraSarModel :
+   public ossimplugins::ossimGeometricSarSensorModel
+   {
+   public:
+      /** @brief default constructor */
+      ossimTerraSarModel();
+      
+      /** @brief copy constructor */
+      ossimTerraSarModel(const ossimTerraSarModel& rhs);
+      
+      /** @brief Destructor */
+      virtual ~ossimTerraSarModel();
+      
+      /**
+       * @brief Method to return the class name.
+       * @return The name of this class.
+       */
+      virtual ossimString getClassName()   const;
+
+      /**
+       * @brief Returns pointer to a new instance, copy of this.
+       */
+      virtual ossimObject* dup() const;
+
+      /**
+       * @brief This function associates an image column number to a slant
+       * range when the image is georeferenced (ground projected).
+       * @param col Column coordinate of the image point
+       */
+      virtual double getSlantRangeFromGeoreferenced(double col) const;
+
+      /**
+       * @brief Method to intantial model from a file.  Attempts to find the
+       * required xml file.
+       *
+       * @param file
+       *
+       * @return true on success, false on error.
+       */
+      bool open(const ossimFilename& file);
+
+      /**
+       * @brief Method to save object state to a keyword list.
+       * @param kwl Keyword list to save to.
+       * @param prefix added to keys when saved.
+       * @return true on success, false on error.
+       */
+      virtual bool saveState(ossimKeywordlist& kwl,
+                             const char* prefix=0) const;
+
+      /**
+       * @brief Method to the load (recreate) the state of the object from a
+       * keyword list. Return true if ok or false on error.
+       * @return true if load OK, false on error
+       */
+      virtual bool loadState (const ossimKeywordlist &kwl, const char *prefix=0);
+   
+      /*!
+       * METHOD: print()
+       * Fulfills base-class pure virtual. Dumps contents of object to ostream.
+       */
+      virtual std::ostream& print(std::ostream& out) const;
+
+      //---
+   	  // Convenient method to print important image info:
+      //---
+      void  printInfo (ostream& os) const;
+   
+      private:
+
+      virtual bool InitPlatformPosition(const ossimKeywordlist &kwl,
+                                        const char *prefix);
+      virtual bool InitSensorParams(const ossimKeywordlist &kwl,
+                                    const char *prefix);
+      virtual bool InitRefPoint(const ossimKeywordlist &kwl, const char *prefix);
+
+      /**
+       * @brief Initializes the Slant Range to Ground Range data sets : 
+       * _SrToGr_R0,_SrToGr_coeffs_number,_SrToGr_exponent,_SrToGr_coeffs,_nbCol
+       */
+      virtual bool InitSRGR(const ossimKeywordlist &kwl, const char *prefix);
+
+      /**
+       * @note This method must be called before initRefPoint.
+       */
+      bool initSRGR(const ossimXmlDocument* xdoc,
+                    const ossimTerraSarProductDoc& rsDoc);
+   
+      bool initPlatformPosition(const ossimXmlDocument* xdoc,
+                                const ossimTerraSarProductDoc& rsDoc);
+
+      bool initSensorParams(const ossimXmlDocument* xdoc,
+                            const ossimTerraSarProductDoc& rsDoc);
+
+      /**
+       * @brief Method to initialize RefPoint object from
+       * TerraSAR product xml file.
+       * @param xdoc Opened product xml file.
+       * @return true on success, false on error.
+       */
+      bool initRefPoint(const ossimXmlDocument* xdoc,
+                        const ossimTerraSarProductDoc& rsDoc);
+      /**
+       * @brief Method to initialize AcquisitionInfo parameters from
+       * TerraSAR product xml file.
+       * @param xdoc Opened product xml file.
+       * @return true on success, false on error.
+       */
+      bool initAcquisitionInfo( const ossimXmlDocument* xdoc, 
+                        const ossimTerraSarProductDoc& tsDoc);
+
+      /**
+       * @brief Method to initialize Calibration parameters from
+       * TerraSAR product xml file.
+       * @param xdoc Opened product xml file.
+       * @return true on success, false on error.
+       */
+	  bool initCalibration( const ossimXmlDocument* xmlDocument, 
+                        const ossimTerraSarProductDoc& tsDoc);
+
+      /**
+       * @brief Method to initialize InfoIncidenceAngle parameters from
+       * TerraSAR product xml file.
+       * @param xdoc Opened product xml file.
+       * @return true on success, false on error.
+       */
+      bool initSceneCoord(
+		     const ossimXmlDocument* xdoc, const ossimTerraSarProductDoc& tsDoc);
+
+      /**
+       * @brief Method to initialize ImageNoise parameters from
+       * TerraSAR product xml file.
+       * @param xdoc Opened product xml file.
+       * @return true on success, false on error.
+       */
+      bool initNoise( const ossimXmlDocument* xmlDocument, const ossimTerraSarProductDoc& tsDoc);
+
+      /**
+       * @brief Method to get ImageNoise parameters from
+       * TerraSAR product xml file at a given node.
+       * @param xdoc Opened product xml file.
+       * @return true on success, false on error.
+       */
+      bool getNoiseAtGivenNode( const ossimRefPtr<ossimXmlNode> xmlDocument, ossimplugins::Noise& noise);
+
+      /**
+       * @brief Method to find the metadata file
+       * TerraSAR file (image or xml).
+       * @param file image or metadata path.
+       * @param metadataFile matadata path.
+       * @return ture if mateadata found, false otherwise.
+       */
+      bool findTSXLeader(const ossimFilename& file, ossimFilename& metadataFile);
+
+
+      /**
+       * @brief Method to find the polLayer from the image file
+       * @param xdoc Opened product xml file.
+       * @param file image or metadata path.
+       * @return true on success, false on error.
+       */
+       bool getPolLayerFromImageFile( const ossimXmlDocument* xmlDocument, const ossimFilename& imageFilename);
+
+      /**
+       * @brief Slant Range TO Ground Range Projection reference point
+       */
+      double _SrToGr_R0;
+   
+      /**
+       * @brief Slant Range TO Ground Range Projection exponents
+       */
+      std::vector<int> _SrToGr_exponent;
+
+      /**
+       * @brief Slant Range TO Ground Range Projection coefficients
+       */
+      std::vector<double> _SrToGr_coeffs;
+      /**
+       * @brief Scene Center range time
+       */
+      double _sceneCenterRangeTime;
+   
+      /**
+       * @brief Slant Range TO Ground Range scaling factor at scene center
+       */
+      double _SrToGr_scaling_factor;
+
+      /**
+       * @brief alternative SRGR computation coefficients. Three doubles.
+       */
+      std::vector<double> _alt_srgr_coefset;
+
+      /**
+       * @brief ProductType.
+       */
+      ossimString _productType;
+
+      /**
+       * @brief RadiometricCorrection.
+       */
+      ossimString _radiometricCorrection;
+
+      /**
+       * @brief ImagingMode (AcquisitionInfo node).
+       */
+      ossimString _imagingMode;
+
+      /**
+       * @brief Sensor (AcquisitionInfo node).
+       */
+      ossimString _acquisitionSensor;
+
+      /**
+       * @brief LookDirection (AcquisitionInfo node).
+       */
+      ossimString _lookDirection;
+
+      /**
+       * @brief PolarisationMode (AcquisitionInfo node).
+       */
+      ossimString _polarisationMode;
+
+      /**
+       * @brief PolLayer (AcquisitionInfo node).
+       */
+      ossimString _polLayer;      
+      std::vector<ossimString> _polLayerList;
+
+      /**
+       * @brief Noise (Noise node).
+       */
+      std::vector<Noise>  _noise;
+      
+      /**
+       * @brief SceneCoord (SceneInfo node)
+       */
+      SceneCoord *_sceneCoord;
+      
+      /**
+       * @brief CalFactor (Calibration node).
+       */
+      std::vector<double> _calFactor;
+
+      /**
+       * @brief centerFrequency (instrument node).
+       */
+      double _radarFrequency;
+
+      /**
+       * @brief number of layer (ImageDataInfo node).
+       */
+      ossim_uint32 _numberOfLayers;
+
+      /**
+       * @brief Azimuthal Start Time (Start acquisition time).
+       */
+      ossimString _azStartTime;
+
+      /**
+       * @brief Azimuthal Stop Time (Start acquisition time).
+       */
+      ossimString _azStopTime;
+
+      /**
+       * @brief First pixel Range Time (Start acquisition time in range direction).
+       */
+      ossimString _rgFirstPixelTime;
+
+      /**
+       * @brief Last pixel Range Time (Start acquisition time in range direction).
+       */
+      ossimString _rgLastPixelTime;
+
+
+      /**
+       * @brief Generation time.
+       */
+       ossimString _generationTime;
+
+      ossimFilename theProductXmlFile;
+
+      TYPE_DATA
+
+   };
+
+} // End: namespace ossimplugins
+
+#endif /* #ifndef ossimTerraSarModel_H */
+
diff --git a/ossim_plugins/ossim/ossimTerraSarProductDoc.cpp b/ossim_plugins/ossim/ossimTerraSarProductDoc.cpp
new file mode 100644
index 0000000..1cfe92c
--- /dev/null
+++ b/ossim_plugins/ossim/ossimTerraSarProductDoc.cpp
@@ -0,0 +1,1477 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Description: Utility class to encapsulate parsing TerraSAR-X product.xml
+// file.
+// 
+//----------------------------------------------------------------------------
+// $Id$
+
+#include <ossimTerraSarProductDoc.h>
+#include <ossimPluginCommon.h>
+#include <otb/Ephemeris.h>
+#include <otb/GeographicEphemeris.h>
+#include <otb/JSDDateTime.h>
+#include <otb/CivilDateTime.h>
+#include <otb/PlatformPosition.h>
+#include <otb/SarSensor.h>
+#include <otb/SensorParams.h>
+#include <otb/RefPoint.h>
+#include <otb/Noise.h>
+#include <otb/ImageNoise.h>
+#include <otb/SceneCoord.h>
+#include <otb/InfoSceneCoord.h>
+#include <ossim/base/ossimDpt.h>
+#include <ossim/base/ossimFilename.h>
+#include <ossim/base/ossimGpt.h>
+#include <ossim/base/ossimIpt.h>
+#include <ossim/base/ossimNotify.h>
+#include <ossim/base/ossimRefPtr.h>
+#include <ossim/base/ossimString.h>
+#include <ossim/base/ossimTrace.h>
+#include <ossim/base/ossimXmlDocument.h>
+#include <ossim/base/ossimXmlNode.h>
+
+// Static trace for debugging
+static ossimTrace traceDebug("ossimTerraSarProductDoc:debug");
+
+
+ossimplugins::ossimTerraSarProductDoc::ossimTerraSarProductDoc()
+{
+}
+
+ossimplugins::ossimTerraSarProductDoc::~ossimTerraSarProductDoc()
+{
+}
+
+bool ossimplugins::ossimTerraSarProductDoc::isTerraSarX(
+   const ossimXmlDocument* xdoc) const
+{
+   bool result = false;
+   if (xdoc)
+   {
+      ossimString s;
+      getMission(xdoc, s);
+      s.upcase();
+      if ( (s == "TSX-1") || (s == "TDX-1") )
+      {
+         result = true;
+      }
+   }
+   return result;
+}
+
+bool ossimplugins::ossimTerraSarProductDoc::initPlatformPosition(
+   const ossimXmlDocument* xdoc, ossimplugins::PlatformPosition* pos) const
+{
+   static const char MODULE[] =
+      "ossimplugins::ossimTerraSarProductDoc::initPlatformPosition";
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)<< MODULE << " entered...\n";
+   }  
+
+   bool result = true;
+   
+   if ( xdoc && pos )
+   {
+      // Get all the stateVector nodes.
+      ossimString path =
+         "/level1Product/platform/orbit/stateVec";
+      std::vector<ossimRefPtr<ossimXmlNode> > xnodes;
+      xdoc->findNodes(path, xnodes);
+      if ( xnodes.size() )
+      {
+         const std::vector<ossimRefPtr<ossimXmlNode> >::size_type COUNT =
+            xnodes.size();
+         
+         std::vector<Ephemeris*> ev;
+         
+         int nbrData = 0; // to keep track of good stateVector count.
+
+         ossimRefPtr<ossimXmlNode> svNode = 0; // stateVector node
+
+         for (ossim_uint32 i = 0 ; i < COUNT; ++i)
+         {
+            svNode = xnodes[i];
+            if ( !svNode )
+            {
+               result = false;
+               break;
+            }
+
+            ossimString s;
+
+            // TSX ephemerisis quality indicator (1:good, 0: wrong)
+            svNode->getAttributeValue(s, "qualInd");
+
+            if (s == "1")
+            {
+               double pos[3];
+               double vit[3];
+               CivilDateTime eph_civil_date;
+               
+               path = "timeUTC";
+               result = ossim::findFirstNode(path, svNode, s);
+               if (result)
+               {
+                  ossim::iso8601TimeStringToCivilDate(s, eph_civil_date);
+               }
+               else
+               {
+                  result = false;
+                  ossimNotify(ossimNotifyLevel_WARN)
+                     << MODULE << " ERROR:\nNode not found: " << path
+                     << std::endl;
+                  break;
+               }
+
+               path = "posX";
+               result = ossim::findFirstNode(path, svNode, s);
+               if (result)
+               {
+                  pos[0] = s.toDouble();
+               }
+               else
+               {
+                  result = false;
+                  ossimNotify(ossimNotifyLevel_WARN)
+                     << MODULE << " ERROR:\nNode not found: " << path
+                     << std::endl;
+                  break;
+               }
+
+               path = "posY";
+               result = ossim::findFirstNode(path, svNode, s);
+               if (result)
+               {
+                  pos[1] = s.toDouble();
+               }
+               else
+               {
+                  result = false;
+                  ossimNotify(ossimNotifyLevel_WARN)
+                     << MODULE << " ERROR:\nNode not found: " << path
+                     << std::endl;
+                  break;
+               }
+
+               path = "posZ";
+               result = ossim::findFirstNode(path, svNode, s);
+               if (result)
+               {
+                  pos[2] = s.toDouble();
+               }
+               else
+               {
+                  result = false;
+                  ossimNotify(ossimNotifyLevel_WARN)
+                     << MODULE << " ERROR:\nNode not found: " << path
+                     << std::endl;
+                  break;
+               }
+               
+               path = "velX";
+               result = ossim::findFirstNode(path, svNode, s);
+               if (result)
+               {
+                  vit[0] = s.toDouble();
+               }
+               else
+               {
+                  result = false;
+                  ossimNotify(ossimNotifyLevel_WARN)
+                     << MODULE << " ERROR:\nNode not found: " << path
+                     << std::endl;
+                  break;
+               }
+               
+               path = "velY";
+               result = ossim::findFirstNode(path, svNode, s);
+               if (result)
+               {
+                  vit[1] = s.toDouble();
+               }
+               else
+               {
+                  result = false;
+                  ossimNotify(ossimNotifyLevel_WARN)
+                     << MODULE << " ERROR:\nNode not found: " << path
+                     << std::endl;
+                  break;
+               }
+               
+               path = "velZ";
+               result = ossim::findFirstNode(path, svNode, s);
+               if (result)
+               {
+                  vit[2] = s.toDouble();
+               }
+               else
+               {
+                  result = false;
+                  ossimNotify(ossimNotifyLevel_WARN)
+                     << MODULE << " ERROR:\nNode not found: " << path
+                     << std::endl;
+                  break;
+               }
+               
+               JSDDateTime eph_jsd_date(eph_civil_date);
+               GeographicEphemeris* eph =
+                  new GeographicEphemeris(eph_jsd_date, pos, vit);
+               ev.push_back(eph);
+               ++nbrData;
+            }  // matches: if (s == "1")
+               
+   } // matches: for (ossim_uint32 i = 0 ; i < COUNT; ++i)
+
+         if (result && ev.size())
+         {
+            Ephemeris** ephemeris = new Ephemeris*[ev.size()];
+            for ( std::vector<Ephemeris*>::size_type evIdx = 0;
+                  evIdx < ev.size();
+                  ++evIdx )
+            {
+               ephemeris[evIdx] = ev[evIdx];
+            }
+            if (traceDebug())
+            {
+               ossimNotify(ossimNotifyLevel_DEBUG)
+                  << " DEBUG\nnbrData:  " << nbrData << "\n";
+            } 
+            pos->setData(ephemeris, nbrData);
+         }
+         else
+         {
+            std::vector<Ephemeris*>::iterator evIdx = ev.begin();
+            while (evIdx != ev.end())
+            {
+               delete (*evIdx);
+               (*evIdx) = 0;
+            }
+            ev.clear();
+         }
+         
+      } // matches: if ( xnodes.size() )
+      else
+      {
+         result = false;
+         ossimNotify(ossimNotifyLevel_WARN)
+            << MODULE << " ERROR:\nNodes not found: " << path << std::endl;
+      }
+      
+   } // matches: if (xdoc && pos)
+   else
+   {
+      result = false;
+   }
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " exit status = " << (result?"true\n":"false\n");
+   } 
+
+   return result;
+}
+
+bool ossimplugins::ossimTerraSarProductDoc::initSensorParams(
+   const ossimXmlDocument* xdoc, SensorParams* sp) const
+{
+   bool result = true;
+
+   if (xdoc && sp)
+   {
+      ossimString s;
+
+      // Get the number of azimuth looks.
+      if ( getNumberOfAzimuthLooks(xdoc, s) )
+      {
+         sp->set_nAzimuthLook(s.toDouble());
+      }
+      else
+      {
+         result = false;
+      }
+
+      // Get the number of range looks.
+      if ( getNumberOfRangeLooks(xdoc, s) )
+      {
+         sp->set_nRangeLook(s.toDouble());
+      }
+      else
+      {
+         result = false;
+      }
+
+      // Get the nominal PRF
+      if ( getCommonPrf(xdoc, s) )
+      {
+         sp->set_prf(s.toDouble());
+      }
+      else
+      {
+         result = false;
+      }
+
+      // Get the radar wave length.
+      if ( getRadarCenterFrequency(xdoc, s) )
+      {
+         const double CLUM = 2.99792458e+8 ;
+         double waveLength = CLUM / s.toDouble();
+         sp->set_rwl(waveLength);
+      }
+      else
+      {
+         result = false;
+      }
+
+      if ( getLookDirection(xdoc, s) )
+      {
+         if (s.upcase() == "RIGHT")
+         {
+            sp->set_sightDirection(SensorParams::Right);
+         }
+         else
+         {
+            sp->set_sightDirection(SensorParams::Left);
+         }
+      }
+      else
+      {
+         result = false;
+      }
+
+      // Get the Sampling frequency.
+      if ( getCommonRsf(xdoc, s) )
+      {
+         sp->set_sf(s.toDouble());
+      }
+      else
+      {
+         result = false;
+      }
+
+      // Ellipsoid hard coded to WGS84.
+      const double SEMI_MAJOR = 6378137.0;
+      const double SEMI_MINOR = 6356752.3142;
+      sp->set_semiMajorAxis(SEMI_MAJOR);
+      sp->set_semiMinorAxis(SEMI_MINOR);
+      
+      if ( isProductGeoreferenced(xdoc) )
+      {
+         if ( getOrbitDirection(xdoc, s) )
+         {
+            int orbitDirectionSign;
+            if ( s.upcase() == "DESCENDING" )
+            {
+               orbitDirectionSign = 1 ;
+            }
+            else
+            {
+               orbitDirectionSign = -1 ;
+            }
+
+            if ( getImageDataStrartWith(xdoc, s) )
+            {
+               if (s=="EARLYAZNEARRG")
+               {
+                  sp->set_col_direction(orbitDirectionSign); 
+                  sp->set_lin_direction(orbitDirectionSign);
+               }
+               else if (s=="EARLYAZFARRG")
+               {
+                  sp->set_col_direction(-orbitDirectionSign);
+                  sp->set_lin_direction(orbitDirectionSign);
+               }
+               else if (s=="LATEAZNEARRG")
+               {
+                  sp->set_col_direction(orbitDirectionSign);
+                  sp->set_lin_direction(-orbitDirectionSign);
+               }
+               else if (s=="LATEAZFARRG") {
+                  sp->set_col_direction(-orbitDirectionSign);
+                  sp->set_lin_direction(-orbitDirectionSign);
+               }
+               else
+               {
+                  //---
+                  // COSAR Files are stored ing with early azimuth,
+                  // near range
+                  //---
+                  sp->set_col_direction(orbitDirectionSign);
+                  sp->set_lin_direction(orbitDirectionSign);
+               }
+            }
+            else
+            {
+               result = false;
+            }
+         }
+         else
+         {
+            result = false;
+         }
+         
+      } // matches: if ( isProductGeoreferenced(xdoc) )
+      else
+      {
+         sp->set_col_direction(1);
+         sp->set_lin_direction(1);
+      }
+      
+   } // matches: if (xdoc && sp)
+   else
+   {
+      result = false;
+   }
+   
+   return result;  
+}
+
+bool ossimplugins::ossimTerraSarProductDoc::initImageSize(
+   const ossimXmlDocument* xdoc, ossimIpt& imageSize) const
+{
+   bool result = true;
+
+   if (xdoc)
+   {
+      ossimString s;
+      if ( getNumberOfColumns(xdoc, s) )
+      {
+         imageSize.x = static_cast<ossim_int32>(s.toFloat64());
+      }
+      else
+      {
+         result = false;
+      }
+      if ( getNumberOfRows(xdoc, s) )
+      {
+         imageSize.y = static_cast<ossim_int32>(s.toFloat64());
+      }
+      else
+      {
+         result = false;
+      }
+   }
+   else
+   {
+      result = false;
+   }
+      
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimplugins::ossimTerraSarProductDoc::initImageSize DEBUG:\nimage size: "
+         << imageSize
+         << "\nexit status = " << (result?"true":"false")
+         << std::endl;
+   }
+   
+   return result;
+}
+
+bool ossimplugins::ossimTerraSarProductDoc::initGsd(
+const ossimXmlDocument* xdoc, ossimDpt& gsd) const
+{
+  bool result = true;
+  
+  if (xdoc)
+  {
+    ossimString s;
+    
+    if ( getProductVariant(xdoc, s) )
+    {
+      if (s == "SSC")
+      {
+        if ( getProjectedSpacingSlantRange(xdoc, s) )
+        {
+          gsd.x = s.toFloat64(); 
+        }
+        else
+        {
+          result = false;
+        }
+        if ( getProjectedSpacingAzimuth(xdoc, s) )
+        {
+          gsd.y = s.toFloat64(); 
+        }
+        else
+        {
+          result = false;
+        }
+      }
+      else
+      {
+        if ( getRowSpacing(xdoc, s) )
+        {
+          gsd.x = s.toFloat64(s);
+        }
+        else
+        {
+          result = false;
+        }
+        if ( getColumnSpacing(xdoc, s) )
+        {
+          gsd.y = s.toFloat64();
+        }
+        else
+        {
+          result = false;
+        }
+      }
+    }
+    else
+    {
+      result = false;
+    }
+  }
+  else
+  {
+    result = false;
+  }
+  
+  if (traceDebug())
+  {
+    ossimNotify(ossimNotifyLevel_DEBUG)
+    << "ossimplugins::ossimTerraSarProductDoc::initGsd DEBUG:\ngsd: "
+    << gsd
+    << "\nexit status = " << (result?"true":"false")
+    << std::endl;
+  }
+  
+  return result;
+}
+
+bool ossimplugins::ossimTerraSarProductDoc::initTiePoints(
+   const ossimXmlDocument* xdoc,
+   std::list<ossimGpt>& gcp,
+   std::list<ossimDpt>& icp) const
+{
+   static const char MODULE[] = "ossimplugins::ossimTerraSarProductDoc::initTiePoints";
+   
+   bool result = true;
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " DEBUG:\n";
+   }
+         
+   if (xdoc)
+   {
+      ossimString s;
+      ossimDpt dpt;
+      ossimGpt gpt;
+
+      // Get the height.
+      result = getSceneAverageHeight(xdoc, s);
+      if (result)
+      {
+         gpt.hgt = s.toFloat64();
+      }
+      
+      // Get the scene center.
+      result = getSceneCenterRefColumn(xdoc, s);
+      if (result)
+      {
+         dpt.x = s.toFloat64() - 1.0;
+      }
+      result = getSceneCenterRefRow(xdoc, s);
+      if (result)
+      {
+         dpt.y = s.toFloat64() - 1.0;
+      }
+      icp.push_back(dpt);
+
+      result = getSceneCenterLat(xdoc, s);
+      if (result)
+      {
+         gpt.lat = s.toFloat64();
+      }
+      result = getSceneCenterLon(xdoc, s);
+      if (result)
+      {
+         gpt.lon = s.toFloat64();
+      }
+      gcp.push_back(gpt);
+      
+      ossimString path =
+         "/level1Product/productInfo/sceneInfo/sceneCornerCoord";
+      std::vector<ossimRefPtr<ossimXmlNode> > xnodes;
+      xdoc->findNodes(path, xnodes);
+      if ( xnodes.size() )
+      {
+         for (ossim_uint32 i = 0; i < xnodes.size(); ++i)
+         {
+            if (xnodes[i].valid())
+            {
+               result = ossim::findFirstNode(ossimString("refRow"),
+                                             xnodes[i], s);
+               if (result)
+               {
+                  dpt.y = s.toDouble() - 1.0;
+               }
+               result = ossim::findFirstNode(ossimString("refColumn"),
+                                             xnodes[i], s);
+               if (result)
+               {
+                  dpt.x = s.toDouble() - 1.0;
+               }
+               icp.push_back(dpt);
+
+               if (traceDebug())
+               {
+                  ossimNotify(ossimNotifyLevel_DEBUG)
+                     << "dpt" << i << ": " << dpt
+                     << "\n";
+               }
+
+               result = ossim::findFirstNode(ossimString("lat"),
+                                             xnodes[i], s);
+               if (result)
+               {
+                  gpt.lat = s.toFloat64();
+               }
+               result = ossim::findFirstNode(ossimString("lon"),
+                                             xnodes[i], s);
+               if (result)
+               {
+                  gpt.lon = s.toDouble();
+               }
+               gcp.push_back(gpt);
+               
+               if (traceDebug())
+               {
+                  ossimNotify(ossimNotifyLevel_DEBUG)
+                     << "gpt" << i << ": " << gpt
+                     << "\n";
+               }
+               
+            } // matches: if (xnodes[i].valid())
+            else
+            {
+               result = false;
+            }
+            
+         } // mathches: for (ossim_uint32 i = 0; i < xnodes.size(); ++i)
+         
+      } // matches: if ( xnodes.size() )
+      else
+      {
+         result = false;  // No nodes found.
+      }
+   } // matches: if (xdoc)
+   else
+   {
+      result = false; // Null pointer passed in.
+   }
+   
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " DEBUG: exit status = " << (result?"true":"false")
+         << std::endl;
+   }
+   
+   return result;
+}
+
+bool ossimplugins::ossimTerraSarProductDoc::isProductGeoreferenced(
+   const ossimXmlDocument* xdoc) const
+{
+   bool result = false;
+   
+   ossimString s;
+   if ( getProjection(xdoc, s) )
+   {
+      result = (s == "GROUNDRANGE");
+   }
+
+   return result;
+}
+
+bool ossimplugins::ossimTerraSarProductDoc::getMission(
+   const ossimXmlDocument* xdoc, ossimString& s) const
+{
+   ossimString path = "/level1Product/generalHeader/mission";
+   ossim::getPath(path, xdoc, s);
+
+   return ossim::getPath(path, xdoc, s);
+}
+
+bool ossimplugins::ossimTerraSarProductDoc::geNumberOfLayers(
+   const ossimXmlDocument* xdoc, ossimString& s) const
+{
+   ossimString path = "/level1Product/productInfo/imageDataInfo/numberOfLayers";
+   ossim::getPath(path, xdoc, s);
+
+   return ossim::getPath(path, xdoc, s);
+}
+
+
+bool ossimplugins::ossimTerraSarProductDoc::getImageFile(
+   const ossimXmlDocument* xdoc, ossimString& s) const
+{
+   bool result = false;
+   ossimString subDir;
+   ossimString fileName;
+   
+   ossimString path = "/level1Product/productComponents/imageData/file/location/path";
+
+   if ( ossim::getPath(path, xdoc, subDir) )
+   {
+      path = "/level1Product/productComponents/imageData/file/location/filename";
+      if (  ossim::getPath(path, xdoc, fileName) )
+      {
+         result = true;
+         s = subDir;
+         s += "/";
+         s += fileName;
+      }
+   }
+   return result;
+}
+
+bool ossimplugins::ossimTerraSarProductDoc::getSceneId(
+   const ossimXmlDocument* xdoc, ossimString& s) const
+{
+   ossimString path = "/level1Product/productInfo/sceneInfo/sceneID";
+   return ossim::getPath(path, xdoc, s);
+}
+
+bool ossimplugins::ossimTerraSarProductDoc::getProjection(
+   const ossimXmlDocument* xdoc, ossimString& s) const
+{
+   ossimString path = "/level1Product/productInfo/productVariantInfo/projection";
+   return ossim::getPath(path, xdoc, s);
+}
+
+bool ossimplugins::ossimTerraSarProductDoc::getProductType(
+   const ossimXmlDocument* xdoc, ossimString& s) const
+{
+   ossimString path = "/level1Product/productInfo/productVariantInfo/productType";
+   return ossim::getPath(path, xdoc, s);
+}
+
+bool ossimplugins::ossimTerraSarProductDoc::getProductVariant(
+const ossimXmlDocument* xdoc, ossimString& s) const
+{
+  ossimString path = "/level1Product/productInfo/productVariantInfo/productVariant";
+  return ossim::getPath(path, xdoc, s);
+}
+
+bool ossimplugins::ossimTerraSarProductDoc::getRadiometricCorrection(
+   const ossimXmlDocument* xdoc, ossimString& s) const
+{
+   ossimString path = "/level1Product/productInfo/productVariantInfo/radiometricCorrection";
+   return ossim::getPath(path, xdoc, s);
+}
+
+
+bool ossimplugins::ossimTerraSarProductDoc::getReferencePoint(
+   const ossimXmlDocument* xdoc, ossimString& s) const
+ {
+    ossimString path = "/level1Product/productSpecific/projectedImageInfo/slantToGroundRangeProjection/referencePoint";
+    return ossim::getPath(path, xdoc, s);
+ }
+
+bool ossimplugins::ossimTerraSarProductDoc::getImageDataStrartWith(
+   const ossimXmlDocument* xdoc, ossimString& s) const
+{
+   bool result = true;
+   ossimString path = "/level1Product/productSpecific/complexImageInfo";
+   std::vector<ossimRefPtr<ossimXmlNode> > xnodes;
+   xdoc->findNodes(path, xnodes);
+   if ( xnodes.size() )
+   {
+      for (ossim_uint32 i = 0; i < xnodes.size(); ++i)
+      {
+         if (xnodes[i].valid())
+         {
+            result = ossim::findFirstNode(ossimString("imageDataStartWith"),
+                                          xnodes[i], s);
+         }
+      }
+   }
+   else
+   {
+      result=false;
+   }
+   return result;
+}
+
+bool ossimplugins::ossimTerraSarProductDoc::getOrbitDirection(
+   const ossimXmlDocument* xdoc, ossimString& s) const
+{
+   ossimString path = "/level1Product/productInfo/missionInfo/orbitDirection";
+   return ossim::getPath(path, xdoc, s);
+}
+
+bool ossimplugins::ossimTerraSarProductDoc::getLookDirection(
+   const ossimXmlDocument* xdoc, ossimString& s) const
+{
+   ossimString path =
+      "/level1Product/productInfo/acquisitionInfo/lookDirection";
+   return ossim::getPath(path, xdoc, s);
+}
+
+bool ossimplugins::ossimTerraSarProductDoc::getGenerationTime(
+    const ossimXmlDocument* xdoc, ossimString& s) const
+{
+   ossimString path =
+      "/level1Product/generalHeader/generationTime";
+   return ossim::getPath(path, xdoc, s);
+}
+
+bool ossimplugins::ossimTerraSarProductDoc::getRangeGateFirstPixel(
+   const ossimXmlDocument* xdoc, ossimString& s) const
+{
+   ossimString path = "/level1Product/productInfo/sceneInfo/rangeTime/firstPixel";
+   return ossim::getPath(path, xdoc, s);
+}
+
+bool ossimplugins::ossimTerraSarProductDoc::getRangeGateLastPixel(
+   const ossimXmlDocument* xdoc, ossimString& s) const
+{
+   ossimString path = "/level1Product/productInfo/sceneInfo/rangeTime/lastPixel";
+   return ossim::getPath(path, xdoc, s);
+}
+
+bool ossimplugins::ossimTerraSarProductDoc::getSceneCenterAzimuthTime(
+   const ossimXmlDocument* xdoc, ossimString& s) const
+{
+   ossimString path = "/level1Product/productInfo/sceneInfo/sceneCenterCoord/azimuthTimeUTC";
+   return ossim::getPath(path, xdoc, s);
+}
+
+bool ossimplugins::ossimTerraSarProductDoc::getSceneCenterRangeTime(
+   const ossimXmlDocument* xdoc, ossimString& s) const
+{
+   ossimString path = "/level1Product/productInfo/sceneInfo/sceneCenterCoord/rangeTime";
+   return ossim::getPath(path, xdoc, s);
+}
+
+bool ossimplugins::ossimTerraSarProductDoc::getSceneCenterRefColumn(
+   const ossimXmlDocument* xdoc, ossimString& s) const
+{
+   ossimString path = "/level1Product/productInfo/sceneInfo/sceneCenterCoord/refColumn";
+   return ossim::getPath(path, xdoc, s);
+}
+
+bool ossimplugins::ossimTerraSarProductDoc::getSceneCenterRefRow(
+   const ossimXmlDocument* xdoc, ossimString& s) const
+{
+   ossimString path = "/level1Product/productInfo/sceneInfo/sceneCenterCoord/refRow";
+   return ossim::getPath(path, xdoc, s);
+}
+
+bool ossimplugins::ossimTerraSarProductDoc::getSceneCenterLat(
+   const ossimXmlDocument* xdoc, ossimString& s) const
+{
+   ossimString path = "/level1Product/productInfo/sceneInfo/sceneCenterCoord/lat";
+   return ossim::getPath(path, xdoc, s);
+}
+
+bool ossimplugins::ossimTerraSarProductDoc::getSceneCenterLon(
+   const ossimXmlDocument* xdoc, ossimString& s) const
+{
+   ossimString path = "/level1Product/productInfo/sceneInfo/sceneCenterCoord/lon";
+   return ossim::getPath(path, xdoc, s);
+}
+
+bool ossimplugins::ossimTerraSarProductDoc::getSceneAverageHeight(
+   const ossimXmlDocument* xdoc, ossimString& s) const
+{
+   ossimString path =
+      "/level1Product/productInfo/sceneInfo/sceneAverageHeight";
+   return ossim::getPath(path, xdoc, s);
+}
+
+bool ossimplugins::ossimTerraSarProductDoc::getRadarCenterFrequency(
+   const ossimXmlDocument* xdoc, ossimString& s) const
+{
+   ossimString path =
+      "/level1Product/instrument/radarParameters/centerFrequency";
+   return ossim::getPath(path, xdoc, s);
+}
+
+bool ossimplugins::ossimTerraSarProductDoc::getAzimuthStartTime(
+   const ossimXmlDocument* xdoc, ossimString& s) const
+{
+  ossimString path = 
+    "/level1Product/productInfo/sceneInfo/start/timeUTC";
+
+  bool res = ossim::getPath(path, xdoc, s);
+
+  if(!res)
+  {
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)<< "Node \"/level1Product/productInfo/sceneInfo/start/timeUTC\" invalid, trying \"/level1Product/instrument/settings/rxGainSetting/startTimeUTC\"...\n";
+   }  
+    path = "/level1Product/instrument/settings/rxGainSetting/startTimeUTC";
+    res = ossim::getPath(path, xdoc, s);
+  }
+
+  return res;
+}
+
+bool ossimplugins::ossimTerraSarProductDoc::getAzimuthStopTime(
+   const ossimXmlDocument* xdoc, ossimString& s) const
+{
+  ossimString path = 
+    "/level1Product/productInfo/sceneInfo/stop/timeUTC";
+  
+  bool res = ossim::getPath(path, xdoc, s);
+  
+  if(!res)
+    {
+      if (traceDebug())
+        {
+          ossimNotify(ossimNotifyLevel_DEBUG)<< "Node \"/level1Product/productInfo/sceneInfo/stop/timeUTC\" invalid, trying \"/level1Product/instrument/settings/rxGainSetting/stopTimeUTC\"...\n";
+        }  
+      path = "/level1Product/instrument/settings/settingRecord/dataSegment segmentID/stopTimeUTC";
+      res = ossim::getPath(path, xdoc, s);
+    }
+  
+  return res;
+
+}
+
+bool ossimplugins::ossimTerraSarProductDoc::getRangeFirstPixelTime(
+   const ossimXmlDocument* xdoc, ossimString& s) const
+{
+  ossimString path =
+    "/level1Product/productInfo/sceneInfo/rangeTime/firstPixel";
+
+  bool res = ossim::getPath(path, xdoc, s);
+
+  return res;
+}
+
+bool ossimplugins::ossimTerraSarProductDoc::getRangeLastPixelTime(
+   const ossimXmlDocument* xdoc, ossimString& s) const
+{
+  ossimString path =
+    "/level1Product/productInfo/sceneInfo/rangeTime/lastPixel";
+
+  bool res = ossim::getPath(path, xdoc, s);
+
+  return res;
+}
+
+
+
+bool ossimplugins::ossimTerraSarProductDoc::getCommonPrf(
+   const ossimXmlDocument* xdoc, ossimString& s) const
+{
+   bool result = true;
+   ossimString path = "/level1Product/productSpecific/complexImageInfo";
+   std::vector<ossimRefPtr<ossimXmlNode> > xnodes;
+   xdoc->findNodes(path, xnodes);
+   if ( xnodes.size() )
+   {
+      for (ossim_uint32 i = 0; i < xnodes.size(); ++i)
+      {
+         if (xnodes[i].valid())
+         {
+            result = ossim::findFirstNode(ossimString("commonPRF"),
+                                          xnodes[i], s);
+         }
+      }
+   }
+   else
+   {
+      result=false;
+   }
+   return result;
+}
+
+bool ossimplugins::ossimTerraSarProductDoc::getCommonRsf(
+   const ossimXmlDocument* xdoc, ossimString& s) const
+{
+   bool result = true;
+   ossimString path = "/level1Product/productSpecific/complexImageInfo";
+   std::vector<ossimRefPtr<ossimXmlNode> > xnodes;
+   xdoc->findNodes(path, xnodes);
+   if ( xnodes.size() )
+   {
+      for (ossim_uint32 i = 0; i < xnodes.size(); ++i)
+      {
+         if (xnodes[i].valid())
+         {
+            result = ossim::findFirstNode(ossimString("commonRSF"),
+                                          xnodes[i], s);
+         }
+      }
+   }
+   else
+   {
+      result=false;
+   }
+   return result;
+}
+
+bool ossimplugins::ossimTerraSarProductDoc::getNumberOfRangeLooks(
+   const ossimXmlDocument* xdoc, ossimString& s) const
+{
+   bool result = true;
+   ossimString path = "/level1Product/processing/processingParameter";
+   std::vector<ossimRefPtr<ossimXmlNode> > xnodes;
+   xdoc->findNodes(path, xnodes);
+   if ( xnodes.size() )
+   {
+      for (ossim_uint32 i = 0; i < xnodes.size(); ++i)
+      {
+         if (xnodes[i].valid())
+         {
+            result = ossim::findFirstNode(ossimString("rangeLooks"),
+                                          xnodes[i], s);
+         }
+      }
+   }
+   else
+   {
+      result=false;
+   }
+   return result;
+}
+
+bool ossimplugins::ossimTerraSarProductDoc::getNumberOfAzimuthLooks(
+   const ossimXmlDocument* xdoc, ossimString& s) const
+{
+   bool result = true;
+   ossimString path = "/level1Product/processing/processingParameter";
+   std::vector<ossimRefPtr<ossimXmlNode> > xnodes;
+   xdoc->findNodes(path, xnodes);
+   if ( xnodes.size() )
+   {
+      for (ossim_uint32 i = 0; i < xnodes.size(); ++i)
+      {
+         if (xnodes[i].valid())
+         {
+            result = ossim::findFirstNode(ossimString("azimuthLooks"),
+                                          xnodes[i], s);
+         }
+      }
+   }
+   else
+   {
+      result=false;
+   }
+   return result;
+}
+
+bool ossimplugins::ossimTerraSarProductDoc::getNumberOfColumns(
+   const ossimXmlDocument* xdoc, ossimString& s) const
+{
+   ossimString path =
+      "/level1Product/productInfo/imageDataInfo/imageRaster/numberOfColumns";
+   return ossim::getPath(path, xdoc, s);
+}
+
+bool ossimplugins::ossimTerraSarProductDoc::getNumberOfRows(
+   const ossimXmlDocument* xdoc, ossimString& s) const
+{
+   ossimString path =
+      "/level1Product/productInfo/imageDataInfo/imageRaster/numberOfRows";
+   return ossim::getPath(path, xdoc, s);
+}
+
+bool ossimplugins::ossimTerraSarProductDoc::getColumnSpacing(
+   const ossimXmlDocument* xdoc, ossimString& s) const
+{
+   ossimString path =
+      "/level1Product/productInfo/imageDataInfo/imageRaster/columnSpacing";
+   return ossim::getPath(path, xdoc, s);
+}
+
+bool ossimplugins::ossimTerraSarProductDoc::getRowSpacing(
+   const ossimXmlDocument* xdoc, ossimString& s) const
+{
+   ossimString path =
+      "/level1Product/productInfo/imageDataInfo/imageRaster/rowSpacing";
+   return ossim::getPath(path, xdoc, s);
+}
+
+bool ossimplugins::ossimTerraSarProductDoc::getProjectedSpacingSlantRange(
+const ossimXmlDocument* xdoc, ossimString& s) const
+{
+  ossimString path =
+  "/level1Product/productSpecific/complexImageInfo/projectedSpacingRange/slantRange";
+  return ossim::getPath(path, xdoc, s);
+}
+
+bool ossimplugins::ossimTerraSarProductDoc::getProjectedSpacingAzimuth(
+const ossimXmlDocument* xdoc, ossimString& s) const
+{
+  ossimString path =
+  "/level1Product/productSpecific/complexImageInfo/projectedSpacingAzimuth";
+  return ossim::getPath(path, xdoc, s);
+}
+
+bool ossimplugins::ossimTerraSarProductDoc::getImagingMode(
+   const ossimXmlDocument* xdoc, ossimString& s) const
+{
+   ossimString path =
+      "/level1Product/productInfo/acquisitionInfo/imagingMode";
+   return ossim::getPath(path, xdoc, s);
+}
+
+bool ossimplugins::ossimTerraSarProductDoc::getAcquisitionSensor(
+   const ossimXmlDocument* xdoc, ossimString& s) const
+{
+   ossimString path =
+      "/level1Product/productInfo/acquisitionInfo/sensor";
+   return ossim::getPath(path, xdoc, s);
+}
+bool ossimplugins::ossimTerraSarProductDoc::getPolarisationMode(
+   const ossimXmlDocument* xdoc, ossimString& s) const
+{
+   ossimString path =
+      "/level1Product/productInfo/acquisitionInfo/polarisationMode";
+   return ossim::getPath(path, xdoc, s);
+}
+bool ossimplugins::ossimTerraSarProductDoc::getPolLayerList(
+   const ossimXmlDocument* xdoc, std::vector<ossimString>& s) const
+{
+   ossimString path =
+      "/level1Product/productInfo/acquisitionInfo/polarisationList/polLayer";
+   return ossim::getPath(path, xdoc, s);
+}
+bool ossimplugins::ossimTerraSarProductDoc::getCalFactor(
+   const ossimXmlDocument* xdoc, std::vector<ossimString>& s) const
+{
+   ossimString path =
+      "/level1Product/calibration/calibrationConstant/calFactor";
+   return ossim::getPath(path, xdoc, s);
+}
+bool ossimplugins::ossimTerraSarProductDoc::getRadarFrequency(
+   const ossimXmlDocument* xdoc, ossimString& s) const
+{
+   ossimString path =
+      "/level1Product/instrument/radarParameters/centerFrequency";
+   return ossim::getPath(path, xdoc, s);
+}
+/*bool ossimplugins::ossimTerraSarProductDoc::getCenterIncidenceAngle(
+   const ossimXmlDocument* xdoc, ossimString& s) const
+{
+   ossimString path =
+      "/level1Product/productInfo/sceneInfo/sceneCenterCoord/incidenceAngle";
+   return ossim::getPath(path, xdoc, s);
+}
+bool ossimplugins::ossimTerraSarProductDoc::getCornerIncidenceAngles(
+    const ossimXmlDocument* xdoc, std::vector<ossimString>& s) const
+{
+  bool result = true;
+  ossim_uint32 refRow = 0;
+  ossim_uint32 refColumn = 0;
+  double incidenceAngle = 0.;
+  ossimString stmp;
+  ossimString path = "/level1Product/productInfo/sceneInfo/sceneCornerCoord";
+  std::vector<ossimRefPtr<ossimXmlNode> > xnodes;
+  xdoc->findNodes(path, xnodes);
+  if (( xnodes.size() ) && (xnodes.size() == 4))
+  {
+    for (ossim_uint32 i = 0; i < xnodes.size(); ++i)
+    {
+      if (xnodes[i].valid())
+      {
+        result = ossim::findFirstNode(ossimString("refRow"), xnodes[i], stmp);
+        refRow = stmp.toUInt32();
+        result = ossim::findFirstNode(ossimString("refColumn"), xnodes[i], stmp);
+        refColumn = stmp.toUInt32();
+        result = ossim::findFirstNode(ossimString("incidenceAngle"), xnodes[i], stmp);
+        // values in vector are indexed with this order
+        //   0 -> lower left
+        //   1 -> upper left
+        //   2 -> upper right
+        //   3 -> lower right
+        
+        if (refRow == 1)
+        {
+          if (refColumn == 1)
+          {
+            s[0] = stmp;
+          }
+          else
+          {
+            s[3] = stmp;
+          }
+        }
+        else
+        {
+          if (refColumn == 1)
+          {
+            s[1] = stmp;
+          }
+          else
+          {
+            s[2] = stmp;
+          }
+        }
+      }
+    }
+  }
+  else
+  {
+    result = false;
+  }
+  
+  return result;
+}*/
+bool ossimplugins::ossimTerraSarProductDoc::initSceneCoord(const ossimXmlDocument* xdoc, ossimplugins::SceneCoord* sceneCoord) const
+{
+  static const char MODULE[] = "ossimplugins::ossimTerraSarProductDoc::initSceneCoord";
+  if (traceDebug())
+  {
+    ossimNotify(ossimNotifyLevel_DEBUG)<< MODULE << " entered...\n";
+  }
+
+  bool result = true;
+
+  if ( xdoc && sceneCoord )
+  {
+    ossimString stmp;
+
+    ossimString path = "/level1Product/productInfo/sceneInfo/sceneCenterCoord";
+    std::vector<ossimRefPtr<ossimXmlNode> > xnodes;
+    xdoc->findNodes(path, xnodes);
+        
+    if ( (xnodes.size() == 1) && (xnodes[0].valid()) )
+    {
+      InfoSceneCoord isc;
+      
+      result = ossim::findFirstNode(ossimString("refRow"), xnodes[0], stmp);
+      isc.set_refRow( stmp.toUInt32() );
+      result = ossim::findFirstNode(ossimString("refColumn"), xnodes[0], stmp);
+      isc.set_refColumn( stmp.toUInt32() );
+      result = ossim::findFirstNode(ossimString("lat"), xnodes[0], stmp);
+      isc.set_lat( stmp.toDouble() );
+      result = ossim::findFirstNode(ossimString("lon"), xnodes[0], stmp);
+      isc.set_lon( stmp.toDouble() );
+      result = ossim::findFirstNode(ossimString("azimuthTimeUTC"), xnodes[0], stmp);
+      isc.set_azimuthTimeUTC( stmp );
+      result = ossim::findFirstNode(ossimString("rangeTime"), xnodes[0], stmp);
+      isc.set_rangeTime( stmp.toDouble() );
+      result = ossim::findFirstNode(ossimString("incidenceAngle"), xnodes[0], stmp);
+      isc.set_incidenceAngle( stmp.toDouble() );
+        
+      sceneCoord->set_centerSceneCoord(isc);
+      
+      ossimString path2 = "/level1Product/productInfo/sceneInfo/sceneCornerCoord";
+      std::vector<ossimRefPtr<ossimXmlNode> > xnodes2;
+      
+      xdoc->findNodes(path2, xnodes2);
+      if ( xnodes2.size() )
+      {
+        std::vector<InfoSceneCoord> tabIsc;
+        
+        for (ossim_uint32 i = 0; i < xnodes2.size(); ++i)
+        {
+          if (xnodes2[i].valid())
+          {
+            InfoSceneCoord isc2;
+            
+            result = ossim::findFirstNode(ossimString("refRow"), xnodes2[i], stmp);
+            isc2.set_refRow( stmp.toUInt32() );
+            result = ossim::findFirstNode(ossimString("refColumn"), xnodes2[i], stmp);
+            isc2.set_refColumn( stmp.toUInt32() );
+            result = ossim::findFirstNode(ossimString("lat"), xnodes[0], stmp);
+            isc2.set_lat( stmp.toDouble() );
+            result = ossim::findFirstNode(ossimString("lon"), xnodes[0], stmp);
+            isc2.set_lon( stmp.toDouble() );
+            result = ossim::findFirstNode(ossimString("azimuthTimeUTC"), xnodes[0], stmp);
+            isc2.set_azimuthTimeUTC( stmp );
+            result = ossim::findFirstNode(ossimString("rangeTime"), xnodes[0], stmp);
+            isc2.set_rangeTime( stmp.toDouble() );
+            result = ossim::findFirstNode(ossimString("incidenceAngle"), xnodes2[i], stmp);
+            isc2.set_incidenceAngle( stmp.toDouble() );
+
+            tabIsc.push_back(isc2);
+          }
+        }
+        
+        sceneCoord->set_cornersSceneCoord( tabIsc );
+        sceneCoord->set_numberOfSceneCoord( tabIsc.size() );
+      }
+    }
+    else
+    {
+      result = false;
+    }
+  }
+  
+  return result;
+}
+
+bool ossimplugins::ossimTerraSarProductDoc::initNoise(
+   const ossimXmlDocument* xdoc, ossimplugins::Noise* noise) const
+{
+   static const char MODULE[] =
+      "ossimplugins::ossimTerraSarProductDoc::initImageNoise";
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)<< MODULE << " entered...\n";
+   }  
+
+   bool result = true;
+
+   if ( xdoc && noise )
+   {
+      ossimString path =
+      "/level1Product/noise/numberOfNoiseRecords";
+      ossimString s;
+      ossim::getPath(path, xdoc, s);
+      std::vector<ImageNoise> tabImageNoise;
+      tabImageNoise.clear();
+      noise->set_numberOfNoiseRecords(s.toInt32());
+
+      // Get all the stateVector nodes.
+      path =
+         "/level1Product/noise/imageNoise";
+      std::vector<ossimRefPtr<ossimXmlNode> > xnodes;
+      xdoc->findNodes(path, xnodes);
+      if ( xnodes.size() )
+      {
+         const std::vector<ossimRefPtr<ossimXmlNode> >::size_type COUNT =
+            xnodes.size();
+//         ossim::iso8601TimeStringToCivilDate(
+         
+         int nbrData = 0; // to keep track of good stateVector count.
+
+         ossimRefPtr<ossimXmlNode> svNode = 0; // stateVector node
+
+         for (ossim_uint32 i = 0 ; i < COUNT; ++i)
+         { 
+            ImageNoise ev;
+            svNode = xnodes[i];
+            if ( !svNode )
+            {
+               result = false;
+               break;
+            }
+
+            ossimString s;
+
+               path = "timeUTC";
+               result = ossim::findFirstNode(path, svNode, s);
+               if (result)
+               {
+                  ev.set_timeUTC(s);
+               }
+               else
+               {
+                  result = false;
+                  ossimNotify(ossimNotifyLevel_WARN)
+                     << MODULE << " ERROR:\nNode not found: " << path
+                     << std::endl;
+                  break;
+               }
+
+               path = "noiseEstimate/validityRangeMin";
+               result = ossim::findFirstNode(path, svNode, s);
+               if (result)
+               {
+                  ev.set_validityRangeMin( s.toDouble() );
+               }
+               else
+               {
+                  result = false;
+                  ossimNotify(ossimNotifyLevel_WARN)
+                     << MODULE << " ERROR:\nNode not found: " << path
+                     << std::endl;
+                  break;
+               }
+               path = "noiseEstimate/validityRangeMax";
+               result = ossim::findFirstNode(path, svNode, s);
+               if (result)
+               {
+                  ev.set_validityRangeMax( s.toDouble() );
+               }
+               else
+               {
+                  result = false;
+                  ossimNotify(ossimNotifyLevel_WARN)
+                     << MODULE << " ERROR:\nNode not found: " << path
+                     << std::endl;
+                  break;
+               }
+               path = "noiseEstimate/referencePoint";
+               result = ossim::findFirstNode(path, svNode, s);
+               if (result)
+               {
+                  ev.set_referencePoint( s.toDouble() );
+               }
+               else
+               {
+                  result = false;
+                  ossimNotify(ossimNotifyLevel_WARN)
+                     << MODULE << " ERROR:\nNode not found: " << path
+                     << std::endl;
+                  break;
+               }
+               path = "noiseEstimate/polynomialDegree";
+               result = ossim::findFirstNode(path, svNode, s);
+               if (result)
+               {
+                  ev.set_polynomialDegree( s.toInt32() );
+               }
+               else
+               {
+                  result = false;
+                  ossimNotify(ossimNotifyLevel_WARN)
+                     << MODULE << " ERROR:\nNode not found: " << path
+                     << std::endl;
+                  break;
+               }
+               //Read Coefficient
+
+               ossimXmlNode::ChildListType nodelist;
+               svNode->findChildNodes("noiseEstimate/coefficient",nodelist);
+
+               ossimXmlNode::ChildListType::const_iterator child_iter = nodelist.begin();
+               std::vector<double> polynomialCoefficients;
+               while(child_iter != nodelist.end())
+               {
+                  double coefficient = ((*child_iter)->getText()).toDouble() ;
+                  polynomialCoefficients.push_back(coefficient);
+                  ++child_iter;
+               }                  
+               ev.set_polynomialCoefficients( polynomialCoefficients );
+
+              tabImageNoise.push_back(ev);
+               ++nbrData;
+
+               
+         } // matches: for (ossim_uint32 i = 0 ; i < COUNT; ++i)
+
+        noise->set_imageNoise(tabImageNoise);
+         
+      } // matches: if ( xnodes.size() )
+      
+   } // matches: if (xdoc && pos)
+   else
+   {
+      result = false;
+   }
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " exit status = " << (result?"true\n":"false\n");
+   } 
+
+   return result;
+}
+
+
+
+
+
+
+
+
diff --git a/ossim_plugins/ossim/ossimTerraSarProductDoc.h b/ossim_plugins/ossim/ossimTerraSarProductDoc.h
new file mode 100644
index 0000000..8fa89a9
--- /dev/null
+++ b/ossim_plugins/ossim/ossimTerraSarProductDoc.h
@@ -0,0 +1,281 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author:  David Burken
+//
+// Description: Utility class to encapsulate parsing TerraSAR-X product.xml
+// file.
+// 
+//----------------------------------------------------------------------------
+// $Id$
+#ifndef ossimTerraSarProductDoc_HEADER
+#define ossimTerraSarProductDoc_HEADER 1
+
+#include <list>
+#include <string>
+#include <vector>
+#include <ossim/base/ossimConstants.h>
+#include <ossim/base/ossimRefPtr.h>
+
+// Forward class declarations outside of namespace ossimplugins.
+class ossimDpt;
+class ossimGpt;
+class ossimIpt;
+class ossimXmlDocument;
+class ossimXmlNode;
+class ossimString;
+
+namespace ossimplugins
+{
+   // Forward class declarations inside of namespace ossimplugins.
+   class CivilDateTime;
+   class PlatformPosition;
+   class RefPoint;
+   class SensorParams;
+   class Noise;
+   class SceneCoord;
+
+   /** @brief Class to encapsulate parsing TerraSAR product xml file. */
+   class ossimTerraSarProductDoc
+   {
+   public:
+      /** @brief default constructor */
+      ossimTerraSarProductDoc();
+      
+      /** @brief destructor */
+      ~ossimTerraSarProductDoc();
+      
+      /**
+       * @brief Checks for node /level1Product/generalHeader/mission containing
+       * "TSX-1".
+       * 
+       * @return true if present, false if not.
+       */
+      bool isTerraSarX(const ossimXmlDocument* xdoc) const;
+      
+      /**
+       * @brief Method to initialize PlatformPosition object from
+       * TerraSAR  product xml file.
+       * @param xdoc Opened product xml file.
+       * @param pos Pointer to PlatformPosition object.
+       * @return true on success, false on error.
+       */
+      bool initPlatformPosition(const ossimXmlDocument* xdoc,
+                                PlatformPosition* pos) const;
+      
+      /**
+       * @brief Method to initialize SensorParams object from
+       * TerraSAR product xml file.
+       * @param xdoc Opened product.xml file.
+       * @param sp Pointer to SensorParams object.
+       * @return true on success, false on error.
+       */
+      bool initSensorParams(const ossimXmlDocument* xdoc,
+                            SensorParams* sp) const;
+      
+      /**
+       * @brief Method to initialize image size from
+       * TerraSAR product xml file.
+       * @param xdoc Opened product.xml file.
+       * @param imageSize The point to initialize.
+       * @return true on success, false on error.
+       */
+      bool initImageSize(const ossimXmlDocument* xdoc,
+                         ossimIpt& imageSize) const;
+      
+      /**
+       * @brief Method to initialize gsd from
+       * TerraSAR product xml file.
+       * @param xdoc Opened product.xml file.
+       * @param gsd The point to initialize.
+       * @return true on success, false on error.
+       */
+      bool initGsd(const ossimXmlDocument* xdoc,
+                   ossimDpt& gsd) const;
+      
+      /**
+       * @brief Method to initialize image tie points from
+       * TerraSAR product xml file.
+       * @param xdoc Opened product.xml file.
+       * @param imageSize The point to initialize.
+       * @return true on success, false on error.
+       */
+      bool initTiePoints(const ossimXmlDocument* xdoc,
+                         std::list<ossimGpt>& gcp,
+                         std::list<ossimDpt>& icp) const;
+      
+      bool isProductGeoreferenced(const ossimXmlDocument* xdoc) const;
+      
+      bool getMission(const ossimXmlDocument* xdoc,
+                      ossimString& s) const;
+      
+      bool geNumberOfLayers(const ossimXmlDocument* xdoc,
+                      ossimString& s) const;
+
+      bool getImageFile(const ossimXmlDocument* xdoc,
+                        ossimString& s) const;
+      
+      bool getSceneId(const ossimXmlDocument* xdoc,
+                      ossimString& s) const;
+      
+      bool getProjection(const ossimXmlDocument* xdoc,
+                         ossimString& s) const;
+      
+      bool getReferencePoint(const ossimXmlDocument* xdoc,
+                             ossimString& s) const;
+      
+      bool getImageDataStrartWith(const ossimXmlDocument* xdoc,
+                                  ossimString& s) const;
+      
+      bool getOrbitDirection(const ossimXmlDocument* xdoc,
+                             ossimString& s) const;
+      
+      bool getLookDirection(const ossimXmlDocument* xdoc,
+                            ossimString& s) const;
+
+      bool getGenerationTime(const ossimXmlDocument* xdoc,
+                            ossimString& s) const;
+
+      /** one based??? */
+      bool getRangeGateFirstPixel(const ossimXmlDocument* xdoc,
+                                  ossimString& s) const;
+      
+      /** one based??? */
+      bool getRangeGateLastPixel(const ossimXmlDocument* xdoc,
+                                 ossimString& s) const;
+      
+      bool getSceneCenterAzimuthTime(const ossimXmlDocument* xdoc,
+                                     ossimString& s) const;
+      
+      bool getSceneCenterRangeTime(const ossimXmlDocument* xdoc,
+                                   ossimString& s) const;
+      
+      /** one based */
+      bool getSceneCenterRefColumn(const ossimXmlDocument* xdoc,
+                                   ossimString& s) const;
+      
+      /** one based */
+      bool getSceneCenterRefRow(const ossimXmlDocument* xdoc,
+                                ossimString& s) const;
+      
+      /** latitude */
+      bool getSceneCenterLat(const ossimXmlDocument* xdoc,
+                             ossimString& s) const;
+      
+      /** longitude */
+      bool getSceneCenterLon(const ossimXmlDocument* xdoc,
+                             ossimString& s) const;
+      
+      bool getSceneAverageHeight(const ossimXmlDocument* xdoc,
+                                 ossimString& s) const;
+      
+      bool getRadarCenterFrequency(const ossimXmlDocument* xdoc,
+                                   ossimString& s) const;
+      
+      bool getAzimuthStartTime(const ossimXmlDocument* xdoc,
+                               ossimString& s) const;
+      
+      bool getAzimuthStopTime(const ossimXmlDocument* xdoc,
+                              ossimString& s) const;
+      
+      bool getRangeFirstPixelTime(const ossimXmlDocument* xdoc,
+                              ossimString& s) const;
+
+      bool getRangeLastPixelTime(const ossimXmlDocument* xdoc,
+                              ossimString& s) const;
+
+      bool getCommonPrf(const ossimXmlDocument* xdoc, ossimString& s) const;
+      
+      /** range sampling rate */
+      bool getCommonRsf(const ossimXmlDocument* xdoc, ossimString& s) const;
+      
+      bool getNumberOfRangeLooks(const ossimXmlDocument* xdoc,
+                                 ossimString& s) const;
+      
+      bool getNumberOfAzimuthLooks(const ossimXmlDocument* xdoc,
+                                   ossimString& s) const;
+      
+      bool getNumberOfColumns(const ossimXmlDocument* xdoc,
+                              ossimString& s) const;
+      
+      bool getNumberOfRows(const ossimXmlDocument* xdoc,
+                           ossimString& s) const;
+      
+      bool getColumnSpacing(const ossimXmlDocument* xdoc,
+                            ossimString& s) const;
+      
+      bool getRowSpacing(const ossimXmlDocument* xdoc,
+                         ossimString& s) const;
+      
+      bool getProjectedSpacingSlantRange(const ossimXmlDocument* xdoc,
+                                         ossimString& s) const;
+
+      bool getProjectedSpacingAzimuth(const ossimXmlDocument* xdoc,
+                                      ossimString& s) const;
+
+      bool getGeodeticTerrainHeight(const ossimXmlDocument* xdoc,
+                                    ossimString& s) const;
+
+      bool getProductType(const ossimXmlDocument* xdoc,
+                                    ossimString& s) const;
+
+      bool getProductVariant(const ossimXmlDocument* xdoc,
+                             ossimString& s) const;
+
+      bool getRadiometricCorrection(const ossimXmlDocument* xdoc,
+                                    ossimString& s) const;
+      bool getImagingMode(const ossimXmlDocument* xdoc,
+                                    ossimString& s) const;
+      bool getAcquisitionSensor(const ossimXmlDocument* xdoc,
+                                    ossimString& s) const;
+      bool getPolarisationMode(const ossimXmlDocument* xdoc,
+                                     ossimString& s) const;
+      bool getPolLayerList(const ossimXmlDocument* xdoc,
+                                    std::vector<ossimString>& s) const;
+      bool getCalFactor(const ossimXmlDocument* xdoc,
+                                    std::vector<ossimString>& s) const;
+      bool getRadarFrequency(const ossimXmlDocument* xdoc,
+                                    ossimString& s) const;
+/*      bool getCenterIncidenceAngle(const ossimXmlDocument* xdoc,
+                                    ossimString& s) const;
+      bool getCornerIncidenceAngles(const ossimXmlDocument* xdoc,
+                                    std::vector<ossimString>& s) const;
+*/
+      /**
+       * @brief Method to initialize IncidenceAngles object from
+       * TerraSAR  product xml file.
+       * @param xdoc Opened product xml file.
+       * @param pos Pointer to PlatformPosition object.
+       * @return true on success, false on error.
+             */
+      bool initSceneCoord(const ossimXmlDocument* xdoc,
+                              SceneCoord* pos) const;
+      
+      /**
+       * @brief Method to initialize Noise object from
+       * TerraSAR  product xml file.
+       * @param xdoc Opened product xml file.
+       * @param pos Pointer to PlatformPosition object.
+       * @return true on success, false on error.
+       */
+      bool initNoise(const ossimXmlDocument* xdoc,
+                                Noise* pos) const;
+
+/*
+      bool getImageNoiseTimeUTC(const ossimXmlDocument* xdoc, ossimString& s) const;
+      bool getImageNoiseValidityRangeMin(const ossimXmlDocument* xdoc, ossimString& s) const;
+      bool getImageNoiseValidityRangeMax(const ossimXmlDocument* xdoc, ossimString& s) const;
+      bool getImageNoiseReferencePoint(const ossimXmlDocument* xdoc, ossimString& s) const;
+      bool getImageNoisePolynomialCoefficient( const ossimXmlDocument* xdoc, std::vector<double>& polynomialCoefficient) const;
+
+*/
+
+   };
+
+} // End: namespace ossimplugins
+
+#endif /* matches: #ifndef ossimTerraSarProductDoc_HEADER */
+
diff --git a/ossim_plugins/ossim/ossimTerraSarTiffReader.cpp b/ossim_plugins/ossim/ossimTerraSarTiffReader.cpp
new file mode 100644
index 0000000..86093a8
--- /dev/null
+++ b/ossim_plugins/ossim/ossimTerraSarTiffReader.cpp
@@ -0,0 +1,345 @@
+//----------------------------------------------------------------------------
+//
+// License:  See top level LICENSE.txt file
+//
+// Author:  David Burken
+//
+// Description: Image handelr for TerraSar-X data that is TIFF based.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include <ossimTerraSarTiffReader.h>
+#include <ossimTerraSarProductDoc.h>
+#include <ossimTerraSarModel.h>
+#include <ossim/base/ossimConstants.h>
+#include <ossim/base/ossimFilename.h>
+#include <ossim/base/ossimKeywordlist.h>
+#include <ossim/base/ossimKeywordNames.h>
+#include <ossim/base/ossimTrace.h>
+#include <ossim/base/ossimNotify.h>
+#include <ossim/base/ossimXmlDocument.h>
+#include <ossim/imaging/ossimImageGeometryRegistry.h>
+#include <ossim/projection/ossimProjection.h>
+#include <ossim/projection/ossimProjectionFactoryRegistry.h>
+#include <ossim/support_data/ossimGeoTiff.h>
+
+// Keyword constants:
+static const char PRODUCT_XML_FILE_KW[] = "product_xml_filename";
+
+namespace ossimplugins
+{
+RTTI_DEF1(ossimTerraSarTiffReader,
+          "ossimTerraSarTiffReader",
+          ossimTiffTileSource)
+}
+
+#ifdef OSSIM_ID_ENABLED
+   static const char OSSIM_ID[] = "$Id$";
+#endif
+   
+static ossimTrace traceDebug("ossimTerraSarTiffReader:degug");  
+
+ossimplugins::ossimTerraSarTiffReader::ossimTerraSarTiffReader()
+   :
+   ossimTiffTileSource()
+{
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimplugins::ossimTerraSarTiffReader::ossimTerraSarTiffReader entered...\n";
+#ifdef OSSIM_ID_ENABLED
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "OSSIM_ID:  " << OSSIM_ID << std::endl;
+#endif
+   }
+}
+
+ossimplugins::ossimTerraSarTiffReader::~ossimTerraSarTiffReader()
+{
+}
+
+bool ossimplugins::ossimTerraSarTiffReader::saveState(
+   ossimKeywordlist& kwl, const char* prefix) const
+{
+   static const char MODULE[] = "ossimplugins::ossimTerraSarTiffReader::saveState";
+   
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " entered...\n";
+   }
+
+   // Save our state:
+   kwl.add(prefix, PRODUCT_XML_FILE_KW, theProductXmlFile.c_str());
+
+   // Save the base:
+   return ossimTiffTileSource::saveState(kwl, prefix);
+}
+
+bool ossimplugins::ossimTerraSarTiffReader::loadState(
+   const ossimKeywordlist& kwl, const char* prefix)
+{
+   static const char MODULE[] = "ossimplugins::ossimTerraSarTiffReader::loadState";
+   
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " entered...\n";
+   }
+
+   bool result = false;
+
+   // Get the product.xml file name.
+   const char* lookup = kwl.find(prefix, PRODUCT_XML_FILE_KW);
+   if (lookup)
+   {
+      theProductXmlFile = lookup;
+      if ( isTerraSarProductFile(theProductXmlFile) )
+      {
+         //---
+         // Although we can open any tiff here we only do if we have matching
+         // TerraSAR-X product.xml.
+         //---
+         result = ossimTiffTileSource::loadState(kwl, prefix);
+      }
+   }
+
+   if (!result)
+   {
+      theProductXmlFile.clear();
+   }
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " exit status = " << (result?"true":"false\n")
+         << std::endl;
+   }
+
+   return result;
+}
+
+ossimString ossimplugins::ossimTerraSarTiffReader::getShortName()const
+{
+   return ossimString("ossim_terrasar_tiff_reader");
+}
+   
+ossimString ossimplugins::ossimTerraSarTiffReader::getLongName()const
+{
+   return ossimString("ossim TerraSAR-X tiff reader");
+}
+
+ossimString  ossimplugins::ossimTerraSarTiffReader::getClassName()const
+{
+   return ossimString("ossimTerraSarTiffReader");
+}
+
+bool ossimplugins::ossimTerraSarTiffReader::open(const ossimFilename& file)
+{
+   static const char MODULE[] = "ossimplugins::ossimTerraSarTiffReader::open";
+   
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " entered...\n"
+         << "file: " << file << "\n";
+   }
+
+   bool result = false;
+   
+   if ( isOpen() )
+   {
+      close();
+   }
+
+   // Check extension to see if it's xml.
+   if ( file.ext().downcase() == "xml" )
+   {
+      ossimRefPtr<ossimXmlDocument> xdoc = new ossimXmlDocument();
+      if ( xdoc->openFile(file) )
+      {
+         // See if it's a TerraSAR-X product xml file.
+         if ( isTerraSarProductFile( xdoc.get() ) )
+         {
+            ossimString s;
+            ossimTerraSarProductDoc helper;
+            
+            if ( helper.getImageFile(xdoc.get(), s) )
+            {
+               ossimFilename imageFile = file.expand().path();
+               imageFile = imageFile.dirCat(s);
+
+               setFilename(imageFile);
+
+               result = ossimTiffTileSource::open();
+               if (result)
+               {
+                  theProductXmlFile = file;
+
+                  completeOpen();
+               }
+            }
+         }
+      }
+      
+   } // matches: if ( file.ext().downcase() == "xml" )
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " exit status = " << (result?"true":"false\n")
+         << std::endl;
+   }
+
+   return result;
+}
+
+void ossimplugins::ossimTerraSarTiffReader::close()
+{
+   theProductXmlFile.clear();
+   ossimTiffTileSource::close();
+}
+
+ossimRefPtr<ossimImageGeometry> ossimplugins::ossimTerraSarTiffReader::getImageGeometry()
+{
+   if ( !theGeometry )
+   {
+      // Check for external geom:
+      theGeometry = getExternalImageGeometry();
+      
+      if ( !theGeometry )
+      {
+         // Check the internal geometry first to avoid a factory call.
+         theGeometry = getInternalImageGeometry();
+
+         // At this point it is assured theGeometry is set.
+
+         //---
+         // WARNING:
+         // Must create/set theGeometry at this point or the next call to
+         // ossimImageGeometryRegistry::extendGeometry will put us in an infinite loop
+         // as it does a recursive call back to ossimImageHandler::getImageGeometry().
+         //---         
+
+         // Check for set projection.
+         if ( !theGeometry->getProjection() )
+         {
+            // Try factories for projection.
+            ossimImageGeometryRegistry::instance()->extendGeometry(this);
+         }
+      }
+
+      // Set image things the geometry object should know about.
+      initImageParameters( theGeometry.get() );
+   }
+   
+   return theGeometry;
+}
+
+ossimRefPtr<ossimImageGeometry>
+ossimplugins::ossimTerraSarTiffReader::getInternalImageGeometry() const
+{
+   static const char MODULE[] = "ossimplugins::ossimTerraSarTiffReader::getInternalImageGeometry";
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " entered...\n";
+   }
+
+   ossimRefPtr<ossimImageGeometry> geom = new ossimImageGeometry();
+   
+   ossimRefPtr<ossimXmlDocument> xdoc = new ossimXmlDocument();
+   if ( xdoc->openFile(theProductXmlFile) )
+   {
+      ossimTerraSarProductDoc helper;
+      ossimString s;
+      if ( helper.getProjection(xdoc.get(), s) )
+      {
+         s.upcase();
+         if ( s == "GROUNDRANGE" )
+         {
+            ossimRefPtr<ossimTerraSarModel> model =
+               new ossimTerraSarModel();
+            if ( model->open(theProductXmlFile) )
+            {
+               // Assign the model to our ossimImageGeometry object.
+               geom->setProjection( model.get() );
+            }
+         }
+         else if ( (s == "MAP") && theTiffPtr )
+         {
+            ossimGeoTiff geotiff;
+
+            //---
+            // Note: must pass false to readTags so it doesn't close our
+            // tiff pointer.
+            //---
+            geotiff.readTags(theTiffPtr, getCurrentEntry(), false);
+            ossimKeywordlist kwl;
+            if(geotiff.addImageGeometry(kwl))
+            {
+               ossimRefPtr<ossimProjection> proj =
+                  ossimProjectionFactoryRegistry::instance()->
+                     createProjection(kwl);
+            
+               if ( proj.valid() )
+               {
+                  // Assign projection to our ossimImageGeometry object.
+                  geom->setProjection( proj.get() );
+               }
+            }
+         }
+         else
+         {
+            if (traceDebug())
+            {
+               ossimNotify(ossimNotifyLevel_DEBUG)
+                  << "WARNING: Unhandled projection: " << s << std::endl;
+               
+            }
+         }
+      }
+      
+   } // matches: if ( xdoc->openFile(theProductXmlFile) )
+   
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " exited..." << std::endl;
+   }
+   
+   return geom;
+}
+
+bool ossimplugins::ossimTerraSarTiffReader::isTerraSarProductFile(
+   const ossimFilename& file) const
+{
+   bool result = false;
+   
+   // Check extension to see if it's xml.
+   if ( file.ext().downcase() == "xml" )
+   {
+      ossimRefPtr<ossimXmlDocument> xdoc = new ossimXmlDocument();
+      if ( xdoc->openFile(file) )
+      {
+         result = isTerraSarProductFile( xdoc.get() );
+      }
+   }
+   
+   return result;
+}
+
+bool ossimplugins::ossimTerraSarTiffReader::isTerraSarProductFile(
+   const ossimXmlDocument* xdoc) const
+{
+   bool result = false;
+
+   if (xdoc)
+   {
+      ossimTerraSarProductDoc helper;
+      
+      // See if it's a TerraSAR-X product xml file.
+      result = helper.isTerraSarX(xdoc);
+   }
+   
+   return result;
+}
diff --git a/ossim_plugins/ossim/ossimTerraSarTiffReader.h b/ossim_plugins/ossim/ossimTerraSarTiffReader.h
new file mode 100644
index 0000000..b6d0544
--- /dev/null
+++ b/ossim_plugins/ossim/ossimTerraSarTiffReader.h
@@ -0,0 +1,110 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author:  David Burken
+//
+// Description: Image handelr for TerraSar-X data that is TIFF based.
+//
+//----------------------------------------------------------------------------
+// $Id$
+#ifndef ossimTerraSarTiffReader_HEADER
+#define ossimTerraSarTiffReader_HEADER 1
+
+#include <ossim/imaging/ossimTiffTileSource.h>
+#include <ossim/base/ossimFilename.h>
+
+// Forward class declarations outside of namespace ossimplugins.
+class ossimXmlDocument;
+
+namespace ossimplugins
+{
+   class ossimTerraSarTiffReader : public ossimTiffTileSource
+   {
+   public:
+      
+      /** default constructor */
+      ossimTerraSarTiffReader();
+      
+      /** virtual destructor */
+      virtual ~ossimTerraSarTiffReader();
+      
+      /** @return "terrasarx" */
+      virtual ossimString getShortName() const;
+      
+      /** @return "ossim TerraSAR-X reader" */
+      virtual ossimString getLongName()  const;
+      
+      /** @return "ossimTerraSarTiffReader" */
+      virtual ossimString getClassName()    const;
+      
+      /**
+       *  This open take the product xml file.
+       *  
+       *  @param file File to open.
+       *
+       *  @return true on success, false on error.
+       */
+      virtual bool open(const ossimFilename& file);
+      
+      /**
+       * Method to save the state of an object to a keyword list.
+       * Return true if ok or false on error.
+       */
+      virtual bool saveState(ossimKeywordlist& kwl,
+                             const char* prefix=0)const;
+      
+      /**
+       * Method to the load (recreate) the state of an object from a keyword
+       * list.  Return true if ok or false on error.
+       */
+      virtual bool loadState(const ossimKeywordlist& kwl,
+                             const char* prefix=0);
+      
+      /** Close method. */
+      virtual void close();
+      
+      /**
+       * Returns the image geometry object associated with this tile source or
+       * NULL if non defined.  The geometry contains full-to-local image
+       * transform as well as projection (image-to-world).
+       */
+      virtual ossimRefPtr<ossimImageGeometry> getImageGeometry();
+
+      /**
+       * @param Method to get geometry from the xml file or internal geotiff
+       * tags.
+       */
+      virtual ossimRefPtr<ossimImageGeometry> getInternalImageGeometry() const;
+      
+   private:
+      
+      /**
+       * @brief Method to check file to see if it's a TerraSAR-X product
+       * xml file.
+       * @param file The file to check.
+       * @return true on success, false on error.
+       */
+      bool isTerraSarProductFile(const ossimFilename& file) const;
+      
+      /**
+       * @brief Method to check file to see if it's a TerraSAR-X product
+       * xml file.
+       * @param xdoc XML document opened up to product.xml file.
+       * @return true on success, false on error.
+       */
+      bool isTerraSarProductFile(const ossimXmlDocument* xdoc) const;
+      
+      
+      ossimFilename theProductXmlFile;
+
+      TYPE_DATA
+   };
+
+} // End: namespace ossimplugins
+
+#endif /* #ifndef ossimTerraSarTiffReader_HEADER */
+
+
diff --git a/ossim_plugins/ossim/ossimTileMapModel.cpp b/ossim_plugins/ossim/ossimTileMapModel.cpp
new file mode 100644
index 0000000..0478389
--- /dev/null
+++ b/ossim_plugins/ossim/ossimTileMapModel.cpp
@@ -0,0 +1,288 @@
+//*******************************************************************
+//
+// License:  See top level LICENSE.txt file.
+//
+// AUTHOR: Jordi Inglada
+//
+// DESCRIPTION:
+//
+// SOFTWARE HISTORY:
+//   23JAN2008  Jordi Inglada, CNES
+//              Initial coding.
+//
+//*****************************************************************************
+
+#include "ossimTileMapModel.h"
+
+#include <stdio.h>
+#include <cstdlib>
+
+#include <ossim/base/ossimKeywordlist.h>
+#include <ossim/base/ossimKeywordNames.h>
+
+//***
+// Define Trace flags for use within this file:
+//***
+#include <ossim/base/ossimTrace.h>
+static ossimTrace traceExec  ("ossimTileMapModel:exec");
+static ossimTrace traceDebug ("ossimTileMapModel:debug");
+
+namespace ossimplugins
+{
+
+   RTTI_DEF1(ossimTileMapModel, "ossimTileMapModel", ossimSensorModel);
+
+//*****************************************************************************
+//  DEFAULT CONSTRUCTOR: ossimTileMapModel()
+//
+//*****************************************************************************
+   ossimTileMapModel::ossimTileMapModel()
+      :
+      ossimSensorModel(),
+      qDepth (1)
+
+   {
+      if (traceExec())  ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimTileMapModel::ossimTileMapModel: entering..." << std::endl;
+
+//   initAdjustableParameters();
+
+//    std::cout << "TileMapModel constructor" << std::endl;
+
+      if (traceExec()) ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimTileMapModel::ossimTileMapModel: returning..." << std::endl;
+   }
+
+
+   bool ossimTileMapModel::open(const ossimFilename& file)
+   {
+      static const char MODULE[] = "ossimTileMapModel::open";
+
+      ossimString os = file.beforePos(4);
+  
+      if (traceDebug())
+      {
+         CLOG << " Entered..." << std::endl
+              << " trying to open file " << file << std::endl;
+      }
+      if(os == "http" || file.ext() == "otb")
+      {
+         return true;
+      }
+  
+      return false;
+   }
+
+
+//*****************************************************************************
+//  CONSTRUCTOR: ossimTileMapModel(kwl)
+//
+//  Constructs model from keywordlist geometry file
+//
+//*****************************************************************************
+   ossimTileMapModel::ossimTileMapModel(const ossimKeywordlist& geom_kwl)
+      :
+      ossimSensorModel(),
+      qDepth (1)
+   {
+      if (traceExec())  ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimTileMapModel::ossimTileMapModel(geom_kwl): entering..." << std::endl;
+
+
+      //***
+      // Parse keywordlist for geometry:
+      //***
+      loadState(geom_kwl);
+
+      if (traceExec()) ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimTileMapModel::ossimTileMapModel(geom_kwl): Exited..." << std::endl;
+   }
+
+//*****************************************************************************
+//  COPY CONSTRUCTOR:
+//*****************************************************************************
+   ossimTileMapModel::ossimTileMapModel(const ossimTileMapModel& rhs)
+      :
+      ossimSensorModel   (rhs),
+      qDepth (rhs.qDepth)
+   {
+      if (traceExec())  ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimTileMapModel::ossimTileMapModel(rhs): entering..." << std::endl;
+
+      //initAdjustableParameters();
+
+      if (traceExec())  ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimTileMapModel::ossimTileMapModel(rhs): returning..." << std::endl;
+   }
+
+//*****************************************************************************
+//  METHOD: ossimTileMapModel::lineSampleHeightToWorld()
+//
+//  Performs the line/sample to groundpoint projection given an elevation.
+//
+//*****************************************************************************
+   void ossimTileMapModel::lineSampleToWorld(const ossimDpt& image_point,
+                                             ossimGpt&       gpt) const
+   {
+      lineSampleHeightToWorld(image_point, 0.0, gpt);
+   }
+   void ossimTileMapModel::lineSampleHeightToWorld(const ossimDpt& image_point,
+                                                   const double&   /* height */,
+                                                   ossimGpt&       gpt) const
+   {
+      if(!image_point.hasNans())
+      {
+         gpt.lon = static_cast<double>(image_point.samp)/(1 << qDepth)/256 *360.0-180.0;
+         double y = static_cast<double>(image_point.line)/(1 << qDepth)/256;
+         double ex = exp(4*M_PI*(y-0.5));
+         gpt.lat = -180.0/M_PI*asin((ex-1)/(ex+1));
+      }
+      else
+      {
+         gpt.makeNan();
+      }
+      return;
+   }
+
+   void ossimTileMapModel::worldToLineSample(const ossimGpt& ground_point,
+                                             ossimDpt&       img_pt) const
+   {
+      // if (traceExec())  ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimTileMapModel::worldToLineSample(): entering..." << std::endl;
+
+      if(ground_point.isLatNan() || ground_point.isLonNan() )
+      {
+         img_pt.makeNan();
+         return;
+      }
+
+      double x = (180.0 + ground_point.lon) / 360.0;
+      double y = - ground_point.lat * M_PI / 180; // convert to radians
+      y = 0.5 * log((1+sin(y)) / (1 - sin(y)));
+      y *= 1.0/(2 * M_PI); // scale factor from radians to normalized
+      y += 0.5; // and make y range from 0 - 1
+
+      img_pt.samp = floor(x*pow(2.,static_cast<double>(qDepth))*256);
+
+      img_pt.line = floor(y*pow(2.,static_cast<double>(qDepth))*256);
+
+      return;
+   }
+
+
+
+//*****************************************************************************
+//  METHOD: ossimTileMapModel::print()
+//
+//  Formatted dump of data members.
+//
+//*****************************************************************************
+   std::ostream& ossimTileMapModel::print(std::ostream& os) const
+   {
+      os << "\nDump of ossimTileMapModel object at "
+         << hex << this << ":\n"
+         << "\nTileMapModel -- Dump of all data members: "
+         << "\n        theImageID: " << theImageID.chars()
+         << "\n        theImageSize: " << theImageSize
+         << "\n        theRefImgPt: " << theRefImgPt
+         << "\n        theRefGndPt: " << theRefGndPt
+         << "\n        theGSD.line: " << theGSD.line
+         << "\n        theGSD.samp: " << theGSD.samp
+         << "\n        qDepth: " << qDepth
+         << endl;
+
+      return ossimSensorModel::print(os);
+   }
+
+//*****************************************************************************
+//  METHOD: ossimTileMapModel::saveState()
+//
+//  Saves the model state to the KWL. This KWL also serves as a geometry file.
+//
+//*****************************************************************************
+   bool ossimTileMapModel::saveState(ossimKeywordlist& kwl,
+                                     const char* prefix) const
+   {
+      if (traceExec())  ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimTileMapModel::saveState: entering..." << std::endl;
+
+      kwl.add(prefix, ossimKeywordNames::TYPE_KW, TYPE_NAME(this));
+
+      kwl.add(prefix, "depth", qDepth);
+
+      //***
+      // Hand off to base class for common stuff:
+      //***
+      ossimSensorModel::saveState(kwl, prefix);
+
+
+      if (traceExec())  ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimTileMapModel::saveState: returning..." << std::endl;
+      return true;
+   }
+
+//*****************************************************************************
+//  METHOD: ossimTileMapModel::loadState()
+//
+//  Restores the model's state from the KWL. This KWL also serves as a
+//  geometry file.
+//
+//*****************************************************************************
+   bool ossimTileMapModel::loadState(const ossimKeywordlist& kwl,
+                                     const char* prefix)
+   {
+      if (traceExec())  ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimTileMapModel::loadState: entering..." << std::endl;
+
+      if (traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimTileMapModel::loadState:"
+                                             << "\nInput kwl:  " << kwl
+                                             << std::endl;
+      }
+
+      const char* value = NULL;
+      //const char* keyword =NULL;
+      bool success;
+
+      //***
+      // Assure this keywordlist contains correct type info:
+      //***
+      value = kwl.find(prefix, ossimKeywordNames::TYPE_KW);
+      if (!value || (strcmp(value, TYPE_NAME(this))))
+      {
+         theErrorStatus = 1;
+         return false;
+      }
+
+      value = kwl.find(prefix, "depth");
+      qDepth = atoi(value);
+
+      //***
+      // Pass on to the base-class for parsing first:
+      //***
+      success = ossimSensorModel::loadState(kwl, prefix);
+      if (!success)
+      {
+         theErrorStatus++;
+         return false;
+      }
+
+
+      updateModel();
+
+      if (traceExec())  ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimTileMapModel::loadState: returning..." << std::endl;
+      return true;
+   }
+
+//*****************************************************************************
+// STATIC METHOD: ossimTileMapModel::writeGeomTemplate
+//
+//  Writes a sample kwl to output stream.
+//
+//*****************************************************************************
+   void ossimTileMapModel::writeGeomTemplate(ostream& os)
+   {
+      if (traceExec())  ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimTileMapModel::writeGeomTemplate: entering..." << std::endl;
+
+      os <<
+         "//**************************************************************\n"
+         "// Template for TileMap model keywordlist\n"
+         "//**************************************************************\n"
+         << ossimKeywordNames::TYPE_KW << ": " << "ossimTileMapModel" << endl;
+
+
+      if (traceExec())  ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimTileMapModel::writeGeomTemplate: returning..." << std::endl;
+      return;
+   }
+} // End: namespace ossimplugins
diff --git a/ossim_plugins/ossim/ossimTileMapModel.h b/ossim_plugins/ossim/ossimTileMapModel.h
new file mode 100644
index 0000000..019049f
--- /dev/null
+++ b/ossim_plugins/ossim/ossimTileMapModel.h
@@ -0,0 +1,166 @@
+//*******************************************************************
+//
+// License:  See top level LICENSE.txt file.
+//
+// DESCRIPTION: Contains declaration of TileMap sensor model class.
+//
+// SOFTWARE HISTORY:
+//   23JAN2008  Jordi Inglada, CNES
+//              Initial coding.
+//
+//*****************************************************************************
+//  $Id: ossimTileMapModel.h 10384 2007-01-26 20:32:12Z gpotts $
+
+#ifndef ossimTileMapModel_HEADER
+#define ossimTileMapModel_HEADER
+
+#include <ossimPluginConstants.h>
+#include <ossim/projection/ossimSensorModel.h>
+#include <ossim/projection/ossimMapProjection.h>
+#include <ossim/base/ossimGpt.h>
+#include <ossim/base/ossimDpt.h>
+#include <ossim/base/ossimMatrix3x3.h>
+#include <iostream>
+
+class ossimMapProjection;
+
+namespace ossimplugins
+{
+//******************************************************************************
+//*
+//* CLASS:  ossimTileMapModel
+//*
+//*******************************************************************************
+class OSSIM_PLUGINS_DLL ossimTileMapModel : public ossimSensorModel
+{
+public:
+  /*!
+   * CONSTRUCTORS:
+   */
+  ossimTileMapModel();
+  ossimTileMapModel(const ossimKeywordlist& geom_kwl);
+  ossimTileMapModel(const ossimTileMapModel& rhs);
+  
+  virtual ~ossimTileMapModel(){};
+
+  enum ProjectionType
+  {
+    UNKNOWN_PROJECTION = 0,
+    UTM_MAP,
+    UTM_ORBIT,
+    SOM_MAP,
+    SOM_ORBIT
+  };
+  
+  /*!
+   * Returns pointer to a new instance, copy of this.
+   */
+  virtual ossimObject* dup() const { return 0; } // TBR
+  
+  /*!
+   * Extends base-class implementation. Dumps contents of object to ostream.
+   */
+  virtual std::ostream& print(std::ostream& out) const;
+  
+
+
+  bool open(const ossimFilename& file);
+
+  /*!
+   * Fulfills ossimObject base-class pure virtuals. Loads and saves geometry
+   * KWL files. Returns true if successful.
+   */
+  virtual bool saveState(ossimKeywordlist& kwl,
+                         const char* prefix=0) const;
+  
+  virtual bool loadState(const ossimKeywordlist& kwl,
+                         const char* prefix=0);
+  
+  /*!
+   * Writes a template of geom keywords processed by loadState and saveState
+   * to output stream.
+   */
+  static void writeGeomTemplate(ostream& os);
+  
+  //***
+  // Overrides base class pure virtual.
+  //***
+  virtual void worldToLineSample(const ossimGpt& ground_point,
+                                 ossimDpt&       img_pt) const;
+  virtual void lineSampleHeightToWorld(const ossimDpt& image_point,
+                                       const double&   heightEllipsoid,
+                                       ossimGpt&       worldPoint) const;
+  virtual void lineSampleToWorld(const ossimDpt& image_point,
+                                 ossimGpt&       worldPoint) const;
+  
+  /*!
+   * Set/Get the depth of the quadtree decomposition
+   *
+   */
+  void setDepth(unsigned int depth){
+    qDepth = depth;
+  }
+  unsigned int getDepth()
+  {
+    return qDepth;
+  }
+  
+  
+  /*!
+   * ossimOptimizableProjection
+   */
+  inline virtual bool useForward()const {return true;} //!image to ground faster
+
+  
+protected:
+  
+
+  
+  //***
+  // Image constant parameters:
+  //***
+  double           theIllumAzimuth;
+  double           theIllumElevation;
+  double           theOrbitAltitude;
+  double           theOrbitInclination;
+  int              theMapZone;
+  ossimDpt         theMapOffset;
+  int              theWrsPathNumber;
+  int              theWrsRowNumber;
+  double           theMeridianalAngle;
+  double           thePositionError;
+ 
+  ProjectionType       theProjectionType;
+  ossimRefPtr<ossimMapProjection>  theMapProjection;
+ 
+  double           theMapAzimAngle;
+  double           theMapAzimCos;
+  double           theMapAzimSin;
+  double           theMap2IcRotAngle;
+  double           theMap2IcRotCos;
+  double           theMap2IcRotSin;
+ // 
+ // //***
+ // // Adjustable parameters:
+ // //***
+  double           theIntrackOffset;
+  double           theCrtrackOffset;
+  double           theLineGsdCorr;
+  double           theSampGsdCorr;
+  double           theRollOffset;
+  double           theYawOffset;
+  double           theYawRate;
+  double           theMapRotation;
+ // 
+ // //***
+ // // Quantities derived from the adjustable parameters:
+ // //***
+  NEWMAT::Matrix   theRollRotMat;
+
+  unsigned int qDepth;  
+  TYPE_DATA
+  
+
+};
+} // End: namespace ossimplugins
+#endif
diff --git a/ossim_plugins/ossim/otb/Arithmetic.h b/ossim_plugins/ossim/otb/Arithmetic.h
new file mode 100644
index 0000000..bb98814
--- /dev/null
+++ b/ossim_plugins/ossim/otb/Arithmetic.h
@@ -0,0 +1,44 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef Arithmetic_h
+#define Arithmetic_h
+
+#include <cmath>
+#include <cstdlib>
+
+namespace ossimplugins
+{
+
+
+/*-------------------------------------------------------------------------*/
+/*          "closest integer" function, returns long                      */
+/*-------------------------------------------------------------------------*/
+
+   long inint (double x)
+   {
+      return (x >= 0.0)  ?  (long)(x + 0.5)  :  (long)(x-0.5) ;
+   }
+
+/*-------------------------------------------------------------------------*/
+/*          "closest integer" function, returns double                    */
+/*-------------------------------------------------------------------------*/
+
+   double fnint (double x)
+   {
+      return (x >= 0.0)  ?  (double)((long)(x + 0.5))  :  (double)((long)(x - 0.5));
+   }
+
+   
+}  // End: namespace ossimplugins
+
+#endif
+
diff --git a/ossim_plugins/ossim/otb/CivilDateTime.cpp b/ossim_plugins/ossim/otb/CivilDateTime.cpp
new file mode 100644
index 0000000..617baa4
--- /dev/null
+++ b/ossim_plugins/ossim/otb/CivilDateTime.cpp
@@ -0,0 +1,474 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include <otb/JulianDate.h>
+#include <otb/CivilDateTime.h>
+#include <otb/JSDDateTime.h>
+#include <otb/GMSTDateTime.h>
+
+#include <cmath>
+#include <cstring>
+#include <cstdlib>
+#include <cstdio>
+#include <ostream>
+
+namespace ossimplugins
+{
+
+
+const double CivilDateTime::JOURCIVIL_LENGTH = 86400.0 ;
+
+CivilDateTime::CivilDateTime():
+  _year(0),
+  _month(0),
+  _day(0),
+  _second(0),
+  _decimal(0.0)
+{
+}
+
+CivilDateTime::CivilDateTime(int year, int month, int day, int second, double decimal):
+  _year(year),
+  _month(month),
+  _day(day),
+  _second(second),
+  _decimal(decimal)
+{
+}
+
+CivilDateTime::CivilDateTime(char* Utc)
+{
+  SetUtcDateTime(Utc);
+}
+
+CivilDateTime::CivilDateTime(const char* Utc)
+{
+  SetUtcDateTime(Utc);
+}
+
+CivilDateTime::~CivilDateTime()
+{
+}
+
+CivilDateTime::CivilDateTime(const CivilDateTime& rhs):
+  _year(rhs._year),
+  _month(rhs._month),
+  _day(rhs._day),
+  _second(rhs._second),
+  _decimal(rhs._decimal)
+{
+
+}
+
+CivilDateTime& CivilDateTime::operator=(const CivilDateTime& rhs)
+{
+  _year = rhs._year;
+  _month = rhs._month;
+  _day = rhs._day;
+  _second = rhs._second;
+  _decimal = rhs._decimal;
+
+  return *this;
+}
+
+int CivilDateTime::AsJulianDate(JulianDate* julianDate)
+{
+  int etat , test ;
+  int an , mois , i , j ;
+  double b , d ;
+
+  if (_month > 2)
+  {
+    an = _year ;
+    mois = _month ;
+  }
+  else
+  {
+    an = _year - 1 ;
+    mois = _month + 12 ;
+  }
+
+  test = _year * 10000 + _month * 100 + _day ;
+  if ((test > 15821004) && (test < 15821015))
+    etat = 1 ;
+  else
+  {
+    etat = 0 ;
+    d = (an < 0)  ?  0.75  :  0.0 ;
+    if (test >= 15821015)
+    {
+      i = an / 100 ;
+      j = 2 - i + i/4 ;
+      b = (double)j + 1720994.5 ;
+    }
+    else
+      b = 1720994.5 ;
+
+    i = (int) (365.25  * (double)an - d) ;
+    j = (int) (30.6001 * (double)(mois + 1)) ;
+    double jourJulien =   (double)(i + j) + (double)_day
+                  + ((double)_second + _decimal) / JOURCIVIL_LENGTH + b ;
+
+    julianDate->set_julianDate(jourJulien);
+  }
+
+  return etat;
+}
+
+int CivilDateTime::SetUtcDateTime(char* Utc)
+{
+  char str_an[5];
+  char str_day[3];
+  char str_month[4];
+  char str_hour[3];
+  char str_min[3];
+  char str_sec[3];
+  char str_micro[7];
+  int i;
+  double exposant;
+
+  /*
+    * year extraction
+    */
+  for (i = 0; i < 4; i++)
+  {
+    str_an[i] = Utc[i+7];
+  }
+
+  str_an[4] = '\0';
+  _year = atoi(str_an);
+  if ( (_year > 2050) || (_year < 1950) )
+    {
+    return 1;
+    }
+
+  /*
+    * month extraction
+    */
+  for (i = 0; i < 3; i++)
+  {
+    str_month[i] = Utc[i+3];
+  }
+
+  str_month[3] = '\0';
+  if (!strcmp(str_month, "JAN"))  _month = 1;
+  else if (!strcmp(str_month, "FEV"))  _month = 2;
+  else if (!strcmp(str_month, "MAR"))  _month = 3;
+  else if (!strcmp(str_month, "APR"))  _month = 4;
+  else if (!strcmp(str_month, "MAY"))  _month = 5;
+  else if (!strcmp(str_month, "JUN"))  _month = 6;
+  else if (!strcmp(str_month, "JUL"))  _month = 7;
+  else if (!strcmp(str_month, "AUG"))  _month = 8;
+  else if (!strcmp(str_month, "SEP"))  _month = 9;
+  else if (!strcmp(str_month, "OCT"))  _month = 10;
+  else if (!strcmp(str_month, "NOV"))  _month = 11;
+  else if (!strcmp(str_month, "DEC"))  _month = 12;
+  else
+  {
+    return 1;
+  }
+
+  /*
+    * day extraction
+    */
+  for (i = 0; i < 2; i++)
+  {
+    str_day[i] = Utc[i];
+  }
+
+  str_day[2] = '\0';
+  _day = atoi(str_day);
+  if ( (_day < 1) || (_day > 31) )
+  {
+    return 1;
+  }
+
+  /*
+    * seconds extraction
+    */
+  for (i = 0; i < 2; i++)
+    {
+    str_hour[i] = Utc[i+12];
+    str_min[i]  = Utc[i+15];
+    str_sec[i]  = Utc[i+18];
+    }
+
+  str_hour[2] = '\0';if ( (atoi(str_hour) < 0) || (atoi(str_hour) > 23) )
+  {
+    return 1;
+  }
+
+  str_min[2]  = '\0';if ( (atoi(str_min)  < 0) || (atoi(str_hour) > 59) )
+  {
+    return 1;
+  }
+  str_sec[2]  = '\0';if ( (atoi(str_sec)  < 0) || (atoi(str_hour) > 59) )
+  {
+    return 1;
+  }
+  _second = 3600*atoi(str_hour) + 60*atoi(str_min) + atoi(str_sec);
+
+  /*
+    * microseconds extraction
+    */
+  for (i = 0; i < 6; i++)
+  {
+    str_micro[i] = Utc[i+21];
+  }
+
+  str_micro[6] = '\0';
+  i = 0;
+  exposant = 10e-6;
+  while ((unsigned int)i < strlen(str_micro) )
+    {
+    if (str_micro[i] == '0') exposant = exposant * 0.1;
+    i++;
+    }
+
+  _decimal = exposant * (double) atoi(str_micro);
+  if ( (_decimal < 0) || (_decimal >= 1) )
+  {
+    return 1;
+  }
+
+  return 0;
+
+}
+
+int CivilDateTime::SetUtcDateTime(const char* Utc)
+{
+  char str_an[5];
+  char str_day[3];
+  char str_month[4];
+  char str_hour[3];
+  char str_min[3];
+  char str_sec[3];
+  char str_micro[7];
+  int i;
+  double exposant;
+
+  /*
+    * year extraction
+    */
+  for (i = 0; i < 4; i++)
+  {
+    str_an[i] = Utc[i+7];
+  }
+
+  str_an[4] = '\0';
+  _year = atoi(str_an);
+  if ( (_year > 2050) || (_year < 1950) )
+    {
+    return 1;
+    }
+
+  /*
+    * month extraction
+    */
+  for (i = 0; i < 3; i++)
+  {
+    str_month[i] = Utc[i+3];
+  }
+
+  str_month[3] = '\0';
+  if (!strcmp(str_month, "JAN"))  _month = 1;
+  else if (!strcmp(str_month, "FEV"))  _month = 2;
+  else if (!strcmp(str_month, "MAR"))  _month = 3;
+  else if (!strcmp(str_month, "APR"))  _month = 4;
+  else if (!strcmp(str_month, "MAY"))  _month = 5;
+  else if (!strcmp(str_month, "JUN"))  _month = 6;
+  else if (!strcmp(str_month, "JUL"))  _month = 7;
+  else if (!strcmp(str_month, "AUG"))  _month = 8;
+  else if (!strcmp(str_month, "SEP"))  _month = 9;
+  else if (!strcmp(str_month, "OCT"))  _month = 10;
+  else if (!strcmp(str_month, "NOV"))  _month = 11;
+  else if (!strcmp(str_month, "DEC"))  _month = 12;
+  else
+  {
+    return 1;
+  }
+
+  /*
+    * day extraction
+    */
+  for (i = 0; i < 2; i++)
+  {
+    str_day[i] = Utc[i];
+  }
+
+  str_day[2] = '\0';
+  _day = atoi(str_day);
+  if ( (_day < 1) || (_day > 31) )
+  {
+    return 1;
+  }
+
+  /*
+    * seconds extraction
+    */
+  for (i = 0; i < 2; i++)
+    {
+    str_hour[i] = Utc[i+12];
+    str_min[i]  = Utc[i+15];
+    str_sec[i]  = Utc[i+18];
+    }
+
+  str_hour[2] = '\0';if ( (atoi(str_hour) < 0) || (atoi(str_hour) > 23) )
+  {
+    return 1;
+  }
+
+  str_min[2]  = '\0';if ( (atoi(str_min)  < 0) || (atoi(str_hour) > 59) )
+  {
+    return 1;
+  }
+  str_sec[2]  = '\0';if ( (atoi(str_sec)  < 0) || (atoi(str_hour) > 59) )
+  {
+    return 1;
+  }
+  _second = 3600*atoi(str_hour) + 60*atoi(str_min) + atoi(str_sec);
+
+  /*
+    * microseconds extraction
+    */
+  for (i = 0; i < 6; i++)
+  {
+    str_micro[i] = Utc[i+21];
+  }
+
+  str_micro[6] = '\0';
+  i = 0;
+  exposant = 10e-6;
+  while ((unsigned int)i < strlen(str_micro) )
+    {
+    if (str_micro[i] == '0') exposant = exposant * 0.1;
+    i++;
+    }
+
+  _decimal = exposant * (double) atoi(str_micro);
+  if ( (_decimal < 0) || (_decimal >= 1) )
+  {
+    return 1;
+  }
+
+  return 0;
+
+}
+
+
+int CivilDateTime::AsJSDDateTime(JSDDateTime* JSDdate)
+{
+  int etat , k ;
+  JulianDate jourJulien;
+  double r ;
+
+  etat = AsJulianDate(&jourJulien );
+  if (etat == 0)
+  {
+    k = (int)(jourJulien.get_julianDate() - 0.5) ;
+
+    double day0hTU = (double)k + 0.5;
+    JSDdate->set_day0hTU(JulianDate(day0hTU));
+
+    r = (jourJulien.get_julianDate() - day0hTU) * JOURCIVIL_LENGTH ;
+    JSDdate->set_second(floor (r)) ;
+    JSDdate->set_decimal(r - JSDdate->get_second()) ;
+  }
+
+  return etat ;
+}
+
+int CivilDateTime::AsGMSTDateTime(GMSTDateTime* GMST)
+{
+  const double TWOPI      = 6.28318530717958647693 ;
+  const double OMEGATERRE  = 6.28318530717958647693 / 86164.09054 ;
+  int etat ;
+  JulianDate jourJulien;
+  double t=0.0;
+        double tsm0hTU=0.0;
+  double tsm;
+  CivilDateTime date0hTU(_year, _month, _day, 0, 0.0);
+
+
+  etat = date0hTU.AsJulianDate(&jourJulien );
+  if (etat == 0)
+  {
+    if (GMST->get_origine() == GMSTDateTime::AN1900)
+    {
+      t = (jourJulien.get_julianDate() - 2415020.0) / 36525.0 ;
+      tsm0hTU = 23925.836 + t * (8640184.542 + t * 0.0929) ;
+      tsm0hTU = tsm0hTU * TWOPI / JOURCIVIL_LENGTH ;
+    }
+    else if (GMST->get_origine() == GMSTDateTime::AN1950)
+    {
+      t = jourJulien.get_julianDate() - 2433281.5 ;
+      tsm0hTU = 1.72944494 + t * 6.3003880987 ;
+    }
+    else if (GMST->get_origine() == GMSTDateTime::AN2000)
+    {
+      t = (jourJulien.get_julianDate() - 2451545.0) / 36525.0 ;
+      tsm0hTU =   24110.54841 + t * (8640184.812866 + t * (0.093103 - t * 6.210e-6)) ;
+      tsm0hTU = tsm0hTU * TWOPI / JOURCIVIL_LENGTH ;
+    }
+    t = tsm0hTU + ((double)_second + _decimal) * OMEGATERRE ;
+    tsm = fmod (t, TWOPI) ;
+
+    if (tsm < 0.0)
+    {
+      tsm = tsm + TWOPI ;
+    }
+    GMST->set_tms(tsm);
+  }
+
+  return etat ;
+}
+
+
+CivilDateTime::operator JulianDate()
+{
+  JulianDate date;
+  AsJulianDate(&date);
+  return date;
+}
+
+CivilDateTime::operator JSDDateTime()
+{
+  JSDDateTime date;
+  AsJSDDateTime(&date);
+  return date;
+}
+
+CivilDateTime::operator GMSTDateTime()
+{
+  GMSTDateTime date;
+  AsGMSTDateTime(&date);
+  return date;
+}
+
+std::ostream& CivilDateTime::print(std::ostream& out) const
+{
+   out << "CivilDateTime:"
+       << "\nyear:    " << _year
+       << "\nmonth:   " << _month
+       << "\nday:     " << _day
+       << "\nsecond:  " << _second
+       << "\ndecimal: " << _decimal
+       << std::endl;
+
+   return out;
+}
+
+std::ostream& operator<<(std::ostream& out, const CivilDateTime& obj)
+{
+   return obj.print(out);
+}
+}
+
diff --git a/ossim_plugins/ossim/otb/CivilDateTime.h b/ossim_plugins/ossim/otb/CivilDateTime.h
new file mode 100644
index 0000000..a57e713
--- /dev/null
+++ b/ossim_plugins/ossim/otb/CivilDateTime.h
@@ -0,0 +1,188 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+
+#ifndef CivilDateTime_h
+#define CivilDateTime_h
+
+#include <ossimPluginConstants.h>
+#include <iosfwd>
+
+namespace ossimplugins
+{
+
+
+class JulianDate;
+class JSDDateTime;
+class GMSTDateTime;
+
+/**
+ * @brief This class represents a date and time in the civil format
+ */
+class OSSIM_PLUGINS_DLL CivilDateTime
+{
+public:
+
+   /**
+    * @brief Constructor
+    */
+   CivilDateTime();
+
+   /**
+    * @brief Constructor with date and time initialisation
+    */
+   CivilDateTime(int year, int month, int day, int second, double decimal);
+
+   /**
+    * @brief Constructor with date and time initialisation using an utc string
+    */
+   CivilDateTime(char* Utc);
+
+   CivilDateTime(const char* Utc);
+
+   /**
+    * @brief Destructor
+    */
+   ~CivilDateTime();
+
+   /**
+    * @brief Copy constructor
+    */
+   CivilDateTime(const CivilDateTime& rhs);
+
+   /**
+    * @brief Affectation operator
+    */
+   CivilDateTime& operator=(const CivilDateTime& rhs);
+
+   /**
+    * @brief This function converts the current CivilDateTime into Julian Date
+    * @return 0 if no error or an int greater than 0 indicating the error
+    * @param julianDate [out] The classe that receives the result of the conversion of the current CivilDateTime into JulianDate
+    */
+   int AsJulianDate(JulianDate* julianDate);
+
+   /**
+    * @brief This function converts the current CivilDateTime into JSDDateTime
+    * @return 0 if no error or an int greater than 0 indicating the error
+    * @param JSDdate [out] The classe that receives the result of the conversion of the current CivilDateTime into JSDDateTime
+    */
+   int AsJSDDateTime(JSDDateTime* JSDdate);
+
+   /**
+    * @brief This function converts the current CivilDateTime into GMSTDateTime
+    * @return 0 if no error or an int greater than 0 indicating the error
+    * @param GMSTdate [out] The classe that receives the result of the conversion of the current CivilDateTime into GMSTDateTime
+    */
+   int AsGMSTDateTime(GMSTDateTime* GMSTdate);
+
+   int get_year()
+   {
+      return _year;
+   };
+
+   int get_month()
+   {
+      return _month;
+   };
+
+   int get_day()
+   {
+      return _day;
+   };
+
+   int get_second()
+   {
+      return _second;
+   };
+
+   double get_decimal()
+   {
+      return _decimal;
+   };
+
+   void set_year(int year)
+   {
+      _year = year;
+   };
+
+   void set_month(int month)
+   {
+      _month = month;
+   };
+
+   void set_day(int day)
+   {
+      _day = day;
+   };
+
+   void set_second(int second)
+   {
+      _second = second;
+   };
+
+   void set_decimal(double decimal)
+   {
+      _decimal = decimal;
+   };
+
+   /**
+    * @brief This function initialize the date and the the time of the class using an utc string
+    * @param Utc Utc string containing the date and time
+    * @return 0 if no error or an int gretter than 0 indiquating the error
+    */
+   int SetUtcDateTime(char* Utc);
+
+   int SetUtcDateTime(const char* Utc);
+
+
+   operator JulianDate() ;
+
+   operator JSDDateTime() ;
+
+   operator GMSTDateTime() ;
+
+   std::ostream& print(std::ostream& out) const;
+
+   friend std::ostream& operator<<(std::ostream& out,
+                                   const CivilDateTime& obj);
+
+
+   static const double JOURCIVIL_LENGTH;
+protected:
+   /**
+    * @brief
+    */
+   int _year;
+   /**
+    * @brief
+    */
+   int _month;
+   /**
+    * @brief
+    */
+   int _day;
+   /**
+    * @brief Number of secondes since the beginning of the day
+    */
+   int _second;
+   /**
+    * @brief
+    */
+   double _decimal;
+
+
+private:
+};
+}
+
+#endif
+
diff --git a/ossim_plugins/ossim/otb/Coordinate.cpp b/ossim_plugins/ossim/otb/Coordinate.cpp
new file mode 100644
index 0000000..0660a9f
--- /dev/null
+++ b/ossim_plugins/ossim/otb/Coordinate.cpp
@@ -0,0 +1,62 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+
+#include <otb/Coordinate.h>
+
+namespace ossimplugins
+{
+
+
+
+Coordinate::Coordinate():
+  _x(0.0),
+  _y(0.0),
+  _z(0.0)
+{
+}
+
+Coordinate::~Coordinate()
+{
+}
+
+Coordinate::Coordinate(double x, double y, double z):
+  _x(x),
+  _y(y),
+  _z(z)
+{
+}
+
+Coordinate::Coordinate(const Coordinate& rhs):
+  _x(rhs._x),
+  _y(rhs._y),
+  _z(rhs._z)
+{
+}
+
+Coordinate& Coordinate::operator=(const Coordinate& rhs)
+{
+  _x = rhs._x;
+  _y = rhs._y;
+  _z = rhs._z;
+
+  return *this;
+}
+
+void Coordinate::set_coordinates(double x, double y, double z)
+{
+  _x = x;
+  _y = y;
+  _z = z;
+
+}
+}
+
diff --git a/ossim_plugins/ossim/otb/Coordinate.h b/ossim_plugins/ossim/otb/Coordinate.h
new file mode 100644
index 0000000..127ad14
--- /dev/null
+++ b/ossim_plugins/ossim/otb/Coordinate.h
@@ -0,0 +1,75 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef Coordinate_h
+#define Coordinate_h
+
+#include <ossimPluginConstants.h>
+
+namespace ossimplugins
+{
+
+
+/**
+ * @brief This class represents a coordinate
+ */
+
+class OSSIM_PLUGINS_DLL Coordinate
+{
+public:
+   /**
+    * @brief Constructor
+    */
+   Coordinate();
+   /**
+    * @brief Destructor
+    */
+   ~Coordinate();
+   /**
+    * @brief Constructor with initializations
+    */
+   Coordinate(double x, double y, double z);
+   /**
+    * @brief Copy constructor
+    */
+   Coordinate(const Coordinate& rhs);
+
+   /**
+    * @brief Affectation operator
+    */
+   Coordinate& operator=(const Coordinate& rhs);
+
+   void set_coordinates(double x, double y, double z);
+
+   double get_x()
+   {
+      return _x;
+   };
+
+   double get_y()
+   {
+      return _y;
+   };
+
+   double get_z()
+   {
+      return _z;
+   };
+protected:
+   double _x;
+   double _y;
+   double _z;
+private:
+};
+}
+
+#endif
+
diff --git a/ossim_plugins/ossim/otb/Ephemeris.cpp b/ossim_plugins/ossim/otb/Ephemeris.cpp
new file mode 100644
index 0000000..b900cac
--- /dev/null
+++ b/ossim_plugins/ossim/otb/Ephemeris.cpp
@@ -0,0 +1,202 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include <otb/Ephemeris.h>
+#include <ossim/base/ossimDpt3d.h>
+#include <ossim/base/ossimKeywordlist.h>
+#include <ossim/base/ossimNotify.h>
+#include <ossim/base/ossimString.h>
+
+namespace ossimplugins
+{
+
+
+static const char PREFIX[]          = "ephemeris.";
+static const char DATE_JULIAN_KW[]  = "date.julian";
+static const char DATE_SECOND_KW[]  = "date.second";
+static const char DATE_DECIMAL_KW[] = "date.decimal";
+static const char POSITION_KW[]     = "position";
+static const char VELOCITY_KW[]     = "velocity";
+
+Ephemeris::Ephemeris()
+{
+  _position[0] = 0.0;
+  _position[1] = 0.0;
+  _position[2] = 0.0;
+  _speed[0] = 0.0;
+  _speed[1] = 0.0;
+  _speed[2] = 0.0;
+}
+
+Ephemeris::~Ephemeris()
+{
+}
+
+Ephemeris::Ephemeris(JSDDateTime date, double pos[3], double speed[3]):
+  _date(date)
+{
+  _position[0] = pos[0];
+  _position[1] = pos[1];
+  _position[2] = pos[2];
+  _speed[0] = speed[0];
+  _speed[1] = speed[1];
+  _speed[2] = speed[2];
+}
+
+Ephemeris::Ephemeris(const Ephemeris& rhs):
+  _date(rhs._date)
+{
+  _position[0] = rhs._position[0];
+  _position[1] = rhs._position[1];
+  _position[2] = rhs._position[2];
+  _speed[0] = rhs._speed[0];
+  _speed[1] = rhs._speed[1];
+  _speed[2] = rhs._speed[2];
+}
+
+Ephemeris& Ephemeris::operator=(const Ephemeris& rhs)
+{
+  _position[0] = rhs._position[0];
+  _position[1] = rhs._position[1];
+  _position[2] = rhs._position[2];
+  _speed[0] = rhs._speed[0];
+  _speed[1] = rhs._speed[1];
+  _speed[2] = rhs._speed[2];
+  _date = rhs._date;
+
+  return *this;
+}
+
+bool Ephemeris::saveState(ossimKeywordlist& kwl, const char* prefix) const
+{
+   std::string pfx;
+   if (prefix)
+   {
+      pfx = prefix;
+   }
+   pfx += PREFIX;
+
+   ossimDpt3d pos(_position[0], _position[1], _position[2]);
+   ossimDpt3d vit(_speed[0], _speed[1], _speed[2]);
+   JulianDate jd = _date.get_day0hTU();
+
+   kwl.add(pfx.c_str(), DATE_JULIAN_KW,  jd.get_julianDate());
+   kwl.add(pfx.c_str(), DATE_SECOND_KW,  _date.get_second());
+   kwl.add(pfx.c_str(), DATE_DECIMAL_KW, _date.get_decimal());
+   kwl.add(pfx.c_str(), POSITION_KW,     pos.toString(15).c_str());
+   kwl.add(pfx.c_str(), VELOCITY_KW,     vit.toString(15).c_str());
+
+   return true;
+}
+
+bool Ephemeris::loadState(const ossimKeywordlist& kwl, const char* prefix)
+{
+   static const char MODULE[] = "Ephemeris::loadState";
+
+   bool result = true;
+
+   std::string pfx;
+   if (prefix)
+   {
+      pfx = prefix;
+   }
+   pfx += "ephemeris.";
+
+   const char* lookup = 0;
+   ossimString s;
+   double d;
+
+   lookup = kwl.find(pfx.c_str(), DATE_JULIAN_KW);
+   if (lookup)
+   {
+      s = lookup;
+      d = s.toDouble();
+      JulianDate jd(d);
+      _date.set_day0hTU(jd);
+   }
+   else
+   {
+      ossimNotify(ossimNotifyLevel_WARN)
+         << MODULE << " Keyword not found: " << DATE_JULIAN_KW << "\n";
+
+      result = false;
+   }
+
+   lookup = kwl.find(pfx.c_str(), DATE_SECOND_KW);
+   if (lookup)
+   {
+      s = lookup;
+      d = s.toDouble();
+      _date.set_second(d);
+   }
+   else
+   {
+      ossimNotify(ossimNotifyLevel_WARN)
+         << MODULE << " Keyword not found: " << DATE_SECOND_KW << "\n";
+      result = false;
+   }
+
+   lookup = kwl.find(pfx.c_str(), DATE_DECIMAL_KW);
+   if (lookup)
+   {
+      s = lookup;
+      d = s.toDouble();
+      _date.set_decimal(d);
+   }
+   else
+   {
+      ossimNotify(ossimNotifyLevel_WARN)
+         << MODULE << " Keyword not found: " << DATE_DECIMAL_KW << "\n";
+      result = false;
+   }
+
+   lookup = kwl.find(pfx.c_str(), POSITION_KW);
+   if (lookup)
+   {
+      std::string ps = lookup;
+
+      ossimDpt3d pt;
+      pt.toPoint(ps);
+
+      _position[0] = pt.x;
+      _position[1] = pt.y;
+      _position[2] = pt.z;
+   }
+   else
+   {
+      ossimNotify(ossimNotifyLevel_WARN)
+         << MODULE << " Keyword not found: " << POSITION_KW << "\n";
+      result = false;
+   }
+
+   lookup = kwl.find(pfx.c_str(), VELOCITY_KW);
+   if (lookup)
+   {
+      std::string ps = lookup;
+
+      ossimDpt3d pt;
+      pt.toPoint(ps);
+
+      _speed[0] = pt.x;
+      _speed[1] = pt.y;
+      _speed[2] = pt.z;
+   }
+   else
+   {
+      ossimNotify(ossimNotifyLevel_WARN)
+         << MODULE << " Keyword not found: " << VELOCITY_KW << "\n";
+      result = false;
+   }
+
+   return result;
+}
+}
+
diff --git a/ossim_plugins/ossim/otb/Ephemeris.h b/ossim_plugins/ossim/otb/Ephemeris.h
new file mode 100644
index 0000000..ee31103
--- /dev/null
+++ b/ossim_plugins/ossim/otb/Ephemeris.h
@@ -0,0 +1,132 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef Ephemeride_h
+#define Ephemeride_h
+
+#include <ossimPluginConstants.h>
+#include <otb/JSDDateTime.h>
+
+class ossimKeywordlist;
+
+namespace ossimplugins
+{
+
+
+/**
+ * @ingroup Ephemeris
+ * @brief This class represents an ephemeris
+ */
+class OSSIM_PLUGINS_DLL Ephemeris
+{
+public:
+   /**
+    * @brief Constructor
+    */
+   Ephemeris();
+
+   /**
+    * @brief Destructor
+    */
+   virtual ~Ephemeris();
+
+   /**
+    * @brief Constructor with initialisations
+    */
+   Ephemeris(JSDDateTime date, double pos[3], double speed[3]);
+   /**
+    * @brief Copy constructor
+    */
+   Ephemeris(const Ephemeris& rhs);
+
+   /**
+    * @brief Affectation operator
+    */
+   Ephemeris& operator=(const Ephemeris& rhs);
+
+   /**
+    * @brief This function creatse a copy of the current class
+    */
+   virtual Ephemeris* Clone()
+   {
+      return new Ephemeris(*this);
+   }
+
+   JSDDateTime get_date() const
+   {
+      return _date;
+   }
+
+   double* get_position()
+   {
+      return _position;
+   }
+
+   const double* get_position() const
+   {
+      return _position;
+   }
+
+   double* get_speed()
+   {
+      return _speed;
+   }
+
+   const double* get_speed() const
+   {
+      return _speed;
+   }
+
+   void set_date(JSDDateTime date)
+   {
+      _date = date;
+   }
+
+   void set_position(double position[3])
+   {
+      _position[0] = position[0];
+      _position[1] = position[1];
+      _position[2] = position[2];
+   }
+
+   void set_speed(double speed[3])
+   {
+      _speed[0] = speed[0];
+      _speed[1] = speed[1];
+      _speed[2] = speed[2];
+   }
+
+   /**
+    * @brief Method to save object state to a keyword list.
+    * @param kwl Keyword list to save to.
+    * @param prefix added to keys when saved.
+    * @return true on success, false on error.
+    */
+   bool saveState(ossimKeywordlist& kwl, const char* prefix=0) const;
+
+   /**
+    * @brief Method to the load (recreate) the state of the object from a
+    * keyword list. Return true if ok or false on error.
+    * @return true if load OK, false on error
+    */
+   bool loadState (const ossimKeywordlist &kwl, const char *prefix=0);
+
+protected:
+
+   JSDDateTime _date;
+   double _position[3];
+   double _speed[3];
+private:
+};
+}
+
+#endif
+
diff --git a/ossim_plugins/ossim/otb/Equation.cpp b/ossim_plugins/ossim/otb/Equation.cpp
new file mode 100644
index 0000000..435c036
--- /dev/null
+++ b/ossim_plugins/ossim/otb/Equation.cpp
@@ -0,0 +1,933 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include <otb/Equation.h>
+
+namespace ossimplugins
+{
+
+
+const double Equation::Epsilon = 1.e-12;
+
+Equation::Equation():
+   _coefficients(NULL),
+   _degree(0),
+   _nbrSol(0),
+   _solutions(NULL)
+{
+  _order.clear();
+}
+
+Equation::~Equation()
+{
+  if (_coefficients != NULL)
+    delete [] _coefficients;
+  if(_solutions != NULL)
+    delete [] _solutions;
+}
+
+Equation::Equation(int degree, std::complex<double>* coefficients):
+   _coefficients(NULL),
+   _degree(0),
+   _nbrSol(0),
+   _solutions(NULL)
+{
+  _order.clear();
+  CreateEquation(degree, coefficients);
+}
+
+void Equation::CreateEquation(int degree, std::complex<double>* coefficients)
+{
+  if (_coefficients != NULL)
+  {
+    delete [] _coefficients;
+  }
+
+  if(_order.size() != 0)
+    _order.clear();
+  if(_solutions != NULL)
+    delete [] _solutions;
+
+  _coefficients = new std::complex<double>[degree+1];
+  _degree = degree;
+
+  for (int i=0;i<=degree;i++)
+  {
+    _coefficients[i] = coefficients[i];
+  }
+}
+
+Equation::Equation(const Equation& rhs)
+{
+  CreateEquation(rhs._degree, rhs._coefficients);
+}
+
+Equation& Equation::operator=(const Equation& rhs)
+{
+  CreateEquation(rhs._degree, rhs._coefficients);
+  return *this;
+}
+
+void Equation::ComputeTrueDegree()
+{
+  double r = 0.0;
+  _trueDegree = _degree +1;
+  while (r <= Epsilon && _trueDegree > 0)
+  {
+    _trueDegree = _trueDegree - 1 ;
+    r = abs(_coefficients[_trueDegree]);
+  }
+}
+
+void Equation::Normalisation()
+{
+  for (int i=0;i<_trueDegree;i++)
+  {
+    _coefficients[i] = _coefficients[i] / _coefficients[_trueDegree];
+  }
+  _coefficients[_trueDegree] = std::complex<double>(1.0,0.0);
+
+  int eMax = 0;
+  int eMin = 0;
+  int e;
+  double r;
+
+  /*
+   * Normalisation by a power of 10
+   */
+  for (int i = 0 ; i < _trueDegree ; i++)
+  {
+    float rr = abs(_coefficients[i]) ;
+    if (rr >= Epsilon)
+    {
+      rr = log10(rr) ;
+      e = ((int)rr) / ((int)(_trueDegree - i)) ;
+      if (e > eMax)
+        eMax = e ;
+      if (e < eMin)
+        eMin = e ;
+    }
+  }
+
+  /*
+   * Normalisation for big values
+   */
+  if (eMax > 0)
+  {
+    /* Normalisation of the unknown for big values */
+    _normalisationType = GreatValues;
+    _normalisationCoefficient = pow (10.0, (double)eMax) ;
+    r    = 1.0 ;
+    for (int i = _trueDegree-1 ; i >= 0 ; i--)
+    {
+      r    = r * _normalisationCoefficient ;
+      _coefficients[i] = _coefficients[i] /  std::complex<double>(r,0.0);
+    }
+  }
+  else if (eMin < 0)
+  {
+    /* Normalisation of the unknown for small */
+    _normalisationType = SmallValues;
+    _normalisationCoefficient = pow(10.0,(double)(-eMin)) ;
+    r    = 1.0 ;
+    for (int i = _trueDegree-1 ; i >= 0 ; i--)
+    {
+      r    = r * _normalisationCoefficient ;
+      _coefficients[i] = _coefficients[i] *  std::complex<double>(r,0.0);
+    }
+  }
+}
+
+void Equation::DeNormalisation()
+{
+  if (_normalisationType == GreatValues)
+  {
+    for (int i=0;i<_nbrSol;i++)
+    {
+      _solutions[i] = _solutions[i] * std::complex<double>(_normalisationCoefficient,0.0);
+    }
+  }
+  else
+  {
+    for (int i=0;i<_nbrSol;i++)
+    {
+      _solutions[i] = _solutions[i] / std::complex<double>(_normalisationCoefficient,0.0);
+    }
+  }
+}
+std::complex<double> Equation::Proche(std::complex<double> z, double epsilon)
+{
+  double x, y, ax, ay ;
+  std::complex<double> result ;
+
+  x  = z.real();
+  y  = z.imag();
+  ax = fabs(x);
+  ay = fabs(y);
+
+  if (ax < epsilon && ay < epsilon)
+    result = std::complex<double>(0.0, 0.0) ;
+  else if (ay < epsilon)
+    result = std::complex<double>(x, 0.0) ;
+  else if (ax < epsilon)
+    result = std::complex<double>(0.0, y) ;
+  else
+  {
+    if ((ay / ax) < epsilon)
+      result = std::complex<double>(x, 0.0) ;
+    else if ((ax / ay) < epsilon)
+      result = std::complex<double>(0.0,y) ;
+    else
+      result = z ;
+  }
+
+  return result ;
+}
+
+void Equation::Solve()
+{
+  ComputeTrueDegree();
+  Normalisation();
+
+  if(_trueDegree == 1)
+  {
+    Solve1();
+  }
+  else if(_trueDegree == 2)
+  {
+    Solve2();
+  }
+  else if(_trueDegree == 3)
+  {
+    Solve3();
+  }
+  else if(_trueDegree == 4)
+  {
+    Solve4();
+  }
+  DeNormalisation();
+}
+
+void Equation::Solve1()
+{
+  _nbrSol = 1;
+
+  if(_order.size() != 0)
+    _order.clear();
+
+  _order.push_back(1);
+
+  if(_solutions != NULL)
+    delete [] _solutions;
+  _solutions = new std::complex<double>[1];
+  _solutions[0] = Proche(-_coefficients[0], Epsilon);
+}
+
+void Equation::Solve2()
+{
+  double r1, r2 ;
+  // double epsilon = 1.e-12 ;
+  std::complex<double> t1, t2, d, z ;
+  std::complex<double> aa[2] ;
+
+  aa[0] = _coefficients[0]/ _coefficients[2];
+  aa[1] = _coefficients[1]/ _coefficients[2];
+
+  t1 = aa[1]* aa[1] ;
+  t2 = aa[0]* std::complex<double>(4.0, 0.0) ;
+  r1 = abs(t1) ;
+  r2 = abs(t2) ;
+  if (r2 > r1)
+    r1 = r2 ;
+  if (r1 > Epsilon)
+  {
+    d  = t1- t2 ;
+    t1 = d/std::complex<double>(r1, 0.0) ;
+  }
+  else
+  {
+    d  = std::complex<double>(0.0, 0.0) ;
+    t1 = std::complex<double>(0.0, 0.0) ;
+  }
+  r1 = abs (t1) ;
+
+  if (r1 <= Epsilon)
+  {
+    /* 1 double root */
+
+    if(_solutions != NULL)
+      delete [] _solutions;
+    _solutions = new std::complex<double>[1];
+
+    if(_order.size() != 0)
+      _order.clear();
+
+    _nbrSol    = 1 ;
+    z         = aa[1]/std::complex<double>(-2.0, 0.0);
+    _solutions[0] = Proche (z, Epsilon) ;
+    _order.push_back(2);
+  }
+  else
+  {
+    /* 2 simple roots */
+
+    if(_solutions != NULL)
+      delete [] _solutions;
+    _solutions = new std::complex<double>[2];
+
+    if(_order.size() != 0)
+      _order.clear();
+
+    _nbrSol   = 2 ;
+    d         = sqrt(d) ;
+    z         = (d-aa[1])/std::complex<double>(2.0, 0.0) ;
+    _solutions[0] = Proche (z, Epsilon) ;
+    z         = (d+aa[1])/std::complex<double>(-2.0, 0.0);
+    _solutions[1] = Proche (z, Epsilon) ;
+    _order.push_back(1);
+    _order.push_back(1);
+  }
+}
+
+void Equation::Solve3(int d4)
+{
+  int d3_1r3 , d3_1r2_1r1 ;
+  double r1, r2, ra[3] ;
+  // double epsilon = 1.e-12 ;
+  std::complex<double> j, j2 ;
+  std::complex<double> d, q, r, s, t, u, v, w ;
+  std::complex<double> aa[3], zProv[3][3] ;
+
+
+  j  = std::complex<double>(-0.5,  sqrt (3.0) / 2.0) ;
+  j2 = std::complex<double>(-0.5, -sqrt (3.0) / 2.0) ;
+
+  /* Normalisation of coefficients */
+  for (int i1 = 0; i1 < 3; i1++)
+    aa[i1] = _coefficients[i1]/_coefficients[3];
+
+  if ( d4 == 0 )
+  {
+    /* Test of existence of a triple root */
+    d3_1r3 = TestDegree3Triple(aa, Epsilon) ;
+
+    /* Test of existence of 1 doubleroot + 1 simple root */
+    d3_1r2_1r1 = TestDegree3SimpleDouble(aa, Epsilon) ;
+  }
+  else
+  {
+    d3_1r3     = 0 ;
+    d3_1r2_1r1 = 0 ;
+  }
+
+
+  if (d3_1r3 == 1)
+  {
+    /* 1 triple root */
+    if(_solutions != NULL)
+      delete [] _solutions;
+    _solutions = new std::complex<double>[1];
+
+    if(_order.size() != 0)
+      _order.clear();
+
+    _nbrSol    = 1 ;
+    _solutions[0] = Proche (aa[2]/std::complex<double>(-3.0, 0.0) , Epsilon) ;
+    _order.push_back(3);
+  }
+  else if (d3_1r2_1r1 == 1)
+  {
+    /* 1 simple root + 1 double root */
+
+    if(_solutions != NULL)
+      delete [] _solutions;
+    _solutions = new std::complex<double>[2];
+
+    if(_order.size() != 0)
+      _order.clear();
+
+    u = (aa[1]* aa[2])/ std::complex<double>(6.0, 0.0) ;
+    v = aa[0]/ std::complex<double> (2.0, 0.0);
+    w = pow(aa[2], 3.0)/ std::complex<double>(27.0, 0.0);
+    r = (u-v)- w ;
+    u = pow (r, 1.0 / 3.0) ;
+    w = aa[2]/ std::complex<double>(3.0, 0.0);
+    zProv[0][0] = -u;
+    zProv[0][1] = u * std::complex<double>(2.0,0.0);
+    zProv[1][0] = u * (j + std::complex<double>(1.0, 0.0));
+    zProv[1][1] = u * (j2* std::complex<double>(2.0, 0.0));
+    zProv[2][0] = u * (j2+ std::complex<double>(1.0, 0.0));
+    zProv[2][1] = u * (j * std::complex<double>(2.0, 0.0));
+    for (int i1 = 0; i1 <= 2; i1++)
+    {
+      zProv[i1][0] = zProv[i1][0]- w;
+      zProv[i1][1] = zProv[i1][1]- w;
+    }
+    for (int i2 = 0; i2 < 3; i2++)
+    {
+      u = std::complex<double>(1.0, 0.0) ;
+
+      for (int i1 = 2; i1 >= 0; i1--)
+        u = u*zProv[i2][0]+aa[i1] ;
+
+      r1  = abs (u) ;
+      u   = std::complex<double>(1.0, 0.0) ;
+
+      for (int i1 = 2; i1 >= 0; i1--)
+        u = u*zProv[i2][1]+ aa[i1] ;
+
+      r2  = abs (u) ;
+      ra[i2] = r1 * r1 + r2 * r2 ;
+    }
+    int i3        = IndiceMin(3, ra) ;
+    _solutions[0] = Proche ( zProv[i3][0] , Epsilon ) ;
+    _solutions[1] = Proche ( zProv[i3][1] , Epsilon ) ;
+    _nbrSol   = 2 ;
+    _order.push_back(2);
+    _order.push_back(1);
+  }
+  else
+  {
+    /* 3 simple roots */
+    u = aa[1]/ std::complex<double>(3.0, 0.0);
+    v = (aa[2]* aa[2]) / std::complex<double>(9.0, 0.0) ;
+    q = u- v ;
+    u = (aa[1]* aa[2]) / std::complex<double>(6.0, 0.0) ;
+    v = aa[0]/ std::complex<double>(2.0, 0.0) ;
+    w = pow(aa[2], 3.0) / std::complex<double>(27.0, 0.0);
+    r = (u-v) - w ;
+    d = sqrt(pow(q, 3.0) + pow(r, 2.0)) ;
+    s = pow ((r + d) , 1.0 / 3.0) ;
+    t = pow ((r - d) , 1.0 / 3.0) ;
+    w = aa[2]/ std::complex<double>(3.0, 0.0);
+
+    zProv[0][0] = s+ t;
+    zProv[0][1] = (j*  s) + (j2* t) ;
+    zProv[0][2] = (j2* s) + (j* t) ;
+    zProv[1][0] = s + (j* t);
+    zProv[1][1] = (j* s) + t;
+    zProv[1][2] = j2 * (s+ t) ;
+    zProv[2][0] = s + (j2* t) ;
+    zProv[2][1] = j * (s+ t);
+    zProv[2][2] = (j2* s) + t;
+    for (int i1 = 0; i1 < 3; i1++)
+    {
+      for (int i2 = 0; i2 < 3; i2++)
+        zProv[i1][i2] = zProv[i1][i2]- w;
+    }
+    for (int i3 = 0; i3 < 3; i3++)
+    {
+      ra[i3] = 0.0 ;
+      for (int i2 = 0; i2 < 3; i2++)
+      {
+        u = std::complex<double>(1.0, 0.0) ;
+        for (int i1 = 2; i1 >= 0; i1--)
+          u = (u* zProv[i3][i2]) + aa[i1] ;
+
+        r1     = abs (u) ;
+        ra[i3] = ra[i3] + r1 * r1 ;
+      }
+    }
+    int i1 = IndiceMin(3, ra) ;
+
+
+    if(_solutions != NULL)
+      delete [] _solutions;
+    _solutions = new std::complex<double>[3];
+
+    if(_order.size() != 0)
+      _order.clear();
+
+    _nbrSol   = 3 ;
+    for (int i3 = 0; i3 < 3; i3++)
+      _solutions[i3] = Proche (zProv[i1][i3] , Epsilon) ;
+    _order.push_back(1);
+    _order.push_back(1);
+    _order.push_back(1);
+  }
+}
+
+void Equation::Solve4()
+{
+  int d4_1r4, d4_2r2, d4_1r3_1r1, d4_1r2_2r1 ;
+  int d4 = 1 ;
+  double epsilon = 1.e-12 ;
+  double r, h[4] ;
+  std::complex<double> d, u, v, w, x, y ;
+  std::complex<double> aa[4], k[4], b[4], zProv[2][4] ;
+
+
+  /* Normalisation of coefficients */
+  for (int i1 = 0; i1 < 4; i1++)
+    aa[i1] = _coefficients[i1]/ _coefficients[4];
+
+  /* Equation reduction :  on the form            */
+  /*       (x-s)**4 + p(x-s)**2 + q(x-s) + r = 0        */
+  /* these coefficients are inserted into table k :    */
+  /*           k[0] = s                                 */
+  /*           k[1] = p                                 */
+  /*           k[2] = q                                 */
+  /*           k[3] = r                                 */
+  k[0] = aa[3]/ std::complex<double>(-4.0, 0.0) ;
+  u    = aa[2] ;
+  v    = ((aa[3]* std::complex<double>(3.0, 0.0)) * (aa[3]/ std::complex<double>(8.0, 0.0))) ;
+  h[0] = abs (u) ;
+  h[1] = abs (v) ;
+
+  if (h[0] < h[1])
+    h[0] = h[1] ;
+  if (h[0] > Epsilon)
+    k[1] = u- v;
+  else
+    k[1] = std::complex<double>(0.0, 0.0) ;
+
+  u    = aa[1] ;
+  v    = (aa[2]* aa[3]) / std::complex<double>(2.0, 0.0) ;
+  w    = pow (aa[3], 3.0) /   std::complex<double>(8.0, 0.0) ;
+  h[0] = abs (u) ;
+  h[1] = abs (v) ;
+  h[2] = abs (w) ;
+  h[0] = h[IndiceMax(3, h)] ;
+  if (h[0] > Epsilon)
+    k[2] = (u- v)+ w ;
+  else
+    k[2] = std::complex<double>(0.0, 0.0) ;
+  u     = aa[0] ;
+  v    = (aa[1]* aa[3]) / std::complex<double>(4.0, 0.0);
+  w    = (aa[2]* aa[3]) * (aa[3]/ std::complex<double>(16.0, 0.0)) ;
+  x    = pow (aa[3], 4.0) * std::complex<double>(3.0 / 256.0, 0.0) ;
+  h[0] = abs (u) ;
+  h[1] = abs (v) ;
+  h[2] = abs (w) ;
+  h[3] = abs (x) ;
+  h[0] = h[IndiceMax(4, h)] ;
+
+  if (h[0]>Epsilon)
+    k[3] = (u- v) + (w- x) ;
+  else
+    k[3] = std::complex<double>(0.0, 0.0) ;
+
+  /* Test of existence of a quadruple root */
+  d4_1r4 = TestDegree4Quad (k, epsilon) ;
+
+  /* Test of existence of 2 double roots */
+  d4_2r2 = TestDegree4DoubleDouble (aa, k, epsilon) ;
+
+  /* Test of existence of 1 triple root + 1 simple root */
+  d4_1r3_1r1 = TestDegree4SimpleTriple (aa, k, epsilon) ;
+
+  /* Test of existence of 1 double root + 2 simple roots */
+  d4_1r2_2r1 = TestDegreeSimpleSimpleDouble (k, epsilon) ;
+
+
+  if (d4_1r4 == 1)
+  {
+    /* 1 quadruple root */
+
+    if(_solutions != NULL)
+      delete [] _solutions;
+    _solutions = new std::complex<double>[1];
+
+
+    if(_order.size() != 0)
+      _order.clear();
+
+    _nbrSol    = 1 ;
+    _solutions[0] = Proche (k[0], Epsilon) ;
+    _order.push_back(4);
+  }
+  else if (d4_2r2 == 1)
+  {
+    /* 2 double roots */
+
+    if(_solutions != NULL)
+      delete [] _solutions;
+    _solutions = new std::complex<double>[2];
+
+    if(_order.size() != 0)
+      _order.clear();
+
+    u         = sqrt (k[1]/ std::complex<double>(-2.0, 0.0)) ;
+    _solutions[0] = Proche ((k[0]+ u) , Epsilon) ;
+    _solutions[1] = Proche ((k[0]- u) , Epsilon) ;
+    _nbrSol    = 2 ;
+    _order.push_back(2);
+    _order.push_back(2);
+  }
+  else if (d4_1r3_1r1 == 1)
+  {
+    /* 1 triple root + 1 simple root */
+
+    if(_solutions != NULL)
+      delete [] _solutions;
+    _solutions = new std::complex<double>[2];
+
+    if(_order.size() != 0)
+      _order.clear();
+
+    u         = (k[2]* std::complex<double>(-3.0, 0.0)) / (k[1]* std::complex<double>(4.0, 0.0)) ;
+    v         = u * std::complex<double>(-3.0, 0.0);
+    _solutions[0] = Proche ((k[0]+ u) , Epsilon) ;
+    _solutions[1] = Proche ((k[0]+ v) , Epsilon) ;
+    _nbrSol    = 2 ;
+    _order.push_back(3);
+    _order.push_back(1);
+  }
+  else if (d4_1r2_2r1 == 1)
+  {
+    /* 1 double root + 2 simple roots */
+
+    if(_solutions != NULL)
+      delete [] _solutions;
+    _solutions = new std::complex<double>[3];
+
+    if(_order.size() != 0)
+      _order.clear();
+
+    if (abs (k[1]) <= Epsilon)
+    {
+      u         = (k[3]* std::complex<double>(-4.0, 0.0)) / (k[2]* std::complex<double>(3.0, 0.0));
+      v         = sqrt ((u* std::complex<double>(-2.0, 0.0)) * u) ;
+      _solutions[0] = Proche ((k[0]+ u) , Epsilon) ;
+      _solutions[1] = Proche ((k[0] + (v- u)) , Epsilon) ;
+      _solutions[2] = Proche ((k[0] - (v+ u)) , Epsilon) ;
+    }
+    else
+    {
+      v = (k[2]* k[2]) * std::complex<double>(9.0, 0.0) ;
+      w = (k[1]* k[3]) * std::complex<double>(32.0, 0.0) ;
+      u = sqrt((v- w)) ;
+      v = (k[2] * std::complex<double>(-3.0, 0.0)) ;
+      w = (k[1] * std::complex<double>(4.0, 0.0)) ;
+      x = ((v+ u) / w) ;
+      y = ((v- u) / w) ;
+      u = ((x* x) * std::complex<double>(-2.0, 0.0)) ;
+      u = sqrt((u- k[1])) ;
+      v = ((y* y) * std::complex<double>(-2.0, 0.0)) ;
+      v = sqrt((v- k[1])) ;
+      zProv[0][0] = (k[0]+ x) ;
+      zProv[0][1] = (k[0] - (x- u)) ;
+      zProv[0][2] = (k[0] - (x+ u)) ;
+      zProv[1][0] = (k[0]+ y) ;
+      zProv[1][1] = (k[0] - (y- v)) ;
+      zProv[1][2] = (k[0] - (y+ v)) ;
+      h[0] = 0.0 ;
+      h[1] = 0.0 ;
+      for (int i1 = 0; i1 < 3; i1++)
+      {
+        u = std::complex<double>(1.0, 0.0) ;
+        for (int i2 = 3; i2 >= 0; i2--)
+          u = ((u* zProv[0][i1])+ aa[i2]) ;
+
+        r    = abs (u) ;
+        h[0] = h[0] + r * r ;
+        u    = std::complex<double>(1.0, 0.0) ;
+        for (int i2 = 3; i2 >= 0; i2--)
+          u = ((u* zProv[1][i1])+ aa[i2]) ;
+        r    = abs (u) ;
+        h[1] = h[1] + r * r ;
+      }
+      int i1 = IndiceMin (2, h) ;
+      for (int i2 = 0; i2 < 3; i2++)
+        _solutions[i2] = Proche (zProv[i1][i2] , Epsilon) ;
+    }
+    _nbrSol   = 3 ;
+    _order.push_back(2);
+    _order.push_back(1);
+    _order.push_back(1);
+  }
+  else
+  {
+    /* 4 simple roots */
+    u    = ((aa[0]* aa[2]) * std::complex<double>(4.0, 0.0)) ;
+    v    = (aa[1] * aa[1]) ;
+    w    = ((aa[0]* aa[3]) * aa[3]) ;
+    b[0] = (u - (v+ w)) ;
+    b[1] = ((aa[1]* aa[3]) - (aa[0]* std::complex<double>(4.0, 0.0))) ;
+    b[2] = -aa[2] ;
+    b[3] = std::complex<double>(1.0, 0.0) ;
+
+    /* The third degree equation is solved by forcing 3 distinct roots (computation precision problem) */
+    Equation eq(3,b);
+    eq.Solve3(d4);
+
+    //Solve3(d4);
+    h[0] = abs ((eq.get_solutions()[1]- eq.get_solutions()[2])) ; /* the root the most distant to    */
+    h[1] = abs ((eq.get_solutions()[0]- eq.get_solutions()[2])) ; /* the 2 others is selected       */
+    h[2] = abs ((eq.get_solutions()[0]- eq.get_solutions()[1])) ;
+    int i1   = IndiceMin (3, h) ;
+    u    = eq.get_solutions()[i1] ;
+    v    = ((aa[2]- u) * std::complex<double>(4.0, 0.0)) ;
+    v    = sqrt(((aa[3]* aa[3]) - v)) ;
+    w    = sqrt(((u* u) - (aa[0]* std::complex<double>(4.0, 0.0)))) ;
+    x    = ((aa[3]+ v) / std::complex<double>(2.0, 0.0)) ;
+    y    = ((u+ w) / std::complex<double>(2.0, 0.0)) ;
+    d    = sqrt(((x* x) - (y* std::complex<double>(4.0, 0.0)))) ;
+    zProv[0][0] = ((x- d) / std::complex<double>(-2.0, 0.0)) ;
+    zProv[0][1] = ((x+ d) / std::complex<double>(-2.0, 0.0)) ;
+
+    x    = ((aa[3]- v) / std::complex<double>(2.0, 0.0)) ;
+    y    = ((u- w) / std::complex<double>(2.0, 0.0)) ;
+    d    = sqrt((x*x) - (y* std::complex<double>(4.0, 0.0))) ;
+    zProv[0][2] = ((x- d) / std::complex<double>(-2.0, 0.0)) ;
+    zProv[0][3] = ((x+ d) / std::complex<double>(-2.0, 0.0)) ;
+
+    x    = ((aa[3]+ v) / std::complex<double>(2.0, 0.0)) ;
+    y    = ((u- w) / std::complex<double>(2.0, 0.0)) ;
+    d    = sqrt(((x*x) - (y* std::complex<double>(4.0, 0.0)))) ;
+    zProv[1][0] = ((x- d) / std::complex<double>(-2.0, 0.0)) ;
+    zProv[1][1] = ((x+ d) / std::complex<double>(-2.0, 0.0)) ;
+
+    x = ((aa[3]- v) / std::complex<double>(2.0, 0.0)) ;
+    y = ((u+ w) / std::complex<double>(2.0, 0.0)) ;
+    d = sqrt((x*x) - (y* std::complex<double>(4.0, 0.0))) ;
+    zProv[1][2] = ((x- d) / std::complex<double>(-2.0, 0.0)) ;
+    zProv[1][3] = ((x+ d) / std::complex<double>(-2.0, 0.0)) ;
+
+    h[0] = 0.0 ;
+    h[1] = 0.0 ;
+    for (int i1 = 0; i1 < 4; i1++)
+    {
+      u = std::complex<double>(1.0, 0.0) ;
+
+      for (int i2 = 3; i2 >= 0; i2--)
+        u = ((u* zProv[0][i1])+ aa[i2]) ;
+
+      r    = abs (u) ;
+      h[0] = h[0] + r * r ;
+      u    = std::complex<double>(1.0, 0.0) ;
+
+      for (int i2 = 3; i2 >= 0; i2--)
+        u = ((u* zProv[1][i1])+ aa[i2]) ;
+
+      r    = abs(u) ;
+      h[1] = h[1] + r * r ;
+    }
+    i1 = IndiceMin (2, h) ;
+
+    if(_solutions != NULL)
+      delete [] _solutions;
+    _solutions = new std::complex<double>[4];
+
+    if(_order.size() != 0)
+      _order.clear();
+
+    for (int i2 = 0; i2 < 4; i2++)
+    {
+      _solutions[i2] = Proche (zProv[i1][i2] , Epsilon) ;
+      _order.push_back(1);
+    }
+    _nbrSol = 4 ;
+  }
+
+}
+
+int Equation::TestDegree3Triple(std::complex<double>* a, double epsilon)
+{
+  double d, dp[2], q, r ;
+  std::complex<double> u, v ;
+
+
+  u     = a[2]* a[2] ;
+  v     = a[1]*std::complex<double>(3.0, 0.0) ;
+  dp[0] = abs (u) ;
+  dp[1] = abs (v) ;
+  d     = (dp[0] > dp[1]) ? dp[0] : dp[1] ;
+  q     = (d > epsilon) ? abs((u- v)/ std::complex<double> (d, 0.0))
+              : 0.0 ;
+
+  u     = a[1]* a[2];
+  v     = a[0]* std::complex<double>(9.0, 0.0) ;
+  dp[0] = abs (u) ;
+  dp[1] = abs (v) ;
+  d     = (dp[0] > dp[1]) ? dp[0] : dp[1] ;
+  r     = (d > epsilon) ? abs ((u-v)/std::complex<double>(d, 0.0))
+              : 0.0 ;
+
+  return ((q <= epsilon) && (r <= epsilon)) ? 1 : 0 ;
+}
+
+int Equation::TestDegree3SimpleDouble(std::complex<double>* a, double epsilon)
+{
+  double d, k, r[5] ;
+  std::complex<double> u, t[5] ;
+
+
+  u    = a[1]*a[2] ;
+  t[0] = pow (a[1], 3.0)*std::complex<double>(4.0,  0.0) ;
+  t[1] = a[0]*a[0]* std::complex<double>(27.0, 0.0);
+  t[2] = a[0]* std::complex<double>(4.0, 0.0)*pow (a[2], 3.0) ;
+  t[3] = -(u* u) ;
+  t[4] = std::complex<double>(-18.0, 0.0)* a[0] * u;
+
+  for (int i = 0 ; i < 5 ; i++)
+    r[i] = abs (t[i]) ;
+
+  k = r[IndiceMax(5, r)] ;
+
+  for (int i = 1 ; i < 5 ; i++)
+    t[0] = t[0]+t[i];
+
+  d = (k > epsilon) ? abs (t[0]/std::complex<double>(k,0.0))
+            : 0.0 ;
+
+  return (d <= epsilon) ? 1 : 0 ;
+}
+
+int Equation::IndiceMin ( int n , double *list )
+{
+  int iMin ;
+  double xMin ;
+
+  iMin = 0 ;
+  xMin = list[0] ;
+  for (int i = 1; i < n; i++)
+  {
+    if ( list[i] < xMin )
+    {
+      iMin = i ;
+      xMin = list[i] ;
+    }
+  }
+  return iMin ;
+}
+
+
+int Equation::IndiceMax ( int n , double *list)
+{
+  int iMax ;
+  double xMax ;
+
+  iMax = 0 ;
+  xMax = list[0] ;
+  for (int i = 1; i < n; i++)
+  {
+    if ( list[i] > xMax )
+    {
+      iMax = i ;
+      xMax = list[i] ;
+    }
+  }
+  return iMax ;
+}
+
+int Equation::TestDegree4Quad ( std::complex<double> *a , double epsilon )
+{
+  double r1, r2, r3 ;
+
+  r1 = abs (a[1]) ;
+  r2 = abs (a[2]) ;
+  r3 = abs (a[3]) ;
+
+  return ((r1 < epsilon) && (r2 < epsilon) && (r3 < epsilon)) ? 1 : 0 ;
+}
+
+int Equation::TestDegree4DoubleDouble ( std::complex<double> *a , std::complex<double> *k , double epsilon )
+{
+  int d4 ;
+  double r0, r1, r2, h[5] ;
+  std::complex<double> u, t[5] ;
+
+
+  u    = (a[3]*  a[3]) ;
+  t[0] = (u* u) * std::complex<double>(3.0 / 16.0, 0.0);
+  t[1] = a[0] * std::complex<double>(4.0,0.0);
+  t[2] = a[3] * a[1];
+  t[3] = u *    a[2];
+  t[4] = a[2] * a[2];
+  for (int i = 0 ; i < 5 ; i++)
+    h[i] = abs (t[i]) ;
+
+  r1 = h[IndiceMax(5, h)] ;
+  u  = (t[0]- t[1]) + t[2];
+  u  = u - (t[3]- t[4]) ;
+  r2 = (r1 > epsilon)  ?  abs (u) / r1  :  0.0 ;
+
+  r1 = abs (k[2]) ;
+  r0 = abs (k[1]) ;
+
+  if ((r0 >= epsilon) && (r1 < epsilon) && (r2 < epsilon))
+    d4 = 1 ;
+  else
+    d4 = 0 ;
+
+  return d4 ;
+}
+
+int Equation::TestDegree4SimpleTriple ( std::complex<double> *a , std::complex<double> *k , double epsilon )
+{
+  int d4 ;
+  double r, r0, r1, r2, h[4] ;
+  std::complex<double> u, t[4] ;
+
+
+  t[0] = a[2] * a[2] ;
+  t[1] = a[0] * std::complex<double>(12.0, 0.0);
+  t[2] = (a[1]* a[3]) * std::complex<double>(3.0, 0.0) ;
+  for (int i = 0 ; i < 3 ; i++)
+    h[i] = abs (t[i]) ;
+
+  r  = h[IndiceMax(3, h)] ;
+  u  = t[0] + (t[1]- t[2]) ;
+  r1 = (r > epsilon)  ?  abs (u) / r  :  0.0 ;
+
+  t[0] = a[1] * a[1];
+  t[1] = (a[0]* a[2]) * std::complex<double>(4.0, 0.0) ;
+  u    = a[3]* std::complex<double>(3.0, 0.0) ;
+  t[2] = (u* u) * (a[0]* std::complex<double>(3.0, 0.0)) ;
+  t[3] = (a[2]* a[2]) * a[2] ;
+  for (int i = 0 ; i < 4 ; i++)
+    h[i] = abs (t[i]) ;
+  r  = h[IndiceMax(4, h)] ;
+  u  = ((t[0]- t[1])* std::complex<double>(27.0, 0.0))+ (t[2]- t[3]) ;
+  r2 = (r > epsilon)  ?  abs (u) / r  :  0.0 ;
+
+  r0 = abs (k[1]) ;
+
+  if ((r0 >= epsilon) && (r1 < epsilon) && (r2 < epsilon))
+    d4 = 1 ;
+  else
+    d4 = 0 ;
+
+  return d4 ;
+}
+
+int Equation::TestDegreeSimpleSimpleDouble( std::complex<double> *a , double epsilon )
+{
+  double r[3] ;
+  std::complex<double> u, v, w ;
+
+
+  u    = (a[1]* a[1]) - (a[3]* std::complex<double>(4.0, 0.0)) ;
+  u    = u* a[3] * u * std::complex<double>(16.0, 0.0);
+  r[0] = abs (u) ;
+
+  w    = pow (a[1], 3.0) *  std::complex<double>(4.0, 0.0) ;
+  v    = (a[2]* a[2]) * std::complex<double>(27.0, 0.0) ,
+  v    = (w+ v) * (a[2]* a[2]) ;
+  r[1] = abs (v) ;
+
+  w    = (a[1]* a[2]) * (a[2]* a[3]) ;
+  w    = w * std::complex<double>(144.0, 0.0) ;
+  r[2] = abs (w) ;
+
+  r[1] = r[IndiceMax(3, r)] ;
+  if (r[1] < epsilon)
+    r[0] = 0.0 ;
+  else if (r[1] <= 1.0)
+    r[0] = abs ((u- v)+ w) ;
+  else
+    r[0] = abs (((u- v)+ w)/ std::complex<double>(r[1], 0.0)) ;
+
+  return (r[0] < (2.0 * epsilon))  ?  1  :  0 ;
+}
+}
+
diff --git a/ossim_plugins/ossim/otb/Equation.h b/ossim_plugins/ossim/otb/Equation.h
new file mode 100644
index 0000000..d08702b
--- /dev/null
+++ b/ossim_plugins/ossim/otb/Equation.h
@@ -0,0 +1,145 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef Equation_h
+#define Equation_h
+
+#include <complex>
+#include <vector>
+#include <ossimPluginConstants.h>
+
+namespace ossimplugins
+{
+
+
+/**
+ * @brief This class manages and solves an equation of the fourth degree
+ */
+class OSSIM_PLUGINS_DLL Equation
+{
+public:
+   /**
+    * @brief Constructor
+    */
+   Equation();
+   /**
+    * @brief Destructor
+    */
+   ~Equation();
+
+   Equation(const Equation& rhs);
+
+   Equation& operator=(const Equation& rhs);
+
+   Equation(int degree, std::complex<double>* coefficients);
+
+   void CreateEquation(int degree, std::complex<double>* coefficients);
+
+   void Solve();
+
+   int get_nbrSol() const
+   {
+      return _nbrSol;
+   };
+
+   const std::complex<double>* get_solutions() const
+   {
+      return _solutions;
+   };
+
+   std::vector<int> get_order() const
+   {
+      return _order;
+   };
+
+protected:
+
+   /**
+    * @brief Equation coefficients
+    */
+   std::complex<double>* _coefficients;
+   /**
+    * @brief Equation degree
+    */
+   int _degree;
+
+   void ComputeTrueDegree();
+
+   void Normalisation();
+   void DeNormalisation();
+   static const double Epsilon;
+
+   int _nbrSol;
+   std::vector<int> _order;
+   std::complex<double>* _solutions;
+private:
+
+   enum NormalisationType
+   {
+      GreatValues,
+      SmallValues
+   };
+
+   NormalisationType _normalisationType;
+   double _normalisationCoefficient;
+   int _trueDegree;
+
+   void Solve1();
+   void Solve2();
+   void Solve3(int d4 =0);
+   void Solve4();
+
+   /**
+    * ??
+    */
+   std::complex<double> Proche(std::complex<double> z, double epsilon);
+
+   /**
+    * @brief Tests whether a triple root exists in a third degree equation
+    */
+   int TestDegree3Triple(std::complex<double>* a, double epsilon);
+   /**
+    * @brief Tests whether a double root and a simple root exist in a third degree equation
+    */
+   int TestDegree3SimpleDouble(std::complex<double>* a, double epsilon);
+
+   /**
+    * @brief Returns the index of the smaller list element
+    */
+   int IndiceMin ( int n , double *list);
+
+   /**
+    * @brief Returns the index of the greater list element
+    */
+   int IndiceMax ( int n , double *list);
+
+   /**
+    * @brief Tests whether a quadruple root exists in a fourth degree equation
+    */
+   int TestDegree4Quad ( std::complex<double> *a , double epsilon );
+   /**
+    * @brief Tests whether two double roots exist in a fourth degree equation
+    */
+   int TestDegree4DoubleDouble ( std::complex<double> *a , std::complex<double> *k , double epsilon );
+   /**
+    * @brief Tests whether one simple root and one triple root exist in a fourth degree equation
+    */
+   int TestDegree4SimpleTriple ( std::complex<double> *a , std::complex<double> *k , double epsilon );
+   /**
+    * @brief Tests whether two simple root and one double root exist in a fourth degree equation
+    */
+   int TestDegreeSimpleSimpleDouble( std::complex<double> *a , double epsilon );
+   ;
+};
+}
+
+#endif
+
diff --git a/ossim_plugins/ossim/otb/GMSTDateTime.cpp b/ossim_plugins/ossim/otb/GMSTDateTime.cpp
new file mode 100644
index 0000000..57e4716
--- /dev/null
+++ b/ossim_plugins/ossim/otb/GMSTDateTime.cpp
@@ -0,0 +1,52 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include <otb/GMSTDateTime.h>
+#include <otb/CivilDateTime.h>
+
+namespace ossimplugins
+{
+
+
+GMSTDateTime::GMSTDateTime():
+  _tms(0)
+{
+}
+
+GMSTDateTime::~GMSTDateTime()
+{
+}
+
+GMSTDateTime::GMSTDateTime(const GMSTDateTime& rhs):
+  _tms(rhs._tms),
+  _origine(rhs._origine)
+{
+}
+
+GMSTDateTime::GMSTDateTime(double tms, Ori_TSM_Green origine):
+  _tms(tms),
+  _origine(origine)
+{
+}
+
+GMSTDateTime::GMSTDateTime(CivilDateTime& rhs)
+{
+  rhs.AsGMSTDateTime(this);
+}
+
+GMSTDateTime& GMSTDateTime::operator=(const GMSTDateTime& rhs)
+{
+  _tms = rhs._tms;
+  _origine = rhs._origine;
+  return *this;
+}
+}
+
diff --git a/ossim_plugins/ossim/otb/GMSTDateTime.h b/ossim_plugins/ossim/otb/GMSTDateTime.h
new file mode 100644
index 0000000..890066b
--- /dev/null
+++ b/ossim_plugins/ossim/otb/GMSTDateTime.h
@@ -0,0 +1,92 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef GMSTDateTime_h
+#define GMSTDateTime_h
+
+#include <ossimPluginConstants.h>
+#include <otb/JulianDate.h>
+
+namespace ossimplugins
+{
+
+
+class CivilDateTime;
+class JulianDate;
+
+/**
+ * @ingroup Date
+ * @brief This class represents a date
+ */
+class OSSIM_PLUGINS_DLL GMSTDateTime
+{
+public:
+
+  enum Ori_TSM_Green { AN1900 , AN1950 , AN2000 } ;
+
+  /**
+   * @brief constructor
+   */
+  GMSTDateTime();
+  /**
+   * @brief Destructor
+   */
+  ~GMSTDateTime();
+  /**
+   * @brief Copy constructor
+   */
+  GMSTDateTime(const GMSTDateTime& rhs);
+
+  /**
+   * @brief Constructor with date initialisation
+   */
+  GMSTDateTime(double tsm, Ori_TSM_Green origine);
+
+  /**
+   * @brief Constructor with date initialisation using a CivilDateTime
+   */
+  GMSTDateTime(CivilDateTime& rhs);
+
+  /**
+   * @brief Affectation operator
+   */
+  GMSTDateTime& operator=(const GMSTDateTime& rhs);
+
+  double get_tms()
+  {
+    return _tms;
+  };
+
+  void set_tms(double  tms)
+  {
+    _tms = tms;
+  };
+
+  Ori_TSM_Green get_origine()
+  {
+    return _origine;
+  };
+
+  void set_origine(Ori_TSM_Green origine)
+  {
+    _origine = origine;
+  }
+protected:
+
+  double _tms;
+  Ori_TSM_Green _origine;
+
+private:
+};
+}
+
+#endif
+
diff --git a/ossim_plugins/ossim/otb/GalileanEphemeris.cpp b/ossim_plugins/ossim/otb/GalileanEphemeris.cpp
new file mode 100644
index 0000000..4580fb3
--- /dev/null
+++ b/ossim_plugins/ossim/otb/GalileanEphemeris.cpp
@@ -0,0 +1,296 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include <otb/GalileanEphemeris.h>
+#include <otb/GeographicEphemeris.h>
+
+#include <otb/GMSTDateTime.h>
+
+#include <cmath>
+
+namespace ossimplugins
+{
+
+
+   GalileanEphemeris::GalileanEphemeris()
+   {
+
+   }
+
+   GalileanEphemeris::~GalileanEphemeris()
+   {
+
+   }
+
+   GalileanEphemeris::GalileanEphemeris(JSDDateTime date, double pos[3], double speed[3]) : Ephemeris(date, pos, speed)
+   {
+
+   }
+
+   GalileanEphemeris::GalileanEphemeris(const GalileanEphemeris& rhs) : Ephemeris(rhs)
+   {
+
+   }
+
+   GalileanEphemeris& GalileanEphemeris::operator=(const GalileanEphemeris& rhs)
+   {
+      ((Ephemeris)*this) = ((Ephemeris)rhs);
+      return *this;
+   }
+
+   void GalileanEphemeris::ToGeographic(GeographicEphemeris* vGeo)
+   {
+      const double OMEGATERRE  = 6.28318530717958647693 / 86164.09054 ;
+      GMSTDateTime h;
+      h.set_origine(GMSTDateTime::AN1950);
+      double s,c;
+
+      double pos[3];
+      double speed[3];
+
+      _date.AsGMSTDateTime(&h) ;
+      c = cos (h.get_tms()) ;
+      s = sin (h.get_tms()) ;
+      vGeo->set_date(_date);
+
+      pos[0] = _position[0]   * c + _position[1] * s ;
+      pos[1] = - _position[0] * s + _position[1] * c ;
+      pos[2] = _position[2] ;
+      speed[0]  =   _speed[0]  * c +  _speed[1] * s - OMEGATERRE * (_position[0] * s - _position[1] * c) ;
+      speed[1]  = - _speed[0]  * s +  _speed[1] * c - OMEGATERRE * (_position[0] * c + _position[1] * s) ;
+      speed[2]  = _speed[2] ;
+
+      vGeo->set_position(pos);
+      vGeo->set_speed(speed);
+   }
+
+   void GalileanEphemeris::ToGeographic(double greenwich,GeographicEphemeris* vGeo)
+   {
+      const double OMEGATERRE  = 6.28318530717958647693 / 86164.09054 ;
+      // int etat,
+      int ierr ;
+      double p[10],pd[10];
+      double day;
+
+      // etat = 0 ;
+
+      vGeo->set_date(this->_date);
+
+
+      day= this->_date.get_day0hTU().get_julianDate();
+
+      ierr = p2nutt( 2, greenwich, day, p, pd ) ;
+
+      double position[3];
+      double speed[3];
+
+      position[0] = _position[0]*p[1] + _position[1]*p[4] + _position[2]*p[7] ;
+
+      position[1] = _position[0]*p[2] + _position[1]*p[5] + _position[2]*p[8] ;
+
+      position[2] = _position[0]*p[3] + _position[1]*p[6] + _position[2]*p[9] ;
+
+      speed[0] = _speed[0]*p[1] +_speed[1]*p[4] + _speed[2]*p[7] + OMEGATERRE * (_position[0]*pd[1] + _position[1]*pd[4] + _position[2]*pd[7] );
+
+      speed[1] = _speed[0]*p[2] + _speed[1]*p[5] + _speed[2] *p[8] + OMEGATERRE * (_position[0]*pd[2] + _position[1]*pd[5] + _position[2]*pd[8] );
+
+      speed[2] = _speed[0]*p[3] + _speed[1]*p[6] + _speed[2]*p[9] + OMEGATERRE * (_position[0]*pd[3] + _position[1]*pd[6] + _position[2]*pd[9] );
+
+      vGeo->set_position(position);
+      vGeo->set_speed(speed);
+   }
+
+   GalileanEphemeris::operator GeographicEphemeris()
+   {
+      GeographicEphemeris rhs;
+      ToGeographic(&rhs);
+      return rhs;
+   }
+
+   GalileanEphemeris::GalileanEphemeris(GeographicEphemeris& rhs)
+   {
+      rhs.ToGalilean(this);
+   }
+
+   int GalileanEphemeris::p2nutt(int newcmb, double greenwich, double day,
+                                 double p[], double pd[] )
+   {
+      const double PI          = 3.14159265358979323846 ;
+      const double TWOPI      = 6.28318530717958647693 ;
+      // const double MU          = 3.9860047e+14 ;
+      // const double JOURCIVIL_LENGTH   = 86400.0 ;
+      // const double JOURSIDERAL = 86164.09054 ;
+      // const double OMEGATERRE  = 6.28318530717958647693 / 86164.09054 ;
+      // const double CLUM        = 2.99792458e+8 ;
+      // const double A_WGS84     = 6378137.0 ;
+      // const double B_WGS84     = 6356752.3141 ;
+/*
+
+  GIVES TRANSFORMATION MATRIX P(3,3) FROM QUASI-INERTIAL MEAN SYSTEM
+  OF DATE TO TRUE SYSTEM OF DATE OR EARTH-FIXED ROTATING SYSTEM BY
+  ROTATION (OPTIONAL) AND NUTATION. USES  SIMPLIFIED ANALYTICAL
+  MODEL DERIVED FROM THE 1980 IAU WAHR THEORY OF NUTATION (REF:
+  ASTRONOMICAL ALMANAC 1984, PP. S23-S26) BY SKIPPING MOST TERMS BELOW
+  0.03 ARCSEC. ACCURACY = 0.5D-6 RADIANS.
+
+  DAY = Julian Day
+  newcmb =-1 => TO TRUE SYSTEM OF DATE
+  = 0 => INTERMEDIATE TRANSFORMATION TO EARTH-FIXED ROTATING
+  SYSTEM BUT WITHOUT NEWCOMB'S ANGLE. (NOT TRUE-OF-DATE)
+  = 1 => TO EARTH-FIXED ROTATING SYSTEM
+
+  P(3,3) = ROTATION MATRIX SUCH THAT
+  THE TRANSFORMATION IS    R(TRANSF) = P * R(INERT)
+
+  COMMON BLOCKS FROM PEPSOC SUBROUTINE 'P2COOT' ARE USED. */
+
+      double arg[10] ;
+      double t, ff, dd, dpsi, deps;
+      double ecl, cecl, secl, dnu, srang;
+      double sra, cra, snu, cnu, sde, cde;
+      double facsin[10],faccos[10];
+
+      int i;
+
+      /*   DATA FOR NUTATION MODELLING */
+      facsin[0]=0.e0;
+      facsin[1]=-0.8338601e-04;
+      facsin[2]=-0.6393238e-05;
+      facsin[3]=-0.1102466e-05;
+      facsin[4]=0.9996858e-06;
+      facsin[5]=0.6913443e-06;
+      facsin[6]=0.3451873e-06;
+      facsin[7]=-0.2506487e-06;
+      facsin[8]=-0.1871381e-06;
+      facsin[9]=-0.1459289e-06;
+
+      faccos[0]=0.e0;
+      faccos[1]=0.4461498e-04;
+      faccos[2]=0.2780891e-05;
+      faccos[3]=0.4736630e-06;
+      faccos[4]=-0.4339082e-06;
+      faccos[5]=0.2617994e-07;
+      faccos[6]=-0.3393696e-08;
+      faccos[7]=0.1085983e-06;
+      faccos[8]=0.9696274e-07;
+      faccos[9]=0.6254096e-07;
+
+
+      /*  ECL = OBLIQUITY OF ECLIPTIC AT EPOCH J2000.0
+          ECL CHANGES BY -0.01300 DEG/CENTURY.
+          ECL = 23 DEG + 26 ' + 21.4119 " */
+      ecl = PI/180.e0*(23.e0 + (26.e0 + 21.4119e0/6.e1)/6.e1);
+      cecl = cos(ecl);
+      secl = sin(ecl);
+
+      /*t= Julian day relative to year 2000 at 12:00:00 */
+      t = day-2451540. - 0.5 ;
+
+      /*  L = MEAN ANOMALY OF THE MOON */
+      arg[6] = fmod( 0.2355548394e+01 + t*( 0.2280271437e+00 + t* 0.1137830e-12 ),TWOPI);
+
+      /*C  L-PRIME = MEAN ANOMALY OF THE SUN (EARTH) */
+      arg[5] = fmod( 0.6240035939e+01 + t*( 0.1720197005e-01 - t* 0.2096864e-14 ),TWOPI);
+
+      /*  F = L - OMEGA (SEE ABOVE AND BELOW) */
+      ff = fmod( 0.1627901934e+01 + t*( 0.2308957196e+00 - t* 0.4817699e-13 ),TWOPI);
+
+      /*  D = MEAN ELONGATION OF THE MOON FROM THE SUN */
+      dd = fmod( 0.5198469514e+01 + t*( 0.2127687104e+00 - t* 0.2504244e-13 ),TWOPI);
+
+      /*  OMEGA = LONGITUDE OF MOON'S ASCENDING NODE FROM MEAN EQUINOX OF DATE */
+      arg[0]=0.e0;
+      arg[1] = fmod( 0.2182438624e+01 - t*( 0.9242175478e-03 - t* 0.2709206e-13 ),TWOPI);
+
+      arg[3] = 2.e0*(ff + arg[1]);
+      arg[2] = arg[3] - 2.e0*dd ;
+      arg[4] = 2.e0*arg[1] ;
+      arg[7] = arg[5] + arg[2] ;
+      arg[8] = 2.e0*ff + arg[1] ;
+      arg[9] = arg[6] + arg[3] ;
+
+      dpsi = 0.e0;
+      deps = 0.e0;
+      for ( i=1 ; i<=9; i++ )
+      {
+         dpsi = dpsi + facsin[i] * sin(arg[i]);
+         deps = deps + faccos[i] * cos(arg[i]);
+      }
+
+
+      /*  ROTATION OF -deps AROUND THE X-AXIS */
+      cde=cos(deps);
+      sde=sin(deps);
+
+      /*  ROTATION OF DNU = dpsi*SIN(ECLIPT) AROUND THE Y-AXIS */
+      dnu = dpsi*secl;
+      cnu=cos(dnu);
+      snu=sin(dnu);
+
+      /*  SELECT WHICH ROTATION IS WANTED FOR THE Z-AXIS */
+      srang=0.e0;
+      if (newcmb == -1)
+      {
+         /*  ROTATION OF SRANG = -DMU = -dpsi*COS(ECLIPT) AROUND THE Z-AXIS */
+         srang = -dpsi*cecl;
+      }
+      else if ( newcmb == 0)
+      {
+         srang = 0.e0;
+      }
+      else if ( newcmb == 1 )
+      {
+         /*  SIDEREAL ANGLE, FROM 'COOT20' WITH NEWCOMB'S FORMULA:*/
+         /*srang = fmod(STD20R+(OMT20R+OMQ20R*day)*day,TWOPI);*/
+      }
+      else if ( newcmb == 2 )
+      {
+         /*  SIDEREAL ANGLE, FROM INPUT */
+         srang = fmod(greenwich*PI/180.e0,TWOPI) ;
+         /*printf("srang dans p2nutt %g",greenwich);*/
+      }
+      else
+      {
+         return -1;;
+      }
+
+
+      sra=sin(srang);
+      cra=cos(srang);
+
+      /*  ROTATION MATRIX = RZ(SRANG)*RX(-deps)*RY(DNU) */
+      p[0] = 0.e0;
+      p[1] = cra*cnu - sra*sde*snu ;
+      p[2] = -sra*cnu - cra*sde*snu ;
+      p[3] = cde*snu ;
+      p[4] = sra*cde ;
+      p[5] = cra*cde ;
+      p[6] = sde ;
+      p[7] = -cra*snu - sra*sde*cnu ;
+      p[8] = sra*snu - cra*sde*cnu ;
+      p[9] = cde*cnu ;
+
+      pd[0] = 0.e0;
+      pd[1] = -sra*cnu - cra*sde*snu ;
+      pd[2] = -cra*cnu + sra*sde*snu ;
+      pd[3] = 0. ;
+      pd[4] = cra*cde ;
+      pd[5] = -sra*cde ;
+      pd[6] = 0. ;
+      pd[7] = sra*snu - cra*sde*cnu ;
+      pd[8] = cra*snu + sra*sde*cnu ;
+      pd[9] = 0. ;
+
+      return 1;
+
+   }
+}
+
diff --git a/ossim_plugins/ossim/otb/GalileanEphemeris.h b/ossim_plugins/ossim/otb/GalileanEphemeris.h
new file mode 100644
index 0000000..928835f
--- /dev/null
+++ b/ossim_plugins/ossim/otb/GalileanEphemeris.h
@@ -0,0 +1,78 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef GalileanEphemeride_h
+#define GalileanEphemeride_h
+
+#include <ossimPluginConstants.h>
+#include <otb/Ephemeris.h>
+
+namespace ossimplugins
+{
+
+
+class GeographicEphemeris;
+/**
+ * @ingroup Ephemeris
+ * @brief This class represents an ephemeris in Galilean coordinates system
+ */
+class OSSIM_PLUGINS_DLL GalileanEphemeris : public Ephemeris
+{
+public:
+  /**
+   * @brief Constructor
+   */
+  GalileanEphemeris();
+
+  /**
+    * @brief Destructor
+    */
+  ~GalileanEphemeris();
+
+  /**
+   * @brief Constructor with initialisations
+   */
+  GalileanEphemeris(JSDDateTime date, double pos[3], double speed[3]);
+
+  /**
+   * @brief Copy constructor
+   */
+  GalileanEphemeris(const GalileanEphemeris& rhs);
+
+  GalileanEphemeris(GeographicEphemeris& rhs);
+  /**
+   * @brief Affectation operator
+   */
+  GalileanEphemeris& operator=(const GalileanEphemeris& rhs);
+
+  /**
+   * @brief This fonction converts the current ephemeris in the Geographic coordinates syst�m
+   */
+  void ToGeographic(GeographicEphemeris* vGeo);
+  void ToGeographic(double greenwich,GeographicEphemeris* vGeo);
+
+  operator GeographicEphemeris();
+
+  /**
+   * @brief This function creates a copy of the current class
+   */
+  virtual Ephemeris* Clone()
+  {
+    return new GalileanEphemeris(*this);
+  };
+protected:
+  int p2nutt(int newcmb, double greenwich, double day, double p[], double pd[] );
+private:
+};
+}
+
+#endif
+
diff --git a/ossim_plugins/ossim/otb/GeodesicCoordinate.cpp b/ossim_plugins/ossim/otb/GeodesicCoordinate.cpp
new file mode 100644
index 0000000..375ed00
--- /dev/null
+++ b/ossim_plugins/ossim/otb/GeodesicCoordinate.cpp
@@ -0,0 +1,45 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include <otb/GeodesicCoordinate.h>
+
+namespace ossimplugins
+{
+
+
+
+GeodesicCoordinate::GeodesicCoordinate()
+{
+}
+
+GeodesicCoordinate::~GeodesicCoordinate()
+{
+}
+
+GeodesicCoordinate::GeodesicCoordinate(double x, double y, double z): Coordinate(x,y,z)
+{
+}
+
+GeodesicCoordinate::GeodesicCoordinate(const GeodesicCoordinate& rhs): Coordinate((Coordinate)rhs)
+{
+}
+
+GeodesicCoordinate& GeodesicCoordinate::operator=(const GeodesicCoordinate& rhs)
+{
+  _x = rhs._x;
+  _y = rhs._x;
+  _z = rhs._x;
+
+  return *this;
+}
+
+}
+
diff --git a/ossim_plugins/ossim/otb/GeodesicCoordinate.h b/ossim_plugins/ossim/otb/GeodesicCoordinate.h
new file mode 100644
index 0000000..5b7acea
--- /dev/null
+++ b/ossim_plugins/ossim/otb/GeodesicCoordinate.h
@@ -0,0 +1,56 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef GeodesicCoordinate_h
+#define GeodesicCoordinate_h
+
+#include <ossimPluginConstants.h>
+#include <otb/Coordinate.h>
+
+namespace ossimplugins
+{
+
+
+/**
+ * @ingroup Date
+ * @brief This class represents a coordinate in a geodesic reference
+ */
+ class OSSIM_PLUGINS_DLL GeodesicCoordinate : public Coordinate
+ {
+ public:
+  /**
+    * @brief Constructor
+    */
+  GeodesicCoordinate();
+  /**
+   * @brief Destructor
+   */
+  ~GeodesicCoordinate();
+  /**
+   * @brief Cosntructor with initializations
+   */
+  GeodesicCoordinate(double x, double y, double z);
+  /**
+   * @brief Copy constructor
+   */
+  GeodesicCoordinate(const GeodesicCoordinate& rhs);
+
+  /**
+   * @brief Affectation operator
+   */
+  GeodesicCoordinate& operator=(const GeodesicCoordinate& rhs);
+ protected:
+ private:
+ };
+}
+
+ #endif
+
diff --git a/ossim_plugins/ossim/otb/GeographicEphemeris.cpp b/ossim_plugins/ossim/otb/GeographicEphemeris.cpp
new file mode 100644
index 0000000..c3b3290
--- /dev/null
+++ b/ossim_plugins/ossim/otb/GeographicEphemeris.cpp
@@ -0,0 +1,86 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include <otb/GeographicEphemeris.h>
+#include <otb/GalileanEphemeris.h>
+
+#include <otb/GMSTDateTime.h>
+
+#include <cmath>
+
+namespace ossimplugins
+{
+
+
+GeographicEphemeris::GeographicEphemeris() : Ephemeris()
+{
+}
+
+GeographicEphemeris::~GeographicEphemeris()
+{
+}
+
+GeographicEphemeris::GeographicEphemeris(JSDDateTime date, double pos[3], double speed[3]) : Ephemeris(date, pos, speed)
+{
+}
+
+GeographicEphemeris::GeographicEphemeris(const GeographicEphemeris& rhs) : Ephemeris(rhs)
+{
+}
+
+GeographicEphemeris& GeographicEphemeris::operator=(const GeographicEphemeris& rhs)
+{
+  ((Ephemeris)*this) = ((Ephemeris)rhs);
+  return *this;
+}
+
+
+void GeographicEphemeris::ToGalilean(GalileanEphemeris* vGal)
+{
+  const double OMEGATERRE  = 6.28318530717958647693 / 86164.09054 ;
+  GMSTDateTime h;
+  h.set_origine(GMSTDateTime::AN1950);
+
+  double s,c;
+  _date.AsGMSTDateTime(&h) ;
+
+    c = cos (h.get_tms()) ;
+    s = sin (h.get_tms()) ;
+  vGal->set_date(_date);
+
+  double pos[3];
+  double speed[3];
+
+    pos[0] = _position[0] * c - _position[1] * s ;
+    pos[1] = _position[0] * s + _position[1] * c ;
+    pos[2] = _position[2] ;
+
+    speed[0]  =  _speed[0]  * c -  _speed[1] * s - OMEGATERRE * (_position[0] * s + _position[1] * c) ;
+    speed[1]  =  _speed[0]  * s +  _speed[1] * c + OMEGATERRE * (_position[0] * c - _position[1] * s) ;
+    speed[2]  = _speed[2] ;
+
+  vGal->set_position(pos);
+    vGal->set_speed(speed);
+}
+
+GeographicEphemeris::operator GalileanEphemeris()
+{
+  GalileanEphemeris rhs;
+  ToGalilean(&rhs);
+  return rhs;
+}
+
+GeographicEphemeris::GeographicEphemeris(GalileanEphemeris& rhs)
+{
+  rhs.ToGeographic(this);
+}
+}
+
diff --git a/ossim_plugins/ossim/otb/GeographicEphemeris.h b/ossim_plugins/ossim/otb/GeographicEphemeris.h
new file mode 100644
index 0000000..53b7699
--- /dev/null
+++ b/ossim_plugins/ossim/otb/GeographicEphemeris.h
@@ -0,0 +1,75 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef GeographicEphemeride_h
+#define GeographicEphemeride_h
+
+#include <ossimPluginConstants.h>
+#include <otb/Ephemeris.h>
+
+namespace ossimplugins
+{
+
+
+class GalileanEphemeris;
+/**
+ * @ingroup Ephemeris
+ * @brief This class represent an ephemeris in Geographic coordinates system
+ */
+class OSSIM_PLUGINS_DLL GeographicEphemeris : public Ephemeris
+{
+public:
+  /**
+   * @brief Constructor
+   */
+  GeographicEphemeris();
+  /**
+    * @brief Destructor
+    */
+  virtual ~GeographicEphemeris();
+
+  /**
+   * @brief Constructor with initialisations
+   */
+  GeographicEphemeris(JSDDateTime date, double pos[3], double speed[3]);
+  /**
+   * @brief Copy constructor
+   */
+  GeographicEphemeris(const GeographicEphemeris& rhs);
+
+  GeographicEphemeris(GalileanEphemeris& rhs);
+  /**
+   * @brief Affectation operator
+   */
+  GeographicEphemeris& operator=(const GeographicEphemeris& rhs);
+
+  /**
+   * @brief This fonction converts the current ephemeris in the Galilean coordinates system
+   */
+  void ToGalilean(GalileanEphemeris* vGal);
+
+  operator GalileanEphemeris();
+
+  /**
+   * @brief This function creates a copy of the current class
+   */
+  virtual Ephemeris* Clone()
+  {
+    return new GeographicEphemeris(*this);
+  };
+protected:
+private:
+
+};
+}
+
+#endif
+
diff --git a/ossim_plugins/ossim/otb/HermiteInterpolator.cpp b/ossim_plugins/ossim/otb/HermiteInterpolator.cpp
new file mode 100644
index 0000000..857f2fb
--- /dev/null
+++ b/ossim_plugins/ossim/otb/HermiteInterpolator.cpp
@@ -0,0 +1,355 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include <otb/HermiteInterpolator.h>
+
+#include <string>
+#include <cassert>
+#include <cmath>
+
+namespace ossimplugins
+{
+
+
+HermiteInterpolator::HermiteInterpolator():
+  theNPointsAvailable(0),
+  theXValues(NULL),
+  theYValues(NULL),
+  thedYValues(NULL),
+  prodC(NULL),
+  sumC(NULL),
+  isComputed(false)
+{
+}
+
+HermiteInterpolator::HermiteInterpolator(int nbrPoints, double* x, double* y, double* dy):
+  theNPointsAvailable(nbrPoints),
+   prodC(NULL),
+   sumC(NULL),
+  isComputed(false)
+{
+  if(x != NULL)
+  {
+    theXValues = new double[theNPointsAvailable];
+    for (int i=0;i<theNPointsAvailable;i++)
+    {
+      theXValues[i] = x[i];
+    }
+  }
+  else
+  {
+    theXValues = NULL;
+  }
+
+  if(y != NULL)
+  {
+    theYValues = new double[theNPointsAvailable];
+    for (int i=0;i<theNPointsAvailable;i++)
+    {
+      theYValues[i] = y[i];
+    }
+  }
+  else
+  {
+    theYValues = NULL;
+  }
+
+  if(dy != NULL)
+  {
+    thedYValues = new double[theNPointsAvailable];
+    for (int i=0;i<theNPointsAvailable;i++)
+    {
+      thedYValues[i] = dy[i];
+    }
+  }
+  else
+  {
+    thedYValues = NULL;
+  }
+
+  for (int i = 1 ; i < theNPointsAvailable ; i++)
+  {
+    /**
+     * @todo Verifier que l'interpolateur n'ai pas besoin ques les abscisses soitent strictement croissantes
+     */
+
+    /*
+     * Les abscisses ne sont pas croissantes
+     */
+//    if (theXValues[i] <= theXValues[i-1])
+//      std::cerr << "WARNING: Hermite interpolation assumes increasing x values" << std::endl;
+    assert(theXValues[i] > theXValues[i-1]);
+  }
+}
+
+HermiteInterpolator::~HermiteInterpolator()
+{
+  Clear();
+}
+
+HermiteInterpolator::HermiteInterpolator(const HermiteInterpolator& rhs):
+  theNPointsAvailable(rhs.theNPointsAvailable),
+  prodC(NULL),
+  sumC(NULL),
+  isComputed(false)
+{
+  if(rhs.theXValues != NULL)
+  {
+    theXValues = new double[theNPointsAvailable];
+    for (int i=0;i<theNPointsAvailable;i++)
+    {
+      theXValues[i] = rhs.theXValues[i];
+    }
+  }
+  else
+  {
+    theXValues = NULL;
+  }
+
+  if(rhs.theYValues != NULL)
+  {
+    theYValues = new double[theNPointsAvailable];
+    for (int i=0;i<theNPointsAvailable;i++)
+    {
+      theYValues[i] = rhs.theYValues[i];
+    }
+  }
+  else
+  {
+    theYValues = NULL;
+  }
+
+  if(rhs.thedYValues != NULL)
+  {
+    thedYValues = new double[theNPointsAvailable];
+    for (int i=0;i<theNPointsAvailable;i++)
+    {
+      thedYValues[i] = rhs.thedYValues[i];
+    }
+  }
+  else
+  {
+    thedYValues = NULL;
+  }
+}
+
+HermiteInterpolator& HermiteInterpolator::operator =(const HermiteInterpolator& rhs)
+{
+  Clear();
+  theNPointsAvailable = rhs.theNPointsAvailable;
+  isComputed = false;
+  if(rhs.theXValues != NULL)
+  {
+    theXValues = new double[theNPointsAvailable];
+    for (int i=0;i<theNPointsAvailable;i++)
+    {
+      theXValues[i] = rhs.theXValues[i];
+    }
+  }
+  else
+  {
+    theXValues = NULL;
+  }
+
+  if(rhs.theYValues != NULL)
+  {
+    theYValues = new double[theNPointsAvailable];
+    for (int i=0;i<theNPointsAvailable;i++)
+    {
+      theYValues[i] = rhs.theYValues[i];
+    }
+  }
+  else
+  {
+    theYValues = NULL;
+  }
+
+  if(rhs.thedYValues != NULL)
+  {
+    thedYValues = new double[theNPointsAvailable];
+    for (int i=0;i<theNPointsAvailable;i++)
+    {
+      thedYValues[i] = rhs.thedYValues[i];
+    }
+  }
+  else
+  {
+    thedYValues = NULL;
+  }
+  prodC = NULL; 
+  sumC = NULL;
+   
+  return *this;
+}
+
+// Interpolation method for the value and the derivative
+int HermiteInterpolator::Interpolate(double x, double& y, double& dy) const
+{
+  //NOTE assume that x is increasing
+
+  // Not enough points to interpolate
+  if (theNPointsAvailable < 2) return -1;
+
+  y = 0.0;
+  dy = 0.0;
+
+  double epsilon = 0.0000000000001;
+
+  //Precompute useful value if they are not available
+  if (!isComputed)
+  {
+    Precompute();
+  }
+
+  for (int i = 0; i < theNPointsAvailable; i++)
+  {
+    double si = 0.0;
+    double hi = 1.0;
+    double ui = 0; //derivative computation
+    double r = x - theXValues[i];
+
+    // check if the point is on the list
+    if ( std::abs(r) < epsilon )
+    {
+      y = theYValues[i];
+      dy = thedYValues[i];
+      return 0;
+    }
+
+    for (int j = 0; j < theNPointsAvailable; j++)
+    {
+      if (j != i)
+      {
+        hi = hi * (x - theXValues[j]);
+        ui = ui + 1 / (x - theXValues[j]);//derivative computation
+      }
+    }
+    hi *= prodC[i];
+    si = sumC[i];
+
+    double f = 1.0 - 2.0 * r * si;
+
+    y += (theYValues[i] * f + thedYValues[i] * r) * hi * hi;
+
+    ui *= hi;//derivative computation
+
+    double fp = 2.0 * hi * (ui * (1.0 - 2.0 * si * r) - hi * si);//derivative computation
+    double d = hi * (hi + 2.0 * r * ui);//derivative computation
+
+    dy += fp * theYValues[i] + d * thedYValues[i];//derivative computation
+
+  }
+
+  return 0;
+}
+
+// Interpolation method for the value only
+// this is about 5 times faster and should be used when time
+// is a constraint.
+int HermiteInterpolator::Interpolate(double x, double& y) const
+{
+  //NOTE assume that x is increasing
+
+  // Not enough points to interpolate
+  if (theNPointsAvailable < 2) return -1;
+
+  y = 0.0;
+
+  //Precompute useful value if they are not available
+  if (!isComputed)
+  {
+    Precompute();
+  }
+
+  for (int i = 0; i < theNPointsAvailable; i++)
+  {
+    double si = 0.0;
+    double hi = 1.0;
+    double r = x - theXValues[i];
+
+    for (int j = 0; j < theNPointsAvailable; j++)
+    {
+      if (j != i)
+      {
+        hi = hi * (x - theXValues[j]);
+      }
+    }
+    hi *= prodC[i];
+    si = sumC[i];
+
+    double f = 1.0 - 2.0 * r * si;
+
+    y += (theYValues[i] * f + thedYValues[i] * r) * hi * hi;
+
+  }
+
+  return 0;
+}
+
+int HermiteInterpolator::Precompute() const
+{
+  prodC = new double[theNPointsAvailable];
+  sumC= new double[theNPointsAvailable];
+
+  for (int i = 0; i < theNPointsAvailable; i++)
+  {
+    prodC[i] = 1;
+    sumC[i] = 0;
+    for (int j = 0; j < theNPointsAvailable; j++)
+    {
+      if (j != i)
+      {
+        double v = 1.0 / (theXValues[i] - theXValues[j]);
+        prodC[i] *= v;
+        sumC[i]  += v;
+      }
+    }
+  }
+  isComputed = true;
+  return 0;
+}
+
+void HermiteInterpolator::Clear()
+{
+  if (theXValues != NULL)
+  {
+    delete[] theXValues;
+    theXValues = NULL;
+  }
+
+  if (theYValues != NULL)
+  {
+    delete[] theYValues;
+    theYValues = NULL;
+  }
+
+  if (thedYValues != NULL)
+  {
+    delete[] thedYValues;
+    thedYValues = NULL;
+  }
+
+  if (prodC != NULL)
+  {
+    delete[] prodC;
+    prodC = NULL;
+  }
+
+  if (sumC != NULL)
+  {
+    delete[] sumC;
+    prodC = NULL;
+  }
+  isComputed = false;
+  theNPointsAvailable = 0;
+}
+}
+
diff --git a/ossim_plugins/ossim/otb/HermiteInterpolator.h b/ossim_plugins/ossim/otb/HermiteInterpolator.h
new file mode 100644
index 0000000..db4114b
--- /dev/null
+++ b/ossim_plugins/ossim/otb/HermiteInterpolator.h
@@ -0,0 +1,97 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef HermiteInterpolator_h
+#define HermiteInterpolator_h
+
+#include <ossimPluginConstants.h>
+
+namespace ossimplugins
+{
+
+
+
+/**
+ * @brief Abstract interpolator
+ * @see Interpolate
+ */
+class OSSIM_PLUGINS_DLL HermiteInterpolator
+{
+public:
+   /**
+    * @brief Constructor
+    */
+   HermiteInterpolator();
+
+   /**
+    * @brief Constructor with initializations
+    * @param nbrPoints Number of points used to perform the interpolation
+    * @param x Values of the points abscissa
+    * @param y Values of the points
+    * @param dy Values of the differential coefficients
+    */
+   HermiteInterpolator(int nbrPoints, double* x, double* y, double* dy);
+
+   /**
+    * @brief Destructor
+    */
+   ~HermiteInterpolator();
+
+   /**
+    * @brief Copy constructor
+    */
+   HermiteInterpolator(const HermiteInterpolator& rhs);
+
+   /**
+    * @brief Affectation operator
+    */
+   HermiteInterpolator& operator =(const HermiteInterpolator& rhs);
+
+   /**
+    * @brief This function performs the interpolation for the abscissa x
+    * @param x Abscissa of the interpolation
+    * @param y [out] value of the point at the abscissa x
+    * @param dy [out] value of the differential coefficient at abscissa x
+    * @return Different of 0 if an error occurs
+    */
+   int Interpolate(double x, double& y, double& dy) const;
+
+   /**
+    * @brief This function performs the interpolation for the abscissa x
+    * @param x Abscissa of the interpolation
+    * @param y [out] value of the point at the abscissa x
+    * @return Different of 0 if an error occurs
+    */
+   int Interpolate(double x, double& y) const;
+
+protected:
+
+   void Clear();
+   int theNPointsAvailable;
+   double* theXValues;
+   double* theYValues;
+   double* thedYValues;
+
+   mutable double* prodC;
+   mutable double* sumC;
+   mutable bool isComputed;
+
+   int Precompute() const; // const in a semantic way
+
+
+private:
+};
+}
+
+#endif
+
+
+
diff --git a/ossim_plugins/ossim/otb/ImageNoise.cpp b/ossim_plugins/ossim/otb/ImageNoise.cpp
new file mode 100644
index 0000000..2baf7e7
--- /dev/null
+++ b/ossim_plugins/ossim/otb/ImageNoise.cpp
@@ -0,0 +1,283 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include <otb/ImageNoise.h>
+#include <ossim/base/ossimDpt3d.h>
+#include <ossim/base/ossimKeywordlist.h>
+#include <ossim/base/ossimNotify.h>
+#include <ossim/base/ossimString.h>
+
+namespace ossimplugins
+{
+
+
+static const char PREFIX[]          = "imageNoise.";
+// static const char TIME_UTC[] = "timeUTC";
+static const char UTC_TIME[] = "timeUTC";
+static const char NOISE_ESTIMATE[] = "noiseEstimate.";
+static const char REFERENCE_POINT[] = "referencePoint";
+static const char VALIDITY_RANGE_MIN[] = "validityRangeMin";
+static const char VALIDITY_RANGE_MAX[] = "validityRangeMax";
+static const char POLYNOMIAL_DEGREE[] = "polynomialDegree";
+static const char COEFFICIENT[] = "coefficient";
+static const char NOISE_ESTIMATE_CONFIDENCE[] = "noiseEstimateConfidence";
+
+ImageNoise::ImageNoise():
+     _timeUTC(),
+     _validityRangeMin(0.),
+     _validityRangeMax(0.),
+     _referencePoint(0.),
+     _polynomialDegree(0),
+     _polynomialCoefficients(0)
+{
+}
+
+ImageNoise::~ImageNoise()
+{
+}
+
+
+ImageNoise::ImageNoise(const ImageNoise& rhs):
+     _timeUTC(rhs._timeUTC),
+     _validityRangeMin(rhs._validityRangeMin),
+     _validityRangeMax(rhs._validityRangeMax),
+     _referencePoint(rhs._referencePoint),
+     _polynomialDegree(rhs._polynomialDegree),
+     _polynomialCoefficients(rhs._polynomialCoefficients)
+{
+}
+
+ImageNoise& ImageNoise::operator=(const ImageNoise& rhs)
+{
+     _timeUTC = rhs._timeUTC;
+     _validityRangeMin = rhs._validityRangeMin;
+     _validityRangeMax = rhs._validityRangeMax;
+     _referencePoint = rhs._referencePoint;
+     _polynomialDegree = rhs._polynomialDegree;
+    _polynomialCoefficients = rhs._polynomialCoefficients;
+  return *this;
+}
+
+bool ImageNoise::saveState(ossimKeywordlist& kwl, const char* prefix) const
+{
+   std::string pfx;
+   std::string pfx2;
+   if (prefix)
+   {
+      pfx = prefix;
+   }
+  pfx += PREFIX;
+  kwl.add(pfx.c_str(), UTC_TIME,  _timeUTC);
+
+  pfx2 = pfx + NOISE_ESTIMATE;
+  kwl.add(pfx2.c_str(), VALIDITY_RANGE_MIN,  _validityRangeMin);
+  kwl.add(pfx2.c_str(), VALIDITY_RANGE_MAX,  _validityRangeMax);
+  kwl.add(pfx2.c_str(), REFERENCE_POINT,  _referencePoint);
+  kwl.add(pfx2.c_str(), POLYNOMIAL_DEGREE,  _polynomialDegree);
+
+  for(unsigned int i=0 ; i<_polynomialCoefficients.size();i++)
+  {
+         ossimString iStr = ossimString::toString(i);
+         ossimString kw = ossimString(COEFFICIENT) + "["+iStr+ "]";
+         kwl.add(pfx2.c_str(), kw.c_str(), _polynomialCoefficients[i]);
+  }
+
+   return true;
+}
+
+bool ImageNoise::loadState(const ossimKeywordlist& kwl, const char* prefix)
+{
+  static const char MODULE[] = "ImageNoise::loadState";
+  bool result = true;
+  std::string pfx;
+  std::string pfx2;
+  if (prefix)
+  {
+    pfx = prefix;
+  }
+   ossimString s;
+   const char* lookup = 0;
+
+  pfx += PREFIX;
+  lookup = kwl.find(pfx.c_str(), UTC_TIME);
+  if (lookup)
+  {
+    s = lookup;
+    _timeUTC = s;
+  }
+  else
+  {
+    ossimNotify(ossimNotifyLevel_WARN)
+         << MODULE << " Keyword not found: " << UTC_TIME << " in "<<pfx.c_str()<<" path.\n";
+    result = false;
+  }
+  pfx2 = pfx + NOISE_ESTIMATE;
+  lookup = kwl.find(pfx2.c_str(), VALIDITY_RANGE_MIN);
+  if (lookup)
+  {
+    s = lookup;
+    _validityRangeMin = s.toDouble();
+  }
+  else
+  {
+    ossimNotify(ossimNotifyLevel_WARN)
+         << MODULE << " Keyword not found: " << VALIDITY_RANGE_MIN << " in "<<pfx2.c_str()<<" path.\n";
+    result = false;
+  }
+  lookup = kwl.find(pfx2.c_str(), VALIDITY_RANGE_MAX);
+  if (lookup)
+  {
+    s = lookup;
+    _validityRangeMax = s.toDouble();
+  }
+  else
+  {
+    ossimNotify(ossimNotifyLevel_WARN)
+         << MODULE << " Keyword not found: " << VALIDITY_RANGE_MAX << " in "<<pfx2.c_str()<<" path\n";
+    result = false;
+  }
+  lookup = kwl.find(pfx2.c_str(), REFERENCE_POINT);
+  if (lookup)
+  {
+    s = lookup;
+    _referencePoint = s.toDouble();
+  }
+  else
+  {
+    ossimNotify(ossimNotifyLevel_WARN)
+         << MODULE << " Keyword not found: " << REFERENCE_POINT << " in "<<pfx2.c_str()<<" path\n";
+    result = false;
+  }
+  lookup = kwl.find(pfx2.c_str(), POLYNOMIAL_DEGREE);
+  if (lookup)
+  {
+    s = lookup;
+    _polynomialDegree = s.toInt32();
+  }
+  else
+  {
+    ossimNotify(ossimNotifyLevel_WARN)
+         << MODULE << " Keyword not found: " << POLYNOMIAL_DEGREE << " in "<<pfx2.c_str()<<" path\n";
+    result = false;
+  }
+
+  for(unsigned int i=0 ; i<_polynomialDegree+1;i++)
+  {
+      ossimString iStr = ossimString::toString(i);
+      ossimString kw = ossimString(COEFFICIENT) + "["+iStr+ "]";
+      lookup = kwl.find(pfx2.c_str(), kw.c_str());
+      if (lookup)
+      {
+        s = lookup;
+        _polynomialCoefficients.push_back( s.toDouble() );
+      }
+      else
+      {
+        ossimNotify(ossimNotifyLevel_WARN)
+         << MODULE << " Keyword not found: " << kw.c_str() << " in "<<pfx2.c_str()<<" path\n";
+        result = false;
+      }
+  }
+
+
+/*
+   pfx += "ImageNoise.";
+
+   const char* lookup = 0;
+   ossimString s;
+   double d;
+
+   lookup = kwl.find(pfx.c_str(), DATE_JULIAN_KW);
+   if (lookup)
+   {
+      s = lookup;
+      d = s.toDouble();
+      JulianDate jd(d);
+      _date.set_day0hTU(jd);
+   }
+   else
+   {
+      ossimNotify(ossimNotifyLevel_WARN)
+         << MODULE << " Keyword not found: " << DATE_JULIAN_KW << "\n";
+
+      result = false;
+   }
+
+   lookup = kwl.find(pfx.c_str(), DATE_SECOND_KW);
+   if (lookup)
+   {
+      s = lookup;
+      d = s.toDouble();
+      _date.set_second(d);
+   }
+   else
+   {
+      ossimNotify(ossimNotifyLevel_WARN)
+         << MODULE << " Keyword not found: " << DATE_SECOND_KW << "\n";
+      result = false;
+   }
+
+   lookup = kwl.find(pfx.c_str(), DATE_DECIMAL_KW);
+   if (lookup)
+   {
+      s = lookup;
+      d = s.toDouble();
+      _date.set_decimal(d);
+   }
+   else
+   {
+      ossimNotify(ossimNotifyLevel_WARN)
+         << MODULE << " Keyword not found: " << DATE_DECIMAL_KW << "\n";
+      result = false;
+   }
+
+   lookup = kwl.find(pfx.c_str(), POSITION_KW);
+   if (lookup)
+   {
+      std::string ps = lookup;
+
+      ossimDpt3d pt;
+      pt.toPoint(ps);
+
+      _position[0] = pt.x;
+      _position[1] = pt.y;
+      _position[2] = pt.z;
+   }
+   else
+   {
+      ossimNotify(ossimNotifyLevel_WARN)
+         << MODULE << " Keyword not found: " << POSITION_KW << "\n";
+      result = false;
+   }
+
+   lookup = kwl.find(pfx.c_str(), VELOCITY_KW);
+   if (lookup)
+   {
+      std::string ps = lookup;
+
+      ossimDpt3d pt;
+      pt.toPoint(ps);
+
+      _speed[0] = pt.x;
+      _speed[1] = pt.y;
+      _speed[2] = pt.z;
+   }
+   else
+   {
+      ossimNotify(ossimNotifyLevel_WARN)
+         << MODULE << " Keyword not found: " << VELOCITY_KW << "\n";
+      result = false;
+   }
+*/
+   return result;
+}
+}
+
diff --git a/ossim_plugins/ossim/otb/ImageNoise.h b/ossim_plugins/ossim/otb/ImageNoise.h
new file mode 100644
index 0000000..51467aa
--- /dev/null
+++ b/ossim_plugins/ossim/otb/ImageNoise.h
@@ -0,0 +1,163 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef ImageNoise_h
+#define ImageNoise_h
+
+#include <vector>
+#include <ossim/base/ossimString.h>
+#include <ossimPluginConstants.h>
+
+
+class ossimKeywordlist;
+
+namespace ossimplugins
+{
+
+
+/**
+ * @ingroup ImageNoise
+ * @brief This class represents an ImageNoise
+ */
+class OSSIM_PLUGINS_DLL ImageNoise
+{
+public:
+   /**
+    * @brief Constructor
+    */
+   ImageNoise();
+
+   /**
+    * @brief Destructor
+    */
+   virtual ~ImageNoise();
+
+   /**
+    * @brief Copy constructor
+    */
+   ImageNoise(const ImageNoise& rhs);
+
+   /**
+    * @brief Affectation operator
+    */
+   ImageNoise& operator=(const ImageNoise& rhs);
+
+   /**
+    * @brief Method to save object state to a keyword list.
+    * @param kwl Keyword list to save to.
+    * @param prefix added to keys when saved.
+    * @return true on success, false on error.
+    */
+   bool saveState(ossimKeywordlist& kwl, const char* prefix=0) const;
+
+   /**
+    * @brief Method to the load (recreate) the state of the object from a
+    * keyword list. Return true if ok or false on error.
+    * @return true if load OK, false on error
+    */
+   bool loadState (const ossimKeywordlist &kwl, const char *prefix=0);
+
+   void set_timeUTC(const ossimString& value)
+   {
+      _timeUTC = value;
+   }
+
+  const ossimString & get_timeUTC(void) const
+  {
+    return _timeUTC;
+  }
+
+   void set_validityRangeMin(double value)
+   {
+      _validityRangeMin = value;
+   }
+  
+  double get_validityRangeMin(void) const
+  {
+    return _validityRangeMin;
+  }
+
+   void set_validityRangeMax(double value)
+   {
+      _validityRangeMax = value;
+   }
+
+  double get_validityRangeMax(void) const
+  {
+    return _validityRangeMax;
+  }
+
+   void set_referencePoint(double value)
+   {
+      _referencePoint = value;
+   }
+
+  double get_referencePoint(void) const
+  {
+    return _referencePoint;
+  }
+  
+   void set_polynomialDegree(unsigned int value)
+   {
+      _polynomialDegree = value;
+   }
+
+  unsigned int get_polynomialDegree() const
+  {
+    return _polynomialDegree;
+  }
+
+
+   void set_polynomialCoefficients(const std::vector<double>& value)
+   {
+      _polynomialCoefficients = value;
+   }
+
+  const std::vector<double> & get_polynomialCoefficients(void) const
+  {
+    return _polynomialCoefficients;
+  }
+
+protected:
+
+      /**
+       * @brief TimeUTC (Noise/ImageNoise node).
+       */
+      ossimString _timeUTC;
+
+      /**
+       * @brief ValidityRangeMin (Noise/ImageNoise node).
+       */
+      double _validityRangeMin;
+      /**
+       * @brief ValidityRangeMax (Noise/ImageNoise node).
+       */
+      double _validityRangeMax;
+      /**
+       * @brief Reference point (Noise/ImageNoise node).
+       */
+      double _referencePoint;
+
+      /**
+       * @brief Polynomial degree (Noise/ImageNoise node).
+       */
+      unsigned int _polynomialDegree;
+      /**
+       * @brief Polynomial coefficients (Noise/ImageNoise node).
+       */
+      std::vector<double> _polynomialCoefficients;
+
+private:
+};
+}
+
+#endif
+
diff --git a/ossim_plugins/ossim/otb/IncidenceAngles.cpp b/ossim_plugins/ossim/otb/IncidenceAngles.cpp
new file mode 100644
index 0000000..e15740b
--- /dev/null
+++ b/ossim_plugins/ossim/otb/IncidenceAngles.cpp
@@ -0,0 +1,162 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include <otb/IncidenceAngles.h>
+#include <ossim/base/ossimDpt3d.h>
+#include <ossim/base/ossimKeywordlist.h>
+#include <ossim/base/ossimNotify.h>
+#include <ossim/base/ossimString.h>
+
+
+namespace ossimplugins
+{
+static const char INCIDENCE_ANGLES[] = "incidenceAngles";
+static const char NUMBER_OF_CORNER_INCIDENCE_ANGLES[] = "numberOfCornerIncidenceAngles";
+static const char CENTER_INCIDENCE_ANGLE[] = "centerInfoIncidenceAngle";
+static const char CORNERS_INCIDENCE_ANGLE[] = "cornersInfoIncidenceAngle";
+
+IncidenceAngles::IncidenceAngles():
+  _numberOfCornerIncidenceAngles(0),
+  _centerInfoIncidenceAngle(),
+  _tabCornersInfoIncidenceAngle()
+{
+}
+
+IncidenceAngles::~IncidenceAngles()
+{
+}
+
+
+IncidenceAngles::IncidenceAngles(const IncidenceAngles& rhs):
+   _numberOfCornerIncidenceAngles(rhs._numberOfCornerIncidenceAngles),
+   _centerInfoIncidenceAngle(rhs._centerInfoIncidenceAngle),
+   _tabCornersInfoIncidenceAngle(rhs._tabCornersInfoIncidenceAngle)
+{
+}
+
+IncidenceAngles& IncidenceAngles::operator=(const IncidenceAngles& rhs)
+{
+  _numberOfCornerIncidenceAngles = rhs._numberOfCornerIncidenceAngles;
+  _centerInfoIncidenceAngle = rhs._centerInfoIncidenceAngle;
+  _tabCornersInfoIncidenceAngle = rhs._tabCornersInfoIncidenceAngle;
+  return *this;
+}
+
+bool IncidenceAngles::saveState(ossimKeywordlist& kwl, const char* prefix) const
+{
+   std::string pfx("");
+   std::string pfx2("");
+   if (prefix)
+   {
+      pfx = prefix;
+   }
+   pfx += INCIDENCE_ANGLES;
+   pfx2 = pfx;
+   pfx2 += ".";
+   
+   kwl.add(pfx2.c_str(), NUMBER_OF_CORNER_INCIDENCE_ANGLES, _numberOfCornerIncidenceAngles);
+
+   std::string s = pfx + "." + CENTER_INCIDENCE_ANGLE;
+   _centerInfoIncidenceAngle.saveState(kwl, s.c_str());
+
+   std::string s2 =pfx + "." + CORNERS_INCIDENCE_ANGLE;
+   for (unsigned int i = 0; i < _tabCornersInfoIncidenceAngle.size(); ++i)
+   {
+      std::string s3 = s2 + "[" + ossimString::toString(i).c_str() + "]";
+      _tabCornersInfoIncidenceAngle[i].saveState(kwl, s3.c_str());
+   }
+
+   return true;
+}
+
+bool IncidenceAngles::loadState(const ossimKeywordlist& kwl, const char* prefix)
+{
+  static const char MODULE[] = "IncidenceAngles::loadState";
+
+   bool result = true;
+
+   ossimString s;
+   const char* lookup = 0;
+   
+   std::string pfx("");
+   if (prefix)
+   {
+      pfx = prefix;
+   }
+   pfx += INCIDENCE_ANGLES;
+   pfx += ".";
+ 
+
+   lookup = kwl.find(pfx.c_str(), NUMBER_OF_CORNER_INCIDENCE_ANGLES);
+
+   if (lookup)
+   {
+     s = lookup;
+     _numberOfCornerIncidenceAngles = s.toUInt32();
+   }
+   else
+   {
+     ossimNotify(ossimNotifyLevel_WARN)
+        << MODULE << " Keyword not found: " << NUMBER_OF_CORNER_INCIDENCE_ANGLES << " in "<<pfx.c_str()<<" path.\n";
+     result = false;
+   }
+   
+   std::string s1 = pfx + CENTER_INCIDENCE_ANGLE;
+   
+   result = _centerInfoIncidenceAngle.loadState(kwl, s1.c_str());
+
+   _tabCornersInfoIncidenceAngle.clear();
+   std::string s2 = pfx + CORNERS_INCIDENCE_ANGLE;
+   for (unsigned int i = 0; i < _numberOfCornerIncidenceAngles; ++i)
+   {
+      std::string s3 = s2 + "[" + ossimString::toString(i).c_str() + "]";
+      InfoIncidenceAngle iia;
+      result = iia.loadState(kwl, s3.c_str());
+      _tabCornersInfoIncidenceAngle.push_back(iia);
+   }
+   if( _numberOfCornerIncidenceAngles != _tabCornersInfoIncidenceAngle.size() )
+   {
+    ossimNotify(ossimNotifyLevel_WARN)
+	<< MODULE << " Keyword " << NUMBER_OF_CORNER_INCIDENCE_ANGLES << " is different with the number of ImageNoise nodes \n";
+   }
+
+  return result;
+}
+
+
+std::ostream& IncidenceAngles::print(std::ostream& out) const
+{
+   out << setprecision(15) << setiosflags(ios::fixed)
+       << "\n IncidentAngles class data members:\n";
+
+   const char* prefix = 0;
+   ossimKeywordlist kwl;
+   ossimString pfx;
+   pfx += INCIDENCE_ANGLES;
+   ossimString s = pfx + "." + NUMBER_OF_CORNER_INCIDENCE_ANGLES;
+   kwl.add(prefix, s.c_str(), _numberOfCornerIncidenceAngles);
+   
+   ossimString s1 = pfx + "." + CENTER_INCIDENCE_ANGLE;
+   _centerInfoIncidenceAngle.saveState(kwl, s1.c_str());
+
+   ossimString s2 =pfx + "." + CORNERS_INCIDENCE_ANGLE;
+   for (unsigned int i = 0; i < _tabCornersInfoIncidenceAngle.size(); ++i)
+   {
+     ossimString s3 = s2 + "[" + ossimString::toString(i) + "]";
+     _tabCornersInfoIncidenceAngle[i].saveState(kwl, s3.c_str());
+   }
+   out << kwl;
+
+   return out;
+}
+
+}
+
diff --git a/ossim_plugins/ossim/otb/IncidenceAngles.h b/ossim_plugins/ossim/otb/IncidenceAngles.h
new file mode 100644
index 0000000..e05fe26
--- /dev/null
+++ b/ossim_plugins/ossim/otb/IncidenceAngles.h
@@ -0,0 +1,105 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef IncidenceAngles_h
+#define IncidenceAngles_h
+
+#include <ossim/base/ossimConstants.h>
+#include <ossimPluginConstants.h>
+#include <otb/JSDDateTime.h>
+#include <otb/InfoIncidenceAngle.h>
+
+class ossimKeywordlist;
+
+namespace ossimplugins
+{
+
+/**
+ * @ingroup IncidenceAngles
+ * @brief This class represents Incidence Angles
+ */
+class OSSIM_PLUGINS_DLL IncidenceAngles
+{
+public:
+   /**
+    * @brief Constructor
+    */
+  IncidenceAngles();
+
+   /**
+    * @brief Destructor
+    */
+  virtual ~IncidenceAngles();
+
+   /**
+    * @brief Copy constructor
+    */
+  IncidenceAngles(const IncidenceAngles& rhs);
+
+   /**
+    * @brief Affectation operator
+    */
+  IncidenceAngles& operator=(const IncidenceAngles& rhs);
+
+   /**
+    * @brief Method to save object state to a keyword list.
+    * @param kwl Keyword list to save to.
+    * @param prefix added to keys when saved.
+    * @return true on success, false on error.
+    */
+   bool saveState(ossimKeywordlist& kwl, const char* prefix=0) const;
+
+   /**
+    * @brief Method to the load (recreate) the state of the object from a
+    * keyword list. Return true if ok or false on error.
+    * @return true if load OK, false on error
+    */
+   bool loadState (const ossimKeywordlist &kwl, const char *prefix=0);
+   /*!
+    * METHOD: print()
+    * Fulfills base-class pure virtual. Dumps contents of object to ostream.
+    */
+   virtual std::ostream& print(std::ostream& out) const;
+
+  void set_numberOfCornerIncidenceAngles(const ossim_uint32& numberOfCornerIncidenceAngles)
+  {
+    _numberOfCornerIncidenceAngles = numberOfCornerIncidenceAngles;
+  }
+  void set_centerInfoIncidenceAngle(const InfoIncidenceAngle& centerInfoIncidenceAngle)
+  {
+    _centerInfoIncidenceAngle = centerInfoIncidenceAngle;
+  }
+  void set_cornersInfoIncidenceAngle(const std::vector<InfoIncidenceAngle>& cornersInfoIncidenceAngle)
+  {
+    _tabCornersInfoIncidenceAngle = cornersInfoIncidenceAngle;
+  }
+
+protected:
+
+      /**
+       * @brief Number of incidence angles
+       */
+      ossim_uint32 _numberOfCornerIncidenceAngles;
+      /**
+       * @brief Center InfoIncidenceAngle.
+       */
+      InfoIncidenceAngle _centerInfoIncidenceAngle;
+      /**
+       * @brief Corners InfoIncidenceAngle.
+       */
+      std::vector<InfoIncidenceAngle> _tabCornersInfoIncidenceAngle;
+  
+private:
+};
+}
+
+#endif
+
diff --git a/ossim_plugins/ossim/otb/InfoIncidenceAngle.cpp b/ossim_plugins/ossim/otb/InfoIncidenceAngle.cpp
new file mode 100644
index 0000000..badb2f4
--- /dev/null
+++ b/ossim_plugins/ossim/otb/InfoIncidenceAngle.cpp
@@ -0,0 +1,124 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include <otb/InfoIncidenceAngle.h>
+#include <ossim/base/ossimDpt3d.h>
+#include <ossim/base/ossimKeywordlist.h>
+#include <ossim/base/ossimNotify.h>
+#include <ossim/base/ossimString.h>
+
+namespace ossimplugins
+{
+
+
+static const char PREFIX[]          = ".infoIncidenceAngle.";
+static const char REF_ROW[]         = "refRow";
+static const char REF_COLUMN[]      = "refColumn";
+static const char INCIDENCE_ANGLE[] = "incidenceAngle";
+
+InfoIncidenceAngle::InfoIncidenceAngle():
+     _refRow(0),
+     _refColumn(0),
+     _incidenceAngle(0.)
+{
+}
+
+InfoIncidenceAngle::~InfoIncidenceAngle()
+{
+}
+
+
+InfoIncidenceAngle::InfoIncidenceAngle(const InfoIncidenceAngle& rhs):
+     _refRow(rhs._refRow),
+     _refColumn(rhs._refColumn),
+     _incidenceAngle(rhs._incidenceAngle)
+{
+}
+
+InfoIncidenceAngle& InfoIncidenceAngle::operator=(const InfoIncidenceAngle& rhs)
+{
+     _refRow = rhs._refRow;
+     _refColumn = rhs._refColumn;
+     _incidenceAngle = rhs._incidenceAngle;
+  return *this;
+}
+
+bool InfoIncidenceAngle::saveState(ossimKeywordlist& kwl, const char* prefix) const
+{
+  std::string pfx;
+  if (prefix)
+  {
+     pfx = prefix;
+  }
+  pfx += PREFIX;
+  kwl.add(pfx.c_str(), REF_ROW,  _refRow);
+  kwl.add(pfx.c_str(), REF_COLUMN, _refColumn);
+  kwl.add(pfx.c_str(), INCIDENCE_ANGLE, _incidenceAngle);
+
+  return true;
+}
+
+bool InfoIncidenceAngle::loadState(const ossimKeywordlist& kwl, const char* prefix)
+{
+  static const char MODULE[] = "InfoIncidenceAngle::loadState";
+  bool result = true;
+  std::string pfx;
+  if (prefix)
+  {
+    pfx = prefix;
+  }
+   ossimString s;
+   const char* lookup = 0;
+
+  pfx += PREFIX;
+  lookup = kwl.find(pfx.c_str(), REF_ROW);
+  if (lookup)
+  {
+    s = lookup;
+    _refRow = s.toUInt32();
+  }
+  else
+  {
+    ossimNotify(ossimNotifyLevel_WARN)
+         << MODULE << " Keyword not found: " << REF_ROW << " in "<<pfx.c_str()<<" path.\n";
+    result = false;
+  }
+  
+  lookup = kwl.find(pfx.c_str(), REF_COLUMN);
+  if (lookup)
+  {
+    s = lookup;
+    _refColumn = s.toUInt32();
+  }
+  else
+  {
+    ossimNotify(ossimNotifyLevel_WARN)
+	<< MODULE << " Keyword not found: " << REF_COLUMN << " in "<<pfx.c_str()<<" path.\n";
+    result = false;
+  }
+  
+  lookup = kwl.find(pfx.c_str(), INCIDENCE_ANGLE);
+  if (lookup)
+  {
+    s = lookup;
+    _incidenceAngle = s.toDouble();
+  }
+  else
+  {
+    ossimNotify(ossimNotifyLevel_WARN)
+	<< MODULE << " Keyword not found: " << INCIDENCE_ANGLE << " in "<<pfx.c_str()<<" path.\n";
+    result = false;
+  }
+
+   return result;
+}
+}
+
diff --git a/ossim_plugins/ossim/otb/InfoIncidenceAngle.h b/ossim_plugins/ossim/otb/InfoIncidenceAngle.h
new file mode 100644
index 0000000..b0b9f1c
--- /dev/null
+++ b/ossim_plugins/ossim/otb/InfoIncidenceAngle.h
@@ -0,0 +1,102 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef InfoIncidenceAngle_h
+#define InfoIncidenceAngle_h
+
+#include <vector>
+#include <ossim/base/ossimString.h>
+#include <ossimPluginConstants.h>
+
+class ossimKeywordlist;
+
+namespace ossimplugins
+{
+
+
+/**
+ * @ingroup InfoIncidenceAngle
+ * @brief This class represents an InfoIncidenceAngle
+ */
+class OSSIM_PLUGINS_DLL InfoIncidenceAngle
+{
+public:
+   /**
+    * @brief Constructor
+    */
+   InfoIncidenceAngle();
+
+   /**
+    * @brief Destructor
+    */
+   virtual ~InfoIncidenceAngle();
+
+   /**
+    * @brief Copy constructor
+    */
+   InfoIncidenceAngle(const InfoIncidenceAngle& rhs);
+
+   /**
+    * @brief Affectation operator
+    */
+   InfoIncidenceAngle& operator=(const InfoIncidenceAngle& rhs);
+
+   /**
+    * @brief Method to save object state to a keyword list.
+    * @param kwl Keyword list to save to.
+    * @param prefix added to keys when saved.
+    * @return true on success, false on error.
+    */
+   bool saveState(ossimKeywordlist& kwl, const char* prefix=0) const;
+
+   /**
+    * @brief Method to the load (recreate) the state of the object from a
+    * keyword list. Return true if ok or false on error.
+    * @return true if load OK, false on error
+    */
+   bool loadState (const ossimKeywordlist &kwl, const char *prefix=0);
+
+   void set_refRow(ossim_uint32 value)
+   {
+      _refRow = value;
+   }
+   void set_refColumn(ossim_uint32 value)
+   {
+      _refColumn = value;
+   }
+   void set_incidenceAngle(double value)
+   {
+      _incidenceAngle = value;
+   }
+
+
+protected:
+
+      /**
+       * @brief Reference Row (refRow node).
+       */
+      ossim_uint32 _refRow;
+
+      /**
+       * @brief Reference Column (refColumn node).
+       */
+      ossim_uint32 _refColumn;
+      /**
+       * @brief IncidenceAngle (incidenceAngle node).
+       */
+      double _incidenceAngle;
+
+private:
+};
+}
+
+#endif
+
diff --git a/ossim_plugins/ossim/otb/InfoSceneCoord.cpp b/ossim_plugins/ossim/otb/InfoSceneCoord.cpp
new file mode 100644
index 0000000..7aa6dd2
--- /dev/null
+++ b/ossim_plugins/ossim/otb/InfoSceneCoord.cpp
@@ -0,0 +1,196 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include <otb/InfoSceneCoord.h>
+#include <ossim/base/ossimDpt3d.h>
+#include <ossim/base/ossimKeywordlist.h>
+#include <ossim/base/ossimNotify.h>
+#include <ossim/base/ossimString.h>
+
+namespace ossimplugins
+{
+
+
+static const char PREFIX[]          = ".";
+static const char REF_ROW[]         = "refRow";
+static const char REF_COLUMN[]      = "refColumn";
+static const char LAT[]             = "lat";
+static const char LON[]             = "lon";
+static const char AZIMUTH_TIME[]    = "azimuthTimeUTC";
+static const char RANGE_TIME[]      = "rangeTime";
+static const char INCIDENCE_ANGLE[] = "incidenceAngle";
+
+InfoSceneCoord::InfoSceneCoord():
+     _refRow(0),
+     _refColumn(0),
+     _lat(0.0),
+     _lon(0.0),
+     _azimuthTimeUTC(),
+     _rangeTime(0.0),
+     _incidenceAngle(0.)
+{
+}
+
+InfoSceneCoord::~InfoSceneCoord()
+{
+}
+
+
+InfoSceneCoord::InfoSceneCoord(const InfoSceneCoord& rhs):
+     _refRow(rhs._refRow),
+     _refColumn(rhs._refColumn),
+     _lat(rhs._lat),
+     _lon(rhs._lon),
+     _azimuthTimeUTC(rhs._azimuthTimeUTC),
+     _rangeTime(rhs._rangeTime),
+     _incidenceAngle(rhs._incidenceAngle)
+{
+}
+
+InfoSceneCoord& InfoSceneCoord::operator=(const InfoSceneCoord& rhs)
+{
+     _refRow = rhs._refRow;
+     _refColumn = rhs._refColumn;
+     _lat = rhs._lat;
+     _lon = rhs._lon;
+     _azimuthTimeUTC = rhs._azimuthTimeUTC;
+     _rangeTime =rhs._rangeTime;
+     _incidenceAngle = rhs._incidenceAngle;
+  return *this;
+}
+
+bool InfoSceneCoord::saveState(ossimKeywordlist& kwl, const char* prefix) const
+{
+  std::string pfx;
+  if (prefix)
+  {
+     pfx = prefix;
+  }
+  pfx += PREFIX;
+  kwl.add(pfx.c_str(), REF_ROW,  _refRow);
+  kwl.add(pfx.c_str(), REF_COLUMN, _refColumn);
+  kwl.add(pfx.c_str(), LAT, _lat);
+  kwl.add(pfx.c_str(), LON, _lon);
+  kwl.add(pfx.c_str(), AZIMUTH_TIME, _azimuthTimeUTC);
+  kwl.add(pfx.c_str(), RANGE_TIME, _rangeTime);
+  kwl.add(pfx.c_str(), INCIDENCE_ANGLE, _incidenceAngle);
+
+  return true;
+}
+
+bool InfoSceneCoord::loadState(const ossimKeywordlist& kwl, const char* prefix)
+{
+  static const char MODULE[] = "InfoSceneCoord::loadState";
+  bool result = true;
+  std::string pfx;
+  if (prefix)
+  {
+    pfx = prefix;
+  }
+   ossimString s;
+   const char* lookup = 0;
+
+  pfx += PREFIX;
+  lookup = kwl.find(pfx.c_str(), REF_ROW);
+  if (lookup)
+  {
+    s = lookup;
+    _refRow = s.toUInt32();
+  }
+  else
+  {
+    ossimNotify(ossimNotifyLevel_WARN)
+         << MODULE << " Keyword not found: " << REF_ROW << " in "<<pfx.c_str()<<" path.\n";
+    result = false;
+  }
+  
+  lookup = kwl.find(pfx.c_str(), REF_COLUMN);
+  if (lookup)
+  {
+    s = lookup;
+    _refColumn = s.toUInt32();
+  }
+  else
+  {
+    ossimNotify(ossimNotifyLevel_WARN)
+	<< MODULE << " Keyword not found: " << REF_COLUMN << " in "<<pfx.c_str()<<" path.\n";
+    result = false;
+  }
+
+  lookup = kwl.find(pfx.c_str(), LAT);
+  if (lookup)
+  {
+    s = lookup;
+    _lat = s.toDouble();
+  }
+  else
+  {
+    ossimNotify(ossimNotifyLevel_WARN)
+	<< MODULE << " Keyword not found: " << LAT << " in "<<pfx.c_str()<<" path.\n";
+    result = false;
+  }
+
+  lookup = kwl.find(pfx.c_str(), LON);
+  if (lookup)
+  {
+    s = lookup;
+    _lon = s.toDouble();
+  }
+  else
+  {
+    ossimNotify(ossimNotifyLevel_WARN)
+	<< MODULE << " Keyword not found: " << LON << " in "<<pfx.c_str()<<" path.\n";
+    result = false;
+  }
+
+  lookup = kwl.find(pfx.c_str(), AZIMUTH_TIME);
+  if (lookup)
+  {
+    s = lookup;
+    _azimuthTimeUTC = s;
+  }
+  else
+  {
+    ossimNotify(ossimNotifyLevel_WARN)
+	<< MODULE << " Keyword not found: " << AZIMUTH_TIME << " in "<<pfx.c_str()<<" path.\n";
+    result = false;
+  }
+
+  lookup = kwl.find(pfx.c_str(), RANGE_TIME);
+  if (lookup)
+  {
+    s = lookup;
+    _rangeTime = s.toDouble();
+  }
+  else
+  {
+    ossimNotify(ossimNotifyLevel_WARN)
+	<< MODULE << " Keyword not found: " << RANGE_TIME << " in "<<pfx.c_str()<<" path.\n";
+    result = false;
+  }
+
+  lookup = kwl.find(pfx.c_str(), INCIDENCE_ANGLE);
+  if (lookup)
+  {
+    s = lookup;
+    _incidenceAngle = s.toDouble();
+  }
+  else
+  {
+    ossimNotify(ossimNotifyLevel_WARN)
+	<< MODULE << " Keyword not found: " << INCIDENCE_ANGLE << " in "<<pfx.c_str()<<" path.\n";
+    result = false;
+  }
+
+   return result;
+}
+}
+
diff --git a/ossim_plugins/ossim/otb/InfoSceneCoord.h b/ossim_plugins/ossim/otb/InfoSceneCoord.h
new file mode 100644
index 0000000..5e09299
--- /dev/null
+++ b/ossim_plugins/ossim/otb/InfoSceneCoord.h
@@ -0,0 +1,134 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef InfoSceneCoord_h
+#define InfoSceneCoord_h
+
+#include <vector>
+#include <ossim/base/ossimString.h>
+#include <ossimPluginConstants.h>
+
+class ossimKeywordlist;
+
+namespace ossimplugins
+{
+
+
+/**
+ * @ingroup InfoSceneCoord
+ * @brief This class represents an InfoSceneCoord
+ */
+class OSSIM_PLUGINS_DLL InfoSceneCoord
+{
+public:
+   /**
+    * @brief Constructor
+    */
+   InfoSceneCoord();
+
+   /**
+    * @brief Destructor
+    */
+   virtual ~InfoSceneCoord();
+
+   /**
+    * @brief Copy constructor
+    */
+   InfoSceneCoord(const InfoSceneCoord& rhs);
+
+   /**
+    * @brief Affectation operator
+    */
+   InfoSceneCoord& operator=(const InfoSceneCoord& rhs);
+
+   /**
+    * @brief Method to save object state to a keyword list.
+    * @param kwl Keyword list to save to.
+    * @param prefix added to keys when saved.
+    * @return true on success, false on error.
+    */
+   bool saveState(ossimKeywordlist& kwl, const char* prefix=0) const;
+
+   /**
+    * @brief Method to the load (recreate) the state of the object from a
+    * keyword list. Return true if ok or false on error.
+    * @return true if load OK, false on error
+    */
+   bool loadState (const ossimKeywordlist &kwl, const char *prefix=0);
+
+   void set_refRow(ossim_uint32 value)
+   {
+      _refRow = value;
+   }
+   void set_refColumn(ossim_uint32 value)
+   {
+      _refColumn = value;
+   }
+   void set_lat(double value)
+   {
+	   _lat = value;
+   }
+   void set_lon(double value)
+   {
+	   _lon = value;
+   }
+   void set_azimuthTimeUTC(ossimString value)
+   {
+	   _azimuthTimeUTC = value;
+   }
+   void set_rangeTime(double value)
+   {
+	   _rangeTime = value;
+   }
+   void set_incidenceAngle(double value)
+   {
+      _incidenceAngle = value;
+   }
+
+
+protected:
+
+      /**
+       * @brief Reference Row (refRow node).
+       */
+      ossim_uint32 _refRow;
+
+      /**
+       * @brief Reference Column (refColumn node).
+       */
+      ossim_uint32 _refColumn;
+      /**
+       * @brief Latitude (lat node).
+       */
+      double _lat;
+      /**
+       * @brief Longitude (lon node).
+       */
+      double _lon;
+      /**
+       * @brief azimuth time  (azimuthTimeUTC node).
+       */
+      ossimString _azimuthTimeUTC;
+      /**
+       * @brief range time  (rangeTime node).
+       */
+      double _rangeTime;
+      /**
+       * @brief IncidenceAngle (incidenceAngle node).
+       */
+      double _incidenceAngle;
+
+private:
+};
+}
+
+#endif
+
diff --git a/ossim_plugins/ossim/otb/JSDDateTime.cpp b/ossim_plugins/ossim/otb/JSDDateTime.cpp
new file mode 100644
index 0000000..002114c
--- /dev/null
+++ b/ossim_plugins/ossim/otb/JSDDateTime.cpp
@@ -0,0 +1,237 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include <otb/JSDDateTime.h>
+#include <otb/CivilDateTime.h>
+#include <otb/JulianDate.h>
+#include <otb/GMSTDateTime.h>
+
+#include <otb/Arithmetic.h>
+
+#include <cmath>
+#include <cstring>
+#include <cstdlib>
+#include <cstdio>
+
+namespace ossimplugins
+{
+
+
+JSDDateTime::JSDDateTime():
+  _day0hTU(0),
+  _second(0.0),
+  _decimal(0.0)
+{
+}
+
+JSDDateTime::~JSDDateTime()
+{
+}
+
+JSDDateTime::JSDDateTime(const JSDDateTime& rhs):
+  _day0hTU(rhs._day0hTU),
+  _second(rhs._second),
+  _decimal(rhs._decimal)
+{
+}
+
+JSDDateTime::JSDDateTime(JulianDate day0hTU, double second, double decimal):
+  _day0hTU(day0hTU),
+  _second(second),
+  _decimal(decimal)
+{
+}
+
+JSDDateTime::JSDDateTime(CivilDateTime& rhs)
+{
+  rhs.AsJSDDateTime(this);
+}
+
+JSDDateTime::JSDDateTime(JulianDate& rhs)
+{
+  rhs.AsJSDDateTime(this);
+}
+
+
+JSDDateTime::JSDDateTime(MJDDateTime& rhs)
+{
+  CivilDateTime referenceCiv;
+
+  /* Initialisation of the MJD reference day (01/01/2000, 0h00) */
+  referenceCiv.set_year(2000);
+  referenceCiv.set_month(01);
+  referenceCiv.set_day(01);
+  referenceCiv.set_second(0);
+  referenceCiv.set_decimal(0.0);
+
+  /* JSD day of the ref. MJD date */
+  JSDDateTime referenceJSD(referenceCiv);
+
+  /* JSD day computation */
+  JulianDate JD((double) rhs.get_day());
+
+  _day0hTU = referenceJSD.get_day0hTU() + JD;
+  _second  = referenceJSD.get_second()  + (double) rhs.get_second();
+  _decimal = referenceJSD.get_decimal() + 0.000001 * (double) rhs.get_microsecond();
+
+  this->NormDate();
+}
+
+JSDDateTime& JSDDateTime::operator=(const JSDDateTime& rhs)
+{
+  _day0hTU = rhs._day0hTU;
+  _second = rhs._second;
+  _decimal = rhs._decimal;
+
+  return *this;
+}
+
+int JSDDateTime::AsJulianDate(JulianDate* julian)
+{
+  double jourJulien = _day0hTU.get_julianDate() + (_second + _decimal) / CivilDateTime::JOURCIVIL_LENGTH ;
+  julian->set_julianDate(jourJulien);
+
+  return 0 ;
+}
+
+int JSDDateTime::AsGMSTDateTime(GMSTDateTime* GMST)
+{
+  const double TWOPI      = 6.28318530717958647693 ;
+  const double OMEGATERRE  = 6.28318530717958647693 / 86164.09054 ;
+
+  int etat ;
+  JulianDate jourJulien;
+  double  t = 0.0;
+        double tsm0hTU = 0.0;
+        double tsm = 0.0;
+  JSDDateTime date0hTU ;
+
+
+  date0hTU         = *this ;
+  date0hTU.set_second(0);
+  date0hTU.set_decimal(0.0);
+
+  etat = date0hTU.AsJulianDate(&jourJulien ) ;
+
+  if (etat == 0)
+  {
+    if (GMST->get_origine() == GMSTDateTime::AN1900)
+    {
+      t       = (jourJulien.get_julianDate() - 2415020.0) / 36525.0 ;
+      tsm0hTU = 23925.836 + t * (8640184.542 + t * 0.0929) ;
+      tsm0hTU = tsm0hTU * TWOPI / CivilDateTime::JOURCIVIL_LENGTH ;
+    }
+    else if (GMST->get_origine() == GMSTDateTime::AN1950)
+    {
+      t       = jourJulien.get_julianDate() - 2433281.5 ;
+      tsm0hTU = 1.72944494 + t * 6.3003880987 ;
+    }
+    else if (GMST->get_origine() == GMSTDateTime::AN2000)
+    {
+      t       = (jourJulien.get_julianDate() - 2451545.0) / 36525.0 ;
+      tsm0hTU =   24110.54841 + t * (8640184.812866
+                + t * (0.093103 - t * 6.210e-6)) ;
+      tsm0hTU = tsm0hTU * TWOPI / CivilDateTime::JOURCIVIL_LENGTH ;
+    }
+    t = tsm0hTU + (_second + _decimal) * OMEGATERRE ;
+    tsm = fmod (t,TWOPI) ;
+    if (tsm < 0.0)
+    {
+      tsm = tsm + TWOPI ;
+    }
+
+    GMST->set_tms(tsm);
+  }
+
+  return etat ;
+}
+
+void JSDDateTime::NormDate()
+{
+  const double epsilon = 1.0e-12 ;
+
+  int k, iu, iv, iw ;
+  double u, v, w, ru, rv, rw ;
+
+
+  w = _day0hTU.get_julianDate() - 0.5 ;
+  if (fabs (w - fnint (w)) < epsilon)
+  {
+    iw = (int)inint(w) ;
+    rw = 0.0 ;
+  }
+  else
+  {
+    iw = (int)w ;
+    rw = w - (double)iw ;
+    if ((iw < 0) && (rw != 0.0))
+    {
+    iw = iw - 1 ;
+    rw = rw + 1.0 ;
+    }
+  }
+
+  v = _second + rw * CivilDateTime::JOURCIVIL_LENGTH ;
+  if (fabs(v - fnint (v)) < epsilon)
+  {
+    iv = (int)inint (v) ;
+    rv = 0.0 ;
+  }
+  else
+  {
+    iv = (int)v ;
+    rv = v - (double)iv ;
+    if ((iv < 0) && (rv != 0.0))
+    {
+      iv = iv - 1 ;
+      rv = rv + 1.0 ;
+    }
+  }
+
+  u  = _decimal + rv ;
+  iu = (int)u ;
+  ru = u - (double)iu ;
+  if ((iu < 0) && (ru != 0.0))
+  {
+    iu = iu - 1 ;
+    ru = ru + 1.0 ;
+  }
+
+  iv = iv + iu ;
+  k  = iv / ((int)inint(CivilDateTime::JOURCIVIL_LENGTH)) ;
+  iw = iw + k ;
+  iv = iv - k * ((int)inint(CivilDateTime::JOURCIVIL_LENGTH)) ;
+  if (iv < 0)
+  {
+    iw = iw - 1 ;
+    iv = iv + (int)inint(CivilDateTime::JOURCIVIL_LENGTH) ;
+  }
+
+  _decimal    = ru ;
+  _second  = (double)iv ;
+  _day0hTU = (double)iw + 0.5 ;
+}
+
+JSDDateTime::operator JulianDate()
+{
+  JulianDate date;
+  this->AsJulianDate(&date);
+  return date;
+}
+
+JSDDateTime::operator GMSTDateTime()
+{
+  GMSTDateTime date;
+  this->AsGMSTDateTime(&date);
+  return date;
+}
+}
+
diff --git a/ossim_plugins/ossim/otb/JSDDateTime.h b/ossim_plugins/ossim/otb/JSDDateTime.h
new file mode 100644
index 0000000..de0911b
--- /dev/null
+++ b/ossim_plugins/ossim/otb/JSDDateTime.h
@@ -0,0 +1,135 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef JSDDateTime_h
+#define JSDDateTime_h
+
+#include <ossimPluginConstants.h>
+#include <otb/JulianDate.h>
+#include <otb/MJDDateTime.h>
+
+namespace ossimplugins
+{
+
+
+class CivilDateTime;
+class GMSTDateTime;
+class JulianDate;
+
+/**
+ * @brief This class represents a date
+ */
+class OSSIM_PLUGINS_DLL JSDDateTime
+{
+public:
+   /**
+    * @brief constructor
+    */
+   JSDDateTime();
+   /**
+    * @brief Destructor
+    */
+   ~JSDDateTime();
+   /**
+    * @brief Copy constructor
+    */
+   JSDDateTime(const JSDDateTime& rhs);
+
+   /**
+    * @brief Constructor with date initialisation
+    */
+   JSDDateTime(JulianDate day0hTU, double second, double decimal);
+
+   /**
+    * @brief Constructor with date initialisation using a CivilDateTime
+    */
+   JSDDateTime(CivilDateTime& rhs);
+
+   /**
+    * @brief Constructor with date initialisation using a CivilDateTime
+    */
+   JSDDateTime(JulianDate& rhs);
+
+   /**
+    * @brief Constructor with date initialisation using a MJDDateTime (Modified Julian Date - Used for ENVISAT)
+    */
+   JSDDateTime(MJDDateTime& rhs);
+
+   /**
+    * @brief Affectation operator
+    */
+   JSDDateTime& operator=(const JSDDateTime& rhs);
+
+   JulianDate get_day0hTU() const
+   {
+      return _day0hTU;
+   }
+
+   double get_second() const
+   {
+      return _second;
+   }
+
+   double get_decimal() const
+   {
+      return _decimal;
+   }
+
+   void set_day0hTU(JulianDate  day)
+   {
+      _day0hTU = day;
+   }
+
+   void set_second(double second)
+   {
+      _second = second;
+   }
+
+   void set_decimal(double decimal)
+   {
+      _decimal = decimal;
+   }
+
+   void NormDate() ;
+
+   /**
+    * @brief This function converts the current JSDDateTime into Julian Date
+    * @return 0 if no error or an int greater than 0 indicating the error
+    * @param julianDate [out] The classe that receives the result of the conversion of the current JSDDateTime in JulianDate
+    */
+   int AsJulianDate(JulianDate* julian);
+
+   /**
+    * @brief This function converts the current JSDDateTime into GMST Date
+    * @return 0 if no error or an int greater than 0 indicating the error
+    * @param julianDate [out] The class that receives the result of the conversion of the current JSDDateTime into GMST Date
+    */
+   int AsGMSTDateTime(GMSTDateTime* GMST);
+
+   operator JulianDate() ;
+   operator GMSTDateTime() ;
+
+protected:
+
+   /**
+    * @brief Julian day at 0h00 UT
+    */
+   JulianDate _day0hTU;
+   double _second;
+   double _decimal;
+
+
+private:
+};
+}
+
+#endif
+
diff --git a/ossim_plugins/ossim/otb/JulianDate.cpp b/ossim_plugins/ossim/otb/JulianDate.cpp
new file mode 100644
index 0000000..bc989c1
--- /dev/null
+++ b/ossim_plugins/ossim/otb/JulianDate.cpp
@@ -0,0 +1,147 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include <otb/CivilDateTime.h>
+#include <otb/JulianDate.h>
+#include <otb/JSDDateTime.h>
+#include <otb/GMSTDateTime.h>
+
+
+#include <cmath>
+#include <cstring>
+#include <cstdlib>
+#include <cstdio>
+
+namespace ossimplugins
+{
+
+
+JulianDate::JulianDate():
+  _julianDate(0.0)
+{
+}
+
+JulianDate::JulianDate(CivilDateTime& rhs)
+{
+  rhs.AsJulianDate(this);
+}
+
+JulianDate::JulianDate(double julianDate):
+  _julianDate(julianDate)
+{
+}
+
+JulianDate::JulianDate(JSDDateTime& rhs)
+{
+  rhs.AsJulianDate(this);
+}
+
+JulianDate::~JulianDate()
+{
+}
+
+JulianDate::JulianDate(const JulianDate& rhs):
+  _julianDate(rhs._julianDate)
+{
+}
+
+JulianDate& JulianDate::operator=(const JulianDate& rhs)
+{
+  _julianDate = rhs._julianDate;
+  return *this;
+}
+
+JulianDate& JulianDate::operator+(const JulianDate& rhs)
+{
+  _julianDate += rhs._julianDate;
+  return *this;
+}
+
+int JulianDate::AsJSDDateTime(JSDDateTime* JSDdate)
+{
+  int k ;
+  double r ;
+
+  k = (int)(_julianDate - 0.5) ;
+  double jJul0hTU = (double)k + 0.5;
+
+  JSDdate->set_day0hTU (jJul0hTU);
+  r = (_julianDate - jJul0hTU) * CivilDateTime::JOURCIVIL_LENGTH ;
+  JSDdate->set_second(floor (r));
+  JSDdate->set_decimal(r - JSDdate->get_second()) ;
+
+  return 0 ;
+}
+
+int JulianDate::AsGMSTDateTime(GMSTDateTime* GMST)
+{
+  const double TWOPI      = 6.28318530717958647693 ;
+  const double OMEGATERRE  = 6.28318530717958647693 / 86164.09054 ;
+
+  int etat=0 , n ;
+  double j0hTU = 0.0;
+        double tsm0hTU = 0.0;
+        double t = 0.0;
+        double d = 0.0;
+        double tsm = 0.0;
+
+
+  n     = (int)(_julianDate - 0.5) ;
+  j0hTU = (double)n + 0.5 ;
+  d     = _julianDate - j0hTU ;
+
+  if (etat == 0)
+  {
+    if (GMST->get_origine() == GMSTDateTime::AN1900)
+    {
+      t       = (j0hTU - 2415020.0) / 36525.0 ;
+      tsm0hTU = 23925.836 + t * (8640184.542 + t * 0.0929) ;
+      tsm0hTU = tsm0hTU * TWOPI / CivilDateTime::JOURCIVIL_LENGTH ;
+    }
+    else if (GMST->get_origine() == GMSTDateTime::AN1950)
+    {
+      t       = j0hTU - 2433281.5 ;
+      tsm0hTU = 1.72944494 + t * 6.3003880987 ;
+    }
+    else if (GMST->get_origine() == GMSTDateTime::AN2000)
+    {
+      t       = (j0hTU - 2451545.0) / 36525.0 ;
+      tsm0hTU =   24110.54841 + t * (8640184.812866 + t * (0.093103 - t * 6.210e-6)) ;
+      tsm0hTU = tsm0hTU * TWOPI / CivilDateTime::JOURCIVIL_LENGTH ;
+    }
+    t = tsm0hTU + d * CivilDateTime::JOURCIVIL_LENGTH * OMEGATERRE ;
+    tsm = fmod (t,TWOPI) ;
+    if (tsm < 0.0)
+    {
+      tsm = tsm + TWOPI ;
+    }
+
+    GMST->set_tms(tsm);
+  }
+
+  return etat ;
+}
+
+JulianDate::operator JSDDateTime()
+{
+  JSDDateTime date;
+  AsJSDDateTime(&date);
+  return date;
+}
+
+JulianDate::operator GMSTDateTime()
+{
+  GMSTDateTime date;
+  AsGMSTDateTime(&date);
+  return date;
+}
+}
+
diff --git a/ossim_plugins/ossim/otb/JulianDate.h b/ossim_plugins/ossim/otb/JulianDate.h
new file mode 100644
index 0000000..c21e340
--- /dev/null
+++ b/ossim_plugins/ossim/otb/JulianDate.h
@@ -0,0 +1,103 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef JulianData_h
+#define JulianData_h
+
+#include <ossimPluginConstants.h>
+
+namespace ossimplugins
+{
+
+
+class CivilDateTime;
+class GMSTDateTime;
+class JSDDateTime;
+/**
+ * @brief This class represents a date in the julian referential
+ */
+class OSSIM_PLUGINS_DLL JulianDate
+{
+public:
+  /**
+   * @brief constructor
+   */
+  JulianDate();
+  /**
+   * @brief Destructor
+   */
+  ~JulianDate();
+  /**
+   * @brief Copy constructor
+   */
+  JulianDate(const JulianDate& rhs);
+
+  /**
+   * @brief Constructor with date initialisation using a CivilDateTime
+   */
+  JulianDate(CivilDateTime& rhs);
+
+  /**
+   * @brief Constructor with date initialisation using a JSDDateTime
+   */
+  JulianDate(JSDDateTime& rhs);
+  /**
+   * @brief Constructor with date initialisation
+   */
+  JulianDate(double julianDate);
+  /**
+   * @brief Affectation operator
+   */
+  JulianDate& operator=(const JulianDate& rhs);
+  /**
+   * @brief Summation operator
+   */
+  JulianDate& operator+(const JulianDate& rhs);
+
+  void set_julianDate(double julianDate)
+  {
+    _julianDate = julianDate;
+  }
+
+  double get_julianDate() const
+  {
+    return _julianDate;
+  }
+
+  /**
+   * @brief This function converts the current JulianDate in JSDDateTime
+   * @return 0 if no error or an int greater than 0 indicating the error
+   * @param JSDdate [out] The classe that receives the result of the conversion of the current JulianDate in JSDDateTime
+   */
+  int AsJSDDateTime(JSDDateTime* JSDdate);
+
+  /**
+   * @brief This function converts the current JulianDate into GMSTDateTime
+   * @return 0 if no error or an int greater than 0 indicating the error
+   * @param GMSTDateTime [out] The class that receives the result of the conversion of the current JulianDate into GMSTDateTime
+   */
+  int AsGMSTDateTime(GMSTDateTime* GMST);
+
+  operator JSDDateTime() ;
+  operator GMSTDateTime() ;
+
+
+protected:
+
+  double _julianDate;
+
+private:
+};
+}
+
+#endif
+
+
diff --git a/ossim_plugins/ossim/otb/MJDDateTime.cpp b/ossim_plugins/ossim/otb/MJDDateTime.cpp
new file mode 100644
index 0000000..fb1bcc9
--- /dev/null
+++ b/ossim_plugins/ossim/otb/MJDDateTime.cpp
@@ -0,0 +1,52 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include <otb/MJDDateTime.h>
+
+namespace ossimplugins
+{
+
+
+MJDDateTime::MJDDateTime():
+  _day(0),
+  _second(0),
+  _microsecond(0)
+{
+}
+
+MJDDateTime::~MJDDateTime()
+{
+}
+
+MJDDateTime::MJDDateTime(const MJDDateTime& rhs):
+  _day(rhs._day),
+  _second(rhs._second),
+  _microsecond(rhs._microsecond)
+{
+}
+
+MJDDateTime::MJDDateTime(long day, unsigned long second, unsigned long microsecond):
+  _day(day),
+  _second(second),
+  _microsecond(microsecond)
+{
+}
+
+MJDDateTime& MJDDateTime::operator=(const MJDDateTime& rhs)
+{
+  _day = rhs._day;
+  _second = rhs._second;
+  _microsecond = rhs._microsecond;
+
+  return *this;
+}
+}
+
diff --git a/ossim_plugins/ossim/otb/MJDDateTime.h b/ossim_plugins/ossim/otb/MJDDateTime.h
new file mode 100644
index 0000000..0590712
--- /dev/null
+++ b/ossim_plugins/ossim/otb/MJDDateTime.h
@@ -0,0 +1,92 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef MJDDateTime_h
+#define MJDDateTime_h
+
+#include <ossimPluginConstants.h>
+
+namespace ossimplugins
+{
+
+
+class CivilDateTime;
+/**
+ * @brief This class represents an MJD date (Modified Julian date)
+ */
+class OSSIM_PLUGINS_DLL MJDDateTime
+{
+public:
+  /**
+   * @brief constructor
+   */
+  MJDDateTime();
+  /**
+   * @brief Destructor
+   */
+  ~MJDDateTime();
+  /**
+   * @brief Copy constructor
+   */
+  MJDDateTime(const MJDDateTime& rhs);
+
+  /**
+   * @brief Constructor with date initialisation
+   */
+  MJDDateTime(long day, unsigned long  second, unsigned long  microsecond);
+
+  /**
+   * @brief Affectation operator
+   */
+  MJDDateTime& operator=(const MJDDateTime& rhs);
+
+  long get_day()
+  {
+    return _day;
+  };
+
+  unsigned long get_second()
+  {
+    return _second;
+  };
+
+  unsigned long get_microsecond()
+  {
+    return _microsecond;
+  };
+
+  void set_day(long  day)
+  {
+    _day = day;
+  };
+
+  void set_second(unsigned long second)
+  {
+    _second = second;
+  };
+
+  void set_microsecond(unsigned long microsecond)
+  {
+    _microsecond = microsecond;
+  };
+protected:
+
+  long _day;
+  unsigned long _second;
+  unsigned long _microsecond;
+
+
+private:
+};
+}
+
+#endif
+
diff --git a/ossim_plugins/ossim/otb/Noise.cpp b/ossim_plugins/ossim/otb/Noise.cpp
new file mode 100644
index 0000000..d00c9c1
--- /dev/null
+++ b/ossim_plugins/ossim/otb/Noise.cpp
@@ -0,0 +1,161 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include <otb/Noise.h>
+#include <ossim/base/ossimDpt3d.h>
+#include <ossim/base/ossimKeywordlist.h>
+#include <ossim/base/ossimNotify.h>
+#include <ossim/base/ossimString.h>
+
+
+namespace ossimplugins
+{
+static const char NOISE[] = "noise";
+static const char NUMBER_OF_NOISE_RECORDS_KW[] = "numberOfNoiseRecords"; 
+static const char NAME_OF_NOISE_POLARISATION_KW[] = "nameOfNoisePolarisation"; 
+
+Noise::Noise():
+  _numberOfNoiseRecords(0),
+  _tabImageNoise(),
+  _polarisation("UNDEFINED")
+{
+}
+
+Noise::~Noise()
+{
+}
+
+
+Noise::Noise(const Noise& rhs):
+  _numberOfNoiseRecords(rhs._numberOfNoiseRecords),
+  _tabImageNoise(rhs._tabImageNoise),
+  _polarisation(rhs._polarisation)
+{
+}
+
+Noise& Noise::operator=(const Noise& rhs)
+{
+  _numberOfNoiseRecords = rhs._numberOfNoiseRecords;
+  _tabImageNoise = rhs._tabImageNoise;
+  _polarisation = rhs._polarisation;
+  return *this;
+}
+
+bool Noise::saveState(ossimKeywordlist& kwl, const char* prefix) const
+{
+   std::string pfx;
+   if (prefix)
+   {
+      pfx = prefix;
+   }
+   pfx += NOISE;
+   
+
+   std::string s = pfx + "." + NAME_OF_NOISE_POLARISATION_KW;
+   kwl.add(prefix, s.c_str(), _polarisation);
+   
+   s = pfx + "." + NUMBER_OF_NOISE_RECORDS_KW;
+   kwl.add(prefix, s.c_str(), _numberOfNoiseRecords);
+   
+   for (unsigned int i = 0; i < _tabImageNoise.size(); ++i)
+   {
+     ossimString s2 = pfx + "[" + ossimString::toString(i).c_str() + "]";
+      _tabImageNoise[i].saveState(kwl, s2.c_str());
+   }
+
+   return true;
+}
+
+bool Noise::loadState(const ossimKeywordlist& kwl, const char* prefix)
+{
+   static const char MODULE[] = "Noise::loadState";
+
+   bool result = true;
+
+   std::string pfx("");
+   if (prefix)
+   {
+      pfx = prefix;
+   }
+   pfx += NOISE;
+
+   ossimString s;
+   const char* lookup = 0;
+   std::string s1 = pfx + ".";
+
+  lookup = kwl.find(s1.c_str(), NAME_OF_NOISE_POLARISATION_KW);
+  if (lookup)
+  {
+    _polarisation = lookup;
+  }
+  else
+  {
+    ossimNotify(ossimNotifyLevel_WARN)
+         << MODULE << " Keyword not found: " << NAME_OF_NOISE_POLARISATION_KW << "\n";
+    result = false;
+  }
+
+  lookup = kwl.find(s1.c_str(), NUMBER_OF_NOISE_RECORDS_KW);
+  if (lookup)
+  {
+    s = lookup;
+    _numberOfNoiseRecords = s.toUInt32();
+  }
+  else
+  {
+    ossimNotify(ossimNotifyLevel_WARN)
+         << MODULE << " Keyword not found: " << NUMBER_OF_NOISE_RECORDS_KW << "\n";
+    result = false;
+  }
+
+   _tabImageNoise.clear();
+   for (unsigned int i = 0; i < _numberOfNoiseRecords; ++i)
+   {
+      std::string s2 = pfx + "[" + ossimString::toString(i).c_str() + "]";
+      ImageNoise in;
+      result = in.loadState(kwl, s2.c_str());
+      _tabImageNoise.push_back(in);
+   }
+   if( _numberOfNoiseRecords != _tabImageNoise.size() )
+   {
+    ossimNotify(ossimNotifyLevel_WARN)
+         << MODULE << " Keyword " << NUMBER_OF_NOISE_RECORDS_KW << " is different with the number of ImageNoise nodes \n";
+   }
+   return result;
+}
+
+
+std::ostream& Noise::print(std::ostream& out) const
+{
+   out << setprecision(15) << setiosflags(ios::fixed)
+       << "\n Noise class data members:\n";
+
+   const char* prefix = 0;
+   ossimKeywordlist kwl;
+   ossimString pfx;
+   pfx += NOISE;
+   ossimString s = pfx + "." + NUMBER_OF_NOISE_RECORDS_KW;
+   kwl.add(prefix, s.c_str(), _numberOfNoiseRecords);
+   s = pfx + "." + NAME_OF_NOISE_POLARISATION_KW;
+   kwl.add(prefix, s.chars(), _polarisation);
+   for (unsigned int i = 0; i < _tabImageNoise.size(); ++i)
+   {
+     ossimString s2 = pfx + "[" + ossimString::toString(i).c_str() + "]";
+     _tabImageNoise[i].saveState(kwl, s2.c_str());
+   }
+
+   out << kwl;
+
+   return out;
+}
+
+}
+
diff --git a/ossim_plugins/ossim/otb/Noise.h b/ossim_plugins/ossim/otb/Noise.h
new file mode 100644
index 0000000..058406e
--- /dev/null
+++ b/ossim_plugins/ossim/otb/Noise.h
@@ -0,0 +1,119 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef Noise_h
+#define Noise_h
+
+#include <ossim/base/ossimConstants.h>
+#include <otb/JSDDateTime.h>
+#include <otb/ImageNoise.h>
+
+class ossimKeywordlist;
+
+namespace ossimplugins
+{
+
+/**
+ * @ingroup Noise
+ * @brief This class represents an Noise
+ */
+class OSSIM_PLUGINS_DLL Noise
+{
+public:
+   /**
+    * @brief Constructor
+    */
+   Noise();
+
+   /**
+    * @brief Destructor
+    */
+   virtual ~Noise();
+
+   /**
+    * @brief Copy constructor
+    */
+   Noise(const Noise& rhs);
+
+   /**
+    * @brief Affectation operator
+    */
+   Noise& operator=(const Noise& rhs);
+
+   /**
+    * @brief Method to save object state to a keyword list.
+    * @param kwl Keyword list to save to.
+    * @param prefix added to keys when saved.
+    * @return true on success, false on error.
+    */
+   bool saveState(ossimKeywordlist& kwl, const char* prefix=0) const;
+
+   /**
+    * @brief Method to the load (recreate) the state of the object from a
+    * keyword list. Return true if ok or false on error.
+    * @return true if load OK, false on error
+    */
+   bool loadState (const ossimKeywordlist &kwl, const char *prefix=0);
+   /*!
+    * METHOD: print()
+    * Fulfills base-class pure virtual. Dumps contents of object to ostream.
+    */
+   virtual std::ostream& print(std::ostream& out) const;
+
+  void set_numberOfNoiseRecords(const ossim_int32&  numberOfNoiseRecords)
+  {
+    _numberOfNoiseRecords = numberOfNoiseRecords;
+  }
+  void set_imageNoise(const std::vector<ImageNoise>& image_noise)
+  {
+    _tabImageNoise = image_noise;
+  }
+  
+  const std::vector<ImageNoise> & get_imageNoise() const
+  {
+    return _tabImageNoise;
+  }
+  void set_imagePolarisation(const ossimString&  polarisation)
+  {
+    _polarisation = polarisation;
+  }
+  
+  const ossimString & get_imagePolarisation() const
+  {
+    return _polarisation;
+  }
+
+
+
+
+protected:
+
+      /**
+       * @brief Image Noise.
+       */
+      ossim_uint32 _numberOfNoiseRecords;
+      /**
+       * @brief Image Noise.
+       */
+      std::vector<ImageNoise> _tabImageNoise;
+      
+      /**
+       * @brief Noise Polarisation Layer.
+       */
+      ossimString _polarisation;      
+      
+  
+private:
+};
+}
+
+#endif
+
diff --git a/ossim_plugins/ossim/otb/PlatformPosition.cpp b/ossim_plugins/ossim/otb/PlatformPosition.cpp
new file mode 100644
index 0000000..07a4506
--- /dev/null
+++ b/ossim_plugins/ossim/otb/PlatformPosition.cpp
@@ -0,0 +1,276 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include <iostream>
+#include <string>
+#include <cmath>
+#include <iomanip>
+#include <vector>
+
+#include <otb/PlatformPosition.h>
+#include <otb/Ephemeris.h>
+#include <otb/HermiteInterpolator.h>
+#include <ossim/base/ossimKeywordlist.h>
+
+namespace ossimplugins
+{
+
+static const char NUMBER_PLATFORM_POSITIONS_KW[] = "platform_positions_count";
+
+PlatformPosition::PlatformPosition():
+   _nbrData(0),
+   _data(NULL),
+   _t(NULL),
+   _p(NULL),
+   _dp(NULL),
+   _interpolator(NULL)
+{
+}
+
+PlatformPosition::~PlatformPosition()
+{
+   Clear();
+      }
+
+void PlatformPosition::Clear()
+{
+   if(_data != NULL)
+   {
+      for (int i=0;i<_nbrData;i++)
+      {
+         delete _data[i];
+            }
+         delete [] _data;
+            }
+      _data = NULL;
+         _nbrData = 0;
+            
+            delete[] _t;
+               if ((_p != NULL) && (_dp != NULL)) {
+                  for (int j=0; j<3; ++j) {
+                     delete[] _p[j];
+                        delete[] _dp[j];
+                           delete _interpolator[j];
+                              }
+                     }
+                  delete[] _p;
+                     delete[] _dp;
+                        
+                        delete[] _interpolator;
+                           }
+
+PlatformPosition::PlatformPosition(const PlatformPosition& rhs)
+{
+   InitData(rhs._data, rhs._nbrData);
+}
+
+PlatformPosition& PlatformPosition::operator=(const PlatformPosition& rhs)
+{
+   Clear();
+      InitData(rhs._data, rhs._nbrData);
+         return *this;
+            }
+
+PlatformPosition::PlatformPosition(Ephemeris** data, int nbrData)
+{
+   InitData(data, nbrData);
+      }
+
+void PlatformPosition::InitData(Ephemeris** data, int nbrData)
+{
+   _nbrData = nbrData;
+      _data = new Ephemeris*[_nbrData];
+         for (int i=0; i<_nbrData; i++)
+         {
+            _data[i] = data[i]->Clone();
+               }
+            InitAuxiliaryData();
+               }
+
+void PlatformPosition::InitAuxiliaryData()
+{
+   const double JOURCIVIL_LENGTH = 86400.0;
+      _t = new double[_nbrData];
+         _p = new double*[3];
+            _dp = new double*[3];
+               _interpolator = new HermiteInterpolator*[3];
+                  for (int j=0; j<3; ++j) {
+                     _p[j] = new double[_nbrData];
+                        _dp[j] = new double[_nbrData];
+                           }
+                     
+                     _t[0] = 0.0;
+                        for (int i = 1; i < _nbrData; i++)
+                        {
+                           _t[i] =   (_data[i]->get_date().get_day0hTU().get_julianDate() - _data[0]->get_date().get_day0hTU().get_julianDate())
+                              * JOURCIVIL_LENGTH
+                              + _data[i]->get_date().get_second() - _data[0]->get_date().get_second()
+                              + _data[i]->get_date().get_decimal() - _data[0]->get_date().get_decimal();
+                              }
+                           
+                           for (int j = 0; j < 3; j++)
+                           {
+                              for (int i = 0; i < _nbrData; i++)
+                              {
+                                 _p[j][i] = _data[i]->get_position()[j];
+                                    _dp[j][i] = _data[i]->get_speed()[j];
+                                       }
+                                 _interpolator[j] = new HermiteInterpolator(_nbrData, _t, _p[j], _dp[j]);
+                                    }
+                              
+                              }
+
+Ephemeris* PlatformPosition::Interpolate(JSDDateTime date) const
+{
+   const double JOURCIVIL_LENGTH = 86400.0;
+      Ephemeris* ephem = NULL;
+         if (_nbrData <= 1)
+         {
+            return NULL;
+               }
+            /*
+             * The first element of the list is cloned to ensure that the
+             * output ephemeris is expressed in the same coordinate system as
+             * input ones
+             */
+            ephem = _data[0]->Clone();
+               
+               /* NORMAL CASE */
+               /*------------*/
+               double dt = 0.0;
+                  
+                  if (ephem != NULL)
+                  {
+                     ephem->set_date(date);
+                        
+                        dt =  (date.get_day0hTU().get_julianDate()
+                               - _data[0]->get_date().get_day0hTU().get_julianDate())
+                           * JOURCIVIL_LENGTH
+                           + date.get_second() - _data[0]->get_date().get_second()
+                           + date.get_decimal() - _data[0]->get_date().get_decimal();
+                           
+                           /* Computation by Everett  */
+                           /*---------------------*/
+                           double pos[3];
+                              double speed[3];
+                                 for (int j = 0; j < 3; j++)
+                                 {
+                                    _interpolator[j]->Interpolate(dt, pos[j], speed[j]);
+                                       }
+                                    ephem->set_position(pos);
+                                       ephem->set_speed(speed);
+                                          }
+                     return ephem;
+                        }
+
+bool PlatformPosition::getPlatformPositionAtTime(JSDDateTime time, std::vector<double>& position, std::vector<double>& speed)
+{
+   Ephemeris* ephemeris = this->Interpolate(time);
+   double* position_ptr = ephemeris->get_position();
+   double* speed_ptr = ephemeris->get_speed();
+   if (position.size() != 3) position.resize(3);
+   if (speed.size() != 3) speed.resize(3);
+   position[0] = position_ptr[0];
+   position[1] = position_ptr[1];
+   position[2] = position_ptr[2];
+   speed[0] = speed_ptr[0];
+   speed[1] = speed_ptr[1];
+   speed[2] = speed_ptr[2];
+   return true;
+}
+   
+
+void PlatformPosition::setData(Ephemeris** data, int nbrData)
+{
+   Clear();
+   InitData(data, nbrData);
+}
+
+Ephemeris* PlatformPosition::getData(int noData) const
+{
+   if(noData >=0 && noData < _nbrData)
+   {
+      return _data[noData];
+         }
+      return NULL;
+         }
+
+int PlatformPosition::getNbrData() const
+{
+   return _nbrData;
+      }
+
+
+bool PlatformPosition::saveState(ossimKeywordlist& kwl,
+                                 const char* prefix) const
+{
+   kwl.add(prefix, NUMBER_PLATFORM_POSITIONS_KW, _nbrData);
+      
+      std::string s1;
+         if (prefix)
+         {
+            s1 = prefix;
+               }
+            
+            for (int i = 0; i < _nbrData; ++i)
+            {
+               std::string s2 = s1;
+                  s2 += "platform_position[";
+                     s2 += ossimString::toString(i).chars();
+                        s2+= "]";
+                           _data[i]->saveState(kwl, s2.c_str());
+                              }
+               
+               return true;
+                  }
+
+
+bool PlatformPosition::loadState(const ossimKeywordlist& kwl,
+                                 const char* prefix)
+{
+   bool result = true;
+      
+      Clear();
+         
+         const char* lookup = 0;
+            lookup = kwl.find(prefix, NUMBER_PLATFORM_POSITIONS_KW);
+               if (!lookup)
+               {
+                  return false;
+                     }
+                  ossimString s = lookup;
+                     _nbrData = s.toInt();
+                        
+                        if (_nbrData)
+                        {
+                           std::string s1;
+                              if (prefix)
+                              {
+                                 s1 = prefix;
+                                    }
+                                 
+                                 _data = new  Ephemeris*[_nbrData];
+                                    for (int i = 0; i < _nbrData; ++i)
+                                    {
+                                       std::string s2 = s1;
+                                          s2 += "platform_position[";
+                                             s2 += ossimString::toString(i).chars();
+                                                s2+= "]";
+                                                   
+                                                   _data[i] = new Ephemeris();
+                                                      _data[i]->loadState(kwl, s2.c_str());
+                                                         }
+                                       }
+                           InitAuxiliaryData();
+                              return result;
+                                 }
+}
+
diff --git a/ossim_plugins/ossim/otb/PlatformPosition.h b/ossim_plugins/ossim/otb/PlatformPosition.h
new file mode 100644
index 0000000..7dc5a06
--- /dev/null
+++ b/ossim_plugins/ossim/otb/PlatformPosition.h
@@ -0,0 +1,137 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef PlatformPosition_h
+#define PlatformPosition_h
+
+#include <vector>
+#include <ossimPluginConstants.h>
+#include <otb/JSDDateTime.h>
+
+class ossimKeywordlist;
+
+namespace ossimplugins
+{
+
+
+   class Ephemeris;
+   class HermiteInterpolator;
+
+
+/**
+ * @ingroup SARModel
+ * @brief This class handles the platform position
+ */
+   class OSSIM_PLUGINS_DLL PlatformPosition
+   {
+   public:
+      /**
+       * @brief Constructor
+       */
+      PlatformPosition();
+      /**
+       * @brief Destructor
+       */
+      ~PlatformPosition();
+      /**
+       * @brief Copy constructor
+       */
+      PlatformPosition(const PlatformPosition& rhs);
+
+      /**
+       * @brief Constructor with initialisation
+       * @param data Ephemeris
+       * @param nbrData Number of Ephemeris in data
+       * @remarks All the ephemeris have to be in the same coordinates system
+       * @remarks This constructor copy the content of data, so it's the
+       * calling fonction that have to manage the memory of data.
+       */
+      PlatformPosition(Ephemeris** data, int nbrData);
+
+      /**
+       * @brief Affectation operator
+       */
+      PlatformPosition& operator=(const PlatformPosition& rhs);
+
+      /**
+       * @brief This function interpolates its ephemeris to create a new ephemeris at the given date and time
+       * @param date Date and time at wich the interpolation have to be done
+       * @return The ephemeris at the given date, or NULL if an error occurs
+       */
+      Ephemeris* Interpolate(JSDDateTime date) const;
+
+
+      /**
+       * @brief This function interpolates its ephemeris to create and extract platform's position and speed
+       * @param date Date and time at wich the interpolation have to be done
+       * @return true, or false if an error occurs
+       */
+      bool getPlatformPositionAtTime(JSDDateTime time, std::vector<double>& position, std::vector<double>& speed);
+
+      PlatformPosition* Clone() const
+      {
+         return new PlatformPosition(*this);
+      };
+
+      void setData(Ephemeris** data, int nbrData);
+      Ephemeris* getData(int noData) const;
+
+      int getNbrData() const;
+      /**
+       * @brief Method to save object state to a keyword list.
+       * @param kwl Keyword list to save to.
+       * @param prefix added to keys when saved.
+       * @return true on success, false on error.
+       */
+      bool saveState(ossimKeywordlist& kwl,
+                     const char* prefix=0) const;
+
+      /**
+       * @brief Method to the load (recreate) the state of the object from a
+       * keyword list. Return true if ok or false on error.
+       * @return true if load OK, false on error
+       */
+      bool loadState(const ossimKeywordlist &kwl, const char *prefix=0);
+
+   protected:
+
+      /**
+       * @brief Internal method to initialize data structures
+       */
+      void InitData(Ephemeris** data, int nbrData);
+      void InitAuxiliaryData();
+
+      /**
+       * @brief Number of platform positions
+       * @see _data
+       */
+      int _nbrData;
+
+      /**
+       * @brief Platform positions
+       */
+      Ephemeris** _data;
+
+      /**
+       * @brief This function deletes all the contents of the class
+       */
+      void Clear();
+
+   private:
+      double * _t;
+      double ** _p;
+      double ** _dp;
+      HermiteInterpolator ** _interpolator;
+   };
+}
+
+#endif
+
diff --git a/ossim_plugins/ossim/otb/RadarSat2NoiseLevel.cpp b/ossim_plugins/ossim/otb/RadarSat2NoiseLevel.cpp
new file mode 100644
index 0000000..37497db
--- /dev/null
+++ b/ossim_plugins/ossim/otb/RadarSat2NoiseLevel.cpp
@@ -0,0 +1,317 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include <otb/RadarSat2NoiseLevel.h>
+#include <ossim/base/ossimDpt3d.h>
+#include <ossim/base/ossimKeywordlist.h>
+#include <ossim/base/ossimNotify.h>
+#include <ossim/base/ossimString.h>
+
+
+namespace ossimplugins
+{
+static const char NOISE[] = "referenceNoiseLevel";
+
+static const char BETA_NOUGHT[] ="BetaNought";
+static const char SIGMA_NOUGHT[] ="SigmaNought";
+static const char GAMMA[] ="Gamma";
+
+static const char INCIDENCE_ANGLE_CORRECTION_NAME_KW[] = "incidenceAngleCorrectionName"; 
+static const char PIXEL_FIRST_NOISE_VALUE_KW[] = "pixelFirstNoiseValue";
+static const char STEP_SIZE_KW[] = "stepSize";
+static const char NUMBER_OF_NOISE_LEVEL_VALUE_KW[] = "numberOfNoiseLevelValues";
+static const char NOISE_LEVEL_VALUES_KW[] = "noiseLevelValues";
+static const char UNITS_KW[] = "units";
+static const char OFFSET_KW[] = "offset";
+static const char GAIN_KW[] = "gain";
+static const char SIZE_KW[] = "size";
+
+RadarSat2NoiseLevel::RadarSat2NoiseLevel():
+  _incidenceAngleCorrectionName("Unknown"), 
+  _pixelFirstNoiseValue(0),
+  _stepSize(0),
+  _numberOfNoiseLevelValues(0),
+  _noiseLevelValues(),
+  _units("Unknown"),
+  _offset(0.0),
+  _gain()
+{
+}
+
+RadarSat2NoiseLevel::~RadarSat2NoiseLevel()
+{
+}
+
+
+RadarSat2NoiseLevel::RadarSat2NoiseLevel(const RadarSat2NoiseLevel& rhs):
+  _incidenceAngleCorrectionName(rhs._incidenceAngleCorrectionName), 
+  _pixelFirstNoiseValue(rhs._pixelFirstNoiseValue),     
+  _stepSize(rhs._stepSize),
+  _numberOfNoiseLevelValues(rhs._numberOfNoiseLevelValues),
+  _noiseLevelValues(rhs._noiseLevelValues),
+  _units(rhs._units), 
+  _offset(rhs._offset),
+  _gain(rhs._gain)
+{
+}
+
+RadarSat2NoiseLevel& RadarSat2NoiseLevel::operator=(const RadarSat2NoiseLevel& rhs)
+{
+  _incidenceAngleCorrectionName = rhs._incidenceAngleCorrectionName; 
+  _pixelFirstNoiseValue = rhs._pixelFirstNoiseValue;     
+  _stepSize = rhs._stepSize;
+  _numberOfNoiseLevelValues = rhs._numberOfNoiseLevelValues;
+  _noiseLevelValues = rhs._noiseLevelValues;
+  _units = rhs._units; 
+  _offset = rhs._offset;
+  _gain = rhs._gain;
+  return *this;
+}
+
+bool RadarSat2NoiseLevel::saveState(ossimKeywordlist& kwl, const char* prefix) const
+{
+   std::string pfx;
+   if (prefix)
+   {
+      pfx = prefix;
+   }
+   pfx += NOISE;
+   
+   if(_incidenceAngleCorrectionName == "Gamma")
+   {
+   		pfx = pfx + "["+ GAMMA +"]";
+   }
+   if(_incidenceAngleCorrectionName == "Sigma Nought")
+   {
+   		pfx = pfx + "["+ SIGMA_NOUGHT +"]";
+   }
+   if(_incidenceAngleCorrectionName == "Beta Nought")
+   {
+   		pfx = pfx + "["+ BETA_NOUGHT +"]";
+   }
+
+   pfx +=".";
+   
+   std::string s = pfx + INCIDENCE_ANGLE_CORRECTION_NAME_KW;
+   kwl.add(prefix, s.c_str(), _incidenceAngleCorrectionName);
+   
+   s = pfx + PIXEL_FIRST_NOISE_VALUE_KW;
+   kwl.add(prefix, s.c_str(), _pixelFirstNoiseValue);
+   
+   s = pfx + STEP_SIZE_KW;
+   kwl.add(prefix, s.c_str(), _stepSize);
+
+   s = pfx + NUMBER_OF_NOISE_LEVEL_VALUE_KW;
+   kwl.add(prefix, s.c_str(), _numberOfNoiseLevelValues);
+   
+   s = pfx + UNITS_KW;
+   kwl.add(prefix, s.c_str(), _units);
+   
+   for (unsigned int i = 0; i < _noiseLevelValues.size(); ++i)
+   {
+      	s = pfx + NOISE_LEVEL_VALUES_KW + "[" + ossimString::toString(i).chars() + "]";
+   		kwl.add(prefix, s.c_str(), _noiseLevelValues[i]);
+   }
+
+   s = pfx + OFFSET_KW;
+   kwl.add(prefix, s.c_str(), _offset);
+
+   s = pfx + GAIN_KW;
+   kwl.add(prefix, s.c_str(), _gain);
+
+   return true;
+}
+
+bool RadarSat2NoiseLevel::loadState(const ossimKeywordlist& kwl, const char* prefix)
+{
+   static const char MODULE[] = "RadarSat2NoiseLevel::loadState";
+
+   //bool         result = true;
+   ossimString  s;
+   const char*  lookup = 0;
+
+   std::string pfx("");
+   if (prefix)
+   {
+      pfx = prefix;
+   }
+
+   pfx += NOISE;
+
+   if(_incidenceAngleCorrectionName == "Gamma")
+   {
+   		pfx = pfx + "["+ GAMMA +"]";
+   }
+   if(_incidenceAngleCorrectionName == "Sigma Nought")
+   {
+   		pfx = pfx + "["+ SIGMA_NOUGHT +"]";
+   }
+   if(_incidenceAngleCorrectionName == "Beta Nought")
+   {
+   		pfx = pfx + "["+ BETA_NOUGHT +"]";
+   }
+   
+   
+
+  std::string s1 = pfx + "["+ GAMMA +"]";
+  lookup = kwl.find(s1.c_str(), INCIDENCE_ANGLE_CORRECTION_NAME_KW);
+  if (!lookup)
+  {
+  		std::string s1 = pfx + "["+ SIGMA_NOUGHT +"]";
+  		lookup = kwl.find(s1.c_str(), INCIDENCE_ANGLE_CORRECTION_NAME_KW);
+  		if (!lookup)
+  		{
+  			std::string s1 = pfx + "["+ BETA_NOUGHT +"]";
+  			lookup = kwl.find(s1.c_str(), INCIDENCE_ANGLE_CORRECTION_NAME_KW);
+  			if (!lookup)
+  			{
+    				ossimNotify(ossimNotifyLevel_WARN)
+         				<< MODULE << " Keyword not found: " << INCIDENCE_ANGLE_CORRECTION_NAME_KW << "\n";
+    				return false;
+  			}
+  		}
+  }
+
+  _incidenceAngleCorrectionName = lookup;
+  pfx= s1;
+
+  lookup = kwl.find(s1.c_str(), PIXEL_FIRST_NOISE_VALUE_KW);
+  if (lookup)
+  {
+    s = lookup;
+    _pixelFirstNoiseValue = s.toUInt32();
+  }
+  else
+  {
+    ossimNotify(ossimNotifyLevel_WARN)
+         << MODULE << " Keyword not found: " << PIXEL_FIRST_NOISE_VALUE_KW << "\n";
+    return false;
+  }
+
+  lookup = kwl.find(s1.c_str(), STEP_SIZE_KW);
+  if (lookup)
+  {
+    s = lookup;
+    _stepSize = s.toUInt32();
+  }
+  else
+  {
+    ossimNotify(ossimNotifyLevel_WARN)
+         << MODULE << " Keyword not found: " << STEP_SIZE_KW << "\n";
+    return false;
+  }
+
+  lookup = kwl.find(s1.c_str(), NUMBER_OF_NOISE_LEVEL_VALUE_KW);
+  if (lookup)
+  {
+    s = lookup;
+    _numberOfNoiseLevelValues = s.toUInt32();
+  }
+  else
+  {
+    ossimNotify(ossimNotifyLevel_WARN)
+         << MODULE << " Keyword not found: " << NUMBER_OF_NOISE_LEVEL_VALUE_KW << "\n";
+    return false;
+  }
+
+
+  lookup = kwl.find(s1.c_str(), UNITS_KW);
+  if (lookup)
+  {
+    _units = lookup;
+  }
+  else
+  {
+    ossimNotify(ossimNotifyLevel_WARN)
+         << MODULE << " Keyword not found: " << UNITS_KW << "\n";
+    return false;
+  }
+   
+   _noiseLevelValues.clear();
+   for (unsigned int i = 0; i < _numberOfNoiseLevelValues; ++i)
+   {
+      	s = pfx + NOISE_LEVEL_VALUES_KW + "[" + ossimString::toString(i) + "]";
+  	  	lookup = kwl.find(s.c_str(), "");
+  	  	if (lookup)
+  		{
+    		s = lookup;
+    		_noiseLevelValues.push_back( s.toDouble() );
+  		}      
+   }
+   
+   if( _numberOfNoiseLevelValues != _noiseLevelValues.size() )
+   {
+    	ossimNotify(ossimNotifyLevel_WARN)
+        		 	<< MODULE
+        		  	<< " Keyword " << NOISE_LEVEL_VALUES_KW 
+        		  	<< " is different with the number of noise level values"
+        		  	<< std::endl;
+        return false;		  	
+   }
+
+  lookup = kwl.find(s1.c_str(), GAIN_KW);
+  if (lookup)
+  {
+    _gain = lookup;;
+  }
+  else
+  {
+    ossimNotify(ossimNotifyLevel_WARN)
+         << MODULE << " Keyword not found: " << GAIN_KW << "\n";
+    return false;
+  }
+
+  lookup = kwl.find(s1.c_str(), OFFSET_KW);
+  if (lookup)
+  {
+    s = lookup;
+    _offset = s.toFloat64();
+  }
+  else
+  {
+    ossimNotify(ossimNotifyLevel_WARN)
+         << MODULE << " Keyword not found: " << OFFSET_KW << "\n";
+    return false;
+  }
+   
+  if( _numberOfNoiseLevelValues != _noiseLevelValues.size() )
+  {
+    	ossimNotify(ossimNotifyLevel_WARN)
+        		 	<< MODULE
+        		  	<< " Keyword " << NOISE_LEVEL_VALUES_KW 
+        		  	<< " is different with the number of noise level values"
+        		  	<< std::endl;
+        return false;		  	
+  }
+
+
+  return true;
+}
+
+
+std::ostream& RadarSat2NoiseLevel::print(std::ostream& out) const
+{
+   out << setprecision(15) << setiosflags(ios::fixed)
+       << "\n RadarSat2NoiseLevel class data members:\n";
+
+   //const char* prefix = 0;
+   //ossimKeywordlist kwl;
+   //ossimString pfx;
+
+   /* TODO Add print method*/
+   
+   //out << kwl;
+
+   return out;
+}
+
+}
+
diff --git a/ossim_plugins/ossim/otb/RadarSat2NoiseLevel.h b/ossim_plugins/ossim/otb/RadarSat2NoiseLevel.h
new file mode 100644
index 0000000..696186e
--- /dev/null
+++ b/ossim_plugins/ossim/otb/RadarSat2NoiseLevel.h
@@ -0,0 +1,161 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef RadarSat2NoiseLevel_h
+#define RadarSat2NoiseLevel_h
+
+#include <ossim/base/ossimConstants.h>
+#include <ossimPluginConstants.h>
+#include <otb/JSDDateTime.h>
+#include <otb/ImageNoise.h>
+
+class ossimKeywordlist;
+
+namespace ossimplugins
+{
+
+/**
+ * @ingroup RadarSat2NoiseLevel
+ * @brief This class represents an Noise
+ */
+class OSSIM_PLUGINS_DLL RadarSat2NoiseLevel
+{
+public:
+   /**
+    * @brief Constructor
+    */
+   RadarSat2NoiseLevel();
+
+   /**
+    * @brief Destructor
+    */
+   virtual ~RadarSat2NoiseLevel();
+
+   /**
+    * @brief Copy constructor
+    */
+   RadarSat2NoiseLevel(const RadarSat2NoiseLevel& rhs);
+
+   /**
+    * @brief Affectation operator
+    */
+   RadarSat2NoiseLevel& operator=(const RadarSat2NoiseLevel& rhs);
+
+   /**
+    * @brief Method to save object state to a keyword list.
+    * @param kwl Keyword list to save to.
+    * @param prefix added to keys when saved.
+    * @return true on success, false on error.
+    */
+   bool saveState(ossimKeywordlist& kwl, const char* prefix=0) const;
+
+   /**
+    * @brief Method to the load (recreate) the state of the object from a
+    * keyword list. Return true if ok or false on error.
+    * @return true if load OK, false on error
+    */
+   bool loadState (const ossimKeywordlist &kwl, const char *prefix=0);
+   /*!
+    * METHOD: print()
+    * Fulfills base-class pure virtual. Dumps contents of object to ostream.
+    */
+   virtual std::ostream& print(std::ostream& out) const;
+   
+   
+   void set_incidenceAngleCorrectionName(const ossimString&  value)
+   {
+    	_incidenceAngleCorrectionName = value;
+   }  
+   void set_pixelFirstNoiseValue(const ossim_uint32&  value)
+   {
+    	_pixelFirstNoiseValue = value;
+   }  
+   void set_stepSize(const ossim_uint32&  value)
+   {
+    	_stepSize = value;
+   }  
+   void set_numberOfNoiseLevelValues(const ossim_uint32&  value)
+   {
+    	_numberOfNoiseLevelValues = value;
+   }  
+   void set_noiseLevelValues(const std::vector<ossim_float64>&  value)
+   {
+    	_noiseLevelValues = value;
+   }  
+   void set_units(const ossimString&  value)
+   {
+    	_units = value;
+   }  
+   void set_offset(const ossim_float64&  value)
+   {
+    	_offset = value;
+   }  
+   void set_gain(const ossimString&  value)
+   {
+    	_gain = value;
+   }  
+
+   const ossimString & get_incidenceAngleCorrectionName() const
+   {
+   		return _incidenceAngleCorrectionName;
+   }
+   const ossimString & get_gain() const
+   {
+   		return _gain;
+   }
+
+protected:
+
+      /**
+       * @brief Incidence Angle correction Name
+       */
+      ossimString               _incidenceAngleCorrectionName; 
+
+      /**
+       * @brief pixel First Noise Value
+       */
+      ossim_uint32              _pixelFirstNoiseValue;     
+      /**
+       * @brief step Size
+       */
+      ossim_uint32              _stepSize;
+
+      /**
+       * @brief number Of Noise Level Values
+       */
+      ossim_uint32              _numberOfNoiseLevelValues;
+
+      /**
+       * @brief noise Level Values
+       */
+      std::vector<ossim_float64> _noiseLevelValues;
+
+      /**
+       * @brief noise Level units
+       */
+      ossimString               _units; 
+      
+      /**
+       * @brief offset value
+       */
+      ossim_float64 _offset;
+
+      /**
+       * @brief lookup table
+       */
+	  ossimString   _gain;
+      
+private:
+};
+}
+
+#endif
+
diff --git a/ossim_plugins/ossim/otb/RectangularCoordinate.cpp b/ossim_plugins/ossim/otb/RectangularCoordinate.cpp
new file mode 100644
index 0000000..979d06f
--- /dev/null
+++ b/ossim_plugins/ossim/otb/RectangularCoordinate.cpp
@@ -0,0 +1,108 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include <otb/RectangularCoordinate.h>
+#include <otb/GeodesicCoordinate.h>
+
+#include <cmath>
+
+namespace ossimplugins
+{
+
+
+RectangularCoordinate::RectangularCoordinate()
+{
+}
+
+RectangularCoordinate::~RectangularCoordinate()
+{
+}
+
+RectangularCoordinate::RectangularCoordinate(double x, double y, double z): Coordinate(x,y,z)
+{
+}
+
+RectangularCoordinate::RectangularCoordinate(const RectangularCoordinate& rhs): Coordinate((Coordinate)rhs)
+{
+}
+
+RectangularCoordinate& RectangularCoordinate::operator=(const RectangularCoordinate& rhs)
+{
+  _x = rhs._x;
+  _y = rhs._x;
+  _z = rhs._x;
+
+  return *this;
+}
+
+void RectangularCoordinate::AsGeodesicCoordinates(double demiGdAxe, double demiPtAxe, GeodesicCoordinate* geod)
+{
+  const double PI          = 3.14159265358979323846 ;
+  const int itmax = 40 ;
+  const double epsilon = 1.0e-6 ;
+
+  int fin , iter ;
+  double u, a2_b2, d, e, f, df, c, s, p, q ;
+
+  double coordCart[3];
+  double coordGeod[3];
+
+  coordCart[0] = _x;
+  coordCart[1] = _y;
+  coordCart[2] = _z;
+
+  u = sqrt (coordCart[0] * coordCart[0] + coordCart[1] * coordCart[1]) ;
+  if (u < epsilon)
+  {
+    coordGeod[0] = 0.0 ;
+    if (coordCart[2] >= 0.0)
+    coordGeod[1] = PI / 2.0 ;
+    else
+    coordGeod[1] = - PI / 2.0 ;
+    coordGeod[2] = fabs (coordCart[2]) - demiPtAxe ;
+  }
+  else
+  {
+    coordGeod[0] = atan2 (coordCart[1] , coordCart[0]) ;
+    a2_b2 = demiGdAxe * demiGdAxe - demiPtAxe * demiPtAxe ;
+    e     = atan (coordCart[2] / u) ;
+    fin   = 0 ;
+    iter  = 0 ;
+    while (fin == 0)
+    {
+      iter++ ;
+      d  = e ;
+      c  = cos (e) ;
+      s  = sin (e) ;
+      p  = demiGdAxe * u ;
+      q  = demiPtAxe * coordCart[2] ;
+      f  = p * s - q * c - a2_b2 * s * c ;
+      df = p * c + q * s - a2_b2 * (c * c - s * s) ;
+      e  = e - f / df ;
+      d  = fabs (e - d) ;
+      if ((d < epsilon) || (iter >= itmax))
+        fin = 1 ;
+    }
+    coordGeod[1] = atan (tan (e) * demiGdAxe / demiPtAxe) ;
+
+    p = cos(coordGeod[1]) ;
+
+    if (fabs(coordGeod[1]) <= (PI * 0.5))
+      coordGeod[2] = (u - demiGdAxe * cos(e)) / cos(coordGeod[1]) ;
+    else
+      coordGeod[2] = (coordCart[2] - demiPtAxe * sin(e)) / sin(coordGeod[1]) ;
+
+    geod->set_coordinates(coordGeod[0],coordGeod[1], coordGeod[2]);
+  }
+  //return 0 ;
+}
+}
+
diff --git a/ossim_plugins/ossim/otb/RectangularCoordinate.h b/ossim_plugins/ossim/otb/RectangularCoordinate.h
new file mode 100644
index 0000000..53e637d
--- /dev/null
+++ b/ossim_plugins/ossim/otb/RectangularCoordinate.h
@@ -0,0 +1,59 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef RectangularCoordinate_h
+#define RectangularCoordinate_h
+
+#include <ossimPluginConstants.h>
+#include <otb/Coordinate.h>
+
+namespace ossimplugins
+{
+
+
+class GeodesicCoordinate;
+/**
+ * @ingroup Date
+ * @brief This class represents a coordinate in a rectangular reference
+ */
+ class OSSIM_PLUGINS_DLL RectangularCoordinate : public Coordinate
+ {
+ public:
+  /**
+    * @brief Constructor
+    */
+  RectangularCoordinate();
+  /**
+   * @brief Destructor
+   */
+  ~RectangularCoordinate();
+  /**
+   * @brief Cosntructor with initializations
+   */
+  RectangularCoordinate(double x, double y, double z);
+  /**
+   * @brief Copy constructor
+   */
+  RectangularCoordinate(const RectangularCoordinate& rhs);
+
+  /**
+   * @brief Affectation operator
+   */
+  RectangularCoordinate& operator=(const RectangularCoordinate& rhs);
+
+  void AsGeodesicCoordinates(double demiGdAxe, double demiPtAxe, GeodesicCoordinate* geod);
+ protected:
+ private:
+ };
+}
+
+ #endif
+
diff --git a/ossim_plugins/ossim/otb/RefPoint.cpp b/ossim_plugins/ossim/otb/RefPoint.cpp
new file mode 100644
index 0000000..fe91054
--- /dev/null
+++ b/ossim_plugins/ossim/otb/RefPoint.cpp
@@ -0,0 +1,199 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include <otb/RefPoint.h>
+#include <otb/Ephemeris.h>
+#include <cstring>
+#include <ossim/base/ossimKeywordlist.h>
+
+namespace ossimplugins
+{
+
+
+static const char PREFIX[]      = "ref_point.";
+static const char DISTANCE_KW[] = "distance";
+static const char LINE_KW[]     = "line";
+static const char COL_KW[]      = "col";
+
+RefPoint::RefPoint():
+   _ephemeris(0),
+   _distance(0.0),
+   _pix_line(0.0),
+   _pix_col(0.0)
+{
+}
+
+RefPoint::~RefPoint()
+{
+   if(_ephemeris != 0)
+   {
+      delete _ephemeris;
+   }
+}
+
+RefPoint::RefPoint(const RefPoint& rhs):
+   _distance(rhs._distance),
+   _pix_line(rhs._pix_line),
+   _pix_col(rhs._pix_col)
+{
+   _ephemeris = rhs._ephemeris->Clone();
+}
+
+RefPoint& RefPoint::operator=(const RefPoint& rhs)
+{
+   _distance = rhs._distance;
+   _pix_line = rhs._pix_line;
+   _pix_col = rhs._pix_col;
+   if(_ephemeris != 0)
+   {
+      delete _ephemeris;
+      _ephemeris = 0;
+   }
+   _ephemeris = rhs._ephemeris->Clone();
+
+   return *this;
+}
+
+void RefPoint::set_ephemeris(Ephemeris* ephemeris)
+{
+   if(_ephemeris != 0)
+   {
+      delete _ephemeris;
+      _ephemeris = 0;
+   }
+   _ephemeris = ephemeris->Clone();
+}
+
+void RefPoint::set_distance(double distance)
+{
+   _distance = distance;
+}
+
+void RefPoint::set_pix_line(double pix_line)
+{
+   _pix_line = pix_line;
+}
+
+void RefPoint::set_pix_col(double pix_col)
+{
+   _pix_col = pix_col;
+}
+
+Ephemeris* RefPoint::get_ephemeris()
+{
+   return _ephemeris;
+}
+
+double RefPoint::get_distance() const
+{
+   return _distance;
+}
+
+double RefPoint::get_pix_line() const
+{
+   return _pix_line;
+}
+
+double RefPoint::get_pix_col() const
+{
+   return _pix_col;
+}
+
+bool RefPoint::saveState(ossimKeywordlist& kwl, const char* prefix) const
+{
+   bool result = true;
+
+   std::string pfx;
+   if (prefix)
+   {
+      pfx = prefix;
+   }
+   pfx += PREFIX;
+
+   if (_ephemeris)
+   {
+      result = _ephemeris->saveState(kwl, pfx.c_str());
+   }
+   else
+   {
+      result = false;
+   }
+
+   kwl.add(pfx.c_str(), DISTANCE_KW, _distance);
+   kwl.add(pfx.c_str(), LINE_KW,     _pix_line);
+   kwl.add(pfx.c_str(), COL_KW,      _pix_col);
+
+   return result;
+}
+
+bool RefPoint::loadState(const ossimKeywordlist& kwl, const char* prefix)
+{
+   bool result = true;
+
+   std::string pfx;
+   if (prefix)
+   {
+      pfx = prefix;
+   }
+   pfx += PREFIX;
+
+
+   if (!_ephemeris)
+   {
+      _ephemeris = new Ephemeris();
+   }
+
+   result = _ephemeris->loadState(kwl, pfx.c_str());
+
+   const char* lookup = 0;
+   ossimString s;
+   double d;
+
+   lookup = kwl.find(pfx.c_str(), DISTANCE_KW);
+   if (lookup)
+   {
+      s = lookup;
+      d = s.toDouble();
+      _distance = d;
+   }
+   else
+   {
+      result = false;
+   }
+
+   lookup = kwl.find(pfx.c_str(), LINE_KW);
+   if (lookup)
+   {
+      s = lookup;
+      d = s.toDouble();
+      _pix_line = d;
+   }
+   else
+   {
+      result = false;
+   }
+
+   lookup = kwl.find(pfx.c_str(), COL_KW);
+   if (lookup)
+   {
+      s = lookup;
+      d = s.toDouble();
+      _pix_col = d;
+   }
+   else
+   {
+      result = false;
+   }
+
+   return result;
+}
+}
+
diff --git a/ossim_plugins/ossim/otb/RefPoint.h b/ossim_plugins/ossim/otb/RefPoint.h
new file mode 100644
index 0000000..d084238
--- /dev/null
+++ b/ossim_plugins/ossim/otb/RefPoint.h
@@ -0,0 +1,89 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef RefPoint_h
+#define RefPoint_h
+
+#include <ossimPluginConstants.h>
+
+class ossimKeywordlist;
+
+namespace ossimplugins
+{
+
+
+class Ephemeris;
+
+
+/**
+ * @brief This class handles the referential point
+ */
+class OSSIM_PLUGINS_DLL RefPoint
+{
+public:
+   /**
+    * @brief Constuctor
+    */
+   RefPoint();
+   /**
+    * @brief Destructor
+    */
+   ~RefPoint();
+   /**
+    * @brief Copy constructor
+    */
+   RefPoint(const RefPoint& rhs);
+   /**
+    * @brief Affectation operator
+    */
+   RefPoint& operator=(const RefPoint& rhs);
+
+   void set_ephemeris(Ephemeris* ephemeris);
+   void set_distance(double distance);
+   void set_pix_line(double pix_line);
+   void set_pix_col(double pix_col);
+
+   Ephemeris* get_ephemeris();
+   double get_distance() const;
+   double get_pix_line() const;
+   double get_pix_col() const;
+
+   RefPoint* Clone()
+   {
+      return new RefPoint(*this);
+   };
+
+   /**
+    * @brief Method to save object state to a keyword list.
+    * @param kwl Keyword list to save to.
+    * @param prefix added to keys when saved.
+    * @return true on success, false on error.
+    */
+   bool saveState(ossimKeywordlist& kwl, const char* prefix=0) const;
+
+   /**
+    * @brief Method to the load (recreate) the state of the object from a
+    * keyword list. Return true if ok or false on error.
+    * @return true if load OK, false on error
+    */
+   bool loadState (const ossimKeywordlist &kwl, const char *prefix=0);
+
+protected:
+   Ephemeris* _ephemeris;
+   double _distance;
+   double _pix_line;
+   double _pix_col;
+private:
+};
+}
+
+#endif
+
diff --git a/ossim_plugins/ossim/otb/SarSensor.cpp b/ossim_plugins/ossim/otb/SarSensor.cpp
new file mode 100644
index 0000000..fabd8a1
--- /dev/null
+++ b/ossim_plugins/ossim/otb/SarSensor.cpp
@@ -0,0 +1,237 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include <otb/SarSensor.h>
+#include <otb/JSDDateTime.h>
+#include <otb/Ephemeris.h>
+#include <otb/GeographicEphemeris.h>
+#include <otb/Sensor.h>
+#include <otb/SensorParams.h>
+#include <otb/PlatformPosition.h>
+#include <otb/Equation.h>
+#include <otb/RectangularCoordinate.h>
+#include <otb/GeodesicCoordinate.h>
+#include <complex>
+
+
+namespace ossimplugins
+{
+
+
+SarSensor::SarSensor(SensorParams* params, PlatformPosition* position) : Sensor(params, position)
+{
+}
+
+SarSensor::~SarSensor()
+{
+}
+
+int SarSensor::ImageToWorld(double distance, JSDDateTime time, double height, double& lon, double& lat) const
+{
+  const double TWOPI      = 6.28318530717958647693 ;
+
+  double semiMajorAxis = _params->get_semiMajorAxis() ;  // default : WGS84
+  double semiMinorAxis = _params->get_semiMinorAxis() ; // default : WGS84
+
+  double lambda = _params->get_rwl();
+  int sensVisee ;
+  if (_params->get_sightDirection() == SensorParams::Right) sensVisee = 1 ;
+  else sensVisee = -1 ;
+
+  Ephemeris* satPosition = _position->Interpolate(time);
+
+  GeographicEphemeris *geoEph = (GeographicEphemeris*)satPosition;
+
+  RectangularCoordinate cart;
+
+  double dopplerCentroid = _params->get_dopcen();
+  double dopcenLinear = _params->get_dopcenLinear();
+  if (dopcenLinear != 0.0)
+  {
+	  dopplerCentroid += dopcenLinear * distance/1000; // Hz/km
+  }
+
+  // note : the Doppler frequency is set to zero
+  int etatLoc = localisationSAR(*geoEph, lambda, distance, dopplerCentroid, sensVisee, semiMajorAxis , semiMinorAxis , height, &cart);
+
+  GeodesicCoordinate geo;
+  cart.AsGeodesicCoordinates(semiMajorAxis , semiMinorAxis, &geo);
+  lon = (geo.get_x())*360.0/TWOPI;
+  lat = (geo.get_y())*360.0/TWOPI;
+
+  delete satPosition;
+
+  return etatLoc ;
+}
+
+int SarSensor::localisationSAR ( GeographicEphemeris posSpeed , double lambda ,
+                        double dist , double fDop , int sensVisee ,
+                        double equRadius , double polRadius ,
+                        double h , RectangularCoordinate* cart ) const
+{
+  double coordCart[3];
+  coordCart[0]=0.0;
+  coordCart[1]=0.0;
+  coordCart[2]=0.0;
+
+
+  double rho2 , k , a , b , c , d , u , v , w ;
+  double x[4] , y[4] , z[4] , r[4] ;
+  bool isEnd;
+
+
+  /* Initialization of characteristical values                */
+  /* note :  for precise computation :                */
+  /*           - ranges are processed in mm                  */
+  /*           - velocities are processed in  km/s           */
+  /*           - frequencies are processed in kHz             */
+  const double KILO = 1.0e-3 ;
+  const double MEGA = 1.0e-6 ;
+  const double EPSILON = 1.0e-12 ;
+
+
+  double dist1 = dist * MEGA ;
+  double fDop1 = fDop * KILO ;
+
+  double he    = (equRadius + h) * MEGA ;       /* Equatorial radius + h */
+  double hp    = (polRadius + h) * MEGA ;       /* Polar radius + h    */
+
+  double posX  = posSpeed.get_position()[0] * MEGA ;
+  double posY  = posSpeed.get_position()[1] * MEGA ;
+  double posZ  = posSpeed.get_position()[2] * MEGA ;
+  double speedX = - posSpeed.get_speed()[0] * KILO ;
+  double speedY = - posSpeed.get_speed()[1] * KILO ;
+  double speedZ = - posSpeed.get_speed()[2] * KILO ;
+
+
+  /* Coefficients computation and equation solving */
+  int state  = 0;
+  u = speedX * posY - speedY * posX ;
+  a = (speedX / u) * (1.0 - (he / hp) * (he / hp)) / 2.0 ;
+  b = (speedX * posZ - speedZ * posX) / u ;
+  rho2 = posX * posX + posY * posY + posZ * posZ ;
+  k    = posX * speedX + posY * speedY + posZ * speedZ -
+         lambda * dist1 * fDop1 / 2.0 ;
+  c = (speedX * (he * he + rho2 - dist1 * dist1) - 2.0 * k * posX) / (2.0 * u);
+
+  u     = speedZ - b * speedY ;
+  v     = c * speedY - k ;
+  w     = v * v - (speedX * speedX) * (he * he - c * c) ;
+
+  std::complex<double> aa[5];
+  aa[0] = std::complex<double>(w,0.0);            /* Constant coefficient     */
+  w     = 2.0 * (u * v - (b * c) * (speedX * speedX)) ;
+  aa[1] = std::complex<double>(w,0.0) ;                     /* First order coefficient  */
+  w     = u * u + 2.0 * a * v * speedY +
+          (speedX * speedX) * ((he / hp) * (he / hp) + b * b + 2.0 * a * c) ;
+  aa[2] = std::complex<double>(w,0.0) ;                     /* Second order coefficient */
+  w     = 2.0 * a * (u * speedY - b * speedX * speedX) ;
+  aa[3] = std::complex<double>(w,0.0) ;                     /* Third order coefficient  */
+  w     = (speedX * speedX + speedY * speedY) * a * a ;
+  aa[4] = std::complex<double>(w,0.0) ;                     /* Fourth order coefficient */
+
+  Equation eq(4,aa);    /* Equation solving */
+  eq.Solve();
+
+  int n = eq.get_nbrSol();
+  const std::complex<double> *root = eq.get_solutions();
+
+  int nRoot = 0 ;
+  for (int i = 0 ; i < n ; i++)               /* Real root selection */
+  {
+    d = fabs(root[i].imag()) ;
+    if (d < EPSILON)
+    {
+      z[nRoot] = root[i].real();
+      y[nRoot] = (a * z[nRoot] - b) * z[nRoot] + c ;
+      x[nRoot] = (k - (speedY * y[nRoot] + speedZ * z[nRoot])) / speedX ;
+      nRoot    = nRoot + 1 ;
+    }
+  }
+  if (nRoot == 0)
+    state = 2 ;  /* No root */
+
+
+  /* Computed roots sort */
+
+  if (state == 0)
+  {
+    int  indice[4] ;
+    for (int i = 0 ; i < nRoot ; i++)
+    {
+      /* Computation of the "distance" between roots images and equation values */
+      u = x[i] - posX ;
+      v = y[i] - posY ;
+      w = z[i] - posZ ;
+      r[i] = fabs ((u * u + v * v + w * w) / (dist1 * dist1) - 1.0 ) ;
+      u = u * speedX ;
+      v = v * speedY ;
+      w = w * speedZ ;
+      if (fabs (fDop) > EPSILON)
+        r[i] = r[i] + fabs (1.0 + 2.0 * (u + v + w) / (lambda * dist1 * fDop1));
+      else
+        r[i] = r[i] + fabs (2.0 * (u + v + w) / (lambda * dist1)) ;
+      u = x[i] / he ;
+      v = y[i] / he ;
+      w = z[i] / hp ;
+      r[i] = r[i] + fabs (u * u + v * v + w * w - 1.0) ;
+      indice[i] = i ;
+    }
+
+    /* Roots sort by increasing differences */
+    isEnd = false ;
+    while (!isEnd)
+    {
+      isEnd = true;
+      for (int i = 0 ; i < (nRoot - 1) ; i++)
+      {
+        int i1 = indice[i] ;
+        int i2 = indice[i+1] ;
+        if (r[i2] < r[i1])
+        {
+          indice[i] = i2 ;
+          indice[i+1] = i1 ;
+          isEnd = false ;
+        }
+      }
+    }
+
+    /* Selection of the correct root (corresponding to the imaging direction) */
+    isEnd = false ;
+    int i = 0 ;
+    while (!isEnd && (i < nRoot))
+    {
+      int i1 = indice[i] ;
+      u  = posY * speedZ - posZ * speedY ;
+      v  = posZ * speedX - posX * speedZ ;
+      w  = posX * speedY - posY * speedX ;
+      a  = x[i1] - posX ;
+      b  = y[i1] - posY ;
+      c  = z[i1] - posZ ;
+      d  = (a * u + b * v + c * w) * sensVisee;
+      if (d >= 0.0)
+      {
+        coordCart[0] = x[i1] / MEGA ;   /* Coordinates in the      */
+        coordCart[1] = y[i1] / MEGA ;   /* geographic referential,  */
+        coordCart[2] = z[i1] / MEGA ;   /* in legal units (m)      */
+        isEnd = true;
+      }
+      i++ ;
+    }
+    if (!isEnd)
+      state = 1 ;  /* No root in the imaging direction */
+  }
+
+  cart->set_coordinates(coordCart[0], coordCart[1], coordCart[2]);
+  return state ;
+}
+}
+
diff --git a/ossim_plugins/ossim/otb/SarSensor.h b/ossim_plugins/ossim/otb/SarSensor.h
new file mode 100644
index 0000000..89ce884
--- /dev/null
+++ b/ossim_plugins/ossim/otb/SarSensor.h
@@ -0,0 +1,72 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef SarSensor_h
+#define SarSensor_h
+
+#include <ossimPluginConstants.h>
+#include <otb/Sensor.h>
+
+namespace ossimplugins
+{
+
+
+class SensorParams;
+class PlatformPosition;
+class GeographicEphemeris;
+class RectangularCoordinate;
+class JSDDateTime;
+/**
+ * @ingroup SARModel
+ * @brief This class provides basic location services for SAR sensors
+ */
+class OSSIM_PLUGINS_DLL SarSensor : Sensor
+{
+public:
+  /**
+   * @brief Constructor
+   *
+   * @remarks This constructor creates a copy of params and position
+   */
+  SarSensor(SensorParams* params, PlatformPosition* position);
+  /**
+   * @brief Destructor
+   */
+  virtual ~SarSensor();
+
+  /**
+   * @brief This function is able to convert image coordinates into geodetic world coordinates using a geometric SAR sensor model
+   *
+   * @param distance : Slant range of the image point
+   * @param time :    Azimuth time of the image point
+   * @param height :  Altitude of the world point
+   * @retval lon :    Longitude of the world point
+   * @retval lat :    Latitude of the world point
+   *
+   * @remark : the doppler frequency is set to zero in this implementation
+   */
+  virtual int ImageToWorld(double distance, JSDDateTime time, double height, double& lon, double& lat) const;
+protected:
+
+  /**
+   * @brief This function is able to convert image coordinates into rectangular world coordinates
+   */
+  int localisationSAR ( GeographicEphemeris posSpeed , double lambda ,
+                        double dist , double fDop , int sensVisee ,
+                        double equRadius , double polRadius ,
+                        double h , RectangularCoordinate* cart ) const;
+private:
+};
+
+}
+
+#endif
+
diff --git a/ossim_plugins/ossim/otb/SceneCoord.cpp b/ossim_plugins/ossim/otb/SceneCoord.cpp
new file mode 100644
index 0000000..3893cda
--- /dev/null
+++ b/ossim_plugins/ossim/otb/SceneCoord.cpp
@@ -0,0 +1,166 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include <otb/SceneCoord.h>
+#include <ossim/base/ossimDpt3d.h>
+#include <ossim/base/ossimKeywordlist.h>
+#include <ossim/base/ossimNotify.h>
+#include <ossim/base/ossimString.h>
+
+
+namespace ossimplugins
+{
+static const char SCENE_COORD[] = "sceneCoord";
+static const char NUMBER_OF_SCENE_CORNER_COORD[] = "numberOfSceneCornerCoord";
+static const char SCENE_CENTER_COORD[] = "sceneCenterCoord";
+static const char SCENE_CORNER_COORD[] = "sceneCornerCoord";
+
+SceneCoord::SceneCoord()
+   :
+   _numberOfSceneCoord(0),
+   _centerSceneCoord(),
+   _tabCornersSceneCoord()
+{
+}
+   
+SceneCoord::~SceneCoord()
+{
+}
+   
+SceneCoord::SceneCoord(const SceneCoord& rhs)
+   :
+   _numberOfSceneCoord(rhs._numberOfSceneCoord),
+   _centerSceneCoord(rhs._centerSceneCoord),
+   _tabCornersSceneCoord(rhs._tabCornersSceneCoord)
+{
+}
+
+SceneCoord& SceneCoord::operator=(const SceneCoord& rhs)
+{
+   if ( this != &rhs )
+   {
+      _numberOfSceneCoord = rhs._numberOfSceneCoord;
+      _centerSceneCoord = rhs._centerSceneCoord;
+      _tabCornersSceneCoord = rhs._tabCornersSceneCoord;
+   }
+   
+   return *this;
+}
+
+bool SceneCoord::saveState(ossimKeywordlist& kwl, const char* prefix) const
+{
+   std::string pfx("");
+   std::string pfx2("");
+   if (prefix)
+   {
+      pfx = prefix;
+   }
+   pfx += SCENE_COORD;
+   pfx2 = pfx;
+   pfx2 += ".";
+   
+   kwl.add(pfx2.c_str(), NUMBER_OF_SCENE_CORNER_COORD, _numberOfSceneCoord);
+
+   std::string s = pfx + "." + SCENE_CENTER_COORD;
+   _centerSceneCoord.saveState(kwl, s.c_str());
+
+   std::string s2 =pfx + "." + SCENE_CORNER_COORD;
+   for (unsigned int i = 0; i < _tabCornersSceneCoord.size(); ++i)
+   {
+      std::string s3 = s2 + "[" + ossimString::toString(i).c_str() + "]";
+      _tabCornersSceneCoord[i].saveState(kwl, s3.c_str());
+   }
+   return true;
+}
+
+bool SceneCoord::loadState(const ossimKeywordlist& kwl, const char* prefix)
+{
+  static const char MODULE[] = "SceneCoord::loadState";
+
+   bool result = true;
+
+   ossimString s;
+   const char* lookup = 0;
+   
+   std::string pfx("");
+   if (prefix)
+   {
+      pfx = prefix;
+   }
+   pfx += SCENE_COORD;
+   pfx += ".";
+ 
+
+   lookup = kwl.find(pfx.c_str(), NUMBER_OF_SCENE_CORNER_COORD);
+
+   if (lookup)
+   {
+     s = lookup;
+     _numberOfSceneCoord = s.toUInt32();
+   }
+   else
+   {
+     ossimNotify(ossimNotifyLevel_WARN)
+        << MODULE << " Keyword not found: " << NUMBER_OF_SCENE_CORNER_COORD << " in "<<pfx.c_str()<<" path.\n";
+     result = false;
+   }
+   
+   std::string s1 = pfx + SCENE_CENTER_COORD;
+   
+   result = _centerSceneCoord.loadState(kwl, s1.c_str());
+
+   _tabCornersSceneCoord.clear();
+   std::string s2 = pfx + SCENE_CORNER_COORD;
+   for (unsigned int i = 0; i < _numberOfSceneCoord; ++i)
+   {
+      std::string s3 = s2 + "[" + ossimString::toString(i).c_str() + "]";
+      InfoSceneCoord isc;
+      result = isc.loadState(kwl, s3.c_str());
+      _tabCornersSceneCoord.push_back(isc);
+   }
+   if( _numberOfSceneCoord != _tabCornersSceneCoord.size() )
+   {
+    ossimNotify(ossimNotifyLevel_WARN)
+	<< MODULE << " Keyword " << NUMBER_OF_SCENE_CORNER_COORD << " is different with the number of _tabCornersScenceCoord nodes \n";
+   }
+
+  return result;
+}
+
+
+std::ostream& SceneCoord::print(std::ostream& out) const
+{
+   out << setprecision(15) << setiosflags(ios::fixed)
+       << "\n SceneCoord class data members:\n";
+
+   const char* prefix = 0;
+   ossimKeywordlist kwl;
+   ossimString pfx;
+   pfx += SCENE_COORD;
+   ossimString s = pfx + "." + NUMBER_OF_SCENE_CORNER_COORD;
+   kwl.add(prefix, s.c_str(), _numberOfSceneCoord);
+   
+   ossimString s1 = pfx + "." + SCENE_CENTER_COORD;
+   _centerSceneCoord.saveState(kwl, s1.c_str());
+
+   ossimString s2 =pfx + "." + SCENE_CORNER_COORD;
+   for (unsigned int i = 0; i < _tabCornersSceneCoord.size(); ++i)
+   {
+     ossimString s3 = s2 + "[" + ossimString::toString(i) + "]";
+     _tabCornersSceneCoord[i].saveState(kwl, s3.c_str());
+   }
+   out << kwl;
+
+   return out;
+}
+
+}
+
diff --git a/ossim_plugins/ossim/otb/SceneCoord.h b/ossim_plugins/ossim/otb/SceneCoord.h
new file mode 100644
index 0000000..e7b3e69
--- /dev/null
+++ b/ossim_plugins/ossim/otb/SceneCoord.h
@@ -0,0 +1,105 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef SceneCoord_h
+#define SceneCoord_h
+
+#include <otb/JSDDateTime.h>
+#include <otb/InfoSceneCoord.h>
+#include <ossim/base/ossimConstants.h>
+#include <ossimPluginConstants.h>
+
+class ossimKeywordlist;
+
+namespace ossimplugins
+{
+
+/**
+ * @ingroup SceneCoord
+ * @brief This class represents Scence coordinate
+ */
+class OSSIM_PLUGINS_DLL SceneCoord
+{
+public:
+   /**
+    * @brief Constructor
+    */
+ SceneCoord();
+
+   /**
+    * @brief Destructor
+    */
+  virtual ~SceneCoord();
+
+   /**
+    * @brief Copy constructor
+    */
+  SceneCoord(const SceneCoord& rhs);
+
+   /**
+    * @brief Affectation operator
+    */
+    SceneCoord& operator=(const SceneCoord& rhs);
+
+    /**
+    * @brief Method to save object state to a keyword list.
+    * @param kwl Keyword list to save to.
+    * @param prefix added to keys when saved.
+    * @return true on success, false on error.
+    */
+   bool saveState(ossimKeywordlist& kwl, const char* prefix=0) const;
+
+   /**
+    * @brief Method to the load (recreate) the state of the object from a
+    * keyword list. Return true if ok or false on error.
+    * @return true if load OK, false on error
+    */
+   bool loadState (const ossimKeywordlist &kwl, const char *prefix=0);
+   /*!
+    * METHOD: print()
+    * Fulfills base-class pure virtual. Dumps contents of object to ostream.
+    */
+   virtual std::ostream& print(std::ostream& out) const;
+
+  void set_numberOfSceneCoord(const ossim_uint32& numberOfSceneCoord)
+  {
+    _numberOfSceneCoord = numberOfSceneCoord;
+  }
+  void set_centerSceneCoord(const InfoSceneCoord& centerSceneCoord)
+  {
+    _centerSceneCoord = centerSceneCoord;
+  }
+  void set_cornersSceneCoord(const std::vector<InfoSceneCoord>& cornersSceneCoord)
+  {
+    _tabCornersSceneCoord = cornersSceneCoord;
+  }
+
+protected:
+
+      /**
+       * @brief Number of scene coordinate
+       */
+      ossim_uint32 _numberOfSceneCoord;
+      /**
+       * @brief Center scene coordinate.
+       */
+      InfoSceneCoord _centerSceneCoord;
+      /**
+       * @brief Corners InfoIncidenceAngle.
+       */
+      std::vector<InfoSceneCoord> _tabCornersSceneCoord;
+  
+private:
+};
+}
+
+#endif
+
diff --git a/ossim_plugins/ossim/otb/Sensor.cpp b/ossim_plugins/ossim/otb/Sensor.cpp
new file mode 100644
index 0000000..b01bfea
--- /dev/null
+++ b/ossim_plugins/ossim/otb/Sensor.cpp
@@ -0,0 +1,41 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include <otb/Sensor.h>
+#include <otb/SensorParams.h>
+#include <otb/PlatformPosition.h>
+
+#include <cstring>
+
+namespace ossimplugins
+{
+
+
+Sensor::Sensor(SensorParams* params, PlatformPosition* position)
+{
+  _params = params->Clone();
+  _position = position->Clone();
+}
+
+Sensor::~Sensor()
+{
+  if(_params != NULL)
+  {
+    delete _params;
+  }
+
+  if(_position != NULL)
+  {
+    delete _position;
+  }
+}
+}
+
diff --git a/ossim_plugins/ossim/otb/Sensor.h b/ossim_plugins/ossim/otb/Sensor.h
new file mode 100644
index 0000000..09ab2e1
--- /dev/null
+++ b/ossim_plugins/ossim/otb/Sensor.h
@@ -0,0 +1,62 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef Services_h
+#define Services_h
+
+#include <ossimPluginConstants.h>
+
+namespace ossimplugins
+{
+
+
+class SensorParams;
+class PlatformPosition;
+class JSDDateTime;
+
+/**
+ * @ingroup SARModel
+ * @brief This class provides basic location services
+ */
+class OSSIM_PLUGINS_DLL Sensor
+{
+public:
+  /**
+   * @brief Constructor
+   *
+   * @remarks This constructor creates a copy of the sensor model (params and position)
+   */
+  Sensor(SensorParams* params, PlatformPosition* position);
+  /**
+   * @brief Destructor
+   */
+  virtual ~Sensor();
+
+  /**
+   * @brief This function is able to convert image coordinates into geodetic world coordinates using a sensor model
+   *
+   * @param distance : Slant range of the image point
+   * @param time :    Azimuth time of the image point
+   * @param height :  Altitude of the world point
+   * @retval lon :    Longitude of the world point
+   * @retval lat :    Latitude of the world point
+   */
+  virtual int ImageToWorld(double distance, JSDDateTime time, double height, double& lon, double& lat) const = 0;
+protected:
+  SensorParams * _params;
+  PlatformPosition* _position;
+
+private:
+};
+
+}
+#endif
+
diff --git a/ossim_plugins/ossim/otb/SensorParams.cpp b/ossim_plugins/ossim/otb/SensorParams.cpp
new file mode 100644
index 0000000..e48f54e
--- /dev/null
+++ b/ossim_plugins/ossim/otb/SensorParams.cpp
@@ -0,0 +1,272 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include <otb/SensorParams.h>
+#include <ossim/base/ossimKeywordlist.h>
+#include <ossim/base/ossimString.h>
+
+namespace ossimplugins
+{
+
+
+static const char PREFIX[]               = "sensor_params.";
+static const char PRF_KW[]               = "prf";
+static const char SF_KW[]                = "sampling_frequency";
+static const char RWL_KW[]               = "radar_wave_length";
+static const char COL_DIR_KW[]           = "column_direction";
+static const char LIN_DIR_KW[]           = "line_direction";
+static const char SIGHT_DIR_KW[]         = "sight_direction";
+static const char SEMI_MAJOR_AXIS_KW[]   = "semi_major_axis";
+static const char SEMI_MINOR_AXIS_KW[]   = "semi_minor_axis";
+static const char NUM_AZIMUTH_LOOKS_KW[] = "number_azimuth_looks";
+static const char NUM_RANGE_LOOKS_KW[]   = "number_range_looks";
+static const char DOPCEN_KW[]            = "doppler_centroid";
+static const char DOPCENLINEAR_KW[]      = "doppler_centroid_linear_term";
+static const char RANGETOFIRSTDATA_KW[]  = "range_to_first_data_sample";
+
+SensorParams::SensorParams():
+   _prf(0.0),
+   _sf(0.0),
+   _rwl(0.0),
+   _col_direction(1),
+   _lin_direction(1),
+   _sightDirection(Right),
+   _semiMajorAxis(6378137.0),
+   _semiMinorAxis(6356752.3141),
+   _nAzimuthLook(1),
+   _nRangeLook(1),
+   _dopcen(0.0),
+   _dopcenLinear(0.0)
+{
+}
+
+SensorParams::~SensorParams()
+{
+}
+
+SensorParams::SensorParams(const SensorParams& rhs):
+   _prf(rhs._prf),
+   _sf(rhs._sf),
+   _rwl(rhs._rwl),
+   _col_direction(rhs._col_direction),
+   _lin_direction(rhs._lin_direction),
+   _sightDirection(rhs._sightDirection),
+   _semiMajorAxis(rhs._semiMajorAxis),
+   _semiMinorAxis(rhs._semiMinorAxis),
+   _nAzimuthLook(rhs._nAzimuthLook),
+   _nRangeLook(rhs._nRangeLook),
+   _dopcen(rhs._dopcen),
+   _dopcenLinear(rhs._dopcenLinear)
+{
+}
+
+SensorParams& SensorParams::operator=(const SensorParams& rhs)
+{
+   _prf = rhs._prf;
+   _sf = rhs._sf;
+   _rwl = rhs._rwl;
+   _col_direction = rhs._col_direction;
+   _lin_direction = rhs._lin_direction;
+   _sightDirection = rhs._sightDirection;
+   _semiMajorAxis = rhs._semiMajorAxis;
+   _semiMinorAxis = rhs._semiMinorAxis;
+   _nAzimuthLook = rhs._nAzimuthLook;
+   _nRangeLook = rhs._nRangeLook;
+   _semiMajorAxis = rhs._semiMajorAxis;
+   _semiMinorAxis = rhs._semiMinorAxis;
+   _dopcen = rhs._dopcen;
+   _dopcenLinear = rhs._dopcenLinear;
+   return *this;
+}
+
+bool SensorParams::saveState(ossimKeywordlist& kwl, const char* prefix) const
+{
+   std::string pfx;
+   if (prefix)
+   {
+      pfx = prefix;
+   }
+   pfx += PREFIX;
+
+   kwl.add(pfx.c_str(), PRF_KW, _prf);
+   kwl.add(pfx.c_str(), SF_KW, _sf);
+   kwl.add(pfx.c_str(), RWL_KW, _rwl);
+   kwl.add(pfx.c_str(), COL_DIR_KW, _col_direction);
+   kwl.add(pfx.c_str(), LIN_DIR_KW, _lin_direction);
+   kwl.add(pfx.c_str(), SIGHT_DIR_KW, static_cast<int>(_sightDirection));
+   kwl.add(pfx.c_str(), SEMI_MAJOR_AXIS_KW, _semiMajorAxis);
+   kwl.add(pfx.c_str(), SEMI_MINOR_AXIS_KW, _semiMinorAxis);
+   kwl.add(pfx.c_str(), NUM_AZIMUTH_LOOKS_KW, _nAzimuthLook);
+   kwl.add(pfx.c_str(), NUM_RANGE_LOOKS_KW, _nRangeLook);
+   kwl.add(pfx.c_str(), DOPCEN_KW, _dopcen);
+   kwl.add(pfx.c_str(), DOPCENLINEAR_KW, _dopcenLinear);
+   return true;
+}
+
+bool SensorParams::loadState(const ossimKeywordlist& kwl, const char* prefix)
+{
+   bool result = true;
+
+   std::string pfx;
+   if (prefix)
+   {
+      pfx = prefix;
+   }
+   pfx += PREFIX;
+
+   ossimString s;
+   const char* lookup = 0;
+
+   lookup = kwl.find(pfx.c_str(), PRF_KW);
+   if (lookup)
+   {
+      s = lookup;
+      _prf = s.toDouble();
+   }
+   else
+   {
+      result = false;
+   }
+
+   lookup = kwl.find(pfx.c_str(), SF_KW);
+   if (lookup)
+   {
+      s = lookup;
+      _sf = s.toDouble();
+   }
+   else
+   {
+      result = false;
+   }
+
+   lookup = kwl.find(pfx.c_str(), RWL_KW);
+   if (lookup)
+   {
+      s = lookup;
+      _rwl = s.toDouble();
+   }
+   else
+   {
+      result = false;
+   }
+
+   lookup = kwl.find(pfx.c_str(), COL_DIR_KW);
+   if (lookup)
+   {
+      s = lookup;
+      _col_direction = s.toInt();
+   }
+   else
+   {
+      result = false;
+   }
+
+   lookup = kwl.find(pfx.c_str(), LIN_DIR_KW);
+   if (lookup)
+   {
+      s = lookup;
+      _lin_direction = s.toInt();
+   }
+   else
+   {
+      result = false;
+   }
+
+   lookup = kwl.find(pfx.c_str(), SIGHT_DIR_KW);
+   if (lookup)
+   {
+      s = lookup;
+      if ( s.toInt() == 0 )
+      {
+         _sightDirection = SensorParams::Left;
+      }
+      else
+      {
+         _sightDirection = SensorParams::Right;
+      }
+   }
+   else
+   {
+      result = false;
+   }
+
+   lookup = kwl.find(pfx.c_str(), SEMI_MAJOR_AXIS_KW);
+   if (lookup)
+   {
+      s = lookup;
+      _semiMajorAxis = s.toDouble();
+   }
+   else
+   {
+      result = false;
+   }
+
+   lookup = kwl.find(pfx.c_str(), SEMI_MINOR_AXIS_KW);
+   if (lookup)
+   {
+      s = lookup;
+      _semiMinorAxis = s.toDouble();
+   }
+   else
+   {
+      result = false;
+   }
+
+   lookup = kwl.find(pfx.c_str(), NUM_AZIMUTH_LOOKS_KW);
+   if (lookup)
+   {
+      s = lookup;
+      _nAzimuthLook = s.toDouble();
+   }
+   else
+   {
+      result = false;
+   }
+
+   lookup = kwl.find(pfx.c_str(), NUM_RANGE_LOOKS_KW);
+   if (lookup)
+   {
+      s = lookup;
+      _nRangeLook = s.toDouble();
+   }
+   else
+   {
+      result = false;
+   }
+
+   lookup = kwl.find(pfx.c_str(), DOPCEN_KW);
+   if (lookup)
+   {
+      s = lookup;
+      _dopcen = s.toDouble();
+   }
+   else
+   {
+      result = false;
+   }
+   return result;
+
+   lookup = kwl.find(pfx.c_str(), DOPCENLINEAR_KW);
+   if (lookup)
+   {
+      s = lookup;
+      _dopcenLinear = s.toDouble();
+   }
+   else
+   {
+      result = false;
+   }
+   return result;
+
+}
+
+}
+
diff --git a/ossim_plugins/ossim/otb/SensorParams.h b/ossim_plugins/ossim/otb/SensorParams.h
new file mode 100644
index 0000000..86183e9
--- /dev/null
+++ b/ossim_plugins/ossim/otb/SensorParams.h
@@ -0,0 +1,267 @@
+//----------------------------------------------------------------------------
+//
+// "Copyright Centre National d'Etudes Spatiales"
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef SensorParams_h
+#define SensorParams_h
+
+#include <ossimPluginConstants.h>
+
+class ossimKeywordlist;
+
+namespace ossimplugins
+{
+
+
+
+/**
+ * @ingroup SARModel
+ * @brief This class handles the sensor parameters
+ */
+
+class OSSIM_PLUGINS_DLL SensorParams
+{
+public:
+
+   enum SightDirection
+   {
+      Left  = 0,
+      Right = 1
+   };
+
+   /**
+    * @brief Constructor
+    */
+   SensorParams();
+   /**
+    * @brief Destructor
+    */
+   virtual ~SensorParams();
+
+   /**
+    *@brief Copy constructor
+    */
+   SensorParams(const SensorParams& rhs);
+
+   /**
+    * @brief Affectation operator
+    */
+   SensorParams& operator=(const SensorParams& rhs);
+
+   double get_prf() const
+   {
+      return _prf;
+   }
+
+   double get_sf() const
+   {
+      return _sf;
+   }
+
+   double get_rwl() const
+   {
+      return _rwl;
+   }
+
+   void set_prf(double prf)
+   {
+      _prf = prf;
+   }
+
+   void set_sf(double sf)
+   {
+      _sf = sf;
+   }
+
+   void set_rwl(double rwl)
+   {
+      _rwl = rwl;
+   }
+
+   SightDirection get_sightDirection() const
+   {
+      return _sightDirection;
+   }
+
+   void set_sightDirection(SightDirection sight)
+   {
+      _sightDirection = sight;
+   }
+
+   virtual SensorParams* Clone()
+   {
+      return new SensorParams(*this);
+   }
+
+   int get_col_direction() const
+   {
+      return _col_direction;
+   }
+
+   int get_lin_direction() const
+   {
+      return _lin_direction;
+   }
+
+   double get_nAzimuthLook() const
+   {
+      return _nAzimuthLook ;
+   }
+
+   double get_nRangeLook() const
+   {
+      return _nRangeLook ;
+   }
+
+   void set_col_direction(int dir)
+   {
+      _col_direction = dir;
+   }
+
+   void set_lin_direction(int dir)
+   {
+      _lin_direction = dir;
+   }
+
+   void set_nAzimuthLook(double look)
+   {
+      _nAzimuthLook = look;
+   }
+
+   void set_nRangeLook(double look)
+   {
+      _nRangeLook = look;
+   }
+
+   double get_semiMajorAxis() const
+   {
+      return _semiMajorAxis ;
+   }
+
+   double get_semiMinorAxis() const
+   {
+      return _semiMinorAxis ;
+   }
+
+   void set_semiMajorAxis(double value)
+   {
+      _semiMajorAxis = value;
+   }
+
+   void set_semiMinorAxis(double value)
+   {
+      _semiMinorAxis = value;
+   }
+
+   double get_dopcen() const
+   {
+     return _dopcen;
+   }
+
+   double get_dopcenLinear() const
+   {
+	   return _dopcenLinear;
+   }
+
+   void set_dopcen(double value)
+   {
+     _dopcen = value;
+   }
+
+   void set_dopcenLinear(double value)
+   {
+	   _dopcenLinear = value;
+   }
+
+
+   /**
+    * @brief Method to save object state to a keyword list.
+    * @param kwl Keyword list to save to.
+    * @param prefix added to keys when saved.
+    * @return true on success, false on error.
+    */
+   bool saveState(ossimKeywordlist& kwl, const char* prefix=0) const;
+
+   /**
+    * @brief Method to the load (recreate) the state of the object from a
+    * keyword list. Return true if ok or false on error.
+    * @return true if load OK, false on error
+    */
+   bool loadState (const ossimKeywordlist &kwl, const char *prefix=0);
+
+protected:
+   /**
+    * @brief Nominal PRF, Hz
+    */
+   double _prf;
+
+   /**
+    * @brief Sampling frequency
+    */
+   double _sf;
+
+   /**
+    * @brief Radar wave length
+    */
+   double _rwl;
+
+   /**
+    * @brief Columns direction (1=increasing, -1=decreasing)
+    */
+   int _col_direction;
+
+   /**
+    * @brief Lines direction (1=increasing, -1=decreasing)
+    */
+   int _lin_direction;
+
+   /**
+    * @brief Antenna pointing direction
+    */
+   SightDirection _sightDirection;
+
+   /**
+    * @brief Ellipsoid semi_major axis, m
+    *        Default : WGS84
+    */
+   double _semiMajorAxis;
+
+   /**
+    * @brief Ellipsoid semi_minor axis, m
+    *        Default : WGS84
+    */
+   double _semiMinorAxis;
+
+   /**
+    * @brief Number of azimuth looks
+    */
+   double _nAzimuthLook ;
+
+   /**
+    * @brief Number of range looks
+    */
+   double _nRangeLook ;
+
+   /**
+    * @brief Doppler centroid (at range 0)
+    */
+   double _dopcen;
+
+   /**
+    * @brief Doppler centroid linear term (wrt range in km)
+    */
+   double _dopcenLinear;
+
+
+private:
+};
+}
+#endif
+
diff --git a/ossim_plugins/ossimPluginConstants.h b/ossim_plugins/ossimPluginConstants.h
new file mode 100644
index 0000000..9d7b9d3
--- /dev/null
+++ b/ossim_plugins/ossimPluginConstants.h
@@ -0,0 +1,43 @@
+//----------------------------------------------------------------------------
+// Copyright (c) 2005, David Burken, all rights reserved.
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author:  David Burken
+//
+// Description: Constants file for ossim plugins.
+//
+// $Id: ossimPluginConstants.h 23664 2015-12-14 14:17:27Z dburken $
+//----------------------------------------------------------------------------
+#ifndef ossimPluginConstants_HEADER
+#define ossimPluginConstants_HEADER
+
+/**
+ * DLL IMPORT/EXORT SECTION
+ */
+#if defined(OSSIM_STATIC)
+#  define OSSIMPLUGINSEXPORT
+#  define OSSIMPLUGINSIMPORT
+#  define OSSIMPLUGINSDLLEXPORT
+#  define OSSIM_PLUGINS_DLL
+#elif defined(__MINGW32__) || defined(__CYGWIN__) || defined(_MSC_VER) || defined(__VISUALC__) || defined(__BORLANDC__) || defined(__WATCOMC__)
+#  define OSSIMPLUGINSEXPORT __declspec(dllexport)
+#  define OSSIMPLUGINSIMPORT __declspec(dllimport)
+#  ifdef OSSIMPLUGINSMAKINGDLL
+#    define OSSIMPLUGINSDLLEXPORT OSSIMPLUGINSEXPORT
+#    define OSSIM_PLUGINS_DLL       OSSIMPLUGINSEXPORT
+#  else
+#    define OSSIMPLUGINSDLLEXPORT OSSIMPLUGINSIMPORT
+#    define OSSIM_PLUGINS_DLL      OSSIMPLUGINSIMPORT
+#  endif
+#else /* not #if defined(_MSC_VER) */
+#  define OSSIMPLUGINSEXPORT
+#  define OSSIMPLUGINSIMPORT
+#  define OSSIMPLUGINSDLLEXPORT
+#  define OSSIM_PLUGINS_DLL
+#endif /* #if defined(_MSC_VER) */
+
+#endif /* #ifndef ossimPluginConstants_HEADER */
+
diff --git a/ossim_plugins/pdal/CMakeLists.txt b/ossim_plugins/pdal/CMakeLists.txt
new file mode 100644
index 0000000..d86c558
--- /dev/null
+++ b/ossim_plugins/pdal/CMakeLists.txt
@@ -0,0 +1,71 @@
+set(LIB_NAME ossimpdal_plugin)
+message( "************** LIBRARY SETUP FOR ossimpdal_plugin******************")
+
+# Include ossim cmake stuff:
+include(OssimVersion)
+include(OssimCommonVariables)
+include(OssimUtilities)
+
+include_directories(${CMAKE_CURRENT_SOURCE_DIR})
+
+set(requiredLibs)
+
+#---
+# Need boost:
+#---
+find_package(Boost)
+if(Boost_FOUND)
+   include_directories(${Boost_INCLUDE_DIRS})
+   set(requiredLibs ${requiredLibs} ${Boost_LIBRARIES})
+else(Boost_FOUND)
+   message(FATAL_ERROR "Could not find boost")
+endif(Boost_FOUND)
+
+find_package(LibXml2)
+if(LIBXML2_FOUND)
+   include_directories(${LIBXML2_INCLUDE_DIR})
+   set(requiredLibs ${requiredLibs} ${LIBXML2_LIBRARIES})
+else(LIBXML2_FOUND)
+   message(FATAL_ERROR "Whoa! Could not find LibXml2")
+endif(LIBXML2_FOUND)
+
+#---
+# FindPDAL.cmake sets:
+# PDAL_INCLUDE_DIR, PDAL_LIBRARIES, and PDAL_FOUND
+#---
+find_package(PDAL)
+if(PDAL_FOUND)
+   include_directories( ${PDAL_INCLUDE_DIR} )
+   set(requiredLibs ${requiredLibs} ${PDAL_LIBRARIES} )
+else(PDAL_FOUND)
+   message(FATAL_ERROR "Could not find pdal")
+endif(PDAL_FOUND)
+
+file(GLOB_RECURSE OSSIMPLUGIN_SRCS *.cpp)
+file(GLOB_RECURSE OSSIMPLUGIN_HEADERS *.h)
+
+#---
+# OSSIMPLUGINSMAKINGDLL controls dll linkage on windows.  
+# Adding this sets OSSIM_PLUGINS_DLL #define TO "__declspec(dllexport)".
+#---
+add_definitions("-DOSSIMPLUGINSMAKINGDLL")
+
+# PDAL uses C++ 2011 code:
+set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11" )
+
+# Adjust the install library path:
+if(OSSIM_INSTALL_PLUGINS_WITH_VERSION)
+   set(INSTALL_LIBRARY_DIR   "${INSTALL_LIBRARY_DIR}/ossim-${OSSIM_VERSION}/plugins")
+else(OSSIM_INSTALL_PLUGINS_WITH_VERSION)
+   set(INSTALL_LIBRARY_DIR   "${INSTALL_LIBRARY_DIR}/ossim/plugins")
+endif(OSSIM_INSTALL_PLUGINS_WITH_VERSION)
+
+OSSIM_LINK_LIBRARY(${LIB_NAME}
+                   COMPONENT_NAME ossim TYPE "${OSSIM_PLUGIN_LINK_TYPE}"
+		   LIBRARIES ${OSSIM_LIBRARY} ${requiredLibs}
+                   HEADERS "${OSSIMPLUGIN_HEADERS}"
+		   SOURCE_FILES "${OSSIMPLUGIN_SRCS}"
+                   INSTALL_LIB)
+
+# Add the test dir:
+add_subdirectory( test )
diff --git a/ossim_plugins/pdal/ossimPdalFileReader.cpp b/ossim_plugins/pdal/ossimPdalFileReader.cpp
new file mode 100644
index 0000000..d352f41
--- /dev/null
+++ b/ossim_plugins/pdal/ossimPdalFileReader.cpp
@@ -0,0 +1,259 @@
+//**************************************************************************************************
+//
+// OSSIM (http://trac.osgeo.org/ossim/)
+//
+// License: MIT
+//
+//**************************************************************************************************
+// $Id: ossimPdalFileReader.cpp 23664 2015-12-14 14:17:27Z dburken $
+
+#include "ossimPdalFileReader.h"
+#include <ossim/point_cloud/ossimPointCloudGeometry.h>
+#include <ossim/base/ossimNotify.h>
+#include <ossim/base/ossimGpt.h>
+#include <ossim/base/ossimUnitConversionTool.h>
+#include <ossim/point_cloud/ossimPointRecord.h>
+#include <pdal/pdal.hpp>
+#include <pdal/PointViewIter.hpp>
+#include <pdal/StatsFilter.hpp>
+#include <pdal/Reader.hpp>
+#include <pdal/FauxReader.hpp>
+
+
+RTTI_DEF1(ossimPdalFileReader, "ossimPdalFileReader" , ossimPdalReader)
+
+using namespace pdal;
+using namespace pdal::Dimension;
+
+ossimPdalFileReader::ossimPdalFileReader()
+{
+}
+
+/** virtual destructor */
+ossimPdalFileReader::~ossimPdalFileReader()
+{
+}
+
+bool ossimPdalFileReader::open(const ossimFilename& fname)
+{
+   // PDAL opens the file here.
+   m_inputFilename = fname;
+   pdal::Stage* reader = 0;
+   try
+   {
+      if (m_inputFilename.contains("fauxreader"))
+      {
+         // Debug generated image:
+         reader = new FauxReader;
+         m_pdalPipe = reader;
+         m_pdalOptions.add("mode", "ramp");
+         BOX3D bbox(-0.001, -0.001, -100.0, 0.001, 0.001, 100.0);
+         m_pdalOptions.add("bounds", bbox);
+         m_pdalOptions.add("num_points", "11");
+         m_pdalPipe->setOptions(m_pdalOptions);
+      }
+      else
+      {
+         StageFactory factory;
+         const string driver = factory.inferReaderDriver(m_inputFilename.string());
+         if (driver == "")
+            throw pdal_error("File type not supported by PDAL");
+         reader = factory.createStage(driver);
+         if (!reader)
+            throw pdal_error("No reader created by PDAL");
+
+         m_pdalOptions.add("filename", m_inputFilename.string());
+         reader->setOptions(m_pdalOptions);
+
+         // Stick a stats filter in the pipeline:
+         m_pdalPipe = new StatsFilter();
+         m_pdalPipe->setInput(*reader);
+      }
+
+      m_pointTable = PointTablePtr(new PointTable);
+      m_pdalPipe->prepare(*m_pointTable);
+      m_pvs = m_pdalPipe->execute(*m_pointTable);
+      if (!m_pvs.empty())
+      {
+         m_currentPV = *(m_pvs.begin());
+
+         // Determine available data fields:
+         establishAvailableFields();
+      }
+
+      std::string wkt;
+      const SpatialReference& srs = reader->getSpatialReference();
+      wkt = srs.getWKT(SpatialReference::eCompoundOK, false);
+      m_geometry = new ossimPointCloudGeometry(wkt);
+   }
+   catch (std::exception& e)
+   {
+      //ossimNotify() << e.what() << endl;
+      return false;
+   }
+
+   // Establish the bounds (geographic & radiometric). These are stored in two extreme point records
+   // maintained by the base class:
+   establishMinMax();
+
+   return true;
+}
+
+ossim_uint32 ossimPdalFileReader::getNumPoints() const
+{
+   if (!m_currentPV)
+      return 0;
+
+   return m_currentPV->size();
+}
+
+
+void ossimPdalFileReader::getFileBlock(ossim_uint32 offset,
+                                       ossimPointBlock& block,
+                                       ossim_uint32 requested) const
+{
+   // A single input file means a single point view coming out of the manager:
+   if (!m_currentPV)
+   {
+      block.clear();
+      return;
+   }
+
+   ossim_uint32 numPoints = m_currentPV->size();
+
+   // Expecting the block object passed in to have been allocated to the desired block size before
+   // this call. Interpreting a size = 0 to mean do nothing:
+   if ((requested == 0) || (offset >= numPoints))
+   {
+      block.clear();
+      return;
+   }
+
+   m_currentPID = offset;
+   parsePointView(block, requested);
+}
+
+void ossimPdalFileReader::establishMinMax()
+{
+   if (!m_pdalPipe || !m_currentPV || !m_geometry.valid())
+      return;
+
+#define USE_STATS_FILTER
+#ifdef USE_STATS_FILTER
+
+   if (!m_minRecord.valid())
+   {
+      m_minRecord = new ossimPointRecord(getFieldCode());
+      m_maxRecord = new ossimPointRecord(getFieldCode());
+   }
+
+   // Attempt to cast down to a stats filter for faster min/max access:
+   ossimString filterName(m_pdalPipe->getName());
+   if (!filterName.contains("filters.stats"))
+   {
+      ossimPdalReader::establishMinMax();
+      return;
+   }
+   pdal::StatsFilter* stats = (pdal::StatsFilter*) m_pdalPipe;
+
+   // The ossimPointRecord should already be initialized with the desired fields set to default
+   // values (i.e., their NULL values):
+   ossimDpt3d minPt, maxPt;
+   const IdList& idList = m_currentPV->dims();
+   IdList::const_iterator dim_iter = idList.begin();
+   while (dim_iter != idList.end())
+   {
+      Id::Enum id = *dim_iter;
+      const stats::Summary& summary = stats->getStats(id);
+
+      switch (id)
+      {
+      case Id::Enum::X: // always do position
+         minPt.x = summary.minimum();
+         maxPt.x = summary.maximum();
+         break;
+      case Id::Enum::Y: // always do position
+         minPt.y = summary.minimum();
+         maxPt.y = summary.maximum();
+         break;
+      case Id::Enum::Z: // always do position
+         minPt.z = summary.minimum();
+         maxPt.z = summary.maximum();
+         break;
+      case Id::Enum::ReturnNumber:
+         if (hasFields(ossimPointRecord::ReturnNumber))
+         {
+            m_minRecord->setField(ossimPointRecord::ReturnNumber, (ossim_float32) summary.minimum());
+            m_maxRecord->setField(ossimPointRecord::ReturnNumber, (ossim_float32) summary.maximum());
+         }
+         break;
+      case Id::Enum::NumberOfReturns:
+         if (hasFields(ossimPointRecord::NumberOfReturns))
+         {
+            m_minRecord->setField(ossimPointRecord::NumberOfReturns, (ossim_float32) summary.minimum());
+            m_maxRecord->setField(ossimPointRecord::NumberOfReturns, (ossim_float32) summary.maximum());
+         }
+         break;
+      case Id::Enum::Intensity:
+         if (hasFields(ossimPointRecord::Intensity))
+         {
+            m_minRecord->setField(ossimPointRecord::Intensity, (ossim_float32) summary.minimum());
+            m_maxRecord->setField(ossimPointRecord::Intensity, (ossim_float32) summary.maximum());
+         }
+         break;
+      case Id::Enum::Red:
+         if (hasFields(ossimPointRecord::Red))
+         {
+            m_minRecord->setField(ossimPointRecord::Red, (ossim_float32) summary.minimum());
+            m_maxRecord->setField(ossimPointRecord::Red, (ossim_float32) summary.maximum());
+         }
+         break;
+      case Id::Enum::Green:
+         if (hasFields(ossimPointRecord::Green))
+         {
+            m_minRecord->setField(ossimPointRecord::Green, (ossim_float32) summary.minimum());
+            m_maxRecord->setField(ossimPointRecord::Green, (ossim_float32) summary.maximum());
+         }
+         break;
+      case Id::Enum::Blue:
+         if (hasFields(ossimPointRecord::Blue))
+         {
+            m_minRecord->setField(ossimPointRecord::Blue, (ossim_float32) summary.minimum());
+            m_maxRecord->setField(ossimPointRecord::Blue, (ossim_float32) summary.maximum());
+         }
+         break;
+      case Id::Enum::Infrared:
+         if (hasFields(ossimPointRecord::Infrared))
+         {
+            m_minRecord->setField(ossimPointRecord::Infrared, (ossim_float32) summary.minimum());
+            m_maxRecord->setField(ossimPointRecord::Infrared, (ossim_float32) summary.maximum());
+         }
+         break;
+      case Id::Enum::GpsTime:
+         if (hasFields(ossimPointRecord::GpsTime))
+         {
+            m_minRecord->setField(ossimPointRecord::GpsTime, (ossim_float32) summary.minimum());
+            m_maxRecord->setField(ossimPointRecord::GpsTime, (ossim_float32) summary.maximum());
+         }
+         break;
+      default:
+         break;
+      }
+      ++dim_iter;
+   }
+
+   // Need to convert X, Y, Z to geographic point (if necessary).
+   ossimGpt min_gpt, max_gpt;
+   m_geometry->convertPos(minPt, min_gpt);
+   m_minRecord->setPosition(min_gpt);
+   m_geometry->convertPos(maxPt, max_gpt);
+   m_maxRecord->setPosition(max_gpt);
+
+#else
+
+   ossimPdalReader::establishMinMax();
+
+#endif
+
+}
+
diff --git a/ossim_plugins/pdal/ossimPdalFileReader.h b/ossim_plugins/pdal/ossimPdalFileReader.h
new file mode 100644
index 0000000..ab8c2b3
--- /dev/null
+++ b/ossim_plugins/pdal/ossimPdalFileReader.h
@@ -0,0 +1,55 @@
+//**************************************************************************************************
+//
+// OSSIM (http://trac.osgeo.org/ossim/)
+//
+// License: MIT
+//
+//**************************************************************************************************
+// $Id: ossimPdalFileReader.h 23664 2015-12-14 14:17:27Z dburken $
+
+#ifndef ossimPdalFileReader_HEADER
+#define ossimPdalFileReader_HEADER 1
+
+#include "ossimPdalReader.h"
+#include "../ossimPluginConstants.h"
+#include <pdal/pdal.hpp>
+
+class ossimPointRecord;
+class Stage;
+
+#define USE_FULL_POINT_CLOUD_BUFFERING
+
+class OSSIM_PLUGINS_DLL ossimPdalFileReader : public ossimPdalReader
+{
+public:
+
+   /** default constructor */
+   ossimPdalFileReader();
+
+   /** virtual destructor */
+   virtual ~ossimPdalFileReader();
+
+   /** Accepts the name of a point cloud file. Returns TRUE if successful.  */
+   virtual bool open(const ossimFilename& fname);
+
+   /**
+    *  Fetches up to maxNumPoints points at the given dataset <offset> in the order they
+    * appear in the data file. Thread-safe implementation accepts a previously-allocated vector
+    * from the caller. The offset is set to offset + block.size (or EOF) upon exit, to
+    * permit sequencing with getNextBlock() implmented in base class.
+    */
+   virtual void getFileBlock(ossim_uint32 offset,
+                             ossimPointBlock& block,
+                             ossim_uint32 maxNumPoints=0xFFFFFFFF) const;
+
+   virtual ossim_uint32 getNumPoints() const;
+
+private:
+   virtual void establishMinMax();
+
+
+TYPE_DATA
+};
+
+#endif /* #ifndef ossimPdalFileReader_HEADER */
+
diff --git a/ossim_plugins/pdal/ossimPdalPluginInit.cpp b/ossim_plugins/pdal/ossimPdalPluginInit.cpp
new file mode 100644
index 0000000..8cda503
--- /dev/null
+++ b/ossim_plugins/pdal/ossimPdalPluginInit.cpp
@@ -0,0 +1,80 @@
+//----------------------------------------------------------------------------
+//
+// License:  See top level LICENSE.txt file
+//
+// Author:  David Burken
+//
+// Description:
+// 
+// OSSIM Point Data Abstractin Library(PDAL) plugin initialization code.
+//
+//----------------------------------------------------------------------------
+// $Id
+
+#include <ossim/plugin/ossimSharedObjectBridge.h>
+#include "../ossimPluginConstants.h"
+#include "ossimPdalReaderFactory.h"
+//#include "ossimPdalImageHandlerFactory.h"
+#include <ossim/base/ossimString.h>
+#include <ossim/point_cloud/ossimPointCloudHandlerRegistry.h>
+#include <ossim/imaging/ossimImageHandlerRegistry.h>
+
+static void setDescription(ossimString& description)
+{
+   description = "pdal reader / writer plugin\n\n";
+}
+
+extern "C"
+{
+   ossimSharedObjectInfo  myInfo;
+   ossimString theDescription;
+   std::vector<ossimString> theObjList;
+
+   const char* getDescription()
+   {
+      return theDescription.c_str();
+   }
+
+   int getNumberOfClassNames()
+   {
+      return (int)theObjList.size();
+   }
+
+   const char* getClassName(int idx)
+   {
+      if(idx < (int)theObjList.size())
+      {
+         return theObjList[0].c_str();
+      }
+      return (const char*)0;
+   }
+
+   /* Note symbols need to be exported on windoze... */ 
+   OSSIM_PLUGINS_DLL void ossimSharedLibraryInitialize(
+      ossimSharedObjectInfo** info)
+   {    
+      myInfo.getDescription = getDescription;
+      myInfo.getNumberOfClassNames = getNumberOfClassNames;
+      myInfo.getClassName = getClassName;
+      
+      *info = &myInfo;
+      
+      /* Register the readers... */
+      ossimPointCloudHandlerRegistry::instance()->
+         registerFactory(ossimPdalReaderFactory::instance());
+      
+      //ossimImageHandlerRegistry::instance()->
+      //   registerFactory(ossimPdalImageHandlerFactory::instance());
+
+      setDescription(theDescription);
+   }
+
+   /* Note symbols need to be exported on windoze... */ 
+   OSSIM_PLUGINS_DLL void ossimSharedLibraryFinalize()
+   {
+      ossimPointCloudHandlerRegistry::instance()->
+         unregisterFactory(ossimPdalReaderFactory::instance());
+      //ossimImageHandlerRegistry::instance()->
+      //   unregisterFactory(ossimPdalImageHandlerFactory::instance());
+   }
+}
diff --git a/ossim_plugins/pdal/ossimPdalReader.cpp b/ossim_plugins/pdal/ossimPdalReader.cpp
new file mode 100644
index 0000000..09d6d72
--- /dev/null
+++ b/ossim_plugins/pdal/ossimPdalReader.cpp
@@ -0,0 +1,336 @@
+//**************************************************************************************************
+//
+// OSSIM (http://trac.osgeo.org/ossim/)
+//
+// License: MIT
+//
+//**************************************************************************************************
+// $Id$
+
+#include "ossimPdalReader.h"
+#include <ossim/point_cloud/ossimPointCloudGeometry.h>
+#include <ossim/base/ossimNotify.h>
+#include <ossim/base/ossimGpt.h>
+#include <ossim/base/ossimUnitConversionTool.h>
+#include <ossim/point_cloud/ossimPointRecord.h>
+#include <pdal/PointViewIter.hpp>
+
+RTTI_DEF1(ossimPdalReader, "ossimPdalReader" , ossimPointCloudHandler)
+
+using namespace pdal;
+using namespace pdal::Dimension;
+
+ossimPdalReader::ossimPdalReader()
+:  m_currentPV (0),
+   m_currentPvOffset (0),
+   m_pdalPipe (0),
+   m_availableFields(0)
+{
+   // create unity-transform, geographic geometry. derived classes may overwrite this later
+   m_geometry = new ossimPointCloudGeometry();
+}
+
+/** virtual destructor */
+ossimPdalReader::~ossimPdalReader()
+{
+   delete m_pdalPipe;
+}
+
+void ossimPdalReader::rewind() const
+{
+   m_currentPvOffset = 0;
+   if (m_pvs.size())
+      m_currentPV = *(m_pvs.begin());
+   else
+      m_currentPV = 0;
+   m_currentPID = 0;
+}
+
+void ossimPdalReader::parsePointView(ossimPointBlock& block, ossim_uint32 maxNumPoints) const
+{
+   ossim_uint32 field_code = block.getFieldCode();
+   while (m_currentPvOffset < m_currentPV->size())
+   {
+      if (block.size() == maxNumPoints)
+         break;
+
+      // Convert point data to OSSIM-friendly format:
+#ifdef NORMALIZE_FIELDS
+      ossim_float32 minI, delI, minC, delC;
+      bool hasIntensity = false;
+      bool hasRGB = false;
+      if (field_code & ossimPointRecord::Intensity)
+      {
+         hasIntensity = true;
+         minI = m_minRecord->getField(ossimPointRecord::Intensity);
+         delI = m_maxRecord->getField(ossimPointRecord::Intensity) - minI;
+      }
+      ossim_uint32 rgb_code = ossimPointRecord::Red | ossimPointRecord::Green | ossimPointRecord::Blue;
+      if ((field_code & rgb_code) == rgb_code)
+      {
+         hasRGB = true;
+         minC = m_minRecord->getField(ossimPointRecord::Red);
+         delC = m_maxRecord->getField(ossimPointRecord::Red) - minC;
+      }
+#endif
+
+      //   cout << "ossimPdalReader::parsePointView() -- point_id = "<< point_id<<endl;
+
+      // Reads directly from the PDAL point buffer:
+      ossimRefPtr<ossimPointRecord> opr = new ossimPointRecord(field_code);
+      parsePoint(opr.get());
+
+      // Normalize intensity and color:
+#ifdef NORMALIZE_FIELDS
+      if (hasIntensity)
+      {
+         float normI = (opr->getField(ossimPointRecord::Intensity) - minI) / delI;
+         opr->setField(ossimPointRecord::Intensity, normI);
+      }
+      if (hasRGB)
+      {
+         float normC = (opr->getField(ossimPointRecord::Red) - minC) / delC;
+         opr->setField(ossimPointRecord::Red, normC);
+         normC = (opr->getField(ossimPointRecord::Green) - minC) / delC;
+         opr->setField(ossimPointRecord::Green, normC);
+         normC = (opr->getField(ossimPointRecord::Blue) - minC) / delC;
+         opr->setField(ossimPointRecord::Blue, normC);
+      }
+#endif
+
+      // Add this point to the output block:
+      opr->setPointId(m_currentPID++);
+      block.addPoint(opr.get());
+      ++m_currentPvOffset;
+   }
+}
+
+void ossimPdalReader::parsePoint(ossimPointRecord* point) const
+{
+   if (!point)
+      return;
+
+   ossimDpt3d dpt3d;
+   ossim_uint8 I8;
+   float F32;
+
+   // The ossimPointRecord should already be initialized with the desired fields set to default
+   // values (i.e., their NULL values):
+   const IdList& idList = m_currentPV->dims();
+   IdList::const_iterator dim_iter = idList.begin();
+   while (dim_iter != idList.end())
+   {
+      Id::Enum id = *dim_iter;
+      switch (id)
+      {
+      case Id::Enum::X: // always do position
+         dpt3d.x = m_currentPV->getFieldAs<double>(Id::Enum::X, m_currentPvOffset);
+         break;
+      case Id::Enum::Y: // always do position
+         dpt3d.y = m_currentPV->getFieldAs<double>(Id::Enum::Y, m_currentPvOffset);
+         break;
+      case Id::Enum::Z: // always do position
+         dpt3d.z = m_currentPV->getFieldAs<double>(Id::Enum::Z, m_currentPvOffset);
+         break;
+      case Id::Enum::ReturnNumber:
+         if (point->hasFields(ossimPointRecord::ReturnNumber))
+         {
+            I8 = m_currentPV->getFieldAs<uint8_t>(Id::Enum::ReturnNumber, m_currentPvOffset);
+            point->setField(ossimPointRecord::ReturnNumber, (ossim_float32) I8);
+         }
+         break;
+      case Id::Enum::NumberOfReturns:
+         if (point->hasFields(ossimPointRecord::NumberOfReturns))
+         {
+            I8 = m_currentPV->getFieldAs<uint8_t>(Id::Enum::NumberOfReturns, m_currentPvOffset);
+            point->setField(ossimPointRecord::NumberOfReturns, (ossim_float32) I8);
+         }
+         break;
+      case Id::Enum::Intensity:
+         if (point->hasFields(ossimPointRecord::Intensity))
+         {
+            F32 = m_currentPV->getFieldAs<float>(Id::Enum::Intensity, m_currentPvOffset);
+            point->setField(ossimPointRecord::Intensity, (ossim_float32) F32);
+         }
+         break;
+      case Id::Enum::Red:
+         if (point->hasFields(ossimPointRecord::Red))
+         {
+            F32 = m_currentPV->getFieldAs<float>(Id::Enum::Red, m_currentPvOffset);
+            point->setField(ossimPointRecord::Red, (ossim_float32) F32);
+         }
+         break;
+      case Id::Enum::Green:
+         if (point->hasFields(ossimPointRecord::Green))
+         {
+            F32 = m_currentPV->getFieldAs<float>(Id::Enum::Green, m_currentPvOffset);
+            point->setField(ossimPointRecord::Green, (ossim_float32) F32);
+         }
+         break;
+      case Id::Enum::Blue:
+         if (point->hasFields(ossimPointRecord::Blue))
+         {
+            F32 = m_currentPV->getFieldAs<float>(Id::Enum::Blue, m_currentPvOffset);
+            point->setField(ossimPointRecord::Blue, (ossim_float32) F32);
+         }
+         break;
+      case Id::Enum::Infrared:
+         if (point->hasFields(ossimPointRecord::Infrared))
+         {
+            F32 = m_currentPV->getFieldAs<float>(Id::Enum::Infrared, m_currentPvOffset);
+            point->setField(ossimPointRecord::Infrared, (ossim_float32) F32);
+         }
+         break;
+      case Id::Enum::GpsTime:
+         if (point->hasFields(ossimPointRecord::GpsTime))
+         {
+            F32 = m_currentPV->getFieldAs<float>(Id::Enum::GpsTime, m_currentPvOffset);
+            point->setField(ossimPointRecord::GpsTime, (ossim_float32) F32);
+         }
+         break;
+      default:
+         break;
+      }
+      ++dim_iter;
+   }
+
+   // Need to convert X, Y, Z to geographic point (if necessary).
+   ossimGpt pos;
+   m_geometry->convertPos(dpt3d, pos);
+   point->setPosition(pos);
+}
+
+void ossimPdalReader::establishMinMax()
+{
+   rewind();
+
+   PointViewSet::iterator pvs_iter = m_pvs.begin();
+   if ((pvs_iter == m_pvs.end()) || (*pvs_iter)->empty())
+      return;
+
+   if (!m_minRecord.valid())
+   {
+      m_minRecord = new ossimPointRecord(getFieldCode());
+      m_maxRecord = new ossimPointRecord(getFieldCode());
+   }
+
+   // Latch first point:
+   m_currentPV = *pvs_iter;
+   parsePoint(m_minRecord.get());
+   *m_maxRecord = *m_minRecord;
+   ossimGpt minPos (m_minRecord->getPosition());
+   ossimGpt maxPos (minPos);
+
+   // Set up loop over all point view sets:
+   ossimRefPtr<ossimPointRecord> opr = new ossimPointRecord(m_minRecord->getFieldCode());
+   while (pvs_iter != m_pvs.end())
+   {
+      // Set up loop over points in each PointView:
+      m_currentPV = *pvs_iter;
+      m_currentPvOffset = 0;
+
+      // Now loop over all points in PV to latch min/max:
+      PointViewIter pv_iter = m_currentPV->begin();
+      while (pv_iter != m_currentPV->end())
+      {
+         parsePoint(opr.get());
+
+         if (opr->getPosition().lat < minPos.lat)
+            minPos.lat = opr->getPosition().lat;
+         if (opr->getPosition().lon < minPos.lon)
+            minPos.lon = opr->getPosition().lon;
+         if (opr->getPosition().hgt < minPos.hgt)
+            minPos.hgt = opr->getPosition().hgt;
+
+         if (opr->getPosition().lat > maxPos.lat)
+            maxPos.lat = opr->getPosition().lat;
+         if (opr->getPosition().lon > maxPos.lon)
+            maxPos.lon = opr->getPosition().lon;
+         if (opr->getPosition().hgt > maxPos.hgt)
+            maxPos.hgt = opr->getPosition().hgt;
+
+         std::map<ossimPointRecord::FIELD_CODES, ossim_float32>::const_iterator field =
+               opr->getFieldMap().begin();
+         while (field != opr->getFieldMap().end())
+         {
+            if (field->second < m_minRecord->getField(field->first))
+               m_minRecord->setField(field->first, field->second);
+            else if (field->second > m_maxRecord->getField(field->first))
+               m_maxRecord->setField(field->first, field->second);
+            ++field;
+         }
+         ++pv_iter;
+         ++m_currentPvOffset;
+      }
+      ++pvs_iter;
+   }
+
+   m_minRecord->setPosition(minPos);
+   m_maxRecord->setPosition(maxPos);
+
+   // Latch overall min and max color band to avoid color distortion when normalizing:
+   const ossimPointRecord::FIELD_CODES R = ossimPointRecord::Red;
+   const ossimPointRecord::FIELD_CODES G = ossimPointRecord::Green;
+   const ossimPointRecord::FIELD_CODES B = ossimPointRecord::Blue;
+   if (m_minRecord->hasFields(R|G|B))
+   {
+      ossim_float32 r = m_minRecord->getField(R);
+      ossim_float32 g = m_minRecord->getField(G);
+      ossim_float32 b = m_minRecord->getField(B);
+      float c = std::min(r, std::min(g, b));
+      m_minRecord->setField(R, c);
+      m_minRecord->setField(G, c);
+      m_minRecord->setField(B, c);
+
+      r = m_maxRecord->getField(R);
+      g = m_maxRecord->getField(G);
+      b = m_maxRecord->getField(B);
+      c = std::max(r, std::max(g, b));
+      m_maxRecord->setField(R, c);
+      m_maxRecord->setField(G, c);
+      m_maxRecord->setField(B, c);
+   }
+
+   rewind();
+}
+
+ossim_uint32 ossimPdalReader::getNumPoints() const
+{
+   ossim_uint32 numPoints = 0;
+
+   PointViewSet::iterator pvs_iter = m_pvs.begin();
+   while (pvs_iter != m_pvs.end())
+   {
+      numPoints += (*pvs_iter)->size();
+      ++pvs_iter;
+   }
+
+   return numPoints;
+}
+
+void ossimPdalReader::establishAvailableFields()
+{
+   m_availableFields = 0;
+   if (!m_currentPV)
+      return;
+
+   if (m_currentPV->hasDim(Id::Enum::Intensity))
+      m_availableFields |= ossimPointRecord::Intensity;
+   if (m_currentPV->hasDim(Id::Enum::ReturnNumber))
+      m_availableFields |= ossimPointRecord::ReturnNumber;
+   if (m_currentPV->hasDim(Id::Enum::NumberOfReturns))
+      m_availableFields |= ossimPointRecord::NumberOfReturns;
+   if (m_currentPV->hasDim(Id::Enum::Red))
+      m_availableFields |= ossimPointRecord::Red;
+   if (m_currentPV->hasDim(Id::Enum::Green))
+      m_availableFields |= ossimPointRecord::Green;
+   if (m_currentPV->hasDim(Id::Enum::Blue))
+      m_availableFields |= ossimPointRecord::Blue;
+   if (m_currentPV->hasDim(Id::Enum::GpsTime))
+      m_availableFields |= ossimPointRecord::GpsTime;
+   if (m_currentPV->hasDim(Id::Enum::Infrared))
+      m_availableFields |= ossimPointRecord::Infrared;
+}
+
+
+
diff --git a/ossim_plugins/pdal/ossimPdalReader.h b/ossim_plugins/pdal/ossimPdalReader.h
new file mode 100644
index 0000000..666f54d
--- /dev/null
+++ b/ossim_plugins/pdal/ossimPdalReader.h
@@ -0,0 +1,80 @@
+//**************************************************************************************************
+//
+// OSSIM (http://trac.osgeo.org/ossim/)
+//
+// License: MIT
+//
+//**************************************************************************************************
+// $Id$
+
+#ifndef ossimPdalReader_HEADER
+#define ossimPdalReader_HEADER 1
+
+#include <ossim/point_cloud/ossimPointCloudHandler.h>
+#include "../ossimPluginConstants.h"
+#include <pdal/pdal.hpp>
+
+class ossimPointRecord;
+#define USE_FULL_POINT_CLOUD_BUFFERING
+
+typedef std::shared_ptr<pdal::PointTable> PointTablePtr;
+
+class OSSIM_PLUGINS_DLL ossimPdalReader : public ossimPointCloudHandler
+{
+public:
+   /** default constructor */
+   ossimPdalReader();
+
+   /** virtual destructor */
+   virtual ~ossimPdalReader();
+
+   virtual void rewind() const;
+
+   /**
+    * Returns number of points in the data file.
+    */
+   virtual ossim_uint32 getNumPoints() const;
+
+   virtual void close() { m_currentPV = 0; m_pointTable = 0; }
+
+   /**
+    * Fetches the data fields ids available from this source, OR'd together for testing against
+    * specific field (@see ossimPointRecord::FIELD_CODES). e.g. (though should use hasField()),
+    *
+    * bool hasIntensity = getFields() & ossimPointRecord::Intensity;
+    */
+   virtual ossim_uint32 getFieldCode() const { return m_availableFields; }
+
+   /**
+    * Sets the data fields ID of interest for this source, and all input sources connected to this.
+    * This is an OR'd mash-up of @see ossimPointRecord::FIELD_CODES
+    */
+   virtual void setFieldCode (ossim_uint32 fieldCode) { m_availableFields = fieldCode; }
+
+protected:
+   /** The current point ID (pid) gets updated. The block is added to -- pre-existing points remain
+    *  or get overwritten if pid matches existing. */
+   void parsePointView(ossimPointBlock& block, ossim_uint32 maxNumPoints = 0xFFFFFFFF) const;
+
+   /** Need to pass allocated ossimPointRecord with field code set to desired fields. The pointNum
+    * is the point index into the point view */
+   void parsePoint(ossimPointRecord* precord) const;
+
+   /** Computes min and max records using points in the current PointViewSet */
+   virtual void establishMinMax();
+
+   virtual void establishAvailableFields();
+
+   mutable pdal::PointViewSet m_pvs;
+   mutable pdal::PointViewPtr m_currentPV;
+   mutable ossim_uint32 m_currentPvOffset;
+   mutable PointTablePtr m_pointTable;
+   pdal::Stage* m_pdalPipe;
+   mutable pdal::Options m_pdalOptions;
+   ossim_uint32 m_availableFields;
+
+   TYPE_DATA
+};
+
+#endif /* #ifndef ossimPdalReader_HEADER */
+
diff --git a/ossim_plugins/pdal/ossimPdalReaderFactory.cpp b/ossim_plugins/pdal/ossimPdalReaderFactory.cpp
new file mode 100644
index 0000000..988ec4c
--- /dev/null
+++ b/ossim_plugins/pdal/ossimPdalReaderFactory.cpp
@@ -0,0 +1,107 @@
+//**************************************************************************************************
+//
+// OSSIM (http://trac.osgeo.org/ossim/)
+//
+// License: MIT
+//
+//**************************************************************************************************
+// $Id$
+
+#include "ossimPdalReaderFactory.h"
+#include <ossim/base/ossimTrace.h>
+#include "ossimPdalFileReader.h"
+#include "ossimRialtoReader.h"
+
+RTTI_DEF1(ossimPdalReaderFactory, "ossimPdalReaderFactory", ossimPointCloudHandlerFactory);
+
+ossimPdalReaderFactory* ossimPdalReaderFactory::m_instance = 0;
+
+ossimPdalReaderFactory::~ossimPdalReaderFactory()
+{
+   m_instance = 0;
+}
+
+ossimPdalReaderFactory* ossimPdalReaderFactory::instance()
+{
+   if (!m_instance)
+   {
+      m_instance = new ossimPdalReaderFactory;
+   }
+   return m_instance;
+}
+
+ossimPdalReader* ossimPdalReaderFactory::open(const ossimFilename& fileName) const
+{
+   ossimRefPtr<ossimPdalReader> reader = 0;
+
+   reader = new ossimPdalFileReader;
+   if (!reader->open(fileName))
+   {
+      reader = new ossimRialtoReader;
+      if (!reader->open(fileName))
+         reader = 0;
+   }
+   return reader.release();
+}
+
+ossimPdalReader* ossimPdalReaderFactory::open(const ossimKeywordlist& kwl,
+                                                const char* prefix) const
+{
+   ossimRefPtr<ossimPdalReader> reader = new ossimPdalFileReader;
+   if (!reader->loadState(kwl, prefix))
+   {
+      reader = new ossimRialtoReader;
+      if (!reader->loadState(kwl, prefix))
+         reader = 0;
+   }
+
+   return reader.release();
+}
+
+ossimObject* ossimPdalReaderFactory::createObject(const ossimString& typeName) const
+{
+   ossimRefPtr<ossimObject> result = 0;
+   if (typeName == "ossimPdalFileReader")
+   {
+      result = new ossimPdalFileReader;
+   }
+   else if (typeName == "ossimPdalTileDbReader")
+   {
+      result = new ossimRialtoReader;
+   }
+   return result.release();
+}
+
+ossimObject* ossimPdalReaderFactory::createObject(const ossimKeywordlist& kwl,
+                                                  const char* prefix) const
+{
+    return (ossimObject*) open(kwl, prefix);
+}
+
+void ossimPdalReaderFactory::getTypeNameList(std::vector<ossimString>& typeList) const
+{
+   typeList.push_back(ossimString("ossimPdalFileReader"));
+   typeList.push_back(ossimString("ossimPdalTileDbReader"));
+}
+
+void ossimPdalReaderFactory::getSupportedExtensions(std::vector<ossimString>& extensionList) const
+{
+   extensionList.push_back(ossimString("las"));
+   extensionList.push_back(ossimString("laz"));
+   extensionList.push_back(ossimString("sqlite"));
+}
+
+ossimPdalReaderFactory::ossimPdalReaderFactory()
+{
+}
+
+ossimPdalReaderFactory::ossimPdalReaderFactory(const ossimPdalReaderFactory&)
+{
+}
+
+void ossimPdalReaderFactory::operator=(const ossimPdalReaderFactory&)
+{
+}
+
+
+
diff --git a/ossim_plugins/pdal/ossimPdalReaderFactory.h b/ossim_plugins/pdal/ossimPdalReaderFactory.h
new file mode 100644
index 0000000..0f07c3b
--- /dev/null
+++ b/ossim_plugins/pdal/ossimPdalReaderFactory.h
@@ -0,0 +1,60 @@
+//**************************************************************************************************
+//
+// OSSIM (http://trac.osgeo.org/ossim/)
+//
+// License: MIT
+//
+//**************************************************************************************************
+// $Id$
+
+#ifndef ossimPdalReaderFactory_HEADER
+#define ossimPdalReaderFactory_HEADER 1
+
+#include <ossim/point_cloud/ossimPointCloudHandlerFactory.h>
+#include "../ossimPluginConstants.h"
+#include "ossimPdalReader.h"
+
+class ossimString;
+class ossimFilename;
+class ossimKeywordlist;
+
+/** @brief Factory for PNG image reader. */
+class OSSIM_PLUGINS_DLL ossimPdalReaderFactory: public ossimPointCloudHandlerFactory
+{
+public:
+
+   /** @brief virtual destructor */
+   virtual ~ossimPdalReaderFactory();
+
+   static ossimPdalReaderFactory* instance();
+
+   virtual ossimPdalReader* open(const ossimFilename& fileName) const;
+
+   virtual ossimPdalReader* open(const ossimKeywordlist& kwl, const char* prefix = 0) const;
+
+   virtual ossimObject* createObject(const ossimString& typeName) const;
+
+   virtual ossimObject* createObject(const ossimKeywordlist& kwl, const char* prefix = 0) const;
+
+   virtual void getTypeNameList(std::vector<ossimString>& typeList) const;
+
+   virtual void getSupportedExtensions(std::vector<ossimString>& extList) const;
+
+protected:
+   /** @brief hidden from use default constructor */
+   ossimPdalReaderFactory();
+
+   /** @brief hidden from use copy constructor */
+   ossimPdalReaderFactory(const ossimPdalReaderFactory&);
+
+   /** @brief hidden from use copy constructor */
+   void operator=(const ossimPdalReaderFactory&);
+
+   /** static instance of this class */
+   static ossimPdalReaderFactory* m_instance;
+
+TYPE_DATA
+};
+
+#endif /* end of #ifndef ossimPdalReaderFactory_HEADER */
+
diff --git a/ossim_plugins/pdal/ossimRialtoReader.cpp b/ossim_plugins/pdal/ossimRialtoReader.cpp
new file mode 100644
index 0000000..0418950
--- /dev/null
+++ b/ossim_plugins/pdal/ossimRialtoReader.cpp
@@ -0,0 +1,206 @@
+#include "ossimRialtoReader.h"
+#include <set>
+#include <vector>
+#include <ossim/base/ossimNotify.h>
+#include <pdal/PointViewIter.hpp>
+#include <rialto/GeoPackageCommon.hpp>
+
+RTTI_DEF1(ossimRialtoReader, "ossimRialtoReader" , ossimPdalReader)
+
+using namespace pdal;
+using namespace rialto;
+
+
+ossimRialtoReader::ossimRialtoReader()
+{
+}
+
+ossimRialtoReader::~ossimRialtoReader()
+{
+   close();
+}
+
+bool ossimRialtoReader::open(const ossimFilename& db_name)
+{
+   m_inputFilename = db_name;
+   rewind();
+
+   if (!m_inputFilename.ext().contains("gpkg"))
+      return false;
+   try
+   {
+      // Connect to Rialto:
+      m_pdalOptions.add("filename", m_inputFilename.string());
+      m_pdalPipe = new RialtoReader;
+      m_pdalOptions.add("verbose", LogLevel::Debug);
+      m_pdalPipe->setOptions(m_pdalOptions);
+      m_pointTable = PointTablePtr(new PointTable);
+      m_pdalPipe->prepare(*m_pointTable);
+   }
+   catch (std::exception& e)
+   {
+      ossimNotify() << e.what() << endl;
+      return false;
+   }
+
+   m_geometry = new ossimPointCloudGeometry();
+
+   establishMinMax();
+
+   return true;
+}
+
+void ossimRialtoReader::getFileBlock(ossim_uint32 /*offset*/,
+                                     ossimPointBlock& block,
+                                     ossim_uint32 /*np*/) const
+{
+   // Rialto does not support file-based reads. Only allowed through the Db
+   ossimNotify(ossimNotifyLevel_WARN) << "ossimRialtoReader::getFileBlock() WARNING: "
+         "Rialto does not support file-based reads. Returning blank point block."<<endl;
+   block.clear();
+}
+
+void ossimRialtoReader::getBlock(const ossimGrect& bounds, ossimPointBlock& block) const
+{
+   // getBlock() (unlike getFileBlock) necessarily starts with an empty data buffer. Only the
+   // field code is referenced to know which fields to pick out of the PDAL table.
+   block.clear();
+
+   // First set up the bounds to be understood by the PDAL rialto reader:
+   double minx = bounds.ul().lon;
+   double maxx = bounds.lr().lon;
+   double miny = bounds.lr().lat;
+   double maxy = bounds.ul().lat;
+   BOX2D bbox_rect (minx, miny, maxx, maxy);
+   std::string bbox_name ("bounds");
+   Option pdalOption;
+   pdalOption.setName(bbox_name);
+   m_pdalOptions.remove(pdalOption);
+   m_pdalOptions.add(bbox_name, bbox_rect);
+   m_pdalPipe->setOptions(m_pdalOptions);
+   m_pointTable = PointTablePtr(new PointTable);
+   m_pdalPipe->prepare(*m_pointTable);
+
+   // Fetch the points:
+   m_pvs = m_pdalPipe->execute(*m_pointTable);
+
+   // Set up loop over all point view sets:
+   m_currentPID = 0;
+   PointViewSet::iterator pvs_iter = m_pvs.begin();
+   while (pvs_iter != m_pvs.end())
+   {
+      // Set up loop over points in each PointView:
+      m_currentPV = *pvs_iter;
+      m_currentPvOffset = 0;
+      parsePointView(block);
+      ++pvs_iter;
+   }
+}
+
+void ossimRialtoReader::establishMinMax()
+{
+   if (!m_pdalPipe)
+      return;
+
+   if (!m_minRecord.valid())
+   {
+      m_minRecord = new ossimPointRecord;
+      m_maxRecord = new ossimPointRecord;
+   }
+
+   m_availableFields = 0;
+   if (!m_pdalPipe)
+      return;
+
+   ossimGpt minGpt, maxGpt;
+   RialtoReader* reader = (RialtoReader*) m_pdalPipe;
+   const GpkgMatrixSet& info = reader->getMatrixSet();
+   const std::vector<GpkgDimension>& dimList = info.getDimensions();
+   std::vector<GpkgDimension>::const_iterator dim_iter = dimList.begin();
+
+   while (dim_iter != dimList.end())
+   {
+      double min_value = dim_iter->getMinimum();
+      double max_value = dim_iter->getMaximum();
+      ossimString dimName = dim_iter->getName();
+
+      if (dimName.contains("X")) // longitude in rialto world
+      {
+         minGpt.lon = min_value;
+         maxGpt.lon = max_value;
+      }
+      if (dimName.contains("Y")) // latitude in rialto world
+      {
+         minGpt.lat = min_value;
+         maxGpt.lat = max_value;
+      }
+      if (dimName.contains("Z")) // height (meters) in rialto world
+      {
+         minGpt.hgt = min_value;
+         maxGpt.hgt = max_value;
+      }
+      if (dimName.contains("Intensity"))
+      {
+         m_availableFields |= ossimPointRecord::Intensity;
+         m_minRecord->setField(ossimPointRecord::Intensity, (float) min_value);
+         m_maxRecord->setField(ossimPointRecord::Intensity, (float) max_value);
+      }
+      else if (dimName.contains("ReturnNumber"))
+      {
+         m_availableFields |= ossimPointRecord::ReturnNumber;
+         m_minRecord->setField(ossimPointRecord::ReturnNumber, (float) min_value);
+         m_maxRecord->setField(ossimPointRecord::ReturnNumber, (float) max_value);
+      }
+      else if (dimName.contains("NumberOfReturns"))
+      {
+         m_availableFields |= ossimPointRecord::NumberOfReturns;
+         m_minRecord->setField(ossimPointRecord::NumberOfReturns, (float) min_value);
+         m_maxRecord->setField(ossimPointRecord::NumberOfReturns, (float) max_value);
+      }
+      else if (dimName.contains("Red"))
+      {
+         m_availableFields |= ossimPointRecord::Red;
+         m_minRecord->setField(ossimPointRecord::Red, (float) min_value);
+         m_maxRecord->setField(ossimPointRecord::Red, (float) max_value);
+      }
+      else if (dimName.contains("Green"))
+      {
+         m_availableFields |= ossimPointRecord::Green;
+         m_minRecord->setField(ossimPointRecord::Green, (float) min_value);
+         m_maxRecord->setField(ossimPointRecord::Green, (float) max_value);
+      }
+      else if (dimName.contains("Blue"))
+      {
+         m_availableFields |= ossimPointRecord::Blue;
+         m_minRecord->setField(ossimPointRecord::Blue, (float) min_value);
+         m_maxRecord->setField(ossimPointRecord::Blue, (float) max_value);
+      }
+      else if (dimName.contains("GpsTime"))
+      {
+         m_availableFields |= ossimPointRecord::GpsTime;
+         m_minRecord->setField(ossimPointRecord::GpsTime, (float) min_value);
+         m_maxRecord->setField(ossimPointRecord::GpsTime, (float) max_value);
+      }
+      else if (dimName.contains("Infrared"))
+      {
+         m_availableFields |= ossimPointRecord::Infrared;
+         m_minRecord->setField(ossimPointRecord::Infrared, (float) min_value);
+         m_maxRecord->setField(ossimPointRecord::Infrared, (float) max_value);
+      }
+      ++dim_iter;
+   }
+
+   m_minRecord->setPosition(minGpt);
+   m_maxRecord->setPosition(maxGpt);
+
+   // TODO: REMOVE DEBUG
+   {
+      cout<<"minPt: "<<*m_minRecord<<endl;
+      cout<<"maxPt: "<<*m_maxRecord<<endl;
+   }
+}
+
+
+
+
+
diff --git a/ossim_plugins/pdal/ossimRialtoReader.h b/ossim_plugins/pdal/ossimRialtoReader.h
new file mode 100644
index 0000000..46a918c
--- /dev/null
+++ b/ossim_plugins/pdal/ossimRialtoReader.h
@@ -0,0 +1,58 @@
+//**************************************************************************************************
+//
+// OSSIM (http://trac.osgeo.org/ossim/)
+//
+// License: MIT
+//
+//**************************************************************************************************
+// $Id: ossimRialtoReader.h 23664 2015-12-14 14:17:27Z dburken $
+
+#ifndef ossimRialtoReader_HEADER
+#define ossimRialtoReader_HEADER 1
+
+#include "ossimPdalReader.h"
+#include "../ossimPluginConstants.h"
+#include <rialto/RialtoReader.hpp>
+#include <pdal/Options.hpp>
+
+class ossimPointRecord;
+#define USE_FULL_POINT_CLOUD_BUFFERING
+
+class OSSIM_PLUGINS_DLL ossimRialtoReader : public ossimPdalReader
+{
+public:
+   /** default constructor */
+   ossimRialtoReader();
+
+   /** virtual destructor */
+   virtual ~ossimRialtoReader();
+
+   /**
+    * Accepts filename of Rialto database file.  Returns TRUE if successful.
+    */
+   virtual bool open(const ossimFilename& fname);
+
+   /**
+    * Riaalto implementation does not support direct file reads, so this method is stubbed out with
+    * a warining message.
+    */
+   virtual void getFileBlock(ossim_uint32 offset, ossimPointBlock& block, ossim_uint32 np=0) const;
+
+   /**
+    * Fetches the block of points inside the block bounds. If the height components of the bounds
+    * are NaN, then only the horizontal bounds are considered. Thread-safe version accepts data
+    * block object from caller. The block object is cleared before points are pushed on the vector.
+    * The block size will be non-zero if points were found.
+    */
+   virtual void getBlock(const ossimGrect& bounds, ossimPointBlock& block) const;
+
+private:
+   virtual void establishMinMax();
+
+   virtual void establishAvailableFields() { establishMinMax(); }
+
+TYPE_DATA
+};
+
+#endif /* #ifndef ossimPdalTileDbReader_HEADER */
+
diff --git a/ossim_plugins/pdal/test/CMakeLists.txt b/ossim_plugins/pdal/test/CMakeLists.txt
new file mode 100644
index 0000000..36f4db4
--- /dev/null
+++ b/ossim_plugins/pdal/test/CMakeLists.txt
@@ -0,0 +1,39 @@
+message( "************** Begin: CMAKE SETUP FOR pdal-plugin-test ******************" )
+
+cmake_minimum_required (VERSION 2.8)
+
+project(ossimcore)
+
+set(requiredLibs)
+
+# Get the library suffix for lib or lib64.
+get_property(LIB64 GLOBAL PROPERTY FIND_LIBRARY_USE_LIB64_PATHS)       
+if(LIB64)
+   set(LIBSUFFIX 64)
+else()
+   set(LIBSUFFIX "")
+endif()
+
+# Add our include and library...
+include_directories("..")
+set(requiredLibs ${requiredLibs} ${PDAL_LIBRARIES} )
+set(requiredLibs ${requiredLibs} ossimpdal_plugin )
+
+message( STATUS "Required libs       = ${requiredLibs}" )
+
+# ---
+# pdal-plugin-test app:
+# ---
+
+# Add the executable:
+add_executable(ossim-pdal-plugin-test plugin-test.cpp )
+
+# Set the output dir:
+set_target_properties(ossim-pdal-plugin-test 
+                      PROPERTIES 
+                      RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin")
+
+# pdal-plugin-test application links with required libs.
+target_link_libraries( ossim-pdal-plugin-test ${requiredLibs} )
+
+message( "************** End: CMAKE SETUP FOR pdal-plugin-test ******************" )
diff --git a/ossim_plugins/pdal/test/README.txt b/ossim_plugins/pdal/test/README.txt
new file mode 100644
index 0000000..dbdb3d4
--- /dev/null
+++ b/ossim_plugins/pdal/test/README.txt
@@ -0,0 +1,39 @@
+PDAL Plugin Tests
+-----------------
+A single executable provides testing for both the ossimPdalFileReader and ossimRialtoReader classes. After building, the executable is available in $OSSIM_BUILD_DIR/bin/ossim-pdal-plugin-test. The executable should be run out of this test directory if the default autzen data is to be used.
+
+The default test data is autzen.las, a small point cloud of ~10,000 points. Alternatively, a filename can be provided on the command line to use a different dataset.
+
+PDAL LAS File Generator
+-----------------------
+This is not really a test, as it does not make use of any OSSIM class of consequence. It is used to generate a sample ramp point cloud LAS file with 11 points. The output is the file "ramp.las" which can serve as input to the PDAL test below.
+
+
+PDAL File Reader Test
+--------------------
+To run the ossimPdalFileReader test, do:
+
+    ossim-pdal-plugin-test pdal [<alt_input.las>]
+
+The output will be the raster file "pdal-OUTPUT.tif". This file can be compared against the expected result found in pdal-EXPECTED.ti. If the optional LAS file is specified, it is used in place of the default autzen.las.
+
+
+RIALTO_TRANSLATE and RIALTO_INFO
+---------------------------------
+This is not a test, but a step that must be run before the rialto test can be executed. This utility generates a rialto geopackage file repesenting the input filename specified:
+
+    rialto_translate -m 0 -v -i <myfile>.las -o <myfile>.gpkg
+
+It will generate a geopackage by the name <myfile>.gpkg, which can be used as input to the rialto test. 
+
+
+Rialto Reader Test
+-------------------
+To run the ossimRialtoReader test, do:
+
+    ossim-pdal-plugin-test rialto [<alt_input.las>]
+
+The output will be the raster file "rialto-OUTPUT.tif". Compare against rialto-EXPECTED.tif. An alternate gpkg file can be specified for generating corresponding TIF image.
+
+
+
diff --git a/ossim_plugins/pdal/test/autzen.las b/ossim_plugins/pdal/test/autzen.las
new file mode 100644
index 0000000..292e404
Binary files /dev/null and b/ossim_plugins/pdal/test/autzen.las differ
diff --git a/ossim_plugins/pdal/test/autzen.xml b/ossim_plugins/pdal/test/autzen.xml
new file mode 100644
index 0000000..46c3609
--- /dev/null
+++ b/ossim_plugins/pdal/test/autzen.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0"?>
+<Pipeline version="1.0">
+    <Reader type="drivers.las.reader">
+        <Option name="filename">
+            ./autzen.las
+        </Option>
+    </Reader>
+</Pipeline>
diff --git a/ossim_plugins/pdal/test/pdal-EXPECTED.tif b/ossim_plugins/pdal/test/pdal-EXPECTED.tif
new file mode 100644
index 0000000..b130816
Binary files /dev/null and b/ossim_plugins/pdal/test/pdal-EXPECTED.tif differ
diff --git a/ossim_plugins/pdal/test/plugin-test.cpp b/ossim_plugins/pdal/test/plugin-test.cpp
new file mode 100644
index 0000000..655e962
--- /dev/null
+++ b/ossim_plugins/pdal/test/plugin-test.cpp
@@ -0,0 +1,170 @@
+//**************************************************************************************************
+//
+// OSSIM (http://trac.osgeo.org/ossim/)
+//
+// License: MIT
+//
+//**************************************************************************************************
+// $Id: plugin-test.cpp 23664 2015-12-14 14:17:27Z dburken $
+#include "../ossimPdalFileReader.h"
+#include "../ossimRialtoReader.h"
+#include <ossim/init/ossimInit.h>
+#include <ossim/base/ossimStringProperty.h>
+#include <ossim/base/ossimKeywordNames.h>
+#include <assert.h>
+#include <ossim/point_cloud/ossimPointCloudImageHandler.h>
+#include <ossim/imaging/ossimTiffWriter.h>
+#include <pdal/pdal.hpp>
+#include <pdal/util/Bounds.hpp>
+#include <pdal/LasWriter.hpp>
+#include <pdal/FauxReader.hpp>
+
+#define TEST_READER false
+
+using namespace pdal;
+
+int usage(char* app_name)
+{
+   cout << "\nUsage: "<<app_name<<" <pdal|rialto|genlas> [filename]\n" << endl;
+   return 1;
+}
+
+bool writeRaster(ossimPdalReader* reader, const char* test)
+{
+   ossimRefPtr<ossimPointCloudImageHandler> ih =  new ossimPointCloudImageHandler;
+   ih->setCurrentEntry((ossim_uint32)ossimPointCloudImageHandler::HIGHEST);
+   ih->setPointCloudHandler(reader);
+
+   ossimDpt gsd;
+   ih->getGSD(gsd, 0);
+   ossimString gsdstr = ossimString::toString((gsd.x + gsd.y)/6.0);
+   ossimRefPtr<ossimProperty> gsd_prop =
+         new ossimStringProperty(ossimKeywordNames::METERS_PER_PIXEL_KW, gsdstr);
+   ih->setProperty(gsd_prop);
+
+   // Set up the writer:
+   ossimRefPtr<ossimTiffWriter> tif_writer =  new ossimTiffWriter();
+   tif_writer->setGeotiffFlag(true);
+
+   ossimFilename outfile (test);
+   outfile += "-OUTPUT.tif";
+   tif_writer->setFilename(outfile);
+   if (tif_writer.valid())
+   {
+      tif_writer->connectMyInputTo(0, ih.get());
+      tif_writer->execute();
+   }
+
+   cout << "Output written to <"<<outfile<<">"<<endl;
+   return true;
+}
+
+
+bool test_rialto(const ossimFilename& fname)
+{
+   cout << "Testing rialto with <"<<fname<<">"<<endl;
+
+   ossimRefPtr<ossimRialtoReader> reader = new ossimRialtoReader;
+   reader->open(fname);
+
+   ossimGrect bounds;
+   reader->getBounds(bounds);
+   cout <<"bounds = "<<bounds<<endl;
+
+   ossimPointBlock pointBlock;
+   reader->getBlock(bounds, pointBlock);
+
+   writeRaster(reader.get(), "rialto");
+
+   return true;
+}
+
+
+bool test_pdal(const ossimFilename& fname)
+{
+   cout << "Testing pdal with <"<<fname<<">"<<endl;
+
+   ossimRefPtr<ossimPdalFileReader> reader = new ossimPdalFileReader;
+   reader->open(fname);
+
+   ossimGrect bounds;
+   reader->getBounds(bounds);
+   cout <<"bounds = "<<bounds<<endl;
+
+   writeRaster(reader.get(), "pdal");
+
+   return 0;
+}
+
+bool genlas(const ossimFilename& fname)
+{
+   cout << "Generating file <"<<fname<<">"<<endl;
+
+   FauxReader reader;
+   Options roptions;
+   BOX3D bbox(-0.001, -0.001, -100.0, 0.001, 0.001, 100.0);
+   roptions.add("bounds", bbox);
+   roptions.add("num_points", 11);
+   roptions.add("mode", "ramp");
+   reader.setOptions(roptions);
+
+   LasWriter writer;
+   Options woptions;
+   woptions.add("filename", fname.string());
+   woptions.add("a_srs", "EPSG:4326"); // causes core dump when ossimInit::initialize() called on startup
+   woptions.add("scale_x", 0.0000001);
+   woptions.add("scale_y", 0.0000001);
+   writer.setOptions(woptions);
+   writer.setInput(reader);
+
+   PointTable wtable;
+   writer.prepare(wtable);
+   writer.execute(wtable);
+
+   return true;
+}
+
+int main(int argc, char** argv)
+{
+   // TODO: Figure out why program core-dumps on exit when this line is included and genlas test is
+   // run. Determined problem to be in GDAL's OGRSpatialReference::SetFromUserInput() called from
+   // PDAL's SpatialReference::setFromUserInput() called when EPSG option is set:
+   //ossimInit::instance()->initialize(argc, argv);
+
+   if (argc == 1)
+      return usage(argv[0]);
+
+   ossimFilename fname;
+   if (argc > 2)
+      fname = argv[2];
+
+   ossimString test_name (argv[1]);
+   bool passed = false;
+   if (test_name.downcase() == "rialto")
+   {
+      if (fname.empty())
+         fname = "autzen.gpkg";
+      passed = test_rialto(fname);
+   }
+   else if (test_name.downcase() == "pdal")
+   {
+      if (fname.empty())
+         fname = "autzen.las";
+      passed = test_pdal(fname);
+   }
+   else if (test_name.downcase() == "genlas")
+   {
+      if (fname.empty())
+         fname = "ramp.las";
+      passed = genlas(fname);
+   }
+   else
+      return usage(argv[0]);
+
+   if (passed)
+      return 0;
+   return 1;
+}
+
+
+
diff --git a/ossim_plugins/pdal/test/rialto-EXPECTED.tif b/ossim_plugins/pdal/test/rialto-EXPECTED.tif
new file mode 100644
index 0000000..d574046
Binary files /dev/null and b/ossim_plugins/pdal/test/rialto-EXPECTED.tif differ
diff --git a/ossim_plugins/png/CMakeLists.txt b/ossim_plugins/png/CMakeLists.txt
new file mode 100644
index 0000000..ef24c3d
--- /dev/null
+++ b/ossim_plugins/png/CMakeLists.txt
@@ -0,0 +1,61 @@
+set(LIB_NAME ossimpng_plugin)
+MESSAGE( "************** LIBRARY SETUP FOR ossimpng_plugin******************")
+
+# Include ossim cmake stuff:
+include(OssimVersion)
+include(OssimCommonVariables)
+include(OssimUtilities)
+
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
+
+SET(requiredLibs)
+
+find_package(PNG)
+IF(PNG_FOUND)
+   INCLUDE_DIRECTORIES( ${PNG_INCLUDE_DIR} )
+   SET(requiredLibs ${requiredLibs} ${PNG_LIBRARIES} )
+ELSE(PNG_FOUND)
+   MESSAGE(FATAL_ERROR "Could not find png")
+ENDIF(PNG_FOUND)
+
+MESSAGE( STATUS "PNG_INCLUDE_DIR = ${PNG_INCLUDE_DIR}")
+MESSAGE( STATUS "PNG_LIBRARIES   = ${PNG_LIBRARIES}")
+
+find_package(ZLIB)
+IF(ZLIB_FOUND)
+   INCLUDE_DIRECTORIES( ${ZLIB_INCLUDE_DIR} )
+   SET(requiredLibs ${requiredLibs} ${ZLIB_LIBRARIES} )
+ELSE(ZLIB_FOUND)
+   MESSAGE(FATAL_ERROR "Could not find zlib")
+ENDIF(ZLIB_FOUND)
+
+find_package(TIFF)
+IF(TIFF_FOUND)
+   INCLUDE_DIRECTORIES( ${TIFF_INCLUDE_DIR} )
+   SET(requiredLibs ${requiredLibs} ${TIFF_LIBRARIES} )
+ELSE(TIFF_FOUND)
+   MESSAGE(FATAL_ERROR "Could not find tiff")
+ENDIF(TIFF_FOUND)
+
+FILE(GLOB_RECURSE OSSIMPLUGIN_SRCS *.cpp)
+FILE(GLOB_RECURSE OSSIMPLUGIN_HEADERS *.h)
+
+####
+# OSSIMPLUGINSMAKINGDLL controls dll linkage on windows.  
+# Adding this sets OSSIM_PLUGINS_DLL #define TO "__declspec(dllexport)".
+###
+add_definitions("-DOSSIMPLUGINSMAKINGDLL")
+
+# Adjust the install library path:
+if(OSSIM_INSTALL_PLUGINS_WITH_VERSION)
+   set(INSTALL_LIBRARY_DIR   "${INSTALL_LIBRARY_DIR}/ossim-${OSSIM_VERSION}/plugins")
+else(OSSIM_INSTALL_PLUGINS_WITH_VERSION)
+   set(INSTALL_LIBRARY_DIR   "${INSTALL_LIBRARY_DIR}/ossim/plugins")
+endif(OSSIM_INSTALL_PLUGINS_WITH_VERSION)
+
+OSSIM_LINK_LIBRARY(${LIB_NAME}
+                   COMPONENT_NAME ossim TYPE "${OSSIM_PLUGIN_LINK_TYPE}"
+		   LIBRARIES ${OSSIM_LIBRARY} ${requiredLibs}
+                   HEADERS "${OSSIMPLUGIN_HEADERS}"
+		   SOURCE_FILES "${OSSIMPLUGIN_SRCS}"
+                   INSTALL_LIB)
diff --git a/ossim_plugins/png/makefile.vc b/ossim_plugins/png/makefile.vc
new file mode 100644
index 0000000..fc66bea
--- /dev/null
+++ b/ossim_plugins/png/makefile.vc
@@ -0,0 +1,59 @@
+###
+# $Id: makefile.vc 12864 2008-05-15 13:13:28Z dburken $
+#
+# Windows nmake make file.  This code should compile with the Microsoft .NET
+# compiler.
+# 
+# Currently for a typical build on windows you would do the following.
+# - cd back to the ossim top and edit its nmake.opt file appropriately.
+# - nmake /f makefile
+#
+# NOTE:  If you make shared apps it's handy to copy the ossim.dll to the bin
+#        directory. 
+###
+
+!INCLUDE ..\nmake.opt
+PLUGIN_ROOT = ossim_png_plugin
+
+###
+# Note: EMBED_MANIFEST variable is set in nmake.opt so make sure it is included
+# before this test.
+###
+!if "$(EMBED_MANIFEST)" == "1"
+!include ..\makefile.inc
+OSSIM_VC_MANIFEST_EMBED_DLL=$(_VC_MANIFEST_EMBED_DLL)
+OSSIM_VC_MANIFEST_CLEAN=$(_VC_MANIFEST_CLEAN)
+!else
+OSSIM_VC_MANIFEST_EMBED_DLL=
+OSSIM_VC_MANIFEST_CLEAN=
+!endif
+
+###
+# PNG includes and libs.
+# WINDOWS : use IntelCompiler7 prebuilt binaries (issues with Visual Studio)
+###
+INC	=	-I.. -I. $(INC) $(PNG_INC)
+LINK	=	link
+
+OBJ = \
+ossimPngPluginInit.obj \
+ossimPngReader.obj \
+ossimPngReaderFactory.obj \
+ossimPngWriter.obj \
+ossimPngWriterFactory.obj
+
+default:	$(OBJ)
+	link /NOLOGO /SUBSYSTEM:WINDOWS /VERSION:$(VERSION_STRING) /DLL /OUT:"$(PLUGIN_ROOT).dll" /IMPLIB:"$(PLUGIN_ROOT).lib" $(OBJ) $(OSSIM_HOME)\lib\ossim.lib $(PNG_LIB) $(ZLIB_LIB)
+	$(OSSIM_VC_MANIFEST_EMBED_DLL)
+
+install:
+	$(CP) $(PLUGIN_ROOT).dll $(INSTALL_DIR)
+
+clean:
+	$(RM) *.obj
+	$(RM) $(OSSIM_PLUGIN_LIB_PATH)\$(PLUGIN_ROOT).*
+	$(OSSIM_VC_MANIFEST_CLEAN)
+
+!if "$(EMBED_MANIFEST)" == "1"
+!include ..\makefile.targ.inc
+!endif
diff --git a/ossim_plugins/png/ossimPngCodec.cpp b/ossim_plugins/png/ossimPngCodec.cpp
new file mode 100644
index 0000000..1c84f2f
--- /dev/null
+++ b/ossim_plugins/png/ossimPngCodec.cpp
@@ -0,0 +1,500 @@
+#include "ossimPngCodec.h"
+#include <ossim/base/ossimConstants.h>
+#include <png.h>
+#include <stdlib.h>
+
+static const char ADD_ALPHA_CHANNEL_KW[] = "add_alpha_channel";
+
+RTTI_DEF1(ossimPngCodec, "ossimPngCodec", ossimCodecBase);
+
+
+static void user_read_data (png_structp png_ptr, png_bytep data, png_size_t length)
+{
+   ossim_uint8** input_pointer = reinterpret_cast<ossim_uint8**>(png_get_io_ptr (png_ptr));
+
+   memcpy (data, *input_pointer, sizeof (ossim_uint8) * length);
+   (*input_pointer) += length;
+}
+
+static void PngWriteCallback(png_structp  png_ptr, png_bytep data, png_size_t length) 
+{
+   std::vector<ossim_uint8> *p = (std::vector<ossim_uint8>*)png_get_io_ptr(png_ptr);
+   p->insert(p->end(), data, data + length);
+}
+ 
+struct TPngDestructor {
+   png_struct *p;
+   TPngDestructor(png_struct *p) : p(p)  {}
+   ~TPngDestructor() { if (p) {  png_destroy_write_struct(&p, NULL); } }
+};
+
+ossimPngCodec::ossimPngCodec(bool addAlpha)
+   :m_addAlphaChannel(addAlpha)
+{
+
+}
+
+ossimString ossimPngCodec::getCodecType()const
+{
+   return "png";
+}
+
+bool ossimPngCodec::encode(const ossimRefPtr<ossimImageData>& in,
+                           std::vector<ossim_uint8>& out ) const
+{
+   out.clear();
+   ossim_int32 colorType = -1;
+   ossim_int32 bitDepth = 0;
+   if(!in->getBuf()) return false;
+   if(in->getNumberOfBands() == 1)
+   {
+      if(m_addAlphaChannel)
+      {
+         colorType = PNG_COLOR_TYPE_GRAY_ALPHA;
+      }
+      else
+      {
+         colorType = PNG_COLOR_TYPE_GRAY;
+      }
+   }
+   else if(in->getNumberOfBands() == 3)
+   {
+      if(m_addAlphaChannel)
+      {
+         colorType = PNG_COLOR_TYPE_RGB_ALPHA;
+      }
+      else
+      {
+         colorType = PNG_COLOR_TYPE_RGB;
+      }
+   }
+   if(colorType < 0) return false;
+
+   switch(in->getScalarType())
+   {
+      case OSSIM_UINT8:
+      {
+         bitDepth = 8;
+         break;
+      }
+      case OSSIM_USHORT11:
+      case OSSIM_UINT16:
+      {
+         bitDepth = 16;
+         break;
+      }
+      default:
+      {
+         bitDepth = 0;
+      }
+   }
+   if(bitDepth == 0) return false;
+   // std::cout << "bitDepth = " << bitDepth << ", BANDS = " << in->getNumberOfBands() << std::endl;
+   ossim_int32 w = in->getWidth();
+   ossim_int32 h = in->getHeight();
+   png_structp p = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+   TPngDestructor destroyPng(p);
+   png_infop info_ptr = png_create_info_struct(p);
+   setjmp(png_jmpbuf(p));
+
+   png_set_IHDR(p, info_ptr, w, h, bitDepth,
+                colorType,
+                PNG_INTERLACE_NONE,
+                PNG_COMPRESSION_TYPE_DEFAULT,
+                PNG_FILTER_TYPE_DEFAULT);
+   png_set_compression_level(p, 1);
+
+   switch(colorType)
+   {
+      case PNG_COLOR_TYPE_GRAY:
+      {
+         if(bitDepth == 8)
+         {
+            ossim_uint8* buf = (ossim_uint8*)in->getBuf();
+            std::vector<ossim_uint8*> rows(h);
+            for(ossim_int32 y=0; y<h;++y)
+            {
+               rows[y] = (ossim_uint8*)(buf + y * w) ;    		
+            }
+            png_set_rows(p, info_ptr, &rows[0]);
+            png_set_write_fn(p, &out, PngWriteCallback, NULL);
+            png_write_png(p, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);
+         }
+         else if(bitDepth == 16)
+         {
+            ossim_uint16* buf = (ossim_uint16*)in->getBuf();
+            std::vector<ossim_uint8*> rows(h);
+            for(int y=0; y<h;++y)
+            {
+               rows[y] = (ossim_uint8*)(buf + y * w) ;    		
+            }
+            png_set_rows(p, info_ptr, &rows[0]);
+            png_set_write_fn(p, &out, PngWriteCallback, NULL);
+            png_write_png(p, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);
+         }
+         break;
+      }
+      case PNG_COLOR_TYPE_GRAY_ALPHA:
+      {
+         if(bitDepth == 8)
+         {
+            std::vector<ossim_uint8> buf(w*h*2);
+            std::vector<ossim_uint8*> rows(h);
+            ossim_uint8* bufPtr = &buf.front();
+            in->unloadTileToBipAlpha(&buf.front(), in->getImageRectangle(), in->getImageRectangle());
+            for(int y=0; y<h;++y)
+            {
+               rows[y] = (ossim_uint8*)(bufPtr + y * (w*2)) ;    		
+            }
+            png_set_rows(p, info_ptr, &rows[0]);
+            png_set_write_fn(p, &out, PngWriteCallback, NULL);
+            png_write_png(p, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);
+
+         }
+         else
+         {
+            std::vector<ossim_uint16> buf(w*h*2);
+            std::vector<ossim_uint8*> rows(h);
+            ossim_uint16* bufPtr = &buf.front();
+            in->unloadTileToBipAlpha(&buf.front(), in->getImageRectangle(), in->getImageRectangle());
+            for(ossim_int32 y=0; y<h;++y)
+            {
+               rows[y] = (ossim_uint8*)(bufPtr + y * (w*2)) ;    		
+            }
+            png_set_rows(p, info_ptr, &rows[0]);
+            png_set_write_fn(p, &out, PngWriteCallback, NULL);
+            png_write_png(p, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);
+         }
+
+         break;
+      }
+      case PNG_COLOR_TYPE_RGB:
+      {
+         if(bitDepth == 8)
+         {
+            std::vector<ossim_uint8> buf(w*h*3);
+            std::vector<ossim_uint8*> rows(h);
+            in->unloadTile(&buf.front(), in->getImageRectangle(), in->getImageRectangle(), OSSIM_BIP);
+            ossim_uint8* bufPtr = &buf.front();
+            for(ossim_int32 y=0; y<h;++y)
+            {
+               rows[y] = (ossim_uint8*)(bufPtr + y * (w*3)) ;    		
+            }
+            png_set_rows(p, info_ptr, &rows[0]);
+            png_set_write_fn(p, &out, PngWriteCallback, NULL);
+            png_write_png(p, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);
+         }
+         else
+         {
+            std::vector<ossim_uint16> buf(w*h*3);
+            std::vector<ossim_uint8*> rows(h);
+            ossim_uint16* bufPtr = &buf.front();
+            in->unloadTile(&buf.front(), in->getImageRectangle(), in->getImageRectangle(),OSSIM_BIP);
+            for(ossim_int32 y=0; y<h;++y)
+            {
+               rows[y] = (ossim_uint8*)(bufPtr + y * (w*3)) ;    		
+            }
+            png_set_rows(p, info_ptr, &rows[0]);
+            png_set_write_fn(p, &out, PngWriteCallback, NULL);
+            png_write_png(p, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);
+         }
+         break;
+      }
+      case PNG_COLOR_TYPE_RGB_ALPHA:
+      {
+         if(bitDepth == 8)
+         {
+            std::vector<ossim_uint8> buf(w*h*4);
+            std::vector<ossim_uint8*> rows(h);
+            in->unloadTileToBipAlpha(&buf.front(), in->getImageRectangle(), in->getImageRectangle());
+            ossim_uint8* bufPtr = &buf.front();
+            for(int y=0; y<h;++y)
+            {
+               rows[y] = (ossim_uint8*)(bufPtr + y * (w*4)) ;    		
+            }
+            png_set_rows(p, info_ptr, &rows[0]);
+            png_set_write_fn(p, &out, PngWriteCallback, NULL);
+            png_write_png(p, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);
+         }
+         else
+         {
+            std::vector<ossim_uint16> buf(w*h*4);
+            std::vector<ossim_uint8*> rows(h);
+            in->unloadTileToBipAlpha(&buf.front(), in->getImageRectangle(), in->getImageRectangle());
+            ossim_uint16* bufPtr = &buf.front();
+            for(ossim_int32 y=0; y<h;++y)
+            {
+               rows[y] = (ossim_uint8*)(bufPtr + y * (w*4)) ;    		
+            }
+            png_set_rows(p, info_ptr, &rows[0]);
+            png_set_write_fn(p, &out, PngWriteCallback, NULL);
+            png_write_png(p, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);
+         }
+         break;
+      }
+   }
+
+   return true;
+}
+
+bool ossimPngCodec::decode(const std::vector<ossim_uint8>& in,
+                           ossimRefPtr<ossimImageData>& out ) const
+{
+   bool result = true;
+   ossim_uint32 y = 0;
+   png_structp  pngPtr = 0;
+   png_infop    infoPtr = 0;
+   png_uint_32 pngWidth = 0;
+   png_uint_32 pngHeight = 0;
+   ossim_int32  pngBitDepth=0, pngByteDepth = 0, pngColorType=0, pngInterlaceType=0;
+
+   // png_bytep* row_pointers=0;
+
+   if (in.empty())
+   {
+      return false;
+   }
+
+   pngPtr = png_create_read_struct (PNG_LIBPNG_VER_STRING, 0, 0, 0);
+   //assert (png_ptr && "creating png_create_write_structpng_create_write_struct failed");
+
+   // Initialize info structure
+   infoPtr = png_create_info_struct (pngPtr);
+
+   // Setup Exception handling
+   setjmp (png_jmpbuf(pngPtr));
+
+   const ossim_uint8* inputPointer = &in.front();//&pngData_arg[0];
+   png_set_read_fn (pngPtr, reinterpret_cast<void*> (&inputPointer), user_read_data);
+
+   png_read_info (pngPtr, infoPtr);
+
+   png_get_IHDR (pngPtr, infoPtr, &pngWidth, &pngHeight, &pngBitDepth,
+                 &pngColorType, &pngInterlaceType, NULL, NULL);
+
+
+
+   // ensure a color bit depth of 8
+   //assert(png_bit_depth==sizeof(T)*8);
+
+   ossim_uint32 pngChannels = 0;
+   switch (pngColorType)
+   {
+      case PNG_COLOR_TYPE_GRAY:
+      {
+         pngChannels = 1;
+         break;
+      }
+      case PNG_COLOR_TYPE_GRAY_ALPHA:
+      {
+         pngChannels = 2;
+         break;	  	
+      }
+      case PNG_COLOR_TYPE_RGB:
+      {
+         pngChannels = 3;
+         break;	  	
+      }
+      case PNG_COLOR_TYPE_RGB_ALPHA:
+      {
+         pngChannels = 4;
+         break;	  	
+      }
+      default:
+      {
+         pngChannels = 0;
+         break;	  	
+      }
+   }
+   pngByteDepth = pngBitDepth>>3;
+   //imageData_arg.clear ();
+   //imageData_arg.resize (png_height * png_width * png_channels);
+
+   ossim_uint32 bytes = pngHeight*pngWidth*pngChannels*pngByteDepth;
+   //row_pointers = reinterpret_cast<png_bytep*> (malloc (sizeof(png_bytep) * png_height));
+   std::vector<ossim_uint8> data(bytes);
+   std::vector<ossim_uint8*> rowPointers(pngHeight);
+   ossim_uint8* dataPtr = &data.front();
+   for (y = 0; y < pngHeight; y++)
+   {
+      rowPointers[y] = reinterpret_cast<ossim_uint8*> (dataPtr + ( y*(pngWidth*pngByteDepth*pngChannels)));
+   }
+
+   png_read_image (pngPtr, &rowPointers.front());
+
+   ossimScalarType scalarType = ((pngByteDepth==1)?OSSIM_UINT8:OSSIM_UINT16);
+   ossim_uint32 bands = pngChannels;
+
+   if((bands == 2) ||(bands==4))
+   {
+      bands = bands - 1;
+   }
+   // now allocate the ossimImageData object if not already allocated
+   if(!out.valid())
+   {
+      out = new ossimImageData(0, scalarType, bands, pngWidth, pngHeight);
+      out->initialize();
+   }
+   else
+   {
+      out->setNumberOfDataComponents(bands);
+      out->setImageRectangleAndBands(ossimIrect(0,0,pngWidth-1,pngHeight-1), bands);
+      out->initialize();
+   }
+
+   if(pngChannels == 1)
+   {
+      // ossim_uint32 idx = 0;
+      memcpy(out->getBuf(0), dataPtr, bytes);
+      out->validate();
+      // once we support alpha channel properly we will need to add alpha settings here
+
+   }
+   else if(pngChannels == 2)
+   {
+      //std::cout << "DECODING 2 channels\n";
+      ossim_uint32 size = pngWidth*pngHeight;
+      ossim_uint32 idx = 0;
+      if(scalarType == OSSIM_UINT16)
+      {
+         ossim_uint16* tempDataPtr = reinterpret_cast<ossim_uint16*> (dataPtr);
+         ossim_uint16* buf = static_cast<ossim_uint16*>(out->getBuf(0));
+
+         for(idx = 0; idx < size;++idx)
+         {
+            *buf = tempDataPtr[0];
+
+            tempDataPtr+=2;++buf;
+         }
+         out->validate();
+      }
+      else if(scalarType == OSSIM_UINT8)
+      {
+         ossim_uint8* tempDataPtr = dataPtr;
+         ossim_uint8* buf = static_cast<ossim_uint8*>(out->getBuf(0));
+
+         for(idx = 0; idx < size;++idx)
+         {
+            *buf = *tempDataPtr;
+
+            tempDataPtr+=2;++buf;
+         }
+         out->validate();
+      }
+      else
+      {
+         result = false;
+      }
+   }
+   else if(pngChannels == 4)
+   {
+      //std::cout << "DECODING 4 channels\n";
+      ossim_uint32 size = pngWidth*pngHeight;
+      ossim_uint32 idx = 0;
+      if(scalarType == OSSIM_UINT16)
+      {
+         ossim_uint16* tempDataPtr = reinterpret_cast<ossim_uint16*> (dataPtr);
+         ossim_uint16* buf1 = static_cast<ossim_uint16*>(out->getBuf(0));
+         ossim_uint16* buf2 = static_cast<ossim_uint16*>(out->getBuf(1));
+         ossim_uint16* buf3 = static_cast<ossim_uint16*>(out->getBuf(2));
+
+         for(idx = 0; idx < size;++idx)
+         {
+            *buf1 = tempDataPtr[0];
+            *buf2 = tempDataPtr[1];
+            *buf3 = tempDataPtr[2];
+
+            tempDataPtr+=4;++buf1;++buf2;++buf3;
+         }
+         out->validate();
+      }
+      else if(scalarType == OSSIM_UINT8)
+      {
+         ossim_uint8* tempDataPtr = dataPtr;
+         ossim_uint8* buf1 = static_cast<ossim_uint8*>(out->getBuf(0));
+         ossim_uint8* buf2 = static_cast<ossim_uint8*>(out->getBuf(1));
+         ossim_uint8* buf3 = static_cast<ossim_uint8*>(out->getBuf(2));
+
+         for(idx = 0; idx < size;++idx)
+         {
+            *buf1 = tempDataPtr[0];
+            *buf2 = tempDataPtr[1];
+            *buf3 = tempDataPtr[2];
+
+            tempDataPtr+=4;++buf1;++buf2;++buf3;
+         }
+         out->validate();
+      }
+      else
+      {
+         result = false;
+      }
+   }
+   else
+   {
+      out->loadTile(dataPtr, out->getImageRectangle(), OSSIM_BIP);
+   }
+
+   if (infoPtr)
+   {
+      png_free_data (pngPtr, infoPtr, PNG_FREE_ALL, -1);
+   }
+   if (pngPtr)
+   {
+      png_destroy_read_struct (&pngPtr, 0, 0);
+   }
+
+   return result;
+}
+
+void ossimPngCodec::setProperty(ossimRefPtr<ossimProperty> property)
+{
+   if(property->getName() == ADD_ALPHA_CHANNEL_KW)
+   {
+      m_addAlphaChannel = property->valueToString().toBool();
+   }
+   else
+   {
+      ossimCodecBase::setProperty(property);
+   }
+}
+
+ossimRefPtr<ossimProperty> ossimPngCodec::getProperty(const ossimString& name)const
+{
+   ossimRefPtr<ossimProperty> result;
+
+   if(name == ADD_ALPHA_CHANNEL_KW)
+   {
+
+   }
+   else
+   {
+      result = ossimCodecBase::getProperty(name);
+   }
+
+   return result;
+}
+
+void ossimPngCodec::getPropertyNames(std::vector<ossimString>& propertyNames)const
+{
+   propertyNames.push_back(ADD_ALPHA_CHANNEL_KW);
+}
+
+bool ossimPngCodec::loadState(const ossimKeywordlist& kwl, const char* prefix)
+{
+   ossimString addAlphaChannel = kwl.find(prefix, ADD_ALPHA_CHANNEL_KW);
+
+   if(!addAlphaChannel.empty())
+   {
+      m_addAlphaChannel = addAlphaChannel.toBool();
+   }
+
+   return ossimCodecBase::loadState(kwl, prefix);
+}
+
+bool ossimPngCodec::saveState(ossimKeywordlist& kwl, const char* prefix)const
+{
+   kwl.add(prefix, ADD_ALPHA_CHANNEL_KW, m_addAlphaChannel);
+
+   return ossimCodecBase::saveState(kwl, prefix);
+}
diff --git a/ossim_plugins/png/ossimPngCodec.h b/ossim_plugins/png/ossimPngCodec.h
new file mode 100644
index 0000000..bb89ab3
--- /dev/null
+++ b/ossim_plugins/png/ossimPngCodec.h
@@ -0,0 +1,93 @@
+#ifndef ossimPngCodec_HEADER
+#define ossimPngCodec_HEADER
+#include <ossim/imaging/ossimCodecBase.h>
+
+class ossimPngCodec : public ossimCodecBase
+{
+public:
+	ossimPngCodec(bool addAlpha=false);
+
+	virtual ossimString getCodecType()const;
+   /**
+    * @brief Encode png method.
+    *
+    * Current options handled by this factory:
+    *
+    * type: png
+    *
+    * @param in Input data to encode.
+    * 
+    * @param out Encoded output data.
+    *
+    * @return true on success, false on failure.
+    */   
+   virtual bool encode( const ossimRefPtr<ossimImageData>& in,
+                        std::vector<ossim_uint8>& out ) const;
+
+   /**
+    * @brief Decode png method.
+    *
+    * @param in Input data to decode.
+    * 
+    * @param out Output tile.  If the pointer to ossimImageData is null
+    * internally it will be created.  For code loops it is better to pre
+    * initialized to correct size.
+    *
+    * @note Caller should set "out's" image rectangle upon successful
+    * decode.
+    *
+    * @return true on success, false on failure.
+    */
+   virtual bool decode( const std::vector<ossim_uint8>& in,
+                        ossimRefPtr<ossimImageData>& out ) const;
+
+   /**
+   * Ineterface to allow for specific properties to be set.
+   *
+   */ 
+   virtual void setProperty(ossimRefPtr<ossimProperty> property);
+   
+   /**
+   * Interface to get the value of a specific property
+   *
+   * @param in name.  Property name to retrieve
+   *
+   * @return property value
+   */
+   virtual ossimRefPtr<ossimProperty> getProperty(const ossimString& name)const; 
+   
+   /**
+   * Get a list of all supported property names.  Currently only "quality" property 
+   * is exposed
+   *
+   * @param out proeprtyNames.  push the list of proeprty names to the list
+   */
+   virtual void getPropertyNames(std::vector<ossimString>& propertyNames)const;
+
+   /**
+   * Allocate the state of the object thorugh a factory load/keywordlist
+   *
+   * @param in kwl. Input keywordlist that holds the values.
+   *
+   * @param in prefix. prefix to use for all keywords.
+   */
+   virtual bool loadState(const ossimKeywordlist& kwl, const char* prefix=0);
+
+   /**
+   * Save the state of the codec to the keywordlist
+   *
+   * @param out kwl. Input keywordlist that holds the values.
+   *
+   * @param in prefix. prefix to use for all keywords.
+   */
+   virtual bool saveState(ossimKeywordlist& kwl, const char* prefix=0)const;
+
+
+protected:
+	bool m_addAlphaChannel;
+
+
+TYPE_DATA;
+};
+
+#endif
diff --git a/ossim_plugins/png/ossimPngCodecFactory.cpp b/ossim_plugins/png/ossimPngCodecFactory.cpp
new file mode 100644
index 0000000..1537b2b
--- /dev/null
+++ b/ossim_plugins/png/ossimPngCodecFactory.cpp
@@ -0,0 +1,94 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author:  David Burken
+//
+// Description:  Factory class definition for codec(encoder/decoder).
+// 
+//----------------------------------------------------------------------------
+// $Id$
+
+#include "ossimPngCodecFactory.h"
+#include <ossim/base/ossimKeywordlist.h>
+#include <ossim/base/ossimKeywordNames.h>
+#include <ossim/base/ossimRefPtr.h>
+#include <ossim/base/ossimString.h>
+#include <ossim/imaging/ossimImageData.h>
+
+#include "ossimPngCodec.h"
+
+#include <string>
+
+ossimPngCodecFactory* ossimPngCodecFactory::m_instance = 0;
+
+static const std::string TYPE_KW    = "type";
+
+ossimPngCodecFactory::~ossimPngCodecFactory()
+{}
+
+ossimPngCodecFactory* ossimPngCodecFactory::instance()
+{
+   if ( !m_instance )
+   {
+      m_instance = new ossimPngCodecFactory();
+   }
+   return m_instance;
+}
+ossimCodecBase* ossimPngCodecFactory::createCodec(const ossimString& type)const
+{
+   ossimRefPtr<ossimPngCodec> result;
+   ossimString tempType = type.downcase();
+   if(tempType == "png") 
+   {
+      result = new ossimPngCodec();
+   }
+   else if(tempType == "pnga")
+   {
+      result = new ossimPngCodec(true);
+   }
+   else if(tempType == STATIC_TYPE_NAME(ossimPngCodec))
+   {
+      result = new ossimPngCodec();
+   }
+
+   return result.release();
+}
+
+ossimCodecBase* ossimPngCodecFactory::createCodec(const ossimKeywordlist& kwl, const char* prefix)const
+{
+   ossimString type = kwl.find(prefix, ossimKeywordNames::TYPE_KW);
+   ossimCodecBase* result = 0;
+   if(!type.empty())
+   {
+      result = this->createCodec(type);
+      if(result)
+      {
+         result->loadState(kwl, prefix);
+      }
+   }
+
+   return result;
+}
+
+void ossimPngCodecFactory::getTypeNameList(std::vector<ossimString>& typeNames)const
+{
+   typeNames.push_back("png");
+   typeNames.push_back("pnga");
+   typeNames.push_back(STATIC_TYPE_NAME(ossimPngCodec));
+}
+
+ossimPngCodecFactory::ossimPngCodecFactory()
+{}
+
+ossimPngCodecFactory::ossimPngCodecFactory(const ossimPngCodecFactory& /* obj */ )
+{}
+
+const ossimPngCodecFactory& ossimPngCodecFactory::operator=(
+   const ossimPngCodecFactory& /* rhs */)
+{
+   return *this;
+}
+
diff --git a/ossim_plugins/png/ossimPngCodecFactory.h b/ossim_plugins/png/ossimPngCodecFactory.h
new file mode 100644
index 0000000..8204dbf
--- /dev/null
+++ b/ossim_plugins/png/ossimPngCodecFactory.h
@@ -0,0 +1,73 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author:  David Burken
+//
+// Description: Factory class declaration for codec(encoder/decoder).
+// 
+//----------------------------------------------------------------------------
+// $Id$
+#ifndef ossimPngCodecFactory_HEADER
+#define ossimPngCodecFactory_HEADER 1
+
+#include <ossim/imaging/ossimCodecFactoryInterface.h>
+
+class ossimFilename;
+class ossimCodecBase;
+
+/**
+ * @brief Codec factory.
+ */
+class ossimPngCodecFactory : public ossimCodecFactoryInterface
+{
+public:
+
+   /** virtual destructor */
+   virtual ~ossimPngCodecFactory();
+
+   /**
+   * @return instance
+   */
+   static ossimPngCodecFactory* instance();
+
+   /**
+   * createCodec takes a type and will return a new codec to encode decode image buffers
+   *
+   * @param in type.  Type identifer used to allocate the proper codec.
+   * @return ossimCodecBase type.
+   */
+   virtual ossimCodecBase* createCodec(const ossimString& type)const;
+
+
+   /**
+   * createCodec takes a type in the keywordlist and will return a new codec to encode decode image buffers
+   *
+   * @param in kwl.  Type identifer used to allocate the proper codec.
+   * @param in prefix.  prefix used to prefix keywords during the construction
+   *                    of the codec
+   * @return ossimCodecBase type.
+   */
+   virtual ossimCodecBase* createCodec(const ossimKeywordlist& kwl, const char* prefix=0)const;
+
+   virtual void getTypeNameList(std::vector<ossimString>& typeNames)const;
+   
+private:
+   
+   /** hidden from use default constructor */
+   ossimPngCodecFactory();
+
+   /** hidden from use copy constructor */
+   ossimPngCodecFactory(const ossimPngCodecFactory& obj);
+
+   /** hidden from use operator = */
+   const ossimPngCodecFactory& operator=(const ossimPngCodecFactory& rhs);
+
+   /** The single instance of this class. */
+   static ossimPngCodecFactory* m_instance;
+};
+
+#endif /* End of "#ifndef ossimCodecFactory_HEADER" */
+
diff --git a/ossim_plugins/png/ossimPngPluginInit.cpp b/ossim_plugins/png/ossimPngPluginInit.cpp
new file mode 100644
index 0000000..4e06e44
--- /dev/null
+++ b/ossim_plugins/png/ossimPngPluginInit.cpp
@@ -0,0 +1,87 @@
+//----------------------------------------------------------------------------
+//
+// License:  See top level LICENSE.txt file
+//
+// Author:  David Burken
+//
+// Description: OSSIM Portable Network Graphics (PNG) plugin initialization
+// code.
+//
+//----------------------------------------------------------------------------
+// $Id: ossimPngPluginInit.cpp 22998 2014-11-23 21:38:13Z gpotts $
+
+#include <ossim/plugin/ossimSharedObjectBridge.h>
+#include "ossimPluginConstants.h"
+#include "ossimPngReaderFactory.h"
+#include "ossimPngWriterFactory.h"
+#include "ossimPngCodecFactory.h"
+#include <ossim/imaging/ossimImageHandlerRegistry.h>
+#include <ossim/imaging/ossimImageWriterFactoryRegistry.h>
+#include <ossim/imaging/ossimCodecFactoryRegistry.h>
+
+static void setDescription(ossimString& description)
+{
+   description = "PNG reader / writer plugin\n\n";
+}
+
+
+extern "C"
+{
+   ossimSharedObjectInfo  myInfo;
+   ossimString theDescription;
+   std::vector<ossimString> theObjList;
+
+   const char* getDescription()
+   {
+      return theDescription.c_str();
+   }
+
+   int getNumberOfClassNames()
+   {
+      return (int)theObjList.size();
+   }
+
+   const char* getClassName(int idx)
+   {
+      if(idx < (int)theObjList.size())
+      {
+         return theObjList[0].c_str();
+      }
+      return (const char*)0;
+   }
+
+   /* Note symbols need to be exported on windoze... */ 
+   OSSIM_PLUGINS_DLL void ossimSharedLibraryInitialize(
+                                                       ossimSharedObjectInfo** info, 
+                                                       const char* /*options*/)
+   {    
+      myInfo.getDescription = getDescription;
+      myInfo.getNumberOfClassNames = getNumberOfClassNames;
+      myInfo.getClassName = getClassName;
+      
+      *info = &myInfo;
+      
+      /* Register the readers... */
+      ossimImageHandlerRegistry::instance()->
+        registerFactory(ossimPngReaderFactory::instance());
+      
+      /* Register the writers... */
+      ossimImageWriterFactoryRegistry::instance()->
+         registerFactory(ossimPngWriterFactory::instance());
+      
+      ossimCodecFactoryRegistry::instance()->registerFactory(ossimPngCodecFactory::instance());
+      setDescription(theDescription);
+  }
+
+   /* Note symbols need to be exported on windoze... */ 
+  OSSIM_PLUGINS_DLL void ossimSharedLibraryFinalize()
+  {
+     ossimImageHandlerRegistry::instance()->
+        unregisterFactory(ossimPngReaderFactory::instance());
+
+     ossimImageWriterFactoryRegistry::instance()->
+        unregisterFactory(ossimPngWriterFactory::instance());
+
+     ossimCodecFactoryRegistry::instance()->unregisterFactory(ossimPngCodecFactory::instance());
+  }
+}
diff --git a/ossim_plugins/png/ossimPngReader.cpp b/ossim_plugins/png/ossimPngReader.cpp
new file mode 100644
index 0000000..f3be45e
--- /dev/null
+++ b/ossim_plugins/png/ossimPngReader.cpp
@@ -0,0 +1,1350 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author:  David Burken
+//
+// Description: OSSIM Portable Network Graphics (PNG) reader (tile source).
+//
+//----------------------------------------------------------------------------
+// $Id: ossimPngReader.cpp 23664 2015-12-14 14:17:27Z dburken $
+
+
+#include "ossimPngReader.h"
+#include <ossim/base/ossimBooleanProperty.h>
+#include <ossim/base/ossimConstants.h>
+#include <ossim/base/ossimEndian.h>
+#include <ossim/base/ossimIpt.h>
+#include <ossim/base/ossimIrect.h>
+#include <ossim/base/ossimKeywordlist.h>
+#include <ossim/base/ossimNotifyContext.h>
+#include <ossim/base/ossimProperty.h>
+#include <ossim/base/ossimTrace.h>
+#include <ossim/imaging/ossimImageDataFactory.h>
+
+#include <zlib.h>
+
+#include <cstddef> /* for NULL */
+#include <cmath>   /* for pow */
+#include <fstream>
+
+// If true alpha channel is passed as a layer.
+static const std::string USE_ALPHA_KW = "use_alpha"; // boolean
+
+RTTI_DEF1(ossimPngReader, "ossimPngReader", ossimImageHandler)
+
+#ifdef OSSIM_ID_ENABLED
+   static const char OSSIM_ID[] = "$Id: ossimPngReader.cpp 23664 2015-12-14 14:17:27Z dburken $";
+#endif
+   
+static ossimTrace traceDebug("ossimPngReader:degug");  
+
+ossimPngReader::ossimPngReader()
+   :
+   ossimImageHandler(),
+   m_tile(0),
+   m_cacheTile(0),
+   m_lineBuffer(0),
+   m_lineBufferSizeInBytes(0),
+   m_str(0),
+   m_restartPosition(0),
+   m_ownsStream( true ),
+   m_bufferRect(0, 0, 0, 0),
+   m_imageRect(0, 0, 0, 0),
+   m_numberOfInputBands(0),
+   m_numberOfOutputBands(0),
+   m_bytePerPixelPerBand(1),
+   m_cacheSize(0),
+   m_cacheId(-1),
+   m_pngReadPtr(0),
+   m_pngReadInfoPtr(0),
+   m_pngColorType(PNG_COLOR_TYPE_GRAY),
+   m_currentRow(0),
+   m_outputScalarType(OSSIM_UINT8),
+   m_interlacePasses(1),
+   m_bitDepth(8),
+   m_readMode(ossimPngReadUnknown),
+   m_maxPixelValue(),
+   m_swapFlag(false),
+   m_useAlphaChannelFlag(false)
+{
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimPngReader::ossimPngReader entered..." << std::endl;
+      readPngVersionInfo();
+#ifdef OSSIM_ID_ENABLED
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "OSSIM_ID:  " << OSSIM_ID << endl;
+#endif
+   }
+}
+
+ossimPngReader::~ossimPngReader()
+{
+   if (isOpen())
+   {
+      close();
+   }
+}
+
+void ossimPngReader::close()
+{
+   destroy();
+   ossimImageHandler::close();
+}
+
+void ossimPngReader::destroy()
+{
+   ossimAppFixedTileCache::instance()->deleteCache(m_cacheId);
+
+   // ossimRefPtrs so assign to 0(unreferencing) will handle memory.
+   m_tile      = 0;
+   m_cacheTile = 0;
+
+   if (m_lineBuffer)
+   {
+      delete [] m_lineBuffer;
+      m_lineBuffer = 0;
+   }
+
+   if (m_pngReadPtr)
+   {
+      png_destroy_read_struct(&m_pngReadPtr, &m_pngReadInfoPtr, NULL);
+      m_pngReadPtr = 0;
+      m_pngReadInfoPtr = 0;
+   }
+
+   if ( m_str && m_ownsStream )
+   {
+      delete m_str;
+      m_str = 0;
+   }
+}
+
+void ossimPngReader::allocate()
+{
+   // Make the cache tile the height of one tile by the image width.
+   ossim::defaultTileSize(m_cacheSize);
+   m_cacheSize.x = m_imageRect.width();
+   
+   ossimAppFixedTileCache::instance()->deleteCache(m_cacheId);
+   m_cacheId = ossimAppFixedTileCache::instance()->
+      newTileCache(m_imageRect, m_cacheSize);
+
+   m_tile = ossimImageDataFactory::instance()->create(this, this);
+   m_cacheTile = (ossimImageData*)m_tile->dup();
+   m_tile->initialize();
+   
+   ossimIrect cache_rect(m_imageRect.ul().x,
+                         m_imageRect.ul().y,
+                         m_imageRect.ul().x + (m_cacheSize.x-1),
+                         m_imageRect.ul().y + (m_cacheSize.y-1));
+   
+   m_cacheTile->setImageRectangle(cache_rect);
+   m_cacheTile->initialize();
+
+   if(m_lineBuffer)
+   {
+      delete [] m_lineBuffer;
+   }
+   m_lineBuffer = new ossim_uint8[m_lineBufferSizeInBytes];
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimPngReader::allocate DEBUG:"
+         << "\nm_cacheTile:\n" << *(m_cacheTile.get())
+         << "\nm_tile:\n"      << *(m_tile.get())
+         << "\ncache tile size:           " << m_cacheSize
+         << "\nimage width:               " << m_imageRect.width()
+         << "\nimage height:              " << m_imageRect.height()
+         << "\nnumber of bands:           " << m_numberOfOutputBands
+         << "\nline buffer size:          " << m_lineBufferSizeInBytes
+         << endl;
+   }
+}
+
+ossimRefPtr<ossimImageData> ossimPngReader::getTile(
+   const ossimIrect& rect, ossim_uint32 resLevel)
+{
+   if ( !m_tile )
+   {
+      // First time through. Allocate memory...
+      allocate();
+   }
+   
+   if (m_tile.valid())
+   {
+      // Image rectangle must be set prior to calling getTile.
+      m_tile->setImageRectangle(rect);
+      
+      if ( getTile( m_tile.get(), resLevel ) == false )
+      {
+         if (m_tile->getDataObjectStatus() != OSSIM_NULL)
+         {
+            m_tile->makeBlank();
+         }
+      }
+   }
+   
+   return m_tile;
+}
+
+bool ossimPngReader::getTile(ossimImageData* result,
+                             ossim_uint32 resLevel)
+{
+   bool status = false;
+   
+   //---
+   // Not open, this tile source bypassed, or invalid res level,
+   // return a blank tile.
+   //---
+   if( isOpen() && isSourceEnabled() && isValidRLevel(resLevel) &&
+       result && (result->getNumberOfBands() == getNumberOfOutputBands()) )
+   {
+      result->ref(); // Increment ref count.
+      
+      //---
+      // Check for overview tile.  Some overviews can contain r0 so always
+      // call even if resLevel is 0.  Method returns true on success, false
+      // on error.
+      //---
+      status = getOverviewTile(resLevel, result);
+
+      if (status)
+      {
+         if(m_outputScalarType == OSSIM_UINT16)
+         {
+            //---
+            // Temp fix:
+            // The overview handler could return a tile of OSSIM_USHORT11 if
+            // the max sample value was not set to 2047.
+            //
+            // To prevent a scalar mismatch set 
+            //---
+            result->setScalarType(m_outputScalarType);
+         }
+      }
+      
+      if (!status) // Did not get an overview tile.
+      {
+         status = true;
+         
+         ossimIrect tile_rect = result->getImageRectangle();
+
+         if ( ! tile_rect.completely_within(getImageRectangle(0)) )
+         {
+            // We won't fill totally so make blank first.
+            m_tile->makeBlank();
+         }
+         
+         if (getImageRectangle(0).intersects(tile_rect))
+         {
+            // Make a clip rect.
+            ossimIrect clip_rect = tile_rect.clipToRect(getImageRectangle(0));
+            
+            // This will validate the tile at the end.
+            fillTile(clip_rect, result);
+         }
+      }
+
+      result->unref();  // Decrement ref count.
+   }
+
+   return status;
+}
+
+void ossimPngReader::fillTile(const ossimIrect& clip_rect,
+                              ossimImageData* tile)
+{
+   if (!tile || !m_str) return;
+
+   ossimIrect buffer_rect = clip_rect;
+   buffer_rect.stretchToTileBoundary(m_cacheSize);
+   buffer_rect.set_ulx(0);
+   buffer_rect.set_lrx(getImageRectangle(0).lr().x);
+
+   ossim_int32 number_of_cache_tiles = buffer_rect.height()/m_cacheSize.y;
+
+#if 0
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "tiles high:  " << number_of_cache_tiles
+         << endl;
+   }
+#endif
+
+   ossimIpt origin = buffer_rect.ul();
+   
+   for (int tileIdx = 0; tileIdx < number_of_cache_tiles; ++tileIdx)
+   {
+      // See if it's in the cache already.
+      ossimRefPtr<ossimImageData> tempTile;
+      tempTile = ossimAppFixedTileCache::instance()->
+         getTile(m_cacheId, origin);
+      if (tempTile.valid())
+      {
+         tile->loadTile(tempTile.get());
+      }
+      else
+      {
+         // Have to read from the png file.
+         ossim_uint32 startLine = static_cast<ossim_uint32>(origin.y);
+         ossim_uint32 stopLine  = 
+            static_cast<ossim_uint32>( min(origin.y+m_cacheSize.y-1,
+                                           getImageRectangle().lr().y) );
+         ossimIrect cache_rect(origin.x,
+                               origin.y,
+                               origin.x+m_cacheSize.x-1,
+                               origin.y+m_cacheSize.y-1);
+         
+         m_cacheTile->setImageRectangle(cache_rect);
+
+         if ( !m_cacheTile->getImageRectangle().
+              completely_within(getImageRectangle()) )
+         {
+            m_cacheTile->makeBlank();
+         }
+
+         if (startLine < m_currentRow)
+         {
+            // Must restart the compression process again.
+            restart();
+         }
+
+         // Gobble any not needed lines.
+         while(m_currentRow < startLine)
+         {
+            png_read_row(m_pngReadPtr, m_lineBuffer, NULL);
+            ++m_currentRow;
+         }
+            
+         switch (m_readMode)
+         {
+            case ossimPngRead8:
+            {
+               copyLines(ossim_uint8(0), stopLine);
+               break;
+            }
+            case ossimPngRead16:
+            {
+               copyLines(ossim_uint16(0), stopLine);
+               break;
+            }
+            case ossimPngRead8a:
+            {
+               if (m_useAlphaChannelFlag)
+               {
+                  copyLines(ossim_uint8(0), stopLine);
+               }
+               else
+               {
+                  // Will burn alpha value into the other bands.
+                  copyLinesWithAlpha(ossim_uint8(0), stopLine);
+               }
+               break;
+            }
+            case ossimPngRead16a:
+            {
+               if (m_useAlphaChannelFlag)
+               {
+                  copyLines(ossim_uint16(0), stopLine); 
+               }
+               else
+               {
+                  // Will burn alpha value into the other bands.
+                  copyLinesWithAlpha(ossim_uint16(0), stopLine);
+               }
+               break;
+            }
+            case ossimPngReadUnknown:
+            default:
+            {
+               break; // should never happen.
+            }
+         }
+
+         m_cacheTile->validate();
+         
+         tile->loadTile(m_cacheTile.get());
+         
+         // Add it to the cache for the next time.
+         ossimAppFixedTileCache::instance()->addTile(m_cacheId,
+                                                     m_cacheTile);
+         
+      } // End of reading for png file.
+      
+      origin.y += m_cacheSize.y;
+      
+   } // for (int tile = 0; tile < number_of_cache_tiles; ++tile)
+   
+   tile->validate();
+}
+
+ossimIrect
+ossimPngReader::getImageRectangle(ossim_uint32 reduced_res_level) const
+{
+   return ossimIrect(0,
+                     0,
+                     getNumberOfSamples(reduced_res_level) - 1,
+                     getNumberOfLines(reduced_res_level)   - 1);
+}
+
+bool ossimPngReader::saveState(ossimKeywordlist& kwl,
+                               const char* prefix) const
+{
+   std::string p = ( prefix ? prefix : "" );
+   std::string v = ossimString::toString(m_useAlphaChannelFlag).string();
+   kwl.addPair( p, USE_ALPHA_KW, v, true );
+   return ossimImageHandler::saveState(kwl, prefix);
+}
+
+bool ossimPngReader::loadState(const ossimKeywordlist& kwl,
+                               const char* prefix)
+{
+   bool result = false;
+   if (ossimImageHandler::loadState(kwl, prefix))
+   {
+      // this was causing core dumps.  Mainly because if prefix is null then
+      // standard string core dumps.  So wrapped with OSSIM string that checks
+      // for this and inits with empty string if null
+      //
+      ossimString value = kwl.findKey( ossimString(prefix).c_str(), USE_ALPHA_KW );
+      if ( value.size() )
+      {
+         ossimString s = value;
+         m_useAlphaChannelFlag = s.toBool();
+      }
+      result = open();
+  }
+   return result;
+}
+
+void ossimPngReader::setProperty(ossimRefPtr<ossimProperty> property)
+{
+   if ( property.valid() )
+   {
+      if ( property->getName().string() == USE_ALPHA_KW )
+      {
+         ossimString s;
+         property->valueToString(s);
+         m_useAlphaChannelFlag = s.toBool();
+      }
+      else
+      {
+         ossimImageHandler::setProperty(property);
+      }
+   }
+}
+
+ossimRefPtr<ossimProperty> ossimPngReader::getProperty(const ossimString& name)const
+{
+   ossimRefPtr<ossimProperty> prop = 0;
+   if ( name.string() == USE_ALPHA_KW )
+   {
+      prop = new ossimBooleanProperty(name, m_useAlphaChannelFlag);
+   }
+   else
+   {
+      prop = ossimImageHandler::getProperty(name);
+   }
+   return prop;
+}
+
+void ossimPngReader::getPropertyNames(std::vector<ossimString>& propertyNames)const
+{
+   propertyNames.push_back( ossimString(USE_ALPHA_KW) );
+   ossimImageHandler::getPropertyNames(propertyNames);
+}
+
+bool ossimPngReader::open()
+{
+   static const char MODULE[] = "ossimPngReader::open";
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimPngReader::open entered..."
+         << "File:  " << theImageFile.c_str()
+         << std::endl;
+   }
+
+   bool result = false;
+
+   // Start with a clean slate.
+   if (isOpen())
+   {
+      close();
+   }
+
+   // Check for empty filename.
+   if ( theImageFile.size() )
+   {
+      // Open the file:
+      std::ifstream* str = new std::ifstream();
+      str->open(theImageFile.c_str(), std::ios_base::in | std::ios_base::binary);
+
+      // Pass to our open:
+      result = open( str, 0, true );
+
+      if (traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG)
+            << MODULE << " DEBUG:\n";
+         if ( result )
+         {
+            ossimNotify(ossimNotifyLevel_DEBUG) << "opened ";
+         }
+         else
+         {
+            ossimNotify(ossimNotifyLevel_DEBUG) << "could not open ";
+         }
+         ossimNotify(ossimNotifyLevel_DEBUG)
+            << theImageFile.c_str() << std::endl;
+      }  
+   }
+   return result;
+}
+
+bool ossimPngReader::open( std::istream* str, std::streamoff restartPosition, bool youOwnIt )
+{
+   bool result = false;
+   if (isOpen())
+   {
+      close();
+   }
+
+   if ( str )
+   {
+      str->seekg( m_restartPosition, std::ios_base::beg );
+
+      if ( checkSignature( str ) )
+      {
+         // Store the pointer:
+         m_str = str;
+         m_restartPosition = restartPosition;
+         m_ownsStream = youOwnIt;
+         
+         result = readPngInit();
+         if ( result )
+         {
+            result = initReader();
+            if ( result )
+            {
+               completeOpen();
+            }
+         }
+         else
+         {
+            destroy();
+         }
+      }
+      else
+      {
+         if ( youOwnIt )
+         {
+            delete str;
+            str = 0;
+         }         
+         
+         if (traceDebug())
+         {
+            ossimNotify(ossimNotifyLevel_DEBUG)
+               << "ossimPngReader::open NOTICE:\n"
+               << "Could not open:  " << theImageFile.c_str()
+               << endl;
+         }
+      }
+   }
+   
+   return result;
+}
+
+ossim_uint32 ossimPngReader::getTileWidth() const
+{
+   return ( m_tile.valid() ? m_tile->getWidth() : 0 );
+}
+
+ossim_uint32 ossimPngReader::getTileHeight() const
+{
+   return ( m_tile.valid() ? m_tile->getHeight() : 0 );
+}
+
+ossim_uint32 ossimPngReader::getNumberOfLines(ossim_uint32 reduced_res_level) const
+{
+   if (reduced_res_level == 0)
+   {
+      return m_imageRect.height();
+   }
+   else if ( theOverview.valid() )
+   {
+      return theOverview->getNumberOfLines(reduced_res_level);
+   }
+
+   return 0;
+}
+
+ossim_uint32 ossimPngReader::getNumberOfSamples(ossim_uint32 reduced_res_level) const
+{
+   if (reduced_res_level == 0)
+   {
+      return m_imageRect.width();
+   }
+   else if ( theOverview.valid() )
+   {
+      return theOverview->getNumberOfSamples(reduced_res_level);
+   }
+
+   return 0;
+}
+
+ossim_uint32 ossimPngReader::getImageTileWidth() const
+{
+   return 0;
+}
+
+ossim_uint32 ossimPngReader::getImageTileHeight() const
+{
+   return 0;
+}
+
+ossimString ossimPngReader::getShortName()const
+{
+   return ossimString("ossim_png_reader");
+}
+   
+ossimString ossimPngReader::getLongName()const
+{
+   return ossimString("ossim png reader");
+}
+
+ossimString  ossimPngReader::getClassName()const
+{
+   return ossimString("ossimPngReader");
+}
+
+ossim_uint32 ossimPngReader::getNumberOfInputBands() const
+{
+   //---
+   // NOTE:  If there is an alpha channel the input band will be one more than
+   // the output bands.  For library purposes the output bands and input bands
+   // are the same.
+   //---
+   return m_numberOfOutputBands;
+}
+
+ossim_uint32 ossimPngReader::getNumberOfOutputBands()const
+{
+   return m_numberOfOutputBands;
+}
+
+ossimScalarType ossimPngReader::getOutputScalarType() const
+{
+   return m_outputScalarType;
+}
+
+bool ossimPngReader::isOpen()const
+{
+   return ( m_str );
+}
+
+double ossimPngReader::getMaxPixelValue(ossim_uint32 band)const
+{
+   //---
+   // Note the size of m_maxPixelValue can be one greater than output bands
+   // if there is an alpa channel.
+   //---
+   if (band < m_numberOfOutputBands)
+   {
+      return m_maxPixelValue[band];
+   }
+   return 255.0;
+}
+
+void ossimPngReader::restart()
+{
+   if ( m_str )
+   {
+      // Destroy the existing memory associated with png structs.
+      if (m_pngReadPtr && m_pngReadInfoPtr)
+      {
+         png_destroy_read_struct(&m_pngReadPtr, &m_pngReadInfoPtr, NULL);
+      }
+
+      m_pngReadPtr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
+                                            NULL,
+                                            NULL,
+                                            NULL);
+      m_pngReadInfoPtr = png_create_info_struct(m_pngReadPtr);
+
+      if ( setjmp( png_jmpbuf(m_pngReadPtr) ) )
+      {
+         ossimNotify(ossimNotifyLevel_WARN)
+            << "Error while reading.  File corrupted?  "
+            << theImageFile
+            << std::endl;
+      
+         return;
+      }
+
+      // Reset the file pointer.
+      m_str->seekg( m_restartPosition, std::ios_base::beg );
+   
+      //---
+      // Pass the static read method to libpng to allow us to use our
+      // c++ stream instead of doing "png_init_io (pp, ...);" with
+      // c stream.
+      //---
+      png_set_read_fn( m_pngReadPtr,
+                       (png_voidp)m_str,
+                       (png_rw_ptr)&ossimPngReader::pngReadData );
+
+      //---
+      // Note we won't do png_set_sig_bytes(png_ptr, 8) here because we are not
+      // rechecking for png signature.
+      //---
+      png_read_info(m_pngReadPtr, m_pngReadInfoPtr);
+
+      //---
+      // If png_set_expand used:
+      // Expand data to 24-bit RGB, or 8-bit grayscale,
+      // with alpha if available.
+      //---
+      bool expandFlag = false;
+
+      if ( m_pngColorType == PNG_COLOR_TYPE_PALETTE )
+      {
+         expandFlag = true;
+      }
+      if ( (m_pngColorType == PNG_COLOR_TYPE_GRAY) && (m_bitDepth < 8) )
+      {
+         expandFlag = true;
+      }
+      if ( png_get_valid(m_pngReadPtr, m_pngReadInfoPtr, PNG_INFO_tRNS) )
+      {
+         expandFlag = true;
+      }
+
+      //---
+      // If png_set_packing used:
+      // Use 1 byte per pixel in 1, 2, or 4-bit depth files. */
+      //---
+      bool packingFlag = false;
+
+      if ( (m_bitDepth < 8) && (m_pngColorType == PNG_COLOR_TYPE_GRAY) )
+      {
+         packingFlag = true;
+      }
+
+      if (expandFlag)
+      {
+         png_set_expand(m_pngReadPtr);
+      }
+      if (packingFlag)
+      {
+         png_set_packing(m_pngReadPtr);
+      }
+
+      // Gamma correction.
+      //    ossim_float64 gamma;
+      //    if (png_get_gAMA(m_pngReadPtr, m_pngReadInfoPtr, &gamma))
+      //    {
+      //       png_set_gamma(m_pngReadPtr, display_exponent, gamma);
+      //    }
+
+      //---
+      // Turn on interlace handling... libpng returns just 1 (ie single pass)
+      //  if the image is not interlaced
+      //---
+      png_set_interlace_handling (m_pngReadPtr);
+
+      //---
+      // Update the info structures after the transformations take effect
+      //---
+      png_read_update_info (m_pngReadPtr, m_pngReadInfoPtr);
+   
+      // We're back on row 0 or first line.
+      m_currentRow = 0;
+   }
+}
+
+bool ossimPngReader::checkSignature( std::istream* str )
+{
+   bool result = false;
+   if ( str )
+   {
+      //---
+      // Verify the file is a png by checking the first eight bytes:
+      // 0x 89 50 4e 47 0d 0a 1a 0a
+      //---
+      ossim_uint8 sig[8];
+      str->read( (char*)sig, 8);
+      if ( str->good() )
+      {
+         if ( png_sig_cmp(sig, 0, 8) == 0 )
+         {
+            result = true;
+         }
+      }
+   }
+   return result;
+}
+
+ossimRefPtr<ossimImageGeometry> ossimPngReader::getImageGeometry()
+{
+   if ( !theGeometry )
+   {
+      //---
+      // Check factory for external geom:
+      //---
+      theGeometry = getExternalImageGeometry();
+
+      if ( !theGeometry )
+      {
+         // Fist time through:
+         theGeometry = new ossimImageGeometry();
+
+         //---
+         // This code does not call ossimImageGeometryRegistry::extendGeometry
+         // by design to avoid wasted factory calls.
+         //---
+      }
+
+      // Set image things the geometry object should know about.
+      initImageParameters( theGeometry.get() );
+   }
+   return theGeometry;
+}
+
+bool ossimPngReader::readPngInit()
+{
+   bool result = false;
+   if ( m_str )
+   {
+      if ( m_str->good() )
+      {
+         m_pngReadPtr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
+                                               NULL,
+                                               NULL,
+                                               NULL);
+         if ( m_pngReadPtr )
+         {
+            m_pngReadInfoPtr = png_create_info_struct(m_pngReadPtr);
+            if ( m_pngReadInfoPtr )
+            {
+               if ( setjmp( png_jmpbuf(m_pngReadPtr) ) == 0 )
+               {
+                  //---
+                  // Pass the static read method to libpng to allow us to use our
+                  // c++ stream instead of doing "png_init_io (pp, ...);" with
+                  // c stream.
+                  //---
+                  png_set_read_fn( m_pngReadPtr,
+                                   (png_voidp)m_str,
+                                   (png_rw_ptr)&ossimPngReader::pngReadData );
+                  png_set_sig_bytes(m_pngReadPtr, 8);
+                  png_read_info(m_pngReadPtr, m_pngReadInfoPtr);
+                  result = true;
+               }
+            }
+            else
+            {
+               // Out of memory?
+               png_destroy_read_struct(&m_pngReadPtr, NULL, NULL);
+            }
+         }
+      }
+   }
+   return result;
+   
+} // End: ossimPngReader::readPngInit()
+
+bool ossimPngReader::initReader()
+{
+   bool result = true;
+   
+   ossim_uint32 height    = png_get_image_height(m_pngReadPtr, m_pngReadInfoPtr);
+   ossim_uint32 width     = png_get_image_width(m_pngReadPtr, m_pngReadInfoPtr);
+   m_bitDepth            = png_get_bit_depth(m_pngReadPtr, m_pngReadInfoPtr);
+   m_pngColorType        = png_get_color_type(m_pngReadPtr, m_pngReadInfoPtr);
+   
+   m_imageRect = ossimIrect(0, 0, width  - 1, height - 1);
+   
+   if (m_bitDepth == 16)
+   {
+      // png_set_strip_16 (m_pngReadPtr);
+      m_bytePerPixelPerBand = 2;
+      m_outputScalarType = OSSIM_UINT16;
+   }
+   else
+   {
+      m_bytePerPixelPerBand = 1;
+   }
+
+   // Set the read mode from scalar and color type.
+   if (m_outputScalarType == OSSIM_UINT8)
+   {
+      if ( (m_pngColorType == PNG_COLOR_TYPE_RGB_ALPHA) ||
+           (m_pngColorType == PNG_COLOR_TYPE_GRAY_ALPHA) )
+      {
+         m_readMode = ossimPngRead8a;
+      }
+      else
+      {
+         m_readMode = ossimPngRead8;
+      }
+   }
+   else
+   {
+      if ( (m_pngColorType == PNG_COLOR_TYPE_RGB_ALPHA) ||
+           (m_pngColorType == PNG_COLOR_TYPE_GRAY_ALPHA) )
+      {
+         m_readMode = ossimPngRead16a;
+      }
+      else
+      {
+         m_readMode = ossimPngRead16;
+      }
+
+      // Set the swap flag.  PNG stores data in network byte order(big endian).
+      if(ossim::byteOrder() == OSSIM_LITTLE_ENDIAN)
+      {
+         m_swapFlag = true;
+      }
+   }
+   
+   //---
+   // If png_set_expand used:
+   // Expand data to 24-bit RGB, or 8-bit grayscale,
+   // with alpha if available.
+   //---
+   bool expandFlag = false;
+
+   if ( m_pngColorType == PNG_COLOR_TYPE_PALETTE )
+   {
+      expandFlag = true;
+   }
+   if ( (m_pngColorType == PNG_COLOR_TYPE_GRAY) && (m_bitDepth < 8) )
+   {
+      expandFlag = true;
+   }
+   if ( png_get_valid(m_pngReadPtr, m_pngReadInfoPtr, PNG_INFO_tRNS) )
+   {
+      expandFlag = true;
+   }
+
+   //---
+   // If png_set_packing used:
+   // Use 1 byte per pixel in 1, 2, or 4-bit depth files. */
+   //---
+   bool packingFlag = false;
+
+   if ( (m_bitDepth < 8) && (m_pngColorType == PNG_COLOR_TYPE_GRAY) )
+   {
+      packingFlag = true;
+   }
+
+   if (expandFlag)
+   {
+       png_set_expand(m_pngReadPtr);
+   }
+   if (packingFlag)
+   {
+      png_set_packing(m_pngReadPtr);
+   }
+
+   // Gamma correction.
+   // ossim_float64 gamma;
+   // if (png_get_gAMA(m_pngReadPtr, m_pngReadInfoPtr, &gamma))
+   // {
+   //    png_set_gamma(png_ptr, display_exponent, gamma);
+   // }
+
+   //---
+   // Turn on interlace handling... libpng returns just 1 (ie single pass)
+   //  if the image is not interlaced
+   //---
+   m_interlacePasses = png_set_interlace_handling (m_pngReadPtr);
+
+   //---
+   // Update the info structures after the transformations take effect
+   //---
+   png_read_update_info (m_pngReadPtr, m_pngReadInfoPtr);
+
+   // TODO:
+   // Add check for image offsets.
+   // Add check for resolution.
+   // Add check for colormap.
+
+   switch (m_pngColorType)
+   {
+      case PNG_COLOR_TYPE_RGB:           /* RGB */
+      {
+         m_numberOfInputBands  = 3;
+         m_numberOfOutputBands = 3;
+         break;
+      }  
+      case PNG_COLOR_TYPE_RGB_ALPHA:     /* RGBA */
+      {
+         m_numberOfInputBands  = 4;
+         if (m_useAlphaChannelFlag)
+         {
+            m_numberOfOutputBands = 4;     
+         }
+         else
+         {
+            m_numberOfOutputBands = 3;    
+         }         
+         break;
+      }
+      case PNG_COLOR_TYPE_GRAY:          /* Grayscale */
+      {
+         m_numberOfInputBands = 1;
+         m_numberOfOutputBands = 1;
+         break;
+      }  
+      case PNG_COLOR_TYPE_GRAY_ALPHA:    /* Grayscale + alpha */
+      {
+         m_numberOfInputBands = 2;
+         if (m_useAlphaChannelFlag)
+         {
+            m_numberOfOutputBands = 2;     
+         }
+         else
+         {
+            m_numberOfOutputBands = 1;
+         }
+        break;
+      }
+     case PNG_COLOR_TYPE_PALETTE:       /* Indexed */
+     {
+        m_numberOfInputBands  = 3;
+        m_numberOfOutputBands = 3;
+        break;
+     }  
+     default:                   /* Unknown type */
+     {
+        result = false;
+     }
+   }
+
+   if ( result )
+   {
+      m_lineBufferSizeInBytes = png_get_rowbytes(m_pngReadPtr, m_pngReadInfoPtr);
+      
+      // Set the max pixel value.
+      setMaxPixelValue();
+      
+      // Set to OSSIM_USHORT11 for use of specialized tile.
+      if (m_maxPixelValue[0] == 2047.0)
+      {
+         m_outputScalarType = OSSIM_USHORT11;
+      }
+
+      // We're on row 0 or first line.
+      m_currentRow = 0;
+      
+      if (traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG)
+            << "ossimPngReader::initReader DEBUG:"
+            << "\nm_imageRect:                     " << m_imageRect
+            << "\nm_bitDepth:                      " << int(m_bitDepth)
+            << "\nm_pngColorType:                  "
+            <<  getPngColorTypeString().c_str()
+            << "\nm_numberOfInputBands:            " << m_numberOfInputBands
+            << "\nm_numberOfOutputBands:           " << m_numberOfOutputBands
+            << "\nm_bytePerPixelPerBand:           " << m_bytePerPixelPerBand
+            << "\nm_lineBufferSizeInBytes:         " << m_lineBufferSizeInBytes
+            << "\nm_interlacePasses:               " << m_interlacePasses
+            << "\npalette expansion:                "
+            << (expandFlag?"on":"off")
+            << "\npacking (1,2,4 bit to one byte):  "
+            << (packingFlag?"on":"off")
+            << "\nm_readMode:                      " << m_readMode
+            << "\nm_swapFlag:                      " << m_swapFlag
+            << std::endl;
+         
+         for (ossim_uint32 band = 0; band < m_numberOfInputBands; ++band)
+         {
+            ossimNotify(ossimNotifyLevel_DEBUG)
+               << "max[" << band << "]:  " << m_maxPixelValue[band]
+               << std::endl;
+         }
+      }
+   }
+
+   return result;
+   
+} // End: ossimPngReader::initReader()
+
+void ossimPngReader::readPngVersionInfo()
+{
+   ossimNotify(ossimNotifyLevel_WARN)
+      << "ossimPngReader::readPngVersionInfo\nCompiled with:"
+      << "\nlibpng " << PNG_LIBPNG_VER_STRING
+      << " using libpng " << PNG_LIBPNG_VER
+      << "\nzlib " << ZLIB_VERSION " using zlib "
+      << zlib_version << std::endl;
+}
+
+ossimString ossimPngReader::getPngColorTypeString() const
+{
+   ossimString result = "unknown";
+   if (m_pngColorType == PNG_COLOR_TYPE_GRAY)
+   {
+      return ossimString("PNG_COLOR_TYPE_GRAY");
+   }
+   else if (m_pngColorType == PNG_COLOR_TYPE_PALETTE)
+   {
+      return ossimString("PNG_COLOR_TYPE_PALETTE");
+   }
+   else if (m_pngColorType == PNG_COLOR_TYPE_RGB)
+   {
+      return ossimString("PNG_COLOR_TYPE_RGB");
+   }
+   else if (m_pngColorType == PNG_COLOR_TYPE_RGB_ALPHA)
+   {
+      return ossimString("PNG_COLOR_TYPE_RGB_ALPHA");
+   }
+   else if (m_pngColorType == PNG_COLOR_TYPE_GRAY_ALPHA)
+   {
+      return ossimString("PNG_COLOR_TYPE_GRAY_ALPHA");
+   }
+
+   return ossimString("unknown");
+}
+
+void ossimPngReader::setMaxPixelValue()
+{
+   ossim_uint32 band;
+   m_maxPixelValue.resize(m_numberOfInputBands);
+   for (band = 0; band < m_numberOfInputBands; ++band)
+   {
+      m_maxPixelValue[band] = 0.0;
+   }
+   
+   if (png_get_valid(m_pngReadPtr, m_pngReadInfoPtr, PNG_INFO_sBIT ))
+   {
+      png_color_8p sig_bit;
+      png_get_sBIT(m_pngReadPtr, m_pngReadInfoPtr, &sig_bit);
+      if (traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG)
+            << "ossimPngReader::setMaxPixelValue DEBUG:"
+            << "\nsig_bit->red:   " << int(sig_bit->red)
+            << "\nsig_bit->green: " << int(sig_bit->green)
+            << "\nsig_bit->blue:  " << int(sig_bit->blue)
+            << "\nsig_bit->gray:  " << int(sig_bit->gray)            
+            << "\nsig_bit->alpa:  " << int(sig_bit->alpha)
+            << endl;
+      }
+      switch (m_pngColorType)
+      {
+         case PNG_COLOR_TYPE_RGB:           /* RGB */
+            m_maxPixelValue[0] = pow(2.0, double(sig_bit->red))-1.0;
+            m_maxPixelValue[1] = pow(2.0, double(sig_bit->green))-1.0;
+            m_maxPixelValue[2] = pow(2.0, double(sig_bit->blue))-1.0;
+            break;
+         case PNG_COLOR_TYPE_RGB_ALPHA:     /* RGBA */
+            m_maxPixelValue[0] = pow(2.0, double(sig_bit->red))-1.0;
+            m_maxPixelValue[1] = pow(2.0, double(sig_bit->green))-1.0;
+            m_maxPixelValue[2] = pow(2.0, double(sig_bit->blue))-1.0;
+            m_maxPixelValue[3] = pow(2.0, double(sig_bit->alpha))-1.0;
+            break;
+         case PNG_COLOR_TYPE_GRAY:          /* Grayscale */
+            m_maxPixelValue[0] = pow(2.0, double(sig_bit->gray))-1.0;
+            break;
+         case PNG_COLOR_TYPE_GRAY_ALPHA:    /* Grayscale + alpha */            
+            m_maxPixelValue[0] = pow(2.0, double(sig_bit->gray))-1.0;
+            m_maxPixelValue[1] = pow(2.0, double(sig_bit->alpha))-1.0;
+            break;
+         case PNG_COLOR_TYPE_PALETTE:       /* Indexed */
+            m_maxPixelValue[0] = 255.0;
+            m_maxPixelValue[1] = 255.0;
+            m_maxPixelValue[2] = 255.0;
+            break;
+         default:                   /* Aie! Unknown type */
+            break;
+      }
+   }
+
+   // Sanity check.
+   for (ossim_uint32 band = 0; band < m_numberOfInputBands; ++band)
+   {
+      if (m_maxPixelValue[band] == 0.0)
+      {
+         if (m_bitDepth <= 8)
+         {
+            m_maxPixelValue[band] = 255.0;
+         }
+         else
+         {
+            m_maxPixelValue[band] = 65535.0;
+         }
+      }
+   }
+}
+
+template <class T>  void ossimPngReader::copyLines(
+   T /*dummy*/,  ossim_uint32 stopLine)
+{
+   const ossim_uint32 SAMPLES = m_imageRect.width();
+
+   T* src = (T*)m_lineBuffer;
+   std::vector<T*> dst(m_numberOfOutputBands);
+
+   ossim_uint32 band = 0;
+   for (band = 0; band < m_numberOfOutputBands; ++band)
+   {
+      dst[band] = (T*) m_cacheTile->getBuf(band);
+   }
+   
+   ossim_int32 bufIdx = 0;
+   
+   while (m_currentRow <= stopLine)
+   {
+      // Read a line from the jpeg file.
+      png_read_row(m_pngReadPtr, m_lineBuffer, NULL);
+      ++m_currentRow;
+
+      if(m_swapFlag)
+      {
+         ossimEndian endian;
+         endian.swap(src, SAMPLES*m_numberOfInputBands);
+      }
+
+      //---
+      // Copy the line which is band interleaved by pixel the the band
+      // separate buffers.
+      //---
+      ossim_uint32 index = 0;
+      for (ossim_uint32 sample = 0; sample < SAMPLES; ++sample)
+      {
+         for (band = 0; band < m_numberOfOutputBands; ++band)
+         {
+            dst[band][bufIdx] = src[index];
+            ++index;
+         }
+         ++bufIdx;
+      }
+   }
+}
+
+template <class T> void ossimPngReader::copyLinesWithAlpha(
+   T, ossim_uint32 stopLine)
+{
+   ossim_float64 denominator;
+   if (m_outputScalarType == OSSIM_UINT8)
+   {
+      denominator = m_maxPixelValue[m_numberOfInputBands-1];
+   }
+   else
+   {
+      denominator = m_maxPixelValue[m_numberOfInputBands-1];
+   }
+
+   const ossim_uint32 SAMPLES = m_imageRect.width();
+   
+   T* src = (T*) m_lineBuffer;
+
+   std::vector<T*> dst(m_numberOfOutputBands);
+   std::vector<T> p(m_numberOfOutputBands);
+   
+   ossim_float64 alpha;
+
+   const ossim_float64 MIN_PIX  = m_cacheTile->getMinPix(0);
+   const ossim_float64 MAX_PIX  = m_cacheTile->getMaxPix(0);
+   const ossim_float64 NULL_PIX = m_cacheTile->getNullPix(0);
+ 
+   ossim_uint32 band = 0;
+   for (band = 0; band < m_numberOfOutputBands; ++band)
+   {
+      dst[band] = (T*)m_cacheTile->getBuf(band);
+   }
+
+   ossim_int32 dstIdx = 0;
+   
+   while (m_currentRow <= stopLine)
+   {
+      // Read a line from the jpeg file.
+      png_read_row(m_pngReadPtr, m_lineBuffer, NULL);
+      ++m_currentRow;
+
+      if(m_swapFlag)
+      {
+         ossimEndian endian;
+         endian.swap(src, SAMPLES*m_numberOfInputBands);
+      }
+      
+      //---
+      // Copy the line which is band interleaved by pixel the the band
+      // separate buffers.
+      //---
+      ossim_uint32 srcIdx = 0;
+      for (ossim_uint32 sample = 0; sample < SAMPLES; ++sample)
+      {
+         // Copy the pixels.
+         for (band = 0; band < m_numberOfOutputBands; ++band)
+         {
+            p[band] = src[srcIdx++];
+         }
+         
+         // Get the alpha channel.
+         alpha = src[srcIdx++];
+         alpha = alpha / denominator;
+         
+         if (alpha == 1.0)
+         {
+            for (band = 0; band < m_numberOfOutputBands; ++band)
+            {
+               dst[band][dstIdx] = p[band];
+            }
+         }
+         else if (alpha == 0.0)
+         {
+            for (band = 0; band < m_numberOfOutputBands; ++band)
+            {
+               dst[band][dstIdx] = static_cast<T>(NULL_PIX);
+            }
+         }
+         else
+         {
+            for (band = 0; band < m_numberOfOutputBands; ++band)
+            {
+               ossim_float64 f = p[band];
+               f = f * alpha;
+               if (f != NULL_PIX)
+               {
+                  dst[band][dstIdx] =
+                     static_cast<T>( (f>=MIN_PIX) ?
+                                     ( (f<=MAX_PIX) ? f : MAX_PIX ) :
+                                     MIN_PIX );
+               }
+               else
+               {
+                  dst[band][dstIdx] = static_cast<T>(NULL_PIX);
+               }
+            }
+         }
+         ++dstIdx; // next sample...
+            
+      } // End of sample loop.
+      
+   } // End of line loop.
+}
+
+// Static function to read from c++ stream.
+void ossimPngReader::pngReadData( png_structp png_ptr, png_bytep data, png_size_t length )
+{
+   std::istream* str = (std::istream*)png_get_io_ptr(png_ptr);
+   if ( str )
+   {
+      str->read( (char*)data, length );
+   }
+}
+
diff --git a/ossim_plugins/png/ossimPngReader.h b/ossim_plugins/png/ossimPngReader.h
new file mode 100644
index 0000000..db958ce
--- /dev/null
+++ b/ossim_plugins/png/ossimPngReader.h
@@ -0,0 +1,323 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author:  David Burken
+//
+// Description: OSSIM Portable Network Graphics (PNG) reader (tile source).
+//
+//----------------------------------------------------------------------------
+// $Id: ossimPngReader.h 23664 2015-12-14 14:17:27Z dburken $
+#ifndef ossimPngReader_HEADER
+#define ossimPngReader_HEADER 1
+
+#include <ossim/imaging/ossimImageHandler.h>
+#include <ossim/imaging/ossimStreamReaderInterface.h>
+#include <ossim/imaging/ossimAppFixedTileCache.h>
+#include <png.h>
+#include <vector>
+
+class ossimImageData;
+
+class ossimPngReader : public ossimImageHandler, public ossimStreamReaderInterface
+{
+public:
+
+   enum ossimPngReadMode
+   {
+      ossimPngReadUnknown = 0,
+      ossimPngRead8       = 1,
+      ossimPngRead16      = 2,
+      ossimPngRead8a      = 3,
+      ossimPngRead16a     = 4 
+   };
+
+   /** default constructor */
+   ossimPngReader();
+
+   /** virtual destructor */
+   virtual ~ossimPngReader();
+
+   /** @return "png" */
+   virtual ossimString getShortName() const;
+
+   /** @return "ossim png" */
+   virtual ossimString getLongName()  const;
+
+   /** @return "ossimPngReader" */
+   virtual ossimString getClassName()    const;
+
+   /**
+    *  Returns a pointer to a tile given an origin representing the upper
+    *  left corner of the tile to grab from the image.
+    *  Satisfies pure virtual from TileSource class.
+    */
+   virtual ossimRefPtr<ossimImageData> getTile(const  ossimIrect& rect,
+                                               ossim_uint32 resLevel=0);
+   /**
+    * Method to get a tile.   
+    *
+    * @param result The tile to stuff.  Note The requested rectangle in full
+    * image space and bands should be set in the result tile prior to
+    * passing.  It will be an error if:
+    * result.getNumberOfBands() != this->getNumberOfOutputBands()
+    *
+    * @return true on success false on error.  If return is false, result
+    *  is undefined so caller should handle appropriately with makeBlank or
+    * whatever.
+    */
+   virtual bool getTile(ossimImageData* result, ossim_uint32 resLevel=0);
+
+    /**
+     *  Returns the number of bands in the image.
+     *  Satisfies pure virtual from ImageHandler class.
+     */
+   virtual ossim_uint32 getNumberOfInputBands() const;
+
+   /**
+    * Returns the number of bands in a tile returned from this TileSource.
+    * Note: we are supporting sources that can have multiple data objects.
+    * If you want to know the scalar type of an object you can pass in the
+    */
+   virtual ossim_uint32 getNumberOfOutputBands()const;
+
+   /**
+     *  Returns the number of lines in the image.
+     *  Satisfies pure virtual from ImageHandler class.
+     */
+   virtual ossim_uint32 getNumberOfLines(ossim_uint32 reduced_res_level = 0) const;
+
+   /**
+    *  Returns the number of samples in the image.
+    *  Satisfies pure virtual from ImageHandler class.
+    */
+   virtual ossim_uint32 getNumberOfSamples(ossim_uint32 reduced_res_level = 0) const;
+
+   /**
+    * Returns the zero based image rectangle for the reduced resolution data
+    * set (rrds) passed in.  Note that rrds 0 is the highest resolution rrds.
+    */
+   virtual ossimIrect getImageRectangle(ossim_uint32 reduced_res_level = 0) const;
+
+   /**
+    * Method to save the state of an object to a keyword list.
+    * Return true if ok or false on error.
+    */
+   virtual bool saveState(ossimKeywordlist& kwl,
+                          const char* prefix=0)const;
+
+   /**
+    * Method to the load (recreate) the state of an object from a keyword
+    * list.  Return true if ok or false on error.
+    */
+   virtual bool loadState(const ossimKeywordlist& kwl,
+                          const char* prefix=0);
+
+   /**
+    * @brief Set propterty method. Overrides ossimImageHandler::setProperty.
+    *
+    * Current property name handled:
+    * "scale" One double value representing the scale in meters per pixel. It is
+    * assumed the scale is same for x and y direction.
+    * 
+    * @param property to set.
+    */
+   virtual void setProperty(ossimRefPtr<ossimProperty> property);
+
+   /**
+     * @brief Get propterty method. Overrides ossimImageHandler::getProperty.
+    * @param name Property name to get.
+    */
+   virtual ossimRefPtr<ossimProperty> getProperty(const ossimString& name) const;
+   
+   /**
+    * @brief Get propterty names. Overrides ossimImageHandler::getPropertyNames.
+    * @param propertyNames Array to initialize.
+    */
+   virtual void getPropertyNames(std::vector<ossimString>& propertyNames) const;
+
+   /**
+    * Returns the output pixel type of the tile source.
+    */
+   virtual ossimScalarType getOutputScalarType() const;
+
+   /**
+    * Returns the width of the output tile.
+    */
+   virtual ossim_uint32    getTileWidth() const;
+
+   /**
+    * Returns the height of the output tile.
+    */
+   virtual ossim_uint32    getTileHeight() const;
+
+   /**
+    * Returns the tile width of the image or 0 if the image is not tiled.
+    * Note: this is not the same as the ossimImageSource::getTileWidth which
+    * returns the output tile width which can be different than the internal
+    * image tile width on disk.
+    */
+   virtual ossim_uint32 getImageTileWidth() const;
+
+   /**
+    * Returns the tile width of the image or 0 if the image is not tiled.
+    * Note: this is not the same as the ossimImageSource::getTileWidth which
+    * returns the output tile width which can be different than the internal
+    * image tile width on disk.
+    */
+   virtual ossim_uint32 getImageTileHeight() const;
+
+   bool isOpen()const;
+
+   virtual double getMaxPixelValue(ossim_uint32 band = 0)const;
+   
+   /**
+    *  @brief open method.
+    *
+    *  This open takes a stream, postition and a flag.
+    *
+    *  @param str Open stream to image.
+    *
+    *  @param restartPosition Typically 0, this is the stream offset to the
+    *  front of the image.
+    *
+    *  @param youOwnIt If true this object takes owner ship of the pointer
+    *  memory and will destroy on close.
+    *  
+    *  @return true on success, false on error.
+    */
+   virtual bool open( std::istream* str,
+                      std::streamoff restartPosition,
+                      bool youOwnIt );
+
+   /** Close method. */
+   virtual void close();
+
+   /**
+    * @return true if first 8 bytes matches png signature, false if not.
+    */
+   bool checkSignature(std::istream* str);
+
+   /**
+    * @brief Gets the image geometry.
+    *
+    * This method overrides ossimImageHandler::getImageGeometry to NOT
+    * call ossimImageGeometryRegistry::instance()->extendGeometry().
+    * 
+    * @return the image geometry object associated with this tile source.
+    * In many case the underlying ossimImageGeometry projection may be NULL
+    * with this reader so callers should check.
+    */
+   virtual ossimRefPtr<ossimImageGeometry> getImageGeometry();
+   
+protected:
+   
+   /**
+    * @brief Performs signature check and initializes png_structp and png_infop.
+    * @return true on success, false on error.
+    */
+   bool readPngInit();
+
+   /**
+    * @brief Initializes this reader from libpng m_pngPtr and infoPtr.
+    * @return true on success, false on error.
+    */
+   bool initReader();
+   
+   void readPngVersionInfo();
+   ossimString getPngColorTypeString() const;
+
+   /**
+    * @Sets the max pixel value.  Attempts to get the sBIT chunk.
+    */
+   void setMaxPixelValue();
+
+   /**
+    *  @brief open method.
+    *
+    *  This open assumes base class ossimImageHandler::theImageFile has been
+    *  set.
+    *
+    *  @return true on success, false on error.
+    */
+   virtual bool open();
+
+   /**
+    * @brief Initializes tiles and buffers.  Called once on first
+    * getTile request.
+    */ 
+   void allocate();
+
+   /**
+    * @brief Free tile and buffer memory.  Deletes stream if own it flag
+    * is set.
+    */
+   void destroy();
+
+   /**
+    * @brief Method to restart reading from the beginning (for backing up).
+    * This is needed as libpng requires sequential read from start of the
+    * image.
+    */
+   void restart();
+
+   /**
+    * @note this method assumes that setImageRectangle has been called on
+    * theTile.
+    */
+   void fillTile(const ossimIrect& clip_rect, ossimImageData* tile);
+
+   template <class T> void copyLines(T dummy,  ossim_uint32 stopLine);
+   template <class T> void copyLinesWithAlpha(T, ossim_uint32 stopLine);
+
+   /**
+    * @brief Callback method for reading from a stream.  This allows us to choose
+    * the stream; hence, writing to a file or memory.  This will be passed
+    * to libpng's png_set_read_fn.
+    */
+   static void pngReadData(
+      png_structp png_ptr, png_bytep data, png_size_t length);
+
+   ossimRefPtr<ossimImageData>  m_tile;
+   ossimRefPtr<ossimImageData>  m_cacheTile;
+
+   ossim_uint8*  m_lineBuffer;
+   ossim_uint32  m_lineBufferSizeInBytes;
+
+   std::istream*  m_str;
+   std::streamoff m_restartPosition;
+   bool           m_ownsStream;
+   
+   ossimIrect    m_bufferRect;
+   ossimIrect    m_imageRect;
+   ossim_uint32  m_numberOfInputBands;
+   ossim_uint32  m_numberOfOutputBands;
+   ossim_uint32  m_bytePerPixelPerBand;
+   ossimIpt      m_cacheSize;
+
+
+   ossimAppFixedTileCache::ossimAppFixedCacheId m_cacheId;
+
+   png_structp      m_pngReadPtr;
+   png_infop        m_pngReadInfoPtr;
+   ossim_int8       m_pngColorType;
+   ossim_uint32     m_currentRow; // 0 at start or first line
+   ossimScalarType  m_outputScalarType;
+   ossim_int32      m_interlacePasses;
+   ossim_int8       m_bitDepth;
+   ossimPngReadMode m_readMode;
+
+   std::vector<ossim_float64> m_maxPixelValue;
+
+   bool m_swapFlag;
+
+   // If true the alpha channel will be passed on as a band.
+   bool m_useAlphaChannelFlag;
+   
+TYPE_DATA
+};
+
+#endif /* #ifndef ossimPngReader_HEADER */
+
diff --git a/ossim_plugins/png/ossimPngReaderFactory.cpp b/ossim_plugins/png/ossimPngReaderFactory.cpp
new file mode 100644
index 0000000..921d4c2
--- /dev/null
+++ b/ossim_plugins/png/ossimPngReaderFactory.cpp
@@ -0,0 +1,164 @@
+//----------------------------------------------------------------------------
+//
+// License:  See top level LICENSE.txt file
+//
+// Author:  David Burken
+//
+// Description: Factory for OSSIM Portable Network Graphics (PNG) reader
+// (tile source).
+//----------------------------------------------------------------------------
+// $Id: ossimPngReaderFactory.cpp 22633 2014-02-20 00:57:42Z dburken $
+
+#include "ossimPngReaderFactory.h"
+#include "ossimPngReader.h"
+#include <ossim/base/ossimKeywordlist.h>
+#include <ossim/base/ossimRefPtr.h>
+#include <ossim/base/ossimString.h>
+#include <ossim/imaging/ossimImageHandler.h>
+#include <ossim/base/ossimTrace.h>
+#include <ossim/base/ossimKeywordNames.h>
+
+static const ossimTrace traceDebug("ossimPngReaderFactory:debug");
+
+RTTI_DEF1(ossimPngReaderFactory,
+          "ossimPngReaderFactory",
+          ossimImageHandlerFactoryBase);
+
+ossimPngReaderFactory* ossimPngReaderFactory::theInstance = 0;
+
+ossimPngReaderFactory::~ossimPngReaderFactory()
+{
+   theInstance = 0;
+}
+
+ossimPngReaderFactory* ossimPngReaderFactory::instance()
+{
+   if(!theInstance)
+   {
+      theInstance = new ossimPngReaderFactory;
+   }
+   return theInstance;
+}
+   
+ossimImageHandler* ossimPngReaderFactory::open(const ossimFilename& fileName,
+                                               bool openOverview)const
+{
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimPngReaderFactory::open(filename) DEBUG: entered..."
+         << "\ntrying ossimPngReader"
+         << std::endl;
+   }
+   
+   ossimRefPtr<ossimImageHandler> reader = new ossimPngReader;
+   reader->setOpenOverviewFlag(openOverview);
+   if(reader->open(fileName) == false)
+   {
+      reader = 0;
+   }
+   
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimPngReaderFactory::open(filename) DEBUG: leaving..."
+         << std::endl;
+   }
+   
+   return reader.release();
+}
+
+ossimImageHandler* ossimPngReaderFactory::open(const ossimKeywordlist& kwl,
+                                               const char* prefix)const
+{
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimPngReaderFactory::open(kwl, prefix) DEBUG: entered..."
+         << "Trying ossimPngReader"
+         << std::endl;
+   }
+
+   ossimRefPtr<ossimImageHandler> reader = new ossimPngReader();
+   if(reader->loadState(kwl, prefix) == false)
+   {
+      reader = 0;
+   }
+   
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimPngReaderFactory::open(kwl, prefix) DEBUG: leaving..."
+         << std::endl;
+   }
+   
+   return reader.release();
+}
+
+ossimRefPtr<ossimImageHandler> ossimPngReaderFactory::open(
+   std::istream* str, std::streamoff restartPosition, bool youOwnIt ) const
+{
+   ossimRefPtr<ossimImageHandler> result = 0;
+   
+   ossimRefPtr<ossimPngReader> reader = new ossimPngReader();
+   if ( reader->open( str, restartPosition, youOwnIt ) )
+   {
+      result = reader.get();
+   }
+   
+   return result;
+}
+
+ossimObject* ossimPngReaderFactory::createObject(
+   const ossimString& typeName)const
+{
+   ossimRefPtr<ossimObject> result = 0;
+   if(typeName == "ossimPngReader")
+   {
+      result = new ossimPngReader;
+   }
+   return result.release();
+}
+
+ossimObject* ossimPngReaderFactory::createObject(const ossimKeywordlist& kwl,
+                                                 const char* prefix)const
+{
+   return this->open(kwl, prefix);
+}
+ 
+void ossimPngReaderFactory::getTypeNameList(std::vector<ossimString>& typeList)const
+{
+   typeList.push_back(ossimString("ossimPngReader"));
+}
+
+void ossimPngReaderFactory::getSupportedExtensions(
+   ossimImageHandlerFactoryBase::UniqueStringList& extensionList)const
+{
+   extensionList.push_back(ossimString("png"));
+}
+
+void ossimPngReaderFactory::getImageHandlersBySuffix(ossimImageHandlerFactoryBase::ImageHandlerList& result,
+                                      const ossimString& ext)const
+{
+   ossimString testExt = ext.downcase();
+   if(ext == "png")
+   {
+      result.push_back(new ossimPngReader);
+   }
+}
+
+void ossimPngReaderFactory::getImageHandlersByMimeType(ossimImageHandlerFactoryBase::ImageHandlerList& result,
+                                        const ossimString& mimeType)const
+{
+   ossimString testExt = mimeType.downcase();
+   if(testExt == "image/png")
+   {
+      result.push_back(new ossimPngReader);
+   }
+}
+
+ossimPngReaderFactory::ossimPngReaderFactory(){}
+
+ossimPngReaderFactory::ossimPngReaderFactory(const ossimPngReaderFactory&){}
+
+void ossimPngReaderFactory::operator=(const ossimPngReaderFactory&){}
diff --git a/ossim_plugins/png/ossimPngReaderFactory.h b/ossim_plugins/png/ossimPngReaderFactory.h
new file mode 100644
index 0000000..ce2bc77
--- /dev/null
+++ b/ossim_plugins/png/ossimPngReaderFactory.h
@@ -0,0 +1,122 @@
+//----------------------------------------------------------------------------
+//
+// License:  See top level LICENSE.txt file
+//
+// Author:  David Burken
+//
+// Description: Factory for OSSIM Portable Network Graphics plugin (PNG)
+// reader.
+//----------------------------------------------------------------------------
+// $Id: ossimPngReaderFactory.h 22633 2014-02-20 00:57:42Z dburken $
+#ifndef ossimPngReaderFactory_HEADER
+#define ossimPngReaderFactory_HEADER 1
+
+#include <ossim/imaging/ossimImageHandlerFactoryBase.h>
+
+class ossimString;
+class ossimFilename;
+class ossimKeywordlist;
+
+/** @brief Factory for PNG image reader. */
+class ossimPngReaderFactory : public ossimImageHandlerFactoryBase
+{
+public:
+
+   /** @brief virtual destructor */
+   virtual ~ossimPngReaderFactory();
+
+   /**
+    * @brief static method to return instance (the only one) of this class.
+    * @return pointer to instance of this class.
+    */
+   static ossimPngReaderFactory* instance();
+
+   /**
+    * @brief open that takes a file name.
+    * @param file The file to open.
+    * @param openOverview If true image handler will attempt to open overview.
+    * default = true 
+    * @return pointer to image handler on success, NULL on failure.
+    */
+   virtual ossimImageHandler* open(const ossimFilename& fileName,
+                                   bool openOverview=true) const;
+
+   /**
+    * @brief open that takes a keyword list and prefix.
+    * @param kwl The keyword list.
+    * @param prefix the keyword list prefix.
+    * @return pointer to image handler on success, NULL on failure.
+    */
+   virtual ossimImageHandler* open(const ossimKeywordlist& kwl,
+                                   const char* prefix=0)const;
+
+   /**
+    *  @brief Open method.
+    *
+    *  This open takes a stream, position and a flag.
+    *
+    *  @param str Open stream to image.
+    *
+    *  @param restartPosition Typically 0, this is the stream offset to the
+    *  front of the image.
+    *
+    *  @param youOwnIt If true the opener takes owner ship of the stream
+    *  pointer and will destroy on close.
+    *  
+    *  @return This implementation returns an ossimRefPtr with a null pointer.
+    */
+   virtual ossimRefPtr<ossimImageHandler> open( std::istream* str,
+                                                std::streamoff restartPosition,
+                                                bool youOwnit ) const;   
+
+   /**
+    * @brief createObject that takes a class name (ossimPngReader)
+    * @param typeName Should be "ossimPngReader".
+    * @return pointer to image writer on success, NULL on failure.
+    */
+   virtual ossimObject* createObject(const ossimString& typeName)const;
+   
+   /**
+    * @brief Creates and object given a keyword list and prefix.
+    * @param kwl The keyword list.
+    * @param prefix the keyword list prefix.
+    * @return pointer to image handler on success, NULL on failure.
+    */
+   virtual ossimObject* createObject(const ossimKeywordlist& kwl,
+                                     const char* prefix=0)const;
+   
+   /**
+    * @brief Adds ossimPngWriter to the typeList.
+    * @param typeList List to add to.
+    */
+   virtual void getTypeNameList(std::vector<ossimString>& typeList)const;
+
+   /**
+    * @brief Method to add supported extension to the list, like "png".
+    *
+    * @param extensionList The list to add to.
+    */
+   virtual void getSupportedExtensions(
+      ossimImageHandlerFactoryBase::UniqueStringList& extensionList)const;
+  
+   virtual void getImageHandlersBySuffix(ImageHandlerList& result,
+                                         const ossimString& ext)const;
+   virtual void getImageHandlersByMimeType(ImageHandlerList& result,
+                                           const ossimString& mimeType)const;
+protected:
+   /** @brief hidden from use default constructor */
+   ossimPngReaderFactory();
+
+   /** @brief hidden from use copy constructor */
+   ossimPngReaderFactory(const ossimPngReaderFactory&);
+
+   /** @brief hidden from use copy constructor */
+   void operator=(const ossimPngReaderFactory&);
+
+   /** static instance of this class */
+   static ossimPngReaderFactory* theInstance;
+
+TYPE_DATA
+};
+
+#endif /* end of #ifndef ossimPngReaderFactory_HEADER */
diff --git a/ossim_plugins/png/ossimPngWriter.cpp b/ossim_plugins/png/ossimPngWriter.cpp
new file mode 100644
index 0000000..cf651ca
--- /dev/null
+++ b/ossim_plugins/png/ossimPngWriter.cpp
@@ -0,0 +1,1017 @@
+//----------------------------------------------------------------------------
+//
+// License:  See top level LICENSE.txt file
+//
+// Author:  David Burken
+// Contributor:  David A. Horner - http://dave.thehorners.com
+//
+// Description: OSSIM Portable Network Graphics (PNG) writer.
+//
+//----------------------------------------------------------------------------
+// $Id: ossimPngWriter.cpp 22466 2013-10-24 18:23:51Z dburken $
+
+#include "ossimPngWriter.h"
+#include <ossim/base/ossimBooleanProperty.h>
+#include <ossim/base/ossimKeywordNames.h>
+#include <ossim/base/ossimTrace.h>
+#include <ossim/base/ossimDpt.h>
+#include <ossim/base/ossimEndian.h>
+#include <ossim/base/ossimKeywordlist.h>
+#include <ossim/base/ossimScalarTypeLut.h>
+#include <ossim/base/ossimStringProperty.h>
+#include <ossim/base/ossimNumericProperty.h>
+#include <ossim/projection/ossimMapProjection.h>
+#include <ossim/imaging/ossimImageData.h>
+#include <ossim/imaging/ossimImageSource.h>
+#include <ossim/imaging/ossimScalarRemapper.h>
+#include <zlib.h>
+#include <cstdlib>
+#include <ctime>
+
+RTTI_DEF1(ossimPngWriter,
+	  "ossimPngWriter",
+	  ossimImageFileWriter)
+
+static const char DEFAULT_FILE_NAME[] = "output.png";
+static const ossim_int32 DEFAULT_PNG_QUALITY = 75;
+
+static const char COMPRESSION_LEVEL_KW[] = "compression_level";
+static const char ADD_ALPHA_CHANNEL_KW[] = "add_alpha_channel";
+
+//---
+// For trace debugging (to enable at runtime do:
+// your_app -T "ossimPngWriter:debug" your_app_args
+//---
+static ossimTrace traceDebug("ossimPngWriter:debug");
+
+//---
+// For the "ident" program which will find all exanded $Id: ossimPngWriter.cpp 22466 2013-10-24 18:23:51Z dburken $ macros and print
+// them.
+//---
+#if OSSIM_ID_ENABLED
+static const char OSSIM_ID[] = "$Id: ossimPngWriter.cpp 22466 2013-10-24 18:23:51Z dburken $";
+#endif
+
+ossimPngWriter::ossimPngWriter()
+   : ossimImageFileWriter(),
+     theOutputStream(0),
+     theOwnsStreamFlag(false),
+     theCompressionLevel(Z_BEST_COMPRESSION),
+     theInterlaceSupport(PNG_INTERLACE_NONE),
+     theCompressionStratagy(Z_FILTERED),
+     thePngFilter(PNG_FILTER_NONE),
+     theGammaFlag(false),
+     theGamma(0.0),
+     theTimeFlag(true),
+     theAlphaChannelFlag(false),     
+     theBackgroundFlag(false),
+     theBackgroundRed(0),
+     theBackgroundGreen(0),
+     theBackgroundBlue(0),
+     theBackgroundGray(0),
+     theTransparentFlag(false),
+     theTransparentRed(0),
+     theTransparentGreen(0),
+     theTransparentBlue(0),
+     theTransparentGray(0)
+
+{
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimPngWriter::ossimPngWriter entered" << std::endl;
+#if OSSIM_ID_ENABLED
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "OSSIM_ID:  "
+         << OSSIM_ID
+         << std::endl;
+#endif
+   }
+
+   // Since there is no internal geometry set the flag to write out one.
+   setWriteExternalGeometryFlag(true);
+
+   theOutputImageType = "ossim_png";
+}
+
+ossimPngWriter::~ossimPngWriter()
+{
+   // This will flush stream and delete it if we own it.
+   close();
+}
+
+ossimString ossimPngWriter::getShortName() const
+{
+   return ossimString("ossim_png_writer");
+}
+
+ossimString ossimPngWriter::getLongName() const
+{
+   return ossimString("ossim png writer");
+}
+
+ossimString ossimPngWriter::getClassName() const
+{
+   return ossimString("ossimPngWriter");
+}
+
+bool ossimPngWriter::writeFile()
+{
+   if( !theInputConnection || (getErrorStatus() != ossimErrorCodes::OSSIM_OK) )
+   {
+      return false;
+   }
+
+   //---
+   // Make sure we can open the file.  Note only the master process is used for
+   // writing...
+   //---
+   if(theInputConnection->isMaster())
+   {
+      if (!isOpen())
+      {
+         open();
+      }
+   }
+
+   return writeStream();
+}
+
+bool ossimPngWriter::writeStream()
+{
+   static const char MODULE[] = "ossimPngWriter::write";
+   
+   if (!theInputConnection) // Must have a sequencer...
+   {
+      if (traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG)
+            << MODULE << " DEBUG:\ntheInputConnection is NULL!" << endl;
+      }
+      return false;
+   }
+   
+   //---
+   // Make sure we have a stream.  Note only the master process is used for
+   // writing...
+   //---
+   if(theInputConnection->isMaster())
+   {
+      if (!theOutputStream)         
+      {
+         ossimNotify(ossimNotifyLevel_WARN)
+            << MODULE << " ERROR:"
+            << "\nNULL output stream!"
+            << "\nReturning from method." << std::endl;
+
+         return false;
+      }
+   }
+   
+   // make sure we have a region of interest
+   if(theAreaOfInterest.hasNans())
+   {
+      theInputConnection->initialize();
+      theAreaOfInterest = theInputConnection->getAreaOfInterest();
+   }
+   else
+   {
+      theInputConnection->setAreaOfInterest(theAreaOfInterest);
+   }
+
+   if(theAreaOfInterest.hasNans()) // Must have an area of interest...
+   {
+      if (traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG)
+            << MODULE << " ERROR:  Area of interest has nans!"
+            << "Area of interest:  "
+            << theAreaOfInterest
+            << "\nReturning..." << endl;
+      }
+
+      return false;
+   }
+
+   // Get the number of bands.  Must be one or three for this writer.
+   ossim_int32 bands = theInputConnection->getNumberOfOutputBands();
+   if (bands != 1 && bands != 3)
+   {
+      ossimNotify(ossimNotifyLevel_WARN)
+         << MODULE << " Range Error:"
+         << "\nInvalid number of input bands!  Must be one or three."
+         << "\nInput bands = " << bands
+         << "\nReturning from method." << endl;
+      
+      return false;
+   }
+
+   //---
+   // PNG only supports unsigned 8 and 16 bit images, so scale if needed.
+   // Note: This needs to be done on all processes.
+   //---
+   ossimScalarType inputScalar = theInputConnection->getOutputScalarType();
+   if( ( (inputScalar != OSSIM_UINT8)  &&
+         (inputScalar != OSSIM_UINT16) &&
+         (inputScalar != OSSIM_USHORT11) ) ||
+       ( (inputScalar != OSSIM_UINT8) && theScaleToEightBitFlag )
+      )
+   {
+      if (traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_WARN)
+            << " WARNING:"
+            << "\nData is being scaled to 8 bit!"
+            << "\nOriginal scalar type:  "
+            << ossimScalarTypeLut::instance()->
+            getEntryString(inputScalar).c_str()
+            << std::endl;
+      }
+
+      //---
+      // Attach a scalar remapper to the end of the input chain.  This will
+      // need to be unattached and deleted at the end of this.
+      //---
+      ossimImageSource* inputSource = new ossimScalarRemapper;
+      inputSource->connectMyInputTo(0, theInputConnection->getInput(0));
+      theInputConnection->connectMyInputTo(0, inputSource);
+      theInputConnection->initialize();
+   }
+
+   setProcessStatus(ossimProcessInterface::PROCESS_STATUS_EXECUTING);
+   setPercentComplete(0.0);
+
+   if(theInputConnection->isMaster())
+   {
+      ossimScalarType outputScalar = theInputConnection->getOutputScalarType();
+      bool swapFlag = doSwap(outputScalar);
+      ossim_int32 imageHeight
+         = theAreaOfInterest.lr().y - theAreaOfInterest.ul().y + 1;
+      ossim_int32 imageWidth
+         = theAreaOfInterest.lr().x - theAreaOfInterest.ul().x + 1;
+      ossim_int32 bands = theInputConnection->getNumberOfOutputBands();
+      ossim_int32 tileHeight    = theInputConnection->getTileHeight();
+      ossim_int32 bytesPerPixel = ossim::scalarSizeInBytes(outputScalar);
+      ossim_int32 bytesPerRow   = bands*imageWidth*bytesPerPixel;
+      ossim_int32 colorType     = getColorType(bands);
+
+      if ( bands == 1 )
+      {
+         theTransparentGray = static_cast<ossim_uint16>( theInputConnection->getNullPixelValue() );
+      }
+      else
+      if ( bands == 3 )
+      {
+         theTransparentRed  = static_cast<ossim_uint16>( theInputConnection->getNullPixelValue(0) );
+         theTransparentGray = static_cast<ossim_uint16>( theInputConnection->getNullPixelValue(1) );
+         theTransparentBlue = static_cast<ossim_uint16>( theInputConnection->getNullPixelValue(2) );
+      }
+
+      if ( theAlphaChannelFlag == true )
+      {
+         bands += 1; // add in the alpha channel
+         bytesPerRow += imageWidth*bytesPerPixel;
+      }
+
+      // Allocate a buffer (tile) to hold a row of bip-format tiles.
+      ossimRefPtr<ossimImageData> bipTile =
+         new ossimImageData(0,
+                            outputScalar,
+                            bands,
+                            imageWidth,
+                            tileHeight);
+      bipTile->initialize();
+
+      //---
+      // Begin of png related stuff.
+      //---
+      png_structp pp   = png_create_write_struct (PNG_LIBPNG_VER_STRING, 0, 0, 0);
+      png_infop   info = png_create_info_struct (pp);
+
+      if ( setjmp( png_jmpbuf(pp) ) )
+      {
+         ossimNotify(ossimNotifyLevel_WARN)
+            << "Error writing image:  " << theFilename.c_str()
+            << std::endl;
+         return false;
+      }
+
+      //---
+      // Pass the static write and flush to libpng to allow us to use our
+      // stream instead of doing "png_init_io (pp, theOutputFilePtr);"
+      //---
+      png_set_write_fn( pp,
+                        (png_voidp)theOutputStream,
+                        (png_rw_ptr) &ossimPngWriter::pngWriteData,
+                        (png_flush_ptr)&ossimPngWriter::pngFlush);
+
+      // Set the compression level.
+      png_set_compression_level(pp, theCompressionLevel);
+
+      //---
+      // Set the filtering.
+      // Note that palette images should usually not be filtered.
+      if (isLutEnabled())
+      {
+         png_set_filter(pp, PNG_FILTER_TYPE_BASE, PNG_FILTER_NONE);
+         png_set_compression_strategy(pp, Z_DEFAULT_STRATEGY);
+      }
+      else
+      {
+         // leave default filter selection alone
+         png_set_compression_strategy(pp, Z_FILTERED);
+      }
+
+      if (traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG)
+            << MODULE << " DEBUG: "
+            << "\nInput scalar:  "
+            << ossimScalarTypeLut::instance()->
+            getEntryString(inputScalar).c_str()
+            << "\nOutput scalar: "
+            <<  ossimScalarTypeLut::instance()->
+            getEntryString(outputScalar).c_str()
+            << "\nOutput Rect:  " << theAreaOfInterest
+            << "\nSwap flag:  " << swapFlag
+            << "\nbytesPerRow:         " << bytesPerRow
+            << "\nimageWidth:          " << imageWidth
+            << "\nimageHeight:         " << imageHeight
+            << "\ngitDepth:            " << getBitDepth(outputScalar)
+            << "\ngetColorType(bands): " << colorType
+            << endl;
+      }
+
+      png_set_IHDR(pp,
+                   info,
+                   imageWidth,
+                   imageHeight,
+                   getBitDepth(outputScalar),
+                   colorType,
+                   theInterlaceSupport,
+                   PNG_COMPRESSION_TYPE_DEFAULT,
+                   PNG_FILTER_TYPE_DEFAULT);
+
+      // Set the palette png_set_PLTE() in writeOptionalChunks()
+      writeOptionalChunks(pp, info);
+
+      png_write_info(pp, info);
+
+      // png_set_packing(pp);
+
+      // Write the image.
+      if(theInterlaceSupport) // interlaced...
+      {
+         // Requires reading whole image into memory...
+         ossimNotify(ossimNotifyLevel_WARN)
+            << "Interlace support not implemented yet!"
+            << std::endl;
+         return false;
+      }
+      else // not interlaced...
+      {
+         theInputConnection->setAreaOfInterest(theAreaOfInterest);
+         theInputConnection->setToStartOfSequence();
+         ossim_uint32 maxY = theInputConnection->getNumberOfTilesVertical();
+
+         //---
+         // Loop through and grab a row of tiles and copy to the buffer.
+         // Then write the buffer to the png file.
+         // Get the next row of tiles ... until finished.
+         //---
+
+         // Row loop, in line direction...
+         for (ossim_uint32 i=0; ( (i<maxY) && (!needsAborting()) ); ++i)
+         {
+            ossimIrect buf_rect = theAreaOfInterest;
+            buf_rect.set_uly(theAreaOfInterest.ul().y+i*tileHeight);
+            buf_rect.set_lry(buf_rect.ul().y + tileHeight - 1);
+ 
+            bipTile->setImageRectangle(buf_rect);
+            void* bipBuf = bipTile->getBuf();
+
+            
+            // Grab lines of data that span the entire width of the image.
+            ossimRefPtr<ossimImageData> t = theInputConnection->getTile( buf_rect );
+            if ( t.valid() )
+            {
+               if ( theAlphaChannelFlag )
+               {
+                  t->computeAlphaChannel();
+                  t->unloadTileToBipAlpha(bipBuf, buf_rect, buf_rect);
+               }
+               else
+               {
+                  t->unloadTile( bipBuf, buf_rect, buf_rect, OSSIM_BIP);
+               }
+
+               // Copy the buffer to the png file.
+               ossim_int32 lines_to_copy =
+                  min( (buf_rect.lr().y-buf_rect.ul().y+1),
+                       (theAreaOfInterest.lr().y-buf_rect.ul().y+1) );
+               
+               if (traceDebug())
+               {
+                  ossimNotify(ossimNotifyLevel_DEBUG)
+                     << MODULE
+                     << "buf_rect:       " << buf_rect
+                     << "lines_to_copy:  " << lines_to_copy << endl;
+               }
+
+               if(!needsAborting())
+               {
+                  if(swapFlag)
+                  {
+                     ossimEndian endian;
+                     endian.swap((ossim_uint16*)bipBuf,
+                                 imageWidth*lines_to_copy*bands);
+                  }
+
+                  ossim_uint8* buf = (ossim_uint8*)bipBuf;
+                  ossim_int32 buf_offset = 0;
+                  for (ossim_int32 line=0; line<lines_to_copy; ++line)
+                  {
+                     png_bytep rowp = (png_bytep)&buf[buf_offset];
+                     png_write_row(pp, rowp);
+                     buf_offset += bytesPerRow;
+                  }
+
+               } // if ( !getProcessStatus() )
+
+               double dPercentComplete = (100.0*(i+1)) / maxY;
+               setPercentComplete( dPercentComplete );
+ 
+            } // if ( t.valid() )
+
+         } // End of loop through tiles in the y direction.
+
+      } // Not interlace write block.
+
+      png_write_end(pp, 0);
+      png_destroy_write_struct(&pp, &info);
+
+      close();
+
+   } // End of if(theInputConnection->isMaster()) block.
+
+   else   // slave process
+   {
+      theInputConnection->slaveProcessTiles();
+   }
+
+   if(needsAborting())
+   {
+      setProcessStatus(ossimProcessInterface::PROCESS_STATUS_ABORTED);
+   }
+   else
+   {
+      setProcessStatus(ossimProcessInterface::PROCESS_STATUS_NOT_EXECUTING);
+   }
+
+   return true;
+}
+
+void ossimPngWriter::pngWriteData(png_structp png_ptr,
+                                  png_bytep   data,
+                                  png_size_t  length)
+{
+   std::ostream* fp = (std::ostream*)png_get_io_ptr(png_ptr);
+
+   fp->write((char*)data, length);
+}
+
+void ossimPngWriter::pngFlush( png_structp png_ptr )
+{
+   std::ostream* fp = (std::ostream*)png_get_io_ptr(png_ptr);
+   fp->flush();
+}
+
+bool ossimPngWriter::saveState(ossimKeywordlist& kwl,
+                               const char* prefix)const
+{
+   kwl.add( prefix,
+            ADD_ALPHA_CHANNEL_KW,
+            ossimString::toString( theAlphaChannelFlag ),
+            true );
+
+   return ossimImageFileWriter::saveState(kwl, prefix);
+}
+
+bool ossimPngWriter::loadState(const ossimKeywordlist& kwl,
+                               const char* prefix)
+{
+   const char* value;
+
+   value = kwl.find(prefix, ADD_ALPHA_CHANNEL_KW);
+   if(value)
+   {
+      setAlphaChannelFlag( ossimString(value).toBool() );
+   }
+
+   theOutputImageType = "png";
+
+   return ossimImageFileWriter::loadState(kwl, prefix);
+}
+
+bool ossimPngWriter::isOpen() const
+{
+   if (theOutputStream)
+   {
+     return true;
+   }
+   return false;
+}
+
+bool ossimPngWriter::open()
+{
+   close();
+
+   // Check for empty filenames.
+   if (theFilename.empty())
+   {
+      return false;
+   }
+
+   // ossimOFStream* os = new ossimOFStream();
+   std::ofstream* os = new std::ofstream();
+   os->open(theFilename.c_str(), ios::out | ios::binary);
+   if(os->is_open())
+   {
+      theOutputStream = os;
+      theOwnsStreamFlag = true;
+      return true;
+   }
+   delete os;
+   os = 0;
+
+   return false;
+}
+
+void ossimPngWriter::close()
+{
+   if (theOutputStream)      
+   {
+      theOutputStream->flush();
+
+      if (theOwnsStreamFlag)
+      {
+         delete theOutputStream;
+         theOutputStream = 0;
+         theOwnsStreamFlag = false;
+      }
+   }
+}
+
+void ossimPngWriter::getImageTypeList(std::vector<ossimString>& imageTypeList)const
+{
+   imageTypeList.push_back(ossimString("ossim_png"));
+}
+
+ossimString ossimPngWriter::getExtension() const
+{
+   return ossimString("png");
+}
+
+bool ossimPngWriter::hasImageType(const ossimString& imageType) const
+{
+   if ( (imageType == "ossim_png") || (imageType == "image/png") )
+   {
+      return true;
+   }
+
+   return false;
+}
+
+void ossimPngWriter::setProperty(ossimRefPtr<ossimProperty> property)
+{
+   if (!property)
+   {
+      return;
+   }
+
+   if (property->getName() == COMPRESSION_LEVEL_KW)
+   {
+      setCompressionLevel(property->valueToString());
+   }
+   else
+   if (property->getName() == ADD_ALPHA_CHANNEL_KW)
+   {
+      setAlphaChannelFlag( property->valueToString().toBool() );
+   }
+   else
+   {
+      ossimImageFileWriter::setProperty(property);
+   }
+}
+
+ossimRefPtr<ossimProperty> ossimPngWriter::getProperty(const ossimString& name)const
+{
+   if (name == COMPRESSION_LEVEL_KW)
+   {
+      ossimStringProperty* stringProp =
+         new ossimStringProperty(name,
+                                 getCompressionLevel(),
+                                 false); // editable flag
+      stringProp->addConstraint(ossimString("z_no_compression"));
+      stringProp->addConstraint(ossimString("z_best_speed"));
+      stringProp->addConstraint(ossimString("z_best_compression"));
+      stringProp->addConstraint(ossimString("z_default_compression"));
+      return stringProp;
+   }
+   else if (name == ADD_ALPHA_CHANNEL_KW)
+   {
+      return new ossimBooleanProperty(ADD_ALPHA_CHANNEL_KW,
+                                      theAlphaChannelFlag);
+   }
+   return ossimImageFileWriter::getProperty(name);
+}
+
+void ossimPngWriter::getPropertyNames(std::vector<ossimString>& propertyNames)const
+{
+   propertyNames.push_back(ossimString(COMPRESSION_LEVEL_KW));
+   propertyNames.push_back(ossimString(ADD_ALPHA_CHANNEL_KW));
+   ossimImageFileWriter::getPropertyNames(propertyNames);
+}
+
+bool ossimPngWriter::doSwap(ossimScalarType outputScalar) const
+{
+   bool result = false;
+   if (outputScalar != OSSIM_UINT8)
+   {
+      if(ossim::byteOrder() == OSSIM_LITTLE_ENDIAN)
+      {
+         result = true;
+      }
+   }
+   return result;
+}
+
+bool ossimPngWriter::isLutEnabled()const
+{
+   // Temp drb...
+   return false;
+}
+
+void ossimPngWriter::writeOptionalChunks(png_structp pp, png_infop info)
+{
+   //---
+   // NOTE:
+   // Per PNG spec
+   // Chunks with no explicit restrictions (``anywhere'') are nonetheless
+   // implicitly constrained to come after the PNG signature and IHDR
+   // chunk, before the IEND chunk, and not to fall between multiple
+   // IDAT chunks.
+   //---
+
+   //---
+   // Write gamma chunk (gAMMA)
+   // Location:   Before first IDAT and PLTE
+   // Multiple:   no
+   //---
+   writeGammaChunk(pp, info);
+
+   //---
+   // Write significant bits (sBIT)
+   // Location: before PLTE and first IDAT
+   // Multiple: no
+   //---
+   writeSignificantBits(pp, info);
+
+   // Set the palette png_set_PLTE()
+
+   //---
+   // Write transparent color chunk (tRNS)
+   // Location: After PLTE, before first IDAT.
+   // Multiple: 
+   //---
+   writeTransparentColorChunk(pp, info);
+
+   //---
+   // Write background color chunk (bKGD)
+   // Location: After PLTE, before first IDAT.
+   // Multiple: no
+   //---
+   writeBackgroundColorChunk(pp, info);
+   
+   //---
+   // Write time stamp chunk (tIME).
+   // Location: anywhere
+   // Multiple: no
+   // 
+   //---
+   writeTimeStampChunk(pp, info);
+   
+   //---
+   // Write any text (tEXt, zTXt).
+   // Location: anywhere
+   // Multiple: yes
+   //---
+   writeLatinTextChunk(pp, info);
+   
+   //---
+   // Write any text (iTXt).
+   // Location: anywhere
+   // Multiple: yes
+   //---
+   writeInternationalTextChunk(pp, info);
+   
+   //---
+   // Write histogram (hIST)
+   // Location: after PLTE, before first IDAT
+   // Multiple: no
+   //---
+   writeHistogram(pp, info);
+
+   //---
+   // Write suggested palette (sPLT)
+   // Location: before first IDAT
+   // Multiple: yes
+   //---
+   writeSuggestedPalette(pp, info);
+   
+   //---
+   // Write physical pixel dimensions (pHYs)
+   // Location: before first IDAT
+   // Multiple: no
+   //---
+   writePhysicalPixelDimensions(pp, info);
+   
+   //---
+   // Write physical scale (sCAL)
+   // Location: before first IDAT
+   // Multiple: no
+   //---
+   writePhysicalScale(pp, info);
+   
+   //---
+   // Write image offset (oFFs)
+   // Location: before first IDAT
+   // Multiple: no
+   //---
+   writeImageOffset(pp, info);
+   
+   //---
+   // Write pixel calibration (pCAL)
+   // Location: after PLTE, before first IDAT
+   // Multiple: no
+   //---
+   writePixelCalibration(pp, info);
+   
+   //---
+   // Write fractal parameters (fRAc)
+   // Location: anywhere
+   // Multiple: yes
+   //---
+   writeFractalParameters(pp, info);
+}
+
+void ossimPngWriter::writeTransparentColorChunk(png_structp pp, png_infop info)
+{
+   if (theTransparentFlag)
+   {
+      png_color_16 transparent;
+      transparent.red   = (png_uint_16)theTransparentRed;
+      transparent.green = (png_uint_16)theTransparentGreen;
+      transparent.blue  = (png_uint_16)theTransparentBlue;
+      transparent.gray  = (png_uint_16)theTransparentGray;
+      png_set_tRNS( pp, info, NULL, 0, &transparent );
+   }
+}
+
+void ossimPngWriter::writeBackgroundColorChunk(png_structp pp, png_infop info)
+{
+   if(theBackgroundFlag)
+   {
+      png_color_16 background;
+      background.red   = theBackgroundRed;
+      background.green = theBackgroundGreen;
+      background.blue  = theBackgroundBlue;
+      background.gray  = theBackgroundGray;
+      png_set_bKGD( pp, info, &background );
+   }
+}
+
+void ossimPngWriter::writeGammaChunk(png_structp pp, png_infop info)
+{
+   if(theGammaFlag)
+   {
+      png_set_gAMA(pp, info, theGamma);
+   }
+}
+
+void ossimPngWriter::writeTimeStampChunk(png_structp pp,
+                                         png_infop info)
+{
+   if(theTimeFlag)
+   {
+      png_time  modtime;
+      time_t t;
+      time(&t);
+      png_convert_from_time_t(&modtime, t);
+      png_set_tIME(pp, info, &modtime); 
+   }
+}
+
+void ossimPngWriter::writeLatinTextChunk(png_structp /* pp */,
+                                         png_infop /* info */)
+{}
+
+void ossimPngWriter::writeInternationalTextChunk(png_structp /* pp */,
+                                                 png_infop /* info */)
+{}
+
+void ossimPngWriter::writeHistogram(png_structp /* pp */,
+                                    png_infop /* info */)
+{}
+
+void ossimPngWriter::writeSignificantBits(png_structp pp,
+                                          png_infop info)
+{
+   // Must be called before PLTE and first IDAT.  No multiple sBIT chunks.
+   if (theInputConnection->getOutputScalarType() != OSSIM_UINT8)
+   {
+      ossim_float64 max = theInputConnection->getMaxPixelValue();
+      if (max <= 65535)
+      {
+         ossim_uint16 max16 = static_cast<ossim_uint16>(max);
+         png_byte bits      = 16;
+         ossim_uint16 s     = 0xffff;
+         while ( (s != 0x0001) && (s >= max16) )
+         {
+            s = s >> 1;
+            if (s < max) break;
+            --bits;
+         }
+         
+         // destroyed by png_destroy_write_struct ??? (drb)
+         png_color_8* sig_bit = new png_color_8; 
+         sig_bit->red   = bits;
+         sig_bit->green = bits;
+         sig_bit->blue  = bits;
+         sig_bit->gray  = bits;
+         sig_bit->alpha = bits;
+         png_set_sBIT(pp, info, sig_bit);
+      }
+   }
+}
+
+void ossimPngWriter::writeSuggestedPalette(png_structp /* pp */,
+                                           png_infop /* info */)
+{}
+
+void ossimPngWriter::writePhysicalPixelDimensions(png_structp /* pp */,
+                                                  png_infop /* info */)
+{}
+
+void ossimPngWriter::writePhysicalScale(png_structp /* pp */,
+                                        png_infop /* info */)
+{}
+
+void ossimPngWriter::writeImageOffset(png_structp /* pp */,
+                                      png_infop /* info */)
+{}
+
+void ossimPngWriter::writePixelCalibration(png_structp /* pp */,
+                                           png_infop /* info */)
+{}
+
+void ossimPngWriter::writeFractalParameters(png_structp /* pp */,
+                                            png_infop /* info */)
+{}
+
+ossim_int32 ossimPngWriter::getColorType(ossim_int32 bands) const
+{
+   //---
+   // 
+   //---
+   ossim_int32 colorType = PNG_COLOR_TYPE_RGB;
+
+   if(theAlphaChannelFlag)
+   {
+      if(bands == 1)
+      {
+         colorType = PNG_COLOR_TYPE_GRAY_ALPHA;
+      }
+      else
+      {
+         colorType = PNG_COLOR_TYPE_RGB_ALPHA;
+      }
+   }
+   else
+   {
+      if (bands == 1)
+      {
+         colorType = PNG_COLOR_TYPE_GRAY;
+      }
+   }
+
+   return colorType;
+}
+
+ossim_int32 ossimPngWriter::getBitDepth(ossimScalarType outputScalar) const
+{
+   // Can be 1, 2, 4, 8, or 16 bits/channel (from IHDR)
+   ossim_int32 bitDepth = 0;
+   
+   switch(outputScalar)
+   {
+      case OSSIM_UINT8:
+         bitDepth = 8;
+         break;
+      case OSSIM_SINT16:
+      case OSSIM_UINT16:
+      case OSSIM_USHORT11:
+         bitDepth = 16;
+         break;
+      default:
+         break;
+   }
+
+   return bitDepth;
+}
+
+ossimString ossimPngWriter::getCompressionLevel() const
+{
+   ossimString result = ossimString("z_default_compression");
+   
+   switch (theCompressionLevel)
+   {
+      case Z_NO_COMPRESSION:
+         result = ossimString("z_no_compression");
+         break;
+         
+      case Z_BEST_SPEED:
+         result = ossimString("z_best_speed");
+         break;
+         
+      case Z_BEST_COMPRESSION:
+         result = ossimString("z_best_compression");
+         break;
+
+      default:
+         break;
+   }
+   return result;
+}
+
+bool ossimPngWriter::setCompressionLevel(const ossimString& level)
+{
+   bool status = true;
+
+   ossimString s = level;
+   s.downcase();
+
+   if(s == "z_no_compression")
+   {
+      theCompressionLevel = Z_NO_COMPRESSION;
+   }
+   else if(s == "z_best_speed")
+   {
+      theCompressionLevel = Z_BEST_SPEED;
+   }
+   else if(s == "z_best_compression")
+   {
+      theCompressionLevel = Z_BEST_COMPRESSION;
+   }
+   else if(s == "z_default_compression")
+   {
+      theCompressionLevel = Z_DEFAULT_COMPRESSION;
+   }
+   else
+   {
+      status = false;
+   }
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "DEBUG:"
+         << "\nossimPngWriter::setCompressionLevel DEBUG"
+         << "passed in level:  " << level.c_str()
+         << "writer level: " << getCompressionLevel().c_str()
+         << endl;
+   }
+
+   return status;
+}
+
+bool ossimPngWriter::getAlphaChannelFlag( void ) const
+{
+   return theAlphaChannelFlag;
+}
+
+void ossimPngWriter::setAlphaChannelFlag( bool flag )
+{
+   theAlphaChannelFlag = flag;
+}
+
+bool ossimPngWriter::setOutputStream(std::ostream& stream)
+{
+   if (theOwnsStreamFlag && theOutputStream)
+   {
+      delete theOutputStream;
+   }
+   theOutputStream = &stream;
+   theOwnsStreamFlag = false;
+   return true;
+}
diff --git a/ossim_plugins/png/ossimPngWriter.h b/ossim_plugins/png/ossimPngWriter.h
new file mode 100644
index 0000000..df1ecea
--- /dev/null
+++ b/ossim_plugins/png/ossimPngWriter.h
@@ -0,0 +1,395 @@
+//----------------------------------------------------------------------------
+//
+// License:  See top level LICENSE.txt file
+//
+// Author:  David Burken
+//
+// Description: OSSIM Portable Network Graphics (PNG) writer.
+//
+//----------------------------------------------------------------------------
+// $Id: ossimPngWriter.h 19878 2011-07-28 16:27:26Z dburken $
+#ifndef ossimPngWriter_HEADER
+#define ossimPngWriter_HEADER
+
+
+#include <ossim/base/ossimRtti.h>
+#include <ossim/imaging/ossimImageFileWriter.h>
+#include <ossim/base/ossimKeywordlist.h>
+#include <ossim/base/ossimNBandLutDataObject.h>
+#include <ossim/base/ossimRefPtr.h>
+#include <png.h>
+#include <ostream>
+
+class ossimPngWriter : public ossimImageFileWriter
+{
+public:
+
+   /* default constructor */
+   ossimPngWriter();
+
+   /* virtual destructor */
+   virtual ~ossimPngWriter();
+
+   /** @return "png writer" */
+   virtual ossimString getShortName() const;
+
+   /** @return "ossim png writer" */
+   virtual ossimString getLongName()  const;
+
+   /** @return "ossimPngReader" */
+   virtual ossimString getClassName()    const;
+
+   /**
+    * Returns a 3-letter extension from the image type descriptor 
+    * (theOutputImageType) that can be used for image file extensions.
+    *
+    * @param imageType string representing image type.
+    *
+    * @return the 3-letter string extension.
+    */
+   virtual ossimString getExtension() const;
+
+   /**
+    * void getImageTypeList(std::vector<ossimString>& imageTypeList)const
+    *
+    * Appends this writer image types to list "imageTypeList".
+    *
+    * This writer only has one type "png".
+    *
+    * @param imageTypeList stl::vector<ossimString> list to append to.
+    */
+   virtual void getImageTypeList(std::vector<ossimString>& imageTypeList)const;
+   
+   virtual bool isOpen()const;   
+   
+   virtual bool open();
+
+   virtual void close();
+   
+   /**
+    * saves the state of the object.
+    */
+   virtual bool saveState(ossimKeywordlist& kwl,
+                          const char* prefix=0)const;
+   
+   /**
+    * Method to the load (recreate) the state of an object from a keyword
+    * list.  Return true if ok or false on error.
+    */
+   virtual bool loadState(const ossimKeywordlist& kwl,
+                          const char* prefix=0);
+
+   /**
+    * Will set the property whose name matches the argument
+    * "property->getName()".
+    *
+    * @param property Object containing property to set.
+    */
+   virtual void setProperty(ossimRefPtr<ossimProperty> property);
+
+   /**
+    * @param name Name of property to return.
+    * 
+    * @returns A pointer to a property object which matches "name".
+    */
+   virtual ossimRefPtr<ossimProperty> getProperty(const ossimString& name)const;
+
+   /**
+    * Pushes this's names onto the list of property names.
+    *
+    * @param propertyNames array to add this's property names to.
+    */
+   virtual void getPropertyNames(std::vector<ossimString>& propertyNames)const;
+
+   bool hasImageType(const ossimString& imageType) const;
+
+   void setLut(const ossimNBandLutDataObject& lut);
+
+   /**
+    * Get the png compression level as a string.
+    *
+    * @return The level which will be one of:
+    * z_no_compression
+    * z_best_speed
+    * z_best_compression
+    * z_default_compression
+    */
+   ossimString getCompressionLevel() const;
+
+   /**
+    * Set the png compression level from a string.
+    *
+    * @param level Should be one of:
+    * z_no_compression
+    * z_best_speed
+    * z_best_compression
+    * z_default_compression
+    *
+    * @return true on success, false if level is not accepted.
+    */
+   bool setCompressionLevel(const ossimString& level);
+
+   /**
+    * Retrieve the writer's setting for whether or not to add an 
+    * alpha channel to the output png image.
+    *
+    * @return true if the writer is configured to create an alpha channel.
+    */
+   bool getAlphaChannelFlag( void ) const;
+
+   /**
+    * Set the writer to add an alpha channel to the output png image.
+    *
+    * @param flag true to create an alpha channel.
+    */
+   void setAlphaChannelFlag( bool flag );
+
+   /**
+    * @brief Method to write the image to a stream.
+    *
+    * @return true on success, false on error.
+    */
+   virtual bool writeStream();
+
+   /**
+    * @brief Sets the output stream to write to.
+    *
+    * The stream will not be closed/deleted by this object.
+    *
+    * @param output The stream to write to.
+    */
+   virtual bool setOutputStream(std::ostream& stream);
+
+private:
+
+   /**
+    * @brief Writes the file to disk or a stream.
+    * @return true on success, false on error.
+    */
+   virtual bool writeFile();
+
+   /**
+    * @brief Callback method for writing to stream.  This allows us to choose
+    * the stream; hence, writing to a file or memory.  This will be passed
+    * to libpng's png_set_write_fn.
+    */
+   static void pngWriteData(png_structp png_ptr, png_bytep data,
+                            png_size_t length);
+
+   /**
+    * @brief Callback method for a flush.  This is a required method for
+    * png_set_write_fn.
+    */
+   static void pngFlush(png_structp png_ptr);
+
+   /** @return true is swapping should be performed, false if not. */
+   bool doSwap(ossimScalarType outputScalar) const;
+
+   bool isLutEnabled()const;
+
+   /**
+    * @brief writes optionial chunks.
+    */
+   void writeOptionalChunks(png_structp pp, png_infop info);
+   
+   //---
+   // Chunck writers.  In place but not implemnted yet.
+   //---
+
+   /**
+    * Write transparent color chunk (tRNS)
+    * Location:   
+    * Multiple:   
+    */
+   void writeTransparentColorChunk(png_structp pp, png_infop info);
+
+   /**
+    * Write gamm chunk (gAMMA)
+    * Location:   Before PLTE, before first IDAT.
+    * Multiple:   no
+    */
+   void writeGammaChunk(png_structp pp, png_infop info);
+
+   /**
+    * Write background color chunk (bKGD)
+    * Location:   After PLTE, before first IDAT.
+    * Multiple:   no
+    */
+   void writeBackgroundColorChunk(png_structp pp, png_infop info);
+   
+   /**
+    * Write time stamp chunk (tIME).
+    * Location: anywhere
+    * Multiple: no
+    */
+   void writeTimeStampChunk(png_structp pp, png_infop info);
+   
+   /**
+    * Write any text (tEXt, zTXt).
+    * Location: anywhere
+    * Multiple: yes
+    */
+   void writeLatinTextChunk(png_structp pp, png_infop info);
+   
+   /**
+    * Write any text (iTXt).
+    * Location: anywhere
+    * Multiple: yes
+    */
+   void writeInternationalTextChunk(png_structp pp, png_infop info);
+   
+   /**
+    * Write histogram (hIST)
+    * Location: after PLTE, before first IDAT
+    * Multiple:   no
+    */
+   void writeHistogram(png_structp pp, png_infop info);
+   
+   /**
+    * Write suggested palette (sPLT)
+    * Location: before first IDAT
+    * Multiple: yes
+    */
+   void writeSuggestedPalette(png_structp pp, png_infop info);
+
+   /**
+    * Write significant bits (sBIT)
+    * Location: before PLTE and first IDAT
+    * Multiple: no
+    */
+   void writeSignificantBits(png_structp pp, png_infop info);
+   
+   /**
+    * Write physical pixel dimensions (pHYs)
+    * Location: before first IDAT
+    * Multiple: no
+    */
+   void writePhysicalPixelDimensions(png_structp pp, png_infop info);
+   
+   /**
+    * Write physical scale (sCAL)
+    * Location: before first IDAT
+    * Multiple: no
+    */
+   void writePhysicalScale(png_structp pp, png_infop info);
+   
+   /**
+    * Write image offset (oFFs)
+    * Location: before first IDAT
+    * Multiple: no
+    */
+   void writeImageOffset(png_structp pp, png_infop info);
+   
+   /**
+    * Write pixel calibration (pCAL)
+    * Location: after PLTE, before first IDAT
+    * Multiple: no
+    */
+   void writePixelCalibration(png_structp pp, png_infop info);
+   
+   /**
+    * Write fractal parameters (fRAc)
+    * Location: anywhere
+    * Multiple: yes
+    */
+   void writeFractalParameters(png_structp pp, png_infop info);
+
+   /**
+    * Get the png color type.
+    *
+    * @return png color type.  One of:
+    * PNG_COLOR_TYPE_GRAY
+    * PNG_COLOR_TYPE_PALETTE
+    * PNG_COLOR_TYPE_RGB
+    * PNG_COLOR_TYPE_RGB_ALPHA
+    * PNG_COLOR_TYPE_GRAY_ALPHA
+    */
+   ossim_int32 getColorType(ossim_int32 bands) const;
+   
+   ossim_int32 getBitDepth(ossimScalarType outputScalar) const;
+   
+   std::ostream* theOutputStream;
+   bool          theOwnsStreamFlag;
+
+   /**
+    * Compression level from zlib.h:
+    * Z_NO_COMPRESSION         0
+    * Z_BEST_SPEED             1
+    * Z_BEST_COMPRESSION       9
+    * Z_DEFAULT_COMPRESSION  (-1)
+    *
+    * Defaulted to Z_BEST_COMPRESSION
+    */
+   ossim_int32       theCompressionLevel;
+
+   /**
+    * Interlace support:
+    * PNG_INTERLACE_ADAM7
+    * PNG_INTERLACE_NONE
+    *
+    * Defaulted to PNG_INTERLACE_NONE
+    */
+   ossim_int32 theInterlaceSupport;
+
+   /**
+    * Z_FILTERED            1
+    * Z_HUFFMAN_ONLY        2
+    * Z_RLE                 3
+    * Z_FIXED               4
+    * Z_DEFAULT_STRATEGY    0
+    *
+    * Default to Z_FILTERED if not palette image,
+    * Z_DEFAULT_STRATEGY if palette.
+    */
+   ossim_int32 theCompressionStratagy;
+
+   /**
+    * PNG_NO_FILTERS     0x00
+    * PNG_FILTER_NONE    0x08
+    * PNG_FILTER_SUB     0x10
+    * PNG_FILTER_UP      0x20
+    * PNG_FILTER_AVG     0x40
+    * PNG_FILTER_PAETH   0x80
+    *
+    * Defaulted to PNG_FILTER_NONE if palette;  If not palette this is left
+    * up to zlib to decide unless the user overrides it.
+    */
+   ossim_int32 thePngFilter;
+
+   /**
+    * For gamma support.
+    * gamma multiplied by 100,000 and rounded to the nearest integer.
+    * So if gamma is 1/2.2 (or 0.45454545...), the value in the gAMA chunk is
+    * 45,455.
+    *
+    * There can be only one gAMA chunk, and it must appear before any
+    * IDATs and also before the PLTE chunk, if one is present.
+    */
+   bool                                 theGammaFlag;
+   ossim_float64                        theGamma;
+
+   /** Time support, either on or off.  Default = on. */
+   bool                                 theTimeFlag;
+
+   /** For alpha channel support. */
+   bool                                 theAlphaChannelFlag;
+
+   /** For background support. */
+   bool                                 theBackgroundFlag;
+   ossim_uint16                         theBackgroundRed;
+   ossim_uint16                         theBackgroundGreen;
+   ossim_uint16                         theBackgroundBlue;
+   ossim_uint16                         theBackgroundGray;
+
+   /** For transparent color support. */
+   bool                                 theTransparentFlag;
+   ossim_uint16                         theTransparentRed;
+   ossim_uint16                         theTransparentGreen;
+   ossim_uint16                         theTransparentBlue;
+   ossim_uint16                         theTransparentGray;
+
+   TYPE_DATA
+
+};
+
+#endif /* #ifndef ossimPngVoid Writer_HEADER */
diff --git a/ossim_plugins/png/ossimPngWriterFactory.cpp b/ossim_plugins/png/ossimPngWriterFactory.cpp
new file mode 100644
index 0000000..a102a2c
--- /dev/null
+++ b/ossim_plugins/png/ossimPngWriterFactory.cpp
@@ -0,0 +1,146 @@
+//----------------------------------------------------------------------------
+//
+// License:  See top level LICENSE.txt file
+//
+// Author:  David Burken
+//
+// Description: Factory for OSSIM Portable Network Graphics (PNG) writer.
+//----------------------------------------------------------------------------
+// $Id: ossimPngWriterFactory.cpp 18003 2010-08-30 18:02:52Z gpotts $
+
+#include "ossimPngWriterFactory.h"
+#include "ossimPngWriter.h"
+#include <ossim/base/ossimKeywordNames.h>
+#include <ossim/base/ossimRefPtr.h>
+#include <ossim/imaging/ossimImageFileWriter.h>
+
+ossimPngWriterFactory* ossimPngWriterFactory::theInstance = 0;
+
+RTTI_DEF1(ossimPngWriterFactory,
+          "ossimPngWriterFactory",
+          ossimImageWriterFactoryBase);
+
+ossimPngWriterFactory::~ossimPngWriterFactory()
+{
+   theInstance = 0;
+}
+
+ossimPngWriterFactory* ossimPngWriterFactory::instance()
+{
+   if(!theInstance)
+   {
+      theInstance = new ossimPngWriterFactory;
+   }
+   return theInstance;
+}
+
+ossimImageFileWriter *ossimPngWriterFactory::createWriterFromExtension(
+   const ossimString& fileExtension)const
+{
+   ossimRefPtr<ossimPngWriter> writer = 0;
+   if ( (fileExtension == "png") || (fileExtension == ".png") )
+   {
+      writer = new ossimPngWriter;
+   }
+   return writer.release();
+}
+
+ossimImageFileWriter*
+ossimPngWriterFactory::createWriter(const ossimKeywordlist& kwl,
+                                    const char *prefix)const
+{
+   ossimRefPtr<ossimImageFileWriter> writer = 0;
+   const char* type = kwl.find(prefix, ossimKeywordNames::TYPE_KW);
+   if (type)
+   {
+      writer = createWriter(ossimString(type));
+      if ( writer.valid() )
+      {
+         if (writer->loadState(kwl, prefix) == false)
+         {
+            writer = 0;
+         }
+      }
+   }
+   return writer.release();
+}
+
+ossimImageFileWriter* ossimPngWriterFactory::createWriter(
+   const ossimString& typeName)const
+{
+   ossimRefPtr<ossimImageFileWriter> writer = 0;
+   if (typeName == "ossimPngWriter")
+   {
+      writer = new ossimPngWriter;
+   }
+   else
+   {
+      // See if the type name is supported by the writer.
+      writer = new ossimPngWriter;
+      if ( writer->hasImageType(typeName) == false )
+      {
+         writer = 0;
+      }
+   }
+   return writer.release();
+}
+
+ossimObject* ossimPngWriterFactory::createObject(const ossimKeywordlist& kwl,
+                                                 const char *prefix)const
+{
+   return createWriter(kwl, prefix);
+}
+
+ossimObject* ossimPngWriterFactory::createObject(
+   const ossimString& typeName) const
+{
+   return createWriter(typeName);
+}
+
+void ossimPngWriterFactory::getExtensions(
+   std::vector<ossimString>& result)const
+{
+   result.push_back("png");
+}
+
+void ossimPngWriterFactory::getTypeNameList(std::vector<ossimString>& typeList)const
+{
+   typeList.push_back(ossimString("ossimPngWriter"));
+}
+
+void ossimPngWriterFactory::getImageTypeList(std::vector<ossimString>& imageTypeList)const
+{
+   ossimRefPtr<ossimPngWriter> writer = new ossimPngWriter;
+   writer->getImageTypeList(imageTypeList);
+   writer = 0;
+}
+
+void ossimPngWriterFactory::getImageFileWritersBySuffix(ossimImageWriterFactoryBase::ImageFileWriterList& result,
+                                                        const ossimString& ext)const
+{
+   ossimString testExt = ext.downcase();
+   if(testExt == "png")
+   {
+      result.push_back(new ossimPngWriter);
+   }
+}
+
+void ossimPngWriterFactory::getImageFileWritersByMimeType(ossimImageWriterFactoryBase::ImageFileWriterList& result,
+                                                          const ossimString& mimeType)const
+{
+   ossimString testMime = mimeType.downcase();
+   if(testMime == "image/png")
+   {
+      result.push_back(new ossimPngWriter);
+   }
+}
+
+ossimPngWriterFactory::ossimPngWriterFactory(){}
+
+ossimPngWriterFactory::ossimPngWriterFactory(const ossimPngWriterFactory&){}
+
+void ossimPngWriterFactory::operator=(const ossimPngWriterFactory&){}
+
+
+
+
diff --git a/ossim_plugins/png/ossimPngWriterFactory.h b/ossim_plugins/png/ossimPngWriterFactory.h
new file mode 100644
index 0000000..2fd151e
--- /dev/null
+++ b/ossim_plugins/png/ossimPngWriterFactory.h
@@ -0,0 +1,112 @@
+//----------------------------------------------------------------------------
+//
+// License:  See top level LICENSE.txt file
+//
+// Author:  David Burken
+//
+// Description: Factory for OSSIM Portable Network Graphics (PNG) writer.
+//----------------------------------------------------------------------------
+// $Id: ossimPngWriterFactory.h 18003 2010-08-30 18:02:52Z gpotts $
+
+#ifndef ossimPngWriterFactory_HEADER
+#define ossimPngWriterFactory_HEADER
+#include <ossim/imaging/ossimImageWriterFactoryBase.h>
+
+class ossimImageFileWriter;
+class ossimKeywordlist;
+class ossimImageWriterFactory;
+
+/** @brief Factory for PNG image writer. */
+class ossimPngWriterFactory: public ossimImageWriterFactoryBase
+{   
+public:
+
+   /** @brief virtual destructor */
+   virtual ~ossimPngWriterFactory();
+
+   /**
+    * @brief static method to return instance (the only one) of this class.
+    * @return pointer to instance of this class.
+    */
+   static ossimPngWriterFactory* instance();
+
+   /**
+    * @brief Creates a writer from extension like "png".
+    * @param fileExtension "png"
+    */
+   virtual ossimImageFileWriter *createWriterFromExtension(
+      const ossimString& fileExtension)const;
+
+   /**
+    * @brief Create that takes a keyword list and prefix.
+    * @param kwl The keyword list.
+    * @param prefix the keyword list prefix.
+    * @return pointer to image handler on success, NULL on failure.
+    */
+   virtual ossimImageFileWriter* createWriter(const ossimKeywordlist& kwl,
+                                              const char *prefix=0)const;
+
+   /**
+    * @brief createWriter that takes a class name (ossimPngWriter)
+    * @param kwl The keyword list.
+    * @param prefix the keyword list prefix.
+    * @return pointer to image writer on success, NULL on failure.
+    */
+   virtual ossimImageFileWriter* createWriter(const ossimString& typeName)const;
+
+   /**
+    * @brief Creates and object given a keyword list.
+    * @param kwl The keyword list.
+    * @param prefix the keyword list prefix.
+    * @return pointer to image writer on success, NULL on failure.
+    */
+   virtual ossimObject* createObject(const ossimKeywordlist& kwl,
+                                     const char *prefix=0)const;
+
+   /**
+    * @brief createObject that takes a class name (ossimPngWriter)
+    * @param typeName Should be "ossimPngReader".
+    * @return pointer to image writer on success, NULL on failure.
+    */
+   virtual ossimObject* createObject(const ossimString& typeName)const;
+
+
+   /**
+    * @brief Adds "png" to list.
+    * @param extList List to add to.
+    */
+   virtual void getExtensions(std::vector<ossimString>& extList)const;
+
+   /**
+    * @brief Adds "ossimPngWriter" to list.
+    * @param typeList List to add to.
+    */
+   virtual void getTypeNameList(std::vector<ossimString>& typeList)const;
+   
+   /**
+    * @brief Adds "ossim_png" to writer list.
+    * @param imageTypeList List to append to.
+    */
+   virtual void getImageTypeList(std::vector<ossimString>& imageTypeList)const;
+   
+   virtual void getImageFileWritersBySuffix(ossimImageWriterFactoryBase::ImageFileWriterList& result,
+                                            const ossimString& ext)const;
+   virtual void getImageFileWritersByMimeType(ossimImageWriterFactoryBase::ImageFileWriterList& result,
+                                              const ossimString& mimeType)const;
+protected:
+   /** @brief hidden from use default constructor */
+   ossimPngWriterFactory();
+
+   /** @brief hidden from use copy constructor */
+   ossimPngWriterFactory(const ossimPngWriterFactory&);
+
+   /** @brief hidden from use copy constructor */
+   void operator=(const ossimPngWriterFactory&);
+
+   /** static instance of this class */
+   static ossimPngWriterFactory* theInstance;
+
+TYPE_DATA
+};
+
+#endif /* end of #ifndef ossimPngWriterFactory_HEADER */
diff --git a/ossim_plugins/registration/CMakeLists.txt b/ossim_plugins/registration/CMakeLists.txt
new file mode 100644
index 0000000..6dad02f
--- /dev/null
+++ b/ossim_plugins/registration/CMakeLists.txt
@@ -0,0 +1,51 @@
+set(LIB_NAME ossimregistration_plugin)
+MESSAGE( "************** LIBRARY SETUP FOR ossimregistration_plugin******************")
+
+# Include ossim cmake stuff:
+include(OssimVersion)
+include(OssimCommonVariables)
+include(OssimUtilities)
+
+find_package(FFTW3)
+#find_package(TIFF)
+#find_package(CURL)
+#find_package(EXPAT)
+#find_library(SQLITE_LIBRARY NAMES sqlite sqlite3)
+#find_library(PROJ4_LIBRARY NAMES proj proj4)
+
+MESSAGE( STATUS "FFTW3_LIBRARY        = ${FFTW3_LIBRARY}" )
+MESSAGE( STATUS "FFTW3_INCLUDE        = ${FFTW3_INCLUDE_DIR}" )
+#MESSAGE( STATUS "TIFF_LIBRARY        = ${TIFF_LIBRARY}" )
+#MESSAGE( STATUS "TIFF_INCLUDE        = ${TIFF_INCLUDE_DIR}" )
+#MESSAGE( STATUS "EXPAT_LIBRARY       = ${EXPAT_LIBRARY}" )
+#MESSAGE( STATUS "SQLITE_LIBRARY      = ${SQLITE_LIBRARY}" )
+#MESSAGE( STATUS "PROJ4_LIBRARY       = ${PROJ4_LIBRARY}" )
+
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
+INCLUDE_DIRECTORIES(${OPENTHREADS_INCLUDE_DIR})
+INCLUDE_DIRECTORIES(${FFTW3_INCLUDE_DIR})
+#INCLUDE_DIRECTORIES(${GDAL_INCLUDE_DIR})
+#INCLUDE_DIRECTORIES(${TIFF_INCLUDE_DIR})
+
+FILE(GLOB_RECURSE OSSIMPLUGIN_SRCS *.cpp)
+FILE(GLOB_RECURSE OSSIMPLUGIN_HEADERS *.h)
+
+#---
+# OSSIMPLUGINSMAKINGDLL controls dll linkage on windows.  
+# Adding this sets OSSIM_PLUGINS_DLL #define TO "__declspec(dllexport)".
+#---
+add_definitions("-DOSSIMPLUGINSMAKINGDLL")
+
+# Adjust the install library path:
+if(OSSIM_INSTALL_PLUGINS_WITH_VERSION)
+   set(INSTALL_LIBRARY_DIR   "${INSTALL_LIBRARY_DIR}/ossim-${OSSIM_VERSION}/plugins")
+else(OSSIM_INSTALL_PLUGINS_WITH_VERSION)
+   set(INSTALL_LIBRARY_DIR   "${INSTALL_LIBRARY_DIR}/ossim/plugins")
+endif(OSSIM_INSTALL_PLUGINS_WITH_VERSION)
+
+OSSIM_LINK_LIBRARY(${LIB_NAME}
+                   COMPONENT_NAME ossim TYPE "${OSSIM_PLUGIN_LINK_TYPE}"
+		   LIBRARIES ${OSSIM_LIBRARIES} ${OPENTHREADS_LIBRARY} ${FFTW3_LIBRARY} 
+                   HEADERS "${OSSIMPLUGIN_HEADERS}"
+		   SOURCE_FILES "${OSSIMPLUGIN_SRCS}"
+                   INSTALL_LIB)
diff --git a/ossim_plugins/registration/makefile.vc b/ossim_plugins/registration/makefile.vc
new file mode 100644
index 0000000..ae06536
--- /dev/null
+++ b/ossim_plugins/registration/makefile.vc
@@ -0,0 +1,68 @@
+###
+# $Id: makefile.vc 16675 2010-02-25 17:43:33Z dburken $
+#
+# Windows nmake make file.  This code should compile with the Microsoft .NET
+# compiler.
+# 
+# Currently for a typical build on windows you would do the following.
+# - cd back to the ossim top and edit its nmake.opt file appropriately.
+# - nmake /f makefile
+#
+# NOTE:  If you make shared apps it's handy to copy the ossim.dll to the bin
+#        directory. 
+###
+
+!INCLUDE ..\nmake.opt
+PLUGIN_ROOT = ossim_reg_plugin
+
+###
+# Note: EMBED_MANIFEST variable is set in nmake.opt so make sure it is included
+# before this test.
+###
+!if "$(EMBED_MANIFEST)" == "1"
+!include ..\makefile.inc
+OSSIM_VC_MANIFEST_EMBED_DLL=$(_VC_MANIFEST_EMBED_DLL)
+OSSIM_VC_MANIFEST_CLEAN=$(_VC_MANIFEST_CLEAN)
+!else
+OSSIM_VC_MANIFEST_EMBED_DLL=
+OSSIM_VC_MANIFEST_CLEAN=
+!endif
+
+###
+# FFTW3 includes and libs.  Found at www.fftw.org.
+# WINDOWS : use IntelCompiler7 prebuilt binaries (issues with Visual Studio)
+###
+FFTW_HOME	= D:\vs9\3rd-party
+FFTW_LINK	= $(FFTW_HOME)\lib\libfftw3-3.lib $(FFTW_HOME)\lib\libfftw3f-3.lib
+# FFTW_LINK=
+FFTW_INCLUDES	= -I$(FFTW_HOME)\includes
+
+INC	=	-I. $(INC) $(FFTW_INCLUDES)
+LINK	=	link
+LFLAGS	=	/NOLOGO /SUBSYSTEM:WINDOWS /LIBPATH:"$(OSSIM_HOME)\lib" $(SHARED_OSSIM_LINK) $(FFTW_LINK) 
+
+OBJ	= 	ossimRegistrationPluginInit.obj \
+		ossimOutlierRejection.obj \
+		ossimTieGenerator.obj \
+		ossimModelOptimizer.obj \
+		ossimRunningSum.obj \
+		ossimHarrisCorners.obj \
+		ossimRegistrationImageSourceFactory.obj \
+		ossimMultiplier.obj \
+		ossimNCC_FFTW.obj \
+		ossimDensityReducer.obj \
+		ossimChipMatch.obj \
+		ossimSquareFunction.obj \
+		ossimExtremaFilter.obj \
+		ossimRegistrationMiscFactory.obj \
+		ossimImageCorrelator.obj
+
+default:	$(OBJ)
+	link /VERSION:1.7.2 /DLL /OUT:"$(PLUGIN_ROOT).dll" /IMPLIB:"$(PLUGIN_ROOT).lib" $(OBJ) $(LFLAGS)
+
+install:
+	$(CP) $(PLUGIN_ROOT).dll $(INSTALL_DIR)
+
+clean:
+	$(RM) *.obj
+	$(RM) $(LIB_DIR)\$(PLUGIN_ROOT).*
diff --git a/ossim_plugins/registration/ossimChipMatch.cpp b/ossim_plugins/registration/ossimChipMatch.cpp
new file mode 100644
index 0000000..ef3c04b
--- /dev/null
+++ b/ossim_plugins/registration/ossimChipMatch.cpp
@@ -0,0 +1,584 @@
+// class ossimChipMatch implementation
+// REQUIRES FFTW version 3.x (Fast Fourier Transform)
+
+#include "ossimChipMatch.h"
+#include <ossim/imaging/ossimImageDataFactory.h>
+#include <ossim/base/ossimIrect.h>
+#include "ossimRunningSum.h"
+#include "ossimNCC_FFTW.h"
+#include <ossim/projection/ossimProjection.h>
+#include <ossim/projection/ossimProjectionFactoryRegistry.h>
+
+#include <fftw3.h>
+
+#include <iostream> //TBR
+
+RTTI_DEF1( ossimChipMatch, "ossimChipMatch", ossimImageCombiner );
+
+// matrix to get the 2nd order x,y best fit polynomial (least mean squares)
+// -order of values (inputs) : from top left to bottom right along rows (normal image scan)
+// -order of coefficients (results) : 1 x y xy xx yy
+// uniform weighting for least mean squares
+
+double ossimChipMatch::theLMS[6*9] = {
+-1.1111111111111116e-001,2.2222222222222210e-001,-1.1111111111111116e-001,2.2222222222222210e-001,5.5555555555555536e-001,2.2222222222222210e-001,-1.1111111111111116e-001,2.2222222222222210e-001,-1.1111111111111116e-001,
+-1.6666666666666666e-001,0.0000000000000000e+000,1.6666666666666666e-001,-1.6666666666666666e-001,0.0000000000000000e+000,1.6666666666666666e-001,-1.6666666666666666e-001,0.0000000000000000e+000,1.6666666666666666e-001,
+-1.6666666666666666e-001,-1.6666666666666666e-001,-1.6666666666666666e-001,0.0000000000000000e+000,0.0000000000000000e+000,0.0000000000000000e+000,1.6666666666666666e-001,1.6666666666666666e-001,1.6666666666666666e-001,
+2.5000000000000000e-001,0.0000000000000000e+000,-2.5000000000000000e-001,0.0000000000000000e+000,0.0000000000000000e+000,0.0000000000000000e+000,-2.5000000000000000e-001,0.0000000000000000e+000,2.5000000000000000e-001,
+1.6666666666666669e-001,-3.3333333333333331e-001,1.6666666666666669e-001,1.6666666666666674e-001,-3.3333333333333326e-001,1.6666666666666674e-001,1.6666666666666669e-001,-3.3333333333333331e-001,1.6666666666666669e-001,
+1.6666666666666669e-001,1.6666666666666674e-001,1.6666666666666669e-001,-3.3333333333333331e-001,-3.3333333333333326e-001,-3.3333333333333331e-001,1.6666666666666669e-001,1.6666666666666674e-001,1.6666666666666669e-001
+};
+
+ossimChipMatch::ossimChipMatch()
+   :ossimImageCombiner(),
+   theSlaveAccuracy(7.0), //TBC
+   theMRadius(5), //TBC
+   theBias(0.0,0.0),
+   theMinNCC(0.75),
+   theNCCengine(NULL),
+   theTile(NULL)
+{
+}
+
+ossimChipMatch::ossimChipMatch(ossimObject *owner,         
+                               ossimImageSource *centers,
+                               ossimImageSource *master, 
+                               ossimImageSource *slave   )
+   :ossimImageCombiner(owner,
+   3,
+   0,
+   true,
+   false),
+   theSlaveAccuracy(7.0), //TBC: set to 0
+   theMRadius(5), //TBC
+   theBias(0.0,0.0),
+   theMinNCC(0.75),
+   theNCCengine(NULL),
+   theTile(NULL)
+{
+   connectMyInputTo(0, centers);
+   connectMyInputTo(1, master);
+   connectMyInputTo(2, slave);
+}
+
+ossimChipMatch::~ossimChipMatch()
+{
+   //no need to erase theTile (automatic)
+   if (theNCCengine!=NULL)
+   {
+      delete theNCCengine;
+      theNCCengine=NULL;
+   }
+}
+
+bool
+ossimChipMatch::canConnectMyInputTo(ossim_int32 index,const ossimConnectableObject* object)const
+{
+   //check that inputs just have one band
+   //max 3 inputs
+   //TBD: check scalar types
+   switch(index)
+   {
+   case 0:
+   case 1:
+   case 2:
+      {
+      ossimImageSource* imagep=PTR_CAST(ossimImageSource, object);
+      if (imagep)
+      {
+         //return (imagep->getNumberOfOutputBands()==1);
+         return true;
+      } else {
+         return false;
+      }
+      }
+      break;
+   default:
+      return false;
+   }
+}
+
+ossimScalarType
+ossimChipMatch::getOutputScalarType()const
+{
+   return OSSIM_NORMALIZED_DOUBLE;
+}
+
+ossimRefPtr<ossimImageData>
+ossimChipMatch::getTile(const ossimIrect &rect, ossim_uint32 resLevel)
+{
+   if(!theTile)
+   {
+      initialize();
+   }
+   long w = rect.width();
+   long h = rect.height();
+   long tw = theTile->getWidth();
+   long th = theTile->getHeight();
+
+   theTile->setImageRectangle(rect);
+      
+   if(w*h != tw*th)
+   {
+     theTile->initialize();
+   }
+   else
+   {
+      theTile->makeBlank();
+   }
+   
+   if (runMatch(rect, resLevel))
+   {
+      //rasterize tie-points
+      ossim_float64* tilebuf = static_cast<ossim_float64*>(theTile->getBuf(0));
+      vector<ossimTDpt>::const_iterator it = theTies.begin();
+      int xc,yc;
+      double x0=rect.ul().x;
+      double y0=rect.ul().y;
+      for (;it!=theTies.end();++it)
+      {
+         //remove upperleft corner and round
+         xc=(int)std::floor(it->x - x0 + 0.5); //TBC : overflow possible?
+         yc=(int)std::floor(it->y - y0 + 0.5);
+         tilebuf[ w*yc + xc] = it->score;
+      }
+      theTile->validate();
+   }
+   return theTile;
+}
+
+// returned vector is destroyed after subsequent calls to getFeatures
+const vector<ossimTDpt>&
+ossimChipMatch::getFeatures(const ossimIrect &rect, ossim_uint32 resLevel)
+{
+   runMatch(rect, resLevel);
+   return theTies;
+}
+
+void 
+ossimChipMatch::initialize()
+{
+   ossimImageCombiner::initialize();
+   theTile = ossimImageDataFactory::instance()->create(this, getOutputScalarType(), getNumberOfOutputBands(), getTileWidth(), getTileHeight());
+   theTile->initialize();
+   //TBD: change tile creation so it isn't within initialize 
+}
+
+double
+ossimChipMatch::getNullPixelValue(ossim_uint32 /*band*/)const
+{
+   return ossim::defaultNull(getOutputScalarType());
+}
+
+double
+ossimChipMatch::getMinPixelValue(ossim_uint32 /*band*/)const
+{
+   return ossim::defaultMin(getOutputScalarType());
+}
+
+double 
+ossimChipMatch::getMaxPixelValue(ossim_uint32 /*band*/)const
+{
+      return ossim::defaultMax(getOutputScalarType());
+}
+
+void 
+ossimChipMatch::setProperty(ossimRefPtr<ossimProperty> property)
+{
+   if(property->getName() == OSSIM_CHIPMATCH_PIXELRADIUS_PROPNAME)
+   {
+      //take ceiling of floating point value
+      setMasterRadius((ossim_uint32)(property->valueToString().toDouble()));//std::ceil(dynamic_cast<const ossimNumericProperty*>(property.get())->asFloat64())));
+   } 
+   else if (property->getName() == OSSIM_CHIPMATCH_SLAVEACCURACY_PROPNAME)
+   {
+      setSlaveAccuracy(property->valueToString().toDouble());//dynamic_cast<const ossimNumericProperty*>(property.get())->asFloat64());
+   }
+   else if (property->getName() == OSSIM_CHIPMATCH_MINNCC_PROPNAME)
+   {
+      setMinNCC(property->valueToString().toDouble());//property.get())->asFloat64());
+   }
+   else
+   {
+      ossimImageCombiner::setProperty(property);
+   }
+}
+
+ossimRefPtr<ossimProperty>
+ossimChipMatch::getProperty(const ossimString& name)const
+{
+   ossimRefPtr<ossimProperty> resultProperty;
+   if(name == OSSIM_CHIPMATCH_PIXELRADIUS_PROPNAME)
+   {
+      ossimNumericProperty* prProperty = new ossimNumericProperty(name,ossimString::toString(getMasterRadius()));
+      prProperty->setConstraints(0.0,50.0); //TBD: change to constants
+      prProperty->setCacheRefreshBit();
+      resultProperty = prProperty;
+   }
+   else if (name == OSSIM_CHIPMATCH_SLAVEACCURACY_PROPNAME)
+   {
+      ossimNumericProperty* prProperty = new ossimNumericProperty(name,ossimString::toString(getSlaveAccuracy()));
+      prProperty->setConstraints(0.0,100000.0); //TBD: change to constants
+      prProperty->setCacheRefreshBit();
+      resultProperty = prProperty;
+   }
+   else if(name == OSSIM_CHIPMATCH_MINNCC_PROPNAME)
+   {
+      ossimNumericProperty* prProperty = new ossimNumericProperty(name,ossimString::toString(getMinNCC()));
+      prProperty->setConstraints(-1.0,1.0); //TBD: change to constants
+      prProperty->setCacheRefreshBit();
+      resultProperty = prProperty;
+   }
+   else
+   {
+      resultProperty = ossimImageCombiner::getProperty(name);
+   }
+   return resultProperty;
+}
+
+void 
+ossimChipMatch::getPropertyNames(std::vector<ossimString>& propertyNames)const
+{
+   ossimImageCombiner::getPropertyNames(propertyNames);
+   
+   propertyNames.push_back(OSSIM_CHIPMATCH_PIXELRADIUS_PROPNAME);
+   propertyNames.push_back(OSSIM_CHIPMATCH_SLAVEACCURACY_PROPNAME);
+   propertyNames.push_back(OSSIM_CHIPMATCH_MINNCC_PROPNAME);
+}
+
+bool ossimChipMatch::saveState(ossimKeywordlist& kwl,
+                                      const char* prefix)const
+{
+   
+   kwl.add(prefix,
+           OSSIM_CHIPMATCH_SLAVEACCURACY_PROPNAME,
+           ossimString::toString(getSlaveAccuracy()).c_str(),
+           true);
+
+   kwl.add(prefix,
+           OSSIM_CHIPMATCH_PIXELRADIUS_PROPNAME,
+           ossimString::toString(getMasterRadius()).c_str(),
+           true);
+
+   kwl.add(prefix,
+           OSSIM_CHIPMATCH_MINNCC_PROPNAME,
+           ossimString::toString(getMinNCC()).c_str(),
+           true);
+   
+   return ossimImageCombiner::saveState(kwl,
+                                        prefix);
+}
+
+bool ossimChipMatch::loadState(const ossimKeywordlist& kwl,
+                                      const char* prefix)
+{
+   const char* sa = kwl.find(prefix, OSSIM_CHIPMATCH_SLAVEACCURACY_PROPNAME);
+   if(sa)
+   {
+      setSlaveAccuracy(ossimString(sa).toDouble());
+   }
+
+   const char* pr = kwl.find(prefix, OSSIM_CHIPMATCH_PIXELRADIUS_PROPNAME);
+   if(pr)
+   {      
+      setMasterRadius(ossimString(pr).toUInt32());
+   }
+
+   const char* mn = kwl.find(prefix, OSSIM_CHIPMATCH_MINNCC_PROPNAME);
+   if(mn)
+   {
+      setMinNCC(ossimString(mn).toDouble());
+   }
+
+   bool result = ossimImageCombiner::loadState(kwl,
+                                               prefix);
+   
+   return result;
+}
+
+ossim_uint32
+ossimChipMatch::getNumberOfOutputBands()const
+{
+   return 1;
+}
+
+ossimIrect
+ossimChipMatch::getBoundingRect(ossim_uint32 resLevel)const
+{
+   //intersect master+slave and add buffer (accuracy)
+   ossimImageSource* master = PTR_CAST(ossimImageSource, getInput(1)); //use corner input only
+   ossimImageSource* slave  = PTR_CAST(ossimImageSource, getInput(2)); //use corner input only
+   
+   ossimIrect res;
+
+   if (master && slave)
+   {
+     //Intersect rectangles
+     res = master->getBoundingRect(resLevel);
+     res.clipToRect(slave->getBoundingRect(resLevel));
+     //buffer with accuracy in pixels
+     //accuracy independent from resLevel
+     ossim_int32 iacc = (ossim_int32)ceil(getSlaveAccuracy());
+     ossimIpt delta_ur(iacc, -iacc); //image axes used
+
+     res.set_ur(res.ur() + delta_ur);
+     res.set_ll(res.ll() - delta_ur);
+
+   } else {
+     res.makeNan();
+   }
+   return res;
+}
+
+ossim_uint32
+ossimChipMatch::getTileWidth() const
+{
+   ossimImageSource* input = PTR_CAST(ossimImageSource, getInput(0));
+   if(input)
+   {
+      return input->getTileWidth();
+   }   
+   return 0;
+}
+
+ossim_uint32
+ossimChipMatch::getTileHeight() const
+{
+   ossimImageSource* input = PTR_CAST(ossimImageSource, getInput(0));
+   if(input)
+   {
+      return input->getTileHeight();
+   }   
+   return 0;
+}
+
+void
+ossimChipMatch::getDecimationFactor(ossim_uint32 resLevel,
+                                          ossimDpt& result)const
+{
+   ossimImageSource* input = PTR_CAST(ossimImageSource,
+                                               getInput(0));
+   if(input)
+   {
+      input->getDecimationFactor(resLevel, result);
+   }
+}
+
+void
+ossimChipMatch::getDecimationFactors(vector<ossimDpt>& decimations)const
+{
+   ossimImageSource* input = PTR_CAST(ossimImageSource,
+                                               getInput(0));
+   if(input)
+   {
+      input->getDecimationFactors(decimations);
+   }     
+}
+
+ossim_uint32
+ossimChipMatch::getNumberOfDecimationLevels()const
+{
+   ossimImageSource* input = PTR_CAST(ossimImageSource,
+                                               getInput(0));
+   if(input)
+   {
+      return input->getNumberOfDecimationLevels();
+   } 
+   return 0;
+}
+
+bool
+ossimChipMatch::runMatch(const ossimIrect &rect, ossim_uint32 resLevel)
+{
+   //erase stored tie points
+   theTies.clear();
+
+   //get Inputs
+   ossimImageSource* corner = PTR_CAST(ossimImageSource, getInput(0));
+   ossimImageSource* master = PTR_CAST(ossimImageSource, getInput(1));
+   ossimImageSource* slave  = PTR_CAST(ossimImageSource, getInput(2));
+   if (!corner || !master || !slave)
+   {
+      return false;
+   }
+
+   long w = rect.width();
+   long h = rect.height();
+   
+   //get corner data tile (same size as inner tile)
+   ossimRefPtr<ossimImageData> cornerData = corner->getTile(rect, resLevel);   
+   if(!cornerData.valid() || !isSourceEnabled())
+   {
+      return false;
+   }
+   
+   //TBD: use pixel size in meters to change delta_lr according to zoom
+
+   if((cornerData->getDataObjectStatus() != OSSIM_NULL) && (cornerData->getDataObjectStatus() != OSSIM_EMPTY))
+   {                  
+      //loop on corners (<>NULL & >=2 TBC)
+      ossim_uint32 coff=0; //offset (speedup)
+      ossim_int32 ci=0;
+      ossim_int32 cj=0;
+      //chip image radii
+      ossimIpt delta_mr(getMasterRadius(), getMasterRadius());
+      ossimIpt delta_lr(getMasterRadius() + (ossim_int32)(ceil(theSlaveAccuracy)),
+                        getMasterRadius() + (ossim_int32)(ceil(theSlaveAccuracy)) );
+
+      for(cj=0;cj<h;++cj) //rows
+      {
+         for(ci=0;ci<w;++ci) //cols
+         {
+            if (!cornerData->isNull(coff,0))
+            {
+               //get master data for specified center + radius
+               // radius doesn't change with resLevel
+               ossimIpt delta_mc(ci,cj);
+               ossimIrect mrect(rect.ul()+delta_mc-delta_mr, rect.ul()+delta_mc+delta_mr); //square, size 2*radius+1 pixels
+               ossimRefPtr<ossimImageData> masterData = master->getTile(mrect, resLevel); //same resLevel?? TBC
+               if ((masterData != NULL)
+                   && (masterData->getDataObjectStatus() != OSSIM_EMPTY) 
+                   && (masterData->getDataObjectStatus() != OSSIM_PARTIAL))
+               {
+                  //get slave data with bias & extended frame (use accuracy)
+                  //bias & extension change with scale
+                  ossimIpt delta_sc(ci+(ossim_int32)floor(theBias.x+0.5),cj+(ossim_int32)floor(theBias.y+0.5)); //biased center : TBD : convert unit to pixels
+                  ossimIrect srect(rect.ul()+delta_sc-delta_lr, rect.ul()+delta_sc+delta_lr); //square, size 2*(radius+accuracy)+1 pixels
+                  ossimRefPtr<ossimImageData> slaveData = slave->getTile(srect, resLevel); //same resLevel?? TBC
+                  if ((slaveData != NULL) 
+                      && (slaveData->getDataObjectStatus() != OSSIM_EMPTY)
+                      && (slaveData->getDataObjectStatus() != OSSIM_PARTIAL))
+                  {
+                     //find normalized cross-correlation maximum
+                     //TBD: assuming floating point input
+                     double dx=0.0;
+                     double dy=0.0;
+                     double ncor=0.0;
+
+                     getMaxCorrelation(masterData, slaveData, &dx, &dy, &ncor);
+                     
+                     //filter on NCC value
+                     if (ncor >= theMinNCC)
+                     {
+                        //create tie point & store
+                        theTies.push_back(ossimTDpt( rect.ul()+delta_mc, ossimDpt(dx,dy), ncor ));
+                     }
+                  }
+               }
+            }
+            ++coff;
+         }
+      }
+      return true;
+   }
+   return false;
+}
+
+void
+ossimChipMatch::getMaxCorrelation(ossimRefPtr<ossimImageData> Mchip, ossimRefPtr<ossimImageData> Schip, 
+                                  double* pdispx, double* pdispy, double* pcor)
+{
+   //use FFTW 3.0.1
+   //assume displacement between center of master to center of slave buffer
+   // Mchip must smaller than Schip (Schip incorporates error buffer)
+
+   ossim_uint32 sx = Schip->getWidth();
+   ossim_uint32 sy = Schip->getHeight();
+   ossim_uint32 mx = Mchip->getWidth();
+   ossim_uint32 my = Mchip->getHeight();
+   //cout<<"mx="<<mx<<" my="<<my<<" sx="<<sx<<" sy="<<sy<<endl; //TBR
+
+   int cx=sx+mx-1;
+   int cy=sy+my-1;
+
+   if (theNCCengine!=NULL)
+   {
+      //check correlation size
+      if (!theNCCengine->sameDims(cy,cx))
+      {
+         //re build NCC engine //TBD : use wisdom
+         delete theNCCengine;
+         theNCCengine=NULL;
+      }
+   }
+   if (theNCCengine==NULL)
+   {
+      //build a new NCC engine //TBD : use wisdom
+      theNCCengine = new ossimNCC_FFTW(cy,cx);
+   }
+
+   theNCCengine->ingestMaster(my,mx,Mchip->getDoubleBuf());
+   theNCCengine->ingestSlave(sy,sx,Schip->getDoubleBuf());
+
+   if (!theNCCengine->calculateNCC())
+   {
+      // TBD err mngt
+      if (pcor) *pcor=0.0;
+      if (pdispx) *pdispx = 0.0;
+      if (pdispy) *pdispy = 0.0;
+      cout<<"Error in NCC calculation"<<endl;
+      return;
+   }
+   int mj          = theNCCengine->getMaxCorrX(); 
+   int mi          = theNCCengine->getMaxCorrY();
+   double bestcorr = theNCCengine->getMaxCorr();
+   int oj = (cx-1)/2;//we know that cx and cy are odd!!
+   int oi = (cy-1)/2;
+   int deltaj = (sx-mx)/2; //we know that sx-mx is even
+   int deltai = (sy-my)/2;
+
+   //original best shift (integer shift for for max value)
+   double dmcx = mj - oj;
+   double dmcy = mi - oi;
+
+   //find maximum, sub-pixel precision
+   //use least-square fit on 2nd order polynomial
+   if ((mj > oj-deltaj) && (mj < oj+deltaj) && (mi > oi-deltai) && (mi < oi+deltai))
+   {
+      //then there's a 3x3 neighborhood we can use to get better precision
+      vector<double> p2c(6); //2nd order x y polynomial coefficents (see theLMS comments)
+      vector<double>::iterator it = p2c.begin();
+      double* pm = theLMS;
+      const ossimNCC_FFTW::cMatrix& corrmat = theNCCengine->getNcc();
+      //matrix product with values of 3x3 neighborhood
+      for (int k=0;k<6;++k)
+      {
+         *it = 0.0;
+         for(int i=-1;i<=1;++i)
+         {
+            for(int j=-1;j<=1;++j)
+            {
+               *it += *(pm++) * corrmat(mi+i, mj+j);
+            }
+         }
+         ++it;
+      }
+      //check convexity (det>0) + downwards orientation (trace<0)
+      double trace = p2c[4] + p2c[5];
+      if (trace<-1e-13) //TBC : -epsilon
+      {
+         double det = p2c[4]*p2c[5] - 0.25*p2c[3]*p2c[3];
+         if (det>1e-13) //TBC : epsilon
+         {
+            //ok : convex + downwards
+            //find maximum position
+            double optx = (p2c[3]*p2c[2] - 2.0 * p2c[5]*p2c[1]) / det * 0.25;
+            double opty = (p2c[3]*p2c[1] - 2.0 * p2c[4]*p2c[2]) / det * 0.25;
+            //limit new position to center pixel square
+            //TBD : need to find better model for NCC subpixel
+            if ((fabs(optx)<=0.501) && (fabs(opty)<=0.501))
+            {
+               dmcx+=optx;
+               dmcy+=opty;
+              //change corelation max value (dangerous) : TBD ? TBC
+            }
+         }
+      }
+   }
+
+   //give results back  
+   if (pcor)   *pcor   = bestcorr;
+   if (pdispx) *pdispx = dmcx;
+   if (pdispy) *pdispy = dmcy;
+}
+
diff --git a/ossim_plugins/registration/ossimChipMatch.h b/ossim_plugins/registration/ossimChipMatch.h
new file mode 100644
index 0000000..42e7901
--- /dev/null
+++ b/ossim_plugins/registration/ossimChipMatch.h
@@ -0,0 +1,110 @@
+// class ossimChipMatch : Image Combiner
+//
+// INPUTS:
+// - input image (slave) : one band
+// - reference image (master) : one band
+// - feature centers map
+//    = image of centers of chips (center= non NULL, > 2.0, pixels), e.g. harris corner map
+//   that image should be co-registered with the master image
+// OPERATION:
+//  matches master chips to slave chips and stores score + displacement.
+//  uses normalized cross correlation
+// PARAMETERS:
+//  accuracy of slave positions (meters)
+//  chip window size(pixels)
+// OUTPUT:
+//  normalized floating point image (0.0<->1.0) with chip matching intensity
+//
+// FUTURE:
+//  handle NULL pixels
+//  add matching on boundaries 
+//  use vector features for matching positions
+//  use vector tiles in Ossim for parallelism
+//
+// created by Frederic Claudel, EORU - CSIR - Aug 2005
+
+#ifndef ossimChipMatch_HEADER
+#define ossimChipMatch_HEADER
+
+#include <ossim/imaging/ossimImageCombiner.h>
+#include <ossim/base/ossimDpt.h>
+#include <ossim/base/ossimNumericProperty.h>
+#include <ossim/base/ossimTDpt.h>
+#include <vector>
+#include "ossimRegistrationExports.h"
+
+#define OSSIM_CHIPMATCH_SLAVEACCURACY_PROPNAME "SlaveAccuracy"
+#define OSSIM_CHIPMATCH_PIXELRADIUS_PROPNAME "PixelRadius"
+#define OSSIM_CHIPMATCH_MINNCC_PROPNAME "MinimumNCC"
+
+class ossimNCC_FFTW;
+
+class OSSIM_REGISTRATION_DLL ossimChipMatch : public ossimImageCombiner
+{
+public:
+   //own public methods
+   ossimChipMatch();
+   ossimChipMatch(ossimObject *owner,         
+                               ossimImageSource *centers,
+                               ossimImageSource *master, 
+                               ossimImageSource *slave   );
+   virtual ~ossimChipMatch();
+
+   inline void setSlaveAccuracy(ossim_float64 acc) { theSlaveAccuracy=acc; } //unit: meters
+   inline ossim_float64 getSlaveAccuracy()const { return theSlaveAccuracy; }
+
+   inline void setMasterRadius(ossim_uint32 r) { theMRadius=r; } //unit : pixels
+   inline ossim_uint32 getMasterRadius()const { return theMRadius; }
+
+   inline void setBias(const ossimDpt& aBias) { theBias=aBias; } //using current projection unit & axes
+   inline const ossimDpt& getBias()const { return theBias; }
+
+   inline void setMinNCC(ossim_float64 m) { theMinNCC=m; } //unitless (between -1.0 and 1.0)
+   inline ossim_float64 getMinNCC()const { return theMinNCC; }
+   
+   virtual const std::vector<ossimTDpt>& getFeatures(const ossimIrect &rect, ossim_uint32 resLevel=0); //vector method for getTile
+   
+   //inherited public methods
+   virtual void                        initialize();
+   virtual bool                        canConnectMyInputTo(ossim_int32 index,const ossimConnectableObject* object)const;
+   virtual double                      getNullPixelValue(ossim_uint32 band)const;
+   virtual double                      getMinPixelValue(ossim_uint32 band=0)const;
+   virtual double                      getMaxPixelValue(ossim_uint32 band=0)const;
+   virtual ossimScalarType 	         getOutputScalarType()const;
+   virtual ossim_uint32                getNumberOfOutputBands()const;
+   virtual ossimIrect                  getBoundingRect(ossim_uint32 resLevel=0)const;
+
+   virtual ossim_uint32 getTileWidth() const;
+   virtual ossim_uint32 getTileHeight() const;
+
+   virtual void getDecimationFactor(ossim_uint32 resLevel, ossimDpt& result)const;
+   virtual void getDecimationFactors(vector<ossimDpt>& decimations)const;
+   virtual ossim_uint32 getNumberOfDecimationLevels()const;
+
+   virtual ossimRefPtr<ossimImageData> getTile (const ossimIrect &rect, ossim_uint32 resLevel=0);
+
+   virtual void setProperty(ossimRefPtr<ossimProperty> property);
+   virtual ossimRefPtr<ossimProperty> getProperty(const ossimString& name)const;
+   virtual void getPropertyNames(std::vector<ossimString>& propertyNames)const;
+
+   virtual bool saveState(ossimKeywordlist& kwl, const char* prefix=0)const;
+   virtual bool loadState(const ossimKeywordlist& kwl, const char* prefix=0);
+
+protected:
+   bool runMatch(const ossimIrect &rect, ossim_uint32 resLevel=0);
+   void getMaxCorrelation(ossimRefPtr<ossimImageData> Mchip, ossimRefPtr<ossimImageData> Schip, 
+                                  double* pdispx, double* pdispy, double* pcor);
+
+   std::vector<ossimTDpt>      theTies;
+   ossim_float64               theSlaveAccuracy;
+   ossim_uint32                theMRadius;
+   ossimDpt                    theBias;
+   ossim_float64               theMinNCC;
+   ossimNCC_FFTW*              theNCCengine;
+   ossimRefPtr<ossimImageData> theTile;
+   //static data
+   static double theLMS[6*9];
+
+TYPE_DATA
+};
+#endif
diff --git a/ossim_plugins/registration/ossimDensityReducer.cpp b/ossim_plugins/registration/ossimDensityReducer.cpp
new file mode 100644
index 0000000..cc28531
--- /dev/null
+++ b/ossim_plugins/registration/ossimDensityReducer.cpp
@@ -0,0 +1,269 @@
+
+#include "ossimDensityReducer.h"
+#include <ossim/imaging/ossimImageDataFactory.h>
+#include <ossim/imaging/ossimImageData.h>
+#include <ossim/base/ossimNumericProperty.h>
+
+#include <algorithm>
+
+using namespace std;
+
+RTTI_DEF1(ossimDensityReducer, "ossimDensityReducer", ossimImageSourceFilter);
+
+static const char* PROP_MAXDENSITY  = "MaxDensity";
+
+//functor for decreasing comparison (strict weak ordering, like greater), for pairs on the first element
+template<class T> class greaterFirst
+{
+   public:
+      bool operator()(const T& x, const T& y)
+      {
+         return x.first > y.first;
+      }
+};
+
+ossimDensityReducer::ossimDensityReducer(ossimObject* owner)
+   :ossimImageSourceFilter(owner),
+    theTile(NULL),
+    theMaxDensity(1.0)
+{
+}
+
+ossimDensityReducer::ossimDensityReducer(ossimImageSource* inputSource)
+   :ossimImageSourceFilter(inputSource),
+    theTile(NULL),
+    theMaxDensity(1.0)
+{
+}
+
+ossimDensityReducer::ossimDensityReducer(ossimObject* owner,
+                                   ossimImageSource* inputSource)
+   :ossimImageSourceFilter(owner, inputSource),
+    theTile(NULL),
+    theMaxDensity(1.0)
+{
+}
+
+ossimRefPtr<ossimImageData> 
+ossimDensityReducer::getTile(const ossimIrect& rect, ossim_uint32 resLevel)
+{
+   if(!isSourceEnabled())
+   {
+      return ossimImageSourceFilter::getTile(rect, resLevel);
+   }
+
+   ossimRefPtr<ossimImageData> inputData =
+      ossimImageSourceFilter::getTile(rect, resLevel);
+
+   if(!inputData.valid() || (!inputData->getBuf()) || (inputData->getDataObjectStatus() ==  OSSIM_EMPTY) || (getMaxDensity()>=1.0))
+   {
+      return inputData;
+   }
+
+   if(!theTile.valid()) initialize();
+   if(!theTile.valid()) return theTile;
+   
+   theTile->setImageRectangleAndBands(rect, inputData->getNumberOfBands());
+   
+   switch(theTile->getScalarType())
+   {
+   case OSSIM_UCHAR:
+   {
+      runFilter((ossim_uint8)0,
+                inputData);
+      break;
+   }
+   case OSSIM_FLOAT:
+   case OSSIM_NORMALIZED_FLOAT:
+   {
+      runFilter((ossim_float32)0,
+                inputData);
+      break;
+   }
+   case OSSIM_USHORT16:
+   case OSSIM_USHORT11:
+   {
+      runFilter((ossim_uint16)0,
+                inputData);
+      break;
+   }
+   case OSSIM_SSHORT16:
+   {
+      runFilter((ossim_sint16)0,
+                inputData);
+      break;
+   }
+   case OSSIM_DOUBLE:
+   case OSSIM_NORMALIZED_DOUBLE:
+   {
+      runFilter((ossim_float64)0,
+                inputData);
+      break;
+   }
+   default:
+   {
+      ossimNotify(ossimNotifyLevel_WARN) << "ossimDensityReducer::getTile WARN: Scalar type = " << theTile->getScalarType()
+                                         << " Not supported by ossimDensityReducer" << std::endl;
+      break;
+   }
+   }
+
+   return theTile;
+}
+
+void ossimDensityReducer::initialize()
+{
+   ossimImageSourceFilter::initialize();
+
+   theTile = NULL;
+
+   if(!isSourceEnabled())
+   {
+      return;
+   }
+   
+   theTile = ossimImageDataFactory::instance()->create(this, this);
+   if(theTile.valid())
+   {
+      theTile->initialize();
+   }
+
+}
+
+void ossimDensityReducer::setProperty(ossimRefPtr<ossimProperty> property)
+{
+   if(!property) return;
+
+   if (property->getName() == PROP_MAXDENSITY)  {
+      ossimNumericProperty* numProperty = PTR_CAST(ossimNumericProperty,
+                                                     property.get());
+      if(numProperty)
+      {
+         setMaxDensity(numProperty->asFloat64());
+      }
+   }  else {
+      ossimImageSourceFilter::setProperty(property);
+   }
+}
+
+ossimRefPtr<ossimProperty> ossimDensityReducer::getProperty(const ossimString& name)const
+{
+   if (name == PROP_MAXDENSITY) {
+      ossimNumericProperty* property = new ossimNumericProperty(name, ossimString::toString(getMaxDensity()),0.0,1.0);
+      property->setCacheRefreshBit();
+      return property;
+   } 
+   return ossimImageSourceFilter::getProperty(name);
+}
+
+void ossimDensityReducer::getPropertyNames(std::vector<ossimString>& propertyNames)const
+{
+   ossimImageSourceFilter::getPropertyNames(propertyNames);
+   
+   propertyNames.push_back(PROP_MAXDENSITY);
+}
+
+
+template <class T>
+void ossimDensityReducer::runFilter(T dummyVariable,
+                                ossimRefPtr<ossimImageData> inputData)
+{
+   // so far neighborhood is 3x3
+   ossim_uint32 bandIdx = 0;
+   ossim_uint32 numberOfBands = inputData->getNumberOfBands();
+  
+   ossim_uint32 width  = theTile->getWidth();
+   ossim_uint32 height = theTile->getHeight();
+   ossim_uint32 tsize  = width * height; //surely a tile cannot hold more than 4 billion pixels?
+
+   //max number of pixels
+   if (getMaxDensity()<=0)
+   {
+      //nullify tile
+      theTile->makeBlank();
+      return;
+   }
+   //we always want at least one point (if density > 0)
+   ossim_uint32 maxp = (ossim_uint32)ceil(getMaxDensity() * tsize);
+   if (maxp >= tsize)
+   {
+      //return everything
+      theTile = inputData; //TBC: should we make a deep copy?
+      return;
+   }
+
+   //initially nullify output tile
+   theTile->makeBlank();
+
+   //init a storage vector for non null pixels : pre-allocate maximum size
+   // stores value and offset from start
+   // will be used for all bands
+   vector< pair< T , ossim_uint32 > > sortv(tsize);
+
+   for(bandIdx = 0; bandIdx < numberOfBands; ++bandIdx)
+   {
+      T* inputBuf  = static_cast<T*>(inputData->getBuf(bandIdx));
+      T* outputBuf = static_cast<T*>(theTile->getBuf(bandIdx));
+      T np         = static_cast<T>(inputData->getNullPix(bandIdx)); //changed to input Null            
+      if(inputBuf&&outputBuf)
+      {
+         //get only non null pixels, and store offset
+         typename vector< pair< T , ossim_uint32 > >::iterator it = sortv.begin();
+         ossim_uint32 o;
+         for(o = 0; o < tsize; ++o,++it)
+         {
+            if (inputBuf[o] != np)
+            {
+               it->first  = inputBuf[o] ;
+               it->second = o ;
+            }
+         }
+
+         //o is now the number of valid elemnts in the vector
+         //arrange vector so that the maxp first elements have larger value than the others
+         if (maxp<o)
+         {
+            nth_element< typename vector< pair< T , ossim_uint32 > >::iterator , greaterFirst< pair< T , ossim_uint32 > > >(
+               sortv.begin(),
+               sortv.begin()+maxp, 
+               sortv.begin()+o, 
+               greaterFirst< pair< T , ossim_uint32 > >());
+            o=maxp;
+         } //else : density below max, nothing to do
+
+         //only display elements between offsets maxp and o
+         typename vector< pair< T , ossim_uint32 > >::iterator nit = sortv.begin();
+         for (ossim_uint32 p=0; p<o; ++p,++nit)
+         {
+            outputBuf[nit->second] = nit->first;
+         }
+
+      }
+   }
+   theTile->validate();
+}
+
+bool ossimDensityReducer::saveState(ossimKeywordlist& kwl,
+                                          const char* prefix)const
+{  
+   kwl.add(prefix,
+          PROP_MAXDENSITY,
+          ossimString::toString(getMaxDensity()),
+          true);
+   
+   return ossimImageSourceFilter::saveState(kwl, prefix);
+}
+
+
+bool ossimDensityReducer::loadState(const ossimKeywordlist& kwl,
+                                          const char* prefix)
+{
+   const char* md = kwl.find(prefix,PROP_MAXDENSITY );
+   if(md)
+   {
+      setMaxDensity(ossimString::toDouble(md));
+   } else {
+      ossimNotify(ossimNotifyLevel_WARN) << "ossimDensityReducer::loadState WARN: no "<<PROP_MAXDENSITY<<" found" << std::endl;
+   }  
+   return ossimImageSourceFilter::loadState(kwl, prefix);
+}
diff --git a/ossim_plugins/registration/ossimDensityReducer.h b/ossim_plugins/registration/ossimDensityReducer.h
new file mode 100644
index 0000000..1ed8794
--- /dev/null
+++ b/ossim_plugins/registration/ossimDensityReducer.h
@@ -0,0 +1,57 @@
+#ifndef ossimDensityReducer_HEADER
+#define ossimDensityReducer_HEADER
+#include <ossim/imaging/ossimImageSourceFilter.h>
+#include "ossimRegistrationExports.h"
+
+/**
+ * class ossimDensityReducer
+ *
+ * orders NON NULL elements in tile
+ * and nullify weaker ones so that a maximum density of non NULL pixel is reached
+ * MaxDensity is a real number, which should between 0 and 1 (unit: pixel^-2)
+ * 
+ * TBD:
+ * -so far all bands are processed in parallel (slow) : define multi-band density reduction
+ *   (I only use it for single band data so far)
+ * -dealing with NULL values
+ * -random pick for too small density values (to avoid no corners at all)
+ */
+class OSSIM_REGISTRATION_DLL ossimDensityReducer : public ossimImageSourceFilter
+{
+public:
+   /**
+    * own methods
+    */
+   ossimDensityReducer(ossimObject* owner=NULL);
+   ossimDensityReducer(ossimImageSource* inputSource);
+   ossimDensityReducer(ossimObject* owner, ossimImageSource* inputSource);
+  
+   inline const ossim_float64& getMaxDensity()const { return theMaxDensity; }
+   inline void                 setMaxDensity(const ossim_float64& aMaxDensity) { theMaxDensity = aMaxDensity; }
+
+   /**
+    * inherited methods
+    */
+   virtual ossimRefPtr<ossimImageData> getTile(const ossimIrect& rect,
+                                               ossim_uint32 resLevel=0);
+   virtual void initialize();
+
+   virtual void setProperty(ossimRefPtr<ossimProperty> property);
+   virtual ossimRefPtr<ossimProperty> getProperty(const ossimString& name)const;
+   virtual void getPropertyNames(std::vector<ossimString>& propertyNames)const;
+
+   virtual bool saveState(ossimKeywordlist& kwl,const char* prefix=0)const;
+   virtual bool loadState(const ossimKeywordlist& kwl,const char* prefix=0);
+   
+protected:
+   ossimRefPtr<ossimImageData> theTile;
+   ossim_float64                theMaxDensity; //! between 0 and 1 included
+   
+   template <class T>
+   void runFilter(T dummyVariable, ossimRefPtr<ossimImageData> inputData);
+   
+TYPE_DATA
+};
+
+
+#endif
diff --git a/ossim_plugins/registration/ossimExtremaFilter.cpp b/ossim_plugins/registration/ossimExtremaFilter.cpp
new file mode 100644
index 0000000..2438e21
--- /dev/null
+++ b/ossim_plugins/registration/ossimExtremaFilter.cpp
@@ -0,0 +1,305 @@
+
+#include "ossimExtremaFilter.h"
+#include <ossim/imaging/ossimImageDataFactory.h>
+#include <ossim/imaging/ossimImageData.h>
+#include <ossim/base/ossimBooleanProperty.h>
+
+RTTI_DEF1(ossimExtremaFilter, "ossimExtremaFilter", ossimImageSourceFilter);
+
+static const char* PROP_ISSTRICT  = "IsStrict";
+static const char* PROP_ISMAXIMUM = "IsMaximum";
+
+ossimExtremaFilter::ossimExtremaFilter(ossimObject* owner)
+   :ossimImageSourceFilter(owner),
+    theTile(NULL),
+    theIsMaximum(true),
+    theIsStrict(true)
+{
+}
+
+ossimExtremaFilter::ossimExtremaFilter(ossimImageSource* inputSource)
+   :ossimImageSourceFilter(inputSource),
+    theTile(NULL),
+    theIsMaximum(true),
+    theIsStrict(true)
+{
+}
+
+ossimExtremaFilter::ossimExtremaFilter(ossimObject* owner,
+                                   ossimImageSource* inputSource)
+   :ossimImageSourceFilter(owner, inputSource),
+    theTile(NULL),
+    theIsMaximum(true),
+    theIsStrict(true)
+{
+}
+
+ossimRefPtr<ossimImageData> 
+ossimExtremaFilter::getTile(const ossimIrect& rect, ossim_uint32 resLevel)
+{
+   if(!isSourceEnabled())
+   {
+      return ossimImageSourceFilter::getTile(rect, resLevel);
+   }
+
+   // expand the rect out to cover the 3x3 horizontal and vertical kernel.
+   ossimIrect requestRect = rect;
+
+   adjustRequestRect(requestRect);
+   
+   ossimRefPtr<ossimImageData> inputData =
+      ossimImageSourceFilter::getTile(requestRect, resLevel);
+
+   if(!inputData.valid() || (!inputData->getBuf()))
+   {
+      return inputData;
+   }
+
+   if(!theTile.valid()) initialize();
+   if(!theTile.valid()) return theTile;
+      
+   theTile->setImageRectangleAndBands(rect, inputData->getNumberOfBands());
+   
+   switch(theTile->getScalarType())
+   {
+   case OSSIM_UCHAR:
+   {
+      runFilter((ossim_uint8)0,
+                inputData);
+      break;
+   }
+   case OSSIM_FLOAT:
+   case OSSIM_NORMALIZED_FLOAT:
+   {
+      runFilter((ossim_float32)0,
+                inputData);
+      break;
+   }
+   case OSSIM_USHORT16:
+   case OSSIM_USHORT11:
+   {
+      runFilter((ossim_uint16)0,
+                inputData);
+      break;
+   }
+   case OSSIM_SSHORT16:
+   {
+      runFilter((ossim_sint16)0,
+                inputData);
+      break;
+   }
+   case OSSIM_DOUBLE:
+   case OSSIM_NORMALIZED_DOUBLE:
+   {
+      runFilter((ossim_float64)0,
+                inputData);
+      break;
+   }
+   default:
+   {
+      ossimNotify(ossimNotifyLevel_WARN) << "ossimExtremaFilter::getTile WARN: Scalar type = " << theTile->getScalarType()
+                                         << " Not supported by ossimExtremaFilter" << std::endl;
+      break;
+   }
+   }
+
+   return theTile;
+}
+
+void ossimExtremaFilter::initialize()
+{
+   ossimImageSourceFilter::initialize();
+
+   theTile = NULL;
+
+   if(!isSourceEnabled())
+   {
+      return;
+   }
+   
+   theTile = ossimImageDataFactory::instance()->create(this, this);
+   if(theTile.valid())
+   {
+      theTile->initialize();
+   }
+
+}
+
+void ossimExtremaFilter::setProperty(ossimRefPtr<ossimProperty> property)
+{
+   if(!property) return;
+
+   if (property->getName() == PROP_ISMAXIMUM)  {
+      ossimBooleanProperty* booleanProperty = PTR_CAST(ossimBooleanProperty,
+                                                     property.get());
+      if(booleanProperty)
+      {
+         setIsMaximum(booleanProperty->getBoolean());
+      }
+   } else if (property->getName() == PROP_ISSTRICT)  {
+      ossimBooleanProperty* booleanProperty = PTR_CAST(ossimBooleanProperty,
+                                                     property.get());
+      if(booleanProperty)
+      {
+         setIsStrict(booleanProperty->getBoolean());
+      }
+   } else {
+      ossimImageSourceFilter::setProperty(property);
+   }
+}
+
+ossimRefPtr<ossimProperty> ossimExtremaFilter::getProperty(const ossimString& name)const
+{
+   if (name == PROP_ISMAXIMUM) {
+      ossimBooleanProperty* property = new ossimBooleanProperty(name, isMaximum());
+      property->setCacheRefreshBit();
+      return property;
+   } else if (name == PROP_ISSTRICT) {
+      ossimBooleanProperty* property = new ossimBooleanProperty(name, isStrict());
+      property->setCacheRefreshBit();
+      return property;
+   }
+   return ossimImageSourceFilter::getProperty(name);
+}
+
+void ossimExtremaFilter::getPropertyNames(std::vector<ossimString>& propertyNames)const
+{
+   ossimImageSourceFilter::getPropertyNames(propertyNames);
+   
+   propertyNames.push_back(PROP_ISMAXIMUM);
+   propertyNames.push_back(PROP_ISSTRICT);
+}
+
+
+void ossimExtremaFilter::adjustRequestRect(ossimIrect& requestRect)const
+{
+   requestRect = ossimIrect(requestRect.ul().x - 1,
+                            requestRect.ul().y - 1,
+                            requestRect.lr().x + 1,
+                            requestRect.lr().y + 1);
+}
+
+template <class T>
+void ossimExtremaFilter::runFilter(T dummyVariable,
+                                ossimRefPtr<ossimImageData> inputData)
+{
+   // so far neighborhood is 3x3
+   ossim_uint32 bandIdx = 0;
+   ossim_uint32 numberOfBands = inputData->getNumberOfBands();
+  
+   ossim_uint32 x = 0;
+   ossim_uint32 y = 0;
+   ossim_uint32 width  = theTile->getWidth();
+   ossim_uint32 height = theTile->getHeight();
+   ossim_int32 rowIncrement  = inputData->getWidth();
+   ossim_int32 rowIncrement2 = 2*inputData->getWidth(); 
+         
+   T centerv;
+   T extremum;
+   bool center_better;
+   for(bandIdx = 0; bandIdx < numberOfBands; ++bandIdx)
+   {
+      //inputBuf has a 1 pixel edge compared to outputBuf
+      T* inputBuf  = static_cast<T*>(inputData->getBuf(bandIdx));
+      T* outputBuf = static_cast<T*>(theTile->getBuf(bandIdx));
+      T np         = static_cast<T>(inputData->getNullPix(bandIdx)); //changed to input Null            
+      if(inputBuf&&outputBuf)
+      {
+         //one pass: maybe faster if changed to two passes
+         T* outB;
+         T* inB;
+         
+      	outB = outputBuf;         
+         inB  = inputBuf;         
+         for(y = 0; y < height; ++y)
+         {
+            for(x = 0; x < width; ++x)
+            {
+               centerv = inB[1+rowIncrement];
+               if (centerv != np)
+               {
+                  if (isMaximum())
+                  {
+                     extremum = max<T>(
+                           max<T>(
+                            max<T>(inB[0],inB[1]),
+                            max<T>(inB[2],inB[rowIncrement])),
+                           max<T>(
+                            max<T>(inB[rowIncrement+2],inB[rowIncrement2]),
+                            max<T>(inB[rowIncrement2+1],inB[rowIncrement2+2])
+                            ));
+                     if (isStrict())
+                     {
+                        center_better = centerv > extremum;
+                     } else {
+                        center_better = centerv >= extremum;
+                     }
+                  } else {
+                     extremum = min<T>(
+                           min<T>(
+                            min<T>(inB[0],inB[1]),
+                            min<T>(inB[2],inB[rowIncrement])),
+                           min<T>(
+                            min<T>(inB[rowIncrement+2],inB[rowIncrement2]),
+                            min<T>(inB[rowIncrement2+1],inB[rowIncrement2+2])
+                            ));
+                     if (isStrict())
+                     {
+                        center_better = centerv < extremum;
+                     } else {
+                        center_better = centerv <= extremum;
+                     }
+                  }
+                  //nullify if not extremum
+                  *outB = center_better ? centerv : np ;
+               }
+               else
+               {
+                  *outB = np;
+               }
+               ++outB;
+               ++inB;
+            }
+            inB+=2; //go to next line, jump due to edge
+         }       
+      }      
+   }
+   theTile->validate();
+}
+
+bool ossimExtremaFilter::saveState(ossimKeywordlist& kwl,
+                                          const char* prefix)const
+{  
+   kwl.add(prefix,
+          PROP_ISMAXIMUM,
+          ossimString::toString(isStrict()),
+          true);
+   kwl.add(prefix,
+          PROP_ISSTRICT,
+           ossimString::toString(isStrict()),
+           true);
+   
+   return ossimImageSourceFilter::saveState(kwl, prefix);
+}
+
+
+bool ossimExtremaFilter::loadState(const ossimKeywordlist& kwl,
+                                          const char* prefix)
+{
+   const char* im = kwl.find(prefix,PROP_ISMAXIMUM );
+   if(im)
+   {
+      setIsMaximum(ossimString::toBool(im));
+   } else {
+      ossimNotify(ossimNotifyLevel_WARN) << "ossimExtremaFilter::loadState WARN: no "<<PROP_ISMAXIMUM<<" found" << std::endl;
+   }
+   const char* is = kwl.find(prefix,PROP_ISSTRICT );
+   if(is)
+   {
+      setIsStrict(ossimString::toBool(is));
+   } else {
+      ossimNotify(ossimNotifyLevel_WARN) << "ossimExtremaFilter::loadState WARN: no "<<PROP_ISSTRICT<<" found" << std::endl;
+   }
+        
+   return ossimImageSourceFilter::loadState(kwl, prefix);
+}
diff --git a/ossim_plugins/registration/ossimExtremaFilter.h b/ossim_plugins/registration/ossimExtremaFilter.h
new file mode 100644
index 0000000..24f35a7
--- /dev/null
+++ b/ossim_plugins/registration/ossimExtremaFilter.h
@@ -0,0 +1,62 @@
+
+#ifndef ossimExtremaFilter_HEADER
+#define ossimExtremaFilter_HEADER
+#include <ossim/imaging/ossimImageSourceFilter.h>
+#include "ossimRegistrationExports.h"
+
+/**
+ * class ossimExtremaFilter
+ *
+ * returns local extrema unchanged (can be maxima or minima, strict or not)
+ * nullify other pixels
+ * uses a 8 pixel neighborhood
+ *
+ * ToBeDone:
+ *  -add vector tiles support
+ *  -add different kind of neighborhoods  - mostly larger
+ */
+class OSSIM_REGISTRATION_DLL ossimExtremaFilter : public ossimImageSourceFilter
+{
+public:
+  /**
+   * own methods
+   */
+   ossimExtremaFilter(ossimObject* owner=NULL);
+   ossimExtremaFilter(ossimImageSource* inputSource);
+   ossimExtremaFilter(ossimObject* owner, ossimImageSource* inputSource);
+
+   inline bool isMaximum()const { return theIsMaximum; }
+   inline void setIsMaximum(bool aMax) { theIsMaximum = aMax; }
+   
+   inline bool isStrict()const { return theIsStrict; }
+   inline void setIsStrict(bool aStrict) { theIsStrict = aStrict; }
+
+  /**
+   *inherited methods
+   */
+   virtual ossimRefPtr<ossimImageData> getTile(const ossimIrect& rect,
+                                               ossim_uint32 resLevel=0);
+   virtual void initialize();
+
+   virtual void setProperty(ossimRefPtr<ossimProperty> property);
+   virtual ossimRefPtr<ossimProperty> getProperty(const ossimString& name)const;
+   virtual void getPropertyNames(std::vector<ossimString>& propertyNames)const;
+
+   virtual bool saveState(ossimKeywordlist& kwl,const char* prefix=0)const;
+   virtual bool loadState(const ossimKeywordlist& kwl,const char* prefix=0);
+   
+protected:
+   ossimRefPtr<ossimImageData> theTile;
+   bool                        theIsMaximum;
+   bool                        theIsStrict;
+   
+   void adjustRequestRect(ossimIrect& requestRect)const;
+   
+   template <class T>
+   void runFilter(T dummyVariable,
+                  ossimRefPtr<ossimImageData> inputData);
+   
+TYPE_DATA
+};
+
+#endif
diff --git a/ossim_plugins/registration/ossimHarrisCorners.cpp b/ossim_plugins/registration/ossimHarrisCorners.cpp
new file mode 100644
index 0000000..fa25896
--- /dev/null
+++ b/ossim_plugins/registration/ossimHarrisCorners.cpp
@@ -0,0 +1,400 @@
+#include "ossimHarrisCorners.h"
+#include <ossim/base/ossimNumericProperty.h>
+#include <ossim/imaging/ossimCastTileSourceFilter.h>
+#include <ossim/imaging/ossimConvolutionFilter1D.h>
+#include <ossim/imaging/ossimImageData.h>
+#include <ossim/imaging/ossimImageGaussianFilter.h>
+#include <ossim/imaging/ossimEquationCombiner.h>
+#include "ossimExtremaFilter.h"
+#include "ossimDensityReducer.h"
+#include "ossimSquareFunction.h"
+#include "ossimMultiplier.h"
+
+RTTI_DEF1(ossimHarrisCorners, "ossimHarrisCorners", ossimImageSourceFilter);
+
+//! property names
+static const char* PROPERTYNAME_K             = "K";
+static const char* PROPERTYNAME_GAUSSSTD      = "GaussStd";
+static const char* PROPERTYNAME_MINCORNERNESS = "MinCornerness";
+static const char* PROPERTYNAME_DENSITY       = "Density";
+
+static double DER_KERNEL[3] = {-0.5,0.0,0.5};
+
+ossimHarrisCorners::ossimHarrisCorners()
+   : ossimImageSourceFilter(),
+     theK(0.05),
+     theGaussStd(1.0),
+     theMinCornerness(0.0),
+     theDensity(0.003)
+{
+   //create sub-processes
+   // ingredients: 
+   // 2x  3x3ConvolutionFilter
+   // 3x  EquationCombiner - for 2nd order products  (a square and a product)
+   // 3x  EquationCombiner - for gaussian smoothing  (clones)
+   // 1x  EquationCombiner - for combining everything
+   // 1x  ExtremaFilter    - for local maxima, 8 neighbours, strict
+   // 1x  DensityReducer   - for spatially filtering local maxima
+   
+   theCastP       = new ossimCastTileSourceFilter();
+   theDxP         = new ossimConvolutionFilter1D();
+   theDyP         = new ossimConvolutionFilter1D();
+   theProductP    = new ossimMultiplier();
+   theSquaresP.push_back(new ossimSquareFunction);
+   theSquaresP.push_back(new ossimSquareFunction);
+   theSmoothP.push_back(new ossimImageGaussianFilter);
+   theSmoothP.push_back(new ossimImageGaussianFilter);
+   theSmoothP.push_back(new ossimImageGaussianFilter);
+   theCornernessP = new ossimEquationCombiner();
+   theLocalMaxP   = new ossimExtremaFilter();
+   theFilterP     = new ossimDensityReducer();
+
+   //initialize parameters for sub-processes
+   theCastP->setOutputScalarType(OSSIM_FLOAT64); //float64 or double??
+
+   theDxP->setKernel(vector<ossim_float64>(DER_KERNEL,DER_KERNEL+3)); //hard coded
+   theDxP->setCenterOffset(1); //hard coded
+   theDxP->setIsHorizontal(true); //hard coded
+   theDxP->setStrictNoData(true);
+
+   theDyP->setKernel(vector<ossim_float64>(DER_KERNEL,DER_KERNEL+3));
+   theDyP->setCenterOffset(1); //hard coded
+   theDyP->setIsHorizontal(false); //hard coded
+   theDyP->setStrictNoData(true);
+      
+   for(int i=0;i<3;++i)
+   {
+     theSmoothP[i]->setGaussStd(theGaussStd);
+     theSmoothP[i]->setStrictNoData(true);
+   }
+
+   theCornernessP->setEquation(getCornernessEquation());
+   theCornernessP->setOutputScalarType(OSSIM_FLOAT64);
+
+   theLocalMaxP->setIsMaximum(true);
+   theLocalMaxP->setIsStrict(true);
+
+   theFilterP->setMaxDensity(getDensity());
+
+   //tie them all up
+   theDxP->connectMyInputTo(0,theCastP.get());
+   theDyP->connectMyInputTo(0,theCastP.get());
+
+   theSquaresP[0]->connectMyInputTo(0,theDxP.get());
+   theSquaresP[1]->connectMyInputTo(0,theDyP.get());
+
+   theProductP->connectMyInputTo(0,theDxP.get());
+   theProductP->connectMyInputTo(1,theDyP.get());
+
+   theSmoothP[0]->connectMyInputTo(0,theSquaresP[0].get());
+   theSmoothP[1]->connectMyInputTo(0,theProductP.get());
+   theSmoothP[2]->connectMyInputTo(0,theSquaresP[1].get());
+
+   for (int i=0;i<3;++i)
+   {   
+      theCornernessP->connectMyInputTo(i,theSmoothP[i].get());
+   }
+
+   theLocalMaxP->connectMyInputTo(0,theCornernessP.get());
+
+   theFilterP->connectMyInputTo(0,theLocalMaxP.get());
+}
+
+ossimHarrisCorners::~ossimHarrisCorners()
+{
+   if(theCastP.valid())
+   {
+      ossim_uint32 idx = 0;
+      theCastP->disconnect();
+      theDxP->disconnect();
+      theDyP->disconnect();
+      theProductP->disconnect();
+      for(idx = 0; idx < theSquaresP.size(); ++idx)
+      {
+         theSquaresP[idx]->disconnect();
+         theSquaresP[idx] = 0;
+      }
+      for(idx = 0; idx < theSmoothP.size(); ++idx)
+      {
+         theSmoothP[idx]->disconnect();
+         theSmoothP[idx] = 0;
+      }
+      theCornernessP->disconnect();
+      theLocalMaxP->disconnect();
+      theFilterP->disconnect();
+      theSmoothP.clear();
+      theCastP = 0;
+      theDxP = 0;
+      theDyP = 0;
+      theCornernessP = 0;
+      theLocalMaxP = 0;
+      theFilterP = 0;
+   }
+}
+
+void ossimHarrisCorners::setProperty(ossimRefPtr<ossimProperty> property)
+{
+   if(!property) return;
+
+   if (property->getName() == PROPERTYNAME_K) {
+      ossimNumericProperty* sProperty = PTR_CAST(ossimNumericProperty,
+                                                     property.get());
+      if(sProperty)
+      {
+         setK(sProperty->asFloat64());
+      }
+   } else if (property->getName() == PROPERTYNAME_GAUSSSTD) {
+      ossimNumericProperty* sProperty = PTR_CAST(ossimNumericProperty,
+                                                     property.get());
+      if(sProperty)
+      {
+         setGaussStd(sProperty->asFloat64());
+      }
+   } else if(property->getName() == PROPERTYNAME_MINCORNERNESS) {
+      ossimNumericProperty* sProperty = PTR_CAST(ossimNumericProperty,
+                                                     property.get());
+      if(sProperty)
+      {
+         setMinCornerness(sProperty->asFloat64());
+      }
+   } else if(property->getName() == PROPERTYNAME_DENSITY) {
+      ossimNumericProperty* sProperty = PTR_CAST(ossimNumericProperty,
+                                                     property.get());
+      if(sProperty)
+      {
+         setDensity(sProperty->asFloat64());
+      }
+   } else {
+      ossimImageSourceFilter::setProperty(property);
+   }
+}
+
+ossimRefPtr<ossimProperty> ossimHarrisCorners::getProperty(const ossimString& name)const
+{
+   if(name == PROPERTYNAME_K) {
+      ossimNumericProperty* property = new ossimNumericProperty(name,ossimString::toString(getK()),0,0.25);
+      property->setCacheRefreshBit();
+      return property;
+   } else if (name == PROPERTYNAME_GAUSSSTD) {
+      ossimNumericProperty* property = new ossimNumericProperty(name,ossimString::toString(getGaussStd()),0.001,15);
+      property->setCacheRefreshBit();
+      return property;
+   } else if (name == PROPERTYNAME_MINCORNERNESS) {
+      ossimNumericProperty* property = new ossimNumericProperty(name,ossimString::toString(getMinCornerness()));
+      property->setCacheRefreshBit();
+      return property;
+   } else if (name == PROPERTYNAME_DENSITY) {
+      ossimNumericProperty* property = new ossimNumericProperty(name,ossimString::toString(getDensity()),0.0,1.0);
+      property->setCacheRefreshBit();
+      return property;
+   }
+   return ossimImageSourceFilter::getProperty(name);
+}
+
+void ossimHarrisCorners::getPropertyNames(std::vector<ossimString>& propertyNames)const
+{
+   ossimImageSourceFilter::getPropertyNames(propertyNames);
+   propertyNames.push_back(PROPERTYNAME_K);
+   propertyNames.push_back(PROPERTYNAME_GAUSSSTD);
+   propertyNames.push_back(PROPERTYNAME_MINCORNERNESS);
+   propertyNames.push_back(PROPERTYNAME_DENSITY);
+}
+
+bool ossimHarrisCorners::saveState(ossimKeywordlist& kwl,
+                                          const char* prefix)const
+{   
+   kwl.add(prefix,
+           PROPERTYNAME_K,
+           getK(),
+           true);
+   kwl.add(prefix,
+          PROPERTYNAME_GAUSSSTD,
+           getGaussStd(),
+           true);
+   kwl.add(prefix,
+          PROPERTYNAME_MINCORNERNESS,
+           getMinCornerness(),
+           true); 
+   kwl.add(prefix,
+          PROPERTYNAME_DENSITY,
+           getDensity(),
+           true); 
+
+   return ossimImageSourceFilter::saveState(kwl, prefix);
+}
+
+
+bool ossimHarrisCorners::loadState(const ossimKeywordlist& kwl,
+                                          const char* prefix)
+{
+   const char* k = kwl.find(prefix, PROPERTYNAME_K);
+   if(k)
+   {      
+      setK(ossimString(k).toDouble());
+   } else {
+      cerr<<"ossimHarrisCorners::loadState : missing property "<< PROPERTYNAME_K<<endl;
+   }
+
+   const char* gs = kwl.find(prefix, PROPERTYNAME_GAUSSSTD);
+   if(gs)
+   {      
+      setGaussStd(ossimString(gs).toDouble());
+   } else {
+      cerr<<"ossimHarrisCorners::loadState : missing property "<< PROPERTYNAME_GAUSSSTD<<endl;
+   }
+
+   const char* mc = kwl.find(prefix, PROPERTYNAME_MINCORNERNESS);
+   if(mc)
+   {      
+      setMinCornerness(ossimString(mc).toDouble());
+   } else {
+      cerr<<"ossimHarrisCorners::loadState : missing property "<< PROPERTYNAME_MINCORNERNESS<<endl;
+   }
+   const char* dd = kwl.find(prefix, PROPERTYNAME_DENSITY);
+   if(dd)
+   {      
+      setDensity(ossimString(dd).toDouble());
+   } else {
+      cerr<<"ossimHarrisCorners::loadState : missing property "<< PROPERTYNAME_DENSITY<<endl;
+   }
+   
+   return ossimImageSourceFilter::loadState(kwl, prefix);
+}
+
+void ossimHarrisCorners::setK(const ossim_float64& v)
+{
+   theK=v;
+   //update processes
+   theCornernessP->setEquation(getCornernessEquation());
+}
+
+void ossimHarrisCorners::setGaussStd(const ossim_float64& v)
+{
+   theGaussStd = v;
+   //update processes
+   for(int i=0;i<3;++i)
+   {
+      theSmoothP[i]->setGaussStd(theGaussStd);
+   }
+}
+
+void ossimHarrisCorners::setMinCornerness(const ossim_float64& v)
+{
+   theMinCornerness = v;
+   //TBC : no impact, not used
+}
+
+void ossimHarrisCorners::setDensity(const ossim_float64& v)
+{
+   theDensity = v;
+   //update process
+   theFilterP->setMaxDensity(getDensity());
+}
+
+void
+ossimHarrisCorners::initialize()
+{
+   ossimImageSourceFilter::initialize();
+   initializeProcesses();
+}
+
+ossimRefPtr<ossimImageData>
+ossimHarrisCorners::getTile(const ossimIrect &tileRect,ossim_uint32 resLevel)
+{
+    if(theInputConnection)
+    {
+       if(isSourceEnabled())
+       {
+         return theFilterP->getTile(tileRect, resLevel);
+       }
+       return theInputConnection->getTile(tileRect, resLevel);
+    }
+    return ossimRefPtr<ossimImageData>();
+}
+
+void
+ossimHarrisCorners::initializeProcesses()
+{
+   theCastP->initialize();
+   theDxP->initialize();
+   theDyP->initialize();
+   theProductP->initialize();
+   theSquaresP[0]->initialize();
+   theSquaresP[1]->initialize();
+   for (int i=0;i<3;++i)
+   {
+      theSmoothP[i]->initialize();
+   }
+   theCornernessP->initialize();
+   theLocalMaxP->initialize();
+   theFilterP->initialize();
+}
+
+void
+ossimHarrisCorners::connectInputEvent(ossimConnectionEvent &event)
+{
+    ossimImageSourceFilter::connectInputEvent(event);
+    if(getInput())
+    {
+       theCastP->connectMyInputTo(0, getInput());
+       initializeProcesses();
+    }
+    else
+    {
+       theCastP->disconnectMyInput(0, false, false);
+       initializeProcesses();
+    }
+}
+
+
+void
+ossimHarrisCorners::disconnectInputEvent(ossimConnectionEvent &event)
+{
+    ossimImageSourceFilter::disconnectInputEvent(event);
+    if(getInput())
+    {
+       theCastP->connectMyInputTo(0, getInput());
+       initializeProcesses();
+    }
+    else
+    {
+       theCastP->disconnectMyInput(0, false, false);
+       initializeProcesses();
+    }
+}
+
+ossimString
+ossimHarrisCorners::getCornernessEquation()const
+{
+   return ossimString("(in[0]*in[2]-in[1]^2)-") + ossimString::toString(theK) + "*(in[0]+in[2])^2";
+}
+
+void
+ossimHarrisCorners::getOutputBandList(std::vector<ossim_uint32>& bandList) const
+{
+   theFilterP->getOutputBandList(bandList);
+}
+
+ossimScalarType
+ossimHarrisCorners::getOutputScalarType() const
+{
+   return theFilterP->getOutputScalarType();
+}
+
+double
+ossimHarrisCorners::getNullPixelValue(ossim_uint32 band)const
+{
+   return theFilterP->getNullPixelValue(band);
+}
+
+double
+ossimHarrisCorners::getMinPixelValue(ossim_uint32 band)const
+{
+   return theFilterP->getMinPixelValue(band);
+}
+
+double
+ossimHarrisCorners::getMaxPixelValue(ossim_uint32 band)const
+{
+   return theFilterP->getMaxPixelValue(band);
+}
diff --git a/ossim_plugins/registration/ossimHarrisCorners.h b/ossim_plugins/registration/ossimHarrisCorners.h
new file mode 100644
index 0000000..72db844
--- /dev/null
+++ b/ossim_plugins/registration/ossimHarrisCorners.h
@@ -0,0 +1,108 @@
+// class ossimHarrisCorner : tile source
+// computes harris corners using an image chain
+// calcultes x and y derivatives, then forms three 2nd order products, smoothg them and combines to form a cornerness map
+// then selects local maxima above a certain threshold
+//
+// INPUT:  one band image
+// OUTPUT: one band, ossim_float64
+//         corners are the only non NULL pixels (non OSSIM_DBL_NAN). value=cornerness
+// PROPERTIES
+//      K  = harris cornerness parameter
+//         min_cornerness = minimum cornerness
+//         smoooth_radius = gaussian smoothing standard deviation
+//
+
+#ifndef ossimHarrisCorners_HEADER
+#define ossimHarrisCorners_HEADER
+
+#include <ossim/imaging/ossimImageSourceFilter.h>
+#include <ossim/imaging/ossimCastTileSourceFilter.h>
+#include <ossim/imaging/ossimConvolutionFilter1D.h>
+#include <ossim/imaging/ossimImageGaussianFilter.h>
+#include <ossim/imaging/ossimEquationCombiner.h>
+#include "ossimExtremaFilter.h"
+#include "ossimDensityReducer.h"
+#include "ossimMultiplier.h"
+#include "ossimSquareFunction.h"
+#include "ossimRegistrationExports.h"
+
+
+class OSSIM_REGISTRATION_DLL ossimHarrisCorners : public ossimImageSourceFilter
+{
+public:
+  /**
+   *own methods
+   */
+   ossimHarrisCorners();
+   virtual ~ossimHarrisCorners();
+
+   inline ossim_float64 getK()const { return theK; }
+   void setK(const ossim_float64& v);
+
+   inline ossim_float64 getGaussStd()const { return theGaussStd; }
+   void setGaussStd(const ossim_float64& v);
+
+   inline ossim_float64 getMinCornerness()const { return theMinCornerness; }
+   void setMinCornerness(const ossim_float64& v);
+
+   inline ossim_float64 getDensity()const { return theDensity; }
+   void setDensity(const ossim_float64& d);
+
+  /**
+   * inherited methods re-implemented due to type change in output
+   */
+   virtual void getOutputBandList(std::vector<ossim_uint32>& bandList) const;
+   virtual ossimScalarType getOutputScalarType() const;
+   virtual double getNullPixelValue(ossim_uint32 band=0)const;
+   virtual double getMinPixelValue(ossim_uint32 band=0)const;
+   virtual double getMaxPixelValue(ossim_uint32 band=0)const;
+   
+  /**
+   * inherited methods
+   */
+   virtual void initialize();
+   virtual ossimRefPtr<ossimImageData> getTile(const ossimIrect &tileRect,ossim_uint32 resLevel=0);
+   
+   //! implemented to pass events to inner processes
+   virtual void connectInputEvent(ossimConnectionEvent &event);
+   virtual void disconnectInputEvent(ossimConnectionEvent &event);
+
+   virtual void setProperty(ossimRefPtr<ossimProperty> property);
+   virtual ossimRefPtr<ossimProperty> getProperty(const ossimString& name)const;
+   virtual void getPropertyNames(std::vector<ossimString>& propertyNames)const;
+
+   virtual bool loadState(const ossimKeywordlist& kwl,const char* prefix = 0);   
+   virtual bool saveState(ossimKeywordlist& kwl,const char* prefix = 0)const;
+   
+protected:
+   /**
+    * protected methods
+    */
+   void initializeProcesses();
+   ossimString getCornernessEquation()const;
+
+  /**
+   *parameters
+   */
+   ossim_float64 theK;
+   ossim_float64 theGaussStd;
+   ossim_float64 theMinCornerness; //not used now
+   ossim_float64 theDensity; //corner density in pixel^-2
+
+  /** 
+   * subprocesses
+   */
+   ossimRefPtr<ossimCastTileSourceFilter> theCastP;
+   ossimRefPtr<ossimConvolutionFilter1D>  theDxP;
+   ossimRefPtr<ossimConvolutionFilter1D>  theDyP;
+   ossimRefPtr<ossimMultiplier>           theProductP;
+   std::vector<ossimRefPtr<ossimSquareFunction> >      theSquaresP;
+   std::vector<ossimRefPtr<ossimImageGaussianFilter> >  theSmoothP;
+   ossimRefPtr<ossimEquationCombiner>     theCornernessP;
+   ossimRefPtr<ossimExtremaFilter>        theLocalMaxP;
+   ossimRefPtr<ossimDensityReducer>       theFilterP;
+
+TYPE_DATA
+};
+
+#endif /* #ifndef ossimHarrisCorners_HEADER */
diff --git a/ossim_plugins/registration/ossimImageCorrelator.cpp b/ossim_plugins/registration/ossimImageCorrelator.cpp
new file mode 100644
index 0000000..6d44a20
--- /dev/null
+++ b/ossim_plugins/registration/ossimImageCorrelator.cpp
@@ -0,0 +1,679 @@
+// ossimImageCorrelator.cpp
+#include <iostream>
+
+#include "ossimImageCorrelator.h"
+#include <ossim/imaging/ossimImageSource.h>
+#include <ossim/imaging/ossimImageHandler.h>
+#include <ossim/imaging/ossimCastTileSourceFilter.h>
+#include <ossim/imaging/ossimImageRenderer.h>
+#include "ossimHarrisCorners.h"
+#include "ossimChipMatch.h"
+#include <ossim/imaging/ossimCacheTileSource.h>
+#include <ossim/imaging/ossimImageChain.h>
+#include <ossim/imaging/ossimBandSelector.h>
+#include "ossimTieGenerator.h"
+#include <ossim/imaging/ossimImageHandlerRegistry.h>
+#include <ossim/projection/ossimMapProjection.h>
+#include <ossim/projection/ossimProjectionFactoryRegistry.h>
+#include <ossim/projection/ossimImageViewProjectionTransform.h>
+#include <ossim/base/ossimTrace.h>
+#include <ossim/base/ossimXmlDocument.h>
+#include <ossim/base/ossimFilenameProperty.h>
+#include <ossim/base/ossimStringProperty.h>
+
+using namespace std;
+
+static ossimTrace traceDebug("ossimImageCorrelator:debug");
+
+RTTI_DEF2(ossimImageCorrelator, "ossimImageCorrelator", ossimOutputSource, ossimProcessInterface);
+
+ossimImageCorrelator::ossimImageCorrelator()
+ : ossimOutputSource(NULL, // owner
+                        0,
+                        0,
+                        true,
+                        true),
+   ossimProcessInterface(),
+   theMaster(),
+   theSlave(),
+   theMasterBand(0),
+   theSlaveBand(0),
+   theScaleRatio(1.0),
+   theSlaveAccuracy(15.0),
+   theCornerDensity(0.002),
+   theProjectionType("M"),
+   theMasterPointProj("G"),
+   theSlavePointProj("I"),
+   theTemplateRadius(7),
+   theMinCorrel(0.8),
+   theHasRun(false),
+   handlerM(NULL),
+   handlerS(NULL),
+   theMasterBandSelector(NULL),
+   theSlaveBandSelector(NULL),
+   theTset()
+{
+   //default output name : XML
+   setOutputName("tiepts.xml");
+
+   //1.add all OSSIM blocks
+   // ingredients :
+   // 2x ossimImageSource (for master & slave)
+   // 2x ossimImagerRenderer
+   // 1x ossimHarrisCorners
+   // 2x ossimCastTileFilter (to get floating point
+   // 1x ossimChipMatch
+   // 1x ossimTieGenerator
+
+   // don't create sources (factories will do it)
+   caster.push_back(new ossimCastTileSourceFilter());
+   caster.push_back(new ossimCastTileSourceFilter());
+   cornerDetector      = new ossimHarrisCorners();
+   matcher             = new ossimChipMatch();
+   generator           = new ossimTieGenerator();
+   
+}
+
+ossimImageCorrelator::~ossimImageCorrelator()
+{
+   //TBC : delete handlers created by factory?
+   generator = 0;
+   if(matcher.valid())
+   {
+      matcher->disconnect();
+      matcher = 0;
+   }
+   if(cornerDetector.valid())
+   {
+      cornerDetector->disconnect();
+      cornerDetector = 0;
+   }
+   
+   if(caster.size())
+   {
+      caster[0]->disconnect();
+      caster[1]->disconnect();
+      caster.clear();
+   }
+   if(theMChain.valid())
+   {
+      theMChain->disconnect();
+   }
+   if(theSChain.valid())
+   {
+      theSChain->disconnect();
+   }
+   theMChain = 0;
+   theSChain = 0;
+}
+
+ossimString ossimImageCorrelator::getRole() const
+{
+   ossimString role = "unknown";
+   
+   //use slave or master projection
+   if (theProjectionType == "S")
+   {
+      role="slave";
+   }
+   else if (theProjectionType == "M")
+   {
+      role="master";
+   }
+   else
+   {
+      cerr<<"ossimImageCorrelator::getRole unknown output projection, need to supply it"<<endl;
+   }
+
+   return role;
+}
+
+ossimImageHandler*  ossimImageCorrelator::getProjectionHandler()
+{
+   //use slave or master projection
+   ossimImageHandler* projHandler = 0;
+   if (theProjectionType == "S")
+   {
+      projHandler = handlerS.get();
+   }
+   else if (theProjectionType == "M")
+   {
+      projHandler = handlerM.get();
+   }
+   else
+   {
+      cerr<<"ossimImageCorrelator::getProjectionHandler cannot get handler for " << getRole() <<endl;
+   }
+   return projHandler;
+}
+
+ossimRefPtr<ossimImageGeometry> ossimImageCorrelator::getOutputImageGeometry()
+{
+   ossimRefPtr<ossimImageGeometry> geom = 0;
+   ossimImageHandler* projHandler = getProjectionHandler();
+   if(projHandler)
+   {
+      geom = projHandler->getImageGeometry();
+   }
+   return geom;
+}
+
+//getOutputProjection() - define output projection
+// according to projType
+ossimMapProjection* ossimImageCorrelator::getOutputProjection()
+{
+   ossimMapProjection* mop = 0;
+
+   ossimRefPtr<ossimImageGeometry> geom = getOutputImageGeometry();
+   if( geom.valid() )
+   {
+      if ( geom->getProjection() )
+      {
+         mop = PTR_CAST(ossimMapProjection, geom->getProjection());
+         if( !mop )
+         {
+            ossimDpt mpp = geom->getMetersPerPixel();
+            ossimProjection* outProjection =
+               ossimProjectionFactoryRegistry::instance()->
+               createProjection(ossimString("ossimEquDistCylProjection"));
+            mop = PTR_CAST(ossimMapProjection, outProjection);
+         }
+         
+         if(mop)
+         {
+            mop->setDatum(ossimDatumFactory::instance()->wgs84());
+            mop->update();
+
+            // apply user scale factor (resize)
+            // then hopefully overviews can be used
+            if ( (theScaleRatio != 1.0) && (theScaleRatio>0) )
+            {
+               cout << "applying scale ratio on " << getRole() <<
+                  ": "<<theScaleRatio << endl; //TBR?
+
+               mop->applyScale(ossimDpt(1.0/theScaleRatio,1.0/theScaleRatio),
+                               false);
+            }
+         }
+      }
+      else
+      {
+         cerr << "ossimImageCorrelator::getOutputProjection cannot create projection from " << getRole() <<" geometry." <<endl;
+      }
+   }
+   else
+   {
+      cerr << "ossimImageCorrelator::getOutputProjection cannot get "
+           <<getRole() << " geometry." << endl;
+   }
+
+   return mop;
+}
+
+// buildRenerer() - builds renderer for an imageSource
+// accounts for :
+//  -scale factor
+//  -required projection
+bool ossimImageCorrelator::buildRenderer(
+   ossimImageChain* chain,
+   ossimMapProjection* outProjection, 
+   ossimImageRenderer* renderer,
+   const ossimFilterResampler::ossimFilterResamplerType& stype ) const
+{
+   if(chain)
+   {
+      chain->add(new ossimCacheTileSource);
+      ossimRefPtr<ossimImageGeometry> geom = chain->getImageGeometry();
+      if(geom.valid()&&geom->getProjection())
+      {       
+         ossimImageViewProjectionTransform* transform = new ossimImageViewProjectionTransform;
+         transform->setImageGeometry(geom.get());
+         transform->setViewGeometry(new ossimImageGeometry(0, outProjection));
+         renderer->setImageViewTransform(transform);
+         renderer->getResampler()->setFilterType(stype);
+         chain->add(renderer);
+         chain->add(new ossimCacheTileSource);
+      }
+      else
+      {
+         cerr<<"ossimImageCorrelator"<<"::buildRenderer cannot get projection from master/slave"<<endl;
+         return false;
+      }      
+   }
+   else
+   {
+      cerr<<"ossimImageCorrelator"<<"::buildRenderer NULL source"<<endl;
+      return false;
+   }
+   return true;
+}
+
+
+bool 
+ossimImageCorrelator::execute()
+{
+   bool result=true;
+
+   if(theMChain.valid())
+   {
+      theMChain->disconnect();
+   }
+   if(theSChain.valid())
+   {
+      theSChain->disconnect();
+   }
+   theMChain = new ossimImageChain;
+   theSChain = new ossimImageChain;
+
+   // -- 1 -- create source handlers
+   handlerM = ossimImageHandlerRegistry::instance()->open(theMaster);
+   if (!handlerM)
+   {
+      cerr<<"ossimImageCorrelator"<<"::execute can't create handler for master image "<< theMaster <<endl;
+      return false;
+   }
+   theMChain->add(handlerM.get());
+   handlerS = ossimImageHandlerRegistry::instance()->open(theSlave);
+   if (!handlerS)
+   {
+      cerr<<"ossimImageCorrelator"<<"::execute can't create handler for slave image  "<< theSlave <<endl;
+      return false;
+   }
+   theSChain->add(handlerS.get());
+   ossimRefPtr<ossimImageSource> theMasterSource = handlerM.get();
+
+   // select only one band (if multiple)
+   ossim_uint32 mbc = theMChain->getNumberOfOutputBands();//handlerM->getNumberOfOutputBands();
+   if (mbc>1)
+   {
+      //add a band selector
+      ossim_uint32 mb = getMasterBand();
+      if (mb>=mbc) 
+      {
+         cerr<<"ossimImageCorrelator"<<"::execute Warning not enough bands in master, only "<< mbc <<endl;
+         mb=0;
+      }
+      cout<<"Using band "<<mb<<" for master"<<endl; //TBR
+      theMasterBandSelector = new ossimBandSelector;
+      theMasterBandSelector->connectMyInputTo(0, handlerM.get());
+      theMasterBandSelector->setOutputBandList(vector<ossim_uint32>(1,mb));
+
+      theMasterSource = theMasterBandSelector.get();
+      theMChain->add(theMasterBandSelector.get());
+   }
+   ossim_uint32 sbc = theSChain->getNumberOfOutputBands();//handlerS->getNumberOfOutputBands();
+   if (sbc>1)
+   {
+      //add a band selector
+      ossim_uint32 sb = getSlaveBand();
+      if (sb>=sbc) 
+      {
+         cerr<<"ossimImageCorrelator"<<"::execute Warning not enough bands in slave, only "<< sbc <<endl;
+         sb=0;
+      }
+      cout<<"Using band "<<sb<<" for slave"<<endl; //TBR
+      theSlaveBandSelector = new ossimBandSelector;
+      theSlaveBandSelector->connectMyInputTo(0, handlerS.get());
+      theSlaveBandSelector->setOutputBandList(vector<ossim_uint32>(1,sb));
+//      theSlaveSource = theSlaveBandSelector;
+      theSChain->add(theSlaveBandSelector.get());
+   }
+
+   // -- 2 -- initialize blocks
+   //init renderers
+   ossimMapProjection* outProj = getOutputProjection();
+   if (outProj)
+   {
+      rendererM = new ossimImageRenderer;
+      
+      result = buildRenderer(theMChain.get(), outProj, rendererM.get()); //TBD : update method //index 0 is for master
+      if (!result) return result;
+      
+      rendererS = new ossimImageRenderer;  
+      result = buildRenderer(theSChain.get(), outProj, rendererS.get()); //index 1 is for slave
+      if (!result) return result;
+   }
+   else
+   {
+      return false;
+   }
+   //init corner Detector
+   cornerDetector->setK(0.05); //hardcoded
+   cornerDetector->setGaussStd(getTemplateRadius() / 2.0); //TBC : hardcoded ratio
+   cornerDetector->setDensity(getCornerDensity());
+
+   //init casters
+   caster[0]->setOutputScalarType(OSSIM_FLOAT64);
+   caster[1]->setOutputScalarType(OSSIM_FLOAT64);
+
+   //init matcher
+   matcher->setSlaveAccuracy(getSlaveAccuracy() * getScaleRatio()); //adapt pixel radius according to scale
+   matcher->setMasterRadius(getTemplateRadius()); //in sync with GaussStd for corners
+   matcher->setBias(ossimDpt(0.0,0.0));
+   matcher->setMinNCC(getMinCorrel());
+
+   generator->close();
+   generator->open();
+   //init gen
+   generator->setOutputName("difftiepts.txt"); //create on the fly image diff text file //TBR
+   generator->setStoreFlag(true); //also keep all tie points in memory
+
+   //TBD : set area of interest to buffer around slave?
+
+   // -- 3 -- tie blocks, from sources to outputs
+
+   caster[0]->connectMyInputTo(0, theMChain.get());
+   caster[1]->connectMyInputTo(0, theSChain.get());
+   cornerDetector->connectMyInputTo(0,theMChain.get());
+   matcher->connectMyInputTo(0,cornerDetector.get());
+   matcher->connectMyInputTo(1,caster[0].get()); // master
+   matcher->connectMyInputTo(2,caster[1].get()); // slave
+   generator->connectMyInputTo(0,matcher.get());
+
+   // -- 4 -- run
+   result = generator->execute();
+
+   const vector<ossimTDpt>& tp = generator->getTiePoints();
+
+   computeDispStats(tp); //TBR ?
+
+   // -- 7 -- convert "Image to Image" to "Ground to Image" tie points    //TBC : use more generic tie points
+   theTset.clearTiePoints();
+
+   //get image<->original image transform for slave
+   ossimImageViewTransform* st = rendererS->getImageViewTransform();
+
+   ossimRefPtr<ossimImageGeometry> geom = getOutputImageGeometry();
+   if ( geom.valid() )
+   {
+      for(vector<ossimTDpt>::const_iterator it = tp.begin();
+          it != tp.end() ;
+          ++it)
+      {
+         ossimRefPtr<ossimTieGpt> tgi(new ossimTieGpt);
+         //set master ground pos
+         geom->localToWorld( it->getMasterPoint() , *tgi ); //TBC : is it always lon/lat WGS84?
+         //set slave image position
+         st->viewToImage( it->getMasterPoint() + it->getSlavePoint() , tgi->refImagePoint() );
+         //set score
+         tgi->setScore(it->score);
+         
+         //add to list
+         theTset.addTiePoint(tgi);
+      }
+   }
+   
+   theTset.setMasterPath(theMaster);
+   theTset.setSlavePath(theSlave);
+
+   //slave image accuracy (pixel)
+   NEWMAT::SymmetricMatrix icov(2);
+   icov=0.0;
+   icov(1,1)= std::pow(0.5 * st->getOutputMetersPerPixel().x / st->getInputMetersPerPixel().x, 2);
+   icov(2,2)= std::pow(0.5 * st->getOutputMetersPerPixel().y / st->getInputMetersPerPixel().y, 2);
+   theTset.setImageCov(icov);
+
+   //master ground precision (degrees)
+   NEWMAT::SymmetricMatrix gcov(3);
+   gcov=0.0;
+   gcov(1,1) = std::pow(outProj->getDecimalDegreesPerPixel().x*0.5, 2);
+   gcov(2,2) = std::pow(outProj->getDecimalDegreesPerPixel().y*0.5, 2);
+   gcov(3,3) = std::pow(30.0, 2); //elevation accuracy, meters^2, harcoded TBC
+   theTset.setGroundCov(gcov);
+
+   // -- 8 -- export as XML/GML
+   ossimRefPtr<ossimXmlNode> set_node = theTset.exportAsGmlNode();
+   ossimXmlDocument gmlDoc;
+   gmlDoc.initRoot(set_node); //need namespaces etc...
+   gmlDoc.write(getOutputName());
+
+   theHasRun = true;
+   return true;
+}
+
+bool
+ossimImageCorrelator::isOpen() const
+{
+   if(generator.valid())
+   {
+      return generator->isOpen();
+   }
+   return false;
+}
+
+bool
+ossimImageCorrelator::open()
+{
+   if(generator.valid())
+   {
+      return generator->open();
+   }
+
+   return false;
+}
+
+void
+ossimImageCorrelator::close()
+{
+   if(generator.valid())
+   {
+      return generator->close();
+   }
+}
+
+bool
+ossimImageCorrelator::addListener(ossimListener* listener)
+{
+   if(generator.valid())
+   {
+      return generator->addListener(listener);
+   }
+
+   return false;
+}
+
+bool
+ossimImageCorrelator::removeListener(ossimListener* listener)
+{
+   if(generator.valid())
+   {
+      return generator->removeListener(listener);
+   }
+
+   return false;
+}
+
+void
+ossimImageCorrelator::computeDispStats(const vector<ossimTDpt>& tp)const
+{
+   // -- 5 -- 2D statistics for tie points displacements
+   // get 1st and 2nd moments
+
+   cout<<"Statistics for tie point displacements"<<endl;
+   cout<<"number of tie points="<<tp.size()<<endl;
+   vector<ossimTDpt>::const_iterator it;
+
+   double isr  = 1.0/getScaleRatio();
+   double isr2 = isr*isr;
+   //mean
+   double sx=0.0, sy=0.0;
+   for (it = tp.begin() ; it != tp.end() ; ++it)
+   {
+      sx += it->tie.x;
+      sy += it->tie.y;
+   }
+   sx /= tp.size(); //mean values
+   sy /= tp.size();
+   cout <<"Mean displacements: mx="<<sx*isr<<" my="<<sy*isr<<endl;
+
+   //x,y correlation
+   double dx,dy;
+   double sx2=0.0, sy2=0.0, sxy=0.0;
+   for (it = tp.begin() ; it != tp.end() ; ++it)
+   {
+      dx = it->tie.x - sx;
+      dy = it->tie.y - sy;
+      sx2 += dx*dx;
+      sxy += dx*dy;
+      sy2 += dy*dy;
+   }
+   sx2 /= tp.size();
+   sy2 /= tp.size();
+   sxy /= tp.size();
+
+   cout <<"Correlation coeffs: Cx2="<<sx2*isr2<<" Cxy="<<sxy*isr2<<" Cy2="<<sy2*isr2<<endl;
+   //calculate eigenvalues + angle for major axis
+   double delta = pow(sx2-sy2,2) + 4*pow(sxy,2);
+   double lmax = 0.5*( sx2+sy2 + sqrt(delta) ); //>=0
+   double lmin = 0.5*( sx2+sy2 - sqrt(delta) ); //>=0
+   double dirx = sx2 - lmax, diry = -sxy; //direction vector for major axis
+   double angle = atan2(-diry, dirx); //invert y since image is oriented downwards and we want map oriented angles
+   cout<<"RMS along eigen axes : rmax="<<sqrt(lmax)*isr<<" rmin="<<sqrt(lmin)*isr<<endl;
+   cout<<"Major axis angle with x axis (degrees): "<< angle / M_PI * 180.0<<endl; 
+}
+
+void ossimImageCorrelator::setProperty(ossimRefPtr<ossimProperty> property)
+{
+   if(!property.valid())
+   {
+      return;
+   }
+   
+   ossimString name = property->getName();
+   
+   if(name == "master_filename")
+   {
+      setMaster(ossimFilename(property->valueToString()));
+   }
+   else if(name == "slave_filename")
+   {
+      setSlave(ossimFilename(property->valueToString()));
+   }
+   else if(name == "master_band")
+   {
+      setMasterBand(property->valueToString().toUInt32());
+   }
+   else if(name == "slave_band")
+   {
+      setSlaveBand(property->valueToString().toUInt32());
+   }
+   else if(name == "scale_ratio")
+   {
+      setScaleRatio(property->valueToString().toFloat64());
+   }
+   else if(name == "corner_density")
+   {
+      setCornerDensity(property->valueToString().toFloat64());
+   }
+   else if(name == "min_correl")
+   {
+      setMinCorrel(property->valueToString().toFloat64());
+   }
+   else if(name == "template_radius")
+   {
+      setTemplateRadius(property->valueToString().toUInt32());
+   }
+   else if(name == "slave_accuracy")
+   {
+      setSlaveAccuracy(property->valueToString().toFloat64());
+   }
+   else if(name == "projection_type")
+   {
+      setProjectionType(property->valueToString());
+   }
+   else if(name == "output_filename")
+   {
+      setOutputName(property->valueToString());
+   }
+   else
+   {
+      ossimOutputSource::setProperty(property);
+   }
+}
+
+ossimRefPtr<ossimProperty> ossimImageCorrelator::getProperty(const ossimString& name)const
+{
+   ossimRefPtr<ossimProperty> result = 0;
+   
+   if(name == "master_filename")
+   {
+      ossimFilenameProperty* filenameProp =
+         new ossimFilenameProperty(name, getMaster());
+      
+      filenameProp->setIoType(ossimFilenameProperty::ossimFilenamePropertyIoType_INPUT);
+      
+      return filenameProp;
+   }
+   else if(name == "slave_filename")
+   {
+      ossimFilenameProperty* filenameProp =
+         new ossimFilenameProperty(name, getSlave());
+      
+      filenameProp->setIoType(ossimFilenameProperty::ossimFilenamePropertyIoType_INPUT);
+      
+      return filenameProp;
+   }
+   else if(name == "master_band")
+   {
+      return new ossimStringProperty(name, ossimString::toString(getMasterBand()));
+   }
+   else if(name == "slave_band")
+   {
+      return new ossimStringProperty(name, ossimString::toString(getSlaveBand()));
+   }
+   else if(name == "scale_ratio")
+   {
+      return new ossimStringProperty(name, ossimString::toString(getScaleRatio()));
+   }
+   else if(name == "corner_density")
+   {
+      return new ossimStringProperty(name, ossimString::toString(getCornerDensity()));
+   }
+   else if(name == "min_correl")
+   {
+      return new ossimStringProperty(name, ossimString::toString(getMinCorrel()));
+   }
+   else if(name == "template_radius")
+   {
+      return new ossimStringProperty(name, ossimString::toString(getTemplateRadius()));
+   }
+   else if(name == "slave_accuracy")
+   {
+      return new ossimStringProperty(name, ossimString::toString(getSlaveAccuracy()));
+   }
+   else if(name == "projection_type")
+   {
+      return new ossimStringProperty(name, getProjectionType());
+   }
+   else if(name == "output_filename")
+   {
+      ossimFilenameProperty* filenameProp =
+         new ossimFilenameProperty(name, theOutputName);
+      
+      filenameProp->setIoType(ossimFilenameProperty::ossimFilenamePropertyIoType_OUTPUT);
+      
+      return filenameProp;
+   }
+   else
+   {
+      return ossimOutputSource::getProperty(name);
+   }
+
+   return result;
+}
+
+void ossimImageCorrelator::getPropertyNames(std::vector<ossimString>& propertyNames)const
+{
+   
+   propertyNames.push_back("master_filename");
+   propertyNames.push_back("slave_filename");
+   propertyNames.push_back("master_band");
+   propertyNames.push_back("slave_band");
+   propertyNames.push_back("scale_ratio");
+   propertyNames.push_back("corner_density");
+   propertyNames.push_back("min_correl");
+   propertyNames.push_back("template_radius");
+   propertyNames.push_back("slave_accuracy");
+   propertyNames.push_back("projection_type");
+   propertyNames.push_back("output_filename");
+}
diff --git a/ossim_plugins/registration/ossimImageCorrelator.h b/ossim_plugins/registration/ossimImageCorrelator.h
new file mode 100644
index 0000000..bf11356
--- /dev/null
+++ b/ossim_plugins/registration/ossimImageCorrelator.h
@@ -0,0 +1,147 @@
+// ossimImageCorrelator
+// class for getting tie-points from a master/slave image pair
+//
+// TODO : generate one file only : XML or Tabulated Text
+// TODO : change TieGPtSet to a generic TiePtSet
+// TODO : increase speed
+
+#ifndef ossimImageCorrelator_HEADER
+#define ossimImageCorrelator_HEADER
+
+#include <ossim/base/ossimString.h>
+#include <ossim/base/ossimFilename.h>
+#include <ossim/base/ossimOutputSource.h>
+#include <ossim/base/ossimProcessInterface.h>
+#include <ossim/base/ossimProcessProgressEvent.h>
+#include <ossim/imaging/ossimFilterResampler.h>
+#include <ossim/imaging/ossimImageChain.h>
+#include <ossim/imaging/ossimImageHandler.h>
+#include <ossim/imaging/ossimBandSelector.h>
+#include <ossim/imaging/ossimImageRenderer.h>
+#include <ossim/imaging/ossimCastTileSourceFilter.h>
+#include <ossim/base/ossimTDpt.h>
+#include <ossim/base/ossimTieGptSet.h>
+#include "ossimRegistrationExports.h"
+#include "ossimHarrisCorners.h"
+#include "ossimTieGenerator.h"
+#include "ossimChipMatch.h"
+#include <vector>
+
+class ossimImageGeometry;
+class ossimMapProjection;
+class ossimListenerManager;
+
+class OSSIM_REGISTRATION_DLL ossimImageCorrelator :
+    public ossimOutputSource,
+    public ossimProcessInterface
+{
+public:
+   ossimImageCorrelator();
+   virtual ~ossimImageCorrelator();
+
+   //accessors to parms
+   inline void               setMaster(const ossimFilename& m) { theMaster=m; }
+   inline const ossimFilename& getMaster()const { return theMaster; }
+   inline void               setSlave(const ossimFilename& s) { theSlave=s; }
+   inline const ossimFilename& getSlave()const { return theSlave; }
+   inline void               setMasterBand(ossim_uint32 b) { theMasterBand=b; }
+   inline ossim_uint32       getMasterBand()const { return theMasterBand; }
+   inline void               setSlaveBand(ossim_uint32 b) { theSlaveBand=b; }
+   inline ossim_uint32       getSlaveBand()const { return theSlaveBand; }
+   inline void               setScaleRatio(const ossim_float64& r) { theScaleRatio=r; }
+   inline ossim_float64      getScaleRatio()const { return theScaleRatio; }
+   inline void               setSlaveAccuracy(const ossim_float64& a) { theSlaveAccuracy=a; }
+   inline ossim_float64      getSlaveAccuracy()const { return theSlaveAccuracy; }
+   inline void               setProjectionType(const ossimString& p) { theProjectionType=p; }
+   inline const ossimString& getProjectionType()const { return theProjectionType; }
+   inline void               setCornerDensity(const ossim_float64& a) { theCornerDensity=a; }
+   inline ossim_float64      getCornerDensity()const { return theCornerDensity; }
+   inline void               setMasterPointProj(const ossimString& p) { theMasterPointProj=p; }
+   inline const ossimString& getMasterPointProj()const { return theMasterPointProj; }
+   inline void               setSlavePointProj(const ossimString& p) { theSlavePointProj=p; }
+   inline const ossimString& getSlavePointProj()const { return theSlavePointProj; }
+   inline void               setTemplateRadius(const ossim_uint32& r) { theTemplateRadius = r; }
+   inline ossim_uint32       getTemplateRadius()const { return theTemplateRadius; }
+   inline void               setMinCorrel(const ossim_float64& c) { theMinCorrel=c; }
+   inline ossim_float64      getMinCorrel()const { return theMinCorrel; }   
+   
+   inline bool hasRun()const { return theHasRun; }
+
+   // inherited methods
+   virtual bool isOpen() const;
+   virtual bool open();
+   virtual void close();
+
+   virtual bool  execute(); //also creates tie point file
+   virtual       ossimObject* getObject()      { return this; }
+   virtual const ossimObject* getObject()const { return this; }
+   virtual       ossimObject* getObjectInterface() { return this; }
+
+   virtual ossimListenerManager* getListenerManagerInterface() { return this; }
+   virtual bool addListener(ossimListener *listener);
+   virtual bool removeListener(ossimListener *listener);
+
+   virtual bool canConnectMyInputTo(ossim_int32 inputIndex,const ossimConnectableObject* object)const { return false; } //TBC : so far no input
+
+   virtual void setProperty(ossimRefPtr<ossimProperty> property);
+   virtual ossimRefPtr<ossimProperty> getProperty(const ossimString& name)const;
+   virtual void getPropertyNames(std::vector<ossimString>& propertyNames)const;
+
+protected:  
+
+   ossimString         getRole() const;
+   ossimImageHandler*  getProjectionHandler();
+   
+   ossimRefPtr<ossimImageGeometry> getOutputImageGeometry();
+
+   ossimMapProjection* getOutputProjection();
+   
+   bool buildRenderer(
+      ossimImageChain* chain,
+//         ossimImageSource* source, 
+         ossimMapProjection* outProjection, 
+         ossimImageRenderer* renderer,
+         const ossimFilterResampler::ossimFilterResamplerType& stype =  ossimFilterResampler::ossimFilterResampler_CUBIC
+         )const;
+
+   void computeDispStats(const vector<ossimTDpt>& tp)const;
+   void rejectOutliersMedian(const vector<ossimTDpt>& tp, vector<ossimTDpt>& ftp, const ossim_float64& relError);
+   void getMedianInlier1D(const vector<double>& sd, const ossim_float64& relError, ossim_float64& median, ossim_uint32& inlierCount);
+
+   ossimFilename   theMaster;
+   ossimFilename   theSlave;
+   ossim_uint32  theMasterBand;
+   ossim_uint32  theSlaveBand;
+   ossim_float64 theScaleRatio;
+   ossim_float64 theSlaveAccuracy;
+   ossim_float64 theCornerDensity;
+   ossimString   theProjectionType;
+   ossimString   theMasterPointProj;
+   ossimString   theSlavePointProj;
+   ossim_uint32  theTemplateRadius; //in pixels
+   ossim_float64 theMinCorrel;
+
+   bool theHasRun; //to know whether execute has been run
+
+   ossimRefPtr<ossimImageChain> theMChain;
+   ossimRefPtr<ossimImageChain> theSChain;
+   
+   ossimRefPtr<ossimImageHandler>   handlerM;
+   ossimRefPtr<ossimImageHandler>   handlerS;
+   ossimRefPtr<ossimBandSelector>   theMasterBandSelector;
+   ossimRefPtr<ossimBandSelector>   theSlaveBandSelector;
+   ossimRefPtr<ossimImageRenderer>  rendererM;
+   ossimRefPtr<ossimImageRenderer>  rendererS;
+   ossimRefPtr<ossimHarrisCorners>  cornerDetector;
+   std::vector<ossimRefPtr<ossimCastTileSourceFilter> > caster;
+   ossimRefPtr<ossimChipMatch>      matcher;
+   ossimRefPtr<ossimTieGenerator>   generator;
+   ossimTieGptSet       theTset;
+
+   //! Disallow operator=
+   const ossimImageCorrelator& operator=(const ossimImageCorrelator& rhs) {return rhs;}
+
+TYPE_DATA
+};
+
+#endif //ossimImageCorrelator_HEADER
diff --git a/ossim_plugins/registration/ossimModelOptimizer.cpp b/ossim_plugins/registration/ossimModelOptimizer.cpp
new file mode 100644
index 0000000..44190c4
--- /dev/null
+++ b/ossim_plugins/registration/ossimModelOptimizer.cpp
@@ -0,0 +1,279 @@
+//*******************************************************************
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author: Frederic Claudel (fclaudel at laposte.net)
+//         ICT4EO,Meraka Institute,CSIR
+//
+// Description: generic model optimization, high-level interface
+//
+//*************************************************************************
+#include "ossimModelOptimizer.h"
+#include <ossim/base/ossimXmlDocument.h>
+#include <ossim/base/ossimNotifyContext.h>
+#include <ossim/base/ossimEcefPoint.h>
+#include <ossim/base/ossimEcefVector.h>
+#include <ossim/base/ossimStringProperty.h>
+#include <ossim/base/ossimFilenameProperty.h>
+#include <ossim/projection/ossimOptimizableProjection.h>
+#include <ossim/projection/ossimProjectionFactoryRegistry.h>
+
+#include <vector>
+#include <algorithm>
+#include <cmath>
+#include <ctime> //for randomizing with time
+
+RTTI_DEF2(ossimModelOptimizer, "ossimModelOptimizer", ossimConnectableObject, ossimProcessInterface);
+
+ossimModelOptimizer::ossimModelOptimizer() :
+   ossimConnectableObject(0, 0, 0),
+   theTiesetFilename(""),
+   theModelDefinitionString("ossimPolynomProjection{1 x y x2 xy y2 x3 y3 xy2 x2y z xz yz}"),
+   theGeomOutputFilename("modopt.geom")
+{
+   //randomize
+   std::srand(std::time(0));
+}
+
+bool
+ossimModelOptimizer::loadGMLTieSet(const ossimString& filepath)
+{
+   // import GML SimpleTiePoints
+
+   //open file and load full XML
+   ossimXmlDocument gmlDoc;
+   bool res = gmlDoc.openFile(filepath);
+   if (!res) {
+      ossimNotify(ossimNotifyLevel_WARN) << 
+         "WARNING: ossimModelOptimizer::loadGMLTieSet cannot open file "<<filepath<<"\n";
+      return false;
+   }
+   
+   //parse XML structure for ONE set of tie point
+   std::vector< ossimRefPtr< ossimXmlNode > > tieSetList;
+   gmlDoc.findNodes(ossimString("/") + ossimTieGptSet::TIEPTSET_TAG, tieSetList);
+
+   if (tieSetList.size() != 1)
+   {
+      ossimNotify(ossimNotifyLevel_WARN) << 
+         "WARNING: ossimModelOptimizer::loadGMLTieSet need exactly one element of type "<<
+         ossimTieGptSet::TIEPTSET_TAG<<", found "<<tieSetList.size()<<"\n";
+      return false;
+   }
+
+   //get the TieSet object
+   res = theTieSet.importFromGmlNode(tieSetList[0]);
+   if (!res) {
+      ossimNotify(ossimNotifyLevel_WARN) << 
+         "WARNING: ossimModelOptimizer::loadGMLTieSet error when decoding XML tie point info\n";
+      return false;
+   }
+
+   theTiesetFilename = filepath;
+   return true;
+}
+
+bool
+ossimModelOptimizer::execute()
+{
+   if(!setupModel(theModelDefinitionString))
+   {
+      return false;
+   }
+   ossim_float64 variance_pix2;
+   if(optimize(&variance_pix2, NULL)) //TBD: add target variance?
+   {
+      //display results with unit
+      cout<<"RMS="<<std::sqrt(variance_pix2)<<" pixels"<<endl;
+
+      if(theGeomOutputFilename!="")
+      {
+         if(!exportModel(theGeomOutputFilename)) return false;
+      }
+   } else {
+      return false;
+   }
+
+   return true;
+}
+
+bool
+ossimModelOptimizer::optimize(ossim_float64* result_var_pix2,
+                              ossim_float64* target_var_pix2)
+{
+   //init optional variance to error
+   if (result_var_pix2!=NULL) *result_var_pix2 = -1.0;
+
+   if(!theModel.valid()) return false;
+
+   //build optimization proj
+   ossimOptimizableProjection* opp = PTR_CAST(ossimOptimizableProjection, theModel.get());
+
+   if (!opp) return false;
+
+   // get meter_per_pixel ratio
+   double varRatio;
+   if (opp->useForward())
+   {
+      varRatio = 1.0;
+   } else {
+      //converts pixel variance (pix2) to image variance (m2)
+      ossimDpt mpp(theModel->getMetersPerPixel());
+      varRatio = (mpp.x*mpp.x + mpp.y*mpp.y) / 2.0;
+   }
+
+   //check that enough info
+   unsigned int minTPC = (opp->degreesOfFreedom()+1)/2;
+   if (minTPC > theTieSet.size())
+   {
+      ossimNotify(ossimNotifyLevel_WARN) << 
+      "WARNING: ossimModelOptimizer::optimize() should use more than "<<minTPC<<" tie points for model: "<<theModelDefinitionString<<"\n";
+   }
+
+   //optimize (using optional target variance)
+   ossim_float64  target_var;
+   ossim_float64* ptarget_var = NULL;
+   if (target_var_pix2)
+   {
+      target_var = (*target_var_pix2) * varRatio;
+      ptarget_var = &target_var;
+   }
+   
+   ossim_float64 variance = opp->optimizeFit(theTieSet, ptarget_var);
+   if (variance<0)
+   {
+      ossimNotify(ossimNotifyLevel_WARN) << 
+      "WARNING: ossimModelOptimizer::optimize() failed optimization for "<<theModelDefinitionString<<"\n";
+      return false;
+   }
+   //convert to pixel2 variance
+   ossim_float64 variance_pix2 = variance / varRatio;
+
+   //normal exit : return optional variance
+   if (result_var_pix2!=NULL) *result_var_pix2 = variance_pix2;
+   return true;
+}
+
+bool 
+ossimModelOptimizer::setupModel(const ossimString& description)
+{
+   theModel = 0;
+   ossimString argProj = description;
+   argProj=argProj.after("{").trim();
+   if (argProj != "")
+   {
+      argProj = argProj.before("}");
+      argProj.trim();
+   }
+   ossimString projName=description;
+   projName = projName.before("{");
+
+   theModelDefinitionString = description;
+   //create projection for rejection
+   ossimProjection* inlierProj = ossimProjectionFactoryRegistry::instance()->createProjection(projName);
+   if (!inlierProj)
+   {
+      ossimNotify(ossimNotifyLevel_FATAL) << 
+         "FATAL: ossimModelOptimizer::setupModel() can't create projection "<<projName<<"\n";
+         return false;
+   }
+   //check if it is an optimizable projection //TBD: create a factory instead, so to get lists?
+   ossimOptimizableProjection* opp = PTR_CAST(ossimOptimizableProjection, inlierProj);
+   if (!opp)
+   {
+      ossimNotify(ossimNotifyLevel_FATAL) << 
+         "FATAL: ossimModelOptimizer::setupModel() rejection projection is not optimizable "<<projName<<"\n";
+         return false;
+   }
+
+   //tune projection parameters
+   if (argProj != "")
+   {
+      bool res = opp->setupOptimizer(argProj);
+      if (!res)
+      {
+         ossimNotify(ossimNotifyLevel_FATAL) << 
+         "FATAL: ossimModelOptimizer::setupModel() projection cannot initialize with given args : "<<argProj<<"\n";
+         return false;
+      }
+   }
+   theModel = inlierProj;
+
+   return true;
+}
+
+bool
+ossimModelOptimizer::exportModel(const ossimFilename& geomFile)const
+{
+   ossimKeywordlist rpc_kwl;
+   if(!theModel.valid())
+   {
+      return false;
+   }
+   theModel->saveState(rpc_kwl);
+   rpc_kwl.write(geomFile);
+
+   //normal exit
+   return true;
+}
+
+void
+ossimModelOptimizer::setProperty(ossimRefPtr<ossimProperty> property)
+{
+   if(!property.valid()) return;
+   
+   ossimString name = property->getName();
+
+   if(name=="model_definition")
+   {
+      setupModel(property->valueToString());
+   }
+   else if(name=="gml_tieset_filename")
+   {
+      loadGMLTieSet(property->valueToString());
+   }
+   else if(name=="geom_output_filename")
+   {
+      theGeomOutputFilename = ossimFilename(property->valueToString());
+   }
+}
+
+ossimRefPtr<ossimProperty>
+ossimModelOptimizer::getProperty(const ossimString& name)const
+{
+   if(name == "model_definition")
+   {
+      return new ossimStringProperty(name, theModelDefinitionString);
+   }
+   else if(name == "geom_output_filename")
+   {
+      ossimFilenameProperty* filenameProp =
+         new ossimFilenameProperty(name, theGeomOutputFilename);
+      
+      filenameProp->setIoType(ossimFilenameProperty::ossimFilenamePropertyIoType_OUTPUT);
+      
+      return filenameProp;
+   }
+   else if(name == "gml_tieset_filename")
+   {
+      ossimFilenameProperty* filenameProp =
+         new ossimFilenameProperty(name, theTiesetFilename);
+      
+      filenameProp->setIoType(ossimFilenameProperty::ossimFilenamePropertyIoType_OUTPUT);
+      
+      return filenameProp;
+   }
+
+   return 0;
+}
+
+void
+ossimModelOptimizer::getPropertyNames(std::vector<ossimString>& propertyNames)const
+{
+   propertyNames.push_back("model_definition");
+   propertyNames.push_back("gml_tieset_filename");
+   propertyNames.push_back("geom_output_filename");
+}
+
diff --git a/ossim_plugins/registration/ossimModelOptimizer.h b/ossim_plugins/registration/ossimModelOptimizer.h
new file mode 100644
index 0000000..69b99ce
--- /dev/null
+++ b/ossim_plugins/registration/ossimModelOptimizer.h
@@ -0,0 +1,92 @@
+#ifndef ossimModelOptimizer_HEADER
+#define ossimModelOptimizer_HEADER
+
+#include <ossim/base/ossimObject.h>
+#include <ossim/base/ossimConnectableObject.h>
+#include <ossim/base/ossimPropertyInterface.h>
+#include <ossim/base/ossimProcessInterface.h>
+#include <ossim/base/ossimProcessProgressEvent.h>
+#include <ossim/base/ossimRefPtr.h>
+#include <ossim/base/ossimString.h>
+#include <ossim/base/ossimTieGptSet.h>
+#include <ossim/projection/ossimProjection.h>
+#include "ossimRegistrationExports.h"
+
+/*!
+ * class ossimModelOptimizer
+ * class for optimizing an existing projection model or creating new model from a set of tie points
+ *
+ * you can use ossimImageCorrelator to get an input (object ossimTieGptSet)
+ *
+ */
+class OSSIM_REGISTRATION_DLL ossimModelOptimizer : public ossimConnectableObject,
+                                                   public ossimProcessInterface
+{
+public:
+   ossimModelOptimizer();
+   virtual ~ossimModelOptimizer() {}
+
+   bool canConnectMyInputTo(ossim_int32 inputIndex,
+                            const ossimConnectableObject* object)const
+   {
+      return false;
+   }
+  /*!
+   * accessors to parms
+   */   
+   inline void  setTieSet(const ossimTieGptSet& aTieSet) { theTieSet=aTieSet; }
+   inline const ossimTieGptSet& getTieSet()const { return theTieSet; }
+
+   inline void  setTiesetFilename(const ossimString& t) { theTiesetFilename = t; }
+   inline const ossimString& getTiesetFilename()const { return theTiesetFilename; }
+
+   inline void  setModelDefinitionString(const ossimString& t) { theModelDefinitionString = t; }
+   inline const ossimString& getModelDefinitionString()const { return theModelDefinitionString; }
+
+   inline void  setGeomOutputFilename(const ossimFilename& op) { theGeomOutputFilename=op; }
+   inline const ossimFilename& getGeomOutputFilename()const { return theGeomOutputFilename; }
+
+   inline ossimRefPtr< ossimProjection > refModel()const { return theModel; }
+
+   bool loadGMLTieSet(const ossimString& filepath); //! file can be generated by correl
+
+   virtual bool setupModel(const ossimString& description);
+   virtual bool exportModel(const ossimFilename& geomFile)const;
+
+   /*!
+    * ossimObject interface
+    */
+   virtual       ossimObject* getObject()      { return this; }
+   virtual const ossimObject* getObject()const { return this; }
+   virtual       ossimObject* getObjectInterface() { return this; }
+
+   /*!
+    * property interface
+    */
+   virtual void setProperty(ossimRefPtr<ossimProperty> property);
+   virtual ossimRefPtr<ossimProperty> getProperty(const ossimString& name)const;
+   virtual void getPropertyNames(std::vector<ossimString>& propertyNames)const;
+
+   /* !
+    * optimization method: 
+    * returns: true for success
+    *          variance , unit pixel^2(if pointer not NULL)
+    * INPUT: target variance in pixel^2 (optional)
+    */
+   virtual bool optimize(ossim_float64* result_var_pix2 = NULL,
+                         ossim_float64* target_var_pix2 = NULL);
+
+   virtual bool execute(); //!process interface to run model optimization
+
+protected:
+   ossimTieGptSet                 theTieSet;
+   ossimString                    theTiesetFilename;
+   ossimString                    theModelDefinitionString;
+   ossimFilename                  theGeomOutputFilename;
+   ossimRefPtr< ossimProjection > theModel;
+
+   inline ossimModelOptimizer(const ossimModelOptimizer& copyme) {} //!disable copy constructor
+   TYPE_DATA
+};
+
+#endif //ossimModelOptimizer_HEADER
diff --git a/ossim_plugins/registration/ossimMultiplier.cpp b/ossim_plugins/registration/ossimMultiplier.cpp
new file mode 100644
index 0000000..59a9cb2
--- /dev/null
+++ b/ossim_plugins/registration/ossimMultiplier.cpp
@@ -0,0 +1,328 @@
+// class ossimMultiplier implementation
+// REQUIRES FFTW version 3.x (Fast Fourier Transform)
+
+#include "ossimMultiplier.h"
+#include <ossim/imaging/ossimImageDataFactory.h>
+#include <ossim/base/ossimIrect.h>
+
+RTTI_DEF1( ossimMultiplier, "ossimMultiplier", ossimImageCombiner );
+
+ossimMultiplier::ossimMultiplier()
+   :
+   ossimImageCombiner()
+{
+}
+
+ossimMultiplier::ossimMultiplier(ossimObject *owner,         
+                                 ossimImageSource *left,
+                                 ossimImageSource *right)
+   :ossimImageCombiner(owner,
+   2,
+   0,
+   true,
+   false)
+{
+   connectMyInputTo(0, left);
+   connectMyInputTo(1, right);
+}
+
+ossimMultiplier::~ossimMultiplier()
+{ 
+}
+
+bool
+ossimMultiplier::canConnectMyInputTo(ossim_int32 index,const ossimConnectableObject* object)const
+{
+   //check that inputs just have one band
+   //max 3 inputs
+   //TBD: check scalar types
+   switch(index)
+   {
+   case 0:
+   case 1:
+      {
+      ossimImageSource* imagep=PTR_CAST(ossimImageSource, object);
+      if (imagep)
+      {
+         return true;
+      } else {
+         return false;
+      }
+      }
+      break;
+   default:
+      return false;
+   }
+}
+
+ossimRefPtr<ossimImageData>
+ossimMultiplier::getTile(const ossimIrect &rect, ossim_uint32 resLevel)
+{
+   if ( (!theNormTile) || (!theMin.size()) )
+   {
+      initialize();
+   }
+
+   long w = rect.width();
+   long h = rect.height();
+   long tw = theNormTile->getWidth();
+   long th = theNormTile->getHeight();
+
+   theNormTile->setImageRectangle(rect);
+
+   if(w*h != tw*th)
+   {
+     theNormTile->initialize();
+   }
+   else
+   {
+      theNormTile->makeBlank();
+   }
+
+   switchTypeRun(rect, resLevel);
+   
+   return theNormTile;
+}
+
+//switchTypeRun: updates theNormTile
+void
+ossimMultiplier::switchTypeRun(const ossimIrect &tileRect, ossim_uint32 resLevel)
+{   
+   //get scalar type & check
+   if (hasDifferentInputs())
+   {
+      ossimNotify(ossimNotifyLevel_WARN)
+         << "All input scalar types must be identical"<< endl;
+      return;
+   }
+   //type template
+   switch(theNormTile->getScalarType())
+   {
+      case OSSIM_UINT8:
+      {
+            operate(static_cast<ossim_uint8>(0),
+                               tileRect,
+                               resLevel);
+            break;
+      }
+      case OSSIM_SINT8:
+      {
+            operate(static_cast<ossim_sint8>(0),
+                               tileRect,
+                               resLevel);
+            break;
+      }
+      case OSSIM_UINT16:
+      case OSSIM_USHORT11:
+      {
+           operate(static_cast<ossim_uint16>(0),
+                               tileRect,
+                               resLevel);
+           break;
+      }
+      case OSSIM_SINT16:
+      {
+           operate(static_cast<ossim_sint16>(0),
+                               tileRect,
+                               resLevel);
+           break;
+      }
+      case OSSIM_SINT32:
+      {
+            operate(static_cast<ossim_sint32>(0),
+                               tileRect,
+                               resLevel);
+            break;
+      }
+      case OSSIM_UINT32:
+      {
+            operate(static_cast<ossim_uint32>(0),
+                               tileRect,
+                               resLevel);
+            break;
+      }
+      case OSSIM_FLOAT: 
+      case OSSIM_NORMALIZED_FLOAT:
+      {
+           operate(static_cast<ossim_float32>(0),
+                               tileRect,
+                               resLevel);
+           break;
+      }
+      case OSSIM_DOUBLE:
+      case OSSIM_NORMALIZED_DOUBLE:
+      {
+            operate(static_cast<ossim_float64>(0),
+                               tileRect,
+                               resLevel);
+            break;
+      }
+      case OSSIM_SCALAR_UNKNOWN:
+      default:
+      {
+         ossimNotify(ossimNotifyLevel_WARN)
+            << "Scalar type = " << theNormTile->getScalarType()
+            << " Not supported by ossimMultiplier" << endl;
+         break;
+      }
+   }
+   theNormTile->validate();
+}
+
+template <class T>
+void
+ossimMultiplier::operate( T,// dummy template variable 
+                             const ossimIrect& tileRect,
+                             ossim_uint32 resLevel)
+{
+   ossimImageSource* left  = PTR_CAST(ossimImageSource, getInput(0));
+   ossimImageSource* right = PTR_CAST(ossimImageSource, getInput(1));
+   double v;
+   if (left && right)
+   {
+      ossimRefPtr<ossimImageData> leftD  = left->getTile(tileRect, resLevel);
+      ossimRefPtr<ossimImageData> rightD = right->getTile(tileRect, resLevel);
+      if ((leftD.valid()) && (rightD.valid()) && (leftD->getDataObjectStatus() != OSSIM_EMPTY) && (rightD->getDataObjectStatus() != OSSIM_EMPTY))
+      {
+         ossim_uint32 upperBound = theNormTile->getWidth() * theNormTile->getHeight();
+         for(ossim_uint32 band = 0; band < theNormTile->getNumberOfBands(); ++band)
+         {
+            T* leftBand      = static_cast<T*>(leftD->getBuf(band));
+            T* rightBand     = static_cast<T*>(rightD->getBuf(band));
+            T* destBand      = static_cast<T*>(theNormTile->getBuf(band));
+            double minv      = theMin[band];
+            double maxv      = theMax[band];
+            double leftNull  = leftD->getNullPix(band);
+            double rightNull = rightD->getNullPix(band);
+
+            if(leftBand&&rightBand)
+            {
+               for(ossim_uint32 offset = 0; offset < upperBound; ++offset)
+               {
+                  if (((double)*leftBand != leftNull) && ((double)*rightBand != rightNull))
+                  {
+                     v = *leftBand * (*rightBand);
+                     //must still check for "overflows"
+                     if (v > maxv) v = maxv;
+                     if (v < minv) v = minv;
+                  
+                     *destBand = static_cast<T>(v);
+                  } //else : destination already blank
+                  
+                  ++leftBand; ++rightBand; ++destBand;
+               }
+            }
+         }
+      }
+   }
+}
+
+void 
+ossimMultiplier::initialize()
+{
+   ossimImageCombiner::initialize();
+   theNormTile = ossimImageDataFactory::instance()->create(this, this);
+   theNormTile->initialize();  //TBD: change tile creation so it isn't within initialize 
+   computeMinMax(); //TBC : is it the right place?
+}
+
+double
+ossimMultiplier::getNullPixelValue(ossim_uint32 band)const
+{
+   return ossim::defaultNull(getOutputScalarType());
+}
+
+double
+ossimMultiplier::getMinPixelValue(ossim_uint32 band)const
+{
+   if (band<theMin.size())
+   {
+      return theMin[band];
+   } else {
+      return ossim::defaultMin(getOutputScalarType());
+   }
+}
+
+double 
+ossimMultiplier::getMaxPixelValue(ossim_uint32 band)const
+{
+   if (band<theMax.size())
+   {
+      return theMax[band];
+   } else {
+      return ossim::defaultMax(getOutputScalarType());
+   }
+}
+
+void
+ossimMultiplier::computeMinMax()
+{
+   // use monotony of (x,y) |-> x*y on lines and rows
+   // => test only four corners and keep min/max
+   ossimImageSource* left  = PTR_CAST(ossimImageSource, getInput(0));
+   ossimImageSource* right = PTR_CAST(ossimImageSource, getInput(1));
+
+   //maximum span: default values
+   double defMin = ossim::defaultMin(getOutputScalarType());
+   double defMax = ossim::defaultMax(getOutputScalarType());
+
+   theMin.clear();
+   theMax.clear();
+
+   //new values
+   if (left && right)
+   {
+      for (ossim_uint32 band=0;band<getNumberOfOutputBands();++band)
+      {
+         double leftspan[2] = { left->getMinPixelValue(band)  , left->getMaxPixelValue(band)  };
+         double rightspan[2]= { right->getMinPixelValue(band) , right->getMaxPixelValue(band) };
+         double v;
+         double minv = defMax; //crossed min-max
+         double maxv = defMin;
+         for (int l=0;l<2;++l)
+         {
+            for (int r=0;r<2;++r)
+            {
+               v = leftspan[l] * rightspan[r];
+               if (v < minv) minv=v;
+               if (v > maxv) maxv=v;
+            }
+         }         
+         theMin.push_back( (minv>defMin) ? minv : defMin );
+         theMax.push_back( (maxv<defMax) ? maxv : defMax );
+      }
+   }
+}
+
+ossim_uint32
+ossimMultiplier::getNumberOfOutputBands()const
+{   
+   ossimImageSource* left  = PTR_CAST(ossimImageSource, getInput(0));
+   ossimImageSource* right = PTR_CAST(ossimImageSource, getInput(1));
+   if (left && right)
+   {
+      return std::min( left->getNumberOfOutputBands(), right->getNumberOfOutputBands() );
+   } else {
+      return 0;
+   }
+}
+
+ossimIrect
+ossimMultiplier::getBoundingRect(ossim_uint32 resLevel)const
+{
+   ossimImageSource* left  = PTR_CAST(ossimImageSource, getInput(0));
+   ossimImageSource* right = PTR_CAST(ossimImageSource, getInput(1));
+   ossimIrect res;
+   if (left && right)
+   {
+     //Intersect rectangles
+     res = left->getBoundingRect(resLevel);
+     res.clipToRect(right->getBoundingRect(resLevel));
+   } 
+   else
+   {
+      res.makeNan();
+   }
+   return res;
+}
+
diff --git a/ossim_plugins/registration/ossimMultiplier.h b/ossim_plugins/registration/ossimMultiplier.h
new file mode 100644
index 0000000..5a1cd10
--- /dev/null
+++ b/ossim_plugins/registration/ossimMultiplier.h
@@ -0,0 +1,52 @@
+// class ossimMultiplier : Image Combiner
+
+#ifndef ossimMultiplier_HEADER
+#define ossimMultiplier_HEADER
+
+#include <ossim/imaging/ossimImageCombiner.h>
+#include <ossim/base/ossimDpt.h>
+#include <ossim/base/ossimTDpt.h>
+#include <vector>
+#include "ossimRegistrationExports.h"
+/**
+ * class ossimMultiplier : Image Combiner
+ * product of input images, of same scalar type
+ *
+ * restrict to minimum number of bands of inputs
+ * no NODATA values used
+ * TODO : any number of inputs
+ *        support any operation : + / -
+ */
+class OSSIM_REGISTRATION_DLL ossimMultiplier : public ossimImageCombiner
+{
+public:
+   //own public methods
+   ossimMultiplier();
+   ossimMultiplier(ossimObject *owner,         
+                   ossimImageSource *left,
+                   ossimImageSource *right);
+   virtual ~ossimMultiplier();   
+   
+   //inherited public methods
+   virtual void                        initialize();
+   virtual bool                        canConnectMyInputTo(ossim_int32 index,const ossimConnectableObject* object)const;
+   virtual double                      getNullPixelValue(ossim_uint32 band)const;
+   virtual double                      getMinPixelValue(ossim_uint32 band=0)const;
+   virtual double                      getMaxPixelValue(ossim_uint32 band=0)const;
+
+   virtual ossim_uint32                getNumberOfOutputBands()const;
+   virtual ossimIrect                  getBoundingRect(ossim_uint32 resLevel=0)const;
+
+   virtual ossimRefPtr<ossimImageData> getTile (const ossimIrect &rect, ossim_uint32 resLevel=0);   
+
+protected:
+   std::vector<double> theMin;
+   std::vector<double> theMax;
+
+   void computeMinMax();
+   void switchTypeRun(const ossimIrect &rect, ossim_uint32 resLevel);
+   template<class T> void operate( T, const ossimIrect& tileRect, ossim_uint32 resLevel);
+
+TYPE_DATA
+};
+#endif
diff --git a/ossim_plugins/registration/ossimNCC_FFTW.cpp b/ossim_plugins/registration/ossimNCC_FFTW.cpp
new file mode 100644
index 0000000..1c55b3e
--- /dev/null
+++ b/ossim_plugins/registration/ossimNCC_FFTW.cpp
@@ -0,0 +1,269 @@
+#include "ossimNCC_FFTW.h"
+#include "ossimRunningSum.h"
+
+#include <cmath>
+
+ossimNCC_FFTW::ossimNCC_FFTW(int cy, int cx, const char* wisdom)
+ : _mx(0),
+   _my(0),
+   _sx(0),
+   _sy(0),
+   _cx(cx),
+   _cy(cy),
+   _pcx(2*(cx/2+1)),
+   _NCC(cy,2*(cx/2+1)),
+   _PS(cy,2*(cx/2+1)),
+   _srs(NULL),
+   _mavg(0.0),
+   _mstd(0.0),
+   _savg(0.0),
+   _sstd(0.0),
+   _maxy(0),
+   _maxx(0),
+   _maxncc(-2)
+{
+   //re-use wisdom (if provided) : IMPORTANT don't exchange wisdom strings across different systems !
+   if (wisdom)
+   {
+      fftw_import_wisdom_from_string(wisdom);
+   }
+
+
+   //create plans : TBC TBD use different planner flags?
+   _splan = fftw_plan_dft_r2c_2d(_cy, 
+                                 _cx,
+                                 _PS.refBuffer(),
+                                 (double(*)[2])_PS.refBuffer(),
+                                 FFTW_MEASURE); //note: ESTIMATE flag does nor erase input/output buffer
+   _mplan = fftw_plan_dft_r2c_2d(_cy, 
+                                 _cx,
+                                 _NCC.refBuffer(),
+                                 (double(*)[2])_NCC.refBuffer(),
+                                 FFTW_MEASURE);
+   //inverse FFT (inplace)
+   _ccplan = fftw_plan_dft_c2r_2d(_cy, 
+                                  _cx,
+                                  (double(*)[2])_NCC.refBuffer(),
+                                  _NCC.refBuffer(),
+                                  FFTW_MEASURE);
+}
+
+ossimNCC_FFTW::~ossimNCC_FFTW()
+{
+   //delete plans (matrices are automatically discarded)
+   fftw_destroy_plan(_ccplan);
+   fftw_destroy_plan(_mplan);
+   fftw_destroy_plan(_splan);
+   //delete running sum
+   if (_srs!=NULL)
+   {
+      delete _srs;
+      _srs=NULL;
+   }
+}
+
+bool
+ossimNCC_FFTW::sameDims(int tcy, int tcx)const
+{
+   return ((tcx==_cx)&&(tcy==_cy));
+}
+
+void
+ossimNCC_FFTW::ingestMaster(int my,int mx, const double* master)
+{
+   //IMPORTANT NOTE this will overwrite the stored NCC
+   if ((my>_cy) || (mx>_cx) || (master==NULL))
+   {
+      //TBD error mngt
+      std::cerr<<"ingestMaster input error"<<std::endl;
+      return;
+   }
+   //store master dims
+   _my=my;
+   _mx=mx;
+
+   //calculate stats
+   moments1(_mx*_my, master, &_mavg, &_mstd);
+
+   //rotate180 master & remove mean, then pad to correlation size   
+   double* pm = _NCC.refBuffer();
+   const double* rm = master + (_mx*_my-1); //last position
+   int i,j;
+   for(i=0;i<_my;++i)
+   {
+      for(j=0;j<_mx;++j)
+      {
+         *(pm++) = *(rm--) - _mavg; // master minus average, reversed pm
+      }
+      for(;j<_pcx;++j) *(pm++)=0.0;
+   }
+   for(;i<_cy;++i) for(j=0;j<_pcx;++j) *(pm++)=0.0;
+}
+
+void
+ossimNCC_FFTW::ingestSlave(int sy, int sx, const double* slave)
+{   
+   if ((sy>_cy) || (sx>_cx) || (slave==NULL))
+   {
+      //TBD error mngt
+      std::cerr<<"ingestSlave input error"<<std::endl;
+      return;
+   }
+   //store slave dims
+   _sy=sy;
+   _sx=sx;
+
+   //calculate running sums
+   if (_srs != NULL) delete _srs;
+   _srs = new ossimRunningSum(_sy, _sx, slave);
+   _savg = _srs->getAverage();
+   _sstd = _srs->getStd();
+
+   //pad slave
+   double* ps= _PS.refBuffer();
+   const double* fs = slave; //first position
+
+   int i,j;
+   for(i=0;i<_sy;++i)
+   {
+      for(j=0;j<_sx;++j)
+      {
+         *(ps++) = *(fs++) - _savg; //remove average value
+      }
+      for(;j<_pcx;++j) *(ps++)=0.0;
+   }
+   for(;i<_cy;++i) for(j=0;j<_pcx;++j) *(ps++)=0.0;
+}
+
+//calculate NCC based on master & slave
+//also stores the maximum NCC position
+bool
+ossimNCC_FFTW::calculateNCC()
+{
+   //check master & slave dimensions
+   if ((_cx != _sx+_mx-1) || (_cy != _sy+_my-1))
+   {
+      //TBD err mngt
+      std::cerr<<"calculateNCC input error"<<std::endl;
+      return false;
+   }
+
+   //transform padded reversed master & padded slave to freq. space
+   fftw_execute(_splan);
+   fftw_execute(_mplan);
+
+   //multiply master by slave in freq. space (half transform only)
+   const double* s = _PS.getBuffer();
+   double*       m = _NCC.refBuffer();
+   double rr;
+   int i,j;
+   for(i=0;i<_cy;++i) 
+   {
+      for(j=0;j<_cx/2+1;++j) //number of complex coeffs (halfed because of real transform)
+      {
+          //own complex multiplication - could be faster(can't use latest complex type)
+         rr   = s[0] * m[0] - s[1] * m[1] ; //real part
+         m[1] = s[1] * m[0] + s[0] * m[1] ; //imaginary part
+         m[0] = rr;
+         m+=2;
+         s+=2;
+      }
+      //note: no jump over padding
+   }
+
+   //transform back to image space : correlation
+   fftw_execute(_ccplan);
+
+   //normalize correlation (for unnormalized FFT in FFTW + local variance of slave)
+   // MASTER cannot be flat because of feature detection (std=0)
+   // use only parts where MASTER is fully included in SLAVE
+   double invmpix= 1.0 / ((double)_mx*_my);
+   double cnorm  = invmpix / (_mstd * (double)_cy*_cx); //cx*cy is due to unnormalized FFT in FFTW //TBC
+   int psi,pei,psj,pej;
+   double wsum,wstd;
+   double maxncor=-2000000;
+   int maxy=-1;
+   int maxx=-1;
+   int startx = _mx-1;
+   int starty = _my-1;
+   int endx   = _sx-1;
+   int endy   = _sy-1;
+   double* pcc   = _NCC.refBuffer() + startx + starty * _pcx;
+
+   for(i=starty;i<endy;++i) 
+   {
+      for(j=startx;j<endx;++j)
+      {
+         //get std & average for master window over PADDED slave
+         psi=i-_my; 
+         pei=i; //master position start& end relatively to slave
+         psj=j-_mx; 
+         pej=j;         
+         wsum =           (_srs->getRS (pei,pej) + _srs->getRS (psi,psj) - _srs->getRS (pei,psj) - _srs->getRS (psi,pej)) * invmpix;
+         wstd = std::sqrt((_srs->getRS2(pei,pej) + _srs->getRS2(psi,psj) - _srs->getRS2(pei,psj) - _srs->getRS2(psi,pej)) * invmpix - wsum*wsum);
+
+         if (wstd > 1e-13)
+         {
+            *pcc = *pcc * cnorm / wstd;
+         } else {
+            *pcc = 0.0;
+         }
+         //keep max index
+         if (maxncor<*pcc) 
+         {
+            maxncor=*pcc;
+            maxy=i; 
+            maxx=j;
+         }
+         ++pcc;
+      }
+
+      pcc+=_pcx-(_sx-_mx);
+   }
+   _maxy   = maxy;
+   _maxx   = maxx;
+   _maxncc = maxncor;
+   return true;
+}
+
+std::string
+ossimNCC_FFTW::getWisdom()const
+{
+   char* ws=fftw_export_wisdom_to_string();
+   if (ws)
+   {
+      std::string s(ws);
+      fftw_free(ws);
+      return s;
+   }
+   return std::string();
+}
+
+void
+ossimNCC_FFTW::moments1(int length, const double* table, double* avg, double* std)const
+{
+   if ((length<=0) || (table==NULL)) return;
+
+   int i;
+   double t;
+   double sum  = 0.0;
+   double sum2 = 0.0;
+   for (i=0;i<length;++i)
+   {
+      t=*(table++);
+      sum  += t;
+      sum2 += t*t;
+   }
+   sum  /= length;
+   sum2 /= length;
+
+   //update output parms
+   if (avg)
+   {
+     *avg = sum;
+   }
+   if (std)
+   {
+      *std = std::sqrt(sum2-sum*sum);
+   }
+}
diff --git a/ossim_plugins/registration/ossimNCC_FFTW.h b/ossim_plugins/registration/ossimNCC_FFTW.h
new file mode 100644
index 0000000..73d332e
--- /dev/null
+++ b/ossim_plugins/registration/ossimNCC_FFTW.h
@@ -0,0 +1,174 @@
+// class for carrying out a series of Normalized Cross Correlations
+// makes use of FFTW plans for speed
+
+#ifndef ossimNCC_FFTW_HEADER
+#define ossimNCC_FFTW_HEADER
+
+#include <fftw3.h>
+#include <string>
+#include <iostream>
+#include <fstream>
+#include <iomanip>
+
+class ossimRunningSum;
+
+class ossimNCC_FFTW
+{
+public:
+
+   //inner class cMatrix for handling double matrices allocated with FFTW
+class cMatrix
+{
+public:
+  cMatrix(int sd, int fd) : _buf(NULL), _fd(fd), _sd(sd)
+  {
+     _buf = (double*)fftw_malloc(sizeof(double)*_fd*_sd);
+  }
+  virtual ~cMatrix()
+  {
+     if (_buf!=NULL) {
+        fftw_free(_buf);
+        _buf = NULL;
+     }     
+  }
+  inline int      fd()const {return _fd;} //fast dimension (column count)
+  inline int      sd()const {return _sd;} //slow dimension
+  inline double*       refBuffer()      {return _buf;}
+  inline const double* getBuffer()const {return _buf;}
+
+  inline double operator()(int fd, int sd)const { return _buf[sd*_fd + fd]; }
+
+  //fill block within matrix with a specified value
+  virtual void fill(double f, int left=0,int top=0, int right=-1, int bottom=-1)
+  {
+     if (right<0)
+     {
+        right = _fd;
+     }
+     if (bottom<0)
+     {
+        bottom = _sd;
+     }
+     double* p = _buf + left + top*_fd;
+     int i,j;
+     for(i=top;i<bottom;++i)
+     {
+        for (j=left;j<right;++j)
+        {
+           *(p++) = f;
+        }
+        p+=left+_fd-right;
+     }
+  }
+  
+  //text output to stream
+  virtual std::ostream& print(std::ostream& os)const
+  {
+     const double* p = _buf;
+     int i,j;
+     for(i=0;i<_sd;++i)
+     {
+        for (j=0;j<_fd;++j)
+        {
+           os<<std::setprecision(10)<<std::setw(18)<<*(p++)<<"\t";
+        }
+        os<<std::endl;
+     }
+     return os;
+  }
+
+  //default is to append matrix
+  virtual void write(const char* fname,
+                      const char* title=NULL,
+                      std::ios_base::openmode mode=std::ios_base::app) const
+  {
+     std::ofstream fs(fname, mode | std::ios_base::out);
+     if (fs.is_open())
+     {
+        if (fs.good())
+        {
+           if (title)
+           {
+              fs<<"cMatrix="<<title<<std::endl;
+           }
+           //do the actual print
+           print(fs);
+        } else {
+           std::cerr<<"cannot successfully open file "<<fname<<" for matrix output"<<std::endl;
+        }
+        fs.close();
+     } else {
+        std::cerr<<"cannot open file "<<fname<<" for matrix output"<<std::endl;
+     }
+  }
+
+protected:
+  double*  _buf;
+  int _fd;
+  int _sd;
+};
+
+//end of inner class cMatrix
+
+
+//constructor allocates buffers and prepares FFTW plans
+//can't change dimensions of NCC
+//can re-use existing wisdom string if provided
+   ossimNCC_FFTW(int cy, int cx, const char* wisdom=0);
+   virtual ~ossimNCC_FFTW();
+
+   bool sameDims(int tcy, int tcx)const; //check dimensions
+
+   void ingestMaster(int my, int mx, const double* master);
+   void ingestSlave (int sy, int sx, const double* slave);
+
+   //must ingest master and slave first
+   virtual bool calculateNCC();
+
+   //master not valid after calculateNCC
+   inline const cMatrix& getPRMaster()const      { return _NCC; } //reversed padded
+   inline const cMatrix& getPSlave()const      { return _PS; } //padded
+
+   //must calculateNCC() first
+   inline const cMatrix& getNcc()const      { return _NCC; }
+   inline double         getMaxCorr()const  { return _maxncc; }
+   inline int            getMaxCorrX()const { return _maxx; }
+   inline int            getMaxCorrY()const { return _maxy; }
+
+   //optional methods
+   inline double         getMasterStd()const { return _mstd; }
+   inline double         getSlaveStd()const  { return _sstd; }
+   inline double         getSlaveAvg()const  { return _savg; }
+
+   //used to keep FFTW wisdom after object destruction
+   std::string getWisdom()const;
+
+protected:
+   int _mx;
+   int _my;
+   int _sx;
+   int _sy;
+   int _cx;
+   int _cy;
+   int _pcx; //physical cx (padded for R2C inplace tranform)
+   cMatrix _NCC; //used for padded master AND NCC
+   cMatrix _PS;  //used for padded slave
+
+   fftw_plan _mplan; //stored plans
+   fftw_plan _splan;
+   fftw_plan _ccplan;
+
+   ossimRunningSum* _srs;
+   double _mavg; //master average
+   double _mstd; //master standard deviation
+   double _savg;
+   double _sstd;
+   int _maxy; //position for maximum NCC value in the matrix
+   int _maxx;
+   double _maxncc; //maximum ncc value
+
+   void moments1(int length, const double* table, double* avg, double* std)const;
+
+};
+
+#endif
diff --git a/ossim_plugins/registration/ossimOutlierRejection.cpp b/ossim_plugins/registration/ossimOutlierRejection.cpp
new file mode 100644
index 0000000..c8a862e
--- /dev/null
+++ b/ossim_plugins/registration/ossimOutlierRejection.cpp
@@ -0,0 +1,314 @@
+
+#include "ossimOutlierRejection.h"
+#include <ossim/base/ossimXmlDocument.h>
+#include <ossim/base/ossimNotifyContext.h>
+#include <ossim/base/ossimEcefPoint.h>
+#include <ossim/base/ossimEcefVector.h>
+#include <ossim/projection/ossimOptimizableProjection.h>
+#include <ossim/projection/ossimProjectionFactoryRegistry.h>
+#include <ossim/base/ossimStringProperty.h>
+#include <ossim/base/ossimNumericProperty.h>
+#include <ossim/base/ossimFilenameProperty.h>
+#include <vector>
+#include <algorithm>
+#include <cmath>
+
+RTTI_DEF1(ossimOutlierRejection, "ossimOutlierRejection", ossimModelOptimizer);
+
+ossimOutlierRejection::ossimOutlierRejection() : 
+       ossimModelOptimizer(),
+       theInlierRatio(0.6),
+       theInlierImageAccuracy(1.0),
+       theInlierOutputFilename("inlier.xml")
+{
+   //change default name to avoid confusion
+   setGeomOutputFilename("rejout.xml");
+}
+
+bool
+ossimOutlierRejection::saveGMLTieSet(const ossimString& filepath)
+{
+   //create a XML document
+   ossimXmlDocument gmlDoc;
+   
+   gmlDoc.initRoot(theTieSet.exportAsGmlNode());
+
+   bool res = gmlDoc.write(filepath);
+   if (!res) {
+      ossimNotify(ossimNotifyLevel_WARN) << 
+         "WARNING: ossimOutlierRejection::loadGMLTieSet cannot save tie points as file "<<filepath<<"\n";
+      return false;
+   }
+
+   return true;
+}
+
+/*!
+ * removeOutliers(): use RANdom SAmple Consensus method (RANSAC)
+ * but stops at the first good fit, without looking for better fits
+ */
+bool
+ossimOutlierRejection::removeOutliers(ossim_float64* result_var_pix2,
+                                      ossim_float64* target_var_pix2)
+{
+   //init optional variance to error
+   if (result_var_pix2!=NULL) *result_var_pix2 = -1.0;
+
+   if(!theModel.valid()) return false;
+   
+   static const double SUCCESS = 0.97; //required chance of success for RANSAC
+   static const double NSTD    = 2.2;  //deviations allowed around mean
+   //check args
+   if ((theInlierRatio<=0.0) || (theInlierRatio>1.0))
+   {
+      ossimNotify(ossimNotifyLevel_WARN) << 
+         "WARNING: ossimOutlierRejection::removeOutliers() bad theInlierRatio\n";
+      return false;
+   }
+   ossimOptimizableProjection* optProj = PTR_CAST(ossimOptimizableProjection, theModel.get());
+   if(!optProj) return false;
+   
+   //direction of transform (cached)
+   bool useForward = optProj->useForward();
+
+   //keep a copy of projection if it needs initialization
+   ossimKeywordlist initialState;
+   bool nis=optProj->needsInitialState(); //cached
+   if (nis)
+   {
+      //save state //TBD: make the copy/restore faster
+      if (!theModel->saveState(initialState))
+      {
+         ossimNotify(ossimNotifyLevel_WARN) << 
+         "WARNING: ossimOutlierRejection::removeOutliers() can't save projection initial state\n";
+      }
+   }
+
+   // convert error to ground if necessary
+   double imageToGroundRatio;
+   if (useForward)
+   {
+      imageToGroundRatio = 1.0;
+   } else {
+      //convert image error to ground error (meters)
+      imageToGroundRatio = theModel->getMetersPerPixel().length()/std::sqrt(2.0);
+   }
+   double maxFitError = imageToGroundRatio * theInlierImageAccuracy; //either pixels or meters
+
+   unsigned long dof = optProj->degreesOfFreedom();
+   unsigned long dofPerPoint = 2L; //use 2 because only 2 uncorelated equations (height is correlated)
+   unsigned long miniPts = (dof+ dofPerPoint-1) / dofPerPoint; //TBD: shouldn't be lower than nbsamples
+   unsigned long miniInliers = (unsigned long)ceil(theTieSet.size()*theInlierRatio);
+
+   //calculate maximum number of iterations (average and std)
+   double probaAllGood = std::pow(theInlierRatio, (int)miniPts);
+   double avg_iter_max = std::log(SUCCESS) / std::log(1.0-probaAllGood);
+   double std_iter_max = std::sqrt(1.0-probaAllGood) / probaAllGood;
+   long iter_max = (long)ceil(avg_iter_max + NSTD * std_iter_max);
+   ossimNotify(ossimNotifyLevel_WARN) << 
+         "INFO: max number of RANSAC iterations = "<<iter_max<<"\n"; //TBR
+
+   unsigned long nbsamples = theTieSet.size();
+
+   ossimNotify(ossimNotifyLevel_WARN) << 
+        "INFO: samples before RANSAC = "<<nbsamples<<"\n"; //TBR
+
+   //array for random draws : init on identity permutation
+   //high memory cost?
+   vector<unsigned long> vshuf(nbsamples);
+
+   //init random / inliers tie point set from current tie set, but with no ties
+   ossimTieGptSet randSelection;
+   randSelection.setMasterPath(theTieSet.getMasterPath());
+   randSelection.setSlavePath(theTieSet.getSlavePath());
+   randSelection.setImageCov(theTieSet.getImageCov());
+   randSelection.setGroundCov(theTieSet.getGroundCov());
+   double bestfit;
+
+   long iterations = 0;
+   unsigned long npos=0;
+   while(iterations < iter_max)
+   {
+
+      //TBD: find out why we need to reset that index table at every iteration
+      for(unsigned long c=0; c<nbsamples; ++c) vshuf[c]=c;
+
+      //randomly select miniPts indices
+      for(unsigned long s=0;s<miniPts;++s)
+      {
+         unsigned long rpick = s+(unsigned long)(((double)std::rand())/(1.0+RAND_MAX)*(nbsamples-s)); //between 0 and nbsamples-1 inc.
+         vshuf[s]     = rpick;
+         vshuf[rpick] = s;
+      }
+
+      //use miniPts random tie points for selection
+      randSelection.clearTiePoints();
+      for(unsigned long c=0;c<miniPts;++c) randSelection.addTiePoint( theTieSet.getTiePoints()[vshuf[c]] );
+      
+      //optimize model with random selection
+      double fitvar = optProj->optimizeFit(randSelection, NULL); //best possible fit, do not use target variance here
+
+      //if optimization goes fine, then test it further
+      if ((fitvar>=0) && (fitvar <= maxFitError*maxFitError)) //RMS must be below max distance
+      {
+         //find other compatible points (and enqueue them)
+         npos = miniPts;
+         double perr;
+         for(unsigned long c=miniPts; c<nbsamples; ++c) 
+         {
+            ossimRefPtr< ossimTieGpt > rt = theTieSet.getTiePoints()[vshuf[c]];
+            if (useForward)
+            {
+               perr = (theModel->forward(*rt) - rt->tie).length(); //image error, unit pixels
+            } else {
+               perr = (ossimEcefPoint(theModel->inverse(rt->tie)) - ossimEcefPoint(*rt)).magnitude(); //ground error, unit meters
+            }
+            if (perr <= maxFitError)
+            {
+               //keep the indices after the miniPts first elts
+               vshuf[npos] = c;
+               vshuf[c]    = npos;
+               ++npos;
+            }
+         }
+
+         //DEBUG TBR
+         ossimNotify(ossimNotifyLevel_WARN) << 
+            "INFO: model finds "<<100.0*npos/((double)nbsamples)<<"% inliers\n"; //TBR
+
+         if (npos >= miniInliers )
+         {
+            //re-optimize model with the new possible inliers :
+            //-add new inliers to sleection
+            for(unsigned long c=miniPts;c<npos;++c) randSelection.addTiePoint( theTieSet.getTiePoints()[vshuf[c]] );
+
+            //use target variance
+            if (target_var_pix2!=NULL)
+            {
+               ossim_float64 target_var = (*target_var_pix2) * imageToGroundRatio * imageToGroundRatio;
+               bestfit = optProj->optimizeFit(randSelection, &target_var); //best possible fit with target variance
+            } else {
+               bestfit = optProj->optimizeFit(randSelection); //best possible fit
+            }
+            //assume fit to be OK (which might NOT be the case...)
+            //TBD iterate over minimal number of times
+            break;
+         }
+      }
+
+      if (nis)
+      {
+         //restore initial state //TBD: make the copy/restore faster
+         if (!theModel->loadState(initialState))
+         {
+            ossimNotify(ossimNotifyLevel_WARN) << 
+            "WARNING: ossimOutlierRejection::removeOutliers() can't reload projection initial state at iteration "<<iterations<<"\n";
+         }
+      }
+
+      iterations++;
+   }
+   if (iterations >= iter_max) 
+   {
+      ossimNotify(ossimNotifyLevel_WARN) << 
+         "WARNING: RANSAC didn't find a solution after "<<iterations<<" iterations"<<endl;
+      return false;
+   }
+
+   //keep inliers
+   theTieSet = randSelection;
+   //display results, with RMS always in pixels
+   ossimNotify(ossimNotifyLevel_WARN) << 
+         "INFO: RANSAC solution found after "<<iterations<<" iterations, nbinliers="<<npos<<endl;
+
+   //convert to pixel2 variance
+   ossim_float64 variance_pix2 = bestfit / (imageToGroundRatio * imageToGroundRatio);
+   //normal exit : return optional variance
+   if (result_var_pix2!=NULL) *result_var_pix2 = variance_pix2;
+
+   return true;
+}
+
+void
+ossimOutlierRejection::setProperty(ossimRefPtr<ossimProperty> property)
+{
+   if(!property.valid()) return;
+   
+   ossimString name = property->getName();
+
+   if(name == "inlier_output_filename")
+   {
+      theInlierOutputFilename = ossimFilename(property->valueToString());
+   }
+   else if(name =="inlier_ratio")
+   {
+      setInlierRatio(property->valueToString().toDouble());
+   }
+   else if(name == "inlier_image_accuracy")
+   {
+      setInlierImageAccuracy(property->valueToString().toDouble());
+   }
+   else {
+      ossimModelOptimizer::setProperty(property);
+   }
+}
+
+ossimRefPtr<ossimProperty>
+ossimOutlierRejection::getProperty(const ossimString& name)const
+{
+   if(name == "inlier_ratio")
+   {
+      return new ossimNumericProperty(name, ossimString::toString(theInlierRatio), 0.0, 1.0);
+   }
+   else if(name == "inlier_image_accuracy")
+   {
+      return new ossimNumericProperty(name, ossimString::toString(theInlierImageAccuracy), 0.0, 1e50);
+   }
+   else if(name == "inlier_output_filename")
+   {
+      return new ossimFilenameProperty(name,theInlierOutputFilename); 
+   }
+
+   return ossimModelOptimizer::getProperty(name);
+}
+
+void
+ossimOutlierRejection::getPropertyNames(std::vector<ossimString>& propertyNames)const
+{
+   ossimModelOptimizer::getPropertyNames(propertyNames);
+
+   propertyNames.push_back("inlier_ratio");
+   propertyNames.push_back("inlier_image_accuracy");
+   propertyNames.push_back("inlier_output_filename");
+}
+
+bool
+ossimOutlierRejection::execute()
+{
+   if(!setupModel(theModelDefinitionString))
+   {
+      return false;
+   }
+   ossim_float64 variance_pix2;
+   if(removeOutliers(&variance_pix2, NULL)) //TBD : use target variance
+   {
+      //display RMS with unit
+      cout<<"RMS="<<std::sqrt(variance_pix2)<<" pixels"<<endl;
+
+      //export results
+      if(theGeomOutputFilename!="")
+      {
+         if(!exportModel(theGeomOutputFilename)) return false;
+      }
+      if(theInlierOutputFilename!="")
+      {
+         if(!saveGMLTieSet(theInlierOutputFilename)) return false;
+      }
+   }
+   else
+   {
+      return false;
+   }
+
+   return true;
+}
diff --git a/ossim_plugins/registration/ossimOutlierRejection.h b/ossim_plugins/registration/ossimOutlierRejection.h
new file mode 100644
index 0000000..978b698
--- /dev/null
+++ b/ossim_plugins/registration/ossimOutlierRejection.h
@@ -0,0 +1,73 @@
+//*******************************************************************
+//
+// License: MIT
+//
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author: Frederic Claudel (fclaudel at laposte.net)
+//         ICT4EO,Meraka Institute,CSIR
+//
+// Description: generic model optimization with RANSAC, high-level interface
+//
+//*************************************************************************
+#ifndef ossimOutlierRejection_HEADER
+#define ossimOutlierRejection_HEADER
+
+#include "ossimModelOptimizer.h"
+
+/*!
+ * class ossimOutlierRejection
+ * class for optimizing a model, while dealing with outliers
+ *
+ * exports a model and a set of tie points (opt)
+ * you can use ossimImageCorrelator to get a tie point input (object ossimTieGptSet)
+ */
+class OSSIM_REGISTRATION_DLL ossimOutlierRejection : public ossimModelOptimizer
+{
+public:
+   ossimOutlierRejection();
+   virtual inline ~ossimOutlierRejection() {}
+
+  /**
+   *accessors to parms
+   */   
+   inline void  setInlierRatio(const ossim_float64& v) { theInlierRatio = v; }
+   inline const ossim_float64& getInlierRatio()const { return theInlierRatio; }
+
+   inline void  setInlierImageAccuracy(const ossim_float64& v) { theInlierImageAccuracy = v; }
+   inline const ossim_float64& getInlierImageAccuracy()const { return theInlierImageAccuracy; }
+
+   /*!
+    * export (modified) tie point set
+    */
+   bool saveGMLTieSet(const ossimString& filepath);
+
+   /*!
+    * remove outliers (using RANSAC)
+    * the projection will be modified, and fitted to inliers if success
+    *
+    * RETURNS: true for success
+    *          variance , unit pixel^2 (optional, if pointer not NULL)
+    * INPUT:  target variance in pixel^2 (optional, and not used so far - feb 2006)
+    */
+   virtual bool removeOutliers(ossim_float64* result_var_pix2 = NULL,
+                               ossim_float64* target_var_pix2 = NULL);
+
+   virtual void setProperty(ossimRefPtr<ossimProperty> property);
+   virtual ossimRefPtr<ossimProperty> getProperty(const ossimString& name)const;
+   virtual void getPropertyNames(std::vector<ossimString>& propertyNames)const;
+
+   virtual bool execute();
+   
+protected:
+   ossim_float64 theInlierRatio;         //!between 0 and 1
+   ossim_float64 theInlierImageAccuracy; //!unit pixels
+   ossimFilename theInlierOutputFilename;
+   //disable copy constructor
+   inline ossimOutlierRejection(const ossimOutlierRejection& copyme) {}
+   
+TYPE_DATA   
+};
+
+#endif //ossimOutlierRejection_HEADER
+
diff --git a/ossim_plugins/registration/ossimRegistrationExports.h b/ossim_plugins/registration/ossimRegistrationExports.h
new file mode 100644
index 0000000..cab4e3e
--- /dev/null
+++ b/ossim_plugins/registration/ossimRegistrationExports.h
@@ -0,0 +1,31 @@
+//----------------------------------------------------------------------------
+// Copyright (c) 2005, Garrett Potts, all rights reserved.
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author:  Garrett Potts
+//
+// Description: Constants file for ossim plugins.
+//
+// $Id: ossimRegistrationExports.h 23664 2015-12-14 14:17:27Z dburken $
+//----------------------------------------------------------------------------
+#ifndef ossimRegistrationExports_HEADER
+#define ossimRegistrationExports_HEADER
+
+#if defined(__MINGW32__) || defined(__CYGWIN__) || defined(_MSC_VER) || defined(__VISUALC__) || defined(__BORLANDC__) || defined(__WATCOMC__)
+#  define OSSIM_REGISTRATION_EXPORT __declspec(dllexport)
+#  define OSSIM_REGISTRATION_IMPORT __declspec(dllexport)
+
+#  ifdef OSSIM_REGISTRATION_MAKINGDLL
+#     define OSSIM_REGISTRATION_DLL OSSIM_REGISTRATION_EXPORT
+#  else
+#     define  OSSIM_REGISTRATION_DLL OSSIM_REGISTRATION_IMPORT
+#  endif
+#else
+# define OSSIM_REGISTRATION_DLL
+#endif
+
+#endif /* #ifndef ossimRegistrationExports_HEADER */
+
diff --git a/ossim_plugins/registration/ossimRegistrationImageSourceFactory.cpp b/ossim_plugins/registration/ossimRegistrationImageSourceFactory.cpp
new file mode 100644
index 0000000..51c95d1
--- /dev/null
+++ b/ossim_plugins/registration/ossimRegistrationImageSourceFactory.cpp
@@ -0,0 +1,130 @@
+#include "ossimRegistrationImageSourceFactory.h"
+#include <ossim/base/ossimTrace.h>
+#include "ossimChipMatch.h"
+#include "ossimDensityReducer.h"
+#include "ossimExtremaFilter.h"
+#include "ossimHarrisCorners.h"
+#include "ossimMultiplier.h"
+#include "ossimSquareFunction.h"
+
+#include <ossim/base/ossimObjectFactoryRegistry.h>
+
+RTTI_DEF1(ossimRegistrationImageSourceFactory, "ossimRegistrationImageSourceFactory", ossimImageSourceFactoryBase);
+ossimRegistrationImageSourceFactory* ossimRegistrationImageSourceFactory::theInstance = 0;
+
+static ossimTrace traceDebug("ossimRegistrationImageSourceFactory:debug");
+
+ossimRegistrationImageSourceFactory::ossimRegistrationImageSourceFactory()
+{
+   theInstance = this;
+}
+
+ossimRegistrationImageSourceFactory::ossimRegistrationImageSourceFactory(const ossimRegistrationImageSourceFactory&)
+{
+}
+
+const ossimRegistrationImageSourceFactory& ossimRegistrationImageSourceFactory::operator=(ossimRegistrationImageSourceFactory&)
+{
+   return *this;
+}
+
+ossimRegistrationImageSourceFactory::~ossimRegistrationImageSourceFactory()
+{
+   theInstance = 0;
+   ossimObjectFactoryRegistry::instance()->unregisterFactory(this);
+}
+
+ossimRegistrationImageSourceFactory* ossimRegistrationImageSourceFactory::instance()
+{
+   if(!theInstance)
+   {
+      theInstance = new ossimRegistrationImageSourceFactory;
+   }
+
+   return theInstance;
+}
+
+ossimObject* ossimRegistrationImageSourceFactory::createObject(const ossimString& name)const
+{
+   if(name == STATIC_TYPE_NAME(ossimChipMatch))
+   {
+      return new ossimChipMatch;
+   }
+   else if(name == STATIC_TYPE_NAME(ossimDensityReducer))
+   {
+      return new ossimDensityReducer;
+   }
+   else if(name == STATIC_TYPE_NAME(ossimExtremaFilter))
+   {
+      return new ossimExtremaFilter;
+   }
+   else if(name == STATIC_TYPE_NAME(ossimHarrisCorners))
+   {
+      return new ossimHarrisCorners;
+   }
+   else if(name == STATIC_TYPE_NAME(ossimMultiplier))
+   {
+      return new ossimMultiplier;
+   }
+   else if(name == STATIC_TYPE_NAME(ossimSquareFunction))
+   {
+      return new ossimSquareFunction;
+   }
+
+   return 0;
+}
+
+ossimObject* ossimRegistrationImageSourceFactory::createObject(const ossimKeywordlist& kwl,
+                                                               const char* prefix)const
+{
+   static const char* MODULE = "ossimImageSourceFactory::createSource";
+   
+   ossimString copyPrefix = prefix;
+   ossimObject* result = NULL;
+   
+   if(traceDebug())
+   {
+      CLOG << "looking up type keyword for prefix = " << copyPrefix << endl;
+   }
+
+   const char* lookup = kwl.find(copyPrefix, "type");
+   if(lookup)
+   {
+      ossimString name = lookup;
+      result           = createObject(name);
+      
+      if(result)
+      {
+         if(traceDebug())
+         {
+            CLOG << "found source " << result->getClassName() << " now loading state" << endl;
+         }
+         result->loadState(kwl, copyPrefix.c_str());
+      }
+      else
+      {
+         if(traceDebug())
+         {
+            CLOG << "type not found " << lookup << endl;
+         }
+      }
+   }
+   else
+   {
+      if(traceDebug())
+      {
+         CLOG << "type keyword not found" << endl;
+      }
+   }
+   return result;
+}
+
+void ossimRegistrationImageSourceFactory::getTypeNameList(std::vector<ossimString>& typeList)const
+{
+   typeList.push_back(STATIC_TYPE_NAME(ossimChipMatch));
+   typeList.push_back(STATIC_TYPE_NAME(ossimDensityReducer));
+   typeList.push_back(STATIC_TYPE_NAME(ossimExtremaFilter));
+   typeList.push_back(STATIC_TYPE_NAME(ossimHarrisCorners));
+   typeList.push_back(STATIC_TYPE_NAME(ossimMultiplier));
+   typeList.push_back(STATIC_TYPE_NAME(ossimSquareFunction));
+}
diff --git a/ossim_plugins/registration/ossimRegistrationImageSourceFactory.h b/ossim_plugins/registration/ossimRegistrationImageSourceFactory.h
new file mode 100644
index 0000000..6204565
--- /dev/null
+++ b/ossim_plugins/registration/ossimRegistrationImageSourceFactory.h
@@ -0,0 +1,25 @@
+#ifndef ossimRegistrationImageSourceFactory_HEADER
+#define ossimRegistrationImageSourceFactory_HEADER
+#include <ossim/imaging/ossimImageSourceFactoryBase.h>
+
+class ossimRegistrationImageSourceFactory : public ossimImageSourceFactoryBase
+{
+public:
+   virtual ~ossimRegistrationImageSourceFactory();
+   static ossimRegistrationImageSourceFactory* instance();
+   virtual ossimObject* createObject(const ossimString& name)const;
+   virtual ossimObject* createObject(const ossimKeywordlist& kwl,
+                                     const char* prefix=0)const;
+   virtual void getTypeNameList(std::vector<ossimString>& typeList)const;
+   
+protected:
+   // Hide from use.
+   ossimRegistrationImageSourceFactory();
+   ossimRegistrationImageSourceFactory(const ossimRegistrationImageSourceFactory&);
+   const ossimRegistrationImageSourceFactory& operator=(ossimRegistrationImageSourceFactory&);
+
+   static ossimRegistrationImageSourceFactory* theInstance;
+TYPE_DATA
+};
+
+#endif
diff --git a/ossim_plugins/registration/ossimRegistrationMiscFactory.cpp b/ossim_plugins/registration/ossimRegistrationMiscFactory.cpp
new file mode 100644
index 0000000..9d583df
--- /dev/null
+++ b/ossim_plugins/registration/ossimRegistrationMiscFactory.cpp
@@ -0,0 +1,62 @@
+#include "ossimRegistrationMiscFactory.h"
+#include "ossimImageCorrelator.h"
+#include "ossimOutlierRejection.h"
+#include "ossimModelOptimizer.h"
+#include <ossim/base/ossimKeywordNames.h>
+
+RTTI_DEF1(ossimRegistrationMiscFactory, "ossimRegistrationMiscFactory", ossimObjectFactory);
+
+ossimRegistrationMiscFactory* ossimRegistrationMiscFactory::theInstance = NULL;
+
+ossimRegistrationMiscFactory* ossimRegistrationMiscFactory::instance()
+{
+   if(!theInstance)
+   {
+      theInstance = new ossimRegistrationMiscFactory;
+   }
+
+   return theInstance;
+}
+
+ossimObject* ossimRegistrationMiscFactory::createObject(const ossimString& typeName)const
+{
+   if(typeName == STATIC_TYPE_NAME(ossimImageCorrelator))
+   {
+      return new ossimImageCorrelator;
+   }
+   if(typeName == STATIC_TYPE_NAME(ossimOutlierRejection))
+   {
+      return new ossimOutlierRejection;
+   }
+   if(typeName == STATIC_TYPE_NAME(ossimModelOptimizer))
+   {
+      return new ossimModelOptimizer;
+   }
+
+   return (ossimObject*)NULL;
+}
+
+ossimObject* ossimRegistrationMiscFactory::createObject(const ossimKeywordlist& kwl,
+                                                  const char* prefix)const
+{
+   const char* type = kwl.find(prefix,
+                               ossimKeywordNames::TYPE_KW);
+   ossimString copyPrefix = prefix;
+   if(type)
+   {
+      ossimObject* object = createObject(ossimString(type));
+      if(object)
+      {
+         object->loadState(kwl, copyPrefix.c_str());
+      }
+      return object;
+   }
+   return NULL;  
+}
+
+void ossimRegistrationMiscFactory::getTypeNameList(std::vector<ossimString>& typeList)const
+{
+   typeList.push_back(STATIC_TYPE_NAME(ossimImageCorrelator));
+   typeList.push_back(STATIC_TYPE_NAME(ossimOutlierRejection));
+   typeList.push_back(STATIC_TYPE_NAME(ossimModelOptimizer));
+}
diff --git a/ossim_plugins/registration/ossimRegistrationMiscFactory.h b/ossim_plugins/registration/ossimRegistrationMiscFactory.h
new file mode 100644
index 0000000..5d117b9
--- /dev/null
+++ b/ossim_plugins/registration/ossimRegistrationMiscFactory.h
@@ -0,0 +1,31 @@
+#ifndef ossimRegistrationMiscFactory_HEADER
+#define ossimRegistrationMiscFactory_HEADER
+#include "ossimRegistrationExports.h"
+#include <ossim/base/ossimObjectFactory.h>
+
+class OSSIM_REGISTRATION_DLL ossimRegistrationMiscFactory : public ossimObjectFactory
+{
+public:
+   ossimRegistrationMiscFactory(){}
+    virtual ~ossimRegistrationMiscFactory(){theInstance = 0;}
+   
+   static ossimRegistrationMiscFactory* instance();
+   virtual ossimObject* createObject(const ossimString& typeName)const;
+   virtual ossimObject* createObject(const ossimKeywordlist& kwl,
+                                     const char* prefix=0)const;
+   /*!
+    * This should return the type name of all objects in all factories.
+    * This is the name used to construct the objects dynamially and this
+    * name must be unique.
+    */
+   virtual void getTypeNameList(std::vector<ossimString>& typeList)const;
+   
+protected:
+   static ossimRegistrationMiscFactory* theInstance;
+   
+TYPE_DATA
+
+  
+};
+
+#endif
diff --git a/ossim_plugins/registration/ossimRegistrationPluginInit.cpp b/ossim_plugins/registration/ossimRegistrationPluginInit.cpp
new file mode 100644
index 0000000..18d676f
--- /dev/null
+++ b/ossim_plugins/registration/ossimRegistrationPluginInit.cpp
@@ -0,0 +1,75 @@
+//*******************************************************************
+// Copyright (C) 2005 David Burken, all rights reserved.
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author:  David Burken
+//*******************************************************************
+//  $Id: ossimRegistrationPluginInit.cpp 23664 2015-12-14 14:17:27Z dburken $
+#include <ossim/plugin/ossimSharedObjectBridge.h>
+#include "ossimRegistrationExports.h"
+#include <ossim/base/ossimObjectFactoryRegistry.h>
+#include <ossim/imaging/ossimImageSourceFactoryRegistry.h>
+#include <ossim/imaging/ossimImageWriterFactoryRegistry.h>
+#include <ossim/projection/ossimProjectionFactoryRegistry.h>
+#include "ossimRegistrationImageSourceFactory.h"
+#include "ossimRegistrationMiscFactory.h"
+
+static void setDescription(ossimString& description)
+{
+   description = "Registration Plugin\n\n";
+}
+
+extern "C"
+{
+   static ossimSharedObjectInfo  myInfo;
+   static ossimString theDescription;
+   static std::vector<ossimString> theObjList;
+   static const char* getDescription()
+   {
+      return theDescription.c_str();
+   }
+   static int getNumberOfClassNames()
+   {
+      return (int)theObjList.size();
+   }
+   static const char* getClassName(int idx)
+   {
+      if(idx < (int)theObjList.size())
+      {
+         return theObjList[0].c_str();
+      }
+      return (const char*)0;
+   }
+
+   /* Note symbols need to be exported on windoze... */ 
+   OSSIM_REGISTRATION_DLL void ossimSharedLibraryInitialize(
+                                                            ossimSharedObjectInfo** info, 
+                                                            const char* options)
+   {
+      myInfo.getDescription = getDescription;
+      myInfo.getNumberOfClassNames = getNumberOfClassNames;
+      myInfo.getClassName = getClassName;
+      setDescription(theDescription);
+      ossimImageSourceFactoryRegistry::instance()->registerFactory(ossimRegistrationImageSourceFactory::instance());
+      ossimObjectFactoryRegistry::instance()->registerFactory(ossimRegistrationMiscFactory::instance());
+
+      if(!theObjList.size())
+      {
+         ossimRegistrationImageSourceFactory::instance()->getTypeNameList(theObjList);
+         ossimRegistrationMiscFactory::instance()->getTypeNameList(theObjList);
+      }
+      *info = &myInfo;
+  }
+
+   /* Note symbols need to be exported on windoze... */ 
+  OSSIM_REGISTRATION_DLL void ossimSharedLibraryFinalize()
+  {
+     ossimImageSourceFactoryRegistry::instance()->unregisterFactory(ossimRegistrationImageSourceFactory::instance());
+     ossimObjectFactoryRegistry::instance()->unregisterFactory(ossimRegistrationMiscFactory::instance());
+     
+  }
+}
+
diff --git a/ossim_plugins/registration/ossimRunningSum.cpp b/ossim_plugins/registration/ossimRunningSum.cpp
new file mode 100644
index 0000000..c2340fd
--- /dev/null
+++ b/ossim_plugins/registration/ossimRunningSum.cpp
@@ -0,0 +1,108 @@
+// class ossimRunningSum : impl.
+//
+#include "ossimRunningSum.h"
+#include <math.h>
+
+using namespace std;
+
+ossimRunningSum::ossimRunningSum(int slowdim, int fastdim, const double* table) :
+    theSd(slowdim), 
+    theFd(fastdim),
+    theNormFact(1.0/((double)slowdim*fastdim))
+{
+   //allocate space
+   unsigned long size = slowdim*fastdim;
+   rs.resize(size);
+   rs2.resize(size);
+
+   int i,j;
+   //use two swipes : first integrate along fastdim, then slowdim
+
+   //fisrt swipe (reading table)
+   vector<double>::iterator is  = rs.begin();
+   vector<double>::iterator is2 = rs2.begin();
+   double t=0.0;
+   double s,s2;
+   for (i=0;i<theSd;++i)
+   {
+      t=*(table++);
+      *is  = s  =t; //init first element of row
+      ++is;
+      *is2 = s2 =t*t;
+      ++is2;
+      for (j=1;j<theFd;++j)
+      {
+         t=*(table++);
+         *is  = s  = t   + s;
+         ++is;
+         *is2 = s2 = t*t + s2;
+         ++is2;
+      }
+   }
+   //second swipe (not reading table), starting on second row
+/* 
+   is  = rs.begin()  + theFd;
+   is2 = rs2.begin() + theFd;
+
+   for (i=1;i<theSd;++i)
+   {
+       for (j=0;j<theFd;++j)
+       {
+         *(is++)  += *(is -theFd);
+         *(is2++) += *(is2-theFd);
+      }
+   }
+*/
+   for (i=1;i<theSd;++i) 
+   {
+       for (j=0;j<theFd;++j)
+       {
+         rs [i*theFd+j] += rs [(i-1)*theFd+j];
+         rs2[i*theFd+j] += rs2[(i-1)*theFd+j];
+      }
+   }
+   
+}
+
+ossimRunningSum::~ossimRunningSum()
+{
+}
+   
+double
+ossimRunningSum::getRS(int p1, int p2)const
+{
+   //boundary correction
+   if ((p1<0) || (p2<0))
+   { 
+      return 0.0;
+   }
+   if (p1>=theSd) p1=theSd-1;
+   if (p2>=theFd) p2=theFd-1;   
+   return rs[p1*theFd + p2];
+}
+
+double
+ossimRunningSum::getRS2(int p1, int p2)const
+{
+   //boundary correction
+   if ((p1<0) || (p2<0))
+   { 
+      return 0.0;
+   }
+   if (p1>=theSd) p1=theSd-1;
+   if (p2>=theFd) p2=theFd-1;   
+   return rs2[p1*theFd + p2];
+}
+
+double
+ossimRunningSum::getAverage()const
+{
+   return rs[theSd*theFd-1] * theNormFact;
+}
+
+double
+ossimRunningSum::getStd()const
+{
+   //fabs avoids nan for uniform data
+   return sqrt(fabs( (rs2[theSd*theFd-1]  - rs[theSd*theFd-1]*rs[theSd*theFd-1]*theNormFact) * theNormFact));
+}
diff --git a/ossim_plugins/registration/ossimRunningSum.h b/ossim_plugins/registration/ossimRunningSum.h
new file mode 100644
index 0000000..022db00
--- /dev/null
+++ b/ossim_plugins/registration/ossimRunningSum.h
@@ -0,0 +1,32 @@
+// class ossimRunningSum
+// provides running sum & running sum of squares two dimesnions buffer
+//
+// IMPORTANT: sums are calculated at object creation (hence const in get accessors)
+//
+#ifndef ossimRunningSum_HEADER
+#define ossimRunningSum_HEADER
+
+#include <vector>
+
+class ossimRunningSum
+{
+public:
+   ossimRunningSum(int slowdim, int fastdim, const double* table);
+   virtual ~ossimRunningSum();
+   
+   // those accessors handle out of bounds positions
+   double getRS(int p1, int p2)const;
+   double getRS2(int p1, int p2)const;
+
+   double getAverage()const; //for convenience
+   double getStd()const; //for convenience
+
+protected:
+   int theSd; // slow varying dimension (row number for row-major image)
+   int theFd; // fast varying dim (col number for a row-major image)
+   double theNormFact;
+   std::vector<double> rs;
+   std::vector<double> rs2;
+};
+
+#endif //ossimRunningSum_HEADER
diff --git a/ossim_plugins/registration/ossimSquareFunction.cpp b/ossim_plugins/registration/ossimSquareFunction.cpp
new file mode 100644
index 0000000..7c0f23e
--- /dev/null
+++ b/ossim_plugins/registration/ossimSquareFunction.cpp
@@ -0,0 +1,285 @@
+
+#include "ossimSquareFunction.h"
+#include <ossim/base/ossimIrect.h>
+#include <ossim/imaging/ossimImageDataFactory.h>
+#include <ossim/base/ossimMatrixProperty.h>
+
+RTTI_DEF1(ossimSquareFunction, "ossimSquareFunction", ossimImageSourceFilter);
+
+ossimSquareFunction::ossimSquareFunction(ossimObject* owner)
+   :ossimImageSourceFilter(owner),
+    theTile(NULL)
+{
+}
+
+ossimSquareFunction::~ossimSquareFunction()
+{
+}
+
+ossimRefPtr<ossimImageData> ossimSquareFunction::getTile(
+   const ossimIrect& tileRect,
+   ossim_uint32 resLevel)
+{
+   if(!theInputConnection)
+   {
+      return theTile;
+   }
+
+   if(!isSourceEnabled())
+   {
+      return theInputConnection->getTile(tileRect, resLevel);
+   }
+
+   ossimRefPtr<ossimImageData> data = theInputConnection->getTile(tileRect,
+                                                                  resLevel);
+
+   if(!data.valid() || !data->getBuf())
+   {
+      return data;
+   }
+
+    // First time through or after an initialize()...
+   if (!theTile.valid())
+   {
+      allocate();
+      if (!theTile.valid()) // Should never happen!
+      {
+         return data;
+      }
+   }
+
+   // First time through, after an initialize() or a setKernel()...
+   if (!theNullPixValue.size())
+   {
+      computeNullMinMax();
+      if (!theNullPixValue.size()) // Should never happen!
+      {
+         return data;
+      }
+   }
+
+   theTile->setImageRectangle(tileRect);
+   theTile->makeBlank();
+   
+   switch(data->getScalarType())
+   {
+      case OSSIM_UINT8:
+      { 
+         applyFunction(static_cast<ossim_uint8>(0), data, theTile);
+         break;
+      }
+      case OSSIM_SINT8:
+      { 
+         applyFunction(static_cast<ossim_sint8>(0), data, theTile);
+         break;
+      }
+      case OSSIM_UINT16:
+      case OSSIM_USHORT11:
+      {
+         applyFunction(static_cast<ossim_uint16>(0), data, theTile);         
+         break;
+      }
+      case OSSIM_SINT16:
+      {
+         applyFunction(static_cast<ossim_sint16>(0), data, theTile);         
+         break;
+      }
+      case OSSIM_UINT32:
+      {
+         applyFunction(static_cast<ossim_uint32>(0), data, theTile);         
+         break;
+      }
+      case OSSIM_SINT32:
+      {
+         applyFunction(static_cast<ossim_sint32>(0), data, theTile);         
+         break;
+      }
+      case OSSIM_FLOAT32: 
+      case OSSIM_NORMALIZED_FLOAT:
+      {
+         applyFunction(static_cast<ossim_float32>(0), data, theTile);         
+         break;
+      }
+      case OSSIM_FLOAT64:
+      case OSSIM_NORMALIZED_DOUBLE:
+      {
+         applyFunction(static_cast<ossim_float64>(0), data, theTile);
+         break;
+      }
+      default:
+      {
+         ossimNotify(ossimNotifyLevel_WARN)
+            << "ossimSquareFunction::getTile WARNING:\n"
+            << "Scalar type = " << theTile->getScalarType()
+            << " Not supported by ossimSquareFunction" << endl;
+         break;
+      }
+   }
+   theTile->validate();
+   
+   return theTile;
+}
+
+
+template<class T> 
+void
+ossimSquareFunction::applyFunction( T,
+   ossimRefPtr<ossimImageData> inputData,
+   ossimRefPtr<ossimImageData> outputData)
+{
+   // let's set up some temporary variables so we don't
+   // have to call the functions in loops.  Iknow that compilers
+   // typically optimize this out but if we are in debug mode 
+   // with no optimization it will still run fast
+   //  
+   double v;
+   ossim_uint32 outputW = outputData->getWidth();
+   ossim_uint32 outputH = outputData->getHeight();
+   for(ossim_uint32 band = 0; band < getNumberOfInputBands(); ++band)
+   {
+      T* inputBuf  = static_cast<T*>(inputData->getBuf(band));
+      T* outputBuf = static_cast<T*>(outputData->getBuf(band));
+      T maxPix     = static_cast<T>(getMaxPixelValue(band));
+      T minPix     = static_cast<T>(getMinPixelValue(band));     
+      T nullPix    = static_cast<T>(inputData->getNullPix(band));
+      T oNullPix   = static_cast<T>(getNullPixelValue(band));
+      
+      if(inputBuf&&outputBuf)
+      {
+         for(ossim_uint32 row = 0; row < outputW; ++row)
+         {
+            for(ossim_uint32 col = 0; col < outputH; ++col)
+            {
+
+               if(*inputBuf != nullPix)
+               {
+                  v = *inputBuf * (*inputBuf);
+                  if(v > maxPix)
+                  {
+                     *outputBuf = maxPix;
+                  }
+                  else if(v < minPix)
+                  {
+                     *outputBuf = minPix;
+                  }
+                  else
+                  {
+                     *outputBuf = static_cast<T>(v);
+                  }
+               }
+               else {
+                  *outputBuf = oNullPix;
+               }
+               ++inputBuf;
+               ++outputBuf;
+            }
+         }
+      }
+   }
+}
+
+
+void ossimSquareFunction::initialize()
+{
+   //---
+   // NOTE:
+   // Since initialize get called often sequentially we will wipe things slick
+   // but not reallocate to avoid multiple delete/allocates.
+   //
+   // On the first getTile call things will be reallocated/computed.
+   //---
+   theTile = NULL;
+   clearNullMinMax();
+}
+
+void ossimSquareFunction::allocate()
+{   
+   if(theInputConnection)
+   {
+      ossimImageDataFactory* idf = ossimImageDataFactory::instance();
+      
+      theTile = idf->create(this,
+                            this);
+      
+      theTile->initialize();
+   }
+}
+
+double ossimSquareFunction::getNullPixelValue(ossim_uint32 band)const
+{
+   if( isSourceEnabled() && (band < theMinPixValue.size()) )
+   {
+      return theNullPixValue[band];
+   }
+   return ossimImageSource::getNullPixelValue(band);
+}
+
+double ossimSquareFunction::getMinPixelValue(ossim_uint32 band)const
+{
+   if( isSourceEnabled() && (band < theMinPixValue.size()) )
+   {
+      return theMinPixValue[band];
+   }   
+   return ossimImageSource::getMinPixelValue(band);
+}
+
+double ossimSquareFunction::getMaxPixelValue(ossim_uint32 band)const
+{
+   if( isSourceEnabled() && (band < theMaxPixValue.size()) )
+   {
+      return theMaxPixValue[band];
+   }
+   return ossimImageSource::getMaxPixelValue(band);
+}
+
+void ossimSquareFunction::clearNullMinMax()
+{
+   theNullPixValue.clear();
+   theMinPixValue.clear();
+   theMaxPixValue.clear();
+}
+
+void ossimSquareFunction::computeNullMinMax()
+{
+   const ossim_uint32 BANDS = getNumberOfOutputBands();
+
+   theNullPixValue.resize(BANDS);
+   theMinPixValue.resize(BANDS);
+   theMaxPixValue.resize(BANDS);
+
+   ossim_float64 defaultNull = ossim::defaultNull(getOutputScalarType());
+   ossim_float64 defaultMin = ossim::defaultMin(getOutputScalarType());
+   ossim_float64 defaultMax = ossim::defaultMax(getOutputScalarType());
+  
+   ossimImageSource* input  = PTR_CAST(ossimImageSource, getInput(0));
+   for (ossim_uint32 band = 0; band < BANDS; ++band)
+   {
+      if(theInputConnection)
+      {
+         double span[2] = { input->getMinPixelValue(band)  , input->getMaxPixelValue(band)  };
+         double v;
+         double minv = defaultMax; //crossed min-max
+         double maxv = defaultMin;
+         for (int l=0;l<2;++l)
+         {
+            for (int r=0;r<2;++r)
+            {
+               v = span[l] * span[r];
+               if (v < minv) minv=v;
+               if (v > maxv) maxv=v;
+            }
+         }         
+         theMinPixValue[band] = (minv>defaultMin) ? minv : defaultMin ;
+         theMaxPixValue[band] = (maxv<defaultMax) ? maxv : defaultMax ;
+      }
+      else // No input connection...
+      {    
+         theMinPixValue[band]  = defaultMin;
+         theMaxPixValue[band]  = defaultMax;
+      }
+      //always default for null
+      theNullPixValue[band] = defaultNull;
+      
+   } // End of band loop.
+}
+
diff --git a/ossim_plugins/registration/ossimSquareFunction.h b/ossim_plugins/registration/ossimSquareFunction.h
new file mode 100644
index 0000000..1114729
--- /dev/null
+++ b/ossim_plugins/registration/ossimSquareFunction.h
@@ -0,0 +1,47 @@
+#ifndef ossimSquareFunction_HEADER
+#define ossimSquareFunction_HEADER
+#include <ossim/imaging/ossimImageSourceFilter.h>
+#include "ossimRegistrationExports.h"
+
+/**
+ * ossimSquareFunction : filter to raise to power of 2
+ */
+class OSSIM_REGISTRATION_DLL ossimSquareFunction : public ossimImageSourceFilter
+{
+public:
+   ossimSquareFunction(ossimObject* owner=NULL);
+   virtual ~ossimSquareFunction();
+
+   virtual ossimString getShortName()const{return ossimString("SquareFunction");}
+   virtual ossimString getLongName()const{return ossimString("raises to power of two");}
+
+   virtual ossimRefPtr<ossimImageData> getTile(const ossimIrect& tileRect,
+                                               ossim_uint32 resLevel=0);
+
+   virtual void initialize();
+
+   virtual double getNullPixelValue(ossim_uint32 band=0) const;
+   virtual double getMinPixelValue(ossim_uint32 band=0)  const;
+   virtual double getMaxPixelValue(ossim_uint32 band=0)  const;
+
+protected:
+
+   template<class T>
+   void applyFunction(T,
+                      ossimRefPtr<ossimImageData> inputData,
+                      ossimRefPtr<ossimImageData> outputData);
+
+   void allocate();
+   void clearNullMinMax();
+   void computeNullMinMax();
+   
+   vector<double> theNullPixValue;
+   vector<double> theMinPixValue;
+   vector<double> theMaxPixValue;   
+   
+   ossimRefPtr<ossimImageData> theTile;                       
+
+TYPE_DATA
+};
+
+#endif /* #ifndef ossimSquareFunction_HEADER */
diff --git a/ossim_plugins/registration/ossimTieGenerator.cpp b/ossim_plugins/registration/ossimTieGenerator.cpp
new file mode 100644
index 0000000..beea02d
--- /dev/null
+++ b/ossim_plugins/registration/ossimTieGenerator.cpp
@@ -0,0 +1,211 @@
+
+#include "ossimTieGenerator.h"
+#include <ossim/imaging/ossimImageGeometry.h>
+#include <ossim/imaging/ossimImageSource.h>
+#include <ossim/imaging/ossimImageHandler.h>
+#include <ossim/base/ossimTrace.h>
+#include <ossim/base/ossimNotifyContext.h>
+#include <fstream>
+#include <iostream> //TBR DEBUG
+using namespace std;
+
+static ossimTrace traceDebug("ossimTieGenerator:debug");
+
+RTTI_DEF2(ossimTieGenerator, "ossimTieGenerator",
+          ossimOutputSource, ossimProcessInterface);
+
+ossimTieGenerator::ossimTieGenerator(ossimImageSource* inputSource)
+      :
+      ossimOutputSource(NULL, // owner
+                        1,
+                        0,
+                        true,
+                        true),
+      ossimProcessInterface(),
+      theAreaOfInterest(),
+      theFilename(ossimFilename::NIL),
+      theFileStream(),
+      theStoreFlag(false)
+{
+   connectMyInputTo(0, inputSource);
+   theAreaOfInterest.makeNan();
+}
+
+ossimTieGenerator::~ossimTieGenerator()
+{
+}
+
+bool ossimTieGenerator::execute()
+{
+   bool status = true;
+   static const char MODULE[] = "ossimTieGenerator::execute";
+
+   if (traceDebug()) CLOG << " Entered..." << endl;
+   
+   ossimImageSource* src = reinterpret_cast<ossimImageSource*>(getInput(0));
+   if (theAreaOfInterest.isNan())
+   {
+      // ChipMatch will provide correct ROI
+      theAreaOfInterest = src->getBoundingRect(0);
+   }
+
+   //open stream
+   open();
+
+   setProcessStatus(ossimProcessInterface::PROCESS_STATUS_EXECUTING);
+   
+   //write out projection info
+   if (theFilename != ossimFilename::NIL)
+   {
+      ossimRefPtr<ossimImageGeometry> geom = src->getImageGeometry();
+      ossimKeywordlist mpk;
+      if(geom.valid())
+      {
+         geom->saveState(mpk);
+      }
+      theFileStream<<mpk.toString(); //writeToStream(theFileStream);
+   }
+
+   //do the actual work there
+   if (status) status = getAllFeatures();  
+   
+   setProcessStatus(ossimProcessInterface::PROCESS_STATUS_NOT_EXECUTING);
+
+   if (traceDebug()) CLOG << " Exited..." << endl;
+
+   //close stream
+   close();
+
+   return status;
+}
+
+bool ossimTieGenerator::getAllFeatures()
+{
+   static const char MODULE[] = "ossimTieGenerator::getAllFeatures";
+
+   if (traceDebug()) CLOG << " Entered..." << endl;
+
+   ossimChipMatch* src = reinterpret_cast<ossimChipMatch*>(getInput(0));
+   if (!src)
+   {
+      ossimNotify(ossimNotifyLevel_WARN)
+         << "WARN ossimTieGenerator::scanForEdges():"
+         << "\nInput source is not a ossimImageChip.  Returning..." << std::endl;
+      return false;
+   }
+
+   // Some constants needed throughout...
+   const ossim_int32 TILE_HEIGHT    = src->getTileHeight();
+   const ossim_int32 TILE_WIDTH     = src->getTileWidth();
+   const ossim_int32 START_LINE = theAreaOfInterest.ul().y;
+   const ossim_int32 STOP_LINE  = theAreaOfInterest.lr().y;
+   const ossim_int32 START_SAMP = theAreaOfInterest.ul().x;
+   const ossim_int32 STOP_SAMP  = theAreaOfInterest.lr().x;
+
+   // For percent complete status.
+   ossim_int32 tilerows=(STOP_LINE-START_LINE+TILE_HEIGHT) / TILE_HEIGHT; //ceil : (stop-start+1+size-1)/size
+   ossim_int32 tilecols=(STOP_SAMP-START_SAMP+TILE_WIDTH) / TILE_WIDTH;
+   double total_tiles = ((double)tilerows)*tilecols;
+   double tiles_processed = 0.0;
+
+   // Set the status message to be "scanning source for edges..."
+   ossimNotify(ossimNotifyLevel_INFO) << "Getting tie points..." << std::endl;
+   
+   // Start off with a percent complete at 0...
+   setPercentComplete(0.0);
+
+   // loop through all tiles
+   // need to use a sequencer for parallelism in the future TBD
+   theTiePoints.clear();
+   ossim_int32 line=START_LINE;
+   ossim_int32 i,j;
+   for (i=0;(i<tilerows)&&!needsAborting();++i)
+   {
+      ossim_int32 samp=START_SAMP;
+      for (j=0;(j<tilecols)&&!needsAborting();++j )
+      {
+         // Get the tie points
+         //TBC : can we go further than source edges with edge tiles?? TBD
+         const vector<ossimTDpt>& tp = src->getFeatures(ossimIrect(ossimIpt(samp, line),ossimIpt(samp+TILE_WIDTH-1,line+TILE_HEIGHT-1)));
+
+         if (theFilename != ossimFilename::NIL)
+         {
+            //write on stream
+            writeTiePoints(tp);
+         }
+         
+         if (getStoreFlag())
+         {
+            //store them : insert at the end (constant time) //TBD : conditional store
+            theTiePoints.insert(theTiePoints.end(),tp.begin(),tp.end());
+         }
+
+         samp+=TILE_WIDTH;
+         // Set the percent complete.
+         tiles_processed += 1.0;
+         setPercentComplete(tiles_processed/total_tiles*100.0);
+
+//DEBUG TBR TBC
+// std::cout<<"p="<<tiles_processed/total_tiles*100.0<<std::endl;
+
+      }
+      line+=TILE_HEIGHT;
+   }
+
+   setPercentComplete(100.0);
+   if (traceDebug()) CLOG << " Exited." << endl;
+   return true;
+}
+
+void ossimTieGenerator::writeTiePoints(const vector<ossimTDpt>& tp)
+{
+   for (vector<ossimTDpt>::const_iterator it=tp.begin();it!=tp.end();++it)
+   {
+      it->printTab(theFileStream);
+      theFileStream<<endl;
+   }
+}
+
+void ossimTieGenerator::setOutputName(const ossimString& filename)
+{
+   ossimOutputSource::setOutputName(filename);
+
+   if (isOpen()) close();
+   
+   if (filename != "")
+   {
+      theFilename = filename;
+   }
+}
+
+void ossimTieGenerator::setAreaOfInterest(const ossimIrect& rect)
+{
+   theAreaOfInterest = rect;
+}
+
+bool ossimTieGenerator::isOpen()const
+{
+   return const_cast<ofstream*>(&theFileStream)->is_open();
+}
+
+bool ossimTieGenerator::open()
+{
+   if(isOpen())
+   {
+      close();
+   }
+
+   if (theFilename == ossimFilename::NIL)
+   {
+      return false;
+   }
+   
+   theFileStream.open(theFilename.c_str());
+
+   return theFileStream.good();
+}
+
+void ossimTieGenerator::close()
+{
+   if (isOpen()) theFileStream.close();
+}
diff --git a/ossim_plugins/registration/ossimTieGenerator.h b/ossim_plugins/registration/ossimTieGenerator.h
new file mode 100644
index 0000000..b7d6c77
--- /dev/null
+++ b/ossim_plugins/registration/ossimTieGenerator.h
@@ -0,0 +1,98 @@
+// class TieGenerator
+//
+// features:
+// execution gets all tie points using a ossimChipMatch object, given
+// -a specific resoultionLevel
+// -a specific rectangular ROI (default : everything in bounds)
+// => it is a global operator
+//
+// can export tie points to a file (optional)
+// tie points are provided by a ossimChipMatch object, using tiled method getFeatures()
+//
+// created by Frederic Claudel, CSIR - Aug 2005 - using ossimVertexExtractor as a model
+//
+// TBD: parallelize : use a sequencer (for vector data as well)
+//
+
+#ifndef ossimTieGenerator_HEADER
+#define ossimTieGenerator_HEADER
+
+#include <fstream>
+
+#include <ossim/base/ossimOutputSource.h>
+#include <ossim/base/ossimProcessInterface.h>
+#include <ossim/base/ossimProcessProgressEvent.h>
+#include <ossim/base/ossimIrect.h>
+#include <ossim/base/ossimTDpt.h>
+#include <ossim/base/ossimFilename.h>
+#include <ossim/imaging/ossimImageSource.h>
+#include "ossimChipMatch.h"
+#include "ossimRegistrationExports.h"
+class ossimImageSource;
+
+//! Class ossimTieGenerator
+
+/*!
+ *  get all tie points from ossimChipMatch using a tiled vector method : getFeatures()
+ */
+class OSSIM_REGISTRATION_DLL ossimTieGenerator : 
+    public ossimOutputSource,
+    public ossimProcessInterface
+{
+public:
+   ossimTieGenerator(ossimImageSource* inputSource=NULL);
+   virtual ~ossimTieGenerator();
+
+   inline bool getStoreFlag()const   { return theStoreFlag; }
+   inline void setStoreFlag(bool sf) { theStoreFlag = sf; }
+
+   virtual       ossimObject* getObject()      { return this; }
+   virtual const ossimObject* getObject()const { return this; }
+   virtual       ossimObject* getObjectInterface() { return this; }
+
+   void setAreaOfInterest(const ossimIrect& rect);
+   virtual void setOutputName(const ossimString& filename);
+   virtual bool isOpen() const;
+   virtual bool open();
+   virtual void close();
+
+   virtual bool execute();
+
+   virtual ossimListenerManager* getListenerManagerInterface() { return this; }   
+   
+/*   virtual void setPercentComplete(double percentComplete)
+      {
+         ossimProcessInterface::setPercentComplete(percentComplete);
+         ossimProcessProgressEvent event(this,
+                                         percentComplete);
+         fireEvent(event);      
+      }
+*/
+   bool canConnectMyInputTo(ossim_int32 inputIndex,
+                            const ossimConnectableObject* object)const
+      {         
+         return (object&& PTR_CAST(ossimChipMatch, object));
+      }
+
+   const vector<ossimTDpt>& getTiePoints() { return theTiePoints; }
+
+protected:
+   bool getAllFeatures();
+   void writeTiePoints(const vector<ossimTDpt>& tp);
+
+private:
+   ossimIrect        theAreaOfInterest;
+   ossimFilename     theFilename;
+   std::ofstream     theFileStream;
+   vector<ossimTDpt> theTiePoints;
+   bool              theStoreFlag;
+
+   //! Disallow copy constructor and operator=
+   ossimTieGenerator(const ossimTieGenerator&) {}
+   const ossimTieGenerator& operator=(const ossimTieGenerator& rhs)
+      {return rhs;}
+
+TYPE_DATA
+};
+
+#endif
diff --git a/ossim_plugins/registration/ossimreg_plugin.vcproj b/ossim_plugins/registration/ossimreg_plugin.vcproj
new file mode 100644
index 0000000..6763524
--- /dev/null
+++ b/ossim_plugins/registration/ossimreg_plugin.vcproj
@@ -0,0 +1,323 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="9.00"
+	Name="ossimreg_plugin"
+	ProjectGUID="{9B718B8B-897E-4DB5-B2E7-A2EEC6B4F8D0}"
+	RootNamespace="ossimreg_plugin"
+	Keyword="Win32Proj"
+	TargetFrameworkVersion="131072"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="Debug|Win32"
+			OutputDirectory="Debug"
+			IntermediateDirectory="Debug"
+			ConfigurationType="2"
+			InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="..\;..\..\ossim\include;..\..\3rdParty\include\;..\..\OpenThreads\include"
+				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;OSSIMREG_PLUGIN_EXPORTS"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				OutputFile="$(SolutionDir)bin\ossimreg_plugin.dll"
+				LinkIncremental="2"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/ossimreg_plugin.pdb"
+				SubSystem="2"
+				RandomizedBaseAddress="1"
+				DataExecutionPrevention="0"
+				ImportLibrary="$(OutDir)/ossimreg_plugin.lib"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|Win32"
+			OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+			IntermediateDirectory="$(ConfigurationName)"
+			ConfigurationType="2"
+			InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				AdditionalIncludeDirectories=""$(InputDir)..\..\ossim\include\";"$(InputDir)..";"$(InputDir)..\..\libwms\include";"$(InputDir)..\..\ossim_dependencies\src\jpeg-6b";"$(InputDir)..\..\ossim_dependencies\include";"$(InputDir)..\..\ossim_dependencies\src\OpenSceneGraph-2.8.1\include""
+				PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;OSSIMUSINGDLL;HAVE_CONFIG_H"
+				RuntimeLibrary="2"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="0"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="fftw3.lib"
+				OutputFile="$(OutDir)\bin\$(ProjectName).dll"
+				LinkIncremental="1"
+				AdditionalLibraryDirectories=""$(InputDir)..\..\ossim_dependencies\src\jpeg-6b";"$(InputDir)..\..\ossim_dependencies\lib";"$(InputDir)..\..\ossim_dependencies\src\OpenSceneGraph-2.8.1\build\lib""
+				GenerateDebugInformation="false"
+				SubSystem="2"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				RandomizedBaseAddress="1"
+				DataExecutionPrevention="0"
+				ImportLibrary="$(OutDir)/ossimreg_plugin.lib"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+				CommandLine=""
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="Source Files"
+			Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
+			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+			>
+			<File
+				RelativePath=".\ossimChipMatch.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\ossimDensityReducer.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\ossimExtremaFilter.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\ossimHarrisCorners.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\ossimImageCorrelator.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\ossimModelOptimizer.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\ossimMultiplier.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\ossimNCC_FFTW.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\ossimOutlierRejection.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\ossimRegistrationImageSourceFactory.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\ossimRegistrationMiscFactory.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\ossimRegistrationPluginInit.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\ossimRunningSum.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\ossimSquareFunction.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\ossimTieGenerator.cpp"
+				>
+			</File>
+		</Filter>
+		<Filter
+			Name="Header Files"
+			Filter="h;hpp;hxx;hm;inl;inc;xsd"
+			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+			>
+			<File
+				RelativePath=".\ossimChipMatch.h"
+				>
+			</File>
+			<File
+				RelativePath=".\ossimDensityReducer.h"
+				>
+			</File>
+			<File
+				RelativePath=".\ossimExtremaFilter.h"
+				>
+			</File>
+			<File
+				RelativePath=".\ossimHarrisCorners.h"
+				>
+			</File>
+			<File
+				RelativePath=".\ossimImageCorrelator.h"
+				>
+			</File>
+			<File
+				RelativePath=".\ossimModelOptimizer.h"
+				>
+			</File>
+			<File
+				RelativePath=".\ossimMultiplier.h"
+				>
+			</File>
+			<File
+				RelativePath=".\ossimNCC_FFTW.h"
+				>
+			</File>
+			<File
+				RelativePath=".\ossimOutlierRejection.h"
+				>
+			</File>
+			<File
+				RelativePath=".\ossimRegistrationExports.h"
+				>
+			</File>
+			<File
+				RelativePath=".\ossimRegistrationImageSourceFactory.h"
+				>
+			</File>
+			<File
+				RelativePath=".\ossimRegistrationMiscFactory.h"
+				>
+			</File>
+			<File
+				RelativePath=".\ossimRunningSum.h"
+				>
+			</File>
+			<File
+				RelativePath=".\ossimSquareFunction.h"
+				>
+			</File>
+			<File
+				RelativePath=".\ossimTieGenerator.h"
+				>
+			</File>
+		</Filter>
+		<Filter
+			Name="Resource Files"
+			Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
+			UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+			>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
diff --git a/ossim_plugins/sqlite/CMakeLists.txt b/ossim_plugins/sqlite/CMakeLists.txt
new file mode 100644
index 0000000..b694a2b
--- /dev/null
+++ b/ossim_plugins/sqlite/CMakeLists.txt
@@ -0,0 +1,72 @@
+set(LIB_NAME ossimsqlite_plugin)
+MESSAGE( "************** LIBRARY SETUP FOR ossimsqlite_plugin******************")
+
+# Include ossim cmake stuff:
+include(OssimVersion)
+include(OssimCommonVariables)
+include(OssimUtilities)
+
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
+
+set(requiredLibs)
+
+# SQLite - Required:
+find_package(SQLITE)
+if(SQLITE_FOUND)
+   include_directories( ${SQLITE_INCLUDE_DIR} )
+   SET(requiredLibs ${requiredLibs} ${SQLITE_LIBRARY})
+else(SQLITE_FOUND)
+   message(FATAL_ERROR "Could not find sqlite")
+endif(SQLITE_FOUND)
+
+# PNG - Required:
+find_package(PNG)
+IF(PNG_FOUND)
+   include_directories( ${PNG_INCLUDE_DIR} )
+   SET(requiredLibs ${requiredLibs} ${PNG_LIBRARIES} )
+ELSE(PNG_FOUND)
+   MESSAGE(FATAL_ERROR "Could not find png")
+ENDIF(PNG_FOUND)
+
+# JPEG - Required:
+find_package( JPEG )
+if( JPEG_FOUND )
+   include_directories( ${JPEG_INCLUDE_DIR} )
+   set( requiredLibs ${requiredLibs} ${JPEG_LIBRARY} )
+else( JPEG_FOUND )
+   message( FATAL_ERROR "Could not find jpeg" )
+endif( JPEG_FOUND )
+
+# OSSIM - Required: 
+find_package(ossim)
+if(OSSIM_FOUND)
+   include_directories( ${OSSIM_INCLUDE_DIR} )
+   set( requiredLibs ${requiredLibs} ${OSSIM_LIBRARIES} )
+else(OSSIM_FOUND)
+   message(FATAL_ERROR "Could not find ossim")
+endif(OSSIM_FOUND)
+
+message("requiredLibs: ${requiredLibs}")
+
+file(GLOB OSSIMPLUGIN_SRCS *.cpp)
+file(GLOB OSSIMPLUGIN_HEADERS *.h)
+
+#---
+# OSSIMPLUGINSMAKINGDLL controls dll linkage on windows.  
+# Adding this sets OSSIM_PLUGINS_DLL #define TO "__declspec(dllexport)".
+#---
+add_definitions("-DOSSIMPLUGINSMAKINGDLL")
+
+# Adjust the install library path:
+if(OSSIM_INSTALL_PLUGINS_WITH_VERSION)
+   set(INSTALL_LIBRARY_DIR   "${INSTALL_LIBRARY_DIR}/ossim-${OSSIM_VERSION}/plugins")
+else(OSSIM_INSTALL_PLUGINS_WITH_VERSION)
+   set(INSTALL_LIBRARY_DIR   "${INSTALL_LIBRARY_DIR}/ossim/plugins")
+endif(OSSIM_INSTALL_PLUGINS_WITH_VERSION)
+
+OSSIM_LINK_LIBRARY(${LIB_NAME}
+                   COMPONENT_NAME ossim TYPE "${OSSIM_PLUGIN_LINK_TYPE}"
+		   LIBRARIES ${OSSIM_LIBRARY} ${requiredLibs}
+                   HEADERS "${OSSIMPLUGIN_HEADERS}"
+		   SOURCE_FILES "${OSSIMPLUGIN_SRCS}"
+                   INSTALL_LIB)
diff --git a/ossim_plugins/sqlite/ossimGpkgContentsRecord.cpp b/ossim_plugins/sqlite/ossimGpkgContentsRecord.cpp
new file mode 100644
index 0000000..b6b2888
--- /dev/null
+++ b/ossim_plugins/sqlite/ossimGpkgContentsRecord.cpp
@@ -0,0 +1,328 @@
+//----------------------------------------------------------------------------
+//
+// File: ossimGpkgContentsRecord.cpp
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Description: Container class for gpkg_contents table.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include "ossimGpkgContentsRecord.h"
+#include "ossimSqliteUtil.h"
+#include <ossim/base/ossimCommon.h>
+#include <ossim/base/ossimDpt.h>
+#include <ossim/base/ossimKeywordlist.h>
+#include <ossim/base/ossimNotify.h>
+#include <sqlite3.h>
+#include <iomanip>
+
+static const std::string TABLE_NAME = "gpkg_contents";
+
+ossimGpkgContentsRecord::ossimGpkgContentsRecord()
+   :
+   ossimGpkgDatabaseRecordBase(),
+   m_table_name(),
+   m_data_type(),
+   m_identifier(),
+   m_description(),
+   m_last_change(),
+   m_min_x(ossim::nan()),
+   m_min_y(ossim::nan()),
+   m_max_x(ossim::nan()),
+   m_max_y(ossim::nan()),
+   m_srs_id(0)
+{
+}
+
+ossimGpkgContentsRecord::ossimGpkgContentsRecord(const ossimGpkgContentsRecord& obj)
+   :
+   ossimGpkgDatabaseRecordBase(),
+   m_table_name(obj.m_table_name),
+   m_data_type(obj.m_data_type),
+   m_identifier(obj.m_identifier),
+   m_description(obj.m_description),
+   m_last_change(obj.m_last_change),
+   m_min_x(obj.m_min_x),
+   m_min_y(obj.m_min_y),
+   m_max_x(obj.m_max_x),
+   m_max_y(obj.m_max_y),
+   m_srs_id(obj.m_srs_id)
+{
+}
+
+const ossimGpkgContentsRecord& ossimGpkgContentsRecord::operator=(
+   const ossimGpkgContentsRecord& copy_this)
+{
+   if ( this != &copy_this )
+   {
+      m_table_name = copy_this.m_table_name;
+      m_data_type = copy_this.m_data_type;
+      m_identifier = copy_this.m_identifier;
+      m_description = copy_this.m_description;
+      m_last_change = copy_this.m_last_change;
+      m_min_x = copy_this.m_min_x;
+      m_min_y = copy_this.m_min_y;
+      m_max_x = copy_this.m_max_x;
+      m_max_y = copy_this.m_max_y;
+      m_srs_id = copy_this.m_srs_id;
+   }
+   return *this;
+}
+
+ossimGpkgContentsRecord::~ossimGpkgContentsRecord()
+{
+}
+
+const std::string& ossimGpkgContentsRecord::getTableName()
+{
+   return TABLE_NAME;
+}
+
+bool ossimGpkgContentsRecord::init( sqlite3_stmt* pStmt )
+{
+   static const char M[] = "ossimGpkgContentsRecord::init";
+   
+   bool status = false;
+
+   if ( pStmt )
+   {
+      const ossim_int32 EXPECTED_COLUMNS = 10;
+      ossim_int32 nCol = sqlite3_column_count( pStmt );
+
+      if ( nCol != EXPECTED_COLUMNS )
+      {
+         ossimNotify(ossimNotifyLevel_WARN)
+            << M << " WARNING:\nUnexpected number of columns: " << nCol
+            << "Expected column count: " << EXPECTED_COLUMNS
+            << std::endl;
+      }
+      
+      if ( nCol >= EXPECTED_COLUMNS )
+      {
+         ossim_int32 columnsFound = 0;
+         std::string colName;
+         const char* c = 0; // To catch null so not to pass to string.
+         
+         for ( ossim_int32 i = 0; i < nCol; ++i )
+         {
+            colName = sqlite3_column_name(pStmt, i);
+            if ( colName.size() )
+            {
+               if ( colName == "table_name" )
+               {
+                  c = (const char*)sqlite3_column_text(pStmt, i);
+                  m_table_name = (c ? c : "");
+                  ++columnsFound;
+               }
+               else if ( colName == "data_type" )
+               {
+                  c = (const char*)sqlite3_column_text(pStmt, i);
+                  m_data_type = (c ? c : "");
+                  ++columnsFound;
+               }
+               else if ( colName == "identifier" )
+               {
+                  c = (const char*)sqlite3_column_text(pStmt, i);
+                  m_identifier = (c ? c : "");
+                  ++columnsFound;
+               }
+               else if ( colName == "description" )
+               {
+                  c = (const char*)sqlite3_column_text(pStmt, i);
+                  m_description = (c ? c : "");
+                  ++columnsFound;
+               }
+               else if ( colName == "last_change" )
+               {
+                  c = (const char*)sqlite3_column_text(pStmt, i);
+                  m_last_change = (c ? c : "");
+                  ++columnsFound;
+               }
+               else if ( colName == "min_x" )
+               {
+                  m_min_x = sqlite3_column_double(pStmt, i);
+                  ++columnsFound;
+               }
+               else if ( colName == "min_y" )
+               {
+                  m_min_y = sqlite3_column_double(pStmt, i);
+                  ++columnsFound;
+               }
+               else if ( colName == "max_x" )
+               {
+                  m_max_x = sqlite3_column_double(pStmt, i);
+                  ++columnsFound;
+               }
+               else if ( colName == "max_y" )
+               {
+                  m_max_y = sqlite3_column_double(pStmt, i);
+                  ++columnsFound;
+               }
+               else if ( colName == "srs_id" )
+               {
+                  m_srs_id = sqlite3_column_int(pStmt, i);
+                  ++columnsFound;
+               }
+               else
+               {
+                  ossimNotify(ossimNotifyLevel_WARN)
+                     << M << " Unhandled column name["
+                     << i << "]: " << colName << std::endl;
+               }
+               
+            } // Matches: if ( colName.size() )
+
+            if ( columnsFound == EXPECTED_COLUMNS )
+            {
+               status = true;
+               break;
+            }
+            
+         } // Matches: for ( ossim_int32 i = 0; i < nCol; ++i )  
+      }
+      
+   } // Matches: if ( pStmt )
+   
+   return status;
+   
+} // End: ossimGpkgContentsRecord::init( sqlite3_stmt* pStmt )
+
+bool ossimGpkgContentsRecord::init(
+   const std::string& tableName, ossim_int32 srs_id,
+   const ossimDpt& minPt, const ossimDpt& maxPt )
+{
+   bool status = false;
+   if ( (minPt.hasNans() == false) && (maxPt.hasNans() == false) )
+   {
+      m_table_name  = tableName;
+      m_data_type   = "tiles";
+      m_identifier  = "Raster Tiles for ";
+      m_identifier  += tableName;
+      m_description = "Create by ossim gpkg writer.";
+      
+      ossim_sqlite::getTime( m_last_change );
+
+      m_min_x  = minPt.x;
+      m_min_y  = minPt.y;
+      m_max_x  = maxPt.x;
+      m_max_y  = maxPt.y;
+      m_srs_id = srs_id;
+      status   = true;
+   }
+   return status;
+}
+
+bool ossimGpkgContentsRecord::createTable( sqlite3* db )
+{
+   bool status = false;
+   if ( db )
+   {
+      status = ossim_sqlite::tableExists( db, TABLE_NAME );
+
+      if ( !status )
+      {
+         std::ostringstream sql;
+         sql << "CREATE TABLE " << TABLE_NAME << " ( "
+             << "table_name TEXT NOT NULL PRIMARY KEY, "
+             << "data_type TEXT NOT NULL, "
+             << "identifier TEXT UNIQUE, "
+             << "description TEXT DEFAULT \"\", "
+
+            //---
+            // Requirement 13:
+            // Note: Spec changed to %fZ.  No %f on linux but sqlite library handles.
+            // << "last_change DATETIME NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%SZ','now')), "
+            //---
+             << "last_change DATETIME NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ','now')), "
+             << "min_x DOUBLE, "
+             << "min_y DOUBLE, "
+             << "max_x DOUBLE, "
+             << "max_y DOUBLE, "
+             << "srs_id INTEGER, "
+             << "CONSTRAINT fk_gc_r_srs_id FOREIGN KEY (srs_id) "
+             << "REFERENCES gpkg_spatial_ref_sys(srs_id)"
+             << ")";
+         
+         if ( ossim_sqlite::exec( db, sql.str() ) == SQLITE_DONE )
+         {
+            status = true;
+         }
+      }
+   }
+   return status;
+}
+
+bool ossimGpkgContentsRecord::insert( sqlite3* db )
+{
+   bool status = false;
+   if ( db )
+   {
+      std::ostringstream sql;
+      sql << "INSERT INTO gpkg_contents VALUES ( "
+          <<  "'" << m_table_name << "', "
+          <<  "'" << m_data_type << "', "
+          <<  "'" << m_identifier << "', "
+          <<  "'" << m_description << "', "
+          <<  "'" << m_last_change << "', "
+          << std::setprecision(16)
+          << m_min_x << ", "
+          << m_min_y << ", "
+          << m_max_x << ", "
+          << m_max_y << ", "
+          << m_srs_id
+          << " )";
+
+      if ( ossim_sqlite::exec( db, sql.str() ) == SQLITE_DONE )
+      {
+         status = true;
+      }    
+   }
+   return status;
+}
+
+void ossimGpkgContentsRecord::saveState( ossimKeywordlist& kwl,
+                                         const std::string& prefix ) const
+{
+   std::string myPref = prefix.size() ? prefix : std::string("gpkg_contents.");
+   std::string value;
+   
+   std::string key = "table_name";
+   kwl.addPair(myPref, key, m_table_name, true);
+
+   key = "data_type";
+   kwl.addPair(myPref, key, m_data_type, true);
+   
+   key = "identifier";
+   kwl.addPair(myPref, key, m_identifier, true);
+   
+   key = "description";
+   kwl.addPair(myPref, key, m_description, true);
+
+   key = "last_change";
+   kwl.addPair(myPref, key, m_last_change, true);
+
+   key = "min_x";
+   value = ossimString::toString(m_min_x, 15).string();
+   kwl.addPair(myPref, key, value, true);
+
+   key = "min_y";
+   value = ossimString::toString(m_min_y, 15).string();
+   kwl.addPair(myPref, key, value, true);
+
+   key = "max_x";
+   value = ossimString::toString(m_max_x, 15).string();
+   kwl.addPair(myPref, key, value, true);
+
+   key = "max_y";
+   value = ossimString::toString(m_max_y, 15).string();
+   kwl.addPair(myPref, key, value, true);
+
+   key = "srs_id";
+   value = ossimString::toString(m_srs_id).string();
+   kwl.addPair(myPref, key, value, true);
+}
+
diff --git a/ossim_plugins/sqlite/ossimGpkgContentsRecord.h b/ossim_plugins/sqlite/ossimGpkgContentsRecord.h
new file mode 100644
index 0000000..0df73f3
--- /dev/null
+++ b/ossim_plugins/sqlite/ossimGpkgContentsRecord.h
@@ -0,0 +1,101 @@
+//----------------------------------------------------------------------------
+//
+// File: ossimGpkgContentsRecord.h
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Description: Container class for gpkg_contents table.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef ossimGpkgContentsRecord_HEADER
+#define ossimonGpkgContentsRecord_HEADER 1
+
+#include "ossimGpkgDatabaseRecordBase.h"
+#include <ossim/base/ossimConstants.h>
+
+class ossimDpt;
+class ossimMapProjection;
+struct sqlite3;
+
+class ossimGpkgContentsRecord : public ossimGpkgDatabaseRecordBase
+{
+public:
+
+   /** @brief default constructor */
+   ossimGpkgContentsRecord();
+
+   /* @brief copy constructor */
+   ossimGpkgContentsRecord(const ossimGpkgContentsRecord& obj);
+
+   /* @brief assignment operator= */
+   const ossimGpkgContentsRecord& operator=(const ossimGpkgContentsRecord& copy_this);
+
+   /** @brief destructor */
+   virtual ~ossimGpkgContentsRecord();
+
+   /**
+    * @brief Get the table name "gpkg_contents".
+    * @return table name
+    */
+   static const std::string& getTableName();
+   
+   /**
+    * @brief Initialize from database.
+    * @param pStmt SQL statement, i.e. result of sqlite3_prepare_v2(...) call.
+    * @return true on success, false on error.
+    */
+   virtual bool init( sqlite3_stmt* pStmt );
+
+   /**
+    * @brief Initialize from projection.
+    * @param tableName e.g. "tiles"
+    * @param srs_id ID of gpkg_spatial_ref_sys record our projection is
+    * relative to.
+    * @param minPt Minimum bounds in either Easting Northin or lat lon.
+    * @param maxPt Maximum bounds in either Easting Northin or lat lon.    * 
+    * @return true on success, false on error.
+    */
+   bool init( const std::string& tableName,
+              ossim_int32 srs_id,
+              const ossimDpt& minPt,
+              const ossimDpt& maxPt );
+   
+   /**
+    * @brief Creates  table in database.
+    * @param db
+    * @return true on success, false on error.
+    */   
+   static bool createTable( sqlite3* db );
+
+   /**
+    * @brief Inserst this record into gpkg_spatial_ref_sys table.
+    * @param db
+    * @return true on success, false on error.
+    */   
+   bool insert( sqlite3* db );
+   
+   /**
+    * @brief Saves the state of object to keyword list.
+    * @param kwl Initialized by this.
+    * @param prefix e.g. "image0.". Can be empty.
+    */
+   virtual void saveState( ossimKeywordlist& kwl, const std::string& prefix ) const;
+
+   std::string   m_table_name;
+   std::string   m_data_type;
+   std::string   m_identifier;
+   std::string   m_description;
+   std::string   m_last_change;
+   ossim_float64 m_min_x;
+   ossim_float64 m_min_y;
+   ossim_float64 m_max_x;
+   ossim_float64 m_max_y;
+   ossim_int32   m_srs_id;
+};
+
+#endif /* #ifndef ossimGpkgContentsRecord_HEADER */
+
diff --git a/ossim_plugins/sqlite/ossimGpkgDatabaseRecordBase.cpp b/ossim_plugins/sqlite/ossimGpkgDatabaseRecordBase.cpp
new file mode 100644
index 0000000..b5aad8f
--- /dev/null
+++ b/ossim_plugins/sqlite/ossimGpkgDatabaseRecordBase.cpp
@@ -0,0 +1,41 @@
+//----------------------------------------------------------------------------
+// File: ossimGpkgDatabaseRecordInferface.h
+// 
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Description: Base class definition for GeoPackage database record.
+// 
+//----------------------------------------------------------------------------
+// $Id$
+
+#include "ossimGpkgDatabaseRecordBase.h"
+#include <ossim/base/ossimKeywordlist.h>
+#include <ostream>
+
+ossimGpkgDatabaseRecordBase::ossimGpkgDatabaseRecordBase()
+   : ossimReferenced()
+{
+}
+
+ossimGpkgDatabaseRecordBase::~ossimGpkgDatabaseRecordBase()
+{
+}
+
+std::ostream& ossimGpkgDatabaseRecordBase::print(std::ostream& out) const
+{
+   ossimKeywordlist kwl;
+   saveState(kwl, std::string(""));
+   out << kwl;
+   return out;
+}
+   
+std::ostream& operator<<(std::ostream& out,
+                         const ossimGpkgDatabaseRecordBase& obj)
+{
+   return obj.print( out );
+}
+
+   
+
diff --git a/ossim_plugins/sqlite/ossimGpkgDatabaseRecordBase.h b/ossim_plugins/sqlite/ossimGpkgDatabaseRecordBase.h
new file mode 100644
index 0000000..c4d7d8f
--- /dev/null
+++ b/ossim_plugins/sqlite/ossimGpkgDatabaseRecordBase.h
@@ -0,0 +1,67 @@
+//----------------------------------------------------------------------------
+// File: ossimGpkgDatabaseRecordInferface.h
+// 
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Description: Base class declaration for GeoPackage database record.
+// 
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef ossimGpkgDatabaseRecordBase_HEADER
+#define ossimGpkgDatabaseRecordBase_HEADER 1
+
+#include <ossim/base/ossimReferenced.h>
+#include <iosfwd>
+#include <string>
+
+class ossimKeywordlist;
+struct sqlite3_stmt;
+
+/** @class ossimGpkgDatabaseRecordBase */
+class ossimGpkgDatabaseRecordBase : public ossimReferenced
+{
+public:
+   
+   /** @brief default constructor */
+   ossimGpkgDatabaseRecordBase();
+
+   /** @brief virtual destructor. */
+   virtual ~ossimGpkgDatabaseRecordBase();
+
+   /**
+    * @brief Initialize from database.
+    * Pure virtual, derived classes must implement.
+    * @param pStmt SQL statement, i.e. result of sqlite3_prepare_v2(...) call.
+    */
+   virtual bool init( sqlite3_stmt* pStmt ) = 0;
+
+   /**
+    * @brief Saves the state of object to keyword list.
+    * Pure virtual, derived classes must implement. 
+    * @param kwl Initialized by this.
+    * @param prefix e.g. "image0.". Can be empty.
+    */
+   virtual void saveState( ossimKeywordlist& kwl,
+                           const std::string& prefix ) const = 0;
+
+   /**
+    * @brief Print method.
+    * @param out Stream to print to.
+    * @return Stream reference.
+    */
+   virtual std::ostream& print(std::ostream& out) const;
+   
+   /**
+    * @brief Convenience operator << function.
+    * @param out Stream to print to.
+    * @param obj Object to print.
+    */
+   friend std::ostream& operator<<(std::ostream& out,
+                                   const ossimGpkgDatabaseRecordBase& obj);
+};
+
+#endif /* #ifndef ossimGpkgDatabaseRecordBase_HEADER */
+
diff --git a/ossim_plugins/sqlite/ossimGpkgInfo.cpp b/ossim_plugins/sqlite/ossimGpkgInfo.cpp
new file mode 100644
index 0000000..f25929f
--- /dev/null
+++ b/ossim_plugins/sqlite/ossimGpkgInfo.cpp
@@ -0,0 +1,209 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author: David Burken
+//
+// Description: GeoPackage Info class.
+// 
+//----------------------------------------------------------------------------
+// $Id$
+
+
+#include "ossimGpkgInfo.h"
+#include "ossimGpkgDatabaseRecordBase.h"
+#include "ossimGpkgUtil.h"
+
+#include <ossim/base/ossimCommon.h>
+#include <ossim/base/ossimException.h>
+#include <ossim/base/ossimKeywordlist.h>
+#include <ossim/base/ossimNotify.h>
+#include <ossim/base/ossimString.h>
+#include <ossim/base/ossimTrace.h>
+
+#include <sqlite3.h>
+
+static ossimTrace traceDebug("ossimGpkgInfo:debug");
+static ossimTrace traceTiles("ossimGpkgInfo:tiles");
+
+ossimGpkgInfo::ossimGpkgInfo()
+   : ossimInfoBase(),
+     m_file()
+{
+}
+
+ossimGpkgInfo::~ossimGpkgInfo()
+{
+}
+
+bool ossimGpkgInfo::open(const ossimFilename& file)
+{
+   bool result = false;
+   
+   if ( file.size() ) // Check for empty filename.
+   {
+      std::ifstream str;
+      str.open( file.c_str(), std::ios_base::in | std::ios_base::binary);
+
+      if ( str.good() ) // Open good...
+      {
+         if ( ossim_gpkg::checkSignature( str ) ) // Has "SQLite format 3" signature.
+         {
+            m_file = file;
+            result = true;
+         }
+      }
+   }
+
+   return result;
+}
+
+std::ostream& ossimGpkgInfo::print(std::ostream& out) const
+{
+   static const char MODULE[] = "ossimGpkgInfo::open";
+   
+   if ( traceDebug() )
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " entered..."
+         << "File:  " << m_file.c_str()
+         << std::endl;
+   }
+
+   // Check for empty filename.
+   if (m_file.size())
+   {
+      sqlite3* db;
+      
+      int rc = sqlite3_open_v2( m_file.c_str(), &db, SQLITE_OPEN_READONLY, 0);
+      if ( rc == SQLITE_OK )
+      {
+         ossimKeywordlist kwl;
+
+         // Get the gpkg_contents records:
+         std::string tableName = "gpkg_contents";
+         std::vector< ossimRefPtr<ossimGpkgDatabaseRecordBase> > records;
+         if ( ossim_gpkg::getTableRows( db, tableName, records ) )
+         {
+            std::vector< ossimRefPtr<ossimGpkgDatabaseRecordBase> >::const_iterator i =
+               records.begin();
+            ossim_int32 index = 0;
+            while ( i != records.end() )
+            {
+               std::string prefix = "gpkg.";
+               prefix += tableName;
+               prefix += ossimString::toString(index++).string();
+               prefix += ".";
+               (*i)->saveState( kwl, prefix );
+               ++i;
+            } 
+         }
+
+         records.clear();
+
+         // Get the gpkg_spatial_ref_sys record:
+         tableName = "gpkg_spatial_ref_sys";
+         if ( ossim_gpkg::getTableRows( db, tableName, records ) )
+         {
+            std::vector< ossimRefPtr<ossimGpkgDatabaseRecordBase> >::const_iterator i =
+               records.begin();
+            ossim_int32 index = 0;
+            while ( i != records.end() )
+            {
+               std::string prefix = "gpkg.";
+               prefix += tableName;
+               prefix += ossimString::toString(index++).string();
+               prefix += ".";
+               (*i)->saveState( kwl, prefix );
+               ++i;
+            }
+         }
+
+         records.clear();
+
+         // Get the gpkg_tile_matrix_set records:
+         tableName = "gpkg_tile_matrix_set";
+         if ( ossim_gpkg::getTableRows( db, tableName, records ) )
+         {
+            std::vector< ossimRefPtr<ossimGpkgDatabaseRecordBase> >::const_iterator i =
+               records.begin();
+            ossim_int32 index = 0;
+            while ( i != records.end() )
+            {
+               std::string prefix = "gpkg.";
+               prefix += tableName;
+               prefix += ossimString::toString(index++).string();
+               prefix += ".";
+               (*i)->saveState( kwl, prefix );
+               ++i;
+
+               if ( traceTiles() )
+               {
+                  std::string key = "table_name";
+                  std::string tileTableName = kwl.findKey( prefix, key );
+                  if ( tileTableName.size() )
+                  {
+                     ossim_gpkg::printTiles( db, tileTableName,
+                                             ossimNotify(ossimNotifyLevel_DEBUG) );
+                  }
+               }
+            } 
+         }
+
+         records.clear();
+
+         // Get the gpkg_tile_matrix_set records:
+         tableName = "gpkg_tile_matrix";
+         if ( ossim_gpkg::getTableRows( db, tableName, records ) )
+         {
+            std::vector< ossimRefPtr<ossimGpkgDatabaseRecordBase> >::const_iterator i =
+               records.begin();
+            ossim_int32 index = 0;
+            while ( i != records.end() )
+            {
+               std::string prefix = "gpkg.";
+               prefix += tableName;
+               prefix += ossimString::toString(index++).string();
+               prefix += ".";
+               (*i)->saveState( kwl, prefix );
+               ++i;
+            } 
+         }
+
+         records.clear();
+         
+         // Get the nsg_tile_matrix_extent records:
+         tableName = "nsg_tile_matrix_extent";
+         if ( ossim_gpkg::getTableRows( db, tableName, records ) )
+         {
+            std::vector< ossimRefPtr<ossimGpkgDatabaseRecordBase> >::const_iterator i =
+               records.begin();
+            ossim_int32 index = 0;
+            while ( i != records.end() )
+            {
+               std::string prefix = "gpkg.";
+               prefix += tableName;
+               prefix += ossimString::toString(index++).string();
+               prefix += ".";
+               (*i)->saveState( kwl, prefix );
+               ++i;
+            } 
+         }
+
+
+
+         if ( kwl.getSize() )
+         {
+            out << kwl << std::endl;
+         }
+      }
+
+      sqlite3_close(db);
+      db = 0;
+   }
+
+   return out;
+}
+
diff --git a/ossim_plugins/sqlite/ossimGpkgInfo.h b/ossim_plugins/sqlite/ossimGpkgInfo.h
new file mode 100644
index 0000000..7927d90
--- /dev/null
+++ b/ossim_plugins/sqlite/ossimGpkgInfo.h
@@ -0,0 +1,60 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author:  David Burken
+//
+// Description: GeoPackage Info class.
+// 
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef ossimGpkgInfo_HEADER
+#define ossimGpkgInfo_HEADER 1
+
+#include <ossim/base/ossimConstants.h>
+#include <ossim/support_data/ossimInfoBase.h>
+#include <ossim/base/ossimFilename.h>
+
+/**
+ * @brief GeoPackage info class.
+ *
+ * Encapsulates the listgeo functionality.
+ */
+class ossimGpkgInfo : public ossimInfoBase
+{
+public:
+   
+   /** default constructor */
+   ossimGpkgInfo();
+
+   /** virtual destructor */
+   virtual ~ossimGpkgInfo();
+
+   /**
+    * @brief open method.
+    *
+    * @param file File name to open.
+    *
+    * @return true on success false on error.
+    */
+   virtual bool open(const ossimFilename& file);
+   
+   /**
+    * Print method.
+    *
+    * @param out Stream to print to.
+    * 
+    * @return std::ostream&
+    */
+   virtual std::ostream& print(std::ostream& out) const;
+
+private:
+
+   ossimFilename  m_file;
+};
+
+#endif /* End of "#ifndef ossimGpkgInfo_HEADER" */
+
diff --git a/ossim_plugins/sqlite/ossimGpkgNsgTileMatrixExtentRecord.cpp b/ossim_plugins/sqlite/ossimGpkgNsgTileMatrixExtentRecord.cpp
new file mode 100644
index 0000000..3089c70
--- /dev/null
+++ b/ossim_plugins/sqlite/ossimGpkgNsgTileMatrixExtentRecord.cpp
@@ -0,0 +1,342 @@
+//----------------------------------------------------------------------------
+//
+// File: ossimGpkgNsgTileMatrixExtentRecord.cpp
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Description: Container class for nsg_tile_matrix_extent table.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include "ossimGpkgNsgTileMatrixExtentRecord.h"
+#include "ossimSqliteUtil.h"
+#include <ossim/base/ossimCommon.h>
+#include <ossim/base/ossimDpt.h>
+#include <ossim/base/ossimDrect.h>
+#include <ossim/base/ossimIrect.h>
+#include <ossim/base/ossimKeywordlist.h>
+#include <ossim/base/ossimNotify.h>
+#include <sqlite3.h>
+#include <iomanip>
+
+static const std::string TABLE_NAME = "nsg_tile_matrix_extent";
+
+ossimGpkgNsgTileMatrixExtentRecord::ossimGpkgNsgTileMatrixExtentRecord()
+   :
+   ossimGpkgDatabaseRecordBase(),   
+   m_table_name(),
+   m_zoom_level(0),
+   m_extent_type(),
+   m_min_column(0),
+   m_min_row(0),
+   m_max_column(0),
+   m_max_row(0),
+   m_min_x(ossim::nan()),
+   m_min_y(ossim::nan()),
+   m_max_x(ossim::nan()),
+   m_max_y(ossim::nan())
+{
+}
+
+ossimGpkgNsgTileMatrixExtentRecord::ossimGpkgNsgTileMatrixExtentRecord(
+   const ossimGpkgNsgTileMatrixExtentRecord& obj)
+   :
+   ossimGpkgDatabaseRecordBase(),
+   m_table_name(obj.m_table_name),
+   m_zoom_level(obj.m_zoom_level),
+   m_extent_type(obj.m_extent_type),
+   m_min_column(obj.m_min_column),
+   m_min_row(obj.m_min_row),
+   m_max_column(obj.m_max_column),
+   m_max_row(obj.m_max_row),   
+   m_min_x(obj.m_min_x),
+   m_min_y(obj.m_min_y),
+   m_max_x(obj.m_max_x),
+   m_max_y(obj.m_max_y)
+{
+}
+
+const ossimGpkgNsgTileMatrixExtentRecord& ossimGpkgNsgTileMatrixExtentRecord::operator=(
+   const ossimGpkgNsgTileMatrixExtentRecord& obj)
+{
+   if ( this != &obj )
+   {
+      m_table_name  = obj.m_table_name;
+      m_zoom_level  = obj.m_zoom_level;
+      m_extent_type = obj.m_extent_type;
+      m_min_column  = obj.m_min_column;
+      m_min_row     = obj.m_min_row;      
+      m_max_column  = obj.m_max_column;
+      m_max_row     = obj.m_max_row;
+      m_min_x       = obj.m_min_x;
+      m_min_y       = obj.m_min_y;
+      m_max_x       = obj.m_max_x;
+      m_max_y       = obj.m_max_y;
+   }
+   return *this;
+}
+
+ossimGpkgNsgTileMatrixExtentRecord::~ossimGpkgNsgTileMatrixExtentRecord()
+{
+}
+
+const std::string& ossimGpkgNsgTileMatrixExtentRecord::getTableName()
+{
+   return TABLE_NAME;
+}
+
+bool ossimGpkgNsgTileMatrixExtentRecord::init( sqlite3_stmt* pStmt )
+{
+   static const char M[] = "ossimGpkgNsgTileMatrixExtentRecord::init";
+   
+   bool status = false;
+
+   if ( pStmt )
+   {
+      const ossim_int32 EXPECTED_COLUMNS = 11;
+      ossim_int32 nCol = sqlite3_column_count( pStmt );
+      
+      if ( nCol != EXPECTED_COLUMNS )
+      {
+         ossimNotify(ossimNotifyLevel_WARN)
+            << M << " WARNING:\nUnexpected number of columns: " << nCol
+            << "Expected column count: " << EXPECTED_COLUMNS
+            << std::endl;
+      }
+      
+      if ( nCol >= EXPECTED_COLUMNS )
+      {
+         ossim_int32 columnsFound = 0;
+         std::string colName;
+         ossim_int32 type;
+         
+         const char* c = 0; // To catch null so not to pass to string.
+         
+         for ( ossim_int32 i = 0; i < nCol; ++i )
+         {
+            colName = sqlite3_column_name(pStmt, i);
+            type    = sqlite3_column_type(pStmt, i);
+            if ( colName.size() )
+            {
+               if ( colName == "table_name" )
+               {
+                  c = (const char*)sqlite3_column_text(pStmt, i);
+                  m_table_name = (c ? c : "");
+                  ++columnsFound;
+               }
+               else if ( ( colName == "zoom_level" ) && ( type == SQLITE_INTEGER ) )
+               {
+                  m_zoom_level = sqlite3_column_int(pStmt, i);
+                  ++columnsFound;
+               }
+               else if ( colName == "extent_type" )
+               {
+                  c = (const char*)sqlite3_column_text(pStmt, i);
+                  m_extent_type = (c ? c : "");
+                  ++columnsFound;
+               }
+               else if ( ( colName == "min_column" ) && ( type == SQLITE_INTEGER ) )
+               {
+                  m_min_column = sqlite3_column_int(pStmt, i);
+                  ++columnsFound;
+               }
+               else if ( ( colName == "min_row" ) && ( type == SQLITE_INTEGER ) )
+               {
+                  m_min_row = sqlite3_column_int(pStmt, i);
+                  ++columnsFound;
+               }
+               else if ( ( colName == "max_column" ) && ( type == SQLITE_INTEGER ) )
+               {
+                  m_max_column = sqlite3_column_int(pStmt, i);
+                  ++columnsFound;
+               }
+               else if ( ( colName == "max_row" ) && ( type == SQLITE_INTEGER ) )
+               {
+                  m_max_row = sqlite3_column_int(pStmt, i);
+                  ++columnsFound;
+               }
+               else if ( ( colName == "min_x" ) && ( type == SQLITE_FLOAT ) )
+               {
+                  m_min_x = sqlite3_column_double(pStmt, i);
+                  ++columnsFound;
+               }
+               else if ( ( colName == "min_y" ) && ( type == SQLITE_FLOAT ) )
+               {
+                  m_min_y = sqlite3_column_double(pStmt, i);
+                  ++columnsFound;
+               }
+               else if ( ( colName == "max_x" ) && ( type == SQLITE_FLOAT ) ) 
+               {
+                  m_max_x = sqlite3_column_double(pStmt, i);
+                  ++columnsFound;
+               }
+               else if ( colName == "max_y" )
+               {
+                  m_max_y = sqlite3_column_double(pStmt, i);
+                  ++columnsFound;
+               }
+               else
+               {
+                  ossimNotify(ossimNotifyLevel_WARN)
+                     << M << " Unhandled column name["
+                     << i << "]: " << colName << std::endl;
+               }
+               
+            } // Matches: if ( colName.size() )
+            
+            if ( columnsFound == EXPECTED_COLUMNS )
+            {
+               status = true;
+               break;
+            }
+            
+         } // Matches: for ( int i = 0; i < nCol; ++i )  
+      }
+      
+   } // Matches: if ( pStmt )
+   
+   return status;
+   
+} // End:  ossimGpkgNsgTileMatrixExtentRecord::init( pStmt )
+
+bool ossimGpkgNsgTileMatrixExtentRecord::init( const std::string& tableName,
+                                               ossim_int32 zoom_level,
+                                               const ossimIrect& imageRect,
+                                               const ossimDrect& projectionRect )
+{
+   bool status = false;
+   if ( (imageRect.hasNans() == false) && (projectionRect.hasNans() == false) )
+   {
+      m_table_name  = tableName;
+      m_zoom_level  = zoom_level;
+      m_extent_type = "complete";
+      m_min_column  = imageRect.ul().x;
+      m_min_row     = imageRect.ul().y;
+      m_max_column  = imageRect.lr().x;
+      m_max_row     = imageRect.lr().y;
+      m_min_x       = projectionRect.ll().x;
+      m_min_y       = projectionRect.ll().y;
+      m_max_x       = projectionRect.ur().x;
+      m_max_y       = projectionRect.ur().y;
+
+      status = true;
+   }
+   return status;
+}
+
+bool ossimGpkgNsgTileMatrixExtentRecord::createTable( sqlite3* db )
+{
+   bool status = false;
+   if ( db )
+   {
+      status = ossim_sqlite::tableExists( db, TABLE_NAME );
+      if ( !status )
+      {
+         std::ostringstream sql;
+         sql << "CREATE TABLE " << TABLE_NAME << " ( "
+             << "table_name TEXT NOT NULL, "
+             << "zoom_level INTEGER NOT NULL, "
+             << "extent_type TEXT NOT NULL, "
+             << "min_column INTEGER NOT NULL, "
+             << "min_row INTEGER NOT NULL, "         
+             << "max_column INTEGER NOT NULL, "
+             << "max_row INTEGER NOT NULL, "         
+             << "min_x DOUBLE NOT NULL, "
+             << "min_y DOUBLE NOT NULL, "
+             << "max_x DOUBLE NOT NULL, "
+             << "max_y DOUBLE NOT NULL, "
+             << "CONSTRAINT pk_ntme PRIMARY KEY (table_name, zoom_level, extent_type, min_column, min_row, max_column, max_row), "
+             << "CONSTRAINT fk_ntme FOREIGN KEY (table_name, zoom_level) "
+             << "REFERENCES gpkg_tile_matrix(table_name, zoom_level)"
+             << ")";
+         
+         if ( ossim_sqlite::exec( db, sql.str() ) == SQLITE_DONE )
+         {
+            status = true;
+         }
+      }
+   }
+   return status;
+}
+
+bool ossimGpkgNsgTileMatrixExtentRecord::insert( sqlite3* db )
+{
+   bool status = false;
+   if ( db )
+   {
+      std::ostringstream sql;
+      sql << "INSERT INTO nsg_tile_matrix_extent VALUES ( "
+          <<  "'" << m_table_name  << "', "
+          << m_zoom_level  << ", "
+          <<  "'" << m_extent_type << "', "
+          << m_min_column  << ", "
+          << m_min_row     << ", "
+          << m_max_column  << ", "
+          << m_max_row     << ", "
+          << std::setprecision(16)
+          << m_min_x << ", "
+          << m_min_y << ", " 
+          << m_max_x << ", "
+          << m_max_y
+          << " )";
+
+      if ( ossim_sqlite::exec( db, sql.str() ) == SQLITE_DONE )
+      {
+         status = true;
+      }
+   }
+   return status;
+}
+
+void ossimGpkgNsgTileMatrixExtentRecord::saveState( ossimKeywordlist& kwl,
+                                                    const std::string& prefix ) const
+{
+   std::string myPref = prefix.size() ? prefix : std::string("nsg_tile_matrix_extent.");
+   std::string value;
+   
+   std::string key = "table_name";
+   kwl.addPair(myPref, key, m_table_name, true);
+
+   key = "zoom_level";
+   value = ossimString::toString(m_zoom_level).string();
+   kwl.addPair(myPref, key, value, true);
+
+   key = "extent_type";
+   kwl.addPair(myPref, key, m_extent_type, true);
+   
+   key = "min_column";
+   value = ossimString::toString(m_min_column).string();
+   kwl.addPair(myPref, key, value, true);
+
+   key = "min_row";
+   value = ossimString::toString(m_min_row).string();
+   kwl.addPair(myPref, key, value, true);
+
+   key = "max_column";
+   value = ossimString::toString(m_max_column).string();
+   kwl.addPair(myPref, key, value, true);
+
+   key = "max_row";
+   value = ossimString::toString(m_max_row).string();
+   kwl.addPair(myPref, key, value, true);
+
+   key = "min_x";
+   value = ossimString::toString(m_min_x, 20).string();
+   kwl.addPair(myPref, key, value, true);
+
+   key = "min_y";
+   value = ossimString::toString(m_min_y, 20).string();
+   kwl.addPair(myPref, key, value, true);
+
+   key = "max_x";
+   value = ossimString::toString(m_max_x, 20).string();
+   kwl.addPair(myPref, key, value, true);
+
+   key = "max_y";
+   value = ossimString::toString(m_max_y, 20).string();
+   kwl.addPair(myPref, key, value, true);
+}
+
diff --git a/ossim_plugins/sqlite/ossimGpkgNsgTileMatrixExtentRecord.h b/ossim_plugins/sqlite/ossimGpkgNsgTileMatrixExtentRecord.h
new file mode 100644
index 0000000..865f525
--- /dev/null
+++ b/ossim_plugins/sqlite/ossimGpkgNsgTileMatrixExtentRecord.h
@@ -0,0 +1,105 @@
+//----------------------------------------------------------------------------
+//
+// File: ossimGpkgNsgTileMatrixExtentRecord.h
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Description: Container class for nsg_tile_matrix_extent table.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef ossimGpkgNsgTileMatrixExtentRecord_HEADER
+#define ossimGpkgNsgTileMatrixExtentRecord_HEADER 1
+
+#include "ossimGpkgDatabaseRecordBase.h"
+#include <ossim/base/ossimConstants.h>
+
+class ossimIrect;
+class ossimDrect;
+struct sqlite3;
+
+class ossimGpkgNsgTileMatrixExtentRecord : public ossimGpkgDatabaseRecordBase
+{
+public:
+
+   /** @brief default constructor */
+   ossimGpkgNsgTileMatrixExtentRecord();
+
+   /* @brief copy constructor */
+   ossimGpkgNsgTileMatrixExtentRecord(const ossimGpkgNsgTileMatrixExtentRecord& obj);
+
+   /* @brief assignment operator= */
+   const ossimGpkgNsgTileMatrixExtentRecord& operator=
+      (const ossimGpkgNsgTileMatrixExtentRecord& obj);
+
+   /** @brief destructor */
+   virtual ~ossimGpkgNsgTileMatrixExtentRecord();
+
+   /**
+    * @brief Get the table name "nsg_tile_matrix_extent".
+    * @return table name
+    */
+   static const std::string& getTableName();
+
+   /**
+    * @brief Initialize from database.
+    * @param pStmt SQL statement, i.e. result of sqlite3_prepare_v2(...) call.
+    */
+   virtual bool init( sqlite3_stmt* pStmt );
+
+   /**
+    * @brief Initialize from projection.
+    * @param tableName e.g. "tiles"
+    * @param zoom_level
+    * @param imageRect 
+    * @param projectionRect Edge to edge either Easting Northin or lat lon.
+    * @return true on success, false on error.
+    */
+   bool init( const std::string& tableName,
+              ossim_int32 zoom_level,
+              const ossimIrect& imageRect,
+              const ossimDrect& projectionRect );
+   
+   /**
+    * @brief Creates  table in database.
+    * @param db
+    * @return true on success, false on error.
+    */   
+   static bool createTable( sqlite3* db );
+
+   /**
+    * @brief Inserst this record into gpkg_spatial_ref_sys table.
+    * @param db
+    * @return true on success, false on error.
+    */   
+   bool insert( sqlite3* db );    
+
+   /**
+    * @brief Saves the state of object.
+    * @param kwl Initialized by this.
+    * @param prefix e.g. "image0.". Can be empty.
+    */
+   virtual void saveState( ossimKeywordlist& kwl,
+                           const std::string& prefix ) const;
+   
+   std::string   m_table_name;
+   ossim_int32   m_zoom_level;
+   
+   /** “complete”,”missing”,“present”,”absent”,”mixed” */
+   std::string   m_extent_type;
+
+   ossim_int32   m_min_column; 
+   ossim_int32   m_min_row;  
+   ossim_int32   m_max_column; 
+   ossim_int32   m_max_row;  
+   ossim_float64 m_min_x;
+   ossim_float64 m_min_y;
+   ossim_float64 m_max_x;
+   ossim_float64 m_max_y;
+};
+
+#endif /* #ifndef ossimGpkgNsgTileMatrixExtentRecord_HEADER */
+
diff --git a/ossim_plugins/sqlite/ossimGpkgReader.cpp b/ossim_plugins/sqlite/ossimGpkgReader.cpp
new file mode 100644
index 0000000..3a69465
--- /dev/null
+++ b/ossim_plugins/sqlite/ossimGpkgReader.cpp
@@ -0,0 +1,984 @@
+//----------------------------------------------------------------------------
+//
+// File: ossimGpkgReader.cpp
+// 
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Description: OSSIM GeoPackage reader (tile source).
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include "ossimGpkgReader.h"
+#include "ossimGpkgSpatialRefSysRecord.h"
+#include "ossimGpkgTileRecord.h"
+#include "ossimGpkgUtil.h"
+
+#include <ossim/base/ossimBooleanProperty.h>
+#include <ossim/base/ossimCommon.h>
+#include <ossim/base/ossimConstants.h>
+#include <ossim/base/ossimDpt.h>
+#include <ossim/base/ossimEndian.h>
+#include <ossim/base/ossimGpt.h>
+#include <ossim/base/ossimIpt.h>
+#include <ossim/base/ossimIrect.h>
+#include <ossim/base/ossimKeywordlist.h>
+#include <ossim/base/ossimNotify.h>
+#include <ossim/base/ossimProperty.h>
+#include <ossim/base/ossimTrace.h>
+
+#include <ossim/imaging/ossimCodecFactoryRegistry.h>
+#include <ossim/imaging/ossimImageDataFactory.h>
+#include <ossim/imaging/ossimImageGeometryRegistry.h>
+#include <ossim/imaging/ossimImageHandlerRegistry.h>
+#include <ossim/imaging/ossimStreamReaderInterface.h>
+
+#include <ossim/projection/ossimMapProjection.h>
+#include <ossim/projection/ossimProjection.h>
+
+#include <sqlite3.h>
+
+#include <cmath>
+#include <sstream>
+
+RTTI_DEF1(ossimGpkgReader, "ossimGpkgReader", ossimImageHandler)
+
+#ifdef OSSIM_ID_ENABLED
+static const char OSSIM_ID[] = "$Id$";
+#endif
+
+static ossimTrace traceDebug("ossimGpkgReader:debug");
+static ossimTrace traceValidate("ossimGpkgReader:validate");
+
+ossimGpkgReader::ossimGpkgReader()
+   :
+   ossimImageHandler(),
+   m_ih(0),
+   m_tile(0),
+   m_cacheTile(0),
+   m_db(0),
+   m_currentEntry(0),
+   m_bands(0),
+   m_scalar(OSSIM_SCALAR_UNKNOWN),
+   m_tileWidth(0),
+   m_tileHeight(0),
+   m_entries(0)
+{
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimGpkgReader::ossimGpkgReader entered...\n";
+#ifdef OSSIM_ID_ENABLED
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "OSSIM_ID:  " << OSSIM_ID << "\n";
+#endif
+   }
+}
+
+ossimGpkgReader::~ossimGpkgReader()
+{
+   if (isOpen())
+   {
+      close();
+   }
+}
+
+void ossimGpkgReader::allocate()
+{
+   m_tile = ossimImageDataFactory::instance()->create(this, this);
+   m_tile->initialize();
+}
+
+ossimRefPtr<ossimImageData> ossimGpkgReader::getTile(
+   const ossimIrect& rect, ossim_uint32 resLevel)
+{
+   if ( !m_tile )
+   {
+      allocate();
+   }
+   
+   if (m_tile.valid())
+   {
+      // Image rectangle must be set prior to calling getTile.
+      m_tile->setImageRectangle(rect);
+      
+      if ( getTile( m_tile.get(), resLevel ) == false )
+      {
+         if (m_tile->getDataObjectStatus() != OSSIM_NULL)
+         {
+            m_tile->makeBlank();
+         }
+      }
+   }
+   
+   return m_tile;
+}
+
+bool ossimGpkgReader::getTile(ossimImageData* result,
+                             ossim_uint32 resLevel)
+{
+   bool status = false;
+   
+   //---
+   // Not open, this tile source bypassed, or invalid res level,
+   // return a blank tile.
+   //---
+   if( isOpen() && isSourceEnabled() && isValidRLevel(resLevel) &&
+       result && (result->getNumberOfBands() == getNumberOfOutputBands()) )
+   {
+      result->ref(); // Increment ref count.
+
+      if ( resLevel < getNumberOfZoomLevels() )
+      {
+         status = true;
+         
+         ossimIrect tileRect = result->getImageRectangle();
+         ossimIrect imageRect = getImageRectangle(resLevel);
+
+         //---
+         // Format allows for missing tiles so alway make blank in case tile
+         // is not filled completely.
+         //---
+         m_tile->makeBlank();
+         
+         if ( imageRect.intersects(tileRect) )
+         {
+            // Make a clip rect.
+            ossimIrect clipRect = tileRect.clipToRect( imageRect );
+            
+            // This will validate the tile at the end.
+            fillTile(resLevel, tileRect, clipRect, result);
+         }
+      }
+      else
+      {
+         status = getOverviewTile(resLevel, result);
+      }
+      
+      result->unref();  // Decrement ref count.
+   }
+
+   return status;
+}
+
+void ossimGpkgReader::fillTile( ossim_uint32 resLevel,
+                                const ossimIrect& tileRect,
+                                const ossimIrect& clipRect,
+                                ossimImageData* tile )
+{
+   if ( tile )
+   {
+      // Get the tile indexes needed to fill the clipRect.
+      std::vector<ossimIpt> tileIndexes;
+      getTileIndexes( resLevel, clipRect, tileIndexes );
+      
+      std::vector<ossimIpt>::const_iterator i = tileIndexes.begin();
+      while ( i != tileIndexes.end() )
+      {
+         ossimRefPtr<ossimImageData> id = getTile( resLevel, (*i) );
+         if ( id.valid() )
+         {
+            ossimIrect tileClipRect = clipRect.clipToRect( id->getImageRectangle() );
+            id->unloadTile( tile->getBuf(), tileRect, tileClipRect, OSSIM_BSQ );
+         }
+         ++i;
+      }
+      
+      tile->validate();
+   }
+}
+
+void ossimGpkgReader::getTileIndexes( ossim_uint32 resLevel,
+                                      const ossimIrect& clipRect,
+                                      std::vector<ossimIpt>& tileIndexes ) const
+{
+   ossimIpt tileSize;
+   getTileSize( resLevel, tileSize );
+
+   if ( tileSize.x && tileSize.y )
+   {
+      ossimIrect expandedRect = clipRect;
+
+      // Add the sub image offset if any:
+      ossimIpt subImageOffset(0,0);
+      if ( m_currentEntry < m_entries.size() )
+      {
+         m_entries[m_currentEntry].getSubImageOffset( resLevel, subImageOffset );
+         expandedRect += subImageOffset;
+      }
+
+      expandedRect.stretchToTileBoundary( tileSize );
+
+      ossim_int32 y = expandedRect.ul().y;
+      while ( y < expandedRect.lr().y )
+      {
+         ossim_int32 x = expandedRect.ul().x;
+         while ( x < expandedRect.lr().x )
+         {
+            ossimIpt index( x/tileSize.x, y/tileSize.y );
+            tileIndexes.push_back( index );
+            x += tileSize.x;
+         }
+         y += tileSize.y;
+      }
+   }
+}
+
+void ossimGpkgReader::getTileSize( ossim_uint32 resLevel, ossimIpt& tileSize ) const
+{
+   if ( m_currentEntry < (ossim_uint32)m_entries.size() )
+   {
+      if ( resLevel < (ossim_uint32)m_entries[m_currentEntry].getTileMatrix().size() )
+      {
+         tileSize.x =
+            (ossim_int32)m_entries[m_currentEntry].getTileMatrix()[resLevel].m_tile_width;
+         tileSize.y =
+            (ossim_int32)m_entries[m_currentEntry].getTileMatrix()[resLevel].m_tile_height;
+      }
+   }
+}
+
+ossimIrect ossimGpkgReader::getImageRectangle(ossim_uint32 resLevel) const
+{
+   return ossimIrect(0,
+                     0,
+                     getNumberOfSamples(resLevel) - 1,
+                     getNumberOfLines(resLevel)   - 1);
+}
+
+bool ossimGpkgReader::saveState(ossimKeywordlist& kwl,
+                                const char* prefix) const
+{
+   return ossimImageHandler::saveState(kwl, prefix);
+}
+
+bool ossimGpkgReader::loadState(const ossimKeywordlist& kwl,
+                               const char* prefix)
+{
+   bool result = false;
+   if (ossimImageHandler::loadState(kwl, prefix))
+   {
+      result = open();
+   }
+   return result;
+}
+
+void ossimGpkgReader::setProperty(ossimRefPtr<ossimProperty> property)
+{
+   ossimImageHandler::setProperty(property);
+}
+
+ossimRefPtr<ossimProperty> ossimGpkgReader::getProperty(const ossimString& name)const
+{
+   ossimRefPtr<ossimProperty> prop = 0;
+   prop = ossimImageHandler::getProperty(name);
+   return prop;
+}
+
+void ossimGpkgReader::getPropertyNames(std::vector<ossimString>& propertyNames)const
+{
+   ossimImageHandler::getPropertyNames(propertyNames);
+}
+
+bool ossimGpkgReader::open()
+{
+   static const char M[] = "ossimGpkgReader::open";
+
+   bool status = false;
+   
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << M << " entered..." << "\nFile:  " << theImageFile.c_str() << "\n";
+   }
+
+   // Start with a clean slate.
+   if (isOpen())
+   {
+      close();
+   }
+
+   std::ifstream str;
+   str.open(theImageFile.c_str(), std::ios_base::in | std::ios_base::binary);
+
+   if ( ossim_gpkg::checkSignature( str ) )
+   {
+      if ( ossim_gpkg::checkApplicationId( str ) == false )
+      {
+         // Just issue a warning at this point as this requirement is new...
+         if (traceDebug())
+         {
+            ossimNotify(ossimNotifyLevel_WARN)
+               << M << " WARNING!"
+               << "File: " << theImageFile << " does not have required application_id!"
+               << "\nProceeding anyway...\n";
+         }
+      }
+      
+      int rc = sqlite3_open_v2( theImageFile.c_str(), &m_db, SQLITE_OPEN_READONLY, 0);
+      if ( rc == SQLITE_OK )
+      {
+         m_entries.clear();
+         ossim_gpkg::getTileEntries( m_db, m_entries );
+
+         if ( m_entries.size() )
+         {
+            status = initImageParams();
+            
+            if (traceDebug())
+            {
+               std::vector<ossimGpkgTileEntry>::const_iterator i = m_entries.begin();
+               while ( i != m_entries.end() )
+               {
+                  ossimNotify(ossimNotifyLevel_DEBUG) << (*i) << "\n";
+                  ++i;
+               }
+            }
+            if (traceValidate())
+            {
+               std::vector<ossimGpkgTileEntry>::const_iterator i = m_entries.begin();
+               while ( i != m_entries.end() )
+               {
+                  (*i).printValidate( ossimNotify(ossimNotifyLevel_DEBUG) );
+                  ++i;
+               }
+            }
+         }
+         
+      }
+   }
+
+   if ( !status )
+   {
+      close();
+   }
+   else
+   {
+      completeOpen();
+   }
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << M << " exit status: " << (status?"true":"false") << "\n";
+   }
+
+   return status;
+}
+
+ossim_uint32 ossimGpkgReader::getTileWidth() const
+{
+   return ( m_tile.valid() ? m_tile->getWidth() : 0 );
+}
+
+ossim_uint32 ossimGpkgReader::getTileHeight() const
+{
+   return ( m_tile.valid() ? m_tile->getHeight() : 0 );
+}
+
+ossim_uint32 ossimGpkgReader::getNumberOfLines(ossim_uint32 resLevel) const
+{
+   ossim_uint32 result = 0;
+   if ( m_currentEntry < m_entries.size() )
+   {
+      if ( resLevel < m_entries[m_currentEntry].getTileMatrix().size() )
+      {
+         result = m_entries[m_currentEntry].getNumberOfLines( resLevel );
+      }
+      else if ( theOverview.valid() )
+      {
+         result = theOverview->getNumberOfLines(resLevel);
+      }
+   }
+   return result;
+}
+
+ossim_uint32 ossimGpkgReader::getNumberOfSamples(ossim_uint32 resLevel) const
+{
+   ossim_uint32 result = 0;
+   if ( m_currentEntry < m_entries.size() )
+   {
+      if ( resLevel < m_entries[m_currentEntry].getTileMatrix().size() )
+      {
+         result = m_entries[m_currentEntry].getNumberOfSamples( resLevel );
+      }
+      else if ( theOverview.valid() )
+      {
+         result = theOverview->getNumberOfSamples(resLevel);
+      }
+   }
+   return result;
+}
+ossim_uint32 ossimGpkgReader::getImageTileWidth() const
+{
+   return m_tileWidth;
+}
+
+ossim_uint32 ossimGpkgReader::getImageTileHeight() const
+{
+   return m_tileHeight;
+}
+
+ossimString ossimGpkgReader::getShortName()const
+{
+   return ossimString("ossim_gpkg_reader");
+}
+   
+ossimString ossimGpkgReader::getLongName()const
+{
+   return ossimString("ossim Geo Package reader");
+}
+
+ossimString  ossimGpkgReader::getClassName()const
+{
+   return ossimString("ossimGpkgReader");
+}
+
+ossim_uint32 ossimGpkgReader::getNumberOfInputBands() const
+{
+   return m_bands;
+}
+
+ossim_uint32 ossimGpkgReader::getNumberOfOutputBands()const
+{
+   return m_bands;
+}
+
+ossimScalarType ossimGpkgReader::getOutputScalarType() const
+{
+   return m_scalar;
+}
+
+bool ossimGpkgReader::isOpen()const
+{
+   return (m_db != 0 );
+}
+
+void ossimGpkgReader::close()
+{
+   if ( isOpen() )
+   {
+      ossimImageHandler::close();
+   }
+   if ( m_db )
+   {
+      sqlite3_close( m_db );
+      m_db = 0;
+   }
+   m_entries.clear();
+}
+
+ossim_uint32 ossimGpkgReader::getNumberOfEntries()const
+{
+   return (ossim_uint32)m_entries.size();
+}
+
+ossim_uint32 ossimGpkgReader::getCurrentEntry()const
+{
+   return m_currentEntry;
+}
+
+void ossimGpkgReader::getEntryList(std::vector<ossim_uint32>& entryList)const
+{
+   for ( ossim_uint32 i = 0; i < m_entries.size(); ++i )
+   {
+      entryList.push_back(i);
+   }
+}
+
+void ossimGpkgReader::getEntryNames(std::vector<ossimString>& entryNames) const
+{
+   std::vector<ossimGpkgTileEntry>::const_iterator i = m_entries.begin();
+   while ( i != m_entries.end() )
+   {
+      entryNames.push_back( ossimString((*i).getTileMatrixSet().m_table_name) );
+      ++i;
+   }
+}
+
+bool ossimGpkgReader::setCurrentEntry(ossim_uint32 entryIdx )
+{
+   bool result = true;
+   if ( m_currentEntry != entryIdx )
+   {
+      if ( entryIdx < getNumberOfEntries() )
+      {
+         m_currentEntry = entryIdx;
+         
+         if ( isOpen() )
+         {
+            // Zero out the tile to force an allocate() call.
+            m_tile = 0;
+            
+            // Clear the geometry.
+            theGeometry = 0;
+            
+            // Must clear or openOverview will use last entries.
+            theOverviewFile.clear();
+
+            // This intitializes bands, scalar, tile width, height...
+            initImageParams();
+            
+            if ( result )
+            {
+               completeOpen();
+            }
+         }
+      }
+      else
+      {
+         result = false; // Entry index out of range.
+      }
+   }
+   return result;
+}
+
+ossim_uint32 ossimGpkgReader::getNumberOfDecimationLevels() const
+{
+   // Internal overviews.
+   ossim_uint32 result = getNumberOfZoomLevels();
+
+   if (theOverview.valid())
+   {
+      // Add external overviews.
+      result += theOverview->getNumberOfDecimationLevels();
+   }
+
+   return result;  
+}
+
+ossim_uint32 ossimGpkgReader::getNumberOfZoomLevels() const
+{
+   ossim_uint32 result = 0;
+   
+   //---
+   // Index 0 is the highest zoom_level which is the best resolution or r0 in ossim terms.
+   // In GeoPackage zoom_level 0 is the lowest resolution.
+   //---
+   if ( m_currentEntry < (ossim_uint32)m_entries.size())
+   {
+      size_t matrixSize = m_entries[m_currentEntry].getTileMatrix().size();
+      if ( matrixSize )
+      {
+         result =
+            m_entries[m_currentEntry].getTileMatrix()[0].m_zoom_level -
+            m_entries[m_currentEntry].getTileMatrix()[ matrixSize-1 ].m_zoom_level + 1;
+      }
+   }
+
+   return result;
+}
+
+ossimRefPtr<ossimImageGeometry> ossimGpkgReader::getImageGeometry()
+{
+   if ( !theGeometry )
+   {
+      //---
+      // Check for external geom - this is a file.geom not to be confused with
+      // geometries picked up from dot.xml, dot.prj, dot.j2w and so on.  We
+      // will check for that later if the getInternalImageGeometry fails.
+      //---
+      theGeometry = getExternalImageGeometry();
+      
+      if ( !theGeometry )
+      {
+         // Check the internal geometry first to avoid a factory call.
+         theGeometry = getInternalImageGeometry();
+         
+         //---
+         // WARNING:
+         // Must create/set the geometry at this point or the next call to
+         // ossimImageGeometryRegistry::extendGeometry will put us in an infinite loop
+         // as it does a recursive call back to ossimImageHandler::getImageGeometry().
+         //---
+         if ( !theGeometry )
+         {
+            theGeometry = new ossimImageGeometry();
+         }
+         
+         // Check for set projection.
+         if ( !theGeometry->getProjection() )
+         {
+            // Last try factories for projection.
+            ossimImageGeometryRegistry::instance()->extendGeometry(this);
+         }
+      }
+
+      // Set image things the geometry object should know about.
+      initImageParameters( theGeometry.get() );
+      
+      if (traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG)
+            << "ossimGpkgReader::getImageGeometry geometry:\n"
+            << *(theGeometry.get()) << "\n";
+      }
+      
+   }
+   return theGeometry;
+   
+} // End: ossimGpkgReader::getImageGeometry()
+
+ossimRefPtr<ossimImageGeometry> ossimGpkgReader::getInternalImageGeometry()
+{
+   static const char M[] = "ossimGpkgReader::getInternalImageGeometry";
+
+   ossimRefPtr<ossimImageGeometry> geom = 0;
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG) << M << " entered...\n";
+   }
+   
+   if ( m_currentEntry < m_entries.size() )
+   {
+      ossimRefPtr<ossimMapProjection> mapProj = m_entries[m_currentEntry].getNewMapProjection();
+
+      if ( mapProj.valid() )
+      {
+         ossimRefPtr<ossimProjection> proj = mapProj.get();
+         if ( proj.valid() )
+         {
+            // Create and assign projection to our ossimImageGeometry object.
+            geom = new ossimImageGeometry();
+            geom->setProjection( proj.get() );
+            if (traceDebug())
+            {
+               ossimNotify(ossimNotifyLevel_DEBUG) << "Created geometry...\n";
+            }
+         }  
+      }
+   }
+
+   if (traceDebug())
+   {
+      if ( geom.valid() )
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG) << M << " exited...\n";
+      }
+   }
+   
+   return geom;
+   
+} // End: ossimGpkgReader::getInternalImageGeometry()
+
+bool ossimGpkgReader::initImageParams()
+{
+   static const char MODULE[] = "ossimGpkgReader::initImageParams";
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " entered...\n";
+   }
+
+   bool result = false;
+   if ( m_db )
+   {
+      if ( m_currentEntry < m_entries.size() )
+      {
+         if ( m_entries[m_currentEntry].getTileMatrix().size() )
+         {
+            ossimIpt index(-1,-1);
+            
+            std::string tableName = m_entries[m_currentEntry].getTileMatrix()[0].m_table_name;
+            ossim_int32 zoomLevel = m_entries[m_currentEntry].getTileMatrix()[0].m_zoom_level;
+
+            // Get the first tile for the highest res zoom level.
+
+            const char *zLeftover;   // Tail of unprocessed SQL
+            sqlite3_stmt *pStmt = 0; // The current SQL statement
+
+            std::ostringstream sql;
+            sql << "SELECT min(id), tile_column, tile_row from "
+                << tableName << " WHERE zoom_level=" << zoomLevel;
+
+            if (traceDebug())
+            {
+               ossimNotify(ossimNotifyLevel_DEBUG)
+                  << "sql:\n" << sql.str() << "\n";
+            }
+            
+            int rc = sqlite3_prepare_v2(m_db,        // Database handle
+                                        sql.str().c_str(),// SQL statement, UTF-8 encoded
+                                        -1,          // Maximum length of zSql in bytes.
+                                        &pStmt,      // OUT: Statement handle
+                                        &zLeftover); // OUT: Pointer to unused portion of zSql
+            if ( rc == SQLITE_OK )
+            {
+               int nCol = sqlite3_column_count( pStmt );
+               if ( nCol == 3 )
+               {
+                  // Read the row:
+                  rc = sqlite3_step(pStmt);
+                  if ( rc == SQLITE_ROW )
+                  {
+                     index.x = sqlite3_column_int(pStmt, 1);
+                     index.y = sqlite3_column_int(pStmt, 2);
+                  }
+               }
+            }
+               
+            sqlite3_finalize(pStmt);
+
+            if ( (index.x > -1) && (index.y > -1) )
+            {
+               // Grab a tile:
+               ossimRefPtr<ossimImageData> tile = getTile( 0, index );
+               if ( tile.valid() )
+               {
+                  // Set the bands:
+                  m_bands = tile->getNumberOfBands();
+
+                  // Set the scalar type:
+                  m_scalar = tile->getScalarType();
+                  
+                  // Set tile size:
+                  m_tileWidth = tile->getWidth();
+                  m_tileHeight = tile->getHeight();
+                  result = true;
+               }
+            }
+
+            if ( !result )
+            {
+               // Set to some default:
+               m_bands = 3;
+               m_scalar = OSSIM_UINT8;
+               m_tileWidth = 256;
+               m_tileHeight = 256;
+               result = true;
+            }
+         }
+      }
+   }
+
+   if ( traceDebug() )
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " exit status = " << (result?"true":"false") << "\n";
+   }
+
+   return result;
+}
+
+ossimRefPtr<ossimImageData> ossimGpkgReader::getTile( ossim_uint32 resLevel,
+                                                      ossimIpt index)
+{
+   static const char MODULE[] = "ossimGpkgReader::getTile(resLevel, index)";
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " entered..."
+         << "\nresLevel: " << resLevel << " index: " << index << "\n";
+   }
+
+   ossimRefPtr<ossimImageData> result = 0;
+   
+   if ( m_db )
+   {
+      if ( m_currentEntry < m_entries.size() )
+      {
+         if ( resLevel < m_entries[m_currentEntry].getTileMatrix().size() )
+         {
+            std::string tableName =
+               m_entries[m_currentEntry].getTileMatrix()[resLevel].m_table_name;
+            ossim_int32 zoomLevel =
+               m_entries[m_currentEntry].getTileMatrix()[resLevel].m_zoom_level;
+            const char *zLeftover;   // Tail of unprocessed SQL
+            sqlite3_stmt *pStmt = 0; // The current SQL statement
+            std::ostringstream sql;
+            sql << "SELECT id, zoom_level, tile_column, tile_row, tile_data from "
+                << tableName
+                << " WHERE zoom_level=" << zoomLevel
+                << " AND tile_column=" << index.x
+                << " AND tile_row=" << index.y;
+
+            if (traceDebug())
+            {
+               ossimNotify(ossimNotifyLevel_DEBUG)
+                  << MODULE << " sql:\n" << sql.str() << "\n";
+            }
+            
+            int rc = sqlite3_prepare_v2(
+               m_db,             // Database handle
+               sql.str().c_str(),// SQL statement, UTF-8 encoded
+               -1,               // Maximum length of zSql in bytes.
+               &pStmt,           // OUT: Statement handle
+               &zLeftover);      // OUT: Pointer to unused portion of zSql
+            if ( rc == SQLITE_OK )
+            {
+               int nCol = sqlite3_column_count( pStmt );
+               if ( nCol )
+               {
+                  // Read the row:
+                  rc = sqlite3_step(pStmt);
+                  if (rc == SQLITE_ROW) //  || (rc == SQLITE_DONE) )
+                  {
+                     ossimGpkgTileRecord tile;
+                     tile.setCopyTileFlag(true);
+                     if (tile.init( pStmt ) )
+                     {
+                        ossimIpt tileSize;
+                        m_entries[m_currentEntry].getTileMatrix()[resLevel].getTileSize(tileSize);
+                        ossimRefPtr<ossimCodecBase> codec;
+                        switch ( tile.getTileType() )
+                        {
+                           case ossimGpkgTileRecord::OSSIM_GPKG_JPEG:
+                           {
+                              // we need to cache this instead of allocating a new codec every tile
+                              // for now just getting it to compile with registry implementation
+                              //
+                              if( !m_jpegCodec.valid() )
+                              {
+                                 m_jpegCodec = ossimCodecFactoryRegistry::instance()->
+                                    createCodec(ossimString("jpeg"));
+                              }
+                              
+                              codec = m_jpegCodec.get();
+                              break;
+                           }
+                           case ossimGpkgTileRecord::OSSIM_GPKG_PNG:
+                           {
+                              if( !m_pngCodec.valid() )
+                              {
+                                 m_pngCodec = ossimCodecFactoryRegistry::instance()->
+                                    createCodec(ossimString("png"));
+                              }
+                              codec = m_pngCodec.get();
+                              break;
+                           }
+                           default:
+                           {
+                              if (traceDebug())
+                              {
+                                 ossimNotify(ossimNotifyLevel_WARN)
+                                    << "Unhandled type: " << tile.getTileType() << endl;;
+                              }
+                              result = 0;
+                              break;
+                           }
+                        }
+                        
+                        if ( codec.valid() )
+                        {
+                           if ( codec->decode(tile.m_tile_data, m_cacheTile ) )
+                           {
+                              result = m_cacheTile;
+                           }
+                           else
+                           {
+                              ossimNotify(ossimNotifyLevel_WARN)
+                                 << "WARNING: decode failed...\n";
+                           }
+                        }
+                        
+                        if ( result.valid() )
+                        {
+                           // Set the tile origin in image space.
+                           ossimIpt origin( index.x*tileSize.x,
+                                            index.y*tileSize.y );
+                           
+                           // Subtract the sub image offset if any:
+                           ossimIpt subImageOffset(0,0);
+                           m_entries[m_currentEntry].getSubImageOffset( resLevel, subImageOffset );
+                           origin -= subImageOffset;
+                           
+                           result->setOrigin( origin );
+                        }
+                        else if (traceDebug())
+                        {
+                           ossimNotify(ossimNotifyLevel_WARN)
+                              << MODULE << " WARNING: result is null!\n";
+                        }
+                     }
+                  }
+                  
+               } // Matches: if ( nCol )
+               
+            } // Matches: if ( rc == SQLITE_OK )
+
+            sqlite3_finalize(pStmt);
+            
+         } // Matches: if(resLevel<m_entries[m_currentEntry].getTileMatrix().size())
+         
+      } // Matches: if ( m_currentEntry < m_entries.size() )
+      
+   } // Matches: if ( m_db )
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " exit result is " << (result.valid()?"set.":"null.") << "\n";
+   }
+
+   return result;
+   
+} // End: ossimGpkgReader::getTile( resLevel, index )
+
+ossimRefPtr<ossimImageData> ossimGpkgReader::uncompressPngTile( const ossimGpkgTileRecord& tile,
+                                                                const ossimIpt& tileSize )
+{
+   ossimRefPtr<ossimImageData> result = 0;
+
+   //---
+   // This copies the data to a stringbuf.  TODO, use tile data
+   // directly.
+   //---
+   if ( tile.m_tile_data.size() )
+   {
+      std::string data( (char*)&tile.m_tile_data.front(),
+                        tile.m_tile_data.size() );
+      std::istringstream is(data);
+                           
+      if ( m_ih.valid() )
+      {
+         // Have an image handler from previous open:
+         ossimStreamReaderInterface* sri =
+            dynamic_cast<ossimStreamReaderInterface*>( m_ih.get() );
+         if ( sri )
+         {
+            if ( sri->open( &is, 0, false ) == false )
+            {
+               // Per the spec tile mime types can be mixed.
+               m_ih = 0;
+            }
+         }
+         else
+         {
+            m_ih = 0;
+         }
+      }
+                           
+      if ( !m_ih )
+      {
+         m_ih = ossimImageHandlerRegistry::instance()->open( &is, 0, false );
+      }
+      
+      if ( m_ih.valid() )
+      {
+         // Get the raw rectangle:
+         ossimIrect rect( 0, 0, tileSize.x - 1, tileSize.y - 1 );
+         
+         // Get the tile from the image handler:
+         result = m_ih->getTile( rect, 0 );
+      }
+   }
+
+   return result;
+   
+} // ossimGpkgReader::uncompressPngTile
+
+void ossimGpkgReader::computeGsd( ossimDpt& gsd) const
+{
+   if ( m_currentEntry < m_entries.size() )
+   {
+      m_entries[m_currentEntry].getGsd( 0, gsd );
+   }
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimGpkgReader::computeGsd DEBUG:\ngsd: " << gsd << "\n";   
+   }
+   
+} // End: ossimGpkgReader::computeGsd
+
diff --git a/ossim_plugins/sqlite/ossimGpkgReader.h b/ossim_plugins/sqlite/ossimGpkgReader.h
new file mode 100644
index 0000000..752ee8e
--- /dev/null
+++ b/ossim_plugins/sqlite/ossimGpkgReader.h
@@ -0,0 +1,293 @@
+//----------------------------------------------------------------------------
+//
+// File: ossimGpkgReader.h
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Description: OSSIM GeoPackage reader (tile source).
+//
+//----------------------------------------------------------------------------
+// $Id$
+#ifndef ossimGpkgReader_HEADER
+#define ossimGpkgReader_HEADER 1
+
+#include <ossim/imaging/ossimImageHandler.h>
+#include <ossim/base/ossimRefPtr.h>
+#include "ossimGpkgTileEntry.h"
+#include <ossim/imaging/ossimCodecBase.h>
+
+#include <vector>
+
+class ossimGpkgTileRecord;
+class ossimImageData;
+struct sqlite3;
+
+class ossimGpkgReader : public ossimImageHandler
+{
+public:
+
+   /** default constructor */
+   ossimGpkgReader();
+
+   /** virtual destructor */
+   virtual ~ossimGpkgReader();
+
+   /** @return "gpkg" */
+   virtual ossimString getShortName() const;
+
+   /** @return "ossim gpkg" */
+   virtual ossimString getLongName()  const;
+
+   /** @return "ossimGpkgReader" */
+   virtual ossimString getClassName()    const;
+
+   /**
+    *  Returns a pointer to a tile given an origin representing the upper
+    *  left corner of the tile to grab from the image.
+    *  Satisfies pure virtual from TileSource class.
+    */
+   virtual ossimRefPtr<ossimImageData> getTile(const  ossimIrect& rect,
+                                               ossim_uint32 resLevel=0);
+   /**
+    * Method to get a tile.   
+    *
+    * @param result The tile to stuff.  Note The requested rectangle in full
+    * image space and bands should be set in the result tile prior to
+    * passing.  It will be an error if:
+    * result.getNumberOfBands() != this->getNumberOfOutputBands()
+    *
+    * @return true on success false on error.  If return is false, result
+    *  is undefined so caller should handle appropriately with makeBlank or
+    * whatever.
+    */
+   virtual bool getTile(ossimImageData* result, ossim_uint32 resLevel=0);
+
+    /**
+     *  Returns the number of bands in the image.
+     *  Satisfies pure virtual from ImageHandler class.
+     */
+   virtual ossim_uint32 getNumberOfInputBands() const;
+
+   /**
+    * Returns the number of bands in a tile returned from this TileSource.
+    * Note: we are supporting sources that can have multiple data objects.
+    * If you want to know the scalar type of an object you can pass in the
+    */
+   virtual ossim_uint32 getNumberOfOutputBands()const;
+
+   /**
+     *  Returns the number of lines in the image.
+     *  Satisfies pure virtual from ImageHandler class.
+     */
+   virtual ossim_uint32 getNumberOfLines(ossim_uint32 resLevel = 0) const;
+
+   /**
+    *  Returns the number of samples in the image.
+    *  Satisfies pure virtual from ImageHandler class.
+    */
+   virtual ossim_uint32 getNumberOfSamples(ossim_uint32 resLevel = 0) const;
+
+   /**
+    * Returns the zero based image rectangle for the reduced resolution data
+    * set (rrds) passed in.  Note that rrds 0 is the highest resolution rrds.
+    */
+   virtual ossimIrect getImageRectangle(ossim_uint32 resLevel = 0) const;
+
+   /**
+    * Method to save the state of an object to a keyword list.
+    * Return true if ok or false on error.
+    */
+   virtual bool saveState(ossimKeywordlist& kwl,
+                          const char* prefix=0)const;
+
+   /**
+    * Method to the load (recreate) the state of an object from a keyword
+    * list.  Return true if ok or false on error.
+    */
+   virtual bool loadState(const ossimKeywordlist& kwl,
+                          const char* prefix=0);
+
+   /**
+    * @brief Set propterty method. Overrides ossimImageHandler::setProperty.
+    *
+    * Current property name handled:
+    * "scale" One double value representing the scale in meters per pixel. It is
+    * assumed the scale is same for x and y direction.
+    * 
+    * @param property to set.
+    */
+   virtual void setProperty(ossimRefPtr<ossimProperty> property);
+
+   /**
+     * @brief Get propterty method. Overrides ossimImageHandler::getProperty.
+    * @param name Property name to get.
+    */
+   virtual ossimRefPtr<ossimProperty> getProperty(const ossimString& name) const;
+   
+   /**
+    * @brief Get propterty names. Overrides ossimImageHandler::getPropertyNames.
+    * @param propertyNames Array to initialize.
+    */
+   virtual void getPropertyNames(std::vector<ossimString>& propertyNames) const;
+
+   /**
+    * Returns the output pixel type of the tile source.
+    */
+   virtual ossimScalarType getOutputScalarType() const;
+
+   /**
+    * Returns the width of the output tile.
+    */
+   virtual ossim_uint32    getTileWidth() const;
+
+   /**
+    * Returns the height of the output tile.
+    */
+   virtual ossim_uint32    getTileHeight() const;
+
+   /**
+    * Returns the tile width of the image or 0 if the image is not tiled.
+    * Note: this is not the same as the ossimImageSource::getTileWidth which
+    * returns the output tile width which can be different than the internal
+    * image tile width on disk.
+    */
+   virtual ossim_uint32 getImageTileWidth() const;
+
+   /**
+    * Returns the tile width of the image or 0 if the image is not tiled.
+    * Note: this is not the same as the ossimImageSource::getTileWidth which
+    * returns the output tile width which can be different than the internal
+    * image tile width on disk.
+    */
+   virtual ossim_uint32 getImageTileHeight() const;
+
+   bool isOpen()const;
+
+   /** Close method. */
+   virtual void close();
+   
+   /** @return The number of entries (images) in the image file. */
+   virtual ossim_uint32 getNumberOfEntries() const;
+
+   /** @return The current entry number. */
+   virtual ossim_uint32 getCurrentEntry()const;
+
+   /**
+    * @brief Gets the entry list.
+    * @param entryList This is the list to initialize with entry indexes.
+    */
+   virtual void getEntryList(std::vector<ossim_uint32>& entryList) const;
+   
+   /**
+    * @brief Get the list of entry names.
+    *
+    * This implementation uses the entry tile table name.
+    * 
+    * @param getEntryNames List to initialize with strings associated with
+    * entries.
+    */
+   virtual void getEntryNames(std::vector<ossimString>& entryNames) const;
+   
+   /**
+    * @param entryIdx Entry number to select.
+    *
+    * @note The implementation does nothing.  Derived classes that handle
+    * multiple images should override.
+    *
+    * @return true if it was able to set the current entry and false otherwise.
+    */
+   virtual bool setCurrentEntry(ossim_uint32 entryIdx);
+
+   /**
+    * @brief Returns the number of decimation levels.
+    * 
+    * This returns the total number of decimation levels.  It is important to
+    * note that res level 0 or full resolution is included in the list and has
+    * decimation values 1.0, 1.0
+    * 
+    * @return The number of decimation levels.
+    */
+   virtual ossim_uint32 getNumberOfDecimationLevels()const;
+
+   /**
+    * @return Returns the image geometry object associated with this tile
+    * source or NULL if non defined.  The geometry contains full-to-local image
+    * transform as well as projection (image-to-world).
+    */
+   virtual ossimRefPtr<ossimImageGeometry> getImageGeometry();
+   
+   /**
+    * @param Method to get geometry from the embedded JP2 GeoTIFF Box.
+    */
+   virtual ossimRefPtr<ossimImageGeometry> getInternalImageGeometry();
+   
+protected:
+
+   /**
+    *  @brief open method.
+    *  @return true on success, false on error.
+    */
+   virtual bool open();
+
+private:
+
+   bool initImageParams();
+
+   /** @brief Allocates m_tile.  Called on first getTile. */
+   void allocate();
+
+   /**
+    * @note this method assumes that setImageRectangle has been called on
+    * theTile.
+    */
+   void fillTile( ossim_uint32 resLevel,
+                  const ossimIrect& tileRect,
+                  const ossimIrect& clipRect,
+                  ossimImageData* tile );
+
+   ossimRefPtr<ossimImageData> getTile( ossim_uint32 resLevel,
+                                        ossimIpt index );
+
+   /**
+    * @brief Uncompresses png tile to m_cacheTile.
+    * @param tile Tile record.
+    * @param tileSize Size of tile.
+    */
+   ossimRefPtr<ossimImageData> uncompressPngTile( const ossimGpkgTileRecord& tile,
+                                                  const ossimIpt& tileSize );
+
+   void getTileIndexes( ossim_uint32 resLevel,
+                        const ossimIrect& clipRect,
+                        std::vector<ossimIpt>& tileIndexes ) const;
+
+   void getTileSize( ossim_uint32 resLevel, ossimIpt& tileSize ) const;
+
+   /** @return Number of internal zoom levels. */
+   ossim_uint32 getNumberOfZoomLevels() const;
+
+   void computeGsd( ossimDpt& gsd) const;
+
+   ossimRefPtr<ossimImageHandler> m_ih;
+   
+   ossimRefPtr<ossimImageData> m_tile;
+   ossimRefPtr<ossimImageData> m_cacheTile;
+   // std::ifstream               m_str;
+   sqlite3*                    m_db;
+   ossim_uint32                m_currentEntry;
+   ossim_uint32                m_bands;
+   ossimScalarType             m_scalar;
+   ossim_uint32                m_tileWidth;
+   ossim_uint32                m_tileHeight;
+   
+   std::vector<ossimGpkgTileEntry> m_entries;
+
+   mutable ossimRefPtr<ossimCodecBase> m_jpegCodec;
+   mutable ossimRefPtr<ossimCodecBase> m_pngCodec;
+
+TYPE_DATA
+};
+
+#endif 
+
diff --git a/ossim_plugins/sqlite/ossimGpkgSpatialRefSysRecord.cpp b/ossim_plugins/sqlite/ossimGpkgSpatialRefSysRecord.cpp
new file mode 100644
index 0000000..8798940
--- /dev/null
+++ b/ossim_plugins/sqlite/ossimGpkgSpatialRefSysRecord.cpp
@@ -0,0 +1,468 @@
+//----------------------------------------------------------------------------
+//
+// File: ossimGpkgSpatialRefSysRecord.cpp
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Description: Container class for gpkg_spatial_ref_sys table.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include "ossimGpkgSpatialRefSysRecord.h"
+#include "ossimSqliteUtil.h"
+
+#include <ossim/base/ossimGpt.h>
+#include <ossim/base/ossimKeywordlist.h>
+#include <ossim/base/ossimNotify.h>
+#include <ossim/base/ossimTrace.h>
+
+#include <ossim/projection/ossimEquDistCylProjection.h>
+#include <ossim/projection/ossimGoogleProjection.h>
+#include <ossim/projection/ossimMapProjection.h>
+#include <ossim/projection/ossimUtmProjection.h>
+
+#include <sqlite3.h>
+
+#include <sstream>
+
+//---
+// For trace debugging. To enable at runtime do:
+// your_app -T "ossimGpkgSpatialRefSysRecord:debug" your_app_args
+//---
+static ossimTrace traceDebug("ossimGpkgSpatialRefSysRecord:debug");
+
+static std::string TABLE_NAME = "gpkg_spatial_ref_sys";
+
+ossimGpkgSpatialRefSysRecord::ossimGpkgSpatialRefSysRecord()
+   :
+   ossimGpkgDatabaseRecordBase(),
+   m_srs_name(),
+   m_srs_id(0),
+   m_organization(),
+   m_organization_coordsys_id(0),
+   m_definition(),
+   m_description()
+{
+}
+
+ossimGpkgSpatialRefSysRecord::ossimGpkgSpatialRefSysRecord(const ossimGpkgSpatialRefSysRecord& obj)
+   :
+   ossimGpkgDatabaseRecordBase(), 
+   m_srs_name(obj.m_srs_name),
+   m_srs_id(obj.m_srs_id),
+   m_organization(obj.m_organization),
+   m_organization_coordsys_id(obj.m_organization_coordsys_id),
+   m_definition(obj.m_definition),
+   m_description(obj.m_description)
+{
+}
+
+const ossimGpkgSpatialRefSysRecord& ossimGpkgSpatialRefSysRecord::operator=(
+   const ossimGpkgSpatialRefSysRecord& obj)
+{
+   if ( this != &obj )
+   {
+      m_srs_name = obj.m_srs_name;
+      m_srs_id = obj.m_srs_id;
+      m_organization = obj.m_organization;
+      m_organization_coordsys_id = obj.m_organization_coordsys_id;
+      m_definition = obj.m_definition;
+      m_description = obj.m_description;
+   }
+   return *this;
+}
+
+ossimGpkgSpatialRefSysRecord::~ossimGpkgSpatialRefSysRecord()
+{
+}
+
+const std::string& ossimGpkgSpatialRefSysRecord::getTableName()
+{
+   return TABLE_NAME;
+}
+
+bool ossimGpkgSpatialRefSysRecord::init( sqlite3_stmt* pStmt )
+{
+   static const char M[] = "ossimGpkgSpatialRefSysRecord::init(pStmt)";
+   
+   bool status = false;
+
+   if ( pStmt )
+   {
+      const ossim_int32 EXPECTED_COLUMNS = 6;
+      ossim_int32 nCol = sqlite3_column_count( pStmt );
+
+      if ( nCol != EXPECTED_COLUMNS )
+      {
+         ossimNotify(ossimNotifyLevel_WARN)
+            << M << " WARNING:\nUnexpected number of columns: " << nCol
+            << "Expected column count: " << EXPECTED_COLUMNS
+            << std::endl;
+      }
+      
+      if ( nCol >= EXPECTED_COLUMNS )
+      {
+         ossim_int32 columnsFound = 0;
+         std::string colName;
+         const char* c = 0; // To catch null so not to pass to string.
+
+         for ( ossim_int32 i = 0; i < nCol; ++i )
+         {
+            colName = sqlite3_column_name(pStmt, i);
+            if ( colName.size() )
+            {
+               if ( colName == "srs_name" )
+               {
+                  c = (const char*)sqlite3_column_text(pStmt, i);
+                  m_srs_name = (c ? c : "");
+                  ++columnsFound;
+               }
+               else if ( colName == "srs_id" )
+               {
+                  m_srs_id = sqlite3_column_int(pStmt, i);
+                  ++columnsFound;
+               }
+               else if ( colName == "organization" )
+               {
+                  c = (const char*)sqlite3_column_text(pStmt, i);
+                  m_organization = (c ? c : "");
+                  ++columnsFound;
+               }
+               else if ( colName == "organization_coordsys_id" )
+               {
+                  m_organization_coordsys_id = sqlite3_column_int(pStmt, i);
+                  ++columnsFound;
+               }
+               else if ( colName == "definition" )
+               {
+                  c = (const char*)sqlite3_column_text(pStmt, i);
+                  m_definition = (c ? c : "");
+                  ++columnsFound;
+               }
+               else if ( colName == "description" )
+               {
+                  c = (const char*)sqlite3_column_text(pStmt, i);
+                  m_description = (c ? c : "" );
+                  ++columnsFound;
+               }               
+               else
+               {
+                  ossimNotify(ossimNotifyLevel_WARN)
+                     << M << " Unhandled column name[" << i << "]: "
+                     << colName << std::endl;
+               }
+               
+            } // Matches: if ( colName.size() )
+            
+            if ( columnsFound == EXPECTED_COLUMNS )
+            {
+               status = true;
+               break;
+            }
+            
+         } // Matches: for ( int i = 0; i < nCol; ++i )  
+      }
+      
+   } // Matches: if ( pStmt )
+   
+   return status;
+   
+} // End: ossimGpkgSpatialRefSysRecord::init( pStmt )
+
+ossimGpkgSpatialRefSysRecord::InitCode
+ossimGpkgSpatialRefSysRecord::init( sqlite3* db, const ossimMapProjection* proj )
+{
+   //---
+   // Data taken from document:
+   // National System for Geospatial-Intelligence (NSG) GeoPackage Encoding
+   // Standard 1.0 Implementation Interoperability Standard (2014-10-29)
+   //---
+   ossimGpkgSpatialRefSysRecord::InitCode initCode = ossimGpkgSpatialRefSysRecord::ERROR;
+   
+   static const char M[] = "ossimGpkgSpatialRefSysRecord::init(proj)";
+
+   if ( db && proj )
+   {
+      ossim_int32 pcsCode   = (ossim_int32)proj->getPcsCode();
+      
+      if ( pcsCode == 4326 )
+      {
+         m_srs_name = "WGS 84 Geographic 2D lat/lon";
+         m_definition = "GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563,AUTHORITY[\"EPSG\",\"7030\"]],AUTHORITY[\"EPSG\",\"6326\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.01745329251994328,AUTHORITY[\"EPSG\",\"9122\"]],AUTHORITY[\"EPSG\",\"4326\"]]";
+         m_organization = "EPSG";
+         m_organization_coordsys_id = 4326;
+         m_description = "Horizontal component of 3D system. Used by the GPS satellite navigation system and for NATO military geodetic surveying.";
+
+         initCode = ossimGpkgSpatialRefSysRecord::OK;
+      }
+      else if ( pcsCode == 3395 )
+      {
+         m_srs_name = "WGS 84 / World Mercator";
+         m_definition = "PROJCS[\"WGS 84 / World Mercator\",GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563,AUTHORITY[\"EPSG\",\"7030\"]],AUTHORITY[\"EPSG\",\"6326\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.01745329251994328,AUTHORITY[\"EPSG\",\"9122\"]],AUTHORITY[\"EPSG\",\"4326\"]],UNIT[\"metre\",1,AUTHORITY[\"EPSG\",\"9001\"]],PROJECTION[\"Mercator_1SP\"],PARAMETER[\"central_meridian\",0],PARAMETER[\"scale_factor\",1],PARA [...]
+         m_organization = "EPSG";
+         m_organization_coordsys_id = 3395;
+         m_description = "Mercator (1SP)";
+
+         initCode = ossimGpkgSpatialRefSysRecord::OK;
+      }
+      else if ( pcsCode == 3857 )
+      {
+         m_srs_name = "WGS 84 / Pseudo-Mercator"; // ???
+         m_definition = "PROJCS[\"WGS 84 / Pseudo-Mercator\",GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563,AUTHORITY[\"EPSG\",\"7030\"]],AUTHORITY[\"EPSG\",\"6326\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9122\"]],AUTHORITY[\"EPSG\",\"4326\"]],PROJECTION[\"Mercator_1SP\"],PARAMETER[\"central_meridian\",0],PARAMETER[\"scale_factor\",1],PARAMETER[\"false_easting\",0],PARAMETER[\"false_no [...]
+         m_organization = "EPSG";
+         m_organization_coordsys_id = 3857;
+         m_description = "Google Projection"; // ?
+         
+         initCode = ossimGpkgSpatialRefSysRecord::OK;
+      }
+      else
+      {
+         ossimString projName = proj->getClassName();
+         ossimString datumCode = proj->getDatum()->code();
+         
+         if ( projName == "ossimUtmProjection" )
+         {
+            if ( datumCode == "WGE" )
+            {
+               const ossimUtmProjection* utmProj =
+                  dynamic_cast<const ossimUtmProjection*>( proj );
+               if ( utmProj )
+               {
+                  ossimGpt origin = proj->origin();
+                  ossimString centralMeridian = ossimString::toString( origin.lond() );
+                  ossimString zone = ossimString::toString( utmProj->getZone() );
+                  char hemisphere = utmProj->getHemisphere();
+                  
+                  m_srs_name = "WGS 84 / UTM zone ";
+                  m_srs_name += zone.string();
+                  if ( hemisphere == 'N' )
+                  {
+                     m_srs_name += "north";
+                  }
+                  else
+                  {
+                     m_srs_name += "south";
+                  }
+                  
+                  m_definition = "PROJCS[\"WGS 84 / UTM zone ";
+                  m_definition += zone.string();
+                  m_definition += hemisphere;
+                  m_definition += "\",GEOGCS[\"WGS 84\",DATUM[\"World Geodetic System_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563,AUTHORITY[\"EPSG\",\"7030\"]],AUTHORITY[\"EPSG\",\"6326\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9122\"]],AUTHORITY[\"EPSG\",\"4326\"]],PROJECTION[\"Transverse Mercator\",AUTHORITY[\"EPSG\",\"9807\"]],PARAMETER[\"Latitude of natural origin\",0],PARAMETER[\"Longitude of natural origin\",";
+                  m_definition += centralMeridian.string();
+                  m_definition += "],PARAMETER[\"scale_factor\",0.9996],PARAMETER[\"false_easting\",500000],PARAMETER[\"false_northing\",";
+                  if ( hemisphere == 'N' )
+                  {
+                     m_definition += "0";
+                  }
+                  else
+                  {
+                     m_definition += "10000000";
+                  }
+                  m_definition += "],UNIT[\"metre\",1,AUTHORITY[\"EPSG\",\"9001\"]],AXIS[\"Easting\",EAST],AXIS[\"Northing\",AUTHORITY[\"EPSG\",\"";
+                  m_definition += ossimString::toString(pcsCode).string();
+                  m_definition += "\"]]";
+                  
+                  m_organization = "EPSG";
+                  m_organization_coordsys_id = pcsCode;
+                  m_description = "Large and medium scale topographic mapping and engineering survey.";
+                  initCode = ossimGpkgSpatialRefSysRecord::OK;
+               }
+               
+            } // Matches: if ( datumCode == "WGE" )
+
+            if ( initCode == ossimGpkgSpatialRefSysRecord::ERROR )
+            {
+               ossimNotify(ossimNotifyLevel_WARN)
+                  << M
+                  << "\nUnhandled projection: " << proj->getClassName()
+                  << "\n datum: " << proj->getDatum()->code() << std::endl;
+            } 
+            
+         } // Matches: if ( projName == "ossimUtmProjection" )
+      }
+
+      if ( initCode == ossimGpkgSpatialRefSysRecord::OK )
+      {
+         m_srs_id = getSrsId( db );
+         if ( m_srs_id != -1 )
+         {
+            // Record was found in database.
+            initCode = ossimGpkgSpatialRefSysRecord::OK_EXISTS;
+         }
+         else
+         {
+            m_srs_id = getNextSrsId( db );
+         }
+      }
+      
+   } // Matches: if ( proj )
+
+   return initCode;
+   
+} // End: ossimGpkgSpatialRefSysRecord::init( proj )
+
+bool ossimGpkgSpatialRefSysRecord::createTable( sqlite3* db )
+{
+   bool status = false;
+   if ( db )
+   {
+      status = ossim_sqlite::tableExists( db, TABLE_NAME );
+
+      if ( !status )
+      {
+         std::ostringstream sql;
+         sql << "CREATE TABLE " << TABLE_NAME << " ( "
+             << "srs_name TEXT NOT NULL, "
+             << "srs_id INTEGER NOT NULL PRIMARY KEY, "
+             << "organization TEXT NOT NULL, "
+             << "organization_coordsys_id INTEGER NOT NULL, "
+             << "definition  TEXT NOT NULL, "
+             << "description TEXT )";
+         
+         if ( ossim_sqlite::exec( db, sql.str() ) == SQLITE_DONE )
+         {
+            // Requirement 11: Create the three required record entries.
+            ossimGpkgSpatialRefSysRecord record;
+            record.m_srs_id = -1;
+            record.m_organization = "NONE";
+            record.m_organization_coordsys_id = -1;
+            record.m_definition = "undefined";
+            
+            if ( record.insert( db ) )
+            {
+               record.m_srs_id = 0;
+               record.m_organization_coordsys_id = 0;
+               
+               if ( record.insert( db ) )
+               {
+                  record.m_srs_id = 1;
+                  record.m_srs_name = "WGS 84 Geographic 2D lat/lon";
+                  record.m_definition = "GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563,AUTHORITY[\"EPSG\",\"7030\"]],AUTHORITY[\"EPSG\",\"6326\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.01745329251994328,AUTHORITY[\"EPSG\",\"9122\"]],AUTHORITY[\"EPSG\",\"4326\"]]";
+                  record.m_organization = "EPSG";
+                  record.m_organization_coordsys_id = 4326;
+                  record.m_description = "Horizontal component of 3D system. Used by the GPS satellite navigation system and for NATO military geodetic surveying.";
+                  
+                  status = record.insert( db );
+               }
+            }
+         }
+      }
+   }
+   
+   return status;
+   
+} // End: ossimGpkgSpatialRefSysRecord::createTable( sqlite3* db )
+
+bool ossimGpkgSpatialRefSysRecord::insert( sqlite3* db )
+{
+   bool status = false;
+   if ( db )
+   {
+      std::ostringstream sql;
+      sql << "INSERT INTO gpkg_spatial_ref_sys VALUES ( "
+          << "'" << m_srs_name << "', "
+          << m_srs_id << ", "
+          << "'" << m_organization << "', "
+          << m_organization_coordsys_id << ", '"
+          << m_definition << "', '"
+          << m_description << "' )";
+
+      if ( ossim_sqlite::exec( db, sql.str() ) == SQLITE_DONE )
+      {
+         status = true;
+      }
+   }
+   return status;
+}
+
+void ossimGpkgSpatialRefSysRecord::saveState( ossimKeywordlist& kwl,
+                                              const std::string& prefix ) const
+{
+   std::string myPref = prefix.size() ? prefix : std::string("gpkg_spatial_ref_sys.");
+   std::string value;
+   
+   std::string key = "srs_name";
+   kwl.addPair(myPref, key, m_srs_name, true);
+
+   key = "srs_id";
+   value = ossimString::toString(m_srs_id).string();
+   kwl.addPair(myPref, key, value, true);
+
+   key = "organization";
+   kwl.addPair(myPref, key, m_organization, true);
+   
+   key = "oganization_coordsys_id";
+   value = ossimString::toString(m_organization_coordsys_id).string();
+   kwl.addPair( myPref, key, value, true);
+
+   key = "definition";
+   kwl.addPair(myPref, key, m_definition, true);
+
+   key = "description";
+   kwl.addPair(myPref, key, m_description, true);
+}
+
+ossim_int32 ossimGpkgSpatialRefSysRecord::getSrsId( sqlite3* db )
+{
+   ossim_int32 result = -1;
+   if ( db )
+   {
+      std::ostringstream sql;
+      sql << "SELECT srs_id FROM gpkg_spatial_ref_sys WHERE organization == '"
+          << m_organization
+          << "' AND organization_coordsys_id == "
+          << m_organization_coordsys_id;
+      
+      const char *zLeftover;                         // Tail of unprocessed SQL
+      sqlite3_stmt *pStmt = 0;                       // The current SQL statement
+      int rc = sqlite3_prepare_v2(db,                // Database handle
+                                  sql.str().c_str(), // SQL statement, UTF-8 encoded
+                                  -1,                // Maximum length of zSql in bytes.
+                                  &pStmt,            // OUT: Statement handle
+                                  &zLeftover);       // OUT: Pointer to unused portion of zSql
+      if ( rc == SQLITE_OK )
+      {
+         // Read the row:
+         rc = sqlite3_step(pStmt);
+         if ( rc == SQLITE_ROW )
+         {
+            result = sqlite3_column_int(pStmt, 0);
+         }
+      }
+      sqlite3_finalize(pStmt);
+   }
+   return result;
+}
+
+ossim_int32 ossimGpkgSpatialRefSysRecord::getNextSrsId( sqlite3* db )
+{
+   ossim_int32 result = 2; // -1, 0, and 1 are created by create table...
+   if ( db )
+   {
+      std::string sql = "SELECT srs_id FROM gpkg_spatial_ref_sys ORDER BY srs_id DESC LIMIT 1";
+
+      const char *zLeftover;                   // Tail of unprocessed SQL
+      sqlite3_stmt *pStmt = 0;                 // The current SQL statement
+      int rc = sqlite3_prepare_v2(db,          // Database handle
+                                  sql.c_str(), // SQL statement, UTF-8 encoded
+                                  -1,          // Maximum length of zSql in bytes.
+                                  &pStmt,      // OUT: Statement handle
+                                  &zLeftover); // OUT: Pointer to unused portion of zSql
+      if ( rc == SQLITE_OK )
+      {
+         // Read the row:
+         rc = sqlite3_step(pStmt);
+         if ( rc == SQLITE_ROW )
+         {
+            result  = sqlite3_column_int(pStmt, 0);
+            ++result;
+         }
+      }
+      sqlite3_finalize(pStmt);
+   }
+   return result;
+}
+
diff --git a/ossim_plugins/sqlite/ossimGpkgSpatialRefSysRecord.h b/ossim_plugins/sqlite/ossimGpkgSpatialRefSysRecord.h
new file mode 100644
index 0000000..8ad10c1
--- /dev/null
+++ b/ossim_plugins/sqlite/ossimGpkgSpatialRefSysRecord.h
@@ -0,0 +1,112 @@
+//----------------------------------------------------------------------------
+//
+// File: ossimGpkgSpatialRefSysRecord.h
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Description: Container class for gpkg_spatial_ref_sys table.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef ossimGpkgSpatialRefSysRecord_HEADER
+#define ossimGpkgSpatialRefSysRecord_HEADER 1
+
+#include "ossimGpkgDatabaseRecordBase.h"
+#include <ossim/base/ossimConstants.h>
+
+class ossimMapProjection;
+struct sqlite3;
+
+class ossimGpkgSpatialRefSysRecord : public ossimGpkgDatabaseRecordBase
+{
+public:
+
+   enum InitCode
+   {
+      ERROR     = -1, // Something bad...
+      OK_EXISTS =  0, // Initialized and entry exist in database.
+      OK        =  1  // Initialized but not in database yet.
+   };
+
+   /** @brief default constructor */
+   ossimGpkgSpatialRefSysRecord();
+
+   /* @brief copy constructor */
+   ossimGpkgSpatialRefSysRecord(const ossimGpkgSpatialRefSysRecord& obj);
+
+   /* @brief assignment operator= */
+   const ossimGpkgSpatialRefSysRecord& operator=(const ossimGpkgSpatialRefSysRecord& obj);
+
+   /** @brief destructor */
+   virtual ~ossimGpkgSpatialRefSysRecord();
+
+   /**
+    * @brief Get the table name "gpkg_spatial_ref_sys".
+    * @return table name
+    */
+   static const std::string& getTableName();
+
+   /**
+    * @brief Initialize from database.
+    * @param pStmt SQL statement, i.e. result of sqlite3_prepare_v2(...) call.
+    * @return true on success, false on error.
+    */
+   virtual bool init( sqlite3_stmt* pStmt );
+
+   /**
+    * @brief Initialize from projection.
+    * @param db
+    * @param proj Output map projection.
+    * @return init code.
+    * @see ossimGpkgSpatialRefSysRecordInitCode enumeration for more.
+    */
+   InitCode init( sqlite3* db, const ossimMapProjection* proj );
+
+   /**
+    * @brief Creates gpkg_contents table in database.
+    * @param db
+    * @return true on success, false on error.
+    */   
+   static bool createTable( sqlite3* db );
+
+   /**
+    * @brief Inserst this record into gpkg_contents table.
+    * @param db
+    * @return true on success, false on error.
+    */   
+   bool insert( sqlite3* db );   
+
+   /**
+    * @brief Saves the state of object.
+    * @param kwl Initialized by this.
+    * @param prefix e.g. "image0.". Can be empty.
+    */
+   virtual void saveState( ossimKeywordlist& kwl, const std::string& prefix ) const;
+
+   /**
+    * @brief Looks in database for matching record and returns the id if found.
+    * @param db
+    * @return srs_id if found; else, -1.
+    */
+   ossim_int32 getSrsId( sqlite3* db );
+
+   /**
+    * @brief Looks in database for matching record and returns the id if found.
+    * @param db
+    * @return srs_id if found; else, -1.
+    */
+   ossim_int32 getNextSrsId( sqlite3* db );
+
+   std::string   m_srs_name;
+   ossim_int32   m_srs_id;
+   std::string   m_organization;
+   ossim_int32   m_organization_coordsys_id;
+   std::string   m_definition;
+   std::string   m_description;
+};
+
+#endif /* #ifndef ossimGpkgSpatialRefSysRecord_HEADER */
+
diff --git a/ossim_plugins/sqlite/ossimGpkgTileEntry.cpp b/ossim_plugins/sqlite/ossimGpkgTileEntry.cpp
new file mode 100644
index 0000000..6ddb48c
--- /dev/null
+++ b/ossim_plugins/sqlite/ossimGpkgTileEntry.cpp
@@ -0,0 +1,435 @@
+//----------------------------------------------------------------------------
+//
+// File: ossimGpkgTileEntry.cpp
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Description: Container class for GeoPackage tile entry.
+//
+// Holds a gpkg_tile_matrix_set and a vector of gpkg_tile_matrix.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include "ossimGpkgTileEntry.h"
+
+#include <ossim/base/ossimDpt.h>
+#include <ossim/base/ossimIpt.h>
+#include <ossim/base/ossimKeywordlist.h>
+#include <ossim/base/ossimString.h>
+
+#include <ossim/projection/ossimEpsgProjectionFactory.h>
+#include <ossim/projection/ossimEquDistCylProjection.h>
+#include <ossim/projection/ossimGoogleProjection.h>
+#include <ossim/projection/ossimMapProjection.h>
+#include <ossim/projection/ossimProjection.h>
+
+#include <algorithm> /* for std::sort */
+#include <iomanip>
+#include <ostream>
+
+static bool tileMatrixSort( const ossimGpkgTileMatrixRecord& i,
+                            const ossimGpkgTileMatrixRecord& j )
+{
+   // This is backwards, want the highest zoom level should be at lowest index.
+   return ( i.m_zoom_level > j.m_zoom_level );
+}
+
+static bool tileMatrixExtentSort(
+   const ossimGpkgNsgTileMatrixExtentRecord& i,
+   const ossimGpkgNsgTileMatrixExtentRecord& j )
+{
+   // This is backwards, want the highest zoom level should be at lowest index.
+   return ( i.m_zoom_level > j.m_zoom_level );
+}
+
+ossimGpkgTileEntry::ossimGpkgTileEntry()
+   :
+   m_srs(),
+   m_tileMatrixSet(),
+   m_tileMatrix(0),
+   m_tileMatrixExtents(0)
+{
+}
+
+ossimGpkgTileEntry::ossimGpkgTileEntry(const ossimGpkgTileEntry& obj)
+   :
+   m_srs(obj.m_srs),
+   m_tileMatrixSet(obj.m_tileMatrixSet),
+   m_tileMatrix(obj.m_tileMatrix),
+   m_tileMatrixExtents(obj.m_tileMatrixExtents)
+{  
+}
+
+const ossimGpkgTileEntry& ossimGpkgTileEntry::operator=(const ossimGpkgTileEntry& obj)
+{
+   if ( this != &obj )
+   {
+      m_srs = obj.m_srs;
+      m_tileMatrixSet = obj.m_tileMatrixSet;
+      m_tileMatrix = obj.m_tileMatrix;
+      m_tileMatrixExtents = obj.m_tileMatrixExtents;
+   }
+   return *this;
+}
+
+ossimGpkgTileEntry::~ossimGpkgTileEntry()
+{
+}
+
+void ossimGpkgTileEntry::setTileMatrixSet(const ossimGpkgTileMatrixSetRecord& set)
+{
+   m_tileMatrixSet = set;
+}
+
+const ossimGpkgTileMatrixSetRecord& ossimGpkgTileEntry::getTileMatrixSet() const
+{
+   return m_tileMatrixSet;
+}
+
+void ossimGpkgTileEntry::setSrs( const ossimGpkgSpatialRefSysRecord& srs )
+{
+   m_srs = srs;
+}
+
+const ossimGpkgSpatialRefSysRecord& ossimGpkgTileEntry::getSrs() const
+{
+   return m_srs;
+}
+
+void ossimGpkgTileEntry::addTileMatrix(const ossimGpkgTileMatrixRecord& level)
+{
+   m_tileMatrix.push_back( level );
+}
+
+const std::vector<ossimGpkgTileMatrixRecord>& ossimGpkgTileEntry::getTileMatrix() const
+{
+   return m_tileMatrix;
+}
+
+void ossimGpkgTileEntry::addTileMatrixExtent(const ossimGpkgNsgTileMatrixExtentRecord& record)
+{
+   m_tileMatrixExtents.push_back( record );
+}
+
+const std::vector<ossimGpkgNsgTileMatrixExtentRecord>&
+ossimGpkgTileEntry::getTileMatrixExtent() const
+{
+   return m_tileMatrixExtents;
+}
+
+void ossimGpkgTileEntry::sortTileMatrix()
+{
+   std::sort(m_tileMatrix.begin(), m_tileMatrix.end(), tileMatrixSort);
+}
+
+void ossimGpkgTileEntry::sortTileMatrixExtents()
+{
+   std::sort(m_tileMatrixExtents.begin(),
+             m_tileMatrixExtents.end(),
+             tileMatrixExtentSort);
+}
+
+void ossimGpkgTileEntry::saveState( ossimKeywordlist& kwl,
+                                    const std::string& prefix ) const
+{
+   m_srs.saveState( kwl, prefix );
+   m_tileMatrixSet.saveState( kwl, prefix );
+   std::string myPrefix = prefix;
+   myPrefix += "gpkg_tile_matrix";
+   for ( ossim_uint32 i = 0; i < (ossim_uint32)m_tileMatrix.size(); ++i )
+   {
+      std::string p = myPrefix;
+      p += ossimString::toString(i).string();
+      p += ".";
+      m_tileMatrix[i].saveState( kwl, p );
+   }
+}
+
+std::ostream& ossimGpkgTileEntry::print(std::ostream& out) const
+{
+   ossimKeywordlist kwl;
+   saveState(kwl, std::string(""));
+   out << kwl;
+   return out;
+}
+
+std::ostream& ossimGpkgTileEntry::printValidate(std::ostream& out) const
+{
+   m_tileMatrixSet.print( out );
+   
+   // Capture the original flags.
+   std::ios_base::fmtflags f = out.flags();  
+
+   // Set the new precision capturing old.
+   std::streamsize oldPrecision = out.precision(15);
+
+   ossim_float64 w = m_tileMatrixSet.getWidth();
+   ossim_float64 h =  m_tileMatrixSet.getHeight();
+
+   out << setiosflags(ios::fixed)
+       << "gpkg_tile_matrix_set.width:                " << w << "\n"
+       << "gpkg_tile_matrix_set.height:               " << h << "\n";
+   
+      
+   for ( ossim_uint32 i = 0; i < (ossim_uint32)m_tileMatrix.size(); ++i )
+   {
+      ossim_float64 computedX =
+         w / m_tileMatrix[i].m_matrix_width / m_tileMatrix[i].m_tile_width;
+      ossim_float64 computedY =
+         h / m_tileMatrix[i].m_matrix_height / m_tileMatrix[i].m_tile_height;
+       
+      cout << "gpkg_tile_matrix[" << i << "].zoom_level:            "
+           << m_tileMatrix[i].m_zoom_level
+           << "\ngpkg_tile_matrix[" << i << "].pixel_x_size:          "
+           << m_tileMatrix[i].m_pixel_x_size
+           << "\ngpkg_tile_matrix[" << i << "].pixel_x_size_computed: "
+           << computedX
+           << "\ngpkg_tile_matrix[" << i << "].pixel_x_size_delta:    "
+           << m_tileMatrix[i].m_pixel_x_size - computedX
+           << "\ngpkg_tile_matrix[" << i << "].pixel_y_size:          "
+           << m_tileMatrix[i].m_pixel_y_size
+           << "\ngpkg_tile_matrix[" << i << "].pixel_y_size_computed: "
+           << computedY
+           << "\ngpkg_tile_matrix[" << i << "].pixel_y_size_delta:    "
+           << m_tileMatrix[i].m_pixel_y_size - computedY
+           << "\n";
+   }
+
+   // Reset flags and precision.
+   out.setf(f);
+   out.precision(oldPrecision);
+
+   return out;
+}
+   
+std::ostream& operator<<(std::ostream& out,
+                         const ossimGpkgTileEntry& obj)
+{
+   return obj.print( out );
+}
+
+ossim_uint32 ossimGpkgTileEntry::getNumberOfLines( ossim_uint32 resLevel ) const
+{
+   ossim_uint32 result = 0;
+
+   if ( resLevel < m_tileMatrix.size() )
+   {
+      // m_tileMatrixExtents may or may not be there.
+      if ( ( resLevel < m_tileMatrixExtents.size() ) &&
+           ( m_tileMatrixExtents[resLevel].m_zoom_level == m_tileMatrix[resLevel].m_zoom_level ) )
+      {
+         result = m_tileMatrixExtents[resLevel].m_max_row -
+            m_tileMatrixExtents[resLevel].m_min_row + 1;
+      }
+      else
+      {
+         ossim_float64 lines =
+            ( m_tileMatrixSet.m_max_y - m_tileMatrixSet.m_min_y ) /
+            m_tileMatrix[resLevel].m_pixel_y_size;
+         if ( lines > 0.0 )
+         {
+            result = (ossim_uint32)(lines + 0.5);
+         }
+      }
+   }
+   
+   return result;
+}
+
+ossim_uint32 ossimGpkgTileEntry::getNumberOfSamples( ossim_uint32 resLevel ) const
+{
+   ossim_uint32 result = 0;
+
+   if ( resLevel < m_tileMatrix.size() )
+   {
+      // m_tileMatrixExtents may or may not be there.
+      if ( ( resLevel < m_tileMatrixExtents.size() ) &&
+           ( m_tileMatrixExtents[resLevel].m_zoom_level == m_tileMatrix[resLevel].m_zoom_level ) )
+      {
+         result = m_tileMatrixExtents[resLevel].m_max_column -
+            m_tileMatrixExtents[resLevel].m_min_column + 1;
+      }
+      else
+      {    
+         ossim_float64 samples =
+            ( m_tileMatrixSet.m_max_x - m_tileMatrixSet.m_min_x ) /
+            m_tileMatrix[resLevel].m_pixel_x_size;
+         if ( samples > 0.0 )
+         {
+            result = (ossim_uint32)(samples + 0.5);
+         }
+      }
+   }
+   
+   return result;
+}
+
+void ossimGpkgTileEntry::getSubImageOffset( ossim_uint32 resLevel, ossimIpt& offset ) const
+{
+   // m_tileMatrixExtents may or may not be there.
+   if ( ( resLevel < m_tileMatrix.size() ) &&
+        ( resLevel < m_tileMatrixExtents.size() ) &&
+        ( m_tileMatrixExtents[resLevel].m_zoom_level == m_tileMatrix[resLevel].m_zoom_level ) )
+   {
+      offset.x = m_tileMatrixExtents[resLevel].m_min_column;
+      offset.y = m_tileMatrixExtents[resLevel].m_min_row;
+   }
+   else
+   {
+      offset.x = 0;
+      offset.y = 0;
+   }
+}
+
+void ossimGpkgTileEntry::getTiePoint( ossimDpt& tie ) const
+{
+   // m_tileMatrixExtents may or may not be there.
+   if ( m_tileMatrix.size() && m_tileMatrixExtents.size() &&
+        ( m_tileMatrixExtents[0].m_zoom_level == m_tileMatrix[0].m_zoom_level ) )
+   {
+      tie.x = m_tileMatrixExtents[0].m_min_x;
+      tie.y = m_tileMatrixExtents[0].m_max_y;
+   }
+   else
+   {
+      tie.x = m_tileMatrixSet.m_min_x;
+      tie.y = m_tileMatrixSet.m_max_y;
+   }
+}
+
+void ossimGpkgTileEntry::getGsd( ossim_uint32 index, ossimDpt& gsd ) const
+{
+   if ( index < m_tileMatrix.size() )
+   {
+      gsd.x = m_tileMatrix[index].m_pixel_x_size;
+      gsd.y = m_tileMatrix[index].m_pixel_y_size;
+   }
+   else
+   {
+      gsd.makeNan();
+   }
+}
+
+void ossimGpkgTileEntry::getZoomLevels( std::vector<ossim_int32>& zoomLevels ) const
+{
+   zoomLevels.clear();
+   std::vector<ossimGpkgTileMatrixRecord>::const_iterator i = m_tileMatrix.begin();
+   while ( i != m_tileMatrix.end() )
+   {
+      zoomLevels.push_back( (*i).m_zoom_level );
+      ++i;
+   }
+}
+
+void ossimGpkgTileEntry::getZoomLevelMatrixSizes(
+   std::vector<ossimIpt>& zoomLevelMatrixSizes ) const
+{
+   zoomLevelMatrixSizes.clear();
+   std::vector<ossimGpkgTileMatrixRecord>::const_iterator i = m_tileMatrix.begin();
+   while ( i != m_tileMatrix.end() )
+   {
+      zoomLevelMatrixSizes.push_back( ossimIpt((*i).m_matrix_width, (*i).m_matrix_height) );
+      ++i;
+   }
+}
+
+ossimRefPtr<ossimMapProjection> ossimGpkgTileEntry::getNewMapProjection() const
+{
+   ossimRefPtr<ossimMapProjection> mapProj = 0;
+
+   if ( m_tileMatrix.size() )
+   {
+      // Must have code, and scale to continue:
+      if ( m_srs.m_organization_coordsys_id &&
+           m_tileMatrix[0].m_pixel_x_size &&
+           m_tileMatrix[0].m_pixel_y_size )
+      {
+         std::string org = ossimString(m_srs.m_organization).upcase().string();
+         
+         if ( org == "EPSG" )
+         {
+            ossim_uint32 code = (ossim_uint32)m_srs.m_organization_coordsys_id;
+            
+            ossimDpt gsd;
+            getGsd( 0, gsd );
+            
+            // Avoid factory call for two most common projections.
+            if ( code == 4326 )
+            {
+               // Geographic, WGS 84
+               
+               //---
+               // ossimEquDistCylProjection uses the origin_latitude for meters per pixel
+               // (gsd) computation. Compute to achieve the proper horizontal sccaling.
+               //---
+               ossimGpt origin(0.0, 0.0);
+               ossim_float64 tmpDbl = ossim::acosd(gsd.y/gsd.x);
+               if ( !ossim::isnan(tmpDbl) )
+               {
+                  origin.lat = tmpDbl;
+               }
+               mapProj = new ossimEquDistCylProjection(ossimEllipsoid(), origin);
+            }
+            else if ( ( code == 3857 ) || ( code == 900913) )
+            {
+               mapProj = new ossimGoogleProjection();
+            }
+            else
+            {
+               ossimString name = "EPSG:";
+               name += ossimString::toString(code);
+               ossimRefPtr<ossimProjection> proj =
+                  ossimEpsgProjectionFactory::instance()->createProjection(name);
+               if ( proj.valid() )
+               {
+                  mapProj = dynamic_cast<ossimMapProjection*>( proj.get() );
+               }
+            }
+            
+            if ( mapProj.valid() )
+            {
+               //---
+               // Set the tie and scale.  NOTE the tie is center of the upper left
+               // pixel; hence, the half pixel shif.
+               //---
+               ossimDpt tie;
+               getTiePoint( tie );
+               
+               if ( mapProj->isGeographic() )
+               {
+                  mapProj->setDecimalDegreesPerPixel(gsd);
+                  
+                  // Tie latitude, longitude:
+                  ossimGpt tiePoint( tie.y, tie.x );
+                  ossimDpt half_pixel_shift = gsd * 0.5;
+                  tiePoint.lat -= half_pixel_shift.lat;
+                  tiePoint.lon += half_pixel_shift.lon;
+                  
+                  mapProj->setUlTiePoints(tiePoint);
+               }
+               else
+               {
+                  mapProj->setMetersPerPixel(gsd);
+                  
+                  // Tie Easting Northing:
+                  ossimDpt half_pixel_shift = gsd * 0.5;
+                  tie.y -= half_pixel_shift.y;
+                  tie.x += half_pixel_shift.x;
+            
+                  mapProj->setUlTiePoints(tie);
+               }
+            }
+      
+         } // Matches: if ( org == "epsg" )
+         
+      } // Matches: if ( m_srs.m_organization_coordsys_id && ...
+      
+   } // Matches: if ( m_tileMatrix.size() )
+
+   return mapProj;
+   
+} // End: ossimGpkgTileEntry::getNewMapProjection()
+
diff --git a/ossim_plugins/sqlite/ossimGpkgTileEntry.h b/ossim_plugins/sqlite/ossimGpkgTileEntry.h
new file mode 100644
index 0000000..8d9a570
--- /dev/null
+++ b/ossim_plugins/sqlite/ossimGpkgTileEntry.h
@@ -0,0 +1,183 @@
+//----------------------------------------------------------------------------
+//
+// File: ossimGpkgTileEntry.h
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Description: Container class for GeoPackage tile entry.
+//
+// Holds a gpkg_tile_matrix_set and a vector of gpkg_tile_matrix.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef ossimGpkgTileEntry_HEADER
+#define ossimonGpkgTileEntry_HEADER 1
+
+#include "ossimGpkgSpatialRefSysRecord.h"
+#include "ossimGpkgTileMatrixRecord.h"
+#include "ossimGpkgTileMatrixSetRecord.h"
+#include "ossimGpkgNsgTileMatrixExtentRecord.h"
+
+#include <ossim/base/ossimRefPtr.h>
+
+#include <iosfwd>
+#include <vector>
+
+class ossimDpt;
+class ossimIpt;
+class ossimKeywordlist;
+class ossimMapProjection;
+
+class ossimGpkgTileEntry
+{
+public:
+   
+   /** @brief default constructor */
+   ossimGpkgTileEntry();
+
+   /* @brief copy constructor */
+   ossimGpkgTileEntry(const ossimGpkgTileEntry& obj);
+
+   /* @brief assignment operator= */
+   const ossimGpkgTileEntry& operator=
+      (const ossimGpkgTileEntry& obj);
+
+   /** @brief destructor */
+   ~ossimGpkgTileEntry();
+
+   /**
+    * @brief Sets the tile matrix set.
+    * @param set
+    */
+   void setTileMatrixSet(const ossimGpkgTileMatrixSetRecord& set);
+
+   /** @return tile matrix set. */
+   const ossimGpkgTileMatrixSetRecord& getTileMatrixSet() const;
+
+   /**
+    * @brief Sets the spatial ref sys.
+    * @param srs
+    */
+   void setSrs( const ossimGpkgSpatialRefSysRecord& srs );
+
+   /** @retrurn Spatial ref sys. */
+   const ossimGpkgSpatialRefSysRecord& getSrs() const;
+
+   /**
+    * @brief Adds a tile matrix level to array.
+    * @param level Level to add.
+    */
+   void addTileMatrix(const ossimGpkgTileMatrixRecord& level);
+
+   /** @return const reference to the tile matrix. */
+   const std::vector<ossimGpkgTileMatrixRecord>& getTileMatrix() const;
+
+   /**
+    * @brief Adds a tile matrix extent level to array.
+    * @param level Level to add.
+    */
+   void addTileMatrixExtent(const ossimGpkgNsgTileMatrixExtentRecord& record);
+
+   /** @return const reference to the tile matrix extent. */
+   const std::vector<ossimGpkgNsgTileMatrixExtentRecord>&
+      getTileMatrixExtent() const;
+
+   /**
+    * @brief Sorts the m_tileMatrix by zoom levels with the highest
+    * zoom level being at the lowest array index.
+    *
+    * The highest zoom level is the best resolution in ossim.  In
+    * other words if zoom level 21 is highest zoom level this is
+    * equal to r0 (reduced resolution 0.
+    */
+   void sortTileMatrix();
+
+   /**
+    * @brief Sorts the m_tileMatrixExtents by zoom levels with the highest
+    * zoom level being at the lowest array index.
+    *
+    * The highest zoom level is the best resolution in ossim.  In
+    * other words if zoom level 21 is highest zoom level this is
+    * equal to r0 (reduced resolution 0.
+    */
+   void sortTileMatrixExtents();
+
+   /**
+    * @brief Saves the state of object.
+    * @param kwl Initialized by this.
+    * @param prefix e.g. "image0.". Can be empty.
+    */
+   void saveState( ossimKeywordlist& kwl,
+                   const std::string& prefix ) const;
+
+   ossim_uint32 getNumberOfLines( ossim_uint32 resLevel ) const;
+   ossim_uint32 getNumberOfSamples( ossim_uint32 resLevel ) const;
+   void getSubImageOffset( ossim_uint32 resLevel, ossimIpt& offset ) const;
+
+   /**
+    * @brief Gets the tie point from the first tile matrix extents if initialized
+    * else from the tile matrix extents.
+    */
+   void getTiePoint( ossimDpt& offset ) const;
+
+   /**
+    * @brief Gets the gsd from tile matrix.
+    * @param index to tile matrix array.
+    * @param gsd Initialized by this. Will be nan if matrix is empty.
+    */
+   void getGsd( ossim_uint32 index, ossimDpt& gsd ) const;
+
+   /**
+    * @brief Gets zoom levels of all tile matrixes.
+    *
+    * @param zoomLevels Intitialized by this.
+    */
+   void getZoomLevels( std::vector<ossim_int32>& zoomLevels ) const;
+
+   /**
+    * @brief Gets zoom level matrix of all tile matrixes.
+    *
+    * @param zoomLevelMatrixSizes Intitialized by this.
+    */
+   void getZoomLevelMatrixSizes( std::vector<ossimIpt>& zoomLevelMatrixSizes ) const;
+
+   /**
+    * @brief Gets the map projection to include setting the tie and scale.
+    * @return Map projection.  Result will be null if matrix is not intialized.
+    */
+   ossimRefPtr<ossimMapProjection> getNewMapProjection() const;
+   
+   /**
+    * @brief Print method.
+    * @param out Stream to print to.
+    * @return Stream reference.
+    */
+   std::ostream& print(std::ostream& out) const;
+
+   /**
+    * @brief Validate method.  Prints data from database and computed values.
+    * @param out Stream to print to.
+    * @return Stream reference.
+    */
+   std::ostream& printValidate(std::ostream& out) const;
+   
+   /**
+    * @brief Convenience operator << function.
+    * @param out Stream to print to.
+    * @param obj Object to print.
+    */
+   friend std::ostream& operator<<(std::ostream& out,
+                                   const ossimGpkgTileEntry& obj);
+   
+private:
+   ossimGpkgSpatialRefSysRecord m_srs;
+   ossimGpkgTileMatrixSetRecord m_tileMatrixSet;
+   std::vector<ossimGpkgTileMatrixRecord> m_tileMatrix;
+   std::vector<ossimGpkgNsgTileMatrixExtentRecord> m_tileMatrixExtents;   
+};
+
+#endif /* #ifndef ossimGpkgTileEntry_HEADER */
+
diff --git a/ossim_plugins/sqlite/ossimGpkgTileMatrixRecord.cpp b/ossim_plugins/sqlite/ossimGpkgTileMatrixRecord.cpp
new file mode 100644
index 0000000..bb9bfd9
--- /dev/null
+++ b/ossim_plugins/sqlite/ossimGpkgTileMatrixRecord.cpp
@@ -0,0 +1,313 @@
+//----------------------------------------------------------------------------
+//
+// File: ossimGpkgTileMatrixRecord.cpp
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Description: Container class for gpkg_tile_matrix table.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include "ossimGpkgTileMatrixRecord.h"
+#include "ossimSqliteUtil.h"
+#include <ossim/base/ossimCommon.h>
+#include <ossim/base/ossimDpt.h>
+#include <ossim/base/ossimIpt.h>
+#include <ossim/base/ossimKeywordlist.h>
+#include <ossim/base/ossimNotify.h>
+#include <sqlite3.h>
+#include <iomanip>
+
+static const std::string TABLE_NAME = "gpkg_tile_matrix";
+
+ossimGpkgTileMatrixRecord::ossimGpkgTileMatrixRecord()
+   :
+   ossimGpkgDatabaseRecordBase(),   
+   m_table_name(),
+   m_zoom_level(0),
+   m_matrix_width(0),
+   m_matrix_height(0),   
+   m_tile_width(0),
+   m_tile_height(0),   
+   m_pixel_x_size(ossim::nan()),
+   m_pixel_y_size(ossim::nan())
+{
+}
+
+ossimGpkgTileMatrixRecord::ossimGpkgTileMatrixRecord(const ossimGpkgTileMatrixRecord& obj)
+   :
+   ossimGpkgDatabaseRecordBase(),
+   m_table_name(obj.m_table_name),
+   m_zoom_level(obj.m_zoom_level),
+   m_matrix_width(obj.m_matrix_width),
+   m_matrix_height(obj.m_matrix_height),
+   m_tile_width(obj.m_tile_width),
+   m_tile_height(obj.m_tile_height),   
+   m_pixel_x_size(obj.m_pixel_x_size),
+   m_pixel_y_size(obj.m_pixel_y_size)
+{
+}
+
+const ossimGpkgTileMatrixRecord& ossimGpkgTileMatrixRecord::operator=(
+   const ossimGpkgTileMatrixRecord& obj)
+{
+   if ( this != &obj )
+   {
+      m_table_name = obj.m_table_name;
+      m_zoom_level = obj.m_zoom_level;
+      m_matrix_width = obj.m_matrix_width;
+      m_matrix_height = obj.m_matrix_height;
+      m_tile_width = obj.m_tile_width;
+      m_tile_height = obj.m_tile_height;   
+      m_pixel_x_size = obj.m_pixel_x_size;
+      m_pixel_y_size = obj.m_pixel_y_size;
+   }
+   return *this;
+}
+
+bool ossimGpkgTileMatrixRecord::init( const std::string& tableName,
+                                      ossim_int32 zoom_level,
+                                      const ossimIpt& matrixSize,
+                                      const ossimIpt& tileSize,
+                                      const ossimDpt& gsd )
+{
+   bool status = false;
+
+   if ( (matrixSize.hasNans() == false) && (tileSize.hasNans() == false) &&
+        (gsd.hasNans() == false) )
+   {
+      m_table_name    = tableName;
+      m_zoom_level    = zoom_level;
+      m_matrix_width  = matrixSize.x;
+      m_matrix_height = matrixSize.y;
+      m_tile_width    = tileSize.x;
+      m_tile_height   = tileSize.y;
+      m_pixel_x_size  = gsd.x;
+      m_pixel_y_size  = gsd.y;
+      status = true;
+   }
+   
+   return status;
+   
+} // End: ossimGpkgTileMatrixRecord::init( zoom_level, ... )
+
+bool ossimGpkgTileMatrixRecord::createTable( sqlite3* db )
+{
+   bool status = false;
+   if ( db )
+   {
+      status = ossim_sqlite::tableExists( db, TABLE_NAME );
+      if ( !status )
+      {
+         std::ostringstream sql;
+         sql << "CREATE TABLE " << TABLE_NAME << " ( "      
+             << "table_name TEXT NOT NULL, "
+             << "zoom_level INTEGER NOT NULL, "
+             << "matrix_width INTEGER NOT NULL, "
+             << "matrix_height INTEGER NOT NULL, "
+             << "tile_width INTEGER NOT NULL, "
+             << "tile_height INTEGER NOT NULL, "
+             << "pixel_x_size DOUBLE NOT NULL, "
+             << "pixel_y_size DOUBLE NOT NULL, "
+             << "CONSTRAINT pk_ttm PRIMARY KEY (table_name, zoom_level), "
+             << "CONSTRAINT fk_tmm_table_name FOREIGN KEY (table_name) REFERENCES gpkg_contents(table_name) "
+             << ")";
+         
+         if ( ossim_sqlite::exec( db, sql.str() ) == SQLITE_DONE )
+         {
+            status = true;
+         }
+      }
+   }
+   return status;
+}
+
+bool ossimGpkgTileMatrixRecord::insert( sqlite3* db )
+{
+   bool status = false;
+   if ( db )
+   {
+      std::ostringstream sql;
+      sql << "INSERT INTO gpkg_tile_matrix VALUES ( "
+          <<  "'" << m_table_name << "', "
+          << m_zoom_level << ", "
+          << m_matrix_width <<  ", "
+          << m_matrix_height << ", "
+          << m_tile_width << ", "
+          << m_tile_height << ", "
+          << std::setiosflags(std::ios::fixed) << std::setprecision(16)
+          << m_pixel_x_size << ", "
+          << m_pixel_y_size
+          << " )";
+
+      if ( ossim_sqlite::exec( db, sql.str() ) == SQLITE_DONE )
+      {
+         status = true;
+      }    
+   }
+   return status;
+}
+
+ossimGpkgTileMatrixRecord::~ossimGpkgTileMatrixRecord()
+{
+}
+
+const std::string& ossimGpkgTileMatrixRecord::getTableName()
+{
+   return TABLE_NAME;
+}
+
+bool ossimGpkgTileMatrixRecord::init( sqlite3_stmt* pStmt )
+{
+   static const char M[] = "ossimGpkgTileMatrixRecord::init";
+   
+   bool status = false;
+   
+   if ( pStmt )
+   {
+      const ossim_int32 EXPECTED_COLUMNS = 8;
+      ossim_int32 nCol = sqlite3_column_count( pStmt );
+
+      if ( nCol != EXPECTED_COLUMNS )
+      {
+         ossimNotify(ossimNotifyLevel_WARN)
+            << M << " WARNING:\nUnexpected number of columns: " << nCol
+            << "Expected column count: " << EXPECTED_COLUMNS
+            << std::endl;
+      }
+      
+      if ( nCol >= EXPECTED_COLUMNS )
+      {
+         ossim_int32 columnsFound = 0;
+         std::string colName;
+         const char* c = 0; // To catch null so not to pass to string.
+         
+         for ( ossim_int32 i = 0; i < nCol; ++i )
+         {
+            colName = sqlite3_column_name(pStmt, i);
+            if ( colName.size() )
+            {
+               if ( colName == "table_name" )
+               {
+                  c = (const char*)sqlite3_column_text(pStmt, i);
+                  m_table_name = (c ? c : "");
+                  ++columnsFound;
+               }
+               else if ( colName == "zoom_level" )
+               {
+                  m_zoom_level = sqlite3_column_int(pStmt, i);
+                  ++columnsFound;
+               }
+               else if ( colName == "matrix_width" )
+               {
+                  m_matrix_width = sqlite3_column_int(pStmt, i);
+                  ++columnsFound;
+               }
+               else if ( colName == "matrix_height" )
+               {
+                  m_matrix_height = sqlite3_column_int(pStmt, i);
+                  ++columnsFound;
+               }
+               else if ( colName == "tile_width" )
+               {
+                  m_tile_width = sqlite3_column_int(pStmt, i);
+                  ++columnsFound;
+               }
+               else if ( colName == "tile_height" )
+               {
+                  m_tile_height = sqlite3_column_int(pStmt, i);
+                  ++columnsFound;
+               }
+               else if ( colName == "pixel_x_size" )
+               {
+                  m_pixel_x_size = sqlite3_column_double(pStmt, i);
+                  ++columnsFound;
+               }
+               else if ( colName == "pixel_y_size" )
+               {
+                  m_pixel_y_size = sqlite3_column_double(pStmt, i);
+                  ++columnsFound;
+               }
+               else
+               {
+                  ossimNotify(ossimNotifyLevel_WARN)
+                     << M << " Unhandled column name["
+                     << i << "]: " << colName << std::endl;
+               }
+            
+            } // Matches: if ( colName.size() )
+         
+            if ( columnsFound == EXPECTED_COLUMNS )
+            {
+               status = true;
+               break;
+            }
+         
+         } // Matches: for ( int i = 0; i < nCol; ++i )  
+      }
+   
+   } // Matches: if ( pStmt )
+   
+   return status;
+   
+} // End: ossimGpkgTileMatrixRecord::init( sqlite3_stmt* pStmt )
+
+void ossimGpkgTileMatrixRecord::saveState( ossimKeywordlist& kwl,
+                                           const std::string& prefix ) const
+{
+   std::string myPref = prefix.size() ? prefix : std::string("gpkg_tile_matrix.");
+   std::string value;
+   
+   std::string key = "table_name";
+   kwl.addPair(myPref, key, m_table_name, true);
+
+   key = "zoom_level";
+   value = ossimString::toString(m_zoom_level).string();
+   kwl.addPair(myPref, key, value, true);
+
+   key = "matrix_width";
+   value = ossimString::toString(m_matrix_width).string();
+   kwl.addPair(myPref, key, value, true);
+
+   key = "matrix_height";
+   value = ossimString::toString(m_matrix_height).string();
+   kwl.addPair(myPref, key, value, true);
+
+   key = "tile_width";
+   value = ossimString::toString(m_tile_width).string();
+   kwl.addPair(myPref, key, value, true);
+
+   key = "tile_height";
+   value = ossimString::toString(m_tile_height).string();
+   kwl.addPair(myPref, key, value, true);
+
+   key = "pixel_x_size";
+   value = ossimString::toString(m_pixel_x_size, 15, true).string();
+   kwl.addPair(myPref, key, value, true);
+
+   key = "pixel_y_size";
+   value = ossimString::toString(m_pixel_y_size, 15, true).string();
+   kwl.addPair(myPref, key, value, true);
+}
+
+void ossimGpkgTileMatrixRecord::getMatrixSize( ossimIpt& size ) const
+{
+   size.x = m_matrix_width;
+   size.y = m_matrix_height;
+}
+
+void ossimGpkgTileMatrixRecord::getTileSize( ossimIpt& size ) const
+{
+   size.x = m_tile_width;
+   size.y = m_tile_height;
+}
+
+void ossimGpkgTileMatrixRecord::getGsd( ossimDpt& gsd ) const
+{
+   gsd.x = m_pixel_x_size;
+   gsd.y = m_pixel_y_size;
+}
+
diff --git a/ossim_plugins/sqlite/ossimGpkgTileMatrixRecord.h b/ossim_plugins/sqlite/ossimGpkgTileMatrixRecord.h
new file mode 100644
index 0000000..3d21751
--- /dev/null
+++ b/ossim_plugins/sqlite/ossimGpkgTileMatrixRecord.h
@@ -0,0 +1,119 @@
+//----------------------------------------------------------------------------
+//
+// File: ossimGpkgTileMatrixRecord.h
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Description: Container class for gpkg_tile_matrix table.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef ossimGpkgTileMatrixRecord_HEADER
+#define ossimGpkgTileMatrixRecord_HEADER 1
+
+#include "ossimGpkgDatabaseRecordBase.h"
+#include <ossim/base/ossimConstants.h>
+
+class ossimDpt;
+class ossimIpt;
+struct sqlite3;
+
+class ossimGpkgTileMatrixRecord : public ossimGpkgDatabaseRecordBase
+{
+public:
+
+   /** @brief default constructor */
+   ossimGpkgTileMatrixRecord();
+
+   /* @brief copy constructor */
+   ossimGpkgTileMatrixRecord(const ossimGpkgTileMatrixRecord& obj);
+
+   /* @brief assignment operator= */
+   const ossimGpkgTileMatrixRecord& operator=
+      (const ossimGpkgTileMatrixRecord& obj);
+
+   /** @brief destructor */
+   virtual ~ossimGpkgTileMatrixRecord();
+
+   /**
+    * @brief Get the table name "gpkg_tile_matrix".
+    * @return table name
+    */
+   static const std::string& getTableName();
+   
+   /**
+    * @brief Initialize from database.
+    * @param pStmt SQL statement, i.e. result of sqlite3_prepare_v2(...) call.
+    */
+   virtual bool init( sqlite3_stmt* pStmt );
+   
+   /**
+    * @brief Initialize method.
+    * @param tableName e.g. "tiles"
+    * @param Zoom level.  Zero being whole Earth...
+    * @param matrixSize Size of tile matrix, i.e. number of horizontal
+    * vertical tiles.
+    * @param tileSize Size of one tile, e.g. 256 x 256.
+    * @param gsd Size of one pixel either in meters or lat lon.
+    * @return true on success, false on error.
+    */
+   bool init( const std::string& tableName,
+              ossim_int32 zoom_level,
+              const ossimIpt& matrixSize,
+              const ossimIpt& tileSize,
+              const ossimDpt& gsd );
+   
+   /**
+    * @brief Creates  table in database.
+    * @param db
+    * @return true on success, false on error.
+    */   
+   static bool createTable( sqlite3* db );
+
+   /**
+    * @brief Inserst this record into gpkg_spatial_ref_sys table.
+    * @param db
+    * @return true on success, false on error.
+    */   
+   bool insert( sqlite3* db );
+   
+   /**
+    * @brief Saves the state of object.
+    * @param kwl Initialized by this.
+    * @param prefix e.g. "image0.". Can be empty.
+    */
+   virtual void saveState( ossimKeywordlist& kwl,
+                           const std::string& prefix ) const;
+
+   /**
+    * @brief Get matrix size. 
+    * @param size Initialized with matrix_width and matrix_height.
+    */
+   void getMatrixSize( ossimIpt& size ) const;
+
+   /**
+    * @brief Get tile size.
+    * @param size Initializes with tile_width and tile_height.
+    */
+   void getTileSize( ossimIpt& size ) const; 
+
+   /**
+    * @brief Get gsd.
+    * @param gsd Initializes with pixel_x_size and pixel_y_size. */
+   void getGsd( ossimDpt& gsd ) const;
+   
+   std::string   m_table_name;
+   ossim_int32   m_zoom_level;
+   ossim_int32   m_matrix_width;
+   ossim_int32   m_matrix_height;   
+   ossim_int32   m_tile_width;
+   ossim_int32   m_tile_height;   
+   ossim_float64 m_pixel_x_size;
+   ossim_float64 m_pixel_y_size;
+};
+
+#endif /* #ifndef ossimGpkgTileMatrixRecord_HEADER */
+
diff --git a/ossim_plugins/sqlite/ossimGpkgTileMatrixSetRecord.cpp b/ossim_plugins/sqlite/ossimGpkgTileMatrixSetRecord.cpp
new file mode 100644
index 0000000..e48b5a9
--- /dev/null
+++ b/ossim_plugins/sqlite/ossimGpkgTileMatrixSetRecord.cpp
@@ -0,0 +1,274 @@
+//----------------------------------------------------------------------------
+//
+// File: ossimGpkgTileMatrixSetRecord.cpp
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Description: Container class for gpkg_tile_matrix_set table.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include "ossimGpkgTileMatrixSetRecord.h"
+#include "ossimSqliteUtil.h"
+#include <ossim/base/ossimCommon.h>
+#include <ossim/base/ossimDpt.h>
+#include <ossim/base/ossimDrect.h>
+#include <ossim/base/ossimKeywordlist.h>
+#include <ossim/base/ossimNotify.h>
+#include <sqlite3.h>
+#include <iomanip>
+
+static const std::string TABLE_NAME = "gpkg_tile_matrix_set";
+
+ossimGpkgTileMatrixSetRecord::ossimGpkgTileMatrixSetRecord()
+   :
+   ossimGpkgDatabaseRecordBase(),   
+   m_table_name(),
+   m_srs_id(0),
+   m_min_x(ossim::nan()),
+   m_min_y(ossim::nan()),
+   m_max_x(ossim::nan()),
+   m_max_y(ossim::nan())
+{
+}
+
+ossimGpkgTileMatrixSetRecord::ossimGpkgTileMatrixSetRecord(const ossimGpkgTileMatrixSetRecord& obj)
+   :
+   ossimGpkgDatabaseRecordBase(),
+   m_table_name(obj.m_table_name),
+   m_srs_id(obj.m_srs_id),
+   m_min_x(obj.m_min_x),
+   m_min_y(obj.m_min_y),
+   m_max_x(obj.m_max_x),
+   m_max_y(obj.m_max_y)
+{
+}
+
+const ossimGpkgTileMatrixSetRecord& ossimGpkgTileMatrixSetRecord::operator=(
+   const ossimGpkgTileMatrixSetRecord& obj)
+{
+   if ( this != &obj )
+   {
+      m_table_name = obj.m_table_name;
+      m_srs_id = obj.m_srs_id;
+      m_min_x = obj.m_min_x;
+      m_min_y = obj.m_min_y;
+      m_max_x = obj.m_max_x;
+      m_max_y = obj.m_max_y;
+   }
+   return *this;
+}
+
+ossimGpkgTileMatrixSetRecord::~ossimGpkgTileMatrixSetRecord()
+{
+}
+
+const std::string& ossimGpkgTileMatrixSetRecord::getTableName()
+{
+   return TABLE_NAME;
+}
+
+bool ossimGpkgTileMatrixSetRecord::init( sqlite3_stmt* pStmt )
+{
+   static const char M[] = "ossimGpkgTileMatrixSetRecord::init";
+   
+   bool status = false;
+
+   if ( pStmt )
+   {
+      const ossim_int32 EXPECTED_COLUMNS = 6;
+      ossim_int32 nCol = sqlite3_column_count( pStmt );
+
+      if ( nCol != EXPECTED_COLUMNS )
+      {
+         ossimNotify(ossimNotifyLevel_WARN)
+            << M << " WARNING:\nUnexpected number of columns: " << nCol
+            << "Expected column count: " << EXPECTED_COLUMNS
+            << std::endl;
+      }
+      
+      if ( nCol >= EXPECTED_COLUMNS )
+      {
+         ossim_int32 columnsFound = 0;
+         std::string colName;
+         const char* c = 0; // To catch null so not to pass to string.
+
+         for ( ossim_int32 i = 0; i < nCol; ++i )
+         {
+            colName = sqlite3_column_name(pStmt, i);
+            if ( colName.size() )
+            {
+               if ( colName == "table_name" )
+               {
+                  c = (const char*)sqlite3_column_text(pStmt, i);
+                  m_table_name = (c ? c : "");
+                  ++columnsFound;
+               }
+               else if ( colName == "srs_id" )
+               {
+                  m_srs_id = sqlite3_column_int(pStmt, i);
+                  ++columnsFound;
+               }
+               else if ( colName == "min_x" )
+               {
+                  m_min_x = sqlite3_column_double(pStmt, i);
+                  ++columnsFound;
+               }
+               else if ( colName == "min_y" )
+               {
+                  m_min_y = sqlite3_column_double(pStmt, i);
+                  ++columnsFound;
+               }
+               else if ( colName == "max_x" )
+               {
+                  m_max_x = sqlite3_column_double(pStmt, i);
+                  ++columnsFound;
+               }
+               else if ( colName == "max_y" )
+               {
+                  m_max_y = sqlite3_column_double(pStmt, i);
+                  ++columnsFound;
+               }
+               else
+               {
+                  ossimNotify(ossimNotifyLevel_WARN)
+                     << M << " Unhandled column name["
+                     << i << "]: " << colName << std::endl;
+               }
+               
+            } // Matches: if ( colName.size() )
+            
+            if ( columnsFound == EXPECTED_COLUMNS )
+            {
+               status = true;
+               break;
+            }
+            
+         } // Matches: for ( int i = 0; i < nCol; ++i )  
+      }
+      
+   } // Matches: if ( pStmt )
+   
+   return status;
+   
+} // End:  ossimGpkgTileMatrixSetRecord::init( pStmt )
+
+bool ossimGpkgTileMatrixSetRecord::init(
+   const std::string& tableName,ossim_int32 srs_id,
+   const ossimDpt& minPt, const ossimDpt& maxPt )
+{
+   bool status = false;
+   if ( (minPt.hasNans() == false) && (maxPt.hasNans() == false) )
+   {
+      m_table_name = tableName;
+      m_srs_id = srs_id;
+      m_min_x  = minPt.x;
+      m_min_y  = minPt.y;
+      m_max_x  = maxPt.x;
+      m_max_y  = maxPt.y;
+      status   = true;
+   }
+   return status;
+}
+
+bool ossimGpkgTileMatrixSetRecord::createTable( sqlite3* db )
+{
+   bool status = false;
+   if ( db )
+   {
+      status = ossim_sqlite::tableExists( db, TABLE_NAME );
+      if ( !status )
+      {
+         std::ostringstream sql;
+         sql << "CREATE TABLE " << TABLE_NAME << " ( "  
+             << "table_name TEXT NOT NULL PRIMARY KEY, "
+             << "srs_id INTEGER NOT NULL, "
+             << "min_x DOUBLE NOT NULL, "
+             << "min_y DOUBLE NOT NULL, "
+             << "max_x DOUBLE NOT NULL, "
+             << "max_y DOUBLE NOT NULL, "
+             << "CONSTRAINT fk_gtms_table_name FOREIGN KEY (table_name) REFERENCES gpkg_contents(table_name), "
+             << "CONSTRAINT fk_gtms_srs FOREIGN KEY (srs_id) REFERENCES gpkg_spatial_ref_sys (srs_id) "
+             << ")";
+         
+         if ( ossim_sqlite::exec( db, sql.str() ) == SQLITE_DONE )
+         {
+            status = true;
+         }
+      }
+   }
+   return status;
+}
+
+bool ossimGpkgTileMatrixSetRecord::insert( sqlite3* db )
+{
+   bool status = false;
+   if ( db )
+   {
+      std::ostringstream sql;
+      sql << "INSERT INTO gpkg_tile_matrix_set VALUES ( "
+          <<  "'" << m_table_name << "', "
+          << m_srs_id << ", "
+          << std::setprecision(16)
+          << m_min_x << ", "
+          << m_min_y << ", " 
+          << m_max_x << ", "
+          << m_max_y
+          << " )";
+
+      if ( ossim_sqlite::exec( db, sql.str() ) == SQLITE_DONE )
+      {
+         status = true;
+      }    
+   }
+   return status;
+}
+
+void ossimGpkgTileMatrixSetRecord::getRect( ossimDrect& rect ) const
+{
+   rect = ossimDrect( m_min_x, m_max_y, m_max_x, m_min_y, OSSIM_RIGHT_HANDED );
+}
+
+ossim_float64 ossimGpkgTileMatrixSetRecord::getWidth() const
+{
+   return m_max_x - m_min_x;
+}
+
+ossim_float64 ossimGpkgTileMatrixSetRecord::getHeight() const
+{
+   return m_max_y - m_min_y;
+}
+
+void ossimGpkgTileMatrixSetRecord::saveState( ossimKeywordlist& kwl,
+                                              const std::string& prefix ) const
+{
+   std::string myPref = prefix.size() ? prefix : std::string("gpkg_tile_matrix_set.");
+   std::string value;
+   
+   std::string key = "table_name";
+   kwl.addPair(myPref, key, m_table_name, true);
+
+   key = "srs_id";
+   value = ossimString::toString(m_srs_id).string();
+   kwl.addPair(myPref, key, value, true);
+
+   key = "min_x";
+   value = ossimString::toString(m_min_x, 15).string();
+   kwl.addPair(myPref, key, value, true);
+
+   key = "min_y";
+   value = ossimString::toString(m_min_y, 15).string();
+   kwl.addPair(myPref, key, value, true);
+
+   key = "max_x";
+   value = ossimString::toString(m_max_x, 15).string();
+   kwl.addPair(myPref, key, value, true);
+
+   key = "max_y";
+   value = ossimString::toString(m_max_y, 15).string();
+   kwl.addPair(myPref, key, value, true);
+}
+
diff --git a/ossim_plugins/sqlite/ossimGpkgTileMatrixSetRecord.h b/ossim_plugins/sqlite/ossimGpkgTileMatrixSetRecord.h
new file mode 100644
index 0000000..06d33c9
--- /dev/null
+++ b/ossim_plugins/sqlite/ossimGpkgTileMatrixSetRecord.h
@@ -0,0 +1,110 @@
+//----------------------------------------------------------------------------
+//
+// File: ossimGpkgTileMatrixSetRecord.h
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Description: Container class for gpkg_tile_matrix_set table.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef ossimGpkgTileMatrixSetRecord_HEADER
+#define ossimGpkgTileMatrixSetRecord_HEADER 1
+
+#include "ossimGpkgDatabaseRecordBase.h"
+#include <ossim/base/ossimConstants.h>
+
+class ossimDpt;
+class ossimDrect;
+struct sqlite3;
+
+class ossimGpkgTileMatrixSetRecord : public ossimGpkgDatabaseRecordBase
+{
+public:
+
+   /** @brief default constructor */
+   ossimGpkgTileMatrixSetRecord();
+
+   /* @brief copy constructor */
+   ossimGpkgTileMatrixSetRecord(const ossimGpkgTileMatrixSetRecord& obj);
+
+   /* @brief assignment operator= */
+   const ossimGpkgTileMatrixSetRecord& operator=
+      (const ossimGpkgTileMatrixSetRecord& obj);
+
+   /** @brief destructor */
+   virtual ~ossimGpkgTileMatrixSetRecord();
+
+   /**
+    * @brief Get the table name "gpkg_tile_matrix_set".
+    * @return table name
+    */
+   static const std::string& getTableName();
+
+   /**
+    * @brief Initialize from database.
+    * @param pStmt SQL statement, i.e. result of sqlite3_prepare_v2(...) call.
+    */
+   virtual bool init( sqlite3_stmt* pStmt );
+
+   /**
+    * @brief Initialize from projection.
+    * @param tableName e.g. "tiles"
+    * @param srs_id ID of gpkg_spatial_ref_sys record our projection is
+    * relative to.
+    * @param minPt Minimum bounds in either Easting Northin or lat lon.
+    * @param maxPt Maximum bounds in either Easting Northin or lat lon.
+    * @return true on success, false on error.
+    */
+   bool init( const std::string& tableName,
+              ossim_int32 srs_id,
+              const ossimDpt& minPt,
+              const ossimDpt& maxPt );
+   
+   /**
+    * @brief Creates  table in database.
+    * @param db
+    * @return true on success, false on error.
+    */   
+   static bool createTable( sqlite3* db );
+
+   /**
+    * @brief Inserst this record into gpkg_spatial_ref_sys table.
+    * @param db
+    * @return true on success, false on error.
+    */   
+   bool insert( sqlite3* db );    
+
+   /**
+    * @brief Saves the state of object.
+    * @param kwl Initialized by this.
+    * @param prefix e.g. "image0.". Can be empty.
+    */
+   virtual void saveState( ossimKeywordlist& kwl,
+                           const std::string& prefix ) const;
+
+   /**
+    * @brief Gets the rectangle from bounds.
+    * @param rect Initialized by this.
+    */
+   void getRect( ossimDrect& rect ) const;
+
+   /** @return width */
+   ossim_float64 getWidth() const;
+
+   /** @return height */
+   ossim_float64 getHeight() const;
+   
+   std::string   m_table_name;
+   ossim_int32   m_srs_id;
+   ossim_float64 m_min_x;
+   ossim_float64 m_min_y;
+   ossim_float64 m_max_x;
+   ossim_float64 m_max_y;
+};
+
+#endif /* #ifndef ossimGpkgTileMatrixSetRecord_HEADER */
+
diff --git a/ossim_plugins/sqlite/ossimGpkgTileRecord.cpp b/ossim_plugins/sqlite/ossimGpkgTileRecord.cpp
new file mode 100644
index 0000000..8d8c14d
--- /dev/null
+++ b/ossim_plugins/sqlite/ossimGpkgTileRecord.cpp
@@ -0,0 +1,333 @@
+//----------------------------------------------------------------------------
+//
+// File: ossimGpkgTileRecord.cpp
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Description: Container class GeoPackage tile record.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include "ossimGpkgTileRecord.h"
+#include "ossimSqliteUtil.h"
+#include <ossim/base/ossimCommon.h>
+#include <ossim/base/ossimDpt.h>
+#include <ossim/base/ossimIpt.h>
+#include <ossim/base/ossimNotify.h>
+#include <sqlite3.h>
+#include <cstring> /* for memcpy */
+
+ossimGpkgTileRecord::ossimGpkgTileRecord()
+   :
+   m_id(0),
+   m_zoom_level(0),
+   m_tile_column(0),
+   m_tile_row(0),
+   m_tile_data(0),
+   m_copy_tile_flag(true)
+{
+}
+
+ossimGpkgTileRecord::ossimGpkgTileRecord(const ossimGpkgTileRecord& obj)
+   :
+   m_id(obj.m_id),
+   m_zoom_level(obj.m_zoom_level),
+   m_tile_column(obj.m_tile_column),
+   m_tile_row(obj.m_tile_row),
+   m_tile_data(obj.m_tile_data),
+   m_copy_tile_flag(obj.m_copy_tile_flag)
+{
+}
+
+const ossimGpkgTileRecord& ossimGpkgTileRecord::operator=(
+   const ossimGpkgTileRecord& obj)
+{
+   if ( this != &obj )
+   {
+      m_id = obj.m_id;
+      m_zoom_level = obj.m_zoom_level;
+      m_tile_column = obj.m_tile_column;
+      m_tile_row = obj.m_tile_row;
+      m_tile_data = obj.m_tile_data;
+      m_copy_tile_flag = obj.m_copy_tile_flag;
+   }
+   return *this;
+}
+
+ossimGpkgTileRecord::~ossimGpkgTileRecord()
+{
+}
+
+bool ossimGpkgTileRecord::init( sqlite3_stmt* pStmt )
+{
+   static const char M[] = "ossimGpkgTileRecord::init";
+   
+   bool status = false;
+
+   if ( pStmt )
+   {
+      const ossim_int32 EXPECTED_COLUMNS = 5;
+      ossim_int32 nCol = sqlite3_column_count( pStmt );
+      
+      if ( nCol != EXPECTED_COLUMNS )
+      {
+         ossimNotify(ossimNotifyLevel_WARN)
+            << M << " WARNING:\nUnexpected number of columns: " << nCol
+            << "Expected column count: " << EXPECTED_COLUMNS
+            << std::endl;
+      }
+      
+      if ( nCol >= EXPECTED_COLUMNS )
+      {
+         ossim_int32 columnsFound = 0;
+         ossim_int32 type = 0;
+         std::string colName;
+         
+         for ( ossim_int32 i = 0; i < nCol; ++i )
+         {
+            colName = sqlite3_column_name(pStmt, i);
+            type = sqlite3_column_type(pStmt, i);
+
+            if ( colName.size() )
+            {
+               if ( ( colName == "id" ) && ( type == SQLITE_INTEGER ) )
+               {
+                  m_id = sqlite3_column_int(pStmt, i);
+                  ++columnsFound;
+               }
+               else if ( ( colName == "zoom_level" ) && ( type == SQLITE_INTEGER ) )
+               {
+                  m_zoom_level = sqlite3_column_int(pStmt, i);
+                  ++columnsFound;
+               }
+               else if ( ( colName == "tile_column" ) && ( type == SQLITE_INTEGER ) )
+               {
+                  m_tile_column = sqlite3_column_int(pStmt, i);
+                  ++columnsFound;
+               }
+               else if ( ( colName == "tile_row" ) && ( type == SQLITE_INTEGER ) )
+               {
+                  m_tile_row = sqlite3_column_int(pStmt, i);
+                  ++columnsFound;
+               }
+               else if ( ( colName == "tile_data" ) && ( type == SQLITE_BLOB ) )
+               {
+                  ++columnsFound;
+
+                  if ( m_copy_tile_flag )
+                  {
+                     ossim_int32 bytes = sqlite3_column_bytes( pStmt, i );
+                     if ( bytes )
+                     {
+                        //---
+                        // Copy the tile data as it will go away on the next:
+                        // sqlite3_step(), sqlite3_reset() or sqlite3_finalize()
+                        //---
+                        m_tile_data.resize( bytes );
+                        std::memcpy( (void*)&m_tile_data.front(),
+                                     sqlite3_column_blob( pStmt, i ), bytes );
+                     }
+                  }
+               }
+               else
+               {
+                  ossimNotify(ossimNotifyLevel_WARN)
+                     << M << " Unexpected column type[" << i << "]: " << type << std::endl;
+                  break;
+               }
+            } // Matches: if ( colName.size() )
+            
+            if ( columnsFound == EXPECTED_COLUMNS )
+            {
+               status = true;
+               break;
+            }
+            
+         } // Matches: for ( int i = 0; i < nCol; ++i )  
+      }
+      
+   } // Matches: if ( pStmt )
+
+#if 0 /* Please leave for debug. (drb) */
+   static bool tracedTile = false;
+   if ( status && !tracedTile )
+   {
+      tracedTile = true;
+      std::ofstream os;
+      std::string file = "debug-tile.";
+      swith( getTileType() )
+      {
+         case OSSIM_GPKG_PNG:
+         {
+            file += "png";
+            break;
+         }
+         case OSSIM_GPKG_JPEG:
+         {
+            file += "jpg";
+            break;
+         }
+         default:
+            break;
+      }
+      
+      os.open( file.c_str(), ios::out | ios::binary);
+      if ( os.good() )
+      {
+         os.write( (char*)&m_tile_data.front(), m_tile_data.size() );
+      }
+      os.close();
+   }
+#endif
+   
+   return status;
+   
+} // End: ossimGpkgTileRecord::init( pStmt )
+
+bool ossimGpkgTileRecord::createTable( sqlite3* db, const std::string& tableName )
+{
+   bool status = false;
+   if ( db )
+   {
+      status = ossim_sqlite::tableExists( db, tableName );
+      if ( !status )
+      {
+         std::ostringstream sql;
+         sql << "CREATE TABLE " << tableName << " ( "
+             << "id INTEGER PRIMARY KEY AUTOINCREMENT, "
+             << "zoom_level INTEGER NOT NULL, "
+             << "tile_column INTEGER NOT NULL, "
+             << "tile_row INTEGER NOT NULL, "
+             << "tile_data BLOB NOT NULL, "
+             << "UNIQUE (zoom_level, tile_column, tile_row) "
+             << ")";
+         
+         if ( ossim_sqlite::exec( db, sql.str() ) == SQLITE_DONE )
+         {
+            status = true;
+         }
+      }
+   }
+   return status;
+}
+
+void ossimGpkgTileRecord::setCopyTileFlag( bool flag )
+{
+   m_copy_tile_flag = flag;
+}
+
+std::ostream& ossimGpkgTileRecord::print(std::ostream& out) const
+{
+   out << "id: " << m_id
+       << "\nzoom_level: " << m_zoom_level
+       << "\nm_tile_column: " << m_tile_column
+       << "\nm_tile_row: " << m_tile_row
+       << "\nsignature_block: ";
+   
+   // Signature block:
+   if ( m_tile_data.size() > 7 )
+   {
+      for ( int i = 0; i < 8; ++i )
+      {
+         out << std::hex << int(m_tile_data[i]) << " ";
+      }
+      out << std::dec;
+   }
+   else
+   {
+      out << "null";
+   }
+   out << "\nmedia_type: " << getTileMediaType() << std::endl;
+   
+   return out;
+}
+
+std::ostream& operator<<(std::ostream& out,
+                         const ossimGpkgTileRecord& obj)
+{
+   return obj.print( out );
+}
+
+void ossimGpkgTileRecord::getTileIndex( ossimIpt& index ) const
+{
+   index.x = m_tile_column;
+   index.y = m_tile_row;
+}
+
+ossimGpkgTileRecord::ossimGpkgTileType ossimGpkgTileRecord::getTileType() const
+{
+   ossimGpkgTileType result = ossimGpkgTileRecord::OSSIM_GPKG_UNKNOWN;
+
+   if ( m_tile_data.size() > 7 )
+   {
+      if ( (m_tile_data[0] == 0xff) &&
+           (m_tile_data[1] == 0xd8) &&
+           (m_tile_data[2] == 0xff) )
+      {
+         if ( (m_tile_data[3] == 0xe0) || (m_tile_data[3] == 0xdb) )
+         {
+            result = ossimGpkgTileRecord::OSSIM_GPKG_JPEG;
+         }
+      }
+      else if ( ( m_tile_data[0] == 0x89 ) &&
+                ( m_tile_data[1] == 0x50 ) &&
+                ( m_tile_data[2] == 0x4e ) &&
+                ( m_tile_data[3] == 0x47 ) &&
+                ( m_tile_data[4] == 0x0d ) &&
+                ( m_tile_data[5] == 0x0a ) &&
+                ( m_tile_data[6] == 0x1a ) &&
+                ( m_tile_data[7] == 0x0a ) )
+      {
+         result = ossimGpkgTileRecord::OSSIM_GPKG_PNG;
+      }
+
+#if 0 /* Please keep for debug. (drb) */
+      if ( result == ossimGpkgTileRecord::OSSIM_GPKG_UNKNOWN )
+      {
+         static bool traced = false;
+         if ( !traced )
+         {
+            if ( result == ossimGpkgTileRecord::OSSIM_GPKG_UNKNOWN )
+            {
+               for ( int i = 0; i < 8; ++i )
+               {
+                  std::cout << std::hex << int(m_tile_data[i]) << " ";
+               }
+               std::cout << std::dec << "\n";
+               traced = true;
+            }
+         }
+      }
+#endif
+   }
+
+   return result;   
+}
+
+std::string ossimGpkgTileRecord::getTileMediaType() const
+{
+   std::string result;
+   switch ( getTileType() )
+   {
+      case ossimGpkgTileRecord::OSSIM_GPKG_JPEG:
+      {
+         result = "image/jpeg";
+         break;
+      }
+      case ossimGpkgTileRecord::OSSIM_GPKG_PNG:
+      {
+         result = "image/png";
+         break;
+      }
+      default:
+      {
+         result = "unknown";
+         break;
+      }
+   }
+   return result;
+}
+
diff --git a/ossim_plugins/sqlite/ossimGpkgTileRecord.h b/ossim_plugins/sqlite/ossimGpkgTileRecord.h
new file mode 100644
index 0000000..930a4ba
--- /dev/null
+++ b/ossim_plugins/sqlite/ossimGpkgTileRecord.h
@@ -0,0 +1,104 @@
+//----------------------------------------------------------------------------
+//
+// File: ossimGpkgTileRecord.h
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Description: Container class for GeoPackage tile record.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef ossimGpkgTileRecord_HEADER
+#define ossimonGpkgTileRecord_HEADER 1
+
+#include <ossim/base/ossimConstants.h>
+#include <iosfwd>
+#include <vector>
+
+class ossimIpt;
+struct sqlite3_stmt;
+struct sqlite3;
+
+class ossimGpkgTileRecord
+{
+public:
+
+   enum ossimGpkgTileType
+   {
+      OSSIM_GPKG_UNKNOWN = 0,
+      OSSIM_GPKG_JPEG    = 1,
+      OSSIM_GPKG_PNG     = 2
+   };
+
+   /** @brief default constructor */
+   ossimGpkgTileRecord();
+
+   /* @brief copy constructor */
+   ossimGpkgTileRecord(const ossimGpkgTileRecord& obj);
+
+   /* @brief assignment operator= */
+   const ossimGpkgTileRecord& operator=
+      (const ossimGpkgTileRecord& obj);
+
+   /** @brief destructor */
+   ~ossimGpkgTileRecord();
+
+   /**
+    * @brief Initialize from database.
+    * @param pStmt SQL statement, i.e. result of sqlite3_prepare_v2(...) call. 
+    */
+   bool init( sqlite3_stmt* pStmt );
+
+   /**
+    * @brief Creates  table in database.
+    * @param db
+    * @param tableName e.g. "tiles", "map_tiles"
+    * @return true on success, false on error.
+    */   
+   static bool createTable( sqlite3* db, const std::string& tableName );  
+
+   void setCopyTileFlag( bool flag );
+
+   /**
+    * @brief Print method.
+    *
+    * Does not print the image blob.
+    * 
+    * @param out Stream to print to.
+    * @return Stream reference.
+    */
+   std::ostream& print(std::ostream& out) const;
+   
+   /**
+    * @brief Convenience operator << function.
+    * @param out Stream to print to.
+    * @param obj Object to print.
+    */
+   friend std::ostream& operator<<(std::ostream& out,
+                                   const ossimGpkgTileRecord& obj);
+
+   /**
+    * @brief Get tile index.
+    * @param size Initializes with tile_column and tile_row.
+    */
+   void getTileIndex( ossimIpt& index ) const;
+
+   /** @return Tile type from signature block. */
+   ossimGpkgTileType getTileType() const;
+
+   /** @return Tile media type from signature block. e.g. "image/png" */
+   std::string getTileMediaType() const;
+
+   ossim_int32 m_id;
+   ossim_int32 m_zoom_level;
+   ossim_int32 m_tile_column;
+   ossim_int32 m_tile_row;
+   std::vector<ossim_uint8> m_tile_data;
+   bool m_copy_tile_flag;
+};
+
+#endif /* #ifndef ossimGpkgTileRecord_HEADER */
+
diff --git a/ossim_plugins/sqlite/ossimGpkgUtil.cpp b/ossim_plugins/sqlite/ossimGpkgUtil.cpp
new file mode 100644
index 0000000..c444313
--- /dev/null
+++ b/ossim_plugins/sqlite/ossimGpkgUtil.cpp
@@ -0,0 +1,627 @@
+//----------------------------------------------------------------------------
+// File: ossimGpkgUtil.cpp
+// 
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Description: OSSIM GeoPackage utility class.
+//----------------------------------------------------------------------------
+// $Id$
+
+#include "ossimGpkgUtil.h"
+#include "ossimGpkgContentsRecord.h"
+#include "ossimGpkgDatabaseRecordBase.h"
+#include "ossimGpkgSpatialRefSysRecord.h"
+#include "ossimGpkgTileEntry.h"
+#include "ossimGpkgTileRecord.h"
+#include "ossimGpkgTileMatrixRecord.h"
+#include "ossimGpkgTileMatrixSetRecord.h"
+#include "ossimGpkgNsgTileMatrixExtentRecord.h"
+
+#include <ossim/base/ossimCommon.h>
+#include <ossim/base/ossimNotify.h>
+
+#include <sqlite3.h>
+#include <fstream>
+#include <ostream>
+#include <sstream>
+
+bool ossim_gpkg::checkSignature(std::istream& in)
+{
+   //---
+   // First 15 bytes should be: "SQLite format 3"
+   // Note the spec says 16 bytes but it doesn't add up.
+   // Samples have '.' at end.
+   //---
+   bool result = false;
+   char SIG[15];
+   in.read(SIG, 15);
+   if ( (SIG[0] == 'S') && (SIG[1] == 'Q') && (SIG[2] == 'L') && (SIG[3] == 'i') &&
+        (SIG[4] == 't') && (SIG[5] == 'e') && (SIG[6] == ' ') && (SIG[7] == 'f') &&
+        (SIG[8] == 'o') && (SIG[9] == 'r') && (SIG[10] == 'm') && (SIG[11] == 'a') &&
+        (SIG[12] == 't') && (SIG[13] == ' ') && (SIG[14] == '3') )   
+   {
+      result = true;
+   }
+   return result;
+}
+
+bool ossim_gpkg::checkApplicationId(std::istream& in)
+{
+   //---
+   // Check the application_id:
+   // Requirement 2: Every GeoPackage must contain 0x47503130 ("GP10" in ACII)
+   // in the application id field of the SQLite database header to indicate a
+   // GeoPackage version 1.0 file.
+   //---
+   bool result = false;
+   char APP_ID[4];
+   in.seekg( 68, std::ios_base::beg );
+   in.read(APP_ID, 4);
+   if ( (APP_ID[0] == 'G') && (APP_ID[1] == 'P') && (APP_ID[2] == '1') && (APP_ID[3] == '0') )
+   {
+      result = true;
+   }
+   return result;
+}
+
+void ossim_gpkg::getTileEntries( sqlite3* db, std::vector<ossimGpkgTileEntry>& entries )
+{
+   if ( db )
+   {
+      // Get all the tile matrix sets.  Each set can be concidered an entry.
+      
+      std::vector<ossimGpkgTileMatrixSetRecord> sets;
+      ossim_gpkg::getGpkgRecords(
+         db, sets, ossimGpkgTileMatrixSetRecord::getTableName() );
+
+      if ( sets.size() )
+      {
+         // Get all the tile matrix rows.
+         std::vector<ossimGpkgTileMatrixRecord> levels;
+         ossim_gpkg::getGpkgRecords(
+            db, levels, ossimGpkgTileMatrixRecord::getTableName() );
+
+          // Get all the nsg tile matrix extent rows.
+         std::vector<ossimGpkgNsgTileMatrixExtentRecord> extents;
+         ossim_gpkg::getGpkgRecords(
+            db, extents, ossimGpkgNsgTileMatrixExtentRecord::getTableName() );
+
+         // Get all the srs rows.
+         std::vector<ossimGpkgSpatialRefSysRecord> srs;
+         ossim_gpkg::getGpkgRecords(
+            db, srs, ossimGpkgSpatialRefSysRecord::getTableName() );
+
+         // For each entry captue the tile matrix and srs that belong to entry.
+         std::vector<ossimGpkgTileMatrixSetRecord>::const_iterator setIdx = sets.begin();
+         while ( setIdx != sets.end() )
+         {
+            ossimGpkgTileEntry entry;
+            entry.setTileMatrixSet(*setIdx);
+
+            // Add tile matrix objects to entry if table_name matches.
+            std::vector<ossimGpkgTileMatrixRecord>::const_iterator mIdx = levels.begin();
+            while ( mIdx != levels.end() )
+            {
+               if ( entry.getTileMatrixSet().m_table_name == (*mIdx).m_table_name )
+               {
+                  // table_name matches...
+                  entry.addTileMatrix( (*mIdx) );
+               }
+               ++mIdx;
+            }
+
+            // Add tile matrix extent objects to entry if table_name matches.
+            std::vector<ossimGpkgNsgTileMatrixExtentRecord>::const_iterator extIdx = extents.begin();
+            while ( extIdx != extents.end() )
+            {
+               if ( entry.getTileMatrixSet().m_table_name == (*extIdx).m_table_name )
+               {
+                  // table_name matches...
+                  entry.addTileMatrixExtent( (*extIdx) );
+               }
+               ++extIdx;
+            }
+
+            std::vector<ossimGpkgSpatialRefSysRecord>::const_iterator srsIdx = srs.begin();
+            while ( srsIdx != srs.end() )
+            {
+               if (entry.getTileMatrixSet().m_srs_id == (*srsIdx).m_srs_id)
+               {
+                  // srs id matches...
+                  entry.setSrs( (*srsIdx) );
+                  break;
+               }
+               ++srsIdx;
+            }
+
+            if ( entry.getTileMatrix().size() )
+            {
+               // The sort call puts the tile matrix entries in highest zoom to lowest order.
+               entry.sortTileMatrix();
+               entry.sortTileMatrixExtents();
+               
+               // Add the entry
+               entries.push_back( entry );
+            }
+            else
+            {
+               ossimNotify(ossimNotifyLevel_WARN)
+                  << "ossim_gpkg::getTileEntries WARNING No levels found for entry!"
+                  << std::endl;
+            }
+
+            ++setIdx; // Next entry.
+         }
+      } 
+      
+   } // Matches: if ( sqlite3* db )
+   
+} // End: ossim_gpkg::getTileEntries( ... )
+
+bool ossim_gpkg::getTileEntry( sqlite3* db,
+                               const std::string& tileTableName,
+                               ossimGpkgTileEntry& entry )
+{
+   bool status = false;
+   
+   if ( db )
+   {
+      // Get all the tile matrix set for the tile table name.
+      ossimGpkgTileMatrixSetRecord set;
+      if ( ossim_gpkg::getGpkgRecord(
+              db, set, ossimGpkgTileMatrixSetRecord::getTableName(), tileTableName ) )
+      {
+         entry.setTileMatrixSet( set );
+
+         // Get all the tile matrix rows.  There's one for each level.
+         std::vector<ossimGpkgTileMatrixRecord> levels;
+         ossim_gpkg::getGpkgRecords(
+            db, levels, ossimGpkgTileMatrixRecord::getTableName(), tileTableName );
+
+         if ( levels.size() )
+         {
+            // Add tile matrix objects to entry if table_name matches.
+            std::vector<ossimGpkgTileMatrixRecord>::const_iterator mIdx = levels.begin();
+            while ( mIdx != levels.end() )
+            {
+               entry.addTileMatrix( (*mIdx) );
+               ++mIdx;
+            }
+            
+            // Get the GpkgSpatialRefSys.  Required or we don't go on.
+            ossimGpkgSpatialRefSysRecord srs;
+            if ( ossim_gpkg::getSrsRecord(
+                    db,
+                    set.m_srs_id,
+                    srs ) )
+            {
+               entry.setSrs( srs );
+
+               //---
+               // At this point we can set the status to true.  The below nsg
+               // tile matrix extent is not required.
+               //---
+               status = true;
+
+               // Add tile matrix extent objects to entry if table_name matches.
+
+               // Get all the nsg tile matrix extent rows.
+               std::vector<ossimGpkgNsgTileMatrixExtentRecord> extents;
+               ossim_gpkg::getGpkgRecords(
+                  db,
+                  extents,
+                  ossimGpkgNsgTileMatrixExtentRecord::getTableName(),
+                  tileTableName );
+               std::vector<ossimGpkgNsgTileMatrixExtentRecord>::const_iterator extIdx =
+                  extents.begin();
+               while ( extIdx != extents.end() )
+               {
+                  if ( entry.getTileMatrixSet().m_table_name == (*extIdx).m_table_name )
+                  {
+                     // table_name matches...
+                     entry.addTileMatrixExtent( (*extIdx) );
+                  }
+                  ++extIdx;
+               }
+
+               if ( entry.getTileMatrix().size() )
+               {
+                  // The sort call puts the tile matrix entries in highest zoom to lowest order.
+                  entry.sortTileMatrix();
+               }
+               if ( entry.getTileMatrixExtent().size() )
+               {
+                  // The sort call puts the tile matrix entries in highest zoom to lowest order.
+                  entry.sortTileMatrixExtents();
+
+                  // If we have extents, the size should match the tile matrix size.
+                  if ( entry.getTileMatrixExtent().size() != entry.getTileMatrix().size() )
+                  {
+                     ossimNotify(ossimNotifyLevel_WARN)
+                        << "ossim_gpkg::getTileEntry WARNING size mismatch between tile matrix"
+                        << " and tile matrix extents!\n";
+                  }
+               }
+            }
+            else
+            {
+               ossimNotify(ossimNotifyLevel_WARN)
+                  << "ossim_gpkg::getTileEntry WARNING No gpkg_spatial_ref_sys record found for"
+                  << " entry!\n";
+            }
+         }
+         else
+         {
+            ossimNotify(ossimNotifyLevel_WARN)
+               << "ossim_gpkg::getTileEntry WARNING No gpkg_tile_matrix records found for entry!"
+               << std::endl;
+         }
+      } 
+      
+   } // Matches: if ( sqlite3* db )
+
+   return status;
+   
+} // End: ossim_gpkg::getTileEntry( ... )
+
+template <class T> void ossim_gpkg::getGpkgRecords( sqlite3* db,
+                                                    std::vector<T>& result,
+                                                    const std::string& dbTableName )
+{
+   if ( db && dbTableName.size() )
+   {
+      const char *zLeftover;      /* Tail of unprocessed SQL */
+      sqlite3_stmt *pStmt = 0;    /* The current SQL statement */
+      std::string sql = "SELECT * from ";
+      sql += dbTableName;
+      
+      int rc = sqlite3_prepare_v2(db,           // Database handle
+                                  sql.c_str(),  // SQL statement, UTF-8 encoded
+                                  -1,           // Maximum length of zSql in bytes.
+                                  &pStmt,       // OUT: Statement handle
+                                  &zLeftover);  // OUT: Pointer to unused portion of zSql
+      if ( rc == SQLITE_OK )
+      {
+         while( 1 )
+         {
+            // Read the row:
+            rc = sqlite3_step(pStmt);
+            if ( rc == SQLITE_ROW )
+            {
+               T record;
+               ossimGpkgDatabaseRecordBase* gpkgRecPtr =
+                  dynamic_cast<ossimGpkgDatabaseRecordBase*>( &record );
+               if ( gpkgRecPtr )
+               {
+                  if ( gpkgRecPtr->init( pStmt ) )
+                  {
+                     result.push_back(record);
+                  }
+                  else
+                  {
+                     ossimNotify(ossimNotifyLevel_WARN)
+                        << "ossim_gpkg::getGpkgRecords init failed!"
+                        << std::endl;
+                     break;
+                  }
+               }
+               else
+               {
+                  break;
+               }
+            }
+            else
+            {
+               break;
+            }
+         }
+      }
+      sqlite3_finalize(pStmt);
+   }
+   
+} // End: ossim_gpkg::getGpkgRecords( db, result, dbTableName )
+
+template <class T> void ossim_gpkg::getGpkgRecords( sqlite3* db,
+                                                    std::vector<T>& result,
+                                                    const std::string& dbTableName,
+                                                    const std::string& table_name )
+{
+   if ( db && dbTableName.size() && table_name.size() )
+   {
+      const char *zLeftover;      /* Tail of unprocessed SQL */
+      sqlite3_stmt *pStmt = 0;    /* The current SQL statement */
+      std::ostringstream sql;
+      sql << "SELECT * from " << dbTableName
+          << " WHERE table_name == '" << table_name << "'";
+      
+      int rc = sqlite3_prepare_v2(db,                 // Database handle
+                                  sql.str().c_str(),  // SQL statement, UTF-8 encoded
+                                  -1,                 // Maximum length of zSql in bytes.
+                                  &pStmt,             // OUT: Statement handle
+                                  &zLeftover);        // OUT: Pointer to unused portion of zSql
+      if ( rc == SQLITE_OK )
+      {
+         while( 1 )
+         {
+            // Read the row:
+            rc = sqlite3_step(pStmt);
+            if ( rc == SQLITE_ROW )
+            {
+               T record;
+               ossimGpkgDatabaseRecordBase* gpkgRecPtr =
+                  dynamic_cast<ossimGpkgDatabaseRecordBase*>( &record );
+               if ( gpkgRecPtr )
+               {
+                  if ( gpkgRecPtr->init( pStmt ) )
+                  {
+                     result.push_back(record);
+                  }
+                  else
+                  {
+                     ossimNotify(ossimNotifyLevel_WARN)
+                        << "ossim_gpkg::getGpkgRecords init failed!"
+                        << std::endl;
+                     break;
+                  }
+               }
+               else
+               {
+                  break;
+               }
+            }
+            else
+            {
+               break;
+            }
+         }
+      }
+      sqlite3_finalize(pStmt);
+   }
+   
+} // End: ossim_gpkg::getGpkgRecords( db, result, dbTableName, table_name )
+
+template <class T> bool ossim_gpkg::getGpkgRecord( sqlite3* db,
+                                                   T& result,
+                                                   const std::string& dbTableName,
+                                                   const std::string& table_name )
+{
+   bool status = false;
+   
+   if ( db && dbTableName.size() && table_name.size() )
+   {
+      const char *zLeftover;      /* Tail of unprocessed SQL */
+      sqlite3_stmt *pStmt = 0;    /* The current SQL statement */
+      std::ostringstream sql;
+      sql << "SELECT * from " << dbTableName
+          << " WHERE table_name == '" << table_name << "'";
+
+      int rc = sqlite3_prepare_v2(db,                // Database handle
+                                  sql.str().c_str(), // SQL statement, UTF-8 encoded
+                                  -1,                // Maximum length of zSql in bytes.
+                                  &pStmt,            // OUT: Statement handle
+                                  &zLeftover);       // OUT: Pointer to unused portion of zSql
+      if ( rc == SQLITE_OK )
+      {
+         // Read the row:
+         rc = sqlite3_step(pStmt);
+         
+         if ( rc == SQLITE_ROW )
+         {
+            ossimGpkgDatabaseRecordBase* gpkgRecPtr =
+               dynamic_cast<ossimGpkgDatabaseRecordBase*>( &result );
+            if ( gpkgRecPtr )
+            {
+               status = gpkgRecPtr->init( pStmt );
+               if ( !status )
+               {
+                  ossimNotify(ossimNotifyLevel_WARN)
+                     << "ossim_gpkg::getGpkgRecord init failed!"
+                     << std::endl;
+               }
+            }
+         }
+      }
+      sqlite3_finalize(pStmt);
+   }
+
+   return status;
+   
+} // End: ossim_gpkg::getGpkgRecord( ... )
+
+
+bool ossim_gpkg::getSrsRecord( sqlite3* db,
+                               ossim_int32 srs_id,
+                               ossimGpkgSpatialRefSysRecord& srs )
+{
+   bool status = false;
+   
+   if ( db )
+   {
+      const char *zLeftover;      /* Tail of unprocessed SQL */
+      sqlite3_stmt *pStmt = 0;    /* The current SQL statement */
+      std::ostringstream sql;
+      sql << "SELECT * from " << srs.getTableName()
+          << " WHERE srs_id == " << srs_id;
+      
+      int rc = sqlite3_prepare_v2(db,                // Database handle
+                                  sql.str().c_str(), // SQL statement, UTF-8 encoded
+                                  -1,                // Maximum length of zSql in bytes.
+                                  &pStmt,            // OUT: Statement handle
+                                  &zLeftover);       // OUT: Pointer to unused portion of zSql
+      if ( rc == SQLITE_OK )
+      {
+         // Read the row:
+         rc = sqlite3_step(pStmt);
+         if ( rc == SQLITE_ROW )
+         {
+            ossimGpkgDatabaseRecordBase* gpkgRecPtr =
+               dynamic_cast<ossimGpkgDatabaseRecordBase*>( &srs );
+            if ( gpkgRecPtr )
+            {
+               status = gpkgRecPtr->init( pStmt );
+               if ( !status )
+               {
+                  ossimNotify(ossimNotifyLevel_WARN)
+                     << "ossim_gpkg::getSrsRecord init failed!"
+                     << std::endl;
+               }
+            }
+         }
+      }
+      sqlite3_finalize(pStmt);
+   }
+
+   return status;
+   
+} // End: ossim_gpkg::getSrsRecord( ... )
+
+bool ossim_gpkg::getTableRows(
+   sqlite3* db,
+   const std::string& tableName,
+   std::vector< ossimRefPtr<ossimGpkgDatabaseRecordBase> >& result )
+{
+   static const char M[] = "ossim_gpkg::getTableRows";
+
+   bool status = false;
+   
+   if ( db && tableName.size() )
+   {
+      const char *zLeftover;      /* Tail of unprocessed SQL */
+      sqlite3_stmt *pStmt = 0;    /* The current SQL statement */
+      std::string sql = "SELECT * from ";
+      sql += tableName;
+
+      int rc = sqlite3_prepare_v2(db,           // Database handle
+                                  sql.c_str(),  // SQL statement, UTF-8 encoded
+                                  -1,           // Maximum length of zSql in bytes.
+                                  &pStmt,       // OUT: Statement handle
+                                  &zLeftover);  // OUT: Pointer to unused portion of zSql
+      if ( rc == SQLITE_OK )
+      {
+         bool initStatus = true;
+         
+         int nCol = sqlite3_column_count( pStmt );
+         if ( nCol )
+         {
+            while( 1 )
+            {
+               // Read the row:
+               rc = sqlite3_step(pStmt);
+               if ( rc == SQLITE_ROW )
+               {
+                  ossimRefPtr<ossimGpkgDatabaseRecordBase> row = getNewTableRecord( tableName );
+                  if ( row.valid() )
+                  {
+                     if ( row->init( pStmt ) )
+                     {
+                        result.push_back(row);
+                     }
+                     else
+                     {
+                        ossimNotify(ossimNotifyLevel_WARN)
+                           << M << " init failed!" << std::endl;
+                        initStatus = false;
+                        break;
+                     }
+                  }
+                  else
+                  {
+                     ossimNotify(ossimNotifyLevel_WARN)
+                        << M << " could not make object for table name: " << tableName
+                        << std::endl;
+                     initStatus = false;
+                     break; 
+                  }
+               }
+               else
+               {
+                  break;
+               }
+            }
+         }
+         if ( initStatus && result.size() )
+         {
+            status = true;
+         }  
+      }
+      sqlite3_finalize(pStmt);
+   }
+   
+   return status;
+   
+} // End: ossim_gpks::getTableRows(...)
+
+ossimRefPtr<ossimGpkgDatabaseRecordBase> ossim_gpkg::getNewTableRecord(
+   const std::string& tableName )
+{
+   ossimRefPtr<ossimGpkgDatabaseRecordBase> result = 0;
+   if ( tableName == ossimGpkgTileMatrixRecord::getTableName() )
+   {
+      result = new ossimGpkgTileMatrixRecord();
+   }
+   else if ( tableName == ossimGpkgTileMatrixSetRecord::getTableName() )
+   {
+      result = new ossimGpkgTileMatrixSetRecord();
+   }
+   else if ( tableName == ossimGpkgSpatialRefSysRecord::getTableName() )
+   {
+      result = new ossimGpkgSpatialRefSysRecord();
+   }
+   else if ( tableName == ossimGpkgContentsRecord::getTableName() )
+   {
+      result = new ossimGpkgContentsRecord();
+   }
+   else if ( tableName == ossimGpkgNsgTileMatrixExtentRecord::getTableName() )
+   {
+      result = new ossimGpkgNsgTileMatrixExtentRecord();
+   }
+
+   return result;
+}
+
+std::ostream& ossim_gpkg::printTiles(sqlite3* db, const std::string& tileTableName, std::ostream& out)
+{
+   if ( db )
+   {
+      const char *zLeftover;      /* Tail of unprocessed SQL */
+      sqlite3_stmt *pStmt = 0;    /* The current SQL statement */
+      std::string sql = "SELECT * from ";
+      sql += tileTableName;
+      
+      int rc = sqlite3_prepare_v2(db,           // Database handle
+                                  sql.c_str(),  // SQL statement, UTF-8 encoded
+                                  -1,           // Maximum length of zSql in bytes.
+                                  &pStmt,       // OUT: Statement handle
+                                  &zLeftover);  // OUT: Pointer to unused portion of zSql
+      if ( rc == SQLITE_OK )
+      {
+         int nCol = sqlite3_column_count( pStmt );
+         if ( nCol )
+         {
+            ossimGpkgTileRecord tile;
+            tile.setCopyTileFlag(false);
+            while( 1 )
+            {
+               // Read the row:
+               rc = sqlite3_step(pStmt);
+               if ( rc == SQLITE_ROW )
+               {
+                  if (tile.init( pStmt ) )
+                  {
+                     out << tile << std::endl;
+                  }     
+               }
+               else
+               {
+                  break;
+               }
+            }
+         }
+      }
+      sqlite3_finalize(pStmt);
+   }
+   return out;
+}
+
diff --git a/ossim_plugins/sqlite/ossimGpkgUtil.h b/ossim_plugins/sqlite/ossimGpkgUtil.h
new file mode 100644
index 0000000..ff58e1d
--- /dev/null
+++ b/ossim_plugins/sqlite/ossimGpkgUtil.h
@@ -0,0 +1,168 @@
+//----------------------------------------------------------------------------
+// File: ossimGpkgUtil.h
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Description: OSSIM GeoPackage utility class.
+//
+//----------------------------------------------------------------------------
+// $Id
+
+#ifndef ossimGpkgUtil_HEADER
+#define ossimGpkgUtil_HEADER 1
+
+#include <ossim/base/ossimRefPtr.h>
+#include "ossimGpkgDatabaseRecordBase.h"
+#include <iosfwd>
+#include <vector>
+
+class ossimGpkgContentsRecord;
+class ossimGpkgSpatialRefSysRecord;
+class ossimGpkgTileEntry;
+class ossimGpkgTileMatrixRecord;
+class ossimGpkgTileMatrixSetRecord;
+
+struct sqlite3;
+
+namespace ossim_gpkg
+{
+   /**
+    * @brief Check signature method.
+    * @return true if requirement 1 and 2 are met in the file; false, if not.
+    */
+   bool checkSignature(std::istream& in);
+
+   /**
+    * @brief Check application_id.
+    * @return true if requirement 2 are met in the file; false, if not.
+    */
+   bool checkApplicationId(std::istream& in);
+
+   /**
+    * @brief Gets all the tile entries.
+    * @param db An open database.
+    * @param entries Initialized by this.
+    */
+   void getTileEntries( sqlite3* db,
+                        std::vector<ossimGpkgTileEntry>& entries );
+   /**
+    * @brief Gets tile entry whos table_name field matches tileTableName.
+    * @param db An open database.
+    * @param table_name e.g. "tiles"
+    * @param entries Initialized by this.
+    */
+   bool getTileEntry( sqlite3* db,
+                      const std::string& tileTableName,
+                      ossimGpkgTileEntry& entry );   
+
+   /**
+    * @brief Get gpkg records.
+    *
+    * class T must be derived from ossimGpkgDatabaseRecordBase.
+    * @param db An open database.
+    * @param result Initialized by this.
+    * @param dbTableName E.g. "gpkg_contents".
+    */
+   template <class T> void getGpkgRecords( sqlite3* db,
+                                           std::vector<T>& result,
+                                           const std::string& dbTableName );
+
+   /**
+    * @brief Get gpkg records.
+    *
+    * class T must be derived from ossimGpkgDatabaseRecordBase.
+    * @param db An open database.
+    * @param result Initialized by this.
+    * @param dbTableName E.g. "gpkg_contents".
+    * @param table_name e.g. "tiles"
+    */
+   template <class T> void getGpkgRecords( sqlite3* db,
+                                           std::vector<T>& result,
+                                           const std::string& dbTableName,
+                                           const std::string& table_name  );
+
+   /**
+    * @brief Get gpkg record.
+    *
+    * class T must be derived from ossimGpkgDatabaseRecordBase.
+    * @param db An open database.
+    * @param result Initialized by this.
+    * @param dbTableName e.g. "gpkg_contents".
+    * @param table_name e.g. "tiles"
+    * @return true on success, false on error.
+    */
+   template <class T> bool getGpkgRecord( sqlite3* db,
+                                          T& result,
+                                          const std::string& dbTableName,
+                                          const std::string& table_name );
+
+
+   /**
+    * @brief Get gpkg_spatial_ref_sys record for srs_it.
+    *
+    * @param db An open database.
+    * @param srs_id ID to look for.
+    * @param srs Initialized by this.
+    * @return true on success, false on error.
+    */
+
+   bool getSrsRecord( sqlite3* db,
+                      ossim_int32 srs_id,
+                      ossimGpkgSpatialRefSysRecord& srs );   
+
+   
+   /**
+    * @brief Parse table rows
+    * @param db An open database.
+    * @param tableName e.g. "gpkg_contents"
+    * @param result Initialized by this with records.
+    * @return true on success, false on error.
+    */
+   bool getTableRows(
+      sqlite3* db,
+      const std::string& tableName,
+      std::vector< ossimRefPtr<ossimGpkgDatabaseRecordBase> >& result );
+
+   /**
+    * @brief Parse gpkg_spatial_ref_sys tables.
+    * @param db An open database.
+    * @param result Initialized by this with records.
+    * @return true on success, false on error.
+    */
+   // bool parseGpkgSpatialRefSysTables(
+   //    sqlite3* db, std::vector< ossimRefPtr<ossimGpkgSpatialRefSysRecord> >& result );
+
+   /**
+    * @brief Parse gpkg_tile_matrix_set tables.
+    * @param db An open database.
+    * @param result Initialized by this with records.
+    * @return true on success, false on error.
+    */
+   // bool parseGpkgTileMatrixSetTables(
+   //    sqlite3* db, std::vector< ossimRefPtr<ossimGpkgTileMatrixSetRecord> >& result );
+
+
+   /**
+    * @brief Parse gpkg_tile_matrix tables.
+    * @param db An open database.
+    * @param result Initialized by this with records.
+    * @return true on success, false on error.
+    */
+   // bool parseGpkgTileMatrixTables(
+   //    sqlite3* db, std::vector< ossimRefPtr<ossimGpkgTileMatrixRecord> >& result );
+
+   /**
+    * @brief Gets table record from table name.
+    * @return Intance of record wrapped in ref ptr.  Contents can be null
+    * if talbeName is not known.
+    */
+   ossimRefPtr<ossimGpkgDatabaseRecordBase> getNewTableRecord(
+      const std::string& tableName );
+
+   std::ostream& printTiles(sqlite3* db, const std::string& tileTableName, std::ostream& out);
+}
+
+#endif /* #ifndef ossimGpkgUtil_HEADER */
+
diff --git a/ossim_plugins/sqlite/ossimGpkgWriter.cpp b/ossim_plugins/sqlite/ossimGpkgWriter.cpp
new file mode 100644
index 0000000..8357721
--- /dev/null
+++ b/ossim_plugins/sqlite/ossimGpkgWriter.cpp
@@ -0,0 +1,3128 @@
+//----------------------------------------------------------------------------
+//
+// File: ossimGpkgReader.cpp
+//
+// Author:  David Burken
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Description: OSSIM Geo Package writer.
+//
+//----------------------------------------------------------------------------
+// $Id$
+
+#include "ossimGpkgWriter.h"
+#include "ossimGpkgContentsRecord.h"
+#include "ossimGpkgNsgTileMatrixExtentRecord.h"
+#include "ossimGpkgSpatialRefSysRecord.h"
+#include "ossimGpkgTileEntry.h"
+#include "ossimGpkgTileRecord.h"
+#include "ossimGpkgTileMatrixRecord.h"
+#include "ossimGpkgTileMatrixSetRecord.h"
+#include "ossimGpkgUtil.h"
+#include "ossimSqliteUtil.h"
+
+#include <ossim/base/ossimBooleanProperty.h>
+#include <ossim/base/ossimCommon.h>
+#include <ossim/base/ossimTrace.h>
+#include <ossim/base/ossimDpt.h>
+#include <ossim/base/ossimEndian.h>
+#include <ossim/base/ossimException.h>
+#include <ossim/base/ossimGpt.h>
+#include <ossim/base/ossimIrect.h>
+#include <ossim/base/ossimKeywordlist.h>
+#include <ossim/base/ossimKeywordNames.h>
+#include <ossim/base/ossimNumericProperty.h>
+#include <ossim/base/ossimScalarTypeLut.h>
+#include <ossim/base/ossimStringProperty.h>
+#include <ossim/base/ossimTrace.h>
+#include <ossim/base/ossimViewInterface.h>
+#include <ossim/base/ossimVisitor.h>
+
+#include <ossim/imaging/ossimCodecFactoryRegistry.h>
+#include <ossim/imaging/ossimImageCombiner.h>
+#include <ossim/imaging/ossimImageData.h>
+#include <ossim/imaging/ossimImageSource.h>
+#include <ossim/imaging/ossimJpegMemDest.h>
+#include <ossim/imaging/ossimRectangleCutFilter.h>
+#include <ossim/imaging/ossimScalarRemapper.h>
+
+#include <ossim/projection/ossimEquDistCylProjection.h>
+#include <ossim/projection/ossimEpsgProjectionFactory.h>
+#include <ossim/projection/ossimGoogleProjection.h>
+#include <ossim/projection/ossimMapProjection.h>
+#include <ossim/projection/ossimMercatorProjection.h>
+
+#include <jpeglib.h>
+#include <sqlite3.h>
+
+#include <algorithm> /* std::sort */
+#include <cmath>
+#include <sstream>
+
+RTTI_DEF1(ossimGpkgWriter, "ossimGpkgWriter", ossimImageFileWriter)
+
+static const std::string ADD_ALPHA_CHANNEL_KW          = "add_alpha_channel";
+static const std::string ADD_ENTRY_KW                  = "add_entry";
+static const std::string ADD_LEVELS_KW                 = "add_levels";
+static const std::string ALIGN_TO_GRID_KW              = "align_to_grid";
+static const std::string APPEND_KW                     = "append";
+static const std::string BATCH_SIZE_KW                 = "batch_size";
+static const std::string CLIP_EXTENTS_KW               = "clip_extents";
+static const std::string CLIP_EXTENTS_ALIGN_TO_GRID_KW = "clip_extents_align_to_grid";
+static const std::string COMPRESSION_LEVEL_KW          = "compression_level";
+static const std::string DEFAULT_FILE_NAME             = "output.gpkg";
+static const std::string EPSG_KW                       = "epsg";
+static const std::string INCLUDE_BLANK_TILES_KW        = "include_blank_tiles";
+static const std::string TILE_SIZE_KW                  = "tile_size";
+static const std::string TILE_TABLE_NAME_KW            = "tile_table_name";
+static const std::string TRUE_KW                       = "true";
+static const std::string USE_PROJECTION_EXTENTS_KW     = "use_projection_extents";
+static const std::string WRITER_MODE_KW                = "writer_mode";
+static const std::string ZOOM_LEVELS_KW                = "zoom_levels";
+
+//---
+// For trace debugging (to enable at runtime do:
+// your_app -T "ossimGpkgWriter:debug" your_app_args
+//---
+static ossimTrace traceDebug("ossimGpkgWriter:debug");
+
+// For the "ident" program:
+#if OSSIM_ID_ENABLED
+static const char OSSIM_ID[] = "$Id: ossimGpkgWriter.cpp 22466 2013-10-24 18:23:51Z dburken $";
+#endif
+
+ossimGpkgWriter::ossimGpkgWriter()
+   :
+   ossimImageFileWriter(),
+   m_db(0),
+   m_batchCount(0),
+   m_batchSize(32),
+   m_projectionBoundingRect(0.0, 0.0, 0.0, 0.0, OSSIM_RIGHT_HANDED),
+   m_sceneBoundingRect(0.0, 0.0, 0.0, 0.0, OSSIM_RIGHT_HANDED),
+   m_clipRect(0.0, 0.0, 0.0, 0.0, OSSIM_RIGHT_HANDED),
+   m_outputRect(0.0, 0.0, 0.0, 0.0, OSSIM_RIGHT_HANDED),
+   m_tileSize(0,0),
+   m_tileTableName(),
+   m_srs_id(-1),
+   m_kwl(new ossimKeywordlist()),
+   m_fullTileCodec(0),
+   m_partialTileCodec(0),
+   m_fullTileCodecAlpha(false),
+   m_partialTileCodecAlpha(false),
+   m_zoomLevels(),
+   m_zoomLevelMatrixSizes(),
+   m_pStmt(0),
+   m_writeBlanks(false)
+{
+   //---
+   // Uncomment for debug mode:
+   // traceDebug.setTraceFlag(true);
+   //---
+   
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimGpkgWriter::ossimGpkgWriter entered" << std::endl;
+#if OSSIM_ID_ENABLED
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "OSSIM_ID:  "
+         << OSSIM_ID
+         << std::endl;
+#endif
+   }
+
+   theOutputImageType = "ossim_gpkg"; // ossimImageFileWriter attribute.
+
+   // Set default options:
+   m_kwl->addPair( ALIGN_TO_GRID_KW, TRUE_KW );
+   m_kwl->addPair( TILE_SIZE_KW, std::string("( 256, 256 )") );
+   m_kwl->addPair( WRITER_MODE_KW, std::string("mixed") );
+
+   // Note batch size dramatically effects speed.
+   m_kwl->addPair( BATCH_SIZE_KW, "32" );
+}
+
+ossimGpkgWriter::~ossimGpkgWriter()
+{
+   close();
+
+   // Not a leak, ref ptr.
+   m_kwl = 0;
+}
+
+ossimString ossimGpkgWriter::getShortName() const
+{
+   return ossimString("ossim_gpkg_writer");
+}
+
+ossimString ossimGpkgWriter::getLongName() const
+{
+   return ossimString("ossim gpkg writer");
+}
+
+ossimString ossimGpkgWriter::getClassName() const
+{
+   return ossimString("ossimGpkgWriter");
+}
+
+bool ossimGpkgWriter::isOpen() const
+{
+   return (m_db?true:false);
+}
+
+bool ossimGpkgWriter::open()
+{
+   bool status = false;
+
+   close();
+   
+   if ( theFilename.size() )
+   {
+      int flags = SQLITE_OPEN_READWRITE;
+
+      if ( theFilename.exists() )
+      {
+         if ( !append() )
+         {
+            theFilename.remove();
+            flags |= SQLITE_OPEN_CREATE;
+         }
+      }
+      else
+      {
+         flags |= SQLITE_OPEN_CREATE;
+         
+         //---
+         // Set the append flags to false for down stream code since there was
+         // no file to append.
+         //---
+         m_kwl->addPair( ADD_ENTRY_KW, std::string("0"), true );
+         m_kwl->addPair( ADD_LEVELS_KW, std::string("0"), true );         
+      }
+
+      int rc = sqlite3_open_v2( theFilename.c_str(), &m_db, flags, 0 );
+      if ( rc == SQLITE_OK )
+      {
+         status = true;
+
+         if ( !append() )
+         {
+            //---
+            // Set the application_id:
+            // Requirement 2: Every GeoPackage must contain 0x47503130 ("GP10" in ACII)
+            // in the application id field of the SQLite database header to indicate a
+            // GeoPackage version 1.0 file.
+            //---
+            const ossim_uint32 ID = 0x47503130;
+            std::ostringstream sql;
+            sql << "PRAGMA application_id = " << ID;
+            if ( ossim_sqlite::exec( m_db, sql.str() ) != SQLITE_DONE )
+            {
+               status = false;
+            }
+         }            
+      }
+      else
+      {
+         close();
+      }
+   }
+   
+   return status;
+}
+
+bool ossimGpkgWriter::openFile( const ossimKeywordlist& options )
+{
+   static const char MODULE[] = "ossimGpkgWriter::openFile";
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " entered...\n";
+   }
+   
+   bool status = false;
+
+   if ( isOpen() )
+   {
+      close();
+   }
+
+   // Add the passed in options to the default options.
+   m_kwl->add( 0, options, true );
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "\nwriter options/settings:\n"
+         << *(m_kwl.get()) << "\n";
+   }
+
+   // Get the filename:
+   if ( getFilename( theFilename ) )
+   {
+      // Open it:
+      if ( open() )
+      {
+         if ( m_db )
+         {
+            if ( createTables( m_db ) )
+            {
+               if ( !append() )
+               {
+                  // New file:
+                  status = initializeGpkg();
+               }
+               else // Existing gpkg....
+               {
+                  // Get the zoom level info needed for disconnected writeTile checks.
+                  std::string tileTableName;
+                  getTileTableName( tileTableName );
+         
+                  ossimGpkgTileEntry entry;
+                  if ( ossim_gpkg::getTileEntry( m_db, tileTableName, entry ) )
+                  {
+                     entry.getZoomLevels( m_zoomLevels );
+                     entry.getZoomLevelMatrixSizes( m_zoomLevelMatrixSizes );
+                     status = true;
+                  }
+               }
+
+               if ( status )
+               {
+                  initializeCodec(); // Throws exception on error.
+
+                  m_writeBlanks = keyIsTrue( INCLUDE_BLANK_TILES_KW );
+                  m_batchSize = getBatchSize();
+                  m_batchCount = 0;
+               }
+            }
+         }
+      }
+   }
+   
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " exit status: " << (status?"true":"false") << std::endl;
+   }
+
+   // status = true;
+
+   return status;
+}
+
+// Method assumes new gpkg with no input connection.
+bool ossimGpkgWriter::initializeGpkg()
+{
+   static const char MODULE[] = "ossimGpkgWriter::initializeGpkg";
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " entered...\n";
+   }
+
+   bool status = false;
+   
+   if ( alignToGrid() ) // Currently only handle align to grid mode.
+   {
+      // Set tile size:
+      getTileSize( m_tileSize );
+
+      // Output projection:
+      ossimRefPtr<ossimMapProjection> proj = getNewOutputProjection();
+      if ( proj.valid() )
+      {
+         // Initialize m_projectionBoundingRect.
+         initializeProjectionRect( proj.get() );
+            
+         m_srs_id = writeGpkgSpatialRefSysTable( m_db, proj.get() );
+         if ( m_srs_id != -1 )
+         {
+            // Initialize m_sceneBoundingRect:
+            if ( getWmsCutBox( m_sceneBoundingRect ) == false )
+            {
+               m_sceneBoundingRect = m_projectionBoundingRect;
+            }
+
+            bool needToExpandFlag = true;
+            //---
+            // Set the initial tie point. will make the AOI come out
+            // (0,0) to (n,n). Needed for getExpandedAoi code. Requires
+            // m_sceneBoundingRect or m_projectionBoundingRect(grid aligned).
+            //---
+            setProjectionTie( proj.get() );
+            // Set the clip rect.
+            if ( getClipExtents( m_clipRect, needToExpandFlag ) == false )
+            {
+               m_clipRect = m_sceneBoundingRect.clipToRect( m_projectionBoundingRect );
+            }
+            
+            // Get the zoom levels:
+            m_zoomLevels.clear();
+            m_zoomLevelMatrixSizes.clear();
+            getZoomLevels( m_zoomLevels );
+
+            ossim_uint32 levels = m_zoomLevels.size();
+
+            if ( levels )
+            {
+               // Get the gsd for the most expanded out level:
+               ossimDpt largestGsd;
+               getGsd( proj.get(), m_zoomLevels[0], largestGsd );
+
+               // Get the gsd for the most expanded out level:
+               ossimDpt smallestGsd;
+               getGsd( proj.get(), m_zoomLevels[ levels-1 ], smallestGsd );
+
+               //---
+               // Set the scale of projection to the largest gsd before
+               // expanding AOI. This will also recenter projection tie
+               // for new gsd.
+               //---
+               applyScaleToProjection( proj.get(), largestGsd );
+
+               // AOI at zoomed out level:
+               ossimIrect aoi;
+               getAoiFromRect( proj.get(), m_clipRect, aoi );
+               
+               // Expand the AOI to even tile boundary:
+               ossimIrect expandedAoi = aoi;
+               if(needToExpandFlag)
+               {
+                  getExpandedAoi( aoi, expandedAoi );                  
+               }
+                        
+               initializeRect( proj.get(), expandedAoi, m_outputRect );
+ 
+               if (traceDebug())
+               {
+                  ossimNotify(ossimNotifyLevel_DEBUG)
+                     << "\n\nfirst level:  " << m_zoomLevels[0]
+                     << "\nlast level:   " << m_zoomLevels[ levels-1 ]
+                     << "\nlevel[" << m_zoomLevels[0] << "] gsd: " << largestGsd
+                     << "\nlevel[" << m_zoomLevels[levels-1] << "] gsd: " << smallestGsd
+                     << "\nexpanded aoi(first zoom level): " << expandedAoi
+                     << "\ntile size:    " << m_tileSize
+                     << "\nscene rect:   " << m_sceneBoundingRect
+                     << "\nclip rect:    " << m_clipRect
+                     << "\noutput rect:  " << m_outputRect
+                     << "\n";
+               }
+
+               if ( writeGpkgContentsTable( m_db, m_outputRect ) )
+               {
+                  if ( writeGpkgTileMatrixSetTable( m_db, m_outputRect ) )
+                  {
+                     ossimDpt gsd;
+                     getGsd( proj.get(), gsd );
+                     
+                     // Write the tile matrix record for each zoom level.
+                     std::vector<ossim_int32>::const_iterator zoomLevel = m_zoomLevels.begin();
+                     while ( zoomLevel != m_zoomLevels.end() )
+                     {
+                        // Get the area of interest.
+                        ossimIrect aoi;
+                        getAoiFromRect( proj.get(), m_outputRect, aoi );
+                        
+                        // Clipped aoi:
+                        ossimIrect clippedAoi;
+                        getAoiFromRect( proj.get(), m_clipRect, clippedAoi );
+                        
+                        // Expanded to tile boundaries:
+                        ossimIrect expandedAoi;
+                        getExpandedAoi( aoi, expandedAoi );
+                        
+                        // Get the number of tiles:
+                        ossimIpt matrixSize;
+                        getMatrixSize( expandedAoi, matrixSize);
+
+                        // Capture for writeTile index check.
+                        m_zoomLevelMatrixSizes.push_back( matrixSize );
+
+                        if (traceDebug())
+                        {
+                           ossimNotify(ossimNotifyLevel_DEBUG)
+                              << "\nlevel:       " << (*zoomLevel)
+                              << "\ngsd:         " << gsd
+                              << "\naoi:         " << aoi
+                              << "\nclippedAoi:  " << clippedAoi
+                              << "\nexpandedAoi: " << expandedAoi
+                              << "\nmatrixSize:  " << matrixSize
+                              << "\n";
+                        }
+
+                        if ( writeGpkgTileMatrixTable( m_db, (*zoomLevel), matrixSize, gsd ) )
+                        {
+                           
+                           if ( writeGpkgNsgTileMatrixExtentTable( m_db, (*zoomLevel),
+                                                                   expandedAoi, clippedAoi ) )
+                           {
+                              status = true;
+                           }
+                           else
+                           {
+                              ossimNotify(ossimNotifyLevel_WARN)
+                                 << MODULE
+                                 << " WARNING:\nwriteGpkgNsgTileMatrixExtentTable call failed!"
+                                 << std::endl;
+                           }
+                        }
+                        else
+                        {
+                           ossimNotify(ossimNotifyLevel_WARN)
+                              << MODULE
+                              << " WARNING:\nwriteGpkgTileMatrixTable call failed!" << std::endl;
+                        }
+         
+                        ++zoomLevel;
+                        
+                        if ( zoomLevel != m_zoomLevels.end() )
+                        {
+                           gsd = gsd / 2.0;
+                           
+                           ossimDpt scale( 0.5, 0.5 );
+                           proj->applyScale( scale, true );
+                           proj->update();
+                        }
+                        
+                     } // Matches: while ( zoomLevel != zoomLevels.end() )
+
+                  } // Matches: if ( writeGpkgTileMatrixSetTable( m_db, m_outputRect ) )
+                  
+               } // Matches: if ( writeGpkgContentsTable( m_db, m_outputRect ) )
+            }
+            else
+            {
+               ossimNotify(ossimNotifyLevel_WARN)
+                  << "Must have at least one zoom level!"
+                  << "Set zoom_levels key in option keyword list."
+                  << "e.g. \"zoom_levels:()4,5,6,7,8,9,10,11\""
+                  << endl;
+            }
+         }
+      }
+   }
+   else if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_WARN) << "Non-grid-aligned mode not supported!\n";
+   }
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " exit status: " << (status?"true":"false") << std::endl;
+   }
+
+   return status;
+}
+
+void ossimGpkgWriter::close()
+{
+   if ( m_db )
+   {
+      sqlite3_close( m_db );
+      m_db = 0;
+   }
+   m_fullTileCodec    = 0;
+   m_partialTileCodec = 0;
+
+   // ??? : if ( m_pStmt ) finalizeTileProcessing()
+
+   m_pStmt = 0;
+   m_batchCount = 0;
+}
+
+bool ossimGpkgWriter::writeFile()
+{
+   static const char MODULE[] = "ossimGpkgWriter::writeFile";
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " entered..."
+         << "\nwriter options/settings:\n"
+         << *(m_kwl.get()) << "\n";
+   }
+   
+   bool status = false;
+   
+   m_batchSize = getBatchSize();
+   m_batchCount = 0;
+
+   try // Exceptions can be thrown...
+   {
+      if( theInputConnection.valid() && (getErrorStatus() == ossimErrorCodes::OSSIM_OK) )
+      {
+         //---
+         // To hold the original input to the image source sequencer. Only used
+         // if we mess with the input chain, e.g. add a scalar remapper.
+         //---
+         ossimRefPtr<ossimConnectableObject> originalSequencerInput = 0;
+
+         //---
+         // Set up input connection for eight bit if needed.
+         // Some writers, e.g. jpeg are only 8 bit.
+         //---
+         if ( (theInputConnection->getOutputScalarType() != OSSIM_UINT8) &&
+              requiresEightBit() )
+         {
+            originalSequencerInput = theInputConnection->getInput(0);
+
+            ossimRefPtr<ossimImageSource> sr = new ossimScalarRemapper();
+
+            // Connect scalar remapper to sequencer input.
+            sr->connectMyInputTo(0, theInputConnection->getInput(0));
+
+            // Connect sequencer to the scalar remapper.
+            theInputConnection->connectMyInputTo(0, sr.get());
+            theInputConnection->initialize();
+         }
+         
+         // Note only the master process used for writing...
+         if( theInputConnection->isMaster() )
+         {
+            if (!isOpen())
+            {
+               open();
+            }
+
+            if ( m_db )
+            {
+               status = createTables( m_db );
+            }
+
+            if ( status )
+            {
+               if ( keyIsTrue( ADD_LEVELS_KW ) )
+               {
+                  status = addLevels();
+               }
+               else
+               {
+                  status = writeEntry();
+               }
+            }
+            
+            close();
+         }
+         else // Matches: if( theInputConnection->isMaster() )
+         {
+            // Slave process only used to get tiles from the input.
+            theInputConnection->slaveProcessTiles();
+         }
+
+         // Reset the connection if needed.
+         if( originalSequencerInput.valid() )
+         {
+            theInputConnection->connectMyInputTo(0, originalSequencerInput.get());
+            originalSequencerInput = 0;   
+         }
+         
+      } // Matches: if ( theInputConnection.isValid() ... )
+   }
+   catch ( const ossimException& e )
+   {
+      ossimNotify(ossimNotifyLevel_WARN)
+         << MODULE << " Caught exception!\n"
+         << e.what()
+         << std::endl;
+      status = false;
+   }
+   catch ( ... )
+   {
+      ossimNotify(ossimNotifyLevel_WARN)
+         << MODULE << " Caught unknown exception!\n"
+         << std::endl;
+      status = false; 
+   }
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " exit status: " << (status?"true":"false") << std::endl;
+   }
+   
+   return status;
+   
+} // End: ossimGpkgWriter::writeFile
+
+bool ossimGpkgWriter::writeEntry()
+{
+   static const char MODULE[] = "ossimGpkgWriter::writeEntry";
+
+   bool status = false;
+
+   // Get the image geometry from the input.   
+   ossimRefPtr<ossimImageGeometry> geom = theInputConnection->getImageGeometry();
+   
+   // Input projection:
+   ossimRefPtr<ossimMapProjection> sourceProj = geom->getAsMapProjection();
+   
+   // Raw area of interest:
+   ossimIrect sourceAoi = getAreaOfInterest();
+   
+   if ( geom.valid() && sourceProj.valid() && (sourceAoi.hasNans() == false) )
+   {
+      ossimRefPtr<ossimMapProjection> productProjection =
+         getNewOutputProjection( geom.get() );
+      
+      if ( productProjection.valid() )
+      {
+         ossimDpt sourceGsd;
+         getGsd( productProjection.get(), sourceGsd );
+         
+         bool gridAligned = alignToGrid();
+         
+         if ( gridAligned &&
+              ( productProjection->getClassName() == "ossimUtmProjection" ) )
+         {
+            // Turn off grid alignment for utm.
+            if (traceDebug())
+            {
+               ossimNotify(ossimNotifyLevel_WARN)
+                  << MODULE << " WARNING!"
+                  << "\"align_to_grid\" option is invalid a UTM projection and is "
+                  << "being disabled..."
+                  << std::endl;
+            }
+            
+            m_kwl->addPair( ALIGN_TO_GRID_KW, std::string("0"), true );
+            gridAligned = false;
+         }
+         
+         // Initialize m_sceneBoundingRect:
+         initializeRect( sourceProj.get(), sourceAoi, m_sceneBoundingRect );
+
+         if ( gridAligned )
+         {
+            // Initialize m_projectionBoundingRect.  Only used if grid aligned.
+            initializeProjectionRect( productProjection.get() );
+         }
+
+         //---
+         // Set the initial tie point. will make the AOI come out
+         // (0,0) to (n,n). Needed for getExpandedAoi code. Requires
+         // m_sceneBoundingRect or m_projectionBoundingRect(grid aligned).
+         //---
+         setProjectionTie( productProjection.get() );
+         
+         if ( gridAligned )
+         {
+            // Set the clip rect.
+            m_clipRect = m_sceneBoundingRect.clipToRect( m_projectionBoundingRect );
+         }
+         else
+         {
+            m_clipRect = m_sceneBoundingRect;
+         }
+         
+         // Set tile size:
+         getTileSize( m_tileSize );
+         
+         // Set the sequence tile size:
+         theInputConnection->setTileSize( m_tileSize );
+         
+         // Get the first aoi from the clip rect.
+         ossimIrect aoi;
+         getAoiFromRect( productProjection.get(), m_clipRect, aoi );
+         
+         // Get the zoom levels to write:
+         ossimDpt fullResGsd;
+         std::vector<ossim_int32> zoomLevels;
+         getZoomLevels( productProjection.get(),
+                        aoi,
+                        sourceGsd,
+                        zoomLevels,
+                        fullResGsd );
+         
+         if ( zoomLevels.size() )
+         {
+            //---
+            // Start zoom level is full res.
+            // Stop zoom level is overview.
+            //---
+            
+            //---
+            // Set the initial full res scale:
+            // Must do this before the below call to
+            // "ossimMapProjection::applyScale"
+            //---
+            bool isGeographic = productProjection->isGeographic();
+            if ( isGeographic )
+            {
+               productProjection->setDecimalDegreesPerPixel( fullResGsd );
+            }
+            else
+            {
+               productProjection->setMetersPerPixel( fullResGsd );
+            }
+
+            // Recenter tie point after resolution change.
+            setProjectionTie( productProjection.get() );
+            
+            // Stop gsd:
+            ossimDpt stopGsd;
+            getGsd( fullResGsd,
+                    zoomLevels[zoomLevels.size()-1],
+                    zoomLevels[0],
+                    stopGsd );
+            
+            //---
+            // Set the scale of projection to the largest gsd before
+            // expanding AOI. This will also recenter projection tie
+            // for new gsd.
+            //---
+            applyScaleToProjection( productProjection.get(), stopGsd );
+
+            // propagate to chains.
+            setView( productProjection.get() );
+            
+            // New aoi at zoomed out level:
+            getAoiFromRect( productProjection.get(), m_clipRect, aoi );
+            
+            // Expand the AOI to even tile boundary:
+            ossimIrect expandedAoi;
+            getExpandedAoi( aoi, expandedAoi );
+            
+            initializeRect( productProjection.get(), expandedAoi, m_outputRect );
+            
+            if (traceDebug())
+            {
+               ossimNotify(ossimNotifyLevel_DEBUG)
+                  << "source aoi:     " << sourceAoi
+                  << "\nproduct aoi:  " << aoi
+                  << "\nexpanded aoi(last zoom level): " << expandedAoi
+                  << "\ngsd:          " << fullResGsd
+                  << "\nstop gsd:     " << stopGsd
+                  << "\ntile size:    " << m_tileSize
+                  << "\nscene rect:   " << m_sceneBoundingRect
+                  << "\nclip rect:    " << m_clipRect
+                  << "\noutput rect:  " << m_outputRect
+                  << "\n";
+               
+               if ( gridAligned )
+               {
+                  ossimNotify(ossimNotifyLevel_DEBUG)
+                     << "\nproj rect:    " << m_projectionBoundingRect << "\n";
+               }
+            }
+            
+            m_srs_id = writeGpkgSpatialRefSysTable( m_db, productProjection.get() );
+            if ( m_srs_id != -1 )
+            {
+               if ( writeGpkgContentsTable( m_db, m_outputRect ) )
+               {
+                  if ( writeGpkgTileMatrixSetTable( m_db, m_outputRect ) )
+                  {
+                     //---
+                     // Note:
+                     // Writer starts at "stop" zoom level(low res) and goes
+                     // to "start"(high res).  I know naming is confusing!
+                     //---
+                     writeZoomLevels( m_db,
+                                      productProjection.get(),
+                                      zoomLevels );
+                     status = true;
+                  }
+               }
+            }
+            
+         } // Matches: if ( zoomLevels.size() )
+         
+      } // Matches: if ( productProjection.valid() )
+      
+   } // Matches: if ( geom.valid() && ... )
+
+   return status;
+               
+} // End: ossimGpkgWriter::writeEntry()
+
+bool ossimGpkgWriter::addLevels()
+{
+   static const char MODULE[] = "ossimGpkgWriter::addLevels";
+
+   bool status = false;
+   
+   // Get the image geometry from the input.   
+   ossimRefPtr<ossimImageGeometry> geom = theInputConnection->getImageGeometry();
+   
+   // Input projection:
+   ossimRefPtr<ossimMapProjection> sourceProj = geom->getAsMapProjection();
+   
+   // Raw area of interest:
+   ossimIrect sourceAoi = getAreaOfInterest();
+   
+   if ( geom.valid() && sourceProj.valid() && (sourceAoi.hasNans() == false) )
+   {
+      ossimRefPtr<ossimMapProjection> productProjection =
+         getNewOutputProjection( geom.get() );
+      
+      if ( productProjection.valid() )
+      {
+         std::string tileTableName;
+         getTileTableName( tileTableName );
+         
+         ossimGpkgTileEntry entry;
+         if ( ossim_gpkg::getTileEntry( m_db, tileTableName, entry ) )
+         {
+            // productProjection must match what's already in there.
+            if ( entry.getSrs().m_organization_coordsys_id ==
+                 (ossim_int32)productProjection->getPcsCode() )
+            {
+               ossimDpt sourceGsd;
+               getGsd( productProjection.get(), sourceGsd );
+            
+               bool gridAligned = alignToGrid();
+               
+               if ( gridAligned &&
+                    ( productProjection->getClassName() == "ossimUtmProjection" ) )
+               {
+                  // Turn off grid alignment for utm.
+                  if (traceDebug())
+                  {
+                     ossimNotify(ossimNotifyLevel_WARN)
+                        << MODULE << " WARNING!"
+                        << "\"align_to_grid\" option is invalid a UTM projection and is "
+                        << "being disabled..."
+                        << std::endl;
+                  }
+                  
+                  m_kwl->addPair( ALIGN_TO_GRID_KW, std::string("0"), true );
+                  gridAligned = false;
+               }
+            
+               // Initialize m_sceneBoundingRect:
+               initializeRect( sourceProj.get(), sourceAoi, m_sceneBoundingRect );
+
+               if ( gridAligned )
+               {
+                  // Initialize m_projectionBoundingRect.  Only used if grid aligned.
+                  initializeProjectionRect( productProjection.get() );
+               }
+
+               //---
+               // Set the initial tie point. Requires m_sceneBoundingRect or
+               // m_projectionBoundingRect(grid aligned).
+               //---
+               setProjectionTie( productProjection.get() );
+
+               // Pull the output rect from the existing entry.
+               entry.getTileMatrixSet().getRect( m_outputRect );
+               
+               if ( gridAligned )
+               {
+                  // Set the clip rect.
+                  m_clipRect = m_sceneBoundingRect.clipToRect( m_projectionBoundingRect );
+               }
+               else
+               {
+                  m_clipRect = m_sceneBoundingRect;
+               }
+
+               // Final clip rect to existing entry.
+               m_clipRect = m_clipRect.clipToRect( m_outputRect );
+               
+               // Set tile size:
+               getTileSize( m_tileSize );
+               
+               // Set the sequence tile size:
+               theInputConnection->setTileSize( m_tileSize );
+               
+               // Get the first aoi from the clip rect.
+               ossimIrect aoi;
+               getAoiFromRect( productProjection.get(), m_clipRect, aoi );
+
+               // Get the current(existing) zoom levels from the entry.
+               std::vector<ossim_int32> currentZoomLevels;
+               entry.getZoomLevels( currentZoomLevels );
+               std::sort( currentZoomLevels.begin(), currentZoomLevels.end() );
+               
+               // Get the zoom levels to write:
+               ossimDpt fullResGsd;
+               std::vector<ossim_int32> zoomLevels;
+               getZoomLevels( productProjection.get(),
+                              aoi,
+                              sourceGsd,
+                              zoomLevels,
+                              fullResGsd );
+
+               // Sanity check.  Throws exception:
+               checkLevels( currentZoomLevels, zoomLevels );
+               
+               if ( zoomLevels.size() )
+               {
+                  //---
+                  // Start zoom level is full res.
+                  // Stop zoom level is overview.
+                  //---
+                  
+                  //---
+                  // Set the initial full res scale:
+                  // Must do this before the below call to
+                  // "ossimMapProjection::applyScale"
+                  //---
+                  bool isGeographic = productProjection->isGeographic();
+                  if ( isGeographic )
+                  {
+                     productProjection->setDecimalDegreesPerPixel( fullResGsd );
+                  }
+                  else
+                  {
+                     productProjection->setMetersPerPixel( fullResGsd );
+                  }
+
+                  // Recenter tie point after resolution change.
+                  setProjectionTie( productProjection.get() );
+                  
+                  // Stop gsd:
+                  ossimDpt stopGsd;
+                  getGsd( fullResGsd,
+                          zoomLevels[zoomLevels.size()-1],
+                          zoomLevels[0],
+                          stopGsd );
+
+                  //---
+                  // Set the scale of projection to the largest gsd before
+                  // expanding AOI. This will also recenter projection tie
+                  // for new gsd.
+                  //---
+                  applyScaleToProjection( productProjection.get(), stopGsd );
+                  
+                  // propagate to chains.
+                  setView( productProjection.get() );
+                  
+                  if (traceDebug())
+                  {
+                     ossimNotify(ossimNotifyLevel_DEBUG)
+                        << "source aoi:     " << sourceAoi
+                        << "\nproduct aoi:  " << aoi
+                        // << "\nexpanded aoi(last zoom level): " << expandedAoi
+                        << "\ngsd:          " << fullResGsd
+                        << "\nstop gsd:     " << stopGsd
+                        << "\ntile size:    " << m_tileSize
+                        << "\nscene rect:   " << m_sceneBoundingRect
+                        << "\nclip rect:    " << m_clipRect
+                        << "\noutput rect:  " << m_outputRect
+                        << "\n";
+                     
+                     if ( gridAligned )
+                     {
+                        ossimNotify(ossimNotifyLevel_DEBUG)
+                           << "\nproj rect:    " << m_projectionBoundingRect << "\n";
+                     }
+                  }
+                  
+                  //---
+                  // Note:
+                  // Writer starts at "stop" zoom level(low res) and goes
+                  // to "start"(high res).  I know naming is confusing!
+                  //---
+                  writeZoomLevels( m_db,
+                                   productProjection.get(),
+                                   zoomLevels );
+                  status = true;
+               
+               } // Matches: if ( zoomLevels.size() )
+
+            } // Matches: if ( entry.getSrs() ...
+            
+         } // Matches: if ( productProjection.valid() )
+         
+      } // Matches: if ( ossim_gpkg::getTileEntry( m_db, ... )
+      
+   } // Matches: if ( geom.valid() && ... )
+
+   return status;
+               
+} // End: ossimGpkgWriter::addLevels()
+
+void ossimGpkgWriter::writeZoomLevels( sqlite3* db,
+                                       ossimMapProjection* proj,
+                                       const std::vector<ossim_int32>& zoomLevels )
+// ossim_int32 fullResZoomLevel,
+//                                     ossim_int32 stopZoomLevel )
+
+{
+   static const char MODULE[] = "ossimGpkgWriter::writeZoomLevels";
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " entered..." << std::endl;
+   }
+   
+   if ( db && proj )
+   {
+      initializeCodec(); // Throws exception on error.
+      
+      ossimDpt gsd;
+      getGsd( proj, gsd );
+
+      // To communicate the percent complete.
+      ossim_float64 tilesWritten = 0.0;
+      ossim_float64 totalTiles   = 0.0;
+
+      std::vector<ossim_int32>::const_iterator zoomLevel = zoomLevels.begin();
+      while ( zoomLevel != zoomLevels.end() )
+      {
+         // Get the area of interest.
+         ossimIrect aoi;
+         getAoiFromRect( proj, m_outputRect, aoi );
+
+         // Clipped aoi:
+         ossimIrect clippedAoi;
+         getAoiFromRect( proj, m_clipRect, clippedAoi );
+
+         // Expanded to tile boundaries:
+         ossimIrect expandedAoi;
+         getExpandedAoi( aoi, expandedAoi );
+         
+         // Get the number of tiles:
+         ossimIpt matrixSize;
+         getMatrixSize( expandedAoi, matrixSize);
+         
+         if ( totalTiles < 1 )
+         {
+            //---
+            // First time through, compute total tiles for percent complete output.
+            // This will be inaccurate if user skips zoom levels for some reason.
+            //
+            // NOTE: Numbers get very large, i.e. billions of tiles.
+            // Was busting the int 32 boundary multiplying
+            // (matrixSize.x * matrixSize.y).
+            //---
+            ossim_float64 x = matrixSize.x;
+            ossim_float64 y = matrixSize.y;
+            totalTiles = x * y;
+            
+            ossim_int32 levels = zoomLevels.size();
+            if ( levels > 1 )
+            {
+               // Tile count doubles in each direction with each additional level.
+               ossim_int32 z = 1;
+               do
+               {
+                  x = x * 2.0;
+                  y = y * 2.0;
+                  totalTiles += (x * y);
+                  ++z;
+               } while ( z < levels );
+            }
+
+            if (traceDebug())
+            {
+               ossimNotify(ossimNotifyLevel_DEBUG)
+                  << "total tiles: " << totalTiles << "\n";
+            }
+         }
+         if (traceDebug())
+         {
+            ossimNotify(ossimNotifyLevel_DEBUG)
+               << "ossimGpkgWriter::writeZoomLevels DEBUG:"
+               << "\nlevel:       " << (*zoomLevel)
+               << "\ngsd:         " << gsd
+               << "\naoi:         " << aoi
+               << "\nclippedAoi:  " << clippedAoi
+               << "\nexpandedAoi: " << expandedAoi
+               << "\nmatrixSize:  " << matrixSize
+               << "\n";
+         }
+
+         if ( writeGpkgTileMatrixTable( db, (*zoomLevel), matrixSize, gsd ) )
+         {
+            
+            if ( writeGpkgNsgTileMatrixExtentTable( db, (*zoomLevel),
+                                                    expandedAoi, clippedAoi ) )
+            {
+               writeTiles( db, expandedAoi, (*zoomLevel), totalTiles, tilesWritten );
+               // writeZoomLevel( db, expandedAoi, (*zoomLevel), totalTiles, tilesWritten );
+            }
+            else
+            {
+               ossimNotify(ossimNotifyLevel_WARN)
+                  << MODULE
+                  << " WARNING:\nwriteGpkgNsgTileMatrixExtentTable call failed!" << std::endl;
+            }
+         }
+         else
+         {
+            ossimNotify(ossimNotifyLevel_WARN)
+               << MODULE
+               << " WARNING:\nwriteGpkgTileMatrixTable call failed!" << std::endl;
+         }
+         
+         if ( needsAborting() ) break;
+         
+         ++zoomLevel;
+         
+         if ( zoomLevel != zoomLevels.end() )
+         {
+            gsd = gsd / 2.0;
+            
+            ossimDpt scale( 0.5, 0.5 );
+            proj->applyScale( scale, true );
+            proj->update();
+            
+            // Propagate projection to chains and update aoi's of cutters.
+            setView( proj );
+         }
+         
+      } // Matches: while ( zoomLevel != zoomLevels.end() )
+      
+   } // Matches: if ( db && proj )
+   
+   if((m_batchCount < m_batchSize)&&(m_batchCount>0))
+   {
+      char * sErrMsg = 0;
+      sqlite3_exec(db, "END TRANSACTION", NULL, NULL, &sErrMsg);
+   }
+   
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << MODULE << " exited...\n";
+   }
+   
+} // ossimGpkgWriter::writeZoomLevels( ... )
+
+void ossimGpkgWriter::writeTiles( sqlite3* db,
+                                  const ossimIrect& aoi,
+                                  ossim_int32 zoomLevel,
+                                  const ossim_float64& totalTiles,
+                                  ossim_float64& tilesWritten )
+{
+   if ( db )
+   {
+      // Initialize the sequencer:
+      theInputConnection->setAreaOfInterest( aoi );
+      theInputConnection->setToStartOfSequence();
+
+      const ossim_int64 ROWS = (ossim_int64)(theInputConnection->getNumberOfTilesVertical());
+      const ossim_int64 COLS = (ossim_int64)(theInputConnection->getNumberOfTilesHorizontal());
+
+      char * sErrMsg = 0;
+      sqlite3_stmt* pStmt = 0; // The current SQL statement
+      std::ostringstream sql;
+      sql << "INSERT INTO " << m_tileTableName << "( zoom_level, tile_column, tile_row, tile_data ) VALUES ( "
+          << "?, " // 1: zoom level
+          << "?, " // 2: col
+          << "?, " // 3: row
+          << "?"   // 4: blob
+          << " )";
+      
+      if (traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG)
+            << "sql:\n" << sql.str() << "\n";
+      }
+      
+      int rc = sqlite3_prepare_v2(db,          // Database handle
+                                  sql.str().c_str(), // SQL statement, UTF-8 encoded
+                                  -1,          // Maximum length of zSql in bytes.
+                                  &pStmt,      // OUT: Statement handle
+                                  NULL);
+
+      bool writeBlanks = keyIsTrue( INCLUDE_BLANK_TILES_KW );
+
+      if(rc == SQLITE_OK)
+      {
+         for ( ossim_int64 row = 0; row < ROWS; ++row )
+         {
+            for ( ossim_int64 col = 0; col < COLS; ++col )
+            {
+               // Grab the tile.
+               ossimRefPtr<ossimImageData> tile = theInputConnection->getNextTile();
+               if ( tile.valid() )
+               {
+                  // Only write tiles that have data in them:
+                  if (tile->getDataObjectStatus() != OSSIM_NULL )
+                  {
+                     if( (tile->getDataObjectStatus() != OSSIM_EMPTY) || writeBlanks )
+                     {
+                        if(m_batchCount == 0)
+                        {
+                           sqlite3_exec(db, "BEGIN TRANSACTION", NULL, NULL, &sErrMsg);
+                        }
+
+                        writeTile( pStmt, db, tile, zoomLevel, row, col);//, quality );
+                        ++m_batchCount;
+
+                        if(m_batchCount == m_batchSize)
+                        {
+                           sqlite3_exec(db, "END TRANSACTION", NULL, NULL, &sErrMsg);
+                           m_batchCount = 0;
+                        }
+                     }
+                  }
+               }
+               else
+               {
+                  std::ostringstream errMsg;
+                  errMsg << "ossimGpkgWriter::writeTiles ERROR: "
+                         << "Sequencer returned null tile pointer for ("
+                         << col << ", " << row << ")";
+                  
+                  throw ossimException( errMsg.str() );
+               }
+
+               // Always increment the tiles written thing.
+               ++tilesWritten;
+
+               if ( needsAborting() ) break;
+               
+            } // End: col loop
+
+            setPercentComplete( (tilesWritten / totalTiles) * 100.0 );
+
+            if ( needsAborting() )
+            {
+               setPercentComplete( 100 );
+               break;
+            }
+             
+         } // End: row loop
+
+         sqlite3_finalize(pStmt);
+      }
+      else
+      {
+         ossimNotify(ossimNotifyLevel_WARN)
+              << "sqlite3_prepare_v2 error: " << sqlite3_errmsg(db) << std::endl;
+      }
+     
+   } // if ( db )
+
+} // End: ossimGpkgWriter::writeTiles( ... )
+
+void ossimGpkgWriter::writeTile( sqlite3_stmt* pStmt,
+                                 sqlite3* db,
+                                 ossimRefPtr<ossimImageData>& tile,
+                                 ossim_int32 zoomLevel,
+                                 ossim_int64 row,
+                                 ossim_int64 col )
+{
+   if ( db && tile.valid() )
+   {
+      std::vector<ossim_uint8> codecTile; // To hold the jpeg encoded tile.
+      bool encodeStatus;
+      std::string ext;
+      int mode = getWriterMode();
+
+      if ( tile->getDataObjectStatus() == OSSIM_FULL )
+      {
+         if ( m_fullTileCodecAlpha )
+         {
+            tile->computeAlphaChannel();
+         }
+         encodeStatus = m_fullTileCodec->encode(tile, codecTile);
+         if((mode == OSSIM_GPGK_WRITER_MODE_JPEG)||(mode == OSSIM_GPGK_WRITER_MODE_MIXED)) ext = ".jpg";
+         else ext = ".png";
+      }
+      else
+      {
+         if ( m_partialTileCodecAlpha )
+         {
+            tile->computeAlphaChannel();
+         }
+         encodeStatus = m_partialTileCodec->encode(tile, codecTile);
+         if(mode == OSSIM_GPGK_WRITER_MODE_JPEG) ext = ".jpg";
+         else ext = ".png";
+     }
+      
+      if ( encodeStatus )
+      {
+         // Insert into the database file(gpkg):
+         int rc = sqlite3_bind_int (pStmt, 1, zoomLevel);
+         rc |= sqlite3_bind_int (pStmt, 2, col);
+         rc |= sqlite3_bind_int (pStmt, 3, row);
+         rc |= sqlite3_bind_blob (pStmt,
+                                  4,
+                                  (void*)&codecTile.front(),
+                                  codecTile.size(),
+                                  SQLITE_TRANSIENT);
+         if (  rc == SQLITE_OK )
+         {
+            rc = sqlite3_step(pStmt);
+            if (  rc == SQLITE_OK )
+            {
+               ossimNotify(ossimNotifyLevel_WARN)
+                  << "sqlite3_step error: " << sqlite3_errmsg(db) << std::endl;
+            }
+            
+         }
+         else
+         {
+            ossimNotify(ossimNotifyLevel_WARN)
+               << "sqlite3_bind_blob error: " << sqlite3_errmsg(db) << std::endl;
+         }
+         
+         sqlite3_clear_bindings(pStmt);
+         sqlite3_reset(pStmt);
+      }
+      
+   } // Matches:  if ( db && tile.valid() )
+}
+
+void ossimGpkgWriter::writeCodecTile( sqlite3_stmt* pStmt,
+                                 sqlite3* db,
+                                 ossim_uint8* codecTile,
+                                 ossim_int32 codecTileSize,
+                                 ossim_int32 zoomLevel,
+                                 ossim_int64 row,
+                                 ossim_int64 col )
+{
+   if ( db && codecTile )
+   {
+      // Insert into the database file(gpkg):
+      int rc = sqlite3_bind_int (pStmt, 1, zoomLevel);
+      rc |= sqlite3_bind_int (pStmt, 2, col);
+      rc |= sqlite3_bind_int (pStmt, 3, row);
+      rc |= sqlite3_bind_blob (pStmt,
+                               4,
+                               (void*)codecTile,
+                               codecTileSize,
+                               SQLITE_TRANSIENT);
+      if (  rc == SQLITE_OK )
+      {
+         rc = sqlite3_step(pStmt);
+         if (  rc == SQLITE_OK )
+         {
+            ossimNotify(ossimNotifyLevel_WARN)
+               << "sqlite3_step error: " << sqlite3_errmsg(db) << std::endl;
+         }
+         
+      }
+      else
+      {
+         ossimNotify(ossimNotifyLevel_WARN)
+            << "sqlite3_bind_blob error: " << sqlite3_errmsg(db) << std::endl;
+      }
+      
+      sqlite3_clear_bindings(pStmt);
+      sqlite3_reset(pStmt);
+      
+   } // Matches:  if ( db && tile.valid() )
+}
+
+// For connectionless write tiles:
+ossim_int32 ossimGpkgWriter::beginTileProcessing()
+{
+   std::ostringstream sql;
+   sql << "INSERT INTO " << m_tileTableName << "( zoom_level, tile_column, tile_row, tile_data ) VALUES ( "
+       << "?, " // 1: zoom level
+       << "?, " // 2: col
+       << "?, " // 3: row
+       << "?"   // 4: blob
+       << " )";
+   
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "sql:\n" << sql.str() << "\n";
+   }
+   
+   return sqlite3_prepare_v2(m_db,              // Database handle
+                             sql.str().c_str(), // SQL statement, UTF-8 encoded
+                             -1,                // Maximum length of zSql in bytes.
+                             &m_pStmt,          // OUT: Statement handle
+                             NULL);
+}
+   
+// For connectionless write tiles:
+bool ossimGpkgWriter::writeTile( ossimRefPtr<ossimImageData>& tile,
+                                 ossim_int32 zoomLevel,
+                                 ossim_int64 row,
+                                 ossim_int64 col )
+{
+   bool status = false;
+
+   if ( tile.valid() )
+   {
+      // Check for valid zoom level:
+      if ( isValidZoomLevelRowCol( zoomLevel, row, col ) )
+      {
+ 
+         // Only write tiles that have data in them:
+         if (tile->getDataObjectStatus() != OSSIM_NULL )
+         {
+            if( (tile->getDataObjectStatus() != OSSIM_EMPTY) || m_writeBlanks )
+            {
+               char* sErrMsg = 0;
+               
+               if(m_batchCount == 0)
+               {
+                  sqlite3_exec(m_db, "BEGIN TRANSACTION", NULL, NULL, &sErrMsg);
+               }
+               
+               writeTile( m_pStmt, m_db, tile, zoomLevel, row, col);//, quality );
+               ++m_batchCount;
+               
+               if(m_batchCount == m_batchSize)
+               {
+                  sqlite3_exec(m_db, "END TRANSACTION", NULL, NULL, &sErrMsg);
+                  m_batchCount = 0;
+               }
+            }
+         }
+         
+         status = true;
+      }
+   }
+
+   return status;
+}
+
+bool ossimGpkgWriter::writeCodecTile(ossim_uint8* codecTile,
+                                     ossim_int32 codecTileSize,
+                                     ossim_int32 zoomLevel,
+                                     ossim_int64 row,
+                                     ossim_int64 col)
+{
+   bool status = true;
+
+   char* sErrMsg = 0;
+   
+   if(m_batchCount == 0)
+   {
+      sqlite3_exec(m_db, "BEGIN TRANSACTION", NULL, NULL, &sErrMsg);
+   }
+   
+   writeCodecTile( m_pStmt, m_db, codecTile, codecTileSize, zoomLevel, row, col);//, quality );
+   ++m_batchCount;
+   
+   if(m_batchCount == m_batchSize)
+   {
+      sqlite3_exec(m_db, "END TRANSACTION", NULL, NULL, &sErrMsg);
+      m_batchCount = 0;
+   }
+
+   return status;
+}
+void ossimGpkgWriter::finalizeTileProcessing()
+{
+   if ( m_batchCount )
+   {
+      char* sErrMsg = 0;
+      sqlite3_exec(m_db, "END TRANSACTION", NULL, NULL, &sErrMsg);
+      m_batchCount = 0;
+   }
+   
+   sqlite3_finalize(m_pStmt);
+   m_pStmt = 0;
+}
+   
+bool ossimGpkgWriter::createTables( sqlite3* db )
+{
+   bool status = false;
+   if ( ossimGpkgSpatialRefSysRecord::createTable( db ) )
+   {
+      if ( ossimGpkgContentsRecord::createTable( db ) )
+      {
+         if ( ossimGpkgTileMatrixSetRecord::createTable( db ) )
+         {
+            if ( ossimGpkgNsgTileMatrixExtentRecord::createTable( db ) )
+            {
+               if ( ossimGpkgTileMatrixRecord::createTable( db ) )
+               {
+                  getTileTableName(m_tileTableName);
+                  status = ossimGpkgTileRecord::createTable( db, m_tileTableName );
+               }
+            }
+         }
+      }
+   }
+   return status;
+}
+
+ossim_int32 ossimGpkgWriter::writeGpkgSpatialRefSysTable(
+   sqlite3* db, const ossimMapProjection* proj )
+{
+   //---
+   // NOTE: the "srs_id" is NOT synonomous with the m_organization_coordsys_id, e.g
+   // 4326.  We need this so that other records can tie themselves to the correct
+   // gpkg_spatial_ref_sys record.
+   //---
+   ossim_int32 srs_id = -1;
+   if ( db && proj )
+   {
+      ossimGpkgSpatialRefSysRecord record;
+      ossimGpkgSpatialRefSysRecord::InitCode returnCode = record.init( db, proj );
+      if ( returnCode == ossimGpkgSpatialRefSysRecord::OK )
+      {
+         if ( record.insert( db ) )
+         {
+            srs_id = record.m_srs_id;
+         }
+      }
+      else if ( returnCode == ossimGpkgSpatialRefSysRecord::OK_EXISTS )
+      {
+         // Record exists in database already(epsg:4326):
+         srs_id = record.m_srs_id;
+      }
+      else if ( returnCode == ossimGpkgSpatialRefSysRecord::ERROR )
+      {
+         ossimNotify(ossimNotifyLevel_WARN)
+            << "ossimGpkgWriter::writeGpkgSpatialRefSysTable ERROR initialized record!\n";
+      }
+   }
+   return srs_id;
+   
+} // End: ossimGpkgWriter::writeGpkgSpatialRefSysTable
+
+bool ossimGpkgWriter::writeGpkgContentsTable( sqlite3* db, const ossimDrect& rect )
+{
+   bool status = false;
+   if ( db )
+   {
+      ossimGpkgContentsRecord record;
+      ossimDpt minPt( rect.ul().x, rect.lr().y);
+      ossimDpt maxPt( rect.lr().x, rect.ul().y);
+
+      if ( record.init( m_tileTableName, m_srs_id, minPt, maxPt ) )
+      {
+         status = record.insert( db );
+      }  
+   }
+   return status;
+}
+
+bool ossimGpkgWriter::writeGpkgTileMatrixSetTable( sqlite3* db, const ossimDrect& rect )
+{
+   bool status = false;
+   if ( db )
+   {
+      ossimGpkgTileMatrixSetRecord record;
+      ossimDpt minPt( rect.ul().x, rect.lr().y);
+      ossimDpt maxPt( rect.lr().x, rect.ul().y);
+      
+      if ( record.init( m_tileTableName, m_srs_id, minPt, maxPt ) )
+      {
+         status = record.insert( db );
+      }  
+   }
+   return status;
+   
+} // End: ossimGpkgWriter::writeGpkgTileMatrixSetTable
+
+bool ossimGpkgWriter::writeGpkgTileMatrixTable( sqlite3* db,
+                                                ossim_int32 zoom_level,
+                                                const ossimIpt& matrixSize,
+                                                const ossimDpt& gsd )
+{
+   bool status = false;
+   if ( db )
+   {
+      ossimGpkgTileMatrixRecord record;
+      if ( record.init( m_tileTableName, zoom_level, matrixSize, m_tileSize, gsd ) )
+      {
+         status = record.insert( db );
+      }  
+   }
+   return status;
+   
+} // End: ossimGpkgWriter::writeGpkgTileMatrixTable
+
+bool ossimGpkgWriter::writeGpkgNsgTileMatrixExtentTable( sqlite3* db,
+                                                         ossim_int32 zoom_level,
+                                                         const ossimIrect& expandedAoi,
+                                                         const ossimIrect& clippedAoi )
+{
+   bool status = false;
+   if ( db )
+   {
+      // Compute the image rect:
+      ossimIrect imageRect( clippedAoi.ul().x - expandedAoi.ul().x,
+                            clippedAoi.ul().y - expandedAoi.ul().y,
+                            clippedAoi.lr().x - expandedAoi.ul().x,
+                            clippedAoi.lr().y - expandedAoi.ul().y );
+      
+      ossimGpkgNsgTileMatrixExtentRecord record;
+      if ( record.init( m_tileTableName, zoom_level, imageRect, m_clipRect ) )
+      {
+         status = record.insert( db );
+      } 
+   }
+   return status;
+   
+} // ossimGpkgWriter::writeGpkgNsgTileMatrixExtentTable( ... )
+
+bool ossimGpkgWriter::saveState(ossimKeywordlist& kwl, const char* prefix) const
+{
+   if ( m_kwl.valid() )
+   {
+      // Lazy man save state...
+      kwl.add( prefix, *(m_kwl.get()), true );
+   }
+   return ossimImageFileWriter::saveState(kwl, prefix);
+}
+
+bool ossimGpkgWriter::loadState(const ossimKeywordlist& kwl, const char* prefix) 
+{
+   if ( m_kwl.valid() )
+   {
+      ossimString regularExpression;
+      if ( prefix )
+      {
+         regularExpression = prefix;
+      }
+      
+      regularExpression += "*";
+      kwl.extractKeysThatMatch( *(m_kwl.get()), regularExpression );
+      
+      if ( prefix )
+      {
+         regularExpression = prefix;
+         m_kwl->stripPrefixFromAll( regularExpression );
+      }
+   }
+   
+   return ossimImageFileWriter::loadState(kwl, prefix);
+}
+
+void ossimGpkgWriter::getImageTypeList(std::vector<ossimString>& imageTypeList)const
+{
+   imageTypeList.push_back(ossimString("ossim_gpkg"));
+}
+
+ossimString ossimGpkgWriter::getExtension() const
+{
+   return ossimString("gpkg");
+}
+
+bool ossimGpkgWriter::hasImageType(const ossimString& imageType) const
+{
+   if ( (imageType == "ossim_gpkg") || (imageType == "image/gpkg") )
+   {
+      return true;
+   }
+
+   return false;
+}
+
+void ossimGpkgWriter::setProperty(ossimRefPtr<ossimProperty> property)
+{
+   if ( property.valid() )
+   {
+      // See if it's one of our properties:
+      std::string key = property->getName().string();
+      if ( ( key == ADD_ALPHA_CHANNEL_KW ) ||
+           ( key == ADD_ENTRY_KW ) ||
+           ( key == ADD_LEVELS_KW ) ||
+           ( key == ALIGN_TO_GRID_KW ) ||
+           ( key == APPEND_KW ) ||           
+           ( key == BATCH_SIZE_KW ) ||
+           ( key == COMPRESSION_LEVEL_KW ) ||
+           ( key == ossimKeywordNames::COMPRESSION_QUALITY_KW ) ||
+           ( key == EPSG_KW ) ||
+           ( key == INCLUDE_BLANK_TILES_KW ) ||
+           ( key == TILE_SIZE_KW ) ||
+           ( key == TILE_TABLE_NAME_KW ) ||           
+           ( key == WRITER_MODE_KW ) ||
+           ( key == ZOOM_LEVELS_KW ) )
+      {
+         ossimString value;
+         property->valueToString(value);
+         m_kwl->addPair( key, value.string(), true );
+      }
+      else
+      {
+         ossimImageFileWriter::setProperty(property);
+      }
+   }
+}
+
+ossimRefPtr<ossimProperty> ossimGpkgWriter::getProperty(const ossimString& name)const
+{
+   ossimRefPtr<ossimProperty> prop = 0;
+   prop = ossimImageFileWriter::getProperty(name);
+   return prop;
+}
+
+void ossimGpkgWriter::getPropertyNames(std::vector<ossimString>& propertyNames)const
+{
+   propertyNames.push_back(ossimString(ADD_ALPHA_CHANNEL_KW));
+   propertyNames.push_back(ossimString(ADD_ENTRY_KW));
+   propertyNames.push_back(ossimString(ADD_LEVELS_KW));      
+   propertyNames.push_back(ossimString(ALIGN_TO_GRID_KW));
+   propertyNames.push_back(ossimString(APPEND_KW));   
+   propertyNames.push_back(ossimString(BATCH_SIZE_KW));
+   propertyNames.push_back(ossimString(COMPRESSION_LEVEL_KW));
+   propertyNames.push_back(ossimString(ossimKeywordNames::COMPRESSION_QUALITY_KW));
+   propertyNames.push_back(ossimString(EPSG_KW));
+   propertyNames.push_back(ossimString(INCLUDE_BLANK_TILES_KW));
+   propertyNames.push_back(ossimString(TILE_SIZE_KW));
+   propertyNames.push_back(ossimString(TILE_TABLE_NAME_KW));
+   propertyNames.push_back(ossimString(WRITER_MODE_KW));
+   propertyNames.push_back(ossimString(ZOOM_LEVELS_KW));
+
+   ossimImageFileWriter::getPropertyNames(propertyNames);
+}
+
+void ossimGpkgWriter::setCompressionQuality(  const std::string& quality )
+{
+   m_kwl->addPair( std::string(ossimKeywordNames::COMPRESSION_QUALITY_KW),
+                   quality );
+}
+
+ossim_uint32 ossimGpkgWriter::getCompressionQuality() const
+{
+   ossim_uint32 quality = 0;
+   std::string value = m_kwl->findKey( std::string(ossimKeywordNames::COMPRESSION_QUALITY_KW) );
+   if ( value.size() )
+   {
+      quality = ossimString(value).toUInt32();
+   }
+   return quality;
+}
+
+ossimString ossimGpkgWriter::getCompressionLevel() const
+{
+   ossimString result = ossimString("z_default_compression");
+#if 0
+   switch (theCompressionLevel)
+   {
+      case Z_NO_COMPRESSION:
+         result = ossimString("z_no_compression");
+         break;
+         
+      case Z_BEST_SPEED:
+         result = ossimString("z_best_speed");
+         break;
+         
+      case Z_BEST_COMPRESSION:
+         result = ossimString("z_best_compression");
+         break;
+
+      default:
+         break;
+   }
+#endif
+   return result;
+}
+
+bool ossimGpkgWriter::setCompressionLevel(const ossimString& /* level */ )
+{
+   bool status = true;
+#if 0
+   ossimString s = level;
+   s.downcase();
+
+   if(s == "z_no_compression")
+   {
+      theCompressionLevel = Z_NO_COMPRESSION;
+   }
+   else if(s == "z_best_speed")
+   {
+      theCompressionLevel = Z_BEST_SPEED;
+   }
+   else if(s == "z_best_compression")
+   {
+      theCompressionLevel = Z_BEST_COMPRESSION;
+   }
+   else if(s == "z_default_compression")
+   {
+      theCompressionLevel = Z_DEFAULT_COMPRESSION;
+   }
+   else
+   {
+      status = false;
+   }
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "DEBUG:"
+         << "\nossimGpkgWriter::setCompressionLevel DEBUG"
+         << "passed in level:  " << level.c_str()
+         << "writer level: " << getCompressionLevel().c_str()
+         << std::endl;
+   }
+#endif
+   return status;
+}
+
+void ossimGpkgWriter::getGsd( const ossimDpt& fullResGsd,
+                              ossim_int32 fullResZoomLevel,
+                              ossim_int32 currentZoomLevel,
+                              ossimDpt& gsd )
+{
+   if ( fullResGsd.hasNans() == false )
+   {
+      double delta = fullResZoomLevel - currentZoomLevel;
+      if ( delta > 0 )
+      {
+         gsd = fullResGsd * ( std::pow( 2.0, delta ) );
+      }
+      else if ( delta < 0 )
+      {
+         gsd = fullResGsd / ( std::pow( 2, std::fabs(delta) ) );
+      }
+      else
+      {
+         gsd = fullResGsd;
+      }
+   }
+}
+
+void ossimGpkgWriter::getGsd( const ossimMapProjection* proj,
+                              ossimDpt& gsd ) const
+{
+   if ( proj )
+   {
+      if ( proj->isGeographic() )
+      {
+         gsd = proj->getDecimalDegreesPerPixel();
+      }
+      else
+      {
+         gsd = proj->getMetersPerPixel();
+      }  
+   }
+}
+
+void ossimGpkgWriter::getGsd( const ossimImageGeometry* geom,
+                              ossimDpt& gsd ) const
+{
+   if ( geom )
+   {
+      const ossimMapProjection* proj = geom->getAsMapProjection();
+      if ( proj )
+      {
+         if ( proj->isGeographic() )
+         {
+            geom->getDegreesPerPixel( gsd );
+         }
+         else
+         {
+            geom->getMetersPerPixel( gsd );
+         }
+      }
+   }
+}
+
+void ossimGpkgWriter::getGsd(
+   const ossimMapProjection* proj, ossim_int32 zoomLevel, ossimDpt& gsd ) const
+{
+   if ( proj )
+   {
+      if ( alignToGrid() )
+      {
+         ossimDpt dims;
+         if ( proj->isGeographic() )
+         {
+            dims.x = 360.0;
+            dims.y = 180.0;
+
+            gsd.x = 360.0/(m_tileSize.x*2);
+            gsd.y = 180.0/m_tileSize.y;
+               
+         }
+         else
+         {
+            getProjectionDimensionsInMeters( proj, dims );
+
+            // Gsd that puts Earth in one tile:
+            gsd.x = dims.x/m_tileSize.x;
+            gsd.y = dims.y/m_tileSize.y;
+         }
+
+         if ( zoomLevel )
+         {
+            gsd = gsd / ( std::pow( 2.0, zoomLevel ) );
+         }
+      }
+      else
+      {
+         gsd.makeNan();
+         
+         // Error message??? (drb)
+      }
+   }
+}
+
+bool ossimGpkgWriter::alignToGrid() const
+{
+   return keyIsTrue( ALIGN_TO_GRID_KW );
+}
+
+bool ossimGpkgWriter::append() const
+{
+   return ( keyIsTrue( ADD_ENTRY_KW ) || keyIsTrue( ADD_LEVELS_KW ) || keyIsTrue( APPEND_KW ) );
+}
+
+bool ossimGpkgWriter::keyIsTrue( const std::string& key ) const
+{ 
+   bool result = false;
+   std::string value = m_kwl->findKey( key );
+   if ( value.size() )
+   {
+      result = ossimString(value).toBool();
+   }
+   return result;
+}
+
+void ossimGpkgWriter::setView( ossimMapProjection* proj )
+{
+   if ( theInputConnection.valid() && proj )
+   {
+      ossimTypeNameVisitor visitor( ossimString("ossimViewInterface"),
+                                    false, // firstofTypeFlag
+                                    (ossimVisitor::VISIT_INPUTS|
+                                     ossimVisitor::VISIT_CHILDREN) );
+      theInputConnection->accept( visitor );
+      if ( visitor.getObjects().size() )
+      {
+         for( ossim_uint32 i = 0; i < visitor.getObjects().size(); ++i )
+         {
+            ossimViewInterface* viewClient = visitor.getObjectAs<ossimViewInterface>( i );
+            if (viewClient)
+            {
+               viewClient->setView( proj );
+            }
+         }
+
+         //---
+         // After a view change the combiners must reset their input rectangles
+         // for each image.
+         //---
+         reInitializeCombiners();
+
+         //---
+         // Cutter, if present, must be updated since the view has been
+         // changed and the cutter's AOI is no longer relative.  Note 
+         // the original AOI was already saved for our writer.
+         //---
+         reInitializeCutters( proj );
+         
+         theInputConnection->initialize();
+      }
+   }
+}
+
+void ossimGpkgWriter::reInitializeCombiners()
+{
+   if ( theInputConnection.valid() )
+   {
+      ossimTypeNameVisitor visitor( ossimString("ossimImageCombiner"),
+                                    false, // firstofTypeFlag
+                                    (ossimVisitor::VISIT_INPUTS|
+                                     ossimVisitor::VISIT_CHILDREN) );
+
+      theInputConnection->accept( visitor );
+      if ( visitor.getObjects().size() )
+      {
+         for( ossim_uint32 i = 0; i < visitor.getObjects().size(); ++i )
+         {
+            ossimImageCombiner* combiner = visitor.getObjectAs<ossimImageCombiner>( i );
+            if (combiner)
+            {
+               combiner->initialize();
+            }
+         }
+      }
+   }
+}
+
+void ossimGpkgWriter::reInitializeCutters( const ossimMapProjection* proj )
+{
+   if ( theInputConnection.valid() && proj )
+   {
+      ossimTypeNameVisitor visitor( ossimString("ossimRectangleCutFilter"),
+                                    false, // firstofTypeFlag
+                                    (ossimVisitor::VISIT_INPUTS|
+                                     ossimVisitor::VISIT_CHILDREN) );
+
+      theInputConnection->accept( visitor );
+      if ( visitor.getObjects().size() )
+      {
+         ossimIrect rect;
+         getAoiFromRect( proj, m_clipRect, rect );
+         
+         for( ossim_uint32 i = 0; i < visitor.getObjects().size(); ++i )
+         {
+            ossimRectangleCutFilter* cutter = visitor.getObjectAs<ossimRectangleCutFilter>( i );
+            if (cutter)
+            {
+               // Set the clip rect of the cutter.
+               cutter->setRectangle(rect);
+
+               // Enable the getTile...
+               cutter->setEnableFlag( true );
+            }
+         }
+      }
+   }
+}
+
+ossimRefPtr<ossimMapProjection> ossimGpkgWriter::getNewOutputProjection(
+   ossimImageGeometry* geom ) const
+{
+   ossimRefPtr<ossimMapProjection> proj = 0;
+
+   if ( geom )
+   {
+      // "epsg" is a writer prop so check for it.  This overrides the input projection.
+      proj = getNewOutputProjection();
+
+      if ( proj.valid() == false )
+      {
+         ossimRefPtr<ossimMapProjection> sourceProj = geom->getAsMapProjection();
+         if ( sourceProj.valid() )
+         {
+            // Check the input projection.  This could have been set by the caller.
+            if ( sourceProj->getClassName() == "ossimEquDistCylProjection" )
+            {
+               // This will be an equdist with origin at 0, 0.
+               proj = getNewGeographicProjection();
+            }
+            else if ( sourceProj->getClassName() == "ossimMercatorProjection" )
+            {
+               // WGS 84 / World Mercator:
+               proj = getNewWorldMercatorProjection();
+            }
+            else if ( sourceProj->getClassName() == "ossimGoogleProjection" )
+            {
+               proj = new ossimGoogleProjection(); // sourceProj;
+            }
+            else if ( sourceProj->getClassName() == "ossimUtmProjection" )
+            {
+               proj = dynamic_cast<ossimMapProjection*>(sourceProj->dup());
+            }
+         }
+
+         // Final default:
+         if ( proj.valid() == false )
+         {
+            //---
+            // DEFAULT: Geographic, WGS 84
+            // Note: May need to switch default to ossimMercatorProjection:
+            //---
+            proj = getNewGeographicProjection();
+         }
+      }
+
+      if ( proj.valid() )
+      {
+         bool isGeographic = proj->isGeographic();
+         bool gridAligned = alignToGrid();
+
+         // Set the gsd:
+         ossimDpt fullResGsd;
+         getGsd( geom, fullResGsd );
+         
+         if ( isGeographic )
+         {
+            if ( gridAligned )
+            {
+               // Make pixels square if not already.
+               if ( fullResGsd.y < fullResGsd.x )
+               {
+                  fullResGsd.x = fullResGsd.y;
+               }
+               else if ( fullResGsd.x < fullResGsd.y )
+               {
+                  fullResGsd.y = fullResGsd.x; 
+               }
+            }
+            proj->setDecimalDegreesPerPixel( fullResGsd );
+         }
+         else
+         {
+            if ( gridAligned && (proj->getClassName() == "ossimUtmProjection" ) )
+            {
+               // Turn off grid alignment for utm.
+               gridAligned = false;
+            }
+            
+            if ( gridAligned )
+            {
+               // Make pixels square if not already.
+               if ( fullResGsd.y < fullResGsd.x )
+               {
+                  fullResGsd.x = fullResGsd.y;
+               }
+               else if ( fullResGsd.x < fullResGsd.y )
+               {
+                  fullResGsd.y = fullResGsd.x; 
+               }
+            }
+            proj->setMetersPerPixel( fullResGsd );
+         }
+      }
+      
+   } // Matches: if ( geom )
+   
+   return proj;
+   
+} // End: ossimGpkgWriter::getNewOutputProjection( geom )
+
+ossimRefPtr<ossimMapProjection> ossimGpkgWriter::getNewOutputProjection() const
+{
+   ossimRefPtr<ossimMapProjection> proj = 0;
+
+   // "epsg" is a writer prop so check for it.  This overrides the input projection.
+   ossim_uint32 epsgCode = getEpsgCode();
+   if ( epsgCode )
+   {
+      if ( epsgCode ==  4326 )
+      {
+         // Geographic, WGS 84
+         proj = getNewGeographicProjection();
+      }
+      else if ( epsgCode == 3395 )
+      {
+         // WGS 84 / World Mercator:
+         proj = getNewWorldMercatorProjection();
+      }
+      else if ( ( epsgCode == 3857 ) || ( epsgCode == 900913) )
+      {
+         proj = new ossimGoogleProjection();
+      }
+      else
+      {
+         // Go to the factory:
+         ossimString name = "EPSG:";
+         name += ossimString::toString(epsgCode);
+         ossimRefPtr<ossimProjection> proj =
+            ossimEpsgProjectionFactory::instance()->createProjection(name);
+         if ( proj.valid() )
+         {
+            proj = dynamic_cast<ossimMapProjection*>( proj.get() );
+         }
+      }
+   }
+
+   return proj;
+   
+} // End: ossimGpkgWriter::getNewOutputProjection()
+
+ossimRefPtr<ossimMapProjection> ossimGpkgWriter::getNewGeographicProjection() const
+{
+   // Geographic, WGS 84, with origin at 0,0 for square pixels in decimal degrees.
+   ossimRefPtr<ossimMapProjection> result =
+      new ossimEquDistCylProjection(
+         ossimEllipsoid(),
+         ossimGpt(0.0, 0.0, 0.0, ossimDatumFactory::instance()->wgs84()) );
+   return result;
+}
+
+ossimRefPtr<ossimMapProjection> ossimGpkgWriter::getNewWorldMercatorProjection() const
+{
+   // EPSG: 3395, "WGS 84 / World Mercator", with origin at 0,0.
+   ossimRefPtr<ossimMapProjection> result =
+      new ossimMercatorProjection(
+         ossimEllipsoid(),
+         ossimGpt(0.0, 0.0, 0.0, ossimDatumFactory::instance()->wgs84()) );
+
+   // Set the pcs(epsg) code:
+   result->setPcsCode( 3395 );
+   
+   return result;
+}
+
+void ossimGpkgWriter::getTileSize( ossimIpt& tileSize ) const
+{
+   std::string value = m_kwl->findKey( TILE_SIZE_KW );
+   if ( value.size() )
+   {
+      tileSize.toPoint( value );
+   }
+   else
+   {
+      ossim::defaultTileSize( tileSize );
+   }
+}
+
+ossim_uint64 ossimGpkgWriter::getBatchSize() const
+{
+   ossim_uint64 size = 32; // ???
+   std::string value = m_kwl->findKey( BATCH_SIZE_KW );
+   if ( value.size() )
+   {
+      size = ossimString(value).toUInt64();
+   }
+   return size;
+}
+
+void ossimGpkgWriter::getZoomLevels( std::vector<ossim_int32>& zoomLevels ) const
+{
+   std::string value = m_kwl->findKey( ZOOM_LEVELS_KW );
+   if ( value.size() )
+   {
+      ossimString stringOfPoints(value);
+      if ( ossim::toSimpleVector(zoomLevels, stringOfPoints) )
+      {
+         std::sort( zoomLevels.begin(), zoomLevels.end() );
+
+         // Check for negative and disallow.
+         if ( zoomLevels[0] < 0 )
+         {
+            zoomLevels.clear();
+
+            // Warning message???
+         }
+      }
+      else
+      {
+         zoomLevels.clear();
+      }
+   }
+   else
+   {
+      zoomLevels.clear();
+   }
+}
+
+
+void ossimGpkgWriter::getZoomLevels( const ossimMapProjection* proj,
+                                     const ossimIrect& aoi,
+                                     const ossimDpt& sourceGsd,
+                                     std::vector<ossim_int32>& zoomLevels,
+                                     ossimDpt& fullResGsd ) const
+{
+   if ( proj && (aoi.hasNans() == false) )
+   {
+      // Initial assignment of full res gsd. Will change if aligned to grid is on.
+      fullResGsd = sourceGsd;
+      
+      // Check for user specified levels.
+      getZoomLevels( zoomLevels );
+      
+      if ( zoomLevels.size() )
+      {
+         if ( alignToGrid() )
+         {
+            ossim_int32 zoomLevel = zoomLevels[zoomLevels.size()-1];
+            if ( proj->isGeographic() )
+            {
+               fullResGsd.x = 360.0/(m_tileSize.x*2);
+               fullResGsd.y = 180.0/m_tileSize.y;
+            }
+            else
+            {
+               ossimDpt dims;
+               getProjectionDimensionsInMeters( proj, dims );
+               
+               // Gsd that puts Earth in one tile:
+               fullResGsd.x = dims.x/m_tileSize.x;
+               fullResGsd.y = dims.y/m_tileSize.y;
+            }
+
+            if ( zoomLevel )
+            {
+               fullResGsd = fullResGsd / ( std::pow( 2.0, zoomLevel ) );
+            }
+         }
+      }
+      else
+      {
+         ossim_int32 levels = getNumberOfZoomLevels( aoi );
+         if ( levels )
+         {
+            if ( alignToGrid() )
+            {
+               ossimDpt zoomGsd;
+               
+               if ( proj->isGeographic() )
+               {
+                  zoomGsd.x = 360.0/(m_tileSize.x*2);
+                  zoomGsd.y = 180.0/m_tileSize.y;
+               }
+               else
+               {
+                  ossimDpt dims;
+                  getProjectionDimensionsInMeters( proj, dims );
+                  
+                  // Gsd that puts Earth in one tile:
+                  zoomGsd.x = dims.x/m_tileSize.x;
+                  zoomGsd.y = dims.y/m_tileSize.y;
+               }
+               
+               if ( fullResGsd.hasNans() == false )
+               {
+                  // If zoom level gsd is below this threshold we stop there.
+                  ossimDpt gsdThreshold = fullResGsd * 1.5;
+                  
+                  // Start full Earth in 2x1 tiles:
+                  ossim_int32 startZoomLevel = 0;
+                  while ( ( zoomGsd.x > gsdThreshold.x ) &&
+                          ( zoomGsd.y > gsdThreshold.y ) )
+                  {
+                     // Go to next level.
+                     zoomGsd = zoomGsd/2.0;
+                     fullResGsd = zoomGsd;
+                     ++startZoomLevel;
+                  }
+                  
+                  ossim_int32 stopZoomLevel = startZoomLevel-(levels-1);
+                  
+                  if ( stopZoomLevel < 0 ) stopZoomLevel = 0;
+                  
+                  for ( ossim_int32 i = stopZoomLevel; i <= startZoomLevel; ++i )
+                  {
+                     zoomLevels.push_back(i);
+                  }
+               }
+            }
+            else // Not grid aligned.
+            {
+               //---
+               // If not grid aligned the full res gsd is the inputs which is
+               // already set.
+               //---
+               for ( ossim_int32 i = 0; i < levels; ++i )
+               {
+                  zoomLevels.push_back(i);
+               }
+            }          
+         }
+      }
+   }
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimGpkgWriter::getZoomLevels DEBUG"
+         << "aoi: " << aoi << "\n"
+         << "sourceGsd: " << sourceGsd << "\n"
+         << "\nfullResGsd:     " << fullResGsd << "\n"
+         << "levels: (";
+      std::vector<ossim_int32>::const_iterator i = zoomLevels.begin();
+      while ( i != zoomLevels.end() )
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG) << (*i);
+         ++i;
+         if ( i != zoomLevels.end() )
+         {
+            ossimNotify(ossimNotifyLevel_DEBUG) << ",";
+         }
+         else
+         {
+            ossimNotify(ossimNotifyLevel_DEBUG) << ")\n";
+         }
+      }
+   }
+   
+} // End: ossimGpkgWriter::getZoomLevels( proj, aoi, ... )
+
+ossim_int32 ossimGpkgWriter::getNumberOfZoomLevels( const ossimIrect& aoi ) const
+{
+   ossim_int32 result = 0;
+
+   if ( aoi.hasNans() == false )
+   {
+      ossim_float64 w = aoi.width();
+      ossim_float64 h = aoi.height();
+
+      // Take it down to at least a quarter of a tile.
+      const ossim_float64 TW = m_tileSize.x/4;
+      const ossim_float64 TH = m_tileSize.y/4;
+      if ( w && h )
+      {
+         ++result; // At least one level.
+         while ( ( TW < w ) && ( TH < h ) )
+         {
+            w /= 2.0;
+            h /= 2.0;
+            ++result;
+         }
+      }
+   }
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimGpkgWriter::getNumberOfZoomLevels DEBUG"
+         << "\nlevels: " << result << "\n";
+   }
+   
+   return result;
+}
+
+void ossimGpkgWriter::getAoiFromRect( const ossimMapProjection* proj,
+                                      const ossimDrect& rect,
+                                      ossimIrect& aoi )
+{
+   static const char MODULE[] = "ossimGpkgWriter::getAoi";
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " entered...\n";
+   }
+   
+   // Take the aoi edges(minPt, maxPt), shift to center pixel and return the aoi.
+   if ( proj )
+   {
+      ossimDpt gsd;
+      getGsd( proj, gsd );
+      ossimDpt halfGsd = gsd/2.0;
+      
+      if (traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG) << "gsd: " << gsd << "\n";
+      }
+
+      ossimDpt ulDpt;
+      ossimDpt lrDpt;
+      
+      if ( proj->isGeographic() )
+      {
+         // Convert the ground points to view space.
+         ossimGpt ulGpt( rect.ul().y-halfGsd.y, rect.ul().x+halfGsd.x, 0.0 );
+         ossimGpt lrGpt( rect.lr().y+halfGsd.y, rect.lr().x-halfGsd.x, 0.0 );
+
+         // Get the view coords of the aoi.
+         proj->worldToLineSample(ulGpt, ulDpt);
+         proj->worldToLineSample(lrGpt, lrDpt);
+
+         if (traceDebug())
+         {
+            ossimNotify(ossimNotifyLevel_DEBUG)
+               << "\nulGpt: " << ulGpt
+               << "\nlrGpt: " << lrGpt
+               << "\nulDpt: " << ulDpt
+               << "\nlrDpt: " << lrDpt
+               << "\n";
+         }
+      }
+      else
+      {
+         ossimDpt ulEnPt( rect.ul().x+halfGsd.x, rect.ul().y-halfGsd.y );
+         ossimDpt lrEnPt( rect.lr().x-halfGsd.x, rect.lr().y+halfGsd.y );
+
+         // Get the view coords of the aoi.
+         proj->eastingNorthingToLineSample( ulEnPt, ulDpt );
+         proj->eastingNorthingToLineSample( lrEnPt, lrDpt );
+      }
+
+      // Area of interest in view space on point boundaries.
+      aoi = ossimIrect( ossimIpt(ulDpt), ossimIpt(lrDpt) );
+
+      if (traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG)
+            << "aoi: " << aoi << "\n"
+            << MODULE << " exited...\n";
+      }
+   }
+   
+} // End: ossimGpkgWriter::getAoiFromRect( ... )
+
+void ossimGpkgWriter::getExpandedAoi( const ossimIrect& aoi,
+                                      ossimIrect& expandedAoi ) const
+{
+   expandedAoi = aoi;
+   expandedAoi.stretchToTileBoundary( m_tileSize );
+}
+
+void ossimGpkgWriter::getMatrixSize(
+   const ossimIrect& rect, ossimIpt& matrixSize ) const
+{
+   matrixSize.x = rect.width()/m_tileSize.x;
+   if ( rect.width() % m_tileSize.x )
+   {
+      ++matrixSize.x;
+   }
+   matrixSize.y = rect.height()/m_tileSize.y;
+   if ( rect.height() % m_tileSize.y )
+   {
+      ++matrixSize.y;
+   }
+}
+
+void ossimGpkgWriter::setProjectionTie( ossimMapProjection* proj ) const
+{
+   if ( proj )
+   {
+      ossimDpt gsd;
+      getGsd( proj, gsd );
+      ossimDpt halfGsd = gsd/2.0;
+      
+      bool gridAligned = alignToGrid();
+      bool isGeographic = proj->isGeographic();
+      if ( isGeographic )
+      {
+         ossimGpt tie(0.0, 0.0, 0.0);
+         if ( gridAligned )
+         {
+            tie.lon = m_projectionBoundingRect.ul().x + halfGsd.x;
+            tie.lat = m_projectionBoundingRect.ul().y - halfGsd.y;
+         }
+         else
+         {
+            tie.lon = m_sceneBoundingRect.ul().x + halfGsd.x;
+            tie.lat = m_sceneBoundingRect.ul().y - halfGsd.y;
+         }
+         proj->setUlTiePoints(tie);
+         
+         if ( traceDebug() )
+         {
+            ossimNotify(ossimNotifyLevel_DEBUG)
+               << "ossimGpkgWriter::setProjectionTie DEBUG:\n"
+               << "tie: " << tie << std::endl;
+         }
+      }
+      else
+      {
+         ossimDpt tie( 0.0, 0.0 );
+         if ( gridAligned )
+         {
+            tie.x = m_projectionBoundingRect.ul().x + halfGsd.x;
+            tie.y = m_projectionBoundingRect.ul().y - halfGsd.y;
+         }
+         else
+         {
+            tie.x = m_sceneBoundingRect.ul().x + halfGsd.x;
+            tie.y = m_sceneBoundingRect.ul().y - halfGsd.y;
+         }
+         
+         proj->setUlTiePoints(tie);
+
+         if ( traceDebug() )
+         {
+            ossimNotify(ossimNotifyLevel_DEBUG)
+               << "ossimGpkgWriter::setProjectionTie DEBUG:\n"
+               << "tie: " << tie << std::endl;
+         }
+      }
+   }
+   
+} // End: ossimGpkgWriter::setProjectionTie
+
+ossimGpkgWriter::ossimGpkgWriterMode ossimGpkgWriter::getWriterMode() const
+{
+   // Default to mixed.
+   ossimGpkgWriterMode mode = OSSIM_GPGK_WRITER_MODE_MIXED;
+   
+   std::string value = m_kwl->findKey( WRITER_MODE_KW );
+   if ( value.size() )
+   {
+      ossimString os(value);
+      os.downcase();
+      
+      if ( os == "jpeg" )
+      {
+         mode = OSSIM_GPGK_WRITER_MODE_JPEG;
+      }
+      else if ( os == "png" )
+      {
+         mode = OSSIM_GPGK_WRITER_MODE_PNG;
+      }
+      else if ( os == "pnga" )
+      {
+         mode = OSSIM_GPGK_WRITER_MODE_PNGA;
+      }
+   }
+   return mode;
+}
+
+std::string ossimGpkgWriter::getWriterModeString( ossimGpkgWriterMode mode ) const
+{
+   std::string result;
+   switch ( mode )
+   {
+      case OSSIM_GPGK_WRITER_MODE_JPEG:
+      {
+         result = "jpeg";
+         break;
+      }
+      case OSSIM_GPGK_WRITER_MODE_MIXED:
+      {
+         result = "mixed";
+         break;
+      }
+      case OSSIM_GPGK_WRITER_MODE_PNG:
+      {
+         result = "png";
+         break;
+      }
+      case OSSIM_GPGK_WRITER_MODE_PNGA:
+      {
+         result = "pnga";
+         break;
+      }
+      case OSSIM_GPGK_WRITER_MODE_UNKNOWN:
+      default:
+      {
+         result = "unknown";
+         break;
+      }
+   }
+   return result;
+}
+
+bool ossimGpkgWriter::requiresEightBit() const
+{
+   bool result = false;
+   ossimGpkgWriterMode mode = getWriterMode();
+   if ( mode == OSSIM_GPGK_WRITER_MODE_JPEG )
+   {
+      result = true;
+   }
+   return result;
+}
+
+ossim_uint32 ossimGpkgWriter::getEpsgCode() const
+{
+   ossim_uint32 result = 0;
+   std::string value = m_kwl->findKey( EPSG_KW );
+   if ( value.size() )
+   {
+      result = ossimString(value).toUInt32();
+   }
+   return result;
+}
+
+void ossimGpkgWriter::getProjectionDimensionsInMeters(
+   const ossimMapProjection* proj, ossimDpt& dims ) const
+{
+   if ( proj )
+   {
+      ossim_uint32 epsgCode = proj->getPcsCode();
+
+      switch( epsgCode )
+      {
+         case 4326:
+         {
+            if ( proj->getOrigin().lat == 0.0 )
+            { 
+               // 20015110.0 * 2 = 40030220.0;
+               dims.x = 40030220.0;
+
+               // 10007555.0 * 2 = 20015110;
+               dims.y = 20015110;  
+            }
+            else
+            {
+               std::ostringstream errMsg;
+               errMsg << "ossimGpkgWriter::getProjectionDimensionsInMeters ERROR:\n"
+                      << "EPSG 4326 Origin latitude is not at 0.\n";
+               throw ossimException( errMsg.str() );
+            }
+            break;
+         }
+         case 3395:
+         {
+            //---
+            // http://spatialreference.org/ref/epsg/3395/
+            // WGS84 Bounds: -180.0000, -80.0000, 180.0000, 84.0000
+            // Projected Bounds: -20037508.3428, -15496570.7397, 20037508.3428, 18764656.2314
+            //---
+            dims.x = 40075016.6856;
+            dims.y = 34261226.9711;
+            
+            break;
+         }
+         case 3857:
+         {
+            // Bounds: 
+            //  -20037508.342789244,-20037508.342789244,20037508.342789244,20037508.342789244
+            //
+            dims.x = 40075016.685578488;//40075016.6856;
+            dims.y = 40075016.685578488;//40075016.6856;
+            break;
+         }
+         default:
+         {
+            std::ostringstream errMsg;
+            errMsg << "ossimGpkgWriter::getProjectionDimensionsInMeters ERROR:\n"
+                   << "Unhandled espg code: " << epsgCode << "\n";
+            throw ossimException( errMsg.str() );
+         }
+      }
+   }
+   
+} // End: ossimGpkgWriter::getProjectionDimensionsInMeters
+
+#if 0
+void ossimGpkgWriter::clipToProjectionBounds(
+   const ossimMapProjection* proj, const ossimGpt& inUlGpt, const ossimGpt& inLrGpt,
+   ossimGpt& outUlGpt, ossimGpt& outLrGpt ) const
+{
+   if ( proj )
+   {
+      outUlGpt = inUlGpt;
+      outLrGpt = inLrGpt;
+
+      ossim_uint32 code = proj->getPcsCode();
+
+      if ( code == 3395 )
+      {
+         //---
+         // http://spatialreference.org/ref/epsg/3395/
+         // WGS84 Bounds: -180.0000, -80.0000, 180.0000, 84.0000
+         //---
+         const ossim_float64 MAX_LAT = 84.0;
+         const ossim_float64 MIN_LAT = -80.0;
+         
+         if ( outUlGpt.lat > MAX_LAT ) outUlGpt.lat = MAX_LAT;
+         if ( outLrGpt.lat < MIN_LAT ) outLrGpt.lat = MIN_LAT;
+      }
+      else if ( code == 3857 )
+      {
+         //---
+         // http://epsg.io/3857
+         // WGS84 bounds: -180.0 -85.06, 180.0 85.06 
+         //---
+         ossim_float64 MAX_LAT = 85.05112878;
+         ossim_float64 MIN_LAT = -85.05112878;
+         
+         if ( outUlGpt.lat > MAX_LAT ) outUlGpt.lat = MAX_LAT;
+         if ( outLrGpt.lat < MIN_LAT ) outLrGpt.lat = MIN_LAT;
+      }
+   }
+   
+} // End: ossimGpkgWriter::clipToProjectionBounds
+#endif
+
+void ossimGpkgWriter::initializeProjectionRect( const ossimMapProjection* proj )
+{
+   if ( proj )
+   {
+      ossim_uint32 epsgCode = proj->getPcsCode();
+
+      switch( epsgCode )
+      {
+         case 4326:
+         {
+            if ( proj->getOrigin().lat == 0.0 )
+            {
+               m_projectionBoundingRect =
+                  ossimDrect( -180.0, 90.0, 180.0, -90.0, OSSIM_RIGHT_HANDED);
+            }
+            else
+            {
+               std::ostringstream errMsg;
+               errMsg << "ossimGpkgWriter::initializeProjectionRect ERROR:\n"
+                      << "EPSG 4326 Origin latitude is not at 0.\n";
+               throw ossimException( errMsg.str() );
+            }
+            break;
+         }
+         case 3395:
+         {
+            //---
+            // http://spatialreference.org/ref/epsg/3395/
+            // WGS84 Bounds: -180.0000, -80.0000, 180.0000, 84.0000
+            // Projected Bounds: -20037508.3428, -15496570.7397, 20037508.3428, 18764656.2314
+            //---
+             m_projectionBoundingRect =
+                ossimDrect( -20037508.3428, 18764656.2314,
+                            20037508.3428, -15496570.7397, OSSIM_RIGHT_HANDED );
+             break;
+         }
+         case 3857:
+         {
+            m_projectionBoundingRect =
+               ossimDrect( -20037508.342789244, 20037508.342789244,
+                           20037508.342789244, -20037508.342789244, OSSIM_RIGHT_HANDED);
+            break;       
+         }
+         default:
+         {
+            std::ostringstream errMsg;
+            errMsg << "ossimGpkgWriter::initializeProjectionRect ERROR:\n"
+                   << "Unhandled espg code: " << epsgCode << "\n";
+            throw ossimException( errMsg.str() );
+         }
+      }
+   }
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimGpkgWriter::initializeProjectionRect:\n"
+         << "projection bounding rect: " << m_projectionBoundingRect
+         << std::endl;
+   }
+   
+} // End: ossimGpkgWriter::initializeProjectionRect
+
+void ossimGpkgWriter::initializeRect( const ossimMapProjection* proj,
+                                      const ossimIrect& aoi,
+                                      ossimDrect& rect )
+{
+   if ( proj )
+   {
+      ossimDpt gsd;
+      getGsd( proj, gsd );
+      ossimDpt halfGsd = gsd/2.0;
+      
+      ossimDpt ulLineSample = aoi.ul();
+      ossimDpt lrLineSample = aoi.lr();
+
+      if ( proj->isGeographic() )
+      {
+         // Convert line, sample to ground points:
+         ossimGpt ulGpt;
+         ossimGpt lrGpt;
+         proj->lineSampleToWorld( ulLineSample, ulGpt );
+         proj->lineSampleToWorld( lrLineSample, lrGpt );
+         
+         ossim_float64 ulx = ossim::max<ossim_float64>( ulGpt.lon - halfGsd.x, -180.0 );
+         ossim_float64 uly = ossim::min<ossim_float64>( ulGpt.lat + halfGsd.y,  90.0 );
+         ossim_float64 lrx = ossim::min<ossim_float64>( lrGpt.lon + halfGsd.x,  180.0 );
+         ossim_float64 lry = ossim::max<ossim_float64>( lrGpt.lat - halfGsd.y, -90.0 );
+         
+         rect = ossimDrect( ulx, uly, lrx, lry, OSSIM_RIGHT_HANDED );
+      }
+      else
+      {
+         ossimDpt ulEastingNorthingPt;
+         ossimDpt lrEastingNorthingPt;
+         proj->lineSampleToEastingNorthing(
+            aoi.ul(), ulEastingNorthingPt );
+         proj->lineSampleToEastingNorthing(
+            aoi.lr(), lrEastingNorthingPt );
+         
+         // Edge to edge scene bounding rect.
+         rect = ossimDrect( ulEastingNorthingPt.x - halfGsd.x,
+                            ulEastingNorthingPt.y + halfGsd.y,
+                            lrEastingNorthingPt.x + halfGsd.x,
+                            lrEastingNorthingPt.y - halfGsd.y,
+                            OSSIM_RIGHT_HANDED);
+      }
+
+   } // Matches: if ( proj.valid() )
+
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimGpkgWriter::initializeRect:"
+         << "\naoi: " << aoi
+         << "\nrect: " << rect
+         << std::endl;
+   }
+   
+} // End: ossimGpkgWriter::initializeRect
+
+void ossimGpkgWriter::getTileTableName( std::string& tileTableName ) const
+{
+   std::string key = "tile_table_name";
+   tileTableName = m_kwl->findKey( key );
+   if ( tileTableName.empty() )
+   {
+      tileTableName = "tiles";
+   }
+}
+
+bool ossimGpkgWriter::getFilename( ossimFilename& file ) const
+{
+   bool status = false;
+   file.string() = m_kwl->findKey( std::string(ossimKeywordNames::FILENAME_KW) );
+   if ( file.size() > 0 )
+   {
+      status = true;
+   }
+   return status;
+}
+
+void ossimGpkgWriter::initializeCodec()
+{
+   ossimGpkgWriterMode mode = getWriterMode();
+   if ( mode == OSSIM_GPGK_WRITER_MODE_JPEG )
+   {
+      m_fullTileCodec = ossimCodecFactoryRegistry::instance()->createCodec(ossimString("jpeg"));
+      m_partialTileCodec = m_fullTileCodec.get();
+      m_fullTileCodecAlpha = false;
+      m_partialTileCodecAlpha = false;
+   }
+   else if(mode == OSSIM_GPGK_WRITER_MODE_PNG)
+   {
+      m_fullTileCodec = ossimCodecFactoryRegistry::instance()->createCodec(ossimString("png"));
+      m_partialTileCodec = m_fullTileCodec.get();
+      m_fullTileCodecAlpha = false;
+      m_partialTileCodecAlpha = false;
+   }
+   else if( mode == OSSIM_GPGK_WRITER_MODE_PNGA )
+   {
+      m_fullTileCodec = ossimCodecFactoryRegistry::instance()->createCodec(ossimString("pnga"));
+      m_partialTileCodec = m_fullTileCodec.get();
+      m_fullTileCodecAlpha = true;
+      m_partialTileCodecAlpha = true;
+   }
+   else if( mode == OSSIM_GPGK_WRITER_MODE_MIXED )
+   {
+      m_fullTileCodec = ossimCodecFactoryRegistry::instance()->createCodec(ossimString("jpeg"));
+      m_partialTileCodec = ossimCodecFactoryRegistry::instance()->createCodec(ossimString("pnga"));
+      m_fullTileCodecAlpha = false;
+      m_partialTileCodecAlpha = true;
+   }
+   else
+   {
+      m_fullTileCodec = 0;
+      m_partialTileCodec = 0;
+   }
+
+   if ( m_fullTileCodec.valid() &&  m_partialTileCodec.valid() )
+   {
+      // Note: This will only take for jpeg.  Png uses compression_level and need to add.      
+      ossim_uint32 quality = getCompressionQuality();
+      if ( !quality )
+      {
+         quality = (ossim_uint32)ossimGpkgWriter::DEFAULT_JPEG_QUALITY;
+      }
+      m_fullTileCodec->setProperty("quality", ossimString::toString(quality));
+      m_partialTileCodec->setProperty("quality", ossimString::toString(quality));
+   }
+   else
+   {
+      std::ostringstream errMsg;
+      errMsg << "ossimGpkgWriter::initializeCodec ERROR:\n"
+             << "Unsupported writer mode: " << getWriterModeString( mode )
+             << "\nCheck for ossim png plugin..."
+             << "\n";
+      throw ossimException( errMsg.str() );
+   }
+}
+
+bool ossimGpkgWriter::getWmsCutBox( ossimDrect& rect ) const
+{
+   const std::string KEY = "cut_wms_bbox";
+   return getRect( KEY, rect );
+}
+
+bool ossimGpkgWriter::getClipExtents( ossimDrect& rect, bool& alignToGridFlag ) const
+{
+   bool result = getRect( CLIP_EXTENTS_KW, rect );
+   alignToGridFlag = true;
+   ossimString value = m_kwl->findKey( CLIP_EXTENTS_ALIGN_TO_GRID_KW );
+   if(!value.empty()) alignToGridFlag = value.toBool();
+
+   return result;
+}
+
+bool ossimGpkgWriter::getRect( const std::string& key, ossimDrect& rect ) const
+{
+   bool status = false;
+   ossimString value;
+   value.string() = m_kwl->findKey( key );
+   if ( value.size() )
+   {
+      std::string replacementPattern = value.string() + std::string(":");
+      ossimString bbox = value.downcase().replaceAllThatMatch(replacementPattern.c_str(),"");
+      std::vector<ossimString> cutBox;
+      bbox.split( cutBox, "," );
+      if( cutBox.size() == 4 )
+      {
+         ossim_float64 minx = cutBox[0].toFloat64();
+         ossim_float64 miny = cutBox[1].toFloat64();
+         ossim_float64 maxx = cutBox[2].toFloat64();
+         ossim_float64 maxy = cutBox[3].toFloat64();
+         rect = ossimDrect( minx, maxy, maxx, miny );
+         status = true;
+      }
+   }
+   return status;
+}
+
+void ossimGpkgWriter::checkLevels(
+   const std::vector<ossim_int32>& currentZoomLevels,
+   const std::vector<ossim_int32>& newZoomLevels ) const
+{
+   static const char MODULE[] = "ossimGpkgWriter::checkLevels";
+
+   // Assuming sorted, low to high arrays.
+   if ( currentZoomLevels.size() )
+   {
+      if ( newZoomLevels.size() )
+      {
+         // Check for new level lower then existing.
+         if ( newZoomLevels[0] <  currentZoomLevels[0] )
+         {
+            std::ostringstream errMsg;
+            errMsg << MODULE
+                   << " ERROR:\n"
+                   << "New level[" << newZoomLevels[0]
+                   << "] will not fit in existing extents of level["
+                   << currentZoomLevels[0] << "].\n";
+            throw ossimException( errMsg.str() );
+         }   
+
+         // 2) level already present
+         std::vector<ossim_int32>::const_iterator newIdx = newZoomLevels.begin();
+         while ( newIdx < newZoomLevels.end() )
+         {
+            std::vector<ossim_int32>::const_iterator currentIdx = currentZoomLevels.begin();
+            while ( currentIdx != currentZoomLevels.end() )
+            {
+               if ( (*newIdx) == (*currentIdx) )
+               {
+                  std::ostringstream errMsg;
+                  errMsg << MODULE
+                         << " ERROR:\n"
+                         << "New level[" << (*newIdx)
+                         << "] already exists in current matrix set.\n";
+                  throw ossimException( errMsg.str() );
+               }
+               ++currentIdx;
+            }
+            ++newIdx;
+         }
+      }
+   }
+   
+} // End: ossimGpkgWriter::checkLevels
+
+bool ossimGpkgWriter::isValidZoomLevelRowCol(
+   ossim_int32 level, ossim_int32 row, ossim_int32 col  ) const
+{
+   bool status = false;
+
+   if ( m_zoomLevels.size() && (m_zoomLevels.size() == m_zoomLevelMatrixSizes.size()) )
+   {
+      std::vector<ossim_int32>::const_iterator zIdx = m_zoomLevels.begin();
+      std::vector<ossimIpt>::const_iterator sIdx = m_zoomLevelMatrixSizes.begin();
+      while ( zIdx != m_zoomLevels.end() )
+      {
+         if ( (*zIdx) == level )
+         {
+            if ( ( row < (*sIdx).y ) && ( col < (*sIdx).x ) &&
+                 ( row > -1 ) && ( col > -1 ) )
+            {
+               status = true;
+               break;
+            }
+         }
+         ++zIdx;
+         ++sIdx;
+      }
+   }
+   
+   return status;
+   
+} // End: ossimGpkgWriter::isValidZoomLevel( ossim_int32 level ) const
+
+
+
+void ossimGpkgWriter::applyScaleToProjection( ossimMapProjection* proj,
+                                              const ossimDpt& desiredGsd ) const
+{
+   if ( proj )
+   {
+      if ( desiredGsd.hasNans() == false )
+      {
+         // Current projection gsd:
+         ossimDpt currentGsd;
+         getGsd( proj, currentGsd );
+         
+         //---
+         // Set the scale of projection to the stop gsd:
+         // True on applyScale is to recenter tie.
+         //---
+         ossimDpt scale;
+         scale.x = desiredGsd.x / currentGsd.x;
+         scale.y = desiredGsd.y / currentGsd.y;
+         proj->applyScale( scale, true );
+
+#if 0 /** Please leave for debug. (drb) */
+         cout << "ossimGpkgWriter::applyScaleToProjection DEBUG:"
+              << "\nproj gsd:    " << currentGsd
+              << "\ndesired gsd: " << desiredGsd
+              << "\nscale:       " << scale
+              << "\n";
+#endif
+      }
+   }
+}
+
+
diff --git a/ossim_plugins/sqlite/ossimGpkgWriter.h b/ossim_plugins/sqlite/ossimGpkgWriter.h
new file mode 100644
index 0000000..964c2de
--- /dev/null
+++ b/ossim_plugins/sqlite/ossimGpkgWriter.h
@@ -0,0 +1,715 @@
+//----------------------------------------------------------------------------
+//
+// File: ossimGpkgWriter.h
+//
+// Author:  David Burken
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Description: OSSIM Geo Package writer.
+//
+//----------------------------------------------------------------------------
+// $Id$
+#ifndef ossimGpkgWriter_HEADER
+#define ossimGpkgWriter_HEADER 1
+
+#include <ossim/imaging/ossimGpkgWriterInterface.h>
+#include <ossim/imaging/ossimImageFileWriter.h>
+#include <ossim/base/ossimIpt.h>
+#include <ossim/base/ossimKeywordlist.h>
+#include <ossim/base/ossimRefPtr.h>
+#include <ossim/imaging/ossimCodecBase.h>
+#include <vector>
+
+// Forward class declarations.
+class ossimDpt;
+class ossimImageData;
+class ossimIrect;
+struct jpeg_compress_struct;
+struct sqlite3;
+struct sqlite3_stmt;
+
+/**
+ * @class ossimGpkgWriter
+ */
+class ossimGpkgWriter :
+   public ossimImageFileWriter, public ossimGpkgWriterInterface
+{
+public:
+
+   // Anonymous enums:
+   enum
+   {
+      DEFAULT_JPEG_QUALITY = 75
+   };
+   
+   enum ossimGpkgWriterMode
+   {
+      OSSIM_GPGK_WRITER_MODE_UNKNOWN = 0,
+      OSSIM_GPGK_WRITER_MODE_JPEG    = 1,  // RGB, 8-bit, JPEG compressed
+      OSSIM_GPGK_WRITER_MODE_PNG     = 2,  // PNG,
+      OSSIM_GPGK_WRITER_MODE_PNGA    = 3,  // PNG with alpha
+      OSSIM_GPGK_WRITER_MODE_MIXED   = 4   // full tiles=jpeg, partials=pnga
+   };
+
+   /* default constructor */
+   ossimGpkgWriter();
+
+   /* virtual destructor */
+   virtual ~ossimGpkgWriter();
+
+   /** @return "gpkg writer" */
+   virtual ossimString getShortName() const;
+
+   /** @return "ossim gpkg writer" */
+   virtual ossimString getLongName()  const;
+
+   /** @return "ossimGpkgReader" */
+   virtual ossimString getClassName()    const;
+
+   /**
+    * Returns a 3-letter extension from the image type descriptor 
+    * (theOutputImageType) that can be used for image file extensions.
+    *
+    * @param imageType string representing image type.
+    *
+    * @return the 3-letter string extension.
+    */
+   virtual ossimString getExtension() const;
+
+   /**
+    * void getImageTypeList(std::vector<ossimString>& imageTypeList)const
+    *
+    * Appends this writer image types to list "imageTypeList".
+    *
+    * This writer only has one type "gpkg".
+    *
+    * @param imageTypeList stl::vector<ossimString> list to append to.
+    */
+   virtual void getImageTypeList(std::vector<ossimString>& imageTypeList)const;
+   
+   /**
+    * saves the state of the object.
+    */
+   virtual bool saveState(ossimKeywordlist& kwl,
+                          const char* prefix=0)const;
+   
+   /**
+    * Method to the load (recreate) the state of an object from a keyword
+    * list.  Return true if ok or false on error.
+    */
+   virtual bool loadState(const ossimKeywordlist& kwl,
+                          const char* prefix=0);
+
+   /**
+    * Will set the property whose name matches the argument
+    * "property->getName()".
+    *
+    * @param property Object containing property to set.
+    */
+   virtual void setProperty(ossimRefPtr<ossimProperty> property);
+
+   /**
+    * @param name Name of property to return.
+    * 
+    * @returns A pointer to a property object which matches "name".
+    */
+   virtual ossimRefPtr<ossimProperty> getProperty(const ossimString& name)const;
+
+   /**
+    * Pushes this's names onto the list of property names.
+    *
+    * @param propertyNames array to add this's property names to.
+    */
+   virtual void getPropertyNames(std::vector<ossimString>& propertyNames)const;
+
+   bool hasImageType(const ossimString& imageType) const;
+
+   /**
+    * Get the gpkg compression level as a string.
+    *
+    * @return The level which will be one of:
+    * z_no_compression
+    * z_best_speed
+    * z_best_compression
+    * z_default_compression
+    */
+   ossimString getCompressionLevel() const;
+
+   /**
+    * Set the gpkg compression level from a string.
+    *
+    * @param level Should be one of:
+    * z_no_compression
+    * z_best_speed
+    * z_best_compression
+    * z_default_compression
+    *
+    * @return true on success, false if level is not accepted.
+    */
+   bool setCompressionLevel(const ossimString& level);
+
+       
+   virtual bool isOpen()const;   
+   
+   virtual bool open();
+
+   /**
+    * @brief Opens file for writing, appending, merging without an input
+    * connection. I.e. opening, then calling writeTile directly.
+    *
+    * Option keywords:
+    * append: bool false=create_new, true=append_existing
+    * epsg: 4326, 3857
+    * filename: output_file.gpkg
+    * tile_table_name: default="tiles"
+    * writer_mode: mixed(default), jpeg, png, pnga
+    * 
+    * 
+    * @param options.  Keyword list containing all options.
+    */
+   virtual bool openFile( const ossimKeywordlist& options );
+   
+   virtual void close();
+
+   /**
+    * @brief Gets the writer mode.
+    *
+    * Default mode = jpeg.
+    *
+    * Potential mode are:
+    * jpeg
+    * png
+    * pnga
+    * 
+    * @return Writer mode.  Default mode = jpeg.
+    */
+   ossimGpkgWriterMode getWriterMode() const;
+
+   /**
+    * @brief Gets the writer mode as string.
+    *
+    * Default mode = jpeg.
+    *
+    * Potential mode are:
+    * jpeg
+    * png
+    * pnga
+    * 
+    * @return Writer mode.  Default mode = jpeg.
+    */
+   std::string getWriterModeString( ossimGpkgWriterMode mode ) const;
+
+   void setCompressionQuality( const std::string& quality );
+
+   /**
+    * @brief Gets the compression quality.
+    *
+    * Result is pulled from options keyword list where
+    * key=compression_quality.
+    * 
+    * @return Compression quality.or 0 if not found.
+    */
+   ossim_uint32 getCompressionQuality() const;
+
+   /**
+    * @brief Calls initial sqlite3_prepare_v2 statement.  Must be called
+    * prior to calling writeTile.
+    * @return SQLITE_OK(0) on success, something other(non-zero) on failure.
+    */
+   virtual ossim_int32 beginTileProcessing();
+
+   /**
+    * @brief Direct interface to writing a tile to database.
+    * @param tile to write.
+    * @param zoolLevel
+    * @param row
+    * @param col
+    * @note Can throw ossimException.
+    * @return true on success, false on error.
+    */
+   virtual bool writeTile( ossimRefPtr<ossimImageData>& tile,
+                           ossim_int32 zoomLevel,
+                           ossim_int64 row,
+                           ossim_int64 col);
+
+   /**
+    * @brief Direct interface to writing a Codec tile to database.
+    * @param codecTile to write.
+    * @param codecTileSize 
+    * @param zoolLevel
+    * @param row
+    * @param col
+    * @note Can throw ossimException.
+    * @return true on success, false on error.
+    */
+   virtual bool writeCodecTile( ossim_uint8* codecTile,
+                           ossim_int32 codecTileSize,
+                           ossim_int32 zoomLevel,
+                           ossim_int64 row,
+                           ossim_int64 col);
+
+   /**
+    * @brief Calls sqlite3_finalize(pStmt) terminating tile processing.
+    */
+   virtual void finalizeTileProcessing();
+   
+private:
+
+   /**
+    * @brief Writes the file to disk or a stream.
+    * @return true on success, false on error.
+    */
+   virtual bool writeFile();
+
+   /**
+    * @brief Writes an entry to gpkg.  This could be either a new file, or a
+    * new tile table.
+    * @return true on success, false on error.
+    */
+   bool writeEntry();
+
+   /**
+    * @brief Adds levels to an existing an gpkg.
+    * @return true on success, false on error.
+    */  
+   bool addLevels();
+   
+   bool createTables( sqlite3* db );
+
+   /**
+    * @return the "srs_id" number pointing to the
+    * gpkg_spatial_ref_sys record for our projection.
+    */
+   ossim_int32 writeGpkgSpatialRefSysTable(
+      sqlite3* db, const ossimMapProjection* proj );
+
+   bool writeGpkgContentsTable( sqlite3* db,
+                                const ossimDrect& boundingRect );
+   
+   bool writeGpkgTileMatrixSetTable( sqlite3* db,
+                                     const ossimDrect& boundingRect );
+
+   /**
+    * @brief Initialize method.
+    * @param db
+    * @param zoom_level.  Zero being whole Earth...
+    * @param matrixSize Size of tile matrix, i.e. number of horizontal
+    * vertical tiles.
+    * @param gsd Size of one pixel either in meters or lat lon.
+    * @return true on success, false on error.
+    */  
+   bool writeGpkgTileMatrixTable( sqlite3* db,
+                                  ossim_int32 zoom_level,
+                                  const ossimIpt& matrixSize,
+                                  const ossimDpt& gsd );
+
+   
+   bool writeGpkgNsgTileMatrixExtentTable( sqlite3* db,
+                                           ossim_int32 zoom_level,
+                                           const ossimIrect& expandedAoi,
+                                           const ossimIrect& clippedAoi);
+
+   void writeZoomLevels( sqlite3* db,
+                         ossimMapProjection* proj,
+                         const std::vector<ossim_int32>& zoomLevels );
+
+   void writeTiles( sqlite3* db,
+                    const ossimIrect& aoi,
+                    ossim_int32 zoomLevel,
+                    const ossim_float64& totalTiles,
+                    ossim_float64& tilesWritten );  
+
+   void writeTile( sqlite3_stmt* pStmt,
+                   sqlite3* db,
+                   ossimRefPtr<ossimImageData>& tile,
+                   ossim_int32 zoomLevel,
+                   ossim_int64 row,
+                   ossim_int64 col);
+   void writeCodecTile( sqlite3_stmt* pStmt,
+                   sqlite3* db,
+                   ossim_uint8* codecTile,
+                   ossim_int32 codecTileSize,
+                   ossim_int32 zoomLevel,
+                   ossim_int64 row,
+                   ossim_int64 col);
+   
+/*
+   void writeJpegTiles( sqlite3* db,
+                        const ossimIrect& aoi,
+                        ossim_int32 zoomLevel,
+                        ossim_uint32 quality,
+                        const ossim_float64& totalTiles,
+                        ossim_float64& tilesWritten );  
+
+   void writeJpegTile( sqlite3_stmt* pStmt,
+                       sqlite3* db,
+                       const ossimRefPtr<ossimImageData>& tile,
+                       ossim_int32 zoomLevel,
+                       ossim_uint32 row,
+                       ossim_uint32 col,
+                       ossim_uint32 quality );
+*/
+   void getGsd( const ossimDpt& fullResGsd,
+                ossim_int32 fullResZoomLevel,
+                ossim_int32 currentZoomLevel,
+                ossimDpt& gsd );
+
+   /**
+    * @brief Get the gsd.
+    *
+    * Gets gsd in either meters or decimal degrees dependent on if the
+    * projection is "geographic" or not.
+    *
+    * @param proj
+    * @param gsd Initialized by this.
+    */
+   void getGsd( const ossimMapProjection* proj,
+                ossimDpt& gsd ) const;
+
+   /**
+    * @brief Get the gsd.
+    *
+    * Gets gsd in either meters or decimal degrees dependent on if the
+    * projection is "geographic" or not.
+    *
+    * @param geom
+    * @param gsd Initialized by this.
+    */
+   void getGsd( const ossimImageGeometry* geom,
+                ossimDpt& gsd ) const;
+
+   /**
+    * @brief Get the gsd.
+    *
+    * Gets gsd in either meters or decimal degrees dependent on if the
+    * projection is "geographic" or not.
+    *
+    * This method assumes zoom level are aligned to the projection grid. If
+    * align_to_grid==false gsd will be "nan"ed.
+    *
+    * @param proj Output projection. 
+    * @param zoomLevel
+    * @param gsd Initialized by this.
+    */
+   void getGsd( const ossimMapProjection* proj,
+                ossim_int32 zoomLevel,
+                ossimDpt& gsd ) const;
+
+   /** @return true if align to grid option is set; false, if not. */
+   bool alignToGrid() const;
+
+   /**
+    * @brief Check if file is to be open new or appended.
+    *
+    * Checks for keywords: add_entry, add_levels
+    * 
+    * @return true if any append option is set; false, if not.
+    */
+   bool append() const;
+
+   /** @return true if "add_levels" key is set to true; false, if not. */
+   bool addLevels() const;
+
+   /** @return true if "add_entry" key is set to true; false, if not. */
+   bool addEntry() const;
+
+   /**
+    * @brief Get the output projection.
+    *
+    * Output projection type is determined in this order:
+    * 1) User set epsg code, e.g. "3395".
+    * 2) Input projection.
+    * 3) Default output (currently geographic.
+    * @return Projection wrapped in ref pointer.
+    */
+   ossimRefPtr<ossimMapProjection> getNewOutputProjection(
+      ossimImageGeometry* geom ) const;
+
+   /** @brief Gets projection from "epsg" code if in options list. */
+   ossimRefPtr<ossimMapProjection> getNewOutputProjection() const;
+
+   ossimRefPtr<ossimMapProjection> getNewGeographicProjection() const;
+   
+   ossimRefPtr<ossimMapProjection> getNewWorldMercatorProjection() const;
+
+   // Propagates view to all resamplers.
+   void setView( ossimMapProjection* proj );
+
+   /**
+    * @brief Finds all combiners and calls initialize to reset the bounding box
+    * after a view change.
+    */
+   void reInitializeCombiners();
+
+   /**
+    * @brief Finds all ossimRectangleCutter and calls setRectangle with a nan
+    * rect to reset the bounding box after a view change.
+    */
+   void reInitializeCutters( const ossimMapProjection* proj );
+   
+   /** @return true if key is set to true; false, if not. */
+   bool keyIsTrue( const std::string& key ) const;
+
+   void getTileSize( ossimIpt& tileSize ) const;
+
+   /**
+    * @brief This is the number of transactions batched before being executed.
+    * @return sqlite transaction batch size.
+    */
+   ossim_uint64 getBatchSize() const;
+
+   /**
+    * @brief Zoom levels needed to get AOI down to one tile.
+    * @param aoi Area of Interest.
+    */
+   ossim_int32 getNumberOfZoomLevels( const ossimIrect& aoi ) const;
+
+   /**
+    * @brief Gets zoom levels from options keyword list if set.
+    *
+    * Keyword: "zoom_levels"
+    *
+    * Splits comma separated list, e.g. "(8,9,10,11)"
+    *
+    * If align to grid is on levels are based on projection grid; else,
+    * stop zoom level is 0, start is the full res level.
+    * @param proj
+    * @param aoi
+    * @param zoomLevels Intitialized by this.
+    * @param fullResGsd Intitialized by this.
+    */
+   void getZoomLevels( std::vector<ossim_int32>& zoomLevels ) const;
+   
+
+   /**
+    * @brief Computes start and stop level.
+    *
+    * If align to grid is on levels are based on projection grid; else,
+    * stop zoom level is 0, start is the full res level.
+    * @param proj
+    * @param aoi
+    * @param sourceGsd Full res gsd of input.
+    * @param zoomLevels Intitialized by this.
+    * @param fullResGsd Intitialized by this to the highest resolution of zoom
+    * levels.  This may or may not be the same as the sourceGsd.
+    */
+   void getZoomLevels( const ossimMapProjection* proj,
+                       const ossimIrect& aoi,
+                       const ossimDpt& sourceGsd,
+                       std::vector<ossim_int32>& zoomLevels,
+                       ossimDpt& fullResGsd ) const;
+
+   /**
+    * @brief Get the view coordinates for edge to edge rect.
+    */
+   void getAoiFromRect( const ossimMapProjection* proj,
+                        const ossimDrect& rect,
+                        ossimIrect& aoi );
+   
+   /**
+    * @brief Gets aoi expanded to tile boundaries.
+    *
+    * This initializes expandedAoi with the aoi expanded to tile boundaries.
+    * 
+    * @param aoi Area of interest.
+    * @param expandedAoi Initialized by this.
+    */
+   void getExpandedAoi( const ossimIrect& aoi, ossimIrect& expandedAoi ) const;
+   
+   void getMatrixSize( const ossimIrect& rect,
+                       ossimIpt& matrixSize ) const;
+
+   void setProjectionTie( ossimMapProjection* proj ) const;
+
+   bool requiresEightBit() const;
+
+   ossim_uint32 getEpsgCode() const;
+
+   /**
+    * @brief Gets the projection dimensions in meters.
+    * @param proj Projection
+    * @param dims Initialized by this.
+    */
+   void getProjectionDimensionsInMeters(
+      const ossimMapProjection* proj, ossimDpt& dims ) const;
+
+#if 0
+   void clipToProjectionBounds(
+      const ossimMapProjection* proj,
+      const ossimGpt& inUlGpt, const ossimGpt& inLrGpt,
+      ossimGpt& outUlGpt, ossimGpt& outLrGpt ) const;
+#endif
+
+   void initializeProjectionRect( const ossimMapProjection* productProj );
+
+   void initializeRect( const ossimMapProjection* proj,
+                        const ossimIrect& aoi,
+                        ossimDrect& rect );
+
+   /**
+    * @brief Gets the tile table name.
+    *
+    * Looks for "tile_table_name" and returns value if found;
+    * else, default="tiles".
+    *
+    * @return tile table name.
+    */
+   void getTileTableName( std::string& tileTableName ) const;
+
+   bool getFilename( ossimFilename& file ) const;
+
+   /**
+    * Initializes m_fullTileCodec and m_partialTileCodec.
+    */
+   void initializeCodec();
+
+   /**
+    * @brief Initializes the output gpkg file.  This method is used for
+    * non-connected writing, e.g. openFile(...), writeTile(...)
+    *
+    * Assumes new gpkg with no input connection.
+    * 
+    * @return true on success, false on error.
+    */
+   bool initializeGpkg();
+
+   /**
+    * @brief Get rectangle in projected space from key: cut_wms_bbox
+    * key:value form:
+    * cut_wms_bbox: <minx>,<miny>,<maxx>,<maxy>
+    * @param rect Initialized by this.  This is in output projection
+    * coordinate space.
+    * @return true on success; false on error.
+    */
+   bool getWmsCutBox( ossimDrect& rect ) const;
+
+   /**
+    * @brief Get clip rectangle in projected space from key: clip_extents
+    * key:value form:
+    * clip_extents: <minx>,<miny>,<maxx>,<maxy>
+    * @param rect Initialized by this.  This is in output projection
+    * coordinate space.
+    * @param alignToGridFlag. Indicates if the clip extents need to be aligned.
+    * The flag will be defaulted to true.
+    * @return true on success; false, on error.
+    */
+   bool getClipExtents( ossimDrect& rect, bool& alignToGridFlag ) const;
+  
+
+    /**
+    * @brief Gets rectangle.
+    * Method assumes form of:
+    * key: <minx>,<miny>,<maxx>,<maxy>
+    * e.g. "clip_extents: <minx>,<miny>,<maxx>,<maxy>"
+    * @param rect Initialized by this.  This is in output projection
+    * coordinate space.
+    * @return true on success; false, on error.
+    */
+   bool getRect( const std::string& key, ossimDrect& rect ) const;
+
+   /**
+    * @brief Checks for:
+    * new level lower then existing.
+    * new level already present
+    *
+    * Throws exception on error.
+    */
+   void checkLevels( const std::vector<ossim_int32>& currentZoomLevels,
+                     const std::vector<ossim_int32>& newZoomLevels ) const;
+
+   /**
+    * @breif Checks to see if level, row, column are within range of existing
+    * gpkg.
+    * @param level Zero base level.
+    * @param row Zero based tile row index.
+    * @param col Zero based tile column index.
+    */
+   bool isValidZoomLevelRowCol( ossim_int32 level,
+                                ossim_int32 row,
+                                ossim_int32 col  ) const;
+
+   /**
+    * @brief Get the current gsd from projection.  Computes the scale, and
+    * calls proj->applyScale(...) recentering tie point.
+    * @param proj
+    * @param desiredGsd Desired gsd after scale change.
+    */
+   void applyScaleToProjection( ossimMapProjection* proj,
+                                const ossimDpt& desiredGsd ) const;
+
+   /** database connection */
+   sqlite3* m_db;
+
+   /** Working variable for holding the current batch count */
+   ossim_uint64 m_batchCount;
+
+   /** Number of transactions batched before being executed. */
+   ossim_uint64 m_batchSize;   
+
+   /**
+    * Holds the bounding rect of the output projection edges either in decimal
+    * degrees for geographic projection or Easting/Northings(meters) for map
+    * projection.  This is "edge to edge" bounds.
+    */
+   ossimDrect m_projectionBoundingRect;
+
+   /**
+    * Holds the bounding rect of the scene edges either in decimal degrees
+    * for geographic projection or Easting/Northings(meters) for map projection.
+    * or Easting/Northings(meters).  This is "edge to edge" bounds.
+    */
+   ossimDrect m_sceneBoundingRect;
+
+   /** AOI clipped to projection rect. This is "edge to edge" bounds. */ 
+   ossimDrect m_clipRect; 
+
+   /**
+    * Expanded(final) AOI clipped to projection rect.
+    * This is "edge to edge" bounds.
+    */
+   ossimDrect m_outputRect;
+
+   ossimIpt m_tileSize;
+
+   std::string m_tileTableName;
+
+   ossim_int32 m_srs_id;
+
+   /** Hold all options. */
+   ossimRefPtr<ossimKeywordlist> m_kwl;
+
+   /**
+    * Will cache and hold the allocated codecs to use for the encoding.
+    * There is a full and partial as in mixed mode you could use jpeg for full
+    * tiles and png with alpha for partial (edge) tiles.
+    */
+   ossimRefPtr<ossimCodecBase> m_fullTileCodec;
+   ossimRefPtr<ossimCodecBase> m_partialTileCodec;
+
+   /** true if codec requires alpha channel. */
+   bool m_fullTileCodecAlpha;
+   bool m_partialTileCodecAlpha;
+
+   /** Holds zoom level indexes for connectionless write tile. */
+   std::vector<ossim_int32> m_zoomLevels;
+
+   /** Hold zoom level matrix sizes for connectionless write tile. */
+   std::vector<ossimIpt> m_zoomLevelMatrixSizes;
+
+   /**
+    * Holds Statement handle from sqlite3_prepare_v2(...) for connectionless
+    * write tile.
+    */
+   sqlite3_stmt* m_pStmt;
+
+   /** Controlled by option key: "include_blank_tiles" */
+   bool m_writeBlanks;
+
+   TYPE_DATA
+};
+
+#endif /* #ifndef ossimGpkgWriter_HEADER */
+
diff --git a/ossim_plugins/sqlite/ossimSqliteInfoFactory.cpp b/ossim_plugins/sqlite/ossimSqliteInfoFactory.cpp
new file mode 100644
index 0000000..5c0ca05
--- /dev/null
+++ b/ossim_plugins/sqlite/ossimSqliteInfoFactory.cpp
@@ -0,0 +1,60 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author: David Burken
+//
+// Description: Factory for SQLite info objects.
+// 
+//----------------------------------------------------------------------------
+// $Id$
+
+#include "ossimSqliteInfoFactory.h"
+#include <ossim/support_data/ossimInfoFactory.h>
+#include <ossim/support_data/ossimInfoBase.h>
+#include <ossim/base/ossimFilename.h>
+#include <ossim/base/ossimRefPtr.h>
+#include "ossimGpkgInfo.h"
+
+ossimSqliteInfoFactory::~ossimSqliteInfoFactory()
+{}
+
+ossimSqliteInfoFactory* ossimSqliteInfoFactory::instance()
+{
+   static ossimSqliteInfoFactory sharedInstance;
+
+   return &sharedInstance;
+}
+
+ossimInfoBase* ossimSqliteInfoFactory::create(const ossimFilename& file) const
+{
+   ossimRefPtr<ossimInfoBase> result = 0;
+
+   std::string ext = file.ext().downcase().string();
+   if ( ext == "gpkg" )
+   {
+      result = new ossimGpkgInfo;
+      if(result->open(file) == false)
+      {
+         result = 0;
+      }
+   }
+
+   return result.release();
+}
+
+ossimSqliteInfoFactory::ossimSqliteInfoFactory()
+{}
+
+ossimSqliteInfoFactory::ossimSqliteInfoFactory(const ossimSqliteInfoFactory& /* obj */ )
+{}
+
+const ossimSqliteInfoFactory& ossimSqliteInfoFactory::operator=(
+   const ossimSqliteInfoFactory& /* rhs */)
+{
+   return *this;
+}
+
+
diff --git a/ossim_plugins/sqlite/ossimSqliteInfoFactory.h b/ossim_plugins/sqlite/ossimSqliteInfoFactory.h
new file mode 100644
index 0000000..71c266a
--- /dev/null
+++ b/ossim_plugins/sqlite/ossimSqliteInfoFactory.h
@@ -0,0 +1,58 @@
+//----------------------------------------------------------------------------
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author: David Burken
+//
+// Description: Factory for SQLite info objects.
+// 
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef ossimSqliteInfoFactory_HEADER
+#define ossimSqliteInfoFactory_HEADER
+
+#include <ossim/base/ossimConstants.h>
+#include <ossim/support_data/ossimInfoFactoryInterface.h>
+
+class ossimFilename;
+class ossimInfoBase;
+
+/**
+ * @brief Info factory.
+ */
+class ossimSqliteInfoFactory : public ossimInfoFactoryInterface
+{
+public:
+
+   /** virtual destructor */
+   virtual ~ossimSqliteInfoFactory();
+
+   static ossimSqliteInfoFactory* instance();
+
+   /**
+    * @brief create method.
+    *
+    * @param file Some file you want info for.
+    *
+    * @return ossimInfoBase* on success 0 on failure.  Caller is responsible
+    * for memory.
+    */
+   virtual ossimInfoBase* create(const ossimFilename& file) const;
+   
+private:
+   
+   /** hidden from use default constructor */
+   ossimSqliteInfoFactory();
+
+   /** hidden from use copy constructor */
+   ossimSqliteInfoFactory(const ossimSqliteInfoFactory& obj);
+
+   /** hidden from use operator = */
+   const ossimSqliteInfoFactory& operator=(const ossimSqliteInfoFactory& rhs);
+};
+
+#endif /* End of "#ifndef ossimSqliteInfoFactory_HEADER" */
+
diff --git a/ossim_plugins/sqlite/ossimSqlitePluginInit.cpp b/ossim_plugins/sqlite/ossimSqlitePluginInit.cpp
new file mode 100644
index 0000000..40eadeb
--- /dev/null
+++ b/ossim_plugins/sqlite/ossimSqlitePluginInit.cpp
@@ -0,0 +1,91 @@
+//----------------------------------------------------------------------------
+//
+// License:  See top level LICENSE.txt file
+//
+// Author:  David Burken
+//
+// Description: OSSIM SQLite plugin initialization
+// code.
+//
+//----------------------------------------------------------------------------
+// $Id: ossimSqlitePluginInit.cpp 19669 2011-05-27 13:27:29Z gpotts $
+
+#include <ossim/plugin/ossimSharedObjectBridge.h>
+#include "ossimSqliteInfoFactory.h"
+#include "ossimPluginConstants.h"
+#include "ossimSqliteReaderFactory.h"
+#include "ossimSqliteWriterFactory.h"
+#include <ossim/imaging/ossimImageHandlerRegistry.h>
+#include <ossim/imaging/ossimImageWriterFactoryRegistry.h>
+#include <ossim/support_data/ossimInfoFactoryRegistry.h>
+
+static void setDescription(ossimString& description)
+{
+   description = "GeoPackage reader / writer plugin\n\n";
+}
+
+
+extern "C"
+{
+   ossimSharedObjectInfo  myInfo;
+   ossimString theDescription;
+   std::vector<ossimString> theObjList;
+
+   const char* getDescription()
+   {
+      return theDescription.c_str();
+   }
+
+   int getNumberOfClassNames()
+   {
+      return (int)theObjList.size();
+   }
+
+   const char* getClassName(int idx)
+   {
+      if(idx < (int)theObjList.size())
+      {
+         return theObjList[0].c_str();
+      }
+      return (const char*)0;
+   }
+
+   /* Note symbols need to be exported on windoze... */ 
+   OSSIM_PLUGINS_DLL void ossimSharedLibraryInitialize(
+                                                       ossimSharedObjectInfo** info, 
+                                                       const char* /*options*/)
+   {    
+      myInfo.getDescription = getDescription;
+      myInfo.getNumberOfClassNames = getNumberOfClassNames;
+      myInfo.getClassName = getClassName;
+      
+      *info = &myInfo;
+      
+      /* Register the readers... */
+      ossimImageHandlerRegistry::instance()->
+        registerFactory(ossimSqliteReaderFactory::instance());
+
+      /* Register the info factoy... */
+      ossimInfoFactoryRegistry::instance()->
+         registerFactory(ossimSqliteInfoFactory::instance());
+      
+      /* Register the writers... */
+      ossimImageWriterFactoryRegistry::instance()->
+         registerFactory(ossimSqliteWriterFactory::instance());
+      
+      setDescription(theDescription);
+  }
+
+   /* Note symbols need to be exported on windoze... */ 
+  OSSIM_PLUGINS_DLL void ossimSharedLibraryFinalize()
+  {
+     ossimImageHandlerRegistry::instance()->
+        unregisterFactory(ossimSqliteReaderFactory::instance());
+
+     ossimInfoFactoryRegistry::instance()->
+        unregisterFactory(ossimSqliteInfoFactory::instance());
+        
+     ossimImageWriterFactoryRegistry::instance()->
+        unregisterFactory(ossimSqliteWriterFactory::instance());
+  }
+}
diff --git a/ossim_plugins/sqlite/ossimSqliteReaderFactory.cpp b/ossim_plugins/sqlite/ossimSqliteReaderFactory.cpp
new file mode 100644
index 0000000..969a03f
--- /dev/null
+++ b/ossim_plugins/sqlite/ossimSqliteReaderFactory.cpp
@@ -0,0 +1,157 @@
+//----------------------------------------------------------------------------
+//
+// License:  See top level LICENSE.txt file
+//
+// Author:  David Burken
+//
+// Description: Factory for OSSIM SQLite reader factory.
+// 
+//----------------------------------------------------------------------------
+// $Id$
+
+#include "ossimSqliteReaderFactory.h"
+#include "ossimGpkgReader.h"
+#include <ossim/base/ossimKeywordlist.h>
+#include <ossim/base/ossimRefPtr.h>
+#include <ossim/base/ossimString.h>
+#include <ossim/imaging/ossimImageHandler.h>
+#include <ossim/base/ossimTrace.h>
+#include <ossim/base/ossimKeywordNames.h>
+
+#include <sqlite3.h>
+
+static const ossimTrace traceDebug("ossimSqliteReaderFactory:debug");
+
+RTTI_DEF1(ossimSqliteReaderFactory,
+          "ossimSqliteReaderFactory",
+          ossimImageHandlerFactoryBase);
+
+ossimSqliteReaderFactory* ossimSqliteReaderFactory::theInstance = 0;
+
+ossimSqliteReaderFactory::~ossimSqliteReaderFactory()
+{
+   theInstance = 0;
+}
+
+ossimSqliteReaderFactory* ossimSqliteReaderFactory::instance()
+{
+   if(!theInstance)
+   {
+      theInstance = new ossimSqliteReaderFactory;
+   }
+   return theInstance;
+}
+   
+ossimImageHandler* ossimSqliteReaderFactory::open(const ossimFilename& file,
+                                                  bool openOverview)const
+{
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimSqliteReaderFactory::open(filename) DEBUG: entered..."
+         << "\ntrying ossimGpkgReader"
+         << std::endl;
+   }
+   ossimRefPtr<ossimImageHandler> reader = 0;
+   
+   std::string ext = file.ext().downcase().string();
+   if ( ext == "gpkg" )
+   {
+      reader = new ossimGpkgReader;
+      reader->setOpenOverviewFlag(openOverview);
+      if(reader->open(file) == false)
+      {
+         reader = 0;
+      }
+   }
+   
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimSqliteReaderFactory::open(filename) DEBUG: leaving..."
+         << std::endl;
+   }
+   
+   return reader.release();
+}
+
+ossimImageHandler* ossimSqliteReaderFactory::open(const ossimKeywordlist& kwl,
+                                               const char* prefix)const
+{
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimSqliteReaderFactory::open(kwl, prefix) DEBUG: entered..."
+         << "Trying ossimGpkgReader"
+         << std::endl;
+   }
+
+   ossimRefPtr<ossimImageHandler> reader = new ossimGpkgReader;
+   if(reader->loadState(kwl, prefix) == false)
+   {
+      reader = 0;
+   }
+   
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimSqliteReaderFactory::open(kwl, prefix) DEBUG: leaving..."
+         << std::endl;
+   }
+   
+   return reader.release();
+}
+
+ossimObject* ossimSqliteReaderFactory::createObject(
+   const ossimString& typeName)const
+{
+   ossimRefPtr<ossimObject> result = 0;
+   if(typeName == "ossimGpkgReader")
+   {
+      result = new ossimGpkgReader;
+   }
+   return result.release();
+}
+
+ossimObject* ossimSqliteReaderFactory::createObject(const ossimKeywordlist& kwl,
+                                                 const char* prefix)const
+{
+   return this->open(kwl, prefix);
+}
+ 
+void ossimSqliteReaderFactory::getTypeNameList(std::vector<ossimString>& typeList)const
+{
+   typeList.push_back(ossimString("ossimGpkgReader"));
+}
+
+void ossimSqliteReaderFactory::getSupportedExtensions(
+   ossimImageHandlerFactoryBase::UniqueStringList& extensionList)const
+{
+   extensionList.push_back(ossimString("gpkg"));
+}
+
+void ossimSqliteReaderFactory::getImageHandlersBySuffix(ossimImageHandlerFactoryBase::ImageHandlerList& result,
+                                      const ossimString& ext)const
+{
+   ossimString testExt = ext.downcase();
+   if(ext == "gpkg")
+   {
+      result.push_back(new ossimGpkgReader);
+   }
+}
+
+void ossimSqliteReaderFactory::getImageHandlersByMimeType(ossimImageHandlerFactoryBase::ImageHandlerList& result,
+                                        const ossimString& mimeType)const
+{
+   ossimString testExt = mimeType.downcase();
+   if(testExt == "image/gpkg")
+   {
+      result.push_back(new ossimGpkgReader);
+   }
+}
+
+ossimSqliteReaderFactory::ossimSqliteReaderFactory(){}
+
+ossimSqliteReaderFactory::ossimSqliteReaderFactory(const ossimSqliteReaderFactory&){}
+
+void ossimSqliteReaderFactory::operator=(const ossimSqliteReaderFactory&){}
diff --git a/ossim_plugins/sqlite/ossimSqliteReaderFactory.h b/ossim_plugins/sqlite/ossimSqliteReaderFactory.h
new file mode 100644
index 0000000..61d8807
--- /dev/null
+++ b/ossim_plugins/sqlite/ossimSqliteReaderFactory.h
@@ -0,0 +1,103 @@
+//----------------------------------------------------------------------------
+//
+// License:  See top level LICENSE.txt file
+//
+// Author:  David Burken
+//
+// Description: Factory for OSSIM SQLite reader factory.
+//----------------------------------------------------------------------------
+// $Id$
+
+#ifndef ossimSqliteReaderFactory_HEADER
+#define ossimSqliteReaderFactory_HEADER 1
+
+#include <ossim/imaging/ossimImageHandlerFactoryBase.h>
+
+class ossimString;
+class ossimFilename;
+class ossimKeywordlist;
+
+/** @brief Factory for SQLITE image reader. */
+class ossimSqliteReaderFactory : public ossimImageHandlerFactoryBase
+{
+public:
+
+   /** @brief virtual destructor */
+   virtual ~ossimSqliteReaderFactory();
+
+   /**
+    * @brief static method to return instance (the only one) of this class.
+    * @return pointer to instance of this class.
+    */
+   static ossimSqliteReaderFactory* instance();
+
+   /**
+    * @brief open that takes a file name.
+    * @param file The file to open.
+    * @param openOverview If true image handler will attempt to open overview.
+    * default = true 
+    * @return pointer to image handler on success, NULL on failure.
+    */
+   virtual ossimImageHandler* open(const ossimFilename& file,
+                                   bool openOverview=true) const;
+
+   /**
+    * @brief open that takes a keyword list and prefix.
+    * @param kwl The keyword list.
+    * @param prefix the keyword list prefix.
+    * @return pointer to image handler on success, NULL on failure.
+    */
+   virtual ossimImageHandler* open(const ossimKeywordlist& kwl,
+                                   const char* prefix=0)const;
+
+   /**
+    * @brief createObject that takes a class name (ossimSqliteReader)
+    * @param typeName Should be "ossimSqliteReader".
+    * @return pointer to image writer on success, NULL on failure.
+    */
+   virtual ossimObject* createObject(const ossimString& typeName)const;
+   
+   /**
+    * @brief Creates and object given a keyword list and prefix.
+    * @param kwl The keyword list.
+    * @param prefix the keyword list prefix.
+    * @return pointer to image handler on success, NULL on failure.
+    */
+   virtual ossimObject* createObject(const ossimKeywordlist& kwl,
+                                     const char* prefix=0)const;
+   
+   /**
+    * @brief Adds ossimSqliteWriter to the typeList.
+    * @param typeList List to add to.
+    */
+   virtual void getTypeNameList(std::vector<ossimString>& typeList)const;
+
+   /**
+    * @brief Method to add supported extension to the list, like "sqlite".
+    *
+    * @param extensionList The list to add to.
+    */
+   virtual void getSupportedExtensions(
+      ossimImageHandlerFactoryBase::UniqueStringList& extensionList)const;
+  
+   virtual void getImageHandlersBySuffix(ImageHandlerList& result,
+                                         const ossimString& ext)const;
+   virtual void getImageHandlersByMimeType(ImageHandlerList& result,
+                                           const ossimString& mimeType)const;
+protected:
+   /** @brief hidden from use default constructor */
+   ossimSqliteReaderFactory();
+
+   /** @brief hidden from use copy constructor */
+   ossimSqliteReaderFactory(const ossimSqliteReaderFactory&);
+
+   /** @brief hidden from use copy constructor */
+   void operator=(const ossimSqliteReaderFactory&);
+
+   /** static instance of this class */
+   static ossimSqliteReaderFactory* theInstance;
+
+TYPE_DATA
+};
+
+#endif /* end of #ifndef ossimSqliteReaderFactory_HEADER */
diff --git a/ossim_plugins/sqlite/ossimSqliteUtil.cpp b/ossim_plugins/sqlite/ossimSqliteUtil.cpp
new file mode 100644
index 0000000..8a3e674
--- /dev/null
+++ b/ossim_plugins/sqlite/ossimSqliteUtil.cpp
@@ -0,0 +1,126 @@
+//----------------------------------------------------------------------------
+// File: ossimGpkgUtil.cpp
+// 
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Description: OSSIM SQLite utility class.
+//----------------------------------------------------------------------------
+// $Id$
+
+#include "ossimSqliteUtil.h"
+#include <ossim/base/ossimNotify.h>
+#include <ossim/base/ossimTrace.h>
+#include <sqlite3.h>
+#include <OpenThreads/Mutex>
+#include <ctime>
+
+static OpenThreads::Mutex timeMutex;
+static ossimTrace traceDebug("ossimSqliteUtil:debug");
+
+int ossim_sqlite::exec( sqlite3* db, const std::string& sql )
+{
+   int rc = SQLITE_ERROR;
+   if ( db && sql.size() )
+   {
+      if (traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG)
+            << "sql:\n" << sql << "\n";
+      }
+
+      sqlite3_stmt* pStmt = 0; // The current SQL statement
+
+      rc = sqlite3_prepare_v2(db,          // Database handle
+                              sql.c_str(), // SQL statement, UTF-8 encoded
+                              -1,          // Maximum length of zSql in bytes.
+                              &pStmt,      // OUT: Statement handle
+                              NULL);
+      if ( rc == SQLITE_OK )
+      {
+         rc = sqlite3_step(pStmt);
+      }
+      else
+      {
+         ossimNotify(ossimNotifyLevel_WARN)
+            << "ossim_sqlite::exec error: " << sqlite3_errmsg(db) << std::endl;
+      }
+      
+      sqlite3_finalize(pStmt);
+   }
+   return rc;
+}
+
+bool ossim_sqlite::tableExists( sqlite3* db, const std::string& tableName )
+{
+   bool status = false;
+   
+   if ( db && tableName.size() )
+   {
+      const char *zLeftover;      /* Tail of unprocessed SQL */
+      sqlite3_stmt *pStmt = 0;    /* The current SQL statement */
+      std::string sql = "SELECT * from ";
+      sql += tableName;
+
+      int rc = sqlite3_prepare_v2(db,           // Database handle
+                                  sql.c_str(),  // SQL statement, UTF-8 encoded
+                                  -1,           // Maximum length of zSql in bytes.
+                                  &pStmt,       // OUT: Statement handle
+                                  &zLeftover);  // OUT: Pointer to unused portion of zSql
+      if ( rc == SQLITE_OK )
+      {
+         int nCol = sqlite3_column_count( pStmt );
+         if ( nCol )
+         {
+            status = true;
+         }
+      }
+      sqlite3_finalize(pStmt);
+   }
+   
+   return status;
+   
+} // End: ossim_sqlite::tableExists(...)
+
+void ossim_sqlite::warn( const std::string& module,
+                         const std::string& columnName,
+                         ossim_int32 columnIndex,
+                         ossim_int32 type )
+{
+   ossimNotify(ossimNotifyLevel_WARN)
+      << module << " Unexpected column name or type[" << columnIndex << "]: "
+      << "name: " << columnName << " type: " << type << std::endl;
+}
+
+void ossim_sqlite::getTime( std::string& result )
+{
+   timeMutex.lock();
+   
+   time_t rawTime;
+   time(&rawTime);
+   
+   struct tm* timeInfo = gmtime(&rawTime);
+
+   size_t size = 0;
+   if ( timeInfo )
+   {
+      const size_t STRING_SIZE = 25;
+      char outStr[STRING_SIZE];
+
+      size = strftime(outStr, STRING_SIZE, "%Y-%m-%dT%H:%M:%S.000Z", timeInfo );
+      if ( size )
+      {
+         // Per strftime spec not needed but null terminating anyway.
+         outStr[STRING_SIZE-1] = '\0';
+         result = outStr;
+      }
+   }
+   if ( !size )
+   {
+      result.clear();
+   }
+
+   timeMutex.unlock();
+}
+
diff --git a/ossim_plugins/sqlite/ossimSqliteUtil.h b/ossim_plugins/sqlite/ossimSqliteUtil.h
new file mode 100644
index 0000000..7ceef97
--- /dev/null
+++ b/ossim_plugins/sqlite/ossimSqliteUtil.h
@@ -0,0 +1,63 @@
+//----------------------------------------------------------------------------
+// File: ossimSqliteUtil.h
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Description: OSSIM SQLite utility class.
+//
+//----------------------------------------------------------------------------
+// $Id
+
+#ifndef ossimSqliteUtil_HEADER
+#define ossimSqliteUtil_HEADER 1
+
+#include <ossim/base/ossimConstants.h>
+#include <string>
+
+struct sqlite3;
+
+namespace ossim_sqlite
+{
+   /**
+    * @brief Preforms sqlite3_prepare_v2, sqlite3_step and sqlite3_finalize.
+    * @param db
+    * @param sql 
+    * @return return code of last command executed.  Typically this is the
+    * return of sqlite3_step but could be return of sqlite3_prepare_v2 if
+    * it had an error, i.e. return is not SQLITE_OK.
+    */   
+   int exec( sqlite3* db, const std::string& sql );
+
+   /**
+    * @brief Checks for existance of table.
+    * @param db An open database.
+    * @param tableName e.g. "gpkg_contents"
+    * @return true on success, false on error.
+    */
+   bool tableExists( sqlite3* db, const std::string& tableName );
+
+   /**
+    * @brief Outputs formated warning message.
+    * @param module e.g. "ossimGpkgNsgTileMatrixSetRecord::init"
+    * @param columnName e.g. "zoom_level", from sqlite3_column_name(...)
+    * @param columnIndex zero based column index.
+    * @param type Type from sqlite3_column_type(...)
+    */
+   void warn( const std::string& module,
+              const std::string& columnName,
+              ossim_int32 columnIndex,
+              ossim_int32 type );
+
+   /**
+    * @brief Gets time in the form of "%Y-%m-%dT%H:%M:%S.000Z".
+    * e.g. 2015-02-10T19:32:15.000Z
+    * @param result Initialized by this.
+    */
+   void getTime( std::string& result );
+   
+} // End: namespace ossim_sqlite
+
+#endif /* #ifndef ossimSqliteUtil_HEADER */
+
diff --git a/ossim_plugins/sqlite/ossimSqliteWriterFactory.cpp b/ossim_plugins/sqlite/ossimSqliteWriterFactory.cpp
new file mode 100644
index 0000000..542beef
--- /dev/null
+++ b/ossim_plugins/sqlite/ossimSqliteWriterFactory.cpp
@@ -0,0 +1,146 @@
+//----------------------------------------------------------------------------
+//
+// License:  See top level LICENSE.txt file
+//
+// Author:  David Burken
+//
+// Description: Factory for OSSIM SQLite writer factory.
+//----------------------------------------------------------------------------
+// $Id$
+
+#include "ossimSqliteWriterFactory.h"
+#include "ossimGpkgWriter.h"
+#include <ossim/base/ossimKeywordNames.h>
+#include <ossim/base/ossimRefPtr.h>
+#include <ossim/imaging/ossimImageFileWriter.h>
+
+ossimSqliteWriterFactory* ossimSqliteWriterFactory::theInstance = 0;
+
+RTTI_DEF1(ossimSqliteWriterFactory,
+          "ossimSqliteWriterFactory",
+          ossimImageWriterFactoryBase);
+
+ossimSqliteWriterFactory::~ossimSqliteWriterFactory()
+{
+   theInstance = 0;
+}
+
+ossimSqliteWriterFactory* ossimSqliteWriterFactory::instance()
+{
+   if(!theInstance)
+   {
+      theInstance = new ossimSqliteWriterFactory;
+   }
+   return theInstance;
+}
+
+ossimImageFileWriter* ossimSqliteWriterFactory::createWriterFromExtension(
+   const ossimString& fileExtension)const
+{
+   ossimRefPtr<ossimGpkgWriter> writer = 0;
+   if ( (fileExtension == "gpkg") || (fileExtension == ".gpkg") )
+   {
+      writer = new ossimGpkgWriter();
+   }
+   return writer.release();
+}
+
+ossimImageFileWriter*
+ossimSqliteWriterFactory::createWriter(const ossimKeywordlist& kwl,
+                                    const char *prefix)const
+{
+   ossimRefPtr<ossimImageFileWriter> writer = 0;
+   const char* type = kwl.find(prefix, ossimKeywordNames::TYPE_KW);
+   if (type)
+   {
+      writer = createWriter(ossimString(type));
+      if ( writer.valid() )
+      {
+         if (writer->loadState(kwl, prefix) == false)
+         {
+            writer = 0;
+         }
+      }
+   }
+   return writer.release();
+}
+
+ossimImageFileWriter* ossimSqliteWriterFactory::createWriter(
+   const ossimString& typeName)const
+{
+   ossimRefPtr<ossimImageFileWriter> writer = 0;
+   if (typeName == "ossimGpkgWriter")
+   {
+      writer = new ossimGpkgWriter();
+   }
+   else
+   {
+      // See if the type name is supported by the writer.
+      writer = new ossimGpkgWriter();
+      if ( writer->hasImageType(typeName) == false )
+      {
+         writer = 0;
+      }
+   }
+   return writer.release();
+}
+
+ossimObject* ossimSqliteWriterFactory::createObject(const ossimKeywordlist& kwl,
+                                                 const char *prefix)const
+{
+   return createWriter(kwl, prefix);
+}
+
+ossimObject* ossimSqliteWriterFactory::createObject(
+   const ossimString& typeName) const
+{
+   return createWriter(typeName);
+}
+
+void ossimSqliteWriterFactory::getExtensions(
+   std::vector<ossimString>& result)const
+{
+   result.push_back("gpkg");
+}
+
+void ossimSqliteWriterFactory::getTypeNameList(std::vector<ossimString>& typeList)const
+{
+   typeList.push_back(ossimString("ossimGpkgWriter"));
+}
+
+void ossimSqliteWriterFactory::getImageTypeList(std::vector<ossimString>& imageTypeList)const
+{
+   ossimRefPtr<ossimGpkgWriter> writer = new ossimGpkgWriter;
+   writer->getImageTypeList(imageTypeList);
+   writer = 0;
+}
+
+void ossimSqliteWriterFactory::getImageFileWritersBySuffix(
+   ossimImageWriterFactoryBase::ImageFileWriterList& result, const ossimString& ext)const
+{
+   ossimString testExt = ext.downcase();
+   if(testExt == "gpkg")
+   {
+      result.push_back(new ossimGpkgWriter);
+   }
+}
+
+void ossimSqliteWriterFactory::getImageFileWritersByMimeType(
+   ossimImageWriterFactoryBase::ImageFileWriterList& result, const ossimString& mimeType)const
+{
+   ossimString testMime = mimeType.downcase();
+   if(testMime == "image/gpkg")
+   {
+      result.push_back(new ossimGpkgWriter);
+   }
+}
+
+ossimSqliteWriterFactory::ossimSqliteWriterFactory(){}
+
+ossimSqliteWriterFactory::ossimSqliteWriterFactory(const ossimSqliteWriterFactory&){}
+
+void ossimSqliteWriterFactory::operator=(const ossimSqliteWriterFactory&){}
+
+
+
+
diff --git a/ossim_plugins/sqlite/ossimSqliteWriterFactory.h b/ossim_plugins/sqlite/ossimSqliteWriterFactory.h
new file mode 100644
index 0000000..c222d29
--- /dev/null
+++ b/ossim_plugins/sqlite/ossimSqliteWriterFactory.h
@@ -0,0 +1,112 @@
+//----------------------------------------------------------------------------
+//
+// License:  See top level LICENSE.txt file
+//
+// Author:  David Burken
+//
+// Description: Factory for OSSIM SQLite writer factory.
+//----------------------------------------------------------------------------
+// $Id$ 
+
+#ifndef ossimSqliteWriterFactory_HEADER
+#define ossimSqliteWriterFactory_HEADER 1
+#include <ossim/imaging/ossimImageWriterFactoryBase.h>
+
+class ossimImageFileWriter;
+class ossimKeywordlist;
+class ossimImageWriterFactory;
+
+/** @brief Factory for SQLITE image writer. */
+class ossimSqliteWriterFactory: public ossimImageWriterFactoryBase
+{   
+public:
+
+   /** @brief virtual destructor */
+   virtual ~ossimSqliteWriterFactory();
+
+   /**
+    * @brief static method to return instance (the only one) of this class.
+    * @return pointer to instance of this class.
+    */
+   static ossimSqliteWriterFactory* instance();
+
+   /**
+    * @brief Creates a writer from extension like "sqlite".
+    * @param fileExtension "sqlite"
+    */
+   virtual ossimImageFileWriter *createWriterFromExtension(
+      const ossimString& fileExtension)const;
+
+   /**
+    * @brief Create that takes a keyword list and prefix.
+    * @param kwl The keyword list.
+    * @param prefix the keyword list prefix.
+    * @return pointer to image handler on success, NULL on failure.
+    */
+   virtual ossimImageFileWriter* createWriter(const ossimKeywordlist& kwl,
+                                              const char *prefix=0)const;
+
+   /**
+    * @brief createWriter that takes a class name (ossimSqliteWriter)
+    * @param kwl The keyword list.
+    * @param prefix the keyword list prefix.
+    * @return pointer to image writer on success, NULL on failure.
+    */
+   virtual ossimImageFileWriter* createWriter(const ossimString& typeName)const;
+
+   /**
+    * @brief Creates and object given a keyword list.
+    * @param kwl The keyword list.
+    * @param prefix the keyword list prefix.
+    * @return pointer to image writer on success, NULL on failure.
+    */
+   virtual ossimObject* createObject(const ossimKeywordlist& kwl,
+                                     const char *prefix=0)const;
+
+   /**
+    * @brief createObject that takes a class name (ossimSqliteWriter)
+    * @param typeName Should be "ossimSqliteReader".
+    * @return pointer to image writer on success, NULL on failure.
+    */
+   virtual ossimObject* createObject(const ossimString& typeName)const;
+
+
+   /**
+    * @brief Adds "sqlite" to list.
+    * @param extList List to add to.
+    */
+   virtual void getExtensions(std::vector<ossimString>& extList)const;
+
+   /**
+    * @brief Adds "ossimSqliteWriter" to list.
+    * @param typeList List to add to.
+    */
+   virtual void getTypeNameList(std::vector<ossimString>& typeList)const;
+   
+   /**
+    * @brief Adds "ossim_sqlite" to writer list.
+    * @param imageTypeList List to append to.
+    */
+   virtual void getImageTypeList(std::vector<ossimString>& imageTypeList)const;
+   
+   virtual void getImageFileWritersBySuffix(ossimImageWriterFactoryBase::ImageFileWriterList& result,
+                                            const ossimString& ext)const;
+   virtual void getImageFileWritersByMimeType(ossimImageWriterFactoryBase::ImageFileWriterList& result,
+                                              const ossimString& mimeType)const;
+protected:
+   /** @brief hidden from use default constructor */
+   ossimSqliteWriterFactory();
+
+   /** @brief hidden from use copy constructor */
+   ossimSqliteWriterFactory(const ossimSqliteWriterFactory&);
+
+   /** @brief hidden from use copy constructor */
+   void operator=(const ossimSqliteWriterFactory&);
+
+   /** static instance of this class */
+   static ossimSqliteWriterFactory* theInstance;
+
+TYPE_DATA
+};
+
+#endif /* end of #ifndef ossimSqliteWriterFactory_HEADER */
diff --git a/ossim_plugins/unit_test/ossimUnitTestImageSourceFactory.cpp b/ossim_plugins/unit_test/ossimUnitTestImageSourceFactory.cpp
new file mode 100644
index 0000000..fdfd36d
--- /dev/null
+++ b/ossim_plugins/unit_test/ossimUnitTestImageSourceFactory.cpp
@@ -0,0 +1,100 @@
+#include "ossimUnitTestImageSourceFactory.h"
+#include <ossim/base/ossimObjectFactoryRegistry.h>
+#include <ossim/base/ossimTrace.h>
+#include <ossim/base/ossimKeywordlist.h>
+#include "ossimUnitTestPolyCutter.h"
+
+RTTI_DEF1(ossimUnitTestImageSourceFactory, "ossimUnitTestImageSourceFactory", ossimImageSourceFactoryBase);
+
+ossimUnitTestImageSourceFactory* ossimUnitTestImageSourceFactory::theInstance=0;
+static ossimTrace traceDebug("ossimUnitTestImageSourceFactory:debug");
+
+ossimUnitTestImageSourceFactory::ossimUnitTestImageSourceFactory()
+{
+   theInstance = this;
+}
+
+ossimUnitTestImageSourceFactory::ossimUnitTestImageSourceFactory(const ossimUnitTestImageSourceFactory& rhs)
+{
+   theInstance = this;
+}
+
+const ossimUnitTestImageSourceFactory& ossimUnitTestImageSourceFactory::operator=(ossimUnitTestImageSourceFactory&)
+{
+   return *this;
+}
+
+ossimUnitTestImageSourceFactory::~ossimUnitTestImageSourceFactory()
+{
+   theInstance = NULL;
+   ossimObjectFactoryRegistry::instance()->unregisterFactory(this);
+}
+
+ossimUnitTestImageSourceFactory* ossimUnitTestImageSourceFactory::instance()
+{
+   if(!theInstance)
+   {
+      theInstance = new ossimUnitTestImageSourceFactory;
+   }
+
+   return theInstance;
+}
+
+ossimObject* ossimUnitTestImageSourceFactory::createObject(const ossimString& name)const
+{
+   if(name==STATIC_TYPE_NAME(ossimUnitTestPolyCutter))
+   {
+      return new ossimUnitTestPolyCutter;
+   }
+   return 0;
+}
+
+ossimObject* ossimUnitTestImageSourceFactory::createObject(const ossimKeywordlist& kwl,
+                                                   const char* prefix)const
+{
+   static const char* MODULE = "ossimUnitTestImageSourceFactory::createObject";
+   
+   ossimString copyPrefix = prefix;
+   ossimObject* result = NULL;
+   
+   if(traceDebug())
+   {
+      CLOG << "looking up type keyword for prefix = " << copyPrefix << std::endl;
+   }
+
+   const char* lookup = kwl.find(copyPrefix, "type");
+   if(lookup)
+   {
+      ossimString name = lookup;
+      result           = createObject(name);
+      
+      if(result)
+      {
+         if(traceDebug())
+         {
+            CLOG << "found source " << result->getClassName() << " now loading state" << std::endl;
+         }
+         result->loadState(kwl, copyPrefix.c_str());
+      }
+      else
+      {
+         if(traceDebug())
+         {
+            CLOG << "type not found " << lookup << std::endl;
+         }
+      }
+   }
+   else
+   {
+      if(traceDebug())
+      {
+         CLOG << "type keyword not found" << std::endl;
+      }
+   }
+   return result;
+}
+
+void ossimUnitTestImageSourceFactory::getTypeNameList(std::vector<ossimString>& typeList)const
+{
+   typeList.push_back("ossimUnitTestPolyCutter");
+}
diff --git a/ossim_plugins/unit_test/ossimUnitTestImageSourceFactory.h b/ossim_plugins/unit_test/ossimUnitTestImageSourceFactory.h
new file mode 100644
index 0000000..f81ed5d
--- /dev/null
+++ b/ossim_plugins/unit_test/ossimUnitTestImageSourceFactory.h
@@ -0,0 +1,23 @@
+#ifndef ossimUnitTestImageSourceFactory_HEADER
+#define ossimUnitTestImageSourceFactory_HEADER
+#include <ossim/imaging/ossimImageSourceFactoryBase.h>
+
+class ossimUnitTestImageSourceFactory : public ossimImageSourceFactoryBase
+{
+public:
+   virtual ~ossimUnitTestImageSourceFactory();
+   static ossimUnitTestImageSourceFactory* instance();
+   virtual ossimObject* createObject(const ossimString& name)const;
+   virtual ossimObject* createObject(const ossimKeywordlist& kwl,
+                                     const char* prefix=0)const;
+   
+   virtual void getTypeNameList(std::vector<ossimString>& typeList)const;
+protected:
+   // Hide from use.
+   ossimUnitTestImageSourceFactory();
+   ossimUnitTestImageSourceFactory(const ossimUnitTestImageSourceFactory&);
+   const ossimUnitTestImageSourceFactory& operator=(ossimUnitTestImageSourceFactory&);
+
+   static ossimUnitTestImageSourceFactory* theInstance;
+TYPE_DATA};
+#endif
diff --git a/ossim_plugins/unit_test/ossimUnitTestPluginInit.cpp b/ossim_plugins/unit_test/ossimUnitTestPluginInit.cpp
new file mode 100644
index 0000000..5d84a06
--- /dev/null
+++ b/ossim_plugins/unit_test/ossimUnitTestPluginInit.cpp
@@ -0,0 +1,76 @@
+//*******************************************************************
+// Copyright (C) 2005 David Burken, all rights reserved.
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author:  David Burken
+//*******************************************************************
+//  $Id: ossimUnitTestPluginInit.cpp 23664 2015-12-14 14:17:27Z dburken $
+#include <gdal.h>
+#include <ossim/plugin/ossimSharedObjectBridge.h>
+#include <ossimPluginConstants.h>
+#include <ossim/imaging/ossimImageHandlerRegistry.h>
+#include <ossim/imaging/ossimImageSourceFactoryRegistry.h>
+#include <ossim/imaging/ossimImageWriterFactoryRegistry.h>
+#include <ossim/projection/ossimProjectionFactoryRegistry.h>
+#include "ossimUnitTestImageSourceFactory.h"
+
+static void setDescription(ossimString& description)
+{
+   description = "Unit test Plugin\n\n"
+      "Tests parts of the OSSIM library.  This is mainly\n"
+      "used for interactive GUI testing.  Components tested:\n"
+      "ossimPolyCutter";
+}
+
+
+extern "C"
+{
+   ossimSharedObjectInfo  myInfo;
+   ossimString theDescription;
+   std::vector<ossimString> theObjList;
+   const char* getDescription()
+   {
+      return theDescription.c_str();
+   }
+   int getNumberOfClassNames()
+   {
+      return (int)theObjList.size();
+   }
+   const char* getClassName(int idx)
+   {
+      if(idx < (int)theObjList.size())
+      {
+         return theObjList[0].c_str();
+      }
+      return (const char*)0;
+   }
+
+   /* Note symbols need to be exported on windoze... */ 
+   OSSIM_PLUGINS_DLL void ossimSharedLibraryInitialize(
+      ossimSharedObjectInfo** info)
+   {
+      myInfo.getDescription = getDescription;
+      myInfo.getNumberOfClassNames = getNumberOfClassNames;
+      myInfo.getClassName = getClassName;
+      
+      *info = &myInfo;
+
+      /* Register the readers... */
+      ossimImageSourceFactoryRegistry::instance()->
+         registerFactory(ossimUnitTestImageSourceFactory::instance());
+      
+      setDescription(theDescription);
+   }
+   
+   /* Note symbols need to be exported on windoze... */ 
+   OSSIM_PLUGINS_DLL void ossimSharedLibraryFinalize()
+   {
+      ossimImageSourceFactoryRegistry::instance()->
+         registerFactory(ossimUnitTestImageSourceFactory::instance());
+      
+   }
+}
+
diff --git a/ossim_plugins/unit_test/ossimUnitTestPolyCutter.cpp b/ossim_plugins/unit_test/ossimUnitTestPolyCutter.cpp
new file mode 100644
index 0000000..4b9a472
--- /dev/null
+++ b/ossim_plugins/unit_test/ossimUnitTestPolyCutter.cpp
@@ -0,0 +1,122 @@
+#include "ossimUnitTestPolyCutter.h"
+#include <ossim/base/ossimStringProperty.h>
+#include <ossim/base/ossimNumericProperty.h>
+
+RTTI_DEF1(ossimUnitTestPolyCutter, "ossimUnitTestPolyCutter", ossimPolyCutter);
+
+ossimUnitTestPolyCutter::ossimUnitTestPolyCutter()
+   :theSeed(0),
+    theNumberOfPoints(10)
+{
+}
+
+void ossimUnitTestPolyCutter::setProperty(ossimRefPtr<ossimProperty> property)
+{
+   ossimString tempName = property->getName();
+   if(tempName == "seed")
+   {
+      
+      theSeed = property->valueToString().toUInt32();
+
+      recompute();
+      return;
+   }
+   else if(tempName == "number_of_points")
+   {
+      theNumberOfPoints = property->valueToString().toUInt32();
+      recompute();
+      return;
+   }
+   
+   ossimPolyCutter::setProperty(property);
+}
+
+ossimRefPtr<ossimProperty> ossimUnitTestPolyCutter::getProperty(const ossimString& name)const
+{
+   if(name == "seed")
+   {
+      ossimNumericProperty* prop = new ossimNumericProperty(name,
+                                                            ossimString::toString(theSeed));
+      prop->setNumericType(ossimNumericProperty::ossimNumericPropertyType_UINT);
+      prop->setReadOnlyFlag(false);
+      prop->setFullRefreshBit();
+      return prop;
+   }
+   if(name == "number_of_points")
+   {
+      ossimNumericProperty* prop = new ossimNumericProperty(name,
+                                                            ossimString::toString(theNumberOfPoints),
+                                                            10,
+                                                            500);
+      prop->setNumericType(ossimNumericProperty::ossimNumericPropertyType_UINT);
+      prop->setReadOnlyFlag(false);
+      prop->setFullRefreshBit();
+      return prop;
+   }
+   
+   return ossimPolyCutter::getProperty(name);
+}
+
+void ossimUnitTestPolyCutter::getPropertyNames(std::vector<ossimString>& propertyNames)const
+{
+   ossimPolyCutter::getPropertyNames(propertyNames);
+   propertyNames.push_back("seed");
+   propertyNames.push_back("number_of_points");
+}
+
+void ossimUnitTestPolyCutter::recompute()
+{
+   thePolygonList.clear();
+   computeBoundingRect();
+   
+   
+   ossimPolygon poly;
+   
+   ossimIrect rect = getBoundingRect();
+   ossimIpt midPoint = rect.midPoint();
+   
+   double radius = ossimMin(rect.width(),
+                            rect.height())/2.0;
+   
+   srand(theSeed);
+   //
+   // calculate a random circle radius
+   // x = r*cos(theta);
+   // y = r*sin(theta);
+   //
+   ossim_float32 idxDegree = 0;
+   ossim_float32 increment = 360.0/theNumberOfPoints;
+   for(idxDegree = 0; idxDegree < 360; idxDegree+=increment)
+   {
+      double tr = ((rand()/(double)RAND_MAX)*(radius/2.0));
+      
+      ossimDpt pt((tr+(radius/2.0))*cosd(idxDegree),
+                  (tr+(radius/2.0))*sind(idxDegree));
+      
+      pt += midPoint;
+      poly.addPoint(pt);
+   }
+   poly.checkOrdering();
+   if(poly.getOrdering()==OSSIM_COUNTERCLOCKWISE_ORDER)
+   {
+      poly.reverseOrder();
+   }
+   addPolygon(poly);
+}
+
+bool ossimUnitTestPolyCutter::saveState(ossimKeywordlist& kwl,
+                                        const char* prefix)const
+{
+   return ossimPolyCutter::saveState(kwl, prefix);
+}
+   
+   /*!
+    * Method to the load (recreate) the state of an object from a keyword
+    * list.  Return true if ok or false on error.
+    */
+bool ossimUnitTestPolyCutter::loadState(const ossimKeywordlist& kwl,
+                                        const char* prefix)
+{
+   return ossimPolyCutter::loadState(kwl, prefix);
+   
+}
diff --git a/ossim_plugins/unit_test/ossimUnitTestPolyCutter.h b/ossim_plugins/unit_test/ossimUnitTestPolyCutter.h
new file mode 100644
index 0000000..c8f9288
--- /dev/null
+++ b/ossim_plugins/unit_test/ossimUnitTestPolyCutter.h
@@ -0,0 +1,34 @@
+#ifndef ossimUnitTestPolyCutter_HEADER
+#define ossimUnitTestPolyCutter_HEADER
+#include <ossim/imaging/ossimPolyCutter.h>
+
+class ossimUnitTestPolyCutter : public ossimPolyCutter
+{
+public:
+   ossimUnitTestPolyCutter();
+   virtual void setProperty(ossimRefPtr<ossimProperty> property);
+   virtual ossimRefPtr<ossimProperty> getProperty(const ossimString& name)const;
+   virtual void getPropertyNames(std::vector<ossimString>& propertyNames)const;
+
+   virtual bool saveState(ossimKeywordlist& kwl,
+                          const char* prefix=0)const;
+   
+   /*!
+    * Method to the load (recreate) the state of an object from a keyword
+    * list.  Return true if ok or false on error.
+    */
+   virtual bool loadState(const ossimKeywordlist& kwl,
+                          const char* prefix=0);
+   
+protected:
+   void recompute();
+   
+   ossim_uint32 theSeed;
+   ossim_uint32 theNumberOfPoints;
+   
+   
+   
+TYPE_DATA
+};
+
+#endif
diff --git a/ossim_plugins/unit_test/unit_test.vcproj b/ossim_plugins/unit_test/unit_test.vcproj
new file mode 100644
index 0000000..235f06d
--- /dev/null
+++ b/ossim_plugins/unit_test/unit_test.vcproj
@@ -0,0 +1,153 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="7.10"
+	Name="ossimunit_test_plugin"
+	ProjectGUID="{ABC4B8B6-8C4F-405D-A370-FD5F22510771}"
+	Keyword="Win32Proj">
+	<Platforms>
+		<Platform
+			Name="Win32"/>
+	</Platforms>
+	<Configurations>
+		<Configuration
+			Name="Debug|Win32"
+			OutputDirectory="Debug"
+			IntermediateDirectory="Debug"
+			ConfigurationType="2"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="..\;..\..\ossim\include;..\..\3rdParty\include\;..\..\OpenThreads\include\"
+				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;UNIT_TEST_EXPORTS"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				OutputFile="$(OutDir)/unit_test.dll"
+				LinkIncremental="2"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/unit_test.pdb"
+				SubSystem="2"
+				ImportLibrary="$(OutDir)/unit_test.lib"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+		<Configuration
+			Name="Release|Win32"
+			OutputDirectory="Release"
+			IntermediateDirectory="Release"
+			ConfigurationType="2"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				InlineFunctionExpansion="1"
+				AdditionalIncludeDirectories="..\;..\..\ossim\include;..\..\3rdParty\include\;..\..\OpenThreads\include\"
+				PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;OSSIMUSINGDLL;HAVE_CONFIG_H"
+				RuntimeLibrary="2"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="FALSE"
+				DebugInformationFormat="0"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				OutputFile="$(SolutionDir)bin\ossimunit_test_plugin.dll"
+				LinkIncremental="1"
+				SuppressStartupBanner="TRUE"
+				AdditionalLibraryDirectories="..\..\3rdParty\lib\"
+				IgnoreDefaultLibraryNames="libcd"
+				GenerateDebugInformation="FALSE"
+				SubSystem="2"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				SupportUnloadOfDelayLoadedDLL="TRUE"
+				ImportLibrary="$(OutDir)/unit_test.lib"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="Source Files"
+			Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
+			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
+			<File
+				RelativePath=".\ossimUnitTestImageSourceFactory.cpp">
+			</File>
+			<File
+				RelativePath=".\ossimUnitTestPluginInit.cpp">
+			</File>
+			<File
+				RelativePath=".\ossimUnitTestPolyCutter.cpp">
+			</File>
+		</Filter>
+		<Filter
+			Name="Header Files"
+			Filter="h;hpp;hxx;hm;inl;inc;xsd"
+			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">
+			<File
+				RelativePath=".\ossimUnitTestImageSourceFactory.h">
+			</File>
+			<File
+				RelativePath=".\ossimUnitTestPolyCutter.h">
+			</File>
+		</Filter>
+		<Filter
+			Name="Resource Files"
+			Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
+			UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}">
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
diff --git a/ossim_plugins/web/CMakeLists.txt b/ossim_plugins/web/CMakeLists.txt
new file mode 100644
index 0000000..7f84933
--- /dev/null
+++ b/ossim_plugins/web/CMakeLists.txt
@@ -0,0 +1,52 @@
+set(LIB_NAME ossimweb_plugin)
+MESSAGE( "**************START  LIBRARY SETUP FOR ossimweb_plugin******************")
+
+# Include ossim cmake stuff:
+include(OssimVersion)
+include(OssimCommonVariables)
+include(OssimUtilities)
+
+find_package(ossim)
+find_package(OpenThreads)
+find_package(TIFF)
+find_package(CURL)
+
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
+INCLUDE_DIRECTORIES(${OPENTHREADS_INCLUDE_DIR})
+INCLUDE_DIRECTORIES(${TIFF_INCLUDE_DIR})
+INCLUDE_DIRECTORIES(${CURL_INCLUDE_DIR})
+
+FILE(GLOB OSSIMPLUGIN_SRCS *.cpp)
+FILE(GLOB OSSIMPLUGIN_HEADERS *.h)
+
+MESSAGE( STATUS "OSSIM_LIBRARIES = ${OSSIM_LIBRARIES}")
+
+IF(NOT CURL_INCLUDE_DIR)
+  MESSAGE( STATUS "************ OSSIM WEB PLUGIN CAN'T BE COMPILED, NO CURL SUPPORT FOUND*************")
+  INCLUDE_DIRECTORIES(${CURL_INCLUDE_DIR})
+ENDIF()
+
+MESSAGE( STATUS "CURL_INCLUDE_DIR = ${CURL_INCLUDE_DIR}")
+MESSAGE( STATUS "CURL_LIBRARIES   = ${CURL_LIBRARIES}")
+
+#---
+# OSSIMPLUGINSMAKINGDLL controls dll linkage on windows.  
+# Adding this sets OSSIM_PLUGINS_DLL #define TO "__declspec(dllexport)".
+#---
+add_definitions("-DOSSIMPLUGINSMAKINGDLL")
+
+# Adjust the install library path:
+if(OSSIM_INSTALL_PLUGINS_WITH_VERSION)
+   set(INSTALL_LIBRARY_DIR   "${INSTALL_LIBRARY_DIR}/ossim-${OSSIM_VERSION}/plugins")
+else(OSSIM_INSTALL_PLUGINS_WITH_VERSION)
+   set(INSTALL_LIBRARY_DIR   "${INSTALL_LIBRARY_DIR}/ossim/plugins")
+endif(OSSIM_INSTALL_PLUGINS_WITH_VERSION)
+
+OSSIM_LINK_LIBRARY(${LIB_NAME}
+                   COMPONENT_NAME ossim TYPE "${OSSIM_PLUGIN_LINK_TYPE}"
+		   LIBRARIES ${OSSIM_LIBRARIES} ${OPENTHREADS_LIBRARY} ${TIFF_LIBRARY} ${CURL_LIBRARIES}
+                   HEADERS "${OSSIMPLUGIN_HEADERS}" 
+		   SOURCE_FILES "${OSSIMPLUGIN_SRCS}"
+                   INSTALL_LIB)
+
+MESSAGE( "************** END LIBRARY SETUP FOR ossimweb_plugin******************")
diff --git a/ossim_plugins/web/ossimCurlHttpRequest.cpp b/ossim_plugins/web/ossimCurlHttpRequest.cpp
new file mode 100644
index 0000000..94ee638
--- /dev/null
+++ b/ossim_plugins/web/ossimCurlHttpRequest.cpp
@@ -0,0 +1,110 @@
+#include "ossimCurlHttpRequest.h"
+
+ossimWebResponse* ossimCurlHttpRequest::getResponse()
+{
+   if(m_response.valid()) return m_response.get();
+   m_response = 0;
+   ossimString protocol = getUrl().getProtocol();
+   if(!supportsProtocol(protocol)) return 0;
+   switch (m_methodType) 
+   {
+      case ossimHttpRequest::HTTP_METHOD_GET:
+      {
+         m_response = new ossimCurlHttpResponse();
+         
+         curl_easy_setopt(m_curl, CURLOPT_HEADERFUNCTION, curlWriteResponseHeader);
+         curl_easy_setopt(m_curl, CURLOPT_HEADERDATA, (void*)m_response.get());
+         curl_easy_setopt(m_curl, CURLOPT_WRITEFUNCTION, curlWriteResponseBody);
+         curl_easy_setopt(m_curl, CURLOPT_WRITEDATA, (void*)m_response.get());
+         //curl_easy_setopt(m_curl, CURLOPT_CONNECT_ONLY, 1);
+         ossimKeywordlist::KeywordMap& headerMap = m_headerOptions.getMap();
+         struct curl_slist *headers=0; /* init to NULL is important */
+         
+         ossimKeywordlist::KeywordMap::iterator iter = headerMap.begin();
+         while(iter != headerMap.end())
+         {
+            //std::cout << ((*iter).first + ":"+(*iter).second).c_str() << std::endl;
+            headers = curl_slist_append(headers, ((*iter).first + ":"+(*iter).second).c_str());
+            ++iter;
+         }
+         ossimString urlString = getUrl().toString();
+         curl_easy_setopt(m_curl, CURLOPT_URL, urlString.c_str());
+         
+         
+         if(protocol == "https")
+         {
+            curl_easy_setopt(m_curl, CURLOPT_SSLVERSION, CURL_SSLVERSION_SSLv3);//);
+            curl_easy_setopt(m_curl, CURLOPT_SSL_VERIFYPEER, 0L);
+         }
+         
+         
+         int rc = curl_easy_perform(m_curl);
+         
+         if(rc == CURLE_SSL_CONNECT_ERROR)
+         {
+            // try default if an error for SSL connect ocurred
+            curl_easy_setopt(m_curl, CURLOPT_SSLVERSION, CURL_SSLVERSION_DEFAULT);
+            rc = curl_easy_perform(m_curl);
+         }
+         bool result = (rc < 1);
+         if(result)
+         {
+            m_response->convertHeaderStreamToKeywordlist();
+         }
+         else
+         {
+            m_lastError = curl_easy_strerror((CURLcode)rc);
+            //std::cout << curl_easy_strerror((CURLcode)rc) << std::endl;
+            m_response = 0;
+         }
+         break;
+      }
+         
+      default:
+         break;
+   }
+   
+   return m_response.get();
+}
+
+bool ossimCurlHttpRequest::supportsProtocol(const ossimString& protocol)const
+{
+   bool result = false;
+   if(protocol == "http")
+   {
+      result = true;
+   }
+   else if(protocol == "https")
+   {
+      curl_version_info_data * vinfo = curl_version_info( CURLVERSION_NOW ); 
+      if( vinfo->features & CURL_VERSION_SSL ) 
+      { 
+         result = true;
+      } 
+   }
+   return result;
+}
+
+int ossimCurlHttpRequest::curlWriteResponseBody(void *buffer, size_t size, size_t nmemb, void *stream)
+{
+   ossimHttpResponse* cStream = static_cast<ossimHttpResponse*>(stream);
+   if(cStream)
+   {
+      cStream->bodyStream().write((char*)buffer, nmemb*size);
+      return nmemb*size;
+   }
+   
+   return 0;
+}
+
+int ossimCurlHttpRequest::curlWriteResponseHeader(void *buffer, size_t size, size_t nmemb, void *stream)
+{
+   ossimHttpResponse* cStream = static_cast<ossimHttpResponse*>(stream);
+   if(cStream)
+   {
+      cStream->headerStream().write((char*)buffer, nmemb*size);
+      return nmemb*size;
+   }
+   
+   return 0;
+}
diff --git a/ossim_plugins/web/ossimCurlHttpRequest.h b/ossim_plugins/web/ossimCurlHttpRequest.h
new file mode 100644
index 0000000..d894e1b
--- /dev/null
+++ b/ossim_plugins/web/ossimCurlHttpRequest.h
@@ -0,0 +1,44 @@
+#ifndef ossimCurlHttpRequest_HEADER
+#define ossimCurlHttpRequest_HEADER
+#include <ossim/base/ossimHttpResponse.h>
+#include <ossim/base/ossimHttpRequest.h>
+#include <curl/curl.h>
+
+class ossimCurlHttpResponse : public ossimHttpResponse
+{
+public:
+   
+};
+
+class ossimCurlHttpRequest : public ossimHttpRequest
+{
+public:
+   ossimCurlHttpRequest()
+   :m_curl(0)
+   {
+      m_curl = curl_easy_init();
+   }
+   virtual ~ossimCurlHttpRequest()
+   {
+      if(m_curl)
+      {
+         curl_easy_cleanup(m_curl);
+         m_curl = 0;
+      }
+   }
+   virtual ossimWebResponse* getResponse();
+   virtual bool supportsProtocol(const ossimString& protocol)const;
+   static int curlWriteResponseBody(void *buffer, size_t size, size_t nmemb, void *stream);
+   static int curlWriteResponseHeader(void *buffer, size_t size, size_t nmemb, void *stream);
+   
+   virtual bool loadState(const ossimKeywordlist& kwl, const char* prefix=0)
+   {
+      m_response = 0;
+      return ossimHttpRequest::loadState(kwl, prefix);
+   }
+   
+protected:
+   CURL* m_curl;
+   mutable ossimRefPtr<ossimCurlHttpResponse> m_response;
+};
+#endif
diff --git a/ossim_plugins/web/ossimWebPluginInit.cpp b/ossim_plugins/web/ossimWebPluginInit.cpp
new file mode 100644
index 0000000..62f934c
--- /dev/null
+++ b/ossim_plugins/web/ossimWebPluginInit.cpp
@@ -0,0 +1,82 @@
+//----------------------------------------------------------------------------
+//
+// License:  See top level LICENSE.txt file
+//
+// Author:  David Burken
+//
+// Description: OSSIM Kakadu plugin initialization
+// code.
+//
+//----------------------------------------------------------------------------
+// $Id: ossimKakaduPluginInit.cpp 20202 2011-11-04 13:57:13Z gpotts $
+
+#include "../ossimPluginConstants.h"
+#include <ossim/plugin/ossimSharedPluginRegistry.h>
+#include <ossim/base/ossimString.h>
+#include <ossim/base/ossimKeywordlist.h>
+#include <ossim/base/ossimWebRequestFactoryRegistry.h>
+#include "ossimWebPluginRequestFactory.h"
+static void setDescription(ossimString& description)
+{
+   description = "Web plugin\n";
+   description += "\tsupport http, https web protocols\n";
+}
+
+
+extern "C"
+{
+   ossimSharedObjectInfo  myInfo;
+   ossimString theDescription;
+   std::vector<ossimString> theObjList;
+
+   const char* getDescription()
+   {
+      return theDescription.c_str();
+   }
+
+   int getNumberOfClassNames()
+   {
+      return (int)theObjList.size();
+   }
+
+   const char* getClassName(int idx)
+   {
+      if(idx < (int)theObjList.size())
+      {
+         return theObjList[0].c_str();
+      }
+      return (const char*)0;
+   }
+
+   /* Note symbols need to be exported on windoze... */ 
+   OSSIM_PLUGINS_DLL void ossimSharedLibraryInitialize(
+                                                       ossimSharedObjectInfo** info, 
+                                                       const char* options)
+   {    
+      myInfo.getDescription = getDescription;
+      myInfo.getNumberOfClassNames = getNumberOfClassNames;
+      myInfo.getClassName = getClassName;
+      
+      *info = &myInfo;
+      ossimKeywordlist kwl;
+      kwl.parseString(ossimString(options));
+      if(ossimString(kwl.find("reader_factory.location")).downcase() == "front")
+      {
+         /* Register the readers... */
+         ossimWebRequestFactoryRegistry::instance()->
+         registerFactoryToFront(ossimWebPluginRequestFactory::instance());
+      }
+      else
+      {
+         /* Register the readers... */
+         ossimWebRequestFactoryRegistry::instance()->
+         registerFactory(ossimWebPluginRequestFactory::instance());
+      }
+      setDescription(theDescription);
+   }
+   
+   /* Note symbols need to be exported on windoze... */ 
+   OSSIM_PLUGINS_DLL void ossimSharedLibraryFinalize()
+   {
+   }
+}
diff --git a/ossim_plugins/web/ossimWebPluginRequestFactory.cpp b/ossim_plugins/web/ossimWebPluginRequestFactory.cpp
new file mode 100644
index 0000000..f79bd87
--- /dev/null
+++ b/ossim_plugins/web/ossimWebPluginRequestFactory.cpp
@@ -0,0 +1,34 @@
+#include "ossimWebPluginRequestFactory.h"
+#include "ossimCurlHttpRequest.h"
+ossimWebPluginRequestFactory* ossimWebPluginRequestFactory::m_instance = 0;
+
+ossimWebPluginRequestFactory::ossimWebPluginRequestFactory()
+{
+   m_instance = this;
+}
+
+ossimWebPluginRequestFactory* ossimWebPluginRequestFactory::instance()
+{
+   if(!m_instance)
+   {
+      m_instance = new ossimWebPluginRequestFactory();
+   }
+   
+   return m_instance;
+}
+
+ossimWebRequest* ossimWebPluginRequestFactory::create(const ossimUrl& url)
+{
+
+   ossimRefPtr<ossimCurlHttpRequest> request = new ossimCurlHttpRequest();
+   
+   if(request->supportsProtocol(url.getProtocol()))
+   {
+      request->set(url, ossimKeywordlist());
+   }
+   else
+   {
+      request = 0;
+   }
+   return request.release();
+}
diff --git a/ossim_plugins/web/ossimWebPluginRequestFactory.h b/ossim_plugins/web/ossimWebPluginRequestFactory.h
new file mode 100644
index 0000000..7e9caa6
--- /dev/null
+++ b/ossim_plugins/web/ossimWebPluginRequestFactory.h
@@ -0,0 +1,17 @@
+#ifndef ossimWebPluginRequestFactory_HEADER
+#define ossimWebPluginRequestFactory_HEADER
+#include <ossim/base/ossimWebRequestFactoryBase.h>
+
+class ossimWebPluginRequestFactory : public ossimWebRequestFactoryBase
+{
+public:
+   static ossimWebPluginRequestFactory* instance();
+   virtual ossimWebRequest* create(const ossimUrl& url);
+   
+protected:
+   ossimWebPluginRequestFactory();
+   
+   static ossimWebPluginRequestFactory* m_instance;
+};
+
+#endif
diff --git a/ossim_plugins/worldwind/ossimDiskCache.cpp b/ossim_plugins/worldwind/ossimDiskCache.cpp
new file mode 100644
index 0000000..2db3894
--- /dev/null
+++ b/ossim_plugins/worldwind/ossimDiskCache.cpp
@@ -0,0 +1,368 @@
+#include "ossimDiskCache.h"
+#include <ossim/base/ossimDirectoryTree.h>
+#include <ossim/base/ossimKeywordlist.h>
+#include <ossim/base/ossimRegExp.h>
+#include <OpenThreads/ScopedLock>
+#include <algorithm>
+
+const ossimString ossimDiskCache::INDEX_FILE_NAME = "cache.idx";
+
+ossimDiskCache::~ossimDiskCache()
+{
+   close();
+}
+
+bool ossimDiskCache::open(const ossimFilename& directory)
+{
+   close();
+   
+   bool result = true;
+   if(directory.isDir())
+   {
+      theRootDirectory = directory;
+      loadIndex();
+   }
+   else
+   {
+      result = false;
+   }
+
+   if(result)
+   {
+      dirty();
+      writeIndex();
+      if(!cacheIndexFile().exists())
+      {
+         result = false;
+      }
+   }
+   
+   return result;
+}
+
+void ossimDiskCache::close()
+{
+   OpenThreads::ScopedLock<OpenThreads::Mutex> lock(theMutex);
+   
+   // need to write access table out to disk
+   writeIndex();
+   theCurrentSize    = 0;
+   theLastTimeStamp  = 0;
+   theRootDirectory  = "";
+   theFileMap.clear();
+}
+
+bool ossimDiskCache::addStream(std::istream& inputStream,
+                               const ossimFilename& outputFile)
+{
+   ossimFilename file = fullPath(outputFile);
+   if(!file.path().exists())
+   {
+      file.path().createDirectory();
+   }
+   std::ofstream out(file.c_str(),
+                     std::ios::out|std::ios::binary);
+
+   if(!out.fail())
+   {
+      char buf[1024];
+
+      while(!inputStream.fail())
+      {
+         inputStream.read(buf, 1024);
+         if(inputStream.gcount() > 0)
+         {
+            out.write(buf, inputStream.gcount());
+         }
+         else
+         {
+            break;
+         }
+      }
+      out.close();
+      
+      accessFile(outputFile);
+   }
+   return true;
+}
+
+bool ossimDiskCache::addFile(const ossimFilename& relativePath)
+{
+   if(!relativePath.path().exists())
+   {
+      relativePath.path().createDirectory();
+   }
+   accessFile(relativePath);
+   freeDiskSpace(); // free disk space if need be
+   return true;
+}
+
+bool ossimDiskCache::isInCache(const ossimFilename& relativePath)const
+{
+   ossimFileInfoMap::const_iterator iter = theFileMap.find(relativePath);
+   return(iter != theFileMap.end());
+}
+
+bool ossimDiskCache::accessFile(const ossimFilename& relativePath)
+{
+   ossimFilename file = fullPath(relativePath);
+
+   ossimFileInfoMap::iterator iter = theFileMap.find(relativePath);
+   
+   if(iter != theFileMap.end())
+   {
+      iter-> second.theTimeStamp = theLastTimeStamp;
+      ++theLastTimeStamp;
+   }
+   else
+   {
+      ossim_uint64 fileSize = 0;
+      if(file.exists())
+      {
+         fileSize = file.fileSize();
+         theCurrentSize += file.fileSize();
+      }
+      theFileMap.insert(std::make_pair(relativePath,
+                                       ossimFileInfo(fileSize,
+                                                     theLastTimeStamp)));
+      ++theLastTimeStamp;
+   }
+
+   dirty();
+   return true;
+}
+
+void ossimDiskCache::clearAll()
+{
+   ossimFileInfoMap::iterator iter = theFileMap.begin();
+
+   while(iter!=theFileMap.end())
+   {
+      ossimFilename file = fullPath(iter->first);
+
+      file.remove();
+      theCurrentSize-=iter->second.theFileSize;
+      
+      ++iter;
+   }
+}
+
+void ossimDiskCache::removeFile(const ossimFilename& relativePath)
+{
+   ossimFileInfoMap::const_iterator iter = theFileMap.find(relativePath);
+   ossimFilename file = fullPath(relativePath);
+   if(iter != theFileMap.end())
+   {
+      file.remove();
+      theCurrentSize-=iter->second.theFileSize;
+   }
+}
+
+void ossimDiskCache::clear(const ossimFilename& relativeDir)
+{
+   ossimFileInfoMap::iterator iter = theFileMap.begin();
+   ossimRegExp regExp;
+
+   regExp.compile(("^"+relativeDir).c_str());
+
+   while(iter!=theFileMap.end())
+   {
+      if(regExp.find(iter->first.c_str()))
+      {
+         ossimFilename file = fullPath(iter->first);
+         file.remove();
+         theCurrentSize-=iter->second.theFileSize;
+      }
+      ++iter;
+   }
+
+   fullPath(relativeDir).remove();
+}
+
+void ossimDiskCache::writeIndex()
+{
+   if(!isDirty()) return;
+   
+   ossimFileInfoMap::iterator iter = theFileMap.begin();
+   ossimKeywordlist kwl;
+   ossim_uint64 idx=0;
+   
+   while(iter!=theFileMap.end())
+   {
+      ossimString prefix = "f" + ossimString::toString(idx) + ".";
+      
+      kwl.add(prefix,
+              "n",
+              iter->first,
+              true);
+      kwl.add(prefix,
+              "s",
+              ossimString::toString(iter->second.theFileSize),
+              true);
+      kwl.add(prefix,
+              "t",
+              ossimString::toString(iter->second.theTimeStamp),
+              true);
+      ++iter;
+      ++idx;
+   }
+   kwl.add("cachesize",
+           ossimString::toString(theCurrentSize),
+           true);
+   kwl.add("last_time_stamp",
+           ossimString::toString(theLastTimeStamp),
+           true);
+   kwl.add("maxsize",
+           ossimString::toString(theMaxCacheSize));
+   kwl.add("minsize",
+           ossimString(theMinCacheSize));
+   
+   ossimFilename indexFileName = fullPath(ossimDiskCache::INDEX_FILE_NAME);
+
+   kwl.write(indexFileName);
+   if(indexFileName.exists())
+   {
+      theDirtyFlag = false;
+   }
+}
+
+bool ossimDiskCache::loadIndex()
+{
+   if(isDirty())
+   {
+      writeIndex();
+   }
+   bool result = true;
+   theFileMap.clear();
+   theCurrentSize = 0;
+   ossimFilename indexFileName = fullPath(ossimDiskCache::INDEX_FILE_NAME);
+   if(indexFileName.exists())
+   {
+      ossimKeywordlist kwl;
+
+      if(!kwl.addFile(indexFileName))
+      {
+         return false;
+      }
+      
+      ossimString regExpression =  ossimString("^(") +"f[0-9]+.)";
+      vector<ossimString> keys =
+         kwl.getSubstringKeyList( regExpression );
+      ossim_uint64 n = keys.size();
+      ossim_uint64 offset = 1;
+      ossim_uint64 idx = 0;
+      std::vector<int> theNumberList(n);
+      for(idx = 0; idx < theNumberList.size();++idx)
+      {
+         ossimString numberStr(keys[idx].begin() + offset,
+                               keys[idx].end());
+         theNumberList[idx] = numberStr.toInt();
+     }
+     std::sort(theNumberList.begin(), theNumberList.end());
+     for(idx=0;idx < theNumberList.size();++idx)
+     {
+        ossimString newPrefix = ossimString("f");
+        newPrefix += ossimString::toString(theNumberList[idx]);
+        newPrefix += ossimString(".");
+
+        ossimString name(kwl.find(newPrefix,
+                                  "n"));
+        ossimString size(kwl.find(newPrefix,
+                                  "s"));
+        ossimString timeStamp(kwl.find(newPrefix,
+                                  "t"));
+        ossimString cachesize(kwl.find("cachesize"));
+        ossimString lastTimeStamp(kwl.find("last_time_stamp"));
+        ossimString maxSize(kwl.find("maxsize"));
+        ossimString minSize(kwl.find("minsize"));
+        
+        theCurrentSize   = cachesize.toUInt32();
+        theLastTimeStamp = lastTimeStamp.toUInt64();
+        theMaxCacheSize  = maxSize.toUInt32();
+        theMinCacheSize  = minSize.toUInt32();
+        theFileMap.insert(std::make_pair(name,
+                                         ossimFileInfo(size.toUInt64(),
+                                                       timeStamp.toUInt64())));  
+     } 
+   }
+//    else
+//    {
+//       ossimDirectoryTree dirTree;
+//       theLastTimeStamp = 0;
+//       if(dirTree.open(rootDirectory()))
+//       {
+//          ossimFilename file;
+         
+//          if(dirTree.getFirst(file))
+//          {
+//             do
+//             {
+//                if(!file.isDir())
+//                {
+//                   ossimFilename fileTmp = file;
+//                   fileTmp.convertBackToForwardSlashes();
+
+                  
+//                   ossimFilename relativePath = stripRootDir(fileTmp);
+                  
+//                   theCurrentSize += file.fileSize();
+//                   theFileMap.insert(std::make_pair(relativePath,
+//                                                    ossimFileInfo(file.fileSize(),
+//                                                                  theLastTimeStamp)));
+//                }
+//             }while(dirTree.getNext(file));
+
+//             // we will start everyone with equal status if nothing is available.
+//             // so all have same access count
+//             //
+//             ++theLastTimeStamp;
+//          }
+//       }
+
+//       dirty();
+//    }
+   return result;
+}
+
+void ossimDiskCache::freeDiskSpace()
+{
+   if(theCurrentSize < theMaxCacheSize) return;
+   while((!theFileMap.empty())&&
+         (theCurrentSize > theMinCacheSize))
+   {
+      ossimFileInfoMap::iterator iter = theFileMap.begin();
+      ossimFileInfoMap::iterator current = iter;
+      ossim_uint64 oldestTime = theLastTimeStamp + 1;
+      while(iter != theFileMap.end())
+      {
+         if(iter->second.theTimeStamp < oldestTime)
+         {
+            current = iter;
+         }
+         
+         ++iter;
+      }
+      if(current != theFileMap.end())
+      {
+         fullPath(current->first).remove();
+         theCurrentSize -= current->second.theFileSize;
+         theFileMap.erase(current);
+         dirty();
+      }
+   }
+}
+
+ossimFilename ossimDiskCache::stripRootDir(const ossimFilename& file)const
+{
+   ossimFilename tempF = file;
+   tempF.convertBackToForwardSlashes();
+   tempF = tempF.substitute(rootDirectory(), "");
+   if(*tempF.begin() == '/')
+   {
+      tempF = ossimFilename(ossimString(tempF.begin()+1,
+                                        tempF.end()));
+   }
+
+   return tempF;
+}
+
diff --git a/ossim_plugins/worldwind/ossimDiskCache.h b/ossim_plugins/worldwind/ossimDiskCache.h
new file mode 100644
index 0000000..9c5edf3
--- /dev/null
+++ b/ossim_plugins/worldwind/ossimDiskCache.h
@@ -0,0 +1,107 @@
+#ifndef ossimDiskCache_HEADER
+#define ossimDiskCache_HEADER
+#include <ossim/base/ossimFilename.h>
+#include <ossim/base/ossimIoStream.h>
+#include <ossim/base/ossimObject.h>
+#include <OpenThreads/Mutex>
+#include <map>
+
+class ossimDiskCache : public ossimObject
+{
+public:
+   // default to 1 gigabyte
+   ossimDiskCache(ossim_uint64 sizeInMegabytes=2048)
+      :theMaxCacheSize(sizeInMegabytes*1024*1024),
+      theMinCacheSize(static_cast<ossim_uint64>(theMaxCacheSize*.75)),
+      theCurrentSize(0),
+      theLastTimeStamp(0),
+      theDirtyFlag(false)
+   {
+   }
+   ~ossimDiskCache();
+   bool open(const ossimFilename& directory);
+   void close();
+   void setDiskCacheSize(ossim_uint64 sizeInMegaBytes)
+   {
+      theMaxCacheSize = sizeInMegaBytes*1024*1024;
+   }
+   void setMinCacheSize(ossim_uint64 sizeInMegaBytes)
+   {
+      theMinCacheSize = sizeInMegaBytes*1024*1024;
+   }
+
+   ossimFilename cacheIndexFile()const
+   {
+      return rootDirectory().dirCat(INDEX_FILE_NAME);
+   }
+   const ossimFilename& rootDirectory()const
+   {
+      return theRootDirectory;
+   }
+
+   void removeFile(const ossimFilename& relativePath);
+   
+   ossimFilename fullPath(const ossimFilename& relativePath)const
+   {
+      return theRootDirectory.dirCat(relativePath);
+   }
+   /**
+    * The input is an input stream and writes the outputFile which is relative to this
+    * root location.
+    */ 
+   bool addStream(std::istream& inputStream,
+                  const ossimFilename& outputFile);
+
+   bool addFile(const ossimFilename& relativeFile);
+   bool isInCache(const ossimFilename& relativePath)const;
+   bool accessFile(const ossimFilename& relativePath);
+   
+   void clearAll();
+   void clear(const ossimFilename& relativeDir);
+
+   void writeIndex();
+   void dirty()
+   {
+      theDirtyFlag = true;
+   }
+   bool isDirty()const
+   {
+      return theDirtyFlag;
+   }
+   
+   void freeDiskSpace();
+   ossimFilename stripRootDir(const ossimFilename& file)const;
+  
+   static const ossimString INDEX_FILE_NAME;
+protected:
+   bool loadIndex();
+   
+   
+   struct ossimFileInfo
+   {
+      public:
+      ossimFileInfo(ossim_uint64 fileSize,
+                    ossim_uint64 timeStamp)
+         :theFileSize(fileSize),
+          theTimeStamp(timeStamp)
+         {
+         }
+      ossim_uint64 theFileSize;
+      ossim_uint64 theTimeStamp;
+   }; 
+   typedef std::map<ossimFilename, ossimFileInfo> ossimFileInfoMap;
+   ossim_uint64  theMaxCacheSize;
+   ossim_uint64  theMinCacheSize;
+   ossim_uint64  theCurrentSize;
+   ossimFilename theRootDirectory;
+   ossim_uint64  theLastTimeStamp;
+   mutable bool  theDirtyFlag;
+   /**
+    * This holds the relative file name and the general file information
+    */
+   ossimFileInfoMap theFileMap;
+
+   mutable OpenThreads::Mutex theMutex;
+};
+
+#endif
diff --git a/ossim_plugins/worldwind/ossimSharedDiskCacheManager.cpp b/ossim_plugins/worldwind/ossimSharedDiskCacheManager.cpp
new file mode 100644
index 0000000..117a777
--- /dev/null
+++ b/ossim_plugins/worldwind/ossimSharedDiskCacheManager.cpp
@@ -0,0 +1,75 @@
+#include "ossimSharedDiskCacheManager.h"
+
+ossimSharedDiskCacheManager* ossimSharedDiskCacheManager::theInstance = 0;
+ossimSharedDiskCacheManager::ossimSharedDiskCacheManager()
+{
+   theInstance = this;
+}
+
+ossimSharedDiskCacheManager::~ossimSharedDiskCacheManager()
+{
+   theInstance = 0;
+}
+
+ossimSharedDiskCacheManager* ossimSharedDiskCacheManager::instance()
+{
+   if(!theInstance)
+   {
+      theInstance = new ossimSharedDiskCacheManager;
+   }
+
+   return theInstance;
+}
+
+ossimRefPtr<ossimDiskCache> ossimSharedDiskCacheManager::getDiskCache(const ossimFilename& file)const
+{
+//    std::cout << "ossimSharedDiskCacheManager::getDiskCache" << std::endl;
+   ossim_uint32 idx = 0;
+
+
+   if(!file.isDir())
+   {
+      return 0;
+   }
+
+//    std::cout << 1 << std::endl;
+   for(idx = 0; idx < theDiskCaches.size(); ++idx)
+   {
+      if(theDiskCaches[idx]->rootDirectory() == file)
+      {
+         return theDiskCaches[idx];
+      }
+   }
+
+   ossimRefPtr<ossimDiskCache> tempCache = new ossimDiskCache;
+
+   if(tempCache->open(file))
+   {
+      theDiskCaches.push_back(tempCache);
+      return tempCache;
+   }
+   else
+   {
+      // notify error
+   }
+
+   return 0;
+}
+
+void ossimSharedDiskCacheManager::releaseDiskCache(const ossimFilename& file)const
+{
+   ossim_uint32 idx = 0;
+   for(idx = 0; idx < theDiskCaches.size(); ++idx)
+   {
+//       std::cout << "Testing root directory = " << theDiskCaches[idx]->rootDirectory() << " == " << file << std::endl;
+      if(theDiskCaches[idx]->rootDirectory() == file)
+      {
+         if(theDiskCaches[idx]->referenceCount() == 1)
+         {
+            theDiskCaches[idx] = 0;
+            theDiskCaches.erase(theDiskCaches.begin() + idx);
+            return;
+         }
+      }
+   }
+}
diff --git a/ossim_plugins/worldwind/ossimSharedDiskCacheManager.h b/ossim_plugins/worldwind/ossimSharedDiskCacheManager.h
new file mode 100644
index 0000000..1f68076
--- /dev/null
+++ b/ossim_plugins/worldwind/ossimSharedDiskCacheManager.h
@@ -0,0 +1,23 @@
+#ifndef ossimSharedDiskCacheManager_HEADER
+#define ossimSharedDiskCacheManager_HEADER
+#include <ossim/base/ossimRefPtr.h>
+#include "ossimDiskCache.h"
+#include <vector>
+
+class ossimSharedDiskCacheManager
+{
+public:
+   ossimSharedDiskCacheManager();
+   ~ossimSharedDiskCacheManager();
+   static ossimSharedDiskCacheManager* instance();
+
+   ossimRefPtr<ossimDiskCache> getDiskCache(const ossimFilename& file)const;
+
+   void releaseDiskCache(const ossimFilename& file)const;
+   
+protected:
+   mutable std::vector<ossimRefPtr<ossimDiskCache> > theDiskCaches;
+   static ossimSharedDiskCacheManager* theInstance;
+};
+
+#endif
diff --git a/ossim_plugins/worldwind/ossimWorldWindExports.h b/ossim_plugins/worldwind/ossimWorldWindExports.h
new file mode 100644
index 0000000..bd9cd18
--- /dev/null
+++ b/ossim_plugins/worldwind/ossimWorldWindExports.h
@@ -0,0 +1,31 @@
+//----------------------------------------------------------------------------
+// Copyright (c) 2005, Garrett Potts, all rights reserved.
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author:  Garrett Potts
+//
+// Description: Constants file for ossim plugins.
+//
+// $Id: ossimWorldWindExports.h 23664 2015-12-14 14:17:27Z dburken $
+//----------------------------------------------------------------------------
+#ifndef ossimWorldWindExports_HEADER
+#define ossimWorldWindExports_HEADER
+
+#if defined(__MINGW32__) || defined(__CYGWIN__) || defined(_MSC_VER) || defined(__VISUALC__) || defined(__BORLANDC__) || defined(__WATCOMC__)
+#  define OSSIM_WORLDWIND_EXPORT __declspec(dllexport)
+#  define OSSIM_WORLDWIND_IMPORT __declspec(dllexport)
+
+#  ifdef OSSIM_WORLDWIND_MAKINGDLL
+#     define OSSIM_WORLDWIND_DLL OSSIM_WORLDWIND_EXPORT
+#  else
+#     define  OSSIM_WORLDWIND_DLL OSSIM_WORLDWIND_IMPORT
+#  endif
+#else
+# define OSSIM_WORLDWIND_DLL
+#endif
+
+#endif /* #ifndef ossimWorldWindExports_HEADER */
+
diff --git a/ossim_plugins/worldwind/ossimWorldWindFactory.cpp b/ossim_plugins/worldwind/ossimWorldWindFactory.cpp
new file mode 100644
index 0000000..c1e458d
--- /dev/null
+++ b/ossim_plugins/worldwind/ossimWorldWindFactory.cpp
@@ -0,0 +1,146 @@
+//*******************************************************************
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author:  Garrett Potts
+//*******************************************************************
+//  $Id: ossimWorldWindFactory.cpp 23664 2015-12-14 14:17:27Z dburken $
+
+#include "ossimWorldWindFactory.h"
+#include "ossimWorldWindHandler.h"
+#include <ossim/base/ossimKeywordlist.h>
+#include <ossim/base/ossimString.h>
+#include <ossim/imaging/ossimImageHandler.h>
+#include <ossim/base/ossimTrace.h>
+#include <ossim/base/ossimKeywordNames.h>
+
+static const ossimTrace traceDebug("ossimWorldWindFactory:debug");
+
+RTTI_DEF1(ossimWorldWindFactory, "ossimWorldWindFactory", ossimImageHandlerFactoryBase);
+
+ossimWorldWindFactory* ossimWorldWindFactory::theInstance = 0;
+ossimWorldWindFactory::~ossimWorldWindFactory()
+{
+   theInstance = (ossimWorldWindFactory*)NULL;
+}
+
+
+ossimWorldWindFactory* ossimWorldWindFactory::instance()
+{
+   if(!theInstance)
+   {
+      theInstance = new ossimWorldWindFactory;
+   }
+
+
+   return theInstance;
+}
+   
+ossimImageHandler* ossimWorldWindFactory::open( const ossimFilename& fileName,
+                                                bool openOverview )const
+{
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG) << "ossimWorldWindFactory::open(filename) DEBUG: entered..." << std::endl;
+   }
+   
+   ossimRefPtr<ossimImageHandler> result;
+   if (traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG)
+         << "ossimWorldWindFactory::open(filename) DEBUG:"
+         << "\ntrying ossimWorldWindHandler"
+         << std::endl;
+   }
+   
+   // make sure you put this last
+   //
+   result = new ossimWorldWindHandler;
+   result->setOpenOverviewFlag(openOverview);
+   if(!result->open(fileName))
+   {
+      result = 0;
+   }
+   return result.release();
+}
+
+ossimImageHandler* ossimWorldWindFactory::open(const ossimKeywordlist& kwl,
+                                          const char* prefix)const
+{
+   ossimRefPtr<ossimImageHandler> result;
+   
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG) << "ossimWorldWindFactory::open(kwl, prefix) DEBUG: entered..." << std::endl;
+   }
+   
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG) << "ossimWorldWindFactory::open(kwl, prefix) DEBUG: trying ossimWorldWindHandler" << std::endl;
+   }
+   result = new ossimWorldWindHandler;
+   if(!result->loadState(kwl, prefix))
+   {
+      result = 0;
+   }
+   
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG) << "ossimWorldWindFactory::open(kwl, prefix) DEBUG: leaving..." << std::endl;
+   }
+   
+   return result.release();
+}
+
+ossimObject* ossimWorldWindFactory::createObject(const ossimString& typeName)const
+{
+   if(STATIC_TYPE_NAME(ossimWorldWindHandler) == typeName)
+   {
+      return new ossimWorldWindHandler();
+   }
+   
+   return (ossimObject*)NULL;
+}
+
+ossimObject* ossimWorldWindFactory::createObject(const ossimKeywordlist& kwl,
+                                                    const char* prefix)const
+{
+   ossimObject* result = (ossimObject*)NULL;
+   const char* type = kwl.find(prefix, ossimKeywordNames::TYPE_KW);
+
+   if(type)
+   {
+      if (ossimString(type).trim() == STATIC_TYPE_NAME(ossimImageHandler))
+      {
+         const char* lookup = kwl.find(prefix, ossimKeywordNames::FILENAME_KW);
+         if (lookup)
+         {
+            // Call the open that takes a filename...
+            result = this->open(kwl, prefix);
+         }
+      }
+      else
+      {
+         result = createObject(ossimString(type));
+         if(result)
+         {
+            result->loadState(kwl, prefix);
+         }
+      }
+   }
+
+   return result;
+}
+ 
+void ossimWorldWindFactory::getTypeNameList(std::vector<ossimString>& typeList)const
+{
+   typeList.push_back(STATIC_TYPE_NAME(ossimWorldWindHandler));
+}
+
+void ossimWorldWindFactory::getSupportedExtensions(ossimImageHandlerFactoryBase::UniqueStringList& extensionList)const
+{
+   extensionList.push_back("xml");
+}
+
diff --git a/ossim_plugins/worldwind/ossimWorldWindFactory.h b/ossim_plugins/worldwind/ossimWorldWindFactory.h
new file mode 100644
index 0000000..4916024
--- /dev/null
+++ b/ossim_plugins/worldwind/ossimWorldWindFactory.h
@@ -0,0 +1,63 @@
+//*******************************************************************
+//
+// License: MIT
+// 
+// See LICENSE.txt file in the top level directory for more details.
+//
+// Author:  Garrett Potts
+//*******************************************************************
+//  $Id: ossimWorldWindFactory.h 23664 2015-12-14 14:17:27Z dburken $
+
+#ifndef ossimWorldWindFactory_HEADER
+#define ossimWorldWindFactory_HEADER
+
+#include <ossim/imaging/ossimImageHandlerFactoryBase.h>
+#include <ossim/base/ossimString.h>
+
+class ossimGdal;
+class ossimFilename;
+class ossimKeywordlist;
+
+//*******************************************************************
+// CLASS:  ossimWorldWindFactory
+//*******************************************************************
+class ossimWorldWindFactory : public ossimImageHandlerFactoryBase
+{
+public:
+   virtual ~ossimWorldWindFactory();
+   static ossimWorldWindFactory* instance();
+   
+   virtual ossimImageHandler* open(const ossimFilename& fileName,
+                                   bool openOverview=true) const;
+   virtual ossimImageHandler* open(const ossimKeywordlist& kwl,
+                                   const char* prefix=0)const;
+
+   
+   virtual ossimObject* createObject(const ossimString& typeName)const;
+   
+   /*!
+    * Creates and object given a keyword list.
+    */
+   virtual ossimObject* createObject(const ossimKeywordlist& kwl,
+                                     const char* prefix=0)const;
+   
+   /*!
+    * This should return the type name of all objects in all factories.
+    * This is the name used to construct the objects dynamially and this
+    * name must be unique.
+    */
+   virtual void getTypeNameList(std::vector<ossimString>& typeList)const;
+   void getSupportedExtensions(ossimImageHandlerFactoryBase::UniqueStringList& extensionList)const;
+ 
+protected:
+   ossimWorldWindFactory(){}
+   ossimWorldWindFactory(const ossimWorldWindFactory&){}
+   void operator = (const ossimWorldWindFactory&){}
+
+   static ossimWorldWindFactory* theInstance;
+
+TYPE_DATA
+};
+
+#endif
+
diff --git a/ossim_plugins/worldwind/ossimWorldWindHandler.cpp b/ossim_plugins/worldwind/ossimWorldWindHandler.cpp
new file mode 100644
index 0000000..c5a5b8e
--- /dev/null
+++ b/ossim_plugins/worldwind/ossimWorldWindHandler.cpp
@@ -0,0 +1,857 @@
+#include "ossimWorldWindHandler.h"
+#include <ossim/base/ossimXmlNode.h>
+#include <ossim/projection/ossimEquDistCylProjection.h>
+#include <ossim/imaging/ossimImageDataFactory.h>
+#include <wms/wmsCurlMemoryStream.h>
+#include <wms/wmsUrl.h>
+#include <ossim/imaging/ossimImageHandlerRegistry.h>
+#include <sstream>
+#include <fstream>
+#include <iomanip>
+#include <ossim/base/ossimKeywordNames.h>
+#include "ossimSharedDiskCacheManager.h"
+#include "ossimWorldWindJpegImage.h"
+#include <ossim/base/ossimIoStream.h>
+#include <ossim/base/ossimTrace.h>
+
+//string relativePath = String.Format(@"{0}\{1:D4}\{1:D4}_{2:D4}.{3}",
+//                      qt.Level, qt.Row, qt.Col, m_imageFileExtension);
+
+static ossimTrace traceDebug("ossimWorldWindHandler:debug");
+
+RTTI_DEF1(ossimWorldWindHandler, "ossimWorldWindHandler", ossimImageHandler);
+
+ossimWorldWindHandler::ossimWorldWindHandler()
+{
+}
+
+ossimWorldWindHandler::~ossimWorldWindHandler()
+{
+   close();
+}
+
+void ossimWorldWindHandler::close()
+{
+   if(theDiskCache.valid())
+   {
+      ossimFilename file = theDiskCache->rootDirectory();
+      theDiskCache = 0;
+      ossimSharedDiskCacheManager::instance()->releaseDiskCache(file);
+   }
+   theLayers.clear();
+}
+
+bool ossimWorldWindHandler::open()
+{
+   bool result = true;
+   theCurrentIdx = 0;
+   theXmlDocument = new ossimXmlDocument;
+   
+   if(theXmlDocument->openFile(getFilename()))
+   {
+      std::vector<ossimRefPtr<ossimXmlNode> > nodeList;
+      theXmlDocument->findNodes("/LayerSet",
+                                nodeList);
+
+      
+      if(nodeList.size())
+      {
+         ossimRefPtr<ossimXmlAttribute> attribute = nodeList[0]->findAttribute("redirect");
+         if(attribute.get())
+         {
+            wmsCurlMemoryStream wmsStream(attribute->getValue());
+
+            ossimNotify(ossimNotifyLevel_INFO) << "ossimWorldWindHandler::open() INFO: Trying to download remote image description from " << attribute->getValue() <<  std::endl;
+            ossimFilename downloadXmlFilename = getFilename();
+            downloadXmlFilename.setExtension("download");
+            if(wmsStream.download(downloadXmlFilename))
+            {
+               theXmlDocument = new ossimXmlDocument;
+                             
+               if(!theXmlDocument->openFile(downloadXmlFilename))
+               {
+                  result = false;
+                  theXmlDocument = 0;
+               }
+               else
+               {
+                  setFilename(downloadXmlFilename);
+               }
+            }
+         }
+
+         if(result)
+         {
+            if(!populateWorldWindStructure())
+            {
+               result = false;
+            }
+         }
+      }
+      
+   }
+   else
+   {
+      result = false;
+   }
+
+   if(result)
+   {
+      initialize();
+   }
+   
+   return result;
+}
+
+bool ossimWorldWindHandler::isOpen()const
+{
+   return (theLayers.size() > 0);
+}
+
+ossim_uint32 ossimWorldWindHandler::getNumberOfLines(ossim_uint32 resLevel)const
+{
+   if(isOpen())
+   {
+      return theLayers[theCurrentIdx].theImageHeight>>resLevel;
+   }
+   
+   return 0;
+}
+
+ossim_uint32 ossimWorldWindHandler::getNumberOfSamples(ossim_uint32 resLevel)const
+{
+   if(isOpen())
+   {
+      return theLayers[theCurrentIdx].theImageWidth>>resLevel;
+   }
+   return 0;
+}
+
+ossim_uint32 ossimWorldWindHandler::getImageTileWidth()const
+{
+   if(isOpen())
+   {
+      return theLayers[theCurrentIdx].theTileSize;
+   }
+   return 0;
+}
+
+ossim_uint32 ossimWorldWindHandler::getImageTileHeight()const
+{
+   if(isOpen())
+   {
+      return theLayers[theCurrentIdx].theTileSize;
+   }
+   return 0;
+}
+
+ossim_uint32 ossimWorldWindHandler::getNumberOfInputBands()const
+{
+   return 3;
+}
+
+ossim_uint32 ossimWorldWindHandler::getNumberOfOutputBands()const
+{
+   return 3;
+}
+
+ossimScalarType ossimWorldWindHandler::getOutputScalarType() const
+{
+   return OSSIM_UINT8;
+}
+
+void ossimWorldWindHandler::getEntryList(std::vector<ossim_uint32>& entryList) const
+{
+   ossim_uint32 idx = 0;
+
+   for(idx = 0; idx < theLayers.size(); ++idx)
+   {
+      entryList.push_back(idx);
+   }
+}
+
+ossim_uint32 ossimWorldWindHandler::getNumberOfEntries()const
+{
+   return theLayers.size();
+}
+
+ossim_uint32 ossimWorldWindHandler::getCurrentEntry()const
+{
+   return theCurrentIdx;
+}
+
+bool ossimWorldWindHandler::setCurrentEntry(ossim_uint32 entryIdx)
+{
+   if(entryIdx < theLayers.size())
+   {
+      theCurrentIdx = entryIdx;
+
+      initialize();
+
+      return true;
+   }
+
+   return false;
+}
+
+ossim_uint32 ossimWorldWindHandler::getNumberOfDecimationLevels()const
+{
+   if(isOpen())
+   {
+      return theLayers[theCurrentIdx].theLevels;
+   }
+   
+   return 0;
+}
+
+void ossimWorldWindHandler::resetMemoryCache()
+{
+   ossim_uint32 idx = 0;
+   if(theRLevelCacheId.size())
+   {
+      for(idx = 0; idx < theRLevelCacheId.size(); ++idx)
+      {
+         ossimAppFixedTileCache::instance()->deleteCache(theRLevelCacheId[idx]);
+      }  
+   }
+   theRLevelCacheId.clear();
+   ossim_uint32 rlevels = getNumberOfDecimationLevels();
+   if(isOpen())
+   {
+      if(rlevels)
+      {
+         ossimIrect boundingRect;
+         for(idx = 0; idx < rlevels; ++idx)
+         {
+            theRLevelCacheId.push_back(ossimAppFixedTileCache::instance()->newTileCache());
+            boundingRect = getBoundingRect((rlevels-idx)-1);
+            ossimIrect tileRect(0,
+                                0,
+                                (boundingRect.width()/theLayers[theCurrentIdx].theTileSize)-1,
+                                (boundingRect.height()/theLayers[theCurrentIdx].theTileSize)-1);
+            ossimAppFixedTileCache::instance()->setRect(theRLevelCacheId[idx],
+                                                        tileRect);
+            ossimAppFixedTileCache::instance()->setTileSize(theRLevelCacheId[idx], ossimIpt(1,1));
+         }
+      }
+   }
+}
+
+void ossimWorldWindHandler::initialize()
+{
+   theResultTile = ossimImageDataFactory::instance()->create(this, this);
+   theLocalTile   = ossimImageDataFactory::instance()->create(this, this);
+
+   if(theResultTile.valid())
+   {
+      theResultTile->initialize();
+	  // gave warnings in windows for unary minus on a unsigned value so put a 0 in front
+      theResultTile->setOrigin(ossimIpt(0 - getNumberOfSamples(0),
+                                        0 - getNumberOfLines(0)));
+      theLocalTile->initialize();
+      theLocalTile->setOrigin(ossimIpt(0-getNumberOfSamples(0),
+                                       0-getNumberOfLines(0)));
+   }
+//    ossim_uint32 tileSizeInBytes = getImageTileWidth()*getImageTileHeight()*3;
+//    if(theJpegDecodeBuffer.size() != tileSizeInBytes)
+//    {
+//       theJpegDecodeBuffer.resize(tileSizeInBytes);
+//    }
+   resetMemoryCache();
+}
+
+bool ossimWorldWindHandler::populateWorldWindStructure()
+{
+   theLayers.clear();
+   
+   std::vector<ossimRefPtr<ossimXmlNode> > childLayerSetList;
+   // add layersets and child layersets for discovering QuadTileSets
+   theXmlDocument->findNodes("/LayerSet/ChildLayerSet",
+                             childLayerSetList);
+   theXmlDocument->findNodes("/LayerSet",
+                             childLayerSetList);
+      
+   if(childLayerSetList.size())
+   {
+      ossim_uint32 idx = 0;
+      for(idx = 0; idx < childLayerSetList.size(); ++idx)
+      {
+         ossimRefPtr<ossimXmlAttribute> childLayerSetName = childLayerSetList[idx]->findAttribute("Name");
+         std::vector<ossimRefPtr<ossimXmlNode> > quadTileSet;
+         childLayerSetList[idx]->findChildNodes("QuadTileSet",
+                                       quadTileSet);
+         if(quadTileSet.size()&&childLayerSetName.valid())
+         {
+            ossim_uint32 quadTileIdx = 0;
+
+            for(quadTileIdx = 0; quadTileIdx < quadTileSet.size(); ++quadTileIdx)
+            {
+               ossimWorldWindHandlerInfo info;
+               ossimRefPtr<ossimXmlNode> name           = quadTileSet[quadTileIdx]->findFirstNode("Name");
+               ossimRefPtr<ossimXmlNode> north          = quadTileSet[quadTileIdx]->findFirstNode("BoundingBox/North/Value");
+               ossimRefPtr<ossimXmlNode> south          = quadTileSet[quadTileIdx]->findFirstNode("BoundingBox/South/Value");
+               ossimRefPtr<ossimXmlNode> east           = quadTileSet[quadTileIdx]->findFirstNode("BoundingBox/East/Value");
+               ossimRefPtr<ossimXmlNode> west           = quadTileSet[quadTileIdx]->findFirstNode("BoundingBox/West/Value");
+               ossimRefPtr<ossimXmlNode> levels         = quadTileSet[quadTileIdx]->findFirstNode("ImageAccessor/NumberLevels");
+               ossimRefPtr<ossimXmlNode> tileSizePixels = quadTileSet[quadTileIdx]->findFirstNode("ImageAccessor/TextureSizePixels");
+               ossimRefPtr<ossimXmlNode> level0Gsd      = quadTileSet[quadTileIdx]->findFirstNode("ImageAccessor/LevelZeroTileSizeDegrees");
+               ossimRefPtr<ossimXmlNode> extension      = quadTileSet[quadTileIdx]->findFirstNode("ImageAccessor/ImageFileExtension");
+               
+               if(name.valid()&&north.valid()&&south.valid()&&east.valid()&&west.valid()&&
+                  levels.valid()&&tileSizePixels.valid()&&level0Gsd.valid())
+               {
+                  info.theQuadTileSetName   = name->getText();
+                  info.theNorth  = north->getText().toDouble();
+                  info.theSouth  = south->getText().toDouble();
+                  info.theEast   = east->getText().toDouble();
+                  info.theWest   = west->getText().toDouble();
+
+                  info.theLevels = levels->getText().toUInt32();
+                  info.theLevel0Gsd = level0Gsd->getText().toDouble();
+                  info.theTileSize  = tileSizePixels->getText().toUInt32();
+
+
+                  info.theNorth     = (std::ceil((info.theNorth+90.0)/info.theLevel0Gsd)*info.theLevel0Gsd)-90.0;
+                  info.theSouth     = (std::floor((info.theSouth+90.0)/info.theLevel0Gsd)*info.theLevel0Gsd)-90.0;
+                  info.theEast     = (std::floor((info.theEast+180.0)/info.theLevel0Gsd)*info.theLevel0Gsd)-180.0;
+                  info.theWest     = (std::ceil((info.theWest+180.0)/info.theLevel0Gsd)*info.theLevel0Gsd)-180.0;
+
+//                   std::cout << "n = " << info.theNorth << std::endl;
+                  // set height and width
+                  info.theImageHeight = (std::abs(info.theNorth-info.theSouth)/(info.theLevel0Gsd));
+                  info.theImageHeight *= std::pow(2.0, (double)(info.theLevels-1));
+                  info.theImageHeight *= info.theTileSize;
+
+                  info.theImageWidth = (std::abs(info.theEast-info.theWest)/info.theLevel0Gsd);
+                  info.theImageWidth *= std::pow(2.0, (double)(info.theLevels-1));
+                  info.theImageWidth *= info.theTileSize;
+                  info.theChildLayerName = childLayerSetName->getValue();
+                  if(info.theLevels > 1)
+                  {
+                     info.theGsd    = (info.theNorth-info.theSouth)/info.theImageHeight;
+                  }
+
+                  
+
+//                   ossim_float64 resX = (lon1-lon0)/info.theLevel0Gsd;
+//                   ossim_float64 resY = (lat1-lat0)/info.theLevel0Gsd;
+
+                  info.theExtension = "";
+                  if(extension.valid())
+                  {
+                     info.theExtension = extension->getText();
+                  }
+                  ossimRefPtr<ossimXmlNode> node = quadTileSet[quadTileIdx]->findFirstNode("ImageAccessor/ImageTileService");
+                  
+                  if(node.valid())
+                  {
+                     if(node->getChildTextValue(info.theDatasetName, "DataSetName")&&
+                        node->getChildTextValue(info.theUrl, "ServerUrl"))
+                     {
+                        info.theAccessorType   = ossimWorldWindHandlerInfo::WW_TILE_SERVER;
+                        theLayers.push_back(info);
+                     }
+                  }
+#if 1
+                  else
+                  {
+                     node = quadTileSet[quadTileIdx]->findFirstNode("ImageAccessor/WMSAccessor");
+                     if(node.valid())
+                     {
+                        info.theUrl = "";
+                        info.theAccessorType   = ossimWorldWindHandlerInfo::WMS;
+                        if(node->getChildTextValue(info.theDatasetName, "WMSLayerName")&&
+                           node->getChildTextValue(info.theUrl, "ServerGetMapUrl"))
+                        {
+                           ossimString tempString;
+                           info.theUrl += "?REQUEST=GetMap&LAYERS=" + info.theDatasetName;
+                           if(node->getChildTextValue(tempString, "WMSLayerStyle"))
+                           {
+                              info.theUrl += ("&STYLES=" + tempString);
+                           }
+                           else
+                           {
+                              info.theUrl += "&STYLES=";
+                           }
+                           if(node->getChildTextValue(tempString, "UseTransparency"))
+                           {
+                              if(tempString.toBool())
+                              {
+                                 info.theUrl += "&TRANSPARENT=TRUE";
+                              }
+                              else
+                              {
+                                 info.theUrl += "&TRANSPARENT=FALSE";
+                              }
+                           }
+                           if(node->getChildTextValue(tempString, "Version"))
+                           {
+                              info.theUrl += ("&VERSION=" + tempString);
+                           }
+                           else
+                           {
+                              info.theUrl += "&VERSION=1.0";
+                           }
+                           if(node->getChildTextValue(tempString, "ImageFormat"))
+                           {
+                              info.theUrl += ("&FORMAT=" + tempString);
+                           }
+                           else
+                           {
+                              info.theUrl += "&FORMAT=image/jpeg";
+                           }
+                           if(node->getChildTextValue(tempString, "ServiceName"))
+                           {
+                              info.theUrl += ("&SERVICE="+tempString);
+                           }
+                           info.theUrl += "&SRS=EPSG:4326";
+                           theLayers.push_back(info);
+                        }
+                     }
+                  }
+#endif
+               }
+            }
+         }
+      }
+   }
+
+   if(theLayers.size())
+   {
+      theDiskCache =ossimSharedDiskCacheManager::instance()->getDiskCache(theImageFile.path());
+   }
+   
+   if(!theDiskCache.valid())
+   {
+      theLayers.clear();
+   }
+   
+   return (theLayers.size()>0);
+}
+
+
+bool ossimWorldWindHandler::getImageGeometry(ossimKeywordlist& kwl,
+                                                  const char* prefix)
+{
+   if(isOpen())
+   {
+
+      ossimEquDistCylProjection equ;
+      
+      ossim_float64 halfGsd = theLayers[theCurrentIdx].theGsd*.5;
+      equ.setDecimalDegreesPerPixel(ossimDpt(theLayers[theCurrentIdx].theGsd,
+                                             theLayers[theCurrentIdx].theGsd));
+      equ.setUlGpt(ossimGpt(theLayers[theCurrentIdx].theNorth - halfGsd,
+                            theLayers[theCurrentIdx].theWest + halfGsd));
+      
+      equ.saveState(kwl);
+      
+      return true;
+   }
+   
+   return false;
+}
+
+ossimRefPtr<ossimImageData> ossimWorldWindHandler::getTile(const ossimIrect& rect,
+                                                           ossim_uint32 resLevel)
+{
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG) <<  "ossimWorldWindHandler::getTile: entered........" << std::endl;
+   }
+   if(!isOpen())
+   {
+      if(traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG) <<  "ossimWorldWindHandler::getTile: leaving 1........" << std::endl;
+      }
+      return 0;
+   }
+   if(resLevel >= getNumberOfReducedResSets()) return 0;
+   ossimIrect imageRect = getBoundingRect(resLevel);
+   if(!rect.intersects(imageRect)) return 0;
+
+   
+   if(!theResultTile)
+   {
+      initialize();
+      if(!theResultTile.valid())
+      {
+         if(traceDebug())
+         {
+            ossimNotify(ossimNotifyLevel_DEBUG) <<  "ossimWorldWindHandler::getTile: leaving 2........" << std::endl;
+         }
+         return 0;
+      }
+   }
+   
+   ossim_uint32 tileSize = theLayers[theCurrentIdx].theTileSize;
+   ossim_uint32 h = getNumberOfLines(resLevel);
+   theResultTile->setImageRectangle(rect);
+
+   theResultTile->makeBlank();
+   ossimIrect clipRect = imageRect.clipToRect(rect);
+   
+   ossim_uint32 tileLeftX  = clipRect.ul().x/tileSize;
+   ossim_uint32 tileRightX = clipRect.ur().x/tileSize;
+   ossim_uint32 tileBottomY = ((imageRect.height() - clipRect.ll().y)/
+                               tileSize);
+   
+   ossim_uint32 tileTopY = ((imageRect.height() - clipRect.ul().y)/
+                            tileSize);
+   
+
+   ossim_uint32 wwLevel = (theLayers[theCurrentIdx].theLevels-1) - resLevel;
+   ossim_uint32 leftTile = tileLeftX;
+
+
+    ossim_uint32 xShift = (ossim_uint32)((theLayers[theCurrentIdx].theWest+180.0)/(theLayers[theCurrentIdx].theLevel0Gsd));
+    ossim_uint32 yShift = (ossim_uint32)((theLayers[theCurrentIdx].theSouth+90.0)/(theLayers[theCurrentIdx].theLevel0Gsd));
+    xShift<<=wwLevel;
+    yShift<<=wwLevel;
+   
+   for(;tileBottomY <= tileTopY; ++tileBottomY)
+   {
+      for(leftTile=tileLeftX;leftTile <=tileRightX; ++leftTile)
+      {
+         ossimRefPtr<ossimImageData> tile = requestTile(wwLevel, leftTile+xShift, tileBottomY+yShift);
+
+         if(tile.valid())
+         {
+            if(tile->getDataObjectStatus() != OSSIM_EMPTY)
+            {
+               tile->setOrigin(ossimIpt(tileSize*leftTile,
+                                        (h - tileBottomY*tileSize) - tileSize));
+               theResultTile->loadTile( convertToProperResult(tile.get()).get());
+            }
+         }
+      }
+   }
+   theResultTile->validate();
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG) <<  "ossimWorldWindHandler::getTile: leaving ........" << std::endl;
+   }
+   
+   return theResultTile;
+}
+
+ossimRefPtr<ossimImageData> ossimWorldWindHandler::requestTile(ossim_uint32 level,
+                                                               ossim_uint32 X,
+                                                               ossim_uint32 Y)
+{
+   double gsd = theLayers[theCurrentIdx].theLevel0Gsd/std::pow(2.0, (double)level);
+   ossimDpt lowerLeftLatLon(((X*gsd)-180),
+                            ((Y*gsd)-90));
+   ossimDpt upperRightLatLon((((X+1)*gsd)-180),
+                             (((Y+1)*gsd)-90));
+   
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG) <<  "ossimWorldWindHandler::requestTile: <" << level << ", " << X << ", " << Y << "> entered........" << std::endl;
+   }
+   ossimRefPtr<ossimImageData> tempTile = requestMemoryCacheTile(level, X, Y);
+   
+   if(tempTile.valid())
+   {
+      if(traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG) <<  "ossimWorldWindHandler::requestTile: returning memory tile........" << std::endl;
+      }
+      return tempTile;
+   }
+
+   tempTile = requestDiskCacheTile(level, X, Y);
+   if(tempTile.valid())
+   {
+      if(traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG) <<  "ossimWorldWindHandler::requestTile: returning disk tile........" << std::endl;
+      }
+      return tempTile;
+   }
+   ossimFilename relativeFile = buildFullRelativeFilename(level, Y, X);
+   ossimFilename fullPath     = theDiskCache->fullPath(relativeFile);
+
+   if(theDiskCache->isInCache(relativeFile))
+   {
+      if(traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG) <<  "ossimWorldWindHandler::requestTile: returning EMPTY tile........" << std::endl;
+      }
+      return 0;
+   }
+   ossimString completeUrl;
+   if(theLayers[theCurrentIdx].theAccessorType == ossimWorldWindHandlerInfo::WW_TILE_SERVER)
+   {
+      completeUrl = (theLayers[theCurrentIdx].theUrl + "?T=" +
+                     theLayers[theCurrentIdx].theDatasetName +
+                     ossimString("&L=") +
+                     ossimString::toString(level) + ossimString("&X=") +
+                     ossimString::toString(X) + ossimString("&Y=") +
+                     ossimString::toString(Y));
+   }
+   else if(theLayers[theCurrentIdx].theAccessorType == ossimWorldWindHandlerInfo::WMS)
+   {
+      completeUrl =  (theLayers[theCurrentIdx].theUrl +
+                      "&BBOX=" +  ossimString::toString(lowerLeftLatLon.x)+ "," +
+                      ossimString::toString(lowerLeftLatLon.y) + "," +
+                      ossimString::toString(upperRightLatLon.x) + "," +
+                      ossimString::toString(upperRightLatLon.y) +
+                      "&BGCOLOR=0x000000" +
+                      "&WIDTH=" + ossimString::toString(theLayers[theCurrentIdx].theTileSize) +
+                      "&HEIGHT=" + ossimString::toString(theLayers[theCurrentIdx].theTileSize));
+
+//       return 0;
+   }
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG) << "URL = " << completeUrl << std::endl;
+   }
+   
+   if(!completeUrl.empty())
+   {
+      wmsUrl url(completeUrl);
+      
+      wmsCurlMemoryStream wmsStream(url.url());
+      wmsStream.setMaxRedirects(1);
+      wmsStream.setMaxNumberRetry(0);
+      wmsStream.setFollowLocationFlag(1);
+      wmsStream.setTimeout(5);
+      fullPath.path().createDirectory();
+      if(traceDebug())
+      {
+         ossimNotify(ossimNotifyLevel_DEBUG) <<  "ossimWorldWindHandler::requestTile: downloading " << url.url() << std::endl;
+      }
+      if(wmsStream.download(fullPath))
+      {
+         std::ifstream in(fullPath.c_str(), ios::in|std::ios::binary);
+         if(!in.fail())
+         {
+            bool ok = false;
+            char buf[1024];
+            in.read(buf, 1023);
+            int c = in.gcount();
+            if(c > 0)
+            {
+               buf[c] = '\0';
+               ossimString tempTest(buf);
+
+               if((!tempTest.contains("xml"))&&
+                  (!tempTest.contains("Service Unavailable")))
+               {
+                  ok = true;
+               }
+               else
+               {
+                  if(traceDebug())
+                  {
+                     ossimNotify(ossimNotifyLevel_DEBUG) << "ERROR = " << buf << std::endl;
+                  }
+                  fullPath.remove();
+                  theDiskCache->addFile(relativeFile);
+               }
+            }
+            in.close();
+            if(ok)
+            {
+               ossimRefPtr<ossimImageHandler> ih = ossimImageHandlerRegistry::instance()->open(fullPath);
+               if(ih.valid())
+               {
+                  if(traceDebug())
+                  {
+                     ossimNotify(ossimNotifyLevel_DEBUG) <<  "ossimWorldWindHandler::requestTile: returning downloaded tile " << relativeFile << std::endl;
+                  }
+                  theDiskCache->addFile(relativeFile);
+                  
+                  return ih->getTile(ih->getBoundingRect());
+               }
+               else
+               {
+                  fullPath.remove();
+                  theDiskCache->addFile(relativeFile);
+               }
+            }
+            else
+            {
+               // let's still mark it for now
+               theDiskCache->addFile(relativeFile);
+            }
+         }
+         else
+         {
+            // let's mark it still in disk cache;
+            fullPath.remove();
+            theDiskCache->addFile(relativeFile);
+         }
+      }
+      else
+      {
+      }
+   }
+   if(traceDebug())
+   {
+      ossimNotify(ossimNotifyLevel_DEBUG) <<  "ossimWorldWindHandler::requestTile: returning NULL tile " << std::endl;
+   }
+   
+   return 0;
+}
+
+
+ossimRefPtr<ossimImageData> ossimWorldWindHandler::requestDiskCacheTile(ossim_uint32 level,
+                                                                        ossim_uint32 X,
+                                                                        ossim_uint32 Y)
+{
+   ossimRefPtr<ossimImageData> data;
+   ossimFilename relativeFile = buildFullRelativeFilename(level, Y, X);
+   ossimFilename fullPath     = theDiskCache->fullPath(relativeFile);
+   if(fullPath.exists())
+   {
+      if(fullPath.fileSize() > 1)
+      {
+         ossimRefPtr<ossimImageHandler> ih = ossimImageHandlerRegistry::instance()->open(fullPath);
+         
+         if(ih.valid())
+         {
+            data = ih->getTile(ih->getBoundingRect());
+            if(data.valid())
+            {
+               data->setOrigin(ossimIpt(X, Y));
+               theDiskCache->accessFile(relativeFile);
+               ossimAppFixedTileCache::instance()->addTile(theRLevelCacheId[level],
+                                                           data);
+//             if(data.valid())
+//             {
+//                ossim_uint8* bands[3];
+//                bands[0] = (ossim_uint8*)data->getBuf(0);
+//                bands[1] = (ossim_uint8*)data->getBuf(1);
+//                bands[2] = (ossim_uint8*)data->getBuf(2);
+
+//                ossim_uint32 maxSize = data->getWidth()*data->getHeight();
+//                ossim_uint32 offset  = 0;
+
+//                for(offset = 0; offset < maxSize; ++offset)
+//                {
+//                   if((bands[0][offset] == 255)&&
+//                      (bands[1][offset] == 255)&&
+//                      (bands[2][offset] == 255))
+//                   {
+//                      bands[0][offset] = bands[1][offset] = bands[2][offset] = 0;
+//                   }
+//                }
+//                data->validate();
+               
+               if(data->getDataObjectStatus() == OSSIM_EMPTY)
+               {
+                  theDiskCache->removeFile(relativeFile);
+                  theDiskCache->addFile(relativeFile);
+                  data = 0;
+               }
+               return data;
+            }
+         }
+      }
+   }
+   else if(theDiskCache->isInCache(relativeFile))
+   {
+      theDiskCache->accessFile(relativeFile);
+   }
+
+   return data;
+}
+
+ossimRefPtr<ossimImageData> ossimWorldWindHandler::requestMemoryCacheTile(ossim_uint32 level,
+                                                                          ossim_uint32 X,
+                                                                          ossim_uint32 Y)
+{
+   ossimFilename relativeFile = buildFullRelativeFilename(level, Y, X);
+   ossimRefPtr<ossimImageData> data = ossimAppFixedTileCache::instance()->getTile(theRLevelCacheId[level],
+                                                                                  ossimIpt(X,Y));
+   return data;
+}
+
+ossimFilename ossimWorldWindHandler::buildTileFilename(ossim_uint32 level,
+                                                   ossim_uint32 row,
+                                                   ossim_uint32 col)const
+{
+   std::ostringstream out;
+
+   out << level << "/"
+       << std::setw(4) << std::setfill('0') << row << "/"
+       << std::setw(4) << std::setfill('0') << row << "_"
+       << std::setw(4) << std::setfill('0') << col;
+
+   if(isOpen())
+   {
+      if(theLayers[theCurrentIdx].theExtension != "")
+      {
+         out << "." << theLayers[theCurrentIdx].theExtension;
+      }
+   }
+   return ossimFilename(out.str().c_str());
+}
+
+ossimFilename ossimWorldWindHandler::buildFullRelativeFilename(ossim_uint32 level,
+                                                               ossim_uint32 row,
+                                                               ossim_uint32 col)const
+{
+   if(!isOpen()) return ossimFilename("");
+   std::ostringstream out;
+
+   ossimFilename tileFilename = buildTileFilename(level, row, col);
+
+   out << theLayers[theCurrentIdx].theChildLayerName << "/"
+       << theLayers[theCurrentIdx].theQuadTileSetName << "/"
+       << tileFilename;
+
+   return ossimFilename(out.str());
+}
+
+bool ossimWorldWindHandler::saveState(ossimKeywordlist& kwl,
+                                      const char* prefix)const
+{
+   return ossimImageHandler::saveState(kwl, prefix);
+}
+
+bool ossimWorldWindHandler::loadState(const ossimKeywordlist& kwl,
+                                      const char* prefix)
+{
+   ossimImageHandler::loadState(kwl, prefix);
+
+   return open();
+}
+
+
+ossimRefPtr<ossimImageData> ossimWorldWindHandler::convertToProperResult(ossimRefPtr<ossimImageData> data)
+{
+   ossimRefPtr<ossimImageData> result = data.get();
+   
+   if(data->getNumberOfBands() != 3)
+   {
+      theLocalTile->setImageRectangle(data->getImageRectangle());
+      ossim_uint8* srcBands[3];
+      ossim_uint8* destBands[3];
+      srcBands[0] = (ossim_uint8*)data->getBuf(0);
+      srcBands[1] = (ossim_uint8*)data->getBuf(1);
+      srcBands[2] = (ossim_uint8*)data->getBuf(2);
+      destBands[0] = (ossim_uint8*)theLocalTile->getBuf(0);
+      destBands[1] = (ossim_uint8*)theLocalTile->getBuf(1);
+      destBands[2] = (ossim_uint8*)theLocalTile->getBuf(2);
+      
+      if(!srcBands[1]) srcBands[1] = srcBands[0];
+      if(!srcBands[2]) srcBands[2] = srcBands[0];
+      ossim_uint32 maxSize = data->getWidth()*data->getHeight();
+      ossim_uint32 offset  = 0;
+      
+      for(offset = 0; offset < maxSize; ++offset)
+      {
+         destBands[0][offset] = srcBands[0][offset];
+         destBands[1][offset] = srcBands[1][offset];
+         destBands[2][offset] = srcBands[2][offset];
+      }
+      theLocalTile->validate();
+      result = theLocalTile.get();
+   }
+
+   return result;
+}
diff --git a/ossim_plugins/worldwind/ossimWorldWindHandler.h b/ossim_plugins/worldwind/ossimWorldWindHandler.h
new file mode 100644
index 0000000..1398a9d
--- /dev/null
+++ b/ossim_plugins/worldwind/ossimWorldWindHandler.h
@@ -0,0 +1,111 @@
+#ifndef ossimWorldWindHandler_HEADER
+#define ossimWorldWindHandler_HEADER
+#include <ossim/imaging/ossimImageHandler.h>
+#include <ossim/base/ossimXmlDocument.h>
+#include "ossimDiskCache.h"
+#include <ossim/imaging/ossimAppFixedTileCache.h>
+
+class ossimWorldWindHandler : public ossimImageHandler
+{
+public:
+   ossimWorldWindHandler();
+   virtual ~ossimWorldWindHandler();
+   virtual bool open();
+   virtual void close();
+   virtual bool isOpen()const;
+   virtual ossim_uint32 getNumberOfLines(ossim_uint32 resLevel)const;
+   virtual ossim_uint32 getNumberOfSamples(ossim_uint32 resLevel)const;
+   virtual ossim_uint32 getImageTileWidth()const;
+   virtual ossim_uint32 getImageTileHeight()const;
+   virtual ossim_uint32 getNumberOfInputBands()const;
+   virtual ossim_uint32 getNumberOfOutputBands()const;
+   virtual ossim_uint32 getCurrentEntry()const;
+   virtual ossim_uint32 getNumberOfEntries()const;
+   virtual bool setCurrentEntry(ossim_uint32 entryIdx);
+   virtual void getEntryList(std::vector<ossim_uint32>& entryList) const;
+   virtual ossim_uint32 getNumberOfDecimationLevels()const;
+   virtual ossimScalarType getOutputScalarType() const;
+  
+   virtual bool getImageGeometry(ossimKeywordlist& kwl,
+                                 const char* prefix=0);
+
+   virtual ossimRefPtr<ossimImageData> getTile(const ossimIrect& rect,
+                                               ossim_uint32 resLevel=0);
+
+   ossimIrect tileBounds(const ossimGpt& gpt,
+                         ossim_uint32 resLevel);
+   
+   ossimRefPtr<ossimImageData> requestTile(ossim_uint32 level,
+                                           ossim_uint32 X,
+                                           ossim_uint32 Y);
+
+   void resetMemoryCache();
+
+   virtual bool saveState(ossimKeywordlist& kwl,
+                          const char* prefix=0)const;
+
+   virtual bool loadState(const ossimKeywordlist& kwl,
+                          const char* prefix=0);
+    
+protected:
+   class ossimWorldWindHandlerInfo
+   {
+   public:
+      enum AccessorType
+      {
+         WMS = 0,
+         WW_TILE_SERVER = 1
+      };
+      ossimWorldWindHandlerInfo()
+      {}
+
+      ossimWorldWindHandlerInfo::AccessorType theAccessorType;
+      ossimString   theUrl;
+      ossim_float64 theNorth;
+      ossim_float64 theSouth;
+      ossim_float64 theEast;
+      ossim_float64 theWest;
+      ossim_uint32  theLevels;
+      ossim_float64 theGsd;
+      ossim_float64 theLevel0Gsd;
+      ossim_uint32  theTileSize;
+      ossim_uint64  theImageWidth;
+      ossim_uint64  theImageHeight;
+      ossimString   theDatasetName;
+      ossimString   theExtension;
+      ossimString   theChildLayerName;
+      ossimString   theQuadTileSetName;
+   };
+   void initialize();
+   bool populateWorldWindStructure();
+   
+   ossimFilename buildTileFilename(ossim_uint32 level,
+                                   ossim_uint32 row,
+                                   ossim_uint32 col)const;
+   ossimFilename buildFullRelativeFilename(ossim_uint32 level,
+                                           ossim_uint32 row,
+                                           ossim_uint32 col)const;
+   ossimRefPtr<ossimImageData> requestMemoryCacheTile(ossim_uint32 level,
+                                                      ossim_uint32 X,
+                                                      ossim_uint32 Y);
+   ossimRefPtr<ossimImageData> requestDiskCacheTile(ossim_uint32 level,
+                                                    ossim_uint32 X,
+                                                    ossim_uint32 Y);
+   ossimRefPtr<ossimImageData> convertToProperResult(ossimRefPtr<ossimImageData> data);
+   
+   ossimRefPtr<ossimXmlDocument> theXmlDocument;
+
+   std::vector<ossimWorldWindHandlerInfo> theLayers;
+   ossim_uint32 theCurrentIdx;
+
+   ossimRefPtr<ossimDiskCache> theDiskCache;
+   ossimRefPtr<ossimImageData> theLocalTile;
+   ossimRefPtr<ossimImageData> theResultTile;
+/*    std::vector<ossim_uint8>    theJpegDecodeBuffer; */
+   std::vector<ossimAppFixedTileCache::ossimAppFixedCacheId> theRLevelCacheId;
+
+   
+TYPE_DATA
+};
+
+#endif
diff --git a/ossim_plugins/worldwind/ossimWorldWindJpegImage.cpp b/ossim_plugins/worldwind/ossimWorldWindJpegImage.cpp
new file mode 100644
index 0000000..1a6b602
--- /dev/null
+++ b/ossim_plugins/worldwind/ossimWorldWindJpegImage.cpp
@@ -0,0 +1,260 @@
+#include "ossimWorldWindJpegImage.h"
+#include <fstream>
+#include <cstring>
+extern "C" {
+#include <jpeglib.h>
+#include <setjmp.h>
+#define JPEG_IO_BUFFER_SIZE   2048
+#define OUTPUT_BUF_SIZE  4096    /* choose an efficiently fwrite'able size */
+  
+typedef struct {
+    struct jpeg_source_mgr pub;   /* public fields */
+
+    JOCTET* buffer;               /* start of buffer */
+   std::istream *stream;
+} ossimWorldWind_source_mgr;
+   
+typedef struct {
+    struct jpeg_destination_mgr pub;
+
+   std::ostream *stream;
+    JOCTET * buffer;
+} ossimWorldWind_destination_mgr;
+
+typedef ossimWorldWind_destination_mgr * ossimWorldWind_dest_ptr;
+
+
+typedef ossimWorldWind_source_mgr * ossimWorldWind_src_ptr;
+
+   
+void ossimWorldWind_init_source ( j_decompress_ptr )
+{
+}
+#define OUTPUT_BUF_SIZE  4096    /* choose an efficiently fwrite'able size */
+
+void init_destination (j_compress_ptr cinfo)
+{
+    ossimWorldWind_dest_ptr dest = (ossimWorldWind_dest_ptr) cinfo->dest;
+
+    /* Allocate the output buffer --- it will be released when done with image */
+    dest->buffer = (JOCTET *)
+        (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+        OUTPUT_BUF_SIZE * sizeof(JOCTET));
+    dest->pub.next_output_byte = dest->buffer;
+    dest->pub.free_in_buffer = OUTPUT_BUF_SIZE;
+}
+
+boolean empty_output_buffer (j_compress_ptr cinfo)
+{
+    ossimWorldWind_dest_ptr dest = (ossimWorldWind_dest_ptr) cinfo->dest;
+
+    dest->stream->write((char*)dest->buffer, OUTPUT_BUF_SIZE);
+    dest->pub.next_output_byte = dest->buffer;
+    dest->pub.free_in_buffer = OUTPUT_BUF_SIZE;
+    return TRUE;
+}
+void term_destination (j_compress_ptr cinfo)
+{
+    ossimWorldWind_dest_ptr dest = (ossimWorldWind_dest_ptr) cinfo->dest;
+    size_t datacount = OUTPUT_BUF_SIZE - dest->pub.free_in_buffer;
+    /* Write any data remaining in the buffer */
+    if (datacount > 0)
+       dest->stream->write((char*)dest->buffer, datacount);
+}
+
+boolean ossimWorldWind_fill_input_buffer ( j_decompress_ptr cinfo )
+{
+    ossimWorldWind_src_ptr src = (ossimWorldWind_src_ptr) cinfo->src;
+
+    src->pub.next_input_byte = src->buffer;
+    std::streamsize start = src->stream->tellg();
+    src->stream->read((char*)(src->buffer),
+                      JPEG_IO_BUFFER_SIZE).tellg();
+    std::streamsize end = src->stream->tellg();
+    
+    src->pub.bytes_in_buffer = end - start;
+
+    if (src->pub.bytes_in_buffer == 0) // check for end-of-stream
+    {
+        // Insert a fake EOI marker
+        src->buffer[0] = 0xFF;
+        src->buffer[1] = JPEG_EOI;
+        src->pub.bytes_in_buffer = 2;
+    }
+    return TRUE;
+}
+
+void ossimWorldWind_skip_input_data ( j_decompress_ptr cinfo, long num_bytes )
+{
+    if (num_bytes > 0)
+    {
+        ossimWorldWind_src_ptr src = (ossimWorldWind_src_ptr) cinfo->src;
+
+        while (num_bytes > (long)src->pub.bytes_in_buffer)
+        {
+            num_bytes -= (long) src->pub.bytes_in_buffer;
+            src->pub.fill_input_buffer(cinfo);
+        }
+        src->pub.next_input_byte += (size_t) num_bytes;
+        src->pub.bytes_in_buffer -= (size_t) num_bytes;
+    }
+}
+
+void ossimWorldWind_term_source ( j_decompress_ptr cinfo )
+{
+    ossimWorldWind_src_ptr src = (ossimWorldWind_src_ptr) cinfo->src;
+
+    if (src->pub.bytes_in_buffer > 0)
+       src->stream->seekg(-(long)src->pub.bytes_in_buffer, std::ios_base::cur);
+    delete[] src->buffer;
+}
+
+
+// JPEG error manager:
+
+struct ossimWorldWind_error_mgr {
+  struct jpeg_error_mgr pub;    /* "public" fields */
+
+  jmp_buf setjmp_buffer;    /* for return to caller */
+};
+
+typedef struct ossimWorldWind_error_mgr * ossimWorldWind_error_ptr;
+
+/*
+ * Here's the routine that will replace the standard error_exit method:
+ */
+
+void ossimWorldWind_error_exit (j_common_ptr cinfo)
+{
+  /* cinfo->err really points to a ossimWorldWind_error_mgr struct, so coerce pointer */
+  ossimWorldWind_error_ptr myerr = (ossimWorldWind_error_ptr) cinfo->err;
+
+  /* Always display the message. */
+  /* We could postpone this until after returning, if we chose. */
+  if (cinfo->err->output_message) (*cinfo->err->output_message) (cinfo);
+
+  /* Return control to the setjmp point */
+  longjmp(myerr->setjmp_buffer, 1);
+}
+
+   
+void ossimWorldWind_jpeg_io_src( j_decompress_ptr cinfo, std::istream& infile )
+{
+    ossimWorldWind_src_ptr src;
+
+    if (cinfo->src == NULL) {    /* first time for this JPEG object? */
+        cinfo->src = (struct jpeg_source_mgr *)
+            (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
+            sizeof(ossimWorldWind_source_mgr));
+    }
+    src = (ossimWorldWind_src_ptr) cinfo->src;
+    src->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */
+    src->buffer = new JOCTET[JPEG_IO_BUFFER_SIZE];
+    src->pub.next_input_byte = NULL; /* until buffer loaded */
+    src->stream = &infile;
+
+    src->pub.init_source = ossimWorldWind_init_source;
+    src->pub.fill_input_buffer = ossimWorldWind_fill_input_buffer;
+    src->pub.skip_input_data = ossimWorldWind_skip_input_data;
+    src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */
+    src->pub.term_source = ossimWorldWind_term_source;
+}
+
+void ossimWorldWind_init_destination (j_compress_ptr cinfo)
+{
+    ossimWorldWind_dest_ptr dest = (ossimWorldWind_dest_ptr) cinfo->dest;
+
+    /* Allocate the output buffer --- it will be released when done with image */
+    dest->buffer = (JOCTET *)
+        (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+        OUTPUT_BUF_SIZE * sizeof(JOCTET));
+    dest->pub.next_output_byte = dest->buffer;
+    dest->pub.free_in_buffer = OUTPUT_BUF_SIZE;
+}
+
+boolean ossimWorldWind_empty_output_buffer (j_compress_ptr cinfo)
+{
+    ossimWorldWind_dest_ptr dest = (ossimWorldWind_dest_ptr) cinfo->dest;
+
+    dest->stream->write((char*)(dest->buffer), OUTPUT_BUF_SIZE);
+    dest->pub.next_output_byte = dest->buffer;
+    dest->pub.free_in_buffer = OUTPUT_BUF_SIZE;
+    return TRUE;
+}
+
+void ossimWorldWind_term_destination (j_compress_ptr cinfo)
+{
+    ossimWorldWind_dest_ptr dest = (ossimWorldWind_dest_ptr) cinfo->dest;
+    size_t datacount = OUTPUT_BUF_SIZE - dest->pub.free_in_buffer;
+    /* Write any data remaining in the buffer */
+    if (datacount > 0)
+       dest->stream->write((char*)(dest->buffer), datacount);
+}
+
+void ossimWorldWind_jpeg_io_dest (j_compress_ptr cinfo, std::ostream& outfile)
+{
+    ossimWorldWind_dest_ptr dest;
+
+    if (cinfo->dest == NULL) {    /* first time for this JPEG object? */
+        cinfo->dest = (struct jpeg_destination_mgr *)
+            (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
+            sizeof(ossimWorldWind_destination_mgr));
+    }
+
+    dest = (ossimWorldWind_dest_ptr) cinfo->dest;
+    dest->pub.init_destination = ossimWorldWind_init_destination;
+    dest->pub.empty_output_buffer = ossimWorldWind_empty_output_buffer;
+    dest->pub.term_destination = ossimWorldWind_term_destination;
+    dest->stream = &outfile;
+}
+} // end extern
+
+int ossimWorldWindJpegImage::decode(std::istream& inputStream,
+                                    ossim_uint8* destBuffer)
+{
+   struct jpeg_decompress_struct cinfo;
+   struct ossimWorldWind_error_mgr jerr;
+   JSAMPARRAY tempbuf;
+   unsigned char *ptr;
+   unsigned stride;
+   
+   cinfo.err = jpeg_std_error( &jerr.pub );
+   jerr.pub.error_exit = ossimWorldWind_error_exit;
+   
+   cinfo.err->output_message=NULL;
+   
+   /* Establish the setjmp return context for ossimWorldWind_error_exit to use. */
+   if (setjmp(jerr.setjmp_buffer))
+   {
+      /* If we get here, the JPEG code has signaled an error.
+       * We need to clean up the JPEG object, close the input file, and return.
+       */
+      (cinfo.src->term_source)(&cinfo);
+      jpeg_destroy_decompress(&cinfo);
+      return FALSE;
+   }
+   
+   jpeg_create_decompress( &cinfo );
+   ossimWorldWind_jpeg_io_src( &cinfo, inputStream );
+   jpeg_read_header( &cinfo, TRUE );
+   cinfo.out_color_space = JCS_RGB;
+   jpeg_start_decompress( &cinfo );
+   
+   ptr = destBuffer;
+
+   stride = cinfo.output_width * 3;
+   tempbuf = (*cinfo.mem->alloc_sarray)
+      ((j_common_ptr) &cinfo, JPOOL_IMAGE, stride, 1 );
+   
+   while ( cinfo.output_scanline < cinfo.output_height )
+   {
+      jpeg_read_scanlines( &cinfo, tempbuf, 1 );
+      memcpy( ptr, tempbuf[0], stride );
+      ptr += stride;
+   }
+   jpeg_finish_decompress( &cinfo );
+   jpeg_destroy_decompress( &cinfo );
+   
+   return TRUE;
+   
+}
diff --git a/ossim_plugins/worldwind/ossimWorldWindJpegImage.h b/ossim_plugins/worldwind/ossimWorldWindJpegImage.h
new file mode 100644
index 0000000..c5de5c7
--- /dev/null
+++ b/ossim_plugins/worldwind/ossimWorldWindJpegImage.h
@@ -0,0 +1,14 @@
+#ifndef ossimWorldWindJpegImage_HEADER
+#define ossimWorldWindJpegImage_HEADER
+#include <iostream>
+#include <ossim/base/ossimConstants.h>
+
+class ossimWorldWindJpegImage
+{
+public:
+   static int decode(std::istream& inputStream,
+                      ossim_uint8* destBuffer);
+   
+};
+
+#endif
diff --git a/ossim_plugins/worldwind/ossimWorldWindPluginInit.cpp b/ossim_plugins/worldwind/ossimWorldWindPluginInit.cpp
new file mode 100644
index 0000000..2a85116
--- /dev/null
+++ b/ossim_plugins/worldwind/ossimWorldWindPluginInit.cpp
@@ -0,0 +1,57 @@
+#include <ossim/plugin/ossimSharedObjectBridge.h>
+#include <ossim/base/ossimString.h>
+#include <ossim/imaging/ossimImageHandlerRegistry.h>
+#include "ossimWorldWindFactory.h"
+#include "ossimWorldWindExports.h"
+
+static void setDescription(ossimString& description)
+{
+   description = "World Wind Plugin";
+}
+
+extern "C"
+{
+   ossimSharedObjectInfo  myInfo;
+   ossimString theDescription;
+   std::vector<ossimString> theObjList;
+   const char* getDescription()
+   {
+      return theDescription.c_str();
+   }
+   int getNumberOfClassNames()
+   {
+      return (int)theObjList.size();
+   }
+   const char* getClassName(int idx)
+   {
+      if(idx < (int)theObjList.size())
+      {
+         return theObjList[0].c_str();
+      }
+      return (const char*)0;
+   }
+
+   /* Note symbols need to be exported on windoze... */ 
+   OSSIM_WORLDWIND_DLL void ossimSharedLibraryInitialize(
+      ossimSharedObjectInfo** info)
+   {    
+      myInfo.getDescription = (ossimSharedLibraryGetDescriptionPtr)getDescription;
+      myInfo.getNumberOfClassNames = (ossimSharedLibraryGetNumberOfClassNamesPtr)getNumberOfClassNames;
+      myInfo.getClassName = (ossimSharedLibraryGetClassNamesPtr)getClassName;
+      
+      *info = &myInfo;
+
+      /* Register the readers... */
+      ossimImageHandlerRegistry::instance()->registerFactory(ossimWorldWindFactory::instance());
+      
+     /* Register the writers... */
+     
+     setDescription(theDescription);
+  }
+
+   /* Note symbols need to be exported on windoze... */ 
+   OSSIM_WORLDWIND_DLL void ossimSharedLibraryFinalize()
+   {
+      
+   }
+}
diff --git a/ossim_plugins/worldwind/ossimworldwind_plugin.vcproj b/ossim_plugins/worldwind/ossimworldwind_plugin.vcproj
new file mode 100644
index 0000000..d824f39
--- /dev/null
+++ b/ossim_plugins/worldwind/ossimworldwind_plugin.vcproj
@@ -0,0 +1,252 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="9.00"
+	Name="ossimworldwind_plugin"
+	ProjectGUID="{535CF245-422A-403C-984C-FBC69051D926}"
+	RootNamespace="ossimworldwind_plugin"
+	Keyword="Win32Proj"
+	TargetFrameworkVersion="131072"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="Debug|Win32"
+			OutputDirectory="Debug"
+			IntermediateDirectory="Debug"
+			ConfigurationType="2"
+			InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories=""$(SolutionDir)..\..\..\ossim_plugins\gdal";"$(SolutionDir)..\..\..\ossim_plugins";"$(SolutionDir)..\..\..\ossim_dependencies\src\gdal-1.4.0\frmts\mem";"$(SolutionDir)..\..\..\ossim\include\";"$(SolutionDir)..\..\..\ossim_dependencies\src\gdal-1.4.0\gcore";"$(SolutionDir)..\..\..\ossim_dependencies\src\3rdParty\include""
+				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;OSSIMWORLDWIND_PLUGIN_EXPORTS"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				OutputFile="$(SolutionDir)bin\ossimworldwind_plugind.dll"
+				LinkIncremental="2"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/ossimworldwind_plugin.pdb"
+				SubSystem="2"
+				RandomizedBaseAddress="1"
+				DataExecutionPrevention="0"
+				ImportLibrary="$(OutDir)/ossimworldwind_plugin.lib"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|Win32"
+			OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+			IntermediateDirectory="Release"
+			ConfigurationType="2"
+			InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				AdditionalIncludeDirectories=""$(InputDir)..\..\ossim\include\";"$(InputDir)..";"$(InputDir)..\..\libwms\include";"$(InputDir)..\..\ossim_dependencies\include""
+				PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;OSSIMUSINGDLL"
+				RuntimeLibrary="2"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="libjpeg.lib  OpenThreads.lib"
+				OutputFile="$(OutDir)\bin\$(ProjectName).dll"
+				LinkIncremental="1"
+				AdditionalLibraryDirectories=""$(InputDir)..\..\ossim_dependencies\lib""
+				IgnoreDefaultLibraryNames="LIBCMT"
+				GenerateDebugInformation="false"
+				ProgramDatabaseFile=""
+				SubSystem="2"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				RandomizedBaseAddress="1"
+				DataExecutionPrevention="0"
+				ImportLibrary="$(OutDir)\lib\$(ProjectName).lib"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="Source Files"
+			Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
+			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+			>
+			<File
+				RelativePath=".\ossimDiskCache.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\ossimSharedDiskCacheManager.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\ossimWorldWindFactory.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\ossimWorldWindHandler.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\ossimWorldWindJpegImage.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\ossimWorldWindPluginInit.cpp"
+				>
+			</File>
+		</Filter>
+		<Filter
+			Name="Header Files"
+			Filter="h;hpp;hxx;hm;inl;inc;xsd"
+			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+			>
+			<File
+				RelativePath=".\ossimDiskCache.h"
+				>
+			</File>
+			<File
+				RelativePath=".\ossimSharedDiskCacheManager.h"
+				>
+			</File>
+			<File
+				RelativePath=".\ossimWorldWindExports.h"
+				>
+			</File>
+			<File
+				RelativePath=".\ossimWorldWindFactory.h"
+				>
+			</File>
+			<File
+				RelativePath=".\ossimWorldWindHandler.h"
+				>
+			</File>
+			<File
+				RelativePath=".\ossimWorldWindJpegImage.h"
+				>
+			</File>
+		</Filter>
+		<Filter
+			Name="Resource Files"
+			Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
+			UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+			>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
diff --git a/ossim_plugins/xcode/ossim_plugins.xcodeproj/project.pbxproj b/ossim_plugins/xcode/ossim_plugins.xcodeproj/project.pbxproj
new file mode 100644
index 0000000..7151514
--- /dev/null
+++ b/ossim_plugins/xcode/ossim_plugins.xcodeproj/project.pbxproj
@@ -0,0 +1,4680 @@
+// !$*UTF8*$!
+{
+	archiveVersion = 1;
+	classes = {
+	};
+	objectVersion = 42;
+	objects = {
+
+/* Begin PBXAggregateTarget section */
+		43378DC010D021ED00ECC5AD /* All */ = {
+			isa = PBXAggregateTarget;
+			buildConfigurationList = 43378DD710D0221400ECC5AD /* Build configuration list for PBXAggregateTarget "All" */;
+			buildPhases = (
+			);
+			dependencies = (
+				43A9A1A51151AE4E000860DA /* PBXTargetDependency */,
+				43378DC810D0220100ECC5AD /* PBXTargetDependency */,
+				43378DCA10D0220100ECC5AD /* PBXTargetDependency */,
+				43378DCC10D0220100ECC5AD /* PBXTargetDependency */,
+				43378DCE10D0220100ECC5AD /* PBXTargetDependency */,
+				43378DD010D0220100ECC5AD /* PBXTargetDependency */,
+				43378DD210D0220100ECC5AD /* PBXTargetDependency */,
+				43333CC110FD00CD00A5B432 /* PBXTargetDependency */,
+				4310BB19110DD99B00C258B9 /* PBXTargetDependency */,
+			);
+			name = All;
+			productName = All;
+		};
+/* End PBXAggregateTarget section */
+
+/* Begin PBXBuildFile section */
+		186EF9590B1F19F200F7886A /* ossim.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 186EF8EA0B1F19E400F7886A /* ossim.framework */; };
+		186EF98A0B1F234F00F7886A /* ossim.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 186EF8EA0B1F19E400F7886A /* ossim.framework */; };
+		186EF9AA0B1F236800F7886A /* ossimChipMatch.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 186EF98C0B1F236800F7886A /* ossimChipMatch.cpp */; };
+		186EF9AB0B1F236800F7886A /* ossimChipMatch.h in Headers */ = {isa = PBXBuildFile; fileRef = 186EF98D0B1F236800F7886A /* ossimChipMatch.h */; };
+		186EF9AC0B1F236800F7886A /* ossimDensityReducer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 186EF98E0B1F236800F7886A /* ossimDensityReducer.cpp */; };
+		186EF9AD0B1F236800F7886A /* ossimDensityReducer.h in Headers */ = {isa = PBXBuildFile; fileRef = 186EF98F0B1F236800F7886A /* ossimDensityReducer.h */; };
+		186EF9AE0B1F236800F7886A /* ossimExtremaFilter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 186EF9900B1F236800F7886A /* ossimExtremaFilter.cpp */; };
+		186EF9AF0B1F236800F7886A /* ossimExtremaFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 186EF9910B1F236800F7886A /* ossimExtremaFilter.h */; };
+		186EF9B00B1F236800F7886A /* ossimHarrisCorners.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 186EF9920B1F236800F7886A /* ossimHarrisCorners.cpp */; };
+		186EF9B10B1F236800F7886A /* ossimHarrisCorners.h in Headers */ = {isa = PBXBuildFile; fileRef = 186EF9930B1F236800F7886A /* ossimHarrisCorners.h */; };
+		186EF9B20B1F236800F7886A /* ossimImageCorrelator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 186EF9940B1F236800F7886A /* ossimImageCorrelator.cpp */; };
+		186EF9B30B1F236800F7886A /* ossimImageCorrelator.h in Headers */ = {isa = PBXBuildFile; fileRef = 186EF9950B1F236800F7886A /* ossimImageCorrelator.h */; };
+		186EF9B40B1F236800F7886A /* ossimModelOptimizer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 186EF9960B1F236800F7886A /* ossimModelOptimizer.cpp */; };
+		186EF9B50B1F236800F7886A /* ossimModelOptimizer.h in Headers */ = {isa = PBXBuildFile; fileRef = 186EF9970B1F236800F7886A /* ossimModelOptimizer.h */; };
+		186EF9B60B1F236800F7886A /* ossimMultiplier.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 186EF9980B1F236800F7886A /* ossimMultiplier.cpp */; };
+		186EF9B70B1F236800F7886A /* ossimMultiplier.h in Headers */ = {isa = PBXBuildFile; fileRef = 186EF9990B1F236800F7886A /* ossimMultiplier.h */; };
+		186EF9B80B1F236800F7886A /* ossimNCC_FFTW.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 186EF99A0B1F236800F7886A /* ossimNCC_FFTW.cpp */; };
+		186EF9B90B1F236800F7886A /* ossimNCC_FFTW.h in Headers */ = {isa = PBXBuildFile; fileRef = 186EF99B0B1F236800F7886A /* ossimNCC_FFTW.h */; };
+		186EF9BA0B1F236800F7886A /* ossimOutlierRejection.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 186EF99C0B1F236800F7886A /* ossimOutlierRejection.cpp */; };
+		186EF9BB0B1F236800F7886A /* ossimOutlierRejection.h in Headers */ = {isa = PBXBuildFile; fileRef = 186EF99D0B1F236800F7886A /* ossimOutlierRejection.h */; };
+		186EF9BC0B1F236800F7886A /* ossimRegistrationExports.h in Headers */ = {isa = PBXBuildFile; fileRef = 186EF99E0B1F236800F7886A /* ossimRegistrationExports.h */; };
+		186EF9BD0B1F236800F7886A /* ossimRegistrationImageSourceFactory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 186EF99F0B1F236800F7886A /* ossimRegistrationImageSourceFactory.cpp */; };
+		186EF9BE0B1F236800F7886A /* ossimRegistrationImageSourceFactory.h in Headers */ = {isa = PBXBuildFile; fileRef = 186EF9A00B1F236800F7886A /* ossimRegistrationImageSourceFactory.h */; };
+		186EF9BF0B1F236800F7886A /* ossimRegistrationMiscFactory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 186EF9A10B1F236800F7886A /* ossimRegistrationMiscFactory.cpp */; };
+		186EF9C00B1F236800F7886A /* ossimRegistrationMiscFactory.h in Headers */ = {isa = PBXBuildFile; fileRef = 186EF9A20B1F236800F7886A /* ossimRegistrationMiscFactory.h */; };
+		186EF9C10B1F236800F7886A /* ossimRegistrationPluginInit.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 186EF9A30B1F236800F7886A /* ossimRegistrationPluginInit.cpp */; };
+		186EF9C20B1F236800F7886A /* ossimRunningSum.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 186EF9A40B1F236800F7886A /* ossimRunningSum.cpp */; };
+		186EF9C30B1F236800F7886A /* ossimRunningSum.h in Headers */ = {isa = PBXBuildFile; fileRef = 186EF9A50B1F236800F7886A /* ossimRunningSum.h */; };
+		186EF9C40B1F236800F7886A /* ossimSquareFunction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 186EF9A60B1F236800F7886A /* ossimSquareFunction.cpp */; };
+		186EF9C50B1F236800F7886A /* ossimSquareFunction.h in Headers */ = {isa = PBXBuildFile; fileRef = 186EF9A70B1F236800F7886A /* ossimSquareFunction.h */; };
+		186EF9C60B1F236800F7886A /* ossimTieGenerator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 186EF9A80B1F236800F7886A /* ossimTieGenerator.cpp */; };
+		186EF9C70B1F236800F7886A /* ossimTieGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = 186EF9A90B1F236800F7886A /* ossimTieGenerator.h */; };
+		186EFA330B1F32FF00F7886A /* ossimDiskCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 186EFA260B1F32FF00F7886A /* ossimDiskCache.cpp */; };
+		186EFA340B1F32FF00F7886A /* ossimDiskCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 186EFA270B1F32FF00F7886A /* ossimDiskCache.h */; };
+		186EFA350B1F32FF00F7886A /* ossimSharedDiskCacheManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 186EFA280B1F32FF00F7886A /* ossimSharedDiskCacheManager.cpp */; };
+		186EFA360B1F32FF00F7886A /* ossimSharedDiskCacheManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 186EFA290B1F32FF00F7886A /* ossimSharedDiskCacheManager.h */; };
+		186EFA370B1F32FF00F7886A /* ossimWorldWindExports.h in Headers */ = {isa = PBXBuildFile; fileRef = 186EFA2B0B1F32FF00F7886A /* ossimWorldWindExports.h */; };
+		186EFA380B1F32FF00F7886A /* ossimWorldWindFactory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 186EFA2C0B1F32FF00F7886A /* ossimWorldWindFactory.cpp */; };
+		186EFA390B1F32FF00F7886A /* ossimWorldWindFactory.h in Headers */ = {isa = PBXBuildFile; fileRef = 186EFA2D0B1F32FF00F7886A /* ossimWorldWindFactory.h */; };
+		186EFA3A0B1F32FF00F7886A /* ossimWorldWindHandler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 186EFA2E0B1F32FF00F7886A /* ossimWorldWindHandler.cpp */; };
+		186EFA3B0B1F32FF00F7886A /* ossimWorldWindHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = 186EFA2F0B1F32FF00F7886A /* ossimWorldWindHandler.h */; };
+		186EFA3C0B1F32FF00F7886A /* ossimWorldWindJpegImage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 186EFA300B1F32FF00F7886A /* ossimWorldWindJpegImage.cpp */; };
+		186EFA3D0B1F32FF00F7886A /* ossimWorldWindJpegImage.h in Headers */ = {isa = PBXBuildFile; fileRef = 186EFA310B1F32FF00F7886A /* ossimWorldWindJpegImage.h */; };
+		186EFA3E0B1F32FF00F7886A /* ossimWorldWindPluginInit.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 186EFA320B1F32FF00F7886A /* ossimWorldWindPluginInit.cpp */; };
+		186EFA420B1F373E00F7886A /* ossim.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 186EF8EA0B1F19E400F7886A /* ossim.framework */; };
+		186EFA6D0B1F39FD00F7886A /* ossimNuiPluginInit.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 186EFA670B1F39FD00F7886A /* ossimNuiPluginInit.cpp */; };
+		186EFA6E0B1F39FD00F7886A /* ossimNuiHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = 186EFA680B1F39FD00F7886A /* ossimNuiHandler.h */; };
+		186EFA6F0B1F39FD00F7886A /* ossimNuiHandler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 186EFA690B1F39FD00F7886A /* ossimNuiHandler.cpp */; };
+		186EFA700B1F39FD00F7886A /* ossimNuiFactory.h in Headers */ = {isa = PBXBuildFile; fileRef = 186EFA6A0B1F39FD00F7886A /* ossimNuiFactory.h */; };
+		186EFA710B1F39FD00F7886A /* ossimNuiFactory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 186EFA6B0B1F39FD00F7886A /* ossimNuiFactory.cpp */; };
+		186EFA720B1F39FD00F7886A /* ossimNuiExports.h in Headers */ = {isa = PBXBuildFile; fileRef = 186EFA6C0B1F39FD00F7886A /* ossimNuiExports.h */; };
+		186EFA7E0B1F3B7D00F7886A /* ossim.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 186EF8EA0B1F19E400F7886A /* ossim.framework */; };
+		430D1FDD0BB2F96B0057E5FF /* ossim.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 186EF8EA0B1F19E400F7886A /* ossim.framework */; };
+		430D20830BB2FA450057E5FF /* ossimPngReaderFactory.h in Headers */ = {isa = PBXBuildFile; fileRef = 430D207A0BB2FA450057E5FF /* ossimPngReaderFactory.h */; };
+		430D20840BB2FA450057E5FF /* ossimPngWriterFactory.h in Headers */ = {isa = PBXBuildFile; fileRef = 430D207B0BB2FA450057E5FF /* ossimPngWriterFactory.h */; };
+		430D20850BB2FA450057E5FF /* ossimPngWriterFactory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 430D207C0BB2FA450057E5FF /* ossimPngWriterFactory.cpp */; };
+		430D20860BB2FA450057E5FF /* ossimPngPluginInit.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 430D207D0BB2FA450057E5FF /* ossimPngPluginInit.cpp */; };
+		430D20870BB2FA450057E5FF /* ossimPngReaderFactory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 430D207E0BB2FA450057E5FF /* ossimPngReaderFactory.cpp */; };
+		430D20880BB2FA450057E5FF /* ossimPngWriter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 430D207F0BB2FA450057E5FF /* ossimPngWriter.cpp */; };
+		430D20890BB2FA450057E5FF /* ossimPngWriter.h in Headers */ = {isa = PBXBuildFile; fileRef = 430D20800BB2FA450057E5FF /* ossimPngWriter.h */; };
+		430D208A0BB2FA450057E5FF /* ossimPngReader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 430D20810BB2FA450057E5FF /* ossimPngReader.cpp */; };
+		430D208B0BB2FA450057E5FF /* ossimPngReader.h in Headers */ = {isa = PBXBuildFile; fileRef = 430D20820BB2FA450057E5FF /* ossimPngReader.h */; };
+		4310BA77110DD27C00C258B9 /* jp2_local.h in Headers */ = {isa = PBXBuildFile; fileRef = 4310BA70110DD27C00C258B9 /* jp2_local.h */; };
+		4310BA78110DD27C00C258B9 /* jp2_shared.h in Headers */ = {isa = PBXBuildFile; fileRef = 4310BA71110DD27C00C258B9 /* jp2_shared.h */; };
+		4310BA79110DD27C00C258B9 /* jp2.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4310BA72110DD27C00C258B9 /* jp2.cpp */; };
+		4310BA7A110DD27C00C258B9 /* jpx_local.h in Headers */ = {isa = PBXBuildFile; fileRef = 4310BA73110DD27C00C258B9 /* jpx_local.h */; };
+		4310BA7B110DD27C00C258B9 /* jpx.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4310BA74110DD27C00C258B9 /* jpx.cpp */; };
+		4310BA7C110DD27C00C258B9 /* mj2_local.h in Headers */ = {isa = PBXBuildFile; fileRef = 4310BA75110DD27C00C258B9 /* mj2_local.h */; };
+		4310BA7D110DD27C00C258B9 /* mj2.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4310BA76110DD27C00C258B9 /* mj2.cpp */; };
+		4310BA86110DD2C600C258B9 /* libkdu_v62R.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 4310BA85110DD2C600C258B9 /* libkdu_v62R.dylib */; };
+		4313210A103C84DF00F96FDF /* Openthreads.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 437184710BCF07BA0002D30E /* Openthreads.framework */; };
+		4313210B103C84DF00F96FDF /* ossim.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 186EF8EA0B1F19E400F7886A /* ossim.framework */; };
+		4329336610FE4B8500C66EB8 /* liblt_kakadu.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4329336310FE4B8500C66EB8 /* liblt_kakadu.a */; };
+		4329336710FE4B8500C66EB8 /* libltidsdk.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4329336410FE4B8500C66EB8 /* libltidsdk.a */; };
+		43333CEB10FD029600A5B432 /* libfcgi.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 43333CE010FD029600A5B432 /* libfcgi.a */; };
+		43333CEC10FD029600A5B432 /* libfcgi++.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 43333CE110FD029600A5B432 /* libfcgi++.a */; };
+		43333CED10FD029600A5B432 /* libgd.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 43333CE210FD029600A5B432 /* libgd.a */; };
+		43333CEE10FD029600A5B432 /* libgdal.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 43333CE310FD029600A5B432 /* libgdal.a */; };
+		43333CEF10FD029600A5B432 /* libgif.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 43333CE410FD029600A5B432 /* libgif.a */; };
+		43333CF010FD029700A5B432 /* libjpeg.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 43333CE510FD029600A5B432 /* libjpeg.a */; };
+		43333CF310FD029700A5B432 /* libnuiSDK.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 43333CE810FD029600A5B432 /* libnuiSDK.a */; };
+		43333CF410FD029700A5B432 /* libpng.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 43333CE910FD029600A5B432 /* libpng.a */; };
+		43333CF510FD029700A5B432 /* libproj.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 43333CEA10FD029600A5B432 /* libproj.a */; };
+		43333CFE10FD031500A5B432 /* libkdu.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 43333CFD10FD031500A5B432 /* libkdu.a */; };
+		43333D0210FD032100A5B432 /* libkdu_a52R.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 43333D0110FD032100A5B432 /* libkdu_a52R.a */; };
+		43377F0410CFFB6400ECC5AD /* ossimCsmSensorModel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 43377EFF10CFFB6400ECC5AD /* ossimCsmSensorModel.cpp */; };
+		43377F0510CFFB6400ECC5AD /* ossimCsmPluginInit.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 43377F0010CFFB6400ECC5AD /* ossimCsmPluginInit.cpp */; };
+		43377F0610CFFB6400ECC5AD /* ossimCsmSensorModel.h in Headers */ = {isa = PBXBuildFile; fileRef = 43377F0110CFFB6400ECC5AD /* ossimCsmSensorModel.h */; };
+		43377F0710CFFB6400ECC5AD /* ossimCsmProjectionFactory.h in Headers */ = {isa = PBXBuildFile; fileRef = 43377F0210CFFB6400ECC5AD /* ossimCsmProjectionFactory.h */; };
+		43377F0810CFFB6400ECC5AD /* ossimCsmProjectionFactory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 43377F0310CFFB6400ECC5AD /* ossimCsmProjectionFactory.cpp */; };
+		43377F2110CFFC8200ECC5AD /* csmapi.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 43377F2010CFFC8200ECC5AD /* csmapi.framework */; };
+		43378A0310D01EFD00ECC5AD /* ossimCsmSupport.h in Headers */ = {isa = PBXBuildFile; fileRef = 43378A0110D01EFD00ECC5AD /* ossimCsmSupport.h */; };
+		43378A0410D01EFD00ECC5AD /* ossimCsmSupport.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 43378A0210D01EFD00ECC5AD /* ossimCsmSupport.cpp */; };
+		43378A1910D020D800ECC5AD /* ossim.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 186EF8EA0B1F19E400F7886A /* ossim.framework */; };
+		436A7E2C10FB9FC400985348 /* Openthreads.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 437184710BCF07BA0002D30E /* Openthreads.framework */; };
+		436A7E2D10FB9FC400985348 /* ossim.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 186EF8EA0B1F19E400F7886A /* ossim.framework */; };
+		436A7E4C10FBA00100985348 /* ossimMrSidReader.h in Headers */ = {isa = PBXBuildFile; fileRef = 436A7E4310FBA00100985348 /* ossimMrSidReader.h */; };
+		436A7E4D10FBA00100985348 /* ossimMrSidWriterFactory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 436A7E4410FBA00100985348 /* ossimMrSidWriterFactory.cpp */; };
+		436A7E4E10FBA00100985348 /* ossimMrSidWriter.h in Headers */ = {isa = PBXBuildFile; fileRef = 436A7E4510FBA00100985348 /* ossimMrSidWriter.h */; };
+		436A7E4F10FBA00100985348 /* ossimMrSidReaderFactory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 436A7E4610FBA00100985348 /* ossimMrSidReaderFactory.cpp */; };
+		436A7E5010FBA00100985348 /* ossimMrSidWriterFactory.h in Headers */ = {isa = PBXBuildFile; fileRef = 436A7E4710FBA00100985348 /* ossimMrSidWriterFactory.h */; };
+		436A7E5110FBA00100985348 /* ossimMrSidReader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 436A7E4810FBA00100985348 /* ossimMrSidReader.cpp */; };
+		436A7E5210FBA00100985348 /* ossimMrSidWriter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 436A7E4910FBA00100985348 /* ossimMrSidWriter.cpp */; };
+		436A7E5310FBA00100985348 /* ossimMrSidReaderFactory.h in Headers */ = {isa = PBXBuildFile; fileRef = 436A7E4A10FBA00100985348 /* ossimMrSidReaderFactory.h */; };
+		436A7E5410FBA00100985348 /* ossimMrSidPluginInit.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 436A7E4B10FBA00100985348 /* ossimMrSidPluginInit.cpp */; };
+		436A7F4B10FBB24200985348 /* ossimKakaduCompressor.h in Headers */ = {isa = PBXBuildFile; fileRef = 436A7F3010FBB24200985348 /* ossimKakaduCompressor.h */; };
+		436A7F4C10FBB24200985348 /* ossimKakaduOverviewBuilderFactory.h in Headers */ = {isa = PBXBuildFile; fileRef = 436A7F3110FBB24200985348 /* ossimKakaduOverviewBuilderFactory.h */; };
+		436A7F4D10FBB24200985348 /* ossimKakaduNitfWriter.h in Headers */ = {isa = PBXBuildFile; fileRef = 436A7F3210FBB24200985348 /* ossimKakaduNitfWriter.h */; };
+		436A7F4E10FBB24200985348 /* ossimKakaduMessaging.h in Headers */ = {isa = PBXBuildFile; fileRef = 436A7F3310FBB24200985348 /* ossimKakaduMessaging.h */; };
+		436A7F4F10FBB24200985348 /* ossimKakaduKeywords.h in Headers */ = {isa = PBXBuildFile; fileRef = 436A7F3410FBB24200985348 /* ossimKakaduKeywords.h */; };
+		436A7F5010FBB24200985348 /* ossimKakaduJp2Reader.h in Headers */ = {isa = PBXBuildFile; fileRef = 436A7F3510FBB24200985348 /* ossimKakaduJp2Reader.h */; };
+		436A7F5110FBB24200985348 /* ossimKakaduReaderFactory.h in Headers */ = {isa = PBXBuildFile; fileRef = 436A7F3610FBB24200985348 /* ossimKakaduReaderFactory.h */; };
+		436A7F5210FBB24200985348 /* ossimKakaduOverviewBuilderFactory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 436A7F3710FBB24200985348 /* ossimKakaduOverviewBuilderFactory.cpp */; };
+		436A7F5310FBB24200985348 /* ossimKakaduCompressedTarget.h in Headers */ = {isa = PBXBuildFile; fileRef = 436A7F3810FBB24200985348 /* ossimKakaduCompressedTarget.h */; };
+		436A7F5410FBB24200985348 /* ossimKakaduJ2kReader.h in Headers */ = {isa = PBXBuildFile; fileRef = 436A7F3910FBB24200985348 /* ossimKakaduJ2kReader.h */; };
+		436A7F5510FBB24200985348 /* ossimKakaduJp2Writer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 436A7F3A10FBB24200985348 /* ossimKakaduJp2Writer.cpp */; };
+		436A7F5610FBB24200985348 /* ossimKakaduCompressedTarget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 436A7F3B10FBB24200985348 /* ossimKakaduCompressedTarget.cpp */; };
+		436A7F5710FBB24200985348 /* ossimKakaduNitfOverviewBuilder.h in Headers */ = {isa = PBXBuildFile; fileRef = 436A7F3C10FBB24200985348 /* ossimKakaduNitfOverviewBuilder.h */; };
+		436A7F5810FBB24200985348 /* ossimKakaduCompressor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 436A7F3D10FBB24200985348 /* ossimKakaduCompressor.cpp */; };
+		436A7F5910FBB24200985348 /* ossimKakaduNitfOverviewBuilder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 436A7F3E10FBB24200985348 /* ossimKakaduNitfOverviewBuilder.cpp */; };
+		436A7F5A10FBB24200985348 /* ossimKakaduNitfReader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 436A7F3F10FBB24200985348 /* ossimKakaduNitfReader.cpp */; };
+		436A7F5B10FBB24200985348 /* ossimKakaduJp2Writer.h in Headers */ = {isa = PBXBuildFile; fileRef = 436A7F4010FBB24200985348 /* ossimKakaduJp2Writer.h */; };
+		436A7F5C10FBB24200985348 /* ossimKakaduJ2kReader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 436A7F4110FBB24200985348 /* ossimKakaduJ2kReader.cpp */; };
+		436A7F5D10FBB24200985348 /* ossimKakaduCommon.h in Headers */ = {isa = PBXBuildFile; fileRef = 436A7F4210FBB24200985348 /* ossimKakaduCommon.h */; };
+		436A7F5E10FBB24200985348 /* ossimKakaduWriterFactory.h in Headers */ = {isa = PBXBuildFile; fileRef = 436A7F4310FBB24200985348 /* ossimKakaduWriterFactory.h */; };
+		436A7F5F10FBB24200985348 /* ossimKakaduNitfWriter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 436A7F4410FBB24200985348 /* ossimKakaduNitfWriter.cpp */; };
+		436A7F6010FBB24200985348 /* ossimKakaduNitfReader.h in Headers */ = {isa = PBXBuildFile; fileRef = 436A7F4510FBB24200985348 /* ossimKakaduNitfReader.h */; };
+		436A7F6110FBB24200985348 /* ossimKakaduReaderFactory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 436A7F4610FBB24200985348 /* ossimKakaduReaderFactory.cpp */; };
+		436A7F6210FBB24200985348 /* ossimKakaduWriterFactory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 436A7F4710FBB24200985348 /* ossimKakaduWriterFactory.cpp */; };
+		436A7F6310FBB24200985348 /* ossimKakaduPluginInit.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 436A7F4810FBB24200985348 /* ossimKakaduPluginInit.cpp */; };
+		436A7F6410FBB24200985348 /* ossimKakaduJp2Reader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 436A7F4910FBB24200985348 /* ossimKakaduJp2Reader.cpp */; };
+		436A7F6510FBB24200985348 /* ossimKakaduCommon.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 436A7F4A10FBB24200985348 /* ossimKakaduCommon.cpp */; };
+		437184730BCF07BA0002D30E /* Openthreads.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 437184710BCF07BA0002D30E /* Openthreads.framework */; };
+		437185060BCF07E80002D30E /* Openthreads.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 437184710BCF07BA0002D30E /* Openthreads.framework */; };
+		437185160BCF095C0002D30E /* Openthreads.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 437184710BCF07BA0002D30E /* Openthreads.framework */; };
+		437185170BCF09690002D30E /* Openthreads.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 437184710BCF07BA0002D30E /* Openthreads.framework */; };
+		437185290BCF0C750002D30E /* Openthreads.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 437184710BCF07BA0002D30E /* Openthreads.framework */; };
+		437185340BCF0C9C0002D30E /* Openthreads.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 437184710BCF07BA0002D30E /* Openthreads.framework */; };
+		4391B4D9110F6D0400B5895E /* kdu_region_decompressor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4391B4D7110F6D0400B5895E /* kdu_region_decompressor.cpp */; };
+		4391B4DA110F6D0400B5895E /* kdu_region_decompressor.h in Headers */ = {isa = PBXBuildFile; fileRef = 4391B4D8110F6D0400B5895E /* kdu_region_decompressor.h */; };
+		4391B4E8110F715600B5895E /* libkdu_v62R.dylib in Sources */ = {isa = PBXBuildFile; fileRef = 4310BA85110DD2C600C258B9 /* libkdu_v62R.dylib */; };
+		43A9A0A61151AC37000860DA /* Openthreads.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 437184710BCF07BA0002D30E /* Openthreads.framework */; };
+		43A9A0A71151AC37000860DA /* ossim.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 186EF8EA0B1F19E400F7886A /* ossim.framework */; };
+		43A9A1441151ADA8000860DA /* ErsSarDataSetSummary.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 43A9A0E31151ADA7000860DA /* ErsSarDataSetSummary.cpp */; };
+		43A9A1451151ADA8000860DA /* ErsSarDataSetSummary.h in Headers */ = {isa = PBXBuildFile; fileRef = 43A9A0E41151ADA7000860DA /* ErsSarDataSetSummary.h */; };
+		43A9A1461151ADA8000860DA /* ErsSarFacilityData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 43A9A0E51151ADA7000860DA /* ErsSarFacilityData.cpp */; };
+		43A9A1471151ADA8000860DA /* ErsSarFacilityData.h in Headers */ = {isa = PBXBuildFile; fileRef = 43A9A0E61151ADA7000860DA /* ErsSarFacilityData.h */; };
+		43A9A1481151ADA8000860DA /* ErsSarFileDescriptor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 43A9A0E71151ADA7000860DA /* ErsSarFileDescriptor.cpp */; };
+		43A9A1491151ADA8000860DA /* ErsSarFileDescriptor.h in Headers */ = {isa = PBXBuildFile; fileRef = 43A9A0E81151ADA7000860DA /* ErsSarFileDescriptor.h */; };
+		43A9A14A1151ADA8000860DA /* ErsSarLeader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 43A9A0E91151ADA7000860DA /* ErsSarLeader.cpp */; };
+		43A9A14B1151ADA8000860DA /* ErsSarLeader.h in Headers */ = {isa = PBXBuildFile; fileRef = 43A9A0EA1151ADA7000860DA /* ErsSarLeader.h */; };
+		43A9A14C1151ADA8000860DA /* ErsSarLeaderFactory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 43A9A0EB1151ADA7000860DA /* ErsSarLeaderFactory.cpp */; };
+		43A9A14D1151ADA8000860DA /* ErsSarLeaderFactory.h in Headers */ = {isa = PBXBuildFile; fileRef = 43A9A0EC1151ADA7000860DA /* ErsSarLeaderFactory.h */; };
+		43A9A14E1151ADA8000860DA /* ErsSarMapProjectionData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 43A9A0ED1151ADA7000860DA /* ErsSarMapProjectionData.cpp */; };
+		43A9A14F1151ADA8000860DA /* ErsSarMapProjectionData.h in Headers */ = {isa = PBXBuildFile; fileRef = 43A9A0EE1151ADA7000860DA /* ErsSarMapProjectionData.h */; };
+		43A9A1501151ADA8000860DA /* ErsSarPlatformPositionData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 43A9A0EF1151ADA7000860DA /* ErsSarPlatformPositionData.cpp */; };
+		43A9A1511151ADA8000860DA /* ErsSarPlatformPositionData.h in Headers */ = {isa = PBXBuildFile; fileRef = 43A9A0F01151ADA7000860DA /* ErsSarPlatformPositionData.h */; };
+		43A9A1521151ADA8000860DA /* ErsSarPositionVectorRecord.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 43A9A0F11151ADA7000860DA /* ErsSarPositionVectorRecord.cpp */; };
+		43A9A1531151ADA8000860DA /* ErsSarPositionVectorRecord.h in Headers */ = {isa = PBXBuildFile; fileRef = 43A9A0F21151ADA7000860DA /* ErsSarPositionVectorRecord.h */; };
+		43A9A1541151ADA8000860DA /* ErsSarRecord.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 43A9A0F31151ADA7000860DA /* ErsSarRecord.cpp */; };
+		43A9A1551151ADA8000860DA /* ErsSarRecord.h in Headers */ = {isa = PBXBuildFile; fileRef = 43A9A0F41151ADA7000860DA /* ErsSarRecord.h */; };
+		43A9A1561151ADA8000860DA /* ErsSarRecordFactory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 43A9A0F51151ADA7000860DA /* ErsSarRecordFactory.cpp */; };
+		43A9A1571151ADA8000860DA /* ErsSarRecordFactory.h in Headers */ = {isa = PBXBuildFile; fileRef = 43A9A0F61151ADA7000860DA /* ErsSarRecordFactory.h */; };
+		43A9A1581151ADA8000860DA /* ErsSarRecordHeader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 43A9A0F71151ADA7000860DA /* ErsSarRecordHeader.cpp */; };
+		43A9A1591151ADA8000860DA /* ErsSarRecordHeader.h in Headers */ = {isa = PBXBuildFile; fileRef = 43A9A0F81151ADA7000860DA /* ErsSarRecordHeader.h */; };
+		43A9A15A1151ADA8000860DA /* Makefile in Sources */ = {isa = PBXBuildFile; fileRef = 43A9A0F91151ADA7000860DA /* Makefile */; };
+		43A9A15B1151ADA8000860DA /* ossimCosmoSkymedModel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 43A9A0FB1151ADA7000860DA /* ossimCosmoSkymedModel.cpp */; };
+		43A9A15C1151ADA8000860DA /* ossimCosmoSkymedModel.h in Headers */ = {isa = PBXBuildFile; fileRef = 43A9A0FC1151ADA7000860DA /* ossimCosmoSkymedModel.h */; };
+		43A9A15D1151ADA8000860DA /* ossimEnvisatAsarModel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 43A9A0FD1151ADA7000860DA /* ossimEnvisatAsarModel.cpp */; };
+		43A9A15E1151ADA8000860DA /* ossimEnvisatAsarModel.h in Headers */ = {isa = PBXBuildFile; fileRef = 43A9A0FE1151ADA7000860DA /* ossimEnvisatAsarModel.h */; };
+		43A9A15F1151ADA8000860DA /* ossimErsSarModel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 43A9A0FF1151ADA7000860DA /* ossimErsSarModel.cpp */; };
+		43A9A1601151ADA8000860DA /* ossimErsSarModel.h in Headers */ = {isa = PBXBuildFile; fileRef = 43A9A1001151ADA8000860DA /* ossimErsSarModel.h */; };
+		43A9A1611151ADA8000860DA /* ossimGeometricSarSensorModel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 43A9A1011151ADA8000860DA /* ossimGeometricSarSensorModel.cpp */; };
+		43A9A1621151ADA8000860DA /* ossimGeometricSarSensorModel.h in Headers */ = {isa = PBXBuildFile; fileRef = 43A9A1021151ADA8000860DA /* ossimGeometricSarSensorModel.h */; };
+		43A9A1631151ADA8000860DA /* ossimPluginCommon.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 43A9A1031151ADA8000860DA /* ossimPluginCommon.cpp */; };
+		43A9A1641151ADA8000860DA /* ossimPluginCommon.h in Headers */ = {isa = PBXBuildFile; fileRef = 43A9A1041151ADA8000860DA /* ossimPluginCommon.h */; };
+		43A9A1651151ADA8000860DA /* ossimPluginInit.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 43A9A1051151ADA8000860DA /* ossimPluginInit.cpp */; };
+		43A9A1661151ADA8000860DA /* ossimPluginProjectionFactory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 43A9A1061151ADA8000860DA /* ossimPluginProjectionFactory.cpp */; };
+		43A9A1671151ADA8000860DA /* ossimPluginProjectionFactory.h in Headers */ = {isa = PBXBuildFile; fileRef = 43A9A1071151ADA8000860DA /* ossimPluginProjectionFactory.h */; };
+		43A9A1681151ADA8000860DA /* ossimPluginReaderFactory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 43A9A1081151ADA8000860DA /* ossimPluginReaderFactory.cpp */; };
+		43A9A1691151ADA8000860DA /* ossimPluginReaderFactory.h in Headers */ = {isa = PBXBuildFile; fileRef = 43A9A1091151ADA8000860DA /* ossimPluginReaderFactory.h */; };
+		43A9A16A1151ADA8000860DA /* ossimRadarSat2Model.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 43A9A10A1151ADA8000860DA /* ossimRadarSat2Model.cpp */; };
+		43A9A16B1151ADA8000860DA /* ossimRadarSat2Model.h in Headers */ = {isa = PBXBuildFile; fileRef = 43A9A10B1151ADA8000860DA /* ossimRadarSat2Model.h */; };
+		43A9A16C1151ADA8000860DA /* ossimRadarSat2ProductDoc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 43A9A10C1151ADA8000860DA /* ossimRadarSat2ProductDoc.cpp */; };
+		43A9A16D1151ADA8000860DA /* ossimRadarSat2ProductDoc.h in Headers */ = {isa = PBXBuildFile; fileRef = 43A9A10D1151ADA8000860DA /* ossimRadarSat2ProductDoc.h */; };
+		43A9A16E1151ADA8000860DA /* ossimRadarSat2RPCModel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 43A9A10E1151ADA8000860DA /* ossimRadarSat2RPCModel.cpp */; };
+		43A9A16F1151ADA8000860DA /* ossimRadarSat2RPCModel.h in Headers */ = {isa = PBXBuildFile; fileRef = 43A9A10F1151ADA8000860DA /* ossimRadarSat2RPCModel.h */; };
+		43A9A1701151ADA8000860DA /* ossimRadarSatModel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 43A9A1101151ADA8000860DA /* ossimRadarSatModel.cpp */; };
+		43A9A1711151ADA8000860DA /* ossimRadarSatModel.h in Headers */ = {isa = PBXBuildFile; fileRef = 43A9A1111151ADA8000860DA /* ossimRadarSatModel.h */; };
+		43A9A1721151ADA8000860DA /* ossimTerraSarModel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 43A9A1121151ADA8000860DA /* ossimTerraSarModel.cpp */; };
+		43A9A1731151ADA8000860DA /* ossimTerraSarModel.h in Headers */ = {isa = PBXBuildFile; fileRef = 43A9A1131151ADA8000860DA /* ossimTerraSarModel.h */; };
+		43A9A1741151ADA8000860DA /* ossimTerraSarProductDoc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 43A9A1141151ADA8000860DA /* ossimTerraSarProductDoc.cpp */; };
+		43A9A1751151ADA8000860DA /* ossimTerraSarProductDoc.h in Headers */ = {isa = PBXBuildFile; fileRef = 43A9A1151151ADA8000860DA /* ossimTerraSarProductDoc.h */; };
+		43A9A1761151ADA8000860DA /* ossimTerraSarTiffReader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 43A9A1161151ADA8000860DA /* ossimTerraSarTiffReader.cpp */; };
+		43A9A1771151ADA8000860DA /* ossimTerraSarTiffReader.h in Headers */ = {isa = PBXBuildFile; fileRef = 43A9A1171151ADA8000860DA /* ossimTerraSarTiffReader.h */; };
+		43A9A1781151ADA8000860DA /* Arithmetic.h in Headers */ = {isa = PBXBuildFile; fileRef = 43A9A1191151ADA8000860DA /* Arithmetic.h */; };
+		43A9A1791151ADA8000860DA /* CivilDateTime.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 43A9A11A1151ADA8000860DA /* CivilDateTime.cpp */; };
+		43A9A17A1151ADA8000860DA /* CivilDateTime.h in Headers */ = {isa = PBXBuildFile; fileRef = 43A9A11B1151ADA8000860DA /* CivilDateTime.h */; };
+		43A9A17B1151ADA8000860DA /* Coordinate.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 43A9A11C1151ADA8000860DA /* Coordinate.cpp */; };
+		43A9A17C1151ADA8000860DA /* Coordinate.h in Headers */ = {isa = PBXBuildFile; fileRef = 43A9A11D1151ADA8000860DA /* Coordinate.h */; };
+		43A9A17D1151ADA8000860DA /* Ephemeris.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 43A9A11E1151ADA8000860DA /* Ephemeris.cpp */; };
+		43A9A17E1151ADA8000860DA /* Ephemeris.h in Headers */ = {isa = PBXBuildFile; fileRef = 43A9A11F1151ADA8000860DA /* Ephemeris.h */; };
+		43A9A17F1151ADA8000860DA /* Equation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 43A9A1201151ADA8000860DA /* Equation.cpp */; };
+		43A9A1801151ADA8000860DA /* Equation.h in Headers */ = {isa = PBXBuildFile; fileRef = 43A9A1211151ADA8000860DA /* Equation.h */; };
+		43A9A1811151ADA8000860DA /* GalileanEphemeris.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 43A9A1221151ADA8000860DA /* GalileanEphemeris.cpp */; };
+		43A9A1821151ADA8000860DA /* GalileanEphemeris.h in Headers */ = {isa = PBXBuildFile; fileRef = 43A9A1231151ADA8000860DA /* GalileanEphemeris.h */; };
+		43A9A1831151ADA8000860DA /* GeodesicCoordinate.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 43A9A1241151ADA8000860DA /* GeodesicCoordinate.cpp */; };
+		43A9A1841151ADA8000860DA /* GeodesicCoordinate.h in Headers */ = {isa = PBXBuildFile; fileRef = 43A9A1251151ADA8000860DA /* GeodesicCoordinate.h */; };
+		43A9A1851151ADA8000860DA /* GeographicEphemeris.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 43A9A1261151ADA8000860DA /* GeographicEphemeris.cpp */; };
+		43A9A1861151ADA8000860DA /* GeographicEphemeris.h in Headers */ = {isa = PBXBuildFile; fileRef = 43A9A1271151ADA8000860DA /* GeographicEphemeris.h */; };
+		43A9A1871151ADA8000860DA /* GMSTDateTime.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 43A9A1281151ADA8000860DA /* GMSTDateTime.cpp */; };
+		43A9A1881151ADA8000860DA /* GMSTDateTime.h in Headers */ = {isa = PBXBuildFile; fileRef = 43A9A1291151ADA8000860DA /* GMSTDateTime.h */; };
+		43A9A1891151ADA8000860DA /* HermiteInterpolator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 43A9A12A1151ADA8000860DA /* HermiteInterpolator.cpp */; };
+		43A9A18A1151ADA8000860DA /* HermiteInterpolator.h in Headers */ = {isa = PBXBuildFile; fileRef = 43A9A12B1151ADA8000860DA /* HermiteInterpolator.h */; };
+		43A9A18B1151ADA8000860DA /* ImageNoise.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 43A9A12C1151ADA8000860DA /* ImageNoise.cpp */; };
+		43A9A18C1151ADA8000860DA /* ImageNoise.h in Headers */ = {isa = PBXBuildFile; fileRef = 43A9A12D1151ADA8000860DA /* ImageNoise.h */; };
+		43A9A18D1151ADA8000860DA /* JSDDateTime.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 43A9A12E1151ADA8000860DA /* JSDDateTime.cpp */; };
+		43A9A18E1151ADA8000860DA /* JSDDateTime.h in Headers */ = {isa = PBXBuildFile; fileRef = 43A9A12F1151ADA8000860DA /* JSDDateTime.h */; };
+		43A9A18F1151ADA8000860DA /* JulianDate.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 43A9A1301151ADA8000860DA /* JulianDate.cpp */; };
+		43A9A1901151ADA8000860DA /* JulianDate.h in Headers */ = {isa = PBXBuildFile; fileRef = 43A9A1311151ADA8000860DA /* JulianDate.h */; };
+		43A9A1911151ADA8000860DA /* Makefile in Sources */ = {isa = PBXBuildFile; fileRef = 43A9A1321151ADA8000860DA /* Makefile */; };
+		43A9A1921151ADA8000860DA /* MJDDateTime.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 43A9A1341151ADA8000860DA /* MJDDateTime.cpp */; };
+		43A9A1931151ADA8000860DA /* MJDDateTime.h in Headers */ = {isa = PBXBuildFile; fileRef = 43A9A1351151ADA8000860DA /* MJDDateTime.h */; };
+		43A9A1941151ADA8000860DA /* Noise.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 43A9A1361151ADA8000860DA /* Noise.cpp */; };
+		43A9A1951151ADA8000860DA /* Noise.h in Headers */ = {isa = PBXBuildFile; fileRef = 43A9A1371151ADA8000860DA /* Noise.h */; };
+		43A9A1961151ADA8000860DA /* PlatformPosition.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 43A9A1381151ADA8000860DA /* PlatformPosition.cpp */; };
+		43A9A1971151ADA8000860DA /* PlatformPosition.h in Headers */ = {isa = PBXBuildFile; fileRef = 43A9A1391151ADA8000860DA /* PlatformPosition.h */; };
+		43A9A1981151ADA8000860DA /* RectangularCoordinate.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 43A9A13A1151ADA8000860DA /* RectangularCoordinate.cpp */; };
+		43A9A1991151ADA8000860DA /* RectangularCoordinate.h in Headers */ = {isa = PBXBuildFile; fileRef = 43A9A13B1151ADA8000860DA /* RectangularCoordinate.h */; };
+		43A9A19A1151ADA8000860DA /* RefPoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 43A9A13C1151ADA8000860DA /* RefPoint.cpp */; };
+		43A9A19B1151ADA8000860DA /* RefPoint.h in Headers */ = {isa = PBXBuildFile; fileRef = 43A9A13D1151ADA8000860DA /* RefPoint.h */; };
+		43A9A19C1151ADA8000860DA /* SarSensor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 43A9A13E1151ADA8000860DA /* SarSensor.cpp */; };
+		43A9A19D1151ADA8000860DA /* SarSensor.h in Headers */ = {isa = PBXBuildFile; fileRef = 43A9A13F1151ADA8000860DA /* SarSensor.h */; };
+		43A9A19E1151ADA8000860DA /* Sensor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 43A9A1401151ADA8000860DA /* Sensor.cpp */; };
+		43A9A19F1151ADA8000860DA /* Sensor.h in Headers */ = {isa = PBXBuildFile; fileRef = 43A9A1411151ADA8000860DA /* Sensor.h */; };
+		43A9A1A01151ADA8000860DA /* SensorParams.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 43A9A1421151ADA8000860DA /* SensorParams.cpp */; };
+		43A9A1A11151ADA8000860DA /* SensorParams.h in Headers */ = {isa = PBXBuildFile; fileRef = 43A9A1431151ADA8000860DA /* SensorParams.h */; };
+		EE69A38E0B28854C00C91DD1 /* wms.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EE69A3850B28850A00C91DD1 /* wms.framework */; };
+		EEA3C4A50E3FA61C00CAAC1A /* ossimEsriShapeFileFilter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EEA3C47C0E3FA61B00CAAC1A /* ossimEsriShapeFileFilter.cpp */; };
+		EEA3C4A60E3FA61C00CAAC1A /* ossimEsriShapeFileFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = EEA3C47D0E3FA61B00CAAC1A /* ossimEsriShapeFileFilter.h */; };
+		EEA3C4A70E3FA61C00CAAC1A /* ossimGdalDataset.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EEA3C47E0E3FA61B00CAAC1A /* ossimGdalDataset.cpp */; };
+		EEA3C4A80E3FA61C00CAAC1A /* ossimGdalDataset.h in Headers */ = {isa = PBXBuildFile; fileRef = EEA3C47F0E3FA61B00CAAC1A /* ossimGdalDataset.h */; };
+		EEA3C4A90E3FA61C00CAAC1A /* ossimGdalFactory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EEA3C4800E3FA61B00CAAC1A /* ossimGdalFactory.cpp */; };
+		EEA3C4AA0E3FA61C00CAAC1A /* ossimGdalFactory.h in Headers */ = {isa = PBXBuildFile; fileRef = EEA3C4810E3FA61B00CAAC1A /* ossimGdalFactory.h */; };
+		EEA3C4AB0E3FA61C00CAAC1A /* ossimGdalImageWriterFactory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EEA3C4820E3FA61B00CAAC1A /* ossimGdalImageWriterFactory.cpp */; };
+		EEA3C4AC0E3FA61C00CAAC1A /* ossimGdalImageWriterFactory.h in Headers */ = {isa = PBXBuildFile; fileRef = EEA3C4830E3FA61B00CAAC1A /* ossimGdalImageWriterFactory.h */; };
+		EEA3C4AD0E3FA61C00CAAC1A /* ossimGdalObjectFactory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EEA3C4840E3FA61B00CAAC1A /* ossimGdalObjectFactory.cpp */; };
+		EEA3C4AE0E3FA61C00CAAC1A /* ossimGdalObjectFactory.h in Headers */ = {isa = PBXBuildFile; fileRef = EEA3C4850E3FA61B00CAAC1A /* ossimGdalObjectFactory.h */; };
+		EEA3C4AF0E3FA61C00CAAC1A /* ossimGdalOgrVectorAnnotation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EEA3C4860E3FA61B00CAAC1A /* ossimGdalOgrVectorAnnotation.cpp */; };
+		EEA3C4B00E3FA61C00CAAC1A /* ossimGdalOgrVectorAnnotation.h in Headers */ = {isa = PBXBuildFile; fileRef = EEA3C4880E3FA61B00CAAC1A /* ossimGdalOgrVectorAnnotation.h */; };
+		EEA3C4B10E3FA61C00CAAC1A /* ossimGdalOverviewBuilder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EEA3C4890E3FA61B00CAAC1A /* ossimGdalOverviewBuilder.cpp */; };
+		EEA3C4B20E3FA61C00CAAC1A /* ossimGdalOverviewBuilder.h in Headers */ = {isa = PBXBuildFile; fileRef = EEA3C48A0E3FA61B00CAAC1A /* ossimGdalOverviewBuilder.h */; };
+		EEA3C4B30E3FA61C00CAAC1A /* ossimGdalOverviewBuilderFactory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EEA3C48B0E3FA61B00CAAC1A /* ossimGdalOverviewBuilderFactory.cpp */; };
+		EEA3C4B40E3FA61C00CAAC1A /* ossimGdalOverviewBuilderFactory.h in Headers */ = {isa = PBXBuildFile; fileRef = EEA3C48C0E3FA61B00CAAC1A /* ossimGdalOverviewBuilderFactory.h */; };
+		EEA3C4B50E3FA61C00CAAC1A /* ossimGdalPluginInit.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EEA3C48D0E3FA61B00CAAC1A /* ossimGdalPluginInit.cpp */; };
+		EEA3C4B60E3FA61C00CAAC1A /* ossimGdalProjectionFactory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EEA3C48E0E3FA61B00CAAC1A /* ossimGdalProjectionFactory.cpp */; };
+		EEA3C4B70E3FA61C00CAAC1A /* ossimGdalProjectionFactory.h in Headers */ = {isa = PBXBuildFile; fileRef = EEA3C4900E3FA61B00CAAC1A /* ossimGdalProjectionFactory.h */; };
+		EEA3C4B80E3FA61C00CAAC1A /* ossimGdalTiledDataset.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EEA3C4910E3FA61B00CAAC1A /* ossimGdalTiledDataset.cpp */; };
+		EEA3C4B90E3FA61C00CAAC1A /* ossimGdalTiledDataset.h in Headers */ = {isa = PBXBuildFile; fileRef = EEA3C4920E3FA61B00CAAC1A /* ossimGdalTiledDataset.h */; };
+		EEA3C4BA0E3FA61C00CAAC1A /* ossimGdalTileSource.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EEA3C4930E3FA61B00CAAC1A /* ossimGdalTileSource.cpp */; };
+		EEA3C4BB0E3FA61C00CAAC1A /* ossimGdalTileSource.h in Headers */ = {isa = PBXBuildFile; fileRef = EEA3C4950E3FA61B00CAAC1A /* ossimGdalTileSource.h */; };
+		EEA3C4BC0E3FA61C00CAAC1A /* ossimGdalType.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EEA3C4970E3FA61B00CAAC1A /* ossimGdalType.cpp */; };
+		EEA3C4BD0E3FA61C00CAAC1A /* ossimGdalType.h in Headers */ = {isa = PBXBuildFile; fileRef = EEA3C4980E3FA61B00CAAC1A /* ossimGdalType.h */; };
+		EEA3C4BE0E3FA61C00CAAC1A /* ossimGdalWriter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EEA3C4990E3FA61B00CAAC1A /* ossimGdalWriter.cpp */; };
+		EEA3C4BF0E3FA61C00CAAC1A /* ossimGdalWriter.h in Headers */ = {isa = PBXBuildFile; fileRef = EEA3C49A0E3FA61B00CAAC1A /* ossimGdalWriter.h */; };
+		EEA3C4C00E3FA61C00CAAC1A /* ossimOgcWktTranslator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EEA3C49B0E3FA61C00CAAC1A /* ossimOgcWktTranslator.cpp */; };
+		EEA3C4C10E3FA61C00CAAC1A /* ossimOgcWktTranslator.h in Headers */ = {isa = PBXBuildFile; fileRef = EEA3C49D0E3FA61C00CAAC1A /* ossimOgcWktTranslator.h */; };
+		EEA3C4C20E3FA61C00CAAC1A /* ossimOgrGdalTileSource.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EEA3C49E0E3FA61C00CAAC1A /* ossimOgrGdalTileSource.cpp */; };
+		EEA3C4C30E3FA61C00CAAC1A /* ossimOgrGdalTileSource.h in Headers */ = {isa = PBXBuildFile; fileRef = EEA3C49F0E3FA61C00CAAC1A /* ossimOgrGdalTileSource.h */; };
+		EEA3C4C40E3FA61C00CAAC1A /* ossimShapeDatabase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EEA3C4A00E3FA61C00CAAC1A /* ossimShapeDatabase.cpp */; };
+		EEA3C4C50E3FA61C00CAAC1A /* ossimShapeDatabase.h in Headers */ = {isa = PBXBuildFile; fileRef = EEA3C4A10E3FA61C00CAAC1A /* ossimShapeDatabase.h */; };
+		EEA3C4C60E3FA61C00CAAC1A /* ossimShapeFile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EEA3C4A20E3FA61C00CAAC1A /* ossimShapeFile.cpp */; };
+		EEA3C4C70E3FA61C00CAAC1A /* ossimShapeFile.h in Headers */ = {isa = PBXBuildFile; fileRef = EEA3C4A30E3FA61C00CAAC1A /* ossimShapeFile.h */; };
+		EEA3C4C80E3FA61C00CAAC1A /* shapefil.h in Headers */ = {isa = PBXBuildFile; fileRef = EEA3C4A40E3FA61C00CAAC1A /* shapefil.h */; };
+		EEA720230B2F4256006E37B7 /* ossim.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 186EF8EA0B1F19E400F7886A /* ossim.framework */; };
+		EEA720C70B2F4331006E37B7 /* ossimContribImageSourceFactory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EEA720BD0B2F4331006E37B7 /* ossimContribImageSourceFactory.cpp */; };
+		EEA720C80B2F4331006E37B7 /* ossimContribPluginInit.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EEA720BE0B2F4331006E37B7 /* ossimContribPluginInit.cpp */; };
+		EEA720C90B2F4331006E37B7 /* ossimCFARFilter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EEA720BF0B2F4331006E37B7 /* ossimCFARFilter.cpp */; };
+		EEA720CA0B2F4331006E37B7 /* ossimContribImageSourceFactory.h in Headers */ = {isa = PBXBuildFile; fileRef = EEA720C00B2F4331006E37B7 /* ossimContribImageSourceFactory.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		EEA720CB0B2F4331006E37B7 /* ossimSPOTNatural.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EEA720C10B2F4331006E37B7 /* ossimSPOTNatural.cpp */; };
+		EEA720CC0B2F4331006E37B7 /* ossimSPOTNatural.h in Headers */ = {isa = PBXBuildFile; fileRef = EEA720C20B2F4331006E37B7 /* ossimSPOTNatural.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		EEA720CD0B2F4331006E37B7 /* ossimComplexAbs.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EEA720C30B2F4331006E37B7 /* ossimComplexAbs.cpp */; };
+		EEA720CE0B2F4331006E37B7 /* ossimComplexAbs.h in Headers */ = {isa = PBXBuildFile; fileRef = EEA720C40B2F4331006E37B7 /* ossimComplexAbs.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		EEA720CF0B2F4331006E37B7 /* ossimContribExports.h in Headers */ = {isa = PBXBuildFile; fileRef = EEA720C50B2F4331006E37B7 /* ossimContribExports.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		EEA720D00B2F4331006E37B7 /* ossimCFARFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = EEA720C60B2F4331006E37B7 /* ossimCFARFilter.h */; settings = {ATTRIBUTES = (Public, ); }; };
+/* End PBXBuildFile section */
+
+/* Begin PBXContainerItemProxy section */
+		186EF8E90B1F19E400F7886A /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 186EF8AA0B1F19E400F7886A /* ossim.xcodeproj */;
+			proxyType = 2;
+			remoteGlobalIDString = 8D07F2C80486CC7A007CD1D0;
+			remoteInfo = ossim;
+		};
+		430EAEE40C6A4E8800E6661B /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = EE69A3800B28850A00C91DD1 /* libwms.xcodeproj */;
+			proxyType = 1;
+			remoteGlobalIDString = 8DC2EF4F0486A6940098B216;
+			remoteInfo = wms;
+		};
+		4310BB18110DD99B00C258B9 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 186EF84C0B1F0A5000F7886A /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = 431320FC103C84DF00F96FDF;
+			remoteInfo = ossimkakadu_plugin;
+		};
+		43333CC010FD00CD00A5B432 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 186EF84C0B1F0A5000F7886A /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = 436A7E1410FB9FC400985348;
+			remoteInfo = ossimmrsid_plugin;
+		};
+		43378DC710D0220100ECC5AD /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 186EF84C0B1F0A5000F7886A /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = 186EF86C0B1F184C00F7886A;
+			remoteInfo = ossimgdal_plugin;
+		};
+		43378DC910D0220100ECC5AD /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 186EF84C0B1F0A5000F7886A /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = 186EF9810B1F222500F7886A;
+			remoteInfo = ossimreg_plugin;
+		};
+		43378DCB10D0220100ECC5AD /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 186EF84C0B1F0A5000F7886A /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = 186EFA1B0B1F321200F7886A;
+			remoteInfo = ossimworldwind_plugin;
+		};
+		43378DCD10D0220100ECC5AD /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 186EF84C0B1F0A5000F7886A /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = 186EFA5E0B1F394100F7886A;
+			remoteInfo = ossimnui_plugin;
+		};
+		43378DCF10D0220100ECC5AD /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 186EF84C0B1F0A5000F7886A /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = 430D1FCD0BB2F96B0057E5FF;
+			remoteInfo = ossimpng_plugin;
+		};
+		43378DD110D0220100ECC5AD /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 186EF84C0B1F0A5000F7886A /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = 43377EF410CFFAC900ECC5AD;
+			remoteInfo = ossimcsm_plugin;
+		};
+		4353102810440474004A4474 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 186EF8AA0B1F19E400F7886A /* ossim.xcodeproj */;
+			proxyType = 2;
+			remoteGlobalIDString = 433628031042E368002A87C7;
+			remoteInfo = "template-app";
+		};
+		4353102A10440474004A4474 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 186EF8AA0B1F19E400F7886A /* ossim.xcodeproj */;
+			proxyType = 2;
+			remoteGlobalIDString = 433628151042E3B0002A87C7;
+			remoteInfo = "ossim-adrg-dump";
+		};
+		4353102C10440474004A4474 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 186EF8AA0B1F19E400F7886A /* ossim.xcodeproj */;
+			proxyType = 2;
+			remoteGlobalIDString = 433628371042E3F6002A87C7;
+			remoteInfo = "ossim-applanix2ogeom";
+		};
+		4353102E10440474004A4474 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 186EF8AA0B1F19E400F7886A /* ossim.xcodeproj */;
+			proxyType = 2;
+			remoteGlobalIDString = 433628551042E461002A87C7;
+			remoteInfo = "ossim-band-merge";
+		};
+		4353103010440474004A4474 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 186EF8AA0B1F19E400F7886A /* ossim.xcodeproj */;
+			proxyType = 2;
+			remoteGlobalIDString = 433628741042E4AC002A87C7;
+			remoteInfo = "ossim-btoa";
+		};
+		4353103210440474004A4474 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 186EF8AA0B1F19E400F7886A /* ossim.xcodeproj */;
+			proxyType = 2;
+			remoteGlobalIDString = 433628861042E4D1002A87C7;
+			remoteInfo = "ossim-chgkwval";
+		};
+		4353103410440474004A4474 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 186EF8AA0B1F19E400F7886A /* ossim.xcodeproj */;
+			proxyType = 2;
+			remoteGlobalIDString = 4336289F1042E52A002A87C7;
+			remoteInfo = "ossim-cmm";
+		};
+		4353103610440474004A4474 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 186EF8AA0B1F19E400F7886A /* ossim.xcodeproj */;
+			proxyType = 2;
+			remoteGlobalIDString = 433628B91042E560002A87C7;
+			remoteInfo = "ossim-computeSrtmStats";
+		};
+		4353103810440474004A4474 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 186EF8AA0B1F19E400F7886A /* ossim.xcodeproj */;
+			proxyType = 2;
+			remoteGlobalIDString = 433628D61042E59C002A87C7;
+			remoteInfo = "ossim-correl";
+		};
+		4353103A10440474004A4474 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 186EF8AA0B1F19E400F7886A /* ossim.xcodeproj */;
+			proxyType = 2;
+			remoteGlobalIDString = 433628F11042E5D1002A87C7;
+			remoteInfo = "ossim-create-cg";
+		};
+		4353103C10440474004A4474 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 186EF8AA0B1F19E400F7886A /* ossim.xcodeproj */;
+			proxyType = 2;
+			remoteGlobalIDString = 4336290B1042E607002A87C7;
+			remoteInfo = "ossim-create-histo";
+		};
+		4353104410440474004A4474 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 186EF8AA0B1F19E400F7886A /* ossim.xcodeproj */;
+			proxyType = 2;
+			remoteGlobalIDString = 433629811042E712002A87C7;
+			remoteInfo = "ossim-dms2deg";
+		};
+		4353104610440474004A4474 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 186EF8AA0B1F19E400F7886A /* ossim.xcodeproj */;
+			proxyType = 2;
+			remoteGlobalIDString = 4336299D1042E759002A87C7;
+			remoteInfo = "ossim-dump-ocg";
+		};
+		4353104810440474004A4474 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 186EF8AA0B1F19E400F7886A /* ossim.xcodeproj */;
+			proxyType = 2;
+			remoteGlobalIDString = 433629B51042E77C002A87C7;
+			remoteInfo = "ossim-ecg2ocg";
+		};
+		4353104A10440474004A4474 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 186EF8AA0B1F19E400F7886A /* ossim.xcodeproj */;
+			proxyType = 2;
+			remoteGlobalIDString = 433629D01042E7B1002A87C7;
+			remoteInfo = "ossim-extract-vertices";
+		};
+		4353104C10440474004A4474 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 186EF8AA0B1F19E400F7886A /* ossim.xcodeproj */;
+			proxyType = 2;
+			remoteGlobalIDString = 433629E41042E807002A87C7;
+			remoteInfo = "ossim-foo";
+		};
+		4353105010440474004A4474 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 186EF8AA0B1F19E400F7886A /* ossim.xcodeproj */;
+			proxyType = 2;
+			remoteGlobalIDString = 43362A2D1042E88F002A87C7;
+			remoteInfo = "ossim-height";
+		};
+		4353105210440474004A4474 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 186EF8AA0B1F19E400F7886A /* ossim.xcodeproj */;
+			proxyType = 2;
+			remoteGlobalIDString = 43362A4B1042E8BD002A87C7;
+			remoteInfo = "ossim-icp";
+		};
+		4353105410440474004A4474 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 186EF8AA0B1F19E400F7886A /* ossim.xcodeproj */;
+			proxyType = 2;
+			remoteGlobalIDString = 43362A631042E8EE002A87C7;
+			remoteInfo = "ossim-igen";
+		};
+		4353105610440474004A4474 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 186EF8AA0B1F19E400F7886A /* ossim.xcodeproj */;
+			proxyType = 2;
+			remoteGlobalIDString = 43362A7D1042E914002A87C7;
+			remoteInfo = "ossim-img2md";
+		};
+		4353105810440474004A4474 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 186EF8AA0B1F19E400F7886A /* ossim.xcodeproj */;
+			proxyType = 2;
+			remoteGlobalIDString = 43362A9A1042E955002A87C7;
+			remoteInfo = "ossim-img2rr";
+		};
+		4353105A10440474004A4474 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 186EF8AA0B1F19E400F7886A /* ossim.xcodeproj */;
+			proxyType = 2;
+			remoteGlobalIDString = 43362AB41042E981002A87C7;
+			remoteInfo = "ossim-info";
+		};
+		4353105C10440474004A4474 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 186EF8AA0B1F19E400F7886A /* ossim.xcodeproj */;
+			proxyType = 2;
+			remoteGlobalIDString = 43362AD21042EA43002A87C7;
+			remoteInfo = "ossim-modopt";
+		};
+		4353105E10440474004A4474 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 186EF8AA0B1F19E400F7886A /* ossim.xcodeproj */;
+			proxyType = 2;
+			remoteGlobalIDString = 43362AEF1042EA81002A87C7;
+			remoteInfo = "ossim-mosaic";
+		};
+		4353106410440474004A4474 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 186EF8AA0B1F19E400F7886A /* ossim.xcodeproj */;
+			proxyType = 2;
+			remoteGlobalIDString = 43362B471042EB45002A87C7;
+			remoteInfo = "ossim-ogeom2ogeom";
+		};
+		4353106610440474004A4474 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 186EF8AA0B1F19E400F7886A /* ossim.xcodeproj */;
+			proxyType = 2;
+			remoteGlobalIDString = 43362B641042EB70002A87C7;
+			remoteInfo = "ossim-orthoigen";
+		};
+		4353106810440474004A4474 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 186EF8AA0B1F19E400F7886A /* ossim.xcodeproj */;
+			proxyType = 2;
+			remoteGlobalIDString = 43362B801042EB9B002A87C7;
+			remoteInfo = "ossim-pixelflip";
+		};
+		4353106A10440474004A4474 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 186EF8AA0B1F19E400F7886A /* ossim.xcodeproj */;
+			proxyType = 2;
+			remoteGlobalIDString = 43362B9B1042EBCE002A87C7;
+			remoteInfo = "ossim-prune";
+		};
+		4353106E10440474004A4474 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 186EF8AA0B1F19E400F7886A /* ossim.xcodeproj */;
+			proxyType = 2;
+			remoteGlobalIDString = 43362BD21042EC26002A87C7;
+			remoteInfo = "ossim-rejout";
+		};
+		4353107010440474004A4474 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 186EF8AA0B1F19E400F7886A /* ossim.xcodeproj */;
+			proxyType = 2;
+			remoteGlobalIDString = 43362BEE1042EC50002A87C7;
+			remoteInfo = "ossim-senint";
+		};
+		4353107210440474004A4474 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 186EF8AA0B1F19E400F7886A /* ossim.xcodeproj */;
+			proxyType = 2;
+			remoteGlobalIDString = 43362C081042EC80002A87C7;
+			remoteInfo = "ossim-space-imaging";
+		};
+		4353107410440474004A4474 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 186EF8AA0B1F19E400F7886A /* ossim.xcodeproj */;
+			proxyType = 2;
+			remoteGlobalIDString = 43362C221042ECAF002A87C7;
+			remoteInfo = "ossim-swapbytes";
+		};
+		4353107610440474004A4474 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 186EF8AA0B1F19E400F7886A /* ossim.xcodeproj */;
+			proxyType = 2;
+			remoteGlobalIDString = 43362C3C1042ECD6002A87C7;
+			remoteInfo = "ossim-tfw2ogeom";
+		};
+		43A9A1A41151AE4E000860DA /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 186EF84C0B1F0A5000F7886A /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = 43A9A0991151AC37000860DA /* ossim_plugin */;
+			remoteInfo = ossim_plugin;
+		};
+		43F4581910FCDAFA002B9133 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 186EF84C0B1F0A5000F7886A /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = 436A7E1410FB9FC400985348;
+			remoteInfo = ossimmrsid_plugin;
+		};
+		EE69A3840B28850A00C91DD1 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = EE69A3800B28850A00C91DD1 /* libwms.xcodeproj */;
+			proxyType = 2;
+			remoteGlobalIDString = 8DC2EF5B0486A6940098B216;
+			remoteInfo = wms;
+		};
+		EEB7D1530E77F4DD007DA09C /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = EE69A3800B28850A00C91DD1 /* libwms.xcodeproj */;
+			proxyType = 2;
+			remoteGlobalIDString = 1FD5B7C80E75D3DC00FBD730;
+			remoteInfo = wmsurl;
+		};
+		EEB7D1550E77F4DD007DA09C /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = EE69A3800B28850A00C91DD1 /* libwms.xcodeproj */;
+			proxyType = 2;
+			remoteGlobalIDString = 1FD5B7EA0E75D46700FBD730;
+			remoteInfo = wmscapabilities.cpp;
+		};
+		EEB7D1570E77F4DD007DA09C /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = EE69A3800B28850A00C91DD1 /* libwms.xcodeproj */;
+			proxyType = 2;
+			remoteGlobalIDString = 1FD5B7FE0E75D4C500FBD730;
+			remoteInfo = wmsgetmap;
+		};
+/* End PBXContainerItemProxy section */
+
+/* Begin PBXFileReference section */
+		186EF8550B1F0A7200F7886A /* common_settings.xcconfig */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.xcconfig; name = common_settings.xcconfig; path = ../../ossim/xcode/ossim/common_settings.xcconfig; sourceTree = SOURCE_ROOT; };
+		186EF86D0B1F184C00F7886A /* libossimgdal_plugin.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libossimgdal_plugin.dylib; sourceTree = BUILT_PRODUCTS_DIR; };
+		186EF8AA0B1F19E400F7886A /* ossim.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = ossim.xcodeproj; path = ../../ossim/xcode/ossim/ossim.xcodeproj; sourceTree = SOURCE_ROOT; };
+		186EF9820B1F222500F7886A /* libossimreg_plugin.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libossimreg_plugin.dylib; sourceTree = BUILT_PRODUCTS_DIR; };
+		186EF98C0B1F236800F7886A /* ossimChipMatch.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ossimChipMatch.cpp; sourceTree = "<group>"; };
+		186EF98D0B1F236800F7886A /* ossimChipMatch.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimChipMatch.h; sourceTree = "<group>"; };
+		186EF98E0B1F236800F7886A /* ossimDensityReducer.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ossimDensityReducer.cpp; sourceTree = "<group>"; };
+		186EF98F0B1F236800F7886A /* ossimDensityReducer.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimDensityReducer.h; sourceTree = "<group>"; };
+		186EF9900B1F236800F7886A /* ossimExtremaFilter.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ossimExtremaFilter.cpp; sourceTree = "<group>"; };
+		186EF9910B1F236800F7886A /* ossimExtremaFilter.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimExtremaFilter.h; sourceTree = "<group>"; };
+		186EF9920B1F236800F7886A /* ossimHarrisCorners.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ossimHarrisCorners.cpp; sourceTree = "<group>"; };
+		186EF9930B1F236800F7886A /* ossimHarrisCorners.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimHarrisCorners.h; sourceTree = "<group>"; };
+		186EF9940B1F236800F7886A /* ossimImageCorrelator.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ossimImageCorrelator.cpp; sourceTree = "<group>"; };
+		186EF9950B1F236800F7886A /* ossimImageCorrelator.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimImageCorrelator.h; sourceTree = "<group>"; };
+		186EF9960B1F236800F7886A /* ossimModelOptimizer.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ossimModelOptimizer.cpp; sourceTree = "<group>"; };
+		186EF9970B1F236800F7886A /* ossimModelOptimizer.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimModelOptimizer.h; sourceTree = "<group>"; };
+		186EF9980B1F236800F7886A /* ossimMultiplier.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ossimMultiplier.cpp; sourceTree = "<group>"; };
+		186EF9990B1F236800F7886A /* ossimMultiplier.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimMultiplier.h; sourceTree = "<group>"; };
+		186EF99A0B1F236800F7886A /* ossimNCC_FFTW.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ossimNCC_FFTW.cpp; sourceTree = "<group>"; };
+		186EF99B0B1F236800F7886A /* ossimNCC_FFTW.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimNCC_FFTW.h; sourceTree = "<group>"; };
+		186EF99C0B1F236800F7886A /* ossimOutlierRejection.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ossimOutlierRejection.cpp; sourceTree = "<group>"; };
+		186EF99D0B1F236800F7886A /* ossimOutlierRejection.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimOutlierRejection.h; sourceTree = "<group>"; };
+		186EF99E0B1F236800F7886A /* ossimRegistrationExports.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimRegistrationExports.h; sourceTree = "<group>"; };
+		186EF99F0B1F236800F7886A /* ossimRegistrationImageSourceFactory.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ossimRegistrationImageSourceFactory.cpp; sourceTree = "<group>"; };
+		186EF9A00B1F236800F7886A /* ossimRegistrationImageSourceFactory.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimRegistrationImageSourceFactory.h; sourceTree = "<group>"; };
+		186EF9A10B1F236800F7886A /* ossimRegistrationMiscFactory.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ossimRegistrationMiscFactory.cpp; sourceTree = "<group>"; };
+		186EF9A20B1F236800F7886A /* ossimRegistrationMiscFactory.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimRegistrationMiscFactory.h; sourceTree = "<group>"; };
+		186EF9A30B1F236800F7886A /* ossimRegistrationPluginInit.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ossimRegistrationPluginInit.cpp; sourceTree = "<group>"; };
+		186EF9A40B1F236800F7886A /* ossimRunningSum.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ossimRunningSum.cpp; sourceTree = "<group>"; };
+		186EF9A50B1F236800F7886A /* ossimRunningSum.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimRunningSum.h; sourceTree = "<group>"; };
+		186EF9A60B1F236800F7886A /* ossimSquareFunction.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ossimSquareFunction.cpp; sourceTree = "<group>"; };
+		186EF9A70B1F236800F7886A /* ossimSquareFunction.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimSquareFunction.h; sourceTree = "<group>"; };
+		186EF9A80B1F236800F7886A /* ossimTieGenerator.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ossimTieGenerator.cpp; sourceTree = "<group>"; };
+		186EF9A90B1F236800F7886A /* ossimTieGenerator.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimTieGenerator.h; sourceTree = "<group>"; };
+		186EFA1C0B1F321200F7886A /* libossimworldwind_plugin.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libossimworldwind_plugin.dylib; sourceTree = BUILT_PRODUCTS_DIR; };
+		186EFA260B1F32FF00F7886A /* ossimDiskCache.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ossimDiskCache.cpp; sourceTree = "<group>"; };
+		186EFA270B1F32FF00F7886A /* ossimDiskCache.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimDiskCache.h; sourceTree = "<group>"; };
+		186EFA280B1F32FF00F7886A /* ossimSharedDiskCacheManager.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ossimSharedDiskCacheManager.cpp; sourceTree = "<group>"; };
+		186EFA290B1F32FF00F7886A /* ossimSharedDiskCacheManager.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimSharedDiskCacheManager.h; sourceTree = "<group>"; };
+		186EFA2A0B1F32FF00F7886A /* ossimworldwind_plugin.vcproj */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.xml; path = ossimworldwind_plugin.vcproj; sourceTree = "<group>"; };
+		186EFA2B0B1F32FF00F7886A /* ossimWorldWindExports.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimWorldWindExports.h; sourceTree = "<group>"; };
+		186EFA2C0B1F32FF00F7886A /* ossimWorldWindFactory.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ossimWorldWindFactory.cpp; sourceTree = "<group>"; };
+		186EFA2D0B1F32FF00F7886A /* ossimWorldWindFactory.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimWorldWindFactory.h; sourceTree = "<group>"; };
+		186EFA2E0B1F32FF00F7886A /* ossimWorldWindHandler.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ossimWorldWindHandler.cpp; sourceTree = "<group>"; };
+		186EFA2F0B1F32FF00F7886A /* ossimWorldWindHandler.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimWorldWindHandler.h; sourceTree = "<group>"; };
+		186EFA300B1F32FF00F7886A /* ossimWorldWindJpegImage.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ossimWorldWindJpegImage.cpp; sourceTree = "<group>"; };
+		186EFA310B1F32FF00F7886A /* ossimWorldWindJpegImage.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ossimWorldWindJpegImage.h; sourceTree = "<group>"; };
+		186EFA320B1F32FF00F7886A /* ossimWorldWindPluginInit.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ossimWorldWindPluginInit.cpp; sourceTree = "<group>"; };
+		186EFA5F0B1F394100F7886A /* libossimnui_plugin.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libossimnui_plugin.dylib; sourceTree = BUILT_PRODUCTS_DIR; };
+		186EFA670B1F39FD00F7886A /* ossimNuiPluginInit.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = ossimNuiPluginInit.cpp; path = ../nui/ossimNuiPluginInit.cpp; sourceTree = SOURCE_ROOT; };
+		186EFA680B1F39FD00F7886A /* ossimNuiHandler.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = ossimNuiHandler.h; path = ../nui/ossimNuiHandler.h; sourceTree = SOURCE_ROOT; };
+		186EFA690B1F39FD00F7886A /* ossimNuiHandler.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = ossimNuiHandler.cpp; path = ../nui/ossimNuiHandler.cpp; sourceTree = SOURCE_ROOT; };
+		186EFA6A0B1F39FD00F7886A /* ossimNuiFactory.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = ossimNuiFactory.h; path = ../nui/ossimNuiFactory.h; sourceTree = SOURCE_ROOT; };
+		186EFA6B0B1F39FD00F7886A /* ossimNuiFactory.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = ossimNuiFactory.cpp; path = ../nui/ossimNuiFactory.cpp; sourceTree = SOURCE_ROOT; };
+		186EFA6C0B1F39FD00F7886A /* ossimNuiExports.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = ossimNuiExports.h; path = ../nui/ossimNuiExports.h; sourceTree = SOURCE_ROOT; };
+		430D1FE10BB2F96B0057E5FF /* libossimpng_plugin.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libossimpng_plugin.dylib; sourceTree = BUILT_PRODUCTS_DIR; };
+		430D207A0BB2FA450057E5FF /* ossimPngReaderFactory.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = ossimPngReaderFactory.h; path = ../png/ossimPngReaderFactory.h; sourceTree = SOURCE_ROOT; };
+		430D207B0BB2FA450057E5FF /* ossimPngWriterFactory.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = ossimPngWriterFactory.h; path = ../png/ossimPngWriterFactory.h; sourceTree = SOURCE_ROOT; };
+		430D207C0BB2FA450057E5FF /* ossimPngWriterFactory.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = ossimPngWriterFactory.cpp; path = ../png/ossimPngWriterFactory.cpp; sourceTree = SOURCE_ROOT; };
+		430D207D0BB2FA450057E5FF /* ossimPngPluginInit.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = ossimPngPluginInit.cpp; path = ../png/ossimPngPluginInit.cpp; sourceTree = SOURCE_ROOT; };
+		430D207E0BB2FA450057E5FF /* ossimPngReaderFactory.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = ossimPngReaderFactory.cpp; path = ../png/ossimPngReaderFactory.cpp; sourceTree = SOURCE_ROOT; };
+		430D207F0BB2FA450057E5FF /* ossimPngWriter.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = ossimPngWriter.cpp; path = ../png/ossimPngWriter.cpp; sourceTree = SOURCE_ROOT; };
+		430D20800BB2FA450057E5FF /* ossimPngWriter.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = ossimPngWriter.h; path = ../png/ossimPngWriter.h; sourceTree = SOURCE_ROOT; };
+		430D20810BB2FA450057E5FF /* ossimPngReader.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = ossimPngReader.cpp; path = ../png/ossimPngReader.cpp; sourceTree = SOURCE_ROOT; };
+		430D20820BB2FA450057E5FF /* ossimPngReader.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = ossimPngReader.h; path = ../png/ossimPngReader.h; sourceTree = SOURCE_ROOT; };
+		4310BA70110DD27C00C258B9 /* jp2_local.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = jp2_local.h; path = "../../ossim_dependencies/kakadu/v6_2_1-00315N/apps/jp2/jp2_local.h"; sourceTree = SOURCE_ROOT; };
+		4310BA71110DD27C00C258B9 /* jp2_shared.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = jp2_shared.h; path = "../../ossim_dependencies/kakadu/v6_2_1-00315N/apps/jp2/jp2_shared.h"; sourceTree = SOURCE_ROOT; };
+		4310BA72110DD27C00C258B9 /* jp2.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = jp2.cpp; path = "../../ossim_dependencies/kakadu/v6_2_1-00315N/apps/jp2/jp2.cpp"; sourceTree = SOURCE_ROOT; };
+		4310BA73110DD27C00C258B9 /* jpx_local.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = jpx_local.h; path = "../../ossim_dependencies/kakadu/v6_2_1-00315N/apps/jp2/jpx_local.h"; sourceTree = SOURCE_ROOT; };
+		4310BA74110DD27C00C258B9 /* jpx.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = jpx.cpp; path = "../../ossim_dependencies/kakadu/v6_2_1-00315N/apps/jp2/jpx.cpp"; sourceTree = SOURCE_ROOT; };
+		4310BA75110DD27C00C258B9 /* mj2_local.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = mj2_local.h; path = "../../ossim_dependencies/kakadu/v6_2_1-00315N/apps/jp2/mj2_local.h"; sourceTree = SOURCE_ROOT; };
+		4310BA76110DD27C00C258B9 /* mj2.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = mj2.cpp; path = "../../ossim_dependencies/kakadu/v6_2_1-00315N/apps/jp2/mj2.cpp"; sourceTree = SOURCE_ROOT; };
+		4310BA85110DD2C600C258B9 /* libkdu_v62R.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libkdu_v62R.dylib; path = ../../ossim_dependencies/kakadu/bin/libkdu_v62R.dylib; sourceTree = SOURCE_ROOT; };
+		43132112103C84DF00F96FDF /* libossimkakadu_plugin.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libossimkakadu_plugin.dylib; sourceTree = BUILT_PRODUCTS_DIR; };
+		4329336310FE4B8500C66EB8 /* liblt_kakadu.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = liblt_kakadu.a; path = ../../ossim_dependencies/mrsid/lib/liblt_kakadu.a; sourceTree = SOURCE_ROOT; };
+		4329336410FE4B8500C66EB8 /* libltidsdk.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libltidsdk.a; path = ../../ossim_dependencies/mrsid/lib/libltidsdk.a; sourceTree = SOURCE_ROOT; };
+		43333CE010FD029600A5B432 /* libfcgi.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libfcgi.a; path = ../../ossim_dependencies/nuiSDK/lib/libfcgi.a; sourceTree = SOURCE_ROOT; };
+		43333CE110FD029600A5B432 /* libfcgi++.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = "libfcgi++.a"; path = "../../ossim_dependencies/nuiSDK/lib/libfcgi++.a"; sourceTree = SOURCE_ROOT; };
+		43333CE210FD029600A5B432 /* libgd.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libgd.a; path = ../../ossim_dependencies/nuiSDK/lib/libgd.a; sourceTree = SOURCE_ROOT; };
+		43333CE310FD029600A5B432 /* libgdal.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libgdal.a; path = ../../ossim_dependencies/nuiSDK/lib/libgdal.a; sourceTree = SOURCE_ROOT; };
+		43333CE410FD029600A5B432 /* libgif.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libgif.a; path = ../../ossim_dependencies/nuiSDK/lib/libgif.a; sourceTree = SOURCE_ROOT; };
+		43333CE510FD029600A5B432 /* libjpeg.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libjpeg.a; path = ../../ossim_dependencies/nuiSDK/lib/libjpeg.a; sourceTree = SOURCE_ROOT; };
+		43333CE810FD029600A5B432 /* libnuiSDK.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libnuiSDK.a; path = ../../ossim_dependencies/nuiSDK/lib/libnuiSDK.a; sourceTree = SOURCE_ROOT; };
+		43333CE910FD029600A5B432 /* libpng.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libpng.a; path = ../../ossim_dependencies/nuiSDK/lib/libpng.a; sourceTree = SOURCE_ROOT; };
+		43333CEA10FD029600A5B432 /* libproj.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libproj.a; path = ../../ossim_dependencies/nuiSDK/lib/libproj.a; sourceTree = SOURCE_ROOT; };
+		43333CFD10FD031500A5B432 /* libkdu.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libkdu.a; path = ../../ossim_dependencies/nuiSDK/lib/libkdu.a; sourceTree = SOURCE_ROOT; };
+		43333D0110FD032100A5B432 /* libkdu_a52R.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libkdu_a52R.a; path = ../../ossim_dependencies/nuiSDK/lib/libkdu_a52R.a; sourceTree = SOURCE_ROOT; };
+		43377EF510CFFAC900ECC5AD /* libossimcsm_plugin.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libossimcsm_plugin.dylib; sourceTree = BUILT_PRODUCTS_DIR; };
+		43377EFF10CFFB6400ECC5AD /* ossimCsmSensorModel.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ossimCsmSensorModel.cpp; path = ../csm/ossimCsmSensorModel.cpp; sourceTree = SOURCE_ROOT; };
+		43377F0010CFFB6400ECC5AD /* ossimCsmPluginInit.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ossimCsmPluginInit.cpp; path = ../csm/ossimCsmPluginInit.cpp; sourceTree = SOURCE_ROOT; };
+		43377F0110CFFB6400ECC5AD /* ossimCsmSensorModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ossimCsmSensorModel.h; path = ../csm/ossimCsmSensorModel.h; sourceTree = SOURCE_ROOT; };
+		43377F0210CFFB6400ECC5AD /* ossimCsmProjectionFactory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ossimCsmProjectionFactory.h; path = ../csm/ossimCsmProjectionFactory.h; sourceTree = SOURCE_ROOT; };
+		43377F0310CFFB6400ECC5AD /* ossimCsmProjectionFactory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ossimCsmProjectionFactory.cpp; path = ../csm/ossimCsmProjectionFactory.cpp; sourceTree = SOURCE_ROOT; };
+		43377F2010CFFC8200ECC5AD /* csmapi.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = csmapi.framework; path = ../../ossim_dependencies/Frameworks/csmapi.framework; sourceTree = SOURCE_ROOT; };
+		43378A0110D01EFD00ECC5AD /* ossimCsmSupport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ossimCsmSupport.h; path = ../csm/ossimCsmSupport.h; sourceTree = SOURCE_ROOT; };
+		43378A0210D01EFD00ECC5AD /* ossimCsmSupport.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ossimCsmSupport.cpp; path = ../csm/ossimCsmSupport.cpp; sourceTree = SOURCE_ROOT; };
+		436A7E3510FB9FC400985348 /* libossimmrsid_plugin.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libossimmrsid_plugin.dylib; sourceTree = BUILT_PRODUCTS_DIR; };
+		436A7E4310FBA00100985348 /* ossimMrSidReader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ossimMrSidReader.h; path = ../mrsid/ossimMrSidReader.h; sourceTree = SOURCE_ROOT; };
+		436A7E4410FBA00100985348 /* ossimMrSidWriterFactory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ossimMrSidWriterFactory.cpp; path = ../mrsid/ossimMrSidWriterFactory.cpp; sourceTree = SOURCE_ROOT; };
+		436A7E4510FBA00100985348 /* ossimMrSidWriter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ossimMrSidWriter.h; path = ../mrsid/ossimMrSidWriter.h; sourceTree = SOURCE_ROOT; };
+		436A7E4610FBA00100985348 /* ossimMrSidReaderFactory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ossimMrSidReaderFactory.cpp; path = ../mrsid/ossimMrSidReaderFactory.cpp; sourceTree = SOURCE_ROOT; };
+		436A7E4710FBA00100985348 /* ossimMrSidWriterFactory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ossimMrSidWriterFactory.h; path = ../mrsid/ossimMrSidWriterFactory.h; sourceTree = SOURCE_ROOT; };
+		436A7E4810FBA00100985348 /* ossimMrSidReader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ossimMrSidReader.cpp; path = ../mrsid/ossimMrSidReader.cpp; sourceTree = SOURCE_ROOT; };
+		436A7E4910FBA00100985348 /* ossimMrSidWriter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ossimMrSidWriter.cpp; path = ../mrsid/ossimMrSidWriter.cpp; sourceTree = SOURCE_ROOT; };
+		436A7E4A10FBA00100985348 /* ossimMrSidReaderFactory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ossimMrSidReaderFactory.h; path = ../mrsid/ossimMrSidReaderFactory.h; sourceTree = SOURCE_ROOT; };
+		436A7E4B10FBA00100985348 /* ossimMrSidPluginInit.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ossimMrSidPluginInit.cpp; path = ../mrsid/ossimMrSidPluginInit.cpp; sourceTree = SOURCE_ROOT; };
+		436A7F3010FBB24200985348 /* ossimKakaduCompressor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ossimKakaduCompressor.h; sourceTree = "<group>"; };
+		436A7F3110FBB24200985348 /* ossimKakaduOverviewBuilderFactory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ossimKakaduOverviewBuilderFactory.h; sourceTree = "<group>"; };
+		436A7F3210FBB24200985348 /* ossimKakaduNitfWriter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ossimKakaduNitfWriter.h; sourceTree = "<group>"; };
+		436A7F3310FBB24200985348 /* ossimKakaduMessaging.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ossimKakaduMessaging.h; sourceTree = "<group>"; };
+		436A7F3410FBB24200985348 /* ossimKakaduKeywords.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ossimKakaduKeywords.h; sourceTree = "<group>"; };
+		436A7F3510FBB24200985348 /* ossimKakaduJp2Reader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ossimKakaduJp2Reader.h; sourceTree = "<group>"; };
+		436A7F3610FBB24200985348 /* ossimKakaduReaderFactory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ossimKakaduReaderFactory.h; sourceTree = "<group>"; };
+		436A7F3710FBB24200985348 /* ossimKakaduOverviewBuilderFactory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ossimKakaduOverviewBuilderFactory.cpp; sourceTree = "<group>"; };
+		436A7F3810FBB24200985348 /* ossimKakaduCompressedTarget.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ossimKakaduCompressedTarget.h; sourceTree = "<group>"; };
+		436A7F3910FBB24200985348 /* ossimKakaduJ2kReader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ossimKakaduJ2kReader.h; sourceTree = "<group>"; };
+		436A7F3A10FBB24200985348 /* ossimKakaduJp2Writer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ossimKakaduJp2Writer.cpp; sourceTree = "<group>"; };
+		436A7F3B10FBB24200985348 /* ossimKakaduCompressedTarget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ossimKakaduCompressedTarget.cpp; sourceTree = "<group>"; };
+		436A7F3C10FBB24200985348 /* ossimKakaduNitfOverviewBuilder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ossimKakaduNitfOverviewBuilder.h; sourceTree = "<group>"; };
+		436A7F3D10FBB24200985348 /* ossimKakaduCompressor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ossimKakaduCompressor.cpp; sourceTree = "<group>"; };
+		436A7F3E10FBB24200985348 /* ossimKakaduNitfOverviewBuilder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ossimKakaduNitfOverviewBuilder.cpp; sourceTree = "<group>"; };
+		436A7F3F10FBB24200985348 /* ossimKakaduNitfReader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ossimKakaduNitfReader.cpp; sourceTree = "<group>"; };
+		436A7F4010FBB24200985348 /* ossimKakaduJp2Writer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ossimKakaduJp2Writer.h; sourceTree = "<group>"; };
+		436A7F4110FBB24200985348 /* ossimKakaduJ2kReader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ossimKakaduJ2kReader.cpp; sourceTree = "<group>"; };
+		436A7F4210FBB24200985348 /* ossimKakaduCommon.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ossimKakaduCommon.h; sourceTree = "<group>"; };
+		436A7F4310FBB24200985348 /* ossimKakaduWriterFactory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ossimKakaduWriterFactory.h; sourceTree = "<group>"; };
+		436A7F4410FBB24200985348 /* ossimKakaduNitfWriter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ossimKakaduNitfWriter.cpp; sourceTree = "<group>"; };
+		436A7F4510FBB24200985348 /* ossimKakaduNitfReader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ossimKakaduNitfReader.h; sourceTree = "<group>"; };
+		436A7F4610FBB24200985348 /* ossimKakaduReaderFactory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ossimKakaduReaderFactory.cpp; sourceTree = "<group>"; };
+		436A7F4710FBB24200985348 /* ossimKakaduWriterFactory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ossimKakaduWriterFactory.cpp; sourceTree = "<group>"; };
+		436A7F4810FBB24200985348 /* ossimKakaduPluginInit.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ossimKakaduPluginInit.cpp; sourceTree = "<group>"; };
+		436A7F4910FBB24200985348 /* ossimKakaduJp2Reader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ossimKakaduJp2Reader.cpp; sourceTree = "<group>"; };
+		436A7F4A10FBB24200985348 /* ossimKakaduCommon.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ossimKakaduCommon.cpp; sourceTree = "<group>"; };
+		437184710BCF07BA0002D30E /* Openthreads.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Openthreads.framework; path = ../../ossim_dependencies/Frameworks/Openthreads.framework; sourceTree = SOURCE_ROOT; };
+		4391B4D7110F6D0400B5895E /* kdu_region_decompressor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = kdu_region_decompressor.cpp; path = "../../ossim_dependencies/kakadu/v6_2_1-00315N/apps/support/kdu_region_decompressor.cpp"; sourceTree = SOURCE_ROOT; };
+		4391B4D8110F6D0400B5895E /* kdu_region_decompressor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = kdu_region_decompressor.h; path = "../../ossim_dependencies/kakadu/v6_2_1-00315N/apps/support/kdu_region_decompressor.h"; sourceTree = SOURCE_ROOT; };
+		43A9A0AE1151AC37000860DA /* libossim_plugin.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libossim_plugin.dylib; sourceTree = BUILT_PRODUCTS_DIR; };
+		43A9A0E31151ADA7000860DA /* ErsSarDataSetSummary.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ErsSarDataSetSummary.cpp; sourceTree = "<group>"; };
+		43A9A0E41151ADA7000860DA /* ErsSarDataSetSummary.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ErsSarDataSetSummary.h; sourceTree = "<group>"; };
+		43A9A0E51151ADA7000860DA /* ErsSarFacilityData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ErsSarFacilityData.cpp; sourceTree = "<group>"; };
+		43A9A0E61151ADA7000860DA /* ErsSarFacilityData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ErsSarFacilityData.h; sourceTree = "<group>"; };
+		43A9A0E71151ADA7000860DA /* ErsSarFileDescriptor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ErsSarFileDescriptor.cpp; sourceTree = "<group>"; };
+		43A9A0E81151ADA7000860DA /* ErsSarFileDescriptor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ErsSarFileDescriptor.h; sourceTree = "<group>"; };
+		43A9A0E91151ADA7000860DA /* ErsSarLeader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ErsSarLeader.cpp; sourceTree = "<group>"; };
+		43A9A0EA1151ADA7000860DA /* ErsSarLeader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ErsSarLeader.h; sourceTree = "<group>"; };
+		43A9A0EB1151ADA7000860DA /* ErsSarLeaderFactory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ErsSarLeaderFactory.cpp; sourceTree = "<group>"; };
+		43A9A0EC1151ADA7000860DA /* ErsSarLeaderFactory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ErsSarLeaderFactory.h; sourceTree = "<group>"; };
+		43A9A0ED1151ADA7000860DA /* ErsSarMapProjectionData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ErsSarMapProjectionData.cpp; sourceTree = "<group>"; };
+		43A9A0EE1151ADA7000860DA /* ErsSarMapProjectionData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ErsSarMapProjectionData.h; sourceTree = "<group>"; };
+		43A9A0EF1151ADA7000860DA /* ErsSarPlatformPositionData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ErsSarPlatformPositionData.cpp; sourceTree = "<group>"; };
+		43A9A0F01151ADA7000860DA /* ErsSarPlatformPositionData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ErsSarPlatformPositionData.h; sourceTree = "<group>"; };
+		43A9A0F11151ADA7000860DA /* ErsSarPositionVectorRecord.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ErsSarPositionVectorRecord.cpp; sourceTree = "<group>"; };
+		43A9A0F21151ADA7000860DA /* ErsSarPositionVectorRecord.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ErsSarPositionVectorRecord.h; sourceTree = "<group>"; };
+		43A9A0F31151ADA7000860DA /* ErsSarRecord.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ErsSarRecord.cpp; sourceTree = "<group>"; };
+		43A9A0F41151ADA7000860DA /* ErsSarRecord.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ErsSarRecord.h; sourceTree = "<group>"; };
+		43A9A0F51151ADA7000860DA /* ErsSarRecordFactory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ErsSarRecordFactory.cpp; sourceTree = "<group>"; };
+		43A9A0F61151ADA7000860DA /* ErsSarRecordFactory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ErsSarRecordFactory.h; sourceTree = "<group>"; };
+		43A9A0F71151ADA7000860DA /* ErsSarRecordHeader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ErsSarRecordHeader.cpp; sourceTree = "<group>"; };
+		43A9A0F81151ADA7000860DA /* ErsSarRecordHeader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ErsSarRecordHeader.h; sourceTree = "<group>"; };
+		43A9A0F91151ADA7000860DA /* Makefile */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = "<group>"; };
+		43A9A0FA1151ADA7000860DA /* makefile.vc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = makefile.vc; sourceTree = "<group>"; };
+		43A9A0FB1151ADA7000860DA /* ossimCosmoSkymedModel.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ossimCosmoSkymedModel.cpp; path = ../ossim/ossimCosmoSkymedModel.cpp; sourceTree = SOURCE_ROOT; };
+		43A9A0FC1151ADA7000860DA /* ossimCosmoSkymedModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ossimCosmoSkymedModel.h; path = ../ossim/ossimCosmoSkymedModel.h; sourceTree = SOURCE_ROOT; };
+		43A9A0FD1151ADA7000860DA /* ossimEnvisatAsarModel.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ossimEnvisatAsarModel.cpp; path = ../ossim/ossimEnvisatAsarModel.cpp; sourceTree = SOURCE_ROOT; };
+		43A9A0FE1151ADA7000860DA /* ossimEnvisatAsarModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ossimEnvisatAsarModel.h; path = ../ossim/ossimEnvisatAsarModel.h; sourceTree = SOURCE_ROOT; };
+		43A9A0FF1151ADA7000860DA /* ossimErsSarModel.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ossimErsSarModel.cpp; path = ../ossim/ossimErsSarModel.cpp; sourceTree = SOURCE_ROOT; };
+		43A9A1001151ADA8000860DA /* ossimErsSarModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ossimErsSarModel.h; path = ../ossim/ossimErsSarModel.h; sourceTree = SOURCE_ROOT; };
+		43A9A1011151ADA8000860DA /* ossimGeometricSarSensorModel.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ossimGeometricSarSensorModel.cpp; path = ../ossim/ossimGeometricSarSensorModel.cpp; sourceTree = SOURCE_ROOT; };
+		43A9A1021151ADA8000860DA /* ossimGeometricSarSensorModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ossimGeometricSarSensorModel.h; path = ../ossim/ossimGeometricSarSensorModel.h; sourceTree = SOURCE_ROOT; };
+		43A9A1031151ADA8000860DA /* ossimPluginCommon.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ossimPluginCommon.cpp; path = ../ossim/ossimPluginCommon.cpp; sourceTree = SOURCE_ROOT; };
+		43A9A1041151ADA8000860DA /* ossimPluginCommon.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ossimPluginCommon.h; path = ../ossim/ossimPluginCommon.h; sourceTree = SOURCE_ROOT; };
+		43A9A1051151ADA8000860DA /* ossimPluginInit.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ossimPluginInit.cpp; path = ../ossim/ossimPluginInit.cpp; sourceTree = SOURCE_ROOT; };
+		43A9A1061151ADA8000860DA /* ossimPluginProjectionFactory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ossimPluginProjectionFactory.cpp; path = ../ossim/ossimPluginProjectionFactory.cpp; sourceTree = SOURCE_ROOT; };
+		43A9A1071151ADA8000860DA /* ossimPluginProjectionFactory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ossimPluginProjectionFactory.h; path = ../ossim/ossimPluginProjectionFactory.h; sourceTree = SOURCE_ROOT; };
+		43A9A1081151ADA8000860DA /* ossimPluginReaderFactory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ossimPluginReaderFactory.cpp; path = ../ossim/ossimPluginReaderFactory.cpp; sourceTree = SOURCE_ROOT; };
+		43A9A1091151ADA8000860DA /* ossimPluginReaderFactory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ossimPluginReaderFactory.h; path = ../ossim/ossimPluginReaderFactory.h; sourceTree = SOURCE_ROOT; };
+		43A9A10A1151ADA8000860DA /* ossimRadarSat2Model.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ossimRadarSat2Model.cpp; path = ../ossim/ossimRadarSat2Model.cpp; sourceTree = SOURCE_ROOT; };
+		43A9A10B1151ADA8000860DA /* ossimRadarSat2Model.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ossimRadarSat2Model.h; path = ../ossim/ossimRadarSat2Model.h; sourceTree = SOURCE_ROOT; };
+		43A9A10C1151ADA8000860DA /* ossimRadarSat2ProductDoc.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ossimRadarSat2ProductDoc.cpp; path = ../ossim/ossimRadarSat2ProductDoc.cpp; sourceTree = SOURCE_ROOT; };
+		43A9A10D1151ADA8000860DA /* ossimRadarSat2ProductDoc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ossimRadarSat2ProductDoc.h; path = ../ossim/ossimRadarSat2ProductDoc.h; sourceTree = SOURCE_ROOT; };
+		43A9A10E1151ADA8000860DA /* ossimRadarSat2RPCModel.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ossimRadarSat2RPCModel.cpp; path = ../ossim/ossimRadarSat2RPCModel.cpp; sourceTree = SOURCE_ROOT; };
+		43A9A10F1151ADA8000860DA /* ossimRadarSat2RPCModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ossimRadarSat2RPCModel.h; path = ../ossim/ossimRadarSat2RPCModel.h; sourceTree = SOURCE_ROOT; };
+		43A9A1101151ADA8000860DA /* ossimRadarSatModel.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ossimRadarSatModel.cpp; path = ../ossim/ossimRadarSatModel.cpp; sourceTree = SOURCE_ROOT; };
+		43A9A1111151ADA8000860DA /* ossimRadarSatModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ossimRadarSatModel.h; path = ../ossim/ossimRadarSatModel.h; sourceTree = SOURCE_ROOT; };
+		43A9A1121151ADA8000860DA /* ossimTerraSarModel.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ossimTerraSarModel.cpp; path = ../ossim/ossimTerraSarModel.cpp; sourceTree = SOURCE_ROOT; };
+		43A9A1131151ADA8000860DA /* ossimTerraSarModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ossimTerraSarModel.h; path = ../ossim/ossimTerraSarModel.h; sourceTree = SOURCE_ROOT; };
+		43A9A1141151ADA8000860DA /* ossimTerraSarProductDoc.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ossimTerraSarProductDoc.cpp; path = ../ossim/ossimTerraSarProductDoc.cpp; sourceTree = SOURCE_ROOT; };
+		43A9A1151151ADA8000860DA /* ossimTerraSarProductDoc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ossimTerraSarProductDoc.h; path = ../ossim/ossimTerraSarProductDoc.h; sourceTree = SOURCE_ROOT; };
+		43A9A1161151ADA8000860DA /* ossimTerraSarTiffReader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ossimTerraSarTiffReader.cpp; path = ../ossim/ossimTerraSarTiffReader.cpp; sourceTree = SOURCE_ROOT; };
+		43A9A1171151ADA8000860DA /* ossimTerraSarTiffReader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ossimTerraSarTiffReader.h; path = ../ossim/ossimTerraSarTiffReader.h; sourceTree = SOURCE_ROOT; };
+		43A9A1191151ADA8000860DA /* Arithmetic.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Arithmetic.h; sourceTree = "<group>"; };
+		43A9A11A1151ADA8000860DA /* CivilDateTime.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CivilDateTime.cpp; sourceTree = "<group>"; };
+		43A9A11B1151ADA8000860DA /* CivilDateTime.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CivilDateTime.h; sourceTree = "<group>"; };
+		43A9A11C1151ADA8000860DA /* Coordinate.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Coordinate.cpp; sourceTree = "<group>"; };
+		43A9A11D1151ADA8000860DA /* Coordinate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Coordinate.h; sourceTree = "<group>"; };
+		43A9A11E1151ADA8000860DA /* Ephemeris.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Ephemeris.cpp; sourceTree = "<group>"; };
+		43A9A11F1151ADA8000860DA /* Ephemeris.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Ephemeris.h; sourceTree = "<group>"; };
+		43A9A1201151ADA8000860DA /* Equation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Equation.cpp; sourceTree = "<group>"; };
+		43A9A1211151ADA8000860DA /* Equation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Equation.h; sourceTree = "<group>"; };
+		43A9A1221151ADA8000860DA /* GalileanEphemeris.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GalileanEphemeris.cpp; sourceTree = "<group>"; };
+		43A9A1231151ADA8000860DA /* GalileanEphemeris.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GalileanEphemeris.h; sourceTree = "<group>"; };
+		43A9A1241151ADA8000860DA /* GeodesicCoordinate.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GeodesicCoordinate.cpp; sourceTree = "<group>"; };
+		43A9A1251151ADA8000860DA /* GeodesicCoordinate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GeodesicCoordinate.h; sourceTree = "<group>"; };
+		43A9A1261151ADA8000860DA /* GeographicEphemeris.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GeographicEphemeris.cpp; sourceTree = "<group>"; };
+		43A9A1271151ADA8000860DA /* GeographicEphemeris.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GeographicEphemeris.h; sourceTree = "<group>"; };
+		43A9A1281151ADA8000860DA /* GMSTDateTime.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GMSTDateTime.cpp; sourceTree = "<group>"; };
+		43A9A1291151ADA8000860DA /* GMSTDateTime.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GMSTDateTime.h; sourceTree = "<group>"; };
+		43A9A12A1151ADA8000860DA /* HermiteInterpolator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HermiteInterpolator.cpp; sourceTree = "<group>"; };
+		43A9A12B1151ADA8000860DA /* HermiteInterpolator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HermiteInterpolator.h; sourceTree = "<group>"; };
+		43A9A12C1151ADA8000860DA /* ImageNoise.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ImageNoise.cpp; sourceTree = "<group>"; };
+		43A9A12D1151ADA8000860DA /* ImageNoise.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ImageNoise.h; sourceTree = "<group>"; };
+		43A9A12E1151ADA8000860DA /* JSDDateTime.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSDDateTime.cpp; sourceTree = "<group>"; };
+		43A9A12F1151ADA8000860DA /* JSDDateTime.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSDDateTime.h; sourceTree = "<group>"; };
+		43A9A1301151ADA8000860DA /* JulianDate.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JulianDate.cpp; sourceTree = "<group>"; };
+		43A9A1311151ADA8000860DA /* JulianDate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JulianDate.h; sourceTree = "<group>"; };
+		43A9A1321151ADA8000860DA /* Makefile */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = "<group>"; };
+		43A9A1331151ADA8000860DA /* makefile.vc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = makefile.vc; sourceTree = "<group>"; };
+		43A9A1341151ADA8000860DA /* MJDDateTime.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MJDDateTime.cpp; sourceTree = "<group>"; };
+		43A9A1351151ADA8000860DA /* MJDDateTime.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MJDDateTime.h; sourceTree = "<group>"; };
+		43A9A1361151ADA8000860DA /* Noise.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Noise.cpp; sourceTree = "<group>"; };
+		43A9A1371151ADA8000860DA /* Noise.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Noise.h; sourceTree = "<group>"; };
+		43A9A1381151ADA8000860DA /* PlatformPosition.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PlatformPosition.cpp; sourceTree = "<group>"; };
+		43A9A1391151ADA8000860DA /* PlatformPosition.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PlatformPosition.h; sourceTree = "<group>"; };
+		43A9A13A1151ADA8000860DA /* RectangularCoordinate.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RectangularCoordinate.cpp; sourceTree = "<group>"; };
+		43A9A13B1151ADA8000860DA /* RectangularCoordinate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RectangularCoordinate.h; sourceTree = "<group>"; };
+		43A9A13C1151ADA8000860DA /* RefPoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RefPoint.cpp; sourceTree = "<group>"; };
+		43A9A13D1151ADA8000860DA /* RefPoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RefPoint.h; sourceTree = "<group>"; };
+		43A9A13E1151ADA8000860DA /* SarSensor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SarSensor.cpp; sourceTree = "<group>"; };
+		43A9A13F1151ADA8000860DA /* SarSensor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SarSensor.h; sourceTree = "<group>"; };
+		43A9A1401151ADA8000860DA /* Sensor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Sensor.cpp; sourceTree = "<group>"; };
+		43A9A1411151ADA8000860DA /* Sensor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Sensor.h; sourceTree = "<group>"; };
+		43A9A1421151ADA8000860DA /* SensorParams.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SensorParams.cpp; sourceTree = "<group>"; };
+		43A9A1431151ADA8000860DA /* SensorParams.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SensorParams.h; sourceTree = "<group>"; };
+		EE69A3800B28850A00C91DD1 /* libwms.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = libwms.xcodeproj; path = ../../libwms/xcode/libwms/libwms.xcodeproj; sourceTree = SOURCE_ROOT; };
+		EE80314D0F138F5500BB8BBB /* ossimNitroPluginInit.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ossimNitroPluginInit.cpp; sourceTree = "<group>"; };
+		EE8031610F13932A00BB8BBB /* ossimNitroHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ossimNitroHandler.h; sourceTree = "<group>"; };
+		EE8031650F13952700BB8BBB /* ossimNitroHandler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ossimNitroHandler.cpp; sourceTree = "<group>"; };
+		EE8031B70F13A6A200BB8BBB /* ossimNitroImageHandlerFactory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ossimNitroImageHandlerFactory.cpp; sourceTree = "<group>"; };
+		EE8031B80F13A6A200BB8BBB /* ossimNitroImageHandlerFactory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ossimNitroImageHandlerFactory.h; sourceTree = "<group>"; };
+		EEA3C47C0E3FA61B00CAAC1A /* ossimEsriShapeFileFilter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ossimEsriShapeFileFilter.cpp; sourceTree = "<group>"; };
+		EEA3C47D0E3FA61B00CAAC1A /* ossimEsriShapeFileFilter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ossimEsriShapeFileFilter.h; sourceTree = "<group>"; };
+		EEA3C47E0E3FA61B00CAAC1A /* ossimGdalDataset.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ossimGdalDataset.cpp; sourceTree = "<group>"; };
+		EEA3C47F0E3FA61B00CAAC1A /* ossimGdalDataset.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ossimGdalDataset.h; sourceTree = "<group>"; };
+		EEA3C4800E3FA61B00CAAC1A /* ossimGdalFactory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ossimGdalFactory.cpp; sourceTree = "<group>"; };
+		EEA3C4810E3FA61B00CAAC1A /* ossimGdalFactory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ossimGdalFactory.h; sourceTree = "<group>"; };
+		EEA3C4820E3FA61B00CAAC1A /* ossimGdalImageWriterFactory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ossimGdalImageWriterFactory.cpp; sourceTree = "<group>"; };
+		EEA3C4830E3FA61B00CAAC1A /* ossimGdalImageWriterFactory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ossimGdalImageWriterFactory.h; sourceTree = "<group>"; };
+		EEA3C4840E3FA61B00CAAC1A /* ossimGdalObjectFactory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ossimGdalObjectFactory.cpp; sourceTree = "<group>"; };
+		EEA3C4850E3FA61B00CAAC1A /* ossimGdalObjectFactory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ossimGdalObjectFactory.h; sourceTree = "<group>"; };
+		EEA3C4860E3FA61B00CAAC1A /* ossimGdalOgrVectorAnnotation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ossimGdalOgrVectorAnnotation.cpp; sourceTree = "<group>"; };
+		EEA3C4880E3FA61B00CAAC1A /* ossimGdalOgrVectorAnnotation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ossimGdalOgrVectorAnnotation.h; sourceTree = "<group>"; };
+		EEA3C4890E3FA61B00CAAC1A /* ossimGdalOverviewBuilder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ossimGdalOverviewBuilder.cpp; sourceTree = "<group>"; };
+		EEA3C48A0E3FA61B00CAAC1A /* ossimGdalOverviewBuilder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ossimGdalOverviewBuilder.h; sourceTree = "<group>"; };
+		EEA3C48B0E3FA61B00CAAC1A /* ossimGdalOverviewBuilderFactory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ossimGdalOverviewBuilderFactory.cpp; sourceTree = "<group>"; };
+		EEA3C48C0E3FA61B00CAAC1A /* ossimGdalOverviewBuilderFactory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ossimGdalOverviewBuilderFactory.h; sourceTree = "<group>"; };
+		EEA3C48D0E3FA61B00CAAC1A /* ossimGdalPluginInit.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ossimGdalPluginInit.cpp; sourceTree = "<group>"; };
+		EEA3C48E0E3FA61B00CAAC1A /* ossimGdalProjectionFactory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ossimGdalProjectionFactory.cpp; sourceTree = "<group>"; };
+		EEA3C48F0E3FA61B00CAAC1A /* ossimGdalProjectionFactory.cpp~ */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "ossimGdalProjectionFactory.cpp~"; sourceTree = "<group>"; };
+		EEA3C4900E3FA61B00CAAC1A /* ossimGdalProjectionFactory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ossimGdalProjectionFactory.h; sourceTree = "<group>"; };
+		EEA3C4910E3FA61B00CAAC1A /* ossimGdalTiledDataset.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ossimGdalTiledDataset.cpp; sourceTree = "<group>"; };
+		EEA3C4920E3FA61B00CAAC1A /* ossimGdalTiledDataset.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ossimGdalTiledDataset.h; sourceTree = "<group>"; };
+		EEA3C4930E3FA61B00CAAC1A /* ossimGdalTileSource.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ossimGdalTileSource.cpp; sourceTree = "<group>"; };
+		EEA3C4940E3FA61B00CAAC1A /* ossimGdalTileSource.cpp~ */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "ossimGdalTileSource.cpp~"; sourceTree = "<group>"; };
+		EEA3C4950E3FA61B00CAAC1A /* ossimGdalTileSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ossimGdalTileSource.h; sourceTree = "<group>"; };
+		EEA3C4960E3FA61B00CAAC1A /* ossimGdalTileSource.h~ */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "ossimGdalTileSource.h~"; sourceTree = "<group>"; };
+		EEA3C4970E3FA61B00CAAC1A /* ossimGdalType.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ossimGdalType.cpp; sourceTree = "<group>"; };
+		EEA3C4980E3FA61B00CAAC1A /* ossimGdalType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ossimGdalType.h; sourceTree = "<group>"; };
+		EEA3C4990E3FA61B00CAAC1A /* ossimGdalWriter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ossimGdalWriter.cpp; sourceTree = "<group>"; };
+		EEA3C49A0E3FA61B00CAAC1A /* ossimGdalWriter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ossimGdalWriter.h; sourceTree = "<group>"; };
+		EEA3C49B0E3FA61C00CAAC1A /* ossimOgcWktTranslator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ossimOgcWktTranslator.cpp; sourceTree = "<group>"; };
+		EEA3C49C0E3FA61C00CAAC1A /* ossimOgcWktTranslator.cpp~ */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "ossimOgcWktTranslator.cpp~"; sourceTree = "<group>"; };
+		EEA3C49D0E3FA61C00CAAC1A /* ossimOgcWktTranslator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ossimOgcWktTranslator.h; sourceTree = "<group>"; };
+		EEA3C49E0E3FA61C00CAAC1A /* ossimOgrGdalTileSource.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ossimOgrGdalTileSource.cpp; sourceTree = "<group>"; };
+		EEA3C49F0E3FA61C00CAAC1A /* ossimOgrGdalTileSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ossimOgrGdalTileSource.h; sourceTree = "<group>"; };
+		EEA3C4A00E3FA61C00CAAC1A /* ossimShapeDatabase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ossimShapeDatabase.cpp; sourceTree = "<group>"; };
+		EEA3C4A10E3FA61C00CAAC1A /* ossimShapeDatabase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ossimShapeDatabase.h; sourceTree = "<group>"; };
+		EEA3C4A20E3FA61C00CAAC1A /* ossimShapeFile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ossimShapeFile.cpp; sourceTree = "<group>"; };
+		EEA3C4A30E3FA61C00CAAC1A /* ossimShapeFile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ossimShapeFile.h; sourceTree = "<group>"; };
+		EEA3C4A40E3FA61C00CAAC1A /* shapefil.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = shapefil.h; sourceTree = "<group>"; };
+		EEA720270B2F4256006E37B7 /* libossimcontrib_plugin.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libossimcontrib_plugin.dylib; sourceTree = BUILT_PRODUCTS_DIR; };
+		EEA720BD0B2F4331006E37B7 /* ossimContribImageSourceFactory.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = ossimContribImageSourceFactory.cpp; path = ../contrib/ossimContribImageSourceFactory.cpp; sourceTree = SOURCE_ROOT; };
+		EEA720BE0B2F4331006E37B7 /* ossimContribPluginInit.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = ossimContribPluginInit.cpp; path = ../contrib/ossimContribPluginInit.cpp; sourceTree = SOURCE_ROOT; };
+		EEA720BF0B2F4331006E37B7 /* ossimCFARFilter.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = ossimCFARFilter.cpp; path = ../contrib/ossimCFARFilter.cpp; sourceTree = SOURCE_ROOT; };
+		EEA720C00B2F4331006E37B7 /* ossimContribImageSourceFactory.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = ossimContribImageSourceFactory.h; path = ../contrib/ossimContribImageSourceFactory.h; sourceTree = SOURCE_ROOT; };
+		EEA720C10B2F4331006E37B7 /* ossimSPOTNatural.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = ossimSPOTNatural.cpp; path = ../contrib/ossimSPOTNatural.cpp; sourceTree = SOURCE_ROOT; };
+		EEA720C20B2F4331006E37B7 /* ossimSPOTNatural.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = ossimSPOTNatural.h; path = ../contrib/ossimSPOTNatural.h; sourceTree = SOURCE_ROOT; };
+		EEA720C30B2F4331006E37B7 /* ossimComplexAbs.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = ossimComplexAbs.cpp; path = ../contrib/ossimComplexAbs.cpp; sourceTree = SOURCE_ROOT; };
+		EEA720C40B2F4331006E37B7 /* ossimComplexAbs.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = ossimComplexAbs.h; path = ../contrib/ossimComplexAbs.h; sourceTree = SOURCE_ROOT; };
+		EEA720C50B2F4331006E37B7 /* ossimContribExports.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = ossimContribExports.h; path = ../contrib/ossimContribExports.h; sourceTree = SOURCE_ROOT; };
+		EEA720C60B2F4331006E37B7 /* ossimCFARFilter.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = ossimCFARFilter.h; path = ../contrib/ossimCFARFilter.h; sourceTree = SOURCE_ROOT; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+		186EF86B0B1F184C00F7886A /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				186EF9590B1F19F200F7886A /* ossim.framework in Frameworks */,
+				437184730BCF07BA0002D30E /* Openthreads.framework in Frameworks */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		186EF9800B1F222500F7886A /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				437185160BCF095C0002D30E /* Openthreads.framework in Frameworks */,
+				186EF98A0B1F234F00F7886A /* ossim.framework in Frameworks */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		186EFA1A0B1F321200F7886A /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				437185170BCF09690002D30E /* Openthreads.framework in Frameworks */,
+				EE69A38E0B28854C00C91DD1 /* wms.framework in Frameworks */,
+				186EFA420B1F373E00F7886A /* ossim.framework in Frameworks */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		186EFA5D0B1F394100F7886A /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				437185290BCF0C750002D30E /* Openthreads.framework in Frameworks */,
+				186EFA7E0B1F3B7D00F7886A /* ossim.framework in Frameworks */,
+				43333CEB10FD029600A5B432 /* libfcgi.a in Frameworks */,
+				43333CEC10FD029600A5B432 /* libfcgi++.a in Frameworks */,
+				43333CED10FD029600A5B432 /* libgd.a in Frameworks */,
+				43333CEE10FD029600A5B432 /* libgdal.a in Frameworks */,
+				43333CEF10FD029600A5B432 /* libgif.a in Frameworks */,
+				43333CF010FD029700A5B432 /* libjpeg.a in Frameworks */,
+				43333CF310FD029700A5B432 /* libnuiSDK.a in Frameworks */,
+				43333CF410FD029700A5B432 /* libpng.a in Frameworks */,
+				43333CF510FD029700A5B432 /* libproj.a in Frameworks */,
+				43333CFE10FD031500A5B432 /* libkdu.a in Frameworks */,
+				43333D0210FD032100A5B432 /* libkdu_a52R.a in Frameworks */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		430D1FDA0BB2F96B0057E5FF /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				437185060BCF07E80002D30E /* Openthreads.framework in Frameworks */,
+				430D1FDD0BB2F96B0057E5FF /* ossim.framework in Frameworks */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		43132109103C84DF00F96FDF /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				4310BA86110DD2C600C258B9 /* libkdu_v62R.dylib in Frameworks */,
+				4313210A103C84DF00F96FDF /* Openthreads.framework in Frameworks */,
+				4313210B103C84DF00F96FDF /* ossim.framework in Frameworks */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		43377EF310CFFAC900ECC5AD /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				43378A1910D020D800ECC5AD /* ossim.framework in Frameworks */,
+				43377F2110CFFC8200ECC5AD /* csmapi.framework in Frameworks */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		436A7E2B10FB9FC400985348 /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				436A7E2C10FB9FC400985348 /* Openthreads.framework in Frameworks */,
+				436A7E2D10FB9FC400985348 /* ossim.framework in Frameworks */,
+				4329336610FE4B8500C66EB8 /* liblt_kakadu.a in Frameworks */,
+				4329336710FE4B8500C66EB8 /* libltidsdk.a in Frameworks */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		43A9A0A51151AC37000860DA /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				43A9A0A61151AC37000860DA /* Openthreads.framework in Frameworks */,
+				43A9A0A71151AC37000860DA /* ossim.framework in Frameworks */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		EEA7201D0B2F4256006E37B7 /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				437185340BCF0C9C0002D30E /* Openthreads.framework in Frameworks */,
+				EEA720230B2F4256006E37B7 /* ossim.framework in Frameworks */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+		186EF84A0B1F0A5000F7886A = {
+			isa = PBXGroup;
+			children = (
+				186EF95F0B1F1AA100F7886A /* Source */,
+				186EF9620B1F1AC100F7886A /* External Frameworks */,
+				186EF9680B1F1B5400F7886A /* External Projects */,
+				186EF86E0B1F184C00F7886A /* Products */,
+			);
+			sourceTree = "<group>";
+		};
+		186EF86E0B1F184C00F7886A /* Products */ = {
+			isa = PBXGroup;
+			children = (
+				186EF86D0B1F184C00F7886A /* libossimgdal_plugin.dylib */,
+				186EF9820B1F222500F7886A /* libossimreg_plugin.dylib */,
+				186EFA1C0B1F321200F7886A /* libossimworldwind_plugin.dylib */,
+				186EFA5F0B1F394100F7886A /* libossimnui_plugin.dylib */,
+				EEA720270B2F4256006E37B7 /* libossimcontrib_plugin.dylib */,
+				430D1FE10BB2F96B0057E5FF /* libossimpng_plugin.dylib */,
+				43132112103C84DF00F96FDF /* libossimkakadu_plugin.dylib */,
+				43377EF510CFFAC900ECC5AD /* libossimcsm_plugin.dylib */,
+				436A7E3510FB9FC400985348 /* libossimmrsid_plugin.dylib */,
+				43A9A0AE1151AC37000860DA /* libossim_plugin.dylib */,
+			);
+			name = Products;
+			sourceTree = "<group>";
+		};
+		186EF8720B1F198600F7886A /* gdal */ = {
+			isa = PBXGroup;
+			children = (
+				EEA3C47C0E3FA61B00CAAC1A /* ossimEsriShapeFileFilter.cpp */,
+				EEA3C47D0E3FA61B00CAAC1A /* ossimEsriShapeFileFilter.h */,
+				EEA3C47E0E3FA61B00CAAC1A /* ossimGdalDataset.cpp */,
+				EEA3C47F0E3FA61B00CAAC1A /* ossimGdalDataset.h */,
+				EEA3C4800E3FA61B00CAAC1A /* ossimGdalFactory.cpp */,
+				EEA3C4810E3FA61B00CAAC1A /* ossimGdalFactory.h */,
+				EEA3C4820E3FA61B00CAAC1A /* ossimGdalImageWriterFactory.cpp */,
+				EEA3C4830E3FA61B00CAAC1A /* ossimGdalImageWriterFactory.h */,
+				EEA3C4840E3FA61B00CAAC1A /* ossimGdalObjectFactory.cpp */,
+				EEA3C4850E3FA61B00CAAC1A /* ossimGdalObjectFactory.h */,
+				EEA3C4860E3FA61B00CAAC1A /* ossimGdalOgrVectorAnnotation.cpp */,
+				EEA3C4880E3FA61B00CAAC1A /* ossimGdalOgrVectorAnnotation.h */,
+				EEA3C4890E3FA61B00CAAC1A /* ossimGdalOverviewBuilder.cpp */,
+				EEA3C48A0E3FA61B00CAAC1A /* ossimGdalOverviewBuilder.h */,
+				EEA3C48B0E3FA61B00CAAC1A /* ossimGdalOverviewBuilderFactory.cpp */,
+				EEA3C48C0E3FA61B00CAAC1A /* ossimGdalOverviewBuilderFactory.h */,
+				EEA3C48D0E3FA61B00CAAC1A /* ossimGdalPluginInit.cpp */,
+				EEA3C48E0E3FA61B00CAAC1A /* ossimGdalProjectionFactory.cpp */,
+				EEA3C48F0E3FA61B00CAAC1A /* ossimGdalProjectionFactory.cpp~ */,
+				EEA3C4900E3FA61B00CAAC1A /* ossimGdalProjectionFactory.h */,
+				EEA3C4910E3FA61B00CAAC1A /* ossimGdalTiledDataset.cpp */,
+				EEA3C4920E3FA61B00CAAC1A /* ossimGdalTiledDataset.h */,
+				EEA3C4930E3FA61B00CAAC1A /* ossimGdalTileSource.cpp */,
+				EEA3C4940E3FA61B00CAAC1A /* ossimGdalTileSource.cpp~ */,
+				EEA3C4950E3FA61B00CAAC1A /* ossimGdalTileSource.h */,
+				EEA3C4960E3FA61B00CAAC1A /* ossimGdalTileSource.h~ */,
+				EEA3C4970E3FA61B00CAAC1A /* ossimGdalType.cpp */,
+				EEA3C4980E3FA61B00CAAC1A /* ossimGdalType.h */,
+				EEA3C4990E3FA61B00CAAC1A /* ossimGdalWriter.cpp */,
+				EEA3C49A0E3FA61B00CAAC1A /* ossimGdalWriter.h */,
+				EEA3C49B0E3FA61C00CAAC1A /* ossimOgcWktTranslator.cpp */,
+				EEA3C49C0E3FA61C00CAAC1A /* ossimOgcWktTranslator.cpp~ */,
+				EEA3C49D0E3FA61C00CAAC1A /* ossimOgcWktTranslator.h */,
+				EEA3C49E0E3FA61C00CAAC1A /* ossimOgrGdalTileSource.cpp */,
+				EEA3C49F0E3FA61C00CAAC1A /* ossimOgrGdalTileSource.h */,
+				EEA3C4A00E3FA61C00CAAC1A /* ossimShapeDatabase.cpp */,
+				EEA3C4A10E3FA61C00CAAC1A /* ossimShapeDatabase.h */,
+				EEA3C4A20E3FA61C00CAAC1A /* ossimShapeFile.cpp */,
+				EEA3C4A30E3FA61C00CAAC1A /* ossimShapeFile.h */,
+				EEA3C4A40E3FA61C00CAAC1A /* shapefil.h */,
+			);
+			name = gdal;
+			path = ../gdal;
+			sourceTree = SOURCE_ROOT;
+		};
+		186EF8AB0B1F19E400F7886A /* Products */ = {
+			isa = PBXGroup;
+			children = (
+				186EF8EA0B1F19E400F7886A /* ossim.framework */,
+				4353102910440474004A4474 /* template-app */,
+				4353102B10440474004A4474 /* ossim-adrg-dump */,
+				4353102D10440474004A4474 /* ossim-applanix2ogeom */,
+				4353102F10440474004A4474 /* ossim-band-merge */,
+				4353103110440474004A4474 /* ossim-btoa */,
+				4353103310440474004A4474 /* template-app */,
+				4353103510440474004A4474 /* ossim-cmm */,
+				4353103710440474004A4474 /* ossim-computeSrtmStats */,
+				4353103910440474004A4474 /* ossim-correl */,
+				4353103B10440474004A4474 /* ossim-create-cg */,
+				4353103D10440474004A4474 /* ossim-create-histo */,
+				4353104510440474004A4474 /* ossim-dms2deg */,
+				4353104710440474004A4474 /* ossim-dump-ocg */,
+				4353104910440474004A4474 /* ossim-ecg2ocg */,
+				4353104B10440474004A4474 /* ossim-extract-vertices */,
+				4353104D10440474004A4474 /* ossim-foo */,
+				4353105110440474004A4474 /* ossim-height */,
+				4353105310440474004A4474 /* ossim-icp */,
+				4353105510440474004A4474 /* ossim-igen */,
+				4353105710440474004A4474 /* ossim-img2md */,
+				4353105910440474004A4474 /* ossim-img2rr */,
+				4353105B10440474004A4474 /* ossim-info */,
+				4353105D10440474004A4474 /* ossim-modopt */,
+				4353105F10440474004A4474 /* ossim-mosaic */,
+				4353106510440474004A4474 /* ossim-ogeom2ogeom */,
+				4353106710440474004A4474 /* ossim-orthoigen */,
+				4353106910440474004A4474 /* ossim-pixelflip */,
+				4353106B10440474004A4474 /* ossim-prune */,
+				4353106F10440474004A4474 /* ossim-rejout */,
+				4353107110440474004A4474 /* ossim-senint */,
+				4353107310440474004A4474 /* ossim-space-imaging */,
+				4353107510440474004A4474 /* ossim-swapbytes */,
+				4353107710440474004A4474 /* ossim-tfw2ogeom */,
+			);
+			name = Products;
+			sourceTree = "<group>";
+		};
+		186EF95F0B1F1AA100F7886A /* Source */ = {
+			isa = PBXGroup;
+			children = (
+				436A7E3910FB9FE600985348 /* mrsid */,
+				43377EF010CFFA7A00ECC5AD /* csm */,
+				43132163103C852900F96FDF /* kakadu */,
+				436C111A0E75909D004C3B42 /* ossim */,
+				430D20790BB2FA2A0057E5FF /* png */,
+				EEA720BC0B2F431F006E37B7 /* contrib */,
+				186EFA660B1F39FD00F7886A /* nui */,
+				EE80314B0F138F5500BB8BBB /* nitro */,
+				186EFA250B1F32FF00F7886A /* worldwind */,
+				186EF8550B1F0A7200F7886A /* common_settings.xcconfig */,
+				186EF8720B1F198600F7886A /* gdal */,
+				186EF98B0B1F236800F7886A /* registration */,
+			);
+			name = Source;
+			sourceTree = "<group>";
+		};
+		186EF9620B1F1AC100F7886A /* External Frameworks */ = {
+			isa = PBXGroup;
+			children = (
+				4310BA85110DD2C600C258B9 /* libkdu_v62R.dylib */,
+				4329335B10FE4B6700C66EB8 /* mrsid */,
+				43333CD510FD023D00A5B432 /* nui */,
+				43377F2010CFFC8200ECC5AD /* csmapi.framework */,
+				437184710BCF07BA0002D30E /* Openthreads.framework */,
+			);
+			name = "External Frameworks";
+			sourceTree = "<group>";
+		};
+		186EF9680B1F1B5400F7886A /* External Projects */ = {
+			isa = PBXGroup;
+			children = (
+				EE69A3800B28850A00C91DD1 /* libwms.xcodeproj */,
+				186EF8AA0B1F19E400F7886A /* ossim.xcodeproj */,
+			);
+			name = "External Projects";
+			sourceTree = "<group>";
+		};
+		186EF98B0B1F236800F7886A /* registration */ = {
+			isa = PBXGroup;
+			children = (
+				186EF98C0B1F236800F7886A /* ossimChipMatch.cpp */,
+				186EF98D0B1F236800F7886A /* ossimChipMatch.h */,
+				186EF98E0B1F236800F7886A /* ossimDensityReducer.cpp */,
+				186EF98F0B1F236800F7886A /* ossimDensityReducer.h */,
+				186EF9900B1F236800F7886A /* ossimExtremaFilter.cpp */,
+				186EF9910B1F236800F7886A /* ossimExtremaFilter.h */,
+				186EF9920B1F236800F7886A /* ossimHarrisCorners.cpp */,
+				186EF9930B1F236800F7886A /* ossimHarrisCorners.h */,
+				186EF9940B1F236800F7886A /* ossimImageCorrelator.cpp */,
+				186EF9950B1F236800F7886A /* ossimImageCorrelator.h */,
+				186EF9960B1F236800F7886A /* ossimModelOptimizer.cpp */,
+				186EF9970B1F236800F7886A /* ossimModelOptimizer.h */,
+				186EF9980B1F236800F7886A /* ossimMultiplier.cpp */,
+				186EF9990B1F236800F7886A /* ossimMultiplier.h */,
+				186EF99A0B1F236800F7886A /* ossimNCC_FFTW.cpp */,
+				186EF99B0B1F236800F7886A /* ossimNCC_FFTW.h */,
+				186EF99C0B1F236800F7886A /* ossimOutlierRejection.cpp */,
+				186EF99D0B1F236800F7886A /* ossimOutlierRejection.h */,
+				186EF99E0B1F236800F7886A /* ossimRegistrationExports.h */,
+				186EF99F0B1F236800F7886A /* ossimRegistrationImageSourceFactory.cpp */,
+				186EF9A00B1F236800F7886A /* ossimRegistrationImageSourceFactory.h */,
+				186EF9A10B1F236800F7886A /* ossimRegistrationMiscFactory.cpp */,
+				186EF9A20B1F236800F7886A /* ossimRegistrationMiscFactory.h */,
+				186EF9A30B1F236800F7886A /* ossimRegistrationPluginInit.cpp */,
+				186EF9A40B1F236800F7886A /* ossimRunningSum.cpp */,
+				186EF9A50B1F236800F7886A /* ossimRunningSum.h */,
+				186EF9A60B1F236800F7886A /* ossimSquareFunction.cpp */,
+				186EF9A70B1F236800F7886A /* ossimSquareFunction.h */,
+				186EF9A80B1F236800F7886A /* ossimTieGenerator.cpp */,
+				186EF9A90B1F236800F7886A /* ossimTieGenerator.h */,
+			);
+			name = registration;
+			path = ../registration;
+			sourceTree = SOURCE_ROOT;
+		};
+		186EFA250B1F32FF00F7886A /* worldwind */ = {
+			isa = PBXGroup;
+			children = (
+				186EFA260B1F32FF00F7886A /* ossimDiskCache.cpp */,
+				186EFA270B1F32FF00F7886A /* ossimDiskCache.h */,
+				186EFA280B1F32FF00F7886A /* ossimSharedDiskCacheManager.cpp */,
+				186EFA290B1F32FF00F7886A /* ossimSharedDiskCacheManager.h */,
+				186EFA2A0B1F32FF00F7886A /* ossimworldwind_plugin.vcproj */,
+				186EFA2B0B1F32FF00F7886A /* ossimWorldWindExports.h */,
+				186EFA2C0B1F32FF00F7886A /* ossimWorldWindFactory.cpp */,
+				186EFA2D0B1F32FF00F7886A /* ossimWorldWindFactory.h */,
+				186EFA2E0B1F32FF00F7886A /* ossimWorldWindHandler.cpp */,
+				186EFA2F0B1F32FF00F7886A /* ossimWorldWindHandler.h */,
+				186EFA300B1F32FF00F7886A /* ossimWorldWindJpegImage.cpp */,
+				186EFA310B1F32FF00F7886A /* ossimWorldWindJpegImage.h */,
+				186EFA320B1F32FF00F7886A /* ossimWorldWindPluginInit.cpp */,
+			);
+			name = worldwind;
+			path = ../worldwind;
+			sourceTree = SOURCE_ROOT;
+		};
+		186EFA660B1F39FD00F7886A /* nui */ = {
+			isa = PBXGroup;
+			children = (
+				186EFA670B1F39FD00F7886A /* ossimNuiPluginInit.cpp */,
+				186EFA680B1F39FD00F7886A /* ossimNuiHandler.h */,
+				186EFA690B1F39FD00F7886A /* ossimNuiHandler.cpp */,
+				186EFA6A0B1F39FD00F7886A /* ossimNuiFactory.h */,
+				186EFA6B0B1F39FD00F7886A /* ossimNuiFactory.cpp */,
+				186EFA6C0B1F39FD00F7886A /* ossimNuiExports.h */,
+			);
+			name = nui;
+			sourceTree = "<group>";
+		};
+		430D20790BB2FA2A0057E5FF /* png */ = {
+			isa = PBXGroup;
+			children = (
+				430D207A0BB2FA450057E5FF /* ossimPngReaderFactory.h */,
+				430D207B0BB2FA450057E5FF /* ossimPngWriterFactory.h */,
+				430D207C0BB2FA450057E5FF /* ossimPngWriterFactory.cpp */,
+				430D207D0BB2FA450057E5FF /* ossimPngPluginInit.cpp */,
+				430D207E0BB2FA450057E5FF /* ossimPngReaderFactory.cpp */,
+				430D207F0BB2FA450057E5FF /* ossimPngWriter.cpp */,
+				430D20800BB2FA450057E5FF /* ossimPngWriter.h */,
+				430D20810BB2FA450057E5FF /* ossimPngReader.cpp */,
+				430D20820BB2FA450057E5FF /* ossimPngReader.h */,
+			);
+			name = png;
+			sourceTree = "<group>";
+		};
+		43132163103C852900F96FDF /* kakadu */ = {
+			isa = PBXGroup;
+			children = (
+				4391B4D7110F6D0400B5895E /* kdu_region_decompressor.cpp */,
+				4391B4D8110F6D0400B5895E /* kdu_region_decompressor.h */,
+				4310BA70110DD27C00C258B9 /* jp2_local.h */,
+				4310BA71110DD27C00C258B9 /* jp2_shared.h */,
+				4310BA72110DD27C00C258B9 /* jp2.cpp */,
+				4310BA73110DD27C00C258B9 /* jpx_local.h */,
+				4310BA74110DD27C00C258B9 /* jpx.cpp */,
+				4310BA75110DD27C00C258B9 /* mj2_local.h */,
+				4310BA76110DD27C00C258B9 /* mj2.cpp */,
+				436A7F3010FBB24200985348 /* ossimKakaduCompressor.h */,
+				436A7F3110FBB24200985348 /* ossimKakaduOverviewBuilderFactory.h */,
+				436A7F3210FBB24200985348 /* ossimKakaduNitfWriter.h */,
+				436A7F3310FBB24200985348 /* ossimKakaduMessaging.h */,
+				436A7F3410FBB24200985348 /* ossimKakaduKeywords.h */,
+				436A7F3510FBB24200985348 /* ossimKakaduJp2Reader.h */,
+				436A7F3610FBB24200985348 /* ossimKakaduReaderFactory.h */,
+				436A7F3710FBB24200985348 /* ossimKakaduOverviewBuilderFactory.cpp */,
+				436A7F3810FBB24200985348 /* ossimKakaduCompressedTarget.h */,
+				436A7F3910FBB24200985348 /* ossimKakaduJ2kReader.h */,
+				436A7F3A10FBB24200985348 /* ossimKakaduJp2Writer.cpp */,
+				436A7F3B10FBB24200985348 /* ossimKakaduCompressedTarget.cpp */,
+				436A7F3C10FBB24200985348 /* ossimKakaduNitfOverviewBuilder.h */,
+				436A7F3D10FBB24200985348 /* ossimKakaduCompressor.cpp */,
+				436A7F3E10FBB24200985348 /* ossimKakaduNitfOverviewBuilder.cpp */,
+				436A7F3F10FBB24200985348 /* ossimKakaduNitfReader.cpp */,
+				436A7F4010FBB24200985348 /* ossimKakaduJp2Writer.h */,
+				436A7F4110FBB24200985348 /* ossimKakaduJ2kReader.cpp */,
+				436A7F4210FBB24200985348 /* ossimKakaduCommon.h */,
+				436A7F4310FBB24200985348 /* ossimKakaduWriterFactory.h */,
+				436A7F4410FBB24200985348 /* ossimKakaduNitfWriter.cpp */,
+				436A7F4510FBB24200985348 /* ossimKakaduNitfReader.h */,
+				436A7F4610FBB24200985348 /* ossimKakaduReaderFactory.cpp */,
+				436A7F4710FBB24200985348 /* ossimKakaduWriterFactory.cpp */,
+				436A7F4810FBB24200985348 /* ossimKakaduPluginInit.cpp */,
+				436A7F4910FBB24200985348 /* ossimKakaduJp2Reader.cpp */,
+				436A7F4A10FBB24200985348 /* ossimKakaduCommon.cpp */,
+			);
+			name = kakadu;
+			path = ../kakadu;
+			sourceTree = SOURCE_ROOT;
+		};
+		4329335B10FE4B6700C66EB8 /* mrsid */ = {
+			isa = PBXGroup;
+			children = (
+				4329336310FE4B8500C66EB8 /* liblt_kakadu.a */,
+				4329336410FE4B8500C66EB8 /* libltidsdk.a */,
+			);
+			name = mrsid;
+			sourceTree = "<group>";
+		};
+		43333CD510FD023D00A5B432 /* nui */ = {
+			isa = PBXGroup;
+			children = (
+				43333D0110FD032100A5B432 /* libkdu_a52R.a */,
+				43333CFD10FD031500A5B432 /* libkdu.a */,
+				43333CE010FD029600A5B432 /* libfcgi.a */,
+				43333CE110FD029600A5B432 /* libfcgi++.a */,
+				43333CE210FD029600A5B432 /* libgd.a */,
+				43333CE310FD029600A5B432 /* libgdal.a */,
+				43333CE410FD029600A5B432 /* libgif.a */,
+				43333CE510FD029600A5B432 /* libjpeg.a */,
+				43333CE810FD029600A5B432 /* libnuiSDK.a */,
+				43333CE910FD029600A5B432 /* libpng.a */,
+				43333CEA10FD029600A5B432 /* libproj.a */,
+			);
+			name = nui;
+			sourceTree = "<group>";
+		};
+		43377EF010CFFA7A00ECC5AD /* csm */ = {
+			isa = PBXGroup;
+			children = (
+				43378A0110D01EFD00ECC5AD /* ossimCsmSupport.h */,
+				43378A0210D01EFD00ECC5AD /* ossimCsmSupport.cpp */,
+				43377EFF10CFFB6400ECC5AD /* ossimCsmSensorModel.cpp */,
+				43377F0010CFFB6400ECC5AD /* ossimCsmPluginInit.cpp */,
+				43377F0110CFFB6400ECC5AD /* ossimCsmSensorModel.h */,
+				43377F0210CFFB6400ECC5AD /* ossimCsmProjectionFactory.h */,
+				43377F0310CFFB6400ECC5AD /* ossimCsmProjectionFactory.cpp */,
+			);
+			name = csm;
+			sourceTree = "<group>";
+		};
+		436A7E3910FB9FE600985348 /* mrsid */ = {
+			isa = PBXGroup;
+			children = (
+				436A7E4310FBA00100985348 /* ossimMrSidReader.h */,
+				436A7E4410FBA00100985348 /* ossimMrSidWriterFactory.cpp */,
+				436A7E4510FBA00100985348 /* ossimMrSidWriter.h */,
+				436A7E4610FBA00100985348 /* ossimMrSidReaderFactory.cpp */,
+				436A7E4710FBA00100985348 /* ossimMrSidWriterFactory.h */,
+				436A7E4810FBA00100985348 /* ossimMrSidReader.cpp */,
+				436A7E4910FBA00100985348 /* ossimMrSidWriter.cpp */,
+				436A7E4A10FBA00100985348 /* ossimMrSidReaderFactory.h */,
+				436A7E4B10FBA00100985348 /* ossimMrSidPluginInit.cpp */,
+			);
+			name = mrsid;
+			sourceTree = "<group>";
+		};
+		436C111A0E75909D004C3B42 /* ossim */ = {
+			isa = PBXGroup;
+			children = (
+				43A9A0E21151ADA7000860DA /* erssar */,
+				43A9A0FB1151ADA7000860DA /* ossimCosmoSkymedModel.cpp */,
+				43A9A0FC1151ADA7000860DA /* ossimCosmoSkymedModel.h */,
+				43A9A0FD1151ADA7000860DA /* ossimEnvisatAsarModel.cpp */,
+				43A9A0FE1151ADA7000860DA /* ossimEnvisatAsarModel.h */,
+				43A9A0FF1151ADA7000860DA /* ossimErsSarModel.cpp */,
+				43A9A1001151ADA8000860DA /* ossimErsSarModel.h */,
+				43A9A1011151ADA8000860DA /* ossimGeometricSarSensorModel.cpp */,
+				43A9A1021151ADA8000860DA /* ossimGeometricSarSensorModel.h */,
+				43A9A1031151ADA8000860DA /* ossimPluginCommon.cpp */,
+				43A9A1041151ADA8000860DA /* ossimPluginCommon.h */,
+				43A9A1051151ADA8000860DA /* ossimPluginInit.cpp */,
+				43A9A1061151ADA8000860DA /* ossimPluginProjectionFactory.cpp */,
+				43A9A1071151ADA8000860DA /* ossimPluginProjectionFactory.h */,
+				43A9A1081151ADA8000860DA /* ossimPluginReaderFactory.cpp */,
+				43A9A1091151ADA8000860DA /* ossimPluginReaderFactory.h */,
+				43A9A10A1151ADA8000860DA /* ossimRadarSat2Model.cpp */,
+				43A9A10B1151ADA8000860DA /* ossimRadarSat2Model.h */,
+				43A9A10C1151ADA8000860DA /* ossimRadarSat2ProductDoc.cpp */,
+				43A9A10D1151ADA8000860DA /* ossimRadarSat2ProductDoc.h */,
+				43A9A10E1151ADA8000860DA /* ossimRadarSat2RPCModel.cpp */,
+				43A9A10F1151ADA8000860DA /* ossimRadarSat2RPCModel.h */,
+				43A9A1101151ADA8000860DA /* ossimRadarSatModel.cpp */,
+				43A9A1111151ADA8000860DA /* ossimRadarSatModel.h */,
+				43A9A1121151ADA8000860DA /* ossimTerraSarModel.cpp */,
+				43A9A1131151ADA8000860DA /* ossimTerraSarModel.h */,
+				43A9A1141151ADA8000860DA /* ossimTerraSarProductDoc.cpp */,
+				43A9A1151151ADA8000860DA /* ossimTerraSarProductDoc.h */,
+				43A9A1161151ADA8000860DA /* ossimTerraSarTiffReader.cpp */,
+				43A9A1171151ADA8000860DA /* ossimTerraSarTiffReader.h */,
+				43A9A1181151ADA8000860DA /* otb */,
+			);
+			name = ossim;
+			sourceTree = "<group>";
+		};
+		43A9A0E21151ADA7000860DA /* erssar */ = {
+			isa = PBXGroup;
+			children = (
+				43A9A0E31151ADA7000860DA /* ErsSarDataSetSummary.cpp */,
+				43A9A0E41151ADA7000860DA /* ErsSarDataSetSummary.h */,
+				43A9A0E51151ADA7000860DA /* ErsSarFacilityData.cpp */,
+				43A9A0E61151ADA7000860DA /* ErsSarFacilityData.h */,
+				43A9A0E71151ADA7000860DA /* ErsSarFileDescriptor.cpp */,
+				43A9A0E81151ADA7000860DA /* ErsSarFileDescriptor.h */,
+				43A9A0E91151ADA7000860DA /* ErsSarLeader.cpp */,
+				43A9A0EA1151ADA7000860DA /* ErsSarLeader.h */,
+				43A9A0EB1151ADA7000860DA /* ErsSarLeaderFactory.cpp */,
+				43A9A0EC1151ADA7000860DA /* ErsSarLeaderFactory.h */,
+				43A9A0ED1151ADA7000860DA /* ErsSarMapProjectionData.cpp */,
+				43A9A0EE1151ADA7000860DA /* ErsSarMapProjectionData.h */,
+				43A9A0EF1151ADA7000860DA /* ErsSarPlatformPositionData.cpp */,
+				43A9A0F01151ADA7000860DA /* ErsSarPlatformPositionData.h */,
+				43A9A0F11151ADA7000860DA /* ErsSarPositionVectorRecord.cpp */,
+				43A9A0F21151ADA7000860DA /* ErsSarPositionVectorRecord.h */,
+				43A9A0F31151ADA7000860DA /* ErsSarRecord.cpp */,
+				43A9A0F41151ADA7000860DA /* ErsSarRecord.h */,
+				43A9A0F51151ADA7000860DA /* ErsSarRecordFactory.cpp */,
+				43A9A0F61151ADA7000860DA /* ErsSarRecordFactory.h */,
+				43A9A0F71151ADA7000860DA /* ErsSarRecordHeader.cpp */,
+				43A9A0F81151ADA7000860DA /* ErsSarRecordHeader.h */,
+				43A9A0F91151ADA7000860DA /* Makefile */,
+				43A9A0FA1151ADA7000860DA /* makefile.vc */,
+			);
+			name = erssar;
+			path = ../ossim/erssar;
+			sourceTree = SOURCE_ROOT;
+		};
+		43A9A1181151ADA8000860DA /* otb */ = {
+			isa = PBXGroup;
+			children = (
+				43A9A1191151ADA8000860DA /* Arithmetic.h */,
+				43A9A11A1151ADA8000860DA /* CivilDateTime.cpp */,
+				43A9A11B1151ADA8000860DA /* CivilDateTime.h */,
+				43A9A11C1151ADA8000860DA /* Coordinate.cpp */,
+				43A9A11D1151ADA8000860DA /* Coordinate.h */,
+				43A9A11E1151ADA8000860DA /* Ephemeris.cpp */,
+				43A9A11F1151ADA8000860DA /* Ephemeris.h */,
+				43A9A1201151ADA8000860DA /* Equation.cpp */,
+				43A9A1211151ADA8000860DA /* Equation.h */,
+				43A9A1221151ADA8000860DA /* GalileanEphemeris.cpp */,
+				43A9A1231151ADA8000860DA /* GalileanEphemeris.h */,
+				43A9A1241151ADA8000860DA /* GeodesicCoordinate.cpp */,
+				43A9A1251151ADA8000860DA /* GeodesicCoordinate.h */,
+				43A9A1261151ADA8000860DA /* GeographicEphemeris.cpp */,
+				43A9A1271151ADA8000860DA /* GeographicEphemeris.h */,
+				43A9A1281151ADA8000860DA /* GMSTDateTime.cpp */,
+				43A9A1291151ADA8000860DA /* GMSTDateTime.h */,
+				43A9A12A1151ADA8000860DA /* HermiteInterpolator.cpp */,
+				43A9A12B1151ADA8000860DA /* HermiteInterpolator.h */,
+				43A9A12C1151ADA8000860DA /* ImageNoise.cpp */,
+				43A9A12D1151ADA8000860DA /* ImageNoise.h */,
+				43A9A12E1151ADA8000860DA /* JSDDateTime.cpp */,
+				43A9A12F1151ADA8000860DA /* JSDDateTime.h */,
+				43A9A1301151ADA8000860DA /* JulianDate.cpp */,
+				43A9A1311151ADA8000860DA /* JulianDate.h */,
+				43A9A1321151ADA8000860DA /* Makefile */,
+				43A9A1331151ADA8000860DA /* makefile.vc */,
+				43A9A1341151ADA8000860DA /* MJDDateTime.cpp */,
+				43A9A1351151ADA8000860DA /* MJDDateTime.h */,
+				43A9A1361151ADA8000860DA /* Noise.cpp */,
+				43A9A1371151ADA8000860DA /* Noise.h */,
+				43A9A1381151ADA8000860DA /* PlatformPosition.cpp */,
+				43A9A1391151ADA8000860DA /* PlatformPosition.h */,
+				43A9A13A1151ADA8000860DA /* RectangularCoordinate.cpp */,
+				43A9A13B1151ADA8000860DA /* RectangularCoordinate.h */,
+				43A9A13C1151ADA8000860DA /* RefPoint.cpp */,
+				43A9A13D1151ADA8000860DA /* RefPoint.h */,
+				43A9A13E1151ADA8000860DA /* SarSensor.cpp */,
+				43A9A13F1151ADA8000860DA /* SarSensor.h */,
+				43A9A1401151ADA8000860DA /* Sensor.cpp */,
+				43A9A1411151ADA8000860DA /* Sensor.h */,
+				43A9A1421151ADA8000860DA /* SensorParams.cpp */,
+				43A9A1431151ADA8000860DA /* SensorParams.h */,
+			);
+			name = otb;
+			path = ../ossim/otb;
+			sourceTree = SOURCE_ROOT;
+		};
+		EE69A3810B28850A00C91DD1 /* Products */ = {
+			isa = PBXGroup;
+			children = (
+				EE69A3850B28850A00C91DD1 /* wms.framework */,
+				EEB7D1540E77F4DD007DA09C /* wmsurl */,
+				EEB7D1560E77F4DD007DA09C /* wmscapabilities.cpp */,
+				EEB7D1580E77F4DD007DA09C /* wmsgetmap */,
+			);
+			name = Products;
+			sourceTree = "<group>";
+		};
+		EE80314B0F138F5500BB8BBB /* nitro */ = {
+			isa = PBXGroup;
+			children = (
+				EE8031B70F13A6A200BB8BBB /* ossimNitroImageHandlerFactory.cpp */,
+				EE8031B80F13A6A200BB8BBB /* ossimNitroImageHandlerFactory.h */,
+				EE8031650F13952700BB8BBB /* ossimNitroHandler.cpp */,
+				EE8031610F13932A00BB8BBB /* ossimNitroHandler.h */,
+				EE80314D0F138F5500BB8BBB /* ossimNitroPluginInit.cpp */,
+			);
+			name = nitro;
+			path = ../nitro;
+			sourceTree = SOURCE_ROOT;
+		};
+		EEA720BC0B2F431F006E37B7 /* contrib */ = {
+			isa = PBXGroup;
+			children = (
+				EEA720BD0B2F4331006E37B7 /* ossimContribImageSourceFactory.cpp */,
+				EEA720BE0B2F4331006E37B7 /* ossimContribPluginInit.cpp */,
+				EEA720BF0B2F4331006E37B7 /* ossimCFARFilter.cpp */,
+				EEA720C00B2F4331006E37B7 /* ossimContribImageSourceFactory.h */,
+				EEA720C10B2F4331006E37B7 /* ossimSPOTNatural.cpp */,
+				EEA720C20B2F4331006E37B7 /* ossimSPOTNatural.h */,
+				EEA720C30B2F4331006E37B7 /* ossimComplexAbs.cpp */,
+				EEA720C40B2F4331006E37B7 /* ossimComplexAbs.h */,
+				EEA720C50B2F4331006E37B7 /* ossimContribExports.h */,
+				EEA720C60B2F4331006E37B7 /* ossimCFARFilter.h */,
+			);
+			name = contrib;
+			sourceTree = "<group>";
+		};
+/* End PBXGroup section */
+
+/* Begin PBXHeadersBuildPhase section */
+		186EF8690B1F184C00F7886A /* Headers */ = {
+			isa = PBXHeadersBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				EEA3C4A60E3FA61C00CAAC1A /* ossimEsriShapeFileFilter.h in Headers */,
+				EEA3C4A80E3FA61C00CAAC1A /* ossimGdalDataset.h in Headers */,
+				EEA3C4AA0E3FA61C00CAAC1A /* ossimGdalFactory.h in Headers */,
+				EEA3C4AC0E3FA61C00CAAC1A /* ossimGdalImageWriterFactory.h in Headers */,
+				EEA3C4AE0E3FA61C00CAAC1A /* ossimGdalObjectFactory.h in Headers */,
+				EEA3C4B00E3FA61C00CAAC1A /* ossimGdalOgrVectorAnnotation.h in Headers */,
+				EEA3C4B20E3FA61C00CAAC1A /* ossimGdalOverviewBuilder.h in Headers */,
+				EEA3C4B40E3FA61C00CAAC1A /* ossimGdalOverviewBuilderFactory.h in Headers */,
+				EEA3C4B70E3FA61C00CAAC1A /* ossimGdalProjectionFactory.h in Headers */,
+				EEA3C4B90E3FA61C00CAAC1A /* ossimGdalTiledDataset.h in Headers */,
+				EEA3C4BB0E3FA61C00CAAC1A /* ossimGdalTileSource.h in Headers */,
+				EEA3C4BD0E3FA61C00CAAC1A /* ossimGdalType.h in Headers */,
+				EEA3C4BF0E3FA61C00CAAC1A /* ossimGdalWriter.h in Headers */,
+				EEA3C4C10E3FA61C00CAAC1A /* ossimOgcWktTranslator.h in Headers */,
+				EEA3C4C30E3FA61C00CAAC1A /* ossimOgrGdalTileSource.h in Headers */,
+				EEA3C4C50E3FA61C00CAAC1A /* ossimShapeDatabase.h in Headers */,
+				EEA3C4C70E3FA61C00CAAC1A /* ossimShapeFile.h in Headers */,
+				EEA3C4C80E3FA61C00CAAC1A /* shapefil.h in Headers */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		186EF97E0B1F222500F7886A /* Headers */ = {
+			isa = PBXHeadersBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				186EF9AB0B1F236800F7886A /* ossimChipMatch.h in Headers */,
+				186EF9AD0B1F236800F7886A /* ossimDensityReducer.h in Headers */,
+				186EF9AF0B1F236800F7886A /* ossimExtremaFilter.h in Headers */,
+				186EF9B10B1F236800F7886A /* ossimHarrisCorners.h in Headers */,
+				186EF9B30B1F236800F7886A /* ossimImageCorrelator.h in Headers */,
+				186EF9B50B1F236800F7886A /* ossimModelOptimizer.h in Headers */,
+				186EF9B70B1F236800F7886A /* ossimMultiplier.h in Headers */,
+				186EF9B90B1F236800F7886A /* ossimNCC_FFTW.h in Headers */,
+				186EF9BB0B1F236800F7886A /* ossimOutlierRejection.h in Headers */,
+				186EF9BC0B1F236800F7886A /* ossimRegistrationExports.h in Headers */,
+				186EF9BE0B1F236800F7886A /* ossimRegistrationImageSourceFactory.h in Headers */,
+				186EF9C00B1F236800F7886A /* ossimRegistrationMiscFactory.h in Headers */,
+				186EF9C30B1F236800F7886A /* ossimRunningSum.h in Headers */,
+				186EF9C50B1F236800F7886A /* ossimSquareFunction.h in Headers */,
+				186EF9C70B1F236800F7886A /* ossimTieGenerator.h in Headers */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		186EFA180B1F321200F7886A /* Headers */ = {
+			isa = PBXHeadersBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				186EFA340B1F32FF00F7886A /* ossimDiskCache.h in Headers */,
+				186EFA360B1F32FF00F7886A /* ossimSharedDiskCacheManager.h in Headers */,
+				186EFA370B1F32FF00F7886A /* ossimWorldWindExports.h in Headers */,
+				186EFA390B1F32FF00F7886A /* ossimWorldWindFactory.h in Headers */,
+				186EFA3B0B1F32FF00F7886A /* ossimWorldWindHandler.h in Headers */,
+				186EFA3D0B1F32FF00F7886A /* ossimWorldWindJpegImage.h in Headers */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		186EFA5B0B1F394100F7886A /* Headers */ = {
+			isa = PBXHeadersBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				186EFA6E0B1F39FD00F7886A /* ossimNuiHandler.h in Headers */,
+				186EFA700B1F39FD00F7886A /* ossimNuiFactory.h in Headers */,
+				186EFA720B1F39FD00F7886A /* ossimNuiExports.h in Headers */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		430D1FCE0BB2F96B0057E5FF /* Headers */ = {
+			isa = PBXHeadersBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				430D20830BB2FA450057E5FF /* ossimPngReaderFactory.h in Headers */,
+				430D20840BB2FA450057E5FF /* ossimPngWriterFactory.h in Headers */,
+				430D20890BB2FA450057E5FF /* ossimPngWriter.h in Headers */,
+				430D208B0BB2FA450057E5FF /* ossimPngReader.h in Headers */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		431320FD103C84DF00F96FDF /* Headers */ = {
+			isa = PBXHeadersBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				436A7F4B10FBB24200985348 /* ossimKakaduCompressor.h in Headers */,
+				436A7F4C10FBB24200985348 /* ossimKakaduOverviewBuilderFactory.h in Headers */,
+				436A7F4D10FBB24200985348 /* ossimKakaduNitfWriter.h in Headers */,
+				436A7F4E10FBB24200985348 /* ossimKakaduMessaging.h in Headers */,
+				436A7F4F10FBB24200985348 /* ossimKakaduKeywords.h in Headers */,
+				436A7F5010FBB24200985348 /* ossimKakaduJp2Reader.h in Headers */,
+				436A7F5110FBB24200985348 /* ossimKakaduReaderFactory.h in Headers */,
+				436A7F5310FBB24200985348 /* ossimKakaduCompressedTarget.h in Headers */,
+				436A7F5410FBB24200985348 /* ossimKakaduJ2kReader.h in Headers */,
+				436A7F5710FBB24200985348 /* ossimKakaduNitfOverviewBuilder.h in Headers */,
+				436A7F5B10FBB24200985348 /* ossimKakaduJp2Writer.h in Headers */,
+				436A7F5D10FBB24200985348 /* ossimKakaduCommon.h in Headers */,
+				436A7F5E10FBB24200985348 /* ossimKakaduWriterFactory.h in Headers */,
+				436A7F6010FBB24200985348 /* ossimKakaduNitfReader.h in Headers */,
+				4310BA77110DD27C00C258B9 /* jp2_local.h in Headers */,
+				4310BA78110DD27C00C258B9 /* jp2_shared.h in Headers */,
+				4310BA7A110DD27C00C258B9 /* jpx_local.h in Headers */,
+				4310BA7C110DD27C00C258B9 /* mj2_local.h in Headers */,
+				4391B4DA110F6D0400B5895E /* kdu_region_decompressor.h in Headers */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		43377EF110CFFAC900ECC5AD /* Headers */ = {
+			isa = PBXHeadersBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				43377F0610CFFB6400ECC5AD /* ossimCsmSensorModel.h in Headers */,
+				43377F0710CFFB6400ECC5AD /* ossimCsmProjectionFactory.h in Headers */,
+				43378A0310D01EFD00ECC5AD /* ossimCsmSupport.h in Headers */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		436A7E1510FB9FC400985348 /* Headers */ = {
+			isa = PBXHeadersBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				436A7E4C10FBA00100985348 /* ossimMrSidReader.h in Headers */,
+				436A7E4E10FBA00100985348 /* ossimMrSidWriter.h in Headers */,
+				436A7E5010FBA00100985348 /* ossimMrSidWriterFactory.h in Headers */,
+				436A7E5310FBA00100985348 /* ossimMrSidReaderFactory.h in Headers */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		43A9A09A1151AC37000860DA /* Headers */ = {
+			isa = PBXHeadersBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				43A9A1451151ADA8000860DA /* ErsSarDataSetSummary.h in Headers */,
+				43A9A1471151ADA8000860DA /* ErsSarFacilityData.h in Headers */,
+				43A9A1491151ADA8000860DA /* ErsSarFileDescriptor.h in Headers */,
+				43A9A14B1151ADA8000860DA /* ErsSarLeader.h in Headers */,
+				43A9A14D1151ADA8000860DA /* ErsSarLeaderFactory.h in Headers */,
+				43A9A14F1151ADA8000860DA /* ErsSarMapProjectionData.h in Headers */,
+				43A9A1511151ADA8000860DA /* ErsSarPlatformPositionData.h in Headers */,
+				43A9A1531151ADA8000860DA /* ErsSarPositionVectorRecord.h in Headers */,
+				43A9A1551151ADA8000860DA /* ErsSarRecord.h in Headers */,
+				43A9A1571151ADA8000860DA /* ErsSarRecordFactory.h in Headers */,
+				43A9A1591151ADA8000860DA /* ErsSarRecordHeader.h in Headers */,
+				43A9A15C1151ADA8000860DA /* ossimCosmoSkymedModel.h in Headers */,
+				43A9A15E1151ADA8000860DA /* ossimEnvisatAsarModel.h in Headers */,
+				43A9A1601151ADA8000860DA /* ossimErsSarModel.h in Headers */,
+				43A9A1621151ADA8000860DA /* ossimGeometricSarSensorModel.h in Headers */,
+				43A9A1641151ADA8000860DA /* ossimPluginCommon.h in Headers */,
+				43A9A1671151ADA8000860DA /* ossimPluginProjectionFactory.h in Headers */,
+				43A9A1691151ADA8000860DA /* ossimPluginReaderFactory.h in Headers */,
+				43A9A16B1151ADA8000860DA /* ossimRadarSat2Model.h in Headers */,
+				43A9A16D1151ADA8000860DA /* ossimRadarSat2ProductDoc.h in Headers */,
+				43A9A16F1151ADA8000860DA /* ossimRadarSat2RPCModel.h in Headers */,
+				43A9A1711151ADA8000860DA /* ossimRadarSatModel.h in Headers */,
+				43A9A1731151ADA8000860DA /* ossimTerraSarModel.h in Headers */,
+				43A9A1751151ADA8000860DA /* ossimTerraSarProductDoc.h in Headers */,
+				43A9A1771151ADA8000860DA /* ossimTerraSarTiffReader.h in Headers */,
+				43A9A1781151ADA8000860DA /* Arithmetic.h in Headers */,
+				43A9A17A1151ADA8000860DA /* CivilDateTime.h in Headers */,
+				43A9A17C1151ADA8000860DA /* Coordinate.h in Headers */,
+				43A9A17E1151ADA8000860DA /* Ephemeris.h in Headers */,
+				43A9A1801151ADA8000860DA /* Equation.h in Headers */,
+				43A9A1821151ADA8000860DA /* GalileanEphemeris.h in Headers */,
+				43A9A1841151ADA8000860DA /* GeodesicCoordinate.h in Headers */,
+				43A9A1861151ADA8000860DA /* GeographicEphemeris.h in Headers */,
+				43A9A1881151ADA8000860DA /* GMSTDateTime.h in Headers */,
+				43A9A18A1151ADA8000860DA /* HermiteInterpolator.h in Headers */,
+				43A9A18C1151ADA8000860DA /* ImageNoise.h in Headers */,
+				43A9A18E1151ADA8000860DA /* JSDDateTime.h in Headers */,
+				43A9A1901151ADA8000860DA /* JulianDate.h in Headers */,
+				43A9A1931151ADA8000860DA /* MJDDateTime.h in Headers */,
+				43A9A1951151ADA8000860DA /* Noise.h in Headers */,
+				43A9A1971151ADA8000860DA /* PlatformPosition.h in Headers */,
+				43A9A1991151ADA8000860DA /* RectangularCoordinate.h in Headers */,
+				43A9A19B1151ADA8000860DA /* RefPoint.h in Headers */,
+				43A9A19D1151ADA8000860DA /* SarSensor.h in Headers */,
+				43A9A19F1151ADA8000860DA /* Sensor.h in Headers */,
+				43A9A1A11151ADA8000860DA /* SensorParams.h in Headers */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		EEA720150B2F4256006E37B7 /* Headers */ = {
+			isa = PBXHeadersBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				EEA720CA0B2F4331006E37B7 /* ossimContribImageSourceFactory.h in Headers */,
+				EEA720CC0B2F4331006E37B7 /* ossimSPOTNatural.h in Headers */,
+				EEA720CE0B2F4331006E37B7 /* ossimComplexAbs.h in Headers */,
+				EEA720CF0B2F4331006E37B7 /* ossimContribExports.h in Headers */,
+				EEA720D00B2F4331006E37B7 /* ossimCFARFilter.h in Headers */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXHeadersBuildPhase section */
+
+/* Begin PBXNativeTarget section */
+		186EF86C0B1F184C00F7886A /* ossimgdal_plugin */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 186EF86F0B1F184C00F7886A /* Build configuration list for PBXNativeTarget "ossimgdal_plugin" */;
+			buildPhases = (
+				186EF8690B1F184C00F7886A /* Headers */,
+				186EF86A0B1F184C00F7886A /* Sources */,
+				186EF86B0B1F184C00F7886A /* Frameworks */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = ossimgdal_plugin;
+			productName = ossimgdal_plugin;
+			productReference = 186EF86D0B1F184C00F7886A /* libossimgdal_plugin.dylib */;
+			productType = "com.apple.product-type.library.dynamic";
+		};
+		186EF9810B1F222500F7886A /* ossimreg_plugin */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 186EF9870B1F226200F7886A /* Build configuration list for PBXNativeTarget "ossimreg_plugin" */;
+			buildPhases = (
+				186EF97E0B1F222500F7886A /* Headers */,
+				186EF97F0B1F222500F7886A /* Sources */,
+				186EF9800B1F222500F7886A /* Frameworks */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = ossimreg_plugin;
+			productName = ossimreg_plugin;
+			productReference = 186EF9820B1F222500F7886A /* libossimreg_plugin.dylib */;
+			productType = "com.apple.product-type.library.dynamic";
+		};
+		186EFA1B0B1F321200F7886A /* ossimworldwind_plugin */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 186EFA220B1F323800F7886A /* Build configuration list for PBXNativeTarget "ossimworldwind_plugin" */;
+			buildPhases = (
+				186EFA180B1F321200F7886A /* Headers */,
+				186EFA190B1F321200F7886A /* Sources */,
+				186EFA1A0B1F321200F7886A /* Frameworks */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+				430EAEE50C6A4E8800E6661B /* PBXTargetDependency */,
+			);
+			name = ossimworldwind_plugin;
+			productName = ossimworldwind_plugin;
+			productReference = 186EFA1C0B1F321200F7886A /* libossimworldwind_plugin.dylib */;
+			productType = "com.apple.product-type.library.dynamic";
+		};
+		186EFA5E0B1F394100F7886A /* ossimnui_plugin */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 186EFA630B1F396700F7886A /* Build configuration list for PBXNativeTarget "ossimnui_plugin" */;
+			buildPhases = (
+				186EFA5B0B1F394100F7886A /* Headers */,
+				186EFA5C0B1F394100F7886A /* Sources */,
+				186EFA5D0B1F394100F7886A /* Frameworks */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = ossimnui_plugin;
+			productName = ossim_nui_plugin;
+			productReference = 186EFA5F0B1F394100F7886A /* libossimnui_plugin.dylib */;
+			productType = "com.apple.product-type.library.dynamic";
+		};
+		430D1FCD0BB2F96B0057E5FF /* ossimpng_plugin */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 430D1FDE0BB2F96B0057E5FF /* Build configuration list for PBXNativeTarget "ossimpng_plugin" */;
+			buildPhases = (
+				430D1FCE0BB2F96B0057E5FF /* Headers */,
+				430D1FD40BB2F96B0057E5FF /* Sources */,
+				430D1FDA0BB2F96B0057E5FF /* Frameworks */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = ossimpng_plugin;
+			productName = ossim_nui_plugin;
+			productReference = 430D1FE10BB2F96B0057E5FF /* libossimpng_plugin.dylib */;
+			productType = "com.apple.product-type.library.dynamic";
+		};
+		431320FC103C84DF00F96FDF /* ossimkakadu_plugin */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 4313210C103C84DF00F96FDF /* Build configuration list for PBXNativeTarget "ossimkakadu_plugin" */;
+			buildPhases = (
+				431320FD103C84DF00F96FDF /* Headers */,
+				43132103103C84DF00F96FDF /* Sources */,
+				43132109103C84DF00F96FDF /* Frameworks */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = ossimkakadu_plugin;
+			productName = ossim_nui_plugin;
+			productReference = 43132112103C84DF00F96FDF /* libossimkakadu_plugin.dylib */;
+			productType = "com.apple.product-type.library.dynamic";
+		};
+		43377EF410CFFAC900ECC5AD /* ossimcsm_plugin */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 43377EFE10CFFAE800ECC5AD /* Build configuration list for PBXNativeTarget "ossimcsm_plugin" */;
+			buildPhases = (
+				43377EF110CFFAC900ECC5AD /* Headers */,
+				43377EF210CFFAC900ECC5AD /* Sources */,
+				43377EF310CFFAC900ECC5AD /* Frameworks */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+				43F4581A10FCDAFA002B9133 /* PBXTargetDependency */,
+			);
+			name = ossimcsm_plugin;
+			productName = ossimcsm_plugin;
+			productReference = 43377EF510CFFAC900ECC5AD /* libossimcsm_plugin.dylib */;
+			productType = "com.apple.product-type.library.dynamic";
+		};
+		436A7E1410FB9FC400985348 /* ossimmrsid_plugin */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 436A7E2F10FB9FC400985348 /* Build configuration list for PBXNativeTarget "ossimmrsid_plugin" */;
+			buildPhases = (
+				436A7E1510FB9FC400985348 /* Headers */,
+				436A7E2010FB9FC400985348 /* Sources */,
+				436A7E2B10FB9FC400985348 /* Frameworks */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = ossimmrsid_plugin;
+			productName = ossim_nui_plugin;
+			productReference = 436A7E3510FB9FC400985348 /* libossimmrsid_plugin.dylib */;
+			productType = "com.apple.product-type.library.dynamic";
+		};
+		43A9A0991151AC37000860DA /* ossim_plugin */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 43A9A0A81151AC37000860DA /* Build configuration list for PBXNativeTarget "ossim_plugin" */;
+			buildPhases = (
+				43A9A09A1151AC37000860DA /* Headers */,
+				43A9A09F1151AC37000860DA /* Sources */,
+				43A9A0A51151AC37000860DA /* Frameworks */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = ossim_plugin;
+			productName = ossim_nui_plugin;
+			productReference = 43A9A0AE1151AC37000860DA /* libossim_plugin.dylib */;
+			productType = "com.apple.product-type.library.dynamic";
+		};
+		EEA720140B2F4256006E37B7 /* ossimcontrib_plugin */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = EEA720240B2F4256006E37B7 /* Build configuration list for PBXNativeTarget "ossimcontrib_plugin" */;
+			buildPhases = (
+				EEA720150B2F4256006E37B7 /* Headers */,
+				EEA720190B2F4256006E37B7 /* Sources */,
+				EEA7201D0B2F4256006E37B7 /* Frameworks */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = ossimcontrib_plugin;
+			productName = ossim_nui_plugin;
+			productReference = EEA720270B2F4256006E37B7 /* libossimcontrib_plugin.dylib */;
+			productType = "com.apple.product-type.library.dynamic";
+		};
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+		186EF84C0B1F0A5000F7886A /* Project object */ = {
+			isa = PBXProject;
+			buildConfigurationList = 186EF84D0B1F0A5000F7886A /* Build configuration list for PBXProject "ossim_plugins" */;
+			compatibilityVersion = "Xcode 2.4";
+			hasScannedForEncodings = 0;
+			mainGroup = 186EF84A0B1F0A5000F7886A;
+			productRefGroup = 186EF86E0B1F184C00F7886A /* Products */;
+			projectDirPath = "";
+			projectReferences = (
+				{
+					ProductGroup = EE69A3810B28850A00C91DD1 /* Products */;
+					ProjectRef = EE69A3800B28850A00C91DD1 /* libwms.xcodeproj */;
+				},
+				{
+					ProductGroup = 186EF8AB0B1F19E400F7886A /* Products */;
+					ProjectRef = 186EF8AA0B1F19E400F7886A /* ossim.xcodeproj */;
+				},
+			);
+			projectRoot = "";
+			targets = (
+				186EF86C0B1F184C00F7886A /* ossimgdal_plugin */,
+				186EF9810B1F222500F7886A /* ossimreg_plugin */,
+				186EFA1B0B1F321200F7886A /* ossimworldwind_plugin */,
+				186EFA5E0B1F394100F7886A /* ossimnui_plugin */,
+				EEA720140B2F4256006E37B7 /* ossimcontrib_plugin */,
+				430D1FCD0BB2F96B0057E5FF /* ossimpng_plugin */,
+				431320FC103C84DF00F96FDF /* ossimkakadu_plugin */,
+				43377EF410CFFAC900ECC5AD /* ossimcsm_plugin */,
+				436A7E1410FB9FC400985348 /* ossimmrsid_plugin */,
+				43A9A0991151AC37000860DA /* ossim_plugin */,
+				43378DC010D021ED00ECC5AD /* All */,
+			);
+		};
+/* End PBXProject section */
+
+/* Begin PBXReferenceProxy section */
+		186EF8EA0B1F19E400F7886A /* ossim.framework */ = {
+			isa = PBXReferenceProxy;
+			fileType = wrapper.framework;
+			path = ossim.framework;
+			remoteRef = 186EF8E90B1F19E400F7886A /* PBXContainerItemProxy */;
+			sourceTree = BUILT_PRODUCTS_DIR;
+		};
+		4353102910440474004A4474 /* template-app */ = {
+			isa = PBXReferenceProxy;
+			fileType = "compiled.mach-o.executable";
+			path = "template-app";
+			remoteRef = 4353102810440474004A4474 /* PBXContainerItemProxy */;
+			sourceTree = BUILT_PRODUCTS_DIR;
+		};
+		4353102B10440474004A4474 /* ossim-adrg-dump */ = {
+			isa = PBXReferenceProxy;
+			fileType = "compiled.mach-o.executable";
+			path = "ossim-adrg-dump";
+			remoteRef = 4353102A10440474004A4474 /* PBXContainerItemProxy */;
+			sourceTree = BUILT_PRODUCTS_DIR;
+		};
+		4353102D10440474004A4474 /* ossim-applanix2ogeom */ = {
+			isa = PBXReferenceProxy;
+			fileType = "compiled.mach-o.executable";
+			path = "ossim-applanix2ogeom";
+			remoteRef = 4353102C10440474004A4474 /* PBXContainerItemProxy */;
+			sourceTree = BUILT_PRODUCTS_DIR;
+		};
+		4353102F10440474004A4474 /* ossim-band-merge */ = {
+			isa = PBXReferenceProxy;
+			fileType = "compiled.mach-o.executable";
+			path = "ossim-band-merge";
+			remoteRef = 4353102E10440474004A4474 /* PBXContainerItemProxy */;
+			sourceTree = BUILT_PRODUCTS_DIR;
+		};
+		4353103110440474004A4474 /* ossim-btoa */ = {
+			isa = PBXReferenceProxy;
+			fileType = "compiled.mach-o.executable";
+			path = "ossim-btoa";
+			remoteRef = 4353103010440474004A4474 /* PBXContainerItemProxy */;
+			sourceTree = BUILT_PRODUCTS_DIR;
+		};
+		4353103310440474004A4474 /* template-app */ = {
+			isa = PBXReferenceProxy;
+			fileType = "compiled.mach-o.executable";
+			path = "template-app";
+			remoteRef = 4353103210440474004A4474 /* PBXContainerItemProxy */;
+			sourceTree = BUILT_PRODUCTS_DIR;
+		};
+		4353103510440474004A4474 /* ossim-cmm */ = {
+			isa = PBXReferenceProxy;
+			fileType = "compiled.mach-o.executable";
+			path = "ossim-cmm";
+			remoteRef = 4353103410440474004A4474 /* PBXContainerItemProxy */;
+			sourceTree = BUILT_PRODUCTS_DIR;
+		};
+		4353103710440474004A4474 /* ossim-computeSrtmStats */ = {
+			isa = PBXReferenceProxy;
+			fileType = "compiled.mach-o.executable";
+			path = "ossim-computeSrtmStats";
+			remoteRef = 4353103610440474004A4474 /* PBXContainerItemProxy */;
+			sourceTree = BUILT_PRODUCTS_DIR;
+		};
+		4353103910440474004A4474 /* ossim-correl */ = {
+			isa = PBXReferenceProxy;
+			fileType = "compiled.mach-o.executable";
+			path = "ossim-correl";
+			remoteRef = 4353103810440474004A4474 /* PBXContainerItemProxy */;
+			sourceTree = BUILT_PRODUCTS_DIR;
+		};
+		4353103B10440474004A4474 /* ossim-create-cg */ = {
+			isa = PBXReferenceProxy;
+			fileType = "compiled.mach-o.executable";
+			path = "ossim-create-cg";
+			remoteRef = 4353103A10440474004A4474 /* PBXContainerItemProxy */;
+			sourceTree = BUILT_PRODUCTS_DIR;
+		};
+		4353103D10440474004A4474 /* ossim-create-histo */ = {
+			isa = PBXReferenceProxy;
+			fileType = "compiled.mach-o.executable";
+			path = "ossim-create-histo";
+			remoteRef = 4353103C10440474004A4474 /* PBXContainerItemProxy */;
+			sourceTree = BUILT_PRODUCTS_DIR;
+		};
+		4353104510440474004A4474 /* ossim-dms2deg */ = {
+			isa = PBXReferenceProxy;
+			fileType = "compiled.mach-o.executable";
+			path = "ossim-dms2deg";
+			remoteRef = 4353104410440474004A4474 /* PBXContainerItemProxy */;
+			sourceTree = BUILT_PRODUCTS_DIR;
+		};
+		4353104710440474004A4474 /* ossim-dump-ocg */ = {
+			isa = PBXReferenceProxy;
+			fileType = "compiled.mach-o.executable";
+			path = "ossim-dump-ocg";
+			remoteRef = 4353104610440474004A4474 /* PBXContainerItemProxy */;
+			sourceTree = BUILT_PRODUCTS_DIR;
+		};
+		4353104910440474004A4474 /* ossim-ecg2ocg */ = {
+			isa = PBXReferenceProxy;
+			fileType = "compiled.mach-o.executable";
+			path = "ossim-ecg2ocg";
+			remoteRef = 4353104810440474004A4474 /* PBXContainerItemProxy */;
+			sourceTree = BUILT_PRODUCTS_DIR;
+		};
+		4353104B10440474004A4474 /* ossim-extract-vertices */ = {
+			isa = PBXReferenceProxy;
+			fileType = "compiled.mach-o.executable";
+			path = "ossim-extract-vertices";
+			remoteRef = 4353104A10440474004A4474 /* PBXContainerItemProxy */;
+			sourceTree = BUILT_PRODUCTS_DIR;
+		};
+		4353104D10440474004A4474 /* ossim-foo */ = {
+			isa = PBXReferenceProxy;
+			fileType = "compiled.mach-o.executable";
+			path = "ossim-foo";
+			remoteRef = 4353104C10440474004A4474 /* PBXContainerItemProxy */;
+			sourceTree = BUILT_PRODUCTS_DIR;
+		};
+		4353105110440474004A4474 /* ossim-height */ = {
+			isa = PBXReferenceProxy;
+			fileType = "compiled.mach-o.executable";
+			path = "ossim-height";
+			remoteRef = 4353105010440474004A4474 /* PBXContainerItemProxy */;
+			sourceTree = BUILT_PRODUCTS_DIR;
+		};
+		4353105310440474004A4474 /* ossim-icp */ = {
+			isa = PBXReferenceProxy;
+			fileType = "compiled.mach-o.executable";
+			path = "ossim-icp";
+			remoteRef = 4353105210440474004A4474 /* PBXContainerItemProxy */;
+			sourceTree = BUILT_PRODUCTS_DIR;
+		};
+		4353105510440474004A4474 /* ossim-igen */ = {
+			isa = PBXReferenceProxy;
+			fileType = "compiled.mach-o.executable";
+			path = "ossim-igen";
+			remoteRef = 4353105410440474004A4474 /* PBXContainerItemProxy */;
+			sourceTree = BUILT_PRODUCTS_DIR;
+		};
+		4353105710440474004A4474 /* ossim-img2md */ = {
+			isa = PBXReferenceProxy;
+			fileType = "compiled.mach-o.executable";
+			path = "ossim-img2md";
+			remoteRef = 4353105610440474004A4474 /* PBXContainerItemProxy */;
+			sourceTree = BUILT_PRODUCTS_DIR;
+		};
+		4353105910440474004A4474 /* ossim-img2rr */ = {
+			isa = PBXReferenceProxy;
+			fileType = "compiled.mach-o.executable";
+			path = "ossim-img2rr";
+			remoteRef = 4353105810440474004A4474 /* PBXContainerItemProxy */;
+			sourceTree = BUILT_PRODUCTS_DIR;
+		};
+		4353105B10440474004A4474 /* ossim-info */ = {
+			isa = PBXReferenceProxy;
+			fileType = "compiled.mach-o.executable";
+			path = "ossim-info";
+			remoteRef = 4353105A10440474004A4474 /* PBXContainerItemProxy */;
+			sourceTree = BUILT_PRODUCTS_DIR;
+		};
+		4353105D10440474004A4474 /* ossim-modopt */ = {
+			isa = PBXReferenceProxy;
+			fileType = "compiled.mach-o.executable";
+			path = "ossim-modopt";
+			remoteRef = 4353105C10440474004A4474 /* PBXContainerItemProxy */;
+			sourceTree = BUILT_PRODUCTS_DIR;
+		};
+		4353105F10440474004A4474 /* ossim-mosaic */ = {
+			isa = PBXReferenceProxy;
+			fileType = "compiled.mach-o.executable";
+			path = "ossim-mosaic";
+			remoteRef = 4353105E10440474004A4474 /* PBXContainerItemProxy */;
+			sourceTree = BUILT_PRODUCTS_DIR;
+		};
+		4353106510440474004A4474 /* ossim-ogeom2ogeom */ = {
+			isa = PBXReferenceProxy;
+			fileType = "compiled.mach-o.executable";
+			path = "ossim-ogeom2ogeom";
+			remoteRef = 4353106410440474004A4474 /* PBXContainerItemProxy */;
+			sourceTree = BUILT_PRODUCTS_DIR;
+		};
+		4353106710440474004A4474 /* ossim-orthoigen */ = {
+			isa = PBXReferenceProxy;
+			fileType = "compiled.mach-o.executable";
+			path = "ossim-orthoigen";
+			remoteRef = 4353106610440474004A4474 /* PBXContainerItemProxy */;
+			sourceTree = BUILT_PRODUCTS_DIR;
+		};
+		4353106910440474004A4474 /* ossim-pixelflip */ = {
+			isa = PBXReferenceProxy;
+			fileType = "compiled.mach-o.executable";
+			path = "ossim-pixelflip";
+			remoteRef = 4353106810440474004A4474 /* PBXContainerItemProxy */;
+			sourceTree = BUILT_PRODUCTS_DIR;
+		};
+		4353106B10440474004A4474 /* ossim-prune */ = {
+			isa = PBXReferenceProxy;
+			fileType = "compiled.mach-o.executable";
+			path = "ossim-prune";
+			remoteRef = 4353106A10440474004A4474 /* PBXContainerItemProxy */;
+			sourceTree = BUILT_PRODUCTS_DIR;
+		};
+		4353106F10440474004A4474 /* ossim-rejout */ = {
+			isa = PBXReferenceProxy;
+			fileType = "compiled.mach-o.executable";
+			path = "ossim-rejout";
+			remoteRef = 4353106E10440474004A4474 /* PBXContainerItemProxy */;
+			sourceTree = BUILT_PRODUCTS_DIR;
+		};
+		4353107110440474004A4474 /* ossim-senint */ = {
+			isa = PBXReferenceProxy;
+			fileType = "compiled.mach-o.executable";
+			path = "ossim-senint";
+			remoteRef = 4353107010440474004A4474 /* PBXContainerItemProxy */;
+			sourceTree = BUILT_PRODUCTS_DIR;
+		};
+		4353107310440474004A4474 /* ossim-space-imaging */ = {
+			isa = PBXReferenceProxy;
+			fileType = "compiled.mach-o.executable";
+			path = "ossim-space-imaging";
+			remoteRef = 4353107210440474004A4474 /* PBXContainerItemProxy */;
+			sourceTree = BUILT_PRODUCTS_DIR;
+		};
+		4353107510440474004A4474 /* ossim-swapbytes */ = {
+			isa = PBXReferenceProxy;
+			fileType = "compiled.mach-o.executable";
+			path = "ossim-swapbytes";
+			remoteRef = 4353107410440474004A4474 /* PBXContainerItemProxy */;
+			sourceTree = BUILT_PRODUCTS_DIR;
+		};
+		4353107710440474004A4474 /* ossim-tfw2ogeom */ = {
+			isa = PBXReferenceProxy;
+			fileType = "compiled.mach-o.executable";
+			path = "ossim-tfw2ogeom";
+			remoteRef = 4353107610440474004A4474 /* PBXContainerItemProxy */;
+			sourceTree = BUILT_PRODUCTS_DIR;
+		};
+		EE69A3850B28850A00C91DD1 /* wms.framework */ = {
+			isa = PBXReferenceProxy;
+			fileType = wrapper.framework;
+			path = wms.framework;
+			remoteRef = EE69A3840B28850A00C91DD1 /* PBXContainerItemProxy */;
+			sourceTree = BUILT_PRODUCTS_DIR;
+		};
+		EEB7D1540E77F4DD007DA09C /* wmsurl */ = {
+			isa = PBXReferenceProxy;
+			fileType = "compiled.mach-o.executable";
+			path = wmsurl;
+			remoteRef = EEB7D1530E77F4DD007DA09C /* PBXContainerItemProxy */;
+			sourceTree = BUILT_PRODUCTS_DIR;
+		};
+		EEB7D1560E77F4DD007DA09C /* wmscapabilities.cpp */ = {
+			isa = PBXReferenceProxy;
+			fileType = "compiled.mach-o.executable";
+			path = wmscapabilities.cpp;
+			remoteRef = EEB7D1550E77F4DD007DA09C /* PBXContainerItemProxy */;
+			sourceTree = BUILT_PRODUCTS_DIR;
+		};
+		EEB7D1580E77F4DD007DA09C /* wmsgetmap */ = {
+			isa = PBXReferenceProxy;
+			fileType = "compiled.mach-o.executable";
+			path = wmsgetmap;
+			remoteRef = EEB7D1570E77F4DD007DA09C /* PBXContainerItemProxy */;
+			sourceTree = BUILT_PRODUCTS_DIR;
+		};
+/* End PBXReferenceProxy section */
+
+/* Begin PBXSourcesBuildPhase section */
+		186EF86A0B1F184C00F7886A /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				EEA3C4A50E3FA61C00CAAC1A /* ossimEsriShapeFileFilter.cpp in Sources */,
+				EEA3C4A70E3FA61C00CAAC1A /* ossimGdalDataset.cpp in Sources */,
+				EEA3C4A90E3FA61C00CAAC1A /* ossimGdalFactory.cpp in Sources */,
+				EEA3C4AB0E3FA61C00CAAC1A /* ossimGdalImageWriterFactory.cpp in Sources */,
+				EEA3C4AD0E3FA61C00CAAC1A /* ossimGdalObjectFactory.cpp in Sources */,
+				EEA3C4AF0E3FA61C00CAAC1A /* ossimGdalOgrVectorAnnotation.cpp in Sources */,
+				EEA3C4B10E3FA61C00CAAC1A /* ossimGdalOverviewBuilder.cpp in Sources */,
+				EEA3C4B30E3FA61C00CAAC1A /* ossimGdalOverviewBuilderFactory.cpp in Sources */,
+				EEA3C4B50E3FA61C00CAAC1A /* ossimGdalPluginInit.cpp in Sources */,
+				EEA3C4B60E3FA61C00CAAC1A /* ossimGdalProjectionFactory.cpp in Sources */,
+				EEA3C4B80E3FA61C00CAAC1A /* ossimGdalTiledDataset.cpp in Sources */,
+				EEA3C4BA0E3FA61C00CAAC1A /* ossimGdalTileSource.cpp in Sources */,
+				EEA3C4BC0E3FA61C00CAAC1A /* ossimGdalType.cpp in Sources */,
+				EEA3C4BE0E3FA61C00CAAC1A /* ossimGdalWriter.cpp in Sources */,
+				EEA3C4C00E3FA61C00CAAC1A /* ossimOgcWktTranslator.cpp in Sources */,
+				EEA3C4C20E3FA61C00CAAC1A /* ossimOgrGdalTileSource.cpp in Sources */,
+				EEA3C4C40E3FA61C00CAAC1A /* ossimShapeDatabase.cpp in Sources */,
+				EEA3C4C60E3FA61C00CAAC1A /* ossimShapeFile.cpp in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		186EF97F0B1F222500F7886A /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				186EF9AA0B1F236800F7886A /* ossimChipMatch.cpp in Sources */,
+				186EF9AC0B1F236800F7886A /* ossimDensityReducer.cpp in Sources */,
+				186EF9AE0B1F236800F7886A /* ossimExtremaFilter.cpp in Sources */,
+				186EF9B00B1F236800F7886A /* ossimHarrisCorners.cpp in Sources */,
+				186EF9B20B1F236800F7886A /* ossimImageCorrelator.cpp in Sources */,
+				186EF9B40B1F236800F7886A /* ossimModelOptimizer.cpp in Sources */,
+				186EF9B60B1F236800F7886A /* ossimMultiplier.cpp in Sources */,
+				186EF9B80B1F236800F7886A /* ossimNCC_FFTW.cpp in Sources */,
+				186EF9BA0B1F236800F7886A /* ossimOutlierRejection.cpp in Sources */,
+				186EF9BD0B1F236800F7886A /* ossimRegistrationImageSourceFactory.cpp in Sources */,
+				186EF9BF0B1F236800F7886A /* ossimRegistrationMiscFactory.cpp in Sources */,
+				186EF9C10B1F236800F7886A /* ossimRegistrationPluginInit.cpp in Sources */,
+				186EF9C20B1F236800F7886A /* ossimRunningSum.cpp in Sources */,
+				186EF9C40B1F236800F7886A /* ossimSquareFunction.cpp in Sources */,
+				186EF9C60B1F236800F7886A /* ossimTieGenerator.cpp in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		186EFA190B1F321200F7886A /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				186EFA330B1F32FF00F7886A /* ossimDiskCache.cpp in Sources */,
+				186EFA350B1F32FF00F7886A /* ossimSharedDiskCacheManager.cpp in Sources */,
+				186EFA380B1F32FF00F7886A /* ossimWorldWindFactory.cpp in Sources */,
+				186EFA3A0B1F32FF00F7886A /* ossimWorldWindHandler.cpp in Sources */,
+				186EFA3C0B1F32FF00F7886A /* ossimWorldWindJpegImage.cpp in Sources */,
+				186EFA3E0B1F32FF00F7886A /* ossimWorldWindPluginInit.cpp in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		186EFA5C0B1F394100F7886A /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				186EFA6D0B1F39FD00F7886A /* ossimNuiPluginInit.cpp in Sources */,
+				186EFA6F0B1F39FD00F7886A /* ossimNuiHandler.cpp in Sources */,
+				186EFA710B1F39FD00F7886A /* ossimNuiFactory.cpp in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		430D1FD40BB2F96B0057E5FF /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				430D20850BB2FA450057E5FF /* ossimPngWriterFactory.cpp in Sources */,
+				430D20860BB2FA450057E5FF /* ossimPngPluginInit.cpp in Sources */,
+				430D20870BB2FA450057E5FF /* ossimPngReaderFactory.cpp in Sources */,
+				430D20880BB2FA450057E5FF /* ossimPngWriter.cpp in Sources */,
+				430D208A0BB2FA450057E5FF /* ossimPngReader.cpp in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		43132103103C84DF00F96FDF /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				436A7F5210FBB24200985348 /* ossimKakaduOverviewBuilderFactory.cpp in Sources */,
+				436A7F5510FBB24200985348 /* ossimKakaduJp2Writer.cpp in Sources */,
+				436A7F5610FBB24200985348 /* ossimKakaduCompressedTarget.cpp in Sources */,
+				436A7F5810FBB24200985348 /* ossimKakaduCompressor.cpp in Sources */,
+				436A7F5910FBB24200985348 /* ossimKakaduNitfOverviewBuilder.cpp in Sources */,
+				436A7F5A10FBB24200985348 /* ossimKakaduNitfReader.cpp in Sources */,
+				436A7F5C10FBB24200985348 /* ossimKakaduJ2kReader.cpp in Sources */,
+				436A7F5F10FBB24200985348 /* ossimKakaduNitfWriter.cpp in Sources */,
+				436A7F6110FBB24200985348 /* ossimKakaduReaderFactory.cpp in Sources */,
+				436A7F6210FBB24200985348 /* ossimKakaduWriterFactory.cpp in Sources */,
+				436A7F6310FBB24200985348 /* ossimKakaduPluginInit.cpp in Sources */,
+				436A7F6410FBB24200985348 /* ossimKakaduJp2Reader.cpp in Sources */,
+				436A7F6510FBB24200985348 /* ossimKakaduCommon.cpp in Sources */,
+				4310BA79110DD27C00C258B9 /* jp2.cpp in Sources */,
+				4310BA7B110DD27C00C258B9 /* jpx.cpp in Sources */,
+				4310BA7D110DD27C00C258B9 /* mj2.cpp in Sources */,
+				4391B4D9110F6D0400B5895E /* kdu_region_decompressor.cpp in Sources */,
+				4391B4E8110F715600B5895E /* libkdu_v62R.dylib in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		43377EF210CFFAC900ECC5AD /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				43377F0410CFFB6400ECC5AD /* ossimCsmSensorModel.cpp in Sources */,
+				43377F0510CFFB6400ECC5AD /* ossimCsmPluginInit.cpp in Sources */,
+				43377F0810CFFB6400ECC5AD /* ossimCsmProjectionFactory.cpp in Sources */,
+				43378A0410D01EFD00ECC5AD /* ossimCsmSupport.cpp in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		436A7E2010FB9FC400985348 /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				436A7E4D10FBA00100985348 /* ossimMrSidWriterFactory.cpp in Sources */,
+				436A7E4F10FBA00100985348 /* ossimMrSidReaderFactory.cpp in Sources */,
+				436A7E5110FBA00100985348 /* ossimMrSidReader.cpp in Sources */,
+				436A7E5210FBA00100985348 /* ossimMrSidWriter.cpp in Sources */,
+				436A7E5410FBA00100985348 /* ossimMrSidPluginInit.cpp in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		43A9A09F1151AC37000860DA /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				43A9A1441151ADA8000860DA /* ErsSarDataSetSummary.cpp in Sources */,
+				43A9A1461151ADA8000860DA /* ErsSarFacilityData.cpp in Sources */,
+				43A9A1481151ADA8000860DA /* ErsSarFileDescriptor.cpp in Sources */,
+				43A9A14A1151ADA8000860DA /* ErsSarLeader.cpp in Sources */,
+				43A9A14C1151ADA8000860DA /* ErsSarLeaderFactory.cpp in Sources */,
+				43A9A14E1151ADA8000860DA /* ErsSarMapProjectionData.cpp in Sources */,
+				43A9A1501151ADA8000860DA /* ErsSarPlatformPositionData.cpp in Sources */,
+				43A9A1521151ADA8000860DA /* ErsSarPositionVectorRecord.cpp in Sources */,
+				43A9A1541151ADA8000860DA /* ErsSarRecord.cpp in Sources */,
+				43A9A1561151ADA8000860DA /* ErsSarRecordFactory.cpp in Sources */,
+				43A9A1581151ADA8000860DA /* ErsSarRecordHeader.cpp in Sources */,
+				43A9A15A1151ADA8000860DA /* Makefile in Sources */,
+				43A9A15B1151ADA8000860DA /* ossimCosmoSkymedModel.cpp in Sources */,
+				43A9A15D1151ADA8000860DA /* ossimEnvisatAsarModel.cpp in Sources */,
+				43A9A15F1151ADA8000860DA /* ossimErsSarModel.cpp in Sources */,
+				43A9A1611151ADA8000860DA /* ossimGeometricSarSensorModel.cpp in Sources */,
+				43A9A1631151ADA8000860DA /* ossimPluginCommon.cpp in Sources */,
+				43A9A1651151ADA8000860DA /* ossimPluginInit.cpp in Sources */,
+				43A9A1661151ADA8000860DA /* ossimPluginProjectionFactory.cpp in Sources */,
+				43A9A1681151ADA8000860DA /* ossimPluginReaderFactory.cpp in Sources */,
+				43A9A16A1151ADA8000860DA /* ossimRadarSat2Model.cpp in Sources */,
+				43A9A16C1151ADA8000860DA /* ossimRadarSat2ProductDoc.cpp in Sources */,
+				43A9A16E1151ADA8000860DA /* ossimRadarSat2RPCModel.cpp in Sources */,
+				43A9A1701151ADA8000860DA /* ossimRadarSatModel.cpp in Sources */,
+				43A9A1721151ADA8000860DA /* ossimTerraSarModel.cpp in Sources */,
+				43A9A1741151ADA8000860DA /* ossimTerraSarProductDoc.cpp in Sources */,
+				43A9A1761151ADA8000860DA /* ossimTerraSarTiffReader.cpp in Sources */,
+				43A9A1791151ADA8000860DA /* CivilDateTime.cpp in Sources */,
+				43A9A17B1151ADA8000860DA /* Coordinate.cpp in Sources */,
+				43A9A17D1151ADA8000860DA /* Ephemeris.cpp in Sources */,
+				43A9A17F1151ADA8000860DA /* Equation.cpp in Sources */,
+				43A9A1811151ADA8000860DA /* GalileanEphemeris.cpp in Sources */,
+				43A9A1831151ADA8000860DA /* GeodesicCoordinate.cpp in Sources */,
+				43A9A1851151ADA8000860DA /* GeographicEphemeris.cpp in Sources */,
+				43A9A1871151ADA8000860DA /* GMSTDateTime.cpp in Sources */,
+				43A9A1891151ADA8000860DA /* HermiteInterpolator.cpp in Sources */,
+				43A9A18B1151ADA8000860DA /* ImageNoise.cpp in Sources */,
+				43A9A18D1151ADA8000860DA /* JSDDateTime.cpp in Sources */,
+				43A9A18F1151ADA8000860DA /* JulianDate.cpp in Sources */,
+				43A9A1911151ADA8000860DA /* Makefile in Sources */,
+				43A9A1921151ADA8000860DA /* MJDDateTime.cpp in Sources */,
+				43A9A1941151ADA8000860DA /* Noise.cpp in Sources */,
+				43A9A1961151ADA8000860DA /* PlatformPosition.cpp in Sources */,
+				43A9A1981151ADA8000860DA /* RectangularCoordinate.cpp in Sources */,
+				43A9A19A1151ADA8000860DA /* RefPoint.cpp in Sources */,
+				43A9A19C1151ADA8000860DA /* SarSensor.cpp in Sources */,
+				43A9A19E1151ADA8000860DA /* Sensor.cpp in Sources */,
+				43A9A1A01151ADA8000860DA /* SensorParams.cpp in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		EEA720190B2F4256006E37B7 /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				EEA720C70B2F4331006E37B7 /* ossimContribImageSourceFactory.cpp in Sources */,
+				EEA720C80B2F4331006E37B7 /* ossimContribPluginInit.cpp in Sources */,
+				EEA720C90B2F4331006E37B7 /* ossimCFARFilter.cpp in Sources */,
+				EEA720CB0B2F4331006E37B7 /* ossimSPOTNatural.cpp in Sources */,
+				EEA720CD0B2F4331006E37B7 /* ossimComplexAbs.cpp in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXTargetDependency section */
+		430EAEE50C6A4E8800E6661B /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			name = wms;
+			targetProxy = 430EAEE40C6A4E8800E6661B /* PBXContainerItemProxy */;
+		};
+		4310BB19110DD99B00C258B9 /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			target = 431320FC103C84DF00F96FDF /* ossimkakadu_plugin */;
+			targetProxy = 4310BB18110DD99B00C258B9 /* PBXContainerItemProxy */;
+		};
+		43333CC110FD00CD00A5B432 /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			target = 436A7E1410FB9FC400985348 /* ossimmrsid_plugin */;
+			targetProxy = 43333CC010FD00CD00A5B432 /* PBXContainerItemProxy */;
+		};
+		43378DC810D0220100ECC5AD /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			target = 186EF86C0B1F184C00F7886A /* ossimgdal_plugin */;
+			targetProxy = 43378DC710D0220100ECC5AD /* PBXContainerItemProxy */;
+		};
+		43378DCA10D0220100ECC5AD /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			target = 186EF9810B1F222500F7886A /* ossimreg_plugin */;
+			targetProxy = 43378DC910D0220100ECC5AD /* PBXContainerItemProxy */;
+		};
+		43378DCC10D0220100ECC5AD /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			target = 186EFA1B0B1F321200F7886A /* ossimworldwind_plugin */;
+			targetProxy = 43378DCB10D0220100ECC5AD /* PBXContainerItemProxy */;
+		};
+		43378DCE10D0220100ECC5AD /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			target = 186EFA5E0B1F394100F7886A /* ossimnui_plugin */;
+			targetProxy = 43378DCD10D0220100ECC5AD /* PBXContainerItemProxy */;
+		};
+		43378DD010D0220100ECC5AD /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			target = 430D1FCD0BB2F96B0057E5FF /* ossimpng_plugin */;
+			targetProxy = 43378DCF10D0220100ECC5AD /* PBXContainerItemProxy */;
+		};
+		43378DD210D0220100ECC5AD /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			target = 43377EF410CFFAC900ECC5AD /* ossimcsm_plugin */;
+			targetProxy = 43378DD110D0220100ECC5AD /* PBXContainerItemProxy */;
+		};
+		43A9A1A51151AE4E000860DA /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			target = 43A9A0991151AC37000860DA /* ossim_plugin */;
+			targetProxy = 43A9A1A41151AE4E000860DA /* PBXContainerItemProxy */;
+		};
+		43F4581A10FCDAFA002B9133 /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			target = 436A7E1410FB9FC400985348 /* ossimmrsid_plugin */;
+			targetProxy = 43F4581910FCDAFA002B9133 /* PBXContainerItemProxy */;
+		};
+/* End PBXTargetDependency section */
+
+/* Begin XCBuildConfiguration section */
+		186EF84E0B1F0A5000F7886A /* Debug */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = 186EF8550B1F0A7200F7886A /* common_settings.xcconfig */;
+			buildSettings = {
+				ARCHS = (
+					i386,
+					ppc,
+				);
+				COPY_PHASE_STRIP = NO;
+				GCC_MODEL_TUNING = "";
+				HEADER_SEARCH_PATHS = (
+					"$(DEV_HOME_PATH)/ossim/include",
+					"$(DEV_HOME_PATH)/ossim_plugins",
+				);
+				SDKROOT = /Developer/SDKs/MacOSX10.4u.sdk;
+			};
+			name = Debug;
+		};
+		186EF84F0B1F0A5000F7886A /* Release */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = 186EF8550B1F0A7200F7886A /* common_settings.xcconfig */;
+			buildSettings = {
+				ARCHS = "$(inherited)";
+				COPY_PHASE_STRIP = YES;
+				GCC_MODEL_TUNING = "";
+				HEADER_SEARCH_PATHS = (
+					"$(DEV_HOME_PATH)/ossim/include",
+					"$(DEV_HOME_PATH)/ossim_plugins",
+					"$(UNIV_HEADER_DEP)",
+				);
+				SDKROOT = /Developer/SDKs/MacOSX10.5.sdk;
+			};
+			name = Release;
+		};
+		186EF8700B1F184C00F7886A /* Debug */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = 186EF8550B1F0A7200F7886A /* common_settings.xcconfig */;
+			buildSettings = {
+				ARCHS = "$(inherited)";
+				COPY_PHASE_STRIP = NO;
+				EXECUTABLE_PREFIX = lib;
+				FRAMEWORK_SEARCH_PATHS = (
+					"$(inherited)",
+					"$(UNIV_DEP)/Frameworks",
+					"$(FRAMEWORK_SEARCH_PATHS_QUOTED_1)",
+				);
+				FRAMEWORK_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/../../ossim_dependencies/Frameworks\"";
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_ENABLE_FIX_AND_CONTINUE = YES;
+				GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
+				GCC_MODEL_TUNING = "";
+				GCC_OPTIMIZATION_LEVEL = 0;
+				HEADER_SEARCH_PATHS = (
+					"$(inherited)",
+					"$(UNIV_DEP)/Frameworks/gdal.framework/Headers",
+				);
+				INSTALL_PATH = "@loader_path/../plugins";
+				LIBRARY_SEARCH_PATHS = "$(UNIV_STATICLIB_DEP)";
+				PREBINDING = NO;
+				PRODUCT_NAME = ossimgdal_plugin;
+				REZ_SEARCH_PATHS = (
+					"$(OSSIM_HOME_PATH)/xcode/ossim/Resources",
+					"$(REZ_SEARCH_PATHS)/**",
+				);
+				ZERO_LINK = NO;
+			};
+			name = Debug;
+		};
+		186EF8710B1F184C00F7886A /* Release */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = 186EF8550B1F0A7200F7886A /* common_settings.xcconfig */;
+			buildSettings = {
+				ARCHS = "$(inherited)";
+				COPY_PHASE_STRIP = YES;
+				EXECUTABLE_PREFIX = lib;
+				FRAMEWORK_SEARCH_PATHS = (
+					"$(inherited)",
+					"$(UNIV_DEP)/Frameworks",
+					"$(FRAMEWORK_SEARCH_PATHS_QUOTED_1)",
+				);
+				FRAMEWORK_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/../../ossim_dependencies/Frameworks\"";
+				GCC_ENABLE_FIX_AND_CONTINUE = NO;
+				GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
+				GCC_MODEL_TUNING = "";
+				HEADER_SEARCH_PATHS = (
+					"$(inherited)",
+					"$(UNIV_DEP)/Frameworks/GDAL.framework/Headers",
+				);
+				INSTALL_PATH = "@loader_path/../plugins";
+				LIBRARY_SEARCH_PATHS = "$(UNIV_STATICLIB_DEP)";
+				OTHER_CFLAGS = "-g";
+				OTHER_LDFLAGS = (
+					"$(UNIV_DEP)/lib/libgdal.a",
+					"$(UNIV_DEP)/lib/libproj.a",
+					"-lz",
+					"-lcurl",
+					"-lexpat",
+					"-lsqlite3",
+				);
+				PREBINDING = NO;
+				PRODUCT_NAME = ossimgdal_plugin;
+				REZ_SEARCH_PATHS = (
+					"$(OSSIM_HOME_PATH)/xcode/ossim/Resources",
+					"$(REZ_SEARCH_PATHS)/**",
+				);
+				ZERO_LINK = NO;
+			};
+			name = Release;
+		};
+		186EF9880B1F226200F7886A /* Debug */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = 186EF8550B1F0A7200F7886A /* common_settings.xcconfig */;
+			buildSettings = {
+				ARCHS = "$(inherited)";
+				COPY_PHASE_STRIP = NO;
+				EXECUTABLE_PREFIX = lib;
+				FRAMEWORK_SEARCH_PATHS = (
+					"$(inherited)",
+					"$(FRAMEWORK_SEARCH_PATHS_QUOTED_1)",
+				);
+				FRAMEWORK_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/../../ossim_dependencies/Frameworks\"";
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_ENABLE_FIX_AND_CONTINUE = YES;
+				GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
+				GCC_MODEL_TUNING = "";
+				GCC_OPTIMIZATION_LEVEL = 0;
+				HEADER_SEARCH_PATHS = (
+					"$(inherited)",
+					"$(UNIV_HEADER_DEP)",
+				);
+				INSTALL_PATH = "@loader_path/../plugins";
+				LIBRARY_SEARCH_PATHS = "$(UNIV_STATICLIB_DEP)";
+				OTHER_LDFLAGS = "$(UNIV_STATICLIB_DEP)/libfftw3.a";
+				PREBINDING = NO;
+				PRIVATE_HEADERS_FOLDER_PATH = "";
+				PRODUCT_NAME = ossimreg_plugin;
+				PUBLIC_HEADERS_FOLDER_PATH = "";
+				REZ_SEARCH_PATHS = (
+					"$(OSSIM_HOME_PATH)/xcode/ossim/Resources",
+					"$(REZ_SEARCH_PATHS)/**",
+				);
+				ZERO_LINK = YES;
+			};
+			name = Debug;
+		};
+		186EF9890B1F226200F7886A /* Release */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = 186EF8550B1F0A7200F7886A /* common_settings.xcconfig */;
+			buildSettings = {
+				ARCHS = "$(inherited)";
+				COPY_PHASE_STRIP = YES;
+				EXECUTABLE_PREFIX = lib;
+				FRAMEWORK_SEARCH_PATHS = (
+					"$(inherited)",
+					"$(FRAMEWORK_SEARCH_PATHS_QUOTED_1)",
+				);
+				FRAMEWORK_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/../../ossim_dependencies/Frameworks\"";
+				GCC_ENABLE_FIX_AND_CONTINUE = NO;
+				GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
+				GCC_MODEL_TUNING = "";
+				HEADER_SEARCH_PATHS = (
+					"$(inherited)",
+					"$(UNIV_HEADER_DEP)",
+				);
+				INSTALL_PATH = "@loader_path/../plugins";
+				LIBRARY_SEARCH_PATHS = "$(UNIV_STATICLIB_DEP)";
+				OTHER_LDFLAGS = "$(UNIV_STATICLIB_DEP)/libfftw3.a";
+				PREBINDING = NO;
+				PRIVATE_HEADERS_FOLDER_PATH = "";
+				PRODUCT_NAME = ossimreg_plugin;
+				PUBLIC_HEADERS_FOLDER_PATH = "";
+				REZ_SEARCH_PATHS = (
+					"$(OSSIM_HOME_PATH)/xcode/ossim/Resources",
+					"$(REZ_SEARCH_PATHS)/**",
+				);
+				ZERO_LINK = NO;
+			};
+			name = Release;
+		};
+		186EFA230B1F323800F7886A /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ARCHS = "$(inherited)";
+				COPY_PHASE_STRIP = NO;
+				EXECUTABLE_PREFIX = lib;
+				FRAMEWORK_SEARCH_PATHS = (
+					"$(inherited)",
+					"$(FRAMEWORK_SEARCH_PATHS_QUOTED_1)",
+					"$(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1)",
+				);
+				FRAMEWORK_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/../../ossim_dependencies/Frameworks\"";
+				FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1 = "\"$(SRCROOT)/../../ossim_dependencies/Frameworks\"";
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_ENABLE_FIX_AND_CONTINUE = YES;
+				GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
+				GCC_MODEL_TUNING = "";
+				GCC_OPTIMIZATION_LEVEL = 0;
+				HEADER_SEARCH_PATHS = (
+					"$(inherited)",
+					"$(UNIV_HEADER_DEP)",
+				);
+				INSTALL_PATH = "@loader_path/../plugins";
+				LIBRARY_SEARCH_PATHS = "$(UNIV_STATICLIB_DEP)";
+				PREBINDING = NO;
+				PRIVATE_HEADERS_FOLDER_PATH = "";
+				PRODUCT_NAME = ossimworldwind_plugin;
+				PUBLIC_HEADERS_FOLDER_PATH = "";
+				REZ_SEARCH_PATHS = (
+					"$(OSSIM_HOME_PATH)/xcode/ossim/Resources",
+					"$(REZ_SEARCH_PATHS)/**",
+				);
+				ZERO_LINK = YES;
+			};
+			name = Debug;
+		};
+		186EFA240B1F323800F7886A /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ARCHS = "$(inherited)";
+				COPY_PHASE_STRIP = YES;
+				EXECUTABLE_PREFIX = lib;
+				FRAMEWORK_SEARCH_PATHS = (
+					"$(inherited)",
+					"$(FRAMEWORK_SEARCH_PATHS_QUOTED_1)",
+					"$(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1)",
+				);
+				FRAMEWORK_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/../../ossim_dependencies/Frameworks\"";
+				FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1 = "\"$(SRCROOT)/../../ossim_dependencies/Frameworks\"";
+				GCC_ENABLE_FIX_AND_CONTINUE = NO;
+				GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
+				GCC_MODEL_TUNING = "";
+				HEADER_SEARCH_PATHS = (
+					"$(inherited)",
+					"$(UNIV_HEADER_DEP)",
+				);
+				INSTALL_PATH = "@loader_path/../plugins";
+				LIBRARY_SEARCH_PATHS = "$(UNIV_STATICLIB_DEP)";
+				PREBINDING = NO;
+				PRIVATE_HEADERS_FOLDER_PATH = "";
+				PRODUCT_NAME = ossimworldwind_plugin;
+				PUBLIC_HEADERS_FOLDER_PATH = "";
+				REZ_SEARCH_PATHS = (
+					"$(OSSIM_HOME_PATH)/xcode/ossim/Resources",
+					"$(REZ_SEARCH_PATHS)/**",
+				);
+				ZERO_LINK = NO;
+			};
+			name = Release;
+		};
+		186EFA640B1F396700F7886A /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ARCHS = "$(inherited)";
+				COPY_PHASE_STRIP = NO;
+				EXECUTABLE_PREFIX = lib;
+				FRAMEWORK_SEARCH_PATHS = (
+					"$(inherited)",
+					"$(FRAMEWORK_SEARCH_PATHS_QUOTED_1)",
+				);
+				FRAMEWORK_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/../../ossim_dependencies/Frameworks\"";
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_ENABLE_FIX_AND_CONTINUE = YES;
+				GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
+				GCC_MODEL_TUNING = "";
+				GCC_OPTIMIZATION_LEVEL = 0;
+				HEADER_SEARCH_PATHS = (
+					"$(inherited)",
+					"$(UNIV_DEP)/nuiSDK/include",
+				);
+				INSTALL_PATH = "@loader_path/../plugins";
+				LIBRARY_SEARCH_PATHS = (
+					"$(UNIV_DEP)/nuiSDK/lib",
+					"$(UNIV_STATICLIB_DEP)",
+				);
+				OTHER_LDFLAGS = (
+					"-lnuiSDK",
+					"-lkdu",
+					"-lkdu_a52R",
+				);
+				PREBINDING = NO;
+				PRIVATE_HEADERS_FOLDER_PATH = "";
+				PRODUCT_NAME = ossimnui_plugin;
+				PUBLIC_HEADERS_FOLDER_PATH = "";
+				REZ_SEARCH_PATHS = (
+					"$(UNIV_DEP)/nuiSDK/lib",
+					/nuiSDK/lib,
+					"$(UNIV_STATICLIB_DEP)",
+				);
+				ZERO_LINK = YES;
+			};
+			name = Debug;
+		};
+		186EFA650B1F396700F7886A /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ARCHS = i386;
+				COPY_PHASE_STRIP = YES;
+				EXECUTABLE_PREFIX = lib;
+				FRAMEWORK_SEARCH_PATHS = (
+					"$(inherited)",
+					"$(FRAMEWORK_SEARCH_PATHS_QUOTED_1)",
+				);
+				FRAMEWORK_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/../../ossim_dependencies/Frameworks\"";
+				GCC_ENABLE_FIX_AND_CONTINUE = NO;
+				GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
+				GCC_MODEL_TUNING = "";
+				HEADER_SEARCH_PATHS = (
+					"$(inherited)",
+					"$(UNIV_DEP)/nuiSDK/include",
+				);
+				INSTALL_PATH = "@loader_path/../plugins";
+				LIBRARY_SEARCH_PATHS = (
+					"$(UNIV_DEP)/nuiSDK/lib",
+					"$(UNIV_STATICLIB_DEP)",
+				);
+				OTHER_CFLAGS = "-g";
+				OTHER_LDFLAGS = "-lz";
+				PREBINDING = NO;
+				PRIVATE_HEADERS_FOLDER_PATH = "";
+				PRODUCT_NAME = ossimnui_plugin;
+				PUBLIC_HEADERS_FOLDER_PATH = "";
+				REZ_SEARCH_PATHS = (
+					"$(UNIV_DEP)/nuiSDK/lib",
+					/nuiSDK/lib,
+					"$(UNIV_STATICLIB_DEP)",
+				);
+				ZERO_LINK = NO;
+			};
+			name = Release;
+		};
+		18A9BC710CDA151F00F4581A /* DebugNativeLeopard */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = 186EF8550B1F0A7200F7886A /* common_settings.xcconfig */;
+			buildSettings = {
+				ARCHS = "$(NATIVE_ARCH)";
+				COPY_PHASE_STRIP = NO;
+				GCC_MODEL_TUNING = "";
+				HEADER_SEARCH_PATHS = (
+					"$(DEV_HOME_PATH)/ossim/include",
+					"$(DEV_HOME_PATH)/ossim_plugins",
+				);
+				SDKROOT = /Developer/SDKs/MacOSX10.5.sdk;
+			};
+			name = DebugNativeLeopard;
+		};
+		18A9BC720CDA151F00F4581A /* DebugNativeLeopard */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = 186EF8550B1F0A7200F7886A /* common_settings.xcconfig */;
+			buildSettings = {
+				ARCHS = "$(inherited)";
+				COPY_PHASE_STRIP = NO;
+				EXECUTABLE_PREFIX = lib;
+				FRAMEWORK_SEARCH_PATHS = (
+					"$(inherited)",
+					"$(UNIV_DEP)/Frameworks",
+					"$(FRAMEWORK_SEARCH_PATHS_QUOTED_1)",
+				);
+				FRAMEWORK_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/../../ossim_dependencies/Frameworks\"";
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_ENABLE_FIX_AND_CONTINUE = YES;
+				GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
+				GCC_MODEL_TUNING = "";
+				GCC_OPTIMIZATION_LEVEL = 0;
+				HEADER_SEARCH_PATHS = (
+					"$(inherited)",
+					"$(UNIV_DEP)/Frameworks/gdal.framework/Headers",
+				);
+				INSTALL_PATH = "@loader_path/../plugins";
+				LIBRARY_SEARCH_PATHS = "$(UNIV_STATICLIB_DEP)";
+				PREBINDING = NO;
+				PRODUCT_NAME = ossimgdal_plugin;
+				REZ_SEARCH_PATHS = (
+					"$(OSSIM_HOME_PATH)/xcode/ossim/Resources",
+					"$(REZ_SEARCH_PATHS)/**",
+				);
+				ZERO_LINK = NO;
+			};
+			name = DebugNativeLeopard;
+		};
+		18A9BC730CDA151F00F4581A /* DebugNativeLeopard */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = 186EF8550B1F0A7200F7886A /* common_settings.xcconfig */;
+			buildSettings = {
+				ARCHS = "$(inherited)";
+				COPY_PHASE_STRIP = NO;
+				EXECUTABLE_PREFIX = lib;
+				FRAMEWORK_SEARCH_PATHS = (
+					"$(inherited)",
+					"$(FRAMEWORK_SEARCH_PATHS_QUOTED_1)",
+				);
+				FRAMEWORK_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/../../ossim_dependencies/Frameworks\"";
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_ENABLE_FIX_AND_CONTINUE = YES;
+				GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
+				GCC_MODEL_TUNING = "";
+				GCC_OPTIMIZATION_LEVEL = 0;
+				HEADER_SEARCH_PATHS = (
+					"$(inherited)",
+					"$(UNIV_HEADER_DEP)",
+				);
+				INSTALL_PATH = "@loader_path/../plugins";
+				LIBRARY_SEARCH_PATHS = "$(UNIV_STATICLIB_DEP)";
+				OTHER_LDFLAGS = "$(UNIV_STATICLIB_DEP)/libfftw3.a";
+				PREBINDING = NO;
+				PRIVATE_HEADERS_FOLDER_PATH = "";
+				PRODUCT_NAME = ossimreg_plugin;
+				PUBLIC_HEADERS_FOLDER_PATH = "";
+				REZ_SEARCH_PATHS = (
+					"$(OSSIM_HOME_PATH)/xcode/ossim/Resources",
+					"$(REZ_SEARCH_PATHS)/**",
+				);
+				ZERO_LINK = YES;
+			};
+			name = DebugNativeLeopard;
+		};
+		18A9BC740CDA151F00F4581A /* DebugNativeLeopard */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ARCHS = "$(inherited)";
+				COPY_PHASE_STRIP = NO;
+				EXECUTABLE_PREFIX = lib;
+				FRAMEWORK_SEARCH_PATHS = (
+					"$(inherited)",
+					"$(FRAMEWORK_SEARCH_PATHS_QUOTED_1)",
+					"$(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1)",
+				);
+				FRAMEWORK_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/../../ossim_dependencies/Frameworks\"";
+				FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1 = "\"$(SRCROOT)/../../ossim_dependencies/Frameworks\"";
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_ENABLE_FIX_AND_CONTINUE = YES;
+				GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
+				GCC_MODEL_TUNING = "";
+				GCC_OPTIMIZATION_LEVEL = 0;
+				HEADER_SEARCH_PATHS = (
+					"$(inherited)",
+					"$(UNIV_HEADER_DEP)",
+				);
+				INSTALL_PATH = "@loader_path/../plugins";
+				LIBRARY_SEARCH_PATHS = "$(UNIV_STATICLIB_DEP)";
+				PREBINDING = NO;
+				PRIVATE_HEADERS_FOLDER_PATH = "";
+				PRODUCT_NAME = ossimworldwind_plugin;
+				PUBLIC_HEADERS_FOLDER_PATH = "";
+				REZ_SEARCH_PATHS = (
+					"$(OSSIM_HOME_PATH)/xcode/ossim/Resources",
+					"$(REZ_SEARCH_PATHS)/**",
+				);
+				ZERO_LINK = YES;
+			};
+			name = DebugNativeLeopard;
+		};
+		18A9BC750CDA151F00F4581A /* DebugNativeLeopard */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ARCHS = "$(inherited)";
+				COPY_PHASE_STRIP = NO;
+				EXECUTABLE_PREFIX = lib;
+				FRAMEWORK_SEARCH_PATHS = (
+					"$(inherited)",
+					"$(FRAMEWORK_SEARCH_PATHS_QUOTED_1)",
+				);
+				FRAMEWORK_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/../../ossim_dependencies/Frameworks\"";
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_ENABLE_FIX_AND_CONTINUE = YES;
+				GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
+				GCC_MODEL_TUNING = "";
+				GCC_OPTIMIZATION_LEVEL = 0;
+				HEADER_SEARCH_PATHS = (
+					"$(inherited)",
+					"$(UNIV_DEP)/nuiSDK/include",
+				);
+				INSTALL_PATH = "@loader_path/../plugins";
+				LIBRARY_SEARCH_PATHS = (
+					"$(UNIV_DEP)/nuiSDK/lib",
+					"$(UNIV_STATICLIB_DEP)",
+				);
+				OTHER_LDFLAGS = (
+					"-lnuiSDK",
+					"-lkdu",
+					"-lkdu_a52R",
+				);
+				PREBINDING = NO;
+				PRIVATE_HEADERS_FOLDER_PATH = "";
+				PRODUCT_NAME = ossimnui_plugin;
+				PUBLIC_HEADERS_FOLDER_PATH = "";
+				REZ_SEARCH_PATHS = (
+					"$(UNIV_DEP)/nuiSDK/lib",
+					/nuiSDK/lib,
+					"$(UNIV_STATICLIB_DEP)",
+				);
+				ZERO_LINK = YES;
+			};
+			name = DebugNativeLeopard;
+		};
+		18A9BC760CDA151F00F4581A /* DebugNativeLeopard */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ARCHS = "$(inherited)";
+				COPY_PHASE_STRIP = NO;
+				EXECUTABLE_PREFIX = lib;
+				FRAMEWORK_SEARCH_PATHS = (
+					"$(inherited)",
+					"$(FRAMEWORK_SEARCH_PATHS_QUOTED_1)",
+				);
+				FRAMEWORK_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/../../ossim_dependencies/Frameworks\"";
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_ENABLE_FIX_AND_CONTINUE = YES;
+				GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
+				GCC_MODEL_TUNING = "";
+				GCC_OPTIMIZATION_LEVEL = 0;
+				HEADER_SEARCH_PATHS = "$(inherited)";
+				INSTALL_PATH = "@loader_path/../plugins";
+				LIBRARY_SEARCH_PATHS = (
+					"$(DEV_HOME_PATH)/ossim_dependencies/nuiSDK/lib",
+					"$(UNIV_STATICLIB_DEP)",
+				);
+				PREBINDING = NO;
+				PRIVATE_HEADERS_FOLDER_PATH = "";
+				PRODUCT_NAME = ossimcontrib_plugin;
+				PUBLIC_HEADERS_FOLDER_PATH = "";
+				REZ_SEARCH_PATHS = (
+					"$(DEV_HOME_PATH)/ossim_dependencies/nuiSDK/lib",
+					"$(UNIV_STATICLIB_DEP)",
+				);
+				ZERO_LINK = YES;
+			};
+			name = DebugNativeLeopard;
+		};
+		18A9BC770CDA151F00F4581A /* DebugNativeLeopard */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ARCHS = "$(inherited)";
+				COPY_PHASE_STRIP = NO;
+				EXECUTABLE_PREFIX = lib;
+				FRAMEWORK_SEARCH_PATHS = (
+					"$(inherited)",
+					"$(FRAMEWORK_SEARCH_PATHS_QUOTED_1)",
+					"$(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1)",
+				);
+				FRAMEWORK_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/../../ossim_dependencies/Frameworks\"";
+				FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1 = "\"$(SRCROOT)/../../ossim_dependencies/Frameworks\"";
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_ENABLE_FIX_AND_CONTINUE = YES;
+				GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
+				GCC_MODEL_TUNING = "";
+				GCC_OPTIMIZATION_LEVEL = 0;
+				HEADER_SEARCH_PATHS = "$(inherited)";
+				INSTALL_PATH = "@loader_path/../plugins";
+				LIBRARY_SEARCH_PATHS = (
+					"$(DEV_HOME_PATH)/ossim_dependencies/nuiSDK/lib",
+					"$(UNIV_STATICLIB_DEP)",
+				);
+				PREBINDING = NO;
+				PRIVATE_HEADERS_FOLDER_PATH = "";
+				PRODUCT_NAME = ossimpng_plugin;
+				PUBLIC_HEADERS_FOLDER_PATH = "";
+				REZ_SEARCH_PATHS = (
+					"$(DEV_HOME_PATH)/ossim_dependencies/nuiSDK/lib",
+					"$(UNIV_STATICLIB_DEP)",
+				);
+				ZERO_LINK = YES;
+			};
+			name = DebugNativeLeopard;
+		};
+		18B28BB90CD579B8008F45B2 /* ReleaseLeopard */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = 186EF8550B1F0A7200F7886A /* common_settings.xcconfig */;
+			buildSettings = {
+				ARCHS = (
+					i386,
+					ppc,
+				);
+				COPY_PHASE_STRIP = YES;
+				GCC_MODEL_TUNING = "";
+				HEADER_SEARCH_PATHS = (
+					"$(DEV_HOME_PATH)/ossim/include",
+					"$(DEV_HOME_PATH)/ossim_plugins",
+					"$(UNIV_HEADER_DEP)",
+				);
+				SDKROOT = /Developer/SDKs/MacOSX10.5.sdk;
+			};
+			name = ReleaseLeopard;
+		};
+		18B28BBA0CD579B8008F45B2 /* ReleaseLeopard */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = 186EF8550B1F0A7200F7886A /* common_settings.xcconfig */;
+			buildSettings = {
+				ARCHS = "$(inherited)";
+				COPY_PHASE_STRIP = YES;
+				EXECUTABLE_PREFIX = lib;
+				FRAMEWORK_SEARCH_PATHS = (
+					"$(inherited)",
+					"$(UNIV_DEP)/Frameworks",
+					"$(FRAMEWORK_SEARCH_PATHS_QUOTED_1)",
+				);
+				FRAMEWORK_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/../../ossim_dependencies/Frameworks\"";
+				GCC_ENABLE_FIX_AND_CONTINUE = NO;
+				GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
+				GCC_MODEL_TUNING = "";
+				HEADER_SEARCH_PATHS = (
+					"$(inherited)",
+					"$(UNIV_DEP)/Frameworks/gdal.framework/Headers",
+				);
+				INSTALL_PATH = "@loader_path/../plugins";
+				LIBRARY_SEARCH_PATHS = "$(UNIV_STATICLIB_DEP)";
+				PREBINDING = NO;
+				PRODUCT_NAME = ossimgdal_plugin;
+				REZ_SEARCH_PATHS = (
+					"$(OSSIM_HOME_PATH)/xcode/ossim/Resources",
+					"$(REZ_SEARCH_PATHS)/**",
+				);
+				ZERO_LINK = NO;
+			};
+			name = ReleaseLeopard;
+		};
+		18B28BBB0CD579B8008F45B2 /* ReleaseLeopard */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = 186EF8550B1F0A7200F7886A /* common_settings.xcconfig */;
+			buildSettings = {
+				ARCHS = "$(inherited)";
+				COPY_PHASE_STRIP = YES;
+				EXECUTABLE_PREFIX = lib;
+				FRAMEWORK_SEARCH_PATHS = (
+					"$(inherited)",
+					"$(FRAMEWORK_SEARCH_PATHS_QUOTED_1)",
+				);
+				FRAMEWORK_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/../../ossim_dependencies/Frameworks\"";
+				GCC_ENABLE_FIX_AND_CONTINUE = NO;
+				GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
+				GCC_MODEL_TUNING = "";
+				HEADER_SEARCH_PATHS = (
+					"$(inherited)",
+					"$(UNIV_HEADER_DEP)",
+				);
+				INSTALL_PATH = "@loader_path/../plugins";
+				LIBRARY_SEARCH_PATHS = "$(UNIV_STATICLIB_DEP)";
+				OTHER_LDFLAGS = "$(UNIV_STATICLIB_DEP)/libfftw3.a";
+				PREBINDING = NO;
+				PRIVATE_HEADERS_FOLDER_PATH = "";
+				PRODUCT_NAME = ossimreg_plugin;
+				PUBLIC_HEADERS_FOLDER_PATH = "";
+				REZ_SEARCH_PATHS = (
+					"$(OSSIM_HOME_PATH)/xcode/ossim/Resources",
+					"$(REZ_SEARCH_PATHS)/**",
+				);
+				ZERO_LINK = NO;
+			};
+			name = ReleaseLeopard;
+		};
+		18B28BBC0CD579B8008F45B2 /* ReleaseLeopard */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ARCHS = "$(inherited)";
+				COPY_PHASE_STRIP = YES;
+				EXECUTABLE_PREFIX = lib;
+				FRAMEWORK_SEARCH_PATHS = (
+					"$(inherited)",
+					"$(FRAMEWORK_SEARCH_PATHS_QUOTED_1)",
+					"$(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1)",
+				);
+				FRAMEWORK_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/../../ossim_dependencies/Frameworks\"";
+				FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1 = "\"$(SRCROOT)/../../ossim_dependencies/Frameworks\"";
+				GCC_ENABLE_FIX_AND_CONTINUE = NO;
+				GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
+				GCC_MODEL_TUNING = "";
+				HEADER_SEARCH_PATHS = (
+					"$(inherited)",
+					"$(UNIV_HEADER_DEP)",
+				);
+				INSTALL_PATH = "@loader_path/../plugins";
+				LIBRARY_SEARCH_PATHS = "$(UNIV_STATICLIB_DEP)";
+				PREBINDING = NO;
+				PRIVATE_HEADERS_FOLDER_PATH = "";
+				PRODUCT_NAME = ossimworldwind_plugin;
+				PUBLIC_HEADERS_FOLDER_PATH = "";
+				REZ_SEARCH_PATHS = (
+					"$(OSSIM_HOME_PATH)/xcode/ossim/Resources",
+					"$(REZ_SEARCH_PATHS)/**",
+				);
+				ZERO_LINK = NO;
+			};
+			name = ReleaseLeopard;
+		};
+		18B28BBD0CD579B8008F45B2 /* ReleaseLeopard */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ARCHS = "$(inherited)";
+				COPY_PHASE_STRIP = YES;
+				EXECUTABLE_PREFIX = lib;
+				FRAMEWORK_SEARCH_PATHS = (
+					"$(inherited)",
+					"$(FRAMEWORK_SEARCH_PATHS_QUOTED_1)",
+				);
+				FRAMEWORK_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/../../ossim_dependencies/Frameworks\"";
+				GCC_ENABLE_FIX_AND_CONTINUE = NO;
+				GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
+				GCC_MODEL_TUNING = "";
+				HEADER_SEARCH_PATHS = (
+					"$(inherited)",
+					"$(UNIV_DEP)/nuiSDK/include",
+				);
+				INSTALL_PATH = "@loader_path/../plugins";
+				LIBRARY_SEARCH_PATHS = (
+					"$(UNIV_DEP)/nuiSDK/lib",
+					"$(UNIV_STATICLIB_DEP)",
+				);
+				OTHER_LDFLAGS = (
+					"-lnuiSDK",
+					"-lkdu",
+					"-lkdu_a52R",
+				);
+				PREBINDING = NO;
+				PRIVATE_HEADERS_FOLDER_PATH = "";
+				PRODUCT_NAME = ossimnui_plugin;
+				PUBLIC_HEADERS_FOLDER_PATH = "";
+				REZ_SEARCH_PATHS = (
+					"$(UNIV_DEP)/nuiSDK/lib",
+					/nuiSDK/lib,
+					"$(UNIV_STATICLIB_DEP)",
+				);
+				ZERO_LINK = NO;
+			};
+			name = ReleaseLeopard;
+		};
+		18B28BBE0CD579B8008F45B2 /* ReleaseLeopard */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ARCHS = "$(inherited)";
+				COPY_PHASE_STRIP = YES;
+				EXECUTABLE_PREFIX = lib;
+				FRAMEWORK_SEARCH_PATHS = (
+					"$(inherited)",
+					"$(FRAMEWORK_SEARCH_PATHS_QUOTED_1)",
+				);
+				FRAMEWORK_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/../../ossim_dependencies/Frameworks\"";
+				GCC_ENABLE_FIX_AND_CONTINUE = NO;
+				GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
+				GCC_MODEL_TUNING = "";
+				HEADER_SEARCH_PATHS = "$(inherited)";
+				INSTALL_PATH = "@loader_path/../plugins";
+				LIBRARY_SEARCH_PATHS = (
+					"$(DEV_HOME_PATH)/ossim_dependencies/nuiSDK/lib",
+					"$(UNIV_STATICLIB_DEP)",
+				);
+				PREBINDING = NO;
+				PRIVATE_HEADERS_FOLDER_PATH = "";
+				PRODUCT_NAME = ossimcontrib_plugin;
+				PUBLIC_HEADERS_FOLDER_PATH = "";
+				REZ_SEARCH_PATHS = (
+					"$(DEV_HOME_PATH)/ossim_dependencies/nuiSDK/lib",
+					"$(UNIV_STATICLIB_DEP)",
+				);
+				ZERO_LINK = NO;
+			};
+			name = ReleaseLeopard;
+		};
+		18B28BBF0CD579B8008F45B2 /* ReleaseLeopard */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ARCHS = "$(inherited)";
+				COPY_PHASE_STRIP = YES;
+				EXECUTABLE_PREFIX = lib;
+				FRAMEWORK_SEARCH_PATHS = (
+					"$(inherited)",
+					"$(FRAMEWORK_SEARCH_PATHS_QUOTED_1)",
+					"$(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1)",
+				);
+				FRAMEWORK_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/../../ossim_dependencies/Frameworks\"";
+				FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1 = "\"$(SRCROOT)/../../ossim_dependencies/Frameworks\"";
+				GCC_ENABLE_FIX_AND_CONTINUE = NO;
+				GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
+				GCC_MODEL_TUNING = "";
+				HEADER_SEARCH_PATHS = "$(inherited)";
+				INSTALL_PATH = "@loader_path/../plugins";
+				LIBRARY_SEARCH_PATHS = (
+					"$(DEV_HOME_PATH)/ossim_dependencies/nuiSDK/lib",
+					"$(UNIV_STATICLIB_DEP)",
+				);
+				OTHER_LDFLAGS = "-lz";
+				PREBINDING = NO;
+				PRIVATE_HEADERS_FOLDER_PATH = "";
+				PRODUCT_NAME = ossimpng_plugin;
+				PUBLIC_HEADERS_FOLDER_PATH = "";
+				REZ_SEARCH_PATHS = (
+					"$(DEV_HOME_PATH)/ossim_dependencies/nuiSDK/lib",
+					"$(UNIV_STATICLIB_DEP)",
+				);
+				ZERO_LINK = NO;
+			};
+			name = ReleaseLeopard;
+		};
+		18E4E4C10BE77FD000C8442B /* DebugNative */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = 186EF8550B1F0A7200F7886A /* common_settings.xcconfig */;
+			buildSettings = {
+				ARCHS = "$(inherited)";
+				COPY_PHASE_STRIP = NO;
+				EXECUTABLE_PREFIX = lib;
+				FRAMEWORK_SEARCH_PATHS = (
+					"$(inherited)",
+					"$(UNIV_DEP)/Frameworks",
+					"$(FRAMEWORK_SEARCH_PATHS_QUOTED_1)",
+				);
+				FRAMEWORK_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/../../ossim_dependencies/Frameworks\"";
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_ENABLE_FIX_AND_CONTINUE = YES;
+				GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
+				GCC_MODEL_TUNING = "";
+				GCC_OPTIMIZATION_LEVEL = 0;
+				HEADER_SEARCH_PATHS = (
+					"$(inherited)",
+					"$(UNIV_DEP)/Frameworks/gdal.framework/Headers",
+				);
+				INSTALL_PATH = "@loader_path/../plugins";
+				LIBRARY_SEARCH_PATHS = "$(UNIV_STATICLIB_DEP)";
+				PREBINDING = NO;
+				PRODUCT_NAME = ossimgdal_plugin;
+				REZ_SEARCH_PATHS = (
+					"$(OSSIM_HOME_PATH)/xcode/ossim/Resources",
+					"$(REZ_SEARCH_PATHS)/**",
+				);
+				ZERO_LINK = NO;
+			};
+			name = DebugNative;
+		};
+		18E4E4C20BE77FD000C8442B /* DebugNative */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = 186EF8550B1F0A7200F7886A /* common_settings.xcconfig */;
+			buildSettings = {
+				ARCHS = "$(inherited)";
+				COPY_PHASE_STRIP = NO;
+				EXECUTABLE_PREFIX = lib;
+				FRAMEWORK_SEARCH_PATHS = (
+					"$(inherited)",
+					"$(FRAMEWORK_SEARCH_PATHS_QUOTED_1)",
+				);
+				FRAMEWORK_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/../../ossim_dependencies/Frameworks\"";
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_ENABLE_FIX_AND_CONTINUE = YES;
+				GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
+				GCC_MODEL_TUNING = "";
+				GCC_OPTIMIZATION_LEVEL = 0;
+				HEADER_SEARCH_PATHS = (
+					"$(inherited)",
+					"$(UNIV_HEADER_DEP)",
+				);
+				INSTALL_PATH = "@loader_path/../plugins";
+				LIBRARY_SEARCH_PATHS = "$(UNIV_STATICLIB_DEP)";
+				OTHER_LDFLAGS = "$(UNIV_STATICLIB_DEP)/libfftw3.a";
+				PREBINDING = NO;
+				PRIVATE_HEADERS_FOLDER_PATH = "";
+				PRODUCT_NAME = ossimreg_plugin;
+				PUBLIC_HEADERS_FOLDER_PATH = "";
+				REZ_SEARCH_PATHS = (
+					"$(OSSIM_HOME_PATH)/xcode/ossim/Resources",
+					"$(REZ_SEARCH_PATHS)/**",
+				);
+				ZERO_LINK = YES;
+			};
+			name = DebugNative;
+		};
+		18E4E4C30BE77FD000C8442B /* DebugNative */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ARCHS = "$(inherited)";
+				COPY_PHASE_STRIP = NO;
+				EXECUTABLE_PREFIX = lib;
+				FRAMEWORK_SEARCH_PATHS = (
+					"$(inherited)",
+					"$(FRAMEWORK_SEARCH_PATHS_QUOTED_1)",
+					"$(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1)",
+				);
+				FRAMEWORK_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/../../ossim_dependencies/Frameworks\"";
+				FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1 = "\"$(SRCROOT)/../../ossim_dependencies/Frameworks\"";
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_ENABLE_FIX_AND_CONTINUE = YES;
+				GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
+				GCC_MODEL_TUNING = "";
+				GCC_OPTIMIZATION_LEVEL = 0;
+				HEADER_SEARCH_PATHS = (
+					"$(inherited)",
+					"$(UNIV_HEADER_DEP)",
+				);
+				INSTALL_PATH = "@loader_path/../plugins";
+				LIBRARY_SEARCH_PATHS = "$(UNIV_STATICLIB_DEP)";
+				PREBINDING = NO;
+				PRIVATE_HEADERS_FOLDER_PATH = "";
+				PRODUCT_NAME = ossimworldwind_plugin;
+				PUBLIC_HEADERS_FOLDER_PATH = "";
+				REZ_SEARCH_PATHS = (
+					"$(OSSIM_HOME_PATH)/xcode/ossim/Resources",
+					"$(REZ_SEARCH_PATHS)/**",
+				);
+				ZERO_LINK = YES;
+			};
+			name = DebugNative;
+		};
+		18E4E4C40BE77FD000C8442B /* DebugNative */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ARCHS = "$(inherited)";
+				COPY_PHASE_STRIP = NO;
+				EXECUTABLE_PREFIX = lib;
+				FRAMEWORK_SEARCH_PATHS = (
+					"$(inherited)",
+					"$(FRAMEWORK_SEARCH_PATHS_QUOTED_1)",
+				);
+				FRAMEWORK_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/../../ossim_dependencies/Frameworks\"";
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_ENABLE_FIX_AND_CONTINUE = YES;
+				GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
+				GCC_MODEL_TUNING = "";
+				GCC_OPTIMIZATION_LEVEL = 0;
+				HEADER_SEARCH_PATHS = (
+					"$(inherited)",
+					"$(UNIV_DEP)/nuiSDK/include",
+				);
+				INSTALL_PATH = "@loader_path/../plugins";
+				LIBRARY_SEARCH_PATHS = (
+					"$(UNIV_DEP)/nuiSDK/lib",
+					"$(UNIV_STATICLIB_DEP)",
+				);
+				OTHER_LDFLAGS = (
+					"-lnuiSDK",
+					"-lkdu",
+					"-lkdu_a52R",
+				);
+				PREBINDING = NO;
+				PRIVATE_HEADERS_FOLDER_PATH = "";
+				PRODUCT_NAME = ossimnui_plugin;
+				PUBLIC_HEADERS_FOLDER_PATH = "";
+				REZ_SEARCH_PATHS = (
+					"$(UNIV_DEP)/nuiSDK/lib",
+					/nuiSDK/lib,
+					"$(UNIV_STATICLIB_DEP)",
+				);
+				ZERO_LINK = YES;
+			};
+			name = DebugNative;
+		};
+		18E4E4C50BE77FD000C8442B /* DebugNative */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ARCHS = "$(inherited)";
+				COPY_PHASE_STRIP = NO;
+				EXECUTABLE_PREFIX = lib;
+				FRAMEWORK_SEARCH_PATHS = (
+					"$(inherited)",
+					"$(FRAMEWORK_SEARCH_PATHS_QUOTED_1)",
+				);
+				FRAMEWORK_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/../../ossim_dependencies/Frameworks\"";
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_ENABLE_FIX_AND_CONTINUE = YES;
+				GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
+				GCC_MODEL_TUNING = "";
+				GCC_OPTIMIZATION_LEVEL = 0;
+				HEADER_SEARCH_PATHS = "$(inherited)";
+				INSTALL_PATH = "@loader_path/../plugins";
+				LIBRARY_SEARCH_PATHS = (
+					"$(DEV_HOME_PATH)/ossim_dependencies/nuiSDK/lib",
+					"$(UNIV_STATICLIB_DEP)",
+				);
+				PREBINDING = NO;
+				PRIVATE_HEADERS_FOLDER_PATH = "";
+				PRODUCT_NAME = ossimcontrib_plugin;
+				PUBLIC_HEADERS_FOLDER_PATH = "";
+				REZ_SEARCH_PATHS = (
+					"$(DEV_HOME_PATH)/ossim_dependencies/nuiSDK/lib",
+					"$(UNIV_STATICLIB_DEP)",
+				);
+				ZERO_LINK = YES;
+			};
+			name = DebugNative;
+		};
+		18E4E4C60BE77FD000C8442B /* DebugNative */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ARCHS = "$(inherited)";
+				COPY_PHASE_STRIP = NO;
+				EXECUTABLE_PREFIX = lib;
+				FRAMEWORK_SEARCH_PATHS = (
+					"$(inherited)",
+					"$(FRAMEWORK_SEARCH_PATHS_QUOTED_1)",
+					"$(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1)",
+				);
+				FRAMEWORK_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/../../ossim_dependencies/Frameworks\"";
+				FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1 = "\"$(SRCROOT)/../../ossim_dependencies/Frameworks\"";
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_ENABLE_FIX_AND_CONTINUE = YES;
+				GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
+				GCC_MODEL_TUNING = "";
+				GCC_OPTIMIZATION_LEVEL = 0;
+				HEADER_SEARCH_PATHS = "$(inherited)";
+				INSTALL_PATH = "@loader_path/../plugins";
+				LIBRARY_SEARCH_PATHS = (
+					"$(DEV_HOME_PATH)/ossim_dependencies/nuiSDK/lib",
+					"$(UNIV_STATICLIB_DEP)",
+				);
+				PREBINDING = NO;
+				PRIVATE_HEADERS_FOLDER_PATH = "";
+				PRODUCT_NAME = ossimpng_plugin;
+				PUBLIC_HEADERS_FOLDER_PATH = "";
+				REZ_SEARCH_PATHS = (
+					"$(DEV_HOME_PATH)/ossim_dependencies/nuiSDK/lib",
+					"$(UNIV_STATICLIB_DEP)",
+				);
+				ZERO_LINK = YES;
+			};
+			name = DebugNative;
+		};
+		18E4E4C70BE77FD000C8442B /* DebugNative */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = 186EF8550B1F0A7200F7886A /* common_settings.xcconfig */;
+			buildSettings = {
+				ARCHS = "$(NATIVE_ARCH)";
+				COPY_PHASE_STRIP = NO;
+				GCC_MODEL_TUNING = "";
+				HEADER_SEARCH_PATHS = (
+					"$(DEV_HOME_PATH)/ossim/include",
+					"$(DEV_HOME_PATH)/ossim_plugins",
+				);
+				SDKROOT = /Developer/SDKs/MacOSX10.4u.sdk;
+			};
+			name = DebugNative;
+		};
+		430D1FDF0BB2F96B0057E5FF /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ARCHS = "$(inherited)";
+				COPY_PHASE_STRIP = NO;
+				EXECUTABLE_PREFIX = lib;
+				FRAMEWORK_SEARCH_PATHS = (
+					"$(inherited)",
+					"$(FRAMEWORK_SEARCH_PATHS_QUOTED_1)",
+					"$(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1)",
+				);
+				FRAMEWORK_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/../../ossim_dependencies/Frameworks\"";
+				FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1 = "\"$(SRCROOT)/../../ossim_dependencies/Frameworks\"";
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_ENABLE_FIX_AND_CONTINUE = YES;
+				GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
+				GCC_MODEL_TUNING = "";
+				GCC_OPTIMIZATION_LEVEL = 0;
+				HEADER_SEARCH_PATHS = "$(inherited)";
+				INSTALL_PATH = "@loader_path/../plugins";
+				LIBRARY_SEARCH_PATHS = (
+					"$(DEV_HOME_PATH)/ossim_dependencies/nuiSDK/lib",
+					"$(UNIV_STATICLIB_DEP)",
+				);
+				PREBINDING = NO;
+				PRIVATE_HEADERS_FOLDER_PATH = "";
+				PRODUCT_NAME = ossimpng_plugin;
+				PUBLIC_HEADERS_FOLDER_PATH = "";
+				REZ_SEARCH_PATHS = (
+					"$(DEV_HOME_PATH)/ossim_dependencies/nuiSDK/lib",
+					"$(UNIV_STATICLIB_DEP)",
+				);
+				ZERO_LINK = YES;
+			};
+			name = Debug;
+		};
+		430D1FE00BB2F96B0057E5FF /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ARCHS = "$(inherited)";
+				COPY_PHASE_STRIP = YES;
+				EXECUTABLE_PREFIX = lib;
+				FRAMEWORK_SEARCH_PATHS = (
+					"$(inherited)",
+					"$(FRAMEWORK_SEARCH_PATHS_QUOTED_1)",
+					"$(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1)",
+				);
+				FRAMEWORK_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/../../ossim_dependencies/Frameworks\"";
+				FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1 = "\"$(SRCROOT)/../../ossim_dependencies/Frameworks\"";
+				GCC_ENABLE_FIX_AND_CONTINUE = NO;
+				GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
+				GCC_MODEL_TUNING = "";
+				HEADER_SEARCH_PATHS = "$(inherited)";
+				INSTALL_PATH = "@loader_path/../plugins";
+				LIBRARY_SEARCH_PATHS = (
+					"$(DEV_HOME_PATH)/ossim_dependencies/nuiSDK/lib",
+					"$(UNIV_STATICLIB_DEP)",
+				);
+				OTHER_LDFLAGS = (
+					"-lz",
+					"$(UNIV_DEP)/lib/libpng.a",
+				);
+				PREBINDING = NO;
+				PRIVATE_HEADERS_FOLDER_PATH = "";
+				PRODUCT_NAME = ossimpng_plugin;
+				PUBLIC_HEADERS_FOLDER_PATH = "";
+				REZ_SEARCH_PATHS = (
+					"$(DEV_HOME_PATH)/ossim_dependencies/nuiSDK/lib",
+					"$(UNIV_STATICLIB_DEP)",
+				);
+				ZERO_LINK = NO;
+			};
+			name = Release;
+		};
+		4313210D103C84DF00F96FDF /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ARCHS = "$(inherited)";
+				COPY_PHASE_STRIP = NO;
+				EXECUTABLE_PREFIX = lib;
+				FRAMEWORK_SEARCH_PATHS = (
+					"$(inherited)",
+					"$(FRAMEWORK_SEARCH_PATHS_QUOTED_1)",
+				);
+				FRAMEWORK_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/../../ossim_dependencies/Frameworks\"";
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_ENABLE_FIX_AND_CONTINUE = YES;
+				GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
+				GCC_MODEL_TUNING = "";
+				GCC_OPTIMIZATION_LEVEL = 0;
+				HEADER_SEARCH_PATHS = (
+					"/Users/Shared/Development/kakadu/v6_2_1-00315N/managed/all_includes/",
+					"/Users/Shared/Development/kakadu/v6_2_1-00315N/coresys/transform",
+					"/Users/Shared/Development/kakadu/v6_2_1-00315N/coresys/common",
+					"/Users/Shared/Development/kakadu/v6_2_1-00315N/coresys/coding",
+					"/Users/Shared/Development/kakadu/v6_2_1-00315N/coresys/roi",
+					"/Users/Shared/Development/kakadu/v6_2_1-00315N/coresys",
+					"$(inherited)",
+				);
+				INSTALL_PATH = "@loader_path/../plugins";
+				LIBRARY_SEARCH_PATHS = (
+					/Users/Shared/Development/kakadu/bin/libkdu_v62R.dylib,
+					"$(DEV_HOME_PATH)/ossim_dependencies/nuiSDK/lib",
+					"$(UNIV_STATICLIB_DEP)",
+					"$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_1)",
+					"$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_2)",
+					"$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_3)",
+				);
+				LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_1 = "\"$(SRCROOT)/../../kakadu/bin\"";
+				LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_2 = "\"$(SRCROOT)/../../ossim_dependencies/kakadu/bin\"";
+				LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_3 = "\"$(SRCROOT)/../../ossim_dependencies/kakadu/bin\"";
+				OTHER_CFLAGS = "-g";
+				PREBINDING = NO;
+				PRIVATE_HEADERS_FOLDER_PATH = "";
+				PRODUCT_NAME = ossimkakadu_plugin;
+				PUBLIC_HEADERS_FOLDER_PATH = "";
+				REZ_SEARCH_PATHS = (
+					"$(DEV_HOME_PATH)/ossim_dependencies/nuiSDK/lib",
+					"$(UNIV_STATICLIB_DEP)",
+				);
+				ZERO_LINK = YES;
+			};
+			name = Debug;
+		};
+		4313210E103C84DF00F96FDF /* DebugNative */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ARCHS = "$(inherited)";
+				COPY_PHASE_STRIP = NO;
+				EXECUTABLE_PREFIX = lib;
+				FRAMEWORK_SEARCH_PATHS = (
+					"$(inherited)",
+					"$(FRAMEWORK_SEARCH_PATHS_QUOTED_1)",
+				);
+				FRAMEWORK_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/../../ossim_dependencies/Frameworks\"";
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_ENABLE_FIX_AND_CONTINUE = YES;
+				GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
+				GCC_MODEL_TUNING = "";
+				GCC_OPTIMIZATION_LEVEL = 0;
+				HEADER_SEARCH_PATHS = (
+					"/Users/Shared/Development/kakadu/v6_2_1-00315N/managed/all_includes/",
+					"/Users/Shared/Development/kakadu/v6_2_1-00315N/coresys/transform",
+					"/Users/Shared/Development/kakadu/v6_2_1-00315N/coresys/common",
+					"/Users/Shared/Development/kakadu/v6_2_1-00315N/coresys/coding",
+					"/Users/Shared/Development/kakadu/v6_2_1-00315N/coresys/roi",
+					"/Users/Shared/Development/kakadu/v6_2_1-00315N/coresys",
+					"$(inherited)",
+				);
+				INSTALL_PATH = "@loader_path/../plugins";
+				LIBRARY_SEARCH_PATHS = (
+					/Users/Shared/Development/kakadu/bin/libkdu_v62R.dylib,
+					"$(DEV_HOME_PATH)/ossim_dependencies/nuiSDK/lib",
+					"$(UNIV_STATICLIB_DEP)",
+					"$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_1)",
+					"$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_2)",
+					"$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_3)",
+				);
+				LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_1 = "\"$(SRCROOT)/../../kakadu/bin\"";
+				LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_2 = "\"$(SRCROOT)/../../ossim_dependencies/kakadu/bin\"";
+				LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_3 = "\"$(SRCROOT)/../../ossim_dependencies/kakadu/bin\"";
+				OTHER_CFLAGS = "-g";
+				PREBINDING = NO;
+				PRIVATE_HEADERS_FOLDER_PATH = "";
+				PRODUCT_NAME = ossimkakadu_plugin;
+				PUBLIC_HEADERS_FOLDER_PATH = "";
+				REZ_SEARCH_PATHS = (
+					"$(DEV_HOME_PATH)/ossim_dependencies/nuiSDK/lib",
+					"$(UNIV_STATICLIB_DEP)",
+				);
+				ZERO_LINK = YES;
+			};
+			name = DebugNative;
+		};
+		4313210F103C84DF00F96FDF /* DebugNativeLeopard */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ARCHS = "$(inherited)";
+				COPY_PHASE_STRIP = NO;
+				EXECUTABLE_PREFIX = lib;
+				FRAMEWORK_SEARCH_PATHS = (
+					"$(inherited)",
+					"$(FRAMEWORK_SEARCH_PATHS_QUOTED_1)",
+				);
+				FRAMEWORK_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/../../ossim_dependencies/Frameworks\"";
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_ENABLE_FIX_AND_CONTINUE = YES;
+				GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
+				GCC_MODEL_TUNING = "";
+				GCC_OPTIMIZATION_LEVEL = 0;
+				HEADER_SEARCH_PATHS = (
+					"/Users/Shared/Development/kakadu/v6_2_1-00315N/managed/all_includes/",
+					"/Users/Shared/Development/kakadu/v6_2_1-00315N/coresys/transform",
+					"/Users/Shared/Development/kakadu/v6_2_1-00315N/coresys/common",
+					"/Users/Shared/Development/kakadu/v6_2_1-00315N/coresys/coding",
+					"/Users/Shared/Development/kakadu/v6_2_1-00315N/coresys/roi",
+					"/Users/Shared/Development/kakadu/v6_2_1-00315N/coresys",
+					"$(inherited)",
+				);
+				INSTALL_PATH = "@loader_path/../plugins";
+				LIBRARY_SEARCH_PATHS = (
+					/Users/Shared/Development/kakadu/bin/libkdu_v62R.dylib,
+					"$(DEV_HOME_PATH)/ossim_dependencies/nuiSDK/lib",
+					"$(UNIV_STATICLIB_DEP)",
+					"$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_1)",
+					"$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_2)",
+					"$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_3)",
+				);
+				LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_1 = "\"$(SRCROOT)/../../kakadu/bin\"";
+				LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_2 = "\"$(SRCROOT)/../../ossim_dependencies/kakadu/bin\"";
+				LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_3 = "\"$(SRCROOT)/../../ossim_dependencies/kakadu/bin\"";
+				OTHER_CFLAGS = "-g";
+				PREBINDING = NO;
+				PRIVATE_HEADERS_FOLDER_PATH = "";
+				PRODUCT_NAME = ossimkakadu_plugin;
+				PUBLIC_HEADERS_FOLDER_PATH = "";
+				REZ_SEARCH_PATHS = (
+					"$(DEV_HOME_PATH)/ossim_dependencies/nuiSDK/lib",
+					"$(UNIV_STATICLIB_DEP)",
+				);
+				ZERO_LINK = YES;
+			};
+			name = DebugNativeLeopard;
+		};
+		43132110103C84DF00F96FDF /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ARCHS = "$(inherited)";
+				COPY_PHASE_STRIP = YES;
+				EXECUTABLE_PREFIX = lib;
+				FRAMEWORK_SEARCH_PATHS = (
+					"$(inherited)",
+					"$(FRAMEWORK_SEARCH_PATHS_QUOTED_1)",
+				);
+				FRAMEWORK_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/../../ossim_dependencies/Frameworks\"";
+				GCC_ENABLE_FIX_AND_CONTINUE = NO;
+				GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
+				GCC_MODEL_TUNING = "";
+				HEADER_SEARCH_PATHS = (
+					"$(UNIV_DEP)/kakadu/v6_2_1-00315N/managed/all_includes/",
+					"$(UNIV_DEP)/kakadu/v6_2_1-00315N/coresys/transform",
+					"$(UNIV_DEP)/kakadu/v6_2_1-00315N/coresys/common",
+					"$(UNIV_DEP)/kakadu/v6_2_1-00315N/coresys/coding",
+					"$(UNIV_DEP)/kakadu/v6_2_1-00315N/coresys/roi",
+					"$(UNIV_DEP)/kakadu/v6_2_1-00315N/coresys",
+					"$(inherited)",
+				);
+				INSTALL_PATH = "@loader_path/../plugins";
+				LIBRARY_SEARCH_PATHS = (
+					/Users/Shared/Development/kakadu/bin/libkdu_v62R.dylib,
+					"$(DEV_HOME_PATH)/ossim_dependencies/nuiSDK/lib",
+					"$(UNIV_STATICLIB_DEP)",
+					"$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_1)",
+					"$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_2)",
+					"$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_3)",
+				);
+				LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_1 = "\"$(SRCROOT)/../../kakadu/bin\"";
+				LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_2 = "\"$(SRCROOT)/../../ossim_dependencies/kakadu/bin\"";
+				LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_3 = "\"$(SRCROOT)/../../ossim_dependencies/kakadu/bin\"";
+				OTHER_CFLAGS = "-g";
+				PREBINDING = NO;
+				PRIVATE_HEADERS_FOLDER_PATH = "";
+				PRODUCT_NAME = ossimkakadu_plugin;
+				PUBLIC_HEADERS_FOLDER_PATH = "";
+				REZ_SEARCH_PATHS = (
+					"$(DEV_HOME_PATH)/ossim_dependencies/nuiSDK/lib",
+					"$(UNIV_STATICLIB_DEP)",
+				);
+				ZERO_LINK = NO;
+			};
+			name = Release;
+		};
+		43132111103C84DF00F96FDF /* ReleaseLeopard */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ARCHS = "$(inherited)";
+				COPY_PHASE_STRIP = YES;
+				EXECUTABLE_PREFIX = lib;
+				FRAMEWORK_SEARCH_PATHS = (
+					"$(inherited)",
+					"$(FRAMEWORK_SEARCH_PATHS_QUOTED_1)",
+				);
+				FRAMEWORK_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/../../ossim_dependencies/Frameworks\"";
+				GCC_ENABLE_FIX_AND_CONTINUE = NO;
+				GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
+				GCC_MODEL_TUNING = "";
+				HEADER_SEARCH_PATHS = (
+					"/Users/Shared/Development/kakadu/v6_2_1-00315N/managed/all_includes/",
+					"/Users/Shared/Development/kakadu/v6_2_1-00315N/coresys/transform",
+					"/Users/Shared/Development/kakadu/v6_2_1-00315N/coresys/common",
+					"/Users/Shared/Development/kakadu/v6_2_1-00315N/coresys/coding",
+					"/Users/Shared/Development/kakadu/v6_2_1-00315N/coresys/roi",
+					"/Users/Shared/Development/kakadu/v6_2_1-00315N/coresys",
+					"$(inherited)",
+				);
+				INSTALL_PATH = "@loader_path/../plugins";
+				LIBRARY_SEARCH_PATHS = (
+					/Users/Shared/Development/kakadu/bin/libkdu_v62R.dylib,
+					"$(DEV_HOME_PATH)/ossim_dependencies/nuiSDK/lib",
+					"$(UNIV_STATICLIB_DEP)",
+					"$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_1)",
+					"$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_2)",
+					"$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_3)",
+				);
+				LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_1 = "\"$(SRCROOT)/../../kakadu/bin\"";
+				LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_2 = "\"$(SRCROOT)/../../ossim_dependencies/kakadu/bin\"";
+				LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_3 = "\"$(SRCROOT)/../../ossim_dependencies/kakadu/bin\"";
+				OTHER_CFLAGS = "-g";
+				PREBINDING = NO;
+				PRIVATE_HEADERS_FOLDER_PATH = "";
+				PRODUCT_NAME = ossimkakadu_plugin;
+				PUBLIC_HEADERS_FOLDER_PATH = "";
+				REZ_SEARCH_PATHS = (
+					"$(DEV_HOME_PATH)/ossim_dependencies/nuiSDK/lib",
+					"$(UNIV_STATICLIB_DEP)",
+				);
+				ZERO_LINK = NO;
+			};
+			name = ReleaseLeopard;
+		};
+		43377EF610CFFACA00ECC5AD /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				COPY_PHASE_STRIP = NO;
+				EXECUTABLE_PREFIX = lib;
+				FRAMEWORK_SEARCH_PATHS = (
+					"$(inherited)",
+					"$(FRAMEWORK_SEARCH_PATHS_QUOTED_1)",
+					"$(FRAMEWORK_SEARCH_PATHS_QUOTED_2)",
+				);
+				FRAMEWORK_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/../../ossim_dependencies/Frameworks\"";
+				FRAMEWORK_SEARCH_PATHS_QUOTED_2 = "\"$(SRCROOT)\"";
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_ENABLE_FIX_AND_CONTINUE = YES;
+				GCC_MODEL_TUNING = G5;
+				GCC_OPTIMIZATION_LEVEL = 0;
+				INSTALL_PATH = /usr/local/lib;
+				PREBINDING = NO;
+				PRODUCT_NAME = ossimcsm_plugin;
+			};
+			name = Debug;
+		};
+		43377EF710CFFACA00ECC5AD /* DebugNative */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				EXECUTABLE_PREFIX = lib;
+				FRAMEWORK_SEARCH_PATHS = (
+					"$(inherited)",
+					"$(FRAMEWORK_SEARCH_PATHS_QUOTED_1)",
+					"$(FRAMEWORK_SEARCH_PATHS_QUOTED_2)",
+				);
+				FRAMEWORK_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/../../ossim_dependencies/Frameworks\"";
+				FRAMEWORK_SEARCH_PATHS_QUOTED_2 = "\"$(SRCROOT)\"";
+				GCC_ENABLE_FIX_AND_CONTINUE = YES;
+				GCC_MODEL_TUNING = G5;
+				INSTALL_PATH = /usr/local/lib;
+				PREBINDING = NO;
+				PRODUCT_NAME = ossimcsm_plugin;
+			};
+			name = DebugNative;
+		};
+		43377EF810CFFACA00ECC5AD /* DebugNativeLeopard */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				EXECUTABLE_PREFIX = lib;
+				FRAMEWORK_SEARCH_PATHS = (
+					"$(inherited)",
+					"$(FRAMEWORK_SEARCH_PATHS_QUOTED_1)",
+					"$(FRAMEWORK_SEARCH_PATHS_QUOTED_2)",
+				);
+				FRAMEWORK_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/../../ossim_dependencies/Frameworks\"";
+				FRAMEWORK_SEARCH_PATHS_QUOTED_2 = "\"$(SRCROOT)\"";
+				GCC_ENABLE_FIX_AND_CONTINUE = YES;
+				GCC_MODEL_TUNING = G5;
+				INSTALL_PATH = /usr/local/lib;
+				PREBINDING = NO;
+				PRODUCT_NAME = ossimcsm_plugin;
+			};
+			name = DebugNativeLeopard;
+		};
+		43377EF910CFFACA00ECC5AD /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				COPY_PHASE_STRIP = YES;
+				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+				EXECUTABLE_PREFIX = lib;
+				FRAMEWORK_SEARCH_PATHS = (
+					"$(inherited)",
+					"$(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1)",
+					"$(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_2)",
+				);
+				FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1 = "\"$(SRCROOT)/../../ossim_dependencies/Frameworks\"";
+				FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_2 = "\"$(SRCROOT)\"";
+				GCC_ENABLE_FIX_AND_CONTINUE = NO;
+				GCC_MODEL_TUNING = G5;
+				INSTALL_PATH = /usr/local/lib;
+				PREBINDING = NO;
+				PRODUCT_NAME = ossimcsm_plugin;
+				ZERO_LINK = NO;
+			};
+			name = Release;
+		};
+		43377EFA10CFFACA00ECC5AD /* ReleaseLeopard */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				EXECUTABLE_PREFIX = lib;
+				FRAMEWORK_SEARCH_PATHS = (
+					"$(inherited)",
+					"$(FRAMEWORK_SEARCH_PATHS_QUOTED_1)",
+					"$(FRAMEWORK_SEARCH_PATHS_QUOTED_2)",
+				);
+				FRAMEWORK_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/../../ossim_dependencies/Frameworks\"";
+				FRAMEWORK_SEARCH_PATHS_QUOTED_2 = "\"$(SRCROOT)\"";
+				GCC_ENABLE_FIX_AND_CONTINUE = YES;
+				GCC_MODEL_TUNING = G5;
+				INSTALL_PATH = /usr/local/lib;
+				PREBINDING = NO;
+				PRODUCT_NAME = ossimcsm_plugin;
+			};
+			name = ReleaseLeopard;
+		};
+		43378DC110D021EE00ECC5AD /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				COPY_PHASE_STRIP = NO;
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_OPTIMIZATION_LEVEL = 0;
+				PRODUCT_NAME = All;
+			};
+			name = Debug;
+		};
+		43378DC210D021EE00ECC5AD /* DebugNative */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				PRODUCT_NAME = All;
+			};
+			name = DebugNative;
+		};
+		43378DC310D021EE00ECC5AD /* DebugNativeLeopard */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				PRODUCT_NAME = All;
+			};
+			name = DebugNativeLeopard;
+		};
+		43378DC410D021EE00ECC5AD /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				COPY_PHASE_STRIP = YES;
+				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+				GCC_ENABLE_FIX_AND_CONTINUE = NO;
+				PRODUCT_NAME = All;
+				ZERO_LINK = NO;
+			};
+			name = Release;
+		};
+		43378DC510D021EE00ECC5AD /* ReleaseLeopard */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				PRODUCT_NAME = All;
+			};
+			name = ReleaseLeopard;
+		};
+		436A7E3010FB9FC400985348 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ARCHS = "$(inherited)";
+				COPY_PHASE_STRIP = NO;
+				EXECUTABLE_PREFIX = lib;
+				FRAMEWORK_SEARCH_PATHS = (
+					"$(inherited)",
+					"$(FRAMEWORK_SEARCH_PATHS_QUOTED_1)",
+					"$(FRAMEWORK_SEARCH_PATHS_QUOTED_2)",
+				);
+				FRAMEWORK_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/../../ossim_dependencies/Frameworks\"";
+				FRAMEWORK_SEARCH_PATHS_QUOTED_2 = "\"$(SRCROOT)/../../ossim_dependencies/Frameworks\"";
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_ENABLE_FIX_AND_CONTINUE = YES;
+				GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
+				GCC_MODEL_TUNING = "";
+				GCC_OPTIMIZATION_LEVEL = 0;
+				HEADER_SEARCH_PATHS = (
+					"/Users/Shared/Development/kakadu/v6_2_1-00315N/managed/all_includes/",
+					"/Users/Shared/Development/kakadu/v6_2_1-00315N/coresys/transform",
+					"/Users/Shared/Development/kakadu/v6_2_1-00315N/coresys/common",
+					"/Users/Shared/Development/kakadu/v6_2_1-00315N/coresys/coding",
+					"/Users/Shared/Development/kakadu/v6_2_1-00315N/coresys/roi",
+					"/Users/Shared/Development/kakadu/v6_2_1-00315N/coresys",
+					"$(inherited)",
+				);
+				INSTALL_PATH = "@loader_path/../plugins";
+				LIBRARY_SEARCH_PATHS = (
+					/Users/Shared/Development/kakadu/bin/libkdu_v62R.dylib,
+					"$(DEV_HOME_PATH)/ossim_dependencies/nuiSDK/lib",
+					"$(UNIV_STATICLIB_DEP)",
+					"$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_1)",
+					"$(LIBRARY_SEARCH_PATHS_QUOTED_1)",
+					"$(LIBRARY_SEARCH_PATHS_QUOTED_2)",
+					"$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_2)",
+					"$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_3)",
+				);
+				LIBRARY_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/../../../../gpotts/Downloads/Geo_DSDK-7.0.0.2167/lib/Release\"";
+				LIBRARY_SEARCH_PATHS_QUOTED_2 = "\"$(SRCROOT)/../../ossim_dependencies/lib/mrsid\"";
+				LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_1 = "\"$(SRCROOT)/../../kakadu/bin\"";
+				LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_2 = "\"$(SRCROOT)/../../ossim_dependencies/lib/mrsid\"";
+				LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_3 = "\"$(SRCROOT)/../../ossim_dependencies/mrsid/lib\"";
+				OTHER_CFLAGS = "-g";
+				PREBINDING = NO;
+				PRIVATE_HEADERS_FOLDER_PATH = "";
+				PRODUCT_NAME = ossimkakadu_plugin;
+				PUBLIC_HEADERS_FOLDER_PATH = "";
+				REZ_SEARCH_PATHS = (
+					"$(DEV_HOME_PATH)/ossim_dependencies/nuiSDK/lib",
+					"$(UNIV_STATICLIB_DEP)",
+				);
+				ZERO_LINK = YES;
+			};
+			name = Debug;
+		};
+		436A7E3110FB9FC400985348 /* DebugNative */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ARCHS = "$(inherited)";
+				COPY_PHASE_STRIP = NO;
+				EXECUTABLE_PREFIX = lib;
+				FRAMEWORK_SEARCH_PATHS = (
+					"$(inherited)",
+					"$(FRAMEWORK_SEARCH_PATHS_QUOTED_1)",
+					"$(FRAMEWORK_SEARCH_PATHS_QUOTED_2)",
+				);
+				FRAMEWORK_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/../../ossim_dependencies/Frameworks\"";
+				FRAMEWORK_SEARCH_PATHS_QUOTED_2 = "\"$(SRCROOT)/../../ossim_dependencies/Frameworks\"";
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_ENABLE_FIX_AND_CONTINUE = YES;
+				GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
+				GCC_MODEL_TUNING = "";
+				GCC_OPTIMIZATION_LEVEL = 0;
+				HEADER_SEARCH_PATHS = (
+					"/Users/Shared/Development/kakadu/v6_2_1-00315N/managed/all_includes/",
+					"/Users/Shared/Development/kakadu/v6_2_1-00315N/coresys/transform",
+					"/Users/Shared/Development/kakadu/v6_2_1-00315N/coresys/common",
+					"/Users/Shared/Development/kakadu/v6_2_1-00315N/coresys/coding",
+					"/Users/Shared/Development/kakadu/v6_2_1-00315N/coresys/roi",
+					"/Users/Shared/Development/kakadu/v6_2_1-00315N/coresys",
+					"$(inherited)",
+				);
+				INSTALL_PATH = "@loader_path/../plugins";
+				LIBRARY_SEARCH_PATHS = (
+					/Users/Shared/Development/kakadu/bin/libkdu_v62R.dylib,
+					"$(DEV_HOME_PATH)/ossim_dependencies/nuiSDK/lib",
+					"$(UNIV_STATICLIB_DEP)",
+					"$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_1)",
+					"$(LIBRARY_SEARCH_PATHS_QUOTED_1)",
+					"$(LIBRARY_SEARCH_PATHS_QUOTED_2)",
+					"$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_2)",
+					"$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_3)",
+				);
+				LIBRARY_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/../../../../gpotts/Downloads/Geo_DSDK-7.0.0.2167/lib/Release\"";
+				LIBRARY_SEARCH_PATHS_QUOTED_2 = "\"$(SRCROOT)/../../ossim_dependencies/lib/mrsid\"";
+				LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_1 = "\"$(SRCROOT)/../../kakadu/bin\"";
+				LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_2 = "\"$(SRCROOT)/../../ossim_dependencies/lib/mrsid\"";
+				LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_3 = "\"$(SRCROOT)/../../ossim_dependencies/mrsid/lib\"";
+				OTHER_CFLAGS = "-g";
+				PREBINDING = NO;
+				PRIVATE_HEADERS_FOLDER_PATH = "";
+				PRODUCT_NAME = ossimkakadu_plugin;
+				PUBLIC_HEADERS_FOLDER_PATH = "";
+				REZ_SEARCH_PATHS = (
+					"$(DEV_HOME_PATH)/ossim_dependencies/nuiSDK/lib",
+					"$(UNIV_STATICLIB_DEP)",
+				);
+				ZERO_LINK = YES;
+			};
+			name = DebugNative;
+		};
+		436A7E3210FB9FC400985348 /* DebugNativeLeopard */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ARCHS = "$(inherited)";
+				COPY_PHASE_STRIP = NO;
+				EXECUTABLE_PREFIX = lib;
+				FRAMEWORK_SEARCH_PATHS = (
+					"$(inherited)",
+					"$(FRAMEWORK_SEARCH_PATHS_QUOTED_1)",
+					"$(FRAMEWORK_SEARCH_PATHS_QUOTED_2)",
+				);
+				FRAMEWORK_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/../../ossim_dependencies/Frameworks\"";
+				FRAMEWORK_SEARCH_PATHS_QUOTED_2 = "\"$(SRCROOT)/../../ossim_dependencies/Frameworks\"";
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_ENABLE_FIX_AND_CONTINUE = YES;
+				GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
+				GCC_MODEL_TUNING = "";
+				GCC_OPTIMIZATION_LEVEL = 0;
+				HEADER_SEARCH_PATHS = (
+					"/Users/Shared/Development/kakadu/v6_2_1-00315N/managed/all_includes/",
+					"/Users/Shared/Development/kakadu/v6_2_1-00315N/coresys/transform",
+					"/Users/Shared/Development/kakadu/v6_2_1-00315N/coresys/common",
+					"/Users/Shared/Development/kakadu/v6_2_1-00315N/coresys/coding",
+					"/Users/Shared/Development/kakadu/v6_2_1-00315N/coresys/roi",
+					"/Users/Shared/Development/kakadu/v6_2_1-00315N/coresys",
+					"$(inherited)",
+				);
+				INSTALL_PATH = "@loader_path/../plugins";
+				LIBRARY_SEARCH_PATHS = (
+					/Users/Shared/Development/kakadu/bin/libkdu_v62R.dylib,
+					"$(DEV_HOME_PATH)/ossim_dependencies/nuiSDK/lib",
+					"$(UNIV_STATICLIB_DEP)",
+					"$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_1)",
+					"$(LIBRARY_SEARCH_PATHS_QUOTED_1)",
+					"$(LIBRARY_SEARCH_PATHS_QUOTED_2)",
+					"$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_2)",
+					"$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_3)",
+				);
+				LIBRARY_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/../../../../gpotts/Downloads/Geo_DSDK-7.0.0.2167/lib/Release\"";
+				LIBRARY_SEARCH_PATHS_QUOTED_2 = "\"$(SRCROOT)/../../ossim_dependencies/lib/mrsid\"";
+				LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_1 = "\"$(SRCROOT)/../../kakadu/bin\"";
+				LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_2 = "\"$(SRCROOT)/../../ossim_dependencies/lib/mrsid\"";
+				LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_3 = "\"$(SRCROOT)/../../ossim_dependencies/mrsid/lib\"";
+				OTHER_CFLAGS = "-g";
+				PREBINDING = NO;
+				PRIVATE_HEADERS_FOLDER_PATH = "";
+				PRODUCT_NAME = ossimkakadu_plugin;
+				PUBLIC_HEADERS_FOLDER_PATH = "";
+				REZ_SEARCH_PATHS = (
+					"$(DEV_HOME_PATH)/ossim_dependencies/nuiSDK/lib",
+					"$(UNIV_STATICLIB_DEP)",
+				);
+				ZERO_LINK = YES;
+			};
+			name = DebugNativeLeopard;
+		};
+		436A7E3310FB9FC400985348 /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ARCHS = "$(inherited)";
+				COPY_PHASE_STRIP = YES;
+				EXECUTABLE_PREFIX = lib;
+				FRAMEWORK_SEARCH_PATHS = (
+					"$(inherited)",
+					"$(FRAMEWORK_SEARCH_PATHS_QUOTED_1)",
+					"$(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1)",
+				);
+				FRAMEWORK_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/../../ossim_dependencies/Frameworks\"";
+				FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1 = "\"$(SRCROOT)/../../ossim_dependencies/Frameworks\"";
+				GCC_ENABLE_FIX_AND_CONTINUE = NO;
+				GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
+				GCC_MODEL_TUNING = "";
+				GCC_VERSION = "$(inherited)";
+				HEADER_SEARCH_PATHS = (
+					"$(inherited)",
+					"$(UNIV_DEP)/mrsid/include",
+				);
+				INSTALL_PATH = "@loader_path/../plugins";
+				LIBRARY_SEARCH_PATHS = (
+					/Users/Shared/Development/kakadu/bin/libkdu_v62R.dylib,
+					"$(DEV_HOME_PATH)/ossim_dependencies/nuiSDK/lib",
+					"$(UNIV_STATICLIB_DEP)",
+					"$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_1)",
+					"$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_2)",
+					"$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_3)",
+					"$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_4)",
+					"$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_5)",
+				);
+				LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_1 = "\"$(SRCROOT)/../../kakadu/bin\"";
+				LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_2 = "\"$(SRCROOT)/../../../../gpotts/Downloads/Geo_DSDK-7.0.0.2167/lib/Release\"";
+				LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_3 = "\"$(SRCROOT)/../../ossim_dependencies/lib/mrsid\"";
+				LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_4 = "\"$(SRCROOT)/../../ossim_dependencies/lib/mrsid\"";
+				LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_5 = "\"$(SRCROOT)/../../ossim_dependencies/mrsid/lib\"";
+				OTHER_CFLAGS = (
+					"-g",
+					"-DOSSIM_ENABLE_MRSID_WRITE=0",
+				);
+				OTHER_LDFLAGS = (
+					"$(inherited)",
+					"$(UNIV_DEP)/mrsid/lib/libgdal.a",
+				);
+				PREBINDING = NO;
+				PRIVATE_HEADERS_FOLDER_PATH = "";
+				PRODUCT_NAME = ossimmrsid_plugin;
+				PUBLIC_HEADERS_FOLDER_PATH = "";
+				REZ_SEARCH_PATHS = (
+					"$(DEV_HOME_PATH)/ossim_dependencies/nuiSDK/lib",
+					"$(UNIV_STATICLIB_DEP)",
+				);
+				ZERO_LINK = NO;
+			};
+			name = Release;
+		};
+		436A7E3410FB9FC400985348 /* ReleaseLeopard */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ARCHS = "$(inherited)";
+				COPY_PHASE_STRIP = YES;
+				EXECUTABLE_PREFIX = lib;
+				FRAMEWORK_SEARCH_PATHS = (
+					"$(inherited)",
+					"$(FRAMEWORK_SEARCH_PATHS_QUOTED_1)",
+					"$(FRAMEWORK_SEARCH_PATHS_QUOTED_2)",
+				);
+				FRAMEWORK_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/../../ossim_dependencies/Frameworks\"";
+				FRAMEWORK_SEARCH_PATHS_QUOTED_2 = "\"$(SRCROOT)/../../ossim_dependencies/Frameworks\"";
+				GCC_ENABLE_FIX_AND_CONTINUE = NO;
+				GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
+				GCC_MODEL_TUNING = "";
+				HEADER_SEARCH_PATHS = (
+					"/Users/Shared/Development/kakadu/v6_2_1-00315N/managed/all_includes/",
+					"/Users/Shared/Development/kakadu/v6_2_1-00315N/coresys/transform",
+					"/Users/Shared/Development/kakadu/v6_2_1-00315N/coresys/common",
+					"/Users/Shared/Development/kakadu/v6_2_1-00315N/coresys/coding",
+					"/Users/Shared/Development/kakadu/v6_2_1-00315N/coresys/roi",
+					"/Users/Shared/Development/kakadu/v6_2_1-00315N/coresys",
+					"$(inherited)",
+				);
+				INSTALL_PATH = "@loader_path/../plugins";
+				LIBRARY_SEARCH_PATHS = (
+					/Users/Shared/Development/kakadu/bin/libkdu_v62R.dylib,
+					"$(DEV_HOME_PATH)/ossim_dependencies/nuiSDK/lib",
+					"$(UNIV_STATICLIB_DEP)",
+					"$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_1)",
+					"$(LIBRARY_SEARCH_PATHS_QUOTED_1)",
+					"$(LIBRARY_SEARCH_PATHS_QUOTED_2)",
+					"$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_2)",
+					"$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_3)",
+				);
+				LIBRARY_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/../../../../gpotts/Downloads/Geo_DSDK-7.0.0.2167/lib/Release\"";
+				LIBRARY_SEARCH_PATHS_QUOTED_2 = "\"$(SRCROOT)/../../ossim_dependencies/lib/mrsid\"";
+				LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_1 = "\"$(SRCROOT)/../../kakadu/bin\"";
+				LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_2 = "\"$(SRCROOT)/../../ossim_dependencies/lib/mrsid\"";
+				LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_3 = "\"$(SRCROOT)/../../ossim_dependencies/mrsid/lib\"";
+				OTHER_CFLAGS = "-g";
+				PREBINDING = NO;
+				PRIVATE_HEADERS_FOLDER_PATH = "";
+				PRODUCT_NAME = ossimkakadu_plugin;
+				PUBLIC_HEADERS_FOLDER_PATH = "";
+				REZ_SEARCH_PATHS = (
+					"$(DEV_HOME_PATH)/ossim_dependencies/nuiSDK/lib",
+					"$(UNIV_STATICLIB_DEP)",
+				);
+				ZERO_LINK = NO;
+			};
+			name = ReleaseLeopard;
+		};
+		43A9A0A91151AC37000860DA /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ARCHS = "$(inherited)";
+				COPY_PHASE_STRIP = NO;
+				EXECUTABLE_PREFIX = lib;
+				FRAMEWORK_SEARCH_PATHS = (
+					"$(inherited)",
+					"$(FRAMEWORK_SEARCH_PATHS_QUOTED_1)",
+					"$(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1)",
+				);
+				FRAMEWORK_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/../../ossim_dependencies/Frameworks\"";
+				FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1 = "\"$(SRCROOT)/../../ossim_dependencies/Frameworks\"";
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_ENABLE_FIX_AND_CONTINUE = YES;
+				GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
+				GCC_MODEL_TUNING = "";
+				GCC_OPTIMIZATION_LEVEL = 0;
+				HEADER_SEARCH_PATHS = "$(inherited)";
+				INSTALL_PATH = "@loader_path/../plugins";
+				LIBRARY_SEARCH_PATHS = (
+					"$(DEV_HOME_PATH)/ossim_dependencies/nuiSDK/lib",
+					"$(UNIV_STATICLIB_DEP)",
+				);
+				PREBINDING = NO;
+				PRIVATE_HEADERS_FOLDER_PATH = "";
+				PRODUCT_NAME = ossimpng_plugin;
+				PUBLIC_HEADERS_FOLDER_PATH = "";
+				REZ_SEARCH_PATHS = (
+					"$(DEV_HOME_PATH)/ossim_dependencies/nuiSDK/lib",
+					"$(UNIV_STATICLIB_DEP)",
+				);
+				ZERO_LINK = YES;
+			};
+			name = Debug;
+		};
+		43A9A0AA1151AC37000860DA /* DebugNative */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ARCHS = "$(inherited)";
+				COPY_PHASE_STRIP = NO;
+				EXECUTABLE_PREFIX = lib;
+				FRAMEWORK_SEARCH_PATHS = (
+					"$(inherited)",
+					"$(FRAMEWORK_SEARCH_PATHS_QUOTED_1)",
+					"$(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1)",
+				);
+				FRAMEWORK_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/../../ossim_dependencies/Frameworks\"";
+				FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1 = "\"$(SRCROOT)/../../ossim_dependencies/Frameworks\"";
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_ENABLE_FIX_AND_CONTINUE = YES;
+				GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
+				GCC_MODEL_TUNING = "";
+				GCC_OPTIMIZATION_LEVEL = 0;
+				HEADER_SEARCH_PATHS = "$(inherited)";
+				INSTALL_PATH = "@loader_path/../plugins";
+				LIBRARY_SEARCH_PATHS = (
+					"$(DEV_HOME_PATH)/ossim_dependencies/nuiSDK/lib",
+					"$(UNIV_STATICLIB_DEP)",
+				);
+				PREBINDING = NO;
+				PRIVATE_HEADERS_FOLDER_PATH = "";
+				PRODUCT_NAME = ossimpng_plugin;
+				PUBLIC_HEADERS_FOLDER_PATH = "";
+				REZ_SEARCH_PATHS = (
+					"$(DEV_HOME_PATH)/ossim_dependencies/nuiSDK/lib",
+					"$(UNIV_STATICLIB_DEP)",
+				);
+				ZERO_LINK = YES;
+			};
+			name = DebugNative;
+		};
+		43A9A0AB1151AC37000860DA /* DebugNativeLeopard */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ARCHS = "$(inherited)";
+				COPY_PHASE_STRIP = NO;
+				EXECUTABLE_PREFIX = lib;
+				FRAMEWORK_SEARCH_PATHS = (
+					"$(inherited)",
+					"$(FRAMEWORK_SEARCH_PATHS_QUOTED_1)",
+					"$(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1)",
+				);
+				FRAMEWORK_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/../../ossim_dependencies/Frameworks\"";
+				FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1 = "\"$(SRCROOT)/../../ossim_dependencies/Frameworks\"";
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_ENABLE_FIX_AND_CONTINUE = YES;
+				GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
+				GCC_MODEL_TUNING = "";
+				GCC_OPTIMIZATION_LEVEL = 0;
+				HEADER_SEARCH_PATHS = "$(inherited)";
+				INSTALL_PATH = "@loader_path/../plugins";
+				LIBRARY_SEARCH_PATHS = (
+					"$(DEV_HOME_PATH)/ossim_dependencies/nuiSDK/lib",
+					"$(UNIV_STATICLIB_DEP)",
+				);
+				PREBINDING = NO;
+				PRIVATE_HEADERS_FOLDER_PATH = "";
+				PRODUCT_NAME = ossimpng_plugin;
+				PUBLIC_HEADERS_FOLDER_PATH = "";
+				REZ_SEARCH_PATHS = (
+					"$(DEV_HOME_PATH)/ossim_dependencies/nuiSDK/lib",
+					"$(UNIV_STATICLIB_DEP)",
+				);
+				ZERO_LINK = YES;
+			};
+			name = DebugNativeLeopard;
+		};
+		43A9A0AC1151AC37000860DA /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ARCHS = "$(inherited)";
+				COPY_PHASE_STRIP = YES;
+				EXECUTABLE_PREFIX = lib;
+				FRAMEWORK_SEARCH_PATHS = (
+					"$(inherited)",
+					"$(FRAMEWORK_SEARCH_PATHS_QUOTED_1)",
+					"$(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1)",
+				);
+				FRAMEWORK_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/../../ossim_dependencies/Frameworks\"";
+				FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1 = "\"$(SRCROOT)/../../ossim_dependencies/Frameworks\"";
+				GCC_ENABLE_FIX_AND_CONTINUE = NO;
+				GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
+				GCC_MODEL_TUNING = "";
+				HEADER_SEARCH_PATHS = (
+					"$(inherited)",
+					"$(DEV_HOME_PATH)/ossim_plugins/ossim",
+				);
+				INSTALL_PATH = "@loader_path/../plugins";
+				LIBRARY_SEARCH_PATHS = (
+					"$(DEV_HOME_PATH)/ossim_dependencies/nuiSDK/lib",
+					"$(UNIV_STATICLIB_DEP)",
+				);
+				OTHER_LDFLAGS = "-lz";
+				PREBINDING = NO;
+				PRIVATE_HEADERS_FOLDER_PATH = "";
+				PRODUCT_NAME = ossim_plugin;
+				PUBLIC_HEADERS_FOLDER_PATH = "";
+				REZ_SEARCH_PATHS = (
+					"$(DEV_HOME_PATH)/ossim_dependencies/nuiSDK/lib",
+					"$(UNIV_STATICLIB_DEP)",
+				);
+				ZERO_LINK = NO;
+			};
+			name = Release;
+		};
+		43A9A0AD1151AC37000860DA /* ReleaseLeopard */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ARCHS = "$(inherited)";
+				COPY_PHASE_STRIP = YES;
+				EXECUTABLE_PREFIX = lib;
+				FRAMEWORK_SEARCH_PATHS = (
+					"$(inherited)",
+					"$(FRAMEWORK_SEARCH_PATHS_QUOTED_1)",
+					"$(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1)",
+				);
+				FRAMEWORK_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/../../ossim_dependencies/Frameworks\"";
+				FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1 = "\"$(SRCROOT)/../../ossim_dependencies/Frameworks\"";
+				GCC_ENABLE_FIX_AND_CONTINUE = NO;
+				GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
+				GCC_MODEL_TUNING = "";
+				HEADER_SEARCH_PATHS = "$(inherited)";
+				INSTALL_PATH = "@loader_path/../plugins";
+				LIBRARY_SEARCH_PATHS = (
+					"$(DEV_HOME_PATH)/ossim_dependencies/nuiSDK/lib",
+					"$(UNIV_STATICLIB_DEP)",
+				);
+				OTHER_LDFLAGS = "-lz";
+				PREBINDING = NO;
+				PRIVATE_HEADERS_FOLDER_PATH = "";
+				PRODUCT_NAME = ossimpng_plugin;
+				PUBLIC_HEADERS_FOLDER_PATH = "";
+				REZ_SEARCH_PATHS = (
+					"$(DEV_HOME_PATH)/ossim_dependencies/nuiSDK/lib",
+					"$(UNIV_STATICLIB_DEP)",
+				);
+				ZERO_LINK = NO;
+			};
+			name = ReleaseLeopard;
+		};
+		EEA720250B2F4256006E37B7 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ARCHS = "$(inherited)";
+				COPY_PHASE_STRIP = NO;
+				EXECUTABLE_PREFIX = lib;
+				FRAMEWORK_SEARCH_PATHS = (
+					"$(inherited)",
+					"$(FRAMEWORK_SEARCH_PATHS_QUOTED_1)",
+				);
+				FRAMEWORK_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/../../ossim_dependencies/Frameworks\"";
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_ENABLE_FIX_AND_CONTINUE = YES;
+				GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
+				GCC_MODEL_TUNING = "";
+				GCC_OPTIMIZATION_LEVEL = 0;
+				HEADER_SEARCH_PATHS = "$(inherited)";
+				INSTALL_PATH = "@loader_path/../plugins";
+				LIBRARY_SEARCH_PATHS = (
+					"$(DEV_HOME_PATH)/ossim_dependencies/nuiSDK/lib",
+					"$(UNIV_STATICLIB_DEP)",
+				);
+				PREBINDING = NO;
+				PRIVATE_HEADERS_FOLDER_PATH = "";
+				PRODUCT_NAME = ossimcontrib_plugin;
+				PUBLIC_HEADERS_FOLDER_PATH = "";
+				REZ_SEARCH_PATHS = (
+					"$(DEV_HOME_PATH)/ossim_dependencies/nuiSDK/lib",
+					"$(UNIV_STATICLIB_DEP)",
+				);
+				ZERO_LINK = YES;
+			};
+			name = Debug;
+		};
+		EEA720260B2F4256006E37B7 /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ARCHS = "$(inherited)";
+				COPY_PHASE_STRIP = YES;
+				EXECUTABLE_PREFIX = lib;
+				FRAMEWORK_SEARCH_PATHS = (
+					"$(inherited)",
+					"$(FRAMEWORK_SEARCH_PATHS_QUOTED_1)",
+				);
+				FRAMEWORK_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/../../ossim_dependencies/Frameworks\"";
+				GCC_ENABLE_FIX_AND_CONTINUE = NO;
+				GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
+				GCC_MODEL_TUNING = "";
+				HEADER_SEARCH_PATHS = "$(inherited)";
+				INSTALL_PATH = "@loader_path/../plugins";
+				LIBRARY_SEARCH_PATHS = (
+					"$(DEV_HOME_PATH)/ossim_dependencies/nuiSDK/lib",
+					"$(UNIV_STATICLIB_DEP)",
+				);
+				PREBINDING = NO;
+				PRIVATE_HEADERS_FOLDER_PATH = "";
+				PRODUCT_NAME = ossimcontrib_plugin;
+				PUBLIC_HEADERS_FOLDER_PATH = "";
+				REZ_SEARCH_PATHS = (
+					"$(DEV_HOME_PATH)/ossim_dependencies/nuiSDK/lib",
+					"$(UNIV_STATICLIB_DEP)",
+				);
+				ZERO_LINK = NO;
+			};
+			name = Release;
+		};
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+		186EF84D0B1F0A5000F7886A /* Build configuration list for PBXProject "ossim_plugins" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				186EF84E0B1F0A5000F7886A /* Debug */,
+				18E4E4C70BE77FD000C8442B /* DebugNative */,
+				18A9BC710CDA151F00F4581A /* DebugNativeLeopard */,
+				186EF84F0B1F0A5000F7886A /* Release */,
+				18B28BB90CD579B8008F45B2 /* ReleaseLeopard */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		186EF86F0B1F184C00F7886A /* Build configuration list for PBXNativeTarget "ossimgdal_plugin" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				186EF8700B1F184C00F7886A /* Debug */,
+				18E4E4C10BE77FD000C8442B /* DebugNative */,
+				18A9BC720CDA151F00F4581A /* DebugNativeLeopard */,
+				186EF8710B1F184C00F7886A /* Release */,
+				18B28BBA0CD579B8008F45B2 /* ReleaseLeopard */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		186EF9870B1F226200F7886A /* Build configuration list for PBXNativeTarget "ossimreg_plugin" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				186EF9880B1F226200F7886A /* Debug */,
+				18E4E4C20BE77FD000C8442B /* DebugNative */,
+				18A9BC730CDA151F00F4581A /* DebugNativeLeopard */,
+				186EF9890B1F226200F7886A /* Release */,
+				18B28BBB0CD579B8008F45B2 /* ReleaseLeopard */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		186EFA220B1F323800F7886A /* Build configuration list for PBXNativeTarget "ossimworldwind_plugin" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				186EFA230B1F323800F7886A /* Debug */,
+				18E4E4C30BE77FD000C8442B /* DebugNative */,
+				18A9BC740CDA151F00F4581A /* DebugNativeLeopard */,
+				186EFA240B1F323800F7886A /* Release */,
+				18B28BBC0CD579B8008F45B2 /* ReleaseLeopard */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		186EFA630B1F396700F7886A /* Build configuration list for PBXNativeTarget "ossimnui_plugin" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				186EFA640B1F396700F7886A /* Debug */,
+				18E4E4C40BE77FD000C8442B /* DebugNative */,
+				18A9BC750CDA151F00F4581A /* DebugNativeLeopard */,
+				186EFA650B1F396700F7886A /* Release */,
+				18B28BBD0CD579B8008F45B2 /* ReleaseLeopard */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		430D1FDE0BB2F96B0057E5FF /* Build configuration list for PBXNativeTarget "ossimpng_plugin" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				430D1FDF0BB2F96B0057E5FF /* Debug */,
+				18E4E4C60BE77FD000C8442B /* DebugNative */,
+				18A9BC770CDA151F00F4581A /* DebugNativeLeopard */,
+				430D1FE00BB2F96B0057E5FF /* Release */,
+				18B28BBF0CD579B8008F45B2 /* ReleaseLeopard */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		4313210C103C84DF00F96FDF /* Build configuration list for PBXNativeTarget "ossimkakadu_plugin" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				4313210D103C84DF00F96FDF /* Debug */,
+				4313210E103C84DF00F96FDF /* DebugNative */,
+				4313210F103C84DF00F96FDF /* DebugNativeLeopard */,
+				43132110103C84DF00F96FDF /* Release */,
+				43132111103C84DF00F96FDF /* ReleaseLeopard */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		43377EFE10CFFAE800ECC5AD /* Build configuration list for PBXNativeTarget "ossimcsm_plugin" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				43377EF610CFFACA00ECC5AD /* Debug */,
+				43377EF710CFFACA00ECC5AD /* DebugNative */,
+				43377EF810CFFACA00ECC5AD /* DebugNativeLeopard */,
+				43377EF910CFFACA00ECC5AD /* Release */,
+				43377EFA10CFFACA00ECC5AD /* ReleaseLeopard */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		43378DD710D0221400ECC5AD /* Build configuration list for PBXAggregateTarget "All" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				43378DC110D021EE00ECC5AD /* Debug */,
+				43378DC210D021EE00ECC5AD /* DebugNative */,
+				43378DC310D021EE00ECC5AD /* DebugNativeLeopard */,
+				43378DC410D021EE00ECC5AD /* Release */,
+				43378DC510D021EE00ECC5AD /* ReleaseLeopard */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		436A7E2F10FB9FC400985348 /* Build configuration list for PBXNativeTarget "ossimmrsid_plugin" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				436A7E3010FB9FC400985348 /* Debug */,
+				436A7E3110FB9FC400985348 /* DebugNative */,
+				436A7E3210FB9FC400985348 /* DebugNativeLeopard */,
+				436A7E3310FB9FC400985348 /* Release */,
+				436A7E3410FB9FC400985348 /* ReleaseLeopard */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		43A9A0A81151AC37000860DA /* Build configuration list for PBXNativeTarget "ossim_plugin" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				43A9A0A91151AC37000860DA /* Debug */,
+				43A9A0AA1151AC37000860DA /* DebugNative */,
+				43A9A0AB1151AC37000860DA /* DebugNativeLeopard */,
+				43A9A0AC1151AC37000860DA /* Release */,
+				43A9A0AD1151AC37000860DA /* ReleaseLeopard */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		EEA720240B2F4256006E37B7 /* Build configuration list for PBXNativeTarget "ossimcontrib_plugin" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				EEA720250B2F4256006E37B7 /* Debug */,
+				18E4E4C50BE77FD000C8442B /* DebugNative */,
+				18A9BC760CDA151F00F4581A /* DebugNativeLeopard */,
+				EEA720260B2F4256006E37B7 /* Release */,
+				18B28BBE0CD579B8008F45B2 /* ReleaseLeopard */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+/* End XCConfigurationList section */
+	};
+	rootObject = 186EF84C0B1F0A5000F7886A /* Project object */;
+}

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-grass/ossim-plugins.git



More information about the Pkg-grass-devel mailing list