From f64add95a99418a6d80db46ee0e7757d6c54c91a Mon Sep 17 00:00:00 2001 From: NaziaAfreen015 Date: Thu, 16 Oct 2025 01:15:49 -0400 Subject: [PATCH 1/2] Introducing more wrappers from zbar for image processing --- pyzbar/wrapper.py | 42 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 40 insertions(+), 2 deletions(-) diff --git a/pyzbar/wrapper.py b/pyzbar/wrapper.py index b9f333a..a38ea92 100644 --- a/pyzbar/wrapper.py +++ b/pyzbar/wrapper.py @@ -1,7 +1,7 @@ """Low-level wrapper around zbar's interface """ from ctypes import ( - c_ubyte, c_char_p, c_int, c_uint, c_ulong, c_void_p, Structure, + c_ubyte, c_char_p, c_int, c_uint, c_ulong, c_void_p, Structure, c_uint32, CFUNCTYPE, POINTER ) from enum import IntEnum, unique @@ -18,7 +18,8 @@ 'zbar_symbol_get_data_length', 'zbar_symbol_get_data', 'zbar_symbol_get_loc_size', 'zbar_symbol_get_loc_x', 'zbar_symbol_get_loc_y', 'zbar_symbol_next', - 'zbar_symbol_get_orientation', 'zbar_symbol_get_quality', + 'zbar_symbol_get_orientation', 'zbar_symbol_get_quality', + 'zbar_image_convert', 'zbar_image_convert_resize', 'zbar_image_get_data', 'zbar_image_get_data_length', ] # Globals populated in load_libzbar @@ -92,6 +93,12 @@ class ZBarOrientation(IntEnum): LEFT = 3 # /**< sideways, read bottom to top */ + + + + + + # Structs class zbar_image_scanner(Structure): """Opaque C++ class with private implementation @@ -148,6 +155,37 @@ def zbar_function(fname, restype, *args): return prototype((fname, load_libzbar())) +############################INTRODUCING MORE WRAPPER########################################## +zbar_image_convert = zbar_function( + 'zbar_image_convert', + POINTER(zbar_image), # returns zbar_image* + POINTER(zbar_image), # const zbar_image* src + c_uint32 # unsigned long dst fourcc (use c_uint32) +) + +zbar_image_convert_resize = zbar_function( + 'zbar_image_convert_resize', + POINTER(zbar_image), # returns zbar_image* + POINTER(zbar_image), # const zbar_image* src + c_uint32, # dst fourcc + c_uint, # width + c_uint # height +) + +zbar_image_get_data = zbar_function( + 'zbar_image_get_data', + c_void_p, + POINTER(zbar_image) +) + +zbar_image_get_data_length = zbar_function( + 'zbar_image_get_data_length', + c_ulong, + POINTER(zbar_image) +) + +############################################################################################# + zbar_version = zbar_function( 'zbar_version', c_int, From 3ffb3f428e2c10e6d94d59bf8e49e0b0996c2364 Mon Sep 17 00:00:00 2001 From: NaziaAfreen015 Date: Thu, 16 Oct 2025 01:16:36 -0400 Subject: [PATCH 2/2] using image wrapper apis for converting to 8bpp from zbar instead of discarding color channels --- pyzbar/pyzbar.py | 56 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 55 insertions(+), 1 deletion(-) diff --git a/pyzbar/pyzbar.py b/pyzbar/pyzbar.py index 5b09ec3..d200807 100644 --- a/pyzbar/pyzbar.py +++ b/pyzbar/pyzbar.py @@ -14,6 +14,7 @@ zbar_symbol_get_loc_size, zbar_symbol_get_loc_x, zbar_symbol_get_loc_y, zbar_symbol_get_quality, zbar_symbol_next, ZBarConfig, ZBarOrientation, ZBarSymbol, EXTERNAL_DEPENDENCIES, + zbar_image_convert, zbar_image_convert_resize, zbar_image_get_data, zbar_image_get_data_length, ) __all__ = [ @@ -21,6 +22,8 @@ ] + + ORIENTATION_AVAILABLE = zbar_symbol_get_orientation is not None Decoded = namedtuple('Decoded', 'data type rect polygon quality orientation') @@ -159,6 +162,9 @@ def _pixel_data(image): if 3 == len(image.shape): # Take just the first channel image = image[:, :, 0] + + + if 'uint8' != str(image.dtype): image = image.astype('uint8') try: @@ -204,8 +210,9 @@ def decode(image, symbols=None): Returns: :obj:`list` of :obj:`Decoded`: The values decoded from barcodes. """ - pixels, width, height = _pixel_data(image) + pixels, width, height = _pixel_data(image) + results = [] with _image_scanner() as scanner: if symbols: @@ -234,3 +241,50 @@ def decode(image, symbols=None): results.extend(_decode_symbols(_symbols_for_image(img))) return results + +######################EXTRA FUNCTIONALITY FOR PYZBAR################################################ + +from ctypes import c_ubyte +import numpy as np +from PIL import Image +def fourcc(a, b, c, d): + return (ord(a) | (ord(b) << 8) | (ord(c) << 16) | (ord(d) << 24)) + + +def local_decode(image): + + # ensure uint8, C-contiguous RGB + + if image.dtype != np.uint8 or not image.flags['C_CONTIGUOUS']: + image = np.ascontiguousarray(image, dtype=np.uint8) + h, w = image.shape[:2] + + results = [] + with _image_scanner() as scanner: + with _image() as img: + zbar_image_set_format(img, fourcc('R','G','B','3')) + zbar_image_set_size(img, w, h) + # pass pointer + byte length (no-op cleanup is fine as None) + zbar_image_set_data(img, c_void_p(image.ctypes.data), image.nbytes, None) + + dst = zbar_image_convert(img, fourcc('Y','8','0','0')) + + # after you have `dst` (Y800) from zbar_image_convert and know w,h: + datalen = zbar_image_get_data_length(dst) + ptr = zbar_image_get_data(dst) + buf = (c_ubyte * datalen).from_address(ptr) + gray = np.frombuffer(buf, dtype=np.uint8).reshape(h, w) # h,w from original image + + # Image.fromarray(gray, mode='L').save("converted_y800.png") + try: + decoded = zbar_scan_image(scanner, dst) + if decoded < 0: + raise PyZbarError('Unsupported image format') + # read symbols from the image you scanned + results.extend(_decode_symbols(_symbols_for_image(dst))) + finally: + zbar_image_destroy(dst) # free converted Y800 buffer + return results + + +######################################################################### \ No newline at end of file