Exif.Image.Orientation issue

Added by Goran Nagy about 1 month ago

I am trying to change orientation of a file with exiv2.

I use this command:

exiv2 mo -M "set Exif.Image.Orientation 8" original.jpg

After this command finishes, I check the file and indeed one byte in the image is changed from 1 to 8, as I would expect.

However quite a few viewers/editors (XnView, Corel Photo Paint, Paint (from Windows 10)) do not recognize this orientation. Other applications (Affinity Photo, Fast Stone image viewer) do properly rotate image.

If I use exiftool to rotate image there is another byte that is changed from 0x09 to 0x03. I don't know what that byte means and how to change it with exiv2 too.

Can someone shed some light on the issue.

Attached original image, image changed with exiv2 and image changed with exiftool.

original.jpg (1.87 MB)

exiv2.jpg (1.87 MB)

exiftool.jpg (1.87 MB)


Replies (13)

RE: Exif.Image.Orientation issue - Added by Goran Nagy about 1 month ago

OK, so I checked EXIF file format. It seems that this image has data format of the Exif.Image.Orientation set to 0x09 (signed long) which is incorrect. Exiftool fixes this and sets it to 0x03 (unsigned short) while exiv2 leaves it as it is (at least with the command I used in my first post). So, now the question is whether I can fix data format from 0x09 to 0x03. I am more interested in doing this programmatically, though any help how to do it via command line tool would also be appreciated.

RE: Exif.Image.Orientation issue - Added by Jim Easterbrook about 1 month ago

You can clear the value with exiv2 mo -M "del Exif.Image.Orientation" original.jpg, then set it as you did before. It will then have the correct data format.

RE: Exif.Image.Orientation issue - Added by Goran Nagy about 1 month ago

Thanks. That's one way to do it. I found another one (explicitly setting data format):

exiv2 -k -M"set Exif.Image.Orientation Short 8" original.jpg

I'm still trying to find how to do it programmatically, which is obviously possible, since evix2 command line tool does it.

RE: Exif.Image.Orientation issue - Added by Jim Easterbrook about 1 month ago

Sorry I can't help with that. I use libexiv2 programmatically via a Python / gexiv2 interface which hides that sort of detail. (But allows me to delete a value and then set it again.)

RE: Exif.Image.Orientation issue - Added by Goran Nagy about 1 month ago

Thanks anyway.

It seems there was an issue in my code.

int Rotation = 8;
exifData["Exif.Image.Orientation"] = Rotation;

instead of

unsigned short Rotation = 8;
exifData["Exif.Image.Orientation"] = Rotation;

RE: Exif.Image.Orientation issue - Added by Robin Mills about 1 month ago

Interesting discussion. Thanks to Jim for answering this one.

The Exif specification provides for 8 types of data. Short, Long, SShort, SLong (and others). See page 14. https://www.exif.org/Exif2-2.PDF

When you set a value of '1', the command-line program defaults to Short. However, you can specify other types if you wish with the syntax:

 $ exiv2 -M'set Exif.Image.Orientation <type> <value>' file ...
Here are examples:
504 rmills@rmillsmbp:~/temp $ curl -O http://clanmills.com/Stonehenge.jpg
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 6599k  100 6599k    0     0  1254k      0  0:00:05  0:00:05 --:--:-- 1354k
505 rmills@rmillsmbp:~/temp $ exiv2 -pa --grep orientation/i Stonehenge.jpg 
Exif.Image.Orientation                       Short       1  top, left
506 rmills@rmillsmbp:~/temp $ exiv2 -M'set Exif.Image.Orientation 8' Stonehenge.jpg 
507 rmills@rmillsmbp:~/temp $ exiv2 -pa --grep orientation/i Stonehenge.jpg 
Exif.Image.Orientation                       Short       1  left, bottom
508 rmills@rmillsmbp:~/temp $ exiv2 -M'set Exif.Image.Orientation SShort 8' Stonehenge.jpg 
509 rmills@rmillsmbp:~/temp $ exiv2 -pa --grep orientation/i Stonehenge.jpg 
Exif.Image.Orientation                       SShort      1  left, bottom
510 rmills@rmillsmbp:~/temp $ exiv2 -M'set Exif.Image.Orientation Long 8' Stonehenge.jpg 
511 rmills@rmillsmbp:~/temp $ exiv2 -pa --grep orientation/i Stonehenge.jpg 
Exif.Image.Orientation                       Long        1  left, bottom
512 rmills@rmillsmbp:~/temp $ 
I wouldn't like to offer an opinion about which applications handle the Orientation flag well. For sure, the Mac's Preview.app doesn't understand Orientation unless it's a Short (as Specified by Exif on page 16)

Incidentally, you should consider the value of Orientation to be a bit-mask. Bit 0 is left-right, Bit 1 is up-down, Bit 2 is 0/90 rotation.

Here's the data in your files:

542 rmills@rmillsmbp:~/temp $ exiv2 -pa --grep image.orientation/i *.jpg
exiftool.jpg          Exif.Image.Orientation                       Short       1  left, bottom
exiv2.jpg             Exif.Image.Orientation                       SLong       1  left, bottom
original.jpg          Exif.Image.Orientation                       SLong       1  top, left
543 rmills@rmillsmbp:~/temp $ 
As you see, exiftool has used Short. The original and exiv2 are using SLong.

To explain your C++ code, please see the document: http://www.exiv2.org/doc/classExiv2_1_1Exifdatum.html

We overload operator=, so to get a Short, use:

exifData["Exif.Image.Orientation"] = (const int16_t) 8;

Exiv2 is not a metadata policeman. We don't enforce the types of data according to the specification. You can set a metadatum to a value and/or type of your choice and I've used that to set Long and SShort. I don't encourage you to use the wrong type, however we provide this capability. Use "the force" carefully. With great power, comes awesome responsibility!

RE: Exif.Image.Orientation issue - Added by Phil Harvey 29 days ago

Robin Mills wrote:

We overload operator=, so to get a Short, use:[...]

This sounds dangerous if I understand correctly -- is it really up to the programmer to specify the storage format for each piece of metadata written? And using the wrong variable type causes the metadata to be written in the wrong format? This sounds like a recipe for disaster. I hope I'm reading this wrong.

RE: Exif.Image.Orientation issue - Added by Robin Mills 29 days ago

Phil

I hope I'm not frightening you. My understanding is that exiv2 will allow you to set the data without reference to the specification. As I usually express this - Exiv2 is not a metadata policeman. He's a tool and it is the user's responsibility to use it correctly.

$ curl http://clanmills.com/Stonehenge.jpg > S.jpg ; exiv2 -pa --grep Exif.Image.DateTime S.jpg
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 6599k  100 6599k    0     0  1265k      0  0:00:05  0:00:05 --:--:-- 1372k
Exif.Image.DateTime                          Ascii      20  2015:07:16 20:25:28
$ exiv2 -M"set Exif.Image.DateTime 2018:10:16 18:43:40" S.jpg ; exiv2 -pa --grep Exif.Image.DateTime S.jpg 
Exif.Image.DateTime                          Ascii      20  2018:10:16 18:43:40
$ exiv2 -M"set Exif.Image.DateTime Short 1 2 3 4 5" S.jpg ; exiv2 -pa --grep Exif.Image.DateTime S.jpg 
Exif.Image.DateTime                          Short       5  1 2 3 4 5
$ exiv2 -M"set Exif.Image.DateTime Rational 1/2 3/4 5/6" S.jpg ; exiv2 -pa --grep Exif.Image.DateTime S.jpg 
Exif.Image.DateTime                          Rational    3  1/2 3/4 5/6
$ 
I believe applications (such as digiKam) provide the "policeman" to conform with standards. We have APIs to inspect the tag database. For example:
709 rmills@rmillsmbp:~/temp $ taglist --help
Usage: taglist [--group name|Groups|Exif|Canon|CanonCs|...]]
Print Exif tags, MakerNote tags, or Iptc datasets
710 rmills@rmillsmbp:~/temp $ taglist Exif | grep Exif.Image.DateTime,
DateTime,    306,    0x0132,    Image,    Exif.Image.DateTime,    Ascii,
    The date and time of image creation. In Exif standard,
      it is the date and time the file was changed.
