Skip to content

Commit

Permalink
[IMP] Rotation to ZebrafyImage
Browse files Browse the repository at this point in the history
Add rotation option to ZebrafyImage.
Write tests to cover rotation with ZebrafyImage and ZebrafyPDF.
  • Loading branch information
miikanissi committed May 16, 2024
1 parent 95774af commit 1da2000
Show file tree
Hide file tree
Showing 7 changed files with 116 additions and 32 deletions.
10 changes: 6 additions & 4 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ If you want more control over the resulting ZPL data, **ZebrafyImage** and
+----------------------+--------------------------------------------------------------------------------------------------------------+
| ``pos_y`` | Pixel y position of the graphic field in resulting ZPL (default ``0``) |
+----------------------+--------------------------------------------------------------------------------------------------------------+
| ``rotation`` | Rotates the image by the specified degree (``0``, ``90``, ``180`` or ``270``, default ``0``) |
+----------------------+--------------------------------------------------------------------------------------------------------------+
| ``complete_zpl`` | Add ZPL header and footer or only get the ZPL graphic field output (``True`` or ``False``, default ``True``) |
+----------------------+--------------------------------------------------------------------------------------------------------------+

Expand All @@ -66,9 +68,6 @@ Additionally, **ZebrafyPDF** supports the following optional parameters:
+======================+==============================================================================================================+
| ``split_pages`` | Split the PDF into separate ZPL labels for each page (``True`` or ``False``, default ``False``) |
+----------------------+--------------------------------------------------------------------------------------------------------------+
| ``rotation`` | Rotates the PDF by the specified degree (``0``, ``90``, ``180`` or ``270``, default ``0``) |
+----------------------+--------------------------------------------------------------------------------------------------------------+



Getting Started
Expand Down Expand Up @@ -126,6 +125,7 @@ Example usage with optional parameters:
height=1280,
pos_x=100,
pos_y=100,
rotation=90,
complete_zpl=True,
).to_zpl()
Expand Down Expand Up @@ -163,7 +163,7 @@ Convert PDF bytes into a complete ZPL string and save to file:
zpl.write(zpl_string)
**ZebrafyPDF** conversion supports the same optional parameters as **ZebrafyImage**
conversion:
conversion, with the addition of the ``split_pages`` parameter to split the PDF pages:

.. code-block:: python
Expand All @@ -180,7 +180,9 @@ conversion:
height=1280,
pos_x=100,
pos_y=100,
rotation=90,
complete_zpl=True,
split_pages=True,
).to_zpl()
with open("output.zpl", "w") as zpl:
Expand Down
9 changes: 6 additions & 3 deletions docs/usage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ ZebrafyPDF and ZebrafyImage Parameters
+----------------------+--------------------------------------------------------------------------------------------------------------+
| ``pos_y`` | Pixel y position of the graphic field in resulting ZPL (default ``0``) |
+----------------------+--------------------------------------------------------------------------------------------------------------+
| ``rotation`` | Rotates the image by the specified degree (``0``, ``90``, ``180`` or ``270``, default ``0``) |
+----------------------+--------------------------------------------------------------------------------------------------------------+
| ``complete_zpl`` | Add ZPL header and footer or only get the ZPL graphic field output (``True`` or ``False``, default ``True``) |
+----------------------+--------------------------------------------------------------------------------------------------------------+

Expand All @@ -50,8 +52,6 @@ Additionally, **ZebrafyPDF** supports the following optional parameters:
+======================+==============================================================================================================+
| ``split_pages`` | Split the PDF into separate ZPL labels for each page (``True`` or ``False``, default ``False``) |
+----------------------+--------------------------------------------------------------------------------------------------------------+
| ``rotation`` | Rotates the PDF by the specified degree (``0``, ``90``, ``180`` or ``270``, default ``0``) |
+----------------------+--------------------------------------------------------------------------------------------------------------+


Conversions
Expand Down Expand Up @@ -89,6 +89,7 @@ Example usage with optional parameters:
height=1280,
pos_x=100,
pos_y=100,
rotation=90,
complete_zpl=True,
).to_zpl()
Expand Down Expand Up @@ -126,7 +127,7 @@ Convert PDF bytes into a complete ZPL string and save to file:
zpl.write(zpl_string)
**ZebrafyPDF** conversion supports the same optional parameters as **ZebrafyImage**
conversion:
conversion, with the addition of the ``split_pages`` parameter to split the PDF pages:

.. code-block:: python
Expand All @@ -143,7 +144,9 @@ conversion:
height=1280,
pos_x=100,
pos_y=100,
rotation=90,
complete_zpl=True,
split_pages=True,
).to_zpl()
with open("output.zpl", "w") as zpl:
Expand Down
3 changes: 3 additions & 0 deletions tests/static/test_image_rotation.zpl

Large diffs are not rendered by default.

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

Large diffs are not rendered by default.

40 changes: 40 additions & 0 deletions tests/test_zebrafy.py
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,19 @@ def test_zebrafy_image_pos_y(self):
with self.assertRaises(TypeError):
zebrafy_image.pos_y = "123"

def test_zebrafy_image_rotation(self):
"""Test ZebrafyImage rotation input"""
im = Image.new(mode="RGB", size=(200, 200))
zebrafy_image = ZebrafyImage(im)
with self.assertRaises(ValueError):
zebrafy_image.rotation = None
with self.assertRaises(TypeError):
zebrafy_image.rotation = "123"
with self.assertRaises(TypeError):
zebrafy_image.rotation = 90.0
with self.assertRaises(ValueError):
zebrafy_image.rotation = 45

def test_zebrafy_image_complete_zpl(self):
"""Test ZebrafyImage complete_zpl input"""
im = Image.new(mode="RGB", size=(200, 200))
Expand Down Expand Up @@ -284,6 +297,13 @@ def test_image_to_zpl_pos_x_pos_y(self):
).to_zpl()
self.assertEqual(gf_zpl, self._read_static_file("test_image_pos_x_pos_y.zpl"))

def test_image_to_zpl_rotation(self):
"""Test image to ZPL with rotation."""
gf_zpl = ZebrafyImage(
self._read_static_file("test_image.png"), rotation=90
).to_zpl()
self.assertEqual(gf_zpl, self._read_static_file("test_image_rotation.zpl"))

def test_multiple_image_to_zpl(self):
"""Test multiple images to ZPL with default options."""
gf_zpl = ZebrafyImage(
Expand Down Expand Up @@ -393,6 +413,19 @@ def test_zebrafy_pdf_pos_y(self):
with self.assertRaises(TypeError):
zebrafy_pdf.pos_y = "123"

def test_zebrafy_pdf_rotation(self):
"""Test ZebrafyPDF rotation"""
pdf = self._read_static_file("test_pdf.pdf")
zebrafy_pdf = ZebrafyPDF(pdf)
with self.assertRaises(ValueError):
zebrafy_pdf.rotation = None
with self.assertRaises(TypeError):
zebrafy_pdf.rotation = "123"
with self.assertRaises(TypeError):
zebrafy_pdf.rotation = 90.0
with self.assertRaises(ValueError):
zebrafy_pdf.rotation = 45

def test_zebrafy_pdf_complete_zpl(self):
"""Test ZebrafyPDF complete_zpl input"""
pdf = self._read_static_file("test_pdf.pdf")
Expand Down Expand Up @@ -465,6 +498,13 @@ def test_pdf_to_zpl_width_height(self):
).to_zpl()
self.assertEqual(gf_zpl, self._read_static_file("test_pdf_width_height.zpl"))

def test_pdf_to_zpl_rotation(self):
"""Test PDF to ZPL with rotation."""
gf_zpl = ZebrafyPDF(
self._read_static_file("test_pdf.pdf"), rotation=90
).to_zpl()
self.assertEqual(gf_zpl, self._read_static_file("test_pdf_rotation.zpl"))

