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

invalid ppem value with 0.15.1 but not with 0.14.0 #217

Open
aegleinformatiquemedicale opened this issue Oct 20, 2023 · 5 comments
Open
Labels
bug contributions welcome Further design discussions and PRs are welcome.

Comments

@aegleinformatiquemedicale

Hi,

If i try this with python 3.9.16

With python-barcode 0140 and Pillow 9.5.0 => OK

Python 3.9.16 (main, Jun 30 2023, 08:01:58) 
[GCC 8.5.0 20210514 (Red Hat 8.5.0-18)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import barcode
>>> from barcode.writer import ImageWriter
>>> num = 'ABC123456'
>>> try:
...     checksum = False
...     CODE39 = barcode.get_barcode_class('code39')
...     options = {'font_size': 0,'text_distance': 0.0,'module_height': 24.0,'quiet_zone': 0.0}
...     options['center_text'] = False
...     ean = CODE39(str(num), writer=ImageWriter(), add_checksum=checksum)
...     ean.save('tmp/sticker_code39_' + num, options=options)
... except Exception as err:
...     print(err)
... 
'tmp/sticker_code39_ABC123456.png'

With python-barcode 0.15.1 and Pillow 10.0.0 (same with 10.0.1) => ERR : invalid ppem value

>>> import barcode
>>> from barcode.writer import ImageWriter
>>> num = 'ABC123456'
>>> try:
...     checksum = False
...     CODE39 = barcode.get_barcode_class('code39')
...     options = {'font_size': 0,'text_distance': 0.0,'module_height': 24.0,'quiet_zone': 0.0}
...     options['center_text'] = False
...     ean = CODE39(str(num), writer=ImageWriter(), add_checksum=checksum)
...     ean.save('tmp/sticker_code39_' + num, options=options)
... except Exception as err:
...     print(err)
... 
invalid ppem value

I didn't see in your documentation what had changed.

Thanks

@WhyNotHugo
Copy link
Owner

I get the same exception with v0.14.0.

> cd python-barcode
> mkvirtualenv python-barcode
> pip install -e '.[images]'
> cat test.py
from __future__ import annotations

import barcode
from barcode.writer import ImageWriter

num = "ABC123456"
checksum = False
CODE39 = barcode.get_barcode_class("code39")
options = {
    "font_size": 0,
    "text_distance": 0.0,
    "module_height": 24.0,
    "quiet_zone": 0.0,
}
options["center_text"] = False
ean = CODE39(str(num), writer=ImageWriter(), add_checksum=checksum)
ean.save("tmp/sticker_code39_" + num, options=options)
> python test.py
Traceback (most recent call last):
  File "/home/hugo/src/github.com/WhyNotHugo/python-barcode/test.py", line 17, in <module>
    ean.save("tmp/sticker_code39_" + num, options=options)
  File "/home/hugo/src/github.com/WhyNotHugo/python-barcode/barcode/base.py", line 65, in save
    output = self.render(options)
             ^^^^^^^^^^^^^^^^^^^^
  File "/home/hugo/src/github.com/WhyNotHugo/python-barcode/barcode/codex.py", line 74, in render
    return super().render(options, text)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/hugo/src/github.com/WhyNotHugo/python-barcode/barcode/base.py", line 105, in render
    raw = self.writer.render(code)
          ^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/hugo/src/github.com/WhyNotHugo/python-barcode/barcode/writer.py", line 265, in render
    self._callbacks["paint_text"](xpos, ypos)
  File "/home/hugo/src/github.com/WhyNotHugo/python-barcode/barcode/writer.py", line 439, in _paint_text
    font = ImageFont.truetype(self.font_path, font_size)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/hugo/.local/state/virtualenvs/python-barcode/lib/python3.11/site-packages/PIL/ImageFont.py", line 797, in truetype
    return freetype(font)
           ^^^^^^^^^^^^^^
  File "/home/hugo/.local/state/virtualenvs/python-barcode/lib/python3.11/site-packages/PIL/ImageFont.py", line 794, in freetype
    return FreeTypeFont(font, size, index, encoding, layout_engine)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/hugo/.local/state/virtualenvs/python-barcode/lib/python3.11/site-packages/PIL/ImageFont.py", line 226, in __init__
    self.font = core.getfont(
                ^^^^^^^^^^^^^
OSError: invalid ppem value

@aegleinformatiquemedicale
Copy link
Author

With which Pillow version ?

That my venv (when its OK) for my test i changed only versions of python-barcode and Pillow between the first try and the second one

Package                Version
---------------------- ------------
alembic                1.10.4
aniso8601              9.0.1
Babel                  2.12.1
blinker                1.6.3
certifi                2023.7.22
click                  8.1.7
deprecation            2.1.0
distlib                0.3.7
filelock               3.12.4
Flask                  2.3.3
flask-babel            3.1.0
Flask-RESTful          0.3.10
Genshi                 0.7.7
greenlet               3.0.0
gunicorn               20.1.0
importlib-metadata     6.8.0
itsdangerous           2.1.2
Jinja2                 3.1.2
lxml                   4.9.3
Mako                   1.2.4
MarkupSafe             2.1.3
mysql-connector-python 8.0.32
packaging              23.2
pdfkit                 1.0.0
pikepdf                7.2.0
**Pillow                 9.5.0**
pip                    23.3
pipenv                 2023.10.3
platformdirs           3.11.0
protobuf               3.20.3
pypng                  0.20220715.0
**python-barcode         0.14.0**
pytz                   2023.3.post1
qrcode                 7.4.2
relatorio              0.10.1
reportlab              3.6.13
setuptools             68.2.2
six                    1.16.0
SQLAlchemy             2.0.22
toml                   0.10.2
typing_extensions      4.8.0
unoserver              1.6
virtualenv             20.24.5
Werkzeug               2.3.7
zipp                   3.17.0

@rpfaff
Copy link

rpfaff commented Oct 23, 2023

I'm getting similar results writing a Code128 barcode to PNG. I've tested these version combinations:

python-barcode   |   Pillow   |   Result
0.13.0           |    8.0.1   |    OK (old prod environment)
0.14.0           |    9.5.0   |    OK
0.14.0           |    10.0.1  |    Error
0.14.0           |    10.1.0  |    Error
0.15.1           |    9.5.0   |    OK
0.15.1           |    10.0.1  |    Error
0.15.1           |    10.1.0  |    Error

Here's the error (this one is python-barcode 0.15.1 and Pilllow 10.1.0, but the traceback is the same):

Code:

# Init bar code writer and create temp barcode image file.
bar_code = barcode.get_barcode_class('code128')
bar_code.default_writer_options['font_size'] = 0
bar_code.default_writer_options['module_width'] = 0.8
bar_code.default_writer_options['module_height'] = 18
bar_code.default_writer_options['quiet_zone'] = 1

image = bar_code(
    order.public_name if order.public_name else order.id_num,
    writer=ImageWriter()
)

barcode_image = image.save(os.getcwd() + '/bc-' + str(counter))


Error:

OSError                                   Traceback (most recent call last)
File ~/code/PackingSlip/flaskslip/lib/python3.10/site-packages/PIL/ImageFont.py:797, in truetype(font, size, index, encoding, layout_engine)
    796 try:
--> 797     return freetype(font)
    798 except OSError:

File ~/code/PackingSlip/flaskslip/lib/python3.10/site-packages/PIL/ImageFont.py:794, in truetype.<locals>.freetype(font)
    793 def freetype(font):
--> 794     return FreeTypeFont(font, size, index, encoding, layout_engine)

File ~/code/PackingSlip/flaskslip/lib/python3.10/site-packages/PIL/ImageFont.py:226, in FreeTypeFont.__init__(self, font, size, index, encoding, layout_engine)
    225             return
--> 226     self.font = core.getfont(
    227         font, size, index, encoding, layout_engine=layout_engine
    228     )
    229 else:

OSError: invalid ppem value

During handling of the above exception, another exception occurred:

OSError                                   Traceback (most recent call last)
Cell In[27], line 1
----> 1 counter = pdf.order_info_block(doc, order, counter, font, ft_sz)

File ~/code/PackingSlip/flaskslip/pstest/Orders/pdf.py:172, in order_info_block(doc, order, counter, font, ft_sz)
    170 else:
    171     image = bar_code(order.id_num, writer=ImageWriter())
--> 172 barcode_image = image.save(os.getcwd() + '/bc-' + str(counter))
    173 counter += 1
    175 # Insert Barcode and Logo to page.

File ~/code/PackingSlip/flaskslip/lib/python3.10/site-packages/barcode/base.py:64, in Barcode.save(self, filename, options, text)
     53 def save(
     54     self, filename: str, options: Optional[dict] = None, text: Optional[str] = None
     55 ) -> str:
     56     """Renders the barcode and saves it in `filename`.
     57 
     58     :param filename: Filename to save the barcode in (without filename extension).
   (...)
     62     :returns: The full filename with extension.
     63     """
---> 64     output = self.render(options, text) if text else self.render(options)
     66     return self.writer.save(filename, output)

File ~/code/PackingSlip/flaskslip/lib/python3.10/site-packages/barcode/codex.py:255, in Code128.render(self, writer_options, text)
    253 options = {"module_width": MIN_SIZE, "quiet_zone": MIN_QUIET_ZONE}
    254 options.update(writer_options or {})
--> 255 return super().render(options, text)

File ~/code/PackingSlip/flaskslip/lib/python3.10/site-packages/barcode/base.py:100, in Barcode.render(self, writer_options, text)
     98 self.writer.set_options(options)
     99 code = self.build()
--> 100 return self.writer.render(code)

File ~/code/PackingSlip/flaskslip/lib/python3.10/site-packages/barcode/writer.py:269, in BaseWriter.render(self, code)
    267     ypos += self.text_distance
    268     xpos = bxs + (bxe - bxs) / 2.0 if self.center_text else bxs
--> 269     self._callbacks["paint_text"](xpos, ypos)
    270 else:
    271     # Else, divide the ean into blocks and print each block
    272     # in the expected position.
    273     text["xpos"] = [bxs - 4 * self.module_width]

File ~/code/PackingSlip/flaskslip/lib/python3.10/site-packages/barcode/writer.py:440, in ImageWriter._paint_text(self, xpos, ypos)
    438 def _paint_text(self, xpos, ypos):
    439     font_size = int(mm2px(pt2mm(self.font_size), self.dpi))
--> 440     font = ImageFont.truetype(self.font_path, font_size)
    441     for subtext in self.text.split("\n"):
    442         pos = (
    443             mm2px(xpos, self.dpi),
    444             mm2px(ypos, self.dpi),
    445         )

File ~/code/PackingSlip/flaskslip/lib/python3.10/site-packages/PIL/ImageFont.py:831, in truetype(font, size, index, encoding, layout_engine)
    829 for walkfilename in walkfilenames:
    830     if ext and walkfilename == ttf_filename:
--> 831         return freetype(os.path.join(walkroot, walkfilename))
    832     elif not ext and os.path.splitext(walkfilename)[0] == ttf_filename:
    833         fontpath = os.path.join(walkroot, walkfilename)

File ~/code/PackingSlip/flaskslip/lib/python3.10/site-packages/PIL/ImageFont.py:794, in truetype.<locals>.freetype(font)
    793 def freetype(font):
--> 794     return FreeTypeFont(font, size, index, encoding, layout_engine)

File ~/code/PackingSlip/flaskslip/lib/python3.10/site-packages/PIL/ImageFont.py:226, in FreeTypeFont.__init__(self, font, size, index, encoding, layout_engine)
    224                 load_from_bytes(f)
    225             return
--> 226     self.font = core.getfont(
    227         font, size, index, encoding, layout_engine=layout_engine
    228     )
    229 else:
    230     load_from_bytes(font)

OSError: invalid ppem value

@WhyNotHugo
Copy link
Owner

  • pillow-9.5.0 works
  • pillow-10.0.0 doesn't

I don't see anything specific in the changelog: https://pillow.readthedocs.io/en/stable/releasenotes/10.0.0.html

The documentation for the function that we're using doesn't specify if font_size=0 is valid: https://pillow.readthedocs.io/en/stable/reference/ImageFont.html#PIL.ImageFont.truetype

I think that the correct fix here is to update writer.py. If the provided font size is zero, skip rendering the text altogether.

@WhyNotHugo WhyNotHugo added bug contributions welcome Further design discussions and PRs are welcome. labels Oct 23, 2023
akx added a commit to akx/python-barcode that referenced this issue Nov 28, 2023
@akx
Copy link
Contributor

akx commented Nov 28, 2023

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug contributions welcome Further design discussions and PRs are welcome.
Projects
None yet
Development

No branches or pull requests

4 participants