Writing a Raster to a Personal Geodatabase

Discussion created by rlcave on Aug 10, 2012
Latest reply on Feb 7, 2014 by erikadade

I am writing code that will export elevation data to a Geodatabase raster.  When I test the program writing output to a File Geodatabase, the output raster is correct.  Using the same test case, and writing to a Personal Geodatabase, the output raster contains only 'no data' values.  I haven't been able to find anything in the documentation that there are differences that I need to be aware of when writing to File vs. Personal Geodatabases.  Does anyone know of anything? 

I am testing using ArcGIS 10.1, but haven't tried this on other versions.

Here is the code I am using:

IRasterWorkspaceExPtr rasterWs;  // Already opened for file or personal geodatabase

IRasterStorageDef2Ptr rasterStorageDef(CLSID_RasterStorageDef);
hr = rasterStorageDef->put_Tiled(VARIANT_FALSE);
IPntPtr cellSize(CLSID_Pnt);
hr = cellSize->SetCoords(aXSpacing, aYSpacing); // spacing values are passed in
hr = rasterStorageDef->putref_CellSize(cellSize);

IRasterDefPtr rasterDef(CLSID_RasterDef);
hr = rasterDef->putref_SpatialReference(aSpatialRef); // spatial ref is passed in and defined correctly

IRasterDataset3Ptr rasterDs;
hr = rasterWs->CreateRasterDataset("temp", 1, PT_FLOAT, rasterStorageDef, ("sde.DEFAULT"), rasterDef, NULL, &rasterDs);

IRasterPtr raster;
hr = rasterDs->CreateFullRaster(&raster);

IRasterPropsPtr rasterProps(raster);
hr = rasterProps->put_Height(aPixHeight); // Height and width are passed in
hr = rasterProps->put_Width(aPixWidth);

CComVariant varNoData;
hr = rasterProps->get_NoDataValue(&varNoData);
float defaultNoData = -FLT_MAX;
CComVariant varDefaultNoData(defaultNoData);    
hr = rasterProps->put_NoDataValue(varDefaultNoData);                

esriGeometry::IEnvelopePtr envelope(esriGeometry::CLSID_Envelope);
double minX, maxX, minY, maxY; // Values passed in
hr = envelope->PutCoords(minX, minY, maxX, maxY);
hr = rasterProps->put_Extent(envelope);

IPntPtr blockSize(CLSID_Pnt);
hr = blockSize->SetCoords((double)aPixWidth, (double)aPixHeight);
IPixelBlockPtr pixelBlock;
hr = raster->CreatePixelBlock(blockSize, &pixelBlock);

CComVariant varPixelArray;
hr = pixelBlock->get_SafeArray(0, &varPixelArray);
COleSafeArray pixels(varPixelArray);
long index[2];

// Get the elevation values
for(index[1] = 0; index[1] < aPixHeight; index[1]++)
    // Write out each elevation in the row
    float theElev;

    for(index[0] = 0; index[0] < aPixWidth; index[0]++)
        if ( elevation value at pixel location is valid )
            pixels.PutElement(index, &theElev);
            pixels.PutElement(index, &noData);

hr = pixelBlock->put_SafeArray(0, pixels.Detach());

IRasterEditPtr rasterEdit(raster);
IPntPtr tlc(CLSID_Pnt);
hr = tlc->SetCoords(0.0, 0.0);
hr = rasterEdit->Write(tlc, pixelBlock);
hr = rasterEdit->Refresh();

ISaveAsPtr saveAs(raster);
IDatasetPtr newDs;
IWorkspacePtr ws(rasterWs);
hr = saveAs->SaveAs("table", ws, CComBSTR("GDB"), &newDs);

Does anyone see anything that looks wrong with respect to how ArcObjects works with File vs. Personal Geodatabases?

Another question related to writing a raster to a geodatabase:  I am having trouble getting the elevation values stored in the geodatabase.  The solution I came up with is to create a temporary raster dataset, use it to create a raster and write the elevation values to the raster, then use ISaveAs to write the raster to the geodatabase. (This is illustrated in the snippet above.) When the process is done, the code deletes the temporary raster dataset. 

Is there a better way to do this?