@@ -193,7 +193,11 @@ def _open(self) -> None:
193193 self .fp .seek (offset )
194194
195195 self ._mode = "RGB"
196- self ._size = None
196+
197+ # The last occurrence of one of these values
198+ # takes precedence over prior occurrences.
199+ bounding_box = None
200+ imagedata_size = None
197201
198202 byte_arr = bytearray (255 )
199203 bytes_mv = memoryview (byte_arr )
@@ -215,8 +219,8 @@ def check_required_header_comments() -> None:
215219 msg = 'EPS header missing "%%BoundingBox" comment'
216220 raise SyntaxError (msg )
217221
218- def _read_comment (s : str ) -> bool :
219- nonlocal reading_trailer_comments
222+ def read_comment (s : str ) -> bool :
223+ nonlocal bounding_box , reading_trailer_comments
220224 try :
221225 m = split .match (s )
222226 except re .error as e :
@@ -231,18 +235,12 @@ def _read_comment(s: str) -> bool:
231235 if k == "BoundingBox" :
232236 if v == "(atend)" :
233237 reading_trailer_comments = True
234- elif not self . _size or ( trailer_reached and reading_trailer_comments ) :
238+ else :
235239 try :
236240 # Note: The DSC spec says that BoundingBox
237241 # fields should be integers, but some drivers
238242 # put floating point values there anyway.
239- box = [int (float (i )) for i in v .split ()]
240- self ._size = box [2 ] - box [0 ], box [3 ] - box [1 ]
241- self .tile = [
242- ImageFile ._Tile (
243- "eps" , (0 , 0 ) + self .size , offset , (length , box )
244- )
245- ]
243+ bounding_box = [int (float (i )) for i in v .split ()]
246244 except Exception :
247245 pass
248246 return True
@@ -293,7 +291,7 @@ def _read_comment(s: str) -> bool:
293291 continue
294292
295293 s = str (bytes_mv [:bytes_read ], "latin-1" )
296- if not _read_comment (s ):
294+ if not read_comment (s ):
297295 m = field .match (s )
298296 if m :
299297 k = m .group (1 )
@@ -327,32 +325,49 @@ def _read_comment(s: str) -> bool:
327325 int (value ) for value in image_data_values [:4 ]
328326 )
329327
328+ imagedata_size = (columns , rows )
329+
330330 if bit_depth == 1 :
331331 self ._mode = "1"
332332 elif bit_depth == 8 :
333333 try :
334334 self ._mode = self .mode_map [mode_id ]
335335 except ValueError :
336- break
337- else :
338- break
339-
340- self ._size = columns , rows
341- return
336+ pass
342337 elif bytes_mv [:5 ] == b"%%EOF" :
343338 break
344339 elif trailer_reached and reading_trailer_comments :
345340 # Load EPS trailer
346341 s = str (bytes_mv [:bytes_read ], "latin-1" )
347- _read_comment (s )
342+ read_comment (s )
348343 elif bytes_mv [:9 ] == b"%%Trailer" :
349344 trailer_reached = True
350345 bytes_read = 0
351346
352- if not self ._size :
347+ # A "BoundingBox" is always required,
348+ # even if an "ImageData" descriptor size exists.
349+ if not bounding_box :
353350 msg = "cannot determine EPS bounding box"
354351 raise OSError (msg )
355352
353+ # An "ImageData" size takes precedence over the "BoundingBox".
354+ if imagedata_size :
355+ self ._size = imagedata_size
356+ else :
357+ self ._size = (
358+ bounding_box [2 ] - bounding_box [0 ],
359+ bounding_box [3 ] - bounding_box [1 ],
360+ )
361+
362+ self .tile = [
363+ ImageFile ._Tile (
364+ codec_name = "eps" ,
365+ extents = (0 , 0 ) + self ._size ,
366+ offset = offset ,
367+ args = (length , bounding_box ),
368+ )
369+ ]
370+
356371 def _find_offset (self , fp : IO [bytes ]) -> tuple [int , int ]:
357372 s = fp .read (4 )
358373
0 commit comments