There is no need to parse the bytes, measuring the image works fine.
The issue (apart from measuring the image and not the filename), is that the context needs to be placed outside of the grid – otherwise, the context {} creates an implicit grid cell which contains the grid.cell(colspan: 2, ...), effectively rendering the colspan argument useless.
When measuring, we set a width to measure against (fixing how much “100%” are) – and we do not set a height on the image elements, as this makes measuring useless (if we set width and height on the image, we set its aspect ratio that way)
#let portrait_landscape(content) = {
// we set an explicit width to make 100% width = 100pt
let dimensions = measure(content, width: 100pt)
if dimensions.width > dimensions.height {
grid.cell(colspan: 2, content)
} else {
grid.cell(colspan: 1, content)
}
}
#set image(fit: "contain", width: 100%) // you must not set the height here, as this will make all images to have the same aspect ratio, as it is measured _after_ it is fit to the set width/height
#context grid(
columns: 3,
rows: 200pt,
gutter: 32pt,
// align: top,
fill: red, // to show cell sizes
portrait_landscape(image("figure.png",)),
portrait_landscape(image("figure.png",)),
portrait_landscape(image("figure.png",)),
portrait_landscape(image("flag-turtle.jpeg",)),
portrait_landscape(image("figure.png",)),
portrait_landscape(image("figure.png",)),
portrait_landscape(image("Screenshot from 2021-02-22 11-12-17.png")),
)
