brechtm / rinohtype

The Python document processor
http://www.mos6581.org/rinohtype
GNU Affero General Public License v3.0
499 stars 59 forks source link

ZeroDivisionError exception caused by JPEG with incomplete LensInfo #319

Closed cjmayo closed 2 years ago

cjmayo commented 2 years ago

Steps to reproduce (with exiftool and ImageMagick): Create index.rst:

.. image:: lensinfo.jpg

Then:

$ magick LOGO: lensinfo.jpg
$ exiftool -exif:resolutionunit=inches -LensInfo="100 100 undef undef" lensinfo.jpg
$ rinoh index.rst
...
  File "/usr/lib/python3.10/site-packages/rinoh/backend/pdf/xobject/jpeg.py", line 228, in _parse_exif_ifd
    result[tag] = get_value(type, count, value_or_offset)
  File "/usr/lib/python3.10/site-packages/rinoh/backend/pdf/xobject/jpeg.py", line 219, in get_value
    value = tuple(num / denom for num, denom in pairs)
  File "/usr/lib/python3.10/site-packages/rinoh/backend/pdf/xobject/jpeg.py", line 219, in <genexpr>
    value = tuple(num / denom for num, denom in pairs)
ZeroDivisionError: division by zero

Catching the exception and returning raw_value seems to work OK for me.

(missing resolutionunit also causes an exception but I haven't seen that one in a real photo)

Please also provide the following information:

brechtm commented 2 years ago

I'm not able to reproduce this despite your detailed instructions. Both rinohtype 0.5.3 and the current master happily process the JPEG file. I think ~ImageMagick (7.1.0-2)~ exiftool (12.30) is not willing to add invalid Lensinfo data to the JPEG:

$ exiftool -exif:resolutionunit=inches -LensInfo="100 100 undef undef" lensinfo.jpg
Warning: Not a floating point number for ExifIFD:LensInfo
    1 image files updated

I assume you bumped into this because you had another JPEG with incomplete lens info? Can you share that image (privately, if needed?

cjmayo commented 2 years ago

Sure, it is in GitHub: https://github.com/DCC-EX/dcc-ex.github.io/raw/1dc4c217e458ee20ce897f8d0a0d474dd81e397a/docs/_static/images/power/20W_DC_buck.jpg

I have exiftool (12.30) as well...

brechtm commented 2 years ago

This image causes another error for me:

  ...
  File "/private/tmp/lensinfo/lib/python3.9/site-packages/rinoh/backend/pdf/__init__.py", line 392, in __init__
    self.xobject = Reader(filename_or_file)
  File "/private/tmp/lensinfo/lib/python3.9/site-packages/rinoh/backend/pdf/xobject/jpeg.py", line 51, in __init__
    icc_profile, adobe_color_transform, dpi) = self._get_metadata()
  File "/private/tmp/lensinfo/lib/python3.9/site-packages/rinoh/backend/pdf/xobject/jpeg.py", line 114, in _get_metadata
    result = self._parse_exif_segment(header_length)
  File "/private/tmp/lensinfo/lib/python3.9/site-packages/rinoh/backend/pdf/xobject/jpeg.py", line 182, in _parse_exif_segment
    EXIF_UNITS[ifd_0th.get(EXIF_RESOLUTION_UNIT, 2)])
KeyError: 1

A ResolutionUnit value of 1 is currently not being handled by rinohtype. I'll try to address this.

Temporarily mapping 1 to inches, I do see the error you reported, so I can also look into handling that case. 👍

LensInfo contains information about the lens that captured the image. If the minimum f-stops are unknown, they should be encoded as 0/0.

brechtm commented 2 years ago

I finally figured out why exiftool wasn't working for me. I'm using xon.sh, which handles command line arguments differently. This works:

exiftool -exif:resolutionunit=inches "-LensInfo=100 100 undef undef" lensinfo.jpg
brechtm commented 2 years ago

Try installing from the master branch to verify whether the issue is fixed now:

pip install https://github.com/brechtm/rinohtype/archive/refs/heads/master.zip
cjmayo commented 2 years ago

Change in https://github.com/brechtm/rinohtype/commit/28737c484470b122d693992bf5f53a7060b7c9de fixes this for me. Thanks!