1import sys
2from ._qrencode import encode as _encode
3from PIL import Image
4
5if sys.version_info >= (3,):
6    unicode = str
7    basestring = (str, bytes)
8
9QR_ECLEVEL_L = 0
10QR_ECLEVEL_M = 1
11QR_ECLEVEL_Q = 2
12QR_ECLEVEL_H = 3
13levels = [QR_ECLEVEL_L, QR_ECLEVEL_M, QR_ECLEVEL_Q, QR_ECLEVEL_H]
14
15
16QR_MODE_8 = 2
17QR_MODE_KANJI = 3
18hints = [QR_MODE_8, QR_MODE_KANJI]
19
20
21def encode(data, version=0, level=QR_ECLEVEL_L, hint=QR_MODE_8,
22           case_sensitive=True):
23    """Creates a QR-Code from string data.
24
25    Args:
26      data: string: The data to encode in a QR-code. If a unicode string is
27          supplied, it will be encoded in UTF-8.
28      version: int: The minimum version to use. If set to 0, the library picks
29          the smallest version that the data fits in.
30      level: int: Error correction level. Defaults to 'L'.
31      hint: int: The type of data to encode. Either QR_MODE_8 or QR_MODE_KANJI.
32      case_sensitive: bool: Should string data be encoded case-preserving?
33    Returns:
34      A (version, size, image) tuple, where image is a size*size PIL image of
35      the QR-code.
36    """
37    if isinstance(data, unicode):
38        data = data.encode('utf8')
39    elif not isinstance(data, basestring):
40        raise ValueError('data argument must be a string.')
41    version = int(version)
42    if level not in levels:
43        raise ValueError('Invalid error-correction level.')
44    if hint not in hints:
45        raise ValueError('Invalid encoding mode.')
46    if case_sensitive:
47        version, size, data = _encode(data, version, level, hint, True)
48    else:
49        version, size, data = _encode(data, version, level, hint, False)
50
51    im = Image.frombytes('L', (size, size), data)
52    return (version, size, im)
53
54def encode_scaled(data, size, version=0, level=QR_ECLEVEL_L, hint=QR_MODE_8,
55                  case_sensitive=True):
56    """Creates a QR-code from string data, resized to the specified dimensions.
57
58    Args:
59      data: string: The data to encode in a QR-code. If a unicode string is
60          supplied, it will be encoded in UTF-8.
61      size: int: Output size. If this is not an exact multiple of the QR-code's
62          dimensions, padding will be added. If this is smaller than the
63          QR-code's dimensions, it is ignored.
64      version: int: The minimum version to use. If set to 0, the library picks
65          the smallest version that the data fits in.
66      level: int: Error correction level. Defaults to 'L'.
67      hint: int: The type of data to encode. Either QR_MODE_8 or QR_MODE_KANJI.
68      case_sensitive: bool: Should string data be encoded case-preserving?
69    Returns:
70      A (version, size, image) tuple, where image is a size*size PIL image of
71      the QR-code.
72    """
73    version, src_size, im = encode(data, version, level, hint, case_sensitive)
74    if size < src_size:
75      size = src_size
76    qr_size = (size / src_size) * src_size
77    im = im.resize((qr_size, qr_size), Image.NEAREST)
78    pad = (size - qr_size) / 2
79    ret = Image.new("L", (size, size), 255)
80    ret.paste(im, (pad, pad))
81
82    return (version, size, ret)
83