pyqrcode / pyqrcodeNG

Python 2 and 3 module to generate QR Codes
BSD 3-Clause "New" or "Revised" License
12 stars 6 forks source link

xbm does not handle scale correctly #8

Closed heuer closed 6 years ago

heuer commented 6 years ago
qr = pyqrcode.create('Test', error='h')
qr.png('test_scale.png', scale=4)

Convert that result into xbm via The Gimp.

Test case

def test_xbm_scale():
    """Test the xbm render against a known good.

    This test checks the *values* contained in the XBM, not the text.
    """
    expected_width_scale = '''#define im_width 116
#define im_height 116
static unsigned short im_bits[] = {
   0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
   0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
   0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
   0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
   0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
   0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
   0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
   0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
   0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
   0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
   0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
   0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
   0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
   0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
   0x0000, 0x0000, 0x0000, 0xffff, 0x0fff, 0x000f, 0xff0f, 0xffff, 0x000f,
   0x0000, 0x0000, 0xffff, 0x0fff, 0x000f, 0xff0f, 0xffff, 0x000f, 0x0000,
   0x0000, 0xffff, 0x0fff, 0x000f, 0xff0f, 0xffff, 0x000f, 0x0000, 0x0000,
   0xffff, 0x0fff, 0x000f, 0xff0f, 0xffff, 0x000f, 0x0000, 0x0000, 0x000f,
   0x0f00, 0xfff0, 0x0f0f, 0x0000, 0x000f, 0x0000, 0x0000, 0x000f, 0x0f00,
   0xfff0, 0x0f0f, 0x0000, 0x000f, 0x0000, 0x0000, 0x000f, 0x0f00, 0xfff0,
   0x0f0f, 0x0000, 0x000f, 0x0000, 0x0000, 0x000f, 0x0f00, 0xfff0, 0x0f0f,
   0x0000, 0x000f, 0x0000, 0x0000, 0xff0f, 0x0f0f, 0xf0ff, 0x0f0f, 0x0fff,
   0x000f, 0x0000, 0x0000, 0xff0f, 0x0f0f, 0xf0ff, 0x0f0f, 0x0fff, 0x000f,
   0x0000, 0x0000, 0xff0f, 0x0f0f, 0xf0ff, 0x0f0f, 0x0fff, 0x000f, 0x0000,
   0x0000, 0xff0f, 0x0f0f, 0xf0ff, 0x0f0f, 0x0fff, 0x000f, 0x0000, 0x0000,
   0xff0f, 0x0f0f, 0xff00, 0x0f00, 0x0fff, 0x000f, 0x0000, 0x0000, 0xff0f,
   0x0f0f, 0xff00, 0x0f00, 0x0fff, 0x000f, 0x0000, 0x0000, 0xff0f, 0x0f0f,
   0xff00, 0x0f00, 0x0fff, 0x000f, 0x0000, 0x0000, 0xff0f, 0x0f0f, 0xff00,
   0x0f00, 0x0fff, 0x000f, 0x0000, 0x0000, 0xff0f, 0x0f0f, 0xf0ff, 0x0f00,
   0x0fff, 0x000f, 0x0000, 0x0000, 0xff0f, 0x0f0f, 0xf0ff, 0x0f00, 0x0fff,
   0x000f, 0x0000, 0x0000, 0xff0f, 0x0f0f, 0xf0ff, 0x0f00, 0x0fff, 0x000f,
   0x0000, 0x0000, 0xff0f, 0x0f0f, 0xf0ff, 0x0f00, 0x0fff, 0x000f, 0x0000,
   0x0000, 0x000f, 0x0f00, 0x00f0, 0x0f0f, 0x0000, 0x000f, 0x0000, 0x0000,
   0x000f, 0x0f00, 0x00f0, 0x0f0f, 0x0000, 0x000f, 0x0000, 0x0000, 0x000f,
   0x0f00, 0x00f0, 0x0f0f, 0x0000, 0x000f, 0x0000, 0x0000, 0x000f, 0x0f00,
   0x00f0, 0x0f0f, 0x0000, 0x000f, 0x0000, 0x0000, 0xffff, 0x0fff, 0x0f0f,
   0xff0f, 0xffff, 0x000f, 0x0000, 0x0000, 0xffff, 0x0fff, 0x0f0f, 0xff0f,
   0xffff, 0x000f, 0x0000, 0x0000, 0xffff, 0x0fff, 0x0f0f, 0xff0f, 0xffff,
   0x000f, 0x0000, 0x0000, 0xffff, 0x0fff, 0x0f0f, 0xff0f, 0xffff, 0x000f,
   0x0000, 0x0000, 0x0000, 0x0000, 0x0fff, 0x000f, 0x0000, 0x0000, 0x0000,
   0x0000, 0x0000, 0x0000, 0x0fff, 0x000f, 0x0000, 0x0000, 0x0000, 0x0000,
   0x0000, 0x0000, 0x0fff, 0x000f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
   0x0000, 0x0fff, 0x000f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0ff0,
   0x0000, 0x0f0f, 0x0f0f, 0x000f, 0x0000, 0x0000, 0x0000, 0x0ff0, 0x0000,
   0x0f0f, 0x0f0f, 0x000f, 0x0000, 0x0000, 0x0000, 0x0ff0, 0x0000, 0x0f0f,
   0x0f0f, 0x000f, 0x0000, 0x0000, 0x0000, 0x0ff0, 0x0000, 0x0f0f, 0x0f0f,
   0x000f, 0x0000, 0x0000, 0xffff, 0x0000, 0xffff, 0x0ff0, 0x0fff, 0x0000,
   0x0000, 0x0000, 0xffff, 0x0000, 0xffff, 0x0ff0, 0x0fff, 0x0000, 0x0000,
   0x0000, 0xffff, 0x0000, 0xffff, 0x0ff0, 0x0fff, 0x0000, 0x0000, 0x0000,
   0xffff, 0x0000, 0xffff, 0x0ff0, 0x0fff, 0x0000, 0x0000, 0x0000, 0xff00,
   0x0f0f, 0xf0ff, 0x00ff, 0xffff, 0x0000, 0x0000, 0x0000, 0xff00, 0x0f0f,
   0xf0ff, 0x00ff, 0xffff, 0x0000, 0x0000, 0x0000, 0xff00, 0x0f0f, 0xf0ff,
   0x00ff, 0xffff, 0x0000, 0x0000, 0x0000, 0xff00, 0x0f0f, 0xf0ff, 0x00ff,
   0xffff, 0x0000, 0x0000, 0x0000, 0xf000, 0x00f0, 0xf000, 0x0000, 0x0fff,
   0x0000, 0x0000, 0x0000, 0xf000, 0x00f0, 0xf000, 0x0000, 0x0fff, 0x0000,
   0x0000, 0x0000, 0xf000, 0x00f0, 0xf000, 0x0000, 0x0fff, 0x0000, 0x0000,
   0x0000, 0xf000, 0x00f0, 0xf000, 0x0000, 0x0fff, 0x0000, 0x0000, 0x0000,
   0x0f00, 0x0f00, 0xff0f, 0x0ff0, 0x0000, 0x000f, 0x0000, 0x0000, 0x0f00,
   0x0f00, 0xff0f, 0x0ff0, 0x0000, 0x000f, 0x0000, 0x0000, 0x0f00, 0x0f00,
   0xff0f, 0x0ff0, 0x0000, 0x000f, 0x0000, 0x0000, 0x0f00, 0x0f00, 0xff0f,
   0x0ff0, 0x0000, 0x000f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0f0f, 0xff00,
   0xff00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0f0f, 0xff00, 0xff00,
   0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0f0f, 0xff00, 0xff00, 0x0000,
   0x0000, 0x0000, 0x0000, 0x0000, 0x0f0f, 0xff00, 0xff00, 0x0000, 0x0000,
   0x0000, 0xffff, 0x0fff, 0x0f00, 0xff00, 0xf0f0, 0x0000, 0x0000, 0x0000,
   0xffff, 0x0fff, 0x0f00, 0xff00, 0xf0f0, 0x0000, 0x0000, 0x0000, 0xffff,
   0x0fff, 0x0f00, 0xff00, 0xf0f0, 0x0000, 0x0000, 0x0000, 0xffff, 0x0fff,
   0x0f00, 0xff00, 0xf0f0, 0x0000, 0x0000, 0x0000, 0x000f, 0x0f00, 0xf0ff,
   0xf0ff, 0x0fff, 0x000f, 0x0000, 0x0000, 0x000f, 0x0f00, 0xf0ff, 0xf0ff,
   0x0fff, 0x000f, 0x0000, 0x0000, 0x000f, 0x0f00, 0xf0ff, 0xf0ff, 0x0fff,
   0x000f, 0x0000, 0x0000, 0x000f, 0x0f00, 0xf0ff, 0xf0ff, 0x0fff, 0x000f,
   0x0000, 0x0000, 0xff0f, 0x0f0f, 0x0f00, 0xf0f0, 0xf0f0, 0x0000, 0x0000,
   0x0000, 0xff0f, 0x0f0f, 0x0f00, 0xf0f0, 0xf0f0, 0x0000, 0x0000, 0x0000,
   0xff0f, 0x0f0f, 0x0f00, 0xf0f0, 0xf0f0, 0x0000, 0x0000, 0x0000, 0xff0f,
   0x0f0f, 0x0f00, 0xf0f0, 0xf0f0, 0x0000, 0x0000, 0x0000, 0xff0f, 0x0f0f,
   0xfff0, 0x0ff0, 0x0ff0, 0x0000, 0x0000, 0x0000, 0xff0f, 0x0f0f, 0xfff0,
   0x0ff0, 0x0ff0, 0x0000, 0x0000, 0x0000, 0xff0f, 0x0f0f, 0xfff0, 0x0ff0,
   0x0ff0, 0x0000, 0x0000, 0x0000, 0xff0f, 0x0f0f, 0xfff0, 0x0ff0, 0x0ff0,
   0x0000, 0x0000, 0x0000, 0xff0f, 0x0f0f, 0x00f0, 0x00ff, 0xfff0, 0x000f,
   0x0000, 0x0000, 0xff0f, 0x0f0f, 0x00f0, 0x00ff, 0xfff0, 0x000f, 0x0000,
   0x0000, 0xff0f, 0x0f0f, 0x00f0, 0x00ff, 0xfff0, 0x000f, 0x0000, 0x0000,
   0xff0f, 0x0f0f, 0x00f0, 0x00ff, 0xfff0, 0x000f, 0x0000, 0x0000, 0x000f,
   0x0f00, 0x0ff0, 0x0fff, 0x0f0f, 0x0000, 0x0000, 0x0000, 0x000f, 0x0f00,
   0x0ff0, 0x0fff, 0x0f0f, 0x0000, 0x0000, 0x0000, 0x000f, 0x0f00, 0x0ff0,
   0x0fff, 0x0f0f, 0x0000, 0x0000, 0x0000, 0x000f, 0x0f00, 0x0ff0, 0x0fff,
   0x0f0f, 0x0000, 0x0000, 0x0000, 0xffff, 0x0fff, 0xf0f0, 0x0f0f, 0xff0f,
   0x0000, 0x0000, 0x0000, 0xffff, 0x0fff, 0xf0f0, 0x0f0f, 0xff0f, 0x0000,
   0x0000, 0x0000, 0xffff, 0x0fff, 0xf0f0, 0x0f0f, 0xff0f, 0x0000, 0x0000,
   0x0000, 0xffff, 0x0fff, 0xf0f0, 0x0f0f, 0xff0f, 0x0000, 0x0000, 0x0000,
   0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
   0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
   0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
   0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
   0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
   0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
   0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
   0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
   0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
   0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
   0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
   0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
   0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
   0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
   0x0000 };
'''

    c = pyqrcode.create('Test').xbm(scale=4)

    # Testing number-by-number to get more useful failure message
    c_width, c_height, c_bits = decompose_xbm(c)
    expected_width, expected_height, expected_bits = decompose_xbm(expected_width_scale)

    # Check the there is the same width and height
    assert c_width == expected_width
    assert c_height == expected_height

    # Check that there is the same number of bits
    assert len(expected_bits) == len(c_bits)

    # Check the bit values
    for i in range(len(expected_bits)):
        assert c_bits[i] == expected_bits[i], "Wrong value at {0}: {1} != {2}".format(i, c_bits[i], expected_bits[i])

Result:

>       assert len(expected_bits) == len(c_bits)
E       AssertionError: assert 600 == 1064
E        +  where 600 = len(['0x00', '0x00', '0x00', '0x00', '0x00', '0x00', ...])
E        +  and   1064 = len(['0x00', '0x00', '0x00', '0x00', '0x00', '0x00', ...])
heuer commented 6 years ago

The resulting XBM file can be imported by The Gimp, though

heuer commented 6 years ago

I was using a wrong XBM format, PyQRCode handels the scale correctly