#include #include #include #include #include #include #include #include #include class ReaderWriterGDAL : public osgDB::ReaderWriter { public: virtual const char* className() const { return "GDAL Image Reader"; } virtual bool acceptsExtension(const std::string& extension) { return osgDB::equalCaseInsensitive(extension,"gdal") || osgDB::equalCaseInsensitive(extension,"gdal"); } virtual ReadResult readImage(const std::string& file, const osgDB::ReaderWriter::Options* options) { // Looks like gdal's GDALRasterBand::GetColorInterpretation() // is not giving proper values for ecw images. There is small // hack to get around bool ecwLoad = osgDB::equalCaseInsensitive(osgDB::getFileExtension(file),"ecw"); //if (!acceptsExtension(ext)) return ReadResult::FILE_NOT_HANDLED; osg::notify(osg::INFO) << "GDAL : " << file << std::endl; std::string fileName = osgDB::findDataFile( file, options ); if (fileName.empty()) return ReadResult::FILE_NOT_FOUND; initGDAL(); std::auto_ptr dataset((GDALDataset*)GDALOpen(fileName.c_str(),GA_ReadOnly)); if (!dataset.get()) return ReadResult::FILE_NOT_HANDLED; int dataWidth = dataset->GetRasterXSize(); int dataHeight = dataset->GetRasterYSize(); int windowX = 0; int windowY = 0; int windowWidth = dataWidth; int windowHeight = dataHeight; int destX = 0; int destY = 0; int destWidth = osg::minimum(dataWidth,1024); int destHeight = osg::minimum(dataHeight,1024); // int destWidth = osg::minimum(dataWidth,4096); // int destHeight = osg::minimum(dataHeight,4096); osgDB::ImageOptions::TexCoordRange* texCoordRange = 0; osgDB::ImageOptions* imageOptions = dynamic_cast(const_cast(options)); if (imageOptions) { osg::notify(osg::INFO)<<"Got ImageOptions"<_sourceImageWindowMode) { case(osgDB::ImageOptions::RATIO_WINDOW): { double desiredX = (double)dataWidth * imageOptions->_sourceRatioWindow.windowX; double desiredY = (double)dataHeight * imageOptions->_sourceRatioWindow.windowY; double desiredWidth = (double)dataWidth * imageOptions->_sourceRatioWindow.windowWidth; double desiredHeight = (double)dataHeight * imageOptions->_sourceRatioWindow.windowHeight; windowX = osg::maximum((int)(floor(desiredX))-margin,0); windowY = osg::maximum((int)(floor(desiredY))-margin,0); windowWidth = osg::minimum((int)(ceil(desiredX + desiredWidth))+margin,dataWidth)-windowX; windowHeight = osg::minimum((int)(ceil(desiredY + desiredHeight))+margin,dataHeight)-windowY; texCoordRange = new osgDB::ImageOptions::TexCoordRange; texCoordRange->set((desiredX-(double)windowX)/(double)windowWidth, ((double)(windowY+windowHeight) -(desiredY+desiredHeight))/(double)windowHeight, (desiredWidth)/(double)windowWidth, (desiredHeight)/(double)windowHeight); osg::notify(osg::INFO)<<"tex coord range "<_x<<" "<_y<<" "<_w<<" "<_h<_sourcePixelWindow.windowX; windowY = imageOptions->_sourcePixelWindow.windowY; windowWidth = imageOptions->_sourcePixelWindow.windowWidth; windowHeight = imageOptions->_sourcePixelWindow.windowHeight; break; default: // leave source window dimensions as whole image. break; } // reapply the window coords to the pixel window so that calling code // knows the original pixel size imageOptions->_sourcePixelWindow.windowX = windowX; imageOptions->_sourcePixelWindow.windowY = windowY; imageOptions->_sourcePixelWindow.windowWidth = windowWidth; imageOptions->_sourcePixelWindow.windowHeight = windowHeight; switch(imageOptions->_destinationImageWindowMode) { case(osgDB::ImageOptions::RATIO_WINDOW): destX = (unsigned int)(floor((double)dataWidth * imageOptions->_destinationRatioWindow.windowX)); destY = (unsigned int)(floor((double)dataHeight * imageOptions->_destinationRatioWindow.windowY)); destWidth = (unsigned int)(ceil((double)dataWidth * (imageOptions->_destinationRatioWindow.windowX + imageOptions->_destinationRatioWindow.windowWidth)))-windowX; destHeight = (unsigned int)(ceil((double)dataHeight * (imageOptions->_destinationRatioWindow.windowY + imageOptions->_destinationRatioWindow.windowHeight)))-windowY; break; case(osgDB::ImageOptions::PIXEL_WINDOW): destX = imageOptions->_destinationPixelWindow.windowX; destY = imageOptions->_destinationPixelWindow.windowY; destWidth = imageOptions->_destinationPixelWindow.windowWidth; destHeight = imageOptions->_destinationPixelWindow.windowHeight; break; default: // leave source window dimensions as whole image. break; } } // windowX = 0; // windowY = 0; // windowWidth = destWidth; // windowHeight = destHeight; osg::notify(osg::INFO) << " windowX = "<GetRasterCount()<GetProjectionRef()<GetGeoTransform(geoTransform)==CE_None) { osg::notify(osg::INFO) << " GetGeoTransform "<< std::endl; osg::notify(osg::INFO) << " Origin = "<GetRasterCount(); GDALRasterBand* bandGray = 0; GDALRasterBand* bandRed = 0; GDALRasterBand* bandGreen = 0; GDALRasterBand* bandBlue = 0; GDALRasterBand* bandAlpha = 0; int internalFormat = GL_LUMINANCE; unsigned int pixelFormat = GL_LUMINANCE; unsigned int dataType = 0; unsigned int numBytesPerPixel = 0; GDALDataType targetGDALType = GDT_Byte; for(int b=1;b<=numBands;++b) { GDALRasterBand* band = dataset->GetRasterBand(b); osg::notify(osg::INFO) << " Band "<GetRasterDataType(); switch(band->GetRasterDataType()) { case(GDT_Byte): dataType = GL_UNSIGNED_BYTE; numBytesPerPixel = 1; break; case(GDT_UInt16): dataType = GL_UNSIGNED_SHORT; numBytesPerPixel = 2; break; case(GDT_Int16): dataType = GL_SHORT; numBytesPerPixel = 2; break; case(GDT_UInt32): dataType = GL_UNSIGNED_INT; numBytesPerPixel = 4; break; case(GDT_Int32): dataType = GL_INT; numBytesPerPixel = 4; break; case(GDT_Float32): dataType = GL_FLOAT; numBytesPerPixel = 4; break; case(GDT_Float64): dataType = GL_DOUBLE; numBytesPerPixel = 8; break; // not handled default: dataType = 0; numBytesPerPixel = 0; break; // not handled } } } int s = destWidth; int t = destHeight; int r = 1; if (dataType==0) { dataType = GL_UNSIGNED_BYTE; numBytesPerPixel = 1; targetGDALType = GDT_Byte; } unsigned char* imageData = 0; if (bandRed && bandGreen && bandBlue) { if (bandAlpha) { // RGBA int pixelSpace=4*numBytesPerPixel; int lineSpace=destWidth * pixelSpace; imageData = new unsigned char[destWidth * destHeight * pixelSpace]; pixelFormat = GL_RGBA; internalFormat = GL_RGBA; osg::notify(osg::INFO) << "reading RGBA"<RasterIO(GF_Read,windowX,windowY,windowWidth,windowHeight,(void*)(imageData+0),destWidth,destHeight,targetGDALType,pixelSpace,lineSpace); bandGreen->RasterIO(GF_Read,windowX,windowY,windowWidth,windowHeight,(void*)(imageData+1),destWidth,destHeight,targetGDALType,pixelSpace,lineSpace); bandBlue->RasterIO(GF_Read,windowX,windowY,windowWidth,windowHeight,(void*)(imageData+2),destWidth,destHeight,targetGDALType,pixelSpace,lineSpace); bandAlpha->RasterIO(GF_Read,windowX,windowY,windowWidth,windowHeight,(void*)(imageData+3),destWidth,destHeight,targetGDALType,pixelSpace,lineSpace); } else { // RGB int pixelSpace=3*numBytesPerPixel; int lineSpace=destWidth * pixelSpace; imageData = new unsigned char[destWidth * destHeight * pixelSpace]; pixelFormat = GL_RGB; internalFormat = GL_RGB; osg::notify(osg::INFO) << "reading RGB"<RasterIO(GF_Read,windowX,windowY,windowWidth,windowHeight,(void*)(imageData+0),destWidth,destHeight,targetGDALType,pixelSpace,lineSpace); bandGreen->RasterIO(GF_Read,windowX,windowY,windowWidth,windowHeight,(void*)(imageData+1),destWidth,destHeight,targetGDALType,pixelSpace,lineSpace); bandBlue->RasterIO(GF_Read,windowX,windowY,windowWidth,windowHeight,(void*)(imageData+2),destWidth,destHeight,targetGDALType,pixelSpace,lineSpace); } } else if (bandGray) { if (bandAlpha) { // Luminance alpha int pixelSpace=2*numBytesPerPixel; int lineSpace=destWidth * pixelSpace; imageData = new unsigned char[destWidth * destHeight * pixelSpace]; pixelFormat = GL_LUMINANCE_ALPHA; internalFormat = GL_LUMINANCE_ALPHA; osg::notify(osg::INFO) << "reading grey + alpha"<RasterIO(GF_Read,windowX,windowY,windowWidth,windowHeight,(void*)(imageData+0),destWidth,destHeight,targetGDALType,pixelSpace,lineSpace); bandAlpha->RasterIO(GF_Read,windowX,windowY,windowWidth,windowHeight,(void*)(imageData+1),destWidth,destHeight,targetGDALType,pixelSpace,lineSpace); } else { // Luminance map int pixelSpace=1*numBytesPerPixel; int lineSpace=destWidth * pixelSpace; imageData = new unsigned char[destWidth * destHeight * pixelSpace]; pixelFormat = GL_LUMINANCE; internalFormat = GL_LUMINANCE; osg::notify(osg::INFO) << "reading grey"<RasterIO(GF_Read,windowX,windowY,windowWidth,windowHeight,(void*)(imageData+0),destWidth,destHeight,targetGDALType,pixelSpace,lineSpace); } } else if (bandAlpha) { // alpha map int pixelSpace=1*numBytesPerPixel; int lineSpace=destWidth * pixelSpace; imageData = new unsigned char[destWidth * destHeight * pixelSpace]; pixelFormat = GL_ALPHA; internalFormat = GL_ALPHA; osg::notify(osg::INFO) << "reading alpha"<RasterIO(GF_Read,windowX,windowY,windowWidth,windowHeight,(void*)(imageData+0),destWidth,destHeight,targetGDALType,pixelSpace,lineSpace); } else { osg::notify(osg::INFO) << "not found any usable bands in file."<setFileName(fileName.c_str()); image->setImage(s,t,r, internalFormat, pixelFormat, dataType, (unsigned char *)imageData, osg::Image::USE_NEW_DELETE); if (texCoordRange) image->setUserData(texCoordRange); image->flipVertical(); return image; } return 0; } virtual ReadResult readHeightField(const std::string& fileName, const osgDB::ReaderWriter::Options* options) { //std::string ext = osgDB::getFileExtension(fileName); //if (!acceptsExtension(ext)) return ReadResult::FILE_NOT_HANDLED; initGDAL(); std::auto_ptr dataset((GDALDataset*)GDALOpen(fileName.c_str(),GA_ReadOnly)); if (!dataset.get()) return ReadResult::FILE_NOT_HANDLED; int dataWidth = dataset->GetRasterXSize(); int dataHeight = dataset->GetRasterYSize(); int windowX = 0; int windowY = 0; int windowWidth = dataWidth; int windowHeight = dataHeight; int destX = 0; int destY = 0; int destWidth = osg::minimum(dataWidth,1024); int destHeight = osg::minimum(dataHeight,1024); osgDB::ImageOptions::TexCoordRange* texCoordRange = 0; const osgDB::ImageOptions* imageOptions = dynamic_cast(options); if (imageOptions) { osg::notify(osg::INFO)<<"Got ImageOptions"<_sourceImageWindowMode) { case(osgDB::ImageOptions::RATIO_WINDOW): { double desiredX = (double)dataWidth * imageOptions->_sourceRatioWindow.windowX; double desiredY = (double)dataHeight * imageOptions->_sourceRatioWindow.windowY; double desiredWidth = (double)dataWidth * imageOptions->_sourceRatioWindow.windowWidth; double desiredHeight = (double)dataHeight * imageOptions->_sourceRatioWindow.windowHeight; windowX = osg::maximum((int)(floor(desiredX))-margin,0); windowY = osg::maximum((int)(floor(desiredY))-margin,0); windowWidth = osg::minimum((int)(ceil(desiredX + desiredWidth))+margin,dataWidth)-windowX; windowHeight = osg::minimum((int)(ceil(desiredY + desiredHeight))+margin,dataHeight)-windowY; texCoordRange = new osgDB::ImageOptions::TexCoordRange; texCoordRange->set((desiredX-(double)windowX)/(double)windowWidth, ((double)(windowY+windowHeight) -(desiredY+desiredHeight))/(double)windowHeight, (desiredWidth)/(double)windowWidth, (desiredHeight)/(double)windowHeight); osg::notify(osg::INFO)<<"tex coord range "<_x<<" "<_y<<" "<_w<<" "<_h<_sourcePixelWindow.windowX; windowY = imageOptions->_sourcePixelWindow.windowY; windowWidth = imageOptions->_sourcePixelWindow.windowWidth; windowHeight = imageOptions->_sourcePixelWindow.windowHeight; break; default: // leave source window dimensions as whole image. break; } switch(imageOptions->_destinationImageWindowMode) { case(osgDB::ImageOptions::RATIO_WINDOW): destX = (unsigned int)(floor((double)dataWidth * imageOptions->_destinationRatioWindow.windowX)); destY = (unsigned int)(floor((double)dataHeight * imageOptions->_destinationRatioWindow.windowY)); destWidth = (unsigned int)(ceil((double)dataWidth * (imageOptions->_destinationRatioWindow.windowX + imageOptions->_destinationRatioWindow.windowWidth)))-windowX; destHeight = (unsigned int)(ceil((double)dataHeight * (imageOptions->_destinationRatioWindow.windowY + imageOptions->_destinationRatioWindow.windowHeight)))-windowY; break; case(osgDB::ImageOptions::PIXEL_WINDOW): destX = imageOptions->_destinationPixelWindow.windowX; destY = imageOptions->_destinationPixelWindow.windowY; destWidth = imageOptions->_destinationPixelWindow.windowWidth; destHeight = imageOptions->_destinationPixelWindow.windowHeight; break; default: // leave source window dimensions as whole image. break; } } // windowX = 0; // windowY = 0; // windowWidth = destWidth; // windowHeight = destHeight; osg::notify(osg::INFO) << " windowX = "<GetRasterCount()<GetProjectionRef()<GetGeoTransform(geoTransform)<<" == CE_None"<GetGCPCount()<GetRasterCount(); GDALRasterBand* bandGray = 0; GDALRasterBand* bandRed = 0; GDALRasterBand* bandGreen = 0; GDALRasterBand* bandBlue = 0; GDALRasterBand* bandAlpha = 0; for(int b=1;b<=numBands;++b) { GDALRasterBand* band = dataset->GetRasterBand(b); osg::notify(osg::INFO) << " Band "<GetColorInterpretation()==GCI_GrayIndex) bandGray = band; else if (band->GetColorInterpretation()==GCI_RedBand) bandRed = band; else if (band->GetColorInterpretation()==GCI_GreenBand) bandGreen = band; else if (band->GetColorInterpretation()==GCI_BlueBand) bandBlue = band; else if (band->GetColorInterpretation()==GCI_AlphaBand) bandAlpha = band; else bandGray = band; } GDALRasterBand* bandSelected = 0; if (!bandSelected && bandGray) bandSelected = bandGray; else if (!bandSelected && bandAlpha) bandSelected = bandAlpha; else if (!bandSelected && bandRed) bandSelected = bandRed; else if (!bandSelected && bandGreen) bandSelected = bandGreen; else if (!bandSelected && bandBlue) bandSelected = bandBlue; if (bandSelected) { osg::HeightField* hf = new osg::HeightField; hf->allocate(destWidth,destHeight); bandSelected->RasterIO(GF_Read,windowX,windowY,windowWidth,windowHeight,(void*)(&(hf->getHeightList().front())),destWidth,destHeight,GDT_Float32,0,0); // now need to flip since the OSG's origin is in lower left corner. osg::notify(osg::INFO)<<"flipping"<getNumRows()-1; for(unsigned int r=0;rgetNumColumns();++c) { float temp = hf->getHeight(c,r); hf->setHeight(c,r,hf->getHeight(c,copy_r)); hf->setHeight(c,copy_r,temp); } } return hf; } return ReadResult::FILE_NOT_HANDLED; } void initGDAL() { static bool s_initialized = false; if (!s_initialized) { s_initialized = true; GDALAllRegister(); } } }; // now register with Registry to instantiate the above // reader/writer. osgDB::RegisterReaderWriterProxy g_readerWriter_GDAL_Proxy;