Despite the native projection of the data and the specified projection of this TIFF being 4326, when loading the exported TIFF in QGIS to view it, the image doesn’t appear to be spatially referenced.
Any insight as to what I am doing wrong or how to ensure the the export TIFF is georeferenced?
I have a sneaking suspicion that the exported TIFF is not a GeoTIFF, and that there are some additional steps necessary to append the projection data, but I haven’t been successful in finding a way to do this.
Here is an Observable notebook where I am playing around with different ways to load and and render GeoTIFF… with varying degrees of success. I welcome all types of feedback and guidance.
My goal is to obtain the highest resolution version of the raster data so that I can transform it into vector data for d3 maps.
Otherwise, ESRI Leaflet will render the layer using just the defaults:
Thanks @andreasplesch ! I’ll have a go at this. It’s weird, because I can plug the MapServer URL into QGIS’ ArcGIS MapServer connector and the resulting (png32) image is spatially projected. The response from the ArcGIS server wraps a reference to the image in a JSON object that carries its geo-referencing information, but since this information isn’t written into the exported TIFF, I’m still trying to figure out how to re-work it so that I can use it properly. I’ve also tried playing around with the SVG exports and using the projection information to add it into a D3-generated map. Just can’t seem to get there!
It sounds like the ArcGIS map server just does not generate GeoTiff. Esri-Leaflet probably uses additional metadata from the mapserver to georeference the image.
looks like it is using the bounds from the request to georeference the returned image.
geoblaze parse uses georaster which lets you specify georeference information for a png:
Depending on what you want to do, that may be enough and you would not need qgis. geotiffjs appears to have a writearraybuffer function which essentially lets you generate a geotiff from a georaster:
Thanks for helping me work through this. There’s definitely a solution in here! I’ve learned from all of this that I don’t necessarily need GeoTIFF to achieve a spatially-referenced image, and that the ArcGIS REST server isn’t providing me a GeoTIFF–just a regular TIFF. Since we already know all the spatial reference information, and since one of the export options allowed by the server it SVG, it likely makes the most sense to try to just map the SVG image into our desired d3 map. I found some pointers on similar processes on Stack Overflow that maybe will help (just dropping the link here not to lose it). While I can kinda conceptually imagine how this can work, I still need to work through the materials @andreasplesch shared and also to play around more. Hopefully I figure something out over the next couple of weeks
… More soon Dropping this in as inspiration to pick up the problem again later and to say that I keep plugging away at this.
I concur, these are the important takeaways. Corner coordinates in “bounds” and fully defined projections suffice to georeference an image. Geotiffs just embed these data points directly in the image (header tags).
After looking more at georaster, it may be that PNG/JPG support is still pending. In that case, the qgis with world file (.pgw,jgw) approach may be easiest.
The returned SVG would still embed a raster image. Not sure if D3 can properly reproject SVG raster images (perhaps filled rectangles), as most examples deal with vector graphics. It is not quite enough to reproject just the corners and distort the embedded image accordingly. While a good approximation for small areas (up to perhaps one degree), each pixel should be reprojected individually (warping in QGIS).
Thanks Andreas! I read the world file documentation. I have not yet tried manually running these calculations, as I was hoping that I could figure out how to ask QGIS to run the export. This step of manual intervention isn’t ideal, but I’d happily enjoy a projected raster of any kind that to help me get started All my attempts to export from QGIS seem to fail:
Since that first notebook was a bit off conceptually, I tried narrowing down the problem here (though from your reply above I might be similarly misguided on my new SVG-focused attempt):
I’ll keep trying! Thank you for sharing these insights and avenues for learning!
Constructing the world file boils down to these six lines in a text file:
pixel size along x, in degrees
0
0
negative pixel size along y, in degrees x-coordinate of the center of the original image’s upper left pixel, in degrees y-coordinate of the center of the original image’s upper left pixel, in degrees
for Spatial Reference: 4326 (lat/long), since the skew is usually 0.
I found that
struggles with a similar issue.
Alternatively, to export the mapserver layer from QGIS, the easiest option would be the Project - Import/Export - Export Map to Image function, essentially a georeferenced screenshot. You can define the extent and resolution which you could base on the original source.
${(xmax - xmin)/(4096 - 1)} // pixel size along x, in degrees
0
0
${(ymax - ymin)/(4096 - 1)}// pixel size along y, in degrees
${xmin} // x-coordinate of the center of the original image’s upper left pixel, in degrees
${ymax} // y-coordinate of the center of the original image’s upper left pixel, in degrees
Clearly, something is off. x seems alright but y is flipped and the pixel size too small. Make sure not to use the input bbox but the returned extent from the json.
Ah, I noticed from the worldfile doc. and I remembered that the y pixel size should be negative. That explains the flipping at least.
I also noticed that using the full extent for bbox does not quite return the full resolution of the source data (which I do not think is available). It would be necessary to request smaller maps at 4k resolution and then stitch those together. I think this size is getting to full resolution:
After loading the raster into QGIS, you will need to assign manually a projection since qgis cannot know what it should be: Set CRS - Set Layer CRS (use 4326).
Looking at my example with the full extent, it appears that requesting a square (4kx4k) image results in an extent which is also square in degrees (13.43 x 13.43). So the y pixel size should be the same or very similar to the x pixel size. In your case, the y pixel size would be about 3x which would work to stretch the squeezed map to about the right size, judging from the screenshot.
For completeness, searching for ‘reprojection’ brings up quite a few notebooks with raster reprojections, for example Raster reprojection / Jake Low / Observable .
Perhaps one could use d3 to associate a 4326 projection with the image, probably with custom offsets and scale, now that these are known. This would effectively work to georegister, eg. retrieve geo-coordinates from image/canvas coordinates. Then one could use image processing such as contouring to retrieve georeferenced features, just like one would in gis.