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

feat: add ability to set pdf image dpi #10

Merged
merged 3 commits into from
Jun 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ repos:
- id: mixed-line-ending
args: ["--fix=lf"]
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.4.5
rev: v0.4.10
hooks:
- id: ruff
args: [--fix]
Expand Down
3 changes: 3 additions & 0 deletions .ruff.toml
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
target-version = "py37"
fix = true
line-length = 88

[lint]
extend-select = [
"B", # flake8-bugbear
"C90", # mccabe
"I", # isort
"E501", # line too long
"UP", # pyupgrade
"D", # pydocstyle
]
Expand All @@ -14,6 +16,7 @@ ignore = ["D100", "D107", "D203", "D212"]

[format]
exclude = ["setup/*"]
docstring-code-format = true

[lint.per-file-ignores]
"__init__.py" = ["F401", "I001"] # ignore unused and unsorted imports in __init__.py
Expand Down
13 changes: 8 additions & 5 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -63,11 +63,13 @@ If you want more control over the resulting ZPL data, **ZebrafyImage** and

Additionally, **ZebrafyPDF** supports the following optional parameters:

+----------------------+--------------------------------------------------------------------------------------------------------------+
| Parameter | Description |
+======================+==============================================================================================================+
| ``split_pages`` | Split the PDF into separate ZPL labels for each page (``True`` or ``False``, default ``False``) |
+----------------------+--------------------------------------------------------------------------------------------------------------+
+----------------------+-----------------------------------------------------------------------------------------------------------------------+
| Parameter | Description |
+======================+=======================================================================================================================+
| ``dpi`` | Pixels per PDF canvas unit, defines resolution scaling of the PDF image (<72: compress, >72: stretch, default ``72``) |
+----------------------+-----------------------------------------------------------------------------------------------------------------------+
| ``split_pages`` | Split the PDF into separate ZPL labels for each page (``True`` or ``False``, default ``False``) |
+----------------------+-----------------------------------------------------------------------------------------------------------------------+


Getting Started
Expand Down Expand Up @@ -176,6 +178,7 @@ conversion, with the addition of the ``split_pages`` parameter to split the PDF
invert=True,
dither=False,
threshold=128,
dpi=72,
width=720,
height=1280,
pos_x=100,
Expand Down
13 changes: 8 additions & 5 deletions docs/usage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,13 @@ ZebrafyPDF and ZebrafyImage Parameters

Additionally, **ZebrafyPDF** supports the following optional parameters:

+----------------------+--------------------------------------------------------------------------------------------------------------+
| Parameter | Description |
+======================+==============================================================================================================+
| ``split_pages`` | Split the PDF into separate ZPL labels for each page (``True`` or ``False``, default ``False``) |
+----------------------+--------------------------------------------------------------------------------------------------------------+
+----------------------+-----------------------------------------------------------------------------------------------------------------------+
| Parameter | Description |
+======================+=======================================================================================================================+
| ``dpi`` | Pixels per PDF canvas unit, defines resolution scaling of the PDF image (<72: compress, >72: stretch, default ``72``) |
+----------------------+-----------------------------------------------------------------------------------------------------------------------+
| ``split_pages`` | Split the PDF into separate ZPL labels for each page (``True`` or ``False``, default ``False``) |
+----------------------+-----------------------------------------------------------------------------------------------------------------------+


Conversions
Expand Down Expand Up @@ -140,6 +142,7 @@ conversion, with the addition of the ``split_pages`` parameter to split the PDF
invert=True,
dither=False,
threshold=128,
dpi=72,
width=720,
height=1280,
pos_x=100,
Expand Down
4 changes: 4 additions & 0 deletions tests/static/test_pdf_high_dpi.zpl

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions tests/static/test_pdf_low_dpi.zpl

Large diffs are not rendered by default.

25 changes: 25 additions & 0 deletions tests/test_zebrafy.py
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,21 @@ def test_zebrafy_pdf_threshold(self):
with self.assertRaises(ValueError):
zebrafy_pdf.threshold = 256

def test_zebrafy_pdf_dpi(self):
"""Test ZebrafyPDF dpi input."""
pdf = self._read_static_file("test_pdf.pdf")
zebrafy_pdf = ZebrafyPDF(pdf)
with self.assertRaises(ValueError):
zebrafy_pdf.dpi = None
with self.assertRaises(TypeError):
zebrafy_pdf.dpi = "123"
with self.assertRaises(ValueError):
zebrafy_pdf.dpi = -1
with self.assertRaises(ValueError):
zebrafy_pdf.dpi = 0
with self.assertRaises(ValueError):
zebrafy_pdf.dpi = 721

def test_zebrafy_pdf_width(self):
"""Test ZebrafyPDF width input."""
pdf = self._read_static_file("test_pdf.pdf")
Expand Down Expand Up @@ -501,6 +516,16 @@ def test_pdf_to_zpl_threshold_high(self):
).to_zpl()
self.assertEqual(gf_zpl, self._read_static_file("test_pdf_high_threshold.zpl"))

def test_pdf_to_zpl_dpi_low(self):
"""Test PDF to ZPL with low DPI."""
gf_zpl = ZebrafyPDF(self._read_static_file("test_pdf.pdf"), dpi=36).to_zpl()
self.assertEqual(gf_zpl, self._read_static_file("test_pdf_low_dpi.zpl"))

def test_pdf_to_zpl_dpi_high(self):
"""Test PDF to ZPL with high DPI."""
gf_zpl = ZebrafyPDF(self._read_static_file("test_pdf.pdf"), dpi=144).to_zpl()
self.assertEqual(gf_zpl, self._read_static_file("test_pdf_high_dpi.zpl"))

def test_pdf_to_zpl_width_height(self):
"""Test PDF to ZPL with set width and height."""
gf_zpl = ZebrafyPDF(
Expand Down
6 changes: 3 additions & 3 deletions zebrafy/__init__.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
"""
zebrafy: A Python library for converting PDF and images to Zebra Programming Language (ZPL).
zebrafy: A Python library for converting PDF and images to Zebra Programming Language.
This package provides tools to facilitate the conversion of PDF documents and images into
and from Zebra Programming Language, which is used by Zebra label printers.
This package provides tools to facilitate the conversion of PDF documents and images \
into and from Zebra Programming Language, which is used by Zebra label printers.
"""

try:
Expand Down
5 changes: 4 additions & 1 deletion zebrafy/graphic_field.py
Original file line number Diff line number Diff line change
Expand Up @@ -174,4 +174,7 @@ def get_graphic_field(self) -> str:
:returns: Complete graphic field string for ZPL.
"""
return f"^GFA,{self._get_binary_byte_count()},{self._get_graphic_field_count()},{self._get_bytes_per_row()},{self._get_data_string()}^FS"
return (
f"^GFA,{self._get_binary_byte_count()},{self._get_graphic_field_count()},"
f"{self._get_bytes_per_row()},{self._get_data_string()}^FS"
)
25 changes: 24 additions & 1 deletion zebrafy/zebrafy_pdf.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ class ZebrafyPDF:
defaults to ``False``
:param threshold: Black pixel threshold for undithered PDF (``0-255``), defaults \
to ``128``
:param dpi: Pixels per PDF canvas unit. This defines the resolution scaling of the \
image (<72: compress, >72: stretch), defaults to ``72``
:param width: Width of the PDF in the resulting ZPL. If ``0``, use default PDF \
width, defaults to ``0``
:param height: Height of the PDF in the resulting ZPL. If ``0``, use default \
Expand All @@ -79,6 +81,7 @@ def __init__(
invert: bool = None,
dither: bool = None,
threshold: int = None,
dpi: int = None,
width: int = None,
height: int = None,
pos_x: int = None,
Expand All @@ -103,6 +106,9 @@ def __init__(
if threshold is None:
threshold = 128
self.threshold = threshold
if dpi is None:
dpi = 72
self.dpi = dpi
if width is None:
width = 0
self.width = width
Expand Down Expand Up @@ -179,6 +185,23 @@ def threshold(self, t):
raise ValueError(f"Threshold must be within 0 to 255. {t} was given.")
self._threshold = t

dpi = property(operator.attrgetter("_dpi"))

@dpi.setter
def dpi(self, t):
if t is None:
raise ValueError("DPI cannot be empty.")
if not isinstance(t, int):
raise TypeError(f"DPI must be an integer. {type(t)} was given.")
if t <= 0:
raise ValueError(f"DPI must be a positive value. {t} was given.")
if t > 720:
raise ValueError(
"DPI must be less than 720. It is recommended to stick to a maximum "
f"of 300 to avoid issues. {t} was given."
)
self._dpi = t

width = property(operator.attrgetter("_width"))

@width.setter
Expand Down Expand Up @@ -273,7 +296,7 @@ def to_zpl(self) -> str:
pdf = PdfDocument(self._pdf_bytes)
graphic_fields = []
for page in pdf:
bitmap = page.render(scale=1, rotation=self._rotation)
bitmap = page.render(scale=(self._dpi / 72), rotation=self._rotation)
pil_image = bitmap.to_pil()
zebrafy_image = ZebrafyImage(
pil_image,
Expand Down
2 changes: 1 addition & 1 deletion zebrafy/zebrafy_zpl.py
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ def to_pdf(self) -> bytes:
page.gen_content()

pdf_bytes = io.BytesIO()
# pypdfium2.PdfDocument save method not to be confused with PIL.Image save method
# pypdfium2.PdfDocument save method not to be confused with PIL.Image save
pdf.save(pdf_bytes)

return pdf_bytes.getvalue()