[Liblas-commits] hg: rough implementation of ColorFetchingTransform

liblas-commits at liblas.org liblas-commits at liblas.org
Thu Nov 11 09:28:25 EST 2010


changeset c84f93be7b8a in /Volumes/Data/www/liblas.org/hg
details: http://hg.liblas.orghg?cmd=changeset;node=c84f93be7b8a
summary: rough implementation of ColorFetchingTransform

diffstat:

 include/liblas/lastransform.hpp |   48 ++++++++++++++++
 src/lastransform.cpp            |  119 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 167 insertions(+), 0 deletions(-)

diffs (197 lines):

diff -r e7b05df8f778 -r c84f93be7b8a include/liblas/lastransform.hpp
--- a/include/liblas/lastransform.hpp	Wed Nov 10 09:40:44 2010 -0600
+++ b/include/liblas/lastransform.hpp	Wed Nov 10 11:47:20 2010 -0600
@@ -48,10 +48,15 @@
 #include <liblas/export.hpp>
 // boost
 #include <boost/shared_ptr.hpp>
+#include <boost/array.hpp>
 // std
 #include <vector>
 #include <string>
 
+#ifdef HAVE_GDAL
+#include <gdal.h>
+#endif
+
 namespace liblas {
 
 /// Defines public interface to LAS transform implementation.
@@ -155,6 +160,49 @@
     
     std::string m_expression;
 };
+
+
+class LAS_DLL ColorFetchingTransform: public TransformI
+{
+public:
+    
+    ColorFetchingTransform( std::string const& datasource, 
+                            std::vector<boost::uint32_t> bands
+                            );
+    ~ColorFetchingTransform();
+
+    bool transform(Point& point);
+
+private:
+
+#ifdef HAVE_GDAL
+    struct GDALSourceDeleter
+    {
+       template <typename T>
+       void operator()(T* ptr)
+       {
+           ::GDALClose(ptr);
+       }
+    };
+
+
+#endif
+
+    liblas::HeaderPtr m_new_header;
+    
+    typedef boost::shared_ptr<void> DataSourcePtr;
+    
+    DataSourcePtr m_ds;
+    std::string m_datasource;
+    std::vector<boost::uint32_t> m_bands;
+    boost::array<double, 6> m_forward_transform;
+    boost::array<double, 6> m_inverse_transform;
+
+    ColorFetchingTransform(ColorFetchingTransform const& other);
+    ColorFetchingTransform& operator=(ColorFetchingTransform const& rhs);
+    
+    void Initialize();
+};
 } // namespace liblas
 
 #endif // ndef LIBLAS_LASTRANSFORM_HPP_INCLUDED
diff -r e7b05df8f778 -r c84f93be7b8a src/lastransform.cpp
--- a/src/lastransform.cpp	Wed Nov 10 09:40:44 2010 -0600
+++ b/src/lastransform.cpp	Wed Nov 10 11:47:20 2010 -0600
@@ -380,5 +380,124 @@
 {
 }
 
+#ifdef HAVE_GDAL
+void CPL_STDCALL ColorFetchingTransformGDALErrorHandler(CPLErr eErrClass, int err_no, const char *msg)
+{
+    std::ostringstream oss;
+    
+    if (eErrClass == CE_Failure || eErrClass == CE_Fatal) {
+        oss <<"GDAL Failure number=" << err_no << ": " << msg;
+        throw std::runtime_error(oss.str());
+    } else {
+        return;
+    }
+}
+#endif
+
+ColorFetchingTransform::ColorFetchingTransform(
+    std::string const& datasource, 
+    std::vector<boost::uint32_t> bands
+)
+    : m_ds(DataSourcePtr())
+    , m_datasource(datasource)
+    , m_bands(bands)
+{
+    Initialize();
+}
+
+void ColorFetchingTransform::Initialize()
+{
+#ifdef HAVE_GDAL
+    GDALAllRegister();
+
+
+    CPLPopErrorHandler();
+    CPLPushErrorHandler(ColorFetchingTransformGDALErrorHandler);
+
+    m_ds = DataSourcePtr(GDALOpen( m_datasource.c_str(), GA_ReadOnly ), GDALSourceDeleter());
+
+    // Assume the first three bands are RGB, and not get any more if the 
+    // user did not supply any bands 
+    if( m_bands.size() == 0 )
+    {
+        for( boost::int32_t i = 0; i < GDALGetRasterCount( m_ds.get() ); i++ )
+        {
+            if (i > 3) break;  
+            m_bands.push_back( i+1 );
+        }
+    }
+    
+    if (GDALGetGeoTransform( m_ds.get(), &m_forward_transform[0] ) != CE_None )
+    {
+        throw std::runtime_error("unable to fetch forward geotransform for raster!");
+    }
+
+    m_forward_transform.assign(0.0);
+    m_inverse_transform.assign(0.0);
+
+    GDALInvGeoTransform( &m_forward_transform[0], &m_inverse_transform[0] );
+
+#endif  
+}
+
+bool ColorFetchingTransform::transform(Point& point)
+{
+#ifdef HAVE_GDAL
+    
+    boost::int32_t pixel = 0;
+    boost::int32_t line = 0;
+    
+    double x = point.GetX();
+    double y = point.GetY();
+    
+
+    pixel = (boost::int32_t) std::floor(
+        m_inverse_transform[0] 
+        + m_inverse_transform[1] * x
+        + m_inverse_transform[2] * y );
+    line = (boost::int32_t) std::floor(
+        m_inverse_transform[3] 
+        + m_inverse_transform[4] * x
+        + m_inverse_transform[5] * y );
+ 
+    if( pixel < 0 || line < 0 
+        || pixel >= GDALGetRasterXSize( m_ds.get() )
+        || line  >= GDALGetRasterYSize( m_ds.get() )
+        )
+    {
+        // The x, y is not coincident with this raster, we'll leave whatever
+        // color value might be there alone.
+        return true;
+    }
+    
+    boost::array<double, 2> pix;
+    boost::array<liblas::Color::value_type, 3> color;
+    
+    for( std::vector<boost::int32_t>::size_type i = 0; 
+         i < m_bands.size(); i++ )
+         {
+             GDALRasterBandH hBand = GDALGetRasterBand( m_ds.get(), m_bands[i] );
+             if (hBand == NULL)
+                 continue;       
+             if( GDALRasterIO( hBand, GF_Read, pixel, line, 1, 1, 
+                               &pix[0], 1, 1, GDT_CFloat64, 0, 0) == CE_None )
+             {
+                 color[i] = static_cast<liblas::Color::value_type>(pix[0]); 
+             }             
+         }
+     point.SetColor(Color(color));
+
+    return true;
+#else
+    boost::ignore_unused_variable_warning(point);
+    return true;
+#endif
+}
+ColorFetchingTransform::~ColorFetchingTransform()
+{
+#ifdef HAVE_GDAL
+    CPLPopErrorHandler();
+#endif
+}
 
 } // namespace liblas


More information about the Liblas-commits mailing list