Open aegleinformatiquemedicale opened 10 months ago
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
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
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
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.
FWIW: invalid ppem value
comes from FreeType in
https://github.com/freetype/freetype/blob/8f255c89e14219ca2489043f699797ee106ec6e9/include/freetype/fterrdef.h#L225-L226
and it's thrown here in
https://github.com/freetype/freetype/blob/8f255c89e14219ca2489043f699797ee106ec6e9/src/truetype/ttobjs.c#L1363-L1367
so the theory that passing in a size <= 0 causes this is very sound :)
Hi,
If i try this with python 3.9.16
With python-barcode 0140 and Pillow 9.5.0 => OK
With python-barcode 0.15.1 and Pillow 10.0.0 (same with 10.0.1) => ERR : invalid ppem value
I didn't see in your documentation what had changed.
Thanks