osgEarth 2.1.1

/home/cube/sources/osgearth/src/osgEarth/ImageToHeightFieldConverter.cpp

Go to the documentation of this file.
00001 /* -*-c++-*- */
00002 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
00003 * Copyright 2008-2010 Pelican Mapping
00004 * http://osgearth.org
00005 *
00006 * osgEarth is free software; you can redistribute it and/or modify
00007 * it under the terms of the GNU Lesser General Public License as published by
00008 * the Free Software Foundation; either version 2 of the License, or
00009 * (at your option) any later version.
00010 *
00011 * This program is distributed in the hope that it will be useful,
00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 * GNU Lesser General Public License for more details.
00015 *
00016 * You should have received a copy of the GNU Lesser General Public License
00017 * along with this program.  If not, see <http://www.gnu.org/licenses/>
00018 */
00019 
00020 #include <osgEarth/ImageToHeightFieldConverter>
00021 #include <osg/Notify>
00022 #include <limits.h>
00023 #include <string.h>
00024 
00025 using namespace osgEarth;
00026 
00027 static bool
00028 isNoData( short s )
00029 {
00030   return s == SHRT_MAX || s == SHRT_MIN;
00031 }
00032 
00033 static bool
00034 isNoData( float f )
00035 {
00036   return f == FLT_MAX || f == FLT_MIN;
00037 }
00038 
00039 
00040 ImageToHeightFieldConverter::ImageToHeightFieldConverter():
00041 _replace_nodata( false ),
00042 _nodata_value( 0.0f )
00043 {
00044   //NOP
00045 }
00046 
00047 void
00048 ImageToHeightFieldConverter::setRemoveNoDataValues( bool which, float f )
00049 {
00050   _nodata_value = f;
00051   _replace_nodata = which;
00052 }
00053 
00054 osg::HeightField* ImageToHeightFieldConverter::convert(const osg::Image* image ) {
00055   if ( !image ) {
00056     return NULL;
00057   }
00058 
00059   osg::HeightField* hf;
00060   if ( image->getPixelSizeInBits() == 32 ) {
00061     hf = convert32( image );
00062   } else {
00063     hf = convert16( image );
00064   }
00065 
00066   // scan for and replace NODATA values. This algorithm is terrible but good enough for now
00067   if ( _replace_nodata )
00068   {
00069     for( unsigned int row=0; row < hf->getNumRows(); ++row )
00070     {
00071       for( unsigned int col=0; col < hf->getNumColumns(); ++col )
00072       {
00073         float val = hf->getHeight(col, row);
00074         if ( !isNoData( val ) ) {
00075           continue;
00076         }
00077         if ( col > 0 )
00078           val = hf->getHeight(col-1,row);
00079         else if ( col <= hf->getNumColumns()-1 )
00080           val = hf->getHeight(col+1,row);
00081 
00082         if ( isNoData( val ) )
00083         {
00084           if ( row > 0 )
00085             val = hf->getHeight(col, row-1);
00086           else if ( row < hf->getNumRows()-1 )
00087             val = hf->getHeight(col, row+1);
00088         }
00089 
00090         if ( isNoData( val ) )
00091         {
00092           val = _nodata_value;
00093         }
00094 
00095         hf->setHeight( col, row, val );
00096       }
00097     }
00098   }
00099 
00100   return hf;
00101 }
00102 
00103 osg::HeightField* ImageToHeightFieldConverter::convert16(const osg::Image* image ) const {
00104   if ( !image ) {
00105     return NULL;
00106   }
00107 
00108   osg::HeightField *hf = new osg::HeightField();
00109   hf->allocate( image->s(), image->t() );
00110 
00111   osg::FloatArray* floats = hf->getFloatArray();
00112 
00113   for( unsigned int i = 0; i < floats->size(); ++i ) {
00114     floats->at( i ) = *(short*)image->data(i);
00115   }
00116 
00117   return hf;
00118 }
00119 
00120 osg::HeightField* ImageToHeightFieldConverter::convert32(const osg::Image* image ) const {
00121   if ( !image ) {
00122     return NULL;
00123   }
00124 
00125   osg::HeightField *hf = new osg::HeightField();
00126   hf->allocate( image->s(), image->t() );
00127 
00128   memcpy( &hf->getFloatArray()->front(), image->data(), sizeof(float) * hf->getFloatArray()->size() );
00129 
00130   return hf;
00131 }
00132 
00133 
00134 osg::HeightField*
00135 ImageToHeightFieldConverter::convert(const osg::Image* image, float scaleFactor)
00136 {
00137   if ( !image ) {
00138     return NULL;
00139   }
00140 
00141   osg::HeightField* hf = convert( image );
00142 
00143   // finally, apply the scale factor.
00144   for( osg::FloatArray::iterator i = hf->getFloatArray()->begin(); i != hf->getFloatArray()->end(); ++i )
00145   {
00146     (*i) *= scaleFactor;
00147   }
00148 
00149   return hf;
00150 }
00151 
00152 osg::Image*
00153 ImageToHeightFieldConverter::convert(const osg::HeightField* hf, int pixelSize)
00154 {
00155   if ( pixelSize == 32 ) {
00156     return convert32( hf );
00157   }
00158 
00159   return convert16( hf );
00160 }
00161 
00162 osg::Image* ImageToHeightFieldConverter::convert16(const osg::HeightField* hf ) const {
00163   if ( !hf ) {
00164     return NULL;
00165   }
00166 
00167   osg::Image* image = new osg::Image();
00168   image->allocateImage(hf->getNumColumns(), hf->getNumRows(), 1, GL_LUMINANCE, GL_SHORT);
00169 
00170   const osg::FloatArray* floats = hf->getFloatArray();
00171 
00172   for( unsigned int i = 0; i < floats->size(); ++i  ) {
00173     *(short*)image->data(i) = (short)floats->at( i );
00174   }
00175 
00176   return image;
00177 }
00178 
00179 osg::Image* ImageToHeightFieldConverter::convert32(const osg::HeightField* hf) const {
00180   if ( !hf ) {
00181     return NULL;
00182   }
00183 
00184   osg::Image* image = new osg::Image();
00185   image->allocateImage(hf->getNumColumns(), hf->getNumRows(), 1, GL_LUMINANCE, GL_FLOAT);
00186 
00187   memcpy( image->data(), &hf->getFloatArray()->front(), sizeof(float) * hf->getFloatArray()->size() );
00188 
00189   return image;
00190 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines