Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

EXIF inconsistencies for "UserComment" tag #5254

Closed
cristianoccazinsp opened this issue Feb 9, 2021 · 13 comments
Closed

EXIF inconsistencies for "UserComment" tag #5254

cristianoccazinsp opened this issue Feb 9, 2021 · 13 comments
Labels

Comments

@cristianoccazinsp
Copy link

What did you do?

Read an image's exif with im.getexif.items().

What did you expect to happen?

"UserComment" (tag 37510) should be properly decoded from images,

What actually happened?

An image captured on an Android device was decoded just fine. However, a similar image generated by the same app from iOS, failed to correctly parse the exif tag, and ended up as binary.

What are your OS, Python and Pillow versions?

  • OS: Windows
  • Python: 3.7.2
  • Pillow: 8.1.0 (happened with 7.1.2 too)
im1 = Image.open("a1.JPEG")
im2 = Image.open("iphone.jpg")

list(im1.getexif().items())
list(im2.getexif().items())

Output:

> list(im1.getexif().items())
[(36864, '0220'), (40961, 1), (37378, 1.58), (37379, -0.65), (37380, 0.0), (37381, 1.58), (37510, '{"datetime":"2021-02-08T20:14:51-03:00","group":2,"user":2,"property":"Non ascii ???","area":"null null","detail":null}'), (41989, 25), (36867, '2021:02:08 20:14:52'), (41987, 0), (36868, '2021:02:08 20:14:52'), (37383, 2), (37386, 4.38), (37385, 16), (37384, 21), (256, 768), (257, 1024), (271, 'Google'), (272, 'Pixel 5'), (274, 0), (37377, 4.572), (259, 6), (33434, 0.0416), (33437, 1.73), (34850, 2), (34853, {1: 'S', 2: (34.0, 54.0, 37.14156), 3: 'W', 4: (56.0, 11.0, 53.43684), 5: b'\x00', 6: 45.0}), (34855, 276), (34665, 233), (41986, 0), (305, 'zInspector3 Version: 3.1.53 (Dev/Test)'), (306, '2021:02:08 20:14:52'), (315, 'test3@gm.com')]

> list(im2.getexif().items())
[(37377, 2.0004559616992172), (37378, 1.6959938128383605), (36867, '2021:02:08 10:44:00'), (36868, '2021:02:08 10:44:00'), (37379, -3.386743237911534), (37380, 0.0), (37383, 5), (37510, b'ASCII\x00\x00\x00{"datetime":"2021-02-08T10:43:59-03:00","group":2,"user":2,"property":"1310 L Street Unit 01","area":"null null","detail":null}'), (37385, 16), (37386, 3.99), (40961, 1), (40962, 768), (41989, 28), (271, 'Apple'), (36880, '-03:00'), (36881, '-03:00'), (36882, '-03:00'), (37521, '349'), (37396, (2015, 1511, 2217, 1330)), (37522, '349'), (40963, 1024), (41495, 2), (272, 'iPhone 7'), (274, 1), (33434, 0.25), (282, 72.0), (283, 72.0), (33437, 1.8), (41729, b'\x01'), (34850, 2), (34853, {1: 'S', 2: (34.0, 54.0, 36.56), 3: 'W', 4: (56.0, 11.0, 53.2), 5: b'\x00', 6: 23.0}), (34855, 250), (296, 2), (41986, 0), (41987, 0), (305, 'zInspector3 Version: 3.1.52'), (42034, (3.9900000095374253, 3.9900000095374253, 1.8, 1.8)), (42035, 'Apple'), (42036, 'iPhone 7 back camera 3.99mm f/1.8'), (306, '2021:02:08 10:44:00'), (315, 'test3@gm.com'), (316, 'iPhone 7'), (34665, 262), (37500, b"Apple iOS\x00\x00\x01MM\x00\x1a\x00\x01\x00\t\x00\x00\x00\x01\x00\x00\x00\x0c\x00\x02\x00\x07\x00\x00\x02.\x00\x00\x01L\x00\x03\x00\x07\x00\x00\x00h\x00\x00\x03z\x00\x04\x00\t\x00\x00\x00\x01\x00\x00\x00\x01\x00\x05\x00\t\x00\x00\x00\x01\x00\x00\x00Q\x00\x06\x00\t\x00\x00\x00\x01\x00\x00\x00I\x00\x07\x00\t\x00\x00\x00\x01\x00\x00\x00\x01\x00\x08\x00\n\x00\x00\x00\x03\x00\x00\x03\xe2\x00\x0c\x00\n\x00\x00\x00\x02\x00\x00\x03\xfa\x00\r\x00\t\x00\x00\x00\x01\x00\x00\x00\x08\x00\x0e\x00\t\x00\x00\x00\x01\x00\x00\x00\x00\x00\x0f\x00\t\x00\x00\x00\x01\x00\x00\x00\x02\x00\x10\x00\t\x00\x00\x00\x01\x00\x00\x00\x01\x00\x14\x00\t\x00\x00\x00\x01\x00\x00\x00\x05\x00\x17\x00\t\x00\x00\x00\x01\x00\x00\x00\x00\x00\x19\x00\t\x00\x00\x00\x01\x00\x00\x00\x00\x00\x1f\x00\t\x00\x00\x00\x01\x00\x00\x00\x00\x00 \x00\x02\x00\x00\x00%\x00\x00\x04\n\x00%\x00\t\x00\x00\x00\x01\x00\x00\x00\x00\x00&\x00\t\x00\x00\x00\x01\x00\x00\x00\x00\x00'\x00\n\x00\x00\x00\x01\x00\x00\x040\x00+\x00\x02\x00\x00\x00%\x00\x00\x048\x00/\x00\t\x00\x00\x00\x01\x00\x00\x00A\x006\x00\t\x00\x00\x00\x01\x00\x00\x00\x06\x00;\x00\t\x00\x00\x00\x01\x00\x00\x00\x00\x00<\x00\t\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00bplist00O\x11\x02\x00\x03\x00\x03\x00\x03\x00\x03\x00\x03\x00\x04\x00\x04\x00\x05\x00\x06\x00\t\x00\x12\x00M\x00g\x00\x1a\x00\x03\x00\x04\x00\x03\x00\x03\x00\x03\x00\x03\x00\x04\x00\x04\x00\x05\x00\x06\x00\n\x00\x19\x00t\x00y\x00\x11\x00\x03\x00\x04\x00\x06\x00\x03\x00\x03\x00\x04\x00\x04\x00\x05\x00\x05\x00\x05\x00\x0b\x00'\x00\x89\x00D\x00s\x00`\x00\x04\x00\x06\x00\x08\x00\x03\x00\x03\x00\x05\x00\x05\x00\x05\x00\x06\x00\x0e\x00:\x00\x8c\x00?\x00\x03\x00>\x00\xf2\x00,\x00\n\x00\x0f\x00\x04\x00\x05\x00\x06\x00\x07\x00\x07\x00\x11\x00S\x00\x7f\x00 \x008\x00\x07\x00\x07\x00\xc9\x00O\x00\x14\x00 \x00\x05\x00\x06\x00\x08\x00\n\x00\x16\x00v\x00\\x00\x06\x00\x05\x00+\x00P\x00L\x005\x00d\x00-\x00G\x00\x06\x00\x08\x00\x0e\x00&\x00\x87\x006\x00\x03\x00\x05\x00\x0e\x00-\x00r\x00i\x00\xaf\x00\xac\x00\x89\x00\x96\x00\x08\x00\x12\x00B\x00\x85\x00\x18\x00\x04\x00\x06\x00\t\x00\x17\x00l\x01\x89\x00\x87\x00L\x00\x8b\x00\x8c\x00\x90\x00\x1c\x00a\x00m\x00\x11\x00\x04\x00\x06\x00\x0b\x00\x13\x00T\x00'\x00G\x00\x84\x00h\x00\x85\x00\xa3\x00j\x00\x92\x00Z\x00\x1e\x00\x1d\x00\t\x00\x1e\x004\x00;\x00k\x00K\x00\xb2\x00\xb0\x00\xb0\x00\xa8\x00\x97\x00\x8b\x00d\x00i\x00'\x00$\x00\x11\x00,\x00B\x00D\x00~\x00\xab\x00\xbf\x00\x9f\x00\xbf\x00\x7f\x00\x82\x00\xa4\x00\xa1\x00\xc0\x00,\x00*\x00\x1a\x00\x14\x00G\x00x\x00\xd8\x00^\x00p\x00\x81\x00W\x00\x84\x00\xa3\x00\xbe\x00\xc0\x00\xf5\x002\x00.\x00#\x00\n\x003\x00\x86\x00\x82\x00\xa8\x00d\x00s\x00/\x00Y\x00[\x00\xbb\x00\xc7\x00'\x017\x002\x00+\x00\x0e\x00;\x00\x8a\x00\xd9\x00\x00\x01\x1b\x01\x7f\x00G\x00V\x00\x86\x00\x86\x00\xce\x00,\x01\\x006\x00.\x00\x19\x00\xba\x00\xf6\x00\xd3\x00\xe9\x00\xf7\x00\xc5\x00\x03\x01\xc8\x00\xb3\x00a\x00\xcd\x00\xf9\x00\xb5\x00:\x001\x00\x1d\x00z\x00\xd0\x00\x95\x00\xd3\x00\xe2\x00\x99\x006\x00\x9c\x00\xab\x00d\x00\x00\x08\x00\x00\x00\x00\x00\x00\x02\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x0cbplist00\xd4\x01\x02\x03\x04\x05\x06\x07\x08UflagsUvalueYtimescaleUepoch\x10\x01\x13\x00\x00E\x11\xbbz\x88\xc7\x12;\x9a\xca\x00\x10\x00\x08\x11\x17\x1d'-/8=\x00\x00\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\t\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00?\x00\x00\r\xd5\x00\x00\xeaE\xff\xfe\xd9l\x00\x02\x19\xfd\xff\xff\x84\xcd\x00\x00\x96F\x00\x00\x00E\x00\x00\x01\x00\x00\x00\x00a\x00\x00\x01\x001993A584-5179-483F-A60C-D43AFBAC63BD\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01CD4AEB57-A780-4E7A-B74A-29F7BD750CEB\x00\x00")]

tobytes output:

> im1.getexif().tobytes()
b'Exif\x00\x00MM\x00*\x00\x00\x00\x08\x00 \x01\x00\x00\x04\x00\x00\x00\x01\x00\x00\x03\x00\x01\x01\x00\x04\x00\x00\x00\x01\x00\x00\x04\x00\x01\x03\x00\x03\x00\x00\x00\x01\x00\x06\x00\x00\x01\x0f\x00\x02\x00\x00\x00\x07\x00\x00\x01\x8e\x01\x10\x00\x02\x00\x00\x00\x08\x00\x00\x01\x96\x01\x12\x00\x03\x00\x00\x00\x01\x00\x00\x00\x00\x011\x00\x02\x00\x00\x00'\x00\x00\x01\x9e\x012\x00\x02\x00\x00\x00\x14\x00\x00\x01\xc6\x01;\x00\x02\x00\x00\x00\r\x00\x00\x01\xda\x82\x9a\x00\x05\x00\x00\x00\x01\x00\x00\x01\xe8\x82\x9d\x00\x05\x00\x00\x00\x01\x00\x00\x01\xf0\x87i\x00\x04\x00\x00\x00\x01\x00\x00\x00\xe9\x88"\x00\x03\x00\x00\x00\x01\x00\x02\x00\x00\x88%\x00\x04\x00\x00\x00\x01\x00\x00\x01\xf8\x88'\x00\x03\x00\x00\x00\x01\x01\x14\x00\x00\x90\x00\x00\x02\x00\x00\x00\x05\x00\x00\x02~\x90\x03\x00\x02\x00\x00\x00\x14\x00\x00\x02\x84\x90\x04\x00\x02\x00\x00\x00\x14\x00\x00\x02\x98\x92\x01\x00\x05\x00\x00\x00\x01\x00\x00\x02\xac\x92\x02\x00\x05\x00\x00\x00\x01\x00\x00\x02\xb4\x92\x03\x00\n\x00\x00\x00\x01\x00\x00\x02\xbc\x92\x04\x00\x05\x00\x00\x00\x01\x00\x00\x02\xc4\x92\x05\x00\x05\x00\x00\x00\x01\x00\x00\x02\xcc\x92\x07\x00\x03\x00\x00\x00\x01\x00\x02\x00\x00\x92\x08\x00\x03\x00\x00\x00\x01\x00\x15\x00\x00\x92\t\x00\x03\x00\x00\x00\x01\x00\x10\x00\x00\x92\n\x00\x05\x00\x00\x00\x01\x00\x00\x02\xd4\x92\x86\x00\x02\x00\x00\x00x\x00\x00\x02\xdc\xa0\x01\x00\x03\x00\x00\x00\x01\x00\x01\x00\x00\xa4\x02\x00\x03\x00\x00\x00\x01\x00\x00\x00\x00\xa4\x03\x00\x03\x00\x00\x00\x01\x00\x00\x00\x00\xa4\x05\x00\x03\x00\x00\x00\x01\x00\x19\x00\x00\x00\x00\x00\x00Google\x00\x00Pixel 5\x00zInspector3 Version: 3.1.53 (Dev/Test)\x00\x002021:02:08 20:14:52\x00test3@gm.com\x00\x00\x00\x00\x00\x1a\x00\x00\x02q\x00\x00\x00\xad\x00\x00\x00d\x00\x06\x00\x01\x00\x02\x00\x00\x00\x02S\x00\x00\x00\x00\x02\x00\x05\x00\x00\x00\x03\x00\x00\x02F\x00\x03\x00\x02\x00\x00\x00\x02W\x00\x00\x00\x00\x04\x00\x05\x00\x00\x00\x03\x00\x00\x02^\x00\x05\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x06\x00\x05\x00\x00\x00\x01\x00\x00\x02v\x00\x00\x00\x00\x00\x00\x00"\x00\x00\x00\x01\x00\x00\x006\x00\x00\x00\x01\x00\x0e+\x1b\x00\x00a\xa8\x00\x00\x008\x00\x00\x00\x01\x00\x00\x00\x0b\x00\x00\x00\x01\x00\x14bq\x00\x00a\xa8\x00\x00\x00-\x00\x00\x00\x010220\x00\x002021:02:08 20:14:52\x002021:02:08 20:14:52\x00\x00\x00\x04w\x00\x00\x00\xfa\x00\x00\x00O\x00\x00\x002\xff\xff\xff\xbf\x00\x00\x00d\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00O\x00\x00\x002\x00\x00\x00\xdb\x00\x00\x002{"datetime":"2021-02-08T20:14:51-03:00","group":2,"user":2,"property":"Non ascii ???","area":"null null","detail":null}\x00'

> im2.getexif().tobytes()
b'Exif\x00\x00MM\x00*\x00\x00\x00\x08\x00,\x01\x0f\x00\x02\x00\x00\x00\x06\x00\x00\x02\x1e\x01\x10\x00\x02\x00\x00\x00\t\x00\x00\x02$\x01\x12\x00\x03\x00\x00\x00\x01\x00\x01\x00\x00\x01\x1a\x00\x05\x00\x00\x00\x01\x00\x00\x02.\x01\x1b\x00\x05\x00\x00\x00\x01\x00\x00\x026\x01(\x00\x03\x00\x00\x00\x01\x00\x02\x00\x00\x011\x00\x02\x00\x00\x00\x1c\x00\x00\x02>\x012\x00\x02\x00\x00\x00\x14\x00\x00\x02Z\x01;\x00\x02\x00\x00\x00\r\x00\x00\x02n\x01<\x00\x02\x00\x00\x00\t\x00\x00\x02|\x82\x9a\x00\x05\x00\x00\x00\x01\x00\x00\x02\x86\x82\x9d\x00\x05\x00\x00\x00\x01\x00\x00\x02\x8e\x87i\x00\x04\x00\x00\x00\x01\x00\x00\x01\x06\x88"\x00\x03\x00\x00\x00\x01\x00\x02\x00\x00\x88%\x00\x04\x00\x00\x00\x01\x00\x00\x02\x96\x88'\x00\x03\x00\x00\x00\x01\x00\xfa\x00\x00\x90\x03\x00\x02\x00\x00\x00\x14\x00\x00\x03\x1c\x90\x04\x00\x02\x00\x00\x00\x14\x00\x00\x030\x90\x10\x00\x02\x00\x00\x00\x07\x00\x00\x03D\x90\x11\x00\x02\x00\x00\x00\x07\x00\x00\x03L\x90\x12\x00\x02\x00\x00\x00\x07\x00\x00\x03T\x92\x01\x00\x05\x00\x00\x00\x01\x00\x00\x03\\x92\x02\x00\x05\x00\x00\x00\x01\x00\x00\x03d\x92\x03\x00\n\x00\x00\x00\x01\x00\x00\x03l\x92\x04\x00\x05\x00\x00\x00\x01\x00\x00\x03t\x92\x07\x00\x03\x00\x00\x00\x01\x00\x05\x00\x00\x92\t\x00\x03\x00\x00\x00\x01\x00\x10\x00\x00\x92\n\x00\x05\x00\x00\x00\x01\x00\x00\x03|\x92\x14\x00\x03\x00\x00\x00\x04\x00\x00\x03\x84\x92|\x00\x01\x00\x00\x04^\x00\x00\x03\x8c\x92\x86\x00\x01\x00\x00\x00\x87\x00\x00\x07\xea\x92\x91\x00\x02\x00\x00\x00\x04349\x00\x92\x92\x00\x02\x00\x00\x00\x04349\x00\xa0\x01\x00\x03\x00\x00\x00\x01\x00\x01\x00\x00\xa0\x02\x00\x03\x00\x00\x00\x01\x03\x00\x00\x00\xa0\x03\x00\x03\x00\x00\x00\x01\x04\x00\x00\x00\xa2\x17\x00\x03\x00\x00\x00\x01\x00\x02\x00\x00\xa3\x01\x00\x01\x00\x00\x00\x01\x01\x00\x00\x00\xa4\x02\x00\x03\x00\x00\x00\x01\x00\x00\x00\x00\xa4\x03\x00\x03\x00\x00\x00\x01\x00\x00\x00\x00\xa4\x05\x00\x03\x00\x00\x00\x01\x00\x1c\x00\x00\xa42\x00\x05\x00\x00\x00\x04\x00\x00\x08r\xa43\x00\x02\x00\x00\x00\x06\x00\x00\x08\x92\xa44\x00\x02\x00\x00\x00"\x00\x00\x08\x98\x00\x00\x00\x00Apple\x00iPhone 7\x00\x00\x00\x00\x00H\x00\x00\x00\x01\x00\x00\x00H\x00\x00\x00\x01zInspector3 Version: 3.1.52\x002021:02:08 10:44:00\x00test3@gm.com\x00\x00iPhone 7\x00\x00\x00\x00\x00\x01\x00\x00\x00\x04\x00\x00\x00\t\x00\x00\x00\x05\x00\x06\x00\x01\x00\x02\x00\x00\x00\x02S\x00\x00\x00\x00\x02\x00\x05\x00\x00\x00\x03\x00\x00\x02\xe4\x00\x03\x00\x02\x00\x00\x00\x02W\x00\x00\x00\x00\x04\x00\x05\x00\x00\x00\x03\x00\x00\x02\xfc\x00\x05\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x06\x00\x05\x00\x00\x00\x01\x00\x00\x03\x14\x00\x00\x00\x00\x00\x00\x00"\x00\x00\x00\x01\x00\x00\x006\x00\x00\x00\x01\x00\x00\x03\x92\x00\x00\x00\x19\x00\x00\x008\x00\x00\x00\x01\x00\x00\x00\x0b\x00\x00\x00\x01\x00\x00\x01\n\x00\x00\x00\x05\x00\x00\x00\x17\x00\x00\x00\x012021:02:08 10:44:00\x002021:02:08 10:44:00\x00-03:00\x00\x00-03:00\x00\x00-03:00\x00\x00\x00\x00f\xd4\x00\x003g\x00\x00\xd6'\x00\x00E\xff\xfe\xd29\x00\x00Y\x1b\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x01\x8f\x00\x00\x00d\x07\xdf\x05\xe7\x08\xa9\x052Apple iOS\x00\x00\x01MM\x00\x1a\x00\x01\x00\t\x00\x00\x00\x01\x00\x00\x00\x0c\x00\x02\x00\x07\x00\x00\x02.\x00\x00\x01L\x00\x03\x00\x07\x00\x00\x00h\x00\x00\x03z\x00\x04\x00\t\x00\x00\x00\x01\x00\x00\x00\x01\x00\x05\x00\t\x00\x00\x00\x01\x00\x00\x00Q\x00\x06\x00\t\x00\x00\x00\x01\x00\x00\x00I\x00\x07\x00\t\x00\x00\x00\x01\x00\x00\x00\x01\x00\x08\x00\n\x00\x00\x00\x03\x00\x00\x03\xe2\x00\x0c\x00\n\x00\x00\x00\x02\x00\x00\x03\xfa\x00\r\x00\t\x00\x00\x00\x01\x00\x00\x00\x08\x00\x0e\x00\t\x00\x00\x00\x01\x00\x00\x00\x00\x00\x0f\x00\t\x00\x00\x00\x01\x00\x00\x00\x02\x00\x10\x00\t\x00\x00\x00\x01\x00\x00\x00\x01\x00\x14\x00\t\x00\x00\x00\x01\x00\x00\x00\x05\x00\x17\x00\t\x00\x00\x00\x01\x00\x00\x00\x00\x00\x19\x00\t\x00\x00\x00\x01\x00\x00\x00\x00\x00\x1f\x00\t\x00\x00\x00\x01\x00\x00\x00\x00\x00 \x00\x02\x00\x00\x00%\x00\x00\x04\n\x00%\x00\t\x00\x00\x00\x01\x00\x00\x00\x00\x00&\x00\t\x00\x00\x00\x01\x00\x00\x00\x00\x00'\x00\n\x00\x00\x00\x01\x00\x00\x040\x00+\x00\x02\x00\x00\x00%\x00\x00\x048\x00/\x00\t\x00\x00\x00\x01\x00\x00\x00A\x006\x00\t\x00\x00\x00\x01\x00\x00\x00\x06\x00;\x00\t\x00\x00\x00\x01\x00\x00\x00\x00\x00<\x00\t\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00bplist00O\x11\x02\x00\x03\x00\x03\x00\x03\x00\x03\x00\x03\x00\x04\x00\x04\x00\x05\x00\x06\x00\t\x00\x12\x00M\x00g\x00\x1a\x00\x03\x00\x04\x00\x03\x00\x03\x00\x03\x00\x03\x00\x04\x00\x04\x00\x05\x00\x06\x00\n\x00\x19\x00t\x00y\x00\x11\x00\x03\x00\x04\x00\x06\x00\x03\x00\x03\x00\x04\x00\x04\x00\x05\x00\x05\x00\x05\x00\x0b\x00'\x00\x89\x00D\x00s\x00`\x00\x04\x00\x06\x00\x08\x00\x03\x00\x03\x00\x05\x00\x05\x00\x05\x00\x06\x00\x0e\x00:\x00\x8c\x00?\x00\x03\x00>\x00\xf2\x00,\x00\n\x00\x0f\x00\x04\x00\x05\x00\x06\x00\x07\x00\x07\x00\x11\x00S\x00\x7f\x00 \x008\x00\x07\x00\x07\x00\xc9\x00O\x00\x14\x00 \x00\x05\x00\x06\x00\x08\x00\n\x00\x16\x00v\x00\\x00\x06\x00\x05\x00+\x00P\x00L\x005\x00d\x00-\x00G\x00\x06\x00\x08\x00\x0e\x00&\x00\x87\x006\x00\x03\x00\x05\x00\x0e\x00-\x00r\x00i\x00\xaf\x00\xac\x00\x89\x00\x96\x00\x08\x00\x12\x00B\x00\x85\x00\x18\x00\x04\x00\x06\x00\t\x00\x17\x00l\x01\x89\x00\x87\x00L\x00\x8b\x00\x8c\x00\x90\x00\x1c\x00a\x00m\x00\x11\x00\x04\x00\x06\x00\x0b\x00\x13\x00T\x00'\x00G\x00\x84\x00h\x00\x85\x00\xa3\x00j\x00\x92\x00Z\x00\x1e\x00\x1d\x00\t\x00\x1e\x004\x00;\x00k\x00K\x00\xb2\x00\xb0\x00\xb0\x00\xa8\x00\x97\x00\x8b\x00d\x00i\x00'\x00$\x00\x11\x00,\x00B\x00D\x00\x00\xab\x00\xbf\x00\x9f\x00\xbf\x00\x7f\x00\x82\x00\xa4\x00\xa1\x00\xc0\x00,\x00*\x00\x1a\x00\x14\x00G\x00x\x00\xd8\x00^\x00p\x00\x81\x00W\x00\x84\x00\xa3\x00\xbe\x00\xc0\x00\xf5\x002\x00.\x00#\x00\n\x003\x00\x86\x00\x82\x00\xa8\x00d\x00s\x00/\x00Y\x00[\x00\xbb\x00\xc7\x00'\x017\x002\x00+\x00\x0e\x00;\x00\x8a\x00\xd9\x00\x00\x01\x1b\x01\x7f\x00G\x00V\x00\x86\x00\x86\x00\xce\x00,\x01\\x006\x00.\x00\x19\x00\xba\x00\xf6\x00\xd3\x00\xe9\x00\xf7\x00\xc5\x00\x03\x01\xc8\x00\xb3\x00a\x00\xcd\x00\xf9\x00\xb5\x00:\x001\x00\x1d\x00z\x00\xd0\x00\x95\x00\xd3\x00\xe2\x00\x99\x006\x00\x9c\x00\xab\x00d\x00\x00\x08\x00\x00\x00\x00\x00\x00\x02\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x0cbplist00\xd4\x01\x02\x03\x04\x05\x06\x07\x08UflagsUvalueYtimescaleUepoch\x10\x01\x13\x00\x00E\x11\xbbz\x88\xc7\x12;\x9a\xca\x00\x10\x00\x08\x11\x17\x1d'-/8=\x00\x00\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\t\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00?\x00\x00\r\xd5\x00\x00\xeaE\xff\xfe\xd9l\x00\x02\x19\xfd\xff\xff\x84\xcd\x00\x00\x96F\x00\x00\x00E\x00\x00\x01\x00\x00\x00\x00a\x00\x00\x01\x001993A584-5179-483F-A60C-D43AFBAC63BD\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01CD4AEB57-A780-4E7A-B74A-29F7BD750CEB\x00\x00ASCII\x00\x00\x00{"datetime":"2021-02-08T10:43:59-03:00","group":2,"user":2,"property":"1310 L Street Unit 01","area":"null null","detail":null}\x00\x00?\xd5\xdf\x00\x0f\xff\xb5\x00?\xd5\xdf\x00\x0f\xff\xb5\x00\x00\x00\t\x00\x00\x00\x05\x00\x00\x00\t\x00\x00\x00\x05Apple\x00iPhone 7 back camera 3.99mm f/1.8\x00'

