osgEarth 2.1.1
|
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 }