int KHistogram::transform(GDALDataset *src, const char *dstName) {
  // prepare "how to make my copy" options to the file driver
  char **options = NULL;
  // optionsForTIFF = CSLSetNameValue(optionsForTIFF, "TILED", "YES");
  // optionsForTIFF = CSLSetNameValue(optionsForTIFF, "BLOCKXSIZE", "512"); //
  // integer multiple of 16
  // optionsForTIFF = CSLSetNameValue(optionsForTIFF, "BLOCKYSIZE", "512"); //
  // integer multiple of 16
  // optionsForTIFF = CSLSetNameValue(optionsForTIFF, "INTERLEAVE", "BAND"); //
  // PIXEL or BAND
  // optionsForTIFF = CSLSetNameValue(optionsForTIFF, "COMPRESS", "ZIP"); //
  // JPEG, LZW, PACKBITS, DEFLATE, ZIP

  // create copy of input image as output image
  GDALDriver *driver = src->GetDriver();
  GDALDataset *dst = (GDALDataset *)driver->CreateCopy(dstName, src, false,
                                                       options, NULL, NULL);
  // CSLDestroy(options);

  // apply transformation table to output image data
  apply(dst);

  // close output file
  GDALClose(dst);

  // normal termination
  return 0;
}
Beispiel #2
0
SEXP
RGDAL_CopyDataset(SEXP sxpDataset, SEXP sxpDriver,
		  SEXP sxpStrict,  SEXP sxpOpts,
		  SEXP sxpFile) {

  GDALDataset *pDataset = getGDALDatasetPtr(sxpDataset);

  const char *filename = asString(sxpFile);

  if (filename == NULL) error("Invalid filename\n");

  GDALDriver *pDriver = getGDALDriverPtr(sxpDriver);

  GDALDataset *pDatasetCopy = pDriver->CreateCopy(filename,
						  pDataset,
						  asInteger(sxpStrict),
						  NULL, NULL, NULL);

  if (pDatasetCopy == NULL) error("Dataset copy failed\n");

  SEXP sxpHandle = R_MakeExternalPtr((void *) pDatasetCopy,
				     mkChar("GDAL Dataset"),
				     R_NilValue);


  return(sxpHandle);

}
void ECWThread::run()
{
    try{
        GDALDataset *poSrcDS = (GDALDataset *)GDALOpen(TO8F(inputPath),GA_ReadOnly);
        if (poSrcDS==NULL)
            throw tr("Open input file failed!");

        if (poSrcDS->GetRasterBand(1)->GetRasterDataType()!=GDT_Byte)
            throw tr("Data type of input file is not byte!");

        GDALDriver *poDriver = GetGDALDriverManager()->GetDriverByName("JP2ECW");
        if (poDriver == NULL)
            throw tr("Data driver of ECW not found!");

        char **papszOptions = NULL;
        papszOptions = CSLSetNameValue( papszOptions, "LARGE_OK", "YES" );
//        papszOptions = CSLSetNameValue( papszOptions, "TARGET", "0" );



        GDALDataset *poDstDS = poDriver->CreateCopy(TO8F(outputPath),poSrcDS,NULL,papszOptions,progress,this);
        if (poDstDS==NULL)
            throw tr("Generate ecw file failed!");
        GDALClose(poSrcDS);
        GDALClose(poDstDS);

        updateProgressBar(100);
    }
    catch (const QString &msg)
    {
        qDebug()<<msg;
    }
}
void save_tile(GDALDriver& drv, dataset_t dstile, char const* const file)
{
    dataset_t dspng(make_dataset(drv.CreateCopy(file, dstile.get(), false, 0, 0, 0)));
    if(!dspng)
    {
        throw std::runtime_error("failed to save tile");
    }
}
Beispiel #5
0
// write image
bool WriteImageGDAL( char *pDstImgFileName, unsigned char *pImageData, int width, int height, int nChannels, double trans[6])
{
    GDALAllRegister();
    char *GType = NULL;
    GType = findImageTypeGDAL(pDstImgFileName);
    if (GType == NULL)
    {
        return false;
    }
    GDALDriver *pMemDriver = NULL;
    pMemDriver = GetGDALDriverManager()->GetDriverByName("MEM");
    if( pMemDriver == NULL )
    {
        return false;
    }
    GDALDataset *pMemDataSet = pMemDriver->Create("", width, height, nChannels, GDT_Byte, NULL);
    GDALRasterBand *pBand = NULL;
    int nLineCount = width * nChannels;
    unsigned char *ptr1 = (unsigned char *)pImageData;
    for (int i = 1; i <= nChannels; i++)
    {
        pBand = pMemDataSet->GetRasterBand(nChannels - i + 1);
        pBand->RasterIO(GF_Write,
                        0,
                        0,
                        width,
                        height,
                        ptr1 + i - 1 ,
                        width,
                        height,
                        GDT_Byte,
                        nChannels,
                        nLineCount);
    }
    //Write the generated data set to the target file
    GDALDriver *pDstDriver = NULL;
    pDstDriver = (GDALDriver *)GDALGetDriverByName(GType);
    if (pDstDriver == NULL)
    {
        return false;
    }
    //Write to the geographic reference information
    pMemDataSet->SetGeoTransform( trans );
    GDALDataset *poDstDS;
    poDstDS = pDstDriver->CreateCopy(pDstImgFileName, pMemDataSet, FALSE, NULL, NULL, NULL);
    if( poDstDS != NULL )
        delete poDstDS;
    GDALClose(pMemDataSet);
    return true;
}
Beispiel #6
0
SEXP
RGDAL_CopyDataset(SEXP sxpDataset, SEXP sxpDriver,
		  SEXP sxpStrict,  SEXP sxpOpts,
		  SEXP sxpFile) {

  GDALDataset *pDataset = getGDALDatasetPtr(sxpDataset);
  char **papszCreateOptions = NULL;
  int i;

  const char *filename = asString(sxpFile);

  if (filename == NULL) error("Invalid filename\n");

  GDALDriver *pDriver = getGDALDriverPtr(sxpDriver);

  installErrorHandler();
  for (i=0; i < length(sxpOpts); i++) papszCreateOptions = CSLAddString( 
    papszCreateOptions, CHAR(STRING_ELT(sxpOpts, i)) );
  uninstallErrorHandlerAndTriggerError();
#ifdef RGDALDEBUG
  installErrorHandler();
  for (i=0; i < CSLCount(papszCreateOptions); i++)
    Rprintf("option %d: %s\n", i, CSLGetField(papszCreateOptions, i));
  uninstallErrorHandlerAndTriggerError();
#endif
  installErrorHandler();
  GDALDataset *pDatasetCopy = pDriver->CreateCopy(filename,
		pDataset, asInteger(sxpStrict),
		papszCreateOptions, NULL, NULL);
  uninstallErrorHandlerAndTriggerError();

  if (pDatasetCopy == NULL) error("Dataset copy failed\n");

  installErrorHandler();
  CSLDestroy(papszCreateOptions);
  uninstallErrorHandlerAndTriggerError();

  SEXP sxpHandle = R_MakeExternalPtr((void *) pDatasetCopy,
				     mkChar("GDAL Dataset"),
				     R_NilValue);


  return(sxpHandle);

}
void CCreateMapFineTune::slotSave()
{
    IMap& map = CMapDB::self().getMap();
    GDALDataset * srcds = map.getDataset();
    if(srcds == 0)
    {
        return;
    }

    double adfGeoTransform[6];
    double u1, v1, u2, v2;
    map.dimensions(u1, v1, u2, v2);
    map.convertRad2M(u1, v1);
    map.convertRad2M(u2, v2);

    srcds->GetGeoTransform( adfGeoTransform );
    adfGeoTransform[0] = u1;
    adfGeoTransform[3] = v1;

    progressBar->show();
    GDALDriver * driver = srcds->GetDriver();

    char **papszOptions = NULL;
    papszOptions = CSLSetNameValue( papszOptions, "TILED", "YES" );
    papszOptions = CSLSetNameValue( papszOptions, "COMPRESS", "DEFLATE" );

    GDALDataset * dstds = driver->CreateCopy(labelOutfile->text().toLocal8Bit(), srcds, false, papszOptions, ProgressFunc, this);
    if(dstds)
    {
        dstds->SetGeoTransform( adfGeoTransform );
        GDALClose(dstds);
    }
    CSLDestroy( papszOptions );

    progressBar->hide();
}
bool gstIconManager::CopyIcon(const std::string& src_path,
                              const std::string& dst_path) {
  // file must not exist already
  if (khExists(dst_path)) {
    notify(NFY_WARN, "Icon \"%s\" already exists", dst_path.c_str());
    return false;
  }

  GDALDataset* srcDataset = static_cast<GDALDataset*>(
                        GDALOpen(src_path.c_str(), GA_ReadOnly));
  if (!srcDataset) {
    notify(NFY_WARN, "Unable to open icon %s", src_path.c_str());
    return false;
  }

  // determine the image type
  // is it rgb or palette_index type
  bool palette_type = false;
  if (srcDataset->GetRasterCount() == 1 &&
      srcDataset->GetRasterBand(1)->GetColorInterpretation() ==
      GCI_PaletteIndex) {
    palette_type = true;
  } else if (srcDataset->GetRasterCount() != 4) {
    notify(NFY_WARN, "%s: Image type not supported", src_path.c_str());
    return false;
  }

  GDALDataset* oldSrcDataset = 0;
  int target_size = 0;
  bool need_scaling = false;
  int srcXSize = srcDataset->GetRasterXSize();
  int srcYSize = srcDataset->GetRasterYSize();
  if ((srcXSize == 32) || (srcXSize == 64)) {
    target_size = srcXSize;
    if ((srcYSize != srcXSize) &&
        (srcYSize != srcXSize*2) &&
        (srcYSize != srcXSize*3)) {
      need_scaling = true;
    }
  } else if (srcXSize < 32) {
    target_size = 32;
    need_scaling = true;
  } else {
    target_size = 64;
    need_scaling = true;
  }

  if (need_scaling) {
    // create a temp output dataset to scale the src
    // icon to a square target_size*target_size. Later we'll make a stack.
    VRTDataset* tempDataset = new VRTDataset(target_size, target_size);
    int numBands = palette_type ? 1 : 4;
    for (int b = 1; b <= numBands; ++b) {
      tempDataset->AddBand(GDT_Byte, NULL);
      VRTSourcedRasterBand* tempBand =
        static_cast<VRTSourcedRasterBand*>(tempDataset->GetRasterBand(b));

      GDALRasterBand* srcBand = srcDataset->GetRasterBand(b);
      tempBand->AddSimpleSource(srcBand,
                                0, 0, srcXSize, srcYSize,
                                0, 0, target_size, target_size);
      if (palette_type) {
        tempBand->SetColorInterpretation(srcBand->GetColorInterpretation());
        tempBand->SetColorTable(srcBand->GetColorTable());
      }
    }
    oldSrcDataset = srcDataset;
    srcDataset = tempDataset;
    srcXSize = srcYSize = target_size;
  }
  assert(srcXSize == target_size);

  // From here on we assume that we have a square, a stack of 2, or a stack of
  // 3. It will be either 32 or 64 wide. The actual size is stored in srcXSize
  // and srcYSize
  bool simpleCopy = false;
  if (srcYSize == srcXSize * 3)
    simpleCopy = true;

  // create a virtual dataset to represent the desired output image
  VRTDataset* vds = new VRTDataset(target_size, target_size * 3);

  // copy all the bands from the source
  int numBands = palette_type ? 1 : 4;
  for (int b = 1; b <= numBands; ++b) {
    vds->AddBand(GDT_Byte, NULL);
    VRTSourcedRasterBand* vrtBand =
      static_cast<VRTSourcedRasterBand*>(vds->GetRasterBand(b));

    GDALRasterBand* srcBand = srcDataset->GetRasterBand(b);
    if (!simpleCopy) {
      // extract the normal icon (on bottom of input image)
      // and put it on the bottom of new image
      // NOTE: srcYSize calculation lets us hand single, square images
      // as well as two squares stacked on top of each other
      vrtBand->AddSimpleSource(
          srcBand,
          0, srcYSize-target_size, target_size, target_size,
          0, target_size*2, target_size, target_size);

      // extract the highlight icon (on top of input image)
      // and put it in the middle of new image
      vrtBand->AddSimpleSource(srcBand,
                               0, 0, target_size, target_size,
                               0, target_size, target_size, target_size);

      // extract the normal icon (on bottom of input image), scale it to 16x16
      // and put it on the top of the new image
      // NOTE: srcYSize calculation lets us hand single, square images
      // as well as two squares stacked on top of each other
      vrtBand->AddSimpleSource(
          srcBand,
          0, srcYSize-target_size, target_size, target_size,
          0, 0, 16, 16);
    } else {
      vrtBand->AddSimpleSource(srcBand,
                               0, 0, target_size, target_size * 3,
                               0, 0, target_size, target_size * 3);
    }
    if (palette_type) {
      vrtBand->SetColorInterpretation(srcBand->GetColorInterpretation());
      vrtBand->SetColorTable(srcBand->GetColorTable());
    }
  }

  // find output driver
  GDALDriver* pngDriver = GetGDALDriverManager()->GetDriverByName("PNG");
  if (pngDriver == NULL) {
    notify(NFY_FATAL, "Unable to find png driver!");
    return false;
  }

  // write out all bands at once
  GDALDataset* dest = pngDriver->CreateCopy(
                      dst_path.c_str(), vds, false, NULL, NULL, NULL);

  delete dest;
  delete vds;
  delete srcDataset;
  delete oldSrcDataset;

  // just in case the umask trimmed any permissions
  khChmod(dst_path, 0666);

  return true;
}
//保存离散化后的信息表到strPath下
void DataCvt_Discrete::SaveDiscreteResult()
{
	//*********************0进程将数据进行存储*****************
	if (m_rankid==0)
	{
		this->TransTable();
		string pFileExtensionName = GetFileExtensionName(m_ResultPathOrTableName);

		if ((pFileExtensionName=="shp")||strcmp(m_DatasourceConStr.c_str(),""))
		{
			/*
			if(strcmp(m_DatasourceConStr.c_str(),"")==0)
			{
			   if (IsFileExist(this->m_ResultPathOrTableName.c_str()))
			   {
				  cout<<this->m_ResultPathOrTableName<<" has existed, please enter a new name..."<<endl;
				  exit(0);
			   }
			}*/
			//将计算后的m_ppfInfoTable保存至c_AllNumsGroupByCols
			for (int i=0; i<this->m_iRecordNum; i++)
			{
				for (int j=0; j<this->m_iAttNum; j++)
				{		
					c_AllNumsGroupByCols[j][i] = this->m_ppfInfoTable[i][j];			
				}
			}  
                        pBaseOperate.CreateCopyShp(m_DatasourceConStr.c_str(),m_PathOrTableName.c_str(),m_ResultPathOrTableName.c_str());
			pBaseOperate.SaveShpFile_byCol(c_AllNumsGroupByCols,this->m_DatasourceConStr.c_str(),this->m_PathOrTableName.c_str(),this->m_ResultPathOrTableName.c_str());
		}
		if (pFileExtensionName=="tif")
		{
			//将计算后的m_ppfInfoTable保存至c_AllNumsGroupByBands
			for (int i=0; i<this->m_iRecordNum; i++)
			{
				for (int j=0; j<this->m_iAttNum; j++)
				{		
					c_AllNumsGroupByBands[j][i] = this->m_ppfInfoTable[i][j];			
				}
			}  
			GDALAllRegister();
			GDALDataset* dataset_gdal = (GDALDataset *) GDALOpen( m_PathOrTableName.c_str(), GA_ReadOnly );
			if (dataset_gdal == NULL )
			{
				cout<<"the file does not exist..."<<endl;
			}
			int width = dataset_gdal->GetRasterXSize();int height = dataset_gdal->GetRasterYSize();

			GDALDriver *driver = dataset_gdal->GetDriver();	GDALDataset *dataset_result;

			dataset_result = driver->CreateCopy(m_ResultPathOrTableName.c_str(),dataset_gdal,0,NULL,NULL,NULL);

			for(int t=0;t<c_CaculateCols.size();t++)
			{
				GDALRasterBand * poband=dataset_result->GetRasterBand(t+1);

				//把结果数据变换到0-255之间,主要是为列了显示美观,否则全是黑色
				int Value_min = c_AllNumsGroupByBands[t][0];int Value_max=c_AllNumsGroupByBands[t][0];
				for (int qq=1;qq<m_iRecordNum;qq++)
				{
					if (c_AllNumsGroupByBands[t][qq]>Value_max)
					{
						Value_max = c_AllNumsGroupByBands[t][qq];
					}
					if (c_AllNumsGroupByBands[t][qq]<Value_min)
					{
						Value_min = c_AllNumsGroupByBands[t][qq];
					}
				}
				for (int qq=0;qq<m_iRecordNum;qq++)
				{
					c_AllNumsGroupByBands[t][qq] = (c_AllNumsGroupByBands[t][qq]-Value_min)*255/(Value_max-Value_min);
				}

				poband->RasterIO(GF_Write,0,0,width,height,c_AllNumsGroupByBands[t],width,height,GDT_CInt16,0,0);
			}
		}
       if(c_IsCoutClassInfor)
       {
		cout<<"Condition attributes number:"<<this->m_iAttNum<<endl;
		cout<<"Records number:"<<this->m_iRecordNum<<endl;

		//保存断点信息
		 int n;
		 cout<<"[Cuts]"<<endl;
		 for(int j=0;j<this->m_iAttNum;j++)
		 {
			cout<<"Column: "<<c_CaculateCols[j]<<endl;
			cout<<"Num of class: "<<this->m_vecSelectedCut[j].size()+1<<endl;
			cout<<"[*,";
			n = this->m_vecSelectedCut[j].size();int i = 0;
			for(i=0;i<n;i++)
			{
				cout<<this->m_vecSelectedCut[j][i]<<") ";
				cout<<i<<endl;
				cout<<"["<<this->m_vecSelectedCut[j][i]<<",";
			}
			cout<<"*] ";
			cout<<i<<endl;
		 }
       }
	}	
}
Beispiel #10
0
GDALDataset *CALSDataset::CreateCopy( const char *pszFilename,
                                      GDALDataset *poSrcDS,
                                      int bStrict,
                                      char ** /* papszOptionsUnused */,
                                      GDALProgressFunc pfnProgress,
                                      void *pProgressData )
{
    if( poSrcDS->GetRasterCount() == 0 ||
        (bStrict && poSrcDS->GetRasterCount() != 1) )
    {
        CPLError( CE_Failure, CPLE_NotSupported,
                  "CALS driver only supports single band raster.");
        return NULL;
    }
    if( poSrcDS->GetRasterBand(1)->
            GetMetadataItem("NBITS", "IMAGE_STRUCTURE") == NULL ||
        !EQUAL(poSrcDS->GetRasterBand(1)->
                   GetMetadataItem("NBITS", "IMAGE_STRUCTURE"), "1") )
    {
        CPLError( bStrict ? CE_Failure : CE_Warning, CPLE_NotSupported,
                  "CALS driver only supports 1-bit.");
        if( bStrict )
            return NULL;
    }

    if( poSrcDS->GetRasterXSize() > 999999 ||
        poSrcDS->GetRasterYSize() > 999999 )
    {
        CPLError(
            CE_Failure, CPLE_NotSupported,
            "CALS driver only supports datasets with dimension <= 999999.");
        return NULL;
    }

    GDALDriver* poGTiffDrv =
        static_cast<GDALDriver *>(GDALGetDriverByName("GTiff"));
    if( poGTiffDrv == NULL )
    {
        CPLError( CE_Failure, CPLE_NotSupported,
                  "CALS driver needs GTiff driver." );
        return NULL;
    }

    // Write a in-memory TIFF with just the TIFF header to figure out
    // how large it will be.
    CPLString osTmpFilename(CPLSPrintf("/vsimem/cals/tmp_%p", poSrcDS));
    char** papszOptions = NULL;
    papszOptions = CSLSetNameValue(papszOptions, "COMPRESS", "CCITTFAX4");
    papszOptions = CSLSetNameValue(papszOptions, "NBITS", "1");
    papszOptions = CSLSetNameValue(papszOptions, "BLOCKYSIZE",
                                   CPLSPrintf("%d", poSrcDS->GetRasterYSize()));
    papszOptions = CSLSetNameValue(papszOptions, "SPARSE_OK", "YES");
    GDALDataset* poDS = poGTiffDrv->Create(osTmpFilename,
                                           poSrcDS->GetRasterXSize(),
                                           poSrcDS->GetRasterYSize(),
                                           1, GDT_Byte,
                                           papszOptions);
    if( poDS == NULL )
    {
        // Should not happen normally (except if CCITTFAX4 not available).
        CSLDestroy(papszOptions);
        return NULL;
    }
    const char INITIAL_PADDING[] = "12345";
     // To adjust padding.
    poDS->SetMetadataItem("TIFFTAG_DOCUMENTNAME", INITIAL_PADDING);
    GDALClose(poDS);
    VSIStatBufL sStat;
    if( VSIStatL(osTmpFilename, &sStat) != 0 )
    {
        // Shoudln't happen really. Just to make Coverity happy.
        CSLDestroy(papszOptions);
        return NULL;
    }
    int nTIFFHeaderSize = static_cast<int>(sStat.st_size);
    VSIUnlink(osTmpFilename);

    // Redo the same thing, but this time write it to the output file
    // and use a variable TIFF tag (TIFFTAG_DOCUMENTNAME) to enlarge the
    // header + the variable TIFF tag so that they are 2048 bytes large.
    char szBuffer[2048+1] = {};
    memset(szBuffer, 'X', 2048 - nTIFFHeaderSize + strlen(INITIAL_PADDING));
    szBuffer[2048 - nTIFFHeaderSize + strlen(INITIAL_PADDING)] = 0;
    GDALDataset* poTmpDS = new CALSWrapperSrcDataset(poSrcDS, szBuffer);
    poDS = poGTiffDrv->CreateCopy(pszFilename, poTmpDS, FALSE, papszOptions,
                                  pfnProgress, pProgressData );
    delete poTmpDS;
    CSLDestroy(papszOptions);
    if( poDS == NULL )
        return NULL;
    delete poDS;

    // Now replace the TIFF header by the CALS header.
    VSILFILE* fp = VSIFOpenL(pszFilename, "rb+");
    if( fp == NULL )
        return NULL; // Shoudln't happen normally.
    memset(szBuffer, ' ', 2048);
    CPLString osField;
    osField = "srcdocid: NONE";
    memcpy(szBuffer, osField, osField.size());

    osField = "dstdocid: NONE";
    memcpy(szBuffer + 128, osField, osField.size());

    osField = "txtfilid: NONE";
    memcpy(szBuffer + 128*2, osField, osField.size());

    osField = "figid: NONE";
    memcpy(szBuffer + 128*3, osField, osField.size());

    osField = "srcgph: NONE";
    memcpy(szBuffer + 128*4, osField, osField.size());

    osField = "doccls: NONE";
    memcpy(szBuffer + 128*5, osField, osField.size());

    osField = "rtype: 1";
    memcpy(szBuffer + 128*6, osField, osField.size());

    int nAngle1 = 0;
    int nAngle2 = 270;
    const char* pszPixelPath = poSrcDS->GetMetadataItem("PIXEL_PATH");
    const char* pszLineProgression = poSrcDS->GetMetadataItem("LINE_PROGRESSION");
    if( pszPixelPath && pszLineProgression )
    {
        nAngle1 = atoi(pszPixelPath);
        nAngle2 = atoi(pszLineProgression);
    }
    osField = CPLSPrintf("rorient: %03d,%03d", nAngle1, nAngle2);
    memcpy(szBuffer + 128*7, osField, osField.size());

    osField = CPLSPrintf("rpelcnt: %06d,%06d",
                         poSrcDS->GetRasterXSize(),
                         poSrcDS->GetRasterYSize());
    memcpy(szBuffer + 128*8, osField, osField.size());

    int nDensity = 200;
    const char* pszXRes = poSrcDS->GetMetadataItem("TIFFTAG_XRESOLUTION");
    const char* pszYRes = poSrcDS->GetMetadataItem("TIFFTAG_YRESOLUTION");
    const char* pszResUnit = poSrcDS->GetMetadataItem("TIFFTAG_RESOLUTIONUNIT");
    if( pszXRes && pszYRes && pszResUnit && EQUAL(pszXRes, pszYRes) &&
        atoi(pszResUnit) == 2 )
    {
        nDensity = atoi(pszXRes);
        if( nDensity < 1 || nDensity > 9999 )
            nDensity = 200;
    }
    osField = CPLSPrintf("rdensty: %04d", nDensity);
    memcpy(szBuffer + 128*9, osField, osField.size());

    osField = "notes: NONE";
    memcpy(szBuffer + 128*10, osField, osField.size());
    VSIFWriteL(szBuffer, 1, 2048, fp);
    VSIFCloseL(fp);

    GDALOpenInfo oOpenInfo(pszFilename, GA_ReadOnly, NULL);
    return Open(&oOpenInfo);
}