I have a raster derived from a .png which has been drawn into a geodatabase. I also have the spatial reference and extent coordinates where I want to georeference the raster.
Is there a way to accomplish it with ArcObjects (10.4.1 SDK) ?
Here is the code I've got so far:
IEnvelope envelope = ArcMap.Document.ActiveView.Extent;
byte[] image = await GetImageAsync(endpointUri, accessToken);
MemoryStream ms = new MemoryStream(image);
Image i = Image.FromStream(ms);
i.Save("demo.png");
IRasterLayer rasterLayer = new RasterLayerClass();
rasterLayer.CreateFromFilePath("demo.png");
// Need to georeference rasterLayer
foreach (ILayer layer in layers)
{
// Get a random feature spatial reference
rasterLayer.SpatialReference = randomFeature.Shape.SpatialReference;
break;
}
IDisplay display = ArcMap.Document.ActiveView.ScreenDisplay;
(ArcMap.Document as ESRI.ArcGIS.ArcMapUI.IMxDocument).FocusMap.AddLayer(rasterLayer);
rasterLayer.Draw(ESRI.ArcGIS.esriSystem.esriDrawPhase.esriDPGeography, display, null);
ArcMap.Document.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewGeography, null, null);
UPDATE:
Obtaining this after adding world file (.pnw) creation, as @MichaelStimson suggested. Way closer, but still doesn't draw as expected. Do I have it right?
IEnvelope envelope = ArcMap.Document.ActiveView.Extent;
byte[] image = await GetImageAsync(endpointUri, accessToken);
MemoryStream ms = new MemoryStream(image);
Image i = Image.FromStream(ms);
i.Save("demo.png");
// Generate demo.pnw file to georeference .png
if (!File.Exists("demo.pnw"))
{
File.Create("demo.pnw").Dispose();
StreamWriter streamWriter = File.AppendText("demo.pnw");
double A = envelope.Width / i.Height;
double D = 0d;
double B = 0d;
double E = -(envelope.Height / i.Width);
double C = envelope.UpperLeft.X;
double F = envelope.UpperLeft.Y;
CultureInfo cultureInfo = new CultureInfo("en-US");
streamWriter.Write(string.Format(cultureInfo, "{0}\n{1}\n{2}\n{3}\n{4}\n{5}", A, D, B, E, C, F));
streamWriter.Dispose();
}
IRasterLayer rasterLayer = new RasterLayerClass();
rasterLayer.CreateFromFilePath("demo.png");
IQueryFilter queryFilterClass = new QueryFilterClass();
foreach (ILayer layer in layers)
{
if (!layer.Valid) continue;
rasterLayer.SpatialReference = ((IGeoDataset)layer).SpatialReference;
break;
}
IDisplay display = ArcMap.Document.ActiveView.ScreenDisplay;
(ArcMap.Document as ESRI.ArcGIS.ArcMapUI.IMxDocument).FocusMap.AddLayer(rasterLayer);
rasterLayer.Draw(ESRI.ArcGIS.esriSystem.esriDrawPhase.esriDPGeography, display, null);
ArcMap.Document.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewGeography, null, null);
UPDATE 2:
After correcting the extension to .pgw and tweaking a bit with the x and y scale it does seem that it is scaling properly but it is not translating where it should (it doesn't even overlap with the envelope), even though I'm just setting in the file the same envelope coordinates used to originally request the image.
Here's the code so far:
IEnvelope envelope = ArcMap.Document.ActiveView.Extent;
byte[] image = await GetImageAsync(endpointUri, accessToken);
MemoryStream ms = new MemoryStream(image);
Image i = Image.FromStream(ms);
i.Save("demo.png");
// Generate demo.pgw file to georeference .png
if (!File.Exists("demo.pgw"))
{
File.Create("demo.pgw").Dispose();
StreamWriter streamWriter = File.AppendText("demo.pgw");
double A = envelope.Width / i.Width;
const double D = 0d;
const double B = 0d;
double E = -(envelope.Height / i.Height);
double C = envelope.UpperLeft.X;
double F = envelope.UpperLeft.Y;
CultureInfo cultureInfo = new CultureInfo("en-US");
streamWriter.Write(string.Format(cultureInfo, "{0}\n{1}\n{2}\n{3}\n{4}\n{5}", A, D, B, E, C, F));
streamWriter.Dispose();
}
IRasterLayer rasterLayer = new RasterLayerClass();
rasterLayer.CreateFromFilePath("demo.png");
rasterLayer.SpatialReference = envelope.SpatialReference;
(ArcMap.Document as ESRI.ArcGIS.ArcMapUI.IMxDocument).FocusMap.AddLayer(rasterLayer);
IDisplay display = ArcMap.Document.ActiveView.ScreenDisplay;
rasterLayer.Draw(ESRI.ArcGIS.esriSystem.esriDrawPhase.esriDPGeography, display, null);
ArcMap.Document.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewGeography, null, null);