AcademySoftwareFoundation / OpenImageIO

Reading, writing, and processing images in a wide variety of file formats, using a format-agnostic API, aimed at VFX applications.
https://openimageio.readthedocs.org
Apache License 2.0
1.95k stars 578 forks source link

provide Orientation value for RAW images #4152

Open kfjahnke opened 6 months ago

kfjahnke commented 6 months ago

As requested, this is a split-off from #4123. As posted there, I think that OIIO should handle image orientation like this:

This should apply to RAW images as well. So for raw images, the default could remain as it is (passing raw:user_flip=-1 to the plugin). If raw::user_flip is passed zero (no autorotation), the data should come in as recorded by the sensor, and the OIIO 'Orientation' property should be set to the corresponding EXIF value - I think it would be wise to adhere to this as the uniform standard, rather than using a second set of numerical values just for RAW files. If the user passes any other value for raw:user_flip, the data would be pre-rotated by the plugin, and the OIIO 'Orientation' property should be set to 1, to reflect that the data - as imported - have been rotated under the user's command - if the user passes in an inappropriate raw:user_flip that's their mistake (or may be deliberate). If finding out the camera orientation is relevant, users can pass raw:user_flip=0 and glean the orientation from the 'Orientation' property, which in turn should be available via the raw:flip value with subsequent translation from libraw numerical codes to EXIF standard. Then they can decide how they want to have the file read. It might be a good idea to add a global OIIO flag to deliberately switch autorotation off for all plugins which support it. This would save users the hassle of coding per-format parameterization if they need to handle orientation themselves.

kfjahnke commented 6 months ago

Looks like this has stalled, so I'll try and get it back on the agenda. #4123 and #4142 have dealt with the issue for HEIF files, but it shouldn't stop there. @lgritz, we have discussed that the policy should change re. autorotation, so the other plugins should follow suit, and this is true for RAW input as well. So far, the behaviour is steered with raw:user_flip - if it's passed zero, the image is not autorotated and the Orientation tag is set, and the default is currently to pass raw:user_flip -1 which results in autorotation by the plugin. But I think that there is no code yet to make the plugin respond to oiio:reorient. Since the raw:user_flip argument is already there, adding this should not be too hard - all that would be needed is code to set raw:user_flip to zero if oiio:reorient is zero - assuming that oiio: arguments should override raw: arguments - should they?

But it does not stop here. The next plugin which would really benefit from orientation handling is input from videos. There, the Orientation tag seems misleading - at least with the videos I've looked at: if the video is in portrait format (like many smartphone videos are nowadays), OIIO returns Orientation 1 and a landscape aspect ratio. This is irritating: the thumbnail in my file manager and exiftool both indicate the video is in portrait format, ffplay and vlc show it in portrait, but if I open it in lux with OIIO, I have to manually rotate it to be able to look at it properly, and in iv I haven't found a way to get a portrait display. So here I'd really appreciate if the plugin would either autorotate by default or provide a correct Orientation if it doesn't.

lgritz commented 6 months ago

Agree on all your points. I'm tagging this as a "help wanted" issue and for anybody reading who knows our secret codeword: 🎣 Mackerel!

kfjahnke commented 6 months ago

for anybody reading who knows our secret codeword: 🎣 Mackerel!

Would you like to share what your secret codeword means?

assuming that oiio: arguments should override raw: arguments - should they?

I suppose this is a policy issue. What's the policy if there is a global oiio: argument and a plugin argument which affect the same feature? Should the plugin still be allowed to accept it's own brand of argument or should it give up on it and react to the oiio: argument instead? The point in case here being oiio:reorient and raw:user_flip: the latter would seem largely redundant if the plugin were to react to oiio:reorient, but beyond not touching or autorotating the image it has the extra feature to orient to a given orientation value whereas oiio:reorient is a boolean.

lgritz commented 6 months ago

for anybody reading who knows our secret codeword: 🎣 Mackerel!

Would you like to share what your secret codeword means?

Yes! It means: "here's a task that's would be ideal for somebody who has been looking for a way to get more involved with the project." It also means "this is something that somebody other than Larry can do, so it's really best for the project if somebody other than Larry does it."

We wanted a catchy, quick way to say that, meant to invoke the old saying, "give a person a fish and you feed them for a day, but teach them to fish and you feed them for a lifetime."

lgritz commented 6 months ago

I suppose this is a policy issue. What's the policy if there is a global oiio: argument and a plugin argument which affect the same feature? Should the plugin still be allowed to accept it's own brand of argument or should it give up on it and react to the oiio: argument instead? The point in case here being oiio:reorient and raw:user_flip: the latter would seem largely redundant if the plugin were to react to oiio:reorient, but beyond not touching or autorotating the image it has the extra feature to orient to a given orientation value whereas oiio:reorient is a boolean.

I think raw:reorient made sense if it was just meant for raw to control things in a very specific way for that reader. It should be changed in documentation to oiio:reorient if we expect a command that works the same way on many/all file types. We can still quietly accept raw:reorient as a synonym for compatibility.

ssh4net commented 5 months ago

This should apply to RAW images as well. So for raw images, the default could remain as it is (passing raw:user_flip=-1 to the plugin). If raw::user_flip is passed zero (no autorotation), the data should come in as recorded by the sensor, and the OIIO 'Orientation' property should be set to the corresponding EXIF value - I think it would be wise to adhere to this as the uniform standard, rather than using a second set of numerical values just for RAW files.

in Libraw, orientation works this way: -1 - rotation took from EXIF orientation tag. 0-8 - EXIF orientation tag replaced with user defined value.

0 == 0-rotation (usually horizontal orientation for a camera with a viewfinder on top).

If I remember right, OIIO in the libraw plugin inherits this behavior. But forcing Libraw plugin to use a user orientation required preload raw file header.