So, an application can determine that the tag Exif.Image.DateTime is a string (type Ascii). There are functions in the code to format date as 20 bytes "YYYY:MM:DD HH:MM:SS\0"

It was this way when I joined the project in 2008. Please don't shoot the messenger!

RE: Exif.Image.Orientation issue - Added by Phil Harvey 28 days ago

I can tell you from experience that incorrect formats are a common problem, and that various applications have problems with unexpected formats.

I don't expect Exiv2 to police the metadata, but it would be much more reasonable if Exiv2 wrote in the correct format by default, and if it required some extra effort to write in a different format. As it stands right now, the extra effort is required to write in the correct format, which will definitely cause more headaches and hair-pulling down the road.

RE: Exif.Image.Orientation issue - Added by Robin Mills 28 days ago

I think you're right. We set the correct data type by default and enable the user to "force" something else.

$ curl http://clanmills.com/Stonehenge.jpg > S.jpg ; exiv2 -pa --grep Exif.Image.DateTime S.jpg
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 6599k  100 6599k    0     0   824k      0  0:00:08  0:00:08 --:--:-- 1216k
Exif.Image.DateTime                          Ascii      20  2015:07:16 20:25:28
$ exiv2 -M"set Exif.Image.DateTime 3 2 1" S.jpg ; exiv2 -pa --grep Exif.Image.DateTime S.jpg 
Exif.Image.DateTime                          Ascii       6  3 2 1  <---- Yip, it's ascii
$ 
If you declare the type, we'll set it.
$ curl http://clanmills.com/Stonehenge.jpg > S.jpg ; exiv2 -pa --grep Exif.Image.DateTime S.jpg
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 6599k  100 6599k    0     0  1321k      0  0:00:04  0:00:04 --:--:-- 1624k
Exif.Image.DateTime                          Ascii      20  2015:07:16 20:25:28
$ exiv2 -M"set Exif.Image.DateTime Short 3 2 1" S.jpg ; exiv2 -pa --grep Exif.Image.DateTime S.jpg <--- Notice 'Short' in the set
Exif.Image.DateTime                          Short       3  3 2 1 <---- We've set an array of 3 shorts
$ 
We could be more diligent with time tags to enforce the formatting.

You know how it is, Phil. There's a never ending and growing request list. The good news is that I have two wonderful people working with me on Exiv2. I'm working hard to get Exiv2 v0.27 RC1 released (probably next week) and GM by the end of the year. Next year, I will deal with the forum and issue/requests - however I'm not going to contribute to the code.

RE: Exif.Image.Orientation issue - Added by Phil Harvey 28 days ago

Robin Mills wrote:

I think you're right. We set the correct data type by default and enable the user to "force" something else.

Just to be clear: I was talking about the API (specifically, the overloaded operator=), which doesn't impose a default format. I understand that the "exiv2" app imposes the correct format by default.

You know how it is, Phil. There's a never ending and growing request list.

I know. :(

I'm working hard to get Exiv2 v0.27 RC1 released (probably next week) and GM by the end of the year.

Excellent!

RE: Exif.Image.Orientation issue - Added by Robin Mills 28 days ago

Next year I want to relax and only deal with Exiv2 correspondence. The others have great ideas and skills to take the project into the future.

I've purchased a Euphonium in September and hope to join a Silver Band next year. And in November I will qualify as a "Run Leader" to help our running club establish a "Couch to 5K" program next year.

So, less C++, more fun. And we're thinking about a trip to Canada in July 2020.

img_1642.jpg (66.5 KB)

RE: Exif.Image.Orientation issue - Added by Phil Harvey 28 days ago

That's a very shiny instrument you've got there! Coincidentally I played the euphonium in school myself.

What? C++ isn't fun? ;)

We've got a spare room for you if you're ever looking for accommodation in the Kingston area.

(1-13/13)

Redmine Appliance - Powered by TurnKey Linux