Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add helper to add background color on image
For some images with alpha channel, the background color and the foreground color are the same after grey scale conversion, this will no allow us to detect 1D or 2D code on the image. The copy_image_on_background() allow to add a background color on a image to avoid this issue. diff --git a/README.rst b/README.rst index 917726b..3866048 100644 --- a/README.rst +++ b/README.rst @@ -35,3 +35,24 @@ How To use ZbarLight codes = zbarlight.scan_codes('qrcode', image) print('QR codes: %s' % codes) + +Troubleshooting +=============== + +In some case ``zbarlight`` will not be able to detect the 1D or 2D code in an image, one of the known cause is that the +image background color is the same as the foreground color after conversion to grey scale (it's happen on images with +alpha channel). You can use the ``copy_image_on_background`` function to add a background color on your image. + +.. code-block:: python + + from PIL import Image + import zbarlight + + file_path = './tests/fixtures/two_qr_codes.png' + with open(file_path, 'rb') as image_file: + image = Image.open(image_file) + image.load() + + new_image = zbarlight.copy_image_on_background(image, color=zbarlight.WHITE) # <<<<<<<<<<<<<<<< Add this line <<<< + codes = zbarlight.scan_codes('qrcode', new_image) + print('QR codes: %s' % codes) diff --git a/docs/reference.rst b/docs/reference.rst index 829f6f6..0e361df 100644 --- a/docs/reference.rst +++ b/docs/reference.rst @@ -2,4 +2,4 @@ Reference ========= .. automodule:: zbarlight - :members: scan_codes + :members: scan_codes, copy_image_on_background diff --git a/src/zbarlight/__init__.py b/src/zbarlight/__init__.py index a0171f5..0f05c83 100644 --- a/src/zbarlight/__init__.py +++ b/src/zbarlight/__init__.py @@ -7,7 +7,17 @@ from ._zbarlight import Symbologies, zbar_code_scanner __version__ = pkg_resources.get_distribution('zbarlight').version -__ALL__ = ['Symbologies', 'UnknownSymbologieError', 'scan_codes'] +__ALL__ = [ + 'Symbologies', + 'UnknownSymbologieError', + 'scan_codes', + 'copy_image_on_background', + 'BLACK', + 'WHITE', +] + +WHITE = (255, 255, 255) +BLACK = (0, 0, 0) class UnknownSymbologieError(Exception): @@ -42,3 +52,18 @@ def scan_codes(code_type, image): if not symbologie: raise UnknownSymbologieError('Unknown Symbologie: %s' % code_type) return zbar_code_scanner(symbologie, raw, width, height) + + +def copy_image_on_background(image, color=WHITE): + """Create a new image by copying the image on a *color* background + + Args: + image (PIL.Image.Image): Image to copy + color (tuple): Background color usually WHITE or BLACK + + Returns: + PIL.Image.Image + """ + background = Image.new("RGB", image.size, color) + background.paste(image, mask=image.split()[3]) + return background diff --git a/tests/fixtures/sample_need_white_background.png b/tests/fixtures/sample_need_white_background.png new file mode 100644 index 0000000..1c2b5ef Binary files /dev/null and b/tests/fixtures/sample_need_white_background.png differ diff --git a/tests/test_scan_codes.py b/tests/test_scan_codes.py index 2b4ad81..f7ae31b 100644 --- a/tests/test_scan_codes.py +++ b/tests/test_scan_codes.py @@ -17,9 +17,9 @@ class ScanCodeTestCase(unittest.TestCase): def assertIsNone(self, obj, msg=None): # Python 2.6 hack return self.assertTrue(obj is None, '%s is not None' % repr(obj)) - def get_image(self, name): + def get_image(self, name, ext='png'): return pil_image( - os.path.join(os.path.dirname(__file__), 'fixtures', '{0}.png'.format(name)) + os.path.join(os.path.dirname(__file__), 'fixtures', '{0}.{1}'.format(name, ext)) ) def test_no_qr_code(self): @@ -59,3 +59,22 @@ class ScanCodeTestCase(unittest.TestCase): zbarlight.UnknownSymbologieError, zbarlight.scan_codes, 'not-a-zbar-symbologie', image, ) + + def test_need_white_background(self): + """ + User submitted sample that can only be decoded after add a white background + """ + # Not working + image = self.get_image('sample_need_white_background') + + self.assertEqual( + sorted(zbarlight.scan_codes('qrcode', image) or []), + [], + ) + + # Working when adding white background + image_with_background = zbarlight.copy_image_on_background(image) + self.assertEqual( + sorted(zbarlight.scan_codes('qrcode', image_with_background) or []), + sorted([b'http://en.m.wikipedia.org']), + )
- Loading branch information