@@ -31,11 +31,17 @@ def __init__(self, classpath=None, java=None):
3131 else :
3232 self .classpath = os .path .join (os .path .dirname (__file__ ), 'java' , '*' )
3333
34- def decode (self , filename , try_harder = False , possible_formats = None ):
34+ def decode (self , filenames , try_harder = False , possible_formats = None ):
3535 possible_formats = (possible_formats ,) if isinstance (possible_formats , str ) else possible_formats
3636
37- file_uri = pathlib .Path (filename ).absolute ().as_uri ()
38- cmd = [self .java , '-cp' , self .classpath , self .cls , file_uri ]
37+ if isinstance (filenames , str ):
38+ one_file = True
39+ filenames = filenames ,
40+ else :
41+ one_file = False
42+ file_uris = [ pathlib .Path (f ).absolute ().as_uri () for f in filenames ]
43+
44+ cmd = [self .java , '-cp' , self .classpath , self .cls ] + file_uris
3945 if try_harder :
4046 cmd .append ('--try_harder' )
4147 if possible_formats :
@@ -54,15 +60,33 @@ def decode(self, filename, try_harder=False, possible_formats=None):
5460 b'Exception in thread "main" java.lang.NoClassDefFoundError:' )):
5561 raise BarCodeReaderException ("Java JARs not found in classpath (%s)" % self .classpath , self .classpath )
5662 elif stdout .startswith (b'''Exception in thread "main" javax.imageio.IIOException: Can't get input stream from URL!''' ):
57- raise BarCodeReaderException ("Could not find image path: %s" % filename , filename )
63+ raise BarCodeReaderException ("Could not find image path: %s" % filenames , filenames )
5864 elif stdout .startswith (b'''Exception in thread "main" java.io.IOException: Could not load ''' ):
59- raise BarCodeReaderException ("Java library could not read image; is it in a supported format?" , filename )
65+ raise BarCodeReaderException ("Java library could not read image; is it in a supported format?" , filenames )
6066 elif stdout .startswith (b'''Exception ''' ):
6167 raise BarCodeReaderException ("Unknown Java exception: %s" % stdout )
6268 elif p .returncode :
6369 raise BarCodeReaderException ("Unexpected Java subprocess return code %d" % p .returncode , self .java )
6470
65- return BarCode .parse (stdout )
71+ if p .returncode :
72+ codes = [ None for fn in filenames ]
73+ else :
74+ file_results = []
75+ for line in stdout .splitlines (True ):
76+ if line .startswith ((b'file:///' ,b'Exception' )):
77+ file_results .append (line )
78+ else :
79+ file_results [- 1 ] += line
80+ codes = [ BarCode .parse (result ) for result in file_results ]
81+
82+ if one_file :
83+ return codes [0 ]
84+ else :
85+ # zxing (insanely) randomly reorders the output blocks, so we have to put them back in the
86+ # expected order, based on their URIs
87+ d = {c .uri : c for c in codes }
88+ return [d [f ] for f in file_uris ]
89+
6690
6791class CLROutputBlock (Enum ):
6892 UNKNOWN = 0
@@ -74,17 +98,17 @@ class BarCode(object):
7498 @classmethod
7599 def parse (cls , zxing_output ):
76100 block = CLROutputBlock .UNKNOWN
77- format = type = None
101+ uri = format = type = None
78102 raw = parsed = b''
79103 points = []
80104
81105 for l in zxing_output .splitlines (True ):
82106 if block == CLROutputBlock .UNKNOWN :
83107 if l .endswith (b': No barcode found\n ' ):
84108 return None
85- m = re .search (rb"format:\s*([^,]+),\s*type:\s*([^)]+)" , l )
109+ m = re .match (rb"(\S+) \( format:\s*([^,]+),\s*type:\s*([^)]+)\ )" , l )
86110 if m :
87- format , type = m .group (1 ).decode (), m .group (2 ).decode ()
111+ uri , format , type = m .group (1 ).decode (), m .group (2 ). decode (), m . group ( 3 ).decode ()
88112 elif l .startswith (b"Raw result:" ):
89113 block = CLROutputBlock .RAW
90114 elif block == CLROutputBlock .RAW :
@@ -104,15 +128,16 @@ def parse(cls, zxing_output):
104128
105129 raw = raw [:- 1 ].decode ()
106130 parsed = parsed [:- 1 ].decode ()
107- return cls (format , type , raw , parsed , points )
131+ return cls (uri , format , type , raw , parsed , points )
108132
109- def __init__ (self , format , type , raw , parsed , points ):
133+ def __init__ (self , uri , format , type , raw , parsed , points ):
110134 self .raw = raw
111135 self .parsed = parsed
136+ self .uri = uri
112137 self .format = format
113138 self .type = type
114139 self .points = points
115140
116141 def __repr__ (self ):
117- return '{}(raw={!r}, parsed={!r}, format={!r}, type={!r}, points={!r})' .format (
118- self .__class__ .__name__ , self .raw , self .parsed , self .format , self .type , self .points )
142+ return '{}(raw={!r}, parsed={!r}, uri={!r}, format={!r}, type={!r}, points={!r})' .format (
143+ self .__class__ .__name__ , self .raw , self .parsed , self .uri , self . format , self .type , self .points )
0 commit comments