void write_map(fs::path file_path, GDALDataType data_type, boost::shared_ptr<Map_Matrix<DataFormat> > data, std::string WKTprojection, GeoTransform transform, std::string driverName) throw(std::runtime_error) { GDALAllRegister(); //This registers all availble raster file formats for use with this utility. How neat is that. We can input any GDAL supported rater file format. const char *pszFormat = driverName.c_str(); GDALDriver * poDriver = GetGDALDriverManager()->GetDriverByName(pszFormat); if (poDriver == NULL) { throw std::runtime_error("No driver for file tyle found"); } char ** papszMetadata = poDriver->GetMetadata(); if (!(CSLFetchBoolean(papszMetadata, GDAL_DCAP_CREATE, FALSE))) { throw std::runtime_error("Driver does not support raster creation"); } char **papszOptions = NULL; papszOptions = CSLSetNameValue(papszOptions, "COMPRESS", "LZW"); GDALDataset *poDstDS = poDriver->Create(file_path.string().c_str(), (int)data->NCols(), (int)data->NRows(), 1, data_type, papszOptions); double adfGeoTransform[6] = {1, 1, 1, 1, 1, 1}; adfGeoTransform[0] = transform.x_origin; adfGeoTransform[1] = transform.pixel_width; adfGeoTransform[2] = transform.x_line_space; adfGeoTransform[3] = transform.y_origin; adfGeoTransform[4] = transform.pixel_height; adfGeoTransform[5] = transform.y_line_space; const char * psz_WKT = WKTprojection.c_str(); poDstDS->SetGeoTransform(adfGeoTransform); poDstDS->SetProjection(psz_WKT); DataFormat * pafScanline = new DataFormat[data->NCols() * data->NRows()]; int pafIterator = 0; for (int i = 0; i < data->NRows(); i++) { for (int j = 0; j < data->NCols(); j++) { pafScanline[pafIterator] = data->Get(i, j); pafIterator++; } } GDALRasterBand * poBand = poDstDS->GetRasterBand(1); poBand->SetNoDataValue(data->NoDataValue()); poBand->RasterIO(GF_Write, 0, 0, (int) data->NCols(), (int) data->NRows(), pafScanline, (int) data->NCols(), (int) data->NRows(), data_type, 0, 0); GDALClose( (GDALDatasetH) poDstDS); }
SEXP RGDAL_SetNoDataValue(SEXP sxpRasterBand, SEXP NoDataValue) { CPLErr err; GDALRasterBand *pRasterBand = getGDALRasterPtr(sxpRasterBand); err = pRasterBand->SetNoDataValue(NUMERIC_POINTER(NoDataValue)[0]); if (err == CE_Failure) warning("setting of missing value not supported by this driver"); return(sxpRasterBand); }
void saveGDAL(const std::string &filename, const std::string &template_name, int xoffset, int yoffset){ GDALDataset *fintempl = (GDALDataset*)GDALOpen(template_name.c_str(), GA_ReadOnly); assert(fintempl!=NULL); //TODO: Error handle GDALDriver *poDriver = GetGDALDriverManager()->GetDriverByName("GTiff"); assert(poDriver!=NULL); //TODO: Error handle GDALDataset *fout = poDriver->Create(filename.c_str(), viewWidth(), viewHeight(), 1, myGDALType(), NULL); assert(fout!=NULL); //TODO: Error handle GDALRasterBand *oband = fout->GetRasterBand(1); oband->SetNoDataValue(no_data); //The geotransform maps each grid cell to a point in an affine-transformed //projection of the actual terrain. The geostransform is specified as follows: // Xgeo = GT(0) + Xpixel*GT(1) + Yline*GT(2) // Ygeo = GT(3) + Xpixel*GT(4) + Yline*GT(5) //In case of north up images, the GT(2) and GT(4) coefficients are zero, and //the GT(1) is pixel width, and GT(5) is pixel height. The (GT(0),GT(3)) //position is the top left corner of the top left pixel of the raster. double geotrans[6]; fintempl->GetGeoTransform(geotrans); //We shift the top-left pixel of hte image eastward to the appropriate //coordinate geotrans[0] += xoffset*geotrans[1]; //We shift the top-left pixel of the image southward to the appropriate //coordinate geotrans[3] += yoffset*geotrans[5]; #ifdef DEBUG std::cerr<<"Filename: "<<std::setw(20)<<filename<<" Xoffset: "<<std::setw(6)<<xoffset<<" Yoffset: "<<std::setw(6)<<yoffset<<" Geotrans0: "<<std::setw(10)<<std::setprecision(10)<<std::fixed<<geotrans[0]<<" Geotrans3: "<<std::setw(10)<<std::setprecision(10)<<std::fixed<<geotrans[3]<< std::endl; #endif fout->SetGeoTransform(geotrans); const char* projection_string=fintempl->GetProjectionRef(); fout->SetProjection(projection_string); GDALClose(fintempl); for(int y=0;y<view_height;y++) oband->RasterIO(GF_Write, 0, y, viewWidth(), 1, data[y].data(), viewWidth(), 1, myGDALType(), 0, 0); GDALClose(fout); }
bool GDALUtilities::createRasterFile(QString& theFilename, QString& theFormat, GDALDataType theType, int theBands, int theRows, int theCols, void ** theData, double * theGeoTransform, const QgsCoordinateReferenceSystem * theCrs, double theNodataValue) { if ( theBands <= 0 ) return false; if ( theRows <= 0 ) return false; if ( theCols <= 0 ) return false; if ( !theData ) return false; /* bool formatSupported = false; QMapIterator<QString, QString> i(mSupportedFormats); while (i.hasNext()) { i.next(); if( theFormat == i.key()) { formatSupported = true; break; } } if ( !formatSupported ) return false; */ //GDALAllRegister(); GDALDriver * driver; //set format char * format = new char[theFormat.size() + 1]; strcpy( format, theFormat.toLocal8Bit().data() ); driver = GetGDALDriverManager()->GetDriverByName(format); if( driver == NULL ) return false; char ** metadata = driver->GetMetadata(); if( !CSLFetchBoolean( metadata, GDAL_DCAP_CREATE, FALSE ) ) return false; GDALDataset * dstDS; //set options char ** options = NULL; options = CSLSetNameValue( options, "COMPRESS", "LZW" ); //if it is a GeoTIFF format set correct compression options if ( !strcmp( format, "GTiff" ) ) { if( theType == GDT_Byte ) { options = CSLSetNameValue( options, "PREDICTOR", "1" ); } else { if ( theType == GDT_UInt16 || theType == GDT_Int16 || theType == GDT_UInt32 || theType == GDT_Int32 ) { options = CSLSetNameValue( options, "PREDICTOR", "2" ); } else { options = CSLSetNameValue( options, "PREDICTOR", "3" ); } } } //set filename char * dstFilename = new char[theFilename.size() + 1]; strcpy( dstFilename, theFilename.toLocal8Bit().data() ); dstDS = driver->Create( dstFilename, theCols, theRows, theBands, theType, options ); delete dstFilename; delete [] options; //set geotransform dstDS->SetGeoTransform( theGeoTransform ); //set CRS char * crsWkt = new char[theCrs->toWkt().size() + 1]; strcpy( crsWkt, theCrs->toWkt().toLocal8Bit().data()); dstDS->SetProjection( crsWkt ); delete crsWkt; GDALRasterBand * band; for( int i=1; i <= theBands; i++ ) { band = dstDS->GetRasterBand( i ); band->SetNoDataValue( theNodataValue ); band->RasterIO( GF_Write, 0, 0, theCols, theRows, theData[ i-1 ], theCols, theRows, theType, 0, 0); } GDALClose( (GDALDatasetH) dstDS ); return true; }
CPLErr GDALDefaultOverviews::BuildOverviews( const char * pszBasename, const char * pszResampling, int nOverviews, int * panOverviewList, int nBands, int * panBandList, GDALProgressFunc pfnProgress, void * pProgressData) { if( pfnProgress == NULL ) pfnProgress = GDALDummyProgress; if( nOverviews == 0 ) return CleanOverviews(); /* -------------------------------------------------------------------- */ /* If we don't already have an overview file, we need to decide */ /* what format to use. */ /* -------------------------------------------------------------------- */ if( poODS == NULL ) { bOvrIsAux = CPLTestBool(CPLGetConfigOption( "USE_RRD", "NO" )); if( bOvrIsAux ) { osOvrFilename = CPLResetExtension(poDS->GetDescription(),"aux"); VSIStatBufL sStatBuf; if( VSIStatExL( osOvrFilename, &sStatBuf, VSI_STAT_EXISTS_FLAG ) == 0 ) osOvrFilename.Printf( "%s.aux", poDS->GetDescription() ); } } /* -------------------------------------------------------------------- */ /* If we already have the overviews open, but they are */ /* read-only, then try and reopen them read-write. */ /* -------------------------------------------------------------------- */ else if( poODS->GetAccess() == GA_ReadOnly ) { GDALClose( poODS ); poODS = static_cast<GDALDataset *>( GDALOpen( osOvrFilename, GA_Update )); if( poODS == NULL ) return CE_Failure; } /* -------------------------------------------------------------------- */ /* Our TIFF overview support currently only works safely if all */ /* bands are handled at the same time. */ /* -------------------------------------------------------------------- */ if( !bOvrIsAux && nBands != poDS->GetRasterCount() ) { CPLError( CE_Failure, CPLE_NotSupported, "Generation of overviews in external TIFF currently only " "supported when operating on all bands. " "Operation failed." ); return CE_Failure; } /* -------------------------------------------------------------------- */ /* If a basename is provided, use it to override the internal */ /* overview filename. */ /* -------------------------------------------------------------------- */ if( pszBasename == NULL && osOvrFilename.length() == 0 ) pszBasename = poDS->GetDescription(); if( pszBasename != NULL ) { if( bOvrIsAux ) osOvrFilename.Printf( "%s.aux", pszBasename ); else osOvrFilename.Printf( "%s.ovr", pszBasename ); } /* -------------------------------------------------------------------- */ /* Establish which of the overview levels we already have, and */ /* which are new. We assume that band 1 of the file is */ /* representative. */ /* -------------------------------------------------------------------- */ GDALRasterBand *poBand = poDS->GetRasterBand( 1 ); int nNewOverviews = 0; int *panNewOverviewList = static_cast<int *>( CPLCalloc(sizeof(int), nOverviews) ); double dfAreaNewOverviews = 0; double dfAreaRefreshedOverviews = 0; for( int i = 0; i < nOverviews && poBand != NULL; i++ ) { for( int j = 0; j < poBand->GetOverviewCount(); j++ ) { GDALRasterBand * poOverview = poBand->GetOverview( j ); if( poOverview == NULL ) continue; int nOvFactor = GDALComputeOvFactor(poOverview->GetXSize(), poBand->GetXSize(), poOverview->GetYSize(), poBand->GetYSize()); if( nOvFactor == panOverviewList[i] || nOvFactor == GDALOvLevelAdjust2( panOverviewList[i], poBand->GetXSize(), poBand->GetYSize() ) ) { panOverviewList[i] *= -1; } } const double dfArea = 1.0 / (panOverviewList[i] * panOverviewList[i]); dfAreaRefreshedOverviews += dfArea; if( panOverviewList[i] > 0 ) { dfAreaNewOverviews += dfArea; panNewOverviewList[nNewOverviews++] = panOverviewList[i]; } } /* -------------------------------------------------------------------- */ /* Build band list. */ /* -------------------------------------------------------------------- */ GDALRasterBand **pahBands = static_cast<GDALRasterBand **>( CPLCalloc(sizeof(GDALRasterBand *), nBands) ); for( int i = 0; i < nBands; i++ ) pahBands[i] = poDS->GetRasterBand( panBandList[i] ); /* -------------------------------------------------------------------- */ /* Build new overviews - Imagine. Keep existing file open if */ /* we have it. But mark all overviews as in need of */ /* regeneration, since HFAAuxBuildOverviews() doesn't actually */ /* produce the imagery. */ /* -------------------------------------------------------------------- */ CPLErr eErr = CE_None; void* pScaledProgress = GDALCreateScaledProgress( 0, dfAreaNewOverviews / dfAreaRefreshedOverviews, pfnProgress, pProgressData ); if( bOvrIsAux ) { if( nNewOverviews == 0 ) { /* if we call HFAAuxBuildOverviews() with nNewOverviews == 0 */ /* because that there's no new, this will wipe existing */ /* overviews (#4831) */ // eErr = CE_None; } else { eErr = HFAAuxBuildOverviews( osOvrFilename, poDS, &poODS, nBands, panBandList, nNewOverviews, panNewOverviewList, pszResampling, GDALScaledProgress, pScaledProgress ); } for( int j = 0; j < nOverviews; j++ ) { if( panOverviewList[j] > 0 ) panOverviewList[j] *= -1; } } /* -------------------------------------------------------------------- */ /* Build new overviews - TIFF. Close TIFF files while we */ /* operate on it. */ /* -------------------------------------------------------------------- */ else { if( poODS != NULL ) { delete poODS; poODS = NULL; } eErr = GTIFFBuildOverviews( osOvrFilename, nBands, pahBands, nNewOverviews, panNewOverviewList, pszResampling, GDALScaledProgress, pScaledProgress ); // Probe for proxy overview filename. if( eErr == CE_Failure ) { const char *pszProxyOvrFilename = poDS->GetMetadataItem("FILENAME","ProxyOverviewRequest"); if( pszProxyOvrFilename != NULL ) { osOvrFilename = pszProxyOvrFilename; eErr = GTIFFBuildOverviews( osOvrFilename, nBands, pahBands, nNewOverviews, panNewOverviewList, pszResampling, GDALScaledProgress, pScaledProgress ); } } if( eErr == CE_None ) { poODS = static_cast<GDALDataset *>( GDALOpen( osOvrFilename, GA_Update ) ); if( poODS == NULL ) eErr = CE_Failure; } } GDALDestroyScaledProgress( pScaledProgress ); /* -------------------------------------------------------------------- */ /* Refresh old overviews that were listed. */ /* -------------------------------------------------------------------- */ GDALRasterBand **papoOverviewBands = static_cast<GDALRasterBand **>( CPLCalloc(sizeof(void*), nOverviews) ); for( int iBand = 0; iBand < nBands && eErr == CE_None; iBand++ ) { poBand = poDS->GetRasterBand( panBandList[iBand] ); nNewOverviews = 0; for( int i = 0; i < nOverviews && poBand != NULL; i++ ) { for( int j = 0; j < poBand->GetOverviewCount(); j++ ) { GDALRasterBand * poOverview = poBand->GetOverview( j ); if( poOverview == NULL ) continue; int bHasNoData = FALSE; double noDataValue = poBand->GetNoDataValue(&bHasNoData); if( bHasNoData ) poOverview->SetNoDataValue(noDataValue); const int nOvFactor = GDALComputeOvFactor(poOverview->GetXSize(), poBand->GetXSize(), poOverview->GetYSize(), poBand->GetYSize()); if( nOvFactor == - panOverviewList[i] || (panOverviewList[i] < 0 && nOvFactor == GDALOvLevelAdjust2( -panOverviewList[i], poBand->GetXSize(), poBand->GetYSize() )) ) { papoOverviewBands[nNewOverviews++] = poOverview; break; } } } if( nNewOverviews > 0 ) { const double dfOffset = dfAreaNewOverviews / dfAreaRefreshedOverviews; const double dfScale = 1.0 - dfOffset; pScaledProgress = GDALCreateScaledProgress( dfOffset + dfScale * iBand / nBands, dfOffset + dfScale * (iBand+1) / nBands, pfnProgress, pProgressData ); eErr = GDALRegenerateOverviews( (GDALRasterBandH) poBand, nNewOverviews, (GDALRasterBandH*)papoOverviewBands, pszResampling, GDALScaledProgress, pScaledProgress ); GDALDestroyScaledProgress( pScaledProgress ); } } /* -------------------------------------------------------------------- */ /* Cleanup */ /* -------------------------------------------------------------------- */ CPLFree( papoOverviewBands ); CPLFree( panNewOverviewList ); CPLFree( pahBands ); /* -------------------------------------------------------------------- */ /* If we have a mask file, we need to build its overviews too. */ /* -------------------------------------------------------------------- */ if( HaveMaskFile() && poMaskDS ) { // Some config option are not compatible with mask overviews // so unset them, and define more sensible values. const bool bJPEG = EQUAL(CPLGetConfigOption("COMPRESS_OVERVIEW", ""), "JPEG"); const bool bPHOTOMETRIC_YCBCR = EQUAL(CPLGetConfigOption("PHOTOMETRIC_OVERVIEW", ""), "YCBCR"); if( bJPEG ) CPLSetThreadLocalConfigOption("COMPRESS_OVERVIEW", "DEFLATE"); if( bPHOTOMETRIC_YCBCR ) CPLSetThreadLocalConfigOption("PHOTOMETRIC_OVERVIEW", ""); poMaskDS->BuildOverviews( pszResampling, nOverviews, panOverviewList, 0, NULL, pfnProgress, pProgressData ); // Restore config option. if( bJPEG ) CPLSetThreadLocalConfigOption("COMPRESS_OVERVIEW", "JPEG"); if( bPHOTOMETRIC_YCBCR ) CPLSetThreadLocalConfigOption("PHOTOMETRIC_OVERVIEW", "YCBCR"); if( bOwnMaskDS ) { // Reset the poMask member of main dataset bands, since it // will become invalid after poMaskDS closing. for( int iBand = 1; iBand <= poDS->GetRasterCount(); iBand ++ ) { GDALRasterBand *poOtherBand = poDS->GetRasterBand(iBand); if( poOtherBand != NULL ) poOtherBand->InvalidateMaskBand(); } GDALClose( poMaskDS ); } // force next request to reread mask file. poMaskDS = NULL; bOwnMaskDS = false; bCheckedForMask = false; } /* -------------------------------------------------------------------- */ /* If we have an overview dataset, then mark all the overviews */ /* with the base dataset Used later for finding overviews */ /* masks. Uggg. */ /* -------------------------------------------------------------------- */ if( poODS ) { const int nOverviewCount = GetOverviewCount(1); for( int iOver = 0; iOver < nOverviewCount; iOver++ ) { GDALRasterBand *poOtherBand = GetOverview( 1, iOver ); GDALDataset *poOverDS = poOtherBand != NULL ? poOtherBand->GetDataset() : NULL; if( poOverDS != NULL ) { poOverDS->oOvManager.poBaseDS = poDS; poOverDS->oOvManager.poDS = poOverDS; } } } return eErr; }
int InCoreInterp::outputFile(const std::string& outputName, int outputFormat, unsigned int outputType, double *adfGeoTransform, const char* wkt) { int i,j,k; FILE **arcFiles; char arcFileName[1024]; FILE **gridFiles; char gridFileName[1024]; const char *ext[6] = {".min", ".max", ".mean", ".idw", ".den", ".std"}; unsigned int type[6] = {OUTPUT_TYPE_MIN, OUTPUT_TYPE_MAX, OUTPUT_TYPE_MEAN, OUTPUT_TYPE_IDW, OUTPUT_TYPE_DEN, OUTPUT_TYPE_STD}; int numTypes = 6; // open ArcGIS files if(outputFormat == OUTPUT_FORMAT_ARC_ASCII || outputFormat == OUTPUT_FORMAT_ALL) { if((arcFiles = (FILE **)malloc(sizeof(FILE *) * numTypes)) == NULL) { cerr << "Arc File open error: " << endl; return -1; } for(i = 0; i < numTypes; i++) { if(outputType & type[i]) { strncpy(arcFileName, outputName.c_str(), sizeof(arcFileName)); strncat(arcFileName, ext[i], strlen(ext[i])); strncat(arcFileName, ".asc", strlen(".asc")); if((arcFiles[i] = fopen(arcFileName, "w+")) == NULL) { cerr << "File open error: " << arcFileName << endl; return -1; } } else { arcFiles[i] = NULL; } } } else { arcFiles = NULL; } // open Grid ASCII files if(outputFormat == OUTPUT_FORMAT_GRID_ASCII || outputFormat == OUTPUT_FORMAT_ALL) { if((gridFiles = (FILE **)malloc(sizeof(FILE *) * numTypes)) == NULL) { cerr << "File array allocation error" << endl; return -1; } for(i = 0; i < numTypes; i++) { if(outputType & type[i]) { strncpy(gridFileName, outputName.c_str(), sizeof(arcFileName)); strncat(gridFileName, ext[i], strlen(ext[i])); strncat(gridFileName, ".grid", strlen(".grid")); if((gridFiles[i] = fopen(gridFileName, "w+")) == NULL) { cerr << "File open error: " << gridFileName << endl; return -1; } } else { gridFiles[i] = NULL; } } } else { gridFiles = NULL; } // print ArcGIS headers if(arcFiles != NULL) { for(i = 0; i < numTypes; i++) { if(arcFiles[i] != NULL) { fprintf(arcFiles[i], "ncols %d\n", GRID_SIZE_X); fprintf(arcFiles[i], "nrows %d\n", GRID_SIZE_Y); fprintf(arcFiles[i], "xllcorner %f\n", min_x - 0.5*GRID_DIST_X); fprintf(arcFiles[i], "yllcorner %f\n", min_y - 0.5*GRID_DIST_Y); fprintf(arcFiles[i], "cellsize %f\n", GRID_DIST_X); fprintf(arcFiles[i], "NODATA_value -9999\n"); } } } // print Grid headers if(gridFiles != NULL) { for(i = 0; i < numTypes; i++) { if(gridFiles[i] != NULL) { fprintf(gridFiles[i], "north: %f\n", min_y - 0.5*GRID_DIST_Y + GRID_DIST_Y*GRID_SIZE_Y); fprintf(gridFiles[i], "south: %f\n", min_y - 0.5*GRID_DIST_Y); fprintf(gridFiles[i], "east: %f\n", min_x - 0.5*GRID_DIST_X + GRID_DIST_X*GRID_SIZE_X); fprintf(gridFiles[i], "west: %f\n", min_x - 0.5*GRID_DIST_X); fprintf(gridFiles[i], "rows: %d\n", GRID_SIZE_Y); fprintf(gridFiles[i], "cols: %d\n", GRID_SIZE_X); } } } // print data for(i = GRID_SIZE_Y - 1; i >= 0; i--) { for(j = 0; j < GRID_SIZE_X; j++) { if(arcFiles != NULL) { // Zmin if(arcFiles[0] != NULL) { if(interp[j][i].empty == 0 && interp[j][i].filled == 0) fprintf(arcFiles[0], "-9999 "); else fprintf(arcFiles[0], "%f ", interp[j][i].Zmin); } // Zmax if(arcFiles[1] != NULL) { if(interp[j][i].empty == 0 && interp[j][i].filled == 0) fprintf(arcFiles[1], "-9999 "); else fprintf(arcFiles[1], "%f ", interp[j][i].Zmax); } // Zmean if(arcFiles[2] != NULL) { if(interp[j][i].empty == 0 && interp[j][i].filled == 0) fprintf(arcFiles[2], "-9999 "); else fprintf(arcFiles[2], "%f ", interp[j][i].Zmean); } // Zidw if(arcFiles[3] != NULL) { if(interp[j][i].empty == 0 && interp[j][i].filled == 0) fprintf(arcFiles[3], "-9999 "); else fprintf(arcFiles[3], "%f ", interp[j][i].Zidw); } // count if(arcFiles[4] != NULL) { if(interp[j][i].empty == 0 && interp[j][i].filled == 0) fprintf(arcFiles[4], "-9999 "); else fprintf(arcFiles[4], "%d ", interp[j][i].count); } // count if(arcFiles[5] != NULL) { if(interp[j][i].empty == 0 && interp[j][i].filled == 0) fprintf(arcFiles[5], "-9999 "); else fprintf(arcFiles[5], "%f ", interp[j][i].Zstd); } } if(gridFiles != NULL) { // Zmin if(gridFiles[0] != NULL) { if(interp[j][i].empty == 0 && interp[j][i].filled == 0) fprintf(gridFiles[0], "-9999 "); else fprintf(gridFiles[0], "%f ", interp[j][i].Zmin); } // Zmax if(gridFiles[1] != NULL) { if(interp[j][i].empty == 0 && interp[j][i].filled == 0) fprintf(gridFiles[1], "-9999 "); else fprintf(gridFiles[1], "%f ", interp[j][i].Zmax); } // Zmean if(gridFiles[2] != NULL) { if(interp[j][i].empty == 0 && interp[j][i].filled == 0) fprintf(gridFiles[2], "-9999 "); else fprintf(gridFiles[2], "%f ", interp[j][i].Zmean); } // Zidw if(gridFiles[3] != NULL) { if(interp[j][i].empty == 0 && interp[j][i].filled == 0) fprintf(gridFiles[3], "-9999 "); else fprintf(gridFiles[3], "%f ", interp[j][i].Zidw); } // count if(gridFiles[4] != NULL) { if(interp[j][i].empty == 0 && interp[j][i].filled == 0) fprintf(gridFiles[4], "-9999 "); else fprintf(gridFiles[4], "%d ", interp[j][i].count); } // count if(gridFiles[5] != NULL) { if(interp[j][i].empty == 0 && interp[j][i].filled == 0) fprintf(gridFiles[5], "-9999 "); else fprintf(gridFiles[5], "%f ", interp[j][i].Zstd); } } } if(arcFiles != NULL) for(k = 0; k < numTypes; k++) { if(arcFiles[k] != NULL) fprintf(arcFiles[k], "\n"); } if(gridFiles != NULL) for(k = 0; k < numTypes; k++) { if(gridFiles[k] != NULL) fprintf(gridFiles[k], "\n"); } } #ifdef HAVE_GDAL GDALDataset **gdalFiles; char gdalFileName[1024]; // open GDAL GeoTIFF files if(outputFormat == OUTPUT_FORMAT_GDAL_GTIFF || outputFormat == OUTPUT_FORMAT_ALL) { GDALAllRegister(); if((gdalFiles = (GDALDataset **)malloc(sizeof(GDALDataset *) * numTypes)) == NULL) { cerr << "File array allocation error" << endl; return -1; } for(i = 0; i < numTypes; i++) { if(outputType & type[i]) { strncpy(gdalFileName, outputName.c_str(), sizeof(gdalFileName)); strncat(gdalFileName, ext[i], strlen(ext[i])); strncat(gdalFileName, ".tif", strlen(".tif")); char **papszMetadata; const char *pszFormat = "GTIFF"; GDALDriver* tpDriver = GetGDALDriverManager()->GetDriverByName(pszFormat); if (tpDriver) { papszMetadata = tpDriver->GetMetadata(); if (CSLFetchBoolean(papszMetadata, GDAL_DCAP_CREATE, FALSE)) { char **papszOptions = NULL; gdalFiles[i] = tpDriver->Create(gdalFileName, GRID_SIZE_X, GRID_SIZE_Y, 1, GDT_Float32, papszOptions); if (gdalFiles[i] == NULL) { cerr << "File open error: " << gdalFileName << endl; return -1; } else { if (adfGeoTransform) { gdalFiles[i]->SetGeoTransform(adfGeoTransform); } else { double defaultTransform [6] = { min_x - 0.5*GRID_DIST_X, // top left x (double)GRID_DIST_X, // w-e pixel resolution 0.0, // no rotation/shear min_y - 0.5*GRID_DIST_Y + GRID_DIST_Y*GRID_SIZE_Y, // top left y 0.0, // no rotation/shear -(double)GRID_DIST_Y }; // n-x pixel resolution (negative value) gdalFiles[i]->SetGeoTransform(defaultTransform); } if (wkt) gdalFiles[i]->SetProjection(wkt); } } } } else { gdalFiles[i] = NULL; } } } else { gdalFiles = NULL; } if (gdalFiles != NULL) { for (i = 0; i < numTypes; i++) { if (gdalFiles[i] != NULL) { float *poRasterData = new float[GRID_SIZE_X*GRID_SIZE_Y]; for (int j = 0; j < GRID_SIZE_X*GRID_SIZE_Y; j++) { poRasterData[j] = 0; } for(j = GRID_SIZE_Y - 1; j >= 0; j--) { for(k = 0; k < GRID_SIZE_X; k++) { int index = (GRID_SIZE_Y - 1 - j) * GRID_SIZE_X + k; if(interp[k][j].empty == 0 && interp[k][j].filled == 0) { poRasterData[index] = -9999.f; } else { switch (i) { case 0: poRasterData[index] = interp[k][j].Zmin; break; case 1: poRasterData[index] = interp[k][j].Zmax; break; case 2: poRasterData[index] = interp[k][j].Zmean; break; case 3: poRasterData[index] = interp[k][j].Zidw; break; case 4: poRasterData[index] = interp[k][j].count; break; case 5: poRasterData[index] = interp[k][j].Zstd; break; } } } } GDALRasterBand *tBand = gdalFiles[i]->GetRasterBand(1); tBand->SetNoDataValue(-9999.f); if (GRID_SIZE_X > 0 && GRID_SIZE_Y > 0) tBand->RasterIO(GF_Write, 0, 0, GRID_SIZE_X, GRID_SIZE_Y, poRasterData, GRID_SIZE_X, GRID_SIZE_Y, GDT_Float32, 0, 0); GDALClose((GDALDatasetH) gdalFiles[i]); delete [] poRasterData; } } } #endif // HAVE_GDAL // close files if(gridFiles != NULL) { for(i = 0; i < numTypes; i++) { if(gridFiles[i] != NULL) fclose(gridFiles[i]); } } if(arcFiles != NULL) { for(i = 0; i < numTypes; i++) { if(arcFiles[i] != NULL) fclose(arcFiles[i]); } } return 0; }
// Slot called when the menu item is triggered // If you created more menu items / toolbar buttons in initiGui, you should // create a separate handler for each action - this single run() method will // not be enough void Heatmap::run() { HeatmapGui d( mQGisIface->mainWindow(), QgisGui::ModalDialogFlags, &mSessionSettings ); if ( d.exec() == QDialog::Accepted ) { // everything runs here // Get the required data from the dialog QgsRectangle myBBox = d.bbox(); int columns = d.columns(); int rows = d.rows(); double cellsize = d.cellSizeX(); // or d.cellSizeY(); both have the same value mDecay = d.decayRatio(); int kernelShape = d.kernelShape(); // Start working on the input vector QgsVectorLayer* inputLayer = d.inputVectorLayer(); // Getting the rasterdataset in place GDALAllRegister(); GDALDataset *emptyDataset; GDALDriver *myDriver; myDriver = GetGDALDriverManager()->GetDriverByName( d.outputFormat().toUtf8() ); if ( myDriver == NULL ) { QMessageBox::information( 0, tr( "GDAL driver error" ), tr( "Cannot open the driver for the specified format" ) ); return; } double geoTransform[6] = { myBBox.xMinimum(), cellsize, 0, myBBox.yMinimum(), 0, cellsize }; emptyDataset = myDriver->Create( d.outputFilename().toUtf8(), columns, rows, 1, GDT_Float32, NULL ); emptyDataset->SetGeoTransform( geoTransform ); // Set the projection on the raster destination to match the input layer emptyDataset->SetProjection( inputLayer->crs().toWkt().toLocal8Bit().data() ); GDALRasterBand *poBand; poBand = emptyDataset->GetRasterBand( 1 ); poBand->SetNoDataValue( NO_DATA ); float* line = ( float * ) CPLMalloc( sizeof( float ) * columns ); for ( int i = 0; i < columns ; i++ ) { line[i] = NO_DATA; } // Write the empty raster for ( int i = 0; i < rows ; i++ ) { poBand->RasterIO( GF_Write, 0, i, columns, 1, line, columns, 1, GDT_Float32, 0, 0 ); } CPLFree( line ); //close the dataset GDALClose(( GDALDatasetH ) emptyDataset ); // open the raster in GA_Update mode GDALDataset *heatmapDS; heatmapDS = ( GDALDataset * ) GDALOpen( d.outputFilename().toUtf8(), GA_Update ); if ( !heatmapDS ) { QMessageBox::information( 0, tr( "Raster update error" ), tr( "Could not open the created raster for updating. The heatmap was not generated." ) ); return; } poBand = heatmapDS->GetRasterBand( 1 ); QgsAttributeList myAttrList; int rField = 0; int wField = 0; // Handle different radius options double radius; double radiusToMapUnits = 1; int myBuffer = 0; if ( d.variableRadius() ) { rField = d.radiusField(); myAttrList.append( rField ); QgsDebugMsg( QString( "Radius Field index received: %1" ).arg( rField ) ); // If not using map units, then calculate a conversion factor to convert the radii to map units if ( d.radiusUnit() == HeatmapGui::Meters ) { radiusToMapUnits = mapUnitsOf( 1, inputLayer->crs() ); } } else { radius = d.radius(); // radius returned by d.radius() is already in map units myBuffer = bufferSize( radius, cellsize ); } if ( d.weighted() ) { wField = d.weightField(); myAttrList.append( wField ); } // This might have attributes or mightnot have attibutes at all // based on the variableRadius() and weighted() QgsFeatureIterator fit = inputLayer->getFeatures( QgsFeatureRequest().setSubsetOfAttributes( myAttrList ) ); int totalFeatures = inputLayer->featureCount(); int counter = 0; QProgressDialog p( tr( "Creating heatmap" ), tr( "Abort" ), 0, totalFeatures, mQGisIface->mainWindow() ); p.setWindowModality( Qt::ApplicationModal ); p.show(); QgsFeature myFeature; while ( fit.nextFeature( myFeature ) ) { counter++; p.setValue( counter ); QApplication::processEvents(); if ( p.wasCanceled() ) { QMessageBox::information( 0, tr( "Heatmap generation aborted" ), tr( "QGIS will now load the partially-computed raster." ) ); break; } QgsGeometry* myPointGeometry; myPointGeometry = myFeature.geometry(); // convert the geometry to point QgsPoint myPoint; myPoint = myPointGeometry->asPoint(); // avoiding any empty points or out of extent points if (( myPoint.x() < myBBox.xMinimum() ) || ( myPoint.y() < myBBox.yMinimum() ) || ( myPoint.x() > myBBox.xMaximum() ) || ( myPoint.y() > myBBox.yMaximum() ) ) { continue; } // If radius is variable then fetch it and calculate new pixel buffer size if ( d.variableRadius() ) { radius = myFeature.attribute( rField ).toDouble() * radiusToMapUnits; myBuffer = bufferSize( radius, cellsize ); } int blockSize = 2 * myBuffer + 1; //Block SIDE would be more appropriate // calculate the pixel position unsigned int xPosition, yPosition; xPosition = (( myPoint.x() - myBBox.xMinimum() ) / cellsize ) - myBuffer; yPosition = (( myPoint.y() - myBBox.yMinimum() ) / cellsize ) - myBuffer; // get the data float *dataBuffer = ( float * ) CPLMalloc( sizeof( float ) * blockSize * blockSize ); poBand->RasterIO( GF_Read, xPosition, yPosition, blockSize, blockSize, dataBuffer, blockSize, blockSize, GDT_Float32, 0, 0 ); double weight = 1.0; if ( d.weighted() ) { weight = myFeature.attribute( wField ).toDouble(); } for ( int xp = 0; xp <= myBuffer; xp++ ) { for ( int yp = 0; yp <= myBuffer; yp++ ) { double distance = sqrt( pow( xp, 2.0 ) + pow( yp, 2.0 ) ); // is pixel outside search bandwidth of feature? if ( distance > myBuffer ) { continue; } double pixelValue = weight * calculateKernelValue( distance, myBuffer, kernelShape ); // clearing anamolies along the axes if ( xp == 0 && yp == 0 ) { pixelValue /= 4; } else if ( xp == 0 || yp == 0 ) { pixelValue /= 2; } int pos[4]; pos[0] = ( myBuffer + xp ) * blockSize + ( myBuffer + yp ); pos[1] = ( myBuffer + xp ) * blockSize + ( myBuffer - yp ); pos[2] = ( myBuffer - xp ) * blockSize + ( myBuffer + yp ); pos[3] = ( myBuffer - xp ) * blockSize + ( myBuffer - yp ); for ( int p = 0; p < 4; p++ ) { if ( dataBuffer[ pos[p] ] == NO_DATA ) { dataBuffer[ pos[p] ] = 0; } dataBuffer[ pos[p] ] += pixelValue; } } } poBand->RasterIO( GF_Write, xPosition, yPosition, blockSize, blockSize, dataBuffer, blockSize, blockSize, GDT_Float32, 0, 0 ); CPLFree( dataBuffer ); } // Finally close the dataset GDALClose(( GDALDatasetH ) heatmapDS ); // Open the file in QGIS window mQGisIface->addRasterLayer( d.outputFilename(), QFileInfo( d.outputFilename() ).baseName() ); } }
CPLErr GTIFFBuildOverviews( const char * pszFilename, int nBands, GDALRasterBand **papoBandList, int nOverviews, int * panOverviewList, const char * pszResampling, GDALProgressFunc pfnProgress, void * pProgressData ) { if( nBands == 0 || nOverviews == 0 ) return CE_None; if( !GTiffOneTimeInit() ) return CE_Failure; TIFF *hOTIFF = nullptr; int nBitsPerPixel = 0; int nCompression = COMPRESSION_NONE; int nPhotometric = 0; int nSampleFormat = 0; int nPlanarConfig = 0; int iOverview = 0; int nXSize = 0; int nYSize = 0; /* -------------------------------------------------------------------- */ /* Verify that the list of bands is suitable for emitting in */ /* TIFF file. */ /* -------------------------------------------------------------------- */ for( int iBand = 0; iBand < nBands; iBand++ ) { int nBandBits = 0; int nBandFormat = 0; GDALRasterBand *hBand = papoBandList[iBand]; switch( hBand->GetRasterDataType() ) { case GDT_Byte: nBandBits = 8; nBandFormat = SAMPLEFORMAT_UINT; break; case GDT_UInt16: nBandBits = 16; nBandFormat = SAMPLEFORMAT_UINT; break; case GDT_Int16: nBandBits = 16; nBandFormat = SAMPLEFORMAT_INT; break; case GDT_UInt32: nBandBits = 32; nBandFormat = SAMPLEFORMAT_UINT; break; case GDT_Int32: nBandBits = 32; nBandFormat = SAMPLEFORMAT_INT; break; case GDT_Float32: nBandBits = 32; nBandFormat = SAMPLEFORMAT_IEEEFP; break; case GDT_Float64: nBandBits = 64; nBandFormat = SAMPLEFORMAT_IEEEFP; break; case GDT_CInt16: nBandBits = 32; nBandFormat = SAMPLEFORMAT_COMPLEXINT; break; case GDT_CInt32: nBandBits = 64; nBandFormat = SAMPLEFORMAT_COMPLEXINT; break; case GDT_CFloat32: nBandBits = 64; nBandFormat = SAMPLEFORMAT_COMPLEXIEEEFP; break; case GDT_CFloat64: nBandBits = 128; nBandFormat = SAMPLEFORMAT_COMPLEXIEEEFP; break; default: CPLAssert( false ); return CE_Failure; } if( hBand->GetMetadataItem( "NBITS", "IMAGE_STRUCTURE" ) ) { nBandBits = atoi(hBand->GetMetadataItem("NBITS", "IMAGE_STRUCTURE")); if( nBandBits == 1 && STARTS_WITH_CI(pszResampling, "AVERAGE_BIT2") ) nBandBits = 8; } if( iBand == 0 ) { nBitsPerPixel = nBandBits; nSampleFormat = nBandFormat; nXSize = hBand->GetXSize(); nYSize = hBand->GetYSize(); } else if( nBitsPerPixel != nBandBits || nSampleFormat != nBandFormat ) { CPLError( CE_Failure, CPLE_NotSupported, "GTIFFBuildOverviews() doesn't support a mixture of band" " data types." ); return CE_Failure; } else if( hBand->GetColorTable() != nullptr ) { CPLError( CE_Failure, CPLE_NotSupported, "GTIFFBuildOverviews() doesn't support building" " overviews of multiple colormapped bands." ); return CE_Failure; } else if( hBand->GetXSize() != nXSize || hBand->GetYSize() != nYSize ) { CPLError( CE_Failure, CPLE_NotSupported, "GTIFFBuildOverviews() doesn't support building" " overviews of different sized bands." ); return CE_Failure; } } /* -------------------------------------------------------------------- */ /* Use specified compression method. */ /* -------------------------------------------------------------------- */ const char *pszCompress = CPLGetConfigOption( "COMPRESS_OVERVIEW", nullptr ); if( pszCompress != nullptr && pszCompress[0] != '\0' ) { nCompression = GTIFFGetCompressionMethod(pszCompress, "COMPRESS_OVERVIEW"); if( nCompression < 0 ) return CE_Failure; } if( nCompression == COMPRESSION_JPEG && nBitsPerPixel > 8 ) { if( nBitsPerPixel > 16 ) { CPLError( CE_Failure, CPLE_NotSupported, "GTIFFBuildOverviews() doesn't support building" " JPEG compressed overviews of nBitsPerPixel > 16." ); return CE_Failure; } nBitsPerPixel = 12; } /* -------------------------------------------------------------------- */ /* Figure out the planar configuration to use. */ /* -------------------------------------------------------------------- */ if( nBands == 1 ) nPlanarConfig = PLANARCONFIG_CONTIG; else nPlanarConfig = PLANARCONFIG_SEPARATE; bool bSourceIsPixelInterleaved = false; bool bSourceIsJPEG2000 = false; if( nBands > 1 ) { GDALDataset* poSrcDS = papoBandList[0]->GetDataset(); if( poSrcDS ) { const char* pszSrcInterleave = poSrcDS->GetMetadataItem("INTERLEAVE", "IMAGE_STRUCTURE"); if( pszSrcInterleave && EQUAL(pszSrcInterleave, "PIXEL") ) { bSourceIsPixelInterleaved = true; } } const char* pszSrcCompression = papoBandList[0]->GetMetadataItem("COMPRESSION", "IMAGE_STRUCTURE"); if( pszSrcCompression ) { bSourceIsJPEG2000 = EQUAL(pszSrcCompression, "JPEG2000"); } if( bSourceIsPixelInterleaved && bSourceIsJPEG2000 ) { nPlanarConfig = PLANARCONFIG_CONTIG; } } const char* pszInterleave = CPLGetConfigOption( "INTERLEAVE_OVERVIEW", nullptr ); if( pszInterleave != nullptr && pszInterleave[0] != '\0' ) { if( EQUAL( pszInterleave, "PIXEL" ) ) nPlanarConfig = PLANARCONFIG_CONTIG; else if( EQUAL( pszInterleave, "BAND" ) ) nPlanarConfig = PLANARCONFIG_SEPARATE; else { CPLError( CE_Failure, CPLE_AppDefined, "INTERLEAVE_OVERVIEW=%s unsupported, " "value must be PIXEL or BAND. ignoring", pszInterleave ); } } /* -------------------------------------------------------------------- */ /* Figure out the photometric interpretation to use. */ /* -------------------------------------------------------------------- */ if( nBands == 3 ) nPhotometric = PHOTOMETRIC_RGB; else if( papoBandList[0]->GetColorTable() != nullptr && !STARTS_WITH_CI(pszResampling, "AVERAGE_BIT2") ) { nPhotometric = PHOTOMETRIC_PALETTE; // Should set the colormap up at this point too! } else if( nBands >= 3 && papoBandList[0]->GetColorInterpretation() == GCI_RedBand && papoBandList[1]->GetColorInterpretation() == GCI_GreenBand && papoBandList[2]->GetColorInterpretation() == GCI_BlueBand ) { nPhotometric = PHOTOMETRIC_RGB; } else nPhotometric = PHOTOMETRIC_MINISBLACK; const char* pszPhotometric = CPLGetConfigOption( "PHOTOMETRIC_OVERVIEW", nullptr ); if( pszPhotometric != nullptr && pszPhotometric[0] != '\0' ) { if( EQUAL( pszPhotometric, "MINISBLACK" ) ) nPhotometric = PHOTOMETRIC_MINISBLACK; else if( EQUAL( pszPhotometric, "MINISWHITE" ) ) nPhotometric = PHOTOMETRIC_MINISWHITE; else if( EQUAL( pszPhotometric, "RGB" )) { nPhotometric = PHOTOMETRIC_RGB; } else if( EQUAL( pszPhotometric, "CMYK" )) { nPhotometric = PHOTOMETRIC_SEPARATED; } else if( EQUAL( pszPhotometric, "YCBCR" )) { nPhotometric = PHOTOMETRIC_YCBCR; // Because of subsampling, setting YCBCR without JPEG compression // leads to a crash currently. Would need to make // GTiffRasterBand::IWriteBlock() aware of subsampling so that it // doesn't overrun buffer size returned by libtiff. if( nCompression != COMPRESSION_JPEG ) { CPLError( CE_Failure, CPLE_NotSupported, "Currently, PHOTOMETRIC_OVERVIEW=YCBCR requires " "COMPRESS_OVERVIEW=JPEG" ); return CE_Failure; } if( pszInterleave != nullptr && pszInterleave[0] != '\0' && nPlanarConfig == PLANARCONFIG_SEPARATE ) { CPLError( CE_Failure, CPLE_NotSupported, "PHOTOMETRIC_OVERVIEW=YCBCR requires " "INTERLEAVE_OVERVIEW=PIXEL" ); return CE_Failure; } else { nPlanarConfig = PLANARCONFIG_CONTIG; } // YCBCR strictly requires 3 bands. Not less, not more // Issue an explicit error message as libtiff one is a bit cryptic: // JPEGLib:Bogus input colorspace. if( nBands != 3 ) { CPLError( CE_Failure, CPLE_NotSupported, "PHOTOMETRIC_OVERVIEW=YCBCR requires a source raster " "with only 3 bands (RGB)" ); return CE_Failure; } } else if( EQUAL( pszPhotometric, "CIELAB" )) { nPhotometric = PHOTOMETRIC_CIELAB; } else if( EQUAL( pszPhotometric, "ICCLAB" )) { nPhotometric = PHOTOMETRIC_ICCLAB; } else if( EQUAL( pszPhotometric, "ITULAB" )) { nPhotometric = PHOTOMETRIC_ITULAB; } else { CPLError( CE_Warning, CPLE_IllegalArg, "PHOTOMETRIC_OVERVIEW=%s value not recognised, ignoring.", pszPhotometric ); } } /* -------------------------------------------------------------------- */ /* Figure out the predictor value to use. */ /* -------------------------------------------------------------------- */ int nPredictor = PREDICTOR_NONE; if( nCompression == COMPRESSION_LZW || nCompression == COMPRESSION_ADOBE_DEFLATE ) { const char* pszPredictor = CPLGetConfigOption( "PREDICTOR_OVERVIEW", nullptr ); if( pszPredictor != nullptr ) { nPredictor = atoi( pszPredictor ); } } /* -------------------------------------------------------------------- */ /* Create the file, if it does not already exist. */ /* -------------------------------------------------------------------- */ VSIStatBufL sStatBuf; VSILFILE* fpL = nullptr; if( VSIStatExL( pszFilename, &sStatBuf, VSI_STAT_EXISTS_FLAG ) != 0 ) { /* -------------------------------------------------------------------- */ /* Compute the uncompressed size. */ /* -------------------------------------------------------------------- */ double dfUncompressedOverviewSize = 0; int nDataTypeSize = GDALGetDataTypeSizeBytes(papoBandList[0]->GetRasterDataType()); for( iOverview = 0; iOverview < nOverviews; iOverview++ ) { const int nOXSize = (nXSize + panOverviewList[iOverview] - 1) / panOverviewList[iOverview]; const int nOYSize = (nYSize + panOverviewList[iOverview] - 1) / panOverviewList[iOverview]; dfUncompressedOverviewSize += nOXSize * static_cast<double>(nOYSize) * nBands * nDataTypeSize; } if( nCompression == COMPRESSION_NONE && dfUncompressedOverviewSize > 4200000000.0 ) { #ifndef BIGTIFF_SUPPORT CPLError( CE_Failure, CPLE_NotSupported, "The overview file would be larger than 4GB, " "but this is the largest size a TIFF can be, " "and BigTIFF is unavailable. " "Creation failed." ); return CE_Failure; #endif } /* -------------------------------------------------------------------- */ /* Should the file be created as a bigtiff file? */ /* -------------------------------------------------------------------- */ const char *pszBIGTIFF = CPLGetConfigOption( "BIGTIFF_OVERVIEW", nullptr ); if( pszBIGTIFF == nullptr ) pszBIGTIFF = "IF_SAFER"; bool bCreateBigTIFF = false; if( EQUAL(pszBIGTIFF,"IF_NEEDED") ) { if( nCompression == COMPRESSION_NONE && dfUncompressedOverviewSize > 4200000000.0 ) bCreateBigTIFF = true; } else if( EQUAL(pszBIGTIFF,"IF_SAFER") ) { // Look at the size of the base image and suppose that // the added overview levels won't be more than 1/2 of // the size of the base image. The theory says 1/3 of the // base image size if the overview levels are 2, 4, 8, 16. // Thus take 1/2 as the security margin for 1/3. const double dfUncompressedImageSize = nXSize * static_cast<double>(nYSize) * nBands * nDataTypeSize; if( dfUncompressedImageSize * 0.5 > 4200000000.0 ) bCreateBigTIFF = true; } else { bCreateBigTIFF = CPLTestBool( pszBIGTIFF ); if( !bCreateBigTIFF && nCompression == COMPRESSION_NONE && dfUncompressedOverviewSize > 4200000000.0 ) { CPLError( CE_Failure, CPLE_NotSupported, "The overview file will be larger than 4GB, " "so BigTIFF is necessary. " "Creation failed."); return CE_Failure; } } #ifndef BIGTIFF_SUPPORT if( bCreateBigTIFF ) { CPLError( CE_Warning, CPLE_NotSupported, "BigTIFF requested, but GDAL built without BigTIFF " "enabled libtiff, request ignored." ); bCreateBigTIFF = false; } #endif if( bCreateBigTIFF ) CPLDebug( "GTiff", "File being created as a BigTIFF." ); fpL = VSIFOpenL( pszFilename, "w+" ); if( fpL == nullptr ) hOTIFF = nullptr; else hOTIFF = VSI_TIFFOpen( pszFilename, bCreateBigTIFF ? "w+8" : "w+", fpL ); if( hOTIFF == nullptr ) { if( CPLGetLastErrorNo() == 0 ) CPLError( CE_Failure, CPLE_OpenFailed, "Attempt to create new tiff file `%s' " "failed in VSI_TIFFOpen().", pszFilename ); if( fpL != nullptr ) CPL_IGNORE_RET_VAL(VSIFCloseL(fpL)); return CE_Failure; } } /* -------------------------------------------------------------------- */ /* Otherwise just open it for update access. */ /* -------------------------------------------------------------------- */ else { fpL = VSIFOpenL( pszFilename, "r+" ); if( fpL == nullptr ) hOTIFF = nullptr; else hOTIFF = VSI_TIFFOpen( pszFilename, "r+", fpL ); if( hOTIFF == nullptr ) { if( CPLGetLastErrorNo() == 0 ) CPLError( CE_Failure, CPLE_OpenFailed, "Attempt to create new tiff file `%s' " "failed in VSI_TIFFOpen().", pszFilename ); if( fpL != nullptr ) CPL_IGNORE_RET_VAL(VSIFCloseL(fpL)); return CE_Failure; } } /* -------------------------------------------------------------------- */ /* Do we have a palette? If so, create a TIFF compatible version. */ /* -------------------------------------------------------------------- */ unsigned short *panRed = nullptr; unsigned short *panGreen = nullptr; unsigned short *panBlue = nullptr; if( nPhotometric == PHOTOMETRIC_PALETTE ) { GDALColorTable *poCT = papoBandList[0]->GetColorTable(); int nColorCount = 65536; if( nBitsPerPixel <= 8 ) nColorCount = 256; panRed = static_cast<unsigned short *>( CPLCalloc(nColorCount, sizeof(unsigned short)) ); panGreen = static_cast<unsigned short *>( CPLCalloc(nColorCount, sizeof(unsigned short)) ); panBlue = static_cast<unsigned short *>( CPLCalloc(nColorCount, sizeof(unsigned short)) ); for( int iColor = 0; iColor < nColorCount; iColor++ ) { GDALColorEntry sRGB = { 0, 0, 0, 0 }; if( poCT->GetColorEntryAsRGB( iColor, &sRGB ) ) { // TODO(schwehr): Check for underflow. // Going from signed short to unsigned short. panRed[iColor] = static_cast<unsigned short>(257 * sRGB.c1); panGreen[iColor] = static_cast<unsigned short>(257 * sRGB.c2); panBlue[iColor] = static_cast<unsigned short>(257 * sRGB.c3); } } } /* -------------------------------------------------------------------- */ /* Do we need some metadata for the overviews? */ /* -------------------------------------------------------------------- */ CPLString osMetadata; GDALDataset *poBaseDS = papoBandList[0]->GetDataset(); GTIFFBuildOverviewMetadata( pszResampling, poBaseDS, osMetadata ); /* -------------------------------------------------------------------- */ /* Loop, creating overviews. */ /* -------------------------------------------------------------------- */ int nOvrBlockXSize = 0; int nOvrBlockYSize = 0; GTIFFGetOverviewBlockSize(&nOvrBlockXSize, &nOvrBlockYSize); CPLString osNoData; // don't move this in inner scope const char* pszNoData = nullptr; int bNoDataSet = FALSE; const double dfNoDataValue = papoBandList[0]->GetNoDataValue(&bNoDataSet); if( bNoDataSet ) { osNoData = GTiffFormatGDALNoDataTagValue(dfNoDataValue); pszNoData = osNoData.c_str(); } std::vector<uint16> anExtraSamples; for( int i = GTIFFGetMaxColorChannels(nPhotometric)+1; i <= nBands; i++ ) { if( papoBandList[i-1]->GetColorInterpretation() == GCI_AlphaBand ) { anExtraSamples.push_back( GTiffGetAlphaValue(CPLGetConfigOption("GTIFF_ALPHA", nullptr), DEFAULT_ALPHA_TYPE)); } else { anExtraSamples.push_back(EXTRASAMPLE_UNSPECIFIED); } } for( iOverview = 0; iOverview < nOverviews; iOverview++ ) { const int nOXSize = (nXSize + panOverviewList[iOverview] - 1) / panOverviewList[iOverview]; const int nOYSize = (nYSize + panOverviewList[iOverview] - 1) / panOverviewList[iOverview]; GTIFFWriteDirectory( hOTIFF, FILETYPE_REDUCEDIMAGE, nOXSize, nOYSize, nBitsPerPixel, nPlanarConfig, nBands, nOvrBlockXSize, nOvrBlockYSize, TRUE, nCompression, nPhotometric, nSampleFormat, nPredictor, panRed, panGreen, panBlue, static_cast<int>(anExtraSamples.size()), anExtraSamples.empty() ? nullptr : anExtraSamples.data(), osMetadata, CPLGetConfigOption( "JPEG_QUALITY_OVERVIEW", nullptr ), CPLGetConfigOption( "JPEG_TABLESMODE_OVERVIEW", nullptr ), pszNoData, nullptr ); } if( panRed ) { CPLFree(panRed); CPLFree(panGreen); CPLFree(panBlue); panRed = nullptr; panGreen = nullptr; panBlue = nullptr; } XTIFFClose( hOTIFF ); if( VSIFCloseL(fpL) != 0 ) return CE_Failure; fpL = nullptr; /* -------------------------------------------------------------------- */ /* Open the overview dataset so that we can get at the overview */ /* bands. */ /* -------------------------------------------------------------------- */ GDALDataset *hODS = GDALDataset::Open( pszFilename, GDAL_OF_RASTER | GDAL_OF_UPDATE ); if( hODS == nullptr ) return CE_Failure; /* -------------------------------------------------------------------- */ /* Do we need to set the jpeg quality? */ /* -------------------------------------------------------------------- */ TIFF *hTIFF = static_cast<TIFF *>( hODS->GetInternalHandle(nullptr) ); if( nCompression == COMPRESSION_JPEG && CPLGetConfigOption( "JPEG_QUALITY_OVERVIEW", nullptr ) != nullptr ) { const int nJpegQuality = atoi(CPLGetConfigOption("JPEG_QUALITY_OVERVIEW","75")); TIFFSetField( hTIFF, TIFFTAG_JPEGQUALITY, nJpegQuality ); GTIFFSetJpegQuality(GDALDataset::ToHandle(hODS), nJpegQuality); } if( nCompression == COMPRESSION_JPEG && CPLGetConfigOption( "JPEG_TABLESMODE_OVERVIEW", nullptr ) != nullptr ) { const int nJpegTablesMode = atoi(CPLGetConfigOption("JPEG_TABLESMODE_OVERVIEW", CPLSPrintf("%d", knGTIFFJpegTablesModeDefault))); TIFFSetField( hTIFF, TIFFTAG_JPEGTABLESMODE, nJpegTablesMode ); GTIFFSetJpegTablesMode(GDALDataset::ToHandle(hODS), nJpegTablesMode); } /* -------------------------------------------------------------------- */ /* Loop writing overview data. */ /* -------------------------------------------------------------------- */ int *panOverviewListSorted = static_cast<int*>(CPLMalloc(sizeof(int) * nOverviews)); memcpy( panOverviewListSorted, panOverviewList, sizeof(int) * nOverviews); std::sort(panOverviewListSorted, panOverviewListSorted + nOverviews); GTIFFSetInExternalOvr(true); CPLErr eErr = CE_None; if( ((bSourceIsPixelInterleaved && bSourceIsJPEG2000) || (nCompression != COMPRESSION_NONE)) && nPlanarConfig == PLANARCONFIG_CONTIG && !GDALDataTypeIsComplex(papoBandList[0]->GetRasterDataType()) && papoBandList[0]->GetColorTable() == nullptr && (STARTS_WITH_CI(pszResampling, "NEAR") || EQUAL(pszResampling, "AVERAGE") || EQUAL(pszResampling, "GAUSS") || EQUAL(pszResampling, "CUBIC") || EQUAL(pszResampling, "CUBICSPLINE") || EQUAL(pszResampling, "LANCZOS") || EQUAL(pszResampling, "BILINEAR")) ) { // In the case of pixel interleaved compressed overviews, we want to // generate the overviews for all the bands block by block, and not // band after band, in order to write the block once and not loose // space in the TIFF file. GDALRasterBand ***papapoOverviewBands = static_cast<GDALRasterBand ***>( CPLCalloc(sizeof(void *), nBands) ); for( int iBand = 0; iBand < nBands && eErr == CE_None; iBand++ ) { GDALRasterBand *poSrcBand = papoBandList[iBand]; GDALRasterBand *poDstBand = hODS->GetRasterBand( iBand + 1 ); papapoOverviewBands[iBand] = static_cast<GDALRasterBand **>( CPLCalloc(sizeof(void *), nOverviews) ); int bHasNoData = FALSE; const double noDataValue = poSrcBand->GetNoDataValue(&bHasNoData); if( bHasNoData ) poDstBand->SetNoDataValue(noDataValue); for( int i = 0; i < nOverviews && eErr == CE_None; i++ ) { for( int j = -1; j < poDstBand->GetOverviewCount() && eErr == CE_None; j++ ) { GDALRasterBand * poOverview = (j < 0 ) ? poDstBand : poDstBand->GetOverview( j ); if( poOverview == nullptr ) { eErr = CE_Failure; continue; } const int nOvFactor = GDALComputeOvFactor(poOverview->GetXSize(), poSrcBand->GetXSize(), poOverview->GetYSize(), poSrcBand->GetYSize()); if( nOvFactor == panOverviewListSorted[i] || nOvFactor == GDALOvLevelAdjust2( panOverviewListSorted[i], poSrcBand->GetXSize(), poSrcBand->GetYSize() ) ) { papapoOverviewBands[iBand][i] = poOverview; if( bHasNoData ) poOverview->SetNoDataValue(noDataValue); break; } } CPLAssert( papapoOverviewBands[iBand][i] != nullptr ); } } if( eErr == CE_None ) eErr = GDALRegenerateOverviewsMultiBand( nBands, papoBandList, nOverviews, papapoOverviewBands, pszResampling, pfnProgress, pProgressData ); for( int iBand = 0; iBand < nBands; iBand++ ) { CPLFree(papapoOverviewBands[iBand]); } CPLFree(papapoOverviewBands); } else { GDALRasterBand **papoOverviews = static_cast<GDALRasterBand **>( CPLCalloc( sizeof(void*), knMaxOverviews ) ); for( int iBand = 0; iBand < nBands && eErr == CE_None; iBand++ ) { GDALRasterBand *hSrcBand = papoBandList[iBand]; GDALRasterBand *hDstBand = hODS->GetRasterBand( iBand + 1 ); int bHasNoData = FALSE; const double noDataValue = hSrcBand->GetNoDataValue(&bHasNoData); if( bHasNoData ) hDstBand->SetNoDataValue(noDataValue); // FIXME: this logic regenerates all overview bands, not only the // ones requested. papoOverviews[0] = hDstBand; int nDstOverviews = hDstBand->GetOverviewCount() + 1; CPLAssert( nDstOverviews < knMaxOverviews ); nDstOverviews = std::min(knMaxOverviews, nDstOverviews); // TODO(schwehr): Convert to starting with i = 1 and remove +1. for( int i = 0; i < nDstOverviews - 1 && eErr == CE_None; i++ ) { papoOverviews[i+1] = hDstBand->GetOverview(i); if( papoOverviews[i+1] == nullptr ) { eErr = CE_Failure; } else { if( bHasNoData ) papoOverviews[i+1]->SetNoDataValue(noDataValue); } } void *pScaledProgressData = GDALCreateScaledProgress( iBand / static_cast<double>( nBands ), (iBand + 1) / static_cast<double>( nBands ), pfnProgress, pProgressData ); if( eErr == CE_None ) eErr = GDALRegenerateOverviews( hSrcBand, nDstOverviews, reinterpret_cast<GDALRasterBandH *>( papoOverviews ), pszResampling, GDALScaledProgress, pScaledProgressData ); GDALDestroyScaledProgress( pScaledProgressData ); } CPLFree( papoOverviews ); } /* -------------------------------------------------------------------- */ /* Cleanup */ /* -------------------------------------------------------------------- */ if( eErr == CE_None ) hODS->FlushCache(); delete hODS; GTIFFSetInExternalOvr(false); CPLFree(panOverviewListSorted); pfnProgress( 1.0, nullptr, pProgressData ); return eErr; }
CPLErr GDALDefaultOverviews::BuildOverviews( const char * pszBasename, const char * pszResampling, int nOverviews, int * panOverviewList, int nBands, int * panBandList, GDALProgressFunc pfnProgress, void * pProgressData) { GDALRasterBand **pahBands; CPLErr eErr; int i; if( pfnProgress == NULL ) pfnProgress = GDALDummyProgress; if( nOverviews == 0 ) return CleanOverviews(); /* -------------------------------------------------------------------- */ /* If we don't already have an overview file, we need to decide */ /* what format to use. */ /* -------------------------------------------------------------------- */ if( poODS == NULL ) { bOvrIsAux = CSLTestBoolean(CPLGetConfigOption( "USE_RRD", "NO" )); if( bOvrIsAux ) { VSIStatBufL sStatBuf; osOvrFilename = CPLResetExtension(poDS->GetDescription(),"aux"); if( VSIStatL( osOvrFilename, &sStatBuf ) == 0 ) osOvrFilename.Printf( "%s.aux", poDS->GetDescription() ); } } /* -------------------------------------------------------------------- */ /* If we already have the overviews open, but they are */ /* read-only, then try and reopen them read-write. */ /* -------------------------------------------------------------------- */ else if( poODS->GetAccess() == GA_ReadOnly ) { GDALClose( poODS ); poODS = (GDALDataset *) GDALOpen( osOvrFilename, GA_Update ); if( poODS == NULL ) return CE_Failure; } /* -------------------------------------------------------------------- */ /* Our TIFF overview support currently only works safely if all */ /* bands are handled at the same time. */ /* -------------------------------------------------------------------- */ if( !bOvrIsAux && nBands != poDS->GetRasterCount() ) { CPLError( CE_Failure, CPLE_NotSupported, "Generation of overviews in external TIFF currently only" " supported when operating on all bands.\n" "Operation failed.\n" ); return CE_Failure; } /* -------------------------------------------------------------------- */ /* If a basename is provided, use it to override the internal */ /* overview filename. */ /* -------------------------------------------------------------------- */ if( pszBasename == NULL && osOvrFilename.length() == 0 ) pszBasename = poDS->GetDescription(); if( pszBasename != NULL ) { if( bOvrIsAux ) osOvrFilename.Printf( "%s.aux", pszBasename ); else osOvrFilename.Printf( "%s.ovr", pszBasename ); } /* -------------------------------------------------------------------- */ /* Establish which of the overview levels we already have, and */ /* which are new. We assume that band 1 of the file is */ /* representative. */ /* -------------------------------------------------------------------- */ int nNewOverviews, *panNewOverviewList = NULL; GDALRasterBand *poBand = poDS->GetRasterBand( 1 ); nNewOverviews = 0; panNewOverviewList = (int *) CPLCalloc(sizeof(int),nOverviews); for( i = 0; i < nOverviews && poBand != NULL; i++ ) { int j; for( j = 0; j < poBand->GetOverviewCount(); j++ ) { int nOvFactor; GDALRasterBand * poOverview = poBand->GetOverview( j ); nOvFactor = (int) (0.5 + poBand->GetXSize() / (double) poOverview->GetXSize()); if( nOvFactor == panOverviewList[i] || nOvFactor == GDALOvLevelAdjust( panOverviewList[i], poBand->GetXSize() ) ) panOverviewList[i] *= -1; } if( panOverviewList[i] > 0 ) panNewOverviewList[nNewOverviews++] = panOverviewList[i]; } /* -------------------------------------------------------------------- */ /* Build band list. */ /* -------------------------------------------------------------------- */ pahBands = (GDALRasterBand **) CPLCalloc(sizeof(GDALRasterBand *),nBands); for( i = 0; i < nBands; i++ ) pahBands[i] = poDS->GetRasterBand( panBandList[i] ); /* -------------------------------------------------------------------- */ /* Build new overviews - Imagine. Keep existing file open if */ /* we have it. But mark all overviews as in need of */ /* regeneration, since HFAAuxBuildOverviews() doesn't actually */ /* produce the imagery. */ /* -------------------------------------------------------------------- */ #ifndef WIN32CE if( bOvrIsAux ) { eErr = HFAAuxBuildOverviews( osOvrFilename, poDS, &poODS, nBands, panBandList, nNewOverviews, panNewOverviewList, pszResampling, pfnProgress, pProgressData ); int j; for( j = 0; j < nOverviews; j++ ) { if( panOverviewList[j] > 0 ) panOverviewList[j] *= -1; } } /* -------------------------------------------------------------------- */ /* Build new overviews - TIFF. Close TIFF files while we */ /* operate on it. */ /* -------------------------------------------------------------------- */ else #endif /* WIN32CE */ { if( poODS != NULL ) { delete poODS; poODS = NULL; } eErr = GTIFFBuildOverviews( osOvrFilename, nBands, pahBands, nNewOverviews, panNewOverviewList, pszResampling, pfnProgress, pProgressData ); // Probe for proxy overview filename. if( eErr == CE_Failure ) { const char *pszProxyOvrFilename = poDS->GetMetadataItem("FILENAME","ProxyOverviewRequest"); if( pszProxyOvrFilename != NULL ) { osOvrFilename = pszProxyOvrFilename; eErr = GTIFFBuildOverviews( osOvrFilename, nBands, pahBands, nNewOverviews, panNewOverviewList, pszResampling, pfnProgress, pProgressData ); } } if( eErr == CE_None ) { poODS = (GDALDataset *) GDALOpen( osOvrFilename, GA_Update ); if( poODS == NULL ) eErr = CE_Failure; } } /* -------------------------------------------------------------------- */ /* Refresh old overviews that were listed. */ /* -------------------------------------------------------------------- */ GDALRasterBand **papoOverviewBands; papoOverviewBands = (GDALRasterBand **) CPLCalloc(sizeof(void*),nOverviews); for( int iBand = 0; iBand < nBands && eErr == CE_None; iBand++ ) { poBand = poDS->GetRasterBand( panBandList[iBand] ); nNewOverviews = 0; for( i = 0; i < nOverviews && poBand != NULL; i++ ) { int j; for( j = 0; j < poBand->GetOverviewCount(); j++ ) { int nOvFactor; GDALRasterBand * poOverview = poBand->GetOverview( j ); int bHasNoData; double noDataValue = poBand->GetNoDataValue(&bHasNoData); if (bHasNoData) poOverview->SetNoDataValue(noDataValue); nOvFactor = (int) (0.5 + poBand->GetXSize() / (double) poOverview->GetXSize()); if( nOvFactor == - panOverviewList[i] || nOvFactor == GDALOvLevelAdjust( -panOverviewList[i], poBand->GetXSize() ) ) { papoOverviewBands[nNewOverviews++] = poOverview; break; } } } if( nNewOverviews > 0 ) { eErr = GDALRegenerateOverviews( (GDALRasterBandH) poBand, nNewOverviews, (GDALRasterBandH*)papoOverviewBands, pszResampling, pfnProgress, pProgressData ); } } /* -------------------------------------------------------------------- */ /* Cleanup */ /* -------------------------------------------------------------------- */ CPLFree( papoOverviewBands ); CPLFree( panNewOverviewList ); CPLFree( pahBands ); /* -------------------------------------------------------------------- */ /* If we have a mask file, we need to build it's overviews */ /* too. */ /* -------------------------------------------------------------------- */ if( HaveMaskFile() && poMaskDS ) { poMaskDS->BuildOverviews( pszResampling, nOverviews, panOverviewList, 0, NULL, pfnProgress, pProgressData ); if( bOwnMaskDS ) GDALClose( poMaskDS ); // force next request to reread mask file. poMaskDS = NULL; bOwnMaskDS = FALSE; bCheckedForMask = FALSE; } /* -------------------------------------------------------------------- */ /* If we have an overview dataset, then mark all the overviews */ /* with the base dataset Used later for finding overviews */ /* masks. Uggg. */ /* -------------------------------------------------------------------- */ if( poODS ) { int nOverviewCount = GetOverviewCount(1); int iOver; for( iOver = 0; iOver < nOverviewCount; iOver++ ) { GDALRasterBand *poBand = GetOverview( 1, iOver ); GDALDataset *poOverDS = NULL; if( poBand != NULL ) poOverDS = poBand->GetDataset(); if (poOverDS != NULL) { poOverDS->oOvManager.poBaseDS = poDS; poOverDS->oOvManager.poDS = poOverDS; } } } return eErr; }
int main(int argc, char* argv[]) { if (argc < 2) { cout << "void-filing-color <infile> <outfile>" << endl;; exit(1); } const char* InFilename = argv[1]; const char* OutFilename = argv[2]; GDALAllRegister(); // Open dataset and get raster band GDALDataset* poDataset = (GDALDataset*) GDALOpen(InFilename, GA_ReadOnly); if(poDataset == NULL) { cout << "Couldn't open dataset " << InFilename << endl; } GDALRasterBand *poInBandr; GDALRasterBand *poInBandg; GDALRasterBand *poInBandb; poInBandr = poDataset->GetRasterBand(1); poInBandg = poDataset->GetRasterBand(2); poInBandb = poDataset->GetRasterBand(3); double adfGeoTransform[6]; poDataset->GetGeoTransform(adfGeoTransform); // Get variables from input dataset const int nXSize = poInBandr->GetXSize(); const int nYSize = poInBandr->GetYSize(); // Create the output dataset and copy over relevant metadata const char* Format = "GTiff"; GDALDriver *poDriver = GetGDALDriverManager()->GetDriverByName(Format); char** Options = NULL; GDALDataset* poDS = poDriver->Create(OutFilename,nXSize,nYSize,3,GDT_Byte,Options); poDS->SetGeoTransform(adfGeoTransform); poDS->SetProjection(poDataset->GetProjectionRef()); GDALRasterBand* poBandr = poDS->GetRasterBand(1); GDALRasterBand* poBandg = poDS->GetRasterBand(2); GDALRasterBand* poBandb = poDS->GetRasterBand(3); poBandr->SetNoDataValue(0); poBandg->SetNoDataValue(0); poBandb->SetNoDataValue(0); GDALAllRegister(); cout << "Read image." << endl; CImg<unsigned char>* ReadPixels = new CImg<unsigned char>(nXSize, nYSize, 1, 3, 0); for (int i = 0; i < nYSize; i++) { cout << "\r" << i << "/" << nYSize; for (int j = 0; j < nXSize; j++) { unsigned char InPixel; poInBandr->RasterIO(GF_Read, j, i, 1, 1, &InPixel, 1, 1, GDT_Byte, 0, 0); (*ReadPixels)(j, i, 0, 0) = InPixel; poInBandg->RasterIO(GF_Read, j, i, 1, 1, &InPixel, 1, 1, GDT_Byte, 0, 0); (*ReadPixels)(j, i, 0, 1) = InPixel; poInBandb->RasterIO(GF_Read, j, i, 1, 1, &InPixel, 1, 1, GDT_Byte, 0, 0); (*ReadPixels)(j, i, 0, 2) = InPixel; } } cout << endl; cout << "Void filling." << endl; CImg<unsigned char>* InPixels = new CImg<unsigned char>(nXSize, nYSize, 1, 3, 0); for (int i = 0; i < nYSize; i++) { cout << "\r" << i << "/" << nYSize; for (int j = 0; j < nXSize; j++) { if (isEmpty(ReadPixels, j, i) && isEmpty(InPixels, j, i)) { int is = i; int ie = i; int js = j; int je = j; const int maxsize = 2; js = max(0, j-maxsize); je = min(nXSize-1, j+maxsize); is = max(0, i-maxsize); ie = min(nYSize-1, i+maxsize); // cout << endl << js << ", " << je << ", " << is << ", " << ie; float fact = 0; float sumr = 0; float sumg = 0; float sumb = 0; for (int ia = is ; ia <= ie ; ia++) { for (int ja = js ; ja <= je ; ja++) { // cout << endl << ia << ", " << ja; if (!isEmpty(ReadPixels, ja, ia)) { int ik = ia - i; int jk = ja - j; float length = ik*ik+jk*jk; float coef = 1/(length*length); sumr += ((*ReadPixels)(ja, ia, 0, 0))*coef; sumg += ((*ReadPixels)(ja, ia, 0, 1))*coef; sumb += ((*ReadPixels)(ja, ia, 0, 2))*coef; fact += coef; } } } // cout << endl << sumr << ", " << sumg << ", " << sumb << ", " << fact; if (fact == 0) { /* unsigned char InPixelr = 0xb5; // ocean blue unsigned char InPixelg = 0xd0; unsigned char InPixelb = 0xd0;*/ unsigned char InPixelr = 0x98; // green earth unsigned char InPixelg = 0xd7; unsigned char InPixelb = 0x88; poBandr->RasterIO(GF_Write, j, i, 1, 1, &InPixelr, 1, 1, GDT_Byte, 0, 0); poBandg->RasterIO(GF_Write, j, i, 1, 1, &InPixelg, 1, 1, GDT_Byte, 0, 0); poBandb->RasterIO(GF_Write, j, i, 1, 1, &InPixelb, 1, 1, GDT_Byte, 0, 0); } else { unsigned char InPixelr = (unsigned char)(sumr / fact); unsigned char InPixelg = (unsigned char)(sumg / fact); unsigned char InPixelb = (unsigned char)(sumb / fact); poBandr->RasterIO(GF_Write, j, i, 1, 1, &InPixelr, 1, 1, GDT_Byte, 0, 0); poBandg->RasterIO(GF_Write, j, i, 1, 1, &InPixelg, 1, 1, GDT_Byte, 0, 0); poBandb->RasterIO(GF_Write, j, i, 1, 1, &InPixelb, 1, 1, GDT_Byte, 0, 0); } } else if (!isEmpty(ReadPixels, j, i)) { unsigned char InPixelr = (*ReadPixels)(j, i, 0, 0); unsigned char InPixelg = (*ReadPixels)(j, i, 0, 1); unsigned char InPixelb = (*ReadPixels)(j, i, 0, 2); poBandr->RasterIO(GF_Write, j, i, 1, 1, &InPixelr, 1, 1, GDT_Byte, 0, 0); poBandg->RasterIO(GF_Write, j, i, 1, 1, &InPixelg, 1, 1, GDT_Byte, 0, 0); poBandb->RasterIO(GF_Write, j, i, 1, 1, &InPixelb, 1, 1, GDT_Byte, 0, 0); } } } cout << endl; delete poDS; return 0; }
GDALDataset *VICARDataset::Open( GDALOpenInfo * poOpenInfo ) { /* -------------------------------------------------------------------- */ /* Does this look like a VICAR dataset? */ /* -------------------------------------------------------------------- */ if( !Identify( poOpenInfo ) ) return NULL; /* -------------------------------------------------------------------- */ /* Open the file using the large file API. */ /* -------------------------------------------------------------------- */ VSILFILE *fpQube = VSIFOpenL( poOpenInfo->pszFilename, "rb" ); if( fpQube == NULL ) return NULL; VICARDataset *poDS = new VICARDataset(); if( ! poDS->oKeywords.Ingest( fpQube, poOpenInfo->pabyHeader ) ) { VSIFCloseL( fpQube ); delete poDS; return NULL; } VSIFCloseL( fpQube ); /***** CHECK ENDIANNESS **************/ const char *value = poDS->GetKeyword( "INTFMT" ); if (!EQUAL(value,"LOW") ) { CPLError( CE_Failure, CPLE_OpenFailed, "%s layout not supported. Abort\n\n", value); delete poDS; return FALSE; } value = poDS->GetKeyword( "REALFMT" ); if (!EQUAL(value,"RIEEE") ) { CPLError( CE_Failure, CPLE_OpenFailed, "%s layout not supported. Abort\n\n", value); delete poDS; return FALSE; } char chByteOrder = 'M'; value = poDS->GetKeyword( "BREALFMT" ); if (EQUAL(value,"VAX") ) { chByteOrder = 'I'; } /************ CHECK INSTRUMENT *****************/ /************ ONLY HRSC TESTED *****************/ bool bIsDTM = false; value = poDS->GetKeyword( "DTM.DTM_OFFSET" ); if (!EQUAL(value,"") ) { bIsDTM = true; } value = poDS->GetKeyword( "BLTYPE" ); if (!EQUAL(value,"M94_HRSC") && !bIsDTM ) { CPLError( CE_Failure, CPLE_OpenFailed, "%s instrument not tested. Continue with caution!\n\n", value); } /*********** Grab layout type (BSQ, BIP, BIL) ************/ char szLayout[10] = "BSQ"; //default to band seq. value = poDS->GetKeyword( "ORG" ); if (!EQUAL(value,"BSQ") ) { CPLError( CE_Failure, CPLE_OpenFailed, "%s layout not supported. Abort\n\n", value); delete poDS; return FALSE; } strcpy(szLayout,"BSQ"); const int nCols = atoi(poDS->GetKeyword("NS")); const int nRows = atoi(poDS->GetKeyword("NL")); const int nBands = atoi(poDS->GetKeyword("NB")); /*********** Grab record bytes **********/ int nSkipBytes = atoi(poDS->GetKeyword("NBB")); GDALDataType eDataType = GDT_Byte; double dfNoData = 0.0; if (EQUAL( poDS->GetKeyword( "FORMAT" ), "BYTE" )) { eDataType = GDT_Byte; dfNoData = NULL1; } else if (EQUAL( poDS->GetKeyword( "FORMAT" ), "HALF" )) { eDataType = GDT_Int16; dfNoData = NULL2; chByteOrder = 'I'; } else if (EQUAL( poDS->GetKeyword( "FORMAT" ), "FULL" )) { eDataType = GDT_UInt32; dfNoData = 0; } else if (EQUAL( poDS->GetKeyword( "FORMAT" ), "REAL" )) { eDataType = GDT_Float32; dfNoData = NULL3; chByteOrder = 'I'; } else { CPLError( CE_Failure, CPLE_AppDefined, "Could not find known VICAR label entries!\n"); delete poDS; return NULL; } if( nRows < 1 || nCols < 1 || nBands < 1 ) { CPLError( CE_Failure, CPLE_AppDefined, "File %s appears to be a VICAR file, but failed to find some " "required keywords.", poDS->GetDescription() ); return FALSE; } /* -------------------------------------------------------------------- */ /* Capture some information from the file that is of interest. */ /* -------------------------------------------------------------------- */ poDS->nRasterXSize = nCols; poDS->nRasterYSize = nRows; double dfULXMap=0.5; double dfULYMap = 0.5; double dfXDim = 1.0; double dfYDim = 1.0; double xulcenter = 0.0; double yulcenter = 0.0; value = poDS->GetKeyword("MAP.MAP_SCALE"); if (strlen(value) > 0 ) { dfXDim = CPLAtof(value); dfYDim = CPLAtof(value) * -1; dfXDim = dfXDim * 1000.0; dfYDim = dfYDim * 1000.0; } double dfSampleOffset_Shift = CPLAtof(CPLGetConfigOption( "PDS_SampleProjOffset_Shift", "-0.5" )); double dfLineOffset_Shift = CPLAtof(CPLGetConfigOption( "PDS_LineProjOffset_Shift", "-0.5" )); double dfSampleOffset_Mult = CPLAtof(CPLGetConfigOption( "PDS_SampleProjOffset_Mult", "-1.0") ); double dfLineOffset_Mult = CPLAtof( CPLGetConfigOption( "PDS_LineProjOffset_Mult", "1.0") ); /*********** Grab LINE_PROJECTION_OFFSET ************/ value = poDS->GetKeyword("MAP.LINE_PROJECTION_OFFSET"); if (strlen(value) > 0) { yulcenter = CPLAtof(value); dfULYMap = ((yulcenter + dfLineOffset_Shift) * -dfYDim * dfLineOffset_Mult); } /*********** Grab SAMPLE_PROJECTION_OFFSET ************/ value = poDS->GetKeyword("MAP.SAMPLE_PROJECTION_OFFSET"); if( strlen(value) > 0 ) { xulcenter = CPLAtof(value); dfULXMap = ((xulcenter + dfSampleOffset_Shift) * dfXDim * dfSampleOffset_Mult); } /* ==================================================================== */ /* Get the coordinate system. */ /* ==================================================================== */ bool bProjectionSet = true; /*********** Grab TARGET_NAME ************/ /**** This is the planets name i.e. MARS ***/ const CPLString target_name = poDS->GetKeyword("MAP.TARGET_NAME"); /********** Grab MAP_PROJECTION_TYPE *****/ const CPLString map_proj_name = poDS->GetKeyword( "MAP.MAP_PROJECTION_TYPE"); /****** Grab semi_major & convert to KM ******/ const double semi_major = CPLAtof(poDS->GetKeyword( "MAP.A_AXIS_RADIUS")) * 1000.0; /****** Grab semi-minor & convert to KM ******/ const double semi_minor = CPLAtof(poDS->GetKeyword( "MAP.C_AXIS_RADIUS")) * 1000.0; /*********** Grab CENTER_LAT ************/ const double center_lat = CPLAtof(poDS->GetKeyword( "MAP.CENTER_LATITUDE")); /*********** Grab CENTER_LON ************/ const double center_lon = CPLAtof(poDS->GetKeyword( "MAP.CENTER_LONGITUDE")); /********** Grab 1st std parallel *******/ const double first_std_parallel = CPLAtof(poDS->GetKeyword( "MAP.FIRST_STANDARD_PARALLEL")); /********** Grab 2nd std parallel *******/ const double second_std_parallel = CPLAtof(poDS->GetKeyword( "MAP.SECOND_STANDARD_PARALLEL")); /*** grab PROJECTION_LATITUDE_TYPE = "PLANETOCENTRIC" ****/ // Need to further study how ocentric/ographic will effect the gdal library. // So far we will use this fact to define a sphere or ellipse for some projections // Frank - may need to talk this over bool bIsGeographic = true; value = poDS->GetKeyword("MAP.COORDINATE_SYSTEM_NAME"); if (EQUAL( value, "PLANETOCENTRIC" )) bIsGeographic = false; /** Set oSRS projection and parameters --- all PDS supported types added if apparently supported in oSRS "AITOFF", ** Not supported in GDAL?? "ALBERS", "BONNE", "BRIESEMEISTER", ** Not supported in GDAL?? "CYLINDRICAL EQUAL AREA", "EQUIDISTANT", "EQUIRECTANGULAR", "GNOMONIC", "HAMMER", ** Not supported in GDAL?? "HENDU", ** Not supported in GDAL?? "LAMBERT AZIMUTHAL EQUAL AREA", "LAMBERT CONFORMAL", "MERCATOR", "MOLLWEIDE", "OBLIQUE CYLINDRICAL", "ORTHOGRAPHIC", "SIMPLE CYLINDRICAL", "SINUSOIDAL", "STEREOGRAPHIC", "TRANSVERSE MERCATOR", "VAN DER GRINTEN", ** Not supported in GDAL?? "WERNER" ** Not supported in GDAL?? **/ CPLDebug( "PDS", "using projection %s\n\n", map_proj_name.c_str()); OGRSpatialReference oSRS; if ((EQUAL( map_proj_name, "EQUIRECTANGULAR" )) || (EQUAL( map_proj_name, "SIMPLE_CYLINDRICAL" )) || (EQUAL( map_proj_name, "EQUIDISTANT" )) ) { oSRS.SetEquirectangular2 ( 0.0, center_lon, center_lat, 0, 0 ); } else if (EQUAL( map_proj_name, "ORTHOGRAPHIC" )) { oSRS.SetOrthographic ( center_lat, center_lon, 0, 0 ); } else if (EQUAL( map_proj_name, "SINUSOIDAL" )) { oSRS.SetSinusoidal ( center_lon, 0, 0 ); } else if (EQUAL( map_proj_name, "MERCATOR" )) { oSRS.SetMercator ( center_lat, center_lon, 1, 0, 0 ); } else if (EQUAL( map_proj_name, "STEREOGRAPHIC" )) { oSRS.SetStereographic ( center_lat, center_lon, 1, 0, 0 ); } else if (EQUAL( map_proj_name, "POLAR_STEREOGRAPHIC")) { oSRS.SetPS ( center_lat, center_lon, 1, 0, 0 ); } else if (EQUAL( map_proj_name, "TRANSVERSE_MERCATOR" )) { oSRS.SetTM ( center_lat, center_lon, 1, 0, 0 ); } else if (EQUAL( map_proj_name, "LAMBERT_CONFORMAL_CONIC" )) { oSRS.SetLCC ( first_std_parallel, second_std_parallel, center_lat, center_lon, 0, 0 ); } else if (EQUAL( map_proj_name, "LAMBERT_AZIMUTHAL_EQUAL_AREA" )) { oSRS.SetLAEA( center_lat, center_lon, 0, 0 ); } else if (EQUAL( map_proj_name, "CYLINDRICAL_EQUAL_AREA" )) { oSRS.SetCEA ( first_std_parallel, center_lon, 0, 0 ); } else if (EQUAL( map_proj_name, "MOLLWEIDE" )) { oSRS.SetMollweide ( center_lon, 0, 0 ); } else if (EQUAL( map_proj_name, "ALBERS" )) { oSRS.SetACEA ( first_std_parallel, second_std_parallel, center_lat, center_lon, 0, 0 ); } else if (EQUAL( map_proj_name, "BONNE" )) { oSRS.SetBonne ( first_std_parallel, center_lon, 0, 0 ); } else if (EQUAL( map_proj_name, "GNOMONIC" )) { oSRS.SetGnomonic ( center_lat, center_lon, 0, 0 ); } else if (EQUAL( map_proj_name, "OBLIQUE_CYLINDRICAL" )) { // hope Swiss Oblique Cylindrical is the same oSRS.SetSOC ( center_lat, center_lon, 0, 0 ); } else { CPLDebug( "VICAR", "Dataset projection %s is not supported. Continuing...", map_proj_name.c_str() ); bProjectionSet = false; } if (bProjectionSet) { //Create projection name, i.e. MERCATOR MARS and set as ProjCS keyword CPLString proj_target_name = map_proj_name + " " + target_name; oSRS.SetProjCS(proj_target_name); //set ProjCS keyword //The geographic/geocentric name will be the same basic name as the body name //'GCS' = Geographic/Geocentric Coordinate System CPLString geog_name = "GCS_" + target_name; //The datum and sphere names will be the same basic name aas the planet CPLString datum_name = "D_" + target_name; CPLString sphere_name = target_name; // + "_IAU_IAG"); //Might not be IAU defined so don't add //calculate inverse flattening from major and minor axis: 1/f = a/(a-b) double iflattening = 0.0; if ((semi_major - semi_minor) < 0.0000001) iflattening = 0; else iflattening = semi_major / (semi_major - semi_minor); //Set the body size but take into consideration which proj is being used to help w/ compatibility //Notice that most PDS projections are spherical based on the fact that ISIS/PICS are spherical //Set the body size but take into consideration which proj is being used to help w/ proj4 compatibility //The use of a Sphere, polar radius or ellipse here is based on how ISIS does it internally if ( ( (EQUAL( map_proj_name, "STEREOGRAPHIC" ) && (fabs(center_lat) == 90)) ) || (EQUAL( map_proj_name, "POLAR_STEREOGRAPHIC" ))) { if (bIsGeographic) { //Geograpraphic, so set an ellipse oSRS.SetGeogCS( geog_name, datum_name, sphere_name, semi_major, iflattening, "Reference_Meridian", 0.0 ); } else { //Geocentric, so force a sphere using the semi-minor axis. I hope... sphere_name += "_polarRadius"; oSRS.SetGeogCS( geog_name, datum_name, sphere_name, semi_minor, 0.0, "Reference_Meridian", 0.0 ); } } else if ( (EQUAL( map_proj_name, "SIMPLE_CYLINDRICAL" )) || (EQUAL( map_proj_name, "EQUIDISTANT" )) || (EQUAL( map_proj_name, "ORTHOGRAPHIC" )) || (EQUAL( map_proj_name, "STEREOGRAPHIC" )) || (EQUAL( map_proj_name, "SINUSOIDAL" )) ) { //isis uses the spherical equation for these projections so force a sphere oSRS.SetGeogCS( geog_name, datum_name, sphere_name, semi_major, 0.0, "Reference_Meridian", 0.0 ); } else if (EQUAL( map_proj_name, "EQUIRECTANGULAR" )) { //isis uses local radius as a sphere, which is pre-calculated in the PDS label as the semi-major sphere_name += "_localRadius"; oSRS.SetGeogCS( geog_name, datum_name, sphere_name, semi_major, 0.0, "Reference_Meridian", 0.0 ); } else { //All other projections: Mercator, Transverse Mercator, Lambert Conformal, etc. //Geographic, so set an ellipse if (bIsGeographic) { oSRS.SetGeogCS( geog_name, datum_name, sphere_name, semi_major, iflattening, "Reference_Meridian", 0.0 ); } else { //Geocentric, so force a sphere. I hope... oSRS.SetGeogCS( geog_name, datum_name, sphere_name, semi_major, 0.0, "Reference_Meridian", 0.0 ); } } // translate back into a projection string. char *pszResult = NULL; oSRS.exportToWkt( &pszResult ); poDS->osProjection = pszResult; CPLFree( pszResult ); } { poDS->bGotTransform = TRUE; poDS->adfGeoTransform[0] = dfULXMap; poDS->adfGeoTransform[1] = dfXDim; poDS->adfGeoTransform[2] = 0.0; poDS->adfGeoTransform[3] = dfULYMap; poDS->adfGeoTransform[4] = 0.0; poDS->adfGeoTransform[5] = dfYDim; } CPLString osQubeFile = poOpenInfo->pszFilename; if( !poDS->bGotTransform ) poDS->bGotTransform = GDALReadWorldFile( osQubeFile, "psw", poDS->adfGeoTransform ); if( !poDS->bGotTransform ) poDS->bGotTransform = GDALReadWorldFile( osQubeFile, "wld", poDS->adfGeoTransform ); /* -------------------------------------------------------------------- */ /* Open target binary file. */ /* -------------------------------------------------------------------- */ if( poOpenInfo->eAccess == GA_ReadOnly ) poDS->fpImage = VSIFOpenL( osQubeFile, "r" ); else poDS->fpImage = VSIFOpenL( osQubeFile, "r+" ); if( poDS->fpImage == NULL ) { CPLError( CE_Failure, CPLE_OpenFailed, "Failed to open %s with write permission.\n%s", osQubeFile.c_str(), VSIStrerror( errno ) ); delete poDS; return NULL; } poDS->eAccess = poOpenInfo->eAccess; /* -------------------------------------------------------------------- */ /* Compute the line offsets. */ /* -------------------------------------------------------------------- */ const long int nItemSize = GDALGetDataTypeSize(eDataType)/8; const long int nPixelOffset = nItemSize; const long int nLineOffset = nPixelOffset * nCols + atoi(poDS->GetKeyword("NBB")) ; const long int nBandOffset = nLineOffset * nRows; nSkipBytes = atoi(poDS->GetKeyword("LBLSIZE")); /* -------------------------------------------------------------------- */ /* Create band information objects. */ /* -------------------------------------------------------------------- */ for( int i = 0; i < nBands; i++ ) { GDALRasterBand *poBand = new RawRasterBand( poDS, i+1, poDS->fpImage, nSkipBytes + nBandOffset * i, nPixelOffset, nLineOffset, eDataType, #ifdef CPL_LSB chByteOrder == 'I' || chByteOrder == 'L', #else chByteOrder == 'M', #endif TRUE ); poDS->SetBand( i+1, poBand ); poBand->SetNoDataValue( dfNoData ); if (bIsDTM) { poBand->SetScale( (double) CPLAtof(poDS->GetKeyword( "DTM.DTM_SCALING_FACTOR") ) ); poBand->SetOffset( (double) CPLAtof(poDS->GetKeyword( "DTM.DTM_OFFSET") ) ); const char* pszMin = poDS->GetKeyword( "DTM.DTM_MINIMUM_DN", NULL ); const char* pszMax = poDS->GetKeyword( "DTM.DTM_MAXIMUM_DN", NULL ); if (pszMin != NULL && pszMax != NULL ) poBand->SetStatistics(CPLAtofM(pszMin),CPLAtofM(pszMax),0,0); const char* pszNoData = poDS->GetKeyword( "DTM.DTM_MISSING_DN", NULL ); if (pszNoData != NULL ) poBand->SetNoDataValue( CPLAtofM(pszNoData) ); } else if (EQUAL( poDS->GetKeyword( "BLTYPE"), "M94_HRSC" )) { float scale=CPLAtof(poDS->GetKeyword("DLRTO8.REFLECTANCE_SCALING_FACTOR","-1.")); if (scale < 0.) { scale = CPLAtof(poDS->GetKeyword( "HRCAL.REFLECTANCE_SCALING_FACTOR","1.")); } poBand->SetScale( scale ); float offset=CPLAtof(poDS->GetKeyword("DLRTO8.REFLECTANCE_OFFSET","-1.")); if (offset < 0.) { offset = CPLAtof(poDS->GetKeyword( "HRCAL.REFLECTANCE_OFFSET","0.")); } poBand->SetOffset( offset ); } const char* pszMin = poDS->GetKeyword( "STATISTICS.MINIMUM", NULL ); const char* pszMax = poDS->GetKeyword( "STATISTICS.MAXIMUM", NULL ); const char* pszMean = poDS->GetKeyword( "STATISTICS.MEAN", NULL ); const char* pszStdDev = poDS->GetKeyword( "STATISTICS.STANDARD_DEVIATION", NULL ); if (pszMin != NULL && pszMax != NULL && pszMean != NULL && pszStdDev != NULL ) poBand->SetStatistics(CPLAtofM(pszMin),CPLAtofM(pszMax),CPLAtofM(pszMean),CPLAtofM(pszStdDev)); } /* -------------------------------------------------------------------- */ /* Instrument-specific keywords as metadata. */ /* -------------------------------------------------------------------- */ /****************** HRSC ******************************/ if (EQUAL( poDS->GetKeyword( "BLTYPE"), "M94_HRSC" ) ) { poDS->SetMetadataItem( "SPACECRAFT_NAME", poDS->GetKeyword( "M94_INSTRUMENT.INSTRUMENT_HOST_NAME") ); poDS->SetMetadataItem( "PRODUCT_TYPE", poDS->GetKeyword( "TYPE")); if (EQUAL( poDS->GetKeyword( "M94_INSTRUMENT.DETECTOR_ID"), "MEX_HRSC_SRC" )) { static const char *apszKeywords[] = { "M94_ORBIT.IMAGE_TIME", "FILE.EVENT_TYPE", "FILE.PROCESSING_LEVEL_ID", "M94_INSTRUMENT.DETECTOR_ID", "M94_CAMERAS.EXPOSURE_DURATION", "HRCONVER.INSTRUMENT_TEMPERATURE", NULL }; for( int i = 0; apszKeywords[i] != NULL; i++ ) { const char *pszKeywordValue = poDS->GetKeyword( apszKeywords[i] ); if( pszKeywordValue != NULL ) poDS->SetMetadataItem( apszKeywords[i], pszKeywordValue ); } } else { static const char *apszKeywords[] = { "M94_ORBIT.START_TIME", "M94_ORBIT.STOP_TIME", "M94_INSTRUMENT.DETECTOR_ID", "M94_CAMERAS.MACROPIXEL_SIZE", "FILE.EVENT_TYPE", "M94_INSTRUMENT.MISSION_PHASE_NAME", "HRORTHO.SPICE_FILE_NAME", "HRCONVER.MISSING_FRAMES", "HRCONVER.OVERFLOW_FRAMES", "HRCONVER.ERROR_FRAMES", "HRFOOT.BEST_GROUND_SAMPLING_DISTANCE", "DLRTO8.RADIANCE_SCALING_FACTOR", "DLRTO8.RADIANCE_OFFSET", "DLRTO8.REFLECTANCE_SCALING_FACTOR", "DLRTO8.REFLECTANCE_OFFSET", "HRCAL.RADIANCE_SCALING_FACTOR", "HRCAL.RADIANCE_OFFSET", "HRCAL.REFLECTANCE_SCALING_FACTOR", "HRCAL.REFLECTANCE_OFFSET", "HRORTHO.DTM_NAME", "HRORTHO.EXTORI_FILE_NAME", "HRORTHO.GEOMETRIC_CALIB_FILE_NAME", NULL }; for( int i = 0; apszKeywords[i] != NULL; i++ ) { const char *pszKeywordValue = poDS->GetKeyword( apszKeywords[i], NULL ); if( pszKeywordValue != NULL ) poDS->SetMetadataItem( apszKeywords[i], pszKeywordValue ); } } } if (bIsDTM && EQUAL( poDS->GetKeyword( "MAP.TARGET_NAME"), "MARS" )) { poDS->SetMetadataItem( "SPACECRAFT_NAME", "MARS_EXPRESS" ); poDS->SetMetadataItem( "PRODUCT_TYPE", "DTM"); static const char *apszKeywords[] = { "DTM.DTM_MISSING_DN", "DTM.DTM_OFFSET", "DTM.DTM_SCALING_FACTOR", "DTM.DTM_A_AXIS_RADIUS", "DTM.DTM_B_AXIS_RADIUS", "DTM.DTM_C_AXIS_RADIUS", "DTM.DTM_DESC", "DTM.DTM_MINIMUM_DN", "DTM.DTM_MAXIMUM_DN", NULL }; for( int i = 0; apszKeywords[i] != NULL; i++ ) { const char *pszKeywordValue = poDS->GetKeyword( apszKeywords[i] ); if( pszKeywordValue != NULL ) poDS->SetMetadataItem( apszKeywords[i], pszKeywordValue ); } } /****************** DAWN ******************************/ else if (EQUAL( poDS->GetKeyword( "INSTRUMENT_ID"), "FC2" )) { poDS->SetMetadataItem( "SPACECRAFT_NAME", "DAWN" ); static const char *apszKeywords[] = {"ORBIT_NUMBER","FILTER_NUMBER", "FRONT_DOOR_STATUS", "FIRST_LINE", "FIRST_LINE_SAMPLE", "PRODUCER_INSTITUTION_NAME", "SOURCE_FILE_NAME", "PROCESSING_LEVEL_ID", "TARGET_NAME", "LIMB_IN_IMAGE", "POLE_IN_IMAGE", "REFLECTANCE_SCALING_FACTOR", "SPICE_FILE_NAME", "SPACECRAFT_CENTRIC_LATITUDE", "SPACECRAFT_EASTERN_LONGITUDE", "FOOTPRINT_POSITIVE_LONGITUDE", NULL }; for( int i = 0; apszKeywords[i] != NULL; i++ ) { const char *pszKeywordValue = poDS->GetKeyword( apszKeywords[i] ); if( pszKeywordValue != NULL ) poDS->SetMetadataItem( apszKeywords[i], pszKeywordValue ); } } else if (bIsDTM && EQUAL( poDS->GetKeyword( "TARGET_NAME"), "VESTA" )) { poDS->SetMetadataItem( "SPACECRAFT_NAME", "DAWN" ); poDS->SetMetadataItem( "PRODUCT_TYPE", "DTM"); static const char *apszKeywords[] = { "DTM_MISSING_DN", "DTM_OFFSET", "DTM_SCALING_FACTOR", "DTM_A_AXIS_RADIUS", "DTM_B_AXIS_RADIUS", "DTM_C_AXIS_RADIUS", "DTM_MINIMUM_DN", "DTM_MAXIMUM_DN", "MAP_PROJECTION_TYPE", "COORDINATE_SYSTEM_NAME", "POSITIVE_LONGITUDE_DIRECTION", "MAP_SCALE", "CENTER_LONGITUDE", "LINE_PROJECTION_OFFSET", "SAMPLE_PROJECTION_OFFSET", NULL }; for( int i = 0; apszKeywords[i] != NULL; i++ ) { const char *pszKeywordValue = poDS->GetKeyword( apszKeywords[i] ); if( pszKeywordValue != NULL ) poDS->SetMetadataItem( apszKeywords[i], pszKeywordValue ); } } /* -------------------------------------------------------------------- */ /* END Instrument-specific keywords as metadata. */ /* -------------------------------------------------------------------- */ if (EQUAL(poDS->GetKeyword( "EOL"), "1" )) poDS->SetMetadataItem( "END-OF-DATASET_LABEL", "PRESENT" ); poDS->SetMetadataItem( "CONVERSION_DETAILS", "http://www.lpi.usra.edu/meetings/lpsc2014/pdf/1088.pdf" ); /* -------------------------------------------------------------------- */ /* Initialize any PAM information. */ /* -------------------------------------------------------------------- */ poDS->TryLoadXML(); /* -------------------------------------------------------------------- */ /* Check for overviews. */ /* -------------------------------------------------------------------- */ poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename ); return( poDS ); }
/* * Algorithm taken from: http://www.quantdec.com/SYSEN597/GTKAV/section9/map_algebra.htm * */ int Raster::ReSample(const char * pOutputRaster, double fNewCellSize, double fNewLeft, double fNewTop, int nNewRows, int nNewCols) { if (fNewCellSize <= 0) return CELL_SIZE_ERROR; if (fNewLeft <=0) return LEFT_ERROR; if (fNewTop <=0) return TOP_ERROR; if (nNewRows <=0) return ROWS_ERROR; if (nNewCols <=0) return COLS_ERROR; /************************************************************************************************* * Open the original dataset and retrieve its basic properties */ GDALDataset * pDSOld = (GDALDataset*) GDALOpen(m_sFilePath, GA_ReadOnly); if (pDSOld == NULL) return INPUT_FILE_ERROR; GDALRasterBand * pRBInput = pDSOld->GetRasterBand(1); /************************************************************************************************* * Create the new dataset. Determine the driver from the output file extension. * Enforce LZW compression for TIFs. The predictor 3 is used for floating point prediction. * Not using this value defaults the LZW to prediction to 1 which causes striping. */ char **papszOptions = NULL; GDALDriver * pDR = NULL; const char * pSuffix = ExtractFileExt(pOutputRaster); if (pSuffix == NULL) return OUTPUT_FILE_EXT_ERROR; else { if (strcmp(pSuffix, ".tif") == 0) { pDR = GetGDALDriverManager()->GetDriverByName("GTiff"); papszOptions = CSLSetNameValue(papszOptions, "COMPRESS", "LZW"); //papszOptions = CSLSetNameValue(papszOptions, "PREDICTOR", "3"); } else if (strcmp(pSuffix, ".img") == 0) pDR = GetGDALDriverManager()->GetDriverByName("HFA"); else return OUTPUT_UNHANDLED_DRIVER; } GDALDataset * pDSOutput = pDR->Create(pOutputRaster, nNewCols, nNewRows, 1, *GetGDALDataType(), papszOptions); CSLDestroy( papszOptions ); if (pDSOutput == NULL) return OUTPUT_FILE_ERROR; GDALRasterBand * pRBOutput = pDSOutput->GetRasterBand(1); if (HasNoDataValue()) { CPLErr er = pRBOutput->SetNoDataValue(this->GetNoDataValue()); if (er == CE_Failure || er == CE_Fatal) return OUTPUT_NO_DATA_ERROR; } double newTransform[6]; newTransform[0] = fNewLeft; newTransform[1] = fNewCellSize; newTransform[2] = 0; newTransform[3] = fNewTop; newTransform[4] = 0; newTransform[5] = -1 * fNewCellSize; pDSOutput->SetGeoTransform(newTransform); pDSOutput->SetProjection(GetProjectionRef()); ReSampleRaster(pRBInput, pRBOutput, fNewCellSize, fNewLeft, fNewTop, nNewRows, nNewCols); CalculateStats(pDSOutput->GetRasterBand(1)); GDALClose(pDSOld); GDALClose(pDSOutput); return PROCESS_OK; }
CPLErr GDALPamDataset::TryLoadAux() { /* -------------------------------------------------------------------- */ /* Initialize PAM. */ /* -------------------------------------------------------------------- */ PamInitialize(); if( psPam == NULL ) return CE_None; /* -------------------------------------------------------------------- */ /* What is the name of the physical file we are referencing? */ /* We allow an override via the psPam->pszPhysicalFile item. */ /* -------------------------------------------------------------------- */ const char *pszPhysicalFile = psPam->osPhysicalFilename; if( strlen(pszPhysicalFile) == 0 && GetDescription() != NULL ) pszPhysicalFile = GetDescription(); if( strlen(pszPhysicalFile) == 0 ) return CE_None; /* -------------------------------------------------------------------- */ /* Try to open .aux file. */ /* -------------------------------------------------------------------- */ GDALDataset *poAuxDS = GDALFindAssociatedAuxFile( pszPhysicalFile, GA_ReadOnly, this ); if( poAuxDS == NULL ) return CE_None; /* -------------------------------------------------------------------- */ /* Do we have an SRS on the aux file? */ /* -------------------------------------------------------------------- */ if( strlen(poAuxDS->GetProjectionRef()) > 0 ) GDALPamDataset::SetProjection( poAuxDS->GetProjectionRef() ); /* -------------------------------------------------------------------- */ /* Geotransform. */ /* -------------------------------------------------------------------- */ if( poAuxDS->GetGeoTransform( psPam->adfGeoTransform ) == CE_None ) psPam->bHaveGeoTransform = TRUE; /* -------------------------------------------------------------------- */ /* GCPs */ /* -------------------------------------------------------------------- */ if( poAuxDS->GetGCPCount() > 0 ) { psPam->nGCPCount = poAuxDS->GetGCPCount(); psPam->pasGCPList = GDALDuplicateGCPs( psPam->nGCPCount, poAuxDS->GetGCPs() ); } /* -------------------------------------------------------------------- */ /* Apply metadata. We likely ought to be merging this in rather */ /* than overwriting everything that was there. */ /* -------------------------------------------------------------------- */ char **papszMD = poAuxDS->GetMetadata(); if( CSLCount(papszMD) > 0 ) { char **papszMerged = CSLMerge( CSLDuplicate(GetMetadata()), papszMD ); GDALPamDataset::SetMetadata( papszMerged ); CSLDestroy( papszMerged ); } papszMD = poAuxDS->GetMetadata("XFORMS"); if( CSLCount(papszMD) > 0 ) { char **papszMerged = CSLMerge( CSLDuplicate(GetMetadata("XFORMS")), papszMD ); GDALPamDataset::SetMetadata( papszMerged, "XFORMS" ); CSLDestroy( papszMerged ); } /* ==================================================================== */ /* Process bands. */ /* ==================================================================== */ int iBand; for( iBand = 0; iBand < poAuxDS->GetRasterCount(); iBand++ ) { if( iBand >= GetRasterCount() ) break; GDALRasterBand *poAuxBand = poAuxDS->GetRasterBand( iBand+1 ); GDALRasterBand *poBand = GetRasterBand( iBand+1 ); papszMD = poAuxBand->GetMetadata(); if( CSLCount(papszMD) > 0 ) { char **papszMerged = CSLMerge( CSLDuplicate(poBand->GetMetadata()), papszMD ); poBand->SetMetadata( papszMerged ); CSLDestroy( papszMerged ); } if( poAuxBand->GetCategoryNames() != NULL ) poBand->SetCategoryNames( poAuxBand->GetCategoryNames() ); if( poAuxBand->GetColorTable() != NULL && poBand->GetColorTable() == NULL ) poBand->SetColorTable( poAuxBand->GetColorTable() ); // histograms? double dfMin, dfMax; int nBuckets, *panHistogram=NULL; if( poAuxBand->GetDefaultHistogram( &dfMin, &dfMax, &nBuckets, &panHistogram, FALSE, NULL, NULL ) == CE_None ) { poBand->SetDefaultHistogram( dfMin, dfMax, nBuckets, panHistogram ); CPLFree( panHistogram ); } // RAT if( poAuxBand->GetDefaultRAT() != NULL ) poBand->SetDefaultRAT( poAuxBand->GetDefaultRAT() ); // NoData int bSuccess = FALSE; double dfNoDataValue = poAuxBand->GetNoDataValue( &bSuccess ); if( bSuccess ) poBand->SetNoDataValue( dfNoDataValue ); } GDALClose( poAuxDS ); /* -------------------------------------------------------------------- */ /* Mark PAM info as clean. */ /* -------------------------------------------------------------------- */ nPamFlags &= ~GPF_DIRTY; return CE_Failure; }
void ccRasterizeTool::generateRaster() const { #ifdef CC_GDAL_SUPPORT if (!m_cloud || !m_grid.isValid()) return; GDALAllRegister(); ccLog::PrintDebug("(GDAL drivers: %i)", GetGDALDriverManager()->GetDriverCount()); const char *pszFormat = "GTiff"; GDALDriver *poDriver = GetGDALDriverManager()->GetDriverByName(pszFormat); if (!poDriver) { ccLog::Error("[GDAL] Driver %s is not supported", pszFormat); return; } char** papszMetadata = poDriver->GetMetadata(); if( !CSLFetchBoolean( papszMetadata, GDAL_DCAP_CREATE, FALSE ) ) { ccLog::Error("[GDAL] Driver %s doesn't support Create() method", pszFormat); return; } //which (and how many) bands shall we create? bool heightBand = true; //height by default bool densityBand = false; bool allSFBands = false; int sfBandIndex = -1; //scalar field index int totalBands = 0; bool interpolateSF = (getTypeOfSFInterpolation() != INVALID_PROJECTION_TYPE); ccPointCloud* pc = m_cloud->isA(CC_TYPES::POINT_CLOUD) ? static_cast<ccPointCloud*>(m_cloud) : 0; bool hasSF = interpolateSF && pc && !m_grid.scalarFields.empty(); RasterExportOptionsDlg reoDlg; reoDlg.dimensionsLabel->setText(QString("%1 x %2").arg(m_grid.width).arg(m_grid.height)); reoDlg.exportHeightsCheckBox->setChecked(heightBand); reoDlg.exportDensityCheckBox->setChecked(densityBand); reoDlg.exportDisplayedSFCheckBox->setEnabled(hasSF); reoDlg.exportAllSFCheckBox->setEnabled(hasSF); reoDlg.exportAllSFCheckBox->setChecked(allSFBands); if (!reoDlg.exec()) return; //we ask the output filename AFTER displaying the export parameters ;) QString outputFilename; { QSettings settings; settings.beginGroup(ccPS::HeightGridGeneration()); QString imageSavePath = settings.value("savePathImage",QApplication::applicationDirPath()).toString(); outputFilename = QFileDialog::getSaveFileName(0,"Save height grid raster",imageSavePath+QString("/raster.tif"),"geotiff (*.tif)"); if (outputFilename.isNull()) return; //save current export path to persistent settings settings.setValue("savePathImage",QFileInfo(outputFilename).absolutePath()); } heightBand = reoDlg.exportHeightsCheckBox->isChecked(); densityBand = reoDlg.exportDensityCheckBox->isChecked(); if (hasSF) { assert(pc); allSFBands = reoDlg.exportAllSFCheckBox->isChecked() && hasSF; if (!allSFBands && reoDlg.exportDisplayedSFCheckBox->isChecked()) { sfBandIndex = pc->getCurrentDisplayedScalarFieldIndex(); if (sfBandIndex < 0) ccLog::Warning("[Rasterize] Cloud has no active (displayed) SF!"); } } totalBands = heightBand ? 1 : 0; if (densityBand) { ++totalBands; } if (allSFBands) { assert(hasSF); for (size_t i=0; i<m_grid.scalarFields.size(); ++i) if (m_grid.scalarFields[i]) ++totalBands; } else if (sfBandIndex >= 0) { ++totalBands; } if (totalBands == 0) { ccLog::Warning("[Rasterize] Warning, can't output a raster with no band! (check export parameters)"); return; } //data type GDALDataType dataType = (std::max(sizeof(PointCoordinateType),sizeof(ScalarType)) > 4 ? GDT_Float64 : GDT_Float32); char **papszOptions = NULL; GDALDataset* poDstDS = poDriver->Create(qPrintable(outputFilename), static_cast<int>(m_grid.width), static_cast<int>(m_grid.height), totalBands, dataType, papszOptions); if (!poDstDS) { ccLog::Error("[GDAL] Failed to create output raster (not enough memory?)"); return; } ccBBox box = getCustomBBox(); assert(box.isValid()); //vertical dimension const unsigned char Z = getProjectionDimension(); assert(Z >= 0 && Z <= 2); const unsigned char X = Z == 2 ? 0 : Z +1; const unsigned char Y = X == 2 ? 0 : X +1; double shiftX = box.minCorner().u[X]; double shiftY = box.minCorner().u[Y]; double stepX = m_grid.gridStep; double stepY = m_grid.gridStep; if (pc) { const CCVector3d& shift = pc->getGlobalShift(); shiftX -= shift.u[X]; shiftY -= shift.u[Y]; double scale = pc->getGlobalScale(); assert(scale != 0); stepX /= scale; stepY /= scale; } double adfGeoTransform[6] = { shiftX, //top left x stepX, //w-e pixel resolution (can be negative) 0, //0 shiftY, //top left y 0, //0 stepY //n-s pixel resolution (can be negative) }; poDstDS->SetGeoTransform( adfGeoTransform ); //OGRSpatialReference oSRS; //oSRS.SetUTM( 11, TRUE ); //oSRS.SetWellKnownGeogCS( "NAD27" ); //char *pszSRS_WKT = NULL; //oSRS.exportToWkt( &pszSRS_WKT ); //poDstDS->SetProjection( pszSRS_WKT ); //CPLFree( pszSRS_WKT ); double* scanline = (double*) CPLMalloc(sizeof(double)*m_grid.width); int currentBand = 0; //exort height band? if (heightBand) { GDALRasterBand* poBand = poDstDS->GetRasterBand(++currentBand); assert(poBand); poBand->SetColorInterpretation(GCI_Undefined); EmptyCellFillOption fillEmptyCellsStrategy = getFillEmptyCellsStrategy(fillEmptyCellsComboBox); double emptyCellHeight = 0; switch (fillEmptyCellsStrategy) { case LEAVE_EMPTY: emptyCellHeight = m_grid.minHeight-1.0; poBand->SetNoDataValue(emptyCellHeight); //should be transparent! break; case FILL_MINIMUM_HEIGHT: emptyCellHeight = m_grid.minHeight; break; case FILL_MAXIMUM_HEIGHT: emptyCellHeight = m_grid.maxHeight; break; case FILL_CUSTOM_HEIGHT: emptyCellHeight = getCustomHeightForEmptyCells(); break; case FILL_AVERAGE_HEIGHT: emptyCellHeight = m_grid.meanHeight; break; default: assert(false); } for (unsigned j=0; j<m_grid.height; ++j) { const RasterCell* aCell = m_grid.data[j]; for (unsigned i=0; i<m_grid.width; ++i,++aCell) { scanline[i] = aCell->h == aCell->h ? aCell->h : emptyCellHeight; } if (poBand->RasterIO( GF_Write, 0, static_cast<int>(j), static_cast<int>(m_grid.width), 1, scanline, static_cast<int>(m_grid.width), 1, GDT_Float64, 0, 0 ) != CE_None) { ccLog::Error("[GDAL] An error occurred while writing the height band!"); if (scanline) CPLFree(scanline); GDALClose( (GDALDatasetH) poDstDS ); return; } } } //export density band if (densityBand) { GDALRasterBand* poBand = poDstDS->GetRasterBand(++currentBand); assert(poBand); poBand->SetColorInterpretation(GCI_Undefined); for (unsigned j=0; j<m_grid.height; ++j) { const RasterCell* aCell = m_grid.data[j]; for (unsigned i=0; i<m_grid.width; ++i,++aCell) { scanline[i] = aCell->nbPoints; } if (poBand->RasterIO( GF_Write, 0, static_cast<int>(j), static_cast<int>(m_grid.width), 1, scanline, static_cast<int>(m_grid.width), 1, GDT_Float64, 0, 0 ) != CE_None) { ccLog::Error("[GDAL] An error occurred while writing the height band!"); if (scanline) CPLFree(scanline); GDALClose( (GDALDatasetH) poDstDS ); return; } } } //export SF bands if (allSFBands || sfBandIndex >= 0) { for (size_t k=0; k<m_grid.scalarFields.size(); ++k) { double* _sfGrid = m_grid.scalarFields[k]; if (_sfGrid && (allSFBands || sfBandIndex == static_cast<int>(k))) //valid SF grid { GDALRasterBand* poBand = poDstDS->GetRasterBand(++currentBand); double sfNanValue = static_cast<double>(CCLib::ScalarField::NaN()); poBand->SetNoDataValue(sfNanValue); //should be transparent! assert(poBand); poBand->SetColorInterpretation(GCI_Undefined); for (unsigned j=0; j<m_grid.height; ++j) { const RasterCell* aCell = m_grid.data[j]; for (unsigned i=0; i<m_grid.width; ++i,++_sfGrid,++aCell) { scanline[i] = aCell->nbPoints ? *_sfGrid : sfNanValue; } if (poBand->RasterIO( GF_Write, 0, static_cast<int>(j), static_cast<int>(m_grid.width), 1, scanline, static_cast<int>(m_grid.width), 1, GDT_Float64, 0, 0 ) != CE_None) { //the corresponding SF should exist on the input cloud CCLib::ScalarField* formerSf = pc->getScalarField(static_cast<int>(k)); assert(formerSf); ccLog::Error(QString("[GDAL] An error occurred while writing the '%1' scalar field band!").arg(formerSf->getName())); k = m_grid.scalarFields.size(); //quick stop break; } } } } } if (scanline) CPLFree(scanline); scanline = 0; /* Once we're done, close properly the dataset */ GDALClose( (GDALDatasetH) poDstDS ); ccLog::Print(QString("[Rasterize] Raster '%1' succesfully saved").arg(outputFilename)); #else assert(false); ccLog::Error("[Rasterize] GDAL not supported by this version! Can't generate a raster..."); #endif }
CPLErr GTIFFBuildOverviews( const char * pszFilename, int nBands, GDALRasterBand **papoBandList, int nOverviews, int * panOverviewList, const char * pszResampling, GDALProgressFunc pfnProgress, void * pProgressData ) { TIFF *hOTIFF; int nBitsPerPixel=0, nCompression=COMPRESSION_NONE, nPhotometric=0; int nSampleFormat=0, nPlanarConfig, iOverview, iBand; int nXSize=0, nYSize=0; if( nBands == 0 || nOverviews == 0 ) return CE_None; if (!GTiffOneTimeInit()) return CE_Failure; /* -------------------------------------------------------------------- */ /* Verify that the list of bands is suitable for emitting in */ /* TIFF file. */ /* -------------------------------------------------------------------- */ for( iBand = 0; iBand < nBands; iBand++ ) { int nBandBits, nBandFormat; GDALRasterBand *hBand = papoBandList[iBand]; switch( hBand->GetRasterDataType() ) { case GDT_Byte: nBandBits = 8; nBandFormat = SAMPLEFORMAT_UINT; break; case GDT_UInt16: nBandBits = 16; nBandFormat = SAMPLEFORMAT_UINT; break; case GDT_Int16: nBandBits = 16; nBandFormat = SAMPLEFORMAT_INT; break; case GDT_UInt32: nBandBits = 32; nBandFormat = SAMPLEFORMAT_UINT; break; case GDT_Int32: nBandBits = 32; nBandFormat = SAMPLEFORMAT_INT; break; case GDT_Float32: nBandBits = 32; nBandFormat = SAMPLEFORMAT_IEEEFP; break; case GDT_Float64: nBandBits = 64; nBandFormat = SAMPLEFORMAT_IEEEFP; break; case GDT_CInt16: nBandBits = 32; nBandFormat = SAMPLEFORMAT_COMPLEXINT; break; case GDT_CInt32: nBandBits = 64; nBandFormat = SAMPLEFORMAT_COMPLEXINT; break; case GDT_CFloat32: nBandBits = 64; nBandFormat = SAMPLEFORMAT_COMPLEXIEEEFP; break; case GDT_CFloat64: nBandBits = 128; nBandFormat = SAMPLEFORMAT_COMPLEXIEEEFP; break; default: CPLAssert( FALSE ); return CE_Failure; } if( hBand->GetMetadataItem( "NBITS", "IMAGE_STRUCTURE" ) ) { nBandBits = atoi(hBand->GetMetadataItem("NBITS","IMAGE_STRUCTURE")); if( nBandBits == 1 && EQUALN(pszResampling,"AVERAGE_BIT2",12) ) nBandBits = 8; } if( iBand == 0 ) { nBitsPerPixel = nBandBits; nSampleFormat = nBandFormat; nXSize = hBand->GetXSize(); nYSize = hBand->GetYSize(); } else if( nBitsPerPixel != nBandBits || nSampleFormat != nBandFormat ) { CPLError( CE_Failure, CPLE_NotSupported, "GTIFFBuildOverviews() doesn't support a mixture of band" " data types." ); return CE_Failure; } else if( hBand->GetColorTable() != NULL ) { CPLError( CE_Failure, CPLE_NotSupported, "GTIFFBuildOverviews() doesn't support building" " overviews of multiple colormapped bands." ); return CE_Failure; } else if( hBand->GetXSize() != nXSize || hBand->GetYSize() != nYSize ) { CPLError( CE_Failure, CPLE_NotSupported, "GTIFFBuildOverviews() doesn't support building" " overviews of different sized bands." ); return CE_Failure; } } /* -------------------------------------------------------------------- */ /* Use specified compression method. */ /* -------------------------------------------------------------------- */ const char *pszCompress = CPLGetConfigOption( "COMPRESS_OVERVIEW", NULL ); if( pszCompress != NULL && pszCompress[0] != '\0' ) { nCompression = GTIFFGetCompressionMethod(pszCompress, "COMPRESS_OVERVIEW"); if (nCompression < 0) return CE_Failure; } if( nCompression == COMPRESSION_JPEG && nBitsPerPixel > 8 ) { if( nBitsPerPixel > 16 ) { CPLError( CE_Failure, CPLE_NotSupported, "GTIFFBuildOverviews() doesn't support building" " JPEG compressed overviews of nBitsPerPixel > 16." ); return CE_Failure; } nBitsPerPixel = 12; } /* -------------------------------------------------------------------- */ /* Figure out the planar configuration to use. */ /* -------------------------------------------------------------------- */ if( nBands == 1 ) nPlanarConfig = PLANARCONFIG_CONTIG; else nPlanarConfig = PLANARCONFIG_SEPARATE; const char* pszInterleave = CPLGetConfigOption( "INTERLEAVE_OVERVIEW", NULL ); if (pszInterleave != NULL && pszInterleave[0] != '\0') { if( EQUAL( pszInterleave, "PIXEL" ) ) nPlanarConfig = PLANARCONFIG_CONTIG; else if( EQUAL( pszInterleave, "BAND" ) ) nPlanarConfig = PLANARCONFIG_SEPARATE; else { CPLError( CE_Failure, CPLE_AppDefined, "INTERLEAVE_OVERVIEW=%s unsupported, value must be PIXEL or BAND. ignoring", pszInterleave ); } } /* -------------------------------------------------------------------- */ /* Figure out the photometric interpretation to use. */ /* -------------------------------------------------------------------- */ if( nBands == 3 ) nPhotometric = PHOTOMETRIC_RGB; else if( papoBandList[0]->GetColorTable() != NULL && !EQUALN(pszResampling,"AVERAGE_BIT2",12) ) { nPhotometric = PHOTOMETRIC_PALETTE; /* should set the colormap up at this point too! */ } else nPhotometric = PHOTOMETRIC_MINISBLACK; const char* pszPhotometric = CPLGetConfigOption( "PHOTOMETRIC_OVERVIEW", NULL ); if (pszPhotometric != NULL && pszPhotometric[0] != '\0') { if( EQUAL( pszPhotometric, "MINISBLACK" ) ) nPhotometric = PHOTOMETRIC_MINISBLACK; else if( EQUAL( pszPhotometric, "MINISWHITE" ) ) nPhotometric = PHOTOMETRIC_MINISWHITE; else if( EQUAL( pszPhotometric, "RGB" )) { nPhotometric = PHOTOMETRIC_RGB; } else if( EQUAL( pszPhotometric, "CMYK" )) { nPhotometric = PHOTOMETRIC_SEPARATED; } else if( EQUAL( pszPhotometric, "YCBCR" )) { nPhotometric = PHOTOMETRIC_YCBCR; /* Because of subsampling, setting YCBCR without JPEG compression leads */ /* to a crash currently. Would need to make GTiffRasterBand::IWriteBlock() */ /* aware of subsampling so that it doesn't overrun buffer size returned */ /* by libtiff */ if ( nCompression != COMPRESSION_JPEG ) { CPLError(CE_Failure, CPLE_NotSupported, "Currently, PHOTOMETRIC_OVERVIEW=YCBCR requires COMPRESS_OVERVIEW=JPEG"); return CE_Failure; } if (pszInterleave != NULL && pszInterleave[0] != '\0' && nPlanarConfig == PLANARCONFIG_SEPARATE) { CPLError(CE_Failure, CPLE_NotSupported, "PHOTOMETRIC_OVERVIEW=YCBCR requires INTERLEAVE_OVERVIEW=PIXEL"); return CE_Failure; } else { nPlanarConfig = PLANARCONFIG_CONTIG; } /* YCBCR strictly requires 3 bands. Not less, not more */ /* Issue an explicit error message as libtiff one is a bit cryptic : */ /* JPEGLib:Bogus input colorspace */ if ( nBands != 3 ) { CPLError(CE_Failure, CPLE_NotSupported, "PHOTOMETRIC_OVERVIEW=YCBCR requires a source raster with only 3 bands (RGB)"); return CE_Failure; } } else if( EQUAL( pszPhotometric, "CIELAB" )) { nPhotometric = PHOTOMETRIC_CIELAB; } else if( EQUAL( pszPhotometric, "ICCLAB" )) { nPhotometric = PHOTOMETRIC_ICCLAB; } else if( EQUAL( pszPhotometric, "ITULAB" )) { nPhotometric = PHOTOMETRIC_ITULAB; } else { CPLError( CE_Warning, CPLE_IllegalArg, "PHOTOMETRIC_OVERVIEW=%s value not recognised, ignoring.\n", pszPhotometric ); } } /* -------------------------------------------------------------------- */ /* Figure out the predictor value to use. */ /* -------------------------------------------------------------------- */ int nPredictor = PREDICTOR_NONE; if ( nCompression == COMPRESSION_LZW || nCompression == COMPRESSION_ADOBE_DEFLATE ) { const char* pszPredictor = CPLGetConfigOption( "PREDICTOR_OVERVIEW", NULL ); if( pszPredictor != NULL ) { nPredictor = atoi( pszPredictor ); } } /* -------------------------------------------------------------------- */ /* Create the file, if it does not already exist. */ /* -------------------------------------------------------------------- */ VSIStatBufL sStatBuf; VSILFILE* fpL = NULL; if( VSIStatExL( pszFilename, &sStatBuf, VSI_STAT_EXISTS_FLAG ) != 0 ) { /* -------------------------------------------------------------------- */ /* Compute the uncompressed size. */ /* -------------------------------------------------------------------- */ double dfUncompressedOverviewSize = 0; int nDataTypeSize = GDALGetDataTypeSize(papoBandList[0]->GetRasterDataType())/8; for( iOverview = 0; iOverview < nOverviews; iOverview++ ) { int nOXSize, nOYSize; nOXSize = (nXSize + panOverviewList[iOverview] - 1) / panOverviewList[iOverview]; nOYSize = (nYSize + panOverviewList[iOverview] - 1) / panOverviewList[iOverview]; dfUncompressedOverviewSize += nOXSize * ((double)nOYSize) * nBands * nDataTypeSize; } if( nCompression == COMPRESSION_NONE && dfUncompressedOverviewSize > 4200000000.0 ) { #ifndef BIGTIFF_SUPPORT CPLError( CE_Failure, CPLE_NotSupported, "The overview file would be larger than 4GB\n" "but this is the largest size a TIFF can be, and BigTIFF is unavailable.\n" "Creation failed." ); return CE_Failure; #endif } /* -------------------------------------------------------------------- */ /* Should the file be created as a bigtiff file? */ /* -------------------------------------------------------------------- */ const char *pszBIGTIFF = CPLGetConfigOption( "BIGTIFF_OVERVIEW", NULL ); if( pszBIGTIFF == NULL ) pszBIGTIFF = "IF_NEEDED"; int bCreateBigTIFF = FALSE; if( EQUAL(pszBIGTIFF,"IF_NEEDED") ) { if( nCompression == COMPRESSION_NONE && dfUncompressedOverviewSize > 4200000000.0 ) bCreateBigTIFF = TRUE; } else if( EQUAL(pszBIGTIFF,"IF_SAFER") ) { /* Look at the size of the base image and suppose that */ /* the added overview levels won't be more than 1/2 of */ /* the size of the base image. The theory says 1/3 of the */ /* base image size if the overview levels are 2, 4, 8, 16... */ /* Thus take 1/2 as the security margin for 1/3 */ double dfUncompressedImageSize = nXSize * ((double)nYSize) * nBands * nDataTypeSize; if( dfUncompressedImageSize * .5 > 4200000000.0 ) bCreateBigTIFF = TRUE; } else { bCreateBigTIFF = CSLTestBoolean( pszBIGTIFF ); if (!bCreateBigTIFF && nCompression == COMPRESSION_NONE && dfUncompressedOverviewSize > 4200000000.0 ) { CPLError( CE_Failure, CPLE_NotSupported, "The overview file will be larger than 4GB, so BigTIFF is necessary.\n" "Creation failed."); return CE_Failure; } } #ifndef BIGTIFF_SUPPORT if( bCreateBigTIFF ) { CPLError( CE_Warning, CPLE_NotSupported, "BigTIFF requested, but GDAL built without BigTIFF\n" "enabled libtiff, request ignored." ); bCreateBigTIFF = FALSE; } #endif if( bCreateBigTIFF ) CPLDebug( "GTiff", "File being created as a BigTIFF." ); fpL = VSIFOpenL( pszFilename, "w+" ); if( fpL == NULL ) hOTIFF = NULL; else hOTIFF = VSI_TIFFOpen( pszFilename, (bCreateBigTIFF) ? "w+8" : "w+", fpL ); if( hOTIFF == NULL ) { if( CPLGetLastErrorNo() == 0 ) CPLError( CE_Failure, CPLE_OpenFailed, "Attempt to create new tiff file `%s'\n" "failed in VSI_TIFFOpen().\n", pszFilename ); if( fpL != NULL ) VSIFCloseL(fpL); return CE_Failure; } } /* -------------------------------------------------------------------- */ /* Otherwise just open it for update access. */ /* -------------------------------------------------------------------- */ else { fpL = VSIFOpenL( pszFilename, "r+" ); if( fpL == NULL ) hOTIFF = NULL; else hOTIFF = VSI_TIFFOpen( pszFilename, "r+", fpL ); if( hOTIFF == NULL ) { if( CPLGetLastErrorNo() == 0 ) CPLError( CE_Failure, CPLE_OpenFailed, "Attempt to create new tiff file `%s'\n" "failed in VSI_TIFFOpen().\n", pszFilename ); if( fpL != NULL ) VSIFCloseL(fpL); return CE_Failure; } } /* -------------------------------------------------------------------- */ /* Do we have a palette? If so, create a TIFF compatible version. */ /* -------------------------------------------------------------------- */ unsigned short *panRed=NULL, *panGreen=NULL, *panBlue=NULL; if( nPhotometric == PHOTOMETRIC_PALETTE ) { GDALColorTable *poCT = papoBandList[0]->GetColorTable(); int nColorCount; if( nBitsPerPixel <= 8 ) nColorCount = 256; else nColorCount = 65536; panRed = (unsigned short *) CPLCalloc(nColorCount,sizeof(unsigned short)); panGreen = (unsigned short *) CPLCalloc(nColorCount,sizeof(unsigned short)); panBlue = (unsigned short *) CPLCalloc(nColorCount,sizeof(unsigned short)); for( int iColor = 0; iColor < nColorCount; iColor++ ) { GDALColorEntry sRGB; if( poCT->GetColorEntryAsRGB( iColor, &sRGB ) ) { panRed[iColor] = (unsigned short) (257 * sRGB.c1); panGreen[iColor] = (unsigned short) (257 * sRGB.c2); panBlue[iColor] = (unsigned short) (257 * sRGB.c3); } } } /* -------------------------------------------------------------------- */ /* Do we need some metadata for the overviews? */ /* -------------------------------------------------------------------- */ CPLString osMetadata; GDALDataset *poBaseDS = papoBandList[0]->GetDataset(); GTIFFBuildOverviewMetadata( pszResampling, poBaseDS, osMetadata ); /* -------------------------------------------------------------------- */ /* Loop, creating overviews. */ /* -------------------------------------------------------------------- */ int nOvrBlockXSize, nOvrBlockYSize; GTIFFGetOverviewBlockSize(&nOvrBlockXSize, &nOvrBlockYSize); for( iOverview = 0; iOverview < nOverviews; iOverview++ ) { int nOXSize, nOYSize; nOXSize = (nXSize + panOverviewList[iOverview] - 1) / panOverviewList[iOverview]; nOYSize = (nYSize + panOverviewList[iOverview] - 1) / panOverviewList[iOverview]; GTIFFWriteDirectory(hOTIFF, FILETYPE_REDUCEDIMAGE, nOXSize, nOYSize, nBitsPerPixel, nPlanarConfig, nBands, nOvrBlockXSize, nOvrBlockYSize, TRUE, nCompression, nPhotometric, nSampleFormat, nPredictor, panRed, panGreen, panBlue, 0, NULL, /* FIXME? how can we fetch extrasamples */ osMetadata ); } if (panRed) { CPLFree(panRed); CPLFree(panGreen); CPLFree(panBlue); panRed = panGreen = panBlue = NULL; } XTIFFClose( hOTIFF ); VSIFCloseL(fpL); fpL = NULL; /* -------------------------------------------------------------------- */ /* Open the overview dataset so that we can get at the overview */ /* bands. */ /* -------------------------------------------------------------------- */ GDALDataset *hODS; CPLErr eErr = CE_None; hODS = (GDALDataset *) GDALOpen( pszFilename, GA_Update ); if( hODS == NULL ) return CE_Failure; /* -------------------------------------------------------------------- */ /* Do we need to set the jpeg quality? */ /* -------------------------------------------------------------------- */ TIFF *hTIFF = (TIFF*) hODS->GetInternalHandle(NULL); if( nCompression == COMPRESSION_JPEG && CPLGetConfigOption( "JPEG_QUALITY_OVERVIEW", NULL ) != NULL ) { int nJpegQuality = atoi(CPLGetConfigOption("JPEG_QUALITY_OVERVIEW","75")); TIFFSetField( hTIFF, TIFFTAG_JPEGQUALITY, nJpegQuality ); GTIFFSetJpegQuality((GDALDatasetH)hODS, nJpegQuality); } /* -------------------------------------------------------------------- */ /* Loop writing overview data. */ /* -------------------------------------------------------------------- */ if (nCompression != COMPRESSION_NONE && nPlanarConfig == PLANARCONFIG_CONTIG && GDALDataTypeIsComplex(papoBandList[0]->GetRasterDataType()) == FALSE && papoBandList[0]->GetColorTable() == NULL && (EQUALN(pszResampling, "NEAR", 4) || EQUAL(pszResampling, "AVERAGE") || EQUAL(pszResampling, "GAUSS") || EQUAL(pszResampling, "CUBIC") || EQUAL(pszResampling, "CUBICSPLINE") || EQUAL(pszResampling, "LANCZOS") || EQUAL(pszResampling, "BILINEAR"))) { /* In the case of pixel interleaved compressed overviews, we want to generate */ /* the overviews for all the bands block by block, and not band after band, */ /* in order to write the block once and not loose space in the TIFF file */ GDALRasterBand ***papapoOverviewBands; papapoOverviewBands = (GDALRasterBand ***) CPLCalloc(sizeof(void*),nBands); for( iBand = 0; iBand < nBands && eErr == CE_None; iBand++ ) { GDALRasterBand *hSrcBand = papoBandList[iBand]; GDALRasterBand *hDstBand = hODS->GetRasterBand( iBand+1 ); papapoOverviewBands[iBand] = (GDALRasterBand **) CPLCalloc(sizeof(void*),nOverviews); papapoOverviewBands[iBand][0] = hDstBand; int bHasNoData; double noDataValue = hSrcBand->GetNoDataValue(&bHasNoData); if (bHasNoData) hDstBand->SetNoDataValue(noDataValue); for( int i = 0; i < nOverviews-1 && eErr == CE_None; i++ ) { papapoOverviewBands[iBand][i+1] = hDstBand->GetOverview(i); if (papapoOverviewBands[iBand][i+1] == NULL) eErr = CE_Failure; else { if (bHasNoData) papapoOverviewBands[iBand][i+1]->SetNoDataValue(noDataValue); } } } if (eErr == CE_None) eErr = GDALRegenerateOverviewsMultiBand(nBands, papoBandList, nOverviews, papapoOverviewBands, pszResampling, pfnProgress, pProgressData ); for( iBand = 0; iBand < nBands; iBand++ ) { CPLFree(papapoOverviewBands[iBand]); } CPLFree(papapoOverviewBands); } else { GDALRasterBand **papoOverviews; papoOverviews = (GDALRasterBand **) CPLCalloc(sizeof(void*),128); for( iBand = 0; iBand < nBands && eErr == CE_None; iBand++ ) { GDALRasterBand *hSrcBand = papoBandList[iBand]; GDALRasterBand *hDstBand; int nDstOverviews; hDstBand = hODS->GetRasterBand( iBand+1 ); int bHasNoData; double noDataValue = hSrcBand->GetNoDataValue(&bHasNoData); if (bHasNoData) hDstBand->SetNoDataValue(noDataValue); papoOverviews[0] = hDstBand; nDstOverviews = hDstBand->GetOverviewCount() + 1; CPLAssert( nDstOverviews < 128 ); nDstOverviews = MIN(128,nDstOverviews); for( int i = 0; i < nDstOverviews-1 && eErr == CE_None; i++ ) { papoOverviews[i+1] = hDstBand->GetOverview(i); if (papoOverviews[i+1] == NULL) eErr = CE_Failure; else { if (bHasNoData) papoOverviews[i+1]->SetNoDataValue(noDataValue); } } void *pScaledProgressData; pScaledProgressData = GDALCreateScaledProgress( iBand / (double) nBands, (iBand+1) / (double) nBands, pfnProgress, pProgressData ); if (eErr == CE_None) eErr = GDALRegenerateOverviews( (GDALRasterBandH) hSrcBand, nDstOverviews, (GDALRasterBandH *) papoOverviews, pszResampling, GDALScaledProgress, pScaledProgressData); GDALDestroyScaledProgress( pScaledProgressData ); } CPLFree( papoOverviews ); } /* -------------------------------------------------------------------- */ /* Cleanup */ /* -------------------------------------------------------------------- */ if (eErr == CE_None) hODS->FlushCache(); delete hODS; pfnProgress( 1.0, NULL, pProgressData ); return eErr; }
int OutCoreInterp::outputFile(char *outputName, int outputFormat, unsigned int outputType, double *adfGeoTransform, const char* wkt) { int i, j, k, l, t; FILE **arcFiles; char arcFileName[1024]; FILE **gridFiles; char gridFileName[1024]; const char *ext[6] = {".min", ".max", ".mean", ".idw", ".den", ".std"}; unsigned int type[6] = {OUTPUT_TYPE_MIN, OUTPUT_TYPE_MAX, OUTPUT_TYPE_MEAN, OUTPUT_TYPE_IDW, OUTPUT_TYPE_DEN, OUTPUT_TYPE_STD}; int numTypes = 6; // open ArcGIS files if(outputFormat == OUTPUT_FORMAT_ARC_ASCII || outputFormat == OUTPUT_FORMAT_ALL) { if((arcFiles = (FILE **)malloc(sizeof(FILE *) * numTypes)) == NULL) { cerr << "Arc File open error: " << endl; return -1; } for(i = 0; i < numTypes; i++) { if(outputType & type[i]) { strncpy(arcFileName, outputName, sizeof(arcFileName)); strncat(arcFileName, ext[i], strlen(ext[i])); strncat(arcFileName, ".asc", strlen(".asc")); if((arcFiles[i] = fopen(arcFileName, "w+")) == NULL) { cerr << "File open error: " << arcFileName << endl; return -1; } } else { arcFiles[i] = NULL; } } } else { arcFiles = NULL; } // open Grid ASCII files if(outputFormat == OUTPUT_FORMAT_GRID_ASCII || outputFormat == OUTPUT_FORMAT_ALL) { if((gridFiles = (FILE **)malloc(sizeof(FILE *) * numTypes)) == NULL) { cerr << "File array allocation error" << endl; return -1; } for(i = 0; i < numTypes; i++) { if(outputType & type[i]) { strncpy(gridFileName, outputName, sizeof(arcFileName)); strncat(gridFileName, ext[i], strlen(ext[i])); strncat(gridFileName, ".grid", strlen(".grid")); if((gridFiles[i] = fopen(gridFileName, "w+")) == NULL) { cerr << "File open error: " << gridFileName << endl; return -1; } } else { gridFiles[i] = NULL; } } } else { gridFiles = NULL; } // print ArcGIS headers if(arcFiles != NULL) { for(i = 0; i < numTypes; i++) { if(arcFiles[i] != NULL) { fprintf(arcFiles[i], "ncols %d\n", GRID_SIZE_X); fprintf(arcFiles[i], "nrows %d\n", GRID_SIZE_Y); fprintf(arcFiles[i], "xllcorner %f\n", min_x); fprintf(arcFiles[i], "yllcorner %f\n", min_y); fprintf(arcFiles[i], "cellsize %f\n", GRID_DIST_X); fprintf(arcFiles[i], "NODATA_value -9999\n"); } } } // print Grid headers if(gridFiles != NULL) { for(i = 0; i < numTypes; i++) { if(gridFiles[i] != NULL) { fprintf(gridFiles[i], "north: %f\n", max_y); fprintf(gridFiles[i], "south: %f\n", min_y); fprintf(gridFiles[i], "east: %f\n", max_x); fprintf(gridFiles[i], "west: %f\n", min_x); fprintf(gridFiles[i], "rows: %d\n", GRID_SIZE_Y); fprintf(gridFiles[i], "cols: %d\n", GRID_SIZE_X); } } } for(i = numFiles -1; i >= 0; i--) { GridFile *gf = gridMap[i]->getGridFile(); gf->map(); int start = gridMap[i]->getLowerBound() - gridMap[i]->getOverlapLowerBound(); int end = gridMap[i]->getUpperBound() - gridMap[i]->getOverlapLowerBound() + 1; //int start = (gridMap[i]->getLowerBound() - gridMap[i]->getOverlapLowerBound()) * GRID_SIZE_X; //int end = (gridMap[i]->getUpperBound() - gridMap[i]->getOverlapLowerBound() + 1) * GRID_SIZE_X; cerr << "Merging " << i << ": from " << (start) << " to " << (end) << endl; cerr << " " << i << ": from " << (start/GRID_SIZE_X) << " to " << (end/GRID_SIZE_X) << endl; for(j = end - 1; j >= start; j--) { for(k = 0; k < GRID_SIZE_X; k++) { int index = j * GRID_SIZE_X + k; if(arcFiles != NULL) { // Zmin if(arcFiles[0] != NULL) { if(gf->interp[index].empty == 0 && gf->interp[index].filled == 0) //if(gf->interp[k][j].Zmin == 0) fprintf(arcFiles[0], "-9999 "); else //fprintf(arcFiles[0], "%f ", gf->interp[j][i].Zmin); fprintf(arcFiles[0], "%f ", gf->interp[index].Zmin); } // Zmax if(arcFiles[1] != NULL) { if(gf->interp[index].empty == 0 && gf->interp[index].filled == 0) fprintf(arcFiles[1], "-9999 "); else fprintf(arcFiles[1], "%f ", gf->interp[index].Zmax); } // Zmean if(arcFiles[2] != NULL) { if(gf->interp[index].empty == 0 && gf->interp[index].filled == 0) fprintf(arcFiles[2], "-9999 "); else fprintf(arcFiles[2], "%f ", gf->interp[index].Zmean); } // Zidw if(arcFiles[3] != NULL) { if(gf->interp[index].empty == 0 && gf->interp[index].filled == 0) fprintf(arcFiles[3], "-9999 "); else fprintf(arcFiles[3], "%f ", gf->interp[index].Zidw); } // count if(arcFiles[4] != NULL) { if(gf->interp[index].empty == 0 && gf->interp[index].filled == 0) fprintf(arcFiles[4], "-9999 "); else fprintf(arcFiles[4], "%d ", gf->interp[index].count); } // Zstd if(arcFiles[5] != NULL) { if(gf->interp[index].empty == 0 && gf->interp[index].filled == 0) fprintf(arcFiles[5], "-9999 "); else fprintf(arcFiles[5], "%f ", gf->interp[index].Zstd); } } if(gridFiles != NULL) { // Zmin if(gridFiles[0] != NULL) { if(gf->interp[index].empty == 0 && gf->interp[index].filled == 0) fprintf(gridFiles[0], "-9999 "); else fprintf(gridFiles[0], "%f ", gf->interp[index].Zmin); } // Zmax if(gridFiles[1] != NULL) { if(gf->interp[index].empty == 0 && gf->interp[index].filled == 0) fprintf(gridFiles[1], "-9999 "); else fprintf(gridFiles[1], "%f ", gf->interp[index].Zmax); } // Zmean if(gridFiles[2] != NULL) { if(gf->interp[index].empty == 0 && gf->interp[index].filled == 0) fprintf(gridFiles[2], "-9999 "); else fprintf(gridFiles[2], "%f ", gf->interp[index].Zmean); } // Zidw if(gridFiles[3] != NULL) { if(gf->interp[index].empty == 0 && gf->interp[index].filled == 0) fprintf(gridFiles[3], "-9999 "); else fprintf(gridFiles[3], "%f ", gf->interp[index].Zidw); } // count if(gridFiles[4] != NULL) { if(gf->interp[index].empty == 0 && gf->interp[index].filled == 0) fprintf(gridFiles[4], "-9999 "); else fprintf(gridFiles[4], "%d ", gf->interp[index].count); } // Zstd if(gridFiles[5] != NULL) { if(gf->interp[index].empty == 0 && gf->interp[index].filled == 0) fprintf(gridFiles[5], "-9999 "); else fprintf(gridFiles[5], "%f ", gf->interp[index].Zstd); } } } if(arcFiles != NULL) for(l = 0; l < numTypes; l++) { if(arcFiles[l] != NULL) fprintf(arcFiles[l], "\n"); } if(gridFiles != NULL) for(l = 0; l < numTypes; l++) { if(gridFiles[l] != NULL) fprintf(gridFiles[l], "\n"); } } gf->unmap(); } #ifdef HAVE_GDAL GDALDataset **gdalFiles; char gdalFileName[1024]; // open GDAL GeoTIFF files if(outputFormat == OUTPUT_FORMAT_GDAL_GTIFF || outputFormat == OUTPUT_FORMAT_ALL) { GDALAllRegister(); if((gdalFiles = (GDALDataset **)malloc(sizeof(GDALDataset *) * numTypes)) == NULL) { cerr << "File array allocation error" << endl; return -1; } for(i = 0; i < numTypes; i++) { if(outputType & type[i]) { strncpy(gdalFileName, outputName, sizeof(gdalFileName)); strncat(gdalFileName, ext[i], strlen(ext[i])); strncat(gdalFileName, ".tif", strlen(".tif")); char **papszMetadata; const char *pszFormat = "GTIFF"; GDALDriver* tpDriver = GetGDALDriverManager()->GetDriverByName(pszFormat); if (tpDriver) { papszMetadata = tpDriver->GetMetadata(); if (CSLFetchBoolean(papszMetadata, GDAL_DCAP_CREATE, FALSE)) { char **papszOptions = NULL; gdalFiles[i] = tpDriver->Create(gdalFileName, GRID_SIZE_X, GRID_SIZE_Y, 1, GDT_Float32, papszOptions); if (gdalFiles[i] == NULL) { cerr << "File open error: " << gdalFileName << endl; return -1; } else { if (adfGeoTransform) gdalFiles[i]->SetGeoTransform(adfGeoTransform); if (wkt) gdalFiles[i]->SetProjection(wkt); } } } } else { gdalFiles[i] = NULL; } } } else { gdalFiles = NULL; } if(gdalFiles != NULL) { for(t = 0; t < numTypes; t++) { if(gdalFiles[t] != NULL) { for(i = numFiles -1; i >= 0; i--) { GridFile *gf = gridMap[i]->getGridFile(); gf->map(); int start = gridMap[i]->getLowerBound() - gridMap[i]->getOverlapLowerBound(); int end = gridMap[i]->getUpperBound() - gridMap[i]->getOverlapLowerBound() + 1; cerr << "Merging " << i << ": from " << (start) << " to " << (end) << endl; cerr << " " << i << ": from " << (start/GRID_SIZE_X) << " to " << (end/GRID_SIZE_X) << endl; float *poRasterData = new float[GRID_SIZE_X*GRID_SIZE_Y]; for (int j = 0; j < GRID_SIZE_X*GRID_SIZE_Y; j++) { poRasterData[j] = 0; } for(j = end - 1; j >= start; j--) { for(k = 0; k < GRID_SIZE_X; k++) { int index = j * GRID_SIZE_X + k; if(gf->interp[index].empty == 0 && gf->interp[index].filled == 0) { poRasterData[index] = -9999.f; } else { switch (t) { case 0: poRasterData[index] = gf->interp[index].Zmin; break; case 1: poRasterData[index] = gf->interp[index].Zmax; break; case 2: poRasterData[index] = gf->interp[index].Zmean; break; case 3: poRasterData[index] = gf->interp[index].Zidw; break; case 4: poRasterData[index] = gf->interp[index].count; break; case 5: poRasterData[index] = gf->interp[index].Zstd; break; } } } } GDALRasterBand *tBand = gdalFiles[t]->GetRasterBand(1); tBand->SetNoDataValue(-9999.f); if (GRID_SIZE_X > 0 && GRID_SIZE_Y > 0) tBand->RasterIO(GF_Write, 0, 0, GRID_SIZE_X, GRID_SIZE_Y, poRasterData, GRID_SIZE_X, GRID_SIZE_Y, GDT_Float32, 0, 0); GDALClose((GDALDatasetH) gdalFiles[t]); delete [] poRasterData; } } } } #endif // HAVE_GDAL // close files if(gridFiles != NULL) { for(i = 0; i < numTypes; i++) { if(gridFiles[i] != NULL) fclose(gridFiles[i]); } } if(arcFiles != NULL) { for(i = 0; i < numTypes; i++) { if(arcFiles[i] != NULL) fclose(arcFiles[i]); } } return 0; }
int main(int argc, char* argv[]) { if (argc < 6) { cout << "webco <infile> <minlat> <minlon> <maxlat> <maxlon> <outfile>" << endl; exit(1); } const char* InFilename = argv[1]; int minlatpixel; int minlonpixel; int maxlatpixel; int maxlonpixel; { double minlat = atoi(argv[2]); double minlon = atoi(argv[3]); double maxlat = atoi(argv[4]); double maxlon = atoi(argv[5]); minlatpixel = minlat*RESOLUTION; minlonpixel = minlon*RESOLUTION; maxlatpixel = maxlat*RESOLUTION; maxlonpixel = maxlon*RESOLUTION; if (minlon == -180.0) { minlonpixel += MARGIN; maxlonpixel += MARGIN; } if (maxlon == 180.0) { minlonpixel -= MARGIN; maxlonpixel -= MARGIN; } } const char* OutFilename = argv[6]; GDALAllRegister(); // Create the output dataset and copy over relevant metadata const char* Format = "GTiff"; GDALDriver *poDriver = GetGDALDriverManager()->GetDriverByName(Format); char** Options = NULL; FILE *file = fopen(InFilename, "r"); cout << "Remove header." << endl; fseek(file, 611, SEEK_CUR); { cout << "Seek to lon/lat." << endl; int seeklat = (90*RESOLUTION-maxlatpixel-MARGIN)*2*WIDTH; int seeklon = (minlonpixel+180*RESOLUTION-MARGIN)*2; fseek(file, seeklon+seeklat, SEEK_CUR); /* if (maxlon == 180) { fseek(file, 1, SEEK_CUR); }*/ } cout << "Process image." << endl; GDALDataset* poDS; GDALRasterBand* poBand; /* char filename[20]; { char ns = maxlat < 0 ? 'S' : 'N'; char ew = minlon < 0 ? 'W' : 'E'; // sprintf(filename, "multi/%c%02i%c%03i.tif", ns, abs(maxlat), ew, abs(minlon)); sprintf(filename, "%c%02i%c%03i.tif", ns, abs(maxlat), ew, abs(minlon)); }*/ poDS = poDriver->Create(OutFilename,(maxlonpixel-minlonpixel)+2*MARGIN,(maxlatpixel-minlatpixel)+2*MARGIN,1,GDT_Float32,Options); // top left x, w-e pixel resolution, rotation, top left y, rotation, n-s pixel resolution double adfGeoTransform[6] = { (minlonpixel-MARGIN)*1.0/RESOLUTION, 1.0/RESOLUTION, 0, (maxlatpixel+MARGIN)*1.0/RESOLUTION, 0, -1.0/RESOLUTION }; poDS->SetGeoTransform(adfGeoTransform); // poDS->SetProjection(poDataset->GetProjectionRef()); poBand = poDS->GetRasterBand(1); poBand->SetNoDataValue(-9999); GDALAllRegister(); for (int y = 0; y < (maxlatpixel-minlatpixel)+2*MARGIN; y++) { cout << "\r" << y << "/" << (maxlatpixel-minlatpixel)+2*MARGIN; for (int x = 0; x < (maxlonpixel-minlonpixel)+2*MARGIN; x++) { int16_t height; int size = fread(&height, 2, 1, file); float pixel = (float)height; poBand->RasterIO(GF_Write, x, y, 1, 1, &pixel, 1, 1, GDT_Float32, 0, 0); } fseek(file, ((360*RESOLUTION-maxlonpixel+minlonpixel)-2*MARGIN)*2, SEEK_CUR); } cout << endl; delete poDS; fclose(file); return 0; }