test.py 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. import importlib.util
  2. import unittest
  3. import math
  4. import platform
  5. import zxingcpp
  6. has_numpy = importlib.util.find_spec('numpy') is not None
  7. has_pil = importlib.util.find_spec('PIL') is not None
  8. has_cv2 = importlib.util.find_spec('cv2') is not None
  9. BF = zxingcpp.BarcodeFormat
  10. CT = zxingcpp.ContentType
  11. class TestFormat(unittest.TestCase):
  12. def test_format(self):
  13. self.assertEqual(zxingcpp.barcode_format_from_str('qrcode'), BF.QRCode)
  14. self.assertEqual(zxingcpp.barcode_formats_from_str('ITF, qrcode'), BF.ITF | BF.QRCode)
  15. class TestReadWrite(unittest.TestCase):
  16. def check_res(self, res, format, text):
  17. self.assertTrue(res.valid)
  18. self.assertEqual(res.format, format)
  19. self.assertEqual(res.text, text)
  20. self.assertEqual(res.bytes, bytes(text, 'utf-8'))
  21. self.assertEqual(res.orientation, 0)
  22. self.assertEqual(res.content_type, CT.Text)
  23. def test_write_read_cycle(self):
  24. format = BF.QRCode
  25. text = "I have the best words."
  26. img = zxingcpp.write_barcode(format, text)
  27. res = zxingcpp.read_barcode(img)
  28. self.check_res(res, format, text)
  29. self.assertEqual(res.symbology_identifier, "]Q1")
  30. # self.assertEqual(res.position.top_left.x, 4)
  31. res = zxingcpp.read_barcode(img, formats=format)
  32. self.check_res(res, format, text)
  33. @unittest.skipIf(not hasattr(zxingcpp, 'create_barcode'), "skipping test for new create_barcode API")
  34. def test_create_write_read_cycle(self):
  35. format = BF.DataMatrix
  36. text = "I have the best words."
  37. img = zxingcpp.create_barcode(text, format).to_image()
  38. res = zxingcpp.read_barcode(img)
  39. self.check_res(res, format, text)
  40. def test_write_read_oned_cycle(self):
  41. format = BF.Code128
  42. text = "I have the best words."
  43. height = 50
  44. width = 400
  45. img = zxingcpp.write_barcode(format, text, width=width, height=height)
  46. # self.assertEqual(img.shape[0], height)
  47. # self.assertEqual(img.shape[1], width)
  48. res = zxingcpp.read_barcode(img)
  49. self.check_res(res, format, text)
  50. # self.assertEqual(res.position.top_left.x, 61)
  51. def test_write_read_multi_cycle(self):
  52. format = BF.QRCode
  53. text = "I have the best words."
  54. img = zxingcpp.write_barcode(format, text)
  55. res = zxingcpp.read_barcodes(img)[0]
  56. self.check_res(res, format, text)
  57. def test_write_read_bytes_cycle(self):
  58. format = BF.QRCode
  59. text = b"\1\2\3\4"
  60. img = zxingcpp.write_barcode(format, text)
  61. res = zxingcpp.read_barcode(img)
  62. self.assertTrue(res.valid)
  63. self.assertEqual(res.bytes, text)
  64. self.assertEqual(res.content_type, CT.Binary)
  65. @unittest.skipIf(not hasattr(zxingcpp, 'create_barcode'), "skipping test for new create_barcode API")
  66. def test_create_write_read_bytes_cycle(self):
  67. format = BF.DataMatrix
  68. text = b"\1\2\3\4"
  69. img = zxingcpp.create_barcode(text, format).to_image()
  70. res = zxingcpp.read_barcode(img)
  71. self.assertTrue(res.valid)
  72. self.assertEqual(res.bytes, text)
  73. self.assertEqual(res.content_type, CT.Binary)
  74. @staticmethod
  75. def zeroes(shape):
  76. return memoryview(b"0" * math.prod(shape)).cast("B", shape=shape)
  77. def test_failed_read_buffer(self):
  78. res = zxingcpp.read_barcode(
  79. self.zeroes((100, 100)), formats=BF.EAN8 | BF.Aztec, binarizer=zxingcpp.Binarizer.BoolCast
  80. )
  81. self.assertEqual(res, None)
  82. @unittest.skipIf(not has_numpy, "need numpy for read/write tests")
  83. def test_failed_read_numpy(self):
  84. import numpy as np
  85. res = zxingcpp.read_barcode(
  86. np.zeros((100, 100), np.uint8), formats=BF.EAN8 | BF.Aztec, binarizer=zxingcpp.Binarizer.BoolCast
  87. )
  88. self.assertEqual(res, None)
  89. def test_write_read_cycle_buffer(self):
  90. format = BF.QRCode
  91. text = "I have the best words."
  92. img = zxingcpp.write_barcode(format, text)
  93. self.check_res(zxingcpp.read_barcode(img), format, text)
  94. @unittest.skipIf(not has_numpy, "need numpy for read/write tests")
  95. def test_write_read_cycle_numpy(self):
  96. import numpy as np
  97. format = BF.QRCode
  98. text = "I have the best words."
  99. img = zxingcpp.write_barcode(format, text, quiet_zone=10)
  100. img = np.array(img)
  101. self.check_res(zxingcpp.read_barcode(img), format, text)
  102. self.check_res(zxingcpp.read_barcode(img[4:40,4:40]), format, text)
  103. @unittest.skipIf(not has_pil, "need PIL for read/write tests")
  104. def test_write_read_cycle_pil(self):
  105. from PIL import Image
  106. format = BF.QRCode
  107. text = "I have the best words."
  108. img = zxingcpp.write_barcode(format, text)
  109. img = Image.fromarray(img, "L")
  110. self.check_res(zxingcpp.read_barcode(img), format, text)
  111. self.check_res(zxingcpp.read_barcode(img.convert("RGB")), format, text)
  112. self.check_res(zxingcpp.read_barcode(img.convert("RGBA")), format, text)
  113. self.check_res(zxingcpp.read_barcode(img.convert("1")), format, text)
  114. self.check_res(zxingcpp.read_barcode(img.convert("CMYK")), format, text)
  115. @unittest.skipIf(not has_cv2, "need cv2 for read/write tests")
  116. def test_write_read_cycle_cv2(self):
  117. import cv2, numpy
  118. format = BF.QRCode
  119. text = "I have the best words."
  120. img = zxingcpp.write_barcode(format, text, quiet_zone=10)
  121. img = cv2.cvtColor(numpy.array(img), cv2.COLOR_GRAY2BGR )
  122. self.check_res(zxingcpp.read_barcode(img), format, text)
  123. self.check_res(zxingcpp.read_barcode(img[4:40,4:40,:]), format, text)
  124. def test_read_invalid_type(self):
  125. self.assertRaisesRegex(
  126. TypeError, "Invalid input: <class 'str'> does not support the buffer protocol.", zxingcpp.read_barcode, "foo"
  127. )
  128. def test_read_invalid_numpy_array_channels_buffer(self):
  129. self.assertRaisesRegex(
  130. ValueError, "Unsupported number of channels for buffer: 4", zxingcpp.read_barcode,
  131. self.zeroes((100, 100, 4))
  132. )
  133. @unittest.skipIf(not has_numpy, "need numpy for read/write tests")
  134. def test_read_invalid_numpy_array_channels_numpy(self):
  135. import numpy as np
  136. self.assertRaisesRegex(
  137. ValueError, "Unsupported number of channels for buffer: 4", zxingcpp.read_barcode,
  138. np.zeros((100, 100, 4), np.uint8)
  139. )
  140. if __name__ == '__main__':
  141. unittest.main()