Merge branch 'capabilities' into text-encoding
This commit is contained in:
commit
f6ce7e45da
|
@ -34,3 +34,7 @@ before_install:
|
|||
script:
|
||||
- tox
|
||||
- codecov
|
||||
notifications:
|
||||
email:
|
||||
on_success: never
|
||||
on_failure: change
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
*********
|
||||
Changelog
|
||||
*********
|
||||
2016-08-?? - Version 2.?.? - "Death and Gravity"
|
||||
|
||||
2016-08-?? - Version 2.?.? - "?"
|
||||
------------------------------------------------
|
||||
|
||||
changes
|
||||
|
@ -14,6 +15,32 @@ contributors
|
|||
- Patrick Kanzler (with code by Frédéric Van der Essen)
|
||||
|
||||
|
||||
2016-08-10 - Version 2.1.3 - "Ethics Gradient"
|
||||
----------------------------------------------
|
||||
|
||||
changes
|
||||
^^^^^^^
|
||||
- configure readthedocs and travis
|
||||
- update doc with hint on image preprocessing
|
||||
- add fix for printing large images (by splitting them into multiple images)
|
||||
|
||||
contributors
|
||||
^^^^^^^^^^^^
|
||||
- Patrick Kanzler
|
||||
|
||||
2016-08-02 - Version 2.1.2 - "Death and Gravity"
|
||||
------------------------------------------------
|
||||
|
||||
changes
|
||||
^^^^^^^
|
||||
- fix File-printer: flush after every call of _raw()
|
||||
- fix lists in documentation
|
||||
- fix CODE128: by adding the control character to the barcode-selection-sequence the barcode became unusable
|
||||
|
||||
contributors
|
||||
^^^^^^^^^^^^
|
||||
- Patrick Kanzler
|
||||
|
||||
2016-08-02 - Version 2.1.1 - "Contents May Differ"
|
||||
--------------------------------------------------
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@ Content
|
|||
user/raspi
|
||||
user/todo
|
||||
user/usage
|
||||
user/barcode
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
Printing Barcodes
|
||||
-----------------
|
||||
:Last Reviewed: 2016-07-31
|
||||
|
||||
Most ESC/POS-printers implement barcode-printing.
|
||||
The barcode-commandset is implemented in the barcode-method.
|
||||
For a list of compatible barcodes you should check the manual of your printer.
|
||||
As a rule of thumb: even older Epson-models support most 1D-barcodes.
|
||||
To be sure just try some implementations and have a look at the notices below.
|
||||
|
||||
barcode-method
|
||||
~~~~~~~~~~~~~~
|
||||
The barcode-method is rather low-level and orients itself on the implementation of ESC/POS.
|
||||
In the future this class could be supplemented by a high-level class that helps the user generating the payload.
|
||||
|
||||
.. py:currentmodule:: escpos.escpos
|
||||
|
||||
.. automethod:: Escpos.barcode
|
||||
:noindex:
|
||||
|
||||
CODE128
|
||||
~~~~~~~
|
||||
Code128 barcodes need a certain format.
|
||||
For now the user has to make sure that the payload is correct.
|
||||
For alphanumeric CODE128 you have to preface your payload with `{B`.
|
||||
|
||||
.. code-block:: Python
|
||||
|
||||
from escpos.printer import Dummy, Serial
|
||||
p = Serial()
|
||||
# print CODE128 012ABCDabcd
|
||||
p.barcode("{B012ABCDabcd", "CODE128", function_type="B")
|
||||
|
||||
A very good description on CODE128 is also on `Wikipedia <https://en.wikipedia.org/wiki/Code_128>`_.
|
|
@ -218,3 +218,34 @@ Here you can download an example, that will print a set of common barcodes:
|
|||
|
||||
* :download:`barcode.bin </download/barcode.bin>` by `@mike42 <https://github.com/mike42>`_
|
||||
|
||||
Hint: preprocess printing
|
||||
-------------------------
|
||||
|
||||
Printing images directly to the printer is rather slow.
|
||||
One factor that slows down the process is the transmission over e.g. serial port.
|
||||
|
||||
Apart from configuring your printer to use the maximum baudrate (in the case of serial-printers), there is not much
|
||||
that you can do.
|
||||
However you could use the :py:class:`escpos.printer.Dummy`-printer to preprocess your image.
|
||||
This is probably best explained by an example:
|
||||
|
||||
.. code-block:: Python
|
||||
|
||||
from escpos.printer import Serial, Dummy
|
||||
|
||||
p = Serial()
|
||||
d = Dummy()
|
||||
|
||||
# create ESC/POS for the print job, this should go really fast
|
||||
d.text("This is my image:\n")
|
||||
d.image("funny_cat.png")
|
||||
d.cut()
|
||||
|
||||
# send code to printer
|
||||
p._raw(d.output)
|
||||
|
||||
This way you could also store the code in a file and print later.
|
||||
You could then for example print the code from another process than your main-program and thus reduce the waiting time.
|
||||
(Of course this will not make the printer print faster.)
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
formats:
|
||||
- pdf
|
||||
- epub
|
||||
requirements_file: doc/requirements.txt
|
||||
python:
|
||||
version: 2
|
||||
setup_py_install: true
|
|
@ -0,0 +1,83 @@
|
|||
import re
|
||||
from os import path
|
||||
import yaml
|
||||
|
||||
|
||||
with open(path.join(path.dirname(__file__), 'capabilities.yml')) as f:
|
||||
PROFILES = yaml.load(f)
|
||||
|
||||
|
||||
class Profile(object):
|
||||
|
||||
profile_data = {}
|
||||
|
||||
def __init__(self, columns=None):
|
||||
self.default_columns = columns
|
||||
|
||||
def __getattr__(self, name):
|
||||
return self.profile_data[name]
|
||||
|
||||
def get_columns(self, font):
|
||||
""" Return the number of columns for the given font.
|
||||
"""
|
||||
if self.default_columns:
|
||||
return self.default_columns
|
||||
|
||||
if 'columnConfigs' in self.profile_data:
|
||||
columns_def = self.columnConfigs[self.defaultColumnConfig]
|
||||
|
||||
elif 'columns' in self.profile_data:
|
||||
columns_def = self.columns
|
||||
|
||||
if isinstance(columns_def, int):
|
||||
return columns_def
|
||||
return columns_def[font]
|
||||
|
||||
|
||||
def get_profile(name=None, **kwargs):
|
||||
if isinstance(name, Profile):
|
||||
return name
|
||||
|
||||
clazz = get_profile_class(name or 'default')
|
||||
return clazz(**kwargs)
|
||||
|
||||
|
||||
|
||||
CLASS_CACHE = {}
|
||||
|
||||
|
||||
def get_profile_class(name):
|
||||
if not name in CLASS_CACHE:
|
||||
profile_data = resolve_profile_data(name)
|
||||
class_name = '%sProfile' % clean(name)
|
||||
new_class = type(class_name, (Profile,), {'profile_data': profile_data})
|
||||
CLASS_CACHE[name] = new_class
|
||||
|
||||
return CLASS_CACHE[name]
|
||||
|
||||
|
||||
def clean(s):
|
||||
# Remove invalid characters
|
||||
s = re.sub('[^0-9a-zA-Z_]', '', s)
|
||||
# Remove leading characters until we find a letter or underscore
|
||||
s = re.sub('^[^a-zA-Z_]+', '', s)
|
||||
return str(s)
|
||||
|
||||
|
||||
def resolve_profile_data(name):
|
||||
data = PROFILES[name]
|
||||
inherits = data.get('inherits')
|
||||
if not inherits:
|
||||
return data
|
||||
|
||||
if not isinstance(inherits, (tuple, list)):
|
||||
inherits = [inherits]
|
||||
|
||||
merged = {}
|
||||
for base in reversed(inherits):
|
||||
base_data = resolve_profile_data(base)
|
||||
merged.update(base_data)
|
||||
merged.update(data)
|
||||
return merged
|
||||
|
||||
|
|
@ -0,0 +1,207 @@
|
|||
# Description of the format
|
||||
abstract:
|
||||
# Defines non-standard code pages that the printer supports, but
|
||||
# that we won't find in Python's encoding system. If you define one
|
||||
# here, don't forget to add it to codePageMap to assign it to a slot.
|
||||
customCodePages:
|
||||
sample:
|
||||
|
||||
# This maps the indexed code page slots to code page names.
|
||||
# Often, the slot assignment is the same, but the device only
|
||||
# supports a subset.
|
||||
codePageMap:
|
||||
0: "CP437"
|
||||
1: "CP932"
|
||||
3: "sample"
|
||||
|
||||
# Maybe not all of the codepages in the map are supported. This
|
||||
# is for subprofiles to select which ones the device knows.
|
||||
codePages: [sample, cp932]
|
||||
|
||||
|
||||
# Many recent Epson-branded thermal receipt printers.
|
||||
default:
|
||||
columns: 42
|
||||
|
||||
barcodeB: true
|
||||
bitImage: true
|
||||
graphics: true
|
||||
starCommands: false
|
||||
qrCode: true
|
||||
|
||||
customCodePages:
|
||||
TCVN-3-1: [
|
||||
" ",
|
||||
" ",
|
||||
" ăâêôơưđ ",
|
||||
" àảãáạ ằẳẵắ ",
|
||||
" ặầẩẫấậè ẻẽ",
|
||||
"éẹềểễếệìỉ ĩíịò",
|
||||
" ỏõóọồổỗốộờởỡớợù",
|
||||
" ủũúụừửữứựỳỷỹýỵ ",
|
||||
]
|
||||
TCVN-3-2: [
|
||||
" ",
|
||||
" ",
|
||||
" ĂÂ Ð ÊÔƠƯ ",
|
||||
" ÀẢÃÁẠ ẰẲẴẮ ",
|
||||
" ẶẦẨẪẤẬÈ ẺẼ",
|
||||
"ÉẸỀỂỄẾỆÌỈ ĨÍỊÒ",
|
||||
" ỎÕÓỌỒỔỖỐỘỜỞỠỚỢÙ",
|
||||
" ỦŨÚỤỪỬỮỨỰỲỶỸÝỴ "
|
||||
]
|
||||
|
||||
|
||||
# Commented-out slots are TODO (might just need uncomment, might
|
||||
# need verification/research)
|
||||
codePageMap:
|
||||
0: "CP437"
|
||||
1: "CP932"
|
||||
2: "CP850"
|
||||
3: "CP860"
|
||||
4: "CP863"
|
||||
5: "CP865"
|
||||
#6: // Hiragana
|
||||
#7: // One-pass printing Kanji characters
|
||||
#8: // Page 8 [One-pass printing Kanji characters]
|
||||
11: "CP851"
|
||||
12: "CP853"
|
||||
13: "CP857"
|
||||
14: "CP737"
|
||||
15: "ISO8859_7"
|
||||
16: "CP1252"
|
||||
17: "CP866"
|
||||
18: "CP852"
|
||||
19: "CP858"
|
||||
#20: // Thai Character Code 42
|
||||
#21: // Thai Character Code 1"
|
||||
#22: // Thai Character Code 13
|
||||
#23: // Thai Character Code 14
|
||||
#24: // Thai Character Code 16
|
||||
#25: // Thai Character Code 17
|
||||
#26: // Thai Character Code 18
|
||||
30: 'TCVN-3-1', # TCVN-3: Vietnamese
|
||||
31: 'TCVN-3-2', # TCVN-3: Vietnamese
|
||||
32: "CP720"
|
||||
33: "CP775"
|
||||
34: "CP855"
|
||||
35: "CP861"
|
||||
36: "CP862"
|
||||
37: "CP864"
|
||||
38: "CP869"
|
||||
39: "ISO8859_2"
|
||||
40: "ISO8859_15"
|
||||
41: "CP1098"
|
||||
42: "CP774"
|
||||
43: "CP772"
|
||||
44: "CP1125"
|
||||
45: "CP1250"
|
||||
46: "CP1251"
|
||||
47: "CP1253"
|
||||
48: "CP1254"
|
||||
49: "CP1255"
|
||||
50: "CP1256"
|
||||
51: "CP1257"
|
||||
52: "CP1258"
|
||||
53: "RK1048"
|
||||
#66: // Devanagari
|
||||
#67: // Bengali
|
||||
#68: // Tamil
|
||||
#69: // Telugu
|
||||
#70: // Assamese
|
||||
#71: // Oriya
|
||||
#72: // Kannada
|
||||
#73: // Malayalam
|
||||
#74: // Gujarati
|
||||
#75: // Punjabi
|
||||
#82: // Marathi
|
||||
#254:
|
||||
#255:
|
||||
|
||||
|
||||
# Designed for non-Epson printers sold online. Without knowing
|
||||
# their character encoding table, only CP437 output is assumed,
|
||||
# and graphics() calls will be disabled, as it usually prints junk
|
||||
# on these models.
|
||||
simple:
|
||||
codePages:
|
||||
- cp437
|
||||
graphics: false
|
||||
|
||||
|
||||
# Profile for Star-branded printers.
|
||||
star:
|
||||
inherits: default
|
||||
starCommands: true
|
||||
|
||||
|
||||
epson:
|
||||
inherits: default
|
||||
manufacturer: "Epson"
|
||||
|
||||
|
||||
"P-822D":
|
||||
inherits: default
|
||||
graphics: false
|
||||
|
||||
|
||||
# http://support.epostraders.co.uk/support-files/documents/3/l7O-TM-T88II_TechnicalRefGuide.pdf
|
||||
"TM-T88II":
|
||||
inherits: epson
|
||||
columns:
|
||||
a: 42
|
||||
b: 56
|
||||
codePages:
|
||||
- PC437 # 0
|
||||
- Katakana # 1
|
||||
- PC850 # 2
|
||||
- PC860 # 3
|
||||
- PC863 # 4
|
||||
- PC865 # 5
|
||||
- PC858 # 19
|
||||
- blank
|
||||
|
||||
# http://support.epostraders.co.uk/support-files/documents/3/l7O-TM-T88II_TechnicalRefGuide.pdf
|
||||
"TM-T88III":
|
||||
inherits: epson
|
||||
columns:
|
||||
a: 42
|
||||
b: 56
|
||||
codePages:
|
||||
- PC437 # 0
|
||||
- Katakana # 1
|
||||
- PC850 # 2
|
||||
- PC860 # 3
|
||||
- PC863 # 4
|
||||
- PC865 # 5
|
||||
- WPC1252 # 16
|
||||
- PC866 # 17
|
||||
- PC852 # 18
|
||||
- PC858 # 19
|
||||
- blank
|
||||
|
||||
|
||||
"TM-P80":
|
||||
inherits: epson
|
||||
defaultColumnConfig: default
|
||||
columnConfigs:
|
||||
default: {'a': 48, 'b': 64, 'kanji': 24}
|
||||
'42_emulation': {'a': 42, 'b': 60, 'kanji': 21}
|
||||
|
||||
|
||||
"TM-P60II 2":
|
||||
inherits: epson
|
||||
columnConfigs:
|
||||
'58mm_paper': {'a': 35, 'b': 42, 'c': 52}
|
||||
'60mm_paper': {'a': 36, 'b': 43, 'c': 54}
|
||||
|
||||
|
||||
"TM-P20 2":
|
||||
inherits: epson
|
||||
# Has 5 fonts!
|
||||
|
||||
"TM-T90":
|
||||
inherits: epson
|
||||
colors:
|
||||
- black
|
||||
- red
|
|
@ -240,10 +240,7 @@ BARCODE_TYPE_B = {
|
|||
'NW7': _SET_BARCODE_TYPE(71),
|
||||
'CODABAR': _SET_BARCODE_TYPE(71), # Same as NW7
|
||||
'CODE93': _SET_BARCODE_TYPE(72),
|
||||
# These are all the same barcode, but using different charcter sets
|
||||
'CODE128A': _SET_BARCODE_TYPE(73) + b'{A', # CODE128 character set A
|
||||
'CODE128B': _SET_BARCODE_TYPE(73) + b'{B', # CODE128 character set B
|
||||
'CODE128C': _SET_BARCODE_TYPE(73) + b'{C', # CODE128 character set C
|
||||
'CODE128': _SET_BARCODE_TYPE(73),
|
||||
'GS1-128': _SET_BARCODE_TYPE(74),
|
||||
'GS1 DATABAR OMNIDIRECTIONAL': _SET_BARCODE_TYPE(75),
|
||||
'GS1 DATABAR TRUNCATED': _SET_BARCODE_TYPE(76),
|
||||
|
|
|
@ -24,6 +24,7 @@ from .magicencode import MagicEncode
|
|||
|
||||
from abc import ABCMeta, abstractmethod # abstract base class support
|
||||
from escpos.image import EscposImage
|
||||
from escpos.capabilities import get_profile
|
||||
|
||||
|
||||
@six.add_metaclass(ABCMeta)
|
||||
|
@ -35,11 +36,11 @@ class Escpos(object):
|
|||
"""
|
||||
device = None
|
||||
|
||||
def __init__(self, columns=32, **kwargs):
|
||||
def __init__(self, profile=None, **kwargs):
|
||||
""" Initialize ESCPOS Printer
|
||||
|
||||
:param columns: Text columns used by the printer. Defaults to 32."""
|
||||
self.columns = columns
|
||||
:param profile: Printer profile"""
|
||||
self.profile = get_profile(profile)
|
||||
self.magic = MagicEncode(**kwargs)
|
||||
|
||||
def __del__(self):
|
||||
|
@ -57,7 +58,8 @@ class Escpos(object):
|
|||
"""
|
||||
pass
|
||||
|
||||
def image(self, img_source, high_density_vertical=True, high_density_horizontal=True, impl="bitImageRaster"):
|
||||
def image(self, img_source, high_density_vertical=True, high_density_horizontal=True, impl="bitImageRaster",
|
||||
fragment_height=1024):
|
||||
""" Print an image
|
||||
|
||||
You can select whether the printer should print in high density or not. The default value is high density.
|
||||
|
@ -77,9 +79,20 @@ class Escpos(object):
|
|||
:param high_density_vertical: print in high density in vertical direction *default:* True
|
||||
:param high_density_horizontal: print in high density in horizontal direction *default:* True
|
||||
:param impl: choose image printing mode between `bitImageRaster`, `graphics` or `bitImageColumn`
|
||||
:param fragment_height: Images larger than this will be split into multiple fragments *default:* 1024
|
||||
|
||||
"""
|
||||
im = EscposImage(img_source)
|
||||
|
||||
if im.height > fragment_height:
|
||||
fragments = im.split(fragment_height)
|
||||
for fragment in fragments:
|
||||
self.image(fragment,
|
||||
high_density_vertical=high_density_vertical,
|
||||
high_density_horizontal=high_density_horizontal,
|
||||
impl=impl,
|
||||
fragment_height=fragment_height)
|
||||
return
|
||||
|
||||
if impl == "bitImageRaster":
|
||||
# GS v 0, raster format bit image
|
||||
|
@ -362,7 +375,7 @@ class Escpos(object):
|
|||
txt = six.text_type(txt)
|
||||
self._raw(self.magic.encode_text(txt=txt))
|
||||
|
||||
def block_text(self, txt, columns=None):
|
||||
def block_text(self, txt, font=None, columns=None):
|
||||
""" Text is printed wrapped to specified columns
|
||||
|
||||
Text has to be encoded in unicode.
|
||||
|
@ -371,7 +384,7 @@ class Escpos(object):
|
|||
:param columns: amount of columns
|
||||
:return: None
|
||||
"""
|
||||
col_count = self.columns if columns is None else columns
|
||||
col_count = self.profile.get_columns(font) if columns is None else columns
|
||||
self.text(textwrap.fill(txt, col_count))
|
||||
|
||||
def set(self, align='left', font='a', text_type='normal', width=1, height=1, density=9, invert=False, smooth=False,
|
||||
|
|
|
@ -8,6 +8,12 @@ This module contains the image format handler :py:class:`EscposImage`.
|
|||
:license: GNU GPL v3
|
||||
"""
|
||||
|
||||
from __future__ import absolute_import
|
||||
from __future__ import division
|
||||
from __future__ import print_function
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import math
|
||||
from PIL import Image, ImageOps
|
||||
|
||||
|
||||
|
@ -30,6 +36,9 @@ class EscposImage(object):
|
|||
else:
|
||||
img_original = Image.open(img_source)
|
||||
|
||||
# store image for eventual further processing (splitting)
|
||||
self.img_original = img_original
|
||||
|
||||
# Convert to white RGB background, paste over white background
|
||||
# to strip alpha.
|
||||
img_original = img_original.convert('RGBA')
|
||||
|
@ -88,3 +97,21 @@ class EscposImage(object):
|
|||
Convert image to raster-format binary
|
||||
"""
|
||||
return self._im.tobytes()
|
||||
|
||||
def split(self, fragment_height):
|
||||
"""
|
||||
Split an image into multiple fragments after fragment_height pixels
|
||||
|
||||
:param fragment_height: height of fragment
|
||||
:return: list of PIL objects
|
||||
"""
|
||||
passes = int(math.ceil(self.height/fragment_height))
|
||||
fragments = []
|
||||
for n in range(0, passes):
|
||||
left = 0
|
||||
right = self.width
|
||||
upper = n * fragment_height
|
||||
lower = min((n + 1) * fragment_height, self.height)
|
||||
box = (left, upper, right, lower)
|
||||
fragments.append(self.img_original.crop(box))
|
||||
return fragments
|
||||
|
|
|
@ -130,3 +130,12 @@ def test_graphics_transparent():
|
|||
instance = printer.Dummy()
|
||||
instance.image('test/resources/black_transparent.png', impl="graphics")
|
||||
assert(instance.output == b'\x1d(L\x0c\x000p0\x01\x011\x02\x00\x02\x00\xc0\x00\x1d(L\x02\x0002')
|
||||
|
||||
|
||||
def test_large_graphics():
|
||||
"""
|
||||
Test whether 'large' graphics that induce a fragmentation are handled correctly.
|
||||
"""
|
||||
instance = printer.Dummy()
|
||||
instance.image('test/resources/black_white.png', impl="bitImageRaster", fragment_height=1)
|
||||
assert(instance.output == b'\x1dv0\x00\x01\x00\x01\x00\xc0\x1dv0\x00\x01\x00\x01\x00\x00')
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
"""tests for the non-native part of qr()
|
||||
|
||||
:author: `Patrick Kanzler <patrick.kanzler@fablab.fau.de>`_
|
||||
:organization: `python-escpos <https://github.com/python-escpos>`_
|
||||
:copyright: Copyright (c) 2016 `python-escpos <https://github.com/python-escpos>`_
|
||||
:license: GNU GPL v3
|
||||
"""
|
||||
|
||||
from __future__ import absolute_import
|
||||
from __future__ import division
|
||||
from __future__ import print_function
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import mock
|
||||
|
||||
from escpos.printer import Dummy
|
||||
from PIL import Image
|
||||
|
||||
|
||||
@mock.patch('escpos.printer.Dummy.image', spec=Dummy)
|
||||
def test_type_of_object_passed_to_image_function(img_function):
|
||||
"""
|
||||
Test the type of object that is passed to the image function during non-native qr-printing.
|
||||
|
||||
The type should be PIL.Image
|
||||
"""
|
||||
d = Dummy()
|
||||
d.qr("LoremIpsum")
|
||||
args, kwargs = img_function.call_args
|
||||
assert isinstance(args[0], Image.Image)
|
|
@ -15,9 +15,10 @@ from __future__ import unicode_literals
|
|||
import mock
|
||||
from hypothesis import given
|
||||
import hypothesis.strategies as st
|
||||
|
||||
from escpos.printer import Dummy
|
||||
import escpos.printer as printer
|
||||
|
||||
|
||||
@given(text=st.text())
|
||||
def test_function_text_dies_ist_ein_test_lf(text):
|
||||
"""test the text printing function with simple string and compare output"""
|
||||
|
@ -25,3 +26,11 @@ def test_function_text_dies_ist_ein_test_lf(text):
|
|||
instance.magic.encode_text = mock.Mock()
|
||||
instance.text(text)
|
||||
instance.magic.encode_text.assert_called_with(txt=text)
|
||||
|
||||
|
||||
def test_block_text():
|
||||
printer = Dummy()
|
||||
printer.block_text(
|
||||
"All the presidents men were eating falafel for breakfast.", font='a')
|
||||
assert printer.output == \
|
||||
'All the presidents men were eating falafel\nfor breakfast.'
|
||||
|
|
|
@ -43,6 +43,20 @@ def test_image_white():
|
|||
_load_and_check_img('canvas_white.' + img_format, 1, 1, b'\x00', [b'\x00'])
|
||||
|
||||
|
||||
def test_split():
|
||||
"""
|
||||
test whether the split-function works as expected
|
||||
"""
|
||||
im = EscposImage('test/resources/black_white.png')
|
||||
(upper_part, lower_part) = im.split(1)
|
||||
upper_part = EscposImage(upper_part)
|
||||
lower_part = EscposImage(lower_part)
|
||||
assert(upper_part.width == lower_part.width == 2)
|
||||
assert(upper_part.height == lower_part.height == 1)
|
||||
assert(upper_part.to_raster_format() == b'\xc0')
|
||||
assert(lower_part.to_raster_format() == b'\x00')
|
||||
|
||||
|
||||
def _load_and_check_img(filename, width_expected, height_expected, raster_format_expected, column_format_expected):
|
||||
"""
|
||||
Load an image, and test whether raster & column formatted output, sizes, etc match expectations.
|
||||
|
|
Loading…
Reference in New Issue