Hi Anwar,
The latest Gdal v3.9.1 is now available in ThinkGeo v14.2.
I found the gdal feature layer successfully gets the bounding box / reads the features, but it has some issues reading the native styles and render it properly, we’re still working on it. Here we created a layer for you which convert part of the GeoPdf to an png and display it, have a try and see if it works for you.
GeoImage bitmap2 = new GeoImage(1024, 512);
var layer2 = new GeoPdfRasterLayer("101018 MAC Moorefields road S T1 THP A3 Landscape.pdf");
layer2.Open();
RectangleShape extent = MapUtil.GetDrawingExtent(layer2.GetBoundingBox(), bitmap2.Width, bitmap2.Height);
GeoCanvas canvas2 = GeoCanvas.CreateDefaultGeoCanvas();
canvas2.BeginDrawing(bitmap2, extent, GeographyUnit.Meter);
layer2.Draw(canvas2, new Collection<SimpleCandidate>());
canvas2.EndDrawing();
bitmap2.Save(Path.Combine($"{_resultFolder}", "GeoPdfTest2_GeoPdfRasterLayer.png"));
class GeoPdfRasterSource : GdalRasterSource
{
private Dataset _dataset;
private string _geoPdfPath;
private RectangleShape? _boundingBox;
public GeoPdfRasterSource(string geoPdfPath)
{
_geoPdfPath = geoPdfPath;
}
protected override void OpenCore()
{
// Register GDAL drivers
OSGeo.GDAL.Gdal.AllRegister();
// Open the GeoPDF
_dataset = OSGeo.GDAL.Gdal.Open(_geoPdfPath, Access.GA_ReadOnly);
if (_dataset == null)
{
throw new Exception("Unable to open GeoPDF file.");
}
}
protected override RectangleShape GetBoundingBoxCore()
{
if (_boundingBox != null) return _boundingBox;
GdalFeatureSource gdalFeatureSource = new GdalFeatureSource(_geoPdfPath);
gdalFeatureSource.Open();
_boundingBox = gdalFeatureSource.GetBoundingBox();
gdalFeatureSource.Close();
return _boundingBox;
}
protected override GeoImage GetImageCore(RectangleShape worldExtent, int canvasWidth, int canvasHeight)
{
// Get the bounding box of the dataset
double[] geoTransform = new double[6];
_dataset.GetGeoTransform(geoTransform);
var extent = worldExtent;
// Get the pixel extent corresponding to the requested geographic extent
var (xOff, yOff, xSize, ySize) = GetPixelExtent(extent, geoTransform, _dataset.RasterXSize, _dataset.RasterYSize);
// Create a memory driver to write PNG to memory
Driver memDriver = OSGeo.GDAL.Gdal.GetDriverByName("MEM");
Dataset memDataset = memDriver.Create("", xSize, ySize, _dataset.RasterCount, _dataset.GetRasterBand(1).DataType, null);
// Read raster data into memory dataset
for (int i = 1; i <= _dataset.RasterCount; i++)
{
Band srcBand = _dataset.GetRasterBand(i);
Band memBand = memDataset.GetRasterBand(i);
// Create a buffer to hold the raster data for this band
int bufferSize = xSize * ySize;
byte[] buffer = new byte[bufferSize];
// Read the raster data from the source band into the buffer
srcBand.ReadRaster(xOff, yOff, xSize, ySize, buffer, xSize, ySize, 0, 0);
// Write the buffer to the memory band
memBand.WriteRaster(0, 0, xSize, ySize, buffer, xSize, ySize, 0, 0);
}
// Convert the memory dataset to PNG
byte[] pngImage = ConvertDatasetToPNG(memDataset);
var geoImage = new GeoImage(pngImage);
var newGeoImage = geoImage.Scale(canvasWidth, canvasHeight);
return newGeoImage;
}
private (int xOff, int yOff, int xSize, int ySize) GetPixelExtent(RectangleShape extent, double[] geoTransform, int rasterWidth, int rasterHeight)
{
// Convert geographic coordinates to pixel coordinates
int xOff = (int)((extent.MinX - geoTransform[0]) / geoTransform[1]);
int yOff = (int)((geoTransform[3] - extent.MaxY) / Math.Abs(geoTransform[5]));
int xSize = (int)((extent.MaxX - extent.MinX) / geoTransform[1]);
int ySize = (int)((extent.MaxY - extent.MinY) / Math.Abs(geoTransform[5]));
// Clamp xOff, yOff to be within valid raster bounds
xOff = Math.Max(0, xOff);
yOff = Math.Max(0, yOff);
// Adjust xSize and ySize if the requested size goes out of bounds
if (xOff + xSize > rasterWidth)
{
xSize = rasterWidth - xOff;
}
if (yOff + ySize > rasterHeight)
{
ySize = rasterHeight - yOff;
}
return (xOff, yOff, xSize, ySize);
}
// Converts a GDAL dataset to a PNG image in byte array format
private byte[] ConvertDatasetToPNG(Dataset dataset)
{
// Create a PNG driver
Driver pngDriver = OSGeo.GDAL.Gdal.GetDriverByName("PNG");
if (pngDriver == null)
{
throw new Exception("PNG driver not available.");
}
// Create a temporary file to store the PNG
string tempPngPath = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName() + ".png");
// Create the PNG file using the dataset
Dataset pngDataset = pngDriver.CreateCopy(tempPngPath, dataset, 0, null, null, null);
// Properly dispose of the created PNG dataset
pngDataset.FlushCache();
pngDataset.Dispose(); // This is crucial to release the file lock
// Read the PNG file into a byte array
byte[] pngImage = File.ReadAllBytes(tempPngPath);
// Clean up the temporary file
File.Delete(tempPngPath);
return pngImage;
}
}
class GeoPdfRasterLayer : GdalRasterLayer
{
public GeoPdfRasterLayer(string geoPdfPath)
{
this.ImageSource = new GeoPdfRasterSource(geoPdfPath);
}
}
Thanks,
Ben