Esempio n. 1
0
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);
}
Esempio n. 2
0
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;

}
Esempio n. 5
0
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;
}
Esempio n. 6
0
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;
}
Esempio n. 7
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() );
  }
}
Esempio n. 8
0
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;
}
Esempio n. 10
0
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;

}
Esempio n. 11
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 );
}
Esempio n. 12
0
/*
 * 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;
}
Esempio n. 13
0
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;
}
Esempio n. 14
0
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
}
Esempio n. 15
0
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;
}
Esempio n. 16
0
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;
}
Esempio n. 17
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;

}