Hex view of the android image:
image

Hex view of the iOS image:
image

For me, it seems like the iOS image is the "correct" one, including the encoding as per the exif documentation (https://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif/usercomment.html). Whereas, the android one seems a bit invalid (no encoding info), but yet Pillow parses it fine.

I'm also attaching the two images I've used for testing:

a1

iphone

@radarhere radarhere added the Exif label Feb 9, 2021
@radarhere
Copy link
Member

Hi. If your goal is just to be able to read the comment, rather than changing the output of getexif(), I'd be more interested in adding a "comment" key to the image's info dictionary for the TIFF format - like GIF and JPEG already do.

Is that what you're after? Or would you like to solve this Exif consistency?

@kmilos
Copy link
Contributor

kmilos commented Feb 9, 2021

Exif spec says that 8 null bytes are used to indicate an "Undefined" character code, so the Android image is perfectly valid in that sense.

Although the possibility of unreadable characters exists, display of these characters is left as a matter of Exif/DCF reader implementation.

@cristianoccazinsp
Copy link
Author

Hi. If your goal is just to be able to read the comment, rather than changing the output of getexif(), I'd be more interested in adding a "comment" key to the image's info dictionary for the TIFF format - like GIF and JPEG already do.

Is that what you're after? Or would you like to solve this Exif consistency?

I wasn't really trying to accomplish anything, but rather debugging some corrupted images and comparing valid ones from multiple devices. After some testing, I noticed this inconsistency and wondered why Pillow wasn't parsing that key every time, so decided to report it.

Do you think it's an expected behaviour? For me, it really looks like a bug.

@kmilos you are right, the android one is also "perfectly fine", although in my testing, the payload was always ascii, and using any unicode character would end up as "??", so my guess is that Android also uses ascii encoding, but fails to set the encoding. Therefore, it would be "better implemented" if Android also included the same bytes iOS does.

Either way, you are both right, both images are properly encoded. So why does Pillow fail to decode one of them?

@kmilos
Copy link
Contributor

kmilos commented Feb 9, 2021

Sorry @cristianoccazinsp on second look I am now also confused...

For the Android image, exiv2 (or exiftool) reports only 120 bytes for that field, and just the content as you see it (plus the null termination character), and there is no required 8 bytes for character code preceding the message - i.e. the null bytes your hex editor screenshot were just a coincidence and that threw me off... The filed type is however already set as ASCII and that's how any app knows in advance how to decode it...

0x9286 Photo        UserComment                 Ascii     120  {"datetime":"2021-02-08T20:14:51-03:00",

iPhone reports 135 bytes which indeed include 8 bytes of code + 127 bytes of (unterminated) message, but the field type is UNDEFINED, and that's why a binary stream is returned, the app needs to decode it itself.

0x9286 Photo        UserComment                 Undefined 135  charset=Ascii {"datetime":"2021-02-08T10:43:59-03:00", ... 

The current Exif 2.32 spec clearly says the filed type should be UNDEFINED and the 8 byte code included at the start, so the Android must be implementing some older version of the spec, or they're just betting on apps doing the right thing when they see a plain old ASCII field...

So I don't really think Pillow is doing anything wrong, it just returns what it grabs from the field directly.

@cristianoccazinsp
Copy link
Author

Now I'm a bit confused as well! So, does PIL parse the values correctly? I was also testing with another exif library (https://github.com/ianare/exif-py), and in that case, both parse the UserComment just fine (no binary data returned).

@kmilos
Copy link
Contributor

kmilos commented Feb 9, 2021

That library might go through the extra trouble to introduce another level of decoding when it comes across a byte stream returned.

@radarhere
Copy link
Member

Yep, it does.

https://github.com/ianare/exif-py/blob/e0e408ff58cf621ef647588ea6c3871bfd010230/exifread/tags/exif.py#L340

0x9286: ('UserComment', make_string_uc),

https://github.com/ianare/exif-py/blob/e0e408ff58cf621ef647588ea6c3871bfd010230/exifread/utils.py#L42-L51

def make_string_uc(seq) -> str:
    """
    Special version to deal with the code in the first 8 bytes of a user comment.
    First 8 bytes gives coding system e.g. ASCII vs. JIS vs Unicode.
    """
    if not isinstance(seq, str):
        seq = seq[8:]
    # Of course, this is only correct if ASCII, and the standard explicitly
    # allows JIS and Unicode.
    return make_string(seq)

@radarhere
Copy link
Member

radarhere commented Mar 15, 2021

So you're just trying to point out a bug, but the discussion here has concluded that there is no bug.

Can this be closed then?

@cristianoccazinsp
Copy link
Author

Yes, not a bug, but perhaps a possible improvement for this special case?

@radarhere radarhere changed the title EXIF inconsistencies (or bug) for "UserComment" tag EXIF inconsistencies for "UserComment" tag Mar 15, 2021
@radarhere
Copy link
Member

Pillow not only reads EXIF tags, but also allows them to be written.
To alter the value when reading the tag would also mean that information has been lost when it came to writing the tag.

To bring it back to my original comment, I'd be more interested in adding a "comment" key to the image's info dictionary for the TIFF format - like GIF and JPEG already do.

@radarhere
Copy link
Member

Ah, I'm wrong. I've been talking about adding a "comment" to TIFFs, but these aren't TIFFs, they're JPEGs - that format already has a "comment".

@radarhere
Copy link
Member

My next idea would be to add a dedicated im.getexif().get_usercomment() method?

@radarhere
Copy link
Member

Since

I think it is best to keep the behaviour as is.

If there is no interest in another method of obtaining that data in a handier way, then I'm going to close this for now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants