Thankyou to @joa-quim I can read Geotiff files using GMT.jl
When I run image = gmtread(“world.tif”,img=true)
the image is of type GMT.GMTimage
GMT.imshow(image) produces a Postscript file
Rather stupidly I would like to use ImageView to display the image quickly. https://github.com/JuliaImages/ImageView.jl
ImageView.imshow() does not have a method for the GMTImage type
Can we work on a conversion to the array types which Image and ImageView like to work with?
I am probably missing the fact that the GMTImage format has lots of metadata about the coordinates etc.
Yes, being able to display with ImageView would be very nice. I even started to look at it once on how to add to Images (condition to display with ImageView) but I think I didn’t really understand what I had to do.
If you look at this line of the source code it even anticipates the memory layout that would be needed to integrate with Images. If someone with more knowledge of Images wanted to give an help, it would be fantastic.
It produces lots of things but in terms of mapping, basically yes. One of it’s modules (grdimage) is able to write raster files (many of the formats supported by GDAL) but without any vector content. However, it has a module that converts (via ghostscript) the ps into may other formats.
I know this example is not using GMT but ArchGDAL to read the GeoTIFF, but perhaps a similar method can be used for GMT:
# add ArchGDAL#idataset
using ArchGDAL
using ImageCore
using ImageView
using ColorTypes
# read the file into a dataset
filename = joinpath(dirname(pathof(ArchGDAL)), "../test/pyrasterio/RGB.byte.tif")
dataset = ArchGDAL.read(filename)
# read all of the 3 bands as UInt8 2D arrays and view them together as colors
# see also https://juliaimages.org/latest/conversions_views.html
img = permuteddimsview(colorview(RGB,
normedview(ArchGDAL.read(dataset, 1)),
normedview(ArchGDAL.read(dataset, 2)),
normedview(ArchGDAL.read(dataset, 3))
), (2,1))
imshow(img)
julia> filename = joinpath(dirname(pathof(ArchGDAL)), "../test/pyrasterio/RGB.byte.tif")
"C:\\Users\\j\\.julia\\packages\\ArchGDAL\\tUwz2\\src\\../test/pyrasterio/RGB.byte.tif"
julia> dataset = ArchGDAL.read(filename)
ERROR: MethodError: no method matching read(::String)
You may have intended to import Base.read
Closest candidates are:
read(::ArchGDAL.Dataset) at C:\Users\j\.julia\packages\ArchGDAL\tUwz2\src\raster\rasterio.jl:308
read(::ArchGDAL.Dataset, ::Array{Int32,1}) at C:\Users\j\.julia\packages\ArchGDAL\tUwz2\src\raster\rasterio.jl:301
read(::ArchGDAL.RasterBand) at C:\Users\j\.julia\packages\ArchGDAL\tUwz2\src\raster\rasterio.jl:195
That’s right, but on the other hand the normed part makes think on a true normalization, which would imply the creation of a new array … but it doesn’t although it shows up at such in the REPL. Find this confusing to grok.
white == 255 #= 8-bit camera =# == 65535 #= 16-bit camera =# == 4095 #= 12-bit camera =# == 1.0 #= floating-point representation =#
While many people who work with images have gotten used to thinking this way, it’s fair to say it’s rather bad mathematics: I’m not aware of any other domain of computation where the above equalities hold (255 == 1.0, seriously?). It also violates our general expectation that “meaning” is independent of “representation”: just do convert(Float64, x) and suddenly you’re very confused. Particularly for cameras with 10-, 12-, and 14-bit depths, it’s very hard to automatically detect pixel-saturation because the maximum output is less than typemax(UInt16), unless you always carry around an extra bit of metadata about the camera.
We’ve gone to the trouble to fix this by introducing a set of numbers, the normed numbers, that allow you to represent 1.0 with an 8-bit number, or a 16-bit number, or the first 10 bits of a 16-bit number, etc. These numbers are just reinterpretations of UInt8, UInt16, etc, but they provide consistent rules of arithmetic in which they behave like their floating-point cousins. Consequently, they fix image mathematics, and whitealways means 1.0 no matter with what precision you choose to represent it.
ReinterpretArray and MappedArrays are magical. In Julia we can:
change the values or apparent element type of an array
choose a subset of an array
reshape an array
permute the dimensions of an array
change the “location” of an array by adjusting the indices to access its elements
all without taking a copy. This makes Julia quite amazing for big data, where raw arrays are too big to hold in memory yet you can do some remarkable transformations efficiently without ever creating a new disk file or running out of memory.
And the magician works for free?
Never mind this is all good for me and it means that images read with GMT can be displayed/manipulated directly without further work.
This is exactly the same amount of work that a fully-optimized “eager” implementation of the cube-root would require. There is literally zero overhead (other than being somewhat harder on the poor compiler). Now, there can be advantages and disadvantages to lazy computation, but Julia’s implementations are magical in the sense that they usually have no cost for the abstraction itself.