def test_pdf_to_zpl_split_pages(self):
"""Test PDF to ZPL with split pages."""
gf_zpl = ZebrafyPDF(
Expand Down
30 changes: 30 additions & 0 deletions zebrafy/zebrafy_image.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ class ZebrafyImage:
image height, defaults to ``0``
:param pos_x: X position of the image on the resulting ZPL, defaults to ``0``
:param pos_y: Y position of the image on the resulting ZPL, defaults to ``0``
:param rotation: Additional rotation in degrees ``0``, ``90``, ``180``, or \
``270``, defaults to ``0``
:param complete_zpl: Return a complete ZPL with header and footer included. \
Otherwise return only the graphic field, defaults to ``True``
Expand All @@ -82,6 +84,7 @@ def __init__(
height: int = None,
pos_x: int = None,
pos_y: int = None,
rotation: int = None,
complete_zpl: bool = None,
):
self.image = image
Expand Down Expand Up @@ -112,6 +115,9 @@ def __init__(
if pos_y is None:
pos_y = 0
self.pos_y = pos_y
if rotation is None:
rotation = 0
self.rotation = rotation
if complete_zpl is None:
complete_zpl = True
self.complete_zpl = complete_zpl
Expand Down Expand Up @@ -251,6 +257,26 @@ def pos_y(self, y):
)
self._pos_y = y

rotation = property(operator.attrgetter("_rotation"))

@rotation.setter
def rotation(self, r):
if r is None:
raise ValueError("Rotation cannot be empty.")
if not isinstance(r, int):
raise TypeError(
"Rotation must be an integer. {param_type} was given.".format(
param_type=type(r)
)
)
if r not in [0, 90, 180, 270]:
raise ValueError(
'Rotation must be "0", "90", "180" or "270". {param} was given.'.format(
param=r
)
)
self._rotation = r

complete_zpl = property(operator.attrgetter("_complete_zpl"))

@complete_zpl.setter
Expand Down Expand Up @@ -288,6 +314,10 @@ def to_zpl(self) -> str:
else:
pil_image = self._image

# Rotate image based on given parameters
if self._rotation:
pil_image = pil_image.rotate(self._rotation, expand=False)

# Resize image if width or height defined in parameters
if self._width or self._height:
width, height = pil_image.size
Expand Down
52 changes: 27 additions & 25 deletions zebrafy/zebrafy_pdf.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,11 @@ class ZebrafyPDF:
PDF height, defaults to ``0``
:param pos_x: X position of the PDF on the resulting ZPL, defaults to ``0``
:param pos_y: Y position of the PDF on the resulting ZPL, defaults to ``0``
:param rotation: Additional rotation in degrees ``0``, ``90``, ``180``, or \
``270``, defaults to ``0``
:param split_pages: Split each PDF page as a new ZPL label \
(only applies if complete_zpl is set), defaults to ``False``
:param complete_zpl: Return a complete ZPL with header and footer included. \
:param rotation: Additional rotation in degrees ``0, 90, 180, or 270)`` \
Otherwise return only the graphic field, defaults to ``True``
.. deprecated:: 1.1.0
Expand All @@ -82,9 +83,9 @@ def __init__(
height: int = None,
pos_x: int = None,
pos_y: int = None,
rotation: int = None,
split_pages: bool = None,
complete_zpl: bool = None,
rotation: int = None,
):
self.pdf_bytes = pdf_bytes
if format is None:
Expand Down Expand Up @@ -114,15 +115,15 @@ def __init__(
if pos_y is None:
pos_y = 0
self.pos_y = pos_y
if rotation is None:
rotation = 0
self.rotation = rotation
if split_pages is None:
split_pages = False
self.split_pages = split_pages
if complete_zpl is None:
complete_zpl = True
self.complete_zpl = complete_zpl
if rotation is None:
rotation = 0
self.rotation = rotation

pdf_bytes = property(operator.attrgetter("_pdf_bytes"))

Expand Down Expand Up @@ -260,6 +261,26 @@ def pos_y(self, y):
)
self._pos_y = y

rotation = property(operator.attrgetter("_rotation"))

@rotation.setter
def rotation(self, r):
if r is None:
raise ValueError("Rotation cannot be empty.")
if not isinstance(r, int):
raise TypeError(
"Rotation must be an integer. {param_type} was given.".format(
param_type=type(r)
)
)
if r not in [0, 90, 180, 270]:
raise ValueError(
'Rotation must be "0", "90", "180" or "270". {param} was given.'.format(
param=r
)
)
self._rotation = r

split_pages = property(operator.attrgetter("_split_pages"))

@split_pages.setter
Expand Down Expand Up @@ -288,26 +309,6 @@ def complete_zpl(self, c):
)
self._complete_zpl = c

rotation = property(operator.attrgetter("_rotation"))

@rotation.setter
def rotation(self, r):
if r is None:
raise ValueError("Rotation cannot be empty.")
if not isinstance(r, int):
raise TypeError(
"Rotation must be an integer. {param_type} was given.".format(
param_type=type(r)
)
)
if r not in [0, 90, 180, 270]:
raise ValueError(
'Rotation must be "0", "90", "180" or "270". {param} was given.'.format(
param=r
)
)
self._rotation = r

def _compression_type_to_format(self, compression_type: str) -> str:
"""
Convert deprecated compression type to format.
Expand Down Expand Up @@ -342,6 +343,7 @@ def to_zpl(self) -> str:
height=self._height,
pos_x=self._pos_x,
pos_y=self._pos_y,
rotation=0, # Rotation is already handled in the PDF rendering
complete_zpl=False,
)

Expand Down

0 comments on commit 1da2000

Please sign in to comment.