Merge pull request #94 from python-escpos/fix-image-printing
Fix problems with python 2 and 3
This commit is contained in:
commit
046cf1ff5b
|
@ -10,51 +10,58 @@ moved to `capabilities` as in `escpos-php by @mike42 <https://github.com/mike42/
|
||||||
:license: GNU GPL v3
|
:license: GNU GPL v3
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
from __future__ import absolute_import
|
||||||
|
from __future__ import division
|
||||||
|
from __future__ import print_function
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
import six
|
||||||
|
|
||||||
# Control characters
|
# Control characters
|
||||||
# as labelled in http://www.novopos.ch/client/EPSON/TM-T20/TM-T20_eng_qr.pdf
|
# as labelled in http://www.novopos.ch/client/EPSON/TM-T20/TM-T20_eng_qr.pdf
|
||||||
NUL = '\x00'
|
NUL = b'\x00'
|
||||||
EOT = '\x04'
|
EOT = b'\x04'
|
||||||
ENQ = '\x05'
|
ENQ = b'\x05'
|
||||||
DLE = '\x10'
|
DLE = b'\x10'
|
||||||
DC4 = '\x14'
|
DC4 = b'\x14'
|
||||||
CAN = '\x18'
|
CAN = b'\x18'
|
||||||
ESC = '\x1b'
|
ESC = b'\x1b'
|
||||||
FS = '\x1c'
|
FS = b'\x1c'
|
||||||
GS = '\x1d'
|
GS = b'\x1d'
|
||||||
|
|
||||||
# Feed control sequences
|
# Feed control sequences
|
||||||
CTL_LF = '\n' # Print and line feed
|
CTL_LF = b'\n' # Print and line feed
|
||||||
CTL_FF = '\f' # Form feed
|
CTL_FF = b'\f' # Form feed
|
||||||
CTL_CR = '\r' # Carriage return
|
CTL_CR = b'\r' # Carriage return
|
||||||
CTL_HT = '\t' # Horizontal tab
|
CTL_HT = b'\t' # Horizontal tab
|
||||||
CTL_SET_HT = ESC + '\x44' # Set horizontal tab positions
|
CTL_SET_HT = ESC + b'\x44' # Set horizontal tab positions
|
||||||
CTL_VT = '\v' # Vertical tab
|
CTL_VT = b'\v' # Vertical tab
|
||||||
|
|
||||||
# Printer hardware
|
# Printer hardware
|
||||||
HW_INIT = ESC + '@' # Clear data in buffer and reset modes
|
HW_INIT = ESC + b'@' # Clear data in buffer and reset modes
|
||||||
HW_SELECT = ESC + '=\x01' # Printer select
|
HW_SELECT = ESC + b'=\x01' # Printer select
|
||||||
|
|
||||||
HW_RESET = ESC + '\x3f\x0a\x00' # Reset printer hardware
|
HW_RESET = ESC + b'\x3f\x0a\x00' # Reset printer hardware
|
||||||
# (TODO: Where is this specified?)
|
# (TODO: Where is this specified?)
|
||||||
|
|
||||||
#{ Cash Drawer (ESC p <pin> <on time: 2*ms> <off time: 2*ms>)
|
#{ Cash Drawer (ESC p <pin> <on time: 2*ms> <off time: 2*ms>)
|
||||||
_CASH_DRAWER = lambda m, t1='', t2='': ESC + 'p' + m + chr(t1) + chr(t2)
|
_CASH_DRAWER = lambda m, t1='', t2='': ESC + b'p' + m + six.int2byte(t1) + six.int2byte(t2)
|
||||||
CD_KICK_2 = _CASH_DRAWER('\x00', 50, 50) # Sends a pulse to pin 2 []
|
CD_KICK_2 = _CASH_DRAWER(b'\x00', 50, 50) # Sends a pulse to pin 2 []
|
||||||
CD_KICK_5 = _CASH_DRAWER('\x01', 50, 50) # Sends a pulse to pin 5 []
|
CD_KICK_5 = _CASH_DRAWER(b'\x01', 50, 50) # Sends a pulse to pin 5 []
|
||||||
|
|
||||||
# Paper Cutter
|
# Paper Cutter
|
||||||
_CUT_PAPER = lambda m: GS + 'V' + m
|
_CUT_PAPER = lambda m: GS + b'V' + m
|
||||||
PAPER_FULL_CUT = _CUT_PAPER('\x00') # Full cut paper
|
PAPER_FULL_CUT = _CUT_PAPER(b'\x00') # Full cut paper
|
||||||
PAPER_PART_CUT = _CUT_PAPER('\x01') # Partial cut paper
|
PAPER_PART_CUT = _CUT_PAPER(b'\x01') # Partial cut paper
|
||||||
|
|
||||||
# Text format
|
# Text format
|
||||||
# TODO: Acquire the "ESC/POS Application Programming Guide for Paper Roll
|
# TODO: Acquire the "ESC/POS Application Programming Guide for Paper Roll
|
||||||
# Printers" and tidy up this stuff too.
|
# Printers" and tidy up this stuff too.
|
||||||
TXT_FLIP_ON = ESC + '\x7b\x01'
|
TXT_FLIP_ON = ESC + b'\x7b\x01'
|
||||||
TXT_FLIP_OFF = ESC + '\x7b\x00'
|
TXT_FLIP_OFF = ESC + b'\x7b\x00'
|
||||||
TXT_SMOOTH_ON = GS + '\x62\x01'
|
TXT_SMOOTH_ON = GS + b'\x62\x01'
|
||||||
TXT_SMOOTH_OFF = GS + '\x62\x00'
|
TXT_SMOOTH_OFF = GS + b'\x62\x00'
|
||||||
TXT_SIZE = GS + '!'
|
TXT_SIZE = GS + b'!'
|
||||||
TXT_WIDTH = {1: 0x00,
|
TXT_WIDTH = {1: 0x00,
|
||||||
2: 0x10,
|
2: 0x10,
|
||||||
3: 0x20,
|
3: 0x20,
|
||||||
|
@ -71,99 +78,99 @@ TXT_HEIGHT = {1: 0x00,
|
||||||
6: 0x05,
|
6: 0x05,
|
||||||
7: 0x06,
|
7: 0x06,
|
||||||
8: 0x07}
|
8: 0x07}
|
||||||
TXT_NORMAL = ESC + '!\x00' # Normal text
|
TXT_NORMAL = ESC + b'!\x00' # Normal text
|
||||||
TXT_2HEIGHT = ESC + '!\x10' # Double height text
|
TXT_2HEIGHT = ESC + b'!\x10' # Double height text
|
||||||
TXT_2WIDTH = ESC + '!\x20' # Double width text
|
TXT_2WIDTH = ESC + b'!\x20' # Double width text
|
||||||
TXT_4SQUARE = ESC + '!\x30' # Quad area text
|
TXT_4SQUARE = ESC + b'!\x30' # Quad area text
|
||||||
TXT_UNDERL_OFF = ESC + '\x2d\x00' # Underline font OFF
|
TXT_UNDERL_OFF = ESC + b'\x2d\x00' # Underline font OFF
|
||||||
TXT_UNDERL_ON = ESC + '\x2d\x01' # Underline font 1-dot ON
|
TXT_UNDERL_ON = ESC + b'\x2d\x01' # Underline font 1-dot ON
|
||||||
TXT_UNDERL2_ON = ESC + '\x2d\x02' # Underline font 2-dot ON
|
TXT_UNDERL2_ON = ESC + b'\x2d\x02' # Underline font 2-dot ON
|
||||||
TXT_BOLD_OFF = ESC + '\x45\x00' # Bold font OFF
|
TXT_BOLD_OFF = ESC + b'\x45\x00' # Bold font OFF
|
||||||
TXT_BOLD_ON = ESC + '\x45\x01' # Bold font ON
|
TXT_BOLD_ON = ESC + b'\x45\x01' # Bold font ON
|
||||||
TXT_FONT_A = ESC + '\x4d\x00' # Font type A
|
TXT_FONT_A = ESC + b'\x4d\x00' # Font type A
|
||||||
TXT_FONT_B = ESC + '\x4d\x01' # Font type B
|
TXT_FONT_B = ESC + b'\x4d\x01' # Font type B
|
||||||
TXT_ALIGN_LT = ESC + '\x61\x00' # Left justification
|
TXT_ALIGN_LT = ESC + b'\x61\x00' # Left justification
|
||||||
TXT_ALIGN_CT = ESC + '\x61\x01' # Centering
|
TXT_ALIGN_CT = ESC + b'\x61\x01' # Centering
|
||||||
TXT_ALIGN_RT = ESC + '\x61\x02' # Right justification
|
TXT_ALIGN_RT = ESC + b'\x61\x02' # Right justification
|
||||||
TXT_INVERT_ON = GS + '\x42\x01' # Inverse Printing ON
|
TXT_INVERT_ON = GS + b'\x42\x01' # Inverse Printing ON
|
||||||
TXT_INVERT_OFF = GS + '\x42\x00' # Inverse Printing OFF
|
TXT_INVERT_OFF = GS + b'\x42\x00' # Inverse Printing OFF
|
||||||
|
|
||||||
# Char code table
|
# Char code table
|
||||||
CHARCODE_PC437 = ESC + '\x74\x00' # USA: Standard Europe
|
CHARCODE_PC437 = ESC + b'\x74\x00' # USA: Standard Europe
|
||||||
CHARCODE_JIS = ESC + '\x74\x01' # Japanese Katakana
|
CHARCODE_JIS = ESC + b'\x74\x01' # Japanese Katakana
|
||||||
CHARCODE_PC850 = ESC + '\x74\x02' # Multilingual
|
CHARCODE_PC850 = ESC + b'\x74\x02' # Multilingual
|
||||||
CHARCODE_PC860 = ESC + '\x74\x03' # Portuguese
|
CHARCODE_PC860 = ESC + b'\x74\x03' # Portuguese
|
||||||
CHARCODE_PC863 = ESC + '\x74\x04' # Canadian-French
|
CHARCODE_PC863 = ESC + b'\x74\x04' # Canadian-French
|
||||||
CHARCODE_PC865 = ESC + '\x74\x05' # Nordic
|
CHARCODE_PC865 = ESC + b'\x74\x05' # Nordic
|
||||||
CHARCODE_WEU = ESC + '\x74\x06' # Simplified Kanji, Hirakana
|
CHARCODE_WEU = ESC + b'\x74\x06' # Simplified Kanji, Hirakana
|
||||||
CHARCODE_GREEK = ESC + '\x74\x07' # Simplified Kanji
|
CHARCODE_GREEK = ESC + b'\x74\x07' # Simplified Kanji
|
||||||
CHARCODE_HEBREW = ESC + '\x74\x08' # Simplified Kanji
|
CHARCODE_HEBREW = ESC + b'\x74\x08' # Simplified Kanji
|
||||||
CHARCODE_PC1252 = ESC + '\x74\x11' # Western European Windows Code Set
|
CHARCODE_PC1252 = ESC + b'\x74\x11' # Western European Windows Code Set
|
||||||
CHARCODE_PC866 = ESC + '\x74\x12' # Cirillic #2
|
CHARCODE_PC866 = ESC + b'\x74\x12' # Cirillic #2
|
||||||
CHARCODE_PC852 = ESC + '\x74\x13' # Latin 2
|
CHARCODE_PC852 = ESC + b'\x74\x13' # Latin 2
|
||||||
CHARCODE_PC858 = ESC + '\x74\x14' # Euro
|
CHARCODE_PC858 = ESC + b'\x74\x14' # Euro
|
||||||
CHARCODE_THAI42 = ESC + '\x74\x15' # Thai character code 42
|
CHARCODE_THAI42 = ESC + b'\x74\x15' # Thai character code 42
|
||||||
CHARCODE_THAI11 = ESC + '\x74\x16' # Thai character code 11
|
CHARCODE_THAI11 = ESC + b'\x74\x16' # Thai character code 11
|
||||||
CHARCODE_THAI13 = ESC + '\x74\x17' # Thai character code 13
|
CHARCODE_THAI13 = ESC + b'\x74\x17' # Thai character code 13
|
||||||
CHARCODE_THAI14 = ESC + '\x74\x18' # Thai character code 14
|
CHARCODE_THAI14 = ESC + b'\x74\x18' # Thai character code 14
|
||||||
CHARCODE_THAI16 = ESC + '\x74\x19' # Thai character code 16
|
CHARCODE_THAI16 = ESC + b'\x74\x19' # Thai character code 16
|
||||||
CHARCODE_THAI17 = ESC + '\x74\x1a' # Thai character code 17
|
CHARCODE_THAI17 = ESC + b'\x74\x1a' # Thai character code 17
|
||||||
CHARCODE_THAI18 = ESC + '\x74\x1b' # Thai character code 18
|
CHARCODE_THAI18 = ESC + b'\x74\x1b' # Thai character code 18
|
||||||
|
|
||||||
# Barcode format
|
# Barcode format
|
||||||
_SET_BARCODE_TXT_POS = lambda n: GS + 'H' + n
|
_SET_BARCODE_TXT_POS = lambda n: GS + b'H' + n
|
||||||
BARCODE_TXT_OFF = _SET_BARCODE_TXT_POS('\x00') # HRI barcode chars OFF
|
BARCODE_TXT_OFF = _SET_BARCODE_TXT_POS(b'\x00') # HRI barcode chars OFF
|
||||||
BARCODE_TXT_ABV = _SET_BARCODE_TXT_POS('\x01') # HRI barcode chars above
|
BARCODE_TXT_ABV = _SET_BARCODE_TXT_POS(b'\x01') # HRI barcode chars above
|
||||||
BARCODE_TXT_BLW = _SET_BARCODE_TXT_POS('\x02') # HRI barcode chars below
|
BARCODE_TXT_BLW = _SET_BARCODE_TXT_POS(b'\x02') # HRI barcode chars below
|
||||||
BARCODE_TXT_BTH = _SET_BARCODE_TXT_POS('\x03') # HRI both above and below
|
BARCODE_TXT_BTH = _SET_BARCODE_TXT_POS(b'\x03') # HRI both above and below
|
||||||
|
|
||||||
_SET_HRI_FONT = lambda n: GS + 'f' + n
|
_SET_HRI_FONT = lambda n: GS + b'f' + n
|
||||||
BARCODE_FONT_A = _SET_HRI_FONT('\x00') # Font type A for HRI barcode chars
|
BARCODE_FONT_A = _SET_HRI_FONT(b'\x00') # Font type A for HRI barcode chars
|
||||||
BARCODE_FONT_B = _SET_HRI_FONT('\x01') # Font type B for HRI barcode chars
|
BARCODE_FONT_B = _SET_HRI_FONT(b'\x01') # Font type B for HRI barcode chars
|
||||||
|
|
||||||
BARCODE_HEIGHT = GS + 'h' # Barcode Height [1-255]
|
BARCODE_HEIGHT = GS + b'h' # Barcode Height [1-255]
|
||||||
BARCODE_WIDTH = GS + 'w' # Barcode Width [2-6]
|
BARCODE_WIDTH = GS + b'w' # Barcode Width [2-6]
|
||||||
|
|
||||||
#NOTE: This isn't actually an ESC/POS command. It's the common prefix to the
|
#NOTE: This isn't actually an ESC/POS command. It's the common prefix to the
|
||||||
# two "print bar code" commands:
|
# two "print bar code" commands:
|
||||||
# - Type A: "GS k <type as integer> <data> NUL"
|
# - Type A: "GS k <type as integer> <data> NUL"
|
||||||
# - TYPE B: "GS k <type as letter> <data length> <data>"
|
# - TYPE B: "GS k <type as letter> <data length> <data>"
|
||||||
# The latter command supports more barcode types
|
# The latter command supports more barcode types
|
||||||
_SET_BARCODE_TYPE = lambda m: GS + 'k' + m
|
_SET_BARCODE_TYPE = lambda m: GS + b'k' + six.int2byte(m)
|
||||||
|
|
||||||
# Barcodes for printing function type A
|
# Barcodes for printing function type A
|
||||||
BARCODE_TYPE_A = {
|
BARCODE_TYPE_A = {
|
||||||
'UPC-A': _SET_BARCODE_TYPE(chr(0)),
|
'UPC-A': _SET_BARCODE_TYPE(0),
|
||||||
'UPC-E': _SET_BARCODE_TYPE(chr(1)),
|
'UPC-E': _SET_BARCODE_TYPE(1),
|
||||||
'EAN13': _SET_BARCODE_TYPE(chr(2)),
|
'EAN13': _SET_BARCODE_TYPE(2),
|
||||||
'EAN8': _SET_BARCODE_TYPE(chr(3)),
|
'EAN8': _SET_BARCODE_TYPE(3),
|
||||||
'CODE39': _SET_BARCODE_TYPE(chr(4)),
|
'CODE39': _SET_BARCODE_TYPE(4),
|
||||||
'ITF': _SET_BARCODE_TYPE(chr(5)),
|
'ITF': _SET_BARCODE_TYPE(5),
|
||||||
'NW7': _SET_BARCODE_TYPE(chr(6)),
|
'NW7': _SET_BARCODE_TYPE(6),
|
||||||
'CODABAR': _SET_BARCODE_TYPE(chr(6)), # Same as NW7
|
'CODABAR': _SET_BARCODE_TYPE(6), # Same as NW7
|
||||||
}
|
}
|
||||||
|
|
||||||
# Barcodes for printing function type B
|
# Barcodes for printing function type B
|
||||||
# The first 8 are the same barcodes as type A
|
# The first 8 are the same barcodes as type A
|
||||||
BARCODE_TYPE_B = {
|
BARCODE_TYPE_B = {
|
||||||
'UPC-A': _SET_BARCODE_TYPE(chr(65)),
|
'UPC-A': _SET_BARCODE_TYPE(65),
|
||||||
'UPC-E': _SET_BARCODE_TYPE(chr(66)),
|
'UPC-E': _SET_BARCODE_TYPE(66),
|
||||||
'EAN13': _SET_BARCODE_TYPE(chr(67)),
|
'EAN13': _SET_BARCODE_TYPE(67),
|
||||||
'EAN8': _SET_BARCODE_TYPE(chr(68)),
|
'EAN8': _SET_BARCODE_TYPE(68),
|
||||||
'CODE39': _SET_BARCODE_TYPE(chr(69)),
|
'CODE39': _SET_BARCODE_TYPE(69),
|
||||||
'ITF': _SET_BARCODE_TYPE(chr(70)),
|
'ITF': _SET_BARCODE_TYPE(70),
|
||||||
'NW7': _SET_BARCODE_TYPE(chr(71)),
|
'NW7': _SET_BARCODE_TYPE(71),
|
||||||
'CODABAR': _SET_BARCODE_TYPE(chr(71)), # Same as NW7
|
'CODABAR': _SET_BARCODE_TYPE(71), # Same as NW7
|
||||||
'CODE93': _SET_BARCODE_TYPE(chr(72)),
|
'CODE93': _SET_BARCODE_TYPE(72),
|
||||||
# These are all the same barcode, but using different charcter sets
|
# These are all the same barcode, but using different charcter sets
|
||||||
'CODE128A': _SET_BARCODE_TYPE(chr(73) + '{A'), # CODE128 character set A
|
'CODE128A': _SET_BARCODE_TYPE(73) + b'{A', # CODE128 character set A
|
||||||
'CODE128B': _SET_BARCODE_TYPE(chr(73) + '{B'), # CODE128 character set B
|
'CODE128B': _SET_BARCODE_TYPE(73) + b'{B', # CODE128 character set B
|
||||||
'CODE128C': _SET_BARCODE_TYPE(chr(73) + '{C'), # CODE128 character set C
|
'CODE128C': _SET_BARCODE_TYPE(73) + b'{C', # CODE128 character set C
|
||||||
'GS1-128': _SET_BARCODE_TYPE(chr(74)),
|
'GS1-128': _SET_BARCODE_TYPE(74),
|
||||||
'GS1 DATABAR OMNIDIRECTIONAL': _SET_BARCODE_TYPE(chr(75)),
|
'GS1 DATABAR OMNIDIRECTIONAL': _SET_BARCODE_TYPE(75),
|
||||||
'GS1 DATABAR TRUNCATED': _SET_BARCODE_TYPE(chr(76)),
|
'GS1 DATABAR TRUNCATED': _SET_BARCODE_TYPE(76),
|
||||||
'GS1 DATABAR LIMITED': _SET_BARCODE_TYPE(chr(77)),
|
'GS1 DATABAR LIMITED': _SET_BARCODE_TYPE(77),
|
||||||
'GS1 DATABAR EXPANDED': _SET_BARCODE_TYPE(chr(78)),
|
'GS1 DATABAR EXPANDED': _SET_BARCODE_TYPE(78),
|
||||||
}
|
}
|
||||||
|
|
||||||
BARCODE_TYPES = {
|
BARCODE_TYPES = {
|
||||||
|
@ -175,19 +182,19 @@ BARCODE_TYPES = {
|
||||||
# Image format
|
# Image format
|
||||||
# NOTE: _PRINT_RASTER_IMG is the obsolete ESC/POS "print raster bit image"
|
# NOTE: _PRINT_RASTER_IMG is the obsolete ESC/POS "print raster bit image"
|
||||||
# command. The constants include a fragment of the data's header.
|
# command. The constants include a fragment of the data's header.
|
||||||
_PRINT_RASTER_IMG = lambda data: GS + 'v0' + data
|
_PRINT_RASTER_IMG = lambda data: GS + b'v0' + data
|
||||||
S_RASTER_N = _PRINT_RASTER_IMG('\x00') # Set raster image normal size
|
S_RASTER_N = _PRINT_RASTER_IMG(b'\x00') # Set raster image normal size
|
||||||
S_RASTER_2W = _PRINT_RASTER_IMG('\x01') # Set raster image double width
|
S_RASTER_2W = _PRINT_RASTER_IMG(b'\x01') # Set raster image double width
|
||||||
S_RASTER_2H = _PRINT_RASTER_IMG('\x02') # Set raster image double height
|
S_RASTER_2H = _PRINT_RASTER_IMG(b'\x02') # Set raster image double height
|
||||||
S_RASTER_Q = _PRINT_RASTER_IMG('\x03') # Set raster image quadruple
|
S_RASTER_Q = _PRINT_RASTER_IMG(b'\x03') # Set raster image quadruple
|
||||||
|
|
||||||
# Printing Density
|
# Printing Density
|
||||||
PD_N50 = GS + '\x7c\x00' # Printing Density -50%
|
PD_N50 = GS + b'\x7c\x00' # Printing Density -50%
|
||||||
PD_N37 = GS + '\x7c\x01' # Printing Density -37.5%
|
PD_N37 = GS + b'\x7c\x01' # Printing Density -37.5%
|
||||||
PD_N25 = GS + '\x7c\x02' # Printing Density -25%
|
PD_N25 = GS + b'\x7c\x02' # Printing Density -25%
|
||||||
PD_N12 = GS + '\x7c\x03' # Printing Density -12.5%
|
PD_N12 = GS + b'\x7c\x03' # Printing Density -12.5%
|
||||||
PD_0 = GS + '\x7c\x04' # Printing Density 0%
|
PD_0 = GS + b'\x7c\x04' # Printing Density 0%
|
||||||
PD_P50 = GS + '\x7c\x08' # Printing Density +50%
|
PD_P50 = GS + b'\x7c\x08' # Printing Density +50%
|
||||||
PD_P37 = GS + '\x7c\x07' # Printing Density +37.5%
|
PD_P37 = GS + b'\x7c\x07' # Printing Density +37.5%
|
||||||
PD_P25 = GS + '\x7c\x06' # Printing Density +25%
|
PD_P25 = GS + b'\x7c\x06' # Printing Density +25%
|
||||||
PD_P12 = GS + '\x7c\x05' # Printing Density +12.5%
|
PD_P12 = GS + b'\x7c\x05' # Printing Density +12.5%
|
||||||
|
|
|
@ -9,10 +9,14 @@ This module contains the abstract base class :py:class:`Escpos`.
|
||||||
:license: GNU GPL v3
|
:license: GNU GPL v3
|
||||||
"""
|
"""
|
||||||
|
|
||||||
try:
|
from __future__ import absolute_import
|
||||||
import Image
|
from __future__ import division
|
||||||
except ImportError:
|
from __future__ import print_function
|
||||||
from PIL import Image
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
import six
|
||||||
|
|
||||||
|
from PIL import Image
|
||||||
|
|
||||||
import qrcode
|
import qrcode
|
||||||
import textwrap
|
import textwrap
|
||||||
|
@ -47,6 +51,7 @@ class Escpos(object):
|
||||||
This function has to be individually implemented by the implementations.
|
This function has to be individually implemented by the implementations.
|
||||||
|
|
||||||
:param msg: message string to be sent to the printer
|
:param msg: message string to be sent to the printer
|
||||||
|
:type msg: bytes
|
||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -63,9 +68,9 @@ class Escpos(object):
|
||||||
else:
|
else:
|
||||||
image_border = 32 - (size % 32)
|
image_border = 32 - (size % 32)
|
||||||
if (image_border % 2) == 0:
|
if (image_border % 2) == 0:
|
||||||
return round(image_border / 2), round(image_border / 2)
|
return image_border // 2, image_border // 2
|
||||||
else:
|
else:
|
||||||
return round(image_border / 2), round((image_border / 2) + 1)
|
return image_border // 2, (image_border // 2) + 1
|
||||||
|
|
||||||
def _print_image(self, line, size):
|
def _print_image(self, line, size):
|
||||||
""" Print formatted image
|
""" Print formatted image
|
||||||
|
@ -75,7 +80,7 @@ class Escpos(object):
|
||||||
"""
|
"""
|
||||||
i = 0
|
i = 0
|
||||||
cont = 0
|
cont = 0
|
||||||
pbuffer = ""
|
pbuffer = b''
|
||||||
|
|
||||||
self._raw(S_RASTER_N)
|
self._raw(S_RASTER_N)
|
||||||
pbuffer = "%02X%02X%02X%02X" % (((size[0]/size[1])/8), 0, size[1] & 0xff, size[1] >> 8)
|
pbuffer = "%02X%02X%02X%02X" % (((size[0]/size[1])/8), 0, size[1] & 0xff, size[1] >> 8)
|
||||||
|
@ -152,7 +157,10 @@ class Escpos(object):
|
||||||
|
|
||||||
:param path_img: complete filename and path to image of type `jpg`, `gif`, `png` or `bmp`
|
:param path_img: complete filename and path to image of type `jpg`, `gif`, `png` or `bmp`
|
||||||
"""
|
"""
|
||||||
im_open = Image.open(path_img)
|
if not isinstance(path_img, Image.Image):
|
||||||
|
im_open = Image.open(path_img)
|
||||||
|
else:
|
||||||
|
im_open = path_img
|
||||||
|
|
||||||
# Remove the alpha channel on transparent images
|
# Remove the alpha channel on transparent images
|
||||||
if im_open.mode == 'RGBA':
|
if im_open.mode == 'RGBA':
|
||||||
|
@ -171,7 +179,7 @@ class Escpos(object):
|
||||||
.. todo:: Seems to be broken. Write test that simply executes function with a dummy printer in order to
|
.. todo:: Seems to be broken. Write test that simply executes function with a dummy printer in order to
|
||||||
check for bugs like these in the future.
|
check for bugs like these in the future.
|
||||||
"""
|
"""
|
||||||
if isinstance(img, (Image, Image.Image)):
|
if isinstance(img, Image.Image):
|
||||||
im = img.convert("RGB")
|
im = img.convert("RGB")
|
||||||
else:
|
else:
|
||||||
im = Image.open(img).convert("RGB")
|
im = Image.open(img).convert("RGB")
|
||||||
|
@ -208,9 +216,11 @@ class Escpos(object):
|
||||||
current += bandsize
|
current += bandsize
|
||||||
|
|
||||||
def direct_image(self, image):
|
def direct_image(self, image):
|
||||||
""" Send image to printer
|
""" Direct printing function for pictures
|
||||||
|
|
||||||
:param image:
|
This function is rather fragile and will fail when the Image object is not suited.
|
||||||
|
|
||||||
|
:param image: PIL image object, containing a 1-bit picture
|
||||||
"""
|
"""
|
||||||
mask = 0x80
|
mask = 0x80
|
||||||
i = 0
|
i = 0
|
||||||
|
@ -241,7 +251,7 @@ class Escpos(object):
|
||||||
i = 0
|
i = 0
|
||||||
temp = 0
|
temp = 0
|
||||||
self._raw(binascii.unhexlify(bytes(buf, "ascii")))
|
self._raw(binascii.unhexlify(bytes(buf, "ascii")))
|
||||||
self._raw('\n')
|
self._raw(b'\n')
|
||||||
|
|
||||||
def qr(self, text):
|
def qr(self, text):
|
||||||
""" Print QR Code for the provided string
|
""" Print QR Code for the provided string
|
||||||
|
@ -398,12 +408,12 @@ class Escpos(object):
|
||||||
self._raw(TXT_ALIGN_CT)
|
self._raw(TXT_ALIGN_CT)
|
||||||
# Height
|
# Height
|
||||||
if 1 <= height <= 255:
|
if 1 <= height <= 255:
|
||||||
self._raw(BARCODE_HEIGHT + chr(height))
|
self._raw(BARCODE_HEIGHT + six.int2byte(height))
|
||||||
else:
|
else:
|
||||||
raise BarcodeSizeError("height = {height}".format(height=height))
|
raise BarcodeSizeError("height = {height}".format(height=height))
|
||||||
# Width
|
# Width
|
||||||
if 2 <= width <= 6:
|
if 2 <= width <= 6:
|
||||||
self._raw(BARCODE_WIDTH + chr(width))
|
self._raw(BARCODE_WIDTH + six.int2byte(width))
|
||||||
else:
|
else:
|
||||||
raise BarcodeSizeError("width = {width}".format(width=width))
|
raise BarcodeSizeError("width = {width}".format(width=width))
|
||||||
# Font
|
# Font
|
||||||
|
@ -436,7 +446,7 @@ class Escpos(object):
|
||||||
|
|
||||||
# Print Code
|
# Print Code
|
||||||
if code:
|
if code:
|
||||||
self._raw(code)
|
self._raw(code.encode())
|
||||||
else:
|
else:
|
||||||
raise BarcodeCodeError()
|
raise BarcodeCodeError()
|
||||||
|
|
||||||
|
@ -448,11 +458,13 @@ class Escpos(object):
|
||||||
|
|
||||||
The text has to be encoded in the currently selected codepage.
|
The text has to be encoded in the currently selected codepage.
|
||||||
|
|
||||||
|
.. todo:: rework this in order to proberly handle encoding
|
||||||
|
|
||||||
:param txt: text to be printed
|
:param txt: text to be printed
|
||||||
:raises: :py:exc:`~escpos.exceptions.TextError`
|
:raises: :py:exc:`~escpos.exceptions.TextError`
|
||||||
"""
|
"""
|
||||||
if txt:
|
if txt:
|
||||||
self._raw(txt)
|
self._raw(txt.encode())
|
||||||
else:
|
else:
|
||||||
# TODO: why is it problematic to print an empty string?
|
# TODO: why is it problematic to print an empty string?
|
||||||
raise TextError()
|
raise TextError()
|
||||||
|
@ -509,7 +521,7 @@ class Escpos(object):
|
||||||
elif width == 1 and height == 1:
|
elif width == 1 and height == 1:
|
||||||
self._raw(TXT_NORMAL)
|
self._raw(TXT_NORMAL)
|
||||||
elif 1 <= width <= 8 and 1 <= height <= 8 and isinstance(width, int) and isinstance(height, int):
|
elif 1 <= width <= 8 and 1 <= height <= 8 and isinstance(width, int) and isinstance(height, int):
|
||||||
self._raw(TXT_SIZE + chr(TXT_WIDTH[width] + TXT_HEIGHT[height]))
|
self._raw(TXT_SIZE + six.int2byte(TXT_WIDTH[width] + TXT_HEIGHT[height]))
|
||||||
else:
|
else:
|
||||||
raise SetVariableError()
|
raise SetVariableError()
|
||||||
# Upside down
|
# Upside down
|
||||||
|
@ -592,7 +604,7 @@ class Escpos(object):
|
||||||
"""
|
"""
|
||||||
# Fix the size between last line and cut
|
# Fix the size between last line and cut
|
||||||
# TODO: handle this with a line feed
|
# TODO: handle this with a line feed
|
||||||
self._raw("\n\n\n\n\n\n")
|
self._raw(b"\n\n\n\n\n\n")
|
||||||
if mode.upper() == "PART":
|
if mode.upper() == "PART":
|
||||||
self._raw(PAPER_PART_CUT)
|
self._raw(PAPER_PART_CUT)
|
||||||
else: # DEFAULT MODE: FULL CUT
|
else: # DEFAULT MODE: FULL CUT
|
||||||
|
@ -649,7 +661,7 @@ class Escpos(object):
|
||||||
if pos < 1 or pos > 16:
|
if pos < 1 or pos > 16:
|
||||||
raise TabPosError()
|
raise TabPosError()
|
||||||
else:
|
else:
|
||||||
self._raw("".join([CTL_SET_HT, hex(pos)]))
|
self._raw(CTL_SET_HT + six.int2byte(pos))
|
||||||
# Set position
|
# Set position
|
||||||
if ctl.upper() == "LF":
|
if ctl.upper() == "LF":
|
||||||
self._raw(CTL_LF)
|
self._raw(CTL_LF)
|
||||||
|
|
|
@ -20,6 +20,11 @@ Result/Exit codes:
|
||||||
:license: GNU GPL v3
|
:license: GNU GPL v3
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
from __future__ import absolute_import
|
||||||
|
from __future__ import division
|
||||||
|
from __future__ import print_function
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
|
||||||
class Error(Exception):
|
class Error(Exception):
|
||||||
""" Base class for ESC/POS errors """
|
""" Base class for ESC/POS errors """
|
||||||
|
|
|
@ -7,6 +7,11 @@
|
||||||
:license: GNU GPL v3
|
:license: GNU GPL v3
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
from __future__ import absolute_import
|
||||||
|
from __future__ import division
|
||||||
|
from __future__ import print_function
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
import usb.core
|
import usb.core
|
||||||
import usb.util
|
import usb.util
|
||||||
import serial
|
import serial
|
||||||
|
@ -74,6 +79,7 @@ class Usb(Escpos):
|
||||||
""" Print any command sent in raw format
|
""" Print any command sent in raw format
|
||||||
|
|
||||||
:param msg: arbitrary code to be printed
|
:param msg: arbitrary code to be printed
|
||||||
|
:type msg: bytes
|
||||||
"""
|
"""
|
||||||
self.device.write(self.out_ep, msg, self.interface)
|
self.device.write(self.out_ep, msg, self.interface)
|
||||||
|
|
||||||
|
@ -138,6 +144,7 @@ class Serial(Escpos):
|
||||||
""" Print any command sent in raw format
|
""" Print any command sent in raw format
|
||||||
|
|
||||||
:param msg: arbitrary code to be printed
|
:param msg: arbitrary code to be printed
|
||||||
|
:type msg: bytes
|
||||||
"""
|
"""
|
||||||
self.device.write(msg)
|
self.device.write(msg)
|
||||||
|
|
||||||
|
@ -196,6 +203,7 @@ class Network(Escpos):
|
||||||
""" Print any command sent in raw format
|
""" Print any command sent in raw format
|
||||||
|
|
||||||
:param msg: arbitrary code to be printed
|
:param msg: arbitrary code to be printed
|
||||||
|
:type msg: bytes
|
||||||
"""
|
"""
|
||||||
self.device.sendall(msg)
|
self.device.sendall(msg)
|
||||||
|
|
||||||
|
@ -242,11 +250,9 @@ class File(Escpos):
|
||||||
""" Print any command sent in raw format
|
""" Print any command sent in raw format
|
||||||
|
|
||||||
:param msg: arbitrary code to be printed
|
:param msg: arbitrary code to be printed
|
||||||
|
:type msg: bytes
|
||||||
"""
|
"""
|
||||||
if type(msg) is str:
|
self.device.write(msg)
|
||||||
self.device.write(msg.encode())
|
|
||||||
else:
|
|
||||||
self.device.write(msg)
|
|
||||||
|
|
||||||
def __del__(self):
|
def __del__(self):
|
||||||
""" Close system file """
|
""" Close system file """
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
[nosetests]
|
||||||
|
verbosity=3
|
||||||
|
with-doctest=1
|
||||||
|
|
||||||
|
[bdist_wheel]
|
||||||
|
# This flag says that the code is written to work on both Python 2 and Python 3.
|
||||||
|
universal=1
|
1
setup.py
1
setup.py
|
@ -70,6 +70,7 @@ setup(
|
||||||
'Pillow>=2.0',
|
'Pillow>=2.0',
|
||||||
'qrcode>=4.0',
|
'qrcode>=4.0',
|
||||||
'pyserial',
|
'pyserial',
|
||||||
|
'six',
|
||||||
],
|
],
|
||||||
tests_require=['tox', 'nose'],
|
tests_require=['tox', 'nose'],
|
||||||
cmdclass={'test': Tox},
|
cmdclass={'test': Tox},
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 16 KiB |
Binary file not shown.
After Width: | Height: | Size: 27 KiB |
Binary file not shown.
After Width: | Height: | Size: 653 B |
|
@ -0,0 +1 @@
|
||||||
|
Dies ist ein Test.
|
|
@ -0,0 +1,50 @@
|
||||||
|
#!/usr/bin/python
|
||||||
|
"""tests for the image printing function
|
||||||
|
|
||||||
|
: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
|
||||||
|
|
||||||
|
from nose.tools import with_setup
|
||||||
|
|
||||||
|
import escpos.printer as printer
|
||||||
|
import os
|
||||||
|
|
||||||
|
devfile = 'testfile'
|
||||||
|
|
||||||
|
def setup_testfile():
|
||||||
|
"""create a testfile as devfile"""
|
||||||
|
fhandle = open(devfile, 'a')
|
||||||
|
try:
|
||||||
|
os.utime(devfile, None)
|
||||||
|
finally:
|
||||||
|
fhandle.close()
|
||||||
|
|
||||||
|
def teardown_testfile():
|
||||||
|
"""destroy testfile again"""
|
||||||
|
os.remove(devfile)
|
||||||
|
|
||||||
|
@with_setup(setup_testfile, teardown_testfile)
|
||||||
|
def test_function_image_with_50x50_png():
|
||||||
|
"""test the image function with 50x50.png (grayscale png)"""
|
||||||
|
instance = printer.File(devfile=devfile)
|
||||||
|
instance.image("test/50x50.png")
|
||||||
|
|
||||||
|
@with_setup(setup_testfile, teardown_testfile)
|
||||||
|
def test_function_image_with_255x255_png():
|
||||||
|
"""test the image function with 255x255.png (grayscale png)"""
|
||||||
|
instance = printer.File(devfile=devfile)
|
||||||
|
instance.image("test/255x255.png")
|
||||||
|
|
||||||
|
@with_setup(setup_testfile, teardown_testfile)
|
||||||
|
def test_function_image_with_400x400_png():
|
||||||
|
"""test the image function with 400x400.png (grayscale png)"""
|
||||||
|
instance = printer.File(devfile=devfile)
|
||||||
|
instance.image("test/400x400.png")
|
|
@ -0,0 +1,42 @@
|
||||||
|
#!/usr/bin/python
|
||||||
|
"""tests for the text printing function
|
||||||
|
|
||||||
|
: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
|
||||||
|
|
||||||
|
from nose.tools import with_setup
|
||||||
|
|
||||||
|
import escpos.printer as printer
|
||||||
|
import os
|
||||||
|
|
||||||
|
import filecmp
|
||||||
|
|
||||||
|
devfile = 'testfile'
|
||||||
|
|
||||||
|
def setup_testfile():
|
||||||
|
"""create a testfile as devfile"""
|
||||||
|
fhandle = open(devfile, 'a')
|
||||||
|
try:
|
||||||
|
os.utime(devfile, None)
|
||||||
|
finally:
|
||||||
|
fhandle.close()
|
||||||
|
|
||||||
|
def teardown_testfile():
|
||||||
|
"""destroy testfile again"""
|
||||||
|
os.remove(devfile)
|
||||||
|
|
||||||
|
@with_setup(setup_testfile, teardown_testfile)
|
||||||
|
def test_function_text_dies_ist_ein_test_lf():
|
||||||
|
"""test the text printing function with simple string and compare output"""
|
||||||
|
instance = printer.File(devfile=devfile)
|
||||||
|
instance.text('Dies ist ein Test.\n')
|
||||||
|
instance.flush()
|
||||||
|
assert(filecmp.cmp('test/Dies ist ein Test.LF.txt', devfile))
|
|
@ -7,6 +7,11 @@
|
||||||
:license: GNU GPL v3
|
:license: GNU GPL v3
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
from __future__ import absolute_import
|
||||||
|
from __future__ import division
|
||||||
|
from __future__ import print_function
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from nose.tools import with_setup
|
from nose.tools import with_setup
|
||||||
|
|
||||||
import escpos.printer as printer
|
import escpos.printer as printer
|
||||||
|
|
Loading…
Reference in New Issue