Image array memory layout¶
The memory layout used to store the image array in the Image container (struct) is described with a 4 chars code word "T|B R|C B|P|L a|A", where:
- T(op) means the array is arranged Top-Down (and B Bottom-Up)
- R(ow) means arrays are in row-major order (C, column-major)
- B(and) means Band interleaving, P(ixel) interleaving, L(ine) interleaving
- a|A is not used yet but reserved for a future case where an image may arrive to GMT as a RGBA array. Currently the A(lpha) array is stored separately in the Image container.
The memory layout is stored in the header member I→header→mem_layout
When images are read via gmt_gdalread, GMT→current.gdal_read_in.O.mem_layout is consulted and the image array is stored according that ordering. Image's struct (I→header→mem_layout is updated here too). So, a consequence of this is that GMT→current.gdal_read_in.O.mem_layout cannot be empty at the time of a gmt_gdalread() call.
PostScript images are created as BRPa and this affects the grdimage -A option, which saves the image on disk through a call to gmt_gdalwrite(). Since this option is currently blocked to external API calls, the mem_layout is hardwired in grdimage (sessions current mem_layout is not affected by this operation).
psconvert can also create Image containers. It currently does so via two different paths:
- In pipe_ghost(), where an in-memory PS struct holds the PS image. This PS is rasterized via pipes and popens to call the ghostscript engine directly without writing any temporary file on disk. Unfortunately this path currently works only on Windows.
- Use the pscovert mechanism to convert the tmp PS file in disk into a png image and read it back via gmt_gdalread().
Now the things that we must take care. Different external interfaces need different memory layouts. For example Matlab wants TCBa (Band interleaved but with column major storage), Julia has several imaging tools. For example Images.jl wants TCPa, but
PyPLot needs TRBa (I think) and other back-ends may need other orderings. The exact same situation is, I think, expect-able from within the python wrap.
We have an helper function that let us change the memory layout in the middle of the game.
GMT_Set_Default (API, "API_IMAGE_LAYOUT", "TCBa");
Not good 1: GMT→current.gdal_read_in.O.mem_layout is born empty (should be GMT_IMAGE_LAYOUT). The sessions should be initialized to GMT_IMAGE_LAYOUT.
Not good 2: The name it self. It started as a GDAL related option (hence its name) but it's more general now.
Question: What should be the the default GMT_IMAGE_LAYOUT? (I'm lost by now)
Remainder: Grid containers use the memory layout concept too (though a bit different than the image's one)